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,169 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resilience utilities combining circuit breaker + retry + timeout for external API calls.
|
|
3
|
+
*
|
|
4
|
+
* @module utils/resilience
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { withCircuitBreaker, type CircuitBreakerConfig } from './circuitBreaker.js';
|
|
8
|
+
import { withRetry, type RetryConfig, RETRY_CONFIGS } from './retry.js';
|
|
9
|
+
import { withTimeout } from './asyncTimeout.js';
|
|
10
|
+
|
|
11
|
+
/** Default timeout for MCP tool calls (30 seconds) */
|
|
12
|
+
const DEFAULT_TOOL_TIMEOUT_MS = 30000;
|
|
13
|
+
|
|
14
|
+
/** Timeout configuration per category */
|
|
15
|
+
const TIMEOUT_CONFIGS = {
|
|
16
|
+
github: 60000, // 60s for GitHub API (rate limiting, large responses)
|
|
17
|
+
local: 30000, // 30s for local tools
|
|
18
|
+
lsp: 30000, // 30s for LSP operations
|
|
19
|
+
package: 30000, // 30s for package search
|
|
20
|
+
} as const;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Per-tool circuit breaker mapping.
|
|
24
|
+
* Isolates failures so one failing tool doesn't block unrelated tools.
|
|
25
|
+
*
|
|
26
|
+
* Grouping rationale:
|
|
27
|
+
* - GitHub: Split by API endpoint (search/content/pulls have different rate limits)
|
|
28
|
+
* - LSP: Split by operation weight (navigation vs hierarchy)
|
|
29
|
+
* - Local: Unified (same failure mode - filesystem)
|
|
30
|
+
* - Package: Unified (could split npm/pypi later)
|
|
31
|
+
*/
|
|
32
|
+
const TOOL_CIRCUIT_MAP: Record<string, string> = {
|
|
33
|
+
// GitHub - separate by endpoint type (rate limits differ)
|
|
34
|
+
githubSearchCode: 'github:search', // Search API (30 req/min)
|
|
35
|
+
githubSearchRepositories: 'github:search', // Search API
|
|
36
|
+
githubSearchPullRequests: 'github:pulls', // PR API (separate quota)
|
|
37
|
+
githubGetFileContent: 'github:content', // Contents API (higher limit)
|
|
38
|
+
githubViewRepoStructure: 'github:content', // Contents API (tree)
|
|
39
|
+
|
|
40
|
+
// LSP - per operation type (different failure modes)
|
|
41
|
+
lspGotoDefinition: 'lsp:navigation', // Fast, single lookup
|
|
42
|
+
lspFindReferences: 'lsp:navigation', // Fast, single lookup
|
|
43
|
+
lspCallHierarchy: 'lsp:hierarchy', // Heavier, recursive operation
|
|
44
|
+
|
|
45
|
+
// Local - unified (same failure mode: filesystem)
|
|
46
|
+
localSearchCode: 'local',
|
|
47
|
+
localGetFileContent: 'local',
|
|
48
|
+
localFindFiles: 'local',
|
|
49
|
+
localViewStructure: 'local',
|
|
50
|
+
|
|
51
|
+
// Package - unified (could split npm/pypi later if needed)
|
|
52
|
+
packageSearch: 'package',
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Combined resilience configuration
|
|
57
|
+
*/
|
|
58
|
+
export interface ResilienceConfig {
|
|
59
|
+
circuitBreaker?: Partial<CircuitBreakerConfig>;
|
|
60
|
+
retry?: RetryConfig;
|
|
61
|
+
/** Fallback value when circuit is open */
|
|
62
|
+
fallback?: () => unknown;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Pre-configured resilience strategies
|
|
67
|
+
*/
|
|
68
|
+
const RESILIENCE_CONFIGS = {
|
|
69
|
+
github: {
|
|
70
|
+
retry: RETRY_CONFIGS.github,
|
|
71
|
+
},
|
|
72
|
+
local: {
|
|
73
|
+
retry: RETRY_CONFIGS.local,
|
|
74
|
+
},
|
|
75
|
+
lsp: {
|
|
76
|
+
retry: RETRY_CONFIGS.lsp,
|
|
77
|
+
},
|
|
78
|
+
package: {
|
|
79
|
+
retry: RETRY_CONFIGS.package,
|
|
80
|
+
},
|
|
81
|
+
} as const;
|
|
82
|
+
|
|
83
|
+
type ResilienceCategory = keyof typeof RESILIENCE_CONFIGS;
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Execute an operation with combined timeout + circuit breaker + retry protection.
|
|
87
|
+
*
|
|
88
|
+
* The protection layers work as follows:
|
|
89
|
+
* 1. TIMEOUT: Wraps entire operation to prevent hanging (outermost)
|
|
90
|
+
* 2. CIRCUIT BREAKER: If circuit is OPEN, fail fast (no retries/timeout)
|
|
91
|
+
* 3. RETRY: If circuit is CLOSED/HALF-OPEN, retry with backoff (innermost)
|
|
92
|
+
*
|
|
93
|
+
* Failures (including timeouts) contribute to circuit state.
|
|
94
|
+
*
|
|
95
|
+
* @param category - Resilience category ('github', 'local', 'lsp')
|
|
96
|
+
* @param operation - Async operation to execute
|
|
97
|
+
* @param context - Context for logging
|
|
98
|
+
* @returns Operation result
|
|
99
|
+
*
|
|
100
|
+
* @example
|
|
101
|
+
* ```typescript
|
|
102
|
+
* const result = await withResilience(
|
|
103
|
+
* 'github',
|
|
104
|
+
* () => githubSearchCode({ queries }),
|
|
105
|
+
* { tool: 'githubSearchCode' }
|
|
106
|
+
* );
|
|
107
|
+
* ```
|
|
108
|
+
*/
|
|
109
|
+
async function withResilience<T>(
|
|
110
|
+
category: ResilienceCategory,
|
|
111
|
+
operation: () => Promise<T>,
|
|
112
|
+
context?: { tool: string }
|
|
113
|
+
): Promise<T> {
|
|
114
|
+
const config = RESILIENCE_CONFIGS[category];
|
|
115
|
+
const timeoutMs = TIMEOUT_CONFIGS[category] || DEFAULT_TOOL_TIMEOUT_MS;
|
|
116
|
+
const toolName = context?.tool || category;
|
|
117
|
+
|
|
118
|
+
// Get tool-specific circuit name (isolates failures per tool/endpoint)
|
|
119
|
+
const circuitName = TOOL_CIRCUIT_MAP[toolName] || category;
|
|
120
|
+
|
|
121
|
+
// Timeout wraps circuit breaker wraps retry
|
|
122
|
+
return withTimeout(
|
|
123
|
+
() => withCircuitBreaker(circuitName, async () => {
|
|
124
|
+
return withRetry(operation, config.retry, context);
|
|
125
|
+
}),
|
|
126
|
+
timeoutMs,
|
|
127
|
+
`${toolName}:timeout`
|
|
128
|
+
);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Execute GitHub API call with resilience protection
|
|
133
|
+
*/
|
|
134
|
+
export async function withGitHubResilience<T>(
|
|
135
|
+
operation: () => Promise<T>,
|
|
136
|
+
toolName: string
|
|
137
|
+
): Promise<T> {
|
|
138
|
+
return withResilience('github', operation, { tool: toolName });
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Execute LSP call with resilience protection
|
|
143
|
+
*/
|
|
144
|
+
export async function withLspResilience<T>(
|
|
145
|
+
operation: () => Promise<T>,
|
|
146
|
+
toolName: string
|
|
147
|
+
): Promise<T> {
|
|
148
|
+
return withResilience('lsp', operation, { tool: toolName });
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Execute local tool call with resilience protection
|
|
153
|
+
*/
|
|
154
|
+
export async function withLocalResilience<T>(
|
|
155
|
+
operation: () => Promise<T>,
|
|
156
|
+
toolName: string
|
|
157
|
+
): Promise<T> {
|
|
158
|
+
return withResilience('local', operation, { tool: toolName });
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Execute package API call (npm/PyPI) with resilience protection
|
|
163
|
+
*/
|
|
164
|
+
export async function withPackageResilience<T>(
|
|
165
|
+
operation: () => Promise<T>,
|
|
166
|
+
toolName: string
|
|
167
|
+
): Promise<T> {
|
|
168
|
+
return withResilience('package', operation, { tool: toolName });
|
|
169
|
+
}
|
|
@@ -0,0 +1,495 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Research-specific response builders for octocode-research skill.
|
|
3
|
+
*
|
|
4
|
+
* Provides high-level response helpers that wrap the MCP role-based response API
|
|
5
|
+
* with research-specific patterns and formatting.
|
|
6
|
+
*
|
|
7
|
+
* NOTE: The MCP tools already provide rich reasoning context via:
|
|
8
|
+
* - mainResearchGoal, researchGoal, reasoning in each result
|
|
9
|
+
* - hasResultsStatusHints, emptyStatusHints, errorStatusHints for guidance
|
|
10
|
+
* - Dynamic per-tool hints based on context
|
|
11
|
+
*
|
|
12
|
+
* This module focuses on formatting and presentation, NOT duplicating reasoning.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import {
|
|
16
|
+
createRoleBasedResult,
|
|
17
|
+
QuickResult,
|
|
18
|
+
StatusEmoji,
|
|
19
|
+
} from 'octocode-mcp/public';
|
|
20
|
+
|
|
21
|
+
// CallToolResult type from MCP SDK (re-exported via octocode-mcp)
|
|
22
|
+
type CallToolResult = ReturnType<typeof createRoleBasedResult>;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Pagination info for paginated responses
|
|
26
|
+
*/
|
|
27
|
+
interface PaginationInfo {
|
|
28
|
+
page: number;
|
|
29
|
+
total: number;
|
|
30
|
+
hasMore: boolean;
|
|
31
|
+
perPage?: number;
|
|
32
|
+
totalItems?: number;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Detailed match location info (preserved from MCP response)
|
|
37
|
+
*/
|
|
38
|
+
interface MatchLocation {
|
|
39
|
+
line: number;
|
|
40
|
+
column?: number;
|
|
41
|
+
value?: string;
|
|
42
|
+
byteOffset?: number;
|
|
43
|
+
charOffset?: number;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* File match info for search results
|
|
48
|
+
*/
|
|
49
|
+
interface FileMatch {
|
|
50
|
+
path: string;
|
|
51
|
+
matches?: number;
|
|
52
|
+
line?: number;
|
|
53
|
+
preview?: string;
|
|
54
|
+
repo?: string;
|
|
55
|
+
/** All match locations - preserved from MCP for detailed analysis */
|
|
56
|
+
allMatches?: MatchLocation[];
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Research context from MCP response
|
|
61
|
+
*/
|
|
62
|
+
interface ResearchContext {
|
|
63
|
+
mainResearchGoal?: string;
|
|
64
|
+
researchGoal?: string;
|
|
65
|
+
reasoning?: string;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Research-specific response builders
|
|
70
|
+
*/
|
|
71
|
+
export const ResearchResponse = {
|
|
72
|
+
/**
|
|
73
|
+
* Search results with navigation hints
|
|
74
|
+
*/
|
|
75
|
+
searchResults(results: {
|
|
76
|
+
files: FileMatch[];
|
|
77
|
+
totalMatches: number;
|
|
78
|
+
pagination?: PaginationInfo;
|
|
79
|
+
searchPattern?: string;
|
|
80
|
+
isLocal?: boolean;
|
|
81
|
+
/** MCP workflow hints - passed through from tool response */
|
|
82
|
+
mcpHints?: string[];
|
|
83
|
+
/** Research context - preserved from the query */
|
|
84
|
+
research?: ResearchContext;
|
|
85
|
+
}): CallToolResult {
|
|
86
|
+
const { files, totalMatches, pagination, searchPattern, mcpHints = [] } = results;
|
|
87
|
+
|
|
88
|
+
// Build summary
|
|
89
|
+
const patternInfo = searchPattern ? ` for "${searchPattern}"` : '';
|
|
90
|
+
const summary =
|
|
91
|
+
files.length > 0
|
|
92
|
+
? `Found ${totalMatches} matches${patternInfo} in ${files.length} files:\n` +
|
|
93
|
+
files
|
|
94
|
+
.slice(0, 10)
|
|
95
|
+
.map(
|
|
96
|
+
f =>
|
|
97
|
+
`- ${f.repo ? `${f.repo}:` : ''}${f.path}${f.line ? ` (line ${f.line})` : ''}${f.matches ? ` [${f.matches} matches]` : ''}${typeof f.preview === 'string' && f.preview ? `\n "${f.preview.slice(0, 100)}${f.preview.length > 100 ? '...' : ''}"` : ''}`
|
|
98
|
+
)
|
|
99
|
+
.join('\n') +
|
|
100
|
+
(files.length > 10 ? `\n... and ${files.length - 10} more files` : '')
|
|
101
|
+
: `No matches found${patternInfo}`;
|
|
102
|
+
|
|
103
|
+
// Build hints - start with MCP hints, add pagination info
|
|
104
|
+
const hints: string[] = [...mcpHints];
|
|
105
|
+
if (files.length > 10) {
|
|
106
|
+
hints.push(`Showing 10 of ${files.length} files`);
|
|
107
|
+
}
|
|
108
|
+
if (pagination?.hasMore) {
|
|
109
|
+
hints.push(`Next page: page=${pagination.page + 1}`);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// Return appropriate response type
|
|
113
|
+
if (files.length === 0) {
|
|
114
|
+
// For empty results, MCP already provides relevant hints
|
|
115
|
+
const emptyHints = mcpHints.length > 0 ? mcpHints : [
|
|
116
|
+
'Try broader search terms',
|
|
117
|
+
'Check spelling and case sensitivity',
|
|
118
|
+
'Remove path filters to widen search',
|
|
119
|
+
];
|
|
120
|
+
return QuickResult.empty(summary, emptyHints);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
if (pagination) {
|
|
124
|
+
return QuickResult.paginated(summary, results, pagination, hints);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
return QuickResult.success(summary, results, hints);
|
|
128
|
+
},
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* File content with context
|
|
132
|
+
*/
|
|
133
|
+
fileContent(result: {
|
|
134
|
+
path: string;
|
|
135
|
+
content: string;
|
|
136
|
+
lines?: { start: number; end: number };
|
|
137
|
+
language?: string;
|
|
138
|
+
totalLines?: number;
|
|
139
|
+
isPartial?: boolean;
|
|
140
|
+
/** MCP workflow hints - passed through from tool response */
|
|
141
|
+
mcpHints?: string[];
|
|
142
|
+
/** Research context - preserved from the query */
|
|
143
|
+
research?: ResearchContext;
|
|
144
|
+
}): CallToolResult {
|
|
145
|
+
const { path, content, lines, language, totalLines, isPartial, mcpHints = [] } = result;
|
|
146
|
+
|
|
147
|
+
const lineInfo = lines ? ` (lines ${lines.start}-${lines.end})` : '';
|
|
148
|
+
const lang = language || detectLanguage(path);
|
|
149
|
+
|
|
150
|
+
// Format content with code fence
|
|
151
|
+
const formattedContent = `📄 ${path}${lineInfo}\n\n\`\`\`${lang}\n${content}\n\`\`\``;
|
|
152
|
+
|
|
153
|
+
// Build hints - start with MCP hints, add contextual info
|
|
154
|
+
const hints: string[] = [...mcpHints];
|
|
155
|
+
hints.push('Content retrieved successfully');
|
|
156
|
+
if (lines) {
|
|
157
|
+
hints.push(`Showing lines ${lines.start}-${lines.end}`);
|
|
158
|
+
}
|
|
159
|
+
if (totalLines && isPartial) {
|
|
160
|
+
hints.push(`File has ${totalLines} total lines`);
|
|
161
|
+
hints.push('Use startLine/endLine for specific ranges');
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
return createRoleBasedResult({
|
|
165
|
+
system: { hints },
|
|
166
|
+
assistant: { summary: formattedContent, format: 'markdown' },
|
|
167
|
+
user: { message: `Retrieved: ${path}`, emoji: StatusEmoji.file },
|
|
168
|
+
data: result,
|
|
169
|
+
});
|
|
170
|
+
},
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* LSP definition/reference/call hierarchy results
|
|
174
|
+
*/
|
|
175
|
+
lspResult(result: {
|
|
176
|
+
symbol: string;
|
|
177
|
+
locations: Array<{ uri: string; line: number; preview?: string }>;
|
|
178
|
+
type: 'definition' | 'references' | 'calls' | 'incoming' | 'outgoing';
|
|
179
|
+
/** MCP workflow hints - passed through from tool response */
|
|
180
|
+
mcpHints?: string[];
|
|
181
|
+
/** Research context - preserved from the query */
|
|
182
|
+
research?: ResearchContext;
|
|
183
|
+
}): CallToolResult {
|
|
184
|
+
const { symbol, locations, type, mcpHints = [] } = result;
|
|
185
|
+
|
|
186
|
+
const typeLabels: Record<string, string> = {
|
|
187
|
+
definition: 'Definition',
|
|
188
|
+
references: 'References',
|
|
189
|
+
calls: 'Call sites',
|
|
190
|
+
incoming: 'Incoming calls',
|
|
191
|
+
outgoing: 'Outgoing calls',
|
|
192
|
+
};
|
|
193
|
+
const typeEmojis: Record<string, string> = {
|
|
194
|
+
definition: StatusEmoji.definition,
|
|
195
|
+
references: StatusEmoji.reference,
|
|
196
|
+
calls: StatusEmoji.call,
|
|
197
|
+
incoming: '📥',
|
|
198
|
+
outgoing: '📤',
|
|
199
|
+
};
|
|
200
|
+
|
|
201
|
+
const typeLabel = typeLabels[type] || type;
|
|
202
|
+
const typeEmoji = typeEmojis[type] || StatusEmoji.info;
|
|
203
|
+
|
|
204
|
+
const summary =
|
|
205
|
+
locations.length > 0
|
|
206
|
+
? `${typeLabel} for "${symbol}":\n` +
|
|
207
|
+
locations
|
|
208
|
+
.map(
|
|
209
|
+
l =>
|
|
210
|
+
`- ${l.uri}:${l.line}${l.preview ? `\n ${l.preview}` : ''}`
|
|
211
|
+
)
|
|
212
|
+
.join('\n')
|
|
213
|
+
: `No ${type} found for "${symbol}"`;
|
|
214
|
+
|
|
215
|
+
// Build hints - start with MCP hints, add contextual info
|
|
216
|
+
const hints: string[] = [...mcpHints];
|
|
217
|
+
if (locations.length > 0) {
|
|
218
|
+
hints.push('Use returned line numbers for further navigation');
|
|
219
|
+
if (type === 'definition') hints.push('Use lspFindReferences to find all usages');
|
|
220
|
+
if (type === 'references') hints.push('Use lspCallHierarchy for call relationships');
|
|
221
|
+
} else if (mcpHints.length === 0) {
|
|
222
|
+
hints.push('Symbol may be external or unindexed');
|
|
223
|
+
hints.push('Try localSearchCode as fallback');
|
|
224
|
+
hints.push('Check if file is in workspace');
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
return createRoleBasedResult({
|
|
228
|
+
system: { hints },
|
|
229
|
+
assistant: { summary },
|
|
230
|
+
user: {
|
|
231
|
+
message: `${typeLabel}: ${locations.length} found`,
|
|
232
|
+
emoji: locations.length > 0 ? typeEmoji : StatusEmoji.empty,
|
|
233
|
+
},
|
|
234
|
+
data: result,
|
|
235
|
+
});
|
|
236
|
+
},
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* Repository structure view
|
|
240
|
+
*/
|
|
241
|
+
repoStructure(result: {
|
|
242
|
+
path: string;
|
|
243
|
+
structure: { files: string[]; folders: string[] };
|
|
244
|
+
depth?: number;
|
|
245
|
+
totalFiles?: number;
|
|
246
|
+
totalFolders?: number;
|
|
247
|
+
owner?: string;
|
|
248
|
+
repo?: string;
|
|
249
|
+
/** MCP workflow hints - passed through from tool response */
|
|
250
|
+
mcpHints?: string[];
|
|
251
|
+
/** Research context - preserved from the query */
|
|
252
|
+
research?: ResearchContext;
|
|
253
|
+
}): CallToolResult {
|
|
254
|
+
const { path, structure, depth, totalFiles, totalFolders, owner, repo, mcpHints = [] } =
|
|
255
|
+
result;
|
|
256
|
+
|
|
257
|
+
const repoInfo = owner && repo ? `${owner}/${repo}` : '';
|
|
258
|
+
const pathInfo = path || '/';
|
|
259
|
+
|
|
260
|
+
const fileList = structure.files.slice(0, 20);
|
|
261
|
+
const folderList = structure.folders.slice(0, 20);
|
|
262
|
+
|
|
263
|
+
const summary =
|
|
264
|
+
`📁 ${repoInfo ? `${repoInfo}:` : ''}${pathInfo}\n\n` +
|
|
265
|
+
(folderList.length > 0
|
|
266
|
+
? `Folders:\n${folderList.map(f => ` 📁 ${f}`).join('\n')}\n\n`
|
|
267
|
+
: '') +
|
|
268
|
+
(fileList.length > 0
|
|
269
|
+
? `Files:\n${fileList.map(f => ` 📄 ${f}`).join('\n')}`
|
|
270
|
+
: 'No files in this directory');
|
|
271
|
+
|
|
272
|
+
// Build hints - start with MCP hints, add contextual info
|
|
273
|
+
const hints: string[] = [...mcpHints];
|
|
274
|
+
if (depth === 1) {
|
|
275
|
+
hints.push('Use depth=2 to see nested contents');
|
|
276
|
+
}
|
|
277
|
+
if (structure.files.length > 20 || structure.folders.length > 20) {
|
|
278
|
+
hints.push('Results truncated - use path filter to narrow scope');
|
|
279
|
+
}
|
|
280
|
+
hints.push('Use localSearchCode or githubSearchCode to find specific files');
|
|
281
|
+
|
|
282
|
+
return createRoleBasedResult({
|
|
283
|
+
system: {
|
|
284
|
+
hints,
|
|
285
|
+
pagination:
|
|
286
|
+
totalFiles || totalFolders
|
|
287
|
+
? {
|
|
288
|
+
currentPage: 1,
|
|
289
|
+
totalPages: 1,
|
|
290
|
+
hasMore: false,
|
|
291
|
+
totalItems: (totalFiles || 0) + (totalFolders || 0),
|
|
292
|
+
}
|
|
293
|
+
: undefined,
|
|
294
|
+
},
|
|
295
|
+
assistant: { summary, format: 'markdown' },
|
|
296
|
+
user: {
|
|
297
|
+
message: `${structure.files.length} files, ${structure.folders.length} folders`,
|
|
298
|
+
emoji: StatusEmoji.folder,
|
|
299
|
+
},
|
|
300
|
+
data: result,
|
|
301
|
+
});
|
|
302
|
+
},
|
|
303
|
+
|
|
304
|
+
/**
|
|
305
|
+
* Package search results
|
|
306
|
+
*/
|
|
307
|
+
packageSearch(result: {
|
|
308
|
+
packages: Array<{
|
|
309
|
+
name: string;
|
|
310
|
+
version?: string;
|
|
311
|
+
description?: string;
|
|
312
|
+
repository?: string;
|
|
313
|
+
}>;
|
|
314
|
+
registry: 'npm' | 'pypi';
|
|
315
|
+
query?: string;
|
|
316
|
+
/** MCP workflow hints - passed through from tool response */
|
|
317
|
+
mcpHints?: string[];
|
|
318
|
+
/** Research context - preserved from the query */
|
|
319
|
+
research?: ResearchContext;
|
|
320
|
+
}): CallToolResult {
|
|
321
|
+
const { packages, registry, query, mcpHints = [] } = result;
|
|
322
|
+
|
|
323
|
+
const queryInfo = query ? ` for "${query}"` : '';
|
|
324
|
+
const summary =
|
|
325
|
+
packages.length > 0
|
|
326
|
+
? `Found ${packages.length} packages${queryInfo} on ${registry.toUpperCase()}:\n` +
|
|
327
|
+
packages
|
|
328
|
+
.slice(0, 10)
|
|
329
|
+
.map(
|
|
330
|
+
p =>
|
|
331
|
+
`- ${p.name}${p.version ? `@${p.version}` : ''}\n ${typeof p.description === 'string' ? p.description : 'No description'}${p.repository ? `\n ${p.repository}` : ''}`
|
|
332
|
+
)
|
|
333
|
+
.join('\n')
|
|
334
|
+
: `No packages found${queryInfo} on ${registry.toUpperCase()}`;
|
|
335
|
+
|
|
336
|
+
// Build hints - start with MCP hints, add contextual info
|
|
337
|
+
const hints: string[] = [...mcpHints];
|
|
338
|
+
if (packages.length > 0) {
|
|
339
|
+
hints.push('Use repository URL with githubViewRepoStructure to explore source');
|
|
340
|
+
hints.push('Use githubSearchCode to find usage examples');
|
|
341
|
+
} else if (mcpHints.length === 0) {
|
|
342
|
+
hints.push('Try different search terms');
|
|
343
|
+
hints.push('Check package name spelling');
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
if (packages.length === 0) {
|
|
347
|
+
return QuickResult.empty(summary, hints);
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
return QuickResult.success(summary, result, hints);
|
|
351
|
+
},
|
|
352
|
+
|
|
353
|
+
/**
|
|
354
|
+
* Pull request search results
|
|
355
|
+
*/
|
|
356
|
+
pullRequests(result: {
|
|
357
|
+
prs: Array<{
|
|
358
|
+
number: number;
|
|
359
|
+
title: string;
|
|
360
|
+
state: string;
|
|
361
|
+
author?: string;
|
|
362
|
+
url?: string;
|
|
363
|
+
}>;
|
|
364
|
+
repo?: string;
|
|
365
|
+
pagination?: PaginationInfo;
|
|
366
|
+
/** MCP workflow hints - passed through from tool response */
|
|
367
|
+
mcpHints?: string[];
|
|
368
|
+
/** Research context - preserved from the query */
|
|
369
|
+
research?: ResearchContext;
|
|
370
|
+
}): CallToolResult {
|
|
371
|
+
const { prs, repo, pagination, mcpHints = [] } = result;
|
|
372
|
+
|
|
373
|
+
const repoInfo = repo ? ` in ${repo}` : '';
|
|
374
|
+
const summary =
|
|
375
|
+
prs.length > 0
|
|
376
|
+
? `Found ${prs.length} pull requests${repoInfo}:\n` +
|
|
377
|
+
prs
|
|
378
|
+
.slice(0, 10)
|
|
379
|
+
.map(
|
|
380
|
+
pr =>
|
|
381
|
+
`- #${pr.number}: ${pr.title} [${pr.state}]${pr.author ? ` by @${pr.author}` : ''}`
|
|
382
|
+
)
|
|
383
|
+
.join('\n')
|
|
384
|
+
: `No pull requests found${repoInfo}`;
|
|
385
|
+
|
|
386
|
+
// Build hints - start with MCP hints, add contextual info
|
|
387
|
+
const hints: string[] = [...mcpHints];
|
|
388
|
+
if (prs.length > 0) {
|
|
389
|
+
hints.push('Use prNumber with type="fullContent" to see full diff');
|
|
390
|
+
hints.push('Use type="partialContent" with file filter for specific changes');
|
|
391
|
+
} else if (mcpHints.length === 0) {
|
|
392
|
+
hints.push('Try broader date range');
|
|
393
|
+
hints.push('Check repository name');
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
if (prs.length === 0) {
|
|
397
|
+
return QuickResult.empty(summary, hints);
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
if (pagination) {
|
|
401
|
+
return QuickResult.paginated(summary, result, pagination, hints);
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
return QuickResult.success(summary, result, hints);
|
|
405
|
+
},
|
|
406
|
+
|
|
407
|
+
/**
|
|
408
|
+
* Generic bulk operation result
|
|
409
|
+
*/
|
|
410
|
+
bulkResult(result: {
|
|
411
|
+
results: Array<{ status: string; data?: unknown; error?: string }>;
|
|
412
|
+
operation: string;
|
|
413
|
+
totalQueries: number;
|
|
414
|
+
}): CallToolResult {
|
|
415
|
+
const { results, operation, totalQueries } = result;
|
|
416
|
+
|
|
417
|
+
const successful = results.filter(r => r.status === 'success').length;
|
|
418
|
+
const failed = results.filter(r => r.status === 'error').length;
|
|
419
|
+
const empty = results.filter(r => r.status === 'empty').length;
|
|
420
|
+
|
|
421
|
+
const summary =
|
|
422
|
+
`Bulk ${operation} completed:\n` +
|
|
423
|
+
`- ✅ Success: ${successful}/${totalQueries}\n` +
|
|
424
|
+
(empty > 0 ? `- 📭 Empty: ${empty}/${totalQueries}\n` : '') +
|
|
425
|
+
(failed > 0 ? `- ❌ Failed: ${failed}/${totalQueries}` : '');
|
|
426
|
+
|
|
427
|
+
const hints: string[] = [];
|
|
428
|
+
if (failed > 0) {
|
|
429
|
+
hints.push('Check individual error messages for failed queries');
|
|
430
|
+
}
|
|
431
|
+
if (empty > 0) {
|
|
432
|
+
hints.push('Empty results may indicate no matches or invalid parameters');
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
const emoji =
|
|
436
|
+
failed === 0
|
|
437
|
+
? StatusEmoji.success
|
|
438
|
+
: failed === totalQueries
|
|
439
|
+
? StatusEmoji.error
|
|
440
|
+
: StatusEmoji.partial;
|
|
441
|
+
|
|
442
|
+
return createRoleBasedResult({
|
|
443
|
+
system: { hints },
|
|
444
|
+
assistant: { summary },
|
|
445
|
+
user: {
|
|
446
|
+
message: `${successful}/${totalQueries} queries succeeded`,
|
|
447
|
+
emoji,
|
|
448
|
+
},
|
|
449
|
+
data: result,
|
|
450
|
+
isError: failed === totalQueries,
|
|
451
|
+
});
|
|
452
|
+
},
|
|
453
|
+
};
|
|
454
|
+
|
|
455
|
+
/**
|
|
456
|
+
* Detect language from file extension
|
|
457
|
+
*/
|
|
458
|
+
function detectLanguage(path: string): string {
|
|
459
|
+
const ext = path.split('.').pop()?.toLowerCase() || '';
|
|
460
|
+
const langMap: Record<string, string> = {
|
|
461
|
+
ts: 'typescript',
|
|
462
|
+
tsx: 'typescript',
|
|
463
|
+
js: 'javascript',
|
|
464
|
+
jsx: 'javascript',
|
|
465
|
+
py: 'python',
|
|
466
|
+
rb: 'ruby',
|
|
467
|
+
go: 'go',
|
|
468
|
+
rs: 'rust',
|
|
469
|
+
java: 'java',
|
|
470
|
+
kt: 'kotlin',
|
|
471
|
+
swift: 'swift',
|
|
472
|
+
c: 'c',
|
|
473
|
+
cpp: 'cpp',
|
|
474
|
+
h: 'c',
|
|
475
|
+
hpp: 'cpp',
|
|
476
|
+
cs: 'csharp',
|
|
477
|
+
php: 'php',
|
|
478
|
+
sh: 'bash',
|
|
479
|
+
bash: 'bash',
|
|
480
|
+
zsh: 'bash',
|
|
481
|
+
yml: 'yaml',
|
|
482
|
+
yaml: 'yaml',
|
|
483
|
+
json: 'json',
|
|
484
|
+
md: 'markdown',
|
|
485
|
+
sql: 'sql',
|
|
486
|
+
html: 'html',
|
|
487
|
+
css: 'css',
|
|
488
|
+
scss: 'scss',
|
|
489
|
+
less: 'less',
|
|
490
|
+
};
|
|
491
|
+
return langMap[ext] || '';
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
// Re-export utilities for convenience
|
|
495
|
+
export { QuickResult, detectLanguage as detectLanguageFromPath };
|