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,1339 @@
|
|
|
1
|
+
import { ExtensionTimeoutError, } from "../extensionClient.js";
|
|
2
|
+
import { lspDefinition, lspReferences } from "./headless/lspFallback.js";
|
|
3
|
+
import { error, extensionRequired, languageIdFromPath, optionalInt, requireInt, requireString, resolveFilePath, successStructured, } from "./utils.js";
|
|
4
|
+
/**
|
|
5
|
+
* LSP cold-start retry wrapper.
|
|
6
|
+
*
|
|
7
|
+
* On SSH remotes the TypeScript language server takes 5-20 s to index the
|
|
8
|
+
* workspace after Windsurf opens. During that window every LSP call times out
|
|
9
|
+
* at the ExtensionClient REQUEST_TIMEOUT (10 s). Retrying with linear backoff
|
|
10
|
+
* converts most cold-start failures into eventual successes without needing any
|
|
11
|
+
* new extension-side protocol.
|
|
12
|
+
*
|
|
13
|
+
* Strategy:
|
|
14
|
+
* attempt 1 → immediate
|
|
15
|
+
* attempt 2 → wait 4 s (TS server usually ready by here)
|
|
16
|
+
* attempt 3 → wait 8 s (catches slow / large workspaces)
|
|
17
|
+
* → hard error with actionable message
|
|
18
|
+
*
|
|
19
|
+
* Non-timeout errors (e.g. network drop) propagate immediately — we only retry
|
|
20
|
+
* on ExtensionTimeoutError because that is the cold-start signal.
|
|
21
|
+
*
|
|
22
|
+
* The AbortSignal is checked before each wait so cancellation is still fast.
|
|
23
|
+
*/
|
|
24
|
+
const LSP_RETRY_DELAYS_MS = [4_000, 8_000];
|
|
25
|
+
export async function lspWithRetry(fn, signal, isLspReady) {
|
|
26
|
+
// Attempt 1 — no wait
|
|
27
|
+
try {
|
|
28
|
+
return await fn();
|
|
29
|
+
}
|
|
30
|
+
catch (err) {
|
|
31
|
+
if (!(err instanceof ExtensionTimeoutError))
|
|
32
|
+
throw err;
|
|
33
|
+
// If the language server is already known-ready, a timeout is a real problem
|
|
34
|
+
// (not a cold-start). Skip retries — they won't help.
|
|
35
|
+
if (isLspReady?.())
|
|
36
|
+
return "timeout";
|
|
37
|
+
}
|
|
38
|
+
// Retry attempts with increasing backoff
|
|
39
|
+
const startedAt = Date.now();
|
|
40
|
+
for (const delayMs of LSP_RETRY_DELAYS_MS) {
|
|
41
|
+
if (signal?.aborted)
|
|
42
|
+
return "timeout";
|
|
43
|
+
// Cap sleep to remaining signal deadline so we never wait longer than the caller allows.
|
|
44
|
+
const elapsed = Date.now() - startedAt;
|
|
45
|
+
const totalBudgetMs = LSP_RETRY_DELAYS_MS.reduce((a, b) => a + b, 0);
|
|
46
|
+
const remainingMs = totalBudgetMs - elapsed;
|
|
47
|
+
const sleepMs = Math.min(delayMs, Math.max(0, remainingMs));
|
|
48
|
+
if (sleepMs <= 0)
|
|
49
|
+
return "timeout";
|
|
50
|
+
await new Promise((resolve, reject) => {
|
|
51
|
+
const onAbort = () => {
|
|
52
|
+
clearTimeout(timer);
|
|
53
|
+
reject(new Error("aborted"));
|
|
54
|
+
};
|
|
55
|
+
const timer = setTimeout(() => {
|
|
56
|
+
signal?.removeEventListener("abort", onAbort);
|
|
57
|
+
resolve();
|
|
58
|
+
}, sleepMs);
|
|
59
|
+
if (signal) {
|
|
60
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
61
|
+
}
|
|
62
|
+
}).catch(() => {
|
|
63
|
+
/* aborted — loop will exit on next iteration */
|
|
64
|
+
});
|
|
65
|
+
if (signal?.aborted)
|
|
66
|
+
return "timeout";
|
|
67
|
+
try {
|
|
68
|
+
return await fn();
|
|
69
|
+
}
|
|
70
|
+
catch (err) {
|
|
71
|
+
if (!(err instanceof ExtensionTimeoutError))
|
|
72
|
+
throw err;
|
|
73
|
+
// still timing out — continue to next delay or fall through
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return "timeout";
|
|
77
|
+
}
|
|
78
|
+
/** Encode a numeric offset as a base64 cursor string. */
|
|
79
|
+
function encodeCursor(offset) {
|
|
80
|
+
return Buffer.from(String(offset)).toString("base64");
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Decode a cursor from args.
|
|
84
|
+
* - Missing/empty cursor → returns 0 (start of first page).
|
|
85
|
+
* - Non-empty string that fails to decode or parse as a valid non-negative integer
|
|
86
|
+
* → returns null so callers can return an "Invalid cursor" error to the client.
|
|
87
|
+
*/
|
|
88
|
+
function decodeCursor(cursor) {
|
|
89
|
+
if (typeof cursor !== "string" || cursor === "")
|
|
90
|
+
return 0;
|
|
91
|
+
try {
|
|
92
|
+
const n = parseInt(Buffer.from(cursor, "base64").toString("utf-8"), 10);
|
|
93
|
+
return Number.isFinite(n) && n >= 0 ? n : null;
|
|
94
|
+
}
|
|
95
|
+
catch {
|
|
96
|
+
return null;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Apply LSP verbosity filtering to a hover result.
|
|
101
|
+
*
|
|
102
|
+
* - "minimal": keep only contents[0] (type signature line); strip documentation.
|
|
103
|
+
* Reduces hover payload by ~60% on well-documented symbols.
|
|
104
|
+
* - "normal": unchanged (default).
|
|
105
|
+
* - "verbose": unchanged (reserved for future expansions).
|
|
106
|
+
*/
|
|
107
|
+
function applyLspVerbosity(result, verbosity) {
|
|
108
|
+
if (verbosity !== "minimal" ||
|
|
109
|
+
typeof result !== "object" ||
|
|
110
|
+
result === null) {
|
|
111
|
+
return result;
|
|
112
|
+
}
|
|
113
|
+
const r = result;
|
|
114
|
+
if (!Array.isArray(r.contents))
|
|
115
|
+
return result;
|
|
116
|
+
return { ...r, contents: r.contents.slice(0, 1) };
|
|
117
|
+
}
|
|
118
|
+
/** Returns a readiness checker for a given file path and extension client. */
|
|
119
|
+
function readinessChecker(extensionClient, filePath) {
|
|
120
|
+
const langId = languageIdFromPath(filePath);
|
|
121
|
+
return () => extensionClient.lspReadyLanguages?.has(langId) ?? false;
|
|
122
|
+
}
|
|
123
|
+
/** Standard error returned when an LSP tool exhausts its retry budget. */
|
|
124
|
+
export function lspColdStartError() {
|
|
125
|
+
return error("Language server timed out after retries — it may still be indexing the workspace. " +
|
|
126
|
+
"Wait a few seconds and try again, or open a TypeScript file in the editor to trigger indexing.");
|
|
127
|
+
}
|
|
128
|
+
export function createGoToDefinitionTool(workspace, extensionClient, hasTypescriptLsp = false) {
|
|
129
|
+
return {
|
|
130
|
+
schema: {
|
|
131
|
+
name: "goToDefinition",
|
|
132
|
+
extensionFallback: true,
|
|
133
|
+
description: "Go to the definition of a symbol at a given position using VS Code LSP.",
|
|
134
|
+
annotations: { readOnlyHint: true },
|
|
135
|
+
inputSchema: {
|
|
136
|
+
type: "object",
|
|
137
|
+
properties: {
|
|
138
|
+
filePath: {
|
|
139
|
+
type: "string",
|
|
140
|
+
description: "Workspace or absolute path",
|
|
141
|
+
},
|
|
142
|
+
line: {
|
|
143
|
+
type: "integer",
|
|
144
|
+
description: "Line number (1-based)",
|
|
145
|
+
},
|
|
146
|
+
column: {
|
|
147
|
+
type: "integer",
|
|
148
|
+
description: "Column (1-based)",
|
|
149
|
+
},
|
|
150
|
+
},
|
|
151
|
+
required: ["filePath", "line", "column"],
|
|
152
|
+
additionalProperties: false,
|
|
153
|
+
},
|
|
154
|
+
outputSchema: {
|
|
155
|
+
type: "object",
|
|
156
|
+
properties: {
|
|
157
|
+
found: { type: "boolean" },
|
|
158
|
+
message: { type: "string" },
|
|
159
|
+
uri: { type: "string" },
|
|
160
|
+
range: {
|
|
161
|
+
type: "object",
|
|
162
|
+
properties: {
|
|
163
|
+
startLine: { type: "number" },
|
|
164
|
+
startColumn: { type: "number" },
|
|
165
|
+
endLine: { type: "number" },
|
|
166
|
+
endColumn: { type: "number" },
|
|
167
|
+
},
|
|
168
|
+
},
|
|
169
|
+
},
|
|
170
|
+
required: ["found"],
|
|
171
|
+
},
|
|
172
|
+
},
|
|
173
|
+
handler: async (args, signal) => {
|
|
174
|
+
const filePath = resolveFilePath(requireString(args, "filePath"), workspace);
|
|
175
|
+
const line = requireInt(args, "line");
|
|
176
|
+
const column = requireInt(args, "column");
|
|
177
|
+
if (extensionClient.isConnected()) {
|
|
178
|
+
const result = await lspWithRetry(() => extensionClient.goToDefinition(filePath, line, column, signal), signal, readinessChecker(extensionClient, filePath));
|
|
179
|
+
if (result === "timeout")
|
|
180
|
+
return lspColdStartError();
|
|
181
|
+
if (result === null) {
|
|
182
|
+
return successStructured({
|
|
183
|
+
found: false,
|
|
184
|
+
message: "No definition found at this position",
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
return successStructured(result);
|
|
188
|
+
}
|
|
189
|
+
// Headless fallback via typescript-language-server
|
|
190
|
+
if (hasTypescriptLsp && workspace) {
|
|
191
|
+
try {
|
|
192
|
+
const locs = await lspDefinition(filePath, line, column, workspace);
|
|
193
|
+
if (locs.length === 0) {
|
|
194
|
+
return successStructured({
|
|
195
|
+
found: false,
|
|
196
|
+
message: "No definition found at this position",
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
const first = locs[0];
|
|
200
|
+
if (!first) {
|
|
201
|
+
return successStructured({
|
|
202
|
+
found: false,
|
|
203
|
+
message: "No definition found at this position",
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
return successStructured({
|
|
207
|
+
found: true,
|
|
208
|
+
uri: first.uri,
|
|
209
|
+
range: {
|
|
210
|
+
startLine: first.range.start.line + 1,
|
|
211
|
+
startColumn: first.range.start.character + 1,
|
|
212
|
+
endLine: first.range.end.line + 1,
|
|
213
|
+
endColumn: first.range.end.character + 1,
|
|
214
|
+
},
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
catch {
|
|
218
|
+
// fall through to extensionRequired
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
return extensionRequired("LSP features", [
|
|
222
|
+
"Use runCommand with tsc, eslint, pyright, or biome for CLI-based analysis",
|
|
223
|
+
"Use getDiagnostics for lint/type-check results from CLI linters",
|
|
224
|
+
]);
|
|
225
|
+
},
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
export function createFindReferencesTool(workspace, extensionClient, hasTypescriptLsp = false) {
|
|
229
|
+
return {
|
|
230
|
+
schema: {
|
|
231
|
+
name: "findReferences",
|
|
232
|
+
extensionFallback: true,
|
|
233
|
+
description: "Find all references to a symbol at a given position using VS Code LSP.",
|
|
234
|
+
annotations: { readOnlyHint: true },
|
|
235
|
+
inputSchema: {
|
|
236
|
+
type: "object",
|
|
237
|
+
properties: {
|
|
238
|
+
filePath: {
|
|
239
|
+
type: "string",
|
|
240
|
+
description: "Workspace or absolute path",
|
|
241
|
+
},
|
|
242
|
+
line: {
|
|
243
|
+
type: "integer",
|
|
244
|
+
description: "Line number (1-based)",
|
|
245
|
+
},
|
|
246
|
+
column: {
|
|
247
|
+
type: "integer",
|
|
248
|
+
description: "Column (1-based)",
|
|
249
|
+
},
|
|
250
|
+
cursor: {
|
|
251
|
+
type: "string",
|
|
252
|
+
description: "Cursor from previous call's nextCursor. Omit on first call.",
|
|
253
|
+
},
|
|
254
|
+
},
|
|
255
|
+
required: ["filePath", "line", "column"],
|
|
256
|
+
additionalProperties: false,
|
|
257
|
+
},
|
|
258
|
+
outputSchema: {
|
|
259
|
+
type: "object",
|
|
260
|
+
properties: {
|
|
261
|
+
found: { type: "boolean" },
|
|
262
|
+
references: {
|
|
263
|
+
type: "array",
|
|
264
|
+
items: {
|
|
265
|
+
type: "object",
|
|
266
|
+
properties: {
|
|
267
|
+
uri: { type: "string" },
|
|
268
|
+
range: { type: "object" },
|
|
269
|
+
},
|
|
270
|
+
},
|
|
271
|
+
},
|
|
272
|
+
total: { type: "integer" },
|
|
273
|
+
nextCursor: { type: "string" },
|
|
274
|
+
},
|
|
275
|
+
required: ["found"],
|
|
276
|
+
},
|
|
277
|
+
},
|
|
278
|
+
handler: async (args, signal) => {
|
|
279
|
+
const filePath = resolveFilePath(requireString(args, "filePath"), workspace);
|
|
280
|
+
const line = requireInt(args, "line");
|
|
281
|
+
const column = requireInt(args, "column");
|
|
282
|
+
const PAGE_SIZE = 100;
|
|
283
|
+
const offset = decodeCursor(args.cursor);
|
|
284
|
+
if (offset === null) {
|
|
285
|
+
return error("Invalid cursor");
|
|
286
|
+
}
|
|
287
|
+
if (extensionClient.isConnected()) {
|
|
288
|
+
const result = await lspWithRetry(() => extensionClient.findReferences(filePath, line, column, signal), signal, readinessChecker(extensionClient, filePath));
|
|
289
|
+
if (result === "timeout")
|
|
290
|
+
return lspColdStartError();
|
|
291
|
+
if (result === null) {
|
|
292
|
+
return successStructured({ found: false, references: [], total: 0 });
|
|
293
|
+
}
|
|
294
|
+
const allRefs = Array.isArray(result.references)
|
|
295
|
+
? result.references
|
|
296
|
+
: [];
|
|
297
|
+
const page = allRefs.slice(offset, offset + PAGE_SIZE);
|
|
298
|
+
const out = {
|
|
299
|
+
...result,
|
|
300
|
+
references: page,
|
|
301
|
+
total: allRefs.length,
|
|
302
|
+
};
|
|
303
|
+
if (offset + PAGE_SIZE < allRefs.length) {
|
|
304
|
+
out.nextCursor = encodeCursor(offset + PAGE_SIZE);
|
|
305
|
+
}
|
|
306
|
+
return successStructured(out);
|
|
307
|
+
}
|
|
308
|
+
// Headless fallback via typescript-language-server
|
|
309
|
+
if (hasTypescriptLsp && workspace) {
|
|
310
|
+
try {
|
|
311
|
+
const locs = await lspReferences(filePath, line, column, workspace);
|
|
312
|
+
const page = locs.slice(offset, offset + PAGE_SIZE);
|
|
313
|
+
const refs = page.map((l) => ({
|
|
314
|
+
uri: l.uri,
|
|
315
|
+
range: {
|
|
316
|
+
startLine: l.range.start.line + 1,
|
|
317
|
+
startColumn: l.range.start.character + 1,
|
|
318
|
+
endLine: l.range.end.line + 1,
|
|
319
|
+
endColumn: l.range.end.character + 1,
|
|
320
|
+
},
|
|
321
|
+
}));
|
|
322
|
+
const out = {
|
|
323
|
+
found: locs.length > 0,
|
|
324
|
+
references: refs,
|
|
325
|
+
total: locs.length,
|
|
326
|
+
};
|
|
327
|
+
if (offset + PAGE_SIZE < locs.length) {
|
|
328
|
+
out.nextCursor = encodeCursor(offset + PAGE_SIZE);
|
|
329
|
+
}
|
|
330
|
+
return successStructured(out);
|
|
331
|
+
}
|
|
332
|
+
catch {
|
|
333
|
+
// fall through to extensionRequired
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
return extensionRequired("LSP features", [
|
|
337
|
+
"Use runCommand with tsc, eslint, pyright, or biome for CLI-based analysis",
|
|
338
|
+
"Use getDiagnostics for lint/type-check results from CLI linters",
|
|
339
|
+
]);
|
|
340
|
+
},
|
|
341
|
+
};
|
|
342
|
+
}
|
|
343
|
+
export function createGetHoverTool(workspace, extensionClient, lspVerbosity = "normal") {
|
|
344
|
+
return {
|
|
345
|
+
schema: {
|
|
346
|
+
name: "getHover",
|
|
347
|
+
extensionRequired: true,
|
|
348
|
+
description: "Get hover information (type info, documentation) for a symbol at a given position.",
|
|
349
|
+
annotations: { readOnlyHint: true },
|
|
350
|
+
inputSchema: {
|
|
351
|
+
type: "object",
|
|
352
|
+
properties: {
|
|
353
|
+
filePath: {
|
|
354
|
+
type: "string",
|
|
355
|
+
description: "Workspace or absolute path",
|
|
356
|
+
},
|
|
357
|
+
line: {
|
|
358
|
+
type: "integer",
|
|
359
|
+
description: "Line number (1-based)",
|
|
360
|
+
},
|
|
361
|
+
column: {
|
|
362
|
+
type: "integer",
|
|
363
|
+
description: "Column (1-based)",
|
|
364
|
+
},
|
|
365
|
+
},
|
|
366
|
+
required: ["filePath", "line", "column"],
|
|
367
|
+
additionalProperties: false,
|
|
368
|
+
},
|
|
369
|
+
outputSchema: {
|
|
370
|
+
type: "object",
|
|
371
|
+
properties: {
|
|
372
|
+
found: { type: "boolean" },
|
|
373
|
+
message: { type: "string" },
|
|
374
|
+
contents: { type: "string" },
|
|
375
|
+
range: { type: "object" },
|
|
376
|
+
},
|
|
377
|
+
required: ["found"],
|
|
378
|
+
},
|
|
379
|
+
},
|
|
380
|
+
handler: async (args, signal) => {
|
|
381
|
+
if (!extensionClient.isConnected()) {
|
|
382
|
+
return extensionRequired("LSP features", [
|
|
383
|
+
"Use runCommand with tsc, eslint, pyright, or biome for CLI-based analysis",
|
|
384
|
+
"Use getDiagnostics for lint/type-check results from CLI linters",
|
|
385
|
+
]);
|
|
386
|
+
}
|
|
387
|
+
const filePath = resolveFilePath(requireString(args, "filePath"), workspace);
|
|
388
|
+
const line = requireInt(args, "line");
|
|
389
|
+
const column = requireInt(args, "column");
|
|
390
|
+
const result = await lspWithRetry(() => extensionClient.getHover(filePath, line, column, signal), signal, readinessChecker(extensionClient, filePath));
|
|
391
|
+
if (result === "timeout")
|
|
392
|
+
return lspColdStartError();
|
|
393
|
+
if (result === null) {
|
|
394
|
+
return successStructured({
|
|
395
|
+
found: false,
|
|
396
|
+
message: "No hover information at this position",
|
|
397
|
+
});
|
|
398
|
+
}
|
|
399
|
+
return successStructured(applyLspVerbosity(result, lspVerbosity));
|
|
400
|
+
},
|
|
401
|
+
};
|
|
402
|
+
}
|
|
403
|
+
export function createGetCodeActionsTool(workspace, extensionClient) {
|
|
404
|
+
return {
|
|
405
|
+
schema: {
|
|
406
|
+
name: "getCodeActions",
|
|
407
|
+
extensionRequired: true,
|
|
408
|
+
description: "Get available code actions (quick fixes, refactorings) for a range in a file.",
|
|
409
|
+
annotations: { readOnlyHint: true },
|
|
410
|
+
inputSchema: {
|
|
411
|
+
type: "object",
|
|
412
|
+
properties: {
|
|
413
|
+
filePath: {
|
|
414
|
+
type: "string",
|
|
415
|
+
description: "Workspace or absolute path",
|
|
416
|
+
},
|
|
417
|
+
startLine: {
|
|
418
|
+
type: "integer",
|
|
419
|
+
description: "Start line (1-based)",
|
|
420
|
+
},
|
|
421
|
+
startColumn: {
|
|
422
|
+
type: "integer",
|
|
423
|
+
description: "Start column (1-based)",
|
|
424
|
+
},
|
|
425
|
+
endLine: {
|
|
426
|
+
type: "integer",
|
|
427
|
+
description: "End line (1-based)",
|
|
428
|
+
},
|
|
429
|
+
endColumn: {
|
|
430
|
+
type: "integer",
|
|
431
|
+
description: "End column (1-based)",
|
|
432
|
+
},
|
|
433
|
+
},
|
|
434
|
+
required: [
|
|
435
|
+
"filePath",
|
|
436
|
+
"startLine",
|
|
437
|
+
"startColumn",
|
|
438
|
+
"endLine",
|
|
439
|
+
"endColumn",
|
|
440
|
+
],
|
|
441
|
+
additionalProperties: false,
|
|
442
|
+
},
|
|
443
|
+
outputSchema: {
|
|
444
|
+
type: "object",
|
|
445
|
+
properties: {
|
|
446
|
+
actions: {
|
|
447
|
+
type: "array",
|
|
448
|
+
items: {
|
|
449
|
+
type: "object",
|
|
450
|
+
properties: {
|
|
451
|
+
title: { type: "string" },
|
|
452
|
+
kind: { type: "string" },
|
|
453
|
+
id: { type: "string" },
|
|
454
|
+
},
|
|
455
|
+
required: ["title"],
|
|
456
|
+
},
|
|
457
|
+
},
|
|
458
|
+
},
|
|
459
|
+
required: ["actions"],
|
|
460
|
+
},
|
|
461
|
+
},
|
|
462
|
+
handler: async (args, signal) => {
|
|
463
|
+
if (!extensionClient.isConnected()) {
|
|
464
|
+
return extensionRequired("LSP features", [
|
|
465
|
+
"Use runCommand with tsc, eslint, pyright, or biome for CLI-based analysis",
|
|
466
|
+
"Use getDiagnostics for lint/type-check results from CLI linters",
|
|
467
|
+
]);
|
|
468
|
+
}
|
|
469
|
+
const filePath = resolveFilePath(requireString(args, "filePath"), workspace);
|
|
470
|
+
const startLine = requireInt(args, "startLine");
|
|
471
|
+
const startColumn = requireInt(args, "startColumn");
|
|
472
|
+
const endLine = requireInt(args, "endLine");
|
|
473
|
+
const endColumn = requireInt(args, "endColumn");
|
|
474
|
+
const result = await lspWithRetry(() => extensionClient.getCodeActions(filePath, startLine, startColumn, endLine, endColumn, signal), signal, readinessChecker(extensionClient, filePath));
|
|
475
|
+
if (result === "timeout")
|
|
476
|
+
return lspColdStartError();
|
|
477
|
+
if (result === null) {
|
|
478
|
+
return successStructured({ actions: [] });
|
|
479
|
+
}
|
|
480
|
+
return successStructured(result);
|
|
481
|
+
},
|
|
482
|
+
};
|
|
483
|
+
}
|
|
484
|
+
export function createApplyCodeActionTool(workspace, extensionClient) {
|
|
485
|
+
return {
|
|
486
|
+
schema: {
|
|
487
|
+
name: "applyCodeAction",
|
|
488
|
+
extensionRequired: true,
|
|
489
|
+
description: "Apply code action by title. Use getCodeActions first to see options.",
|
|
490
|
+
annotations: { destructiveHint: true },
|
|
491
|
+
inputSchema: {
|
|
492
|
+
type: "object",
|
|
493
|
+
properties: {
|
|
494
|
+
filePath: {
|
|
495
|
+
type: "string",
|
|
496
|
+
description: "Workspace or absolute path",
|
|
497
|
+
},
|
|
498
|
+
startLine: {
|
|
499
|
+
type: "integer",
|
|
500
|
+
description: "Start line (1-based)",
|
|
501
|
+
},
|
|
502
|
+
startColumn: {
|
|
503
|
+
type: "integer",
|
|
504
|
+
description: "Start column (1-based)",
|
|
505
|
+
},
|
|
506
|
+
endLine: {
|
|
507
|
+
type: "integer",
|
|
508
|
+
description: "End line (1-based)",
|
|
509
|
+
},
|
|
510
|
+
endColumn: {
|
|
511
|
+
type: "integer",
|
|
512
|
+
description: "End column (1-based)",
|
|
513
|
+
},
|
|
514
|
+
actionTitle: {
|
|
515
|
+
type: "string",
|
|
516
|
+
description: "Exact action title from getCodeActions output",
|
|
517
|
+
},
|
|
518
|
+
},
|
|
519
|
+
required: [
|
|
520
|
+
"filePath",
|
|
521
|
+
"startLine",
|
|
522
|
+
"startColumn",
|
|
523
|
+
"endLine",
|
|
524
|
+
"endColumn",
|
|
525
|
+
"actionTitle",
|
|
526
|
+
],
|
|
527
|
+
additionalProperties: false,
|
|
528
|
+
},
|
|
529
|
+
outputSchema: {
|
|
530
|
+
type: "object",
|
|
531
|
+
properties: {
|
|
532
|
+
applied: { type: "boolean" },
|
|
533
|
+
title: { type: "string" },
|
|
534
|
+
command: { type: ["string", "null"] },
|
|
535
|
+
error: { type: "string" },
|
|
536
|
+
available: {
|
|
537
|
+
type: "array",
|
|
538
|
+
items: { type: "string" },
|
|
539
|
+
},
|
|
540
|
+
},
|
|
541
|
+
required: ["applied"],
|
|
542
|
+
additionalProperties: true,
|
|
543
|
+
},
|
|
544
|
+
},
|
|
545
|
+
handler: async (args, signal) => {
|
|
546
|
+
if (!extensionClient.isConnected()) {
|
|
547
|
+
return extensionRequired("LSP features", [
|
|
548
|
+
"Use runCommand with tsc, eslint, pyright, or biome for CLI-based analysis",
|
|
549
|
+
"Use getDiagnostics for lint/type-check results from CLI linters",
|
|
550
|
+
]);
|
|
551
|
+
}
|
|
552
|
+
const filePath = resolveFilePath(requireString(args, "filePath"), workspace);
|
|
553
|
+
const actionTitle = requireString(args, "actionTitle", 500);
|
|
554
|
+
const startLine = requireInt(args, "startLine");
|
|
555
|
+
const startColumn = requireInt(args, "startColumn");
|
|
556
|
+
const endLine = requireInt(args, "endLine");
|
|
557
|
+
const endColumn = requireInt(args, "endColumn");
|
|
558
|
+
let result;
|
|
559
|
+
try {
|
|
560
|
+
result = await extensionClient.applyCodeAction(filePath, startLine, startColumn, endLine, endColumn, actionTitle, signal);
|
|
561
|
+
}
|
|
562
|
+
catch (err) {
|
|
563
|
+
if (err instanceof ExtensionTimeoutError) {
|
|
564
|
+
return error("Language server timed out — it may still be indexing. " +
|
|
565
|
+
"Wait a few seconds and try again.");
|
|
566
|
+
}
|
|
567
|
+
throw err;
|
|
568
|
+
}
|
|
569
|
+
if (result === null) {
|
|
570
|
+
return error("Extension returned no result — code action may not be available");
|
|
571
|
+
}
|
|
572
|
+
return successStructured(result);
|
|
573
|
+
},
|
|
574
|
+
};
|
|
575
|
+
}
|
|
576
|
+
export function createPreviewCodeActionTool(workspace, extensionClient) {
|
|
577
|
+
return {
|
|
578
|
+
schema: {
|
|
579
|
+
name: "previewCodeAction",
|
|
580
|
+
extensionRequired: true,
|
|
581
|
+
description: "Preview edits a code action would make without applying. Use before applyCodeAction.",
|
|
582
|
+
annotations: { readOnlyHint: true },
|
|
583
|
+
inputSchema: {
|
|
584
|
+
type: "object",
|
|
585
|
+
properties: {
|
|
586
|
+
filePath: {
|
|
587
|
+
type: "string",
|
|
588
|
+
description: "Workspace or absolute path",
|
|
589
|
+
},
|
|
590
|
+
startLine: {
|
|
591
|
+
type: "integer",
|
|
592
|
+
description: "Start line (1-based)",
|
|
593
|
+
},
|
|
594
|
+
startColumn: {
|
|
595
|
+
type: "integer",
|
|
596
|
+
description: "Start column (1-based)",
|
|
597
|
+
},
|
|
598
|
+
endLine: {
|
|
599
|
+
type: "integer",
|
|
600
|
+
description: "End line (1-based)",
|
|
601
|
+
},
|
|
602
|
+
endColumn: {
|
|
603
|
+
type: "integer",
|
|
604
|
+
description: "End column (1-based)",
|
|
605
|
+
},
|
|
606
|
+
actionTitle: {
|
|
607
|
+
type: "string",
|
|
608
|
+
description: "Exact action title from getCodeActions output",
|
|
609
|
+
},
|
|
610
|
+
},
|
|
611
|
+
required: [
|
|
612
|
+
"filePath",
|
|
613
|
+
"startLine",
|
|
614
|
+
"startColumn",
|
|
615
|
+
"endLine",
|
|
616
|
+
"endColumn",
|
|
617
|
+
"actionTitle",
|
|
618
|
+
],
|
|
619
|
+
additionalProperties: false,
|
|
620
|
+
},
|
|
621
|
+
outputSchema: {
|
|
622
|
+
type: "object",
|
|
623
|
+
properties: {
|
|
624
|
+
title: { type: "string" },
|
|
625
|
+
changes: {
|
|
626
|
+
type: "array",
|
|
627
|
+
items: {
|
|
628
|
+
type: "object",
|
|
629
|
+
properties: {
|
|
630
|
+
file: { type: "string" },
|
|
631
|
+
edits: {
|
|
632
|
+
type: "array",
|
|
633
|
+
items: {
|
|
634
|
+
type: "object",
|
|
635
|
+
properties: {
|
|
636
|
+
range: {
|
|
637
|
+
type: "object",
|
|
638
|
+
properties: {
|
|
639
|
+
startLine: { type: "number" },
|
|
640
|
+
startColumn: { type: "number" },
|
|
641
|
+
endLine: { type: "number" },
|
|
642
|
+
endColumn: { type: "number" },
|
|
643
|
+
},
|
|
644
|
+
required: [
|
|
645
|
+
"startLine",
|
|
646
|
+
"startColumn",
|
|
647
|
+
"endLine",
|
|
648
|
+
"endColumn",
|
|
649
|
+
],
|
|
650
|
+
},
|
|
651
|
+
newText: { type: "string" },
|
|
652
|
+
},
|
|
653
|
+
required: ["range", "newText"],
|
|
654
|
+
},
|
|
655
|
+
},
|
|
656
|
+
},
|
|
657
|
+
required: ["file", "edits"],
|
|
658
|
+
},
|
|
659
|
+
},
|
|
660
|
+
totalFiles: { type: "number" },
|
|
661
|
+
totalEdits: { type: "number" },
|
|
662
|
+
note: { type: "string" },
|
|
663
|
+
},
|
|
664
|
+
required: ["title", "changes"],
|
|
665
|
+
},
|
|
666
|
+
},
|
|
667
|
+
handler: async (args, signal) => {
|
|
668
|
+
if (!extensionClient.isConnected()) {
|
|
669
|
+
return extensionRequired("LSP features", [
|
|
670
|
+
"Use getCodeActions to list available actions first",
|
|
671
|
+
"Use applyCodeAction to apply without preview if extension reconnects",
|
|
672
|
+
]);
|
|
673
|
+
}
|
|
674
|
+
const filePath = resolveFilePath(requireString(args, "filePath"), workspace);
|
|
675
|
+
const actionTitle = requireString(args, "actionTitle", 500);
|
|
676
|
+
const startLine = requireInt(args, "startLine");
|
|
677
|
+
const startColumn = requireInt(args, "startColumn");
|
|
678
|
+
const endLine = requireInt(args, "endLine");
|
|
679
|
+
const endColumn = requireInt(args, "endColumn");
|
|
680
|
+
const result = await lspWithRetry(() => extensionClient.previewCodeAction(filePath, startLine, startColumn, endLine, endColumn, actionTitle, signal), signal, readinessChecker(extensionClient, filePath));
|
|
681
|
+
if (result === "timeout")
|
|
682
|
+
return lspColdStartError();
|
|
683
|
+
if (result === null) {
|
|
684
|
+
return error("Extension returned no result — code action may not be available");
|
|
685
|
+
}
|
|
686
|
+
return successStructured(result);
|
|
687
|
+
},
|
|
688
|
+
};
|
|
689
|
+
}
|
|
690
|
+
export function createRenameSymbolTool(workspace, extensionClient) {
|
|
691
|
+
return {
|
|
692
|
+
schema: {
|
|
693
|
+
name: "renameSymbol",
|
|
694
|
+
extensionRequired: true,
|
|
695
|
+
description: "Rename symbol across all files via LSP. Returns affected files and edit counts.",
|
|
696
|
+
annotations: { destructiveHint: true },
|
|
697
|
+
inputSchema: {
|
|
698
|
+
type: "object",
|
|
699
|
+
properties: {
|
|
700
|
+
filePath: {
|
|
701
|
+
type: "string",
|
|
702
|
+
description: "Workspace or absolute path",
|
|
703
|
+
},
|
|
704
|
+
line: {
|
|
705
|
+
type: "integer",
|
|
706
|
+
description: "Line number (1-based)",
|
|
707
|
+
},
|
|
708
|
+
column: {
|
|
709
|
+
type: "integer",
|
|
710
|
+
description: "Column (1-based)",
|
|
711
|
+
},
|
|
712
|
+
newName: {
|
|
713
|
+
type: "string",
|
|
714
|
+
description: "New name for the symbol",
|
|
715
|
+
},
|
|
716
|
+
},
|
|
717
|
+
required: ["filePath", "line", "column", "newName"],
|
|
718
|
+
additionalProperties: false,
|
|
719
|
+
},
|
|
720
|
+
outputSchema: {
|
|
721
|
+
type: "object",
|
|
722
|
+
properties: {
|
|
723
|
+
success: { type: "boolean" },
|
|
724
|
+
newName: { type: "string" },
|
|
725
|
+
affectedFiles: {
|
|
726
|
+
type: "array",
|
|
727
|
+
items: {
|
|
728
|
+
type: "object",
|
|
729
|
+
properties: {
|
|
730
|
+
file: { type: "string" },
|
|
731
|
+
editCount: { type: "number" },
|
|
732
|
+
},
|
|
733
|
+
required: ["file", "editCount"],
|
|
734
|
+
},
|
|
735
|
+
},
|
|
736
|
+
totalEdits: { type: "number" },
|
|
737
|
+
error: { type: "string" },
|
|
738
|
+
},
|
|
739
|
+
required: ["success"],
|
|
740
|
+
},
|
|
741
|
+
},
|
|
742
|
+
handler: async (args, signal) => {
|
|
743
|
+
if (!extensionClient.isConnected()) {
|
|
744
|
+
return extensionRequired("LSP features", [
|
|
745
|
+
"Use runCommand with tsc, eslint, pyright, or biome for CLI-based analysis",
|
|
746
|
+
"Use getDiagnostics for lint/type-check results from CLI linters",
|
|
747
|
+
]);
|
|
748
|
+
}
|
|
749
|
+
const filePath = resolveFilePath(requireString(args, "filePath"), workspace);
|
|
750
|
+
const newName = requireString(args, "newName", 256);
|
|
751
|
+
if (/[\x00-\x1f]/.test(newName)) {
|
|
752
|
+
return error("newName must not contain control characters");
|
|
753
|
+
}
|
|
754
|
+
const line = requireInt(args, "line");
|
|
755
|
+
const column = requireInt(args, "column");
|
|
756
|
+
const result = await lspWithRetry(() => extensionClient.renameSymbol(filePath, line, column, newName, signal), signal, readinessChecker(extensionClient, filePath));
|
|
757
|
+
if (result === "timeout")
|
|
758
|
+
return lspColdStartError();
|
|
759
|
+
if (result === null) {
|
|
760
|
+
return error("Extension returned no result — symbol may not be renameable at this position");
|
|
761
|
+
}
|
|
762
|
+
return successStructured(result);
|
|
763
|
+
},
|
|
764
|
+
};
|
|
765
|
+
}
|
|
766
|
+
export function createGetCallHierarchyTool(workspace, extensionClient) {
|
|
767
|
+
return {
|
|
768
|
+
schema: {
|
|
769
|
+
name: "getCallHierarchy",
|
|
770
|
+
extensionRequired: true,
|
|
771
|
+
description: 'Get the call hierarchy for a function or method. Use direction="incoming" to find callers, "outgoing" to see everything it calls, or "both" (default).',
|
|
772
|
+
annotations: { readOnlyHint: true },
|
|
773
|
+
inputSchema: {
|
|
774
|
+
type: "object",
|
|
775
|
+
properties: {
|
|
776
|
+
filePath: {
|
|
777
|
+
type: "string",
|
|
778
|
+
description: "Workspace or absolute path",
|
|
779
|
+
},
|
|
780
|
+
line: {
|
|
781
|
+
type: "integer",
|
|
782
|
+
description: "Line number (1-based)",
|
|
783
|
+
},
|
|
784
|
+
column: {
|
|
785
|
+
type: "integer",
|
|
786
|
+
description: "Column (1-based)",
|
|
787
|
+
},
|
|
788
|
+
direction: {
|
|
789
|
+
type: "string",
|
|
790
|
+
enum: ["incoming", "outgoing", "both"],
|
|
791
|
+
description: '"incoming"=callers, "outgoing"=callees, "both"=all (default)',
|
|
792
|
+
},
|
|
793
|
+
maxResults: {
|
|
794
|
+
type: "integer",
|
|
795
|
+
description: "Max callers/callees per direction (default: 50, max: 200)",
|
|
796
|
+
},
|
|
797
|
+
cursor: {
|
|
798
|
+
type: "string",
|
|
799
|
+
description: "Cursor from previous call's nextCursor. Omit on first call.",
|
|
800
|
+
},
|
|
801
|
+
},
|
|
802
|
+
required: ["filePath", "line", "column"],
|
|
803
|
+
additionalProperties: false,
|
|
804
|
+
},
|
|
805
|
+
outputSchema: {
|
|
806
|
+
type: "object",
|
|
807
|
+
properties: {
|
|
808
|
+
found: { type: "boolean" },
|
|
809
|
+
message: { type: "string" },
|
|
810
|
+
incoming: { type: "array", items: { type: "object" } },
|
|
811
|
+
outgoing: { type: "array", items: { type: "object" } },
|
|
812
|
+
incomingTotal: { type: "integer" },
|
|
813
|
+
outgoingTotal: { type: "integer" },
|
|
814
|
+
nextCursor: { type: "string" },
|
|
815
|
+
},
|
|
816
|
+
required: ["found"],
|
|
817
|
+
},
|
|
818
|
+
},
|
|
819
|
+
handler: async (args, signal) => {
|
|
820
|
+
if (!extensionClient.isConnected()) {
|
|
821
|
+
return extensionRequired("getCallHierarchy");
|
|
822
|
+
}
|
|
823
|
+
const filePath = resolveFilePath(requireString(args, "filePath"), workspace);
|
|
824
|
+
const line = requireInt(args, "line");
|
|
825
|
+
const column = requireInt(args, "column");
|
|
826
|
+
const rawDirection = typeof args.direction === "string" ? args.direction : "both";
|
|
827
|
+
if (!["incoming", "outgoing", "both"].includes(rawDirection)) {
|
|
828
|
+
return error('direction must be "incoming", "outgoing", or "both"');
|
|
829
|
+
}
|
|
830
|
+
const maxResults = optionalInt(args, "maxResults", 1, 200) ?? 50;
|
|
831
|
+
const PAGE_SIZE = 50;
|
|
832
|
+
const offset = decodeCursor(args.cursor);
|
|
833
|
+
if (offset === null) {
|
|
834
|
+
return error("Invalid cursor");
|
|
835
|
+
}
|
|
836
|
+
const result = await lspWithRetry(() => extensionClient.getCallHierarchy(filePath, line, column, rawDirection, maxResults, signal), signal, readinessChecker(extensionClient, filePath));
|
|
837
|
+
if (result === "timeout")
|
|
838
|
+
return lspColdStartError();
|
|
839
|
+
if (result === null) {
|
|
840
|
+
return successStructured({
|
|
841
|
+
found: false,
|
|
842
|
+
message: "No call hierarchy available at this position — ensure a language server is active",
|
|
843
|
+
});
|
|
844
|
+
}
|
|
845
|
+
const r = result;
|
|
846
|
+
const allIncoming = Array.isArray(r.incoming)
|
|
847
|
+
? r.incoming
|
|
848
|
+
: [];
|
|
849
|
+
const allOutgoing = Array.isArray(r.outgoing)
|
|
850
|
+
? r.outgoing
|
|
851
|
+
: [];
|
|
852
|
+
const pageIncoming = allIncoming.slice(offset, offset + PAGE_SIZE);
|
|
853
|
+
const pageOutgoing = allOutgoing.slice(offset, offset + PAGE_SIZE);
|
|
854
|
+
const out = {
|
|
855
|
+
...r,
|
|
856
|
+
incoming: pageIncoming,
|
|
857
|
+
outgoing: pageOutgoing,
|
|
858
|
+
incomingTotal: allIncoming.length,
|
|
859
|
+
outgoingTotal: allOutgoing.length,
|
|
860
|
+
};
|
|
861
|
+
if (offset + PAGE_SIZE < allIncoming.length ||
|
|
862
|
+
offset + PAGE_SIZE < allOutgoing.length) {
|
|
863
|
+
out.nextCursor = encodeCursor(offset + PAGE_SIZE);
|
|
864
|
+
}
|
|
865
|
+
return successStructured(out);
|
|
866
|
+
},
|
|
867
|
+
};
|
|
868
|
+
}
|
|
869
|
+
export function createSearchWorkspaceSymbolsTool(workspace, extensionClient, hasUniversalCtags = false) {
|
|
870
|
+
return {
|
|
871
|
+
schema: {
|
|
872
|
+
name: "searchWorkspaceSymbols",
|
|
873
|
+
extensionFallback: true,
|
|
874
|
+
description: "Search workspace symbols (classes, fns, vars, interfaces) by name via LSP.",
|
|
875
|
+
annotations: { readOnlyHint: true },
|
|
876
|
+
inputSchema: {
|
|
877
|
+
type: "object",
|
|
878
|
+
properties: {
|
|
879
|
+
query: {
|
|
880
|
+
type: "string",
|
|
881
|
+
description: "Symbol name or partial name",
|
|
882
|
+
},
|
|
883
|
+
maxResults: {
|
|
884
|
+
type: "integer",
|
|
885
|
+
description: "Max results (default: 50, max: 200)",
|
|
886
|
+
},
|
|
887
|
+
},
|
|
888
|
+
required: ["query"],
|
|
889
|
+
additionalProperties: false,
|
|
890
|
+
},
|
|
891
|
+
outputSchema: {
|
|
892
|
+
type: "object",
|
|
893
|
+
properties: {
|
|
894
|
+
symbols: {
|
|
895
|
+
type: "array",
|
|
896
|
+
items: {
|
|
897
|
+
type: "object",
|
|
898
|
+
properties: {
|
|
899
|
+
name: { type: "string" },
|
|
900
|
+
kind: { type: "string" },
|
|
901
|
+
uri: { type: "string" },
|
|
902
|
+
range: { type: "object" },
|
|
903
|
+
containerName: { type: "string" },
|
|
904
|
+
},
|
|
905
|
+
required: ["name", "kind", "uri"],
|
|
906
|
+
},
|
|
907
|
+
},
|
|
908
|
+
count: { type: "number" },
|
|
909
|
+
},
|
|
910
|
+
required: ["symbols", "count"],
|
|
911
|
+
},
|
|
912
|
+
},
|
|
913
|
+
handler: async (args, signal) => {
|
|
914
|
+
const query = requireString(args, "query", 256);
|
|
915
|
+
if (query.trim().length === 0) {
|
|
916
|
+
return error("query must not be empty");
|
|
917
|
+
}
|
|
918
|
+
const maxResults = optionalInt(args, "maxResults", 1, 200) ?? 50;
|
|
919
|
+
if (extensionClient.isConnected()) {
|
|
920
|
+
const result = await lspWithRetry(() => extensionClient.searchSymbols(query, maxResults, signal), signal);
|
|
921
|
+
if (result === "timeout")
|
|
922
|
+
return lspColdStartError();
|
|
923
|
+
if (result === null) {
|
|
924
|
+
return successStructured({ symbols: [], count: 0 });
|
|
925
|
+
}
|
|
926
|
+
return successStructured(result);
|
|
927
|
+
}
|
|
928
|
+
// Headless fallback: Universal Ctags JSON output
|
|
929
|
+
if (hasUniversalCtags && workspace) {
|
|
930
|
+
return searchWithCtags(workspace, query, maxResults, signal);
|
|
931
|
+
}
|
|
932
|
+
return extensionRequired("LSP symbol search", [
|
|
933
|
+
"Install universal-ctags for headless fallback: sudo apt-get install universal-ctags (Linux) or brew install universal-ctags (macOS)",
|
|
934
|
+
"Use searchWorkspace with a grep pattern as an alternative",
|
|
935
|
+
]);
|
|
936
|
+
},
|
|
937
|
+
};
|
|
938
|
+
}
|
|
939
|
+
/** Universal Ctags headless fallback for searchWorkspaceSymbols. */
|
|
940
|
+
async function searchWithCtags(workspace, query, maxResults, signal) {
|
|
941
|
+
const { execFile } = await import("node:child_process");
|
|
942
|
+
const { promisify } = await import("node:util");
|
|
943
|
+
const execFileAsync = promisify(execFile);
|
|
944
|
+
try {
|
|
945
|
+
const { stdout } = await execFileAsync("ctags", [
|
|
946
|
+
"--output-format=json",
|
|
947
|
+
"--fields=+KSn",
|
|
948
|
+
"--recurse",
|
|
949
|
+
"--totals=no",
|
|
950
|
+
`-f`,
|
|
951
|
+
`-`,
|
|
952
|
+
workspace,
|
|
953
|
+
], { timeout: 15_000, maxBuffer: 10 * 1024 * 1024, signal });
|
|
954
|
+
const lowerQuery = query.toLowerCase();
|
|
955
|
+
const symbols = [];
|
|
956
|
+
for (const line of stdout.split("\n")) {
|
|
957
|
+
if (!line.trim() || line.startsWith("!_"))
|
|
958
|
+
continue;
|
|
959
|
+
try {
|
|
960
|
+
const tag = JSON.parse(line);
|
|
961
|
+
if (!tag.name?.toLowerCase().includes(lowerQuery))
|
|
962
|
+
continue;
|
|
963
|
+
symbols.push({
|
|
964
|
+
name: tag.name,
|
|
965
|
+
kind: tag.kind ?? "unknown",
|
|
966
|
+
uri: tag.path ?? "",
|
|
967
|
+
line: tag.line ?? 0,
|
|
968
|
+
...(tag.scope ? { containerName: tag.scope } : {}),
|
|
969
|
+
});
|
|
970
|
+
if (symbols.length >= maxResults)
|
|
971
|
+
break;
|
|
972
|
+
}
|
|
973
|
+
catch {
|
|
974
|
+
// skip malformed lines
|
|
975
|
+
}
|
|
976
|
+
}
|
|
977
|
+
return successStructured({ symbols, count: symbols.length });
|
|
978
|
+
}
|
|
979
|
+
catch {
|
|
980
|
+
return successStructured({ symbols: [], count: 0 });
|
|
981
|
+
}
|
|
982
|
+
}
|
|
983
|
+
export function createPrepareRenameTool(workspace, extensionClient) {
|
|
984
|
+
return {
|
|
985
|
+
schema: {
|
|
986
|
+
name: "prepareRename",
|
|
987
|
+
extensionRequired: true,
|
|
988
|
+
description: "Check if symbol can be renamed. Returns canRename:false with reason if not. Use before renameSymbol.",
|
|
989
|
+
annotations: { readOnlyHint: true },
|
|
990
|
+
inputSchema: {
|
|
991
|
+
type: "object",
|
|
992
|
+
properties: {
|
|
993
|
+
filePath: {
|
|
994
|
+
type: "string",
|
|
995
|
+
description: "Workspace or absolute path",
|
|
996
|
+
},
|
|
997
|
+
line: {
|
|
998
|
+
type: "integer",
|
|
999
|
+
description: "1-based line number",
|
|
1000
|
+
},
|
|
1001
|
+
column: {
|
|
1002
|
+
type: "integer",
|
|
1003
|
+
description: "1-based column number",
|
|
1004
|
+
},
|
|
1005
|
+
},
|
|
1006
|
+
required: ["filePath", "line", "column"],
|
|
1007
|
+
additionalProperties: false,
|
|
1008
|
+
},
|
|
1009
|
+
outputSchema: {
|
|
1010
|
+
type: "object",
|
|
1011
|
+
properties: {
|
|
1012
|
+
canRename: { type: "boolean" },
|
|
1013
|
+
reason: { type: "string" },
|
|
1014
|
+
placeholder: { type: "string" },
|
|
1015
|
+
range: {
|
|
1016
|
+
type: "object",
|
|
1017
|
+
properties: {
|
|
1018
|
+
startLine: { type: "number" },
|
|
1019
|
+
startColumn: { type: "number" },
|
|
1020
|
+
endLine: { type: "number" },
|
|
1021
|
+
endColumn: { type: "number" },
|
|
1022
|
+
},
|
|
1023
|
+
},
|
|
1024
|
+
},
|
|
1025
|
+
required: ["canRename"],
|
|
1026
|
+
},
|
|
1027
|
+
},
|
|
1028
|
+
handler: async (args, signal) => {
|
|
1029
|
+
const filePath = resolveFilePath(requireString(args, "filePath"), workspace);
|
|
1030
|
+
const line = requireInt(args, "line", 1);
|
|
1031
|
+
const column = requireInt(args, "column", 1);
|
|
1032
|
+
if (!extensionClient.isConnected()) {
|
|
1033
|
+
return extensionRequired("prepareRename (LSP rename check)", [
|
|
1034
|
+
"Use renameSymbol directly if you are confident the symbol supports renaming",
|
|
1035
|
+
]);
|
|
1036
|
+
}
|
|
1037
|
+
const result = await lspWithRetry(() => extensionClient.prepareRename(filePath, line, column, signal), signal, readinessChecker(extensionClient, filePath));
|
|
1038
|
+
if (result === "timeout")
|
|
1039
|
+
return lspColdStartError();
|
|
1040
|
+
return successStructured(result ?? {
|
|
1041
|
+
canRename: false,
|
|
1042
|
+
reason: "Symbol does not support renaming at this position",
|
|
1043
|
+
});
|
|
1044
|
+
},
|
|
1045
|
+
};
|
|
1046
|
+
}
|
|
1047
|
+
export function createFormatRangeTool(workspace, extensionClient) {
|
|
1048
|
+
return {
|
|
1049
|
+
schema: {
|
|
1050
|
+
name: "formatRange",
|
|
1051
|
+
extensionRequired: true,
|
|
1052
|
+
description: "Format a line range via LSP formatter. Faster than full formatDocument for large files.",
|
|
1053
|
+
annotations: { readOnlyHint: false },
|
|
1054
|
+
inputSchema: {
|
|
1055
|
+
type: "object",
|
|
1056
|
+
properties: {
|
|
1057
|
+
filePath: {
|
|
1058
|
+
type: "string",
|
|
1059
|
+
description: "Workspace or absolute path",
|
|
1060
|
+
},
|
|
1061
|
+
startLine: {
|
|
1062
|
+
type: "integer",
|
|
1063
|
+
description: "1-based start line (inclusive)",
|
|
1064
|
+
},
|
|
1065
|
+
endLine: {
|
|
1066
|
+
type: "integer",
|
|
1067
|
+
description: "1-based end line (inclusive)",
|
|
1068
|
+
},
|
|
1069
|
+
},
|
|
1070
|
+
required: ["filePath", "startLine", "endLine"],
|
|
1071
|
+
additionalProperties: false,
|
|
1072
|
+
},
|
|
1073
|
+
outputSchema: {
|
|
1074
|
+
type: "object",
|
|
1075
|
+
properties: {
|
|
1076
|
+
formatted: { type: "boolean" },
|
|
1077
|
+
editCount: { type: "number" },
|
|
1078
|
+
reason: { type: "string" },
|
|
1079
|
+
},
|
|
1080
|
+
required: ["formatted"],
|
|
1081
|
+
},
|
|
1082
|
+
},
|
|
1083
|
+
handler: async (args, signal) => {
|
|
1084
|
+
const filePath = resolveFilePath(requireString(args, "filePath"), workspace);
|
|
1085
|
+
const startLine = requireInt(args, "startLine", 1);
|
|
1086
|
+
const endLine = requireInt(args, "endLine", 1);
|
|
1087
|
+
if (endLine < startLine) {
|
|
1088
|
+
return error("endLine must be >= startLine");
|
|
1089
|
+
}
|
|
1090
|
+
if (!extensionClient.isConnected()) {
|
|
1091
|
+
return extensionRequired("formatRange (LSP range formatting)", [
|
|
1092
|
+
"Use formatDocument to format the entire file instead",
|
|
1093
|
+
"Use runCommand with biome or prettier for CLI-based formatting",
|
|
1094
|
+
]);
|
|
1095
|
+
}
|
|
1096
|
+
const result = await lspWithRetry(() => extensionClient.formatRange(filePath, startLine, endLine, signal), signal, readinessChecker(extensionClient, filePath));
|
|
1097
|
+
if (result === "timeout")
|
|
1098
|
+
return lspColdStartError();
|
|
1099
|
+
if (result === null) {
|
|
1100
|
+
return successStructured({
|
|
1101
|
+
formatted: false,
|
|
1102
|
+
reason: "No formatter available for this file type",
|
|
1103
|
+
});
|
|
1104
|
+
}
|
|
1105
|
+
return successStructured(result);
|
|
1106
|
+
},
|
|
1107
|
+
};
|
|
1108
|
+
}
|
|
1109
|
+
export function createFindImplementationsTool(workspace, extensionClient) {
|
|
1110
|
+
return {
|
|
1111
|
+
schema: {
|
|
1112
|
+
name: "findImplementations",
|
|
1113
|
+
extensionRequired: true,
|
|
1114
|
+
description: "Find implementations of interface, abstract method, or abstract class.",
|
|
1115
|
+
annotations: { readOnlyHint: true },
|
|
1116
|
+
inputSchema: {
|
|
1117
|
+
type: "object",
|
|
1118
|
+
properties: {
|
|
1119
|
+
filePath: {
|
|
1120
|
+
type: "string",
|
|
1121
|
+
description: "Workspace or absolute path",
|
|
1122
|
+
},
|
|
1123
|
+
line: {
|
|
1124
|
+
type: "integer",
|
|
1125
|
+
description: "Line number (1-based)",
|
|
1126
|
+
},
|
|
1127
|
+
column: {
|
|
1128
|
+
type: "integer",
|
|
1129
|
+
description: "Column (1-based)",
|
|
1130
|
+
},
|
|
1131
|
+
},
|
|
1132
|
+
required: ["filePath", "line", "column"],
|
|
1133
|
+
additionalProperties: false,
|
|
1134
|
+
},
|
|
1135
|
+
outputSchema: {
|
|
1136
|
+
type: "object",
|
|
1137
|
+
properties: {
|
|
1138
|
+
found: { type: "boolean" },
|
|
1139
|
+
implementations: {
|
|
1140
|
+
type: "array",
|
|
1141
|
+
items: {
|
|
1142
|
+
type: "object",
|
|
1143
|
+
properties: {
|
|
1144
|
+
file: { type: "string" },
|
|
1145
|
+
line: { type: "number" },
|
|
1146
|
+
column: { type: "number" },
|
|
1147
|
+
endLine: { type: "number" },
|
|
1148
|
+
endColumn: { type: "number" },
|
|
1149
|
+
},
|
|
1150
|
+
},
|
|
1151
|
+
},
|
|
1152
|
+
count: { type: "number" },
|
|
1153
|
+
},
|
|
1154
|
+
required: ["found"],
|
|
1155
|
+
},
|
|
1156
|
+
},
|
|
1157
|
+
handler: async (args, signal) => {
|
|
1158
|
+
if (!extensionClient.isConnected()) {
|
|
1159
|
+
return extensionRequired("LSP features", [
|
|
1160
|
+
"Use runCommand with tsc, eslint, pyright, or biome for CLI-based analysis",
|
|
1161
|
+
"Use getDiagnostics for lint/type-check results from CLI linters",
|
|
1162
|
+
]);
|
|
1163
|
+
}
|
|
1164
|
+
const filePath = resolveFilePath(requireString(args, "filePath"), workspace);
|
|
1165
|
+
const line = requireInt(args, "line");
|
|
1166
|
+
const column = requireInt(args, "column");
|
|
1167
|
+
const result = await lspWithRetry(() => extensionClient.findImplementations(filePath, line, column, signal), signal, readinessChecker(extensionClient, filePath));
|
|
1168
|
+
if (result === "timeout")
|
|
1169
|
+
return lspColdStartError();
|
|
1170
|
+
if (result === null) {
|
|
1171
|
+
return successStructured({
|
|
1172
|
+
found: false,
|
|
1173
|
+
implementations: [],
|
|
1174
|
+
count: 0,
|
|
1175
|
+
});
|
|
1176
|
+
}
|
|
1177
|
+
// Cap implementations array at 50 (matches getCallHierarchy baseline).
|
|
1178
|
+
const FIND_IMPLEMENTATIONS_MAX = 50;
|
|
1179
|
+
if (result && typeof result === "object") {
|
|
1180
|
+
const r = result;
|
|
1181
|
+
if (Array.isArray(r.implementations)) {
|
|
1182
|
+
const full = r.implementations;
|
|
1183
|
+
if (full.length > FIND_IMPLEMENTATIONS_MAX) {
|
|
1184
|
+
return successStructured({
|
|
1185
|
+
...r,
|
|
1186
|
+
implementations: full.slice(0, FIND_IMPLEMENTATIONS_MAX),
|
|
1187
|
+
truncated: true,
|
|
1188
|
+
totalCount: full.length,
|
|
1189
|
+
});
|
|
1190
|
+
}
|
|
1191
|
+
}
|
|
1192
|
+
}
|
|
1193
|
+
return successStructured(result);
|
|
1194
|
+
},
|
|
1195
|
+
};
|
|
1196
|
+
}
|
|
1197
|
+
export function createGoToTypeDefinitionTool(workspace, extensionClient) {
|
|
1198
|
+
return {
|
|
1199
|
+
schema: {
|
|
1200
|
+
name: "goToTypeDefinition",
|
|
1201
|
+
extensionRequired: true,
|
|
1202
|
+
description: "Go to the type definition of a symbol. Unlike goToDefinition (navigates to declaration), this navigates to where the type itself is defined.",
|
|
1203
|
+
annotations: { readOnlyHint: true },
|
|
1204
|
+
inputSchema: {
|
|
1205
|
+
type: "object",
|
|
1206
|
+
properties: {
|
|
1207
|
+
filePath: {
|
|
1208
|
+
type: "string",
|
|
1209
|
+
description: "Workspace or absolute path",
|
|
1210
|
+
},
|
|
1211
|
+
line: {
|
|
1212
|
+
type: "integer",
|
|
1213
|
+
description: "Line number (1-based)",
|
|
1214
|
+
},
|
|
1215
|
+
column: {
|
|
1216
|
+
type: "integer",
|
|
1217
|
+
description: "Column (1-based)",
|
|
1218
|
+
},
|
|
1219
|
+
},
|
|
1220
|
+
required: ["filePath", "line", "column"],
|
|
1221
|
+
additionalProperties: false,
|
|
1222
|
+
},
|
|
1223
|
+
outputSchema: {
|
|
1224
|
+
type: "object",
|
|
1225
|
+
properties: {
|
|
1226
|
+
found: { type: "boolean" },
|
|
1227
|
+
message: { type: "string" },
|
|
1228
|
+
locations: {
|
|
1229
|
+
type: "array",
|
|
1230
|
+
items: {
|
|
1231
|
+
type: "object",
|
|
1232
|
+
properties: {
|
|
1233
|
+
file: { type: "string" },
|
|
1234
|
+
line: { type: "number" },
|
|
1235
|
+
column: { type: "number" },
|
|
1236
|
+
endLine: { type: "number" },
|
|
1237
|
+
endColumn: { type: "number" },
|
|
1238
|
+
},
|
|
1239
|
+
},
|
|
1240
|
+
},
|
|
1241
|
+
},
|
|
1242
|
+
required: ["found"],
|
|
1243
|
+
},
|
|
1244
|
+
},
|
|
1245
|
+
handler: async (args, signal) => {
|
|
1246
|
+
if (!extensionClient.isConnected()) {
|
|
1247
|
+
return extensionRequired("LSP features", [
|
|
1248
|
+
"Use runCommand with tsc, eslint, pyright, or biome for CLI-based analysis",
|
|
1249
|
+
"Use getDiagnostics for lint/type-check results from CLI linters",
|
|
1250
|
+
]);
|
|
1251
|
+
}
|
|
1252
|
+
const filePath = resolveFilePath(requireString(args, "filePath"), workspace);
|
|
1253
|
+
const line = requireInt(args, "line");
|
|
1254
|
+
const column = requireInt(args, "column");
|
|
1255
|
+
const result = await lspWithRetry(() => extensionClient.goToTypeDefinition(filePath, line, column, signal), signal, readinessChecker(extensionClient, filePath));
|
|
1256
|
+
if (result === "timeout")
|
|
1257
|
+
return lspColdStartError();
|
|
1258
|
+
if (result === null) {
|
|
1259
|
+
return successStructured({
|
|
1260
|
+
found: false,
|
|
1261
|
+
message: "No type definition found at this position",
|
|
1262
|
+
});
|
|
1263
|
+
}
|
|
1264
|
+
return successStructured(result);
|
|
1265
|
+
},
|
|
1266
|
+
};
|
|
1267
|
+
}
|
|
1268
|
+
export function createGoToDeclarationTool(workspace, extensionClient) {
|
|
1269
|
+
return {
|
|
1270
|
+
schema: {
|
|
1271
|
+
name: "goToDeclaration",
|
|
1272
|
+
extensionRequired: true,
|
|
1273
|
+
description: "Go to the declaration of a symbol (header file in C/C++, .d.ts entry in TypeScript). Unlike goToDefinition, navigates to the 'declare' statement rather than the implementation.",
|
|
1274
|
+
annotations: { readOnlyHint: true },
|
|
1275
|
+
inputSchema: {
|
|
1276
|
+
type: "object",
|
|
1277
|
+
properties: {
|
|
1278
|
+
filePath: {
|
|
1279
|
+
type: "string",
|
|
1280
|
+
description: "Workspace or absolute path",
|
|
1281
|
+
},
|
|
1282
|
+
line: {
|
|
1283
|
+
type: "integer",
|
|
1284
|
+
description: "Line number (1-based)",
|
|
1285
|
+
},
|
|
1286
|
+
column: {
|
|
1287
|
+
type: "integer",
|
|
1288
|
+
description: "Column (1-based)",
|
|
1289
|
+
},
|
|
1290
|
+
},
|
|
1291
|
+
required: ["filePath", "line", "column"],
|
|
1292
|
+
additionalProperties: false,
|
|
1293
|
+
},
|
|
1294
|
+
outputSchema: {
|
|
1295
|
+
type: "object",
|
|
1296
|
+
properties: {
|
|
1297
|
+
found: { type: "boolean" },
|
|
1298
|
+
message: { type: "string" },
|
|
1299
|
+
locations: {
|
|
1300
|
+
type: "array",
|
|
1301
|
+
items: {
|
|
1302
|
+
type: "object",
|
|
1303
|
+
properties: {
|
|
1304
|
+
file: { type: "string" },
|
|
1305
|
+
line: { type: "number" },
|
|
1306
|
+
column: { type: "number" },
|
|
1307
|
+
endLine: { type: "number" },
|
|
1308
|
+
endColumn: { type: "number" },
|
|
1309
|
+
},
|
|
1310
|
+
},
|
|
1311
|
+
},
|
|
1312
|
+
},
|
|
1313
|
+
required: ["found"],
|
|
1314
|
+
},
|
|
1315
|
+
},
|
|
1316
|
+
handler: async (args, signal) => {
|
|
1317
|
+
if (!extensionClient.isConnected()) {
|
|
1318
|
+
return extensionRequired("LSP features", [
|
|
1319
|
+
"Use runCommand with tsc, eslint, pyright, or biome for CLI-based analysis",
|
|
1320
|
+
"Use getDiagnostics for lint/type-check results from CLI linters",
|
|
1321
|
+
]);
|
|
1322
|
+
}
|
|
1323
|
+
const filePath = resolveFilePath(requireString(args, "filePath"), workspace);
|
|
1324
|
+
const line = requireInt(args, "line");
|
|
1325
|
+
const column = requireInt(args, "column");
|
|
1326
|
+
const result = await lspWithRetry(() => extensionClient.goToDeclaration(filePath, line, column, signal), signal, readinessChecker(extensionClient, filePath));
|
|
1327
|
+
if (result === "timeout")
|
|
1328
|
+
return lspColdStartError();
|
|
1329
|
+
if (result === null) {
|
|
1330
|
+
return successStructured({
|
|
1331
|
+
found: false,
|
|
1332
|
+
message: "No declaration found at this position",
|
|
1333
|
+
});
|
|
1334
|
+
}
|
|
1335
|
+
return successStructured(result);
|
|
1336
|
+
},
|
|
1337
|
+
};
|
|
1338
|
+
}
|
|
1339
|
+
//# sourceMappingURL=lsp.js.map
|