@alexkroman1/aai-cli 5.5.1 → 5.7.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/README.md +16 -7
- package/dist/{_agent-DMyOab9_.mjs → _agent-2nVugrN3.mjs} +22 -3
- package/dist/_agent.d.ts +3 -1
- package/dist/_api-client-B-upMGkc.mjs +104 -0
- package/dist/_api-client.d.ts +16 -0
- package/dist/_cli-common.d.ts +65 -0
- package/dist/{_config-5AEqhh-O.mjs → _config-Y5V-5Krn.mjs} +58 -9
- package/dist/_config.d.ts +23 -1
- package/dist/_deploy.d.ts +7 -0
- package/dist/{_dev-server-vV05Fnki.mjs → _dev-server-BB5N8kdh.mjs} +2 -2
- package/dist/{_init-BZ9t_Kz-.mjs → _init-D7JIT-IJ.mjs} +3 -3
- package/dist/{_slug-api-DaqQJHk8.mjs → _slug-api-CGJSST9B.mjs} +2 -2
- package/dist/_studio-commands.d.ts +73 -0
- package/dist/_studio.d.ts +64 -0
- package/dist/{_templates-Bv8CR800.mjs → _templates-Bt6u9_68.mjs} +19 -8
- package/dist/_templates.d.ts +9 -0
- package/dist/{_typecheck-gate-9IHWDnl1.mjs → _typecheck-gate-DvE8S3aQ.mjs} +1 -1
- package/dist/{build-D_PgQOD4.mjs → build-BXwDB78d.mjs} +1 -1
- package/dist/cli.mjs +264 -32
- package/dist/delete-DRNfvczK.mjs +53 -0
- package/dist/delete.d.ts +9 -2
- package/dist/{deploy-1eaXcfUw.mjs → deploy-Cp-wgME3.mjs} +7 -5
- package/dist/deploy.d.ts +2 -0
- package/dist/{dev-gVNdGFYY.mjs → dev-C4KyxouE.mjs} +1 -1
- package/dist/{init-DoU4_txp.mjs → init-BT-IU9AR.mjs} +15 -14
- package/dist/login-AA_UdRI-.mjs +172 -0
- package/dist/login.d.ts +33 -20
- package/dist/scaffold/package.json +4 -4
- package/dist/{secret-CGAIAbUx.mjs → secret-Dr0qnxeb.mjs} +1 -1
- package/dist/{storage-CnhOayhm.mjs → storage-CoQB8d-u.mjs} +1 -1
- package/dist/studio-sXvYUxr5.mjs +325 -0
- package/dist/studio.d.ts +54 -0
- package/package.json +4 -4
- package/dist/_api-client-MenP4-O7.mjs +0 -49
- package/dist/delete-DXilFBb1.mjs +0 -29
- package/dist/login-C59ZHzuO.mjs +0 -109
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Internals of the studio-workspace commands (`aai list/pull/push/publish`):
|
|
3
|
+
* the local source-file walk and the thin clients for the platform's
|
|
4
|
+
* `/studio/projects` routes. The workspace is the single source of truth —
|
|
5
|
+
* these helpers only move files between a local directory and the project's
|
|
6
|
+
* workspace row; production deploys happen exclusively through the studio's
|
|
7
|
+
* Publish route (which runs the deploy machinery in the project's sandbox).
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Mirrors of the studio workspace caps (`aai-studio-server/studio-limits.ts`)
|
|
11
|
+
* — by value, like `aai-guest/limits.ts`, since the CLI cannot depend on the
|
|
12
|
+
* private server package. The server re-validates every push; these exist so
|
|
13
|
+
* an oversized file is a named warning locally instead of a rejected upload.
|
|
14
|
+
*/
|
|
15
|
+
export declare const MAX_STUDIO_FILE_BYTES = 256000;
|
|
16
|
+
export declare const MAX_STUDIO_FILES = 100;
|
|
17
|
+
/**
|
|
18
|
+
* Walk a local project into the path→content record a workspace stores —
|
|
19
|
+
* the CLI-side twin of the guest's `snapshotWorkspace`: same ignored
|
|
20
|
+
* directories, same caps, oversized and non-text files skipped with a
|
|
21
|
+
* warning rather than failing the whole push.
|
|
22
|
+
*/
|
|
23
|
+
export declare function collectSourceFiles(dir: string): Promise<{
|
|
24
|
+
files: Record<string, string>;
|
|
25
|
+
warnings: string[];
|
|
26
|
+
}>;
|
|
27
|
+
/**
|
|
28
|
+
* A studio project name derived from a directory name, or null if unusable.
|
|
29
|
+
*
|
|
30
|
+
* A `-preview` suffix is deliberately unusable. Publishing a project deploys
|
|
31
|
+
* it under the project's own name, so a `*-preview` project would claim a
|
|
32
|
+
* slug the studio's orphan-preview sweep reaps hourly — deleting the agent,
|
|
33
|
+
* its app-database schema, and its secrets on a schedule the user never
|
|
34
|
+
* asked for. Refusing the name is recoverable (rename the directory); losing
|
|
35
|
+
* a published agent to the reaper is not.
|
|
36
|
+
*/
|
|
37
|
+
export declare function projectNameFromDir(dir: string): string | null;
|
|
38
|
+
/** The shareable studio URL for a project — what every command prints. */
|
|
39
|
+
export declare function studioProjectUrl(serverUrl: string, project: string): string;
|
|
40
|
+
/** `GET /studio/projects/:project` — see `projectPayload` server-side. */
|
|
41
|
+
export type StudioProject = {
|
|
42
|
+
files: Record<string, string>;
|
|
43
|
+
sourceHash: string;
|
|
44
|
+
deployedSlug?: string;
|
|
45
|
+
unpublished?: boolean;
|
|
46
|
+
};
|
|
47
|
+
export declare function listStudioProjects(serverUrl: string, apiKey: string): Promise<string[]>;
|
|
48
|
+
/** Fetch a project, or null when it doesn't exist (the push existence probe). */
|
|
49
|
+
export declare function fetchStudioProject(serverUrl: string, apiKey: string, project: string): Promise<StudioProject | null>;
|
|
50
|
+
/** `PUT /studio/projects/:project/source` — the atomic whole-tree push. */
|
|
51
|
+
export declare function pushStudioSource(serverUrl: string, apiKey: string, project: string, body: {
|
|
52
|
+
files: Record<string, string>;
|
|
53
|
+
baseHash?: string | undefined;
|
|
54
|
+
}): Promise<{
|
|
55
|
+
sourceHash: string;
|
|
56
|
+
created: boolean;
|
|
57
|
+
}>;
|
|
58
|
+
/** `POST /studio/projects/:project/deploy` — Publish, in the project's sandbox. */
|
|
59
|
+
export declare function publishStudioProject(serverUrl: string, apiKey: string, project: string): Promise<{
|
|
60
|
+
ok: true;
|
|
61
|
+
slug: string;
|
|
62
|
+
url: string;
|
|
63
|
+
output: string;
|
|
64
|
+
}>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { a as errorMessage } from "./_utils-Ch0J4s6a.mjs";
|
|
3
|
-
import { t as getMonorepoRoot } from "./_agent-
|
|
3
|
+
import { t as getMonorepoRoot } from "./_agent-2nVugrN3.mjs";
|
|
4
4
|
import { existsSync } from "node:fs";
|
|
5
5
|
import path from "node:path";
|
|
6
6
|
import fs from "node:fs/promises";
|
|
@@ -47,6 +47,22 @@ async function listTemplates(root = resolveTemplatesDir()) {
|
|
|
47
47
|
return available.filter((e) => e.isDirectory()).map((e) => e.name).sort();
|
|
48
48
|
}
|
|
49
49
|
/**
|
|
50
|
+
* Layer the base scaffold (package.json, tsconfig, …) into targetDir
|
|
51
|
+
* WITHOUT overwriting anything already there. Shared by `aai init`
|
|
52
|
+
* (underneath a template) and `aai pull` (underneath the studio workspace
|
|
53
|
+
* files — the workspace stores source, and the scaffold completes it into a
|
|
54
|
+
* runnable project the same way the guest's `ensureProjectShape` does
|
|
55
|
+
* before an in-sandbox build).
|
|
56
|
+
*/
|
|
57
|
+
async function layerScaffold(targetDir) {
|
|
58
|
+
const scaffoldDir = path.join(resolveTemplatesDir(), "scaffold");
|
|
59
|
+
if (existsSync(scaffoldDir)) await fs.cp(scaffoldDir, targetDir, {
|
|
60
|
+
recursive: true,
|
|
61
|
+
force: false,
|
|
62
|
+
errorOnExist: false
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
50
66
|
* Copy a template into targetDir, merging scaffold files underneath.
|
|
51
67
|
*/
|
|
52
68
|
async function downloadAndMergeTemplate(template, targetDir) {
|
|
@@ -58,12 +74,7 @@ async function downloadAndMergeTemplate(template, targetDir) {
|
|
|
58
74
|
recursive: true,
|
|
59
75
|
force: true
|
|
60
76
|
});
|
|
61
|
-
|
|
62
|
-
if (existsSync(scaffoldDir)) await fs.cp(scaffoldDir, targetDir, {
|
|
63
|
-
recursive: true,
|
|
64
|
-
force: false,
|
|
65
|
-
errorOnExist: false
|
|
66
|
-
});
|
|
77
|
+
await layerScaffold(targetDir);
|
|
67
78
|
}
|
|
68
79
|
//#endregion
|
|
69
|
-
export { REPO_URL, downloadAndMergeTemplate, listTemplates };
|
|
80
|
+
export { REPO_URL, downloadAndMergeTemplate, layerScaffold, listTemplates };
|
package/dist/_templates.d.ts
CHANGED
|
@@ -21,6 +21,15 @@ export declare function bundledTemplatesDir(): string;
|
|
|
21
21
|
* can never drift.
|
|
22
22
|
*/
|
|
23
23
|
export declare function listTemplates(root?: string): Promise<string[]>;
|
|
24
|
+
/**
|
|
25
|
+
* Layer the base scaffold (package.json, tsconfig, …) into targetDir
|
|
26
|
+
* WITHOUT overwriting anything already there. Shared by `aai init`
|
|
27
|
+
* (underneath a template) and `aai pull` (underneath the studio workspace
|
|
28
|
+
* files — the workspace stores source, and the scaffold completes it into a
|
|
29
|
+
* runnable project the same way the guest's `ensureProjectShape` does
|
|
30
|
+
* before an in-sandbox build).
|
|
31
|
+
*/
|
|
32
|
+
export declare function layerScaffold(targetDir: string): Promise<void>;
|
|
24
33
|
/**
|
|
25
34
|
* Copy a template into targetDir, merging scaffold files underneath.
|
|
26
35
|
*/
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { n as log, o as CliError, u as ok } from "./_ui-8kOEB-JH.mjs";
|
|
3
3
|
import { r as evalWorkerBundle, t as buildAgentBundle } from "./_bundler-Cjaxa2wi.mjs";
|
|
4
|
-
import {
|
|
4
|
+
import { assertTypechecks } from "./_typecheck-gate-DvE8S3aQ.mjs";
|
|
5
5
|
import { classifyVitestError, runVitest } from "./test-3Gq4pqH_.mjs";
|
|
6
6
|
//#region build.ts
|
|
7
7
|
/**
|
package/dist/cli.mjs
CHANGED
|
@@ -5,7 +5,7 @@ import { existsSync, readFileSync } from "node:fs";
|
|
|
5
5
|
import path from "node:path";
|
|
6
6
|
import { fileURLToPath } from "node:url";
|
|
7
7
|
import { defineCommand, runMain } from "citty";
|
|
8
|
-
//#region
|
|
8
|
+
//#region _cli-common.ts
|
|
9
9
|
/** Shared arg definitions for citty commands. */
|
|
10
10
|
const sharedArgs = {
|
|
11
11
|
server: {
|
|
@@ -23,21 +23,95 @@ const sharedArgs = {
|
|
|
23
23
|
description: "Output JSON (auto-detected in non-TTY)"
|
|
24
24
|
}
|
|
25
25
|
};
|
|
26
|
-
|
|
26
|
+
/** Flags citty handles itself, so no command declares them. */
|
|
27
|
+
const BUILTIN_FLAGS = /* @__PURE__ */ new Set([
|
|
28
|
+
"help",
|
|
29
|
+
"h",
|
|
30
|
+
"version",
|
|
31
|
+
"v"
|
|
32
|
+
]);
|
|
27
33
|
/**
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
34
|
+
* Flags in `rawArgs` that `argsDef` doesn't declare, in the form the user
|
|
35
|
+
* typed them.
|
|
36
|
+
*
|
|
37
|
+
* citty silently drops an unrecognized flag, so `aai push --serverr=http://x`
|
|
38
|
+
* exited 0 having pushed to the DEFAULT server — production, for an installed
|
|
39
|
+
* CLI — as if the flag had been honoured. Since `--server` is what decides
|
|
40
|
+
* where the API key and secret values are sent, a typo quietly retargeting it
|
|
41
|
+
* is worth failing on.
|
|
31
42
|
*/
|
|
32
|
-
function
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
43
|
+
function findUnknownFlags(rawArgs, argsDef) {
|
|
44
|
+
const declared = declaredFlagNames(argsDef);
|
|
45
|
+
const unknown = [];
|
|
46
|
+
for (const raw of rawArgs) {
|
|
47
|
+
if (raw === "--") break;
|
|
48
|
+
const token = flagToken(raw);
|
|
49
|
+
if (token && !declared.has(canonicalFlag(token))) unknown.push(token);
|
|
50
|
+
}
|
|
51
|
+
return unknown;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* A flag's comparison key: dashes dropped and lower-cased, with a leading
|
|
55
|
+
* `no` negation removed.
|
|
56
|
+
*
|
|
57
|
+
* citty accepts both `--allowMissingSecrets` and `--allow-missing-secrets` for
|
|
58
|
+
* an arg declared as `allowMissingSecrets`, and the guest's in-sandbox Publish
|
|
59
|
+
* spawns the kebab-case spelling. Comparing the literal text rejected
|
|
60
|
+
* `--allow-missing-secrets` as unknown and broke Publish for every studio
|
|
61
|
+
* user, so both sides are normalized to one key.
|
|
62
|
+
*/
|
|
63
|
+
function canonicalFlag(flag) {
|
|
64
|
+
return flag.replace(/^--?/, "").replace(/^no-/, "").replace(/-/g, "").toLowerCase();
|
|
65
|
+
}
|
|
66
|
+
/** Every flag name and alias `argsDef` declares, plus citty's built-ins. */
|
|
67
|
+
function declaredFlagNames(argsDef) {
|
|
68
|
+
const declared = new Set([...BUILTIN_FLAGS].map(canonicalFlag));
|
|
69
|
+
for (const [name, def] of Object.entries(argsDef)) {
|
|
70
|
+
const { type, alias } = def;
|
|
71
|
+
if (type === "positional") continue;
|
|
72
|
+
declared.add(canonicalFlag(name));
|
|
73
|
+
if (typeof alias === "string") declared.add(canonicalFlag(alias));
|
|
74
|
+
else if (Array.isArray(alias)) for (const a of alias) declared.add(canonicalFlag(a));
|
|
75
|
+
}
|
|
76
|
+
return declared;
|
|
77
|
+
}
|
|
78
|
+
/** The flag part of `raw` (`--server` from `--server=x`), or null if positional. */
|
|
79
|
+
function flagToken(raw) {
|
|
80
|
+
if (!raw.startsWith("-") || raw === "-" || /^-\d/.test(raw)) return null;
|
|
81
|
+
const eq = raw.indexOf("=");
|
|
82
|
+
return eq === -1 ? raw : raw.slice(0, eq);
|
|
83
|
+
}
|
|
84
|
+
/** Resolve a possibly-nested `Resolvable` citty field. */
|
|
85
|
+
async function resolve(value) {
|
|
86
|
+
return typeof value === "function" ? await value() : await value;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Unknown flags in `argv` for whichever (possibly nested) subcommand it
|
|
90
|
+
* selects — `[]` when everything is declared.
|
|
91
|
+
*
|
|
92
|
+
* Walks the real command tree rather than re-listing flags, so this cannot
|
|
93
|
+
* drift from what the commands accept. An unknown SUBCOMMAND is not reported:
|
|
94
|
+
* citty already answers that with usage text and a non-zero exit.
|
|
95
|
+
*/
|
|
96
|
+
async function unknownFlagsForArgv(root, argv) {
|
|
97
|
+
let cmd = root;
|
|
98
|
+
let i = 0;
|
|
99
|
+
for (; i < argv.length; i++) {
|
|
100
|
+
const token = argv[i];
|
|
101
|
+
if (token === void 0 || token.startsWith("-")) break;
|
|
102
|
+
const subCommands = await resolve(cmd.subCommands);
|
|
103
|
+
const next = subCommands?.[token];
|
|
104
|
+
if (next === void 0) {
|
|
105
|
+
if (subCommands && Object.keys(subCommands).length > 0) return [];
|
|
106
|
+
break;
|
|
107
|
+
}
|
|
108
|
+
const resolved = await resolve(next);
|
|
109
|
+
if (resolved === void 0) break;
|
|
110
|
+
cmd = resolved;
|
|
111
|
+
}
|
|
112
|
+
const argsDef = await resolve(cmd.args) ?? {};
|
|
113
|
+
return findUnknownFlags(argv.slice(i), argsDef);
|
|
39
114
|
}
|
|
40
|
-
const VERSION = readCliVersion(cliDir);
|
|
41
115
|
/** Shared command setup: resolve cwd, optionally require agent.ts. */
|
|
42
116
|
async function setup(opts) {
|
|
43
117
|
const cwd = resolveCwd();
|
|
@@ -77,6 +151,140 @@ async function runCommand(args, fn) {
|
|
|
77
151
|
if (mode === "json") await writeLine(`${JSON.stringify(result)}\n`);
|
|
78
152
|
if (!result.ok) process.exit(1);
|
|
79
153
|
}
|
|
154
|
+
//#endregion
|
|
155
|
+
//#region _studio-commands.ts
|
|
156
|
+
const list = defineCommand({
|
|
157
|
+
meta: {
|
|
158
|
+
name: "list",
|
|
159
|
+
description: "List your studio projects"
|
|
160
|
+
},
|
|
161
|
+
args: {
|
|
162
|
+
server: sharedArgs.server,
|
|
163
|
+
json: sharedArgs.json
|
|
164
|
+
},
|
|
165
|
+
async run({ args }) {
|
|
166
|
+
await runCommand(args, async () => {
|
|
167
|
+
const cwd = resolveCwd();
|
|
168
|
+
const { executeList } = await import("./studio-sXvYUxr5.mjs");
|
|
169
|
+
return executeList({
|
|
170
|
+
cwd,
|
|
171
|
+
server: args.server
|
|
172
|
+
});
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
});
|
|
176
|
+
const pull = defineCommand({
|
|
177
|
+
meta: {
|
|
178
|
+
name: "pull",
|
|
179
|
+
description: "Pull a studio project into a local directory"
|
|
180
|
+
},
|
|
181
|
+
args: {
|
|
182
|
+
project: {
|
|
183
|
+
type: "positional",
|
|
184
|
+
description: "Studio project name (see `aai list`)",
|
|
185
|
+
required: true
|
|
186
|
+
},
|
|
187
|
+
dir: {
|
|
188
|
+
type: "positional",
|
|
189
|
+
description: "Target directory (default: the project name)",
|
|
190
|
+
required: false
|
|
191
|
+
},
|
|
192
|
+
force: {
|
|
193
|
+
type: "boolean",
|
|
194
|
+
alias: "f",
|
|
195
|
+
description: "Overwrite files in a non-empty directory"
|
|
196
|
+
},
|
|
197
|
+
server: sharedArgs.server,
|
|
198
|
+
json: sharedArgs.json
|
|
199
|
+
},
|
|
200
|
+
async run({ args }) {
|
|
201
|
+
await runCommand(args, async () => {
|
|
202
|
+
const cwd = resolveCwd();
|
|
203
|
+
const { executePull } = await import("./studio-sXvYUxr5.mjs");
|
|
204
|
+
return executePull({
|
|
205
|
+
cwd,
|
|
206
|
+
project: args.project,
|
|
207
|
+
dir: args.dir,
|
|
208
|
+
force: args.force,
|
|
209
|
+
server: args.server
|
|
210
|
+
});
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
});
|
|
214
|
+
const push = defineCommand({
|
|
215
|
+
meta: {
|
|
216
|
+
name: "push",
|
|
217
|
+
description: "Sync this project's source to its studio workspace"
|
|
218
|
+
},
|
|
219
|
+
args: {
|
|
220
|
+
force: {
|
|
221
|
+
type: "boolean",
|
|
222
|
+
alias: "f",
|
|
223
|
+
description: "Overwrite studio-side changes instead of failing the fast-forward check"
|
|
224
|
+
},
|
|
225
|
+
server: sharedArgs.server,
|
|
226
|
+
json: sharedArgs.json
|
|
227
|
+
},
|
|
228
|
+
async run({ args }) {
|
|
229
|
+
await runCommand(args, async () => {
|
|
230
|
+
const cwd = await setup({ agent: true });
|
|
231
|
+
const { executePush } = await import("./studio-sXvYUxr5.mjs");
|
|
232
|
+
return executePush({
|
|
233
|
+
cwd,
|
|
234
|
+
server: args.server,
|
|
235
|
+
force: args.force
|
|
236
|
+
});
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
});
|
|
240
|
+
const publish = defineCommand({
|
|
241
|
+
meta: {
|
|
242
|
+
name: "publish",
|
|
243
|
+
description: "Push to the studio and deploy to production (the studio's Publish button)"
|
|
244
|
+
},
|
|
245
|
+
args: {
|
|
246
|
+
force: {
|
|
247
|
+
type: "boolean",
|
|
248
|
+
alias: "f",
|
|
249
|
+
description: "Overwrite studio-side changes instead of failing the fast-forward check"
|
|
250
|
+
},
|
|
251
|
+
server: sharedArgs.server,
|
|
252
|
+
json: sharedArgs.json,
|
|
253
|
+
skipTypecheck: {
|
|
254
|
+
type: "boolean",
|
|
255
|
+
description: "Skip type checking before publishing"
|
|
256
|
+
}
|
|
257
|
+
},
|
|
258
|
+
async run({ args }) {
|
|
259
|
+
await runCommand(args, async () => {
|
|
260
|
+
const cwd = await setup({ agent: true });
|
|
261
|
+
const { executePublish } = await import("./studio-sXvYUxr5.mjs");
|
|
262
|
+
return executePublish({
|
|
263
|
+
cwd,
|
|
264
|
+
server: args.server,
|
|
265
|
+
force: args.force,
|
|
266
|
+
skipTypecheck: args.skipTypecheck
|
|
267
|
+
});
|
|
268
|
+
});
|
|
269
|
+
}
|
|
270
|
+
});
|
|
271
|
+
//#endregion
|
|
272
|
+
//#region cli.ts
|
|
273
|
+
const cliDir = path.dirname(fileURLToPath(import.meta.url));
|
|
274
|
+
/**
|
|
275
|
+
* Read this CLI's own version from its package.json (source layout keeps it
|
|
276
|
+
* next to cli.ts; dist layout one level up). A missing or corrupt file must
|
|
277
|
+
* not brick every command over a cosmetic string — warn and fall back.
|
|
278
|
+
*/
|
|
279
|
+
function readCliVersion(dir) {
|
|
280
|
+
for (const candidate of [path.join(dir, "package.json"), path.join(dir, "..", "package.json")]) try {
|
|
281
|
+
const parsed = JSON.parse(readFileSync(candidate, "utf-8"));
|
|
282
|
+
if (typeof parsed.version === "string") return parsed.version;
|
|
283
|
+
} catch {}
|
|
284
|
+
process.stderr.write("warning: could not read aai's package.json — reporting version unknown\n");
|
|
285
|
+
return "unknown";
|
|
286
|
+
}
|
|
287
|
+
const VERSION = readCliVersion(cliDir);
|
|
80
288
|
const init = defineCommand({
|
|
81
289
|
meta: {
|
|
82
290
|
name: "init",
|
|
@@ -108,7 +316,7 @@ const init = defineCommand({
|
|
|
108
316
|
},
|
|
109
317
|
async run({ args }) {
|
|
110
318
|
await runCommand(args, async (mode) => {
|
|
111
|
-
const { executeInit } = await import("./init-
|
|
319
|
+
const { executeInit } = await import("./init-BT-IU9AR.mjs");
|
|
112
320
|
return executeInit({
|
|
113
321
|
dir: args.dir,
|
|
114
322
|
force: args.force,
|
|
@@ -137,7 +345,7 @@ const dev = defineCommand({
|
|
|
137
345
|
async run({ args }) {
|
|
138
346
|
await runCommand(args, async () => {
|
|
139
347
|
const cwd = await setup({ agent: true });
|
|
140
|
-
const { executeDev } = await import("./dev-
|
|
348
|
+
const { executeDev } = await import("./dev-C4KyxouE.mjs");
|
|
141
349
|
return executeDev({
|
|
142
350
|
cwd,
|
|
143
351
|
port: args.port
|
|
@@ -178,7 +386,7 @@ const build = defineCommand({
|
|
|
178
386
|
async run({ args }) {
|
|
179
387
|
await runCommand(args, async () => {
|
|
180
388
|
const cwd = await setup({ agent: true });
|
|
181
|
-
const { executeBuild } = await import("./build-
|
|
389
|
+
const { executeBuild } = await import("./build-BXwDB78d.mjs");
|
|
182
390
|
return executeBuild({
|
|
183
391
|
cwd,
|
|
184
392
|
skipTests: args.skipTests,
|
|
@@ -190,7 +398,8 @@ const build = defineCommand({
|
|
|
190
398
|
const deploy = defineCommand({
|
|
191
399
|
meta: {
|
|
192
400
|
name: "deploy",
|
|
193
|
-
description: "
|
|
401
|
+
description: "(internal) used by studio Publish",
|
|
402
|
+
hidden: true
|
|
194
403
|
},
|
|
195
404
|
args: {
|
|
196
405
|
server: sharedArgs.server,
|
|
@@ -199,6 +408,10 @@ const deploy = defineCommand({
|
|
|
199
408
|
type: "boolean",
|
|
200
409
|
description: "Deploy even when the agent's providers are missing credentials (the server warns instead of rejecting; set them afterwards with `aai secret put`)"
|
|
201
410
|
},
|
|
411
|
+
allowPreviewSlug: {
|
|
412
|
+
type: "boolean",
|
|
413
|
+
description: "Permit a `-preview`-suffixed slug (reserved for studio auto-previews; studio-internal — a slug you claim this way is subject to the preview reaper)"
|
|
414
|
+
},
|
|
202
415
|
skipTypecheck: {
|
|
203
416
|
type: "boolean",
|
|
204
417
|
description: "Skip type checking before deploy"
|
|
@@ -207,11 +420,12 @@ const deploy = defineCommand({
|
|
|
207
420
|
async run({ args }) {
|
|
208
421
|
await runCommand(args, async () => {
|
|
209
422
|
const cwd = await setup({ agent: true });
|
|
210
|
-
const { executeDeploy } = await import("./deploy-
|
|
423
|
+
const { executeDeploy } = await import("./deploy-Cp-wgME3.mjs");
|
|
211
424
|
return executeDeploy({
|
|
212
425
|
cwd,
|
|
213
426
|
server: args.server,
|
|
214
427
|
allowMissingSecrets: args.allowMissingSecrets,
|
|
428
|
+
allowPreviewSlug: args.allowPreviewSlug,
|
|
215
429
|
skipTypecheck: args.skipTypecheck
|
|
216
430
|
});
|
|
217
431
|
});
|
|
@@ -220,7 +434,7 @@ const deploy = defineCommand({
|
|
|
220
434
|
const del = defineCommand({
|
|
221
435
|
meta: {
|
|
222
436
|
name: "delete",
|
|
223
|
-
description: "
|
|
437
|
+
description: "Delete the studio project and its deployed agents"
|
|
224
438
|
},
|
|
225
439
|
args: {
|
|
226
440
|
server: sharedArgs.server,
|
|
@@ -229,7 +443,7 @@ const del = defineCommand({
|
|
|
229
443
|
async run({ args }) {
|
|
230
444
|
await runCommand(args, async () => {
|
|
231
445
|
const cwd = await setup();
|
|
232
|
-
const { executeDelete } = await import("./delete-
|
|
446
|
+
const { executeDelete } = await import("./delete-DRNfvczK.mjs");
|
|
233
447
|
return executeDelete({
|
|
234
448
|
cwd,
|
|
235
449
|
server: args.server
|
|
@@ -260,7 +474,7 @@ const secret = defineCommand({
|
|
|
260
474
|
async run({ args }) {
|
|
261
475
|
await runCommand(args, async (mode) => {
|
|
262
476
|
const cwd = await setup();
|
|
263
|
-
const { executeSecretPut, NO_INPUT, readStdin } = await import("./secret-
|
|
477
|
+
const { executeSecretPut, NO_INPUT, readStdin } = await import("./secret-Dr0qnxeb.mjs");
|
|
264
478
|
const value = mode === "json" ? await readStdin() : void 0;
|
|
265
479
|
if (mode === "json" && !value) throw new CliError(...NO_INPUT);
|
|
266
480
|
return executeSecretPut(cwd, args.name, value, args.server);
|
|
@@ -284,7 +498,7 @@ const secret = defineCommand({
|
|
|
284
498
|
async run({ args }) {
|
|
285
499
|
await runCommand(args, async () => {
|
|
286
500
|
const cwd = await setup();
|
|
287
|
-
const { executeSecretDelete } = await import("./secret-
|
|
501
|
+
const { executeSecretDelete } = await import("./secret-Dr0qnxeb.mjs");
|
|
288
502
|
return executeSecretDelete(cwd, args.name, args.server);
|
|
289
503
|
});
|
|
290
504
|
}
|
|
@@ -301,7 +515,7 @@ const secret = defineCommand({
|
|
|
301
515
|
async run({ args }) {
|
|
302
516
|
await runCommand(args, async () => {
|
|
303
517
|
const cwd = await setup();
|
|
304
|
-
const { executeSecretList } = await import("./secret-
|
|
518
|
+
const { executeSecretList } = await import("./secret-Dr0qnxeb.mjs");
|
|
305
519
|
return executeSecretList(cwd, args.server);
|
|
306
520
|
});
|
|
307
521
|
}
|
|
@@ -336,7 +550,7 @@ const storage = defineCommand({
|
|
|
336
550
|
},
|
|
337
551
|
async run({ args }) {
|
|
338
552
|
await runCommand(args, async () => {
|
|
339
|
-
const { executeStorageStatus } = await import("./storage-
|
|
553
|
+
const { executeStorageStatus } = await import("./storage-CoQB8d-u.mjs");
|
|
340
554
|
return executeStorageStatus(resolveStorageCwd(args.dir), args.server);
|
|
341
555
|
});
|
|
342
556
|
}
|
|
@@ -353,7 +567,7 @@ const storage = defineCommand({
|
|
|
353
567
|
},
|
|
354
568
|
async run({ args }) {
|
|
355
569
|
await runCommand(args, async () => {
|
|
356
|
-
const { executeStorageEnable } = await import("./storage-
|
|
570
|
+
const { executeStorageEnable } = await import("./storage-CoQB8d-u.mjs");
|
|
357
571
|
return executeStorageEnable(resolveStorageCwd(args.dir), args.server);
|
|
358
572
|
});
|
|
359
573
|
}
|
|
@@ -375,7 +589,7 @@ const storage = defineCommand({
|
|
|
375
589
|
},
|
|
376
590
|
async run({ args }) {
|
|
377
591
|
await runCommand(args, async () => {
|
|
378
|
-
const { executeStorageDisable } = await import("./storage-
|
|
592
|
+
const { executeStorageDisable } = await import("./storage-CoQB8d-u.mjs");
|
|
379
593
|
return executeStorageDisable(resolveStorageCwd(args.dir), {
|
|
380
594
|
server: args.server,
|
|
381
595
|
force: args.force
|
|
@@ -388,7 +602,7 @@ const storage = defineCommand({
|
|
|
388
602
|
const login = defineCommand({
|
|
389
603
|
meta: {
|
|
390
604
|
name: "login",
|
|
391
|
-
description: "
|
|
605
|
+
description: "Link your signed-in browser account and save your API key"
|
|
392
606
|
},
|
|
393
607
|
args: {
|
|
394
608
|
server: sharedArgs.server,
|
|
@@ -396,7 +610,7 @@ const login = defineCommand({
|
|
|
396
610
|
},
|
|
397
611
|
async run({ args }) {
|
|
398
612
|
await runCommand(args, async () => {
|
|
399
|
-
const { executeLogin } = await import("./login-
|
|
613
|
+
const { executeLogin } = await import("./login-AA_UdRI-.mjs");
|
|
400
614
|
return executeLogin({ server: args.server });
|
|
401
615
|
});
|
|
402
616
|
}
|
|
@@ -409,7 +623,7 @@ const templates = defineCommand({
|
|
|
409
623
|
args: { json: sharedArgs.json },
|
|
410
624
|
async run({ args }) {
|
|
411
625
|
await runCommand(args, async (mode) => {
|
|
412
|
-
const { listTemplates } = await import("./_templates-
|
|
626
|
+
const { listTemplates } = await import("./_templates-Bt6u9_68.mjs");
|
|
413
627
|
const names = await listTemplates();
|
|
414
628
|
if (mode === "human") {
|
|
415
629
|
for (const name of names) log.message(name);
|
|
@@ -433,6 +647,10 @@ const mainCommand = defineCommand({
|
|
|
433
647
|
dev,
|
|
434
648
|
test,
|
|
435
649
|
build,
|
|
650
|
+
list,
|
|
651
|
+
pull,
|
|
652
|
+
push,
|
|
653
|
+
publish,
|
|
436
654
|
deploy,
|
|
437
655
|
delete: del,
|
|
438
656
|
login,
|
|
@@ -450,14 +668,28 @@ if (process.env.VITEST !== "true") {
|
|
|
450
668
|
return;
|
|
451
669
|
}
|
|
452
670
|
if (process.stdin.isTTY && process.stdout.isTTY) {
|
|
453
|
-
if (await (await import("@clack/prompts")).confirm({ message: "
|
|
671
|
+
if (await (await import("@clack/prompts")).confirm({ message: "Publish this agent to production?" }) !== true) {
|
|
454
672
|
log.info("Cancelled. Run `aai --help` to see all commands.");
|
|
455
673
|
process.exit(0);
|
|
456
674
|
}
|
|
457
675
|
}
|
|
458
|
-
process.argv.splice(2, 0, "
|
|
676
|
+
process.argv.splice(2, 0, "publish");
|
|
677
|
+
};
|
|
678
|
+
/**
|
|
679
|
+
* Refuse an unrecognized flag instead of ignoring it.
|
|
680
|
+
*
|
|
681
|
+
* citty drops one silently, so `aai push --serverr=http://x` exited 0 having
|
|
682
|
+
* pushed to the DEFAULT server. `--server` decides where the API key and
|
|
683
|
+
* secret values go, so a typo that quietly retargets it is worth failing on.
|
|
684
|
+
*/
|
|
685
|
+
const assertKnownFlags = async () => {
|
|
686
|
+
const unknown = await unknownFlagsForArgv(mainCommand, process.argv.slice(2));
|
|
687
|
+
if (unknown.length === 0) return;
|
|
688
|
+
log.error(`Unknown ${unknown.length === 1 ? "option" : "options"}: ${unknown.join(", ")}`);
|
|
689
|
+
log.info("Run `aai <command> --help` to see the options it accepts.");
|
|
690
|
+
process.exit(1);
|
|
459
691
|
};
|
|
460
|
-
runDefault().then(() => runMain(mainCommand)).catch((err) => {
|
|
692
|
+
runDefault().then(assertKnownFlags).then(() => runMain(mainCommand)).catch((err) => {
|
|
461
693
|
log.error(errorMessage(err));
|
|
462
694
|
process.exitCode = 1;
|
|
463
695
|
});
|
|
@@ -0,0 +1,53 @@
|
|
|
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";
|
|
5
|
+
import { n as apiRequest, t as HINT_NOT_DEPLOYED } from "./_api-client-B-upMGkc.mjs";
|
|
6
|
+
//#region delete.ts
|
|
7
|
+
async function runDelete(opts) {
|
|
8
|
+
await apiRequest(`${opts.url}/${opts.slug}`, {
|
|
9
|
+
method: "DELETE",
|
|
10
|
+
apiKey: opts.apiKey,
|
|
11
|
+
action: "delete",
|
|
12
|
+
hints: { 404: HINT_NOT_DEPLOYED },
|
|
13
|
+
...opts.fetch ? { fetch: opts.fetch } : {}
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Delete THE PROJECT. A studio-linked directory deletes its studio project
|
|
18
|
+
* (`DELETE /studio/projects/:project`), which cascades server-side to the
|
|
19
|
+
* workspace, chat, and the project's deployed + preview agents — the exact
|
|
20
|
+
* delete the studio's own Delete button runs. A directory that only knows a
|
|
21
|
+
* slug (no studio link) deletes that deployed agent directly.
|
|
22
|
+
*/
|
|
23
|
+
async function executeDelete(opts) {
|
|
24
|
+
const { cwd } = opts;
|
|
25
|
+
const { config, serverUrl, apiKey } = await resolveDeployTarget(cwd, opts.server);
|
|
26
|
+
if (config?.studioProject) {
|
|
27
|
+
const project = config.studioProject;
|
|
28
|
+
log.step(`Deleting studio project ${project} (and its deployed agents)`);
|
|
29
|
+
await apiRequest(`${serverUrl}/studio/projects/${encodeURIComponent(project)}`, {
|
|
30
|
+
method: "DELETE",
|
|
31
|
+
apiKey,
|
|
32
|
+
action: "delete",
|
|
33
|
+
hints: { 404: "Run `aai list` to see your projects." }
|
|
34
|
+
});
|
|
35
|
+
log.success(`Deleted ${project}`);
|
|
36
|
+
await writeProjectConfig(cwd, { serverUrl });
|
|
37
|
+
return ok({
|
|
38
|
+
project,
|
|
39
|
+
...config.slug ? { slug: config.slug } : {}
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
const { slug } = await getServerInfo(cwd, opts.server);
|
|
43
|
+
log.step(`Deleting ${slug}`);
|
|
44
|
+
await runDelete({
|
|
45
|
+
url: serverUrl,
|
|
46
|
+
slug,
|
|
47
|
+
apiKey
|
|
48
|
+
});
|
|
49
|
+
log.success(`Deleted ${serverUrl}/${slug}`);
|
|
50
|
+
return ok({ slug });
|
|
51
|
+
}
|
|
52
|
+
//#endregion
|
|
53
|
+
export { executeDelete };
|
package/dist/delete.d.ts
CHANGED
|
@@ -8,9 +8,16 @@ export type DeleteOpts = {
|
|
|
8
8
|
};
|
|
9
9
|
export declare function runDelete(opts: DeleteOpts): Promise<void>;
|
|
10
10
|
type DeleteData = {
|
|
11
|
-
slug
|
|
11
|
+
slug?: string;
|
|
12
|
+
project?: string;
|
|
12
13
|
};
|
|
13
|
-
/**
|
|
14
|
+
/**
|
|
15
|
+
* Delete THE PROJECT. A studio-linked directory deletes its studio project
|
|
16
|
+
* (`DELETE /studio/projects/:project`), which cascades server-side to the
|
|
17
|
+
* workspace, chat, and the project's deployed + preview agents — the exact
|
|
18
|
+
* delete the studio's own Delete button runs. A directory that only knows a
|
|
19
|
+
* slug (no studio link) deletes that deployed agent directly.
|
|
20
|
+
*/
|
|
14
21
|
export declare function executeDelete(opts: {
|
|
15
22
|
cwd: string;
|
|
16
23
|
server?: string | undefined;
|