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,644 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Playground V2 Page - Full-featured MCP playground with transport configuration
|
|
3
|
+
* @copyright 2024-2026 nirholas
|
|
4
|
+
* @license MIT
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
'use client';
|
|
8
|
+
|
|
9
|
+
import { Suspense, useEffect, useCallback, useMemo, useState, useRef } from 'react';
|
|
10
|
+
import { motion, AnimatePresence } from 'framer-motion';
|
|
11
|
+
import {
|
|
12
|
+
Terminal,
|
|
13
|
+
ArrowLeft,
|
|
14
|
+
History,
|
|
15
|
+
Settings,
|
|
16
|
+
X,
|
|
17
|
+
} from 'lucide-react';
|
|
18
|
+
import Link from 'next/link';
|
|
19
|
+
|
|
20
|
+
import Header from '@/components/Header';
|
|
21
|
+
import Footer from '@/components/Footer';
|
|
22
|
+
import ParticleBackground from '@/components/ParticleBackground';
|
|
23
|
+
import { Button } from '@/components/ui/button';
|
|
24
|
+
|
|
25
|
+
// Playground components
|
|
26
|
+
import {
|
|
27
|
+
TransportConfigurator,
|
|
28
|
+
ConnectionStatusV2 as ConnectionStatus,
|
|
29
|
+
CapabilityTabs,
|
|
30
|
+
ToolsPanel,
|
|
31
|
+
ResourcesPanel,
|
|
32
|
+
PromptsPanel,
|
|
33
|
+
ExecutionLogV2 as ExecutionLog,
|
|
34
|
+
EmptyStates,
|
|
35
|
+
FirstTimeGuide,
|
|
36
|
+
ShareButton,
|
|
37
|
+
} from '@/components/playground';
|
|
38
|
+
|
|
39
|
+
// Hooks
|
|
40
|
+
import { usePlayground, useExecutionHistory } from '@/hooks';
|
|
41
|
+
import type { TransportConfig as HooksTransportConfig, McpTool, McpResource, McpPrompt, PlaygroundTab } from '@/hooks/types';
|
|
42
|
+
import type { TransportConfig as ComponentTransportConfig, LogEntry } from '@/components/playground/types';
|
|
43
|
+
|
|
44
|
+
// Local hooks
|
|
45
|
+
import { useUrlState } from './use-url-state';
|
|
46
|
+
import { useShortcuts } from './use-shortcuts';
|
|
47
|
+
|
|
48
|
+
// ============================================================================
|
|
49
|
+
// Type Definitions for Playground
|
|
50
|
+
// We use 'any' assertions to bridge the gap between hook types and component types
|
|
51
|
+
// since they are structurally compatible but TypeScript sees them as different
|
|
52
|
+
// ============================================================================
|
|
53
|
+
|
|
54
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
55
|
+
type AnyTool = any;
|
|
56
|
+
type AnyResource = any;
|
|
57
|
+
type AnyPrompt = any;
|
|
58
|
+
type AnyCapabilities = any;
|
|
59
|
+
/* eslint-enable @typescript-eslint/no-explicit-any */
|
|
60
|
+
|
|
61
|
+
// ============================================================================
|
|
62
|
+
// Type Adapters
|
|
63
|
+
// ============================================================================
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Convert hook TransportConfig to component TransportConfig
|
|
67
|
+
*/
|
|
68
|
+
function toComponentTransport(config: HooksTransportConfig | null): ComponentTransportConfig | null {
|
|
69
|
+
if (!config) return null;
|
|
70
|
+
|
|
71
|
+
switch (config.type) {
|
|
72
|
+
case 'stdio':
|
|
73
|
+
return {
|
|
74
|
+
type: 'stdio',
|
|
75
|
+
command: config.command,
|
|
76
|
+
args: config.args,
|
|
77
|
+
env: config.env,
|
|
78
|
+
};
|
|
79
|
+
case 'sse':
|
|
80
|
+
case 'http':
|
|
81
|
+
return {
|
|
82
|
+
type: 'sse',
|
|
83
|
+
url: config.url,
|
|
84
|
+
headers: config.headers,
|
|
85
|
+
};
|
|
86
|
+
case 'websocket':
|
|
87
|
+
return {
|
|
88
|
+
type: 'streamable-http',
|
|
89
|
+
url: config.url,
|
|
90
|
+
headers: config.headers,
|
|
91
|
+
};
|
|
92
|
+
default:
|
|
93
|
+
return null;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Convert component TransportConfig to hook TransportConfig
|
|
99
|
+
*/
|
|
100
|
+
function toHooksTransport(config: ComponentTransportConfig): HooksTransportConfig {
|
|
101
|
+
switch (config.type) {
|
|
102
|
+
case 'stdio':
|
|
103
|
+
return {
|
|
104
|
+
type: 'stdio',
|
|
105
|
+
command: config.command,
|
|
106
|
+
args: config.args,
|
|
107
|
+
env: config.env,
|
|
108
|
+
};
|
|
109
|
+
case 'sse':
|
|
110
|
+
return {
|
|
111
|
+
type: 'sse',
|
|
112
|
+
url: config.url,
|
|
113
|
+
headers: config.headers,
|
|
114
|
+
};
|
|
115
|
+
case 'streamable-http':
|
|
116
|
+
return {
|
|
117
|
+
type: 'http',
|
|
118
|
+
url: config.url,
|
|
119
|
+
headers: config.headers,
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// ============================================================================
|
|
125
|
+
// Main Page Component
|
|
126
|
+
// ============================================================================
|
|
127
|
+
|
|
128
|
+
function PlaygroundV2Content() {
|
|
129
|
+
// Initialize playground hook
|
|
130
|
+
const playground = usePlayground();
|
|
131
|
+
|
|
132
|
+
// Execution history
|
|
133
|
+
const executionHistory = useExecutionHistory({ persist: true });
|
|
134
|
+
|
|
135
|
+
// URL state sync
|
|
136
|
+
useUrlState({
|
|
137
|
+
transportConfig: playground.transportConfig,
|
|
138
|
+
setTransportConfig: playground.setTransportConfig,
|
|
139
|
+
activeTab: playground.activeTab,
|
|
140
|
+
setActiveTab: playground.setActiveTab,
|
|
141
|
+
selectedToolName: playground.selectedTool?.name,
|
|
142
|
+
tools: playground.tools.tools,
|
|
143
|
+
setSelectedTool: playground.setSelectedTool,
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
// Local state
|
|
147
|
+
const [showSettings, setShowSettings] = useState(false);
|
|
148
|
+
const [showHistory, setShowHistory] = useState(false);
|
|
149
|
+
const [showFirstTimeGuide, setShowFirstTimeGuide] = useState(false);
|
|
150
|
+
const searchInputRef = useRef<HTMLInputElement>(null);
|
|
151
|
+
|
|
152
|
+
// Check if first time user
|
|
153
|
+
useEffect(() => {
|
|
154
|
+
if (typeof window !== 'undefined') {
|
|
155
|
+
const hasVisited = localStorage.getItem('mcp-playground-v2-visited');
|
|
156
|
+
if (!hasVisited) {
|
|
157
|
+
setShowFirstTimeGuide(true);
|
|
158
|
+
localStorage.setItem('mcp-playground-v2-visited', 'true');
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}, []);
|
|
162
|
+
|
|
163
|
+
// Keyboard shortcuts
|
|
164
|
+
const executeSelectedTool = useCallback(() => {
|
|
165
|
+
if (playground.selectedTool && playground.activeTab === 'tools') {
|
|
166
|
+
// Trigger execute via the ToolsPanel
|
|
167
|
+
// This is handled by the panel itself
|
|
168
|
+
}
|
|
169
|
+
}, [playground.selectedTool, playground.activeTab]);
|
|
170
|
+
|
|
171
|
+
const focusSearch = useCallback(() => {
|
|
172
|
+
searchInputRef.current?.focus();
|
|
173
|
+
}, []);
|
|
174
|
+
|
|
175
|
+
const clearSelection = useCallback(() => {
|
|
176
|
+
playground.setSelectedTool(null);
|
|
177
|
+
playground.setSelectedResource(null);
|
|
178
|
+
playground.setSelectedPrompt(null);
|
|
179
|
+
}, [playground]);
|
|
180
|
+
|
|
181
|
+
const copyLastResult = useCallback(() => {
|
|
182
|
+
const lastEntry = executionHistory.history[0];
|
|
183
|
+
if (lastEntry?.result) {
|
|
184
|
+
navigator.clipboard.writeText(JSON.stringify(lastEntry.result, null, 2));
|
|
185
|
+
}
|
|
186
|
+
}, [executionHistory.history]);
|
|
187
|
+
|
|
188
|
+
useShortcuts({
|
|
189
|
+
onExecute: executeSelectedTool,
|
|
190
|
+
onFocusSearch: focusSearch,
|
|
191
|
+
onSwitchToTab: (tab: 1 | 2 | 3) => {
|
|
192
|
+
if (tab === 1) playground.setActiveTab('tools');
|
|
193
|
+
else if (tab === 2) playground.setActiveTab('resources');
|
|
194
|
+
else if (tab === 3) playground.setActiveTab('prompts');
|
|
195
|
+
},
|
|
196
|
+
onClearSelection: clearSelection,
|
|
197
|
+
onCopyLastResult: copyLastResult,
|
|
198
|
+
enabled: true,
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
// Connection handlers
|
|
202
|
+
const handleConnect = useCallback(() => {
|
|
203
|
+
if (playground.transportConfig) {
|
|
204
|
+
playground.connection.connect(toHooksTransport(playground.transportConfig as unknown as ComponentTransportConfig));
|
|
205
|
+
}
|
|
206
|
+
}, [playground.transportConfig, playground.connection]);
|
|
207
|
+
|
|
208
|
+
const handleDisconnect = useCallback(() => {
|
|
209
|
+
playground.connection.disconnect();
|
|
210
|
+
}, [playground.connection]);
|
|
211
|
+
|
|
212
|
+
// Transport config change handler
|
|
213
|
+
const handleTransportChange = useCallback((config: ComponentTransportConfig) => {
|
|
214
|
+
playground.setTransportConfig(toHooksTransport(config));
|
|
215
|
+
}, [playground]);
|
|
216
|
+
|
|
217
|
+
// Tool execution handler - uses tool name to avoid type incompatibility
|
|
218
|
+
const handleToolExecute = useCallback((toolName: string, params: Record<string, unknown>) => {
|
|
219
|
+
playground.tools.executeTool(toolName, params);
|
|
220
|
+
}, [playground.tools]);
|
|
221
|
+
|
|
222
|
+
// Wrapper for ToolsPanel that adapts the type
|
|
223
|
+
const handleToolsPanelExecute = useCallback((tool: { name: string }, params: Record<string, unknown>) => {
|
|
224
|
+
handleToolExecute(tool.name, params);
|
|
225
|
+
}, [handleToolExecute]);
|
|
226
|
+
|
|
227
|
+
// Resource read handler
|
|
228
|
+
const handleResourceRead = useCallback((uri: string) => {
|
|
229
|
+
playground.resources.readResource(uri);
|
|
230
|
+
}, [playground.resources]);
|
|
231
|
+
|
|
232
|
+
// Prompt execute handler
|
|
233
|
+
const handlePromptExecute = useCallback((name: string, args?: Record<string, string>) => {
|
|
234
|
+
playground.prompts.getPrompt(name, args);
|
|
235
|
+
}, [playground.prompts]);
|
|
236
|
+
|
|
237
|
+
// Convert execution history to log entries
|
|
238
|
+
const logEntries = useMemo((): LogEntry[] => {
|
|
239
|
+
return executionHistory.history.map((entry, index) => ({
|
|
240
|
+
id: entry.id || `log-${index}`,
|
|
241
|
+
type: entry.success ? 'success' as const : 'error' as const,
|
|
242
|
+
message: `${entry.type}: ${entry.name}`,
|
|
243
|
+
timestamp: entry.timestamp,
|
|
244
|
+
data: entry.result || entry.error,
|
|
245
|
+
}));
|
|
246
|
+
}, [executionHistory.history]);
|
|
247
|
+
|
|
248
|
+
// Counts for capability tabs
|
|
249
|
+
const counts = useMemo(() => ({
|
|
250
|
+
tools: playground.tools.tools.length,
|
|
251
|
+
resources: playground.resources.resources.length,
|
|
252
|
+
prompts: playground.prompts.prompts.length,
|
|
253
|
+
}), [playground.tools.tools.length, playground.resources.resources.length, playground.prompts.prompts.length]);
|
|
254
|
+
|
|
255
|
+
// Last tool execution
|
|
256
|
+
const lastToolExecution = playground.tools.executions[0];
|
|
257
|
+
const toolLastResult = lastToolExecution?.result;
|
|
258
|
+
const toolLastError = lastToolExecution?.error;
|
|
259
|
+
const isToolExecuting = lastToolExecution?.status === 'pending' || lastToolExecution?.status === 'running';
|
|
260
|
+
|
|
261
|
+
// Last resource read
|
|
262
|
+
const lastResourceRead = playground.resources.reads[0];
|
|
263
|
+
const resourceLastContents = lastResourceRead?.contents;
|
|
264
|
+
const resourceLastError = lastResourceRead?.error;
|
|
265
|
+
const isResourceReading = lastResourceRead?.status === 'pending' || lastResourceRead?.status === 'loading';
|
|
266
|
+
|
|
267
|
+
// Last prompt execution
|
|
268
|
+
const lastPromptExecution = playground.prompts.executions[0];
|
|
269
|
+
const promptLastMessages = lastPromptExecution?.messages;
|
|
270
|
+
const promptLastError = lastPromptExecution?.error;
|
|
271
|
+
const isPromptExecuting = lastPromptExecution?.status === 'pending' || lastPromptExecution?.status === 'loading';
|
|
272
|
+
|
|
273
|
+
// Determine page state
|
|
274
|
+
const isConnected = playground.connection.status === 'connected';
|
|
275
|
+
const isConnecting = playground.connection.status === 'connecting';
|
|
276
|
+
const hasError = playground.connection.status === 'error';
|
|
277
|
+
|
|
278
|
+
return (
|
|
279
|
+
<main id="main-content" className="relative min-h-screen flex flex-col bg-black">
|
|
280
|
+
<ParticleBackground />
|
|
281
|
+
<Header />
|
|
282
|
+
|
|
283
|
+
<div className="container mx-auto px-4 pt-24 pb-8 flex-1 flex flex-col">
|
|
284
|
+
{/* Back link and actions */}
|
|
285
|
+
<motion.div
|
|
286
|
+
initial={{ opacity: 0, x: -20 }}
|
|
287
|
+
animate={{ opacity: 1, x: 0 }}
|
|
288
|
+
className="mb-6 flex items-center justify-between"
|
|
289
|
+
>
|
|
290
|
+
<Link
|
|
291
|
+
href="/"
|
|
292
|
+
className="inline-flex items-center gap-2 text-sm text-neutral-400 hover:text-white transition-colors"
|
|
293
|
+
>
|
|
294
|
+
<ArrowLeft className="w-4 h-4" />
|
|
295
|
+
Back to Home
|
|
296
|
+
</Link>
|
|
297
|
+
|
|
298
|
+
<div className="flex items-center gap-2">
|
|
299
|
+
<Button
|
|
300
|
+
onClick={() => setShowHistory(!showHistory)}
|
|
301
|
+
variant="outline"
|
|
302
|
+
size="sm"
|
|
303
|
+
className="gap-2"
|
|
304
|
+
>
|
|
305
|
+
<History className="w-4 h-4" />
|
|
306
|
+
<span className="hidden sm:inline">History</span>
|
|
307
|
+
</Button>
|
|
308
|
+
<ShareButton
|
|
309
|
+
transportConfig={toComponentTransport(playground.transportConfig)}
|
|
310
|
+
activeTab={playground.activeTab}
|
|
311
|
+
selectedToolName={playground.selectedTool?.name}
|
|
312
|
+
/>
|
|
313
|
+
</div>
|
|
314
|
+
</motion.div>
|
|
315
|
+
|
|
316
|
+
{/* Page header */}
|
|
317
|
+
<motion.div
|
|
318
|
+
initial={{ opacity: 0, y: 20 }}
|
|
319
|
+
animate={{ opacity: 1, y: 0 }}
|
|
320
|
+
className="text-center mb-8"
|
|
321
|
+
>
|
|
322
|
+
<div className="inline-flex items-center gap-2 px-4 py-2 rounded-full bg-white/5 border border-neutral-800 mb-6">
|
|
323
|
+
<Terminal className="w-4 h-4 text-white" />
|
|
324
|
+
<span className="text-sm font-medium text-neutral-400">
|
|
325
|
+
MCP <span className="text-white font-semibold">Playground</span>
|
|
326
|
+
</span>
|
|
327
|
+
<span className="ml-2 px-2 py-0.5 text-xs bg-green-500/20 text-green-400 rounded-full">
|
|
328
|
+
v2
|
|
329
|
+
</span>
|
|
330
|
+
</div>
|
|
331
|
+
|
|
332
|
+
<h1 className="text-4xl md:text-5xl font-bold text-white mb-4">
|
|
333
|
+
Interactive MCP Testing
|
|
334
|
+
</h1>
|
|
335
|
+
<p className="text-lg text-neutral-400 max-w-2xl mx-auto">
|
|
336
|
+
Connect to any MCP server and test tools, resources, and prompts interactively.
|
|
337
|
+
</p>
|
|
338
|
+
</motion.div>
|
|
339
|
+
|
|
340
|
+
{/* First time guide modal */}
|
|
341
|
+
<AnimatePresence>
|
|
342
|
+
{showFirstTimeGuide && (
|
|
343
|
+
<motion.div
|
|
344
|
+
initial={{ opacity: 0 }}
|
|
345
|
+
animate={{ opacity: 1 }}
|
|
346
|
+
exit={{ opacity: 0 }}
|
|
347
|
+
className="fixed inset-0 z-50 flex items-center justify-center p-4 bg-black/80 backdrop-blur-sm"
|
|
348
|
+
onClick={() => setShowFirstTimeGuide(false)}
|
|
349
|
+
>
|
|
350
|
+
<motion.div
|
|
351
|
+
initial={{ scale: 0.95, opacity: 0 }}
|
|
352
|
+
animate={{ scale: 1, opacity: 1 }}
|
|
353
|
+
exit={{ scale: 0.95, opacity: 0 }}
|
|
354
|
+
className="relative max-w-2xl w-full max-h-[80vh] overflow-y-auto bg-neutral-900 border border-neutral-800 rounded-xl"
|
|
355
|
+
onClick={(e) => e.stopPropagation()}
|
|
356
|
+
>
|
|
357
|
+
<button
|
|
358
|
+
onClick={() => setShowFirstTimeGuide(false)}
|
|
359
|
+
className="absolute top-4 right-4 text-neutral-400 hover:text-white"
|
|
360
|
+
>
|
|
361
|
+
<X className="w-5 h-5" />
|
|
362
|
+
</button>
|
|
363
|
+
<FirstTimeGuide onGetStarted={() => setShowFirstTimeGuide(false)} />
|
|
364
|
+
</motion.div>
|
|
365
|
+
</motion.div>
|
|
366
|
+
)}
|
|
367
|
+
</AnimatePresence>
|
|
368
|
+
|
|
369
|
+
{/* Main content area with optional sidebar */}
|
|
370
|
+
<div className="flex-1 flex flex-col lg:flex-row gap-6">
|
|
371
|
+
{/* Main panel */}
|
|
372
|
+
<div className="flex-1 flex flex-col gap-6 min-w-0">
|
|
373
|
+
{/* Connection Section */}
|
|
374
|
+
<motion.section
|
|
375
|
+
initial={{ opacity: 0, y: 20 }}
|
|
376
|
+
animate={{ opacity: 1, y: 0 }}
|
|
377
|
+
transition={{ delay: 0.1 }}
|
|
378
|
+
className="p-4 md:p-6 rounded-2xl border border-neutral-800 bg-neutral-900/50 backdrop-blur-xl"
|
|
379
|
+
>
|
|
380
|
+
<div className="flex flex-col gap-4">
|
|
381
|
+
<TransportConfigurator
|
|
382
|
+
value={toComponentTransport(playground.transportConfig)}
|
|
383
|
+
onChange={handleTransportChange}
|
|
384
|
+
disabled={isConnected || isConnecting}
|
|
385
|
+
/>
|
|
386
|
+
<ConnectionStatus
|
|
387
|
+
status={playground.connection.status}
|
|
388
|
+
sessionId={playground.connection.sessionId}
|
|
389
|
+
serverInfo={playground.connection.serverInfo}
|
|
390
|
+
capabilities={playground.connection.capabilities as AnyCapabilities}
|
|
391
|
+
error={playground.connection.error}
|
|
392
|
+
onConnect={handleConnect}
|
|
393
|
+
onDisconnect={handleDisconnect}
|
|
394
|
+
onDismissError={playground.connection.clearError}
|
|
395
|
+
/>
|
|
396
|
+
</div>
|
|
397
|
+
</motion.section>
|
|
398
|
+
|
|
399
|
+
{/* Capabilities Section */}
|
|
400
|
+
{isConnected ? (
|
|
401
|
+
<motion.section
|
|
402
|
+
initial={{ opacity: 0, y: 20 }}
|
|
403
|
+
animate={{ opacity: 1, y: 0 }}
|
|
404
|
+
transition={{ delay: 0.2 }}
|
|
405
|
+
className="flex-1 flex flex-col min-h-[400px] md:min-h-[500px] rounded-2xl border border-neutral-800 bg-neutral-900/50 backdrop-blur-xl overflow-hidden"
|
|
406
|
+
>
|
|
407
|
+
{/* Tabs */}
|
|
408
|
+
<div className="p-3 md:p-4 border-b border-neutral-800">
|
|
409
|
+
<CapabilityTabs
|
|
410
|
+
activeTab={playground.activeTab}
|
|
411
|
+
onTabChange={playground.setActiveTab}
|
|
412
|
+
capabilities={playground.connection.capabilities as AnyCapabilities}
|
|
413
|
+
counts={counts}
|
|
414
|
+
/>
|
|
415
|
+
</div>
|
|
416
|
+
|
|
417
|
+
{/* Tab Content */}
|
|
418
|
+
<div className="flex-1 overflow-hidden">
|
|
419
|
+
<AnimatePresence mode="wait">
|
|
420
|
+
{playground.activeTab === 'tools' && (
|
|
421
|
+
<motion.div
|
|
422
|
+
key="tools"
|
|
423
|
+
initial={{ opacity: 0, x: -10 }}
|
|
424
|
+
animate={{ opacity: 1, x: 0 }}
|
|
425
|
+
exit={{ opacity: 0, x: 10 }}
|
|
426
|
+
className="h-full"
|
|
427
|
+
>
|
|
428
|
+
{playground.tools.tools.length > 0 ? (
|
|
429
|
+
<ToolsPanel
|
|
430
|
+
tools={playground.tools.tools as AnyTool[]}
|
|
431
|
+
selectedTool={playground.selectedTool as AnyTool}
|
|
432
|
+
onSelectTool={(tool: AnyTool) => playground.setSelectedTool(tool)}
|
|
433
|
+
onExecute={handleToolsPanelExecute}
|
|
434
|
+
isExecuting={isToolExecuting}
|
|
435
|
+
lastResult={toolLastResult}
|
|
436
|
+
lastError={toolLastError}
|
|
437
|
+
/>
|
|
438
|
+
) : (
|
|
439
|
+
<EmptyStates type="no-tools" />
|
|
440
|
+
)}
|
|
441
|
+
</motion.div>
|
|
442
|
+
)}
|
|
443
|
+
|
|
444
|
+
{playground.activeTab === 'resources' && (
|
|
445
|
+
<motion.div
|
|
446
|
+
key="resources"
|
|
447
|
+
initial={{ opacity: 0, x: -10 }}
|
|
448
|
+
animate={{ opacity: 1, x: 0 }}
|
|
449
|
+
exit={{ opacity: 0, x: 10 }}
|
|
450
|
+
className="h-full"
|
|
451
|
+
>
|
|
452
|
+
{playground.resources.resources.length > 0 ? (
|
|
453
|
+
<ResourcesPanel
|
|
454
|
+
resources={playground.resources.resources as AnyResource[]}
|
|
455
|
+
selectedResource={playground.selectedResource as AnyResource}
|
|
456
|
+
onSelectResource={(res: AnyResource) => playground.setSelectedResource(res)}
|
|
457
|
+
onRead={handleResourceRead}
|
|
458
|
+
isReading={isResourceReading}
|
|
459
|
+
lastContents={resourceLastContents as any}
|
|
460
|
+
lastError={resourceLastError}
|
|
461
|
+
/>
|
|
462
|
+
) : (
|
|
463
|
+
<EmptyStates type="no-resources" />
|
|
464
|
+
)}
|
|
465
|
+
</motion.div>
|
|
466
|
+
)}
|
|
467
|
+
|
|
468
|
+
{playground.activeTab === 'prompts' && (
|
|
469
|
+
<motion.div
|
|
470
|
+
key="prompts"
|
|
471
|
+
initial={{ opacity: 0, x: -10 }}
|
|
472
|
+
animate={{ opacity: 1, x: 0 }}
|
|
473
|
+
exit={{ opacity: 0, x: 10 }}
|
|
474
|
+
className="h-full"
|
|
475
|
+
>
|
|
476
|
+
{playground.prompts.prompts.length > 0 ? (
|
|
477
|
+
<PromptsPanel
|
|
478
|
+
prompts={playground.prompts.prompts as AnyPrompt[]}
|
|
479
|
+
selectedPrompt={playground.selectedPrompt as AnyPrompt}
|
|
480
|
+
onSelectPrompt={(prompt: AnyPrompt) => playground.setSelectedPrompt(prompt)}
|
|
481
|
+
onExecute={handlePromptExecute}
|
|
482
|
+
isExecuting={isPromptExecuting}
|
|
483
|
+
lastMessages={promptLastMessages as any}
|
|
484
|
+
lastError={promptLastError}
|
|
485
|
+
/>
|
|
486
|
+
) : (
|
|
487
|
+
<EmptyStates type="no-prompts" />
|
|
488
|
+
)}
|
|
489
|
+
</motion.div>
|
|
490
|
+
)}
|
|
491
|
+
</AnimatePresence>
|
|
492
|
+
</div>
|
|
493
|
+
</motion.section>
|
|
494
|
+
) : (
|
|
495
|
+
<motion.section
|
|
496
|
+
initial={{ opacity: 0, y: 20 }}
|
|
497
|
+
animate={{ opacity: 1, y: 0 }}
|
|
498
|
+
transition={{ delay: 0.2 }}
|
|
499
|
+
className="flex-1 flex items-center justify-center min-h-[400px] rounded-2xl border border-neutral-800 bg-neutral-900/50 backdrop-blur-xl"
|
|
500
|
+
>
|
|
501
|
+
<EmptyStates
|
|
502
|
+
type="not-connected"
|
|
503
|
+
onAction={playground.transportConfig ? handleConnect : undefined}
|
|
504
|
+
/>
|
|
505
|
+
</motion.section>
|
|
506
|
+
)}
|
|
507
|
+
</div>
|
|
508
|
+
|
|
509
|
+
{/* History sidebar - desktop */}
|
|
510
|
+
<AnimatePresence>
|
|
511
|
+
{showHistory && (
|
|
512
|
+
<motion.aside
|
|
513
|
+
initial={{ opacity: 0, x: 20 }}
|
|
514
|
+
animate={{ opacity: 1, x: 0 }}
|
|
515
|
+
exit={{ opacity: 0, x: 20 }}
|
|
516
|
+
className="hidden lg:block w-80 flex-shrink-0"
|
|
517
|
+
>
|
|
518
|
+
<div className="sticky top-24 rounded-2xl border border-neutral-800 bg-neutral-900/50 backdrop-blur-xl overflow-hidden">
|
|
519
|
+
<div className="p-4 border-b border-neutral-800 flex items-center justify-between">
|
|
520
|
+
<h3 className="font-semibold text-white flex items-center gap-2">
|
|
521
|
+
<History className="w-4 h-4" />
|
|
522
|
+
Execution History
|
|
523
|
+
</h3>
|
|
524
|
+
<Button
|
|
525
|
+
onClick={executionHistory.clear}
|
|
526
|
+
variant="ghost"
|
|
527
|
+
size="sm"
|
|
528
|
+
className="text-neutral-400 hover:text-white"
|
|
529
|
+
>
|
|
530
|
+
Clear
|
|
531
|
+
</Button>
|
|
532
|
+
</div>
|
|
533
|
+
<ExecutionLog
|
|
534
|
+
entries={logEntries}
|
|
535
|
+
maxHeight={500}
|
|
536
|
+
onClear={executionHistory.clear}
|
|
537
|
+
/>
|
|
538
|
+
</div>
|
|
539
|
+
</motion.aside>
|
|
540
|
+
)}
|
|
541
|
+
</AnimatePresence>
|
|
542
|
+
</div>
|
|
543
|
+
|
|
544
|
+
{/* Mobile history panel */}
|
|
545
|
+
<AnimatePresence>
|
|
546
|
+
{showHistory && (
|
|
547
|
+
<motion.div
|
|
548
|
+
initial={{ opacity: 0, y: 20 }}
|
|
549
|
+
animate={{ opacity: 1, y: 0 }}
|
|
550
|
+
exit={{ opacity: 0, y: 20 }}
|
|
551
|
+
className="lg:hidden mt-6"
|
|
552
|
+
>
|
|
553
|
+
<div className="rounded-2xl border border-neutral-800 bg-neutral-900/50 backdrop-blur-xl overflow-hidden">
|
|
554
|
+
<div className="p-4 border-b border-neutral-800 flex items-center justify-between">
|
|
555
|
+
<h3 className="font-semibold text-white flex items-center gap-2">
|
|
556
|
+
<History className="w-4 h-4" />
|
|
557
|
+
Execution History
|
|
558
|
+
</h3>
|
|
559
|
+
<div className="flex items-center gap-2">
|
|
560
|
+
<Button
|
|
561
|
+
onClick={executionHistory.clear}
|
|
562
|
+
variant="ghost"
|
|
563
|
+
size="sm"
|
|
564
|
+
className="text-neutral-400 hover:text-white"
|
|
565
|
+
>
|
|
566
|
+
Clear
|
|
567
|
+
</Button>
|
|
568
|
+
<Button
|
|
569
|
+
onClick={() => setShowHistory(false)}
|
|
570
|
+
variant="ghost"
|
|
571
|
+
size="sm"
|
|
572
|
+
>
|
|
573
|
+
<X className="w-4 h-4" />
|
|
574
|
+
</Button>
|
|
575
|
+
</div>
|
|
576
|
+
</div>
|
|
577
|
+
<ExecutionLog
|
|
578
|
+
entries={logEntries}
|
|
579
|
+
maxHeight={300}
|
|
580
|
+
onClear={executionHistory.clear}
|
|
581
|
+
/>
|
|
582
|
+
</div>
|
|
583
|
+
</motion.div>
|
|
584
|
+
)}
|
|
585
|
+
</AnimatePresence>
|
|
586
|
+
</div>
|
|
587
|
+
|
|
588
|
+
<Footer />
|
|
589
|
+
</main>
|
|
590
|
+
);
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
// ============================================================================
|
|
594
|
+
// Page Export
|
|
595
|
+
// ============================================================================
|
|
596
|
+
|
|
597
|
+
export default function PlaygroundV2Page() {
|
|
598
|
+
return (
|
|
599
|
+
<Suspense fallback={<PlaygroundSkeleton />}>
|
|
600
|
+
<PlaygroundV2Content />
|
|
601
|
+
</Suspense>
|
|
602
|
+
);
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
// ============================================================================
|
|
606
|
+
// Skeleton Component
|
|
607
|
+
// ============================================================================
|
|
608
|
+
|
|
609
|
+
function PlaygroundSkeleton() {
|
|
610
|
+
return (
|
|
611
|
+
<main className="relative min-h-screen flex flex-col bg-black">
|
|
612
|
+
<div className="container mx-auto px-4 pt-24 pb-8 flex-1">
|
|
613
|
+
{/* Header skeleton */}
|
|
614
|
+
<div className="text-center mb-8">
|
|
615
|
+
<div className="h-8 w-48 bg-neutral-800 rounded-full mx-auto mb-6 animate-pulse" />
|
|
616
|
+
<div className="h-12 w-96 bg-neutral-800 rounded mx-auto mb-4 animate-pulse" />
|
|
617
|
+
<div className="h-6 w-80 bg-neutral-800 rounded mx-auto animate-pulse" />
|
|
618
|
+
</div>
|
|
619
|
+
|
|
620
|
+
{/* Connection section skeleton */}
|
|
621
|
+
<div className="p-6 rounded-2xl border border-neutral-800 bg-neutral-900/50 mb-6">
|
|
622
|
+
<div className="flex flex-col lg:flex-row gap-6">
|
|
623
|
+
<div className="flex-1 space-y-4">
|
|
624
|
+
<div className="h-10 bg-neutral-800 rounded animate-pulse" />
|
|
625
|
+
<div className="h-10 bg-neutral-800 rounded animate-pulse" />
|
|
626
|
+
</div>
|
|
627
|
+
<div className="lg:w-80 h-32 bg-neutral-800 rounded animate-pulse" />
|
|
628
|
+
</div>
|
|
629
|
+
</div>
|
|
630
|
+
|
|
631
|
+
{/* Main content skeleton */}
|
|
632
|
+
<div className="min-h-[500px] rounded-2xl border border-neutral-800 bg-neutral-900/50 p-6">
|
|
633
|
+
<div className="h-10 w-64 bg-neutral-800 rounded mb-6 animate-pulse" />
|
|
634
|
+
<div className="grid grid-cols-2 gap-4">
|
|
635
|
+
<div className="h-24 bg-neutral-800 rounded animate-pulse" />
|
|
636
|
+
<div className="h-24 bg-neutral-800 rounded animate-pulse" />
|
|
637
|
+
<div className="h-24 bg-neutral-800 rounded animate-pulse" />
|
|
638
|
+
<div className="h-24 bg-neutral-800 rounded animate-pulse" />
|
|
639
|
+
</div>
|
|
640
|
+
</div>
|
|
641
|
+
</div>
|
|
642
|
+
</main>
|
|
643
|
+
);
|
|
644
|
+
}
|