octocode-cli 1.2.6 → 1.2.8
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 -63
- package/README.md +85 -142
- package/out/octocode-cli.js +7063 -6934
- package/package.json +8 -6
- package/skills/README.md +97 -120
- package/skills/octocode-code-engineer/.claude/settings.local.json +18 -0
- package/skills/octocode-code-engineer/.octocode/rfc/RFC-code-engineer-weakness-fixes.md +255 -0
- package/skills/octocode-code-engineer/.plan/VALIDATED_PLAN.md +223 -0
- package/skills/octocode-code-engineer/README.md +178 -0
- package/skills/octocode-code-engineer/SKILL.md +418 -0
- package/skills/octocode-code-engineer/coverage/architecture.ts.html +7828 -0
- package/skills/octocode-code-engineer/coverage/ast-helpers.ts.html +211 -0
- package/skills/octocode-code-engineer/coverage/ast-search.ts.html +1795 -0
- package/skills/octocode-code-engineer/coverage/base.css +224 -0
- package/skills/octocode-code-engineer/coverage/block-navigation.js +87 -0
- package/skills/octocode-code-engineer/coverage/cache.ts.html +376 -0
- package/skills/octocode-code-engineer/coverage/cli.ts.html +982 -0
- package/skills/octocode-code-engineer/coverage/clover.xml +3217 -0
- package/skills/octocode-code-engineer/coverage/collect-effects.ts.html +664 -0
- package/skills/octocode-code-engineer/coverage/collect-input-sources.ts.html +577 -0
- package/skills/octocode-code-engineer/coverage/collect-performance.ts.html +331 -0
- package/skills/octocode-code-engineer/coverage/collect-prototype-pollution.ts.html +421 -0
- package/skills/octocode-code-engineer/coverage/collect-security.ts.html +604 -0
- package/skills/octocode-code-engineer/coverage/collect-test-profile.ts.html +589 -0
- package/skills/octocode-code-engineer/coverage/coverage-final.json +30 -0
- package/skills/octocode-code-engineer/coverage/dependencies.ts.html +997 -0
- package/skills/octocode-code-engineer/coverage/dependency-summary.ts.html +688 -0
- package/skills/octocode-code-engineer/coverage/discovery.ts.html +322 -0
- package/skills/octocode-code-engineer/coverage/favicon.png +0 -0
- package/skills/octocode-code-engineer/coverage/graph-analytics.ts.html +1510 -0
- package/skills/octocode-code-engineer/coverage/index.html +536 -0
- package/skills/octocode-code-engineer/coverage/index.ts.html +826 -0
- package/skills/octocode-code-engineer/coverage/metrics.ts.html +553 -0
- package/skills/octocode-code-engineer/coverage/pipeline.ts.html +2044 -0
- package/skills/octocode-code-engineer/coverage/prettify.css +1 -0
- package/skills/octocode-code-engineer/coverage/prettify.js +2 -0
- package/skills/octocode-code-engineer/coverage/report-analysis.ts.html +1570 -0
- package/skills/octocode-code-engineer/coverage/report-writer.ts.html +1102 -0
- package/skills/octocode-code-engineer/coverage/security-detectors.ts.html +1747 -0
- package/skills/octocode-code-engineer/coverage/semantic-detectors.ts.html +2152 -0
- package/skills/octocode-code-engineer/coverage/semantic.ts.html +1897 -0
- package/skills/octocode-code-engineer/coverage/sort-arrow-sprite.png +0 -0
- package/skills/octocode-code-engineer/coverage/sorter.js +210 -0
- package/skills/octocode-code-engineer/coverage/summary-md.ts.html +1222 -0
- package/skills/octocode-code-engineer/coverage/test-quality-detectors.ts.html +1039 -0
- package/skills/octocode-code-engineer/coverage/tree-sitter-analyzer.ts.html +955 -0
- package/skills/octocode-code-engineer/coverage/ts-analyzer.ts.html +1213 -0
- package/skills/octocode-code-engineer/coverage/types.ts.html +2473 -0
- package/skills/octocode-code-engineer/coverage/utils.ts.html +820 -0
- package/skills/octocode-code-engineer/eslint.config.mjs +54 -0
- package/skills/octocode-code-engineer/minify-scripts.mjs +32 -0
- package/skills/octocode-code-engineer/package.json +54 -0
- package/skills/octocode-code-engineer/references/agent-ast-reading-rfc.md +95 -0
- package/skills/octocode-code-engineer/references/architecture-techniques.md +121 -0
- package/skills/octocode-code-engineer/references/ast-search.md +210 -0
- package/skills/octocode-code-engineer/references/ast-tree-search.md +151 -0
- package/skills/octocode-code-engineer/references/cli-reference.md +167 -0
- package/skills/octocode-code-engineer/references/concepts.md +107 -0
- package/skills/octocode-code-engineer/references/finding-categories.md +128 -0
- package/skills/octocode-code-engineer/references/improvement-roadmap.md +304 -0
- package/skills/octocode-code-engineer/references/output-files.md +144 -0
- package/skills/octocode-code-engineer/references/playbooks.md +204 -0
- package/skills/octocode-code-engineer/references/present-results.md +136 -0
- package/skills/octocode-code-engineer/references/tool-workflows.md +566 -0
- package/skills/octocode-code-engineer/references/validate-investigate.md +225 -0
- package/skills/octocode-code-engineer/scripts/analysis/dependencies.js +1 -0
- package/skills/octocode-code-engineer/scripts/analysis/dependency-summary.js +1 -0
- package/skills/octocode-code-engineer/scripts/analysis/discovery.js +1 -0
- package/skills/octocode-code-engineer/scripts/analysis/graph-analytics.js +1 -0
- package/skills/octocode-code-engineer/scripts/analysis/semantic.js +1 -0
- package/skills/octocode-code-engineer/scripts/ast/helpers.js +1 -0
- package/skills/octocode-code-engineer/scripts/ast/metrics.js +1 -0
- package/skills/octocode-code-engineer/scripts/ast/search.js +2 -0
- package/skills/octocode-code-engineer/scripts/ast/tree-search.js +2 -0
- package/skills/octocode-code-engineer/scripts/ast/tree-sitter.js +1 -0
- package/skills/octocode-code-engineer/scripts/ast/ts-analyzer.js +1 -0
- package/skills/octocode-code-engineer/scripts/collectors/chains.js +1 -0
- package/skills/octocode-code-engineer/scripts/collectors/effects.js +1 -0
- package/skills/octocode-code-engineer/scripts/collectors/input-sources.js +1 -0
- package/skills/octocode-code-engineer/scripts/collectors/performance.js +1 -0
- package/skills/octocode-code-engineer/scripts/collectors/prototype-pollution.js +1 -0
- package/skills/octocode-code-engineer/scripts/collectors/security.js +1 -0
- package/skills/octocode-code-engineer/scripts/collectors/test-profile.js +1 -0
- package/skills/octocode-code-engineer/scripts/common/is-direct-run.js +1 -0
- package/skills/octocode-code-engineer/scripts/common/utils.js +1 -0
- package/skills/octocode-code-engineer/scripts/detectors/code-quality.js +1 -0
- package/skills/octocode-code-engineer/scripts/detectors/cohesion.js +1 -0
- package/skills/octocode-code-engineer/scripts/detectors/coupling.js +1 -0
- package/skills/octocode-code-engineer/scripts/detectors/cycle.js +1 -0
- package/skills/octocode-code-engineer/scripts/detectors/dead-code.js +1 -0
- package/skills/octocode-code-engineer/scripts/detectors/import-style.js +1 -0
- package/skills/octocode-code-engineer/scripts/detectors/index.js +1 -0
- package/skills/octocode-code-engineer/scripts/detectors/security.js +1 -0
- package/skills/octocode-code-engineer/scripts/detectors/semantic.js +1 -0
- package/skills/octocode-code-engineer/scripts/detectors/shared.js +1 -0
- package/skills/octocode-code-engineer/scripts/detectors/test-quality.js +1 -0
- package/skills/octocode-code-engineer/scripts/index.js +1 -0
- package/skills/octocode-code-engineer/scripts/pipeline/cache.js +1 -0
- package/skills/octocode-code-engineer/scripts/pipeline/cli.js +1 -0
- package/skills/octocode-code-engineer/scripts/pipeline/main.js +2 -0
- package/skills/octocode-code-engineer/scripts/reporting/analysis.js +1 -0
- package/skills/octocode-code-engineer/scripts/reporting/summary-md.js +1 -0
- package/skills/octocode-code-engineer/scripts/reporting/writer.js +1 -0
- package/skills/octocode-code-engineer/scripts/types/constants.js +1 -0
- package/skills/octocode-code-engineer/scripts/types/index.js +1 -0
- package/skills/octocode-code-engineer/scripts/types/interfaces.js +1 -0
- package/skills/octocode-code-engineer/src/analysis/dependencies.test.ts +545 -0
- package/skills/octocode-code-engineer/src/analysis/dependencies.ts +406 -0
- package/skills/octocode-code-engineer/src/analysis/dependency-summary.test.ts +566 -0
- package/skills/octocode-code-engineer/src/analysis/dependency-summary.ts +257 -0
- package/skills/octocode-code-engineer/src/analysis/discovery.test.ts +420 -0
- package/skills/octocode-code-engineer/src/analysis/discovery.ts +87 -0
- package/skills/octocode-code-engineer/src/analysis/graph-analytics.test.ts +449 -0
- package/skills/octocode-code-engineer/src/analysis/graph-analytics.ts +534 -0
- package/skills/octocode-code-engineer/src/analysis/semantic.test.ts +1533 -0
- package/skills/octocode-code-engineer/src/analysis/semantic.ts +830 -0
- package/skills/octocode-code-engineer/src/ast/helpers.test.ts +185 -0
- package/skills/octocode-code-engineer/src/ast/helpers.ts +62 -0
- package/skills/octocode-code-engineer/src/ast/metrics.test.ts +304 -0
- package/skills/octocode-code-engineer/src/ast/metrics.ts +204 -0
- package/skills/octocode-code-engineer/src/ast/search.test.ts +647 -0
- package/skills/octocode-code-engineer/src/ast/search.ts +648 -0
- package/skills/octocode-code-engineer/src/ast/tree-search.test.ts +199 -0
- package/skills/octocode-code-engineer/src/ast/tree-search.ts +392 -0
- package/skills/octocode-code-engineer/src/ast/tree-sitter.test.ts +407 -0
- package/skills/octocode-code-engineer/src/ast/tree-sitter.ts +402 -0
- package/skills/octocode-code-engineer/src/ast/ts-analyzer.test.ts +1864 -0
- package/skills/octocode-code-engineer/src/ast/ts-analyzer.ts +509 -0
- package/skills/octocode-code-engineer/src/collectors/chains.ts +74 -0
- package/skills/octocode-code-engineer/src/collectors/effects.test.ts +490 -0
- package/skills/octocode-code-engineer/src/collectors/effects.ts +332 -0
- package/skills/octocode-code-engineer/src/collectors/input-sources.test.ts +144 -0
- package/skills/octocode-code-engineer/src/collectors/input-sources.ts +196 -0
- package/skills/octocode-code-engineer/src/collectors/performance.test.ts +82 -0
- package/skills/octocode-code-engineer/src/collectors/performance.ts +141 -0
- package/skills/octocode-code-engineer/src/collectors/prototype-pollution.test.ts +55 -0
- package/skills/octocode-code-engineer/src/collectors/prototype-pollution.ts +162 -0
- package/skills/octocode-code-engineer/src/collectors/security.test.ts +124 -0
- package/skills/octocode-code-engineer/src/collectors/security.ts +309 -0
- package/skills/octocode-code-engineer/src/collectors/test-profile.test.ts +97 -0
- package/skills/octocode-code-engineer/src/collectors/test-profile.ts +269 -0
- package/skills/octocode-code-engineer/src/common/is-direct-run.test.ts +32 -0
- package/skills/octocode-code-engineer/src/common/is-direct-run.ts +13 -0
- package/skills/octocode-code-engineer/src/common/utils.test.ts +463 -0
- package/skills/octocode-code-engineer/src/common/utils.ts +304 -0
- package/skills/octocode-code-engineer/src/detectors/code-quality.ts +966 -0
- package/skills/octocode-code-engineer/src/detectors/cohesion.ts +539 -0
- package/skills/octocode-code-engineer/src/detectors/coupling.ts +323 -0
- package/skills/octocode-code-engineer/src/detectors/cycle.ts +349 -0
- package/skills/octocode-code-engineer/src/detectors/dead-code.ts +320 -0
- package/skills/octocode-code-engineer/src/detectors/import-style.ts +376 -0
- package/skills/octocode-code-engineer/src/detectors/index.test.ts +3061 -0
- package/skills/octocode-code-engineer/src/detectors/index.ts +88 -0
- package/skills/octocode-code-engineer/src/detectors/security.test.ts +882 -0
- package/skills/octocode-code-engineer/src/detectors/security.ts +821 -0
- package/skills/octocode-code-engineer/src/detectors/semantic.ts +758 -0
- package/skills/octocode-code-engineer/src/detectors/shared.ts +49 -0
- package/skills/octocode-code-engineer/src/detectors/test-quality.test.ts +388 -0
- package/skills/octocode-code-engineer/src/detectors/test-quality.ts +367 -0
- package/skills/octocode-code-engineer/src/index.test.ts +4425 -0
- package/skills/octocode-code-engineer/src/index.ts +403 -0
- package/skills/octocode-code-engineer/src/pipeline/cache.test.ts +199 -0
- package/skills/octocode-code-engineer/src/pipeline/cache.ts +130 -0
- package/skills/octocode-code-engineer/src/pipeline/cli.test.ts +493 -0
- package/skills/octocode-code-engineer/src/pipeline/cli.ts +344 -0
- package/skills/octocode-code-engineer/src/pipeline/main.test.ts +174 -0
- package/skills/octocode-code-engineer/src/pipeline/main.ts +1074 -0
- package/skills/octocode-code-engineer/src/pipeline.test.ts +84 -0
- package/skills/octocode-code-engineer/src/reporting/analysis.test.ts +782 -0
- package/skills/octocode-code-engineer/src/reporting/analysis.ts +688 -0
- package/skills/octocode-code-engineer/src/reporting/output-contract.test.ts +463 -0
- package/skills/octocode-code-engineer/src/reporting/summary-md.test.ts +421 -0
- package/skills/octocode-code-engineer/src/reporting/summary-md.ts +714 -0
- package/skills/octocode-code-engineer/src/reporting/writer.ts +430 -0
- package/skills/octocode-code-engineer/src/sanity.test.ts +47 -0
- package/skills/octocode-code-engineer/src/types/constants.ts +248 -0
- package/skills/octocode-code-engineer/src/types/index.ts +80 -0
- package/skills/octocode-code-engineer/src/types/interfaces.ts +682 -0
- package/skills/octocode-code-engineer/tsconfig.json +17 -0
- package/skills/octocode-code-engineer/vitest.config.ts +8 -0
- package/skills/octocode-documentation-writer/README.md +113 -0
- package/skills/octocode-documentation-writer/SKILL.md +886 -0
- package/skills/octocode-documentation-writer/references/agent-discovery-analysis.md +453 -0
- package/skills/octocode-documentation-writer/references/agent-documentation-writer.md +255 -0
- package/skills/octocode-documentation-writer/references/agent-engineer-questions.md +247 -0
- package/skills/octocode-documentation-writer/references/agent-orchestrator.md +370 -0
- package/skills/octocode-documentation-writer/references/agent-qa-validator.md +227 -0
- package/skills/octocode-documentation-writer/references/agent-researcher.md +250 -0
- package/skills/octocode-documentation-writer/schemas/analysis-schema.json +886 -0
- package/skills/octocode-documentation-writer/schemas/discovery-tasks.json +96 -0
- package/skills/octocode-documentation-writer/schemas/documentation-structure.json +373 -0
- package/skills/octocode-documentation-writer/schemas/partial-discovery-schema.json +102 -0
- package/skills/octocode-documentation-writer/schemas/partial-research-schema.json +98 -0
- package/skills/octocode-documentation-writer/schemas/qa-results-schema.json +113 -0
- package/skills/octocode-documentation-writer/schemas/questions-schema.json +228 -0
- package/skills/octocode-documentation-writer/schemas/research-schema.json +104 -0
- package/skills/octocode-documentation-writer/schemas/state-schema.json +222 -0
- package/skills/octocode-documentation-writer/schemas/work-assignments-schema.json +74 -0
- package/skills/octocode-plan/SKILL.md +122 -116
- package/skills/octocode-prompt-optimizer/SKILL.md +617 -0
- package/skills/octocode-pull-request-reviewer/README.md +249 -0
- package/skills/octocode-pull-request-reviewer/SKILL.md +479 -0
- package/skills/octocode-pull-request-reviewer/references/dependency-check.md +74 -0
- package/skills/octocode-pull-request-reviewer/references/domain-reviewers.md +24 -0
- package/skills/octocode-pull-request-reviewer/references/execution-lifecycle.md +441 -0
- package/skills/octocode-pull-request-reviewer/references/flow-analysis-protocol.md +64 -0
- package/skills/octocode-pull-request-reviewer/references/output-template.md +174 -0
- package/skills/octocode-pull-request-reviewer/references/parallel-agent-protocol.md +182 -0
- package/skills/octocode-pull-request-reviewer/references/review-guidelines.md +26 -0
- package/skills/octocode-pull-request-reviewer/references/verification-checklist.md +40 -0
- package/skills/octocode-research/.claude/settings.local.json +46 -0
- package/skills/octocode-research/.octocode/plan/code-review-fixes/plan.md +312 -0
- package/skills/octocode-research/.octocode/plan/code-review-fixes/research.md +212 -0
- package/skills/octocode-research/.octocode/plans/NODE_SERVER_START_PLAN.md +755 -0
- package/skills/octocode-research/.octocode/research/code-review/research.md +371 -0
- package/skills/octocode-research/.octocode/review/IMPROVEMENTS.md +391 -0
- package/skills/octocode-research/.octocode/review/REVIEW_PLAN.md +289 -0
- package/skills/octocode-research/.octocode/review/REVIEW_REPORT.md +356 -0
- package/skills/octocode-research/AGENTS.md +349 -0
- package/skills/octocode-research/README.md +494 -0
- package/skills/octocode-research/SKILL.md +652 -274
- package/skills/octocode-research/docs/API_REFERENCE.md +562 -0
- package/skills/octocode-research/docs/ARCHITECTURE.md +554 -0
- package/skills/octocode-research/docs/FLOWS.md +577 -0
- package/skills/octocode-research/docs/OVERVIEW.md +564 -0
- package/skills/octocode-research/docs/SERVER_FLOWS.md +631 -0
- package/skills/octocode-research/ecosystem.config.cjs +88 -0
- package/skills/octocode-research/eslint.config.mjs +27 -0
- package/skills/octocode-research/package.json +84 -0
- package/skills/octocode-research/references/GUARDRAILS.md +40 -0
- package/skills/octocode-research/references/PARALLEL_AGENT_PROTOCOL.md +178 -0
- package/skills/octocode-research/references/roast-prompt.md +149 -0
- package/skills/octocode-research/scripts/server-init.d.ts +2 -0
- package/skills/octocode-research/scripts/server-init.js +2 -0
- package/skills/octocode-research/scripts/server.d.ts +8 -0
- package/skills/octocode-research/scripts/server.js +445 -0
- package/skills/octocode-research/src/__tests__/integration/circuitBreaker.test.ts +205 -0
- package/skills/octocode-research/src/__tests__/integration/routes.test.ts +374 -0
- package/skills/octocode-research/src/__tests__/unit/circuitBreaker.test.ts +245 -0
- package/skills/octocode-research/src/__tests__/unit/errorHandler.test.ts +183 -0
- package/skills/octocode-research/src/__tests__/unit/httpPreprocess.test.ts +157 -0
- package/skills/octocode-research/src/__tests__/unit/logger.test.ts +143 -0
- package/skills/octocode-research/src/__tests__/unit/queryParser.test.ts +130 -0
- package/skills/octocode-research/src/__tests__/unit/responseBuilder.test.ts +469 -0
- package/skills/octocode-research/src/__tests__/unit/retry.test.ts +205 -0
- package/skills/octocode-research/src/index.ts +186 -0
- package/skills/octocode-research/src/mcpCache.ts +49 -0
- package/skills/octocode-research/src/middleware/errorHandler.ts +65 -0
- package/skills/octocode-research/src/middleware/logger.ts +61 -0
- package/skills/octocode-research/src/middleware/queryParser.ts +115 -0
- package/skills/octocode-research/src/middleware/readiness.ts +17 -0
- package/skills/octocode-research/src/routes/github.ts +197 -0
- package/skills/octocode-research/src/routes/local.ts +175 -0
- package/skills/octocode-research/src/routes/lsp.ts +177 -0
- package/skills/octocode-research/src/routes/package.ts +127 -0
- package/skills/octocode-research/src/routes/prompts.ts +138 -0
- package/skills/octocode-research/src/routes/tools.ts +677 -0
- package/skills/octocode-research/src/server-init.ts +363 -0
- package/skills/octocode-research/src/server.ts +285 -0
- package/skills/octocode-research/src/types/errorGuards.ts +151 -0
- package/skills/octocode-research/src/types/express.d.ts +76 -0
- package/skills/octocode-research/src/types/guards.ts +98 -0
- package/skills/octocode-research/src/types/mcp.ts +119 -0
- package/skills/octocode-research/src/types/responses.ts +199 -0
- package/skills/octocode-research/src/types/toolTypes.ts +33 -0
- package/skills/octocode-research/src/utils/asyncTimeout.ts +116 -0
- package/skills/octocode-research/src/utils/circuitBreaker.ts +492 -0
- package/skills/octocode-research/src/utils/colors.ts +53 -0
- package/skills/octocode-research/src/utils/errorQueue.ts +71 -0
- package/skills/octocode-research/src/utils/logEmoji.ts +103 -0
- package/skills/octocode-research/src/utils/logger.ts +413 -0
- package/skills/octocode-research/src/utils/resilience.ts +169 -0
- package/skills/octocode-research/src/utils/responseBuilder.ts +495 -0
- package/skills/octocode-research/src/utils/responseFactory.ts +100 -0
- package/skills/octocode-research/src/utils/responseParser.ts +272 -0
- package/skills/octocode-research/src/utils/retry.ts +280 -0
- package/skills/octocode-research/src/utils/routeFactory.ts +117 -0
- package/skills/octocode-research/src/utils/url.ts +20 -0
- package/skills/octocode-research/src/validation/httpPreprocess.ts +155 -0
- package/skills/octocode-research/src/validation/index.ts +2 -0
- package/skills/octocode-research/src/validation/schemas.ts +578 -0
- package/skills/octocode-research/src/validation/toolCallSchema.ts +132 -0
- package/skills/octocode-research/tsconfig.json +21 -0
- package/skills/octocode-research/tsdown.config.ts +42 -0
- package/skills/octocode-research/vitest.config.ts +20 -0
- package/skills/octocode-researcher/SKILL.md +461 -0
- package/skills/octocode-researcher/references/fallbacks.md +120 -0
- package/skills/{octocode-local-search → octocode-researcher}/references/tool-reference.md +132 -49
- package/skills/{octocode-local-search → octocode-researcher}/references/workflow-patterns.md +204 -4
- package/skills/octocode-rfc-generator/SKILL.md +223 -0
- package/skills/octocode-rfc-generator/references/rfc-template.md +193 -0
- package/skills/octocode-roast/SKILL.md +63 -21
- package/skills/octocode-implement/SKILL.md +0 -293
- package/skills/octocode-implement/references/execution-phases.md +0 -317
- package/skills/octocode-implement/references/tool-reference.md +0 -403
- package/skills/octocode-implement/references/workflow-patterns.md +0 -385
- package/skills/octocode-local-search/SKILL.md +0 -449
- package/skills/octocode-pr-review/SKILL.md +0 -391
- package/skills/octocode-pr-review/references/domain-reviewers.md +0 -105
- package/skills/octocode-pr-review/references/execution-lifecycle.md +0 -116
- package/skills/octocode-pr-review/references/research-flows.md +0 -75
- package/skills/octocode-research/references/tool-reference.md +0 -304
- package/skills/octocode-research/references/workflow-patterns.md +0 -325
|
@@ -0,0 +1,677 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tools Info Routes - Expose tool metadata via HTTP
|
|
3
|
+
*
|
|
4
|
+
* Routes:
|
|
5
|
+
* GET /tools/list - List all tools (concise)
|
|
6
|
+
* GET /tools/info - List all tools with details
|
|
7
|
+
* GET /tools/info/:toolName - Get specific tool info
|
|
8
|
+
* POST /tools/call/:toolName - Execute a tool directly (simplified!)
|
|
9
|
+
*
|
|
10
|
+
* Query params:
|
|
11
|
+
* schema=true - Include schema information
|
|
12
|
+
* hints=true - Include hints information
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { Router, type Request, type Response, type NextFunction } from 'express';
|
|
16
|
+
import { getMcpContent } from '../mcpCache.js';
|
|
17
|
+
import { transformToJsonSchema } from '../types/mcp.js';
|
|
18
|
+
import { zodToJsonSchema } from 'zod-to-json-schema';
|
|
19
|
+
import type { z } from 'zod/v4';
|
|
20
|
+
|
|
21
|
+
// Import Zod schemas from octocode-mcp (source of truth)
|
|
22
|
+
import {
|
|
23
|
+
GitHubCodeSearchQuerySchema,
|
|
24
|
+
GitHubViewRepoStructureQuerySchema,
|
|
25
|
+
GitHubReposSearchSingleQuerySchema,
|
|
26
|
+
GitHubPullRequestSearchQuerySchema,
|
|
27
|
+
FileContentQuerySchema,
|
|
28
|
+
RipgrepQuerySchema,
|
|
29
|
+
FetchContentQuerySchema,
|
|
30
|
+
FindFilesQuerySchema,
|
|
31
|
+
ViewStructureQuerySchema,
|
|
32
|
+
LSPGotoDefinitionQuerySchema,
|
|
33
|
+
LSPFindReferencesQuerySchema,
|
|
34
|
+
LSPCallHierarchyQuerySchema,
|
|
35
|
+
PackageSearchQuerySchema,
|
|
36
|
+
} from 'octocode-mcp/public';
|
|
37
|
+
import {
|
|
38
|
+
githubSearchCode,
|
|
39
|
+
githubGetFileContent,
|
|
40
|
+
githubViewRepoStructure,
|
|
41
|
+
githubSearchRepositories,
|
|
42
|
+
githubSearchPullRequests,
|
|
43
|
+
packageSearch,
|
|
44
|
+
localSearchCode,
|
|
45
|
+
localGetFileContent,
|
|
46
|
+
localFindFiles,
|
|
47
|
+
localViewStructure,
|
|
48
|
+
lspGotoDefinition,
|
|
49
|
+
lspFindReferences,
|
|
50
|
+
lspCallHierarchy,
|
|
51
|
+
logToolCall,
|
|
52
|
+
} from '../index.js';
|
|
53
|
+
import {
|
|
54
|
+
withGitHubResilience,
|
|
55
|
+
withLocalResilience,
|
|
56
|
+
withLspResilience,
|
|
57
|
+
withPackageResilience,
|
|
58
|
+
} from '../utils/resilience.js';
|
|
59
|
+
import { parseToolResponse, parseToolResponseBulk } from '../utils/responseParser.js';
|
|
60
|
+
import { fireAndForgetWithTimeout } from '../utils/asyncTimeout.js';
|
|
61
|
+
import { validateToolCallBody, getValidationHints } from '../validation/toolCallSchema.js';
|
|
62
|
+
import { checkReadiness } from '../middleware/readiness.js';
|
|
63
|
+
|
|
64
|
+
export const toolsRoutes = Router();
|
|
65
|
+
|
|
66
|
+
// Apply readiness check middleware to all tools routes
|
|
67
|
+
toolsRoutes.use(checkReadiness);
|
|
68
|
+
|
|
69
|
+
// Package version for response metadata
|
|
70
|
+
const PACKAGE_VERSION = '2.0.0';
|
|
71
|
+
|
|
72
|
+
interface ToolsInfoQuery {
|
|
73
|
+
schema?: string;
|
|
74
|
+
hints?: string;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// ============================================================================
|
|
78
|
+
// Zod Schema Registry - Maps tool names to their Zod schemas (source of truth)
|
|
79
|
+
// ============================================================================
|
|
80
|
+
|
|
81
|
+
const TOOL_ZOD_SCHEMAS: Record<string, z.ZodType> = {
|
|
82
|
+
// GitHub tools
|
|
83
|
+
githubSearchCode: GitHubCodeSearchQuerySchema,
|
|
84
|
+
githubGetFileContent: FileContentQuerySchema,
|
|
85
|
+
githubViewRepoStructure: GitHubViewRepoStructureQuerySchema,
|
|
86
|
+
githubSearchRepositories: GitHubReposSearchSingleQuerySchema,
|
|
87
|
+
githubSearchPullRequests: GitHubPullRequestSearchQuerySchema,
|
|
88
|
+
// Local tools
|
|
89
|
+
localSearchCode: RipgrepQuerySchema,
|
|
90
|
+
localGetFileContent: FetchContentQuerySchema,
|
|
91
|
+
localFindFiles: FindFilesQuerySchema,
|
|
92
|
+
localViewStructure: ViewStructureQuerySchema,
|
|
93
|
+
// LSP tools
|
|
94
|
+
lspGotoDefinition: LSPGotoDefinitionQuerySchema,
|
|
95
|
+
lspFindReferences: LSPFindReferencesQuerySchema,
|
|
96
|
+
lspCallHierarchy: LSPCallHierarchyQuerySchema,
|
|
97
|
+
// Package tools
|
|
98
|
+
packageSearch: PackageSearchQuerySchema,
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Convert a Zod v4 schema to JSON Schema via zod-to-json-schema.
|
|
103
|
+
* The library expects Zod v3 types; schemas are structurally compatible at runtime.
|
|
104
|
+
*/
|
|
105
|
+
function toJsonSchema(
|
|
106
|
+
schema: z.ZodType,
|
|
107
|
+
name: string
|
|
108
|
+
): Record<string, unknown> | null {
|
|
109
|
+
try {
|
|
110
|
+
type ZodToJsonSchemaInput = Parameters<typeof zodToJsonSchema>[0];
|
|
111
|
+
return zodToJsonSchema(schema as unknown as ZodToJsonSchemaInput, {
|
|
112
|
+
name,
|
|
113
|
+
$refStrategy: 'none',
|
|
114
|
+
}) as Record<string, unknown>;
|
|
115
|
+
} catch {
|
|
116
|
+
return null;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function getToolJsonSchema(toolName: string): Record<string, unknown> | null {
|
|
121
|
+
const zodSchema = TOOL_ZOD_SCHEMAS[toolName];
|
|
122
|
+
return zodSchema ? toJsonSchema(zodSchema, toolName) : null;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* GET /tools/list - Static list of all tools (concise discovery)
|
|
127
|
+
*
|
|
128
|
+
* Returns static JSON with tool names and short descriptions.
|
|
129
|
+
* Use /tools/info/:toolName to get full description + schema BEFORE calling a tool.
|
|
130
|
+
*/
|
|
131
|
+
toolsRoutes.get('/list', (_req: Request, res: Response) => {
|
|
132
|
+
res.json({
|
|
133
|
+
success: true,
|
|
134
|
+
data: {
|
|
135
|
+
tools: [
|
|
136
|
+
{ name: 'githubSearchCode', description: 'Search code in GitHub repos' },
|
|
137
|
+
{ name: 'githubGetFileContent', description: 'Read file from GitHub repo' },
|
|
138
|
+
{ name: 'githubViewRepoStructure', description: 'View GitHub repo tree' },
|
|
139
|
+
{ name: 'githubSearchRepositories', description: 'Search GitHub repositories' },
|
|
140
|
+
{ name: 'githubSearchPullRequests', description: 'Search pull requests' },
|
|
141
|
+
{ name: 'packageSearch', description: 'Search npm/PyPI packages' },
|
|
142
|
+
{ name: 'localSearchCode', description: 'Search local code with ripgrep' },
|
|
143
|
+
{ name: 'localGetFileContent', description: 'Read local file content' },
|
|
144
|
+
{ name: 'localFindFiles', description: 'Find files by pattern/metadata' },
|
|
145
|
+
{ name: 'localViewStructure', description: 'View local directory tree' },
|
|
146
|
+
{ name: 'lspGotoDefinition', description: 'Go to symbol definition' },
|
|
147
|
+
{ name: 'lspFindReferences', description: 'Find all symbol references' },
|
|
148
|
+
{ name: 'lspCallHierarchy', description: 'Get call hierarchy' },
|
|
149
|
+
],
|
|
150
|
+
},
|
|
151
|
+
hints: ['GET /tools/info/{name} for full schema before calling'],
|
|
152
|
+
});
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* GET /tools/info - Get info about all available tools
|
|
157
|
+
*/
|
|
158
|
+
toolsRoutes.get('/info', async (
|
|
159
|
+
req: Request,
|
|
160
|
+
res: Response,
|
|
161
|
+
next: NextFunction
|
|
162
|
+
) => {
|
|
163
|
+
try {
|
|
164
|
+
const content = getMcpContent();
|
|
165
|
+
|
|
166
|
+
const query = req.query as ToolsInfoQuery;
|
|
167
|
+
const includeSchema = query.schema === 'true';
|
|
168
|
+
const includeHints = query.hints === 'true';
|
|
169
|
+
|
|
170
|
+
const toolNames = Object.keys(content.tools);
|
|
171
|
+
const tools = toolNames.map(name => {
|
|
172
|
+
const tool = content.tools[name];
|
|
173
|
+
const result: Record<string, unknown> = {
|
|
174
|
+
name: tool.name,
|
|
175
|
+
description: tool.description,
|
|
176
|
+
};
|
|
177
|
+
|
|
178
|
+
if (includeSchema) {
|
|
179
|
+
result.schema = tool.schema;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
if (includeHints) {
|
|
183
|
+
result.hints = {
|
|
184
|
+
hasResults: tool.hints.hasResults,
|
|
185
|
+
empty: tool.hints.empty,
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
return result;
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
const response: Record<string, unknown> = {
|
|
193
|
+
totalTools: toolNames.length,
|
|
194
|
+
toolNames,
|
|
195
|
+
tools,
|
|
196
|
+
};
|
|
197
|
+
|
|
198
|
+
if (includeHints) {
|
|
199
|
+
response.baseHints = content.baseHints;
|
|
200
|
+
response.genericErrorHints = content.genericErrorHints;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
res.json({
|
|
204
|
+
success: true,
|
|
205
|
+
data: response,
|
|
206
|
+
hints: ['Use /tools/info/:{{TOOL_NAME}} to get the scheme and description before using it'],
|
|
207
|
+
});
|
|
208
|
+
} catch (error) {
|
|
209
|
+
next(error);
|
|
210
|
+
}
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* GET /tools/info/:toolName - Get full info for a specific tool (call before using!)
|
|
215
|
+
*
|
|
216
|
+
* Returns complete description, JSON schema, and hints for a tool.
|
|
217
|
+
* ALWAYS call this before using a tool to understand its parameters.
|
|
218
|
+
*
|
|
219
|
+
* @example
|
|
220
|
+
* GET /tools/info/localSearchCode
|
|
221
|
+
*
|
|
222
|
+
* Response includes:
|
|
223
|
+
* - name: Tool name
|
|
224
|
+
* - description: Full description with usage details
|
|
225
|
+
* - schema: Complete JSON schema with all parameters
|
|
226
|
+
* - hints: Success/empty result hints
|
|
227
|
+
*/
|
|
228
|
+
toolsRoutes.get('/info/:toolName', async (
|
|
229
|
+
req: Request,
|
|
230
|
+
res: Response,
|
|
231
|
+
next: NextFunction
|
|
232
|
+
) => {
|
|
233
|
+
try {
|
|
234
|
+
const content = getMcpContent();
|
|
235
|
+
|
|
236
|
+
const { toolName } = req.params;
|
|
237
|
+
const query = req.query as ToolsInfoQuery;
|
|
238
|
+
const includeSchema = query.schema !== 'false'; // Default true for specific tool
|
|
239
|
+
const includeHints = query.hints !== 'false'; // Default true for specific tool
|
|
240
|
+
|
|
241
|
+
const tool = content.tools[toolName];
|
|
242
|
+
|
|
243
|
+
if (!tool) {
|
|
244
|
+
const availableTools = Object.keys(content.tools);
|
|
245
|
+
res.status(404).json({
|
|
246
|
+
success: false,
|
|
247
|
+
data: null,
|
|
248
|
+
hints: [
|
|
249
|
+
`Tool not found: ${toolName}`,
|
|
250
|
+
`Available tools: ${availableTools.slice(0, 5).join(', ')}...`,
|
|
251
|
+
'Check spelling or use /tools/list to see all tools',
|
|
252
|
+
],
|
|
253
|
+
});
|
|
254
|
+
return;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
const result: Record<string, unknown> = {
|
|
258
|
+
name: tool.name,
|
|
259
|
+
description: tool.description,
|
|
260
|
+
};
|
|
261
|
+
|
|
262
|
+
if (includeSchema) {
|
|
263
|
+
// Try to get the actual Zod schema (source of truth with correct types and required fields)
|
|
264
|
+
const zodJsonSchema = getToolJsonSchema(toolName);
|
|
265
|
+
if (zodJsonSchema) {
|
|
266
|
+
result.inputSchema = zodJsonSchema;
|
|
267
|
+
result._schemaSource = 'zod'; // Indicates this is from the authoritative Zod schema
|
|
268
|
+
} else {
|
|
269
|
+
// Fallback to metadata-based schema (less accurate)
|
|
270
|
+
result.inputSchema = transformToJsonSchema(tool.schema, tool.name);
|
|
271
|
+
result._schemaSource = 'metadata'; // Indicates this is a fallback
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
if (includeHints) {
|
|
276
|
+
result.toolHints = {
|
|
277
|
+
hasResults: tool.hints.hasResults,
|
|
278
|
+
empty: tool.hints.empty,
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
res.json({
|
|
283
|
+
success: true,
|
|
284
|
+
data: result,
|
|
285
|
+
hints: ['Review schema carefully before calling this tool'],
|
|
286
|
+
});
|
|
287
|
+
} catch (error) {
|
|
288
|
+
next(error);
|
|
289
|
+
}
|
|
290
|
+
});
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* GET /tools/metadata - Get raw complete metadata (advanced)
|
|
294
|
+
*/
|
|
295
|
+
toolsRoutes.get('/metadata', async (
|
|
296
|
+
_req: Request,
|
|
297
|
+
res: Response,
|
|
298
|
+
next: NextFunction
|
|
299
|
+
) => {
|
|
300
|
+
try {
|
|
301
|
+
const content = getMcpContent();
|
|
302
|
+
|
|
303
|
+
res.json({
|
|
304
|
+
success: true,
|
|
305
|
+
data: {
|
|
306
|
+
instructions: content.instructions,
|
|
307
|
+
toolCount: Object.keys(content.tools).length,
|
|
308
|
+
promptCount: Object.keys(content.prompts).length,
|
|
309
|
+
hasBaseSchema: !!content.baseSchema,
|
|
310
|
+
},
|
|
311
|
+
hints: ['Use /tools/info for detailed tool information'],
|
|
312
|
+
});
|
|
313
|
+
} catch (error) {
|
|
314
|
+
next(error);
|
|
315
|
+
}
|
|
316
|
+
});
|
|
317
|
+
|
|
318
|
+
/**
|
|
319
|
+
* GET /tools/schemas - Get all tools with their complete JSON schemas
|
|
320
|
+
*
|
|
321
|
+
* Returns all tool names with their full JSON schemas (from Zod).
|
|
322
|
+
* Useful for bulk schema retrieval without calling /info/:toolName for each.
|
|
323
|
+
*
|
|
324
|
+
* @example
|
|
325
|
+
* GET /tools/schemas
|
|
326
|
+
*
|
|
327
|
+
* Response:
|
|
328
|
+
* {
|
|
329
|
+
* "success": true,
|
|
330
|
+
* "data": {
|
|
331
|
+
* "totalTools": 13,
|
|
332
|
+
* "schemas": {
|
|
333
|
+
* "localSearchCode": { "type": "object", "properties": {...} },
|
|
334
|
+
* "githubSearchCode": { "type": "object", "properties": {...} },
|
|
335
|
+
* ...
|
|
336
|
+
* }
|
|
337
|
+
* }
|
|
338
|
+
* }
|
|
339
|
+
*/
|
|
340
|
+
toolsRoutes.get('/schemas', async (
|
|
341
|
+
_req: Request,
|
|
342
|
+
res: Response,
|
|
343
|
+
next: NextFunction
|
|
344
|
+
) => {
|
|
345
|
+
try {
|
|
346
|
+
const schemas: Record<string, Record<string, unknown>> = {};
|
|
347
|
+
const toolNames = Object.keys(TOOL_ZOD_SCHEMAS);
|
|
348
|
+
|
|
349
|
+
for (const toolName of toolNames) {
|
|
350
|
+
const schema = getToolJsonSchema(toolName);
|
|
351
|
+
if (schema) {
|
|
352
|
+
schemas[toolName] = schema;
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
res.json({
|
|
357
|
+
success: true,
|
|
358
|
+
data: {
|
|
359
|
+
totalTools: toolNames.length,
|
|
360
|
+
schemas,
|
|
361
|
+
},
|
|
362
|
+
hints: ['All schemas derived from Zod (source of truth)'],
|
|
363
|
+
});
|
|
364
|
+
} catch (error) {
|
|
365
|
+
next(error);
|
|
366
|
+
}
|
|
367
|
+
});
|
|
368
|
+
|
|
369
|
+
/**
|
|
370
|
+
* GET /tools/system - Get the FULL system instructions
|
|
371
|
+
*
|
|
372
|
+
* Returns the complete system prompt that should be loaded into context FIRST.
|
|
373
|
+
* This defines the agent's behavior, methodology, and best practices.
|
|
374
|
+
*
|
|
375
|
+
* @example
|
|
376
|
+
* GET /tools/system
|
|
377
|
+
*
|
|
378
|
+
* Response:
|
|
379
|
+
* {
|
|
380
|
+
* "instructions": "## Expert Code Forensics Agent...",
|
|
381
|
+
* "_meta": { "charCount": 5432, "version": "2.0.0" }
|
|
382
|
+
* }
|
|
383
|
+
*/
|
|
384
|
+
toolsRoutes.get('/system', async (
|
|
385
|
+
_req: Request,
|
|
386
|
+
res: Response,
|
|
387
|
+
next: NextFunction
|
|
388
|
+
) => {
|
|
389
|
+
try {
|
|
390
|
+
const content = getMcpContent();
|
|
391
|
+
|
|
392
|
+
res.json({
|
|
393
|
+
success: true,
|
|
394
|
+
data: {
|
|
395
|
+
instructions: content.instructions,
|
|
396
|
+
charCount: content.instructions.length,
|
|
397
|
+
version: PACKAGE_VERSION,
|
|
398
|
+
},
|
|
399
|
+
hints: ['Load this system prompt FIRST before using tools'],
|
|
400
|
+
});
|
|
401
|
+
} catch (error) {
|
|
402
|
+
next(error);
|
|
403
|
+
}
|
|
404
|
+
});
|
|
405
|
+
|
|
406
|
+
/**
|
|
407
|
+
* GET /tools/initContext - Combined system prompt and all tool schemas
|
|
408
|
+
*
|
|
409
|
+
* Combines /tools/system + /tools/schemas in one call for faster init.
|
|
410
|
+
* Returns:
|
|
411
|
+
* - system_prompt: Full instructions
|
|
412
|
+
* - tools_schema: All tool JSON schemas from Zod
|
|
413
|
+
*
|
|
414
|
+
* @example
|
|
415
|
+
* GET /tools/initContext
|
|
416
|
+
*
|
|
417
|
+
* Response:
|
|
418
|
+
* {
|
|
419
|
+
* "success": true,
|
|
420
|
+
* "system_prompt": "## Expert Code Forensics Agent...",
|
|
421
|
+
* "tools_schema": { "localSearchCode": {...}, ... },
|
|
422
|
+
* "_meta": { "promptCharCount": 5432, "toolsCount": 13, "version": "2.0.0" }
|
|
423
|
+
* }
|
|
424
|
+
*/
|
|
425
|
+
toolsRoutes.get('/initContext', async (
|
|
426
|
+
_req: Request,
|
|
427
|
+
res: Response,
|
|
428
|
+
next: NextFunction
|
|
429
|
+
) => {
|
|
430
|
+
try {
|
|
431
|
+
const content = getMcpContent();
|
|
432
|
+
|
|
433
|
+
// Build schemas (same as /tools/schemas)
|
|
434
|
+
const schemas: Record<string, Record<string, unknown>> = {};
|
|
435
|
+
for (const toolName of Object.keys(TOOL_ZOD_SCHEMAS)) {
|
|
436
|
+
const schema = getToolJsonSchema(toolName);
|
|
437
|
+
if (schema) schemas[toolName] = schema;
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
res.json({
|
|
441
|
+
success: true,
|
|
442
|
+
system_prompt: content.instructions,
|
|
443
|
+
tools_schema: schemas,
|
|
444
|
+
_meta: {
|
|
445
|
+
promptCharCount: content.instructions.length,
|
|
446
|
+
toolsCount: Object.keys(schemas).length,
|
|
447
|
+
version: PACKAGE_VERSION,
|
|
448
|
+
},
|
|
449
|
+
});
|
|
450
|
+
} catch (error) {
|
|
451
|
+
next(error);
|
|
452
|
+
}
|
|
453
|
+
});
|
|
454
|
+
|
|
455
|
+
// ============================================================================
|
|
456
|
+
// Tool Registry - Maps tool names to functions and resilience wrappers
|
|
457
|
+
// ============================================================================
|
|
458
|
+
|
|
459
|
+
type ResilienceFn = <T>(fn: () => Promise<T>, toolName: string) => Promise<T>;
|
|
460
|
+
|
|
461
|
+
/**
|
|
462
|
+
* Tool registry entry for dynamic dispatch.
|
|
463
|
+
* Tool functions are dispatched by name at runtime; Zod schemas validate inputs.
|
|
464
|
+
*/
|
|
465
|
+
interface ToolEntry {
|
|
466
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
467
|
+
fn: (params: any) => Promise<any>;
|
|
468
|
+
resilience: ResilienceFn;
|
|
469
|
+
category: 'github' | 'local' | 'lsp' | 'package';
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
const TOOL_REGISTRY: Record<string, ToolEntry> = {
|
|
473
|
+
// GitHub tools
|
|
474
|
+
githubSearchCode: { fn: githubSearchCode, resilience: withGitHubResilience, category: 'github' },
|
|
475
|
+
githubGetFileContent: { fn: githubGetFileContent, resilience: withGitHubResilience, category: 'github' },
|
|
476
|
+
githubViewRepoStructure: { fn: githubViewRepoStructure, resilience: withGitHubResilience, category: 'github' },
|
|
477
|
+
githubSearchRepositories: { fn: githubSearchRepositories, resilience: withGitHubResilience, category: 'github' },
|
|
478
|
+
githubSearchPullRequests: { fn: githubSearchPullRequests, resilience: withGitHubResilience, category: 'github' },
|
|
479
|
+
|
|
480
|
+
// Local tools
|
|
481
|
+
localSearchCode: { fn: localSearchCode, resilience: withLocalResilience, category: 'local' },
|
|
482
|
+
localGetFileContent: { fn: localGetFileContent, resilience: withLocalResilience, category: 'local' },
|
|
483
|
+
localFindFiles: { fn: localFindFiles, resilience: withLocalResilience, category: 'local' },
|
|
484
|
+
localViewStructure: { fn: localViewStructure, resilience: withLocalResilience, category: 'local' },
|
|
485
|
+
|
|
486
|
+
// LSP tools
|
|
487
|
+
lspGotoDefinition: { fn: lspGotoDefinition, resilience: withLspResilience, category: 'lsp' },
|
|
488
|
+
lspFindReferences: { fn: lspFindReferences, resilience: withLspResilience, category: 'lsp' },
|
|
489
|
+
lspCallHierarchy: { fn: lspCallHierarchy, resilience: withLspResilience, category: 'lsp' },
|
|
490
|
+
|
|
491
|
+
// Package tools
|
|
492
|
+
packageSearch: { fn: packageSearch, resilience: withPackageResilience, category: 'package' },
|
|
493
|
+
};
|
|
494
|
+
|
|
495
|
+
/**
|
|
496
|
+
* Extract repository identifiers from query parameters for session logging
|
|
497
|
+
*/
|
|
498
|
+
function extractReposFromQueries(queries: unknown[]): string[] {
|
|
499
|
+
const repos: string[] = [];
|
|
500
|
+
for (const query of queries) {
|
|
501
|
+
const q = query as Record<string, unknown>;
|
|
502
|
+
// GitHub repos: owner/repo format
|
|
503
|
+
if (q.owner && q.repo) {
|
|
504
|
+
repos.push(`${q.owner}/${q.repo}`);
|
|
505
|
+
}
|
|
506
|
+
// Local paths
|
|
507
|
+
if (q.path && typeof q.path === 'string') {
|
|
508
|
+
repos.push(q.path);
|
|
509
|
+
}
|
|
510
|
+
// LSP uris
|
|
511
|
+
if (q.uri && typeof q.uri === 'string') {
|
|
512
|
+
repos.push(q.uri);
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
return [...new Set(repos)]; // Deduplicate
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
/**
|
|
519
|
+
* Extract research parameters from the first query for logging
|
|
520
|
+
*/
|
|
521
|
+
function extractResearchParams(queries: unknown[]): {
|
|
522
|
+
mainResearchGoal?: string;
|
|
523
|
+
researchGoal?: string;
|
|
524
|
+
reasoning?: string;
|
|
525
|
+
} {
|
|
526
|
+
if (queries.length === 0) return {};
|
|
527
|
+
const q = queries[0] as Record<string, unknown>;
|
|
528
|
+
return {
|
|
529
|
+
mainResearchGoal: q.mainResearchGoal as string | undefined,
|
|
530
|
+
researchGoal: q.researchGoal as string | undefined,
|
|
531
|
+
reasoning: q.reasoning as string | undefined,
|
|
532
|
+
};
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
/**
|
|
536
|
+
* POST /tools/call/:toolName - Execute a tool directly with JSON body
|
|
537
|
+
*
|
|
538
|
+
* This is the SIMPLIFIED way to call tools. Instead of URL-encoded query params,
|
|
539
|
+
* just POST a JSON body with your queries array.
|
|
540
|
+
*
|
|
541
|
+
* @example
|
|
542
|
+
* POST /tools/call/localSearchCode
|
|
543
|
+
* Content-Type: application/json
|
|
544
|
+
*
|
|
545
|
+
* {
|
|
546
|
+
* "queries": [{
|
|
547
|
+
* "mainResearchGoal": "Find authentication handlers",
|
|
548
|
+
* "researchGoal": "Locate auth middleware",
|
|
549
|
+
* "reasoning": "Understanding auth flow",
|
|
550
|
+
* "pattern": "authenticate",
|
|
551
|
+
* "path": "/Users/me/project",
|
|
552
|
+
* "type": "ts"
|
|
553
|
+
* }]
|
|
554
|
+
* }
|
|
555
|
+
*
|
|
556
|
+
* Response:
|
|
557
|
+
* {
|
|
558
|
+
* "tool": "localSearchCode",
|
|
559
|
+
* "success": true,
|
|
560
|
+
* "data": { ... parsed tool response ... },
|
|
561
|
+
* "hints": ["Use lineHint for LSP tools", ...]
|
|
562
|
+
* }
|
|
563
|
+
*/
|
|
564
|
+
toolsRoutes.post('/call/:toolName', async (
|
|
565
|
+
req: Request,
|
|
566
|
+
res: Response,
|
|
567
|
+
next: NextFunction
|
|
568
|
+
) => {
|
|
569
|
+
// Set up AbortController for client disconnection handling
|
|
570
|
+
// NOTE: req.on('close') fires when request body is consumed, not client disconnect
|
|
571
|
+
// Use res.on('close') + socket.destroyed to detect actual client disconnection
|
|
572
|
+
const abortController = new AbortController();
|
|
573
|
+
let isAborted = false;
|
|
574
|
+
|
|
575
|
+
res.on('close', () => {
|
|
576
|
+
// Only abort if client disconnected before we finished responding
|
|
577
|
+
if (!res.writableEnded && req.socket?.destroyed) {
|
|
578
|
+
isAborted = true;
|
|
579
|
+
abortController.abort();
|
|
580
|
+
}
|
|
581
|
+
});
|
|
582
|
+
|
|
583
|
+
try {
|
|
584
|
+
const { toolName } = req.params;
|
|
585
|
+
|
|
586
|
+
// Validate tool exists
|
|
587
|
+
const toolEntry = TOOL_REGISTRY[toolName];
|
|
588
|
+
if (!toolEntry) {
|
|
589
|
+
const availableTools = Object.keys(TOOL_REGISTRY);
|
|
590
|
+
res.status(404).json({
|
|
591
|
+
tool: toolName,
|
|
592
|
+
success: false,
|
|
593
|
+
data: null,
|
|
594
|
+
hints: [
|
|
595
|
+
`Tool not found: ${toolName}`,
|
|
596
|
+
`Available tools: ${availableTools.join(', ')}`,
|
|
597
|
+
'Check spelling or use GET /tools/list',
|
|
598
|
+
],
|
|
599
|
+
});
|
|
600
|
+
return;
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
// Validate request body using schema
|
|
604
|
+
const validation = validateToolCallBody(req.body);
|
|
605
|
+
if (!validation.success) {
|
|
606
|
+
res.status(400).json({
|
|
607
|
+
tool: toolName,
|
|
608
|
+
success: false,
|
|
609
|
+
data: null,
|
|
610
|
+
hints: getValidationHints(toolName, validation.error!),
|
|
611
|
+
});
|
|
612
|
+
return;
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
const { queries } = validation.data!;
|
|
616
|
+
|
|
617
|
+
// Check if request was aborted before execution
|
|
618
|
+
if (isAborted) return;
|
|
619
|
+
|
|
620
|
+
// Execute tool with resilience (includes timeout + circuit breaker + retry)
|
|
621
|
+
const rawResult = await toolEntry.resilience(
|
|
622
|
+
() => toolEntry.fn({ queries }),
|
|
623
|
+
toolName
|
|
624
|
+
);
|
|
625
|
+
|
|
626
|
+
// Check if request was aborted after execution
|
|
627
|
+
if (isAborted) return;
|
|
628
|
+
|
|
629
|
+
// Log tool call for session telemetry
|
|
630
|
+
const repos = extractReposFromQueries(queries);
|
|
631
|
+
const researchParams = extractResearchParams(queries);
|
|
632
|
+
fireAndForgetWithTimeout(
|
|
633
|
+
() => logToolCall(
|
|
634
|
+
toolName,
|
|
635
|
+
repos,
|
|
636
|
+
researchParams.mainResearchGoal,
|
|
637
|
+
researchParams.researchGoal,
|
|
638
|
+
researchParams.reasoning
|
|
639
|
+
),
|
|
640
|
+
5000,
|
|
641
|
+
'logToolCall'
|
|
642
|
+
);
|
|
643
|
+
|
|
644
|
+
const mcpResponse = rawResult as { content: Array<{ type: string; text: string }> };
|
|
645
|
+
|
|
646
|
+
// For multiple queries, return bulk response format
|
|
647
|
+
if (queries.length > 1) {
|
|
648
|
+
const bulkParsed = parseToolResponseBulk(mcpResponse);
|
|
649
|
+
|
|
650
|
+
res.status(bulkParsed.isError ? 500 : 200).json({
|
|
651
|
+
tool: toolName,
|
|
652
|
+
bulk: true,
|
|
653
|
+
success: !bulkParsed.isError,
|
|
654
|
+
instructions: bulkParsed.instructions,
|
|
655
|
+
results: bulkParsed.results,
|
|
656
|
+
hints: bulkParsed.hints,
|
|
657
|
+
counts: bulkParsed.counts,
|
|
658
|
+
});
|
|
659
|
+
return;
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
// Single query - use existing response format for backward compatibility
|
|
663
|
+
const parsed = parseToolResponse(mcpResponse);
|
|
664
|
+
|
|
665
|
+
res.status(parsed.isError ? 500 : 200).json({
|
|
666
|
+
tool: toolName,
|
|
667
|
+
success: !parsed.isError,
|
|
668
|
+
data: parsed.data,
|
|
669
|
+
hints: parsed.hints,
|
|
670
|
+
research: parsed.research,
|
|
671
|
+
});
|
|
672
|
+
} catch (error) {
|
|
673
|
+
// Skip error handling if request was aborted
|
|
674
|
+
if (isAborted) return;
|
|
675
|
+
next(error);
|
|
676
|
+
}
|
|
677
|
+
});
|