@alexkroman1/aai-cli 0.12.2 → 0.12.3

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.
@@ -78,7 +78,7 @@ async function bundleAgent(agent, opts) {
78
78
  } catch (err) {
79
79
  throw new BundleError(errorMessage(err), { cause: err });
80
80
  }
81
- if (!(opts?.skipClient ?? !agent.clientEntry)) try {
81
+ if (!opts?.skipClient && agent.clientEntry) try {
82
82
  await build({
83
83
  root: agent.dir,
84
84
  base: "./",
@@ -102,7 +102,7 @@ async function bundleAgent(agent, opts) {
102
102
  };
103
103
  }
104
104
  async function buildAgentBundle(cwd) {
105
- const { loadAgent } = await import("./_discover-a8yIuqEp.mjs").then((n) => n.t);
105
+ const { loadAgent } = await import("./_discover-DzsMlg3G.mjs").then((n) => n.t);
106
106
  const { log } = await import("./_ui-DWGXImbO.mjs");
107
107
  const agent = await loadAgent(cwd);
108
108
  if (!agent) throw new Error("No agent found — run `aai init` first");
@@ -3,8 +3,9 @@ import { existsSync } from "node:fs";
3
3
  import path from "node:path";
4
4
  import { fileURLToPath } from "node:url";
5
5
  import fs from "node:fs/promises";
6
+ import os from "node:os";
7
+ import ci from "ci-info";
6
8
  import { consola } from "consola";
7
- import { humanId } from "human-id";
8
9
  import { z } from "zod";
9
10
  import { createInterface } from "node:readline";
10
11
  //#region \0rolldown/runtime.js
@@ -22,9 +23,10 @@ var __exportAll = (all, no_symbols) => {
22
23
  //#region _prompts.ts
23
24
  /**
24
25
  * Prompt the user for a password (masked input).
25
- * Returns the entered string.
26
+ * Throws in CI or non-TTY environments instead of hanging.
26
27
  */
27
28
  async function askPassword(message) {
29
+ if (ci.isCI || !process.stdin.isTTY) throw new Error(`Interactive prompt requires a terminal. Set ${message} as an environment variable in CI.`);
28
30
  const rl = createInterface({
29
31
  input: process.stdin,
30
32
  output: process.stdout
@@ -32,11 +34,11 @@ async function askPassword(message) {
32
34
  process.stdout.write(`${message}: `);
33
35
  const stdin = process.stdin;
34
36
  const wasRaw = stdin.isRaw;
35
- if (stdin.isTTY) stdin.setRawMode(true);
37
+ stdin.setRawMode(true);
36
38
  try {
37
39
  return await readMasked(stdin);
38
40
  } finally {
39
- if (stdin.isTTY) stdin.setRawMode(wasRaw ?? false);
41
+ stdin.setRawMode(wasRaw ?? false);
40
42
  rl.close();
41
43
  }
42
44
  }
@@ -65,8 +67,8 @@ var _discover_exports = /* @__PURE__ */ __exportAll({
65
67
  DEFAULT_SERVER: () => DEFAULT_SERVER,
66
68
  ensureApiKeyInEnv: () => ensureApiKeyInEnv,
67
69
  fileExists: () => fileExists,
68
- generateSlug: () => generateSlug,
69
70
  getApiKey: () => getApiKey,
71
+ getConfigDir: () => getConfigDir,
70
72
  getServerInfo: () => getServerInfo,
71
73
  isDevMode: () => isDevMode,
72
74
  loadAgent: () => loadAgent,
@@ -85,16 +87,11 @@ const ProjectConfigSchema = z.object({
85
87
  function resolveCwd() {
86
88
  return process.env.INIT_CWD || process.cwd();
87
89
  }
88
- /**
89
- * Generates a human-readable slug using human-id.
90
- */
91
- function generateSlug() {
92
- return humanId({
93
- separator: "-",
94
- capitalize: false
95
- });
90
+ function getConfigDir() {
91
+ if (process.platform === "win32") return path.join(process.env.APPDATA ?? path.join(os.homedir(), "AppData", "Roaming"), "aai");
92
+ return path.join(process.env.XDG_CONFIG_HOME ?? path.join(os.homedir(), ".config"), "aai");
96
93
  }
97
- const CONFIG_DIR = path.join(process.env.HOME ?? process.env.USERPROFILE ?? ".", ".config", "aai");
94
+ const CONFIG_DIR = getConfigDir();
98
95
  const CONFIG_FILE = path.join(CONFIG_DIR, "config.json");
99
96
  async function readAuthConfig() {
100
97
  try {
@@ -120,6 +117,7 @@ async function getApiKey() {
120
117
  if (process.env.ASSEMBLYAI_API_KEY) return process.env.ASSEMBLYAI_API_KEY;
121
118
  const config = await readAuthConfig();
122
119
  if (config.assemblyai_api_key) return config.assemblyai_api_key;
120
+ if (ci.isCI || !process.stdin.isTTY) throw new Error("No ASSEMBLYAI_API_KEY found. Set the ASSEMBLYAI_API_KEY environment variable in CI or non-interactive environments.");
123
121
  const { log } = await import("./_ui-DWGXImbO.mjs");
124
122
  log.info("Get your API key at https://www.assemblyai.com/dashboard/signup");
125
123
  log.info("Or set the ASSEMBLYAI_API_KEY environment variable to skip this prompt.");
@@ -207,7 +205,7 @@ async function fileExists(p) {
207
205
  */
208
206
  async function loadAgent(dir) {
209
207
  if (!await fileExists(path.join(dir, "agent.ts"))) return null;
210
- const slug = (await readProjectConfig(dir))?.slug ?? generateSlug();
208
+ const slug = (await readProjectConfig(dir))?.slug ?? "";
211
209
  const clientEntry = await fileExists(path.join(dir, "client.tsx")) ? path.join(dir, "client.tsx") : "";
212
210
  return {
213
211
  slug,
@@ -217,4 +215,4 @@ async function loadAgent(dir) {
217
215
  };
218
216
  }
219
217
  //#endregion
220
- export { getApiKey as a, readProjectConfig as c, writeProjectConfig as d, askPassword as f, generateSlug as i, resolveCwd as l, ensureApiKeyInEnv as n, getServerInfo as o, fileExists as r, isDevMode as s, _discover_exports as t, resolveServerUrl as u };
218
+ export { getServerInfo as a, resolveCwd as c, askPassword as d, getApiKey as i, resolveServerUrl as l, ensureApiKeyInEnv as n, isDevMode as o, fileExists as r, readProjectConfig as s, _discover_exports as t, writeProjectConfig as u };
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { t as downloadAndMergeTemplate } from "./_templates-CtZBILce.mjs";
2
+ import { t as downloadAndMergeTemplate } from "./_templates-BDkbj3TM.mjs";
3
3
  import path from "node:path";
4
4
  import fs from "node:fs/promises";
5
5
  //#region _init.ts
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { s as isDevMode } from "./_discover-a8yIuqEp.mjs";
2
+ import { o as isDevMode } from "./_discover-DzsMlg3G.mjs";
3
3
  import { existsSync } from "node:fs";
4
4
  import path from "node:path";
5
5
  import { fileURLToPath } from "node:url";
package/dist/cli.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { l as resolveCwd, n as ensureApiKeyInEnv, r as fileExists } from "./_discover-a8yIuqEp.mjs";
2
+ import { c as resolveCwd, n as ensureApiKeyInEnv, r as fileExists } from "./_discover-DzsMlg3G.mjs";
3
3
  import { readFileSync } from "node:fs";
4
4
  import path from "node:path";
5
5
  import { fileURLToPath } from "node:url";
@@ -35,7 +35,7 @@ function findPkgJson(dir) {
35
35
  const VERSION = JSON.parse(findPkgJson(cliDir)).version;
36
36
  async function ensureAgent(cwd, yes) {
37
37
  if (!await fileExists(path.join(cwd, "agent.ts"))) {
38
- const { runInitCommand } = await import("./init-BYX6pxjd.mjs");
38
+ const { runInitCommand } = await import("./init-CNuntiij.mjs");
39
39
  return runInitCommand({ yes }, { quiet: true });
40
40
  }
41
41
  return cwd;
@@ -91,7 +91,7 @@ const init = defineCommand({
91
91
  },
92
92
  async run({ args }) {
93
93
  await handleErrors(async () => {
94
- const { runInitCommand } = await import("./init-BYX6pxjd.mjs");
94
+ const { runInitCommand } = await import("./init-CNuntiij.mjs");
95
95
  await runInitCommand({
96
96
  dir: args.dir,
97
97
  template: args.template,
@@ -136,7 +136,7 @@ const test = defineCommand({
136
136
  async run() {
137
137
  await handleErrors(async () => {
138
138
  const cwd = await setup();
139
- const { runTestCommand } = await import("./test-CYoqKJP0.mjs");
139
+ const { runTestCommand } = await import("./test-yqHGZPF3.mjs");
140
140
  await runTestCommand(cwd);
141
141
  });
142
142
  }
@@ -158,10 +158,10 @@ const build = defineCommand({
158
158
  await handleErrors(async () => {
159
159
  const cwd = await setup(args, { agent: true });
160
160
  if (!args.skipTests) {
161
- const { runVitest } = await import("./test-CYoqKJP0.mjs");
161
+ const { runVitest } = await import("./test-yqHGZPF3.mjs");
162
162
  runVitest(cwd);
163
163
  }
164
- const { runBuildCommand } = await import("./_bundler-2yKukgnU.mjs");
164
+ const { runBuildCommand } = await import("./_bundler-DQtFVeww.mjs");
165
165
  await runBuildCommand(cwd);
166
166
  });
167
167
  }
@@ -173,20 +173,15 @@ const deploy = defineCommand({
173
173
  },
174
174
  args: {
175
175
  server: sharedArgs.server,
176
- dryRun: {
177
- type: "boolean",
178
- description: "Validate and bundle without deploying"
179
- },
180
176
  yes: sharedArgs.yes
181
177
  },
182
178
  async run({ args }) {
183
179
  await handleErrors(async () => {
184
180
  const cwd = await setup(args, { agent: true });
185
- const { runDeployCommand } = await import("./deploy-CnscqVZv.mjs");
181
+ const { runDeployCommand } = await import("./deploy-CLs8gLHV.mjs");
186
182
  await runDeployCommand({
187
183
  cwd,
188
- ...args.server ? { server: args.server } : {},
189
- ...args.dryRun ? { dryRun: args.dryRun } : {}
184
+ ...args.server ? { server: args.server } : {}
190
185
  });
191
186
  });
192
187
  }
@@ -200,7 +195,7 @@ const del = defineCommand({
200
195
  async run({ args }) {
201
196
  await handleErrors(async () => {
202
197
  const cwd = await setup();
203
- const { runDeleteCommand } = await import("./delete-BvRel3Tw.mjs");
198
+ const { runDeleteCommand } = await import("./delete-CalIL6Pg.mjs");
204
199
  await runDeleteCommand({
205
200
  cwd,
206
201
  ...args.server ? { server: args.server } : {}
@@ -219,16 +214,19 @@ const secret = defineCommand({
219
214
  name: "put",
220
215
  description: "Create or update a secret"
221
216
  },
222
- args: { name: {
223
- type: "positional",
224
- description: "Secret name",
225
- required: true
226
- } },
217
+ args: {
218
+ name: {
219
+ type: "positional",
220
+ description: "Secret name",
221
+ required: true
222
+ },
223
+ server: sharedArgs.server
224
+ },
227
225
  async run({ args }) {
228
226
  await handleErrors(async () => {
229
227
  const cwd = await setup(void 0, { apiKey: true });
230
- const { runSecretPut } = await import("./secret-DLosn47q.mjs");
231
- await runSecretPut(cwd, args.name);
228
+ const { runSecretPut } = await import("./secret-xmLQ96Yz.mjs");
229
+ await runSecretPut(cwd, args.name, args.server);
232
230
  });
233
231
  }
234
232
  }),
@@ -237,16 +235,19 @@ const secret = defineCommand({
237
235
  name: "delete",
238
236
  description: "Delete a secret"
239
237
  },
240
- args: { name: {
241
- type: "positional",
242
- description: "Secret name",
243
- required: true
244
- } },
238
+ args: {
239
+ name: {
240
+ type: "positional",
241
+ description: "Secret name",
242
+ required: true
243
+ },
244
+ server: sharedArgs.server
245
+ },
245
246
  async run({ args }) {
246
247
  await handleErrors(async () => {
247
248
  const cwd = await setup(void 0, { apiKey: true });
248
- const { runSecretDelete } = await import("./secret-DLosn47q.mjs");
249
- await runSecretDelete(cwd, args.name);
249
+ const { runSecretDelete } = await import("./secret-xmLQ96Yz.mjs");
250
+ await runSecretDelete(cwd, args.name, args.server);
250
251
  });
251
252
  }
252
253
  }),
@@ -255,11 +256,12 @@ const secret = defineCommand({
255
256
  name: "list",
256
257
  description: "List all secrets"
257
258
  },
258
- async run() {
259
+ args: { server: sharedArgs.server },
260
+ async run({ args }) {
259
261
  await handleErrors(async () => {
260
262
  const cwd = await setup(void 0, { apiKey: true });
261
- const { runSecretList } = await import("./secret-DLosn47q.mjs");
262
- await runSecretList(cwd);
263
+ const { runSecretList } = await import("./secret-xmLQ96Yz.mjs");
264
+ await runSecretList(cwd, args.server);
263
265
  });
264
266
  }
265
267
  })
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { o as getServerInfo } from "./_discover-a8yIuqEp.mjs";
2
+ import { a as getServerInfo } from "./_discover-DzsMlg3G.mjs";
3
3
  import { log } from "./_ui-DWGXImbO.mjs";
4
4
  import { n as apiError, r as apiRequest, t as HINT_INVALID_API_KEY } from "./_api-client-H4MFOr8j.mjs";
5
5
  //#region _delete.ts
@@ -0,0 +1,53 @@
1
+ #!/usr/bin/env node
2
+ import { i as getApiKey, l as resolveServerUrl, s as readProjectConfig, u as writeProjectConfig } from "./_discover-DzsMlg3G.mjs";
3
+ import { buildAgentBundle } from "./_bundler-DQtFVeww.mjs";
4
+ import { fmtUrl, log } from "./_ui-DWGXImbO.mjs";
5
+ import { n as apiError, r as apiRequest, t as HINT_INVALID_API_KEY } from "./_api-client-H4MFOr8j.mjs";
6
+ //#region _deploy.ts
7
+ async function runDeploy(opts) {
8
+ const fetchFn = opts.fetch ?? globalThis.fetch.bind(globalThis);
9
+ const body = JSON.stringify({
10
+ ...opts.slug ? { slug: opts.slug } : {},
11
+ env: opts.env,
12
+ worker: opts.bundle.worker,
13
+ clientFiles: opts.bundle.clientFiles
14
+ });
15
+ const resp = await apiRequest(`${opts.url}/deploy`, {
16
+ method: "POST",
17
+ body,
18
+ apiKey: opts.apiKey,
19
+ action: "deploy"
20
+ }, fetchFn);
21
+ if (resp.ok) return { slug: (await resp.json()).slug };
22
+ const text = await resp.text();
23
+ let hint;
24
+ if (resp.status === 401) hint = HINT_INVALID_API_KEY;
25
+ else if (resp.status === 413) hint = "Your bundle is too large. Try reducing dependencies or splitting your agent.";
26
+ throw new Error(apiError("deploy", resp.status, text, hint).message);
27
+ }
28
+ //#endregion
29
+ //#region deploy.ts
30
+ async function runDeployCommand(opts) {
31
+ const { cwd } = opts;
32
+ const apiKey = await getApiKey();
33
+ const projectConfig = await readProjectConfig(cwd);
34
+ const serverUrl = resolveServerUrl(opts.server, projectConfig?.serverUrl);
35
+ const bundle = await buildAgentBundle(cwd);
36
+ const slug = projectConfig?.slug;
37
+ log.step(`Deploying${slug ? ` ${slug}` : ""}…`);
38
+ const deployed = await runDeploy({
39
+ url: serverUrl,
40
+ bundle,
41
+ env: { ASSEMBLYAI_API_KEY: apiKey },
42
+ ...slug ? { slug } : {},
43
+ apiKey
44
+ });
45
+ await writeProjectConfig(cwd, {
46
+ slug: deployed.slug,
47
+ serverUrl
48
+ });
49
+ const agentUrl = `${serverUrl}/${deployed.slug}`;
50
+ log.success(`Deployed ${fmtUrl(agentUrl)}`);
51
+ }
52
+ //#endregion
53
+ export { runDeployCommand };
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
- import { l as resolveCwd, n as ensureApiKeyInEnv, r as fileExists } from "./_discover-a8yIuqEp.mjs";
3
- import { n as listTemplates } from "./_templates-CtZBILce.mjs";
2
+ import { c as resolveCwd, n as ensureApiKeyInEnv, r as fileExists } from "./_discover-DzsMlg3G.mjs";
3
+ import { n as listTemplates } from "./_templates-BDkbj3TM.mjs";
4
4
  import { log } from "./_ui-DWGXImbO.mjs";
5
5
  import path from "node:path";
6
6
  import fs from "node:fs/promises";
@@ -90,7 +90,7 @@ async function runInitCommand(opts, extra) {
90
90
  const template = opts.template ?? await promptTemplate(opts.yes);
91
91
  const s = p.spinner();
92
92
  s.start(`Creating ${dir} from ${template} template`);
93
- const { runInit } = await import("./_init-VzVTpJFZ.mjs");
93
+ const { runInit } = await import("./_init-CbMs9S2O.mjs");
94
94
  await runInit({
95
95
  targetDir: cwd,
96
96
  template
@@ -98,7 +98,7 @@ async function runInitCommand(opts, extra) {
98
98
  s.stop("Project created");
99
99
  await installDeps(cwd);
100
100
  if (!(opts.skipDeploy || extra?.quiet)) {
101
- const { runDeployCommand } = await import("./deploy-CnscqVZv.mjs");
101
+ const { runDeployCommand } = await import("./deploy-CLs8gLHV.mjs");
102
102
  await runDeployCommand({
103
103
  cwd,
104
104
  ...opts.server ? { server: opts.server } : {}
@@ -0,0 +1,46 @@
1
+ #!/usr/bin/env node
2
+ import { a as getServerInfo, d as askPassword } from "./_discover-DzsMlg3G.mjs";
3
+ import { log } from "./_ui-DWGXImbO.mjs";
4
+ import { n as apiError, r as apiRequest, t as HINT_INVALID_API_KEY } from "./_api-client-H4MFOr8j.mjs";
5
+ //#region secret.ts
6
+ async function secretRequest(cwd, pathSuffix, init, server) {
7
+ const { serverUrl, slug, apiKey } = await getServerInfo(cwd, server);
8
+ const resp = await apiRequest(`${serverUrl}/${slug}/secret${pathSuffix}`, {
9
+ ...init,
10
+ apiKey,
11
+ action: "secret"
12
+ });
13
+ if (!resp.ok) {
14
+ const text = await resp.text();
15
+ const hint = resp.status === 401 ? HINT_INVALID_API_KEY : void 0;
16
+ throw apiError("secret", resp.status, text, hint);
17
+ }
18
+ return {
19
+ resp,
20
+ slug
21
+ };
22
+ }
23
+ async function runSecretPut(cwd, name, server) {
24
+ const value = await askPassword(`Enter value for ${name}`);
25
+ if (!value) throw new Error("No value provided");
26
+ const { slug } = await secretRequest(cwd, "", {
27
+ method: "PUT",
28
+ body: JSON.stringify({ [name]: value })
29
+ }, server);
30
+ log.success(`Set ${name} for ${slug}`);
31
+ }
32
+ async function runSecretDelete(cwd, name, server) {
33
+ const { slug } = await secretRequest(cwd, `/${name}`, { method: "DELETE" }, server);
34
+ log.success(`Deleted ${name} from ${slug}`);
35
+ }
36
+ async function runSecretList(cwd, server) {
37
+ const { resp } = await secretRequest(cwd, "", void 0, server);
38
+ const { vars } = await resp.json();
39
+ if (vars.length === 0) log.info("No secrets set. Use `aai secret put <name>` to add one.");
40
+ else {
41
+ log.message(`${vars.length} secret${vars.length === 1 ? "" : "s"}:`);
42
+ for (const name of vars) log.message(` ${name}`);
43
+ }
44
+ }
45
+ //#endregion
46
+ export { runSecretDelete, runSecretList, runSecretPut };
@@ -2,7 +2,7 @@
2
2
  import { log } from "./_ui-DWGXImbO.mjs";
3
3
  import { existsSync } from "node:fs";
4
4
  import path from "node:path";
5
- import { execSync } from "node:child_process";
5
+ import { execFileSync } from "node:child_process";
6
6
  //#region test.ts
7
7
  /**
8
8
  * `aai test` — run agent tests via vitest.
@@ -15,7 +15,13 @@ import { execSync } from "node:child_process";
15
15
  */
16
16
  function runVitest(cwd) {
17
17
  if (!(existsSync(path.join(cwd, "agent.test.ts")) || existsSync(path.join(cwd, "agent.test.js")))) return false;
18
- execSync(`npx vitest run --root . ${existsSync(path.join(cwd, "agent.test.ts")) ? "agent.test.ts" : "agent.test.js"}`, {
18
+ execFileSync("npx", [
19
+ "vitest",
20
+ "run",
21
+ "--root",
22
+ ".",
23
+ existsSync(path.join(cwd, "agent.test.ts")) ? "agent.test.ts" : "agent.test.js"
24
+ ], {
19
25
  cwd,
20
26
  stdio: "inherit",
21
27
  env: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alexkroman1/aai-cli",
3
- "version": "0.12.2",
3
+ "version": "0.12.3",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "aai": "dist/cli.mjs"
@@ -9,19 +9,22 @@
9
9
  "dist"
10
10
  ],
11
11
  "dependencies": {
12
- "@clack/prompts": "^1.1.0",
12
+ "@clack/prompts": "^1.2.0",
13
+ "ci-info": "^4.4.0",
13
14
  "citty": "^0.2.1",
14
15
  "consola": "^3.4.2",
15
16
  "giget": "^2.0.0",
16
- "human-id": "^4.1.3",
17
17
  "vite": "^8.0.3",
18
18
  "zod": "^4.3.6",
19
- "@alexkroman1/aai": "0.12.2"
19
+ "@alexkroman1/aai": "0.12.3"
20
20
  },
21
21
  "devDependencies": {
22
- "playwright": "^1.58.2",
23
- "tsdown": "^0.21.5",
24
- "vitest": "^4.1.1"
22
+ "get-port": "^7.2.0",
23
+ "playwright": "^1.59.0",
24
+ "tree-kill": "^1.2.2",
25
+ "tsdown": "^0.21.7",
26
+ "verdaccio": "^6.3.2",
27
+ "vitest": "^4.1.2"
25
28
  },
26
29
  "engines": {
27
30
  "node": ">=22.6"
@@ -32,6 +35,8 @@
32
35
  "directory": "packages/aai-cli"
33
36
  },
34
37
  "scripts": {
38
+ "test": "vitest run",
39
+ "test:coverage": "vitest run --coverage",
35
40
  "build": "tsdown",
36
41
  "typecheck": "tsc --noEmit",
37
42
  "lint": "biome check .",
@@ -1,92 +0,0 @@
1
- #!/usr/bin/env node
2
- import { a as getApiKey, c as readProjectConfig, d as writeProjectConfig, i as generateSlug, u as resolveServerUrl } from "./_discover-a8yIuqEp.mjs";
3
- import { buildAgentBundle } from "./_bundler-2yKukgnU.mjs";
4
- import { fmtUrl, log } from "./_ui-DWGXImbO.mjs";
5
- import { n as apiError, r as apiRequest, t as HINT_INVALID_API_KEY } from "./_api-client-H4MFOr8j.mjs";
6
- //#region _deploy.ts
7
- const MAX_SLUG_RETRIES = 20;
8
- async function attempt(fetchFn, url, slug, body, apiKey) {
9
- const resp = await apiRequest(`${url}/${slug}/deploy`, {
10
- method: "POST",
11
- body,
12
- apiKey,
13
- action: "deploy"
14
- }, fetchFn);
15
- if (resp.ok) return {
16
- ok: true,
17
- slug
18
- };
19
- const text = await resp.text();
20
- if (resp.status === 403 && text.includes("owned by another")) return {
21
- ok: false,
22
- retry: true
23
- };
24
- let hint;
25
- if (resp.status === 401) hint = HINT_INVALID_API_KEY;
26
- else if (resp.status === 403 && text.includes("Slug")) hint = "This slug is already taken. Set a different slug in .aai/project.json.";
27
- else if (resp.status === 413) hint = "Your bundle is too large. Try reducing dependencies or splitting your agent.";
28
- return {
29
- ok: false,
30
- retry: false,
31
- error: apiError("deploy", resp.status, text, hint).message
32
- };
33
- }
34
- async function runDeploy(opts) {
35
- const fetchFn = opts.fetch ?? globalThis.fetch.bind(globalThis);
36
- const body = JSON.stringify({
37
- env: opts.env,
38
- worker: opts.bundle.worker,
39
- clientFiles: opts.bundle.clientFiles
40
- });
41
- let slug = opts.slug;
42
- for (let i = 0; i < MAX_SLUG_RETRIES; i++) {
43
- const result = await attempt(fetchFn, opts.url, slug, body, opts.apiKey);
44
- if (result.ok) return { slug: result.slug };
45
- if (!result.retry) throw new Error(result.error);
46
- slug = generateSlug();
47
- }
48
- throw new Error(`Could not find an available slug after ${MAX_SLUG_RETRIES} attempts. Set one manually in .aai/project.json.`);
49
- }
50
- //#endregion
51
- //#region deploy.ts
52
- async function deployBundle(opts) {
53
- const { bundle, serverUrl, apiKey, cwd } = opts;
54
- let { slug } = opts;
55
- log.step(`Deploying ${slug}`);
56
- slug = (await runDeploy({
57
- url: serverUrl,
58
- bundle,
59
- env: { ASSEMBLYAI_API_KEY: apiKey },
60
- slug,
61
- apiKey
62
- })).slug;
63
- await writeProjectConfig(cwd, {
64
- slug,
65
- serverUrl
66
- });
67
- const agentUrl = `${serverUrl}/${slug}`;
68
- log.success(`Deployed ${fmtUrl(agentUrl)}`);
69
- return agentUrl;
70
- }
71
- async function runDeployCommand(opts) {
72
- const { cwd } = opts;
73
- const dryRun = opts.dryRun ?? false;
74
- const apiKey = dryRun ? "" : await getApiKey();
75
- const projectConfig = await readProjectConfig(cwd);
76
- const serverUrl = resolveServerUrl(opts.server, projectConfig?.serverUrl);
77
- const bundle = await buildAgentBundle(cwd);
78
- const slug = projectConfig?.slug ?? bundle.slug;
79
- if (dryRun) {
80
- log.info(`Dry run complete — would deploy as ${slug}`);
81
- return;
82
- }
83
- await deployBundle({
84
- bundle,
85
- serverUrl,
86
- apiKey,
87
- slug,
88
- cwd
89
- });
90
- }
91
- //#endregion
92
- export { runDeployCommand };
@@ -1,47 +0,0 @@
1
- #!/usr/bin/env node
2
- import { f as askPassword, o as getServerInfo } from "./_discover-a8yIuqEp.mjs";
3
- import { log } from "./_ui-DWGXImbO.mjs";
4
- //#region secret.ts
5
- async function apiFetch(cwd, pathSuffix, init) {
6
- const { serverUrl, slug, apiKey } = await getServerInfo(cwd);
7
- const resp = await fetch(`${serverUrl}/${slug}/secret${pathSuffix}`, {
8
- ...init,
9
- headers: {
10
- Authorization: `Bearer ${apiKey}`,
11
- ...init?.headers
12
- }
13
- });
14
- if (!resp.ok) {
15
- const text = await resp.text();
16
- throw new Error(`Secret operation failed: ${text}`);
17
- }
18
- return {
19
- resp,
20
- slug
21
- };
22
- }
23
- async function runSecretPut(cwd, name) {
24
- const value = await askPassword(`Enter value for ${name}`);
25
- if (!value) throw new Error("No value provided");
26
- const { slug } = await apiFetch(cwd, "", {
27
- method: "PUT",
28
- headers: { "Content-Type": "application/json" },
29
- body: JSON.stringify({ [name]: value })
30
- });
31
- log.success(`Set ${name} for ${slug}`);
32
- }
33
- async function runSecretDelete(cwd, name) {
34
- const { slug } = await apiFetch(cwd, `/${name}`, { method: "DELETE" });
35
- log.success(`Deleted ${name} from ${slug}`);
36
- }
37
- async function runSecretList(cwd) {
38
- const { resp } = await apiFetch(cwd, "");
39
- const { vars } = await resp.json();
40
- if (vars.length === 0) log.info("No secrets set. Use `aai secret put <name>` to add one.");
41
- else {
42
- log.message(`${vars.length} secret${vars.length === 1 ? "" : "s"}:`);
43
- for (const name of vars) log.message(` ${name}`);
44
- }
45
- }
46
- //#endregion
47
- export { runSecretDelete, runSecretList, runSecretPut };