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,251 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Queue type definitions
|
|
3
|
+
* @copyright Copyright (c) 2024-2026 nirholas
|
|
4
|
+
* @license MIT
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Job status types
|
|
9
|
+
*/
|
|
10
|
+
export type JobStatus = 'pending' | 'processing' | 'completed' | 'failed' | 'cancelled' | 'delayed';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Job priority levels
|
|
14
|
+
*/
|
|
15
|
+
export type JobPriority = 'low' | 'normal' | 'high' | 'critical';
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Job definition
|
|
19
|
+
*/
|
|
20
|
+
export interface Job<T = unknown> {
|
|
21
|
+
/** Unique job identifier */
|
|
22
|
+
id: string;
|
|
23
|
+
/** Job payload data */
|
|
24
|
+
data: T;
|
|
25
|
+
/** Current job status */
|
|
26
|
+
status: JobStatus;
|
|
27
|
+
/** Job priority (higher = processed first) */
|
|
28
|
+
priority?: number;
|
|
29
|
+
/** Number of processing attempts */
|
|
30
|
+
attempts: number;
|
|
31
|
+
/** Maximum retry attempts */
|
|
32
|
+
maxRetries?: number;
|
|
33
|
+
/** Job result (when completed) */
|
|
34
|
+
result?: unknown;
|
|
35
|
+
/** Error message (when failed) */
|
|
36
|
+
error?: string;
|
|
37
|
+
/** Delay in milliseconds before processing */
|
|
38
|
+
delay?: number;
|
|
39
|
+
/** Timeout in milliseconds */
|
|
40
|
+
timeout?: number;
|
|
41
|
+
/** Job creation timestamp */
|
|
42
|
+
createdAt?: Date;
|
|
43
|
+
/** Last update timestamp */
|
|
44
|
+
updatedAt?: Date;
|
|
45
|
+
/** Processing start timestamp */
|
|
46
|
+
startedAt?: Date;
|
|
47
|
+
/** Completion timestamp */
|
|
48
|
+
completedAt?: Date;
|
|
49
|
+
/** Failure timestamp */
|
|
50
|
+
failedAt?: Date;
|
|
51
|
+
/** Custom tags for filtering */
|
|
52
|
+
tags?: string[];
|
|
53
|
+
/** Custom metadata */
|
|
54
|
+
metadata?: Record<string, unknown>;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Job options for enqueueing
|
|
59
|
+
*/
|
|
60
|
+
export interface JobOptions {
|
|
61
|
+
/** Job priority (higher = processed first) */
|
|
62
|
+
priority?: number;
|
|
63
|
+
/** Maximum retry attempts */
|
|
64
|
+
maxRetries?: number;
|
|
65
|
+
/** Delay in milliseconds before processing */
|
|
66
|
+
delay?: number;
|
|
67
|
+
/** Timeout in milliseconds */
|
|
68
|
+
timeout?: number;
|
|
69
|
+
/** Custom tags for filtering */
|
|
70
|
+
tags?: string[];
|
|
71
|
+
/** Custom metadata */
|
|
72
|
+
metadata?: Record<string, unknown>;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Queue configuration
|
|
77
|
+
*/
|
|
78
|
+
export interface QueueConfig {
|
|
79
|
+
/** Maximum concurrent jobs */
|
|
80
|
+
maxConcurrency?: number;
|
|
81
|
+
/** Default job priority */
|
|
82
|
+
defaultPriority?: number;
|
|
83
|
+
/** Default max retries */
|
|
84
|
+
maxRetries?: number;
|
|
85
|
+
/** Delay between retries in milliseconds */
|
|
86
|
+
retryDelay?: number;
|
|
87
|
+
/** Default job timeout in milliseconds */
|
|
88
|
+
jobTimeout?: number;
|
|
89
|
+
/** Maximum completed jobs to keep */
|
|
90
|
+
maxCompletedJobs?: number;
|
|
91
|
+
/** Maximum failed jobs to keep */
|
|
92
|
+
maxFailedJobs?: number;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Queue statistics
|
|
97
|
+
*/
|
|
98
|
+
export interface QueueStats {
|
|
99
|
+
/** Number of pending jobs */
|
|
100
|
+
pending: number;
|
|
101
|
+
/** Number of processing jobs */
|
|
102
|
+
processing: number;
|
|
103
|
+
/** Number of completed jobs */
|
|
104
|
+
completed: number;
|
|
105
|
+
/** Number of failed jobs */
|
|
106
|
+
failed: number;
|
|
107
|
+
/** Total jobs in queue */
|
|
108
|
+
total: number;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Job handler function
|
|
113
|
+
*/
|
|
114
|
+
export type JobHandler<T = unknown, R = unknown> = (job: Job<T>) => Promise<R>;
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Queue interface that all queue implementations must follow
|
|
118
|
+
*/
|
|
119
|
+
export interface QueueInterface<T = unknown> {
|
|
120
|
+
/**
|
|
121
|
+
* Enqueue a new job
|
|
122
|
+
* @param data - Job payload
|
|
123
|
+
* @param options - Job options
|
|
124
|
+
* @returns The created job
|
|
125
|
+
*/
|
|
126
|
+
enqueue(data: T, options?: JobOptions): Promise<Job<T>>;
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Dequeue the next job for processing
|
|
130
|
+
* @returns The next job or null if queue is empty
|
|
131
|
+
*/
|
|
132
|
+
dequeue(): Promise<Job<T> | null>;
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Get job status
|
|
136
|
+
* @param jobId - Job ID
|
|
137
|
+
* @returns Job status or null if not found
|
|
138
|
+
*/
|
|
139
|
+
getStatus(jobId: string): Promise<JobStatus | null>;
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Get job by ID
|
|
143
|
+
* @param jobId - Job ID
|
|
144
|
+
* @returns Job or null if not found
|
|
145
|
+
*/
|
|
146
|
+
getJob(jobId: string): Promise<Job<T> | null>;
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Register a callback for job completion
|
|
150
|
+
* @param callback - Callback function
|
|
151
|
+
*/
|
|
152
|
+
onComplete(callback: (job: Job<T>) => void): void;
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Register a callback for job failure
|
|
156
|
+
* @param callback - Callback function
|
|
157
|
+
*/
|
|
158
|
+
onFail(callback: (job: Job<T>, error: Error) => void): void;
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Process jobs with a handler
|
|
162
|
+
* @param handler - Job handler function
|
|
163
|
+
*/
|
|
164
|
+
process(handler: JobHandler<T>): Promise<void>;
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Cancel a job
|
|
168
|
+
* @param jobId - Job ID
|
|
169
|
+
* @returns True if job was cancelled
|
|
170
|
+
*/
|
|
171
|
+
cancel?(jobId: string): Promise<boolean>;
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Retry a failed job
|
|
175
|
+
* @param jobId - Job ID
|
|
176
|
+
* @returns The retried job or null
|
|
177
|
+
*/
|
|
178
|
+
retry?(jobId: string): Promise<Job<T> | null>;
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Get queue statistics
|
|
182
|
+
*/
|
|
183
|
+
getStats(): Promise<QueueStats>;
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Get jobs by status
|
|
187
|
+
* @param status - Job status to filter
|
|
188
|
+
* @param limit - Maximum jobs to return
|
|
189
|
+
*/
|
|
190
|
+
getJobsByStatus?(status: JobStatus, limit?: number): Promise<Job<T>[]>;
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Clear completed jobs
|
|
194
|
+
* @returns Number of jobs cleared
|
|
195
|
+
*/
|
|
196
|
+
clearCompleted?(): Promise<number>;
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Clear failed jobs
|
|
200
|
+
* @returns Number of jobs cleared
|
|
201
|
+
*/
|
|
202
|
+
clearFailed?(): Promise<number>;
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* Pause the queue
|
|
206
|
+
*/
|
|
207
|
+
pause?(): Promise<void>;
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Resume the queue
|
|
211
|
+
*/
|
|
212
|
+
resume?(): Promise<void>;
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Close the queue connection
|
|
216
|
+
*/
|
|
217
|
+
close?(): Promise<void>;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Convert priority name to number
|
|
222
|
+
*/
|
|
223
|
+
export function priorityToNumber(priority: JobPriority): number {
|
|
224
|
+
switch (priority) {
|
|
225
|
+
case 'critical':
|
|
226
|
+
return 100;
|
|
227
|
+
case 'high':
|
|
228
|
+
return 50;
|
|
229
|
+
case 'normal':
|
|
230
|
+
return 0;
|
|
231
|
+
case 'low':
|
|
232
|
+
return -50;
|
|
233
|
+
default:
|
|
234
|
+
return 0;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* Helper to create a job with common defaults
|
|
240
|
+
*/
|
|
241
|
+
export function createJobOptions(
|
|
242
|
+
priority: JobPriority = 'normal',
|
|
243
|
+
options: Partial<JobOptions> = {}
|
|
244
|
+
): JobOptions {
|
|
245
|
+
return {
|
|
246
|
+
priority: priorityToNumber(priority),
|
|
247
|
+
maxRetries: 3,
|
|
248
|
+
timeout: 60000,
|
|
249
|
+
...options
|
|
250
|
+
};
|
|
251
|
+
}
|
|
@@ -0,0 +1,409 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview readme-extractor module implementation
|
|
3
|
+
* @copyright Copyright (c) 2024-2026 nirholas
|
|
4
|
+
* @license MIT
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* README Extractor
|
|
9
|
+
* Extract API information from README markdown files
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { marked } from 'marked';
|
|
13
|
+
import { ExtractedTool, CodeExample } from './types';
|
|
14
|
+
|
|
15
|
+
export class ReadmeExtractor {
|
|
16
|
+
/**
|
|
17
|
+
* Extract tools from README
|
|
18
|
+
*/
|
|
19
|
+
async extract(readme: string): Promise<ExtractedTool[]> {
|
|
20
|
+
const tools: ExtractedTool[] = [];
|
|
21
|
+
|
|
22
|
+
// Parse markdown
|
|
23
|
+
const tokens = marked.lexer(readme);
|
|
24
|
+
|
|
25
|
+
// 1. Extract from code examples (JS/TS)
|
|
26
|
+
const examples = this.extractCodeExamples(tokens);
|
|
27
|
+
for (const example of examples) {
|
|
28
|
+
const tool = this.exampleToTool(example);
|
|
29
|
+
if (tool) {
|
|
30
|
+
tools.push(tool);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// 2. Extract from Python @mcp.tool decorators
|
|
35
|
+
const pythonTools = this.extractPythonMcpTools(tokens);
|
|
36
|
+
tools.push(...pythonTools);
|
|
37
|
+
|
|
38
|
+
// 3. Extract from tool lists in text ("Available Tools" sections)
|
|
39
|
+
const listTools = this.extractToolLists(tokens);
|
|
40
|
+
tools.push(...listTools);
|
|
41
|
+
|
|
42
|
+
return tools;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Extract Python MCP tools from code blocks
|
|
47
|
+
*/
|
|
48
|
+
private extractPythonMcpTools(tokens: any[]): ExtractedTool[] {
|
|
49
|
+
const tools: ExtractedTool[] = [];
|
|
50
|
+
|
|
51
|
+
for (const token of tokens) {
|
|
52
|
+
if (token.type === 'code' && (token.lang === 'python' || token.lang === 'py')) {
|
|
53
|
+
// Match @mcp.tool decorators
|
|
54
|
+
const mcpToolPattern = /@mcp\.tool\s*\(\s*name\s*=\s*["']([^"']+)["']\s*,\s*description\s*=\s*["']([^"']+)["']/g;
|
|
55
|
+
let match;
|
|
56
|
+
while ((match = mcpToolPattern.exec(token.text)) !== null) {
|
|
57
|
+
tools.push({
|
|
58
|
+
name: match[1],
|
|
59
|
+
description: match[2],
|
|
60
|
+
inputSchema: { type: 'object', properties: {}, required: [] },
|
|
61
|
+
source: { type: 'readme', file: 'README.md', line: 0 }
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Match FastMCP tool decorator patterns
|
|
66
|
+
const fastMcpPattern = /@(\w+)\.tool\s*(?:\(([^)]+)\))?/g;
|
|
67
|
+
while ((match = fastMcpPattern.exec(token.text)) !== null) {
|
|
68
|
+
const args = match[2] || '';
|
|
69
|
+
const nameMatch = args.match(/name\s*=\s*["']([^"']+)["']/);
|
|
70
|
+
const descMatch = args.match(/description\s*=\s*["']([^"']+)["']/);
|
|
71
|
+
if (nameMatch) {
|
|
72
|
+
tools.push({
|
|
73
|
+
name: nameMatch[1],
|
|
74
|
+
description: descMatch?.[1] || `${nameMatch[1]} tool`,
|
|
75
|
+
inputSchema: { type: 'object', properties: {}, required: [] },
|
|
76
|
+
source: { type: 'readme', file: 'README.md', line: 0 }
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return tools;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Extract tools from text lists ("Available Tools", "Tools", etc.)
|
|
88
|
+
*/
|
|
89
|
+
private extractToolLists(tokens: any[]): ExtractedTool[] {
|
|
90
|
+
const tools: ExtractedTool[] = [];
|
|
91
|
+
let inToolsSection = false;
|
|
92
|
+
const toolsSectionPatterns = /^(available\s+tools?|tools?|features|capabilities|commands?)$/i;
|
|
93
|
+
|
|
94
|
+
for (let i = 0; i < tokens.length; i++) {
|
|
95
|
+
const token = tokens[i];
|
|
96
|
+
|
|
97
|
+
// Check for tools section heading
|
|
98
|
+
if (token.type === 'heading') {
|
|
99
|
+
inToolsSection = toolsSectionPatterns.test(token.text.trim());
|
|
100
|
+
continue;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// Extract from bullet lists in tools section
|
|
104
|
+
if (inToolsSection && token.type === 'list') {
|
|
105
|
+
for (const item of token.items || []) {
|
|
106
|
+
const tool = this.parseToolListItem(item.text || item.raw || '');
|
|
107
|
+
if (tool) {
|
|
108
|
+
tools.push(tool);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// Also check paragraphs for inline tool mentions
|
|
114
|
+
if (inToolsSection && token.type === 'paragraph') {
|
|
115
|
+
const inlineTools = this.parseInlineTools(token.text || '');
|
|
116
|
+
tools.push(...inlineTools);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
return tools;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Parse a tool list item like "**View:** Read files" or "- Edit: Modify files"
|
|
125
|
+
*/
|
|
126
|
+
private parseToolListItem(text: string): ExtractedTool | null {
|
|
127
|
+
// Pattern: **ToolName:** Description or ToolName: Description
|
|
128
|
+
const patterns = [
|
|
129
|
+
/^\*\*([\w-]+)\*\*[:\s]+(.+)$/,
|
|
130
|
+
/^\*([\w-]+)\*[:\s]+(.+)$/,
|
|
131
|
+
/^([\w-]+)[:\s]+(.+)$/,
|
|
132
|
+
/^`([\w-]+)`[:\s]+(.+)$/
|
|
133
|
+
];
|
|
134
|
+
|
|
135
|
+
for (const pattern of patterns) {
|
|
136
|
+
const match = text.match(pattern);
|
|
137
|
+
if (match) {
|
|
138
|
+
const name = match[1].trim();
|
|
139
|
+
const description = match[2].trim();
|
|
140
|
+
|
|
141
|
+
// Skip common non-tool patterns
|
|
142
|
+
if (this.isLikelyTool(name)) {
|
|
143
|
+
return {
|
|
144
|
+
name: this.normalizeToolName(name),
|
|
145
|
+
description,
|
|
146
|
+
inputSchema: { type: 'object', properties: {}, required: [] },
|
|
147
|
+
source: { type: 'readme', file: 'README.md', line: 0 }
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
return null;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Parse inline tool mentions
|
|
158
|
+
*/
|
|
159
|
+
private parseInlineTools(text: string): ExtractedTool[] {
|
|
160
|
+
const tools: ExtractedTool[] = [];
|
|
161
|
+
|
|
162
|
+
// Look for patterns like "The Edit tool allows..." or "Use the GrepTool for..."
|
|
163
|
+
const pattern = /(?:the\s+)?([A-Z][a-zA-Z]+(?:Tool)?)[:\s]+([^.]+\.)/gi;
|
|
164
|
+
let match;
|
|
165
|
+
|
|
166
|
+
while ((match = pattern.exec(text)) !== null) {
|
|
167
|
+
const name = match[1];
|
|
168
|
+
const description = match[2].trim();
|
|
169
|
+
|
|
170
|
+
if (this.isLikelyTool(name)) {
|
|
171
|
+
tools.push({
|
|
172
|
+
name: this.normalizeToolName(name),
|
|
173
|
+
description,
|
|
174
|
+
inputSchema: { type: 'object', properties: {}, required: [] },
|
|
175
|
+
source: { type: 'readme', file: 'README.md', line: 0 }
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
return tools;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Check if name looks like a tool
|
|
185
|
+
*/
|
|
186
|
+
private isLikelyTool(name: string): boolean {
|
|
187
|
+
// Tool names are usually PascalCase or contain 'Tool'
|
|
188
|
+
const toolPatterns = [
|
|
189
|
+
/^[A-Z][a-z]+[A-Z]/, // PascalCase
|
|
190
|
+
/Tool$/i, // Ends with Tool
|
|
191
|
+
/^(get|set|list|create|update|delete|fetch|search|run|execute)/i, // Common verbs
|
|
192
|
+
/^(View|Edit|Replace|Bash|LS|Grep|Glob|Read|Write)/i // Known tool names
|
|
193
|
+
];
|
|
194
|
+
|
|
195
|
+
// Skip common non-tool words
|
|
196
|
+
const skipWords = /^(the|a|an|is|are|this|that|or|and|for|with|to|from|in|on|at)$/i;
|
|
197
|
+
if (skipWords.test(name)) return false;
|
|
198
|
+
|
|
199
|
+
return toolPatterns.some(p => p.test(name));
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* Normalize tool name to consistent format
|
|
204
|
+
*/
|
|
205
|
+
private normalizeToolName(name: string): string {
|
|
206
|
+
// Remove 'Tool' suffix if present, keep PascalCase
|
|
207
|
+
return name.replace(/Tool$/i, '');
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* Extract code examples from markdown tokens
|
|
212
|
+
*/
|
|
213
|
+
private extractCodeExamples(tokens: any[]): CodeExample[] {
|
|
214
|
+
const examples: CodeExample[] = [];
|
|
215
|
+
let currentHeading = '';
|
|
216
|
+
|
|
217
|
+
for (let i = 0; i < tokens.length; i++) {
|
|
218
|
+
const token = tokens[i];
|
|
219
|
+
|
|
220
|
+
if (token.type === 'heading') {
|
|
221
|
+
currentHeading = token.text;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
if (token.type === 'code') {
|
|
225
|
+
const lang = token.lang || 'javascript';
|
|
226
|
+
|
|
227
|
+
if (this.isApiExample(token.text, lang)) {
|
|
228
|
+
examples.push({
|
|
229
|
+
code: token.text,
|
|
230
|
+
language: lang,
|
|
231
|
+
description: currentHeading,
|
|
232
|
+
file: 'README.md',
|
|
233
|
+
line: 0
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
return examples;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* Check if code block is an API example
|
|
244
|
+
*/
|
|
245
|
+
private isApiExample(code: string, lang: string): boolean {
|
|
246
|
+
// Must be JavaScript/TypeScript
|
|
247
|
+
if (!['javascript', 'typescript', 'js', 'ts'].includes(lang)) {
|
|
248
|
+
return false;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
// Look for API call patterns
|
|
252
|
+
const patterns = [
|
|
253
|
+
/\.get\(/,
|
|
254
|
+
/\.post\(/,
|
|
255
|
+
/\.put\(/,
|
|
256
|
+
/\.delete\(/,
|
|
257
|
+
/\.patch\(/,
|
|
258
|
+
/fetch\(/,
|
|
259
|
+
/axios\./,
|
|
260
|
+
/\.create\(/,
|
|
261
|
+
/\.update\(/,
|
|
262
|
+
/\.list\(/,
|
|
263
|
+
/\.retrieve\(/
|
|
264
|
+
];
|
|
265
|
+
|
|
266
|
+
return patterns.some(pattern => pattern.test(code));
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
/**
|
|
270
|
+
* Convert code example to MCP tool
|
|
271
|
+
*/
|
|
272
|
+
private exampleToTool(example: CodeExample): ExtractedTool | null {
|
|
273
|
+
try {
|
|
274
|
+
// Extract method name
|
|
275
|
+
const methodMatch = example.code.match(/(?:await\s+)?(?:\w+\.)?(\w+)\(/);
|
|
276
|
+
if (!methodMatch) return null;
|
|
277
|
+
|
|
278
|
+
const methodName = methodMatch[1];
|
|
279
|
+
|
|
280
|
+
// Extract parameters
|
|
281
|
+
const params = this.extractParameters(example.code);
|
|
282
|
+
|
|
283
|
+
// Extract description
|
|
284
|
+
const description = example.description || `Call ${methodName}`;
|
|
285
|
+
|
|
286
|
+
return {
|
|
287
|
+
name: this.toToolName(methodName),
|
|
288
|
+
description,
|
|
289
|
+
inputSchema: {
|
|
290
|
+
type: 'object',
|
|
291
|
+
properties: params,
|
|
292
|
+
required: Object.keys(params).filter(k => params[k].required)
|
|
293
|
+
},
|
|
294
|
+
implementation: this.generateImplementation(methodName, params),
|
|
295
|
+
examples: [example.code],
|
|
296
|
+
source: {
|
|
297
|
+
type: 'readme',
|
|
298
|
+
file: example.file,
|
|
299
|
+
line: example.line
|
|
300
|
+
}
|
|
301
|
+
};
|
|
302
|
+
} catch (error) {
|
|
303
|
+
return null;
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
/**
|
|
308
|
+
* Extract parameters from code
|
|
309
|
+
*/
|
|
310
|
+
private extractParameters(code: string): Record<string, any> {
|
|
311
|
+
const params: Record<string, any> = {};
|
|
312
|
+
|
|
313
|
+
// Look for object literals passed as arguments
|
|
314
|
+
const objectMatch = code.match(/\{([^}]+)\}/);
|
|
315
|
+
if (objectMatch) {
|
|
316
|
+
const objectContent = objectMatch[1];
|
|
317
|
+
|
|
318
|
+
// Extract key-value pairs
|
|
319
|
+
const pairs = objectContent.split(',');
|
|
320
|
+
for (const pair of pairs) {
|
|
321
|
+
const [key, value] = pair.split(':').map(s => s.trim());
|
|
322
|
+
if (key && value) {
|
|
323
|
+
params[key] = {
|
|
324
|
+
type: this.inferType(value),
|
|
325
|
+
description: `${key} parameter`,
|
|
326
|
+
required: true
|
|
327
|
+
};
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
return params;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
/**
|
|
336
|
+
* Infer type from value
|
|
337
|
+
*/
|
|
338
|
+
private inferType(value: string): string {
|
|
339
|
+
if (/^['"]/.test(value)) return 'string';
|
|
340
|
+
if (/^\d+$/.test(value)) return 'number';
|
|
341
|
+
if (/^(true|false)$/.test(value)) return 'boolean';
|
|
342
|
+
if (/^\[/.test(value)) return 'array';
|
|
343
|
+
if (/^\{/.test(value)) return 'object';
|
|
344
|
+
return 'string';
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
/**
|
|
348
|
+
* Convert method name to tool name
|
|
349
|
+
*/
|
|
350
|
+
private toToolName(methodName: string): string {
|
|
351
|
+
// camelCase to snake_case
|
|
352
|
+
return methodName.replace(/([A-Z])/g, '_$1').toLowerCase();
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
/**
|
|
356
|
+
* Generate implementation code
|
|
357
|
+
*/
|
|
358
|
+
private generateImplementation(methodName: string, params: Record<string, any>): string {
|
|
359
|
+
const paramNames = Object.keys(params);
|
|
360
|
+
|
|
361
|
+
return `async function ${methodName}(args: any) {
|
|
362
|
+
const { ${paramNames.join(', ')} } = args;
|
|
363
|
+
|
|
364
|
+
// Auto-generated implementation for ${methodName}
|
|
365
|
+
// Calls the underlying API method with validated parameters
|
|
366
|
+
const response = await api.${methodName}({ ${paramNames.join(', ')} });
|
|
367
|
+
|
|
368
|
+
return response;
|
|
369
|
+
}`;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
/**
|
|
373
|
+
* Extract documentation links from README
|
|
374
|
+
*/
|
|
375
|
+
extractDocumentationLinks(readme: string): Array<{ url: string; title: string }> {
|
|
376
|
+
const links: Array<{ url: string; title: string }> = [];
|
|
377
|
+
const linkPattern = /\[([^\]]+)\]\(([^)]+)\)/g;
|
|
378
|
+
|
|
379
|
+
let match;
|
|
380
|
+
while ((match = linkPattern.exec(readme)) !== null) {
|
|
381
|
+
const [, title, url] = match;
|
|
382
|
+
|
|
383
|
+
// Only keep documentation links
|
|
384
|
+
if (this.isDocumentationUrl(url)) {
|
|
385
|
+
links.push({ url, title });
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
return links;
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
/**
|
|
393
|
+
* Check if URL is documentation
|
|
394
|
+
*/
|
|
395
|
+
private isDocumentationUrl(url: string): boolean {
|
|
396
|
+
const docPatterns = [
|
|
397
|
+
/docs?\./,
|
|
398
|
+
/developer\./,
|
|
399
|
+
/api\./,
|
|
400
|
+
/reference\./,
|
|
401
|
+
/\/docs\//,
|
|
402
|
+
/\/api\//,
|
|
403
|
+
/\/reference\//,
|
|
404
|
+
/\/guide\//
|
|
405
|
+
];
|
|
406
|
+
|
|
407
|
+
return docPatterns.some(pattern => pattern.test(url));
|
|
408
|
+
}
|
|
409
|
+
}
|