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.
- package/README.md +174 -46
- package/bin/build-if-source.js +23 -0
- package/cli/commands.d.ts +26 -0
- package/cli/commands.js +836 -811
- package/cli/commands.js.map +1 -0
- package/cli/explorer/advanced.d.ts +14 -0
- package/cli/explorer/advanced.js +321 -329
- package/cli/explorer/advanced.js.map +1 -0
- package/cli/explorer/app.d.ts +1 -0
- package/cli/explorer/app.js +384 -313
- package/cli/explorer/app.js.map +1 -0
- package/cli/explorer/assistant.d.ts +9 -0
- package/cli/explorer/assistant.js +58 -0
- package/cli/explorer/assistant.js.map +1 -0
- package/cli/explorer/commands.d.ts +17 -0
- package/cli/explorer/commands.js +368 -302
- package/cli/explorer/commands.js.map +1 -0
- package/cli/explorer/featureViews.d.ts +124 -0
- package/cli/explorer/featureViews.js +179 -0
- package/cli/explorer/featureViews.js.map +1 -0
- package/cli/explorer/github.d.ts +21 -0
- package/cli/explorer/github.js +42 -44
- package/cli/explorer/github.js.map +1 -0
- package/cli/explorer/graphs.d.ts +7 -0
- package/cli/explorer/graphs.js +90 -95
- package/cli/explorer/graphs.js.map +1 -0
- package/cli/explorer/picker.d.ts +22 -0
- package/cli/explorer/picker.js +150 -0
- package/cli/explorer/picker.js.map +1 -0
- package/cli/explorer/report.d.ts +85 -0
- package/cli/explorer/report.js +60 -0
- package/cli/explorer/report.js.map +1 -0
- package/cli/explorer/session.d.ts +449 -0
- package/cli/explorer/session.js +143 -144
- package/cli/explorer/session.js.map +1 -0
- package/cli/explorer/views.d.ts +19 -0
- package/cli/explorer/views.js +465 -482
- package/cli/explorer/views.js.map +1 -0
- package/cli/explorer/wrap.d.ts +1 -0
- package/cli/explorer/wrap.js +28 -44
- package/cli/explorer/wrap.js.map +1 -0
- package/cli/main.d.ts +1 -0
- package/cli/main.js +214 -161
- package/cli/main.js.map +1 -0
- package/cli/prompt.d.ts +5 -0
- package/cli/prompt.js +84 -80
- package/cli/prompt.js.map +1 -0
- package/cli/scanOptions.d.ts +2 -0
- package/cli/scanOptions.js +11 -0
- package/cli/scanOptions.js.map +1 -0
- package/cli/ui.d.ts +33 -0
- package/cli/ui.js +35 -44
- package/cli/ui.js.map +1 -0
- package/cli/wizard.d.ts +187 -0
- package/cli/wizard.js +304 -284
- package/cli/wizard.js.map +1 -0
- package/package.json +15 -4
- package/public/app.d.ts +1 -0
- package/public/app.js +1057 -1009
- package/public/app.js.map +1 -0
- package/public/browser.d.ts +68 -0
- package/public/browser.js +2 -0
- package/public/browser.js.map +1 -0
- package/public/index.html +30 -13
- package/public/js/about.d.ts +6 -0
- package/public/js/about.js +152 -172
- package/public/js/about.js.map +1 -0
- package/public/js/aiDraft.d.ts +3 -0
- package/public/js/aiDraft.js +116 -124
- package/public/js/aiDraft.js.map +1 -0
- package/public/js/analysisPanel.d.ts +7 -0
- package/public/js/analysisPanel.js +166 -166
- package/public/js/analysisPanel.js.map +1 -0
- package/public/js/analysisReport.d.ts +38 -0
- package/public/js/analysisReport.js +105 -110
- package/public/js/analysisReport.js.map +1 -0
- package/public/js/api.d.ts +26 -0
- package/public/js/api.js +176 -167
- package/public/js/api.js.map +1 -0
- package/public/js/atlas.d.ts +6 -0
- package/public/js/atlas.js +50 -58
- package/public/js/atlas.js.map +1 -0
- package/public/js/blameView.d.ts +2 -0
- package/public/js/blameView.js +36 -37
- package/public/js/blameView.js.map +1 -0
- package/public/js/codeTab.d.ts +3 -0
- package/public/js/codeTab.js +175 -180
- package/public/js/codeTab.js.map +1 -0
- package/public/js/codeViewer.d.ts +5 -0
- package/public/js/codeViewer.js +162 -150
- package/public/js/codeViewer.js.map +1 -0
- package/public/js/components/FileChip.d.ts +9 -0
- package/public/js/components/FileChip.js +45 -49
- package/public/js/components/FileChip.js.map +1 -0
- package/public/js/components/MetricSparkline.d.ts +7 -0
- package/public/js/components/MetricSparkline.js +35 -44
- package/public/js/components/MetricSparkline.js.map +1 -0
- package/public/js/components/RiskBadge.d.ts +9 -0
- package/public/js/components/RiskBadge.js +55 -63
- package/public/js/components/RiskBadge.js.map +1 -0
- package/public/js/deepAnalysisView.d.ts +99 -0
- package/public/js/deepAnalysisView.js +282 -302
- package/public/js/deepAnalysisView.js.map +1 -0
- package/public/js/diagramPane.d.ts +8 -0
- package/public/js/diagramPane.js +133 -135
- package/public/js/diagramPane.js.map +1 -0
- package/public/js/diffView.d.ts +6 -0
- package/public/js/diffView.js +222 -209
- package/public/js/diffView.js.map +1 -0
- package/public/js/docsView.d.ts +2 -0
- package/public/js/docsView.js +441 -442
- package/public/js/docsView.js.map +1 -0
- package/public/js/dom.d.ts +189 -0
- package/public/js/dom.js +5 -0
- package/public/js/dom.js.map +1 -0
- package/public/js/fileSourceBrowser.d.ts +5 -0
- package/public/js/fileSourceBrowser.js +33 -41
- package/public/js/fileSourceBrowser.js.map +1 -0
- package/public/js/flameGraph.d.ts +5 -0
- package/public/js/flameGraph.js +62 -72
- package/public/js/flameGraph.js.map +1 -0
- package/public/js/forceGraph.d.ts +10 -0
- package/public/js/forceGraph.js +581 -556
- package/public/js/forceGraph.js.map +1 -0
- package/public/js/heatmap.d.ts +4 -0
- package/public/js/heatmap.js +142 -164
- package/public/js/heatmap.js.map +1 -0
- package/public/js/highlight.d.ts +2 -0
- package/public/js/highlight.js +116 -107
- package/public/js/highlight.js.map +1 -0
- package/public/js/html.d.ts +2 -0
- package/public/js/html.js +14 -44
- package/public/js/html.js.map +1 -0
- package/public/js/insightsView.d.ts +5 -0
- package/public/js/insightsView.js +93 -111
- package/public/js/insightsView.js.map +1 -0
- package/public/js/inspector.d.ts +37 -0
- package/public/js/inspector.js +416 -445
- package/public/js/inspector.js.map +1 -0
- package/public/js/llm.d.ts +113 -0
- package/public/js/llm.js +233 -272
- package/public/js/llm.js.map +1 -0
- package/public/js/mapView.d.ts +3 -0
- package/public/js/mapView.js +121 -120
- package/public/js/mapView.js.map +1 -0
- package/public/js/markdown.d.ts +3 -0
- package/public/js/markdown.js +84 -91
- package/public/js/markdown.js.map +1 -0
- package/public/js/mindmap.d.ts +32 -0
- package/public/js/mindmap.js +244 -259
- package/public/js/mindmap.js.map +1 -0
- package/public/js/mobilePanels.d.ts +5 -0
- package/public/js/mobilePanels.js +50 -0
- package/public/js/mobilePanels.js.map +1 -0
- package/public/js/repoFiles.d.ts +12 -0
- package/public/js/repoFiles.js +28 -27
- package/public/js/repoFiles.js.map +1 -0
- package/public/js/reviewView.d.ts +28 -0
- package/public/js/reviewView.js +256 -0
- package/public/js/reviewView.js.map +1 -0
- package/public/js/sbomView.d.ts +3 -0
- package/public/js/sbomView.js +59 -67
- package/public/js/sbomView.js.map +1 -0
- package/public/js/scanCache.d.ts +16 -0
- package/public/js/scanCache.js +67 -65
- package/public/js/scanCache.js.map +1 -0
- package/public/js/search.d.ts +7 -0
- package/public/js/search.js +868 -800
- package/public/js/search.js.map +1 -0
- package/public/js/searchLocal.d.ts +42 -0
- package/public/js/searchLocal.js +87 -0
- package/public/js/searchLocal.js.map +1 -0
- package/public/js/serverSettings.d.ts +5 -0
- package/public/js/serverSettings.js +153 -164
- package/public/js/serverSettings.js.map +1 -0
- package/public/js/state.d.ts +798 -0
- package/public/js/state.js +114 -122
- package/public/js/state.js.map +1 -0
- package/public/js/tour.d.ts +6 -0
- package/public/js/tour.js +5 -7
- package/public/js/tour.js.map +1 -0
- package/public/js/transitions.d.ts +2 -0
- package/public/js/transitions.js +9 -10
- package/public/js/transitions.js.map +1 -0
- package/public/js/tree.d.ts +12 -0
- package/public/js/tree.js +157 -154
- package/public/js/tree.js.map +1 -0
- package/public/js/workflowsView.d.ts +3 -0
- package/public/js/workflowsView.js +15 -22
- package/public/js/workflowsView.js.map +1 -0
- package/public/search.css +495 -0
- package/public/styles.css +163 -346
- package/public/workbench.css +166 -0
- package/server/apiAuth.d.ts +3 -0
- package/server/apiAuth.js +18 -20
- package/server/apiAuth.js.map +1 -0
- package/server/apiDiff.d.ts +2 -0
- package/server/apiDiff.js +20 -18
- package/server/apiDiff.js.map +1 -0
- package/server/apiDocs.d.ts +2 -0
- package/server/apiDocs.js +38 -40
- package/server/apiDocs.js.map +1 -0
- package/server/apiFile.d.ts +1 -0
- package/server/apiFile.js +14 -17
- package/server/apiFile.js.map +1 -0
- package/server/apiGitBlame.d.ts +2 -0
- package/server/apiGitBlame.js +50 -51
- package/server/apiGitBlame.js.map +1 -0
- package/server/apiMcp.d.ts +4 -0
- package/server/apiMcp.js +64 -66
- package/server/apiMcp.js.map +1 -0
- package/server/apiReview.d.ts +2 -0
- package/server/apiReview.js +45 -0
- package/server/apiReview.js.map +1 -0
- package/server/apiScan.d.ts +5 -0
- package/server/apiScan.js +90 -71
- package/server/apiScan.js.map +1 -0
- package/server/apiSearch.d.ts +33 -0
- package/server/apiSearch.js +184 -200
- package/server/apiSearch.js.map +1 -0
- package/server/apiSettings.d.ts +4 -0
- package/server/apiSettings.js +84 -85
- package/server/apiSettings.js.map +1 -0
- package/server/apiTools.d.ts +3 -0
- package/server/apiTools.js +55 -56
- package/server/apiTools.js.map +1 -0
- package/server/auth.d.ts +5 -0
- package/server/auth.js +54 -51
- package/server/auth.js.map +1 -0
- package/server/config.d.ts +42 -0
- package/server/config.js +189 -194
- package/server/config.js.map +1 -0
- package/server/daemon.d.ts +12 -0
- package/server/daemon.js +124 -114
- package/server/daemon.js.map +1 -0
- package/server/fileSourceNode.d.ts +2 -0
- package/server/fileSourceNode.js +34 -36
- package/server/fileSourceNode.js.map +1 -0
- package/server/gitClone.d.ts +9 -0
- package/server/gitClone.js +59 -61
- package/server/gitClone.js.map +1 -0
- package/server/gitDiff.d.ts +36 -0
- package/server/gitDiff.js +271 -169
- package/server/gitDiff.js.map +1 -0
- package/server/gitHistory.d.ts +12 -0
- package/server/gitHistory.js +80 -80
- package/server/gitHistory.js.map +1 -0
- package/server/gitRemote.d.ts +12 -0
- package/server/gitRemote.js +37 -38
- package/server/gitRemote.js.map +1 -0
- package/server/htmlText.d.ts +4 -0
- package/server/htmlText.js +16 -23
- package/server/htmlText.js.map +1 -0
- package/server/http.d.ts +5 -0
- package/server/http.js +27 -30
- package/server/http.js.map +1 -0
- package/server/httpGuards.d.ts +2 -0
- package/server/httpGuards.js +47 -43
- package/server/httpGuards.js.map +1 -0
- package/server/https.d.ts +34 -0
- package/server/https.js +121 -111
- package/server/https.js.map +1 -0
- package/server/index.d.ts +40 -0
- package/server/index.js +139 -147
- package/server/index.js.map +1 -0
- package/server/layout.d.ts +26 -0
- package/server/layout.js +59 -64
- package/server/layout.js.map +1 -0
- package/server/llmProxy.d.ts +3 -0
- package/server/llmProxy.js +137 -135
- package/server/llmProxy.js.map +1 -0
- package/server/logger.d.ts +38 -0
- package/server/logger.js +198 -211
- package/server/logger.js.map +1 -0
- package/server/mcp/analysis.d.ts +29 -0
- package/server/mcp/analysis.js +99 -120
- package/server/mcp/analysis.js.map +1 -0
- package/server/mcp/http.d.ts +9 -0
- package/server/mcp/http.js +128 -137
- package/server/mcp/http.js.map +1 -0
- package/server/mcp/runner.d.ts +68 -0
- package/server/mcp/runner.js +208 -218
- package/server/mcp/runner.js.map +1 -0
- package/server/mcp/server.d.ts +29 -0
- package/server/mcp/server.js +166 -179
- package/server/mcp/server.js.map +1 -0
- package/server/mcp/standalone.d.ts +1 -0
- package/server/mcp/standalone.js +8 -10
- package/server/mcp/standalone.js.map +1 -0
- package/server/mcp/tools.d.ts +2020 -0
- package/server/mcp/tools.js +523 -574
- package/server/mcp/tools.js.map +1 -0
- package/server/paths.d.ts +3 -0
- package/server/paths.js +17 -15
- package/server/paths.js.map +1 -0
- package/server/pidfile.d.ts +9 -0
- package/server/pidfile.js +43 -45
- package/server/pidfile.js.map +1 -0
- package/server/review.d.ts +5 -0
- package/server/review.js +35 -0
- package/server/review.js.map +1 -0
- package/server/router.d.ts +33 -0
- package/server/router.js +191 -197
- package/server/router.js.map +1 -0
- package/server/scanRequest.d.ts +3 -0
- package/server/scanRequest.js +36 -0
- package/server/scanRequest.js.map +1 -0
- package/server/searchIndex.d.ts +17 -0
- package/server/searchIndex.js +83 -80
- package/server/searchIndex.js.map +1 -0
- package/server/sessions.d.ts +14 -0
- package/server/sessions.js +62 -70
- package/server/sessions.js.map +1 -0
- package/server/startup.d.ts +118 -0
- package/server/startup.js +143 -148
- package/server/startup.js.map +1 -0
- package/server/static.d.ts +6 -0
- package/server/static.js +28 -31
- package/server/static.js.map +1 -0
- package/server/tools/install.d.ts +4 -0
- package/server/tools/install.js +176 -185
- package/server/tools/install.js.map +1 -0
- package/server/tools/parse.d.ts +8 -0
- package/server/tools/parse.js +112 -114
- package/server/tools/parse.js.map +1 -0
- package/server/tools/platform.d.ts +9 -0
- package/server/tools/platform.js +49 -47
- package/server/tools/platform.js.map +1 -0
- package/server/tools/registry.d.ts +137 -0
- package/server/tools/registry.js +173 -172
- package/server/tools/registry.js.map +1 -0
- package/server/tools/scan.d.ts +34 -0
- package/server/tools/scan.js +89 -98
- package/server/tools/scan.js.map +1 -0
- package/server/tools.d.ts +34 -0
- package/server/tools.js +94 -107
- package/server/tools.js.map +1 -0
- package/server/tunnel.d.ts +29 -0
- package/server/tunnel.js +61 -66
- package/server/tunnel.js.map +1 -0
- package/shared/analyzer/docs.d.ts +16 -0
- package/shared/analyzer/docs.js +99 -93
- package/shared/analyzer/docs.js.map +1 -0
- package/shared/analyzer/explainLocal.d.ts +4 -0
- package/shared/analyzer/explainLocal.js +122 -142
- package/shared/analyzer/explainLocal.js.map +1 -0
- package/shared/analyzer/github.d.ts +37 -0
- package/shared/analyzer/github.js +41 -43
- package/shared/analyzer/github.js.map +1 -0
- package/shared/analyzer/graph.d.ts +41 -0
- package/shared/analyzer/graph.js +393 -400
- package/shared/analyzer/graph.js.map +1 -0
- package/shared/analyzer/health.d.ts +33 -0
- package/shared/analyzer/health.js +197 -193
- package/shared/analyzer/health.js.map +1 -0
- package/shared/analyzer/history.d.ts +29 -0
- package/shared/analyzer/history.js +110 -111
- package/shared/analyzer/history.js.map +1 -0
- package/shared/analyzer/jsonConfig.d.ts +2 -0
- package/shared/analyzer/jsonConfig.js +61 -0
- package/shared/analyzer/jsonConfig.js.map +1 -0
- package/shared/analyzer/languages/csharp.d.ts +26 -0
- package/shared/analyzer/languages/csharp.js +83 -88
- package/shared/analyzer/languages/csharp.js.map +1 -0
- package/shared/analyzer/languages/generic.d.ts +23 -0
- package/shared/analyzer/languages/generic.js +94 -105
- package/shared/analyzer/languages/generic.js.map +1 -0
- package/shared/analyzer/languages/go.d.ts +24 -0
- package/shared/analyzer/languages/go.js +45 -54
- package/shared/analyzer/languages/go.js.map +1 -0
- package/shared/analyzer/languages/index.d.ts +6 -0
- package/shared/analyzer/languages/index.js +19 -20
- package/shared/analyzer/languages/index.js.map +1 -0
- package/shared/analyzer/languages/java.d.ts +20 -0
- package/shared/analyzer/languages/java.js +73 -78
- package/shared/analyzer/languages/java.js.map +1 -0
- package/shared/analyzer/languages/javascript.d.ts +12 -0
- package/shared/analyzer/languages/javascript.js +258 -209
- package/shared/analyzer/languages/javascript.js.map +1 -0
- package/shared/analyzer/languages/python.d.ts +23 -0
- package/shared/analyzer/languages/python.js +92 -100
- package/shared/analyzer/languages/python.js.map +1 -0
- package/shared/analyzer/languages/rust.d.ts +17 -0
- package/shared/analyzer/languages/rust.js +96 -98
- package/shared/analyzer/languages/rust.js.map +1 -0
- package/shared/analyzer/languages/typescript.d.ts +11 -0
- package/shared/analyzer/languages/typescript.js +117 -116
- package/shared/analyzer/languages/typescript.js.map +1 -0
- package/shared/analyzer/licenses.d.ts +18 -0
- package/shared/analyzer/licenses.js +130 -133
- package/shared/analyzer/licenses.js.map +1 -0
- package/shared/analyzer/metrics.d.ts +20 -0
- package/shared/analyzer/metrics.js +112 -104
- package/shared/analyzer/metrics.js.map +1 -0
- package/shared/analyzer/pathUtil.d.ts +10 -0
- package/shared/analyzer/pathUtil.js +29 -35
- package/shared/analyzer/pathUtil.js.map +1 -0
- package/shared/analyzer/patterns.d.ts +11 -0
- package/shared/analyzer/patterns.js +231 -253
- package/shared/analyzer/patterns.js.map +1 -0
- package/shared/analyzer/scan.d.ts +62 -0
- package/shared/analyzer/scan.js +451 -442
- package/shared/analyzer/scan.js.map +1 -0
- package/shared/analyzer/scanControl.d.ts +11 -0
- package/shared/analyzer/scanControl.js +62 -0
- package/shared/analyzer/scanControl.js.map +1 -0
- package/shared/analyzer/security.d.ts +18 -0
- package/shared/analyzer/security.js +159 -159
- package/shared/analyzer/security.js.map +1 -0
- package/shared/analyzer/services.d.ts +5 -0
- package/shared/analyzer/services.js +141 -138
- package/shared/analyzer/services.js.map +1 -0
- package/shared/analyzer/stack.d.ts +6 -0
- package/shared/analyzer/stack.js +134 -141
- package/shared/analyzer/stack.js.map +1 -0
- package/shared/analyzer/tour.d.ts +2 -0
- package/shared/analyzer/tour.js +45 -53
- package/shared/analyzer/tour.js.map +1 -0
- package/shared/analyzer/util.d.ts +8 -0
- package/shared/analyzer/util.js +130 -76
- package/shared/analyzer/util.js.map +1 -0
- package/shared/analyzer/workflows.d.ts +8 -0
- package/shared/analyzer/workflows.js +139 -134
- package/shared/analyzer/workflows.js.map +1 -0
- package/shared/contracts.d.ts +250 -0
- package/shared/contracts.js +2 -0
- package/shared/contracts.js.map +1 -0
- package/shared/diagram/aiFacts.d.ts +35 -0
- package/shared/diagram/aiFacts.js +102 -105
- package/shared/diagram/aiFacts.js.map +1 -0
- package/shared/diagram/aiMermaid.d.ts +5 -0
- package/shared/diagram/aiMermaid.js +46 -45
- package/shared/diagram/aiMermaid.js.map +1 -0
- package/shared/diagram/atlas.d.ts +16 -0
- package/shared/diagram/atlas.js +51 -60
- package/shared/diagram/atlas.js.map +1 -0
- package/shared/diagram/mermaid.d.ts +43 -0
- package/shared/diagram/mermaid.js +348 -370
- package/shared/diagram/mermaid.js.map +1 -0
- package/shared/review/contracts.d.ts +95 -0
- package/shared/review/contracts.js +2 -0
- package/shared/review/contracts.js.map +1 -0
- package/shared/review/review.d.ts +10 -0
- package/shared/review/review.js +184 -0
- package/shared/review/review.js.map +1 -0
- package/shared/search/query.d.ts +32 -0
- package/shared/search/query.js +395 -388
- package/shared/search/query.js.map +1 -0
package/server/llmProxy.js
CHANGED
|
@@ -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
|
-
|
|
14
|
-
|
|
15
|
-
|
|
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
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
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
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
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
|
-
|
|
67
|
-
|
|
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
|
-
|
|
87
|
-
|
|
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
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
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
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
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
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
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
|
-
|
|
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
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
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
|
-
|
|
161
|
-
|
|
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
|
+
};
|