gitnexus 1.6.10-rc.1 → 1.6.10-rc.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (117) hide show
  1. package/README.md +68 -15
  2. package/dist/cli/analyze.js +106 -3
  3. package/dist/cli/cli-message.d.ts +1 -1
  4. package/dist/cli/doctor.d.ts +5 -0
  5. package/dist/cli/doctor.js +41 -3
  6. package/dist/cli/editor-targets.js +11 -0
  7. package/dist/cli/embeddings.d.ts +12 -0
  8. package/dist/cli/embeddings.js +49 -0
  9. package/dist/cli/help-i18n.js +4 -0
  10. package/dist/cli/i18n/en.d.ts +4 -0
  11. package/dist/cli/i18n/en.js +4 -0
  12. package/dist/cli/i18n/resources.d.ts +8 -0
  13. package/dist/cli/i18n/zh-CN.d.ts +4 -0
  14. package/dist/cli/i18n/zh-CN.js +4 -0
  15. package/dist/cli/index.js +11 -0
  16. package/dist/cli/setup.js +33 -24
  17. package/dist/core/embeddings/embedder.js +16 -2
  18. package/dist/core/embeddings/http-client.d.ts +28 -1
  19. package/dist/core/embeddings/http-client.js +107 -15
  20. package/dist/core/embeddings/node-module-compat.d.ts +23 -0
  21. package/dist/core/embeddings/node-module-compat.js +23 -0
  22. package/dist/core/embeddings/onnxruntime-common-resolver.js +6 -3
  23. package/dist/core/embeddings/onnxruntime-node-resolver.js +31 -5
  24. package/dist/core/embeddings/runtime-install.d.ts +119 -0
  25. package/dist/core/embeddings/runtime-install.js +372 -0
  26. package/dist/core/embeddings/runtime-support.d.ts +48 -17
  27. package/dist/core/embeddings/runtime-support.js +96 -0
  28. package/dist/core/group/extractors/http-patterns/python.js +246 -108
  29. package/dist/core/group/extractors/manifest-extractor.js +4 -0
  30. package/dist/core/ingestion/cobol/jcl-processor.js +9 -8
  31. package/dist/core/ingestion/cobol-processor.js +27 -26
  32. package/dist/core/ingestion/community-processor.d.ts +51 -1
  33. package/dist/core/ingestion/community-processor.js +316 -63
  34. package/dist/core/ingestion/emit-references.js +3 -2
  35. package/dist/core/ingestion/markdown-processor.js +3 -2
  36. package/dist/core/ingestion/parsing-processor.d.ts +3 -1
  37. package/dist/core/ingestion/parsing-processor.js +4 -0
  38. package/dist/core/ingestion/pipeline-phases/parse-impl.js +42 -0
  39. package/dist/core/ingestion/route-extractors/constant-resolver.d.ts +83 -0
  40. package/dist/core/ingestion/route-extractors/constant-resolver.js +131 -0
  41. package/dist/core/ingestion/route-extractors/python-const-resolver.d.ts +75 -0
  42. package/dist/core/ingestion/route-extractors/python-const-resolver.js +299 -0
  43. package/dist/core/ingestion/tree-sitter-queries.d.ts +1 -1
  44. package/dist/core/ingestion/tree-sitter-queries.js +12 -1
  45. package/dist/core/ingestion/utils/line-base.d.ts +20 -0
  46. package/dist/core/ingestion/utils/line-base.js +20 -0
  47. package/dist/core/ingestion/utils/symbol-labels.d.ts +21 -0
  48. package/dist/core/ingestion/utils/symbol-labels.js +45 -0
  49. package/dist/core/ingestion/workers/parse-worker.d.ts +34 -0
  50. package/dist/core/ingestion/workers/parse-worker.js +39 -4
  51. package/dist/core/ingestion/workers/result-merge.js +4 -0
  52. package/dist/core/lbug/csv-generator.js +8 -2
  53. package/dist/core/lbug/extension-load-error.d.ts +67 -0
  54. package/dist/core/lbug/extension-load-error.js +320 -0
  55. package/dist/core/lbug/extension-loader.d.ts +17 -2
  56. package/dist/core/lbug/extension-loader.js +38 -13
  57. package/dist/core/lbug/lbug-adapter.js +7 -16
  58. package/dist/core/lbug/native-check.d.ts +22 -0
  59. package/dist/core/lbug/native-check.js +66 -0
  60. package/dist/core/lbug/pool-adapter.js +10 -1
  61. package/dist/core/lbug/sidecar-recovery.d.ts +32 -0
  62. package/dist/core/lbug/sidecar-recovery.js +91 -7
  63. package/dist/core/platform/capabilities.js +27 -1
  64. package/dist/core/run-analyze.js +33 -6
  65. package/dist/core/search/fts-indexes.d.ts +7 -0
  66. package/dist/core/search/fts-indexes.js +37 -0
  67. package/dist/mcp/core/embedder.js +16 -2
  68. package/dist/mcp/local/line-display.d.ts +22 -0
  69. package/dist/mcp/local/line-display.js +3 -0
  70. package/dist/mcp/local/local-backend.d.ts +14 -0
  71. package/dist/mcp/local/local-backend.js +63 -19
  72. package/dist/mcp/local/pdg-impact.d.ts +5 -3
  73. package/dist/mcp/local/pdg-impact.js +5 -2
  74. package/dist/mcp/resources.js +1 -0
  75. package/dist/mcp/tools.js +1 -1
  76. package/dist/server/api.js +2 -2
  77. package/dist/storage/parse-cache.js +1 -1
  78. package/dist/storage/repo-manager.d.ts +6 -1
  79. package/dist/storage/repo-manager.js +6 -1
  80. package/hooks/antigravity/gitnexus-antigravity-hook.cjs +50 -3
  81. package/hooks/claude/gitnexus-hook.cjs +59 -9
  82. package/package.json +5 -3
  83. package/scripts/cross-platform-tests.ts +25 -0
  84. package/scripts/ensure-fts.ts +32 -0
  85. package/scripts/install-duckdb-extension.mjs +85 -24
  86. package/scripts/run-cross-platform.ts +46 -6
  87. package/scripts/shard-arg.ts +30 -0
  88. package/web/assets/{agent-Dli_x7bU.js → agent-BYSIWGsh.js} +1 -1
  89. package/web/assets/{architectureDiagram-UL44E2DR-dEkqUZN9.js → architectureDiagram-UL44E2DR-CyuGW0uP.js} +1 -1
  90. package/web/assets/{chunk-LCXTWHL2-CfLLCywY.js → chunk-LCXTWHL2-DVREwhp-.js} +1 -1
  91. package/web/assets/{chunk-RG4AUYOV-CqWzWsV3.js → chunk-RG4AUYOV-C9vCX6ww.js} +1 -1
  92. package/web/assets/{classDiagram-KGZ6W3CR-CMne4tG9.js → classDiagram-KGZ6W3CR-CGMEoNQ9.js} +1 -1
  93. package/web/assets/{classDiagram-v2-72OJOZXJ-CMne4tG9.js → classDiagram-v2-72OJOZXJ-CGMEoNQ9.js} +1 -1
  94. package/web/assets/{dagre-ND4H6XIP-Co5rRx9X.js → dagre-ND4H6XIP-t2C8kx0k.js} +1 -1
  95. package/web/assets/{diagram-3NCE3AQN-DBp4O00j.js → diagram-3NCE3AQN-C9ptKwnW.js} +1 -1
  96. package/web/assets/{diagram-GF46GFSD-6N_8yS0i.js → diagram-GF46GFSD-mPO3zDtx.js} +1 -1
  97. package/web/assets/{diagram-QXG6HAR7-Di093rFg.js → diagram-QXG6HAR7-yhaYsLwX.js} +1 -1
  98. package/web/assets/{diagram-WEQXMOUZ-DZWi4SUN.js → diagram-WEQXMOUZ-0wPxtBci.js} +1 -1
  99. package/web/assets/{erDiagram-L5TCEMPS-8X1y6R4Y.js → erDiagram-L5TCEMPS-S5bL5d3-.js} +1 -1
  100. package/web/assets/{flowDiagram-H6V6AXG4-CMpY8Ufn.js → flowDiagram-H6V6AXG4-C3K_EeGO.js} +1 -1
  101. package/web/assets/{index-KctnI3Vq.js → index-CxQeu15d.js} +5 -5
  102. package/web/assets/index-pwIeWBc_.css +2 -0
  103. package/web/assets/{infoDiagram-3YFTVSEB-BaLMZkUg.js → infoDiagram-3YFTVSEB-DZCeN1eh.js} +1 -1
  104. package/web/assets/{ishikawaDiagram-BNXS4ZKH-DfYpxnE5.js → ishikawaDiagram-BNXS4ZKH-Dh7VlS5F.js} +1 -1
  105. package/web/assets/{kanban-definition-75IXJCU3-CpfVLLf9.js → kanban-definition-75IXJCU3-BO0rtopY.js} +1 -1
  106. package/web/assets/{mindmap-definition-2TDM6QVE-DypvbOMQ.js → mindmap-definition-2TDM6QVE-ChLJpHp4.js} +1 -1
  107. package/web/assets/{pieDiagram-CU6KROY3-s27EFWgP.js → pieDiagram-CU6KROY3-BUmB1P5T.js} +1 -1
  108. package/web/assets/{requirementDiagram-JXO7QTGE-CWhqInuf.js → requirementDiagram-JXO7QTGE-BGc7wqB-.js} +1 -1
  109. package/web/assets/{sequenceDiagram-VS2MUI6T-RyTlZ5cR.js → sequenceDiagram-VS2MUI6T-BurftNoj.js} +1 -1
  110. package/web/assets/{stateDiagram-7D4R322I-DTjVfX4A.js → stateDiagram-7D4R322I-CvWv3Bds.js} +1 -1
  111. package/web/assets/{stateDiagram-v2-36443NZ5-xY9_k9_Q.js → stateDiagram-v2-36443NZ5-CGQHxdn1.js} +1 -1
  112. package/web/assets/{timeline-definition-O6YCAMPW-DrrqLYAf.js → timeline-definition-O6YCAMPW-JFXCOr3m.js} +1 -1
  113. package/web/assets/{vennDiagram-MWXL3ELB-B0RkWAim.js → vennDiagram-MWXL3ELB-BBSN9X0h.js} +1 -1
  114. package/web/assets/{wardleyDiagram-CUQ6CDDI-boUxiQ5F.js → wardleyDiagram-CUQ6CDDI-ROVyUxuA.js} +1 -1
  115. package/web/assets/{xychartDiagram-N2JHSOCM-BOLm0eNm.js → xychartDiagram-N2JHSOCM-CmNsPJD5.js} +1 -1
  116. package/web/index.html +2 -2
  117. package/web/assets/index-_lgn7hs5.css +0 -2
package/README.md CHANGED
@@ -43,13 +43,13 @@ To configure MCP for your editor, run `npx gitnexus setup` once — or set it up
43
43
  | **Claude Code** | Yes | Yes | Yes (PreToolUse + PostToolUse) | **Full** |
44
44
  | **Cursor** | Yes | Yes | Yes (postToolUse, [manual install](../gitnexus-cursor-integration/README.md#hook-install)) | **Full** |
45
45
  | **Antigravity** (Google) | Yes | Yes | Yes (AfterTool, [Gemini CLI hooks schema](https://geminicli.com/docs/hooks/reference/)) | **Full** |
46
- | **Codex** | Yes | Yes | — | MCP + Skills |
46
+ | **Codex** | Yes | Yes | Yes (PreToolUse + PostToolUse, [Codex hooks](https://developers.openai.com/codex/hooks)) | **Full** |
47
47
  | **OpenCode** | Yes | Yes | — | MCP + Skills |
48
48
  | **CodeBuddy** (Tencent) | Yes | Yes | — | MCP + Skills |
49
49
  | **Qoder** (Alibaba) | Yes | Yes | — | MCP + Skills |
50
50
  | **Windsurf** | Yes | — | — | MCP |
51
51
 
52
- > **Claude Code** gets the deepest integration: MCP tools + agent skills + PreToolUse hooks that automatically enrich grep/glob/bash calls with knowledge graph context + PostToolUse hooks that detect a stale index after commits and prompt the agent to reindex.
52
+ > **Claude Code** and **Codex** get the deepest integration: MCP tools + agent skills + PreToolUse hooks that automatically enrich grep/glob/bash calls with knowledge graph context + PostToolUse hooks that detect a stale index after commits and prompt the agent to reindex.
53
53
 
54
54
  ### Community Integrations
55
55
 
@@ -71,12 +71,23 @@ claude mcp add gitnexus -- npx -y gitnexus@latest mcp
71
71
  claude mcp add gitnexus -- cmd /c npx -y gitnexus@latest mcp
72
72
  ```
73
73
 
74
- ### Codex (full support — MCP + skills)
74
+ ### Codex (full support — MCP + skills + hooks)
75
75
 
76
76
  ```bash
77
77
  codex mcp add gitnexus -- npx -y gitnexus@latest mcp
78
78
  ```
79
79
 
80
+ Codex hooks (PreToolUse graph enrichment + PostToolUse stale-index detection in `~/.codex/hooks.json`, [same schema as Claude Code](https://developers.openai.com/codex/hooks)) need the bundled adapter script, so they are installed by `gitnexus setup -c codex` rather than manually.
81
+
82
+ Alternatively, install everything as a [Codex plugin](https://developers.openai.com/codex/plugins/build) (MCP + skills + hooks in one step):
83
+
84
+ ```bash
85
+ codex plugin marketplace add abhigyanpatwari/GitNexus
86
+ # then inside Codex: /plugins → install "GitNexus"
87
+ ```
88
+
89
+ > **Codex notes:** SessionStart is intentionally not registered — Codex reads [AGENTS.md natively](https://developers.openai.com/codex/guides/agents-md), which already carries the GitNexus context block. Newly installed hooks need a one-time approval in Codex via `/hooks` before they run. Pick **one** install route (`gitnexus setup -c codex` **or** the plugin): plugin hooks load alongside `~/.codex/hooks.json`, so installing both can fire duplicate hooks per tool call.
90
+
80
91
  ### Cursor / Windsurf
81
92
 
82
93
  Add to `~/.cursor/mcp.json` (global — works for all projects):
@@ -152,6 +163,16 @@ GitNexus builds a complete knowledge graph of your codebase through a multi-phas
152
163
 
153
164
  The result is a **LadybugDB graph database** stored locally in `.gitnexus/` with full-text search and semantic embeddings.
154
165
 
166
+ ### Experimental community detection engine
167
+
168
+ Community detection uses the bundled Graphology Leiden implementation by default. To test the #2337 Icebug migration path without changing default analyze behavior, set:
169
+
170
+ ```bash
171
+ GITNEXUS_COMMUNITY_ENGINE=icebug npx gitnexus analyze
172
+ ```
173
+
174
+ Supported values are `graphology`, `icebug`, and `auto`. The Icebug path is an experimental probe: GitNexus does not bundle an Icebug native package yet, and if a separately resolvable module is unavailable or its API does not match the expected `Graph.fromCSR` / `ParallelLeidenView` shape, analyze falls back to Graphology and reports the fallback in progress output. Today `auto` is behaviorally identical to `icebug`: both try Icebug and fall back to Graphology, while `graphology` skips the Icebug probe entirely.
175
+
155
176
  ## MCP Tools
156
177
 
157
178
  Your AI agent gets **17 tools** (15 per-repo + 2 group) automatically:
@@ -209,6 +230,7 @@ gitnexus analyze [path] # Index a repository (or update stale index)
209
230
  gitnexus analyze --repair-fts # Fast path: rebuild/verify only FTS indexes on existing index data
210
231
  gitnexus analyze --force # Full rebuild: re-parse + graph rebuild + FTS rebuild
211
232
  gitnexus analyze --embeddings # Enable embedding generation (slower, better search)
233
+ gitnexus embeddings install # Fetch the optional local embedding stack on demand (--cuda, --force)
212
234
  gitnexus analyze --skills # Generate repo-specific skill files from detected communities
213
235
  gitnexus analyze --skip-agents-md # Preserve custom AGENTS.md/CLAUDE.md gitnexus section edits
214
236
  gitnexus analyze --skip-skills # Skip installing .claude/skills/gitnexus/ skill files
@@ -409,18 +431,40 @@ If `npm install -g gitnexus` fails on native modules:
409
431
  npm install -g gitnexus
410
432
  ```
411
433
 
434
+ ### Installation fails behind an HTTP proxy (`onnxruntime-node` postinstall)
435
+
436
+ `onnxruntime-node`'s postinstall downloads optional CUDA GPU binaries from `api.nuget.org` — outside the npm registry, so registry mirrors don't cover it, and its proxy layer (`global-agent`) ignores the standard `HTTP_PROXY`/`HTTPS_PROXY` variables and rejects 302 redirects ([#2370](https://github.com/abhigyanpatwari/GitNexus/issues/2370)).
437
+
438
+ Since the packages are optional dependencies, a failed download no longer breaks `npm install -g gitnexus` — npm skips the embedding stack and everything else works. The stack then **self-heals on demand**: the first `gitnexus analyze --embeddings` (or an explicit `gitnexus embeddings install`) fetches it through your configured npm registry — mirrors and proxies apply, no NuGet download involved — into `~/.gitnexus/embedding-runtime`.
439
+
440
+ ```bash
441
+ # heal a proxy-degraded install manually (CPU embeddings; registry-only)
442
+ gitnexus embeddings install
443
+
444
+ # reinstall into the prefix even when the stack already resolves
445
+ gitnexus embeddings install --force
446
+
447
+ # CUDA GPU hosts: also fetch GPU binaries (NuGet; set the proxy global-agent reads)
448
+ GLOBAL_AGENT_HTTPS_PROXY=<proxy-url> gitnexus embeddings install --cuda
449
+ ```
450
+
451
+ The prefix defaults to `~/.gitnexus/embedding-runtime`; set `GITNEXUS_EMBEDDING_RUNTIME_DIR` to install it elsewhere (e.g. a writable path in a container).
452
+
453
+ > **Node requirement for the on-demand prefix:** the self-heal loads the prefixed packages via `module.registerHooks`, available on Node **≥ 22.15** (on the 22.x line) or **≥ 23.5** (on the 23.x line). On an older Node the packages install but can't be loaded from the prefix — reinstall them into the install itself instead (works on every supported Node): `ONNXRUNTIME_NODE_INSTALL=skip npm install -g gitnexus` (Windows: `set ONNXRUNTIME_NODE_INSTALL=skip && npm install -g gitnexus`). Skipping only the CUDA download keeps full CPU embeddings (CPU embeddings don't need it). Check the result any time with `gitnexus doctor` (Embeddings → Support line).
454
+
412
455
  ### Analyze warns about unavailable FTS or VECTOR extensions
413
456
 
414
- GitNexus uses optional DuckDB extensions for BM25 and vector search. The `gitnexus serve` and MCP read paths only ever try to `LOAD` the extensions — they never block on a network install. The `analyze` command, by default, attempts one bounded out-of-process `INSTALL` if `LOAD` fails and proceeds even when that install times out, so the index is always written to disk; BM25/vector search degrade gracefully until the extensions become available.
457
+ GitNexus uses optional DuckDB extensions for BM25 and vector search. The `gitnexus serve` and MCP read paths only ever try to `LOAD` the extensions — they never block on a network install. The `analyze` command, by default, attempts one bounded out-of-process install if `LOAD` fails (a plain `INSTALL` to download a missing extension, escalating to `FORCE INSTALL` only when the `LOAD` error shows the existing file is broken or truncated, so a permanent non-file failure does not re-download on every run) and proceeds even when that install times out, so the index is always written to disk; BM25/vector search degrade gracefully until the extensions become available.
415
458
 
416
459
  Configure the behavior with these environment variables:
417
460
 
418
461
  | Variable | Values | Default | Effect |
419
462
  | -------------------------------------------- | ---------------------------- | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
420
- | `GITNEXUS_LBUG_EXTENSION_INSTALL` | `auto`, `load-only`, `never` | `auto` | `auto` runs one bounded INSTALL if LOAD fails. `load-only` only uses already-installed extensions (recommended for offline / firewalled environments). `never` skips optional extensions entirely. |
421
- | `GITNEXUS_LBUG_EXTENSION_INSTALL_TIMEOUT_MS` | positive integer | `15000` | Wall-clock budget for the out-of-process `INSTALL` child before it is killed. |
463
+ | `GITNEXUS_LBUG_EXTENSION_INSTALL` | `auto`, `load-only`, `never` | `auto` | `auto` runs one bounded install if LOAD fails — a plain `INSTALL`, escalating to `FORCE INSTALL` only when the LOAD error shows the present extension file is broken. `load-only` only uses already-installed extensions (recommended for offline / firewalled environments). `never` skips optional extensions entirely. |
464
+ | `GITNEXUS_LBUG_EXTENSION_INSTALL_TIMEOUT_MS` | positive integer | `15000` | Wall-clock budget for the out-of-process extension-install child before it is killed. |
422
465
  | `GITNEXUS_FTS_STEMMER` | supported LadybugDB stemmer | `porter` | Stemmer used when rebuilding BM25/FTS indexes. Use `none` for CJK-heavy repositories, or a language stemmer such as `german`, `french`, or `spanish` when that better matches repository comments and identifiers. Re-run `gitnexus analyze --repair-fts` after changing it. |
423
466
  | `GITNEXUS_FTS_CJK_SEGMENTATION` | `none`, `bigram` | `none` | `bigram` inserts overlapping character-bigram boundaries into Chinese/Japanese Han-ideograph spans in `content`/`description` before FTS indexing, so LadybugDB's space-only tokenizer can see sub-phrase word boundaries. Scoped to CJK Unified Ideographs only — Japanese Hiragana/Katakana and Korean Hangul are not currently segmented. Unlike `GITNEXUS_FTS_STEMMER`, this rewrites stored text — enabling it on an already-indexed repo requires a full `gitnexus analyze --force`; neither `--repair-fts` nor a plain incremental `analyze` applies it to previously-indexed files. Set the same value wherever `analyze` and search-serving processes (CLI query, MCP server, web server) run. |
467
+ | `GITNEXUS_COMMUNITY_ENGINE` | `graphology`, `icebug`, `auto` | `graphology` | Community-detection engine used during analyze. `graphology` uses the bundled default path. `icebug` and `auto` currently behave identically: both try the experimental Icebug CSR path and fall back to Graphology if the optional native module is unavailable or incompatible. |
424
468
  | `GITNEXUS_WAL_CHECKPOINT_THRESHOLD` | integer `>= -1` | `67108864` (64 MiB) | LadybugDB WAL auto-checkpoint threshold during analyze (bytes). Auto-checkpoint remains enabled; `-1` keeps Ladybug's stock ~16 MiB. Larger thresholds reduce checkpoint frequency but increase the WAL size at rotation time — choose a smaller value on disk-constrained environments. |
425
469
 
426
470
  ```bash
@@ -502,17 +546,26 @@ After scope resolution, analyze prunes inert block-local value symbols (a functi
502
546
 
503
547
  Programmatic callers can pass `keepLocalValueSymbols: true` in `PipelineOptions` instead of setting the env var.
504
548
 
505
- ### Hook augmentation/notifications are silently skipped
549
+ ### Hook augmentation and skip diagnostics
506
550
 
507
- The Claude Code / Antigravity hooks intentionally stay **silent** on normal skip
551
+ The Claude Code / Antigravity hooks keep their **stderr** silent on normal skip
508
552
  paths so strict hook runners (e.g. Codex `PreToolUse`) never see unexpected
509
- output. A search may not be augmented — or a stale-index reminder may not appear
510
- on stderr — when the GitNexus MCP server owns the repo DB, when the DB-lock probe
511
- times out and fails closed, or when the index is already current.
512
-
513
- To see why a hook skipped, set `GITNEXUS_DEBUG=1` and re-run the action the hook
514
- writes the reason (e.g. `[GitNexus] augment skipped: MCP server owns DB`) and the
515
- stale-index hint to its stderr:
553
+ diagnostic output.
554
+
555
+ When a GitNexus process holds the repo DB write lock (the common case the MCP
556
+ server is running, or the DB-lock probe timed out and failed closed), the local
557
+ CLI `augment` can't run (LadybugDB is single-writer). Rather than drop the
558
+ augmentation, the hook hands the agent a short, conditional MCP-query hint on
559
+ stdout (the sanctioned `additionalContext` channel) — _"if the GitNexus MCP tools
560
+ are live in this session, call `query` …"_ — so an agent that has the tools can
561
+ still fetch graph-ranked context. The hint is throttled to at most once per repo
562
+ per window (`GITNEXUS_MCP_HINT_THROTTLE_MS`, default 10 min; `0` disables), so an
563
+ owner-locked session isn't nudged on every search. A stale-index reminder, or an
564
+ already-current index, stays silent.
565
+
566
+ To see why a hook skipped the CLI augment, set `GITNEXUS_DEBUG=1` and re-run the
567
+ action — the hook writes the reason (e.g. `[GitNexus] augment skipped: MCP server
568
+ owns DB`) and the stale-index hint to its stderr:
516
569
 
517
570
  ```bash
518
571
  GITNEXUS_DEBUG=1 <your command> # surfaces hook skip/diagnostic reasons on stderr
@@ -27,8 +27,9 @@ import { cliError } from './cli-message.js';
27
27
  import { EMBEDDING_DIMS_ERROR, normalizeEmbeddingDims } from './embedding-dims.js';
28
28
  import { formatElapsed } from './format-elapsed.js';
29
29
  import { isHfDownloadFailure } from '../core/embeddings/hf-env.js';
30
- import { safeUrl } from '../core/embeddings/http-client.js';
31
- import { isLocalEmbeddingRuntimeBlockerMessage } from '../core/embeddings/runtime-support.js';
30
+ import { isHttpEmbeddingDimsError, isHttpEmbeddingError, isHttpMode, safeUrl, } from '../core/embeddings/http-client.js';
31
+ import { isLocalEmbeddingRuntimeBlockerMessage, isMissingLocalEmbeddingStackMessage, localEmbeddingPrefixUnloadableMessage, localEmbeddingStackMissingMessage, } from '../core/embeddings/runtime-support.js';
32
+ import { ANALYZE_EMBEDDING_INSTALL_TIMEOUT_MS, getEmbeddingInstallTimeoutMs, getEmbeddingRuntimeDir, installEmbeddingRuntime, isPrefixRuntimeLoadable, resolveEmbeddingRuntime, } from '../core/embeddings/runtime-install.js';
32
33
  import { warnIfNpm11NpxRisk } from './resolve-invocation.js';
33
34
  // Capture stderr.write at module load BEFORE anything (LadybugDB native
34
35
  // init, progress bar, console redirection) can monkey-patch it. The
@@ -797,6 +798,52 @@ const analyzeCommandImpl = async (inputPath, cliOptions) => {
797
798
  console.log(' Note: custom HTTP embeddings require BOTH --embedding-base-url and --embedding-model ' +
798
799
  '(or the matching env vars). Falling back to local ONNX embeddings.\n');
799
800
  }
801
+ // On-demand embedding runtime (#2370): when the optional stack was pruned at
802
+ // install time (proxy-blocked NuGet download in onnxruntime-node's
803
+ // postinstall), heal it here instead of failing later in the pipeline. The
804
+ // install goes through the user's npm registry config (mirrors/proxies
805
+ // apply) with --ignore-scripts, so no NuGet download is attempted. Runs
806
+ // before bar.start() like the sibling validations above.
807
+ if (embeddingsEnabled && !isHttpMode()) {
808
+ const resolved = resolveEmbeddingRuntime();
809
+ // Resolved-but-unloadable (a populated prefix on a Node with no
810
+ // module.registerHooks), or nothing installed on such a Node: fail fast with
811
+ // capability guidance instead of dying mid-pipeline over an unusable prefix
812
+ // or downloading a runtime the loader can't reach. A package-sourced stack
813
+ // never needs the hook, so it is excluded. --embeddings was explicitly
814
+ // requested and this failure is deterministic, so fail fast rather than
815
+ // silently degrading to BM25 (distinct from a transient install timeout).
816
+ if (!isPrefixRuntimeLoadable() && (resolved === null || resolved.source === 'runtime-prefix')) {
817
+ cliError(` ${localEmbeddingPrefixUnloadableMessage().replace(/\n/g, '\n ')}\n`, {
818
+ recoveryHint: 'local-embedding-stack-missing',
819
+ });
820
+ process.exitCode = 1;
821
+ return;
822
+ }
823
+ // On-demand embedding runtime (#2370): when the optional stack was pruned at
824
+ // install time (proxy-blocked NuGet download in onnxruntime-node's
825
+ // postinstall), heal it here instead of failing later in the pipeline. The
826
+ // install goes through the user's npm registry config (mirrors/proxies
827
+ // apply) with --ignore-scripts, so no NuGet download is attempted.
828
+ if (resolved === null) {
829
+ console.log(` Local embedding runtime is not installed (optional packages were skipped at install time).\n` +
830
+ ` Downloading it now from your npm registry into ${getEmbeddingRuntimeDir()} …\n` +
831
+ ` (one-time; rerun manually anytime with \`gitnexus embeddings install\`)\n`);
832
+ try {
833
+ // Short deadline (env override still wins): analyze is interactive, so a
834
+ // blackholed proxy must not stall the whole index run for the 10-minute
835
+ // default — fail over to the guidance below instead.
836
+ await installEmbeddingRuntime({}, getEmbeddingInstallTimeoutMs(ANALYZE_EMBEDDING_INSTALL_TIMEOUT_MS));
837
+ console.log(' Embedding runtime installed.\n');
838
+ }
839
+ catch (err) {
840
+ cliError(` Could not install the embedding runtime: ${err instanceof Error ? err.message : String(err)}\n\n` +
841
+ ` ${localEmbeddingStackMissingMessage().replace(/\n/g, '\n ')}\n`, { recoveryHint: 'local-embedding-stack-missing' });
842
+ process.exitCode = 1;
843
+ return;
844
+ }
845
+ }
846
+ }
800
847
  if (options.repairFts && options.force) {
801
848
  cliError(' Cannot combine `--repair-fts` with `--force`. ' +
802
849
  'Use `--repair-fts` for fast FTS-only repair, or `--force` for a full rebuild.\n');
@@ -1203,10 +1250,66 @@ const analyzeCommandImpl = async (inputPath, cliOptions) => {
1203
1250
  process.exitCode = 1;
1204
1251
  return;
1205
1252
  }
1253
+ // The optional embedding stack (@huggingface/transformers → onnxruntime-node)
1254
+ // was pruned at install time — usually a proxy-blocked NuGet download during
1255
+ // onnxruntime-node's postinstall (#2370). Checked before the generic
1256
+ // module-not-found "installation may be corrupt" hint below, which would
1257
+ // otherwise misdiagnose a deliberate optional-dependency skip.
1258
+ if (isMissingLocalEmbeddingStackMessage(msg)) {
1259
+ cliError(` ${msg.replace(/\n/g, '\n ')}\n`, {
1260
+ recoveryHint: 'local-embedding-stack-missing',
1261
+ });
1262
+ process.exitCode = 1;
1263
+ return;
1264
+ }
1265
+ // Malformed GITNEXUS_EMBEDDING_DIMS env var (#2385). readConfig() throws a
1266
+ // plain Error (a config mistake, not an endpoint failure), surfacing here from
1267
+ // httpEmbed()->readConfig() inside the analysis run. Show a clean config
1268
+ // message rather than a raw stack dump. The --embedding-dims CLI flag is
1269
+ // validated up front (EMBEDDING_DIMS_ERROR); this covers the env-var path.
1270
+ // Checked before the endpoint/HF branches: it is a plain Error, so
1271
+ // isHttpEmbeddingError() is false and the HF network heuristic must not claim it.
1272
+ if (isHttpEmbeddingDimsError(msg)) {
1273
+ cliError(` ${msg.replace(/\n/g, '\n ')}\n`, {
1274
+ recoveryHint: 'embedding-dims-invalid',
1275
+ });
1276
+ process.exitCode = 1;
1277
+ return;
1278
+ }
1279
+ // Custom HTTP embedding endpoint failure (#2385). When a `--embedding-base-url`
1280
+ // is configured, HTTP mode never downloads a model — so a failure talking to
1281
+ // that endpoint must NOT show the huggingface-download guidance. Keyed on the
1282
+ // error *type* (HttpEmbeddingError), not its message text, so it stays correct
1283
+ // regardless of locale or wording. Checked before the HF branch, whose network
1284
+ // heuristic (`fetch failed` / `ECONNREFUSED`) would otherwise also match a
1285
+ // wrapped endpoint-connection error. The header is deliberately neutral: this
1286
+ // type covers both never-reached failures (connection/timeout/DNS) and
1287
+ // reached-but-failed ones (4xx/5xx, dimension/shape mismatch), so it must not
1288
+ // assert "unreachable". The thrown `msg` carries the specific reason (and the
1289
+ // masked URL where one applies), so it is surfaced verbatim.
1290
+ if (isHttpEmbeddingError(err)) {
1291
+ cliError(` The custom embedding endpoint request failed.\n` +
1292
+ ` ${msg.replace(/\n/g, '\n ')}\n` +
1293
+ ` Suggestions:\n` +
1294
+ ` 1. Verify the endpoint URL is reachable and running ` +
1295
+ `(--embedding-base-url / GITNEXUS_EMBEDDING_URL: host, port, /v1 path).\n` +
1296
+ ` 2. Confirm the model name and embedding dimensions match what the endpoint serves.\n` +
1297
+ ` 3. Re-run without --embeddings to index without vectors.\n`, { recoveryHint: 'http-embedding-endpoint-error' });
1298
+ process.exitCode = 1;
1299
+ return;
1300
+ }
1301
+ // isHttpMode() is a pure presence probe (URL+MODEL) that never throws — a
1302
+ // malformed GITNEXUS_EMBEDDING_DIMS is handled by the dims branch above — so
1303
+ // no defensive try/catch is needed here (#2385).
1304
+ const inHttpMode = isHttpMode();
1206
1305
  // HF download failure — show clean guidance without the raw stack trace.
1207
1306
  // Checked before writeFatalToStderr so the user sees one focused message
1208
1307
  // rather than a stack-trace dump followed by a second remediation block.
1209
- if (isHfDownloadFailure(msg) || msg.includes('Failed to download embedding model')) {
1308
+ // Gated on !inHttpMode: with a custom endpoint configured no model download
1309
+ // is ever attempted, so a network error there is the endpoint's, handled by
1310
+ // the HttpEmbeddingError branch above — never HF's (#2385).
1311
+ if ((isHfDownloadFailure(msg) || msg.includes('Failed to download embedding model')) &&
1312
+ !inHttpMode) {
1210
1313
  cliError(` The embedding model could not be downloaded.\n` +
1211
1314
  ` huggingface.co may be unreachable from your network\n` +
1212
1315
  ` (e.g. behind a corporate proxy or a regional firewall).\n` +
@@ -12,7 +12,7 @@ import { type CliMessageKey, type CliMessageVars } from './i18n/index.js';
12
12
  * Consumers can import this type to narrow log-record `recoveryHint`
13
13
  * fields without restating the literal list.
14
14
  */
15
- export type RecoveryHint = 'wal-corruption' | 'wal-checkpoint-threshold' | 'heap-oom-respawn' | 'native-worker-abort' | 'hf-endpoint-unreachable' | 'local-embedding-unsupported' | 'large-repo' | 'npm-resolution' | 'module-not-found' | 'gitnexusrc-invalid' | 'default-branch-invalid';
15
+ export type RecoveryHint = 'wal-corruption' | 'wal-checkpoint-threshold' | 'heap-oom-respawn' | 'native-worker-abort' | 'hf-endpoint-unreachable' | 'http-embedding-endpoint-error' | 'embedding-dims-invalid' | 'local-embedding-unsupported' | 'local-embedding-stack-missing' | 'large-repo' | 'npm-resolution' | 'module-not-found' | 'gitnexusrc-invalid' | 'default-branch-invalid';
16
16
  /**
17
17
  * Common shape for the optional structured-field bag passed to
18
18
  * `cliError`/`cliWarn`/`cliInfo`. Typed so the `recoveryHint` slot is
@@ -1,3 +1,4 @@
1
+ import { type EmbeddingRuntimeResolution } from '../core/embeddings/runtime-install.js';
1
2
  export declare function displayWidth(value: string): number;
2
3
  export declare function padDisplayEnd(value: string, columns: number): string;
3
4
  /**
@@ -14,6 +15,10 @@ export declare function localEmbeddingDoctorStatus(opts: {
14
15
  httpMode: boolean;
15
16
  platform?: NodeJS.Platform;
16
17
  arch?: NodeJS.Architecture;
18
+ /** Injectable for tests; defaults to probing the real install. */
19
+ resolution?: EmbeddingRuntimeResolution | null;
20
+ /** Injectable for tests; defaults to this Node's registerHooks capability. */
21
+ prefixLoadable?: boolean;
17
22
  }): {
18
23
  status: string;
19
24
  detail: string | null;
@@ -1,9 +1,11 @@
1
1
  import { getRuntimeCapabilities, getRuntimeFingerprint } from '../core/platform/capabilities.js';
2
2
  import { resolveEmbeddingConfig } from '../core/embeddings/config.js';
3
3
  import { isHttpMode } from '../core/embeddings/http-client.js';
4
- import { getLocalEmbeddingRuntimeBlocker } from '../core/embeddings/runtime-support.js';
4
+ import { getLocalEmbeddingRuntimeBlocker, localEmbeddingPrefixUnloadableMessage, localEmbeddingStackMissingMessage, } from '../core/embeddings/runtime-support.js';
5
+ import { isPrefixRuntimeLoadable, resolveEmbeddingRuntime, } from '../core/embeddings/runtime-install.js';
5
6
  import { cudaRedirectDoctorStatus } from '../core/embeddings/onnxruntime-node-resolver.js';
6
- import { checkLbugNative } from '../core/lbug/native-check.js';
7
+ import { checkLbugNative, probeFtsExtensionLoad } from '../core/lbug/native-check.js';
8
+ import { diagnoseExtensionLoad } from '../core/lbug/extension-load-error.js';
7
9
  import { getExtensionInstallPolicy } from '../core/lbug/extension-loader.js';
8
10
  import { t } from './i18n/index.js';
9
11
  function isCombiningMark(codePoint) {
@@ -64,6 +66,25 @@ export function localEmbeddingDoctorStatus(opts) {
64
66
  if (blocker) {
65
67
  return { status: `✗ local embeddings unavailable on ${platform}/${arch}`, detail: blocker };
66
68
  }
69
+ // The stack is an optionalDependency — npm prunes it when onnxruntime-node's
70
+ // postinstall can't download its CUDA binaries (proxy/firewall, #2370).
71
+ const resolution = opts.resolution !== undefined ? opts.resolution : resolveEmbeddingRuntime();
72
+ if (resolution === null) {
73
+ return {
74
+ status: '✗ optional embedding stack not installed',
75
+ detail: localEmbeddingStackMissingMessage(),
76
+ };
77
+ }
78
+ // A prefix-sourced stack needs module.registerHooks to load; on Node < 22.15 /
79
+ // < 23.5 it is present but unreachable (#2372). Report loadability, not bare
80
+ // presence, so the diagnostic stops claiming a ✓ the loader can't honour.
81
+ const prefixLoadable = opts.prefixLoadable ?? isPrefixRuntimeLoadable();
82
+ if (resolution.source === 'runtime-prefix' && !prefixLoadable) {
83
+ return {
84
+ status: '✗ embedding stack installed in the prefix but not loadable on this Node',
85
+ detail: localEmbeddingPrefixUnloadableMessage(),
86
+ };
87
+ }
67
88
  return { status: '✓ local embeddings supported', detail: null };
68
89
  }
69
90
  export const doctorCommand = async () => {
@@ -88,7 +109,24 @@ export const doctorCommand = async () => {
88
109
  console.log('');
89
110
  console.log(t('doctor.capabilities'));
90
111
  console.log(` ${label('doctor.labels.graphStore', 18)}${capabilities.graph}`);
91
- console.log(` ${label('doctor.labels.fullTextSearch', 18)}${capabilities.fts}`);
112
+ // Live LOAD probe, not the static platform capability — the static value
113
+ // said "available" while analyze failed to load the extension (#2374).
114
+ const ftsProbe = nativeCheck.ok
115
+ ? await probeFtsExtensionLoad()
116
+ : { loaded: false, reason: 'LadybugDB native module (lbugjs.node) failed to load' };
117
+ console.log(` ${label('doctor.labels.fullTextSearch', 18)}${ftsProbe.loaded ? 'available' : 'unavailable'}`);
118
+ if (!ftsProbe.loaded && ftsProbe.reason) {
119
+ console.log(` ${padDisplayEnd('', 18)}${ftsProbe.reason}`);
120
+ // Add an actionable remedy for recognized failure classes (#2374). The
121
+ // Windows missing-dependency case is the point of this: the raw error 126
122
+ // ("specified module could not be found") is opaque, so name the fix (VC++
123
+ // redist, then OpenSSL) instead of leaving the user to reinstall in vain.
124
+ // `unknown`'s remedy is "run doctor", which would be circular here.
125
+ const { kind, remedy } = diagnoseExtensionLoad(ftsProbe.reason);
126
+ if (kind !== 'unknown') {
127
+ console.log(` ${padDisplayEnd('', 18)}${remedy}`);
128
+ }
129
+ }
92
130
  console.log(` ${label('doctor.labels.vectorIndex', 18)}${capabilities.vector}`);
93
131
  console.log(` ${label('doctor.labels.semanticMode', 18)}${capabilities.semanticMode}`);
94
132
  // Surface the optional-extension install policy so offline users can see
@@ -102,6 +102,17 @@ export function getEditorTargets(home = os.homedir()) {
102
102
  needle: 'gitnexus-hook',
103
103
  scriptDir: path.join(home, '.claude', 'hooks', 'gitnexus'),
104
104
  },
105
+ {
106
+ id: 'codex',
107
+ label: 'Codex',
108
+ // Codex hooks use Claude Code's exact {hooks: {Event: [...]}} JSON shape
109
+ // and hookSpecificOutput response contract, in a dedicated hooks.json
110
+ // (https://developers.openai.com/codex/hooks).
111
+ settingsFile: path.join(home, '.codex', 'hooks.json'),
112
+ events: ['PreToolUse', 'PostToolUse'],
113
+ needle: 'gitnexus-hook',
114
+ scriptDir: path.join(home, '.codex', 'hooks', 'gitnexus'),
115
+ },
105
116
  {
106
117
  id: 'antigravity',
107
118
  label: 'Antigravity',
@@ -0,0 +1,12 @@
1
+ export interface EmbeddingsInstallOptions {
2
+ cuda?: boolean;
3
+ force?: boolean;
4
+ }
5
+ /**
6
+ * `gitnexus embeddings install [--cuda] [--force]` — fetch the optional local
7
+ * embedding stack on demand (#2370). Goes through the user's npm registry
8
+ * config (mirrors/proxies apply); with --cuda it additionally runs
9
+ * onnxruntime-node's postinstall to download the CUDA GPU binaries from NuGet
10
+ * (set GLOBAL_AGENT_HTTPS_PROXY behind a proxy).
11
+ */
12
+ export declare const embeddingsInstallCommand: (options?: EmbeddingsInstallOptions) => Promise<void>;
@@ -0,0 +1,49 @@
1
+ import { cliError, cliInfo, cliWarn } from './cli-message.js';
2
+ import { getEmbeddingRuntimeDir, getEmbeddingStackSpecs, installEmbeddingRuntime, isPrefixRuntimeLoadable, resolveEmbeddingRuntime, } from '../core/embeddings/runtime-install.js';
3
+ import { localEmbeddingPrefixUnloadableMessage } from '../core/embeddings/runtime-support.js';
4
+ /**
5
+ * `gitnexus embeddings install [--cuda] [--force]` — fetch the optional local
6
+ * embedding stack on demand (#2370). Goes through the user's npm registry
7
+ * config (mirrors/proxies apply); with --cuda it additionally runs
8
+ * onnxruntime-node's postinstall to download the CUDA GPU binaries from NuGet
9
+ * (set GLOBAL_AGENT_HTTPS_PROXY behind a proxy).
10
+ */
11
+ export const embeddingsInstallCommand = async (options = {}) => {
12
+ const resolved = resolveEmbeddingRuntime();
13
+ if (resolved?.source === 'package' && !options.force) {
14
+ cliInfo('The embedding stack is already installed with gitnexus itself — nothing to do.\n' +
15
+ '(Use --force to install a copy into the runtime prefix anyway.)');
16
+ return;
17
+ }
18
+ const specs = Object.entries(getEmbeddingStackSpecs())
19
+ .map(([name, spec]) => `${name}@${spec}`)
20
+ .join(', ');
21
+ cliInfo(`Installing ${specs} into ${getEmbeddingRuntimeDir()} …`);
22
+ cliInfo(options.cuda
23
+ ? 'CUDA mode: onnxruntime-node will download GPU binaries from NuGet ' +
24
+ '(set GLOBAL_AGENT_HTTPS_PROXY=<proxy-url> behind a proxy).'
25
+ : 'CPU mode: install scripts are skipped — only your npm registry is contacted.');
26
+ try {
27
+ await installEmbeddingRuntime({ cuda: options.cuda, onOutput: (line) => cliInfo(` ${line}`) });
28
+ }
29
+ catch (err) {
30
+ cliError(`${err instanceof Error ? err.message : String(err)}\n`, {
31
+ recoveryHint: 'local-embedding-stack-missing',
32
+ });
33
+ process.exitCode = 1;
34
+ return;
35
+ }
36
+ const postInstall = resolveEmbeddingRuntime();
37
+ if (postInstall === null) {
38
+ cliInfo('✗ Install completed but the stack still does not resolve — check the output above.');
39
+ process.exitCode = 1;
40
+ return;
41
+ }
42
+ if (postInstall.source === 'runtime-prefix' && !isPrefixRuntimeLoadable()) {
43
+ // The packages are in the prefix, but this Node has no module.registerHooks
44
+ // to load them — don't claim readiness the loader can't honour.
45
+ cliWarn(`${localEmbeddingPrefixUnloadableMessage()}\n`);
46
+ return;
47
+ }
48
+ cliInfo('✓ Embedding runtime installed. `gitnexus analyze --embeddings` is ready.');
49
+ };
@@ -17,6 +17,8 @@ const COMMAND_DESCRIPTION_KEYS = {
17
17
  list: 'help.command.list.description',
18
18
  status: 'help.command.status.description',
19
19
  doctor: 'help.command.doctor.description',
20
+ embeddings: 'help.command.embeddings.description',
21
+ 'embeddings install': 'help.command.embeddings.install.description',
20
22
  clean: 'help.command.clean.description',
21
23
  remove: 'help.command.remove.description',
22
24
  wiki: 'help.command.wiki.description',
@@ -143,6 +145,8 @@ const OPTION_DESCRIPTION_KEYS = {
143
145
  'eval-server|-p, --port <port>': 'help.option.port',
144
146
  'eval-server|--host <host>': 'help.option.evalServer.host',
145
147
  'eval-server|--idle-timeout <seconds>': 'help.option.evalServer.idleTimeout',
148
+ 'embeddings install|--cuda': 'help.option.embeddings.install.cuda',
149
+ 'embeddings install|--force': 'help.option.embeddings.install.force',
146
150
  'group create|--force': 'help.option.group.create.force',
147
151
  'group sync|--skip-embeddings': 'help.option.group.sync.skipEmbeddings',
148
152
  'group sync|--exact-only': 'help.option.group.sync.exactOnly',
@@ -117,6 +117,8 @@ export declare const en: {
117
117
  readonly 'help.command.list.description': "List all indexed repositories";
118
118
  readonly 'help.command.status.description': "Show index status for current repo";
119
119
  readonly 'help.command.doctor.description': "Show runtime platform capabilities and embedding configuration";
120
+ readonly 'help.command.embeddings.description': "Manage the on-demand local embedding runtime";
121
+ readonly 'help.command.embeddings.install.description': "Install the local embedding stack (@huggingface/transformers + onnxruntime-node) on demand. Heals installs where npm skipped the optional packages (e.g. behind an HTTP proxy, #2370). Downloads only from your configured npm registry — mirrors and proxies apply.";
120
122
  readonly 'help.command.clean.description': "Delete GitNexus index for current repo";
121
123
  readonly 'help.command.remove.description': "Delete the GitNexus index for a registered repo (by alias, name, or absolute path). Unlike `clean`, does not require being inside the repo. Idempotent on unknown targets.";
122
124
  readonly 'help.command.wiki.description': "Generate repository wiki from knowledge graph";
@@ -220,6 +222,8 @@ export declare const en: {
220
222
  readonly 'help.option.check.cycles': "Detect circular imports and fail when any are found";
221
223
  readonly 'help.option.evalServer.host': "Bind address (default: 127.0.0.1, use 0.0.0.0 to expose to all interfaces)";
222
224
  readonly 'help.option.evalServer.idleTimeout': "Auto-shutdown after N seconds idle (0 = disabled)";
225
+ readonly 'help.option.embeddings.install.cuda': "Also download the CUDA GPU binaries (runs onnxruntime-node's NuGet postinstall; set GLOBAL_AGENT_HTTPS_PROXY behind a proxy)";
226
+ readonly 'help.option.embeddings.install.force': "Install into the runtime prefix even when the stack already resolves";
223
227
  readonly 'help.option.group.create.force': "Overwrite existing group";
224
228
  readonly 'help.option.group.sync.skipEmbeddings': "Exact + BM25 only (no embedding fallback)";
225
229
  readonly 'help.option.group.sync.exactOnly': "Exact match only";
@@ -117,6 +117,8 @@ export const en = {
117
117
  'help.command.list.description': 'List all indexed repositories',
118
118
  'help.command.status.description': 'Show index status for current repo',
119
119
  'help.command.doctor.description': 'Show runtime platform capabilities and embedding configuration',
120
+ 'help.command.embeddings.description': 'Manage the on-demand local embedding runtime',
121
+ 'help.command.embeddings.install.description': 'Install the local embedding stack (@huggingface/transformers + onnxruntime-node) on demand. Heals installs where npm skipped the optional packages (e.g. behind an HTTP proxy, #2370). Downloads only from your configured npm registry — mirrors and proxies apply.',
120
122
  'help.command.clean.description': 'Delete GitNexus index for current repo',
121
123
  'help.command.remove.description': 'Delete the GitNexus index for a registered repo (by alias, name, or absolute path). Unlike `clean`, does not require being inside the repo. Idempotent on unknown targets.',
122
124
  'help.command.wiki.description': 'Generate repository wiki from knowledge graph',
@@ -220,6 +222,8 @@ export const en = {
220
222
  'help.option.check.cycles': 'Detect circular imports and fail when any are found',
221
223
  'help.option.evalServer.host': 'Bind address (default: 127.0.0.1, use 0.0.0.0 to expose to all interfaces)',
222
224
  'help.option.evalServer.idleTimeout': 'Auto-shutdown after N seconds idle (0 = disabled)',
225
+ 'help.option.embeddings.install.cuda': "Also download the CUDA GPU binaries (runs onnxruntime-node's NuGet postinstall; set GLOBAL_AGENT_HTTPS_PROXY behind a proxy)",
226
+ 'help.option.embeddings.install.force': 'Install into the runtime prefix even when the stack already resolves',
223
227
  'help.option.group.create.force': 'Overwrite existing group',
224
228
  'help.option.group.sync.skipEmbeddings': 'Exact + BM25 only (no embedding fallback)',
225
229
  'help.option.group.sync.exactOnly': 'Exact match only',
@@ -118,6 +118,8 @@ export declare const cliResources: {
118
118
  readonly 'help.command.list.description': "List all indexed repositories";
119
119
  readonly 'help.command.status.description': "Show index status for current repo";
120
120
  readonly 'help.command.doctor.description': "Show runtime platform capabilities and embedding configuration";
121
+ readonly 'help.command.embeddings.description': "Manage the on-demand local embedding runtime";
122
+ readonly 'help.command.embeddings.install.description': "Install the local embedding stack (@huggingface/transformers + onnxruntime-node) on demand. Heals installs where npm skipped the optional packages (e.g. behind an HTTP proxy, #2370). Downloads only from your configured npm registry — mirrors and proxies apply.";
121
123
  readonly 'help.command.clean.description': "Delete GitNexus index for current repo";
122
124
  readonly 'help.command.remove.description': "Delete the GitNexus index for a registered repo (by alias, name, or absolute path). Unlike `clean`, does not require being inside the repo. Idempotent on unknown targets.";
123
125
  readonly 'help.command.wiki.description': "Generate repository wiki from knowledge graph";
@@ -221,6 +223,8 @@ export declare const cliResources: {
221
223
  readonly 'help.option.check.cycles': "Detect circular imports and fail when any are found";
222
224
  readonly 'help.option.evalServer.host': "Bind address (default: 127.0.0.1, use 0.0.0.0 to expose to all interfaces)";
223
225
  readonly 'help.option.evalServer.idleTimeout': "Auto-shutdown after N seconds idle (0 = disabled)";
226
+ readonly 'help.option.embeddings.install.cuda': "Also download the CUDA GPU binaries (runs onnxruntime-node's NuGet postinstall; set GLOBAL_AGENT_HTTPS_PROXY behind a proxy)";
227
+ readonly 'help.option.embeddings.install.force': "Install into the runtime prefix even when the stack already resolves";
224
228
  readonly 'help.option.group.create.force': "Overwrite existing group";
225
229
  readonly 'help.option.group.sync.skipEmbeddings': "Exact + BM25 only (no embedding fallback)";
226
230
  readonly 'help.option.group.sync.exactOnly': "Exact match only";
@@ -360,6 +364,8 @@ export declare const cliResources: {
360
364
  'help.command.list.description': string;
361
365
  'help.command.status.description': string;
362
366
  'help.command.doctor.description': string;
367
+ 'help.command.embeddings.description': string;
368
+ 'help.command.embeddings.install.description': string;
363
369
  'help.command.clean.description': string;
364
370
  'help.command.remove.description': string;
365
371
  'help.command.wiki.description': string;
@@ -463,6 +469,8 @@ export declare const cliResources: {
463
469
  'help.option.check.cycles': string;
464
470
  'help.option.evalServer.host': string;
465
471
  'help.option.evalServer.idleTimeout': string;
472
+ 'help.option.embeddings.install.cuda': string;
473
+ 'help.option.embeddings.install.force': string;
466
474
  'help.option.group.create.force': string;
467
475
  'help.option.group.sync.skipEmbeddings': string;
468
476
  'help.option.group.sync.exactOnly': string;
@@ -117,6 +117,8 @@ export declare const zhCN: {
117
117
  'help.command.list.description': string;
118
118
  'help.command.status.description': string;
119
119
  'help.command.doctor.description': string;
120
+ 'help.command.embeddings.description': string;
121
+ 'help.command.embeddings.install.description': string;
120
122
  'help.command.clean.description': string;
121
123
  'help.command.remove.description': string;
122
124
  'help.command.wiki.description': string;
@@ -220,6 +222,8 @@ export declare const zhCN: {
220
222
  'help.option.check.cycles': string;
221
223
  'help.option.evalServer.host': string;
222
224
  'help.option.evalServer.idleTimeout': string;
225
+ 'help.option.embeddings.install.cuda': string;
226
+ 'help.option.embeddings.install.force': string;
223
227
  'help.option.group.create.force': string;
224
228
  'help.option.group.sync.skipEmbeddings': string;
225
229
  'help.option.group.sync.exactOnly': string;
@@ -117,6 +117,8 @@ export const zhCN = {
117
117
  'help.command.list.description': '列出所有已索引仓库',
118
118
  'help.command.status.description': '显示当前仓库的索引状态',
119
119
  'help.command.doctor.description': '显示运行平台能力和嵌入配置',
120
+ 'help.command.embeddings.description': '管理按需安装的本地嵌入运行时',
121
+ 'help.command.embeddings.install.description': '按需安装本地嵌入组件(@huggingface/transformers + onnxruntime-node)。修复 npm 跳过可选包的安装(例如在 HTTP 代理后,#2370)。仅从你配置的 npm registry 下载 — 镜像和代理均生效。',
120
122
  'help.command.clean.description': '删除当前仓库的 GitNexus 索引',
121
123
  'help.command.remove.description': '删除已注册仓库的 GitNexus 索引(按别名、名称或绝对路径)。与 `clean` 不同,不要求位于仓库内;未知目标会幂等处理。',
122
124
  'help.command.wiki.description': '从知识图谱生成仓库 Wiki',
@@ -220,6 +222,8 @@ export const zhCN = {
220
222
  'help.option.check.cycles': '检测循环导入,并在发现循环时失败',
221
223
  'help.option.evalServer.host': '绑定地址(默认:127.0.0.1;用 0.0.0.0 暴露到所有网卡)',
222
224
  'help.option.evalServer.idleTimeout': '空闲 N 秒后自动关闭(0 = 禁用)',
225
+ 'help.option.embeddings.install.cuda': '同时下载 CUDA GPU 二进制文件(运行 onnxruntime-node 的 NuGet postinstall;代理后请设置 GLOBAL_AGENT_HTTPS_PROXY)',
226
+ 'help.option.embeddings.install.force': '即使嵌入组件已可解析,也强制安装到运行时目录',
223
227
  'help.option.group.create.force': '覆盖现有仓库组',
224
228
  'help.option.group.sync.skipEmbeddings': '仅使用 exact + BM25(不使用嵌入回退)',
225
229
  'help.option.group.sync.exactOnly': '仅精确匹配',