@backbencher/brain 0.0.0-stage → 0.1.1
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-Q5APTJQL.js +17 -0
- package/dist/brain-relationship-enrichment-MYR2AM4F.js +558 -0
- package/dist/brain.sql-EIM4WS4D.js +29 -0
- package/dist/chunk-22V37YTK.js +1758 -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-2WXYNLBA.js +29 -0
- package/dist/chunk-3CTFIJJB.js +17 -0
- package/dist/chunk-3ZTOHHSW.js +2104 -0
- package/dist/chunk-4H22TLOT.js +543 -0
- package/dist/chunk-5BVAH26D.js +340 -0
- package/dist/chunk-62DHLYW6.js +3427 -0
- package/dist/chunk-7AN7U5IZ.js +371 -0
- package/dist/chunk-7DRPNVIN.js +782 -0
- package/dist/chunk-7MBYT777.js +174 -0
- package/dist/chunk-AHDWGM7Q.js +236 -0
- package/dist/chunk-B5GEAAYF.js +818 -0
- package/dist/chunk-BEIZZ73B.js +1479 -0
- package/dist/chunk-BQ3OVQ3P.js +125 -0
- package/dist/chunk-D2Q4Y47A.js +53 -0
- package/dist/chunk-DIYAGQJL.js +34 -0
- package/dist/chunk-DWKXZ6IF.js +336 -0
- package/dist/chunk-DYM4FQEE.js +90 -0
- package/dist/chunk-ENW4BTBA.js +930 -0
- package/dist/chunk-EWMWK7WN.js +75 -0
- package/dist/chunk-EY5ZZUUA.js +626 -0
- package/dist/chunk-GBI7V7KY.js +69 -0
- package/dist/chunk-GEFFO6O2.js +152 -0
- package/dist/chunk-HJEWO5EV.js +247 -0
- package/dist/chunk-HQSPJDHI.js +613 -0
- package/dist/chunk-KAET47ZL.js +125 -0
- package/dist/chunk-KCDECRJY.js +440 -0
- package/dist/chunk-L5TDYKYK.js +76 -0
- package/dist/chunk-MLKGABMK.js +9 -0
- package/dist/chunk-NO3U3FJQ.js +201 -0
- package/dist/chunk-OWISBAOF.js +61 -0
- package/dist/chunk-QKTRECYS.js +1119 -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-RM3PY6TG.js +376 -0
- package/dist/chunk-ROMM6KMC.js +433 -0
- package/dist/chunk-SGGCSHAX.js +12050 -0
- package/dist/chunk-SK6YVHFZ.js +211 -0
- package/dist/chunk-SM7RFQRO.js +214 -0
- package/dist/chunk-UGR4QIGS.js +67 -0
- package/dist/chunk-UQNQZXHY.js +711 -0
- package/dist/chunk-UUNHHX4M.js +13 -0
- package/dist/chunk-VL52PL2T.js +71 -0
- package/dist/chunk-WIG36E67.js +196 -0
- package/dist/chunk-XHK3WWGB.js +7436 -0
- package/dist/chunk-XTQM2IP3.js +2863 -0
- package/dist/chunk-ZE2LG76D.js +1296 -0
- package/dist/chunk-ZETTGPAW.js +6950 -0
- package/dist/cli/index.js +37 -0
- package/dist/config-HZAAYDP3.js +10 -0
- package/dist/content-search-7XIP555Q.js +593 -0
- package/dist/database-76RP44JG.js +9 -0
- package/dist/doctor-ANGETYMN.js +395 -0
- package/dist/edit-engine-CG72LDZD.js +51 -0
- package/dist/engine-BKEOGN7N.js +11 -0
- package/dist/engine-VIW6NSKO.js +18 -0
- package/dist/fingerprint-OBLIMZLP.js +33 -0
- package/dist/framework-intelligence-3LORTPOX.js +860 -0
- package/dist/freshness-3K6VU5OT.js +174 -0
- package/dist/graph-engine-HBSQNPTB.js +21 -0
- package/dist/graph_request-Q6NKB6N2.js +350 -0
- package/dist/impact_request-LYP672WE.js +68 -0
- package/dist/index-space-IUUN5WYV.js +15 -0
- package/dist/index-status-7OVGYSGW.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-FK2XKZXY.js +88 -0
- package/dist/pool-worker.js +1153 -0
- package/dist/project-health-6XPENVAA.js +94 -0
- package/dist/project-index-5SDPHITE.js +57 -0
- package/dist/project-registry-ZJ3DVUGO.js +355 -0
- package/dist/real-bash-analyzer-EJAU5LW5.js +2201 -0
- package/dist/real-c-analyzer-HBD3FNNH.js +5942 -0
- package/dist/real-clean-analyzer-4EEZLPV5.js +3470 -0
- package/dist/real-clojure-analyzer-Q55EBOO2.js +2818 -0
- package/dist/real-cpp-analyzer-IVVOD25R.js +4101 -0
- package/dist/real-csharp-analyzer-ZBNLNJZJ.js +3298 -0
- package/dist/real-css-analyzer-6XRQLUN7.js +15 -0
- package/dist/real-dart-analyzer-OLR72EFW.js +3944 -0
- package/dist/real-elixir-analyzer-MQWGAH2I.js +2192 -0
- package/dist/real-erlang-analyzer-7BVPQEHO.js +1731 -0
- package/dist/real-fsharp-analyzer-C2UPFNOA.js +2390 -0
- package/dist/real-go-analyzer-UKGI43YS.js +4126 -0
- package/dist/real-graphql-analyzer-VE2EEFII.js +1442 -0
- package/dist/real-groovy-analyzer-W26VACFW.js +2285 -0
- package/dist/real-haskell-analyzer-5CVVAJRX.js +2533 -0
- package/dist/real-hcl-analyzer-5ZT4U43N.js +725 -0
- package/dist/real-html-analyzer-JWNX3C6I.js +1759 -0
- package/dist/real-java-analyzer-GU42VBGQ.js +4677 -0
- package/dist/real-javascript-analyzer-QA4QOJ6W.js +14 -0
- package/dist/real-json-analyzer-MPA6PRXL.js +1640 -0
- package/dist/real-julia-analyzer-22CWYQMN.js +2085 -0
- package/dist/real-kotlin-analyzer-QDZJLXXU.js +3956 -0
- package/dist/real-lua-analyzer-G7NHLYKS.js +1957 -0
- package/dist/real-makefile-analyzer-OCY3GT5N.js +920 -0
- package/dist/real-markdown-analyzer-TEJK2JXJ.js +1215 -0
- package/dist/real-matlab-analyzer-Q5SWLN7Z.js +480 -0
- package/dist/real-nim-analyzer-YLXSK563.js +3603 -0
- package/dist/real-objective-c-analyzer-D23ACC2R.js +1518 -0
- package/dist/real-perl-analyzer-WWTRHYDT.js +1865 -0
- package/dist/real-php-analyzer-JNKJHTCL.js +9368 -0
- package/dist/real-powershell-analyzer-XRSNQERV.js +2915 -0
- package/dist/real-protobuf-analyzer-3OKUCZ7T.js +867 -0
- package/dist/real-python-analyzer-VXAFWI72.js +4880 -0
- package/dist/real-r-analyzer-ZGAIDVI4.js +2596 -0
- package/dist/real-ruby-analyzer-X2KTLVBH.js +2429 -0
- package/dist/real-rust-analyzer-OFFHPL2A.js +3359 -0
- package/dist/real-scala-analyzer-TSTW27J6.js +3293 -0
- package/dist/real-scss-analyzer-AVWYPSOQ.js +1515 -0
- package/dist/real-solidity-analyzer-UCI2KWUB.js +2608 -0
- package/dist/real-sql-analyzer-F77ZMQXR.js +3840 -0
- package/dist/real-svelte-analyzer-SF7NRUO5.js +2532 -0
- package/dist/real-swift-analyzer-MN5QT3QN.js +2311 -0
- package/dist/real-toml-analyzer-66L7BDCQ.js +929 -0
- package/dist/real-typescript-analyzer-6KEMVDWQ.js +14 -0
- package/dist/real-vb-analyzer-VICVPOP7.js +3145 -0
- package/dist/real-vba-analyzer-HXLTTHKM.js +466 -0
- package/dist/real-vue-analyzer-QXR56CFV.js +2680 -0
- package/dist/real-xml-analyzer-YL465ZJW.js +2405 -0
- package/dist/real-yaml-analyzer-SUBCBNSI.js +3528 -0
- package/dist/real-zig-analyzer-HIQLZMGY.js +2430 -0
- package/dist/regex-search-NJKHMZNO.js +239 -0
- package/dist/rules-ACHPB7QU.js +152 -0
- package/dist/scoped-path-MJYWJZQX.js +11 -0
- package/dist/setup-show-NT5ZHYNE.js +15 -0
- package/dist/setup-wizard-G5YYR5T6.js +24 -0
- package/dist/symbol-search-GZJIM2J2.js +16 -0
- package/dist/taint-KXUHHPIE.js +202 -0
- package/dist/taint-analyzer-N7YLZU3N.js +163 -0
- package/dist/tool-handlers-OJDC35DI.js +72 -0
- package/dist/tool-registry-BPEJNSZG.js +17 -0
- package/dist/tool-validation-Q57YMMBX.js +32 -0
- package/dist/type-inference-QMT2RMLV.js +13 -0
- package/dist/vector-binary-LMY4QGAN.js +19 -0
- package/dist/version-ABP2TUL2.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,125 @@
|
|
|
1
|
+
// src/cli/terminal-style.ts
|
|
2
|
+
var CODES = {
|
|
3
|
+
bold: "\x1B[1m",
|
|
4
|
+
dim: "\x1B[2m",
|
|
5
|
+
red: "\x1B[31m",
|
|
6
|
+
green: "\x1B[32m",
|
|
7
|
+
yellow: "\x1B[33m",
|
|
8
|
+
cyan: "\x1B[36m",
|
|
9
|
+
reset: "\x1B[0m"
|
|
10
|
+
};
|
|
11
|
+
function colorEnabled(ctx = {}) {
|
|
12
|
+
const env = ctx.env ?? process.env;
|
|
13
|
+
if (env.NO_COLOR !== void 0 && env.NO_COLOR !== "") return false;
|
|
14
|
+
if (env.FORCE_COLOR === "1" || env.FORCE_COLOR === "true") return true;
|
|
15
|
+
return ctx.isTTY === true;
|
|
16
|
+
}
|
|
17
|
+
function style(text, kinds, enabled) {
|
|
18
|
+
if (!enabled || text.length === 0) return text;
|
|
19
|
+
let prefix = "";
|
|
20
|
+
for (const kind of kinds) prefix += CODES[kind] ?? "";
|
|
21
|
+
if (prefix.length === 0) return text;
|
|
22
|
+
return `${prefix}${text}${CODES.reset}`;
|
|
23
|
+
}
|
|
24
|
+
function bold(text, enabled) {
|
|
25
|
+
return style(text, ["bold"], enabled);
|
|
26
|
+
}
|
|
27
|
+
function dim(text, enabled) {
|
|
28
|
+
return style(text, ["dim"], enabled);
|
|
29
|
+
}
|
|
30
|
+
function cyan(text, enabled) {
|
|
31
|
+
return style(text, ["cyan"], enabled);
|
|
32
|
+
}
|
|
33
|
+
function green(text, enabled) {
|
|
34
|
+
return style(text, ["green"], enabled);
|
|
35
|
+
}
|
|
36
|
+
function yellow(text, enabled) {
|
|
37
|
+
return style(text, ["yellow"], enabled);
|
|
38
|
+
}
|
|
39
|
+
function red(text, enabled) {
|
|
40
|
+
return style(text, ["red"], enabled);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// src/util/log.ts
|
|
44
|
+
var LEVEL_LABELS = {
|
|
45
|
+
[0 /* TRACE */]: "TRACE",
|
|
46
|
+
[1 /* DEBUG */]: "DEBUG",
|
|
47
|
+
[2 /* INFO */]: "INFO",
|
|
48
|
+
[3 /* WARN */]: "WARN",
|
|
49
|
+
[4 /* ERROR */]: "ERROR",
|
|
50
|
+
[5 /* SILENT */]: "SILENT"
|
|
51
|
+
};
|
|
52
|
+
var globalLevel = 2 /* INFO */;
|
|
53
|
+
if (process.env.BB_LOG_LEVEL) {
|
|
54
|
+
const parsed = Number(process.env.BB_LOG_LEVEL);
|
|
55
|
+
const byName = LEVEL_LABELS[process.env.BB_LOG_LEVEL.toUpperCase()];
|
|
56
|
+
if (byName !== void 0) {
|
|
57
|
+
globalLevel = byName;
|
|
58
|
+
} else if (!Number.isNaN(parsed) && parsed >= 0 /* TRACE */ && parsed <= 5 /* SILENT */) {
|
|
59
|
+
globalLevel = parsed;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
function setLogLevel(level) {
|
|
63
|
+
globalLevel = level;
|
|
64
|
+
}
|
|
65
|
+
function formatMessage(level, module, msg, context) {
|
|
66
|
+
const now = /* @__PURE__ */ new Date();
|
|
67
|
+
const time = `${String(now.getHours()).padStart(2, "0")}:${String(now.getMinutes()).padStart(2, "0")}:${String(now.getSeconds()).padStart(2, "0")}`;
|
|
68
|
+
const label = LEVEL_LABELS[level];
|
|
69
|
+
const ctx = context && Object.keys(context).length > 0 ? ` ${JSON.stringify(context)}` : "";
|
|
70
|
+
const useColor = colorEnabled({ isTTY: process.stderr.isTTY === true });
|
|
71
|
+
if (!useColor) return `[${label}] [${time}] [${module}] ${msg}${ctx}`;
|
|
72
|
+
const head = `[${label}] [${time}] [${module}]`;
|
|
73
|
+
const headColored = level === 4 /* ERROR */ ? red(head, true) : level === 3 /* WARN */ ? yellow(head, true) : dim(head, true);
|
|
74
|
+
const msgColored = level === 4 /* ERROR */ ? red(msg, true) : level === 3 /* WARN */ ? yellow(msg, true) : msg;
|
|
75
|
+
const ctxColored = ctx ? dim(ctx, true) : "";
|
|
76
|
+
return `${headColored} ${msgColored}${ctxColored}`;
|
|
77
|
+
}
|
|
78
|
+
function createLogger(module) {
|
|
79
|
+
return {
|
|
80
|
+
trace(msg, context) {
|
|
81
|
+
if (globalLevel <= 0 /* TRACE */) {
|
|
82
|
+
process.stderr.write(formatMessage(0 /* TRACE */, module, msg, context) + "\n");
|
|
83
|
+
}
|
|
84
|
+
},
|
|
85
|
+
debug(msg, context) {
|
|
86
|
+
if (globalLevel <= 1 /* DEBUG */) {
|
|
87
|
+
process.stderr.write(formatMessage(1 /* DEBUG */, module, msg, context) + "\n");
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
info(msg, context) {
|
|
91
|
+
if (globalLevel <= 2 /* INFO */) {
|
|
92
|
+
process.stderr.write(formatMessage(2 /* INFO */, module, msg, context) + "\n");
|
|
93
|
+
}
|
|
94
|
+
},
|
|
95
|
+
warn(msg, context) {
|
|
96
|
+
if (globalLevel <= 3 /* WARN */) {
|
|
97
|
+
process.stderr.write(formatMessage(3 /* WARN */, module, msg, context) + "\n");
|
|
98
|
+
}
|
|
99
|
+
},
|
|
100
|
+
error(msg, context) {
|
|
101
|
+
if (globalLevel <= 4 /* ERROR */) {
|
|
102
|
+
process.stderr.write(formatMessage(4 /* ERROR */, module, msg, context) + "\n");
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// src/tool/brain-log.ts
|
|
109
|
+
var logger = createLogger("brain");
|
|
110
|
+
function create(tags) {
|
|
111
|
+
const service = tags?.service ?? "brain";
|
|
112
|
+
return createLogger(service);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export {
|
|
116
|
+
colorEnabled,
|
|
117
|
+
bold,
|
|
118
|
+
dim,
|
|
119
|
+
cyan,
|
|
120
|
+
green,
|
|
121
|
+
yellow,
|
|
122
|
+
red,
|
|
123
|
+
setLogLevel,
|
|
124
|
+
create
|
|
125
|
+
};
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
// src/ast/scoped-path.ts
|
|
2
|
+
import { existsSync, realpathSync, statSync } from "fs";
|
|
3
|
+
import path from "path";
|
|
4
|
+
function canonicalProjectRoot(projectPath) {
|
|
5
|
+
const resolved = path.resolve(projectPath);
|
|
6
|
+
try {
|
|
7
|
+
return realpathSync.native(resolved);
|
|
8
|
+
} catch {
|
|
9
|
+
return resolved;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
function isInsideProject(absolute, projectRoot) {
|
|
13
|
+
if (absolute === projectRoot) return true;
|
|
14
|
+
return absolute.startsWith(projectRoot + path.sep);
|
|
15
|
+
}
|
|
16
|
+
function resolveScopedProjectFile(projectPath, input) {
|
|
17
|
+
const projectRoot = canonicalProjectRoot(projectPath);
|
|
18
|
+
const raw = typeof input === "string" ? input.trim() : "";
|
|
19
|
+
if (raw.length === 0) return { ok: false, reason: "empty-path", resolved: projectRoot, projectRoot };
|
|
20
|
+
const lexical = path.resolve(projectRoot, raw);
|
|
21
|
+
if (!isInsideProject(lexical, projectRoot)) {
|
|
22
|
+
return { ok: false, reason: "outside-project", resolved: lexical, projectRoot };
|
|
23
|
+
}
|
|
24
|
+
let canonical = lexical;
|
|
25
|
+
try {
|
|
26
|
+
canonical = realpathSync.native(lexical);
|
|
27
|
+
} catch {
|
|
28
|
+
return { ok: false, reason: "not-found", resolved: lexical, projectRoot };
|
|
29
|
+
}
|
|
30
|
+
if (!isInsideProject(canonical, projectRoot)) {
|
|
31
|
+
return { ok: false, reason: "outside-project", resolved: canonical, projectRoot };
|
|
32
|
+
}
|
|
33
|
+
try {
|
|
34
|
+
if (!statSync(canonical).isFile()) return { ok: false, reason: "not-a-file", resolved: canonical, projectRoot };
|
|
35
|
+
} catch {
|
|
36
|
+
return { ok: false, reason: "not-found", resolved: canonical, projectRoot };
|
|
37
|
+
}
|
|
38
|
+
if (!existsSync(canonical)) return { ok: false, reason: "not-found", resolved: canonical, projectRoot };
|
|
39
|
+
return { ok: true, absolute: canonical };
|
|
40
|
+
}
|
|
41
|
+
function describeScopedPathRefusal(result) {
|
|
42
|
+
const where = `(resolved against ${result.projectRoot})`;
|
|
43
|
+
if (result.reason === "empty-path") return `--file path is empty ${where}`;
|
|
44
|
+
if (result.reason === "not-found") return `--file not found: ${result.resolved} ${where}`;
|
|
45
|
+
if (result.reason === "not-a-file") return `--file is not a file: ${result.resolved} ${where}`;
|
|
46
|
+
return `--file is outside the project: ${result.resolved}; the project root is ${result.projectRoot}`;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export {
|
|
50
|
+
canonicalProjectRoot,
|
|
51
|
+
resolveScopedProjectFile,
|
|
52
|
+
describeScopedPathRefusal
|
|
53
|
+
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import {
|
|
2
|
+
bbProjectsDir
|
|
3
|
+
} from "./chunk-2BSKD7O3.js";
|
|
4
|
+
|
|
5
|
+
// src/util/project-id.ts
|
|
6
|
+
import { createHash } from "crypto";
|
|
7
|
+
import { existsSync, mkdirSync, realpathSync, renameSync } from "fs";
|
|
8
|
+
import path from "path";
|
|
9
|
+
function getProjectId(projectPath) {
|
|
10
|
+
const resolved = path.resolve(projectPath);
|
|
11
|
+
let canonical = resolved;
|
|
12
|
+
try {
|
|
13
|
+
canonical = realpathSync.native(resolved);
|
|
14
|
+
} catch {
|
|
15
|
+
}
|
|
16
|
+
const canonicalId = createHash("sha1").update(canonical).digest("hex").substring(0, 40);
|
|
17
|
+
if (canonical !== resolved) {
|
|
18
|
+
const legacyId = createHash("sha1").update(resolved).digest("hex").substring(0, 40);
|
|
19
|
+
const legacyDir = path.join(bbProjectsDir(), legacyId);
|
|
20
|
+
const canonicalDir = path.join(bbProjectsDir(), canonicalId);
|
|
21
|
+
if (existsSync(legacyDir) && !existsSync(canonicalDir)) {
|
|
22
|
+
mkdirSync(bbProjectsDir(), { recursive: true });
|
|
23
|
+
try {
|
|
24
|
+
renameSync(legacyDir, canonicalDir);
|
|
25
|
+
} catch {
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return canonicalId;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export {
|
|
33
|
+
getProjectId
|
|
34
|
+
};
|
|
@@ -0,0 +1,336 @@
|
|
|
1
|
+
import {
|
|
2
|
+
fingerprintKey
|
|
3
|
+
} from "./chunk-2RRBMNBQ.js";
|
|
4
|
+
import {
|
|
5
|
+
SemanticEngine,
|
|
6
|
+
assessEndpoint,
|
|
7
|
+
classifyStatus,
|
|
8
|
+
describeEmbeddingSetup,
|
|
9
|
+
isEmbeddingDisabled,
|
|
10
|
+
observedEmbeddingFailures,
|
|
11
|
+
parseEndpoint,
|
|
12
|
+
probeEmbeddingEndpoint,
|
|
13
|
+
readRuntimeOptions
|
|
14
|
+
} from "./chunk-B5GEAAYF.js";
|
|
15
|
+
import {
|
|
16
|
+
LOCAL_VECTOR_DIMENSION
|
|
17
|
+
} from "./chunk-7AN7U5IZ.js";
|
|
18
|
+
import {
|
|
19
|
+
bbDataDir
|
|
20
|
+
} from "./chunk-2BSKD7O3.js";
|
|
21
|
+
import {
|
|
22
|
+
__export
|
|
23
|
+
} from "./chunk-MLKGABMK.js";
|
|
24
|
+
|
|
25
|
+
// src/setup/setup-show.ts
|
|
26
|
+
import { existsSync, readFileSync, statSync } from "fs";
|
|
27
|
+
import path from "path";
|
|
28
|
+
|
|
29
|
+
// src/brain/semantic/embedding-diagnosis.ts
|
|
30
|
+
var embedding_diagnosis_exports = {};
|
|
31
|
+
__export(embedding_diagnosis_exports, {
|
|
32
|
+
LOCAL_DIMENSION: () => LOCAL_DIMENSION,
|
|
33
|
+
buildEmbeddingChain: () => buildEmbeddingChain,
|
|
34
|
+
buildEmbeddingDiagnosis: () => buildEmbeddingDiagnosis,
|
|
35
|
+
embeddingChainVerdict: () => embeddingChainVerdict,
|
|
36
|
+
probeEmbeddingDiagnosis: () => probeEmbeddingDiagnosis,
|
|
37
|
+
renderChainSummary: () => renderChainSummary,
|
|
38
|
+
severityOf: () => severityOf
|
|
39
|
+
});
|
|
40
|
+
var LOCAL_LABEL_HINT = SemanticEngine.LOCAL_MODEL_LABEL;
|
|
41
|
+
function sourceLabel(tier, field) {
|
|
42
|
+
return tier === "env" ? `env:BB_EMBEDDING_${field}` : `file:${tier}`;
|
|
43
|
+
}
|
|
44
|
+
function buildEmbeddingChain(state, env = process.env) {
|
|
45
|
+
const options = readRuntimeOptions(env);
|
|
46
|
+
const layers = [];
|
|
47
|
+
const winner = state.tiers.find((t) => t.tier === state.winner && t.complete);
|
|
48
|
+
if (isEmbeddingDisabled(env)) {
|
|
49
|
+
layers.push({
|
|
50
|
+
order: 0,
|
|
51
|
+
role: "disabled",
|
|
52
|
+
label: "embeddings disabled",
|
|
53
|
+
endpoint: "none",
|
|
54
|
+
model: "none",
|
|
55
|
+
keyState: "not-required",
|
|
56
|
+
source: "env:BB_EMBEDDING_DISABLED",
|
|
57
|
+
active: true,
|
|
58
|
+
problems: []
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
if (state.configured && winner) {
|
|
62
|
+
const hasKey = typeof winner.keyFingerprint === "string" && winner.keyFingerprint.length > 0;
|
|
63
|
+
const readiness = assessEndpoint(
|
|
64
|
+
winner.baseURL ?? "",
|
|
65
|
+
hasKey ? sourceLabel(winner.tier, "API_KEY") : "none",
|
|
66
|
+
hasKey ? sourceLabel(winner.tier, "API_KEY") : "none"
|
|
67
|
+
);
|
|
68
|
+
layers.push({
|
|
69
|
+
order: layers.length,
|
|
70
|
+
role: "primary",
|
|
71
|
+
label: `primary provider (${winner.tier})`,
|
|
72
|
+
endpoint: winner.baseURL ?? "",
|
|
73
|
+
model: winner.model ?? "",
|
|
74
|
+
keyState: readiness.hasKey ? "present" : readiness.loopback ? "not-required" : "absent",
|
|
75
|
+
source: `url ${sourceLabel(winner.tier, "BASE_URL")} \xB7 model ${sourceLabel(winner.tier, "MODEL")} \xB7 key ${hasKey ? sourceLabel(winner.tier, "API_KEY") : "none"}`,
|
|
76
|
+
active: !options.disabled,
|
|
77
|
+
problems: readiness.problems
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
if (options.fallback) {
|
|
81
|
+
const fbKeySource = options.fallback.apiKey ? "env:BB_EMBEDDING_API_KEY" : "none";
|
|
82
|
+
const readiness = assessEndpoint(options.fallback.baseURL, fbKeySource, "env:BB_EMBEDDING_FALLBACK_API_KEY");
|
|
83
|
+
layers.push({
|
|
84
|
+
order: layers.length,
|
|
85
|
+
role: "fallback",
|
|
86
|
+
label: "fallback provider",
|
|
87
|
+
endpoint: options.fallback.baseURL,
|
|
88
|
+
model: options.fallback.model,
|
|
89
|
+
keyState: readiness.hasKey ? "present" : readiness.loopback ? "not-required" : "absent",
|
|
90
|
+
source: `url env:BB_EMBEDDING_FALLBACK_BASE_URL \xB7 model env:BB_EMBEDDING_FALLBACK_MODEL \xB7 key ${options.fallback.apiKey ? "env:BB_EMBEDDING_FALLBACK_API_KEY" : "none"}`,
|
|
91
|
+
active: !options.disabled && state.configured,
|
|
92
|
+
problems: readiness.problems
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
layers.push({
|
|
96
|
+
order: layers.length,
|
|
97
|
+
role: "local",
|
|
98
|
+
label: "local word vectors",
|
|
99
|
+
endpoint: "offline",
|
|
100
|
+
model: LOCAL_LABEL_HINT,
|
|
101
|
+
keyState: "not-required",
|
|
102
|
+
source: "built in",
|
|
103
|
+
active: true,
|
|
104
|
+
problems: []
|
|
105
|
+
});
|
|
106
|
+
return layers;
|
|
107
|
+
}
|
|
108
|
+
function detectTierOrderDisagreement(state, env) {
|
|
109
|
+
if (state.winner !== "global") return null;
|
|
110
|
+
const project = state.tiers.find((t) => t.tier === "project");
|
|
111
|
+
if (!project?.complete) return null;
|
|
112
|
+
const explicit = (env.BB_CONFIG_FILE ?? "").trim();
|
|
113
|
+
return {
|
|
114
|
+
reported: state.winner,
|
|
115
|
+
actual: explicit ? "BB_CONFIG_FILE" : "project",
|
|
116
|
+
detail: `bb setup show and bb doctor report the global tier as the winner, but the runtime merges the file tiers project-last (bb.json overrides ~/.bb/config.json), so indexing actually uses ${explicit ? "BB_CONFIG_FILE" : "the project's bb.json"}` + (project.model ? ` (model ${project.model})` : "") + `.`
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
function reconstructSources(state) {
|
|
120
|
+
const firstWith = (field, pick, fallback) => {
|
|
121
|
+
for (const tier of state.tiers) {
|
|
122
|
+
const value = pick(tier);
|
|
123
|
+
if (typeof value === "string" && value.length > 0) return sourceLabel(tier.tier, field);
|
|
124
|
+
}
|
|
125
|
+
return fallback;
|
|
126
|
+
};
|
|
127
|
+
return {
|
|
128
|
+
baseURL: firstWith("BASE_URL", (t) => t.baseURL, "default"),
|
|
129
|
+
model: firstWith("MODEL", (t) => t.model, "default"),
|
|
130
|
+
apiKey: firstWith("API_KEY", (t) => t.keyFingerprint, "none")
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
function buildEmbeddingDiagnosis(opts) {
|
|
134
|
+
const env = opts.env ?? process.env;
|
|
135
|
+
const state = opts.state;
|
|
136
|
+
const chain = buildEmbeddingChain(state, env);
|
|
137
|
+
const winner = state.tiers.find((t) => t.tier === state.winner && t.complete);
|
|
138
|
+
const sources = reconstructSources(state);
|
|
139
|
+
const setup = describeEmbeddingSetup(
|
|
140
|
+
{ baseURL: winner?.baseURL ?? "", model: winner?.model ?? "", configured: state.configured, sources },
|
|
141
|
+
env
|
|
142
|
+
);
|
|
143
|
+
const observed = opts.observedFailures ?? observedEmbeddingFailures().map((f) => ({ ...f, latched: true }));
|
|
144
|
+
return {
|
|
145
|
+
disabled: isEmbeddingDisabled(env),
|
|
146
|
+
configured: state.configured,
|
|
147
|
+
remoteReady: setup.remoteReady && !isEmbeddingDisabled(env),
|
|
148
|
+
fallbackConfigured: chain.some((l) => l.role === "fallback"),
|
|
149
|
+
primaryLayer: chain.find((l) => l.role === "primary") ?? null,
|
|
150
|
+
chain,
|
|
151
|
+
problems: setup.problems,
|
|
152
|
+
observedFailures: observed,
|
|
153
|
+
probe: null,
|
|
154
|
+
tierOrderDisagreement: detectTierOrderDisagreement(state, env)
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
async function probeEmbeddingDiagnosis(diagnosis, env = process.env) {
|
|
158
|
+
const layer = diagnosis.primaryLayer;
|
|
159
|
+
if (!layer || diagnosis.disabled) return { ...diagnosis, probe: null };
|
|
160
|
+
const endpoint = parseEndpoint(layer.endpoint);
|
|
161
|
+
const key = readApiKeyForProbe(layer, env);
|
|
162
|
+
const result = await probeEmbeddingEndpoint(
|
|
163
|
+
{ baseURL: layer.endpoint, apiKey: key, model: layer.model },
|
|
164
|
+
{ timeoutMs: Math.min(readRuntimeOptions(env).timeoutMs, 15e3) }
|
|
165
|
+
);
|
|
166
|
+
return {
|
|
167
|
+
...diagnosis,
|
|
168
|
+
probe: {
|
|
169
|
+
ok: result.ok,
|
|
170
|
+
elapsedMs: result.elapsedMs,
|
|
171
|
+
endpoint: layer.endpoint,
|
|
172
|
+
model: layer.model,
|
|
173
|
+
dimension: result.dimension,
|
|
174
|
+
status: result.status,
|
|
175
|
+
kind: result.kind ?? (result.ok ? void 0 : classifyStatus(result.status ?? 0)),
|
|
176
|
+
advice: result.advice,
|
|
177
|
+
message: result.message
|
|
178
|
+
}
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
function readApiKeyForProbe(layer, env) {
|
|
182
|
+
if (layer.keyState === "absent") return "";
|
|
183
|
+
if (layer.source.startsWith("env:")) return env.BB_EMBEDDING_API_KEY ?? "";
|
|
184
|
+
return "";
|
|
185
|
+
}
|
|
186
|
+
function severityOf(problem) {
|
|
187
|
+
return problem.severity;
|
|
188
|
+
}
|
|
189
|
+
function renderChainSummary(diagnosis) {
|
|
190
|
+
return diagnosis.chain.map((l) => {
|
|
191
|
+
const mark = l.active ? "\u2192" : " ";
|
|
192
|
+
const target = l.role === "local" ? `${l.endpoint} \xB7 ${LOCAL_VECTOR_DIMENSION}-dim` : `${l.endpoint} \xB7 ${l.model}`;
|
|
193
|
+
const key = l.role === "local" || l.role === "disabled" ? "" : ` \xB7 key ${l.keyState}`;
|
|
194
|
+
return ` ${mark} ${l.order + 1}. ${l.label}: ${target}${key} [${l.source}]`;
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
function embeddingChainVerdict(diagnosis) {
|
|
198
|
+
if (diagnosis.disabled) return "disabled (BB_EMBEDDING_DISABLED) \u2014 local word vectors only";
|
|
199
|
+
if (diagnosis.remoteReady) return diagnosis.fallbackConfigured ? "remote ready (primary + fallback)" : "remote ready";
|
|
200
|
+
return "remote NOT usable \u2014 semantic search degrades to local word vectors";
|
|
201
|
+
}
|
|
202
|
+
var LOCAL_DIMENSION = LOCAL_VECTOR_DIMENSION;
|
|
203
|
+
|
|
204
|
+
// src/setup/setup-show.ts
|
|
205
|
+
function readJsonSafe(p) {
|
|
206
|
+
try {
|
|
207
|
+
if (!existsSync(p)) return null;
|
|
208
|
+
return JSON.parse(readFileSync(p, "utf8"));
|
|
209
|
+
} catch {
|
|
210
|
+
return null;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
function fileMode(p) {
|
|
214
|
+
try {
|
|
215
|
+
return statSync(p).mode & 511;
|
|
216
|
+
} catch {
|
|
217
|
+
return void 0;
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
function completeTier(tier, baseURL, model, key, file, skippedMarker) {
|
|
221
|
+
const present = baseURL !== void 0 || model !== void 0 || key !== void 0 || skippedMarker === true;
|
|
222
|
+
const complete = typeof baseURL === "string" && baseURL.length > 0 && typeof model === "string" && model.length > 0;
|
|
223
|
+
const missing = [];
|
|
224
|
+
if (!baseURL) missing.push("base URL");
|
|
225
|
+
if (!model) missing.push("model");
|
|
226
|
+
return {
|
|
227
|
+
tier,
|
|
228
|
+
present,
|
|
229
|
+
complete,
|
|
230
|
+
baseURL: typeof baseURL === "string" ? baseURL : void 0,
|
|
231
|
+
model: typeof model === "string" ? model : void 0,
|
|
232
|
+
keyFingerprint: typeof key === "string" && key.length > 0 ? fingerprintKey(key) : void 0,
|
|
233
|
+
file,
|
|
234
|
+
fileMode: file ? fileMode(file) : void 0,
|
|
235
|
+
incompleteReason: present && !complete ? `missing: ${missing.join(" + ")}` : void 0
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
function describeEmbeddingConfig(cwd = process.cwd(), env = process.env, dataDir = bbDataDir()) {
|
|
239
|
+
const globalFile = path.join(dataDir, "config.json");
|
|
240
|
+
const global = readJsonSafe(globalFile);
|
|
241
|
+
const projectFile = path.join(cwd, "bb.json");
|
|
242
|
+
const project = readJsonSafe(projectFile);
|
|
243
|
+
const envTier = completeTier(
|
|
244
|
+
"env",
|
|
245
|
+
env.BB_EMBEDDING_BASE_URL,
|
|
246
|
+
env.BB_EMBEDDING_MODEL,
|
|
247
|
+
env.BB_EMBEDDING_API_KEY
|
|
248
|
+
);
|
|
249
|
+
const globalTier = completeTier(
|
|
250
|
+
"global",
|
|
251
|
+
global?.embedding_base_url,
|
|
252
|
+
global?.embedding_model,
|
|
253
|
+
global?.embedding_api_key,
|
|
254
|
+
globalFile,
|
|
255
|
+
global?.setup_skipped === true
|
|
256
|
+
);
|
|
257
|
+
if (global && global.setup_skipped === true) globalTier.skippedMarker = true;
|
|
258
|
+
const projectTier = completeTier(
|
|
259
|
+
"project",
|
|
260
|
+
project?.embedding_base_url,
|
|
261
|
+
project?.embedding_model,
|
|
262
|
+
project?.embedding_api_key,
|
|
263
|
+
projectFile
|
|
264
|
+
);
|
|
265
|
+
const tiers = [envTier, globalTier, projectTier];
|
|
266
|
+
const winningTier = tiers.find((t) => t.complete);
|
|
267
|
+
const state = {
|
|
268
|
+
winner: winningTier?.tier ?? "none",
|
|
269
|
+
configured: Boolean(winningTier),
|
|
270
|
+
tiers
|
|
271
|
+
};
|
|
272
|
+
state.diagnosis = buildEmbeddingDiagnosis({ state, env });
|
|
273
|
+
return state;
|
|
274
|
+
}
|
|
275
|
+
function renderSetupShow(state) {
|
|
276
|
+
const lines = [];
|
|
277
|
+
lines.push("bb \u2014 embedding configuration");
|
|
278
|
+
lines.push("Precedence: env > ~/.bb/config.json > bb.json");
|
|
279
|
+
lines.push("");
|
|
280
|
+
const tierLabel = { env: "env", global: "global", project: "project" };
|
|
281
|
+
for (const t of state.tiers) {
|
|
282
|
+
const label = tierLabel[t.tier].padEnd(7);
|
|
283
|
+
if (!t.present) {
|
|
284
|
+
lines.push(`${label}: \u2014 (not set)`);
|
|
285
|
+
continue;
|
|
286
|
+
}
|
|
287
|
+
if (!t.complete) {
|
|
288
|
+
const key2 = t.keyFingerprint ? ` (key: \u2022\u2022\u2022\u2022${t.keyFingerprint})` : "";
|
|
289
|
+
const skipped = t.skippedMarker ? " \xB7 wizard skipped" : "";
|
|
290
|
+
lines.push(`${label}: \u2717 ${t.incompleteReason ?? "incomplete"}${key2}${skipped}`);
|
|
291
|
+
continue;
|
|
292
|
+
}
|
|
293
|
+
const key = t.keyFingerprint ? `key: \u2022\u2022\u2022\u2022${t.keyFingerprint}` : "key: none";
|
|
294
|
+
let line = `${label}: \u2713 ${t.baseURL} \xB7 ${t.model} \xB7 ${key}`;
|
|
295
|
+
if (t.fileMode !== void 0 && t.fileMode !== 384) {
|
|
296
|
+
line += ` \xB7 mode: ${t.fileMode.toString(8)} (expected: 600 \u2014 fix with bb doctor)`;
|
|
297
|
+
} else if (t.fileMode !== void 0) {
|
|
298
|
+
line += ` \xB7 mode: 600`;
|
|
299
|
+
}
|
|
300
|
+
if (t.skippedMarker) line += " \xB7 wizard skipped";
|
|
301
|
+
lines.push(line);
|
|
302
|
+
}
|
|
303
|
+
lines.push("");
|
|
304
|
+
if (state.configured) {
|
|
305
|
+
const w = state.winner;
|
|
306
|
+
lines.push(`Winner: ${tierLabel[w]}`);
|
|
307
|
+
} else {
|
|
308
|
+
lines.push("Winner: none \u2014 semantic search will use local vectors (weaker). Setup: bb setup");
|
|
309
|
+
}
|
|
310
|
+
const diagnosis = state.diagnosis;
|
|
311
|
+
if (diagnosis) {
|
|
312
|
+
lines.push("");
|
|
313
|
+
lines.push(`Chain: ${embeddingChainVerdict(diagnosis)}`);
|
|
314
|
+
for (const line of renderChainSummary(diagnosis)) lines.push(line);
|
|
315
|
+
const problems = diagnosis.problems.filter((p) => !/^No embedding provider is configured/.test(p.message));
|
|
316
|
+
for (const p of problems) {
|
|
317
|
+
const varName = p.envVar ? `${p.envVar}: ` : "";
|
|
318
|
+
lines.push(` ! ${varName}${p.message}`);
|
|
319
|
+
}
|
|
320
|
+
for (const f of diagnosis.observedFailures) {
|
|
321
|
+
lines.push(` \u2717 ${f.status} ${f.kind} from ${f.baseURL} \u2014 ${f.advice}`);
|
|
322
|
+
}
|
|
323
|
+
if (diagnosis.tierOrderDisagreement) {
|
|
324
|
+
lines.push(` ! ${diagnosis.tierOrderDisagreement.detail}`);
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
return lines.join("\n") + "\n";
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
export {
|
|
331
|
+
buildEmbeddingDiagnosis,
|
|
332
|
+
renderChainSummary,
|
|
333
|
+
embedding_diagnosis_exports,
|
|
334
|
+
describeEmbeddingConfig,
|
|
335
|
+
renderSetupShow
|
|
336
|
+
};
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
// src/ast/index-space.ts
|
|
2
|
+
import { statSync } from "fs";
|
|
3
|
+
function runPragma(rawDb, body) {
|
|
4
|
+
const driver = rawDb?.native ?? rawDb;
|
|
5
|
+
if (typeof driver?.pragma === "function") return driver.pragma(body);
|
|
6
|
+
if (typeof driver?.prepare === "function") {
|
|
7
|
+
const stmt = driver.prepare(`PRAGMA ${body}`);
|
|
8
|
+
if (typeof stmt?.all === "function") {
|
|
9
|
+
const rows = stmt.all();
|
|
10
|
+
return Array.isArray(rows) ? rows : [rows];
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
return void 0;
|
|
14
|
+
}
|
|
15
|
+
function checkpointWal(rawDb) {
|
|
16
|
+
try {
|
|
17
|
+
const result = runPragma(rawDb, "wal_checkpoint(TRUNCATE)");
|
|
18
|
+
const row = Array.isArray(result) ? result[0] : result;
|
|
19
|
+
if (row && typeof row === "object" && "busy" in row) return Number(row.busy) === 0;
|
|
20
|
+
return true;
|
|
21
|
+
} catch {
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
function spaceReport(rawDb, dbPath) {
|
|
26
|
+
let dbBytes = 0;
|
|
27
|
+
let walBytes = 0;
|
|
28
|
+
try {
|
|
29
|
+
dbBytes = statSync(dbPath).size;
|
|
30
|
+
} catch {
|
|
31
|
+
}
|
|
32
|
+
try {
|
|
33
|
+
walBytes = statSync(`${dbPath}-wal`).size;
|
|
34
|
+
} catch {
|
|
35
|
+
}
|
|
36
|
+
let freelistBytes = 0;
|
|
37
|
+
let freeRatio = 0;
|
|
38
|
+
try {
|
|
39
|
+
const freeRow = runPragma(rawDb, "freelist_count");
|
|
40
|
+
const pageRow = runPragma(rawDb, "page_size");
|
|
41
|
+
const first = (row, key) => Array.isArray(row) ? row[0]?.[key] : row?.[key];
|
|
42
|
+
const free = Number(first(freeRow, "freelist_count") ?? 0);
|
|
43
|
+
const pageSize = Number(first(pageRow, "page_size") ?? 0);
|
|
44
|
+
freelistBytes = free * pageSize;
|
|
45
|
+
freeRatio = dbBytes > 0 ? freelistBytes / dbBytes : 0;
|
|
46
|
+
} catch {
|
|
47
|
+
}
|
|
48
|
+
return { dbBytes, walBytes, freelistBytes, freeRatio, checkpointed: false, vacuumed: false, vacuumMs: null };
|
|
49
|
+
}
|
|
50
|
+
function shouldVacuumAfterWipe(input) {
|
|
51
|
+
const minBytes = input.minBytes ?? 256 * 1024 * 1024;
|
|
52
|
+
return input.rowsDeleted > 0 && input.dbBytes >= minBytes;
|
|
53
|
+
}
|
|
54
|
+
function reclaimSpace(rawDb, dbPath, opts = {}) {
|
|
55
|
+
const checkpointed = checkpointWal(rawDb);
|
|
56
|
+
const before = spaceReport(rawDb, dbPath);
|
|
57
|
+
const ratioFloor = opts.vacuumAboveRatio ?? 0.25;
|
|
58
|
+
const byteFloor = opts.vacuumAboveBytes ?? 64 * 1024 * 1024;
|
|
59
|
+
const wantVacuum = opts.vacuum === true && before.freelistBytes >= byteFloor && before.freeRatio >= ratioFloor;
|
|
60
|
+
let vacuumed = false;
|
|
61
|
+
let vacuumMs = null;
|
|
62
|
+
if (wantVacuum && process.env.BB_INDEX_VACUUM !== "0") {
|
|
63
|
+
const started = Date.now();
|
|
64
|
+
try {
|
|
65
|
+
rawDb.exec("VACUUM");
|
|
66
|
+
vacuumed = true;
|
|
67
|
+
} catch (e) {
|
|
68
|
+
opts.log?.("VACUUM skipped", { error: String(e?.message ?? e) });
|
|
69
|
+
}
|
|
70
|
+
vacuumMs = Date.now() - started;
|
|
71
|
+
if (vacuumed) checkpointWal(rawDb);
|
|
72
|
+
}
|
|
73
|
+
const after = spaceReport(rawDb, dbPath);
|
|
74
|
+
return { ...after, checkpointed, vacuumed, vacuumMs };
|
|
75
|
+
}
|
|
76
|
+
function formatSpace(report) {
|
|
77
|
+
const mb = (n) => `${(n / 1024 / 1024).toFixed(1)} MB`;
|
|
78
|
+
const parts = [`db ${mb(report.dbBytes)}`, `wal ${mb(report.walBytes)}`];
|
|
79
|
+
if (report.freeRatio > 0) parts.push(`${(report.freeRatio * 100).toFixed(0)}% free`);
|
|
80
|
+
if (report.vacuumed && report.vacuumMs !== null) parts.push(`vacuumed in ${(report.vacuumMs / 1e3).toFixed(1)}s`);
|
|
81
|
+
return parts.join(", ");
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export {
|
|
85
|
+
checkpointWal,
|
|
86
|
+
spaceReport,
|
|
87
|
+
shouldVacuumAfterWipe,
|
|
88
|
+
reclaimSpace,
|
|
89
|
+
formatSpace
|
|
90
|
+
};
|