assistant-ui 0.0.111 → 0.0.113

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 (90) hide show
  1. package/dist/codemods/v0-12/assistant-api-to-aui.d.ts.map +1 -1
  2. package/dist/codemods/v0-12/assistant-api-to-aui.js +87 -62
  3. package/dist/codemods/v0-12/assistant-api-to-aui.js.map +1 -1
  4. package/dist/codemods/v0-12/primitive-if-to-aui-if.d.ts.map +1 -1
  5. package/dist/codemods/v0-12/primitive-if-to-aui-if.js +31 -45
  6. package/dist/codemods/v0-12/primitive-if-to-aui-if.js.map +1 -1
  7. package/dist/commands/add.d.ts +1 -1
  8. package/dist/commands/add.d.ts.map +1 -1
  9. package/dist/commands/add.js +4 -2
  10. package/dist/commands/add.js.map +1 -1
  11. package/dist/commands/create.d.ts.map +1 -1
  12. package/dist/commands/create.js +33 -10
  13. package/dist/commands/create.js.map +1 -1
  14. package/dist/commands/info.d.ts.map +1 -1
  15. package/dist/commands/info.js +2 -1
  16. package/dist/commands/info.js.map +1 -1
  17. package/dist/commands/init.d.ts.map +1 -1
  18. package/dist/commands/init.js +4 -2
  19. package/dist/commands/init.js.map +1 -1
  20. package/dist/commands/mcp.d.ts.map +1 -1
  21. package/dist/commands/mcp.js +25 -28
  22. package/dist/commands/mcp.js.map +1 -1
  23. package/dist/commands/update.js +6 -7
  24. package/dist/commands/update.js.map +1 -1
  25. package/dist/commands/upgrade.d.ts.map +1 -1
  26. package/dist/commands/upgrade.js +5 -2
  27. package/dist/commands/upgrade.js.map +1 -1
  28. package/dist/index.js +2 -6
  29. package/dist/index.js.map +1 -1
  30. package/dist/lib/agent-skill.d.ts +1 -1
  31. package/dist/lib/agent-skill.d.ts.map +1 -1
  32. package/dist/lib/agent-skill.js.map +1 -1
  33. package/dist/lib/create-project.d.ts +2 -3
  34. package/dist/lib/create-project.d.ts.map +1 -1
  35. package/dist/lib/create-project.js +17 -42
  36. package/dist/lib/create-project.js.map +1 -1
  37. package/dist/lib/handle-cli-error.d.ts +5 -0
  38. package/dist/lib/handle-cli-error.d.ts.map +1 -0
  39. package/dist/lib/handle-cli-error.js +17 -0
  40. package/dist/lib/handle-cli-error.js.map +1 -0
  41. package/dist/lib/install-ai-sdk-lib.js +8 -1
  42. package/dist/lib/install-ai-sdk-lib.js.map +1 -1
  43. package/dist/lib/install-edge-lib.js +4 -8
  44. package/dist/lib/install-edge-lib.js.map +1 -1
  45. package/dist/lib/run-spawn.d.ts +16 -2
  46. package/dist/lib/run-spawn.d.ts.map +1 -1
  47. package/dist/lib/run-spawn.js +87 -9
  48. package/dist/lib/run-spawn.js.map +1 -1
  49. package/dist/lib/transform.d.ts +1 -1
  50. package/dist/lib/transform.d.ts.map +1 -1
  51. package/dist/lib/transform.js +12 -25
  52. package/dist/lib/transform.js.map +1 -1
  53. package/dist/lib/upgrade.js +20 -16
  54. package/dist/lib/upgrade.js.map +1 -1
  55. package/dist/lib/utils/file-scanner.d.ts +9 -1
  56. package/dist/lib/utils/file-scanner.d.ts.map +1 -1
  57. package/dist/lib/utils/file-scanner.js +22 -20
  58. package/dist/lib/utils/file-scanner.js.map +1 -1
  59. package/dist/lib/utils/package-installer.js +1 -1
  60. package/dist/lib/utils/package-manager.d.ts +3 -1
  61. package/dist/lib/utils/package-manager.d.ts.map +1 -1
  62. package/dist/lib/utils/package-manager.js +22 -10
  63. package/dist/lib/utils/package-manager.js.map +1 -1
  64. package/package.json +6 -6
  65. package/plugin/skills/assistant-ui/SKILL.md +3 -3
  66. package/src/codemods/v0-12/__tests__/assistant-api-to-aui.test.ts +370 -0
  67. package/src/codemods/v0-12/__tests__/primitive-if-to-aui-if.test.ts +100 -0
  68. package/src/codemods/v0-12/assistant-api-to-aui.ts +227 -134
  69. package/src/codemods/v0-12/primitive-if-to-aui-if.ts +44 -72
  70. package/src/commands/add.ts +5 -5
  71. package/src/commands/create.ts +41 -7
  72. package/src/commands/info.ts +1 -0
  73. package/src/commands/init.ts +4 -6
  74. package/src/commands/mcp.ts +20 -29
  75. package/src/commands/update.ts +6 -8
  76. package/src/commands/upgrade.ts +5 -2
  77. package/src/index.ts +2 -7
  78. package/src/lib/agent-skill.ts +2 -1
  79. package/src/lib/create-project.ts +24 -58
  80. package/src/lib/handle-cli-error.test.ts +67 -0
  81. package/src/lib/handle-cli-error.ts +17 -0
  82. package/src/lib/install-ai-sdk-lib.ts +13 -1
  83. package/src/lib/install-edge-lib.ts +7 -8
  84. package/src/lib/run-spawn.test.ts +148 -0
  85. package/src/lib/run-spawn.ts +121 -11
  86. package/src/lib/transform.test.ts +62 -0
  87. package/src/lib/transform.ts +21 -37
  88. package/src/lib/upgrade.ts +23 -19
  89. package/src/lib/utils/file-scanner.ts +26 -20
  90. package/src/lib/utils/package-manager.ts +29 -12
@@ -1,6 +1,7 @@
1
+ import { SpawnExitError, SpawnSignalError, hasActiveSpawn, runSpawn } from "../lib/run-spawn.js";
1
2
  import { logger } from "../lib/utils/logger.js";
2
- import { SpawnExitError, runSpawn } from "../lib/run-spawn.js";
3
- import { dlxCommand, downloadProject, resolveLatestReleaseRef, resolvePackageManager, resolvePackageManagerForCwd, scaffoldProject, transformProject } from "../lib/create-project.js";
3
+ import { resolvePackageManagerForCwd } from "../lib/utils/package-manager.js";
4
+ import { dlxCommand, downloadProject, resolveLatestReleaseRef, resolvePackageManager, scaffoldProject, transformProject } from "../lib/create-project.js";
4
5
  import { buildSkillsAddCommand, resolveSkillsInstall } from "../lib/agent-skill.js";
5
6
  import { Command, Option } from "commander";
6
7
  import chalk from "chalk";
@@ -416,13 +417,30 @@ const create = new Command().name("create").description("create a new project").
416
417
  logger.info(`Creating project from ${project.category}: ${project.label}`);
417
418
  logger.break();
418
419
  const pm = await resolvePackageManagerForCwd(path.dirname(absoluteProjectDir), resolvePackageManager(opts));
420
+ let cleanupArmed = true;
419
421
  const cleanupOnExit = () => {
422
+ if (!cleanupArmed) return;
423
+ cleanupArmed = false;
420
424
  fs.rmSync(absoluteProjectDir, {
421
425
  recursive: true,
422
426
  force: true
423
427
  });
424
428
  };
429
+ const disarmCleanup = () => {
430
+ cleanupArmed = false;
431
+ process.removeListener("exit", cleanupOnExit);
432
+ process.removeListener("SIGINT", cleanupOnSignal);
433
+ process.removeListener("SIGTERM", cleanupOnSignal);
434
+ };
435
+ const cleanupOnSignal = (signal) => {
436
+ if (hasActiveSpawn()) return;
437
+ cleanupOnExit();
438
+ disarmCleanup();
439
+ process.kill(process.pid, signal);
440
+ };
425
441
  process.once("exit", cleanupOnExit);
442
+ process.on("SIGINT", cleanupOnSignal);
443
+ process.on("SIGTERM", cleanupOnSignal);
426
444
  try {
427
445
  if (!localSourceRoot) logger.step("Resolving latest release...");
428
446
  const ref = await refPromise;
@@ -456,19 +474,18 @@ const create = new Command().name("create").description("create a new project").
456
474
  const [skillsCmd, skillsArgs] = buildSkillsAddCommand(pm, { stdinIsTTY });
457
475
  try {
458
476
  await runSpawn(skillsCmd, skillsArgs, absoluteProjectDir);
459
- } catch {
477
+ } catch (error) {
478
+ if (error instanceof SpawnSignalError) throw error;
460
479
  logger.warn(`Could not add assistant-ui agent skills. You can add them later with:\n ${skillsCmd} ${skillsArgs.join(" ")}`);
461
480
  }
462
481
  }
463
482
  } catch (err) {
464
- fs.rmSync(absoluteProjectDir, {
465
- recursive: true,
466
- force: true
467
- });
483
+ cleanupOnExit();
484
+ disarmCleanup();
468
485
  throw err;
469
486
  }
470
487
  if (transformResult.registryInstallFailure) {
471
- process.removeListener("exit", cleanupOnExit);
488
+ disarmCleanup();
472
489
  logger.break();
473
490
  logger.error("Project created with missing components.");
474
491
  logger.info("Retry the component install with:");
@@ -490,7 +507,8 @@ const create = new Command().name("create").description("create a new project").
490
507
  "--overwrite",
491
508
  presetUrl
492
509
  ], absoluteProjectDir);
493
- } catch {
510
+ } catch (error) {
511
+ if (error instanceof SpawnSignalError) throw error;
494
512
  logger.warn(`Preset application failed. You can retry manually with:\n ${dlxCmd} ${[
495
513
  ...dlxArgs,
496
514
  "shadcn@latest",
@@ -499,7 +517,7 @@ const create = new Command().name("create").description("create a new project").
499
517
  ].join(" ")}`);
500
518
  }
501
519
  }
502
- process.removeListener("exit", cleanupOnExit);
520
+ disarmCleanup();
503
521
  logger.break();
504
522
  logger.success("Project created successfully!");
505
523
  logger.break();
@@ -517,6 +535,11 @@ const create = new Command().name("create").description("create a new project").
517
535
  logger.info(` # Set up your environment variables in ${envFile}`);
518
536
  logger.info(` ${runCmd} ${devScript}`);
519
537
  } catch (error) {
538
+ if (error instanceof SpawnSignalError) {
539
+ cleanupOnExit();
540
+ disarmCleanup();
541
+ throw error;
542
+ }
520
543
  if (error instanceof SpawnExitError) {
521
544
  logger.error(`Project creation failed with code ${error.code}`);
522
545
  process.exit(error.code);
@@ -1 +1 @@
1
- {"version":3,"file":"create.js","names":[],"sources":["../../src/commands/create.ts"],"sourcesContent":["import { Command, Option } from \"commander\";\nimport chalk from \"chalk\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport * as p from \"@clack/prompts\";\nimport { logger } from \"../lib/utils/logger\";\nimport {\n dlxCommand,\n downloadProject,\n resolveLatestReleaseRef,\n resolvePackageManager,\n resolvePackageManagerForCwd,\n scaffoldProject,\n transformProject,\n type TransformResult,\n} from \"../lib/create-project\";\nimport { runSpawn, SpawnExitError } from \"../lib/run-spawn\";\nimport {\n buildSkillsAddCommand,\n resolveSkillsInstall,\n} from \"../lib/agent-skill\";\n\nexport interface ProjectMetadata {\n name: string;\n label: string;\n description?: string;\n category: \"template\" | \"example\";\n path: string;\n hasLocalComponents: boolean;\n}\n\nexport const PROJECT_METADATA: ProjectMetadata[] = [\n // Templates\n {\n name: \"default\",\n label: \"Default\",\n description: \"Default template with Vercel AI SDK\",\n category: \"template\",\n path: \"templates/default\",\n hasLocalComponents: false,\n },\n {\n name: \"minimal\",\n label: \"Minimal\",\n description: \"Bare-bones starting point\",\n category: \"template\",\n path: \"templates/minimal\",\n hasLocalComponents: true,\n },\n {\n name: \"cloud\",\n label: \"Cloud\",\n description: \"Cloud-backed persistence starter\",\n category: \"template\",\n path: \"templates/cloud\",\n hasLocalComponents: false,\n },\n {\n name: \"cloud-clerk\",\n label: \"Cloud + Clerk\",\n description: \"Cloud-backed starter with Clerk auth\",\n category: \"template\",\n path: \"templates/cloud-clerk\",\n hasLocalComponents: false,\n },\n {\n name: \"langchain\",\n label: \"LangChain\",\n description: \"LangGraph starter with the react-langchain adapter\",\n category: \"template\",\n path: \"templates/langchain\",\n hasLocalComponents: false,\n },\n {\n name: \"mcp\",\n label: \"MCP\",\n description: \"MCP tools + MCP Apps renderer starter\",\n category: \"template\",\n path: \"templates/mcp\",\n hasLocalComponents: false,\n },\n {\n name: \"eve\",\n label: \"Eve\",\n description: \"Eve agent + Next.js starter\",\n category: \"template\",\n path: \"templates/eve\",\n hasLocalComponents: false,\n },\n // Examples\n {\n name: \"with-ag-ui\",\n label: \"AG-UI\",\n description: \"AG-UI protocol integration\",\n category: \"example\",\n path: \"examples/with-ag-ui\",\n hasLocalComponents: false,\n },\n {\n name: \"with-google-adk\",\n label: \"Google ADK\",\n description: \"Google ADK agent integration\",\n category: \"example\",\n path: \"examples/with-google-adk\",\n hasLocalComponents: false,\n },\n {\n name: \"with-ai-sdk-v7\",\n label: \"AI SDK v7\",\n description: \"Vercel AI SDK v7\",\n category: \"example\",\n path: \"examples/with-ai-sdk-v7\",\n hasLocalComponents: false,\n },\n {\n name: \"with-eve\",\n label: \"Eve\",\n description: \"Eve agent integration\",\n category: \"example\",\n path: \"examples/with-eve\",\n hasLocalComponents: false,\n },\n {\n name: \"with-artifacts\",\n label: \"Artifacts\",\n description: \"Artifact rendering\",\n category: \"example\",\n path: \"examples/with-artifacts\",\n hasLocalComponents: false,\n },\n {\n name: \"with-assistant-transport\",\n label: \"Assistant Transport\",\n description: \"Assistant transport protocol\",\n category: \"example\",\n path: \"examples/with-assistant-transport\",\n hasLocalComponents: false,\n },\n {\n name: \"with-chain-of-thought\",\n label: \"Chain of Thought\",\n description: \"Chain-of-thought, tool calls, and source citations\",\n category: \"example\",\n path: \"examples/with-chain-of-thought\",\n hasLocalComponents: false,\n },\n {\n name: \"with-cloud\",\n label: \"Cloud Example\",\n description: \"Cloud integration example\",\n category: \"example\",\n path: \"examples/with-cloud\",\n hasLocalComponents: false,\n },\n {\n name: \"with-custom-thread-list\",\n label: \"Custom Thread List\",\n description: \"Custom thread list UI\",\n category: \"example\",\n path: \"examples/with-custom-thread-list\",\n hasLocalComponents: false,\n },\n {\n name: \"with-elevenlabs-conversational\",\n label: \"ElevenLabs Conversational\",\n description: \"Realtime voice with ElevenLabs\",\n category: \"example\",\n path: \"examples/with-elevenlabs-conversational\",\n hasLocalComponents: false,\n },\n {\n name: \"with-elevenlabs-scribe\",\n label: \"ElevenLabs Scribe\",\n description: \"Audio/speech integration\",\n category: \"example\",\n path: \"examples/with-elevenlabs-scribe\",\n hasLocalComponents: false,\n },\n {\n name: \"with-livekit\",\n label: \"LiveKit Voice\",\n description: \"Realtime voice with LiveKit\",\n category: \"example\",\n path: \"examples/with-livekit\",\n hasLocalComponents: false,\n },\n {\n name: \"with-expo\",\n label: \"Expo\",\n description: \"Expo / React Native\",\n category: \"example\",\n path: \"examples/with-expo\",\n hasLocalComponents: true,\n },\n {\n name: \"with-interactables\",\n label: \"Interactables\",\n description: \"AI-driven interactive UI components\",\n category: \"example\",\n path: \"examples/with-interactables\",\n hasLocalComponents: false,\n },\n {\n name: \"with-external-store\",\n label: \"External Store\",\n description: \"Custom message store\",\n category: \"example\",\n path: \"examples/with-external-store\",\n hasLocalComponents: false,\n },\n {\n name: \"with-ffmpeg\",\n label: \"FFmpeg\",\n description: \"File processing\",\n category: \"example\",\n path: \"examples/with-ffmpeg\",\n hasLocalComponents: false,\n },\n {\n name: \"with-langgraph\",\n label: \"LangGraph Example\",\n description: \"LangGraph integration\",\n category: \"example\",\n path: \"examples/with-langgraph\",\n hasLocalComponents: false,\n },\n {\n name: \"with-react-hook-form\",\n label: \"React Hook Form\",\n description: \"Form integration\",\n category: \"example\",\n path: \"examples/with-react-hook-form\",\n hasLocalComponents: false,\n },\n {\n name: \"with-react-ink\",\n label: \"React Ink\",\n description: \"Terminal UI chat\",\n category: \"example\",\n path: \"examples/with-react-ink\",\n hasLocalComponents: true,\n },\n {\n name: \"with-react-router\",\n label: \"React Router\",\n description: \"React Router v7 + Vite\",\n category: \"example\",\n path: \"examples/with-react-router\",\n hasLocalComponents: false,\n },\n {\n name: \"with-tanstack\",\n label: \"TanStack\",\n description: \"TanStack/React Router + Vite\",\n category: \"example\",\n path: \"examples/with-tanstack\",\n hasLocalComponents: false,\n },\n {\n name: \"with-resumable-stream\",\n label: \"Resumable Stream\",\n description: \"Resumable LLM stream that survives reload mid-response\",\n category: \"example\",\n path: \"examples/with-resumable-stream\",\n hasLocalComponents: false,\n },\n {\n name: \"with-openui\",\n label: \"OpenUI\",\n description: \"OpenUI generative UI integration\",\n category: \"example\",\n path: \"examples/with-openui\",\n hasLocalComponents: false,\n },\n];\n\n// Examples that exist in the monorepo but are intentionally excluded from the CLI:\n//\n// - waterfall: Still in development, not ready for production.\n// - with-cloud-standalone: For cloud without assistant-ui — not for the\n// assistant-ui CLI.\n// - with-store: In development, not ready for public use of the tap store.\n// - with-tap-runtime: In development, not ready for public use of the tap\n// store.\n\nconst templateNames = PROJECT_METADATA.filter(\n (m) => m.category === \"template\",\n).map((m) => m.name);\n\nconst exampleNames = PROJECT_METADATA.filter(\n (m) => m.category === \"example\",\n).map((m) => m.name);\n\nexport async function resolveProject(params: {\n template?: string;\n example?: string;\n stdinIsTTY?: boolean;\n select?: typeof p.select;\n isCancel?: typeof p.isCancel;\n}): Promise<ProjectMetadata | null> {\n const {\n template,\n example,\n stdinIsTTY = process.stdin.isTTY,\n select = p.select,\n isCancel = p.isCancel,\n } = params;\n\n if (template !== undefined) {\n const meta = PROJECT_METADATA.find(\n (m) => m.name === template && m.category === \"template\",\n );\n if (!meta) {\n logger.error(`Unknown template: ${template}`);\n logger.info(`Available templates: ${templateNames.join(\", \")}`);\n process.exit(1);\n }\n return meta;\n }\n\n if (example !== undefined) {\n const meta = PROJECT_METADATA.find(\n (m) => m.name === example && m.category === \"example\",\n );\n if (!meta) {\n logger.error(`Unknown example: ${example}`);\n logger.info(`Available examples: ${exampleNames.join(\", \")}`);\n process.exit(1);\n }\n return meta;\n }\n\n if (!stdinIsTTY) {\n return PROJECT_METADATA.find((m) => m.name === \"default\")!;\n }\n\n const selected = await select({\n message: \"Select a project to scaffold:\",\n options: [\n {\n value: \"_separator\",\n label: \"────── Starter Templates ──────\",\n disabled: true,\n },\n ...PROJECT_METADATA.filter((m) => m.category === \"template\").map((m) => ({\n value: m.name,\n label: m.label,\n ...(m.description ? { hint: m.description } : {}),\n })),\n {\n value: \"_separator\",\n label: \"────── Feature Examples ──────\",\n disabled: true,\n },\n ...PROJECT_METADATA.filter((m) => m.category === \"example\").map((m) => ({\n value: m.name,\n label: m.label,\n ...(m.description ? { hint: m.description } : {}),\n })),\n ],\n });\n\n if (isCancel(selected)) {\n return null;\n }\n\n const meta = PROJECT_METADATA.find((m) => m.name === selected);\n if (!meta) {\n logger.error(`Unknown selection: ${String(selected)}`);\n process.exit(1);\n }\n return meta;\n}\n\nexport function resolveCreateProjectDirectory(params: {\n projectDirectory?: string;\n stdinIsTTY?: boolean;\n}): string | undefined {\n const { projectDirectory, stdinIsTTY = process.stdin.isTTY } = params;\n\n if (projectDirectory) return projectDirectory;\n if (!stdinIsTTY) return \"my-aui-app\";\n return undefined;\n}\n\nconst PLAYGROUND_PRESET_BASE_URL =\n \"https://www.assistant-ui.com/playground/init\";\n\nexport function resolvePresetUrl(preset: string): string {\n if (preset.startsWith(\"http://\") || preset.startsWith(\"https://\")) {\n return preset;\n }\n return `${PLAYGROUND_PRESET_BASE_URL}?preset=${encodeURIComponent(preset)}`;\n}\n\nexport interface ScaffoldSelectorOptions {\n template?: string;\n example?: string;\n preset?: string;\n native?: boolean;\n ink?: boolean;\n}\n\nexport interface ResolvedScaffoldSelector {\n template?: string;\n example?: string;\n preset?: string;\n}\n\nconst scaffoldSelectorHelp =\n \"Choose one scaffold selector: --template <name>, --example <name>, --native, or --ink. --preset <name-or-url> can be used with --template or by itself.\";\n\nfunction getPresetConflict(opts: ScaffoldSelectorOptions): string | undefined {\n if (opts.example !== undefined) return \"--example\";\n if (opts.native) return \"--native\";\n if (opts.ink) return \"--ink\";\n return undefined;\n}\n\nexport function resolveScaffoldSelector(\n opts: ScaffoldSelectorOptions,\n): ResolvedScaffoldSelector {\n const hasPreset = opts.preset !== undefined;\n const presetConflict = getPresetConflict(opts);\n const selectors = [\n opts.template !== undefined ? \"--template\" : undefined,\n opts.example !== undefined ? \"--example\" : undefined,\n opts.native ? \"--native\" : undefined,\n opts.ink ? \"--ink\" : undefined,\n ].filter((selector): selector is string => selector !== undefined);\n\n if (selectors.length > 1) {\n throw new Error(\n `Only one scaffold selector can be provided (${selectors.join(\", \")}). ${scaffoldSelectorHelp}`,\n );\n }\n\n if (hasPreset && presetConflict) {\n throw new Error(\n `Cannot use --preset with ${presetConflict}. ${scaffoldSelectorHelp}`,\n );\n }\n\n if (opts.native) return { example: \"with-expo\" };\n if (opts.ink) return { example: \"with-react-ink\" };\n\n if (opts.preset !== undefined && opts.template === undefined) {\n return { template: \"default\", preset: opts.preset };\n }\n\n return {\n ...(opts.template !== undefined && { template: opts.template }),\n ...(opts.example !== undefined && { example: opts.example }),\n ...(hasPreset && { preset: opts.preset }),\n };\n}\n\nexport const create = new Command()\n .name(\"create\")\n .description(\"create a new project\")\n .argument(\"[project-directory]\")\n .usage(`${chalk.green(\"[project-directory]\")} [options]`)\n .option(\n \"-t, --template <template>\",\n `template to use (${templateNames.join(\", \")})`,\n )\n .option(\n \"-e, --example <example>\",\n `create from an example (${exampleNames.join(\", \")})`,\n )\n .option(\n \"-p, --preset <name-or-url>\",\n \"preset name or URL (e.g., chatgpt or https://www.assistant-ui.com/playground/init?preset=chatgpt)\",\n )\n .option(\"--use-npm\", \"explicitly use npm\")\n .option(\"--use-pnpm\", \"explicitly use pnpm\")\n .option(\"--use-yarn\", \"explicitly use yarn\")\n .option(\"--use-bun\", \"explicitly use bun\")\n .option(\"--native\", \"create an Expo / React Native project\")\n .option(\"--ink\", \"create a React Ink terminal project\")\n .option(\"--skip-install\", \"skip installing packages\")\n .option(\"--skills\", \"add assistant-ui agent skills for AI coding assistants\")\n .option(\"--no-skills\", \"skip adding assistant-ui agent skills\")\n .addOption(\n new Option(\n \"--debug-source-root <path>\",\n \"copy templates/examples from a local assistant-ui repo root\",\n ).hideHelp(),\n )\n .action(async (projectDirectory, opts) => {\n let scaffoldSelector: ResolvedScaffoldSelector;\n try {\n scaffoldSelector = resolveScaffoldSelector(opts);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n logger.error(message);\n process.exit(1);\n }\n\n const localSourceRoot = opts.debugSourceRoot\n ? path.resolve(opts.debugSourceRoot)\n : undefined;\n\n // Start release ref resolution early (runs during user prompts)\n const refPromise = localSourceRoot\n ? Promise.resolve(undefined)\n : resolveLatestReleaseRef();\n\n // 1. Resolve project directory\n let resolvedProjectDirectory = resolveCreateProjectDirectory({\n projectDirectory,\n });\n\n if (!resolvedProjectDirectory) {\n const result = await p.text({\n message: \"Project name:\",\n placeholder: \"my-aui-app\",\n defaultValue: \"my-aui-app\",\n validate: (value?: string) => {\n const name = (value ?? \"\").trim();\n if (!name) return \"Project name cannot be empty\";\n if (name === \".\" || name === \"..\")\n return \"Project name cannot be . or ..\";\n if (name.includes(\"/\") || name.includes(\"\\\\\"))\n return \"Project name cannot contain path separators\";\n return undefined;\n },\n });\n\n if (p.isCancel(result)) {\n p.cancel(\"Project creation cancelled.\");\n process.exit(0);\n }\n\n resolvedProjectDirectory = result;\n }\n\n // Check directory\n const absoluteProjectDir = path.resolve(resolvedProjectDirectory);\n try {\n const files = fs.readdirSync(absoluteProjectDir);\n if (files.length > 0) {\n logger.error(\n `Directory ${resolvedProjectDirectory} already exists and is not empty`,\n );\n process.exit(1);\n }\n } catch (err: unknown) {\n const code =\n err instanceof Error ? (err as NodeJS.ErrnoException).code : undefined;\n if (code === \"ENOENT\") {\n // Directory doesn't exist — good, proceed\n } else if (code === \"ENOTDIR\") {\n logger.error(\n `${resolvedProjectDirectory} already exists and is not a directory`,\n );\n process.exit(1);\n } else {\n const message = err instanceof Error ? err.message : String(err);\n logger.error(`Cannot access ${resolvedProjectDirectory}: ${message}`);\n process.exit(1);\n }\n }\n\n // 2. Resolve scaffold target\n const project = await resolveProject(scaffoldSelector);\n if (!project) {\n p.cancel(\"Project creation cancelled.\");\n process.exit(0);\n }\n\n const stdinIsTTY = process.stdin.isTTY;\n let installSkills = resolveSkillsInstall({\n skills: opts.skills,\n stdinIsTTY,\n });\n if (installSkills === undefined) {\n const result = await p.confirm({\n message: \"Add assistant-ui agent skills for AI coding assistants?\",\n initialValue: true,\n });\n\n if (p.isCancel(result)) {\n p.cancel(\"Project creation cancelled.\");\n process.exit(0);\n }\n\n installSkills = result;\n }\n\n logger.info(`Creating project from ${project.category}: ${project.label}`);\n logger.break();\n\n const pm = await resolvePackageManagerForCwd(\n path.dirname(absoluteProjectDir),\n resolvePackageManager(opts),\n );\n\n // Clean up partial project directory on unexpected exit (e.g. Ctrl+C)\n const cleanupOnExit = () => {\n fs.rmSync(absoluteProjectDir, { recursive: true, force: true });\n };\n process.once(\"exit\", cleanupOnExit);\n\n try {\n // 3. Resolve latest release ref (started before prompts)\n if (!localSourceRoot) {\n logger.step(\"Resolving latest release...\");\n }\n const ref = await refPromise;\n if (!localSourceRoot && !ref) {\n logger.warn(\"Could not resolve latest release, downloading from HEAD\");\n }\n\n // 4. Scaffold project\n logger.step(\n localSourceRoot\n ? `Copying project from local source: ${localSourceRoot}`\n : \"Downloading project...\",\n );\n let transformResult: TransformResult;\n try {\n const source = localSourceRoot\n ? { kind: \"local\" as const, rootDir: localSourceRoot }\n : {\n kind: \"github\" as const,\n ref,\n };\n await scaffoldProject(project.path, absoluteProjectDir, source);\n\n // If the template didn't exist at the release tag, retry from HEAD\n if (\n !localSourceRoot &&\n ref &&\n !fs.existsSync(path.join(absoluteProjectDir, \"package.json\"))\n ) {\n fs.rmSync(absoluteProjectDir, { recursive: true, force: true });\n logger.warn(\n \"Template not found at release tag, downloading from HEAD\",\n );\n await downloadProject(project.path, absoluteProjectDir);\n }\n\n // 5. Run transform pipeline\n transformResult = await transformProject(absoluteProjectDir, {\n hasLocalComponents: project.hasLocalComponents,\n skipInstall: opts.skipInstall,\n packageManager: pm,\n });\n\n if (installSkills) {\n logger.step(\"Adding assistant-ui agent skills...\");\n const [skillsCmd, skillsArgs] = buildSkillsAddCommand(pm, {\n stdinIsTTY,\n });\n try {\n await runSpawn(skillsCmd, skillsArgs, absoluteProjectDir);\n } catch {\n logger.warn(\n `Could not add assistant-ui agent skills. You can add them later with:\\n ${skillsCmd} ${skillsArgs.join(\" \")}`,\n );\n }\n }\n } catch (err) {\n // Clean up partially created project directory\n fs.rmSync(absoluteProjectDir, { recursive: true, force: true });\n throw err;\n }\n\n if (transformResult.registryInstallFailure) {\n process.removeListener(\"exit\", cleanupOnExit);\n logger.break();\n logger.error(\"Project created with missing components.\");\n logger.info(\"Retry the component install with:\");\n logger.info(` cd ${resolvedProjectDirectory}`);\n logger.info(` ${transformResult.registryInstallFailure.retryCommand}`);\n process.exit(1);\n }\n\n // 6. Apply preset if provided\n if (scaffoldSelector.preset) {\n const presetUrl = resolvePresetUrl(scaffoldSelector.preset);\n logger.info(\"Applying preset configuration...\");\n logger.break();\n const [dlxCmd, dlxArgs] = dlxCommand(pm);\n try {\n await runSpawn(\n dlxCmd,\n [\n ...dlxArgs,\n \"shadcn@latest\",\n \"add\",\n \"--yes\",\n \"--overwrite\",\n presetUrl,\n ],\n absoluteProjectDir,\n );\n } catch {\n logger.warn(\n `Preset application failed. You can retry manually with:\\n ${dlxCmd} ${[...dlxArgs, \"shadcn@latest\", \"add\", presetUrl].join(\" \")}`,\n );\n }\n }\n\n process.removeListener(\"exit\", cleanupOnExit);\n\n logger.break();\n logger.success(\"Project created successfully!\");\n logger.break();\n const runCmd = pm === \"npm\" ? \"npm run\" : pm;\n let devScript = \"dev\";\n let envFile = \".env.local\";\n try {\n const scaffoldedPkg = JSON.parse(\n fs.readFileSync(\n path.join(absoluteProjectDir, \"package.json\"),\n \"utf-8\",\n ),\n );\n devScript = scaffoldedPkg.scripts?.dev\n ? \"dev\"\n : scaffoldedPkg.scripts?.start\n ? \"start\"\n : \"dev\";\n envFile = scaffoldedPkg.dependencies?.next ? \".env.local\" : \".env\";\n } catch {\n // Fall back to defaults if package.json cannot be read\n }\n\n logger.info(\"Next steps:\");\n logger.info(` cd ${resolvedProjectDirectory}`);\n if (opts.skipInstall) {\n logger.info(` ${pm} install`);\n }\n logger.info(` # Set up your environment variables in ${envFile}`);\n logger.info(` ${runCmd} ${devScript}`);\n } catch (error) {\n if (error instanceof SpawnExitError) {\n logger.error(`Project creation failed with code ${error.code}`);\n process.exit(error.code);\n }\n const message = error instanceof Error ? error.message : String(error);\n logger.error(`Failed to create project: ${message}`);\n process.exit(1);\n }\n });\n"],"mappings":";;;;;;;;;;AA+BA,MAAa,mBAAsC;CAEjD;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CAEA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;AACF;AAWA,MAAM,gBAAgB,iBAAiB,QACpC,MAAM,EAAE,aAAa,UACxB,CAAC,CAAC,KAAK,MAAM,EAAE,IAAI;AAEnB,MAAM,eAAe,iBAAiB,QACnC,MAAM,EAAE,aAAa,SACxB,CAAC,CAAC,KAAK,MAAM,EAAE,IAAI;AAEnB,eAAsB,eAA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"}
1
+ {"version":3,"file":"create.js","names":[],"sources":["../../src/commands/create.ts"],"sourcesContent":["import { Command, Option } from \"commander\";\nimport chalk from \"chalk\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport * as p from \"@clack/prompts\";\nimport { logger } from \"../lib/utils/logger\";\nimport {\n dlxCommand,\n downloadProject,\n resolveLatestReleaseRef,\n resolvePackageManager,\n scaffoldProject,\n transformProject,\n type TransformResult,\n} from \"../lib/create-project\";\nimport {\n hasActiveSpawn,\n runSpawn,\n SpawnExitError,\n SpawnSignalError,\n} from \"../lib/run-spawn\";\nimport { resolvePackageManagerForCwd } from \"../lib/utils/package-manager\";\nimport {\n buildSkillsAddCommand,\n resolveSkillsInstall,\n} from \"../lib/agent-skill\";\n\nexport interface ProjectMetadata {\n name: string;\n label: string;\n description?: string;\n category: \"template\" | \"example\";\n path: string;\n hasLocalComponents: boolean;\n}\n\nexport const PROJECT_METADATA: ProjectMetadata[] = [\n // Templates\n {\n name: \"default\",\n label: \"Default\",\n description: \"Default template with Vercel AI SDK\",\n category: \"template\",\n path: \"templates/default\",\n hasLocalComponents: false,\n },\n {\n name: \"minimal\",\n label: \"Minimal\",\n description: \"Bare-bones starting point\",\n category: \"template\",\n path: \"templates/minimal\",\n hasLocalComponents: true,\n },\n {\n name: \"cloud\",\n label: \"Cloud\",\n description: \"Cloud-backed persistence starter\",\n category: \"template\",\n path: \"templates/cloud\",\n hasLocalComponents: false,\n },\n {\n name: \"cloud-clerk\",\n label: \"Cloud + Clerk\",\n description: \"Cloud-backed starter with Clerk auth\",\n category: \"template\",\n path: \"templates/cloud-clerk\",\n hasLocalComponents: false,\n },\n {\n name: \"langchain\",\n label: \"LangChain\",\n description: \"LangGraph starter with the react-langchain adapter\",\n category: \"template\",\n path: \"templates/langchain\",\n hasLocalComponents: false,\n },\n {\n name: \"mcp\",\n label: \"MCP\",\n description: \"MCP tools + MCP Apps renderer starter\",\n category: \"template\",\n path: \"templates/mcp\",\n hasLocalComponents: false,\n },\n {\n name: \"eve\",\n label: \"Eve\",\n description: \"Eve agent + Next.js starter\",\n category: \"template\",\n path: \"templates/eve\",\n hasLocalComponents: false,\n },\n // Examples\n {\n name: \"with-ag-ui\",\n label: \"AG-UI\",\n description: \"AG-UI protocol integration\",\n category: \"example\",\n path: \"examples/with-ag-ui\",\n hasLocalComponents: false,\n },\n {\n name: \"with-google-adk\",\n label: \"Google ADK\",\n description: \"Google ADK agent integration\",\n category: \"example\",\n path: \"examples/with-google-adk\",\n hasLocalComponents: false,\n },\n {\n name: \"with-ai-sdk-v7\",\n label: \"AI SDK v7\",\n description: \"Vercel AI SDK v7\",\n category: \"example\",\n path: \"examples/with-ai-sdk-v7\",\n hasLocalComponents: false,\n },\n {\n name: \"with-eve\",\n label: \"Eve\",\n description: \"Eve agent integration\",\n category: \"example\",\n path: \"examples/with-eve\",\n hasLocalComponents: false,\n },\n {\n name: \"with-artifacts\",\n label: \"Artifacts\",\n description: \"Artifact rendering\",\n category: \"example\",\n path: \"examples/with-artifacts\",\n hasLocalComponents: false,\n },\n {\n name: \"with-assistant-transport\",\n label: \"Assistant Transport\",\n description: \"Assistant transport protocol\",\n category: \"example\",\n path: \"examples/with-assistant-transport\",\n hasLocalComponents: false,\n },\n {\n name: \"with-chain-of-thought\",\n label: \"Chain of Thought\",\n description: \"Chain-of-thought, tool calls, and source citations\",\n category: \"example\",\n path: \"examples/with-chain-of-thought\",\n hasLocalComponents: false,\n },\n {\n name: \"with-cloud\",\n label: \"Cloud Example\",\n description: \"Cloud integration example\",\n category: \"example\",\n path: \"examples/with-cloud\",\n hasLocalComponents: false,\n },\n {\n name: \"with-custom-thread-list\",\n label: \"Custom Thread List\",\n description: \"Custom thread list UI\",\n category: \"example\",\n path: \"examples/with-custom-thread-list\",\n hasLocalComponents: false,\n },\n {\n name: \"with-elevenlabs-conversational\",\n label: \"ElevenLabs Conversational\",\n description: \"Realtime voice with ElevenLabs\",\n category: \"example\",\n path: \"examples/with-elevenlabs-conversational\",\n hasLocalComponents: false,\n },\n {\n name: \"with-elevenlabs-scribe\",\n label: \"ElevenLabs Scribe\",\n description: \"Audio/speech integration\",\n category: \"example\",\n path: \"examples/with-elevenlabs-scribe\",\n hasLocalComponents: false,\n },\n {\n name: \"with-livekit\",\n label: \"LiveKit Voice\",\n description: \"Realtime voice with LiveKit\",\n category: \"example\",\n path: \"examples/with-livekit\",\n hasLocalComponents: false,\n },\n {\n name: \"with-expo\",\n label: \"Expo\",\n description: \"Expo / React Native\",\n category: \"example\",\n path: \"examples/with-expo\",\n hasLocalComponents: true,\n },\n {\n name: \"with-interactables\",\n label: \"Interactables\",\n description: \"AI-driven interactive UI components\",\n category: \"example\",\n path: \"examples/with-interactables\",\n hasLocalComponents: false,\n },\n {\n name: \"with-external-store\",\n label: \"External Store\",\n description: \"Custom message store\",\n category: \"example\",\n path: \"examples/with-external-store\",\n hasLocalComponents: false,\n },\n {\n name: \"with-ffmpeg\",\n label: \"FFmpeg\",\n description: \"File processing\",\n category: \"example\",\n path: \"examples/with-ffmpeg\",\n hasLocalComponents: false,\n },\n {\n name: \"with-langgraph\",\n label: \"LangGraph Example\",\n description: \"LangGraph integration\",\n category: \"example\",\n path: \"examples/with-langgraph\",\n hasLocalComponents: false,\n },\n {\n name: \"with-react-hook-form\",\n label: \"React Hook Form\",\n description: \"Form integration\",\n category: \"example\",\n path: \"examples/with-react-hook-form\",\n hasLocalComponents: false,\n },\n {\n name: \"with-react-ink\",\n label: \"React Ink\",\n description: \"Terminal UI chat\",\n category: \"example\",\n path: \"examples/with-react-ink\",\n hasLocalComponents: true,\n },\n {\n name: \"with-react-router\",\n label: \"React Router\",\n description: \"React Router v7 + Vite\",\n category: \"example\",\n path: \"examples/with-react-router\",\n hasLocalComponents: false,\n },\n {\n name: \"with-tanstack\",\n label: \"TanStack\",\n description: \"TanStack/React Router + Vite\",\n category: \"example\",\n path: \"examples/with-tanstack\",\n hasLocalComponents: false,\n },\n {\n name: \"with-resumable-stream\",\n label: \"Resumable Stream\",\n description: \"Resumable LLM stream that survives reload mid-response\",\n category: \"example\",\n path: \"examples/with-resumable-stream\",\n hasLocalComponents: false,\n },\n {\n name: \"with-openui\",\n label: \"OpenUI\",\n description: \"OpenUI generative UI integration\",\n category: \"example\",\n path: \"examples/with-openui\",\n hasLocalComponents: false,\n },\n];\n\n// Examples that exist in the monorepo but are intentionally excluded from the CLI:\n//\n// - waterfall: Still in development, not ready for production.\n// - with-cloud-standalone: For cloud without assistant-ui — not for the\n// assistant-ui CLI.\n// - with-store: In development, not ready for public use of the tap store.\n// - with-tap-runtime: In development, not ready for public use of the tap\n// store.\n\nconst templateNames = PROJECT_METADATA.filter(\n (m) => m.category === \"template\",\n).map((m) => m.name);\n\nconst exampleNames = PROJECT_METADATA.filter(\n (m) => m.category === \"example\",\n).map((m) => m.name);\n\nexport async function resolveProject(params: {\n template?: string;\n example?: string;\n stdinIsTTY?: boolean;\n select?: typeof p.select;\n isCancel?: typeof p.isCancel;\n}): Promise<ProjectMetadata | null> {\n const {\n template,\n example,\n stdinIsTTY = process.stdin.isTTY,\n select = p.select,\n isCancel = p.isCancel,\n } = params;\n\n if (template !== undefined) {\n const meta = PROJECT_METADATA.find(\n (m) => m.name === template && m.category === \"template\",\n );\n if (!meta) {\n logger.error(`Unknown template: ${template}`);\n logger.info(`Available templates: ${templateNames.join(\", \")}`);\n process.exit(1);\n }\n return meta;\n }\n\n if (example !== undefined) {\n const meta = PROJECT_METADATA.find(\n (m) => m.name === example && m.category === \"example\",\n );\n if (!meta) {\n logger.error(`Unknown example: ${example}`);\n logger.info(`Available examples: ${exampleNames.join(\", \")}`);\n process.exit(1);\n }\n return meta;\n }\n\n if (!stdinIsTTY) {\n return PROJECT_METADATA.find((m) => m.name === \"default\")!;\n }\n\n const selected = await select({\n message: \"Select a project to scaffold:\",\n options: [\n {\n value: \"_separator\",\n label: \"────── Starter Templates ──────\",\n disabled: true,\n },\n ...PROJECT_METADATA.filter((m) => m.category === \"template\").map((m) => ({\n value: m.name,\n label: m.label,\n ...(m.description ? { hint: m.description } : {}),\n })),\n {\n value: \"_separator\",\n label: \"────── Feature Examples ──────\",\n disabled: true,\n },\n ...PROJECT_METADATA.filter((m) => m.category === \"example\").map((m) => ({\n value: m.name,\n label: m.label,\n ...(m.description ? { hint: m.description } : {}),\n })),\n ],\n });\n\n if (isCancel(selected)) {\n return null;\n }\n\n const meta = PROJECT_METADATA.find((m) => m.name === selected);\n if (!meta) {\n logger.error(`Unknown selection: ${String(selected)}`);\n process.exit(1);\n }\n return meta;\n}\n\nexport function resolveCreateProjectDirectory(params: {\n projectDirectory?: string;\n stdinIsTTY?: boolean;\n}): string | undefined {\n const { projectDirectory, stdinIsTTY = process.stdin.isTTY } = params;\n\n if (projectDirectory) return projectDirectory;\n if (!stdinIsTTY) return \"my-aui-app\";\n return undefined;\n}\n\nconst PLAYGROUND_PRESET_BASE_URL =\n \"https://www.assistant-ui.com/playground/init\";\n\nexport function resolvePresetUrl(preset: string): string {\n if (preset.startsWith(\"http://\") || preset.startsWith(\"https://\")) {\n return preset;\n }\n return `${PLAYGROUND_PRESET_BASE_URL}?preset=${encodeURIComponent(preset)}`;\n}\n\nexport interface ScaffoldSelectorOptions {\n template?: string;\n example?: string;\n preset?: string;\n native?: boolean;\n ink?: boolean;\n}\n\nexport interface ResolvedScaffoldSelector {\n template?: string;\n example?: string;\n preset?: string;\n}\n\nconst scaffoldSelectorHelp =\n \"Choose one scaffold selector: --template <name>, --example <name>, --native, or --ink. --preset <name-or-url> can be used with --template or by itself.\";\n\nfunction getPresetConflict(opts: ScaffoldSelectorOptions): string | undefined {\n if (opts.example !== undefined) return \"--example\";\n if (opts.native) return \"--native\";\n if (opts.ink) return \"--ink\";\n return undefined;\n}\n\nexport function resolveScaffoldSelector(\n opts: ScaffoldSelectorOptions,\n): ResolvedScaffoldSelector {\n const hasPreset = opts.preset !== undefined;\n const presetConflict = getPresetConflict(opts);\n const selectors = [\n opts.template !== undefined ? \"--template\" : undefined,\n opts.example !== undefined ? \"--example\" : undefined,\n opts.native ? \"--native\" : undefined,\n opts.ink ? \"--ink\" : undefined,\n ].filter((selector): selector is string => selector !== undefined);\n\n if (selectors.length > 1) {\n throw new Error(\n `Only one scaffold selector can be provided (${selectors.join(\", \")}). ${scaffoldSelectorHelp}`,\n );\n }\n\n if (hasPreset && presetConflict) {\n throw new Error(\n `Cannot use --preset with ${presetConflict}. ${scaffoldSelectorHelp}`,\n );\n }\n\n if (opts.native) return { example: \"with-expo\" };\n if (opts.ink) return { example: \"with-react-ink\" };\n\n if (opts.preset !== undefined && opts.template === undefined) {\n return { template: \"default\", preset: opts.preset };\n }\n\n return {\n ...(opts.template !== undefined && { template: opts.template }),\n ...(opts.example !== undefined && { example: opts.example }),\n ...(hasPreset && { preset: opts.preset }),\n };\n}\n\nexport const create = new Command()\n .name(\"create\")\n .description(\"create a new project\")\n .argument(\"[project-directory]\")\n .usage(`${chalk.green(\"[project-directory]\")} [options]`)\n .option(\n \"-t, --template <template>\",\n `template to use (${templateNames.join(\", \")})`,\n )\n .option(\n \"-e, --example <example>\",\n `create from an example (${exampleNames.join(\", \")})`,\n )\n .option(\n \"-p, --preset <name-or-url>\",\n \"preset name or URL (e.g., chatgpt or https://www.assistant-ui.com/playground/init?preset=chatgpt)\",\n )\n .option(\"--use-npm\", \"explicitly use npm\")\n .option(\"--use-pnpm\", \"explicitly use pnpm\")\n .option(\"--use-yarn\", \"explicitly use yarn\")\n .option(\"--use-bun\", \"explicitly use bun\")\n .option(\"--native\", \"create an Expo / React Native project\")\n .option(\"--ink\", \"create a React Ink terminal project\")\n .option(\"--skip-install\", \"skip installing packages\")\n .option(\"--skills\", \"add assistant-ui agent skills for AI coding assistants\")\n .option(\"--no-skills\", \"skip adding assistant-ui agent skills\")\n .addOption(\n new Option(\n \"--debug-source-root <path>\",\n \"copy templates/examples from a local assistant-ui repo root\",\n ).hideHelp(),\n )\n .action(async (projectDirectory, opts) => {\n let scaffoldSelector: ResolvedScaffoldSelector;\n try {\n scaffoldSelector = resolveScaffoldSelector(opts);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n logger.error(message);\n process.exit(1);\n }\n\n const localSourceRoot = opts.debugSourceRoot\n ? path.resolve(opts.debugSourceRoot)\n : undefined;\n\n // Start release ref resolution early (runs during user prompts)\n const refPromise = localSourceRoot\n ? Promise.resolve(undefined)\n : resolveLatestReleaseRef();\n\n // 1. Resolve project directory\n let resolvedProjectDirectory = resolveCreateProjectDirectory({\n projectDirectory,\n });\n\n if (!resolvedProjectDirectory) {\n const result = await p.text({\n message: \"Project name:\",\n placeholder: \"my-aui-app\",\n defaultValue: \"my-aui-app\",\n validate: (value?: string) => {\n const name = (value ?? \"\").trim();\n if (!name) return \"Project name cannot be empty\";\n if (name === \".\" || name === \"..\")\n return \"Project name cannot be . or ..\";\n if (name.includes(\"/\") || name.includes(\"\\\\\"))\n return \"Project name cannot contain path separators\";\n return undefined;\n },\n });\n\n if (p.isCancel(result)) {\n p.cancel(\"Project creation cancelled.\");\n process.exit(0);\n }\n\n resolvedProjectDirectory = result;\n }\n\n // Check directory\n const absoluteProjectDir = path.resolve(resolvedProjectDirectory);\n try {\n const files = fs.readdirSync(absoluteProjectDir);\n if (files.length > 0) {\n logger.error(\n `Directory ${resolvedProjectDirectory} already exists and is not empty`,\n );\n process.exit(1);\n }\n } catch (err: unknown) {\n const code =\n err instanceof Error ? (err as NodeJS.ErrnoException).code : undefined;\n if (code === \"ENOENT\") {\n // Directory doesn't exist — good, proceed\n } else if (code === \"ENOTDIR\") {\n logger.error(\n `${resolvedProjectDirectory} already exists and is not a directory`,\n );\n process.exit(1);\n } else {\n const message = err instanceof Error ? err.message : String(err);\n logger.error(`Cannot access ${resolvedProjectDirectory}: ${message}`);\n process.exit(1);\n }\n }\n\n // 2. Resolve scaffold target\n const project = await resolveProject(scaffoldSelector);\n if (!project) {\n p.cancel(\"Project creation cancelled.\");\n process.exit(0);\n }\n\n const stdinIsTTY = process.stdin.isTTY;\n let installSkills = resolveSkillsInstall({\n skills: opts.skills,\n stdinIsTTY,\n });\n if (installSkills === undefined) {\n const result = await p.confirm({\n message: \"Add assistant-ui agent skills for AI coding assistants?\",\n initialValue: true,\n });\n\n if (p.isCancel(result)) {\n p.cancel(\"Project creation cancelled.\");\n process.exit(0);\n }\n\n installSkills = result;\n }\n\n logger.info(`Creating project from ${project.category}: ${project.label}`);\n logger.break();\n\n const pm = await resolvePackageManagerForCwd(\n path.dirname(absoluteProjectDir),\n resolvePackageManager(opts),\n );\n\n // Clean up partial project directory on unexpected exit (e.g. Ctrl+C)\n let cleanupArmed = true;\n const cleanupOnExit = () => {\n if (!cleanupArmed) return;\n cleanupArmed = false;\n fs.rmSync(absoluteProjectDir, { recursive: true, force: true });\n };\n const disarmCleanup = () => {\n cleanupArmed = false;\n process.removeListener(\"exit\", cleanupOnExit);\n process.removeListener(\"SIGINT\", cleanupOnSignal);\n process.removeListener(\"SIGTERM\", cleanupOnSignal);\n };\n // Node emits no \"exit\" when a signal kills the process. An in-flight\n // runSpawn forwards the signal itself, so the directory is removed on the\n // error path once the child is reaped rather than while it is still writing.\n const cleanupOnSignal = (signal: NodeJS.Signals) => {\n if (hasActiveSpawn()) return;\n cleanupOnExit();\n disarmCleanup();\n process.kill(process.pid, signal);\n };\n\n process.once(\"exit\", cleanupOnExit);\n process.on(\"SIGINT\", cleanupOnSignal);\n process.on(\"SIGTERM\", cleanupOnSignal);\n\n try {\n // 3. Resolve latest release ref (started before prompts)\n if (!localSourceRoot) {\n logger.step(\"Resolving latest release...\");\n }\n const ref = await refPromise;\n if (!localSourceRoot && !ref) {\n logger.warn(\"Could not resolve latest release, downloading from HEAD\");\n }\n\n // 4. Scaffold project\n logger.step(\n localSourceRoot\n ? `Copying project from local source: ${localSourceRoot}`\n : \"Downloading project...\",\n );\n let transformResult: TransformResult;\n try {\n const source = localSourceRoot\n ? { kind: \"local\" as const, rootDir: localSourceRoot }\n : {\n kind: \"github\" as const,\n ref,\n };\n await scaffoldProject(project.path, absoluteProjectDir, source);\n\n // If the template didn't exist at the release tag, retry from HEAD\n if (\n !localSourceRoot &&\n ref &&\n !fs.existsSync(path.join(absoluteProjectDir, \"package.json\"))\n ) {\n fs.rmSync(absoluteProjectDir, { recursive: true, force: true });\n logger.warn(\n \"Template not found at release tag, downloading from HEAD\",\n );\n await downloadProject(project.path, absoluteProjectDir);\n }\n\n // 5. Run transform pipeline\n transformResult = await transformProject(absoluteProjectDir, {\n hasLocalComponents: project.hasLocalComponents,\n skipInstall: opts.skipInstall,\n packageManager: pm,\n });\n\n if (installSkills) {\n logger.step(\"Adding assistant-ui agent skills...\");\n const [skillsCmd, skillsArgs] = buildSkillsAddCommand(pm, {\n stdinIsTTY,\n });\n try {\n await runSpawn(skillsCmd, skillsArgs, absoluteProjectDir);\n } catch (error) {\n if (error instanceof SpawnSignalError) throw error;\n logger.warn(\n `Could not add assistant-ui agent skills. You can add them later with:\\n ${skillsCmd} ${skillsArgs.join(\" \")}`,\n );\n }\n }\n } catch (err) {\n // Clean up partially created project directory\n cleanupOnExit();\n disarmCleanup();\n throw err;\n }\n\n if (transformResult.registryInstallFailure) {\n disarmCleanup();\n logger.break();\n logger.error(\"Project created with missing components.\");\n logger.info(\"Retry the component install with:\");\n logger.info(` cd ${resolvedProjectDirectory}`);\n logger.info(` ${transformResult.registryInstallFailure.retryCommand}`);\n process.exit(1);\n }\n\n // 6. Apply preset if provided\n if (scaffoldSelector.preset) {\n const presetUrl = resolvePresetUrl(scaffoldSelector.preset);\n logger.info(\"Applying preset configuration...\");\n logger.break();\n const [dlxCmd, dlxArgs] = dlxCommand(pm);\n try {\n await runSpawn(\n dlxCmd,\n [\n ...dlxArgs,\n \"shadcn@latest\",\n \"add\",\n \"--yes\",\n \"--overwrite\",\n presetUrl,\n ],\n absoluteProjectDir,\n );\n } catch (error) {\n if (error instanceof SpawnSignalError) throw error;\n logger.warn(\n `Preset application failed. You can retry manually with:\\n ${dlxCmd} ${[...dlxArgs, \"shadcn@latest\", \"add\", presetUrl].join(\" \")}`,\n );\n }\n }\n\n disarmCleanup();\n\n logger.break();\n logger.success(\"Project created successfully!\");\n logger.break();\n const runCmd = pm === \"npm\" ? \"npm run\" : pm;\n let devScript = \"dev\";\n let envFile = \".env.local\";\n try {\n const scaffoldedPkg = JSON.parse(\n fs.readFileSync(\n path.join(absoluteProjectDir, \"package.json\"),\n \"utf-8\",\n ),\n );\n devScript = scaffoldedPkg.scripts?.dev\n ? \"dev\"\n : scaffoldedPkg.scripts?.start\n ? \"start\"\n : \"dev\";\n envFile = scaffoldedPkg.dependencies?.next ? \".env.local\" : \".env\";\n } catch {\n // Fall back to defaults if package.json cannot be read\n }\n\n logger.info(\"Next steps:\");\n logger.info(` cd ${resolvedProjectDirectory}`);\n if (opts.skipInstall) {\n logger.info(` ${pm} install`);\n }\n logger.info(` # Set up your environment variables in ${envFile}`);\n logger.info(` ${runCmd} ${devScript}`);\n } catch (error) {\n if (error instanceof SpawnSignalError) {\n cleanupOnExit();\n disarmCleanup();\n throw error;\n }\n if (error instanceof SpawnExitError) {\n logger.error(`Project creation failed with code ${error.code}`);\n process.exit(error.code);\n }\n const message = error instanceof Error ? error.message : String(error);\n logger.error(`Failed to create project: ${message}`);\n process.exit(1);\n }\n });\n"],"mappings":";;;;;;;;;;;AAoCA,MAAa,mBAAsC;CAEjD;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CAEA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;AACF;AAWA,MAAM,gBAAgB,iBAAiB,QACpC,MAAM,EAAE,aAAa,UACxB,CAAC,CAAC,KAAK,MAAM,EAAE,IAAI;AAEnB,MAAM,eAAe,iBAAiB,QACnC,MAAM,EAAE,aAAa,SACxB,CAAC,CAAC,KAAK,MAAM,EAAE,IAAI;AAEnB,eAAsB,eA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"}
@@ -1 +1 @@
1
- {"version":3,"file":"info.d.ts","names":[],"sources":["../../src/commands/info.ts"],"mappings":";;;iBAiNgB,eAAe,iBAAiB;cAyMnC,MAAI"}
1
+ {"version":3,"file":"info.d.ts","names":[],"sources":["../../src/commands/info.ts"],"mappings":";;;iBAkNgB,eAAe,iBAAiB;cAyMnC,MAAI"}
@@ -1,12 +1,12 @@
1
1
  import { logPackageJsonParseError } from "../lib/utils/package-json.js";
2
2
  import { findWorkspaceRoot, resolveRealPath } from "../lib/utils/workspace.js";
3
+ import * as os$1 from "node:os";
3
4
  import { Command } from "commander";
4
5
  import chalk from "chalk";
5
6
  import * as fs$1 from "node:fs";
6
7
  import * as path$1 from "node:path";
7
8
  import { detect } from "detect-package-manager";
8
9
  import { spawnSync } from "node:child_process";
9
- import * as os$1 from "node:os";
10
10
  import { satisfies } from "semver";
11
11
  //#region src/commands/info.ts
12
12
  const ASSISTANT_UI_PACKAGES = [
@@ -20,6 +20,7 @@ const ASSISTANT_UI_PACKAGES = [
20
20
  "assistant-cloud",
21
21
  "@assistant-ui/cloud-ai-sdk",
22
22
  "@assistant-ui/eve",
23
+ "@assistant-ui/ai-sdk",
23
24
  "@assistant-ui/react-ai-sdk",
24
25
  "@assistant-ui/react-langgraph",
25
26
  "@assistant-ui/react-ag-ui",
@@ -1 +1 @@
1
- {"version":3,"file":"info.js","names":["path","fs","os"],"sources":["../../src/commands/info.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport * as fs from \"node:fs\";\nimport * as os from \"node:os\";\nimport * as path from \"node:path\";\nimport { spawnSync } from \"node:child_process\";\nimport chalk from \"chalk\";\nimport { detect } from \"detect-package-manager\";\nimport { satisfies } from \"semver\";\nimport { logPackageJsonParseError } from \"../lib/utils/package-json\";\nimport { findWorkspaceRoot, resolveRealPath } from \"../lib/utils/workspace\";\n\nexport { findWorkspaceRoot };\n\nconst ASSISTANT_UI_PACKAGES = [\n // Distribution\n \"@assistant-ui/react\",\n \"@assistant-ui/react-native\",\n \"@assistant-ui/react-ink\",\n // Core (should not be installed directly)\n \"@assistant-ui/core\",\n \"@assistant-ui/store\",\n \"@assistant-ui/tap\",\n // Streaming & Cloud\n \"assistant-stream\",\n \"assistant-cloud\",\n \"@assistant-ui/cloud-ai-sdk\",\n // Adapters\n \"@assistant-ui/eve\",\n \"@assistant-ui/react-ai-sdk\",\n \"@assistant-ui/react-langgraph\",\n \"@assistant-ui/react-ag-ui\",\n \"@assistant-ui/react-a2a\",\n \"@assistant-ui/react-data-stream\",\n \"@assistant-ui/react-google-adk\",\n // UI / Rendering\n \"@assistant-ui/react-markdown\",\n \"@assistant-ui/react-streamdown\",\n \"@assistant-ui/react-lexical\",\n \"@assistant-ui/react-syntax-highlighter\",\n \"@assistant-ui/react-hook-form\",\n // Observability & DevTools\n \"@assistant-ui/react-o11y\",\n \"@assistant-ui/react-devtools\",\n];\n\nconst ECOSYSTEM_PACKAGES = [\n \"react\",\n \"react-dom\",\n \"react-native\",\n \"next\",\n \"vite\",\n \"expo\",\n \"ai\",\n \"zod\",\n \"zustand\",\n \"typescript\",\n];\n\n// Packages that users should NOT install directly — they are internal\n// dependencies pulled in automatically by distribution packages.\nconst SHOULD_NOT_DIRECT_INSTALL = new Set([\n \"@assistant-ui/core\",\n \"@assistant-ui/store\",\n \"@assistant-ui/tap\",\n]);\n\nfunction resolvePackageJson(pkg: string, cwd: string): string | null {\n let dir = cwd;\n const root = path.parse(dir).root;\n while (dir !== root) {\n const candidate = path.join(\n dir,\n \"node_modules\",\n ...pkg.split(\"/\"),\n \"package.json\",\n );\n if (fs.existsSync(candidate)) return candidate;\n dir = path.dirname(dir);\n }\n return null;\n}\n\nfunction getInstalledVersion(pkg: string, cwd: string): string | null {\n try {\n const pkgJsonPath = resolvePackageJson(pkg, cwd);\n if (pkgJsonPath) {\n const pkgJson = JSON.parse(fs.readFileSync(pkgJsonPath, \"utf8\"));\n return pkgJson.version ?? null;\n }\n } catch {\n // ignore\n }\n return null;\n}\n\nfunction readProjectDeps(\n projectPkg: Record<string, unknown>,\n): Record<string, string> {\n return {\n ...((projectPkg.dependencies ?? {}) as Record<string, string>),\n ...((projectPkg.devDependencies ?? {}) as Record<string, string>),\n };\n}\n\nfunction getAssistantUiPackageNames(\n projectPkg: Record<string, unknown>,\n): string[] {\n const declaredPackages = Object.keys(readProjectDeps(projectPkg))\n .filter((name) => name.startsWith(\"@assistant-ui/\"))\n .sort();\n\n return [...new Set([...ASSISTANT_UI_PACKAGES, ...declaredPackages])];\n}\n\nfunction getSpecifiedRange(\n pkg: string,\n projectPkg: Record<string, unknown>,\n): string | null {\n const deps = (projectPkg.dependencies ?? {}) as Record<string, string>;\n const devDeps = (projectPkg.devDependencies ?? {}) as Record<string, string>;\n return deps[pkg] ?? devDeps[pkg] ?? null;\n}\n\nfunction getPeerDeps(pkg: string, cwd: string): Record<string, string> | null {\n try {\n const pkgJsonPath = resolvePackageJson(pkg, cwd);\n if (pkgJsonPath) {\n const pkgJson = JSON.parse(fs.readFileSync(pkgJsonPath, \"utf8\"));\n return (pkgJson.peerDependencies as Record<string, string>) ?? null;\n }\n } catch {\n // ignore\n }\n return null;\n}\n\nfunction detectFramework(\n projectPkg: Record<string, unknown>,\n cwd: string,\n): string {\n const deps = readProjectDeps(projectPkg);\n\n if (deps.next) {\n const v = getInstalledVersion(\"next\", cwd);\n return `Next.js ${v ?? deps.next}`;\n }\n if (deps.expo) {\n const v = getInstalledVersion(\"expo\", cwd);\n return `Expo ${v ?? deps.expo}`;\n }\n if (deps.vite) {\n const v = getInstalledVersion(\"vite\", cwd);\n return `Vite ${v ?? deps.vite}`;\n }\n if (deps[\"@remix-run/react\"] || deps.remix) return \"Remix\";\n if (deps.gatsby) return \"Gatsby\";\n if (deps.astro) return \"Astro\";\n return \"Unknown\";\n}\n\nfunction getOsInfo(): string {\n const platform = os.platform();\n const arch = os.arch();\n const release = os.release();\n\n switch (platform) {\n case \"darwin\": {\n const result = spawnSync(\"sw_vers\", [\"-productVersion\"], {\n encoding: \"utf8\",\n });\n const macVer = result.stdout?.trim();\n return macVer\n ? `macOS ${macVer} (${arch})`\n : `macOS ${release} (${arch})`;\n }\n case \"win32\":\n return `Windows ${release} (${arch})`;\n case \"linux\":\n return `Linux ${release} (${arch})`;\n default:\n return `${platform} ${release} (${arch})`;\n }\n}\n\nfunction getCliVersion(): string {\n try {\n const packageJson = JSON.parse(\n fs.readFileSync(new URL(\"../../package.json\", import.meta.url), \"utf8\"),\n ) as { version?: unknown };\n return typeof packageJson.version === \"string\"\n ? packageJson.version\n : \"unknown\";\n } catch {\n return \"unknown\";\n }\n}\n\nasync function getPackageManagerInfo(\n cwd: string,\n): Promise<{ name: string; version: string }> {\n const pm = await detect({ cwd });\n const result = spawnSync(pm, [\"--version\"], {\n encoding: \"utf8\",\n cwd,\n });\n const version = result.stdout?.trim() ?? \"unknown\";\n return { name: pm, version };\n}\n\nexport function satisfiesRange(version: string, range: string): boolean {\n const normalizedRange = range.startsWith(\"workspace:\")\n ? range.slice(\"workspace:\".length)\n : range;\n\n return (\n normalizedRange === \"\" ||\n normalizedRange === \"^\" ||\n normalizedRange === \"~\" ||\n normalizedRange === \"any\" ||\n satisfies(version, normalizedRange, { includePrerelease: true })\n );\n}\n\ninterface PackageInfo {\n name: string;\n version: string;\n range: string | null;\n}\n\ninterface InfoData {\n cliVersion: string;\n os: string;\n node: string;\n pm: { name: string; version: string };\n framework: string;\n isMonorepo: boolean;\n packages: PackageInfo[];\n ecosystem: PackageInfo[];\n warnings: string[];\n}\n\nfunction collectPackages(\n names: string[],\n cwd: string,\n projectPkg: Record<string, unknown>,\n): PackageInfo[] {\n const result: PackageInfo[] = [];\n const deps = readProjectDeps(projectPkg);\n\n for (const name of names) {\n const version = getInstalledVersion(name, cwd);\n if (version) {\n result.push({\n name,\n version,\n range: getSpecifiedRange(name, projectPkg),\n });\n } else {\n // Fallback: no node_modules, show range from package.json\n const range = deps[name];\n if (range && !range.startsWith(\"workspace:\")) {\n result.push({ name, version: `${range} (not installed)`, range });\n }\n }\n }\n return result;\n}\n\nfunction collectWarnings(\n packages: PackageInfo[],\n cwd: string,\n projectPkg: Record<string, unknown>,\n): string[] {\n const warnings: string[] = [];\n const deps = readProjectDeps(projectPkg);\n\n // Check peer dependency mismatches\n for (const pkg of packages) {\n const peerDeps = getPeerDeps(pkg.name, cwd);\n if (!peerDeps) continue;\n\n for (const [peerName, peerRange] of Object.entries(peerDeps)) {\n const peerVersion = getInstalledVersion(peerName, cwd);\n if (!peerVersion) continue;\n if (!satisfiesRange(peerVersion, peerRange)) {\n warnings.push(\n `${pkg.name} requires ${peerName} ${peerRange}, found ${peerVersion}`,\n );\n }\n }\n }\n\n // Check for direct install of internal packages\n for (const name of SHOULD_NOT_DIRECT_INSTALL) {\n if (deps[name]) {\n warnings.push(\n `${name} should not be installed directly — it is an internal dependency`,\n );\n }\n }\n\n return warnings;\n}\n\nasync function collectInfo(\n cwd: string,\n projectPkg: Record<string, unknown>,\n): Promise<InfoData> {\n const pm = await getPackageManagerInfo(cwd);\n const packages = collectPackages(\n getAssistantUiPackageNames(projectPkg),\n cwd,\n projectPkg,\n );\n const ecosystem = collectPackages(ECOSYSTEM_PACKAGES, cwd, projectPkg);\n const warnings = collectWarnings(packages, cwd, projectPkg);\n\n return {\n cliVersion: getCliVersion(),\n os: getOsInfo(),\n node: process.version,\n pm,\n framework: detectFramework(projectPkg, cwd),\n isMonorepo: findWorkspaceRoot(cwd) !== null,\n packages,\n ecosystem,\n warnings,\n };\n}\n\nfunction formatSection(label: string, items: PackageInfo[]): string[] {\n if (items.length === 0) return [];\n const lines: string[] = [];\n lines.push(\"\");\n lines.push(`${label}:`);\n const maxLen = Math.max(...items.map((p) => p.name.length));\n for (const pkg of items) {\n lines.push(` ${pkg.name.padEnd(maxLen)} ${pkg.version}`);\n }\n return lines;\n}\n\nfunction renderPlain(data: InfoData): string[] {\n const lines: string[] = [];\n\n lines.push(\"Environment:\");\n lines.push(` assistant-ui CLI: ${data.cliVersion}`);\n lines.push(` OS: ${data.os}`);\n lines.push(` Node.js: ${data.node}`);\n lines.push(` Package Manager: ${data.pm.name} ${data.pm.version}`);\n lines.push(` Framework: ${data.framework}`);\n if (data.isMonorepo) {\n lines.push(` Monorepo: yes`);\n }\n\n lines.push(...formatSection(\"Packages\", data.packages));\n lines.push(...formatSection(\"Ecosystem\", data.ecosystem));\n\n if (data.warnings.length > 0) {\n lines.push(\"\");\n lines.push(\"Warnings:\");\n for (const w of data.warnings) {\n lines.push(` ! ${w}`);\n }\n }\n\n return lines;\n}\n\nfunction renderColored(data: InfoData): string[] {\n const lines: string[] = [];\n\n lines.push(chalk.bold(\"Environment:\"));\n lines.push(` assistant-ui CLI: ${data.cliVersion}`);\n lines.push(` OS: ${data.os}`);\n lines.push(` Node.js: ${data.node}`);\n lines.push(` Package Manager: ${data.pm.name} ${data.pm.version}`);\n lines.push(` Framework: ${data.framework}`);\n if (data.isMonorepo) {\n lines.push(` Monorepo: yes`);\n }\n\n if (data.packages.length > 0) {\n const section = formatSection(\"Packages\", data.packages);\n section[0] = \"\";\n section[1] = chalk.bold(\"Packages:\");\n lines.push(...section);\n } else {\n lines.push(\"\");\n lines.push(chalk.yellow(\" No assistant-ui packages found.\"));\n }\n\n if (data.ecosystem.length > 0) {\n const section = formatSection(\"Ecosystem\", data.ecosystem);\n section[0] = \"\";\n section[1] = chalk.bold(\"Ecosystem:\");\n lines.push(...section);\n }\n\n if (data.warnings.length > 0) {\n lines.push(\"\");\n lines.push(chalk.yellow.bold(\"Warnings:\"));\n for (const w of data.warnings) {\n lines.push(chalk.yellow(` ! ${w}`));\n }\n }\n\n return lines;\n}\n\nexport const info = new Command()\n .name(\"info\")\n .description(\"Print environment and package information for bug reports.\")\n .option(\n \"-c, --cwd <cwd>\",\n \"the working directory. defaults to the current directory.\",\n process.cwd(),\n )\n .action(async (opts) => {\n const cwd = resolveRealPath(opts.cwd);\n const packageJsonPath = path.join(cwd, \"package.json\");\n\n if (!fs.existsSync(packageJsonPath)) {\n console.error(\n chalk.red(\"No package.json found in the current directory.\"),\n );\n process.exit(1);\n }\n\n const packageJsonContent = fs.readFileSync(packageJsonPath, \"utf8\");\n let projectPkg: Record<string, unknown>;\n try {\n projectPkg = JSON.parse(packageJsonContent);\n } catch {\n logPackageJsonParseError(packageJsonPath, \"info\");\n process.exit(1);\n }\n\n const data = await collectInfo(cwd, projectPkg);\n\n // Colored output for terminal\n console.log(\"\");\n for (const line of renderColored(data)) {\n console.log(line);\n }\n console.log(\"\");\n\n // Copyable plain text\n const plain = renderPlain(data);\n const block = [\"```\", ...plain, \"```\"].join(\"\\n\");\n\n console.log(chalk.dim(\"— Copy the text below into your bug report —\"));\n console.log(\"\");\n console.log(block);\n console.log(\"\");\n });\n"],"mappings":"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"}
1
+ {"version":3,"file":"info.js","names":["path","fs","os"],"sources":["../../src/commands/info.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport * as fs from \"node:fs\";\nimport * as os from \"node:os\";\nimport * as path from \"node:path\";\nimport { spawnSync } from \"node:child_process\";\nimport chalk from \"chalk\";\nimport { detect } from \"detect-package-manager\";\nimport { satisfies } from \"semver\";\nimport { logPackageJsonParseError } from \"../lib/utils/package-json\";\nimport { findWorkspaceRoot, resolveRealPath } from \"../lib/utils/workspace\";\n\nexport { findWorkspaceRoot };\n\nconst ASSISTANT_UI_PACKAGES = [\n // Distribution\n \"@assistant-ui/react\",\n \"@assistant-ui/react-native\",\n \"@assistant-ui/react-ink\",\n // Core (should not be installed directly)\n \"@assistant-ui/core\",\n \"@assistant-ui/store\",\n \"@assistant-ui/tap\",\n // Streaming & Cloud\n \"assistant-stream\",\n \"assistant-cloud\",\n \"@assistant-ui/cloud-ai-sdk\",\n // Adapters\n \"@assistant-ui/eve\",\n \"@assistant-ui/ai-sdk\",\n \"@assistant-ui/react-ai-sdk\",\n \"@assistant-ui/react-langgraph\",\n \"@assistant-ui/react-ag-ui\",\n \"@assistant-ui/react-a2a\",\n \"@assistant-ui/react-data-stream\",\n \"@assistant-ui/react-google-adk\",\n // UI / Rendering\n \"@assistant-ui/react-markdown\",\n \"@assistant-ui/react-streamdown\",\n \"@assistant-ui/react-lexical\",\n \"@assistant-ui/react-syntax-highlighter\",\n \"@assistant-ui/react-hook-form\",\n // Observability & DevTools\n \"@assistant-ui/react-o11y\",\n \"@assistant-ui/react-devtools\",\n];\n\nconst ECOSYSTEM_PACKAGES = [\n \"react\",\n \"react-dom\",\n \"react-native\",\n \"next\",\n \"vite\",\n \"expo\",\n \"ai\",\n \"zod\",\n \"zustand\",\n \"typescript\",\n];\n\n// Packages that users should NOT install directly — they are internal\n// dependencies pulled in automatically by distribution packages.\nconst SHOULD_NOT_DIRECT_INSTALL = new Set([\n \"@assistant-ui/core\",\n \"@assistant-ui/store\",\n \"@assistant-ui/tap\",\n]);\n\nfunction resolvePackageJson(pkg: string, cwd: string): string | null {\n let dir = cwd;\n const root = path.parse(dir).root;\n while (dir !== root) {\n const candidate = path.join(\n dir,\n \"node_modules\",\n ...pkg.split(\"/\"),\n \"package.json\",\n );\n if (fs.existsSync(candidate)) return candidate;\n dir = path.dirname(dir);\n }\n return null;\n}\n\nfunction getInstalledVersion(pkg: string, cwd: string): string | null {\n try {\n const pkgJsonPath = resolvePackageJson(pkg, cwd);\n if (pkgJsonPath) {\n const pkgJson = JSON.parse(fs.readFileSync(pkgJsonPath, \"utf8\"));\n return pkgJson.version ?? null;\n }\n } catch {\n // ignore\n }\n return null;\n}\n\nfunction readProjectDeps(\n projectPkg: Record<string, unknown>,\n): Record<string, string> {\n return {\n ...((projectPkg.dependencies ?? {}) as Record<string, string>),\n ...((projectPkg.devDependencies ?? {}) as Record<string, string>),\n };\n}\n\nfunction getAssistantUiPackageNames(\n projectPkg: Record<string, unknown>,\n): string[] {\n const declaredPackages = Object.keys(readProjectDeps(projectPkg))\n .filter((name) => name.startsWith(\"@assistant-ui/\"))\n .sort();\n\n return [...new Set([...ASSISTANT_UI_PACKAGES, ...declaredPackages])];\n}\n\nfunction getSpecifiedRange(\n pkg: string,\n projectPkg: Record<string, unknown>,\n): string | null {\n const deps = (projectPkg.dependencies ?? {}) as Record<string, string>;\n const devDeps = (projectPkg.devDependencies ?? {}) as Record<string, string>;\n return deps[pkg] ?? devDeps[pkg] ?? null;\n}\n\nfunction getPeerDeps(pkg: string, cwd: string): Record<string, string> | null {\n try {\n const pkgJsonPath = resolvePackageJson(pkg, cwd);\n if (pkgJsonPath) {\n const pkgJson = JSON.parse(fs.readFileSync(pkgJsonPath, \"utf8\"));\n return (pkgJson.peerDependencies as Record<string, string>) ?? null;\n }\n } catch {\n // ignore\n }\n return null;\n}\n\nfunction detectFramework(\n projectPkg: Record<string, unknown>,\n cwd: string,\n): string {\n const deps = readProjectDeps(projectPkg);\n\n if (deps.next) {\n const v = getInstalledVersion(\"next\", cwd);\n return `Next.js ${v ?? deps.next}`;\n }\n if (deps.expo) {\n const v = getInstalledVersion(\"expo\", cwd);\n return `Expo ${v ?? deps.expo}`;\n }\n if (deps.vite) {\n const v = getInstalledVersion(\"vite\", cwd);\n return `Vite ${v ?? deps.vite}`;\n }\n if (deps[\"@remix-run/react\"] || deps.remix) return \"Remix\";\n if (deps.gatsby) return \"Gatsby\";\n if (deps.astro) return \"Astro\";\n return \"Unknown\";\n}\n\nfunction getOsInfo(): string {\n const platform = os.platform();\n const arch = os.arch();\n const release = os.release();\n\n switch (platform) {\n case \"darwin\": {\n const result = spawnSync(\"sw_vers\", [\"-productVersion\"], {\n encoding: \"utf8\",\n });\n const macVer = result.stdout?.trim();\n return macVer\n ? `macOS ${macVer} (${arch})`\n : `macOS ${release} (${arch})`;\n }\n case \"win32\":\n return `Windows ${release} (${arch})`;\n case \"linux\":\n return `Linux ${release} (${arch})`;\n default:\n return `${platform} ${release} (${arch})`;\n }\n}\n\nfunction getCliVersion(): string {\n try {\n const packageJson = JSON.parse(\n fs.readFileSync(new URL(\"../../package.json\", import.meta.url), \"utf8\"),\n ) as { version?: unknown };\n return typeof packageJson.version === \"string\"\n ? packageJson.version\n : \"unknown\";\n } catch {\n return \"unknown\";\n }\n}\n\nasync function getPackageManagerInfo(\n cwd: string,\n): Promise<{ name: string; version: string }> {\n const pm = await detect({ cwd });\n const result = spawnSync(pm, [\"--version\"], {\n encoding: \"utf8\",\n cwd,\n });\n const version = result.stdout?.trim() ?? \"unknown\";\n return { name: pm, version };\n}\n\nexport function satisfiesRange(version: string, range: string): boolean {\n const normalizedRange = range.startsWith(\"workspace:\")\n ? range.slice(\"workspace:\".length)\n : range;\n\n return (\n normalizedRange === \"\" ||\n normalizedRange === \"^\" ||\n normalizedRange === \"~\" ||\n normalizedRange === \"any\" ||\n satisfies(version, normalizedRange, { includePrerelease: true })\n );\n}\n\ninterface PackageInfo {\n name: string;\n version: string;\n range: string | null;\n}\n\ninterface InfoData {\n cliVersion: string;\n os: string;\n node: string;\n pm: { name: string; version: string };\n framework: string;\n isMonorepo: boolean;\n packages: PackageInfo[];\n ecosystem: PackageInfo[];\n warnings: string[];\n}\n\nfunction collectPackages(\n names: string[],\n cwd: string,\n projectPkg: Record<string, unknown>,\n): PackageInfo[] {\n const result: PackageInfo[] = [];\n const deps = readProjectDeps(projectPkg);\n\n for (const name of names) {\n const version = getInstalledVersion(name, cwd);\n if (version) {\n result.push({\n name,\n version,\n range: getSpecifiedRange(name, projectPkg),\n });\n } else {\n // Fallback: no node_modules, show range from package.json\n const range = deps[name];\n if (range && !range.startsWith(\"workspace:\")) {\n result.push({ name, version: `${range} (not installed)`, range });\n }\n }\n }\n return result;\n}\n\nfunction collectWarnings(\n packages: PackageInfo[],\n cwd: string,\n projectPkg: Record<string, unknown>,\n): string[] {\n const warnings: string[] = [];\n const deps = readProjectDeps(projectPkg);\n\n // Check peer dependency mismatches\n for (const pkg of packages) {\n const peerDeps = getPeerDeps(pkg.name, cwd);\n if (!peerDeps) continue;\n\n for (const [peerName, peerRange] of Object.entries(peerDeps)) {\n const peerVersion = getInstalledVersion(peerName, cwd);\n if (!peerVersion) continue;\n if (!satisfiesRange(peerVersion, peerRange)) {\n warnings.push(\n `${pkg.name} requires ${peerName} ${peerRange}, found ${peerVersion}`,\n );\n }\n }\n }\n\n // Check for direct install of internal packages\n for (const name of SHOULD_NOT_DIRECT_INSTALL) {\n if (deps[name]) {\n warnings.push(\n `${name} should not be installed directly — it is an internal dependency`,\n );\n }\n }\n\n return warnings;\n}\n\nasync function collectInfo(\n cwd: string,\n projectPkg: Record<string, unknown>,\n): Promise<InfoData> {\n const pm = await getPackageManagerInfo(cwd);\n const packages = collectPackages(\n getAssistantUiPackageNames(projectPkg),\n cwd,\n projectPkg,\n );\n const ecosystem = collectPackages(ECOSYSTEM_PACKAGES, cwd, projectPkg);\n const warnings = collectWarnings(packages, cwd, projectPkg);\n\n return {\n cliVersion: getCliVersion(),\n os: getOsInfo(),\n node: process.version,\n pm,\n framework: detectFramework(projectPkg, cwd),\n isMonorepo: findWorkspaceRoot(cwd) !== null,\n packages,\n ecosystem,\n warnings,\n };\n}\n\nfunction formatSection(label: string, items: PackageInfo[]): string[] {\n if (items.length === 0) return [];\n const lines: string[] = [];\n lines.push(\"\");\n lines.push(`${label}:`);\n const maxLen = Math.max(...items.map((p) => p.name.length));\n for (const pkg of items) {\n lines.push(` ${pkg.name.padEnd(maxLen)} ${pkg.version}`);\n }\n return lines;\n}\n\nfunction renderPlain(data: InfoData): string[] {\n const lines: string[] = [];\n\n lines.push(\"Environment:\");\n lines.push(` assistant-ui CLI: ${data.cliVersion}`);\n lines.push(` OS: ${data.os}`);\n lines.push(` Node.js: ${data.node}`);\n lines.push(` Package Manager: ${data.pm.name} ${data.pm.version}`);\n lines.push(` Framework: ${data.framework}`);\n if (data.isMonorepo) {\n lines.push(` Monorepo: yes`);\n }\n\n lines.push(...formatSection(\"Packages\", data.packages));\n lines.push(...formatSection(\"Ecosystem\", data.ecosystem));\n\n if (data.warnings.length > 0) {\n lines.push(\"\");\n lines.push(\"Warnings:\");\n for (const w of data.warnings) {\n lines.push(` ! ${w}`);\n }\n }\n\n return lines;\n}\n\nfunction renderColored(data: InfoData): string[] {\n const lines: string[] = [];\n\n lines.push(chalk.bold(\"Environment:\"));\n lines.push(` assistant-ui CLI: ${data.cliVersion}`);\n lines.push(` OS: ${data.os}`);\n lines.push(` Node.js: ${data.node}`);\n lines.push(` Package Manager: ${data.pm.name} ${data.pm.version}`);\n lines.push(` Framework: ${data.framework}`);\n if (data.isMonorepo) {\n lines.push(` Monorepo: yes`);\n }\n\n if (data.packages.length > 0) {\n const section = formatSection(\"Packages\", data.packages);\n section[0] = \"\";\n section[1] = chalk.bold(\"Packages:\");\n lines.push(...section);\n } else {\n lines.push(\"\");\n lines.push(chalk.yellow(\" No assistant-ui packages found.\"));\n }\n\n if (data.ecosystem.length > 0) {\n const section = formatSection(\"Ecosystem\", data.ecosystem);\n section[0] = \"\";\n section[1] = chalk.bold(\"Ecosystem:\");\n lines.push(...section);\n }\n\n if (data.warnings.length > 0) {\n lines.push(\"\");\n lines.push(chalk.yellow.bold(\"Warnings:\"));\n for (const w of data.warnings) {\n lines.push(chalk.yellow(` ! ${w}`));\n }\n }\n\n return lines;\n}\n\nexport const info = new Command()\n .name(\"info\")\n .description(\"Print environment and package information for bug reports.\")\n .option(\n \"-c, --cwd <cwd>\",\n \"the working directory. defaults to the current directory.\",\n process.cwd(),\n )\n .action(async (opts) => {\n const cwd = resolveRealPath(opts.cwd);\n const packageJsonPath = path.join(cwd, \"package.json\");\n\n if (!fs.existsSync(packageJsonPath)) {\n console.error(\n chalk.red(\"No package.json found in the current directory.\"),\n );\n process.exit(1);\n }\n\n const packageJsonContent = fs.readFileSync(packageJsonPath, \"utf8\");\n let projectPkg: Record<string, unknown>;\n try {\n projectPkg = JSON.parse(packageJsonContent);\n } catch {\n logPackageJsonParseError(packageJsonPath, \"info\");\n process.exit(1);\n }\n\n const data = await collectInfo(cwd, projectPkg);\n\n // Colored output for terminal\n console.log(\"\");\n for (const line of renderColored(data)) {\n console.log(line);\n }\n console.log(\"\");\n\n // Copyable plain text\n const plain = renderPlain(data);\n const block = [\"```\", ...plain, \"```\"].join(\"\\n\");\n\n console.log(chalk.dim(\"— Copy the text below into your bug report —\"));\n console.log(\"\");\n console.log(block);\n console.log(\"\");\n });\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"init.d.ts","names":[],"sources":["../../src/commands/init.ts"],"mappings":";;UAgBU;EACR;EACA;;iBAGc,8BAA8B;EAC5C;EACA;IACE;iBAYY,sBACd;cAKW,MAAI"}
1
+ {"version":3,"file":"init.d.ts","names":[],"sources":["../../src/commands/init.ts"],"mappings":";;UAaU;EACR;EACA;;iBAGc,8BAA8B;EAC5C;EACA;IACE;iBAYY,sBACd;cAKW,MAAI"}
@@ -1,6 +1,7 @@
1
+ import { SpawnExitError, SpawnSignalError, runSpawn } from "../lib/run-spawn.js";
1
2
  import { logger } from "../lib/utils/logger.js";
2
- import { SpawnExitError, runSpawn } from "../lib/run-spawn.js";
3
- import { dlxCommand, resolvePackageManager, resolvePackageManagerForCwd } from "../lib/create-project.js";
3
+ import { resolvePackageManagerForCwd } from "../lib/utils/package-manager.js";
4
+ import { dlxCommand, resolvePackageManager } from "../lib/create-project.js";
4
5
  import { create } from "./create.js";
5
6
  import { getComponentsJsonStyle, resolveQuickStartRegistryUrl } from "../lib/utils/registry.js";
6
7
  import { Command, Option } from "commander";
@@ -82,6 +83,7 @@ const init = new Command().name("init").description("initialize assistant-ui in
82
83
  logger.success("Project initialized successfully!");
83
84
  logger.info("You can now add more components with 'assistant-ui add'");
84
85
  } catch (error) {
86
+ if (error instanceof SpawnSignalError) throw error;
85
87
  if (error instanceof SpawnExitError) {
86
88
  logger.error(`Initialization failed with code ${error.code}`);
87
89
  process.exit(error.code);
@@ -1 +1 @@
1
- {"version":3,"file":"init.js","names":[],"sources":["../../src/commands/init.ts"],"sourcesContent":["import { Command, Option } from \"commander\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport {\n dlxCommand,\n resolvePackageManager,\n resolvePackageManagerForCwd,\n} from \"../lib/create-project\";\nimport { runSpawn, SpawnExitError } from \"../lib/run-spawn\";\nimport { logger } from \"../lib/utils/logger\";\nimport {\n getComponentsJsonStyle,\n resolveQuickStartRegistryUrl,\n} from \"../lib/utils/registry\";\nimport { create } from \"./create\";\n\ninterface ExistingProjectInitPlan {\n initArgs: string[];\n addArgs: string[];\n}\n\nexport function createExistingProjectInitPlan(params: {\n yes: boolean;\n overwrite: boolean;\n}): ExistingProjectInitPlan {\n const { yes, overwrite } = params;\n const initArgs = yes\n ? [`shadcn@latest`, \"init\", \"--defaults\", \"--yes\"]\n : [`shadcn@latest`, \"init\"];\n const addArgs = [`shadcn@latest`, \"add\"];\n if (yes) addArgs.push(\"--yes\");\n if (overwrite) addArgs.push(\"--overwrite\");\n\n return { initArgs, addArgs };\n}\n\nexport function isNonInteractiveShell(\n stdinIsTTY = process.stdin.isTTY,\n): boolean {\n return !stdinIsTTY;\n}\n\nexport const init = new Command()\n .name(\"init\")\n .description(\"initialize assistant-ui in an existing project\")\n .argument(\"[project-directory]\", \"directory for the new project\")\n .option(\"-y, --yes\", \"skip confirmation prompt.\", false)\n .option(\"-o, --overwrite\", \"overwrite existing files.\", false)\n .option(\n \"-c, --cwd <cwd>\",\n \"the working directory. defaults to the current directory.\",\n process.cwd(),\n )\n .addOption(\n new Option(\n \"-p, --preset <name-or-url>\",\n \"preset name or URL (forwarded to 'assistant-ui create')\",\n ).hideHelp(),\n )\n .option(\"--use-npm\", \"explicitly use npm\")\n .option(\"--use-pnpm\", \"explicitly use pnpm\")\n .option(\"--use-yarn\", \"explicitly use yarn\")\n .option(\"--use-bun\", \"explicitly use bun\")\n .option(\"--skip-install\", \"skip installing packages\")\n .action(async (projectDirectory, opts) => {\n const cwd = opts.cwd;\n const presetUrl = opts.preset as string | undefined;\n const targetDir = projectDirectory\n ? path.resolve(cwd, projectDirectory)\n : cwd;\n\n const componentsConfigPath = path.join(targetDir, \"components.json\");\n\n if (!presetUrl && fs.existsSync(componentsConfigPath)) {\n logger.warn(\"Project is already initialized.\");\n logger.info(\"Use 'assistant-ui add' to add more components.\");\n return;\n }\n\n const packageJsonPath = path.join(targetDir, \"package.json\");\n const packageJsonExists = fs.existsSync(packageJsonPath);\n\n if (presetUrl || !packageJsonExists) {\n if (!presetUrl) {\n logger.info(\"No existing project found. Running 'create' instead...\");\n logger.break();\n }\n\n const createArgs: string[] = [];\n if (projectDirectory) createArgs.push(projectDirectory);\n if (presetUrl) createArgs.push(\"--preset\", presetUrl);\n if (opts.useNpm) createArgs.push(\"--use-npm\");\n if (opts.usePnpm) createArgs.push(\"--use-pnpm\");\n if (opts.useYarn) createArgs.push(\"--use-yarn\");\n if (opts.useBun) createArgs.push(\"--use-bun\");\n if (opts.skipInstall) createArgs.push(\"--skip-install\");\n\n await create.parseAsync(createArgs, { from: \"user\" });\n return;\n }\n\n logger.info(\"Initializing assistant-ui in existing project...\");\n logger.break();\n\n if (!opts.yes && isNonInteractiveShell()) {\n logger.error(\n [\n \"Detected a non-interactive shell, but 'assistant-ui init' needs interactive prompts by default.\",\n \"To run this in CI/agent mode, re-run with '--yes' so shadcn initialization and component install run non-interactively.\",\n \"Example: assistant-ui init --yes\",\n ].join(\"\\n\"),\n );\n process.exit(1);\n }\n\n try {\n const pm = await resolvePackageManagerForCwd(\n targetDir,\n resolvePackageManager(opts),\n );\n const [dlxCmd, dlxArgs] = dlxCommand(pm);\n\n const { initArgs, addArgs } = createExistingProjectInitPlan({\n yes: opts.yes,\n overwrite: opts.overwrite,\n });\n\n await runSpawn(dlxCmd, [...dlxArgs, ...initArgs], targetDir);\n const registryUrl = resolveQuickStartRegistryUrl(\n getComponentsJsonStyle(targetDir),\n );\n await runSpawn(dlxCmd, [...dlxArgs, ...addArgs, registryUrl], targetDir);\n\n logger.break();\n logger.success(\"Project initialized successfully!\");\n logger.info(\"You can now add more components with 'assistant-ui add'\");\n } catch (error) {\n if (error instanceof SpawnExitError) {\n logger.error(`Initialization failed with code ${error.code}`);\n process.exit(error.code);\n }\n const message = error instanceof Error ? error.message : String(error);\n logger.error(`Failed to initialize: ${message}`);\n process.exit(1);\n }\n });\n"],"mappings":"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"}
1
+ {"version":3,"file":"init.js","names":[],"sources":["../../src/commands/init.ts"],"sourcesContent":["import { Command, Option } from \"commander\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport { dlxCommand, resolvePackageManager } from \"../lib/create-project\";\nimport { runSpawn, SpawnExitError, SpawnSignalError } from \"../lib/run-spawn\";\nimport { logger } from \"../lib/utils/logger\";\nimport { resolvePackageManagerForCwd } from \"../lib/utils/package-manager\";\nimport {\n getComponentsJsonStyle,\n resolveQuickStartRegistryUrl,\n} from \"../lib/utils/registry\";\nimport { create } from \"./create\";\n\ninterface ExistingProjectInitPlan {\n initArgs: string[];\n addArgs: string[];\n}\n\nexport function createExistingProjectInitPlan(params: {\n yes: boolean;\n overwrite: boolean;\n}): ExistingProjectInitPlan {\n const { yes, overwrite } = params;\n const initArgs = yes\n ? [`shadcn@latest`, \"init\", \"--defaults\", \"--yes\"]\n : [`shadcn@latest`, \"init\"];\n const addArgs = [`shadcn@latest`, \"add\"];\n if (yes) addArgs.push(\"--yes\");\n if (overwrite) addArgs.push(\"--overwrite\");\n\n return { initArgs, addArgs };\n}\n\nexport function isNonInteractiveShell(\n stdinIsTTY = process.stdin.isTTY,\n): boolean {\n return !stdinIsTTY;\n}\n\nexport const init = new Command()\n .name(\"init\")\n .description(\"initialize assistant-ui in an existing project\")\n .argument(\"[project-directory]\", \"directory for the new project\")\n .option(\"-y, --yes\", \"skip confirmation prompt.\", false)\n .option(\"-o, --overwrite\", \"overwrite existing files.\", false)\n .option(\n \"-c, --cwd <cwd>\",\n \"the working directory. defaults to the current directory.\",\n process.cwd(),\n )\n .addOption(\n new Option(\n \"-p, --preset <name-or-url>\",\n \"preset name or URL (forwarded to 'assistant-ui create')\",\n ).hideHelp(),\n )\n .option(\"--use-npm\", \"explicitly use npm\")\n .option(\"--use-pnpm\", \"explicitly use pnpm\")\n .option(\"--use-yarn\", \"explicitly use yarn\")\n .option(\"--use-bun\", \"explicitly use bun\")\n .option(\"--skip-install\", \"skip installing packages\")\n .action(async (projectDirectory, opts) => {\n const cwd = opts.cwd;\n const presetUrl = opts.preset as string | undefined;\n const targetDir = projectDirectory\n ? path.resolve(cwd, projectDirectory)\n : cwd;\n\n const componentsConfigPath = path.join(targetDir, \"components.json\");\n\n if (!presetUrl && fs.existsSync(componentsConfigPath)) {\n logger.warn(\"Project is already initialized.\");\n logger.info(\"Use 'assistant-ui add' to add more components.\");\n return;\n }\n\n const packageJsonPath = path.join(targetDir, \"package.json\");\n const packageJsonExists = fs.existsSync(packageJsonPath);\n\n if (presetUrl || !packageJsonExists) {\n if (!presetUrl) {\n logger.info(\"No existing project found. Running 'create' instead...\");\n logger.break();\n }\n\n const createArgs: string[] = [];\n if (projectDirectory) createArgs.push(projectDirectory);\n if (presetUrl) createArgs.push(\"--preset\", presetUrl);\n if (opts.useNpm) createArgs.push(\"--use-npm\");\n if (opts.usePnpm) createArgs.push(\"--use-pnpm\");\n if (opts.useYarn) createArgs.push(\"--use-yarn\");\n if (opts.useBun) createArgs.push(\"--use-bun\");\n if (opts.skipInstall) createArgs.push(\"--skip-install\");\n\n await create.parseAsync(createArgs, { from: \"user\" });\n return;\n }\n\n logger.info(\"Initializing assistant-ui in existing project...\");\n logger.break();\n\n if (!opts.yes && isNonInteractiveShell()) {\n logger.error(\n [\n \"Detected a non-interactive shell, but 'assistant-ui init' needs interactive prompts by default.\",\n \"To run this in CI/agent mode, re-run with '--yes' so shadcn initialization and component install run non-interactively.\",\n \"Example: assistant-ui init --yes\",\n ].join(\"\\n\"),\n );\n process.exit(1);\n }\n\n try {\n const pm = await resolvePackageManagerForCwd(\n targetDir,\n resolvePackageManager(opts),\n );\n const [dlxCmd, dlxArgs] = dlxCommand(pm);\n\n const { initArgs, addArgs } = createExistingProjectInitPlan({\n yes: opts.yes,\n overwrite: opts.overwrite,\n });\n\n await runSpawn(dlxCmd, [...dlxArgs, ...initArgs], targetDir);\n const registryUrl = resolveQuickStartRegistryUrl(\n getComponentsJsonStyle(targetDir),\n );\n await runSpawn(dlxCmd, [...dlxArgs, ...addArgs, registryUrl], targetDir);\n\n logger.break();\n logger.success(\"Project initialized successfully!\");\n logger.info(\"You can now add more components with 'assistant-ui add'\");\n } catch (error) {\n if (error instanceof SpawnSignalError) throw error;\n if (error instanceof SpawnExitError) {\n logger.error(`Initialization failed with code ${error.code}`);\n process.exit(error.code);\n }\n const message = error instanceof Error ? error.message : String(error);\n logger.error(`Failed to initialize: ${message}`);\n process.exit(1);\n }\n });\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"mcp.d.ts","names":[],"sources":["../../src/commands/mcp.ts"],"mappings":";;cAoPa,KAAG"}
1
+ {"version":3,"file":"mcp.d.ts","names":[],"sources":["../../src/commands/mcp.ts"],"mappings":";;cA0Oa,KAAG"}
@@ -1,10 +1,10 @@
1
+ import { SpawnExitError, SpawnSignalError, runSpawn } from "../lib/run-spawn.js";
1
2
  import { logger } from "../lib/utils/logger.js";
3
+ import os from "node:os";
2
4
  import { Command } from "commander";
3
5
  import fs from "node:fs";
4
6
  import path from "node:path";
5
7
  import * as p from "@clack/prompts";
6
- import { spawn } from "cross-spawn";
7
- import os from "node:os";
8
8
  //#region src/commands/mcp.ts
9
9
  const MCP_CONFIGS = {
10
10
  cursor: {
@@ -78,33 +78,29 @@ async function installForTarget(target) {
78
78
  if (target === "claude-code") {
79
79
  logger.info("Installing MCP server for Claude Code...");
80
80
  logger.break();
81
- const child = spawn("claude", [
82
- "mcp",
83
- "add",
84
- "assistant-ui",
85
- "--",
86
- "npx",
87
- "-y",
88
- "@assistant-ui/mcp-docs-server"
89
- ], { stdio: "inherit" });
90
- return new Promise((resolve, reject) => {
91
- child.on("error", (error) => {
81
+ try {
82
+ await runSpawn("claude", [
83
+ "mcp",
84
+ "add",
85
+ "assistant-ui",
86
+ "--",
87
+ "npx",
88
+ "-y",
89
+ "@assistant-ui/mcp-docs-server"
90
+ ]);
91
+ } catch (error) {
92
+ if (error instanceof SpawnSignalError) throw error;
93
+ if (error instanceof SpawnExitError) logger.error(`Installation failed with code ${error.code}`);
94
+ else if (error instanceof Error) {
92
95
  logger.error(`Failed to install: ${error.message}`);
93
96
  logger.info("Make sure Claude Code CLI is installed: https://docs.anthropic.com/en/docs/claude-code");
94
- reject(error);
95
- });
96
- child.on("close", (code) => {
97
- if (code !== 0) {
98
- logger.error(`Installation failed with code ${code}`);
99
- reject(/* @__PURE__ */ new Error(`Exit code ${code}`));
100
- } else {
101
- logger.break();
102
- logger.success("MCP server installed for Claude Code!");
103
- logger.info("The server starts automatically. Try asking about assistant-ui!");
104
- resolve();
105
- }
106
- });
107
- });
97
+ }
98
+ throw error;
99
+ }
100
+ logger.break();
101
+ logger.success("MCP server installed for Claude Code!");
102
+ logger.info("The server starts automatically. Try asking about assistant-ui!");
103
+ return;
108
104
  }
109
105
  if (target === "claude-desktop" && process.platform === "linux") {
110
106
  logger.error("Claude Desktop is not available on Linux.");
@@ -187,7 +183,8 @@ const mcp = new Command().name("mcp").description("install assistant-ui MCP docs
187
183
  }
188
184
  for (const target of targets) try {
189
185
  await installForTarget(target);
190
- } catch {
186
+ } catch (error) {
187
+ if (error instanceof SpawnSignalError) throw error;
191
188
  process.exit(1);
192
189
  }
193
190
  });
@@ -1 +1 @@
1
- {"version":3,"file":"mcp.js","names":[],"sources":["../../src/commands/mcp.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport os from \"node:os\";\nimport { spawn } from \"cross-spawn\";\nimport { logger } from \"../lib/utils/logger\";\nimport * as p from \"@clack/prompts\";\n\ntype MCPTarget =\n | \"cursor\"\n | \"windsurf\"\n | \"vscode\"\n | \"zed\"\n | \"claude-code\"\n | \"claude-desktop\";\n\nconst MCP_CONFIGS: Record<\n Exclude<MCPTarget, \"claude-code\">,\n {\n name: string;\n getPath: () => string;\n config: object;\n postInstall?: string;\n }\n> = {\n cursor: {\n name: \"Cursor\",\n getPath: () => path.join(process.cwd(), \".cursor\", \"mcp.json\"),\n config: {\n mcpServers: {\n \"assistant-ui\": {\n command: \"npx\",\n args: [\"-y\", \"@assistant-ui/mcp-docs-server\"],\n },\n },\n },\n postInstall:\n \"Open Cursor Settings → MCP → find 'assistant-ui' and click enable.\",\n },\n windsurf: {\n name: \"Windsurf\",\n getPath: () =>\n path.join(os.homedir(), \".codeium\", \"windsurf\", \"mcp_config.json\"),\n config: {\n mcpServers: {\n \"assistant-ui\": {\n command: \"npx\",\n args: [\"-y\", \"@assistant-ui/mcp-docs-server\"],\n },\n },\n },\n postInstall: \"Fully quit and re-open Windsurf to activate.\",\n },\n vscode: {\n name: \"VSCode\",\n getPath: () => path.join(process.cwd(), \".vscode\", \"mcp.json\"),\n config: {\n servers: {\n \"assistant-ui\": {\n command: \"npx\",\n args: [\"-y\", \"@assistant-ui/mcp-docs-server\"],\n type: \"stdio\",\n },\n },\n },\n postInstall:\n \"Enable MCP in Settings → search 'MCP' → enable 'Chat > MCP'. Use Copilot Chat in Agent mode.\",\n },\n zed: {\n name: \"Zed\",\n getPath: () => {\n if (process.platform === \"win32\") {\n return path.join(process.env.APPDATA || \"\", \"Zed\", \"settings.json\");\n }\n if (process.platform === \"darwin\") {\n return path.join(os.homedir(), \".zed\", \"settings.json\");\n }\n return path.join(os.homedir(), \".config\", \"zed\", \"settings.json\");\n },\n config: {\n context_servers: {\n \"assistant-ui\": {\n command: {\n path: \"npx\",\n args: [\"-y\", \"@assistant-ui/mcp-docs-server\"],\n },\n },\n },\n },\n postInstall: \"The server starts automatically with the Assistant Panel.\",\n },\n \"claude-desktop\": {\n name: \"Claude Desktop\",\n getPath: () => {\n if (process.platform === \"win32\") {\n return path.join(\n process.env.APPDATA || \"\",\n \"Claude\",\n \"claude_desktop_config.json\",\n );\n }\n return path.join(\n os.homedir(),\n \"Library\",\n \"Application Support\",\n \"Claude\",\n \"claude_desktop_config.json\",\n );\n },\n config: {\n mcpServers: {\n \"assistant-ui\": {\n command: \"npx\",\n args: [\"-y\", \"@assistant-ui/mcp-docs-server\"],\n },\n },\n },\n postInstall: \"Restart Claude Desktop to activate.\",\n },\n};\n\nfunction deepMerge(target: any, source: any): any {\n const result = { ...target };\n for (const key of Object.keys(source)) {\n if (\n source[key] &&\n typeof source[key] === \"object\" &&\n !Array.isArray(source[key])\n ) {\n result[key] = deepMerge(result[key] || {}, source[key]);\n } else {\n result[key] = source[key];\n }\n }\n return result;\n}\n\nclass McpConfigParseError extends Error {\n constructor(targetName: string, configPath: string, flag: string) {\n super(\n `Invalid ${targetName} MCP config JSON at ${configPath}. Fix the JSON syntax, then run: assistant-ui mcp ${flag}`,\n );\n this.name = \"McpConfigParseError\";\n }\n}\n\nconst getTargetFlag = (target: Exclude<MCPTarget, \"claude-code\">) =>\n `--${target}`;\n\nasync function installForTarget(target: MCPTarget): Promise<void> {\n if (target === \"claude-code\") {\n logger.info(\"Installing MCP server for Claude Code...\");\n logger.break();\n\n const child = spawn(\n \"claude\",\n [\n \"mcp\",\n \"add\",\n \"assistant-ui\",\n \"--\",\n \"npx\",\n \"-y\",\n \"@assistant-ui/mcp-docs-server\",\n ],\n {\n stdio: \"inherit\",\n },\n );\n\n return new Promise((resolve, reject) => {\n child.on(\"error\", (error) => {\n logger.error(`Failed to install: ${error.message}`);\n logger.info(\n \"Make sure Claude Code CLI is installed: https://docs.anthropic.com/en/docs/claude-code\",\n );\n reject(error);\n });\n\n child.on(\"close\", (code) => {\n if (code !== 0) {\n logger.error(`Installation failed with code ${code}`);\n reject(new Error(`Exit code ${code}`));\n } else {\n logger.break();\n logger.success(\"MCP server installed for Claude Code!\");\n logger.info(\n \"The server starts automatically. Try asking about assistant-ui!\",\n );\n resolve();\n }\n });\n });\n }\n\n if (target === \"claude-desktop\" && process.platform === \"linux\") {\n logger.error(\"Claude Desktop is not available on Linux.\");\n logger.info(\n \"See: https://claude.ai/download for supported operating systems.\",\n );\n throw new Error(\"Unsupported platform for Claude Desktop\");\n }\n\n const targetConfig = MCP_CONFIGS[target];\n const configPath = targetConfig.getPath();\n const configDir = path.dirname(configPath);\n\n logger.info(`Installing MCP server for ${targetConfig.name}...`);\n\n if (!fs.existsSync(configDir)) {\n fs.mkdirSync(configDir, { recursive: true });\n }\n\n let existingConfig: any = {};\n if (fs.existsSync(configPath)) {\n const content = fs.readFileSync(configPath, \"utf-8\");\n try {\n existingConfig = JSON.parse(content);\n } catch {\n const flag = getTargetFlag(target);\n logger.error(`Could not parse ${targetConfig.name} MCP config.`);\n logger.info(`Config path: ${configPath}`);\n logger.info(\n `Fix the JSON syntax in that file, then run: assistant-ui mcp ${flag}`,\n );\n logger.info(\"No changes were written.\");\n throw new McpConfigParseError(targetConfig.name, configPath, flag);\n }\n }\n\n const newConfig = deepMerge(existingConfig, targetConfig.config);\n\n fs.writeFileSync(configPath, `${JSON.stringify(newConfig, null, 2)}\\n`);\n\n logger.break();\n logger.success(`MCP server installed for ${targetConfig.name}!`);\n logger.info(`Config written to: ${configPath}`);\n\n if (targetConfig.postInstall) {\n logger.break();\n logger.info(targetConfig.postInstall);\n }\n}\n\nexport const mcp = new Command()\n .name(\"mcp\")\n .description(\"install assistant-ui MCP docs server for your IDE\")\n .option(\"--cursor\", \"install for Cursor\")\n .option(\"--windsurf\", \"install for Windsurf\")\n .option(\"--vscode\", \"install for VSCode\")\n .option(\"--zed\", \"install for Zed\")\n .option(\"--claude-code\", \"install for Claude Code\")\n .option(\"--claude-desktop\", \"install for Claude Desktop\")\n .action(async (opts) => {\n const targets: MCPTarget[] = [];\n\n if (opts.cursor) targets.push(\"cursor\");\n if (opts.windsurf) targets.push(\"windsurf\");\n if (opts.vscode) targets.push(\"vscode\");\n if (opts.zed) targets.push(\"zed\");\n if (opts.claudeCode) targets.push(\"claude-code\");\n if (opts.claudeDesktop) targets.push(\"claude-desktop\");\n\n // If no target specified, prompt user\n if (targets.length === 0) {\n p.intro(\"assistant-ui MCP Server Installation\");\n\n const selected = await p.select({\n message: \"Select your IDE or tool:\",\n options: [\n { value: \"cursor\", label: \"Cursor\" },\n { value: \"windsurf\", label: \"Windsurf\" },\n { value: \"vscode\", label: \"VSCode\" },\n { value: \"zed\", label: \"Zed\" },\n { value: \"claude-code\", label: \"Claude Code\" },\n { value: \"claude-desktop\", label: \"Claude Desktop\" },\n ],\n });\n\n if (p.isCancel(selected)) {\n p.cancel(\"Installation cancelled.\");\n process.exit(0);\n }\n\n targets.push(selected as MCPTarget);\n }\n\n for (const target of targets) {\n try {\n await installForTarget(target);\n } catch {\n process.exit(1);\n }\n }\n });\n"],"mappings":"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"}
1
+ {"version":3,"file":"mcp.js","names":[],"sources":["../../src/commands/mcp.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport os from \"node:os\";\nimport { logger } from \"../lib/utils/logger\";\nimport { runSpawn, SpawnExitError, SpawnSignalError } from \"../lib/run-spawn\";\nimport * as p from \"@clack/prompts\";\n\ntype MCPTarget =\n | \"cursor\"\n | \"windsurf\"\n | \"vscode\"\n | \"zed\"\n | \"claude-code\"\n | \"claude-desktop\";\n\nconst MCP_CONFIGS: Record<\n Exclude<MCPTarget, \"claude-code\">,\n {\n name: string;\n getPath: () => string;\n config: object;\n postInstall?: string;\n }\n> = {\n cursor: {\n name: \"Cursor\",\n getPath: () => path.join(process.cwd(), \".cursor\", \"mcp.json\"),\n config: {\n mcpServers: {\n \"assistant-ui\": {\n command: \"npx\",\n args: [\"-y\", \"@assistant-ui/mcp-docs-server\"],\n },\n },\n },\n postInstall:\n \"Open Cursor Settings → MCP → find 'assistant-ui' and click enable.\",\n },\n windsurf: {\n name: \"Windsurf\",\n getPath: () =>\n path.join(os.homedir(), \".codeium\", \"windsurf\", \"mcp_config.json\"),\n config: {\n mcpServers: {\n \"assistant-ui\": {\n command: \"npx\",\n args: [\"-y\", \"@assistant-ui/mcp-docs-server\"],\n },\n },\n },\n postInstall: \"Fully quit and re-open Windsurf to activate.\",\n },\n vscode: {\n name: \"VSCode\",\n getPath: () => path.join(process.cwd(), \".vscode\", \"mcp.json\"),\n config: {\n servers: {\n \"assistant-ui\": {\n command: \"npx\",\n args: [\"-y\", \"@assistant-ui/mcp-docs-server\"],\n type: \"stdio\",\n },\n },\n },\n postInstall:\n \"Enable MCP in Settings → search 'MCP' → enable 'Chat > MCP'. Use Copilot Chat in Agent mode.\",\n },\n zed: {\n name: \"Zed\",\n getPath: () => {\n if (process.platform === \"win32\") {\n return path.join(process.env.APPDATA || \"\", \"Zed\", \"settings.json\");\n }\n if (process.platform === \"darwin\") {\n return path.join(os.homedir(), \".zed\", \"settings.json\");\n }\n return path.join(os.homedir(), \".config\", \"zed\", \"settings.json\");\n },\n config: {\n context_servers: {\n \"assistant-ui\": {\n command: {\n path: \"npx\",\n args: [\"-y\", \"@assistant-ui/mcp-docs-server\"],\n },\n },\n },\n },\n postInstall: \"The server starts automatically with the Assistant Panel.\",\n },\n \"claude-desktop\": {\n name: \"Claude Desktop\",\n getPath: () => {\n if (process.platform === \"win32\") {\n return path.join(\n process.env.APPDATA || \"\",\n \"Claude\",\n \"claude_desktop_config.json\",\n );\n }\n return path.join(\n os.homedir(),\n \"Library\",\n \"Application Support\",\n \"Claude\",\n \"claude_desktop_config.json\",\n );\n },\n config: {\n mcpServers: {\n \"assistant-ui\": {\n command: \"npx\",\n args: [\"-y\", \"@assistant-ui/mcp-docs-server\"],\n },\n },\n },\n postInstall: \"Restart Claude Desktop to activate.\",\n },\n};\n\nfunction deepMerge(target: any, source: any): any {\n const result = { ...target };\n for (const key of Object.keys(source)) {\n if (\n source[key] &&\n typeof source[key] === \"object\" &&\n !Array.isArray(source[key])\n ) {\n result[key] = deepMerge(result[key] || {}, source[key]);\n } else {\n result[key] = source[key];\n }\n }\n return result;\n}\n\nclass McpConfigParseError extends Error {\n constructor(targetName: string, configPath: string, flag: string) {\n super(\n `Invalid ${targetName} MCP config JSON at ${configPath}. Fix the JSON syntax, then run: assistant-ui mcp ${flag}`,\n );\n this.name = \"McpConfigParseError\";\n }\n}\n\nconst getTargetFlag = (target: Exclude<MCPTarget, \"claude-code\">) =>\n `--${target}`;\n\nasync function installForTarget(target: MCPTarget): Promise<void> {\n if (target === \"claude-code\") {\n logger.info(\"Installing MCP server for Claude Code...\");\n logger.break();\n\n try {\n await runSpawn(\"claude\", [\n \"mcp\",\n \"add\",\n \"assistant-ui\",\n \"--\",\n \"npx\",\n \"-y\",\n \"@assistant-ui/mcp-docs-server\",\n ]);\n } catch (error) {\n if (error instanceof SpawnSignalError) throw error;\n if (error instanceof SpawnExitError) {\n logger.error(`Installation failed with code ${error.code}`);\n } else if (error instanceof Error) {\n logger.error(`Failed to install: ${error.message}`);\n logger.info(\n \"Make sure Claude Code CLI is installed: https://docs.anthropic.com/en/docs/claude-code\",\n );\n }\n throw error;\n }\n\n logger.break();\n logger.success(\"MCP server installed for Claude Code!\");\n logger.info(\n \"The server starts automatically. Try asking about assistant-ui!\",\n );\n return;\n }\n\n if (target === \"claude-desktop\" && process.platform === \"linux\") {\n logger.error(\"Claude Desktop is not available on Linux.\");\n logger.info(\n \"See: https://claude.ai/download for supported operating systems.\",\n );\n throw new Error(\"Unsupported platform for Claude Desktop\");\n }\n\n const targetConfig = MCP_CONFIGS[target];\n const configPath = targetConfig.getPath();\n const configDir = path.dirname(configPath);\n\n logger.info(`Installing MCP server for ${targetConfig.name}...`);\n\n if (!fs.existsSync(configDir)) {\n fs.mkdirSync(configDir, { recursive: true });\n }\n\n let existingConfig: any = {};\n if (fs.existsSync(configPath)) {\n const content = fs.readFileSync(configPath, \"utf-8\");\n try {\n existingConfig = JSON.parse(content);\n } catch {\n const flag = getTargetFlag(target);\n logger.error(`Could not parse ${targetConfig.name} MCP config.`);\n logger.info(`Config path: ${configPath}`);\n logger.info(\n `Fix the JSON syntax in that file, then run: assistant-ui mcp ${flag}`,\n );\n logger.info(\"No changes were written.\");\n throw new McpConfigParseError(targetConfig.name, configPath, flag);\n }\n }\n\n const newConfig = deepMerge(existingConfig, targetConfig.config);\n\n fs.writeFileSync(configPath, `${JSON.stringify(newConfig, null, 2)}\\n`);\n\n logger.break();\n logger.success(`MCP server installed for ${targetConfig.name}!`);\n logger.info(`Config written to: ${configPath}`);\n\n if (targetConfig.postInstall) {\n logger.break();\n logger.info(targetConfig.postInstall);\n }\n}\n\nexport const mcp = new Command()\n .name(\"mcp\")\n .description(\"install assistant-ui MCP docs server for your IDE\")\n .option(\"--cursor\", \"install for Cursor\")\n .option(\"--windsurf\", \"install for Windsurf\")\n .option(\"--vscode\", \"install for VSCode\")\n .option(\"--zed\", \"install for Zed\")\n .option(\"--claude-code\", \"install for Claude Code\")\n .option(\"--claude-desktop\", \"install for Claude Desktop\")\n .action(async (opts) => {\n const targets: MCPTarget[] = [];\n\n if (opts.cursor) targets.push(\"cursor\");\n if (opts.windsurf) targets.push(\"windsurf\");\n if (opts.vscode) targets.push(\"vscode\");\n if (opts.zed) targets.push(\"zed\");\n if (opts.claudeCode) targets.push(\"claude-code\");\n if (opts.claudeDesktop) targets.push(\"claude-desktop\");\n\n // If no target specified, prompt user\n if (targets.length === 0) {\n p.intro(\"assistant-ui MCP Server Installation\");\n\n const selected = await p.select({\n message: \"Select your IDE or tool:\",\n options: [\n { value: \"cursor\", label: \"Cursor\" },\n { value: \"windsurf\", label: \"Windsurf\" },\n { value: \"vscode\", label: \"VSCode\" },\n { value: \"zed\", label: \"Zed\" },\n { value: \"claude-code\", label: \"Claude Code\" },\n { value: \"claude-desktop\", label: \"Claude Desktop\" },\n ],\n });\n\n if (p.isCancel(selected)) {\n p.cancel(\"Installation cancelled.\");\n process.exit(0);\n }\n\n targets.push(selected as MCPTarget);\n }\n\n for (const target of targets) {\n try {\n await installForTarget(target);\n } catch (error) {\n if (error instanceof SpawnSignalError) throw error;\n process.exit(1);\n }\n }\n });\n"],"mappings":"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"}