@alexkroman1/aai-cli 5.8.1 → 5.10.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 (46) hide show
  1. package/README.md +5 -1
  2. package/bin.mjs +32 -0
  3. package/dist/{_agent-2nVugrN3.mjs → _agent-DS2PUJcl.mjs} +1 -1
  4. package/dist/{_bundler-Cjaxa2wi.mjs → _bundler-DC17suWN.mjs} +2 -2
  5. package/dist/_config-DMyolIk9.mjs +242 -0
  6. package/dist/_config.d.ts +28 -9
  7. package/dist/_dev-env.d.ts +38 -0
  8. package/dist/{_dev-server-BB5N8kdh.mjs → _dev-server-B3ivqyEd.mjs} +75 -55
  9. package/dist/_dev-server.d.ts +2 -2
  10. package/dist/{_init-Dei2JRmn.mjs → _init-CYLvYU-B.mjs} +3 -3
  11. package/dist/{_ui-8kOEB-JH.mjs → _output-CC300DzW.mjs} +1 -42
  12. package/dist/{_server-common-CnaP_Urf.mjs → _server-common-DX8Bfrf5.mjs} +1 -1
  13. package/dist/{_slug-api-CGJSST9B.mjs → _slug-api-fRNNR8tz.mjs} +1 -1
  14. package/dist/{_templates-BfyRyE7z.mjs → _templates-BWJOiWOO.mjs} +2 -2
  15. package/dist/{_typecheck-gate-DvE8S3aQ.mjs → _typecheck-gate-DB-PY0A3.mjs} +2 -1
  16. package/dist/_ui-DfwfDbT-.mjs +68 -0
  17. package/dist/_ui.d.ts +19 -0
  18. package/dist/{_utils-Ch0J4s6a.mjs → _utils-8KKw-bzi.mjs} +9 -2
  19. package/dist/_utils.d.ts +9 -2
  20. package/dist/{build-BXwDB78d.mjs → build-CACFbdQ4.mjs} +5 -4
  21. package/dist/cli.mjs +21 -20
  22. package/dist/{client-bundler-yiWoXrgb.mjs → client-bundler-DONm-khu.mjs} +1 -1
  23. package/dist/client-bundler.mjs +1 -1
  24. package/dist/{delete-DRNfvczK.mjs → delete-DEZ7u3u4.mjs} +6 -4
  25. package/dist/delete.d.ts +5 -0
  26. package/dist/{deploy-Cp-wgME3.mjs → deploy-Ch0d_jje.mjs} +8 -7
  27. package/dist/{dev-C4KyxouE.mjs → dev-CdeRcYiQ.mjs} +7 -6
  28. package/dist/{init-BpBbttOv.mjs → init-Nc6fB774.mjs} +6 -5
  29. package/dist/{login-AA_UdRI-.mjs → login-BeFUiU6M.mjs} +9 -9
  30. package/dist/scaffold/CLAUDE.md +39 -14
  31. package/dist/scaffold/package.json +3 -3
  32. package/dist/{secret-Dr0qnxeb.mjs → secret-4_dYyrpA.mjs} +3 -2
  33. package/dist/{storage-CoQB8d-u.mjs → storage-BTfErOOW.mjs} +3 -2
  34. package/dist/{studio-_UBBvh5V.mjs → studio-LNvXtWak.mjs} +7 -6
  35. package/dist/templates/dispatch-center/agent.ts +4 -6
  36. package/dist/templates/retail/agent.ts +4 -6
  37. package/dist/templates/retail/registry.test.ts +5 -3
  38. package/dist/templates/retail/resolve.test.ts +6 -4
  39. package/dist/templates/retail/seed.test.ts +21 -13
  40. package/dist/templates/retail/shared.test.ts +9 -5
  41. package/dist/templates/solo-rpg/agent.test.ts +7 -5
  42. package/dist/templates/solo-rpg/shared.ts +2 -2
  43. package/dist/{test-3Gq4pqH_.mjs → test-C-V98oC-.mjs} +4 -4
  44. package/dist/typecheck.mjs +65 -14
  45. package/package.json +5 -4
  46. package/dist/_config-Y5V-5Krn.mjs +0 -173
@@ -1,6 +1,4 @@
1
1
  #!/usr/bin/env node
2
- import { styleText } from "node:util";
3
- import * as p from "@clack/prompts";
4
2
  //#region _output.ts
5
3
  /**
6
4
  * Determine output mode from CLI flags and TTY state.
@@ -72,43 +70,4 @@ var CliError = class extends Error {
72
70
  }
73
71
  };
74
72
  //#endregion
75
- //#region _ui.ts
76
- const noop = () => {};
77
- let silenced = false;
78
- /** Log instance that delegates to clack (human mode) or no-ops (JSON mode). */
79
- const log = new Proxy(p.log, { get(target, prop, receiver) {
80
- return silenced ? noop : Reflect.get(target, prop, receiver);
81
- } });
82
- /** Replace all log methods with no-ops. Call once in JSON mode. */
83
- function silenceOutput() {
84
- silenced = true;
85
- }
86
- /**
87
- * Unwrap a clack prompt result, exiting cleanly if the user cancelled.
88
- * `message` lets the caller name what was cancelled (e.g. "Setup cancelled").
89
- */
90
- function unwrapCancel(result, message = "Cancelled") {
91
- if (p.isCancel(result)) {
92
- p.cancel(message);
93
- process.exit(0);
94
- }
95
- return result;
96
- }
97
- /** Format a URL for display. */
98
- function fmtUrl(url) {
99
- return styleText("cyanBright", url);
100
- }
101
- /**
102
- * Parse and validate a port string. Returns the numeric port or throws.
103
- *
104
- * Deliberately zod-free: this module loads on every CLI invocation
105
- * (including `aai --help`), and keeping zod off that path is the same
106
- * startup-cost invariant `_utils.ts` documents for its error helpers.
107
- */
108
- function parsePort(raw) {
109
- const port = raw.trim() === "" ? NaN : Number(raw);
110
- if (!Number.isInteger(port) || port < 0 || port > 65535) throw new Error(`Invalid port: ${raw}. Must be a number between 0 and 65535.`);
111
- return port;
112
- }
113
- //#endregion
114
- export { unwrapCancel as a, getOutputMode as c, writeLine as d, silenceOutput as i, installStdoutGuard as l, log as n, CliError as o, parsePort as r, fail as s, fmtUrl as t, ok as u };
73
+ export { ok as a, installStdoutGuard as i, fail as n, writeLine as o, getOutputMode as r, CliError as t };
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { r as errorCode } from "./_utils-Ch0J4s6a.mjs";
2
+ import { r as errorCode } from "./_utils-8KKw-bzi.mjs";
3
3
  import path from "node:path";
4
4
  import { parseEnv } from "node:util";
5
5
  import fs from "node:fs/promises";
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { n as getServerInfo } from "./_agent-2nVugrN3.mjs";
2
+ import { n as getServerInfo } from "./_agent-DS2PUJcl.mjs";
3
3
  import { n as apiRequest, t as HINT_NOT_DEPLOYED } from "./_api-client-B-upMGkc.mjs";
4
4
  //#region _slug-api.ts
5
5
  /**
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
- import { a as errorMessage } from "./_utils-Ch0J4s6a.mjs";
3
- import { t as getMonorepoRoot } from "./_agent-2nVugrN3.mjs";
2
+ import { a as errorMessage } from "./_utils-8KKw-bzi.mjs";
3
+ import { t as getMonorepoRoot } from "./_agent-DS2PUJcl.mjs";
4
4
  import { existsSync } from "node:fs";
5
5
  import path from "node:path";
6
6
  import fs from "node:fs/promises";
@@ -1,5 +1,6 @@
1
1
  #!/usr/bin/env node
2
- import { n as log, o as CliError } from "./_ui-8kOEB-JH.mjs";
2
+ import { t as CliError } from "./_output-CC300DzW.mjs";
3
+ import { n as log } from "./_ui-DfwfDbT-.mjs";
3
4
  import { typecheckProject } from "./typecheck.mjs";
4
5
  //#region _typecheck-gate.ts
5
6
  /**
@@ -0,0 +1,68 @@
1
+ #!/usr/bin/env node
2
+ import { styleText } from "node:util";
3
+ import * as p from "@clack/prompts";
4
+ //#region _ui.ts
5
+ const noop = () => {};
6
+ let silenced = false;
7
+ /** Log instance that delegates to clack (human mode) or no-ops (JSON mode). */
8
+ const log = new Proxy(p.log, { get(target, prop, receiver) {
9
+ return silenced ? noop : Reflect.get(target, prop, receiver);
10
+ } });
11
+ /** Replace all log methods with no-ops. Call once in JSON mode. */
12
+ function silenceOutput() {
13
+ silenced = true;
14
+ }
15
+ /**
16
+ * Emit a message that must survive JSON mode — human mode gets the normal
17
+ * clack styling, JSON mode gets a plain line on STDERR.
18
+ *
19
+ * `silenceOutput` no-ops every `log` method so that JSON mode's contract
20
+ * ("exactly one result line on stdout") holds. That is right for
21
+ * request/response commands, and wrong for LONG-RUNNING ones: `aai dev`
22
+ * writes its single JSON line at startup and then keeps running, so every
23
+ * later message — a failed rebuild, an unhandled rejection, "the dev server
24
+ * is down; save a file to retry" — was silenced for the rest of the process.
25
+ * And JSON mode is AUTO-DETECTED on a pipe, so that is the normal case:
26
+ * `aai dev > dev.log`, a process supervisor, or a container all hid every
27
+ * build failure, leaving the old agent served with nothing to say why edits
28
+ * had stopped taking effect.
29
+ *
30
+ * stderr keeps the stdout contract intact — a script still parses one JSON
31
+ * line — while a human tailing the log sees what happened.
32
+ */
33
+ function notify(level, message) {
34
+ if (!silenced) {
35
+ log[level](message);
36
+ return;
37
+ }
38
+ process.stderr.write(`${message}\n`);
39
+ }
40
+ /**
41
+ * Unwrap a clack prompt result, exiting cleanly if the user cancelled.
42
+ * `message` lets the caller name what was cancelled (e.g. "Setup cancelled").
43
+ */
44
+ function unwrapCancel(result, message = "Cancelled") {
45
+ if (p.isCancel(result)) {
46
+ p.cancel(message);
47
+ process.exit(0);
48
+ }
49
+ return result;
50
+ }
51
+ /** Format a URL for display. */
52
+ function fmtUrl(url) {
53
+ return styleText("cyanBright", url);
54
+ }
55
+ /**
56
+ * Parse and validate a port string. Returns the numeric port or throws.
57
+ *
58
+ * Deliberately zod-free: this module loads on every CLI invocation
59
+ * (including `aai --help`), and keeping zod off that path is the same
60
+ * startup-cost invariant `_utils.ts` documents for its error helpers.
61
+ */
62
+ function parsePort(raw) {
63
+ const port = raw.trim() === "" ? NaN : Number(raw);
64
+ if (!Number.isInteger(port) || port < 0 || port > 65535) throw new Error(`Invalid port: ${raw}. Must be a number between 0 and 65535.`);
65
+ return port;
66
+ }
67
+ //#endregion
68
+ export { silenceOutput as a, parsePort as i, log as n, unwrapCancel as o, notify as r, fmtUrl as t };
package/dist/_ui.d.ts CHANGED
@@ -4,6 +4,25 @@ type Log = typeof p.log;
4
4
  export declare const log: Log;
5
5
  /** Replace all log methods with no-ops. Call once in JSON mode. */
6
6
  export declare function silenceOutput(): void;
7
+ /**
8
+ * Emit a message that must survive JSON mode — human mode gets the normal
9
+ * clack styling, JSON mode gets a plain line on STDERR.
10
+ *
11
+ * `silenceOutput` no-ops every `log` method so that JSON mode's contract
12
+ * ("exactly one result line on stdout") holds. That is right for
13
+ * request/response commands, and wrong for LONG-RUNNING ones: `aai dev`
14
+ * writes its single JSON line at startup and then keeps running, so every
15
+ * later message — a failed rebuild, an unhandled rejection, "the dev server
16
+ * is down; save a file to retry" — was silenced for the rest of the process.
17
+ * And JSON mode is AUTO-DETECTED on a pipe, so that is the normal case:
18
+ * `aai dev > dev.log`, a process supervisor, or a container all hid every
19
+ * build failure, leaving the old agent served with nothing to say why edits
20
+ * had stopped taking effect.
21
+ *
22
+ * stderr keeps the stdout contract intact — a script still parses one JSON
23
+ * line — while a human tailing the log sees what happened.
24
+ */
25
+ export declare function notify(level: "error" | "warn" | "info" | "success", message: string): void;
7
26
  /**
8
27
  * Unwrap a clack prompt result, exiting cleanly if the user cancelled.
9
28
  * `message` lets the caller name what was cancelled (e.g. "Setup cancelled").
@@ -72,8 +72,15 @@ async function readJson(filePath) {
72
72
  * torn config.json fails `JSON.parse`, reads back as `{}`, and the next
73
73
  * read-modify-write silently wipes fields like `approvedServers`. Rename on
74
74
  * the same filesystem is atomic, so readers only ever see a complete file.
75
- * Two concurrent CLI processes can still lose each other's *updates*
76
- * (last rename wins) acceptable for these small user-config files.
75
+ *
76
+ * Atomic per WRITE is not atomic per read-modify-write: two concurrent CLI
77
+ * processes still lose each other's *updates* (last rename wins). That was
78
+ * long documented here as acceptable "for these small user-config files",
79
+ * and it is — for `.aai/project.json`, which is per-directory. It is NOT
80
+ * acceptable for the GLOBAL config, where it dropped the API key a
81
+ * successful `aai login` had just reported saving. Every global-config
82
+ * update therefore goes through `updateGlobalConfig` in `_config.ts`, which
83
+ * holds a cross-process lock around the read and the write.
77
84
  *
78
85
  * `mode` restricts the file's permissions (the rename carries the temp
79
86
  * file's mode to the destination, so an existing world-readable file is
package/dist/_utils.d.ts CHANGED
@@ -35,8 +35,15 @@ export declare function readJson(filePath: string): Promise<unknown>;
35
35
  * torn config.json fails `JSON.parse`, reads back as `{}`, and the next
36
36
  * read-modify-write silently wipes fields like `approvedServers`. Rename on
37
37
  * the same filesystem is atomic, so readers only ever see a complete file.
38
- * Two concurrent CLI processes can still lose each other's *updates*
39
- * (last rename wins) acceptable for these small user-config files.
38
+ *
39
+ * Atomic per WRITE is not atomic per read-modify-write: two concurrent CLI
40
+ * processes still lose each other's *updates* (last rename wins). That was
41
+ * long documented here as acceptable "for these small user-config files",
42
+ * and it is — for `.aai/project.json`, which is per-directory. It is NOT
43
+ * acceptable for the GLOBAL config, where it dropped the API key a
44
+ * successful `aai login` had just reported saving. Every global-config
45
+ * update therefore goes through `updateGlobalConfig` in `_config.ts`, which
46
+ * holds a cross-process lock around the read and the write.
40
47
  *
41
48
  * `mode` restricts the file's permissions (the rename carries the temp
42
49
  * file's mode to the destination, so an existing world-readable file is
@@ -1,8 +1,9 @@
1
1
  #!/usr/bin/env node
2
- import { n as log, o as CliError, u as ok } from "./_ui-8kOEB-JH.mjs";
3
- import { r as evalWorkerBundle, t as buildAgentBundle } from "./_bundler-Cjaxa2wi.mjs";
4
- import { assertTypechecks } from "./_typecheck-gate-DvE8S3aQ.mjs";
5
- import { classifyVitestError, runVitest } from "./test-3Gq4pqH_.mjs";
2
+ import { a as ok, t as CliError } from "./_output-CC300DzW.mjs";
3
+ import { n as log } from "./_ui-DfwfDbT-.mjs";
4
+ import { r as evalWorkerBundle, t as buildAgentBundle } from "./_bundler-DC17suWN.mjs";
5
+ import { assertTypechecks } from "./_typecheck-gate-DB-PY0A3.mjs";
6
+ import { classifyVitestError, runVitest } from "./test-C-V98oC-.mjs";
6
7
  //#region build.ts
7
8
  /**
8
9
  * `aai build` — bundle the agent without deploying, behind the same gates
package/dist/cli.mjs CHANGED
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env node
2
- import { c as getOutputMode, d as writeLine, i as silenceOutput, l as installStdoutGuard, n as log, o as CliError, s as fail } from "./_ui-8kOEB-JH.mjs";
3
- import { a as errorMessage, l as resolveCwd, o as fileExists, t as AGENT_ENTRY } from "./_utils-Ch0J4s6a.mjs";
2
+ import { i as installStdoutGuard, n as fail, o as writeLine, r as getOutputMode, t as CliError } from "./_output-CC300DzW.mjs";
3
+ import { a as silenceOutput, n as log } from "./_ui-DfwfDbT-.mjs";
4
+ import { a as errorMessage, l as resolveCwd, o as fileExists, t as AGENT_ENTRY } from "./_utils-8KKw-bzi.mjs";
4
5
  import { existsSync, readFileSync } from "node:fs";
5
6
  import path from "node:path";
6
7
  import { fileURLToPath } from "node:url";
@@ -165,7 +166,7 @@ const list = defineCommand({
165
166
  async run({ args }) {
166
167
  await runCommand(args, async () => {
167
168
  const cwd = resolveCwd();
168
- const { executeList } = await import("./studio-_UBBvh5V.mjs");
169
+ const { executeList } = await import("./studio-LNvXtWak.mjs");
169
170
  return executeList({
170
171
  cwd,
171
172
  server: args.server
@@ -200,7 +201,7 @@ const pull = defineCommand({
200
201
  async run({ args }) {
201
202
  await runCommand(args, async () => {
202
203
  const cwd = resolveCwd();
203
- const { executePull } = await import("./studio-_UBBvh5V.mjs");
204
+ const { executePull } = await import("./studio-LNvXtWak.mjs");
204
205
  return executePull({
205
206
  cwd,
206
207
  project: args.project,
@@ -228,7 +229,7 @@ const push = defineCommand({
228
229
  async run({ args }) {
229
230
  await runCommand(args, async () => {
230
231
  const cwd = await setup({ agent: true });
231
- const { executePush } = await import("./studio-_UBBvh5V.mjs");
232
+ const { executePush } = await import("./studio-LNvXtWak.mjs");
232
233
  return executePush({
233
234
  cwd,
234
235
  server: args.server,
@@ -258,7 +259,7 @@ const publish = defineCommand({
258
259
  async run({ args }) {
259
260
  await runCommand(args, async () => {
260
261
  const cwd = await setup({ agent: true });
261
- const { executePublish } = await import("./studio-_UBBvh5V.mjs");
262
+ const { executePublish } = await import("./studio-LNvXtWak.mjs");
262
263
  return executePublish({
263
264
  cwd,
264
265
  server: args.server,
@@ -316,7 +317,7 @@ const init = defineCommand({
316
317
  },
317
318
  async run({ args }) {
318
319
  await runCommand(args, async (mode) => {
319
- const { executeInit } = await import("./init-BpBbttOv.mjs");
320
+ const { executeInit } = await import("./init-Nc6fB774.mjs");
320
321
  return executeInit({
321
322
  dir: args.dir,
322
323
  force: args.force,
@@ -345,7 +346,7 @@ const dev = defineCommand({
345
346
  async run({ args }) {
346
347
  await runCommand(args, async () => {
347
348
  const cwd = await setup({ agent: true });
348
- const { executeDev } = await import("./dev-C4KyxouE.mjs");
349
+ const { executeDev } = await import("./dev-CdeRcYiQ.mjs");
349
350
  return executeDev({
350
351
  cwd,
351
352
  port: args.port
@@ -362,7 +363,7 @@ const test = defineCommand({
362
363
  async run({ args }) {
363
364
  await runCommand(args, async () => {
364
365
  const cwd = await setup();
365
- const { executeTest } = await import("./test-3Gq4pqH_.mjs");
366
+ const { executeTest } = await import("./test-C-V98oC-.mjs");
366
367
  return executeTest(cwd);
367
368
  });
368
369
  }
@@ -386,7 +387,7 @@ const build = defineCommand({
386
387
  async run({ args }) {
387
388
  await runCommand(args, async () => {
388
389
  const cwd = await setup({ agent: true });
389
- const { executeBuild } = await import("./build-BXwDB78d.mjs");
390
+ const { executeBuild } = await import("./build-CACFbdQ4.mjs");
390
391
  return executeBuild({
391
392
  cwd,
392
393
  skipTests: args.skipTests,
@@ -420,7 +421,7 @@ const deploy = defineCommand({
420
421
  async run({ args }) {
421
422
  await runCommand(args, async () => {
422
423
  const cwd = await setup({ agent: true });
423
- const { executeDeploy } = await import("./deploy-Cp-wgME3.mjs");
424
+ const { executeDeploy } = await import("./deploy-Ch0d_jje.mjs");
424
425
  return executeDeploy({
425
426
  cwd,
426
427
  server: args.server,
@@ -443,7 +444,7 @@ const del = defineCommand({
443
444
  async run({ args }) {
444
445
  await runCommand(args, async () => {
445
446
  const cwd = await setup();
446
- const { executeDelete } = await import("./delete-DRNfvczK.mjs");
447
+ const { executeDelete } = await import("./delete-DEZ7u3u4.mjs");
447
448
  return executeDelete({
448
449
  cwd,
449
450
  server: args.server
@@ -474,7 +475,7 @@ const secret = defineCommand({
474
475
  async run({ args }) {
475
476
  await runCommand(args, async (mode) => {
476
477
  const cwd = await setup();
477
- const { executeSecretPut, NO_INPUT, readStdin } = await import("./secret-Dr0qnxeb.mjs");
478
+ const { executeSecretPut, NO_INPUT, readStdin } = await import("./secret-4_dYyrpA.mjs");
478
479
  const value = mode === "json" ? await readStdin() : void 0;
479
480
  if (mode === "json" && !value) throw new CliError(...NO_INPUT);
480
481
  return executeSecretPut(cwd, args.name, value, args.server);
@@ -498,7 +499,7 @@ const secret = defineCommand({
498
499
  async run({ args }) {
499
500
  await runCommand(args, async () => {
500
501
  const cwd = await setup();
501
- const { executeSecretDelete } = await import("./secret-Dr0qnxeb.mjs");
502
+ const { executeSecretDelete } = await import("./secret-4_dYyrpA.mjs");
502
503
  return executeSecretDelete(cwd, args.name, args.server);
503
504
  });
504
505
  }
@@ -515,7 +516,7 @@ const secret = defineCommand({
515
516
  async run({ args }) {
516
517
  await runCommand(args, async () => {
517
518
  const cwd = await setup();
518
- const { executeSecretList } = await import("./secret-Dr0qnxeb.mjs");
519
+ const { executeSecretList } = await import("./secret-4_dYyrpA.mjs");
519
520
  return executeSecretList(cwd, args.server);
520
521
  });
521
522
  }
@@ -550,7 +551,7 @@ const storage = defineCommand({
550
551
  },
551
552
  async run({ args }) {
552
553
  await runCommand(args, async () => {
553
- const { executeStorageStatus } = await import("./storage-CoQB8d-u.mjs");
554
+ const { executeStorageStatus } = await import("./storage-BTfErOOW.mjs");
554
555
  return executeStorageStatus(resolveStorageCwd(args.dir), args.server);
555
556
  });
556
557
  }
@@ -567,7 +568,7 @@ const storage = defineCommand({
567
568
  },
568
569
  async run({ args }) {
569
570
  await runCommand(args, async () => {
570
- const { executeStorageEnable } = await import("./storage-CoQB8d-u.mjs");
571
+ const { executeStorageEnable } = await import("./storage-BTfErOOW.mjs");
571
572
  return executeStorageEnable(resolveStorageCwd(args.dir), args.server);
572
573
  });
573
574
  }
@@ -589,7 +590,7 @@ const storage = defineCommand({
589
590
  },
590
591
  async run({ args }) {
591
592
  await runCommand(args, async () => {
592
- const { executeStorageDisable } = await import("./storage-CoQB8d-u.mjs");
593
+ const { executeStorageDisable } = await import("./storage-BTfErOOW.mjs");
593
594
  return executeStorageDisable(resolveStorageCwd(args.dir), {
594
595
  server: args.server,
595
596
  force: args.force
@@ -610,7 +611,7 @@ const login = defineCommand({
610
611
  },
611
612
  async run({ args }) {
612
613
  await runCommand(args, async () => {
613
- const { executeLogin } = await import("./login-AA_UdRI-.mjs");
614
+ const { executeLogin } = await import("./login-BeFUiU6M.mjs");
614
615
  return executeLogin({ server: args.server });
615
616
  });
616
617
  }
@@ -623,7 +624,7 @@ const templates = defineCommand({
623
624
  args: { json: sharedArgs.json },
624
625
  async run({ args }) {
625
626
  await runCommand(args, async (mode) => {
626
- const { listTemplates } = await import("./_templates-BfyRyE7z.mjs");
627
+ const { listTemplates } = await import("./_templates-BWJOiWOO.mjs");
627
628
  const names = await listTemplates();
628
629
  if (mode === "human") {
629
630
  for (const name of names) log.message(name);
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { a as errorMessage$1, o as fileExists } from "./_utils-Ch0J4s6a.mjs";
2
+ import { a as errorMessage$1, o as fileExists } from "./_utils-8KKw-bzi.mjs";
3
3
  import { t as withPreservedNodeEnv } from "./_vite-env-Dg_QlVv0.mjs";
4
4
  import { existsSync, unlinkSync, writeFileSync } from "node:fs";
5
5
  import path from "node:path";
@@ -1,3 +1,3 @@
1
1
  #!/usr/bin/env node
2
- import { t as buildClient } from "./client-bundler-yiWoXrgb.mjs";
2
+ import { t as buildClient } from "./client-bundler-DONm-khu.mjs";
3
3
  export { buildClient };
@@ -1,7 +1,8 @@
1
1
  #!/usr/bin/env node
2
- import { n as log, u as ok } from "./_ui-8kOEB-JH.mjs";
3
- import { l as writeProjectConfig } from "./_config-Y5V-5Krn.mjs";
4
- import { i as resolveDeployTarget, n as getServerInfo } from "./_agent-2nVugrN3.mjs";
2
+ import { a as ok } from "./_output-CC300DzW.mjs";
3
+ import { n as log } from "./_ui-DfwfDbT-.mjs";
4
+ import { c as writeProjectConfig } from "./_config-DMyolIk9.mjs";
5
+ import { i as resolveDeployTarget, n as getServerInfo } from "./_agent-DS2PUJcl.mjs";
5
6
  import { n as apiRequest, t as HINT_NOT_DEPLOYED } from "./_api-client-B-upMGkc.mjs";
6
7
  //#region delete.ts
7
8
  async function runDelete(opts) {
@@ -10,7 +11,8 @@ async function runDelete(opts) {
10
11
  apiKey: opts.apiKey,
11
12
  action: "delete",
12
13
  hints: { 404: HINT_NOT_DEPLOYED },
13
- ...opts.fetch ? { fetch: opts.fetch } : {}
14
+ ...opts.fetch ? { fetch: opts.fetch } : {},
15
+ ...opts.retryDelay === void 0 ? {} : { retryDelay: opts.retryDelay }
14
16
  });
15
17
  }
16
18
  /**
package/dist/delete.d.ts CHANGED
@@ -5,6 +5,11 @@ export type DeleteOpts = {
5
5
  apiKey: string;
6
6
  /** Optional fetch implementation for testing. Defaults to globalThis.fetch. */
7
7
  fetch?: typeof globalThis.fetch;
8
+ /**
9
+ * Delay between retries in ms (default 300, see `_api-client.ts`). Tests
10
+ * pass 0 so retry-path assertions don't sleep real wall-clock time.
11
+ */
12
+ retryDelay?: number;
8
13
  };
9
14
  export declare function runDelete(opts: DeleteOpts): Promise<void>;
10
15
  type DeleteData = {
@@ -1,11 +1,12 @@
1
1
  #!/usr/bin/env node
2
- import { n as log, t as fmtUrl, u as ok } from "./_ui-8kOEB-JH.mjs";
3
- import { a as errorMessage } from "./_utils-Ch0J4s6a.mjs";
4
- import { t as buildAgentBundle } from "./_bundler-Cjaxa2wi.mjs";
5
- import { s as updateProjectConfig } from "./_config-Y5V-5Krn.mjs";
6
- import { t as resolveServerEnv } from "./_server-common-CnaP_Urf.mjs";
7
- import { i as resolveDeployTarget } from "./_agent-2nVugrN3.mjs";
8
- import { assertTypechecks } from "./_typecheck-gate-DvE8S3aQ.mjs";
2
+ import { a as ok } from "./_output-CC300DzW.mjs";
3
+ import { n as log, t as fmtUrl } from "./_ui-DfwfDbT-.mjs";
4
+ import { a as errorMessage } from "./_utils-8KKw-bzi.mjs";
5
+ import { t as buildAgentBundle } from "./_bundler-DC17suWN.mjs";
6
+ import { s as updateProjectConfig } from "./_config-DMyolIk9.mjs";
7
+ import { t as resolveServerEnv } from "./_server-common-DX8Bfrf5.mjs";
8
+ import { i as resolveDeployTarget } from "./_agent-DS2PUJcl.mjs";
9
+ import { assertTypechecks } from "./_typecheck-gate-DB-PY0A3.mjs";
9
10
  import { n as apiRequest } from "./_api-client-B-upMGkc.mjs";
10
11
  import { gzipSync } from "node:zlib";
11
12
  //#region _deploy.ts
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env node
2
- import { n as log, r as parsePort, t as fmtUrl, u as ok } from "./_ui-8kOEB-JH.mjs";
3
- import { i as errorDetail } from "./_utils-Ch0J4s6a.mjs";
2
+ import { a as ok } from "./_output-CC300DzW.mjs";
3
+ import { i as parsePort, n as log, r as notify, t as fmtUrl } from "./_ui-DfwfDbT-.mjs";
4
+ import { i as errorDetail } from "./_utils-8KKw-bzi.mjs";
4
5
  import path from "node:path";
5
6
  import { styleText } from "node:util";
6
7
  //#region dev.ts
@@ -11,7 +12,7 @@ import { styleText } from "node:util";
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-BB5N8kdh.mjs");
15
+ const { startDevServer } = await import("./_dev-server-B3ivqyEd.mjs");
15
16
  let cleanup;
16
17
  let shuttingDown = false;
17
18
  const onSignal = () => {
@@ -19,7 +20,7 @@ async function executeDev(opts) {
19
20
  shuttingDown = true;
20
21
  if (!cleanup) process.exit(130);
21
22
  cleanup().then(() => process.exit(0), (err) => {
22
- log.error(`Shutdown failed: ${errorDetail(err)}`);
23
+ notify("error", `Shutdown failed: ${errorDetail(err)}`);
23
24
  process.exit(1);
24
25
  });
25
26
  };
@@ -33,10 +34,10 @@ async function executeDev(opts) {
33
34
  log.success(`${styleText("bold", agentName)} running at ${fmtUrl(url)}`);
34
35
  log.info("Press Ctrl-C to stop");
35
36
  process.on("unhandledRejection", (err) => {
36
- log.error(`Unhandled rejection: ${errorDetail(err)}`);
37
+ notify("error", `Unhandled rejection: ${errorDetail(err)}`);
37
38
  });
38
39
  process.on("uncaughtException", (err) => {
39
- log.error(`Uncaught exception: ${errorDetail(err)}`);
40
+ notify("error", `Uncaught exception: ${errorDetail(err)}`);
40
41
  });
41
42
  return ok({ url });
42
43
  }
@@ -1,7 +1,8 @@
1
1
  #!/usr/bin/env node
2
- import { a as unwrapCancel, n as log, u as ok } from "./_ui-8kOEB-JH.mjs";
3
- import { a as errorMessage, c as readJson, l as resolveCwd, o as fileExists, t as AGENT_ENTRY } from "./_utils-Ch0J4s6a.mjs";
4
- import { r as isDevMode, t as getMonorepoRoot } from "./_agent-2nVugrN3.mjs";
2
+ import { a as ok } from "./_output-CC300DzW.mjs";
3
+ import { n as log, o as unwrapCancel } from "./_ui-DfwfDbT-.mjs";
4
+ import { a as errorMessage, c as readJson, l as resolveCwd, o as fileExists, t as AGENT_ENTRY } from "./_utils-8KKw-bzi.mjs";
5
+ import { r as isDevMode, t as getMonorepoRoot } from "./_agent-DS2PUJcl.mjs";
5
6
  import path from "node:path";
6
7
  import { styleText } from "node:util";
7
8
  import * as p from "@clack/prompts";
@@ -74,7 +75,7 @@ function resolveTargetDir(dir) {
74
75
  }
75
76
  /** Publish after init and return deploy metadata if successful. */
76
77
  async function tryPublish(cwd, server) {
77
- const { executePublish } = await import("./studio-_UBBvh5V.mjs");
78
+ const { executePublish } = await import("./studio-LNvXtWak.mjs");
78
79
  try {
79
80
  const result = await executePublish({
80
81
  cwd,
@@ -93,7 +94,7 @@ async function tryPublish(cwd, server) {
93
94
  }
94
95
  /** Scaffold the project, optionally showing a spinner. */
95
96
  async function scaffoldProject(dir, cwd, template, silent) {
96
- const { runInit } = await import("./_init-Dei2JRmn.mjs");
97
+ const { runInit } = await import("./_init-CYLvYU-B.mjs");
97
98
  const s = silent ? void 0 : p.spinner();
98
99
  s?.start(`Creating ${dir}`);
99
100
  await runInit({
@@ -1,7 +1,8 @@
1
1
  #!/usr/bin/env node
2
- import { n as log, o as CliError, u as ok } from "./_ui-8kOEB-JH.mjs";
3
- import { c as writeGlobalConfig, i as readGlobalConfig, r as getConfigDir, t as approveServer } from "./_config-Y5V-5Krn.mjs";
4
- import { a as resolveServerUrl } from "./_agent-2nVugrN3.mjs";
2
+ import { a as ok, t as CliError } from "./_output-CC300DzW.mjs";
3
+ import { n as log } from "./_ui-DfwfDbT-.mjs";
4
+ import { o as updateGlobalConfig, r as readGlobalConfig, t as approveServer } from "./_config-DMyolIk9.mjs";
5
+ import { a as resolveServerUrl } from "./_agent-DS2PUJcl.mjs";
5
6
  import { spawn } from "node:child_process";
6
7
  import { setTimeout } from "node:timers/promises";
7
8
  import { randomBytes } from "node:crypto";
@@ -103,7 +104,7 @@ async function pollForGrant(fetchFn, serverUrl, code, opts) {
103
104
  }
104
105
  }
105
106
  function requireTty() {
106
- if (!process.stdin.isTTY) throw new CliError("login_interactive", "`aai login` is interactive and needs a TTY.", "Non-interactive setups can set the ASSEMBLYAI_API_KEY environment variable instead.");
107
+ if (!process.stdin.isTTY) throw new CliError("login_interactive", "`aai login` is interactive and needs a TTY.", "Log in on a machine with a terminal, then point AAI_CONFIG_DIR at that config dir — logging in is the only way to authenticate.");
107
108
  }
108
109
  function openerFor(platform) {
109
110
  if (platform === "darwin") return ["open", []];
@@ -144,7 +145,7 @@ async function executeLogin(opts, deps = {}) {
144
145
  const globalConfig = await readGlobalConfig();
145
146
  const serverUrl = resolveServerUrl(opts.server, void 0, globalConfig.approvedServers ?? []);
146
147
  if (opts.server) await approveServer(serverUrl);
147
- if ((await jsonBody(await reachable(fetchFn, `${serverUrl}/studio/auth`, serverUrl), "Reading the server's login configuration")).mode === "none") throw new CliError("login_unavailable", "This server has no browser login configured, so there is no account to link.", "Set the ASSEMBLYAI_API_KEY environment variable insteadit's the only other way to authenticate.");
148
+ if ((await jsonBody(await reachable(fetchFn, `${serverUrl}/studio/auth`, serverUrl), "Reading the server's login configuration")).mode === "none") throw new CliError("login_unavailable", "This server has no browser login configured, so there is no account to link.", "Point `--server` at a platform with browser login configured linking an account there is the only way to authenticate.");
148
149
  const code = randomBytes(32).toString("base64url");
149
150
  const linkUrl = `${serverUrl}/?cli-link=${code}`;
150
151
  log.info(`Opening the browser to link your account…\n ${linkUrl}`);
@@ -156,11 +157,10 @@ async function executeLogin(opts, deps = {}) {
156
157
  deadline: Date.now() + (deps.timeoutMs ?? LINK_TIMEOUT_MS)
157
158
  });
158
159
  if (!granted.apiKey) throw new CliError("login_failed", "Linking your account did not return an API key.");
159
- const dir = getConfigDir();
160
- await writeGlobalConfig(dir, {
161
- ...await readGlobalConfig(dir),
160
+ await updateGlobalConfig((config) => ({
161
+ ...config,
162
162
  apiKey: granted.apiKey
163
- });
163
+ }));
164
164
  const email = granted.email ?? "your account";
165
165
  log.success(`Linked ${email} — your API key is saved for future commands.`);
166
166
  return ok({