patchwork-os 0.2.0-alpha.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/LICENSE +21 -0
- package/README.bridge.md +352 -0
- package/README.md +72 -0
- package/deploy/README.md +172 -0
- package/deploy/bootstrap-new-vps.sh +364 -0
- package/deploy/claude-ide-bridge.service.template +67 -0
- package/deploy/claude-ide-bridge@.service +31 -0
- package/deploy/ecosystem.config.js.example +36 -0
- package/deploy/install-vps-service.sh +240 -0
- package/deploy/nginx-claude-bridge.conf.template +129 -0
- package/dist/activityLog.d.ts +112 -0
- package/dist/activityLog.js +399 -0
- package/dist/activityLog.js.map +1 -0
- package/dist/activityTypes.d.ts +28 -0
- package/dist/activityTypes.js +9 -0
- package/dist/activityTypes.js.map +1 -0
- package/dist/adapters/base.d.ts +78 -0
- package/dist/adapters/base.js +14 -0
- package/dist/adapters/base.js.map +1 -0
- package/dist/adapters/claude.d.ts +18 -0
- package/dist/adapters/claude.js +276 -0
- package/dist/adapters/claude.js.map +1 -0
- package/dist/adapters/gemini.d.ts +17 -0
- package/dist/adapters/gemini.js +218 -0
- package/dist/adapters/gemini.js.map +1 -0
- package/dist/adapters/grok.d.ts +7 -0
- package/dist/adapters/grok.js +21 -0
- package/dist/adapters/grok.js.map +1 -0
- package/dist/adapters/index.d.ts +5 -0
- package/dist/adapters/index.js +37 -0
- package/dist/adapters/index.js.map +1 -0
- package/dist/adapters/local.d.ts +7 -0
- package/dist/adapters/local.js +22 -0
- package/dist/adapters/local.js.map +1 -0
- package/dist/adapters/openai.d.ts +22 -0
- package/dist/adapters/openai.js +284 -0
- package/dist/adapters/openai.js.map +1 -0
- package/dist/adapters/sse.d.ts +13 -0
- package/dist/adapters/sse.js +58 -0
- package/dist/adapters/sse.js.map +1 -0
- package/dist/analyticsAggregator.d.ts +28 -0
- package/dist/analyticsAggregator.js +133 -0
- package/dist/analyticsAggregator.js.map +1 -0
- package/dist/analyticsPrefs.d.ts +9 -0
- package/dist/analyticsPrefs.js +50 -0
- package/dist/analyticsPrefs.js.map +1 -0
- package/dist/analyticsSend.d.ts +12 -0
- package/dist/analyticsSend.js +34 -0
- package/dist/analyticsSend.js.map +1 -0
- package/dist/approvalHttp.d.ts +46 -0
- package/dist/approvalHttp.js +370 -0
- package/dist/approvalHttp.js.map +1 -0
- package/dist/approvalQueue.d.ts +49 -0
- package/dist/approvalQueue.js +84 -0
- package/dist/approvalQueue.js.map +1 -0
- package/dist/automation.d.ts +675 -0
- package/dist/automation.js +1038 -0
- package/dist/automation.js.map +1 -0
- package/dist/bridge.d.ts +85 -0
- package/dist/bridge.js +1535 -0
- package/dist/bridge.js.map +1 -0
- package/dist/bridgeLockDiscovery.d.ts +11 -0
- package/dist/bridgeLockDiscovery.js +49 -0
- package/dist/bridgeLockDiscovery.js.map +1 -0
- package/dist/bridgeToken.d.ts +22 -0
- package/dist/bridgeToken.js +114 -0
- package/dist/bridgeToken.js.map +1 -0
- package/dist/bridgeToolsRules.d.ts +20 -0
- package/dist/bridgeToolsRules.js +79 -0
- package/dist/bridgeToolsRules.js.map +1 -0
- package/dist/ccPermissions.d.ts +59 -0
- package/dist/ccPermissions.js +163 -0
- package/dist/ccPermissions.js.map +1 -0
- package/dist/claudeDriver.d.ts +129 -0
- package/dist/claudeDriver.js +459 -0
- package/dist/claudeDriver.js.map +1 -0
- package/dist/claudeMdPatch.d.ts +29 -0
- package/dist/claudeMdPatch.js +164 -0
- package/dist/claudeMdPatch.js.map +1 -0
- package/dist/claudeOrchestrator.d.ts +171 -0
- package/dist/claudeOrchestrator.js +591 -0
- package/dist/claudeOrchestrator.js.map +1 -0
- package/dist/commands/install.d.ts +1 -0
- package/dist/commands/install.js +158 -0
- package/dist/commands/install.js.map +1 -0
- package/dist/commands/marketplace.d.ts +11 -0
- package/dist/commands/marketplace.js +120 -0
- package/dist/commands/marketplace.js.map +1 -0
- package/dist/commands/patchworkInit.d.ts +14 -0
- package/dist/commands/patchworkInit.js +155 -0
- package/dist/commands/patchworkInit.js.map +1 -0
- package/dist/commands/task.d.ts +14 -0
- package/dist/commands/task.js +289 -0
- package/dist/commands/task.js.map +1 -0
- package/dist/commands/tokenEfficiency.d.ts +9 -0
- package/dist/commands/tokenEfficiency.js +211 -0
- package/dist/commands/tokenEfficiency.js.map +1 -0
- package/dist/commands/tools.d.ts +28 -0
- package/dist/commands/tools.js +326 -0
- package/dist/commands/tools.js.map +1 -0
- package/dist/commitIssueLinkLog.d.ts +77 -0
- package/dist/commitIssueLinkLog.js +142 -0
- package/dist/commitIssueLinkLog.js.map +1 -0
- package/dist/companions/registry.d.ts +12 -0
- package/dist/companions/registry.js +71 -0
- package/dist/companions/registry.js.map +1 -0
- package/dist/config.d.ts +105 -0
- package/dist/config.js +720 -0
- package/dist/config.js.map +1 -0
- package/dist/crypto.d.ts +16 -0
- package/dist/crypto.js +34 -0
- package/dist/crypto.js.map +1 -0
- package/dist/dashboard.d.ts +12 -0
- package/dist/dashboard.js +149 -0
- package/dist/dashboard.js.map +1 -0
- package/dist/decisionTraceLog.d.ts +77 -0
- package/dist/decisionTraceLog.js +147 -0
- package/dist/decisionTraceLog.js.map +1 -0
- package/dist/errors.d.ts +32 -0
- package/dist/errors.js +34 -0
- package/dist/errors.js.map +1 -0
- package/dist/extensionClient.d.ts +279 -0
- package/dist/extensionClient.js +1253 -0
- package/dist/extensionClient.js.map +1 -0
- package/dist/fileLock.d.ts +36 -0
- package/dist/fileLock.js +121 -0
- package/dist/fileLock.js.map +1 -0
- package/dist/fp/activityAnalytics.d.ts +39 -0
- package/dist/fp/activityAnalytics.js +111 -0
- package/dist/fp/activityAnalytics.js.map +1 -0
- package/dist/fp/async.d.ts +48 -0
- package/dist/fp/async.js +60 -0
- package/dist/fp/async.js.map +1 -0
- package/dist/fp/automationInterpreter.d.ts +37 -0
- package/dist/fp/automationInterpreter.js +523 -0
- package/dist/fp/automationInterpreter.js.map +1 -0
- package/dist/fp/automationProgram.d.ts +89 -0
- package/dist/fp/automationProgram.js +29 -0
- package/dist/fp/automationProgram.js.map +1 -0
- package/dist/fp/automationState.d.ts +135 -0
- package/dist/fp/automationState.js +206 -0
- package/dist/fp/automationState.js.map +1 -0
- package/dist/fp/automationUtils.d.ts +31 -0
- package/dist/fp/automationUtils.js +61 -0
- package/dist/fp/automationUtils.js.map +1 -0
- package/dist/fp/brandedTypes.d.ts +32 -0
- package/dist/fp/brandedTypes.js +41 -0
- package/dist/fp/brandedTypes.js.map +1 -0
- package/dist/fp/commandDescription.d.ts +18 -0
- package/dist/fp/commandDescription.js +125 -0
- package/dist/fp/commandDescription.js.map +1 -0
- package/dist/fp/extensionSnapshot.d.ts +10 -0
- package/dist/fp/extensionSnapshot.js +14 -0
- package/dist/fp/extensionSnapshot.js.map +1 -0
- package/dist/fp/index.d.ts +8 -0
- package/dist/fp/index.js +9 -0
- package/dist/fp/index.js.map +1 -0
- package/dist/fp/interpreterContext.d.ts +69 -0
- package/dist/fp/interpreterContext.js +56 -0
- package/dist/fp/interpreterContext.js.map +1 -0
- package/dist/fp/policyParser.d.ts +16 -0
- package/dist/fp/policyParser.js +334 -0
- package/dist/fp/policyParser.js.map +1 -0
- package/dist/fp/result.d.ts +38 -0
- package/dist/fp/result.js +57 -0
- package/dist/fp/result.js.map +1 -0
- package/dist/fp/tokenBucket.d.ts +27 -0
- package/dist/fp/tokenBucket.js +36 -0
- package/dist/fp/tokenBucket.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1465 -0
- package/dist/index.js.map +1 -0
- package/dist/instructionsUtils.d.ts +17 -0
- package/dist/instructionsUtils.js +38 -0
- package/dist/instructionsUtils.js.map +1 -0
- package/dist/lockfile.d.ts +16 -0
- package/dist/lockfile.js +172 -0
- package/dist/lockfile.js.map +1 -0
- package/dist/logger.d.ts +16 -0
- package/dist/logger.js +68 -0
- package/dist/logger.js.map +1 -0
- package/dist/oauth.d.ts +105 -0
- package/dist/oauth.js +880 -0
- package/dist/oauth.js.map +1 -0
- package/dist/orchestrator/childBridgeClient.d.ts +33 -0
- package/dist/orchestrator/childBridgeClient.js +321 -0
- package/dist/orchestrator/childBridgeClient.js.map +1 -0
- package/dist/orchestrator/childBridgeRegistry.d.ts +67 -0
- package/dist/orchestrator/childBridgeRegistry.js +297 -0
- package/dist/orchestrator/childBridgeRegistry.js.map +1 -0
- package/dist/orchestrator/index.d.ts +3 -0
- package/dist/orchestrator/index.js +3 -0
- package/dist/orchestrator/index.js.map +1 -0
- package/dist/orchestrator/orchestratorBridge.d.ts +32 -0
- package/dist/orchestrator/orchestratorBridge.js +412 -0
- package/dist/orchestrator/orchestratorBridge.js.map +1 -0
- package/dist/orchestrator/orchestratorConfig.d.ts +11 -0
- package/dist/orchestrator/orchestratorConfig.js +85 -0
- package/dist/orchestrator/orchestratorConfig.js.map +1 -0
- package/dist/orchestrator/orchestratorTools.d.ts +16 -0
- package/dist/orchestrator/orchestratorTools.js +272 -0
- package/dist/orchestrator/orchestratorTools.js.map +1 -0
- package/dist/patchworkCli.d.ts +15 -0
- package/dist/patchworkCli.js +41 -0
- package/dist/patchworkCli.js.map +1 -0
- package/dist/patchworkConfig.d.ts +28 -0
- package/dist/patchworkConfig.js +30 -0
- package/dist/patchworkConfig.js.map +1 -0
- package/dist/plugin.d.ts +106 -0
- package/dist/plugin.js +31 -0
- package/dist/plugin.js.map +1 -0
- package/dist/pluginLoader.d.ts +44 -0
- package/dist/pluginLoader.js +357 -0
- package/dist/pluginLoader.js.map +1 -0
- package/dist/pluginWatcher.d.ts +24 -0
- package/dist/pluginWatcher.js +139 -0
- package/dist/pluginWatcher.js.map +1 -0
- package/dist/preToolUseHook.d.ts +10 -0
- package/dist/preToolUseHook.js +57 -0
- package/dist/preToolUseHook.js.map +1 -0
- package/dist/probe.d.ts +35 -0
- package/dist/probe.js +143 -0
- package/dist/probe.js.map +1 -0
- package/dist/prompts.d.ts +27 -0
- package/dist/prompts.js +1680 -0
- package/dist/prompts.js.map +1 -0
- package/dist/quickTaskPresets.d.ts +64 -0
- package/dist/quickTaskPresets.js +156 -0
- package/dist/quickTaskPresets.js.map +1 -0
- package/dist/recipes/compiler.d.ts +44 -0
- package/dist/recipes/compiler.js +140 -0
- package/dist/recipes/compiler.js.map +1 -0
- package/dist/recipes/installer.d.ts +25 -0
- package/dist/recipes/installer.js +62 -0
- package/dist/recipes/installer.js.map +1 -0
- package/dist/recipes/parser.d.ts +18 -0
- package/dist/recipes/parser.js +160 -0
- package/dist/recipes/parser.js.map +1 -0
- package/dist/recipes/scheduler.d.ts +45 -0
- package/dist/recipes/scheduler.js +110 -0
- package/dist/recipes/scheduler.js.map +1 -0
- package/dist/recipes/schema.d.ts +71 -0
- package/dist/recipes/schema.js +11 -0
- package/dist/recipes/schema.js.map +1 -0
- package/dist/recipesHttp.d.ts +63 -0
- package/dist/recipesHttp.js +183 -0
- package/dist/recipesHttp.js.map +1 -0
- package/dist/resources.d.ts +33 -0
- package/dist/resources.js +266 -0
- package/dist/resources.js.map +1 -0
- package/dist/riskTier.d.ts +40 -0
- package/dist/riskTier.js +142 -0
- package/dist/riskTier.js.map +1 -0
- package/dist/runLog.d.ts +90 -0
- package/dist/runLog.js +143 -0
- package/dist/runLog.js.map +1 -0
- package/dist/server.d.ts +160 -0
- package/dist/server.js +1244 -0
- package/dist/server.js.map +1 -0
- package/dist/sessionCheckpoint.d.ts +37 -0
- package/dist/sessionCheckpoint.js +123 -0
- package/dist/sessionCheckpoint.js.map +1 -0
- package/dist/streamableHttp.d.ts +86 -0
- package/dist/streamableHttp.js +702 -0
- package/dist/streamableHttp.js.map +1 -0
- package/dist/telemetry.d.ts +18 -0
- package/dist/telemetry.js +95 -0
- package/dist/telemetry.js.map +1 -0
- package/dist/tools/activityLog.d.ts +140 -0
- package/dist/tools/activityLog.js +204 -0
- package/dist/tools/activityLog.js.map +1 -0
- package/dist/tools/auditDependencies.d.ts +67 -0
- package/dist/tools/auditDependencies.js +298 -0
- package/dist/tools/auditDependencies.js.map +1 -0
- package/dist/tools/batchLsp.d.ts +262 -0
- package/dist/tools/batchLsp.js +328 -0
- package/dist/tools/batchLsp.js.map +1 -0
- package/dist/tools/blame-utils.d.ts +30 -0
- package/dist/tools/blame-utils.js +60 -0
- package/dist/tools/blame-utils.js.map +1 -0
- package/dist/tools/bridgeDoctor.d.ts +78 -0
- package/dist/tools/bridgeDoctor.js +542 -0
- package/dist/tools/bridgeDoctor.js.map +1 -0
- package/dist/tools/bridgeStatus.d.ts +122 -0
- package/dist/tools/bridgeStatus.js +250 -0
- package/dist/tools/bridgeStatus.js.map +1 -0
- package/dist/tools/cancelClaudeTask.d.ts +48 -0
- package/dist/tools/cancelClaudeTask.js +56 -0
- package/dist/tools/cancelClaudeTask.js.map +1 -0
- package/dist/tools/checkDocumentDirty.d.ts +56 -0
- package/dist/tools/checkDocumentDirty.js +74 -0
- package/dist/tools/checkDocumentDirty.js.map +1 -0
- package/dist/tools/clipboard.d.ts +80 -0
- package/dist/tools/clipboard.js +211 -0
- package/dist/tools/clipboard.js.map +1 -0
- package/dist/tools/closeTabs.d.ts +84 -0
- package/dist/tools/closeTabs.js +97 -0
- package/dist/tools/closeTabs.js.map +1 -0
- package/dist/tools/codeLens.d.ts +50 -0
- package/dist/tools/codeLens.js +47 -0
- package/dist/tools/codeLens.js.map +1 -0
- package/dist/tools/contextBundle.d.ts +75 -0
- package/dist/tools/contextBundle.js +218 -0
- package/dist/tools/contextBundle.js.map +1 -0
- package/dist/tools/createIssueFromAIComment.d.ts +75 -0
- package/dist/tools/createIssueFromAIComment.js +119 -0
- package/dist/tools/createIssueFromAIComment.js.map +1 -0
- package/dist/tools/ctxGetTaskContext.d.ts +103 -0
- package/dist/tools/ctxGetTaskContext.js +274 -0
- package/dist/tools/ctxGetTaskContext.js.map +1 -0
- package/dist/tools/ctxQueryTraces.d.ts +142 -0
- package/dist/tools/ctxQueryTraces.js +194 -0
- package/dist/tools/ctxQueryTraces.js.map +1 -0
- package/dist/tools/ctxSaveTrace.d.ts +87 -0
- package/dist/tools/ctxSaveTrace.js +94 -0
- package/dist/tools/ctxSaveTrace.js.map +1 -0
- package/dist/tools/debug.d.ts +206 -0
- package/dist/tools/debug.js +234 -0
- package/dist/tools/debug.js.map +1 -0
- package/dist/tools/decorations.d.ts +130 -0
- package/dist/tools/decorations.js +160 -0
- package/dist/tools/decorations.js.map +1 -0
- package/dist/tools/detectUnusedCode.d.ts +78 -0
- package/dist/tools/detectUnusedCode.js +173 -0
- package/dist/tools/detectUnusedCode.js.map +1 -0
- package/dist/tools/documentLinks.d.ts +62 -0
- package/dist/tools/documentLinks.js +55 -0
- package/dist/tools/documentLinks.js.map +1 -0
- package/dist/tools/editText.d.ts +108 -0
- package/dist/tools/editText.js +318 -0
- package/dist/tools/editText.js.map +1 -0
- package/dist/tools/enrichCommit.d.ts +89 -0
- package/dist/tools/enrichCommit.js +201 -0
- package/dist/tools/enrichCommit.js.map +1 -0
- package/dist/tools/enrichStackTrace.d.ts +121 -0
- package/dist/tools/enrichStackTrace.js +194 -0
- package/dist/tools/enrichStackTrace.js.map +1 -0
- package/dist/tools/explainDiagnostic.d.ts +137 -0
- package/dist/tools/explainDiagnostic.js +230 -0
- package/dist/tools/explainDiagnostic.js.map +1 -0
- package/dist/tools/explainSymbol.d.ts +119 -0
- package/dist/tools/explainSymbol.js +177 -0
- package/dist/tools/explainSymbol.js.map +1 -0
- package/dist/tools/fileOperations.d.ts +186 -0
- package/dist/tools/fileOperations.js +330 -0
- package/dist/tools/fileOperations.js.map +1 -0
- package/dist/tools/fileWatcher.d.ts +107 -0
- package/dist/tools/fileWatcher.js +121 -0
- package/dist/tools/fileWatcher.js.map +1 -0
- package/dist/tools/findFiles.d.ts +65 -0
- package/dist/tools/findFiles.js +142 -0
- package/dist/tools/findFiles.js.map +1 -0
- package/dist/tools/findRelatedTests.d.ts +83 -0
- package/dist/tools/findRelatedTests.js +196 -0
- package/dist/tools/findRelatedTests.js.map +1 -0
- package/dist/tools/fixAllLintErrors.d.ts +66 -0
- package/dist/tools/fixAllLintErrors.js +128 -0
- package/dist/tools/fixAllLintErrors.js.map +1 -0
- package/dist/tools/foldingRanges.d.ts +50 -0
- package/dist/tools/foldingRanges.js +51 -0
- package/dist/tools/foldingRanges.js.map +1 -0
- package/dist/tools/formatAndSave.d.ts +57 -0
- package/dist/tools/formatAndSave.js +87 -0
- package/dist/tools/formatAndSave.js.map +1 -0
- package/dist/tools/formatDocument.d.ts +61 -0
- package/dist/tools/formatDocument.js +144 -0
- package/dist/tools/formatDocument.js.map +1 -0
- package/dist/tools/generateAPIDocumentation.d.ts +62 -0
- package/dist/tools/generateAPIDocumentation.js +249 -0
- package/dist/tools/generateAPIDocumentation.js.map +1 -0
- package/dist/tools/generateTests.d.ts +75 -0
- package/dist/tools/generateTests.js +226 -0
- package/dist/tools/generateTests.js.map +1 -0
- package/dist/tools/getAIComments.d.ts +79 -0
- package/dist/tools/getAIComments.js +93 -0
- package/dist/tools/getAIComments.js.map +1 -0
- package/dist/tools/getAnalyticsReport.d.ts +102 -0
- package/dist/tools/getAnalyticsReport.js +137 -0
- package/dist/tools/getAnalyticsReport.js.map +1 -0
- package/dist/tools/getArchitectureContext.d.ts +85 -0
- package/dist/tools/getArchitectureContext.js +135 -0
- package/dist/tools/getArchitectureContext.js.map +1 -0
- package/dist/tools/getBufferContent.d.ts +80 -0
- package/dist/tools/getBufferContent.js +207 -0
- package/dist/tools/getBufferContent.js.map +1 -0
- package/dist/tools/getChangeImpact.d.ts +76 -0
- package/dist/tools/getChangeImpact.js +184 -0
- package/dist/tools/getChangeImpact.js.map +1 -0
- package/dist/tools/getClaudeTaskStatus.d.ts +87 -0
- package/dist/tools/getClaudeTaskStatus.js +89 -0
- package/dist/tools/getClaudeTaskStatus.js.map +1 -0
- package/dist/tools/getCodeCoverage.d.ts +86 -0
- package/dist/tools/getCodeCoverage.js +237 -0
- package/dist/tools/getCodeCoverage.js.map +1 -0
- package/dist/tools/getCommitsForIssue.d.ts +98 -0
- package/dist/tools/getCommitsForIssue.js +106 -0
- package/dist/tools/getCommitsForIssue.js.map +1 -0
- package/dist/tools/getCurrentSelection.d.ts +123 -0
- package/dist/tools/getCurrentSelection.js +113 -0
- package/dist/tools/getCurrentSelection.js.map +1 -0
- package/dist/tools/getDebugState.d.ts +140 -0
- package/dist/tools/getDebugState.js +109 -0
- package/dist/tools/getDebugState.js.map +1 -0
- package/dist/tools/getDependencyTree.d.ts +59 -0
- package/dist/tools/getDependencyTree.js +207 -0
- package/dist/tools/getDependencyTree.js.map +1 -0
- package/dist/tools/getDiagnostics.d.ts +108 -0
- package/dist/tools/getDiagnostics.js +371 -0
- package/dist/tools/getDiagnostics.js.map +1 -0
- package/dist/tools/getDiffFromHandoff.d.ts +89 -0
- package/dist/tools/getDiffFromHandoff.js +163 -0
- package/dist/tools/getDiffFromHandoff.js.map +1 -0
- package/dist/tools/getDocumentSymbols.d.ts +74 -0
- package/dist/tools/getDocumentSymbols.js +177 -0
- package/dist/tools/getDocumentSymbols.js.map +1 -0
- package/dist/tools/getFileTree.d.ts +66 -0
- package/dist/tools/getFileTree.js +131 -0
- package/dist/tools/getFileTree.js.map +1 -0
- package/dist/tools/getGitDiff.d.ts +50 -0
- package/dist/tools/getGitDiff.js +73 -0
- package/dist/tools/getGitDiff.js.map +1 -0
- package/dist/tools/getGitHotspots.d.ts +88 -0
- package/dist/tools/getGitHotspots.js +145 -0
- package/dist/tools/getGitHotspots.js.map +1 -0
- package/dist/tools/getGitLog.d.ts +62 -0
- package/dist/tools/getGitLog.js +87 -0
- package/dist/tools/getGitLog.js.map +1 -0
- package/dist/tools/getGitStatus.d.ts +72 -0
- package/dist/tools/getGitStatus.js +126 -0
- package/dist/tools/getGitStatus.js.map +1 -0
- package/dist/tools/getImportTree.d.ts +73 -0
- package/dist/tools/getImportTree.js +223 -0
- package/dist/tools/getImportTree.js.map +1 -0
- package/dist/tools/getImportedSignatures.d.ts +62 -0
- package/dist/tools/getImportedSignatures.js +255 -0
- package/dist/tools/getImportedSignatures.js.map +1 -0
- package/dist/tools/getOpenEditors.d.ts +62 -0
- package/dist/tools/getOpenEditors.js +126 -0
- package/dist/tools/getOpenEditors.js.map +1 -0
- package/dist/tools/getPRTemplate.d.ts +68 -0
- package/dist/tools/getPRTemplate.js +187 -0
- package/dist/tools/getPRTemplate.js.map +1 -0
- package/dist/tools/getProjectContext.d.ts +114 -0
- package/dist/tools/getProjectContext.js +344 -0
- package/dist/tools/getProjectContext.js.map +1 -0
- package/dist/tools/getProjectInfo.d.ts +51 -0
- package/dist/tools/getProjectInfo.js +325 -0
- package/dist/tools/getProjectInfo.js.map +1 -0
- package/dist/tools/getSecurityAdvisories.d.ts +105 -0
- package/dist/tools/getSecurityAdvisories.js +472 -0
- package/dist/tools/getSecurityAdvisories.js.map +1 -0
- package/dist/tools/getSessionUsage.d.ts +58 -0
- package/dist/tools/getSessionUsage.js +57 -0
- package/dist/tools/getSessionUsage.js.map +1 -0
- package/dist/tools/getSymbolHistory.d.ts +157 -0
- package/dist/tools/getSymbolHistory.js +256 -0
- package/dist/tools/getSymbolHistory.js.map +1 -0
- package/dist/tools/getToolCapabilities.d.ts +69 -0
- package/dist/tools/getToolCapabilities.js +298 -0
- package/dist/tools/getToolCapabilities.js.map +1 -0
- package/dist/tools/getTypeSignature.d.ts +70 -0
- package/dist/tools/getTypeSignature.js +132 -0
- package/dist/tools/getTypeSignature.js.map +1 -0
- package/dist/tools/getWorkspaceFolders.d.ts +58 -0
- package/dist/tools/getWorkspaceFolders.js +69 -0
- package/dist/tools/getWorkspaceFolders.js.map +1 -0
- package/dist/tools/getWorkspaceSettings.d.ts +44 -0
- package/dist/tools/getWorkspaceSettings.js +70 -0
- package/dist/tools/getWorkspaceSettings.js.map +1 -0
- package/dist/tools/git-utils.d.ts +16 -0
- package/dist/tools/git-utils.js +46 -0
- package/dist/tools/git-utils.js.map +1 -0
- package/dist/tools/gitHistory.d.ts +110 -0
- package/dist/tools/gitHistory.js +167 -0
- package/dist/tools/gitHistory.js.map +1 -0
- package/dist/tools/gitWrite.d.ts +612 -0
- package/dist/tools/gitWrite.js +983 -0
- package/dist/tools/gitWrite.js.map +1 -0
- package/dist/tools/github/actions.d.ts +152 -0
- package/dist/tools/github/actions.js +195 -0
- package/dist/tools/github/actions.js.map +1 -0
- package/dist/tools/github/index.d.ts +3 -0
- package/dist/tools/github/index.js +4 -0
- package/dist/tools/github/index.js.map +1 -0
- package/dist/tools/github/issues.d.ts +281 -0
- package/dist/tools/github/issues.js +340 -0
- package/dist/tools/github/issues.js.map +1 -0
- package/dist/tools/github/pr.d.ts +433 -0
- package/dist/tools/github/pr.js +588 -0
- package/dist/tools/github/pr.js.map +1 -0
- package/dist/tools/github/shared.d.ts +4 -0
- package/dist/tools/github/shared.js +12 -0
- package/dist/tools/github/shared.js.map +1 -0
- package/dist/tools/handoffNote.d.ts +106 -0
- package/dist/tools/handoffNote.js +232 -0
- package/dist/tools/handoffNote.js.map +1 -0
- package/dist/tools/headless/lspClient.d.ts +26 -0
- package/dist/tools/headless/lspClient.js +221 -0
- package/dist/tools/headless/lspClient.js.map +1 -0
- package/dist/tools/headless/lspFallback.d.ts +28 -0
- package/dist/tools/headless/lspFallback.js +122 -0
- package/dist/tools/headless/lspFallback.js.map +1 -0
- package/dist/tools/hoverAtCursor.d.ts +54 -0
- package/dist/tools/hoverAtCursor.js +68 -0
- package/dist/tools/hoverAtCursor.js.map +1 -0
- package/dist/tools/httpClient.d.ts +141 -0
- package/dist/tools/httpClient.js +486 -0
- package/dist/tools/httpClient.js.map +1 -0
- package/dist/tools/index.d.ts +49 -0
- package/dist/tools/index.js +672 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/inlayHints.d.ts +81 -0
- package/dist/tools/inlayHints.js +76 -0
- package/dist/tools/inlayHints.js.map +1 -0
- package/dist/tools/issueRefs.d.ts +14 -0
- package/dist/tools/issueRefs.js +27 -0
- package/dist/tools/issueRefs.js.map +1 -0
- package/dist/tools/jumpToFirstError.d.ts +63 -0
- package/dist/tools/jumpToFirstError.js +124 -0
- package/dist/tools/jumpToFirstError.js.map +1 -0
- package/dist/tools/launchQuickTask.d.ts +76 -0
- package/dist/tools/launchQuickTask.js +170 -0
- package/dist/tools/launchQuickTask.js.map +1 -0
- package/dist/tools/linters/biome.d.ts +2 -0
- package/dist/tools/linters/biome.js +44 -0
- package/dist/tools/linters/biome.js.map +1 -0
- package/dist/tools/linters/cargo.d.ts +2 -0
- package/dist/tools/linters/cargo.js +45 -0
- package/dist/tools/linters/cargo.js.map +1 -0
- package/dist/tools/linters/eslint.d.ts +2 -0
- package/dist/tools/linters/eslint.js +59 -0
- package/dist/tools/linters/eslint.js.map +1 -0
- package/dist/tools/linters/govet.d.ts +2 -0
- package/dist/tools/linters/govet.js +37 -0
- package/dist/tools/linters/govet.js.map +1 -0
- package/dist/tools/linters/pyright.d.ts +2 -0
- package/dist/tools/linters/pyright.js +34 -0
- package/dist/tools/linters/pyright.js.map +1 -0
- package/dist/tools/linters/ruff.d.ts +2 -0
- package/dist/tools/linters/ruff.js +30 -0
- package/dist/tools/linters/ruff.js.map +1 -0
- package/dist/tools/linters/types.d.ts +16 -0
- package/dist/tools/linters/types.js +2 -0
- package/dist/tools/linters/types.js.map +1 -0
- package/dist/tools/linters/typescript.d.ts +2 -0
- package/dist/tools/linters/typescript.js +38 -0
- package/dist/tools/linters/typescript.js.map +1 -0
- package/dist/tools/listClaudeTasks.d.ts +84 -0
- package/dist/tools/listClaudeTasks.js +88 -0
- package/dist/tools/listClaudeTasks.js.map +1 -0
- package/dist/tools/listTerminals.d.ts +55 -0
- package/dist/tools/listTerminals.js +78 -0
- package/dist/tools/listTerminals.js.map +1 -0
- package/dist/tools/lsp.d.ts +1086 -0
- package/dist/tools/lsp.js +1339 -0
- package/dist/tools/lsp.js.map +1 -0
- package/dist/tools/navigateToSymbolByName.d.ts +56 -0
- package/dist/tools/navigateToSymbolByName.js +170 -0
- package/dist/tools/navigateToSymbolByName.js.map +1 -0
- package/dist/tools/openDiff.d.ts +66 -0
- package/dist/tools/openDiff.js +126 -0
- package/dist/tools/openDiff.js.map +1 -0
- package/dist/tools/openFile.d.ts +69 -0
- package/dist/tools/openFile.js +129 -0
- package/dist/tools/openFile.js.map +1 -0
- package/dist/tools/openInBrowser.d.ts +55 -0
- package/dist/tools/openInBrowser.js +129 -0
- package/dist/tools/openInBrowser.js.map +1 -0
- package/dist/tools/organizeImports.d.ts +56 -0
- package/dist/tools/organizeImports.js +115 -0
- package/dist/tools/organizeImports.js.map +1 -0
- package/dist/tools/performanceReport.d.ts +133 -0
- package/dist/tools/performanceReport.js +218 -0
- package/dist/tools/performanceReport.js.map +1 -0
- package/dist/tools/planPersistence.d.ts +306 -0
- package/dist/tools/planPersistence.js +485 -0
- package/dist/tools/planPersistence.js.map +1 -0
- package/dist/tools/previewEdit.d.ts +107 -0
- package/dist/tools/previewEdit.js +270 -0
- package/dist/tools/previewEdit.js.map +1 -0
- package/dist/tools/recentTracesDigest.d.ts +35 -0
- package/dist/tools/recentTracesDigest.js +98 -0
- package/dist/tools/recentTracesDigest.js.map +1 -0
- package/dist/tools/refactorAnalyze.d.ts +78 -0
- package/dist/tools/refactorAnalyze.js +141 -0
- package/dist/tools/refactorAnalyze.js.map +1 -0
- package/dist/tools/refactorExtractFunction.d.ts +52 -0
- package/dist/tools/refactorExtractFunction.js +121 -0
- package/dist/tools/refactorExtractFunction.js.map +1 -0
- package/dist/tools/refactorPreview.d.ts +75 -0
- package/dist/tools/refactorPreview.js +93 -0
- package/dist/tools/refactorPreview.js.map +1 -0
- package/dist/tools/replaceBlock.d.ts +62 -0
- package/dist/tools/replaceBlock.js +125 -0
- package/dist/tools/replaceBlock.js.map +1 -0
- package/dist/tools/resumeClaudeTask.d.ts +75 -0
- package/dist/tools/resumeClaudeTask.js +149 -0
- package/dist/tools/resumeClaudeTask.js.map +1 -0
- package/dist/tools/runClaudeTask.d.ts +97 -0
- package/dist/tools/runClaudeTask.js +224 -0
- package/dist/tools/runClaudeTask.js.map +1 -0
- package/dist/tools/runCommand.d.ts +82 -0
- package/dist/tools/runCommand.js +101 -0
- package/dist/tools/runCommand.js.map +1 -0
- package/dist/tools/runTests.d.ts +146 -0
- package/dist/tools/runTests.js +315 -0
- package/dist/tools/runTests.js.map +1 -0
- package/dist/tools/saveDocument.d.ts +50 -0
- package/dist/tools/saveDocument.js +73 -0
- package/dist/tools/saveDocument.js.map +1 -0
- package/dist/tools/screenshot.d.ts +23 -0
- package/dist/tools/screenshot.js +43 -0
- package/dist/tools/screenshot.js.map +1 -0
- package/dist/tools/screenshotAndAnnotate.d.ts +103 -0
- package/dist/tools/screenshotAndAnnotate.js +192 -0
- package/dist/tools/screenshotAndAnnotate.js.map +1 -0
- package/dist/tools/searchAndReplace.d.ts +108 -0
- package/dist/tools/searchAndReplace.js +281 -0
- package/dist/tools/searchAndReplace.js.map +1 -0
- package/dist/tools/searchTools.d.ts +61 -0
- package/dist/tools/searchTools.js +85 -0
- package/dist/tools/searchTools.js.map +1 -0
- package/dist/tools/searchWorkspace.d.ts +99 -0
- package/dist/tools/searchWorkspace.js +189 -0
- package/dist/tools/searchWorkspace.js.map +1 -0
- package/dist/tools/selectionRanges.d.ts +58 -0
- package/dist/tools/selectionRanges.js +61 -0
- package/dist/tools/selectionRanges.js.map +1 -0
- package/dist/tools/semanticTokens.d.ts +87 -0
- package/dist/tools/semanticTokens.js +86 -0
- package/dist/tools/semanticTokens.js.map +1 -0
- package/dist/tools/setActiveWorkspaceFolder.d.ts +41 -0
- package/dist/tools/setActiveWorkspaceFolder.js +38 -0
- package/dist/tools/setActiveWorkspaceFolder.js.map +1 -0
- package/dist/tools/signatureHelp.d.ts +86 -0
- package/dist/tools/signatureHelp.js +79 -0
- package/dist/tools/signatureHelp.js.map +1 -0
- package/dist/tools/spawnWorkspace.d.ts +103 -0
- package/dist/tools/spawnWorkspace.js +268 -0
- package/dist/tools/spawnWorkspace.js.map +1 -0
- package/dist/tools/stackTraceParser.d.ts +43 -0
- package/dist/tools/stackTraceParser.js +139 -0
- package/dist/tools/stackTraceParser.js.map +1 -0
- package/dist/tools/terminal.d.ts +352 -0
- package/dist/tools/terminal.js +670 -0
- package/dist/tools/terminal.js.map +1 -0
- package/dist/tools/testRunners/cargoTest.d.ts +2 -0
- package/dist/tools/testRunners/cargoTest.js +129 -0
- package/dist/tools/testRunners/cargoTest.js.map +1 -0
- package/dist/tools/testRunners/goTest.d.ts +2 -0
- package/dist/tools/testRunners/goTest.js +108 -0
- package/dist/tools/testRunners/goTest.js.map +1 -0
- package/dist/tools/testRunners/pytest.d.ts +2 -0
- package/dist/tools/testRunners/pytest.js +135 -0
- package/dist/tools/testRunners/pytest.js.map +1 -0
- package/dist/tools/testRunners/types.d.ts +18 -0
- package/dist/tools/testRunners/types.js +2 -0
- package/dist/tools/testRunners/types.js.map +1 -0
- package/dist/tools/testRunners/vitestJest.d.ts +3 -0
- package/dist/tools/testRunners/vitestJest.js +215 -0
- package/dist/tools/testRunners/vitestJest.js.map +1 -0
- package/dist/tools/testTraceToSource.d.ts +80 -0
- package/dist/tools/testTraceToSource.js +206 -0
- package/dist/tools/testTraceToSource.js.map +1 -0
- package/dist/tools/transaction.d.ts +243 -0
- package/dist/tools/transaction.js +309 -0
- package/dist/tools/transaction.js.map +1 -0
- package/dist/tools/typeHierarchy.d.ts +77 -0
- package/dist/tools/typeHierarchy.js +86 -0
- package/dist/tools/typeHierarchy.js.map +1 -0
- package/dist/tools/utils.d.ts +124 -0
- package/dist/tools/utils.js +566 -0
- package/dist/tools/utils.js.map +1 -0
- package/dist/tools/vscodeCommands.d.ts +90 -0
- package/dist/tools/vscodeCommands.js +112 -0
- package/dist/tools/vscodeCommands.js.map +1 -0
- package/dist/tools/vscodeTasks.d.ts +102 -0
- package/dist/tools/vscodeTasks.js +110 -0
- package/dist/tools/vscodeTasks.js.map +1 -0
- package/dist/tools/watchDiagnostics.d.ts +64 -0
- package/dist/tools/watchDiagnostics.js +270 -0
- package/dist/tools/watchDiagnostics.js.map +1 -0
- package/dist/tools/workspaceSettings.d.ts +57 -0
- package/dist/tools/workspaceSettings.js +80 -0
- package/dist/tools/workspaceSettings.js.map +1 -0
- package/dist/transport.d.ts +207 -0
- package/dist/transport.js +1272 -0
- package/dist/transport.js.map +1 -0
- package/dist/version.d.ts +13 -0
- package/dist/version.js +31 -0
- package/dist/version.js.map +1 -0
- package/dist/wsUtils.d.ts +8 -0
- package/dist/wsUtils.js +54 -0
- package/dist/wsUtils.js.map +1 -0
- package/package.json +118 -0
- package/scripts/gen-claude-desktop-config.sh +124 -0
- package/scripts/gen-mcp-config.sh +390 -0
- package/scripts/install-extension.sh +106 -0
- package/scripts/mcp-stdio-shim.cjs +482 -0
- package/scripts/postinstall.mjs +68 -0
- package/scripts/start-all.sh +502 -0
- package/scripts/start-orchestrator.sh +186 -0
- package/scripts/start-remote.sh +126 -0
- package/scripts/start-vps.sh +116 -0
- package/templates/CLAUDE.bridge.md +125 -0
- package/templates/automation-policies/security-first.json +46 -0
- package/templates/automation-policies/strict-lint.json +41 -0
- package/templates/automation-policies/test-driven.json +54 -0
- package/templates/automation-policy.example.json +105 -0
- package/templates/bridge-tools.md +111 -0
- package/templates/dispatch-context.md +33 -0
- package/templates/managed-agent/code-review-agent.md +50 -0
- package/templates/managed-agent/managed-agent-mcp.json +102 -0
- package/templates/recipes/ambient-journal.yaml +11 -0
- package/templates/recipes/daily-status.yaml +21 -0
- package/templates/recipes/lint-on-save.yaml +13 -0
- package/templates/recipes/stale-branches.yaml +18 -0
- package/templates/recipes/watch-failing-tests.yaml +15 -0
- package/templates/scheduled-tasks/dependency-audit/SKILL.md +77 -0
- package/templates/scheduled-tasks/health-check/SKILL.md +73 -0
- package/templates/scheduled-tasks/nightly-review/SKILL.md +69 -0
|
@@ -0,0 +1,670 @@
|
|
|
1
|
+
import { INTERPRETER_COMMANDS } from "../config.js";
|
|
2
|
+
import { ExtensionTimeoutError, } from "../extensionClient.js";
|
|
3
|
+
import { error, execSafe, extensionRequired, optionalBool, optionalInt, optionalString, requireString, resolveFilePath, successStructured, } from "./utils.js";
|
|
4
|
+
/**
|
|
5
|
+
* Flags that allow interpreter commands to execute arbitrary code.
|
|
6
|
+
* Mirrors DANGEROUS_INTERPRETER_FLAGS in runCommand.ts — applied here to
|
|
7
|
+
* terminal commands where the shell is involved and quoting cannot be trusted.
|
|
8
|
+
*/
|
|
9
|
+
const TERMINAL_DANGEROUS_INTERPRETER_FLAGS = new Set([
|
|
10
|
+
"-e",
|
|
11
|
+
"--eval",
|
|
12
|
+
"-c",
|
|
13
|
+
"--print",
|
|
14
|
+
"-p",
|
|
15
|
+
"--input-type",
|
|
16
|
+
"--import",
|
|
17
|
+
"--loader",
|
|
18
|
+
"--experimental-loader",
|
|
19
|
+
"-m",
|
|
20
|
+
"--inspect", // Node.js debugger — opens a remote debug port
|
|
21
|
+
"--inspect-brk", // Node.js debugger (break on start)
|
|
22
|
+
"--inspect-port", // Node.js debugger port override
|
|
23
|
+
]);
|
|
24
|
+
/**
|
|
25
|
+
* Flags that redirect where commands read config/manifests from.
|
|
26
|
+
* Mirrors DANGEROUS_PATH_FLAGS in runCommand.ts.
|
|
27
|
+
*/
|
|
28
|
+
const TERMINAL_DANGEROUS_PATH_FLAGS = new Set([
|
|
29
|
+
"--prefix",
|
|
30
|
+
"--manifest-path",
|
|
31
|
+
"--config",
|
|
32
|
+
"--rcfile",
|
|
33
|
+
"--require",
|
|
34
|
+
"-r",
|
|
35
|
+
"--userconfig",
|
|
36
|
+
"--globalconfig",
|
|
37
|
+
"-f",
|
|
38
|
+
"--makefile",
|
|
39
|
+
]);
|
|
40
|
+
/**
|
|
41
|
+
* Per-command exemptions from TERMINAL_DANGEROUS_PATH_FLAGS.
|
|
42
|
+
* Mirrors PATH_FLAG_EXEMPTIONS in runCommand.ts.
|
|
43
|
+
*/
|
|
44
|
+
const TERMINAL_PATH_FLAG_EXEMPTIONS = {
|
|
45
|
+
psql: new Set(["--config"]),
|
|
46
|
+
pg_dump: new Set(["--config"]),
|
|
47
|
+
pg_restore: new Set(["--config"]),
|
|
48
|
+
};
|
|
49
|
+
/** Environment variable names that could enable privilege escalation */
|
|
50
|
+
const DANGEROUS_ENV_VARS = new Set([
|
|
51
|
+
"PATH",
|
|
52
|
+
"LD_PRELOAD",
|
|
53
|
+
"LD_LIBRARY_PATH",
|
|
54
|
+
"DYLD_INSERT_LIBRARIES",
|
|
55
|
+
"DYLD_LIBRARY_PATH",
|
|
56
|
+
"DYLD_FRAMEWORK_PATH",
|
|
57
|
+
"NODE_OPTIONS",
|
|
58
|
+
"NODE_PATH",
|
|
59
|
+
"PYTHONSTARTUP",
|
|
60
|
+
"PYTHONPATH",
|
|
61
|
+
"PYTHONHOME",
|
|
62
|
+
"RUBYOPT",
|
|
63
|
+
"RUBYLIB",
|
|
64
|
+
"PERL5OPT",
|
|
65
|
+
"PERL5LIB",
|
|
66
|
+
"CLASSPATH",
|
|
67
|
+
"BASH_ENV",
|
|
68
|
+
"ENV",
|
|
69
|
+
"ZDOTDIR",
|
|
70
|
+
"EDITOR",
|
|
71
|
+
"VISUAL",
|
|
72
|
+
"SHELL",
|
|
73
|
+
"HOME",
|
|
74
|
+
"XDG_CONFIG_HOME",
|
|
75
|
+
"XDG_DATA_HOME",
|
|
76
|
+
"GIT_SSH_COMMAND",
|
|
77
|
+
"GIT_EXEC_PATH",
|
|
78
|
+
"NPM_CONFIG_SCRIPT_SHELL",
|
|
79
|
+
"CARGO_HOME",
|
|
80
|
+
]);
|
|
81
|
+
/**
|
|
82
|
+
* Validate terminal command tokens for dangerous flags.
|
|
83
|
+
* Returns an error string if a dangerous flag is found, undefined otherwise.
|
|
84
|
+
*
|
|
85
|
+
* Terminal commands run inside a real shell, so flag-level argument injection
|
|
86
|
+
* (e.g. `git -c core.pager=evil`) cannot be caught by the metacharacter filter.
|
|
87
|
+
* We apply the same flag blocklists used by runCommand for interpreter and
|
|
88
|
+
* config-redirect flags.
|
|
89
|
+
*/
|
|
90
|
+
function validateTerminalCommandFlags(command) {
|
|
91
|
+
const tokens = command.trim().split(/\s+/);
|
|
92
|
+
const cmd = tokens[0]?.toLowerCase() ?? "";
|
|
93
|
+
const isInterpreter = INTERPRETER_COMMANDS.has(cmd);
|
|
94
|
+
for (let i = 1; i < tokens.length; i++) {
|
|
95
|
+
const tok = tokens[i] ?? "";
|
|
96
|
+
// Strip value for flags like --config=value → --config
|
|
97
|
+
const flag = tok.split("=")[0] ?? tok;
|
|
98
|
+
if (isInterpreter && TERMINAL_DANGEROUS_INTERPRETER_FLAGS.has(flag)) {
|
|
99
|
+
return `Flag "${flag}" is not allowed for interpreter command "${cmd}" (code execution risk)`;
|
|
100
|
+
}
|
|
101
|
+
const exemptions = TERMINAL_PATH_FLAG_EXEMPTIONS[cmd];
|
|
102
|
+
if (TERMINAL_DANGEROUS_PATH_FLAGS.has(flag) && !exemptions?.has(flag)) {
|
|
103
|
+
return `Flag "${flag}" is not allowed in terminal commands (config redirect risk)`;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
return undefined;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Validate a terminal command string against security rules.
|
|
110
|
+
* Returns an error message if invalid, undefined if the command is safe.
|
|
111
|
+
*/
|
|
112
|
+
function validateCommand(text, commandAllowlist) {
|
|
113
|
+
// Reject non-ASCII whitespace (U+00A0, etc.) — these bypass quote guard but
|
|
114
|
+
// pass whitespace-splitting checks, potentially corrupting the argv array.
|
|
115
|
+
if (/[\u00a0\u1680\u2000-\u200a\u2028\u2029\u202f\u205f\u3000]/.test(text)) {
|
|
116
|
+
return "Command must not contain non-ASCII whitespace characters.";
|
|
117
|
+
}
|
|
118
|
+
// Also block Unicode line/paragraph separators (\u2028, \u2029) which act
|
|
119
|
+
// as line terminators in JavaScript and some shell contexts.
|
|
120
|
+
if (/[\n\r\u2028\u2029]/.test(text)) {
|
|
121
|
+
return "Command must not contain newlines. Send one command at a time.";
|
|
122
|
+
}
|
|
123
|
+
if (/[;&|`$()<>{}!\\~]/.test(text)) {
|
|
124
|
+
return ("Command must not contain shell metacharacters (;&|`$()<>{}!\\~). " +
|
|
125
|
+
"These could chain additional commands beyond the allowlist.");
|
|
126
|
+
}
|
|
127
|
+
const firstWord = text.trim().split(/\s+/)[0]?.toLowerCase();
|
|
128
|
+
if (firstWord && !commandAllowlist.includes(firstWord)) {
|
|
129
|
+
return (`Command "${firstWord}" is not in the allowlist. ` +
|
|
130
|
+
`Allowed commands: ${commandAllowlist.join(", ")}. ` +
|
|
131
|
+
`Use --allow-command ${firstWord} to add it.`);
|
|
132
|
+
}
|
|
133
|
+
return validateTerminalCommandFlags(text);
|
|
134
|
+
}
|
|
135
|
+
/** Apply prefix to a terminal name (no-op when prefix is empty).
|
|
136
|
+
* When prefix is set and name is undefined, generates a unique prefixed default name
|
|
137
|
+
* so the terminal remains discoverable by listTerminals for this session. */
|
|
138
|
+
function prefixName(name, prefix) {
|
|
139
|
+
if (!prefix)
|
|
140
|
+
return name;
|
|
141
|
+
if (name === undefined) {
|
|
142
|
+
// Generate a unique default so unnamed terminals are still session-scoped
|
|
143
|
+
return `${prefix}terminal-${Date.now().toString(36)}`;
|
|
144
|
+
}
|
|
145
|
+
return `${prefix}${name}`;
|
|
146
|
+
}
|
|
147
|
+
/** Strip prefix from a terminal name (no-op when prefix is empty). */
|
|
148
|
+
function stripPrefix(name, prefix) {
|
|
149
|
+
if (!prefix)
|
|
150
|
+
return name;
|
|
151
|
+
return name.startsWith(prefix) ? name.slice(prefix.length) : name;
|
|
152
|
+
}
|
|
153
|
+
/** In multi-session mode, index-based terminal lookup is unsafe because the
|
|
154
|
+
* global index does not correspond to the session-scoped index shown by listTerminals.
|
|
155
|
+
* Returns an error string when this case is detected, or null if the call is safe. */
|
|
156
|
+
function checkIndexWithPrefix(name, index, prefix) {
|
|
157
|
+
if (prefix && name === undefined && index !== undefined) {
|
|
158
|
+
return ("Terminal index-based lookup is not supported when multiple agent sessions are active. " +
|
|
159
|
+
"Use terminal name instead (from listTerminals). " +
|
|
160
|
+
"Index 0 in your session refers to a different global index than in VS Code.");
|
|
161
|
+
}
|
|
162
|
+
return null;
|
|
163
|
+
}
|
|
164
|
+
export function createGetTerminalOutputTool(extensionClient, terminalPrefix = "") {
|
|
165
|
+
return {
|
|
166
|
+
schema: {
|
|
167
|
+
name: "getTerminalOutput",
|
|
168
|
+
extensionRequired: true,
|
|
169
|
+
description: "Get recent output from a VS Code integrated terminal. Identify by name or index (from listTerminals). Returns last N lines. On headless VPS/SSH, use runInTerminal instead.",
|
|
170
|
+
annotations: { readOnlyHint: true },
|
|
171
|
+
inputSchema: {
|
|
172
|
+
type: "object",
|
|
173
|
+
properties: {
|
|
174
|
+
name: {
|
|
175
|
+
type: "string",
|
|
176
|
+
description: "Terminal name to retrieve output from",
|
|
177
|
+
},
|
|
178
|
+
index: {
|
|
179
|
+
type: "integer",
|
|
180
|
+
description: "Terminal index (0-based) from listTerminals",
|
|
181
|
+
},
|
|
182
|
+
lines: {
|
|
183
|
+
type: "integer",
|
|
184
|
+
description: "Recent lines to retrieve (default 100, max 5000)",
|
|
185
|
+
},
|
|
186
|
+
},
|
|
187
|
+
additionalProperties: false,
|
|
188
|
+
},
|
|
189
|
+
outputSchema: {
|
|
190
|
+
type: "object",
|
|
191
|
+
properties: {
|
|
192
|
+
output: { type: "string" },
|
|
193
|
+
lines: { type: "array", items: { type: "string" } },
|
|
194
|
+
},
|
|
195
|
+
},
|
|
196
|
+
},
|
|
197
|
+
handler: async (args, _signal) => {
|
|
198
|
+
if (!extensionClient.isConnected()) {
|
|
199
|
+
return extensionRequired("terminal output");
|
|
200
|
+
}
|
|
201
|
+
const name = optionalString(args, "name", 256);
|
|
202
|
+
const index = optionalInt(args, "index", 0, 100);
|
|
203
|
+
const lines = optionalInt(args, "lines", 1, 5000);
|
|
204
|
+
if (name === undefined && index === undefined) {
|
|
205
|
+
return error("At least one of 'name' or 'index' must be provided to identify the terminal");
|
|
206
|
+
}
|
|
207
|
+
const indexErr = checkIndexWithPrefix(name, index, terminalPrefix);
|
|
208
|
+
if (indexErr)
|
|
209
|
+
return error(indexErr);
|
|
210
|
+
try {
|
|
211
|
+
const result = await extensionClient.getTerminalOutput(prefixName(name, terminalPrefix), index, lines);
|
|
212
|
+
if (result === null) {
|
|
213
|
+
return error("Terminal not found");
|
|
214
|
+
}
|
|
215
|
+
return successStructured(result);
|
|
216
|
+
}
|
|
217
|
+
catch (err) {
|
|
218
|
+
if (err instanceof ExtensionTimeoutError) {
|
|
219
|
+
return error("Extension timed out — terminal features may be unavailable");
|
|
220
|
+
}
|
|
221
|
+
throw err;
|
|
222
|
+
}
|
|
223
|
+
},
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
export function createCreateTerminalTool(workspace, extensionClient, terminalPrefix = "") {
|
|
227
|
+
return {
|
|
228
|
+
schema: {
|
|
229
|
+
name: "createTerminal",
|
|
230
|
+
extensionRequired: true,
|
|
231
|
+
annotations: { destructiveHint: true },
|
|
232
|
+
description: "Create VS Code integrated terminal. Options: name, cwd, env vars, shell.",
|
|
233
|
+
inputSchema: {
|
|
234
|
+
type: "object",
|
|
235
|
+
properties: {
|
|
236
|
+
name: {
|
|
237
|
+
type: "string",
|
|
238
|
+
description: "Display name for the terminal",
|
|
239
|
+
},
|
|
240
|
+
cwd: {
|
|
241
|
+
type: "string",
|
|
242
|
+
description: "Working dir for terminal (must be within workspace)",
|
|
243
|
+
},
|
|
244
|
+
env: {
|
|
245
|
+
type: "object",
|
|
246
|
+
description: "Extra env vars (key-value pairs, max 50 entries)",
|
|
247
|
+
additionalProperties: { type: "string" },
|
|
248
|
+
},
|
|
249
|
+
show: {
|
|
250
|
+
type: "boolean",
|
|
251
|
+
description: "Show terminal panel after creation (default: true)",
|
|
252
|
+
},
|
|
253
|
+
},
|
|
254
|
+
additionalProperties: false,
|
|
255
|
+
},
|
|
256
|
+
outputSchema: {
|
|
257
|
+
type: "object",
|
|
258
|
+
properties: {
|
|
259
|
+
name: { type: "string" },
|
|
260
|
+
index: { type: "integer" },
|
|
261
|
+
},
|
|
262
|
+
},
|
|
263
|
+
},
|
|
264
|
+
handler: async (args, _signal) => {
|
|
265
|
+
if (!extensionClient.isConnected()) {
|
|
266
|
+
return extensionRequired("createTerminal");
|
|
267
|
+
}
|
|
268
|
+
const name = optionalString(args, "name", 256);
|
|
269
|
+
const rawCwd = optionalString(args, "cwd");
|
|
270
|
+
const resolvedCwd = rawCwd
|
|
271
|
+
? resolveFilePath(rawCwd, workspace)
|
|
272
|
+
: undefined;
|
|
273
|
+
const rawEnv = args.env;
|
|
274
|
+
let env;
|
|
275
|
+
if (rawEnv !== undefined) {
|
|
276
|
+
if (typeof rawEnv !== "object" ||
|
|
277
|
+
rawEnv === null ||
|
|
278
|
+
Array.isArray(rawEnv)) {
|
|
279
|
+
return error("'env' must be an object with string key-value pairs");
|
|
280
|
+
}
|
|
281
|
+
const keys = Object.keys(rawEnv);
|
|
282
|
+
if (keys.length > 50) {
|
|
283
|
+
return error("'env' must have at most 50 entries");
|
|
284
|
+
}
|
|
285
|
+
env = {};
|
|
286
|
+
for (const [k, v] of Object.entries(rawEnv)) {
|
|
287
|
+
if (typeof v !== "string") {
|
|
288
|
+
return error(`env["${k}"] must be a string`);
|
|
289
|
+
}
|
|
290
|
+
if (DANGEROUS_ENV_VARS.has(k.toUpperCase())) {
|
|
291
|
+
return error(`Environment variable "${k}" is blocked for security — it can redirect command execution`);
|
|
292
|
+
}
|
|
293
|
+
env[k] = v;
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
const show = optionalBool(args, "show") ?? true;
|
|
297
|
+
try {
|
|
298
|
+
const result = await extensionClient.createTerminal(prefixName(name, terminalPrefix), resolvedCwd, env, show);
|
|
299
|
+
if (result === null) {
|
|
300
|
+
return error("Failed to create terminal");
|
|
301
|
+
}
|
|
302
|
+
// Strip prefix from returned name so the agent sees its logical name
|
|
303
|
+
const resultWithName = result;
|
|
304
|
+
const stripped = terminalPrefix && resultWithName.name
|
|
305
|
+
? {
|
|
306
|
+
...result,
|
|
307
|
+
name: stripPrefix(resultWithName.name, terminalPrefix),
|
|
308
|
+
}
|
|
309
|
+
: result;
|
|
310
|
+
return successStructured(stripped);
|
|
311
|
+
}
|
|
312
|
+
catch (err) {
|
|
313
|
+
if (err instanceof ExtensionTimeoutError) {
|
|
314
|
+
return error("Extension timed out — terminal features may be unavailable");
|
|
315
|
+
}
|
|
316
|
+
throw err;
|
|
317
|
+
}
|
|
318
|
+
},
|
|
319
|
+
};
|
|
320
|
+
}
|
|
321
|
+
export function createWaitForTerminalOutputTool(extensionClient, terminalPrefix = "") {
|
|
322
|
+
return {
|
|
323
|
+
schema: {
|
|
324
|
+
name: "waitForTerminalOutput",
|
|
325
|
+
extensionRequired: true,
|
|
326
|
+
description: "Block until regex matches terminal output. Returns {matched, matchedLine, elapsed} or timedOut.",
|
|
327
|
+
annotations: { readOnlyHint: true },
|
|
328
|
+
inputSchema: {
|
|
329
|
+
type: "object",
|
|
330
|
+
required: ["pattern"],
|
|
331
|
+
properties: {
|
|
332
|
+
pattern: {
|
|
333
|
+
type: "string",
|
|
334
|
+
description: "JS regex to match against terminal output lines",
|
|
335
|
+
},
|
|
336
|
+
name: {
|
|
337
|
+
type: "string",
|
|
338
|
+
description: "Terminal name (from listTerminals). Uses active if omitted.",
|
|
339
|
+
},
|
|
340
|
+
index: {
|
|
341
|
+
type: "integer",
|
|
342
|
+
description: "Terminal index (0-based) from listTerminals. Used if name omitted.",
|
|
343
|
+
},
|
|
344
|
+
timeout: {
|
|
345
|
+
type: "integer",
|
|
346
|
+
description: "Seconds to wait (default: 30, max: 300)",
|
|
347
|
+
},
|
|
348
|
+
},
|
|
349
|
+
additionalProperties: false,
|
|
350
|
+
},
|
|
351
|
+
outputSchema: {
|
|
352
|
+
type: "object",
|
|
353
|
+
properties: {
|
|
354
|
+
matched: { type: "boolean" },
|
|
355
|
+
matchedLine: { type: "string" },
|
|
356
|
+
elapsed: { type: "integer" },
|
|
357
|
+
timedOut: { type: "boolean" },
|
|
358
|
+
},
|
|
359
|
+
required: ["matched"],
|
|
360
|
+
},
|
|
361
|
+
},
|
|
362
|
+
// Extension adds a 5 s internal buffer on top of the user timeout — raise
|
|
363
|
+
// the tool ceiling by 10 s so the extension response always arrives before
|
|
364
|
+
// the MCP transport cancels the request.
|
|
365
|
+
timeoutMs: 610_000,
|
|
366
|
+
handler: async (args, _signal) => {
|
|
367
|
+
if (!extensionClient.isConnected()) {
|
|
368
|
+
return extensionRequired("waitForTerminalOutput");
|
|
369
|
+
}
|
|
370
|
+
const pattern = requireString(args, "pattern", 1_000);
|
|
371
|
+
const name = optionalString(args, "name", 256);
|
|
372
|
+
const index = optionalInt(args, "index", 0, 100);
|
|
373
|
+
const timeoutSec = optionalInt(args, "timeout", 1, 300) ?? 30;
|
|
374
|
+
const timeoutMs = timeoutSec * 1_000;
|
|
375
|
+
const indexErr = checkIndexWithPrefix(name, index, terminalPrefix);
|
|
376
|
+
if (indexErr)
|
|
377
|
+
return error(indexErr);
|
|
378
|
+
// Validate the regex on the bridge side to give a fast, clear error
|
|
379
|
+
try {
|
|
380
|
+
new RegExp(pattern);
|
|
381
|
+
}
|
|
382
|
+
catch (e) {
|
|
383
|
+
return error(`Invalid regex pattern: ${e instanceof Error ? e.message : String(e)}`);
|
|
384
|
+
}
|
|
385
|
+
// Reject patterns with nested quantifiers — these can cause catastrophic backtracking (ReDoS)
|
|
386
|
+
// when tested repeatedly against terminal output lines over a long polling window.
|
|
387
|
+
if (/\([^)]*[+*]\)[+*?]/.test(pattern) ||
|
|
388
|
+
/\([^)]*\{[^}]+\}\)[+*{?]/.test(pattern) ||
|
|
389
|
+
/[+*][+*]|\{[^}]+\}[+*]/.test(pattern)) {
|
|
390
|
+
return error("Pattern contains nested quantifiers (e.g. (a+)+) which can cause catastrophic backtracking. " +
|
|
391
|
+
"Simplify the regex — use a literal string match or a non-nested quantifier.");
|
|
392
|
+
}
|
|
393
|
+
try {
|
|
394
|
+
const result = await extensionClient.waitForTerminalOutput(pattern, prefixName(name, terminalPrefix), index, timeoutMs);
|
|
395
|
+
if (result === null) {
|
|
396
|
+
return error("Extension did not respond — ensure the VS Code extension is running");
|
|
397
|
+
}
|
|
398
|
+
return successStructured(result);
|
|
399
|
+
}
|
|
400
|
+
catch (err) {
|
|
401
|
+
if (err instanceof ExtensionTimeoutError) {
|
|
402
|
+
return error("Extension connection timed out waiting for terminal output");
|
|
403
|
+
}
|
|
404
|
+
throw err;
|
|
405
|
+
}
|
|
406
|
+
},
|
|
407
|
+
};
|
|
408
|
+
}
|
|
409
|
+
export function createRunInTerminalTool(workspace, extensionClient, commandAllowlist, terminalPrefix = "") {
|
|
410
|
+
return {
|
|
411
|
+
schema: {
|
|
412
|
+
name: "runInTerminal",
|
|
413
|
+
annotations: { destructiveHint: true, openWorldHint: true },
|
|
414
|
+
description: "Execute command and wait for completion. Returns exit code and output. Prefer over runCommand.",
|
|
415
|
+
inputSchema: {
|
|
416
|
+
type: "object",
|
|
417
|
+
required: ["command"],
|
|
418
|
+
properties: {
|
|
419
|
+
command: {
|
|
420
|
+
type: "string",
|
|
421
|
+
description: "Shell command to run (no metacharacters or newlines)",
|
|
422
|
+
},
|
|
423
|
+
name: {
|
|
424
|
+
type: "string",
|
|
425
|
+
description: "Terminal name (from listTerminals). Uses active if omitted.",
|
|
426
|
+
},
|
|
427
|
+
index: {
|
|
428
|
+
type: "integer",
|
|
429
|
+
description: "Terminal index (0-based) from listTerminals. Used if name omitted.",
|
|
430
|
+
},
|
|
431
|
+
timeout: {
|
|
432
|
+
type: "integer",
|
|
433
|
+
description: "Seconds to wait for completion (default: 30, max: 300)",
|
|
434
|
+
},
|
|
435
|
+
show: {
|
|
436
|
+
type: "boolean",
|
|
437
|
+
description: "Focus terminal panel while running (default: true)",
|
|
438
|
+
},
|
|
439
|
+
},
|
|
440
|
+
additionalProperties: false,
|
|
441
|
+
},
|
|
442
|
+
outputSchema: {
|
|
443
|
+
type: "object",
|
|
444
|
+
properties: {
|
|
445
|
+
exitCode: { type: "integer" },
|
|
446
|
+
stdout: { type: "string" },
|
|
447
|
+
stderr: { type: "string" },
|
|
448
|
+
fallback: { type: "string" },
|
|
449
|
+
},
|
|
450
|
+
},
|
|
451
|
+
},
|
|
452
|
+
// Extension adds a 5 s internal buffer on top of the user timeout — raise
|
|
453
|
+
// the tool ceiling by 10 s so the extension response always arrives before
|
|
454
|
+
// the MCP transport cancels the request.
|
|
455
|
+
timeoutMs: 610_000,
|
|
456
|
+
handler: async (args, signal) => {
|
|
457
|
+
const command = requireString(args, "command", 10_000);
|
|
458
|
+
const name = optionalString(args, "name", 256);
|
|
459
|
+
const index = optionalInt(args, "index", 0, 100);
|
|
460
|
+
const timeoutSec = optionalInt(args, "timeout", 1, 300) ?? 30;
|
|
461
|
+
const show = optionalBool(args, "show") ?? true;
|
|
462
|
+
const timeoutMs = timeoutSec * 1_000;
|
|
463
|
+
const cmdErr = validateCommand(command, commandAllowlist);
|
|
464
|
+
if (cmdErr)
|
|
465
|
+
return error(cmdErr);
|
|
466
|
+
// Attempt VS Code shell integration path when extension is connected
|
|
467
|
+
if (extensionClient.isConnected()) {
|
|
468
|
+
const indexErr = checkIndexWithPrefix(name, index, terminalPrefix);
|
|
469
|
+
if (indexErr)
|
|
470
|
+
return error(indexErr);
|
|
471
|
+
try {
|
|
472
|
+
const result = await extensionClient.executeInTerminal(command, prefixName(name, terminalPrefix), index, timeoutMs, show);
|
|
473
|
+
if (result !== null) {
|
|
474
|
+
return successStructured(result);
|
|
475
|
+
}
|
|
476
|
+
// null means shell integration unavailable (SSH remote, no PTY hooks)
|
|
477
|
+
// — fall through to subprocess fallback below
|
|
478
|
+
}
|
|
479
|
+
catch (err) {
|
|
480
|
+
if (err instanceof ExtensionTimeoutError) {
|
|
481
|
+
// The command was already dispatched to the VS Code terminal but shell
|
|
482
|
+
// integration did not return output in time. Do NOT fall through to the
|
|
483
|
+
// subprocess fallback — the command may have already started running and
|
|
484
|
+
// re-executing it would double-invoke non-idempotent operations.
|
|
485
|
+
return error("runInTerminal timed out waiting for shell integration output. " +
|
|
486
|
+
"The command may still be running in the VS Code terminal. " +
|
|
487
|
+
"Use runCommand for non-interactive commands that need reliable output capture.");
|
|
488
|
+
}
|
|
489
|
+
throw err;
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
// Subprocess fallback: runs the command directly in the workspace using
|
|
493
|
+
// execSafe (same primitive as runCommand). This path activates when:
|
|
494
|
+
// • The extension is not connected
|
|
495
|
+
// • Shell integration is unavailable (SSH remote, headless VPS)
|
|
496
|
+
// • executeInTerminal timed out waiting for a shell event
|
|
497
|
+
//
|
|
498
|
+
// The command has already passed validateCommand so first-token allowlist
|
|
499
|
+
// and metacharacter checks are satisfied. Split on whitespace for execSafe
|
|
500
|
+
// which takes argv-style args rather than a raw shell string.
|
|
501
|
+
// Reject quoted arguments — naive whitespace splitting cannot handle them
|
|
502
|
+
// correctly and would corrupt the argv array (e.g. "npm run 'my script'"
|
|
503
|
+
// becomes ["npm", "run", "'my", "script'"]). Use runCommand with an
|
|
504
|
+
// explicit args array for commands with space-containing arguments.
|
|
505
|
+
if (/"/.test(command) || /'/.test(command)) {
|
|
506
|
+
return error("runInTerminal does not support quoted arguments in the fallback (headless) path. " +
|
|
507
|
+
"Use runCommand with an explicit args array for arguments containing spaces.");
|
|
508
|
+
}
|
|
509
|
+
const tokens = command.trim().split(/\s+/);
|
|
510
|
+
const cmd = tokens[0] ?? command;
|
|
511
|
+
const cmdArgs = tokens.slice(1);
|
|
512
|
+
const fallbackResult = await execSafe(cmd, cmdArgs, {
|
|
513
|
+
cwd: workspace,
|
|
514
|
+
timeout: timeoutMs,
|
|
515
|
+
signal: signal ?? undefined,
|
|
516
|
+
});
|
|
517
|
+
return successStructured({ ...fallbackResult, fallback: "subprocess" });
|
|
518
|
+
},
|
|
519
|
+
};
|
|
520
|
+
}
|
|
521
|
+
export function createDisposeTerminalTool(extensionClient, terminalPrefix = "") {
|
|
522
|
+
return {
|
|
523
|
+
schema: {
|
|
524
|
+
name: "disposeTerminal",
|
|
525
|
+
extensionRequired: true,
|
|
526
|
+
description: "Close a VS Code terminal by name or index.",
|
|
527
|
+
annotations: { destructiveHint: true },
|
|
528
|
+
inputSchema: {
|
|
529
|
+
type: "object",
|
|
530
|
+
properties: {
|
|
531
|
+
name: {
|
|
532
|
+
type: "string",
|
|
533
|
+
description: "Terminal name to dispose",
|
|
534
|
+
},
|
|
535
|
+
index: {
|
|
536
|
+
type: "integer",
|
|
537
|
+
description: "Terminal index (0-based) from listTerminals",
|
|
538
|
+
},
|
|
539
|
+
},
|
|
540
|
+
additionalProperties: false,
|
|
541
|
+
},
|
|
542
|
+
outputSchema: {
|
|
543
|
+
type: "object",
|
|
544
|
+
properties: {
|
|
545
|
+
disposed: { type: "boolean" },
|
|
546
|
+
},
|
|
547
|
+
},
|
|
548
|
+
},
|
|
549
|
+
handler: async (args, _signal) => {
|
|
550
|
+
if (!extensionClient.isConnected()) {
|
|
551
|
+
return extensionRequired("disposeTerminal");
|
|
552
|
+
}
|
|
553
|
+
const name = optionalString(args, "name", 256);
|
|
554
|
+
const index = optionalInt(args, "index", 0, 100);
|
|
555
|
+
if (name === undefined && index === undefined) {
|
|
556
|
+
return error("At least one of 'name' or 'index' must be provided to identify the terminal");
|
|
557
|
+
}
|
|
558
|
+
const indexErr = checkIndexWithPrefix(name, index, terminalPrefix);
|
|
559
|
+
if (indexErr)
|
|
560
|
+
return error(indexErr);
|
|
561
|
+
try {
|
|
562
|
+
const result = await extensionClient.disposeTerminal(prefixName(name, terminalPrefix), index);
|
|
563
|
+
if (result === null) {
|
|
564
|
+
return error("Terminal not found");
|
|
565
|
+
}
|
|
566
|
+
return successStructured(result);
|
|
567
|
+
}
|
|
568
|
+
catch (err) {
|
|
569
|
+
if (err instanceof ExtensionTimeoutError) {
|
|
570
|
+
return error("Extension timed out — terminal features may be unavailable");
|
|
571
|
+
}
|
|
572
|
+
throw err;
|
|
573
|
+
}
|
|
574
|
+
},
|
|
575
|
+
};
|
|
576
|
+
}
|
|
577
|
+
export function createSendTerminalCommandTool(extensionClient, commandAllowlist, terminalPrefix = "") {
|
|
578
|
+
return {
|
|
579
|
+
schema: {
|
|
580
|
+
name: "sendTerminalCommand",
|
|
581
|
+
extensionRequired: true,
|
|
582
|
+
annotations: { destructiveHint: true, openWorldHint: true },
|
|
583
|
+
description: "Send text/command to VS Code terminal. Fire-and-forget; use getTerminalOutput to check results.",
|
|
584
|
+
inputSchema: {
|
|
585
|
+
type: "object",
|
|
586
|
+
required: ["text"],
|
|
587
|
+
properties: {
|
|
588
|
+
text: {
|
|
589
|
+
type: "string",
|
|
590
|
+
description: "Text or command to send to the terminal",
|
|
591
|
+
},
|
|
592
|
+
name: {
|
|
593
|
+
type: "string",
|
|
594
|
+
description: "Terminal name to send to",
|
|
595
|
+
},
|
|
596
|
+
index: {
|
|
597
|
+
type: "integer",
|
|
598
|
+
description: "Terminal index (0-based) from listTerminals",
|
|
599
|
+
},
|
|
600
|
+
addNewline: {
|
|
601
|
+
type: "boolean",
|
|
602
|
+
description: "Append newline to execute as command (default: true)",
|
|
603
|
+
},
|
|
604
|
+
isCommand: {
|
|
605
|
+
type: "boolean",
|
|
606
|
+
description: "False for short stdin responses to prompts (max 512 chars, no shell metacharacters).",
|
|
607
|
+
},
|
|
608
|
+
},
|
|
609
|
+
additionalProperties: false,
|
|
610
|
+
},
|
|
611
|
+
outputSchema: {
|
|
612
|
+
type: "object",
|
|
613
|
+
properties: {
|
|
614
|
+
sent: { type: "boolean" },
|
|
615
|
+
},
|
|
616
|
+
},
|
|
617
|
+
},
|
|
618
|
+
handler: async (args, _signal) => {
|
|
619
|
+
if (!extensionClient.isConnected()) {
|
|
620
|
+
return extensionRequired("sendTerminalCommand");
|
|
621
|
+
}
|
|
622
|
+
const text = requireString(args, "text", 10_000);
|
|
623
|
+
const name = optionalString(args, "name", 256);
|
|
624
|
+
const index = optionalInt(args, "index", 0, 100);
|
|
625
|
+
const addNewline = optionalBool(args, "addNewline") ?? true;
|
|
626
|
+
const isCommand = optionalBool(args, "isCommand") ?? true;
|
|
627
|
+
if (name === undefined && index === undefined) {
|
|
628
|
+
return error("At least one of 'name' or 'index' must be provided to identify the terminal");
|
|
629
|
+
}
|
|
630
|
+
const indexErr = checkIndexWithPrefix(name, index, terminalPrefix);
|
|
631
|
+
if (indexErr)
|
|
632
|
+
return error(indexErr);
|
|
633
|
+
if (isCommand) {
|
|
634
|
+
const cmdErr = validateCommand(text, commandAllowlist);
|
|
635
|
+
if (cmdErr)
|
|
636
|
+
return error(cmdErr);
|
|
637
|
+
}
|
|
638
|
+
else {
|
|
639
|
+
// isCommand:false is for short stdin responses to interactive prompts only.
|
|
640
|
+
// Enforce a tight length cap and block shell metacharacters to prevent
|
|
641
|
+
// this path from being used as an allowlist bypass for arbitrary shell commands.
|
|
642
|
+
if (text.length > 512) {
|
|
643
|
+
return error("isCommand:false input must be 512 characters or fewer (stdin prompt responses only)");
|
|
644
|
+
}
|
|
645
|
+
if (/[|&;<>`$(){}[\]\n\r]/.test(text)) {
|
|
646
|
+
return error("isCommand:false input must not contain shell metacharacters (|, &, ;, <, >, `, $, (, ), {, }, [, ], newlines). Use isCommand:true for shell commands.");
|
|
647
|
+
}
|
|
648
|
+
// Reject ASCII control characters (below 0x20, excluding tab)
|
|
649
|
+
// to prevent terminal injection via Ctrl-C (0x03), Ctrl-D (0x04), etc.
|
|
650
|
+
if (/[\x00-\x08\x0b-\x1f\x7f]/.test(text)) {
|
|
651
|
+
return error("isCommand:false input must not contain ASCII control characters (Ctrl-C, Ctrl-D, ESC, etc.).");
|
|
652
|
+
}
|
|
653
|
+
}
|
|
654
|
+
try {
|
|
655
|
+
const result = await extensionClient.sendTerminalCommand(text, prefixName(name, terminalPrefix), index, addNewline);
|
|
656
|
+
if (result === null) {
|
|
657
|
+
return error("Failed to send command to terminal");
|
|
658
|
+
}
|
|
659
|
+
return successStructured(result);
|
|
660
|
+
}
|
|
661
|
+
catch (err) {
|
|
662
|
+
if (err instanceof ExtensionTimeoutError) {
|
|
663
|
+
return error("Extension timed out — terminal features may be unavailable");
|
|
664
|
+
}
|
|
665
|
+
throw err;
|
|
666
|
+
}
|
|
667
|
+
},
|
|
668
|
+
};
|
|
669
|
+
}
|
|
670
|
+
//# sourceMappingURL=terminal.js.map
|