@alexkroman1/aai-cli 1.8.3 → 1.9.0

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 (31) hide show
  1. package/dist/_agent-cHGzbDVG.mjs +108 -0
  2. package/dist/_api-client-yJD7xGfd.mjs +47 -0
  3. package/dist/_bundler-BRQFvx00.mjs +62 -0
  4. package/dist/_config-zV70t71V.mjs +125 -0
  5. package/dist/_dev-server-CBrIeDoI.mjs +214 -0
  6. package/dist/{_init-Bh5etNEh.mjs → _init-y7K-dzni.mjs} +17 -43
  7. package/dist/{_output-vvoR6N1x.mjs → _output-fy2bXRNb.mjs} +12 -19
  8. package/dist/{_ui-nOp7hFVy.mjs → _ui-YqQ6Fi8K.mjs} +14 -20
  9. package/dist/_utils-BeU10C7O.mjs +55 -0
  10. package/dist/_vite-env-CmXG4ZAu.mjs +31 -0
  11. package/dist/cli.mjs +41 -40
  12. package/dist/client-bundler-D4VKqCxw.mjs +125 -0
  13. package/dist/client-bundler.mjs +3 -0
  14. package/dist/{delete-BEC2ZXbk.mjs → delete-DE35s3d5.mjs} +7 -8
  15. package/dist/{deploy-D8uMWSDH.mjs → deploy-C0LittrE.mjs} +20 -18
  16. package/dist/{dev-D2EwGHYi.mjs → dev-BvjnXK2x.mjs} +10 -3
  17. package/dist/{init-GWTdzrrm.mjs → init-kYsRaf7e.mjs} +29 -75
  18. package/dist/{secret-DlSN4FdF.mjs → secret-D-90QtDQ.mjs} +14 -16
  19. package/dist/{test-BLYrV5ap.mjs → test-C6jwCnFu.mjs} +30 -5
  20. package/dist/types.mjs +2 -0
  21. package/dist/worker-bundler.mjs +68 -0
  22. package/package.json +24 -13
  23. package/dist/_agent-De8f1JdZ.mjs +0 -38
  24. package/dist/_api-client-Cf9Lv2Rw.mjs +0 -46
  25. package/dist/_bundler-CMMSjh9o.mjs +0 -143
  26. package/dist/_config-B0FXR5GQ.mjs +0 -77
  27. package/dist/_default-html-BasMCgr9.mjs +0 -62
  28. package/dist/_dev-server-DMFyqc9v.mjs +0 -143
  29. package/dist/_utils-DZo3_J_v.mjs +0 -23
  30. package/dist/rolldown-runtime-uZa2dNXj.mjs +0 -15
  31. /package/dist/{_server-common-BVkNI-o4.mjs → _server-common-QpOTRZgi.mjs} +0 -0
@@ -1,13 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { t as __exportAll } from "./rolldown-runtime-uZa2dNXj.mjs";
3
2
  //#region _output.ts
4
- var _output_exports = /* @__PURE__ */ __exportAll({
5
- CliError: () => CliError,
6
- fail: () => fail,
7
- getOutputMode: () => getOutputMode,
8
- ok: () => ok,
9
- withOutput: () => withOutput
10
- });
11
3
  /**
12
4
  * Determine output mode from CLI flags and TTY state.
13
5
  *
@@ -21,19 +13,20 @@ function getOutputMode(args, isTTY = Boolean(process.stdout.isTTY)) {
21
13
  /**
22
14
  * Wrap a command function to handle output formatting.
23
15
  *
24
- * - `fn` does the work and returns a `CommandResult<T>`. It must not print.
25
- * - `humanRender` formats the result for human-readable TTY output.
16
+ * - `fn` does the work and returns a `CommandResult<T>`. Human-readable
17
+ * output is printed inside `fn` itself.
26
18
  * - In JSON mode, writes exactly one JSON line to stdout.
27
19
  */
28
- async function withOutput(mode, fn, humanRender) {
20
+ async function withOutput(mode, fn) {
29
21
  const result = await fn();
30
- if (mode === "json") {
31
- process.stdout.write(`${JSON.stringify(result)}\n`);
32
- if (!result.ok) process.exit(1);
33
- } else {
34
- humanRender(result);
35
- if (!result.ok) process.exit(1);
36
- }
22
+ if (mode === "json") await writeLine(`${JSON.stringify(result)}\n`);
23
+ if (!result.ok) process.exit(1);
24
+ }
25
+ /** Write a line to stdout, resolving only once it has been flushed. */
26
+ function writeLine(line) {
27
+ return new Promise((resolve) => {
28
+ process.stdout.write(line, () => resolve());
29
+ });
37
30
  }
38
31
  /** Create an ok result. */
39
32
  function ok(data) {
@@ -67,4 +60,4 @@ var CliError = class extends Error {
67
60
  }
68
61
  };
69
62
  //#endregion
70
- export { ok as a, getOutputMode as i, _output_exports as n, fail as r, CliError as t };
63
+ export { withOutput as a, ok as i, fail as n, writeLine as o, getOutputMode as r, CliError as t };
@@ -1,30 +1,24 @@
1
1
  #!/usr/bin/env node
2
- import { t as __exportAll } from "./rolldown-runtime-uZa2dNXj.mjs";
3
- import { log } from "@clack/prompts";
2
+ import * as p from "@clack/prompts";
4
3
  import { colorize } from "consola/utils";
5
4
  //#region _ui.ts
6
- var _ui_exports = /* @__PURE__ */ __exportAll({
7
- fmtUrl: () => fmtUrl,
8
- log: () => log$1,
9
- parsePort: () => parsePort,
10
- silenceOutput: () => silenceOutput
11
- });
12
5
  const noop = () => {};
13
- let _delegate = log;
6
+ let silenced = false;
14
7
  /** Log instance that delegates to clack (human mode) or no-ops (JSON mode). */
15
- const log$1 = new Proxy(log, { get(_target, prop, receiver) {
16
- return Reflect.get(_delegate, prop, receiver);
8
+ const log = new Proxy(p.log, { get(target, prop, receiver) {
9
+ return silenced ? noop : Reflect.get(target, prop, receiver);
17
10
  } });
18
11
  /** Replace all log methods with no-ops. Call once in JSON mode. */
19
12
  function silenceOutput() {
20
- _delegate = {
21
- info: noop,
22
- success: noop,
23
- error: noop,
24
- warn: noop,
25
- step: noop,
26
- message: noop
27
- };
13
+ silenced = true;
14
+ }
15
+ /** Unwrap a clack prompt result, exiting cleanly if the user cancelled. */
16
+ function unwrapCancel(result) {
17
+ if (p.isCancel(result)) {
18
+ p.cancel("Setup cancelled");
19
+ process.exit(0);
20
+ }
21
+ return result;
28
22
  }
29
23
  /** Format a URL for display. */
30
24
  function fmtUrl(url) {
@@ -37,4 +31,4 @@ function parsePort(raw) {
37
31
  return port;
38
32
  }
39
33
  //#endregion
40
- export { silenceOutput as a, parsePort as i, fmtUrl as n, log$1 as r, _ui_exports as t };
34
+ export { unwrapCancel as a, silenceOutput as i, log as n, parsePort as r, fmtUrl as t };
@@ -0,0 +1,55 @@
1
+ #!/usr/bin/env node
2
+ import path from "node:path";
3
+ import fs from "node:fs/promises";
4
+ //#region _utils.ts
5
+ /** Resolve the working directory from INIT_CWD or process.cwd(). */
6
+ function resolveCwd() {
7
+ return process.env.INIT_CWD || process.cwd();
8
+ }
9
+ /**
10
+ * Extract a message from an unknown error. Local copy of `errorMessage` from
11
+ * `@alexkroman1/aai` — importing the root barrel pulls zod into every CLI
12
+ * invocation (including `aai --help`), so the one-liner lives here instead.
13
+ */
14
+ function errorMessage(err) {
15
+ return err instanceof Error ? err.message : String(err);
16
+ }
17
+ /**
18
+ * Extract a stack (falling back to the message) from an unknown error. Local
19
+ * copy of `errorDetail` from `@alexkroman1/aai` for the same reason as
20
+ * {@link errorMessage} above.
21
+ */
22
+ function errorDetail(err) {
23
+ return err instanceof Error ? err.stack ?? err.message : String(err);
24
+ }
25
+ /** True when `err` is a filesystem EEXIST error (target already exists). */
26
+ function isEexist(err) {
27
+ return err instanceof Error && "code" in err && err.code === "EEXIST";
28
+ }
29
+ /** Validate that a module's default export is a valid agent definition. Throws if invalid. */
30
+ function validateAgentExport(mod) {
31
+ if (!mod?.name || typeof mod.name !== "string") throw new Error("agent.ts must export default agent({ name: ... })");
32
+ }
33
+ async function fileExists(p) {
34
+ try {
35
+ await fs.access(p);
36
+ return true;
37
+ } catch {
38
+ return false;
39
+ }
40
+ }
41
+ /** Read and parse a JSON file. Returns null if the file is missing or malformed. */
42
+ async function readJson(filePath) {
43
+ try {
44
+ return JSON.parse(await fs.readFile(filePath, "utf-8"));
45
+ } catch {
46
+ return null;
47
+ }
48
+ }
49
+ /** Write `data` as pretty-printed JSON (+ trailing newline), creating parent dirs. */
50
+ async function writeJson(filePath, data) {
51
+ await fs.mkdir(path.dirname(filePath), { recursive: true });
52
+ await fs.writeFile(filePath, `${JSON.stringify(data, null, 2)}\n`);
53
+ }
54
+ //#endregion
55
+ export { readJson as a, writeJson as c, isEexist as i, errorMessage as n, resolveCwd as o, fileExists as r, validateAgentExport as s, errorDetail as t };
@@ -0,0 +1,31 @@
1
+ #!/usr/bin/env node
2
+ //#region _vite-env.ts
3
+ /**
4
+ * Run a Vite build without letting it mutate the calling process's env.
5
+ *
6
+ * Vite's `build()` sets `process.env.NODE_ENV = "production"` when NODE_ENV is
7
+ * unset — a global, permanent side effect on whatever process invoked it. That
8
+ * is fine for a one-shot `aai build`, but both long-lived callers are broken by
9
+ * it:
10
+ *
11
+ * - `aai dev` rebuilds on every file change, so the first rebuild would flip
12
+ * the dev server into production mode.
13
+ * - The platform studio builds inside the server process, where flipping
14
+ * NODE_ENV makes the sandbox demand gVisor ("gVisor (runsc) is required in
15
+ * production but not found on PATH") and refuse every subsequent deploy on a
16
+ * dev machine.
17
+ *
18
+ * Snapshot and restore rather than pinning a value: callers that legitimately
19
+ * run with NODE_ENV=production must keep it.
20
+ */
21
+ async function withPreservedNodeEnv(fn) {
22
+ const saved = process.env.NODE_ENV;
23
+ try {
24
+ return await fn();
25
+ } finally {
26
+ if (saved === void 0) delete process.env.NODE_ENV;
27
+ else process.env.NODE_ENV = saved;
28
+ }
29
+ }
30
+ //#endregion
31
+ export { withPreservedNodeEnv as t };
package/dist/cli.mjs CHANGED
@@ -1,11 +1,10 @@
1
1
  #!/usr/bin/env node
2
- import { i as getOutputMode, r as fail, t as CliError } from "./_output-vvoR6N1x.mjs";
3
- import { a as silenceOutput } from "./_ui-nOp7hFVy.mjs";
4
- import { n as resolveCwd, t as fileExists } from "./_utils-DZo3_J_v.mjs";
2
+ import { a as withOutput, n as fail, o as writeLine, r as getOutputMode, t as CliError } from "./_output-fy2bXRNb.mjs";
3
+ import { i as silenceOutput, n as log } from "./_ui-YqQ6Fi8K.mjs";
4
+ import { n as errorMessage, o as resolveCwd, r as fileExists } from "./_utils-BeU10C7O.mjs";
5
5
  import { existsSync, readFileSync } from "node:fs";
6
6
  import path from "node:path";
7
7
  import { fileURLToPath } from "node:url";
8
- import { errorMessage } from "@alexkroman1/aai";
9
8
  import { defineCommand, runMain } from "citty";
10
9
  //#region cli.ts
11
10
  /** Shared arg definitions for citty commands. */
@@ -57,26 +56,33 @@ async function handleErrors(mode, fn) {
57
56
  const hint = err instanceof CliError ? err.hint : void 0;
58
57
  if (mode === "json") {
59
58
  const result = fail(code, errorMessage(err), hint);
60
- process.stdout.write(`${JSON.stringify(result)}\n`);
59
+ await writeLine(`${JSON.stringify(result)}\n`);
61
60
  process.exit(1);
62
61
  }
63
- const { log } = await import("./_ui-nOp7hFVy.mjs").then((n) => n.t);
64
62
  log.error(errorMessage(err));
65
63
  process.exit(1);
66
64
  }
67
65
  }
68
66
  /**
69
67
  * Run a command body with standard error handling, output mode resolution, and withOutput wrapping.
70
- * `setYes` controls whether json mode sets `args.yes = true` (default true for most commands).
68
+ *
69
+ * - `setYes`: json mode sets `args.yes = true` (only meaningful for commands with a `yes` arg).
70
+ * - `apiKey`: prompt for / resolve the AssemblyAI API key before the command body runs
71
+ * (default true — pass false for commands that never talk to the platform).
71
72
  */
72
73
  async function runCommand(args, fn, opts = {}) {
73
74
  const mode = getOutputMode(args);
74
75
  if (mode === "json") {
75
76
  silenceOutput();
76
- if (opts.setYes !== false) args.yes = true;
77
+ if (opts.setYes) args.yes = true;
77
78
  }
78
- const { withOutput } = await import("./_output-vvoR6N1x.mjs").then((n) => n.n);
79
- await handleErrors(mode, () => withOutput(mode, () => fn(mode), () => {}));
79
+ await handleErrors(mode, () => withOutput(mode, async () => {
80
+ if (opts.apiKey !== false) {
81
+ const { ensureApiKey } = await import("./_config-zV70t71V.mjs").then((n) => n.t);
82
+ await ensureApiKey();
83
+ }
84
+ return fn(mode);
85
+ }));
80
86
  }
81
87
  const init = defineCommand({
82
88
  meta: {
@@ -113,16 +119,18 @@ const init = defineCommand({
113
119
  },
114
120
  async run({ args }) {
115
121
  await runCommand(args, async (mode) => {
116
- const { executeInit } = await import("./init-GWTdzrrm.mjs");
122
+ const { executeInit } = await import("./init-kYsRaf7e.mjs");
117
123
  return executeInit({
118
124
  dir: args.dir,
119
125
  force: args.force,
120
126
  template: args.template,
121
127
  yes: args.yes,
122
- skipApi: args.skipApi,
123
128
  skipDeploy: args.skipDeploy,
124
129
  server: args.server
125
130
  }, mode === "json" ? { silent: true } : void 0);
131
+ }, {
132
+ setYes: true,
133
+ apiKey: !args.skipApi
126
134
  });
127
135
  }
128
136
  });
@@ -133,14 +141,12 @@ const dev = defineCommand({
133
141
  },
134
142
  args: {
135
143
  port: sharedArgs.port,
136
- server: sharedArgs.server,
137
- yes: sharedArgs.yes,
138
144
  json: sharedArgs.json
139
145
  },
140
146
  async run({ args }) {
141
147
  await runCommand(args, async () => {
142
148
  const cwd = await setup({ agent: true });
143
- const { executeDev } = await import("./dev-D2EwGHYi.mjs");
149
+ const { executeDev } = await import("./dev-BvjnXK2x.mjs");
144
150
  return executeDev({
145
151
  cwd,
146
152
  port: args.port
@@ -157,9 +163,9 @@ const test = defineCommand({
157
163
  async run({ args }) {
158
164
  await runCommand(args, async () => {
159
165
  const cwd = await setup();
160
- const { executeTest } = await import("./test-BLYrV5ap.mjs");
166
+ const { executeTest } = await import("./test-C6jwCnFu.mjs");
161
167
  return executeTest(cwd);
162
- }, { setYes: false });
168
+ }, { apiKey: false });
163
169
  }
164
170
  });
165
171
  const build = defineCommand({
@@ -168,8 +174,6 @@ const build = defineCommand({
168
174
  description: "Bundle agent without deploying"
169
175
  },
170
176
  args: {
171
- server: sharedArgs.server,
172
- yes: sharedArgs.yes,
173
177
  json: sharedArgs.json,
174
178
  skipTests: {
175
179
  type: "boolean",
@@ -180,12 +184,12 @@ const build = defineCommand({
180
184
  await runCommand(args, async () => {
181
185
  const cwd = await setup({ agent: true });
182
186
  if (!args.skipTests) {
183
- const { runVitest } = await import("./test-BLYrV5ap.mjs");
187
+ const { runVitest } = await import("./test-C6jwCnFu.mjs");
184
188
  runVitest(cwd);
185
189
  }
186
- const { executeBuild } = await import("./_bundler-CMMSjh9o.mjs");
190
+ const { executeBuild } = await import("./_bundler-BRQFvx00.mjs");
187
191
  return executeBuild(cwd);
188
- });
192
+ }, { apiKey: false });
189
193
  }
190
194
  });
191
195
  const deploy = defineCommand({
@@ -195,13 +199,12 @@ const deploy = defineCommand({
195
199
  },
196
200
  args: {
197
201
  server: sharedArgs.server,
198
- yes: sharedArgs.yes,
199
202
  json: sharedArgs.json
200
203
  },
201
204
  async run({ args }) {
202
205
  await runCommand(args, async () => {
203
206
  const cwd = await setup({ agent: true });
204
- const { executeDeploy } = await import("./deploy-D8uMWSDH.mjs");
207
+ const { executeDeploy } = await import("./deploy-C0LittrE.mjs");
205
208
  return executeDeploy({
206
209
  cwd,
207
210
  ...args.server ? { server: args.server } : {}
@@ -221,12 +224,12 @@ const del = defineCommand({
221
224
  async run({ args }) {
222
225
  await runCommand(args, async () => {
223
226
  const cwd = await setup();
224
- const { executeDelete } = await import("./delete-BEC2ZXbk.mjs");
227
+ const { executeDelete } = await import("./delete-DE35s3d5.mjs");
225
228
  return executeDelete({
226
229
  cwd,
227
230
  ...args.server ? { server: args.server } : {}
228
231
  });
229
- }, { setYes: false });
232
+ });
230
233
  }
231
234
  });
232
235
  const secret = defineCommand({
@@ -252,15 +255,11 @@ const secret = defineCommand({
252
255
  async run({ args }) {
253
256
  await runCommand(args, async (mode) => {
254
257
  const cwd = await setup();
255
- const { executeSecretPut, readStdin } = await import("./secret-DlSN4FdF.mjs");
258
+ const { executeSecretPut, readStdin } = await import("./secret-D-90QtDQ.mjs");
256
259
  const value = mode === "json" ? await readStdin() : void 0;
257
- if (mode === "json" && !value) {
258
- const result = fail("no_input", "No value provided", "Pipe secret value to stdin");
259
- process.stdout.write(`${JSON.stringify(result)}\n`);
260
- process.exit(1);
261
- }
260
+ if (mode === "json" && !value) throw new CliError("no_input", "No value provided", "Pipe secret value to stdin");
262
261
  return executeSecretPut(cwd, args.name, value, args.server);
263
- }, { setYes: false });
262
+ });
264
263
  }
265
264
  }),
266
265
  delete: defineCommand({
@@ -280,9 +279,9 @@ const secret = defineCommand({
280
279
  async run({ args }) {
281
280
  await runCommand(args, async () => {
282
281
  const cwd = await setup();
283
- const { executeSecretDelete } = await import("./secret-DlSN4FdF.mjs");
282
+ const { executeSecretDelete } = await import("./secret-D-90QtDQ.mjs");
284
283
  return executeSecretDelete(cwd, args.name, args.server);
285
- }, { setYes: false });
284
+ });
286
285
  }
287
286
  }),
288
287
  list: defineCommand({
@@ -297,9 +296,9 @@ const secret = defineCommand({
297
296
  async run({ args }) {
298
297
  await runCommand(args, async () => {
299
298
  const cwd = await setup();
300
- const { executeSecretList } = await import("./secret-DlSN4FdF.mjs");
299
+ const { executeSecretList } = await import("./secret-D-90QtDQ.mjs");
301
300
  return executeSecretList(cwd, args.server);
302
- }, { setYes: false });
301
+ });
303
302
  }
304
303
  })
305
304
  }
@@ -322,7 +321,7 @@ const mainCommand = defineCommand({
322
321
  });
323
322
  if (process.env.VITEST !== "true") {
324
323
  const sub = process.argv[2];
325
- const helpFlags = new Set([
324
+ const helpFlags = /* @__PURE__ */ new Set([
326
325
  "--help",
327
326
  "--version",
328
327
  "-h",
@@ -332,8 +331,10 @@ if (process.env.VITEST !== "true") {
332
331
  const defaultCmd = existsSync(path.join(resolveCwd(), "agent.ts")) ? "deploy" : "init";
333
332
  process.argv.splice(2, 0, defaultCmd);
334
333
  }
335
- const cmd = process.argv[2];
336
- (helpFlags.has(cmd ?? "") || cmd === "test" || cmd === "build" ? Promise.resolve() : import("./_config-B0FXR5GQ.mjs").then((n) => n.t).then((m) => m.ensureApiKey())).then(() => runMain(mainCommand));
334
+ runMain(mainCommand).catch((err) => {
335
+ log.error(errorMessage(err));
336
+ process.exitCode = 1;
337
+ });
337
338
  }
338
339
  //#endregion
339
340
  export { mainCommand };
@@ -0,0 +1,125 @@
1
+ #!/usr/bin/env node
2
+ import { r as fileExists } from "./_utils-BeU10C7O.mjs";
3
+ import { t as withPreservedNodeEnv } from "./_vite-env-CmXG4ZAu.mjs";
4
+ import { existsSync, unlinkSync, writeFileSync } from "node:fs";
5
+ import path from "node:path";
6
+ import fs from "node:fs/promises";
7
+ import { isTextAssetPath } from "@alexkroman1/aai";
8
+ import { build } from "vite";
9
+ //#region _default-html.ts
10
+ /**
11
+ * Default index.html for agents with a custom client.tsx but no index.html.
12
+ * Used by both the dev server (Vite HMR) and the production bundler.
13
+ * Users can override by placing their own index.html in the project root.
14
+ */
15
+ const DEFAULT_HTML = `<!DOCTYPE html>
16
+ <html lang="en">
17
+ <head>
18
+ <meta charset="UTF-8" />
19
+ <meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover" />
20
+ <title>aai</title>
21
+ <link rel="icon" href="data:," />
22
+ <style>html, body { background: #FBF8F2; margin: 0; }</style>
23
+ </head>
24
+ <body>
25
+ <main id="app"></main>
26
+ <script type="module" src="./client.tsx"><\/script>
27
+ </body>
28
+ </html>`;
29
+ /**
30
+ * Vite plugin that serves a fallback index.html in dev mode when one doesn't
31
+ * exist on disk. No-op if index.html exists (user override).
32
+ */
33
+ function fallbackHtmlPlugin(root) {
34
+ const htmlExists = existsSync(path.join(root, "index.html"));
35
+ return {
36
+ name: "aai-fallback-html",
37
+ configureServer(server) {
38
+ if (htmlExists) return;
39
+ server.middlewares.use((req, res, next) => {
40
+ if (req.url === "/" || req.url === "/index.html") {
41
+ server.transformIndexHtml("/", DEFAULT_HTML, req.originalUrl).then((html) => {
42
+ res.setHeader("Content-Type", "text/html");
43
+ res.end(html);
44
+ }, next);
45
+ return;
46
+ }
47
+ next();
48
+ });
49
+ }
50
+ };
51
+ }
52
+ /**
53
+ * Write a temporary index.html for Vite build (HTML must be on disk for build).
54
+ * Returns a cleanup function to remove it. No-op if index.html already exists.
55
+ */
56
+ function writeTempHtml(root) {
57
+ const htmlPath = path.join(root, "index.html");
58
+ if (existsSync(htmlPath)) return () => {};
59
+ writeFileSync(htmlPath, DEFAULT_HTML);
60
+ return () => {
61
+ try {
62
+ unlinkSync(htmlPath);
63
+ } catch {}
64
+ };
65
+ }
66
+ //#endregion
67
+ //#region client-bundler.ts
68
+ /**
69
+ * Client SPA bundling — the one implementation of "turn a `client.tsx` into
70
+ * deployable `clientFiles`".
71
+ *
72
+ * Public (no `_` prefix) because the platform's browser studio reuses it: a
73
+ * studio workspace is materialized to a directory and built through this same
74
+ * function, so a UI published from the browser is byte-identical to one
75
+ * deployed with `aai deploy`. Keep it that way — a second client bundler is
76
+ * how the two paths would silently drift.
77
+ *
78
+ * The studio differs from a CLI project in two ways, hence the options:
79
+ * it has no `vite.config.ts` to supply React/Tailwind plugins, and its files
80
+ * are untrusted so any config the workspace *does* contain must be ignored.
81
+ */
82
+ const DEFAULT_OUT_DIR = ".aai/client";
83
+ /**
84
+ * Build the client SPA with Vite if `client.tsx` exists.
85
+ * Returns a map of relative file paths to string contents for deploy,
86
+ * or `{}` when the project has no `client.tsx`.
87
+ */
88
+ async function buildClient(cwd, opts = {}) {
89
+ if (!await fileExists(path.join(cwd, "client.tsx"))) return {};
90
+ const outDir = opts.outDir ?? DEFAULT_OUT_DIR;
91
+ const clientDir = path.join(cwd, outDir);
92
+ const cleanupHtml = writeTempHtml(cwd);
93
+ try {
94
+ await withPreservedNodeEnv(() => build({
95
+ root: cwd,
96
+ base: "./",
97
+ logLevel: "silent",
98
+ ...opts.configFile === false && { configFile: false },
99
+ ...opts.plugins && { plugins: opts.plugins },
100
+ build: {
101
+ outDir,
102
+ emptyOutDir: true
103
+ }
104
+ }));
105
+ } finally {
106
+ cleanupHtml();
107
+ }
108
+ return readClientDir(clientDir);
109
+ }
110
+ /** Read a built client directory into an in-memory deploy payload. */
111
+ async function readClientDir(clientDir) {
112
+ const files = {};
113
+ const entries = await fs.readdir(clientDir, {
114
+ recursive: true,
115
+ withFileTypes: true
116
+ });
117
+ await Promise.all(entries.filter((entry) => entry.isFile()).map(async (entry) => {
118
+ const abs = path.join(entry.parentPath, entry.name);
119
+ const rel = path.relative(clientDir, abs).split(path.sep).join("/");
120
+ files[rel] = isTextAssetPath(rel) ? await fs.readFile(abs, "utf-8") : (await fs.readFile(abs)).toString("base64");
121
+ }));
122
+ return files;
123
+ }
124
+ //#endregion
125
+ export { fallbackHtmlPlugin as n, buildClient as t };
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ import { t as buildClient } from "./client-bundler-D4VKqCxw.mjs";
3
+ export { buildClient };
@@ -1,17 +1,16 @@
1
1
  #!/usr/bin/env node
2
- import { a as ok } from "./_output-vvoR6N1x.mjs";
3
- import { r as log } from "./_ui-nOp7hFVy.mjs";
4
- import { getServerInfo } from "./_agent-De8f1JdZ.mjs";
5
- import { t as apiRequestOrThrow } from "./_api-client-Cf9Lv2Rw.mjs";
2
+ import { i as ok } from "./_output-fy2bXRNb.mjs";
3
+ import { n as log } from "./_ui-YqQ6Fi8K.mjs";
4
+ import { r as getServerInfo } from "./_agent-cHGzbDVG.mjs";
5
+ import { t as apiRequest } from "./_api-client-yJD7xGfd.mjs";
6
6
  //#region _delete.ts
7
7
  async function runDelete(opts) {
8
- await apiRequestOrThrow(`${opts.url}/${opts.slug}`, {
8
+ await apiRequest(`${opts.url}/${opts.slug}`, {
9
9
  method: "DELETE",
10
10
  apiKey: opts.apiKey,
11
- action: "delete"
12
- }, {
11
+ action: "delete",
13
12
  hints: { 404: "The agent may not be deployed. Check `.aai/project.json` for the correct slug." },
14
- fetch: opts.fetch
13
+ ...opts.fetch ? { fetch: opts.fetch } : {}
15
14
  });
16
15
  }
17
16
  //#endregion
@@ -1,39 +1,41 @@
1
1
  #!/usr/bin/env node
2
- import { a as ok } from "./_output-vvoR6N1x.mjs";
3
- import { n as fmtUrl, r as log } from "./_ui-nOp7hFVy.mjs";
4
- import { i as writeProjectConfig, n as ensureApiKey, r as readProjectConfig } from "./_config-B0FXR5GQ.mjs";
5
- import { resolveServerUrl } from "./_agent-De8f1JdZ.mjs";
6
- import { buildAgentBundle } from "./_bundler-CMMSjh9o.mjs";
7
- import { t as resolveServerEnv } from "./_server-common-BVkNI-o4.mjs";
8
- import { t as apiRequestOrThrow } from "./_api-client-Cf9Lv2Rw.mjs";
2
+ import { s as writeProjectConfig } from "./_config-zV70t71V.mjs";
3
+ import { i as ok } from "./_output-fy2bXRNb.mjs";
4
+ import { n as log, t as fmtUrl } from "./_ui-YqQ6Fi8K.mjs";
5
+ import { a as resolveDeployTarget } from "./_agent-cHGzbDVG.mjs";
6
+ import { buildAgentBundle } from "./_bundler-BRQFvx00.mjs";
7
+ import { t as resolveServerEnv } from "./_server-common-QpOTRZgi.mjs";
8
+ import { t as apiRequest } from "./_api-client-yJD7xGfd.mjs";
9
+ import { gzipSync } from "node:zlib";
9
10
  //#region _deploy.ts
10
11
  async function runDeploy(opts) {
11
- const body = JSON.stringify({
12
+ const body = gzipSync(JSON.stringify({
12
13
  ...opts.slug ? { slug: opts.slug } : {},
13
14
  env: opts.env,
14
15
  worker: opts.bundle.worker,
15
16
  clientFiles: opts.bundle.clientFiles,
16
17
  agentConfig: opts.bundle.agentConfig
17
- });
18
- return { slug: (await (await apiRequestOrThrow(`${opts.url}/deploy`, {
18
+ }));
19
+ return { slug: (await apiRequest(`${opts.url}/deploy`, {
19
20
  method: "POST",
20
21
  body,
22
+ headers: {
23
+ "Content-Type": "application/json",
24
+ "Content-Encoding": "gzip"
25
+ },
21
26
  apiKey: opts.apiKey,
22
- action: "deploy"
23
- }, {
27
+ action: "deploy",
24
28
  hints: { 413: "Your bundle is too large. Try reducing dependencies or splitting your agent." },
25
- fetch: opts.fetch
26
- })).json()).slug };
29
+ ...opts.fetch ? { fetch: opts.fetch } : {}
30
+ })).slug };
27
31
  }
28
32
  //#endregion
29
33
  //#region deploy.ts
30
34
  async function executeDeploy(opts) {
31
35
  const { cwd } = opts;
32
- const projectConfig = await readProjectConfig(cwd);
33
- const serverUrl = resolveServerUrl(opts.server, projectConfig?.serverUrl);
34
- const bundle = await buildAgentBundle(cwd);
36
+ const { config: projectConfig, serverUrl, apiKey } = await resolveDeployTarget(cwd, opts.server);
37
+ const bundle = await buildAgentBundle(cwd, { minify: true });
35
38
  const slug = projectConfig?.slug;
36
- const apiKey = await ensureApiKey();
37
39
  const env = await resolveServerEnv(cwd);
38
40
  log.step(`Deploying${slug ? ` ${slug}` : ""}…`);
39
41
  const deployed = await runDeploy({
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env node
2
- import { a as ok } from "./_output-vvoR6N1x.mjs";
3
- import { i as parsePort, n as fmtUrl, r as log } from "./_ui-nOp7hFVy.mjs";
2
+ import { i as ok } from "./_output-fy2bXRNb.mjs";
3
+ import { n as log, r as parsePort, t as fmtUrl } from "./_ui-YqQ6Fi8K.mjs";
4
+ import { t as errorDetail } from "./_utils-BeU10C7O.mjs";
4
5
  import path from "node:path";
5
6
  import { colorize } from "consola/utils";
6
7
  //#region dev.ts
@@ -11,7 +12,7 @@ import { colorize } from "consola/utils";
11
12
  async function executeDev(opts) {
12
13
  const port = parsePort(opts.port);
13
14
  const agentName = path.basename(path.resolve(opts.cwd));
14
- const { startDevServer } = await import("./_dev-server-DMFyqc9v.mjs");
15
+ const { startDevServer } = await import("./_dev-server-CBrIeDoI.mjs");
15
16
  const cleanup = await startDevServer({
16
17
  cwd: opts.cwd,
17
18
  port
@@ -24,6 +25,12 @@ async function executeDev(opts) {
24
25
  };
25
26
  process.on("SIGINT", onSignal);
26
27
  process.on("SIGTERM", onSignal);
28
+ process.on("unhandledRejection", (err) => {
29
+ log.error(`Unhandled rejection: ${errorDetail(err)}`);
30
+ });
31
+ process.on("uncaughtException", (err) => {
32
+ log.error(`Uncaught exception: ${errorDetail(err)}`);
33
+ });
27
34
  return ok({ url });
28
35
  }
29
36
  //#endregion