@alexkroman1/aai-cli 13.2.0 → 13.3.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.
- package/bin.mjs +1 -1
- package/dist/{_agent-BTwZJu4P.mjs → _agent-Clbq3a4h.mjs} +2 -2
- package/dist/{_bundler-C31rlcYz.mjs → _bundler-DEkjO1d8.mjs} +3 -3
- package/dist/{_config-CmJOFsAP.mjs → _config-ZY2euhdh.mjs} +7 -4
- package/dist/_config.d.ts +25 -1
- package/dist/{_dev-server-DWvkNoIS.mjs → _dev-server-C13xuGB1.mjs} +13 -13
- package/dist/_e2e-test-utils.d.ts +15 -7
- package/dist/{_init-BURbdHNM.mjs → _init-Ci4QGjp8.mjs} +58 -10
- package/dist/{_output-CKkmWs7i.mjs → _output-DbJt9gsl.mjs} +34 -3
- package/dist/_output.d.ts +17 -1
- package/dist/{_preflight-Co1G9Jww.mjs → _preflight-B2laWPdU.mjs} +1 -1
- package/dist/{_server-common-6e0QI4mq.mjs → _server-common-BV4_CrP3.mjs} +3 -3
- package/dist/{_slug-api-CfGQq1Tt.mjs → _slug-api-DlKpj91X.mjs} +3 -3
- package/dist/{_studio-B1waXMuR.mjs → _studio-DTi3EdXQ.mjs} +3 -3
- package/dist/{_templates-0Zr2z6yA.mjs → _templates-V4l5sZJy.mjs} +2 -2
- package/dist/{_typecheck-gate-BXvUNnfs.mjs → _typecheck-gate-sV4N5F93.mjs} +3 -3
- package/dist/{_ui-u7T4YooX.mjs → _ui-DCt4qZrk.mjs} +1 -1
- package/dist/{_utils-B8QmtFhK.mjs → _utils-Dhd058D9.mjs} +1 -1
- package/dist/{_vite-env-D9Qj6KPX.mjs → _vite-env-kejF0p2L.mjs} +1 -1
- package/dist/{_workflow-determinism-f9J-5Zlj.mjs → _workflow-determinism-C9l8uC2R.mjs} +1 -1
- package/dist/{build-BLlLOrng.mjs → build-CWyFGe-W.mjs} +11 -8
- package/dist/cli.d.ts +2 -1
- package/dist/cli.mjs +120 -46
- package/dist/{client-bundler-j5c46x0G.mjs → client-bundler-CT-_26c5.mjs} +4 -4
- package/dist/client-bundler.mjs +1 -1
- package/dist/{delete-X_CRgCf6.mjs → delete-RqlQZ6Y_.mjs} +6 -6
- package/dist/{deploy-BzZ-r4iM.mjs → deploy-B7f3CK7v.mjs} +13 -13
- package/dist/{dev-BDykFvcc.mjs → dev-DamXieW_.mjs} +5 -5
- package/dist/{eval-0qEOdm0l.mjs → eval-h3DTVfRw.mjs} +27 -11
- package/dist/eval.d.ts +2 -0
- package/dist/{init-BtJI306C.mjs → init-D-vFrV8h.mjs} +7 -7
- package/dist/{login-DeUETobb.mjs → login-CDiemNmC.mjs} +5 -5
- package/dist/{logs-hWnJ66Bl.mjs → logs-DGwPNCzB.mjs} +4 -4
- package/dist/project-config.mjs +1 -1
- package/dist/scaffold/.env.example +17 -1
- package/dist/scaffold/package.json +6 -5
- package/dist/secret-V1w7y9-j.mjs +162 -0
- package/dist/secret.d.ts +41 -8
- package/dist/{studio-BxAS_FQQ.mjs → studio-BpMCfUNx.mjs} +9 -9
- package/dist/templates/briefing-desk/agent.test.ts +7 -3
- package/dist/templates/call-audit/agent.test.ts +14 -3
- package/dist/templates/call-audit/client.tsx +14 -17
- package/dist/templates/embedded-assets/agent.test.ts +7 -1
- package/dist/templates/health-assistant/agent.test.ts +8 -4
- package/dist/templates/link-digest/agent.test.ts +7 -1
- package/dist/templates/link-digest/client.tsx +17 -21
- package/dist/templates/night-owl/agent.test.ts +6 -1
- package/dist/templates/pipeline-simple/agent.test.ts +31 -14
- package/dist/templates/podcast-digest/agent.test.ts +13 -3
- package/dist/templates/podcast-digest/client.tsx +12 -15
- package/dist/templates/recap-workflow/agent.test.ts +22 -9
- package/dist/templates/redline/agent.test.ts +7 -1
- package/dist/templates/redline/client.tsx +12 -15
- package/dist/templates/research-workflow/agent.test.ts +7 -1
- package/dist/templates/retail/registry.test.ts +99 -58
- package/dist/templates/simple/agent.test.ts +39 -6
- package/dist/templates/spoken-summary/agent.test.ts +12 -3
- package/dist/templates/spoken-summary/client.tsx +14 -18
- package/dist/templates/transcription-workflow/agent.test.ts +16 -8
- package/dist/templates/transcription-workflow/client.tsx +19 -26
- package/dist/test-guenJUxi.mjs +255 -0
- package/dist/test.d.ts +97 -31
- package/dist/typecheck.mjs +2 -2
- package/dist/worker-bundler.mjs +3 -3
- package/dist/{workflow-BBu5oEDw.mjs → workflow-BZyKLkhV.mjs} +5 -5
- package/package.json +10 -10
- package/dist/bin.d.mts +0 -2
- package/dist/secret-B-3T5tvr.mjs +0 -61
- package/dist/test-CiLab-AA.mjs +0 -182
- package/dist/tsdown.config.d.ts +0 -2
package/bin.mjs
CHANGED
|
@@ -25,7 +25,7 @@ enableCompileCache();
|
|
|
25
25
|
// Source wins when present: a checkout that has also been built must keep
|
|
26
26
|
// running `cli.ts`, or `pnpm link --global` would silently serve a stale
|
|
27
27
|
// `dist/` instead of the working tree.
|
|
28
|
-
const source = new URL("./cli.ts", import.meta.url);
|
|
28
|
+
const source = new URL("./src/cli.ts", import.meta.url);
|
|
29
29
|
const entry = existsSync(fileURLToPath(source))
|
|
30
30
|
? source
|
|
31
31
|
: new URL("./dist/cli.mjs", import.meta.url);
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { a as serverOrigin, i as readProjectConfig, n as ensureApiKey, r as readGlobalConfig, t as approveServer } from "./_config-
|
|
2
|
+
import { a as serverOrigin, i as readProjectConfig, n as ensureApiKey, r as readGlobalConfig, t as approveServer } from "./_config-ZY2euhdh.mjs";
|
|
3
3
|
import { existsSync } from "node:fs";
|
|
4
4
|
import path from "node:path";
|
|
5
5
|
import { fileURLToPath } from "node:url";
|
|
6
6
|
import { VALID_SLUG_RE } from "@alexkroman1/aai/internal";
|
|
7
|
-
//#region _agent.ts
|
|
7
|
+
//#region src/_agent.ts
|
|
8
8
|
const DEFAULT_SERVER = "https://alexkroman--aai-server-web-server.modal.run";
|
|
9
9
|
const DEFAULT_DEV_SERVER = "http://localhost:8080";
|
|
10
10
|
let _cachedMonorepoRoot;
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { f as validateAgentExport } from "./_utils-
|
|
3
|
-
import { t as buildClient } from "./client-bundler-
|
|
2
|
+
import { f as validateAgentExport } from "./_utils-Dhd058D9.mjs";
|
|
3
|
+
import { t as buildClient } from "./client-bundler-CT-_26c5.mjs";
|
|
4
4
|
import { buildWorker } from "./worker-bundler.mjs";
|
|
5
5
|
import path from "node:path";
|
|
6
6
|
import { pathToFileURL } from "node:url";
|
|
7
7
|
import { mkdtemp, rm, writeFile } from "node:fs/promises";
|
|
8
8
|
import { tmpdir } from "node:os";
|
|
9
9
|
import { hash } from "node:crypto";
|
|
10
|
-
//#region _bundler.ts
|
|
10
|
+
//#region src/_bundler.ts
|
|
11
11
|
/**
|
|
12
12
|
* Bundle an agent directory: build agent.ts into worker ESM + client files.
|
|
13
13
|
*
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { t as CliError } from "./_output-
|
|
3
|
-
import { c as isEexist, l as readJson, o as errorMessage, p as writeJson } from "./_utils-
|
|
2
|
+
import { t as CliError } from "./_output-DbJt9gsl.mjs";
|
|
3
|
+
import { c as isEexist, l as readJson, o as errorMessage, p as writeJson } from "./_utils-Dhd058D9.mjs";
|
|
4
4
|
import { mkdtempSync } from "node:fs";
|
|
5
5
|
import path from "node:path";
|
|
6
6
|
import fs from "node:fs/promises";
|
|
@@ -8,7 +8,7 @@ import { sleep } from "@alexkroman1/aai/internal";
|
|
|
8
8
|
import { tmpdir } from "node:os";
|
|
9
9
|
import envPaths from "env-paths";
|
|
10
10
|
import { z } from "zod";
|
|
11
|
-
//#region _config.ts
|
|
11
|
+
//#region src/_config.ts
|
|
12
12
|
/**
|
|
13
13
|
* `.aai/project.json` lives in the working tree, so everything in it is
|
|
14
14
|
* untrusted input — a cloned repo can supply any value.
|
|
@@ -230,6 +230,8 @@ async function readGlobalConfig(configDir) {
|
|
|
230
230
|
async function writeGlobalConfig(configDir, data) {
|
|
231
231
|
await writeJson(path.join(configDir, "config.json"), data, { mode: 384 });
|
|
232
232
|
}
|
|
233
|
+
/** Local-session remedies FIRST — the two that need no account at all. */
|
|
234
|
+
const LOCAL_SESSION_HINT = "Any ONE of these is enough, and the first two need no aai account:\n 1. Put ASSEMBLYAI_API_KEY=<your key> in this project's .env — the same file `aai publish` uploads.\n 2. Or export it in your shell: export ASSEMBLYAI_API_KEY=<your key>\n 3. Or run `aai login`, and `aai dev` will use your account's key.\nGet a key at https://www.assemblyai.com/dashboard.";
|
|
233
235
|
/**
|
|
234
236
|
* The credential every platform command runs on.
|
|
235
237
|
*
|
|
@@ -251,9 +253,10 @@ async function writeGlobalConfig(configDir, data) {
|
|
|
251
253
|
* pointing `AAI_CONFIG_DIR` at a config dir holding a key from an interactive
|
|
252
254
|
* `aai login`.
|
|
253
255
|
*/
|
|
254
|
-
async function ensureApiKey(configDir) {
|
|
256
|
+
async function ensureApiKey(configDir, use = "platform") {
|
|
255
257
|
const config = await readGlobalConfig(configDir ?? getConfigDir());
|
|
256
258
|
if (config.apiKey) return config.apiKey;
|
|
259
|
+
if (use === "local-session") throw new CliError("missing_assemblyai_key", "ASSEMBLYAI_API_KEY is not set, and this agent's pipeline needs it to start a session.", LOCAL_SESSION_HINT);
|
|
257
260
|
throw new CliError("not_logged_in", "You're not logged in.", "Run `aai login` to link your account. Non-interactive setups can point AAI_CONFIG_DIR at a config dir holding a logged-in key.");
|
|
258
261
|
}
|
|
259
262
|
//#endregion
|
package/dist/_config.d.ts
CHANGED
|
@@ -73,6 +73,30 @@ export declare function updateGlobalConfig(update: (current: GlobalConfig) => Gl
|
|
|
73
73
|
export declare function approveServer(url: string, configDir?: string): Promise<void>;
|
|
74
74
|
export declare function readGlobalConfig(configDir?: string): Promise<GlobalConfig>;
|
|
75
75
|
export declare function writeGlobalConfig(configDir: string, data: GlobalConfig): Promise<void>;
|
|
76
|
+
/**
|
|
77
|
+
* Why the caller wants the key, which is what the FAILURE has to answer.
|
|
78
|
+
*
|
|
79
|
+
* One source, two questions. `"platform"` asks "who is this CLI logged in
|
|
80
|
+
* as?" — for `publish`/`push`/`logs`/`secret` a platform account genuinely IS
|
|
81
|
+
* the requirement, so the refusal is account-shaped and points at
|
|
82
|
+
* `aai login`. `"local-session"` is `aai dev` asking for a PROVIDER
|
|
83
|
+
* credential that the logged-in account merely happens to be able to supply:
|
|
84
|
+
* `ASSEMBLYAI_API_KEY` in `.env`, or exported in the shell, starts the same
|
|
85
|
+
* server with no account anywhere (see `resolveAgentEnv` in `_dev-server.ts`,
|
|
86
|
+
* which reaches here only when neither carries one).
|
|
87
|
+
*
|
|
88
|
+
* Answering the second question with the first's sentence is the defect this
|
|
89
|
+
* parameter exists to fix: `not_logged_in` names only account remedies
|
|
90
|
+
* (`aai login`, `AAI_CONFIG_DIR`), so `aai dev` read as "local development is
|
|
91
|
+
* gated on a cloud account" — and most of a twenty-persona DX audit believed
|
|
92
|
+
* it and abandoned the documented primary feedback loop, which was never
|
|
93
|
+
* gated at all.
|
|
94
|
+
*
|
|
95
|
+
* A PARAMETER rather than a second exported function because the source is
|
|
96
|
+
* shared: both answers must keep reading the one slot `aai login` writes, and
|
|
97
|
+
* a sibling function is how the two come to disagree about where a key lives.
|
|
98
|
+
*/
|
|
99
|
+
export type ApiKeyUse = "platform" | "local-session";
|
|
76
100
|
/**
|
|
77
101
|
* The credential every platform command runs on.
|
|
78
102
|
*
|
|
@@ -94,5 +118,5 @@ export declare function writeGlobalConfig(configDir: string, data: GlobalConfig)
|
|
|
94
118
|
* pointing `AAI_CONFIG_DIR` at a config dir holding a key from an interactive
|
|
95
119
|
* `aai login`.
|
|
96
120
|
*/
|
|
97
|
-
export declare function ensureApiKey(configDir?: string): Promise<string>;
|
|
121
|
+
export declare function ensureApiKey(configDir?: string, use?: ApiKeyUse): Promise<string>;
|
|
98
122
|
export {};
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { i as outputSilenced, r as notify } from "./_ui-
|
|
3
|
-
import { i as errorCode, o as errorMessage$1 } from "./_utils-
|
|
4
|
-
import { n as fallbackHtmlPlugin } from "./client-bundler-
|
|
5
|
-
import { t as DEDUPED_PEERS } from "./_vite-env-
|
|
2
|
+
import { i as outputSilenced, r as notify } from "./_ui-DCt4qZrk.mjs";
|
|
3
|
+
import { i as errorCode, o as errorMessage$1 } from "./_utils-Dhd058D9.mjs";
|
|
4
|
+
import { n as fallbackHtmlPlugin } from "./client-bundler-CT-_26c5.mjs";
|
|
5
|
+
import { t as DEDUPED_PEERS } from "./_vite-env-kejF0p2L.mjs";
|
|
6
6
|
import { buildWorker } from "./worker-bundler.mjs";
|
|
7
7
|
import { typecheckProject } from "./typecheck.mjs";
|
|
8
|
-
import { n as ensureApiKey } from "./_config-
|
|
9
|
-
import { n as createWorkerEvaluator } from "./_bundler-
|
|
10
|
-
import { t as resolveServerEnv } from "./_server-common-
|
|
8
|
+
import { n as ensureApiKey } from "./_config-ZY2euhdh.mjs";
|
|
9
|
+
import { n as createWorkerEvaluator } from "./_bundler-DEkjO1d8.mjs";
|
|
10
|
+
import { t as resolveServerEnv } from "./_server-common-BV4_CrP3.mjs";
|
|
11
11
|
import { existsSync, statSync } from "node:fs";
|
|
12
12
|
import path from "node:path";
|
|
13
13
|
import { omitUndefined } from "@alexkroman1/aai/utils";
|
|
@@ -19,7 +19,7 @@ import { defaultClientDir } from "@alexkroman1/aai-ui/client-dir";
|
|
|
19
19
|
import { watch } from "chokidar";
|
|
20
20
|
import getPort, { portNumbers } from "get-port";
|
|
21
21
|
import pDebounce from "p-debounce";
|
|
22
|
-
//#region _dev-env.ts
|
|
22
|
+
//#region src/_dev-env.ts
|
|
23
23
|
/**
|
|
24
24
|
* The env handed to `createServer` for host-mode connections: provider
|
|
25
25
|
* credentials plus the `AAI_ALLOW_HOST` gate read straight from the shell
|
|
@@ -97,7 +97,7 @@ function createDevLogger(silenced) {
|
|
|
97
97
|
};
|
|
98
98
|
}
|
|
99
99
|
//#endregion
|
|
100
|
-
//#region _dev-restart.ts
|
|
100
|
+
//#region src/_dev-restart.ts
|
|
101
101
|
/**
|
|
102
102
|
* Restart supervision for `aai dev`.
|
|
103
103
|
*
|
|
@@ -230,7 +230,7 @@ function createRestartSupervisor(ops) {
|
|
|
230
230
|
};
|
|
231
231
|
}
|
|
232
232
|
//#endregion
|
|
233
|
-
//#region _dev-typecheck.ts
|
|
233
|
+
//#region src/_dev-typecheck.ts
|
|
234
234
|
/**
|
|
235
235
|
* The background typecheck under `aai dev`.
|
|
236
236
|
*
|
|
@@ -276,7 +276,7 @@ function createDevTypecheck(cwd, report = notify) {
|
|
|
276
276
|
} };
|
|
277
277
|
}
|
|
278
278
|
//#endregion
|
|
279
|
-
//#region _dev-vite-config.ts
|
|
279
|
+
//#region src/_dev-vite-config.ts
|
|
280
280
|
/**
|
|
281
281
|
* The Vite dev server's config for a project with a `client.tsx`.
|
|
282
282
|
*
|
|
@@ -468,7 +468,7 @@ function viteDevConfig(cwd, vitePort, backendPort) {
|
|
|
468
468
|
};
|
|
469
469
|
}
|
|
470
470
|
//#endregion
|
|
471
|
-
//#region _dev-server.ts
|
|
471
|
+
//#region src/_dev-server.ts
|
|
472
472
|
/**
|
|
473
473
|
* Dev server for directory-based agents.
|
|
474
474
|
*
|
|
@@ -507,7 +507,7 @@ async function resolveAgentEnv(root, agentDef) {
|
|
|
507
507
|
const env = await resolveServerEnv(root);
|
|
508
508
|
const required = requiredProviderEnvVars(agentDef);
|
|
509
509
|
const hasShellKey = Boolean(process.env.ASSEMBLYAI_API_KEY);
|
|
510
|
-
if (required.includes("ASSEMBLYAI_API_KEY") && !env.ASSEMBLYAI_API_KEY && !hasShellKey) env.ASSEMBLYAI_API_KEY = await ensureApiKey();
|
|
510
|
+
if (required.includes("ASSEMBLYAI_API_KEY") && !env.ASSEMBLYAI_API_KEY && !hasShellKey) env.ASSEMBLYAI_API_KEY = await ensureApiKey(void 0, "local-session");
|
|
511
511
|
for (const warning of agentEnvWarnings(agentDef, env)) notify("warn", warning);
|
|
512
512
|
for (const warning of agentConfigWarnings(agentDef)) notify("warn", warning);
|
|
513
513
|
return env;
|
|
@@ -5,22 +5,30 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { type ChildProcess } from "node:child_process";
|
|
7
7
|
import type { MockRegistry } from "./_mock-registry.ts";
|
|
8
|
-
export declare const
|
|
8
|
+
export declare const packageDir: string;
|
|
9
9
|
export declare const packagesDir: string;
|
|
10
10
|
export declare const pm: "pnpm" | "npm" | "yarn";
|
|
11
11
|
export declare function aaiEnv(): NodeJS.ProcessEnv;
|
|
12
12
|
export declare function aai(aaiBin: string, args: string[], cwd: string, timeoutMs?: number): void;
|
|
13
13
|
/**
|
|
14
|
-
* {@link aai}, but CAPTURING
|
|
15
|
-
*
|
|
14
|
+
* {@link aai}, but CAPTURING and expecting the CLI to FAIL — for the cases
|
|
15
|
+
* whose subject is what it SAID on its way to a non-zero exit.
|
|
16
16
|
*
|
|
17
|
-
*
|
|
18
|
-
* every other call: an e2e failure's
|
|
19
|
-
* in the run log, and capturing it
|
|
17
|
+
* Capturing is separate from {@link aai} rather than a flag on it, because
|
|
18
|
+
* `stdio: "inherit"` is load-bearing for every other call: an e2e failure's
|
|
19
|
+
* only diagnosis trail is the child's output in the run log, and capturing it
|
|
20
|
+
* by default would take that away.
|
|
21
|
+
*
|
|
22
|
+
* The exit code is asserted HERE rather than left to the caller. `execaSync`
|
|
23
|
+
* throws on a non-zero exit, so the capturing helper this replaced could only
|
|
24
|
+
* be pointed at commands that succeed — and a `try`/`catch` around it would
|
|
25
|
+
* pass just as happily on a zero exit, which is the bug the one caller exists
|
|
26
|
+
* to catch (`aai test` named its unrun specs and exited 0 anyway).
|
|
20
27
|
*/
|
|
21
|
-
export declare function
|
|
28
|
+
export declare function aaiOutputFailing(aaiBin: string, args: string[], cwd: string, timeoutMs?: number): {
|
|
22
29
|
stdout: string;
|
|
23
30
|
stderr: string;
|
|
31
|
+
exitCode: number;
|
|
24
32
|
};
|
|
25
33
|
/**
|
|
26
34
|
* Build the CLI and return the path to the built binary.
|
|
@@ -1,10 +1,25 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { c as isEexist, l as readJson, p as writeJson } from "./_utils-
|
|
3
|
-
import { r as isDevMode, t as getMonorepoRoot } from "./_agent-
|
|
4
|
-
import { REPO_URL, downloadAndMergeTemplate } from "./_templates-
|
|
2
|
+
import { c as isEexist, l as readJson, p as writeJson } from "./_utils-Dhd058D9.mjs";
|
|
3
|
+
import { r as isDevMode, t as getMonorepoRoot } from "./_agent-Clbq3a4h.mjs";
|
|
4
|
+
import { REPO_URL, downloadAndMergeTemplate } from "./_templates-V4l5sZJy.mjs";
|
|
5
5
|
import path from "node:path";
|
|
6
6
|
import fs from "node:fs/promises";
|
|
7
|
-
//#region _init.ts
|
|
7
|
+
//#region src/_init.ts
|
|
8
|
+
/**
|
|
9
|
+
* The README every scaffolded project gets, and the first thing a new author
|
|
10
|
+
* reads. Three things in it are corrections rather than prose:
|
|
11
|
+
*
|
|
12
|
+
* - **`npm run dev`, never a bare `aai dev`.** The CLI is a devDependency, so
|
|
13
|
+
* after `npm install` the binary is in `node_modules/.bin` and NOT on
|
|
14
|
+
* `PATH`. The old quickstart said `aai dev`, which fails with
|
|
15
|
+
* `command not found` for everyone who has not installed the CLI globally.
|
|
16
|
+
* - **The key `aai dev` needs is named, with the two LOCAL ways first.** No
|
|
17
|
+
* step of local development needs a platform account; a twenty-persona DX
|
|
18
|
+
* audit read the account-shaped failure it used to get and concluded the
|
|
19
|
+
* opposite, then stopped using the loop this file documents.
|
|
20
|
+
* - **`aai login` appears where it is actually required.** It was in no
|
|
21
|
+
* user-facing doc at all, while the quickstart's own publish step needs it.
|
|
22
|
+
*/
|
|
8
23
|
function readmeContent(slug) {
|
|
9
24
|
return `# ${slug}
|
|
10
25
|
|
|
@@ -14,8 +29,41 @@ A voice agent built with [aai](${REPO_URL}).
|
|
|
14
29
|
|
|
15
30
|
\`\`\`sh
|
|
16
31
|
npm install # Install dependencies
|
|
17
|
-
|
|
18
|
-
|
|
32
|
+
npm run dev # Run locally on http://localhost:3000 (opens browser)
|
|
33
|
+
\`\`\`
|
|
34
|
+
|
|
35
|
+
The \`aai\` CLI is a devDependency of this project, so it lives in
|
|
36
|
+
\`node_modules/.bin\` rather than on your \`PATH\`. Run it through npm
|
|
37
|
+
(\`npm run dev\`, \`npm test\`, \`npm run build\`) or with \`npx aai <command>\`.
|
|
38
|
+
|
|
39
|
+
### The one key local development needs
|
|
40
|
+
|
|
41
|
+
The default pipeline (speech-to-text → LLM → text-to-speech) runs on a single
|
|
42
|
+
AssemblyAI key. **Any one of these is enough, and the first two need no aai
|
|
43
|
+
account** — nothing about running this agent locally is gated on one:
|
|
44
|
+
|
|
45
|
+
1. Put \`ASSEMBLYAI_API_KEY=<your key>\` in \`.env\` (this project's \`.env.example\`
|
|
46
|
+
documents it, and it is the same file \`aai publish\` uploads as secrets).
|
|
47
|
+
2. Or export it in your shell: \`export ASSEMBLYAI_API_KEY=<your key>\`.
|
|
48
|
+
3. Or run \`npx aai login\`, and \`aai dev\` will use your account's key.
|
|
49
|
+
|
|
50
|
+
Get a key at <https://www.assemblyai.com/dashboard>.
|
|
51
|
+
|
|
52
|
+
## Publishing
|
|
53
|
+
|
|
54
|
+
Publishing (and the studio it syncs to) is the one part that does need an
|
|
55
|
+
account:
|
|
56
|
+
|
|
57
|
+
\`\`\`sh
|
|
58
|
+
npx aai login # Link your account — once per machine
|
|
59
|
+
npm run publish:agent # Publish to production (and sync to the studio)
|
|
60
|
+
\`\`\`
|
|
61
|
+
|
|
62
|
+
You can also run this agent as a plain Node server, with no aai account and
|
|
63
|
+
nothing managed:
|
|
64
|
+
|
|
65
|
+
\`\`\`sh
|
|
66
|
+
npm start # Builds, then serves on http://127.0.0.1:3000
|
|
19
67
|
\`\`\`
|
|
20
68
|
|
|
21
69
|
## Secrets
|
|
@@ -32,9 +80,9 @@ MY_API_KEY=secret-value
|
|
|
32
80
|
**Production** — set secrets on the server:
|
|
33
81
|
|
|
34
82
|
\`\`\`sh
|
|
35
|
-
aai secret put MY_KEY # Set a secret (prompts for value)
|
|
36
|
-
aai secret list # List secret names
|
|
37
|
-
aai secret delete MY_KEY # Remove a secret
|
|
83
|
+
npx aai secret put MY_KEY # Set a secret (prompts for value)
|
|
84
|
+
npx aai secret list # List secret names
|
|
85
|
+
npx aai secret delete MY_KEY # Remove a secret
|
|
38
86
|
\`\`\`
|
|
39
87
|
|
|
40
88
|
`;
|
|
@@ -134,7 +182,7 @@ async function pinSharedDeps(targetDir, packagesDir, pkgJson) {
|
|
|
134
182
|
return;
|
|
135
183
|
}
|
|
136
184
|
const block = [...pins].sort(([a], [b]) => compareNames(a, b)).map(([name, version]) => ` "${name}": "${version}"`).join("\n");
|
|
137
|
-
await fs.writeFile(file, `${existing.trimEnd()}\n\n# Added by \`aai init\` in DEV MODE only — see pinSharedDeps in\n# packages/aai-cli/_init.ts. The @alexkroman1/* packages above are LINKED to
|
|
185
|
+
await fs.writeFile(file, `${existing.trimEnd()}\n\n# Added by \`aai init\` in DEV MODE only — see pinSharedDeps in\n# packages/aai-cli/src/_init.ts. The @alexkroman1/* packages above are LINKED to
|
|
138
186
|
# this checkout, so anything they and this project both depend on has to be
|
|
139
187
|
# ONE copy: two copies of xstate are two incompatible sets of types, and the
|
|
140
188
|
# typecheck gate refuses the deploy.\noverrides:\n${block}\n`);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
//#region _output.ts
|
|
2
|
+
//#region src/_output.ts
|
|
3
3
|
/**
|
|
4
4
|
* Determine output mode from CLI flags and TTY state.
|
|
5
5
|
*
|
|
@@ -11,7 +11,37 @@ function getOutputMode(args, isTTY = Boolean(process.stdout.isTTY)) {
|
|
|
11
11
|
return isTTY ? "human" : "json";
|
|
12
12
|
}
|
|
13
13
|
/**
|
|
14
|
-
*
|
|
14
|
+
* A CSI sequence — `ESC [ params intermediates final` — which covers every SGR
|
|
15
|
+
* colour pair a diagnostic can arrive wearing (`\u001B[31m` … `\u001B[0m`,
|
|
16
|
+
* `\u001B[38;5;246m`) as well as cursor moves.
|
|
17
|
+
*/
|
|
18
|
+
const ANSI_RAW = new RegExp(`${String.fromCharCode(27)}\\[[0-?]*[ -/]*[@-~]`, "g");
|
|
19
|
+
/**
|
|
20
|
+
* The same sequence AFTER `JSON.stringify`, which escapes the ESC byte as the
|
|
21
|
+
* six characters `\u001b`. Both forms are needed because a caller stringifies
|
|
22
|
+
* a whole result and hands the line here — see {@link writeLine}.
|
|
23
|
+
*/
|
|
24
|
+
const ANSI_JSON = /\\u001[bB]\[[0-?]*[ -/]*[@-~]/g;
|
|
25
|
+
/**
|
|
26
|
+
* Remove ANSI escape sequences, in raw or JSON-escaped form.
|
|
27
|
+
*
|
|
28
|
+
* A bundler colours its own diagnostics unconditionally, so `aai build`'s
|
|
29
|
+
* failure reached the JSON envelope as per-character SGR pairs
|
|
30
|
+
* (`[38;5;246m1 │[0m [38;5;249mi[0m[38;5;249mm[0m…`) — illegible in a CI log
|
|
31
|
+
* and meaningless to a `jq` consumer, which is the audience JSON mode has.
|
|
32
|
+
*/
|
|
33
|
+
function stripAnsi(text) {
|
|
34
|
+
return text.replace(ANSI_RAW, "").replace(ANSI_JSON, "");
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Write a machine-readable line to stdout, resolving only once it has been
|
|
38
|
+
* flushed.
|
|
39
|
+
*
|
|
40
|
+
* ANSI escapes are stripped on the way out. This function carries JSON mode's
|
|
41
|
+
* one result line and nothing else — human output goes through `log.*` in
|
|
42
|
+
* `_ui.ts`, which is where colour belongs — so stripping here is what keeps
|
|
43
|
+
* the envelope clean no matter which module built the string inside it, and
|
|
44
|
+
* leaves a TTY's coloured diagnostic intact.
|
|
15
45
|
*
|
|
16
46
|
* Resolves (never rejects) even when the write fails: the common failure is
|
|
17
47
|
* EPIPE — the consumer closed the pipe (`aai … --json | head -1`) — and there
|
|
@@ -19,8 +49,9 @@ function getOutputMode(args, isTTY = Boolean(process.stdout.isTTY)) {
|
|
|
19
49
|
* Stream-level `'error'` events are handled by {@link installStdoutGuard}.
|
|
20
50
|
*/
|
|
21
51
|
function writeLine(line) {
|
|
52
|
+
const clean = stripAnsi(line);
|
|
22
53
|
return new Promise((resolve) => {
|
|
23
|
-
process.stdout.write(
|
|
54
|
+
process.stdout.write(clean, () => resolve());
|
|
24
55
|
});
|
|
25
56
|
}
|
|
26
57
|
/**
|
package/dist/_output.d.ts
CHANGED
|
@@ -23,7 +23,23 @@ export declare function getOutputMode(args: {
|
|
|
23
23
|
json?: boolean | undefined;
|
|
24
24
|
}, isTTY?: boolean): OutputMode;
|
|
25
25
|
/**
|
|
26
|
-
*
|
|
26
|
+
* Remove ANSI escape sequences, in raw or JSON-escaped form.
|
|
27
|
+
*
|
|
28
|
+
* A bundler colours its own diagnostics unconditionally, so `aai build`'s
|
|
29
|
+
* failure reached the JSON envelope as per-character SGR pairs
|
|
30
|
+
* (`[38;5;246m1 │[0m [38;5;249mi[0m[38;5;249mm[0m…`) — illegible in a CI log
|
|
31
|
+
* and meaningless to a `jq` consumer, which is the audience JSON mode has.
|
|
32
|
+
*/
|
|
33
|
+
export declare function stripAnsi(text: string): string;
|
|
34
|
+
/**
|
|
35
|
+
* Write a machine-readable line to stdout, resolving only once it has been
|
|
36
|
+
* flushed.
|
|
37
|
+
*
|
|
38
|
+
* ANSI escapes are stripped on the way out. This function carries JSON mode's
|
|
39
|
+
* one result line and nothing else — human output goes through `log.*` in
|
|
40
|
+
* `_ui.ts`, which is where colour belongs — so stripping here is what keeps
|
|
41
|
+
* the envelope clean no matter which module built the string inside it, and
|
|
42
|
+
* leaves a TTY's coloured diagnostic intact.
|
|
27
43
|
*
|
|
28
44
|
* Resolves (never rejects) even when the write fails: the common failure is
|
|
29
45
|
* EPIPE — the consumer closed the pipe (`aai … --json | head -1`) — and there
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { requiredProviderEnvVars } from "@alexkroman1/aai-runtime";
|
|
3
|
-
//#region _preflight.ts
|
|
3
|
+
//#region src/_preflight.ts
|
|
4
4
|
/**
|
|
5
5
|
* The deploy-time credential preflight — the classic dev/prod failure, caught
|
|
6
6
|
* before the upload instead of at the deployed agent's first session.
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { i as errorCode } from "./_utils-
|
|
2
|
+
import { i as errorCode } from "./_utils-Dhd058D9.mjs";
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import { parseEnv } from "node:util";
|
|
5
5
|
import fs from "node:fs/promises";
|
|
6
|
-
//#region _server-common.ts
|
|
6
|
+
//#region src/_server-common.ts
|
|
7
7
|
/**
|
|
8
8
|
* Build the `ctx.env` record that agent tools will see at runtime.
|
|
9
9
|
*
|
|
@@ -35,7 +35,7 @@ async function resolveServerEnv(cwd, baseEnv) {
|
|
|
35
35
|
const env = {};
|
|
36
36
|
for (const [key, fileVal] of Object.entries(fileEntries)) {
|
|
37
37
|
const val = source[key] ?? fileVal;
|
|
38
|
-
if (val !== void 0) env[key] = val;
|
|
38
|
+
if (val !== void 0 && val !== "") env[key] = val;
|
|
39
39
|
}
|
|
40
40
|
return env;
|
|
41
41
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { n as getServerInfo } from "./_agent-
|
|
3
|
-
import { l as HINT_NOT_DEPLOYED, s as studioProjectApiUrl, u as apiRequest } from "./_studio-
|
|
4
|
-
//#region _slug-api.ts
|
|
2
|
+
import { n as getServerInfo } from "./_agent-Clbq3a4h.mjs";
|
|
3
|
+
import { l as HINT_NOT_DEPLOYED, s as studioProjectApiUrl, u as apiRequest } from "./_studio-DTi3EdXQ.mjs";
|
|
4
|
+
//#region src/_slug-api.ts
|
|
5
5
|
/**
|
|
6
6
|
* Authenticated request against a deployed agent's slug-scoped resource
|
|
7
7
|
* (`${serverUrl}/${slug}${resourcePath}`) — the one shape every per-agent
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { t as CliError } from "./_output-
|
|
2
|
+
import { t as CliError } from "./_output-DbJt9gsl.mjs";
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import { isRecord, omitUndefined } from "@alexkroman1/aai/utils";
|
|
5
5
|
import { MAX_SLUG_LENGTH, PREVIEW_SLUG_SUFFIX, VALID_SLUG_RE } from "@alexkroman1/aai/internal";
|
|
6
6
|
import { isLocalOnlyFile, snapshotWorkspaceFiles } from "@alexkroman1/aai/workspace-files";
|
|
7
7
|
import { FetchError, ofetch } from "ofetch";
|
|
8
8
|
import { slugifyName } from "@alexkroman1/aai/slugify";
|
|
9
|
-
//#region _api-client.ts
|
|
9
|
+
//#region src/_api-client.ts
|
|
10
10
|
/**
|
|
11
11
|
* Shared HTTP helper for platform API calls (deploy, delete, secrets).
|
|
12
12
|
*
|
|
@@ -143,7 +143,7 @@ function toApiError(err, url, opts) {
|
|
|
143
143
|
return new Error(`${opts.action} failed: could not reach ${url}\n ${hint}`, { cause });
|
|
144
144
|
}
|
|
145
145
|
//#endregion
|
|
146
|
-
//#region _studio.ts
|
|
146
|
+
//#region src/_studio.ts
|
|
147
147
|
/**
|
|
148
148
|
* Internals of the studio-workspace commands (`aai list/pull/push/publish`):
|
|
149
149
|
* the local source-file walk and the thin clients for the platform's
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { o as errorMessage$1 } from "./_utils-
|
|
3
|
-
import { t as getMonorepoRoot } from "./_agent-
|
|
2
|
+
import { o as errorMessage$1 } from "./_utils-Dhd058D9.mjs";
|
|
3
|
+
import { t as getMonorepoRoot } from "./_agent-Clbq3a4h.mjs";
|
|
4
4
|
import { existsSync } from "node:fs";
|
|
5
5
|
import path from "node:path";
|
|
6
6
|
import { isRecord } from "@alexkroman1/aai/utils";
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { t as CliError } from "./_output-
|
|
3
|
-
import { n as log } from "./_ui-
|
|
2
|
+
import { t as CliError } from "./_output-DbJt9gsl.mjs";
|
|
3
|
+
import { n as log } from "./_ui-DCt4qZrk.mjs";
|
|
4
4
|
import { typecheckProject } from "./typecheck.mjs";
|
|
5
|
-
//#region _typecheck-gate.ts
|
|
5
|
+
//#region src/_typecheck-gate.ts
|
|
6
6
|
/**
|
|
7
7
|
* The build/deploy typecheck gate: run the project's own `tsc --noEmit`
|
|
8
8
|
* (see `typecheck.ts`) and turn a failure into a structured CliError. The
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { styleText } from "node:util";
|
|
3
3
|
import * as p from "@clack/prompts";
|
|
4
|
-
//#region _ui.ts
|
|
4
|
+
//#region src/_ui.ts
|
|
5
5
|
const noop = () => {};
|
|
6
6
|
let silenced = false;
|
|
7
7
|
/** Log instance that delegates to clack (human mode) or no-ops (JSON mode). */
|
|
@@ -3,7 +3,7 @@ import { readFileSync } from "node:fs";
|
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import { errorDetail, errorMessage, errorMessage as errorMessage$1, omitUndefined } from "@alexkroman1/aai/utils";
|
|
5
5
|
import fs from "node:fs/promises";
|
|
6
|
-
//#region _utils.ts
|
|
6
|
+
//#region src/_utils.ts
|
|
7
7
|
/**
|
|
8
8
|
* The file that marks a directory as an agent project — the single source
|
|
9
9
|
* for the entry filename every command checks or scaffolds.
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { a as ok, t as CliError } from "./_output-
|
|
3
|
-
import { n as log, r as notify } from "./_ui-
|
|
4
|
-
import { r as evalWorkerBundle, t as buildAgentBundle } from "./_bundler-
|
|
5
|
-
import { assertTypechecks } from "./_typecheck-gate-
|
|
6
|
-
import { n as scanWorkflowDeterminism, t as determinismWarnings } from "./_workflow-determinism-
|
|
7
|
-
import { classifyVitestError, runVitest } from "./test-
|
|
2
|
+
import { a as ok, t as CliError } from "./_output-DbJt9gsl.mjs";
|
|
3
|
+
import { n as log, r as notify } from "./_ui-DCt4qZrk.mjs";
|
|
4
|
+
import { r as evalWorkerBundle, t as buildAgentBundle } from "./_bundler-DEkjO1d8.mjs";
|
|
5
|
+
import { assertTypechecks } from "./_typecheck-gate-sV4N5F93.mjs";
|
|
6
|
+
import { n as scanWorkflowDeterminism, t as determinismWarnings } from "./_workflow-determinism-C9l8uC2R.mjs";
|
|
7
|
+
import { TEST_FILES, classifyVitestError, runVitest } from "./test-guenJUxi.mjs";
|
|
8
8
|
import path from "node:path";
|
|
9
9
|
import fs from "node:fs/promises";
|
|
10
10
|
import { agentConfigWarnings } from "@alexkroman1/aai/manifest";
|
|
11
|
-
//#region build.ts
|
|
11
|
+
//#region src/build.ts
|
|
12
12
|
/**
|
|
13
13
|
* `aai build` — bundle the agent without deploying, behind the same gates
|
|
14
14
|
* deploy runs (tests, then typecheck), so the command previews the deploy
|
|
@@ -43,7 +43,10 @@ function testGateError(err) {
|
|
|
43
43
|
async function executeBuild(opts) {
|
|
44
44
|
const { cwd } = opts;
|
|
45
45
|
if (!opts.skipTests) try {
|
|
46
|
-
runVitest(cwd
|
|
46
|
+
runVitest(cwd, {
|
|
47
|
+
candidates: TEST_FILES,
|
|
48
|
+
all: true
|
|
49
|
+
});
|
|
47
50
|
} catch (err) {
|
|
48
51
|
throw testGateError(err);
|
|
49
52
|
}
|
package/dist/cli.d.ts
CHANGED
|
@@ -1 +1,2 @@
|
|
|
1
|
-
|
|
1
|
+
import { type ArgsDef, type CommandDef } from "citty";
|
|
2
|
+
export declare const mainCommand: CommandDef<ArgsDef>;
|