assistant-ui 0.0.49 → 0.0.50
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/utils/createTransformer.d.ts +15 -0
- package/dist/codemods/utils/createTransformer.d.ts.map +1 -0
- package/dist/codemods/v0-8/ui-package-split.d.ts +3 -0
- package/dist/codemods/v0-8/ui-package-split.d.ts.map +1 -0
- package/dist/codemods/v0-9/edge-package-split.d.ts +3 -0
- package/dist/codemods/v0-9/edge-package-split.d.ts.map +1 -0
- package/dist/commands/add.d.ts +3 -0
- package/dist/commands/add.d.ts.map +1 -0
- package/dist/commands/create.d.ts +3 -0
- package/dist/commands/create.d.ts.map +1 -0
- package/dist/commands/init.d.ts +3 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/update.d.ts +3 -0
- package/dist/commands/update.d.ts.map +1 -0
- package/dist/commands/upgrade.d.ts +10 -0
- package/dist/commands/upgrade.d.ts.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/lib/install-ai-sdk-lib.d.ts +2 -0
- package/dist/lib/install-ai-sdk-lib.d.ts.map +1 -0
- package/dist/lib/install-edge-lib.d.ts +2 -0
- package/dist/lib/install-edge-lib.d.ts.map +1 -0
- package/dist/lib/install-ui-lib.d.ts +2 -0
- package/dist/lib/install-ui-lib.d.ts.map +1 -0
- package/dist/lib/transform-options.d.ts +7 -0
- package/dist/lib/transform-options.d.ts.map +1 -0
- package/dist/lib/transform.d.ts +21 -0
- package/dist/lib/transform.d.ts.map +1 -0
- package/dist/lib/upgrade.d.ts +9 -0
- package/dist/lib/upgrade.d.ts.map +1 -0
- package/package.json +3 -5
- package/src/codemods/utils/createTransformer.ts +41 -0
- package/src/codemods/v0-8/ui-package-split.ts +203 -0
- package/src/codemods/v0-9/edge-package-split.ts +226 -0
- package/src/commands/add.ts +47 -0
- package/src/commands/create.ts +92 -0
- package/src/commands/init.ts +50 -0
- package/src/commands/update.ts +60 -0
- package/src/commands/upgrade.ts +55 -0
- package/src/index.ts +28 -0
- package/src/lib/install-ai-sdk-lib.ts +92 -0
- package/src/lib/install-edge-lib.ts +92 -0
- package/src/lib/install-ui-lib.ts +92 -0
- package/src/lib/transform-options.ts +6 -0
- package/src/lib/transform.ts +177 -0
- package/src/lib/upgrade.ts +83 -0
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
import { createTransformer } from "../utils/createTransformer";
|
|
2
|
+
|
|
3
|
+
const reactEdgeExports: string[] = [
|
|
4
|
+
// Edge Runtime
|
|
5
|
+
"useEdgeRuntime",
|
|
6
|
+
"EdgeRuntimeOptions",
|
|
7
|
+
"EdgeModelAdapter",
|
|
8
|
+
"EdgeChatAdapter",
|
|
9
|
+
"EdgeRuntimeRequestOptions",
|
|
10
|
+
"createEdgeRuntimeAPI",
|
|
11
|
+
"getEdgeRuntimeResponse",
|
|
12
|
+
|
|
13
|
+
// Core Types
|
|
14
|
+
"CoreMessage",
|
|
15
|
+
"CoreUserMessage",
|
|
16
|
+
"CoreAssistantMessage",
|
|
17
|
+
"CoreSystemMessage",
|
|
18
|
+
"CoreUserContentPart",
|
|
19
|
+
"CoreAssistantContentPart",
|
|
20
|
+
"CoreToolCallContentPart",
|
|
21
|
+
|
|
22
|
+
// Core message converters
|
|
23
|
+
"fromCoreMessages",
|
|
24
|
+
"fromCoreMessage",
|
|
25
|
+
"toCoreMessages",
|
|
26
|
+
"toCoreMessage",
|
|
27
|
+
];
|
|
28
|
+
|
|
29
|
+
// Language model converters to be moved to react-ai-sdk
|
|
30
|
+
const reactAiSdkExports: string[] = [
|
|
31
|
+
"toLanguageModelMessages",
|
|
32
|
+
"toLanguageModelTools",
|
|
33
|
+
"fromLanguageModelMessages",
|
|
34
|
+
"fromLanguageModelTools",
|
|
35
|
+
"useDangerousInBrowserRuntime",
|
|
36
|
+
];
|
|
37
|
+
|
|
38
|
+
const migrateToEdgePackage = createTransformer(({ j, root, markAsChanged }) => {
|
|
39
|
+
const sourcesToMigrate: string[] = ["@assistant-ui/react"];
|
|
40
|
+
const movedEdgeSpecifiers: any[] = [];
|
|
41
|
+
const movedAiSdkSpecifiers: any[] = [];
|
|
42
|
+
let lastMigratedImportPath: any = null;
|
|
43
|
+
|
|
44
|
+
root
|
|
45
|
+
.find(j.ImportDeclaration)
|
|
46
|
+
.filter((path: any) => sourcesToMigrate.includes(path.value.source.value))
|
|
47
|
+
.forEach((path: any) => {
|
|
48
|
+
let hadMigratedSpecifiers = false;
|
|
49
|
+
const remainingSpecifiers: any[] = [];
|
|
50
|
+
path.value.specifiers.forEach((specifier: any) => {
|
|
51
|
+
if (
|
|
52
|
+
j.ImportSpecifier.check(specifier) &&
|
|
53
|
+
reactEdgeExports.includes(specifier.imported.name as string)
|
|
54
|
+
) {
|
|
55
|
+
movedEdgeSpecifiers.push(specifier);
|
|
56
|
+
hadMigratedSpecifiers = true;
|
|
57
|
+
} else if (
|
|
58
|
+
j.ImportSpecifier.check(specifier) &&
|
|
59
|
+
reactAiSdkExports.includes(specifier.imported.name as string)
|
|
60
|
+
) {
|
|
61
|
+
movedAiSdkSpecifiers.push(specifier);
|
|
62
|
+
hadMigratedSpecifiers = true;
|
|
63
|
+
} else {
|
|
64
|
+
remainingSpecifiers.push(specifier);
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
if (hadMigratedSpecifiers) {
|
|
68
|
+
lastMigratedImportPath = path;
|
|
69
|
+
}
|
|
70
|
+
if (remainingSpecifiers.length === 0) {
|
|
71
|
+
j(path).remove();
|
|
72
|
+
markAsChanged();
|
|
73
|
+
} else if (remainingSpecifiers.length !== path.value.specifiers.length) {
|
|
74
|
+
path.value.specifiers = remainingSpecifiers;
|
|
75
|
+
markAsChanged();
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
// Add imports for react-edge
|
|
80
|
+
if (movedEdgeSpecifiers.length > 0) {
|
|
81
|
+
const existingEdgeImport = root.find(j.ImportDeclaration, {
|
|
82
|
+
source: { value: "@assistant-ui/react-edge" },
|
|
83
|
+
});
|
|
84
|
+
if (existingEdgeImport.size() > 0) {
|
|
85
|
+
existingEdgeImport.forEach((path: any) => {
|
|
86
|
+
movedEdgeSpecifiers.forEach((specifier: any) => {
|
|
87
|
+
if (
|
|
88
|
+
!path.value.specifiers.some(
|
|
89
|
+
(s: any) => s.imported.name === specifier.imported.name,
|
|
90
|
+
)
|
|
91
|
+
) {
|
|
92
|
+
path.value.specifiers.push(specifier);
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
});
|
|
96
|
+
} else {
|
|
97
|
+
const newImport = j.importDeclaration(
|
|
98
|
+
movedEdgeSpecifiers,
|
|
99
|
+
j.literal("@assistant-ui/react-edge"),
|
|
100
|
+
);
|
|
101
|
+
if (lastMigratedImportPath) {
|
|
102
|
+
j(lastMigratedImportPath).insertAfter(newImport);
|
|
103
|
+
} else {
|
|
104
|
+
const firstImport = root.find(j.ImportDeclaration).at(0);
|
|
105
|
+
if (firstImport.size() > 0) {
|
|
106
|
+
firstImport.insertBefore(newImport);
|
|
107
|
+
} else {
|
|
108
|
+
root.get().node.program.body.unshift(newImport);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
markAsChanged();
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Add imports for react-ai-sdk
|
|
116
|
+
if (movedAiSdkSpecifiers.length > 0) {
|
|
117
|
+
const existingAiSdkImport = root.find(j.ImportDeclaration, {
|
|
118
|
+
source: { value: "@assistant-ui/react-ai-sdk" },
|
|
119
|
+
});
|
|
120
|
+
if (existingAiSdkImport.size() > 0) {
|
|
121
|
+
existingAiSdkImport.forEach((path: any) => {
|
|
122
|
+
movedAiSdkSpecifiers.forEach((specifier: any) => {
|
|
123
|
+
if (
|
|
124
|
+
!path.value.specifiers.some(
|
|
125
|
+
(s: any) => s.imported.name === specifier.imported.name,
|
|
126
|
+
)
|
|
127
|
+
) {
|
|
128
|
+
path.value.specifiers.push(specifier);
|
|
129
|
+
}
|
|
130
|
+
});
|
|
131
|
+
});
|
|
132
|
+
} else {
|
|
133
|
+
const newImport = j.importDeclaration(
|
|
134
|
+
movedAiSdkSpecifiers,
|
|
135
|
+
j.literal("@assistant-ui/react-ai-sdk"),
|
|
136
|
+
);
|
|
137
|
+
if (lastMigratedImportPath) {
|
|
138
|
+
j(lastMigratedImportPath).insertAfter(newImport);
|
|
139
|
+
} else {
|
|
140
|
+
const firstImport = root.find(j.ImportDeclaration).at(0);
|
|
141
|
+
if (firstImport.size() > 0) {
|
|
142
|
+
firstImport.insertBefore(newImport);
|
|
143
|
+
} else {
|
|
144
|
+
root.get().node.program.body.unshift(newImport);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
markAsChanged();
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// Migrate imports from edge/converters
|
|
152
|
+
root.find(j.ImportDeclaration).forEach((path: any) => {
|
|
153
|
+
const sourceValue: string = path.value.source.value;
|
|
154
|
+
if (
|
|
155
|
+
sourceValue.startsWith("@assistant-ui/react/") &&
|
|
156
|
+
(sourceValue.includes("edge/") ||
|
|
157
|
+
sourceValue.includes("dangerous-in-browser/"))
|
|
158
|
+
) {
|
|
159
|
+
path.value.source = j.literal(
|
|
160
|
+
sourceValue.replace(
|
|
161
|
+
"@assistant-ui/react/",
|
|
162
|
+
"@assistant-ui/react-edge/",
|
|
163
|
+
),
|
|
164
|
+
);
|
|
165
|
+
markAsChanged();
|
|
166
|
+
}
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
// Migrate language model converter imports from react-edge to react-ai-sdk
|
|
170
|
+
root.find(j.ImportDeclaration).forEach((path: any) => {
|
|
171
|
+
const sourceValue: string = path.value.source.value;
|
|
172
|
+
if (sourceValue === "@assistant-ui/react-edge") {
|
|
173
|
+
let hasLanguageModelConverters = false;
|
|
174
|
+
const remainingSpecifiers: any[] = [];
|
|
175
|
+
const aiSdkSpecifiers: any[] = [];
|
|
176
|
+
|
|
177
|
+
path.value.specifiers.forEach((specifier: any) => {
|
|
178
|
+
if (
|
|
179
|
+
j.ImportSpecifier.check(specifier) &&
|
|
180
|
+
reactAiSdkExports.includes(specifier.imported.name as string)
|
|
181
|
+
) {
|
|
182
|
+
aiSdkSpecifiers.push(specifier);
|
|
183
|
+
hasLanguageModelConverters = true;
|
|
184
|
+
} else {
|
|
185
|
+
remainingSpecifiers.push(specifier);
|
|
186
|
+
}
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
if (hasLanguageModelConverters) {
|
|
190
|
+
if (remainingSpecifiers.length === 0) {
|
|
191
|
+
j(path).remove();
|
|
192
|
+
} else {
|
|
193
|
+
path.value.specifiers = remainingSpecifiers;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
const existingAiSdkImport = root.find(j.ImportDeclaration, {
|
|
197
|
+
source: { value: "@assistant-ui/react-ai-sdk" },
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
if (existingAiSdkImport.size() > 0) {
|
|
201
|
+
existingAiSdkImport.forEach((importPath: any) => {
|
|
202
|
+
aiSdkSpecifiers.forEach((specifier: any) => {
|
|
203
|
+
if (
|
|
204
|
+
!importPath.value.specifiers.some(
|
|
205
|
+
(s: any) => s.imported.name === specifier.imported.name,
|
|
206
|
+
)
|
|
207
|
+
) {
|
|
208
|
+
importPath.value.specifiers.push(specifier);
|
|
209
|
+
}
|
|
210
|
+
});
|
|
211
|
+
});
|
|
212
|
+
} else {
|
|
213
|
+
const newImport = j.importDeclaration(
|
|
214
|
+
aiSdkSpecifiers,
|
|
215
|
+
j.literal("@assistant-ui/react-ai-sdk"),
|
|
216
|
+
);
|
|
217
|
+
j(path).insertAfter(newImport);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
markAsChanged();
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
});
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
export default migrateToEdgePackage;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import { spawn } from "cross-spawn";
|
|
3
|
+
|
|
4
|
+
const REGISTRY_BASE_URL = "https://r.assistant-ui.com";
|
|
5
|
+
|
|
6
|
+
export const add = new Command()
|
|
7
|
+
.name("add")
|
|
8
|
+
.description("add a component to your project")
|
|
9
|
+
.argument("<components...>", "the components to add")
|
|
10
|
+
.option("-y, --yes", "skip confirmation prompt.", true)
|
|
11
|
+
.option("-o, --overwrite", "overwrite existing files.", false)
|
|
12
|
+
.option(
|
|
13
|
+
"-c, --cwd <cwd>",
|
|
14
|
+
"the working directory. defaults to the current directory.",
|
|
15
|
+
process.cwd(),
|
|
16
|
+
)
|
|
17
|
+
.option("-p, --path <path>", "the path to add the component to.")
|
|
18
|
+
.action((components: string[], opts) => {
|
|
19
|
+
const componentsToAdd = components.map((c) => {
|
|
20
|
+
if (!/^[a-zA-Z0-9-\/]+$/.test(c)) {
|
|
21
|
+
throw new Error(`Invalid component name: ${c}`);
|
|
22
|
+
}
|
|
23
|
+
return `${REGISTRY_BASE_URL}/${encodeURIComponent(c)}`;
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
const args = [`shadcn@latest`, "add", ...componentsToAdd];
|
|
27
|
+
|
|
28
|
+
if (opts.yes) args.push("--yes");
|
|
29
|
+
if (opts.overwrite) args.push("--overwrite");
|
|
30
|
+
if (opts.cwd) args.push("--cwd", opts.cwd);
|
|
31
|
+
if (opts.path) args.push("--path", opts.path);
|
|
32
|
+
|
|
33
|
+
const child = spawn("npx", args, {
|
|
34
|
+
stdio: "inherit",
|
|
35
|
+
shell: true,
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
child.on("error", (error) => {
|
|
39
|
+
console.error(`Error: ${error.message}`);
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
child.on("close", (code) => {
|
|
43
|
+
if (code !== 0) {
|
|
44
|
+
console.log(`other-package-script process exited with code ${code}`);
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
});
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import chalk from "chalk";
|
|
3
|
+
import { spawn } from "cross-spawn";
|
|
4
|
+
|
|
5
|
+
export const create = new Command()
|
|
6
|
+
.name("create")
|
|
7
|
+
.description("create a new project")
|
|
8
|
+
.argument("[project-directory]")
|
|
9
|
+
.usage(`${chalk.green("[project-directory]")} [options]`)
|
|
10
|
+
.option(
|
|
11
|
+
"-t, --template <template>",
|
|
12
|
+
`
|
|
13
|
+
|
|
14
|
+
The template to use for the project, e.g. default, langgraph
|
|
15
|
+
`,
|
|
16
|
+
)
|
|
17
|
+
.option(
|
|
18
|
+
"--use-npm",
|
|
19
|
+
`
|
|
20
|
+
|
|
21
|
+
Explicitly tell the CLI to bootstrap the application using npm
|
|
22
|
+
`,
|
|
23
|
+
)
|
|
24
|
+
.option(
|
|
25
|
+
"--use-pnpm",
|
|
26
|
+
`
|
|
27
|
+
|
|
28
|
+
Explicitly tell the CLI to bootstrap the application using pnpm
|
|
29
|
+
`,
|
|
30
|
+
)
|
|
31
|
+
.option(
|
|
32
|
+
"--use-yarn",
|
|
33
|
+
`
|
|
34
|
+
|
|
35
|
+
Explicitly tell the CLI to bootstrap the application using Yarn
|
|
36
|
+
`,
|
|
37
|
+
)
|
|
38
|
+
.option(
|
|
39
|
+
"--use-bun",
|
|
40
|
+
`
|
|
41
|
+
|
|
42
|
+
Explicitly tell the CLI to bootstrap the application using Bun
|
|
43
|
+
`,
|
|
44
|
+
)
|
|
45
|
+
.option(
|
|
46
|
+
"--skip-install",
|
|
47
|
+
`
|
|
48
|
+
|
|
49
|
+
Explicitly tell the CLI to skip installing packages
|
|
50
|
+
`,
|
|
51
|
+
)
|
|
52
|
+
.action((_, opts) => {
|
|
53
|
+
const templates = {
|
|
54
|
+
default: "https://github.com/assistant-ui/assistant-ui-starter",
|
|
55
|
+
langgraph:
|
|
56
|
+
"https://github.com/assistant-ui/assistant-ui-starter-langgraph",
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
const templateUrl =
|
|
60
|
+
templates[(opts.template as keyof typeof templates) ?? "default"];
|
|
61
|
+
if (!templateUrl) {
|
|
62
|
+
console.error(`Unknown template: ${opts.template}`);
|
|
63
|
+
process.exit(1);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const filteredArgs = process.argv.slice(3).filter((arg, index, arr) => {
|
|
67
|
+
return !(
|
|
68
|
+
arg === "-t" ||
|
|
69
|
+
arg === "--template" ||
|
|
70
|
+
arr[index - 1] === "-t" ||
|
|
71
|
+
arr[index - 1] === "--template"
|
|
72
|
+
);
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
const child = spawn(
|
|
76
|
+
"npx",
|
|
77
|
+
[`create-next-app@latest`, ...filteredArgs, "-e", templateUrl],
|
|
78
|
+
{
|
|
79
|
+
stdio: "inherit",
|
|
80
|
+
},
|
|
81
|
+
);
|
|
82
|
+
|
|
83
|
+
child.on("error", (error) => {
|
|
84
|
+
console.error(`Error: ${error.message}`);
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
child.on("close", (code) => {
|
|
88
|
+
if (code !== 0) {
|
|
89
|
+
console.log(`other-package-script process exited with code ${code}`);
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
});
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import { spawn } from "cross-spawn";
|
|
3
|
+
import fs from "fs";
|
|
4
|
+
import path from "path";
|
|
5
|
+
import chalk from "chalk";
|
|
6
|
+
import { create } from "./create";
|
|
7
|
+
|
|
8
|
+
export const init = new Command()
|
|
9
|
+
.name("init")
|
|
10
|
+
.description("initialize assistant-ui in a new or existing project")
|
|
11
|
+
.action(async () => {
|
|
12
|
+
// Check if package.json exists in the current directory
|
|
13
|
+
const packageJsonPath = path.join(process.cwd(), "package.json");
|
|
14
|
+
const packageJsonExists = fs.existsSync(packageJsonPath);
|
|
15
|
+
|
|
16
|
+
if (packageJsonExists) {
|
|
17
|
+
// If package.json exists, run shadcn add command
|
|
18
|
+
console.log(
|
|
19
|
+
chalk.blue("Initializing assistant-ui in existing project..."),
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
const child = spawn(
|
|
23
|
+
"npx",
|
|
24
|
+
[
|
|
25
|
+
`shadcn@latest`,
|
|
26
|
+
"add",
|
|
27
|
+
"https://r.assistant-ui.com/chat/b/ai-sdk-quick-start/json",
|
|
28
|
+
],
|
|
29
|
+
{
|
|
30
|
+
stdio: "inherit",
|
|
31
|
+
},
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
child.on("error", (error) => {
|
|
35
|
+
console.error(`Error: ${error.message}`);
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
child.on("close", (code) => {
|
|
39
|
+
if (code !== 0) {
|
|
40
|
+
console.log(`shadcn process exited with code ${code}`);
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
} else {
|
|
44
|
+
// If package.json doesn't exist, use the create command
|
|
45
|
+
console.log(chalk.blue("Creating a new assistant-ui project..."));
|
|
46
|
+
|
|
47
|
+
// Execute the create command with default template
|
|
48
|
+
await create.parseAsync([]);
|
|
49
|
+
}
|
|
50
|
+
});
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import fs from "fs";
|
|
3
|
+
import path from "path";
|
|
4
|
+
import chalk from "chalk";
|
|
5
|
+
import { detect } from "detect-package-manager";
|
|
6
|
+
import { sync as spawnSync } from "cross-spawn";
|
|
7
|
+
|
|
8
|
+
export const update = new Command()
|
|
9
|
+
.name("update")
|
|
10
|
+
.description(
|
|
11
|
+
"Update all '@assistant-ui/*' and 'assistant-stream' packages in package.json to latest versions using your package manager.",
|
|
12
|
+
)
|
|
13
|
+
.option("--dry", "Print the package manager command instead of running it.")
|
|
14
|
+
.action(async (opts) => {
|
|
15
|
+
const packageJsonPath = path.join(process.cwd(), "package.json");
|
|
16
|
+
if (!fs.existsSync(packageJsonPath)) {
|
|
17
|
+
console.error(
|
|
18
|
+
chalk.red("No package.json found in the current directory."),
|
|
19
|
+
);
|
|
20
|
+
process.exit(1);
|
|
21
|
+
}
|
|
22
|
+
const pkg = JSON.parse(fs.readFileSync(packageJsonPath, "utf-8"));
|
|
23
|
+
const sections = ["dependencies", "devDependencies"];
|
|
24
|
+
const targets: string[] = [];
|
|
25
|
+
for (const section of sections) {
|
|
26
|
+
if (!pkg[section]) continue;
|
|
27
|
+
for (const dep in pkg[section]) {
|
|
28
|
+
if (dep.startsWith("@assistant-ui/") || dep === "assistant-stream") {
|
|
29
|
+
targets.push(dep);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
if (!targets.length) {
|
|
34
|
+
console.log(chalk.yellow("No matching packages found to update."));
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
const pm = await detect({ cwd: process.cwd() });
|
|
38
|
+
let cmd: string;
|
|
39
|
+
if (pm === "yarn") {
|
|
40
|
+
cmd = `yarn add ${targets.map((d) => `${d}@latest`).join(" ")}`;
|
|
41
|
+
} else if (pm === "pnpm") {
|
|
42
|
+
cmd = `pnpm add ${targets.map((d) => `${d}@latest`).join(" ")}`;
|
|
43
|
+
} else if (pm === "bun") {
|
|
44
|
+
cmd = `bun add ${targets.map((d) => `${d}@latest`).join(" ")}`;
|
|
45
|
+
} else {
|
|
46
|
+
cmd = `npm install ${targets.map((d) => `${d}@latest`).join(" ")}`;
|
|
47
|
+
}
|
|
48
|
+
if (opts.dry) {
|
|
49
|
+
console.log(chalk.blue("\nDry run: would run the following command:"));
|
|
50
|
+
console.log(cmd);
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
console.log(chalk.blue(`\nRunning: ${cmd}`));
|
|
54
|
+
const result = spawnSync(cmd, { shell: true, stdio: "inherit" });
|
|
55
|
+
if (result.status !== 0) {
|
|
56
|
+
console.error(chalk.red("Package manager update failed."));
|
|
57
|
+
process.exit(result.status || 1);
|
|
58
|
+
}
|
|
59
|
+
console.log(chalk.green("\nAll packages updated to latest version!"));
|
|
60
|
+
});
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import { transform } from "../lib/transform";
|
|
3
|
+
import { upgrade } from "../lib/upgrade";
|
|
4
|
+
import debug from "debug";
|
|
5
|
+
|
|
6
|
+
export interface TransformOptions {
|
|
7
|
+
dry?: boolean;
|
|
8
|
+
print?: boolean;
|
|
9
|
+
verbose?: boolean;
|
|
10
|
+
jscodeshift?: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const error = debug("codemod:error");
|
|
14
|
+
debug.enable("codemod:*");
|
|
15
|
+
|
|
16
|
+
const addTransformOptions = (command: Command): Command => {
|
|
17
|
+
return command
|
|
18
|
+
.option("-d, --dry", "Dry run (no changes are made to files)")
|
|
19
|
+
.option("-p, --print", "Print transformed files to stdout")
|
|
20
|
+
.option("--verbose", "Show more information about the transform process")
|
|
21
|
+
.option(
|
|
22
|
+
"-j, --jscodeshift <options>",
|
|
23
|
+
"Pass options directly to jscodeshift",
|
|
24
|
+
);
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export const codemodCommand = addTransformOptions(
|
|
28
|
+
new Command()
|
|
29
|
+
.name("codemod")
|
|
30
|
+
.description("CLI tool for running codemods")
|
|
31
|
+
.argument("<codemod>", "Codemod to run (e.g., rewrite-framework-imports)")
|
|
32
|
+
.argument("<source>", "Path to source files or directory to transform"),
|
|
33
|
+
).action((codemod, source, options: TransformOptions) => {
|
|
34
|
+
try {
|
|
35
|
+
transform(codemod, source, options);
|
|
36
|
+
} catch (err: any) {
|
|
37
|
+
error(`Error transforming: ${err}`);
|
|
38
|
+
error(err.stack);
|
|
39
|
+
process.exit(1);
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
export const upgradeCommand = addTransformOptions(
|
|
44
|
+
new Command()
|
|
45
|
+
.command("upgrade")
|
|
46
|
+
.description("Upgrade ai package dependencies and apply codemods"),
|
|
47
|
+
).action((options: TransformOptions) => {
|
|
48
|
+
try {
|
|
49
|
+
upgrade(options);
|
|
50
|
+
} catch (err: any) {
|
|
51
|
+
error(`Error upgrading: ${err}`);
|
|
52
|
+
error(err.stack);
|
|
53
|
+
process.exit(1);
|
|
54
|
+
}
|
|
55
|
+
});
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { Command } from "commander";
|
|
4
|
+
import { create } from "./commands/create";
|
|
5
|
+
import { add } from "./commands/add";
|
|
6
|
+
import { codemodCommand, upgradeCommand } from "./commands/upgrade";
|
|
7
|
+
import { init } from "./commands/init";
|
|
8
|
+
import { update } from "./commands/update";
|
|
9
|
+
|
|
10
|
+
process.on("SIGINT", () => process.exit(0));
|
|
11
|
+
process.on("SIGTERM", () => process.exit(0));
|
|
12
|
+
|
|
13
|
+
function main() {
|
|
14
|
+
const program = new Command()
|
|
15
|
+
.name("assistant-ui")
|
|
16
|
+
.description("add components and dependencies to your project");
|
|
17
|
+
|
|
18
|
+
program.addCommand(add);
|
|
19
|
+
program.addCommand(create);
|
|
20
|
+
program.addCommand(init);
|
|
21
|
+
program.addCommand(codemodCommand);
|
|
22
|
+
program.addCommand(upgradeCommand);
|
|
23
|
+
program.addCommand(update);
|
|
24
|
+
|
|
25
|
+
program.parse();
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
main();
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import * as fs from "fs";
|
|
2
|
+
import * as path from "path";
|
|
3
|
+
import { execSync } from "child_process";
|
|
4
|
+
import { sync as globSync } from "glob";
|
|
5
|
+
import * as readline from "readline";
|
|
6
|
+
import { detect } from "detect-package-manager";
|
|
7
|
+
|
|
8
|
+
function askQuestion(query: string): Promise<string> {
|
|
9
|
+
return new Promise((resolve) => {
|
|
10
|
+
const rl = readline.createInterface({
|
|
11
|
+
input: process.stdin,
|
|
12
|
+
output: process.stdout,
|
|
13
|
+
});
|
|
14
|
+
rl.question(query, (answer) => {
|
|
15
|
+
rl.close();
|
|
16
|
+
resolve(answer);
|
|
17
|
+
});
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function isPackageInstalled(pkg: string): boolean {
|
|
22
|
+
const cwd = process.cwd();
|
|
23
|
+
try {
|
|
24
|
+
const pkgJsonPath = path.join(cwd, "package.json");
|
|
25
|
+
if (fs.existsSync(pkgJsonPath)) {
|
|
26
|
+
const pkgJson = JSON.parse(fs.readFileSync(pkgJsonPath, "utf8"));
|
|
27
|
+
const deps = pkgJson.dependencies || {};
|
|
28
|
+
const devDeps = pkgJson.devDependencies || {};
|
|
29
|
+
if (deps[pkg] || devDeps[pkg]) {
|
|
30
|
+
return true;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
} catch (e) {
|
|
34
|
+
// Fall back to node_modules check below.
|
|
35
|
+
}
|
|
36
|
+
const modulePath = path.join(cwd, "node_modules", ...pkg.split("/"));
|
|
37
|
+
return fs.existsSync(modulePath);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export default async function installAiSdkLib(): Promise<void> {
|
|
41
|
+
const cwd = process.cwd();
|
|
42
|
+
const pattern = "**/*.{js,jsx,ts,tsx}";
|
|
43
|
+
const files = globSync(pattern, {
|
|
44
|
+
cwd,
|
|
45
|
+
ignore: ["**/node_modules/**", "**/dist/**", "**/build/**"],
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
let found = false;
|
|
49
|
+
for (const file of files) {
|
|
50
|
+
const fullPath = path.join(cwd, file);
|
|
51
|
+
const content = fs.readFileSync(fullPath, "utf8");
|
|
52
|
+
if (content.includes("@assistant-ui/react-ai-sdk")) {
|
|
53
|
+
found = true;
|
|
54
|
+
break;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (found) {
|
|
59
|
+
if (isPackageInstalled("@assistant-ui/react-ai-sdk")) {
|
|
60
|
+
console.log(
|
|
61
|
+
"@assistant-ui/react-ai-sdk is already installed. Skipping installation.",
|
|
62
|
+
);
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const answer = await askQuestion(
|
|
67
|
+
"AI SDK imports were added but @assistant-ui/react-ai-sdk is not installed. Do you want to install it? (Y/n) ",
|
|
68
|
+
);
|
|
69
|
+
if (answer === "" || answer.toLowerCase().startsWith("y")) {
|
|
70
|
+
const pm = await detect();
|
|
71
|
+
let cmd = "";
|
|
72
|
+
if (pm === "yarn") {
|
|
73
|
+
cmd = "yarn add @assistant-ui/react-ai-sdk";
|
|
74
|
+
} else if (pm === "pnpm") {
|
|
75
|
+
cmd = "pnpm add @assistant-ui/react-ai-sdk";
|
|
76
|
+
} else if (pm === "bun") {
|
|
77
|
+
cmd = "bun add @assistant-ui/react-ai-sdk";
|
|
78
|
+
} else {
|
|
79
|
+
cmd = "npm install @assistant-ui/react-ai-sdk";
|
|
80
|
+
}
|
|
81
|
+
try {
|
|
82
|
+
execSync(cmd, { stdio: "inherit" });
|
|
83
|
+
} catch (e) {
|
|
84
|
+
console.error("Installation failed:", e);
|
|
85
|
+
}
|
|
86
|
+
} else {
|
|
87
|
+
console.log("Skipping installation.");
|
|
88
|
+
}
|
|
89
|
+
} else {
|
|
90
|
+
console.log("No AI SDK imports found; skipping installation.");
|
|
91
|
+
}
|
|
92
|
+
}
|