@alexkroman1/aai-cli 5.1.0 → 5.2.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-D39qatZJ.mjs → _agent-D8zBb3M5.mjs} +2 -3
- package/dist/_agent.d.ts +39 -0
- package/dist/{_api-client-a6cPMebU.mjs → _api-client-MenP4-O7.mjs} +3 -1
- package/dist/_api-client.d.ts +37 -0
- package/dist/{_bundler-DdmuZzeR.mjs → _bundler-DFS4xxqE.mjs} +3 -13
- package/dist/_bundler.d.ts +46 -0
- package/dist/{_config-Czjhvaax.mjs → _config-D3F9km8X.mjs} +3 -3
- package/dist/_config.d.ts +57 -0
- package/dist/_default-html.d.ts +12 -0
- package/dist/_deploy.d.ts +28 -0
- package/dist/{_dev-server-BCbEUhmv.mjs → _dev-server-BBUWo0sb.mjs} +12 -14
- package/dist/_dev-server.d.ts +74 -0
- package/dist/{_init-H-lw7czL.mjs → _init-DU-sXH6S.mjs} +47 -65
- package/dist/_init.d.ts +7 -0
- package/dist/_mock-api.d.ts +22 -0
- package/dist/_mock-registry.d.ts +17 -0
- package/dist/_output.d.ts +50 -0
- package/dist/{_server-common-B75oco06.mjs → _server-common-CnaP_Urf.mjs} +2 -1
- package/dist/_server-common.d.ts +17 -0
- package/dist/_slug-api-19R5kZ0U.mjs +27 -0
- package/dist/_slug-api.d.ts +15 -0
- package/dist/_templates.d.ts +21 -0
- package/dist/{_typecheck-gate-B1GcKZX-.mjs → _typecheck-gate-9IHWDnl1.mjs} +2 -2
- package/dist/_typecheck-gate.d.ts +7 -0
- package/dist/{_ui-DXZ9prrM.mjs → _ui-8kOEB-JH.mjs} +6 -3
- package/dist/_ui.d.ts +22 -0
- package/dist/{_utils-C502jKo8.mjs → _utils-Ch0J4s6a.mjs} +17 -1
- package/dist/_utils.d.ts +48 -0
- package/dist/_vite-env.d.ts +8 -0
- package/dist/build-Xq1xxoSg.mjs +38 -0
- package/dist/build.d.ts +16 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.mjs +35 -52
- package/dist/{client-bundler-DO3GgO6p.mjs → client-bundler-BWDkUeEP.mjs} +5 -6
- package/dist/client-bundler.d.ts +21 -0
- package/dist/client-bundler.mjs +1 -1
- package/dist/{delete-K24hW1ab.mjs → delete-kSXFLxek.mjs} +4 -4
- package/dist/delete.d.ts +18 -0
- package/dist/{deploy-D-dnt9L8.mjs → deploy-Ci0X1gp2.mjs} +8 -8
- package/dist/deploy.d.ts +15 -0
- package/dist/{dev-C8o-p13B.mjs → dev-g7sGt8qX.mjs} +3 -3
- package/dist/dev.d.ts +13 -0
- package/dist/{init-B53rR3yD.mjs → init-BjeK8crW.mjs} +10 -17
- package/dist/init.d.ts +24 -0
- package/dist/scaffold/.env.example +11 -0
- package/dist/scaffold/CLAUDE.md +919 -0
- package/dist/scaffold/global.d.ts +1 -0
- package/dist/scaffold/package.json +32 -0
- package/dist/scaffold/pnpm-workspace.yaml +13 -0
- package/dist/scaffold/tsconfig.json +19 -0
- package/dist/scaffold/vite.config.ts +14 -0
- package/dist/scaffold/vitest.config.ts +24 -0
- package/dist/{secret-C4unwCEw.mjs → secret-DOva9OGk.mjs} +21 -20
- package/dist/secret.d.ts +25 -0
- package/dist/{storage-tZM1J8qj.mjs → storage-vM6HjDZZ.mjs} +6 -13
- package/dist/storage.d.ts +22 -0
- package/dist/templates/code-interpreter/agent.ts +11 -0
- package/dist/templates/code-interpreter/system-prompt.md +18 -0
- package/dist/templates/dispatch-center/agent.test.ts +153 -0
- package/dist/templates/dispatch-center/agent.ts +50 -0
- package/dist/templates/dispatch-center/client.tsx +378 -0
- package/dist/templates/dispatch-center/shared.ts +631 -0
- package/dist/templates/dispatch-center/system-prompt.md +39 -0
- package/dist/templates/dispatch-center/tools/incident_add_note.ts +27 -0
- package/dist/templates/dispatch-center/tools/incident_create.ts +79 -0
- package/dist/templates/dispatch-center/tools/incident_escalate.ts +88 -0
- package/dist/templates/dispatch-center/tools/incident_get.ts +36 -0
- package/dist/templates/dispatch-center/tools/incident_triage.ts +78 -0
- package/dist/templates/dispatch-center/tools/incident_update_status.ts +68 -0
- package/dist/templates/dispatch-center/tools/ops_dashboard.ts +52 -0
- package/dist/templates/dispatch-center/tools/ops_protocols.ts +27 -0
- package/dist/templates/dispatch-center/tools/ops_run_scenario.ts +149 -0
- package/dist/templates/dispatch-center/tools/resources_dispatch.ts +97 -0
- package/dist/templates/dispatch-center/tools/resources_get_available.ts +36 -0
- package/dist/templates/dispatch-center/tools/resources_update_status.ts +62 -0
- package/dist/templates/embedded-assets/agent.ts +55 -0
- package/dist/templates/embedded-assets/knowledge.json +20 -0
- package/dist/templates/health-assistant/agent.ts +174 -0
- package/dist/templates/health-assistant/system-prompt.md +17 -0
- package/dist/templates/infocom-adventure/agent.ts +119 -0
- package/dist/templates/infocom-adventure/client.tsx +279 -0
- package/dist/templates/infocom-adventure/shared.ts +38 -0
- package/dist/templates/infocom-adventure/system-prompt.md +43 -0
- package/dist/templates/math-buddy/agent.ts +16 -0
- package/dist/templates/math-buddy/system-prompt.md +12 -0
- package/dist/templates/night-owl/agent.ts +76 -0
- package/dist/templates/night-owl/client.tsx +130 -0
- package/dist/templates/night-owl/shared.ts +5 -0
- package/dist/templates/personal-finance/agent.ts +11 -0
- package/dist/templates/personal-finance/system-prompt.md +17 -0
- package/dist/templates/pipeline-simple/agent.test.ts +32 -0
- package/dist/templates/pipeline-simple/agent.ts +13 -0
- package/dist/templates/pizza-ordering/agent.test.ts +235 -0
- package/dist/templates/pizza-ordering/agent.ts +174 -0
- package/dist/templates/pizza-ordering/client.tsx +120 -0
- package/dist/templates/pizza-ordering/shared.ts +142 -0
- package/dist/templates/pizza-ordering/system-prompt.md +17 -0
- package/dist/templates/simple/agent.ts +5 -0
- package/dist/templates/solo-rpg/agent.test.ts +477 -0
- package/dist/templates/solo-rpg/agent.ts +37 -0
- package/dist/templates/solo-rpg/client.tsx +809 -0
- package/dist/templates/solo-rpg/shared.ts +747 -0
- package/dist/templates/solo-rpg/system-prompt.md +115 -0
- package/dist/templates/solo-rpg/tools/action_roll.ts +98 -0
- package/dist/templates/solo-rpg/tools/burn_momentum.ts +69 -0
- package/dist/templates/solo-rpg/tools/check_state.ts +11 -0
- package/dist/templates/solo-rpg/tools/load_game.ts +25 -0
- package/dist/templates/solo-rpg/tools/oracle.ts +248 -0
- package/dist/templates/solo-rpg/tools/save_game.ts +20 -0
- package/dist/templates/solo-rpg/tools/setup_character.ts +208 -0
- package/dist/templates/solo-rpg/tools/update_state.ts +170 -0
- package/dist/templates/web-researcher/agent.ts +11 -0
- package/dist/{test-CgWhus_Z.mjs → test-3Gq4pqH_.mjs} +5 -7
- package/dist/test.d.ts +39 -0
- package/dist/tsdown.config.d.ts +2 -0
- package/dist/typecheck.d.ts +26 -0
- package/dist/typecheck.mjs +6 -10
- package/dist/worker-bundler.d.ts +29 -0
- package/package.json +9 -6
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Structured output support for CLI commands.
|
|
3
|
+
*
|
|
4
|
+
* In JSON mode (non-TTY or --json), commands emit exactly one JSON line to
|
|
5
|
+
* stdout. In human mode (TTY, default), commands use @clack/prompts as before.
|
|
6
|
+
*/
|
|
7
|
+
export type OutputMode = "json" | "human";
|
|
8
|
+
export type CommandResult<T> = {
|
|
9
|
+
ok: true;
|
|
10
|
+
data: T;
|
|
11
|
+
} | {
|
|
12
|
+
ok: false;
|
|
13
|
+
error: string;
|
|
14
|
+
code: string;
|
|
15
|
+
hint?: string;
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Determine output mode from CLI flags and TTY state.
|
|
19
|
+
*
|
|
20
|
+
* Priority: --json flag > --no-json flag > TTY auto-detection.
|
|
21
|
+
*/
|
|
22
|
+
export declare function getOutputMode(args: {
|
|
23
|
+
json?: boolean | undefined;
|
|
24
|
+
}, isTTY?: boolean): OutputMode;
|
|
25
|
+
/**
|
|
26
|
+
* Write a line to stdout, resolving only once it has been flushed.
|
|
27
|
+
*
|
|
28
|
+
* Resolves (never rejects) even when the write fails: the common failure is
|
|
29
|
+
* EPIPE — the consumer closed the pipe (`aai … --json | head -1`) — and there
|
|
30
|
+
* is nothing useful to do about a broken stdout except carry on and exit.
|
|
31
|
+
* Stream-level `'error'` events are handled by {@link installStdoutGuard}.
|
|
32
|
+
*/
|
|
33
|
+
export declare function writeLine(line: string): Promise<void>;
|
|
34
|
+
/**
|
|
35
|
+
* Install an `'error'` listener on stdout so a broken pipe doesn't crash the
|
|
36
|
+
* CLI with an unhandled `'error'` event. EPIPE (consumer went away, e.g.
|
|
37
|
+
* `aai … --json | head -1`) exits quietly; anything else is reported on
|
|
38
|
+
* stderr and exits non-zero.
|
|
39
|
+
*/
|
|
40
|
+
export declare function installStdoutGuard(stream?: NodeJS.WriteStream): void;
|
|
41
|
+
/** Create an ok result. */
|
|
42
|
+
export declare function ok<T>(data: T): CommandResult<T>;
|
|
43
|
+
/** Create an error result. */
|
|
44
|
+
export declare function fail<T>(code: string, error: string, hint?: string): CommandResult<T>;
|
|
45
|
+
/** Typed CLI error that carries a structured error code and optional hint. */
|
|
46
|
+
export declare class CliError extends Error {
|
|
47
|
+
readonly code: string;
|
|
48
|
+
readonly hint?: string | undefined;
|
|
49
|
+
constructor(code: string, message: string, hint?: string, options?: ErrorOptions);
|
|
50
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import { r as errorCode } from "./_utils-Ch0J4s6a.mjs";
|
|
2
3
|
import path from "node:path";
|
|
3
4
|
import { parseEnv } from "node:util";
|
|
4
5
|
import fs from "node:fs/promises";
|
|
@@ -26,7 +27,7 @@ async function resolveServerEnv(cwd, baseEnv) {
|
|
|
26
27
|
try {
|
|
27
28
|
content = await fs.readFile(path.join(cwd, ".env"), "utf-8");
|
|
28
29
|
} catch (err) {
|
|
29
|
-
if (err
|
|
30
|
+
if (errorCode(err) !== "ENOENT") throw err;
|
|
30
31
|
}
|
|
31
32
|
if (content !== null) fileEntries = parseEnv(content);
|
|
32
33
|
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Build the `ctx.env` record that agent tools will see at runtime.
|
|
3
|
+
*
|
|
4
|
+
* Only variables explicitly declared in `.env` are included — matching
|
|
5
|
+
* the platform sandbox behavior where `ctx.env`
|
|
6
|
+
* contains only secrets set via `aai secret put`. This prevents agents
|
|
7
|
+
* from accidentally depending on shell-level vars (PATH, HOME, etc.) that
|
|
8
|
+
* won't exist in production.
|
|
9
|
+
*
|
|
10
|
+
* Values are resolved by merging the `.env` file with the current
|
|
11
|
+
* environment — existing shell exports take precedence over `.env`
|
|
12
|
+
* defaults, without mutating `process.env`.
|
|
13
|
+
*
|
|
14
|
+
* @param cwd - Project directory containing `.env` (optional).
|
|
15
|
+
* @param baseEnv - Override the environment to read values from (tests only).
|
|
16
|
+
*/
|
|
17
|
+
export declare function resolveServerEnv(cwd?: string, baseEnv?: Record<string, string | undefined>): Promise<Record<string, string>>;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { n as getServerInfo } from "./_agent-D8zBb3M5.mjs";
|
|
3
|
+
import { n as apiRequest, t as HINT_NOT_DEPLOYED } from "./_api-client-MenP4-O7.mjs";
|
|
4
|
+
//#region _slug-api.ts
|
|
5
|
+
/**
|
|
6
|
+
* Authenticated request against a deployed agent's slug-scoped resource
|
|
7
|
+
* (`${serverUrl}/${slug}${resourcePath}`) — the one shape every per-agent
|
|
8
|
+
* command (secret, storage) shares, including the standard "not deployed"
|
|
9
|
+
* 404 hint.
|
|
10
|
+
*
|
|
11
|
+
* Its own module (rather than living beside `getServerInfo` in `_agent.ts`)
|
|
12
|
+
* so tests can mock `_agent.ts`/`_api-client.ts` while this composition
|
|
13
|
+
* stays real — an intra-module call would bypass those mocks.
|
|
14
|
+
*/
|
|
15
|
+
async function slugRequest(cwd, resourcePath, init, server) {
|
|
16
|
+
const { serverUrl, slug, apiKey } = await getServerInfo(cwd, server);
|
|
17
|
+
return {
|
|
18
|
+
data: await apiRequest(`${serverUrl}/${slug}${resourcePath}`, {
|
|
19
|
+
...init,
|
|
20
|
+
apiKey,
|
|
21
|
+
hints: { 404: HINT_NOT_DEPLOYED }
|
|
22
|
+
}),
|
|
23
|
+
slug
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
//#endregion
|
|
27
|
+
export { slugRequest as t };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { type ApiRequestOptions } from "./_api-client.ts";
|
|
2
|
+
/**
|
|
3
|
+
* Authenticated request against a deployed agent's slug-scoped resource
|
|
4
|
+
* (`${serverUrl}/${slug}${resourcePath}`) — the one shape every per-agent
|
|
5
|
+
* command (secret, storage) shares, including the standard "not deployed"
|
|
6
|
+
* 404 hint.
|
|
7
|
+
*
|
|
8
|
+
* Its own module (rather than living beside `getServerInfo` in `_agent.ts`)
|
|
9
|
+
* so tests can mock `_agent.ts`/`_api-client.ts` while this composition
|
|
10
|
+
* stays real — an intra-module call would bypass those mocks.
|
|
11
|
+
*/
|
|
12
|
+
export declare function slugRequest<T = unknown>(cwd: string, resourcePath: string, init: Pick<ApiRequestOptions, "method" | "body" | "action">, server?: string): Promise<{
|
|
13
|
+
data: T;
|
|
14
|
+
slug: string;
|
|
15
|
+
}>;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export declare const REPO_URL = "https://github.com/alexkroman/agent";
|
|
2
|
+
/**
|
|
3
|
+
* Templates as shipped inside the published tarball, copied into `dist/` by
|
|
4
|
+
* `bundle-templates.mjs` at build time — so this resolves to `dist/` for a
|
|
5
|
+
* published CLI and to the (template-less) package root when running source
|
|
6
|
+
* in the monorepo, where the branch above wins.
|
|
7
|
+
*
|
|
8
|
+
* They used to be fetched at `init` time with giget from
|
|
9
|
+
* `github:alexkroman/agent/packages/aai-templates#main`. That required a
|
|
10
|
+
* network for every `init`, and pinned templates to `main` regardless of the
|
|
11
|
+
* CLI version the user had installed, so a template written against a newer
|
|
12
|
+
* SDK could land in a project resolving an older one. Bundling pins the two
|
|
13
|
+
* together by construction. It also puts the templates inside the studio's
|
|
14
|
+
* guest sandbox, which has the CLI in its baked toolchain but no way to fetch
|
|
15
|
+
* anything from GitHub.
|
|
16
|
+
*/
|
|
17
|
+
export declare function bundledTemplatesDir(): string;
|
|
18
|
+
/**
|
|
19
|
+
* Copy a template into targetDir, merging scaffold files underneath.
|
|
20
|
+
*/
|
|
21
|
+
export declare function downloadAndMergeTemplate(template: string, targetDir: string): Promise<void>;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { n as log, o as CliError } from "./_ui-
|
|
2
|
+
import { n as log, o as CliError } from "./_ui-8kOEB-JH.mjs";
|
|
3
3
|
import { typecheckProject } from "./typecheck.mjs";
|
|
4
4
|
//#region _typecheck-gate.ts
|
|
5
5
|
/**
|
|
@@ -14,4 +14,4 @@ async function assertTypechecks(cwd) {
|
|
|
14
14
|
if (!result.ok) throw new CliError("typecheck_failed", result.output, "Fix the type errors, or pass --skipTypecheck to build anyway");
|
|
15
15
|
}
|
|
16
16
|
//#endregion
|
|
17
|
-
export { assertTypechecks };
|
|
17
|
+
export { assertTypechecks as t };
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The build/deploy typecheck gate: run the project's own `tsc --noEmit`
|
|
3
|
+
* (see `typecheck.ts`) and turn a failure into a structured CliError. The
|
|
4
|
+
* bundlers strip types unchecked, so without this a type-broken agent
|
|
5
|
+
* ships and misbehaves at runtime instead of failing here.
|
|
6
|
+
*/
|
|
7
|
+
export declare function assertTypechecks(cwd: string): Promise<void>;
|
|
@@ -83,10 +83,13 @@ const log = new Proxy(p.log, { get(target, prop, receiver) {
|
|
|
83
83
|
function silenceOutput() {
|
|
84
84
|
silenced = true;
|
|
85
85
|
}
|
|
86
|
-
/**
|
|
87
|
-
|
|
86
|
+
/**
|
|
87
|
+
* Unwrap a clack prompt result, exiting cleanly if the user cancelled.
|
|
88
|
+
* `message` lets the caller name what was cancelled (e.g. "Setup cancelled").
|
|
89
|
+
*/
|
|
90
|
+
function unwrapCancel(result, message = "Cancelled") {
|
|
88
91
|
if (p.isCancel(result)) {
|
|
89
|
-
p.cancel(
|
|
92
|
+
p.cancel(message);
|
|
90
93
|
process.exit(0);
|
|
91
94
|
}
|
|
92
95
|
return result;
|
package/dist/_ui.d.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import * as p from "@clack/prompts";
|
|
2
|
+
type Log = typeof p.log;
|
|
3
|
+
/** Log instance that delegates to clack (human mode) or no-ops (JSON mode). */
|
|
4
|
+
export declare const log: Log;
|
|
5
|
+
/** Replace all log methods with no-ops. Call once in JSON mode. */
|
|
6
|
+
export declare function silenceOutput(): void;
|
|
7
|
+
/**
|
|
8
|
+
* Unwrap a clack prompt result, exiting cleanly if the user cancelled.
|
|
9
|
+
* `message` lets the caller name what was cancelled (e.g. "Setup cancelled").
|
|
10
|
+
*/
|
|
11
|
+
export declare function unwrapCancel<T>(result: T | symbol, message?: string): T;
|
|
12
|
+
/** Format a URL for display. */
|
|
13
|
+
export declare function fmtUrl(url: string): string;
|
|
14
|
+
/**
|
|
15
|
+
* Parse and validate a port string. Returns the numeric port or throws.
|
|
16
|
+
*
|
|
17
|
+
* Deliberately zod-free: this module loads on every CLI invocation
|
|
18
|
+
* (including `aai --help`), and keeping zod off that path is the same
|
|
19
|
+
* startup-cost invariant `_utils.ts` documents for its error helpers.
|
|
20
|
+
*/
|
|
21
|
+
export declare function parsePort(raw: string): number;
|
|
22
|
+
export {};
|
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import { readFileSync } from "node:fs";
|
|
2
3
|
import path from "node:path";
|
|
3
4
|
import fs from "node:fs/promises";
|
|
4
5
|
import { errorDetail, errorMessage, errorMessage as errorMessage$1 } from "@alexkroman1/aai/utils";
|
|
5
6
|
//#region _utils.ts
|
|
7
|
+
/**
|
|
8
|
+
* The file that marks a directory as an agent project — the single source
|
|
9
|
+
* for the entry filename every command checks or scaffolds.
|
|
10
|
+
*/
|
|
11
|
+
const AGENT_ENTRY = "agent.ts";
|
|
6
12
|
/** Resolve the working directory from INIT_CWD or process.cwd(). */
|
|
7
13
|
function resolveCwd() {
|
|
8
14
|
return process.env.INIT_CWD || process.cwd();
|
|
@@ -19,6 +25,16 @@ function isEexist(err) {
|
|
|
19
25
|
function validateAgentExport(mod) {
|
|
20
26
|
if (!mod?.name || typeof mod.name !== "string") throw new Error("agent.ts must export default agent({ name: ... })");
|
|
21
27
|
}
|
|
28
|
+
/**
|
|
29
|
+
* Absolute path of `binName`'s script declared by the package.json at
|
|
30
|
+
* `pkgJsonPath`, or undefined when the package declares no such bin.
|
|
31
|
+
* Handles both `"bin": "script.js"` and `"bin": { name: "script.js" }`.
|
|
32
|
+
*/
|
|
33
|
+
function binFromPackageJson(pkgJsonPath, binName) {
|
|
34
|
+
const pkg = JSON.parse(readFileSync(pkgJsonPath, "utf-8"));
|
|
35
|
+
const bin = typeof pkg.bin === "string" ? pkg.bin : pkg.bin?.[binName];
|
|
36
|
+
return bin ? path.join(path.dirname(pkgJsonPath), bin) : void 0;
|
|
37
|
+
}
|
|
22
38
|
async function fileExists(p) {
|
|
23
39
|
try {
|
|
24
40
|
await fs.access(p);
|
|
@@ -79,4 +95,4 @@ async function writeJson(filePath, data, opts = {}) {
|
|
|
79
95
|
}
|
|
80
96
|
}
|
|
81
97
|
//#endregion
|
|
82
|
-
export {
|
|
98
|
+
export { errorMessage$1 as a, readJson as c, writeJson as d, errorDetail as i, resolveCwd as l, binFromPackageJson as n, fileExists as o, errorCode as r, isEexist as s, AGENT_ENTRY as t, validateAgentExport as u };
|
package/dist/_utils.d.ts
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
export { errorDetail, errorMessage } from "@alexkroman1/aai/utils";
|
|
2
|
+
/**
|
|
3
|
+
* The file that marks a directory as an agent project — the single source
|
|
4
|
+
* for the entry filename every command checks or scaffolds.
|
|
5
|
+
*/
|
|
6
|
+
export declare const AGENT_ENTRY = "agent.ts";
|
|
7
|
+
/** Resolve the working directory from INIT_CWD or process.cwd(). */
|
|
8
|
+
export declare function resolveCwd(): string;
|
|
9
|
+
/** The `code` of a Node errno-style error (`"ENOENT"`, `"EPIPE"`, …), or undefined. */
|
|
10
|
+
export declare function errorCode(err: unknown): string | undefined;
|
|
11
|
+
/** True when `err` is a filesystem EEXIST error (target already exists). */
|
|
12
|
+
export declare function isEexist(err: unknown): boolean;
|
|
13
|
+
/** Validate that a module's default export is a valid agent definition. Throws if invalid. */
|
|
14
|
+
export declare function validateAgentExport(mod: any): void;
|
|
15
|
+
/**
|
|
16
|
+
* Absolute path of `binName`'s script declared by the package.json at
|
|
17
|
+
* `pkgJsonPath`, or undefined when the package declares no such bin.
|
|
18
|
+
* Handles both `"bin": "script.js"` and `"bin": { name: "script.js" }`.
|
|
19
|
+
*/
|
|
20
|
+
export declare function binFromPackageJson(pkgJsonPath: string, binName: string): string | undefined;
|
|
21
|
+
export declare function fileExists(p: string): Promise<boolean>;
|
|
22
|
+
/**
|
|
23
|
+
* Read and parse a JSON file. Returns null only when the file does not exist
|
|
24
|
+
* (ENOENT — the "optional file" case). A file that exists but cannot be read
|
|
25
|
+
* (EACCES, …) or parsed throws instead: treating a corrupted file as absent
|
|
26
|
+
* hides real problems — e.g. a corrupted `.aai/project.json` would silently
|
|
27
|
+
* deploy under a NEW slug, orphaning the live deployment.
|
|
28
|
+
*/
|
|
29
|
+
export declare function readJson(filePath: string): Promise<unknown>;
|
|
30
|
+
/**
|
|
31
|
+
* Write `data` as pretty-printed JSON (+ trailing newline), creating parent dirs.
|
|
32
|
+
*
|
|
33
|
+
* Writes to a temp file in the same directory, then renames it into place.
|
|
34
|
+
* A plain `writeFile` can be observed (or left, on crash) half-written; a
|
|
35
|
+
* torn config.json fails `JSON.parse`, reads back as `{}`, and the next
|
|
36
|
+
* read-modify-write silently wipes fields like `approvedServers`. Rename on
|
|
37
|
+
* the same filesystem is atomic, so readers only ever see a complete file.
|
|
38
|
+
* Two concurrent CLI processes can still lose each other's *updates*
|
|
39
|
+
* (last rename wins) — acceptable for these small user-config files.
|
|
40
|
+
*
|
|
41
|
+
* `mode` restricts the file's permissions (the rename carries the temp
|
|
42
|
+
* file's mode to the destination, so an existing world-readable file is
|
|
43
|
+
* tightened on the next write). The parent directory is created 0o700 in
|
|
44
|
+
* that case so a fresh config dir never goes through a readable window.
|
|
45
|
+
*/
|
|
46
|
+
export declare function writeJson(filePath: string, data: unknown, opts?: {
|
|
47
|
+
mode?: number;
|
|
48
|
+
}): Promise<void>;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `env` is injectable for tests ONLY, so specs can exercise the
|
|
3
|
+
* snapshot/refcount logic on a plain object instead of mutating (and
|
|
4
|
+
* repeatedly deleting) the real `process.env.NODE_ENV` mid-suite.
|
|
5
|
+
*/
|
|
6
|
+
export declare function withPreservedNodeEnv<T>(fn: () => Promise<T>, env?: {
|
|
7
|
+
NODE_ENV?: string;
|
|
8
|
+
}): Promise<T>;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { n as log, o as CliError, u as ok } from "./_ui-8kOEB-JH.mjs";
|
|
3
|
+
import { r as evalWorkerBundle, t as buildAgentBundle } from "./_bundler-DFS4xxqE.mjs";
|
|
4
|
+
import { t as assertTypechecks } from "./_typecheck-gate-9IHWDnl1.mjs";
|
|
5
|
+
import { classifyVitestError, runVitest } from "./test-3Gq4pqH_.mjs";
|
|
6
|
+
//#region build.ts
|
|
7
|
+
/**
|
|
8
|
+
* `aai build` — bundle the agent without deploying, behind the same gates
|
|
9
|
+
* deploy runs (tests, then typecheck), so the command previews the deploy
|
|
10
|
+
* artifact and its failures alike.
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* Map a {@link runVitest} failure to a CliError — distinguishing a real test
|
|
14
|
+
* failure (test_failed) from the runner not spawning (spawn_failed) instead
|
|
15
|
+
* of a generic command_failed.
|
|
16
|
+
*/
|
|
17
|
+
function testGateError(err) {
|
|
18
|
+
const { code, message } = classifyVitestError(err);
|
|
19
|
+
return new CliError(code, message, "Re-run with --skipTests to build without tests", { cause: err });
|
|
20
|
+
}
|
|
21
|
+
async function executeBuild(opts) {
|
|
22
|
+
const { cwd } = opts;
|
|
23
|
+
if (!opts.skipTests) try {
|
|
24
|
+
runVitest(cwd);
|
|
25
|
+
} catch (err) {
|
|
26
|
+
throw testGateError(err);
|
|
27
|
+
}
|
|
28
|
+
if (!opts.skipTypecheck) await assertTypechecks(cwd);
|
|
29
|
+
const bundle = await buildAgentBundle(cwd, { minify: true });
|
|
30
|
+
const agentDef = await evalWorkerBundle(bundle.worker);
|
|
31
|
+
log.success("Build complete");
|
|
32
|
+
return ok({
|
|
33
|
+
name: agentDef.name,
|
|
34
|
+
workerBytes: bundle.worker.length
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
//#endregion
|
|
38
|
+
export { executeBuild };
|
package/dist/build.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `aai build` — bundle the agent without deploying, behind the same gates
|
|
3
|
+
* deploy runs (tests, then typecheck), so the command previews the deploy
|
|
4
|
+
* artifact and its failures alike.
|
|
5
|
+
*/
|
|
6
|
+
import { type CommandResult } from "./_output.ts";
|
|
7
|
+
type BuildData = {
|
|
8
|
+
name: string;
|
|
9
|
+
workerBytes: number;
|
|
10
|
+
};
|
|
11
|
+
export declare function executeBuild(opts: {
|
|
12
|
+
cwd: string;
|
|
13
|
+
skipTests?: boolean | undefined;
|
|
14
|
+
skipTypecheck?: boolean | undefined;
|
|
15
|
+
}): Promise<CommandResult<BuildData>>;
|
|
16
|
+
export {};
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const mainCommand: import("citty").CommandDef<import("citty").ArgsDef>;
|
package/dist/cli.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { c as getOutputMode, d as writeLine, i as silenceOutput, l as installStdoutGuard, n as log, o as CliError, s as fail } from "./_ui-
|
|
3
|
-
import {
|
|
2
|
+
import { c as getOutputMode, d as writeLine, i as silenceOutput, l as installStdoutGuard, n as log, o as CliError, s as fail } from "./_ui-8kOEB-JH.mjs";
|
|
3
|
+
import { a as errorMessage, l as resolveCwd, o as fileExists, t as AGENT_ENTRY } from "./_utils-Ch0J4s6a.mjs";
|
|
4
4
|
import { existsSync, readFileSync } from "node:fs";
|
|
5
5
|
import path from "node:path";
|
|
6
6
|
import { fileURLToPath } from "node:url";
|
|
@@ -8,12 +8,6 @@ import { defineCommand, runMain } from "citty";
|
|
|
8
8
|
//#region cli.ts
|
|
9
9
|
/** Shared arg definitions for citty commands. */
|
|
10
10
|
const sharedArgs = {
|
|
11
|
-
port: {
|
|
12
|
-
type: "string",
|
|
13
|
-
alias: "p",
|
|
14
|
-
description: "Port to listen on",
|
|
15
|
-
default: "3000"
|
|
16
|
-
},
|
|
17
11
|
server: {
|
|
18
12
|
type: "string",
|
|
19
13
|
alias: "s",
|
|
@@ -48,7 +42,7 @@ const VERSION = readCliVersion(cliDir);
|
|
|
48
42
|
async function setup(opts) {
|
|
49
43
|
const cwd = resolveCwd();
|
|
50
44
|
if (opts?.agent) {
|
|
51
|
-
if (!await fileExists(path.join(cwd, "agent.ts"))) throw new Error(
|
|
45
|
+
if (!await fileExists(path.join(cwd, "agent.ts"))) throw new Error(`No ${AGENT_ENTRY} found in the current directory. Run \`aai init\` first.`);
|
|
52
46
|
}
|
|
53
47
|
return cwd;
|
|
54
48
|
}
|
|
@@ -56,7 +50,6 @@ async function setup(opts) {
|
|
|
56
50
|
* Run a command body with standard output-mode resolution, error handling,
|
|
57
51
|
* and result emission.
|
|
58
52
|
*
|
|
59
|
-
* - `setYes`: json mode sets `args.yes = true` (only meaningful for commands with a `yes` arg).
|
|
60
53
|
* - API key acquisition is owned by `resolveDeployTarget`/`getServerInfo`
|
|
61
54
|
* inside the commands that talk to the platform — after the server-trust
|
|
62
55
|
* check, so an untrusted `serverUrl` is refused without prompting for a
|
|
@@ -66,12 +59,9 @@ async function setup(opts) {
|
|
|
66
59
|
* human mode logs the message, JSON mode writes exactly one result line,
|
|
67
60
|
* and both exit 1.
|
|
68
61
|
*/
|
|
69
|
-
async function runCommand(args, fn
|
|
62
|
+
async function runCommand(args, fn) {
|
|
70
63
|
const mode = getOutputMode(args);
|
|
71
|
-
if (mode === "json")
|
|
72
|
-
silenceOutput();
|
|
73
|
-
if (opts.setYes) args.yes = true;
|
|
74
|
-
}
|
|
64
|
+
if (mode === "json") silenceOutput();
|
|
75
65
|
let result;
|
|
76
66
|
try {
|
|
77
67
|
result = await fn(mode);
|
|
@@ -115,16 +105,16 @@ const init = defineCommand({
|
|
|
115
105
|
},
|
|
116
106
|
async run({ args }) {
|
|
117
107
|
await runCommand(args, async (mode) => {
|
|
118
|
-
const { executeInit } = await import("./init-
|
|
108
|
+
const { executeInit } = await import("./init-BjeK8crW.mjs");
|
|
119
109
|
return executeInit({
|
|
120
110
|
dir: args.dir,
|
|
121
111
|
force: args.force,
|
|
122
112
|
template: args.template,
|
|
123
|
-
yes: args.yes,
|
|
113
|
+
yes: mode === "json" ? true : args.yes,
|
|
124
114
|
skipDeploy: args.skipDeploy,
|
|
125
115
|
server: args.server
|
|
126
116
|
}, mode === "json" ? { silent: true } : void 0);
|
|
127
|
-
}
|
|
117
|
+
});
|
|
128
118
|
}
|
|
129
119
|
});
|
|
130
120
|
const dev = defineCommand({
|
|
@@ -133,13 +123,18 @@ const dev = defineCommand({
|
|
|
133
123
|
description: "Start a local development server"
|
|
134
124
|
},
|
|
135
125
|
args: {
|
|
136
|
-
port:
|
|
126
|
+
port: {
|
|
127
|
+
type: "string",
|
|
128
|
+
alias: "p",
|
|
129
|
+
description: "Port to listen on",
|
|
130
|
+
default: "3000"
|
|
131
|
+
},
|
|
137
132
|
json: sharedArgs.json
|
|
138
133
|
},
|
|
139
134
|
async run({ args }) {
|
|
140
135
|
await runCommand(args, async () => {
|
|
141
136
|
const cwd = await setup({ agent: true });
|
|
142
|
-
const { executeDev } = await import("./dev-
|
|
137
|
+
const { executeDev } = await import("./dev-g7sGt8qX.mjs");
|
|
143
138
|
return executeDev({
|
|
144
139
|
cwd,
|
|
145
140
|
port: args.port
|
|
@@ -156,7 +151,7 @@ const test = defineCommand({
|
|
|
156
151
|
async run({ args }) {
|
|
157
152
|
await runCommand(args, async () => {
|
|
158
153
|
const cwd = await setup();
|
|
159
|
-
const { executeTest } = await import("./test-
|
|
154
|
+
const { executeTest } = await import("./test-3Gq4pqH_.mjs");
|
|
160
155
|
return executeTest(cwd);
|
|
161
156
|
});
|
|
162
157
|
}
|
|
@@ -180,24 +175,12 @@ const build = defineCommand({
|
|
|
180
175
|
async run({ args }) {
|
|
181
176
|
await runCommand(args, async () => {
|
|
182
177
|
const cwd = await setup({ agent: true });
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
try {
|
|
190
|
-
runVitest(cwd);
|
|
191
|
-
} catch (err) {
|
|
192
|
-
throw toCliError(err);
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
if (!args.skipTypecheck) {
|
|
196
|
-
const { assertTypechecks } = await import("./_typecheck-gate-B1GcKZX-.mjs");
|
|
197
|
-
await assertTypechecks(cwd);
|
|
198
|
-
}
|
|
199
|
-
const { executeBuild } = await import("./_bundler-DdmuZzeR.mjs");
|
|
200
|
-
return executeBuild(cwd);
|
|
178
|
+
const { executeBuild } = await import("./build-Xq1xxoSg.mjs");
|
|
179
|
+
return executeBuild({
|
|
180
|
+
cwd,
|
|
181
|
+
skipTests: args.skipTests,
|
|
182
|
+
skipTypecheck: args.skipTypecheck
|
|
183
|
+
});
|
|
201
184
|
});
|
|
202
185
|
}
|
|
203
186
|
});
|
|
@@ -221,12 +204,12 @@ const deploy = defineCommand({
|
|
|
221
204
|
async run({ args }) {
|
|
222
205
|
await runCommand(args, async () => {
|
|
223
206
|
const cwd = await setup({ agent: true });
|
|
224
|
-
const { executeDeploy } = await import("./deploy-
|
|
207
|
+
const { executeDeploy } = await import("./deploy-Ci0X1gp2.mjs");
|
|
225
208
|
return executeDeploy({
|
|
226
209
|
cwd,
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
210
|
+
server: args.server,
|
|
211
|
+
allowMissingSecrets: args.allowMissingSecrets,
|
|
212
|
+
skipTypecheck: args.skipTypecheck
|
|
230
213
|
});
|
|
231
214
|
});
|
|
232
215
|
}
|
|
@@ -243,10 +226,10 @@ const del = defineCommand({
|
|
|
243
226
|
async run({ args }) {
|
|
244
227
|
await runCommand(args, async () => {
|
|
245
228
|
const cwd = await setup();
|
|
246
|
-
const { executeDelete } = await import("./delete-
|
|
229
|
+
const { executeDelete } = await import("./delete-kSXFLxek.mjs");
|
|
247
230
|
return executeDelete({
|
|
248
231
|
cwd,
|
|
249
|
-
|
|
232
|
+
server: args.server
|
|
250
233
|
});
|
|
251
234
|
});
|
|
252
235
|
}
|
|
@@ -274,9 +257,9 @@ const secret = defineCommand({
|
|
|
274
257
|
async run({ args }) {
|
|
275
258
|
await runCommand(args, async (mode) => {
|
|
276
259
|
const cwd = await setup();
|
|
277
|
-
const { executeSecretPut, readStdin } = await import("./secret-
|
|
260
|
+
const { executeSecretPut, NO_INPUT, readStdin } = await import("./secret-DOva9OGk.mjs");
|
|
278
261
|
const value = mode === "json" ? await readStdin() : void 0;
|
|
279
|
-
if (mode === "json" && !value) throw new CliError(
|
|
262
|
+
if (mode === "json" && !value) throw new CliError(...NO_INPUT);
|
|
280
263
|
return executeSecretPut(cwd, args.name, value, args.server);
|
|
281
264
|
});
|
|
282
265
|
}
|
|
@@ -298,7 +281,7 @@ const secret = defineCommand({
|
|
|
298
281
|
async run({ args }) {
|
|
299
282
|
await runCommand(args, async () => {
|
|
300
283
|
const cwd = await setup();
|
|
301
|
-
const { executeSecretDelete } = await import("./secret-
|
|
284
|
+
const { executeSecretDelete } = await import("./secret-DOva9OGk.mjs");
|
|
302
285
|
return executeSecretDelete(cwd, args.name, args.server);
|
|
303
286
|
});
|
|
304
287
|
}
|
|
@@ -315,7 +298,7 @@ const secret = defineCommand({
|
|
|
315
298
|
async run({ args }) {
|
|
316
299
|
await runCommand(args, async () => {
|
|
317
300
|
const cwd = await setup();
|
|
318
|
-
const { executeSecretList } = await import("./secret-
|
|
301
|
+
const { executeSecretList } = await import("./secret-DOva9OGk.mjs");
|
|
319
302
|
return executeSecretList(cwd, args.server);
|
|
320
303
|
});
|
|
321
304
|
}
|
|
@@ -350,7 +333,7 @@ const storage = defineCommand({
|
|
|
350
333
|
},
|
|
351
334
|
async run({ args }) {
|
|
352
335
|
await runCommand(args, async () => {
|
|
353
|
-
const { executeStorageStatus } = await import("./storage-
|
|
336
|
+
const { executeStorageStatus } = await import("./storage-vM6HjDZZ.mjs");
|
|
354
337
|
return executeStorageStatus(resolveStorageCwd(args.dir), args.server);
|
|
355
338
|
});
|
|
356
339
|
}
|
|
@@ -367,7 +350,7 @@ const storage = defineCommand({
|
|
|
367
350
|
},
|
|
368
351
|
async run({ args }) {
|
|
369
352
|
await runCommand(args, async () => {
|
|
370
|
-
const { executeStorageEnable } = await import("./storage-
|
|
353
|
+
const { executeStorageEnable } = await import("./storage-vM6HjDZZ.mjs");
|
|
371
354
|
return executeStorageEnable(resolveStorageCwd(args.dir), args.server);
|
|
372
355
|
});
|
|
373
356
|
}
|
|
@@ -389,7 +372,7 @@ const storage = defineCommand({
|
|
|
389
372
|
},
|
|
390
373
|
async run({ args }) {
|
|
391
374
|
await runCommand(args, async () => {
|
|
392
|
-
const { executeStorageDisable } = await import("./storage-
|
|
375
|
+
const { executeStorageDisable } = await import("./storage-vM6HjDZZ.mjs");
|
|
393
376
|
return executeStorageDisable(resolveStorageCwd(args.dir), {
|
|
394
377
|
server: args.server,
|
|
395
378
|
force: args.force
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
2
|
+
import { a as errorMessage$1, o as fileExists } from "./_utils-Ch0J4s6a.mjs";
|
|
3
3
|
import { t as withPreservedNodeEnv } from "./_vite-env-Dg_QlVv0.mjs";
|
|
4
4
|
import { existsSync, unlinkSync, writeFileSync } from "node:fs";
|
|
5
5
|
import path from "node:path";
|
|
6
6
|
import fs from "node:fs/promises";
|
|
7
|
-
import { isTextAssetPath } from "@alexkroman1/aai";
|
|
7
|
+
import { isTextAssetPath } from "@alexkroman1/aai/utils";
|
|
8
8
|
import { build } from "vite";
|
|
9
9
|
//#region _default-html.ts
|
|
10
10
|
/**
|
|
@@ -65,7 +65,7 @@ function writeTempHtml(root) {
|
|
|
65
65
|
writeFileSync(htmlPath, DEFAULT_HTML);
|
|
66
66
|
} catch (err) {
|
|
67
67
|
cleanup();
|
|
68
|
-
throw new Error(`Failed to write a temporary index.html at ${htmlPath} for the client build — is the project directory writable? (${errorMessage(err)})`, { cause: err });
|
|
68
|
+
throw new Error(`Failed to write a temporary index.html at ${htmlPath} for the client build — is the project directory writable? (${errorMessage$1(err)})`, { cause: err });
|
|
69
69
|
}
|
|
70
70
|
return cleanup;
|
|
71
71
|
}
|
|
@@ -88,8 +88,7 @@ const DEFAULT_OUT_DIR = ".aai/client";
|
|
|
88
88
|
*
|
|
89
89
|
* Deduping states the peer contract in terms the bundler enforces, and it is
|
|
90
90
|
* what a React app wants anyway: two copies of React in one bundle break
|
|
91
|
-
* hooks. Guarded by `client-bundler.test.ts
|
|
92
|
-
* hold in the image, `aai-server/dockerfile-packaging.test.ts`.
|
|
91
|
+
* hooks. Guarded by `client-bundler.test.ts`.
|
|
93
92
|
*/
|
|
94
93
|
const DEDUPED_PEERS = ["react", "react-dom"];
|
|
95
94
|
/**
|
|
@@ -131,7 +130,7 @@ async function readClientDir(clientDir) {
|
|
|
131
130
|
withFileTypes: true
|
|
132
131
|
});
|
|
133
132
|
} catch (err) {
|
|
134
|
-
throw new Error(`Client build produced no output at ${clientDir}: ${errorMessage(err)}`, { cause: err });
|
|
133
|
+
throw new Error(`Client build produced no output at ${clientDir}: ${errorMessage$1(err)}`, { cause: err });
|
|
135
134
|
}
|
|
136
135
|
await Promise.all(entries.filter((entry) => entry.isFile()).map(async (entry) => {
|
|
137
136
|
const abs = path.join(entry.parentPath, entry.name);
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { type PluginOption } from "vite";
|
|
2
|
+
export type BuildClientOptions = {
|
|
3
|
+
/**
|
|
4
|
+
* Plugins to inject instead of relying on the project's `vite.config.ts`
|
|
5
|
+
* (React + Tailwind for the studio, whose workspace has neither).
|
|
6
|
+
*/
|
|
7
|
+
plugins?: PluginOption[];
|
|
8
|
+
/**
|
|
9
|
+
* `false` ignores any `vite.config.ts` under `cwd`. The studio passes this:
|
|
10
|
+
* a Vite config is executable code, and workspace files are untrusted.
|
|
11
|
+
*/
|
|
12
|
+
configFile?: false;
|
|
13
|
+
/** Build output directory, relative to `cwd`. */
|
|
14
|
+
outDir?: string;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Build the client SPA with Vite if `client.tsx` exists.
|
|
18
|
+
* Returns a map of relative file paths to string contents for deploy,
|
|
19
|
+
* or `{}` when the project has no `client.tsx`.
|
|
20
|
+
*/
|
|
21
|
+
export declare function buildClient(cwd: string, opts?: BuildClientOptions): Promise<Record<string, string>>;
|
package/dist/client-bundler.mjs
CHANGED