assistant-ui 0.0.104 → 0.0.106
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/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-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 +7 -4
- 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 +12 -4
- 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 +57 -21
- 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 +12 -15
- 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/lib/agent-skill.d.ts +0 -1
- package/dist/lib/agent-skill.d.ts.map +1 -1
- package/dist/lib/create-project.d.ts.map +1 -1
- package/dist/lib/create-project.js +23 -9
- 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 +24 -0
- package/dist/lib/utils/registry.js.map +1 -0
- package/dist/program.d.ts +0 -1
- package/dist/program.d.ts.map +1 -1
- package/package.json +10 -7
- package/src/commands/add.ts +8 -3
- package/src/commands/create.ts +12 -4
- package/src/commands/doctor.ts +83 -34
- package/src/commands/info.ts +32 -26
- 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 +46 -8
- package/src/lib/utils/registry.test.ts +108 -0
- package/src/lib/utils/registry.ts +39 -0
package/README.md
CHANGED
|
@@ -27,7 +27,7 @@ npx assistant-ui@latest create my-app
|
|
|
27
27
|
npx assistant-ui@latest create my-app --template minimal
|
|
28
28
|
|
|
29
29
|
# scaffold from a feature example
|
|
30
|
-
npx assistant-ui@latest create my-app --example with-ai-sdk-
|
|
30
|
+
npx assistant-ui@latest create my-app --example with-ai-sdk-v7
|
|
31
31
|
|
|
32
32
|
# scaffold an Expo / React Native project
|
|
33
33
|
npx assistant-ui@latest create my-app --native
|
|
@@ -58,7 +58,7 @@ npx assistant-ui info
|
|
|
58
58
|
|
|
59
59
|
## Templates
|
|
60
60
|
|
|
61
|
-
`create` scaffolds from named templates: `default` (AI SDK), `minimal`, `cloud`, `cloud-clerk`, `
|
|
61
|
+
`create` scaffolds from named templates: `default` (AI SDK), `minimal`, `cloud`, `cloud-clerk`, `langchain`, `mcp`, `eve`. Pass `-t <name>`, pass `--example <name>` for examples such as `with-ai-sdk-v7`, use `--native` for Expo / React Native, use `--ink` for React Ink, or pass `--preset <url>` to scaffold from an `assistant-ui.com` playground link.
|
|
62
62
|
|
|
63
63
|
## Documentation
|
|
64
64
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createTransformer.d.ts","names":[],"sources":["../../../src/codemods/utils/createTransformer.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"createTransformer.d.ts","names":[],"sources":["../../../src/codemods/utils/createTransformer.ts"],"mappings":";;KAEY,uBACV,SAAS,kBACT,UAAU,UACV,KAAK,KACL;UAGe;;;;EAIf,GAAG;;;;EAKH,MAAM;EAEN;;iBAGc,kBAAkB,aAAa,uBACjB,UAAU,UAAU,KAAK,KAAK"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"content-part-to-message-part.d.ts","names":[],"sources":["../../../src/codemods/v0-11/content-part-to-message-part.ts"],"mappings":";cAuEM
|
|
1
|
+
{"version":3,"file":"content-part-to-message-part.d.ts","names":[],"sources":["../../../src/codemods/v0-11/content-part-to-message-part.ts"],"mappings":";cAuEM,kCAA+B,yCAAA,UAAA,oCAAA,KAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"assistant-api-to-aui.d.ts","names":[],"sources":["../../../src/codemods/v0-12/assistant-api-to-aui.ts"],"mappings":";cAsFM,
|
|
1
|
+
{"version":3,"file":"assistant-api-to-aui.d.ts","names":[],"sources":["../../../src/codemods/v0-12/assistant-api-to-aui.ts"],"mappings":";cAsFM,2BAAwB,yCAAA,UAAA,oCAAA,KAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"event-names-to-camelcase.d.ts","names":[],"sources":["../../../src/codemods/v0-12/event-names-to-camelcase.ts"],"mappings":";cAYM,
|
|
1
|
+
{"version":3,"file":"event-names-to-camelcase.d.ts","names":[],"sources":["../../../src/codemods/v0-12/event-names-to-camelcase.ts"],"mappings":";cAYM,+BAA4B,yCAAA,UAAA,oCAAA,KAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"primitive-if-to-aui-if.d.ts","names":[],"sources":["../../../src/codemods/v0-12/primitive-if-to-aui-if.ts"],"mappings":";cAmKM,
|
|
1
|
+
{"version":3,"file":"primitive-if-to-aui-if.d.ts","names":[],"sources":["../../../src/codemods/v0-12/primitive-if-to-aui-if.ts"],"mappings":";cAmKM,4BAAyB,yCAAA,UAAA,oCAAA,KAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ui-package-split.d.ts","names":[],"sources":["../../../src/codemods/v0-8/ui-package-split.ts"],"mappings":";cA8BM,
|
|
1
|
+
{"version":3,"file":"ui-package-split.d.ts","names":[],"sources":["../../../src/codemods/v0-8/ui-package-split.ts"],"mappings":";cA8BM,qBAAkB,yCAAA,UAAA,oCAAA,KAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"edge-package-split.d.ts","names":[],"sources":["../../../src/codemods/v0-9/edge-package-split.ts"],"mappings":";cA8BM,
|
|
1
|
+
{"version":3,"file":"edge-package-split.d.ts","names":[],"sources":["../../../src/codemods/v0-9/edge-package-split.ts"],"mappings":";cA8BM,uBAAoB,yCAAA,UAAA,oCAAA,KAAA"}
|
package/dist/commands/add.d.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { PackageManagerName } from "../lib/create-project.js";
|
|
2
2
|
import { Command } from "commander";
|
|
3
|
-
|
|
4
3
|
//#region src/commands/add.d.ts
|
|
5
4
|
interface AddComponentsPlan {
|
|
6
5
|
command: string;
|
|
@@ -13,6 +12,7 @@ declare function createAddComponentsPlan(params: {
|
|
|
13
12
|
overwrite?: boolean;
|
|
14
13
|
cwd?: string;
|
|
15
14
|
path?: string;
|
|
15
|
+
style?: string;
|
|
16
16
|
}): AddComponentsPlan;
|
|
17
17
|
declare const add: Command;
|
|
18
18
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"add.d.ts","names":[],"sources":["../../src/commands/add.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"add.d.ts","names":[],"sources":["../../src/commands/add.ts"],"mappings":";;;UAeiB;EACf;EACA;;iBAGc,wBAAwB;EACtC;EACA,gBAAgB;EAChB;EACA;EACA;EACA;EACA;IACE;cAqBS,KAAG"}
|
package/dist/commands/add.js
CHANGED
|
@@ -2,13 +2,13 @@ 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 { hasConfig } from "../lib/utils/config.js";
|
|
5
|
+
import { getComponentsJsonStyle, resolveRegistryItemUrl } from "../lib/utils/registry.js";
|
|
5
6
|
import { Command } from "commander";
|
|
6
7
|
//#region src/commands/add.ts
|
|
7
|
-
const REGISTRY_BASE_URL = "https://r.assistant-ui.com";
|
|
8
8
|
function createAddComponentsPlan(params) {
|
|
9
9
|
const componentsToAdd = params.components.map((c) => {
|
|
10
10
|
if (!/^[a-zA-Z0-9-/]+$/.test(c)) throw new Error(`Invalid component name: ${c}`);
|
|
11
|
-
return
|
|
11
|
+
return resolveRegistryItemUrl(c, params.style);
|
|
12
12
|
});
|
|
13
13
|
const [command, dlxArgs] = dlxCommand(params.packageManager);
|
|
14
14
|
const args = [
|
|
@@ -32,13 +32,16 @@ const add = new Command().name("add").description("add a component to your proje
|
|
|
32
32
|
logger.break();
|
|
33
33
|
}
|
|
34
34
|
logger.step(`Adding ${components.length} component(s)...`);
|
|
35
|
+
const packageManager = await resolvePackageManagerForCwd(opts.cwd, resolvePackageManager(opts));
|
|
36
|
+
const style = getComponentsJsonStyle(opts.cwd);
|
|
35
37
|
const { command, args } = createAddComponentsPlan({
|
|
36
38
|
components,
|
|
37
|
-
packageManager
|
|
39
|
+
packageManager,
|
|
38
40
|
yes: opts.yes,
|
|
39
41
|
overwrite: opts.overwrite,
|
|
40
42
|
cwd: opts.cwd,
|
|
41
|
-
path: opts.path
|
|
43
|
+
path: opts.path,
|
|
44
|
+
...style === void 0 ? {} : { style }
|
|
42
45
|
});
|
|
43
46
|
try {
|
|
44
47
|
await runSpawn(command, args, opts.cwd);
|
package/dist/commands/add.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"add.js","names":[],"sources":["../../src/commands/add.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport { logger } from \"../lib/utils/logger\";\nimport { hasConfig } from \"../lib/utils/config\";\nimport {\n dlxCommand,\n resolvePackageManager,\n resolvePackageManagerForCwd,\n type PackageManagerName,\n} from \"../lib/create-project\";\nimport { runSpawn, SpawnExitError } from \"../lib/run-spawn\";\n\
|
|
1
|
+
{"version":3,"file":"add.js","names":[],"sources":["../../src/commands/add.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport { logger } from \"../lib/utils/logger\";\nimport { hasConfig } from \"../lib/utils/config\";\nimport {\n getComponentsJsonStyle,\n resolveRegistryItemUrl,\n} from \"../lib/utils/registry\";\nimport {\n dlxCommand,\n resolvePackageManager,\n resolvePackageManagerForCwd,\n type PackageManagerName,\n} from \"../lib/create-project\";\nimport { runSpawn, SpawnExitError } from \"../lib/run-spawn\";\n\nexport interface AddComponentsPlan {\n command: string;\n args: string[];\n}\n\nexport function createAddComponentsPlan(params: {\n components: string[];\n packageManager: PackageManagerName;\n yes?: boolean;\n overwrite?: boolean;\n cwd?: string;\n path?: string;\n style?: string;\n}): AddComponentsPlan {\n const componentsToAdd = params.components.map((c) => {\n if (!/^[a-zA-Z0-9-/]+$/.test(c)) {\n throw new Error(`Invalid component name: ${c}`);\n }\n return resolveRegistryItemUrl(c, params.style);\n });\n\n const [command, dlxArgs] = dlxCommand(params.packageManager);\n const args = [...dlxArgs, \"shadcn@latest\", \"add\", ...componentsToAdd];\n\n // For npm, dlxArgs may already include `--yes` for npx auto-install.\n // This flag is for shadcn's own confirmation prompt.\n if (params.yes) args.push(\"--yes\");\n if (params.overwrite) args.push(\"--overwrite\");\n if (params.cwd) args.push(\"--cwd\", params.cwd);\n if (params.path) args.push(\"--path\", params.path);\n\n return { command, args };\n}\n\nexport const add = new Command()\n .name(\"add\")\n .description(\"add a component to your project\")\n .argument(\"<components...>\", \"the components to add\")\n .option(\"-y, --yes\", \"skip confirmation prompt.\", true)\n .option(\"-o, --overwrite\", \"overwrite existing files.\", false)\n .option(\n \"-c, --cwd <cwd>\",\n \"the working directory. defaults to the current directory.\",\n process.cwd(),\n )\n .option(\"-p, --path <path>\", \"the path to add the component to.\")\n .option(\"--use-npm\", \"explicitly use npm\")\n .option(\"--use-pnpm\", \"explicitly use pnpm\")\n .option(\"--use-yarn\", \"explicitly use yarn\")\n .option(\"--use-bun\", \"explicitly use bun\")\n .action(async (components: string[], opts) => {\n // Check if project is initialized\n if (!hasConfig(opts.cwd)) {\n logger.warn(\n \"It looks like you haven't initialized your project yet. Run 'assistant-ui init' first.\",\n );\n logger.break();\n }\n\n logger.step(`Adding ${components.length} component(s)...`);\n\n const packageManager = await resolvePackageManagerForCwd(\n opts.cwd,\n resolvePackageManager(opts),\n );\n const style = getComponentsJsonStyle(opts.cwd);\n const { command, args } = createAddComponentsPlan({\n components,\n packageManager,\n yes: opts.yes,\n overwrite: opts.overwrite,\n cwd: opts.cwd,\n path: opts.path,\n ...(style === undefined ? {} : { style }),\n });\n\n try {\n await runSpawn(command, args, opts.cwd);\n } catch (error) {\n if (error instanceof SpawnExitError) {\n logger.error(`Process exited with code ${error.code}`);\n process.exit(error.code);\n }\n const message = error instanceof Error ? error.message : String(error);\n logger.error(`Failed to add components: ${message}`);\n process.exit(1);\n }\n\n logger.success(\"Components added successfully!\");\n });\n"],"mappings":";;;;;;;AAoBA,SAAgB,wBAAwB,QAQlB;CACpB,MAAM,kBAAkB,OAAO,WAAW,KAAK,MAAM;EACnD,IAAI,CAAC,mBAAmB,KAAK,CAAC,GAC5B,MAAM,IAAI,MAAM,2BAA2B,GAAG;EAEhD,OAAO,uBAAuB,GAAG,OAAO,KAAK;CAC/C,CAAC;CAED,MAAM,CAAC,SAAS,WAAW,WAAW,OAAO,cAAc;CAC3D,MAAM,OAAO;EAAC,GAAG;EAAS;EAAiB;EAAO,GAAG;CAAe;CAIpE,IAAI,OAAO,KAAK,KAAK,KAAK,OAAO;CACjC,IAAI,OAAO,WAAW,KAAK,KAAK,aAAa;CAC7C,IAAI,OAAO,KAAK,KAAK,KAAK,SAAS,OAAO,GAAG;CAC7C,IAAI,OAAO,MAAM,KAAK,KAAK,UAAU,OAAO,IAAI;CAEhD,OAAO;EAAE;EAAS;CAAK;AACzB;AAEA,MAAa,MAAM,IAAI,QAAQ,CAAC,CAC7B,KAAK,KAAK,CAAC,CACX,YAAY,iCAAiC,CAAC,CAC9C,SAAS,mBAAmB,uBAAuB,CAAC,CACpD,OAAO,aAAa,6BAA6B,IAAI,CAAC,CACtD,OAAO,mBAAmB,6BAA6B,KAAK,CAAC,CAC7D,OACC,mBACA,6DACA,QAAQ,IAAI,CACd,CAAC,CACA,OAAO,qBAAqB,mCAAmC,CAAC,CAChE,OAAO,aAAa,oBAAoB,CAAC,CACzC,OAAO,cAAc,qBAAqB,CAAC,CAC3C,OAAO,cAAc,qBAAqB,CAAC,CAC3C,OAAO,aAAa,oBAAoB,CAAC,CACzC,OAAO,OAAO,YAAsB,SAAS;CAE5C,IAAI,CAAC,UAAU,KAAK,GAAG,GAAG;EACxB,OAAO,KACL,wFACF;EACA,OAAO,MAAM;CACf;CAEA,OAAO,KAAK,UAAU,WAAW,OAAO,iBAAiB;CAEzD,MAAM,iBAAiB,MAAM,4BAC3B,KAAK,KACL,sBAAsB,IAAI,CAC5B;CACA,MAAM,QAAQ,uBAAuB,KAAK,GAAG;CAC7C,MAAM,EAAE,SAAS,SAAS,wBAAwB;EAChD;EACA;EACA,KAAK,KAAK;EACV,WAAW,KAAK;EAChB,KAAK,KAAK;EACV,MAAM,KAAK;EACX,GAAI,UAAU,KAAA,IAAY,CAAC,IAAI,EAAE,MAAM;CACzC,CAAC;CAED,IAAI;EACF,MAAM,SAAS,SAAS,MAAM,KAAK,GAAG;CACxC,SAAS,OAAO;EACd,IAAI,iBAAiB,gBAAgB;GACnC,OAAO,MAAM,4BAA4B,MAAM,MAAM;GACrD,QAAQ,KAAK,MAAM,IAAI;EACzB;EACA,MAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;EACrE,OAAO,MAAM,6BAA6B,SAAS;EACnD,QAAQ,KAAK,CAAC;CAChB;CAEA,OAAO,QAAQ,gCAAgC;AACjD,CAAC"}
|
package/dist/commands/agent.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent.d.ts","names":[],"sources":["../../src/commands/agent.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"agent.d.ts","names":[],"sources":["../../src/commands/agent.ts"],"mappings":";;cAuBa,OAAK"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create.d.ts","names":[],"sources":["../../src/commands/create.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"create.d.ts","names":[],"sources":["../../src/commands/create.ts"],"mappings":";;;UAqBiB;EACf;EACA;EACA;EACA;EACA;EACA;;cAGW,kBAAkB;iBA8PT,eAAe;EACnC;EACA;EACA;EACA,gBAAgB,EAAE;EAClB,kBAAkB,EAAE;IAClB,QAAQ;iBA2EI,8BAA8B;EAC5C;EACA;;iBAYc,iBAAiB;UAOhB;EACf;EACA;EACA;EACA;EACA;;UAGe;EACf;EACA;EACA;;iBAac,wBACd,MAAM,0BACL;cAoCU,QAAM"}
|
package/dist/commands/create.js
CHANGED
|
@@ -82,11 +82,11 @@ const PROJECT_METADATA = [
|
|
|
82
82
|
hasLocalComponents: false
|
|
83
83
|
},
|
|
84
84
|
{
|
|
85
|
-
name: "with-ai-sdk-
|
|
86
|
-
label: "AI SDK
|
|
87
|
-
description: "Vercel AI SDK
|
|
85
|
+
name: "with-ai-sdk-v7",
|
|
86
|
+
label: "AI SDK v7",
|
|
87
|
+
description: "Vercel AI SDK v7",
|
|
88
88
|
category: "example",
|
|
89
|
-
path: "examples/with-ai-sdk-
|
|
89
|
+
path: "examples/with-ai-sdk-v7",
|
|
90
90
|
hasLocalComponents: false
|
|
91
91
|
},
|
|
92
92
|
{
|
|
@@ -232,6 +232,14 @@ const PROJECT_METADATA = [
|
|
|
232
232
|
category: "example",
|
|
233
233
|
path: "examples/with-tanstack",
|
|
234
234
|
hasLocalComponents: false
|
|
235
|
+
},
|
|
236
|
+
{
|
|
237
|
+
name: "with-resumable-stream",
|
|
238
|
+
label: "Resumable Stream",
|
|
239
|
+
description: "Resumable LLM stream that survives reload mid-response",
|
|
240
|
+
category: "example",
|
|
241
|
+
path: "examples/with-resumable-stream",
|
|
242
|
+
hasLocalComponents: false
|
|
235
243
|
}
|
|
236
244
|
];
|
|
237
245
|
const templateNames = PROJECT_METADATA.filter((m) => m.category === "template").map((m) => m.name);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create.js","names":[],"sources":["../../src/commands/create.ts"],"sourcesContent":["import { Command, Option } from \"commander\";\nimport chalk from \"chalk\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport * as p from \"@clack/prompts\";\nimport { logger } from \"../lib/utils/logger\";\nimport {\n dlxCommand,\n downloadProject,\n resolveLatestReleaseRef,\n resolvePackageManager,\n resolvePackageManagerForCwd,\n scaffoldProject,\n transformProject,\n} from \"../lib/create-project\";\nimport { runSpawn, SpawnExitError } from \"../lib/run-spawn\";\nimport {\n buildSkillsAddCommand,\n resolveSkillsInstall,\n} from \"../lib/agent-skill\";\n\nexport interface ProjectMetadata {\n name: string;\n label: string;\n description?: string;\n category: \"template\" | \"example\";\n path: string;\n hasLocalComponents: boolean;\n}\n\nexport const PROJECT_METADATA: ProjectMetadata[] = [\n // Templates\n {\n name: \"default\",\n label: \"Default\",\n description: \"Default template with Vercel AI SDK\",\n category: \"template\",\n path: \"templates/default\",\n hasLocalComponents: false,\n },\n {\n name: \"minimal\",\n label: \"Minimal\",\n description: \"Bare-bones starting point\",\n category: \"template\",\n path: \"templates/minimal\",\n hasLocalComponents: true,\n },\n {\n name: \"cloud\",\n label: \"Cloud\",\n description: \"Cloud-backed persistence starter\",\n category: \"template\",\n path: \"templates/cloud\",\n hasLocalComponents: false,\n },\n {\n name: \"cloud-clerk\",\n label: \"Cloud + Clerk\",\n description: \"Cloud-backed starter with Clerk auth\",\n category: \"template\",\n path: \"templates/cloud-clerk\",\n hasLocalComponents: false,\n },\n {\n name: \"langchain\",\n label: \"LangChain\",\n description: \"LangGraph starter with the react-langchain adapter\",\n category: \"template\",\n path: \"templates/langchain\",\n hasLocalComponents: false,\n },\n {\n name: \"mcp\",\n label: \"MCP\",\n description: \"MCP tools + MCP Apps renderer starter\",\n category: \"template\",\n path: \"templates/mcp\",\n hasLocalComponents: false,\n },\n {\n name: \"eve\",\n label: \"Eve\",\n description: \"Eve agent + Next.js starter\",\n category: \"template\",\n path: \"templates/eve\",\n hasLocalComponents: false,\n },\n // Examples\n {\n name: \"with-ag-ui\",\n label: \"AG-UI\",\n description: \"AG-UI protocol integration\",\n category: \"example\",\n path: \"examples/with-ag-ui\",\n hasLocalComponents: false,\n },\n {\n name: \"with-google-adk\",\n label: \"Google ADK\",\n description: \"Google ADK agent integration\",\n category: \"example\",\n path: \"examples/with-google-adk\",\n hasLocalComponents: false,\n },\n {\n name: \"with-ai-sdk-v6\",\n label: \"AI SDK v6\",\n description: \"Vercel AI SDK v6\",\n category: \"example\",\n path: \"examples/with-ai-sdk-v6\",\n hasLocalComponents: false,\n },\n {\n name: \"with-eve\",\n label: \"Eve\",\n description: \"Eve agent integration\",\n category: \"example\",\n path: \"examples/with-eve\",\n hasLocalComponents: false,\n },\n {\n name: \"with-artifacts\",\n label: \"Artifacts\",\n description: \"Artifact rendering\",\n category: \"example\",\n path: \"examples/with-artifacts\",\n hasLocalComponents: false,\n },\n {\n name: \"with-assistant-transport\",\n label: \"Assistant Transport\",\n description: \"Assistant transport protocol\",\n category: \"example\",\n path: \"examples/with-assistant-transport\",\n hasLocalComponents: false,\n },\n {\n name: \"with-chain-of-thought\",\n label: \"Chain of Thought\",\n description: \"Chain-of-thought, tool calls, and source citations\",\n category: \"example\",\n path: \"examples/with-chain-of-thought\",\n hasLocalComponents: false,\n },\n {\n name: \"with-cloud\",\n label: \"Cloud Example\",\n description: \"Cloud integration example\",\n category: \"example\",\n path: \"examples/with-cloud\",\n hasLocalComponents: false,\n },\n {\n name: \"with-custom-thread-list\",\n label: \"Custom Thread List\",\n description: \"Custom thread list UI\",\n category: \"example\",\n path: \"examples/with-custom-thread-list\",\n hasLocalComponents: false,\n },\n {\n name: \"with-elevenlabs-conversational\",\n label: \"ElevenLabs Conversational\",\n description: \"Realtime voice with ElevenLabs\",\n category: \"example\",\n path: \"examples/with-elevenlabs-conversational\",\n hasLocalComponents: true,\n },\n {\n name: \"with-elevenlabs-scribe\",\n label: \"ElevenLabs Scribe\",\n description: \"Audio/speech integration\",\n category: \"example\",\n path: \"examples/with-elevenlabs-scribe\",\n hasLocalComponents: false,\n },\n {\n name: \"with-livekit\",\n label: \"LiveKit Voice\",\n description: \"Realtime voice with LiveKit\",\n category: \"example\",\n path: \"examples/with-livekit\",\n hasLocalComponents: true,\n },\n {\n name: \"with-expo\",\n label: \"Expo\",\n description: \"Expo / React Native\",\n category: \"example\",\n path: \"examples/with-expo\",\n hasLocalComponents: true,\n },\n {\n name: \"with-interactables\",\n label: \"Interactables\",\n description: \"AI-driven interactive UI components\",\n category: \"example\",\n path: \"examples/with-interactables\",\n hasLocalComponents: true,\n },\n {\n name: \"with-external-store\",\n label: \"External Store\",\n description: \"Custom message store\",\n category: \"example\",\n path: \"examples/with-external-store\",\n hasLocalComponents: false,\n },\n {\n name: \"with-ffmpeg\",\n label: \"FFmpeg\",\n description: \"File processing\",\n category: \"example\",\n path: \"examples/with-ffmpeg\",\n hasLocalComponents: false,\n },\n {\n name: \"with-langgraph\",\n label: \"LangGraph Example\",\n description: \"LangGraph integration\",\n category: \"example\",\n path: \"examples/with-langgraph\",\n hasLocalComponents: false,\n },\n {\n name: \"with-react-hook-form\",\n label: \"React Hook Form\",\n description: \"Form integration\",\n category: \"example\",\n path: \"examples/with-react-hook-form\",\n hasLocalComponents: false,\n },\n {\n name: \"with-react-ink\",\n label: \"React Ink\",\n description: \"Terminal UI chat\",\n category: \"example\",\n path: \"examples/with-react-ink\",\n hasLocalComponents: true,\n },\n {\n name: \"with-react-router\",\n label: \"React Router\",\n description: \"React Router v7 + Vite\",\n category: \"example\",\n path: \"examples/with-react-router\",\n hasLocalComponents: false,\n },\n {\n name: \"with-tanstack\",\n label: \"TanStack\",\n description: \"TanStack/React Router + Vite\",\n category: \"example\",\n path: \"examples/with-tanstack\",\n hasLocalComponents: false,\n },\n];\n\n// Examples that exist in the monorepo but are intentionally excluded from the CLI:\n//\n// - waterfall: Still in development, not ready for production.\n// - with-cloud-standalone: For cloud without assistant-ui — not for the\n// assistant-ui CLI.\n// - with-store: In development, not ready for public use of the tap store.\n// - with-tap-runtime: In development, not ready for public use of the tap\n// store.\n\nconst templateNames = PROJECT_METADATA.filter(\n (m) => m.category === \"template\",\n).map((m) => m.name);\n\nconst exampleNames = PROJECT_METADATA.filter(\n (m) => m.category === \"example\",\n).map((m) => m.name);\n\nexport async function resolveProject(params: {\n template?: string;\n example?: string;\n stdinIsTTY?: boolean;\n select?: typeof p.select;\n isCancel?: typeof p.isCancel;\n}): Promise<ProjectMetadata | null> {\n const {\n template,\n example,\n stdinIsTTY = process.stdin.isTTY,\n select = p.select,\n isCancel = p.isCancel,\n } = params;\n\n if (template !== undefined) {\n const meta = PROJECT_METADATA.find(\n (m) => m.name === template && m.category === \"template\",\n );\n if (!meta) {\n logger.error(`Unknown template: ${template}`);\n logger.info(`Available templates: ${templateNames.join(\", \")}`);\n process.exit(1);\n }\n return meta;\n }\n\n if (example !== undefined) {\n const meta = PROJECT_METADATA.find(\n (m) => m.name === example && m.category === \"example\",\n );\n if (!meta) {\n logger.error(`Unknown example: ${example}`);\n logger.info(`Available examples: ${exampleNames.join(\", \")}`);\n process.exit(1);\n }\n return meta;\n }\n\n if (!stdinIsTTY) {\n return PROJECT_METADATA.find((m) => m.name === \"default\")!;\n }\n\n const selected = await select({\n message: \"Select a project to scaffold:\",\n options: [\n {\n value: \"_separator\",\n label: \"────── Starter Templates ──────\",\n disabled: true,\n },\n ...PROJECT_METADATA.filter((m) => m.category === \"template\").map((m) => ({\n value: m.name,\n label: m.label,\n ...(m.description ? { hint: m.description } : {}),\n })),\n {\n value: \"_separator\",\n label: \"────── Feature Examples ──────\",\n disabled: true,\n },\n ...PROJECT_METADATA.filter((m) => m.category === \"example\").map((m) => ({\n value: m.name,\n label: m.label,\n ...(m.description ? { hint: m.description } : {}),\n })),\n ],\n });\n\n if (isCancel(selected)) {\n return null;\n }\n\n const meta = PROJECT_METADATA.find((m) => m.name === selected);\n if (!meta) {\n logger.error(`Unknown selection: ${String(selected)}`);\n process.exit(1);\n }\n return meta;\n}\n\nexport function resolveCreateProjectDirectory(params: {\n projectDirectory?: string;\n stdinIsTTY?: boolean;\n}): string | undefined {\n const { projectDirectory, stdinIsTTY = process.stdin.isTTY } = params;\n\n if (projectDirectory) return projectDirectory;\n if (!stdinIsTTY) return \"my-aui-app\";\n return undefined;\n}\n\nconst PLAYGROUND_PRESET_BASE_URL =\n \"https://www.assistant-ui.com/playground/init\";\n\nexport function resolvePresetUrl(preset: string): string {\n if (preset.startsWith(\"http://\") || preset.startsWith(\"https://\")) {\n return preset;\n }\n return `${PLAYGROUND_PRESET_BASE_URL}?preset=${encodeURIComponent(preset)}`;\n}\n\nexport interface ScaffoldSelectorOptions {\n template?: string;\n example?: string;\n preset?: string;\n native?: boolean;\n ink?: boolean;\n}\n\nexport interface ResolvedScaffoldSelector {\n template?: string;\n example?: string;\n preset?: string;\n}\n\nconst scaffoldSelectorHelp =\n \"Choose one scaffold selector: --template <name>, --example <name>, --native, or --ink. --preset <name-or-url> can be used with --template or by itself.\";\n\nfunction getPresetConflict(opts: ScaffoldSelectorOptions): string | undefined {\n if (opts.example !== undefined) return \"--example\";\n if (opts.native) return \"--native\";\n if (opts.ink) return \"--ink\";\n return undefined;\n}\n\nexport function resolveScaffoldSelector(\n opts: ScaffoldSelectorOptions,\n): ResolvedScaffoldSelector {\n const hasPreset = opts.preset !== undefined;\n const presetConflict = getPresetConflict(opts);\n const selectors = [\n opts.template !== undefined ? \"--template\" : undefined,\n opts.example !== undefined ? \"--example\" : undefined,\n opts.native ? \"--native\" : undefined,\n opts.ink ? \"--ink\" : undefined,\n ].filter((selector): selector is string => selector !== undefined);\n\n if (selectors.length > 1) {\n throw new Error(\n `Only one scaffold selector can be provided (${selectors.join(\", \")}). ${scaffoldSelectorHelp}`,\n );\n }\n\n if (hasPreset && presetConflict) {\n throw new Error(\n `Cannot use --preset with ${presetConflict}. ${scaffoldSelectorHelp}`,\n );\n }\n\n if (opts.native) return { example: \"with-expo\" };\n if (opts.ink) return { example: \"with-react-ink\" };\n\n if (opts.preset !== undefined && opts.template === undefined) {\n return { template: \"default\", preset: opts.preset };\n }\n\n return {\n ...(opts.template !== undefined && { template: opts.template }),\n ...(opts.example !== undefined && { example: opts.example }),\n ...(hasPreset && { preset: opts.preset }),\n };\n}\n\nexport const create = new Command()\n .name(\"create\")\n .description(\"create a new project\")\n .argument(\"[project-directory]\")\n .usage(`${chalk.green(\"[project-directory]\")} [options]`)\n .option(\n \"-t, --template <template>\",\n `template to use (${templateNames.join(\", \")})`,\n )\n .option(\n \"-e, --example <example>\",\n `create from an example (${exampleNames.join(\", \")})`,\n )\n .option(\n \"-p, --preset <name-or-url>\",\n \"preset name or URL (e.g., chatgpt or https://www.assistant-ui.com/playground/init?preset=chatgpt)\",\n )\n .option(\"--use-npm\", \"explicitly use npm\")\n .option(\"--use-pnpm\", \"explicitly use pnpm\")\n .option(\"--use-yarn\", \"explicitly use yarn\")\n .option(\"--use-bun\", \"explicitly use bun\")\n .option(\"--native\", \"create an Expo / React Native project\")\n .option(\"--ink\", \"create a React Ink terminal project\")\n .option(\"--skip-install\", \"skip installing packages\")\n .option(\"--skills\", \"add assistant-ui agent skills for AI coding assistants\")\n .option(\"--no-skills\", \"skip adding assistant-ui agent skills\")\n .addOption(\n new Option(\n \"--debug-source-root <path>\",\n \"copy templates/examples from a local assistant-ui repo root\",\n ).hideHelp(),\n )\n .action(async (projectDirectory, opts) => {\n let scaffoldSelector: ResolvedScaffoldSelector;\n try {\n scaffoldSelector = resolveScaffoldSelector(opts);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n logger.error(message);\n process.exit(1);\n }\n\n const localSourceRoot = opts.debugSourceRoot\n ? path.resolve(opts.debugSourceRoot)\n : undefined;\n\n // Start release ref resolution early (runs during user prompts)\n const refPromise = localSourceRoot\n ? Promise.resolve(undefined)\n : resolveLatestReleaseRef();\n\n // 1. Resolve project directory\n let resolvedProjectDirectory = resolveCreateProjectDirectory({\n projectDirectory,\n });\n\n if (!resolvedProjectDirectory) {\n const result = await p.text({\n message: \"Project name:\",\n placeholder: \"my-aui-app\",\n defaultValue: \"my-aui-app\",\n validate: (value?: string) => {\n const name = (value ?? \"\").trim();\n if (!name) return \"Project name cannot be empty\";\n if (name === \".\" || name === \"..\")\n return \"Project name cannot be . or ..\";\n if (name.includes(\"/\") || name.includes(\"\\\\\"))\n return \"Project name cannot contain path separators\";\n return undefined;\n },\n });\n\n if (p.isCancel(result)) {\n p.cancel(\"Project creation cancelled.\");\n process.exit(0);\n }\n\n resolvedProjectDirectory = result;\n }\n\n // Check directory\n const absoluteProjectDir = path.resolve(resolvedProjectDirectory);\n try {\n const files = fs.readdirSync(absoluteProjectDir);\n if (files.length > 0) {\n logger.error(\n `Directory ${resolvedProjectDirectory} already exists and is not empty`,\n );\n process.exit(1);\n }\n } catch (err: unknown) {\n const code =\n err instanceof Error ? (err as NodeJS.ErrnoException).code : undefined;\n if (code === \"ENOENT\") {\n // Directory doesn't exist — good, proceed\n } else if (code === \"ENOTDIR\") {\n logger.error(\n `${resolvedProjectDirectory} already exists and is not a directory`,\n );\n process.exit(1);\n } else {\n const message = err instanceof Error ? err.message : String(err);\n logger.error(`Cannot access ${resolvedProjectDirectory}: ${message}`);\n process.exit(1);\n }\n }\n\n // 2. Resolve scaffold target\n const project = await resolveProject(scaffoldSelector);\n if (!project) {\n p.cancel(\"Project creation cancelled.\");\n process.exit(0);\n }\n\n const stdinIsTTY = process.stdin.isTTY;\n let installSkills = resolveSkillsInstall({\n skills: opts.skills,\n stdinIsTTY,\n });\n if (installSkills === undefined) {\n const result = await p.confirm({\n message: \"Add assistant-ui agent skills for AI coding assistants?\",\n initialValue: true,\n });\n\n if (p.isCancel(result)) {\n p.cancel(\"Project creation cancelled.\");\n process.exit(0);\n }\n\n installSkills = result;\n }\n\n logger.info(`Creating project from ${project.category}: ${project.label}`);\n logger.break();\n\n const pm = await resolvePackageManagerForCwd(\n path.dirname(absoluteProjectDir),\n resolvePackageManager(opts),\n );\n\n // Clean up partial project directory on unexpected exit (e.g. Ctrl+C)\n const cleanupOnExit = () => {\n fs.rmSync(absoluteProjectDir, { recursive: true, force: true });\n };\n process.once(\"exit\", cleanupOnExit);\n\n try {\n // 3. Resolve latest release ref (started before prompts)\n if (!localSourceRoot) {\n logger.step(\"Resolving latest release...\");\n }\n const ref = await refPromise;\n if (!localSourceRoot && !ref) {\n logger.warn(\"Could not resolve latest release, downloading from HEAD\");\n }\n\n // 4. Scaffold project\n logger.step(\n localSourceRoot\n ? `Copying project from local source: ${localSourceRoot}`\n : \"Downloading project...\",\n );\n try {\n const source = localSourceRoot\n ? { kind: \"local\" as const, rootDir: localSourceRoot }\n : {\n kind: \"github\" as const,\n ref,\n };\n await scaffoldProject(project.path, absoluteProjectDir, source);\n\n // If the template didn't exist at the release tag, retry from HEAD\n if (\n !localSourceRoot &&\n ref &&\n !fs.existsSync(path.join(absoluteProjectDir, \"package.json\"))\n ) {\n fs.rmSync(absoluteProjectDir, { recursive: true, force: true });\n logger.warn(\n \"Template not found at release tag, downloading from HEAD\",\n );\n await downloadProject(project.path, absoluteProjectDir);\n }\n\n // 5. Run transform pipeline\n await transformProject(absoluteProjectDir, {\n hasLocalComponents: project.hasLocalComponents,\n skipInstall: opts.skipInstall,\n packageManager: pm,\n });\n\n if (installSkills) {\n logger.step(\"Adding assistant-ui agent skills...\");\n const [skillsCmd, skillsArgs] = buildSkillsAddCommand(pm, {\n stdinIsTTY,\n });\n try {\n await runSpawn(skillsCmd, skillsArgs, absoluteProjectDir);\n } catch {\n logger.warn(\n `Could not add assistant-ui agent skills. You can add them later with:\\n ${skillsCmd} ${skillsArgs.join(\" \")}`,\n );\n }\n }\n } catch (err) {\n // Clean up partially created project directory\n fs.rmSync(absoluteProjectDir, { recursive: true, force: true });\n throw err;\n }\n\n // 6. Apply preset if provided\n if (scaffoldSelector.preset) {\n const presetUrl = resolvePresetUrl(scaffoldSelector.preset);\n logger.info(\"Applying preset configuration...\");\n logger.break();\n const [dlxCmd, dlxArgs] = dlxCommand(pm);\n try {\n await runSpawn(\n dlxCmd,\n [\n ...dlxArgs,\n \"shadcn@latest\",\n \"add\",\n \"--yes\",\n \"--overwrite\",\n presetUrl,\n ],\n absoluteProjectDir,\n );\n } catch {\n logger.warn(\n `Preset application failed. You can retry manually with:\\n ${dlxCmd} ${[...dlxArgs, \"shadcn@latest\", \"add\", presetUrl].join(\" \")}`,\n );\n }\n }\n\n process.removeListener(\"exit\", cleanupOnExit);\n\n logger.break();\n logger.success(\"Project created successfully!\");\n logger.break();\n const runCmd = pm === \"npm\" ? \"npm run\" : pm;\n let devScript = \"dev\";\n let envFile = \".env.local\";\n try {\n const scaffoldedPkg = JSON.parse(\n fs.readFileSync(\n path.join(absoluteProjectDir, \"package.json\"),\n \"utf-8\",\n ),\n );\n devScript = scaffoldedPkg.scripts?.dev\n ? \"dev\"\n : scaffoldedPkg.scripts?.start\n ? \"start\"\n : \"dev\";\n envFile = scaffoldedPkg.dependencies?.next ? \".env.local\" : \".env\";\n } catch {\n // Fall back to defaults if package.json cannot be read\n }\n\n logger.info(\"Next steps:\");\n logger.info(` cd ${resolvedProjectDirectory}`);\n if (opts.skipInstall) {\n logger.info(` ${pm} install`);\n }\n logger.info(` # Set up your environment variables in ${envFile}`);\n logger.info(` ${runCmd} ${devScript}`);\n } catch (error) {\n if (error instanceof SpawnExitError) {\n logger.error(`Project creation failed with code ${error.code}`);\n process.exit(error.code);\n }\n const message = error instanceof Error ? error.message : String(error);\n logger.error(`Failed to create project: ${message}`);\n process.exit(1);\n }\n });\n"],"mappings":";;;;;;;;;;AA8BA,MAAa,mBAAsC;CAEjD;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CAEA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CAC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"}
|
|
1
|
+
{"version":3,"file":"create.js","names":[],"sources":["../../src/commands/create.ts"],"sourcesContent":["import { Command, Option } from \"commander\";\nimport chalk from \"chalk\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport * as p from \"@clack/prompts\";\nimport { logger } from \"../lib/utils/logger\";\nimport {\n dlxCommand,\n downloadProject,\n resolveLatestReleaseRef,\n resolvePackageManager,\n resolvePackageManagerForCwd,\n scaffoldProject,\n transformProject,\n} from \"../lib/create-project\";\nimport { runSpawn, SpawnExitError } from \"../lib/run-spawn\";\nimport {\n buildSkillsAddCommand,\n resolveSkillsInstall,\n} from \"../lib/agent-skill\";\n\nexport interface ProjectMetadata {\n name: string;\n label: string;\n description?: string;\n category: \"template\" | \"example\";\n path: string;\n hasLocalComponents: boolean;\n}\n\nexport const PROJECT_METADATA: ProjectMetadata[] = [\n // Templates\n {\n name: \"default\",\n label: \"Default\",\n description: \"Default template with Vercel AI SDK\",\n category: \"template\",\n path: \"templates/default\",\n hasLocalComponents: false,\n },\n {\n name: \"minimal\",\n label: \"Minimal\",\n description: \"Bare-bones starting point\",\n category: \"template\",\n path: \"templates/minimal\",\n hasLocalComponents: true,\n },\n {\n name: \"cloud\",\n label: \"Cloud\",\n description: \"Cloud-backed persistence starter\",\n category: \"template\",\n path: \"templates/cloud\",\n hasLocalComponents: false,\n },\n {\n name: \"cloud-clerk\",\n label: \"Cloud + Clerk\",\n description: \"Cloud-backed starter with Clerk auth\",\n category: \"template\",\n path: \"templates/cloud-clerk\",\n hasLocalComponents: false,\n },\n {\n name: \"langchain\",\n label: \"LangChain\",\n description: \"LangGraph starter with the react-langchain adapter\",\n category: \"template\",\n path: \"templates/langchain\",\n hasLocalComponents: false,\n },\n {\n name: \"mcp\",\n label: \"MCP\",\n description: \"MCP tools + MCP Apps renderer starter\",\n category: \"template\",\n path: \"templates/mcp\",\n hasLocalComponents: false,\n },\n {\n name: \"eve\",\n label: \"Eve\",\n description: \"Eve agent + Next.js starter\",\n category: \"template\",\n path: \"templates/eve\",\n hasLocalComponents: false,\n },\n // Examples\n {\n name: \"with-ag-ui\",\n label: \"AG-UI\",\n description: \"AG-UI protocol integration\",\n category: \"example\",\n path: \"examples/with-ag-ui\",\n hasLocalComponents: false,\n },\n {\n name: \"with-google-adk\",\n label: \"Google ADK\",\n description: \"Google ADK agent integration\",\n category: \"example\",\n path: \"examples/with-google-adk\",\n hasLocalComponents: false,\n },\n {\n name: \"with-ai-sdk-v7\",\n label: \"AI SDK v7\",\n description: \"Vercel AI SDK v7\",\n category: \"example\",\n path: \"examples/with-ai-sdk-v7\",\n hasLocalComponents: false,\n },\n {\n name: \"with-eve\",\n label: \"Eve\",\n description: \"Eve agent integration\",\n category: \"example\",\n path: \"examples/with-eve\",\n hasLocalComponents: false,\n },\n {\n name: \"with-artifacts\",\n label: \"Artifacts\",\n description: \"Artifact rendering\",\n category: \"example\",\n path: \"examples/with-artifacts\",\n hasLocalComponents: false,\n },\n {\n name: \"with-assistant-transport\",\n label: \"Assistant Transport\",\n description: \"Assistant transport protocol\",\n category: \"example\",\n path: \"examples/with-assistant-transport\",\n hasLocalComponents: false,\n },\n {\n name: \"with-chain-of-thought\",\n label: \"Chain of Thought\",\n description: \"Chain-of-thought, tool calls, and source citations\",\n category: \"example\",\n path: \"examples/with-chain-of-thought\",\n hasLocalComponents: false,\n },\n {\n name: \"with-cloud\",\n label: \"Cloud Example\",\n description: \"Cloud integration example\",\n category: \"example\",\n path: \"examples/with-cloud\",\n hasLocalComponents: false,\n },\n {\n name: \"with-custom-thread-list\",\n label: \"Custom Thread List\",\n description: \"Custom thread list UI\",\n category: \"example\",\n path: \"examples/with-custom-thread-list\",\n hasLocalComponents: false,\n },\n {\n name: \"with-elevenlabs-conversational\",\n label: \"ElevenLabs Conversational\",\n description: \"Realtime voice with ElevenLabs\",\n category: \"example\",\n path: \"examples/with-elevenlabs-conversational\",\n hasLocalComponents: true,\n },\n {\n name: \"with-elevenlabs-scribe\",\n label: \"ElevenLabs Scribe\",\n description: \"Audio/speech integration\",\n category: \"example\",\n path: \"examples/with-elevenlabs-scribe\",\n hasLocalComponents: false,\n },\n {\n name: \"with-livekit\",\n label: \"LiveKit Voice\",\n description: \"Realtime voice with LiveKit\",\n category: \"example\",\n path: \"examples/with-livekit\",\n hasLocalComponents: true,\n },\n {\n name: \"with-expo\",\n label: \"Expo\",\n description: \"Expo / React Native\",\n category: \"example\",\n path: \"examples/with-expo\",\n hasLocalComponents: true,\n },\n {\n name: \"with-interactables\",\n label: \"Interactables\",\n description: \"AI-driven interactive UI components\",\n category: \"example\",\n path: \"examples/with-interactables\",\n hasLocalComponents: true,\n },\n {\n name: \"with-external-store\",\n label: \"External Store\",\n description: \"Custom message store\",\n category: \"example\",\n path: \"examples/with-external-store\",\n hasLocalComponents: false,\n },\n {\n name: \"with-ffmpeg\",\n label: \"FFmpeg\",\n description: \"File processing\",\n category: \"example\",\n path: \"examples/with-ffmpeg\",\n hasLocalComponents: false,\n },\n {\n name: \"with-langgraph\",\n label: \"LangGraph Example\",\n description: \"LangGraph integration\",\n category: \"example\",\n path: \"examples/with-langgraph\",\n hasLocalComponents: false,\n },\n {\n name: \"with-react-hook-form\",\n label: \"React Hook Form\",\n description: \"Form integration\",\n category: \"example\",\n path: \"examples/with-react-hook-form\",\n hasLocalComponents: false,\n },\n {\n name: \"with-react-ink\",\n label: \"React Ink\",\n description: \"Terminal UI chat\",\n category: \"example\",\n path: \"examples/with-react-ink\",\n hasLocalComponents: true,\n },\n {\n name: \"with-react-router\",\n label: \"React Router\",\n description: \"React Router v7 + Vite\",\n category: \"example\",\n path: \"examples/with-react-router\",\n hasLocalComponents: false,\n },\n {\n name: \"with-tanstack\",\n label: \"TanStack\",\n description: \"TanStack/React Router + Vite\",\n category: \"example\",\n path: \"examples/with-tanstack\",\n hasLocalComponents: false,\n },\n {\n name: \"with-resumable-stream\",\n label: \"Resumable Stream\",\n description: \"Resumable LLM stream that survives reload mid-response\",\n category: \"example\",\n path: \"examples/with-resumable-stream\",\n hasLocalComponents: false,\n },\n];\n\n// Examples that exist in the monorepo but are intentionally excluded from the CLI:\n//\n// - waterfall: Still in development, not ready for production.\n// - with-cloud-standalone: For cloud without assistant-ui — not for the\n// assistant-ui CLI.\n// - with-store: In development, not ready for public use of the tap store.\n// - with-tap-runtime: In development, not ready for public use of the tap\n// store.\n\nconst templateNames = PROJECT_METADATA.filter(\n (m) => m.category === \"template\",\n).map((m) => m.name);\n\nconst exampleNames = PROJECT_METADATA.filter(\n (m) => m.category === \"example\",\n).map((m) => m.name);\n\nexport async function resolveProject(params: {\n template?: string;\n example?: string;\n stdinIsTTY?: boolean;\n select?: typeof p.select;\n isCancel?: typeof p.isCancel;\n}): Promise<ProjectMetadata | null> {\n const {\n template,\n example,\n stdinIsTTY = process.stdin.isTTY,\n select = p.select,\n isCancel = p.isCancel,\n } = params;\n\n if (template !== undefined) {\n const meta = PROJECT_METADATA.find(\n (m) => m.name === template && m.category === \"template\",\n );\n if (!meta) {\n logger.error(`Unknown template: ${template}`);\n logger.info(`Available templates: ${templateNames.join(\", \")}`);\n process.exit(1);\n }\n return meta;\n }\n\n if (example !== undefined) {\n const meta = PROJECT_METADATA.find(\n (m) => m.name === example && m.category === \"example\",\n );\n if (!meta) {\n logger.error(`Unknown example: ${example}`);\n logger.info(`Available examples: ${exampleNames.join(\", \")}`);\n process.exit(1);\n }\n return meta;\n }\n\n if (!stdinIsTTY) {\n return PROJECT_METADATA.find((m) => m.name === \"default\")!;\n }\n\n const selected = await select({\n message: \"Select a project to scaffold:\",\n options: [\n {\n value: \"_separator\",\n label: \"────── Starter Templates ──────\",\n disabled: true,\n },\n ...PROJECT_METADATA.filter((m) => m.category === \"template\").map((m) => ({\n value: m.name,\n label: m.label,\n ...(m.description ? { hint: m.description } : {}),\n })),\n {\n value: \"_separator\",\n label: \"────── Feature Examples ──────\",\n disabled: true,\n },\n ...PROJECT_METADATA.filter((m) => m.category === \"example\").map((m) => ({\n value: m.name,\n label: m.label,\n ...(m.description ? { hint: m.description } : {}),\n })),\n ],\n });\n\n if (isCancel(selected)) {\n return null;\n }\n\n const meta = PROJECT_METADATA.find((m) => m.name === selected);\n if (!meta) {\n logger.error(`Unknown selection: ${String(selected)}`);\n process.exit(1);\n }\n return meta;\n}\n\nexport function resolveCreateProjectDirectory(params: {\n projectDirectory?: string;\n stdinIsTTY?: boolean;\n}): string | undefined {\n const { projectDirectory, stdinIsTTY = process.stdin.isTTY } = params;\n\n if (projectDirectory) return projectDirectory;\n if (!stdinIsTTY) return \"my-aui-app\";\n return undefined;\n}\n\nconst PLAYGROUND_PRESET_BASE_URL =\n \"https://www.assistant-ui.com/playground/init\";\n\nexport function resolvePresetUrl(preset: string): string {\n if (preset.startsWith(\"http://\") || preset.startsWith(\"https://\")) {\n return preset;\n }\n return `${PLAYGROUND_PRESET_BASE_URL}?preset=${encodeURIComponent(preset)}`;\n}\n\nexport interface ScaffoldSelectorOptions {\n template?: string;\n example?: string;\n preset?: string;\n native?: boolean;\n ink?: boolean;\n}\n\nexport interface ResolvedScaffoldSelector {\n template?: string;\n example?: string;\n preset?: string;\n}\n\nconst scaffoldSelectorHelp =\n \"Choose one scaffold selector: --template <name>, --example <name>, --native, or --ink. --preset <name-or-url> can be used with --template or by itself.\";\n\nfunction getPresetConflict(opts: ScaffoldSelectorOptions): string | undefined {\n if (opts.example !== undefined) return \"--example\";\n if (opts.native) return \"--native\";\n if (opts.ink) return \"--ink\";\n return undefined;\n}\n\nexport function resolveScaffoldSelector(\n opts: ScaffoldSelectorOptions,\n): ResolvedScaffoldSelector {\n const hasPreset = opts.preset !== undefined;\n const presetConflict = getPresetConflict(opts);\n const selectors = [\n opts.template !== undefined ? \"--template\" : undefined,\n opts.example !== undefined ? \"--example\" : undefined,\n opts.native ? \"--native\" : undefined,\n opts.ink ? \"--ink\" : undefined,\n ].filter((selector): selector is string => selector !== undefined);\n\n if (selectors.length > 1) {\n throw new Error(\n `Only one scaffold selector can be provided (${selectors.join(\", \")}). ${scaffoldSelectorHelp}`,\n );\n }\n\n if (hasPreset && presetConflict) {\n throw new Error(\n `Cannot use --preset with ${presetConflict}. ${scaffoldSelectorHelp}`,\n );\n }\n\n if (opts.native) return { example: \"with-expo\" };\n if (opts.ink) return { example: \"with-react-ink\" };\n\n if (opts.preset !== undefined && opts.template === undefined) {\n return { template: \"default\", preset: opts.preset };\n }\n\n return {\n ...(opts.template !== undefined && { template: opts.template }),\n ...(opts.example !== undefined && { example: opts.example }),\n ...(hasPreset && { preset: opts.preset }),\n };\n}\n\nexport const create = new Command()\n .name(\"create\")\n .description(\"create a new project\")\n .argument(\"[project-directory]\")\n .usage(`${chalk.green(\"[project-directory]\")} [options]`)\n .option(\n \"-t, --template <template>\",\n `template to use (${templateNames.join(\", \")})`,\n )\n .option(\n \"-e, --example <example>\",\n `create from an example (${exampleNames.join(\", \")})`,\n )\n .option(\n \"-p, --preset <name-or-url>\",\n \"preset name or URL (e.g., chatgpt or https://www.assistant-ui.com/playground/init?preset=chatgpt)\",\n )\n .option(\"--use-npm\", \"explicitly use npm\")\n .option(\"--use-pnpm\", \"explicitly use pnpm\")\n .option(\"--use-yarn\", \"explicitly use yarn\")\n .option(\"--use-bun\", \"explicitly use bun\")\n .option(\"--native\", \"create an Expo / React Native project\")\n .option(\"--ink\", \"create a React Ink terminal project\")\n .option(\"--skip-install\", \"skip installing packages\")\n .option(\"--skills\", \"add assistant-ui agent skills for AI coding assistants\")\n .option(\"--no-skills\", \"skip adding assistant-ui agent skills\")\n .addOption(\n new Option(\n \"--debug-source-root <path>\",\n \"copy templates/examples from a local assistant-ui repo root\",\n ).hideHelp(),\n )\n .action(async (projectDirectory, opts) => {\n let scaffoldSelector: ResolvedScaffoldSelector;\n try {\n scaffoldSelector = resolveScaffoldSelector(opts);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n logger.error(message);\n process.exit(1);\n }\n\n const localSourceRoot = opts.debugSourceRoot\n ? path.resolve(opts.debugSourceRoot)\n : undefined;\n\n // Start release ref resolution early (runs during user prompts)\n const refPromise = localSourceRoot\n ? Promise.resolve(undefined)\n : resolveLatestReleaseRef();\n\n // 1. Resolve project directory\n let resolvedProjectDirectory = resolveCreateProjectDirectory({\n projectDirectory,\n });\n\n if (!resolvedProjectDirectory) {\n const result = await p.text({\n message: \"Project name:\",\n placeholder: \"my-aui-app\",\n defaultValue: \"my-aui-app\",\n validate: (value?: string) => {\n const name = (value ?? \"\").trim();\n if (!name) return \"Project name cannot be empty\";\n if (name === \".\" || name === \"..\")\n return \"Project name cannot be . or ..\";\n if (name.includes(\"/\") || name.includes(\"\\\\\"))\n return \"Project name cannot contain path separators\";\n return undefined;\n },\n });\n\n if (p.isCancel(result)) {\n p.cancel(\"Project creation cancelled.\");\n process.exit(0);\n }\n\n resolvedProjectDirectory = result;\n }\n\n // Check directory\n const absoluteProjectDir = path.resolve(resolvedProjectDirectory);\n try {\n const files = fs.readdirSync(absoluteProjectDir);\n if (files.length > 0) {\n logger.error(\n `Directory ${resolvedProjectDirectory} already exists and is not empty`,\n );\n process.exit(1);\n }\n } catch (err: unknown) {\n const code =\n err instanceof Error ? (err as NodeJS.ErrnoException).code : undefined;\n if (code === \"ENOENT\") {\n // Directory doesn't exist — good, proceed\n } else if (code === \"ENOTDIR\") {\n logger.error(\n `${resolvedProjectDirectory} already exists and is not a directory`,\n );\n process.exit(1);\n } else {\n const message = err instanceof Error ? err.message : String(err);\n logger.error(`Cannot access ${resolvedProjectDirectory}: ${message}`);\n process.exit(1);\n }\n }\n\n // 2. Resolve scaffold target\n const project = await resolveProject(scaffoldSelector);\n if (!project) {\n p.cancel(\"Project creation cancelled.\");\n process.exit(0);\n }\n\n const stdinIsTTY = process.stdin.isTTY;\n let installSkills = resolveSkillsInstall({\n skills: opts.skills,\n stdinIsTTY,\n });\n if (installSkills === undefined) {\n const result = await p.confirm({\n message: \"Add assistant-ui agent skills for AI coding assistants?\",\n initialValue: true,\n });\n\n if (p.isCancel(result)) {\n p.cancel(\"Project creation cancelled.\");\n process.exit(0);\n }\n\n installSkills = result;\n }\n\n logger.info(`Creating project from ${project.category}: ${project.label}`);\n logger.break();\n\n const pm = await resolvePackageManagerForCwd(\n path.dirname(absoluteProjectDir),\n resolvePackageManager(opts),\n );\n\n // Clean up partial project directory on unexpected exit (e.g. Ctrl+C)\n const cleanupOnExit = () => {\n fs.rmSync(absoluteProjectDir, { recursive: true, force: true });\n };\n process.once(\"exit\", cleanupOnExit);\n\n try {\n // 3. Resolve latest release ref (started before prompts)\n if (!localSourceRoot) {\n logger.step(\"Resolving latest release...\");\n }\n const ref = await refPromise;\n if (!localSourceRoot && !ref) {\n logger.warn(\"Could not resolve latest release, downloading from HEAD\");\n }\n\n // 4. Scaffold project\n logger.step(\n localSourceRoot\n ? `Copying project from local source: ${localSourceRoot}`\n : \"Downloading project...\",\n );\n try {\n const source = localSourceRoot\n ? { kind: \"local\" as const, rootDir: localSourceRoot }\n : {\n kind: \"github\" as const,\n ref,\n };\n await scaffoldProject(project.path, absoluteProjectDir, source);\n\n // If the template didn't exist at the release tag, retry from HEAD\n if (\n !localSourceRoot &&\n ref &&\n !fs.existsSync(path.join(absoluteProjectDir, \"package.json\"))\n ) {\n fs.rmSync(absoluteProjectDir, { recursive: true, force: true });\n logger.warn(\n \"Template not found at release tag, downloading from HEAD\",\n );\n await downloadProject(project.path, absoluteProjectDir);\n }\n\n // 5. Run transform pipeline\n await transformProject(absoluteProjectDir, {\n hasLocalComponents: project.hasLocalComponents,\n skipInstall: opts.skipInstall,\n packageManager: pm,\n });\n\n if (installSkills) {\n logger.step(\"Adding assistant-ui agent skills...\");\n const [skillsCmd, skillsArgs] = buildSkillsAddCommand(pm, {\n stdinIsTTY,\n });\n try {\n await runSpawn(skillsCmd, skillsArgs, absoluteProjectDir);\n } catch {\n logger.warn(\n `Could not add assistant-ui agent skills. You can add them later with:\\n ${skillsCmd} ${skillsArgs.join(\" \")}`,\n );\n }\n }\n } catch (err) {\n // Clean up partially created project directory\n fs.rmSync(absoluteProjectDir, { recursive: true, force: true });\n throw err;\n }\n\n // 6. Apply preset if provided\n if (scaffoldSelector.preset) {\n const presetUrl = resolvePresetUrl(scaffoldSelector.preset);\n logger.info(\"Applying preset configuration...\");\n logger.break();\n const [dlxCmd, dlxArgs] = dlxCommand(pm);\n try {\n await runSpawn(\n dlxCmd,\n [\n ...dlxArgs,\n \"shadcn@latest\",\n \"add\",\n \"--yes\",\n \"--overwrite\",\n presetUrl,\n ],\n absoluteProjectDir,\n );\n } catch {\n logger.warn(\n `Preset application failed. You can retry manually with:\\n ${dlxCmd} ${[...dlxArgs, \"shadcn@latest\", \"add\", presetUrl].join(\" \")}`,\n );\n }\n }\n\n process.removeListener(\"exit\", cleanupOnExit);\n\n logger.break();\n logger.success(\"Project created successfully!\");\n logger.break();\n const runCmd = pm === \"npm\" ? \"npm run\" : pm;\n let devScript = \"dev\";\n let envFile = \".env.local\";\n try {\n const scaffoldedPkg = JSON.parse(\n fs.readFileSync(\n path.join(absoluteProjectDir, \"package.json\"),\n \"utf-8\",\n ),\n );\n devScript = scaffoldedPkg.scripts?.dev\n ? \"dev\"\n : scaffoldedPkg.scripts?.start\n ? \"start\"\n : \"dev\";\n envFile = scaffoldedPkg.dependencies?.next ? \".env.local\" : \".env\";\n } catch {\n // Fall back to defaults if package.json cannot be read\n }\n\n logger.info(\"Next steps:\");\n logger.info(` cd ${resolvedProjectDirectory}`);\n if (opts.skipInstall) {\n logger.info(` ${pm} install`);\n }\n logger.info(` # Set up your environment variables in ${envFile}`);\n logger.info(` ${runCmd} ${devScript}`);\n } catch (error) {\n if (error instanceof SpawnExitError) {\n logger.error(`Project creation failed with code ${error.code}`);\n process.exit(error.code);\n }\n const message = error instanceof Error ? error.message : String(error);\n logger.error(`Failed to create project: ${message}`);\n process.exit(1);\n }\n });\n"],"mappings":";;;;;;;;;;AA8BA,MAAa,mBAAsC;CAEjD;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CAEA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,MAAM;EACN,oBAAoB;CACtB;AACF;AAWA,MAAM,gBAAgB,iBAAiB,QACpC,MAAM,EAAE,aAAa,UACxB,CAAC,CAAC,KAAK,MAAM,EAAE,IAAI;AAEnB,MAAM,eAAe,iBAAiB,QACnC,MAAM,EAAE,aAAa,SACxB,CAAC,CAAC,KAAK,MAAM,EAAE,IAAI;AAEnB,eAAsB,eAAe,QAMD;CAClC,MAAM,EACJ,UACA,SACA,aAAa,QAAQ,MAAM,OAC3B,SAAS,EAAE,QACX,WAAW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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"doctor.d.ts","names":[],"sources":["../../src/commands/doctor.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"doctor.d.ts","names":[],"sources":["../../src/commands/doctor.ts"],"mappings":";;UAkBiB;EACf;EACA;EACA;;iBAuKc,0BAA0B,cAAc;UAQvC;EACf;EACA,eAAe;;iBAGD,eACd,UAAU,sBACT;iBAmBa,mBAAmB,UAAU;iBAmC7B,cAAc,WAAW;UAOxB;EACf;EACA;EACA;;iBAGc,aACd,UAAU,qBACV,QAAQ,6BACP;cAsFU,QAAM"}
|
package/dist/commands/doctor.js
CHANGED
|
@@ -2,6 +2,7 @@ import { Command } from "commander";
|
|
|
2
2
|
import chalk from "chalk";
|
|
3
3
|
import * as fs$1 from "node:fs";
|
|
4
4
|
import * as path$1 from "node:path";
|
|
5
|
+
import { compare, valid } from "semver";
|
|
5
6
|
//#region src/commands/doctor.ts
|
|
6
7
|
const ASSISTANT_UI_PACKAGE_NAMES = /* @__PURE__ */ new Set([
|
|
7
8
|
"assistant-stream",
|
|
@@ -73,9 +74,60 @@ function walkNodeModulesAt(baseDir, results, visited) {
|
|
|
73
74
|
} else processPackageDir(path$1.join(nm, entry.name), results, visited);
|
|
74
75
|
}
|
|
75
76
|
}
|
|
77
|
+
const TRACKED_PNPM_ENTRY_PREFIXES = [
|
|
78
|
+
"@assistant-ui+",
|
|
79
|
+
"assistant-ui@",
|
|
80
|
+
"assistant-stream@",
|
|
81
|
+
"assistant-cloud@"
|
|
82
|
+
];
|
|
83
|
+
function isTrackedPnpmEntry(dirName) {
|
|
84
|
+
return TRACKED_PNPM_ENTRY_PREFIXES.some((p) => dirName.startsWith(p));
|
|
85
|
+
}
|
|
86
|
+
function processTrackedPackagesIn(nm, results, visited) {
|
|
87
|
+
let entries;
|
|
88
|
+
try {
|
|
89
|
+
entries = fs$1.readdirSync(nm, { withFileTypes: true });
|
|
90
|
+
} catch {
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
for (const entry of entries) {
|
|
94
|
+
if (entry.name.startsWith(".")) continue;
|
|
95
|
+
if (!entry.isDirectory() && !entry.isSymbolicLink()) continue;
|
|
96
|
+
if (entry.name.startsWith("@")) {
|
|
97
|
+
const scopeDir = path$1.join(nm, entry.name);
|
|
98
|
+
let scoped;
|
|
99
|
+
try {
|
|
100
|
+
scoped = fs$1.readdirSync(scopeDir, { withFileTypes: true });
|
|
101
|
+
} catch {
|
|
102
|
+
continue;
|
|
103
|
+
}
|
|
104
|
+
for (const s of scoped) {
|
|
105
|
+
if (!s.isDirectory() && !s.isSymbolicLink()) continue;
|
|
106
|
+
if (!isTrackedPackage(`${entry.name}/${s.name}`)) continue;
|
|
107
|
+
processPackageDir(path$1.join(scopeDir, s.name), results, visited);
|
|
108
|
+
}
|
|
109
|
+
} else if (isTrackedPackage(entry.name)) processPackageDir(path$1.join(nm, entry.name), results, visited);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
function walkPnpmStore(cwd, results, visited) {
|
|
113
|
+
const storeDir = path$1.join(cwd, "node_modules", ".pnpm");
|
|
114
|
+
let entries;
|
|
115
|
+
try {
|
|
116
|
+
entries = fs$1.readdirSync(storeDir, { withFileTypes: true });
|
|
117
|
+
} catch {
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
for (const entry of entries) {
|
|
121
|
+
if (!entry.isDirectory() && !entry.isSymbolicLink()) continue;
|
|
122
|
+
if (!isTrackedPnpmEntry(entry.name)) continue;
|
|
123
|
+
processTrackedPackagesIn(path$1.join(storeDir, entry.name, "node_modules"), results, visited);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
76
126
|
function discoverInstalledPackages(cwd) {
|
|
77
127
|
const results = [];
|
|
78
|
-
|
|
128
|
+
const visited = { set: /* @__PURE__ */ new Set() };
|
|
129
|
+
walkNodeModulesAt(cwd, results, visited);
|
|
130
|
+
walkPnpmStore(cwd, results, visited);
|
|
79
131
|
return results;
|
|
80
132
|
}
|
|
81
133
|
function findDuplicates(packages) {
|
|
@@ -111,27 +163,11 @@ async function fetchAllLatestVersions(names) {
|
|
|
111
163
|
const entries = await Promise.all(names.map(async (n) => [n, await fetchLatestVersion(n)]));
|
|
112
164
|
return new Map(entries);
|
|
113
165
|
}
|
|
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
166
|
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);
|
|
167
|
+
const validA = valid(a);
|
|
168
|
+
const validB = valid(b);
|
|
169
|
+
if (!validA || !validB) return a.localeCompare(b);
|
|
170
|
+
return compare(validA, validB);
|
|
135
171
|
}
|
|
136
172
|
function findOutdated(packages, latest) {
|
|
137
173
|
const newestByName = /* @__PURE__ */ new Map();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"doctor.js","names":["fs","path"],"sources":["../../src/commands/doctor.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport chalk from \"chalk\";\n\nconst ASSISTANT_UI_PACKAGE_NAMES = new Set([\n \"assistant-stream\",\n \"assistant-cloud\",\n \"assistant-ui\",\n]);\n\nfunction isTrackedPackage(name: string | undefined): boolean {\n if (!name) return false;\n if (name.startsWith(\"@assistant-ui/\")) return true;\n return ASSISTANT_UI_PACKAGE_NAMES.has(name);\n}\n\nexport interface DiscoveredPackage {\n name: string;\n version: string;\n installPath: string;\n}\n\ninterface ProcessedDir {\n set: Set<string>;\n}\n\nfunction readJson(file: string): Record<string, unknown> | null {\n try {\n return JSON.parse(fs.readFileSync(file, \"utf8\"));\n } catch {\n return null;\n }\n}\n\nfunction processPackageDir(\n pkgDir: string,\n results: DiscoveredPackage[],\n visited: ProcessedDir,\n): void {\n const real = (() => {\n try {\n return fs.realpathSync(pkgDir);\n } catch {\n return pkgDir;\n }\n })();\n if (visited.set.has(real)) return;\n visited.set.add(real);\n\n const pkgJson = readJson(path.join(pkgDir, \"package.json\"));\n let isTracked = false;\n if (pkgJson) {\n const name = pkgJson.name as string | undefined;\n const version = pkgJson.version as string | undefined;\n if (name && version && isTrackedPackage(name)) {\n results.push({ name, version, installPath: pkgDir });\n isTracked = true;\n }\n }\n\n // Only descend into nested node_modules of tracked packages. Transitive\n // copies of @assistant-ui/* live inside packages that depend on them,\n // which are themselves tracked. Walking every unrelated package's\n // subtree turns a doctor run on a large repo into thousands of stat\n // calls for no gain.\n if (isTracked) {\n walkNodeModulesAt(pkgDir, results, visited);\n }\n}\n\nfunction walkNodeModulesAt(\n baseDir: string,\n results: DiscoveredPackage[],\n visited: ProcessedDir,\n): void {\n const nm = path.join(baseDir, \"node_modules\");\n if (!fs.existsSync(nm)) return;\n\n let entries: fs.Dirent[];\n try {\n entries = fs.readdirSync(nm, { withFileTypes: true });\n } catch {\n return;\n }\n\n for (const entry of entries) {\n if (entry.name.startsWith(\".\")) continue;\n if (!entry.isDirectory() && !entry.isSymbolicLink()) continue;\n\n if (entry.name.startsWith(\"@\")) {\n const scopeDir = path.join(nm, entry.name);\n let scoped: fs.Dirent[];\n try {\n scoped = fs.readdirSync(scopeDir, { withFileTypes: true });\n } catch {\n continue;\n }\n for (const s of scoped) {\n if (!s.isDirectory() && !s.isSymbolicLink()) continue;\n processPackageDir(path.join(scopeDir, s.name), results, visited);\n }\n } else {\n processPackageDir(path.join(nm, entry.name), results, visited);\n }\n }\n}\n\n// Discover every installation of an assistant-ui-family package reachable\n// from `cwd`. Recurses into nested node_modules so transitive copies\n// (the real source of duplicate-version bugs) are not missed.\nexport function discoverInstalledPackages(cwd: string): DiscoveredPackage[] {\n const results: DiscoveredPackage[] = [];\n const visited: ProcessedDir = { set: new Set() };\n walkNodeModulesAt(cwd, results, visited);\n return results;\n}\n\nexport interface DuplicateGroup {\n name: string;\n installations: DiscoveredPackage[];\n}\n\nexport function findDuplicates(\n packages: DiscoveredPackage[],\n): DuplicateGroup[] {\n const byName = new Map<string, DiscoveredPackage[]>();\n for (const pkg of packages) {\n const list = byName.get(pkg.name) ?? [];\n list.push(pkg);\n byName.set(pkg.name, list);\n }\n\n const duplicates: DuplicateGroup[] = [];\n for (const [name, installations] of byName) {\n const versions = new Set(installations.map((i) => i.version));\n if (versions.size > 1) {\n duplicates.push({ name, installations });\n }\n }\n duplicates.sort((a, b) => a.name.localeCompare(b.name));\n return duplicates;\n}\n\nexport function uniquePackageNames(packages: DiscoveredPackage[]): string[] {\n return Array.from(new Set(packages.map((p) => p.name))).sort();\n}\n\n// Package names use a restricted character set (`[a-z0-9._~-]` plus a\n// leading `@scope/` for scoped packages — see the npm package-name spec)\n// and the npm registry expects the scope's `@` and `/` un-encoded. So a\n// simple validation + concatenation is both correct and avoids the\n// CodeQL \"incomplete string escaping\" foot-gun of `encodeURIComponent`\n// + targeted un-escape.\nconst VALID_NPM_NAME = /^(@[a-z0-9._~-]+\\/)?[a-z0-9._~-]+$/;\n\nasync function fetchLatestVersion(name: string): Promise<string | null> {\n if (!VALID_NPM_NAME.test(name)) return null;\n try {\n const res = await fetch(`https://registry.npmjs.org/${name}/latest`, {\n headers: { Accept: \"application/json\" },\n });\n if (!res.ok) return null;\n const data = (await res.json()) as { version?: string };\n return data.version ?? null;\n } catch {\n return null;\n }\n}\n\nasync function fetchAllLatestVersions(\n names: string[],\n): Promise<Map<string, string | null>> {\n const entries = await Promise.all(\n names.map(async (n) => [n, await fetchLatestVersion(n)] as const),\n );\n return new Map(entries);\n}\n\ninterface SemverParts {\n major: number;\n minor: number;\n patch: number;\n prerelease: string;\n}\n\nfunction parseSemver(v: string): SemverParts | null {\n const m = /^(\\d+)\\.(\\d+)\\.(\\d+)(?:-([^+\\s]+))?/.exec(v);\n if (!m) return null;\n return {\n major: parseInt(m[1]!, 10),\n minor: parseInt(m[2]!, 10),\n patch: parseInt(m[3]!, 10),\n prerelease: m[4] ?? \"\",\n };\n}\n\nexport function compareSemver(a: string, b: string): number {\n const pa = parseSemver(a);\n const pb = parseSemver(b);\n if (!pa || !pb) return a.localeCompare(b);\n if (pa.major !== pb.major) return pa.major - pb.major;\n if (pa.minor !== pb.minor) return pa.minor - pb.minor;\n if (pa.patch !== pb.patch) return pa.patch - pb.patch;\n\n // Per SemVer §11: a version with a prerelease tag is *less than* the\n // same x.y.z without one. We compare tags lexically for a stable\n // ordering across prereleases — good enough for doctor's \"is X older\n // than the npm latest\" check.\n if (pa.prerelease === pb.prerelease) return 0;\n if (!pa.prerelease) return 1;\n if (!pb.prerelease) return -1;\n return pa.prerelease.localeCompare(pb.prerelease);\n}\n\nexport interface OutdatedPackage {\n name: string;\n current: string;\n latest: string;\n}\n\nexport function findOutdated(\n packages: DiscoveredPackage[],\n latest: Map<string, string | null>,\n): OutdatedPackage[] {\n const newestByName = new Map<string, string>();\n for (const pkg of packages) {\n const existing = newestByName.get(pkg.name);\n if (!existing || compareSemver(pkg.version, existing) > 0) {\n newestByName.set(pkg.name, pkg.version);\n }\n }\n\n const result: OutdatedPackage[] = [];\n for (const [name, current] of newestByName) {\n const latestVersion = latest.get(name);\n if (!latestVersion) continue;\n if (compareSemver(current, latestVersion) < 0) {\n result.push({ name, current, latest: latestVersion });\n }\n }\n result.sort((a, b) => a.name.localeCompare(b.name));\n return result;\n}\n\nfunction relativeInstallPath(installPath: string, cwd: string): string {\n const rel = path.relative(cwd, installPath);\n return rel.startsWith(\"..\") ? installPath : rel;\n}\n\nfunction reportDuplicates(\n duplicates: DuplicateGroup[],\n cwd: string,\n lines: string[],\n): void {\n if (duplicates.length === 0) {\n lines.push(chalk.green(\"✓ No duplicate versions detected.\"));\n return;\n }\n\n lines.push(chalk.red.bold(\"✗ Duplicate versions detected:\"));\n for (const dup of duplicates) {\n const versions = Array.from(\n new Set(dup.installations.map((i) => i.version)),\n )\n .sort(compareSemver)\n .join(\", \");\n lines.push(chalk.red(` ${dup.name} → ${versions}`));\n for (const inst of dup.installations) {\n lines.push(\n chalk.dim(\n ` ${inst.version} ${relativeInstallPath(inst.installPath, cwd)}`,\n ),\n );\n }\n }\n lines.push(\"\");\n lines.push(\n chalk.yellow(\n \"Duplicates almost always cause subtle runtime bugs (see https://github.com/assistant-ui/assistant-ui/issues/4101).\",\n ),\n );\n lines.push(\n chalk.yellow(\n \"Fix by aligning all @assistant-ui/* packages to compatible versions — run:\",\n ),\n );\n lines.push(chalk.cyan(\" npx assistant-ui update\"));\n}\n\nfunction reportOutdated(outdated: OutdatedPackage[], lines: string[]): void {\n if (outdated.length === 0) {\n lines.push(chalk.green(\"✓ All assistant-ui packages are up to date.\"));\n return;\n }\n\n lines.push(chalk.yellow.bold(\"! Outdated packages:\"));\n const maxLen = Math.max(...outdated.map((o) => o.name.length));\n for (const o of outdated) {\n lines.push(\n chalk.yellow(\n ` ${o.name.padEnd(maxLen)} ${o.current} → ${o.latest} (latest)`,\n ),\n );\n }\n lines.push(\"\");\n lines.push(chalk.yellow(\"Run the following to upgrade everything:\"));\n lines.push(chalk.cyan(\" npx assistant-ui update\"));\n}\n\nexport const doctor = new Command()\n .name(\"doctor\")\n .description(\n \"Diagnose mismatched or outdated assistant-ui packages (including transitive ones).\",\n )\n .option(\n \"-c, --cwd <cwd>\",\n \"the working directory. defaults to the current directory.\",\n process.cwd(),\n )\n .option(\"--no-network\", \"Skip the npm registry check for latest versions.\")\n .action(async (opts: { cwd: string; network: boolean }) => {\n const cwd = path.resolve(opts.cwd);\n const packageJsonPath = path.join(cwd, \"package.json\");\n\n if (!fs.existsSync(packageJsonPath)) {\n console.error(\n chalk.red(\"No package.json found in the current directory.\"),\n );\n process.exit(1);\n }\n\n console.log(\"\");\n console.log(chalk.bold(\"Running assistant-ui doctor...\"));\n console.log(\"\");\n\n const installed = discoverInstalledPackages(cwd);\n\n if (installed.length === 0) {\n console.log(\n chalk.yellow(\n \"No assistant-ui packages found in node_modules. Did you run `npm install`?\",\n ),\n );\n console.log(\"\");\n return;\n }\n\n const duplicates = findDuplicates(installed);\n\n let latest = new Map<string, string | null>();\n if (opts.network) {\n latest = await fetchAllLatestVersions(uniquePackageNames(installed));\n }\n const outdated = findOutdated(installed, latest);\n\n const lines: string[] = [];\n reportDuplicates(duplicates, cwd, lines);\n lines.push(\"\");\n if (opts.network) {\n reportOutdated(outdated, lines);\n } else {\n lines.push(chalk.dim(\"Skipped npm registry check (--no-network).\"));\n }\n\n for (const line of lines) console.log(line);\n console.log(\"\");\n\n if (duplicates.length > 0) {\n process.exitCode = 1;\n }\n });\n"],"mappings":";;;;;AAKA,MAAM,6CAA6B,IAAI,IAAI;CACzC;CACA;CACA;AACF,CAAC;AAED,SAAS,iBAAiB,MAAmC;CAC3D,IAAI,CAAC,MAAM,OAAO;CAClB,IAAI,KAAK,WAAW,gBAAgB,GAAG,OAAO;CAC9C,OAAO,2BAA2B,IAAI,IAAI;AAC5C;AAYA,SAAS,SAAS,MAA8C;CAC9D,IAAI;EACF,OAAO,KAAK,MAAMA,KAAG,aAAa,MAAM,MAAM,CAAC;CACjD,QAAQ;EACN,OAAO;CACT;AACF;AAEA,SAAS,kBACP,QACA,SACA,SACM;CACN,MAAM,cAAc;EAClB,IAAI;GACF,OAAOA,KAAG,aAAa,MAAM;EAC/B,QAAQ;GACN,OAAO;EACT;CACF,EAAA,CAAG;CACH,IAAI,QAAQ,IAAI,IAAI,IAAI,GAAG;CAC3B,QAAQ,IAAI,IAAI,IAAI;CAEpB,MAAM,UAAU,SAASC,OAAK,KAAK,QAAQ,cAAc,CAAC;CAC1D,IAAI,YAAY;CAChB,IAAI,SAAS;EACX,MAAM,OAAO,QAAQ;EACrB,MAAM,UAAU,QAAQ;EACxB,IAAI,QAAQ,WAAW,iBAAiB,IAAI,GAAG;GAC7C,QAAQ,KAAK;IAAE;IAAM;IAAS,aAAa;GAAO,CAAC;GACnD,YAAY;EACd;CACF;CAOA,IAAI,WACF,kBAAkB,QAAQ,SAAS,OAAO;AAE9C;AAEA,SAAS,kBACP,SACA,SACA,SACM;CACN,MAAM,KAAKA,OAAK,KAAK,SAAS,cAAc;CAC5C,IAAI,CAACD,KAAG,WAAW,EAAE,GAAG;CAExB,IAAI;CACJ,IAAI;EACF,UAAUA,KAAG,YAAY,IAAI,EAAE,eAAe,KAAK,CAAC;CACtD,QAAQ;EACN;CACF;CAEA,KAAK,MAAM,SAAS,SAAS;EAC3B,IAAI,MAAM,KAAK,WAAW,GAAG,GAAG;EAChC,IAAI,CAAC,MAAM,YAAY,KAAK,CAAC,MAAM,eAAe,GAAG;EAErD,IAAI,MAAM,KAAK,WAAW,GAAG,GAAG;GAC9B,MAAM,WAAWC,OAAK,KAAK,IAAI,MAAM,IAAI;GACzC,IAAI;GACJ,IAAI;IACF,SAASD,KAAG,YAAY,UAAU,EAAE,eAAe,KAAK,CAAC;GAC3D,QAAQ;IACN;GACF;GACA,KAAK,MAAM,KAAK,QAAQ;IACtB,IAAI,CAAC,EAAE,YAAY,KAAK,CAAC,EAAE,eAAe,GAAG;IAC7C,kBAAkBC,OAAK,KAAK,UAAU,EAAE,IAAI,GAAG,SAAS,OAAO;GACjE;EACF,OACE,kBAAkBA,OAAK,KAAK,IAAI,MAAM,IAAI,GAAG,SAAS,OAAO;CAEjE;AACF;AAKA,SAAgB,0BAA0B,KAAkC;CAC1E,MAAM,UAA+B,CAAC;CAEtC,kBAAkB,KAAK,SAAS,EADA,qBAAK,IAAI,IAAI,EACP,CAAC;CACvC,OAAO;AACT;AAOA,SAAgB,eACd,UACkB;CAClB,MAAM,yBAAS,IAAI,IAAiC;CACpD,KAAK,MAAM,OAAO,UAAU;EAC1B,MAAM,OAAO,OAAO,IAAI,IAAI,IAAI,KAAK,CAAC;EACtC,KAAK,KAAK,GAAG;EACb,OAAO,IAAI,IAAI,MAAM,IAAI;CAC3B;CAEA,MAAM,aAA+B,CAAC;CACtC,KAAK,MAAM,CAAC,MAAM,kBAAkB,QAElC,IAAI,IADiB,IAAI,cAAc,KAAK,MAAM,EAAE,OAAO,CAChD,CAAC,CAAC,OAAO,GAClB,WAAW,KAAK;EAAE;EAAM;CAAc,CAAC;CAG3C,WAAW,MAAM,GAAG,MAAM,EAAE,KAAK,cAAc,EAAE,IAAI,CAAC;CACtD,OAAO;AACT;AAEA,SAAgB,mBAAmB,UAAyC;CAC1E,OAAO,MAAM,KAAK,IAAI,IAAI,SAAS,KAAK,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK;AAC/D;AAQA,MAAM,iBAAiB;AAEvB,eAAe,mBAAmB,MAAsC;CACtE,IAAI,CAAC,eAAe,KAAK,IAAI,GAAG,OAAO;CACvC,IAAI;EACF,MAAM,MAAM,MAAM,MAAM,8BAA8B,KAAK,UAAU,EACnE,SAAS,EAAE,QAAQ,mBAAmB,EACxC,CAAC;EACD,IAAI,CAAC,IAAI,IAAI,OAAO;EAEpB,QAAO,MADa,IAAI,KAAK,EAAA,CACjB,WAAW;CACzB,QAAQ;EACN,OAAO;CACT;AACF;AAEA,eAAe,uBACb,OACqC;CACrC,MAAM,UAAU,MAAM,QAAQ,IAC5B,MAAM,IAAI,OAAO,MAAM,CAAC,GAAG,MAAM,mBAAmB,CAAC,CAAC,CAAU,CAClE;CACA,OAAO,IAAI,IAAI,OAAO;AACxB;AASA,SAAS,YAAY,GAA+B;CAClD,MAAM,IAAI,sCAAsC,KAAK,CAAC;CACtD,IAAI,CAAC,GAAG,OAAO;CACf,OAAO;EACL,OAAO,SAAS,EAAE,IAAK,EAAE;EACzB,OAAO,SAAS,EAAE,IAAK,EAAE;EACzB,OAAO,SAAS,EAAE,IAAK,EAAE;EACzB,YAAY,EAAE,MAAM;CACtB;AACF;AAEA,SAAgB,cAAc,GAAW,GAAmB;CAC1D,MAAM,KAAK,YAAY,CAAC;CACxB,MAAM,KAAK,YAAY,CAAC;CACxB,IAAI,CAAC,MAAM,CAAC,IAAI,OAAO,EAAE,cAAc,CAAC;CACxC,IAAI,GAAG,UAAU,GAAG,OAAO,OAAO,GAAG,QAAQ,GAAG;CAChD,IAAI,GAAG,UAAU,GAAG,OAAO,OAAO,GAAG,QAAQ,GAAG;CAChD,IAAI,GAAG,UAAU,GAAG,OAAO,OAAO,GAAG,QAAQ,GAAG;CAMhD,IAAI,GAAG,eAAe,GAAG,YAAY,OAAO;CAC5C,IAAI,CAAC,GAAG,YAAY,OAAO;CAC3B,IAAI,CAAC,GAAG,YAAY,OAAO;CAC3B,OAAO,GAAG,WAAW,cAAc,GAAG,UAAU;AAClD;AAQA,SAAgB,aACd,UACA,QACmB;CACnB,MAAM,+BAAe,IAAI,IAAoB;CAC7C,KAAK,MAAM,OAAO,UAAU;EAC1B,MAAM,WAAW,aAAa,IAAI,IAAI,IAAI;EAC1C,IAAI,CAAC,YAAY,cAAc,IAAI,SAAS,QAAQ,IAAI,GACtD,aAAa,IAAI,IAAI,MAAM,IAAI,OAAO;CAE1C;CAEA,MAAM,SAA4B,CAAC;CACnC,KAAK,MAAM,CAAC,MAAM,YAAY,cAAc;EAC1C,MAAM,gBAAgB,OAAO,IAAI,IAAI;EACrC,IAAI,CAAC,eAAe;EACpB,IAAI,cAAc,SAAS,aAAa,IAAI,GAC1C,OAAO,KAAK;GAAE;GAAM;GAAS,QAAQ;EAAc,CAAC;CAExD;CACA,OAAO,MAAM,GAAG,MAAM,EAAE,KAAK,cAAc,EAAE,IAAI,CAAC;CAClD,OAAO;AACT;AAEA,SAAS,oBAAoB,aAAqB,KAAqB;CACrE,MAAM,MAAMA,OAAK,SAAS,KAAK,WAAW;CAC1C,OAAO,IAAI,WAAW,IAAI,IAAI,cAAc;AAC9C;AAEA,SAAS,iBACP,YACA,KACA,OACM;CACN,IAAI,WAAW,WAAW,GAAG;EAC3B,MAAM,KAAK,MAAM,MAAM,mCAAmC,CAAC;EAC3D;CACF;CAEA,MAAM,KAAK,MAAM,IAAI,KAAK,gCAAgC,CAAC;CAC3D,KAAK,MAAM,OAAO,YAAY;EAC5B,MAAM,WAAW,MAAM,KACrB,IAAI,IAAI,IAAI,cAAc,KAAK,MAAM,EAAE,OAAO,CAAC,CACjD,CAAC,CACE,KAAK,aAAa,CAAC,CACnB,KAAK,IAAI;EACZ,MAAM,KAAK,MAAM,IAAI,KAAK,IAAI,KAAK,KAAK,UAAU,CAAC;EACnD,KAAK,MAAM,QAAQ,IAAI,eACrB,MAAM,KACJ,MAAM,IACJ,OAAO,KAAK,QAAQ,IAAI,oBAAoB,KAAK,aAAa,GAAG,GACnE,CACF;CAEJ;CACA,MAAM,KAAK,EAAE;CACb,MAAM,KACJ,MAAM,OACJ,oHACF,CACF;CACA,MAAM,KACJ,MAAM,OACJ,4EACF,CACF;CACA,MAAM,KAAK,MAAM,KAAK,6BAA6B,CAAC;AACtD;AAEA,SAAS,eAAe,UAA6B,OAAuB;CAC1E,IAAI,SAAS,WAAW,GAAG;EACzB,MAAM,KAAK,MAAM,MAAM,6CAA6C,CAAC;EACrE;CACF;CAEA,MAAM,KAAK,MAAM,OAAO,KAAK,sBAAsB,CAAC;CACpD,MAAM,SAAS,KAAK,IAAI,GAAG,SAAS,KAAK,MAAM,EAAE,KAAK,MAAM,CAAC;CAC7D,KAAK,MAAM,KAAK,UACd,MAAM,KACJ,MAAM,OACJ,KAAK,EAAE,KAAK,OAAO,MAAM,EAAE,IAAI,EAAE,QAAQ,KAAK,EAAE,OAAO,UACzD,CACF;CAEF,MAAM,KAAK,EAAE;CACb,MAAM,KAAK,MAAM,OAAO,0CAA0C,CAAC;CACnE,MAAM,KAAK,MAAM,KAAK,6BAA6B,CAAC;AACtD;AAEA,MAAa,SAAS,IAAI,QAAQ,CAAC,CAChC,KAAK,QAAQ,CAAC,CACd,YACC,oFACF,CAAC,CACA,OACC,mBACA,6DACA,QAAQ,IAAI,CACd,CAAC,CACA,OAAO,gBAAgB,kDAAkD,CAAC,CAC1E,OAAO,OAAO,SAA4C;CACzD,MAAM,MAAMA,OAAK,QAAQ,KAAK,GAAG;CACjC,MAAM,kBAAkBA,OAAK,KAAK,KAAK,cAAc;CAErD,IAAI,CAACD,KAAG,WAAW,eAAe,GAAG;EACnC,QAAQ,MACN,MAAM,IAAI,iDAAiD,CAC7D;EACA,QAAQ,KAAK,CAAC;CAChB;CAEA,QAAQ,IAAI,EAAE;CACd,QAAQ,IAAI,MAAM,KAAK,gCAAgC,CAAC;CACxD,QAAQ,IAAI,EAAE;CAEd,MAAM,YAAY,0BAA0B,GAAG;CAE/C,IAAI,UAAU,WAAW,GAAG;EAC1B,QAAQ,IACN,MAAM,OACJ,4EACF,CACF;EACA,QAAQ,IAAI,EAAE;EACd;CACF;CAEA,MAAM,aAAa,eAAe,SAAS;CAE3C,IAAI,yBAAS,IAAI,IAA2B;CAC5C,IAAI,KAAK,SACP,SAAS,MAAM,uBAAuB,mBAAmB,SAAS,CAAC;CAErE,MAAM,WAAW,aAAa,WAAW,MAAM;CAE/C,MAAM,QAAkB,CAAC;CACzB,iBAAiB,YAAY,KAAK,KAAK;CACvC,MAAM,KAAK,EAAE;CACb,IAAI,KAAK,SACP,eAAe,UAAU,KAAK;MAE9B,MAAM,KAAK,MAAM,IAAI,4CAA4C,CAAC;CAGpE,KAAK,MAAM,QAAQ,OAAO,QAAQ,IAAI,IAAI;CAC1C,QAAQ,IAAI,EAAE;CAEd,IAAI,WAAW,SAAS,GACtB,QAAQ,WAAW;AAEvB,CAAC"}
|
|
1
|
+
{"version":3,"file":"doctor.js","names":["fs","path"],"sources":["../../src/commands/doctor.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport chalk from \"chalk\";\nimport { compare, valid } from \"semver\";\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// 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`. Recurses into nested node_modules so transitive copies\n// (the real source of duplicate-version bugs) are not missed, and scans the\n// pnpm `.pnpm` virtual store, which the hoisted walk cannot reach.\nexport function discoverInstalledPackages(cwd: string): DiscoveredPackage[] {\n const results: DiscoveredPackage[] = [];\n const visited: ProcessedDir = { set: new Set() };\n walkNodeModulesAt(cwd, results, visited);\n walkPnpmStore(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\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 = 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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"}
|
package/dist/commands/info.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { Command } from "commander";
|
|
2
|
-
|
|
3
2
|
//#region src/commands/info.d.ts
|
|
3
|
+
declare function findWorkspaceRoot(cwd: string): string | null;
|
|
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":";;iBA2FgB,kBAAkB;iBAwHlB,eAAe,iBAAiB;cAqMnC,MAAI"}
|