github-to-mcp-monorepo 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +8 -0
- package/.github/CODEOWNERS +6 -0
- package/.husky/pre-commit +1 -0
- package/.nvmrc +1 -0
- package/.prettierignore +5 -0
- package/.prettierrc +7 -0
- package/.vscode/settings.json +4 -0
- package/ARCHITECTURE.md +1429 -0
- package/CHANGELOG.md +167 -0
- package/CONTRIBUTING.md +327 -0
- package/LICENSE +201 -0
- package/README.md +1028 -0
- package/SECURITY.md +248 -0
- package/VISUAL_GUIDE.md +437 -0
- package/apps/vscode/IMPLEMENTATION.md +480 -0
- package/apps/vscode/README.md +248 -0
- package/apps/vscode/package.json +381 -0
- package/apps/vscode/resources/icon.png +0 -0
- package/apps/vscode/resources/icon.svg +5 -0
- package/apps/vscode/src/commands/browseRegistry.ts +211 -0
- package/apps/vscode/src/commands/configureClaudeDesktop.ts +332 -0
- package/apps/vscode/src/commands/convert.ts +82 -0
- package/apps/vscode/src/commands/convertCurrentRepo.ts +109 -0
- package/apps/vscode/src/commands/convertFromUrl.ts +138 -0
- package/apps/vscode/src/commands/index.ts +121 -0
- package/apps/vscode/src/commands/validate.ts +197 -0
- package/apps/vscode/src/extension.ts +464 -0
- package/apps/vscode/src/global.d.ts +36 -0
- package/apps/vscode/src/test/extension.test.ts +73 -0
- package/apps/vscode/src/utils/file-generator.ts +529 -0
- package/apps/vscode/src/utils/github-api.ts +335 -0
- package/apps/vscode/src/utils/index.ts +29 -0
- package/apps/vscode/src/utils/mcp-config.ts +334 -0
- package/apps/vscode/src/utils/storage.ts +87 -0
- package/apps/vscode/src/views/McpServersTreeView.ts +160 -0
- package/apps/vscode/src/views/OutputChannelView.ts +195 -0
- package/apps/vscode/src/views/StatusBarItem.ts +251 -0
- package/apps/vscode/src/views/ToolsExplorerView.ts +314 -0
- package/apps/vscode/src/views/historyProvider.ts +75 -0
- package/apps/vscode/src/views/index.ts +12 -0
- package/apps/vscode/src/views/resultsPanel.ts +330 -0
- package/apps/vscode/src/webviews/ConversionPanel.ts +350 -0
- package/apps/vscode/src/webviews/ToolDetailsPanel.ts +448 -0
- package/apps/vscode/src/webviews/index.ts +9 -0
- package/apps/vscode/src/webviews/webview-ui/styles.ts +492 -0
- package/apps/vscode/tsconfig.json +20 -0
- package/apps/web/PLAYGROUND_GUIDE.md +499 -0
- package/apps/web/README.md +505 -0
- package/apps/web/app/api/convert/route.ts +100 -0
- package/apps/web/app/api/convert/stream/route.ts +198 -0
- package/apps/web/app/api/deploy/route.ts +157 -0
- package/apps/web/app/api/edge/route.ts +308 -0
- package/apps/web/app/api/export-docker/route.ts +284 -0
- package/apps/web/app/api/generate-openapi/route.ts +119 -0
- package/apps/web/app/api/mcp/[serverId]/route.ts +263 -0
- package/apps/web/app/api/playground/connect/route.ts +143 -0
- package/apps/web/app/api/playground/disconnect/route.ts +78 -0
- package/apps/web/app/api/playground/execute/route.ts +135 -0
- package/apps/web/app/api/playground/sessions/route.ts +103 -0
- package/apps/web/app/api/playground/tools/route.ts +117 -0
- package/apps/web/app/api/playground/v2/connect/route.ts +96 -0
- package/apps/web/app/api/playground/v2/disconnect/route.ts +88 -0
- package/apps/web/app/api/playground/v2/health/route.ts +80 -0
- package/apps/web/app/api/playground/v2/prompts/route.ts +160 -0
- package/apps/web/app/api/playground/v2/resources/route.ts +159 -0
- package/apps/web/app/api/playground/v2/sessions/route.ts +184 -0
- package/apps/web/app/api/playground/v2/tools/route.ts +167 -0
- package/apps/web/app/api/stream/route.ts +232 -0
- package/apps/web/app/batch/BatchConvertClient.tsx +190 -0
- package/apps/web/app/batch/page.tsx +37 -0
- package/apps/web/app/convert/page.tsx +269 -0
- package/apps/web/app/dashboard/page.tsx +380 -0
- package/apps/web/app/globals.css +622 -0
- package/apps/web/app/layout.tsx +120 -0
- package/apps/web/app/manifest.ts +31 -0
- package/apps/web/app/opengraph-image.tsx +112 -0
- package/apps/web/app/page.old.tsx +924 -0
- package/apps/web/app/page.tsx +77 -0
- package/apps/web/app/playground/page.tsx +306 -0
- package/apps/web/app/playground/v2/error.tsx +163 -0
- package/apps/web/app/playground/v2/layout.tsx +58 -0
- package/apps/web/app/playground/v2/loading.tsx +152 -0
- package/apps/web/app/playground/v2/page.tsx +644 -0
- package/apps/web/app/playground/v2/providers.tsx +214 -0
- package/apps/web/app/playground/v2/use-shortcuts.ts +209 -0
- package/apps/web/app/playground/v2/use-url-state.ts +296 -0
- package/apps/web/app/providers.tsx +22 -0
- package/apps/web/app/sitemap.ts +32 -0
- package/apps/web/app/twitter-image.tsx +112 -0
- package/apps/web/components/BranchSelector.tsx +401 -0
- package/apps/web/components/ClaudeConfigExport.tsx +226 -0
- package/apps/web/components/Features.tsx +84 -0
- package/apps/web/components/Footer.tsx +119 -0
- package/apps/web/components/GenerationProgress.tsx +248 -0
- package/apps/web/components/GithubUrlInput.tsx +483 -0
- package/apps/web/components/Header.tsx +175 -0
- package/apps/web/components/Hero.tsx +117 -0
- package/apps/web/components/HowItWorks.tsx +119 -0
- package/apps/web/components/InstallBanner.tsx +158 -0
- package/apps/web/components/Logo.tsx +116 -0
- package/apps/web/components/ParticleBackground.tsx +105 -0
- package/apps/web/components/Playground.tsx +472 -0
- package/apps/web/components/PlaygroundToolTester.tsx +410 -0
- package/apps/web/components/ProductCards.tsx +179 -0
- package/apps/web/components/SplitView.tsx +194 -0
- package/apps/web/components/ToolFilter.tsx +260 -0
- package/apps/web/components/ToolList.tsx +325 -0
- package/apps/web/components/batch/BatchConvert.tsx +785 -0
- package/apps/web/components/batch/index.ts +7 -0
- package/apps/web/components/convert/ConfigTabs.tsx +230 -0
- package/apps/web/components/convert/ConversionResult.tsx +482 -0
- package/apps/web/components/convert/InlinePlayground.tsx +259 -0
- package/apps/web/components/convert/LoadingSteps.tsx +311 -0
- package/apps/web/components/convert/OneClickInstall.tsx +224 -0
- package/apps/web/components/convert/ToolCard.tsx +189 -0
- package/apps/web/components/convert/TryInPlayground.tsx +242 -0
- package/apps/web/components/convert/index.ts +12 -0
- package/apps/web/components/deploy/DeployButton.tsx +369 -0
- package/apps/web/components/deploy/index.ts +7 -0
- package/apps/web/components/docker/DockerExport.tsx +690 -0
- package/apps/web/components/docker/index.ts +7 -0
- package/apps/web/components/install/OneClickInstall.tsx +676 -0
- package/apps/web/components/install/index.ts +7 -0
- package/apps/web/components/playground/CapabilityTabs.tsx +150 -0
- package/apps/web/components/playground/ConnectionStatusV2.tsx +322 -0
- package/apps/web/components/playground/EmptyStates.tsx +305 -0
- package/apps/web/components/playground/ExecutionLog.tsx +260 -0
- package/apps/web/components/playground/ExecutionLogV2.tsx +378 -0
- package/apps/web/components/playground/JsonViewer.tsx +388 -0
- package/apps/web/components/playground/PlaygroundLayout.tsx +244 -0
- package/apps/web/components/playground/PromptsPanel.tsx +385 -0
- package/apps/web/components/playground/ResourcesPanel.tsx +378 -0
- package/apps/web/components/playground/SchemaForm.tsx +477 -0
- package/apps/web/components/playground/ServerStatus.tsx +151 -0
- package/apps/web/components/playground/ShareButton.tsx +239 -0
- package/apps/web/components/playground/ToolsPanel.tsx +309 -0
- package/apps/web/components/playground/TransportConfigurator.tsx +563 -0
- package/apps/web/components/playground/index.ts +74 -0
- package/apps/web/components/playground/types.ts +202 -0
- package/apps/web/components/streaming/StreamingProgress.tsx +441 -0
- package/apps/web/components/streaming/index.ts +7 -0
- package/apps/web/components/ui/badge.tsx +42 -0
- package/apps/web/components/ui/button.tsx +88 -0
- package/apps/web/components/ui/card.tsx +75 -0
- package/apps/web/components/ui/code-block.tsx +122 -0
- package/apps/web/components/ui/index.ts +12 -0
- package/apps/web/components/ui/input.tsx +55 -0
- package/apps/web/components/ui/tabs.tsx +61 -0
- package/apps/web/hooks/index.ts +85 -0
- package/apps/web/hooks/types.ts +1173 -0
- package/apps/web/hooks/use-conversion.ts +133 -0
- package/apps/web/hooks/use-execution-history.ts +376 -0
- package/apps/web/hooks/use-generation-progress.ts +147 -0
- package/apps/web/hooks/use-local-storage.ts +88 -0
- package/apps/web/hooks/use-mcp-client.ts +623 -0
- package/apps/web/hooks/use-mcp-connection.ts +500 -0
- package/apps/web/hooks/use-mcp-execution.ts +282 -0
- package/apps/web/hooks/use-mcp-prompts.ts +441 -0
- package/apps/web/hooks/use-mcp-resources.ts +430 -0
- package/apps/web/hooks/use-mcp-tools.ts +540 -0
- package/apps/web/hooks/use-playground-store.ts +299 -0
- package/apps/web/hooks/use-playground.ts +184 -0
- package/apps/web/hooks/use-streaming-conversion.ts +227 -0
- package/apps/web/hooks/useBatchConversion.ts +271 -0
- package/apps/web/hooks/useDockerConfig.ts +161 -0
- package/apps/web/hooks/usePlatformDetection.ts +80 -0
- package/apps/web/hooks/useStreaming.ts +199 -0
- package/apps/web/lib/api/errors.ts +386 -0
- package/apps/web/lib/api/index.ts +137 -0
- package/apps/web/lib/api/logger.ts +187 -0
- package/apps/web/lib/api/middleware.ts +364 -0
- package/apps/web/lib/api/openapi.ts +977 -0
- package/apps/web/lib/api/session-manager.ts +594 -0
- package/apps/web/lib/api/types.ts +433 -0
- package/apps/web/lib/api/validation.ts +523 -0
- package/apps/web/lib/constants.ts +114 -0
- package/apps/web/lib/mcp/client.ts +1137 -0
- package/apps/web/lib/mcp/events.ts +651 -0
- package/apps/web/lib/mcp/index.ts +347 -0
- package/apps/web/lib/mcp/logger.ts +428 -0
- package/apps/web/lib/mcp/metrics.ts +703 -0
- package/apps/web/lib/mcp/retry.ts +616 -0
- package/apps/web/lib/mcp/session-manager.ts +779 -0
- package/apps/web/lib/mcp/transports.ts +988 -0
- package/apps/web/lib/mcp/types.ts +594 -0
- package/apps/web/lib/mcp-client-enhanced.ts +871 -0
- package/apps/web/lib/mcp-client.ts +778 -0
- package/apps/web/lib/mcp-errors.ts +489 -0
- package/apps/web/lib/mcp-sandbox.ts +593 -0
- package/apps/web/lib/mcp-testing.ts +428 -0
- package/apps/web/lib/mcp-types.ts +448 -0
- package/apps/web/lib/playground-store.tsx +1147 -0
- package/apps/web/lib/utils.ts +439 -0
- package/apps/web/next-env.d.ts +5 -0
- package/apps/web/next.config.js +23 -0
- package/apps/web/package.json +55 -0
- package/apps/web/postcss.config.js +6 -0
- package/apps/web/public/.well-known/ai-plugin.json +17 -0
- package/apps/web/public/logo.svg +6 -0
- package/apps/web/public/robots.txt +22 -0
- package/apps/web/public/schema.json +27 -0
- package/apps/web/tailwind.config.js +26 -0
- package/apps/web/tailwind.config.ts +123 -0
- package/apps/web/tsconfig.json +20 -0
- package/apps/web/types/deploy.ts +139 -0
- package/apps/web/types/index.ts +247 -0
- package/apps/web/vercel.json +39 -0
- package/eslint.config.mjs +23 -0
- package/llms.txt +102 -0
- package/mkdocs/docs/api/core.md +318 -0
- package/mkdocs/docs/api/index.md +128 -0
- package/mkdocs/docs/api/mcp-server.md +301 -0
- package/mkdocs/docs/api/openapi-parser.md +254 -0
- package/mkdocs/docs/assets/logo.svg +7 -0
- package/mkdocs/docs/changelog.md +118 -0
- package/mkdocs/docs/cli/generate.md +148 -0
- package/mkdocs/docs/cli/index.md +52 -0
- package/mkdocs/docs/cli/inspect.md +164 -0
- package/mkdocs/docs/cli/serve.md +136 -0
- package/mkdocs/docs/concepts/classification.md +254 -0
- package/mkdocs/docs/concepts/how-it-works.md +299 -0
- package/mkdocs/docs/concepts/index.md +77 -0
- package/mkdocs/docs/concepts/mcp-protocol.md +362 -0
- package/mkdocs/docs/concepts/tool-types.md +382 -0
- package/mkdocs/docs/contributing/architecture.md +262 -0
- package/mkdocs/docs/contributing/development.md +245 -0
- package/mkdocs/docs/contributing/index.md +73 -0
- package/mkdocs/docs/contributing/testing.md +320 -0
- package/mkdocs/docs/getting-started/configuration.md +235 -0
- package/mkdocs/docs/getting-started/index.md +54 -0
- package/mkdocs/docs/getting-started/installation.md +145 -0
- package/mkdocs/docs/getting-started/quickstart.md +160 -0
- package/mkdocs/docs/guides/batch.md +375 -0
- package/mkdocs/docs/guides/claude-desktop.md +227 -0
- package/mkdocs/docs/guides/cursor.md +188 -0
- package/mkdocs/docs/guides/custom-tools.md +367 -0
- package/mkdocs/docs/guides/index.md +78 -0
- package/mkdocs/docs/guides/private-repos.md +221 -0
- package/mkdocs/docs/guides/vscode.md +247 -0
- package/mkdocs/docs/index.md +175 -0
- package/mkdocs/docs/reference/config.md +223 -0
- package/mkdocs/docs/reference/env.md +192 -0
- package/mkdocs/docs/reference/index.md +102 -0
- package/mkdocs/docs/reference/tools.md +309 -0
- package/mkdocs/docs/stylesheets/extra.css +231 -0
- package/mkdocs/mkdocs.yml +204 -0
- package/mkdocs/overrides/.gitkeep +1 -0
- package/mkdocs/overrides/main.html +7 -0
- package/mkdocs/python-deps.txt +7 -0
- package/mkdocs/vercel.json +11 -0
- package/package.json +63 -0
- package/packages/core/package.json +61 -0
- package/packages/core/src/__tests__/bitbucket-client.test.ts +366 -0
- package/packages/core/src/__tests__/cli.test.ts +235 -0
- package/packages/core/src/__tests__/code-extractor.test.ts +378 -0
- package/packages/core/src/__tests__/docker-generator.test.ts +255 -0
- package/packages/core/src/__tests__/github-client.test.ts +390 -0
- package/packages/core/src/__tests__/gitlab-client.test.ts +319 -0
- package/packages/core/src/__tests__/go-extractor.test.ts +351 -0
- package/packages/core/src/__tests__/graphql-extractor.test.ts +330 -0
- package/packages/core/src/__tests__/java-extractor.test.ts +497 -0
- package/packages/core/src/__tests__/plugins.test.ts +467 -0
- package/packages/core/src/__tests__/readme-extractor.test.ts +258 -0
- package/packages/core/src/__tests__/redis-cache.test.ts +307 -0
- package/packages/core/src/__tests__/rust-extractor.test.ts +252 -0
- package/packages/core/src/__tests__/streaming.test.ts +251 -0
- package/packages/core/src/additional-extractors.ts +333 -0
- package/packages/core/src/cache/cache-interface.ts +179 -0
- package/packages/core/src/cache/index.ts +210 -0
- package/packages/core/src/cache/redis-cache.ts +291 -0
- package/packages/core/src/cache/upstash-cache.ts +379 -0
- package/packages/core/src/cache.ts +251 -0
- package/packages/core/src/cli.ts +822 -0
- package/packages/core/src/code-extractor.ts +696 -0
- package/packages/core/src/docker-generator.ts +470 -0
- package/packages/core/src/edge-compatible.ts +491 -0
- package/packages/core/src/extractors/go-extractor.ts +791 -0
- package/packages/core/src/extractors/index.ts +9 -0
- package/packages/core/src/extractors/java-extractor.ts +937 -0
- package/packages/core/src/extractors/rust-extractor.ts +744 -0
- package/packages/core/src/github-client.ts +319 -0
- package/packages/core/src/go-generator.ts +356 -0
- package/packages/core/src/graphql-extractor.ts +358 -0
- package/packages/core/src/index.ts +797 -0
- package/packages/core/src/langchain-exporter.ts +617 -0
- package/packages/core/src/language-parsers.ts +1114 -0
- package/packages/core/src/mcp-introspector.ts +279 -0
- package/packages/core/src/monorepo-detector.ts +378 -0
- package/packages/core/src/plugins/index.ts +370 -0
- package/packages/core/src/plugins/registry.ts +404 -0
- package/packages/core/src/plugins/types.ts +215 -0
- package/packages/core/src/providers/base-provider.ts +246 -0
- package/packages/core/src/providers/bitbucket-client.ts +464 -0
- package/packages/core/src/providers/gitlab-client.ts +388 -0
- package/packages/core/src/providers/index.ts +176 -0
- package/packages/core/src/python-generator.ts +260 -0
- package/packages/core/src/queue/index.ts +100 -0
- package/packages/core/src/queue/memory-queue.ts +445 -0
- package/packages/core/src/queue/redis-queue.ts +578 -0
- package/packages/core/src/queue/types.ts +251 -0
- package/packages/core/src/readme-extractor.ts +409 -0
- package/packages/core/src/schema-generator.ts +638 -0
- package/packages/core/src/streaming.ts +999 -0
- package/packages/core/src/types.ts +289 -0
- package/packages/core/tsconfig.json +9 -0
- package/packages/core/tsup.config.ts +25 -0
- package/packages/mcp-server/README.md +297 -0
- package/packages/mcp-server/package.json +55 -0
- package/packages/mcp-server/src/__tests__/mcp-server.test.ts +177 -0
- package/packages/mcp-server/src/__tests__/tools.test.ts +217 -0
- package/packages/mcp-server/src/index.ts +1206 -0
- package/packages/mcp-server/src/prompts/index.ts +601 -0
- package/packages/mcp-server/src/tools/export-docker.ts +362 -0
- package/packages/mcp-server/src/tools/generate-openapi.ts +162 -0
- package/packages/mcp-server/src/tools/monitor-mcp-server.ts +448 -0
- package/packages/mcp-server/src/tools/stream-convert.ts +398 -0
- package/packages/mcp-server/src/tools/test-mcp-tool.ts +531 -0
- package/packages/mcp-server/tsconfig.json +12 -0
- package/packages/mcp-server/tsup.config.ts +14 -0
- package/packages/openapi-parser/package-lock.json +3028 -0
- package/packages/openapi-parser/package.json +41 -0
- package/packages/openapi-parser/src/analyzer.ts +700 -0
- package/packages/openapi-parser/src/asyncapi-parser.ts +475 -0
- package/packages/openapi-parser/src/cli.ts +302 -0
- package/packages/openapi-parser/src/generator.ts +570 -0
- package/packages/openapi-parser/src/generators/express-analyzer.ts +649 -0
- package/packages/openapi-parser/src/generators/fastapi-analyzer.ts +960 -0
- package/packages/openapi-parser/src/generators/index.ts +200 -0
- package/packages/openapi-parser/src/generators/nextjs-analyzer.ts +768 -0
- package/packages/openapi-parser/src/generators/openapi-builder.ts +527 -0
- package/packages/openapi-parser/src/generators/types.ts +298 -0
- package/packages/openapi-parser/src/graphql-parser.ts +462 -0
- package/packages/openapi-parser/src/grpc-parser.ts +649 -0
- package/packages/openapi-parser/src/har-parser.ts +723 -0
- package/packages/openapi-parser/src/index.ts +635 -0
- package/packages/openapi-parser/src/insomnia-parser.ts +614 -0
- package/packages/openapi-parser/src/parser.ts +231 -0
- package/packages/openapi-parser/src/postman-parser.ts +611 -0
- package/packages/openapi-parser/src/ref-resolver.ts +313 -0
- package/packages/openapi-parser/src/transformer.ts +459 -0
- package/packages/openapi-parser/tests/generators/express.test.ts +209 -0
- package/packages/openapi-parser/tests/generators/fastapi.test.ts +236 -0
- package/packages/openapi-parser/tests/generators/nextjs.test.ts +273 -0
- package/packages/openapi-parser/tests/parsers.test.ts +847 -0
- package/packages/openapi-parser/tsconfig.json +9 -0
- package/packages/openapi-parser/tsup.config.ts +11 -0
- package/packages/registry/package.json +59 -0
- package/packages/registry/src/cli.ts +456 -0
- package/packages/registry/src/index.ts +44 -0
- package/packages/registry/src/popular/github.json +47 -0
- package/packages/registry/src/popular/index.ts +55 -0
- package/packages/registry/src/popular/linear.json +42 -0
- package/packages/registry/src/popular/notion.json +42 -0
- package/packages/registry/src/popular/openai.json +40 -0
- package/packages/registry/src/popular/resend.json +38 -0
- package/packages/registry/src/popular/slack.json +42 -0
- package/packages/registry/src/popular/stripe.json +163 -0
- package/packages/registry/src/popular/supabase.json +42 -0
- package/packages/registry/src/popular/twilio.json +40 -0
- package/packages/registry/src/popular/vercel.json +40 -0
- package/packages/registry/src/registry.ts +492 -0
- package/packages/registry/src/storage.ts +334 -0
- package/packages/registry/src/types.ts +275 -0
- package/packages/registry/src/updater.ts +208 -0
- package/packages/registry/tsconfig.json +10 -0
- package/packages/registry/tsup.config.ts +11 -0
- package/pnpm-workspace.yaml +3 -0
- package/scripts/build-docs.sh +16 -0
- package/server.json +9 -0
- package/templates/Dockerfile.python.template +60 -0
- package/templates/Dockerfile.typescript.template +60 -0
- package/templates/docker-compose.template.yml +68 -0
- package/tests/fixtures/express-app/index.js +34 -0
- package/tests/fixtures/express-app/routes/posts.js +43 -0
- package/tests/fixtures/express-app/routes/users.js +58 -0
- package/tests/fixtures/fastapi-app/main.py +125 -0
- package/tests/fixtures/fastapi-app/routes/admin.py +42 -0
- package/tests/fixtures/graphql/simple-schema.graphql +65 -0
- package/tests/fixtures/mocks/github-api-responses.json +63 -0
- package/tests/fixtures/nextjs-app/app/api/posts/route.ts +55 -0
- package/tests/fixtures/nextjs-app/app/api/users/[id]/route.ts +63 -0
- package/tests/fixtures/nextjs-app/app/api/users/route.ts +44 -0
- package/tests/fixtures/nextjs-app/pages/api/health.ts +28 -0
- package/tests/fixtures/openapi/petstore.yaml +179 -0
- package/tests/integration/langchain-export.test.ts +405 -0
- package/tests/integration/openapi-conversion.test.ts +221 -0
- package/tsconfig.json +18 -0
- package/vitest.config.ts +32 -0
|
@@ -0,0 +1,791 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Go code extractor for extracting tools from Go codebases
|
|
3
|
+
* @copyright Copyright (c) 2024-2026 nirholas
|
|
4
|
+
* @license MIT
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { ExtractedTool, ParsedDocumentation } from '../types';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Extracted Go function information
|
|
11
|
+
*/
|
|
12
|
+
interface GoFunction {
|
|
13
|
+
name: string;
|
|
14
|
+
receiver?: {
|
|
15
|
+
name: string;
|
|
16
|
+
type: string;
|
|
17
|
+
isPointer: boolean;
|
|
18
|
+
};
|
|
19
|
+
params: Array<{
|
|
20
|
+
name: string;
|
|
21
|
+
type: string;
|
|
22
|
+
}>;
|
|
23
|
+
returns: Array<{
|
|
24
|
+
name?: string;
|
|
25
|
+
type: string;
|
|
26
|
+
}>;
|
|
27
|
+
documentation: ParsedDocumentation | null;
|
|
28
|
+
line: number;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Go route handler info
|
|
33
|
+
*/
|
|
34
|
+
interface GoRouteHandler {
|
|
35
|
+
method: string;
|
|
36
|
+
path: string;
|
|
37
|
+
handler: string;
|
|
38
|
+
framework: 'gin' | 'echo' | 'chi' | 'gorilla' | 'fiber' | 'net/http';
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* GoExtractor extracts tools from Go codebases
|
|
43
|
+
* Supports:
|
|
44
|
+
* - Gin routes
|
|
45
|
+
* - Echo routes
|
|
46
|
+
* - Chi routes
|
|
47
|
+
* - Gorilla mux routes
|
|
48
|
+
* - Fiber routes
|
|
49
|
+
* - net/http handlers
|
|
50
|
+
* - Public functions with doc comments
|
|
51
|
+
*/
|
|
52
|
+
export class GoExtractor {
|
|
53
|
+
/**
|
|
54
|
+
* Extract tools from Go code
|
|
55
|
+
*/
|
|
56
|
+
async extract(code: string, filename: string): Promise<ExtractedTool[]> {
|
|
57
|
+
const tools: ExtractedTool[] = [];
|
|
58
|
+
|
|
59
|
+
// Extract from web framework routes
|
|
60
|
+
const ginTools = this.extractGinRoutes(code, filename);
|
|
61
|
+
const echoTools = this.extractEchoRoutes(code, filename);
|
|
62
|
+
const chiTools = this.extractChiRoutes(code, filename);
|
|
63
|
+
const gorillaTools = this.extractGorillaRoutes(code, filename);
|
|
64
|
+
const fiberTools = this.extractFiberRoutes(code, filename);
|
|
65
|
+
const httpTools = this.extractNetHttpHandlers(code, filename);
|
|
66
|
+
|
|
67
|
+
tools.push(...ginTools, ...echoTools, ...chiTools, ...gorillaTools, ...fiberTools, ...httpTools);
|
|
68
|
+
|
|
69
|
+
// Extract from exported functions with documentation
|
|
70
|
+
const exportedFunctions = this.extractExportedFunctions(code, filename);
|
|
71
|
+
tools.push(...exportedFunctions);
|
|
72
|
+
|
|
73
|
+
return tools;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Extract Gin framework routes
|
|
78
|
+
* Patterns:
|
|
79
|
+
* - r.GET("/path", handler)
|
|
80
|
+
* - router.POST("/path", handler)
|
|
81
|
+
* - group.PUT("/path", handler)
|
|
82
|
+
*/
|
|
83
|
+
private extractGinRoutes(code: string, filename: string): ExtractedTool[] {
|
|
84
|
+
const tools: ExtractedTool[] = [];
|
|
85
|
+
|
|
86
|
+
// Pattern for Gin routes
|
|
87
|
+
const routePattern = /(\w+)\.(GET|POST|PUT|DELETE|PATCH|HEAD|OPTIONS)\s*\(\s*"([^"]+)"\s*,\s*(\w+(?:\.\w+)?)/gi;
|
|
88
|
+
|
|
89
|
+
let match;
|
|
90
|
+
while ((match = routePattern.exec(code)) !== null) {
|
|
91
|
+
const [, , method, path, handler] = match;
|
|
92
|
+
const lineNum = code.substring(0, match.index).split('\n').length;
|
|
93
|
+
|
|
94
|
+
// Try to find the handler function
|
|
95
|
+
const funcInfo = this.findFunctionByName(code, handler);
|
|
96
|
+
|
|
97
|
+
tools.push({
|
|
98
|
+
name: this.generateToolName(method, path, handler),
|
|
99
|
+
description: funcInfo?.documentation?.description || `${method} ${path}`,
|
|
100
|
+
inputSchema: this.buildGinInputSchema(funcInfo, path),
|
|
101
|
+
source: {
|
|
102
|
+
type: 'code',
|
|
103
|
+
file: filename,
|
|
104
|
+
line: lineNum
|
|
105
|
+
},
|
|
106
|
+
confidence: 0.8
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Also check for gin.H response patterns to infer response types
|
|
111
|
+
// r.JSON(200, gin.H{"message": "success"})
|
|
112
|
+
|
|
113
|
+
return tools;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Extract Echo framework routes
|
|
118
|
+
* Patterns:
|
|
119
|
+
* - e.GET("/path", handler)
|
|
120
|
+
* - g.POST("/path", handler)
|
|
121
|
+
*/
|
|
122
|
+
private extractEchoRoutes(code: string, filename: string): ExtractedTool[] {
|
|
123
|
+
const tools: ExtractedTool[] = [];
|
|
124
|
+
|
|
125
|
+
// Echo uses similar syntax to Gin
|
|
126
|
+
const routePattern = /(\w+)\.(GET|POST|PUT|DELETE|PATCH|HEAD|OPTIONS)\s*\(\s*"([^"]+)"\s*,\s*(\w+(?:\.\w+)?)/gi;
|
|
127
|
+
|
|
128
|
+
// Check if this is an Echo project
|
|
129
|
+
if (!code.includes('echo.') && !code.includes('"github.com/labstack/echo')) {
|
|
130
|
+
return tools;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
let match;
|
|
134
|
+
while ((match = routePattern.exec(code)) !== null) {
|
|
135
|
+
const [, , method, path, handler] = match;
|
|
136
|
+
const lineNum = code.substring(0, match.index).split('\n').length;
|
|
137
|
+
|
|
138
|
+
const funcInfo = this.findFunctionByName(code, handler);
|
|
139
|
+
|
|
140
|
+
tools.push({
|
|
141
|
+
name: this.generateToolName(method, path, handler),
|
|
142
|
+
description: funcInfo?.documentation?.description || `${method} ${path}`,
|
|
143
|
+
inputSchema: this.buildEchoInputSchema(funcInfo, path),
|
|
144
|
+
source: {
|
|
145
|
+
type: 'code',
|
|
146
|
+
file: filename,
|
|
147
|
+
line: lineNum
|
|
148
|
+
},
|
|
149
|
+
confidence: 0.8
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
return tools;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Extract Chi router routes
|
|
158
|
+
* Patterns:
|
|
159
|
+
* - r.Get("/path", handler)
|
|
160
|
+
* - r.Post("/path", handler)
|
|
161
|
+
* - r.Route("/path", func(r chi.Router) {...})
|
|
162
|
+
*/
|
|
163
|
+
private extractChiRoutes(code: string, filename: string): ExtractedTool[] {
|
|
164
|
+
const tools: ExtractedTool[] = [];
|
|
165
|
+
|
|
166
|
+
// Check if this is a Chi project (handle chi/v5 and older versions)
|
|
167
|
+
if (!code.includes('chi.') && !code.includes('go-chi/chi')) {
|
|
168
|
+
return tools;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// Chi uses PascalCase methods
|
|
172
|
+
const routePattern = /(\w+)\.(Get|Post|Put|Delete|Patch|Head|Options)\s*\(\s*"([^"]+)"\s*,\s*(\w+(?:\.\w+)?)/gi;
|
|
173
|
+
|
|
174
|
+
let match;
|
|
175
|
+
while ((match = routePattern.exec(code)) !== null) {
|
|
176
|
+
const [, , method, path, handler] = match;
|
|
177
|
+
const lineNum = code.substring(0, match.index).split('\n').length;
|
|
178
|
+
|
|
179
|
+
const funcInfo = this.findFunctionByName(code, handler);
|
|
180
|
+
|
|
181
|
+
tools.push({
|
|
182
|
+
name: this.generateToolName(method.toUpperCase(), path, handler),
|
|
183
|
+
description: funcInfo?.documentation?.description || `${method.toUpperCase()} ${path}`,
|
|
184
|
+
inputSchema: this.buildChiInputSchema(funcInfo, path),
|
|
185
|
+
source: {
|
|
186
|
+
type: 'code',
|
|
187
|
+
file: filename,
|
|
188
|
+
line: lineNum
|
|
189
|
+
},
|
|
190
|
+
confidence: 0.8
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
return tools;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Extract Gorilla mux routes
|
|
199
|
+
* Patterns:
|
|
200
|
+
* - r.HandleFunc("/path", handler).Methods("GET")
|
|
201
|
+
* - r.HandleFunc("/path", handler).Methods("GET", "POST")
|
|
202
|
+
*/
|
|
203
|
+
private extractGorillaRoutes(code: string, filename: string): ExtractedTool[] {
|
|
204
|
+
const tools: ExtractedTool[] = [];
|
|
205
|
+
|
|
206
|
+
// Check if this is a Gorilla project
|
|
207
|
+
if (!code.includes('mux.') && !code.includes('"github.com/gorilla/mux')) {
|
|
208
|
+
return tools;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// Gorilla HandleFunc pattern
|
|
212
|
+
const routePattern = /(\w+)\.HandleFunc\s*\(\s*"([^"]+)"\s*,\s*(\w+(?:\.\w+)?)\s*\)(?:\.Methods\s*\(\s*"([^"]+)")?/gi;
|
|
213
|
+
|
|
214
|
+
let match;
|
|
215
|
+
while ((match = routePattern.exec(code)) !== null) {
|
|
216
|
+
const [, , path, handler, method] = match;
|
|
217
|
+
const lineNum = code.substring(0, match.index).split('\n').length;
|
|
218
|
+
const httpMethod = method?.toUpperCase() || 'GET';
|
|
219
|
+
|
|
220
|
+
const funcInfo = this.findFunctionByName(code, handler);
|
|
221
|
+
|
|
222
|
+
tools.push({
|
|
223
|
+
name: this.generateToolName(httpMethod, path, handler),
|
|
224
|
+
description: funcInfo?.documentation?.description || `${httpMethod} ${path}`,
|
|
225
|
+
inputSchema: this.buildHttpInputSchema(funcInfo, path),
|
|
226
|
+
source: {
|
|
227
|
+
type: 'code',
|
|
228
|
+
file: filename,
|
|
229
|
+
line: lineNum
|
|
230
|
+
},
|
|
231
|
+
confidence: 0.7
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
return tools;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* Extract Fiber framework routes
|
|
240
|
+
* Patterns:
|
|
241
|
+
* - app.Get("/path", handler)
|
|
242
|
+
* - api.Post("/path", handler)
|
|
243
|
+
*/
|
|
244
|
+
private extractFiberRoutes(code: string, filename: string): ExtractedTool[] {
|
|
245
|
+
const tools: ExtractedTool[] = [];
|
|
246
|
+
|
|
247
|
+
// Check if this is a Fiber project
|
|
248
|
+
if (!code.includes('fiber.') && !code.includes('"github.com/gofiber/fiber')) {
|
|
249
|
+
return tools;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
// Fiber uses PascalCase methods
|
|
253
|
+
const routePattern = /(\w+)\.(Get|Post|Put|Delete|Patch|Head|Options)\s*\(\s*"([^"]+)"\s*,\s*(\w+(?:\.\w+)?)/gi;
|
|
254
|
+
|
|
255
|
+
let match;
|
|
256
|
+
while ((match = routePattern.exec(code)) !== null) {
|
|
257
|
+
const [, , method, path, handler] = match;
|
|
258
|
+
const lineNum = code.substring(0, match.index).split('\n').length;
|
|
259
|
+
|
|
260
|
+
const funcInfo = this.findFunctionByName(code, handler);
|
|
261
|
+
|
|
262
|
+
tools.push({
|
|
263
|
+
name: this.generateToolName(method.toUpperCase(), path, handler),
|
|
264
|
+
description: funcInfo?.documentation?.description || `${method.toUpperCase()} ${path}`,
|
|
265
|
+
inputSchema: this.buildFiberInputSchema(funcInfo, path),
|
|
266
|
+
source: {
|
|
267
|
+
type: 'code',
|
|
268
|
+
file: filename,
|
|
269
|
+
line: lineNum
|
|
270
|
+
},
|
|
271
|
+
confidence: 0.8
|
|
272
|
+
});
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
return tools;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* Extract net/http handlers
|
|
280
|
+
* Patterns:
|
|
281
|
+
* - http.HandleFunc("/path", handler)
|
|
282
|
+
* - mux.Handle("/path", handler)
|
|
283
|
+
*/
|
|
284
|
+
private extractNetHttpHandlers(code: string, filename: string): ExtractedTool[] {
|
|
285
|
+
const tools: ExtractedTool[] = [];
|
|
286
|
+
|
|
287
|
+
// http.HandleFunc pattern
|
|
288
|
+
const handleFuncPattern = /http\.HandleFunc\s*\(\s*"([^"]+)"\s*,\s*(\w+(?:\.\w+)?)/gi;
|
|
289
|
+
|
|
290
|
+
let match;
|
|
291
|
+
while ((match = handleFuncPattern.exec(code)) !== null) {
|
|
292
|
+
const [, path, handler] = match;
|
|
293
|
+
const lineNum = code.substring(0, match.index).split('\n').length;
|
|
294
|
+
|
|
295
|
+
const funcInfo = this.findFunctionByName(code, handler);
|
|
296
|
+
|
|
297
|
+
tools.push({
|
|
298
|
+
name: this.generateToolName('ANY', path, handler),
|
|
299
|
+
description: funcInfo?.documentation?.description || `HTTP handler: ${path}`,
|
|
300
|
+
inputSchema: this.buildHttpInputSchema(funcInfo, path),
|
|
301
|
+
source: {
|
|
302
|
+
type: 'code',
|
|
303
|
+
file: filename,
|
|
304
|
+
line: lineNum
|
|
305
|
+
},
|
|
306
|
+
confidence: 0.6
|
|
307
|
+
});
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
return tools;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
/**
|
|
314
|
+
* Extract exported functions with documentation
|
|
315
|
+
*/
|
|
316
|
+
private extractExportedFunctions(code: string, filename: string): ExtractedTool[] {
|
|
317
|
+
const tools: ExtractedTool[] = [];
|
|
318
|
+
const lines = code.split('\n');
|
|
319
|
+
|
|
320
|
+
for (let i = 0; i < lines.length; i++) {
|
|
321
|
+
const line = lines[i];
|
|
322
|
+
|
|
323
|
+
// Go exported functions start with uppercase letter
|
|
324
|
+
if (/^\s*func\s+(?:\([^)]+\)\s+)?[A-Z]\w*\s*\(/.test(line)) {
|
|
325
|
+
// Check if this is a handler function (already processed)
|
|
326
|
+
const funcInfo = this.parseFunction(lines, i);
|
|
327
|
+
|
|
328
|
+
if (funcInfo && funcInfo.documentation && !this.isHttpHandler(funcInfo)) {
|
|
329
|
+
tools.push({
|
|
330
|
+
name: funcInfo.name,
|
|
331
|
+
description: funcInfo.documentation.description || funcInfo.name,
|
|
332
|
+
inputSchema: this.buildFunctionInputSchema(funcInfo),
|
|
333
|
+
source: {
|
|
334
|
+
type: 'code',
|
|
335
|
+
file: filename,
|
|
336
|
+
line: i + 1
|
|
337
|
+
},
|
|
338
|
+
confidence: 0.6,
|
|
339
|
+
confidenceFactors: {
|
|
340
|
+
documentation: 0.8,
|
|
341
|
+
types: 0.9,
|
|
342
|
+
examples: funcInfo.documentation.examples?.length ? 0.7 : 0.2,
|
|
343
|
+
source: 0.7
|
|
344
|
+
}
|
|
345
|
+
});
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
return tools;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
/**
|
|
354
|
+
* Find a function by name
|
|
355
|
+
*/
|
|
356
|
+
private findFunctionByName(code: string, name: string): GoFunction | null {
|
|
357
|
+
const lines = code.split('\n');
|
|
358
|
+
|
|
359
|
+
// Handle method notation (e.g., "ctrl.Handler")
|
|
360
|
+
const funcName = name.includes('.') ? name.split('.').pop()! : name;
|
|
361
|
+
|
|
362
|
+
const pattern = new RegExp(`^\\s*func\\s+(?:\\([^)]+\\)\\s+)?${funcName}\\s*\\(`);
|
|
363
|
+
|
|
364
|
+
for (let i = 0; i < lines.length; i++) {
|
|
365
|
+
if (pattern.test(lines[i])) {
|
|
366
|
+
return this.parseFunction(lines, i);
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
return null;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
/**
|
|
373
|
+
* Parse a Go function definition
|
|
374
|
+
*/
|
|
375
|
+
private parseFunction(lines: string[], lineIndex: number): GoFunction | null {
|
|
376
|
+
const line = lines[lineIndex];
|
|
377
|
+
|
|
378
|
+
// Match function signature
|
|
379
|
+
// func Name(params) (returns)
|
|
380
|
+
// func (r *Receiver) Name(params) (returns)
|
|
381
|
+
const funcMatch = line.match(/^\s*func\s+(?:\((\w+)\s+(\*?)(\w+)\)\s+)?(\w+)\s*\(([^)]*)\)(?:\s*\(([^)]+)\)|\s*(\w+))?/);
|
|
382
|
+
|
|
383
|
+
if (!funcMatch) return null;
|
|
384
|
+
|
|
385
|
+
const [, receiverName, isPointer, receiverType, name, paramsStr, multiReturns, singleReturn] = funcMatch;
|
|
386
|
+
|
|
387
|
+
// Parse receiver if present
|
|
388
|
+
const receiver = receiverName ? {
|
|
389
|
+
name: receiverName,
|
|
390
|
+
type: receiverType,
|
|
391
|
+
isPointer: isPointer === '*'
|
|
392
|
+
} : undefined;
|
|
393
|
+
|
|
394
|
+
// Parse parameters
|
|
395
|
+
const params = this.parseParameters(paramsStr);
|
|
396
|
+
|
|
397
|
+
// Parse return types
|
|
398
|
+
const returns = this.parseReturns(multiReturns || singleReturn || '');
|
|
399
|
+
|
|
400
|
+
// Look for doc comments
|
|
401
|
+
const documentation = this.parseDocComments(lines, lineIndex);
|
|
402
|
+
|
|
403
|
+
return {
|
|
404
|
+
name,
|
|
405
|
+
receiver,
|
|
406
|
+
params,
|
|
407
|
+
returns,
|
|
408
|
+
documentation,
|
|
409
|
+
line: lineIndex + 1
|
|
410
|
+
};
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
/**
|
|
414
|
+
* Parse function parameters
|
|
415
|
+
*/
|
|
416
|
+
private parseParameters(paramsStr: string): GoFunction['params'] {
|
|
417
|
+
const params: GoFunction['params'] = [];
|
|
418
|
+
if (!paramsStr.trim()) return params;
|
|
419
|
+
|
|
420
|
+
// Split by comma, handling complex types
|
|
421
|
+
const paramParts = this.splitParams(paramsStr);
|
|
422
|
+
|
|
423
|
+
// Go allows grouping params with same type: a, b int
|
|
424
|
+
let lastType = '';
|
|
425
|
+
const parsedParams: Array<{ names: string[]; type: string }> = [];
|
|
426
|
+
|
|
427
|
+
for (const part of paramParts) {
|
|
428
|
+
const trimmed = part.trim();
|
|
429
|
+
if (!trimmed) continue;
|
|
430
|
+
|
|
431
|
+
// Check if this part has a type
|
|
432
|
+
const match = trimmed.match(/^([\w,\s]+)\s+(.+)$/);
|
|
433
|
+
|
|
434
|
+
if (match) {
|
|
435
|
+
const names = match[1].split(',').map(n => n.trim()).filter(Boolean);
|
|
436
|
+
const type = match[2].trim();
|
|
437
|
+
parsedParams.push({ names, type });
|
|
438
|
+
lastType = type;
|
|
439
|
+
} else {
|
|
440
|
+
// This might be a name without type (uses next param's type)
|
|
441
|
+
parsedParams.push({ names: [trimmed], type: '' });
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
// Fill in missing types (Go allows a, b int syntax)
|
|
446
|
+
for (let i = parsedParams.length - 1; i >= 0; i--) {
|
|
447
|
+
if (parsedParams[i].type === '' && i < parsedParams.length - 1) {
|
|
448
|
+
parsedParams[i].type = parsedParams[i + 1].type;
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
// Flatten into params array
|
|
453
|
+
for (const p of parsedParams) {
|
|
454
|
+
for (const name of p.names) {
|
|
455
|
+
if (name && p.type) {
|
|
456
|
+
params.push({ name, type: p.type });
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
return params;
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
/**
|
|
465
|
+
* Split parameters handling nested types
|
|
466
|
+
*/
|
|
467
|
+
private splitParams(paramsStr: string): string[] {
|
|
468
|
+
const params: string[] = [];
|
|
469
|
+
let current = '';
|
|
470
|
+
let depth = 0;
|
|
471
|
+
|
|
472
|
+
for (const char of paramsStr) {
|
|
473
|
+
if (char === '<' || char === '(' || char === '[' || char === '{') {
|
|
474
|
+
depth++;
|
|
475
|
+
current += char;
|
|
476
|
+
} else if (char === '>' || char === ')' || char === ']' || char === '}') {
|
|
477
|
+
depth--;
|
|
478
|
+
current += char;
|
|
479
|
+
} else if (char === ',' && depth === 0) {
|
|
480
|
+
params.push(current.trim());
|
|
481
|
+
current = '';
|
|
482
|
+
} else {
|
|
483
|
+
current += char;
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
if (current.trim()) {
|
|
488
|
+
params.push(current.trim());
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
return params;
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
/**
|
|
495
|
+
* Parse return types
|
|
496
|
+
*/
|
|
497
|
+
private parseReturns(returnsStr: string): GoFunction['returns'] {
|
|
498
|
+
const returns: GoFunction['returns'] = [];
|
|
499
|
+
if (!returnsStr.trim()) return returns;
|
|
500
|
+
|
|
501
|
+
const parts = this.splitParams(returnsStr);
|
|
502
|
+
|
|
503
|
+
for (const part of parts) {
|
|
504
|
+
const trimmed = part.trim();
|
|
505
|
+
if (!trimmed) continue;
|
|
506
|
+
|
|
507
|
+
// Check for named return: name Type
|
|
508
|
+
const namedMatch = trimmed.match(/^(\w+)\s+(.+)$/);
|
|
509
|
+
if (namedMatch) {
|
|
510
|
+
returns.push({ name: namedMatch[1], type: namedMatch[2] });
|
|
511
|
+
} else {
|
|
512
|
+
returns.push({ type: trimmed });
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
return returns;
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
/**
|
|
520
|
+
* Parse doc comments
|
|
521
|
+
*/
|
|
522
|
+
private parseDocComments(lines: string[], funcLineIndex: number): ParsedDocumentation | null {
|
|
523
|
+
const docLines: string[] = [];
|
|
524
|
+
let i = funcLineIndex - 1;
|
|
525
|
+
|
|
526
|
+
while (i >= 0) {
|
|
527
|
+
const line = lines[i].trim();
|
|
528
|
+
if (line.startsWith('//')) {
|
|
529
|
+
docLines.unshift(line.substring(2).trim());
|
|
530
|
+
i--;
|
|
531
|
+
} else if (line === '') {
|
|
532
|
+
// Allow one blank line
|
|
533
|
+
if (i > 0 && lines[i - 1].trim().startsWith('//')) {
|
|
534
|
+
i--;
|
|
535
|
+
} else {
|
|
536
|
+
break;
|
|
537
|
+
}
|
|
538
|
+
} else {
|
|
539
|
+
break;
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
if (docLines.length === 0) return null;
|
|
544
|
+
|
|
545
|
+
return this.parseDocumentation(docLines);
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
/**
|
|
549
|
+
* Parse documentation content
|
|
550
|
+
*/
|
|
551
|
+
private parseDocumentation(docLines: string[]): ParsedDocumentation {
|
|
552
|
+
const doc: ParsedDocumentation = {
|
|
553
|
+
params: [],
|
|
554
|
+
examples: []
|
|
555
|
+
};
|
|
556
|
+
|
|
557
|
+
let description = '';
|
|
558
|
+
|
|
559
|
+
for (const line of docLines) {
|
|
560
|
+
// Go doc doesn't have formal param syntax, but we can detect patterns
|
|
561
|
+
// @param name description (if someone uses it)
|
|
562
|
+
const paramMatch = line.match(/^@param\s+(\w+)\s+(.+)/i);
|
|
563
|
+
if (paramMatch) {
|
|
564
|
+
doc.params.push({
|
|
565
|
+
name: paramMatch[1],
|
|
566
|
+
description: paramMatch[2]
|
|
567
|
+
});
|
|
568
|
+
continue;
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
// Example: line detection
|
|
572
|
+
if (line.toLowerCase().startsWith('example:')) {
|
|
573
|
+
doc.examples!.push(line.substring(8).trim());
|
|
574
|
+
continue;
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
description += (description ? ' ' : '') + line;
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
doc.description = description.trim() || undefined;
|
|
581
|
+
return doc;
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
/**
|
|
585
|
+
* Check if function is an HTTP handler
|
|
586
|
+
*/
|
|
587
|
+
private isHttpHandler(funcInfo: GoFunction): boolean {
|
|
588
|
+
// HTTP handlers typically have specific parameter patterns
|
|
589
|
+
const handlerParams = [
|
|
590
|
+
'http.ResponseWriter',
|
|
591
|
+
'*http.Request',
|
|
592
|
+
'*gin.Context',
|
|
593
|
+
'echo.Context',
|
|
594
|
+
'*fiber.Ctx',
|
|
595
|
+
'http.Handler'
|
|
596
|
+
];
|
|
597
|
+
|
|
598
|
+
return funcInfo.params.some(p =>
|
|
599
|
+
handlerParams.some(hp => p.type.includes(hp.replace('*', '')))
|
|
600
|
+
);
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
/**
|
|
604
|
+
* Generate tool name
|
|
605
|
+
*/
|
|
606
|
+
private generateToolName(method: string, path: string, handlerName: string): string {
|
|
607
|
+
const pathParts = path
|
|
608
|
+
.split('/')
|
|
609
|
+
.filter(p => p && !p.startsWith('{') && !p.startsWith(':'))
|
|
610
|
+
.map(p => p.replace(/-/g, '_').toLowerCase());
|
|
611
|
+
|
|
612
|
+
if (pathParts.length > 0) {
|
|
613
|
+
return `${method.toLowerCase()}_${pathParts.join('_')}`;
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
// Use handler name, converting from PascalCase to snake_case
|
|
617
|
+
return handlerName
|
|
618
|
+
.replace(/([A-Z])/g, '_$1')
|
|
619
|
+
.toLowerCase()
|
|
620
|
+
.replace(/^_/, '')
|
|
621
|
+
.replace(/\._/g, '_');
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
/**
|
|
625
|
+
* Build input schema for Gin handlers
|
|
626
|
+
*/
|
|
627
|
+
private buildGinInputSchema(
|
|
628
|
+
funcInfo: GoFunction | null,
|
|
629
|
+
path: string
|
|
630
|
+
): { type: 'object'; properties: Record<string, any>; required: string[] } {
|
|
631
|
+
const properties: Record<string, any> = {};
|
|
632
|
+
const required: string[] = [];
|
|
633
|
+
|
|
634
|
+
// Extract path parameters (Gin uses :param syntax)
|
|
635
|
+
const pathParams = path.match(/:(\w+)/g) || [];
|
|
636
|
+
for (const param of pathParams) {
|
|
637
|
+
const name = param.substring(1);
|
|
638
|
+
properties[name] = {
|
|
639
|
+
type: 'string',
|
|
640
|
+
description: `Path parameter: ${name}`
|
|
641
|
+
};
|
|
642
|
+
required.push(name);
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
return { type: 'object', properties, required };
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
/**
|
|
649
|
+
* Build input schema for Echo handlers
|
|
650
|
+
*/
|
|
651
|
+
private buildEchoInputSchema(
|
|
652
|
+
funcInfo: GoFunction | null,
|
|
653
|
+
path: string
|
|
654
|
+
): { type: 'object'; properties: Record<string, any>; required: string[] } {
|
|
655
|
+
// Echo uses :param syntax like Gin
|
|
656
|
+
return this.buildGinInputSchema(funcInfo, path);
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
/**
|
|
660
|
+
* Build input schema for Chi handlers
|
|
661
|
+
*/
|
|
662
|
+
private buildChiInputSchema(
|
|
663
|
+
funcInfo: GoFunction | null,
|
|
664
|
+
path: string
|
|
665
|
+
): { type: 'object'; properties: Record<string, any>; required: string[] } {
|
|
666
|
+
const properties: Record<string, any> = {};
|
|
667
|
+
const required: string[] = [];
|
|
668
|
+
|
|
669
|
+
// Chi uses {param} syntax
|
|
670
|
+
const pathParams = path.match(/\{(\w+)\}/g) || [];
|
|
671
|
+
for (const param of pathParams) {
|
|
672
|
+
const name = param.slice(1, -1);
|
|
673
|
+
properties[name] = {
|
|
674
|
+
type: 'string',
|
|
675
|
+
description: `Path parameter: ${name}`
|
|
676
|
+
};
|
|
677
|
+
required.push(name);
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
return { type: 'object', properties, required };
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
/**
|
|
684
|
+
* Build input schema for Fiber handlers
|
|
685
|
+
*/
|
|
686
|
+
private buildFiberInputSchema(
|
|
687
|
+
funcInfo: GoFunction | null,
|
|
688
|
+
path: string
|
|
689
|
+
): { type: 'object'; properties: Record<string, any>; required: string[] } {
|
|
690
|
+
const properties: Record<string, any> = {};
|
|
691
|
+
const required: string[] = [];
|
|
692
|
+
|
|
693
|
+
// Fiber uses :param syntax
|
|
694
|
+
const pathParams = path.match(/:(\w+)/g) || [];
|
|
695
|
+
for (const param of pathParams) {
|
|
696
|
+
const name = param.substring(1);
|
|
697
|
+
properties[name] = {
|
|
698
|
+
type: 'string',
|
|
699
|
+
description: `Path parameter: ${name}`
|
|
700
|
+
};
|
|
701
|
+
required.push(name);
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
return { type: 'object', properties, required };
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
/**
|
|
708
|
+
* Build input schema for net/http handlers
|
|
709
|
+
*/
|
|
710
|
+
private buildHttpInputSchema(
|
|
711
|
+
funcInfo: GoFunction | null,
|
|
712
|
+
path: string
|
|
713
|
+
): { type: 'object'; properties: Record<string, any>; required: string[] } {
|
|
714
|
+
// net/http doesn't have built-in path params
|
|
715
|
+
return { type: 'object', properties: {}, required: [] };
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
/**
|
|
719
|
+
* Build input schema from function params
|
|
720
|
+
*/
|
|
721
|
+
private buildFunctionInputSchema(
|
|
722
|
+
funcInfo: GoFunction
|
|
723
|
+
): { type: 'object'; properties: Record<string, any>; required: string[] } {
|
|
724
|
+
const properties: Record<string, any> = {};
|
|
725
|
+
const required: string[] = [];
|
|
726
|
+
|
|
727
|
+
for (const param of funcInfo.params) {
|
|
728
|
+
// Skip context parameters
|
|
729
|
+
if (param.type.includes('context.Context') || param.type.includes('Context')) {
|
|
730
|
+
continue;
|
|
731
|
+
}
|
|
732
|
+
|
|
733
|
+
const isPointer = param.type.startsWith('*');
|
|
734
|
+
|
|
735
|
+
properties[param.name] = {
|
|
736
|
+
type: this.goTypeToJsonSchema(param.type),
|
|
737
|
+
description: funcInfo.documentation?.params.find(p => p.name === param.name)?.description || param.name
|
|
738
|
+
};
|
|
739
|
+
|
|
740
|
+
if (!isPointer) {
|
|
741
|
+
required.push(param.name);
|
|
742
|
+
}
|
|
743
|
+
}
|
|
744
|
+
|
|
745
|
+
return { type: 'object', properties, required };
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
/**
|
|
749
|
+
* Convert Go type to JSON Schema type
|
|
750
|
+
*/
|
|
751
|
+
private goTypeToJsonSchema(goType: string): string {
|
|
752
|
+
const type = goType.trim().replace(/^\*/, ''); // Remove pointer
|
|
753
|
+
|
|
754
|
+
// Array/slice types
|
|
755
|
+
if (type.startsWith('[]')) {
|
|
756
|
+
return 'array';
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
// Map types
|
|
760
|
+
if (type.startsWith('map[')) {
|
|
761
|
+
return 'object';
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
// Primitive type mapping
|
|
765
|
+
const typeMap: Record<string, string> = {
|
|
766
|
+
'string': 'string',
|
|
767
|
+
'int': 'integer',
|
|
768
|
+
'int8': 'integer',
|
|
769
|
+
'int16': 'integer',
|
|
770
|
+
'int32': 'integer',
|
|
771
|
+
'int64': 'integer',
|
|
772
|
+
'uint': 'integer',
|
|
773
|
+
'uint8': 'integer',
|
|
774
|
+
'uint16': 'integer',
|
|
775
|
+
'uint32': 'integer',
|
|
776
|
+
'uint64': 'integer',
|
|
777
|
+
'float32': 'number',
|
|
778
|
+
'float64': 'number',
|
|
779
|
+
'bool': 'boolean',
|
|
780
|
+
'byte': 'integer',
|
|
781
|
+
'rune': 'integer'
|
|
782
|
+
};
|
|
783
|
+
|
|
784
|
+
if (typeMap[type]) {
|
|
785
|
+
return typeMap[type];
|
|
786
|
+
}
|
|
787
|
+
|
|
788
|
+
// Default to object for structs and interfaces
|
|
789
|
+
return 'object';
|
|
790
|
+
}
|
|
791
|
+
}
|