assistant-ui 0.0.106 → 0.0.107
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/codemods/v0-12/assistant-api-to-aui.js.map +1 -1
- package/dist/codemods/v0-8/ui-package-split.js.map +1 -1
- package/dist/commands/add.js +1 -1
- package/dist/commands/add.js.map +1 -1
- package/dist/commands/create.d.ts.map +1 -1
- package/dist/commands/create.js +14 -4
- package/dist/commands/create.js.map +1 -1
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +11 -10
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/info.d.ts +1 -1
- package/dist/commands/info.d.ts.map +1 -1
- package/dist/commands/info.js +13 -14
- package/dist/commands/info.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/lib/create-project.d.ts +7 -2
- package/dist/lib/create-project.d.ts.map +1 -1
- package/dist/lib/create-project.js +13 -10
- package/dist/lib/create-project.js.map +1 -1
- package/dist/lib/run-spawn.d.ts.map +1 -1
- package/dist/lib/utils/logger.d.ts.map +1 -1
- package/dist/lib/utils/registry.js +2 -1
- package/dist/lib/utils/registry.js.map +1 -1
- package/dist/lib/utils/workspace.d.ts +6 -0
- package/dist/lib/utils/workspace.d.ts.map +1 -0
- package/dist/lib/utils/workspace.js +28 -0
- package/dist/lib/utils/workspace.js.map +1 -0
- package/package.json +4 -4
- package/plugin/skills/assistant-ui/SKILL.md +24 -5
- package/src/commands/add.ts +1 -1
- package/src/commands/create.ts +16 -4
- package/src/commands/doctor.ts +17 -13
- package/src/commands/info.ts +21 -20
- package/src/lib/create-project.ts +25 -14
- package/src/lib/utils/registry.test.ts +8 -2
- package/src/lib/utils/registry.ts +5 -1
- package/src/lib/utils/workspace.ts +34 -0
package/src/commands/doctor.ts
CHANGED
|
@@ -3,6 +3,7 @@ import * as fs from "node:fs";
|
|
|
3
3
|
import * as path from "node:path";
|
|
4
4
|
import chalk from "chalk";
|
|
5
5
|
import { compare, valid } from "semver";
|
|
6
|
+
import { findWorkspaceRoot, resolveRealPath } from "../lib/utils/workspace";
|
|
6
7
|
|
|
7
8
|
const ASSISTANT_UI_PACKAGE_NAMES = new Set([
|
|
8
9
|
"assistant-stream",
|
|
@@ -39,13 +40,7 @@ function processPackageDir(
|
|
|
39
40
|
results: DiscoveredPackage[],
|
|
40
41
|
visited: ProcessedDir,
|
|
41
42
|
): void {
|
|
42
|
-
const real = (
|
|
43
|
-
try {
|
|
44
|
-
return fs.realpathSync(pkgDir);
|
|
45
|
-
} catch {
|
|
46
|
-
return pkgDir;
|
|
47
|
-
}
|
|
48
|
-
})();
|
|
43
|
+
const real = resolveRealPath(pkgDir);
|
|
49
44
|
if (visited.set.has(real)) return;
|
|
50
45
|
visited.set.add(real);
|
|
51
46
|
|
|
@@ -183,14 +178,23 @@ function walkPnpmStore(
|
|
|
183
178
|
}
|
|
184
179
|
|
|
185
180
|
// Discover every installation of an assistant-ui-family package reachable
|
|
186
|
-
// from `cwd`.
|
|
187
|
-
//
|
|
188
|
-
//
|
|
181
|
+
// from `cwd`. Node resolves packages through ancestor node_modules directories,
|
|
182
|
+
// so inspect each level to include workspace-hoisted installs. Nested installs
|
|
183
|
+
// and pnpm virtual stores are scanned to catch duplicate transitive copies.
|
|
189
184
|
export function discoverInstalledPackages(cwd: string): DiscoveredPackage[] {
|
|
190
185
|
const results: DiscoveredPackage[] = [];
|
|
191
186
|
const visited: ProcessedDir = { set: new Set() };
|
|
192
|
-
|
|
193
|
-
|
|
187
|
+
let dir = resolveRealPath(cwd);
|
|
188
|
+
const scanRoot = findWorkspaceRoot(dir) ?? dir;
|
|
189
|
+
|
|
190
|
+
while (true) {
|
|
191
|
+
walkNodeModulesAt(dir, results, visited);
|
|
192
|
+
walkPnpmStore(dir, results, visited);
|
|
193
|
+
|
|
194
|
+
if (dir === scanRoot) break;
|
|
195
|
+
dir = path.dirname(dir);
|
|
196
|
+
}
|
|
197
|
+
|
|
194
198
|
return results;
|
|
195
199
|
}
|
|
196
200
|
|
|
@@ -369,7 +373,7 @@ export const doctor = new Command()
|
|
|
369
373
|
)
|
|
370
374
|
.option("--no-network", "Skip the npm registry check for latest versions.")
|
|
371
375
|
.action(async (opts: { cwd: string; network: boolean }) => {
|
|
372
|
-
const cwd =
|
|
376
|
+
const cwd = resolveRealPath(opts.cwd);
|
|
373
377
|
const packageJsonPath = path.join(cwd, "package.json");
|
|
374
378
|
|
|
375
379
|
if (!fs.existsSync(packageJsonPath)) {
|
package/src/commands/info.ts
CHANGED
|
@@ -6,6 +6,9 @@ import { spawnSync } from "node:child_process";
|
|
|
6
6
|
import chalk from "chalk";
|
|
7
7
|
import { detect } from "detect-package-manager";
|
|
8
8
|
import { satisfies } from "semver";
|
|
9
|
+
import { findWorkspaceRoot, resolveRealPath } from "../lib/utils/workspace";
|
|
10
|
+
|
|
11
|
+
export { findWorkspaceRoot };
|
|
9
12
|
|
|
10
13
|
const ASSISTANT_UI_PACKAGES = [
|
|
11
14
|
// Distribution
|
|
@@ -89,25 +92,6 @@ function getInstalledVersion(pkg: string, cwd: string): string | null {
|
|
|
89
92
|
return null;
|
|
90
93
|
}
|
|
91
94
|
|
|
92
|
-
export function findWorkspaceRoot(cwd: string): string | null {
|
|
93
|
-
let dir = cwd;
|
|
94
|
-
const root = path.parse(dir).root;
|
|
95
|
-
while (true) {
|
|
96
|
-
if (fs.existsSync(path.join(dir, "pnpm-workspace.yaml"))) return dir;
|
|
97
|
-
const pkgPath = path.join(dir, "package.json");
|
|
98
|
-
if (fs.existsSync(pkgPath)) {
|
|
99
|
-
try {
|
|
100
|
-
const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf8"));
|
|
101
|
-
if (pkg.workspaces) return dir;
|
|
102
|
-
} catch {
|
|
103
|
-
// ignore
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
if (dir === root) return null;
|
|
107
|
-
dir = path.dirname(dir);
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
|
|
111
95
|
function readProjectDeps(
|
|
112
96
|
projectPkg: Record<string, unknown>,
|
|
113
97
|
): Record<string, string> {
|
|
@@ -197,6 +181,19 @@ function getOsInfo(): string {
|
|
|
197
181
|
}
|
|
198
182
|
}
|
|
199
183
|
|
|
184
|
+
function getCliVersion(): string {
|
|
185
|
+
try {
|
|
186
|
+
const packageJson = JSON.parse(
|
|
187
|
+
fs.readFileSync(new URL("../../package.json", import.meta.url), "utf8"),
|
|
188
|
+
) as { version?: unknown };
|
|
189
|
+
return typeof packageJson.version === "string"
|
|
190
|
+
? packageJson.version
|
|
191
|
+
: "unknown";
|
|
192
|
+
} catch {
|
|
193
|
+
return "unknown";
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
200
197
|
async function getPackageManagerInfo(
|
|
201
198
|
cwd: string,
|
|
202
199
|
): Promise<{ name: string; version: string }> {
|
|
@@ -230,6 +227,7 @@ interface PackageInfo {
|
|
|
230
227
|
}
|
|
231
228
|
|
|
232
229
|
interface InfoData {
|
|
230
|
+
cliVersion: string;
|
|
233
231
|
os: string;
|
|
234
232
|
node: string;
|
|
235
233
|
pm: { name: string; version: string };
|
|
@@ -317,6 +315,7 @@ async function collectInfo(
|
|
|
317
315
|
const warnings = collectWarnings(packages, cwd, projectPkg);
|
|
318
316
|
|
|
319
317
|
return {
|
|
318
|
+
cliVersion: getCliVersion(),
|
|
320
319
|
os: getOsInfo(),
|
|
321
320
|
node: process.version,
|
|
322
321
|
pm,
|
|
@@ -344,6 +343,7 @@ function renderPlain(data: InfoData): string[] {
|
|
|
344
343
|
const lines: string[] = [];
|
|
345
344
|
|
|
346
345
|
lines.push("Environment:");
|
|
346
|
+
lines.push(` assistant-ui CLI: ${data.cliVersion}`);
|
|
347
347
|
lines.push(` OS: ${data.os}`);
|
|
348
348
|
lines.push(` Node.js: ${data.node}`);
|
|
349
349
|
lines.push(` Package Manager: ${data.pm.name} ${data.pm.version}`);
|
|
@@ -370,6 +370,7 @@ function renderColored(data: InfoData): string[] {
|
|
|
370
370
|
const lines: string[] = [];
|
|
371
371
|
|
|
372
372
|
lines.push(chalk.bold("Environment:"));
|
|
373
|
+
lines.push(` assistant-ui CLI: ${data.cliVersion}`);
|
|
373
374
|
lines.push(` OS: ${data.os}`);
|
|
374
375
|
lines.push(` Node.js: ${data.node}`);
|
|
375
376
|
lines.push(` Package Manager: ${data.pm.name} ${data.pm.version}`);
|
|
@@ -415,7 +416,7 @@ export const info = new Command()
|
|
|
415
416
|
process.cwd(),
|
|
416
417
|
)
|
|
417
418
|
.action(async (opts) => {
|
|
418
|
-
const cwd =
|
|
419
|
+
const cwd = resolveRealPath(opts.cwd);
|
|
419
420
|
const packageJsonPath = path.join(cwd, "package.json");
|
|
420
421
|
|
|
421
422
|
if (!fs.existsSync(packageJsonPath)) {
|
|
@@ -210,22 +210,25 @@ export async function resolvePackageManagerForCwd(
|
|
|
210
210
|
}
|
|
211
211
|
}
|
|
212
212
|
|
|
213
|
+
export interface TransformResult {
|
|
214
|
+
registryInstallFailure?: { retryCommand: string };
|
|
215
|
+
}
|
|
216
|
+
|
|
213
217
|
export async function transformProject(
|
|
214
218
|
projectDir: string,
|
|
215
219
|
opts: TransformOptions,
|
|
216
|
-
): Promise<
|
|
220
|
+
): Promise<TransformResult> {
|
|
217
221
|
logger.step("Transforming package.json...");
|
|
218
222
|
transformPackageJson(projectDir);
|
|
219
223
|
|
|
224
|
+
logger.step("Transforming project files...");
|
|
225
|
+
transformTsConfig(projectDir);
|
|
226
|
+
transformCssFiles(projectDir);
|
|
227
|
+
|
|
220
228
|
let assistantUI: string[] | undefined;
|
|
221
229
|
let shadcnUI: string[] | undefined;
|
|
222
230
|
|
|
223
231
|
if (!opts.hasLocalComponents) {
|
|
224
|
-
logger.step("Transforming project files...");
|
|
225
|
-
|
|
226
|
-
transformTsConfig(projectDir);
|
|
227
|
-
transformCssFiles(projectDir);
|
|
228
|
-
|
|
229
232
|
const components = scanRequiredComponents(projectDir);
|
|
230
233
|
assistantUI = components.assistantUI;
|
|
231
234
|
shadcnUI = components.shadcnUI;
|
|
@@ -249,8 +252,15 @@ export async function transformProject(
|
|
|
249
252
|
const auiComponents = assistantUI.map((c) => `@assistant-ui/${c}`);
|
|
250
253
|
const components = [...allShadcn, ...auiComponents];
|
|
251
254
|
logger.step(`Installing components: ${components.join(", ")}...`);
|
|
252
|
-
await installShadcnRegistry(
|
|
255
|
+
const failure = await installShadcnRegistry(
|
|
256
|
+
projectDir,
|
|
257
|
+
components,
|
|
258
|
+
"components",
|
|
259
|
+
pm,
|
|
260
|
+
);
|
|
261
|
+
if (failure) return { registryInstallFailure: failure };
|
|
253
262
|
}
|
|
263
|
+
return {};
|
|
254
264
|
}
|
|
255
265
|
|
|
256
266
|
function transformPackageJson(projectDir: string): void {
|
|
@@ -326,7 +336,8 @@ function transformTsConfig(projectDir: string): void {
|
|
|
326
336
|
Array.isArray(targets) &&
|
|
327
337
|
targets.some(
|
|
328
338
|
(target) =>
|
|
329
|
-
typeof target === "string" &&
|
|
339
|
+
typeof target === "string" &&
|
|
340
|
+
(target.includes("packages/ui/") || target.startsWith("../")),
|
|
330
341
|
);
|
|
331
342
|
if (workspaceKeys.has(key) || targetsWorkspace) {
|
|
332
343
|
delete tsconfig.compilerOptions.paths[key];
|
|
@@ -461,20 +472,20 @@ async function installShadcnRegistry(
|
|
|
461
472
|
components: string[],
|
|
462
473
|
label: string,
|
|
463
474
|
pm: PackageManagerName,
|
|
464
|
-
): Promise<
|
|
475
|
+
): Promise<{ retryCommand: string } | undefined> {
|
|
465
476
|
const [cmd, dlxArgs] = dlxCommand(pm);
|
|
466
477
|
// For npm, dlxArgs may already include `--yes` for npx auto-install.
|
|
467
478
|
// The trailing `--yes` is for shadcn's own confirmation prompt.
|
|
468
|
-
const
|
|
479
|
+
const retryArgs = [...dlxArgs, "shadcn@latest", "add", ...components];
|
|
480
|
+
const addArgs = [...retryArgs, "--yes"];
|
|
469
481
|
|
|
470
482
|
try {
|
|
471
483
|
await runSpawn(cmd, addArgs, projectDir);
|
|
484
|
+
return undefined;
|
|
472
485
|
} catch (error) {
|
|
473
486
|
if (error instanceof SpawnExitError) {
|
|
474
|
-
logger.warn(
|
|
475
|
-
|
|
476
|
-
);
|
|
477
|
-
return;
|
|
487
|
+
logger.warn(`shadcn exited with code ${error.code}.`);
|
|
488
|
+
return { retryCommand: `${cmd} ${retryArgs.join(" ")}` };
|
|
478
489
|
}
|
|
479
490
|
|
|
480
491
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -94,9 +94,15 @@ describe("resolveRegistryItemUrl", () => {
|
|
|
94
94
|
);
|
|
95
95
|
});
|
|
96
96
|
|
|
97
|
-
it("uses the
|
|
97
|
+
it("uses the base URL without a style", () => {
|
|
98
98
|
expect(resolveRegistryItemUrl("thread")).toBe(
|
|
99
|
-
"https://r.assistant-ui.com/thread.json",
|
|
99
|
+
"https://r.assistant-ui.com/base/thread.json",
|
|
100
|
+
);
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
it("uses the base URL for an explicit undefined style", () => {
|
|
104
|
+
expect(resolveRegistryItemUrl("thread", undefined)).toBe(
|
|
105
|
+
"https://r.assistant-ui.com/base/thread.json",
|
|
100
106
|
);
|
|
101
107
|
});
|
|
102
108
|
|
|
@@ -31,7 +31,11 @@ export function resolveRegistryItemUrl(
|
|
|
31
31
|
component: string,
|
|
32
32
|
style?: string,
|
|
33
33
|
): string {
|
|
34
|
-
|
|
34
|
+
if (style === undefined) {
|
|
35
|
+
return `${REGISTRY_BASE_URL}/base/${encodeURIComponent(component)}.json`;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const registryUrl = style.startsWith("base-")
|
|
35
39
|
? `${REGISTRY_BASE_URL}/styles/${encodeURIComponent(style)}`
|
|
36
40
|
: REGISTRY_BASE_URL;
|
|
37
41
|
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import * as fs from "node:fs";
|
|
2
|
+
import * as path from "node:path";
|
|
3
|
+
|
|
4
|
+
export function resolveRealPath(inputPath: string): string {
|
|
5
|
+
const resolved = path.resolve(inputPath);
|
|
6
|
+
|
|
7
|
+
try {
|
|
8
|
+
return fs.realpathSync(resolved);
|
|
9
|
+
} catch {
|
|
10
|
+
return resolved;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function findWorkspaceRoot(cwd: string): string | null {
|
|
15
|
+
let dir = path.resolve(cwd);
|
|
16
|
+
const root = path.parse(dir).root;
|
|
17
|
+
|
|
18
|
+
while (true) {
|
|
19
|
+
if (fs.existsSync(path.join(dir, "pnpm-workspace.yaml"))) return dir;
|
|
20
|
+
|
|
21
|
+
const pkgPath = path.join(dir, "package.json");
|
|
22
|
+
if (fs.existsSync(pkgPath)) {
|
|
23
|
+
try {
|
|
24
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf8"));
|
|
25
|
+
if (pkg.workspaces) return dir;
|
|
26
|
+
} catch {
|
|
27
|
+
// Malformed package manifests are not workspace markers.
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (dir === root) return null;
|
|
32
|
+
dir = path.dirname(dir);
|
|
33
|
+
}
|
|
34
|
+
}
|