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,448 +1,448 @@
|
|
|
1
|
-
import { jest, describe, test, expect, beforeEach } from '@jest/globals';
|
|
2
|
-
import { createMockLogger
|
|
3
|
-
|
|
4
|
-
// Mock child_process BEFORE importing TerminalTool
|
|
5
|
-
const mockExec = jest.fn();
|
|
6
|
-
const mockSpawn = jest.fn();
|
|
7
|
-
|
|
8
|
-
jest.unstable_mockModule('child_process', () => ({
|
|
9
|
-
exec: mockExec,
|
|
10
|
-
spawn: mockSpawn,
|
|
11
|
-
execSync: jest.fn(() => ''),
|
|
12
|
-
default: { exec: mockExec, spawn: mockSpawn, execSync: jest.fn(() => '') }
|
|
13
|
-
}));
|
|
14
|
-
|
|
15
|
-
// Mock fs/promises
|
|
16
|
-
const mockFs = {
|
|
17
|
-
stat: jest.fn(),
|
|
18
|
-
readdir: jest.fn(),
|
|
19
|
-
mkdir: jest.fn()
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
jest.unstable_mockModule('fs/promises', () => ({
|
|
23
|
-
default: mockFs,
|
|
24
|
-
...mockFs
|
|
25
|
-
}));
|
|
26
|
-
|
|
27
|
-
// Mock constants
|
|
28
|
-
const TERMINAL_CONFIG = {
|
|
29
|
-
STATES: {
|
|
30
|
-
RUNNING: 'running',
|
|
31
|
-
COMPLETED: 'completed',
|
|
32
|
-
FAILED: 'failed',
|
|
33
|
-
KILLED: 'killed'
|
|
34
|
-
},
|
|
35
|
-
MAX_OUTPUT_SIZE: 100000
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
jest.unstable_mockModule('../../utilities/constants.js', () => ({
|
|
39
|
-
TOOL_STATUS: { PENDING: 'pending', EXECUTING: 'executing', COMPLETED: 'completed', FAILED: 'failed' },
|
|
40
|
-
OPERATION_STATUS: { NOT_FOUND: 'not_found' },
|
|
41
|
-
ERROR_TYPES: {},
|
|
42
|
-
SYSTEM_DEFAULTS: { MAX_TOOL_EXECUTION_TIME: 300000 },
|
|
43
|
-
TERMINAL_CONFIG
|
|
44
|
-
}));
|
|
45
|
-
|
|
46
|
-
// Mock tagParser
|
|
47
|
-
jest.unstable_mockModule('../../utilities/tagParser.js', () => ({
|
|
48
|
-
default: {
|
|
49
|
-
extractContent: jest.fn((content, tag) => {
|
|
50
|
-
const regex = new RegExp(`<${tag}>([\\s\\S]*?)<\\/${tag}>`, 'gi');
|
|
51
|
-
const matches = [];
|
|
52
|
-
let match;
|
|
53
|
-
while ((match = regex.exec(content)) !== null) {
|
|
54
|
-
matches.push(match[1]);
|
|
55
|
-
}
|
|
56
|
-
return matches;
|
|
57
|
-
})
|
|
58
|
-
}
|
|
59
|
-
}));
|
|
60
|
-
|
|
61
|
-
// Mock DirectoryAccessManager
|
|
62
|
-
jest.unstable_mockModule('../../utilities/directoryAccessManager.js', () => ({
|
|
63
|
-
default: class MockDirectoryAccessManager {
|
|
64
|
-
constructor() {}
|
|
65
|
-
createDirectoryAccess(config) { return config; }
|
|
66
|
-
getWorkingDirectory(config) { return config.workingDirectory || '/project'; }
|
|
67
|
-
validateReadAccess() { return { allowed: true }; }
|
|
68
|
-
validateWriteAccess() { return { allowed: true }; }
|
|
69
|
-
}
|
|
70
|
-
}));
|
|
71
|
-
|
|
72
|
-
const { default: TerminalTool } = await import('../terminalTool.js');
|
|
73
|
-
|
|
74
|
-
// Helper: configure mockExec to call callback with success
|
|
75
|
-
function setupExecSuccess(stdout = 'output', stderr = '') {
|
|
76
|
-
mockExec.mockImplementation((cmd, opts, cb) => {
|
|
77
|
-
if (typeof opts === 'function') { cb = opts;
|
|
78
|
-
process.nextTick(() => cb(null, stdout, stderr));
|
|
79
|
-
return { pid: 12345, on: jest.fn(), kill: jest.fn(), killed: false };
|
|
80
|
-
});
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
// Helper: configure mockExec to call callback with error
|
|
84
|
-
function setupExecError(message = 'command failed', code = 1, stdout = '', stderr = 'error output') {
|
|
85
|
-
mockExec.mockImplementation((cmd, opts, cb) => {
|
|
86
|
-
if (typeof opts === 'function') { cb = opts;
|
|
87
|
-
const error = new Error(message);
|
|
88
|
-
error.code = code;
|
|
89
|
-
process.nextTick(() => cb(error, stdout, stderr));
|
|
90
|
-
return { pid: 12345, on: jest.fn(), kill: jest.fn(), killed: false };
|
|
91
|
-
});
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
describe('TerminalTool', () => {
|
|
95
|
-
let tool;
|
|
96
|
-
let logger;
|
|
97
|
-
const context = { agentId: 'agent-1', projectDir: '/project' };
|
|
98
|
-
|
|
99
|
-
beforeEach(() => {
|
|
100
|
-
jest.clearAllMocks();
|
|
101
|
-
logger = createMockLogger();
|
|
102
|
-
tool = new TerminalTool({}, logger);
|
|
103
|
-
// Override translateCommand to return command as-is for simpler testing
|
|
104
|
-
tool.translateCommand = jest.fn(async (cmd) => cmd);
|
|
105
|
-
});
|
|
106
|
-
|
|
107
|
-
test('constructor sets metadata correctly', () => {
|
|
108
|
-
expect(tool.id).toBe('terminal');
|
|
109
|
-
expect(tool.requiresProject).toBe(false);
|
|
110
|
-
expect(tool.timeout).toBe(120000);
|
|
111
|
-
});
|
|
112
|
-
|
|
113
|
-
test('getDescription mentions terminal', () => {
|
|
114
|
-
const desc = tool.getDescription();
|
|
115
|
-
expect(desc).toContain('Terminal Tool');
|
|
116
|
-
expect(desc).toContain('run-command');
|
|
117
|
-
});
|
|
118
|
-
|
|
119
|
-
test('getSupportedActions returns all action types', () => {
|
|
120
|
-
const actions = tool.getSupportedActions();
|
|
121
|
-
expect(actions).toContain('run-command');
|
|
122
|
-
expect(actions).toContain('change-directory');
|
|
123
|
-
expect(actions).toContain('list-directory');
|
|
124
|
-
expect(actions).toContain('create-directory');
|
|
125
|
-
expect(actions).toContain('get-working-directory');
|
|
126
|
-
});
|
|
127
|
-
|
|
128
|
-
test('getRequiredParameters returns actions', () => {
|
|
129
|
-
expect(tool.getRequiredParameters()).toEqual(['actions']);
|
|
130
|
-
});
|
|
131
|
-
|
|
132
|
-
test('parseParameters extracts run-command from XML', () => {
|
|
133
|
-
const content = '<run-command>npm install</run-command>';
|
|
134
|
-
const result = tool.parseParameters(content);
|
|
135
|
-
expect(result.actions).toEqual([{ type: 'run-command', command: 'npm install' }]);
|
|
136
|
-
});
|
|
137
|
-
|
|
138
|
-
test('parseParameters extracts change-directory from XML', () => {
|
|
139
|
-
const content = '<change-directory>src/components</change-directory>';
|
|
140
|
-
const result = tool.parseParameters(content);
|
|
141
|
-
expect(result.actions).toEqual([{ type: 'change-directory', directory: 'src/components' }]);
|
|
142
|
-
});
|
|
143
|
-
|
|
144
|
-
test('parseParameters extracts get-working-directory from XML', () => {
|
|
145
|
-
const content = '<get-working-directory>true</get-working-directory>';
|
|
146
|
-
const result = tool.parseParameters(content);
|
|
147
|
-
expect(result.actions.some(a => a.type === 'get-working-directory')).toBe(true);
|
|
148
|
-
});
|
|
149
|
-
|
|
150
|
-
test('parseParameters extracts timeout and async flags', () => {
|
|
151
|
-
const content = '<run-command>ls</run-command><timeout>5000</timeout><async>true</async>';
|
|
152
|
-
const result = tool.parseParameters(content);
|
|
153
|
-
expect(result.timeout).toBe(5000);
|
|
154
|
-
expect(result.async).toBe(true);
|
|
155
|
-
});
|
|
156
|
-
|
|
157
|
-
test('customValidateParameters rejects empty actions', () => {
|
|
158
|
-
const result = tool.customValidateParameters({ actions: [] });
|
|
159
|
-
expect(result.valid).toBe(false);
|
|
160
|
-
});
|
|
161
|
-
|
|
162
|
-
test('customValidateParameters rejects action without type', () => {
|
|
163
|
-
const result = tool.customValidateParameters({ actions: [{ command: 'ls' }] });
|
|
164
|
-
expect(result.valid).toBe(false);
|
|
165
|
-
});
|
|
166
|
-
|
|
167
|
-
test('customValidateParameters rejects run-command without command', () => {
|
|
168
|
-
const result = tool.customValidateParameters({
|
|
169
|
-
actions: [{ type: 'run-command', command: '' }]
|
|
170
|
-
});
|
|
171
|
-
expect(result.valid).toBe(false);
|
|
172
|
-
});
|
|
173
|
-
|
|
174
|
-
test('customValidateParameters rejects blocked commands', () => {
|
|
175
|
-
const result = tool.customValidateParameters({
|
|
176
|
-
actions: [{ type: 'run-command', command: 'rm -rf /' }]
|
|
177
|
-
});
|
|
178
|
-
expect(result.valid).toBe(false);
|
|
179
|
-
expect(result.errors.some(e => e.includes('blocked'))).toBe(true);
|
|
180
|
-
});
|
|
181
|
-
|
|
182
|
-
test('customValidateParameters rejects change-directory without directory', () => {
|
|
183
|
-
const result = tool.customValidateParameters({
|
|
184
|
-
actions: [{ type: 'change-directory', directory: '' }]
|
|
185
|
-
});
|
|
186
|
-
expect(result.valid).toBe(false);
|
|
187
|
-
});
|
|
188
|
-
|
|
189
|
-
test('customValidateParameters rejects unknown action type', () => {
|
|
190
|
-
const result = tool.customValidateParameters({
|
|
191
|
-
actions: [{ type: 'unknown-action' }]
|
|
192
|
-
});
|
|
193
|
-
expect(result.valid).toBe(false);
|
|
194
|
-
});
|
|
195
|
-
|
|
196
|
-
test('customValidateParameters accepts valid actions', () => {
|
|
197
|
-
const result = tool.customValidateParameters({
|
|
198
|
-
actions: [{ type: 'run-command', command: 'npm install' }]
|
|
199
|
-
});
|
|
200
|
-
expect(result.valid).toBe(true);
|
|
201
|
-
});
|
|
202
|
-
|
|
203
|
-
test('isBlockedCommand detects blocked commands', () => {
|
|
204
|
-
expect(tool.isBlockedCommand('rm -rf /')).toBe(true);
|
|
205
|
-
expect(tool.isBlockedCommand('format C:')).toBe(true);
|
|
206
|
-
expect(tool.isBlockedCommand('shutdown')).toBe(true);
|
|
207
|
-
expect(tool.isBlockedCommand('npm install')).toBe(false);
|
|
208
|
-
});
|
|
209
|
-
|
|
210
|
-
test('isBlockedCommand is case-insensitive', () => {
|
|
211
|
-
expect(tool.isBlockedCommand('SHUTDOWN')).toBe(true);
|
|
212
|
-
expect(tool.isBlockedCommand('Format')).toBe(true);
|
|
213
|
-
});
|
|
214
|
-
|
|
215
|
-
// Per-agent config overrides (agent.toolConfig.terminal). These ride in
|
|
216
|
-
// via context.toolConfig in execute() — see BaseTool#getEffectiveConfig.
|
|
217
|
-
describe('per-agent toolConfig overrides', () => {
|
|
218
|
-
test('per-agent blockedCommands refuses a command that is globally allowed', async () => {
|
|
219
|
-
const result = await tool.execute(
|
|
220
|
-
{ actions: [{ type: 'run-command', command: 'curl https://evil.example' }] },
|
|
221
|
-
{ ...context, toolConfig: { blockedCommands: ['curl'] } }
|
|
222
|
-
);
|
|
223
|
-
expect(result.success).toBe(false);
|
|
224
|
-
expect(result.error).toMatch(/blocked by agent policy/);
|
|
225
|
-
// Must not execute the blocked command.
|
|
226
|
-
expect(mockExec).not.toHaveBeenCalled();
|
|
227
|
-
});
|
|
228
|
-
|
|
229
|
-
test('per-agent allowedCommands rejects anything not in the list', async () => {
|
|
230
|
-
const result = await tool.execute(
|
|
231
|
-
{ actions: [{ type: 'run-command', command: 'npm install' }] },
|
|
232
|
-
{ ...context, toolConfig: { allowedCommands: ['git'] } }
|
|
233
|
-
);
|
|
234
|
-
expect(result.success).toBe(false);
|
|
235
|
-
expect(result.error).toMatch(/not in the agent's allowed list/);
|
|
236
|
-
expect(mockExec).not.toHaveBeenCalled();
|
|
237
|
-
});
|
|
238
|
-
|
|
239
|
-
test('per-agent allowedCommands accepts matches (prefix ok)', async () => {
|
|
240
|
-
setupExecSuccess('main');
|
|
241
|
-
const result = await tool.execute(
|
|
242
|
-
{ actions: [{ type: 'run-command', command: 'git status' }] },
|
|
243
|
-
{ ...context, toolConfig: { allowedCommands: ['git'] } }
|
|
244
|
-
);
|
|
245
|
-
expect(result.success).toBe(true);
|
|
246
|
-
expect(mockExec).toHaveBeenCalled();
|
|
247
|
-
});
|
|
248
|
-
|
|
249
|
-
test('blocked wins over allowed when both set', async () => {
|
|
250
|
-
const result = await tool.execute(
|
|
251
|
-
{ actions: [{ type: 'run-command', command: 'rm file.txt' }] },
|
|
252
|
-
{ ...context, toolConfig: { allowedCommands: ['rm'], blockedCommands: ['rm'] } }
|
|
253
|
-
);
|
|
254
|
-
expect(result.success).toBe(false);
|
|
255
|
-
expect(result.error).toMatch(/blocked by agent policy/);
|
|
256
|
-
});
|
|
257
|
-
|
|
258
|
-
test('no toolConfig → global rules apply (unchanged behavior)', async () => {
|
|
259
|
-
setupExecSuccess('ok');
|
|
260
|
-
const result = await tool.execute(
|
|
261
|
-
{ actions: [{ type: 'run-command', command: 'echo hi' }] },
|
|
262
|
-
context
|
|
263
|
-
);
|
|
264
|
-
expect(result.success).toBe(true);
|
|
265
|
-
});
|
|
266
|
-
|
|
267
|
-
test('empty allowedCommands array is treated as "any" (not "none")', async () => {
|
|
268
|
-
// Empty list means "no override" not "nothing allowed". Otherwise
|
|
269
|
-
// setting the override to [] would brick the agent.
|
|
270
|
-
setupExecSuccess('ok');
|
|
271
|
-
const result = await tool.execute(
|
|
272
|
-
{ actions: [{ type: 'run-command', command: 'echo hi' }] },
|
|
273
|
-
{ ...context, toolConfig: { allowedCommands: [] } }
|
|
274
|
-
);
|
|
275
|
-
expect(result.success).toBe(true);
|
|
276
|
-
});
|
|
277
|
-
});
|
|
278
|
-
|
|
279
|
-
test('execute run-command returns stdout on success', async () => {
|
|
280
|
-
setupExecSuccess('hello world');
|
|
281
|
-
|
|
282
|
-
const result = await tool.execute(
|
|
283
|
-
{ actions: [{ type: 'run-command', command: 'echo hello' }] },
|
|
284
|
-
context
|
|
285
|
-
);
|
|
286
|
-
|
|
287
|
-
expect(result.success).toBe(true);
|
|
288
|
-
expect(result.actions[0].success).toBe(true);
|
|
289
|
-
expect(result.actions[0].stdout).toBe('hello world');
|
|
290
|
-
expect(result.actions[0].exitCode).toBe(0);
|
|
291
|
-
});
|
|
292
|
-
|
|
293
|
-
test('execute run-command handles command error', async () => {
|
|
294
|
-
setupExecError('command not found', 127, '', 'bash: badcmd: command not found');
|
|
295
|
-
|
|
296
|
-
const result = await tool.execute(
|
|
297
|
-
{ actions: [{ type: 'run-command', command: 'badcmd' }] },
|
|
298
|
-
context
|
|
299
|
-
);
|
|
300
|
-
|
|
301
|
-
// The tool resolves even on failure, just with success: false on the action
|
|
302
|
-
expect(result.actions[0].success).toBe(false);
|
|
303
|
-
expect(result.actions[0].exitCode).toBe(127);
|
|
304
|
-
expect(result.actions[0].error).toContain('command not found');
|
|
305
|
-
});
|
|
306
|
-
|
|
307
|
-
test('execute run-command captures exit code', async () => {
|
|
308
|
-
setupExecError('exit 2', 2);
|
|
309
|
-
|
|
310
|
-
const result = await tool.execute(
|
|
311
|
-
{ actions: [{ type: 'run-command', command: 'exit 2' }] },
|
|
312
|
-
context
|
|
313
|
-
);
|
|
314
|
-
|
|
315
|
-
expect(result.actions[0].exitCode).toBe(2);
|
|
316
|
-
});
|
|
317
|
-
|
|
318
|
-
test('execute change-directory updates working dir', async () => {
|
|
319
|
-
mockFs.stat.mockResolvedValue({ isDirectory: () => true });
|
|
320
|
-
|
|
321
|
-
const result = await tool.execute(
|
|
322
|
-
{ actions: [{ type: 'change-directory', directory: 'src' }] },
|
|
323
|
-
context
|
|
324
|
-
);
|
|
325
|
-
|
|
326
|
-
expect(result.success).toBe(true);
|
|
327
|
-
expect(result.actions[0].success).toBe(true);
|
|
328
|
-
expect(result.actions[0].action).toBe('change-directory');
|
|
329
|
-
expect(result.workingDirectory).toContain('src');
|
|
330
|
-
});
|
|
331
|
-
|
|
332
|
-
test('execute get-working-directory returns current dir', async () => {
|
|
333
|
-
const result = await tool.execute(
|
|
334
|
-
{ actions: [{ type: 'get-working-directory' }] },
|
|
335
|
-
context
|
|
336
|
-
);
|
|
337
|
-
|
|
338
|
-
expect(result.success).toBe(true);
|
|
339
|
-
expect(result.actions[0].action).toBe('get-working-directory');
|
|
340
|
-
expect(result.actions[0].workingDirectory).toBeTruthy();
|
|
341
|
-
});
|
|
342
|
-
|
|
343
|
-
test('execute list-directory returns directory contents', async () => {
|
|
344
|
-
mockFs.readdir.mockResolvedValue([
|
|
345
|
-
{ name: 'file.js', isDirectory: () => false, isFile: () => true, isSymbolicLink: () => false },
|
|
346
|
-
{ name: 'src', isDirectory: () => true, isFile: () => false, isSymbolicLink: () => false }
|
|
347
|
-
]);
|
|
348
|
-
|
|
349
|
-
const result = await tool.execute(
|
|
350
|
-
{ actions: [{ type: 'list-directory', directory: '/project' }] },
|
|
351
|
-
context
|
|
352
|
-
);
|
|
353
|
-
|
|
354
|
-
expect(result.success).toBe(true);
|
|
355
|
-
expect(result.actions[0].totalItems).toBe(2);
|
|
356
|
-
expect(result.actions[0].files).toBe(1);
|
|
357
|
-
expect(result.actions[0].directories).toBe(1);
|
|
358
|
-
});
|
|
359
|
-
|
|
360
|
-
test('execute create-directory creates directory', async () => {
|
|
361
|
-
mockFs.mkdir.mockResolvedValue(undefined);
|
|
362
|
-
|
|
363
|
-
const result = await tool.execute(
|
|
364
|
-
{ actions: [{ type: 'create-directory', directory: 'new-dir' }] },
|
|
365
|
-
context
|
|
366
|
-
);
|
|
367
|
-
|
|
368
|
-
expect(result.success).toBe(true);
|
|
369
|
-
expect(result.actions[0].success).toBe(true);
|
|
370
|
-
expect(result.actions[0].action).toBe('create-directory');
|
|
371
|
-
});
|
|
372
|
-
|
|
373
|
-
test('execute handles multiple actions', async () => {
|
|
374
|
-
setupExecSuccess('ok');
|
|
375
|
-
|
|
376
|
-
const result = await tool.execute(
|
|
377
|
-
{
|
|
378
|
-
actions: [
|
|
379
|
-
{ type: 'get-working-directory' },
|
|
380
|
-
{ type: 'run-command', command: 'echo ok' }
|
|
381
|
-
]
|
|
382
|
-
},
|
|
383
|
-
context
|
|
384
|
-
);
|
|
385
|
-
|
|
386
|
-
expect(result.executedActions).toBe(2);
|
|
387
|
-
expect(result.actions.length).toBe(2);
|
|
388
|
-
});
|
|
389
|
-
|
|
390
|
-
test('execute reports overall failure when some actions fail', async () => {
|
|
391
|
-
setupExecError('fail', 1);
|
|
392
|
-
|
|
393
|
-
const result = await tool.execute(
|
|
394
|
-
{ actions: [{ type: 'run-command', command: 'fail-cmd' }] },
|
|
395
|
-
context
|
|
396
|
-
);
|
|
397
|
-
|
|
398
|
-
expect(result.success).toBe(false);
|
|
399
|
-
expect(result.failedActions).toBe(1);
|
|
400
|
-
});
|
|
401
|
-
|
|
402
|
-
test('execute handles action throwing error gracefully', async () => {
|
|
403
|
-
mockFs.readdir.mockRejectedValue(new Error('permission denied'));
|
|
404
|
-
|
|
405
|
-
const result = await tool.execute(
|
|
406
|
-
{ actions: [{ type: 'list-directory', directory: '/forbidden' }] },
|
|
407
|
-
context
|
|
408
|
-
);
|
|
409
|
-
|
|
410
|
-
expect(result.actions[0].success).toBe(false);
|
|
411
|
-
expect(result.actions[0].error).toContain('permission denied');
|
|
412
|
-
});
|
|
413
|
-
|
|
414
|
-
test('addToHistory records command and trims history', () => {
|
|
415
|
-
for (let i = 0; i < 110; i++) {
|
|
416
|
-
tool.addToHistory(
|
|
417
|
-
{ type: 'run-command', command: `cmd-${i}` },
|
|
418
|
-
{ success: true, executionTime: 10, workingDirectory: '/project' },
|
|
419
|
-
'agent-1'
|
|
420
|
-
);
|
|
421
|
-
}
|
|
422
|
-
expect(tool.commandHistory.length).toBe(100);
|
|
423
|
-
});
|
|
424
|
-
|
|
425
|
-
test('execute uses directoryAccess working directory', async () => {
|
|
426
|
-
setupExecSuccess('ok');
|
|
427
|
-
|
|
428
|
-
const result = await tool.execute(
|
|
429
|
-
{ actions: [{ type: 'run-command', command: 'ls' }] },
|
|
430
|
-
{
|
|
431
|
-
agentId: 'agent-1',
|
|
432
|
-
projectDir: '/project',
|
|
433
|
-
directoryAccess: {
|
|
434
|
-
workingDirectory: '/custom/dir',
|
|
435
|
-
writeEnabledDirectories: ['/custom/dir']
|
|
436
|
-
}
|
|
437
|
-
}
|
|
438
|
-
);
|
|
439
|
-
|
|
440
|
-
expect(result.success).toBe(true);
|
|
441
|
-
});
|
|
442
|
-
|
|
443
|
-
test('getParameterSchema returns valid schema', () => {
|
|
444
|
-
const schema = tool.getParameterSchema();
|
|
445
|
-
expect(schema.type).toBe('object');
|
|
446
|
-
expect(schema.properties).toHaveProperty('actions');
|
|
447
|
-
});
|
|
448
|
-
});
|
|
1
|
+
import { jest, describe, test, expect, beforeEach } from '@jest/globals';
|
|
2
|
+
import { createMockLogger } from '../../__test-utils__/mockFactories.js';
|
|
3
|
+
|
|
4
|
+
// Mock child_process BEFORE importing TerminalTool
|
|
5
|
+
const mockExec = jest.fn();
|
|
6
|
+
const mockSpawn = jest.fn();
|
|
7
|
+
|
|
8
|
+
jest.unstable_mockModule('child_process', () => ({
|
|
9
|
+
exec: mockExec,
|
|
10
|
+
spawn: mockSpawn,
|
|
11
|
+
execSync: jest.fn(() => ''),
|
|
12
|
+
default: { exec: mockExec, spawn: mockSpawn, execSync: jest.fn(() => '') }
|
|
13
|
+
}));
|
|
14
|
+
|
|
15
|
+
// Mock fs/promises
|
|
16
|
+
const mockFs = {
|
|
17
|
+
stat: jest.fn(),
|
|
18
|
+
readdir: jest.fn(),
|
|
19
|
+
mkdir: jest.fn()
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
jest.unstable_mockModule('fs/promises', () => ({
|
|
23
|
+
default: mockFs,
|
|
24
|
+
...mockFs
|
|
25
|
+
}));
|
|
26
|
+
|
|
27
|
+
// Mock constants
|
|
28
|
+
const TERMINAL_CONFIG = {
|
|
29
|
+
STATES: {
|
|
30
|
+
RUNNING: 'running',
|
|
31
|
+
COMPLETED: 'completed',
|
|
32
|
+
FAILED: 'failed',
|
|
33
|
+
KILLED: 'killed'
|
|
34
|
+
},
|
|
35
|
+
MAX_OUTPUT_SIZE: 100000
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
jest.unstable_mockModule('../../utilities/constants.js', () => ({
|
|
39
|
+
TOOL_STATUS: { PENDING: 'pending', EXECUTING: 'executing', COMPLETED: 'completed', FAILED: 'failed' },
|
|
40
|
+
OPERATION_STATUS: { NOT_FOUND: 'not_found' },
|
|
41
|
+
ERROR_TYPES: {},
|
|
42
|
+
SYSTEM_DEFAULTS: { MAX_TOOL_EXECUTION_TIME: 300000 },
|
|
43
|
+
TERMINAL_CONFIG
|
|
44
|
+
}));
|
|
45
|
+
|
|
46
|
+
// Mock tagParser
|
|
47
|
+
jest.unstable_mockModule('../../utilities/tagParser.js', () => ({
|
|
48
|
+
default: {
|
|
49
|
+
extractContent: jest.fn((content, tag) => {
|
|
50
|
+
const regex = new RegExp(`<${tag}>([\\s\\S]*?)<\\/${tag}>`, 'gi');
|
|
51
|
+
const matches = [];
|
|
52
|
+
let match;
|
|
53
|
+
while ((match = regex.exec(content)) !== null) {
|
|
54
|
+
matches.push(match[1]);
|
|
55
|
+
}
|
|
56
|
+
return matches;
|
|
57
|
+
})
|
|
58
|
+
}
|
|
59
|
+
}));
|
|
60
|
+
|
|
61
|
+
// Mock DirectoryAccessManager
|
|
62
|
+
jest.unstable_mockModule('../../utilities/directoryAccessManager.js', () => ({
|
|
63
|
+
default: class MockDirectoryAccessManager {
|
|
64
|
+
constructor() {}
|
|
65
|
+
createDirectoryAccess(config) { return config; }
|
|
66
|
+
getWorkingDirectory(config) { return config.workingDirectory || '/project'; }
|
|
67
|
+
validateReadAccess() { return { allowed: true }; }
|
|
68
|
+
validateWriteAccess() { return { allowed: true }; }
|
|
69
|
+
}
|
|
70
|
+
}));
|
|
71
|
+
|
|
72
|
+
const { default: TerminalTool } = await import('../terminalTool.js');
|
|
73
|
+
|
|
74
|
+
// Helper: configure mockExec to call callback with success
|
|
75
|
+
function setupExecSuccess(stdout = 'output', stderr = '') {
|
|
76
|
+
mockExec.mockImplementation((cmd, opts, cb) => {
|
|
77
|
+
if (typeof opts === 'function') { cb = opts; }
|
|
78
|
+
process.nextTick(() => cb(null, stdout, stderr));
|
|
79
|
+
return { pid: 12345, on: jest.fn(), kill: jest.fn(), killed: false };
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Helper: configure mockExec to call callback with error
|
|
84
|
+
function setupExecError(message = 'command failed', code = 1, stdout = '', stderr = 'error output') {
|
|
85
|
+
mockExec.mockImplementation((cmd, opts, cb) => {
|
|
86
|
+
if (typeof opts === 'function') { cb = opts; }
|
|
87
|
+
const error = new Error(message);
|
|
88
|
+
error.code = code;
|
|
89
|
+
process.nextTick(() => cb(error, stdout, stderr));
|
|
90
|
+
return { pid: 12345, on: jest.fn(), kill: jest.fn(), killed: false };
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
describe('TerminalTool', () => {
|
|
95
|
+
let tool;
|
|
96
|
+
let logger;
|
|
97
|
+
const context = { agentId: 'agent-1', projectDir: '/project' };
|
|
98
|
+
|
|
99
|
+
beforeEach(() => {
|
|
100
|
+
jest.clearAllMocks();
|
|
101
|
+
logger = createMockLogger();
|
|
102
|
+
tool = new TerminalTool({}, logger);
|
|
103
|
+
// Override translateCommand to return command as-is for simpler testing
|
|
104
|
+
tool.translateCommand = jest.fn(async (cmd) => cmd);
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
test('constructor sets metadata correctly', () => {
|
|
108
|
+
expect(tool.id).toBe('terminal');
|
|
109
|
+
expect(tool.requiresProject).toBe(false);
|
|
110
|
+
expect(tool.timeout).toBe(120000);
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
test('getDescription mentions terminal', () => {
|
|
114
|
+
const desc = tool.getDescription();
|
|
115
|
+
expect(desc).toContain('Terminal Tool');
|
|
116
|
+
expect(desc).toContain('run-command');
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
test('getSupportedActions returns all action types', () => {
|
|
120
|
+
const actions = tool.getSupportedActions();
|
|
121
|
+
expect(actions).toContain('run-command');
|
|
122
|
+
expect(actions).toContain('change-directory');
|
|
123
|
+
expect(actions).toContain('list-directory');
|
|
124
|
+
expect(actions).toContain('create-directory');
|
|
125
|
+
expect(actions).toContain('get-working-directory');
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
test('getRequiredParameters returns actions', () => {
|
|
129
|
+
expect(tool.getRequiredParameters()).toEqual(['actions']);
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
test('parseParameters extracts run-command from XML', () => {
|
|
133
|
+
const content = '<run-command>npm install</run-command>';
|
|
134
|
+
const result = tool.parseParameters(content);
|
|
135
|
+
expect(result.actions).toEqual([{ type: 'run-command', command: 'npm install' }]);
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
test('parseParameters extracts change-directory from XML', () => {
|
|
139
|
+
const content = '<change-directory>src/components</change-directory>';
|
|
140
|
+
const result = tool.parseParameters(content);
|
|
141
|
+
expect(result.actions).toEqual([{ type: 'change-directory', directory: 'src/components' }]);
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
test('parseParameters extracts get-working-directory from XML', () => {
|
|
145
|
+
const content = '<get-working-directory>true</get-working-directory>';
|
|
146
|
+
const result = tool.parseParameters(content);
|
|
147
|
+
expect(result.actions.some(a => a.type === 'get-working-directory')).toBe(true);
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
test('parseParameters extracts timeout and async flags', () => {
|
|
151
|
+
const content = '<run-command>ls</run-command><timeout>5000</timeout><async>true</async>';
|
|
152
|
+
const result = tool.parseParameters(content);
|
|
153
|
+
expect(result.timeout).toBe(5000);
|
|
154
|
+
expect(result.async).toBe(true);
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
test('customValidateParameters rejects empty actions', () => {
|
|
158
|
+
const result = tool.customValidateParameters({ actions: [] });
|
|
159
|
+
expect(result.valid).toBe(false);
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
test('customValidateParameters rejects action without type', () => {
|
|
163
|
+
const result = tool.customValidateParameters({ actions: [{ command: 'ls' }] });
|
|
164
|
+
expect(result.valid).toBe(false);
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
test('customValidateParameters rejects run-command without command', () => {
|
|
168
|
+
const result = tool.customValidateParameters({
|
|
169
|
+
actions: [{ type: 'run-command', command: '' }]
|
|
170
|
+
});
|
|
171
|
+
expect(result.valid).toBe(false);
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
test('customValidateParameters rejects blocked commands', () => {
|
|
175
|
+
const result = tool.customValidateParameters({
|
|
176
|
+
actions: [{ type: 'run-command', command: 'rm -rf /' }]
|
|
177
|
+
});
|
|
178
|
+
expect(result.valid).toBe(false);
|
|
179
|
+
expect(result.errors.some(e => e.includes('blocked'))).toBe(true);
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
test('customValidateParameters rejects change-directory without directory', () => {
|
|
183
|
+
const result = tool.customValidateParameters({
|
|
184
|
+
actions: [{ type: 'change-directory', directory: '' }]
|
|
185
|
+
});
|
|
186
|
+
expect(result.valid).toBe(false);
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
test('customValidateParameters rejects unknown action type', () => {
|
|
190
|
+
const result = tool.customValidateParameters({
|
|
191
|
+
actions: [{ type: 'unknown-action' }]
|
|
192
|
+
});
|
|
193
|
+
expect(result.valid).toBe(false);
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
test('customValidateParameters accepts valid actions', () => {
|
|
197
|
+
const result = tool.customValidateParameters({
|
|
198
|
+
actions: [{ type: 'run-command', command: 'npm install' }]
|
|
199
|
+
});
|
|
200
|
+
expect(result.valid).toBe(true);
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
test('isBlockedCommand detects blocked commands', () => {
|
|
204
|
+
expect(tool.isBlockedCommand('rm -rf /')).toBe(true);
|
|
205
|
+
expect(tool.isBlockedCommand('format C:')).toBe(true);
|
|
206
|
+
expect(tool.isBlockedCommand('shutdown')).toBe(true);
|
|
207
|
+
expect(tool.isBlockedCommand('npm install')).toBe(false);
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
test('isBlockedCommand is case-insensitive', () => {
|
|
211
|
+
expect(tool.isBlockedCommand('SHUTDOWN')).toBe(true);
|
|
212
|
+
expect(tool.isBlockedCommand('Format')).toBe(true);
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
// Per-agent config overrides (agent.toolConfig.terminal). These ride in
|
|
216
|
+
// via context.toolConfig in execute() — see BaseTool#getEffectiveConfig.
|
|
217
|
+
describe('per-agent toolConfig overrides', () => {
|
|
218
|
+
test('per-agent blockedCommands refuses a command that is globally allowed', async () => {
|
|
219
|
+
const result = await tool.execute(
|
|
220
|
+
{ actions: [{ type: 'run-command', command: 'curl https://evil.example' }] },
|
|
221
|
+
{ ...context, toolConfig: { blockedCommands: ['curl'] } }
|
|
222
|
+
);
|
|
223
|
+
expect(result.success).toBe(false);
|
|
224
|
+
expect(result.error).toMatch(/blocked by agent policy/);
|
|
225
|
+
// Must not execute the blocked command.
|
|
226
|
+
expect(mockExec).not.toHaveBeenCalled();
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
test('per-agent allowedCommands rejects anything not in the list', async () => {
|
|
230
|
+
const result = await tool.execute(
|
|
231
|
+
{ actions: [{ type: 'run-command', command: 'npm install' }] },
|
|
232
|
+
{ ...context, toolConfig: { allowedCommands: ['git'] } }
|
|
233
|
+
);
|
|
234
|
+
expect(result.success).toBe(false);
|
|
235
|
+
expect(result.error).toMatch(/not in the agent's allowed list/);
|
|
236
|
+
expect(mockExec).not.toHaveBeenCalled();
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
test('per-agent allowedCommands accepts matches (prefix ok)', async () => {
|
|
240
|
+
setupExecSuccess('main');
|
|
241
|
+
const result = await tool.execute(
|
|
242
|
+
{ actions: [{ type: 'run-command', command: 'git status' }] },
|
|
243
|
+
{ ...context, toolConfig: { allowedCommands: ['git'] } }
|
|
244
|
+
);
|
|
245
|
+
expect(result.success).toBe(true);
|
|
246
|
+
expect(mockExec).toHaveBeenCalled();
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
test('blocked wins over allowed when both set', async () => {
|
|
250
|
+
const result = await tool.execute(
|
|
251
|
+
{ actions: [{ type: 'run-command', command: 'rm file.txt' }] },
|
|
252
|
+
{ ...context, toolConfig: { allowedCommands: ['rm'], blockedCommands: ['rm'] } }
|
|
253
|
+
);
|
|
254
|
+
expect(result.success).toBe(false);
|
|
255
|
+
expect(result.error).toMatch(/blocked by agent policy/);
|
|
256
|
+
});
|
|
257
|
+
|
|
258
|
+
test('no toolConfig → global rules apply (unchanged behavior)', async () => {
|
|
259
|
+
setupExecSuccess('ok');
|
|
260
|
+
const result = await tool.execute(
|
|
261
|
+
{ actions: [{ type: 'run-command', command: 'echo hi' }] },
|
|
262
|
+
context
|
|
263
|
+
);
|
|
264
|
+
expect(result.success).toBe(true);
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
test('empty allowedCommands array is treated as "any" (not "none")', async () => {
|
|
268
|
+
// Empty list means "no override" not "nothing allowed". Otherwise
|
|
269
|
+
// setting the override to [] would brick the agent.
|
|
270
|
+
setupExecSuccess('ok');
|
|
271
|
+
const result = await tool.execute(
|
|
272
|
+
{ actions: [{ type: 'run-command', command: 'echo hi' }] },
|
|
273
|
+
{ ...context, toolConfig: { allowedCommands: [] } }
|
|
274
|
+
);
|
|
275
|
+
expect(result.success).toBe(true);
|
|
276
|
+
});
|
|
277
|
+
});
|
|
278
|
+
|
|
279
|
+
test('execute run-command returns stdout on success', async () => {
|
|
280
|
+
setupExecSuccess('hello world');
|
|
281
|
+
|
|
282
|
+
const result = await tool.execute(
|
|
283
|
+
{ actions: [{ type: 'run-command', command: 'echo hello' }] },
|
|
284
|
+
context
|
|
285
|
+
);
|
|
286
|
+
|
|
287
|
+
expect(result.success).toBe(true);
|
|
288
|
+
expect(result.actions[0].success).toBe(true);
|
|
289
|
+
expect(result.actions[0].stdout).toBe('hello world');
|
|
290
|
+
expect(result.actions[0].exitCode).toBe(0);
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
test('execute run-command handles command error', async () => {
|
|
294
|
+
setupExecError('command not found', 127, '', 'bash: badcmd: command not found');
|
|
295
|
+
|
|
296
|
+
const result = await tool.execute(
|
|
297
|
+
{ actions: [{ type: 'run-command', command: 'badcmd' }] },
|
|
298
|
+
context
|
|
299
|
+
);
|
|
300
|
+
|
|
301
|
+
// The tool resolves even on failure, just with success: false on the action
|
|
302
|
+
expect(result.actions[0].success).toBe(false);
|
|
303
|
+
expect(result.actions[0].exitCode).toBe(127);
|
|
304
|
+
expect(result.actions[0].error).toContain('command not found');
|
|
305
|
+
});
|
|
306
|
+
|
|
307
|
+
test('execute run-command captures exit code', async () => {
|
|
308
|
+
setupExecError('exit 2', 2);
|
|
309
|
+
|
|
310
|
+
const result = await tool.execute(
|
|
311
|
+
{ actions: [{ type: 'run-command', command: 'exit 2' }] },
|
|
312
|
+
context
|
|
313
|
+
);
|
|
314
|
+
|
|
315
|
+
expect(result.actions[0].exitCode).toBe(2);
|
|
316
|
+
});
|
|
317
|
+
|
|
318
|
+
test('execute change-directory updates working dir', async () => {
|
|
319
|
+
mockFs.stat.mockResolvedValue({ isDirectory: () => true });
|
|
320
|
+
|
|
321
|
+
const result = await tool.execute(
|
|
322
|
+
{ actions: [{ type: 'change-directory', directory: 'src' }] },
|
|
323
|
+
context
|
|
324
|
+
);
|
|
325
|
+
|
|
326
|
+
expect(result.success).toBe(true);
|
|
327
|
+
expect(result.actions[0].success).toBe(true);
|
|
328
|
+
expect(result.actions[0].action).toBe('change-directory');
|
|
329
|
+
expect(result.workingDirectory).toContain('src');
|
|
330
|
+
});
|
|
331
|
+
|
|
332
|
+
test('execute get-working-directory returns current dir', async () => {
|
|
333
|
+
const result = await tool.execute(
|
|
334
|
+
{ actions: [{ type: 'get-working-directory' }] },
|
|
335
|
+
context
|
|
336
|
+
);
|
|
337
|
+
|
|
338
|
+
expect(result.success).toBe(true);
|
|
339
|
+
expect(result.actions[0].action).toBe('get-working-directory');
|
|
340
|
+
expect(result.actions[0].workingDirectory).toBeTruthy();
|
|
341
|
+
});
|
|
342
|
+
|
|
343
|
+
test('execute list-directory returns directory contents', async () => {
|
|
344
|
+
mockFs.readdir.mockResolvedValue([
|
|
345
|
+
{ name: 'file.js', isDirectory: () => false, isFile: () => true, isSymbolicLink: () => false },
|
|
346
|
+
{ name: 'src', isDirectory: () => true, isFile: () => false, isSymbolicLink: () => false }
|
|
347
|
+
]);
|
|
348
|
+
|
|
349
|
+
const result = await tool.execute(
|
|
350
|
+
{ actions: [{ type: 'list-directory', directory: '/project' }] },
|
|
351
|
+
context
|
|
352
|
+
);
|
|
353
|
+
|
|
354
|
+
expect(result.success).toBe(true);
|
|
355
|
+
expect(result.actions[0].totalItems).toBe(2);
|
|
356
|
+
expect(result.actions[0].files).toBe(1);
|
|
357
|
+
expect(result.actions[0].directories).toBe(1);
|
|
358
|
+
});
|
|
359
|
+
|
|
360
|
+
test('execute create-directory creates directory', async () => {
|
|
361
|
+
mockFs.mkdir.mockResolvedValue(undefined);
|
|
362
|
+
|
|
363
|
+
const result = await tool.execute(
|
|
364
|
+
{ actions: [{ type: 'create-directory', directory: 'new-dir' }] },
|
|
365
|
+
context
|
|
366
|
+
);
|
|
367
|
+
|
|
368
|
+
expect(result.success).toBe(true);
|
|
369
|
+
expect(result.actions[0].success).toBe(true);
|
|
370
|
+
expect(result.actions[0].action).toBe('create-directory');
|
|
371
|
+
});
|
|
372
|
+
|
|
373
|
+
test('execute handles multiple actions', async () => {
|
|
374
|
+
setupExecSuccess('ok');
|
|
375
|
+
|
|
376
|
+
const result = await tool.execute(
|
|
377
|
+
{
|
|
378
|
+
actions: [
|
|
379
|
+
{ type: 'get-working-directory' },
|
|
380
|
+
{ type: 'run-command', command: 'echo ok' }
|
|
381
|
+
]
|
|
382
|
+
},
|
|
383
|
+
context
|
|
384
|
+
);
|
|
385
|
+
|
|
386
|
+
expect(result.executedActions).toBe(2);
|
|
387
|
+
expect(result.actions.length).toBe(2);
|
|
388
|
+
});
|
|
389
|
+
|
|
390
|
+
test('execute reports overall failure when some actions fail', async () => {
|
|
391
|
+
setupExecError('fail', 1);
|
|
392
|
+
|
|
393
|
+
const result = await tool.execute(
|
|
394
|
+
{ actions: [{ type: 'run-command', command: 'fail-cmd' }] },
|
|
395
|
+
context
|
|
396
|
+
);
|
|
397
|
+
|
|
398
|
+
expect(result.success).toBe(false);
|
|
399
|
+
expect(result.failedActions).toBe(1);
|
|
400
|
+
});
|
|
401
|
+
|
|
402
|
+
test('execute handles action throwing error gracefully', async () => {
|
|
403
|
+
mockFs.readdir.mockRejectedValue(new Error('permission denied'));
|
|
404
|
+
|
|
405
|
+
const result = await tool.execute(
|
|
406
|
+
{ actions: [{ type: 'list-directory', directory: '/forbidden' }] },
|
|
407
|
+
context
|
|
408
|
+
);
|
|
409
|
+
|
|
410
|
+
expect(result.actions[0].success).toBe(false);
|
|
411
|
+
expect(result.actions[0].error).toContain('permission denied');
|
|
412
|
+
});
|
|
413
|
+
|
|
414
|
+
test('addToHistory records command and trims history', () => {
|
|
415
|
+
for (let i = 0; i < 110; i++) {
|
|
416
|
+
tool.addToHistory(
|
|
417
|
+
{ type: 'run-command', command: `cmd-${i}` },
|
|
418
|
+
{ success: true, executionTime: 10, workingDirectory: '/project' },
|
|
419
|
+
'agent-1'
|
|
420
|
+
);
|
|
421
|
+
}
|
|
422
|
+
expect(tool.commandHistory.length).toBe(100);
|
|
423
|
+
});
|
|
424
|
+
|
|
425
|
+
test('execute uses directoryAccess working directory', async () => {
|
|
426
|
+
setupExecSuccess('ok');
|
|
427
|
+
|
|
428
|
+
const result = await tool.execute(
|
|
429
|
+
{ actions: [{ type: 'run-command', command: 'ls' }] },
|
|
430
|
+
{
|
|
431
|
+
agentId: 'agent-1',
|
|
432
|
+
projectDir: '/project',
|
|
433
|
+
directoryAccess: {
|
|
434
|
+
workingDirectory: '/custom/dir',
|
|
435
|
+
writeEnabledDirectories: ['/custom/dir']
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
);
|
|
439
|
+
|
|
440
|
+
expect(result.success).toBe(true);
|
|
441
|
+
});
|
|
442
|
+
|
|
443
|
+
test('getParameterSchema returns valid schema', () => {
|
|
444
|
+
const schema = tool.getParameterSchema();
|
|
445
|
+
expect(schema.type).toBe('object');
|
|
446
|
+
expect(schema.properties).toHaveProperty('actions');
|
|
447
|
+
});
|
|
448
|
+
});
|