assistant-ui 0.0.121 → 0.0.122

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 (55) hide show
  1. package/dist/commands/add.d.ts.map +1 -1
  2. package/dist/commands/add.js +1 -2
  3. package/dist/commands/add.js.map +1 -1
  4. package/dist/commands/create.d.ts.map +1 -1
  5. package/dist/commands/create.js +2 -2
  6. package/dist/commands/create.js.map +1 -1
  7. package/dist/commands/info.js +1 -1
  8. package/dist/commands/init.d.ts.map +1 -1
  9. package/dist/commands/init.js +1 -2
  10. package/dist/commands/init.js.map +1 -1
  11. package/dist/commands/mcp.d.ts.map +1 -1
  12. package/dist/commands/mcp.js +95 -23
  13. package/dist/commands/mcp.js.map +1 -1
  14. package/dist/lib/agent-skill.d.ts.map +1 -1
  15. package/dist/lib/agent-skill.js +9 -27
  16. package/dist/lib/agent-skill.js.map +1 -1
  17. package/dist/lib/create-project.d.ts +0 -9
  18. package/dist/lib/create-project.d.ts.map +1 -1
  19. package/dist/lib/create-project.js +15 -46
  20. package/dist/lib/create-project.js.map +1 -1
  21. package/dist/lib/transform.d.ts +0 -4
  22. package/dist/lib/transform.d.ts.map +1 -1
  23. package/dist/lib/transform.js +7 -16
  24. package/dist/lib/transform.js.map +1 -1
  25. package/dist/lib/utils/download.d.ts +5 -0
  26. package/dist/lib/utils/download.d.ts.map +1 -0
  27. package/dist/lib/utils/download.js +41 -0
  28. package/dist/lib/utils/download.js.map +1 -0
  29. package/dist/lib/utils/file-scanner.d.ts +0 -1
  30. package/dist/lib/utils/file-scanner.d.ts.map +1 -1
  31. package/dist/lib/utils/file-scanner.js +1 -16
  32. package/dist/lib/utils/file-scanner.js.map +1 -1
  33. package/dist/lib/utils/package-manager.d.ts +7 -0
  34. package/dist/lib/utils/package-manager.d.ts.map +1 -1
  35. package/dist/lib/utils/package-manager.js +15 -1
  36. package/dist/lib/utils/package-manager.js.map +1 -1
  37. package/package.json +3 -3
  38. package/src/commands/add.ts +2 -1
  39. package/src/commands/create.ts +5 -3
  40. package/src/commands/init.ts +5 -2
  41. package/src/commands/mcp.ts +223 -56
  42. package/src/lib/agent-skill.ts +17 -43
  43. package/src/lib/create-project.test.ts +0 -17
  44. package/src/lib/create-project.ts +33 -98
  45. package/src/lib/transform-files.test.ts +1 -3
  46. package/src/lib/transform.ts +6 -20
  47. package/src/lib/utils/download.ts +57 -0
  48. package/src/lib/utils/file-scanner.ts +0 -26
  49. package/src/lib/utils/package-manager.ts +26 -0
  50. package/src/lib/utils/registry.test.ts +0 -6
  51. package/templates/cloud-harness/app/api/chat/route.ts +1 -0
  52. package/templates/cloud-harness/components/assistant-ui/elements/collapsible-root.tsx +19 -0
  53. package/templates/cloud-harness/components/assistant-ui/elements/markdown-text.tsx +1 -1
  54. package/templates/cloud-harness/components/assistant-ui/elements/tool-fallback.aui.tsx +198 -30
  55. package/templates/cloud-harness/package.json +12 -12
@@ -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 { 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 HOSTED_MCP_URL = \"https://www.assistant-ui.com/mcp\";\n\nconst MCP_CONFIGS: Record<\n Exclude<MCPTarget, \"claude-code\">,\n {\n name: string;\n getPath: () => string;\n config: object;\n replaceServerKey?: string;\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 url: HOSTED_MCP_URL,\n },\n },\n },\n replaceServerKey: \"mcpServers\",\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 serverUrl: HOSTED_MCP_URL,\n },\n },\n },\n replaceServerKey: \"mcpServers\",\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 type: \"http\",\n url: HOSTED_MCP_URL,\n },\n },\n },\n replaceServerKey: \"servers\",\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 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\", [\"mcp\", \"remove\", \"assistant-ui\"]).catch(\n (error: unknown) => {\n if (error instanceof SpawnSignalError) throw error;\n },\n );\n await runSpawn(\"claude\", [\n \"mcp\",\n \"add\",\n \"--transport\",\n \"http\",\n \"assistant-ui\",\n HOSTED_MCP_URL,\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 `Connects to the hosted assistant-ui MCP server at ${HOSTED_MCP_URL}.`,\n );\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 if (targetConfig.replaceServerKey) {\n const key = targetConfig.replaceServerKey;\n newConfig[key] = {\n ...newConfig[key],\n \"assistant-ui\": (targetConfig.config as any)[key][\"assistant-ui\"],\n };\n }\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.replaceServerKey) {\n logger.break();\n logger.info(\n `Connects to the hosted assistant-ui MCP server at ${HOSTED_MCP_URL}.`,\n );\n }\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(\"connect your IDE to the assistant-ui MCP server\")\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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"}
1
+ {"version":3,"file":"mcp.js","names":["parseJsonc"],"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 {\n applyEdits,\n parse as parseJsonc,\n parseTree,\n stripComments,\n type Node,\n type ParseError,\n} from \"jsonc-parser\";\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 HOSTED_MCP_URL = \"https://www.assistant-ui.com/mcp\";\n\nconst MCP_CONFIGS: Record<\n Exclude<MCPTarget, \"claude-code\">,\n {\n name: string;\n getPath: () => string;\n serverKey: string;\n server: object;\n jsonc?: boolean;\n postInstall?: string;\n }\n> = {\n cursor: {\n name: \"Cursor\",\n getPath: () => path.join(process.cwd(), \".cursor\", \"mcp.json\"),\n serverKey: \"mcpServers\",\n server: { url: HOSTED_MCP_URL },\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 serverKey: \"mcpServers\",\n server: { serverUrl: HOSTED_MCP_URL },\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 serverKey: \"servers\",\n server: { type: \"http\", url: HOSTED_MCP_URL },\n jsonc: true,\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 serverKey: \"context_servers\",\n jsonc: true,\n getPath: () => {\n if (process.platform === \"win32\") {\n return path.join(process.env.APPDATA || \"\", \"Zed\", \"settings.json\");\n }\n return path.join(os.homedir(), \".config\", \"zed\", \"settings.json\");\n },\n server: {\n command: {\n path: \"npx\",\n args: [\"-y\", \"@assistant-ui/mcp-docs-server\"],\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 serverKey: \"mcpServers\",\n server: {\n command: \"npx\",\n args: [\"-y\", \"@assistant-ui/mcp-docs-server\"],\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\nconst lastPropertyValue = (node: Node, key: string) =>\n node.children?.findLast((property) => property.children?.[0]?.value === key)\n ?.children?.[1];\n\nconst lineStartAt = (content: string, offset: number) =>\n content.lastIndexOf(\"\\n\", offset - 1) + 1;\n\nconst lineIndentAt = (content: string, offset: number) =>\n content.slice(lineStartAt(content, offset), offset).match(/^[\\t ]*/)?.[0] ??\n \"\";\n\nconst getIndentUnit = (content: string, object: Node) => {\n const objectLine = lineStartAt(content, object.offset);\n const objectIndent = lineIndentAt(content, object.offset);\n const multilineChild = object.children?.find(\n (child) => lineStartAt(content, child.offset) > objectLine,\n );\n if (multilineChild) {\n const childIndent = lineIndentAt(content, multilineChild.offset);\n if (\n childIndent.startsWith(objectIndent) &&\n childIndent.length > objectIndent.length\n ) {\n return childIndent.slice(objectIndent.length);\n }\n }\n\n const documentIndent = content.match(/(?:^|\\r?\\n)([\\t ]+)(?=\")/)?.[1];\n if (documentIndent?.includes(\"\\t\")) return \"\\t\";\n return documentIndent || \" \";\n};\n\nconst stringifyValue = (\n value: object,\n baseIndent: string,\n indentUnit: string,\n eol: string,\n) =>\n JSON.stringify(value, null, indentUnit).replaceAll(\n \"\\n\",\n `${eol}${baseIndent}`,\n );\n\nconst appendObjectProperty = (\n content: string,\n object: Node,\n key: string,\n value: object,\n eol: string,\n) => {\n const objectIndent = lineIndentAt(content, object.offset);\n const indentUnit = getIndentUnit(content, object);\n const propertyIndent = objectIndent + indentUnit;\n const property = `${propertyIndent}${JSON.stringify(key)}: ${stringifyValue(\n value,\n propertyIndent,\n indentUnit,\n eol,\n )}`;\n const closeOffset = object.offset + object.length - 1;\n const closeLineStart = lineStartAt(content, closeOffset);\n const closeOnOwnLine = /^[\\t ]*$/.test(\n content.slice(closeLineStart, closeOffset),\n );\n const edits = [\n {\n offset: closeOnOwnLine ? closeLineStart : closeOffset,\n length: 0,\n content: closeOnOwnLine\n ? `${property}${eol}`\n : `${eol}${property}${eol}${objectIndent}`,\n },\n ];\n\n const lastProperty = object.children?.at(-1);\n if (lastProperty) {\n const propertyEnd = lastProperty.offset + lastProperty.length;\n const trailingContent = stripComments(\n content.slice(propertyEnd, closeOffset),\n ).trimStart();\n if (!trailingContent.startsWith(\",\")) {\n edits.unshift({ offset: propertyEnd, length: 0, content: \",\" });\n }\n }\n\n return applyEdits(content, edits);\n};\n\nconst replaceNodeValue = (\n content: string,\n node: Node,\n container: Node,\n value: object,\n eol: string,\n) =>\n applyEdits(content, [\n {\n offset: node.offset,\n length: node.length,\n content: stringifyValue(\n value,\n lineIndentAt(content, node.offset),\n getIndentUnit(content, container),\n eol,\n ),\n },\n ]);\n\nfunction updateJsoncConfig(\n content: string,\n serverKey: string,\n server: object,\n): string {\n const eol = content.includes(\"\\r\\n\") ? \"\\r\\n\" : \"\\n\";\n const root = parseTree(content, [], {\n allowTrailingComma: true,\n allowEmptyContent: true,\n });\n if (!root) {\n const initialized = JSON.stringify(\n { [serverKey]: { \"assistant-ui\": server } },\n null,\n 2,\n ).replaceAll(\"\\n\", eol);\n if (!content.trim()) return `${initialized}${eol}`;\n return `${content}${content.endsWith(eol) ? \"\" : eol}${initialized}${eol}`;\n }\n\n // JSONC resolves duplicate keys to the last value.\n const servers = lastPropertyValue(root, serverKey);\n if (!servers) {\n return appendObjectProperty(\n content,\n root,\n serverKey,\n { \"assistant-ui\": server },\n eol,\n );\n }\n\n if (servers.type !== \"object\") {\n return replaceNodeValue(\n content,\n servers,\n root,\n { \"assistant-ui\": server },\n eol,\n );\n }\n\n const existing = lastPropertyValue(servers, \"assistant-ui\");\n return existing\n ? replaceNodeValue(content, existing, servers, server, eol)\n : appendObjectProperty(content, servers, \"assistant-ui\", server, eol);\n}\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\", [\"mcp\", \"remove\", \"assistant-ui\"]).catch(\n (error: unknown) => {\n if (error instanceof SpawnSignalError) throw error;\n },\n );\n await runSpawn(\"claude\", [\n \"mcp\",\n \"add\",\n \"--transport\",\n \"http\",\n \"assistant-ui\",\n HOSTED_MCP_URL,\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 `Connects to the hosted assistant-ui MCP server at ${HOSTED_MCP_URL}.`,\n );\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 let content = \"{}\\n\";\n if (fs.existsSync(configPath)) {\n content = fs.readFileSync(configPath, \"utf-8\");\n try {\n if (targetConfig.jsonc) {\n const errors: ParseError[] = [];\n existingConfig = parseJsonc(content, errors, {\n allowTrailingComma: true,\n allowEmptyContent: true,\n });\n if (existingConfig === undefined) existingConfig = {};\n if (\n errors.length > 0 ||\n existingConfig === null ||\n typeof existingConfig !== \"object\" ||\n Array.isArray(existingConfig)\n ) {\n throw new SyntaxError(\"Invalid MCP configuration\");\n }\n } else {\n existingConfig = JSON.parse(content);\n if (\n existingConfig === null ||\n typeof existingConfig !== \"object\" ||\n Array.isArray(existingConfig)\n ) {\n throw new SyntaxError(\"Invalid MCP configuration\");\n }\n }\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 updatedContent = updateJsoncConfig(\n content,\n targetConfig.serverKey,\n target === \"zed\" || target === \"claude-desktop\"\n ? deepMerge(\n existingConfig[targetConfig.serverKey]?.[\"assistant-ui\"] ?? {},\n targetConfig.server,\n )\n : targetConfig.server,\n );\n fs.writeFileSync(configPath, updatedContent);\n\n logger.break();\n logger.success(`MCP server installed for ${targetConfig.name}!`);\n logger.info(`Config written to: ${configPath}`);\n\n if (target === \"cursor\" || target === \"windsurf\" || target === \"vscode\") {\n logger.break();\n logger.info(\n `Connects to the hosted assistant-ui MCP server at ${HOSTED_MCP_URL}.`,\n );\n }\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(\"connect your IDE to the assistant-ui MCP server\")\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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"}
@@ -1 +1 @@
1
- {"version":3,"file":"agent-skill.d.ts","sourceRoot":"","sources":["../../src/lib/agent-skill.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,KAAK,kBAAkB,EAAE,mCAAgC;AAElE,eAAO,MAAM,cAAc,wBAAwB,CAAC;AACpD,eAAO,MAAM,aAAa,6CAA6C,CAAC;AACxE,eAAO,MAAM,oBAAoB,iFAAuD,CAAC;AAEzF,wBAAgB,oBAAoB,CAAC,MAAM,EAAE;IAC3C,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB,GAAG,OAAO,GAAG,SAAS,CAKtB;AAED,wBAAgB,qBAAqB,CACnC,EAAE,EAAE,kBAAkB,EACtB,MAAM,GAAE;IAAE,UAAU,CAAC,EAAE,OAAO,CAAA;CAAO,GACpC,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAUpB;AAED,wBAAgB,eAAe,IAAI,MAAM,CAIxC;AAED,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,MAAM,CAAC,CAgE1D"}
1
+ {"version":3,"file":"agent-skill.d.ts","sourceRoot":"","sources":["../../src/lib/agent-skill.ts"],"names":[],"mappings":"AAIA,OAAO,EAAc,KAAK,kBAAkB,EAAE,mCAAgC;AAE9E,eAAO,MAAM,cAAc,wBAAwB,CAAC;AACpD,eAAO,MAAM,aAAa,6CAA6C,CAAC;AACxE,eAAO,MAAM,oBAAoB,iFAAuD,CAAC;AAEzF,wBAAgB,oBAAoB,CAAC,MAAM,EAAE;IAC3C,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB,GAAG,OAAO,GAAG,SAAS,CAKtB;AAED,wBAAgB,qBAAqB,CACnC,EAAE,EAAE,kBAAkB,EACtB,MAAM,GAAE;IAAE,UAAU,CAAC,EAAE,OAAO,CAAA;CAAO,GACpC,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAUpB;AAED,wBAAgB,eAAe,IAAI,MAAM,CAIxC;AAED,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,MAAM,CAAC,CA2C1D"}
@@ -1,8 +1,8 @@
1
- import { DOWNLOAD_TIMEOUT_MS, dlxCommand, resolveGitHubAuthToken } from "./create-project.js";
1
+ import { dlxCommand } from "./utils/package-manager.js";
2
+ import { withStagedDownload } from "./utils/download.js";
2
3
  import fs from "node:fs";
3
4
  import path from "node:path";
4
5
  import os from "node:os";
5
- import { downloadTemplate } from "giget";
6
6
  //#region src/lib/agent-skill.ts
7
7
  const SKILLS_PACKAGE = "assistant-ui/skills";
8
8
  const SKILLS_COMMIT = "139674dc888ee076982b6726e8e6f5d0fe0b5f67";
@@ -51,34 +51,16 @@ async function ensureSkillsPlugin() {
51
51
  process.once("exit", removeStaging);
52
52
  process.once("SIGINT", removeStagingOnSignal);
53
53
  process.once("SIGTERM", removeStagingOnSignal);
54
- const origDebug = process.env.DEBUG;
55
- delete process.env.DEBUG;
56
- let timer;
57
- let downloadSettled = false;
58
- let download;
59
- try {
60
- const authToken = resolveGitHubAuthToken();
61
- download = downloadTemplate(SKILLS_PLUGIN_SOURCE, {
62
- dir: staging,
63
- preferOffline: true,
64
- silent: true,
65
- ...authToken ? { auth: authToken } : {}
66
- }).finally(() => {
67
- downloadSettled = true;
68
- });
69
- const timeout = new Promise((_, reject) => {
70
- timer = setTimeout(() => reject(/* @__PURE__ */ new Error("Download timed out.")), DOWNLOAD_TIMEOUT_MS);
71
- });
72
- await Promise.race([download, timeout]).catch((error) => {
54
+ await withStagedDownload(SKILLS_PLUGIN_SOURCE, {
55
+ dir: staging,
56
+ preferOffline: true,
57
+ silent: true
58
+ }, "Download timed out.", removeStaging, async (download) => {
59
+ await download.catch((error) => {
73
60
  throw new Error("Could not fetch the assistant-ui skills from GitHub. Check your network, or set GITHUB_TOKEN if you are rate limited.", { cause: error });
74
61
  });
75
62
  await publish(staging, dir, marker);
76
- } finally {
77
- clearTimeout(timer);
78
- if (origDebug !== void 0) process.env.DEBUG = origDebug;
79
- if (!download || downloadSettled) removeStaging();
80
- else download.then(removeStaging, removeStaging);
81
- }
63
+ });
82
64
  return dir;
83
65
  }
84
66
  async function publish(staging, dir, marker, retry = true) {
@@ -1 +1 @@
1
- {"version":3,"file":"agent-skill.js","names":[],"sources":["../../src/lib/agent-skill.ts"],"sourcesContent":["import fs from \"node:fs\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport { downloadTemplate } from \"giget\";\nimport {\n DOWNLOAD_TIMEOUT_MS,\n dlxCommand,\n resolveGitHubAuthToken,\n} from \"./create-project\";\nimport { type PackageManagerName } from \"./utils/package-manager\";\n\nexport const SKILLS_PACKAGE = \"assistant-ui/skills\";\nexport const SKILLS_COMMIT = \"139674dc888ee076982b6726e8e6f5d0fe0b5f67\";\nexport const SKILLS_PLUGIN_SOURCE = `gh:${SKILLS_PACKAGE}/assistant-ui#${SKILLS_COMMIT}`;\n\nexport function resolveSkillsInstall(params: {\n skills?: boolean;\n stdinIsTTY?: boolean;\n}): boolean | undefined {\n const { skills, stdinIsTTY = process.stdin.isTTY } = params;\n if (skills !== undefined) return skills;\n if (!stdinIsTTY) return true;\n return undefined;\n}\n\nexport function buildSkillsAddCommand(\n pm: PackageManagerName,\n params: { stdinIsTTY?: boolean } = {},\n): [string, string[]] {\n const { stdinIsTTY = process.stdin.isTTY } = params;\n const [command, dlxArgs] = dlxCommand(pm);\n const args = [...dlxArgs, \"skills\", \"add\", SKILLS_PACKAGE];\n\n // Without a TTY the skills CLI cannot prompt for agent platforms, so skip its\n // confirmation; with a TTY it owns the platform selection interactively.\n if (!stdinIsTTY) args.push(\"--yes\");\n\n return [command, args];\n}\n\nexport function skillsPluginDir(): string {\n const cacheHome =\n process.env.XDG_CACHE_HOME || path.join(os.homedir(), \".cache\");\n return path.join(cacheHome, \"assistant-ui\", \"skills\", SKILLS_COMMIT);\n}\n\nexport async function ensureSkillsPlugin(): Promise<string> {\n const dir = skillsPluginDir();\n const marker = path.join(dir, \".claude-plugin\", \"plugin.json\");\n if (fs.existsSync(marker)) return dir;\n\n const parent = path.dirname(dir);\n await fs.promises.mkdir(parent, { recursive: true });\n const staging = await fs.promises.mkdtemp(path.join(parent, \".staging-\"));\n // Node emits no \"exit\" when a signal kills the process, so the staging\n // directory is removed on the signal and the signal re-raised. The\n // listeners stay armed until the removal runs, which a download that\n // outlives the timeout defers past the caller's own exit.\n const removeStaging = () => {\n process.removeListener(\"exit\", removeStaging);\n process.removeListener(\"SIGINT\", removeStagingOnSignal);\n process.removeListener(\"SIGTERM\", removeStagingOnSignal);\n fs.rmSync(staging, { recursive: true, force: true });\n };\n const removeStagingOnSignal = (signal: NodeJS.Signals) => {\n removeStaging();\n process.kill(process.pid, signal);\n };\n process.once(\"exit\", removeStaging);\n process.once(\"SIGINT\", removeStagingOnSignal);\n process.once(\"SIGTERM\", removeStagingOnSignal);\n\n // giget logs to console.debug whenever DEBUG is set, which the `debug`\n // package does at module load for an unrelated namespace.\n const origDebug = process.env.DEBUG;\n delete process.env.DEBUG;\n let timer: ReturnType<typeof setTimeout> | undefined;\n let downloadSettled = false;\n let download: Promise<unknown> | undefined;\n try {\n const authToken = resolveGitHubAuthToken();\n download = downloadTemplate(SKILLS_PLUGIN_SOURCE, {\n dir: staging,\n preferOffline: true,\n silent: true,\n ...(authToken ? { auth: authToken } : {}),\n }).finally(() => {\n downloadSettled = true;\n });\n const timeout = new Promise<never>((_, reject) => {\n timer = setTimeout(\n () => reject(new Error(\"Download timed out.\")),\n DOWNLOAD_TIMEOUT_MS,\n );\n });\n await Promise.race([download, timeout]).catch((error: unknown) => {\n throw new Error(\n \"Could not fetch the assistant-ui skills from GitHub. Check your network, or set GITHUB_TOKEN if you are rate limited.\",\n { cause: error },\n );\n });\n await publish(staging, dir, marker);\n } finally {\n clearTimeout(timer);\n if (origDebug !== undefined) process.env.DEBUG = origDebug;\n if (!download || downloadSettled) removeStaging();\n else void download.then(removeStaging, removeStaging);\n }\n\n return dir;\n}\n\n// A rename fails when the target directory exists and is not empty. A\n// concurrent invocation that published the same commit meanwhile wins and\n// the staged copy is dropped; a directory without the marker is a stale\n// partial cache and is replaced.\nasync function publish(\n staging: string,\n dir: string,\n marker: string,\n retry = true,\n): Promise<void> {\n try {\n await fs.promises.rename(staging, dir);\n } catch (error) {\n if (fs.existsSync(marker)) return;\n if (!retry) throw error;\n await fs.promises.rm(dir, { recursive: true, force: true });\n await publish(staging, dir, marker, false);\n }\n}\n"],"mappings":";;;;;;AAWA,MAAa,iBAAiB;AAC9B,MAAa,gBAAgB;AAC7B,MAAa,uBAAuB,MAAM,eAAe,gBAAgB;AAEzE,SAAgB,qBAAqB,QAGb;CACtB,MAAM,EAAE,QAAQ,aAAa,QAAQ,MAAM,UAAU;CACrD,IAAI,WAAW,KAAA,GAAW,OAAO;CACjC,IAAI,CAAC,YAAY,OAAO;AAE1B;AAEA,SAAgB,sBACd,IACA,SAAmC,CAAC,GAChB;CACpB,MAAM,EAAE,aAAa,QAAQ,MAAM,UAAU;CAC7C,MAAM,CAAC,SAAS,WAAW,WAAW,EAAE;CACxC,MAAM,OAAO;EAAC,GAAG;EAAS;EAAU;EAAO;CAAc;CAIzD,IAAI,CAAC,YAAY,KAAK,KAAK,OAAO;CAElC,OAAO,CAAC,SAAS,IAAI;AACvB;AAEA,SAAgB,kBAA0B;CACxC,MAAM,YACJ,QAAQ,IAAI,kBAAkB,KAAK,KAAK,GAAG,QAAQ,GAAG,QAAQ;CAChE,OAAO,KAAK,KAAK,WAAW,gBAAgB,UAAU,aAAa;AACrE;AAEA,eAAsB,qBAAsC;CAC1D,MAAM,MAAM,gBAAgB;CAC5B,MAAM,SAAS,KAAK,KAAK,KAAK,kBAAkB,aAAa;CAC7D,IAAI,GAAG,WAAW,MAAM,GAAG,OAAO;CAElC,MAAM,SAAS,KAAK,QAAQ,GAAG;CAC/B,MAAM,GAAG,SAAS,MAAM,QAAQ,EAAE,WAAW,KAAK,CAAC;CACnD,MAAM,UAAU,MAAM,GAAG,SAAS,QAAQ,KAAK,KAAK,QAAQ,WAAW,CAAC;CAKxE,MAAM,sBAAsB;EAC1B,QAAQ,eAAe,QAAQ,aAAa;EAC5C,QAAQ,eAAe,UAAU,qBAAqB;EACtD,QAAQ,eAAe,WAAW,qBAAqB;EACvD,GAAG,OAAO,SAAS;GAAE,WAAW;GAAM,OAAO;EAAK,CAAC;CACrD;CACA,MAAM,yBAAyB,WAA2B;EACxD,cAAc;EACd,QAAQ,KAAK,QAAQ,KAAK,MAAM;CAClC;CACA,QAAQ,KAAK,QAAQ,aAAa;CAClC,QAAQ,KAAK,UAAU,qBAAqB;CAC5C,QAAQ,KAAK,WAAW,qBAAqB;CAI7C,MAAM,YAAY,QAAQ,IAAI;CAC9B,OAAO,QAAQ,IAAI;CACnB,IAAI;CACJ,IAAI,kBAAkB;CACtB,IAAI;CACJ,IAAI;EACF,MAAM,YAAY,uBAAuB;EACzC,WAAW,iBAAiB,sBAAsB;GAChD,KAAK;GACL,eAAe;GACf,QAAQ;GACR,GAAI,YAAY,EAAE,MAAM,UAAU,IAAI,CAAC;EACzC,CAAC,CAAC,CAAC,cAAc;GACf,kBAAkB;EACpB,CAAC;EACD,MAAM,UAAU,IAAI,SAAgB,GAAG,WAAW;GAChD,QAAQ,iBACA,uBAAO,IAAI,MAAM,qBAAqB,CAAC,GAC7C,mBACF;EACF,CAAC;EACD,MAAM,QAAQ,KAAK,CAAC,UAAU,OAAO,CAAC,CAAC,CAAC,OAAO,UAAmB;GAChE,MAAM,IAAI,MACR,yHACA,EAAE,OAAO,MAAM,CACjB;EACF,CAAC;EACD,MAAM,QAAQ,SAAS,KAAK,MAAM;CACpC,UAAU;EACR,aAAa,KAAK;EAClB,IAAI,cAAc,KAAA,GAAW,QAAQ,IAAI,QAAQ;EACjD,IAAI,CAAC,YAAY,iBAAiB,cAAc;OAC3C,SAAc,KAAK,eAAe,aAAa;CACtD;CAEA,OAAO;AACT;AAMA,eAAe,QACb,SACA,KACA,QACA,QAAQ,MACO;CACf,IAAI;EACF,MAAM,GAAG,SAAS,OAAO,SAAS,GAAG;CACvC,SAAS,OAAO;EACd,IAAI,GAAG,WAAW,MAAM,GAAG;EAC3B,IAAI,CAAC,OAAO,MAAM;EAClB,MAAM,GAAG,SAAS,GAAG,KAAK;GAAE,WAAW;GAAM,OAAO;EAAK,CAAC;EAC1D,MAAM,QAAQ,SAAS,KAAK,QAAQ,KAAK;CAC3C;AACF"}
1
+ {"version":3,"file":"agent-skill.js","names":[],"sources":["../../src/lib/agent-skill.ts"],"sourcesContent":["import fs from \"node:fs\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport { withStagedDownload } from \"./utils/download\";\nimport { dlxCommand, type PackageManagerName } from \"./utils/package-manager\";\n\nexport const SKILLS_PACKAGE = \"assistant-ui/skills\";\nexport const SKILLS_COMMIT = \"139674dc888ee076982b6726e8e6f5d0fe0b5f67\";\nexport const SKILLS_PLUGIN_SOURCE = `gh:${SKILLS_PACKAGE}/assistant-ui#${SKILLS_COMMIT}`;\n\nexport function resolveSkillsInstall(params: {\n skills?: boolean;\n stdinIsTTY?: boolean;\n}): boolean | undefined {\n const { skills, stdinIsTTY = process.stdin.isTTY } = params;\n if (skills !== undefined) return skills;\n if (!stdinIsTTY) return true;\n return undefined;\n}\n\nexport function buildSkillsAddCommand(\n pm: PackageManagerName,\n params: { stdinIsTTY?: boolean } = {},\n): [string, string[]] {\n const { stdinIsTTY = process.stdin.isTTY } = params;\n const [command, dlxArgs] = dlxCommand(pm);\n const args = [...dlxArgs, \"skills\", \"add\", SKILLS_PACKAGE];\n\n // Without a TTY the skills CLI cannot prompt for agent platforms, so skip its\n // confirmation; with a TTY it owns the platform selection interactively.\n if (!stdinIsTTY) args.push(\"--yes\");\n\n return [command, args];\n}\n\nexport function skillsPluginDir(): string {\n const cacheHome =\n process.env.XDG_CACHE_HOME || path.join(os.homedir(), \".cache\");\n return path.join(cacheHome, \"assistant-ui\", \"skills\", SKILLS_COMMIT);\n}\n\nexport async function ensureSkillsPlugin(): Promise<string> {\n const dir = skillsPluginDir();\n const marker = path.join(dir, \".claude-plugin\", \"plugin.json\");\n if (fs.existsSync(marker)) return dir;\n\n const parent = path.dirname(dir);\n await fs.promises.mkdir(parent, { recursive: true });\n const staging = await fs.promises.mkdtemp(path.join(parent, \".staging-\"));\n // Node emits no \"exit\" when a signal kills the process, so the staging\n // directory is removed on the signal and the signal re-raised. The\n // listeners stay armed until the removal runs, which a download that\n // outlives the timeout defers past the caller's own exit.\n const removeStaging = () => {\n process.removeListener(\"exit\", removeStaging);\n process.removeListener(\"SIGINT\", removeStagingOnSignal);\n process.removeListener(\"SIGTERM\", removeStagingOnSignal);\n fs.rmSync(staging, { recursive: true, force: true });\n };\n const removeStagingOnSignal = (signal: NodeJS.Signals) => {\n removeStaging();\n process.kill(process.pid, signal);\n };\n process.once(\"exit\", removeStaging);\n process.once(\"SIGINT\", removeStagingOnSignal);\n process.once(\"SIGTERM\", removeStagingOnSignal);\n\n await withStagedDownload(\n SKILLS_PLUGIN_SOURCE,\n { dir: staging, preferOffline: true, silent: true },\n \"Download timed out.\",\n removeStaging,\n async (download) => {\n await download.catch((error: unknown) => {\n throw new Error(\n \"Could not fetch the assistant-ui skills from GitHub. Check your network, or set GITHUB_TOKEN if you are rate limited.\",\n { cause: error },\n );\n });\n await publish(staging, dir, marker);\n },\n );\n\n return dir;\n}\n\n// A rename fails when the target directory exists and is not empty. A\n// concurrent invocation that published the same commit meanwhile wins and\n// the staged copy is dropped; a directory without the marker is a stale\n// partial cache and is replaced.\nasync function publish(\n staging: string,\n dir: string,\n marker: string,\n retry = true,\n): Promise<void> {\n try {\n await fs.promises.rename(staging, dir);\n } catch (error) {\n if (fs.existsSync(marker)) return;\n if (!retry) throw error;\n await fs.promises.rm(dir, { recursive: true, force: true });\n await publish(staging, dir, marker, false);\n }\n}\n"],"mappings":";;;;;;AAMA,MAAa,iBAAiB;AAC9B,MAAa,gBAAgB;AAC7B,MAAa,uBAAuB,MAAM,eAAe,gBAAgB;AAEzE,SAAgB,qBAAqB,QAGb;CACtB,MAAM,EAAE,QAAQ,aAAa,QAAQ,MAAM,UAAU;CACrD,IAAI,WAAW,KAAA,GAAW,OAAO;CACjC,IAAI,CAAC,YAAY,OAAO;AAE1B;AAEA,SAAgB,sBACd,IACA,SAAmC,CAAC,GAChB;CACpB,MAAM,EAAE,aAAa,QAAQ,MAAM,UAAU;CAC7C,MAAM,CAAC,SAAS,WAAW,WAAW,EAAE;CACxC,MAAM,OAAO;EAAC,GAAG;EAAS;EAAU;EAAO;CAAc;CAIzD,IAAI,CAAC,YAAY,KAAK,KAAK,OAAO;CAElC,OAAO,CAAC,SAAS,IAAI;AACvB;AAEA,SAAgB,kBAA0B;CACxC,MAAM,YACJ,QAAQ,IAAI,kBAAkB,KAAK,KAAK,GAAG,QAAQ,GAAG,QAAQ;CAChE,OAAO,KAAK,KAAK,WAAW,gBAAgB,UAAU,aAAa;AACrE;AAEA,eAAsB,qBAAsC;CAC1D,MAAM,MAAM,gBAAgB;CAC5B,MAAM,SAAS,KAAK,KAAK,KAAK,kBAAkB,aAAa;CAC7D,IAAI,GAAG,WAAW,MAAM,GAAG,OAAO;CAElC,MAAM,SAAS,KAAK,QAAQ,GAAG;CAC/B,MAAM,GAAG,SAAS,MAAM,QAAQ,EAAE,WAAW,KAAK,CAAC;CACnD,MAAM,UAAU,MAAM,GAAG,SAAS,QAAQ,KAAK,KAAK,QAAQ,WAAW,CAAC;CAKxE,MAAM,sBAAsB;EAC1B,QAAQ,eAAe,QAAQ,aAAa;EAC5C,QAAQ,eAAe,UAAU,qBAAqB;EACtD,QAAQ,eAAe,WAAW,qBAAqB;EACvD,GAAG,OAAO,SAAS;GAAE,WAAW;GAAM,OAAO;EAAK,CAAC;CACrD;CACA,MAAM,yBAAyB,WAA2B;EACxD,cAAc;EACd,QAAQ,KAAK,QAAQ,KAAK,MAAM;CAClC;CACA,QAAQ,KAAK,QAAQ,aAAa;CAClC,QAAQ,KAAK,UAAU,qBAAqB;CAC5C,QAAQ,KAAK,WAAW,qBAAqB;CAE7C,MAAM,mBACJ,sBACA;EAAE,KAAK;EAAS,eAAe;EAAM,QAAQ;CAAK,GAClD,uBACA,eACA,OAAO,aAAa;EAClB,MAAM,SAAS,OAAO,UAAmB;GACvC,MAAM,IAAI,MACR,yHACA,EAAE,OAAO,MAAM,CACjB;EACF,CAAC;EACD,MAAM,QAAQ,SAAS,KAAK,MAAM;CACpC,CACF;CAEA,OAAO;AACT;AAMA,eAAe,QACb,SACA,KACA,QACA,QAAQ,MACO;CACf,IAAI;EACF,MAAM,GAAG,SAAS,OAAO,SAAS,GAAG;CACvC,SAAS,OAAO;EACd,IAAI,GAAG,WAAW,MAAM,GAAG;EAC3B,IAAI,CAAC,OAAO,MAAM;EAClB,MAAM,GAAG,SAAS,GAAG,KAAK;GAAE,WAAW;GAAM,OAAO;EAAK,CAAC;EAC1D,MAAM,QAAQ,SAAS,KAAK,QAAQ,KAAK;CAC3C;AACF"}
@@ -1,5 +1,4 @@
1
1
  import { type PackageManagerName } from "./utils/package-manager.js";
2
- export declare function dlxCommand(pm: PackageManagerName): [string, string[]];
3
2
  export interface TransformOptions {
4
3
  hasLocalComponents: boolean;
5
4
  skipInstall?: boolean;
@@ -12,15 +11,7 @@ export type ProjectSource = {
12
11
  kind: "local";
13
12
  rootDir: string;
14
13
  };
15
- export declare function resolvePackageManager(opts: {
16
- useNpm?: boolean;
17
- usePnpm?: boolean;
18
- useYarn?: boolean;
19
- useBun?: boolean;
20
- }): PackageManagerName | undefined;
21
- export declare function resolveGitHubAuthToken(): string | undefined;
22
14
  export declare function resolveLatestReleaseRef(): Promise<string | undefined>;
23
- export declare const DOWNLOAD_TIMEOUT_MS = 30000;
24
15
  export declare function cleanupPendingProjectDownloads(): void;
25
16
  export declare function downloadProject(repoPath: string, destDir: string, ref?: string): Promise<void>;
26
17
  export declare function scaffoldProject(repoPath: string, destDir: string, source: ProjectSource): Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"create-project.d.ts","sourceRoot":"","sources":["../../src/lib/create-project.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,KAAK,kBAAkB,EAAE,mCAAgC;AAOlE,wBAAgB,UAAU,CAAC,EAAE,EAAE,kBAAkB,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAWrE;AAED,MAAM,WAAW,gBAAgB;IAC/B,kBAAkB,EAAE,OAAO,CAAC;IAC5B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,cAAc,EAAE,kBAAkB,CAAC;CACpC;AAED,MAAM,MAAM,aAAa,GACrB;IACE,IAAI,EAAE,QAAQ,CAAC;IACf,GAAG,EAAE,MAAM,GAAG,SAAS,CAAC;CACzB,GACD;IACE,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAaN,wBAAgB,qBAAqB,CAAC,IAAI,EAAE;IAC1C,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB,GAAG,kBAAkB,GAAG,SAAS,CAMjC;AAED,wBAAgB,sBAAsB,IAAI,MAAM,GAAG,SAAS,CAK3D;AAMD,wBAAsB,uBAAuB,IAAI,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAe3E;AAED,eAAO,MAAM,mBAAmB,QAAS,CAAC;AAG1C,wBAAgB,8BAA8B,IAAI,IAAI,CAMrD;AAED,wBAAsB,eAAe,CACnC,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,GAAG,CAAC,EAAE,MAAM,GACX,OAAO,CAAC,IAAI,CAAC,CAgIf;AAYD,wBAAsB,eAAe,CACnC,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,aAAa,GACpB,OAAO,CAAC,IAAI,CAAC,CAyBf;AAED,MAAM,WAAW,eAAe;IAC9B,sBAAsB,CAAC,EAAE;QAAE,YAAY,EAAE,MAAM,CAAA;KAAE,CAAC;IAClD,sBAAsB,CAAC,EAAE,MAAM,CAAC;CACjC;AAED,wBAAsB,gBAAgB,CACpC,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,gBAAgB,GACrB,OAAO,CAAC,eAAe,CAAC,CAoC1B;AA6JD,UAAU,kBAAkB;IAC1B,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AA4CD;;;;;;;GAOG;AACH,wBAAsB,gCAAgC,CACpD,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,IAAI,CAAC,CA8Gf;AAED,wBAAgB,sBAAsB,CAAC,UAAU,EAAE,MAAM,GAAG,kBAAkB,CA8B7E"}
1
+ {"version":3,"file":"create-project.d.ts","sourceRoot":"","sources":["../../src/lib/create-project.ts"],"names":[],"mappings":"AAUA,OAAO,EAAc,KAAK,kBAAkB,EAAE,mCAAgC;AAQ9E,MAAM,WAAW,gBAAgB;IAC/B,kBAAkB,EAAE,OAAO,CAAC;IAC5B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,cAAc,EAAE,kBAAkB,CAAC;CACpC;AAED,MAAM,MAAM,aAAa,GACrB;IACE,IAAI,EAAE,QAAQ,CAAC;IACf,GAAG,EAAE,MAAM,GAAG,SAAS,CAAC;CACzB,GACD;IACE,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAiBN,wBAAsB,uBAAuB,IAAI,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAe3E;AAID,wBAAgB,8BAA8B,IAAI,IAAI,CAMrD;AAED,wBAAsB,eAAe,CACnC,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,GAAG,CAAC,EAAE,MAAM,GACX,OAAO,CAAC,IAAI,CAAC,CAiGf;AAYD,wBAAsB,eAAe,CACnC,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,aAAa,GACpB,OAAO,CAAC,IAAI,CAAC,CAyBf;AAED,MAAM,WAAW,eAAe;IAC9B,sBAAsB,CAAC,EAAE;QAAE,YAAY,EAAE,MAAM,CAAA;KAAE,CAAC;IAClD,sBAAsB,CAAC,EAAE,MAAM,CAAC;CACjC;AAED,wBAAsB,gBAAgB,CACpC,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,gBAAgB,GACrB,OAAO,CAAC,eAAe,CAAC,CAoC1B;AA6JD,UAAU,kBAAkB;IAC1B,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AA4CD;;;;;;;GAOG;AACH,wBAAsB,gCAAgC,CACpD,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,IAAI,CAAC,CA8Gf;AAED,wBAAgB,sBAAsB,CAAC,UAAU,EAAE,MAAM,GAAG,kBAAkB,CA8B7E"}
@@ -1,21 +1,14 @@
1
1
  import { logger } from "./utils/logger.js";
2
2
  import { detectRegistryPlatform, resolveRegistryItemUrl } from "./utils/registry.js";
3
3
  import { SpawnExitError, SpawnSignalError, runSpawn } from "./run-spawn.js";
4
+ import { dlxCommand } from "./utils/package-manager.js";
5
+ import { resolveGitHubAuthToken, withStagedDownload } from "./utils/download.js";
4
6
  import { readProjectFiles } from "./utils/file-scanner.js";
5
7
  import * as fs$1 from "node:fs";
6
8
  import * as path$1 from "node:path";
7
9
  import * as os$1 from "node:os";
8
- import { downloadTemplate } from "giget";
9
10
  import { parse, printParseErrorCode } from "jsonc-parser";
10
11
  //#region src/lib/create-project.ts
11
- function dlxCommand(pm) {
12
- switch (pm) {
13
- case "pnpm": return ["pnpm", ["dlx"]];
14
- case "yarn": return ["yarn", ["dlx"]];
15
- case "bun": return ["bunx", []];
16
- case "npm": return ["npx", ["--yes"]];
17
- }
18
- }
19
12
  const LOCAL_PROJECT_ARTIFACT_DIRS = [
20
13
  "node_modules",
21
14
  ".next",
@@ -23,15 +16,6 @@ const LOCAL_PROJECT_ARTIFACT_DIRS = [
23
16
  "build"
24
17
  ];
25
18
  const LOCAL_PROJECT_ARTIFACT_GLOB_IGNORES = LOCAL_PROJECT_ARTIFACT_DIRS.map((dir) => `**/${dir}/**`);
26
- function resolvePackageManager(opts) {
27
- if (opts.useNpm) return "npm";
28
- if (opts.usePnpm) return "pnpm";
29
- if (opts.useYarn) return "yarn";
30
- if (opts.useBun) return "bun";
31
- }
32
- function resolveGitHubAuthToken() {
33
- return (process.env.GIGET_AUTH ?? process.env.GITHUB_TOKEN ?? process.env.GH_TOKEN)?.trim() || void 0;
34
- }
35
19
  function toBearerAuthHeader(token) {
36
20
  return token.toLowerCase().startsWith("bearer ") ? token : `Bearer ${token}`;
37
21
  }
@@ -45,7 +29,6 @@ async function resolveLatestReleaseRef() {
45
29
  return;
46
30
  }
47
31
  }
48
- const DOWNLOAD_TIMEOUT_MS = 3e4;
49
32
  const pendingDownloadCleanups = /* @__PURE__ */ new Set();
50
33
  function cleanupPendingProjectDownloads() {
51
34
  for (const cleanup of pendingDownloadCleanups) {
@@ -56,12 +39,9 @@ function cleanupPendingProjectDownloads() {
56
39
  }
57
40
  async function downloadProject(repoPath, destDir, ref) {
58
41
  const source = ref ? `gh:assistant-ui/assistant-ui/${repoPath}#${ref}` : `gh:assistant-ui/assistant-ui/${repoPath}`;
59
- const origDebug = process.env.DEBUG;
60
- delete process.env.DEBUG;
61
42
  let destinationCreated = false;
62
43
  let stagingDir;
63
- let downloadPromise;
64
- let downloadFinished = false;
44
+ let downloadStarted = false;
65
45
  let downloadCommitted = false;
66
46
  let cleanupRequested = false;
67
47
  const removeCleanupListeners = () => {
@@ -107,27 +87,20 @@ async function downloadProject(repoPath, destDir, ref) {
107
87
  }
108
88
  process.once("exit", cleanupOnExit);
109
89
  pendingDownloadCleanups.add(cleanupOnExit);
110
- const authToken = resolveGitHubAuthToken();
111
- downloadPromise = downloadTemplate(source, {
112
- dir: stagingDir,
90
+ const currentStagingDir = stagingDir;
91
+ downloadStarted = true;
92
+ await withStagedDownload(source, {
93
+ dir: currentStagingDir,
113
94
  force: true,
114
- silent: true,
115
- ...authToken ? { auth: authToken } : {}
116
- }).finally(() => {
117
- downloadFinished = true;
118
- });
119
- let timer;
120
- const timeoutPromise = new Promise((_, reject) => {
121
- timer = setTimeout(() => reject(/* @__PURE__ */ new Error("Download timed out. This may be due to GitHub rate limiting or a network issue. Try again in a few minutes.")), DOWNLOAD_TIMEOUT_MS);
122
- });
123
- try {
124
- await Promise.race([downloadPromise, timeoutPromise]);
95
+ silent: true
96
+ }, "Download timed out. This may be due to GitHub rate limiting or a network issue. Try again in a few minutes.", removeStagingDir, async (download) => {
97
+ await download;
125
98
  if (cleanupRequested) throw new Error("Download was interrupted.");
126
99
  destinationCreated = !fs$1.existsSync(destDir);
127
100
  await fs$1.promises.mkdir(destDir, { recursive: true });
128
- for (const entry of await fs$1.promises.readdir(stagingDir)) {
101
+ for (const entry of await fs$1.promises.readdir(currentStagingDir)) {
129
102
  const target = path$1.join(destDir, entry);
130
- const sourceEntry = path$1.join(stagingDir, entry);
103
+ const sourceEntry = path$1.join(currentStagingDir, entry);
131
104
  await fs$1.promises.rm(target, {
132
105
  recursive: true,
133
106
  force: true
@@ -147,13 +120,9 @@ async function downloadProject(repoPath, destDir, ref) {
147
120
  }
148
121
  }
149
122
  downloadCommitted = true;
150
- } finally {
151
- clearTimeout(timer);
152
- }
123
+ });
153
124
  } finally {
154
- if (!downloadPromise || downloadFinished) await removeStagingDir();
155
- else downloadPromise.then(removeStagingDir, removeStagingDir);
156
- if (origDebug !== void 0) process.env.DEBUG = origDebug;
125
+ if (!downloadStarted) await removeStagingDir();
157
126
  }
158
127
  }
159
128
  function shouldCopyLocalProjectPath(src, projectDir) {
@@ -455,6 +424,6 @@ async function installShadcnRegistry(projectDir, components, label, pm) {
455
424
  }
456
425
  }
457
426
  //#endregion
458
- export { DOWNLOAD_TIMEOUT_MS, cleanupPendingProjectDownloads, dlxCommand, downloadProject, reconcileAssistantUIImportLayout, resolveGitHubAuthToken, resolveLatestReleaseRef, resolvePackageManager, scaffoldProject, scanRequiredComponents, transformProject };
427
+ export { cleanupPendingProjectDownloads, downloadProject, reconcileAssistantUIImportLayout, resolveLatestReleaseRef, scaffoldProject, scanRequiredComponents, transformProject };
459
428
 
460
429
  //# sourceMappingURL=create-project.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"create-project.js","names":["fs","path","os","parseJsonc"],"sources":["../../src/lib/create-project.ts"],"sourcesContent":["import * as fs from \"node:fs\";\nimport * as os from \"node:os\";\nimport * as path from \"node:path\";\nimport { downloadTemplate } from \"giget\";\nimport {\n parse as parseJsonc,\n printParseErrorCode,\n type ParseError,\n} from \"jsonc-parser\";\nimport { logger } from \"./utils/logger\";\nimport { runSpawn, SpawnExitError, SpawnSignalError } from \"./run-spawn\";\nimport { type PackageManagerName } from \"./utils/package-manager\";\nimport { readProjectFiles } from \"./utils/file-scanner\";\nimport {\n detectRegistryPlatform,\n resolveRegistryItemUrl,\n} from \"./utils/registry\";\n\nexport function dlxCommand(pm: PackageManagerName): [string, string[]] {\n switch (pm) {\n case \"pnpm\":\n return [\"pnpm\", [\"dlx\"]];\n case \"yarn\":\n return [\"yarn\", [\"dlx\"]];\n case \"bun\":\n return [\"bunx\", []];\n case \"npm\":\n return [\"npx\", [\"--yes\"]];\n }\n}\n\nexport interface TransformOptions {\n hasLocalComponents: boolean;\n skipInstall?: boolean;\n packageManager: PackageManagerName;\n}\n\nexport type ProjectSource =\n | {\n kind: \"github\";\n ref: string | undefined;\n }\n | {\n kind: \"local\";\n rootDir: string;\n };\n\nconst LOCAL_PROJECT_ARTIFACT_DIRS: readonly string[] = [\n \"node_modules\",\n \".next\",\n \"dist\",\n \"build\",\n];\n\nconst LOCAL_PROJECT_ARTIFACT_GLOB_IGNORES = LOCAL_PROJECT_ARTIFACT_DIRS.map(\n (dir) => `**/${dir}/**`,\n);\n\nexport function resolvePackageManager(opts: {\n useNpm?: boolean;\n usePnpm?: boolean;\n useYarn?: boolean;\n useBun?: boolean;\n}): PackageManagerName | undefined {\n if (opts.useNpm) return \"npm\";\n if (opts.usePnpm) return \"pnpm\";\n if (opts.useYarn) return \"yarn\";\n if (opts.useBun) return \"bun\";\n return undefined;\n}\n\nexport function resolveGitHubAuthToken(): string | undefined {\n const token =\n process.env.GIGET_AUTH ?? process.env.GITHUB_TOKEN ?? process.env.GH_TOKEN;\n const trimmed = token?.trim();\n return trimmed || undefined;\n}\n\nfunction toBearerAuthHeader(token: string): string {\n return token.toLowerCase().startsWith(\"bearer \") ? token : `Bearer ${token}`;\n}\n\nexport async function resolveLatestReleaseRef(): Promise<string | undefined> {\n try {\n const authToken = resolveGitHubAuthToken();\n const res = await fetch(\n \"https://api.github.com/repos/assistant-ui/assistant-ui/releases/latest\",\n authToken\n ? { headers: { Authorization: toBearerAuthHeader(authToken) } }\n : undefined,\n );\n if (!res.ok) return undefined;\n const release = (await res.json()) as { tag_name: string };\n return release.tag_name || undefined;\n } catch {\n return undefined;\n }\n}\n\nexport const DOWNLOAD_TIMEOUT_MS = 30_000;\nconst pendingDownloadCleanups = new Set<() => void>();\n\nexport function cleanupPendingProjectDownloads(): void {\n for (const cleanup of pendingDownloadCleanups) {\n pendingDownloadCleanups.delete(cleanup);\n process.removeListener(\"exit\", cleanup);\n cleanup();\n }\n}\n\nexport async function downloadProject(\n repoPath: string,\n destDir: string,\n ref?: string,\n): Promise<void> {\n const source = ref\n ? `gh:assistant-ui/assistant-ui/${repoPath}#${ref}`\n : `gh:assistant-ui/assistant-ui/${repoPath}`;\n\n // Suppress giget's debug output. The `debug` package (used by the upgrade\n // command) sets process.env.DEBUG at module-load time, and giget logs to\n // console.debug whenever that env var is truthy — even for unrelated\n // namespaces. Temporarily unsetting it targets the root cause.\n const origDebug = process.env.DEBUG;\n delete process.env.DEBUG;\n let destinationCreated = false;\n let stagingDir: string | undefined;\n let downloadPromise: Promise<unknown> | undefined;\n let downloadFinished = false;\n let downloadCommitted = false;\n let cleanupRequested = false;\n const removeCleanupListeners = () => {\n process.removeListener(\"exit\", cleanupOnExit);\n pendingDownloadCleanups.delete(cleanupOnExit);\n };\n const attemptSyncCleanup = (cleanup: () => void) => {\n try {\n cleanup();\n } catch {\n return;\n }\n };\n const cleanupOnExit = () => {\n cleanupRequested = true;\n const currentStagingDir = stagingDir;\n if (currentStagingDir) {\n attemptSyncCleanup(() => {\n fs.rmSync(currentStagingDir, { recursive: true, force: true });\n });\n }\n if (destinationCreated && !downloadCommitted) {\n attemptSyncCleanup(() => {\n fs.rmdirSync(destDir);\n });\n }\n };\n const removeStagingDir = async () => {\n if (stagingDir) {\n await fs.promises\n .rm(stagingDir, { recursive: true, force: true })\n .catch(() => undefined);\n }\n removeCleanupListeners();\n if (destinationCreated && !downloadCommitted) {\n await fs.promises.rmdir(destDir).catch(() => undefined);\n }\n };\n try {\n await fs.promises.mkdir(path.dirname(destDir), { recursive: true });\n try {\n stagingDir = await fs.promises.mkdtemp(\n path.join(path.dirname(destDir), \".assistant-ui-download-\"),\n );\n } catch (error) {\n const code = (error as NodeJS.ErrnoException).code;\n if (code !== \"EACCES\" && code !== \"EPERM\" && code !== \"EROFS\") {\n throw error;\n }\n stagingDir = await fs.promises.mkdtemp(\n path.join(os.tmpdir(), \".assistant-ui-download-\"),\n );\n }\n process.once(\"exit\", cleanupOnExit);\n pendingDownloadCleanups.add(cleanupOnExit);\n\n const authToken = resolveGitHubAuthToken();\n downloadPromise = downloadTemplate(source, {\n dir: stagingDir,\n force: true,\n silent: true,\n ...(authToken ? { auth: authToken } : {}),\n }).finally(() => {\n downloadFinished = true;\n });\n\n let timer: ReturnType<typeof setTimeout>;\n const timeoutPromise = new Promise<never>((_, reject) => {\n timer = setTimeout(\n () =>\n reject(\n new Error(\n \"Download timed out. This may be due to GitHub rate limiting or a network issue. Try again in a few minutes.\",\n ),\n ),\n DOWNLOAD_TIMEOUT_MS,\n );\n });\n\n try {\n await Promise.race([downloadPromise, timeoutPromise]);\n if (cleanupRequested) throw new Error(\"Download was interrupted.\");\n destinationCreated = !fs.existsSync(destDir);\n await fs.promises.mkdir(destDir, { recursive: true });\n for (const entry of await fs.promises.readdir(stagingDir)) {\n const target = path.join(destDir, entry);\n const sourceEntry = path.join(stagingDir, entry);\n await fs.promises.rm(target, { recursive: true, force: true });\n try {\n await fs.promises.rename(sourceEntry, target);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== \"EXDEV\") throw error;\n await fs.promises.cp(sourceEntry, target, {\n recursive: true,\n force: true,\n });\n await fs.promises.rm(sourceEntry, { recursive: true, force: true });\n }\n }\n downloadCommitted = true;\n } finally {\n clearTimeout(timer!);\n }\n } finally {\n if (!downloadPromise || downloadFinished) {\n await removeStagingDir();\n } else {\n void downloadPromise.then(removeStagingDir, removeStagingDir);\n }\n if (origDebug !== undefined) {\n process.env.DEBUG = origDebug;\n }\n }\n}\n\nfunction shouldCopyLocalProjectPath(src: string, projectDir: string): boolean {\n const relative = path.relative(projectDir, src);\n if (!relative) return true;\n\n const segments = relative.split(path.sep);\n return !segments.some((segment) =>\n LOCAL_PROJECT_ARTIFACT_DIRS.includes(segment),\n );\n}\n\nexport async function scaffoldProject(\n repoPath: string,\n destDir: string,\n source: ProjectSource,\n): Promise<void> {\n if (source.kind === \"github\") {\n await downloadProject(repoPath, destDir, source.ref);\n return;\n }\n\n const localProjectDir = path.resolve(source.rootDir, repoPath);\n try {\n fs.cpSync(localProjectDir, destDir, {\n recursive: true,\n force: true,\n filter: (src) => shouldCopyLocalProjectPath(src, localProjectDir),\n });\n } catch (error) {\n const code =\n error instanceof Error\n ? (error as NodeJS.ErrnoException).code\n : undefined;\n if (code === \"ENOENT\") {\n throw new Error(\n `Local project source does not exist: ${localProjectDir}`,\n );\n }\n throw error;\n }\n}\n\nexport interface TransformResult {\n registryInstallFailure?: { retryCommand: string };\n registryInstallCommand?: string;\n}\n\nexport async function transformProject(\n projectDir: string,\n opts: TransformOptions,\n): Promise<TransformResult> {\n logger.step(\"Transforming package.json...\");\n transformPackageJson(projectDir);\n\n logger.step(\"Transforming project files...\");\n transformTsConfig(projectDir);\n transformCssFiles(projectDir);\n\n const components = opts.hasLocalComponents\n ? undefined\n : resolveRegistryComponents(projectDir, scanRequiredComponents(projectDir));\n\n const pm = opts.packageManager;\n if (opts.skipInstall) {\n if (!components) return {};\n const [cmd, dlxArgs] = dlxCommand(pm);\n return {\n registryInstallCommand: `${cmd} ${[...dlxArgs, \"shadcn@latest\", \"add\", ...components].join(\" \")}`,\n };\n }\n\n logger.step(\"Installing dependencies...\");\n await installDependencies(projectDir, pm);\n\n if (components) {\n logger.step(`Installing components: ${components.join(\", \")}...`);\n const failure = await installShadcnRegistry(\n projectDir,\n components,\n \"components\",\n pm,\n );\n if (failure) return { registryInstallFailure: failure };\n await reconcileAssistantUIImportLayout(projectDir);\n }\n return {};\n}\n\nfunction resolveRegistryComponents(\n projectDir: string,\n { assistantUI, shadcnUI }: RequiredComponents,\n): string[] {\n if (detectRegistryPlatform(projectDir) === \"native\") {\n return [\"utils\", ...shadcnUI, ...assistantUI].map((component) =>\n resolveRegistryItemUrl(component, undefined, \"native\"),\n );\n }\n return [\n \"@assistant-ui/utils\",\n ...shadcnUI,\n ...assistantUI.map((component) => `@assistant-ui/${component}`),\n ];\n}\n\nfunction transformPackageJson(projectDir: string): void {\n const pkgPath = path.join(projectDir, \"package.json\");\n const pkg = JSON.parse(fs.readFileSync(pkgPath, \"utf-8\"));\n\n // Remove @assistant-ui/ui dependency\n if (pkg.dependencies?.[\"@assistant-ui/ui\"]) {\n delete pkg.dependencies[\"@assistant-ui/ui\"];\n }\n\n // Transform workspace dependencies to latest\n for (const depType of [\"dependencies\", \"devDependencies\"] as const) {\n const deps = pkg[depType];\n if (!deps) continue;\n\n for (const [name, version] of Object.entries(deps)) {\n if (String(version).includes(\"workspace:\")) {\n deps[name] = \"latest\";\n }\n }\n }\n\n // Remove devDependencies that are workspace-only\n if (pkg.devDependencies?.[\"@assistant-ui/x-buildutils\"]) {\n delete pkg.devDependencies[\"@assistant-ui/x-buildutils\"];\n }\n\n // Update package name to be unique\n const dirName = path.basename(projectDir);\n pkg.name = dirName;\n\n fs.writeFileSync(pkgPath, `${JSON.stringify(pkg, null, 2)}\\n`);\n}\n\nfunction parseTsConfig(content: string): any {\n const errors: ParseError[] = [];\n const tsconfig = parseJsonc(content, errors, { allowTrailingComma: true });\n const error = errors[0];\n if (error) {\n throw new SyntaxError(\n `Invalid tsconfig.json: ${printParseErrorCode(error.error)} at offset ${error.offset}`,\n );\n }\n return tsconfig;\n}\n\nfunction transformTsConfig(projectDir: string): void {\n const tsconfigPath = path.join(projectDir, \"tsconfig.json\");\n\n if (!fs.existsSync(tsconfigPath)) {\n return;\n }\n\n const content = fs.readFileSync(tsconfigPath, \"utf-8\");\n const tsconfig = parseTsConfig(content);\n\n // Remove workspace paths\n if (tsconfig.compilerOptions?.paths) {\n const workspaceKeys = new Set([\n \"@/components/assistant-ui/*\",\n \"@/components/icons/*\",\n \"@/components/ui/*\",\n \"@/components/ui/radix/*\",\n \"@/hooks/*\",\n \"@/lib/utils\",\n \"@assistant-ui/ui/*\",\n ]);\n for (const [key, targets] of Object.entries(\n tsconfig.compilerOptions.paths as Record<string, unknown>,\n )) {\n const targetsWorkspace =\n Array.isArray(targets) &&\n targets.some(\n (target) =>\n typeof target === \"string\" &&\n (target.includes(\"packages/ui/\") || target.startsWith(\"../\")),\n );\n if (workspaceKeys.has(key) || targetsWorkspace) {\n delete tsconfig.compilerOptions.paths[key];\n }\n }\n\n if (Object.keys(tsconfig.compilerOptions.paths).length === 0) {\n delete tsconfig.compilerOptions.paths;\n }\n }\n\n // If extends uses @assistant-ui/x-buildutils, replace with inline config\n if (tsconfig.extends?.includes(\"@assistant-ui/x-buildutils\")) {\n const isNext = tsconfig.extends.includes(\"ts/next\");\n delete tsconfig.extends;\n\n const inlinedCompilerOptions = {\n target: \"ESNext\",\n lib: [\"dom\", \"dom.iterable\", \"ES2023\"],\n skipLibCheck: true,\n strict: true,\n noEmit: true,\n esModuleInterop: true,\n module: \"ESNext\",\n moduleResolution: \"bundler\",\n resolveJsonModule: true,\n isolatedModules: true,\n jsx: \"react-jsx\",\n ...(isNext ? { plugins: [{ name: \"next\" }] } : {}),\n };\n\n tsconfig.compilerOptions = {\n ...inlinedCompilerOptions,\n ...tsconfig.compilerOptions,\n paths: {\n \"@/*\": [\"./*\"],\n ...(tsconfig.compilerOptions?.paths || {}),\n },\n };\n }\n\n fs.writeFileSync(tsconfigPath, `${JSON.stringify(tsconfig, null, 2)}\\n`);\n}\n\nfunction transformCssFiles(projectDir: string): void {\n for (const { fullPath, content } of readProjectFiles(\"**/*.css\", {\n cwd: projectDir,\n ignore: LOCAL_PROJECT_ARTIFACT_GLOB_IGNORES,\n })) {\n try {\n const newContent = content.replace(\n /@source\\s+[\"'][^\"']*packages\\/ui\\/src[^\"']*[\"'];\\s*\\n?/g,\n \"\",\n );\n\n if (newContent !== content) {\n fs.writeFileSync(fullPath, newContent);\n }\n } catch {\n continue;\n }\n }\n}\n\ninterface RequiredComponents {\n assistantUI: string[];\n shadcnUI: string[];\n}\n\nfunction stripImportExtension(component: string): string {\n return component.replace(/\\.[cm]?[tj]sx?$/, \"\");\n}\n\nconst ASSISTANT_UI_OWNED_UI = new Set([\n \"accordion\",\n \"badge\",\n \"diff-viewer\",\n \"direction\",\n \"dot-matrix\",\n \"number-roll\",\n \"select\",\n \"tabs\",\n]);\n\nconst BARE_ELEMENT_ITEMS = new Set([\n \"file\",\n \"generative-ui\",\n \"heat-graph\",\n \"image\",\n \"logos\",\n \"markdown-text\",\n \"syntax-highlighter\",\n \"tooltip-icon-button\",\n]);\n\nfunction toAssistantUIItem(specifier: string): string | null {\n let name = stripImportExtension(specifier);\n const inElements = name.startsWith(\"elements/\");\n if (inElements) {\n name = name.slice(\"elements/\".length);\n } else if (name.includes(\"/\")) {\n return null;\n }\n if (name.endsWith(\".aui\")) {\n return name.slice(0, -\".aui\".length);\n }\n return inElements && !BARE_ELEMENT_ITEMS.has(name)\n ? `elements-${name}`\n : name;\n}\n\n/**\n * Example snapshots are downloaded at a release tag while the shadcn registry\n * is live, so a snapshot may import components at the legacy flat path\n * (`@/components/assistant-ui/<name>`) after the registry has moved the file\n * to `components/assistant-ui/elements/<name>.aui.tsx`. Resolve each legacy\n * specifier against the files the registry actually installed and rewrite it\n * only when the legacy path is absent and the elements layout has it.\n */\nexport async function reconcileAssistantUIImportLayout(\n projectDir: string,\n): Promise<void> {\n const componentRoots = [\"components\", \"src/components\"]\n .map((dir) => path.join(projectDir, dir, \"assistant-ui\"))\n .filter((dir) => fs.existsSync(dir));\n if (componentRoots.length === 0) return;\n\n const resolvesAtLegacyPath = (name: string) =>\n componentRoots.some((root) =>\n [\".tsx\", \".ts\", \"/index.tsx\", \"/index.ts\"].some((suffix) =>\n fs.existsSync(path.join(root, `${name}${suffix}`)),\n ),\n );\n\n // Index the installed tree by import name so the rewrite follows whatever\n // layout the registry delivered — some items install as\n // elements/<name>.aui.tsx, others as elements/<name>.tsx, and a future\n // layout move should not require new knowledge here.\n const installedByName = new Map<string, string>();\n for (const root of componentRoots) {\n for (const { file } of readProjectFiles(\"**/*.{ts,tsx}\", { cwd: root })) {\n const normalized = file.split(path.sep).join(\"/\");\n if (!normalized.includes(\"/\")) continue;\n const specifier = normalized.replace(/\\.[cm]?[tj]sx?$/, \"\");\n const name = path.posix.basename(specifier).replace(/\\.aui$/, \"\");\n // A flat legacy import maps to the registry's `<name>` item, which is\n // the `.aui` file; a colliding bare file with the same basename belongs\n // to the distinct `elements-<name>` item, so the `.aui` variant wins.\n const existing = installedByName.get(name);\n if (\n existing === undefined ||\n (!existing.endsWith(\".aui\") && specifier.endsWith(\".aui\"))\n ) {\n installedByName.set(name, specifier);\n }\n }\n }\n if (installedByName.size === 0) return;\n\n const { default: jscodeshift } = await import(\"jscodeshift\");\n const parsers = {\n ts: jscodeshift.withParser(\"ts\"),\n tsx: jscodeshift.withParser(\"tsx\"),\n };\n\n for (const { fullPath, content } of readProjectFiles(\"**/*.{ts,tsx}\", {\n cwd: projectDir,\n ignore: LOCAL_PROJECT_ARTIFACT_GLOB_IGNORES,\n })) {\n if (!content.includes(\"@/components/assistant-ui/\")) continue;\n\n const replacements: Array<{ start: number; end: number; value: string }> =\n [];\n const collectReplacement = (source: {\n value?: unknown;\n start?: number | null;\n end?: number | null;\n }) => {\n if (\n typeof source.value !== \"string\" ||\n source.start == null ||\n source.end == null\n ) {\n return;\n }\n\n const prefix = \"@/components/assistant-ui/\";\n if (!source.value.startsWith(prefix)) return;\n const specifier = source.value.slice(prefix.length);\n if (specifier.includes(\"/\")) return;\n\n const name = stripImportExtension(specifier);\n const installed = installedByName.get(name);\n if (resolvesAtLegacyPath(name) || installed === undefined) return;\n\n const raw = content.slice(source.start, source.end);\n const quote = raw[0];\n if ((quote !== '\"' && quote !== \"'\") || raw.at(-1) !== quote) return;\n replacements.push({\n start: source.start,\n end: source.end,\n value: `${quote}@/components/assistant-ui/${installed}${quote}`,\n });\n };\n\n const j = fullPath.endsWith(\".tsx\") ? parsers.tsx : parsers.ts;\n let root;\n try {\n root = j(content);\n } catch {\n continue;\n }\n root\n .find(j.ImportDeclaration)\n .forEach(({ node }) => collectReplacement(node.source));\n root\n .find(j.ExportNamedDeclaration)\n .forEach(({ node }) => node.source && collectReplacement(node.source));\n root\n .find(j.ExportAllDeclaration)\n .forEach(({ node }) => collectReplacement(node.source));\n\n let next = content;\n for (const replacement of replacements.sort((a, b) => b.start - a.start)) {\n next =\n next.slice(0, replacement.start) +\n replacement.value +\n next.slice(replacement.end);\n }\n if (next !== content) fs.writeFileSync(fullPath, next);\n }\n}\n\nexport function scanRequiredComponents(projectDir: string): RequiredComponents {\n const assistantUIComponents = new Set<string>();\n const shadcnUIComponents = new Set<string>();\n\n for (const { content } of readProjectFiles(\"**/*.{ts,tsx}\", {\n cwd: projectDir,\n ignore: LOCAL_PROJECT_ARTIFACT_GLOB_IGNORES,\n })) {\n const assistantUIRegex =\n /from\\s+[\"']@\\/components\\/assistant-ui\\/([^\"']+)[\"']/g;\n for (const match of content.matchAll(assistantUIRegex)) {\n const item = toAssistantUIItem(match[1]!);\n if (item) assistantUIComponents.add(item);\n }\n\n const uiRegex = /from\\s+[\"']@\\/components\\/ui\\/([^\"']+)[\"']/g;\n for (const match of content.matchAll(uiRegex)) {\n const name = stripImportExtension(match[1]!);\n if (ASSISTANT_UI_OWNED_UI.has(name)) {\n assistantUIComponents.add(name);\n } else {\n shadcnUIComponents.add(name);\n }\n }\n }\n\n return {\n assistantUI: Array.from(assistantUIComponents),\n shadcnUI: Array.from(shadcnUIComponents),\n };\n}\n\nasync function installDependencies(\n projectDir: string,\n pm: PackageManagerName,\n): Promise<void> {\n const args = pm === \"yarn\" ? [] : [\"install\"];\n try {\n await runSpawn(pm, args, projectDir);\n } catch (error) {\n if (error instanceof SpawnSignalError) {\n throw error;\n }\n if (error instanceof SpawnExitError) {\n throw new Error(`${pm} install exited with code ${error.code}`);\n }\n const message = error instanceof Error ? error.message : String(error);\n throw new Error(`Failed to install dependencies: ${message}`);\n }\n}\n\nasync function installShadcnRegistry(\n projectDir: string,\n components: string[],\n label: string,\n pm: PackageManagerName,\n): Promise<{ retryCommand: string } | undefined> {\n const [cmd, dlxArgs] = dlxCommand(pm);\n // For npm, dlxArgs may already include `--yes` for npx auto-install.\n // The trailing `--yes` is for shadcn's own confirmation prompt.\n const retryArgs = [...dlxArgs, \"shadcn@latest\", \"add\", ...components];\n const addArgs = [...retryArgs, \"--yes\"];\n\n try {\n await runSpawn(cmd, addArgs, projectDir);\n return undefined;\n } catch (error) {\n if (error instanceof SpawnSignalError) {\n throw error;\n }\n if (error instanceof SpawnExitError) {\n logger.warn(`shadcn exited with code ${error.code}.`);\n return { retryCommand: `${cmd} ${retryArgs.join(\" \")}` };\n }\n\n const message = error instanceof Error ? error.message : String(error);\n throw new Error(`Failed to install ${label}: ${message}`);\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"create-project.js","names":["fs","path","os","parseJsonc"],"sources":["../../src/lib/create-project.ts"],"sourcesContent":["import * as fs from \"node:fs\";\nimport * as os from \"node:os\";\nimport * as path from \"node:path\";\nimport {\n parse as parseJsonc,\n printParseErrorCode,\n type ParseError,\n} from \"jsonc-parser\";\nimport { logger } from \"./utils/logger\";\nimport { runSpawn, SpawnExitError, SpawnSignalError } from \"./run-spawn\";\nimport { dlxCommand, type PackageManagerName } from \"./utils/package-manager\";\nimport { resolveGitHubAuthToken, withStagedDownload } from \"./utils/download\";\nimport { readProjectFiles } from \"./utils/file-scanner\";\nimport {\n detectRegistryPlatform,\n resolveRegistryItemUrl,\n} from \"./utils/registry\";\n\nexport interface TransformOptions {\n hasLocalComponents: boolean;\n skipInstall?: boolean;\n packageManager: PackageManagerName;\n}\n\nexport type ProjectSource =\n | {\n kind: \"github\";\n ref: string | undefined;\n }\n | {\n kind: \"local\";\n rootDir: string;\n };\n\nconst LOCAL_PROJECT_ARTIFACT_DIRS: readonly string[] = [\n \"node_modules\",\n \".next\",\n \"dist\",\n \"build\",\n];\n\nconst LOCAL_PROJECT_ARTIFACT_GLOB_IGNORES = LOCAL_PROJECT_ARTIFACT_DIRS.map(\n (dir) => `**/${dir}/**`,\n);\n\nfunction toBearerAuthHeader(token: string): string {\n return token.toLowerCase().startsWith(\"bearer \") ? token : `Bearer ${token}`;\n}\n\nexport async function resolveLatestReleaseRef(): Promise<string | undefined> {\n try {\n const authToken = resolveGitHubAuthToken();\n const res = await fetch(\n \"https://api.github.com/repos/assistant-ui/assistant-ui/releases/latest\",\n authToken\n ? { headers: { Authorization: toBearerAuthHeader(authToken) } }\n : undefined,\n );\n if (!res.ok) return undefined;\n const release = (await res.json()) as { tag_name: string };\n return release.tag_name || undefined;\n } catch {\n return undefined;\n }\n}\n\nconst pendingDownloadCleanups = new Set<() => void>();\n\nexport function cleanupPendingProjectDownloads(): void {\n for (const cleanup of pendingDownloadCleanups) {\n pendingDownloadCleanups.delete(cleanup);\n process.removeListener(\"exit\", cleanup);\n cleanup();\n }\n}\n\nexport async function downloadProject(\n repoPath: string,\n destDir: string,\n ref?: string,\n): Promise<void> {\n const source = ref\n ? `gh:assistant-ui/assistant-ui/${repoPath}#${ref}`\n : `gh:assistant-ui/assistant-ui/${repoPath}`;\n\n let destinationCreated = false;\n let stagingDir: string | undefined;\n let downloadStarted = false;\n let downloadCommitted = false;\n let cleanupRequested = false;\n const removeCleanupListeners = () => {\n process.removeListener(\"exit\", cleanupOnExit);\n pendingDownloadCleanups.delete(cleanupOnExit);\n };\n const attemptSyncCleanup = (cleanup: () => void) => {\n try {\n cleanup();\n } catch {\n return;\n }\n };\n const cleanupOnExit = () => {\n cleanupRequested = true;\n const currentStagingDir = stagingDir;\n if (currentStagingDir) {\n attemptSyncCleanup(() => {\n fs.rmSync(currentStagingDir, { recursive: true, force: true });\n });\n }\n if (destinationCreated && !downloadCommitted) {\n attemptSyncCleanup(() => {\n fs.rmdirSync(destDir);\n });\n }\n };\n const removeStagingDir = async () => {\n if (stagingDir) {\n await fs.promises\n .rm(stagingDir, { recursive: true, force: true })\n .catch(() => undefined);\n }\n removeCleanupListeners();\n if (destinationCreated && !downloadCommitted) {\n await fs.promises.rmdir(destDir).catch(() => undefined);\n }\n };\n try {\n await fs.promises.mkdir(path.dirname(destDir), { recursive: true });\n try {\n stagingDir = await fs.promises.mkdtemp(\n path.join(path.dirname(destDir), \".assistant-ui-download-\"),\n );\n } catch (error) {\n const code = (error as NodeJS.ErrnoException).code;\n if (code !== \"EACCES\" && code !== \"EPERM\" && code !== \"EROFS\") {\n throw error;\n }\n stagingDir = await fs.promises.mkdtemp(\n path.join(os.tmpdir(), \".assistant-ui-download-\"),\n );\n }\n process.once(\"exit\", cleanupOnExit);\n pendingDownloadCleanups.add(cleanupOnExit);\n\n const currentStagingDir = stagingDir;\n downloadStarted = true;\n await withStagedDownload(\n source,\n { dir: currentStagingDir, force: true, silent: true },\n \"Download timed out. This may be due to GitHub rate limiting or a network issue. Try again in a few minutes.\",\n removeStagingDir,\n async (download) => {\n await download;\n if (cleanupRequested) throw new Error(\"Download was interrupted.\");\n destinationCreated = !fs.existsSync(destDir);\n await fs.promises.mkdir(destDir, { recursive: true });\n for (const entry of await fs.promises.readdir(currentStagingDir)) {\n const target = path.join(destDir, entry);\n const sourceEntry = path.join(currentStagingDir, entry);\n await fs.promises.rm(target, { recursive: true, force: true });\n try {\n await fs.promises.rename(sourceEntry, target);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== \"EXDEV\") throw error;\n await fs.promises.cp(sourceEntry, target, {\n recursive: true,\n force: true,\n });\n await fs.promises.rm(sourceEntry, { recursive: true, force: true });\n }\n }\n downloadCommitted = true;\n },\n );\n } finally {\n if (!downloadStarted) await removeStagingDir();\n }\n}\n\nfunction shouldCopyLocalProjectPath(src: string, projectDir: string): boolean {\n const relative = path.relative(projectDir, src);\n if (!relative) return true;\n\n const segments = relative.split(path.sep);\n return !segments.some((segment) =>\n LOCAL_PROJECT_ARTIFACT_DIRS.includes(segment),\n );\n}\n\nexport async function scaffoldProject(\n repoPath: string,\n destDir: string,\n source: ProjectSource,\n): Promise<void> {\n if (source.kind === \"github\") {\n await downloadProject(repoPath, destDir, source.ref);\n return;\n }\n\n const localProjectDir = path.resolve(source.rootDir, repoPath);\n try {\n fs.cpSync(localProjectDir, destDir, {\n recursive: true,\n force: true,\n filter: (src) => shouldCopyLocalProjectPath(src, localProjectDir),\n });\n } catch (error) {\n const code =\n error instanceof Error\n ? (error as NodeJS.ErrnoException).code\n : undefined;\n if (code === \"ENOENT\") {\n throw new Error(\n `Local project source does not exist: ${localProjectDir}`,\n );\n }\n throw error;\n }\n}\n\nexport interface TransformResult {\n registryInstallFailure?: { retryCommand: string };\n registryInstallCommand?: string;\n}\n\nexport async function transformProject(\n projectDir: string,\n opts: TransformOptions,\n): Promise<TransformResult> {\n logger.step(\"Transforming package.json...\");\n transformPackageJson(projectDir);\n\n logger.step(\"Transforming project files...\");\n transformTsConfig(projectDir);\n transformCssFiles(projectDir);\n\n const components = opts.hasLocalComponents\n ? undefined\n : resolveRegistryComponents(projectDir, scanRequiredComponents(projectDir));\n\n const pm = opts.packageManager;\n if (opts.skipInstall) {\n if (!components) return {};\n const [cmd, dlxArgs] = dlxCommand(pm);\n return {\n registryInstallCommand: `${cmd} ${[...dlxArgs, \"shadcn@latest\", \"add\", ...components].join(\" \")}`,\n };\n }\n\n logger.step(\"Installing dependencies...\");\n await installDependencies(projectDir, pm);\n\n if (components) {\n logger.step(`Installing components: ${components.join(\", \")}...`);\n const failure = await installShadcnRegistry(\n projectDir,\n components,\n \"components\",\n pm,\n );\n if (failure) return { registryInstallFailure: failure };\n await reconcileAssistantUIImportLayout(projectDir);\n }\n return {};\n}\n\nfunction resolveRegistryComponents(\n projectDir: string,\n { assistantUI, shadcnUI }: RequiredComponents,\n): string[] {\n if (detectRegistryPlatform(projectDir) === \"native\") {\n return [\"utils\", ...shadcnUI, ...assistantUI].map((component) =>\n resolveRegistryItemUrl(component, undefined, \"native\"),\n );\n }\n return [\n \"@assistant-ui/utils\",\n ...shadcnUI,\n ...assistantUI.map((component) => `@assistant-ui/${component}`),\n ];\n}\n\nfunction transformPackageJson(projectDir: string): void {\n const pkgPath = path.join(projectDir, \"package.json\");\n const pkg = JSON.parse(fs.readFileSync(pkgPath, \"utf-8\"));\n\n // Remove @assistant-ui/ui dependency\n if (pkg.dependencies?.[\"@assistant-ui/ui\"]) {\n delete pkg.dependencies[\"@assistant-ui/ui\"];\n }\n\n // Transform workspace dependencies to latest\n for (const depType of [\"dependencies\", \"devDependencies\"] as const) {\n const deps = pkg[depType];\n if (!deps) continue;\n\n for (const [name, version] of Object.entries(deps)) {\n if (String(version).includes(\"workspace:\")) {\n deps[name] = \"latest\";\n }\n }\n }\n\n // Remove devDependencies that are workspace-only\n if (pkg.devDependencies?.[\"@assistant-ui/x-buildutils\"]) {\n delete pkg.devDependencies[\"@assistant-ui/x-buildutils\"];\n }\n\n // Update package name to be unique\n const dirName = path.basename(projectDir);\n pkg.name = dirName;\n\n fs.writeFileSync(pkgPath, `${JSON.stringify(pkg, null, 2)}\\n`);\n}\n\nfunction parseTsConfig(content: string): any {\n const errors: ParseError[] = [];\n const tsconfig = parseJsonc(content, errors, { allowTrailingComma: true });\n const error = errors[0];\n if (error) {\n throw new SyntaxError(\n `Invalid tsconfig.json: ${printParseErrorCode(error.error)} at offset ${error.offset}`,\n );\n }\n return tsconfig;\n}\n\nfunction transformTsConfig(projectDir: string): void {\n const tsconfigPath = path.join(projectDir, \"tsconfig.json\");\n\n if (!fs.existsSync(tsconfigPath)) {\n return;\n }\n\n const content = fs.readFileSync(tsconfigPath, \"utf-8\");\n const tsconfig = parseTsConfig(content);\n\n // Remove workspace paths\n if (tsconfig.compilerOptions?.paths) {\n const workspaceKeys = new Set([\n \"@/components/assistant-ui/*\",\n \"@/components/icons/*\",\n \"@/components/ui/*\",\n \"@/components/ui/radix/*\",\n \"@/hooks/*\",\n \"@/lib/utils\",\n \"@assistant-ui/ui/*\",\n ]);\n for (const [key, targets] of Object.entries(\n tsconfig.compilerOptions.paths as Record<string, unknown>,\n )) {\n const targetsWorkspace =\n Array.isArray(targets) &&\n targets.some(\n (target) =>\n typeof target === \"string\" &&\n (target.includes(\"packages/ui/\") || target.startsWith(\"../\")),\n );\n if (workspaceKeys.has(key) || targetsWorkspace) {\n delete tsconfig.compilerOptions.paths[key];\n }\n }\n\n if (Object.keys(tsconfig.compilerOptions.paths).length === 0) {\n delete tsconfig.compilerOptions.paths;\n }\n }\n\n // If extends uses @assistant-ui/x-buildutils, replace with inline config\n if (tsconfig.extends?.includes(\"@assistant-ui/x-buildutils\")) {\n const isNext = tsconfig.extends.includes(\"ts/next\");\n delete tsconfig.extends;\n\n const inlinedCompilerOptions = {\n target: \"ESNext\",\n lib: [\"dom\", \"dom.iterable\", \"ES2023\"],\n skipLibCheck: true,\n strict: true,\n noEmit: true,\n esModuleInterop: true,\n module: \"ESNext\",\n moduleResolution: \"bundler\",\n resolveJsonModule: true,\n isolatedModules: true,\n jsx: \"react-jsx\",\n ...(isNext ? { plugins: [{ name: \"next\" }] } : {}),\n };\n\n tsconfig.compilerOptions = {\n ...inlinedCompilerOptions,\n ...tsconfig.compilerOptions,\n paths: {\n \"@/*\": [\"./*\"],\n ...(tsconfig.compilerOptions?.paths || {}),\n },\n };\n }\n\n fs.writeFileSync(tsconfigPath, `${JSON.stringify(tsconfig, null, 2)}\\n`);\n}\n\nfunction transformCssFiles(projectDir: string): void {\n for (const { fullPath, content } of readProjectFiles(\"**/*.css\", {\n cwd: projectDir,\n ignore: LOCAL_PROJECT_ARTIFACT_GLOB_IGNORES,\n })) {\n try {\n const newContent = content.replace(\n /@source\\s+[\"'][^\"']*packages\\/ui\\/src[^\"']*[\"'];\\s*\\n?/g,\n \"\",\n );\n\n if (newContent !== content) {\n fs.writeFileSync(fullPath, newContent);\n }\n } catch {\n continue;\n }\n }\n}\n\ninterface RequiredComponents {\n assistantUI: string[];\n shadcnUI: string[];\n}\n\nfunction stripImportExtension(component: string): string {\n return component.replace(/\\.[cm]?[tj]sx?$/, \"\");\n}\n\nconst ASSISTANT_UI_OWNED_UI = new Set([\n \"accordion\",\n \"badge\",\n \"diff-viewer\",\n \"direction\",\n \"dot-matrix\",\n \"number-roll\",\n \"select\",\n \"tabs\",\n]);\n\nconst BARE_ELEMENT_ITEMS = new Set([\n \"file\",\n \"generative-ui\",\n \"heat-graph\",\n \"image\",\n \"logos\",\n \"markdown-text\",\n \"syntax-highlighter\",\n \"tooltip-icon-button\",\n]);\n\nfunction toAssistantUIItem(specifier: string): string | null {\n let name = stripImportExtension(specifier);\n const inElements = name.startsWith(\"elements/\");\n if (inElements) {\n name = name.slice(\"elements/\".length);\n } else if (name.includes(\"/\")) {\n return null;\n }\n if (name.endsWith(\".aui\")) {\n return name.slice(0, -\".aui\".length);\n }\n return inElements && !BARE_ELEMENT_ITEMS.has(name)\n ? `elements-${name}`\n : name;\n}\n\n/**\n * Example snapshots are downloaded at a release tag while the shadcn registry\n * is live, so a snapshot may import components at the legacy flat path\n * (`@/components/assistant-ui/<name>`) after the registry has moved the file\n * to `components/assistant-ui/elements/<name>.aui.tsx`. Resolve each legacy\n * specifier against the files the registry actually installed and rewrite it\n * only when the legacy path is absent and the elements layout has it.\n */\nexport async function reconcileAssistantUIImportLayout(\n projectDir: string,\n): Promise<void> {\n const componentRoots = [\"components\", \"src/components\"]\n .map((dir) => path.join(projectDir, dir, \"assistant-ui\"))\n .filter((dir) => fs.existsSync(dir));\n if (componentRoots.length === 0) return;\n\n const resolvesAtLegacyPath = (name: string) =>\n componentRoots.some((root) =>\n [\".tsx\", \".ts\", \"/index.tsx\", \"/index.ts\"].some((suffix) =>\n fs.existsSync(path.join(root, `${name}${suffix}`)),\n ),\n );\n\n // Index the installed tree by import name so the rewrite follows whatever\n // layout the registry delivered — some items install as\n // elements/<name>.aui.tsx, others as elements/<name>.tsx, and a future\n // layout move should not require new knowledge here.\n const installedByName = new Map<string, string>();\n for (const root of componentRoots) {\n for (const { file } of readProjectFiles(\"**/*.{ts,tsx}\", { cwd: root })) {\n const normalized = file.split(path.sep).join(\"/\");\n if (!normalized.includes(\"/\")) continue;\n const specifier = normalized.replace(/\\.[cm]?[tj]sx?$/, \"\");\n const name = path.posix.basename(specifier).replace(/\\.aui$/, \"\");\n // A flat legacy import maps to the registry's `<name>` item, which is\n // the `.aui` file; a colliding bare file with the same basename belongs\n // to the distinct `elements-<name>` item, so the `.aui` variant wins.\n const existing = installedByName.get(name);\n if (\n existing === undefined ||\n (!existing.endsWith(\".aui\") && specifier.endsWith(\".aui\"))\n ) {\n installedByName.set(name, specifier);\n }\n }\n }\n if (installedByName.size === 0) return;\n\n const { default: jscodeshift } = await import(\"jscodeshift\");\n const parsers = {\n ts: jscodeshift.withParser(\"ts\"),\n tsx: jscodeshift.withParser(\"tsx\"),\n };\n\n for (const { fullPath, content } of readProjectFiles(\"**/*.{ts,tsx}\", {\n cwd: projectDir,\n ignore: LOCAL_PROJECT_ARTIFACT_GLOB_IGNORES,\n })) {\n if (!content.includes(\"@/components/assistant-ui/\")) continue;\n\n const replacements: Array<{ start: number; end: number; value: string }> =\n [];\n const collectReplacement = (source: {\n value?: unknown;\n start?: number | null;\n end?: number | null;\n }) => {\n if (\n typeof source.value !== \"string\" ||\n source.start == null ||\n source.end == null\n ) {\n return;\n }\n\n const prefix = \"@/components/assistant-ui/\";\n if (!source.value.startsWith(prefix)) return;\n const specifier = source.value.slice(prefix.length);\n if (specifier.includes(\"/\")) return;\n\n const name = stripImportExtension(specifier);\n const installed = installedByName.get(name);\n if (resolvesAtLegacyPath(name) || installed === undefined) return;\n\n const raw = content.slice(source.start, source.end);\n const quote = raw[0];\n if ((quote !== '\"' && quote !== \"'\") || raw.at(-1) !== quote) return;\n replacements.push({\n start: source.start,\n end: source.end,\n value: `${quote}@/components/assistant-ui/${installed}${quote}`,\n });\n };\n\n const j = fullPath.endsWith(\".tsx\") ? parsers.tsx : parsers.ts;\n let root;\n try {\n root = j(content);\n } catch {\n continue;\n }\n root\n .find(j.ImportDeclaration)\n .forEach(({ node }) => collectReplacement(node.source));\n root\n .find(j.ExportNamedDeclaration)\n .forEach(({ node }) => node.source && collectReplacement(node.source));\n root\n .find(j.ExportAllDeclaration)\n .forEach(({ node }) => collectReplacement(node.source));\n\n let next = content;\n for (const replacement of replacements.sort((a, b) => b.start - a.start)) {\n next =\n next.slice(0, replacement.start) +\n replacement.value +\n next.slice(replacement.end);\n }\n if (next !== content) fs.writeFileSync(fullPath, next);\n }\n}\n\nexport function scanRequiredComponents(projectDir: string): RequiredComponents {\n const assistantUIComponents = new Set<string>();\n const shadcnUIComponents = new Set<string>();\n\n for (const { content } of readProjectFiles(\"**/*.{ts,tsx}\", {\n cwd: projectDir,\n ignore: LOCAL_PROJECT_ARTIFACT_GLOB_IGNORES,\n })) {\n const assistantUIRegex =\n /from\\s+[\"']@\\/components\\/assistant-ui\\/([^\"']+)[\"']/g;\n for (const match of content.matchAll(assistantUIRegex)) {\n const item = toAssistantUIItem(match[1]!);\n if (item) assistantUIComponents.add(item);\n }\n\n const uiRegex = /from\\s+[\"']@\\/components\\/ui\\/([^\"']+)[\"']/g;\n for (const match of content.matchAll(uiRegex)) {\n const name = stripImportExtension(match[1]!);\n if (ASSISTANT_UI_OWNED_UI.has(name)) {\n assistantUIComponents.add(name);\n } else {\n shadcnUIComponents.add(name);\n }\n }\n }\n\n return {\n assistantUI: Array.from(assistantUIComponents),\n shadcnUI: Array.from(shadcnUIComponents),\n };\n}\n\nasync function installDependencies(\n projectDir: string,\n pm: PackageManagerName,\n): Promise<void> {\n const args = pm === \"yarn\" ? [] : [\"install\"];\n try {\n await runSpawn(pm, args, projectDir);\n } catch (error) {\n if (error instanceof SpawnSignalError) {\n throw error;\n }\n if (error instanceof SpawnExitError) {\n throw new Error(`${pm} install exited with code ${error.code}`);\n }\n const message = error instanceof Error ? error.message : String(error);\n throw new Error(`Failed to install dependencies: ${message}`);\n }\n}\n\nasync function installShadcnRegistry(\n projectDir: string,\n components: string[],\n label: string,\n pm: PackageManagerName,\n): Promise<{ retryCommand: string } | undefined> {\n const [cmd, dlxArgs] = dlxCommand(pm);\n // For npm, dlxArgs may already include `--yes` for npx auto-install.\n // The trailing `--yes` is for shadcn's own confirmation prompt.\n const retryArgs = [...dlxArgs, \"shadcn@latest\", \"add\", ...components];\n const addArgs = [...retryArgs, \"--yes\"];\n\n try {\n await runSpawn(cmd, addArgs, projectDir);\n return undefined;\n } catch (error) {\n if (error instanceof SpawnSignalError) {\n throw error;\n }\n if (error instanceof SpawnExitError) {\n logger.warn(`shadcn exited with code ${error.code}.`);\n return { retryCommand: `${cmd} ${retryArgs.join(\" \")}` };\n }\n\n const message = error instanceof Error ? error.message : String(error);\n throw new Error(`Failed to install ${label}: ${message}`);\n }\n}\n"],"mappings":"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"}
@@ -4,10 +4,6 @@ import type { TransformOptions } from "./transform-options.js";
4
4
  * Directory scans only include files containing "assistant-ui".
5
5
  */
6
6
  export declare function getRelevantFiles(source: string): string[];
7
- /**
8
- * Counts the number of files that need to be processed
9
- */
10
- export declare function countFilesToProcess(source: string): number;
11
7
  export type TransformErrors = {
12
8
  transform: string;
13
9
  filename: string;
@@ -1 +1 @@
1
- {"version":3,"file":"transform.d.ts","sourceRoot":"","sources":["../../src/lib/transform.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,+BAA4B;AAW5D;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CA4BzD;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAE1D;AAqCD,MAAM,MAAM,eAAe,GAAG;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;CACjB,EAAE,CAAC;AAEJ,wBAAsB,SAAS,CAC7B,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,EACd,gBAAgB,EAAE,gBAAgB,EAClC,OAAO,GAAE;IACP,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,CAAC,EAAE,CAAC,cAAc,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9C,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;CACJ,GACtB,OAAO,CAAC,eAAe,CAAC,CAwC1B"}
1
+ {"version":3,"file":"transform.d.ts","sourceRoot":"","sources":["../../src/lib/transform.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,+BAA4B;AAW5D;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAqBzD;AAqCD,MAAM,MAAM,eAAe,GAAG;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;CACjB,EAAE,CAAC;AAEJ,wBAAsB,SAAS,CAC7B,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,EACd,gBAAgB,EAAE,gBAAgB,EAClC,OAAO,GAAE;IACP,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,CAAC,EAAE,CAAC,cAAc,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9C,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;CACJ,GACtB,OAAO,CAAC,eAAe,CAAC,CAwC1B"}
@@ -1,7 +1,7 @@
1
1
  import { SpawnExitError, SpawnSignalError, runSpawnCapture } from "./run-spawn.js";
2
+ import { readProjectFiles } from "./utils/file-scanner.js";
2
3
  import * as fs$1 from "node:fs";
3
4
  import path from "node:path";
4
- import { sync } from "glob";
5
5
  import { fileURLToPath } from "node:url";
6
6
  import debug from "debug";
7
7
  //#region src/lib/transform.ts
@@ -15,7 +15,9 @@ const __dirname = path.dirname(__filename);
15
15
  function getRelevantFiles(source) {
16
16
  const target = path.resolve(source);
17
17
  if (fs$1.statSync(target).isFile()) return /\.(js|jsx|ts|tsx)$/.test(target) ? [target] : [];
18
- return sync("**/*.{js,jsx,ts,tsx}", {
18
+ const pattern = "**/*.{js,jsx,ts,tsx}";
19
+ const relevantFiles = [];
20
+ for (const { fullPath, content } of readProjectFiles(pattern, {
19
21
  cwd: target,
20
22
  ignore: [
21
23
  "**/node_modules/**",
@@ -24,19 +26,8 @@ function getRelevantFiles(source) {
24
26
  "**/*.min.js",
25
27
  "**/*.bundle.js"
26
28
  ]
27
- }).map((file) => path.join(target, file)).filter((file) => {
28
- try {
29
- return fs$1.readFileSync(file, "utf8").includes("assistant-ui");
30
- } catch {
31
- return false;
32
- }
33
- });
34
- }
35
- /**
36
- * Counts the number of files that need to be processed
37
- */
38
- function countFilesToProcess(source) {
39
- return getRelevantFiles(source).length;
29
+ })) if (content.includes("assistant-ui")) relevantFiles.push(fullPath);
30
+ return relevantFiles;
40
31
  }
41
32
  function buildCommand(codemodPath, targetFiles, options) {
42
33
  const command = [
@@ -80,6 +71,6 @@ async function transform(codemod, source, transformOptions, options = { logStatu
80
71
  return [];
81
72
  }
82
73
  //#endregion
83
- export { countFilesToProcess, getRelevantFiles, transform };
74
+ export { getRelevantFiles, transform };
84
75
 
85
76
  //# sourceMappingURL=transform.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"transform.js","names":["fs","globSync"],"sources":["../../src/lib/transform.ts"],"sourcesContent":["import debug from \"debug\";\nimport path from \"node:path\";\nimport type { TransformOptions } from \"./transform-options\";\nimport { fileURLToPath } from \"node:url\";\nimport * as fs from \"node:fs\";\nimport { sync as globSync } from \"glob\";\nimport { runSpawnCapture, SpawnExitError, SpawnSignalError } from \"./run-spawn\";\n\nconst log = debug(\"codemod:transform\");\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = path.dirname(__filename);\n\n/**\n * Gets relevant source files from an explicit file or directory target.\n * Directory scans only include files containing \"assistant-ui\".\n */\nexport function getRelevantFiles(source: string): string[] {\n const target = path.resolve(source);\n if (fs.statSync(target).isFile()) {\n return /\\.(js|jsx|ts|tsx)$/.test(target) ? [target] : [];\n }\n\n const pattern = \"**/*.{js,jsx,ts,tsx}\";\n const files = globSync(pattern, {\n cwd: target,\n ignore: [\n \"**/node_modules/**\",\n \"**/dist/**\",\n \"**/build/**\",\n \"**/*.min.js\",\n \"**/*.bundle.js\",\n ],\n }).map((file) => path.join(target, file));\n\n const relevantFiles = files.filter((file) => {\n try {\n const content = fs.readFileSync(file, \"utf8\");\n return content.includes(\"assistant-ui\");\n } catch {\n return false;\n }\n });\n\n return relevantFiles;\n}\n\n/**\n * Counts the number of files that need to be processed\n */\nexport function countFilesToProcess(source: string): number {\n return getRelevantFiles(source).length;\n}\n\nfunction buildCommand(\n codemodPath: string,\n targetFiles: string[],\n options: TransformOptions,\n): string[] {\n const command = [\n \"npx\",\n \"jscodeshift\",\n \"-t\",\n codemodPath,\n ...targetFiles,\n \"--parser\",\n \"tsx\",\n \"--fail-on-error\",\n ];\n\n if (options.dry) {\n command.push(\"--dry\");\n }\n\n if (options.print) {\n command.push(\"--print\");\n }\n\n if (options.verbose) {\n command.push(\"--verbose\");\n }\n\n if (options.jscodeshift) {\n command.push(options.jscodeshift);\n }\n\n return command;\n}\n\nexport type TransformErrors = {\n transform: string;\n filename: string;\n summary: string;\n}[];\n\nexport async function transform(\n codemod: string,\n source: string,\n transformOptions: TransformOptions,\n options: {\n logStatus: boolean;\n onProgress?: (processedFiles: number) => void;\n relevantFiles?: string[];\n } = { logStatus: true },\n): Promise<TransformErrors> {\n if (options.logStatus) {\n log(`Applying codemod '${codemod}': ${source}`);\n }\n const codemodPath = path.resolve(__dirname, `../codemods/${codemod}.js`);\n\n // Use pre-computed relevant files if provided, otherwise get them\n const targetFiles = options.relevantFiles || getRelevantFiles(source);\n\n if (targetFiles.length === 0) {\n log(`No relevant files found for codemod '${codemod}'`);\n return [];\n }\n\n log(`Found ${targetFiles.length} relevant files for codemod '${codemod}'`);\n\n const command = buildCommand(codemodPath, targetFiles, transformOptions);\n\n const result = await runSpawnCapture(command[0]!, command.slice(1));\n if (result.signal !== null) {\n throw new SpawnSignalError(result.signal, false);\n }\n if (result.code !== 0) {\n const failure = new SpawnExitError(\n result.code || 1,\n result.stderr,\n result.stdout,\n );\n failure.message = `Codemod '${codemod}' failed\\n${failure.message}`;\n throw failure;\n }\n\n const { stdout } = result;\n\n if (options.onProgress) {\n const processedFiles = (stdout.match(/Processing file/g) || []).length;\n options.onProgress(processedFiles);\n }\n\n return [];\n}\n"],"mappings":";;;;;;;AAQA,MAAM,MAAM,MAAM,mBAAmB;AAErC,MAAM,aAAa,cAAc,YAAY,GAAG;AAChD,MAAM,YAAY,KAAK,QAAQ,UAAU;;;;;AAMzC,SAAgB,iBAAiB,QAA0B;CACzD,MAAM,SAAS,KAAK,QAAQ,MAAM;CAClC,IAAIA,KAAG,SAAS,MAAM,CAAC,CAAC,OAAO,GAC7B,OAAO,qBAAqB,KAAK,MAAM,IAAI,CAAC,MAAM,IAAI,CAAC;CAwBzD,OApBcC,KAAS,wBAAS;EAC9B,KAAK;EACL,QAAQ;GACN;GACA;GACA;GACA;GACA;EACF;CACF,CAAC,CAAC,CAAC,KAAK,SAAS,KAAK,KAAK,QAAQ,IAAI,CAEb,CAAC,CAAC,QAAQ,SAAS;EAC3C,IAAI;GAEF,OADgBD,KAAG,aAAa,MAAM,MACzB,CAAC,CAAC,SAAS,cAAc;EACxC,QAAQ;GACN,OAAO;EACT;CACF,CAEmB;AACrB;;;;AAKA,SAAgB,oBAAoB,QAAwB;CAC1D,OAAO,iBAAiB,MAAM,CAAC,CAAC;AAClC;AAEA,SAAS,aACP,aACA,aACA,SACU;CACV,MAAM,UAAU;EACd;EACA;EACA;EACA;EACA,GAAG;EACH;EACA;EACA;CACF;CAEA,IAAI,QAAQ,KACV,QAAQ,KAAK,OAAO;CAGtB,IAAI,QAAQ,OACV,QAAQ,KAAK,SAAS;CAGxB,IAAI,QAAQ,SACV,QAAQ,KAAK,WAAW;CAG1B,IAAI,QAAQ,aACV,QAAQ,KAAK,QAAQ,WAAW;CAGlC,OAAO;AACT;AAQA,eAAsB,UACpB,SACA,QACA,kBACA,UAII,EAAE,WAAW,KAAK,GACI;CAC1B,IAAI,QAAQ,WACV,IAAI,qBAAqB,QAAQ,KAAK,QAAQ;CAEhD,MAAM,cAAc,KAAK,QAAQ,WAAW,eAAe,QAAQ,IAAI;CAGvE,MAAM,cAAc,QAAQ,iBAAiB,iBAAiB,MAAM;CAEpE,IAAI,YAAY,WAAW,GAAG;EAC5B,IAAI,wCAAwC,QAAQ,EAAE;EACtD,OAAO,CAAC;CACV;CAEA,IAAI,SAAS,YAAY,OAAO,+BAA+B,QAAQ,EAAE;CAEzE,MAAM,UAAU,aAAa,aAAa,aAAa,gBAAgB;CAEvE,MAAM,SAAS,MAAM,gBAAgB,QAAQ,IAAK,QAAQ,MAAM,CAAC,CAAC;CAClE,IAAI,OAAO,WAAW,MACpB,MAAM,IAAI,iBAAiB,OAAO,QAAQ,KAAK;CAEjD,IAAI,OAAO,SAAS,GAAG;EACrB,MAAM,UAAU,IAAI,eAClB,OAAO,QAAQ,GACf,OAAO,QACP,OAAO,MACT;EACA,QAAQ,UAAU,YAAY,QAAQ,YAAY,QAAQ;EAC1D,MAAM;CACR;CAEA,MAAM,EAAE,WAAW;CAEnB,IAAI,QAAQ,YAAY;EACtB,MAAM,kBAAkB,OAAO,MAAM,kBAAkB,KAAK,CAAC,EAAA,CAAG;EAChE,QAAQ,WAAW,cAAc;CACnC;CAEA,OAAO,CAAC;AACV"}
1
+ {"version":3,"file":"transform.js","names":["fs"],"sources":["../../src/lib/transform.ts"],"sourcesContent":["import debug from \"debug\";\nimport path from \"node:path\";\nimport type { TransformOptions } from \"./transform-options\";\nimport { fileURLToPath } from \"node:url\";\nimport * as fs from \"node:fs\";\nimport { runSpawnCapture, SpawnExitError, SpawnSignalError } from \"./run-spawn\";\nimport { readProjectFiles } from \"./utils/file-scanner\";\n\nconst log = debug(\"codemod:transform\");\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = path.dirname(__filename);\n\n/**\n * Gets relevant source files from an explicit file or directory target.\n * Directory scans only include files containing \"assistant-ui\".\n */\nexport function getRelevantFiles(source: string): string[] {\n const target = path.resolve(source);\n if (fs.statSync(target).isFile()) {\n return /\\.(js|jsx|ts|tsx)$/.test(target) ? [target] : [];\n }\n\n const pattern = \"**/*.{js,jsx,ts,tsx}\";\n const relevantFiles: string[] = [];\n for (const { fullPath, content } of readProjectFiles(pattern, {\n cwd: target,\n ignore: [\n \"**/node_modules/**\",\n \"**/dist/**\",\n \"**/build/**\",\n \"**/*.min.js\",\n \"**/*.bundle.js\",\n ],\n })) {\n if (content.includes(\"assistant-ui\")) relevantFiles.push(fullPath);\n }\n return relevantFiles;\n}\n\nfunction buildCommand(\n codemodPath: string,\n targetFiles: string[],\n options: TransformOptions,\n): string[] {\n const command = [\n \"npx\",\n \"jscodeshift\",\n \"-t\",\n codemodPath,\n ...targetFiles,\n \"--parser\",\n \"tsx\",\n \"--fail-on-error\",\n ];\n\n if (options.dry) {\n command.push(\"--dry\");\n }\n\n if (options.print) {\n command.push(\"--print\");\n }\n\n if (options.verbose) {\n command.push(\"--verbose\");\n }\n\n if (options.jscodeshift) {\n command.push(options.jscodeshift);\n }\n\n return command;\n}\n\nexport type TransformErrors = {\n transform: string;\n filename: string;\n summary: string;\n}[];\n\nexport async function transform(\n codemod: string,\n source: string,\n transformOptions: TransformOptions,\n options: {\n logStatus: boolean;\n onProgress?: (processedFiles: number) => void;\n relevantFiles?: string[];\n } = { logStatus: true },\n): Promise<TransformErrors> {\n if (options.logStatus) {\n log(`Applying codemod '${codemod}': ${source}`);\n }\n const codemodPath = path.resolve(__dirname, `../codemods/${codemod}.js`);\n\n // Use pre-computed relevant files if provided, otherwise get them\n const targetFiles = options.relevantFiles || getRelevantFiles(source);\n\n if (targetFiles.length === 0) {\n log(`No relevant files found for codemod '${codemod}'`);\n return [];\n }\n\n log(`Found ${targetFiles.length} relevant files for codemod '${codemod}'`);\n\n const command = buildCommand(codemodPath, targetFiles, transformOptions);\n\n const result = await runSpawnCapture(command[0]!, command.slice(1));\n if (result.signal !== null) {\n throw new SpawnSignalError(result.signal, false);\n }\n if (result.code !== 0) {\n const failure = new SpawnExitError(\n result.code || 1,\n result.stderr,\n result.stdout,\n );\n failure.message = `Codemod '${codemod}' failed\\n${failure.message}`;\n throw failure;\n }\n\n const { stdout } = result;\n\n if (options.onProgress) {\n const processedFiles = (stdout.match(/Processing file/g) || []).length;\n options.onProgress(processedFiles);\n }\n\n return [];\n}\n"],"mappings":";;;;;;;AAQA,MAAM,MAAM,MAAM,mBAAmB;AAErC,MAAM,aAAa,cAAc,YAAY,GAAG;AAChD,MAAM,YAAY,KAAK,QAAQ,UAAU;;;;;AAMzC,SAAgB,iBAAiB,QAA0B;CACzD,MAAM,SAAS,KAAK,QAAQ,MAAM;CAClC,IAAIA,KAAG,SAAS,MAAM,CAAC,CAAC,OAAO,GAC7B,OAAO,qBAAqB,KAAK,MAAM,IAAI,CAAC,MAAM,IAAI,CAAC;CAGzD,MAAM,UAAU;CAChB,MAAM,gBAA0B,CAAC;CACjC,KAAK,MAAM,EAAE,UAAU,aAAa,iBAAiB,SAAS;EAC5D,KAAK;EACL,QAAQ;GACN;GACA;GACA;GACA;GACA;EACF;CACF,CAAC,GACC,IAAI,QAAQ,SAAS,cAAc,GAAG,cAAc,KAAK,QAAQ;CAEnE,OAAO;AACT;AAEA,SAAS,aACP,aACA,aACA,SACU;CACV,MAAM,UAAU;EACd;EACA;EACA;EACA;EACA,GAAG;EACH;EACA;EACA;CACF;CAEA,IAAI,QAAQ,KACV,QAAQ,KAAK,OAAO;CAGtB,IAAI,QAAQ,OACV,QAAQ,KAAK,SAAS;CAGxB,IAAI,QAAQ,SACV,QAAQ,KAAK,WAAW;CAG1B,IAAI,QAAQ,aACV,QAAQ,KAAK,QAAQ,WAAW;CAGlC,OAAO;AACT;AAQA,eAAsB,UACpB,SACA,QACA,kBACA,UAII,EAAE,WAAW,KAAK,GACI;CAC1B,IAAI,QAAQ,WACV,IAAI,qBAAqB,QAAQ,KAAK,QAAQ;CAEhD,MAAM,cAAc,KAAK,QAAQ,WAAW,eAAe,QAAQ,IAAI;CAGvE,MAAM,cAAc,QAAQ,iBAAiB,iBAAiB,MAAM;CAEpE,IAAI,YAAY,WAAW,GAAG;EAC5B,IAAI,wCAAwC,QAAQ,EAAE;EACtD,OAAO,CAAC;CACV;CAEA,IAAI,SAAS,YAAY,OAAO,+BAA+B,QAAQ,EAAE;CAEzE,MAAM,UAAU,aAAa,aAAa,aAAa,gBAAgB;CAEvE,MAAM,SAAS,MAAM,gBAAgB,QAAQ,IAAK,QAAQ,MAAM,CAAC,CAAC;CAClE,IAAI,OAAO,WAAW,MACpB,MAAM,IAAI,iBAAiB,OAAO,QAAQ,KAAK;CAEjD,IAAI,OAAO,SAAS,GAAG;EACrB,MAAM,UAAU,IAAI,eAClB,OAAO,QAAQ,GACf,OAAO,QACP,OAAO,MACT;EACA,QAAQ,UAAU,YAAY,QAAQ,YAAY,QAAQ;EAC1D,MAAM;CACR;CAEA,MAAM,EAAE,WAAW;CAEnB,IAAI,QAAQ,YAAY;EACtB,MAAM,kBAAkB,OAAO,MAAM,kBAAkB,KAAK,CAAC,EAAA,CAAG;EAChE,QAAQ,WAAW,cAAc;CACnC;CAEA,OAAO,CAAC;AACV"}
@@ -0,0 +1,5 @@
1
+ import { downloadTemplate } from "giget";
2
+ export declare const DOWNLOAD_TIMEOUT_MS = 30000;
3
+ export declare function resolveGitHubAuthToken(): string | undefined;
4
+ export declare function withStagedDownload<T>(source: string, options: NonNullable<Parameters<typeof downloadTemplate>[1]>, timeoutMessage: string, cleanup: () => void | Promise<void>, consumeDownload: (download: Promise<unknown>) => Promise<T>): Promise<T>;
5
+ //# sourceMappingURL=download.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"download.d.ts","sourceRoot":"","sources":["../../../src/lib/utils/download.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,OAAO,CAAC;AAEzC,eAAO,MAAM,mBAAmB,QAAS,CAAC;AAE1C,wBAAgB,sBAAsB,IAAI,MAAM,GAAG,SAAS,CAK3D;AAED,wBAAsB,kBAAkB,CAAC,CAAC,EACxC,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,WAAW,CAAC,UAAU,CAAC,OAAO,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAAC,EAC5D,cAAc,EAAE,MAAM,EACtB,OAAO,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,EACnC,eAAe,EAAE,CAAC,QAAQ,EAAE,OAAO,CAAC,OAAO,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,GAC1D,OAAO,CAAC,CAAC,CAAC,CAuCZ"}