@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.
- package/dist/_agent-cHGzbDVG.mjs +108 -0
- package/dist/_api-client-yJD7xGfd.mjs +47 -0
- package/dist/_bundler-BRQFvx00.mjs +62 -0
- package/dist/_config-zV70t71V.mjs +125 -0
- package/dist/_dev-server-CBrIeDoI.mjs +214 -0
- package/dist/{_init-Bh5etNEh.mjs → _init-y7K-dzni.mjs} +17 -43
- package/dist/{_output-vvoR6N1x.mjs → _output-fy2bXRNb.mjs} +12 -19
- package/dist/{_ui-nOp7hFVy.mjs → _ui-YqQ6Fi8K.mjs} +14 -20
- package/dist/_utils-BeU10C7O.mjs +55 -0
- package/dist/_vite-env-CmXG4ZAu.mjs +31 -0
- package/dist/cli.mjs +41 -40
- package/dist/client-bundler-D4VKqCxw.mjs +125 -0
- package/dist/client-bundler.mjs +3 -0
- package/dist/{delete-BEC2ZXbk.mjs → delete-DE35s3d5.mjs} +7 -8
- package/dist/{deploy-D8uMWSDH.mjs → deploy-C0LittrE.mjs} +20 -18
- package/dist/{dev-D2EwGHYi.mjs → dev-BvjnXK2x.mjs} +10 -3
- package/dist/{init-GWTdzrrm.mjs → init-kYsRaf7e.mjs} +29 -75
- package/dist/{secret-DlSN4FdF.mjs → secret-D-90QtDQ.mjs} +14 -16
- package/dist/{test-BLYrV5ap.mjs → test-C6jwCnFu.mjs} +30 -5
- package/dist/types.mjs +2 -0
- package/dist/worker-bundler.mjs +68 -0
- package/package.json +24 -13
- package/dist/_agent-De8f1JdZ.mjs +0 -38
- package/dist/_api-client-Cf9Lv2Rw.mjs +0 -46
- package/dist/_bundler-CMMSjh9o.mjs +0 -143
- package/dist/_config-B0FXR5GQ.mjs +0 -77
- package/dist/_default-html-BasMCgr9.mjs +0 -62
- package/dist/_dev-server-DMFyqc9v.mjs +0 -143
- package/dist/_utils-DZo3_J_v.mjs +0 -23
- package/dist/rolldown-runtime-uZa2dNXj.mjs +0 -15
- /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>`.
|
|
25
|
-
*
|
|
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
|
|
20
|
+
async function withOutput(mode, fn) {
|
|
29
21
|
const result = await fn();
|
|
30
|
-
if (mode === "json") {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
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 {
|
|
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
|
|
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
|
|
6
|
+
let silenced = false;
|
|
14
7
|
/** Log instance that delegates to clack (human mode) or no-ops (JSON mode). */
|
|
15
|
-
const log
|
|
16
|
-
return Reflect.get(
|
|
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
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
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 {
|
|
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 {
|
|
3
|
-
import {
|
|
4
|
-
import { n as resolveCwd,
|
|
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
|
-
|
|
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
|
-
*
|
|
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
|
|
77
|
+
if (opts.setYes) args.yes = true;
|
|
77
78
|
}
|
|
78
|
-
|
|
79
|
-
|
|
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-
|
|
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-
|
|
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-
|
|
166
|
+
const { executeTest } = await import("./test-C6jwCnFu.mjs");
|
|
161
167
|
return executeTest(cwd);
|
|
162
|
-
}, {
|
|
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-
|
|
187
|
+
const { runVitest } = await import("./test-C6jwCnFu.mjs");
|
|
184
188
|
runVitest(cwd);
|
|
185
189
|
}
|
|
186
|
-
const { executeBuild } = await import("./_bundler-
|
|
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-
|
|
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-
|
|
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
|
-
}
|
|
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-
|
|
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
|
-
}
|
|
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-
|
|
282
|
+
const { executeSecretDelete } = await import("./secret-D-90QtDQ.mjs");
|
|
284
283
|
return executeSecretDelete(cwd, args.name, args.server);
|
|
285
|
-
}
|
|
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-
|
|
299
|
+
const { executeSecretList } = await import("./secret-D-90QtDQ.mjs");
|
|
301
300
|
return executeSecretList(cwd, args.server);
|
|
302
|
-
}
|
|
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
|
-
|
|
336
|
-
|
|
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 };
|
|
@@ -1,17 +1,16 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { getServerInfo } from "./_agent-
|
|
5
|
-
import { t as
|
|
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
|
|
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 {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import { buildAgentBundle } from "./_bundler-
|
|
7
|
-
import { t as resolveServerEnv } from "./_server-common-
|
|
8
|
-
import { t as
|
|
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 (
|
|
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
|
-
})).
|
|
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
|
|
33
|
-
const
|
|
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 {
|
|
3
|
-
import {
|
|
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-
|
|
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
|