gitnexus 1.6.4-rc.11 → 1.6.4-rc.111

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 (411) hide show
  1. package/README.md +35 -0
  2. package/dist/_shared/index.d.ts +8 -0
  3. package/dist/_shared/index.d.ts.map +1 -1
  4. package/dist/_shared/index.js +9 -0
  5. package/dist/_shared/index.js.map +1 -1
  6. package/dist/_shared/integrations/circuit-breaker.d.ts +183 -0
  7. package/dist/_shared/integrations/circuit-breaker.d.ts.map +1 -0
  8. package/dist/_shared/integrations/circuit-breaker.js +236 -0
  9. package/dist/_shared/integrations/circuit-breaker.js.map +1 -0
  10. package/dist/_shared/integrations/resilient-fetch.d.ts +99 -0
  11. package/dist/_shared/integrations/resilient-fetch.d.ts.map +1 -0
  12. package/dist/_shared/integrations/resilient-fetch.js +204 -0
  13. package/dist/_shared/integrations/resilient-fetch.js.map +1 -0
  14. package/dist/_shared/integrations/retry.d.ts +60 -0
  15. package/dist/_shared/integrations/retry.d.ts.map +1 -0
  16. package/dist/_shared/integrations/retry.js +67 -0
  17. package/dist/_shared/integrations/retry.js.map +1 -0
  18. package/dist/_shared/integrations/understand-quickly.d.ts +79 -0
  19. package/dist/_shared/integrations/understand-quickly.d.ts.map +1 -0
  20. package/dist/_shared/integrations/understand-quickly.js +139 -0
  21. package/dist/_shared/integrations/understand-quickly.js.map +1 -0
  22. package/dist/_shared/scope-resolution/finalize-algorithm.d.ts +11 -9
  23. package/dist/_shared/scope-resolution/finalize-algorithm.d.ts.map +1 -1
  24. package/dist/_shared/scope-resolution/finalize-algorithm.js +91 -36
  25. package/dist/_shared/scope-resolution/finalize-algorithm.js.map +1 -1
  26. package/dist/_shared/test-helpers.d.ts +13 -0
  27. package/dist/_shared/test-helpers.d.ts.map +1 -0
  28. package/dist/_shared/test-helpers.js +13 -0
  29. package/dist/_shared/test-helpers.js.map +1 -0
  30. package/dist/cli/ai-context.js +2 -1
  31. package/dist/cli/analyze.d.ts +14 -1
  32. package/dist/cli/analyze.js +223 -40
  33. package/dist/cli/clean.js +4 -3
  34. package/dist/cli/cli-message.d.ts +15 -0
  35. package/dist/cli/cli-message.js +61 -0
  36. package/dist/cli/doctor.d.ts +1 -0
  37. package/dist/cli/doctor.js +31 -0
  38. package/dist/cli/eval-server.js +37 -12
  39. package/dist/cli/group.js +4 -3
  40. package/dist/cli/index-repo.js +2 -2
  41. package/dist/cli/index.js +25 -2
  42. package/dist/cli/mcp.d.ts +21 -0
  43. package/dist/cli/mcp.js +52 -15
  44. package/dist/cli/optional-grammars.d.ts +47 -0
  45. package/dist/cli/optional-grammars.js +87 -0
  46. package/dist/cli/publish.d.ts +29 -0
  47. package/dist/cli/publish.js +174 -0
  48. package/dist/cli/remove.js +7 -4
  49. package/dist/cli/serve.js +31 -13
  50. package/dist/cli/setup.js +46 -16
  51. package/dist/cli/tool.js +6 -5
  52. package/dist/cli/wiki.js +39 -6
  53. package/dist/config/ignore-service.js +4 -1
  54. package/dist/core/augmentation/engine.js +1 -1
  55. package/dist/core/embedding-mode.d.ts +21 -0
  56. package/dist/core/embedding-mode.js +18 -0
  57. package/dist/core/embeddings/config.d.ts +2 -0
  58. package/dist/core/embeddings/config.js +36 -0
  59. package/dist/core/embeddings/embedder.js +55 -27
  60. package/dist/core/embeddings/embedding-pipeline.d.ts +7 -1
  61. package/dist/core/embeddings/embedding-pipeline.js +106 -40
  62. package/dist/core/embeddings/exact-search.d.ts +15 -0
  63. package/dist/core/embeddings/exact-search.js +27 -0
  64. package/dist/core/embeddings/hf-env.d.ts +135 -0
  65. package/dist/core/embeddings/hf-env.js +232 -0
  66. package/dist/core/embeddings/http-client.d.ts +6 -0
  67. package/dist/core/embeddings/http-client.js +22 -18
  68. package/dist/core/embeddings/types.d.ts +4 -0
  69. package/dist/core/embeddings/types.js +2 -0
  70. package/dist/core/git-staleness.d.ts +6 -0
  71. package/dist/core/git-staleness.js +35 -5
  72. package/dist/core/group/bridge-db.js +319 -170
  73. package/dist/core/group/config-parser.js +23 -1
  74. package/dist/core/group/cross-impact.d.ts +44 -0
  75. package/dist/core/group/cross-impact.js +82 -8
  76. package/dist/core/group/extractors/elixir-workspace-extractor.d.ts +15 -0
  77. package/dist/core/group/extractors/elixir-workspace-extractor.js +204 -0
  78. package/dist/core/group/extractors/go-workspace-extractor.d.ts +14 -0
  79. package/dist/core/group/extractors/go-workspace-extractor.js +217 -0
  80. package/dist/core/group/extractors/grpc-extractor.js +15 -3
  81. package/dist/core/group/extractors/http-route-extractor.js +9 -1
  82. package/dist/core/group/extractors/include-extractor.d.ts +39 -0
  83. package/dist/core/group/extractors/include-extractor.js +565 -0
  84. package/dist/core/group/extractors/java-workspace-extractor.d.ts +16 -0
  85. package/dist/core/group/extractors/java-workspace-extractor.js +204 -0
  86. package/dist/core/group/extractors/manifest-extractor.js +34 -6
  87. package/dist/core/group/extractors/node-workspace-extractor.d.ts +14 -0
  88. package/dist/core/group/extractors/node-workspace-extractor.js +207 -0
  89. package/dist/core/group/extractors/python-workspace-extractor.d.ts +15 -0
  90. package/dist/core/group/extractors/python-workspace-extractor.js +205 -0
  91. package/dist/core/group/extractors/rust-workspace-extractor.d.ts +44 -0
  92. package/dist/core/group/extractors/rust-workspace-extractor.js +240 -0
  93. package/dist/core/group/extractors/thrift-extractor.d.ts +22 -0
  94. package/dist/core/group/extractors/thrift-extractor.js +282 -0
  95. package/dist/core/group/extractors/thrift-patterns/index.d.ts +4 -0
  96. package/dist/core/group/extractors/thrift-patterns/index.js +10 -0
  97. package/dist/core/group/extractors/thrift-patterns/java.d.ts +2 -0
  98. package/dist/core/group/extractors/thrift-patterns/java.js +220 -0
  99. package/dist/core/group/extractors/thrift-patterns/types.d.ts +17 -0
  100. package/dist/core/group/extractors/thrift-patterns/types.js +1 -0
  101. package/dist/core/group/extractors/topic-extractor.js +14 -14
  102. package/dist/core/group/extractors/workspace-extractor.d.ts +13 -0
  103. package/dist/core/group/extractors/workspace-extractor.js +65 -0
  104. package/dist/core/group/matching.d.ts +3 -3
  105. package/dist/core/group/matching.js +136 -50
  106. package/dist/core/group/service.d.ts +1 -0
  107. package/dist/core/group/service.js +5 -4
  108. package/dist/core/group/storage.js +70 -4
  109. package/dist/core/group/sync.js +85 -14
  110. package/dist/core/group/types.d.ts +22 -1
  111. package/dist/core/ingestion/ast-cache.js +2 -1
  112. package/dist/core/ingestion/call-processor.d.ts +3 -3
  113. package/dist/core/ingestion/call-processor.js +65 -69
  114. package/dist/core/ingestion/cluster-enricher.js +3 -2
  115. package/dist/core/ingestion/cobol/cobol-copy-expander.js +4 -20
  116. package/dist/core/ingestion/cobol/cobol-preprocessor.d.ts +2 -0
  117. package/dist/core/ingestion/cobol/cobol-preprocessor.js +14 -2
  118. package/dist/core/ingestion/cpp-ue-preprocessor.d.ts +12 -0
  119. package/dist/core/ingestion/cpp-ue-preprocessor.js +260 -0
  120. package/dist/core/ingestion/entry-point-scoring.d.ts +0 -18
  121. package/dist/core/ingestion/entry-point-scoring.js +7 -188
  122. package/dist/core/ingestion/field-extractors/configs/csharp.js +8 -3
  123. package/dist/core/ingestion/filesystem-walker.js +3 -2
  124. package/dist/core/ingestion/framework-detection.d.ts +0 -120
  125. package/dist/core/ingestion/framework-detection.js +7 -365
  126. package/dist/core/ingestion/heritage-processor.js +12 -6
  127. package/dist/core/ingestion/import-processor.js +17 -14
  128. package/dist/core/ingestion/language-config.js +6 -5
  129. package/dist/core/ingestion/language-provider.d.ts +55 -0
  130. package/dist/core/ingestion/languages/c-cpp.js +72 -0
  131. package/dist/core/ingestion/languages/cobol.js +2 -0
  132. package/dist/core/ingestion/languages/csharp/captures.js +93 -0
  133. package/dist/core/ingestion/languages/csharp/query.js +6 -0
  134. package/dist/core/ingestion/languages/csharp.js +49 -0
  135. package/dist/core/ingestion/languages/dart.js +36 -0
  136. package/dist/core/ingestion/languages/go/arity-metadata.d.ts +8 -0
  137. package/dist/core/ingestion/languages/go/arity-metadata.js +37 -0
  138. package/dist/core/ingestion/languages/go/arity.d.ts +2 -0
  139. package/dist/core/ingestion/languages/go/arity.js +14 -0
  140. package/dist/core/ingestion/languages/go/cache-stats.d.ts +7 -0
  141. package/dist/core/ingestion/languages/go/cache-stats.js +15 -0
  142. package/dist/core/ingestion/languages/go/captures.d.ts +2 -0
  143. package/dist/core/ingestion/languages/go/captures.js +128 -0
  144. package/dist/core/ingestion/languages/go/expand-wildcards.d.ts +15 -0
  145. package/dist/core/ingestion/languages/go/expand-wildcards.js +93 -0
  146. package/dist/core/ingestion/languages/go/import-decomposer.d.ts +3 -0
  147. package/dist/core/ingestion/languages/go/import-decomposer.js +44 -0
  148. package/dist/core/ingestion/languages/go/import-target.d.ts +21 -0
  149. package/dist/core/ingestion/languages/go/import-target.js +67 -0
  150. package/dist/core/ingestion/languages/go/index.d.ts +17 -0
  151. package/dist/core/ingestion/languages/go/index.js +17 -0
  152. package/dist/core/ingestion/languages/go/interface-impls.d.ts +4 -0
  153. package/dist/core/ingestion/languages/go/interface-impls.js +72 -0
  154. package/dist/core/ingestion/languages/go/interpret.d.ts +11 -0
  155. package/dist/core/ingestion/languages/go/interpret.js +146 -0
  156. package/dist/core/ingestion/languages/go/merge-bindings.d.ts +2 -0
  157. package/dist/core/ingestion/languages/go/merge-bindings.js +18 -0
  158. package/dist/core/ingestion/languages/go/method-owners.d.ts +17 -0
  159. package/dist/core/ingestion/languages/go/method-owners.js +96 -0
  160. package/dist/core/ingestion/languages/go/namespace-mirror.d.ts +15 -0
  161. package/dist/core/ingestion/languages/go/namespace-mirror.js +53 -0
  162. package/dist/core/ingestion/languages/go/package-siblings.d.ts +11 -0
  163. package/dist/core/ingestion/languages/go/package-siblings.js +84 -0
  164. package/dist/core/ingestion/languages/go/query.d.ts +3 -0
  165. package/dist/core/ingestion/languages/go/query.js +207 -0
  166. package/dist/core/ingestion/languages/go/range-binding.d.ts +8 -0
  167. package/dist/core/ingestion/languages/go/range-binding.js +108 -0
  168. package/dist/core/ingestion/languages/go/receiver-binding.d.ts +3 -0
  169. package/dist/core/ingestion/languages/go/receiver-binding.js +21 -0
  170. package/dist/core/ingestion/languages/go/scope-resolver.d.ts +2 -0
  171. package/dist/core/ingestion/languages/go/scope-resolver.js +33 -0
  172. package/dist/core/ingestion/languages/go/simple-hooks.d.ts +4 -0
  173. package/dist/core/ingestion/languages/go/simple-hooks.js +21 -0
  174. package/dist/core/ingestion/languages/go/type-binding.d.ts +3 -0
  175. package/dist/core/ingestion/languages/go/type-binding.js +237 -0
  176. package/dist/core/ingestion/languages/go.js +50 -0
  177. package/dist/core/ingestion/languages/java.js +21 -0
  178. package/dist/core/ingestion/languages/kotlin.js +41 -0
  179. package/dist/core/ingestion/languages/php.js +35 -0
  180. package/dist/core/ingestion/languages/python/captures.js +19 -4
  181. package/dist/core/ingestion/languages/python/import-target.js +121 -25
  182. package/dist/core/ingestion/languages/python.js +41 -0
  183. package/dist/core/ingestion/languages/ruby.js +25 -0
  184. package/dist/core/ingestion/languages/rust.js +35 -0
  185. package/dist/core/ingestion/languages/swift.js +68 -0
  186. package/dist/core/ingestion/languages/typescript/captures.js +22 -0
  187. package/dist/core/ingestion/languages/typescript/query.d.ts +7 -0
  188. package/dist/core/ingestion/languages/typescript/query.js +205 -5
  189. package/dist/core/ingestion/languages/typescript.js +132 -11
  190. package/dist/core/ingestion/languages/vue.js +2 -0
  191. package/dist/core/ingestion/method-extractors/configs/swift.js +3 -4
  192. package/dist/core/ingestion/method-extractors/generic.js +2 -1
  193. package/dist/core/ingestion/model/resolve.js +31 -11
  194. package/dist/core/ingestion/parsing-processor.js +27 -11
  195. package/dist/core/ingestion/pipeline-phases/cobol.js +4 -3
  196. package/dist/core/ingestion/pipeline-phases/communities.js +2 -1
  197. package/dist/core/ingestion/pipeline-phases/cross-file-impl.js +5 -4
  198. package/dist/core/ingestion/pipeline-phases/cross-file.js +3 -2
  199. package/dist/core/ingestion/pipeline-phases/markdown.js +2 -1
  200. package/dist/core/ingestion/pipeline-phases/mro.js +2 -1
  201. package/dist/core/ingestion/pipeline-phases/orm.js +2 -1
  202. package/dist/core/ingestion/pipeline-phases/parse-impl.js +9 -8
  203. package/dist/core/ingestion/pipeline-phases/processes.js +12 -6
  204. package/dist/core/ingestion/pipeline-phases/routes.js +4 -3
  205. package/dist/core/ingestion/pipeline-phases/runner.js +3 -2
  206. package/dist/core/ingestion/pipeline-phases/tools.d.ts +1 -0
  207. package/dist/core/ingestion/pipeline-phases/tools.js +12 -5
  208. package/dist/core/ingestion/process-processor.js +4 -3
  209. package/dist/core/ingestion/registry-primary-flag.js +1 -0
  210. package/dist/core/ingestion/scope-extractor-bridge.js +2 -2
  211. package/dist/core/ingestion/scope-extractor.js +18 -5
  212. package/dist/core/ingestion/scope-resolution/contract/scope-resolver.d.ts +60 -1
  213. package/dist/core/ingestion/scope-resolution/graph-bridge/ids.js +33 -3
  214. package/dist/core/ingestion/scope-resolution/passes/free-call-fallback.d.ts +3 -1
  215. package/dist/core/ingestion/scope-resolution/passes/free-call-fallback.js +49 -1
  216. package/dist/core/ingestion/scope-resolution/passes/imported-return-types.d.ts +7 -1
  217. package/dist/core/ingestion/scope-resolution/passes/imported-return-types.js +1 -1
  218. package/dist/core/ingestion/scope-resolution/passes/mro.js +2 -1
  219. package/dist/core/ingestion/scope-resolution/passes/receiver-bound-calls.js +48 -25
  220. package/dist/core/ingestion/scope-resolution/pipeline/phase.js +3 -2
  221. package/dist/core/ingestion/scope-resolution/pipeline/registry.js +2 -0
  222. package/dist/core/ingestion/scope-resolution/pipeline/run.js +27 -6
  223. package/dist/core/ingestion/scope-resolution/scope/namespace-targets.d.ts +1 -1
  224. package/dist/core/ingestion/scope-resolution/scope/namespace-targets.js +7 -1
  225. package/dist/core/ingestion/scope-resolution/scope/walkers.js +23 -0
  226. package/dist/core/ingestion/tree-sitter-queries.d.ts +2 -2
  227. package/dist/core/ingestion/tree-sitter-queries.js +149 -0
  228. package/dist/core/ingestion/type-env.js +2 -1
  229. package/dist/core/ingestion/type-extractors/swift.js +7 -4
  230. package/dist/core/ingestion/utils/ast-helpers.d.ts +12 -1
  231. package/dist/core/ingestion/utils/ast-helpers.js +15 -1
  232. package/dist/core/ingestion/utils/max-file-size.js +2 -1
  233. package/dist/core/ingestion/vue-sfc-extractor.js +18 -1
  234. package/dist/core/ingestion/workers/parse-worker.d.ts +1 -0
  235. package/dist/core/ingestion/workers/parse-worker.js +21 -10
  236. package/dist/core/ingestion/workers/worker-pool.d.ts +11 -4
  237. package/dist/core/ingestion/workers/worker-pool.js +303 -49
  238. package/dist/core/lbug/csv-generator.js +5 -1
  239. package/dist/core/lbug/extension-loader.d.ts +86 -0
  240. package/dist/core/lbug/extension-loader.js +186 -0
  241. package/dist/core/lbug/lbug-adapter.d.ts +54 -17
  242. package/dist/core/lbug/lbug-adapter.js +202 -158
  243. package/dist/core/lbug/lbug-config.d.ts +102 -0
  244. package/dist/core/lbug/lbug-config.js +303 -0
  245. package/dist/core/lbug/pool-adapter.d.ts +1 -4
  246. package/dist/core/lbug/pool-adapter.js +82 -39
  247. package/dist/core/lbug/schema.d.ts +1 -1
  248. package/dist/core/lbug/schema.js +12 -1
  249. package/dist/core/logger.d.ts +125 -0
  250. package/dist/core/logger.js +323 -0
  251. package/dist/core/platform/capabilities.d.ts +24 -0
  252. package/dist/core/platform/capabilities.js +54 -0
  253. package/dist/core/run-analyze.d.ts +8 -1
  254. package/dist/core/run-analyze.js +71 -16
  255. package/dist/core/search/bm25-index.d.ts +6 -1
  256. package/dist/core/search/bm25-index.js +27 -10
  257. package/dist/core/search/hybrid-search.d.ts +4 -3
  258. package/dist/core/search/hybrid-search.js +6 -5
  259. package/dist/core/tree-sitter/parser-loader.d.ts +2 -2
  260. package/dist/core/tree-sitter/parser-loader.js +173 -68
  261. package/dist/core/wiki/cursor-client.js +2 -1
  262. package/dist/core/wiki/llm-client.d.ts +16 -0
  263. package/dist/core/wiki/llm-client.js +107 -74
  264. package/dist/mcp/compatible-stdio-transport.js +7 -1
  265. package/dist/mcp/core/embedder.js +37 -16
  266. package/dist/mcp/core/lbug-adapter.d.ts +7 -1
  267. package/dist/mcp/core/lbug-adapter.js +7 -1
  268. package/dist/mcp/local/local-backend.d.ts +9 -0
  269. package/dist/mcp/local/local-backend.js +199 -45
  270. package/dist/mcp/server.js +26 -8
  271. package/dist/mcp/stdio-capture.d.ts +40 -0
  272. package/dist/mcp/stdio-capture.js +53 -0
  273. package/dist/mcp/stdio-context.d.ts +47 -0
  274. package/dist/mcp/stdio-context.js +145 -0
  275. package/dist/mcp/tools.d.ts +2 -0
  276. package/dist/mcp/tools.js +33 -0
  277. package/dist/server/api.d.ts +20 -0
  278. package/dist/server/api.js +222 -86
  279. package/dist/server/git-clone.d.ts +75 -2
  280. package/dist/server/git-clone.js +229 -13
  281. package/dist/server/mcp-http.js +2 -1
  282. package/dist/server/validation.d.ts +98 -0
  283. package/dist/server/validation.js +142 -0
  284. package/dist/storage/git.d.ts +57 -0
  285. package/dist/storage/git.js +124 -2
  286. package/dist/storage/repo-manager.d.ts +40 -2
  287. package/dist/storage/repo-manager.js +121 -13
  288. package/hooks/claude/gitnexus-hook.cjs +62 -3
  289. package/package.json +13 -10
  290. package/scripts/build-tree-sitter-dart.cjs +53 -0
  291. package/scripts/build-tree-sitter-proto.cjs +12 -1
  292. package/scripts/install-duckdb-extension.mjs +48 -0
  293. package/vendor/node_modules/node-addon-api/node_addon_api.target.mk +16 -14
  294. package/vendor/node_modules/node-addon-api/node_addon_api_except.target.mk +16 -14
  295. package/vendor/node_modules/node-addon-api/node_addon_api_except_all.target.mk +16 -14
  296. package/vendor/node_modules/node-addon-api/node_addon_api_maybe.target.mk +16 -14
  297. package/vendor/tree-sitter-dart/README.md +18 -0
  298. package/vendor/tree-sitter-dart/binding.gyp +31 -0
  299. package/vendor/tree-sitter-dart/bindings/node/binding.cc +20 -0
  300. package/vendor/tree-sitter-dart/bindings/node/index.d.ts +28 -0
  301. package/vendor/tree-sitter-dart/bindings/node/index.js +7 -0
  302. package/vendor/tree-sitter-dart/grammar.js +2895 -0
  303. package/vendor/tree-sitter-dart/package.json +18 -0
  304. package/vendor/tree-sitter-dart/queries/highlights.scm +246 -0
  305. package/vendor/tree-sitter-dart/queries/tags.scm +92 -0
  306. package/vendor/tree-sitter-dart/queries/test.scm +1 -0
  307. package/vendor/tree-sitter-dart/src/grammar.json +12459 -0
  308. package/vendor/tree-sitter-dart/src/node-types.json +15055 -0
  309. package/vendor/tree-sitter-dart/src/parser.c +196127 -0
  310. package/vendor/tree-sitter-dart/src/scanner.c +130 -0
  311. package/vendor/tree-sitter-dart/src/tree_sitter/alloc.h +54 -0
  312. package/vendor/tree-sitter-dart/src/tree_sitter/array.h +290 -0
  313. package/vendor/tree-sitter-dart/src/tree_sitter/parser.h +265 -0
  314. package/vendor/tree-sitter-swift/LICENSE +21 -0
  315. package/vendor/tree-sitter-swift/README.md +139 -0
  316. package/vendor/tree-sitter-swift/bindings/node/index.d.ts +28 -0
  317. package/vendor/tree-sitter-swift/bindings/node/index.js +7 -0
  318. package/vendor/tree-sitter-swift/package.json +28 -0
  319. package/vendor/tree-sitter-swift/prebuilds/darwin-arm64/tree-sitter-swift.node +0 -0
  320. package/vendor/tree-sitter-swift/prebuilds/darwin-x64/tree-sitter-swift.node +0 -0
  321. package/vendor/tree-sitter-swift/prebuilds/linux-arm64/tree-sitter-swift.node +0 -0
  322. package/vendor/tree-sitter-swift/prebuilds/linux-x64/tree-sitter-swift.node +0 -0
  323. package/vendor/tree-sitter-swift/prebuilds/win32-arm64/tree-sitter-swift.node +0 -0
  324. package/vendor/tree-sitter-swift/prebuilds/win32-x64/tree-sitter-swift.node +0 -0
  325. package/vendor/tree-sitter-swift/src/node-types.json +30694 -0
  326. package/web/assets/agent-BpHQleHE.js +597 -0
  327. package/web/assets/architecture-YZFGNWBL-S5CXDPWN-BUzkWgDl.js +1 -0
  328. package/web/assets/{architectureDiagram-EMZXCZ2Q-Domyk_gO.js → architectureDiagram-EMZXCZ2Q-CXbzok1G.js} +3 -3
  329. package/web/assets/{blockDiagram-IGV67L2C-B_2kD7tM.js → blockDiagram-IGV67L2C-DA1QJ4ZB.js} +4 -4
  330. package/web/assets/{c4Diagram-DFAF54RM-BhJJW8Gg.js → c4Diagram-DFAF54RM-DeJV1rCn.js} +2 -2
  331. package/web/assets/{chunk-3GS5O3IE-jlWIjPsl.js → chunk-3GS5O3IE-B8hpnia8.js} +2 -2
  332. package/web/assets/{chunk-3YCYZ6SJ-Blq_IzZs.js → chunk-3YCYZ6SJ-B-BVu21C.js} +1 -1
  333. package/web/assets/{chunk-6NTNNK5N-DyPc58pp.js → chunk-6NTNNK5N-DW-jYSDr.js} +1 -1
  334. package/web/assets/{chunk-A34GCYZU-BI2i_LdU.js → chunk-A34GCYZU-BbZl-IKy.js} +1 -1
  335. package/web/assets/{chunk-DJ7UZH7F-i11ywiBl.js → chunk-DJ7UZH7F-B5tMfF87.js} +1 -1
  336. package/web/assets/{chunk-DKKBVRCY-1SffGI1N.js → chunk-DKKBVRCY-Djm-6K_e.js} +2 -2
  337. package/web/assets/{chunk-DU5LTGQ6-DaPeiwD5.js → chunk-DU5LTGQ6-QPoynYcp.js} +1 -1
  338. package/web/assets/{chunk-FXACKDTF-uhhi2PC2.js → chunk-FXACKDTF-jieSmbe2.js} +3 -3
  339. package/web/assets/chunk-H3VCZNTA-8EMHZ3SV.js +1 -0
  340. package/web/assets/chunk-HN6EAY2L-CgE_agsD.js +1 -0
  341. package/web/assets/{chunk-O5ABG6QK-Bt-Km84H.js → chunk-O5ABG6QK-DEZV1O19.js} +1 -1
  342. package/web/assets/{chunk-PK6DOVAG-ChlWY0BQ.js → chunk-PK6DOVAG-BXv0JnsJ.js} +3 -3
  343. package/web/assets/{chunk-RNJOYNJ4-B724K7cW.js → chunk-RNJOYNJ4-BiBkF9dN.js} +1 -1
  344. package/web/assets/chunk-RWUO3TPN-DTWzAhQ1.js +1 -0
  345. package/web/assets/chunk-TBF5ZNIQ-BSl6s9lT.js +1 -0
  346. package/web/assets/{chunk-TYMNRAUI-g1h33cq-.js → chunk-TYMNRAUI-D1NDLIMG.js} +1 -1
  347. package/web/assets/{chunk-W7ZLLLMY-Du-Hb9yb.js → chunk-W7ZLLLMY-Bu-cdLzs.js} +1 -1
  348. package/web/assets/{chunk-WSB5WSVC-B123clsZ.js → chunk-WSB5WSVC-Dor71SOz.js} +1 -1
  349. package/web/assets/{chunk-XGPFEOL4-BR7Eue38.js → chunk-XGPFEOL4-CUonLRle.js} +1 -1
  350. package/web/assets/classDiagram-PPOCWD7C-Cdd6UdVv.js +1 -0
  351. package/web/assets/classDiagram-v2-23LJLIIU-DNhxY2Ib.js +1 -0
  352. package/web/assets/{cose-bilkent-PNC4W37J-DCfErU-A.js → cose-bilkent-PNC4W37J-DdZq7Qz_.js} +1 -1
  353. package/web/assets/dagre-E77IOHMT-Cfj_6e17.js +4 -0
  354. package/web/assets/{diagram-H7BISOXX-CUVHlmAh.js → diagram-H7BISOXX-BNvpsrBv.js} +2 -2
  355. package/web/assets/{diagram-JC5VWROH-BoyOxulB.js → diagram-JC5VWROH-Cn0rtDbJ.js} +1 -1
  356. package/web/assets/{diagram-LXUTUG65-osr9hb7N.js → diagram-LXUTUG65-CHfoVKNm.js} +2 -2
  357. package/web/assets/{diagram-WEHSV5V5-d8nUqS39.js → diagram-WEHSV5V5-BLxHksnu.js} +1 -1
  358. package/web/assets/{erDiagram-GCSMX5X6-b-IwOhPS.js → erDiagram-GCSMX5X6-DfdN6iqF.js} +2 -2
  359. package/web/assets/flowDiagram-OTCZ4VVT-aAZw4c_M.js +162 -0
  360. package/web/assets/ganttDiagram-MUNLMDZQ-BEfC_7Or.js +292 -0
  361. package/web/assets/gitGraph-7Q5UKJZL-54BCDZD5-B6ZeRLP0.js +1 -0
  362. package/web/assets/gitGraphDiagram-3HKGZ4G3-CG0kC8Q5.js +106 -0
  363. package/web/assets/{index-C_xK08EW.js → index-3NUCUW2s.js} +124 -123
  364. package/web/assets/info-OMHHGYJF-BF2H5H6G-BIOsZy0W.js +1 -0
  365. package/web/assets/infoDiagram-MN7RKWGX-DUoMH-pq.js +2 -0
  366. package/web/assets/{ishikawaDiagram-YMYX4NHK-CXsnC2FA.js → ishikawaDiagram-YMYX4NHK-BF8AtDaj.js} +2 -2
  367. package/web/assets/{journeyDiagram-SO5T7YLQ-BzZ07B-X.js → journeyDiagram-SO5T7YLQ-BW8oKa3N.js} +3 -3
  368. package/web/assets/{kanban-definition-LJHFXRCJ-C6_EpAd9.js → kanban-definition-LJHFXRCJ-DzbOsR-2.js} +6 -6
  369. package/web/assets/{mindmap-definition-2EUWGEK5-CCYGWZ1m.js → mindmap-definition-2EUWGEK5-BIXGQALq.js} +25 -25
  370. package/web/assets/packet-4T2RLAQJ-EV4IVRXR-Bs7ysNMU.js +1 -0
  371. package/web/assets/pie-ZZUOXDRM-N23DN5KN-Csi8nnbH.js +1 -0
  372. package/web/assets/{pieDiagram-3IATQBI2-RyvRlQb4.js → pieDiagram-3IATQBI2-QY-u7P6a.js} +3 -3
  373. package/web/assets/{quadrantDiagram-E256RVCF-Bfb6sxCx.js → quadrantDiagram-E256RVCF-Di4aNiU8.js} +3 -3
  374. package/web/assets/radar-PYXPWWZC-P6TP7ZYP-DJlyXh2-.js +1 -0
  375. package/web/assets/{requirementDiagram-M5DCFWZL-DjvHDyvN.js → requirementDiagram-M5DCFWZL-CzUUrhQD.js} +4 -4
  376. package/web/assets/{sankeyDiagram-L3NBLAOT-CBCbbl8s.js → sankeyDiagram-L3NBLAOT-D2fbMiIU.js} +3 -3
  377. package/web/assets/{sequenceDiagram-ZOUHS735-BscU8TUR.js → sequenceDiagram-ZOUHS735-BNdkqguh.js} +6 -6
  378. package/web/assets/stateDiagram-MLPALWAM-51_Q2w2L.js +1 -0
  379. package/web/assets/stateDiagram-v2-B5LQ5ZB2-8nHs2aNE.js +1 -0
  380. package/web/assets/{timeline-definition-5SPVSISX-DigPA1X8.js → timeline-definition-5SPVSISX-DkMiGj4Z.js} +9 -9
  381. package/web/assets/treeView-SZITEDCU-5DXDK3XO-Cy6P0_CZ.js +1 -0
  382. package/web/assets/treemap-W4RFUUIX-WYLRDWKO-C_pp1R7A.js +1 -0
  383. package/web/assets/{vennDiagram-IE5QUKF5-C91UkZIf.js → vennDiagram-IE5QUKF5-BCxMmf9q.js} +3 -3
  384. package/web/assets/wardley-RL74JXVD-BCRCBASE-CMStJhpn.js +1 -0
  385. package/web/assets/{wardleyDiagram-XU3VSMPF-DloBhI0U.js → wardleyDiagram-XU3VSMPF-ijlLF77s.js} +4 -4
  386. package/web/assets/{xychartDiagram-ZHJ5623Y-BGWJvgwI.js → xychartDiagram-ZHJ5623Y-DZ7fP1_3.js} +3 -3
  387. package/web/index.html +1 -1
  388. package/scripts/patch-tree-sitter-swift.cjs +0 -78
  389. package/web/assets/agent-DaprsFSX.js +0 -597
  390. package/web/assets/architecture-YZFGNWBL-S5CXDPWN-DEdGaPg2.js +0 -1
  391. package/web/assets/chunk-H3VCZNTA-IchcISDt.js +0 -1
  392. package/web/assets/chunk-HN6EAY2L-D7ZFMNrB.js +0 -1
  393. package/web/assets/chunk-RWUO3TPN-DYn1XriD.js +0 -1
  394. package/web/assets/chunk-TBF5ZNIQ-DKtDz6ae.js +0 -1
  395. package/web/assets/classDiagram-PPOCWD7C-BglfKSs_.js +0 -1
  396. package/web/assets/classDiagram-v2-23LJLIIU-BSzTM28O.js +0 -1
  397. package/web/assets/dagre-E77IOHMT-tDRRhDoN.js +0 -4
  398. package/web/assets/flowDiagram-OTCZ4VVT-Ott2Q0AP.js +0 -162
  399. package/web/assets/ganttDiagram-MUNLMDZQ-BYtgN_5s.js +0 -292
  400. package/web/assets/gitGraph-7Q5UKJZL-54BCDZD5-CFyBIGZq.js +0 -1
  401. package/web/assets/gitGraphDiagram-3HKGZ4G3-CsVD2gn4.js +0 -106
  402. package/web/assets/info-OMHHGYJF-BF2H5H6G-yjAxKEzh.js +0 -1
  403. package/web/assets/infoDiagram-MN7RKWGX-DXK0Unn5.js +0 -2
  404. package/web/assets/packet-4T2RLAQJ-EV4IVRXR-B8k4E3IT.js +0 -1
  405. package/web/assets/pie-ZZUOXDRM-N23DN5KN-DdvfY118.js +0 -1
  406. package/web/assets/radar-PYXPWWZC-P6TP7ZYP-1EEDC_yU.js +0 -1
  407. package/web/assets/stateDiagram-MLPALWAM-CJusEK2D.js +0 -1
  408. package/web/assets/stateDiagram-v2-B5LQ5ZB2-DImJ3PXD.js +0 -1
  409. package/web/assets/treeView-SZITEDCU-5DXDK3XO-CzPDt3aG.js +0 -1
  410. package/web/assets/treemap-W4RFUUIX-WYLRDWKO-B9Iqiorr.js +0 -1
  411. package/web/assets/wardley-RL74JXVD-BCRCBASE-x42Qw7hp.js +0 -1
package/README.md CHANGED
@@ -156,6 +156,7 @@ gitnexus analyze --embeddings # Enable embedding generation (slower, better s
156
156
  gitnexus analyze --skip-agents-md # Preserve custom AGENTS.md/CLAUDE.md gitnexus section edits
157
157
  gitnexus analyze --verbose # Log skipped files when parsers are unavailable
158
158
  gitnexus analyze --max-file-size 1024 # Skip files larger than N KB (default: 512, cap: 32768)
159
+ gitnexus analyze --worker-timeout 60 # Increase worker idle timeout for slow parses
159
160
  gitnexus mcp # Start MCP server (stdio) — serves all indexed repos
160
161
  gitnexus serve # Start local HTTP server (multi-repo) for web UI
161
162
  gitnexus index # Register an existing .gitnexus/ folder into the global registry
@@ -295,6 +296,25 @@ If `npm install -g gitnexus` fails on native modules:
295
296
  npm install -g gitnexus
296
297
  ```
297
298
 
299
+ ### Analyze warns about unavailable FTS or VECTOR extensions
300
+
301
+ 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.
302
+
303
+ Configure the behavior with two environment variables:
304
+
305
+ | Variable | Values | Default | Effect |
306
+ |----------|--------|---------|--------|
307
+ | `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. |
308
+ | `GITNEXUS_LBUG_EXTENSION_INSTALL_TIMEOUT_MS` | positive integer | `15000` | Wall-clock budget for the out-of-process `INSTALL` child before it is killed. |
309
+
310
+ ```bash
311
+ # Offline/airgapped: never reach the network for extensions
312
+ GITNEXUS_LBUG_EXTENSION_INSTALL=load-only npx gitnexus analyze
313
+
314
+ # Slow network: give extension downloads more time
315
+ GITNEXUS_LBUG_EXTENSION_INSTALL_TIMEOUT_MS=30000 npx gitnexus analyze
316
+ ```
317
+
298
318
  ### Analysis runs out of memory
299
319
 
300
320
  For very large repositories:
@@ -323,6 +343,21 @@ npx gitnexus analyze
323
343
 
324
344
  Values above **32768 KB (32 MB)** are clamped to the tree-sitter parser ceiling; invalid values fall back to the 512 KB default with a one-time warning. When an override is active, `analyze` prints the effective threshold in its startup banner (e.g. `GITNEXUS_MAX_FILE_SIZE: effective threshold 2048KB (default 512KB)`).
325
345
 
346
+ ### Analyze reports a worker timeout
347
+
348
+ Worker parse timeouts are recoverable. GitNexus retries stalled worker jobs with backoff, splits large jobs to isolate slow files, and falls back to the sequential parser when needed. If a large repository needs more time per worker job, use either:
349
+
350
+ ```bash
351
+ # CLI flag, in seconds
352
+ npx gitnexus analyze --worker-timeout 60
353
+
354
+ # Environment variable, in milliseconds
355
+ export GITNEXUS_WORKER_SUB_BATCH_TIMEOUT_MS=60000
356
+ npx gitnexus analyze
357
+ ```
358
+
359
+ For repositories with very large source files, `GITNEXUS_WORKER_SUB_BATCH_MAX_BYTES` controls the worker job byte budget. The default is **8388608 bytes (8 MB)**.
360
+
326
361
  ## Privacy
327
362
 
328
363
  - All processing happens locally on your machine
@@ -48,6 +48,14 @@ export { buildScopeTree, canParentScope, ScopeTreeInvariantError, } from './scop
48
48
  export type { ScopeTree } from './scope-resolution/scope-tree.js';
49
49
  export { buildPositionIndex } from './scope-resolution/position-index.js';
50
50
  export type { PositionIndex } from './scope-resolution/position-index.js';
51
+ export { withRetry, computeBackoffMs } from './integrations/retry.js';
52
+ export type { RetryOptions, RetryDecision } from './integrations/retry.js';
53
+ export { CircuitBreaker, CircuitOpenError, getBreaker } from './integrations/circuit-breaker.js';
54
+ export type { CircuitBreakerOptions } from './integrations/circuit-breaker.js';
55
+ export { resilientFetch, ResilientFetchExhaustedError, RETRY_AFTER_CAP_MS, parseRetryAfter, } from './integrations/resilient-fetch.js';
56
+ export type { ResilientFetchOptions } from './integrations/resilient-fetch.js';
57
+ export { UNDERSTAND_QUICKLY_DISPATCH_URL, UNDERSTAND_QUICKLY_EVENT_TYPE, UNDERSTAND_QUICKLY_TOKEN_ENV, buildUqDispatchPayload, isValidOwnerRepo, parseOwnerRepoFromRemote, stripGitSuffix, } from './integrations/understand-quickly.js';
58
+ export type { UqDispatchPayload } from './integrations/understand-quickly.js';
51
59
  export { diffResolutions } from './scope-resolution/shadow/diff.js';
52
60
  export type { ShadowAgreement, ShadowCallsite, ShadowDiff, } from './scope-resolution/shadow/diff.js';
53
61
  export { aggregateDiffs } from './scope-resolution/shadow/aggregate.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -33,6 +33,15 @@ export { CLASS_KINDS, METHOD_KINDS, FIELD_KINDS } from './scope-resolution/regis
33
33
  export { makeScopeId, clearScopeIdInternPool } from './scope-resolution/scope-id.js';
34
34
  export { buildScopeTree, canParentScope, ScopeTreeInvariantError, } from './scope-resolution/scope-tree.js';
35
35
  export { buildPositionIndex } from './scope-resolution/position-index.js';
36
+ // Resilient fetch primitives — bounded retries + per-process circuit breaker.
37
+ // Test-only helpers (`__resetBreakerRegistry__`, `classifyOutcome`) are
38
+ // reachable via the separate `gitnexus-shared/test-helpers` subpath; do
39
+ // NOT add them here. Production consumers must not call them.
40
+ export { withRetry, computeBackoffMs } from './integrations/retry.js';
41
+ export { CircuitBreaker, CircuitOpenError, getBreaker } from './integrations/circuit-breaker.js';
42
+ export { resilientFetch, ResilientFetchExhaustedError, RETRY_AFTER_CAP_MS, parseRetryAfter, } from './integrations/resilient-fetch.js';
43
+ // Understand-Quickly registry integration (opt-in)
44
+ export { UNDERSTAND_QUICKLY_DISPATCH_URL, UNDERSTAND_QUICKLY_EVENT_TYPE, UNDERSTAND_QUICKLY_TOKEN_ENV, buildUqDispatchPayload, isValidOwnerRepo, parseOwnerRepoFromRemote, stripGitSuffix, } from './integrations/understand-quickly.js';
36
45
  // Shadow-mode diff + aggregation (RFC §6.3; Ring 2 SHARED #918)
37
46
  export { diffResolutions } from './scope-resolution/shadow/diff.js';
38
47
  export { aggregateDiffs } from './scope-resolution/shadow/aggregate.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AASA,mBAAmB;AACnB,OAAO,EACL,WAAW,EACX,cAAc,EACd,SAAS,EACT,oBAAoB,GACrB,MAAM,4BAA4B,CAAC;AAGpC,mBAAmB;AACnB,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,EAAE,uBAAuB,EAAE,6BAA6B,EAAE,MAAM,yBAAyB,CAAC;AAiCjG,8DAA8D;AAC9D,OAAO,EAAE,eAAe,EAAE,wBAAwB,EAAE,MAAM,wCAAwC,CAAC;AACnG,OAAO,EAAE,eAAe,EAAE,MAAM,uCAAuC,CAAC;AAGxE,yDAAyD;AACzD,OAAO,EACL,uBAAuB,EACvB,oBAAoB,GACrB,MAAM,+CAA+C,CAAC;AAGvD,sEAAsE;AACtE,OAAO,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;AAEhE,OAAO,EAAE,qBAAqB,EAAE,MAAM,0CAA0C,CAAC;AAEjF,OAAO,EAAE,uBAAuB,EAAE,MAAM,4CAA4C,CAAC;AAGrF,gEAAgE;AAChE,yEAAyE;AACzE,2DAA2D;AAC3D,OAAO,EAAE,cAAc,EAAE,MAAM,wCAAwC,CAAC;AAOxE,oFAAoF;AACpF,OAAO,EAAE,wBAAwB,EAAE,MAAM,6CAA6C,CAAC;AAMvF,uEAAuE;AACvE,OAAO,EAAE,QAAQ,EAAE,MAAM,0CAA0C,CAAC;AAUpE,sEAAsE;AACtE,OAAO,EAAE,kBAAkB,EAAE,MAAM,iDAAiD,CAAC;AAErF,OAAO,EAAE,mBAAmB,EAAE,MAAM,kDAAkD,CAAC;AAKvF,OAAO,EAAE,kBAAkB,EAAE,MAAM,iDAAiD,CAAC;AAKrF,OAAO,EAAE,UAAU,EAAE,MAAM,8CAA8C,CAAC;AAE1E,OAAO,EAAE,eAAe,EAAE,MAAM,mDAAmD,CAAC;AAEpF,OAAO,EAAE,eAAe,EAAE,sBAAsB,EAAE,MAAM,2CAA2C,CAAC;AAEpG,OAAO,EACL,gCAAgC,EAChC,kBAAkB,GACnB,MAAM,6CAA6C,CAAC;AAErD,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,0CAA0C,CAAC;AAQlG,2EAA2E;AAC3E,OAAO,EAAE,WAAW,EAAE,sBAAsB,EAAE,MAAM,gCAAgC,CAAC;AAErF,OAAO,EACL,cAAc,EACd,cAAc,EACd,uBAAuB,GACxB,MAAM,kCAAkC,CAAC;AAE1C,OAAO,EAAE,kBAAkB,EAAE,MAAM,sCAAsC,CAAC;AAG1E,gEAAgE;AAChE,OAAO,EAAE,eAAe,EAAE,MAAM,mCAAmC,CAAC;AAMpE,OAAO,EAAE,cAAc,EAAE,MAAM,wCAAwC,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AASA,mBAAmB;AACnB,OAAO,EACL,WAAW,EACX,cAAc,EACd,SAAS,EACT,oBAAoB,GACrB,MAAM,4BAA4B,CAAC;AAGpC,mBAAmB;AACnB,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,EAAE,uBAAuB,EAAE,6BAA6B,EAAE,MAAM,yBAAyB,CAAC;AAiCjG,8DAA8D;AAC9D,OAAO,EAAE,eAAe,EAAE,wBAAwB,EAAE,MAAM,wCAAwC,CAAC;AACnG,OAAO,EAAE,eAAe,EAAE,MAAM,uCAAuC,CAAC;AAGxE,yDAAyD;AACzD,OAAO,EACL,uBAAuB,EACvB,oBAAoB,GACrB,MAAM,+CAA+C,CAAC;AAGvD,sEAAsE;AACtE,OAAO,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;AAEhE,OAAO,EAAE,qBAAqB,EAAE,MAAM,0CAA0C,CAAC;AAEjF,OAAO,EAAE,uBAAuB,EAAE,MAAM,4CAA4C,CAAC;AAGrF,gEAAgE;AAChE,yEAAyE;AACzE,2DAA2D;AAC3D,OAAO,EAAE,cAAc,EAAE,MAAM,wCAAwC,CAAC;AAOxE,oFAAoF;AACpF,OAAO,EAAE,wBAAwB,EAAE,MAAM,6CAA6C,CAAC;AAMvF,uEAAuE;AACvE,OAAO,EAAE,QAAQ,EAAE,MAAM,0CAA0C,CAAC;AAUpE,sEAAsE;AACtE,OAAO,EAAE,kBAAkB,EAAE,MAAM,iDAAiD,CAAC;AAErF,OAAO,EAAE,mBAAmB,EAAE,MAAM,kDAAkD,CAAC;AAKvF,OAAO,EAAE,kBAAkB,EAAE,MAAM,iDAAiD,CAAC;AAKrF,OAAO,EAAE,UAAU,EAAE,MAAM,8CAA8C,CAAC;AAE1E,OAAO,EAAE,eAAe,EAAE,MAAM,mDAAmD,CAAC;AAEpF,OAAO,EAAE,eAAe,EAAE,sBAAsB,EAAE,MAAM,2CAA2C,CAAC;AAEpG,OAAO,EACL,gCAAgC,EAChC,kBAAkB,GACnB,MAAM,6CAA6C,CAAC;AAErD,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,0CAA0C,CAAC;AAQlG,2EAA2E;AAC3E,OAAO,EAAE,WAAW,EAAE,sBAAsB,EAAE,MAAM,gCAAgC,CAAC;AAErF,OAAO,EACL,cAAc,EACd,cAAc,EACd,uBAAuB,GACxB,MAAM,kCAAkC,CAAC;AAE1C,OAAO,EAAE,kBAAkB,EAAE,MAAM,sCAAsC,CAAC;AAG1E,8EAA8E;AAC9E,wEAAwE;AACxE,wEAAwE;AACxE,8DAA8D;AAC9D,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAEtE,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,mCAAmC,CAAC;AAEjG,OAAO,EACL,cAAc,EACd,4BAA4B,EAC5B,kBAAkB,EAClB,eAAe,GAChB,MAAM,mCAAmC,CAAC;AAG3C,mDAAmD;AACnD,OAAO,EACL,+BAA+B,EAC/B,6BAA6B,EAC7B,4BAA4B,EAC5B,sBAAsB,EACtB,gBAAgB,EAChB,wBAAwB,EACxB,cAAc,GACf,MAAM,sCAAsC,CAAC;AAG9C,gEAAgE;AAChE,OAAO,EAAE,eAAe,EAAE,MAAM,mCAAmC,CAAC;AAMpE,OAAO,EAAE,cAAc,EAAE,MAAM,wCAAwC,CAAC"}
@@ -0,0 +1,183 @@
1
+ /**
2
+ * Per-process circuit breaker.
3
+ *
4
+ * Closed -> Open transition fires after `failureThreshold` consecutive
5
+ * failures. While Open, `check` throws `CircuitOpenError` until
6
+ * `cooldownMs` has elapsed since the breaker tripped. The first call
7
+ * after the cooldown enters Half-Open and consumes the *probe permit*:
8
+ * a recorded success returns to Closed; a recorded failure flips back
9
+ * to Open with a fresh timestamp.
10
+ *
11
+ * Half-open admits exactly one in-flight probe at a time. Concurrent
12
+ * callers attempting `check()` while a probe is outstanding receive
13
+ * `CircuitOpenError` with `retryAfterMs = halfOpenRetryAfterMs` (default
14
+ * 1000ms; configurable). This prevents the recovery-time thundering
15
+ * herd that defeats the breaker's "fail fast" promise.
16
+ *
17
+ * Outcome reporting splits permit-release from state-resolution:
18
+ * - `recordSuccess` — releases the probe permit, resets the failure
19
+ * counter, transitions to Closed. Reserved for true 2xx/3xx outcomes.
20
+ * - `recordFailure` — releases the probe permit, increments the
21
+ * consecutive-failure counter, transitions to Open with a fresh
22
+ * `openedAt` (when called from Half-Open or when the threshold
23
+ * trips from Closed).
24
+ * - `recordNeutral` — releases the probe permit, BUT leaves state and
25
+ * counter untouched. Used for outcomes that are neither evidence of
26
+ * backend health nor evidence of backend failure (caller-driven
27
+ * cancellation, local timeout, terminal 4xx client errors). Critical
28
+ * design point: if `recordNeutral` did not release the permit, a
29
+ * single `TimeoutError` from per-attempt `AbortSignal.timeout` would
30
+ * route through `recordNeutral` and permanently park the breaker in
31
+ * half-open until process restart. Releasing the permit while leaving
32
+ * state half-open keeps the "neutral doesn't claim health" semantic
33
+ * without creating that wedge.
34
+ *
35
+ * Pairing invariant: every successful `check()` MUST be paired with
36
+ * exactly one `record*()` on every code path including throws. Direct
37
+ * consumers should wrap the protected operation in `try/finally`:
38
+ *
39
+ * breaker.check();
40
+ * try {
41
+ * const result = await operation();
42
+ * breaker.recordSuccess();
43
+ * return result;
44
+ * } catch (err) {
45
+ * // classify err and call recordFailure / recordNeutral / etc.
46
+ * throw err;
47
+ * }
48
+ *
49
+ * `resilientFetch`'s catch-all on `fetchImpl` already satisfies this
50
+ * for that consumer.
51
+ *
52
+ * Atomicity model: the half-open gate relies on JavaScript event-loop
53
+ * single-threadedness within a synchronous `check()` body. There is no
54
+ * `await` inside `check()`; concurrent callers serialize on microtask
55
+ * order, and exactly one observes `probeInFlight === false`. Do not
56
+ * introduce `await` inside `check()` without revisiting the gate. If
57
+ * this code is ever ported to a runtime with shared-memory threads
58
+ * (Node `worker_threads` with `SharedArrayBuffer`, Web Workers with
59
+ * shared registries), the boolean must become an atomic CAS — Resilience4j
60
+ * and Hystrix use atomic permits *because* they run in JVM thread pools.
61
+ *
62
+ * Runtime-agnostic: depends only on a `now()` clock and standard JS —
63
+ * no Node-only imports. Tests inject `now` to advance the clock
64
+ * deterministically without `vi.useFakeTimers()`.
65
+ */
66
+ export declare class CircuitOpenError extends Error {
67
+ readonly name = "CircuitOpenError";
68
+ /** Approximate wait time before the breaker may transition to Half-Open
69
+ * (or before the in-flight probe is expected to resolve). */
70
+ readonly retryAfterMs: number;
71
+ constructor(retryAfterMs: number, key?: string);
72
+ }
73
+ export interface CircuitBreakerOptions {
74
+ /** Consecutive failures required to trip Closed -> Open. */
75
+ failureThreshold?: number;
76
+ /** Milliseconds Open before the next call may probe (Half-Open). */
77
+ cooldownMs?: number;
78
+ /**
79
+ * Milliseconds to suggest in `CircuitOpenError.retryAfterMs` when the
80
+ * breaker is Half-Open with the probe permit consumed. Default 1000ms.
81
+ * Consumers with long-running protected ops (LLM streaming, large
82
+ * uploads) should raise this — the cooldown clock is no longer the
83
+ * right answer because cooldown has elapsed. Returning 0 invites
84
+ * retry storms; returning the full cooldown misleads about wait.
85
+ */
86
+ halfOpenRetryAfterMs?: number;
87
+ /** Optional key for error messages and registry lookups. */
88
+ key?: string;
89
+ /** Clock override — defaults to `Date.now`. Tests inject deterministic time. */
90
+ now?: () => number;
91
+ }
92
+ type State = 'closed' | 'open' | 'half-open';
93
+ export declare class CircuitBreaker {
94
+ private readonly failureThreshold;
95
+ private readonly cooldownMs;
96
+ private readonly halfOpenRetryAfterMs;
97
+ private readonly key;
98
+ private readonly now;
99
+ private state;
100
+ private consecutiveFailures;
101
+ private openedAt;
102
+ /**
103
+ * True between a successful `check()` and the next `record*()` call
104
+ * during Half-Open. Gates concurrent callers from stampeding a still-
105
+ * recovering dependency. Boolean rather than counter — single-permit
106
+ * is the conservative end of the Hystrix/Resilience4j spectrum.
107
+ */
108
+ private probeInFlight;
109
+ constructor(opts?: CircuitBreakerOptions);
110
+ /**
111
+ * Throw `CircuitOpenError` if the breaker won't admit this call.
112
+ * Otherwise consume the half-open probe permit (if applicable) and
113
+ * return so the caller can attempt the protected work.
114
+ *
115
+ * Three rejection paths:
116
+ * 1. Open and still in cooldown → throws with `retryAfterMs` =
117
+ * remaining cooldown.
118
+ * 2. Open with cooldown elapsed AND a probe is already in flight
119
+ * (race: another caller transitioned to half-open and grabbed
120
+ * the permit on a microtask before us) → throws with
121
+ * `halfOpenRetryAfterMs`.
122
+ * 3. Half-Open with probe in flight → throws with `halfOpenRetryAfterMs`.
123
+ *
124
+ * **Pairing invariant**: every successful return from `check()` MUST
125
+ * be paired with exactly one `recordSuccess` / `recordFailure` /
126
+ * `recordNeutral` on every code path including thrown exceptions.
127
+ * Failing to pair leaves the probe permit consumed forever and
128
+ * wedges the breaker. See file-header JSDoc for the canonical
129
+ * try/finally pattern.
130
+ */
131
+ check(): void;
132
+ recordSuccess(): void;
133
+ recordFailure(): void;
134
+ /**
135
+ * Releases the probe permit BUT leaves state and counter untouched.
136
+ * Use when an attempt produced a response or error that should not
137
+ * influence breaker health in either direction — caller-driven aborts,
138
+ * local AbortSignal timeouts, terminal 4xx client errors.
139
+ *
140
+ * Why permit-release-without-state-resolution: if `recordNeutral` did
141
+ * not clear `probeInFlight`, a single `TimeoutError` from per-attempt
142
+ * `AbortSignal.timeout` (which routes through neutral classification)
143
+ * would permanently park the breaker in half-open. Since timeouts are
144
+ * an *expected* outcome under flaky-dependency conditions, the cited
145
+ * "per-attempt timeout bounds the stuck state" mitigation would itself
146
+ * be the trigger for a permanent wedge. Releasing the permit closes
147
+ * that loop while keeping the "neutral doesn't claim dependency
148
+ * health" semantic.
149
+ *
150
+ * Calling `recordSuccess` for these would erase legitimate prior
151
+ * failure signal; calling `recordFailure` would trip the breaker for
152
+ * outcomes the backend isn't responsible for.
153
+ */
154
+ recordNeutral(): void;
155
+ /**
156
+ * Pure read — no state mutation, no permit accounting. Returns the
157
+ * *would-be* state at the current instant: 'half-open' if the breaker
158
+ * is open with cooldown elapsed (regardless of whether a probe is in
159
+ * flight), 'open' if open and still in cooldown, 'closed' otherwise.
160
+ *
161
+ * Inspection-only; safe to call from tests without consuming a probe
162
+ * permit. The implicit Open -> Half-Open transition that mutates
163
+ * `state` lives in `check()` only.
164
+ */
165
+ getState(): State;
166
+ getConsecutiveFailures(): number;
167
+ /** Inspection-only test accessor for the half-open probe permit. */
168
+ isProbeInFlight(): boolean;
169
+ /** Timestamp (ms since epoch) when the breaker last transitioned to Open,
170
+ * or `null` if it's currently Closed. Useful for computing remaining
171
+ * cooldown without consuming a probe permit via `check()`. */
172
+ getOpenedAt(): number | null;
173
+ /** Configured cooldown duration in milliseconds. */
174
+ getCooldownMs(): number;
175
+ }
176
+ export declare function getBreaker(key: string, opts?: CircuitBreakerOptions): CircuitBreaker;
177
+ /**
178
+ * Test-only: clear all registered breakers. Tests must call this in
179
+ * `beforeEach` to prevent breaker state from leaking across test cases.
180
+ */
181
+ export declare function __resetBreakerRegistry__(): void;
182
+ export {};
183
+ //# sourceMappingURL=circuit-breaker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"circuit-breaker.d.ts","sourceRoot":"","sources":["../../src/integrations/circuit-breaker.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgEG;AAEH,qBAAa,gBAAiB,SAAQ,KAAK;IACzC,SAAkB,IAAI,sBAAsB;IAC5C;kEAC8D;IAC9D,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;gBAElB,YAAY,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM;CAQ/C;AAED,MAAM,WAAW,qBAAqB;IACpC,4DAA4D;IAC5D,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,oEAAoE;IACpE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;;;;;OAOG;IACH,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,4DAA4D;IAC5D,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,gFAAgF;IAChF,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACpB;AAED,KAAK,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,WAAW,CAAC;AAE7C,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAS;IAC1C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAS;IAC9C,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAqB;IACzC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAe;IAEnC,OAAO,CAAC,KAAK,CAAmB;IAChC,OAAO,CAAC,mBAAmB,CAAK;IAChC,OAAO,CAAC,QAAQ,CAAuB;IACvC;;;;;OAKG;IACH,OAAO,CAAC,aAAa,CAAS;gBAElB,IAAI,GAAE,qBAA0B;IAQ5C;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,KAAK,IAAI,IAAI;IAqBb,aAAa,IAAI,IAAI;IAOrB,aAAa,IAAI,IAAI;IASrB;;;;;;;;;;;;;;;;;;;OAmBG;IACH,aAAa,IAAI,IAAI;IAKrB;;;;;;;;;OASG;IACH,QAAQ,IAAI,KAAK;IAOjB,sBAAsB,IAAI,MAAM;IAGhC,oEAAoE;IACpE,eAAe,IAAI,OAAO;IAG1B;;mEAE+D;IAC/D,WAAW,IAAI,MAAM,GAAG,IAAI;IAG5B,oDAAoD;IACpD,aAAa,IAAI,MAAM;CAGxB;AAUD,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,qBAAqB,GAAG,cAAc,CAOpF;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,IAAI,IAAI,CAE/C"}
@@ -0,0 +1,236 @@
1
+ /**
2
+ * Per-process circuit breaker.
3
+ *
4
+ * Closed -> Open transition fires after `failureThreshold` consecutive
5
+ * failures. While Open, `check` throws `CircuitOpenError` until
6
+ * `cooldownMs` has elapsed since the breaker tripped. The first call
7
+ * after the cooldown enters Half-Open and consumes the *probe permit*:
8
+ * a recorded success returns to Closed; a recorded failure flips back
9
+ * to Open with a fresh timestamp.
10
+ *
11
+ * Half-open admits exactly one in-flight probe at a time. Concurrent
12
+ * callers attempting `check()` while a probe is outstanding receive
13
+ * `CircuitOpenError` with `retryAfterMs = halfOpenRetryAfterMs` (default
14
+ * 1000ms; configurable). This prevents the recovery-time thundering
15
+ * herd that defeats the breaker's "fail fast" promise.
16
+ *
17
+ * Outcome reporting splits permit-release from state-resolution:
18
+ * - `recordSuccess` — releases the probe permit, resets the failure
19
+ * counter, transitions to Closed. Reserved for true 2xx/3xx outcomes.
20
+ * - `recordFailure` — releases the probe permit, increments the
21
+ * consecutive-failure counter, transitions to Open with a fresh
22
+ * `openedAt` (when called from Half-Open or when the threshold
23
+ * trips from Closed).
24
+ * - `recordNeutral` — releases the probe permit, BUT leaves state and
25
+ * counter untouched. Used for outcomes that are neither evidence of
26
+ * backend health nor evidence of backend failure (caller-driven
27
+ * cancellation, local timeout, terminal 4xx client errors). Critical
28
+ * design point: if `recordNeutral` did not release the permit, a
29
+ * single `TimeoutError` from per-attempt `AbortSignal.timeout` would
30
+ * route through `recordNeutral` and permanently park the breaker in
31
+ * half-open until process restart. Releasing the permit while leaving
32
+ * state half-open keeps the "neutral doesn't claim health" semantic
33
+ * without creating that wedge.
34
+ *
35
+ * Pairing invariant: every successful `check()` MUST be paired with
36
+ * exactly one `record*()` on every code path including throws. Direct
37
+ * consumers should wrap the protected operation in `try/finally`:
38
+ *
39
+ * breaker.check();
40
+ * try {
41
+ * const result = await operation();
42
+ * breaker.recordSuccess();
43
+ * return result;
44
+ * } catch (err) {
45
+ * // classify err and call recordFailure / recordNeutral / etc.
46
+ * throw err;
47
+ * }
48
+ *
49
+ * `resilientFetch`'s catch-all on `fetchImpl` already satisfies this
50
+ * for that consumer.
51
+ *
52
+ * Atomicity model: the half-open gate relies on JavaScript event-loop
53
+ * single-threadedness within a synchronous `check()` body. There is no
54
+ * `await` inside `check()`; concurrent callers serialize on microtask
55
+ * order, and exactly one observes `probeInFlight === false`. Do not
56
+ * introduce `await` inside `check()` without revisiting the gate. If
57
+ * this code is ever ported to a runtime with shared-memory threads
58
+ * (Node `worker_threads` with `SharedArrayBuffer`, Web Workers with
59
+ * shared registries), the boolean must become an atomic CAS — Resilience4j
60
+ * and Hystrix use atomic permits *because* they run in JVM thread pools.
61
+ *
62
+ * Runtime-agnostic: depends only on a `now()` clock and standard JS —
63
+ * no Node-only imports. Tests inject `now` to advance the clock
64
+ * deterministically without `vi.useFakeTimers()`.
65
+ */
66
+ export class CircuitOpenError extends Error {
67
+ name = 'CircuitOpenError';
68
+ /** Approximate wait time before the breaker may transition to Half-Open
69
+ * (or before the in-flight probe is expected to resolve). */
70
+ retryAfterMs;
71
+ constructor(retryAfterMs, key) {
72
+ super(key
73
+ ? `Circuit '${key}' is open; retry in ${Math.ceil(retryAfterMs / 1000)}s`
74
+ : `Circuit is open; retry in ${Math.ceil(retryAfterMs / 1000)}s`);
75
+ this.retryAfterMs = retryAfterMs;
76
+ }
77
+ }
78
+ export class CircuitBreaker {
79
+ failureThreshold;
80
+ cooldownMs;
81
+ halfOpenRetryAfterMs;
82
+ key;
83
+ now;
84
+ state = 'closed';
85
+ consecutiveFailures = 0;
86
+ openedAt = null;
87
+ /**
88
+ * True between a successful `check()` and the next `record*()` call
89
+ * during Half-Open. Gates concurrent callers from stampeding a still-
90
+ * recovering dependency. Boolean rather than counter — single-permit
91
+ * is the conservative end of the Hystrix/Resilience4j spectrum.
92
+ */
93
+ probeInFlight = false;
94
+ constructor(opts = {}) {
95
+ this.failureThreshold = opts.failureThreshold ?? 3;
96
+ this.cooldownMs = opts.cooldownMs ?? 30_000;
97
+ this.halfOpenRetryAfterMs = opts.halfOpenRetryAfterMs ?? 1_000;
98
+ this.key = opts.key;
99
+ this.now = opts.now ?? (() => Date.now());
100
+ }
101
+ /**
102
+ * Throw `CircuitOpenError` if the breaker won't admit this call.
103
+ * Otherwise consume the half-open probe permit (if applicable) and
104
+ * return so the caller can attempt the protected work.
105
+ *
106
+ * Three rejection paths:
107
+ * 1. Open and still in cooldown → throws with `retryAfterMs` =
108
+ * remaining cooldown.
109
+ * 2. Open with cooldown elapsed AND a probe is already in flight
110
+ * (race: another caller transitioned to half-open and grabbed
111
+ * the permit on a microtask before us) → throws with
112
+ * `halfOpenRetryAfterMs`.
113
+ * 3. Half-Open with probe in flight → throws with `halfOpenRetryAfterMs`.
114
+ *
115
+ * **Pairing invariant**: every successful return from `check()` MUST
116
+ * be paired with exactly one `recordSuccess` / `recordFailure` /
117
+ * `recordNeutral` on every code path including thrown exceptions.
118
+ * Failing to pair leaves the probe permit consumed forever and
119
+ * wedges the breaker. See file-header JSDoc for the canonical
120
+ * try/finally pattern.
121
+ */
122
+ check() {
123
+ if (this.state === 'open' && this.openedAt !== null) {
124
+ const elapsed = this.now() - this.openedAt;
125
+ if (elapsed < this.cooldownMs) {
126
+ throw new CircuitOpenError(this.cooldownMs - elapsed, this.key);
127
+ }
128
+ // Cooldown elapsed — transition to Half-Open. The very next
129
+ // `probeInFlight` check below decides whether THIS caller gets
130
+ // the permit or hits the gate.
131
+ this.state = 'half-open';
132
+ }
133
+ if (this.state === 'half-open') {
134
+ if (this.probeInFlight) {
135
+ throw new CircuitOpenError(this.halfOpenRetryAfterMs, this.key);
136
+ }
137
+ this.probeInFlight = true;
138
+ }
139
+ // Closed state falls through silently.
140
+ }
141
+ recordSuccess() {
142
+ this.probeInFlight = false;
143
+ this.consecutiveFailures = 0;
144
+ this.state = 'closed';
145
+ this.openedAt = null;
146
+ }
147
+ recordFailure() {
148
+ this.probeInFlight = false;
149
+ this.consecutiveFailures += 1;
150
+ if (this.state === 'half-open' || this.consecutiveFailures >= this.failureThreshold) {
151
+ this.state = 'open';
152
+ this.openedAt = this.now();
153
+ }
154
+ }
155
+ /**
156
+ * Releases the probe permit BUT leaves state and counter untouched.
157
+ * Use when an attempt produced a response or error that should not
158
+ * influence breaker health in either direction — caller-driven aborts,
159
+ * local AbortSignal timeouts, terminal 4xx client errors.
160
+ *
161
+ * Why permit-release-without-state-resolution: if `recordNeutral` did
162
+ * not clear `probeInFlight`, a single `TimeoutError` from per-attempt
163
+ * `AbortSignal.timeout` (which routes through neutral classification)
164
+ * would permanently park the breaker in half-open. Since timeouts are
165
+ * an *expected* outcome under flaky-dependency conditions, the cited
166
+ * "per-attempt timeout bounds the stuck state" mitigation would itself
167
+ * be the trigger for a permanent wedge. Releasing the permit closes
168
+ * that loop while keeping the "neutral doesn't claim dependency
169
+ * health" semantic.
170
+ *
171
+ * Calling `recordSuccess` for these would erase legitimate prior
172
+ * failure signal; calling `recordFailure` would trip the breaker for
173
+ * outcomes the backend isn't responsible for.
174
+ */
175
+ recordNeutral() {
176
+ this.probeInFlight = false;
177
+ // State and consecutiveFailures are preserved by design.
178
+ }
179
+ /**
180
+ * Pure read — no state mutation, no permit accounting. Returns the
181
+ * *would-be* state at the current instant: 'half-open' if the breaker
182
+ * is open with cooldown elapsed (regardless of whether a probe is in
183
+ * flight), 'open' if open and still in cooldown, 'closed' otherwise.
184
+ *
185
+ * Inspection-only; safe to call from tests without consuming a probe
186
+ * permit. The implicit Open -> Half-Open transition that mutates
187
+ * `state` lives in `check()` only.
188
+ */
189
+ getState() {
190
+ if (this.state === 'open' && this.openedAt !== null) {
191
+ const elapsed = this.now() - this.openedAt;
192
+ if (elapsed >= this.cooldownMs)
193
+ return 'half-open';
194
+ }
195
+ return this.state;
196
+ }
197
+ getConsecutiveFailures() {
198
+ return this.consecutiveFailures;
199
+ }
200
+ /** Inspection-only test accessor for the half-open probe permit. */
201
+ isProbeInFlight() {
202
+ return this.probeInFlight;
203
+ }
204
+ /** Timestamp (ms since epoch) when the breaker last transitioned to Open,
205
+ * or `null` if it's currently Closed. Useful for computing remaining
206
+ * cooldown without consuming a probe permit via `check()`. */
207
+ getOpenedAt() {
208
+ return this.openedAt;
209
+ }
210
+ /** Configured cooldown duration in milliseconds. */
211
+ getCooldownMs() {
212
+ return this.cooldownMs;
213
+ }
214
+ }
215
+ // ─── Per-process registry ────────────────────────────────────────────
216
+ //
217
+ // Single shared map keyed on caller-chosen strings. Used by
218
+ // `resilient-fetch.ts` so multiple call sites targeting the same logical
219
+ // endpoint share breaker state. Per-process only — not persisted.
220
+ const registry = new Map();
221
+ export function getBreaker(key, opts) {
222
+ let breaker = registry.get(key);
223
+ if (!breaker) {
224
+ breaker = new CircuitBreaker({ ...opts, key });
225
+ registry.set(key, breaker);
226
+ }
227
+ return breaker;
228
+ }
229
+ /**
230
+ * Test-only: clear all registered breakers. Tests must call this in
231
+ * `beforeEach` to prevent breaker state from leaking across test cases.
232
+ */
233
+ export function __resetBreakerRegistry__() {
234
+ registry.clear();
235
+ }
236
+ //# sourceMappingURL=circuit-breaker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"circuit-breaker.js","sourceRoot":"","sources":["../../src/integrations/circuit-breaker.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,99 @@
1
+ /**
2
+ * `resilientFetch` — fetch wrapped in retry + circuit breaker, with
3
+ * GitHub-flavoured retry classification baked in (Retry-After parsing,
4
+ * 401/403/404/422 treated as terminal client errors).
5
+ *
6
+ * Designed for the `gitnexus publish` GitHub `repository_dispatch`
7
+ * call, but the classification rules apply to any GitHub REST endpoint.
8
+ * Runtime-agnostic — no Node-only imports.
9
+ */
10
+ import { CircuitBreaker, CircuitOpenError, type CircuitBreakerOptions } from './circuit-breaker.js';
11
+ import { type RetryOptions } from './retry.js';
12
+ export { CircuitOpenError };
13
+ export interface ResilientFetchOptions {
14
+ /** Optional fetch implementation override. Defaults to `globalThis.fetch`. */
15
+ fetchImpl?: typeof fetch;
16
+ /**
17
+ * Logical key for the breaker. Defaults to `<host><pathname>` of the
18
+ * request URL — call sites targeting the same endpoint share breaker
19
+ * state regardless of query-string differences.
20
+ */
21
+ breakerKey?: string;
22
+ /** Per-call breaker override. Used for tests and one-off configuration. */
23
+ breaker?: CircuitBreaker;
24
+ /** Tuning knobs for the breaker registered under `breakerKey`. */
25
+ breakerOptions?: CircuitBreakerOptions;
26
+ /** Tuning knobs for the retry helper. */
27
+ retry?: Partial<Pick<RetryOptions, 'maxAttempts' | 'baseDelayMs' | 'capDelayMs'>> & {
28
+ sleep?: RetryOptions['sleep'];
29
+ random?: RetryOptions['random'];
30
+ };
31
+ /** Clock override propagated into Retry-After HTTP-date math and breaker. */
32
+ now?: () => number;
33
+ }
34
+ /** Cap on any single Retry-After wait — protects CLI from a buggy registry. */
35
+ export declare const RETRY_AFTER_CAP_MS = 30000;
36
+ /**
37
+ * Parse a `Retry-After` header value into milliseconds.
38
+ * Accepts either a delta-seconds integer (`"30"`) or an HTTP-date.
39
+ * Returns null on parse failure or negative deltas.
40
+ */
41
+ export declare function parseRetryAfter(value: string | null, now?: () => number): number | null;
42
+ /** Internal: outcome classification used by the resilientFetch loop. */
43
+ type Outcome = {
44
+ kind: 'success';
45
+ resp: Response;
46
+ } | {
47
+ kind: 'terminal-client';
48
+ resp: Response;
49
+ } | {
50
+ kind: 'retryable-status';
51
+ resp: Response;
52
+ afterMs: number | undefined;
53
+ } | {
54
+ kind: 'terminal-network';
55
+ err: unknown;
56
+ } | {
57
+ kind: 'retryable-network';
58
+ err: unknown;
59
+ };
60
+ /** Exported for unit tests. */
61
+ export declare function classifyOutcome(result: {
62
+ kind: 'error';
63
+ err: unknown;
64
+ } | {
65
+ kind: 'response';
66
+ resp: Response;
67
+ }, now: () => number): Outcome;
68
+ /** Final error thrown when retries are exhausted on a 5xx / 429. */
69
+ export declare class ResilientFetchExhaustedError extends Error {
70
+ readonly response: Response;
71
+ readonly name = "ResilientFetchExhaustedError";
72
+ constructor(response: Response);
73
+ }
74
+ /**
75
+ * Wrap `fetch` with bounded retries and a per-process circuit breaker.
76
+ *
77
+ * Semantics:
78
+ * - 5xx and 429 responses are retried; 429 honors `Retry-After` (capped).
79
+ * - Network throws are retried unless they are `TimeoutError` DOMExceptions.
80
+ * - Timeouts and 4xx (other than 429) are returned/thrown without retry
81
+ * AND without incrementing the breaker — they reflect caller config
82
+ * or local network state, not registry health.
83
+ * - Each `fetch` call carries the caller-supplied `signal` (e.g. an
84
+ * `AbortSignal.timeout()`) — that timeout bounds each individual
85
+ * attempt, not the whole retry sequence.
86
+ * - When the breaker is open, throws `CircuitOpenError` synchronously
87
+ * without invoking `fetch`.
88
+ * - When retries are exhausted on a 5xx / 429, throws
89
+ * `ResilientFetchExhaustedError` carrying the last response.
90
+ *
91
+ * Cumulative wall-clock budget:
92
+ * maxAttempts × (per-attempt-timeout + capDelayMs)
93
+ * With defaults (3, 500ms base, 5000ms cap) and a typical 15s per-attempt
94
+ * timeout from the caller's signal, worst case is ~3 × (15s + 5s) = 60s.
95
+ * Callers that want a tighter total bound should reduce `maxAttempts` or
96
+ * wrap `resilientFetch` in their own outer `AbortSignal.timeout()`.
97
+ */
98
+ export declare function resilientFetch(input: string | URL, init: RequestInit | undefined, opts?: ResilientFetchOptions): Promise<Response>;
99
+ //# sourceMappingURL=resilient-fetch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resilient-fetch.d.ts","sourceRoot":"","sources":["../../src/integrations/resilient-fetch.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EACL,cAAc,EACd,gBAAgB,EAEhB,KAAK,qBAAqB,EAC3B,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAoB,KAAK,YAAY,EAAE,MAAM,YAAY,CAAC;AAEjE,OAAO,EAAE,gBAAgB,EAAE,CAAC;AAE5B,MAAM,WAAW,qBAAqB;IACpC,8EAA8E;IAC9E,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;IACzB;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,2EAA2E;IAC3E,OAAO,CAAC,EAAE,cAAc,CAAC;IACzB,kEAAkE;IAClE,cAAc,CAAC,EAAE,qBAAqB,CAAC;IACvC,yCAAyC;IACzC,KAAK,CAAC,EAAE,OAAO,CAAC,IAAI,CAAC,YAAY,EAAE,aAAa,GAAG,aAAa,GAAG,YAAY,CAAC,CAAC,GAAG;QAClF,KAAK,CAAC,EAAE,YAAY,CAAC,OAAO,CAAC,CAAC;QAC9B,MAAM,CAAC,EAAE,YAAY,CAAC,QAAQ,CAAC,CAAC;KACjC,CAAC;IACF,6EAA6E;IAC7E,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACpB;AAED,+EAA+E;AAC/E,eAAO,MAAM,kBAAkB,QAAS,CAAC;AAQzC;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,EAAE,GAAG,GAAE,MAAM,MAAiB,GAAG,MAAM,GAAG,IAAI,CAejG;AAED,wEAAwE;AACxE,KAAK,OAAO,GACR;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,IAAI,EAAE,QAAQ,CAAA;CAAE,GACnC;IAAE,IAAI,EAAE,iBAAiB,CAAC;IAAC,IAAI,EAAE,QAAQ,CAAA;CAAE,GAC3C;IAAE,IAAI,EAAE,kBAAkB,CAAC;IAAC,IAAI,EAAE,QAAQ,CAAC;IAAC,OAAO,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,GACzE;IAAE,IAAI,EAAE,kBAAkB,CAAC;IAAC,GAAG,EAAE,OAAO,CAAA;CAAE,GAC1C;IAAE,IAAI,EAAE,mBAAmB,CAAC;IAAC,GAAG,EAAE,OAAO,CAAA;CAAE,CAAC;AAEhD,+BAA+B;AAC/B,wBAAgB,eAAe,CAC7B,MAAM,EAAE;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,GAAG,EAAE,OAAO,CAAA;CAAE,GAAG;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,IAAI,EAAE,QAAQ,CAAA;CAAE,EAC9E,GAAG,EAAE,MAAM,MAAM,GAChB,OAAO,CAiCT;AAcD,oEAAoE;AACpE,qBAAa,4BAA6B,SAAQ,KAAK;aAEzB,QAAQ,EAAE,QAAQ;IAD9C,SAAkB,IAAI,kCAAkC;gBAC5B,QAAQ,EAAE,QAAQ;CAG/C;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAsB,cAAc,CAClC,KAAK,EAAE,MAAM,GAAG,GAAG,EACnB,IAAI,EAAE,WAAW,GAAG,SAAS,EAC7B,IAAI,GAAE,qBAA0B,GAC/B,OAAO,CAAC,QAAQ,CAAC,CA8GnB"}