assistant-ui 0.0.125 → 0.0.127

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. package/README.md +18 -2
  2. package/dist/codemods/utils/createTransformer.js +1 -2
  3. package/dist/codemods/utils/resolveBinding.js +1 -2
  4. package/dist/codemods/v0-11/content-part-to-message-part.js +1 -2
  5. package/dist/codemods/v0-12/assistant-api-to-aui.js +1 -2
  6. package/dist/codemods/v0-12/event-names-to-camelcase.js +1 -2
  7. package/dist/codemods/v0-12/primitive-if-to-aui-if.js +1 -2
  8. package/dist/codemods/v0-15/aui-accessor-calls-to-properties.js +1 -2
  9. package/dist/codemods/v0-8/ui-package-split.js +1 -2
  10. package/dist/codemods/v0-9/edge-package-split.js +1 -2
  11. package/dist/commands/add.js +1 -2
  12. package/dist/commands/agent.js +1 -2
  13. package/dist/commands/cloud.d.ts.map +1 -1
  14. package/dist/commands/cloud.js +70 -31
  15. package/dist/commands/cloud.js.map +1 -1
  16. package/dist/commands/create.js +1 -2
  17. package/dist/commands/doctor.js +1 -2
  18. package/dist/commands/info.js +1 -2
  19. package/dist/commands/init.js +1 -2
  20. package/dist/commands/mcp.js +1 -2
  21. package/dist/commands/update.js +1 -2
  22. package/dist/commands/upgrade.js +1 -2
  23. package/dist/index.js +1 -2
  24. package/dist/lib/agent-skill.d.ts +2 -2
  25. package/dist/lib/agent-skill.js +2 -3
  26. package/dist/lib/agent-skill.js.map +1 -1
  27. package/dist/lib/cloud-abort.js +1 -2
  28. package/dist/lib/cloud-auth.d.ts +1 -0
  29. package/dist/lib/cloud-auth.d.ts.map +1 -1
  30. package/dist/lib/cloud-auth.js +2 -3
  31. package/dist/lib/cloud-auth.js.map +1 -1
  32. package/dist/lib/cloud-config.d.ts +11 -1
  33. package/dist/lib/cloud-config.d.ts.map +1 -1
  34. package/dist/lib/cloud-config.js +52 -16
  35. package/dist/lib/cloud-config.js.map +1 -1
  36. package/dist/lib/cloud-provision.d.ts.map +1 -1
  37. package/dist/lib/cloud-provision.js +7 -3
  38. package/dist/lib/cloud-provision.js.map +1 -1
  39. package/dist/lib/cloud-remote.d.ts +16 -1
  40. package/dist/lib/cloud-remote.d.ts.map +1 -1
  41. package/dist/lib/cloud-remote.js +53 -9
  42. package/dist/lib/cloud-remote.js.map +1 -1
  43. package/dist/lib/cloud-setup-login.js +1 -2
  44. package/dist/lib/cloud-url.js +1 -2
  45. package/dist/lib/create-project.js +1 -2
  46. package/dist/lib/handle-cli-error.js +1 -2
  47. package/dist/lib/install-ai-sdk-lib.js +1 -2
  48. package/dist/lib/install-edge-lib.js +1 -2
  49. package/dist/lib/run-spawn.js +1 -2
  50. package/dist/lib/safe-project-file.d.ts +2 -0
  51. package/dist/lib/safe-project-file.d.ts.map +1 -0
  52. package/dist/lib/safe-project-file.js +25 -0
  53. package/dist/lib/safe-project-file.js.map +1 -0
  54. package/dist/lib/transform.js +1 -2
  55. package/dist/lib/upgrade.js +1 -2
  56. package/dist/lib/utils/config.js +1 -2
  57. package/dist/lib/utils/download.js +1 -2
  58. package/dist/lib/utils/file-scanner.js +1 -2
  59. package/dist/lib/utils/logger.js +1 -2
  60. package/dist/lib/utils/package-installer.js +1 -2
  61. package/dist/lib/utils/package-json.js +1 -2
  62. package/dist/lib/utils/package-manager.js +1 -2
  63. package/dist/lib/utils/registry.js +1 -2
  64. package/dist/lib/utils/workspace.js +1 -2
  65. package/dist/program.js +1 -2
  66. package/dist/run.js +1 -2
  67. package/package.json +7 -7
  68. package/src/commands/cloud.test.ts +156 -0
  69. package/src/commands/cloud.ts +93 -41
  70. package/src/commands/mcp.test.ts +123 -0
  71. package/src/lib/agent-skill.ts +1 -1
  72. package/src/lib/cloud-auth.ts +1 -1
  73. package/src/lib/cloud-config.test.ts +139 -1
  74. package/src/lib/cloud-config.ts +59 -8
  75. package/src/lib/cloud-provision.test.ts +26 -1
  76. package/src/lib/cloud-provision.ts +3 -0
  77. package/src/lib/cloud-remote.test.ts +99 -3
  78. package/src/lib/cloud-remote.ts +93 -7
  79. package/src/lib/safe-project-file.ts +31 -0
  80. package/templates/cloud-harness/components/assistant-ui/elements/attachment-state.ts +59 -0
  81. package/templates/cloud-harness/components/assistant-ui/elements/attachment.aui.tsx +11 -44
  82. package/templates/cloud-harness/components/assistant-ui/elements/thread.aui.tsx +1 -1
  83. package/templates/cloud-harness/package.json +12 -12
  84. package/templates/cloud-harness/.gitignore +0 -42
@@ -2,7 +2,7 @@ import { abortable } from "./cloud-abort.js";
2
2
  import { validateCloudUrl } from "./cloud-url.js";
3
3
  import { randomUUID } from "node:crypto";
4
4
  import { StatewireClient, StatewireHttp } from "statewire";
5
- //#region src/lib/cloud-setup-login.ts
5
+ // src/lib/cloud-setup-login.ts
6
6
  const validInputs = (inputs) => Array.isArray(inputs) && inputs.every((input) => input !== null && typeof input === "object" && typeof input.id === "string" && typeof input.status === "string");
7
7
  const setupLoginUrl = (authorization, issuer, attempt = randomUUID()) => {
8
8
  const url = new URL(authorization.verificationUriComplete);
@@ -131,7 +131,6 @@ const connectCloudLoginSetup = async (url) => {
131
131
  dispose
132
132
  };
133
133
  };
134
- //#endregion
135
134
  export { connectCloudLoginSetup, setupLoginUrl };
136
135
 
137
136
  //# sourceMappingURL=cloud-setup-login.js.map
@@ -1,4 +1,4 @@
1
- //#region src/lib/cloud-url.ts
1
+ // src/lib/cloud-url.ts
2
2
  const validateCloudUrl = (value) => {
3
3
  const url = new URL(value);
4
4
  if (url.username || url.password || url.search || url.hash || url.protocol !== "https:" && !(url.protocol === "http:" && [
@@ -8,7 +8,6 @@ const validateCloudUrl = (value) => {
8
8
  ].includes(url.hostname))) throw new Error("Cloud, accounts and setup URLs must use HTTPS or HTTP localhost for development.");
9
9
  return value.replace(/\/+$/, "");
10
10
  };
11
- //#endregion
12
11
  export { validateCloudUrl };
13
12
 
14
13
  //# sourceMappingURL=cloud-url.js.map
@@ -8,7 +8,7 @@ import * as fs$1 from "node:fs";
8
8
  import * as path$1 from "node:path";
9
9
  import * as os$1 from "node:os";
10
10
  import { parse, printParseErrorCode } from "jsonc-parser";
11
- //#region src/lib/create-project.ts
11
+ // src/lib/create-project.ts
12
12
  const LOCAL_PROJECT_ARTIFACT_DIRS = [
13
13
  "node_modules",
14
14
  ".next",
@@ -423,7 +423,6 @@ async function installShadcnRegistry(projectDir, components, label, pm) {
423
423
  throw new Error(`Failed to install ${label}: ${message}`);
424
424
  }
425
425
  }
426
- //#endregion
427
426
  export { cleanupPendingProjectDownloads, downloadProject, reconcileAssistantUIImportLayout, resolveLatestReleaseRef, scaffoldProject, scanRequiredComponents, transformProject };
428
427
 
429
428
  //# sourceMappingURL=create-project.js.map
@@ -1,6 +1,6 @@
1
1
  import { SpawnSignalError } from "./run-spawn.js";
2
2
  import { constants } from "node:os";
3
- //#region src/lib/handle-cli-error.ts
3
+ // src/lib/handle-cli-error.ts
4
4
  function handleCliError(error) {
5
5
  if (error instanceof SpawnSignalError) {
6
6
  process.exitCode = 128 + (constants.signals[error.signal] ?? 0);
@@ -11,7 +11,6 @@ function handleCliError(error) {
11
11
  console.error(error);
12
12
  process.exitCode = 1;
13
13
  }
14
- //#endregion
15
14
  export { handleCliError };
16
15
 
17
16
  //# sourceMappingURL=handle-cli-error.js.map
@@ -1,5 +1,5 @@
1
1
  import { installPackageIfNeeded } from "./utils/package-installer.js";
2
- //#region src/lib/install-ai-sdk-lib.ts
2
+ // src/lib/install-ai-sdk-lib.ts
3
3
  async function installAiSdkLib() {
4
4
  await installPackageIfNeeded({
5
5
  packageName: "@assistant-ui/ai-sdk",
@@ -16,7 +16,6 @@ async function installAiSdkLib() {
16
16
  notFoundMessage: "No legacy AI SDK imports found; skipping installation."
17
17
  });
18
18
  }
19
- //#endregion
20
19
  export { installAiSdkLib as default };
21
20
 
22
21
  //# sourceMappingURL=install-ai-sdk-lib.js.map
@@ -1,5 +1,5 @@
1
1
  import { installPackageIfNeeded } from "./utils/package-installer.js";
2
- //#region src/lib/install-edge-lib.ts
2
+ // src/lib/install-edge-lib.ts
3
3
  async function installEdgeLib() {
4
4
  await installPackageIfNeeded({
5
5
  packageName: "@assistant-ui/ai-sdk",
@@ -9,7 +9,6 @@ async function installEdgeLib() {
9
9
  notFoundMessage: "No Edge Runtime imports found; skipping installation."
10
10
  });
11
11
  }
12
- //#endregion
13
12
  export { installEdgeLib as default };
14
13
 
15
14
  //# sourceMappingURL=install-edge-lib.js.map
@@ -1,5 +1,5 @@
1
1
  import { spawn } from "cross-spawn";
2
- //#region src/lib/run-spawn.ts
2
+ // src/lib/run-spawn.ts
3
3
  var SpawnExitError = class extends Error {
4
4
  code;
5
5
  stderr;
@@ -113,7 +113,6 @@ function runSpawn(command, args, cwd) {
113
113
  function runSpawnCapture(command, args, cwd) {
114
114
  return spawnProcess(command, args, cwd, true);
115
115
  }
116
- //#endregion
117
116
  export { SpawnExitError, SpawnSignalError, hasActiveSpawn, runSpawn, runSpawnCapture };
118
117
 
119
118
  //# sourceMappingURL=run-spawn.js.map
@@ -0,0 +1,2 @@
1
+ export declare const assertSafeProjectFile: (file: string, projectRoot: string) => void;
2
+ //# sourceMappingURL=safe-project-file.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"safe-project-file.d.ts","sourceRoot":"","sources":["../../src/lib/safe-project-file.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,qBAAqB,GAAI,MAAM,MAAM,EAAE,aAAa,MAAM,SA2BtE,CAAC"}
@@ -0,0 +1,25 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ // src/lib/safe-project-file.ts
4
+ const assertSafeProjectFile = (file, projectRoot) => {
5
+ try {
6
+ if (fs.lstatSync(file).isSymbolicLink()) throw new Error(`${file} is a symbolic link`);
7
+ } catch (error) {
8
+ if (error.code !== "ENOENT") throw error;
9
+ }
10
+ const root = fs.realpathSync(projectRoot);
11
+ let parent = path.dirname(file);
12
+ const missing = [];
13
+ while (!fs.existsSync(parent)) {
14
+ const next = path.dirname(parent);
15
+ if (next === parent) break;
16
+ missing.unshift(path.basename(parent));
17
+ parent = next;
18
+ }
19
+ const resolvedParent = path.join(fs.realpathSync(parent), ...missing);
20
+ const relative = path.relative(root, resolvedParent);
21
+ if (relative === ".." || relative.startsWith(`..${path.sep}`) || path.isAbsolute(relative)) throw new Error(`${file} has a parent directory outside the project`);
22
+ };
23
+ export { assertSafeProjectFile };
24
+
25
+ //# sourceMappingURL=safe-project-file.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"safe-project-file.js","names":[],"sources":["../../src/lib/safe-project-file.ts"],"sourcesContent":["import fs from \"node:fs\";\nimport path from \"node:path\";\n\nexport const assertSafeProjectFile = (file: string, projectRoot: string) => {\n try {\n if (fs.lstatSync(file).isSymbolicLink()) {\n throw new Error(`${file} is a symbolic link`);\n }\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== \"ENOENT\") throw error;\n }\n\n const root = fs.realpathSync(projectRoot);\n let parent = path.dirname(file);\n const missing: string[] = [];\n while (!fs.existsSync(parent)) {\n const next = path.dirname(parent);\n if (next === parent) break;\n missing.unshift(path.basename(parent));\n parent = next;\n }\n const resolvedParent = path.join(fs.realpathSync(parent), ...missing);\n const relative = path.relative(root, resolvedParent);\n if (\n relative === \"..\" ||\n relative.startsWith(`..${path.sep}`) ||\n path.isAbsolute(relative)\n ) {\n throw new Error(`${file} has a parent directory outside the project`);\n }\n};\n"],"mappings":";;;AAGA,MAAa,yBAAyB,MAAc,gBAAwB;CAC1E,IAAI;EACF,IAAI,GAAG,UAAU,IAAI,CAAC,CAAC,eAAe,GACpC,MAAM,IAAI,MAAM,GAAG,KAAK,oBAAoB;CAEhD,SAAS,OAAO;EACd,IAAK,MAAgC,SAAS,UAAU,MAAM;CAChE;CAEA,MAAM,OAAO,GAAG,aAAa,WAAW;CACxC,IAAI,SAAS,KAAK,QAAQ,IAAI;CAC9B,MAAM,UAAoB,CAAC;CAC3B,OAAO,CAAC,GAAG,WAAW,MAAM,GAAG;EAC7B,MAAM,OAAO,KAAK,QAAQ,MAAM;EAChC,IAAI,SAAS,QAAQ;EACrB,QAAQ,QAAQ,KAAK,SAAS,MAAM,CAAC;EACrC,SAAS;CACX;CACA,MAAM,iBAAiB,KAAK,KAAK,GAAG,aAAa,MAAM,GAAG,GAAG,OAAO;CACpE,MAAM,WAAW,KAAK,SAAS,MAAM,cAAc;CACnD,IACE,aAAa,QACb,SAAS,WAAW,KAAK,KAAK,KAAK,KACnC,KAAK,WAAW,QAAQ,GAExB,MAAM,IAAI,MAAM,GAAG,KAAK,4CAA4C;AAExE"}
@@ -4,7 +4,7 @@ import * as fs$1 from "node:fs";
4
4
  import path from "node:path";
5
5
  import { fileURLToPath } from "node:url";
6
6
  import debug from "debug";
7
- //#region src/lib/transform.ts
7
+ // src/lib/transform.ts
8
8
  const log = debug("codemod:transform");
9
9
  const __filename = fileURLToPath(import.meta.url);
10
10
  const __dirname = path.dirname(__filename);
@@ -70,7 +70,6 @@ async function transform(codemod, source, transformOptions, options = { logStatu
70
70
  }
71
71
  return [];
72
72
  }
73
- //#endregion
74
73
  export { getRelevantFiles, transform };
75
74
 
76
75
  //# sourceMappingURL=transform.js.map
@@ -4,7 +4,7 @@ import installEdgeLib from "./install-edge-lib.js";
4
4
  import installAiSdkLib from "./install-ai-sdk-lib.js";
5
5
  import debug from "debug";
6
6
  import { Presets, SingleBar } from "cli-progress";
7
- //#region src/lib/upgrade.ts
7
+ // src/lib/upgrade.ts
8
8
  const bundle = [
9
9
  "v0-9/edge-package-split",
10
10
  "v0-11/content-part-to-message-part",
@@ -63,7 +63,6 @@ async function upgrade(options) {
63
63
  log("Upgrade complete.");
64
64
  logger.success("Upgrade complete!");
65
65
  }
66
- //#endregion
67
66
  export { upgrade };
68
67
 
69
68
  //# sourceMappingURL=upgrade.js.map
@@ -1,7 +1,7 @@
1
1
  import { logger } from "./logger.js";
2
2
  import * as fs$1 from "node:fs";
3
3
  import * as path$1 from "node:path";
4
- //#region src/lib/utils/config.ts
4
+ // src/lib/utils/config.ts
5
5
  const CONFIG_FILE_NAMES = ["assistant-ui.json", "components.json"];
6
6
  function getConfig(cwd = process.cwd()) {
7
7
  for (const fileName of CONFIG_FILE_NAMES) {
@@ -23,7 +23,6 @@ function saveConfig(config, cwd = process.cwd()) {
23
23
  function hasConfig(cwd = process.cwd()) {
24
24
  return CONFIG_FILE_NAMES.some((fileName) => fs$1.existsSync(path$1.join(cwd, fileName)));
25
25
  }
26
- //#endregion
27
26
  export { getConfig, hasConfig, saveConfig };
28
27
 
29
28
  //# sourceMappingURL=config.js.map
@@ -1,5 +1,5 @@
1
1
  import { downloadTemplate } from "giget";
2
- //#region src/lib/utils/download.ts
2
+ // src/lib/utils/download.ts
3
3
  const DOWNLOAD_TIMEOUT_MS = 3e4;
4
4
  function resolveGitHubAuthToken() {
5
5
  return (process.env.GIGET_AUTH ?? process.env.GITHUB_TOKEN ?? process.env.GH_TOKEN)?.trim() || void 0;
@@ -35,7 +35,6 @@ async function withStagedDownload(source, options, timeoutMessage, cleanup, cons
35
35
  }
36
36
  }
37
37
  }
38
- //#endregion
39
38
  export { DOWNLOAD_TIMEOUT_MS, resolveGitHubAuthToken, withStagedDownload };
40
39
 
41
40
  //# sourceMappingURL=download.js.map
@@ -1,7 +1,7 @@
1
1
  import * as fs$1 from "node:fs";
2
2
  import * as path$1 from "node:path";
3
3
  import { sync } from "glob";
4
- //#region src/lib/utils/file-scanner.ts
4
+ // src/lib/utils/file-scanner.ts
5
5
  function* readProjectFiles(pattern, options) {
6
6
  const files = sync(pattern, options);
7
7
  for (const file of files) {
@@ -32,7 +32,6 @@ function scanForImport(importPattern, options = {}) {
32
32
  })) if (patterns.some((p) => content.includes(p))) return true;
33
33
  return false;
34
34
  }
35
- //#endregion
36
35
  export { readProjectFiles, scanForImport };
37
36
 
38
37
  //# sourceMappingURL=file-scanner.js.map
@@ -1,5 +1,5 @@
1
1
  import chalk from "chalk";
2
- //#region src/lib/utils/logger.ts
2
+ // src/lib/utils/logger.ts
3
3
  const logger = {
4
4
  info: (message) => {
5
5
  console.log(chalk.blue(message));
@@ -20,7 +20,6 @@ const logger = {
20
20
  console.log("");
21
21
  }
22
22
  };
23
- //#endregion
24
23
  export { logger };
25
24
 
26
25
  //# sourceMappingURL=logger.js.map
@@ -1,7 +1,7 @@
1
1
  import { logger } from "./logger.js";
2
2
  import { askQuestion, installPackage, isPackageInstalled } from "./package-manager.js";
3
3
  import { scanForImport } from "./file-scanner.js";
4
- //#region src/lib/utils/package-installer.ts
4
+ // src/lib/utils/package-installer.ts
5
5
  async function installPackageIfNeeded(config) {
6
6
  if (!scanForImport(config.importPatterns)) {
7
7
  logger.info(config.notFoundMessage);
@@ -16,7 +16,6 @@ async function installPackageIfNeeded(config) {
16
16
  if (!await installPackage(config.packageName)) throw new Error(`Failed to install ${config.packageName}`);
17
17
  } else logger.info("Skipping installation.");
18
18
  }
19
- //#endregion
20
19
  export { installPackageIfNeeded };
21
20
 
22
21
  //# sourceMappingURL=package-installer.js.map
@@ -1,11 +1,10 @@
1
1
  import { logger } from "./logger.js";
2
- //#region src/lib/utils/package-json.ts
2
+ // src/lib/utils/package-json.ts
3
3
  function logPackageJsonParseError(packageJsonPath, commandName) {
4
4
  logger.error("Could not parse package.json.");
5
5
  console.error(`Package path: ${packageJsonPath}`);
6
6
  console.error(`Fix the JSON syntax in that file, then run: assistant-ui ${commandName}`);
7
7
  }
8
- //#endregion
9
8
  export { logPackageJsonParseError };
10
9
 
11
10
  //# sourceMappingURL=package-json.js.map
@@ -4,7 +4,7 @@ import * as fs$1 from "node:fs";
4
4
  import * as path$1 from "node:path";
5
5
  import { detect } from "detect-package-manager";
6
6
  import * as readline from "node:readline";
7
- //#region src/lib/utils/package-manager.ts
7
+ // src/lib/utils/package-manager.ts
8
8
  function dlxCommand(pm) {
9
9
  switch (pm) {
10
10
  case "pnpm": return ["pnpm", ["dlx"]];
@@ -106,7 +106,6 @@ async function installPackage(packageName, cwd) {
106
106
  return false;
107
107
  }
108
108
  }
109
- //#endregion
110
109
  export { askQuestion, dlxCommand, getInstallCommand, installPackage, isPackageInstalled, resolvePackageManager, resolvePackageManagerForCwd };
111
110
 
112
111
  //# sourceMappingURL=package-manager.js.map
@@ -1,6 +1,6 @@
1
1
  import * as fs$1 from "node:fs";
2
2
  import * as path$1 from "node:path";
3
- //#region src/lib/utils/registry.ts
3
+ // src/lib/utils/registry.ts
4
4
  const REGISTRY_BASE_URL = "https://r.assistant-ui.com";
5
5
  const SHARED_REGISTRY_ITEMS = /* @__PURE__ */ new Set(["utils"]);
6
6
  function detectRegistryPlatform(cwd) {
@@ -30,7 +30,6 @@ function resolveRegistryItemUrl(component, style, platform = "web") {
30
30
  if (style === void 0) return `${REGISTRY_BASE_URL}/base/${encodeURIComponent(component)}.json`;
31
31
  return `${style.startsWith("base-") ? `${REGISTRY_BASE_URL}/styles/${encodeURIComponent(style)}` : REGISTRY_BASE_URL}/${encodeURIComponent(component)}.json`;
32
32
  }
33
- //#endregion
34
33
  export { SHARED_REGISTRY_ITEMS, detectRegistryPlatform, getComponentsJsonStyle, resolveQuickStartRegistryUrl, resolveRegistryItemUrl };
35
34
 
36
35
  //# sourceMappingURL=registry.js.map
@@ -1,6 +1,6 @@
1
1
  import * as fs$1 from "node:fs";
2
2
  import * as path$1 from "node:path";
3
- //#region src/lib/utils/workspace.ts
3
+ // src/lib/utils/workspace.ts
4
4
  function resolveRealPath(inputPath) {
5
5
  const resolved = path$1.resolve(inputPath);
6
6
  try {
@@ -22,7 +22,6 @@ function findWorkspaceRoot(cwd) {
22
22
  dir = path$1.dirname(dir);
23
23
  }
24
24
  }
25
- //#endregion
26
25
  export { findWorkspaceRoot, resolveRealPath };
27
26
 
28
27
  //# sourceMappingURL=workspace.js.map
package/dist/program.js CHANGED
@@ -9,11 +9,10 @@ import { mcp } from "./commands/mcp.js";
9
9
  import { update } from "./commands/update.js";
10
10
  import { codemodCommand, upgradeCommand } from "./commands/upgrade.js";
11
11
  import { Command } from "commander";
12
- //#region src/program.ts
12
+ // src/program.ts
13
13
  function buildProgram() {
14
14
  return new Command().name("assistant-ui").description("add components and dependencies to your project").addCommand(add).addCommand(create).addCommand(init).addCommand(mcp).addCommand(codemodCommand).addCommand(upgradeCommand).addCommand(update).addCommand(agent).addCommand(cloud).addCommand(info).addCommand(doctor);
15
15
  }
16
- //#endregion
17
16
  export { buildProgram };
18
17
 
19
18
  //# sourceMappingURL=program.js.map
package/dist/run.js CHANGED
@@ -1,9 +1,8 @@
1
1
  import { buildProgram } from "./program.js";
2
- //#region src/run.ts
2
+ // src/run.ts
3
3
  async function runCli() {
4
4
  await buildProgram().parseAsync();
5
5
  }
6
- //#endregion
7
6
  export { runCli };
8
7
 
9
8
  //# sourceMappingURL=run.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "assistant-ui",
3
- "version": "0.0.125",
3
+ "version": "0.0.127",
4
4
  "description": "CLI for assistant-ui",
5
5
  "keywords": [
6
6
  "cli",
@@ -39,20 +39,20 @@
39
39
  "glob": "^13.0.6",
40
40
  "jscodeshift": "^17.4.0",
41
41
  "jsonc-parser": "^3.3.1",
42
- "react": "^19.3.0",
42
+ "react": "^19.3.1",
43
43
  "semver": "^7.8.5",
44
- "statewire": "^0.19.4"
44
+ "statewire": "^0.22.1"
45
45
  },
46
46
  "devDependencies": {
47
- "@assistant-ui/x-buildutils": "0.0.30",
47
+ "@assistant-ui/x-buildutils": "0.0.32",
48
48
  "@types/cli-progress": "^3.11.6",
49
49
  "@types/cross-spawn": "^6.0.6",
50
50
  "@types/debug": "^4.1.13",
51
51
  "@types/jscodeshift": "^17.3.0",
52
- "@types/node": "^26.6.4",
52
+ "@types/node": "^26.6.5",
53
53
  "@types/semver": "^7.8.0",
54
- "@vitest/coverage-v8": "^5.0.3",
55
- "vitest": "^5.0.3"
54
+ "@vitest/coverage-v8": "^5.0.5",
55
+ "vitest": "^5.0.5"
56
56
  },
57
57
  "publishConfig": {
58
58
  "access": "public",
@@ -11,6 +11,7 @@ const {
11
11
  cloudAccessToken,
12
12
  savedCloudAccessToken,
13
13
  runCloudCommand,
14
+ sendCloudCommand,
14
15
  loginToCloud,
15
16
  provisionCloudHarness,
16
17
  scaffold,
@@ -23,6 +24,7 @@ const {
23
24
  cloudAccessToken: vi.fn(),
24
25
  savedCloudAccessToken: vi.fn(),
25
26
  runCloudCommand: vi.fn(),
27
+ sendCloudCommand: vi.fn(),
26
28
  loginToCloud: vi.fn(),
27
29
  provisionCloudHarness: vi.fn(),
28
30
  scaffold: vi.fn(),
@@ -45,6 +47,7 @@ vi.mock("../lib/cloud-auth", async (importOriginal) => ({
45
47
  vi.mock("../lib/cloud-remote", async (importOriginal) => ({
46
48
  ...(await importOriginal<typeof import("../lib/cloud-remote")>()),
47
49
  runCloudCommand,
50
+ sendCloudCommand,
48
51
  }));
49
52
  vi.mock("../lib/cloud-provision", async (importOriginal) => ({
50
53
  ...(await importOriginal<typeof import("../lib/cloud-provision")>()),
@@ -102,6 +105,106 @@ const options = {
102
105
  };
103
106
 
104
107
  describe("cloud setup", () => {
108
+ it("creates a new organization and project through Cloud commands", async () => {
109
+ const directory = await fixture();
110
+ fetchOrganizations.mockResolvedValue([]);
111
+ fetchProjects.mockResolvedValue([]);
112
+ sendCloudCommand.mockReset();
113
+ sendCloudCommand
114
+ .mockResolvedValueOnce({
115
+ exitCode: 0,
116
+ stdout: JSON.stringify({
117
+ id: "org-new",
118
+ slug: "new-team",
119
+ name: "New",
120
+ }),
121
+ })
122
+ .mockResolvedValueOnce({
123
+ exitCode: 0,
124
+ stdout: JSON.stringify({
125
+ id: "project-new",
126
+ slug: "chat-app",
127
+ name: "Chat",
128
+ }),
129
+ });
130
+ provisionCloudHarness.mockResolvedValueOnce({
131
+ project_id: "project-new",
132
+ workspace_id: "shared-workspace",
133
+ harness_id: "harness-1",
134
+ harness_origin: "https://harness.example.com",
135
+ api_origin: "https://project.example.com",
136
+ api_key: "cloud-server-key",
137
+ });
138
+ await setupCloud(directory, {
139
+ ...options,
140
+ newOrg: "new-team",
141
+ newProject: "chat-app",
142
+ name: "Chat",
143
+ });
144
+ expect(sendCloudCommand.mock.calls).toEqual([
145
+ [
146
+ options.apiUrl,
147
+ ["orgs", "create", "new-team", "--name", "Chat", "--json"],
148
+ "oauth-access",
149
+ ],
150
+ [
151
+ options.apiUrl,
152
+ [
153
+ "projects",
154
+ "create",
155
+ "chat-app",
156
+ "--name",
157
+ "Chat",
158
+ "--org",
159
+ "org-new",
160
+ "--json",
161
+ ],
162
+ "oauth-access",
163
+ ],
164
+ ]);
165
+ expect(createProject).not.toHaveBeenCalled();
166
+ expect(provisionCloudHarness).toHaveBeenLastCalledWith(
167
+ options.apiUrl,
168
+ "oauth-access",
169
+ expect.objectContaining({ org_id: "org-new", project_id: "project-new" }),
170
+ );
171
+ });
172
+
173
+ it("refuses a creation answer without an id, slug and name", async () => {
174
+ const directory = await fixture();
175
+ fetchProjects.mockResolvedValue([]);
176
+ sendCloudCommand.mockReset();
177
+ const before = provisionCloudHarness.mock.calls.length;
178
+ for (const stdout of [
179
+ JSON.stringify({ project: { id: "p" } }),
180
+ JSON.stringify({ id: "", slug: "chat-app", name: "Chat" }),
181
+ "not json",
182
+ ]) {
183
+ sendCloudCommand.mockResolvedValueOnce({ exitCode: 0, stdout });
184
+ await expect(
185
+ setupCloud(directory, { ...options, newProject: "chat-app" }),
186
+ ).rejects.toThrow(/Unexpected response from `projects create/);
187
+ }
188
+ expect(provisionCloudHarness.mock.calls.length).toBe(before);
189
+ });
190
+
191
+ it("stops with the Cloud command's error when creation is refused", async () => {
192
+ const directory = await fixture();
193
+ fetchProjects.mockResolvedValue([]);
194
+ sendCloudCommand.mockReset();
195
+ sendCloudCommand.mockResolvedValueOnce({
196
+ exitCode: 1,
197
+ stderr: "You don't have permission to create projects in team.\n",
198
+ });
199
+ const before = provisionCloudHarness.mock.calls.length;
200
+ await expect(
201
+ setupCloud(directory, { ...options, newProject: "chat-app" }),
202
+ ).rejects.toThrow(
203
+ "Could not create project: You don't have permission to create projects in team.",
204
+ );
205
+ expect(provisionCloudHarness.mock.calls.length).toBe(before);
206
+ });
207
+
105
208
  it("selects an existing project and scaffolds a shared harness with server-only credentials", async () => {
106
209
  const directory = await fixture();
107
210
  await setupCloud(directory, { ...options, org: "team", project: "chat" });
@@ -293,4 +396,57 @@ describe("cloud remote forwarding", () => {
293
396
  expect(savedCloudAccessToken).toHaveBeenCalled();
294
397
  expect(cloudAccessToken).not.toHaveBeenCalled();
295
398
  });
399
+
400
+ it("answers help for a local command here, with its flags", async () => {
401
+ const write = vi
402
+ .spyOn(process.stdout, "write")
403
+ .mockImplementation(() => true);
404
+ try {
405
+ await expect(forwarded(["help", "setup"])).resolves.toEqual([]);
406
+ const text = write.mock.calls.map(([chunk]) => String(chunk)).join("");
407
+ expect(text).toMatch(/--new-project <slug>/);
408
+ expect(text).toMatch(/--backend-url <url>/);
409
+ } finally {
410
+ write.mockRestore();
411
+ }
412
+ });
413
+
414
+ it("sends the directory defaults and the action handlers along", async () => {
415
+ runCloudCommand.mockImplementationOnce(async (_args, options) => {
416
+ expect(typeof options.defaults).toBe("function");
417
+ expect(typeof options.openUrl).toBe("function");
418
+ return 0;
419
+ });
420
+ await cloud.parseAsync(["projects", "show"], { from: "user" });
421
+ expect(runCloudCommand).toHaveBeenCalled();
422
+ });
423
+ });
424
+
425
+ describe("cloud --no-open", () => {
426
+ const sent = async (argv: string[]) => {
427
+ runCloudCommand.mockClear();
428
+ runCloudCommand.mockResolvedValue(0);
429
+ await cloud.parseAsync(argv, { from: "user" });
430
+ const [args, options] = runCloudCommand.mock.calls[0]!;
431
+ return { args, noOpen: options.noOpen };
432
+ };
433
+
434
+ it("is the client's flag before --, and the remote command's after it", async () => {
435
+ await expect(
436
+ sent(["projects", "list", "--no-open", "--json"]),
437
+ ).resolves.toEqual({
438
+ args: ["projects", "list", "--json"],
439
+ noOpen: true,
440
+ });
441
+ await expect(
442
+ sent(["projects", "show", "--", "--no-open"]),
443
+ ).resolves.toEqual({
444
+ args: ["projects", "show", "--no-open"],
445
+ noOpen: false,
446
+ });
447
+ await expect(sent(["projects", "list"])).resolves.toEqual({
448
+ args: ["projects", "list"],
449
+ noOpen: false,
450
+ });
451
+ });
296
452
  });