onbuzz 4.9.13 → 4.10.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/node_modules/glob/README.md +31 -5
- package/node_modules/glob/dist/commonjs/glob.d.ts +8 -0
- package/node_modules/glob/dist/commonjs/glob.d.ts.map +1 -1
- package/node_modules/glob/dist/commonjs/glob.js +2 -1
- package/node_modules/glob/dist/commonjs/glob.js.map +1 -1
- package/node_modules/glob/dist/commonjs/index.min.js +3 -3
- package/node_modules/glob/dist/commonjs/index.min.js.map +4 -4
- package/node_modules/glob/dist/commonjs/pattern.d.ts +3 -0
- package/node_modules/glob/dist/commonjs/pattern.d.ts.map +1 -1
- package/node_modules/glob/dist/commonjs/pattern.js +4 -0
- package/node_modules/glob/dist/commonjs/pattern.js.map +1 -1
- package/node_modules/glob/dist/esm/glob.d.ts +8 -0
- package/node_modules/glob/dist/esm/glob.d.ts.map +1 -1
- package/node_modules/glob/dist/esm/glob.js +2 -1
- package/node_modules/glob/dist/esm/glob.js.map +1 -1
- package/node_modules/glob/dist/esm/index.min.js +3 -3
- package/node_modules/glob/dist/esm/index.min.js.map +4 -4
- package/node_modules/glob/dist/esm/pattern.d.ts +3 -0
- package/node_modules/glob/dist/esm/pattern.d.ts.map +1 -1
- package/node_modules/glob/dist/esm/pattern.js +4 -0
- package/node_modules/glob/dist/esm/pattern.js.map +1 -1
- package/node_modules/{@isaacs → glob/node_modules}/balanced-match/README.md +7 -10
- package/node_modules/{@isaacs → glob/node_modules}/balanced-match/package.json +7 -18
- package/node_modules/{@isaacs → glob/node_modules}/brace-expansion/README.md +3 -6
- package/node_modules/{@isaacs → glob/node_modules}/brace-expansion/dist/commonjs/index.js +6 -4
- package/node_modules/glob/node_modules/brace-expansion/dist/commonjs/index.js.map +1 -0
- package/node_modules/{@isaacs → glob/node_modules}/brace-expansion/dist/esm/index.js +6 -4
- package/node_modules/glob/node_modules/brace-expansion/dist/esm/index.js.map +1 -0
- package/node_modules/{@isaacs → glob/node_modules}/brace-expansion/package.json +11 -7
- package/node_modules/glob/node_modules/minimatch/README.md +76 -1
- package/node_modules/glob/node_modules/minimatch/dist/commonjs/assert-valid-pattern.d.ts +1 -1
- package/node_modules/glob/node_modules/minimatch/dist/commonjs/assert-valid-pattern.d.ts.map +1 -1
- package/node_modules/glob/node_modules/minimatch/dist/commonjs/assert-valid-pattern.js.map +1 -1
- package/node_modules/glob/node_modules/minimatch/dist/commonjs/ast.d.ts +4 -2
- package/node_modules/glob/node_modules/minimatch/dist/commonjs/ast.d.ts.map +1 -1
- package/node_modules/glob/node_modules/minimatch/dist/commonjs/ast.js +309 -55
- package/node_modules/glob/node_modules/minimatch/dist/commonjs/ast.js.map +1 -1
- package/node_modules/glob/node_modules/minimatch/dist/commonjs/brace-expressions.d.ts.map +1 -1
- package/node_modules/glob/node_modules/minimatch/dist/commonjs/brace-expressions.js +2 -4
- package/node_modules/glob/node_modules/minimatch/dist/commonjs/brace-expressions.js.map +1 -1
- package/node_modules/glob/node_modules/minimatch/dist/commonjs/escape.d.ts +1 -1
- package/node_modules/glob/node_modules/minimatch/dist/commonjs/escape.d.ts.map +1 -1
- package/node_modules/glob/node_modules/minimatch/dist/commonjs/escape.js +4 -4
- package/node_modules/glob/node_modules/minimatch/dist/commonjs/escape.js.map +1 -1
- package/node_modules/glob/node_modules/minimatch/dist/commonjs/index.d.ts +81 -1
- package/node_modules/glob/node_modules/minimatch/dist/commonjs/index.d.ts.map +1 -1
- package/node_modules/glob/node_modules/minimatch/dist/commonjs/index.js +232 -134
- package/node_modules/glob/node_modules/minimatch/dist/commonjs/index.js.map +1 -1
- package/node_modules/glob/node_modules/minimatch/dist/commonjs/unescape.d.ts +1 -1
- package/node_modules/glob/node_modules/minimatch/dist/commonjs/unescape.d.ts.map +1 -1
- package/node_modules/glob/node_modules/minimatch/dist/commonjs/unescape.js +8 -8
- package/node_modules/glob/node_modules/minimatch/dist/commonjs/unescape.js.map +1 -1
- package/node_modules/glob/node_modules/minimatch/dist/esm/assert-valid-pattern.d.ts +1 -1
- package/node_modules/glob/node_modules/minimatch/dist/esm/assert-valid-pattern.d.ts.map +1 -1
- package/node_modules/glob/node_modules/minimatch/dist/esm/assert-valid-pattern.js.map +1 -1
- package/node_modules/glob/node_modules/minimatch/dist/esm/ast.d.ts +4 -2
- package/node_modules/glob/node_modules/minimatch/dist/esm/ast.d.ts.map +1 -1
- package/node_modules/glob/node_modules/minimatch/dist/esm/ast.js +309 -55
- package/node_modules/glob/node_modules/minimatch/dist/esm/ast.js.map +1 -1
- package/node_modules/glob/node_modules/minimatch/dist/esm/brace-expressions.d.ts.map +1 -1
- package/node_modules/glob/node_modules/minimatch/dist/esm/brace-expressions.js +2 -4
- package/node_modules/glob/node_modules/minimatch/dist/esm/brace-expressions.js.map +1 -1
- package/node_modules/glob/node_modules/minimatch/dist/esm/escape.d.ts +1 -1
- package/node_modules/glob/node_modules/minimatch/dist/esm/escape.d.ts.map +1 -1
- package/node_modules/glob/node_modules/minimatch/dist/esm/escape.js +4 -4
- package/node_modules/glob/node_modules/minimatch/dist/esm/escape.js.map +1 -1
- package/node_modules/glob/node_modules/minimatch/dist/esm/index.d.ts +81 -1
- package/node_modules/glob/node_modules/minimatch/dist/esm/index.d.ts.map +1 -1
- package/node_modules/glob/node_modules/minimatch/dist/esm/index.js +232 -134
- package/node_modules/glob/node_modules/minimatch/dist/esm/index.js.map +1 -1
- package/node_modules/glob/node_modules/minimatch/dist/esm/unescape.d.ts +1 -1
- package/node_modules/glob/node_modules/minimatch/dist/esm/unescape.d.ts.map +1 -1
- package/node_modules/glob/node_modules/minimatch/dist/esm/unescape.js +8 -8
- package/node_modules/glob/node_modules/minimatch/dist/esm/unescape.js.map +1 -1
- package/node_modules/glob/node_modules/minimatch/package.json +17 -11
- package/node_modules/glob/package.json +10 -13
- package/node_modules/minipass/LICENSE.md +55 -0
- package/node_modules/minipass/dist/commonjs/index.d.ts +12 -16
- package/node_modules/minipass/dist/commonjs/index.d.ts.map +1 -1
- package/node_modules/minipass/dist/commonjs/index.js +13 -3
- package/node_modules/minipass/dist/commonjs/index.js.map +1 -1
- package/node_modules/minipass/dist/esm/index.d.ts +12 -16
- package/node_modules/minipass/dist/esm/index.d.ts.map +1 -1
- package/node_modules/minipass/dist/esm/index.js +3 -1
- package/node_modules/minipass/dist/esm/index.js.map +1 -1
- package/node_modules/minipass/package.json +9 -14
- package/node_modules/path-scurry/node_modules/lru-cache/README.md +96 -10
- package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/browser/diagnostics-channel-browser.d.ts.map +1 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/browser/diagnostics-channel-browser.js.map +1 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/browser/diagnostics-channel.d.ts +5 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/browser/diagnostics-channel.js +7 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/browser/index.d.ts +1400 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/browser/index.d.ts.map +1 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/browser/index.js +1726 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/browser/index.js.map +1 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/browser/index.min.js +2 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/browser/index.min.js.map +7 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/browser/perf.d.ts +12 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/browser/perf.d.ts.map +1 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/browser/perf.js +10 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/browser/perf.js.map +1 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/diagnostics-channel-cjs.cjs.map +1 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/diagnostics-channel-cjs.d.cts.map +1 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/diagnostics-channel.d.ts +5 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/diagnostics-channel.js +7 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/index.d.ts +109 -32
- package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/index.d.ts.map +1 -1
- package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/index.js +334 -197
- package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/index.js.map +1 -1
- package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/index.min.js +1 -1
- package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/index.min.js.map +4 -4
- package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/node/diagnostics-channel-node.d.ts.map +1 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/node/diagnostics-channel-node.js.map +1 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/node/diagnostics-channel.d.ts +5 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/node/diagnostics-channel.js +9 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/node/index.d.ts +1400 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/node/index.d.ts.map +1 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/node/index.js +1726 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/node/index.js.map +1 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/node/index.min.js +2 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/node/index.min.js.map +7 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/node/perf.d.ts +12 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/node/perf.d.ts.map +1 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/node/perf.js +10 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/node/perf.js.map +1 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/perf.d.ts +12 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/perf.d.ts.map +1 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/perf.js +10 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/perf.js.map +1 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/browser/diagnostics-channel-browser.d.ts.map +1 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/browser/diagnostics-channel-browser.js.map +1 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/browser/diagnostics-channel.d.ts +5 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/browser/diagnostics-channel.js +4 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/browser/index.d.ts +1400 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/browser/index.d.ts.map +1 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/browser/index.js +1722 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/browser/index.js.map +1 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/browser/index.min.js +2 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/browser/index.min.js.map +7 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/browser/perf.d.ts +12 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/browser/perf.d.ts.map +1 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/browser/perf.js +7 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/browser/perf.js.map +1 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/diagnostics-channel-esm.d.mts.map +1 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/diagnostics-channel-esm.mjs.map +1 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/diagnostics-channel.d.ts +5 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/diagnostics-channel.js +19 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/index.d.ts +109 -32
- package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/index.d.ts.map +1 -1
- package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/index.js +333 -196
- package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/index.js.map +1 -1
- package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/index.min.js +1 -1
- package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/index.min.js.map +4 -4
- package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/node/diagnostics-channel-node.d.ts.map +1 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/node/diagnostics-channel-node.js.map +1 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/node/diagnostics-channel.d.ts +5 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/node/diagnostics-channel.js +6 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/node/index.d.ts +1400 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/node/index.d.ts.map +1 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/node/index.js +1722 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/node/index.js.map +1 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/node/index.min.js +2 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/node/index.min.js.map +7 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/node/perf.d.ts +12 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/node/perf.d.ts.map +1 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/node/perf.js +7 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/node/perf.js.map +1 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/perf.d.ts +12 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/perf.d.ts.map +1 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/perf.js +7 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/perf.js.map +1 -0
- package/node_modules/path-scurry/node_modules/lru-cache/package.json +71 -18
- package/node_modules/path-scurry/package.json +8 -24
- package/package.json +1 -1
- package/scripts/debug-balance-probe.mjs +35 -35
- package/scripts/push-image.sh +43 -43
- package/scripts/setup-acr.sh +65 -65
- package/scripts/verify-optional-deps.js +96 -1
- package/src/__tests__/composioCliFlags.test.js +239 -239
- package/src/analyzers/CSSAnalyzer.js +298 -297
- package/src/analyzers/ConfigValidator.js +691 -690
- package/src/analyzers/ESLintAnalyzer.js +320 -320
- package/src/analyzers/JavaScriptAnalyzer.js +260 -261
- package/src/analyzers/PrettierFormatter.js +246 -247
- package/src/analyzers/PythonAnalyzer.js +283 -283
- package/src/analyzers/SecurityAnalyzer.js +729 -729
- package/src/analyzers/SparrowAnalyzer.js +341 -341
- package/src/analyzers/TypeScriptAnalyzer.js +247 -247
- package/src/analyzers/__tests__/CSSAnalyzer.test.js +41 -41
- package/src/analyzers/__tests__/ConfigValidator.test.js +362 -362
- package/src/analyzers/__tests__/JavaScriptAnalyzer.test.js +40 -40
- package/src/analyzers/__tests__/PythonAnalyzer.test.js +205 -208
- package/src/analyzers/__tests__/SecurityAnalyzer.test.js +303 -303
- package/src/analyzers/__tests__/TypeScriptAnalyzer.test.js +187 -187
- package/src/analyzers/codeCloneDetector/analyzer.js +344 -344
- package/src/analyzers/codeCloneDetector/detector.js +250 -250
- package/src/analyzers/codeCloneDetector/index.js +194 -192
- package/src/analyzers/codeCloneDetector/parser.js +199 -199
- package/src/core/__tests__/agentPool.test.js +866 -866
- package/src/core/__tests__/agentPoolAutoResume.test.js +209 -209
- package/src/core/__tests__/agentPoolWakeOnMessage.test.js +315 -315
- package/src/core/__tests__/agentScheduler.emptyResponseChatStall.test.js +213 -213
- package/src/core/__tests__/agentScheduler.errorCategorisation.test.js +246 -246
- package/src/core/__tests__/agentScheduler.firstChunkTimeout.test.js +138 -138
- package/src/core/__tests__/agentScheduler.modeTransitions.test.js +233 -233
- package/src/core/__tests__/agentScheduler.nativePromptPick.test.js +319 -319
- package/src/core/__tests__/agentScheduler.taskLifecycleInstruction.test.js +78 -78
- package/src/core/__tests__/agentScheduler.visualizer.test.js +258 -258
- package/src/core/__tests__/flowCheckpointStore.test.js +140 -140
- package/src/core/__tests__/flowEndToEnd.test.js +565 -565
- package/src/core/__tests__/flowFieldMapping.test.js +188 -189
- package/src/core/__tests__/flowLintClientMirror.test.js +96 -98
- package/src/core/__tests__/flowSavePayload.test.js +170 -169
- package/src/core/__tests__/flowTemplates.test.js +311 -311
- package/src/core/__tests__/flowVersionStore.test.js +123 -123
- package/src/core/__tests__/messageProcessor.test.js +669 -669
- package/src/core/__tests__/stateManager.test.js +0 -1
- package/src/core/agentPool.js +2474 -2475
- package/src/core/agentScheduler.js +1 -4
- package/src/core/contextManager.js +708 -708
- package/src/core/flowExecutor.js +1510 -1510
- package/src/core/flowFieldMapping.js +136 -138
- package/src/core/messageProcessor.js +953 -954
- package/src/core/orchestrator.js +593 -595
- package/src/core/stateManager.js +1765 -1752
- package/src/index.js +1221 -1221
- package/src/interfaces/__tests__/archivedAgentDelete.test.js +207 -207
- package/src/interfaces/__tests__/bulkAgentRoute.test.js +361 -361
- package/src/interfaces/__tests__/imageServing.test.js +228 -228
- package/src/interfaces/__tests__/remoteSessionAuth.test.js +308 -308
- package/src/interfaces/__tests__/videoJobsRoutes.test.js +178 -179
- package/src/interfaces/__tests__/webServer.marketplace.test.js +629 -629
- package/src/interfaces/schedulerRoutes.js +50 -50
- package/src/interfaces/terminal/__tests__/smoke/connection.test.js +341 -350
- package/src/interfaces/terminal/__tests__/smoke/enhancements.test.js +156 -156
- package/src/interfaces/terminal/__tests__/smoke/imports.test.js +325 -330
- package/src/interfaces/terminal/__tests__/smoke/tools.test.js +385 -388
- package/src/interfaces/terminal/api/session.js +265 -266
- package/src/interfaces/terminal/api/websocket.js +496 -497
- package/src/interfaces/terminal/components/AgentCreator.js +691 -705
- package/src/interfaces/terminal/components/AgentEditor.js +676 -678
- package/src/interfaces/terminal/components/AgentSwitcher.js +331 -330
- package/src/interfaces/terminal/components/ErrorPanel.js +263 -264
- package/src/interfaces/terminal/components/Header.js +28 -28
- package/src/interfaces/terminal/components/Layout.js +598 -603
- package/src/interfaces/terminal/components/MessageList.js +280 -281
- package/src/interfaces/terminal/components/SettingsPanel.js +410 -415
- package/src/interfaces/terminal/components/StatusBar.js +2 -0
- package/src/interfaces/terminal/index.js +168 -168
- package/src/interfaces/terminal/state/useAgentControl.js +496 -496
- package/src/interfaces/terminal/state/useAgents.js +537 -537
- package/src/interfaces/terminal/state/useMessages.js +629 -630
- package/src/interfaces/terminal/state/useTools.js +554 -554
- package/src/interfaces/terminal/utils/debugLogger.js +44 -44
- package/src/interfaces/terminal/utils/settingsStorage.js +232 -232
- package/src/interfaces/webServer.js +7578 -7579
- package/src/interfaces/webServer.js.bak +7046 -7046
- package/src/modules/fileExplorer/__tests__/zipDownload.test.js +237 -237
- package/src/modules/fileExplorer/controller.js +470 -469
- package/src/modules/fileExplorer/routes.js +285 -286
- package/src/modules/widget/__tests__/isDisabled.test.js +41 -41
- package/src/modules/widget/__tests__/routes.test.js +677 -678
- package/src/modules/widget/__tests__/runtime.test.js +401 -401
- package/src/modules/widget/__tests__/versioning.test.js +309 -309
- package/src/modules/widget/__tests__/webComponentRuntime.test.js +565 -565
- package/src/modules/widget/__tests__/widgetTool.test.js +316 -316
- package/src/modules/widget/routes.js +435 -435
- package/src/modules/widget/runtime/bundle.js +640 -640
- package/src/modules/widget/runtime/webComponentBundle.js +470 -470
- package/src/modules/widget/schema.js +182 -181
- package/src/modules/widget/widgetTool.js +1389 -1389
- package/src/services/__tests__/agentActivityService.test.js +401 -402
- package/src/services/__tests__/benchmarkService.test.js +184 -184
- package/src/services/__tests__/contextInjectionService.test.js +246 -246
- package/src/services/__tests__/conversationQuery.test.js +721 -723
- package/src/services/__tests__/credentialVault.test.js +469 -469
- package/src/services/__tests__/discordService.integration.test.js +638 -639
- package/src/services/__tests__/flowContextService.test.js +590 -590
- package/src/services/__tests__/memoryService.test.js +1 -1
- package/src/services/__tests__/messageSource.test.js +380 -380
- package/src/services/__tests__/modelRouterNaming.test.js +111 -111
- package/src/services/__tests__/projectDetector.test.js +34 -34
- package/src/services/__tests__/promptService.test.js +242 -242
- package/src/services/__tests__/telegramService.test.js +941 -941
- package/src/services/__tests__/tokenCountingService.test.js +48 -48
- package/src/services/agentActivityService.js +419 -420
- package/src/services/aiService.js +2997 -3001
- package/src/services/apiKeyManager.js +359 -359
- package/src/services/benchmarkService.js +196 -196
- package/src/services/codebaseKnowledgeService.js +2 -2
- package/src/services/composioService.js +738 -738
- package/src/services/conversationCompactionService.js +1258 -1257
- package/src/services/credentialVault.js +685 -685
- package/src/services/discordService.js +792 -793
- package/src/services/embeddings/__tests__/azureCustomProvider.test.js +232 -232
- package/src/services/embeddings/__tests__/embeddingService.test.js +417 -417
- package/src/services/embeddings/__tests__/localProvider.test.js +263 -263
- package/src/services/embeddings/autoRecall.js +218 -219
- package/src/services/embeddings/indexers/__tests__/agentIndexer.test.js +232 -232
- package/src/services/embeddings/indexers/__tests__/memoryIndexer.test.js +418 -418
- package/src/services/embeddings/indexers/__tests__/reminisceIndexer.test.js +356 -357
- package/src/services/embeddings/indexers/__tests__/skillsIndexer.test.js +145 -145
- package/src/services/embeddings/indexers/__tests__/taskIndexer.test.js +146 -146
- package/src/services/embeddings/indexers/composioIndexer.js +279 -279
- package/src/services/embeddings/providerInterface.js +206 -206
- package/src/services/embeddings/providers/localProvider.js +11 -7
- package/src/services/embeddings/providers/openaiProvider.js +101 -101
- package/src/services/embeddings/vectorStore/inMemoryJsonStore.js +356 -356
- package/src/services/errorHandler.js +809 -809
- package/src/services/flowContextService.js +586 -586
- package/src/services/grounding/MockAdapter.js +125 -125
- package/src/services/modelRouterService.js +26 -31
- package/src/services/modelsService.js +322 -322
- package/src/services/ollamaService.js +452 -452
- package/src/services/projectDetector.js +403 -404
- package/src/services/promptService.js +418 -418
- package/src/services/qualityInspector.js +795 -795
- package/src/services/scheduleService.js +726 -726
- package/src/services/serviceRegistry.js +386 -386
- package/src/services/telegrafBot.js +174 -174
- package/src/services/telegramService.js +1972 -1972
- package/src/services/visualEditorBridge.js +1033 -1033
- package/src/services/visualEditorServer.js +1769 -1774
- package/src/services/whatsappService.js +667 -668
- package/src/tools/__tests__/agentCommunicationTool.findAgent.test.js +226 -226
- package/src/tools/__tests__/agentCommunicationTool.test.js +3 -3
- package/src/tools/__tests__/agentDelayTool.test.js +342 -342
- package/src/tools/__tests__/baseTool.test.js +3 -3
- package/src/tools/__tests__/codeMapTool.test.js +915 -915
- package/src/tools/__tests__/fileContentReplaceTool.test.js +309 -309
- package/src/tools/__tests__/fileTreeTool.test.js +274 -274
- package/src/tools/__tests__/filesystemTool.test.js +815 -815
- package/src/tools/__tests__/foundryWebSearchTool.test.js +252 -252
- package/src/tools/__tests__/imageTool.validator.test.js +194 -194
- package/src/tools/__tests__/jobDoneTool.test.js +580 -581
- package/src/tools/__tests__/memoryTool.forgetStale.test.js +272 -272
- package/src/tools/__tests__/memoryTool.reminisce.test.js +2 -2
- package/src/tools/__tests__/memoryTool.reminisceSemanticSearch.test.js +301 -301
- package/src/tools/__tests__/memoryTool.semanticSearch.test.js +405 -405
- package/src/tools/__tests__/memoryTool.teamPool.test.js +293 -293
- package/src/tools/__tests__/memoryTool.test.js +1 -1
- package/src/tools/__tests__/seekTool.test.js +282 -282
- package/src/tools/__tests__/skillsTool.search.test.js +164 -164
- package/src/tools/__tests__/skillsTool.test.js +226 -226
- package/src/tools/__tests__/staticAnalysisTool.test.js +509 -509
- package/src/tools/__tests__/taskManagerTool.discipline.test.js +137 -137
- package/src/tools/__tests__/taskManagerTool.search.test.js +143 -143
- package/src/tools/__tests__/taskManagerTool.test.js +866 -866
- package/src/tools/__tests__/terminalTool.test.js +448 -448
- package/src/tools/__tests__/toolShapeForgiveness.test.js +259 -260
- package/src/tools/__tests__/userPromptTool.test.js +297 -297
- package/src/tools/__tests__/videoTool.jobs.test.js +147 -147
- package/src/tools/__tests__/webTool.e2e.test.js +609 -603
- package/src/tools/__tests__/webTool.unit.test.js +195 -195
- package/src/tools/__tests__/webTool.visionModel.test.js +75 -75
- package/src/tools/agentCommunicationTool.js +8 -10
- package/src/tools/agentDelayTool.js +496 -497
- package/src/tools/asyncToolManager.js +602 -603
- package/src/tools/baseTool.js +12 -11
- package/src/tools/cloneDetectionTool.js +576 -581
- package/src/tools/codeMapTool.js +0 -6
- package/src/tools/composioTool.js +617 -617
- package/src/tools/dependencyResolverTool.js +1211 -1212
- package/src/tools/desktop/DesktopTool.js +629 -638
- package/src/tools/desktop/__tests__/DesktopTool.e2e.test.js +306 -306
- package/src/tools/desktop/__tests__/DesktopTool.test.js +507 -507
- package/src/tools/desktop/__tests__/osController.test.js +364 -364
- package/src/tools/desktop/osController.js +491 -491
- package/src/tools/docxTool.js +623 -623
- package/src/tools/excelTool.js +636 -636
- package/src/tools/fileContentReplaceTool.js +5 -7
- package/src/tools/fileSystemTool.js +12 -19
- package/src/tools/fileTreeTool.js +840 -840
- package/src/tools/foundryWebSearchTool.js +273 -273
- package/src/tools/helpTool.js +198 -198
- package/src/tools/imageTool.js +1397 -1397
- package/src/tools/importAnalyzerTool.js +1056 -1056
- package/src/tools/jobDoneTool.js +495 -495
- package/src/tools/memoryTool.js +1 -1
- package/src/tools/office/pres/__tests__/presSystem.test.js +365 -365
- package/src/tools/office/pres/archetypes/agenda.js +61 -61
- package/src/tools/office/pres/archetypes/bentoGrid.js +218 -219
- package/src/tools/office/pres/archetypes/bigStat.js +140 -142
- package/src/tools/office/pres/archetypes/closing.js +70 -70
- package/src/tools/office/pres/archetypes/hero.js +70 -70
- package/src/tools/office/pres/archetypes/productHero.js +93 -94
- package/src/tools/office/pres/archetypes/table.js +73 -74
- package/src/tools/office/pres/backgrounds/orb.js +66 -66
- package/src/tools/office/pres/components.js +422 -423
- package/src/tools/officeTool.js +441 -441
- package/src/tools/pdfTool.js +625 -627
- package/src/tools/platformControlTool.js +1081 -1081
- package/src/tools/seekTool.js +917 -918
- package/src/tools/skillsTool.js +1 -1
- package/src/tools/staticAnalysisTool.js +2143 -2146
- package/src/tools/taskManagerTool.js +3324 -3324
- package/src/tools/terminalTool.js +2615 -2618
- package/src/tools/videoTool.js +1303 -1303
- package/src/tools/visionTool.js +508 -508
- package/src/tools/visualEditorTool.js +1289 -1290
- package/src/tools/webTool.js +3368 -3368
- package/src/tools/whatsappTool.js +464 -464
- package/src/types/__tests__/agent.test.js +499 -499
- package/src/types/__tests__/contextReference.test.js +606 -606
- package/src/types/__tests__/conversation.test.js +555 -555
- package/src/types/__tests__/toolCommand.test.js +584 -584
- package/src/types/contextReference.js +974 -971
- package/src/types/conversation.js +729 -729
- package/src/types/toolCommand.js +746 -746
- package/src/utilities/__tests__/attachmentValidator.test.js +80 -80
- package/src/utilities/__tests__/auditReport.test.js +328 -328
- package/src/utilities/__tests__/directoryAccessManager.test.js +388 -388
- package/src/utilities/__tests__/jsonRepair.test.js +103 -104
- package/src/utilities/__tests__/modeTransitionReasons.test.js +105 -105
- package/src/utilities/__tests__/platformUtils.test.js +80 -87
- package/src/utilities/__tests__/structuredFileValidator.test.js +261 -263
- package/src/utilities/__tests__/toolConstants.test.js +92 -94
- package/src/utilities/__tests__/useIsTouchDevice.detect.test.js +114 -114
- package/src/utilities/__tests__/webUiUtilSync.test.js +117 -117
- package/src/utilities/attachmentValidator.js +284 -288
- package/src/utilities/authCache.js.backup-1779570472481 +121 -121
- package/src/utilities/browserStealth.js +631 -630
- package/src/utilities/configManager.js +616 -617
- package/src/utilities/directoryAccessManager.js +564 -565
- package/src/utilities/fileProcessor.js +308 -307
- package/src/utilities/humanBehavior.js +454 -453
- package/src/utilities/logger.js +479 -479
- package/src/utilities/structuredFileValidator.js +696 -699
- package/src/utilities/tagParser.js +5 -10
- package/src/utilities/userDataDir.js +308 -308
- package/node_modules/@isaacs/brace-expansion/dist/commonjs/index.js.map +0 -1
- package/node_modules/@isaacs/brace-expansion/dist/esm/index.js.map +0 -1
- package/node_modules/minipass/LICENSE +0 -15
- /package/node_modules/{@isaacs → glob/node_modules}/balanced-match/LICENSE.md +0 -0
- /package/node_modules/{@isaacs → glob/node_modules}/balanced-match/dist/commonjs/index.d.ts +0 -0
- /package/node_modules/{@isaacs → glob/node_modules}/balanced-match/dist/commonjs/index.d.ts.map +0 -0
- /package/node_modules/{@isaacs → glob/node_modules}/balanced-match/dist/commonjs/index.js +0 -0
- /package/node_modules/{@isaacs → glob/node_modules}/balanced-match/dist/commonjs/index.js.map +0 -0
- /package/node_modules/{@isaacs → glob/node_modules}/balanced-match/dist/commonjs/package.json +0 -0
- /package/node_modules/{@isaacs → glob/node_modules}/balanced-match/dist/esm/index.d.ts +0 -0
- /package/node_modules/{@isaacs → glob/node_modules}/balanced-match/dist/esm/index.d.ts.map +0 -0
- /package/node_modules/{@isaacs → glob/node_modules}/balanced-match/dist/esm/index.js +0 -0
- /package/node_modules/{@isaacs → glob/node_modules}/balanced-match/dist/esm/index.js.map +0 -0
- /package/node_modules/{@isaacs → glob/node_modules}/balanced-match/dist/esm/package.json +0 -0
- /package/node_modules/{@isaacs → glob/node_modules}/brace-expansion/LICENSE +0 -0
- /package/node_modules/{@isaacs → glob/node_modules}/brace-expansion/dist/commonjs/index.d.ts +0 -0
- /package/node_modules/{@isaacs → glob/node_modules}/brace-expansion/dist/commonjs/index.d.ts.map +0 -0
- /package/node_modules/{@isaacs → glob/node_modules}/brace-expansion/dist/commonjs/package.json +0 -0
- /package/node_modules/{@isaacs → glob/node_modules}/brace-expansion/dist/esm/index.d.ts +0 -0
- /package/node_modules/{@isaacs → glob/node_modules}/brace-expansion/dist/esm/index.d.ts.map +0 -0
- /package/node_modules/{@isaacs → glob/node_modules}/brace-expansion/dist/esm/package.json +0 -0
|
@@ -1,359 +1,359 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* API Key Manager - Persistent API key storage
|
|
3
|
-
*
|
|
4
|
-
* Purpose:
|
|
5
|
-
* - Store API keys with encrypted persistence to disk
|
|
6
|
-
* - Manage both platform (Loxia) and vendor-specific keys
|
|
7
|
-
* - Provide keys to AI services based on model requirements
|
|
8
|
-
* - Survive backend restarts by loading persisted keys
|
|
9
|
-
*
|
|
10
|
-
* Note: API keys are stored globally (not per-session) since there's
|
|
11
|
-
* only one user using the local backend. Session IDs are ephemeral
|
|
12
|
-
* and change on every restart, so session-based storage doesn't make sense.
|
|
13
|
-
*/
|
|
14
|
-
|
|
15
|
-
import { promises as fs } from 'fs';
|
|
16
|
-
import path from 'path';
|
|
17
|
-
import { getUserDataPaths, ensureUserDataDirs } from '../utilities/userDataDir.js';
|
|
18
|
-
import { isPlaceholderApiKey } from '../utilities/apiKeyPlaceholders.js';
|
|
19
|
-
import {
|
|
20
|
-
getOrCreateEncryptionKey as _getOrCreateEncryptionKey,
|
|
21
|
-
encrypt as _cipherEncrypt,
|
|
22
|
-
decrypt as _cipherDecrypt,
|
|
23
|
-
} from '../utilities/secretsCipher.js';
|
|
24
|
-
|
|
25
|
-
class ApiKeyManager {
|
|
26
|
-
constructor(logger) {
|
|
27
|
-
this.logger = logger;
|
|
28
|
-
|
|
29
|
-
// Global API keys (persisted)
|
|
30
|
-
this.keys = {
|
|
31
|
-
loxiaApiKey: null,
|
|
32
|
-
vendorKeys: {}
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
// Persistence configuration
|
|
36
|
-
this.persistenceFile = null;
|
|
37
|
-
this.encryptionKey = null;
|
|
38
|
-
this.initialized = false;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Initialize persistence - must be called before using persistence features
|
|
43
|
-
* @returns {Promise<void>}
|
|
44
|
-
*/
|
|
45
|
-
async initialize() {
|
|
46
|
-
if (this.initialized) return;
|
|
47
|
-
|
|
48
|
-
try {
|
|
49
|
-
await ensureUserDataDirs();
|
|
50
|
-
const paths = getUserDataPaths();
|
|
51
|
-
this.persistenceFile = path.join(paths.settings, 'api-keys.enc');
|
|
52
|
-
|
|
53
|
-
// Generate or load machine-specific encryption key
|
|
54
|
-
this.encryptionKey = await this._getOrCreateEncryptionKey(paths.settings);
|
|
55
|
-
|
|
56
|
-
// Load persisted keys
|
|
57
|
-
await this.loadFromDisk();
|
|
58
|
-
|
|
59
|
-
this.initialized = true;
|
|
60
|
-
this.logger?.info('[ApiKeyManager] Initialized with persistence', {
|
|
61
|
-
hasLoxiaKey: !!this.keys.loxiaApiKey
|
|
62
|
-
});
|
|
63
|
-
} catch (error) {
|
|
64
|
-
this.logger?.warn('[ApiKeyManager] Persistence initialization failed, using memory-only mode', {
|
|
65
|
-
error: error.message
|
|
66
|
-
});
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* Cipher primitives delegate to `utilities/secretsCipher.js` so the
|
|
72
|
-
* api-keys.enc and auth-cache.enc stores share one implementation
|
|
73
|
-
* and one byte layout. See that module for the on-disk format and
|
|
74
|
-
* the KEY_DERIVATION_DOMAIN constant.
|
|
75
|
-
*/
|
|
76
|
-
async _getOrCreateEncryptionKey(settingsDir) {
|
|
77
|
-
return _getOrCreateEncryptionKey(settingsDir, this.logger);
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
_encrypt(plaintext) {
|
|
81
|
-
return _cipherEncrypt(plaintext, this.encryptionKey);
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
_decrypt(encryptedData) {
|
|
85
|
-
return _cipherDecrypt(encryptedData, this.encryptionKey);
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
/**
|
|
89
|
-
* Persist keys to encrypted file
|
|
90
|
-
* @returns {Promise<void>}
|
|
91
|
-
*/
|
|
92
|
-
async persist() {
|
|
93
|
-
if (!this.persistenceFile || !this.encryptionKey) {
|
|
94
|
-
return; // Persistence not initialized
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
try {
|
|
98
|
-
const data = {
|
|
99
|
-
version: 2,
|
|
100
|
-
savedAt: new Date().toISOString(),
|
|
101
|
-
keys: this.keys
|
|
102
|
-
};
|
|
103
|
-
|
|
104
|
-
const encrypted = this._encrypt(JSON.stringify(data));
|
|
105
|
-
await fs.writeFile(this.persistenceFile, encrypted, { mode: 0o600 });
|
|
106
|
-
|
|
107
|
-
this.logger?.debug('[ApiKeyManager] Keys persisted to disk');
|
|
108
|
-
} catch (error) {
|
|
109
|
-
this.logger?.warn('[ApiKeyManager] Failed to persist keys', { error: error.message });
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
/**
|
|
114
|
-
* Load persisted keys from disk
|
|
115
|
-
* @returns {Promise<void>}
|
|
116
|
-
*/
|
|
117
|
-
async loadFromDisk() {
|
|
118
|
-
if (!this.persistenceFile || !this.encryptionKey) {
|
|
119
|
-
return; // Persistence not initialized
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
try {
|
|
123
|
-
const encrypted = await fs.readFile(this.persistenceFile, 'utf8');
|
|
124
|
-
const decrypted = this._decrypt(encrypted);
|
|
125
|
-
const data = JSON.parse(decrypted);
|
|
126
|
-
|
|
127
|
-
// Handle both v1 (session-based) and v2 (global) formats
|
|
128
|
-
if (data.version === 2 && data.keys) {
|
|
129
|
-
// New format: direct global keys
|
|
130
|
-
this.keys = data.keys;
|
|
131
|
-
} else if (data.globalKeys) {
|
|
132
|
-
// Old format: migrate from globalKeys
|
|
133
|
-
this.keys = data.globalKeys;
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
// Scrub any UI placeholder strings that a buggy older build may
|
|
137
|
-
// have written to disk before the API-key sanitiser was added.
|
|
138
|
-
// Without this, a poisoned persist file keeps 401-ing every agent
|
|
139
|
-
// request even after the UI fix is deployed.
|
|
140
|
-
let scrubbed = false;
|
|
141
|
-
if (isPlaceholderApiKey(this.keys?.loxiaApiKey)) {
|
|
142
|
-
this.logger?.warn('[ApiKeyManager] Scrubbing placeholder loxiaApiKey from persisted store');
|
|
143
|
-
this.keys.loxiaApiKey = null;
|
|
144
|
-
scrubbed = true;
|
|
145
|
-
}
|
|
146
|
-
if (this.keys?.vendorKeys && typeof this.keys.vendorKeys === 'object') {
|
|
147
|
-
for (const k of Object.keys(this.keys.vendorKeys)) {
|
|
148
|
-
if (isPlaceholderApiKey(this.keys.vendorKeys[k])) {
|
|
149
|
-
this.logger?.warn(`[ApiKeyManager] Scrubbing placeholder vendor key: ${k}`);
|
|
150
|
-
delete this.keys.vendorKeys[k];
|
|
151
|
-
scrubbed = true;
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
if (scrubbed) {
|
|
156
|
-
// Best-effort re-persist so the scrub takes effect on the next
|
|
157
|
-
// boot too. Failures here aren't fatal — we already have clean
|
|
158
|
-
// in-memory state.
|
|
159
|
-
try { await this.persist(); } catch { /* ok */ }
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
this.logger?.info('[ApiKeyManager] Loaded persisted keys', {
|
|
163
|
-
hasLoxiaKey: !!this.keys.loxiaApiKey,
|
|
164
|
-
vendorKeys: Object.keys(this.keys.vendorKeys || {}),
|
|
165
|
-
savedAt: data.savedAt
|
|
166
|
-
});
|
|
167
|
-
} catch (error) {
|
|
168
|
-
if (error.code === 'ENOENT') {
|
|
169
|
-
this.logger?.debug('[ApiKeyManager] No persisted keys found');
|
|
170
|
-
} else {
|
|
171
|
-
this.logger?.warn('[ApiKeyManager] Failed to load persisted keys', {
|
|
172
|
-
error: error.message
|
|
173
|
-
});
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
/**
|
|
179
|
-
* Set API keys (sessionId parameter kept for API compatibility but ignored).
|
|
180
|
-
*
|
|
181
|
-
* Defense-in-depth: reject UI placeholder strings on the way in. Earlier
|
|
182
|
-
* the frontend wrote display-only placeholders like
|
|
183
|
-
* `lx_••••••••••••••••(server-managed)` and the `platform-managed`
|
|
184
|
-
* sentinel into the editable settings field, then auto-save echoed them
|
|
185
|
-
* back here — overwriting the real key with the literal placeholder and
|
|
186
|
-
* 401-ing every subsequent agent request. The frontend has been fixed
|
|
187
|
-
* to never write those values, but this guard makes sure a regression
|
|
188
|
-
* (or a third-party UI hitting this endpoint) can't repeat the bug.
|
|
189
|
-
*
|
|
190
|
-
* @param {string} sessionId - Ignored, kept for API compatibility
|
|
191
|
-
* @param {Object} keys - API keys object
|
|
192
|
-
* @param {string} keys.loxiaApiKey - Loxia platform API key
|
|
193
|
-
* @param {Object} keys.vendorKeys - Vendor-specific keys
|
|
194
|
-
*/
|
|
195
|
-
async setSessionKeys(sessionId, keys) {
|
|
196
|
-
if (keys.loxiaApiKey) {
|
|
197
|
-
if (isPlaceholderApiKey(keys.loxiaApiKey)) {
|
|
198
|
-
this.logger?.warn('[ApiKeyManager] Refusing to store placeholder string as Loxia API key — keeping existing key', {
|
|
199
|
-
received: keys.loxiaApiKey.slice(0, 16) + '…'
|
|
200
|
-
});
|
|
201
|
-
} else {
|
|
202
|
-
this.keys.loxiaApiKey = keys.loxiaApiKey;
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
if (keys.vendorKeys) {
|
|
206
|
-
const cleanVendor = {};
|
|
207
|
-
for (const [vendor, value] of Object.entries(keys.vendorKeys)) {
|
|
208
|
-
if (isPlaceholderApiKey(value)) {
|
|
209
|
-
this.logger?.warn(`[ApiKeyManager] Refusing to store placeholder for vendor ${vendor} — keeping existing key`);
|
|
210
|
-
continue;
|
|
211
|
-
}
|
|
212
|
-
cleanVendor[vendor] = value;
|
|
213
|
-
}
|
|
214
|
-
this.keys.vendorKeys = { ...this.keys.vendorKeys, ...cleanVendor };
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
this.logger?.info('[ApiKeyManager] API keys updated', {
|
|
218
|
-
hasLoxiaKey: !!this.keys.loxiaApiKey,
|
|
219
|
-
vendorKeys: Object.keys(this.keys.vendorKeys || {})
|
|
220
|
-
});
|
|
221
|
-
|
|
222
|
-
await this.persist();
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
/**
|
|
226
|
-
* Get API keys (sessionId parameter kept for API compatibility but ignored)
|
|
227
|
-
* @param {string} sessionId - Ignored, kept for API compatibility
|
|
228
|
-
* @returns {Object} API keys object
|
|
229
|
-
*/
|
|
230
|
-
getSessionKeys(
|
|
231
|
-
return this.keys;
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
/**
|
|
235
|
-
* Get the appropriate API key for a model/request
|
|
236
|
-
* @param {string} sessionId - Ignored, kept for API compatibility
|
|
237
|
-
* @param {Object} options - Request options
|
|
238
|
-
* @param {boolean} options.platformProvided - Whether this is a platform-provided model
|
|
239
|
-
* @param {string} options.vendor - Vendor name (anthropic, openai, etc.)
|
|
240
|
-
* @returns {Object} { loxiaApiKey, vendorApiKey }
|
|
241
|
-
*/
|
|
242
|
-
getKeysForRequest(sessionId, options = {}) {
|
|
243
|
-
const result = {
|
|
244
|
-
loxiaApiKey: this.keys.loxiaApiKey,
|
|
245
|
-
vendorApiKey: null
|
|
246
|
-
};
|
|
247
|
-
|
|
248
|
-
// For direct access models, also include vendor-specific key
|
|
249
|
-
if (!options.platformProvided && options.vendor && this.keys.vendorKeys) {
|
|
250
|
-
result.vendorApiKey = this.keys.vendorKeys[options.vendor];
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
return result;
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
/**
|
|
257
|
-
* Get the API key the embedding provider should use.
|
|
258
|
-
*
|
|
259
|
-
* @param {'azure'|'openai'|'local'|'disabled'} provider
|
|
260
|
-
* @returns {string|null}
|
|
261
|
-
*
|
|
262
|
-
* Wiring:
|
|
263
|
-
* - 'azure' → Loxia backend proxy → uses loxiaApiKey (same as chat)
|
|
264
|
-
* - 'openai' → direct to api.openai.com → uses vendorKeys.openai (BYOK)
|
|
265
|
-
* - 'local' → fully offline → no key needed
|
|
266
|
-
* - 'disabled' → caller shouldn't be asking → returns null
|
|
267
|
-
*
|
|
268
|
-
* Called by EmbeddingService via the `getApiKey` callback passed to
|
|
269
|
-
* each provider. Callback (not stored string) so key rotation is
|
|
270
|
-
* picked up immediately without re-instantiating providers.
|
|
271
|
-
*/
|
|
272
|
-
getEmbeddingApiKey(provider) {
|
|
273
|
-
switch (provider) {
|
|
274
|
-
case 'azure': return this.keys?.loxiaApiKey || null;
|
|
275
|
-
case 'openai': return this.keys?.vendorKeys?.openai || null;
|
|
276
|
-
case 'azure-custom': return this.keys?.vendorKeys?.azureCustom || null;
|
|
277
|
-
case 'local':
|
|
278
|
-
case 'disabled':
|
|
279
|
-
default:
|
|
280
|
-
return null;
|
|
281
|
-
}
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
/**
|
|
285
|
-
* Remove API keys (clears all keys)
|
|
286
|
-
* @param {string} sessionId - Ignored, kept for API compatibility
|
|
287
|
-
*/
|
|
288
|
-
async removeSessionKeys(
|
|
289
|
-
const hadKeys = !!this.keys.loxiaApiKey;
|
|
290
|
-
this.keys = {
|
|
291
|
-
loxiaApiKey: null,
|
|
292
|
-
vendorKeys: {}
|
|
293
|
-
};
|
|
294
|
-
|
|
295
|
-
if (hadKeys) {
|
|
296
|
-
this.logger?.info('[ApiKeyManager] API keys removed');
|
|
297
|
-
await this.persist();
|
|
298
|
-
}
|
|
299
|
-
return hadKeys;
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
/**
|
|
303
|
-
* Set global API keys (same as setSessionKeys, kept for API compatibility)
|
|
304
|
-
* @param {Object} keys - API keys
|
|
305
|
-
*/
|
|
306
|
-
async setGlobalKeys(keys) {
|
|
307
|
-
return this.setSessionKeys(null, keys);
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
/**
|
|
311
|
-
* Get active sessions info (returns empty for compatibility)
|
|
312
|
-
* @returns {Array}
|
|
313
|
-
*/
|
|
314
|
-
getActiveSessions() {
|
|
315
|
-
return [];
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
/**
|
|
319
|
-
* Cleanup (no-op, kept for API compatibility)
|
|
320
|
-
*/
|
|
321
|
-
cleanupExpiredSessions() {
|
|
322
|
-
return 0;
|
|
323
|
-
}
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
export default ApiKeyManager;
|
|
327
|
-
|
|
328
|
-
/* ------------------------------------------------------------------------ */
|
|
329
|
-
/* Singleton accessor */
|
|
330
|
-
/* */
|
|
331
|
-
/* The LoxiaSystem creates one ApiKeyManager and registers it here so cross- */
|
|
332
|
-
/* cutting services (e.g. composioService) can read vendor keys without */
|
|
333
|
-
/* dragging the manager through 10 layers of constructor arguments. Pure */
|
|
334
|
-
/* accessor — no implicit instantiation, no I/O. */
|
|
335
|
-
/* ------------------------------------------------------------------------ */
|
|
336
|
-
|
|
337
|
-
let _registered = null;
|
|
338
|
-
|
|
339
|
-
/**
|
|
340
|
-
* Register the system-level ApiKeyManager. Called once by LoxiaSystem
|
|
341
|
-
* (src/index.js) right after instantiation.
|
|
342
|
-
*/
|
|
343
|
-
export function registerApiKeyManager(instance) {
|
|
344
|
-
_registered = instance;
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
/**
|
|
348
|
-
* Returns the registered ApiKeyManager, or `null` if the system hasn't
|
|
349
|
-
* registered one yet (tests, or partial bootstrap). Callers should
|
|
350
|
-
* handle null gracefully — usually by falling back to env vars.
|
|
351
|
-
*/
|
|
352
|
-
export function getApiKeyManager() {
|
|
353
|
-
return _registered;
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
/** Test-only: clear the registration. */
|
|
357
|
-
export function _resetApiKeyManagerRegistrationForTests() {
|
|
358
|
-
_registered = null;
|
|
359
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* API Key Manager - Persistent API key storage
|
|
3
|
+
*
|
|
4
|
+
* Purpose:
|
|
5
|
+
* - Store API keys with encrypted persistence to disk
|
|
6
|
+
* - Manage both platform (Loxia) and vendor-specific keys
|
|
7
|
+
* - Provide keys to AI services based on model requirements
|
|
8
|
+
* - Survive backend restarts by loading persisted keys
|
|
9
|
+
*
|
|
10
|
+
* Note: API keys are stored globally (not per-session) since there's
|
|
11
|
+
* only one user using the local backend. Session IDs are ephemeral
|
|
12
|
+
* and change on every restart, so session-based storage doesn't make sense.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { promises as fs } from 'fs';
|
|
16
|
+
import path from 'path';
|
|
17
|
+
import { getUserDataPaths, ensureUserDataDirs } from '../utilities/userDataDir.js';
|
|
18
|
+
import { isPlaceholderApiKey } from '../utilities/apiKeyPlaceholders.js';
|
|
19
|
+
import {
|
|
20
|
+
getOrCreateEncryptionKey as _getOrCreateEncryptionKey,
|
|
21
|
+
encrypt as _cipherEncrypt,
|
|
22
|
+
decrypt as _cipherDecrypt,
|
|
23
|
+
} from '../utilities/secretsCipher.js';
|
|
24
|
+
|
|
25
|
+
class ApiKeyManager {
|
|
26
|
+
constructor(logger) {
|
|
27
|
+
this.logger = logger;
|
|
28
|
+
|
|
29
|
+
// Global API keys (persisted)
|
|
30
|
+
this.keys = {
|
|
31
|
+
loxiaApiKey: null,
|
|
32
|
+
vendorKeys: {}
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
// Persistence configuration
|
|
36
|
+
this.persistenceFile = null;
|
|
37
|
+
this.encryptionKey = null;
|
|
38
|
+
this.initialized = false;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Initialize persistence - must be called before using persistence features
|
|
43
|
+
* @returns {Promise<void>}
|
|
44
|
+
*/
|
|
45
|
+
async initialize() {
|
|
46
|
+
if (this.initialized) return;
|
|
47
|
+
|
|
48
|
+
try {
|
|
49
|
+
await ensureUserDataDirs();
|
|
50
|
+
const paths = getUserDataPaths();
|
|
51
|
+
this.persistenceFile = path.join(paths.settings, 'api-keys.enc');
|
|
52
|
+
|
|
53
|
+
// Generate or load machine-specific encryption key
|
|
54
|
+
this.encryptionKey = await this._getOrCreateEncryptionKey(paths.settings);
|
|
55
|
+
|
|
56
|
+
// Load persisted keys
|
|
57
|
+
await this.loadFromDisk();
|
|
58
|
+
|
|
59
|
+
this.initialized = true;
|
|
60
|
+
this.logger?.info('[ApiKeyManager] Initialized with persistence', {
|
|
61
|
+
hasLoxiaKey: !!this.keys.loxiaApiKey
|
|
62
|
+
});
|
|
63
|
+
} catch (error) {
|
|
64
|
+
this.logger?.warn('[ApiKeyManager] Persistence initialization failed, using memory-only mode', {
|
|
65
|
+
error: error.message
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Cipher primitives delegate to `utilities/secretsCipher.js` so the
|
|
72
|
+
* api-keys.enc and auth-cache.enc stores share one implementation
|
|
73
|
+
* and one byte layout. See that module for the on-disk format and
|
|
74
|
+
* the KEY_DERIVATION_DOMAIN constant.
|
|
75
|
+
*/
|
|
76
|
+
async _getOrCreateEncryptionKey(settingsDir) {
|
|
77
|
+
return _getOrCreateEncryptionKey(settingsDir, this.logger);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
_encrypt(plaintext) {
|
|
81
|
+
return _cipherEncrypt(plaintext, this.encryptionKey);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
_decrypt(encryptedData) {
|
|
85
|
+
return _cipherDecrypt(encryptedData, this.encryptionKey);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Persist keys to encrypted file
|
|
90
|
+
* @returns {Promise<void>}
|
|
91
|
+
*/
|
|
92
|
+
async persist() {
|
|
93
|
+
if (!this.persistenceFile || !this.encryptionKey) {
|
|
94
|
+
return; // Persistence not initialized
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
try {
|
|
98
|
+
const data = {
|
|
99
|
+
version: 2,
|
|
100
|
+
savedAt: new Date().toISOString(),
|
|
101
|
+
keys: this.keys
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
const encrypted = this._encrypt(JSON.stringify(data));
|
|
105
|
+
await fs.writeFile(this.persistenceFile, encrypted, { mode: 0o600 });
|
|
106
|
+
|
|
107
|
+
this.logger?.debug('[ApiKeyManager] Keys persisted to disk');
|
|
108
|
+
} catch (error) {
|
|
109
|
+
this.logger?.warn('[ApiKeyManager] Failed to persist keys', { error: error.message });
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Load persisted keys from disk
|
|
115
|
+
* @returns {Promise<void>}
|
|
116
|
+
*/
|
|
117
|
+
async loadFromDisk() {
|
|
118
|
+
if (!this.persistenceFile || !this.encryptionKey) {
|
|
119
|
+
return; // Persistence not initialized
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
try {
|
|
123
|
+
const encrypted = await fs.readFile(this.persistenceFile, 'utf8');
|
|
124
|
+
const decrypted = this._decrypt(encrypted);
|
|
125
|
+
const data = JSON.parse(decrypted);
|
|
126
|
+
|
|
127
|
+
// Handle both v1 (session-based) and v2 (global) formats
|
|
128
|
+
if (data.version === 2 && data.keys) {
|
|
129
|
+
// New format: direct global keys
|
|
130
|
+
this.keys = data.keys;
|
|
131
|
+
} else if (data.globalKeys) {
|
|
132
|
+
// Old format: migrate from globalKeys
|
|
133
|
+
this.keys = data.globalKeys;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// Scrub any UI placeholder strings that a buggy older build may
|
|
137
|
+
// have written to disk before the API-key sanitiser was added.
|
|
138
|
+
// Without this, a poisoned persist file keeps 401-ing every agent
|
|
139
|
+
// request even after the UI fix is deployed.
|
|
140
|
+
let scrubbed = false;
|
|
141
|
+
if (isPlaceholderApiKey(this.keys?.loxiaApiKey)) {
|
|
142
|
+
this.logger?.warn('[ApiKeyManager] Scrubbing placeholder loxiaApiKey from persisted store');
|
|
143
|
+
this.keys.loxiaApiKey = null;
|
|
144
|
+
scrubbed = true;
|
|
145
|
+
}
|
|
146
|
+
if (this.keys?.vendorKeys && typeof this.keys.vendorKeys === 'object') {
|
|
147
|
+
for (const k of Object.keys(this.keys.vendorKeys)) {
|
|
148
|
+
if (isPlaceholderApiKey(this.keys.vendorKeys[k])) {
|
|
149
|
+
this.logger?.warn(`[ApiKeyManager] Scrubbing placeholder vendor key: ${k}`);
|
|
150
|
+
delete this.keys.vendorKeys[k];
|
|
151
|
+
scrubbed = true;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
if (scrubbed) {
|
|
156
|
+
// Best-effort re-persist so the scrub takes effect on the next
|
|
157
|
+
// boot too. Failures here aren't fatal — we already have clean
|
|
158
|
+
// in-memory state.
|
|
159
|
+
try { await this.persist(); } catch { /* ok */ }
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
this.logger?.info('[ApiKeyManager] Loaded persisted keys', {
|
|
163
|
+
hasLoxiaKey: !!this.keys.loxiaApiKey,
|
|
164
|
+
vendorKeys: Object.keys(this.keys.vendorKeys || {}),
|
|
165
|
+
savedAt: data.savedAt
|
|
166
|
+
});
|
|
167
|
+
} catch (error) {
|
|
168
|
+
if (error.code === 'ENOENT') {
|
|
169
|
+
this.logger?.debug('[ApiKeyManager] No persisted keys found');
|
|
170
|
+
} else {
|
|
171
|
+
this.logger?.warn('[ApiKeyManager] Failed to load persisted keys', {
|
|
172
|
+
error: error.message
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Set API keys (sessionId parameter kept for API compatibility but ignored).
|
|
180
|
+
*
|
|
181
|
+
* Defense-in-depth: reject UI placeholder strings on the way in. Earlier
|
|
182
|
+
* the frontend wrote display-only placeholders like
|
|
183
|
+
* `lx_••••••••••••••••(server-managed)` and the `platform-managed`
|
|
184
|
+
* sentinel into the editable settings field, then auto-save echoed them
|
|
185
|
+
* back here — overwriting the real key with the literal placeholder and
|
|
186
|
+
* 401-ing every subsequent agent request. The frontend has been fixed
|
|
187
|
+
* to never write those values, but this guard makes sure a regression
|
|
188
|
+
* (or a third-party UI hitting this endpoint) can't repeat the bug.
|
|
189
|
+
*
|
|
190
|
+
* @param {string} sessionId - Ignored, kept for API compatibility
|
|
191
|
+
* @param {Object} keys - API keys object
|
|
192
|
+
* @param {string} keys.loxiaApiKey - Loxia platform API key
|
|
193
|
+
* @param {Object} keys.vendorKeys - Vendor-specific keys
|
|
194
|
+
*/
|
|
195
|
+
async setSessionKeys(sessionId, keys) {
|
|
196
|
+
if (keys.loxiaApiKey) {
|
|
197
|
+
if (isPlaceholderApiKey(keys.loxiaApiKey)) {
|
|
198
|
+
this.logger?.warn('[ApiKeyManager] Refusing to store placeholder string as Loxia API key — keeping existing key', {
|
|
199
|
+
received: keys.loxiaApiKey.slice(0, 16) + '…'
|
|
200
|
+
});
|
|
201
|
+
} else {
|
|
202
|
+
this.keys.loxiaApiKey = keys.loxiaApiKey;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
if (keys.vendorKeys) {
|
|
206
|
+
const cleanVendor = {};
|
|
207
|
+
for (const [vendor, value] of Object.entries(keys.vendorKeys)) {
|
|
208
|
+
if (isPlaceholderApiKey(value)) {
|
|
209
|
+
this.logger?.warn(`[ApiKeyManager] Refusing to store placeholder for vendor ${vendor} — keeping existing key`);
|
|
210
|
+
continue;
|
|
211
|
+
}
|
|
212
|
+
cleanVendor[vendor] = value;
|
|
213
|
+
}
|
|
214
|
+
this.keys.vendorKeys = { ...this.keys.vendorKeys, ...cleanVendor };
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
this.logger?.info('[ApiKeyManager] API keys updated', {
|
|
218
|
+
hasLoxiaKey: !!this.keys.loxiaApiKey,
|
|
219
|
+
vendorKeys: Object.keys(this.keys.vendorKeys || {})
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
await this.persist();
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* Get API keys (sessionId parameter kept for API compatibility but ignored)
|
|
227
|
+
* @param {string} sessionId - Ignored, kept for API compatibility
|
|
228
|
+
* @returns {Object} API keys object
|
|
229
|
+
*/
|
|
230
|
+
getSessionKeys(_sessionId) {
|
|
231
|
+
return this.keys;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* Get the appropriate API key for a model/request
|
|
236
|
+
* @param {string} sessionId - Ignored, kept for API compatibility
|
|
237
|
+
* @param {Object} options - Request options
|
|
238
|
+
* @param {boolean} options.platformProvided - Whether this is a platform-provided model
|
|
239
|
+
* @param {string} options.vendor - Vendor name (anthropic, openai, etc.)
|
|
240
|
+
* @returns {Object} { loxiaApiKey, vendorApiKey }
|
|
241
|
+
*/
|
|
242
|
+
getKeysForRequest(sessionId, options = {}) {
|
|
243
|
+
const result = {
|
|
244
|
+
loxiaApiKey: this.keys.loxiaApiKey,
|
|
245
|
+
vendorApiKey: null
|
|
246
|
+
};
|
|
247
|
+
|
|
248
|
+
// For direct access models, also include vendor-specific key
|
|
249
|
+
if (!options.platformProvided && options.vendor && this.keys.vendorKeys) {
|
|
250
|
+
result.vendorApiKey = this.keys.vendorKeys[options.vendor];
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
return result;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* Get the API key the embedding provider should use.
|
|
258
|
+
*
|
|
259
|
+
* @param {'azure'|'openai'|'local'|'disabled'} provider
|
|
260
|
+
* @returns {string|null}
|
|
261
|
+
*
|
|
262
|
+
* Wiring:
|
|
263
|
+
* - 'azure' → Loxia backend proxy → uses loxiaApiKey (same as chat)
|
|
264
|
+
* - 'openai' → direct to api.openai.com → uses vendorKeys.openai (BYOK)
|
|
265
|
+
* - 'local' → fully offline → no key needed
|
|
266
|
+
* - 'disabled' → caller shouldn't be asking → returns null
|
|
267
|
+
*
|
|
268
|
+
* Called by EmbeddingService via the `getApiKey` callback passed to
|
|
269
|
+
* each provider. Callback (not stored string) so key rotation is
|
|
270
|
+
* picked up immediately without re-instantiating providers.
|
|
271
|
+
*/
|
|
272
|
+
getEmbeddingApiKey(provider) {
|
|
273
|
+
switch (provider) {
|
|
274
|
+
case 'azure': return this.keys?.loxiaApiKey || null;
|
|
275
|
+
case 'openai': return this.keys?.vendorKeys?.openai || null;
|
|
276
|
+
case 'azure-custom': return this.keys?.vendorKeys?.azureCustom || null;
|
|
277
|
+
case 'local':
|
|
278
|
+
case 'disabled':
|
|
279
|
+
default:
|
|
280
|
+
return null;
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/**
|
|
285
|
+
* Remove API keys (clears all keys)
|
|
286
|
+
* @param {string} sessionId - Ignored, kept for API compatibility
|
|
287
|
+
*/
|
|
288
|
+
async removeSessionKeys(_sessionId) {
|
|
289
|
+
const hadKeys = !!this.keys.loxiaApiKey;
|
|
290
|
+
this.keys = {
|
|
291
|
+
loxiaApiKey: null,
|
|
292
|
+
vendorKeys: {}
|
|
293
|
+
};
|
|
294
|
+
|
|
295
|
+
if (hadKeys) {
|
|
296
|
+
this.logger?.info('[ApiKeyManager] API keys removed');
|
|
297
|
+
await this.persist();
|
|
298
|
+
}
|
|
299
|
+
return hadKeys;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
/**
|
|
303
|
+
* Set global API keys (same as setSessionKeys, kept for API compatibility)
|
|
304
|
+
* @param {Object} keys - API keys
|
|
305
|
+
*/
|
|
306
|
+
async setGlobalKeys(keys) {
|
|
307
|
+
return this.setSessionKeys(null, keys);
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
/**
|
|
311
|
+
* Get active sessions info (returns empty for compatibility)
|
|
312
|
+
* @returns {Array}
|
|
313
|
+
*/
|
|
314
|
+
getActiveSessions() {
|
|
315
|
+
return [];
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
/**
|
|
319
|
+
* Cleanup (no-op, kept for API compatibility)
|
|
320
|
+
*/
|
|
321
|
+
cleanupExpiredSessions() {
|
|
322
|
+
return 0;
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
export default ApiKeyManager;
|
|
327
|
+
|
|
328
|
+
/* ------------------------------------------------------------------------ */
|
|
329
|
+
/* Singleton accessor */
|
|
330
|
+
/* */
|
|
331
|
+
/* The LoxiaSystem creates one ApiKeyManager and registers it here so cross- */
|
|
332
|
+
/* cutting services (e.g. composioService) can read vendor keys without */
|
|
333
|
+
/* dragging the manager through 10 layers of constructor arguments. Pure */
|
|
334
|
+
/* accessor — no implicit instantiation, no I/O. */
|
|
335
|
+
/* ------------------------------------------------------------------------ */
|
|
336
|
+
|
|
337
|
+
let _registered = null;
|
|
338
|
+
|
|
339
|
+
/**
|
|
340
|
+
* Register the system-level ApiKeyManager. Called once by LoxiaSystem
|
|
341
|
+
* (src/index.js) right after instantiation.
|
|
342
|
+
*/
|
|
343
|
+
export function registerApiKeyManager(instance) {
|
|
344
|
+
_registered = instance;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
/**
|
|
348
|
+
* Returns the registered ApiKeyManager, or `null` if the system hasn't
|
|
349
|
+
* registered one yet (tests, or partial bootstrap). Callers should
|
|
350
|
+
* handle null gracefully — usually by falling back to env vars.
|
|
351
|
+
*/
|
|
352
|
+
export function getApiKeyManager() {
|
|
353
|
+
return _registered;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
/** Test-only: clear the registration. */
|
|
357
|
+
export function _resetApiKeyManagerRegistrationForTests() {
|
|
358
|
+
_registered = null;
|
|
359
|
+
}
|