@aixyz/cli 0.1.2 → 0.2.4
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 +11 -1
- package/bin.ts +15 -6
- package/build/AixyzConfigPlugin.ts +32 -2
- package/build/AixyzServerPlugin.ts +30 -4
- package/build/index.ts +81 -4
- package/package.json +5 -3
package/README.md
CHANGED
|
@@ -34,12 +34,22 @@ aixyz-cli dev --port 8080
|
|
|
34
34
|
|
|
35
35
|
### `aixyz-cli build`
|
|
36
36
|
|
|
37
|
-
Build the agent for
|
|
37
|
+
Build the agent for deployment.
|
|
38
|
+
|
|
39
|
+
**Default behavior:** Bundles into a single file for Bun Runtime at `./.aixyz/output/server.js`
|
|
38
40
|
|
|
39
41
|
```bash
|
|
40
42
|
aixyz-cli build
|
|
41
43
|
```
|
|
42
44
|
|
|
45
|
+
**With --vercel flag or VERCEL=1:** Build for Vercel deployment using the [Build Output API v3](https://vercel.com/docs/build-output-api/v3) at `.vercel/output/`
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
aixyz-cli build --vercel
|
|
49
|
+
# or automatically detected on Vercel
|
|
50
|
+
VERCEL=1 aixyz-cli build
|
|
51
|
+
```
|
|
52
|
+
|
|
43
53
|
## License
|
|
44
54
|
|
|
45
55
|
MIT
|
package/bin.ts
CHANGED
|
@@ -27,27 +27,36 @@ program
|
|
|
27
27
|
|
|
28
28
|
program
|
|
29
29
|
.command("build")
|
|
30
|
-
.description("Build the aixyz agent
|
|
30
|
+
.description("Build the aixyz agent")
|
|
31
|
+
.option("--output <type>", "Output format: 'standalone' or 'vercel'")
|
|
31
32
|
.addHelpText(
|
|
32
33
|
"after",
|
|
33
34
|
`
|
|
34
35
|
Details:
|
|
35
|
-
Bundles your aixyz agent
|
|
36
|
+
Bundles your aixyz agent for deployment.
|
|
37
|
+
|
|
38
|
+
Default behavior (auto-detected):
|
|
39
|
+
Bundles into a single executable file for Standalone at ./.aixyz/output/server.js
|
|
40
|
+
|
|
41
|
+
With --output vercel or VERCEL=1 env:
|
|
42
|
+
Generates Vercel Build Output API v3 structure at .vercel/output/
|
|
43
|
+
(Automatically detected when deploying to Vercel)
|
|
36
44
|
|
|
37
45
|
The build process:
|
|
38
46
|
1. Loads aixyz.config.ts from the current directory
|
|
39
47
|
2. Detects entrypoint (app/server.ts or auto-generates from app/agent.ts + app/tools/)
|
|
40
|
-
3.
|
|
48
|
+
3. Bundles the application
|
|
41
49
|
4. Copies static assets from public/ (if present)
|
|
42
50
|
|
|
43
|
-
Output is written to .vercel/output/ in the current directory.
|
|
44
|
-
|
|
45
51
|
Prerequisites:
|
|
46
52
|
- An aixyz.config.ts with a default export
|
|
47
53
|
- An entrypoint at app/server.ts, or app/agent.ts + app/tools/ for auto-generation
|
|
48
54
|
|
|
49
55
|
Examples:
|
|
50
|
-
$ aixyz build
|
|
56
|
+
$ aixyz build # Build standalone (default)
|
|
57
|
+
$ aixyz build --output standalone # Build standalone explicitly
|
|
58
|
+
$ aixyz build --output vercel # Build for Vercel deployment
|
|
59
|
+
$ VERCEL=1 aixyz build # Auto-detected Vercel build`,
|
|
51
60
|
)
|
|
52
61
|
.action(handleAction(build));
|
|
53
62
|
|
|
@@ -1,11 +1,38 @@
|
|
|
1
1
|
import { getAixyzConfig } from "@aixyz/config";
|
|
2
2
|
import type { BunPlugin } from "bun";
|
|
3
|
+
import boxen from "boxen";
|
|
4
|
+
import chalk from "chalk";
|
|
5
|
+
|
|
6
|
+
function label(text: string): string {
|
|
7
|
+
return chalk.dim(text.padEnd(14));
|
|
8
|
+
}
|
|
3
9
|
|
|
4
10
|
export function AixyzConfigPlugin(): BunPlugin {
|
|
5
11
|
const materialized = getAixyzConfig();
|
|
6
12
|
|
|
7
|
-
|
|
8
|
-
|
|
13
|
+
const maxLen = Math.max(materialized.url.length, materialized.x402.payTo.length);
|
|
14
|
+
const description =
|
|
15
|
+
materialized.description.length > maxLen
|
|
16
|
+
? materialized.description.slice(0, maxLen - 1) + "…"
|
|
17
|
+
: materialized.description;
|
|
18
|
+
|
|
19
|
+
const lines = [
|
|
20
|
+
`${label("Name")}${materialized.name}`,
|
|
21
|
+
`${label("Description")}${description}`,
|
|
22
|
+
`${label("URL")}${materialized.url}`,
|
|
23
|
+
`${label("Version")}${materialized.version}`,
|
|
24
|
+
`${label("x402 PayTo")}${materialized.x402.payTo}`,
|
|
25
|
+
`${label("x402 Network")}${materialized.x402.network}`,
|
|
26
|
+
];
|
|
27
|
+
console.log(
|
|
28
|
+
boxen(lines.join("\n"), {
|
|
29
|
+
padding: { left: 1, right: 1, top: 0, bottom: 0 },
|
|
30
|
+
borderStyle: "round",
|
|
31
|
+
borderColor: "green",
|
|
32
|
+
title: "aixyz.config.ts",
|
|
33
|
+
titleAlignment: "left",
|
|
34
|
+
}),
|
|
35
|
+
);
|
|
9
36
|
|
|
10
37
|
return {
|
|
11
38
|
name: "aixyz-config",
|
|
@@ -16,6 +43,9 @@ export function AixyzConfigPlugin(): BunPlugin {
|
|
|
16
43
|
export function getAixyzConfig() {
|
|
17
44
|
return config;
|
|
18
45
|
}
|
|
46
|
+
export function getAixyzConfigRuntime() {
|
|
47
|
+
return config;
|
|
48
|
+
}
|
|
19
49
|
`,
|
|
20
50
|
loader: "ts",
|
|
21
51
|
}));
|
|
@@ -2,7 +2,7 @@ import type { BunPlugin } from "bun";
|
|
|
2
2
|
import { existsSync, mkdirSync, readdirSync, writeFileSync } from "fs";
|
|
3
3
|
import { resolve, relative, basename, join } from "path";
|
|
4
4
|
|
|
5
|
-
export function AixyzServerPlugin(entrypoint: string): BunPlugin {
|
|
5
|
+
export function AixyzServerPlugin(entrypoint: string, mode: "vercel" | "standalone"): BunPlugin {
|
|
6
6
|
return {
|
|
7
7
|
name: "aixyz-entrypoint",
|
|
8
8
|
setup(build) {
|
|
@@ -10,9 +10,28 @@ export function AixyzServerPlugin(entrypoint: string): BunPlugin {
|
|
|
10
10
|
if (args.path !== entrypoint) return;
|
|
11
11
|
|
|
12
12
|
const source = await Bun.file(args.path).text();
|
|
13
|
-
const transformed = source.replace(/export\s+default\s+(\w+)\s*;/, "export default $1.express;");
|
|
14
13
|
|
|
15
|
-
|
|
14
|
+
if (mode === "vercel") {
|
|
15
|
+
// For Vercel, export server.express for serverless function
|
|
16
|
+
const transformed = source.replace(/export\s+default\s+(\w+)\s*;/, "export default $1.express;");
|
|
17
|
+
return { contents: transformed, loader: "ts" };
|
|
18
|
+
} else {
|
|
19
|
+
// For standalone, keep the server export but add startup code
|
|
20
|
+
// TODO(@fuxingloh): use Bun.serve later.
|
|
21
|
+
const transformed = source.replace(
|
|
22
|
+
/export\s+default\s+(\w+)\s*;/,
|
|
23
|
+
`export default $1;
|
|
24
|
+
|
|
25
|
+
// Auto-start server when run directly
|
|
26
|
+
if (import.meta.main) {
|
|
27
|
+
const port = parseInt(process.env.PORT || "3000", 10);
|
|
28
|
+
$1.express.listen(port, () => {
|
|
29
|
+
console.log(\`Server listening on port \${port}\`);
|
|
30
|
+
});
|
|
31
|
+
}`,
|
|
32
|
+
);
|
|
33
|
+
return { contents: transformed, loader: "ts" };
|
|
34
|
+
}
|
|
16
35
|
});
|
|
17
36
|
},
|
|
18
37
|
};
|
|
@@ -47,6 +66,13 @@ function generateServer(appDir: string, entrypointDir: string): string {
|
|
|
47
66
|
|
|
48
67
|
imports.push('import { AixyzServer } from "aixyz/server";');
|
|
49
68
|
|
|
69
|
+
const hasAccepts = existsSync(resolve(appDir, "accepts.ts"));
|
|
70
|
+
if (hasAccepts) {
|
|
71
|
+
imports.push(`import { facilitator } from "${importPrefix}/accepts";`);
|
|
72
|
+
} else {
|
|
73
|
+
imports.push('import { facilitator } from "aixyz/accepts";');
|
|
74
|
+
}
|
|
75
|
+
|
|
50
76
|
const hasAgent = existsSync(resolve(appDir, "agent.ts"));
|
|
51
77
|
if (hasAgent) {
|
|
52
78
|
imports.push('import { useA2A } from "aixyz/server/adapters/a2a";');
|
|
@@ -74,7 +100,7 @@ function generateServer(appDir: string, entrypointDir: string): string {
|
|
|
74
100
|
}
|
|
75
101
|
}
|
|
76
102
|
|
|
77
|
-
body.push("const server = new AixyzServer();");
|
|
103
|
+
body.push("const server = new AixyzServer(facilitator);");
|
|
78
104
|
body.push("await server.initialize();");
|
|
79
105
|
body.push("server.unstable_withIndexPage();");
|
|
80
106
|
|
package/build/index.ts
CHANGED
|
@@ -2,12 +2,89 @@ import { resolve } from "path";
|
|
|
2
2
|
import { existsSync, mkdirSync, cpSync, rmSync } from "fs";
|
|
3
3
|
import { AixyzConfigPlugin } from "./AixyzConfigPlugin";
|
|
4
4
|
import { AixyzServerPlugin, getEntrypointMayGenerate } from "./AixyzServerPlugin";
|
|
5
|
+
import { getAixyzConfig } from "@aixyz/config";
|
|
6
|
+
import { loadEnvConfig } from "@next/env";
|
|
7
|
+
import chalk from "chalk";
|
|
5
8
|
|
|
6
|
-
|
|
7
|
-
|
|
9
|
+
interface BuildOptions {
|
|
10
|
+
output?: string;
|
|
11
|
+
}
|
|
8
12
|
|
|
13
|
+
export async function build(options: BuildOptions = {}): Promise<void> {
|
|
14
|
+
const cwd = process.cwd();
|
|
15
|
+
loadEnvConfig(cwd, false);
|
|
9
16
|
const entrypoint = getEntrypointMayGenerate(cwd, "build");
|
|
10
17
|
|
|
18
|
+
// Determine output target: explicit CLI flag takes precedence, then config file, then auto-detect VERCEL env
|
|
19
|
+
const config = getAixyzConfig();
|
|
20
|
+
const target = options.output ?? config.build?.output ?? (process.env.VERCEL === "1" ? "vercel" : "standalone");
|
|
21
|
+
|
|
22
|
+
if (target === "vercel") {
|
|
23
|
+
console.log(chalk.cyan("▶") + " Building for " + chalk.bold("Vercel") + "...");
|
|
24
|
+
await buildVercel(entrypoint);
|
|
25
|
+
} else {
|
|
26
|
+
console.log(chalk.cyan("▶") + " Building for " + chalk.bold("Standalone") + "...");
|
|
27
|
+
await buildBun(entrypoint);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
async function buildBun(entrypoint: string): Promise<void> {
|
|
32
|
+
const cwd = process.cwd();
|
|
33
|
+
|
|
34
|
+
const outputDir = resolve(cwd, ".aixyz/output");
|
|
35
|
+
rmSync(outputDir, { recursive: true, force: true });
|
|
36
|
+
mkdirSync(outputDir, { recursive: true });
|
|
37
|
+
|
|
38
|
+
// Build as a single bundled file for Bun Runtime
|
|
39
|
+
const result = await Bun.build({
|
|
40
|
+
entrypoints: [entrypoint],
|
|
41
|
+
outdir: outputDir,
|
|
42
|
+
naming: "server.js",
|
|
43
|
+
target: "bun",
|
|
44
|
+
format: "esm",
|
|
45
|
+
sourcemap: "linked",
|
|
46
|
+
plugins: [AixyzConfigPlugin(), AixyzServerPlugin(entrypoint, "standalone")],
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
if (!result.success) {
|
|
50
|
+
console.error("Build failed:");
|
|
51
|
+
for (const log of result.logs) {
|
|
52
|
+
console.error(log);
|
|
53
|
+
}
|
|
54
|
+
process.exit(1);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Write package.json for ESM support
|
|
58
|
+
await Bun.write(resolve(outputDir, "package.json"), JSON.stringify({ type: "module" }, null, 2));
|
|
59
|
+
|
|
60
|
+
// Copy static assets (public/ → .aixyz/output/public/)
|
|
61
|
+
const publicDir = resolve(cwd, "public");
|
|
62
|
+
if (existsSync(publicDir)) {
|
|
63
|
+
const destPublicDir = resolve(outputDir, "public");
|
|
64
|
+
cpSync(publicDir, destPublicDir, { recursive: true });
|
|
65
|
+
console.log("Copied public/ →", destPublicDir);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const iconFile = resolve(cwd, "app/icon.png");
|
|
69
|
+
if (existsSync(iconFile)) {
|
|
70
|
+
cpSync(iconFile, resolve(outputDir, "icon.png"));
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// Log summary
|
|
74
|
+
console.log("");
|
|
75
|
+
console.log("Build complete! Output:");
|
|
76
|
+
console.log(" .aixyz/output/server.js");
|
|
77
|
+
console.log(" .aixyz/output/package.json");
|
|
78
|
+
if (existsSync(publicDir) || existsSync(iconFile)) {
|
|
79
|
+
console.log(" .aixyz/output/public/ and assets");
|
|
80
|
+
}
|
|
81
|
+
console.log("");
|
|
82
|
+
console.log("To run: bun .aixyz/output/server.js");
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
async function buildVercel(entrypoint: string): Promise<void> {
|
|
86
|
+
const cwd = process.cwd();
|
|
87
|
+
|
|
11
88
|
const outputDir = resolve(cwd, ".vercel/output");
|
|
12
89
|
rmSync(outputDir, { recursive: true, force: true });
|
|
13
90
|
|
|
@@ -22,7 +99,7 @@ export async function build(): Promise<void> {
|
|
|
22
99
|
target: "bun",
|
|
23
100
|
format: "esm",
|
|
24
101
|
sourcemap: "linked",
|
|
25
|
-
plugins: [AixyzConfigPlugin(), AixyzServerPlugin(entrypoint)],
|
|
102
|
+
plugins: [AixyzConfigPlugin(), AixyzServerPlugin(entrypoint, "vercel")],
|
|
26
103
|
});
|
|
27
104
|
|
|
28
105
|
if (!result.success) {
|
|
@@ -85,6 +162,6 @@ export async function build(): Promise<void> {
|
|
|
85
162
|
console.log("");
|
|
86
163
|
console.log("Build complete! Output:");
|
|
87
164
|
console.log(" .vercel/output/config.json");
|
|
88
|
-
console.log(" .vercel/output/functions/index.func/
|
|
165
|
+
console.log(" .vercel/output/functions/index.func/server.js");
|
|
89
166
|
console.log(" .vercel/output/static/");
|
|
90
167
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aixyz/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.4",
|
|
4
4
|
"description": "CLI for building and deploying aixyz agents.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ai",
|
|
@@ -30,9 +30,11 @@
|
|
|
30
30
|
"bin.ts"
|
|
31
31
|
],
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"@aixyz/config": "
|
|
33
|
+
"@aixyz/config": "0.0.0",
|
|
34
34
|
"@next/env": "^16.1.6",
|
|
35
|
-
"
|
|
35
|
+
"boxen": "^8.0.0",
|
|
36
|
+
"chalk": "^5.0.0",
|
|
37
|
+
"commander": "^14.0.3"
|
|
36
38
|
},
|
|
37
39
|
"engines": {
|
|
38
40
|
"bun": ">=1.3.0"
|