assistant-ui 0.0.105 → 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/README.md +2 -2
- package/dist/codemods/utils/createTransformer.d.ts +0 -1
- package/dist/codemods/utils/createTransformer.d.ts.map +1 -1
- package/dist/codemods/v0-11/content-part-to-message-part.d.ts.map +1 -1
- package/dist/codemods/v0-12/assistant-api-to-aui.d.ts.map +1 -1
- package/dist/codemods/v0-12/assistant-api-to-aui.js.map +1 -1
- package/dist/codemods/v0-12/event-names-to-camelcase.d.ts.map +1 -1
- package/dist/codemods/v0-12/primitive-if-to-aui-if.d.ts.map +1 -1
- package/dist/codemods/v0-8/ui-package-split.d.ts.map +1 -1
- package/dist/codemods/v0-8/ui-package-split.js.map +1 -1
- package/dist/codemods/v0-9/edge-package-split.d.ts.map +1 -1
- package/dist/commands/add.d.ts +1 -1
- package/dist/commands/add.d.ts.map +1 -1
- package/dist/commands/add.js +8 -5
- package/dist/commands/add.js.map +1 -1
- package/dist/commands/agent.d.ts +0 -1
- package/dist/commands/agent.d.ts.map +1 -1
- package/dist/commands/create.d.ts +0 -1
- package/dist/commands/create.d.ts.map +1 -1
- package/dist/commands/create.js +26 -8
- package/dist/commands/create.js.map +1 -1
- package/dist/commands/doctor.d.ts +0 -1
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +66 -29
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/info.d.ts +3 -2
- package/dist/commands/info.d.ts.map +1 -1
- package/dist/commands/info.js +22 -26
- package/dist/commands/info.js.map +1 -1
- package/dist/commands/init.d.ts +1 -3
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +14 -24
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/mcp.d.ts +0 -1
- package/dist/commands/mcp.d.ts.map +1 -1
- package/dist/commands/mcp.js +14 -4
- package/dist/commands/mcp.js.map +1 -1
- package/dist/commands/update.d.ts +0 -1
- package/dist/commands/update.d.ts.map +1 -1
- package/dist/commands/update.js +14 -1
- package/dist/commands/update.js.map +1 -1
- package/dist/commands/upgrade.d.ts +0 -1
- package/dist/commands/upgrade.d.ts.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/lib/agent-skill.d.ts +0 -1
- package/dist/lib/agent-skill.d.ts.map +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 +34 -17
- package/dist/lib/create-project.js.map +1 -1
- package/dist/lib/install-ai-sdk-lib.d.ts.map +1 -1
- package/dist/lib/install-edge-lib.d.ts.map +1 -1
- package/dist/lib/install-ui-lib.d.ts.map +1 -1
- package/dist/lib/run-spawn.d.ts.map +1 -1
- package/dist/lib/transform-options.d.ts.map +1 -1
- package/dist/lib/transform.d.ts +0 -1
- package/dist/lib/transform.d.ts.map +1 -1
- package/dist/lib/upgrade.d.ts +0 -1
- package/dist/lib/upgrade.d.ts.map +1 -1
- package/dist/lib/utils/config.d.ts.map +1 -1
- package/dist/lib/utils/file-scanner.d.ts.map +1 -1
- package/dist/lib/utils/logger.d.ts.map +1 -1
- package/dist/lib/utils/package-installer.d.ts.map +1 -1
- package/dist/lib/utils/package-manager.d.ts.map +1 -1
- package/dist/lib/utils/registry.d.ts +7 -0
- package/dist/lib/utils/registry.d.ts.map +1 -0
- package/dist/lib/utils/registry.js +25 -0
- package/dist/lib/utils/registry.js.map +1 -0
- 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/dist/program.d.ts +0 -1
- package/dist/program.d.ts.map +1 -1
- package/package.json +12 -9
- package/plugin/skills/assistant-ui/SKILL.md +24 -5
- package/src/commands/add.ts +9 -4
- package/src/commands/create.ts +28 -8
- package/src/commands/doctor.ts +97 -44
- package/src/commands/info.ts +49 -42
- package/src/commands/init.ts +16 -24
- package/src/commands/mcp.ts +20 -5
- package/src/commands/update.ts +17 -1
- package/src/lib/create-project.ts +64 -20
- package/src/lib/utils/registry.test.ts +114 -0
- package/src/lib/utils/registry.ts +43 -0
- package/src/lib/utils/workspace.ts +34 -0
package/dist/commands/doctor.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
import { findWorkspaceRoot, resolveRealPath } from "../lib/utils/workspace.js";
|
|
1
2
|
import { Command } from "commander";
|
|
2
3
|
import chalk from "chalk";
|
|
3
4
|
import * as fs$1 from "node:fs";
|
|
4
5
|
import * as path$1 from "node:path";
|
|
6
|
+
import { compare, valid } from "semver";
|
|
5
7
|
//#region src/commands/doctor.ts
|
|
6
8
|
const ASSISTANT_UI_PACKAGE_NAMES = /* @__PURE__ */ new Set([
|
|
7
9
|
"assistant-stream",
|
|
@@ -21,13 +23,7 @@ function readJson(file) {
|
|
|
21
23
|
}
|
|
22
24
|
}
|
|
23
25
|
function processPackageDir(pkgDir, results, visited) {
|
|
24
|
-
const real = (
|
|
25
|
-
try {
|
|
26
|
-
return fs$1.realpathSync(pkgDir);
|
|
27
|
-
} catch {
|
|
28
|
-
return pkgDir;
|
|
29
|
-
}
|
|
30
|
-
})();
|
|
26
|
+
const real = resolveRealPath(pkgDir);
|
|
31
27
|
if (visited.set.has(real)) return;
|
|
32
28
|
visited.set.add(real);
|
|
33
29
|
const pkgJson = readJson(path$1.join(pkgDir, "package.json"));
|
|
@@ -73,9 +69,66 @@ function walkNodeModulesAt(baseDir, results, visited) {
|
|
|
73
69
|
} else processPackageDir(path$1.join(nm, entry.name), results, visited);
|
|
74
70
|
}
|
|
75
71
|
}
|
|
72
|
+
const TRACKED_PNPM_ENTRY_PREFIXES = [
|
|
73
|
+
"@assistant-ui+",
|
|
74
|
+
"assistant-ui@",
|
|
75
|
+
"assistant-stream@",
|
|
76
|
+
"assistant-cloud@"
|
|
77
|
+
];
|
|
78
|
+
function isTrackedPnpmEntry(dirName) {
|
|
79
|
+
return TRACKED_PNPM_ENTRY_PREFIXES.some((p) => dirName.startsWith(p));
|
|
80
|
+
}
|
|
81
|
+
function processTrackedPackagesIn(nm, results, visited) {
|
|
82
|
+
let entries;
|
|
83
|
+
try {
|
|
84
|
+
entries = fs$1.readdirSync(nm, { withFileTypes: true });
|
|
85
|
+
} catch {
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
for (const entry of entries) {
|
|
89
|
+
if (entry.name.startsWith(".")) continue;
|
|
90
|
+
if (!entry.isDirectory() && !entry.isSymbolicLink()) continue;
|
|
91
|
+
if (entry.name.startsWith("@")) {
|
|
92
|
+
const scopeDir = path$1.join(nm, entry.name);
|
|
93
|
+
let scoped;
|
|
94
|
+
try {
|
|
95
|
+
scoped = fs$1.readdirSync(scopeDir, { withFileTypes: true });
|
|
96
|
+
} catch {
|
|
97
|
+
continue;
|
|
98
|
+
}
|
|
99
|
+
for (const s of scoped) {
|
|
100
|
+
if (!s.isDirectory() && !s.isSymbolicLink()) continue;
|
|
101
|
+
if (!isTrackedPackage(`${entry.name}/${s.name}`)) continue;
|
|
102
|
+
processPackageDir(path$1.join(scopeDir, s.name), results, visited);
|
|
103
|
+
}
|
|
104
|
+
} else if (isTrackedPackage(entry.name)) processPackageDir(path$1.join(nm, entry.name), results, visited);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
function walkPnpmStore(cwd, results, visited) {
|
|
108
|
+
const storeDir = path$1.join(cwd, "node_modules", ".pnpm");
|
|
109
|
+
let entries;
|
|
110
|
+
try {
|
|
111
|
+
entries = fs$1.readdirSync(storeDir, { withFileTypes: true });
|
|
112
|
+
} catch {
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
for (const entry of entries) {
|
|
116
|
+
if (!entry.isDirectory() && !entry.isSymbolicLink()) continue;
|
|
117
|
+
if (!isTrackedPnpmEntry(entry.name)) continue;
|
|
118
|
+
processTrackedPackagesIn(path$1.join(storeDir, entry.name, "node_modules"), results, visited);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
76
121
|
function discoverInstalledPackages(cwd) {
|
|
77
122
|
const results = [];
|
|
78
|
-
|
|
123
|
+
const visited = { set: /* @__PURE__ */ new Set() };
|
|
124
|
+
let dir = resolveRealPath(cwd);
|
|
125
|
+
const scanRoot = findWorkspaceRoot(dir) ?? dir;
|
|
126
|
+
while (true) {
|
|
127
|
+
walkNodeModulesAt(dir, results, visited);
|
|
128
|
+
walkPnpmStore(dir, results, visited);
|
|
129
|
+
if (dir === scanRoot) break;
|
|
130
|
+
dir = path$1.dirname(dir);
|
|
131
|
+
}
|
|
79
132
|
return results;
|
|
80
133
|
}
|
|
81
134
|
function findDuplicates(packages) {
|
|
@@ -111,27 +164,11 @@ async function fetchAllLatestVersions(names) {
|
|
|
111
164
|
const entries = await Promise.all(names.map(async (n) => [n, await fetchLatestVersion(n)]));
|
|
112
165
|
return new Map(entries);
|
|
113
166
|
}
|
|
114
|
-
function parseSemver(v) {
|
|
115
|
-
const m = /^(\d+)\.(\d+)\.(\d+)(?:-([^+\s]+))?/.exec(v);
|
|
116
|
-
if (!m) return null;
|
|
117
|
-
return {
|
|
118
|
-
major: parseInt(m[1], 10),
|
|
119
|
-
minor: parseInt(m[2], 10),
|
|
120
|
-
patch: parseInt(m[3], 10),
|
|
121
|
-
prerelease: m[4] ?? ""
|
|
122
|
-
};
|
|
123
|
-
}
|
|
124
167
|
function compareSemver(a, b) {
|
|
125
|
-
const
|
|
126
|
-
const
|
|
127
|
-
if (!
|
|
128
|
-
|
|
129
|
-
if (pa.minor !== pb.minor) return pa.minor - pb.minor;
|
|
130
|
-
if (pa.patch !== pb.patch) return pa.patch - pb.patch;
|
|
131
|
-
if (pa.prerelease === pb.prerelease) return 0;
|
|
132
|
-
if (!pa.prerelease) return 1;
|
|
133
|
-
if (!pb.prerelease) return -1;
|
|
134
|
-
return pa.prerelease.localeCompare(pb.prerelease);
|
|
168
|
+
const validA = valid(a);
|
|
169
|
+
const validB = valid(b);
|
|
170
|
+
if (!validA || !validB) return a.localeCompare(b);
|
|
171
|
+
return compare(validA, validB);
|
|
135
172
|
}
|
|
136
173
|
function findOutdated(packages, latest) {
|
|
137
174
|
const newestByName = /* @__PURE__ */ new Map();
|
|
@@ -185,7 +222,7 @@ function reportOutdated(outdated, lines) {
|
|
|
185
222
|
lines.push(chalk.cyan(" npx assistant-ui update"));
|
|
186
223
|
}
|
|
187
224
|
const doctor = new Command().name("doctor").description("Diagnose mismatched or outdated assistant-ui packages (including transitive ones).").option("-c, --cwd <cwd>", "the working directory. defaults to the current directory.", process.cwd()).option("--no-network", "Skip the npm registry check for latest versions.").action(async (opts) => {
|
|
188
|
-
const cwd =
|
|
225
|
+
const cwd = resolveRealPath(opts.cwd);
|
|
189
226
|
const packageJsonPath = path$1.join(cwd, "package.json");
|
|
190
227
|
if (!fs$1.existsSync(packageJsonPath)) {
|
|
191
228
|
console.error(chalk.red("No package.json found in the current directory."));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"doctor.js","names":["fs","path"],"sources":["../../src/commands/doctor.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport chalk from \"chalk\";\n\nconst ASSISTANT_UI_PACKAGE_NAMES = new Set([\n \"assistant-stream\",\n \"assistant-cloud\",\n \"assistant-ui\",\n]);\n\nfunction isTrackedPackage(name: string | undefined): boolean {\n if (!name) return false;\n if (name.startsWith(\"@assistant-ui/\")) return true;\n return ASSISTANT_UI_PACKAGE_NAMES.has(name);\n}\n\nexport interface DiscoveredPackage {\n name: string;\n version: string;\n installPath: string;\n}\n\ninterface ProcessedDir {\n set: Set<string>;\n}\n\nfunction readJson(file: string): Record<string, unknown> | null {\n try {\n return JSON.parse(fs.readFileSync(file, \"utf8\"));\n } catch {\n return null;\n }\n}\n\nfunction processPackageDir(\n pkgDir: string,\n results: DiscoveredPackage[],\n visited: ProcessedDir,\n): void {\n const real = (() => {\n try {\n return fs.realpathSync(pkgDir);\n } catch {\n return pkgDir;\n }\n })();\n if (visited.set.has(real)) return;\n visited.set.add(real);\n\n const pkgJson = readJson(path.join(pkgDir, \"package.json\"));\n let isTracked = false;\n if (pkgJson) {\n const name = pkgJson.name as string | undefined;\n const version = pkgJson.version as string | undefined;\n if (name && version && isTrackedPackage(name)) {\n results.push({ name, version, installPath: pkgDir });\n isTracked = true;\n }\n }\n\n // Only descend into nested node_modules of tracked packages. Transitive\n // copies of @assistant-ui/* live inside packages that depend on them,\n // which are themselves tracked. Walking every unrelated package's\n // subtree turns a doctor run on a large repo into thousands of stat\n // calls for no gain.\n if (isTracked) {\n walkNodeModulesAt(pkgDir, results, visited);\n }\n}\n\nfunction walkNodeModulesAt(\n baseDir: string,\n results: DiscoveredPackage[],\n visited: ProcessedDir,\n): void {\n const nm = path.join(baseDir, \"node_modules\");\n if (!fs.existsSync(nm)) return;\n\n let entries: fs.Dirent[];\n try {\n entries = fs.readdirSync(nm, { withFileTypes: true });\n } catch {\n return;\n }\n\n for (const entry of entries) {\n if (entry.name.startsWith(\".\")) continue;\n if (!entry.isDirectory() && !entry.isSymbolicLink()) continue;\n\n if (entry.name.startsWith(\"@\")) {\n const scopeDir = path.join(nm, entry.name);\n let scoped: fs.Dirent[];\n try {\n scoped = fs.readdirSync(scopeDir, { withFileTypes: true });\n } catch {\n continue;\n }\n for (const s of scoped) {\n if (!s.isDirectory() && !s.isSymbolicLink()) continue;\n processPackageDir(path.join(scopeDir, s.name), results, visited);\n }\n } else {\n processPackageDir(path.join(nm, entry.name), results, visited);\n }\n }\n}\n\n// Discover every installation of an assistant-ui-family package reachable\n// from `cwd`. Recurses into nested node_modules so transitive copies\n// (the real source of duplicate-version bugs) are not missed.\nexport function discoverInstalledPackages(cwd: string): DiscoveredPackage[] {\n const results: DiscoveredPackage[] = [];\n const visited: ProcessedDir = { set: new Set() };\n walkNodeModulesAt(cwd, results, visited);\n return results;\n}\n\nexport interface DuplicateGroup {\n name: string;\n installations: DiscoveredPackage[];\n}\n\nexport function findDuplicates(\n packages: DiscoveredPackage[],\n): DuplicateGroup[] {\n const byName = new Map<string, DiscoveredPackage[]>();\n for (const pkg of packages) {\n const list = byName.get(pkg.name) ?? [];\n list.push(pkg);\n byName.set(pkg.name, list);\n }\n\n const duplicates: DuplicateGroup[] = [];\n for (const [name, installations] of byName) {\n const versions = new Set(installations.map((i) => i.version));\n if (versions.size > 1) {\n duplicates.push({ name, installations });\n }\n }\n duplicates.sort((a, b) => a.name.localeCompare(b.name));\n return duplicates;\n}\n\nexport function uniquePackageNames(packages: DiscoveredPackage[]): string[] {\n return Array.from(new Set(packages.map((p) => p.name))).sort();\n}\n\n// Package names use a restricted character set (`[a-z0-9._~-]` plus a\n// leading `@scope/` for scoped packages — see the npm package-name spec)\n// and the npm registry expects the scope's `@` and `/` un-encoded. So a\n// simple validation + concatenation is both correct and avoids the\n// CodeQL \"incomplete string escaping\" foot-gun of `encodeURIComponent`\n// + targeted un-escape.\nconst VALID_NPM_NAME = /^(@[a-z0-9._~-]+\\/)?[a-z0-9._~-]+$/;\n\nasync function fetchLatestVersion(name: string): Promise<string | null> {\n if (!VALID_NPM_NAME.test(name)) return null;\n try {\n const res = await fetch(`https://registry.npmjs.org/${name}/latest`, {\n headers: { Accept: \"application/json\" },\n });\n if (!res.ok) return null;\n const data = (await res.json()) as { version?: string };\n return data.version ?? null;\n } catch {\n return null;\n }\n}\n\nasync function fetchAllLatestVersions(\n names: string[],\n): Promise<Map<string, string | null>> {\n const entries = await Promise.all(\n names.map(async (n) => [n, await fetchLatestVersion(n)] as const),\n );\n return new Map(entries);\n}\n\ninterface SemverParts {\n major: number;\n minor: number;\n patch: number;\n prerelease: string;\n}\n\nfunction parseSemver(v: string): SemverParts | null {\n const m = /^(\\d+)\\.(\\d+)\\.(\\d+)(?:-([^+\\s]+))?/.exec(v);\n if (!m) return null;\n return {\n major: parseInt(m[1]!, 10),\n minor: parseInt(m[2]!, 10),\n patch: parseInt(m[3]!, 10),\n prerelease: m[4] ?? \"\",\n };\n}\n\nexport function compareSemver(a: string, b: string): number {\n const pa = parseSemver(a);\n const pb = parseSemver(b);\n if (!pa || !pb) return a.localeCompare(b);\n if (pa.major !== pb.major) return pa.major - pb.major;\n if (pa.minor !== pb.minor) return pa.minor - pb.minor;\n if (pa.patch !== pb.patch) return pa.patch - pb.patch;\n\n // Per SemVer §11: a version with a prerelease tag is *less than* the\n // same x.y.z without one. We compare tags lexically for a stable\n // ordering across prereleases — good enough for doctor's \"is X older\n // than the npm latest\" check.\n if (pa.prerelease === pb.prerelease) return 0;\n if (!pa.prerelease) return 1;\n if (!pb.prerelease) return -1;\n return pa.prerelease.localeCompare(pb.prerelease);\n}\n\nexport interface OutdatedPackage {\n name: string;\n current: string;\n latest: string;\n}\n\nexport function findOutdated(\n packages: DiscoveredPackage[],\n latest: Map<string, string | null>,\n): OutdatedPackage[] {\n const newestByName = new Map<string, string>();\n for (const pkg of packages) {\n const existing = newestByName.get(pkg.name);\n if (!existing || compareSemver(pkg.version, existing) > 0) {\n newestByName.set(pkg.name, pkg.version);\n }\n }\n\n const result: OutdatedPackage[] = [];\n for (const [name, current] of newestByName) {\n const latestVersion = latest.get(name);\n if (!latestVersion) continue;\n if (compareSemver(current, latestVersion) < 0) {\n result.push({ name, current, latest: latestVersion });\n }\n }\n result.sort((a, b) => a.name.localeCompare(b.name));\n return result;\n}\n\nfunction relativeInstallPath(installPath: string, cwd: string): string {\n const rel = path.relative(cwd, installPath);\n return rel.startsWith(\"..\") ? installPath : rel;\n}\n\nfunction reportDuplicates(\n duplicates: DuplicateGroup[],\n cwd: string,\n lines: string[],\n): void {\n if (duplicates.length === 0) {\n lines.push(chalk.green(\"✓ No duplicate versions detected.\"));\n return;\n }\n\n lines.push(chalk.red.bold(\"✗ Duplicate versions detected:\"));\n for (const dup of duplicates) {\n const versions = Array.from(\n new Set(dup.installations.map((i) => i.version)),\n )\n .sort(compareSemver)\n .join(\", \");\n lines.push(chalk.red(` ${dup.name} → ${versions}`));\n for (const inst of dup.installations) {\n lines.push(\n chalk.dim(\n ` ${inst.version} ${relativeInstallPath(inst.installPath, cwd)}`,\n ),\n );\n }\n }\n lines.push(\"\");\n lines.push(\n chalk.yellow(\n \"Duplicates almost always cause subtle runtime bugs (see https://github.com/assistant-ui/assistant-ui/issues/4101).\",\n ),\n );\n lines.push(\n chalk.yellow(\n \"Fix by aligning all @assistant-ui/* packages to compatible versions — run:\",\n ),\n );\n lines.push(chalk.cyan(\" npx assistant-ui update\"));\n}\n\nfunction reportOutdated(outdated: OutdatedPackage[], lines: string[]): void {\n if (outdated.length === 0) {\n lines.push(chalk.green(\"✓ All assistant-ui packages are up to date.\"));\n return;\n }\n\n lines.push(chalk.yellow.bold(\"! Outdated packages:\"));\n const maxLen = Math.max(...outdated.map((o) => o.name.length));\n for (const o of outdated) {\n lines.push(\n chalk.yellow(\n ` ${o.name.padEnd(maxLen)} ${o.current} → ${o.latest} (latest)`,\n ),\n );\n }\n lines.push(\"\");\n lines.push(chalk.yellow(\"Run the following to upgrade everything:\"));\n lines.push(chalk.cyan(\" npx assistant-ui update\"));\n}\n\nexport const doctor = new Command()\n .name(\"doctor\")\n .description(\n \"Diagnose mismatched or outdated assistant-ui packages (including transitive ones).\",\n )\n .option(\n \"-c, --cwd <cwd>\",\n \"the working directory. defaults to the current directory.\",\n process.cwd(),\n )\n .option(\"--no-network\", \"Skip the npm registry check for latest versions.\")\n .action(async (opts: { cwd: string; network: boolean }) => {\n const cwd = path.resolve(opts.cwd);\n const packageJsonPath = path.join(cwd, \"package.json\");\n\n if (!fs.existsSync(packageJsonPath)) {\n console.error(\n chalk.red(\"No package.json found in the current directory.\"),\n );\n process.exit(1);\n }\n\n console.log(\"\");\n console.log(chalk.bold(\"Running assistant-ui doctor...\"));\n console.log(\"\");\n\n const installed = discoverInstalledPackages(cwd);\n\n if (installed.length === 0) {\n console.log(\n chalk.yellow(\n \"No assistant-ui packages found in node_modules. Did you run `npm install`?\",\n ),\n );\n console.log(\"\");\n return;\n }\n\n const duplicates = findDuplicates(installed);\n\n let latest = new Map<string, string | null>();\n if (opts.network) {\n latest = await fetchAllLatestVersions(uniquePackageNames(installed));\n }\n const outdated = findOutdated(installed, latest);\n\n const lines: string[] = [];\n reportDuplicates(duplicates, cwd, lines);\n lines.push(\"\");\n if (opts.network) {\n reportOutdated(outdated, lines);\n } else {\n lines.push(chalk.dim(\"Skipped npm registry check (--no-network).\"));\n }\n\n for (const line of lines) console.log(line);\n console.log(\"\");\n\n if (duplicates.length > 0) {\n process.exitCode = 1;\n }\n });\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"doctor.js","names":["fs","path"],"sources":["../../src/commands/doctor.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport chalk from \"chalk\";\nimport { compare, valid } from \"semver\";\nimport { findWorkspaceRoot, resolveRealPath } from \"../lib/utils/workspace\";\n\nconst ASSISTANT_UI_PACKAGE_NAMES = new Set([\n \"assistant-stream\",\n \"assistant-cloud\",\n \"assistant-ui\",\n]);\n\nfunction isTrackedPackage(name: string | undefined): boolean {\n if (!name) return false;\n if (name.startsWith(\"@assistant-ui/\")) return true;\n return ASSISTANT_UI_PACKAGE_NAMES.has(name);\n}\n\nexport interface DiscoveredPackage {\n name: string;\n version: string;\n installPath: string;\n}\n\ninterface ProcessedDir {\n set: Set<string>;\n}\n\nfunction readJson(file: string): Record<string, unknown> | null {\n try {\n return JSON.parse(fs.readFileSync(file, \"utf8\"));\n } catch {\n return null;\n }\n}\n\nfunction processPackageDir(\n pkgDir: string,\n results: DiscoveredPackage[],\n visited: ProcessedDir,\n): void {\n const real = resolveRealPath(pkgDir);\n if (visited.set.has(real)) return;\n visited.set.add(real);\n\n const pkgJson = readJson(path.join(pkgDir, \"package.json\"));\n let isTracked = false;\n if (pkgJson) {\n const name = pkgJson.name as string | undefined;\n const version = pkgJson.version as string | undefined;\n if (name && version && isTrackedPackage(name)) {\n results.push({ name, version, installPath: pkgDir });\n isTracked = true;\n }\n }\n\n // Only descend into nested node_modules of tracked packages. Transitive\n // copies of @assistant-ui/* live inside packages that depend on them,\n // which are themselves tracked. Walking every unrelated package's\n // subtree turns a doctor run on a large repo into thousands of stat\n // calls for no gain.\n if (isTracked) {\n walkNodeModulesAt(pkgDir, results, visited);\n }\n}\n\nfunction walkNodeModulesAt(\n baseDir: string,\n results: DiscoveredPackage[],\n visited: ProcessedDir,\n): void {\n const nm = path.join(baseDir, \"node_modules\");\n if (!fs.existsSync(nm)) return;\n\n let entries: fs.Dirent[];\n try {\n entries = fs.readdirSync(nm, { withFileTypes: true });\n } catch {\n return;\n }\n\n for (const entry of entries) {\n if (entry.name.startsWith(\".\")) continue;\n if (!entry.isDirectory() && !entry.isSymbolicLink()) continue;\n\n if (entry.name.startsWith(\"@\")) {\n const scopeDir = path.join(nm, entry.name);\n let scoped: fs.Dirent[];\n try {\n scoped = fs.readdirSync(scopeDir, { withFileTypes: true });\n } catch {\n continue;\n }\n for (const s of scoped) {\n if (!s.isDirectory() && !s.isSymbolicLink()) continue;\n processPackageDir(path.join(scopeDir, s.name), results, visited);\n }\n } else {\n processPackageDir(path.join(nm, entry.name), results, visited);\n }\n }\n}\n\n// pnpm keeps every real package dir in the `.pnpm` virtual store as\n// `node_modules/.pnpm/<pkg>@<ver>[_<peerhash>]/node_modules/<pkg>` and never\n// nests a package's deps inside its own dir, so the hoisted-layout walk above\n// only ever reaches the project's direct deps. The store dir name encodes the\n// package, so filtering by a tracked prefix keeps this pass O(tracked entries).\nconst TRACKED_PNPM_ENTRY_PREFIXES = [\n \"@assistant-ui+\",\n \"assistant-ui@\",\n \"assistant-stream@\",\n \"assistant-cloud@\",\n];\n\nfunction isTrackedPnpmEntry(dirName: string): boolean {\n return TRACKED_PNPM_ENTRY_PREFIXES.some((p) => dirName.startsWith(p));\n}\n\nfunction processTrackedPackagesIn(\n nm: string,\n results: DiscoveredPackage[],\n visited: ProcessedDir,\n): void {\n let entries: fs.Dirent[];\n try {\n entries = fs.readdirSync(nm, { withFileTypes: true });\n } catch {\n return;\n }\n\n for (const entry of entries) {\n if (entry.name.startsWith(\".\")) continue;\n if (!entry.isDirectory() && !entry.isSymbolicLink()) continue;\n\n if (entry.name.startsWith(\"@\")) {\n const scopeDir = path.join(nm, entry.name);\n let scoped: fs.Dirent[];\n try {\n scoped = fs.readdirSync(scopeDir, { withFileTypes: true });\n } catch {\n continue;\n }\n for (const s of scoped) {\n if (!s.isDirectory() && !s.isSymbolicLink()) continue;\n if (!isTrackedPackage(`${entry.name}/${s.name}`)) continue;\n processPackageDir(path.join(scopeDir, s.name), results, visited);\n }\n } else if (isTrackedPackage(entry.name)) {\n processPackageDir(path.join(nm, entry.name), results, visited);\n }\n }\n}\n\nfunction walkPnpmStore(\n cwd: string,\n results: DiscoveredPackage[],\n visited: ProcessedDir,\n): void {\n const storeDir = path.join(cwd, \"node_modules\", \".pnpm\");\n let entries: fs.Dirent[];\n try {\n entries = fs.readdirSync(storeDir, { withFileTypes: true });\n } catch {\n return;\n }\n\n for (const entry of entries) {\n if (!entry.isDirectory() && !entry.isSymbolicLink()) continue;\n if (!isTrackedPnpmEntry(entry.name)) continue;\n processTrackedPackagesIn(\n path.join(storeDir, entry.name, \"node_modules\"),\n results,\n visited,\n );\n }\n}\n\n// Discover every installation of an assistant-ui-family package reachable\n// from `cwd`. Node resolves packages through ancestor node_modules directories,\n// so inspect each level to include workspace-hoisted installs. Nested installs\n// and pnpm virtual stores are scanned to catch duplicate transitive copies.\nexport function discoverInstalledPackages(cwd: string): DiscoveredPackage[] {\n const results: DiscoveredPackage[] = [];\n const visited: ProcessedDir = { set: new Set() };\n let dir = resolveRealPath(cwd);\n const scanRoot = findWorkspaceRoot(dir) ?? dir;\n\n while (true) {\n walkNodeModulesAt(dir, results, visited);\n walkPnpmStore(dir, results, visited);\n\n if (dir === scanRoot) break;\n dir = path.dirname(dir);\n }\n\n return results;\n}\n\nexport interface DuplicateGroup {\n name: string;\n installations: DiscoveredPackage[];\n}\n\nexport function findDuplicates(\n packages: DiscoveredPackage[],\n): DuplicateGroup[] {\n const byName = new Map<string, DiscoveredPackage[]>();\n for (const pkg of packages) {\n const list = byName.get(pkg.name) ?? [];\n list.push(pkg);\n byName.set(pkg.name, list);\n }\n\n const duplicates: DuplicateGroup[] = [];\n for (const [name, installations] of byName) {\n const versions = new Set(installations.map((i) => i.version));\n if (versions.size > 1) {\n duplicates.push({ name, installations });\n }\n }\n duplicates.sort((a, b) => a.name.localeCompare(b.name));\n return duplicates;\n}\n\nexport function uniquePackageNames(packages: DiscoveredPackage[]): string[] {\n return Array.from(new Set(packages.map((p) => p.name))).sort();\n}\n\n// Package names use a restricted character set (`[a-z0-9._~-]` plus a\n// leading `@scope/` for scoped packages — see the npm package-name spec)\n// and the npm registry expects the scope's `@` and `/` un-encoded. So a\n// simple validation + concatenation is both correct and avoids the\n// CodeQL \"incomplete string escaping\" foot-gun of `encodeURIComponent`\n// + targeted un-escape.\nconst VALID_NPM_NAME = /^(@[a-z0-9._~-]+\\/)?[a-z0-9._~-]+$/;\n\nasync function fetchLatestVersion(name: string): Promise<string | null> {\n if (!VALID_NPM_NAME.test(name)) return null;\n try {\n const res = await fetch(`https://registry.npmjs.org/${name}/latest`, {\n headers: { Accept: \"application/json\" },\n });\n if (!res.ok) return null;\n const data = (await res.json()) as { version?: string };\n return data.version ?? null;\n } catch {\n return null;\n }\n}\n\nasync function fetchAllLatestVersions(\n names: string[],\n): Promise<Map<string, string | null>> {\n const entries = await Promise.all(\n names.map(async (n) => [n, await fetchLatestVersion(n)] as const),\n );\n return new Map(entries);\n}\n\nexport function compareSemver(a: string, b: string): number {\n const validA = valid(a);\n const validB = valid(b);\n if (!validA || !validB) return a.localeCompare(b);\n return compare(validA, validB);\n}\n\nexport interface OutdatedPackage {\n name: string;\n current: string;\n latest: string;\n}\n\nexport function findOutdated(\n packages: DiscoveredPackage[],\n latest: Map<string, string | null>,\n): OutdatedPackage[] {\n const newestByName = new Map<string, string>();\n for (const pkg of packages) {\n const existing = newestByName.get(pkg.name);\n if (!existing || compareSemver(pkg.version, existing) > 0) {\n newestByName.set(pkg.name, pkg.version);\n }\n }\n\n const result: OutdatedPackage[] = [];\n for (const [name, current] of newestByName) {\n const latestVersion = latest.get(name);\n if (!latestVersion) continue;\n if (compareSemver(current, latestVersion) < 0) {\n result.push({ name, current, latest: latestVersion });\n }\n }\n result.sort((a, b) => a.name.localeCompare(b.name));\n return result;\n}\n\nfunction relativeInstallPath(installPath: string, cwd: string): string {\n const rel = path.relative(cwd, installPath);\n return rel.startsWith(\"..\") ? installPath : rel;\n}\n\nfunction reportDuplicates(\n duplicates: DuplicateGroup[],\n cwd: string,\n lines: string[],\n): void {\n if (duplicates.length === 0) {\n lines.push(chalk.green(\"✓ No duplicate versions detected.\"));\n return;\n }\n\n lines.push(chalk.red.bold(\"✗ Duplicate versions detected:\"));\n for (const dup of duplicates) {\n const versions = Array.from(\n new Set(dup.installations.map((i) => i.version)),\n )\n .sort(compareSemver)\n .join(\", \");\n lines.push(chalk.red(` ${dup.name} → ${versions}`));\n for (const inst of dup.installations) {\n lines.push(\n chalk.dim(\n ` ${inst.version} ${relativeInstallPath(inst.installPath, cwd)}`,\n ),\n );\n }\n }\n lines.push(\"\");\n lines.push(\n chalk.yellow(\n \"Duplicates almost always cause subtle runtime bugs (see https://github.com/assistant-ui/assistant-ui/issues/4101).\",\n ),\n );\n lines.push(\n chalk.yellow(\n \"Fix by aligning all @assistant-ui/* packages to compatible versions — run:\",\n ),\n );\n lines.push(chalk.cyan(\" npx assistant-ui update\"));\n}\n\nfunction reportOutdated(outdated: OutdatedPackage[], lines: string[]): void {\n if (outdated.length === 0) {\n lines.push(chalk.green(\"✓ All assistant-ui packages are up to date.\"));\n return;\n }\n\n lines.push(chalk.yellow.bold(\"! Outdated packages:\"));\n const maxLen = Math.max(...outdated.map((o) => o.name.length));\n for (const o of outdated) {\n lines.push(\n chalk.yellow(\n ` ${o.name.padEnd(maxLen)} ${o.current} → ${o.latest} (latest)`,\n ),\n );\n }\n lines.push(\"\");\n lines.push(chalk.yellow(\"Run the following to upgrade everything:\"));\n lines.push(chalk.cyan(\" npx assistant-ui update\"));\n}\n\nexport const doctor = new Command()\n .name(\"doctor\")\n .description(\n \"Diagnose mismatched or outdated assistant-ui packages (including transitive ones).\",\n )\n .option(\n \"-c, --cwd <cwd>\",\n \"the working directory. defaults to the current directory.\",\n process.cwd(),\n )\n .option(\"--no-network\", \"Skip the npm registry check for latest versions.\")\n .action(async (opts: { cwd: string; network: boolean }) => {\n const cwd = resolveRealPath(opts.cwd);\n const packageJsonPath = path.join(cwd, \"package.json\");\n\n if (!fs.existsSync(packageJsonPath)) {\n console.error(\n chalk.red(\"No package.json found in the current directory.\"),\n );\n process.exit(1);\n }\n\n console.log(\"\");\n console.log(chalk.bold(\"Running assistant-ui doctor...\"));\n console.log(\"\");\n\n const installed = discoverInstalledPackages(cwd);\n\n if (installed.length === 0) {\n console.log(\n chalk.yellow(\n \"No assistant-ui packages found in node_modules. Did you run `npm install`?\",\n ),\n );\n console.log(\"\");\n return;\n }\n\n const duplicates = findDuplicates(installed);\n\n let latest = new Map<string, string | null>();\n if (opts.network) {\n latest = await fetchAllLatestVersions(uniquePackageNames(installed));\n }\n const outdated = findOutdated(installed, latest);\n\n const lines: string[] = [];\n reportDuplicates(duplicates, cwd, lines);\n lines.push(\"\");\n if (opts.network) {\n reportOutdated(outdated, lines);\n } else {\n lines.push(chalk.dim(\"Skipped npm registry check (--no-network).\"));\n }\n\n for (const line of lines) console.log(line);\n console.log(\"\");\n\n if (duplicates.length > 0) {\n process.exitCode = 1;\n }\n });\n"],"mappings":"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"}
|
package/dist/commands/info.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
import { findWorkspaceRoot } from "../lib/utils/workspace.js";
|
|
1
2
|
import { Command } from "commander";
|
|
2
|
-
|
|
3
3
|
//#region src/commands/info.d.ts
|
|
4
|
+
declare function satisfiesRange(version: string, range: string): boolean;
|
|
4
5
|
declare const info: Command;
|
|
5
6
|
//#endregion
|
|
6
|
-
export { info };
|
|
7
|
+
export { findWorkspaceRoot, info, satisfiesRange };
|
|
7
8
|
//# sourceMappingURL=info.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"info.d.ts","names":[],"sources":["../../src/commands/info.ts"],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"info.d.ts","names":[],"sources":["../../src/commands/info.ts"],"mappings":";;;iBAgNgB,eAAe,iBAAiB;cAyMnC,MAAI"}
|
package/dist/commands/info.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { findWorkspaceRoot, resolveRealPath } from "../lib/utils/workspace.js";
|
|
1
2
|
import { Command } from "commander";
|
|
2
3
|
import chalk from "chalk";
|
|
3
4
|
import * as fs$1 from "node:fs";
|
|
@@ -5,6 +6,7 @@ import * as path$1 from "node:path";
|
|
|
5
6
|
import { detect } from "detect-package-manager";
|
|
6
7
|
import { spawnSync } from "node:child_process";
|
|
7
8
|
import * as os$1 from "node:os";
|
|
9
|
+
import { satisfies } from "semver";
|
|
8
10
|
//#region src/commands/info.ts
|
|
9
11
|
const ASSISTANT_UI_PACKAGES = [
|
|
10
12
|
"@assistant-ui/react",
|
|
@@ -65,25 +67,16 @@ function getInstalledVersion(pkg, cwd) {
|
|
|
65
67
|
} catch {}
|
|
66
68
|
return null;
|
|
67
69
|
}
|
|
68
|
-
function findWorkspaceRoot(cwd) {
|
|
69
|
-
let dir = path$1.dirname(cwd);
|
|
70
|
-
const root = path$1.parse(dir).root;
|
|
71
|
-
while (dir !== root) {
|
|
72
|
-
if (fs$1.existsSync(path$1.join(dir, "pnpm-workspace.yaml"))) return dir;
|
|
73
|
-
const pkgPath = path$1.join(dir, "package.json");
|
|
74
|
-
if (fs$1.existsSync(pkgPath)) try {
|
|
75
|
-
if (JSON.parse(fs$1.readFileSync(pkgPath, "utf8")).workspaces) return dir;
|
|
76
|
-
} catch {}
|
|
77
|
-
dir = path$1.dirname(dir);
|
|
78
|
-
}
|
|
79
|
-
return null;
|
|
80
|
-
}
|
|
81
70
|
function readProjectDeps(projectPkg) {
|
|
82
71
|
return {
|
|
83
72
|
...projectPkg.dependencies ?? {},
|
|
84
73
|
...projectPkg.devDependencies ?? {}
|
|
85
74
|
};
|
|
86
75
|
}
|
|
76
|
+
function getAssistantUiPackageNames(projectPkg) {
|
|
77
|
+
const declaredPackages = Object.keys(readProjectDeps(projectPkg)).filter((name) => name.startsWith("@assistant-ui/")).sort();
|
|
78
|
+
return [.../* @__PURE__ */ new Set([...ASSISTANT_UI_PACKAGES, ...declaredPackages])];
|
|
79
|
+
}
|
|
87
80
|
function getSpecifiedRange(pkg, projectPkg) {
|
|
88
81
|
const deps = projectPkg.dependencies ?? {};
|
|
89
82
|
const devDeps = projectPkg.devDependencies ?? {};
|
|
@@ -120,6 +113,14 @@ function getOsInfo() {
|
|
|
120
113
|
default: return `${platform} ${release} (${arch})`;
|
|
121
114
|
}
|
|
122
115
|
}
|
|
116
|
+
function getCliVersion() {
|
|
117
|
+
try {
|
|
118
|
+
const packageJson = JSON.parse(fs$1.readFileSync(new URL("../../package.json", import.meta.url), "utf8"));
|
|
119
|
+
return typeof packageJson.version === "string" ? packageJson.version : "unknown";
|
|
120
|
+
} catch {
|
|
121
|
+
return "unknown";
|
|
122
|
+
}
|
|
123
|
+
}
|
|
123
124
|
async function getPackageManagerInfo(cwd) {
|
|
124
125
|
const pm = await detect({ cwd });
|
|
125
126
|
return {
|
|
@@ -131,16 +132,8 @@ async function getPackageManagerInfo(cwd) {
|
|
|
131
132
|
};
|
|
132
133
|
}
|
|
133
134
|
function satisfiesRange(version, range) {
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
const major = (v) => parseInt(clean(v).split(".")[0], 10);
|
|
137
|
-
if (range.includes("||")) return range.split("||").some((part) => satisfiesRange(version, part.trim()));
|
|
138
|
-
const rangeMajor = major(range);
|
|
139
|
-
const versionMajor = major(version);
|
|
140
|
-
if (Number.isNaN(rangeMajor) || Number.isNaN(versionMajor)) return true;
|
|
141
|
-
if (range.startsWith("^")) return versionMajor >= rangeMajor;
|
|
142
|
-
if (range.startsWith(">=")) return versionMajor >= rangeMajor;
|
|
143
|
-
return versionMajor >= rangeMajor;
|
|
135
|
+
const normalizedRange = range.startsWith("workspace:") ? range.slice(10) : range;
|
|
136
|
+
return normalizedRange === "" || normalizedRange === "^" || normalizedRange === "~" || normalizedRange === "any" || satisfies(version, normalizedRange, { includePrerelease: true });
|
|
144
137
|
}
|
|
145
138
|
function collectPackages(names, cwd, projectPkg) {
|
|
146
139
|
const result = [];
|
|
@@ -180,10 +173,11 @@ function collectWarnings(packages, cwd, projectPkg) {
|
|
|
180
173
|
}
|
|
181
174
|
async function collectInfo(cwd, projectPkg) {
|
|
182
175
|
const pm = await getPackageManagerInfo(cwd);
|
|
183
|
-
const packages = collectPackages(
|
|
176
|
+
const packages = collectPackages(getAssistantUiPackageNames(projectPkg), cwd, projectPkg);
|
|
184
177
|
const ecosystem = collectPackages(ECOSYSTEM_PACKAGES, cwd, projectPkg);
|
|
185
178
|
const warnings = collectWarnings(packages, cwd, projectPkg);
|
|
186
179
|
return {
|
|
180
|
+
cliVersion: getCliVersion(),
|
|
187
181
|
os: getOsInfo(),
|
|
188
182
|
node: process.version,
|
|
189
183
|
pm,
|
|
@@ -206,6 +200,7 @@ function formatSection(label, items) {
|
|
|
206
200
|
function renderPlain(data) {
|
|
207
201
|
const lines = [];
|
|
208
202
|
lines.push("Environment:");
|
|
203
|
+
lines.push(` assistant-ui CLI: ${data.cliVersion}`);
|
|
209
204
|
lines.push(` OS: ${data.os}`);
|
|
210
205
|
lines.push(` Node.js: ${data.node}`);
|
|
211
206
|
lines.push(` Package Manager: ${data.pm.name} ${data.pm.version}`);
|
|
@@ -223,6 +218,7 @@ function renderPlain(data) {
|
|
|
223
218
|
function renderColored(data) {
|
|
224
219
|
const lines = [];
|
|
225
220
|
lines.push(chalk.bold("Environment:"));
|
|
221
|
+
lines.push(` assistant-ui CLI: ${data.cliVersion}`);
|
|
226
222
|
lines.push(` OS: ${data.os}`);
|
|
227
223
|
lines.push(` Node.js: ${data.node}`);
|
|
228
224
|
lines.push(` Package Manager: ${data.pm.name} ${data.pm.version}`);
|
|
@@ -251,7 +247,7 @@ function renderColored(data) {
|
|
|
251
247
|
return lines;
|
|
252
248
|
}
|
|
253
249
|
const info = new Command().name("info").description("Print environment and package information for bug reports.").option("-c, --cwd <cwd>", "the working directory. defaults to the current directory.", process.cwd()).action(async (opts) => {
|
|
254
|
-
const cwd =
|
|
250
|
+
const cwd = resolveRealPath(opts.cwd);
|
|
255
251
|
const packageJsonPath = path$1.join(cwd, "package.json");
|
|
256
252
|
if (!fs$1.existsSync(packageJsonPath)) {
|
|
257
253
|
console.error(chalk.red("No package.json found in the current directory."));
|
|
@@ -272,6 +268,6 @@ const info = new Command().name("info").description("Print environment and packa
|
|
|
272
268
|
console.log("");
|
|
273
269
|
});
|
|
274
270
|
//#endregion
|
|
275
|
-
export { info };
|
|
271
|
+
export { findWorkspaceRoot, info, satisfiesRange };
|
|
276
272
|
|
|
277
273
|
//# sourceMappingURL=info.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"info.js","names":["path","fs","os"],"sources":["../../src/commands/info.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport * as fs from \"node:fs\";\nimport * as os from \"node:os\";\nimport * as path from \"node:path\";\nimport { spawnSync } from \"node:child_process\";\nimport chalk from \"chalk\";\nimport { detect } from \"detect-package-manager\";\n\nconst ASSISTANT_UI_PACKAGES = [\n // Distribution\n \"@assistant-ui/react\",\n \"@assistant-ui/react-native\",\n \"@assistant-ui/react-ink\",\n // Core (should not be installed directly)\n \"@assistant-ui/core\",\n \"@assistant-ui/store\",\n \"@assistant-ui/tap\",\n // Streaming & Cloud\n \"assistant-stream\",\n \"assistant-cloud\",\n \"@assistant-ui/cloud-ai-sdk\",\n // Adapters\n \"@assistant-ui/eve\",\n \"@assistant-ui/react-ai-sdk\",\n \"@assistant-ui/react-langgraph\",\n \"@assistant-ui/react-ag-ui\",\n \"@assistant-ui/react-a2a\",\n \"@assistant-ui/react-data-stream\",\n \"@assistant-ui/react-google-adk\",\n // UI / Rendering\n \"@assistant-ui/react-markdown\",\n \"@assistant-ui/react-streamdown\",\n \"@assistant-ui/react-lexical\",\n \"@assistant-ui/react-syntax-highlighter\",\n \"@assistant-ui/react-hook-form\",\n // Observability & DevTools\n \"@assistant-ui/react-o11y\",\n \"@assistant-ui/react-devtools\",\n];\n\nconst ECOSYSTEM_PACKAGES = [\n \"react\",\n \"react-dom\",\n \"react-native\",\n \"next\",\n \"vite\",\n \"expo\",\n \"ai\",\n \"zod\",\n \"zustand\",\n \"typescript\",\n];\n\n// Packages that users should NOT install directly — they are internal\n// dependencies pulled in automatically by distribution packages.\nconst SHOULD_NOT_DIRECT_INSTALL = new Set([\n \"@assistant-ui/core\",\n \"@assistant-ui/store\",\n \"@assistant-ui/tap\",\n]);\n\nfunction resolvePackageJson(pkg: string, cwd: string): string | null {\n let dir = cwd;\n const root = path.parse(dir).root;\n while (dir !== root) {\n const candidate = path.join(\n dir,\n \"node_modules\",\n ...pkg.split(\"/\"),\n \"package.json\",\n );\n if (fs.existsSync(candidate)) return candidate;\n dir = path.dirname(dir);\n }\n return null;\n}\n\nfunction getInstalledVersion(pkg: string, cwd: string): string | null {\n try {\n const pkgJsonPath = resolvePackageJson(pkg, cwd);\n if (pkgJsonPath) {\n const pkgJson = JSON.parse(fs.readFileSync(pkgJsonPath, \"utf8\"));\n return pkgJson.version ?? null;\n }\n } catch {\n // ignore\n }\n return null;\n}\n\nfunction findWorkspaceRoot(cwd: string): string | null {\n let dir = path.dirname(cwd);\n const root = path.parse(dir).root;\n while (dir !== root) {\n if (fs.existsSync(path.join(dir, \"pnpm-workspace.yaml\"))) return dir;\n const pkgPath = path.join(dir, \"package.json\");\n if (fs.existsSync(pkgPath)) {\n try {\n const pkg = JSON.parse(fs.readFileSync(pkgPath, \"utf8\"));\n if (pkg.workspaces) return dir;\n } catch {\n // ignore\n }\n }\n dir = path.dirname(dir);\n }\n return null;\n}\n\nfunction readProjectDeps(\n projectPkg: Record<string, unknown>,\n): Record<string, string> {\n return {\n ...((projectPkg.dependencies ?? {}) as Record<string, string>),\n ...((projectPkg.devDependencies ?? {}) as Record<string, string>),\n };\n}\n\nfunction getSpecifiedRange(\n pkg: string,\n projectPkg: Record<string, unknown>,\n): string | null {\n const deps = (projectPkg.dependencies ?? {}) as Record<string, string>;\n const devDeps = (projectPkg.devDependencies ?? {}) as Record<string, string>;\n return deps[pkg] ?? devDeps[pkg] ?? null;\n}\n\nfunction getPeerDeps(pkg: string, cwd: string): Record<string, string> | null {\n try {\n const pkgJsonPath = resolvePackageJson(pkg, cwd);\n if (pkgJsonPath) {\n const pkgJson = JSON.parse(fs.readFileSync(pkgJsonPath, \"utf8\"));\n return (pkgJson.peerDependencies as Record<string, string>) ?? null;\n }\n } catch {\n // ignore\n }\n return null;\n}\n\nfunction detectFramework(\n projectPkg: Record<string, unknown>,\n cwd: string,\n): string {\n const deps = readProjectDeps(projectPkg);\n\n if (deps.next) {\n const v = getInstalledVersion(\"next\", cwd);\n return `Next.js ${v ?? deps.next}`;\n }\n if (deps.expo) {\n const v = getInstalledVersion(\"expo\", cwd);\n return `Expo ${v ?? deps.expo}`;\n }\n if (deps.vite) {\n const v = getInstalledVersion(\"vite\", cwd);\n return `Vite ${v ?? deps.vite}`;\n }\n if (deps[\"@remix-run/react\"] || deps.remix) return \"Remix\";\n if (deps.gatsby) return \"Gatsby\";\n if (deps.astro) return \"Astro\";\n return \"Unknown\";\n}\n\nfunction getOsInfo(): string {\n const platform = os.platform();\n const arch = os.arch();\n const release = os.release();\n\n switch (platform) {\n case \"darwin\": {\n const result = spawnSync(\"sw_vers\", [\"-productVersion\"], {\n encoding: \"utf8\",\n });\n const macVer = result.stdout?.trim();\n return macVer\n ? `macOS ${macVer} (${arch})`\n : `macOS ${release} (${arch})`;\n }\n case \"win32\":\n return `Windows ${release} (${arch})`;\n case \"linux\":\n return `Linux ${release} (${arch})`;\n default:\n return `${platform} ${release} (${arch})`;\n }\n}\n\nasync function getPackageManagerInfo(\n cwd: string,\n): Promise<{ name: string; version: string }> {\n const pm = await detect({ cwd });\n const result = spawnSync(pm, [\"--version\"], {\n encoding: \"utf8\",\n cwd,\n });\n const version = result.stdout?.trim() ?? \"unknown\";\n return { name: pm, version };\n}\n\nfunction satisfiesRange(version: string, range: string): boolean {\n if (range === \"*\" || range === \"any\") return true;\n\n const clean = (v: string) => v.replace(/^[^\\d]*/, \"\");\n const major = (v: string) => parseInt(clean(v).split(\".\")[0]!, 10);\n\n if (range.includes(\"||\")) {\n return range\n .split(\"||\")\n .some((part) => satisfiesRange(version, part.trim()));\n }\n\n const rangeMajor = major(range);\n const versionMajor = major(version);\n\n if (Number.isNaN(rangeMajor) || Number.isNaN(versionMajor)) return true;\n\n if (range.startsWith(\"^\")) return versionMajor >= rangeMajor;\n if (range.startsWith(\">=\")) return versionMajor >= rangeMajor;\n\n return versionMajor >= rangeMajor;\n}\n\ninterface PackageInfo {\n name: string;\n version: string;\n range: string | null;\n}\n\ninterface InfoData {\n os: string;\n node: string;\n pm: { name: string; version: string };\n framework: string;\n isMonorepo: boolean;\n packages: PackageInfo[];\n ecosystem: PackageInfo[];\n warnings: string[];\n}\n\nfunction collectPackages(\n names: string[],\n cwd: string,\n projectPkg: Record<string, unknown>,\n): PackageInfo[] {\n const result: PackageInfo[] = [];\n const deps = readProjectDeps(projectPkg);\n\n for (const name of names) {\n const version = getInstalledVersion(name, cwd);\n if (version) {\n result.push({\n name,\n version,\n range: getSpecifiedRange(name, projectPkg),\n });\n } else {\n // Fallback: no node_modules, show range from package.json\n const range = deps[name];\n if (range && !range.startsWith(\"workspace:\")) {\n result.push({ name, version: `${range} (not installed)`, range });\n }\n }\n }\n return result;\n}\n\nfunction collectWarnings(\n packages: PackageInfo[],\n cwd: string,\n projectPkg: Record<string, unknown>,\n): string[] {\n const warnings: string[] = [];\n const deps = readProjectDeps(projectPkg);\n\n // Check peer dependency mismatches\n for (const pkg of packages) {\n const peerDeps = getPeerDeps(pkg.name, cwd);\n if (!peerDeps) continue;\n\n for (const [peerName, peerRange] of Object.entries(peerDeps)) {\n const peerVersion = getInstalledVersion(peerName, cwd);\n if (!peerVersion) continue;\n if (!satisfiesRange(peerVersion, peerRange)) {\n warnings.push(\n `${pkg.name} requires ${peerName} ${peerRange}, found ${peerVersion}`,\n );\n }\n }\n }\n\n // Check for direct install of internal packages\n for (const name of SHOULD_NOT_DIRECT_INSTALL) {\n if (deps[name]) {\n warnings.push(\n `${name} should not be installed directly — it is an internal dependency`,\n );\n }\n }\n\n return warnings;\n}\n\nasync function collectInfo(\n cwd: string,\n projectPkg: Record<string, unknown>,\n): Promise<InfoData> {\n const pm = await getPackageManagerInfo(cwd);\n const packages = collectPackages(ASSISTANT_UI_PACKAGES, cwd, projectPkg);\n const ecosystem = collectPackages(ECOSYSTEM_PACKAGES, cwd, projectPkg);\n const warnings = collectWarnings(packages, cwd, projectPkg);\n\n return {\n os: getOsInfo(),\n node: process.version,\n pm,\n framework: detectFramework(projectPkg, cwd),\n isMonorepo: findWorkspaceRoot(cwd) !== null,\n packages,\n ecosystem,\n warnings,\n };\n}\n\nfunction formatSection(label: string, items: PackageInfo[]): string[] {\n if (items.length === 0) return [];\n const lines: string[] = [];\n lines.push(\"\");\n lines.push(`${label}:`);\n const maxLen = Math.max(...items.map((p) => p.name.length));\n for (const pkg of items) {\n lines.push(` ${pkg.name.padEnd(maxLen)} ${pkg.version}`);\n }\n return lines;\n}\n\nfunction renderPlain(data: InfoData): string[] {\n const lines: string[] = [];\n\n lines.push(\"Environment:\");\n lines.push(` OS: ${data.os}`);\n lines.push(` Node.js: ${data.node}`);\n lines.push(` Package Manager: ${data.pm.name} ${data.pm.version}`);\n lines.push(` Framework: ${data.framework}`);\n if (data.isMonorepo) {\n lines.push(` Monorepo: yes`);\n }\n\n lines.push(...formatSection(\"Packages\", data.packages));\n lines.push(...formatSection(\"Ecosystem\", data.ecosystem));\n\n if (data.warnings.length > 0) {\n lines.push(\"\");\n lines.push(\"Warnings:\");\n for (const w of data.warnings) {\n lines.push(` ! ${w}`);\n }\n }\n\n return lines;\n}\n\nfunction renderColored(data: InfoData): string[] {\n const lines: string[] = [];\n\n lines.push(chalk.bold(\"Environment:\"));\n lines.push(` OS: ${data.os}`);\n lines.push(` Node.js: ${data.node}`);\n lines.push(` Package Manager: ${data.pm.name} ${data.pm.version}`);\n lines.push(` Framework: ${data.framework}`);\n if (data.isMonorepo) {\n lines.push(` Monorepo: yes`);\n }\n\n if (data.packages.length > 0) {\n const section = formatSection(\"Packages\", data.packages);\n section[0] = \"\";\n section[1] = chalk.bold(\"Packages:\");\n lines.push(...section);\n } else {\n lines.push(\"\");\n lines.push(chalk.yellow(\" No assistant-ui packages found.\"));\n }\n\n if (data.ecosystem.length > 0) {\n const section = formatSection(\"Ecosystem\", data.ecosystem);\n section[0] = \"\";\n section[1] = chalk.bold(\"Ecosystem:\");\n lines.push(...section);\n }\n\n if (data.warnings.length > 0) {\n lines.push(\"\");\n lines.push(chalk.yellow.bold(\"Warnings:\"));\n for (const w of data.warnings) {\n lines.push(chalk.yellow(` ! ${w}`));\n }\n }\n\n return lines;\n}\n\nexport const info = new Command()\n .name(\"info\")\n .description(\"Print environment and package information for bug reports.\")\n .option(\n \"-c, --cwd <cwd>\",\n \"the working directory. defaults to the current directory.\",\n process.cwd(),\n )\n .action(async (opts) => {\n const cwd = path.resolve(opts.cwd);\n const packageJsonPath = path.join(cwd, \"package.json\");\n\n if (!fs.existsSync(packageJsonPath)) {\n console.error(\n chalk.red(\"No package.json found in the current directory.\"),\n );\n process.exit(1);\n }\n\n const projectPkg = JSON.parse(fs.readFileSync(packageJsonPath, \"utf8\"));\n const data = await collectInfo(cwd, projectPkg);\n\n // Colored output for terminal\n console.log(\"\");\n for (const line of renderColored(data)) {\n console.log(line);\n }\n console.log(\"\");\n\n // Copyable plain text\n const plain = renderPlain(data);\n const block = [\"```\", ...plain, \"```\"].join(\"\\n\");\n\n console.log(chalk.dim(\"— Copy the text below into your bug report —\"));\n console.log(\"\");\n console.log(block);\n console.log(\"\");\n });\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"info.js","names":["path","fs","os"],"sources":["../../src/commands/info.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport * as fs from \"node:fs\";\nimport * as os from \"node:os\";\nimport * as path from \"node:path\";\nimport { spawnSync } from \"node:child_process\";\nimport chalk from \"chalk\";\nimport { detect } from \"detect-package-manager\";\nimport { satisfies } from \"semver\";\nimport { findWorkspaceRoot, resolveRealPath } from \"../lib/utils/workspace\";\n\nexport { findWorkspaceRoot };\n\nconst ASSISTANT_UI_PACKAGES = [\n // Distribution\n \"@assistant-ui/react\",\n \"@assistant-ui/react-native\",\n \"@assistant-ui/react-ink\",\n // Core (should not be installed directly)\n \"@assistant-ui/core\",\n \"@assistant-ui/store\",\n \"@assistant-ui/tap\",\n // Streaming & Cloud\n \"assistant-stream\",\n \"assistant-cloud\",\n \"@assistant-ui/cloud-ai-sdk\",\n // Adapters\n \"@assistant-ui/eve\",\n \"@assistant-ui/react-ai-sdk\",\n \"@assistant-ui/react-langgraph\",\n \"@assistant-ui/react-ag-ui\",\n \"@assistant-ui/react-a2a\",\n \"@assistant-ui/react-data-stream\",\n \"@assistant-ui/react-google-adk\",\n // UI / Rendering\n \"@assistant-ui/react-markdown\",\n \"@assistant-ui/react-streamdown\",\n \"@assistant-ui/react-lexical\",\n \"@assistant-ui/react-syntax-highlighter\",\n \"@assistant-ui/react-hook-form\",\n // Observability & DevTools\n \"@assistant-ui/react-o11y\",\n \"@assistant-ui/react-devtools\",\n];\n\nconst ECOSYSTEM_PACKAGES = [\n \"react\",\n \"react-dom\",\n \"react-native\",\n \"next\",\n \"vite\",\n \"expo\",\n \"ai\",\n \"zod\",\n \"zustand\",\n \"typescript\",\n];\n\n// Packages that users should NOT install directly — they are internal\n// dependencies pulled in automatically by distribution packages.\nconst SHOULD_NOT_DIRECT_INSTALL = new Set([\n \"@assistant-ui/core\",\n \"@assistant-ui/store\",\n \"@assistant-ui/tap\",\n]);\n\nfunction resolvePackageJson(pkg: string, cwd: string): string | null {\n let dir = cwd;\n const root = path.parse(dir).root;\n while (dir !== root) {\n const candidate = path.join(\n dir,\n \"node_modules\",\n ...pkg.split(\"/\"),\n \"package.json\",\n );\n if (fs.existsSync(candidate)) return candidate;\n dir = path.dirname(dir);\n }\n return null;\n}\n\nfunction getInstalledVersion(pkg: string, cwd: string): string | null {\n try {\n const pkgJsonPath = resolvePackageJson(pkg, cwd);\n if (pkgJsonPath) {\n const pkgJson = JSON.parse(fs.readFileSync(pkgJsonPath, \"utf8\"));\n return pkgJson.version ?? null;\n }\n } catch {\n // ignore\n }\n return null;\n}\n\nfunction readProjectDeps(\n projectPkg: Record<string, unknown>,\n): Record<string, string> {\n return {\n ...((projectPkg.dependencies ?? {}) as Record<string, string>),\n ...((projectPkg.devDependencies ?? {}) as Record<string, string>),\n };\n}\n\nfunction getAssistantUiPackageNames(\n projectPkg: Record<string, unknown>,\n): string[] {\n const declaredPackages = Object.keys(readProjectDeps(projectPkg))\n .filter((name) => name.startsWith(\"@assistant-ui/\"))\n .sort();\n\n return [...new Set([...ASSISTANT_UI_PACKAGES, ...declaredPackages])];\n}\n\nfunction getSpecifiedRange(\n pkg: string,\n projectPkg: Record<string, unknown>,\n): string | null {\n const deps = (projectPkg.dependencies ?? {}) as Record<string, string>;\n const devDeps = (projectPkg.devDependencies ?? {}) as Record<string, string>;\n return deps[pkg] ?? devDeps[pkg] ?? null;\n}\n\nfunction getPeerDeps(pkg: string, cwd: string): Record<string, string> | null {\n try {\n const pkgJsonPath = resolvePackageJson(pkg, cwd);\n if (pkgJsonPath) {\n const pkgJson = JSON.parse(fs.readFileSync(pkgJsonPath, \"utf8\"));\n return (pkgJson.peerDependencies as Record<string, string>) ?? null;\n }\n } catch {\n // ignore\n }\n return null;\n}\n\nfunction detectFramework(\n projectPkg: Record<string, unknown>,\n cwd: string,\n): string {\n const deps = readProjectDeps(projectPkg);\n\n if (deps.next) {\n const v = getInstalledVersion(\"next\", cwd);\n return `Next.js ${v ?? deps.next}`;\n }\n if (deps.expo) {\n const v = getInstalledVersion(\"expo\", cwd);\n return `Expo ${v ?? deps.expo}`;\n }\n if (deps.vite) {\n const v = getInstalledVersion(\"vite\", cwd);\n return `Vite ${v ?? deps.vite}`;\n }\n if (deps[\"@remix-run/react\"] || deps.remix) return \"Remix\";\n if (deps.gatsby) return \"Gatsby\";\n if (deps.astro) return \"Astro\";\n return \"Unknown\";\n}\n\nfunction getOsInfo(): string {\n const platform = os.platform();\n const arch = os.arch();\n const release = os.release();\n\n switch (platform) {\n case \"darwin\": {\n const result = spawnSync(\"sw_vers\", [\"-productVersion\"], {\n encoding: \"utf8\",\n });\n const macVer = result.stdout?.trim();\n return macVer\n ? `macOS ${macVer} (${arch})`\n : `macOS ${release} (${arch})`;\n }\n case \"win32\":\n return `Windows ${release} (${arch})`;\n case \"linux\":\n return `Linux ${release} (${arch})`;\n default:\n return `${platform} ${release} (${arch})`;\n }\n}\n\nfunction getCliVersion(): string {\n try {\n const packageJson = JSON.parse(\n fs.readFileSync(new URL(\"../../package.json\", import.meta.url), \"utf8\"),\n ) as { version?: unknown };\n return typeof packageJson.version === \"string\"\n ? packageJson.version\n : \"unknown\";\n } catch {\n return \"unknown\";\n }\n}\n\nasync function getPackageManagerInfo(\n cwd: string,\n): Promise<{ name: string; version: string }> {\n const pm = await detect({ cwd });\n const result = spawnSync(pm, [\"--version\"], {\n encoding: \"utf8\",\n cwd,\n });\n const version = result.stdout?.trim() ?? \"unknown\";\n return { name: pm, version };\n}\n\nexport function satisfiesRange(version: string, range: string): boolean {\n const normalizedRange = range.startsWith(\"workspace:\")\n ? range.slice(\"workspace:\".length)\n : range;\n\n return (\n normalizedRange === \"\" ||\n normalizedRange === \"^\" ||\n normalizedRange === \"~\" ||\n normalizedRange === \"any\" ||\n satisfies(version, normalizedRange, { includePrerelease: true })\n );\n}\n\ninterface PackageInfo {\n name: string;\n version: string;\n range: string | null;\n}\n\ninterface InfoData {\n cliVersion: string;\n os: string;\n node: string;\n pm: { name: string; version: string };\n framework: string;\n isMonorepo: boolean;\n packages: PackageInfo[];\n ecosystem: PackageInfo[];\n warnings: string[];\n}\n\nfunction collectPackages(\n names: string[],\n cwd: string,\n projectPkg: Record<string, unknown>,\n): PackageInfo[] {\n const result: PackageInfo[] = [];\n const deps = readProjectDeps(projectPkg);\n\n for (const name of names) {\n const version = getInstalledVersion(name, cwd);\n if (version) {\n result.push({\n name,\n version,\n range: getSpecifiedRange(name, projectPkg),\n });\n } else {\n // Fallback: no node_modules, show range from package.json\n const range = deps[name];\n if (range && !range.startsWith(\"workspace:\")) {\n result.push({ name, version: `${range} (not installed)`, range });\n }\n }\n }\n return result;\n}\n\nfunction collectWarnings(\n packages: PackageInfo[],\n cwd: string,\n projectPkg: Record<string, unknown>,\n): string[] {\n const warnings: string[] = [];\n const deps = readProjectDeps(projectPkg);\n\n // Check peer dependency mismatches\n for (const pkg of packages) {\n const peerDeps = getPeerDeps(pkg.name, cwd);\n if (!peerDeps) continue;\n\n for (const [peerName, peerRange] of Object.entries(peerDeps)) {\n const peerVersion = getInstalledVersion(peerName, cwd);\n if (!peerVersion) continue;\n if (!satisfiesRange(peerVersion, peerRange)) {\n warnings.push(\n `${pkg.name} requires ${peerName} ${peerRange}, found ${peerVersion}`,\n );\n }\n }\n }\n\n // Check for direct install of internal packages\n for (const name of SHOULD_NOT_DIRECT_INSTALL) {\n if (deps[name]) {\n warnings.push(\n `${name} should not be installed directly — it is an internal dependency`,\n );\n }\n }\n\n return warnings;\n}\n\nasync function collectInfo(\n cwd: string,\n projectPkg: Record<string, unknown>,\n): Promise<InfoData> {\n const pm = await getPackageManagerInfo(cwd);\n const packages = collectPackages(\n getAssistantUiPackageNames(projectPkg),\n cwd,\n projectPkg,\n );\n const ecosystem = collectPackages(ECOSYSTEM_PACKAGES, cwd, projectPkg);\n const warnings = collectWarnings(packages, cwd, projectPkg);\n\n return {\n cliVersion: getCliVersion(),\n os: getOsInfo(),\n node: process.version,\n pm,\n framework: detectFramework(projectPkg, cwd),\n isMonorepo: findWorkspaceRoot(cwd) !== null,\n packages,\n ecosystem,\n warnings,\n };\n}\n\nfunction formatSection(label: string, items: PackageInfo[]): string[] {\n if (items.length === 0) return [];\n const lines: string[] = [];\n lines.push(\"\");\n lines.push(`${label}:`);\n const maxLen = Math.max(...items.map((p) => p.name.length));\n for (const pkg of items) {\n lines.push(` ${pkg.name.padEnd(maxLen)} ${pkg.version}`);\n }\n return lines;\n}\n\nfunction renderPlain(data: InfoData): string[] {\n const lines: string[] = [];\n\n lines.push(\"Environment:\");\n lines.push(` assistant-ui CLI: ${data.cliVersion}`);\n lines.push(` OS: ${data.os}`);\n lines.push(` Node.js: ${data.node}`);\n lines.push(` Package Manager: ${data.pm.name} ${data.pm.version}`);\n lines.push(` Framework: ${data.framework}`);\n if (data.isMonorepo) {\n lines.push(` Monorepo: yes`);\n }\n\n lines.push(...formatSection(\"Packages\", data.packages));\n lines.push(...formatSection(\"Ecosystem\", data.ecosystem));\n\n if (data.warnings.length > 0) {\n lines.push(\"\");\n lines.push(\"Warnings:\");\n for (const w of data.warnings) {\n lines.push(` ! ${w}`);\n }\n }\n\n return lines;\n}\n\nfunction renderColored(data: InfoData): string[] {\n const lines: string[] = [];\n\n lines.push(chalk.bold(\"Environment:\"));\n lines.push(` assistant-ui CLI: ${data.cliVersion}`);\n lines.push(` OS: ${data.os}`);\n lines.push(` Node.js: ${data.node}`);\n lines.push(` Package Manager: ${data.pm.name} ${data.pm.version}`);\n lines.push(` Framework: ${data.framework}`);\n if (data.isMonorepo) {\n lines.push(` Monorepo: yes`);\n }\n\n if (data.packages.length > 0) {\n const section = formatSection(\"Packages\", data.packages);\n section[0] = \"\";\n section[1] = chalk.bold(\"Packages:\");\n lines.push(...section);\n } else {\n lines.push(\"\");\n lines.push(chalk.yellow(\" No assistant-ui packages found.\"));\n }\n\n if (data.ecosystem.length > 0) {\n const section = formatSection(\"Ecosystem\", data.ecosystem);\n section[0] = \"\";\n section[1] = chalk.bold(\"Ecosystem:\");\n lines.push(...section);\n }\n\n if (data.warnings.length > 0) {\n lines.push(\"\");\n lines.push(chalk.yellow.bold(\"Warnings:\"));\n for (const w of data.warnings) {\n lines.push(chalk.yellow(` ! ${w}`));\n }\n }\n\n return lines;\n}\n\nexport const info = new Command()\n .name(\"info\")\n .description(\"Print environment and package information for bug reports.\")\n .option(\n \"-c, --cwd <cwd>\",\n \"the working directory. defaults to the current directory.\",\n process.cwd(),\n )\n .action(async (opts) => {\n const cwd = resolveRealPath(opts.cwd);\n const packageJsonPath = path.join(cwd, \"package.json\");\n\n if (!fs.existsSync(packageJsonPath)) {\n console.error(\n chalk.red(\"No package.json found in the current directory.\"),\n );\n process.exit(1);\n }\n\n const projectPkg = JSON.parse(fs.readFileSync(packageJsonPath, \"utf8\"));\n const data = await collectInfo(cwd, projectPkg);\n\n // Colored output for terminal\n console.log(\"\");\n for (const line of renderColored(data)) {\n console.log(line);\n }\n console.log(\"\");\n\n // Copyable plain text\n const plain = renderPlain(data);\n const block = [\"```\", ...plain, \"```\"].join(\"\\n\");\n\n console.log(chalk.dim(\"— Copy the text below into your bug report —\"));\n console.log(\"\");\n console.log(block);\n console.log(\"\");\n });\n"],"mappings":"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"}
|
package/dist/commands/init.d.ts
CHANGED
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
import { Command } from "commander";
|
|
2
|
-
|
|
3
2
|
//#region src/commands/init.d.ts
|
|
4
3
|
interface ExistingProjectInitPlan {
|
|
5
|
-
initArgs: string[]
|
|
4
|
+
initArgs: string[];
|
|
6
5
|
addArgs: string[];
|
|
7
6
|
}
|
|
8
7
|
declare function createExistingProjectInitPlan(params: {
|
|
9
8
|
yes: boolean;
|
|
10
9
|
overwrite: boolean;
|
|
11
|
-
registryUrl: string;
|
|
12
10
|
}): ExistingProjectInitPlan;
|
|
13
11
|
declare function isNonInteractiveShell(stdinIsTTY?: boolean): boolean;
|
|
14
12
|
declare const init: Command;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init.d.ts","names":[],"sources":["../../src/commands/init.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"init.d.ts","names":[],"sources":["../../src/commands/init.ts"],"mappings":";;UAgBU;EACR;EACA;;iBAGc,8BAA8B;EAC5C;EACA;IACE;iBAYY,sBACd;cAKW,MAAI"}
|
package/dist/commands/init.js
CHANGED
|
@@ -2,35 +2,22 @@ import { logger } from "../lib/utils/logger.js";
|
|
|
2
2
|
import { SpawnExitError, runSpawn } from "../lib/run-spawn.js";
|
|
3
3
|
import { dlxCommand, resolvePackageManager, resolvePackageManagerForCwd } from "../lib/create-project.js";
|
|
4
4
|
import { create } from "./create.js";
|
|
5
|
+
import { getComponentsJsonStyle, resolveQuickStartRegistryUrl } from "../lib/utils/registry.js";
|
|
5
6
|
import { Command, Option } from "commander";
|
|
6
7
|
import fs from "node:fs";
|
|
7
8
|
import path from "node:path";
|
|
8
9
|
//#region src/commands/init.ts
|
|
9
|
-
const DEFAULT_REGISTRY_URL = "https://r.assistant-ui.com/chat/b/ai-sdk-quick-start/json";
|
|
10
10
|
function createExistingProjectInitPlan(params) {
|
|
11
|
-
const { yes, overwrite
|
|
12
|
-
|
|
13
|
-
const addArgs = [`shadcn@latest`, "add"];
|
|
14
|
-
if (overwrite) addArgs.push("--overwrite");
|
|
15
|
-
addArgs.push(registryUrl);
|
|
16
|
-
return {
|
|
17
|
-
initArgs: null,
|
|
18
|
-
addArgs
|
|
19
|
-
};
|
|
20
|
-
}
|
|
21
|
-
const initArgs = [
|
|
11
|
+
const { yes, overwrite } = params;
|
|
12
|
+
const initArgs = yes ? [
|
|
22
13
|
`shadcn@latest`,
|
|
23
14
|
"init",
|
|
24
15
|
"--defaults",
|
|
25
16
|
"--yes"
|
|
26
|
-
];
|
|
27
|
-
const addArgs = [
|
|
28
|
-
|
|
29
|
-
"add",
|
|
30
|
-
"--yes"
|
|
31
|
-
];
|
|
17
|
+
] : [`shadcn@latest`, "init"];
|
|
18
|
+
const addArgs = [`shadcn@latest`, "add"];
|
|
19
|
+
if (yes) addArgs.push("--yes");
|
|
32
20
|
if (overwrite) addArgs.push("--overwrite");
|
|
33
|
-
addArgs.push(registryUrl);
|
|
34
21
|
return {
|
|
35
22
|
initArgs,
|
|
36
23
|
addArgs
|
|
@@ -67,7 +54,6 @@ const init = new Command().name("init").description("initialize assistant-ui in
|
|
|
67
54
|
await create.parseAsync(createArgs, { from: "user" });
|
|
68
55
|
return;
|
|
69
56
|
}
|
|
70
|
-
const registryUrl = DEFAULT_REGISTRY_URL;
|
|
71
57
|
logger.info("Initializing assistant-ui in existing project...");
|
|
72
58
|
logger.break();
|
|
73
59
|
if (!opts.yes && isNonInteractiveShell()) {
|
|
@@ -82,11 +68,15 @@ const init = new Command().name("init").description("initialize assistant-ui in
|
|
|
82
68
|
const [dlxCmd, dlxArgs] = dlxCommand(await resolvePackageManagerForCwd(targetDir, resolvePackageManager(opts)));
|
|
83
69
|
const { initArgs, addArgs } = createExistingProjectInitPlan({
|
|
84
70
|
yes: opts.yes,
|
|
85
|
-
overwrite: opts.overwrite
|
|
86
|
-
registryUrl
|
|
71
|
+
overwrite: opts.overwrite
|
|
87
72
|
});
|
|
88
|
-
|
|
89
|
-
|
|
73
|
+
await runSpawn(dlxCmd, [...dlxArgs, ...initArgs], targetDir);
|
|
74
|
+
const registryUrl = resolveQuickStartRegistryUrl(getComponentsJsonStyle(targetDir));
|
|
75
|
+
await runSpawn(dlxCmd, [
|
|
76
|
+
...dlxArgs,
|
|
77
|
+
...addArgs,
|
|
78
|
+
registryUrl
|
|
79
|
+
], targetDir);
|
|
90
80
|
logger.break();
|
|
91
81
|
logger.success("Project initialized successfully!");
|
|
92
82
|
logger.info("You can now add more components with 'assistant-ui add'");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init.js","names":[],"sources":["../../src/commands/init.ts"],"sourcesContent":["import { Command, Option } from \"commander\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport {\n dlxCommand,\n resolvePackageManager,\n resolvePackageManagerForCwd,\n} from \"../lib/create-project\";\nimport { runSpawn, SpawnExitError } from \"../lib/run-spawn\";\nimport { logger } from \"../lib/utils/logger\";\nimport {
|
|
1
|
+
{"version":3,"file":"init.js","names":[],"sources":["../../src/commands/init.ts"],"sourcesContent":["import { Command, Option } from \"commander\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport {\n dlxCommand,\n resolvePackageManager,\n resolvePackageManagerForCwd,\n} from \"../lib/create-project\";\nimport { runSpawn, SpawnExitError } from \"../lib/run-spawn\";\nimport { logger } from \"../lib/utils/logger\";\nimport {\n getComponentsJsonStyle,\n resolveQuickStartRegistryUrl,\n} from \"../lib/utils/registry\";\nimport { create } from \"./create\";\n\ninterface ExistingProjectInitPlan {\n initArgs: string[];\n addArgs: string[];\n}\n\nexport function createExistingProjectInitPlan(params: {\n yes: boolean;\n overwrite: boolean;\n}): ExistingProjectInitPlan {\n const { yes, overwrite } = params;\n const initArgs = yes\n ? [`shadcn@latest`, \"init\", \"--defaults\", \"--yes\"]\n : [`shadcn@latest`, \"init\"];\n const addArgs = [`shadcn@latest`, \"add\"];\n if (yes) addArgs.push(\"--yes\");\n if (overwrite) addArgs.push(\"--overwrite\");\n\n return { initArgs, addArgs };\n}\n\nexport function isNonInteractiveShell(\n stdinIsTTY = process.stdin.isTTY,\n): boolean {\n return !stdinIsTTY;\n}\n\nexport const init = new Command()\n .name(\"init\")\n .description(\"initialize assistant-ui in an existing project\")\n .argument(\"[project-directory]\", \"directory for the new project\")\n .option(\"-y, --yes\", \"skip confirmation prompt.\", false)\n .option(\"-o, --overwrite\", \"overwrite existing files.\", false)\n .option(\n \"-c, --cwd <cwd>\",\n \"the working directory. defaults to the current directory.\",\n process.cwd(),\n )\n .addOption(\n new Option(\n \"-p, --preset <name-or-url>\",\n \"preset name or URL (forwarded to 'assistant-ui create')\",\n ).hideHelp(),\n )\n .option(\"--use-npm\", \"explicitly use npm\")\n .option(\"--use-pnpm\", \"explicitly use pnpm\")\n .option(\"--use-yarn\", \"explicitly use yarn\")\n .option(\"--use-bun\", \"explicitly use bun\")\n .option(\"--skip-install\", \"skip installing packages\")\n .action(async (projectDirectory, opts) => {\n const cwd = opts.cwd;\n const presetUrl = opts.preset as string | undefined;\n const targetDir = projectDirectory\n ? path.resolve(cwd, projectDirectory)\n : cwd;\n\n const componentsConfigPath = path.join(targetDir, \"components.json\");\n\n if (!presetUrl && fs.existsSync(componentsConfigPath)) {\n logger.warn(\"Project is already initialized.\");\n logger.info(\"Use 'assistant-ui add' to add more components.\");\n return;\n }\n\n const packageJsonPath = path.join(targetDir, \"package.json\");\n const packageJsonExists = fs.existsSync(packageJsonPath);\n\n if (presetUrl || !packageJsonExists) {\n if (!presetUrl) {\n logger.info(\"No existing project found. Running 'create' instead...\");\n logger.break();\n }\n\n const createArgs: string[] = [];\n if (projectDirectory) createArgs.push(projectDirectory);\n if (presetUrl) createArgs.push(\"--preset\", presetUrl);\n if (opts.useNpm) createArgs.push(\"--use-npm\");\n if (opts.usePnpm) createArgs.push(\"--use-pnpm\");\n if (opts.useYarn) createArgs.push(\"--use-yarn\");\n if (opts.useBun) createArgs.push(\"--use-bun\");\n if (opts.skipInstall) createArgs.push(\"--skip-install\");\n\n await create.parseAsync(createArgs, { from: \"user\" });\n return;\n }\n\n logger.info(\"Initializing assistant-ui in existing project...\");\n logger.break();\n\n if (!opts.yes && isNonInteractiveShell()) {\n logger.error(\n [\n \"Detected a non-interactive shell, but 'assistant-ui init' needs interactive prompts by default.\",\n \"To run this in CI/agent mode, re-run with '--yes' so shadcn initialization and component install run non-interactively.\",\n \"Example: assistant-ui init --yes\",\n ].join(\"\\n\"),\n );\n process.exit(1);\n }\n\n try {\n const pm = await resolvePackageManagerForCwd(\n targetDir,\n resolvePackageManager(opts),\n );\n const [dlxCmd, dlxArgs] = dlxCommand(pm);\n\n const { initArgs, addArgs } = createExistingProjectInitPlan({\n yes: opts.yes,\n overwrite: opts.overwrite,\n });\n\n await runSpawn(dlxCmd, [...dlxArgs, ...initArgs], targetDir);\n const registryUrl = resolveQuickStartRegistryUrl(\n getComponentsJsonStyle(targetDir),\n );\n await runSpawn(dlxCmd, [...dlxArgs, ...addArgs, registryUrl], targetDir);\n\n logger.break();\n logger.success(\"Project initialized successfully!\");\n logger.info(\"You can now add more components with 'assistant-ui add'\");\n } catch (error) {\n if (error instanceof SpawnExitError) {\n logger.error(`Initialization failed with code ${error.code}`);\n process.exit(error.code);\n }\n const message = error instanceof Error ? error.message : String(error);\n logger.error(`Failed to initialize: ${message}`);\n process.exit(1);\n }\n });\n"],"mappings":"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"}
|
package/dist/commands/mcp.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcp.d.ts","names":[],"sources":["../../src/commands/mcp.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"mcp.d.ts","names":[],"sources":["../../src/commands/mcp.ts"],"mappings":";;cAoPa,KAAG"}
|
package/dist/commands/mcp.js
CHANGED
|
@@ -67,6 +67,13 @@ function deepMerge(target, source) {
|
|
|
67
67
|
else result[key] = source[key];
|
|
68
68
|
return result;
|
|
69
69
|
}
|
|
70
|
+
var McpConfigParseError = class extends Error {
|
|
71
|
+
constructor(targetName, configPath, flag) {
|
|
72
|
+
super(`Invalid ${targetName} MCP config JSON at ${configPath}. Fix the JSON syntax, then run: assistant-ui mcp ${flag}`);
|
|
73
|
+
this.name = "McpConfigParseError";
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
const getTargetFlag = (target) => `--${target}`;
|
|
70
77
|
async function installForTarget(target) {
|
|
71
78
|
if (target === "claude-code") {
|
|
72
79
|
logger.info("Installing MCP server for Claude Code...");
|
|
@@ -114,10 +121,13 @@ async function installForTarget(target) {
|
|
|
114
121
|
const content = fs.readFileSync(configPath, "utf-8");
|
|
115
122
|
try {
|
|
116
123
|
existingConfig = JSON.parse(content);
|
|
117
|
-
} catch
|
|
118
|
-
|
|
119
|
-
logger.error(
|
|
120
|
-
|
|
124
|
+
} catch {
|
|
125
|
+
const flag = getTargetFlag(target);
|
|
126
|
+
logger.error(`Could not parse ${targetConfig.name} MCP config.`);
|
|
127
|
+
logger.info(`Config path: ${configPath}`);
|
|
128
|
+
logger.info(`Fix the JSON syntax in that file, then run: assistant-ui mcp ${flag}`);
|
|
129
|
+
logger.info("No changes were written.");
|
|
130
|
+
throw new McpConfigParseError(targetConfig.name, configPath, flag);
|
|
121
131
|
}
|
|
122
132
|
}
|
|
123
133
|
const newConfig = deepMerge(existingConfig, targetConfig.config);
|