@amplitude/wizard 1.0.0-beta.0 → 1.0.0-beta.1

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.
Files changed (34) hide show
  1. package/dist/bin.js +42 -8
  2. package/dist/package.json +2 -1
  3. package/dist/src/lib/agent-interface.js +10 -22
  4. package/dist/src/lib/agent-runner.js +4 -6
  5. package/dist/src/lib/commandments.js +1 -1
  6. package/dist/src/lib/constants.d.ts +0 -3
  7. package/dist/src/lib/constants.js +1 -4
  8. package/dist/src/lib/wizard-session.d.ts +6 -0
  9. package/dist/src/lib/wizard-session.js +1 -0
  10. package/dist/src/run.js +1 -1
  11. package/dist/src/steps/add-mcp-server-to-clients/index.js +3 -3
  12. package/dist/src/steps/add-or-update-environment-variables.js +5 -17
  13. package/dist/src/steps/run-prettier.js +1 -1
  14. package/dist/src/steps/upload-environment-variables/index.js +2 -2
  15. package/dist/src/ui/tui/components/ConsoleView.js +16 -2
  16. package/dist/src/ui/tui/console-commands.d.ts +5 -0
  17. package/dist/src/ui/tui/console-commands.js +15 -0
  18. package/dist/src/ui/tui/screens/AuthScreen.js +72 -14
  19. package/dist/src/ui/tui/screens/ChecklistScreen.js +1 -1
  20. package/dist/src/ui/tui/screens/IntroScreen.js +2 -2
  21. package/dist/src/ui/tui/screens/McpScreen.js +42 -27
  22. package/dist/src/ui/tui/screens/OutroScreen.js +1 -1
  23. package/dist/src/ui/tui/store.d.ts +17 -0
  24. package/dist/src/ui/tui/store.js +55 -19
  25. package/dist/src/utils/analytics.d.ts +27 -3
  26. package/dist/src/utils/analytics.js +83 -44
  27. package/dist/src/utils/oauth.js +1 -1
  28. package/dist/src/utils/setup-utils.d.ts +11 -0
  29. package/dist/src/utils/setup-utils.js +81 -4
  30. package/dist/src/utils/shell-completions.d.ts +2 -2
  31. package/dist/src/utils/shell-completions.js +8 -1
  32. package/dist/src/utils/track-wizard-feedback.d.ts +5 -0
  33. package/dist/src/utils/track-wizard-feedback.js +25 -0
  34. package/package.json +2 -1
@@ -60,6 +60,17 @@ export declare function getPackageManager(options: Pick<WizardOptions, 'installD
60
60
  ci?: boolean;
61
61
  }): Promise<PackageManager>;
62
62
  export declare function isUsingTypeScript({ installDir, }: Pick<WizardOptions, 'installDir'>): boolean;
63
+ /**
64
+ * Best-effort credentials for `--ci` when `--api-key` / AMPLITUDE_WIZARD_API_KEY
65
+ * is not set: project-local key (.env.local / keychain), then OAuth id token from
66
+ * ~/.ampli.json plus org/workspace from ampli.json (same resolution as interactive bootstrap).
67
+ */
68
+ export declare function tryResolveCredentialsForCi(installDir: string): Promise<{
69
+ host: string;
70
+ projectApiKey: string;
71
+ accessToken: string;
72
+ cloudRegion: CloudRegion;
73
+ } | null>;
63
74
  /**
64
75
  * Get project data for the wizard via Amplitude OAuth or CI API key.
65
76
  *
@@ -46,6 +46,7 @@ exports.tryGetPackageJson = tryGetPackageJson;
46
46
  exports.updatePackageDotJson = updatePackageDotJson;
47
47
  exports.getPackageManager = getPackageManager;
48
48
  exports.isUsingTypeScript = isUsingTypeScript;
49
+ exports.tryResolveCredentialsForCi = tryResolveCredentialsForCi;
49
50
  exports.getOrAskForProjectData = getOrAskForProjectData;
50
51
  exports.createNewConfigFile = createNewConfigFile;
51
52
  const childProcess = __importStar(require("node:child_process"));
@@ -63,7 +64,6 @@ const ui_1 = require("../ui");
63
64
  const oauth_1 = require("./oauth");
64
65
  const api_1 = require("../lib/api");
65
66
  const ampli_settings_1 = require("./ampli-settings");
66
- const constants_2 = require("../lib/constants");
67
67
  const urls_1 = require("./urls");
68
68
  const semver_1 = require("./semver");
69
69
  const wizard_abort_1 = require("./wizard-abort");
@@ -151,11 +151,11 @@ async function installPackage({ packageName, alreadyInstalled, packageNameDispla
151
151
  }
152
152
  catch (e) {
153
153
  sdkInstallSpinner.stop('Installation failed.');
154
- (0, ui_1.getUI)().log.error(`${chalk_1.default.red('Encountered the following error during installation:')}\n\n${e}\n\n${chalk_1.default.dim(`The wizard has created a \`amplitude-wizard-installation-error-*.log\` file. If you think this issue is caused by the Amplitude wizard, create an issue on GitHub and include the log file's content:\n${constants_1.ISSUES_URL}`)}`);
154
+ (0, ui_1.getUI)().log.error(`${chalk_1.default.red('Encountered the following error during installation:')}\n\n${e}\n\n${chalk_1.default.dim(`The wizard has created a \`amplitude-wizard-installation-error-*.log\` file. If you think this issue is caused by the Amplitude wizard, create an issue on GitHub and include the log file's content:\n${constants_1.OUTBOUND_URLS.githubIssues}`)}`);
155
155
  await abort();
156
156
  }
157
157
  sdkInstallSpinner.stop(`${alreadyInstalled ? 'Updated' : 'Installed'} ${chalk_1.default.bold.cyan(packageNameDisplayLabel ?? packageName)} with ${chalk_1.default.bold(pkgManager.label)}.`);
158
- analytics_1.analytics.wizardCapture('package installed', {
158
+ analytics_1.analytics.wizardCapture('Package Installed', {
159
159
  package_name: packageName,
160
160
  package_manager: pkgManager.name,
161
161
  integration,
@@ -237,6 +237,57 @@ function isUsingTypeScript({ installDir, }) {
237
237
  return false;
238
238
  }
239
239
  }
240
+ /**
241
+ * Best-effort credentials for `--ci` when `--api-key` / AMPLITUDE_WIZARD_API_KEY
242
+ * is not set: project-local key (.env.local / keychain), then OAuth id token from
243
+ * ~/.ampli.json plus org/workspace from ampli.json (same resolution as interactive bootstrap).
244
+ */
245
+ async function tryResolveCredentialsForCi(installDir) {
246
+ const { readApiKeyWithSource } = await import('./api-key-store.js');
247
+ const local = readApiKeyWithSource(installDir);
248
+ if (local) {
249
+ return {
250
+ host: constants_1.DEFAULT_HOST_URL,
251
+ projectApiKey: local.key,
252
+ accessToken: local.key,
253
+ cloudRegion: 'us',
254
+ };
255
+ }
256
+ const { getStoredUser, getStoredToken } = await import('./ampli-settings.js');
257
+ const { readAmpliConfig } = await import('../lib/ampli-config.js');
258
+ const { getAPIKey } = await import('./get-api-key.js');
259
+ const { getHostFromRegion } = await import('./urls.js');
260
+ const storedUser = getStoredUser();
261
+ const realUser = storedUser && storedUser.id !== 'pending' ? storedUser : null;
262
+ const projectConfig = readAmpliConfig(installDir);
263
+ const projectZone = projectConfig.ok ? projectConfig.config.Zone : undefined;
264
+ const zone = realUser?.zone ?? projectZone ?? constants_1.DEFAULT_AMPLITUDE_ZONE;
265
+ const storedToken = realUser
266
+ ? getStoredToken(realUser.id, realUser.zone)
267
+ : getStoredToken(undefined, zone);
268
+ if (!storedToken?.idToken) {
269
+ return null;
270
+ }
271
+ const workspaceId = projectConfig.ok
272
+ ? projectConfig.config.WorkspaceId
273
+ : undefined;
274
+ const projectApiKey = await getAPIKey({
275
+ installDir,
276
+ idToken: storedToken.idToken,
277
+ zone,
278
+ workspaceId,
279
+ });
280
+ if (!projectApiKey) {
281
+ return null;
282
+ }
283
+ const cloudRegion = zone === 'eu' ? 'eu' : 'us';
284
+ return {
285
+ host: getHostFromRegion(cloudRegion),
286
+ projectApiKey,
287
+ accessToken: storedToken.idToken,
288
+ cloudRegion,
289
+ };
290
+ }
240
291
  /**
241
292
  * Get project data for the wizard via Amplitude OAuth or CI API key.
242
293
  *
@@ -258,6 +309,32 @@ async function getOrAskForProjectData(_options) {
258
309
  cloudRegion: 'us',
259
310
  };
260
311
  }
312
+ if (_options.ci) {
313
+ const ciInstallDir = _options.installDir;
314
+ if (!ciInstallDir) {
315
+ (0, ui_1.getUI)().log.error(chalk_1.default.red('CI mode requires --install-dir (or AMPLITUDE_WIZARD_INSTALL_DIR).'));
316
+ await (0, wizard_abort_1.wizardAbort)({
317
+ message: 'CI mode requires an install directory.',
318
+ });
319
+ }
320
+ else {
321
+ const resolved = await tryResolveCredentialsForCi(ciInstallDir);
322
+ if (resolved) {
323
+ (0, ui_1.getUI)().log.info(chalk_1.default.dim('Resolved Amplitude API key non-interactively (CI mode).'));
324
+ return {
325
+ host: resolved.host,
326
+ projectApiKey: resolved.projectApiKey,
327
+ accessToken: resolved.accessToken,
328
+ projectId: _options.projectId ?? 0,
329
+ cloudRegion: resolved.cloudRegion,
330
+ };
331
+ }
332
+ (0, ui_1.getUI)().log.error(chalk_1.default.red('CI mode could not resolve a project API key. Pass --api-key or AMPLITUDE_WIZARD_API_KEY, store a key in the project (.env.local / keychain), or ensure ~/.ampli.json has a valid OAuth session (and ampli.json includes WorkspaceId if needed).'));
333
+ await (0, wizard_abort_1.wizardAbort)({
334
+ message: 'CI mode requires a project API key or resolvable Amplitude credentials.',
335
+ });
336
+ }
337
+ }
261
338
  // Force fresh OAuth for projects that haven't been set up yet — no local
262
339
  // ampli.json means we don't know which Amplitude org this project belongs to.
263
340
  let forceFresh = false;
@@ -280,7 +357,7 @@ async function getOrAskForProjectData(_options) {
280
357
  async function askForWizardLogin(opts = {}) {
281
358
  // ── 1. Authenticate via Amplitude OAuth (reuses ampli CLI session) ──
282
359
  const auth = await (0, oauth_1.performAmplitudeAuth)({
283
- zone: constants_2.DEFAULT_AMPLITUDE_ZONE,
360
+ zone: constants_1.DEFAULT_AMPLITUDE_ZONE,
284
361
  forceFresh: opts.forceFresh,
285
362
  });
286
363
  // ── 2. Detect actual cloud region (EU users auth via US endpoint but
@@ -1,7 +1,7 @@
1
1
  type SupportedShell = 'zsh' | 'bash';
2
2
  export declare function detectShell(): SupportedShell | null;
3
- export declare const ZSH_COMPLETION_SCRIPT = "###-begin-amplitude-wizard-completions-###\n\n_amplitude_wizard() {\n local state\n local -a commands global_opts wizard_opts\n\n commands=(\n 'login:Log in to your Amplitude account'\n 'logout:Log out of your Amplitude account'\n 'whoami:Show the currently logged-in Amplitude account'\n 'slack:Set up Amplitude Slack integration'\n 'mcp:MCP server management commands'\n 'completion:Print shell completion script'\n )\n\n global_opts=(\n '--debug[Enable verbose logging]'\n '--verbose[Print diagnostic info to the run log]'\n '--signup[Create a new Amplitude account during setup]'\n '--ci[Enable non-interactive CI mode]'\n '--api-key[Amplitude project API key]:key:'\n '--project-id[Amplitude project ID]:id:'\n '--local-mcp[Use local MCP server at http://localhost:8787/mcp]'\n {-h,--help}'[Show help]'\n {-v,--version}'[Show version]'\n )\n\n wizard_opts=(\n '--force-install[Force package install even if peer checks fail]'\n '--install-dir[Directory to install Amplitude in]:dir:_files -/'\n '--integration[Framework integration to set up]:integration:(nextjs vue react-router django flask fastapi javascript_web javascript_node python)'\n '--menu[Show integration selection menu instead of auto-detecting]'\n '--benchmark[Run in benchmark mode with per-phase token tracking]'\n )\n\n _arguments -C \\\n '1: :->cmd' \\\n '*:: :->args'\n\n case $state in\n cmd)\n _describe 'command' commands\n _arguments $global_opts $wizard_opts\n ;;\n args)\n case ${words[1]} in\n mcp)\n local -a mcp_cmds\n mcp_cmds=('add:Install Amplitude MCP server' 'remove:Remove Amplitude MCP server')\n _arguments -C '1: :->sub' '*:: :->subargs'\n case $state in\n sub) _describe 'mcp command' mcp_cmds ;;\n subargs) _arguments '--local[Use local MCP server at http://localhost:8787]' ;;\n esac\n ;;\n login)\n _arguments '--zone[Amplitude data center zone]:zone:(us eu)'\n ;;\n *)\n _arguments $global_opts $wizard_opts\n ;;\n esac\n ;;\n esac\n}\n\n(( $+functions[compdef] )) || { autoload -Uz compinit; compinit; }\ncompdef _amplitude_wizard amplitude-wizard\n###-end-amplitude-wizard-completions-###";
4
- export declare const BASH_COMPLETION_SCRIPT = "###-begin-amplitude-wizard-completions-###\n_amplitude_wizard_completions() {\n local cur prev\n cur=\"${COMP_WORDS[COMP_CWORD]}\"\n prev=\"${COMP_WORDS[COMP_CWORD-1]}\"\n\n local commands=\"login logout whoami slack mcp completion\"\n local global_flags=\"--debug --verbose --signup --ci --api-key --project-id --local-mcp --help --version\"\n local wizard_flags=\"--force-install --install-dir --integration --menu --benchmark\"\n local integrations=\"nextjs vue react-router django flask fastapi javascript_web javascript_node python\"\n\n if [[ ${COMP_CWORD} -eq 1 ]]; then\n COMPREPLY=($(compgen -W \"$commands $global_flags $wizard_flags\" -- \"$cur\"))\n return\n fi\n\n case \"${COMP_WORDS[1]}\" in\n mcp)\n if [[ ${COMP_CWORD} -eq 2 ]]; then\n COMPREPLY=($(compgen -W \"add remove\" -- \"$cur\"))\n else\n COMPREPLY=($(compgen -W \"--local\" -- \"$cur\"))\n fi\n ;;\n login)\n if [[ \"$prev\" == \"--zone\" ]]; then\n COMPREPLY=($(compgen -W \"us eu\" -- \"$cur\"))\n else\n COMPREPLY=($(compgen -W \"--zone\" -- \"$cur\"))\n fi\n ;;\n *)\n if [[ \"$prev\" == \"--integration\" ]]; then\n COMPREPLY=($(compgen -W \"$integrations\" -- \"$cur\"))\n elif [[ \"$prev\" == \"--install-dir\" ]]; then\n COMPREPLY=($(compgen -d -- \"$cur\"))\n else\n COMPREPLY=($(compgen -W \"$global_flags $wizard_flags\" -- \"$cur\"))\n fi\n ;;\n esac\n}\ncomplete -F _amplitude_wizard_completions amplitude-wizard\n###-end-amplitude-wizard-completions-###";
3
+ export declare const ZSH_COMPLETION_SCRIPT = "###-begin-amplitude-wizard-completions-###\n\n_amplitude_wizard() {\n local state\n local -a commands global_opts wizard_opts\n\n commands=(\n 'login:Log in to your Amplitude account'\n 'logout:Log out of your Amplitude account'\n 'whoami:Show the currently logged-in Amplitude account'\n 'feedback:Send product feedback'\n 'slack:Set up Amplitude Slack integration'\n 'mcp:MCP server management commands'\n 'completion:Print shell completion script'\n )\n\n global_opts=(\n '--debug[Enable verbose logging]'\n '--verbose[Print diagnostic info to the run log]'\n '--signup[Create a new Amplitude account during setup]'\n '--ci[Enable non-interactive CI mode]'\n '--api-key[Amplitude project API key]:key:'\n '--project-id[Amplitude project ID]:id:'\n '--local-mcp[Use local MCP server at http://localhost:8787/mcp]'\n {-h,--help}'[Show help]'\n {-v,--version}'[Show version]'\n )\n\n wizard_opts=(\n '--force-install[Force package install even if peer checks fail]'\n '--install-dir[Directory to install Amplitude in]:dir:_files -/'\n '--integration[Framework integration to set up]:integration:(nextjs vue react-router django flask fastapi javascript_web javascript_node python)'\n '--menu[Show integration selection menu instead of auto-detecting]'\n '--benchmark[Run in benchmark mode with per-phase token tracking]'\n )\n\n _arguments -C \\\n '1: :->cmd' \\\n '*:: :->args'\n\n case $state in\n cmd)\n _describe 'command' commands\n _arguments $global_opts $wizard_opts\n ;;\n args)\n case ${words[1]} in\n mcp)\n local -a mcp_cmds\n mcp_cmds=('add:Install Amplitude MCP server' 'remove:Remove Amplitude MCP server')\n _arguments -C '1: :->sub' '*:: :->subargs'\n case $state in\n sub) _describe 'mcp command' mcp_cmds ;;\n subargs) _arguments '--local[Use local MCP server at http://localhost:8787]' ;;\n esac\n ;;\n login)\n _arguments '--zone[Amplitude data center zone]:zone:(us eu)'\n ;;\n feedback)\n _arguments '--message[Feedback message]:message:' '-m[Feedback message]:message:'\n ;;\n *)\n _arguments $global_opts $wizard_opts\n ;;\n esac\n ;;\n esac\n}\n\n(( $+functions[compdef] )) || { autoload -Uz compinit; compinit; }\ncompdef _amplitude_wizard amplitude-wizard\n###-end-amplitude-wizard-completions-###";
4
+ export declare const BASH_COMPLETION_SCRIPT = "###-begin-amplitude-wizard-completions-###\n_amplitude_wizard_completions() {\n local cur prev\n cur=\"${COMP_WORDS[COMP_CWORD]}\"\n prev=\"${COMP_WORDS[COMP_CWORD-1]}\"\n\n local commands=\"login logout whoami feedback slack mcp completion\"\n local global_flags=\"--debug --verbose --signup --ci --api-key --project-id --local-mcp --help --version\"\n local wizard_flags=\"--force-install --install-dir --integration --menu --benchmark\"\n local integrations=\"nextjs vue react-router django flask fastapi javascript_web javascript_node python\"\n\n if [[ ${COMP_CWORD} -eq 1 ]]; then\n COMPREPLY=($(compgen -W \"$commands $global_flags $wizard_flags\" -- \"$cur\"))\n return\n fi\n\n case \"${COMP_WORDS[1]}\" in\n mcp)\n if [[ ${COMP_CWORD} -eq 2 ]]; then\n COMPREPLY=($(compgen -W \"add remove\" -- \"$cur\"))\n else\n COMPREPLY=($(compgen -W \"--local\" -- \"$cur\"))\n fi\n ;;\n login)\n if [[ \"$prev\" == \"--zone\" ]]; then\n COMPREPLY=($(compgen -W \"us eu\" -- \"$cur\"))\n else\n COMPREPLY=($(compgen -W \"--zone\" -- \"$cur\"))\n fi\n ;;\n feedback)\n COMPREPLY=($(compgen -W \"--message -m\" -- \"$cur\"))\n ;;\n *)\n if [[ \"$prev\" == \"--integration\" ]]; then\n COMPREPLY=($(compgen -W \"$integrations\" -- \"$cur\"))\n elif [[ \"$prev\" == \"--install-dir\" ]]; then\n COMPREPLY=($(compgen -d -- \"$cur\"))\n else\n COMPREPLY=($(compgen -W \"$global_flags $wizard_flags\" -- \"$cur\"))\n fi\n ;;\n esac\n}\ncomplete -F _amplitude_wizard_completions amplitude-wizard\n###-end-amplitude-wizard-completions-###";
5
5
  /**
6
6
  * Silently appends `eval "$(amplitude-wizard completion)"` to the user's shell
7
7
  * RC file if it isn't already there. Call fire-and-forget at startup.
@@ -72,6 +72,7 @@ _amplitude_wizard() {
72
72
  'login:Log in to your Amplitude account'
73
73
  'logout:Log out of your Amplitude account'
74
74
  'whoami:Show the currently logged-in Amplitude account'
75
+ 'feedback:Send product feedback'
75
76
  'slack:Set up Amplitude Slack integration'
76
77
  'mcp:MCP server management commands'
77
78
  'completion:Print shell completion script'
@@ -120,6 +121,9 @@ _amplitude_wizard() {
120
121
  login)
121
122
  _arguments '--zone[Amplitude data center zone]:zone:(us eu)'
122
123
  ;;
124
+ feedback)
125
+ _arguments '--message[Feedback message]:message:' '-m[Feedback message]:message:'
126
+ ;;
123
127
  *)
124
128
  _arguments $global_opts $wizard_opts
125
129
  ;;
@@ -137,7 +141,7 @@ _amplitude_wizard_completions() {
137
141
  cur="${DB}COMP_WORDS[COMP_CWORD]}"
138
142
  prev="${DB}COMP_WORDS[COMP_CWORD-1]}"
139
143
 
140
- local commands="login logout whoami slack mcp completion"
144
+ local commands="login logout whoami feedback slack mcp completion"
141
145
  local global_flags="--debug --verbose --signup --ci --api-key --project-id --local-mcp --help --version"
142
146
  local wizard_flags="--force-install --install-dir --integration --menu --benchmark"
143
147
  local integrations="nextjs vue react-router django flask fastapi javascript_web javascript_node python"
@@ -162,6 +166,9 @@ _amplitude_wizard_completions() {
162
166
  COMPREPLY=($(compgen -W "--zone" -- "$cur"))
163
167
  fi
164
168
  ;;
169
+ feedback)
170
+ COMPREPLY=($(compgen -W "--message -m" -- "$cur"))
171
+ ;;
165
172
  *)
166
173
  if [[ "$prev" == "--integration" ]]; then
167
174
  COMPREPLY=($(compgen -W "$integrations" -- "$cur"))
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Send a single feedback event to Amplitude via the Node SDK.
3
+ * Uses the same API key and server URL as other wizard telemetry.
4
+ */
5
+ export declare function trackWizardFeedback(message: string): Promise<void>;
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.trackWizardFeedback = trackWizardFeedback;
4
+ const analytics_node_1 = require("@amplitude/analytics-node");
5
+ const uuid_1 = require("uuid");
6
+ const analytics_js_1 = require("./analytics.js");
7
+ /**
8
+ * Send a single feedback event to Amplitude via the Node SDK.
9
+ * Uses the same API key and server URL as other wizard telemetry.
10
+ */
11
+ async function trackWizardFeedback(message) {
12
+ const trimmed = message.trim();
13
+ if (!trimmed) {
14
+ throw new Error('Feedback message cannot be empty');
15
+ }
16
+ const apiKey = (0, analytics_js_1.resolveTelemetryApiKey)();
17
+ if (!apiKey) {
18
+ throw new Error('Feedback cannot be sent: set AMPLITUDE_API_KEY or unset it to use the default telemetry project.');
19
+ }
20
+ const client = (0, analytics_node_1.createInstance)();
21
+ await client.init(apiKey, { serverUrl: (0, analytics_js_1.getAmplitudeNodeServerUrl)() }).promise;
22
+ const deviceId = (0, uuid_1.v4)();
23
+ client.track(analytics_js_1.WIZARD_FEEDBACK_EVENT_TYPE, { message: trimmed }, { device_id: deviceId });
24
+ await client.flush().promise;
25
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@amplitude/wizard",
3
- "version": "1.0.0-beta.0",
3
+ "version": "1.0.0-beta.1",
4
4
  "homepage": "https://github.com/amplitude/wizard",
5
5
  "repository": "https://github.com/amplitude/wizard",
6
6
  "description": "The Amplitude wizard helps you to configure your project",
@@ -37,6 +37,7 @@
37
37
  },
38
38
  "dependencies": {
39
39
  "@amplitude/analytics-browser": "^2.0.0",
40
+ "@amplitude/analytics-node": "^1.5.51",
40
41
  "@anthropic-ai/claude-agent-sdk": "0.2.7",
41
42
  "@inkjs/ui": "^2.0.0",
42
43
  "@inquirer/prompts": "^8.3.0",