assistant-ui 0.0.123 → 0.0.124

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/dist/codemods/v0-11/content-part-to-message-part.d.ts.map +1 -1
  2. package/dist/codemods/v0-11/content-part-to-message-part.js +126 -40
  3. package/dist/codemods/v0-11/content-part-to-message-part.js.map +1 -1
  4. package/dist/codemods/v0-12/event-names-to-camelcase.d.ts.map +1 -1
  5. package/dist/codemods/v0-12/event-names-to-camelcase.js +2 -2
  6. package/dist/codemods/v0-12/event-names-to-camelcase.js.map +1 -1
  7. package/dist/codemods/v0-12/primitive-if-to-aui-if.d.ts.map +1 -1
  8. package/dist/codemods/v0-12/primitive-if-to-aui-if.js +53 -37
  9. package/dist/codemods/v0-12/primitive-if-to-aui-if.js.map +1 -1
  10. package/dist/codemods/v0-8/ui-package-split.d.ts.map +1 -1
  11. package/dist/codemods/v0-8/ui-package-split.js +11 -35
  12. package/dist/codemods/v0-8/ui-package-split.js.map +1 -1
  13. package/dist/codemods/v0-9/edge-package-split.d.ts.map +1 -1
  14. package/dist/codemods/v0-9/edge-package-split.js +15 -69
  15. package/dist/codemods/v0-9/edge-package-split.js.map +1 -1
  16. package/dist/lib/utils/package-installer.d.ts.map +1 -1
  17. package/dist/lib/utils/package-installer.js +3 -2
  18. package/dist/lib/utils/package-installer.js.map +1 -1
  19. package/package.json +1 -1
  20. package/src/codemods/v0-11/__tests__/content-part-to-message-part.test.ts +268 -2
  21. package/src/codemods/v0-11/content-part-to-message-part.ts +211 -80
  22. package/src/codemods/v0-12/__tests__/event-names-to-camelcase.test.ts +23 -0
  23. package/src/codemods/v0-12/__tests__/primitive-if-to-aui-if.test.ts +115 -0
  24. package/src/codemods/v0-12/event-names-to-camelcase.ts +2 -8
  25. package/src/codemods/v0-12/primitive-if-to-aui-if.ts +87 -57
  26. package/src/codemods/v0-8/__tests__/ui-package-split.test.ts +83 -0
  27. package/src/codemods/v0-8/ui-package-split.ts +21 -59
  28. package/src/codemods/v0-9/edge-package-split.test.ts +100 -0
  29. package/src/codemods/v0-9/edge-package-split.ts +30 -139
  30. package/src/lib/utils/package-installer.test.ts +39 -0
  31. package/src/lib/utils/package-installer.ts +3 -1
  32. package/templates/cloud-harness/components/assistant-ui/elements/tool-fallback.aui.tsx +17 -8
  33. package/templates/cloud-harness/package.json +2 -2
@@ -1 +1 @@
1
- {"version":3,"file":"content-part-to-message-part.d.ts","sourceRoot":"","sources":["../../../src/codemods/v0-11/content-part-to-message-part.ts"],"names":[],"mappings":"AAuEA,QAAA,MAAM,+BAA+B,6HAiGpC,CAAC;AAEF,eAAe,+BAA+B,CAAC"}
1
+ {"version":3,"file":"content-part-to-message-part.d.ts","sourceRoot":"","sources":["../../../src/codemods/v0-11/content-part-to-message-part.ts"],"names":[],"mappings":"AAwEA,QAAA,MAAM,+BAA+B,6HAmOpC,CAAC;AAEF,eAAe,+BAA+B,CAAC"}
@@ -1,4 +1,5 @@
1
1
  import { createTransformer } from "../utils/createTransformer.js";
2
+ import { resolveBinding } from "../utils/resolveBinding.js";
2
3
  //#region src/codemods/v0-11/content-part-to-message-part.ts
3
4
  const typeRenamingMap = {
4
5
  TextContentPart: "TextMessagePart",
@@ -49,54 +50,139 @@ const typeRenamingMap = {
49
50
  ContentPartPrimitiveInProgress: "MessagePartPrimitiveInProgress"
50
51
  };
51
52
  const migrateContentPartToMessagePart = createTransformer(({ j, root, markAsChanged }) => {
53
+ const renameExport = (path, newName) => {
54
+ const specifier = path.value;
55
+ const replacement = j.exportSpecifier.from({
56
+ local: j.identifier(newName),
57
+ exported: j.Identifier.check(specifier.exported) ? j.identifier(specifier.exported.name) : specifier.exported
58
+ });
59
+ replacement.exportKind = specifier.exportKind;
60
+ replacement.comments = specifier.comments;
61
+ path.replace(replacement);
62
+ };
63
+ const declaredNames = /* @__PURE__ */ new Set();
64
+ root.find(j.TSTypeParameter).forEach((path) => {
65
+ declaredNames.add(path.value.name.name ?? path.value.name);
66
+ });
67
+ const identifiers = root.find(j.Identifier).paths();
68
+ for (const path of identifiers) if (path.parent.value.id === path.value) declaredNames.add(path.value.name);
69
+ const usedNames = new Set(identifiers.map((path) => path.value.name));
70
+ const messageBindings = /* @__PURE__ */ new Set();
71
+ const namespaceBindings = /* @__PURE__ */ new Set();
72
+ const namespaceNames = /* @__PURE__ */ new Set();
52
73
  root.find(j.ImportDeclaration).forEach((path) => {
53
74
  const source = path.value.source.value;
54
- if (typeof source === "string" && source.startsWith("@assistant-ui/")) path.value.specifiers?.forEach((specifier) => {
55
- if (j.ImportSpecifier.check(specifier)) {
56
- const oldName = specifier.imported.name;
57
- if (typeRenamingMap[oldName]) {
58
- specifier.imported.name = typeRenamingMap[oldName];
59
- if (specifier.local && specifier.local.name === oldName) specifier.local.name = typeRenamingMap[oldName];
60
- markAsChanged();
61
- }
75
+ if (typeof source !== "string" || !source.startsWith("@assistant-ui/")) return;
76
+ path.value.specifiers?.forEach((specifier, index) => {
77
+ if (j.ImportNamespaceSpecifier.check(specifier)) {
78
+ namespaceBindings.add(specifier.local);
79
+ if (j.Identifier.check(specifier.local)) namespaceNames.add(specifier.local.name);
80
+ return;
62
81
  }
63
- });
64
- });
65
- root.find(j.MemberExpression).forEach((path) => {
66
- if (path.value.object && path.value.object.name === "MessagePrimitive" && path.value.property && path.value.property.name === "Content") {
67
- path.value.property.name = "Parts";
82
+ if (!j.ImportSpecifier.check(specifier) || !j.Identifier.check(specifier.imported) || !j.Identifier.check(specifier.local)) return;
83
+ const oldName = specifier.imported.name;
84
+ const importKind = specifier.importKind;
85
+ const typeOnly = path.value.importKind === "type" || importKind === "type";
86
+ if (oldName === "MessagePrimitive" && !typeOnly) messageBindings.add(specifier.local);
87
+ const newName = typeRenamingMap[oldName];
88
+ if (!newName) return;
89
+ const references = identifiers.filter((reference) => {
90
+ const node = reference.value;
91
+ if (node.name !== oldName) return false;
92
+ const parent = reference.parent.value;
93
+ if (parent.type.startsWith("Import") || parent.id === node || parent.label === node) return false;
94
+ if (parent.key === node && !parent.computed && parent.value !== node) return false;
95
+ if (parent.property === node && !parent.computed) return false;
96
+ if (j.TSQualifiedName.check(parent) && parent.right === node) return false;
97
+ if (j.JSXAttribute.check(parent) || j.JSXNamespacedName.check(parent)) return false;
98
+ if ((j.JSXOpeningElement.check(parent) || j.JSXClosingElement.check(parent)) && /^[a-z]/.test(oldName)) return false;
99
+ if (j.ExportSpecifier.check(parent) && (reference.parent.parent.value.source || parent.local !== node)) return false;
100
+ return true;
101
+ });
102
+ const canRename = specifier.local.name === oldName && !usedNames.has(newName) && !declaredNames.has(newName) && !declaredNames.has(oldName) && references.every((reference) => {
103
+ const binding = resolveBinding(j, reference, oldName);
104
+ return binding === specifier.local || typeOnly && !binding;
105
+ });
106
+ if (canRename) for (const reference of references) {
107
+ const parent = reference.parent.value;
108
+ if ((j.Property.check(parent) || j.ObjectProperty.check(parent)) && parent.shorthand) {
109
+ parent.shorthand = false;
110
+ parent.key = j.identifier(oldName);
111
+ parent.value = j.identifier(newName);
112
+ } else if (j.ExportSpecifier.check(parent)) renameExport(reference.parent, newName);
113
+ else reference.value.name = newName;
114
+ }
115
+ const replacement = j.importSpecifier(j.identifier(newName), j.identifier(canRename ? newName : specifier.local.name));
116
+ replacement.importKind = importKind;
117
+ replacement.comments = specifier.comments;
118
+ path.get("specifiers", index).replace(replacement);
68
119
  markAsChanged();
69
- }
120
+ });
70
121
  });
71
- root.find(j.JSXMemberExpression).forEach((path) => {
72
- if (path.value.object && path.value.object.name === "MessagePrimitive" && path.value.property && path.value.property.name === "Content") {
73
- path.value.property.name = "Parts";
122
+ root.find(j.ExportNamedDeclaration).forEach((path) => {
123
+ const source = path.value.source?.value;
124
+ if (typeof source !== "string" || !source.startsWith("@assistant-ui/")) return;
125
+ path.value.specifiers?.forEach((specifier, index) => {
126
+ if (!j.ExportSpecifier.check(specifier) || !j.Identifier.check(specifier.local)) return;
127
+ const newName = typeRenamingMap[specifier.local.name];
128
+ if (!newName) return;
129
+ renameExport(path.get("specifiers", index), newName);
74
130
  markAsChanged();
75
- }
76
- });
77
- Object.entries(typeRenamingMap).forEach(([oldName, newName]) => {
78
- root.find(j.TSTypeReference).forEach((path) => {
79
- if (path.value.typeName && path.value.typeName.name === oldName) {
80
- path.value.typeName.name = newName;
81
- markAsChanged();
82
- }
83
- });
84
- root.find(j.Identifier).forEach((path) => {
85
- if (path.value.name === oldName) {
86
- if (j.ImportSpecifier.check(path.parent.value)) return;
87
- if (j.Property.check(path.parent.value) && path.parent.value.key === path.value) return;
88
- if (j.MemberExpression.check(path.parent.value) && path.parent.value.property === path.value) return;
89
- path.value.name = newName;
90
- markAsChanged();
91
- }
92
- });
93
- root.find(j.JSXIdentifier).forEach((path) => {
94
- if (path.value.name === oldName) {
95
- path.value.name = newName;
96
- markAsChanged();
97
- }
98
131
  });
99
132
  });
133
+ const isTypeShadowed = (path, name) => {
134
+ if (!declaredNames.has(name)) return false;
135
+ for (let current = path.parent; current; current = current.parent) {
136
+ const node = current.value;
137
+ if (node.type === "TSTypeParameterDeclaration" && node.params.some((param) => param.name === name)) return true;
138
+ if (node.type === "ClassExpression" && node.id?.name === name) return true;
139
+ if (![
140
+ "Program",
141
+ "BlockStatement",
142
+ "TSModuleBlock"
143
+ ].includes(node.type)) continue;
144
+ if (node.body.some((statement) => {
145
+ const declaration = statement.declaration ?? statement;
146
+ return [
147
+ "TSInterfaceDeclaration",
148
+ "TSTypeAliasDeclaration",
149
+ "TSEnumDeclaration",
150
+ "ClassDeclaration",
151
+ "TSModuleDeclaration"
152
+ ].includes(declaration.type) && declaration.id?.name === name;
153
+ })) return true;
154
+ }
155
+ return false;
156
+ };
157
+ const isInTypeQuery = (path) => {
158
+ for (let current = path.parent; current; current = current.parent) if (j.TSTypeQuery.check(current.value)) return true;
159
+ return false;
160
+ };
161
+ const renameNamespaceMember = (path) => {
162
+ const node = path.value;
163
+ const qualified = j.TSQualifiedName.check(node);
164
+ const object = qualified ? node.left : node.object;
165
+ const property = qualified ? node.right : node.property;
166
+ if (node.computed || !j.Identifier.check(object) || !j.Identifier.check(property)) return;
167
+ const newName = typeRenamingMap[property.name];
168
+ if (!newName) return;
169
+ if (qualified && !isInTypeQuery(path)) {
170
+ if (!namespaceNames.has(object.name) || isTypeShadowed(path, object.name)) return;
171
+ } else if (!namespaceBindings.has(resolveBinding(j, path, object.name))) return;
172
+ property.name = newName;
173
+ markAsChanged();
174
+ };
175
+ root.find(j.TSQualifiedName).forEach(renameNamespaceMember);
176
+ root.find(j.JSXMemberExpression).forEach(renameNamespaceMember);
177
+ root.find(j.MemberExpression).forEach(renameNamespaceMember);
178
+ const renameContent = (path) => {
179
+ const { object, property, computed } = path.value;
180
+ if (computed || !j.Identifier.check(object) || !j.Identifier.check(property) || property.name !== "Content" || !messageBindings.has(resolveBinding(j, path, object.name))) return;
181
+ property.name = "Parts";
182
+ markAsChanged();
183
+ };
184
+ root.find(j.MemberExpression).forEach(renameContent);
185
+ root.find(j.JSXMemberExpression).forEach(renameContent);
100
186
  });
101
187
  //#endregion
102
188
  export { migrateContentPartToMessagePart as default };
@@ -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":"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"}
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\";\nimport { resolveBinding } from \"../utils/resolveBinding\";\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 const renameExport = (path: any, newName: string) => {\n const specifier = path.value;\n const replacement: any = j.exportSpecifier.from({\n local: j.identifier(newName),\n exported: j.Identifier.check(specifier.exported)\n ? j.identifier(specifier.exported.name)\n : specifier.exported,\n });\n replacement.exportKind = specifier.exportKind;\n replacement.comments = specifier.comments;\n path.replace(replacement);\n };\n\n const declaredNames = new Set<string>();\n root.find(j.TSTypeParameter).forEach((path: any) => {\n declaredNames.add(path.value.name.name ?? path.value.name);\n });\n const identifiers = root.find(j.Identifier).paths();\n for (const path of identifiers) {\n if (path.parent.value.id === path.value)\n declaredNames.add(path.value.name);\n }\n const usedNames = new Set(identifiers.map((path: any) => path.value.name));\n const messageBindings = new Set<any>();\n const namespaceBindings = new Set<any>();\n const namespaceNames = new Set<string>();\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 return;\n\n path.value.specifiers?.forEach((specifier: any, index: number) => {\n if (j.ImportNamespaceSpecifier.check(specifier)) {\n namespaceBindings.add(specifier.local);\n if (j.Identifier.check(specifier.local))\n namespaceNames.add(specifier.local.name);\n return;\n }\n if (\n !j.ImportSpecifier.check(specifier) ||\n !j.Identifier.check(specifier.imported) ||\n !j.Identifier.check(specifier.local)\n )\n return;\n const oldName = specifier.imported.name;\n const importKind = (specifier as { importKind?: string }).importKind;\n const typeOnly =\n path.value.importKind === \"type\" || importKind === \"type\";\n if (oldName === \"MessagePrimitive\" && !typeOnly) {\n messageBindings.add(specifier.local);\n }\n const newName = typeRenamingMap[oldName];\n if (!newName) return;\n\n const references = identifiers.filter((reference: any) => {\n const node = reference.value;\n if (node.name !== oldName) return false;\n const parent = reference.parent.value;\n if (\n parent.type.startsWith(\"Import\") ||\n parent.id === node ||\n parent.label === node\n )\n return false;\n if (parent.key === node && !parent.computed && parent.value !== node)\n return false;\n if (parent.property === node && !parent.computed) return false;\n if (j.TSQualifiedName.check(parent) && parent.right === node)\n return false;\n if (j.JSXAttribute.check(parent) || j.JSXNamespacedName.check(parent))\n return false;\n if (\n (j.JSXOpeningElement.check(parent) ||\n j.JSXClosingElement.check(parent)) &&\n /^[a-z]/.test(oldName)\n )\n return false;\n if (\n j.ExportSpecifier.check(parent) &&\n (reference.parent.parent.value.source || parent.local !== node)\n )\n return false;\n return true;\n });\n // Retain the local alias when a declaration in either TypeScript namespace\n // could capture a renamed reference. The resolver covers value bindings.\n const canRename =\n specifier.local.name === oldName &&\n !usedNames.has(newName) &&\n !declaredNames.has(newName) &&\n !declaredNames.has(oldName) &&\n references.every((reference: any) => {\n const binding = resolveBinding(j, reference, oldName);\n return binding === specifier.local || (typeOnly && !binding);\n });\n if (canRename) {\n for (const reference of references) {\n const parent = reference.parent.value;\n if (\n (j.Property.check(parent) || j.ObjectProperty.check(parent)) &&\n parent.shorthand\n ) {\n parent.shorthand = false;\n parent.key = j.identifier(oldName);\n parent.value = j.identifier(newName);\n } else if (j.ExportSpecifier.check(parent)) {\n renameExport(reference.parent, newName);\n } else {\n reference.value.name = newName;\n }\n }\n }\n const replacement: any = j.importSpecifier(\n j.identifier(newName),\n j.identifier(canRename ? newName : specifier.local.name),\n );\n replacement.importKind = importKind;\n replacement.comments = specifier.comments;\n path.get(\"specifiers\", index).replace(replacement);\n markAsChanged();\n });\n });\n\n root.find(j.ExportNamedDeclaration).forEach((path: any) => {\n const source = path.value.source?.value;\n if (typeof source !== \"string\" || !source.startsWith(\"@assistant-ui/\"))\n return;\n path.value.specifiers?.forEach((specifier: any, index: number) => {\n if (\n !j.ExportSpecifier.check(specifier) ||\n !j.Identifier.check(specifier.local)\n )\n return;\n const newName = typeRenamingMap[specifier.local.name];\n if (!newName) return;\n renameExport(path.get(\"specifiers\", index), newName);\n markAsChanged();\n });\n });\n\n const isTypeShadowed = (path: any, name: string) => {\n if (!declaredNames.has(name)) return false;\n for (let current = path.parent; current; current = current.parent) {\n const node = current.value;\n if (\n node.type === \"TSTypeParameterDeclaration\" &&\n node.params.some((param: any) => param.name === name)\n )\n return true;\n if (node.type === \"ClassExpression\" && node.id?.name === name)\n return true;\n if (![\"Program\", \"BlockStatement\", \"TSModuleBlock\"].includes(node.type))\n continue;\n if (\n node.body.some((statement: any) => {\n const declaration = statement.declaration ?? statement;\n return (\n [\n \"TSInterfaceDeclaration\",\n \"TSTypeAliasDeclaration\",\n \"TSEnumDeclaration\",\n \"ClassDeclaration\",\n \"TSModuleDeclaration\",\n ].includes(declaration.type) && declaration.id?.name === name\n );\n })\n )\n return true;\n }\n return false;\n };\n\n const isInTypeQuery = (path: any) => {\n for (let current = path.parent; current; current = current.parent) {\n if (j.TSTypeQuery.check(current.value)) return true;\n }\n return false;\n };\n\n const renameNamespaceMember = (path: any) => {\n const node = path.value;\n const qualified = j.TSQualifiedName.check(node);\n const object = qualified ? node.left : node.object;\n const property = qualified ? node.right : node.property;\n if (\n node.computed ||\n !j.Identifier.check(object) ||\n !j.Identifier.check(property)\n )\n return;\n const newName = typeRenamingMap[property.name];\n if (!newName) return;\n if (qualified && !isInTypeQuery(path)) {\n if (\n !namespaceNames.has(object.name) ||\n isTypeShadowed(path, object.name)\n )\n return;\n } else if (!namespaceBindings.has(resolveBinding(j, path, object.name))) {\n return;\n }\n property.name = newName;\n markAsChanged();\n };\n root.find(j.TSQualifiedName).forEach(renameNamespaceMember);\n root.find(j.JSXMemberExpression).forEach(renameNamespaceMember);\n root.find(j.MemberExpression).forEach(renameNamespaceMember);\n\n const renameContent = (path: any) => {\n const { object, property, computed } = path.value;\n if (\n computed ||\n !j.Identifier.check(object) ||\n !j.Identifier.check(property) ||\n property.name !== \"Content\" ||\n !messageBindings.has(resolveBinding(j, path, object.name))\n )\n return;\n property.name = \"Parts\";\n markAsChanged();\n };\n root.find(j.MemberExpression).forEach(renameContent);\n root.find(j.JSXMemberExpression).forEach(renameContent);\n },\n);\n\nexport default migrateContentPartToMessagePart;\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"event-names-to-camelcase.d.ts","sourceRoot":"","sources":["../../../src/codemods/v0-12/event-names-to-camelcase.ts"],"names":[],"mappings":"AAYA,QAAA,MAAM,4BAA4B,6HAsCjC,CAAC;AAEF,eAAe,4BAA4B,CAAC"}
1
+ {"version":3,"file":"event-names-to-camelcase.d.ts","sourceRoot":"","sources":["../../../src/codemods/v0-12/event-names-to-camelcase.ts"],"names":[],"mappings":"AAWA,QAAA,MAAM,4BAA4B,6HAiCjC,CAAC;AAEF,eAAe,4BAA4B,CAAC"}
@@ -13,7 +13,7 @@ const migrateEventNamesToCamelCase = createTransformer(({ j, root, markAsChanged
13
13
  const node = path.value;
14
14
  if (typeof node.value === "string") {
15
15
  const oldEventName = node.value;
16
- if (eventNameMap[oldEventName]) {
16
+ if (Object.hasOwn(eventNameMap, oldEventName)) {
17
17
  node.value = eventNameMap[oldEventName];
18
18
  markAsChanged();
19
19
  }
@@ -23,7 +23,7 @@ const migrateEventNamesToCamelCase = createTransformer(({ j, root, markAsChanged
23
23
  path.value.quasis.forEach((quasi) => {
24
24
  if (quasi.value && typeof quasi.value.raw === "string") {
25
25
  const oldEventName = quasi.value.raw;
26
- if (eventNameMap[oldEventName]) {
26
+ if (Object.hasOwn(eventNameMap, oldEventName)) {
27
27
  const newEventName = eventNameMap[oldEventName];
28
28
  quasi.value.raw = newEventName;
29
29
  quasi.value.cooked = newEventName;
@@ -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,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
+ {"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\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 root.find(j.Literal).forEach((path: any) => {\n const node = path.value;\n\n if (typeof node.value === \"string\") {\n const oldEventName = node.value;\n\n if (Object.hasOwn(eventNameMap, oldEventName)) {\n const newEventName = eventNameMap[oldEventName];\n node.value = newEventName;\n markAsChanged();\n }\n }\n });\n\n root.find(j.TemplateLiteral).forEach((path: any) => {\n const node = path.value;\n\n node.quasis.forEach((quasi: any) => {\n if (quasi.value && typeof quasi.value.raw === \"string\") {\n const oldEventName = quasi.value.raw;\n\n if (Object.hasOwn(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":";;AAEA,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;CAC9B,KAAK,KAAK,EAAE,OAAO,CAAC,CAAC,SAAS,SAAc;EAC1C,MAAM,OAAO,KAAK;EAElB,IAAI,OAAO,KAAK,UAAU,UAAU;GAClC,MAAM,eAAe,KAAK;GAE1B,IAAI,OAAO,OAAO,cAAc,YAAY,GAAG;IAE7C,KAAK,QADgB,aAAa;IAElC,cAAc;GAChB;EACF;CACF,CAAC;CAED,KAAK,KAAK,EAAE,eAAe,CAAC,CAAC,SAAS,SAAc;EAGlD,KAFkB,MAEb,OAAO,SAAS,UAAe;GAClC,IAAI,MAAM,SAAS,OAAO,MAAM,MAAM,QAAQ,UAAU;IACtD,MAAM,eAAe,MAAM,MAAM;IAEjC,IAAI,OAAO,OAAO,cAAc,YAAY,GAAG;KAC7C,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.d.ts","sourceRoot":"","sources":["../../../src/codemods/v0-12/primitive-if-to-aui-if.ts"],"names":[],"mappings":"AAyLA,QAAA,MAAM,yBAAyB,6HAyJ9B,CAAC;AAEF,eAAe,yBAAyB,CAAC"}
1
+ {"version":3,"file":"primitive-if-to-aui-if.d.ts","sourceRoot":"","sources":["../../../src/codemods/v0-12/primitive-if-to-aui-if.ts"],"names":[],"mappings":"AA0LA,QAAA,MAAM,yBAAyB,6HAsL9B,CAAC;AAEF,eAAe,yBAAyB,CAAC"}
@@ -1,4 +1,5 @@
1
1
  import { createTransformer } from "../utils/createTransformer.js";
2
+ import { resolveBinding } from "../utils/resolveBinding.js";
2
3
  //#region src/codemods/v0-12/primitive-if-to-aui-if.ts
3
4
  const primitiveMap = {
4
5
  ThreadPrimitive: {
@@ -114,25 +115,57 @@ const buildConditionString = (j, fragments) => {
114
115
  }).reduce((left, right) => j.logicalExpression("&&", left, right))).toSource();
115
116
  };
116
117
  const migratePrimitiveIfToAuiIf = createTransformer(({ j, root, markAsChanged }) => {
117
- let needsAuiIfImport = false;
118
- const importedPrimitives = /* @__PURE__ */ new Set();
118
+ const importedPrimitives = /* @__PURE__ */ new Map();
119
+ const auiIfImports = [];
120
+ const usedNames = /* @__PURE__ */ new Set();
121
+ root.find(j.Identifier).forEach((path) => usedNames.add(path.value.name));
122
+ root.find(j.JSXIdentifier).forEach((path) => usedNames.add(path.value.name));
119
123
  root.find(j.ImportDeclaration).forEach((path) => {
120
- const source = path.value.source.value;
121
- if (typeof source === "string" && source.startsWith("@assistant-ui/")) path.value.specifiers?.forEach((specifier) => {
122
- if (j.ImportSpecifier.check(specifier)) {
123
- const name = String(specifier.local?.name ?? specifier.imported.name);
124
- if (primitiveMap[name] || fixedConditionMap[name]) importedPrimitives.add(name);
125
- }
124
+ const declaration = path.value;
125
+ const source = declaration.source.value;
126
+ if (typeof source !== "string" || !source.startsWith("@assistant-ui/") || declaration.importKind === "type") return;
127
+ declaration.specifiers?.forEach((specifier) => {
128
+ if (!j.ImportSpecifier.check(specifier) || !j.Identifier.check(specifier.imported) || !j.Identifier.check(specifier.local) || specifier.importKind === "type") return;
129
+ const name = specifier.imported.name;
130
+ const binding = specifier.local;
131
+ if (primitiveMap[name] || fixedConditionMap[name]) importedPrimitives.set(binding.name, {
132
+ name,
133
+ declaration,
134
+ binding
135
+ });
136
+ if (name === "AuiIf") auiIfImports.push({
137
+ source,
138
+ binding
139
+ });
126
140
  });
127
141
  });
128
142
  if (importedPrimitives.size === 0) return;
129
- const convertElementToAuiIf = (elementPath, conditionBody) => {
143
+ const getPrimitive = (path, localName) => {
144
+ const primitive = importedPrimitives.get(localName);
145
+ return primitive && resolveBinding(j, path, localName) === primitive.binding ? primitive : void 0;
146
+ };
147
+ const getAuiIfName = (path, declaration) => {
148
+ const source = declaration.source.value;
149
+ const existing = auiIfImports.find((entry) => entry.source === source && !/^[a-z]/.test(entry.binding.name) && resolveBinding(j, path, entry.binding.name) === entry.binding);
150
+ if (existing) return existing.binding.name;
151
+ let name = "AuiIf";
152
+ for (let suffix = 1; usedNames.has(name); suffix++) name = `AuiIf${suffix}`;
153
+ usedNames.add(name);
154
+ const binding = j.identifier(name);
155
+ declaration.specifiers.push(j.importSpecifier(j.identifier("AuiIf"), binding));
156
+ auiIfImports.push({
157
+ source,
158
+ binding
159
+ });
160
+ return name;
161
+ };
162
+ const convertElementToAuiIf = (elementPath, conditionBody, declaration) => {
163
+ const localName = getAuiIfName(elementPath, declaration);
130
164
  const arrowFnAst = j(`(s) => ${conditionBody}`).find(j.ArrowFunctionExpression).paths()[0].value;
131
165
  const opening = elementPath.value.openingElement;
132
- opening.name = j.jsxIdentifier("AuiIf");
166
+ opening.name = j.jsxIdentifier(localName);
133
167
  opening.attributes = [j.jsxAttribute(j.jsxIdentifier("condition"), j.jsxExpressionContainer(arrowFnAst))];
134
- if (elementPath.value.closingElement) elementPath.value.closingElement.name = j.jsxIdentifier("AuiIf");
135
- needsAuiIfImport = true;
168
+ if (elementPath.value.closingElement) elementPath.value.closingElement.name = j.jsxIdentifier(localName);
136
169
  markAsChanged();
137
170
  };
138
171
  root.find(j.JSXElement).forEach((path) => {
@@ -140,13 +173,13 @@ const migratePrimitiveIfToAuiIf = createTransformer(({ j, root, markAsChanged })
140
173
  if (!j.JSXMemberExpression.check(name)) return;
141
174
  if (!j.JSXIdentifier.check(name.object)) return;
142
175
  if (!j.JSXIdentifier.check(name.property)) return;
143
- const primitiveName = name.object.name;
176
+ const primitive = getPrimitive(path, name.object.name);
177
+ if (!primitive) return;
144
178
  const propertyName = name.property.name;
145
- const conditionBody = fixedConditionMap[primitiveName]?.[propertyName];
179
+ const conditionBody = fixedConditionMap[primitive.name]?.[propertyName];
146
180
  if (!conditionBody) return;
147
- if (!importedPrimitives.has(primitiveName)) return;
148
181
  if ((path.value.openingElement.attributes || []).length > 0) return;
149
- convertElementToAuiIf(path, conditionBody);
182
+ convertElementToAuiIf(path, conditionBody, primitive.declaration);
150
183
  });
151
184
  root.find(j.JSXElement).forEach((path) => {
152
185
  const name = path.value.openingElement.name;
@@ -154,10 +187,10 @@ const migratePrimitiveIfToAuiIf = createTransformer(({ j, root, markAsChanged })
154
187
  if (!j.JSXIdentifier.check(name.object)) return;
155
188
  if (!j.JSXIdentifier.check(name.property)) return;
156
189
  if (name.property.name !== "If") return;
157
- const primitiveName = name.object.name;
158
- const propMap = primitiveMap[primitiveName];
190
+ const primitive = getPrimitive(path, name.object.name);
191
+ if (!primitive) return;
192
+ const propMap = primitiveMap[primitive.name];
159
193
  if (!propMap) return;
160
- if (!importedPrimitives.has(primitiveName)) return;
161
194
  const attrs = path.value.openingElement.attributes || [];
162
195
  const fragments = [];
163
196
  let hasUnknownProp = false;
@@ -185,25 +218,8 @@ const migratePrimitiveIfToAuiIf = createTransformer(({ j, root, markAsChanged })
185
218
  if (fragment) fragments.push(fragment);
186
219
  }
187
220
  if (hasUnknownProp || fragments.length === 0) return;
188
- convertElementToAuiIf(path, buildConditionString(j, fragments));
221
+ convertElementToAuiIf(path, buildConditionString(j, fragments), primitive.declaration);
189
222
  });
190
- if (needsAuiIfImport) {
191
- let hasAuiIfImport = false;
192
- let assistantUiImport = null;
193
- root.find(j.ImportDeclaration).forEach((path) => {
194
- const source = path.value.source.value;
195
- if (typeof source === "string" && source.startsWith("@assistant-ui/")) {
196
- assistantUiImport = path;
197
- path.value.specifiers?.forEach((specifier) => {
198
- if (j.ImportSpecifier.check(specifier) && (specifier.imported.name === "AuiIf" || specifier.local?.name === "AuiIf")) hasAuiIfImport = true;
199
- });
200
- }
201
- });
202
- if (!hasAuiIfImport && assistantUiImport) {
203
- assistantUiImport.value.specifiers.push(j.importSpecifier(j.identifier("AuiIf")));
204
- markAsChanged();
205
- }
206
- }
207
223
  });
208
224
  //#endregion
209
225
  export { migratePrimitiveIfToAuiIf as default };
@@ -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: (v) => ({\n expression: `s.message.role ${v === false ? \"!==\" : \"===\"} \"user\"`,\n negated: false,\n }),\n assistant: (v) => ({\n expression: `s.message.role ${v === false ? \"!==\" : \"===\"} \"assistant\"`,\n negated: false,\n }),\n system: (v) => ({\n expression: `s.message.role ${v === false ? \"!==\" : \"===\"} \"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// A prop value the maps cannot faithfully express as a static condition\n// (dynamic expressions, `{undefined}`); elements carrying one are skipped\n// so runtime behavior is never silently changed.\nconst UNSUPPORTED_VALUE: unique symbol = Symbol(\"unsupported\");\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 * - anything else (dynamic expressions): → UNSUPPORTED_VALUE\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 // NullLiteral bases Literal in ast-types but carries no `value` field,\n // so it must be recognized before the generic Literal branch.\n if (j.NullLiteral.check(expr)) return null;\n if (j.Literal.check(expr)) {\n if (expr.value === null) return null;\n return expr.value;\n }\n return UNSUPPORTED_VALUE;\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 UNSUPPORTED_VALUE;\n};\n\n// Composed as a syntax tree so the printer parenthesizes by precedence;\n// concatenated text lets `!` and `&&` reassociate a fragment's own operators.\nconst buildConditionString = (\n j: any,\n fragments: ConditionFragment[],\n): string => {\n const parseExpression = (source: string) =>\n j(`${source};`).find(j.ExpressionStatement).nodes()[0]!.expression;\n\n const condition = fragments\n .map((f) => {\n const expression = parseExpression(f.expression);\n return f.negated ? j.unaryExpression(\"!\", expression) : expression;\n })\n .reduce((left: any, right: any) => j.logicalExpression(\"&&\", left, right));\n\n return j(condition).toSource();\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 // Opening and closing tags are rewritten together per element, so a\n // skipped element can never be left with a mismatched closing tag.\n const convertElementToAuiIf = (elementPath: any, conditionBody: string) => {\n const arrowFnAst = j(`(s) => ${conditionBody}`)\n .find(j.ArrowFunctionExpression)\n .paths()[0]!.value;\n\n const opening = elementPath.value.openingElement;\n opening.name = j.jsxIdentifier(\"AuiIf\");\n opening.attributes = [\n j.jsxAttribute(\n j.jsxIdentifier(\"condition\"),\n j.jsxExpressionContainer(arrowFnAst),\n ),\n ];\n if (elementPath.value.closingElement) {\n elementPath.value.closingElement.name = j.jsxIdentifier(\"AuiIf\");\n }\n\n needsAuiIfImport = true;\n markAsChanged();\n };\n\n // Process fixed-condition components: <ThreadPrimitive.Empty> → <AuiIf condition={...}>\n root.find(j.JSXElement).forEach((path: any) => {\n const name = path.value.openingElement.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 conditionBody = fixedConditionMap[primitiveName]?.[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.openingElement.attributes || [];\n if (attrs.length > 0) return;\n\n convertElementToAuiIf(path, conditionBody);\n });\n\n // Process JSX elements: <ThreadPrimitive.If ...> → <AuiIf condition={...}>\n root.find(j.JSXElement).forEach((path: any) => {\n const name = path.value.openingElement.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.openingElement.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) {\n // e.g. JSXNamespacedName — not expressible as a condition\n hasUnknownProp = true;\n continue;\n }\n\n const mapper = propMap[propName];\n if (!mapper) {\n hasUnknownProp = true;\n continue;\n }\n\n const value = getAttrValue(j, attr);\n if (value === UNSUPPORTED_VALUE) {\n hasUnknownProp = true;\n continue;\n }\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 convertElementToAuiIf(path, buildConditionString(j, fragments));\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\";\nimport { resolveBinding } from \"../utils/resolveBinding\";\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: (v) => ({\n expression: `s.message.role ${v === false ? \"!==\" : \"===\"} \"user\"`,\n negated: false,\n }),\n assistant: (v) => ({\n expression: `s.message.role ${v === false ? \"!==\" : \"===\"} \"assistant\"`,\n negated: false,\n }),\n system: (v) => ({\n expression: `s.message.role ${v === false ? \"!==\" : \"===\"} \"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// A prop value the maps cannot faithfully express as a static condition\n// (dynamic expressions, `{undefined}`); elements carrying one are skipped\n// so runtime behavior is never silently changed.\nconst UNSUPPORTED_VALUE: unique symbol = Symbol(\"unsupported\");\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 * - anything else (dynamic expressions): → UNSUPPORTED_VALUE\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 // NullLiteral bases Literal in ast-types but carries no `value` field,\n // so it must be recognized before the generic Literal branch.\n if (j.NullLiteral.check(expr)) return null;\n if (j.Literal.check(expr)) {\n if (expr.value === null) return null;\n return expr.value;\n }\n return UNSUPPORTED_VALUE;\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 UNSUPPORTED_VALUE;\n};\n\n// Composed as a syntax tree so the printer parenthesizes by precedence;\n// concatenated text lets `!` and `&&` reassociate a fragment's own operators.\nconst buildConditionString = (\n j: any,\n fragments: ConditionFragment[],\n): string => {\n const parseExpression = (source: string) =>\n j(`${source};`).find(j.ExpressionStatement).nodes()[0]!.expression;\n\n const condition = fragments\n .map((f) => {\n const expression = parseExpression(f.expression);\n return f.negated ? j.unaryExpression(\"!\", expression) : expression;\n })\n .reduce((left: any, right: any) => j.logicalExpression(\"&&\", left, right));\n\n return j(condition).toSource();\n};\n\nconst migratePrimitiveIfToAuiIf = createTransformer(\n ({ j, root, markAsChanged }) => {\n const importedPrimitives = new Map<\n string,\n { name: string; declaration: any; binding: any }\n >();\n const auiIfImports: { source: string; binding: any }[] = [];\n const usedNames = new Set<string>();\n root\n .find(j.Identifier)\n .forEach((path: any) => usedNames.add(path.value.name));\n root\n .find(j.JSXIdentifier)\n .forEach((path: any) => usedNames.add(path.value.name));\n\n root.find(j.ImportDeclaration).forEach((path: any) => {\n const declaration = path.value;\n const source = declaration.source.value;\n if (\n typeof source !== \"string\" ||\n !source.startsWith(\"@assistant-ui/\") ||\n declaration.importKind === \"type\"\n )\n return;\n\n declaration.specifiers?.forEach((specifier: any) => {\n if (\n !j.ImportSpecifier.check(specifier) ||\n !j.Identifier.check(specifier.imported) ||\n !j.Identifier.check(specifier.local) ||\n (specifier as { importKind?: string }).importKind === \"type\"\n )\n return;\n const name = specifier.imported.name;\n const binding = specifier.local;\n if (primitiveMap[name] || fixedConditionMap[name]) {\n importedPrimitives.set(binding.name, { name, declaration, binding });\n }\n if (name === \"AuiIf\") auiIfImports.push({ source, binding });\n });\n });\n\n if (importedPrimitives.size === 0) return;\n\n const getPrimitive = (path: any, localName: string) => {\n const primitive = importedPrimitives.get(localName);\n return primitive &&\n resolveBinding(j, path, localName) === primitive.binding\n ? primitive\n : undefined;\n };\n\n const getAuiIfName = (path: any, declaration: any) => {\n const source = declaration.source.value;\n const existing = auiIfImports.find(\n (entry) =>\n entry.source === source &&\n !/^[a-z]/.test(entry.binding.name) &&\n resolveBinding(j, path, entry.binding.name) === entry.binding,\n );\n if (existing) return existing.binding.name;\n\n let name = \"AuiIf\";\n for (let suffix = 1; usedNames.has(name); suffix++)\n name = `AuiIf${suffix}`;\n usedNames.add(name);\n const binding = j.identifier(name);\n declaration.specifiers.push(\n j.importSpecifier(j.identifier(\"AuiIf\"), binding),\n );\n auiIfImports.push({ source, binding });\n return name;\n };\n\n // Opening and closing tags are rewritten together per element, so a\n // skipped element can never be left with a mismatched closing tag.\n const convertElementToAuiIf = (\n elementPath: any,\n conditionBody: string,\n declaration: any,\n ) => {\n const localName = getAuiIfName(elementPath, declaration);\n const arrowFnAst = j(`(s) => ${conditionBody}`)\n .find(j.ArrowFunctionExpression)\n .paths()[0]!.value;\n\n const opening = elementPath.value.openingElement;\n opening.name = j.jsxIdentifier(localName);\n opening.attributes = [\n j.jsxAttribute(\n j.jsxIdentifier(\"condition\"),\n j.jsxExpressionContainer(arrowFnAst),\n ),\n ];\n if (elementPath.value.closingElement) {\n elementPath.value.closingElement.name = j.jsxIdentifier(localName);\n }\n\n markAsChanged();\n };\n\n // Process fixed-condition components: <ThreadPrimitive.Empty> → <AuiIf condition={...}>\n root.find(j.JSXElement).forEach((path: any) => {\n const name = path.value.openingElement.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 primitive = getPrimitive(path, name.object.name);\n if (!primitive) return;\n const propertyName = name.property.name as string;\n const conditionBody = fixedConditionMap[primitive.name]?.[propertyName];\n if (!conditionBody) return;\n\n // Only transform if there are no props (other than children, which are implicit)\n const attrs: any[] = path.value.openingElement.attributes || [];\n if (attrs.length > 0) return;\n\n convertElementToAuiIf(path, conditionBody, primitive.declaration);\n });\n\n // Process JSX elements: <ThreadPrimitive.If ...> → <AuiIf condition={...}>\n root.find(j.JSXElement).forEach((path: any) => {\n const name = path.value.openingElement.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 primitive = getPrimitive(path, name.object.name);\n if (!primitive) return;\n const propMap = primitiveMap[primitive.name];\n if (!propMap) return;\n\n // Extract props\n const attrs: any[] = path.value.openingElement.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) {\n // e.g. JSXNamespacedName — not expressible as a condition\n hasUnknownProp = true;\n continue;\n }\n\n const mapper = propMap[propName];\n if (!mapper) {\n hasUnknownProp = true;\n continue;\n }\n\n const value = getAttrValue(j, attr);\n if (value === UNSUPPORTED_VALUE) {\n hasUnknownProp = true;\n continue;\n }\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 convertElementToAuiIf(\n path,\n buildConditionString(j, fragments),\n primitive.declaration,\n );\n });\n },\n);\n\nexport default migratePrimitiveIfToAuiIf;\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"ui-package-split.d.ts","sourceRoot":"","sources":["../../../src/codemods/v0-8/ui-package-split.ts"],"names":[],"mappings":"AA8BA,QAAA,MAAM,kBAAkB,6HAoKtB,CAAC;AAEH,eAAe,kBAAkB,CAAC"}
1
+ {"version":3,"file":"ui-package-split.d.ts","sourceRoot":"","sources":["../../../src/codemods/v0-8/ui-package-split.ts"],"names":[],"mappings":"AA8BA,QAAA,MAAM,kBAAkB,6HA8HtB,CAAC;AAEH,eAAe,kBAAkB,CAAC"}
@@ -29,44 +29,20 @@ const reactUIExports = [
29
29
  ];
30
30
  const migrateAssistantUI = createTransformer(({ j, root, markAsChanged }) => {
31
31
  const sourcesToMigrate = ["@assistant-ui/react", "@assistant-ui/react-markdown"];
32
- const movedSpecifiers = [];
33
- let lastMigratedImportPath = null;
34
- root.find(j.ImportDeclaration).filter((path) => sourcesToMigrate.includes(path.value.source.value)).forEach((path) => {
35
- let hadMigratedSpecifiers = false;
36
- const remainingSpecifiers = [];
37
- path.value.specifiers.forEach((specifier) => {
38
- if (j.ImportSpecifier.check(specifier) && reactUIExports.includes(specifier.imported.name)) {
39
- movedSpecifiers.push(specifier);
40
- hadMigratedSpecifiers = true;
41
- } else remainingSpecifiers.push(specifier);
42
- });
43
- if (hadMigratedSpecifiers) lastMigratedImportPath = path;
44
- if (remainingSpecifiers.length === 0) {
45
- j(path).remove();
46
- markAsChanged();
47
- } else if (remainingSpecifiers.length !== path.value.specifiers.length) {
48
- path.value.specifiers = remainingSpecifiers;
49
- markAsChanged();
50
- }
51
- });
52
- if (movedSpecifiers.length > 0) {
53
- const existingReactUIImport = root.find(j.ImportDeclaration, { source: { value: "@assistant-ui/react-ui" } });
54
- if (existingReactUIImport.size() > 0) existingReactUIImport.forEach((path) => {
55
- movedSpecifiers.forEach((specifier) => {
56
- if (!path.value.specifiers.some((s) => s.imported.name === specifier.imported.name)) path.value.specifiers.push(specifier);
57
- });
58
- });
32
+ root.find(j.ImportDeclaration).filter((path) => sourcesToMigrate.includes(path.node.source.value)).forEach((path) => {
33
+ const specifiers = path.node.specifiers ?? [];
34
+ const moved = specifiers.filter((specifier) => j.ImportSpecifier.check(specifier) && reactUIExports.includes(specifier.imported.name));
35
+ if (moved.length === 0) return;
36
+ const destination = j.literal("@assistant-ui/react-ui");
37
+ if (moved.length === specifiers.length) path.node.source = destination;
59
38
  else {
60
- const newImport = j.importDeclaration(movedSpecifiers, j.literal("@assistant-ui/react-ui"));
61
- if (lastMigratedImportPath) j(lastMigratedImportPath).insertAfter(newImport);
62
- else {
63
- const firstImport = root.find(j.ImportDeclaration).at(0);
64
- if (firstImport.size() > 0) firstImport.insertBefore(newImport);
65
- else root.get().node.program.body.unshift(newImport);
66
- }
39
+ path.node.specifiers = specifiers.filter((specifier) => !moved.includes(specifier));
40
+ const declaration = j.importDeclaration(moved, destination);
41
+ declaration.importKind = path.node.importKind ?? "value";
42
+ j(path).insertAfter(declaration);
67
43
  }
68
44
  markAsChanged();
69
- }
45
+ });
70
46
  const cssReplacements = {
71
47
  "@assistant-ui/react/styles/index.css": "@assistant-ui/react-ui/styles/index.css",
72
48
  "@assistant-ui/react/styles/modal.css": "@assistant-ui/react-ui/styles/modal.css",