@amplitude/wizard 1.0.0-beta.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/LICENSE +47 -0
- package/README.md +119 -0
- package/dist/bin.d.ts +2 -0
- package/dist/bin.js +763 -0
- package/dist/package.json +144 -0
- package/dist/src/frameworks/android/android-wizard-agent.d.ts +6 -0
- package/dist/src/frameworks/android/android-wizard-agent.js +72 -0
- package/dist/src/frameworks/android/utils.d.ts +11 -0
- package/dist/src/frameworks/android/utils.js +32 -0
- package/dist/src/frameworks/django/django-wizard-agent.d.ts +8 -0
- package/dist/src/frameworks/django/django-wizard-agent.js +171 -0
- package/dist/src/frameworks/django/utils.d.ts +31 -0
- package/dist/src/frameworks/django/utils.js +305 -0
- package/dist/src/frameworks/fastapi/fastapi-wizard-agent.d.ts +11 -0
- package/dist/src/frameworks/fastapi/fastapi-wizard-agent.js +189 -0
- package/dist/src/frameworks/fastapi/utils.d.ts +26 -0
- package/dist/src/frameworks/fastapi/utils.js +257 -0
- package/dist/src/frameworks/flask/flask-wizard-agent.d.ts +8 -0
- package/dist/src/frameworks/flask/flask-wizard-agent.js +177 -0
- package/dist/src/frameworks/flask/utils.d.ts +28 -0
- package/dist/src/frameworks/flask/utils.js +343 -0
- package/dist/src/frameworks/flutter/flutter-wizard-agent.d.ts +4 -0
- package/dist/src/frameworks/flutter/flutter-wizard-agent.js +57 -0
- package/dist/src/frameworks/flutter/utils.d.ts +7 -0
- package/dist/src/frameworks/flutter/utils.js +64 -0
- package/dist/src/frameworks/generic/generic-wizard-agent.d.ts +2 -0
- package/dist/src/frameworks/generic/generic-wizard-agent.js +176 -0
- package/dist/src/frameworks/go/go-wizard-agent.d.ts +4 -0
- package/dist/src/frameworks/go/go-wizard-agent.js +57 -0
- package/dist/src/frameworks/go/utils.d.ts +5 -0
- package/dist/src/frameworks/go/utils.js +44 -0
- package/dist/src/frameworks/java/java-wizard-agent.d.ts +7 -0
- package/dist/src/frameworks/java/java-wizard-agent.js +73 -0
- package/dist/src/frameworks/java/utils.d.ts +15 -0
- package/dist/src/frameworks/java/utils.js +64 -0
- package/dist/src/frameworks/javascript-node/javascript-node-wizard-agent.d.ts +4 -0
- package/dist/src/frameworks/javascript-node/javascript-node-wizard-agent.js +57 -0
- package/dist/src/frameworks/javascript-web/javascript-web-wizard-agent.d.ts +3 -0
- package/dist/src/frameworks/javascript-web/javascript-web-wizard-agent.js +151 -0
- package/dist/src/frameworks/javascript-web/utils.d.ts +28 -0
- package/dist/src/frameworks/javascript-web/utils.js +153 -0
- package/dist/src/frameworks/nextjs/nextjs-wizard-agent.d.ts +7 -0
- package/dist/src/frameworks/nextjs/nextjs-wizard-agent.js +98 -0
- package/dist/src/frameworks/nextjs/utils.d.ts +12 -0
- package/dist/src/frameworks/nextjs/utils.js +51 -0
- package/dist/src/frameworks/python/python-wizard-agent.d.ts +7 -0
- package/dist/src/frameworks/python/python-wizard-agent.js +193 -0
- package/dist/src/frameworks/python/utils.d.ts +28 -0
- package/dist/src/frameworks/python/utils.js +146 -0
- package/dist/src/frameworks/react-native/react-native-wizard-agent.d.ts +6 -0
- package/dist/src/frameworks/react-native/react-native-wizard-agent.js +84 -0
- package/dist/src/frameworks/react-native/utils.d.ts +21 -0
- package/dist/src/frameworks/react-native/utils.js +82 -0
- package/dist/src/frameworks/react-router/react-router-wizard-agent.d.ts +7 -0
- package/dist/src/frameworks/react-router/react-router-wizard-agent.js +98 -0
- package/dist/src/frameworks/react-router/utils.d.ts +13 -0
- package/dist/src/frameworks/react-router/utils.js +160 -0
- package/dist/src/frameworks/swift/swift-wizard-agent.d.ts +7 -0
- package/dist/src/frameworks/swift/swift-wizard-agent.js +72 -0
- package/dist/src/frameworks/swift/utils.d.ts +12 -0
- package/dist/src/frameworks/swift/utils.js +82 -0
- package/dist/src/frameworks/unity/unity-wizard-agent.d.ts +6 -0
- package/dist/src/frameworks/unity/unity-wizard-agent.js +79 -0
- package/dist/src/frameworks/unity/utils.d.ts +12 -0
- package/dist/src/frameworks/unity/utils.js +66 -0
- package/dist/src/frameworks/unreal/unreal-wizard-agent.d.ts +6 -0
- package/dist/src/frameworks/unreal/unreal-wizard-agent.js +77 -0
- package/dist/src/frameworks/unreal/utils.d.ts +10 -0
- package/dist/src/frameworks/unreal/utils.js +29 -0
- package/dist/src/frameworks/vue/vue-wizard-agent.d.ts +4 -0
- package/dist/src/frameworks/vue/vue-wizard-agent.js +64 -0
- package/dist/src/lib/agent-hooks.d.ts +26 -0
- package/dist/src/lib/agent-hooks.js +118 -0
- package/dist/src/lib/agent-interface.d.ts +175 -0
- package/dist/src/lib/agent-interface.js +1217 -0
- package/dist/src/lib/agent-runner.d.ts +9 -0
- package/dist/src/lib/agent-runner.js +415 -0
- package/dist/src/lib/ampli-config.d.ts +105 -0
- package/dist/src/lib/ampli-config.js +178 -0
- package/dist/src/lib/api.d.ts +107 -0
- package/dist/src/lib/api.js +442 -0
- package/dist/src/lib/commandments.d.ts +1 -0
- package/dist/src/lib/commandments.js +24 -0
- package/dist/src/lib/console-query.d.ts +27 -0
- package/dist/src/lib/console-query.js +121 -0
- package/dist/src/lib/constants.d.ts +124 -0
- package/dist/src/lib/constants.js +170 -0
- package/dist/src/lib/detect-amplitude.d.ts +31 -0
- package/dist/src/lib/detect-amplitude.js +407 -0
- package/dist/src/lib/framework-config.d.ts +188 -0
- package/dist/src/lib/framework-config.js +21 -0
- package/dist/src/lib/health-checks/endpoints.d.ts +3 -0
- package/dist/src/lib/health-checks/endpoints.js +45 -0
- package/dist/src/lib/health-checks/index.d.ts +4 -0
- package/dist/src/lib/health-checks/index.js +22 -0
- package/dist/src/lib/health-checks/readiness.d.ts +24 -0
- package/dist/src/lib/health-checks/readiness.js +118 -0
- package/dist/src/lib/health-checks/statuspage.d.ts +9 -0
- package/dist/src/lib/health-checks/statuspage.js +104 -0
- package/dist/src/lib/health-checks/types.d.ts +31 -0
- package/dist/src/lib/health-checks/types.js +9 -0
- package/dist/src/lib/helper-functions.d.ts +1 -0
- package/dist/src/lib/helper-functions.js +5 -0
- package/dist/src/lib/middleware/benchmark.d.ts +54 -0
- package/dist/src/lib/middleware/benchmark.js +48 -0
- package/dist/src/lib/middleware/benchmarks/cache-tracker.d.ts +44 -0
- package/dist/src/lib/middleware/benchmarks/cache-tracker.js +80 -0
- package/dist/src/lib/middleware/benchmarks/compaction-tracker.d.ts +29 -0
- package/dist/src/lib/middleware/benchmarks/compaction-tracker.js +59 -0
- package/dist/src/lib/middleware/benchmarks/context-size-tracker.d.ts +26 -0
- package/dist/src/lib/middleware/benchmarks/context-size-tracker.js +55 -0
- package/dist/src/lib/middleware/benchmarks/cost-tracker.d.ts +16 -0
- package/dist/src/lib/middleware/benchmarks/cost-tracker.js +75 -0
- package/dist/src/lib/middleware/benchmarks/duration-tracker.d.ts +20 -0
- package/dist/src/lib/middleware/benchmarks/duration-tracker.js +39 -0
- package/dist/src/lib/middleware/benchmarks/index.d.ts +9 -0
- package/dist/src/lib/middleware/benchmarks/index.js +67 -0
- package/dist/src/lib/middleware/benchmarks/json-writer.d.ts +15 -0
- package/dist/src/lib/middleware/benchmarks/json-writer.js +144 -0
- package/dist/src/lib/middleware/benchmarks/summary.d.ts +9 -0
- package/dist/src/lib/middleware/benchmarks/summary.js +105 -0
- package/dist/src/lib/middleware/benchmarks/token-tracker.d.ts +40 -0
- package/dist/src/lib/middleware/benchmarks/token-tracker.js +76 -0
- package/dist/src/lib/middleware/benchmarks/turn-counter.d.ts +34 -0
- package/dist/src/lib/middleware/benchmarks/turn-counter.js +58 -0
- package/dist/src/lib/middleware/config.d.ts +24 -0
- package/dist/src/lib/middleware/config.js +96 -0
- package/dist/src/lib/middleware/index.d.ts +11 -0
- package/dist/src/lib/middleware/index.js +17 -0
- package/dist/src/lib/middleware/phase-detector.d.ts +8 -0
- package/dist/src/lib/middleware/phase-detector.js +63 -0
- package/dist/src/lib/middleware/pipeline.d.ts +29 -0
- package/dist/src/lib/middleware/pipeline.js +81 -0
- package/dist/src/lib/middleware/schemas.d.ts +27 -0
- package/dist/src/lib/middleware/schemas.js +84 -0
- package/dist/src/lib/middleware/types.d.ts +94 -0
- package/dist/src/lib/middleware/types.js +8 -0
- package/dist/src/lib/package-manager-detection.d.ts +42 -0
- package/dist/src/lib/package-manager-detection.js +292 -0
- package/dist/src/lib/registry.d.ts +3 -0
- package/dist/src/lib/registry.js +42 -0
- package/dist/src/lib/safe-tools.d.ts +2 -0
- package/dist/src/lib/safe-tools.js +214 -0
- package/dist/src/lib/wizard-session.d.ts +220 -0
- package/dist/src/lib/wizard-session.js +127 -0
- package/dist/src/lib/wizard-tools.d.ts +82 -0
- package/dist/src/lib/wizard-tools.js +499 -0
- package/dist/src/run.d.ts +19 -0
- package/dist/src/run.js +151 -0
- package/dist/src/steps/add-mcp-server-to-clients/MCPClient.d.ts +30 -0
- package/dist/src/steps/add-mcp-server-to-clients/MCPClient.js +141 -0
- package/dist/src/steps/add-mcp-server-to-clients/clients/claude-code.d.ts +29 -0
- package/dist/src/steps/add-mcp-server-to-clients/clients/claude-code.js +180 -0
- package/dist/src/steps/add-mcp-server-to-clients/clients/claude.d.ts +20 -0
- package/dist/src/steps/add-mcp-server-to-clients/clients/claude.js +63 -0
- package/dist/src/steps/add-mcp-server-to-clients/clients/codex.d.ts +28 -0
- package/dist/src/steps/add-mcp-server-to-clients/clients/codex.js +77 -0
- package/dist/src/steps/add-mcp-server-to-clients/clients/cursor.d.ts +24 -0
- package/dist/src/steps/add-mcp-server-to-clients/clients/cursor.js +60 -0
- package/dist/src/steps/add-mcp-server-to-clients/clients/visual-studio-code.d.ts +27 -0
- package/dist/src/steps/add-mcp-server-to-clients/clients/visual-studio-code.js +101 -0
- package/dist/src/steps/add-mcp-server-to-clients/clients/zed.d.ts +26 -0
- package/dist/src/steps/add-mcp-server-to-clients/clients/zed.js +102 -0
- package/dist/src/steps/add-mcp-server-to-clients/defaults.d.ts +44 -0
- package/dist/src/steps/add-mcp-server-to-clients/defaults.js +123 -0
- package/dist/src/steps/add-mcp-server-to-clients/index.d.ts +19 -0
- package/dist/src/steps/add-mcp-server-to-clients/index.js +110 -0
- package/dist/src/steps/add-or-update-environment-variables.d.ts +10 -0
- package/dist/src/steps/add-or-update-environment-variables.js +188 -0
- package/dist/src/steps/index.d.ts +4 -0
- package/dist/src/steps/index.js +20 -0
- package/dist/src/steps/run-prettier.d.ts +5 -0
- package/dist/src/steps/run-prettier.js +90 -0
- package/dist/src/steps/upload-environment-variables/EnvironmentProvider.d.ts +11 -0
- package/dist/src/steps/upload-environment-variables/EnvironmentProvider.js +11 -0
- package/dist/src/steps/upload-environment-variables/index.d.ts +6 -0
- package/dist/src/steps/upload-environment-variables/index.js +37 -0
- package/dist/src/steps/upload-environment-variables/providers/vercel.d.ts +15 -0
- package/dist/src/steps/upload-environment-variables/providers/vercel.js +145 -0
- package/dist/src/telemetry.d.ts +2 -0
- package/dist/src/telemetry.js +12 -0
- package/dist/src/ui/index.d.ts +8 -0
- package/dist/src/ui/index.js +16 -0
- package/dist/src/ui/logging-ui.d.ts +56 -0
- package/dist/src/ui/logging-ui.js +157 -0
- package/dist/src/ui/tui/App.d.ts +6 -0
- package/dist/src/ui/tui/App.js +34 -0
- package/dist/src/ui/tui/components/AmplitudeLogo.d.ts +5 -0
- package/dist/src/ui/tui/components/AmplitudeLogo.js +81 -0
- package/dist/src/ui/tui/components/AmplitudeTextLogo.d.ts +3 -0
- package/dist/src/ui/tui/components/AmplitudeTextLogo.js +31 -0
- package/dist/src/ui/tui/components/ConsoleView.d.ts +23 -0
- package/dist/src/ui/tui/components/ConsoleView.js +220 -0
- package/dist/src/ui/tui/components/TitleBar.d.ts +6 -0
- package/dist/src/ui/tui/components/TitleBar.js +16 -0
- package/dist/src/ui/tui/console-commands.d.ts +16 -0
- package/dist/src/ui/tui/console-commands.js +31 -0
- package/dist/src/ui/tui/context/CommandModeContext.d.ts +2 -0
- package/dist/src/ui/tui/context/CommandModeContext.js +3 -0
- package/dist/src/ui/tui/flows.d.ts +48 -0
- package/dist/src/ui/tui/flows.js +154 -0
- package/dist/src/ui/tui/hooks/useScreenInput.d.ts +13 -0
- package/dist/src/ui/tui/hooks/useScreenInput.js +18 -0
- package/dist/src/ui/tui/hooks/useStdoutDimensions.d.ts +9 -0
- package/dist/src/ui/tui/hooks/useStdoutDimensions.js +29 -0
- package/dist/src/ui/tui/ink-ui.d.ts +62 -0
- package/dist/src/ui/tui/ink-ui.js +142 -0
- package/dist/src/ui/tui/primitives/CardLayout.d.ts +12 -0
- package/dist/src/ui/tui/primitives/CardLayout.js +9 -0
- package/dist/src/ui/tui/primitives/ConfirmationInput.d.ts +13 -0
- package/dist/src/ui/tui/primitives/ConfirmationInput.js +35 -0
- package/dist/src/ui/tui/primitives/DissolveTransition.d.ts +21 -0
- package/dist/src/ui/tui/primitives/DissolveTransition.js +143 -0
- package/dist/src/ui/tui/primitives/EventPlanViewer.d.ts +9 -0
- package/dist/src/ui/tui/primitives/EventPlanViewer.js +9 -0
- package/dist/src/ui/tui/primitives/KagiSmallWebViewer.d.ts +7 -0
- package/dist/src/ui/tui/primitives/KagiSmallWebViewer.js +101 -0
- package/dist/src/ui/tui/primitives/LoadingBox.d.ts +8 -0
- package/dist/src/ui/tui/primitives/LoadingBox.js +9 -0
- package/dist/src/ui/tui/primitives/LogViewer.d.ts +11 -0
- package/dist/src/ui/tui/primitives/LogViewer.js +55 -0
- package/dist/src/ui/tui/primitives/PickerMenu.d.ts +20 -0
- package/dist/src/ui/tui/primitives/PickerMenu.js +212 -0
- package/dist/src/ui/tui/primitives/ProgressList.d.ts +15 -0
- package/dist/src/ui/tui/primitives/ProgressList.js +29 -0
- package/dist/src/ui/tui/primitives/PromptLabel.d.ts +11 -0
- package/dist/src/ui/tui/primitives/PromptLabel.js +12 -0
- package/dist/src/ui/tui/primitives/ReportViewer.d.ts +12 -0
- package/dist/src/ui/tui/primitives/ReportViewer.js +99 -0
- package/dist/src/ui/tui/primitives/ScreenErrorBoundary.d.ts +26 -0
- package/dist/src/ui/tui/primitives/ScreenErrorBoundary.js +29 -0
- package/dist/src/ui/tui/primitives/SlashCommandInput.d.ts +21 -0
- package/dist/src/ui/tui/primitives/SlashCommandInput.js +85 -0
- package/dist/src/ui/tui/primitives/SnakeGame.d.ts +1 -0
- package/dist/src/ui/tui/primitives/SnakeGame.js +1 -0
- package/dist/src/ui/tui/primitives/SplitView.d.ts +11 -0
- package/dist/src/ui/tui/primitives/SplitView.js +8 -0
- package/dist/src/ui/tui/primitives/TabContainer.d.ts +18 -0
- package/dist/src/ui/tui/primitives/TabContainer.js +30 -0
- package/dist/src/ui/tui/primitives/index.d.ts +23 -0
- package/dist/src/ui/tui/primitives/index.js +19 -0
- package/dist/src/ui/tui/router.d.ts +61 -0
- package/dist/src/ui/tui/router.js +104 -0
- package/dist/src/ui/tui/screen-registry.d.ts +19 -0
- package/dist/src/ui/tui/screen-registry.js +56 -0
- package/dist/src/ui/tui/screens/ActivationOptionsScreen.d.ts +12 -0
- package/dist/src/ui/tui/screens/ActivationOptionsScreen.js +57 -0
- package/dist/src/ui/tui/screens/AuthScreen.d.ts +18 -0
- package/dist/src/ui/tui/screens/AuthScreen.js +107 -0
- package/dist/src/ui/tui/screens/ChecklistScreen.d.ts +22 -0
- package/dist/src/ui/tui/screens/ChecklistScreen.js +122 -0
- package/dist/src/ui/tui/screens/DataIngestionCheckScreen.d.ts +24 -0
- package/dist/src/ui/tui/screens/DataIngestionCheckScreen.js +113 -0
- package/dist/src/ui/tui/screens/DataSetupScreen.d.ts +17 -0
- package/dist/src/ui/tui/screens/DataSetupScreen.js +73 -0
- package/dist/src/ui/tui/screens/IntroScreen.d.ts +16 -0
- package/dist/src/ui/tui/screens/IntroScreen.js +86 -0
- package/dist/src/ui/tui/screens/LoginScreen.d.ts +15 -0
- package/dist/src/ui/tui/screens/LoginScreen.js +65 -0
- package/dist/src/ui/tui/screens/LogoutScreen.d.ts +12 -0
- package/dist/src/ui/tui/screens/LogoutScreen.js +28 -0
- package/dist/src/ui/tui/screens/McpScreen.d.ts +26 -0
- package/dist/src/ui/tui/screens/McpScreen.js +148 -0
- package/dist/src/ui/tui/screens/OutageScreen.d.ts +10 -0
- package/dist/src/ui/tui/screens/OutageScreen.js +17 -0
- package/dist/src/ui/tui/screens/OutroScreen.d.ts +11 -0
- package/dist/src/ui/tui/screens/OutroScreen.js +69 -0
- package/dist/src/ui/tui/screens/RegionSelectScreen.d.ts +17 -0
- package/dist/src/ui/tui/screens/RegionSelectScreen.js +40 -0
- package/dist/src/ui/tui/screens/RunScreen.d.ts +16 -0
- package/dist/src/ui/tui/screens/RunScreen.js +212 -0
- package/dist/src/ui/tui/screens/SettingsOverrideScreen.d.ts +10 -0
- package/dist/src/ui/tui/screens/SettingsOverrideScreen.js +23 -0
- package/dist/src/ui/tui/screens/SetupScreen.d.ts +13 -0
- package/dist/src/ui/tui/screens/SetupScreen.js +73 -0
- package/dist/src/ui/tui/screens/SlackScreen.d.ts +25 -0
- package/dist/src/ui/tui/screens/SlackScreen.js +97 -0
- package/dist/src/ui/tui/services/mcp-installer.d.ts +25 -0
- package/dist/src/ui/tui/services/mcp-installer.js +82 -0
- package/dist/src/ui/tui/start-tui.d.ts +10 -0
- package/dist/src/ui/tui/start-tui.js +50 -0
- package/dist/src/ui/tui/store.d.ts +231 -0
- package/dist/src/ui/tui/store.js +568 -0
- package/dist/src/ui/tui/styles.d.ts +31 -0
- package/dist/src/ui/tui/styles.js +33 -0
- package/dist/src/ui/wizard-ui.d.ts +110 -0
- package/dist/src/ui/wizard-ui.js +18 -0
- package/dist/src/utils/ampli-settings.d.ts +37 -0
- package/dist/src/utils/ampli-settings.js +182 -0
- package/dist/src/utils/analytics.d.ts +35 -0
- package/dist/src/utils/analytics.js +133 -0
- package/dist/src/utils/anthropic-status.d.ts +17 -0
- package/dist/src/utils/anthropic-status.js +51 -0
- package/dist/src/utils/api-key-store.d.ts +35 -0
- package/dist/src/utils/api-key-store.js +176 -0
- package/dist/src/utils/bash.d.ts +2 -0
- package/dist/src/utils/bash.js +53 -0
- package/dist/src/utils/custom-headers.d.ts +9 -0
- package/dist/src/utils/custom-headers.js +23 -0
- package/dist/src/utils/debug.d.ts +23 -0
- package/dist/src/utils/debug.js +86 -0
- package/dist/src/utils/environment.d.ts +4 -0
- package/dist/src/utils/environment.js +76 -0
- package/dist/src/utils/file-utils.d.ts +2 -0
- package/dist/src/utils/file-utils.js +16 -0
- package/dist/src/utils/get-api-key.d.ts +17 -0
- package/dist/src/utils/get-api-key.js +50 -0
- package/dist/src/utils/logging.d.ts +9 -0
- package/dist/src/utils/logging.js +48 -0
- package/dist/src/utils/oauth.d.ts +53 -0
- package/dist/src/utils/oauth.js +354 -0
- package/dist/src/utils/package-json.d.ts +25 -0
- package/dist/src/utils/package-json.js +26 -0
- package/dist/src/utils/package-manager.d.ts +21 -0
- package/dist/src/utils/package-manager.js +208 -0
- package/dist/src/utils/semver.d.ts +21 -0
- package/dist/src/utils/semver.js +61 -0
- package/dist/src/utils/setup-utils.d.ts +82 -0
- package/dist/src/utils/setup-utils.js +467 -0
- package/dist/src/utils/shell-completions.d.ts +10 -0
- package/dist/src/utils/shell-completions.js +199 -0
- package/dist/src/utils/string.d.ts +1 -0
- package/dist/src/utils/string.js +8 -0
- package/dist/src/utils/types.d.ts +72 -0
- package/dist/src/utils/types.js +2 -0
- package/dist/src/utils/urls.d.ts +14 -0
- package/dist/src/utils/urls.js +69 -0
- package/dist/src/utils/vendor/is-unicorn-supported.d.ts +1 -0
- package/dist/src/utils/vendor/is-unicorn-supported.js +23 -0
- package/dist/src/utils/wizard-abort.d.ts +13 -0
- package/dist/src/utils/wizard-abort.js +56 -0
- package/man/amplitude-wizard.1 +170 -0
- package/package.json +144 -0
package/dist/bin.js
ADDED
|
@@ -0,0 +1,763 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
4
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
5
|
+
};
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
const semver_1 = require("semver");
|
|
8
|
+
const logging_1 = require("./src/utils/logging");
|
|
9
|
+
const dotenv_1 = require("dotenv");
|
|
10
|
+
(0, dotenv_1.config)();
|
|
11
|
+
const yargs_1 = __importDefault(require("yargs"));
|
|
12
|
+
const helpers_1 = require("yargs/helpers");
|
|
13
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
14
|
+
const fs_1 = require("fs");
|
|
15
|
+
const path_1 = require("path");
|
|
16
|
+
const zod_1 = require("zod");
|
|
17
|
+
const WIZARD_VERSION = (() => {
|
|
18
|
+
// npm/pnpm set this when running via package scripts
|
|
19
|
+
if (process.env.npm_package_version)
|
|
20
|
+
return process.env.npm_package_version;
|
|
21
|
+
// Fallback: read package.json relative to this file
|
|
22
|
+
try {
|
|
23
|
+
const pkg = zod_1.z
|
|
24
|
+
.object({ version: zod_1.z.string().optional() })
|
|
25
|
+
.passthrough()
|
|
26
|
+
.parse(JSON.parse((0, fs_1.readFileSync)((0, path_1.resolve)((0, path_1.dirname)(__filename), '..', 'package.json'), 'utf-8')));
|
|
27
|
+
return pkg.version ?? 'unknown';
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
return 'unknown';
|
|
31
|
+
}
|
|
32
|
+
})();
|
|
33
|
+
const NODE_VERSION_RANGE = '>=18.17.0';
|
|
34
|
+
// Have to run this above the other imports because they are importing clack that
|
|
35
|
+
// has the problematic imports.
|
|
36
|
+
if (!(0, semver_1.satisfies)(process.version, NODE_VERSION_RANGE)) {
|
|
37
|
+
(0, logging_1.red)(`Amplitude wizard requires Node.js ${NODE_VERSION_RANGE}. You are using Node.js ${process.version}. Please upgrade your Node.js version.`);
|
|
38
|
+
process.exit(1);
|
|
39
|
+
}
|
|
40
|
+
const run_1 = require("./src/run");
|
|
41
|
+
const environment_1 = require("./src/utils/environment");
|
|
42
|
+
const ui_1 = require("./src/ui");
|
|
43
|
+
const logging_ui_1 = require("./src/ui/logging-ui");
|
|
44
|
+
const shell_completions_1 = require("./src/utils/shell-completions");
|
|
45
|
+
const api_key_store_1 = require("./src/utils/api-key-store");
|
|
46
|
+
if (process.env.NODE_ENV === 'test') {
|
|
47
|
+
void (async () => {
|
|
48
|
+
try {
|
|
49
|
+
const { server } = await import('./e2e-tests/mocks/server.js');
|
|
50
|
+
server.listen({
|
|
51
|
+
onUnhandledRequest: 'bypass',
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
// Mock server import failed - this can happen during non-E2E tests
|
|
56
|
+
}
|
|
57
|
+
})();
|
|
58
|
+
}
|
|
59
|
+
void (0, yargs_1.default)((0, helpers_1.hideBin)(process.argv))
|
|
60
|
+
.env('AMPLITUDE_WIZARD')
|
|
61
|
+
// global options
|
|
62
|
+
.options({
|
|
63
|
+
debug: {
|
|
64
|
+
default: false,
|
|
65
|
+
describe: 'Enable verbose logging\nenv: AMPLITUDE_WIZARD_DEBUG',
|
|
66
|
+
type: 'boolean',
|
|
67
|
+
},
|
|
68
|
+
verbose: {
|
|
69
|
+
default: false,
|
|
70
|
+
describe: 'Print diagnostic info (working dir, config, etc.) to the log\nenv: AMPLITUDE_WIZARD_VERBOSE',
|
|
71
|
+
type: 'boolean',
|
|
72
|
+
},
|
|
73
|
+
default: {
|
|
74
|
+
default: true,
|
|
75
|
+
describe: 'Use default options for all prompts\nenv: AMPLITUDE_WIZARD_DEFAULT',
|
|
76
|
+
type: 'boolean',
|
|
77
|
+
},
|
|
78
|
+
signup: {
|
|
79
|
+
default: false,
|
|
80
|
+
describe: 'Create a new Amplitude account during setup\nenv: AMPLITUDE_WIZARD_SIGNUP',
|
|
81
|
+
type: 'boolean',
|
|
82
|
+
},
|
|
83
|
+
'local-mcp': {
|
|
84
|
+
default: false,
|
|
85
|
+
describe: 'Use local MCP server at http://localhost:8787/mcp\nenv: AMPLITUDE_WIZARD_LOCAL_MCP',
|
|
86
|
+
type: 'boolean',
|
|
87
|
+
},
|
|
88
|
+
ci: {
|
|
89
|
+
default: false,
|
|
90
|
+
describe: 'Enable CI mode for non-interactive execution\nenv: AMPLITUDE_WIZARD_CI',
|
|
91
|
+
type: 'boolean',
|
|
92
|
+
},
|
|
93
|
+
'api-key': {
|
|
94
|
+
describe: 'Amplitude API key for authentication\nenv: AMPLITUDE_WIZARD_API_KEY',
|
|
95
|
+
type: 'string',
|
|
96
|
+
},
|
|
97
|
+
'project-id': {
|
|
98
|
+
describe: 'Amplitude project ID to use (optional; when not set, uses default from API key or OAuth)\nenv: AMPLITUDE_WIZARD_PROJECT_ID',
|
|
99
|
+
type: 'string',
|
|
100
|
+
},
|
|
101
|
+
})
|
|
102
|
+
.command(['$0'], 'Run the Amplitude setup wizard', (yargs) => {
|
|
103
|
+
return yargs.options({
|
|
104
|
+
'force-install': {
|
|
105
|
+
default: false,
|
|
106
|
+
describe: 'Force install packages even if peer dependency checks fail\nenv: AMPLITUDE_WIZARD_FORCE_INSTALL',
|
|
107
|
+
type: 'boolean',
|
|
108
|
+
},
|
|
109
|
+
'install-dir': {
|
|
110
|
+
describe: 'Directory to install Amplitude in\nenv: AMPLITUDE_WIZARD_INSTALL_DIR',
|
|
111
|
+
type: 'string',
|
|
112
|
+
},
|
|
113
|
+
integration: {
|
|
114
|
+
describe: 'Integration to set up',
|
|
115
|
+
choices: [
|
|
116
|
+
'nextjs',
|
|
117
|
+
'vue',
|
|
118
|
+
'react-router',
|
|
119
|
+
'django',
|
|
120
|
+
'flask',
|
|
121
|
+
'fastapi',
|
|
122
|
+
'javascript_web',
|
|
123
|
+
'javascript_node',
|
|
124
|
+
'python',
|
|
125
|
+
],
|
|
126
|
+
type: 'string',
|
|
127
|
+
},
|
|
128
|
+
menu: {
|
|
129
|
+
default: false,
|
|
130
|
+
describe: 'Show menu for manual integration selection instead of auto-detecting\nenv: AMPLITUDE_WIZARD_MENU',
|
|
131
|
+
type: 'boolean',
|
|
132
|
+
},
|
|
133
|
+
benchmark: {
|
|
134
|
+
default: false,
|
|
135
|
+
describe: 'Run in benchmark mode with per-phase token tracking\nenv: AMPLITUDE_WIZARD_BENCHMARK',
|
|
136
|
+
type: 'boolean',
|
|
137
|
+
},
|
|
138
|
+
});
|
|
139
|
+
}, (argv) => {
|
|
140
|
+
const options = { ...argv };
|
|
141
|
+
// CI mode validation and TTY check
|
|
142
|
+
if (options.ci) {
|
|
143
|
+
// Use LoggingUI for CI mode (no dependencies, no prompts)
|
|
144
|
+
(0, ui_1.setUI)(new logging_ui_1.LoggingUI());
|
|
145
|
+
if (!options.apiKey) {
|
|
146
|
+
(0, ui_1.getUI)().intro(chalk_1.default.inverse(`Amplitude Wizard`));
|
|
147
|
+
(0, ui_1.getUI)().log.error('CI mode requires --api-key (Amplitude project API key)');
|
|
148
|
+
process.exit(1);
|
|
149
|
+
}
|
|
150
|
+
if (!options.installDir) {
|
|
151
|
+
(0, ui_1.getUI)().intro(chalk_1.default.inverse(`Amplitude Wizard`));
|
|
152
|
+
(0, ui_1.getUI)().log.error('CI mode requires --install-dir (directory to install Amplitude in)');
|
|
153
|
+
process.exit(1);
|
|
154
|
+
}
|
|
155
|
+
void (0, run_1.runWizard)(options);
|
|
156
|
+
}
|
|
157
|
+
else if ((0, environment_1.isNonInteractiveEnvironment)()) {
|
|
158
|
+
// Non-interactive non-CI: error out
|
|
159
|
+
(0, ui_1.getUI)().intro(chalk_1.default.inverse(`Amplitude Wizard`));
|
|
160
|
+
(0, ui_1.getUI)().log.error('This installer requires an interactive terminal (TTY) to run.\n' +
|
|
161
|
+
'It appears you are running in a non-interactive environment.\n' +
|
|
162
|
+
'Please run the wizard in an interactive terminal.\n\n' +
|
|
163
|
+
'For CI/CD environments, use --ci mode:\n' +
|
|
164
|
+
' npx @amplitude/wizard --ci --api-key <your-key> --install-dir .');
|
|
165
|
+
process.exit(1);
|
|
166
|
+
}
|
|
167
|
+
else {
|
|
168
|
+
// Interactive TTY: launch the Ink TUI
|
|
169
|
+
void (async () => {
|
|
170
|
+
// Silently install shell completions on first run.
|
|
171
|
+
const { installCompletions } = await import('./src/utils/shell-completions.js');
|
|
172
|
+
installCompletions();
|
|
173
|
+
try {
|
|
174
|
+
const { startTUI } = await import('./src/ui/tui/start-tui.js');
|
|
175
|
+
const { buildSession } = await import('./src/lib/wizard-session.js');
|
|
176
|
+
const tui = startTUI(WIZARD_VERSION);
|
|
177
|
+
// Build session from CLI args and attach to store
|
|
178
|
+
const session = buildSession({
|
|
179
|
+
debug: options.debug,
|
|
180
|
+
verbose: options.verbose,
|
|
181
|
+
forceInstall: options.forceInstall,
|
|
182
|
+
installDir: options.installDir,
|
|
183
|
+
ci: false,
|
|
184
|
+
signup: options.signup,
|
|
185
|
+
localMcp: options.localMcp,
|
|
186
|
+
apiKey: options.apiKey,
|
|
187
|
+
menu: options.menu,
|
|
188
|
+
integration: options.integration,
|
|
189
|
+
benchmark: options.benchmark,
|
|
190
|
+
projectId: options.projectId,
|
|
191
|
+
});
|
|
192
|
+
// If --api-key was provided, skip the OAuth/TUI auth flow entirely.
|
|
193
|
+
if (session.apiKey) {
|
|
194
|
+
const { DEFAULT_HOST_URL } = await import('./src/lib/constants.js');
|
|
195
|
+
session.credentials = {
|
|
196
|
+
accessToken: session.apiKey,
|
|
197
|
+
projectApiKey: session.apiKey,
|
|
198
|
+
host: DEFAULT_HOST_URL,
|
|
199
|
+
projectId: session.projectId ?? 0,
|
|
200
|
+
};
|
|
201
|
+
session.projectHasData = false;
|
|
202
|
+
}
|
|
203
|
+
else {
|
|
204
|
+
// Pre-populate region + credentials from all available sources for
|
|
205
|
+
// returning users. This skips RegionSelect and Auth without requiring
|
|
206
|
+
// a persisted OAuth token.
|
|
207
|
+
const installDir = session.installDir;
|
|
208
|
+
const [{ getStoredUser, getStoredToken }, { readAmpliConfig }, { getAPIKey }, { getHostFromRegion }, { logToFile },] = await Promise.all([
|
|
209
|
+
import('./src/utils/ampli-settings.js'),
|
|
210
|
+
import('./src/lib/ampli-config.js'),
|
|
211
|
+
import('./src/utils/get-api-key.js'),
|
|
212
|
+
import('./src/utils/urls.js'),
|
|
213
|
+
import('./src/utils/debug.js'),
|
|
214
|
+
]);
|
|
215
|
+
// Zone: prefer a real (non-pending) stored user, fall back to
|
|
216
|
+
// the Zone field in the project-level ampli.json.
|
|
217
|
+
const storedUser = getStoredUser();
|
|
218
|
+
const realUser = storedUser && storedUser.id !== 'pending' ? storedUser : null;
|
|
219
|
+
const projectConfig = readAmpliConfig(installDir);
|
|
220
|
+
const projectZone = projectConfig.ok
|
|
221
|
+
? projectConfig.config.Zone
|
|
222
|
+
: undefined;
|
|
223
|
+
const zone = realUser?.zone ?? projectZone ?? null;
|
|
224
|
+
if (zone) {
|
|
225
|
+
session.region = zone;
|
|
226
|
+
}
|
|
227
|
+
// Skip Auth when we have a stored OAuth token ā use it to fetch
|
|
228
|
+
// (or look up) the project API key, then pre-populate credentials.
|
|
229
|
+
if (zone) {
|
|
230
|
+
const storedToken = realUser
|
|
231
|
+
? getStoredToken(realUser.id, realUser.zone)
|
|
232
|
+
: getStoredToken(undefined, zone);
|
|
233
|
+
if (storedToken) {
|
|
234
|
+
logToFile(`[bin] getAPIKey: zone=${zone} hasWorkspaceId=${!!session.selectedWorkspaceId}`);
|
|
235
|
+
const projectApiKey = await getAPIKey({
|
|
236
|
+
installDir,
|
|
237
|
+
idToken: storedToken.idToken,
|
|
238
|
+
zone,
|
|
239
|
+
workspaceId: session.selectedWorkspaceId ?? undefined,
|
|
240
|
+
});
|
|
241
|
+
if (projectApiKey) {
|
|
242
|
+
logToFile('[bin] getAPIKey: resolved project API key');
|
|
243
|
+
(0, api_key_store_1.persistApiKey)(projectApiKey, installDir);
|
|
244
|
+
session.credentials = {
|
|
245
|
+
accessToken: storedToken.idToken,
|
|
246
|
+
idToken: storedToken.idToken,
|
|
247
|
+
projectApiKey,
|
|
248
|
+
host: getHostFromRegion(zone),
|
|
249
|
+
projectId: 0,
|
|
250
|
+
};
|
|
251
|
+
// Pre-populate activationLevel so DataSetup is also skipped,
|
|
252
|
+
// giving a single wipe from Intro ā Run/Setup.
|
|
253
|
+
// DataSetup would set 'none' anyway (projectId=0 prevents the
|
|
254
|
+
// real check), so this is equivalent ā just earlier.
|
|
255
|
+
session.activationLevel = 'none';
|
|
256
|
+
session.projectHasData = false;
|
|
257
|
+
}
|
|
258
|
+
else {
|
|
259
|
+
logToFile('[bin] getAPIKey: returned null ā showing apiKeyNotice');
|
|
260
|
+
// Region is already pre-populated above; prompt for the
|
|
261
|
+
// key manually with a hint about org-admin permissions.
|
|
262
|
+
session.apiKeyNotice =
|
|
263
|
+
"Your API key couldn't be fetched automatically. " +
|
|
264
|
+
'Only organization admins can access project API keys ā ' +
|
|
265
|
+
'if you need one, ask an admin to share it with you.';
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
// Pre-populate org/workspace from ampli.json so activation checks
|
|
270
|
+
// (DataSetupScreen, DataIngestionCheckScreen) have the IDs they need
|
|
271
|
+
// even when the SUSI flow was skipped.
|
|
272
|
+
if (projectConfig.ok && projectConfig.config.OrgId) {
|
|
273
|
+
session.selectedOrgId = String(projectConfig.config.OrgId);
|
|
274
|
+
}
|
|
275
|
+
if (projectConfig.ok && projectConfig.config.WorkspaceId) {
|
|
276
|
+
session.selectedWorkspaceId = projectConfig.config.WorkspaceId;
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
tui.store.session = session;
|
|
280
|
+
const { FRAMEWORK_REGISTRY } = await import('./src/lib/registry.js');
|
|
281
|
+
const { detectIntegration } = await import('./src/run.js');
|
|
282
|
+
const installDir = session.installDir ?? process.cwd();
|
|
283
|
+
// Verbose startup diagnostics ā always written to the log file;
|
|
284
|
+
// visible in the RunScreen "Logs" tab.
|
|
285
|
+
if (session.verbose || session.debug) {
|
|
286
|
+
const { enableDebugLogs, logToFile } = await import('./src/utils/debug.js');
|
|
287
|
+
enableDebugLogs();
|
|
288
|
+
logToFile('[verbose] Amplitude Wizard starting');
|
|
289
|
+
logToFile(`[verbose] node : ${process.version}`);
|
|
290
|
+
logToFile(`[verbose] process.cwd() : ${process.cwd()}`);
|
|
291
|
+
logToFile(`[verbose] installDir : ${installDir}`);
|
|
292
|
+
logToFile(`[verbose] platform : ${process.platform}`);
|
|
293
|
+
logToFile(`[verbose] argv : ${process.argv.join(' ')}`);
|
|
294
|
+
}
|
|
295
|
+
const { DETECTION_TIMEOUT_MS } = await import('./src/lib/constants.js');
|
|
296
|
+
// āā OAuth + account setup āāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
297
|
+
// Runs concurrently with framework detection while AuthScreen shows.
|
|
298
|
+
// When OAuth completes, store.setOAuthComplete() triggers the
|
|
299
|
+
// AuthScreen SUSI pickers (org ā workspace ā API key).
|
|
300
|
+
// AuthScreen calls store.setCredentials() when done, advancing the
|
|
301
|
+
// router past Auth ā RegionSelect ā DataSetup ā to IntroScreen.
|
|
302
|
+
const authTask = (async () => {
|
|
303
|
+
// Skip the full OAuth + SUSI flow when credentials were pre-populated
|
|
304
|
+
// from ~/.ampli.json + the saved API key (returning user).
|
|
305
|
+
if (tui.store.session.credentials !== null)
|
|
306
|
+
return;
|
|
307
|
+
try {
|
|
308
|
+
const { ampliConfigExists } = await import('./src/lib/ampli-config.js');
|
|
309
|
+
const { performAmplitudeAuth } = await import('./src/utils/oauth.js');
|
|
310
|
+
const { fetchAmplitudeUser } = await import('./src/lib/api.js');
|
|
311
|
+
const { DEFAULT_AMPLITUDE_ZONE } = await import('./src/lib/constants.js');
|
|
312
|
+
const { storeToken } = await import('./src/utils/ampli-settings.js');
|
|
313
|
+
const forceFresh = !ampliConfigExists(installDir);
|
|
314
|
+
// Wait for the user to pick a region (or for it to be pre-populated
|
|
315
|
+
// from ~/.ampli.json for returning users) before opening the OAuth URL,
|
|
316
|
+
// since the auth endpoint differs between US and EU.
|
|
317
|
+
await new Promise((resolve) => {
|
|
318
|
+
if (tui.store.session.region !== null) {
|
|
319
|
+
resolve();
|
|
320
|
+
return;
|
|
321
|
+
}
|
|
322
|
+
const unsub = tui.store.subscribe(() => {
|
|
323
|
+
if (tui.store.session.region !== null) {
|
|
324
|
+
unsub();
|
|
325
|
+
resolve();
|
|
326
|
+
}
|
|
327
|
+
});
|
|
328
|
+
});
|
|
329
|
+
const zone = tui.store.session.region === 'eu'
|
|
330
|
+
? 'eu'
|
|
331
|
+
: DEFAULT_AMPLITUDE_ZONE;
|
|
332
|
+
let auth = await performAmplitudeAuth({
|
|
333
|
+
zone,
|
|
334
|
+
forceFresh,
|
|
335
|
+
});
|
|
336
|
+
// Update login URL (clears the "copy this URL" hint)
|
|
337
|
+
tui.store.setLoginUrl(null);
|
|
338
|
+
// Zone was already selected by the user before OAuth started.
|
|
339
|
+
const cloudRegion = zone;
|
|
340
|
+
let userInfo;
|
|
341
|
+
try {
|
|
342
|
+
userInfo = await fetchAmplitudeUser(auth.idToken, cloudRegion);
|
|
343
|
+
}
|
|
344
|
+
catch {
|
|
345
|
+
// Token may be expired ā re-open the browser for a fresh login
|
|
346
|
+
tui.store.setLoginUrl(null);
|
|
347
|
+
auth = await performAmplitudeAuth({ zone, forceFresh: true });
|
|
348
|
+
userInfo = await fetchAmplitudeUser(auth.idToken, cloudRegion);
|
|
349
|
+
}
|
|
350
|
+
// Persist to ~/.ampli.json
|
|
351
|
+
storeToken({
|
|
352
|
+
id: userInfo.id,
|
|
353
|
+
firstName: userInfo.firstName,
|
|
354
|
+
lastName: userInfo.lastName,
|
|
355
|
+
email: userInfo.email,
|
|
356
|
+
zone: auth.zone,
|
|
357
|
+
}, {
|
|
358
|
+
accessToken: auth.accessToken,
|
|
359
|
+
idToken: auth.idToken,
|
|
360
|
+
refreshToken: auth.refreshToken,
|
|
361
|
+
expiresAt: new Date(Date.now() + 3600 * 1000).toISOString(),
|
|
362
|
+
});
|
|
363
|
+
// Signal AuthScreen ā triggers org/workspace/API key pickers
|
|
364
|
+
tui.store.setOAuthComplete({
|
|
365
|
+
accessToken: auth.accessToken,
|
|
366
|
+
idToken: auth.idToken,
|
|
367
|
+
cloudRegion,
|
|
368
|
+
orgs: userInfo.orgs,
|
|
369
|
+
});
|
|
370
|
+
}
|
|
371
|
+
catch (err) {
|
|
372
|
+
// Auth failure is non-fatal here ā agent-runner will retry/handle it
|
|
373
|
+
if (process.env.DEBUG || process.env.AMPLITUDE_WIZARD_DEBUG) {
|
|
374
|
+
console.error('OAuth setup error:', err);
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
})();
|
|
378
|
+
// āā Framework detection āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
379
|
+
// Runs concurrently with auth while AuthScreen shows.
|
|
380
|
+
const detectionTask = (async () => {
|
|
381
|
+
const detectedIntegration = await Promise.race([
|
|
382
|
+
detectIntegration(installDir),
|
|
383
|
+
new Promise((resolve) => setTimeout(() => resolve(undefined), DETECTION_TIMEOUT_MS)),
|
|
384
|
+
]);
|
|
385
|
+
if (detectedIntegration) {
|
|
386
|
+
const config = FRAMEWORK_REGISTRY[detectedIntegration];
|
|
387
|
+
// Run gatherContext for the friendly variant label
|
|
388
|
+
if (config.metadata.gatherContext) {
|
|
389
|
+
try {
|
|
390
|
+
const context = await Promise.race([
|
|
391
|
+
config.metadata.gatherContext({
|
|
392
|
+
installDir,
|
|
393
|
+
debug: session.debug,
|
|
394
|
+
forceInstall: session.forceInstall,
|
|
395
|
+
default: false,
|
|
396
|
+
signup: session.signup,
|
|
397
|
+
localMcp: session.localMcp,
|
|
398
|
+
ci: session.ci,
|
|
399
|
+
menu: session.menu,
|
|
400
|
+
benchmark: session.benchmark,
|
|
401
|
+
}),
|
|
402
|
+
new Promise((resolve) => setTimeout(() => resolve({}), DETECTION_TIMEOUT_MS)),
|
|
403
|
+
]);
|
|
404
|
+
for (const [key, value] of Object.entries(context)) {
|
|
405
|
+
if (!(key in session.frameworkContext)) {
|
|
406
|
+
tui.store.setFrameworkContext(key, value);
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
catch {
|
|
411
|
+
// Detection failed ā will show generic name
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
tui.store.setFrameworkConfig(detectedIntegration, config);
|
|
415
|
+
if (!session.detectedFrameworkLabel) {
|
|
416
|
+
tui.store.setDetectedFramework(config.metadata.name);
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
// Feature discovery ā deterministic scan of package.json deps
|
|
420
|
+
try {
|
|
421
|
+
const { readFileSync } = await import('fs');
|
|
422
|
+
const pkgPath = (0, path_1.join)(installDir, 'package.json');
|
|
423
|
+
const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));
|
|
424
|
+
const allDeps = {
|
|
425
|
+
...pkg.dependencies,
|
|
426
|
+
...pkg.devDependencies,
|
|
427
|
+
};
|
|
428
|
+
const depNames = Object.keys(allDeps);
|
|
429
|
+
const { DiscoveredFeature } = await import('./src/lib/wizard-session.js');
|
|
430
|
+
if (depNames.some((d) => ['stripe', '@stripe/stripe-js'].includes(d))) {
|
|
431
|
+
tui.store.addDiscoveredFeature(DiscoveredFeature.Stripe);
|
|
432
|
+
}
|
|
433
|
+
// LLM SDK detection ā sourced from Amplitude LLM analytics skill
|
|
434
|
+
const LLM_PACKAGES = [
|
|
435
|
+
'openai',
|
|
436
|
+
'@anthropic-ai/sdk',
|
|
437
|
+
'ai',
|
|
438
|
+
'@ai-sdk/openai',
|
|
439
|
+
'langchain',
|
|
440
|
+
'@langchain/openai',
|
|
441
|
+
'@langchain/langgraph',
|
|
442
|
+
'@google/generative-ai',
|
|
443
|
+
'@google/genai',
|
|
444
|
+
'@instructor-ai/instructor',
|
|
445
|
+
'@mastra/core',
|
|
446
|
+
'portkey-ai',
|
|
447
|
+
];
|
|
448
|
+
if (depNames.some((d) => LLM_PACKAGES.includes(d))) {
|
|
449
|
+
tui.store.addDiscoveredFeature(DiscoveredFeature.LLM);
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
catch {
|
|
453
|
+
// No package.json or parse error ā skip feature discovery
|
|
454
|
+
}
|
|
455
|
+
// Signal detection is done ā IntroScreen shows picker or results
|
|
456
|
+
tui.store.setDetectionComplete();
|
|
457
|
+
})();
|
|
458
|
+
// Gate runWizard on the user reaching RunScreen ā at that point
|
|
459
|
+
// auth, data check, and any setup questions are all complete.
|
|
460
|
+
const { Screen } = await import('./src/ui/tui/router.js');
|
|
461
|
+
tui.store.onEnterScreen(Screen.Run, () => tui.store.completeSetup());
|
|
462
|
+
// Wait for auth and framework detection to finish concurrently.
|
|
463
|
+
await Promise.all([authTask, detectionTask]);
|
|
464
|
+
if (session.verbose || session.debug) {
|
|
465
|
+
const { logToFile } = await import('./src/utils/debug.js');
|
|
466
|
+
logToFile(`[verbose] detection : ${tui.store.session.integration ?? 'none'}`);
|
|
467
|
+
logToFile(`[verbose] framework : ${tui.store.session.detectedFrameworkLabel ?? 'unknown'}`);
|
|
468
|
+
logToFile(`[verbose] region : ${tui.store.session.region ?? 'not set'}`);
|
|
469
|
+
}
|
|
470
|
+
// Blocks until onEnterScreen(Screen.Run) fires completeSetup().
|
|
471
|
+
await tui.waitForSetup();
|
|
472
|
+
// Before calling the AI agent, do a quick static check to see if
|
|
473
|
+
// Amplitude is already installed in the project. If so, skip the
|
|
474
|
+
// agent entirely and advance directly to MCP setup.
|
|
475
|
+
const { detectAmplitudeInProject } = await import('./src/lib/detect-amplitude.js');
|
|
476
|
+
const localDetection = detectAmplitudeInProject(installDir);
|
|
477
|
+
if (localDetection.confidence !== 'none') {
|
|
478
|
+
const { logToFile: log } = await import('./src/utils/debug.js');
|
|
479
|
+
log(`[bin] Amplitude already detected (${localDetection.reason ?? 'unknown'}) ā skipping agent`);
|
|
480
|
+
const { RunPhase, OutroKind } = await import('./src/lib/wizard-session.js');
|
|
481
|
+
tui.store.setAmplitudePreDetected();
|
|
482
|
+
tui.store.setOutroData({ kind: OutroKind.Success });
|
|
483
|
+
tui.store.setRunPhase(RunPhase.Completed);
|
|
484
|
+
}
|
|
485
|
+
else {
|
|
486
|
+
await (0, run_1.runWizard)(options, tui.store.session);
|
|
487
|
+
}
|
|
488
|
+
// Keep the outro screen visible ā let process.exit() handle cleanup
|
|
489
|
+
}
|
|
490
|
+
catch (err) {
|
|
491
|
+
// TUI unavailable (e.g., in test environment) ā continue with default UI
|
|
492
|
+
if (process.env.DEBUG || process.env.AMPLITUDE_WIZARD_DEBUG) {
|
|
493
|
+
console.error('TUI init failed:', err);
|
|
494
|
+
}
|
|
495
|
+
await (0, run_1.runWizard)(options);
|
|
496
|
+
}
|
|
497
|
+
})();
|
|
498
|
+
}
|
|
499
|
+
})
|
|
500
|
+
.command('login', 'Log in to your Amplitude account', (yargs) => {
|
|
501
|
+
return yargs.options({
|
|
502
|
+
zone: {
|
|
503
|
+
describe: 'Amplitude data center zone (us or eu)',
|
|
504
|
+
choices: ['us', 'eu'],
|
|
505
|
+
default: 'us',
|
|
506
|
+
type: 'string',
|
|
507
|
+
},
|
|
508
|
+
});
|
|
509
|
+
}, (argv) => {
|
|
510
|
+
void (async () => {
|
|
511
|
+
(0, ui_1.setUI)(new logging_ui_1.LoggingUI());
|
|
512
|
+
const { performAmplitudeAuth } = await import('./src/utils/oauth.js');
|
|
513
|
+
const { fetchAmplitudeUser } = await import('./src/lib/api.js');
|
|
514
|
+
const { storeToken } = await import('./src/utils/ampli-settings.js');
|
|
515
|
+
const zone = argv.zone;
|
|
516
|
+
try {
|
|
517
|
+
const { getStoredUser, getStoredToken } = await import('./src/utils/ampli-settings.js');
|
|
518
|
+
// If a valid cached session exists, display the stored user without
|
|
519
|
+
// re-fetching from the API (the cached idToken may be expired).
|
|
520
|
+
const cachedToken = getStoredToken(undefined, zone);
|
|
521
|
+
const cachedUser = cachedToken ? getStoredUser() : undefined;
|
|
522
|
+
if (cachedUser && cachedUser.id !== 'pending') {
|
|
523
|
+
console.log(chalk_1.default.green(`ā Already logged in as ${cachedUser.firstName} ${cachedUser.lastName} <${cachedUser.email}>`));
|
|
524
|
+
if (cachedUser.zone !== 'us') {
|
|
525
|
+
console.log(chalk_1.default.dim(` Zone: ${cachedUser.zone}`));
|
|
526
|
+
}
|
|
527
|
+
process.exit(0);
|
|
528
|
+
}
|
|
529
|
+
const auth = await performAmplitudeAuth({ zone });
|
|
530
|
+
const user = await fetchAmplitudeUser(auth.idToken, auth.zone);
|
|
531
|
+
storeToken({
|
|
532
|
+
id: user.id,
|
|
533
|
+
firstName: user.firstName,
|
|
534
|
+
lastName: user.lastName,
|
|
535
|
+
email: user.email,
|
|
536
|
+
zone: auth.zone,
|
|
537
|
+
}, {
|
|
538
|
+
accessToken: auth.accessToken,
|
|
539
|
+
idToken: auth.idToken,
|
|
540
|
+
refreshToken: auth.refreshToken,
|
|
541
|
+
expiresAt: new Date(Date.now() + 3600 * 1000).toISOString(),
|
|
542
|
+
});
|
|
543
|
+
console.log(chalk_1.default.green(`ā Logged in as ${user.firstName} ${user.lastName} <${user.email}>`));
|
|
544
|
+
if (user.orgs.length > 0) {
|
|
545
|
+
console.log(chalk_1.default.dim(` Org: ${user.orgs.map((o) => o.name).join(', ')}`));
|
|
546
|
+
}
|
|
547
|
+
process.exit(0);
|
|
548
|
+
}
|
|
549
|
+
catch (e) {
|
|
550
|
+
console.error(chalk_1.default.red(`Login failed: ${e instanceof Error ? e.message : String(e)}`));
|
|
551
|
+
process.exit(1);
|
|
552
|
+
}
|
|
553
|
+
})();
|
|
554
|
+
})
|
|
555
|
+
.command('logout', 'Log out of your Amplitude account', () => { }, (argv) => {
|
|
556
|
+
void (async () => {
|
|
557
|
+
const { getStoredUser, clearStoredCredentials } = await import('./src/utils/ampli-settings.js');
|
|
558
|
+
const { clearApiKey } = await import('./src/utils/api-key-store.js');
|
|
559
|
+
const installDir = argv.installDir ?? process.cwd();
|
|
560
|
+
const user = getStoredUser();
|
|
561
|
+
try {
|
|
562
|
+
clearStoredCredentials();
|
|
563
|
+
clearApiKey(installDir);
|
|
564
|
+
if (user) {
|
|
565
|
+
console.log(chalk_1.default.green(`ā Logged out ${user.email}`));
|
|
566
|
+
}
|
|
567
|
+
else {
|
|
568
|
+
console.log(chalk_1.default.dim('No active session found.'));
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
catch {
|
|
572
|
+
console.log(chalk_1.default.dim('No active session found.'));
|
|
573
|
+
}
|
|
574
|
+
process.exit(0);
|
|
575
|
+
})();
|
|
576
|
+
})
|
|
577
|
+
.command('whoami', 'Show the currently logged-in Amplitude account', () => { }, (_argv) => {
|
|
578
|
+
void (async () => {
|
|
579
|
+
const { getStoredUser, getStoredToken } = await import('./src/utils/ampli-settings.js');
|
|
580
|
+
const user = getStoredUser();
|
|
581
|
+
const token = getStoredToken();
|
|
582
|
+
if (user && token && user.id !== 'pending') {
|
|
583
|
+
console.log(`Logged in as ${chalk_1.default.bold(user.firstName + ' ' + user.lastName)} <${user.email}>`);
|
|
584
|
+
if (user.zone !== 'us')
|
|
585
|
+
console.log(chalk_1.default.dim(`Zone: ${user.zone}`));
|
|
586
|
+
}
|
|
587
|
+
else {
|
|
588
|
+
console.log(chalk_1.default.yellow('Not logged in. Run `amplitude-wizard login` to authenticate.'));
|
|
589
|
+
}
|
|
590
|
+
process.exit(0);
|
|
591
|
+
})();
|
|
592
|
+
})
|
|
593
|
+
.command('slack', 'Set up Amplitude Slack integration', (y) => y, (argv) => {
|
|
594
|
+
void (async () => {
|
|
595
|
+
try {
|
|
596
|
+
const { startTUI } = await import('./src/ui/tui/start-tui.js');
|
|
597
|
+
const { buildSession } = await import('./src/lib/wizard-session.js');
|
|
598
|
+
const { Flow } = await import('./src/ui/tui/router.js');
|
|
599
|
+
const { getStoredUser, getStoredToken } = await import('./src/utils/ampli-settings.js');
|
|
600
|
+
const { getHostFromRegion } = await import('./src/utils/urls.js');
|
|
601
|
+
const session = buildSession({
|
|
602
|
+
debug: typeof argv['debug'] === 'boolean' ? argv['debug'] : undefined,
|
|
603
|
+
});
|
|
604
|
+
// Pre-populate credentials from ~/.ampli.json so SlackScreen can
|
|
605
|
+
// resolve the org name via fetchAmplitudeUser.
|
|
606
|
+
const storedUser = getStoredUser();
|
|
607
|
+
const zone = storedUser?.zone ?? 'us';
|
|
608
|
+
const storedToken = getStoredToken(storedUser?.id, zone);
|
|
609
|
+
if (storedToken) {
|
|
610
|
+
session.region = zone;
|
|
611
|
+
session.credentials = {
|
|
612
|
+
accessToken: storedToken.idToken,
|
|
613
|
+
projectApiKey: '',
|
|
614
|
+
host: getHostFromRegion(zone),
|
|
615
|
+
projectId: 0,
|
|
616
|
+
};
|
|
617
|
+
}
|
|
618
|
+
// Pass the pre-populated session so it's available before the first render.
|
|
619
|
+
startTUI(WIZARD_VERSION, Flow.SlackSetup, session);
|
|
620
|
+
}
|
|
621
|
+
catch {
|
|
622
|
+
(0, ui_1.setUI)(new logging_ui_1.LoggingUI());
|
|
623
|
+
const { getCloudUrlFromRegion } = await import('./src/utils/urls.js');
|
|
624
|
+
const opn = (await import('opn')).default;
|
|
625
|
+
const url = `${getCloudUrlFromRegion('us')}/settings/profile`;
|
|
626
|
+
(0, ui_1.getUI)().log.info(`Opening Amplitude Settings to connect Slack: ${url}`);
|
|
627
|
+
await opn(url, { wait: false });
|
|
628
|
+
}
|
|
629
|
+
})();
|
|
630
|
+
})
|
|
631
|
+
.command('region', 'Switch data-center region (US or EU)', (y) => y, (argv) => {
|
|
632
|
+
void (async () => {
|
|
633
|
+
try {
|
|
634
|
+
const { startTUI } = await import('./src/ui/tui/start-tui.js');
|
|
635
|
+
const { buildSession } = await import('./src/lib/wizard-session.js');
|
|
636
|
+
const { Flow } = await import('./src/ui/tui/router.js');
|
|
637
|
+
const { getStoredUser, getStoredToken, updateStoredUserZone } = await import('./src/utils/ampli-settings.js');
|
|
638
|
+
const { getHostFromRegion } = await import('./src/utils/urls.js');
|
|
639
|
+
const session = buildSession({
|
|
640
|
+
debug: typeof argv['debug'] === 'boolean' ? argv['debug'] : undefined,
|
|
641
|
+
});
|
|
642
|
+
// Show the "Switch data-center region" variant of RegionSelectScreen.
|
|
643
|
+
session.regionForced = true;
|
|
644
|
+
// Pre-populate credentials from ~/.ampli.json so the screen has context.
|
|
645
|
+
const storedUser = getStoredUser();
|
|
646
|
+
const zone = storedUser?.zone ?? 'us';
|
|
647
|
+
const storedToken = getStoredToken(storedUser?.id, zone);
|
|
648
|
+
if (storedToken) {
|
|
649
|
+
session.credentials = {
|
|
650
|
+
accessToken: storedToken.idToken,
|
|
651
|
+
projectApiKey: '',
|
|
652
|
+
host: getHostFromRegion(zone),
|
|
653
|
+
projectId: 0,
|
|
654
|
+
};
|
|
655
|
+
}
|
|
656
|
+
const tui = startTUI(WIZARD_VERSION, Flow.RegionSelect, session);
|
|
657
|
+
// Wait for the user to pick a region, then persist and exit.
|
|
658
|
+
const pickedRegion = await new Promise((resolve) => {
|
|
659
|
+
const unsub = tui.store.subscribe(() => {
|
|
660
|
+
const s = tui.store.session;
|
|
661
|
+
if (s.region !== null && !s.regionForced) {
|
|
662
|
+
unsub();
|
|
663
|
+
resolve(s.region);
|
|
664
|
+
}
|
|
665
|
+
});
|
|
666
|
+
});
|
|
667
|
+
const updated = updateStoredUserZone(pickedRegion);
|
|
668
|
+
if (updated) {
|
|
669
|
+
console.log(chalk_1.default.green(`\nā Region updated to ${pickedRegion.toUpperCase()}`));
|
|
670
|
+
}
|
|
671
|
+
else {
|
|
672
|
+
console.log(chalk_1.default.dim(`\nRegion set to ${pickedRegion.toUpperCase()}. Run \`amplitude-wizard login\` to authenticate.`));
|
|
673
|
+
}
|
|
674
|
+
process.exit(0);
|
|
675
|
+
}
|
|
676
|
+
catch {
|
|
677
|
+
(0, ui_1.setUI)(new logging_ui_1.LoggingUI());
|
|
678
|
+
(0, ui_1.getUI)().log.error('Could not start region picker. Use --zone with `amplitude-wizard login` to set your region.');
|
|
679
|
+
process.exit(1);
|
|
680
|
+
}
|
|
681
|
+
})();
|
|
682
|
+
})
|
|
683
|
+
.command('mcp <command>', 'MCP server management commands', (yargs) => {
|
|
684
|
+
return yargs
|
|
685
|
+
.command('add', 'Install Amplitude MCP server to supported clients', (yargs) => {
|
|
686
|
+
return yargs.options({
|
|
687
|
+
local: {
|
|
688
|
+
default: false,
|
|
689
|
+
describe: 'Add local development MCP server (http://localhost:8787)',
|
|
690
|
+
type: 'boolean',
|
|
691
|
+
},
|
|
692
|
+
});
|
|
693
|
+
}, (argv) => {
|
|
694
|
+
const options = { ...argv };
|
|
695
|
+
void (async () => {
|
|
696
|
+
try {
|
|
697
|
+
const { startTUI } = await import('./src/ui/tui/start-tui.js');
|
|
698
|
+
const { buildSession } = await import('./src/lib/wizard-session.js');
|
|
699
|
+
const { Flow } = await import('./src/ui/tui/router.js');
|
|
700
|
+
const tui = startTUI(WIZARD_VERSION, Flow.McpAdd);
|
|
701
|
+
const session = buildSession({
|
|
702
|
+
debug: options.debug,
|
|
703
|
+
localMcp: options.local,
|
|
704
|
+
});
|
|
705
|
+
tui.store.session = session;
|
|
706
|
+
}
|
|
707
|
+
catch {
|
|
708
|
+
// TUI unavailable ā fallback to logging
|
|
709
|
+
(0, ui_1.setUI)(new logging_ui_1.LoggingUI());
|
|
710
|
+
const { addMCPServerToClientsStep } = await import('./src/steps/add-mcp-server-to-clients/index.js');
|
|
711
|
+
await addMCPServerToClientsStep({
|
|
712
|
+
local: options.local,
|
|
713
|
+
});
|
|
714
|
+
}
|
|
715
|
+
})();
|
|
716
|
+
})
|
|
717
|
+
.command('remove', 'Remove Amplitude MCP server from supported clients', (yargs) => {
|
|
718
|
+
return yargs.options({
|
|
719
|
+
local: {
|
|
720
|
+
default: false,
|
|
721
|
+
describe: 'Remove local development MCP server (http://localhost:8787)',
|
|
722
|
+
type: 'boolean',
|
|
723
|
+
},
|
|
724
|
+
});
|
|
725
|
+
}, (argv) => {
|
|
726
|
+
const options = { ...argv };
|
|
727
|
+
void (async () => {
|
|
728
|
+
try {
|
|
729
|
+
const { startTUI } = await import('./src/ui/tui/start-tui.js');
|
|
730
|
+
const { buildSession } = await import('./src/lib/wizard-session.js');
|
|
731
|
+
const { Flow } = await import('./src/ui/tui/router.js');
|
|
732
|
+
const tui = startTUI(WIZARD_VERSION, Flow.McpRemove);
|
|
733
|
+
const session = buildSession({
|
|
734
|
+
debug: options.debug,
|
|
735
|
+
localMcp: options.local,
|
|
736
|
+
});
|
|
737
|
+
tui.store.session = session;
|
|
738
|
+
}
|
|
739
|
+
catch {
|
|
740
|
+
// TUI unavailable ā fallback to logging
|
|
741
|
+
(0, ui_1.setUI)(new logging_ui_1.LoggingUI());
|
|
742
|
+
const { removeMCPServerFromClientsStep } = await import('./src/steps/add-mcp-server-to-clients/index.js');
|
|
743
|
+
await removeMCPServerFromClientsStep({
|
|
744
|
+
local: options.local,
|
|
745
|
+
});
|
|
746
|
+
}
|
|
747
|
+
})();
|
|
748
|
+
})
|
|
749
|
+
.demandCommand(1, 'You must specify a subcommand (add or remove)')
|
|
750
|
+
.help();
|
|
751
|
+
})
|
|
752
|
+
.command('completion', 'Print shell completion script\n(add `eval "$(amplitude-wizard completion)"` to ~/.zshrc or ~/.bashrc)', () => { }, () => {
|
|
753
|
+
const script = (process.env.SHELL ?? '').endsWith('zsh')
|
|
754
|
+
? shell_completions_1.ZSH_COMPLETION_SCRIPT
|
|
755
|
+
: shell_completions_1.BASH_COMPLETION_SCRIPT;
|
|
756
|
+
process.stdout.write(script + '\n');
|
|
757
|
+
process.exit(0);
|
|
758
|
+
})
|
|
759
|
+
.help()
|
|
760
|
+
.alias('help', 'h')
|
|
761
|
+
.version()
|
|
762
|
+
.alias('version', 'v')
|
|
763
|
+
.wrap(process.stdout.isTTY ? yargs_1.default.terminalWidth() : 80).argv;
|