@aixyz/cli 0.1.2 → 0.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/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 Vercel deployment using the [Build Output API v3](https://vercel.com/docs/build-output-api/v3).
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,35 @@ program
27
27
 
28
28
  program
29
29
  .command("build")
30
- .description("Build the aixyz agent for Vercel deployment")
30
+ .description("Build the aixyz agent")
31
+ .option("--vercel", "Build for Vercel deployment with serverless function output")
31
32
  .addHelpText(
32
33
  "after",
33
34
  `
34
35
  Details:
35
- Bundles your aixyz agent into a Vercel serverless function output.
36
+ Bundles your aixyz agent for deployment.
37
+
38
+ Default behavior:
39
+ Bundles into a single executable file for Bun Runtime at ./.aixyz/output/server.js
40
+
41
+ With --vercel flag 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. Generates Vercel Build Output API v3 structure
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 for Bun Runtime (default)
57
+ $ aixyz build --vercel # Build for Vercel deployment
58
+ $ VERCEL=1 aixyz build # Auto-detected Vercel build`,
51
59
  )
52
60
  .action(handleAction(build));
53
61
 
@@ -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
- // TODO(@fuxingloh): change how this is formatted
8
- console.log("AixyzConfig loaded:", materialized);
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",
@@ -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
- return { contents: transformed, loader: "ts" };
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,87 @@ 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 { loadEnvConfig } from "@next/env";
6
+ import chalk from "chalk";
5
7
 
6
- export async function build(): Promise<void> {
7
- const cwd = process.cwd();
8
+ interface BuildOptions {
9
+ vercel?: boolean;
10
+ }
11
+
12
+ export async function build(options: BuildOptions = {}): Promise<void> {
13
+ // Auto-detect Vercel environment
14
+ const isVercel = options.vercel || process.env.VERCEL === "1";
8
15
 
16
+ const cwd = process.cwd();
17
+ loadEnvConfig(cwd, false);
9
18
  const entrypoint = getEntrypointMayGenerate(cwd, "build");
10
19
 
20
+ if (isVercel) {
21
+ console.log(chalk.cyan("▶") + " Building for " + chalk.bold("Vercel") + "...");
22
+ await buildVercel(entrypoint);
23
+ } else {
24
+ console.log(chalk.cyan("▶") + " Building for " + chalk.bold("Bun Runtime") + "...");
25
+ await buildBun(entrypoint);
26
+ }
27
+ }
28
+
29
+ async function buildBun(entrypoint: string): Promise<void> {
30
+ const cwd = process.cwd();
31
+
32
+ const outputDir = resolve(cwd, ".aixyz/output");
33
+ rmSync(outputDir, { recursive: true, force: true });
34
+ mkdirSync(outputDir, { recursive: true });
35
+
36
+ // Build as a single bundled file for Bun Runtime
37
+ const result = await Bun.build({
38
+ entrypoints: [entrypoint],
39
+ outdir: outputDir,
40
+ naming: "server.js",
41
+ target: "bun",
42
+ format: "esm",
43
+ sourcemap: "linked",
44
+ plugins: [AixyzConfigPlugin(), AixyzServerPlugin(entrypoint, "standalone")],
45
+ });
46
+
47
+ if (!result.success) {
48
+ console.error("Build failed:");
49
+ for (const log of result.logs) {
50
+ console.error(log);
51
+ }
52
+ process.exit(1);
53
+ }
54
+
55
+ // Write package.json for ESM support
56
+ await Bun.write(resolve(outputDir, "package.json"), JSON.stringify({ type: "module" }, null, 2));
57
+
58
+ // Copy static assets (public/ → .aixyz/output/public/)
59
+ const publicDir = resolve(cwd, "public");
60
+ if (existsSync(publicDir)) {
61
+ const destPublicDir = resolve(outputDir, "public");
62
+ cpSync(publicDir, destPublicDir, { recursive: true });
63
+ console.log("Copied public/ →", destPublicDir);
64
+ }
65
+
66
+ const iconFile = resolve(cwd, "app/icon.png");
67
+ if (existsSync(iconFile)) {
68
+ cpSync(iconFile, resolve(outputDir, "icon.png"));
69
+ }
70
+
71
+ // Log summary
72
+ console.log("");
73
+ console.log("Build complete! Output:");
74
+ console.log(" .aixyz/output/server.js");
75
+ console.log(" .aixyz/output/package.json");
76
+ if (existsSync(publicDir) || existsSync(iconFile)) {
77
+ console.log(" .aixyz/output/public/ and assets");
78
+ }
79
+ console.log("");
80
+ console.log("To run: bun .aixyz/output/server.js");
81
+ }
82
+
83
+ async function buildVercel(entrypoint: string): Promise<void> {
84
+ const cwd = process.cwd();
85
+
11
86
  const outputDir = resolve(cwd, ".vercel/output");
12
87
  rmSync(outputDir, { recursive: true, force: true });
13
88
 
@@ -22,7 +97,7 @@ export async function build(): Promise<void> {
22
97
  target: "bun",
23
98
  format: "esm",
24
99
  sourcemap: "linked",
25
- plugins: [AixyzConfigPlugin(), AixyzServerPlugin(entrypoint)],
100
+ plugins: [AixyzConfigPlugin(), AixyzServerPlugin(entrypoint, "vercel")],
26
101
  });
27
102
 
28
103
  if (!result.success) {
@@ -85,6 +160,6 @@ export async function build(): Promise<void> {
85
160
  console.log("");
86
161
  console.log("Build complete! Output:");
87
162
  console.log(" .vercel/output/config.json");
88
- console.log(" .vercel/output/functions/index.func/index.js");
163
+ console.log(" .vercel/output/functions/index.func/server.js");
89
164
  console.log(" .vercel/output/static/");
90
165
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aixyz/cli",
3
- "version": "0.1.2",
3
+ "version": "0.2.0",
4
4
  "description": "CLI for building and deploying aixyz agents.",
5
5
  "keywords": [
6
6
  "ai",
@@ -32,7 +32,9 @@
32
32
  "dependencies": {
33
33
  "@aixyz/config": "workspace:*",
34
34
  "@next/env": "^16.1.6",
35
- "commander": "^13.0.0"
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"