assistant-ui 0.0.98 → 0.0.100
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/codemods/v0-11/content-part-to-message-part.js.map +1 -1
- package/dist/codemods/v0-12/assistant-api-to-aui.js.map +1 -1
- package/dist/codemods/v0-12/event-names-to-camelcase.js.map +1 -1
- package/dist/codemods/v0-12/primitive-if-to-aui-if.js.map +1 -1
- package/dist/codemods/v0-8/ui-package-split.js.map +1 -1
- package/dist/codemods/v0-9/edge-package-split.js.map +1 -1
- package/dist/commands/add.js.map +1 -1
- package/dist/commands/agent.js.map +1 -1
- package/dist/commands/create.js.map +1 -1
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/info.js.map +1 -1
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/mcp.js.map +1 -1
- package/dist/commands/update.js.map +1 -1
- package/dist/commands/upgrade.js.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/lib/create-project.js.map +1 -1
- package/dist/lib/transform.js.map +1 -1
- package/dist/lib/utils/file-scanner.js.map +1 -1
- package/dist/lib/utils/package-installer.js.map +1 -1
- package/package.json +7 -7
- package/plugin/skills/assistant-ui/SKILL.md +29 -16
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"content-part-to-message-part.js","names":[],"sources":["../../../src/codemods/v0-11/content-part-to-message-part.ts"],"sourcesContent":["import { createTransformer } from \"../utils/createTransformer\";\n\n// Map of old ContentPart names to new MessagePart names\nconst typeRenamingMap: Record<string, string> = {\n // Core types\n TextContentPart: \"TextMessagePart\",\n ReasoningContentPart: \"ReasoningMessagePart\",\n SourceContentPart: \"SourceMessagePart\",\n ImageContentPart: \"ImageMessagePart\",\n FileContentPart: \"FileMessagePart\",\n Unstable_AudioContentPart: \"Unstable_AudioMessagePart\",\n ToolCallContentPart: \"ToolCallMessagePart\",\n\n // Status types\n ContentPartStatus: \"MessagePartStatus\",\n ToolCallContentPartStatus: \"ToolCallMessagePartStatus\",\n\n // Thread message parts\n ThreadUserContentPart: \"ThreadUserMessagePart\",\n ThreadAssistantContentPart: \"ThreadAssistantMessagePart\",\n\n // Runtime and state types\n ContentPartRuntime: \"MessagePartRuntime\",\n ContentPartState: \"MessagePartState\",\n\n // Component types\n EmptyContentPartComponent: \"EmptyMessagePartComponent\",\n TextContentPartComponent: \"TextMessagePartComponent\",\n ReasoningContentPartComponent: \"ReasoningMessagePartComponent\",\n SourceContentPartComponent: \"SourceMessagePartComponent\",\n ImageContentPartComponent: \"ImageMessagePartComponent\",\n FileContentPartComponent: \"FileMessagePartComponent\",\n Unstable_AudioContentPartComponent: \"Unstable_AudioMessagePartComponent\",\n ToolCallContentPartComponent: \"ToolCallMessagePartComponent\",\n\n // Props types\n EmptyContentPartProps: \"EmptyMessagePartProps\",\n TextContentPartProps: \"TextMessagePartProps\",\n ReasoningContentPartProps: \"ReasoningMessagePartProps\",\n SourceContentPartProps: \"SourceMessagePartProps\",\n ImageContentPartProps: \"ImageMessagePartProps\",\n FileContentPartProps: \"FileMessagePartProps\",\n Unstable_AudioContentPartProps: \"Unstable_AudioMessagePartProps\",\n ToolCallContentPartProps: \"ToolCallMessagePartProps\",\n\n // Provider types\n TextContentPartProvider: \"TextMessagePartProvider\",\n TextContentPartProviderProps: \"TextMessagePartProviderProps\",\n ContentPartRuntimeProvider: \"MessagePartRuntimeProvider\",\n\n // Context types\n ContentPartContext: \"MessagePartContext\",\n ContentPartContextValue: \"MessagePartContextValue\",\n\n // Hook names\n useContentPart: \"useMessagePart\",\n useContentPartRuntime: \"useMessagePartRuntime\",\n useContentPartText: \"useMessagePartText\",\n useContentPartReasoning: \"useMessagePartReasoning\",\n useContentPartSource: \"useMessagePartSource\",\n useContentPartFile: \"useMessagePartFile\",\n useContentPartImage: \"useMessagePartImage\",\n useTextContentPart: \"useTextMessagePart\",\n\n // Primitive names\n ContentPartPrimitive: \"MessagePartPrimitive\",\n ContentPartPrimitiveText: \"MessagePartPrimitiveText\",\n ContentPartPrimitiveImage: \"MessagePartPrimitiveImage\",\n ContentPartPrimitiveInProgress: \"MessagePartPrimitiveInProgress\",\n};\n\nconst migrateContentPartToMessagePart = createTransformer(\n ({ j, root, markAsChanged }) => {\n // 1. Update imports\n root.find(j.ImportDeclaration).forEach((path: any) => {\n const source = path.value.source.value;\n\n // Only process imports from @assistant-ui packages\n if (typeof source === \"string\" && source.startsWith(\"@assistant-ui/\")) {\n path.value.specifiers?.forEach((specifier: any) => {\n if (j.ImportSpecifier.check(specifier)) {\n const oldName = specifier.imported.name as string;\n if (typeRenamingMap[oldName]) {\n specifier.imported.name = typeRenamingMap[oldName];\n if (specifier.local && specifier.local.name === oldName) {\n specifier.local.name = typeRenamingMap[oldName];\n }\n markAsChanged();\n }\n }\n });\n }\n });\n\n // 2. Update MessagePrimitive.Content to MessagePrimitive.Parts\n root.find(j.MemberExpression).forEach((path: any) => {\n if (\n path.value.object &&\n path.value.object.name === \"MessagePrimitive\" &&\n path.value.property &&\n path.value.property.name === \"Content\"\n ) {\n path.value.property.name = \"Parts\";\n markAsChanged();\n }\n });\n\n // 3. Update JSX member expressions (e.g., MessagePrimitive.Content in JSX)\n root.find(j.JSXMemberExpression).forEach((path: any) => {\n if (\n path.value.object &&\n path.value.object.name === \"MessagePrimitive\" &&\n path.value.property &&\n path.value.property.name === \"Content\"\n ) {\n path.value.property.name = \"Parts\";\n markAsChanged();\n }\n });\n\n // 4. Update all identifiers for types, hooks, and primitives\n Object.entries(typeRenamingMap).forEach(([oldName, newName]) => {\n // Update type references\n root.find(j.TSTypeReference).forEach((path: any) => {\n if (path.value.typeName && path.value.typeName.name === oldName) {\n path.value.typeName.name = newName;\n markAsChanged();\n }\n });\n\n // Update identifier references\n root.find(j.Identifier).forEach((path: any) => {\n if (path.value.name === oldName) {\n // Skip if this is part of an import declaration (already handled above)\n if (j.ImportSpecifier.check(path.parent.value)) {\n return;\n }\n\n // Skip if this is a property key in an object\n if (\n j.Property.check(path.parent.value) &&\n path.parent.value.key === path.value\n ) {\n return;\n }\n\n // Skip if this is a property in a member expression\n if (\n j.MemberExpression.check(path.parent.value) &&\n path.parent.value.property === path.value\n ) {\n return;\n }\n\n path.value.name = newName;\n markAsChanged();\n }\n });\n\n // Update JSX element names\n root.find(j.JSXIdentifier).forEach((path: any) => {\n if (path.value.name === oldName) {\n path.value.name = newName;\n markAsChanged();\n }\n });\n });\n },\n);\n\nexport default migrateContentPartToMessagePart;\n"],"mappings":";;AAGA,MAAM,kBAA0C;CAE9C,iBAAiB;CACjB,sBAAsB;CACtB,mBAAmB;CACnB,kBAAkB;CAClB,iBAAiB;CACjB,2BAA2B;CAC3B,qBAAqB;CAGrB,mBAAmB;CACnB,2BAA2B;CAG3B,uBAAuB;CACvB,4BAA4B;CAG5B,oBAAoB;CACpB,kBAAkB;CAGlB,2BAA2B;CAC3B,0BAA0B;CAC1B,+BAA+B;CAC/B,4BAA4B;CAC5B,2BAA2B;CAC3B,0BAA0B;CAC1B,oCAAoC;CACpC,8BAA8B;CAG9B,uBAAuB;CACvB,sBAAsB;CACtB,2BAA2B;CAC3B,wBAAwB;CACxB,uBAAuB;CACvB,sBAAsB;CACtB,gCAAgC;CAChC,0BAA0B;CAG1B,yBAAyB;CACzB,8BAA8B;CAC9B,4BAA4B;CAG5B,oBAAoB;CACpB,yBAAyB;CAGzB,gBAAgB;CAChB,uBAAuB;CACvB,oBAAoB;CACpB,yBAAyB;CACzB,sBAAsB;CACtB,oBAAoB;CACpB,qBAAqB;CACrB,oBAAoB;CAGpB,sBAAsB;CACtB,0BAA0B;CAC1B,2BAA2B;CAC3B,gCAAgC;AAClC;AAEA,MAAM,kCAAkC,mBACrC,EAAE,GAAG,MAAM,oBAAoB;CAE9B,KAAK,KAAK,EAAE,iBAAiB,
|
|
1
|
+
{"version":3,"file":"content-part-to-message-part.js","names":[],"sources":["../../../src/codemods/v0-11/content-part-to-message-part.ts"],"sourcesContent":["import { createTransformer } from \"../utils/createTransformer\";\n\n// Map of old ContentPart names to new MessagePart names\nconst typeRenamingMap: Record<string, string> = {\n // Core types\n TextContentPart: \"TextMessagePart\",\n ReasoningContentPart: \"ReasoningMessagePart\",\n SourceContentPart: \"SourceMessagePart\",\n ImageContentPart: \"ImageMessagePart\",\n FileContentPart: \"FileMessagePart\",\n Unstable_AudioContentPart: \"Unstable_AudioMessagePart\",\n ToolCallContentPart: \"ToolCallMessagePart\",\n\n // Status types\n ContentPartStatus: \"MessagePartStatus\",\n ToolCallContentPartStatus: \"ToolCallMessagePartStatus\",\n\n // Thread message parts\n ThreadUserContentPart: \"ThreadUserMessagePart\",\n ThreadAssistantContentPart: \"ThreadAssistantMessagePart\",\n\n // Runtime and state types\n ContentPartRuntime: \"MessagePartRuntime\",\n ContentPartState: \"MessagePartState\",\n\n // Component types\n EmptyContentPartComponent: \"EmptyMessagePartComponent\",\n TextContentPartComponent: \"TextMessagePartComponent\",\n ReasoningContentPartComponent: \"ReasoningMessagePartComponent\",\n SourceContentPartComponent: \"SourceMessagePartComponent\",\n ImageContentPartComponent: \"ImageMessagePartComponent\",\n FileContentPartComponent: \"FileMessagePartComponent\",\n Unstable_AudioContentPartComponent: \"Unstable_AudioMessagePartComponent\",\n ToolCallContentPartComponent: \"ToolCallMessagePartComponent\",\n\n // Props types\n EmptyContentPartProps: \"EmptyMessagePartProps\",\n TextContentPartProps: \"TextMessagePartProps\",\n ReasoningContentPartProps: \"ReasoningMessagePartProps\",\n SourceContentPartProps: \"SourceMessagePartProps\",\n ImageContentPartProps: \"ImageMessagePartProps\",\n FileContentPartProps: \"FileMessagePartProps\",\n Unstable_AudioContentPartProps: \"Unstable_AudioMessagePartProps\",\n ToolCallContentPartProps: \"ToolCallMessagePartProps\",\n\n // Provider types\n TextContentPartProvider: \"TextMessagePartProvider\",\n TextContentPartProviderProps: \"TextMessagePartProviderProps\",\n ContentPartRuntimeProvider: \"MessagePartRuntimeProvider\",\n\n // Context types\n ContentPartContext: \"MessagePartContext\",\n ContentPartContextValue: \"MessagePartContextValue\",\n\n // Hook names\n useContentPart: \"useMessagePart\",\n useContentPartRuntime: \"useMessagePartRuntime\",\n useContentPartText: \"useMessagePartText\",\n useContentPartReasoning: \"useMessagePartReasoning\",\n useContentPartSource: \"useMessagePartSource\",\n useContentPartFile: \"useMessagePartFile\",\n useContentPartImage: \"useMessagePartImage\",\n useTextContentPart: \"useTextMessagePart\",\n\n // Primitive names\n ContentPartPrimitive: \"MessagePartPrimitive\",\n ContentPartPrimitiveText: \"MessagePartPrimitiveText\",\n ContentPartPrimitiveImage: \"MessagePartPrimitiveImage\",\n ContentPartPrimitiveInProgress: \"MessagePartPrimitiveInProgress\",\n};\n\nconst migrateContentPartToMessagePart = createTransformer(\n ({ j, root, markAsChanged }) => {\n // 1. Update imports\n root.find(j.ImportDeclaration).forEach((path: any) => {\n const source = path.value.source.value;\n\n // Only process imports from @assistant-ui packages\n if (typeof source === \"string\" && source.startsWith(\"@assistant-ui/\")) {\n path.value.specifiers?.forEach((specifier: any) => {\n if (j.ImportSpecifier.check(specifier)) {\n const oldName = specifier.imported.name as string;\n if (typeRenamingMap[oldName]) {\n specifier.imported.name = typeRenamingMap[oldName];\n if (specifier.local && specifier.local.name === oldName) {\n specifier.local.name = typeRenamingMap[oldName];\n }\n markAsChanged();\n }\n }\n });\n }\n });\n\n // 2. Update MessagePrimitive.Content to MessagePrimitive.Parts\n root.find(j.MemberExpression).forEach((path: any) => {\n if (\n path.value.object &&\n path.value.object.name === \"MessagePrimitive\" &&\n path.value.property &&\n path.value.property.name === \"Content\"\n ) {\n path.value.property.name = \"Parts\";\n markAsChanged();\n }\n });\n\n // 3. Update JSX member expressions (e.g., MessagePrimitive.Content in JSX)\n root.find(j.JSXMemberExpression).forEach((path: any) => {\n if (\n path.value.object &&\n path.value.object.name === \"MessagePrimitive\" &&\n path.value.property &&\n path.value.property.name === \"Content\"\n ) {\n path.value.property.name = \"Parts\";\n markAsChanged();\n }\n });\n\n // 4. Update all identifiers for types, hooks, and primitives\n Object.entries(typeRenamingMap).forEach(([oldName, newName]) => {\n // Update type references\n root.find(j.TSTypeReference).forEach((path: any) => {\n if (path.value.typeName && path.value.typeName.name === oldName) {\n path.value.typeName.name = newName;\n markAsChanged();\n }\n });\n\n // Update identifier references\n root.find(j.Identifier).forEach((path: any) => {\n if (path.value.name === oldName) {\n // Skip if this is part of an import declaration (already handled above)\n if (j.ImportSpecifier.check(path.parent.value)) {\n return;\n }\n\n // Skip if this is a property key in an object\n if (\n j.Property.check(path.parent.value) &&\n path.parent.value.key === path.value\n ) {\n return;\n }\n\n // Skip if this is a property in a member expression\n if (\n j.MemberExpression.check(path.parent.value) &&\n path.parent.value.property === path.value\n ) {\n return;\n }\n\n path.value.name = newName;\n markAsChanged();\n }\n });\n\n // Update JSX element names\n root.find(j.JSXIdentifier).forEach((path: any) => {\n if (path.value.name === oldName) {\n path.value.name = newName;\n markAsChanged();\n }\n });\n });\n },\n);\n\nexport default migrateContentPartToMessagePart;\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"assistant-api-to-aui.js","names":[],"sources":["../../../src/codemods/v0-12/assistant-api-to-aui.ts"],"sourcesContent":["import { createTransformer } from \"../utils/createTransformer\";\n\n// Map of old hook names to new hook names\nconst hookRenamingMap: Record<string, string> = {\n useAssistantApi: \"useAui\",\n useAssistantState: \"useAuiState\",\n useAssistantEvent: \"useAuiEvent\",\n};\n\n// Map of old component names to new component names\nconst componentRenamingMap: Record<string, string> = {\n AssistantIf: \"AuiIf\",\n AssistantProvider: \"AuiProvider\",\n};\n\nconst isUseAuiCall = (j: any, node: any): boolean => {\n return (\n node &&\n j.CallExpression.check(node) &&\n j.Identifier.check(node.callee) &&\n (node.callee.name === \"useAui\" || node.callee.name === \"useAssistantApi\")\n );\n};\n\n// Check if a scope node directly contains an 'api' variable declaration\nconst scopeHasDirectApiDeclaration = (j: any, scopeNode: any): boolean => {\n // Get the body of the scope\n let body = null;\n if (\n j.FunctionDeclaration.check(scopeNode) ||\n j.FunctionExpression.check(scopeNode)\n ) {\n body = scopeNode.body?.body;\n } else if (j.ArrowFunctionExpression.check(scopeNode)) {\n // Arrow functions might have block or expression body\n if (j.BlockStatement.check(scopeNode.body)) {\n body = scopeNode.body.body;\n }\n } else if (j.BlockStatement.check(scopeNode)) {\n body = scopeNode.body;\n }\n\n if (!Array.isArray(body)) return false;\n\n // Check only direct statements in this scope's body\n for (const statement of body) {\n if (j.VariableDeclaration.check(statement)) {\n for (const declarator of statement.declarations) {\n if (j.Identifier.check(declarator.id) && declarator.id.name === \"api\") {\n // Don't count it as shadowing if it's from useAui\n if (!isUseAuiCall(j, declarator.init)) {\n return true;\n }\n }\n }\n }\n }\n\n return false;\n};\n\n// Check if a path is inside a scope that shadows the api variable\nconst isInsideShadowingScope = (j: any, identifierPath: any): boolean => {\n let currentPath = identifierPath.parent;\n\n while (currentPath) {\n const node = currentPath.value;\n\n // Check if this is a scope-creating node (function, arrow function, block)\n if (\n j.FunctionDeclaration.check(node) ||\n j.FunctionExpression.check(node) ||\n j.ArrowFunctionExpression.check(node) ||\n j.BlockStatement.check(node)\n ) {\n if (scopeHasDirectApiDeclaration(j, node)) {\n return true;\n }\n }\n\n currentPath = currentPath.parent;\n }\n\n return false;\n};\n\nconst migrateAssistantApiToAui = createTransformer(\n ({ j, root, markAsChanged }) => {\n let hasApiFromUseAui = false;\n\n // 1. Update imports\n root.find(j.ImportDeclaration).forEach((path: any) => {\n const source = path.value.source.value;\n\n // Only process imports from @assistant-ui packages\n if (typeof source === \"string\" && source.startsWith(\"@assistant-ui/\")) {\n path.value.specifiers?.forEach((specifier: any) => {\n if (j.ImportSpecifier.check(specifier)) {\n const oldName = specifier.imported.name as string;\n\n // Rename hooks\n if (hookRenamingMap[oldName]) {\n const newName = hookRenamingMap[oldName];\n specifier.imported.name = newName;\n if (specifier.local && specifier.local.name === oldName) {\n specifier.local.name = newName;\n }\n markAsChanged();\n }\n\n // Rename components\n if (componentRenamingMap[oldName]) {\n const newName = componentRenamingMap[oldName];\n specifier.imported.name = newName;\n if (specifier.local && specifier.local.name === oldName) {\n specifier.local.name = newName;\n }\n markAsChanged();\n }\n }\n });\n }\n });\n\n // 2. Find and rename variable declarations from useAui (or useAssistantApi)\n root.find(j.VariableDeclarator).forEach((path: any) => {\n const init = path.value.init;\n\n // Check if this is a call to useAui or useAssistantApi\n if (isUseAuiCall(j, init)) {\n if (j.Identifier.check(path.value.id)) {\n const oldVarName = path.value.id.name;\n\n // Only rename if it's called 'api'\n if (oldVarName === \"api\") {\n path.value.id.name = \"aui\";\n hasApiFromUseAui = true;\n markAsChanged();\n }\n }\n }\n });\n\n // 3. Rename all references to 'api' if we found it from useAui\n if (hasApiFromUseAui) {\n root.find(j.Identifier).forEach((path: any) => {\n if (path.value.name === \"api\") {\n // Skip if this is part of an import\n if (j.ImportSpecifier.check(path.parent.value)) {\n return;\n }\n\n // Skip if this is a variable declarator id\n if (j.VariableDeclarator.check(path.parent.value)) {\n const declarator = path.parent.value;\n if (declarator.id === path.value) {\n return;\n }\n }\n\n // Skip if this is a property key in an object (e.g., { api: true })\n if (j.Property.check(path.parent.value)) {\n const prop = path.parent.value;\n if (prop.key === path.value && !prop.shorthand && !prop.computed) {\n return;\n }\n }\n\n if (j.ObjectProperty.check(path.parent.value)) {\n const prop = path.parent.value;\n if (prop.key === path.value && !prop.shorthand && !prop.computed) {\n return;\n }\n }\n\n // Skip if this is a property in a member expression (e.g., foo.api)\n if (\n j.MemberExpression.check(path.parent.value) &&\n path.parent.value.property === path.value &&\n !path.parent.value.computed\n ) {\n return;\n }\n\n // Skip if this is a JSX attribute name\n if (j.JSXAttribute.check(path.parent.value)) {\n return;\n }\n\n // Skip if this identifier is inside a scope that shadows the api variable\n if (isInsideShadowingScope(j, path)) {\n return;\n }\n\n // Update the reference\n path.value.name = \"aui\";\n markAsChanged();\n }\n });\n\n // Also handle JSX identifiers\n root.find(j.JSXIdentifier).forEach((path: any) => {\n if (path.value.name === \"api\") {\n if (!isInsideShadowingScope(j, path)) {\n path.value.name = \"aui\";\n markAsChanged();\n }\n }\n });\n }\n\n // 4. Update hook call references (in case they're used as values)\n Object.entries(hookRenamingMap).forEach(([oldName, newName]) => {\n root.find(j.Identifier).forEach((path: any) => {\n if (path.value.name === oldName) {\n // Skip if already handled in imports\n if (j.ImportSpecifier.check(path.parent.value)) {\n return;\n }\n\n // This might be a reference to the hook as a value\n path.value.name = newName;\n markAsChanged();\n }\n });\n });\n\n // 5. Update JSX component names\n Object.entries(componentRenamingMap).forEach(([oldName, newName]) => {\n // Update JSX opening elements\n root.find(j.JSXOpeningElement).forEach((path: any) => {\n if (\n j.JSXIdentifier.check(path.value.name) &&\n path.value.name.name === oldName\n ) {\n path.value.name.name = newName;\n markAsChanged();\n }\n });\n\n // Update JSX closing elements\n root.find(j.JSXClosingElement).forEach((path: any) => {\n if (\n j.JSXIdentifier.check(path.value.name) &&\n path.value.name.name === oldName\n ) {\n path.value.name.name = newName;\n markAsChanged();\n }\n });\n\n // Update regular identifier references (for component references)\n root.find(j.Identifier).forEach((path: any) => {\n if (path.value.name === oldName) {\n // Skip if already handled in imports\n if (j.ImportSpecifier.check(path.parent.value)) {\n return;\n }\n\n // Skip JSX identifiers (already handled above)\n if (j.JSXIdentifier.check(path.value)) {\n return;\n }\n\n // This might be a reference to the component as a value\n path.value.name = newName;\n markAsChanged();\n }\n });\n });\n },\n);\n\nexport default migrateAssistantApiToAui;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"assistant-api-to-aui.js","names":[],"sources":["../../../src/codemods/v0-12/assistant-api-to-aui.ts"],"sourcesContent":["import { createTransformer } from \"../utils/createTransformer\";\n\n// Map of old hook names to new hook names\nconst hookRenamingMap: Record<string, string> = {\n useAssistantApi: \"useAui\",\n useAssistantState: \"useAuiState\",\n useAssistantEvent: \"useAuiEvent\",\n};\n\n// Map of old component names to new component names\nconst componentRenamingMap: Record<string, string> = {\n AssistantIf: \"AuiIf\",\n AssistantProvider: \"AuiProvider\",\n};\n\nconst isUseAuiCall = (j: any, node: any): boolean => {\n return (\n node &&\n j.CallExpression.check(node) &&\n j.Identifier.check(node.callee) &&\n (node.callee.name === \"useAui\" || node.callee.name === \"useAssistantApi\")\n );\n};\n\n// Check if a scope node directly contains an 'api' variable declaration\nconst scopeHasDirectApiDeclaration = (j: any, scopeNode: any): boolean => {\n // Get the body of the scope\n let body = null;\n if (\n j.FunctionDeclaration.check(scopeNode) ||\n j.FunctionExpression.check(scopeNode)\n ) {\n body = scopeNode.body?.body;\n } else if (j.ArrowFunctionExpression.check(scopeNode)) {\n // Arrow functions might have block or expression body\n if (j.BlockStatement.check(scopeNode.body)) {\n body = scopeNode.body.body;\n }\n } else if (j.BlockStatement.check(scopeNode)) {\n body = scopeNode.body;\n }\n\n if (!Array.isArray(body)) return false;\n\n // Check only direct statements in this scope's body\n for (const statement of body) {\n if (j.VariableDeclaration.check(statement)) {\n for (const declarator of statement.declarations) {\n if (j.Identifier.check(declarator.id) && declarator.id.name === \"api\") {\n // Don't count it as shadowing if it's from useAui\n if (!isUseAuiCall(j, declarator.init)) {\n return true;\n }\n }\n }\n }\n }\n\n return false;\n};\n\n// Check if a path is inside a scope that shadows the api variable\nconst isInsideShadowingScope = (j: any, identifierPath: any): boolean => {\n let currentPath = identifierPath.parent;\n\n while (currentPath) {\n const node = currentPath.value;\n\n // Check if this is a scope-creating node (function, arrow function, block)\n if (\n j.FunctionDeclaration.check(node) ||\n j.FunctionExpression.check(node) ||\n j.ArrowFunctionExpression.check(node) ||\n j.BlockStatement.check(node)\n ) {\n if (scopeHasDirectApiDeclaration(j, node)) {\n return true;\n }\n }\n\n currentPath = currentPath.parent;\n }\n\n return false;\n};\n\nconst migrateAssistantApiToAui = createTransformer(\n ({ j, root, markAsChanged }) => {\n let hasApiFromUseAui = false;\n\n // 1. Update imports\n root.find(j.ImportDeclaration).forEach((path: any) => {\n const source = path.value.source.value;\n\n // Only process imports from @assistant-ui packages\n if (typeof source === \"string\" && source.startsWith(\"@assistant-ui/\")) {\n path.value.specifiers?.forEach((specifier: any) => {\n if (j.ImportSpecifier.check(specifier)) {\n const oldName = specifier.imported.name as string;\n\n // Rename hooks\n if (hookRenamingMap[oldName]) {\n const newName = hookRenamingMap[oldName];\n specifier.imported.name = newName;\n if (specifier.local && specifier.local.name === oldName) {\n specifier.local.name = newName;\n }\n markAsChanged();\n }\n\n // Rename components\n if (componentRenamingMap[oldName]) {\n const newName = componentRenamingMap[oldName];\n specifier.imported.name = newName;\n if (specifier.local && specifier.local.name === oldName) {\n specifier.local.name = newName;\n }\n markAsChanged();\n }\n }\n });\n }\n });\n\n // 2. Find and rename variable declarations from useAui (or useAssistantApi)\n root.find(j.VariableDeclarator).forEach((path: any) => {\n const init = path.value.init;\n\n // Check if this is a call to useAui or useAssistantApi\n if (isUseAuiCall(j, init)) {\n if (j.Identifier.check(path.value.id)) {\n const oldVarName = path.value.id.name;\n\n // Only rename if it's called 'api'\n if (oldVarName === \"api\") {\n path.value.id.name = \"aui\";\n hasApiFromUseAui = true;\n markAsChanged();\n }\n }\n }\n });\n\n // 3. Rename all references to 'api' if we found it from useAui\n if (hasApiFromUseAui) {\n root.find(j.Identifier).forEach((path: any) => {\n if (path.value.name === \"api\") {\n // Skip if this is part of an import\n if (j.ImportSpecifier.check(path.parent.value)) {\n return;\n }\n\n // Skip if this is a variable declarator id\n if (j.VariableDeclarator.check(path.parent.value)) {\n const declarator = path.parent.value;\n if (declarator.id === path.value) {\n return;\n }\n }\n\n // Skip if this is a property key in an object (e.g., { api: true })\n if (j.Property.check(path.parent.value)) {\n const prop = path.parent.value;\n if (prop.key === path.value && !prop.shorthand && !prop.computed) {\n return;\n }\n }\n\n if (j.ObjectProperty.check(path.parent.value)) {\n const prop = path.parent.value;\n if (prop.key === path.value && !prop.shorthand && !prop.computed) {\n return;\n }\n }\n\n // Skip if this is a property in a member expression (e.g., foo.api)\n if (\n j.MemberExpression.check(path.parent.value) &&\n path.parent.value.property === path.value &&\n !path.parent.value.computed\n ) {\n return;\n }\n\n // Skip if this is a JSX attribute name\n if (j.JSXAttribute.check(path.parent.value)) {\n return;\n }\n\n // Skip if this identifier is inside a scope that shadows the api variable\n if (isInsideShadowingScope(j, path)) {\n return;\n }\n\n // Update the reference\n path.value.name = \"aui\";\n markAsChanged();\n }\n });\n\n // Also handle JSX identifiers\n root.find(j.JSXIdentifier).forEach((path: any) => {\n if (path.value.name === \"api\") {\n if (!isInsideShadowingScope(j, path)) {\n path.value.name = \"aui\";\n markAsChanged();\n }\n }\n });\n }\n\n // 4. Update hook call references (in case they're used as values)\n Object.entries(hookRenamingMap).forEach(([oldName, newName]) => {\n root.find(j.Identifier).forEach((path: any) => {\n if (path.value.name === oldName) {\n // Skip if already handled in imports\n if (j.ImportSpecifier.check(path.parent.value)) {\n return;\n }\n\n // This might be a reference to the hook as a value\n path.value.name = newName;\n markAsChanged();\n }\n });\n });\n\n // 5. Update JSX component names\n Object.entries(componentRenamingMap).forEach(([oldName, newName]) => {\n // Update JSX opening elements\n root.find(j.JSXOpeningElement).forEach((path: any) => {\n if (\n j.JSXIdentifier.check(path.value.name) &&\n path.value.name.name === oldName\n ) {\n path.value.name.name = newName;\n markAsChanged();\n }\n });\n\n // Update JSX closing elements\n root.find(j.JSXClosingElement).forEach((path: any) => {\n if (\n j.JSXIdentifier.check(path.value.name) &&\n path.value.name.name === oldName\n ) {\n path.value.name.name = newName;\n markAsChanged();\n }\n });\n\n // Update regular identifier references (for component references)\n root.find(j.Identifier).forEach((path: any) => {\n if (path.value.name === oldName) {\n // Skip if already handled in imports\n if (j.ImportSpecifier.check(path.parent.value)) {\n return;\n }\n\n // Skip JSX identifiers (already handled above)\n if (j.JSXIdentifier.check(path.value)) {\n return;\n }\n\n // This might be a reference to the component as a value\n path.value.name = newName;\n markAsChanged();\n }\n });\n });\n },\n);\n\nexport default migrateAssistantApiToAui;\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"event-names-to-camelcase.js","names":[],"sources":["../../../src/codemods/v0-12/event-names-to-camelcase.ts"],"sourcesContent":["import { createTransformer } from \"../utils/createTransformer\";\n\n// Map of old kebab-case event names to new camelCase event names\nconst eventNameMap: Record<string, string> = {\n \"thread.run-start\": \"thread.runStart\",\n \"thread.run-end\": \"thread.runEnd\",\n \"thread.model-context-update\": \"thread.modelContextUpdate\",\n \"composer.attachment-add\": \"composer.attachmentAdd\",\n \"thread-list-item.switched-to\": \"threadListItem.switchedTo\",\n \"thread-list-item.switched-away\": \"threadListItem.switchedAway\",\n};\n\nconst migrateEventNamesToCamelCase = createTransformer(\n ({ j, root, markAsChanged }) => {\n // Find all string literals in the code\n root.find(j.Literal).forEach((path: any) => {\n const node = path.value;\n\n // Check if this is a string literal\n if (typeof node.value === \"string\") {\n const oldEventName = node.value;\n\n // Check if this event name needs to be migrated\n if (eventNameMap[oldEventName]) {\n const newEventName = eventNameMap[oldEventName];\n node.value = newEventName;\n markAsChanged();\n }\n }\n });\n\n // Also handle template literals (in case event names are in template strings)\n root.find(j.TemplateLiteral).forEach((path: any) => {\n const node = path.value;\n\n // Check quasi (string parts) in template literals\n node.quasis.forEach((quasi: any) => {\n if (quasi.value && typeof quasi.value.raw === \"string\") {\n const oldEventName = quasi.value.raw;\n\n if (eventNameMap[oldEventName]) {\n const newEventName = eventNameMap[oldEventName];\n quasi.value.raw = newEventName;\n quasi.value.cooked = newEventName;\n markAsChanged();\n }\n }\n });\n });\n },\n);\n\nexport default migrateEventNamesToCamelCase;\n"],"mappings":";;AAGA,MAAM,eAAuC;CAC3C,oBAAoB;CACpB,kBAAkB;CAClB,+BAA+B;CAC/B,2BAA2B;CAC3B,gCAAgC;CAChC,kCAAkC;AACpC;AAEA,MAAM,+BAA+B,mBAClC,EAAE,GAAG,MAAM,oBAAoB;CAE9B,KAAK,KAAK,EAAE,OAAO,
|
|
1
|
+
{"version":3,"file":"event-names-to-camelcase.js","names":[],"sources":["../../../src/codemods/v0-12/event-names-to-camelcase.ts"],"sourcesContent":["import { createTransformer } from \"../utils/createTransformer\";\n\n// Map of old kebab-case event names to new camelCase event names\nconst eventNameMap: Record<string, string> = {\n \"thread.run-start\": \"thread.runStart\",\n \"thread.run-end\": \"thread.runEnd\",\n \"thread.model-context-update\": \"thread.modelContextUpdate\",\n \"composer.attachment-add\": \"composer.attachmentAdd\",\n \"thread-list-item.switched-to\": \"threadListItem.switchedTo\",\n \"thread-list-item.switched-away\": \"threadListItem.switchedAway\",\n};\n\nconst migrateEventNamesToCamelCase = createTransformer(\n ({ j, root, markAsChanged }) => {\n // Find all string literals in the code\n root.find(j.Literal).forEach((path: any) => {\n const node = path.value;\n\n // Check if this is a string literal\n if (typeof node.value === \"string\") {\n const oldEventName = node.value;\n\n // Check if this event name needs to be migrated\n if (eventNameMap[oldEventName]) {\n const newEventName = eventNameMap[oldEventName];\n node.value = newEventName;\n markAsChanged();\n }\n }\n });\n\n // Also handle template literals (in case event names are in template strings)\n root.find(j.TemplateLiteral).forEach((path: any) => {\n const node = path.value;\n\n // Check quasi (string parts) in template literals\n node.quasis.forEach((quasi: any) => {\n if (quasi.value && typeof quasi.value.raw === \"string\") {\n const oldEventName = quasi.value.raw;\n\n if (eventNameMap[oldEventName]) {\n const newEventName = eventNameMap[oldEventName];\n quasi.value.raw = newEventName;\n quasi.value.cooked = newEventName;\n markAsChanged();\n }\n }\n });\n });\n },\n);\n\nexport default migrateEventNamesToCamelCase;\n"],"mappings":";;AAGA,MAAM,eAAuC;CAC3C,oBAAoB;CACpB,kBAAkB;CAClB,+BAA+B;CAC/B,2BAA2B;CAC3B,gCAAgC;CAChC,kCAAkC;AACpC;AAEA,MAAM,+BAA+B,mBAClC,EAAE,GAAG,MAAM,oBAAoB;CAE9B,KAAK,KAAK,EAAE,OAAO,CAAC,CAAC,SAAS,SAAc;EAC1C,MAAM,OAAO,KAAK;EAGlB,IAAI,OAAO,KAAK,UAAU,UAAU;GAClC,MAAM,eAAe,KAAK;GAG1B,IAAI,aAAa,eAAe;IAE9B,KAAK,QADgB,aAAa;IAElC,cAAc;GAChB;EACF;CACF,CAAC;CAGD,KAAK,KAAK,EAAE,eAAe,CAAC,CAAC,SAAS,SAAc;EAIlD,KAHkB,MAGb,OAAO,SAAS,UAAe;GAClC,IAAI,MAAM,SAAS,OAAO,MAAM,MAAM,QAAQ,UAAU;IACtD,MAAM,eAAe,MAAM,MAAM;IAEjC,IAAI,aAAa,eAAe;KAC9B,MAAM,eAAe,aAAa;KAClC,MAAM,MAAM,MAAM;KAClB,MAAM,MAAM,SAAS;KACrB,cAAc;IAChB;GACF;EACF,CAAC;CACH,CAAC;AACH,CACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"primitive-if-to-aui-if.js","names":[],"sources":["../../../src/codemods/v0-12/primitive-if-to-aui-if.ts"],"sourcesContent":["import { createTransformer } from \"../utils/createTransformer\";\n\ntype ConditionFragment = {\n expression: string;\n negated: boolean;\n};\n\n// Map ThreadPrimitive.If props to condition expressions\nconst threadPropMap: Record<\n string,\n (value: unknown) => ConditionFragment | null\n> = {\n empty: (v) => ({\n expression: \"s.thread.isEmpty\",\n negated: v === false,\n }),\n running: (v) => ({\n expression: \"s.thread.isRunning\",\n negated: v === false,\n }),\n disabled: (v) => ({\n expression: \"s.thread.isDisabled\",\n negated: v === false,\n }),\n};\n\n// Map MessagePrimitive.If props to condition expressions\nconst messagePropMap: Record<\n string,\n (value: unknown) => ConditionFragment | null\n> = {\n user: () => ({ expression: 's.message.role === \"user\"', negated: false }),\n assistant: () => ({\n expression: 's.message.role === \"assistant\"',\n negated: false,\n }),\n system: () => ({\n expression: 's.message.role === \"system\"',\n negated: false,\n }),\n hasBranches: () => ({\n expression: \"s.message.branchCount >= 2\",\n negated: false,\n }),\n copied: (v) => ({\n expression: \"s.message.isCopied\",\n negated: v === false,\n }),\n last: (v) => ({\n expression: \"s.message.isLast\",\n negated: v === false,\n }),\n lastOrHover: () => ({\n expression: \"s.message.isHovering || s.message.isLast\",\n negated: false,\n }),\n speaking: (v) => ({\n expression: \"s.message.speech != null\",\n negated: v === false,\n }),\n hasAttachments: (v) =>\n v === true\n ? {\n expression:\n 's.message.role === \"user\" && !!s.message.attachments?.length',\n negated: false,\n }\n : {\n expression:\n 's.message.role !== \"user\" || !s.message.attachments?.length',\n negated: false,\n },\n hasContent: (v) => ({\n expression: \"s.message.parts.length > 0\",\n negated: v === false,\n }),\n submittedFeedback: (v) => {\n if (v === null) {\n return {\n expression:\n \"(s.message.metadata.submittedFeedback?.type ?? null) === null\",\n negated: false,\n };\n }\n return {\n expression: `s.message.metadata.submittedFeedback?.type === \"${v}\"`,\n negated: false,\n };\n },\n};\n\n// Map ComposerPrimitive.If props to condition expressions\nconst composerPropMap: Record<\n string,\n (value: unknown) => ConditionFragment | null\n> = {\n editing: (v) => ({\n expression: \"s.composer.isEditing\",\n negated: v === false,\n }),\n dictation: (v) => ({\n expression: \"s.composer.dictation != null\",\n negated: v === false,\n }),\n};\n\nconst primitiveMap: Record<\n string,\n Record<string, (value: unknown) => ConditionFragment | null>\n> = {\n ThreadPrimitive: threadPropMap,\n MessagePrimitive: messagePropMap,\n ComposerPrimitive: composerPropMap,\n};\n\n// Map of XPrimitive.Component → fixed condition (no props needed)\nconst fixedConditionMap: Record<string, Record<string, string>> = {\n ThreadPrimitive: {\n Empty: \"s.thread.isEmpty\",\n },\n};\n\n/**\n * Extract the value of a JSX attribute.\n * - Boolean prop (no value): `<X.If user>` → `true`\n * - `{true}` / `{false}`: → `true` / `false`\n * - `{\"positive\"}`: → `\"positive\"`\n * - `{null}`: → `null`\n */\nconst getAttrValue = (j: any, attr: any): unknown => {\n // Boolean attribute (no value), e.g. `<X.If user>`\n if (attr.value === null || attr.value === undefined) {\n return true;\n }\n\n // JSX expression container: `{true}`, `{false}`, `{\"positive\"}`, `{null}`\n if (j.JSXExpressionContainer.check(attr.value)) {\n const expr = attr.value.expression;\n if (j.BooleanLiteral.check(expr)) return expr.value;\n if (j.Literal.check(expr)) {\n if (expr.value === null) return null;\n return expr.value;\n }\n if (j.NullLiteral.check(expr)) return null;\n if (j.Identifier.check(expr) && expr.name === \"undefined\") return undefined;\n }\n\n // String literal\n if (j.StringLiteral.check(attr.value) || j.Literal.check(attr.value)) {\n return attr.value.value;\n }\n\n return undefined;\n};\n\nconst buildConditionString = (fragments: ConditionFragment[]): string => {\n const parts = fragments.map((f) =>\n f.negated ? `!${f.expression}` : f.expression,\n );\n if (parts.length === 1) return parts[0]!;\n return parts.join(\" && \");\n};\n\nconst migratePrimitiveIfToAuiIf = createTransformer(\n ({ j, root, markAsChanged }) => {\n let needsAuiIfImport = false;\n\n // Track which primitive namespaces are imported\n const importedPrimitives = new Set<string>();\n root.find(j.ImportDeclaration).forEach((path: any) => {\n const source = path.value.source.value;\n if (typeof source === \"string\" && source.startsWith(\"@assistant-ui/\")) {\n path.value.specifiers?.forEach((specifier: any) => {\n if (j.ImportSpecifier.check(specifier)) {\n const name = String(\n specifier.local?.name ?? specifier.imported.name,\n );\n if (primitiveMap[name] || fixedConditionMap[name]) {\n importedPrimitives.add(name);\n }\n }\n });\n }\n });\n\n if (importedPrimitives.size === 0) return;\n\n // Process fixed-condition components: <ThreadPrimitive.Empty> → <AuiIf condition={...}>\n root.find(j.JSXOpeningElement).forEach((path: any) => {\n const name = path.value.name;\n if (!j.JSXMemberExpression.check(name)) return;\n if (!j.JSXIdentifier.check(name.object)) return;\n if (!j.JSXIdentifier.check(name.property)) return;\n\n const primitiveName = name.object.name as string;\n const propertyName = name.property.name as string;\n const fixedMap = fixedConditionMap[primitiveName];\n if (!fixedMap) return;\n const conditionBody = fixedMap[propertyName];\n if (!conditionBody) return;\n if (!importedPrimitives.has(primitiveName)) return;\n\n // Only transform if there are no props (other than children, which are implicit)\n const attrs: any[] = path.value.attributes || [];\n if (attrs.length > 0) return;\n\n const arrowFnAst = j(`(s) => ${conditionBody}`)\n .find(j.ArrowFunctionExpression)\n .paths()[0]!.value;\n\n path.value.name = j.jsxIdentifier(\"AuiIf\");\n path.value.attributes = [\n j.jsxAttribute(\n j.jsxIdentifier(\"condition\"),\n j.jsxExpressionContainer(arrowFnAst),\n ),\n ];\n\n needsAuiIfImport = true;\n markAsChanged();\n });\n\n // Update closing elements for fixed-condition components\n root.find(j.JSXClosingElement).forEach((path: any) => {\n const name = path.value.name;\n if (!j.JSXMemberExpression.check(name)) return;\n if (!j.JSXIdentifier.check(name.object)) return;\n if (!j.JSXIdentifier.check(name.property)) return;\n\n const primitiveName = name.object.name as string;\n const propertyName = name.property.name as string;\n const fixedMap = fixedConditionMap[primitiveName];\n if (!fixedMap?.[propertyName]) return;\n if (!importedPrimitives.has(primitiveName)) return;\n\n path.value.name = j.jsxIdentifier(\"AuiIf\");\n markAsChanged();\n });\n\n // Process JSX elements: <ThreadPrimitive.If ...> → <AuiIf condition={...}>\n root.find(j.JSXOpeningElement).forEach((path: any) => {\n const name = path.value.name;\n\n // Check for `<XPrimitive.If ...>`\n if (!j.JSXMemberExpression.check(name)) return;\n if (!j.JSXIdentifier.check(name.object)) return;\n if (!j.JSXIdentifier.check(name.property)) return;\n if (name.property.name !== \"If\") return;\n\n const primitiveName = name.object.name;\n const propMap = primitiveMap[primitiveName];\n if (!propMap) return;\n if (!importedPrimitives.has(primitiveName)) return;\n\n // Extract props\n const attrs: any[] = path.value.attributes || [];\n const fragments: ConditionFragment[] = [];\n let hasUnknownProp = false;\n\n for (const attr of attrs) {\n if (!j.JSXAttribute.check(attr)) {\n // JSX spread attributes — can't migrate\n hasUnknownProp = true;\n continue;\n }\n const propName =\n typeof attr.name.name === \"string\" ? attr.name.name : null;\n if (!propName) continue;\n\n const mapper = propMap[propName];\n if (!mapper) {\n hasUnknownProp = true;\n continue;\n }\n\n const value = getAttrValue(j, attr);\n const fragment = mapper(value);\n if (fragment) {\n fragments.push(fragment);\n }\n }\n\n // If we couldn't map all props, skip this element\n if (hasUnknownProp || fragments.length === 0) return;\n\n const conditionBody = buildConditionString(fragments);\n\n // Parse the arrow function as an expression to get a proper AST node\n const arrowFnAst = j(`(s) => ${conditionBody}`)\n .find(j.ArrowFunctionExpression)\n .paths()[0]!.value;\n\n // Replace <XPrimitive.If ...> with <AuiIf condition={...}>\n path.value.name = j.jsxIdentifier(\"AuiIf\");\n\n // Replace all attributes with a single condition prop\n path.value.attributes = [\n j.jsxAttribute(\n j.jsxIdentifier(\"condition\"),\n j.jsxExpressionContainer(arrowFnAst),\n ),\n ];\n\n needsAuiIfImport = true;\n markAsChanged();\n });\n\n // Update closing elements to match\n root.find(j.JSXClosingElement).forEach((path: any) => {\n const name = path.value.name;\n if (!j.JSXMemberExpression.check(name)) return;\n if (!j.JSXIdentifier.check(name.object)) return;\n if (!j.JSXIdentifier.check(name.property)) return;\n if (name.property.name !== \"If\") return;\n\n const primitiveName = name.object.name;\n if (!primitiveMap[primitiveName]) return;\n if (!importedPrimitives.has(primitiveName)) return;\n\n path.value.name = j.jsxIdentifier(\"AuiIf\");\n markAsChanged();\n });\n\n // Add AuiIf import if needed\n if (needsAuiIfImport) {\n let hasAuiIfImport = false;\n let assistantUiImport: any = null;\n\n root.find(j.ImportDeclaration).forEach((path: any) => {\n const source = path.value.source.value;\n if (typeof source === \"string\" && source.startsWith(\"@assistant-ui/\")) {\n assistantUiImport = path;\n path.value.specifiers?.forEach((specifier: any) => {\n if (\n j.ImportSpecifier.check(specifier) &&\n (specifier.imported.name === \"AuiIf\" ||\n specifier.local?.name === \"AuiIf\")\n ) {\n hasAuiIfImport = true;\n }\n });\n }\n });\n\n if (!hasAuiIfImport && assistantUiImport) {\n assistantUiImport.value.specifiers.push(\n j.importSpecifier(j.identifier(\"AuiIf\")),\n );\n markAsChanged();\n }\n }\n },\n);\n\nexport default migratePrimitiveIfToAuiIf;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"primitive-if-to-aui-if.js","names":[],"sources":["../../../src/codemods/v0-12/primitive-if-to-aui-if.ts"],"sourcesContent":["import { createTransformer } from \"../utils/createTransformer\";\n\ntype ConditionFragment = {\n expression: string;\n negated: boolean;\n};\n\n// Map ThreadPrimitive.If props to condition expressions\nconst threadPropMap: Record<\n string,\n (value: unknown) => ConditionFragment | null\n> = {\n empty: (v) => ({\n expression: \"s.thread.isEmpty\",\n negated: v === false,\n }),\n running: (v) => ({\n expression: \"s.thread.isRunning\",\n negated: v === false,\n }),\n disabled: (v) => ({\n expression: \"s.thread.isDisabled\",\n negated: v === false,\n }),\n};\n\n// Map MessagePrimitive.If props to condition expressions\nconst messagePropMap: Record<\n string,\n (value: unknown) => ConditionFragment | null\n> = {\n user: () => ({ expression: 's.message.role === \"user\"', negated: false }),\n assistant: () => ({\n expression: 's.message.role === \"assistant\"',\n negated: false,\n }),\n system: () => ({\n expression: 's.message.role === \"system\"',\n negated: false,\n }),\n hasBranches: () => ({\n expression: \"s.message.branchCount >= 2\",\n negated: false,\n }),\n copied: (v) => ({\n expression: \"s.message.isCopied\",\n negated: v === false,\n }),\n last: (v) => ({\n expression: \"s.message.isLast\",\n negated: v === false,\n }),\n lastOrHover: () => ({\n expression: \"s.message.isHovering || s.message.isLast\",\n negated: false,\n }),\n speaking: (v) => ({\n expression: \"s.message.speech != null\",\n negated: v === false,\n }),\n hasAttachments: (v) =>\n v === true\n ? {\n expression:\n 's.message.role === \"user\" && !!s.message.attachments?.length',\n negated: false,\n }\n : {\n expression:\n 's.message.role !== \"user\" || !s.message.attachments?.length',\n negated: false,\n },\n hasContent: (v) => ({\n expression: \"s.message.parts.length > 0\",\n negated: v === false,\n }),\n submittedFeedback: (v) => {\n if (v === null) {\n return {\n expression:\n \"(s.message.metadata.submittedFeedback?.type ?? null) === null\",\n negated: false,\n };\n }\n return {\n expression: `s.message.metadata.submittedFeedback?.type === \"${v}\"`,\n negated: false,\n };\n },\n};\n\n// Map ComposerPrimitive.If props to condition expressions\nconst composerPropMap: Record<\n string,\n (value: unknown) => ConditionFragment | null\n> = {\n editing: (v) => ({\n expression: \"s.composer.isEditing\",\n negated: v === false,\n }),\n dictation: (v) => ({\n expression: \"s.composer.dictation != null\",\n negated: v === false,\n }),\n};\n\nconst primitiveMap: Record<\n string,\n Record<string, (value: unknown) => ConditionFragment | null>\n> = {\n ThreadPrimitive: threadPropMap,\n MessagePrimitive: messagePropMap,\n ComposerPrimitive: composerPropMap,\n};\n\n// Map of XPrimitive.Component → fixed condition (no props needed)\nconst fixedConditionMap: Record<string, Record<string, string>> = {\n ThreadPrimitive: {\n Empty: \"s.thread.isEmpty\",\n },\n};\n\n/**\n * Extract the value of a JSX attribute.\n * - Boolean prop (no value): `<X.If user>` → `true`\n * - `{true}` / `{false}`: → `true` / `false`\n * - `{\"positive\"}`: → `\"positive\"`\n * - `{null}`: → `null`\n */\nconst getAttrValue = (j: any, attr: any): unknown => {\n // Boolean attribute (no value), e.g. `<X.If user>`\n if (attr.value === null || attr.value === undefined) {\n return true;\n }\n\n // JSX expression container: `{true}`, `{false}`, `{\"positive\"}`, `{null}`\n if (j.JSXExpressionContainer.check(attr.value)) {\n const expr = attr.value.expression;\n if (j.BooleanLiteral.check(expr)) return expr.value;\n if (j.Literal.check(expr)) {\n if (expr.value === null) return null;\n return expr.value;\n }\n if (j.NullLiteral.check(expr)) return null;\n if (j.Identifier.check(expr) && expr.name === \"undefined\") return undefined;\n }\n\n // String literal\n if (j.StringLiteral.check(attr.value) || j.Literal.check(attr.value)) {\n return attr.value.value;\n }\n\n return undefined;\n};\n\nconst buildConditionString = (fragments: ConditionFragment[]): string => {\n const parts = fragments.map((f) =>\n f.negated ? `!${f.expression}` : f.expression,\n );\n if (parts.length === 1) return parts[0]!;\n return parts.join(\" && \");\n};\n\nconst migratePrimitiveIfToAuiIf = createTransformer(\n ({ j, root, markAsChanged }) => {\n let needsAuiIfImport = false;\n\n // Track which primitive namespaces are imported\n const importedPrimitives = new Set<string>();\n root.find(j.ImportDeclaration).forEach((path: any) => {\n const source = path.value.source.value;\n if (typeof source === \"string\" && source.startsWith(\"@assistant-ui/\")) {\n path.value.specifiers?.forEach((specifier: any) => {\n if (j.ImportSpecifier.check(specifier)) {\n const name = String(\n specifier.local?.name ?? specifier.imported.name,\n );\n if (primitiveMap[name] || fixedConditionMap[name]) {\n importedPrimitives.add(name);\n }\n }\n });\n }\n });\n\n if (importedPrimitives.size === 0) return;\n\n // Process fixed-condition components: <ThreadPrimitive.Empty> → <AuiIf condition={...}>\n root.find(j.JSXOpeningElement).forEach((path: any) => {\n const name = path.value.name;\n if (!j.JSXMemberExpression.check(name)) return;\n if (!j.JSXIdentifier.check(name.object)) return;\n if (!j.JSXIdentifier.check(name.property)) return;\n\n const primitiveName = name.object.name as string;\n const propertyName = name.property.name as string;\n const fixedMap = fixedConditionMap[primitiveName];\n if (!fixedMap) return;\n const conditionBody = fixedMap[propertyName];\n if (!conditionBody) return;\n if (!importedPrimitives.has(primitiveName)) return;\n\n // Only transform if there are no props (other than children, which are implicit)\n const attrs: any[] = path.value.attributes || [];\n if (attrs.length > 0) return;\n\n const arrowFnAst = j(`(s) => ${conditionBody}`)\n .find(j.ArrowFunctionExpression)\n .paths()[0]!.value;\n\n path.value.name = j.jsxIdentifier(\"AuiIf\");\n path.value.attributes = [\n j.jsxAttribute(\n j.jsxIdentifier(\"condition\"),\n j.jsxExpressionContainer(arrowFnAst),\n ),\n ];\n\n needsAuiIfImport = true;\n markAsChanged();\n });\n\n // Update closing elements for fixed-condition components\n root.find(j.JSXClosingElement).forEach((path: any) => {\n const name = path.value.name;\n if (!j.JSXMemberExpression.check(name)) return;\n if (!j.JSXIdentifier.check(name.object)) return;\n if (!j.JSXIdentifier.check(name.property)) return;\n\n const primitiveName = name.object.name as string;\n const propertyName = name.property.name as string;\n const fixedMap = fixedConditionMap[primitiveName];\n if (!fixedMap?.[propertyName]) return;\n if (!importedPrimitives.has(primitiveName)) return;\n\n path.value.name = j.jsxIdentifier(\"AuiIf\");\n markAsChanged();\n });\n\n // Process JSX elements: <ThreadPrimitive.If ...> → <AuiIf condition={...}>\n root.find(j.JSXOpeningElement).forEach((path: any) => {\n const name = path.value.name;\n\n // Check for `<XPrimitive.If ...>`\n if (!j.JSXMemberExpression.check(name)) return;\n if (!j.JSXIdentifier.check(name.object)) return;\n if (!j.JSXIdentifier.check(name.property)) return;\n if (name.property.name !== \"If\") return;\n\n const primitiveName = name.object.name;\n const propMap = primitiveMap[primitiveName];\n if (!propMap) return;\n if (!importedPrimitives.has(primitiveName)) return;\n\n // Extract props\n const attrs: any[] = path.value.attributes || [];\n const fragments: ConditionFragment[] = [];\n let hasUnknownProp = false;\n\n for (const attr of attrs) {\n if (!j.JSXAttribute.check(attr)) {\n // JSX spread attributes — can't migrate\n hasUnknownProp = true;\n continue;\n }\n const propName =\n typeof attr.name.name === \"string\" ? attr.name.name : null;\n if (!propName) continue;\n\n const mapper = propMap[propName];\n if (!mapper) {\n hasUnknownProp = true;\n continue;\n }\n\n const value = getAttrValue(j, attr);\n const fragment = mapper(value);\n if (fragment) {\n fragments.push(fragment);\n }\n }\n\n // If we couldn't map all props, skip this element\n if (hasUnknownProp || fragments.length === 0) return;\n\n const conditionBody = buildConditionString(fragments);\n\n // Parse the arrow function as an expression to get a proper AST node\n const arrowFnAst = j(`(s) => ${conditionBody}`)\n .find(j.ArrowFunctionExpression)\n .paths()[0]!.value;\n\n // Replace <XPrimitive.If ...> with <AuiIf condition={...}>\n path.value.name = j.jsxIdentifier(\"AuiIf\");\n\n // Replace all attributes with a single condition prop\n path.value.attributes = [\n j.jsxAttribute(\n j.jsxIdentifier(\"condition\"),\n j.jsxExpressionContainer(arrowFnAst),\n ),\n ];\n\n needsAuiIfImport = true;\n markAsChanged();\n });\n\n // Update closing elements to match\n root.find(j.JSXClosingElement).forEach((path: any) => {\n const name = path.value.name;\n if (!j.JSXMemberExpression.check(name)) return;\n if (!j.JSXIdentifier.check(name.object)) return;\n if (!j.JSXIdentifier.check(name.property)) return;\n if (name.property.name !== \"If\") return;\n\n const primitiveName = name.object.name;\n if (!primitiveMap[primitiveName]) return;\n if (!importedPrimitives.has(primitiveName)) return;\n\n path.value.name = j.jsxIdentifier(\"AuiIf\");\n markAsChanged();\n });\n\n // Add AuiIf import if needed\n if (needsAuiIfImport) {\n let hasAuiIfImport = false;\n let assistantUiImport: any = null;\n\n root.find(j.ImportDeclaration).forEach((path: any) => {\n const source = path.value.source.value;\n if (typeof source === \"string\" && source.startsWith(\"@assistant-ui/\")) {\n assistantUiImport = path;\n path.value.specifiers?.forEach((specifier: any) => {\n if (\n j.ImportSpecifier.check(specifier) &&\n (specifier.imported.name === \"AuiIf\" ||\n specifier.local?.name === \"AuiIf\")\n ) {\n hasAuiIfImport = true;\n }\n });\n }\n });\n\n if (!hasAuiIfImport && assistantUiImport) {\n assistantUiImport.value.specifiers.push(\n j.importSpecifier(j.identifier(\"AuiIf\")),\n );\n markAsChanged();\n }\n }\n },\n);\n\nexport default migratePrimitiveIfToAuiIf;\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ui-package-split.js","names":[],"sources":["../../../src/codemods/v0-8/ui-package-split.ts"],"sourcesContent":["import { createTransformer } from \"../utils/createTransformer\";\n\nconst reactUIExports: string[] = [\n \"ThreadConfigProvider\",\n \"useThreadConfig\",\n \"ThreadConfig\",\n \"ThreadWelcomeConfig\",\n \"UserMessageConfig\",\n \"AssistantMessageConfig\",\n \"StringsConfig\",\n \"SuggestionConfig\",\n \"ThreadConfigProviderProps\",\n \"AssistantActionBar\",\n \"AssistantMessage\",\n \"AssistantModal\",\n \"BranchPicker\",\n \"Composer\",\n \"MessagePart\",\n \"AttachmentUI\",\n \"EditComposer\",\n \"Thread\",\n \"ThreadList\",\n \"ThreadListItem\",\n \"ThreadWelcome\",\n \"UserMessage\",\n \"makeMarkdownText\",\n \"MakeMarkdownTextProps\",\n \"CodeHeader\",\n];\n\nconst migrateAssistantUI = createTransformer(({ j, root, markAsChanged }) => {\n const sourcesToMigrate: string[] = [\n \"@assistant-ui/react\",\n \"@assistant-ui/react-markdown\",\n ];\n const movedSpecifiers: any[] = [];\n let lastMigratedImportPath: any = null;\n\n root\n .find(j.ImportDeclaration)\n .filter((path: any) => sourcesToMigrate.includes(path.value.source.value))\n .forEach((path: any) => {\n let hadMigratedSpecifiers = false;\n const remainingSpecifiers: any[] = [];\n path.value.specifiers.forEach((specifier: any) => {\n if (\n j.ImportSpecifier.check(specifier) &&\n reactUIExports.includes(specifier.imported.name as string)\n ) {\n movedSpecifiers.push(specifier);\n hadMigratedSpecifiers = true;\n } else {\n remainingSpecifiers.push(specifier);\n }\n });\n if (hadMigratedSpecifiers) {\n lastMigratedImportPath = path;\n }\n if (remainingSpecifiers.length === 0) {\n j(path).remove();\n markAsChanged();\n } else if (remainingSpecifiers.length !== path.value.specifiers.length) {\n path.value.specifiers = remainingSpecifiers;\n markAsChanged();\n }\n });\n\n if (movedSpecifiers.length > 0) {\n const existingReactUIImport = root.find(j.ImportDeclaration, {\n source: { value: \"@assistant-ui/react-ui\" },\n });\n if (existingReactUIImport.size() > 0) {\n existingReactUIImport.forEach((path: any) => {\n movedSpecifiers.forEach((specifier: any) => {\n if (\n !path.value.specifiers.some(\n (s: any) => s.imported.name === specifier.imported.name,\n )\n ) {\n path.value.specifiers.push(specifier);\n }\n });\n });\n } else {\n const newImport = j.importDeclaration(\n movedSpecifiers,\n j.literal(\"@assistant-ui/react-ui\"),\n );\n if (lastMigratedImportPath) {\n j(lastMigratedImportPath).insertAfter(newImport);\n } else {\n const firstImport = root.find(j.ImportDeclaration).at(0);\n if (firstImport.size() > 0) {\n firstImport.insertBefore(newImport);\n } else {\n root.get().node.program.body.unshift(newImport);\n }\n }\n }\n markAsChanged();\n }\n\n const cssReplacements: Record<string, string> = {\n \"@assistant-ui/react/styles/index.css\":\n \"@assistant-ui/react-ui/styles/index.css\",\n \"@assistant-ui/react/styles/modal.css\":\n \"@assistant-ui/react-ui/styles/modal.css\",\n \"@assistant-ui/react-markdown/styles/markdown.css\":\n \"@assistant-ui/react-ui/styles/markdown.css\",\n };\n\n root.find(j.ImportDeclaration).forEach((path: any) => {\n const sourceValue: string = path.value.source.value;\n if (cssReplacements[sourceValue]) {\n path.value.source = j.literal(cssReplacements[sourceValue]);\n markAsChanged();\n }\n });\n\n let removedMarkdownPlugin = false;\n root\n .find(j.CallExpression, { callee: { name: \"require\" } })\n .filter((path: any) => {\n const arg = path.value.arguments[0];\n return (\n arg &&\n (arg.type === \"Literal\" || arg.type === \"StringLiteral\") &&\n arg.value === \"@assistant-ui/react-markdown/tailwindcss\"\n );\n })\n .forEach((path: any) => {\n removedMarkdownPlugin = true;\n const parent = path.parentPath;\n if (parent?.value && parent.value.type === \"VariableDeclarator\") {\n const varDecl = parent.parentPath;\n if (\n varDecl?.value.declarations &&\n varDecl.value.declarations.length === 1\n ) {\n j(varDecl).remove();\n } else {\n varDecl.value.declarations = varDecl.value.declarations.filter(\n (decl: any) => decl !== parent.value,\n );\n }\n markAsChanged();\n } else {\n j(path).remove();\n markAsChanged();\n }\n });\n\n root\n .find(j.CallExpression, { callee: { name: \"require\" } })\n .filter((path: any) => {\n const arg = path.value.arguments[0];\n return (\n arg &&\n (arg.type === \"Literal\" || arg.type === \"StringLiteral\") &&\n arg.value === \"@assistant-ui/react/tailwindcss\"\n );\n })\n .forEach((path: any) => {\n path.value.arguments[0].value = \"@assistant-ui/react-ui/tailwindcss\";\n markAsChanged();\n if (removedMarkdownPlugin) {\n if (\n path.parentPath?.value &&\n path.parentPath.value.type === \"CallExpression\" &&\n path.parentPath.value.arguments.length > 0\n ) {\n const configObj = path.parentPath.value.arguments[0];\n if (configObj && configObj.type === \"ObjectExpression\") {\n const componentsProp = configObj.properties.find((prop: any) => {\n return (\n (prop.key.name === \"components\" ||\n prop.key.value === \"components\") &&\n prop.value.type === \"ArrayExpression\"\n );\n });\n if (componentsProp) {\n const componentsArray = componentsProp.value.elements;\n const hasMarkdown = componentsArray.some(\n (el: any) => el.type === \"Literal\" && el.value === \"markdown\",\n );\n if (!hasMarkdown) {\n componentsArray.push(j.literal(\"markdown\"));\n markAsChanged();\n }\n }\n }\n }\n }\n });\n});\n\nexport default migrateAssistantUI;\n"],"mappings":";;AAEA,MAAM,iBAA2B;CAC/B;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF;AAEA,MAAM,qBAAqB,mBAAmB,EAAE,GAAG,MAAM,oBAAoB;CAC3E,MAAM,mBAA6B,CACjC,uBACA,8BACF;CACA,MAAM,kBAAyB,CAAC;CAChC,IAAI,yBAA8B;CAElC,KACG,KAAK,EAAE,iBAAiB,
|
|
1
|
+
{"version":3,"file":"ui-package-split.js","names":[],"sources":["../../../src/codemods/v0-8/ui-package-split.ts"],"sourcesContent":["import { createTransformer } from \"../utils/createTransformer\";\n\nconst reactUIExports: string[] = [\n \"ThreadConfigProvider\",\n \"useThreadConfig\",\n \"ThreadConfig\",\n \"ThreadWelcomeConfig\",\n \"UserMessageConfig\",\n \"AssistantMessageConfig\",\n \"StringsConfig\",\n \"SuggestionConfig\",\n \"ThreadConfigProviderProps\",\n \"AssistantActionBar\",\n \"AssistantMessage\",\n \"AssistantModal\",\n \"BranchPicker\",\n \"Composer\",\n \"MessagePart\",\n \"AttachmentUI\",\n \"EditComposer\",\n \"Thread\",\n \"ThreadList\",\n \"ThreadListItem\",\n \"ThreadWelcome\",\n \"UserMessage\",\n \"makeMarkdownText\",\n \"MakeMarkdownTextProps\",\n \"CodeHeader\",\n];\n\nconst migrateAssistantUI = createTransformer(({ j, root, markAsChanged }) => {\n const sourcesToMigrate: string[] = [\n \"@assistant-ui/react\",\n \"@assistant-ui/react-markdown\",\n ];\n const movedSpecifiers: any[] = [];\n let lastMigratedImportPath: any = null;\n\n root\n .find(j.ImportDeclaration)\n .filter((path: any) => sourcesToMigrate.includes(path.value.source.value))\n .forEach((path: any) => {\n let hadMigratedSpecifiers = false;\n const remainingSpecifiers: any[] = [];\n path.value.specifiers.forEach((specifier: any) => {\n if (\n j.ImportSpecifier.check(specifier) &&\n reactUIExports.includes(specifier.imported.name as string)\n ) {\n movedSpecifiers.push(specifier);\n hadMigratedSpecifiers = true;\n } else {\n remainingSpecifiers.push(specifier);\n }\n });\n if (hadMigratedSpecifiers) {\n lastMigratedImportPath = path;\n }\n if (remainingSpecifiers.length === 0) {\n j(path).remove();\n markAsChanged();\n } else if (remainingSpecifiers.length !== path.value.specifiers.length) {\n path.value.specifiers = remainingSpecifiers;\n markAsChanged();\n }\n });\n\n if (movedSpecifiers.length > 0) {\n const existingReactUIImport = root.find(j.ImportDeclaration, {\n source: { value: \"@assistant-ui/react-ui\" },\n });\n if (existingReactUIImport.size() > 0) {\n existingReactUIImport.forEach((path: any) => {\n movedSpecifiers.forEach((specifier: any) => {\n if (\n !path.value.specifiers.some(\n (s: any) => s.imported.name === specifier.imported.name,\n )\n ) {\n path.value.specifiers.push(specifier);\n }\n });\n });\n } else {\n const newImport = j.importDeclaration(\n movedSpecifiers,\n j.literal(\"@assistant-ui/react-ui\"),\n );\n if (lastMigratedImportPath) {\n j(lastMigratedImportPath).insertAfter(newImport);\n } else {\n const firstImport = root.find(j.ImportDeclaration).at(0);\n if (firstImport.size() > 0) {\n firstImport.insertBefore(newImport);\n } else {\n root.get().node.program.body.unshift(newImport);\n }\n }\n }\n markAsChanged();\n }\n\n const cssReplacements: Record<string, string> = {\n \"@assistant-ui/react/styles/index.css\":\n \"@assistant-ui/react-ui/styles/index.css\",\n \"@assistant-ui/react/styles/modal.css\":\n \"@assistant-ui/react-ui/styles/modal.css\",\n \"@assistant-ui/react-markdown/styles/markdown.css\":\n \"@assistant-ui/react-ui/styles/markdown.css\",\n };\n\n root.find(j.ImportDeclaration).forEach((path: any) => {\n const sourceValue: string = path.value.source.value;\n if (cssReplacements[sourceValue]) {\n path.value.source = j.literal(cssReplacements[sourceValue]);\n markAsChanged();\n }\n });\n\n let removedMarkdownPlugin = false;\n root\n .find(j.CallExpression, { callee: { name: \"require\" } })\n .filter((path: any) => {\n const arg = path.value.arguments[0];\n return (\n arg &&\n (arg.type === \"Literal\" || arg.type === \"StringLiteral\") &&\n arg.value === \"@assistant-ui/react-markdown/tailwindcss\"\n );\n })\n .forEach((path: any) => {\n removedMarkdownPlugin = true;\n const parent = path.parentPath;\n if (parent?.value && parent.value.type === \"VariableDeclarator\") {\n const varDecl = parent.parentPath;\n if (\n varDecl?.value.declarations &&\n varDecl.value.declarations.length === 1\n ) {\n j(varDecl).remove();\n } else {\n varDecl.value.declarations = varDecl.value.declarations.filter(\n (decl: any) => decl !== parent.value,\n );\n }\n markAsChanged();\n } else {\n j(path).remove();\n markAsChanged();\n }\n });\n\n root\n .find(j.CallExpression, { callee: { name: \"require\" } })\n .filter((path: any) => {\n const arg = path.value.arguments[0];\n return (\n arg &&\n (arg.type === \"Literal\" || arg.type === \"StringLiteral\") &&\n arg.value === \"@assistant-ui/react/tailwindcss\"\n );\n })\n .forEach((path: any) => {\n path.value.arguments[0].value = \"@assistant-ui/react-ui/tailwindcss\";\n markAsChanged();\n if (removedMarkdownPlugin) {\n if (\n path.parentPath?.value &&\n path.parentPath.value.type === \"CallExpression\" &&\n path.parentPath.value.arguments.length > 0\n ) {\n const configObj = path.parentPath.value.arguments[0];\n if (configObj && configObj.type === \"ObjectExpression\") {\n const componentsProp = configObj.properties.find((prop: any) => {\n return (\n (prop.key.name === \"components\" ||\n prop.key.value === \"components\") &&\n prop.value.type === \"ArrayExpression\"\n );\n });\n if (componentsProp) {\n const componentsArray = componentsProp.value.elements;\n const hasMarkdown = componentsArray.some(\n (el: any) => el.type === \"Literal\" && el.value === \"markdown\",\n );\n if (!hasMarkdown) {\n componentsArray.push(j.literal(\"markdown\"));\n markAsChanged();\n }\n }\n }\n }\n }\n });\n});\n\nexport default migrateAssistantUI;\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"edge-package-split.js","names":[],"sources":["../../../src/codemods/v0-9/edge-package-split.ts"],"sourcesContent":["import { createTransformer } from \"../utils/createTransformer\";\n\n// Chat runtime and converter exports moved to react-ai-sdk\nconst reactAiSdkExports: string[] = [\n // Chat Runtime (replaces edge runtime)\n \"useChatRuntime\",\n\n // Core Types\n \"CoreMessage\",\n \"CoreUserMessage\",\n \"CoreAssistantMessage\",\n \"CoreSystemMessage\",\n \"CoreUserMessagePart\",\n \"CoreAssistantMessagePart\",\n \"CoreToolCallMessagePart\",\n\n // Core message converters\n \"fromCoreMessages\",\n \"fromCoreMessage\",\n \"toCoreMessages\",\n \"toCoreMessage\",\n\n // Language model converters\n \"toLanguageModelMessages\",\n \"toLanguageModelTools\",\n \"fromLanguageModelMessages\",\n \"fromLanguageModelTools\",\n \"useDangerousInBrowserRuntime\",\n];\n\nconst migrateToEdgePackage = createTransformer(({ j, root, markAsChanged }) => {\n const sourcesToMigrate: string[] = [\"@assistant-ui/react\"];\n const movedAiSdkSpecifiers: any[] = [];\n let lastMigratedImportPath: any = null;\n\n root\n .find(j.ImportDeclaration)\n .filter((path: any) => sourcesToMigrate.includes(path.value.source.value))\n .forEach((path: any) => {\n let hadMigratedSpecifiers = false;\n const remainingSpecifiers: any[] = [];\n path.value.specifiers.forEach((specifier: any) => {\n if (\n j.ImportSpecifier.check(specifier) &&\n reactAiSdkExports.includes(specifier.imported.name as string)\n ) {\n movedAiSdkSpecifiers.push(specifier);\n hadMigratedSpecifiers = true;\n } else {\n remainingSpecifiers.push(specifier);\n }\n });\n if (hadMigratedSpecifiers) {\n lastMigratedImportPath = path;\n }\n if (remainingSpecifiers.length === 0) {\n j(path).remove();\n markAsChanged();\n } else if (remainingSpecifiers.length !== path.value.specifiers.length) {\n path.value.specifiers = remainingSpecifiers;\n markAsChanged();\n }\n });\n\n // Add imports for react-ai-sdk (all edge-related imports now go here)\n if (movedAiSdkSpecifiers.length > 0) {\n const existingAiSdkImport = root.find(j.ImportDeclaration, {\n source: { value: \"@assistant-ui/react-ai-sdk\" },\n });\n if (existingAiSdkImport.size() > 0) {\n existingAiSdkImport.forEach((path: any) => {\n movedAiSdkSpecifiers.forEach((specifier: any) => {\n if (\n !path.value.specifiers.some(\n (s: any) => s.imported.name === specifier.imported.name,\n )\n ) {\n path.value.specifiers.push(specifier);\n }\n });\n });\n } else {\n const newImport = j.importDeclaration(\n movedAiSdkSpecifiers,\n j.literal(\"@assistant-ui/react-ai-sdk\"),\n );\n if (lastMigratedImportPath) {\n j(lastMigratedImportPath).insertAfter(newImport);\n } else {\n const firstImport = root.find(j.ImportDeclaration).at(0);\n if (firstImport.size() > 0) {\n firstImport.insertBefore(newImport);\n } else {\n root.get().node.program.body.unshift(newImport);\n }\n }\n }\n markAsChanged();\n }\n\n // Migrate imports from edge/converters\n root.find(j.ImportDeclaration).forEach((path: any) => {\n const sourceValue: string = path.value.source.value;\n if (\n sourceValue.startsWith(\"@assistant-ui/react/\") &&\n (sourceValue.includes(\"edge/\") ||\n sourceValue.includes(\"dangerous-in-browser/\"))\n ) {\n path.value.source = j.literal(\n sourceValue.replace(\n \"@assistant-ui/react/\",\n \"@assistant-ui/react-ai-sdk/\",\n ),\n );\n markAsChanged();\n }\n });\n\n // Migrate language model converter imports from react-edge to react-ai-sdk\n root.find(j.ImportDeclaration).forEach((path: any) => {\n const sourceValue: string = path.value.source.value;\n if (\n sourceValue === \"@assistant-ui/react-edge\" ||\n sourceValue === \"@assistant-ui/react\"\n ) {\n let hasLanguageModelConverters = false;\n const remainingSpecifiers: any[] = [];\n const aiSdkSpecifiers: any[] = [];\n\n path.value.specifiers.forEach((specifier: any) => {\n if (\n j.ImportSpecifier.check(specifier) &&\n reactAiSdkExports.includes(specifier.imported.name as string)\n ) {\n aiSdkSpecifiers.push(specifier);\n hasLanguageModelConverters = true;\n } else {\n remainingSpecifiers.push(specifier);\n }\n });\n\n if (hasLanguageModelConverters) {\n if (remainingSpecifiers.length === 0) {\n j(path).remove();\n } else {\n path.value.specifiers = remainingSpecifiers;\n }\n\n const existingAiSdkImport = root.find(j.ImportDeclaration, {\n source: { value: \"@assistant-ui/react-ai-sdk\" },\n });\n\n if (existingAiSdkImport.size() > 0) {\n existingAiSdkImport.forEach((importPath: any) => {\n aiSdkSpecifiers.forEach((specifier: any) => {\n if (\n !importPath.value.specifiers.some(\n (s: any) => s.imported.name === specifier.imported.name,\n )\n ) {\n importPath.value.specifiers.push(specifier);\n }\n });\n });\n } else {\n const newImport = j.importDeclaration(\n aiSdkSpecifiers,\n j.literal(\"@assistant-ui/react-ai-sdk\"),\n );\n j(path).insertAfter(newImport);\n }\n\n markAsChanged();\n }\n }\n });\n});\n\nexport default migrateToEdgePackage;\n"],"mappings":";;AAGA,MAAM,oBAA8B;CAElC;CAGA;CACA;CACA;CACA;CACA;CACA;CACA;CAGA;CACA;CACA;CACA;CAGA;CACA;CACA;CACA;CACA;AACF;AAEA,MAAM,uBAAuB,mBAAmB,EAAE,GAAG,MAAM,oBAAoB;CAC7E,MAAM,mBAA6B,CAAC,qBAAqB;CACzD,MAAM,uBAA8B,CAAC;CACrC,IAAI,yBAA8B;CAElC,KACG,KAAK,EAAE,iBAAiB,
|
|
1
|
+
{"version":3,"file":"edge-package-split.js","names":[],"sources":["../../../src/codemods/v0-9/edge-package-split.ts"],"sourcesContent":["import { createTransformer } from \"../utils/createTransformer\";\n\n// Chat runtime and converter exports moved to react-ai-sdk\nconst reactAiSdkExports: string[] = [\n // Chat Runtime (replaces edge runtime)\n \"useChatRuntime\",\n\n // Core Types\n \"CoreMessage\",\n \"CoreUserMessage\",\n \"CoreAssistantMessage\",\n \"CoreSystemMessage\",\n \"CoreUserMessagePart\",\n \"CoreAssistantMessagePart\",\n \"CoreToolCallMessagePart\",\n\n // Core message converters\n \"fromCoreMessages\",\n \"fromCoreMessage\",\n \"toCoreMessages\",\n \"toCoreMessage\",\n\n // Language model converters\n \"toLanguageModelMessages\",\n \"toLanguageModelTools\",\n \"fromLanguageModelMessages\",\n \"fromLanguageModelTools\",\n \"useDangerousInBrowserRuntime\",\n];\n\nconst migrateToEdgePackage = createTransformer(({ j, root, markAsChanged }) => {\n const sourcesToMigrate: string[] = [\"@assistant-ui/react\"];\n const movedAiSdkSpecifiers: any[] = [];\n let lastMigratedImportPath: any = null;\n\n root\n .find(j.ImportDeclaration)\n .filter((path: any) => sourcesToMigrate.includes(path.value.source.value))\n .forEach((path: any) => {\n let hadMigratedSpecifiers = false;\n const remainingSpecifiers: any[] = [];\n path.value.specifiers.forEach((specifier: any) => {\n if (\n j.ImportSpecifier.check(specifier) &&\n reactAiSdkExports.includes(specifier.imported.name as string)\n ) {\n movedAiSdkSpecifiers.push(specifier);\n hadMigratedSpecifiers = true;\n } else {\n remainingSpecifiers.push(specifier);\n }\n });\n if (hadMigratedSpecifiers) {\n lastMigratedImportPath = path;\n }\n if (remainingSpecifiers.length === 0) {\n j(path).remove();\n markAsChanged();\n } else if (remainingSpecifiers.length !== path.value.specifiers.length) {\n path.value.specifiers = remainingSpecifiers;\n markAsChanged();\n }\n });\n\n // Add imports for react-ai-sdk (all edge-related imports now go here)\n if (movedAiSdkSpecifiers.length > 0) {\n const existingAiSdkImport = root.find(j.ImportDeclaration, {\n source: { value: \"@assistant-ui/react-ai-sdk\" },\n });\n if (existingAiSdkImport.size() > 0) {\n existingAiSdkImport.forEach((path: any) => {\n movedAiSdkSpecifiers.forEach((specifier: any) => {\n if (\n !path.value.specifiers.some(\n (s: any) => s.imported.name === specifier.imported.name,\n )\n ) {\n path.value.specifiers.push(specifier);\n }\n });\n });\n } else {\n const newImport = j.importDeclaration(\n movedAiSdkSpecifiers,\n j.literal(\"@assistant-ui/react-ai-sdk\"),\n );\n if (lastMigratedImportPath) {\n j(lastMigratedImportPath).insertAfter(newImport);\n } else {\n const firstImport = root.find(j.ImportDeclaration).at(0);\n if (firstImport.size() > 0) {\n firstImport.insertBefore(newImport);\n } else {\n root.get().node.program.body.unshift(newImport);\n }\n }\n }\n markAsChanged();\n }\n\n // Migrate imports from edge/converters\n root.find(j.ImportDeclaration).forEach((path: any) => {\n const sourceValue: string = path.value.source.value;\n if (\n sourceValue.startsWith(\"@assistant-ui/react/\") &&\n (sourceValue.includes(\"edge/\") ||\n sourceValue.includes(\"dangerous-in-browser/\"))\n ) {\n path.value.source = j.literal(\n sourceValue.replace(\n \"@assistant-ui/react/\",\n \"@assistant-ui/react-ai-sdk/\",\n ),\n );\n markAsChanged();\n }\n });\n\n // Migrate language model converter imports from react-edge to react-ai-sdk\n root.find(j.ImportDeclaration).forEach((path: any) => {\n const sourceValue: string = path.value.source.value;\n if (\n sourceValue === \"@assistant-ui/react-edge\" ||\n sourceValue === \"@assistant-ui/react\"\n ) {\n let hasLanguageModelConverters = false;\n const remainingSpecifiers: any[] = [];\n const aiSdkSpecifiers: any[] = [];\n\n path.value.specifiers.forEach((specifier: any) => {\n if (\n j.ImportSpecifier.check(specifier) &&\n reactAiSdkExports.includes(specifier.imported.name as string)\n ) {\n aiSdkSpecifiers.push(specifier);\n hasLanguageModelConverters = true;\n } else {\n remainingSpecifiers.push(specifier);\n }\n });\n\n if (hasLanguageModelConverters) {\n if (remainingSpecifiers.length === 0) {\n j(path).remove();\n } else {\n path.value.specifiers = remainingSpecifiers;\n }\n\n const existingAiSdkImport = root.find(j.ImportDeclaration, {\n source: { value: \"@assistant-ui/react-ai-sdk\" },\n });\n\n if (existingAiSdkImport.size() > 0) {\n existingAiSdkImport.forEach((importPath: any) => {\n aiSdkSpecifiers.forEach((specifier: any) => {\n if (\n !importPath.value.specifiers.some(\n (s: any) => s.imported.name === specifier.imported.name,\n )\n ) {\n importPath.value.specifiers.push(specifier);\n }\n });\n });\n } else {\n const newImport = j.importDeclaration(\n aiSdkSpecifiers,\n j.literal(\"@assistant-ui/react-ai-sdk\"),\n );\n j(path).insertAfter(newImport);\n }\n\n markAsChanged();\n }\n }\n });\n});\n\nexport default migrateToEdgePackage;\n"],"mappings":"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"}
|
package/dist/commands/add.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"add.js","names":[],"sources":["../../src/commands/add.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport { logger } from \"../lib/utils/logger\";\nimport { hasConfig } from \"../lib/utils/config\";\nimport {\n dlxCommand,\n resolvePackageManager,\n resolvePackageManagerForCwd,\n type PackageManagerName,\n} from \"../lib/create-project\";\nimport { runSpawn, SpawnExitError } from \"../lib/run-spawn\";\n\nconst REGISTRY_BASE_URL = \"https://r.assistant-ui.com\";\n\nexport interface AddComponentsPlan {\n command: string;\n args: string[];\n}\n\nexport function createAddComponentsPlan(params: {\n components: string[];\n packageManager: PackageManagerName;\n yes?: boolean;\n overwrite?: boolean;\n cwd?: string;\n path?: string;\n}): AddComponentsPlan {\n const componentsToAdd = params.components.map((c) => {\n if (!/^[a-zA-Z0-9-/]+$/.test(c)) {\n throw new Error(`Invalid component name: ${c}`);\n }\n return `${REGISTRY_BASE_URL}/${encodeURIComponent(c)}.json`;\n });\n\n const [command, dlxArgs] = dlxCommand(params.packageManager);\n const args = [...dlxArgs, \"shadcn@latest\", \"add\", ...componentsToAdd];\n\n // For npm, dlxArgs may already include `--yes` for npx auto-install.\n // This flag is for shadcn's own confirmation prompt.\n if (params.yes) args.push(\"--yes\");\n if (params.overwrite) args.push(\"--overwrite\");\n if (params.cwd) args.push(\"--cwd\", params.cwd);\n if (params.path) args.push(\"--path\", params.path);\n\n return { command, args };\n}\n\nexport const add = new Command()\n .name(\"add\")\n .description(\"add a component to your project\")\n .argument(\"<components...>\", \"the components to add\")\n .option(\"-y, --yes\", \"skip confirmation prompt.\", true)\n .option(\"-o, --overwrite\", \"overwrite existing files.\", false)\n .option(\n \"-c, --cwd <cwd>\",\n \"the working directory. defaults to the current directory.\",\n process.cwd(),\n )\n .option(\"-p, --path <path>\", \"the path to add the component to.\")\n .option(\"--use-npm\", \"explicitly use npm\")\n .option(\"--use-pnpm\", \"explicitly use pnpm\")\n .option(\"--use-yarn\", \"explicitly use yarn\")\n .option(\"--use-bun\", \"explicitly use bun\")\n .action(async (components: string[], opts) => {\n // Check if project is initialized\n if (!hasConfig(opts.cwd)) {\n logger.warn(\n \"It looks like you haven't initialized your project yet. Run 'assistant-ui init' first.\",\n );\n logger.break();\n }\n\n logger.step(`Adding ${components.length} component(s)...`);\n\n const packageManager = await resolvePackageManagerForCwd(\n opts.cwd,\n resolvePackageManager(opts),\n );\n const { command, args } = createAddComponentsPlan({\n components,\n packageManager,\n yes: opts.yes,\n overwrite: opts.overwrite,\n cwd: opts.cwd,\n path: opts.path,\n });\n\n try {\n await runSpawn(command, args, opts.cwd);\n } catch (error) {\n if (error instanceof SpawnExitError) {\n logger.error(`Process exited with code ${error.code}`);\n process.exit(error.code);\n }\n const message = error instanceof Error ? error.message : String(error);\n logger.error(`Failed to add components: ${message}`);\n process.exit(1);\n }\n\n logger.success(\"Components added successfully!\");\n });\n"],"mappings":";;;;;;AAWA,MAAM,oBAAoB;AAO1B,SAAgB,wBAAwB,QAOlB;CACpB,MAAM,kBAAkB,OAAO,WAAW,KAAK,MAAM;EACnD,IAAI,CAAC,mBAAmB,KAAK,CAAC,GAC5B,MAAM,IAAI,MAAM,2BAA2B,GAAG;EAEhD,OAAO,GAAG,kBAAkB,GAAG,mBAAmB,CAAC,EAAE;CACvD,CAAC;CAED,MAAM,CAAC,SAAS,WAAW,WAAW,OAAO,cAAc;CAC3D,MAAM,OAAO;EAAC,GAAG;EAAS;EAAiB;EAAO,GAAG;CAAe;CAIpE,IAAI,OAAO,KAAK,KAAK,KAAK,OAAO;CACjC,IAAI,OAAO,WAAW,KAAK,KAAK,aAAa;CAC7C,IAAI,OAAO,KAAK,KAAK,KAAK,SAAS,OAAO,GAAG;CAC7C,IAAI,OAAO,MAAM,KAAK,KAAK,UAAU,OAAO,IAAI;CAEhD,OAAO;EAAE;EAAS;CAAK;AACzB;AAEA,MAAa,MAAM,IAAI,QAAQ,
|
|
1
|
+
{"version":3,"file":"add.js","names":[],"sources":["../../src/commands/add.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport { logger } from \"../lib/utils/logger\";\nimport { hasConfig } from \"../lib/utils/config\";\nimport {\n dlxCommand,\n resolvePackageManager,\n resolvePackageManagerForCwd,\n type PackageManagerName,\n} from \"../lib/create-project\";\nimport { runSpawn, SpawnExitError } from \"../lib/run-spawn\";\n\nconst REGISTRY_BASE_URL = \"https://r.assistant-ui.com\";\n\nexport interface AddComponentsPlan {\n command: string;\n args: string[];\n}\n\nexport function createAddComponentsPlan(params: {\n components: string[];\n packageManager: PackageManagerName;\n yes?: boolean;\n overwrite?: boolean;\n cwd?: string;\n path?: string;\n}): AddComponentsPlan {\n const componentsToAdd = params.components.map((c) => {\n if (!/^[a-zA-Z0-9-/]+$/.test(c)) {\n throw new Error(`Invalid component name: ${c}`);\n }\n return `${REGISTRY_BASE_URL}/${encodeURIComponent(c)}.json`;\n });\n\n const [command, dlxArgs] = dlxCommand(params.packageManager);\n const args = [...dlxArgs, \"shadcn@latest\", \"add\", ...componentsToAdd];\n\n // For npm, dlxArgs may already include `--yes` for npx auto-install.\n // This flag is for shadcn's own confirmation prompt.\n if (params.yes) args.push(\"--yes\");\n if (params.overwrite) args.push(\"--overwrite\");\n if (params.cwd) args.push(\"--cwd\", params.cwd);\n if (params.path) args.push(\"--path\", params.path);\n\n return { command, args };\n}\n\nexport const add = new Command()\n .name(\"add\")\n .description(\"add a component to your project\")\n .argument(\"<components...>\", \"the components to add\")\n .option(\"-y, --yes\", \"skip confirmation prompt.\", true)\n .option(\"-o, --overwrite\", \"overwrite existing files.\", false)\n .option(\n \"-c, --cwd <cwd>\",\n \"the working directory. defaults to the current directory.\",\n process.cwd(),\n )\n .option(\"-p, --path <path>\", \"the path to add the component to.\")\n .option(\"--use-npm\", \"explicitly use npm\")\n .option(\"--use-pnpm\", \"explicitly use pnpm\")\n .option(\"--use-yarn\", \"explicitly use yarn\")\n .option(\"--use-bun\", \"explicitly use bun\")\n .action(async (components: string[], opts) => {\n // Check if project is initialized\n if (!hasConfig(opts.cwd)) {\n logger.warn(\n \"It looks like you haven't initialized your project yet. Run 'assistant-ui init' first.\",\n );\n logger.break();\n }\n\n logger.step(`Adding ${components.length} component(s)...`);\n\n const packageManager = await resolvePackageManagerForCwd(\n opts.cwd,\n resolvePackageManager(opts),\n );\n const { command, args } = createAddComponentsPlan({\n components,\n packageManager,\n yes: opts.yes,\n overwrite: opts.overwrite,\n cwd: opts.cwd,\n path: opts.path,\n });\n\n try {\n await runSpawn(command, args, opts.cwd);\n } catch (error) {\n if (error instanceof SpawnExitError) {\n logger.error(`Process exited with code ${error.code}`);\n process.exit(error.code);\n }\n const message = error instanceof Error ? error.message : String(error);\n logger.error(`Failed to add components: ${message}`);\n process.exit(1);\n }\n\n logger.success(\"Components added successfully!\");\n });\n"],"mappings":";;;;;;AAWA,MAAM,oBAAoB;AAO1B,SAAgB,wBAAwB,QAOlB;CACpB,MAAM,kBAAkB,OAAO,WAAW,KAAK,MAAM;EACnD,IAAI,CAAC,mBAAmB,KAAK,CAAC,GAC5B,MAAM,IAAI,MAAM,2BAA2B,GAAG;EAEhD,OAAO,GAAG,kBAAkB,GAAG,mBAAmB,CAAC,EAAE;CACvD,CAAC;CAED,MAAM,CAAC,SAAS,WAAW,WAAW,OAAO,cAAc;CAC3D,MAAM,OAAO;EAAC,GAAG;EAAS;EAAiB;EAAO,GAAG;CAAe;CAIpE,IAAI,OAAO,KAAK,KAAK,KAAK,OAAO;CACjC,IAAI,OAAO,WAAW,KAAK,KAAK,aAAa;CAC7C,IAAI,OAAO,KAAK,KAAK,KAAK,SAAS,OAAO,GAAG;CAC7C,IAAI,OAAO,MAAM,KAAK,KAAK,UAAU,OAAO,IAAI;CAEhD,OAAO;EAAE;EAAS;CAAK;AACzB;AAEA,MAAa,MAAM,IAAI,QAAQ,CAAC,CAC7B,KAAK,KAAK,CAAC,CACX,YAAY,iCAAiC,CAAC,CAC9C,SAAS,mBAAmB,uBAAuB,CAAC,CACpD,OAAO,aAAa,6BAA6B,IAAI,CAAC,CACtD,OAAO,mBAAmB,6BAA6B,KAAK,CAAC,CAC7D,OACC,mBACA,6DACA,QAAQ,IAAI,CACd,CAAC,CACA,OAAO,qBAAqB,mCAAmC,CAAC,CAChE,OAAO,aAAa,oBAAoB,CAAC,CACzC,OAAO,cAAc,qBAAqB,CAAC,CAC3C,OAAO,cAAc,qBAAqB,CAAC,CAC3C,OAAO,aAAa,oBAAoB,CAAC,CACzC,OAAO,OAAO,YAAsB,SAAS;CAE5C,IAAI,CAAC,UAAU,KAAK,GAAG,GAAG;EACxB,OAAO,KACL,wFACF;EACA,OAAO,MAAM;CACf;CAEA,OAAO,KAAK,UAAU,WAAW,OAAO,iBAAiB;CAMzD,MAAM,EAAE,SAAS,SAAS,wBAAwB;EAChD;EACA,gBAAA,MAN2B,4BAC3B,KAAK,KACL,sBAAsB,IAAI,CAC5B;EAIE,KAAK,KAAK;EACV,WAAW,KAAK;EAChB,KAAK,KAAK;EACV,MAAM,KAAK;CACb,CAAC;CAED,IAAI;EACF,MAAM,SAAS,SAAS,MAAM,KAAK,GAAG;CACxC,SAAS,OAAO;EACd,IAAI,iBAAiB,gBAAgB;GACnC,OAAO,MAAM,4BAA4B,MAAM,MAAM;GACrD,QAAQ,KAAK,MAAM,IAAI;EACzB;EACA,MAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;EACrE,OAAO,MAAM,6BAA6B,SAAS;EACnD,QAAQ,KAAK,CAAC;CAChB;CAEA,OAAO,QAAQ,gCAAgC;AACjD,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent.js","names":[],"sources":["../../src/commands/agent.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport { resolve, dirname } from \"node:path\";\nimport { existsSync } from \"node:fs\";\nimport { fileURLToPath } from \"node:url\";\nimport { launch } from \"@assistant-ui/agent-launcher\";\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\n\nfunction getPluginPath(): string {\n // In dist/, plugin is at ../../plugin relative to dist/commands/agent.js\n // In dev (src/), plugin is at ../../plugin relative to src/commands/\n const candidates = [\n resolve(__dirname, \"..\", \"..\", \"plugin\"),\n resolve(__dirname, \"..\", \"plugin\"),\n ];\n for (const candidate of candidates) {\n if (existsSync(candidate)) return candidate;\n }\n throw new Error(\n `Could not locate the assistant-ui plugin directory. Checked:\\n${candidates.map((c) => ` ${c}`).join(\"\\n\")}`,\n );\n}\n\nexport const agent = new Command()\n .name(\"agent\")\n .description(\"launch Claude Code with assistant-ui skills\")\n .argument(\"<prompt...>\", \"prompt for the agent\")\n .option(\"--dry\", \"print the command instead of running it\")\n .action((promptParts: string[], opts) => {\n const prompt = promptParts.join(\" \");\n\n launch({\n pluginDir: getPluginPath(),\n skillName: \"assistant-ui\",\n prompt,\n dry: opts.dry,\n });\n });\n"],"mappings":";;;;;;AAMA,MAAM,YAAY,QAAQ,cAAc,OAAO,KAAK,GAAG,CAAC;AAExD,SAAS,gBAAwB;CAG/B,MAAM,aAAa,CACjB,QAAQ,WAAW,MAAM,MAAM,QAAQ,GACvC,QAAQ,WAAW,MAAM,QAAQ,CACnC;CACA,KAAK,MAAM,aAAa,YACtB,IAAI,WAAW,SAAS,GAAG,OAAO;CAEpC,MAAM,IAAI,MACR,iEAAiE,WAAW,KAAK,MAAM,KAAK,GAAG,
|
|
1
|
+
{"version":3,"file":"agent.js","names":[],"sources":["../../src/commands/agent.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport { resolve, dirname } from \"node:path\";\nimport { existsSync } from \"node:fs\";\nimport { fileURLToPath } from \"node:url\";\nimport { launch } from \"@assistant-ui/agent-launcher\";\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\n\nfunction getPluginPath(): string {\n // In dist/, plugin is at ../../plugin relative to dist/commands/agent.js\n // In dev (src/), plugin is at ../../plugin relative to src/commands/\n const candidates = [\n resolve(__dirname, \"..\", \"..\", \"plugin\"),\n resolve(__dirname, \"..\", \"plugin\"),\n ];\n for (const candidate of candidates) {\n if (existsSync(candidate)) return candidate;\n }\n throw new Error(\n `Could not locate the assistant-ui plugin directory. Checked:\\n${candidates.map((c) => ` ${c}`).join(\"\\n\")}`,\n );\n}\n\nexport const agent = new Command()\n .name(\"agent\")\n .description(\"launch Claude Code with assistant-ui skills\")\n .argument(\"<prompt...>\", \"prompt for the agent\")\n .option(\"--dry\", \"print the command instead of running it\")\n .action((promptParts: string[], opts) => {\n const prompt = promptParts.join(\" \");\n\n launch({\n pluginDir: getPluginPath(),\n skillName: \"assistant-ui\",\n prompt,\n dry: opts.dry,\n });\n });\n"],"mappings":";;;;;;AAMA,MAAM,YAAY,QAAQ,cAAc,OAAO,KAAK,GAAG,CAAC;AAExD,SAAS,gBAAwB;CAG/B,MAAM,aAAa,CACjB,QAAQ,WAAW,MAAM,MAAM,QAAQ,GACvC,QAAQ,WAAW,MAAM,QAAQ,CACnC;CACA,KAAK,MAAM,aAAa,YACtB,IAAI,WAAW,SAAS,GAAG,OAAO;CAEpC,MAAM,IAAI,MACR,iEAAiE,WAAW,KAAK,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,IAAI,GAC5G;AACF;AAEA,MAAa,QAAQ,IAAI,QAAQ,CAAC,CAC/B,KAAK,OAAO,CAAC,CACb,YAAY,6CAA6C,CAAC,CAC1D,SAAS,eAAe,sBAAsB,CAAC,CAC/C,OAAO,SAAS,yCAAyC,CAAC,CAC1D,QAAQ,aAAuB,SAAS;CACvC,MAAM,SAAS,YAAY,KAAK,GAAG;CAEnC,OAAO;EACL,WAAW,cAAc;EACzB,WAAW;EACX;EACA,KAAK,KAAK;CACZ,CAAC;AACH,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create.js","names":[],"sources":["../../src/commands/create.ts"],"sourcesContent":["import { Command, Option } from \"commander\";\nimport chalk from \"chalk\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport * as p from \"@clack/prompts\";\nimport { logger } from \"../lib/utils/logger\";\nimport {\n dlxCommand,\n downloadProject,\n resolveLatestReleaseRef,\n resolvePackageManager,\n resolvePackageManagerForCwd,\n scaffoldProject,\n transformProject,\n} from \"../lib/create-project\";\nimport { runSpawn, SpawnExitError } from \"../lib/run-spawn\";\nimport {\n buildSkillsAddCommand,\n resolveSkillsInstall,\n} from \"../lib/agent-skill\";\n\nexport interface ProjectMetadata {\n name: string;\n label: string;\n description?: string;\n category: \"template\" | \"example\";\n path: string;\n hasLocalComponents: boolean;\n}\n\nexport const PROJECT_METADATA: ProjectMetadata[] = [\n // Templates\n {\n name: \"default\",\n label: \"Default\",\n description: \"Default template with Vercel AI SDK\",\n category: \"template\",\n path: \"templates/default\",\n hasLocalComponents: false,\n },\n {\n name: \"minimal\",\n label: \"Minimal\",\n description: \"Bare-bones starting point\",\n category: \"template\",\n path: \"templates/minimal\",\n hasLocalComponents: true,\n },\n {\n name: \"cloud\",\n label: \"Cloud\",\n description: \"Cloud-backed persistence starter\",\n category: \"template\",\n path: \"templates/cloud\",\n hasLocalComponents: false,\n },\n {\n name: \"cloud-clerk\",\n label: \"Cloud + Clerk\",\n description: \"Cloud-backed starter with Clerk auth\",\n category: \"template\",\n path: \"templates/cloud-clerk\",\n hasLocalComponents: false,\n },\n {\n name: \"langgraph\",\n label: \"LangGraph\",\n description: \"LangGraph starter template\",\n category: \"template\",\n path: \"templates/langgraph\",\n hasLocalComponents: false,\n },\n {\n name: \"mcp\",\n label: \"MCP\",\n description: \"MCP tools + MCP Apps renderer starter\",\n category: \"template\",\n path: \"templates/mcp\",\n hasLocalComponents: false,\n },\n // Examples\n {\n name: \"with-ag-ui\",\n label: \"AG-UI\",\n description: \"AG-UI protocol integration\",\n category: \"example\",\n path: \"examples/with-ag-ui\",\n hasLocalComponents: false,\n },\n {\n name: \"with-google-adk\",\n label: \"Google ADK\",\n description: \"Google ADK agent integration\",\n category: \"example\",\n path: \"examples/with-google-adk\",\n hasLocalComponents: false,\n },\n {\n name: \"with-ai-sdk-v6\",\n label: \"AI SDK v6\",\n description: \"Vercel AI SDK v6\",\n category: \"example\",\n path: \"examples/with-ai-sdk-v6\",\n hasLocalComponents: false,\n },\n {\n name: \"with-artifacts\",\n label: \"Artifacts\",\n description: \"Artifact rendering\",\n category: \"example\",\n path: \"examples/with-artifacts\",\n hasLocalComponents: false,\n },\n {\n name: \"with-assistant-transport\",\n label: \"Assistant Transport\",\n description: \"Assistant transport protocol\",\n category: \"example\",\n path: \"examples/with-assistant-transport\",\n hasLocalComponents: false,\n },\n {\n name: \"with-chain-of-thought\",\n label: \"Chain of Thought\",\n description: \"Chain-of-thought, tool calls, and source citations\",\n category: \"example\",\n path: \"examples/with-chain-of-thought\",\n hasLocalComponents: false,\n },\n {\n name: \"with-cloud\",\n label: \"Cloud Example\",\n description: \"Cloud integration example\",\n category: \"example\",\n path: \"examples/with-cloud\",\n hasLocalComponents: false,\n },\n {\n name: \"with-custom-thread-list\",\n label: \"Custom Thread List\",\n description: \"Custom thread list UI\",\n category: \"example\",\n path: \"examples/with-custom-thread-list\",\n hasLocalComponents: false,\n },\n {\n name: \"with-elevenlabs-conversational\",\n label: \"ElevenLabs Conversational\",\n description: \"Realtime voice with ElevenLabs\",\n category: \"example\",\n path: \"examples/with-elevenlabs-conversational\",\n hasLocalComponents: true,\n },\n {\n name: \"with-elevenlabs-scribe\",\n label: \"ElevenLabs Scribe\",\n description: \"Audio/speech integration\",\n category: \"example\",\n path: \"examples/with-elevenlabs-scribe\",\n hasLocalComponents: false,\n },\n {\n name: \"with-livekit\",\n label: \"LiveKit Voice\",\n description: \"Realtime voice with LiveKit\",\n category: \"example\",\n path: \"examples/with-livekit\",\n hasLocalComponents: true,\n },\n {\n name: \"with-expo\",\n label: \"Expo\",\n description: \"Expo / React Native\",\n category: \"example\",\n path: \"examples/with-expo\",\n hasLocalComponents: true,\n },\n {\n name: \"with-interactables\",\n label: \"Interactables\",\n description: \"AI-driven interactive UI components\",\n category: \"example\",\n path: \"examples/with-interactables\",\n hasLocalComponents: true,\n },\n {\n name: \"with-external-store\",\n label: \"External Store\",\n description: \"Custom message store\",\n category: \"example\",\n path: \"examples/with-external-store\",\n hasLocalComponents: false,\n },\n {\n name: \"with-ffmpeg\",\n label: \"FFmpeg\",\n description: \"File processing\",\n category: \"example\",\n path: \"examples/with-ffmpeg\",\n hasLocalComponents: false,\n },\n {\n name: \"with-langgraph\",\n label: \"LangGraph Example\",\n description: \"LangGraph integration\",\n category: \"example\",\n path: \"examples/with-langgraph\",\n hasLocalComponents: false,\n },\n {\n name: \"with-react-hook-form\",\n label: \"React Hook Form\",\n description: \"Form integration\",\n category: \"example\",\n path: \"examples/with-react-hook-form\",\n hasLocalComponents: false,\n },\n {\n name: \"with-react-ink\",\n label: \"React Ink\",\n description: \"Terminal UI chat\",\n category: \"example\",\n path: \"examples/with-react-ink\",\n hasLocalComponents: true,\n },\n {\n name: \"with-react-router\",\n label: \"React Router\",\n description: \"React Router v7 + Vite\",\n category: \"example\",\n path: \"examples/with-react-router\",\n hasLocalComponents: false,\n },\n {\n name: \"with-tanstack\",\n label: \"TanStack\",\n description: \"TanStack/React Router + Vite\",\n category: \"example\",\n path: \"examples/with-tanstack\",\n hasLocalComponents: false,\n },\n];\n\n// Examples that exist in the monorepo but are intentionally excluded from the CLI:\n//\n// - waterfall: Still in development, not ready for production.\n// - with-cloud-standalone: For cloud without assistant-ui — not for the\n// assistant-ui CLI.\n// - with-store: In development, not ready for public use of the tap store.\n// - with-tap-runtime: In development, not ready for public use of the tap\n// store.\n\nconst templateNames = PROJECT_METADATA.filter(\n (m) => m.category === \"template\",\n).map((m) => m.name);\n\nconst exampleNames = PROJECT_METADATA.filter(\n (m) => m.category === \"example\",\n).map((m) => m.name);\n\nexport async function resolveProject(params: {\n template?: string;\n example?: string;\n stdinIsTTY?: boolean;\n select?: typeof p.select;\n isCancel?: typeof p.isCancel;\n}): Promise<ProjectMetadata | null> {\n const {\n template,\n example,\n stdinIsTTY = process.stdin.isTTY,\n select = p.select,\n isCancel = p.isCancel,\n } = params;\n\n if (template !== undefined) {\n const meta = PROJECT_METADATA.find(\n (m) => m.name === template && m.category === \"template\",\n );\n if (!meta) {\n logger.error(`Unknown template: ${template}`);\n logger.info(`Available templates: ${templateNames.join(\", \")}`);\n process.exit(1);\n }\n return meta;\n }\n\n if (example !== undefined) {\n const meta = PROJECT_METADATA.find(\n (m) => m.name === example && m.category === \"example\",\n );\n if (!meta) {\n logger.error(`Unknown example: ${example}`);\n logger.info(`Available examples: ${exampleNames.join(\", \")}`);\n process.exit(1);\n }\n return meta;\n }\n\n if (!stdinIsTTY) {\n return PROJECT_METADATA.find((m) => m.name === \"default\")!;\n }\n\n const selected = await select({\n message: \"Select a project to scaffold:\",\n options: [\n {\n value: \"_separator\",\n label: \"────── Starter Templates ──────\",\n disabled: true,\n },\n ...PROJECT_METADATA.filter((m) => m.category === \"template\").map((m) => ({\n value: m.name,\n label: m.label,\n ...(m.description ? { hint: m.description } : {}),\n })),\n {\n value: \"_separator\",\n label: \"────── Feature Examples ──────\",\n disabled: true,\n },\n ...PROJECT_METADATA.filter((m) => m.category === \"example\").map((m) => ({\n value: m.name,\n label: m.label,\n ...(m.description ? { hint: m.description } : {}),\n })),\n ],\n });\n\n if (isCancel(selected)) {\n return null;\n }\n\n const meta = PROJECT_METADATA.find((m) => m.name === selected);\n if (!meta) {\n logger.error(`Unknown selection: ${String(selected)}`);\n process.exit(1);\n }\n return meta;\n}\n\nexport function resolveCreateProjectDirectory(params: {\n projectDirectory?: string;\n stdinIsTTY?: boolean;\n}): string | undefined {\n const { projectDirectory, stdinIsTTY = process.stdin.isTTY } = params;\n\n if (projectDirectory) return projectDirectory;\n if (!stdinIsTTY) return \"my-aui-app\";\n return undefined;\n}\n\nconst PLAYGROUND_PRESET_BASE_URL =\n \"https://www.assistant-ui.com/playground/init\";\n\nexport function resolvePresetUrl(preset: string): string {\n if (preset.startsWith(\"http://\") || preset.startsWith(\"https://\")) {\n return preset;\n }\n return `${PLAYGROUND_PRESET_BASE_URL}?preset=${encodeURIComponent(preset)}`;\n}\n\nexport interface ScaffoldSelectorOptions {\n template?: string;\n example?: string;\n preset?: string;\n native?: boolean;\n ink?: boolean;\n}\n\nexport interface ResolvedScaffoldSelector {\n template?: string;\n example?: string;\n preset?: string;\n}\n\nconst scaffoldSelectorHelp =\n \"Choose one scaffold selector: --template <name>, --example <name>, --native, or --ink. --preset <name-or-url> can be used with --template or by itself.\";\n\nfunction getPresetConflict(opts: ScaffoldSelectorOptions): string | undefined {\n if (opts.example !== undefined) return \"--example\";\n if (opts.native) return \"--native\";\n if (opts.ink) return \"--ink\";\n return undefined;\n}\n\nexport function resolveScaffoldSelector(\n opts: ScaffoldSelectorOptions,\n): ResolvedScaffoldSelector {\n const hasPreset = opts.preset !== undefined;\n const presetConflict = getPresetConflict(opts);\n const selectors = [\n opts.template !== undefined ? \"--template\" : undefined,\n opts.example !== undefined ? \"--example\" : undefined,\n opts.native ? \"--native\" : undefined,\n opts.ink ? \"--ink\" : undefined,\n ].filter((selector): selector is string => selector !== undefined);\n\n if (selectors.length > 1) {\n throw new Error(\n `Only one scaffold selector can be provided (${selectors.join(\", \")}). ${scaffoldSelectorHelp}`,\n );\n }\n\n if (hasPreset && presetConflict) {\n throw new Error(\n `Cannot use --preset with ${presetConflict}. ${scaffoldSelectorHelp}`,\n );\n }\n\n if (opts.native) return { example: \"with-expo\" };\n if (opts.ink) return { example: \"with-react-ink\" };\n\n if (opts.preset !== undefined && opts.template === undefined) {\n return { template: \"default\", preset: opts.preset };\n }\n\n return {\n ...(opts.template !== undefined && { template: opts.template }),\n ...(opts.example !== undefined && { example: opts.example }),\n ...(hasPreset && { preset: opts.preset }),\n };\n}\n\nexport const create = new Command()\n .name(\"create\")\n .description(\"create a new project\")\n .argument(\"[project-directory]\")\n .usage(`${chalk.green(\"[project-directory]\")} [options]`)\n .option(\n \"-t, --template <template>\",\n `template to use (${templateNames.join(\", \")})`,\n )\n .option(\n \"-e, --example <example>\",\n `create from an example (${exampleNames.join(\", \")})`,\n )\n .option(\n \"-p, --preset <name-or-url>\",\n \"preset name or URL (e.g., chatgpt or https://www.assistant-ui.com/playground/init?preset=chatgpt)\",\n )\n .option(\"--use-npm\", \"explicitly use npm\")\n .option(\"--use-pnpm\", \"explicitly use pnpm\")\n .option(\"--use-yarn\", \"explicitly use yarn\")\n .option(\"--use-bun\", \"explicitly use bun\")\n .option(\"--native\", \"create an Expo / React Native project\")\n .option(\"--ink\", \"create a React Ink terminal project\")\n .option(\"--skip-install\", \"skip installing packages\")\n .option(\"--skills\", \"add assistant-ui agent skills for AI coding assistants\")\n .option(\"--no-skills\", \"skip adding assistant-ui agent skills\")\n .addOption(\n new Option(\n \"--debug-source-root <path>\",\n \"copy templates/examples from a local assistant-ui repo root\",\n ).hideHelp(),\n )\n .action(async (projectDirectory, opts) => {\n let scaffoldSelector: ResolvedScaffoldSelector;\n try {\n scaffoldSelector = resolveScaffoldSelector(opts);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n logger.error(message);\n process.exit(1);\n }\n\n const localSourceRoot = opts.debugSourceRoot\n ? path.resolve(opts.debugSourceRoot)\n : undefined;\n\n // Start release ref resolution early (runs during user prompts)\n const refPromise = localSourceRoot\n ? Promise.resolve(undefined)\n : resolveLatestReleaseRef();\n\n // 1. Resolve project directory\n let resolvedProjectDirectory = resolveCreateProjectDirectory({\n projectDirectory,\n });\n\n if (!resolvedProjectDirectory) {\n const result = await p.text({\n message: \"Project name:\",\n placeholder: \"my-aui-app\",\n defaultValue: \"my-aui-app\",\n validate: (value?: string) => {\n const name = (value ?? \"\").trim();\n if (!name) return \"Project name cannot be empty\";\n if (name === \".\" || name === \"..\")\n return \"Project name cannot be . or ..\";\n if (name.includes(\"/\") || name.includes(\"\\\\\"))\n return \"Project name cannot contain path separators\";\n return undefined;\n },\n });\n\n if (p.isCancel(result)) {\n p.cancel(\"Project creation cancelled.\");\n process.exit(0);\n }\n\n resolvedProjectDirectory = result;\n }\n\n // Check directory\n const absoluteProjectDir = path.resolve(resolvedProjectDirectory);\n try {\n const files = fs.readdirSync(absoluteProjectDir);\n if (files.length > 0) {\n logger.error(\n `Directory ${resolvedProjectDirectory} already exists and is not empty`,\n );\n process.exit(1);\n }\n } catch (err: unknown) {\n const code =\n err instanceof Error ? (err as NodeJS.ErrnoException).code : undefined;\n if (code === \"ENOENT\") {\n // Directory doesn't exist — good, proceed\n } else if (code === \"ENOTDIR\") {\n logger.error(\n `${resolvedProjectDirectory} already exists and is not a directory`,\n );\n process.exit(1);\n } else {\n const message = err instanceof Error ? err.message : String(err);\n logger.error(`Cannot access ${resolvedProjectDirectory}: ${message}`);\n process.exit(1);\n }\n }\n\n // 2. Resolve scaffold target\n const project = await resolveProject(scaffoldSelector);\n if (!project) {\n p.cancel(\"Project creation cancelled.\");\n process.exit(0);\n }\n\n const stdinIsTTY = process.stdin.isTTY;\n let installSkills = resolveSkillsInstall({\n skills: opts.skills,\n stdinIsTTY,\n });\n if (installSkills === undefined) {\n const result = await p.confirm({\n message: \"Add assistant-ui agent skills for AI coding assistants?\",\n initialValue: true,\n });\n\n if (p.isCancel(result)) {\n p.cancel(\"Project creation cancelled.\");\n process.exit(0);\n }\n\n installSkills = result;\n }\n\n logger.info(`Creating project from ${project.category}: ${project.label}`);\n logger.break();\n\n const pm = await resolvePackageManagerForCwd(\n path.dirname(absoluteProjectDir),\n resolvePackageManager(opts),\n );\n\n // Clean up partial project directory on unexpected exit (e.g. Ctrl+C)\n const cleanupOnExit = () => {\n fs.rmSync(absoluteProjectDir, { recursive: true, force: true });\n };\n process.once(\"exit\", cleanupOnExit);\n\n try {\n // 3. Resolve latest release ref (started before prompts)\n if (!localSourceRoot) {\n logger.step(\"Resolving latest release...\");\n }\n const ref = await refPromise;\n if (!localSourceRoot && !ref) {\n logger.warn(\"Could not resolve latest release, downloading from HEAD\");\n }\n\n // 4. Scaffold project\n logger.step(\n localSourceRoot\n ? `Copying project from local source: ${localSourceRoot}`\n : \"Downloading project...\",\n );\n try {\n const source = localSourceRoot\n ? { kind: \"local\" as const, rootDir: localSourceRoot }\n : {\n kind: \"github\" as const,\n ref,\n };\n await scaffoldProject(project.path, absoluteProjectDir, source);\n\n // If the template didn't exist at the release tag, retry from HEAD\n if (\n !localSourceRoot &&\n ref &&\n !fs.existsSync(path.join(absoluteProjectDir, \"package.json\"))\n ) {\n fs.rmSync(absoluteProjectDir, { recursive: true, force: true });\n logger.warn(\n \"Template not found at release tag, downloading from HEAD\",\n );\n await downloadProject(project.path, absoluteProjectDir);\n }\n\n // 5. Run transform pipeline\n await transformProject(absoluteProjectDir, {\n hasLocalComponents: project.hasLocalComponents,\n skipInstall: opts.skipInstall,\n packageManager: pm,\n });\n\n if (installSkills) {\n logger.step(\"Adding assistant-ui agent skills...\");\n const [skillsCmd, skillsArgs] = buildSkillsAddCommand(pm, {\n stdinIsTTY,\n });\n try {\n await runSpawn(skillsCmd, skillsArgs, absoluteProjectDir);\n } catch {\n logger.warn(\n `Could not add assistant-ui agent skills. You can add them later with:\\n ${skillsCmd} ${skillsArgs.join(\" \")}`,\n );\n }\n }\n } catch (err) {\n // Clean up partially created project directory\n fs.rmSync(absoluteProjectDir, { recursive: true, force: true });\n throw err;\n }\n\n // 6. Apply preset if provided\n if (scaffoldSelector.preset) {\n const presetUrl = resolvePresetUrl(scaffoldSelector.preset);\n logger.info(\"Applying preset configuration...\");\n logger.break();\n const [dlxCmd, dlxArgs] = dlxCommand(pm);\n try {\n await runSpawn(\n dlxCmd,\n [\n ...dlxArgs,\n \"shadcn@latest\",\n \"add\",\n \"--yes\",\n \"--overwrite\",\n presetUrl,\n ],\n absoluteProjectDir,\n );\n } catch {\n logger.warn(\n `Preset application failed. You can retry manually with:\\n ${dlxCmd} ${[...dlxArgs, \"shadcn@latest\", \"add\", presetUrl].join(\" \")}`,\n );\n }\n }\n\n process.removeListener(\"exit\", cleanupOnExit);\n\n logger.break();\n logger.success(\"Project created successfully!\");\n logger.break();\n const runCmd = pm === \"npm\" ? \"npm run\" : pm;\n let devScript = \"dev\";\n let envFile = \".env.local\";\n try {\n const scaffoldedPkg = JSON.parse(\n fs.readFileSync(\n path.join(absoluteProjectDir, \"package.json\"),\n \"utf-8\",\n ),\n );\n devScript = scaffoldedPkg.scripts?.dev\n ? \"dev\"\n : scaffoldedPkg.scripts?.start\n ? \"start\"\n : \"dev\";\n envFile = scaffoldedPkg.dependencies?.next ? \".env.local\" : \".env\";\n } catch {\n // Fall back to defaults if package.json cannot be read\n }\n\n logger.info(\"Next steps:\");\n logger.info(` cd ${resolvedProjectDirectory}`);\n if (opts.skipInstall) {\n logger.info(` ${pm} install`);\n }\n logger.info(` # Set up your environment variables in ${envFile}`);\n logger.info(` ${runCmd} ${devScript}`);\n } catch (error) {\n if (error instanceof SpawnExitError) {\n logger.error(`Project creation failed with code ${error.code}`);\n process.exit(error.code);\n }\n const message = error instanceof Error ? error.message : String(error);\n logger.error(`Failed to create project: ${message}`);\n process.exit(1);\n }\n });\n"],"mappings":";;;;;;;;;;AA8BA,MAAa,mBAAsC;CAEjD;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CAEA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CAC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"}
|
|
1
|
+
{"version":3,"file":"create.js","names":[],"sources":["../../src/commands/create.ts"],"sourcesContent":["import { Command, Option } from \"commander\";\nimport chalk from \"chalk\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport * as p from \"@clack/prompts\";\nimport { logger } from \"../lib/utils/logger\";\nimport {\n dlxCommand,\n downloadProject,\n resolveLatestReleaseRef,\n resolvePackageManager,\n resolvePackageManagerForCwd,\n scaffoldProject,\n transformProject,\n} from \"../lib/create-project\";\nimport { runSpawn, SpawnExitError } from \"../lib/run-spawn\";\nimport {\n buildSkillsAddCommand,\n resolveSkillsInstall,\n} from \"../lib/agent-skill\";\n\nexport interface ProjectMetadata {\n name: string;\n label: string;\n description?: string;\n category: \"template\" | \"example\";\n path: string;\n hasLocalComponents: boolean;\n}\n\nexport const PROJECT_METADATA: ProjectMetadata[] = [\n // Templates\n {\n name: \"default\",\n label: \"Default\",\n description: \"Default template with Vercel AI SDK\",\n category: \"template\",\n path: \"templates/default\",\n hasLocalComponents: false,\n },\n {\n name: \"minimal\",\n label: \"Minimal\",\n description: \"Bare-bones starting point\",\n category: \"template\",\n path: \"templates/minimal\",\n hasLocalComponents: true,\n },\n {\n name: \"cloud\",\n label: \"Cloud\",\n description: \"Cloud-backed persistence starter\",\n category: \"template\",\n path: \"templates/cloud\",\n hasLocalComponents: false,\n },\n {\n name: \"cloud-clerk\",\n label: \"Cloud + Clerk\",\n description: \"Cloud-backed starter with Clerk auth\",\n category: \"template\",\n path: \"templates/cloud-clerk\",\n hasLocalComponents: false,\n },\n {\n name: \"langgraph\",\n label: \"LangGraph\",\n description: \"LangGraph starter template\",\n category: \"template\",\n path: \"templates/langgraph\",\n hasLocalComponents: false,\n },\n {\n name: \"mcp\",\n label: \"MCP\",\n description: \"MCP tools + MCP Apps renderer starter\",\n category: \"template\",\n path: \"templates/mcp\",\n hasLocalComponents: false,\n },\n // Examples\n {\n name: \"with-ag-ui\",\n label: \"AG-UI\",\n description: \"AG-UI protocol integration\",\n category: \"example\",\n path: \"examples/with-ag-ui\",\n hasLocalComponents: false,\n },\n {\n name: \"with-google-adk\",\n label: \"Google ADK\",\n description: \"Google ADK agent integration\",\n category: \"example\",\n path: \"examples/with-google-adk\",\n hasLocalComponents: false,\n },\n {\n name: \"with-ai-sdk-v6\",\n label: \"AI SDK v6\",\n description: \"Vercel AI SDK v6\",\n category: \"example\",\n path: \"examples/with-ai-sdk-v6\",\n hasLocalComponents: false,\n },\n {\n name: \"with-artifacts\",\n label: \"Artifacts\",\n description: \"Artifact rendering\",\n category: \"example\",\n path: \"examples/with-artifacts\",\n hasLocalComponents: false,\n },\n {\n name: \"with-assistant-transport\",\n label: \"Assistant Transport\",\n description: \"Assistant transport protocol\",\n category: \"example\",\n path: \"examples/with-assistant-transport\",\n hasLocalComponents: false,\n },\n {\n name: \"with-chain-of-thought\",\n label: \"Chain of Thought\",\n description: \"Chain-of-thought, tool calls, and source citations\",\n category: \"example\",\n path: \"examples/with-chain-of-thought\",\n hasLocalComponents: false,\n },\n {\n name: \"with-cloud\",\n label: \"Cloud Example\",\n description: \"Cloud integration example\",\n category: \"example\",\n path: \"examples/with-cloud\",\n hasLocalComponents: false,\n },\n {\n name: \"with-custom-thread-list\",\n label: \"Custom Thread List\",\n description: \"Custom thread list UI\",\n category: \"example\",\n path: \"examples/with-custom-thread-list\",\n hasLocalComponents: false,\n },\n {\n name: \"with-elevenlabs-conversational\",\n label: \"ElevenLabs Conversational\",\n description: \"Realtime voice with ElevenLabs\",\n category: \"example\",\n path: \"examples/with-elevenlabs-conversational\",\n hasLocalComponents: true,\n },\n {\n name: \"with-elevenlabs-scribe\",\n label: \"ElevenLabs Scribe\",\n description: \"Audio/speech integration\",\n category: \"example\",\n path: \"examples/with-elevenlabs-scribe\",\n hasLocalComponents: false,\n },\n {\n name: \"with-livekit\",\n label: \"LiveKit Voice\",\n description: \"Realtime voice with LiveKit\",\n category: \"example\",\n path: \"examples/with-livekit\",\n hasLocalComponents: true,\n },\n {\n name: \"with-expo\",\n label: \"Expo\",\n description: \"Expo / React Native\",\n category: \"example\",\n path: \"examples/with-expo\",\n hasLocalComponents: true,\n },\n {\n name: \"with-interactables\",\n label: \"Interactables\",\n description: \"AI-driven interactive UI components\",\n category: \"example\",\n path: \"examples/with-interactables\",\n hasLocalComponents: true,\n },\n {\n name: \"with-external-store\",\n label: \"External Store\",\n description: \"Custom message store\",\n category: \"example\",\n path: \"examples/with-external-store\",\n hasLocalComponents: false,\n },\n {\n name: \"with-ffmpeg\",\n label: \"FFmpeg\",\n description: \"File processing\",\n category: \"example\",\n path: \"examples/with-ffmpeg\",\n hasLocalComponents: false,\n },\n {\n name: \"with-langgraph\",\n label: \"LangGraph Example\",\n description: \"LangGraph integration\",\n category: \"example\",\n path: \"examples/with-langgraph\",\n hasLocalComponents: false,\n },\n {\n name: \"with-react-hook-form\",\n label: \"React Hook Form\",\n description: \"Form integration\",\n category: \"example\",\n path: \"examples/with-react-hook-form\",\n hasLocalComponents: false,\n },\n {\n name: \"with-react-ink\",\n label: \"React Ink\",\n description: \"Terminal UI chat\",\n category: \"example\",\n path: \"examples/with-react-ink\",\n hasLocalComponents: true,\n },\n {\n name: \"with-react-router\",\n label: \"React Router\",\n description: \"React Router v7 + Vite\",\n category: \"example\",\n path: \"examples/with-react-router\",\n hasLocalComponents: false,\n },\n {\n name: \"with-tanstack\",\n label: \"TanStack\",\n description: \"TanStack/React Router + Vite\",\n category: \"example\",\n path: \"examples/with-tanstack\",\n hasLocalComponents: false,\n },\n];\n\n// Examples that exist in the monorepo but are intentionally excluded from the CLI:\n//\n// - waterfall: Still in development, not ready for production.\n// - with-cloud-standalone: For cloud without assistant-ui — not for the\n// assistant-ui CLI.\n// - with-store: In development, not ready for public use of the tap store.\n// - with-tap-runtime: In development, not ready for public use of the tap\n// store.\n\nconst templateNames = PROJECT_METADATA.filter(\n (m) => m.category === \"template\",\n).map((m) => m.name);\n\nconst exampleNames = PROJECT_METADATA.filter(\n (m) => m.category === \"example\",\n).map((m) => m.name);\n\nexport async function resolveProject(params: {\n template?: string;\n example?: string;\n stdinIsTTY?: boolean;\n select?: typeof p.select;\n isCancel?: typeof p.isCancel;\n}): Promise<ProjectMetadata | null> {\n const {\n template,\n example,\n stdinIsTTY = process.stdin.isTTY,\n select = p.select,\n isCancel = p.isCancel,\n } = params;\n\n if (template !== undefined) {\n const meta = PROJECT_METADATA.find(\n (m) => m.name === template && m.category === \"template\",\n );\n if (!meta) {\n logger.error(`Unknown template: ${template}`);\n logger.info(`Available templates: ${templateNames.join(\", \")}`);\n process.exit(1);\n }\n return meta;\n }\n\n if (example !== undefined) {\n const meta = PROJECT_METADATA.find(\n (m) => m.name === example && m.category === \"example\",\n );\n if (!meta) {\n logger.error(`Unknown example: ${example}`);\n logger.info(`Available examples: ${exampleNames.join(\", \")}`);\n process.exit(1);\n }\n return meta;\n }\n\n if (!stdinIsTTY) {\n return PROJECT_METADATA.find((m) => m.name === \"default\")!;\n }\n\n const selected = await select({\n message: \"Select a project to scaffold:\",\n options: [\n {\n value: \"_separator\",\n label: \"────── Starter Templates ──────\",\n disabled: true,\n },\n ...PROJECT_METADATA.filter((m) => m.category === \"template\").map((m) => ({\n value: m.name,\n label: m.label,\n ...(m.description ? { hint: m.description } : {}),\n })),\n {\n value: \"_separator\",\n label: \"────── Feature Examples ──────\",\n disabled: true,\n },\n ...PROJECT_METADATA.filter((m) => m.category === \"example\").map((m) => ({\n value: m.name,\n label: m.label,\n ...(m.description ? { hint: m.description } : {}),\n })),\n ],\n });\n\n if (isCancel(selected)) {\n return null;\n }\n\n const meta = PROJECT_METADATA.find((m) => m.name === selected);\n if (!meta) {\n logger.error(`Unknown selection: ${String(selected)}`);\n process.exit(1);\n }\n return meta;\n}\n\nexport function resolveCreateProjectDirectory(params: {\n projectDirectory?: string;\n stdinIsTTY?: boolean;\n}): string | undefined {\n const { projectDirectory, stdinIsTTY = process.stdin.isTTY } = params;\n\n if (projectDirectory) return projectDirectory;\n if (!stdinIsTTY) return \"my-aui-app\";\n return undefined;\n}\n\nconst PLAYGROUND_PRESET_BASE_URL =\n \"https://www.assistant-ui.com/playground/init\";\n\nexport function resolvePresetUrl(preset: string): string {\n if (preset.startsWith(\"http://\") || preset.startsWith(\"https://\")) {\n return preset;\n }\n return `${PLAYGROUND_PRESET_BASE_URL}?preset=${encodeURIComponent(preset)}`;\n}\n\nexport interface ScaffoldSelectorOptions {\n template?: string;\n example?: string;\n preset?: string;\n native?: boolean;\n ink?: boolean;\n}\n\nexport interface ResolvedScaffoldSelector {\n template?: string;\n example?: string;\n preset?: string;\n}\n\nconst scaffoldSelectorHelp =\n \"Choose one scaffold selector: --template <name>, --example <name>, --native, or --ink. --preset <name-or-url> can be used with --template or by itself.\";\n\nfunction getPresetConflict(opts: ScaffoldSelectorOptions): string | undefined {\n if (opts.example !== undefined) return \"--example\";\n if (opts.native) return \"--native\";\n if (opts.ink) return \"--ink\";\n return undefined;\n}\n\nexport function resolveScaffoldSelector(\n opts: ScaffoldSelectorOptions,\n): ResolvedScaffoldSelector {\n const hasPreset = opts.preset !== undefined;\n const presetConflict = getPresetConflict(opts);\n const selectors = [\n opts.template !== undefined ? \"--template\" : undefined,\n opts.example !== undefined ? \"--example\" : undefined,\n opts.native ? \"--native\" : undefined,\n opts.ink ? \"--ink\" : undefined,\n ].filter((selector): selector is string => selector !== undefined);\n\n if (selectors.length > 1) {\n throw new Error(\n `Only one scaffold selector can be provided (${selectors.join(\", \")}). ${scaffoldSelectorHelp}`,\n );\n }\n\n if (hasPreset && presetConflict) {\n throw new Error(\n `Cannot use --preset with ${presetConflict}. ${scaffoldSelectorHelp}`,\n );\n }\n\n if (opts.native) return { example: \"with-expo\" };\n if (opts.ink) return { example: \"with-react-ink\" };\n\n if (opts.preset !== undefined && opts.template === undefined) {\n return { template: \"default\", preset: opts.preset };\n }\n\n return {\n ...(opts.template !== undefined && { template: opts.template }),\n ...(opts.example !== undefined && { example: opts.example }),\n ...(hasPreset && { preset: opts.preset }),\n };\n}\n\nexport const create = new Command()\n .name(\"create\")\n .description(\"create a new project\")\n .argument(\"[project-directory]\")\n .usage(`${chalk.green(\"[project-directory]\")} [options]`)\n .option(\n \"-t, --template <template>\",\n `template to use (${templateNames.join(\", \")})`,\n )\n .option(\n \"-e, --example <example>\",\n `create from an example (${exampleNames.join(\", \")})`,\n )\n .option(\n \"-p, --preset <name-or-url>\",\n \"preset name or URL (e.g., chatgpt or https://www.assistant-ui.com/playground/init?preset=chatgpt)\",\n )\n .option(\"--use-npm\", \"explicitly use npm\")\n .option(\"--use-pnpm\", \"explicitly use pnpm\")\n .option(\"--use-yarn\", \"explicitly use yarn\")\n .option(\"--use-bun\", \"explicitly use bun\")\n .option(\"--native\", \"create an Expo / React Native project\")\n .option(\"--ink\", \"create a React Ink terminal project\")\n .option(\"--skip-install\", \"skip installing packages\")\n .option(\"--skills\", \"add assistant-ui agent skills for AI coding assistants\")\n .option(\"--no-skills\", \"skip adding assistant-ui agent skills\")\n .addOption(\n new Option(\n \"--debug-source-root <path>\",\n \"copy templates/examples from a local assistant-ui repo root\",\n ).hideHelp(),\n )\n .action(async (projectDirectory, opts) => {\n let scaffoldSelector: ResolvedScaffoldSelector;\n try {\n scaffoldSelector = resolveScaffoldSelector(opts);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n logger.error(message);\n process.exit(1);\n }\n\n const localSourceRoot = opts.debugSourceRoot\n ? path.resolve(opts.debugSourceRoot)\n : undefined;\n\n // Start release ref resolution early (runs during user prompts)\n const refPromise = localSourceRoot\n ? Promise.resolve(undefined)\n : resolveLatestReleaseRef();\n\n // 1. Resolve project directory\n let resolvedProjectDirectory = resolveCreateProjectDirectory({\n projectDirectory,\n });\n\n if (!resolvedProjectDirectory) {\n const result = await p.text({\n message: \"Project name:\",\n placeholder: \"my-aui-app\",\n defaultValue: \"my-aui-app\",\n validate: (value?: string) => {\n const name = (value ?? \"\").trim();\n if (!name) return \"Project name cannot be empty\";\n if (name === \".\" || name === \"..\")\n return \"Project name cannot be . or ..\";\n if (name.includes(\"/\") || name.includes(\"\\\\\"))\n return \"Project name cannot contain path separators\";\n return undefined;\n },\n });\n\n if (p.isCancel(result)) {\n p.cancel(\"Project creation cancelled.\");\n process.exit(0);\n }\n\n resolvedProjectDirectory = result;\n }\n\n // Check directory\n const absoluteProjectDir = path.resolve(resolvedProjectDirectory);\n try {\n const files = fs.readdirSync(absoluteProjectDir);\n if (files.length > 0) {\n logger.error(\n `Directory ${resolvedProjectDirectory} already exists and is not empty`,\n );\n process.exit(1);\n }\n } catch (err: unknown) {\n const code =\n err instanceof Error ? (err as NodeJS.ErrnoException).code : undefined;\n if (code === \"ENOENT\") {\n // Directory doesn't exist — good, proceed\n } else if (code === \"ENOTDIR\") {\n logger.error(\n `${resolvedProjectDirectory} already exists and is not a directory`,\n );\n process.exit(1);\n } else {\n const message = err instanceof Error ? err.message : String(err);\n logger.error(`Cannot access ${resolvedProjectDirectory}: ${message}`);\n process.exit(1);\n }\n }\n\n // 2. Resolve scaffold target\n const project = await resolveProject(scaffoldSelector);\n if (!project) {\n p.cancel(\"Project creation cancelled.\");\n process.exit(0);\n }\n\n const stdinIsTTY = process.stdin.isTTY;\n let installSkills = resolveSkillsInstall({\n skills: opts.skills,\n stdinIsTTY,\n });\n if (installSkills === undefined) {\n const result = await p.confirm({\n message: \"Add assistant-ui agent skills for AI coding assistants?\",\n initialValue: true,\n });\n\n if (p.isCancel(result)) {\n p.cancel(\"Project creation cancelled.\");\n process.exit(0);\n }\n\n installSkills = result;\n }\n\n logger.info(`Creating project from ${project.category}: ${project.label}`);\n logger.break();\n\n const pm = await resolvePackageManagerForCwd(\n path.dirname(absoluteProjectDir),\n resolvePackageManager(opts),\n );\n\n // Clean up partial project directory on unexpected exit (e.g. Ctrl+C)\n const cleanupOnExit = () => {\n fs.rmSync(absoluteProjectDir, { recursive: true, force: true });\n };\n process.once(\"exit\", cleanupOnExit);\n\n try {\n // 3. Resolve latest release ref (started before prompts)\n if (!localSourceRoot) {\n logger.step(\"Resolving latest release...\");\n }\n const ref = await refPromise;\n if (!localSourceRoot && !ref) {\n logger.warn(\"Could not resolve latest release, downloading from HEAD\");\n }\n\n // 4. Scaffold project\n logger.step(\n localSourceRoot\n ? `Copying project from local source: ${localSourceRoot}`\n : \"Downloading project...\",\n );\n try {\n const source = localSourceRoot\n ? { kind: \"local\" as const, rootDir: localSourceRoot }\n : {\n kind: \"github\" as const,\n ref,\n };\n await scaffoldProject(project.path, absoluteProjectDir, source);\n\n // If the template didn't exist at the release tag, retry from HEAD\n if (\n !localSourceRoot &&\n ref &&\n !fs.existsSync(path.join(absoluteProjectDir, \"package.json\"))\n ) {\n fs.rmSync(absoluteProjectDir, { recursive: true, force: true });\n logger.warn(\n \"Template not found at release tag, downloading from HEAD\",\n );\n await downloadProject(project.path, absoluteProjectDir);\n }\n\n // 5. Run transform pipeline\n await transformProject(absoluteProjectDir, {\n hasLocalComponents: project.hasLocalComponents,\n skipInstall: opts.skipInstall,\n packageManager: pm,\n });\n\n if (installSkills) {\n logger.step(\"Adding assistant-ui agent skills...\");\n const [skillsCmd, skillsArgs] = buildSkillsAddCommand(pm, {\n stdinIsTTY,\n });\n try {\n await runSpawn(skillsCmd, skillsArgs, absoluteProjectDir);\n } catch {\n logger.warn(\n `Could not add assistant-ui agent skills. You can add them later with:\\n ${skillsCmd} ${skillsArgs.join(\" \")}`,\n );\n }\n }\n } catch (err) {\n // Clean up partially created project directory\n fs.rmSync(absoluteProjectDir, { recursive: true, force: true });\n throw err;\n }\n\n // 6. Apply preset if provided\n if (scaffoldSelector.preset) {\n const presetUrl = resolvePresetUrl(scaffoldSelector.preset);\n logger.info(\"Applying preset configuration...\");\n logger.break();\n const [dlxCmd, dlxArgs] = dlxCommand(pm);\n try {\n await runSpawn(\n dlxCmd,\n [\n ...dlxArgs,\n \"shadcn@latest\",\n \"add\",\n \"--yes\",\n \"--overwrite\",\n presetUrl,\n ],\n absoluteProjectDir,\n );\n } catch {\n logger.warn(\n `Preset application failed. You can retry manually with:\\n ${dlxCmd} ${[...dlxArgs, \"shadcn@latest\", \"add\", presetUrl].join(\" \")}`,\n );\n }\n }\n\n process.removeListener(\"exit\", cleanupOnExit);\n\n logger.break();\n logger.success(\"Project created successfully!\");\n logger.break();\n const runCmd = pm === \"npm\" ? \"npm run\" : pm;\n let devScript = \"dev\";\n let envFile = \".env.local\";\n try {\n const scaffoldedPkg = JSON.parse(\n fs.readFileSync(\n path.join(absoluteProjectDir, \"package.json\"),\n \"utf-8\",\n ),\n );\n devScript = scaffoldedPkg.scripts?.dev\n ? \"dev\"\n : scaffoldedPkg.scripts?.start\n ? \"start\"\n : \"dev\";\n envFile = scaffoldedPkg.dependencies?.next ? \".env.local\" : \".env\";\n } catch {\n // Fall back to defaults if package.json cannot be read\n }\n\n logger.info(\"Next steps:\");\n logger.info(` cd ${resolvedProjectDirectory}`);\n if (opts.skipInstall) {\n logger.info(` ${pm} install`);\n }\n logger.info(` # Set up your environment variables in ${envFile}`);\n logger.info(` ${runCmd} ${devScript}`);\n } catch (error) {\n if (error instanceof SpawnExitError) {\n logger.error(`Project creation failed with code ${error.code}`);\n process.exit(error.code);\n }\n const message = error instanceof Error ? error.message : String(error);\n logger.error(`Failed to create project: ${message}`);\n process.exit(1);\n }\n });\n"],"mappings":";;;;;;;;;;AA8BA,MAAa,mBAAsC;CAEjD;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CAEA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CAC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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"doctor.js","names":["fs","path"],"sources":["../../src/commands/doctor.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport chalk from \"chalk\";\n\nconst ASSISTANT_UI_PACKAGE_NAMES = new Set([\n \"assistant-stream\",\n \"assistant-cloud\",\n \"assistant-ui\",\n]);\n\nfunction isTrackedPackage(name: string | undefined): boolean {\n if (!name) return false;\n if (name.startsWith(\"@assistant-ui/\")) return true;\n return ASSISTANT_UI_PACKAGE_NAMES.has(name);\n}\n\nexport interface DiscoveredPackage {\n name: string;\n version: string;\n installPath: string;\n}\n\ninterface ProcessedDir {\n set: Set<string>;\n}\n\nfunction readJson(file: string): Record<string, unknown> | null {\n try {\n return JSON.parse(fs.readFileSync(file, \"utf8\"));\n } catch {\n return null;\n }\n}\n\nfunction processPackageDir(\n pkgDir: string,\n results: DiscoveredPackage[],\n visited: ProcessedDir,\n): void {\n const real = (() => {\n try {\n return fs.realpathSync(pkgDir);\n } catch {\n return pkgDir;\n }\n })();\n if (visited.set.has(real)) return;\n visited.set.add(real);\n\n const pkgJson = readJson(path.join(pkgDir, \"package.json\"));\n let isTracked = false;\n if (pkgJson) {\n const name = pkgJson.name as string | undefined;\n const version = pkgJson.version as string | undefined;\n if (name && version && isTrackedPackage(name)) {\n results.push({ name, version, installPath: pkgDir });\n isTracked = true;\n }\n }\n\n // Only descend into nested node_modules of tracked packages. Transitive\n // copies of @assistant-ui/* live inside packages that depend on them,\n // which are themselves tracked. Walking every unrelated package's\n // subtree turns a doctor run on a large repo into thousands of stat\n // calls for no gain.\n if (isTracked) {\n walkNodeModulesAt(pkgDir, results, visited);\n }\n}\n\nfunction walkNodeModulesAt(\n baseDir: string,\n results: DiscoveredPackage[],\n visited: ProcessedDir,\n): void {\n const nm = path.join(baseDir, \"node_modules\");\n if (!fs.existsSync(nm)) return;\n\n let entries: fs.Dirent[];\n try {\n entries = fs.readdirSync(nm, { withFileTypes: true });\n } catch {\n return;\n }\n\n for (const entry of entries) {\n if (entry.name.startsWith(\".\")) continue;\n if (!entry.isDirectory() && !entry.isSymbolicLink()) continue;\n\n if (entry.name.startsWith(\"@\")) {\n const scopeDir = path.join(nm, entry.name);\n let scoped: fs.Dirent[];\n try {\n scoped = fs.readdirSync(scopeDir, { withFileTypes: true });\n } catch {\n continue;\n }\n for (const s of scoped) {\n if (!s.isDirectory() && !s.isSymbolicLink()) continue;\n processPackageDir(path.join(scopeDir, s.name), results, visited);\n }\n } else {\n processPackageDir(path.join(nm, entry.name), results, visited);\n }\n }\n}\n\n// Discover every installation of an assistant-ui-family package reachable\n// from `cwd`. Recurses into nested node_modules so transitive copies\n// (the real source of duplicate-version bugs) are not missed.\nexport function discoverInstalledPackages(cwd: string): DiscoveredPackage[] {\n const results: DiscoveredPackage[] = [];\n const visited: ProcessedDir = { set: new Set() };\n walkNodeModulesAt(cwd, results, visited);\n return results;\n}\n\nexport interface DuplicateGroup {\n name: string;\n installations: DiscoveredPackage[];\n}\n\nexport function findDuplicates(\n packages: DiscoveredPackage[],\n): DuplicateGroup[] {\n const byName = new Map<string, DiscoveredPackage[]>();\n for (const pkg of packages) {\n const list = byName.get(pkg.name) ?? [];\n list.push(pkg);\n byName.set(pkg.name, list);\n }\n\n const duplicates: DuplicateGroup[] = [];\n for (const [name, installations] of byName) {\n const versions = new Set(installations.map((i) => i.version));\n if (versions.size > 1) {\n duplicates.push({ name, installations });\n }\n }\n duplicates.sort((a, b) => a.name.localeCompare(b.name));\n return duplicates;\n}\n\nexport function uniquePackageNames(packages: DiscoveredPackage[]): string[] {\n return Array.from(new Set(packages.map((p) => p.name))).sort();\n}\n\n// Package names use a restricted character set (`[a-z0-9._~-]` plus a\n// leading `@scope/` for scoped packages — see the npm package-name spec)\n// and the npm registry expects the scope's `@` and `/` un-encoded. So a\n// simple validation + concatenation is both correct and avoids the\n// CodeQL \"incomplete string escaping\" foot-gun of `encodeURIComponent`\n// + targeted un-escape.\nconst VALID_NPM_NAME = /^(@[a-z0-9._~-]+\\/)?[a-z0-9._~-]+$/;\n\nasync function fetchLatestVersion(name: string): Promise<string | null> {\n if (!VALID_NPM_NAME.test(name)) return null;\n try {\n const res = await fetch(`https://registry.npmjs.org/${name}/latest`, {\n headers: { Accept: \"application/json\" },\n });\n if (!res.ok) return null;\n const data = (await res.json()) as { version?: string };\n return data.version ?? null;\n } catch {\n return null;\n }\n}\n\nasync function fetchAllLatestVersions(\n names: string[],\n): Promise<Map<string, string | null>> {\n const entries = await Promise.all(\n names.map(async (n) => [n, await fetchLatestVersion(n)] as const),\n );\n return new Map(entries);\n}\n\ninterface SemverParts {\n major: number;\n minor: number;\n patch: number;\n prerelease: string;\n}\n\nfunction parseSemver(v: string): SemverParts | null {\n const m = /^(\\d+)\\.(\\d+)\\.(\\d+)(?:-([^+\\s]+))?/.exec(v);\n if (!m) return null;\n return {\n major: parseInt(m[1]!, 10),\n minor: parseInt(m[2]!, 10),\n patch: parseInt(m[3]!, 10),\n prerelease: m[4] ?? \"\",\n };\n}\n\nexport function compareSemver(a: string, b: string): number {\n const pa = parseSemver(a);\n const pb = parseSemver(b);\n if (!pa || !pb) return a.localeCompare(b);\n if (pa.major !== pb.major) return pa.major - pb.major;\n if (pa.minor !== pb.minor) return pa.minor - pb.minor;\n if (pa.patch !== pb.patch) return pa.patch - pb.patch;\n\n // Per SemVer §11: a version with a prerelease tag is *less than* the\n // same x.y.z without one. We compare tags lexically for a stable\n // ordering across prereleases — good enough for doctor's \"is X older\n // than the npm latest\" check.\n if (pa.prerelease === pb.prerelease) return 0;\n if (!pa.prerelease) return 1;\n if (!pb.prerelease) return -1;\n return pa.prerelease.localeCompare(pb.prerelease);\n}\n\nexport interface OutdatedPackage {\n name: string;\n current: string;\n latest: string;\n}\n\nexport function findOutdated(\n packages: DiscoveredPackage[],\n latest: Map<string, string | null>,\n): OutdatedPackage[] {\n const newestByName = new Map<string, string>();\n for (const pkg of packages) {\n const existing = newestByName.get(pkg.name);\n if (!existing || compareSemver(pkg.version, existing) > 0) {\n newestByName.set(pkg.name, pkg.version);\n }\n }\n\n const result: OutdatedPackage[] = [];\n for (const [name, current] of newestByName) {\n const latestVersion = latest.get(name);\n if (!latestVersion) continue;\n if (compareSemver(current, latestVersion) < 0) {\n result.push({ name, current, latest: latestVersion });\n }\n }\n result.sort((a, b) => a.name.localeCompare(b.name));\n return result;\n}\n\nfunction relativeInstallPath(installPath: string, cwd: string): string {\n const rel = path.relative(cwd, installPath);\n return rel.startsWith(\"..\") ? installPath : rel;\n}\n\nfunction reportDuplicates(\n duplicates: DuplicateGroup[],\n cwd: string,\n lines: string[],\n): void {\n if (duplicates.length === 0) {\n lines.push(chalk.green(\"✓ No duplicate versions detected.\"));\n return;\n }\n\n lines.push(chalk.red.bold(\"✗ Duplicate versions detected:\"));\n for (const dup of duplicates) {\n const versions = Array.from(\n new Set(dup.installations.map((i) => i.version)),\n )\n .sort(compareSemver)\n .join(\", \");\n lines.push(chalk.red(` ${dup.name} → ${versions}`));\n for (const inst of dup.installations) {\n lines.push(\n chalk.dim(\n ` ${inst.version} ${relativeInstallPath(inst.installPath, cwd)}`,\n ),\n );\n }\n }\n lines.push(\"\");\n lines.push(\n chalk.yellow(\n \"Duplicates almost always cause subtle runtime bugs (see https://github.com/assistant-ui/assistant-ui/issues/4101).\",\n ),\n );\n lines.push(\n chalk.yellow(\n \"Fix by aligning all @assistant-ui/* packages to compatible versions — run:\",\n ),\n );\n lines.push(chalk.cyan(\" npx assistant-ui update\"));\n}\n\nfunction reportOutdated(outdated: OutdatedPackage[], lines: string[]): void {\n if (outdated.length === 0) {\n lines.push(chalk.green(\"✓ All assistant-ui packages are up to date.\"));\n return;\n }\n\n lines.push(chalk.yellow.bold(\"! Outdated packages:\"));\n const maxLen = Math.max(...outdated.map((o) => o.name.length));\n for (const o of outdated) {\n lines.push(\n chalk.yellow(\n ` ${o.name.padEnd(maxLen)} ${o.current} → ${o.latest} (latest)`,\n ),\n );\n }\n lines.push(\"\");\n lines.push(chalk.yellow(\"Run the following to upgrade everything:\"));\n lines.push(chalk.cyan(\" npx assistant-ui update\"));\n}\n\nexport const doctor = new Command()\n .name(\"doctor\")\n .description(\n \"Diagnose mismatched or outdated assistant-ui packages (including transitive ones).\",\n )\n .option(\n \"-c, --cwd <cwd>\",\n \"the working directory. defaults to the current directory.\",\n process.cwd(),\n )\n .option(\"--no-network\", \"Skip the npm registry check for latest versions.\")\n .action(async (opts: { cwd: string; network: boolean }) => {\n const cwd = path.resolve(opts.cwd);\n const packageJsonPath = path.join(cwd, \"package.json\");\n\n if (!fs.existsSync(packageJsonPath)) {\n console.error(\n chalk.red(\"No package.json found in the current directory.\"),\n );\n process.exit(1);\n }\n\n console.log(\"\");\n console.log(chalk.bold(\"Running assistant-ui doctor...\"));\n console.log(\"\");\n\n const installed = discoverInstalledPackages(cwd);\n\n if (installed.length === 0) {\n console.log(\n chalk.yellow(\n \"No assistant-ui packages found in node_modules. Did you run `npm install`?\",\n ),\n );\n console.log(\"\");\n return;\n }\n\n const duplicates = findDuplicates(installed);\n\n let latest = new Map<string, string | null>();\n if (opts.network) {\n latest = await fetchAllLatestVersions(uniquePackageNames(installed));\n }\n const outdated = findOutdated(installed, latest);\n\n const lines: string[] = [];\n reportDuplicates(duplicates, cwd, lines);\n lines.push(\"\");\n if (opts.network) {\n reportOutdated(outdated, lines);\n } else {\n lines.push(chalk.dim(\"Skipped npm registry check (--no-network).\"));\n }\n\n for (const line of lines) console.log(line);\n console.log(\"\");\n\n if (duplicates.length > 0) {\n process.exitCode = 1;\n }\n });\n"],"mappings":";;;;;AAKA,MAAM,6BAA6B,IAAI,IAAI;CACzC;CACA;CACA;AACF,CAAC;AAED,SAAS,iBAAiB,MAAmC;CAC3D,IAAI,CAAC,MAAM,OAAO;CAClB,IAAI,KAAK,WAAW,gBAAgB,GAAG,OAAO;CAC9C,OAAO,2BAA2B,IAAI,IAAI;AAC5C;AAYA,SAAS,SAAS,MAA8C;CAC9D,IAAI;EACF,OAAO,KAAK,MAAMA,KAAG,aAAa,MAAM,MAAM,CAAC;CACjD,QAAQ;EACN,OAAO;CACT;AACF;AAEA,SAAS,kBACP,QACA,SACA,SACM;CACN,MAAM,cAAc;EAClB,IAAI;GACF,OAAOA,KAAG,aAAa,MAAM;EAC/B,QAAQ;GACN,OAAO;EACT;CACF,GAAG;CACH,IAAI,QAAQ,IAAI,IAAI,IAAI,GAAG;CAC3B,QAAQ,IAAI,IAAI,IAAI;CAEpB,MAAM,UAAU,SAASC,OAAK,KAAK,QAAQ,cAAc,CAAC;CAC1D,IAAI,YAAY;CAChB,IAAI,SAAS;EACX,MAAM,OAAO,QAAQ;EACrB,MAAM,UAAU,QAAQ;EACxB,IAAI,QAAQ,WAAW,iBAAiB,IAAI,GAAG;GAC7C,QAAQ,KAAK;IAAE;IAAM;IAAS,aAAa;GAAO,CAAC;GACnD,YAAY;EACd;CACF;CAOA,IAAI,WACF,kBAAkB,QAAQ,SAAS,OAAO;AAE9C;AAEA,SAAS,kBACP,SACA,SACA,SACM;CACN,MAAM,KAAKA,OAAK,KAAK,SAAS,cAAc;CAC5C,IAAI,CAACD,KAAG,WAAW,EAAE,GAAG;CAExB,IAAI;CACJ,IAAI;EACF,UAAUA,KAAG,YAAY,IAAI,EAAE,eAAe,KAAK,CAAC;CACtD,QAAQ;EACN;CACF;CAEA,KAAK,MAAM,SAAS,SAAS;EAC3B,IAAI,MAAM,KAAK,WAAW,GAAG,GAAG;EAChC,IAAI,CAAC,MAAM,YAAY,KAAK,CAAC,MAAM,eAAe,GAAG;EAErD,IAAI,MAAM,KAAK,WAAW,GAAG,GAAG;GAC9B,MAAM,WAAWC,OAAK,KAAK,IAAI,MAAM,IAAI;GACzC,IAAI;GACJ,IAAI;IACF,SAASD,KAAG,YAAY,UAAU,EAAE,eAAe,KAAK,CAAC;GAC3D,QAAQ;IACN;GACF;GACA,KAAK,MAAM,KAAK,QAAQ;IACtB,IAAI,CAAC,EAAE,YAAY,KAAK,CAAC,EAAE,eAAe,GAAG;IAC7C,kBAAkBC,OAAK,KAAK,UAAU,EAAE,IAAI,GAAG,SAAS,OAAO;GACjE;EACF,OACE,kBAAkBA,OAAK,KAAK,IAAI,MAAM,IAAI,GAAG,SAAS,OAAO;CAEjE;AACF;AAKA,SAAgB,0BAA0B,KAAkC;CAC1E,MAAM,UAA+B,CAAC;CAEtC,kBAAkB,KAAK,SAAS,EADA,qBAAK,IAAI,IAAI,EACP,CAAC;CACvC,OAAO;AACT;AAOA,SAAgB,eACd,UACkB;CAClB,MAAM,yBAAS,IAAI,IAAiC;CACpD,KAAK,MAAM,OAAO,UAAU;EAC1B,MAAM,OAAO,OAAO,IAAI,IAAI,IAAI,KAAK,CAAC;EACtC,KAAK,KAAK,GAAG;EACb,OAAO,IAAI,IAAI,MAAM,IAAI;CAC3B;CAEA,MAAM,aAA+B,CAAC;CACtC,KAAK,MAAM,CAAC,MAAM,kBAAkB,QAElC,IAAI,IADiB,IAAI,cAAc,KAAK,MAAM,EAAE,OAAO,CAChD,EAAE,OAAO,GAClB,WAAW,KAAK;EAAE;EAAM;CAAc,CAAC;CAG3C,WAAW,MAAM,GAAG,MAAM,EAAE,KAAK,cAAc,EAAE,IAAI,CAAC;CACtD,OAAO;AACT;AAEA,SAAgB,mBAAmB,UAAyC;CAC1E,OAAO,MAAM,KAAK,IAAI,IAAI,SAAS,KAAK,MAAM,EAAE,IAAI,CAAC,CAAC,EAAE,KAAK;AAC/D;AAQA,MAAM,iBAAiB;AAEvB,eAAe,mBAAmB,MAAsC;CACtE,IAAI,CAAC,eAAe,KAAK,IAAI,GAAG,OAAO;CACvC,IAAI;EACF,MAAM,MAAM,MAAM,MAAM,8BAA8B,KAAK,UAAU,EACnE,SAAS,EAAE,QAAQ,mBAAmB,EACxC,CAAC;EACD,IAAI,CAAC,IAAI,IAAI,OAAO;EAEpB,QAAO,MADa,IAAI,KAAK,GACjB,WAAW;CACzB,QAAQ;EACN,OAAO;CACT;AACF;AAEA,eAAe,uBACb,OACqC;CACrC,MAAM,UAAU,MAAM,QAAQ,IAC5B,MAAM,IAAI,OAAO,MAAM,CAAC,GAAG,MAAM,mBAAmB,CAAC,CAAC,CAAU,CAClE;CACA,OAAO,IAAI,IAAI,OAAO;AACxB;AASA,SAAS,YAAY,GAA+B;CAClD,MAAM,IAAI,sCAAsC,KAAK,CAAC;CACtD,IAAI,CAAC,GAAG,OAAO;CACf,OAAO;EACL,OAAO,SAAS,EAAE,IAAK,EAAE;EACzB,OAAO,SAAS,EAAE,IAAK,EAAE;EACzB,OAAO,SAAS,EAAE,IAAK,EAAE;EACzB,YAAY,EAAE,MAAM;CACtB;AACF;AAEA,SAAgB,cAAc,GAAW,GAAmB;CAC1D,MAAM,KAAK,YAAY,CAAC;CACxB,MAAM,KAAK,YAAY,CAAC;CACxB,IAAI,CAAC,MAAM,CAAC,IAAI,OAAO,EAAE,cAAc,CAAC;CACxC,IAAI,GAAG,UAAU,GAAG,OAAO,OAAO,GAAG,QAAQ,GAAG;CAChD,IAAI,GAAG,UAAU,GAAG,OAAO,OAAO,GAAG,QAAQ,GAAG;CAChD,IAAI,GAAG,UAAU,GAAG,OAAO,OAAO,GAAG,QAAQ,GAAG;CAMhD,IAAI,GAAG,eAAe,GAAG,YAAY,OAAO;CAC5C,IAAI,CAAC,GAAG,YAAY,OAAO;CAC3B,IAAI,CAAC,GAAG,YAAY,OAAO;CAC3B,OAAO,GAAG,WAAW,cAAc,GAAG,UAAU;AAClD;AAQA,SAAgB,aACd,UACA,QACmB;CACnB,MAAM,+BAAe,IAAI,IAAoB;CAC7C,KAAK,MAAM,OAAO,UAAU;EAC1B,MAAM,WAAW,aAAa,IAAI,IAAI,IAAI;EAC1C,IAAI,CAAC,YAAY,cAAc,IAAI,SAAS,QAAQ,IAAI,GACtD,aAAa,IAAI,IAAI,MAAM,IAAI,OAAO;CAE1C;CAEA,MAAM,SAA4B,CAAC;CACnC,KAAK,MAAM,CAAC,MAAM,YAAY,cAAc;EAC1C,MAAM,gBAAgB,OAAO,IAAI,IAAI;EACrC,IAAI,CAAC,eAAe;EACpB,IAAI,cAAc,SAAS,aAAa,IAAI,GAC1C,OAAO,KAAK;GAAE;GAAM;GAAS,QAAQ;EAAc,CAAC;CAExD;CACA,OAAO,MAAM,GAAG,MAAM,EAAE,KAAK,cAAc,EAAE,IAAI,CAAC;CAClD,OAAO;AACT;AAEA,SAAS,oBAAoB,aAAqB,KAAqB;CACrE,MAAM,MAAMA,OAAK,SAAS,KAAK,WAAW;CAC1C,OAAO,IAAI,WAAW,IAAI,IAAI,cAAc;AAC9C;AAEA,SAAS,iBACP,YACA,KACA,OACM;CACN,IAAI,WAAW,WAAW,GAAG;EAC3B,MAAM,KAAK,MAAM,MAAM,mCAAmC,CAAC;EAC3D;CACF;CAEA,MAAM,KAAK,MAAM,IAAI,KAAK,gCAAgC,CAAC;CAC3D,KAAK,MAAM,OAAO,YAAY;EAC5B,MAAM,WAAW,MAAM,KACrB,IAAI,IAAI,IAAI,cAAc,KAAK,MAAM,EAAE,OAAO,CAAC,CACjD,EACG,KAAK,aAAa,EAClB,KAAK,IAAI;EACZ,MAAM,KAAK,MAAM,IAAI,KAAK,IAAI,KAAK,KAAK,UAAU,CAAC;EACnD,KAAK,MAAM,QAAQ,IAAI,eACrB,MAAM,KACJ,MAAM,IACJ,OAAO,KAAK,QAAQ,IAAI,oBAAoB,KAAK,aAAa,GAAG,GACnE,CACF;CAEJ;CACA,MAAM,KAAK,EAAE;CACb,MAAM,KACJ,MAAM,OACJ,oHACF,CACF;CACA,MAAM,KACJ,MAAM,OACJ,4EACF,CACF;CACA,MAAM,KAAK,MAAM,KAAK,6BAA6B,CAAC;AACtD;AAEA,SAAS,eAAe,UAA6B,OAAuB;CAC1E,IAAI,SAAS,WAAW,GAAG;EACzB,MAAM,KAAK,MAAM,MAAM,6CAA6C,CAAC;EACrE;CACF;CAEA,MAAM,KAAK,MAAM,OAAO,KAAK,sBAAsB,CAAC;CACpD,MAAM,SAAS,KAAK,IAAI,GAAG,SAAS,KAAK,MAAM,EAAE,KAAK,MAAM,CAAC;CAC7D,KAAK,MAAM,KAAK,UACd,MAAM,KACJ,MAAM,OACJ,KAAK,EAAE,KAAK,OAAO,MAAM,EAAE,IAAI,EAAE,QAAQ,KAAK,EAAE,OAAO,UACzD,CACF;CAEF,MAAM,KAAK,EAAE;CACb,MAAM,KAAK,MAAM,OAAO,0CAA0C,CAAC;CACnE,MAAM,KAAK,MAAM,KAAK,6BAA6B,CAAC;AACtD;AAEA,MAAa,SAAS,IAAI,QAAQ,EAC/B,KAAK,QAAQ,EACb,YACC,oFACF,EACC,OACC,mBACA,6DACA,QAAQ,IAAI,CACd,EACC,OAAO,gBAAgB,kDAAkD,EACzE,OAAO,OAAO,SAA4C;CACzD,MAAM,MAAMA,OAAK,QAAQ,KAAK,GAAG;CACjC,MAAM,kBAAkBA,OAAK,KAAK,KAAK,cAAc;CAErD,IAAI,CAACD,KAAG,WAAW,eAAe,GAAG;EACnC,QAAQ,MACN,MAAM,IAAI,iDAAiD,CAC7D;EACA,QAAQ,KAAK,CAAC;CAChB;CAEA,QAAQ,IAAI,EAAE;CACd,QAAQ,IAAI,MAAM,KAAK,gCAAgC,CAAC;CACxD,QAAQ,IAAI,EAAE;CAEd,MAAM,YAAY,0BAA0B,GAAG;CAE/C,IAAI,UAAU,WAAW,GAAG;EAC1B,QAAQ,IACN,MAAM,OACJ,4EACF,CACF;EACA,QAAQ,IAAI,EAAE;EACd;CACF;CAEA,MAAM,aAAa,eAAe,SAAS;CAE3C,IAAI,yBAAS,IAAI,IAA2B;CAC5C,IAAI,KAAK,SACP,SAAS,MAAM,uBAAuB,mBAAmB,SAAS,CAAC;CAErE,MAAM,WAAW,aAAa,WAAW,MAAM;CAE/C,MAAM,QAAkB,CAAC;CACzB,iBAAiB,YAAY,KAAK,KAAK;CACvC,MAAM,KAAK,EAAE;CACb,IAAI,KAAK,SACP,eAAe,UAAU,KAAK;MAE9B,MAAM,KAAK,MAAM,IAAI,4CAA4C,CAAC;CAGpE,KAAK,MAAM,QAAQ,OAAO,QAAQ,IAAI,IAAI;CAC1C,QAAQ,IAAI,EAAE;CAEd,IAAI,WAAW,SAAS,GACtB,QAAQ,WAAW;AAEvB,CAAC"}
|
|
1
|
+
{"version":3,"file":"doctor.js","names":["fs","path"],"sources":["../../src/commands/doctor.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport chalk from \"chalk\";\n\nconst ASSISTANT_UI_PACKAGE_NAMES = new Set([\n \"assistant-stream\",\n \"assistant-cloud\",\n \"assistant-ui\",\n]);\n\nfunction isTrackedPackage(name: string | undefined): boolean {\n if (!name) return false;\n if (name.startsWith(\"@assistant-ui/\")) return true;\n return ASSISTANT_UI_PACKAGE_NAMES.has(name);\n}\n\nexport interface DiscoveredPackage {\n name: string;\n version: string;\n installPath: string;\n}\n\ninterface ProcessedDir {\n set: Set<string>;\n}\n\nfunction readJson(file: string): Record<string, unknown> | null {\n try {\n return JSON.parse(fs.readFileSync(file, \"utf8\"));\n } catch {\n return null;\n }\n}\n\nfunction processPackageDir(\n pkgDir: string,\n results: DiscoveredPackage[],\n visited: ProcessedDir,\n): void {\n const real = (() => {\n try {\n return fs.realpathSync(pkgDir);\n } catch {\n return pkgDir;\n }\n })();\n if (visited.set.has(real)) return;\n visited.set.add(real);\n\n const pkgJson = readJson(path.join(pkgDir, \"package.json\"));\n let isTracked = false;\n if (pkgJson) {\n const name = pkgJson.name as string | undefined;\n const version = pkgJson.version as string | undefined;\n if (name && version && isTrackedPackage(name)) {\n results.push({ name, version, installPath: pkgDir });\n isTracked = true;\n }\n }\n\n // Only descend into nested node_modules of tracked packages. Transitive\n // copies of @assistant-ui/* live inside packages that depend on them,\n // which are themselves tracked. Walking every unrelated package's\n // subtree turns a doctor run on a large repo into thousands of stat\n // calls for no gain.\n if (isTracked) {\n walkNodeModulesAt(pkgDir, results, visited);\n }\n}\n\nfunction walkNodeModulesAt(\n baseDir: string,\n results: DiscoveredPackage[],\n visited: ProcessedDir,\n): void {\n const nm = path.join(baseDir, \"node_modules\");\n if (!fs.existsSync(nm)) return;\n\n let entries: fs.Dirent[];\n try {\n entries = fs.readdirSync(nm, { withFileTypes: true });\n } catch {\n return;\n }\n\n for (const entry of entries) {\n if (entry.name.startsWith(\".\")) continue;\n if (!entry.isDirectory() && !entry.isSymbolicLink()) continue;\n\n if (entry.name.startsWith(\"@\")) {\n const scopeDir = path.join(nm, entry.name);\n let scoped: fs.Dirent[];\n try {\n scoped = fs.readdirSync(scopeDir, { withFileTypes: true });\n } catch {\n continue;\n }\n for (const s of scoped) {\n if (!s.isDirectory() && !s.isSymbolicLink()) continue;\n processPackageDir(path.join(scopeDir, s.name), results, visited);\n }\n } else {\n processPackageDir(path.join(nm, entry.name), results, visited);\n }\n }\n}\n\n// Discover every installation of an assistant-ui-family package reachable\n// from `cwd`. Recurses into nested node_modules so transitive copies\n// (the real source of duplicate-version bugs) are not missed.\nexport function discoverInstalledPackages(cwd: string): DiscoveredPackage[] {\n const results: DiscoveredPackage[] = [];\n const visited: ProcessedDir = { set: new Set() };\n walkNodeModulesAt(cwd, results, visited);\n return results;\n}\n\nexport interface DuplicateGroup {\n name: string;\n installations: DiscoveredPackage[];\n}\n\nexport function findDuplicates(\n packages: DiscoveredPackage[],\n): DuplicateGroup[] {\n const byName = new Map<string, DiscoveredPackage[]>();\n for (const pkg of packages) {\n const list = byName.get(pkg.name) ?? [];\n list.push(pkg);\n byName.set(pkg.name, list);\n }\n\n const duplicates: DuplicateGroup[] = [];\n for (const [name, installations] of byName) {\n const versions = new Set(installations.map((i) => i.version));\n if (versions.size > 1) {\n duplicates.push({ name, installations });\n }\n }\n duplicates.sort((a, b) => a.name.localeCompare(b.name));\n return duplicates;\n}\n\nexport function uniquePackageNames(packages: DiscoveredPackage[]): string[] {\n return Array.from(new Set(packages.map((p) => p.name))).sort();\n}\n\n// Package names use a restricted character set (`[a-z0-9._~-]` plus a\n// leading `@scope/` for scoped packages — see the npm package-name spec)\n// and the npm registry expects the scope's `@` and `/` un-encoded. So a\n// simple validation + concatenation is both correct and avoids the\n// CodeQL \"incomplete string escaping\" foot-gun of `encodeURIComponent`\n// + targeted un-escape.\nconst VALID_NPM_NAME = /^(@[a-z0-9._~-]+\\/)?[a-z0-9._~-]+$/;\n\nasync function fetchLatestVersion(name: string): Promise<string | null> {\n if (!VALID_NPM_NAME.test(name)) return null;\n try {\n const res = await fetch(`https://registry.npmjs.org/${name}/latest`, {\n headers: { Accept: \"application/json\" },\n });\n if (!res.ok) return null;\n const data = (await res.json()) as { version?: string };\n return data.version ?? null;\n } catch {\n return null;\n }\n}\n\nasync function fetchAllLatestVersions(\n names: string[],\n): Promise<Map<string, string | null>> {\n const entries = await Promise.all(\n names.map(async (n) => [n, await fetchLatestVersion(n)] as const),\n );\n return new Map(entries);\n}\n\ninterface SemverParts {\n major: number;\n minor: number;\n patch: number;\n prerelease: string;\n}\n\nfunction parseSemver(v: string): SemverParts | null {\n const m = /^(\\d+)\\.(\\d+)\\.(\\d+)(?:-([^+\\s]+))?/.exec(v);\n if (!m) return null;\n return {\n major: parseInt(m[1]!, 10),\n minor: parseInt(m[2]!, 10),\n patch: parseInt(m[3]!, 10),\n prerelease: m[4] ?? \"\",\n };\n}\n\nexport function compareSemver(a: string, b: string): number {\n const pa = parseSemver(a);\n const pb = parseSemver(b);\n if (!pa || !pb) return a.localeCompare(b);\n if (pa.major !== pb.major) return pa.major - pb.major;\n if (pa.minor !== pb.minor) return pa.minor - pb.minor;\n if (pa.patch !== pb.patch) return pa.patch - pb.patch;\n\n // Per SemVer §11: a version with a prerelease tag is *less than* the\n // same x.y.z without one. We compare tags lexically for a stable\n // ordering across prereleases — good enough for doctor's \"is X older\n // than the npm latest\" check.\n if (pa.prerelease === pb.prerelease) return 0;\n if (!pa.prerelease) return 1;\n if (!pb.prerelease) return -1;\n return pa.prerelease.localeCompare(pb.prerelease);\n}\n\nexport interface OutdatedPackage {\n name: string;\n current: string;\n latest: string;\n}\n\nexport function findOutdated(\n packages: DiscoveredPackage[],\n latest: Map<string, string | null>,\n): OutdatedPackage[] {\n const newestByName = new Map<string, string>();\n for (const pkg of packages) {\n const existing = newestByName.get(pkg.name);\n if (!existing || compareSemver(pkg.version, existing) > 0) {\n newestByName.set(pkg.name, pkg.version);\n }\n }\n\n const result: OutdatedPackage[] = [];\n for (const [name, current] of newestByName) {\n const latestVersion = latest.get(name);\n if (!latestVersion) continue;\n if (compareSemver(current, latestVersion) < 0) {\n result.push({ name, current, latest: latestVersion });\n }\n }\n result.sort((a, b) => a.name.localeCompare(b.name));\n return result;\n}\n\nfunction relativeInstallPath(installPath: string, cwd: string): string {\n const rel = path.relative(cwd, installPath);\n return rel.startsWith(\"..\") ? installPath : rel;\n}\n\nfunction reportDuplicates(\n duplicates: DuplicateGroup[],\n cwd: string,\n lines: string[],\n): void {\n if (duplicates.length === 0) {\n lines.push(chalk.green(\"✓ No duplicate versions detected.\"));\n return;\n }\n\n lines.push(chalk.red.bold(\"✗ Duplicate versions detected:\"));\n for (const dup of duplicates) {\n const versions = Array.from(\n new Set(dup.installations.map((i) => i.version)),\n )\n .sort(compareSemver)\n .join(\", \");\n lines.push(chalk.red(` ${dup.name} → ${versions}`));\n for (const inst of dup.installations) {\n lines.push(\n chalk.dim(\n ` ${inst.version} ${relativeInstallPath(inst.installPath, cwd)}`,\n ),\n );\n }\n }\n lines.push(\"\");\n lines.push(\n chalk.yellow(\n \"Duplicates almost always cause subtle runtime bugs (see https://github.com/assistant-ui/assistant-ui/issues/4101).\",\n ),\n );\n lines.push(\n chalk.yellow(\n \"Fix by aligning all @assistant-ui/* packages to compatible versions — run:\",\n ),\n );\n lines.push(chalk.cyan(\" npx assistant-ui update\"));\n}\n\nfunction reportOutdated(outdated: OutdatedPackage[], lines: string[]): void {\n if (outdated.length === 0) {\n lines.push(chalk.green(\"✓ All assistant-ui packages are up to date.\"));\n return;\n }\n\n lines.push(chalk.yellow.bold(\"! Outdated packages:\"));\n const maxLen = Math.max(...outdated.map((o) => o.name.length));\n for (const o of outdated) {\n lines.push(\n chalk.yellow(\n ` ${o.name.padEnd(maxLen)} ${o.current} → ${o.latest} (latest)`,\n ),\n );\n }\n lines.push(\"\");\n lines.push(chalk.yellow(\"Run the following to upgrade everything:\"));\n lines.push(chalk.cyan(\" npx assistant-ui update\"));\n}\n\nexport const doctor = new Command()\n .name(\"doctor\")\n .description(\n \"Diagnose mismatched or outdated assistant-ui packages (including transitive ones).\",\n )\n .option(\n \"-c, --cwd <cwd>\",\n \"the working directory. defaults to the current directory.\",\n process.cwd(),\n )\n .option(\"--no-network\", \"Skip the npm registry check for latest versions.\")\n .action(async (opts: { cwd: string; network: boolean }) => {\n const cwd = path.resolve(opts.cwd);\n const packageJsonPath = path.join(cwd, \"package.json\");\n\n if (!fs.existsSync(packageJsonPath)) {\n console.error(\n chalk.red(\"No package.json found in the current directory.\"),\n );\n process.exit(1);\n }\n\n console.log(\"\");\n console.log(chalk.bold(\"Running assistant-ui doctor...\"));\n console.log(\"\");\n\n const installed = discoverInstalledPackages(cwd);\n\n if (installed.length === 0) {\n console.log(\n chalk.yellow(\n \"No assistant-ui packages found in node_modules. Did you run `npm install`?\",\n ),\n );\n console.log(\"\");\n return;\n }\n\n const duplicates = findDuplicates(installed);\n\n let latest = new Map<string, string | null>();\n if (opts.network) {\n latest = await fetchAllLatestVersions(uniquePackageNames(installed));\n }\n const outdated = findOutdated(installed, latest);\n\n const lines: string[] = [];\n reportDuplicates(duplicates, cwd, lines);\n lines.push(\"\");\n if (opts.network) {\n reportOutdated(outdated, lines);\n } else {\n lines.push(chalk.dim(\"Skipped npm registry check (--no-network).\"));\n }\n\n for (const line of lines) console.log(line);\n console.log(\"\");\n\n if (duplicates.length > 0) {\n process.exitCode = 1;\n }\n });\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"info.js","names":["path","fs","os"],"sources":["../../src/commands/info.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport * as fs from \"node:fs\";\nimport * as os from \"node:os\";\nimport * as path from \"node:path\";\nimport { spawnSync } from \"node:child_process\";\nimport chalk from \"chalk\";\nimport { detect } from \"detect-package-manager\";\n\nconst ASSISTANT_UI_PACKAGES = [\n // Distribution\n \"@assistant-ui/react\",\n \"@assistant-ui/react-native\",\n \"@assistant-ui/react-ink\",\n // Core (should not be installed directly)\n \"@assistant-ui/core\",\n \"@assistant-ui/store\",\n \"@assistant-ui/tap\",\n // Streaming & Cloud\n \"assistant-stream\",\n \"assistant-cloud\",\n \"@assistant-ui/cloud-ai-sdk\",\n // Adapters\n \"@assistant-ui/react-ai-sdk\",\n \"@assistant-ui/react-langgraph\",\n \"@assistant-ui/react-ag-ui\",\n \"@assistant-ui/react-a2a\",\n \"@assistant-ui/react-data-stream\",\n \"@assistant-ui/react-google-adk\",\n // UI / Rendering\n \"@assistant-ui/react-markdown\",\n \"@assistant-ui/react-streamdown\",\n \"@assistant-ui/react-lexical\",\n \"@assistant-ui/react-syntax-highlighter\",\n \"@assistant-ui/react-hook-form\",\n // Observability & DevTools\n \"@assistant-ui/react-o11y\",\n \"@assistant-ui/react-devtools\",\n];\n\nconst ECOSYSTEM_PACKAGES = [\n \"react\",\n \"react-dom\",\n \"react-native\",\n \"next\",\n \"vite\",\n \"expo\",\n \"ai\",\n \"zod\",\n \"zustand\",\n \"typescript\",\n];\n\n// Packages that users should NOT install directly — they are internal\n// dependencies pulled in automatically by distribution packages.\nconst SHOULD_NOT_DIRECT_INSTALL = new Set([\n \"@assistant-ui/core\",\n \"@assistant-ui/store\",\n \"@assistant-ui/tap\",\n]);\n\nfunction resolvePackageJson(pkg: string, cwd: string): string | null {\n let dir = cwd;\n const root = path.parse(dir).root;\n while (dir !== root) {\n const candidate = path.join(\n dir,\n \"node_modules\",\n ...pkg.split(\"/\"),\n \"package.json\",\n );\n if (fs.existsSync(candidate)) return candidate;\n dir = path.dirname(dir);\n }\n return null;\n}\n\nfunction getInstalledVersion(pkg: string, cwd: string): string | null {\n try {\n const pkgJsonPath = resolvePackageJson(pkg, cwd);\n if (pkgJsonPath) {\n const pkgJson = JSON.parse(fs.readFileSync(pkgJsonPath, \"utf8\"));\n return pkgJson.version ?? null;\n }\n } catch {\n // ignore\n }\n return null;\n}\n\nfunction findWorkspaceRoot(cwd: string): string | null {\n let dir = path.dirname(cwd);\n const root = path.parse(dir).root;\n while (dir !== root) {\n if (fs.existsSync(path.join(dir, \"pnpm-workspace.yaml\"))) return dir;\n const pkgPath = path.join(dir, \"package.json\");\n if (fs.existsSync(pkgPath)) {\n try {\n const pkg = JSON.parse(fs.readFileSync(pkgPath, \"utf8\"));\n if (pkg.workspaces) return dir;\n } catch {\n // ignore\n }\n }\n dir = path.dirname(dir);\n }\n return null;\n}\n\nfunction readProjectDeps(\n projectPkg: Record<string, unknown>,\n): Record<string, string> {\n return {\n ...((projectPkg.dependencies ?? {}) as Record<string, string>),\n ...((projectPkg.devDependencies ?? {}) as Record<string, string>),\n };\n}\n\nfunction getSpecifiedRange(\n pkg: string,\n projectPkg: Record<string, unknown>,\n): string | null {\n const deps = (projectPkg.dependencies ?? {}) as Record<string, string>;\n const devDeps = (projectPkg.devDependencies ?? {}) as Record<string, string>;\n return deps[pkg] ?? devDeps[pkg] ?? null;\n}\n\nfunction getPeerDeps(pkg: string, cwd: string): Record<string, string> | null {\n try {\n const pkgJsonPath = resolvePackageJson(pkg, cwd);\n if (pkgJsonPath) {\n const pkgJson = JSON.parse(fs.readFileSync(pkgJsonPath, \"utf8\"));\n return (pkgJson.peerDependencies as Record<string, string>) ?? null;\n }\n } catch {\n // ignore\n }\n return null;\n}\n\nfunction detectFramework(\n projectPkg: Record<string, unknown>,\n cwd: string,\n): string {\n const deps = readProjectDeps(projectPkg);\n\n if (deps.next) {\n const v = getInstalledVersion(\"next\", cwd);\n return `Next.js ${v ?? deps.next}`;\n }\n if (deps.expo) {\n const v = getInstalledVersion(\"expo\", cwd);\n return `Expo ${v ?? deps.expo}`;\n }\n if (deps.vite) {\n const v = getInstalledVersion(\"vite\", cwd);\n return `Vite ${v ?? deps.vite}`;\n }\n if (deps[\"@remix-run/react\"] || deps.remix) return \"Remix\";\n if (deps.gatsby) return \"Gatsby\";\n if (deps.astro) return \"Astro\";\n return \"Unknown\";\n}\n\nfunction getOsInfo(): string {\n const platform = os.platform();\n const arch = os.arch();\n const release = os.release();\n\n switch (platform) {\n case \"darwin\": {\n const result = spawnSync(\"sw_vers\", [\"-productVersion\"], {\n encoding: \"utf8\",\n });\n const macVer = result.stdout?.trim();\n return macVer\n ? `macOS ${macVer} (${arch})`\n : `macOS ${release} (${arch})`;\n }\n case \"win32\":\n return `Windows ${release} (${arch})`;\n case \"linux\":\n return `Linux ${release} (${arch})`;\n default:\n return `${platform} ${release} (${arch})`;\n }\n}\n\nasync function getPackageManagerInfo(\n cwd: string,\n): Promise<{ name: string; version: string }> {\n const pm = await detect({ cwd });\n const result = spawnSync(pm, [\"--version\"], {\n encoding: \"utf8\",\n cwd,\n });\n const version = result.stdout?.trim() ?? \"unknown\";\n return { name: pm, version };\n}\n\nfunction satisfiesRange(version: string, range: string): boolean {\n if (range === \"*\" || range === \"any\") return true;\n\n const clean = (v: string) => v.replace(/^[^\\d]*/, \"\");\n const major = (v: string) => parseInt(clean(v).split(\".\")[0]!, 10);\n\n if (range.includes(\"||\")) {\n return range\n .split(\"||\")\n .some((part) => satisfiesRange(version, part.trim()));\n }\n\n const rangeMajor = major(range);\n const versionMajor = major(version);\n\n if (Number.isNaN(rangeMajor) || Number.isNaN(versionMajor)) return true;\n\n if (range.startsWith(\"^\")) return versionMajor >= rangeMajor;\n if (range.startsWith(\">=\")) return versionMajor >= rangeMajor;\n\n return versionMajor >= rangeMajor;\n}\n\ninterface PackageInfo {\n name: string;\n version: string;\n range: string | null;\n}\n\ninterface InfoData {\n os: string;\n node: string;\n pm: { name: string; version: string };\n framework: string;\n isMonorepo: boolean;\n packages: PackageInfo[];\n ecosystem: PackageInfo[];\n warnings: string[];\n}\n\nfunction collectPackages(\n names: string[],\n cwd: string,\n projectPkg: Record<string, unknown>,\n): PackageInfo[] {\n const result: PackageInfo[] = [];\n const deps = readProjectDeps(projectPkg);\n\n for (const name of names) {\n const version = getInstalledVersion(name, cwd);\n if (version) {\n result.push({\n name,\n version,\n range: getSpecifiedRange(name, projectPkg),\n });\n } else {\n // Fallback: no node_modules, show range from package.json\n const range = deps[name];\n if (range && !range.startsWith(\"workspace:\")) {\n result.push({ name, version: `${range} (not installed)`, range });\n }\n }\n }\n return result;\n}\n\nfunction collectWarnings(\n packages: PackageInfo[],\n cwd: string,\n projectPkg: Record<string, unknown>,\n): string[] {\n const warnings: string[] = [];\n const deps = readProjectDeps(projectPkg);\n\n // Check peer dependency mismatches\n for (const pkg of packages) {\n const peerDeps = getPeerDeps(pkg.name, cwd);\n if (!peerDeps) continue;\n\n for (const [peerName, peerRange] of Object.entries(peerDeps)) {\n const peerVersion = getInstalledVersion(peerName, cwd);\n if (!peerVersion) continue;\n if (!satisfiesRange(peerVersion, peerRange)) {\n warnings.push(\n `${pkg.name} requires ${peerName} ${peerRange}, found ${peerVersion}`,\n );\n }\n }\n }\n\n // Check for direct install of internal packages\n for (const name of SHOULD_NOT_DIRECT_INSTALL) {\n if (deps[name]) {\n warnings.push(\n `${name} should not be installed directly — it is an internal dependency`,\n );\n }\n }\n\n return warnings;\n}\n\nasync function collectInfo(\n cwd: string,\n projectPkg: Record<string, unknown>,\n): Promise<InfoData> {\n const pm = await getPackageManagerInfo(cwd);\n const packages = collectPackages(ASSISTANT_UI_PACKAGES, cwd, projectPkg);\n const ecosystem = collectPackages(ECOSYSTEM_PACKAGES, cwd, projectPkg);\n const warnings = collectWarnings(packages, cwd, projectPkg);\n\n return {\n os: getOsInfo(),\n node: process.version,\n pm,\n framework: detectFramework(projectPkg, cwd),\n isMonorepo: findWorkspaceRoot(cwd) !== null,\n packages,\n ecosystem,\n warnings,\n };\n}\n\nfunction formatSection(label: string, items: PackageInfo[]): string[] {\n if (items.length === 0) return [];\n const lines: string[] = [];\n lines.push(\"\");\n lines.push(`${label}:`);\n const maxLen = Math.max(...items.map((p) => p.name.length));\n for (const pkg of items) {\n lines.push(` ${pkg.name.padEnd(maxLen)} ${pkg.version}`);\n }\n return lines;\n}\n\nfunction renderPlain(data: InfoData): string[] {\n const lines: string[] = [];\n\n lines.push(\"Environment:\");\n lines.push(` OS: ${data.os}`);\n lines.push(` Node.js: ${data.node}`);\n lines.push(` Package Manager: ${data.pm.name} ${data.pm.version}`);\n lines.push(` Framework: ${data.framework}`);\n if (data.isMonorepo) {\n lines.push(` Monorepo: yes`);\n }\n\n lines.push(...formatSection(\"Packages\", data.packages));\n lines.push(...formatSection(\"Ecosystem\", data.ecosystem));\n\n if (data.warnings.length > 0) {\n lines.push(\"\");\n lines.push(\"Warnings:\");\n for (const w of data.warnings) {\n lines.push(` ! ${w}`);\n }\n }\n\n return lines;\n}\n\nfunction renderColored(data: InfoData): string[] {\n const lines: string[] = [];\n\n lines.push(chalk.bold(\"Environment:\"));\n lines.push(` OS: ${data.os}`);\n lines.push(` Node.js: ${data.node}`);\n lines.push(` Package Manager: ${data.pm.name} ${data.pm.version}`);\n lines.push(` Framework: ${data.framework}`);\n if (data.isMonorepo) {\n lines.push(` Monorepo: yes`);\n }\n\n if (data.packages.length > 0) {\n const section = formatSection(\"Packages\", data.packages);\n section[0] = \"\";\n section[1] = chalk.bold(\"Packages:\");\n lines.push(...section);\n } else {\n lines.push(\"\");\n lines.push(chalk.yellow(\" No assistant-ui packages found.\"));\n }\n\n if (data.ecosystem.length > 0) {\n const section = formatSection(\"Ecosystem\", data.ecosystem);\n section[0] = \"\";\n section[1] = chalk.bold(\"Ecosystem:\");\n lines.push(...section);\n }\n\n if (data.warnings.length > 0) {\n lines.push(\"\");\n lines.push(chalk.yellow.bold(\"Warnings:\"));\n for (const w of data.warnings) {\n lines.push(chalk.yellow(` ! ${w}`));\n }\n }\n\n return lines;\n}\n\nexport const info = new Command()\n .name(\"info\")\n .description(\"Print environment and package information for bug reports.\")\n .option(\n \"-c, --cwd <cwd>\",\n \"the working directory. defaults to the current directory.\",\n process.cwd(),\n )\n .action(async (opts) => {\n const cwd = path.resolve(opts.cwd);\n const packageJsonPath = path.join(cwd, \"package.json\");\n\n if (!fs.existsSync(packageJsonPath)) {\n console.error(\n chalk.red(\"No package.json found in the current directory.\"),\n );\n process.exit(1);\n }\n\n const projectPkg = JSON.parse(fs.readFileSync(packageJsonPath, \"utf8\"));\n const data = await collectInfo(cwd, projectPkg);\n\n // Colored output for terminal\n console.log(\"\");\n for (const line of renderColored(data)) {\n console.log(line);\n }\n console.log(\"\");\n\n // Copyable plain text\n const plain = renderPlain(data);\n const block = [\"```\", ...plain, \"```\"].join(\"\\n\");\n\n console.log(chalk.dim(\"— Copy the text below into your bug report —\"));\n console.log(\"\");\n console.log(block);\n console.log(\"\");\n });\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"info.js","names":["path","fs","os"],"sources":["../../src/commands/info.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport * as fs from \"node:fs\";\nimport * as os from \"node:os\";\nimport * as path from \"node:path\";\nimport { spawnSync } from \"node:child_process\";\nimport chalk from \"chalk\";\nimport { detect } from \"detect-package-manager\";\n\nconst ASSISTANT_UI_PACKAGES = [\n // Distribution\n \"@assistant-ui/react\",\n \"@assistant-ui/react-native\",\n \"@assistant-ui/react-ink\",\n // Core (should not be installed directly)\n \"@assistant-ui/core\",\n \"@assistant-ui/store\",\n \"@assistant-ui/tap\",\n // Streaming & Cloud\n \"assistant-stream\",\n \"assistant-cloud\",\n \"@assistant-ui/cloud-ai-sdk\",\n // Adapters\n \"@assistant-ui/react-ai-sdk\",\n \"@assistant-ui/react-langgraph\",\n \"@assistant-ui/react-ag-ui\",\n \"@assistant-ui/react-a2a\",\n \"@assistant-ui/react-data-stream\",\n \"@assistant-ui/react-google-adk\",\n // UI / Rendering\n \"@assistant-ui/react-markdown\",\n \"@assistant-ui/react-streamdown\",\n \"@assistant-ui/react-lexical\",\n \"@assistant-ui/react-syntax-highlighter\",\n \"@assistant-ui/react-hook-form\",\n // Observability & DevTools\n \"@assistant-ui/react-o11y\",\n \"@assistant-ui/react-devtools\",\n];\n\nconst ECOSYSTEM_PACKAGES = [\n \"react\",\n \"react-dom\",\n \"react-native\",\n \"next\",\n \"vite\",\n \"expo\",\n \"ai\",\n \"zod\",\n \"zustand\",\n \"typescript\",\n];\n\n// Packages that users should NOT install directly — they are internal\n// dependencies pulled in automatically by distribution packages.\nconst SHOULD_NOT_DIRECT_INSTALL = new Set([\n \"@assistant-ui/core\",\n \"@assistant-ui/store\",\n \"@assistant-ui/tap\",\n]);\n\nfunction resolvePackageJson(pkg: string, cwd: string): string | null {\n let dir = cwd;\n const root = path.parse(dir).root;\n while (dir !== root) {\n const candidate = path.join(\n dir,\n \"node_modules\",\n ...pkg.split(\"/\"),\n \"package.json\",\n );\n if (fs.existsSync(candidate)) return candidate;\n dir = path.dirname(dir);\n }\n return null;\n}\n\nfunction getInstalledVersion(pkg: string, cwd: string): string | null {\n try {\n const pkgJsonPath = resolvePackageJson(pkg, cwd);\n if (pkgJsonPath) {\n const pkgJson = JSON.parse(fs.readFileSync(pkgJsonPath, \"utf8\"));\n return pkgJson.version ?? null;\n }\n } catch {\n // ignore\n }\n return null;\n}\n\nfunction findWorkspaceRoot(cwd: string): string | null {\n let dir = path.dirname(cwd);\n const root = path.parse(dir).root;\n while (dir !== root) {\n if (fs.existsSync(path.join(dir, \"pnpm-workspace.yaml\"))) return dir;\n const pkgPath = path.join(dir, \"package.json\");\n if (fs.existsSync(pkgPath)) {\n try {\n const pkg = JSON.parse(fs.readFileSync(pkgPath, \"utf8\"));\n if (pkg.workspaces) return dir;\n } catch {\n // ignore\n }\n }\n dir = path.dirname(dir);\n }\n return null;\n}\n\nfunction readProjectDeps(\n projectPkg: Record<string, unknown>,\n): Record<string, string> {\n return {\n ...((projectPkg.dependencies ?? {}) as Record<string, string>),\n ...((projectPkg.devDependencies ?? {}) as Record<string, string>),\n };\n}\n\nfunction getSpecifiedRange(\n pkg: string,\n projectPkg: Record<string, unknown>,\n): string | null {\n const deps = (projectPkg.dependencies ?? {}) as Record<string, string>;\n const devDeps = (projectPkg.devDependencies ?? {}) as Record<string, string>;\n return deps[pkg] ?? devDeps[pkg] ?? null;\n}\n\nfunction getPeerDeps(pkg: string, cwd: string): Record<string, string> | null {\n try {\n const pkgJsonPath = resolvePackageJson(pkg, cwd);\n if (pkgJsonPath) {\n const pkgJson = JSON.parse(fs.readFileSync(pkgJsonPath, \"utf8\"));\n return (pkgJson.peerDependencies as Record<string, string>) ?? null;\n }\n } catch {\n // ignore\n }\n return null;\n}\n\nfunction detectFramework(\n projectPkg: Record<string, unknown>,\n cwd: string,\n): string {\n const deps = readProjectDeps(projectPkg);\n\n if (deps.next) {\n const v = getInstalledVersion(\"next\", cwd);\n return `Next.js ${v ?? deps.next}`;\n }\n if (deps.expo) {\n const v = getInstalledVersion(\"expo\", cwd);\n return `Expo ${v ?? deps.expo}`;\n }\n if (deps.vite) {\n const v = getInstalledVersion(\"vite\", cwd);\n return `Vite ${v ?? deps.vite}`;\n }\n if (deps[\"@remix-run/react\"] || deps.remix) return \"Remix\";\n if (deps.gatsby) return \"Gatsby\";\n if (deps.astro) return \"Astro\";\n return \"Unknown\";\n}\n\nfunction getOsInfo(): string {\n const platform = os.platform();\n const arch = os.arch();\n const release = os.release();\n\n switch (platform) {\n case \"darwin\": {\n const result = spawnSync(\"sw_vers\", [\"-productVersion\"], {\n encoding: \"utf8\",\n });\n const macVer = result.stdout?.trim();\n return macVer\n ? `macOS ${macVer} (${arch})`\n : `macOS ${release} (${arch})`;\n }\n case \"win32\":\n return `Windows ${release} (${arch})`;\n case \"linux\":\n return `Linux ${release} (${arch})`;\n default:\n return `${platform} ${release} (${arch})`;\n }\n}\n\nasync function getPackageManagerInfo(\n cwd: string,\n): Promise<{ name: string; version: string }> {\n const pm = await detect({ cwd });\n const result = spawnSync(pm, [\"--version\"], {\n encoding: \"utf8\",\n cwd,\n });\n const version = result.stdout?.trim() ?? \"unknown\";\n return { name: pm, version };\n}\n\nfunction satisfiesRange(version: string, range: string): boolean {\n if (range === \"*\" || range === \"any\") return true;\n\n const clean = (v: string) => v.replace(/^[^\\d]*/, \"\");\n const major = (v: string) => parseInt(clean(v).split(\".\")[0]!, 10);\n\n if (range.includes(\"||\")) {\n return range\n .split(\"||\")\n .some((part) => satisfiesRange(version, part.trim()));\n }\n\n const rangeMajor = major(range);\n const versionMajor = major(version);\n\n if (Number.isNaN(rangeMajor) || Number.isNaN(versionMajor)) return true;\n\n if (range.startsWith(\"^\")) return versionMajor >= rangeMajor;\n if (range.startsWith(\">=\")) return versionMajor >= rangeMajor;\n\n return versionMajor >= rangeMajor;\n}\n\ninterface PackageInfo {\n name: string;\n version: string;\n range: string | null;\n}\n\ninterface InfoData {\n os: string;\n node: string;\n pm: { name: string; version: string };\n framework: string;\n isMonorepo: boolean;\n packages: PackageInfo[];\n ecosystem: PackageInfo[];\n warnings: string[];\n}\n\nfunction collectPackages(\n names: string[],\n cwd: string,\n projectPkg: Record<string, unknown>,\n): PackageInfo[] {\n const result: PackageInfo[] = [];\n const deps = readProjectDeps(projectPkg);\n\n for (const name of names) {\n const version = getInstalledVersion(name, cwd);\n if (version) {\n result.push({\n name,\n version,\n range: getSpecifiedRange(name, projectPkg),\n });\n } else {\n // Fallback: no node_modules, show range from package.json\n const range = deps[name];\n if (range && !range.startsWith(\"workspace:\")) {\n result.push({ name, version: `${range} (not installed)`, range });\n }\n }\n }\n return result;\n}\n\nfunction collectWarnings(\n packages: PackageInfo[],\n cwd: string,\n projectPkg: Record<string, unknown>,\n): string[] {\n const warnings: string[] = [];\n const deps = readProjectDeps(projectPkg);\n\n // Check peer dependency mismatches\n for (const pkg of packages) {\n const peerDeps = getPeerDeps(pkg.name, cwd);\n if (!peerDeps) continue;\n\n for (const [peerName, peerRange] of Object.entries(peerDeps)) {\n const peerVersion = getInstalledVersion(peerName, cwd);\n if (!peerVersion) continue;\n if (!satisfiesRange(peerVersion, peerRange)) {\n warnings.push(\n `${pkg.name} requires ${peerName} ${peerRange}, found ${peerVersion}`,\n );\n }\n }\n }\n\n // Check for direct install of internal packages\n for (const name of SHOULD_NOT_DIRECT_INSTALL) {\n if (deps[name]) {\n warnings.push(\n `${name} should not be installed directly — it is an internal dependency`,\n );\n }\n }\n\n return warnings;\n}\n\nasync function collectInfo(\n cwd: string,\n projectPkg: Record<string, unknown>,\n): Promise<InfoData> {\n const pm = await getPackageManagerInfo(cwd);\n const packages = collectPackages(ASSISTANT_UI_PACKAGES, cwd, projectPkg);\n const ecosystem = collectPackages(ECOSYSTEM_PACKAGES, cwd, projectPkg);\n const warnings = collectWarnings(packages, cwd, projectPkg);\n\n return {\n os: getOsInfo(),\n node: process.version,\n pm,\n framework: detectFramework(projectPkg, cwd),\n isMonorepo: findWorkspaceRoot(cwd) !== null,\n packages,\n ecosystem,\n warnings,\n };\n}\n\nfunction formatSection(label: string, items: PackageInfo[]): string[] {\n if (items.length === 0) return [];\n const lines: string[] = [];\n lines.push(\"\");\n lines.push(`${label}:`);\n const maxLen = Math.max(...items.map((p) => p.name.length));\n for (const pkg of items) {\n lines.push(` ${pkg.name.padEnd(maxLen)} ${pkg.version}`);\n }\n return lines;\n}\n\nfunction renderPlain(data: InfoData): string[] {\n const lines: string[] = [];\n\n lines.push(\"Environment:\");\n lines.push(` OS: ${data.os}`);\n lines.push(` Node.js: ${data.node}`);\n lines.push(` Package Manager: ${data.pm.name} ${data.pm.version}`);\n lines.push(` Framework: ${data.framework}`);\n if (data.isMonorepo) {\n lines.push(` Monorepo: yes`);\n }\n\n lines.push(...formatSection(\"Packages\", data.packages));\n lines.push(...formatSection(\"Ecosystem\", data.ecosystem));\n\n if (data.warnings.length > 0) {\n lines.push(\"\");\n lines.push(\"Warnings:\");\n for (const w of data.warnings) {\n lines.push(` ! ${w}`);\n }\n }\n\n return lines;\n}\n\nfunction renderColored(data: InfoData): string[] {\n const lines: string[] = [];\n\n lines.push(chalk.bold(\"Environment:\"));\n lines.push(` OS: ${data.os}`);\n lines.push(` Node.js: ${data.node}`);\n lines.push(` Package Manager: ${data.pm.name} ${data.pm.version}`);\n lines.push(` Framework: ${data.framework}`);\n if (data.isMonorepo) {\n lines.push(` Monorepo: yes`);\n }\n\n if (data.packages.length > 0) {\n const section = formatSection(\"Packages\", data.packages);\n section[0] = \"\";\n section[1] = chalk.bold(\"Packages:\");\n lines.push(...section);\n } else {\n lines.push(\"\");\n lines.push(chalk.yellow(\" No assistant-ui packages found.\"));\n }\n\n if (data.ecosystem.length > 0) {\n const section = formatSection(\"Ecosystem\", data.ecosystem);\n section[0] = \"\";\n section[1] = chalk.bold(\"Ecosystem:\");\n lines.push(...section);\n }\n\n if (data.warnings.length > 0) {\n lines.push(\"\");\n lines.push(chalk.yellow.bold(\"Warnings:\"));\n for (const w of data.warnings) {\n lines.push(chalk.yellow(` ! ${w}`));\n }\n }\n\n return lines;\n}\n\nexport const info = new Command()\n .name(\"info\")\n .description(\"Print environment and package information for bug reports.\")\n .option(\n \"-c, --cwd <cwd>\",\n \"the working directory. defaults to the current directory.\",\n process.cwd(),\n )\n .action(async (opts) => {\n const cwd = path.resolve(opts.cwd);\n const packageJsonPath = path.join(cwd, \"package.json\");\n\n if (!fs.existsSync(packageJsonPath)) {\n console.error(\n chalk.red(\"No package.json found in the current directory.\"),\n );\n process.exit(1);\n }\n\n const projectPkg = JSON.parse(fs.readFileSync(packageJsonPath, \"utf8\"));\n const data = await collectInfo(cwd, projectPkg);\n\n // Colored output for terminal\n console.log(\"\");\n for (const line of renderColored(data)) {\n console.log(line);\n }\n console.log(\"\");\n\n // Copyable plain text\n const plain = renderPlain(data);\n const block = [\"```\", ...plain, \"```\"].join(\"\\n\");\n\n console.log(chalk.dim(\"— Copy the text below into your bug report —\"));\n console.log(\"\");\n console.log(block);\n console.log(\"\");\n });\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init.js","names":[],"sources":["../../src/commands/init.ts"],"sourcesContent":["import { Command, Option } from \"commander\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport {\n dlxCommand,\n resolvePackageManager,\n resolvePackageManagerForCwd,\n} from \"../lib/create-project\";\nimport { runSpawn, SpawnExitError } from \"../lib/run-spawn\";\nimport { logger } from \"../lib/utils/logger\";\nimport { create } from \"./create\";\n\nconst DEFAULT_REGISTRY_URL =\n \"https://r.assistant-ui.com/chat/b/ai-sdk-quick-start/json\";\n\ninterface ExistingProjectInitPlan {\n initArgs: string[] | null;\n addArgs: string[];\n}\n\nexport function createExistingProjectInitPlan(params: {\n yes: boolean;\n overwrite: boolean;\n registryUrl: string;\n}): ExistingProjectInitPlan {\n const { yes, overwrite, registryUrl } = params;\n\n if (!yes) {\n const addArgs = [`shadcn@latest`, \"add\"];\n if (overwrite) addArgs.push(\"--overwrite\");\n addArgs.push(registryUrl);\n return { initArgs: null, addArgs };\n }\n\n const initArgs = [`shadcn@latest`, \"init\", \"--defaults\", \"--yes\"];\n\n const addArgs = [`shadcn@latest`, \"add\", \"--yes\"];\n if (overwrite) addArgs.push(\"--overwrite\");\n addArgs.push(registryUrl);\n\n return { initArgs, addArgs };\n}\n\nexport function isNonInteractiveShell(\n stdinIsTTY = process.stdin.isTTY,\n): boolean {\n return !stdinIsTTY;\n}\n\nexport const init = new Command()\n .name(\"init\")\n .description(\"initialize assistant-ui in an existing project\")\n .argument(\"[project-directory]\", \"directory for the new project\")\n .option(\"-y, --yes\", \"skip confirmation prompt.\", false)\n .option(\"-o, --overwrite\", \"overwrite existing files.\", false)\n .option(\n \"-c, --cwd <cwd>\",\n \"the working directory. defaults to the current directory.\",\n process.cwd(),\n )\n .addOption(\n new Option(\n \"-p, --preset <name-or-url>\",\n \"preset name or URL (forwarded to 'assistant-ui create')\",\n ).hideHelp(),\n )\n .option(\"--use-npm\", \"explicitly use npm\")\n .option(\"--use-pnpm\", \"explicitly use pnpm\")\n .option(\"--use-yarn\", \"explicitly use yarn\")\n .option(\"--use-bun\", \"explicitly use bun\")\n .option(\"--skip-install\", \"skip installing packages\")\n .action(async (projectDirectory, opts) => {\n const cwd = opts.cwd;\n const presetUrl = opts.preset as string | undefined;\n const targetDir = projectDirectory\n ? path.resolve(cwd, projectDirectory)\n : cwd;\n\n const componentsConfigPath = path.join(targetDir, \"components.json\");\n\n if (!presetUrl && fs.existsSync(componentsConfigPath)) {\n logger.warn(\"Project is already initialized.\");\n logger.info(\"Use 'assistant-ui add' to add more components.\");\n return;\n }\n\n const packageJsonPath = path.join(targetDir, \"package.json\");\n const packageJsonExists = fs.existsSync(packageJsonPath);\n\n if (presetUrl || !packageJsonExists) {\n if (!presetUrl) {\n logger.info(\"No existing project found. Running 'create' instead...\");\n logger.break();\n }\n\n const createArgs: string[] = [];\n if (projectDirectory) createArgs.push(projectDirectory);\n if (presetUrl) createArgs.push(\"--preset\", presetUrl);\n if (opts.useNpm) createArgs.push(\"--use-npm\");\n if (opts.usePnpm) createArgs.push(\"--use-pnpm\");\n if (opts.useYarn) createArgs.push(\"--use-yarn\");\n if (opts.useBun) createArgs.push(\"--use-bun\");\n if (opts.skipInstall) createArgs.push(\"--skip-install\");\n\n await create.parseAsync(createArgs, { from: \"user\" });\n return;\n }\n\n const registryUrl = DEFAULT_REGISTRY_URL;\n logger.info(\"Initializing assistant-ui in existing project...\");\n logger.break();\n\n if (!opts.yes && isNonInteractiveShell()) {\n logger.error(\n [\n \"Detected a non-interactive shell, but 'assistant-ui init' needs interactive prompts by default.\",\n \"To run this in CI/agent mode, re-run with '--yes' so shadcn initialization and component install run non-interactively.\",\n \"Example: assistant-ui init --yes\",\n ].join(\"\\n\"),\n );\n process.exit(1);\n }\n\n try {\n const pm = await resolvePackageManagerForCwd(\n targetDir,\n resolvePackageManager(opts),\n );\n const [dlxCmd, dlxArgs] = dlxCommand(pm);\n\n const { initArgs, addArgs } = createExistingProjectInitPlan({\n yes: opts.yes,\n overwrite: opts.overwrite,\n registryUrl,\n });\n\n if (initArgs) {\n await runSpawn(dlxCmd, [...dlxArgs, ...initArgs], targetDir);\n }\n await runSpawn(dlxCmd, [...dlxArgs, ...addArgs], targetDir);\n\n logger.break();\n logger.success(\"Project initialized successfully!\");\n logger.info(\"You can now add more components with 'assistant-ui add'\");\n } catch (error) {\n if (error instanceof SpawnExitError) {\n logger.error(`Initialization failed with code ${error.code}`);\n process.exit(error.code);\n }\n const message = error instanceof Error ? error.message : String(error);\n logger.error(`Failed to initialize: ${message}`);\n process.exit(1);\n }\n });\n"],"mappings":";;;;;;;;AAYA,MAAM,uBACJ;AAOF,SAAgB,8BAA8B,QAIlB;CAC1B,MAAM,EAAE,KAAK,WAAW,gBAAgB;CAExC,IAAI,CAAC,KAAK;EACR,MAAM,UAAU,CAAC,iBAAiB,KAAK;EACvC,IAAI,WAAW,QAAQ,KAAK,aAAa;EACzC,QAAQ,KAAK,WAAW;EACxB,OAAO;GAAE,UAAU;GAAM;EAAQ;CACnC;CAEA,MAAM,WAAW;EAAC;EAAiB;EAAQ;EAAc;CAAO;CAEhE,MAAM,UAAU;EAAC;EAAiB;EAAO;CAAO;CAChD,IAAI,WAAW,QAAQ,KAAK,aAAa;CACzC,QAAQ,KAAK,WAAW;CAExB,OAAO;EAAE;EAAU;CAAQ;AAC7B;AAEA,SAAgB,sBACd,aAAa,QAAQ,MAAM,OAClB;CACT,OAAO,CAAC;AACV;AAEA,MAAa,OAAO,IAAI,QAAQ,
|
|
1
|
+
{"version":3,"file":"init.js","names":[],"sources":["../../src/commands/init.ts"],"sourcesContent":["import { Command, Option } from \"commander\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport {\n dlxCommand,\n resolvePackageManager,\n resolvePackageManagerForCwd,\n} from \"../lib/create-project\";\nimport { runSpawn, SpawnExitError } from \"../lib/run-spawn\";\nimport { logger } from \"../lib/utils/logger\";\nimport { create } from \"./create\";\n\nconst DEFAULT_REGISTRY_URL =\n \"https://r.assistant-ui.com/chat/b/ai-sdk-quick-start/json\";\n\ninterface ExistingProjectInitPlan {\n initArgs: string[] | null;\n addArgs: string[];\n}\n\nexport function createExistingProjectInitPlan(params: {\n yes: boolean;\n overwrite: boolean;\n registryUrl: string;\n}): ExistingProjectInitPlan {\n const { yes, overwrite, registryUrl } = params;\n\n if (!yes) {\n const addArgs = [`shadcn@latest`, \"add\"];\n if (overwrite) addArgs.push(\"--overwrite\");\n addArgs.push(registryUrl);\n return { initArgs: null, addArgs };\n }\n\n const initArgs = [`shadcn@latest`, \"init\", \"--defaults\", \"--yes\"];\n\n const addArgs = [`shadcn@latest`, \"add\", \"--yes\"];\n if (overwrite) addArgs.push(\"--overwrite\");\n addArgs.push(registryUrl);\n\n return { initArgs, addArgs };\n}\n\nexport function isNonInteractiveShell(\n stdinIsTTY = process.stdin.isTTY,\n): boolean {\n return !stdinIsTTY;\n}\n\nexport const init = new Command()\n .name(\"init\")\n .description(\"initialize assistant-ui in an existing project\")\n .argument(\"[project-directory]\", \"directory for the new project\")\n .option(\"-y, --yes\", \"skip confirmation prompt.\", false)\n .option(\"-o, --overwrite\", \"overwrite existing files.\", false)\n .option(\n \"-c, --cwd <cwd>\",\n \"the working directory. defaults to the current directory.\",\n process.cwd(),\n )\n .addOption(\n new Option(\n \"-p, --preset <name-or-url>\",\n \"preset name or URL (forwarded to 'assistant-ui create')\",\n ).hideHelp(),\n )\n .option(\"--use-npm\", \"explicitly use npm\")\n .option(\"--use-pnpm\", \"explicitly use pnpm\")\n .option(\"--use-yarn\", \"explicitly use yarn\")\n .option(\"--use-bun\", \"explicitly use bun\")\n .option(\"--skip-install\", \"skip installing packages\")\n .action(async (projectDirectory, opts) => {\n const cwd = opts.cwd;\n const presetUrl = opts.preset as string | undefined;\n const targetDir = projectDirectory\n ? path.resolve(cwd, projectDirectory)\n : cwd;\n\n const componentsConfigPath = path.join(targetDir, \"components.json\");\n\n if (!presetUrl && fs.existsSync(componentsConfigPath)) {\n logger.warn(\"Project is already initialized.\");\n logger.info(\"Use 'assistant-ui add' to add more components.\");\n return;\n }\n\n const packageJsonPath = path.join(targetDir, \"package.json\");\n const packageJsonExists = fs.existsSync(packageJsonPath);\n\n if (presetUrl || !packageJsonExists) {\n if (!presetUrl) {\n logger.info(\"No existing project found. Running 'create' instead...\");\n logger.break();\n }\n\n const createArgs: string[] = [];\n if (projectDirectory) createArgs.push(projectDirectory);\n if (presetUrl) createArgs.push(\"--preset\", presetUrl);\n if (opts.useNpm) createArgs.push(\"--use-npm\");\n if (opts.usePnpm) createArgs.push(\"--use-pnpm\");\n if (opts.useYarn) createArgs.push(\"--use-yarn\");\n if (opts.useBun) createArgs.push(\"--use-bun\");\n if (opts.skipInstall) createArgs.push(\"--skip-install\");\n\n await create.parseAsync(createArgs, { from: \"user\" });\n return;\n }\n\n const registryUrl = DEFAULT_REGISTRY_URL;\n logger.info(\"Initializing assistant-ui in existing project...\");\n logger.break();\n\n if (!opts.yes && isNonInteractiveShell()) {\n logger.error(\n [\n \"Detected a non-interactive shell, but 'assistant-ui init' needs interactive prompts by default.\",\n \"To run this in CI/agent mode, re-run with '--yes' so shadcn initialization and component install run non-interactively.\",\n \"Example: assistant-ui init --yes\",\n ].join(\"\\n\"),\n );\n process.exit(1);\n }\n\n try {\n const pm = await resolvePackageManagerForCwd(\n targetDir,\n resolvePackageManager(opts),\n );\n const [dlxCmd, dlxArgs] = dlxCommand(pm);\n\n const { initArgs, addArgs } = createExistingProjectInitPlan({\n yes: opts.yes,\n overwrite: opts.overwrite,\n registryUrl,\n });\n\n if (initArgs) {\n await runSpawn(dlxCmd, [...dlxArgs, ...initArgs], targetDir);\n }\n await runSpawn(dlxCmd, [...dlxArgs, ...addArgs], targetDir);\n\n logger.break();\n logger.success(\"Project initialized successfully!\");\n logger.info(\"You can now add more components with 'assistant-ui add'\");\n } catch (error) {\n if (error instanceof SpawnExitError) {\n logger.error(`Initialization failed with code ${error.code}`);\n process.exit(error.code);\n }\n const message = error instanceof Error ? error.message : String(error);\n logger.error(`Failed to initialize: ${message}`);\n process.exit(1);\n }\n });\n"],"mappings":"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"}
|
package/dist/commands/mcp.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcp.js","names":[],"sources":["../../src/commands/mcp.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport os from \"node:os\";\nimport { spawn } from \"cross-spawn\";\nimport { logger } from \"../lib/utils/logger\";\nimport * as p from \"@clack/prompts\";\n\ntype MCPTarget =\n | \"cursor\"\n | \"windsurf\"\n | \"vscode\"\n | \"zed\"\n | \"claude-code\"\n | \"claude-desktop\";\n\nconst MCP_CONFIGS: Record<\n Exclude<MCPTarget, \"claude-code\">,\n {\n name: string;\n getPath: () => string;\n config: object;\n postInstall?: string;\n }\n> = {\n cursor: {\n name: \"Cursor\",\n getPath: () => path.join(process.cwd(), \".cursor\", \"mcp.json\"),\n config: {\n mcpServers: {\n \"assistant-ui\": {\n command: \"npx\",\n args: [\"-y\", \"@assistant-ui/mcp-docs-server\"],\n },\n },\n },\n postInstall:\n \"Open Cursor Settings → MCP → find 'assistant-ui' and click enable.\",\n },\n windsurf: {\n name: \"Windsurf\",\n getPath: () =>\n path.join(os.homedir(), \".codeium\", \"windsurf\", \"mcp_config.json\"),\n config: {\n mcpServers: {\n \"assistant-ui\": {\n command: \"npx\",\n args: [\"-y\", \"@assistant-ui/mcp-docs-server\"],\n },\n },\n },\n postInstall: \"Fully quit and re-open Windsurf to activate.\",\n },\n vscode: {\n name: \"VSCode\",\n getPath: () => path.join(process.cwd(), \".vscode\", \"mcp.json\"),\n config: {\n servers: {\n \"assistant-ui\": {\n command: \"npx\",\n args: [\"-y\", \"@assistant-ui/mcp-docs-server\"],\n type: \"stdio\",\n },\n },\n },\n postInstall:\n \"Enable MCP in Settings → search 'MCP' → enable 'Chat > MCP'. Use Copilot Chat in Agent mode.\",\n },\n zed: {\n name: \"Zed\",\n getPath: () => {\n if (process.platform === \"win32\") {\n return path.join(process.env.APPDATA || \"\", \"Zed\", \"settings.json\");\n }\n if (process.platform === \"darwin\") {\n return path.join(os.homedir(), \".zed\", \"settings.json\");\n }\n return path.join(os.homedir(), \".config\", \"zed\", \"settings.json\");\n },\n config: {\n context_servers: {\n \"assistant-ui\": {\n command: {\n path: \"npx\",\n args: [\"-y\", \"@assistant-ui/mcp-docs-server\"],\n },\n },\n },\n },\n postInstall: \"The server starts automatically with the Assistant Panel.\",\n },\n \"claude-desktop\": {\n name: \"Claude Desktop\",\n getPath: () => {\n if (process.platform === \"win32\") {\n return path.join(\n process.env.APPDATA || \"\",\n \"Claude\",\n \"claude_desktop_config.json\",\n );\n }\n return path.join(\n os.homedir(),\n \"Library\",\n \"Application Support\",\n \"Claude\",\n \"claude_desktop_config.json\",\n );\n },\n config: {\n mcpServers: {\n \"assistant-ui\": {\n command: \"npx\",\n args: [\"-y\", \"@assistant-ui/mcp-docs-server\"],\n },\n },\n },\n postInstall: \"Restart Claude Desktop to activate.\",\n },\n};\n\nfunction deepMerge(target: any, source: any): any {\n const result = { ...target };\n for (const key of Object.keys(source)) {\n if (\n source[key] &&\n typeof source[key] === \"object\" &&\n !Array.isArray(source[key])\n ) {\n result[key] = deepMerge(result[key] || {}, source[key]);\n } else {\n result[key] = source[key];\n }\n }\n return result;\n}\n\nasync function installForTarget(target: MCPTarget): Promise<void> {\n if (target === \"claude-code\") {\n logger.info(\"Installing MCP server for Claude Code...\");\n logger.break();\n\n const child = spawn(\n \"claude\",\n [\n \"mcp\",\n \"add\",\n \"assistant-ui\",\n \"--\",\n \"npx\",\n \"-y\",\n \"@assistant-ui/mcp-docs-server\",\n ],\n {\n stdio: \"inherit\",\n },\n );\n\n return new Promise((resolve, reject) => {\n child.on(\"error\", (error) => {\n logger.error(`Failed to install: ${error.message}`);\n logger.info(\n \"Make sure Claude Code CLI is installed: https://docs.anthropic.com/en/docs/claude-code\",\n );\n reject(error);\n });\n\n child.on(\"close\", (code) => {\n if (code !== 0) {\n logger.error(`Installation failed with code ${code}`);\n reject(new Error(`Exit code ${code}`));\n } else {\n logger.break();\n logger.success(\"MCP server installed for Claude Code!\");\n logger.info(\n \"The server starts automatically. Try asking about assistant-ui!\",\n );\n resolve();\n }\n });\n });\n }\n\n if (target === \"claude-desktop\" && process.platform === \"linux\") {\n logger.error(\"Claude Desktop is not available on Linux.\");\n logger.info(\n \"See: https://claude.ai/download for supported operating systems.\",\n );\n throw new Error(\"Unsupported platform for Claude Desktop\");\n }\n\n const targetConfig = MCP_CONFIGS[target];\n const configPath = targetConfig.getPath();\n const configDir = path.dirname(configPath);\n\n logger.info(`Installing MCP server for ${targetConfig.name}...`);\n\n if (!fs.existsSync(configDir)) {\n fs.mkdirSync(configDir, { recursive: true });\n }\n\n let existingConfig: any = {};\n if (fs.existsSync(configPath)) {\n const content = fs.readFileSync(configPath, \"utf-8\");\n try {\n existingConfig = JSON.parse(content);\n } catch (e) {\n logger.error(`Could not parse existing config at ${configPath}`);\n logger.error(\n \"Please fix the JSON syntax error before running this command.\",\n );\n throw e;\n }\n }\n\n const newConfig = deepMerge(existingConfig, targetConfig.config);\n\n fs.writeFileSync(configPath, `${JSON.stringify(newConfig, null, 2)}\\n`);\n\n logger.break();\n logger.success(`MCP server installed for ${targetConfig.name}!`);\n logger.info(`Config written to: ${configPath}`);\n\n if (targetConfig.postInstall) {\n logger.break();\n logger.info(targetConfig.postInstall);\n }\n}\n\nexport const mcp = new Command()\n .name(\"mcp\")\n .description(\"install assistant-ui MCP docs server for your IDE\")\n .option(\"--cursor\", \"install for Cursor\")\n .option(\"--windsurf\", \"install for Windsurf\")\n .option(\"--vscode\", \"install for VSCode\")\n .option(\"--zed\", \"install for Zed\")\n .option(\"--claude-code\", \"install for Claude Code\")\n .option(\"--claude-desktop\", \"install for Claude Desktop\")\n .action(async (opts) => {\n const targets: MCPTarget[] = [];\n\n if (opts.cursor) targets.push(\"cursor\");\n if (opts.windsurf) targets.push(\"windsurf\");\n if (opts.vscode) targets.push(\"vscode\");\n if (opts.zed) targets.push(\"zed\");\n if (opts.claudeCode) targets.push(\"claude-code\");\n if (opts.claudeDesktop) targets.push(\"claude-desktop\");\n\n // If no target specified, prompt user\n if (targets.length === 0) {\n p.intro(\"assistant-ui MCP Server Installation\");\n\n const selected = await p.select({\n message: \"Select your IDE or tool:\",\n options: [\n { value: \"cursor\", label: \"Cursor\" },\n { value: \"windsurf\", label: \"Windsurf\" },\n { value: \"vscode\", label: \"VSCode\" },\n { value: \"zed\", label: \"Zed\" },\n { value: \"claude-code\", label: \"Claude Code\" },\n { value: \"claude-desktop\", label: \"Claude Desktop\" },\n ],\n });\n\n if (p.isCancel(selected)) {\n p.cancel(\"Installation cancelled.\");\n process.exit(0);\n }\n\n targets.push(selected as MCPTarget);\n }\n\n for (const target of targets) {\n try {\n await installForTarget(target);\n } catch {\n process.exit(1);\n }\n }\n });\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"mcp.js","names":[],"sources":["../../src/commands/mcp.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport os from \"node:os\";\nimport { spawn } from \"cross-spawn\";\nimport { logger } from \"../lib/utils/logger\";\nimport * as p from \"@clack/prompts\";\n\ntype MCPTarget =\n | \"cursor\"\n | \"windsurf\"\n | \"vscode\"\n | \"zed\"\n | \"claude-code\"\n | \"claude-desktop\";\n\nconst MCP_CONFIGS: Record<\n Exclude<MCPTarget, \"claude-code\">,\n {\n name: string;\n getPath: () => string;\n config: object;\n postInstall?: string;\n }\n> = {\n cursor: {\n name: \"Cursor\",\n getPath: () => path.join(process.cwd(), \".cursor\", \"mcp.json\"),\n config: {\n mcpServers: {\n \"assistant-ui\": {\n command: \"npx\",\n args: [\"-y\", \"@assistant-ui/mcp-docs-server\"],\n },\n },\n },\n postInstall:\n \"Open Cursor Settings → MCP → find 'assistant-ui' and click enable.\",\n },\n windsurf: {\n name: \"Windsurf\",\n getPath: () =>\n path.join(os.homedir(), \".codeium\", \"windsurf\", \"mcp_config.json\"),\n config: {\n mcpServers: {\n \"assistant-ui\": {\n command: \"npx\",\n args: [\"-y\", \"@assistant-ui/mcp-docs-server\"],\n },\n },\n },\n postInstall: \"Fully quit and re-open Windsurf to activate.\",\n },\n vscode: {\n name: \"VSCode\",\n getPath: () => path.join(process.cwd(), \".vscode\", \"mcp.json\"),\n config: {\n servers: {\n \"assistant-ui\": {\n command: \"npx\",\n args: [\"-y\", \"@assistant-ui/mcp-docs-server\"],\n type: \"stdio\",\n },\n },\n },\n postInstall:\n \"Enable MCP in Settings → search 'MCP' → enable 'Chat > MCP'. Use Copilot Chat in Agent mode.\",\n },\n zed: {\n name: \"Zed\",\n getPath: () => {\n if (process.platform === \"win32\") {\n return path.join(process.env.APPDATA || \"\", \"Zed\", \"settings.json\");\n }\n if (process.platform === \"darwin\") {\n return path.join(os.homedir(), \".zed\", \"settings.json\");\n }\n return path.join(os.homedir(), \".config\", \"zed\", \"settings.json\");\n },\n config: {\n context_servers: {\n \"assistant-ui\": {\n command: {\n path: \"npx\",\n args: [\"-y\", \"@assistant-ui/mcp-docs-server\"],\n },\n },\n },\n },\n postInstall: \"The server starts automatically with the Assistant Panel.\",\n },\n \"claude-desktop\": {\n name: \"Claude Desktop\",\n getPath: () => {\n if (process.platform === \"win32\") {\n return path.join(\n process.env.APPDATA || \"\",\n \"Claude\",\n \"claude_desktop_config.json\",\n );\n }\n return path.join(\n os.homedir(),\n \"Library\",\n \"Application Support\",\n \"Claude\",\n \"claude_desktop_config.json\",\n );\n },\n config: {\n mcpServers: {\n \"assistant-ui\": {\n command: \"npx\",\n args: [\"-y\", \"@assistant-ui/mcp-docs-server\"],\n },\n },\n },\n postInstall: \"Restart Claude Desktop to activate.\",\n },\n};\n\nfunction deepMerge(target: any, source: any): any {\n const result = { ...target };\n for (const key of Object.keys(source)) {\n if (\n source[key] &&\n typeof source[key] === \"object\" &&\n !Array.isArray(source[key])\n ) {\n result[key] = deepMerge(result[key] || {}, source[key]);\n } else {\n result[key] = source[key];\n }\n }\n return result;\n}\n\nasync function installForTarget(target: MCPTarget): Promise<void> {\n if (target === \"claude-code\") {\n logger.info(\"Installing MCP server for Claude Code...\");\n logger.break();\n\n const child = spawn(\n \"claude\",\n [\n \"mcp\",\n \"add\",\n \"assistant-ui\",\n \"--\",\n \"npx\",\n \"-y\",\n \"@assistant-ui/mcp-docs-server\",\n ],\n {\n stdio: \"inherit\",\n },\n );\n\n return new Promise((resolve, reject) => {\n child.on(\"error\", (error) => {\n logger.error(`Failed to install: ${error.message}`);\n logger.info(\n \"Make sure Claude Code CLI is installed: https://docs.anthropic.com/en/docs/claude-code\",\n );\n reject(error);\n });\n\n child.on(\"close\", (code) => {\n if (code !== 0) {\n logger.error(`Installation failed with code ${code}`);\n reject(new Error(`Exit code ${code}`));\n } else {\n logger.break();\n logger.success(\"MCP server installed for Claude Code!\");\n logger.info(\n \"The server starts automatically. Try asking about assistant-ui!\",\n );\n resolve();\n }\n });\n });\n }\n\n if (target === \"claude-desktop\" && process.platform === \"linux\") {\n logger.error(\"Claude Desktop is not available on Linux.\");\n logger.info(\n \"See: https://claude.ai/download for supported operating systems.\",\n );\n throw new Error(\"Unsupported platform for Claude Desktop\");\n }\n\n const targetConfig = MCP_CONFIGS[target];\n const configPath = targetConfig.getPath();\n const configDir = path.dirname(configPath);\n\n logger.info(`Installing MCP server for ${targetConfig.name}...`);\n\n if (!fs.existsSync(configDir)) {\n fs.mkdirSync(configDir, { recursive: true });\n }\n\n let existingConfig: any = {};\n if (fs.existsSync(configPath)) {\n const content = fs.readFileSync(configPath, \"utf-8\");\n try {\n existingConfig = JSON.parse(content);\n } catch (e) {\n logger.error(`Could not parse existing config at ${configPath}`);\n logger.error(\n \"Please fix the JSON syntax error before running this command.\",\n );\n throw e;\n }\n }\n\n const newConfig = deepMerge(existingConfig, targetConfig.config);\n\n fs.writeFileSync(configPath, `${JSON.stringify(newConfig, null, 2)}\\n`);\n\n logger.break();\n logger.success(`MCP server installed for ${targetConfig.name}!`);\n logger.info(`Config written to: ${configPath}`);\n\n if (targetConfig.postInstall) {\n logger.break();\n logger.info(targetConfig.postInstall);\n }\n}\n\nexport const mcp = new Command()\n .name(\"mcp\")\n .description(\"install assistant-ui MCP docs server for your IDE\")\n .option(\"--cursor\", \"install for Cursor\")\n .option(\"--windsurf\", \"install for Windsurf\")\n .option(\"--vscode\", \"install for VSCode\")\n .option(\"--zed\", \"install for Zed\")\n .option(\"--claude-code\", \"install for Claude Code\")\n .option(\"--claude-desktop\", \"install for Claude Desktop\")\n .action(async (opts) => {\n const targets: MCPTarget[] = [];\n\n if (opts.cursor) targets.push(\"cursor\");\n if (opts.windsurf) targets.push(\"windsurf\");\n if (opts.vscode) targets.push(\"vscode\");\n if (opts.zed) targets.push(\"zed\");\n if (opts.claudeCode) targets.push(\"claude-code\");\n if (opts.claudeDesktop) targets.push(\"claude-desktop\");\n\n // If no target specified, prompt user\n if (targets.length === 0) {\n p.intro(\"assistant-ui MCP Server Installation\");\n\n const selected = await p.select({\n message: \"Select your IDE or tool:\",\n options: [\n { value: \"cursor\", label: \"Cursor\" },\n { value: \"windsurf\", label: \"Windsurf\" },\n { value: \"vscode\", label: \"VSCode\" },\n { value: \"zed\", label: \"Zed\" },\n { value: \"claude-code\", label: \"Claude Code\" },\n { value: \"claude-desktop\", label: \"Claude Desktop\" },\n ],\n });\n\n if (p.isCancel(selected)) {\n p.cancel(\"Installation cancelled.\");\n process.exit(0);\n }\n\n targets.push(selected as MCPTarget);\n }\n\n for (const target of targets) {\n try {\n await installForTarget(target);\n } catch {\n process.exit(1);\n }\n }\n });\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"update.js","names":["spawnSync"],"sources":["../../src/commands/update.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport { sync as spawnSync } from \"cross-spawn\";\nimport { logger } from \"../lib/utils/logger\";\nimport { getInstallCommand } from \"../lib/utils/package-manager\";\n\nexport const update = new Command()\n .name(\"update\")\n .description(\n \"Update all '@assistant-ui/*' and 'assistant-*' packages in package.json to latest versions using your package manager.\",\n )\n .option(\"--dry\", \"Print the package manager command instead of running it.\")\n .option(\n \"-c, --cwd <cwd>\",\n \"the working directory. defaults to the current directory.\",\n process.cwd(),\n )\n .action(async (opts) => {\n const packageJsonPath = path.join(opts.cwd, \"package.json\");\n if (!fs.existsSync(packageJsonPath)) {\n logger.error(\"No package.json found in the current directory.\");\n process.exit(1);\n }\n\n const pkg = JSON.parse(fs.readFileSync(packageJsonPath, \"utf-8\"));\n const sections = [\"dependencies\", \"devDependencies\"];\n const targets: string[] = [];\n\n for (const section of sections) {\n if (!pkg[section]) continue;\n for (const dep in pkg[section]) {\n if (\n dep.startsWith(\"@assistant-ui/\") ||\n dep === \"assistant-stream\" ||\n dep === \"assistant-cloud\"\n ) {\n targets.push(dep);\n }\n }\n }\n\n if (!targets.length) {\n logger.warn(\"No matching packages found to update.\");\n return;\n }\n\n logger.info(`Found ${targets.length} package(s) to update:`);\n targets.forEach((pkg) => {\n logger.info(` - ${pkg}`);\n });\n logger.break();\n\n // Build command using the utility\n const installCmd = await getInstallCommand(\n targets.map((d) => `${d}@latest`),\n opts.cwd,\n );\n\n if (opts.dry) {\n logger.info(\"Dry run: would run the following command:\");\n logger.info(` ${installCmd.command} ${installCmd.args.join(\" \")}`);\n return;\n }\n\n logger.step(\"Updating packages...\");\n const result = spawnSync(installCmd.command, installCmd.args, {\n stdio: \"inherit\",\n cwd: opts.cwd,\n });\n\n if (result.status !== 0) {\n logger.error(\"Package manager update failed.\");\n process.exit(result.status || 1);\n }\n\n logger.break();\n logger.success(\"All packages updated to latest version!\");\n });\n"],"mappings":";;;;;;;AAOA,MAAa,SAAS,IAAI,QAAQ,
|
|
1
|
+
{"version":3,"file":"update.js","names":["spawnSync"],"sources":["../../src/commands/update.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport { sync as spawnSync } from \"cross-spawn\";\nimport { logger } from \"../lib/utils/logger\";\nimport { getInstallCommand } from \"../lib/utils/package-manager\";\n\nexport const update = new Command()\n .name(\"update\")\n .description(\n \"Update all '@assistant-ui/*' and 'assistant-*' packages in package.json to latest versions using your package manager.\",\n )\n .option(\"--dry\", \"Print the package manager command instead of running it.\")\n .option(\n \"-c, --cwd <cwd>\",\n \"the working directory. defaults to the current directory.\",\n process.cwd(),\n )\n .action(async (opts) => {\n const packageJsonPath = path.join(opts.cwd, \"package.json\");\n if (!fs.existsSync(packageJsonPath)) {\n logger.error(\"No package.json found in the current directory.\");\n process.exit(1);\n }\n\n const pkg = JSON.parse(fs.readFileSync(packageJsonPath, \"utf-8\"));\n const sections = [\"dependencies\", \"devDependencies\"];\n const targets: string[] = [];\n\n for (const section of sections) {\n if (!pkg[section]) continue;\n for (const dep in pkg[section]) {\n if (\n dep.startsWith(\"@assistant-ui/\") ||\n dep === \"assistant-stream\" ||\n dep === \"assistant-cloud\"\n ) {\n targets.push(dep);\n }\n }\n }\n\n if (!targets.length) {\n logger.warn(\"No matching packages found to update.\");\n return;\n }\n\n logger.info(`Found ${targets.length} package(s) to update:`);\n targets.forEach((pkg) => {\n logger.info(` - ${pkg}`);\n });\n logger.break();\n\n // Build command using the utility\n const installCmd = await getInstallCommand(\n targets.map((d) => `${d}@latest`),\n opts.cwd,\n );\n\n if (opts.dry) {\n logger.info(\"Dry run: would run the following command:\");\n logger.info(` ${installCmd.command} ${installCmd.args.join(\" \")}`);\n return;\n }\n\n logger.step(\"Updating packages...\");\n const result = spawnSync(installCmd.command, installCmd.args, {\n stdio: \"inherit\",\n cwd: opts.cwd,\n });\n\n if (result.status !== 0) {\n logger.error(\"Package manager update failed.\");\n process.exit(result.status || 1);\n }\n\n logger.break();\n logger.success(\"All packages updated to latest version!\");\n });\n"],"mappings":";;;;;;;AAOA,MAAa,SAAS,IAAI,QAAQ,CAAC,CAChC,KAAK,QAAQ,CAAC,CACd,YACC,wHACF,CAAC,CACA,OAAO,SAAS,0DAA0D,CAAC,CAC3E,OACC,mBACA,6DACA,QAAQ,IAAI,CACd,CAAC,CACA,OAAO,OAAO,SAAS;CACtB,MAAM,kBAAkB,KAAK,KAAK,KAAK,KAAK,cAAc;CAC1D,IAAI,CAAC,GAAG,WAAW,eAAe,GAAG;EACnC,OAAO,MAAM,iDAAiD;EAC9D,QAAQ,KAAK,CAAC;CAChB;CAEA,MAAM,MAAM,KAAK,MAAM,GAAG,aAAa,iBAAiB,OAAO,CAAC;CAChE,MAAM,WAAW,CAAC,gBAAgB,iBAAiB;CACnD,MAAM,UAAoB,CAAC;CAE3B,KAAK,MAAM,WAAW,UAAU;EAC9B,IAAI,CAAC,IAAI,UAAU;EACnB,KAAK,MAAM,OAAO,IAAI,UACpB,IACE,IAAI,WAAW,gBAAgB,KAC/B,QAAQ,sBACR,QAAQ,mBAER,QAAQ,KAAK,GAAG;CAGtB;CAEA,IAAI,CAAC,QAAQ,QAAQ;EACnB,OAAO,KAAK,uCAAuC;EACnD;CACF;CAEA,OAAO,KAAK,SAAS,QAAQ,OAAO,uBAAuB;CAC3D,QAAQ,SAAS,QAAQ;EACvB,OAAO,KAAK,OAAO,KAAK;CAC1B,CAAC;CACD,OAAO,MAAM;CAGb,MAAM,aAAa,MAAM,kBACvB,QAAQ,KAAK,MAAM,GAAG,EAAE,QAAQ,GAChC,KAAK,GACP;CAEA,IAAI,KAAK,KAAK;EACZ,OAAO,KAAK,2CAA2C;EACvD,OAAO,KAAK,KAAK,WAAW,QAAQ,GAAG,WAAW,KAAK,KAAK,GAAG,GAAG;EAClE;CACF;CAEA,OAAO,KAAK,sBAAsB;CAClC,MAAM,SAASA,KAAU,WAAW,SAAS,WAAW,MAAM;EAC5D,OAAO;EACP,KAAK,KAAK;CACZ,CAAC;CAED,IAAI,OAAO,WAAW,GAAG;EACvB,OAAO,MAAM,gCAAgC;EAC7C,QAAQ,KAAK,OAAO,UAAU,CAAC;CACjC;CAEA,OAAO,MAAM;CACb,OAAO,QAAQ,yCAAyC;AAC1D,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"upgrade.js","names":[],"sources":["../../src/commands/upgrade.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport { transform } from \"../lib/transform\";\nimport { upgrade } from \"../lib/upgrade\";\nimport debug from \"debug\";\n\nexport interface TransformOptions {\n dry?: boolean;\n print?: boolean;\n verbose?: boolean;\n jscodeshift?: string;\n}\n\nconst error = debug(\"codemod:error\");\ndebug.enable(\"codemod:*\");\n\nconst addTransformOptions = (command: Command): Command => {\n return command\n .option(\"-d, --dry\", \"Dry run (no changes are made to files)\")\n .option(\"-p, --print\", \"Print transformed files to stdout\")\n .option(\"--verbose\", \"Show more information about the transform process\")\n .option(\n \"-j, --jscodeshift <options>\",\n \"Pass options directly to jscodeshift\",\n );\n};\n\nexport const codemodCommand = addTransformOptions(\n new Command()\n .name(\"codemod\")\n .description(\"CLI tool for running codemods\")\n .argument(\"<codemod>\", \"Codemod to run (e.g., rewrite-framework-imports)\")\n .argument(\"<source>\", \"Path to source files or directory to transform\"),\n).action((codemod, source, options: TransformOptions) => {\n try {\n transform(codemod, source, options);\n } catch (err) {\n const errorMessage = err instanceof Error ? err.message : String(err);\n const errorStack = err instanceof Error ? err.stack : undefined;\n error(`Error transforming: ${errorMessage}`);\n if (errorStack) {\n error(errorStack);\n }\n process.exit(1);\n }\n});\n\nexport const upgradeCommand = addTransformOptions(\n new Command()\n .command(\"upgrade\")\n .description(\"Upgrade ai package dependencies and apply codemods\"),\n).action((options: TransformOptions) => {\n try {\n upgrade(options);\n } catch (err) {\n const errorMessage = err instanceof Error ? err.message : String(err);\n const errorStack = err instanceof Error ? err.stack : undefined;\n error(`Error upgrading: ${errorMessage}`);\n if (errorStack) {\n error(errorStack);\n }\n process.exit(1);\n }\n});\n"],"mappings":";;;;;AAYA,MAAM,QAAQ,MAAM,eAAe;AACnC,MAAM,OAAO,WAAW;AAExB,MAAM,uBAAuB,YAA8B;CACzD,OAAO,QACJ,OAAO,aAAa,wCAAwC,
|
|
1
|
+
{"version":3,"file":"upgrade.js","names":[],"sources":["../../src/commands/upgrade.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport { transform } from \"../lib/transform\";\nimport { upgrade } from \"../lib/upgrade\";\nimport debug from \"debug\";\n\nexport interface TransformOptions {\n dry?: boolean;\n print?: boolean;\n verbose?: boolean;\n jscodeshift?: string;\n}\n\nconst error = debug(\"codemod:error\");\ndebug.enable(\"codemod:*\");\n\nconst addTransformOptions = (command: Command): Command => {\n return command\n .option(\"-d, --dry\", \"Dry run (no changes are made to files)\")\n .option(\"-p, --print\", \"Print transformed files to stdout\")\n .option(\"--verbose\", \"Show more information about the transform process\")\n .option(\n \"-j, --jscodeshift <options>\",\n \"Pass options directly to jscodeshift\",\n );\n};\n\nexport const codemodCommand = addTransformOptions(\n new Command()\n .name(\"codemod\")\n .description(\"CLI tool for running codemods\")\n .argument(\"<codemod>\", \"Codemod to run (e.g., rewrite-framework-imports)\")\n .argument(\"<source>\", \"Path to source files or directory to transform\"),\n).action((codemod, source, options: TransformOptions) => {\n try {\n transform(codemod, source, options);\n } catch (err) {\n const errorMessage = err instanceof Error ? err.message : String(err);\n const errorStack = err instanceof Error ? err.stack : undefined;\n error(`Error transforming: ${errorMessage}`);\n if (errorStack) {\n error(errorStack);\n }\n process.exit(1);\n }\n});\n\nexport const upgradeCommand = addTransformOptions(\n new Command()\n .command(\"upgrade\")\n .description(\"Upgrade ai package dependencies and apply codemods\"),\n).action((options: TransformOptions) => {\n try {\n upgrade(options);\n } catch (err) {\n const errorMessage = err instanceof Error ? err.message : String(err);\n const errorStack = err instanceof Error ? err.stack : undefined;\n error(`Error upgrading: ${errorMessage}`);\n if (errorStack) {\n error(errorStack);\n }\n process.exit(1);\n }\n});\n"],"mappings":";;;;;AAYA,MAAM,QAAQ,MAAM,eAAe;AACnC,MAAM,OAAO,WAAW;AAExB,MAAM,uBAAuB,YAA8B;CACzD,OAAO,QACJ,OAAO,aAAa,wCAAwC,CAAC,CAC7D,OAAO,eAAe,mCAAmC,CAAC,CAC1D,OAAO,aAAa,mDAAmD,CAAC,CACxE,OACC,+BACA,sCACF;AACJ;AAEA,MAAa,iBAAiB,oBAC5B,IAAI,QAAQ,CAAC,CACV,KAAK,SAAS,CAAC,CACf,YAAY,+BAA+B,CAAC,CAC5C,SAAS,aAAa,kDAAkD,CAAC,CACzE,SAAS,YAAY,gDAAgD,CAC1E,CAAC,CAAC,QAAQ,SAAS,QAAQ,YAA8B;CACvD,IAAI;EACF,UAAU,SAAS,QAAQ,OAAO;CACpC,SAAS,KAAK;EACZ,MAAM,eAAe,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;EACpE,MAAM,aAAa,eAAe,QAAQ,IAAI,QAAQ,KAAA;EACtD,MAAM,uBAAuB,cAAc;EAC3C,IAAI,YACF,MAAM,UAAU;EAElB,QAAQ,KAAK,CAAC;CAChB;AACF,CAAC;AAED,MAAa,iBAAiB,oBAC5B,IAAI,QAAQ,CAAC,CACV,QAAQ,SAAS,CAAC,CAClB,YAAY,oDAAoD,CACrE,CAAC,CAAC,QAAQ,YAA8B;CACtC,IAAI;EACF,QAAQ,OAAO;CACjB,SAAS,KAAK;EACZ,MAAM,eAAe,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;EACpE,MAAM,aAAa,eAAe,QAAQ,IAAI,QAAQ,KAAA;EACtD,MAAM,oBAAoB,cAAc;EACxC,IAAI,YACF,MAAM,UAAU;EAElB,QAAQ,KAAK,CAAC;CAChB;AACF,CAAC"}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { Command } from \"commander\";\nimport { create } from \"./commands/create\";\nimport { add } from \"./commands/add\";\nimport { codemodCommand, upgradeCommand } from \"./commands/upgrade\";\nimport { init } from \"./commands/init\";\nimport { update } from \"./commands/update\";\nimport { mcp } from \"./commands/mcp\";\nimport { agent } from \"./commands/agent\";\nimport { info } from \"./commands/info\";\nimport { doctor } from \"./commands/doctor\";\n\nprocess.on(\"SIGINT\", () => process.exit(0));\nprocess.on(\"SIGTERM\", () => process.exit(0));\n\nfunction main() {\n const program = new Command()\n .name(\"assistant-ui\")\n .description(\"add components and dependencies to your project\");\n\n program.addCommand(add);\n program.addCommand(create);\n program.addCommand(init);\n program.addCommand(mcp);\n program.addCommand(codemodCommand);\n program.addCommand(upgradeCommand);\n program.addCommand(update);\n program.addCommand(agent);\n program.addCommand(info);\n program.addCommand(doctor);\n\n program.parse();\n}\n\nmain();\n"],"mappings":";;;;;;;;;;;;AAaA,QAAQ,GAAG,gBAAgB,QAAQ,KAAK,CAAC,CAAC;AAC1C,QAAQ,GAAG,iBAAiB,QAAQ,KAAK,CAAC,CAAC;AAE3C,SAAS,OAAO;CACd,MAAM,UAAU,IAAI,QAAQ,
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { Command } from \"commander\";\nimport { create } from \"./commands/create\";\nimport { add } from \"./commands/add\";\nimport { codemodCommand, upgradeCommand } from \"./commands/upgrade\";\nimport { init } from \"./commands/init\";\nimport { update } from \"./commands/update\";\nimport { mcp } from \"./commands/mcp\";\nimport { agent } from \"./commands/agent\";\nimport { info } from \"./commands/info\";\nimport { doctor } from \"./commands/doctor\";\n\nprocess.on(\"SIGINT\", () => process.exit(0));\nprocess.on(\"SIGTERM\", () => process.exit(0));\n\nfunction main() {\n const program = new Command()\n .name(\"assistant-ui\")\n .description(\"add components and dependencies to your project\");\n\n program.addCommand(add);\n program.addCommand(create);\n program.addCommand(init);\n program.addCommand(mcp);\n program.addCommand(codemodCommand);\n program.addCommand(upgradeCommand);\n program.addCommand(update);\n program.addCommand(agent);\n program.addCommand(info);\n program.addCommand(doctor);\n\n program.parse();\n}\n\nmain();\n"],"mappings":";;;;;;;;;;;;AAaA,QAAQ,GAAG,gBAAgB,QAAQ,KAAK,CAAC,CAAC;AAC1C,QAAQ,GAAG,iBAAiB,QAAQ,KAAK,CAAC,CAAC;AAE3C,SAAS,OAAO;CACd,MAAM,UAAU,IAAI,QAAQ,CAAC,CAC1B,KAAK,cAAc,CAAC,CACpB,YAAY,iDAAiD;CAEhE,QAAQ,WAAW,GAAG;CACtB,QAAQ,WAAW,MAAM;CACzB,QAAQ,WAAW,IAAI;CACvB,QAAQ,WAAW,GAAG;CACtB,QAAQ,WAAW,cAAc;CACjC,QAAQ,WAAW,cAAc;CACjC,QAAQ,WAAW,MAAM;CACzB,QAAQ,WAAW,KAAK;CACxB,QAAQ,WAAW,IAAI;CACvB,QAAQ,WAAW,MAAM;CAEzB,QAAQ,MAAM;AAChB;AAEA,KAAK"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-project.js","names":["path","fs","globSync"],"sources":["../../src/lib/create-project.ts"],"sourcesContent":["import * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport { downloadTemplate } from \"giget\";\nimport { sync as globSync } from \"glob\";\nimport { detect } from \"detect-package-manager\";\nimport { logger } from \"./utils/logger\";\nimport { runSpawn, SpawnExitError } from \"./run-spawn\";\n\nexport type PackageManagerName = \"npm\" | \"pnpm\" | \"yarn\" | \"bun\";\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 async function resolveLatestReleaseRef(): Promise<string | undefined> {\n try {\n const res = await fetch(\n \"https://api.github.com/repos/assistant-ui/assistant-ui/releases/latest\",\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 DOWNLOAD_TIMEOUT_MS = 30_000;\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 try {\n const downloadPromise = downloadTemplate(source, {\n dir: destDir,\n force: true,\n silent: 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 } finally {\n clearTimeout(timer!);\n }\n } finally {\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\nfunction detectFromUserAgent(): PackageManagerName | undefined {\n const ua = process.env.npm_config_user_agent;\n if (!ua) return undefined;\n if (ua.startsWith(\"bun/\")) return \"bun\";\n if (ua.startsWith(\"pnpm/\")) return \"pnpm\";\n if (ua.startsWith(\"yarn/\")) return \"yarn\";\n if (ua.startsWith(\"npm/\")) return \"npm\";\n return undefined;\n}\n\nexport async function resolvePackageManagerForCwd(\n cwd: string,\n packageManager?: PackageManagerName,\n): Promise<PackageManagerName> {\n if (packageManager) return packageManager;\n const fromAgent = detectFromUserAgent();\n if (fromAgent) return fromAgent;\n try {\n return await detect({ cwd });\n } catch {\n return \"npm\";\n }\n}\n\nexport async function transformProject(\n projectDir: string,\n opts: TransformOptions,\n): Promise<void> {\n logger.step(\"Transforming package.json...\");\n transformPackageJson(projectDir);\n\n let assistantUI: string[] | undefined;\n let shadcnUI: string[] | undefined;\n\n if (!opts.hasLocalComponents) {\n logger.step(\"Transforming project files...\");\n\n transformTsConfig(projectDir);\n transformCssFiles(projectDir);\n\n const components = scanRequiredComponents(projectDir);\n assistantUI = components.assistantUI;\n shadcnUI = components.shadcnUI;\n }\n\n const pm = opts.packageManager;\n if (!opts.skipInstall) {\n logger.step(\"Installing dependencies...\");\n await installDependencies(projectDir, pm);\n }\n\n if (!opts.hasLocalComponents && shadcnUI && assistantUI) {\n const allShadcn = shadcnUI.includes(\"utils\")\n ? shadcnUI\n : [...shadcnUI, \"utils\"];\n const auiComponents = assistantUI.map((c) => `@assistant-ui/${c}`);\n const components = [...allShadcn, ...auiComponents];\n logger.step(`Installing components: ${components.join(\", \")}...`);\n await installShadcnRegistry(projectDir, components, \"components\", pm);\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 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 = JSON.parse(content);\n\n // Remove workspace paths\n if (tsconfig.compilerOptions?.paths) {\n delete tsconfig.compilerOptions.paths[\"@/components/assistant-ui/*\"];\n delete tsconfig.compilerOptions.paths[\"@/components/icons/*\"];\n delete tsconfig.compilerOptions.paths[\"@/components/ui/*\"];\n delete tsconfig.compilerOptions.paths[\"@/hooks/*\"];\n delete tsconfig.compilerOptions.paths[\"@/lib/utils\"];\n delete tsconfig.compilerOptions.paths[\"@assistant-ui/ui/*\"];\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 const cssFiles = globSync(\"**/*.css\", {\n cwd: projectDir,\n ignore: LOCAL_PROJECT_ARTIFACT_GLOB_IGNORES,\n });\n\n for (const file of cssFiles) {\n const fullPath = path.join(projectDir, file);\n try {\n const content = fs.readFileSync(fullPath, \"utf-8\");\n\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 // Ignore files that cannot be read/written\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\nfunction scanRequiredComponents(projectDir: string): RequiredComponents {\n const files = globSync(\"**/*.{ts,tsx}\", {\n cwd: projectDir,\n ignore: LOCAL_PROJECT_ARTIFACT_GLOB_IGNORES,\n });\n\n const assistantUIComponents = new Set<string>();\n const shadcnUIComponents = new Set<string>();\n\n for (const file of files) {\n const fullPath = path.join(projectDir, file);\n try {\n const content = fs.readFileSync(fullPath, \"utf-8\");\n\n const assistantUIRegex =\n /from\\s+[\"']@\\/components\\/assistant-ui\\/([^\"']+)[\"']/g;\n for (const match of content.matchAll(assistantUIRegex)) {\n assistantUIComponents.add(stripImportExtension(match[1]!));\n }\n\n const uiRegex = /from\\s+[\"']@\\/components\\/ui\\/([^\"']+)[\"']/g;\n for (const match of content.matchAll(uiRegex)) {\n shadcnUIComponents.add(stripImportExtension(match[1]!));\n }\n } catch {\n // Ignore files that cannot be read\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 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<void> {\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 addArgs = [...dlxArgs, \"shadcn@latest\", \"add\", ...components, \"--yes\"];\n\n try {\n await runSpawn(cmd, addArgs, projectDir);\n } catch (error) {\n if (error instanceof SpawnExitError) {\n logger.warn(\n `shadcn exited with code ${error.code}. Run the following to retry:\\n ${cmd} ${addArgs.slice(0, -1).join(\" \")}`,\n );\n return;\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":["path","fs","globSync"],"sources":["../../src/lib/create-project.ts"],"sourcesContent":["import * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport { downloadTemplate } from \"giget\";\nimport { sync as globSync } from \"glob\";\nimport { detect } from \"detect-package-manager\";\nimport { logger } from \"./utils/logger\";\nimport { runSpawn, SpawnExitError } from \"./run-spawn\";\n\nexport type PackageManagerName = \"npm\" | \"pnpm\" | \"yarn\" | \"bun\";\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 async function resolveLatestReleaseRef(): Promise<string | undefined> {\n try {\n const res = await fetch(\n \"https://api.github.com/repos/assistant-ui/assistant-ui/releases/latest\",\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 DOWNLOAD_TIMEOUT_MS = 30_000;\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 try {\n const downloadPromise = downloadTemplate(source, {\n dir: destDir,\n force: true,\n silent: 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 } finally {\n clearTimeout(timer!);\n }\n } finally {\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\nfunction detectFromUserAgent(): PackageManagerName | undefined {\n const ua = process.env.npm_config_user_agent;\n if (!ua) return undefined;\n if (ua.startsWith(\"bun/\")) return \"bun\";\n if (ua.startsWith(\"pnpm/\")) return \"pnpm\";\n if (ua.startsWith(\"yarn/\")) return \"yarn\";\n if (ua.startsWith(\"npm/\")) return \"npm\";\n return undefined;\n}\n\nexport async function resolvePackageManagerForCwd(\n cwd: string,\n packageManager?: PackageManagerName,\n): Promise<PackageManagerName> {\n if (packageManager) return packageManager;\n const fromAgent = detectFromUserAgent();\n if (fromAgent) return fromAgent;\n try {\n return await detect({ cwd });\n } catch {\n return \"npm\";\n }\n}\n\nexport async function transformProject(\n projectDir: string,\n opts: TransformOptions,\n): Promise<void> {\n logger.step(\"Transforming package.json...\");\n transformPackageJson(projectDir);\n\n let assistantUI: string[] | undefined;\n let shadcnUI: string[] | undefined;\n\n if (!opts.hasLocalComponents) {\n logger.step(\"Transforming project files...\");\n\n transformTsConfig(projectDir);\n transformCssFiles(projectDir);\n\n const components = scanRequiredComponents(projectDir);\n assistantUI = components.assistantUI;\n shadcnUI = components.shadcnUI;\n }\n\n const pm = opts.packageManager;\n if (!opts.skipInstall) {\n logger.step(\"Installing dependencies...\");\n await installDependencies(projectDir, pm);\n }\n\n if (!opts.hasLocalComponents && shadcnUI && assistantUI) {\n const allShadcn = shadcnUI.includes(\"utils\")\n ? shadcnUI\n : [...shadcnUI, \"utils\"];\n const auiComponents = assistantUI.map((c) => `@assistant-ui/${c}`);\n const components = [...allShadcn, ...auiComponents];\n logger.step(`Installing components: ${components.join(\", \")}...`);\n await installShadcnRegistry(projectDir, components, \"components\", pm);\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 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 = JSON.parse(content);\n\n // Remove workspace paths\n if (tsconfig.compilerOptions?.paths) {\n delete tsconfig.compilerOptions.paths[\"@/components/assistant-ui/*\"];\n delete tsconfig.compilerOptions.paths[\"@/components/icons/*\"];\n delete tsconfig.compilerOptions.paths[\"@/components/ui/*\"];\n delete tsconfig.compilerOptions.paths[\"@/hooks/*\"];\n delete tsconfig.compilerOptions.paths[\"@/lib/utils\"];\n delete tsconfig.compilerOptions.paths[\"@assistant-ui/ui/*\"];\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 const cssFiles = globSync(\"**/*.css\", {\n cwd: projectDir,\n ignore: LOCAL_PROJECT_ARTIFACT_GLOB_IGNORES,\n });\n\n for (const file of cssFiles) {\n const fullPath = path.join(projectDir, file);\n try {\n const content = fs.readFileSync(fullPath, \"utf-8\");\n\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 // Ignore files that cannot be read/written\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\nfunction scanRequiredComponents(projectDir: string): RequiredComponents {\n const files = globSync(\"**/*.{ts,tsx}\", {\n cwd: projectDir,\n ignore: LOCAL_PROJECT_ARTIFACT_GLOB_IGNORES,\n });\n\n const assistantUIComponents = new Set<string>();\n const shadcnUIComponents = new Set<string>();\n\n for (const file of files) {\n const fullPath = path.join(projectDir, file);\n try {\n const content = fs.readFileSync(fullPath, \"utf-8\");\n\n const assistantUIRegex =\n /from\\s+[\"']@\\/components\\/assistant-ui\\/([^\"']+)[\"']/g;\n for (const match of content.matchAll(assistantUIRegex)) {\n assistantUIComponents.add(stripImportExtension(match[1]!));\n }\n\n const uiRegex = /from\\s+[\"']@\\/components\\/ui\\/([^\"']+)[\"']/g;\n for (const match of content.matchAll(uiRegex)) {\n shadcnUIComponents.add(stripImportExtension(match[1]!));\n }\n } catch {\n // Ignore files that cannot be read\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 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<void> {\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 addArgs = [...dlxArgs, \"shadcn@latest\", \"add\", ...components, \"--yes\"];\n\n try {\n await runSpawn(cmd, addArgs, projectDir);\n } catch (error) {\n if (error instanceof SpawnExitError) {\n logger.warn(\n `shadcn exited with code ${error.code}. Run the following to retry:\\n ${cmd} ${addArgs.slice(0, -1).join(\" \")}`,\n );\n return;\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 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transform.js","names":["globSync","fs"],"sources":["../../src/lib/transform.ts"],"sourcesContent":["import { execFileSync, spawnSync } from \"node:child_process\";\nimport 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\";\n\nconst log = debug(\"codemod:transform\");\nconst error = debug(\"codemod:transform:error\");\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = path.dirname(__filename);\n\n/**\n * Gets the list of files that need to be processed in the codebase\n * Only includes files that contain \"assistant-ui\" to optimize performance\n */\nexport function getRelevantFiles(cwd: string): string[] {\n const pattern = \"**/*.{js,jsx,ts,tsx}\";\n const files = globSync(pattern, {\n cwd,\n ignore: [\n \"**/node_modules/**\",\n \"**/dist/**\",\n \"**/build/**\",\n \"**/*.min.js\",\n \"**/*.bundle.js\",\n ],\n });\n\n // Filter files to only include those containing \"assistant-ui\"\n const relevantFiles = files.filter((file) => {\n try {\n const content = fs.readFileSync(path.join(cwd, file), \"utf8\");\n return content.includes(\"assistant-ui\");\n } catch {\n return false;\n }\n });\n\n return relevantFiles.map((file) => path.join(cwd, file));\n}\n\n/**\n * Counts the number of files that need to be processed\n */\nexport function countFilesToProcess(cwd: string): number {\n return getRelevantFiles(cwd).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 ];\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\nfunction parseErrors(transform: string, output: string): TransformErrors {\n const errors: TransformErrors = [];\n const errorRegex = /ERR (.+) Transformation error/g;\n const syntaxErrorRegex = /SyntaxError: .+/g;\n\n for (const match of output.matchAll(errorRegex)) {\n const filename = match[1]!;\n const syntaxErrorMatch = syntaxErrorRegex.exec(output);\n if (syntaxErrorMatch) {\n const summary = syntaxErrorMatch[0];\n errors.push({ transform, filename, summary });\n }\n }\n\n return errors;\n}\n\nexport 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): 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 // Use spawn instead of execFileSync to capture output in real-time\n if (options.onProgress) {\n const result = spawnSync(command[0]!, command.slice(1), {\n encoding: \"utf8\",\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n });\n\n const stdout = result.stdout || \"\";\n\n // Count the number of processed files from the output\n const processedFiles = (stdout.match(/Processing file/g) || []).length;\n if (options.onProgress) {\n options.onProgress(processedFiles);\n }\n\n const errors = parseErrors(codemod, stdout);\n if (options.logStatus && errors.length > 0) {\n errors.forEach(({ transform, filename, summary }) => {\n error(\n `Error applying codemod [codemod=${transform}, path=${filename}, summary=${summary}]`,\n );\n });\n }\n return errors;\n } else {\n // Use the original synchronous approach if no progress callback\n const stdout = execFileSync(command[0]!, command.slice(1), {\n encoding: \"utf8\",\n stdio: \"pipe\",\n });\n const errors = parseErrors(codemod, stdout);\n if (options.logStatus && errors.length > 0) {\n errors.forEach(({ transform, filename, summary }) => {\n error(\n `Error applying codemod [codemod=${transform}, path=${filename}, summary=${summary}]`,\n );\n });\n }\n return errors;\n }\n}\n"],"mappings":";;;;;;;AAQA,MAAM,MAAM,MAAM,mBAAmB;AACrC,MAAM,QAAQ,MAAM,yBAAyB;AAE7C,MAAM,aAAa,cAAc,OAAO,KAAK,GAAG;AAChD,MAAM,YAAY,KAAK,QAAQ,UAAU;;;;;AAMzC,SAAgB,iBAAiB,KAAuB;CAuBtD,OArBcA,KAAS,wBAAS;EAC9B;EACA,QAAQ;GACN;GACA;GACA;GACA;GACA;EACF;CACF,CAG0B,
|
|
1
|
+
{"version":3,"file":"transform.js","names":["globSync","fs"],"sources":["../../src/lib/transform.ts"],"sourcesContent":["import { execFileSync, spawnSync } from \"node:child_process\";\nimport 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\";\n\nconst log = debug(\"codemod:transform\");\nconst error = debug(\"codemod:transform:error\");\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = path.dirname(__filename);\n\n/**\n * Gets the list of files that need to be processed in the codebase\n * Only includes files that contain \"assistant-ui\" to optimize performance\n */\nexport function getRelevantFiles(cwd: string): string[] {\n const pattern = \"**/*.{js,jsx,ts,tsx}\";\n const files = globSync(pattern, {\n cwd,\n ignore: [\n \"**/node_modules/**\",\n \"**/dist/**\",\n \"**/build/**\",\n \"**/*.min.js\",\n \"**/*.bundle.js\",\n ],\n });\n\n // Filter files to only include those containing \"assistant-ui\"\n const relevantFiles = files.filter((file) => {\n try {\n const content = fs.readFileSync(path.join(cwd, file), \"utf8\");\n return content.includes(\"assistant-ui\");\n } catch {\n return false;\n }\n });\n\n return relevantFiles.map((file) => path.join(cwd, file));\n}\n\n/**\n * Counts the number of files that need to be processed\n */\nexport function countFilesToProcess(cwd: string): number {\n return getRelevantFiles(cwd).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 ];\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\nfunction parseErrors(transform: string, output: string): TransformErrors {\n const errors: TransformErrors = [];\n const errorRegex = /ERR (.+) Transformation error/g;\n const syntaxErrorRegex = /SyntaxError: .+/g;\n\n for (const match of output.matchAll(errorRegex)) {\n const filename = match[1]!;\n const syntaxErrorMatch = syntaxErrorRegex.exec(output);\n if (syntaxErrorMatch) {\n const summary = syntaxErrorMatch[0];\n errors.push({ transform, filename, summary });\n }\n }\n\n return errors;\n}\n\nexport 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): 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 // Use spawn instead of execFileSync to capture output in real-time\n if (options.onProgress) {\n const result = spawnSync(command[0]!, command.slice(1), {\n encoding: \"utf8\",\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n });\n\n const stdout = result.stdout || \"\";\n\n // Count the number of processed files from the output\n const processedFiles = (stdout.match(/Processing file/g) || []).length;\n if (options.onProgress) {\n options.onProgress(processedFiles);\n }\n\n const errors = parseErrors(codemod, stdout);\n if (options.logStatus && errors.length > 0) {\n errors.forEach(({ transform, filename, summary }) => {\n error(\n `Error applying codemod [codemod=${transform}, path=${filename}, summary=${summary}]`,\n );\n });\n }\n return errors;\n } else {\n // Use the original synchronous approach if no progress callback\n const stdout = execFileSync(command[0]!, command.slice(1), {\n encoding: \"utf8\",\n stdio: \"pipe\",\n });\n const errors = parseErrors(codemod, stdout);\n if (options.logStatus && errors.length > 0) {\n errors.forEach(({ transform, filename, summary }) => {\n error(\n `Error applying codemod [codemod=${transform}, path=${filename}, summary=${summary}]`,\n );\n });\n }\n return errors;\n }\n}\n"],"mappings":";;;;;;;AAQA,MAAM,MAAM,MAAM,mBAAmB;AACrC,MAAM,QAAQ,MAAM,yBAAyB;AAE7C,MAAM,aAAa,cAAc,OAAO,KAAK,GAAG;AAChD,MAAM,YAAY,KAAK,QAAQ,UAAU;;;;;AAMzC,SAAgB,iBAAiB,KAAuB;CAuBtD,OArBcA,KAAS,wBAAS;EAC9B;EACA,QAAQ;GACN;GACA;GACA;GACA;GACA;EACF;CACF,CAG0B,CAAC,CAAC,QAAQ,SAAS;EAC3C,IAAI;GAEF,OADgBC,KAAG,aAAa,KAAK,KAAK,KAAK,IAAI,GAAG,MACzC,CAAC,CAAC,SAAS,cAAc;EACxC,QAAQ;GACN,OAAO;EACT;CACF,CAEmB,CAAC,CAAC,KAAK,SAAS,KAAK,KAAK,KAAK,IAAI,CAAC;AACzD;;;;AAKA,SAAgB,oBAAoB,KAAqB;CACvD,OAAO,iBAAiB,GAAG,CAAC,CAAC;AAC/B;AAEA,SAAS,aACP,aACA,aACA,SACU;CACV,MAAM,UAAU;EACd;EACA;EACA;EACA;EACA,GAAG;EACH;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,SAAS,YAAY,WAAmB,QAAiC;CACvE,MAAM,SAA0B,CAAC;CACjC,MAAM,aAAa;CACnB,MAAM,mBAAmB;CAEzB,KAAK,MAAM,SAAS,OAAO,SAAS,UAAU,GAAG;EAC/C,MAAM,WAAW,MAAM;EACvB,MAAM,mBAAmB,iBAAiB,KAAK,MAAM;EACrD,IAAI,kBAAkB;GACpB,MAAM,UAAU,iBAAiB;GACjC,OAAO,KAAK;IAAE;IAAW;IAAU;GAAQ,CAAC;EAC9C;CACF;CAEA,OAAO;AACT;AAEA,SAAgB,UACd,SACA,QACA,kBACA,UAII,EAAE,WAAW,KAAK,GACL;CACjB,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;CAGvE,IAAI,QAAQ,YAAY;EAMtB,MAAM,SALS,UAAU,QAAQ,IAAK,QAAQ,MAAM,CAAC,GAAG;GACtD,UAAU;GACV,OAAO;IAAC;IAAU;IAAQ;GAAM;EAClC,CAEoB,CAAC,CAAC,UAAU;EAGhC,MAAM,kBAAkB,OAAO,MAAM,kBAAkB,KAAK,CAAC,EAAA,CAAG;EAChE,IAAI,QAAQ,YACV,QAAQ,WAAW,cAAc;EAGnC,MAAM,SAAS,YAAY,SAAS,MAAM;EAC1C,IAAI,QAAQ,aAAa,OAAO,SAAS,GACvC,OAAO,SAAS,EAAE,WAAW,UAAU,cAAc;GACnD,MACE,mCAAmC,UAAU,SAAS,SAAS,YAAY,QAAQ,EACrF;EACF,CAAC;EAEH,OAAO;CACT,OAAO;EAML,MAAM,SAAS,YAAY,SAJZ,aAAa,QAAQ,IAAK,QAAQ,MAAM,CAAC,GAAG;GACzD,UAAU;GACV,OAAO;EACT,CACyC,CAAC;EAC1C,IAAI,QAAQ,aAAa,OAAO,SAAS,GACvC,OAAO,SAAS,EAAE,WAAW,UAAU,cAAc;GACnD,MACE,mCAAmC,UAAU,SAAS,SAAS,YAAY,QAAQ,EACrF;EACF,CAAC;EAEH,OAAO;CACT;AACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file-scanner.js","names":["globSync","path","fs"],"sources":["../../../src/lib/utils/file-scanner.ts"],"sourcesContent":["import * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport { sync as globSync } from \"glob\";\n\nexport interface ScanOptions {\n cwd?: string;\n pattern?: string;\n ignore?: string[];\n}\n\nexport function scanForImport(\n importPattern: string | string[],\n options: ScanOptions = {},\n): boolean {\n const cwd = options.cwd || process.cwd();\n const pattern = options.pattern || \"**/*.{js,jsx,ts,tsx}\";\n const ignore = options.ignore || [\n \"**/node_modules/**\",\n \"**/dist/**\",\n \"**/build/**\",\n ];\n\n const files = globSync(pattern, { cwd, ignore });\n const patterns = Array.isArray(importPattern)\n ? importPattern\n : [importPattern];\n\n for (const file of files) {\n const fullPath = path.join(cwd, file);\n try {\n const content = fs.readFileSync(fullPath, \"utf8\");\n if (patterns.some((p) => content.includes(p))) {\n return true;\n }\n } catch {\n // Ignore files that cannot be read\n }\n }\n\n return false;\n}\n\nexport function getFilesContaining(\n searchString: string,\n options: ScanOptions = {},\n): string[] {\n const cwd = options.cwd || process.cwd();\n const pattern = options.pattern || \"**/*.{js,jsx,ts,tsx}\";\n const ignore = options.ignore || [\n \"**/node_modules/**\",\n \"**/dist/**\",\n \"**/build/**\",\n ];\n\n const files = globSync(pattern, { cwd, ignore });\n const result: string[] = [];\n\n for (const file of files) {\n const fullPath = path.join(cwd, file);\n try {\n const content = fs.readFileSync(fullPath, \"utf8\");\n if (content.includes(searchString)) {\n result.push(fullPath);\n }\n } catch {\n // Ignore files that cannot be read\n }\n }\n\n return result;\n}\n"],"mappings":";;;;AAUA,SAAgB,cACd,eACA,UAAuB,CAAC,GACf;CACT,MAAM,MAAM,QAAQ,OAAO,QAAQ,IAAI;CAQvC,MAAM,QAAQA,KAPE,QAAQ,WAAW,wBAOH;EAAE;EAAK,QANxB,QAAQ,UAAU;GAC/B;GACA;GACA;EACF;CAE8C,CAAC;CAC/C,MAAM,WAAW,MAAM,QAAQ,aAAa,IACxC,gBACA,CAAC,aAAa;CAElB,KAAK,MAAM,QAAQ,OAAO;EACxB,MAAM,WAAWC,OAAK,KAAK,KAAK,IAAI;EACpC,IAAI;GACF,MAAM,UAAUC,KAAG,aAAa,UAAU,MAAM;GAChD,IAAI,SAAS,MAAM,MAAM,QAAQ,SAAS,CAAC,CAAC,GAC1C,OAAO;EAEX,QAAQ,CAER;CACF;CAEA,OAAO;AACT;AAEA,SAAgB,mBACd,cACA,UAAuB,CAAC,GACd;CACV,MAAM,MAAM,QAAQ,OAAO,QAAQ,IAAI;CAQvC,MAAM,QAAQF,KAPE,QAAQ,WAAW,wBAOH;EAAE;EAAK,QANxB,QAAQ,UAAU;GAC/B;GACA;GACA;EACF;CAE8C,CAAC;CAC/C,MAAM,SAAmB,CAAC;CAE1B,KAAK,MAAM,QAAQ,OAAO;EACxB,MAAM,WAAWC,OAAK,KAAK,KAAK,IAAI;EACpC,IAAI;GAEF,IADgBC,KAAG,aAAa,UAAU,MAChC,
|
|
1
|
+
{"version":3,"file":"file-scanner.js","names":["globSync","path","fs"],"sources":["../../../src/lib/utils/file-scanner.ts"],"sourcesContent":["import * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport { sync as globSync } from \"glob\";\n\nexport interface ScanOptions {\n cwd?: string;\n pattern?: string;\n ignore?: string[];\n}\n\nexport function scanForImport(\n importPattern: string | string[],\n options: ScanOptions = {},\n): boolean {\n const cwd = options.cwd || process.cwd();\n const pattern = options.pattern || \"**/*.{js,jsx,ts,tsx}\";\n const ignore = options.ignore || [\n \"**/node_modules/**\",\n \"**/dist/**\",\n \"**/build/**\",\n ];\n\n const files = globSync(pattern, { cwd, ignore });\n const patterns = Array.isArray(importPattern)\n ? importPattern\n : [importPattern];\n\n for (const file of files) {\n const fullPath = path.join(cwd, file);\n try {\n const content = fs.readFileSync(fullPath, \"utf8\");\n if (patterns.some((p) => content.includes(p))) {\n return true;\n }\n } catch {\n // Ignore files that cannot be read\n }\n }\n\n return false;\n}\n\nexport function getFilesContaining(\n searchString: string,\n options: ScanOptions = {},\n): string[] {\n const cwd = options.cwd || process.cwd();\n const pattern = options.pattern || \"**/*.{js,jsx,ts,tsx}\";\n const ignore = options.ignore || [\n \"**/node_modules/**\",\n \"**/dist/**\",\n \"**/build/**\",\n ];\n\n const files = globSync(pattern, { cwd, ignore });\n const result: string[] = [];\n\n for (const file of files) {\n const fullPath = path.join(cwd, file);\n try {\n const content = fs.readFileSync(fullPath, \"utf8\");\n if (content.includes(searchString)) {\n result.push(fullPath);\n }\n } catch {\n // Ignore files that cannot be read\n }\n }\n\n return result;\n}\n"],"mappings":";;;;AAUA,SAAgB,cACd,eACA,UAAuB,CAAC,GACf;CACT,MAAM,MAAM,QAAQ,OAAO,QAAQ,IAAI;CAQvC,MAAM,QAAQA,KAPE,QAAQ,WAAW,wBAOH;EAAE;EAAK,QANxB,QAAQ,UAAU;GAC/B;GACA;GACA;EACF;CAE8C,CAAC;CAC/C,MAAM,WAAW,MAAM,QAAQ,aAAa,IACxC,gBACA,CAAC,aAAa;CAElB,KAAK,MAAM,QAAQ,OAAO;EACxB,MAAM,WAAWC,OAAK,KAAK,KAAK,IAAI;EACpC,IAAI;GACF,MAAM,UAAUC,KAAG,aAAa,UAAU,MAAM;GAChD,IAAI,SAAS,MAAM,MAAM,QAAQ,SAAS,CAAC,CAAC,GAC1C,OAAO;EAEX,QAAQ,CAER;CACF;CAEA,OAAO;AACT;AAEA,SAAgB,mBACd,cACA,UAAuB,CAAC,GACd;CACV,MAAM,MAAM,QAAQ,OAAO,QAAQ,IAAI;CAQvC,MAAM,QAAQF,KAPE,QAAQ,WAAW,wBAOH;EAAE;EAAK,QANxB,QAAQ,UAAU;GAC/B;GACA;GACA;EACF;CAE8C,CAAC;CAC/C,MAAM,SAAmB,CAAC;CAE1B,KAAK,MAAM,QAAQ,OAAO;EACxB,MAAM,WAAWC,OAAK,KAAK,KAAK,IAAI;EACpC,IAAI;GAEF,IADgBC,KAAG,aAAa,UAAU,MAChC,CAAC,CAAC,SAAS,YAAY,GAC/B,OAAO,KAAK,QAAQ;EAExB,QAAQ,CAER;CACF;CAEA,OAAO;AACT"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"package-installer.js","names":[],"sources":["../../../src/lib/utils/package-installer.ts"],"sourcesContent":["import { scanForImport } from \"./file-scanner\";\nimport {\n isPackageInstalled,\n askQuestion,\n installPackage,\n} from \"./package-manager\";\nimport { logger } from \"./logger\";\n\nexport interface PackageInstallConfig {\n packageName: string;\n importPatterns: string[];\n promptMessage: string;\n skipMessage: string;\n notFoundMessage: string;\n}\n\nexport async function installPackageIfNeeded(\n config: PackageInstallConfig,\n): Promise<void> {\n const found = scanForImport(config.importPatterns);\n\n if (!found) {\n logger.info(config.notFoundMessage);\n return;\n }\n\n if (isPackageInstalled(config.packageName)) {\n logger.info(config.skipMessage);\n return;\n }\n\n const answer = await askQuestion(config.promptMessage);\n if (answer === \"\" || answer.toLowerCase().startsWith(\"y\")) {\n await installPackage(config.packageName);\n } else {\n logger.info(\"Skipping installation.\");\n }\n}\n"],"mappings":";;;;AAgBA,eAAsB,uBACpB,QACe;CAGf,IAAI,CAFU,cAAc,OAAO,cAE1B,GAAG;EACV,OAAO,KAAK,OAAO,eAAe;EAClC;CACF;CAEA,IAAI,mBAAmB,OAAO,WAAW,GAAG;EAC1C,OAAO,KAAK,OAAO,WAAW;EAC9B;CACF;CAEA,MAAM,SAAS,MAAM,YAAY,OAAO,aAAa;CACrD,IAAI,WAAW,MAAM,OAAO,YAAY,
|
|
1
|
+
{"version":3,"file":"package-installer.js","names":[],"sources":["../../../src/lib/utils/package-installer.ts"],"sourcesContent":["import { scanForImport } from \"./file-scanner\";\nimport {\n isPackageInstalled,\n askQuestion,\n installPackage,\n} from \"./package-manager\";\nimport { logger } from \"./logger\";\n\nexport interface PackageInstallConfig {\n packageName: string;\n importPatterns: string[];\n promptMessage: string;\n skipMessage: string;\n notFoundMessage: string;\n}\n\nexport async function installPackageIfNeeded(\n config: PackageInstallConfig,\n): Promise<void> {\n const found = scanForImport(config.importPatterns);\n\n if (!found) {\n logger.info(config.notFoundMessage);\n return;\n }\n\n if (isPackageInstalled(config.packageName)) {\n logger.info(config.skipMessage);\n return;\n }\n\n const answer = await askQuestion(config.promptMessage);\n if (answer === \"\" || answer.toLowerCase().startsWith(\"y\")) {\n await installPackage(config.packageName);\n } else {\n logger.info(\"Skipping installation.\");\n }\n}\n"],"mappings":";;;;AAgBA,eAAsB,uBACpB,QACe;CAGf,IAAI,CAFU,cAAc,OAAO,cAE1B,GAAG;EACV,OAAO,KAAK,OAAO,eAAe;EAClC;CACF;CAEA,IAAI,mBAAmB,OAAO,WAAW,GAAG;EAC1C,OAAO,KAAK,OAAO,WAAW;EAC9B;CACF;CAEA,MAAM,SAAS,MAAM,YAAY,OAAO,aAAa;CACrD,IAAI,WAAW,MAAM,OAAO,YAAY,CAAC,CAAC,WAAW,GAAG,GACtD,MAAM,eAAe,OAAO,WAAW;MAEvC,OAAO,KAAK,wBAAwB;AAExC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "assistant-ui",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.100",
|
|
4
4
|
"description": "CLI for assistant-ui",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cli",
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
],
|
|
27
27
|
"sideEffects": false,
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@clack/prompts": "^1.5.
|
|
29
|
+
"@clack/prompts": "^1.5.1",
|
|
30
30
|
"chalk": "^5.6.2",
|
|
31
31
|
"cli-progress": "^3.12.0",
|
|
32
32
|
"commander": "^15.0.0",
|
|
@@ -36,17 +36,17 @@
|
|
|
36
36
|
"giget": "^3.2.0",
|
|
37
37
|
"glob": "^13.0.6",
|
|
38
38
|
"jscodeshift": "^17.3.0",
|
|
39
|
-
"@assistant-ui/agent-launcher": "0.1.
|
|
39
|
+
"@assistant-ui/agent-launcher": "0.1.6"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
42
|
"@types/cli-progress": "^3.11.6",
|
|
43
43
|
"@types/cross-spawn": "^6.0.6",
|
|
44
44
|
"@types/debug": "^4.1.13",
|
|
45
45
|
"@types/jscodeshift": "^17.3.0",
|
|
46
|
-
"@types/node": "^25.9.
|
|
47
|
-
"@vitest/coverage-v8": "^4.1.
|
|
48
|
-
"vitest": "^4.1.
|
|
49
|
-
"@assistant-ui/x-buildutils": "0.0.
|
|
46
|
+
"@types/node": "^25.9.2",
|
|
47
|
+
"@vitest/coverage-v8": "^4.1.8",
|
|
48
|
+
"vitest": "^4.1.8",
|
|
49
|
+
"@assistant-ui/x-buildutils": "0.0.12"
|
|
50
50
|
},
|
|
51
51
|
"publishConfig": {
|
|
52
52
|
"access": "public",
|
|
@@ -124,33 +124,46 @@ const result = streamText({
|
|
|
124
124
|
|
|
125
125
|
### Frontend tool UI:
|
|
126
126
|
|
|
127
|
-
|
|
128
|
-
"use client";
|
|
127
|
+
Create a toolkit with a renderer for the tool. The tool executes on the backend, so the entry uses `externalTool()` and only attaches UI:
|
|
129
128
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
129
|
+
```tsx
|
|
130
|
+
// app/toolkit.tsx
|
|
131
|
+
"use generative";
|
|
132
|
+
|
|
133
|
+
import { defineToolkit, externalTool } from "@assistant-ui/react";
|
|
134
|
+
|
|
135
|
+
export default defineToolkit({
|
|
136
|
+
get_weather: {
|
|
137
|
+
execute: externalTool(),
|
|
138
|
+
render: ({ args, result }) => {
|
|
139
|
+
return (
|
|
140
|
+
<div>
|
|
141
|
+
<p>Weather for {args?.location}</p>
|
|
142
|
+
{result && <p>{result.temperature}F, {result.condition}</p>}
|
|
143
|
+
</div>
|
|
144
|
+
);
|
|
145
|
+
},
|
|
141
146
|
},
|
|
142
147
|
});
|
|
143
148
|
```
|
|
144
149
|
|
|
145
|
-
Register the
|
|
150
|
+
Register the toolkit in your assistant component:
|
|
146
151
|
|
|
147
152
|
```tsx
|
|
148
|
-
|
|
149
|
-
|
|
153
|
+
import { AssistantRuntimeProvider, Tools, useAui } from "@assistant-ui/react";
|
|
154
|
+
import toolkit from "@/app/toolkit";
|
|
155
|
+
|
|
156
|
+
const aui = useAui({
|
|
157
|
+
tools: Tools({ toolkit }),
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
<AssistantRuntimeProvider aui={aui} runtime={runtime}>
|
|
150
161
|
<Thread />
|
|
151
162
|
</AssistantRuntimeProvider>
|
|
152
163
|
```
|
|
153
164
|
|
|
165
|
+
Do not use `makeAssistantToolUI`, `useAssistantToolUI`, `makeAssistantTool`, or `useAssistantTool`; they are deprecated in favor of toolkits.
|
|
166
|
+
|
|
154
167
|
## Key Packages
|
|
155
168
|
|
|
156
169
|
| Package | Purpose |
|