codebase-onboarder 0.6.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (448) hide show
  1. package/README.md +174 -46
  2. package/bin/build-if-source.js +23 -0
  3. package/cli/commands.d.ts +26 -0
  4. package/cli/commands.js +836 -811
  5. package/cli/commands.js.map +1 -0
  6. package/cli/explorer/advanced.d.ts +14 -0
  7. package/cli/explorer/advanced.js +321 -329
  8. package/cli/explorer/advanced.js.map +1 -0
  9. package/cli/explorer/app.d.ts +1 -0
  10. package/cli/explorer/app.js +384 -313
  11. package/cli/explorer/app.js.map +1 -0
  12. package/cli/explorer/assistant.d.ts +9 -0
  13. package/cli/explorer/assistant.js +58 -0
  14. package/cli/explorer/assistant.js.map +1 -0
  15. package/cli/explorer/commands.d.ts +17 -0
  16. package/cli/explorer/commands.js +368 -302
  17. package/cli/explorer/commands.js.map +1 -0
  18. package/cli/explorer/featureViews.d.ts +124 -0
  19. package/cli/explorer/featureViews.js +179 -0
  20. package/cli/explorer/featureViews.js.map +1 -0
  21. package/cli/explorer/github.d.ts +21 -0
  22. package/cli/explorer/github.js +42 -44
  23. package/cli/explorer/github.js.map +1 -0
  24. package/cli/explorer/graphs.d.ts +7 -0
  25. package/cli/explorer/graphs.js +90 -95
  26. package/cli/explorer/graphs.js.map +1 -0
  27. package/cli/explorer/picker.d.ts +22 -0
  28. package/cli/explorer/picker.js +150 -0
  29. package/cli/explorer/picker.js.map +1 -0
  30. package/cli/explorer/report.d.ts +85 -0
  31. package/cli/explorer/report.js +60 -0
  32. package/cli/explorer/report.js.map +1 -0
  33. package/cli/explorer/session.d.ts +449 -0
  34. package/cli/explorer/session.js +143 -144
  35. package/cli/explorer/session.js.map +1 -0
  36. package/cli/explorer/views.d.ts +19 -0
  37. package/cli/explorer/views.js +465 -482
  38. package/cli/explorer/views.js.map +1 -0
  39. package/cli/explorer/wrap.d.ts +1 -0
  40. package/cli/explorer/wrap.js +28 -44
  41. package/cli/explorer/wrap.js.map +1 -0
  42. package/cli/main.d.ts +1 -0
  43. package/cli/main.js +214 -161
  44. package/cli/main.js.map +1 -0
  45. package/cli/prompt.d.ts +5 -0
  46. package/cli/prompt.js +84 -80
  47. package/cli/prompt.js.map +1 -0
  48. package/cli/scanOptions.d.ts +2 -0
  49. package/cli/scanOptions.js +11 -0
  50. package/cli/scanOptions.js.map +1 -0
  51. package/cli/ui.d.ts +33 -0
  52. package/cli/ui.js +35 -44
  53. package/cli/ui.js.map +1 -0
  54. package/cli/wizard.d.ts +187 -0
  55. package/cli/wizard.js +304 -284
  56. package/cli/wizard.js.map +1 -0
  57. package/package.json +15 -4
  58. package/public/app.d.ts +1 -0
  59. package/public/app.js +1057 -1009
  60. package/public/app.js.map +1 -0
  61. package/public/browser.d.ts +68 -0
  62. package/public/browser.js +2 -0
  63. package/public/browser.js.map +1 -0
  64. package/public/index.html +30 -13
  65. package/public/js/about.d.ts +6 -0
  66. package/public/js/about.js +152 -172
  67. package/public/js/about.js.map +1 -0
  68. package/public/js/aiDraft.d.ts +3 -0
  69. package/public/js/aiDraft.js +116 -124
  70. package/public/js/aiDraft.js.map +1 -0
  71. package/public/js/analysisPanel.d.ts +7 -0
  72. package/public/js/analysisPanel.js +166 -166
  73. package/public/js/analysisPanel.js.map +1 -0
  74. package/public/js/analysisReport.d.ts +38 -0
  75. package/public/js/analysisReport.js +105 -110
  76. package/public/js/analysisReport.js.map +1 -0
  77. package/public/js/api.d.ts +26 -0
  78. package/public/js/api.js +176 -167
  79. package/public/js/api.js.map +1 -0
  80. package/public/js/atlas.d.ts +6 -0
  81. package/public/js/atlas.js +50 -58
  82. package/public/js/atlas.js.map +1 -0
  83. package/public/js/blameView.d.ts +2 -0
  84. package/public/js/blameView.js +36 -37
  85. package/public/js/blameView.js.map +1 -0
  86. package/public/js/codeTab.d.ts +3 -0
  87. package/public/js/codeTab.js +175 -180
  88. package/public/js/codeTab.js.map +1 -0
  89. package/public/js/codeViewer.d.ts +5 -0
  90. package/public/js/codeViewer.js +162 -150
  91. package/public/js/codeViewer.js.map +1 -0
  92. package/public/js/components/FileChip.d.ts +9 -0
  93. package/public/js/components/FileChip.js +45 -49
  94. package/public/js/components/FileChip.js.map +1 -0
  95. package/public/js/components/MetricSparkline.d.ts +7 -0
  96. package/public/js/components/MetricSparkline.js +35 -44
  97. package/public/js/components/MetricSparkline.js.map +1 -0
  98. package/public/js/components/RiskBadge.d.ts +9 -0
  99. package/public/js/components/RiskBadge.js +55 -63
  100. package/public/js/components/RiskBadge.js.map +1 -0
  101. package/public/js/deepAnalysisView.d.ts +99 -0
  102. package/public/js/deepAnalysisView.js +282 -302
  103. package/public/js/deepAnalysisView.js.map +1 -0
  104. package/public/js/diagramPane.d.ts +8 -0
  105. package/public/js/diagramPane.js +133 -135
  106. package/public/js/diagramPane.js.map +1 -0
  107. package/public/js/diffView.d.ts +6 -0
  108. package/public/js/diffView.js +222 -209
  109. package/public/js/diffView.js.map +1 -0
  110. package/public/js/docsView.d.ts +2 -0
  111. package/public/js/docsView.js +441 -442
  112. package/public/js/docsView.js.map +1 -0
  113. package/public/js/dom.d.ts +189 -0
  114. package/public/js/dom.js +5 -0
  115. package/public/js/dom.js.map +1 -0
  116. package/public/js/fileSourceBrowser.d.ts +5 -0
  117. package/public/js/fileSourceBrowser.js +33 -41
  118. package/public/js/fileSourceBrowser.js.map +1 -0
  119. package/public/js/flameGraph.d.ts +5 -0
  120. package/public/js/flameGraph.js +62 -72
  121. package/public/js/flameGraph.js.map +1 -0
  122. package/public/js/forceGraph.d.ts +10 -0
  123. package/public/js/forceGraph.js +581 -556
  124. package/public/js/forceGraph.js.map +1 -0
  125. package/public/js/heatmap.d.ts +4 -0
  126. package/public/js/heatmap.js +142 -164
  127. package/public/js/heatmap.js.map +1 -0
  128. package/public/js/highlight.d.ts +2 -0
  129. package/public/js/highlight.js +116 -107
  130. package/public/js/highlight.js.map +1 -0
  131. package/public/js/html.d.ts +2 -0
  132. package/public/js/html.js +14 -44
  133. package/public/js/html.js.map +1 -0
  134. package/public/js/insightsView.d.ts +5 -0
  135. package/public/js/insightsView.js +93 -111
  136. package/public/js/insightsView.js.map +1 -0
  137. package/public/js/inspector.d.ts +37 -0
  138. package/public/js/inspector.js +416 -445
  139. package/public/js/inspector.js.map +1 -0
  140. package/public/js/llm.d.ts +113 -0
  141. package/public/js/llm.js +233 -272
  142. package/public/js/llm.js.map +1 -0
  143. package/public/js/mapView.d.ts +3 -0
  144. package/public/js/mapView.js +121 -120
  145. package/public/js/mapView.js.map +1 -0
  146. package/public/js/markdown.d.ts +3 -0
  147. package/public/js/markdown.js +84 -91
  148. package/public/js/markdown.js.map +1 -0
  149. package/public/js/mindmap.d.ts +32 -0
  150. package/public/js/mindmap.js +244 -259
  151. package/public/js/mindmap.js.map +1 -0
  152. package/public/js/mobilePanels.d.ts +5 -0
  153. package/public/js/mobilePanels.js +50 -0
  154. package/public/js/mobilePanels.js.map +1 -0
  155. package/public/js/repoFiles.d.ts +12 -0
  156. package/public/js/repoFiles.js +28 -27
  157. package/public/js/repoFiles.js.map +1 -0
  158. package/public/js/reviewView.d.ts +28 -0
  159. package/public/js/reviewView.js +256 -0
  160. package/public/js/reviewView.js.map +1 -0
  161. package/public/js/sbomView.d.ts +3 -0
  162. package/public/js/sbomView.js +59 -67
  163. package/public/js/sbomView.js.map +1 -0
  164. package/public/js/scanCache.d.ts +16 -0
  165. package/public/js/scanCache.js +67 -65
  166. package/public/js/scanCache.js.map +1 -0
  167. package/public/js/search.d.ts +7 -0
  168. package/public/js/search.js +868 -800
  169. package/public/js/search.js.map +1 -0
  170. package/public/js/searchLocal.d.ts +42 -0
  171. package/public/js/searchLocal.js +87 -0
  172. package/public/js/searchLocal.js.map +1 -0
  173. package/public/js/serverSettings.d.ts +5 -0
  174. package/public/js/serverSettings.js +153 -164
  175. package/public/js/serverSettings.js.map +1 -0
  176. package/public/js/state.d.ts +798 -0
  177. package/public/js/state.js +114 -122
  178. package/public/js/state.js.map +1 -0
  179. package/public/js/tour.d.ts +6 -0
  180. package/public/js/tour.js +5 -7
  181. package/public/js/tour.js.map +1 -0
  182. package/public/js/transitions.d.ts +2 -0
  183. package/public/js/transitions.js +9 -10
  184. package/public/js/transitions.js.map +1 -0
  185. package/public/js/tree.d.ts +12 -0
  186. package/public/js/tree.js +157 -154
  187. package/public/js/tree.js.map +1 -0
  188. package/public/js/workflowsView.d.ts +3 -0
  189. package/public/js/workflowsView.js +15 -22
  190. package/public/js/workflowsView.js.map +1 -0
  191. package/public/search.css +495 -0
  192. package/public/styles.css +163 -346
  193. package/public/workbench.css +166 -0
  194. package/server/apiAuth.d.ts +3 -0
  195. package/server/apiAuth.js +18 -20
  196. package/server/apiAuth.js.map +1 -0
  197. package/server/apiDiff.d.ts +2 -0
  198. package/server/apiDiff.js +20 -18
  199. package/server/apiDiff.js.map +1 -0
  200. package/server/apiDocs.d.ts +2 -0
  201. package/server/apiDocs.js +38 -40
  202. package/server/apiDocs.js.map +1 -0
  203. package/server/apiFile.d.ts +1 -0
  204. package/server/apiFile.js +14 -17
  205. package/server/apiFile.js.map +1 -0
  206. package/server/apiGitBlame.d.ts +2 -0
  207. package/server/apiGitBlame.js +50 -51
  208. package/server/apiGitBlame.js.map +1 -0
  209. package/server/apiMcp.d.ts +4 -0
  210. package/server/apiMcp.js +64 -66
  211. package/server/apiMcp.js.map +1 -0
  212. package/server/apiReview.d.ts +2 -0
  213. package/server/apiReview.js +45 -0
  214. package/server/apiReview.js.map +1 -0
  215. package/server/apiScan.d.ts +5 -0
  216. package/server/apiScan.js +90 -71
  217. package/server/apiScan.js.map +1 -0
  218. package/server/apiSearch.d.ts +33 -0
  219. package/server/apiSearch.js +184 -200
  220. package/server/apiSearch.js.map +1 -0
  221. package/server/apiSettings.d.ts +4 -0
  222. package/server/apiSettings.js +84 -85
  223. package/server/apiSettings.js.map +1 -0
  224. package/server/apiTools.d.ts +3 -0
  225. package/server/apiTools.js +55 -56
  226. package/server/apiTools.js.map +1 -0
  227. package/server/auth.d.ts +5 -0
  228. package/server/auth.js +54 -51
  229. package/server/auth.js.map +1 -0
  230. package/server/config.d.ts +42 -0
  231. package/server/config.js +189 -194
  232. package/server/config.js.map +1 -0
  233. package/server/daemon.d.ts +12 -0
  234. package/server/daemon.js +124 -114
  235. package/server/daemon.js.map +1 -0
  236. package/server/fileSourceNode.d.ts +2 -0
  237. package/server/fileSourceNode.js +34 -36
  238. package/server/fileSourceNode.js.map +1 -0
  239. package/server/gitClone.d.ts +9 -0
  240. package/server/gitClone.js +59 -61
  241. package/server/gitClone.js.map +1 -0
  242. package/server/gitDiff.d.ts +36 -0
  243. package/server/gitDiff.js +271 -169
  244. package/server/gitDiff.js.map +1 -0
  245. package/server/gitHistory.d.ts +12 -0
  246. package/server/gitHistory.js +80 -80
  247. package/server/gitHistory.js.map +1 -0
  248. package/server/gitRemote.d.ts +12 -0
  249. package/server/gitRemote.js +37 -38
  250. package/server/gitRemote.js.map +1 -0
  251. package/server/htmlText.d.ts +4 -0
  252. package/server/htmlText.js +16 -23
  253. package/server/htmlText.js.map +1 -0
  254. package/server/http.d.ts +5 -0
  255. package/server/http.js +27 -30
  256. package/server/http.js.map +1 -0
  257. package/server/httpGuards.d.ts +2 -0
  258. package/server/httpGuards.js +47 -43
  259. package/server/httpGuards.js.map +1 -0
  260. package/server/https.d.ts +34 -0
  261. package/server/https.js +121 -111
  262. package/server/https.js.map +1 -0
  263. package/server/index.d.ts +40 -0
  264. package/server/index.js +139 -147
  265. package/server/index.js.map +1 -0
  266. package/server/layout.d.ts +26 -0
  267. package/server/layout.js +59 -64
  268. package/server/layout.js.map +1 -0
  269. package/server/llmProxy.d.ts +3 -0
  270. package/server/llmProxy.js +137 -135
  271. package/server/llmProxy.js.map +1 -0
  272. package/server/logger.d.ts +38 -0
  273. package/server/logger.js +198 -211
  274. package/server/logger.js.map +1 -0
  275. package/server/mcp/analysis.d.ts +29 -0
  276. package/server/mcp/analysis.js +99 -120
  277. package/server/mcp/analysis.js.map +1 -0
  278. package/server/mcp/http.d.ts +9 -0
  279. package/server/mcp/http.js +128 -137
  280. package/server/mcp/http.js.map +1 -0
  281. package/server/mcp/runner.d.ts +68 -0
  282. package/server/mcp/runner.js +208 -218
  283. package/server/mcp/runner.js.map +1 -0
  284. package/server/mcp/server.d.ts +29 -0
  285. package/server/mcp/server.js +166 -179
  286. package/server/mcp/server.js.map +1 -0
  287. package/server/mcp/standalone.d.ts +1 -0
  288. package/server/mcp/standalone.js +8 -10
  289. package/server/mcp/standalone.js.map +1 -0
  290. package/server/mcp/tools.d.ts +2020 -0
  291. package/server/mcp/tools.js +523 -574
  292. package/server/mcp/tools.js.map +1 -0
  293. package/server/paths.d.ts +3 -0
  294. package/server/paths.js +17 -15
  295. package/server/paths.js.map +1 -0
  296. package/server/pidfile.d.ts +9 -0
  297. package/server/pidfile.js +43 -45
  298. package/server/pidfile.js.map +1 -0
  299. package/server/review.d.ts +5 -0
  300. package/server/review.js +35 -0
  301. package/server/review.js.map +1 -0
  302. package/server/router.d.ts +33 -0
  303. package/server/router.js +191 -197
  304. package/server/router.js.map +1 -0
  305. package/server/scanRequest.d.ts +3 -0
  306. package/server/scanRequest.js +36 -0
  307. package/server/scanRequest.js.map +1 -0
  308. package/server/searchIndex.d.ts +17 -0
  309. package/server/searchIndex.js +83 -80
  310. package/server/searchIndex.js.map +1 -0
  311. package/server/sessions.d.ts +14 -0
  312. package/server/sessions.js +62 -70
  313. package/server/sessions.js.map +1 -0
  314. package/server/startup.d.ts +118 -0
  315. package/server/startup.js +143 -148
  316. package/server/startup.js.map +1 -0
  317. package/server/static.d.ts +6 -0
  318. package/server/static.js +28 -31
  319. package/server/static.js.map +1 -0
  320. package/server/tools/install.d.ts +4 -0
  321. package/server/tools/install.js +176 -185
  322. package/server/tools/install.js.map +1 -0
  323. package/server/tools/parse.d.ts +8 -0
  324. package/server/tools/parse.js +112 -114
  325. package/server/tools/parse.js.map +1 -0
  326. package/server/tools/platform.d.ts +9 -0
  327. package/server/tools/platform.js +49 -47
  328. package/server/tools/platform.js.map +1 -0
  329. package/server/tools/registry.d.ts +137 -0
  330. package/server/tools/registry.js +173 -172
  331. package/server/tools/registry.js.map +1 -0
  332. package/server/tools/scan.d.ts +34 -0
  333. package/server/tools/scan.js +89 -98
  334. package/server/tools/scan.js.map +1 -0
  335. package/server/tools.d.ts +34 -0
  336. package/server/tools.js +94 -107
  337. package/server/tools.js.map +1 -0
  338. package/server/tunnel.d.ts +29 -0
  339. package/server/tunnel.js +61 -66
  340. package/server/tunnel.js.map +1 -0
  341. package/shared/analyzer/docs.d.ts +16 -0
  342. package/shared/analyzer/docs.js +99 -93
  343. package/shared/analyzer/docs.js.map +1 -0
  344. package/shared/analyzer/explainLocal.d.ts +4 -0
  345. package/shared/analyzer/explainLocal.js +122 -142
  346. package/shared/analyzer/explainLocal.js.map +1 -0
  347. package/shared/analyzer/github.d.ts +37 -0
  348. package/shared/analyzer/github.js +41 -43
  349. package/shared/analyzer/github.js.map +1 -0
  350. package/shared/analyzer/graph.d.ts +41 -0
  351. package/shared/analyzer/graph.js +393 -400
  352. package/shared/analyzer/graph.js.map +1 -0
  353. package/shared/analyzer/health.d.ts +33 -0
  354. package/shared/analyzer/health.js +197 -193
  355. package/shared/analyzer/health.js.map +1 -0
  356. package/shared/analyzer/history.d.ts +29 -0
  357. package/shared/analyzer/history.js +110 -111
  358. package/shared/analyzer/history.js.map +1 -0
  359. package/shared/analyzer/jsonConfig.d.ts +2 -0
  360. package/shared/analyzer/jsonConfig.js +61 -0
  361. package/shared/analyzer/jsonConfig.js.map +1 -0
  362. package/shared/analyzer/languages/csharp.d.ts +26 -0
  363. package/shared/analyzer/languages/csharp.js +83 -88
  364. package/shared/analyzer/languages/csharp.js.map +1 -0
  365. package/shared/analyzer/languages/generic.d.ts +23 -0
  366. package/shared/analyzer/languages/generic.js +94 -105
  367. package/shared/analyzer/languages/generic.js.map +1 -0
  368. package/shared/analyzer/languages/go.d.ts +24 -0
  369. package/shared/analyzer/languages/go.js +45 -54
  370. package/shared/analyzer/languages/go.js.map +1 -0
  371. package/shared/analyzer/languages/index.d.ts +6 -0
  372. package/shared/analyzer/languages/index.js +19 -20
  373. package/shared/analyzer/languages/index.js.map +1 -0
  374. package/shared/analyzer/languages/java.d.ts +20 -0
  375. package/shared/analyzer/languages/java.js +73 -78
  376. package/shared/analyzer/languages/java.js.map +1 -0
  377. package/shared/analyzer/languages/javascript.d.ts +12 -0
  378. package/shared/analyzer/languages/javascript.js +258 -209
  379. package/shared/analyzer/languages/javascript.js.map +1 -0
  380. package/shared/analyzer/languages/python.d.ts +23 -0
  381. package/shared/analyzer/languages/python.js +92 -100
  382. package/shared/analyzer/languages/python.js.map +1 -0
  383. package/shared/analyzer/languages/rust.d.ts +17 -0
  384. package/shared/analyzer/languages/rust.js +96 -98
  385. package/shared/analyzer/languages/rust.js.map +1 -0
  386. package/shared/analyzer/languages/typescript.d.ts +11 -0
  387. package/shared/analyzer/languages/typescript.js +117 -116
  388. package/shared/analyzer/languages/typescript.js.map +1 -0
  389. package/shared/analyzer/licenses.d.ts +18 -0
  390. package/shared/analyzer/licenses.js +130 -133
  391. package/shared/analyzer/licenses.js.map +1 -0
  392. package/shared/analyzer/metrics.d.ts +20 -0
  393. package/shared/analyzer/metrics.js +112 -104
  394. package/shared/analyzer/metrics.js.map +1 -0
  395. package/shared/analyzer/pathUtil.d.ts +10 -0
  396. package/shared/analyzer/pathUtil.js +29 -35
  397. package/shared/analyzer/pathUtil.js.map +1 -0
  398. package/shared/analyzer/patterns.d.ts +11 -0
  399. package/shared/analyzer/patterns.js +231 -253
  400. package/shared/analyzer/patterns.js.map +1 -0
  401. package/shared/analyzer/scan.d.ts +62 -0
  402. package/shared/analyzer/scan.js +451 -442
  403. package/shared/analyzer/scan.js.map +1 -0
  404. package/shared/analyzer/scanControl.d.ts +11 -0
  405. package/shared/analyzer/scanControl.js +62 -0
  406. package/shared/analyzer/scanControl.js.map +1 -0
  407. package/shared/analyzer/security.d.ts +18 -0
  408. package/shared/analyzer/security.js +159 -159
  409. package/shared/analyzer/security.js.map +1 -0
  410. package/shared/analyzer/services.d.ts +5 -0
  411. package/shared/analyzer/services.js +141 -138
  412. package/shared/analyzer/services.js.map +1 -0
  413. package/shared/analyzer/stack.d.ts +6 -0
  414. package/shared/analyzer/stack.js +134 -141
  415. package/shared/analyzer/stack.js.map +1 -0
  416. package/shared/analyzer/tour.d.ts +2 -0
  417. package/shared/analyzer/tour.js +45 -53
  418. package/shared/analyzer/tour.js.map +1 -0
  419. package/shared/analyzer/util.d.ts +8 -0
  420. package/shared/analyzer/util.js +130 -76
  421. package/shared/analyzer/util.js.map +1 -0
  422. package/shared/analyzer/workflows.d.ts +8 -0
  423. package/shared/analyzer/workflows.js +139 -134
  424. package/shared/analyzer/workflows.js.map +1 -0
  425. package/shared/contracts.d.ts +250 -0
  426. package/shared/contracts.js +2 -0
  427. package/shared/contracts.js.map +1 -0
  428. package/shared/diagram/aiFacts.d.ts +35 -0
  429. package/shared/diagram/aiFacts.js +102 -105
  430. package/shared/diagram/aiFacts.js.map +1 -0
  431. package/shared/diagram/aiMermaid.d.ts +5 -0
  432. package/shared/diagram/aiMermaid.js +46 -45
  433. package/shared/diagram/aiMermaid.js.map +1 -0
  434. package/shared/diagram/atlas.d.ts +16 -0
  435. package/shared/diagram/atlas.js +51 -60
  436. package/shared/diagram/atlas.js.map +1 -0
  437. package/shared/diagram/mermaid.d.ts +43 -0
  438. package/shared/diagram/mermaid.js +348 -370
  439. package/shared/diagram/mermaid.js.map +1 -0
  440. package/shared/review/contracts.d.ts +95 -0
  441. package/shared/review/contracts.js +2 -0
  442. package/shared/review/contracts.js.map +1 -0
  443. package/shared/review/review.d.ts +10 -0
  444. package/shared/review/review.js +184 -0
  445. package/shared/review/review.js.map +1 -0
  446. package/shared/search/query.d.ts +32 -0
  447. package/shared/search/query.js +395 -388
  448. package/shared/search/query.js.map +1 -0
@@ -1,20 +1,17 @@
1
1
  // Forwards chat-completion requests to any OpenAI-compatible endpoint and
2
2
  // streams the answer straight back. The API key passes through in memory
3
3
  // only — it is never written anywhere, and never appears in logs.
4
-
5
4
  import { sendError, sendJSON } from './http.js';
6
-
7
5
  const UPSTREAM_TIMEOUT_MS = 60_000;
8
6
  const MAX_MESSAGES_BYTES = 120_000;
9
-
10
7
  const EXTRA_ALLOWED = new Set(['reasoning', 'temperature', 'top_p', 'presence_penalty', 'frequency_penalty']);
11
-
12
8
  export function detectProvider(apiKey, baseUrl) {
13
- if (apiKey?.startsWith('sk-ant-')) return 'anthropic';
14
- if (apiKey?.startsWith('AIza')) return 'gemini';
15
- return 'openai';
9
+ if (apiKey?.startsWith('sk-ant-'))
10
+ return 'anthropic';
11
+ if (apiKey?.startsWith('AIza'))
12
+ return 'gemini';
13
+ return 'openai';
16
14
  }
17
-
18
15
  // Extracts the provider's request id from an upstream response. Each
19
16
  // provider spells it differently; the order in this list is "what we have
20
17
  // seen", not "what is correct" — a missing id is fine and collapses to
@@ -22,141 +19,146 @@ export function detectProvider(apiKey, baseUrl) {
22
19
  // is anything with a `.get(name)` method, which both `Response.headers` and
23
20
  // a hand-rolled plain object can satisfy in the test suite.
24
21
  export function extractRequestId(headers) {
25
- if (!headers || typeof headers.get !== 'function') return null;
26
- return headers.get('x-request-id')
27
- || headers.get('request-id')
28
- || headers.get('x-amzn-requestid')
29
- || headers.get('x-goog-request-id')
30
- || null;
22
+ if (!headers || typeof headers.get !== 'function')
23
+ return null;
24
+ return headers.get('x-request-id')
25
+ || headers.get('request-id')
26
+ || headers.get('x-amzn-requestid')
27
+ || headers.get('x-goog-request-id')
28
+ || null;
31
29
  }
32
-
33
30
  export async function proxyChat(res, body) {
34
- const { baseUrl, apiKey, model, messages } = body || {};
35
- const stream = body.stream !== false;
36
- const maxTokens = Math.min(Number(body.max_tokens) || 700, 4096);
37
-
38
- if (!model || typeof model !== 'string') {
39
- return sendError(res, 400, 'A model name is needed.');
40
- }
41
- if (!Array.isArray(messages) || !messages.length) {
42
- return sendError(res, 400, 'No messages to send.');
43
- }
44
- if (JSON.stringify(messages).length > MAX_MESSAGES_BYTES) {
45
- return sendError(res, 413, 'That prompt is too large. Try a smaller file.');
46
- }
47
-
48
- const provider = detectProvider(apiKey, baseUrl);
49
-
50
- let url;
51
- let headers = { 'content-type': 'application/json' };
52
- let payload = { stream };
53
- const isAzure = /\.openai\.azure\.com|\.cognitiveservices\.azure\.com/i.test(baseUrl || '');
54
-
55
- if (provider === 'anthropic') {
56
- url = 'https://api.anthropic.com/v1/messages';
57
- headers['x-api-key'] = apiKey;
58
- headers['anthropic-version'] = '2023-06-01';
59
-
60
- let system = '';
61
- const anthropicMessages = [];
62
- for (const m of messages) {
63
- if (m.role === 'system') system += m.content + '\n';
64
- else anthropicMessages.push({ role: m.role === 'user' ? 'user' : 'assistant', content: m.content });
31
+ const { baseUrl, apiKey, model, messages } = body || {};
32
+ const stream = body.stream !== false;
33
+ const maxTokens = Math.min(Number(body.max_tokens) || 700, 4096);
34
+ if (!model || typeof model !== 'string') {
35
+ return sendError(res, 400, 'A model name is needed.');
65
36
  }
66
- payload = {
67
- model,
68
- max_tokens: maxTokens,
69
- messages: anthropicMessages,
70
- system: system.trim() || undefined,
71
- stream
72
- };
73
- } else if (provider === 'gemini') {
74
- const streamSuffix = stream ? 'streamGenerateContent?alt=sse' : 'generateContent';
75
- url = `https://generativelanguage.googleapis.com/v1beta/models/${model}:${streamSuffix}&key=${apiKey}`;
76
-
77
- let system_instruction = null;
78
- const contents = [];
79
- for (const m of messages) {
80
- if (m.role === 'system') {
81
- system_instruction = { parts: [{ text: m.content }] };
82
- } else {
83
- contents.push({ role: m.role === 'assistant' ? 'model' : 'user', parts: [{ text: m.content }] });
84
- }
37
+ if (!Array.isArray(messages) || !messages.length) {
38
+ return sendError(res, 400, 'No messages to send.');
85
39
  }
86
- payload = {
87
- contents,
88
- system_instruction,
89
- generationConfig: { maxOutputTokens: maxTokens }
90
- };
91
- } else {
92
- // OpenAI default
93
- if (!baseUrl || !/^https?:\/\/\S+$/.test(baseUrl)) {
94
- return sendError(res, 400, 'A valid base URL is needed — something like https://api.openai.com/v1.');
40
+ if (JSON.stringify(messages).length > MAX_MESSAGES_BYTES) {
41
+ return sendError(res, 413, 'That prompt is too large. Try a smaller file.');
95
42
  }
96
- url = baseUrl.replace(/\/+$/, '') + '/chat/completions';
97
- if (apiKey) {
98
- if (isAzure) headers['api-key'] = apiKey;
99
- else headers.authorization = 'Bearer ' + apiKey;
43
+ const provider = detectProvider(apiKey, baseUrl);
44
+ let url;
45
+ let headers = { 'content-type': 'application/json' };
46
+ let payload = { stream };
47
+ const isAzure = /\.openai\.azure\.com|\.cognitiveservices\.azure\.com/i.test(baseUrl || '');
48
+ if (provider === 'anthropic') {
49
+ url = 'https://api.anthropic.com/v1/messages';
50
+ headers['x-api-key'] = apiKey;
51
+ headers['anthropic-version'] = '2023-06-01';
52
+ let system = '';
53
+ const anthropicMessages = [];
54
+ for (const m of messages) {
55
+ if (m.role === 'system')
56
+ system += m.content + '\n';
57
+ else
58
+ anthropicMessages.push({ role: m.role === 'user' ? 'user' : 'assistant', content: m.content });
59
+ }
60
+ payload = {
61
+ model,
62
+ max_tokens: maxTokens,
63
+ messages: anthropicMessages,
64
+ system: system.trim() || undefined,
65
+ stream
66
+ };
100
67
  }
101
- payload = { model, messages, stream };
102
- if (isAzure) payload.max_completion_tokens = maxTokens;
103
- else payload.max_tokens = maxTokens;
104
- for (const key of Object.keys(body)) {
105
- if (EXTRA_ALLOWED.has(key)) payload[key] = body[key];
68
+ else if (provider === 'gemini') {
69
+ const streamSuffix = stream ? 'streamGenerateContent?alt=sse' : 'generateContent';
70
+ url = `https://generativelanguage.googleapis.com/v1beta/models/${model}:${streamSuffix}&key=${apiKey}`;
71
+ let system_instruction = null;
72
+ const contents = [];
73
+ for (const m of messages) {
74
+ if (m.role === 'system') {
75
+ system_instruction = { parts: [{ text: m.content }] };
76
+ }
77
+ else {
78
+ contents.push({ role: m.role === 'assistant' ? 'model' : 'user', parts: [{ text: m.content }] });
79
+ }
80
+ }
81
+ payload = {
82
+ contents,
83
+ system_instruction,
84
+ generationConfig: { maxOutputTokens: maxTokens }
85
+ };
106
86
  }
107
- }
108
-
109
- let upstream;
110
- try {
111
- upstream = await fetch(url, {
112
- method: 'POST',
113
- headers,
114
- body: JSON.stringify(payload),
115
- signal: AbortSignal.timeout(UPSTREAM_TIMEOUT_MS),
87
+ else {
88
+ // OpenAI default
89
+ if (!baseUrl || !/^https?:\/\/\S+$/.test(baseUrl)) {
90
+ return sendError(res, 400, 'A valid base URL is needed — something like https://api.openai.com/v1.');
91
+ }
92
+ url = baseUrl.replace(/\/+$/, '') + '/chat/completions';
93
+ if (apiKey) {
94
+ if (isAzure)
95
+ headers['api-key'] = apiKey;
96
+ else
97
+ headers.authorization = 'Bearer ' + apiKey;
98
+ }
99
+ payload = { model, messages, stream };
100
+ if (isAzure)
101
+ payload.max_completion_tokens = maxTokens;
102
+ else
103
+ payload.max_tokens = maxTokens;
104
+ for (const key of Object.keys(body)) {
105
+ if (EXTRA_ALLOWED.has(key))
106
+ payload[key] = body[key];
107
+ }
108
+ }
109
+ let upstream;
110
+ try {
111
+ upstream = await fetch(url, {
112
+ method: 'POST',
113
+ headers,
114
+ body: JSON.stringify(payload),
115
+ signal: AbortSignal.timeout(UPSTREAM_TIMEOUT_MS),
116
+ });
117
+ }
118
+ catch (err) {
119
+ const why = err.name === 'TimeoutError' ? 'The endpoint took too long to answer.' : 'Could not reach ' + url + '.';
120
+ return sendError(res, 502, why);
121
+ }
122
+ if (!upstream.ok) {
123
+ const text = await upstream.text().catch(() => '');
124
+ let detail = text.slice(0, 400);
125
+ try {
126
+ const parsed = JSON.parse(text);
127
+ detail = parsed.error?.message || detail;
128
+ }
129
+ catch { }
130
+ // The provider's request id, when it sends one. Most providers do —
131
+ // OpenAI, Anthropic, Google all set one of these on every response —
132
+ // and "ask the user to paste this" is far more useful than "ask the
133
+ // user to describe what they did". `extractRequestId` is the one place
134
+ // that knows the spelling; the response body only carries the field
135
+ // when there is one to carry, so missing ids stay out of the payload.
136
+ const requestId = extractRequestId(upstream.headers);
137
+ const body = {
138
+ error: `The provider answered ${upstream.status}.`,
139
+ detail,
140
+ };
141
+ if (requestId)
142
+ body.requestId = requestId;
143
+ return sendJSON(res, upstream.status, body);
144
+ }
145
+ if (!stream) {
146
+ const json = await upstream.json().catch(() => null);
147
+ return sendJSON(res, 200, json || {});
148
+ }
149
+ res.writeHead(200, {
150
+ 'content-type': 'text/event-stream',
151
+ 'cache-control': 'no-cache',
152
+ connection: 'keep-alive',
116
153
  });
117
- } catch (err) {
118
- const why = err.name === 'TimeoutError' ? 'The endpoint took too long to answer.' : 'Could not reach ' + url + '.';
119
- return sendError(res, 502, why);
120
- }
121
-
122
- if (!upstream.ok) {
123
- const text = await upstream.text().catch(() => '');
124
- let detail = text.slice(0, 400);
154
+ res.on('close', () => upstream.body?.cancel().catch((..._args) => { }));
125
155
  try {
126
- const parsed = JSON.parse(text);
127
- detail = parsed.error?.message || detail;
128
- } catch {}
129
- // The provider's request id, when it sends one. Most providers do —
130
- // OpenAI, Anthropic, Google all set one of these on every response —
131
- // and "ask the user to paste this" is far more useful than "ask the
132
- // user to describe what they did". `extractRequestId` is the one place
133
- // that knows the spelling; the response body only carries the field
134
- // when there is one to carry, so missing ids stay out of the payload.
135
- const requestId = extractRequestId(upstream.headers);
136
- const body = {
137
- error: `The provider answered ${upstream.status}.`,
138
- detail,
139
- };
140
- if (requestId) body.requestId = requestId;
141
- return sendJSON(res, upstream.status, body);
142
- }
143
-
144
- if (!stream) {
145
- const json = await upstream.json().catch(() => null);
146
- return sendJSON(res, 200, json || {});
147
- }
148
-
149
- res.writeHead(200, {
150
- 'content-type': 'text/event-stream',
151
- 'cache-control': 'no-cache',
152
- connection: 'keep-alive',
153
- });
154
- res.on('close', () => upstream.body?.cancel().catch(() => {}));
155
-
156
- try {
157
- for await (const chunk of upstream.body) {
158
- if (!res.write(chunk)) await new Promise((r) => res.once('drain', r));
156
+ for await (const chunk of upstream.body) {
157
+ if (!res.write(chunk))
158
+ await new Promise((r) => res.once('drain', r));
159
+ }
159
160
  }
160
- } catch {}
161
- res.end();
161
+ catch { }
162
+ res.end();
162
163
  }
164
+ //# sourceMappingURL=llmProxy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"llmProxy.js","sourceRoot":"","sources":["../src/server/llmProxy.ts"],"names":[],"mappings":"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","sourcesContent":["// Forwards chat-completion requests to any OpenAI-compatible endpoint and\n// streams the answer straight back. The API key passes through in memory\n// only — it is never written anywhere, and never appears in logs.\n\nimport { sendError, sendJSON } from './http.js';\n\nconst UPSTREAM_TIMEOUT_MS = 60_000;\nconst MAX_MESSAGES_BYTES = 120_000;\n\nconst EXTRA_ALLOWED = new Set(['reasoning', 'temperature', 'top_p', 'presence_penalty', 'frequency_penalty']);\n\nexport function detectProvider(apiKey, baseUrl) {\n if (apiKey?.startsWith('sk-ant-')) return 'anthropic';\n if (apiKey?.startsWith('AIza')) return 'gemini';\n return 'openai';\n}\n\n// Extracts the provider's request id from an upstream response. Each\n// provider spells it differently; the order in this list is \"what we have\n// seen\", not \"what is correct\" — a missing id is fine and collapses to\n// null. The function is pure and exported for tests; the `headers` argument\n// is anything with a `.get(name)` method, which both `Response.headers` and\n// a hand-rolled plain object can satisfy in the test suite.\nexport function extractRequestId(headers) {\n if (!headers || typeof headers.get !== 'function') return null;\n return headers.get('x-request-id')\n || headers.get('request-id')\n || headers.get('x-amzn-requestid')\n || headers.get('x-goog-request-id')\n || null;\n}\n\nexport async function proxyChat(res, body) {\n const { baseUrl, apiKey, model, messages } = body || {};\n const stream = body.stream !== false;\n const maxTokens = Math.min(Number(body.max_tokens) || 700, 4096);\n\n if (!model || typeof model !== 'string') {\n return sendError(res, 400, 'A model name is needed.');\n }\n if (!Array.isArray(messages) || !messages.length) {\n return sendError(res, 400, 'No messages to send.');\n }\n if (JSON.stringify(messages).length > MAX_MESSAGES_BYTES) {\n return sendError(res, 413, 'That prompt is too large. Try a smaller file.');\n }\n\n const provider = detectProvider(apiKey, baseUrl);\n\n let url;\n let headers: Record<string, string> = { 'content-type': 'application/json' };\n let payload: Record<string, unknown> = { stream };\n const isAzure = /\\.openai\\.azure\\.com|\\.cognitiveservices\\.azure\\.com/i.test(baseUrl || '');\n\n if (provider === 'anthropic') {\n url = 'https://api.anthropic.com/v1/messages';\n headers['x-api-key'] = apiKey;\n headers['anthropic-version'] = '2023-06-01';\n \n let system = '';\n const anthropicMessages = [];\n for (const m of messages) {\n if (m.role === 'system') system += m.content + '\\n';\n else anthropicMessages.push({ role: m.role === 'user' ? 'user' : 'assistant', content: m.content });\n }\n payload = {\n model,\n max_tokens: maxTokens,\n messages: anthropicMessages,\n system: system.trim() || undefined,\n stream\n };\n } else if (provider === 'gemini') {\n const streamSuffix = stream ? 'streamGenerateContent?alt=sse' : 'generateContent';\n url = `https://generativelanguage.googleapis.com/v1beta/models/${model}:${streamSuffix}&key=${apiKey}`;\n \n let system_instruction = null;\n const contents = [];\n for (const m of messages) {\n if (m.role === 'system') {\n system_instruction = { parts: [{ text: m.content }] };\n } else {\n contents.push({ role: m.role === 'assistant' ? 'model' : 'user', parts: [{ text: m.content }] });\n }\n }\n payload = {\n contents,\n system_instruction,\n generationConfig: { maxOutputTokens: maxTokens }\n };\n } else {\n // OpenAI default\n if (!baseUrl || !/^https?:\\/\\/\\S+$/.test(baseUrl)) {\n return sendError(res, 400, 'A valid base URL is needed — something like https://api.openai.com/v1.');\n }\n url = baseUrl.replace(/\\/+$/, '') + '/chat/completions';\n if (apiKey) {\n if (isAzure) headers['api-key'] = apiKey;\n else headers.authorization = 'Bearer ' + apiKey;\n }\n payload = { model, messages, stream };\n if (isAzure) payload.max_completion_tokens = maxTokens;\n else payload.max_tokens = maxTokens;\n for (const key of Object.keys(body)) {\n if (EXTRA_ALLOWED.has(key)) payload[key] = body[key];\n }\n }\n\n let upstream;\n try {\n upstream = await fetch(url, {\n method: 'POST',\n headers,\n body: JSON.stringify(payload),\n signal: AbortSignal.timeout(UPSTREAM_TIMEOUT_MS),\n });\n } catch (err) {\n const why = err.name === 'TimeoutError' ? 'The endpoint took too long to answer.' : 'Could not reach ' + url + '.';\n return sendError(res, 502, why);\n }\n\n if (!upstream.ok) {\n const text = await upstream.text().catch(() => '');\n let detail = text.slice(0, 400);\n try {\n const parsed = JSON.parse(text);\n detail = parsed.error?.message || detail;\n } catch {}\n // The provider's request id, when it sends one. Most providers do —\n // OpenAI, Anthropic, Google all set one of these on every response —\n // and \"ask the user to paste this\" is far more useful than \"ask the\n // user to describe what they did\". `extractRequestId` is the one place\n // that knows the spelling; the response body only carries the field\n // when there is one to carry, so missing ids stay out of the payload.\n const requestId = extractRequestId(upstream.headers);\n const body: { error: string; detail: string; requestId?: string } = {\n error: `The provider answered ${upstream.status}.`,\n detail,\n };\n if (requestId) body.requestId = requestId;\n return sendJSON(res, upstream.status, body);\n }\n\n if (!stream) {\n const json = await upstream.json().catch(() => null);\n return sendJSON(res, 200, json || {});\n }\n\n res.writeHead(200, {\n 'content-type': 'text/event-stream',\n 'cache-control': 'no-cache',\n connection: 'keep-alive',\n });\n res.on('close', () => upstream.body?.cancel().catch((..._args: unknown[]) => {}));\n\n try {\n for await (const chunk of upstream.body) {\n if (!res.write(chunk)) await new Promise((r) => res.once('drain', r));\n }\n } catch {}\n res.end();\n}\n"]}
@@ -0,0 +1,38 @@
1
+ export declare const SEVERITY: {
2
+ error: number;
3
+ warn: number;
4
+ info: number;
5
+ debug: number;
6
+ };
7
+ export declare function classifyPath(pathname?: string): "action" | "noise" | "poll";
8
+ export declare function classifyRequest(req?: Record<string, any>): "action" | "noise" | "poll";
9
+ export declare function formatMessage(entry: any): string;
10
+ export declare function identifyingTail(text: any): string;
11
+ export declare function fitPath(text: any, max: any): string;
12
+ export declare const LEVEL_MIN_COLUMNS = 52;
13
+ export declare const SHORT_TIME_COLUMNS = 24;
14
+ export declare const NO_TIME_COLUMNS = 12;
15
+ export declare function showLevel(columns: any): boolean;
16
+ export declare function showFullTime(columns: any): boolean;
17
+ export declare function showTime(columns: any): boolean;
18
+ export declare function timeColumn(entry: any, columns: any): string;
19
+ export declare function prefixWidth(columns: any): number;
20
+ export declare function messageWidth(columns: any): number;
21
+ export declare function formatEntry(entry: any, { columns }?: Record<string, any>): string;
22
+ export declare function renderEntry(entry: any, { color, columns }?: Record<string, any>): string;
23
+ export declare function noiseSummary(count: any, ms?: number): string;
24
+ export declare function logEntry(level: any, msg: any, extra?: Record<string, any>): {
25
+ ts: string;
26
+ time: string;
27
+ level: any;
28
+ msg: any;
29
+ };
30
+ export declare function createLogger(level?: string, options?: Record<string, any>): {
31
+ debug: (msg: any, extra: any) => void;
32
+ info: (msg: any, extra: any) => void;
33
+ warn: (msg: any, extra: any) => void;
34
+ error: (msg: any, extra: any) => void;
35
+ http: (req: any) => void;
36
+ flush: () => void;
37
+ suppressed: () => number;
38
+ };