@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 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,36 @@ 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("--output <type>", "Output format: 'standalone' or 'vercel'")
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 (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. 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 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
- // 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",
@@ -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
- 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,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
- export async function build(): Promise<void> {
7
- const cwd = process.cwd();
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/index.js");
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.1.2",
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": "workspace:*",
33
+ "@aixyz/config": "0.0.0",
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"