@aigne/cli 1.49.0-beta.8 → 1.49.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/CHANGELOG.md CHANGED
@@ -1,5 +1,57 @@
1
1
  # Changelog
2
2
 
3
+ ## [1.49.0](https://github.com/AIGNE-io/aigne-framework/compare/cli-v1.49.0-beta.10...cli-v1.49.0) (2025-09-27)
4
+
5
+
6
+ ### Dependencies
7
+
8
+ * The following workspace dependencies were updated
9
+ * dependencies
10
+ * @aigne/agent-library bumped to 1.21.46
11
+ * @aigne/agentic-memory bumped to 1.0.46
12
+ * @aigne/aigne-hub bumped to 0.10.0
13
+ * @aigne/core bumped to 1.61.0
14
+ * @aigne/default-memory bumped to 1.2.9
15
+ * @aigne/observability-api bumped to 0.11.0
16
+ * @aigne/openai bumped to 0.16.0
17
+ * devDependencies
18
+ * @aigne/test-utils bumped to 0.5.53
19
+
20
+ ## [1.49.0-beta.10](https://github.com/AIGNE-io/aigne-framework/compare/cli-v1.49.0-beta.9...cli-v1.49.0-beta.10) (2025-09-27)
21
+
22
+
23
+ ### Bug Fixes
24
+
25
+ * **cli:** resolve input schema not working for run command ([#557](https://github.com/AIGNE-io/aigne-framework/issues/557)) ([6fa12b3](https://github.com/AIGNE-io/aigne-framework/commit/6fa12b3e068aaec28cf204c3a3f7c471bd2827ae))
26
+
27
+ ## [1.49.0-beta.9](https://github.com/AIGNE-io/aigne-framework/compare/cli-v1.49.0-beta.8...cli-v1.49.0-beta.9) (2025-09-26)
28
+
29
+
30
+ ### Features
31
+
32
+ * **cli:** add `--beta` `--target-version` `--force` options for `upgrade` command ([#555](https://github.com/AIGNE-io/aigne-framework/issues/555)) ([f9f0471](https://github.com/AIGNE-io/aigne-framework/commit/f9f04719020cca00bc3adbe8169c42422201df49))
33
+
34
+
35
+ ### Bug Fixes
36
+
37
+ * **blocklet:** observability blocklet start failure ([#554](https://github.com/AIGNE-io/aigne-framework/issues/554)) ([8431d4d](https://github.com/AIGNE-io/aigne-framework/commit/8431d4d89a4b96f735f23e774e9545bbe1fd811c))
38
+ * **blocklet:** observability blocklet start failure ([#554](https://github.com/AIGNE-io/aigne-framework/issues/554)) ([8431d4d](https://github.com/AIGNE-io/aigne-framework/commit/8431d4d89a4b96f735f23e774e9545bbe1fd811c))
39
+
40
+
41
+ ### Dependencies
42
+
43
+ * The following workspace dependencies were updated
44
+ * dependencies
45
+ * @aigne/agent-library bumped to 1.21.46-beta.9
46
+ * @aigne/agentic-memory bumped to 1.0.46-beta.9
47
+ * @aigne/aigne-hub bumped to 0.10.0-beta.9
48
+ * @aigne/core bumped to 1.61.0-beta.8
49
+ * @aigne/default-memory bumped to 1.2.9-beta.9
50
+ * @aigne/observability-api bumped to 0.11.0-beta.1
51
+ * @aigne/openai bumped to 0.16.0-beta.9
52
+ * devDependencies
53
+ * @aigne/test-utils bumped to 0.5.53-beta.8
54
+
3
55
  ## [1.49.0-beta.8](https://github.com/AIGNE-io/aigne-framework/compare/cli-v1.49.0-beta.7...cli-v1.49.0-beta.8) (2025-09-26)
4
56
 
5
57
 
@@ -1,27 +1,41 @@
1
- import type { Agent, AIGNE, Message } from "@aigne/core";
2
1
  import type { CommandModule } from "yargs";
2
+ import { type AgentInChildProcess, type LoadAIGNEInChildProcessResult } from "../utils/workers/run-aigne-in-child-process.js";
3
3
  import { type AgentRunCommonOptions } from "../utils/yargs.js";
4
4
  export declare function createAppCommands(): CommandModule[];
5
5
  export declare const agentCommandModule: ({ dir, agent, }: {
6
6
  dir: string;
7
- agent: Agent;
7
+ agent: AgentInChildProcess;
8
8
  }) => CommandModule<unknown, AgentRunCommonOptions>;
9
- export declare function invokeCLIAgentFromDir(options: {
10
- dir: string;
11
- agent: string;
12
- input: Message & AgentRunCommonOptions;
13
- }): Promise<void>;
14
- export declare function loadApplication({ name, dir, forceUpgrade, }: {
15
- name: string;
16
- dir?: string;
17
- forceUpgrade?: boolean;
18
- }): Promise<{
19
- aigne: AIGNE;
9
+ interface LoadApplicationOptions {
10
+ packageName: string;
20
11
  dir: string;
12
+ install?: boolean;
13
+ }
14
+ interface LoadApplicationResult {
15
+ aigne: LoadAIGNEInChildProcessResult;
21
16
  version: string;
22
17
  isCache?: boolean;
18
+ }
19
+ export declare function loadApplication(options: LoadApplicationOptions & {
20
+ install: true;
21
+ }): Promise<LoadApplicationResult>;
22
+ export declare function loadApplication(options: LoadApplicationOptions & {
23
+ install?: false;
24
+ }): Promise<LoadApplicationResult | null>;
25
+ export declare function installApp({ dir, packageName, beta, version, }: {
26
+ dir: string;
27
+ packageName: string;
28
+ beta?: boolean;
29
+ version?: string;
30
+ }): Promise<{
31
+ url: string;
32
+ version: string;
23
33
  }>;
24
- export declare function getNpmTgzInfo(name: string): Promise<{
34
+ export declare function getNpmTgzInfo(name: string, { version, beta }?: {
35
+ version?: string;
36
+ beta?: boolean;
37
+ }): Promise<{
25
38
  version: string;
26
- url: any;
39
+ url: string;
27
40
  }>;
41
+ export {};
@@ -1,16 +1,14 @@
1
- import assert from "node:assert";
2
1
  import { spawn } from "node:child_process";
3
2
  import { mkdir, readFile, rm, stat, writeFile } from "node:fs/promises";
4
3
  import { homedir } from "node:os";
5
4
  import { join } from "node:path";
6
5
  import { logger } from "@aigne/core/utils/logger.js";
6
+ import { jsonSchemaToZod } from "@aigne/json-schema-to-zod";
7
7
  import { Listr, PRESET_TIMER } from "@aigne/listr2";
8
8
  import { joinURL } from "ufo";
9
9
  import { downloadAndExtract } from "../utils/download.js";
10
- import { loadAIGNE } from "../utils/load-aigne.js";
11
- import { runAgentWithAIGNE } from "../utils/run-with-aigne.js";
12
- import { safeLoadAIGNE } from "../utils/workers/load-aigne.js";
13
- import { parseAgentInput, withAgentInputSchema, } from "../utils/yargs.js";
10
+ import { runAIGNEInChildProcess, } from "../utils/workers/run-aigne-in-child-process.js";
11
+ import { withAgentInputSchema } from "../utils/yargs.js";
14
12
  import { serveMCPServerFromDir } from "./serve-mcp.js";
15
13
  const NPM_PACKAGE_CACHE_TIME_MS = 1000 * 60 * 60 * 24; // 1 day
16
14
  /**
@@ -23,11 +21,13 @@ function shouldUseBetaApps() {
23
21
  const builtinApps = [
24
22
  {
25
23
  name: "doc-smith",
24
+ packageName: "@aigne/doc-smith",
26
25
  describe: "Generate and maintain project docs — powered by agents.",
27
26
  aliases: ["docsmith", "doc"],
28
27
  },
29
28
  {
30
29
  name: "web-smith",
30
+ packageName: "@aigne/web-smith",
31
31
  describe: "Generate and maintain project website pages — powered by agents.",
32
32
  aliases: ["websmith", "web"],
33
33
  },
@@ -38,30 +38,28 @@ export function createAppCommands() {
38
38
  describe: app.describe,
39
39
  aliases: app.aliases,
40
40
  builder: async (yargs) => {
41
- const { aigne, dir, version, isCache } = await loadApplication({
42
- name: app.name,
43
- });
44
- yargs
45
- .option("model", {
46
- type: "string",
47
- description: "Model to use for the application, example: openai:gpt-4.1 or google:gemini-2.5-flash",
48
- })
49
- .command(serveMcpCommandModule({ name: app.name, dir }))
50
- .command(upgradeCommandModule({
51
- name: app.name,
41
+ const dir = join(homedir(), ".aigne", "registry.npmjs.org", app.packageName);
42
+ const { aigne, version } = await loadApplication({
52
43
  dir,
53
- isLatest: !isCache,
54
- version,
55
- }));
56
- if (aigne.cli.chat) {
44
+ packageName: app.packageName,
45
+ install: true,
46
+ });
47
+ if (aigne.cli?.chat) {
57
48
  yargs.command({
58
49
  ...agentCommandModule({ dir, agent: aigne.cli.chat }),
59
50
  command: "$0",
60
51
  });
61
52
  }
62
- for (const agent of aigne.cli.agents) {
53
+ for (const agent of aigne.cli?.agents ?? []) {
63
54
  yargs.command(agentCommandModule({ dir, agent }));
64
55
  }
56
+ yargs
57
+ .option("model", {
58
+ type: "string",
59
+ description: "Model to use for the application, example: openai:gpt-4.1 or google:gemini-2.5-flash",
60
+ })
61
+ .command(serveMcpCommandModule({ name: app.name, dir }))
62
+ .command(upgradeCommandModule({ packageName: app.packageName, dir }));
65
63
  yargs.version(`${app.name} v${version}`).alias("version", "v");
66
64
  return yargs.demandCommand();
67
65
  },
@@ -92,18 +90,39 @@ const serveMcpCommandModule = ({ name, dir, }) => ({
92
90
  await serveMCPServerFromDir({ ...options, dir });
93
91
  },
94
92
  });
95
- const upgradeCommandModule = ({ name, dir, isLatest, version, }) => ({
93
+ const upgradeCommandModule = ({ packageName, dir, }) => ({
96
94
  command: "upgrade",
97
- describe: `Upgrade ${name} to the latest version`,
98
- handler: async () => {
99
- if (!isLatest) {
100
- const result = await loadApplication({ name, dir, forceUpgrade: true });
101
- if (version !== result.version) {
102
- console.log(`\n✅ Upgraded ${name} to version ${result.version}`);
103
- return;
104
- }
95
+ describe: `Upgrade ${packageName} to the latest version`,
96
+ builder: (argv) => {
97
+ return argv
98
+ .option("beta", {
99
+ type: "boolean",
100
+ describe: "Use beta versions if available",
101
+ })
102
+ .option("target-version", {
103
+ type: "string",
104
+ describe: "Specify a version to upgrade to (default is latest)",
105
+ alias: ["to", "target"],
106
+ })
107
+ .option("force", {
108
+ type: "boolean",
109
+ describe: "Force upgrade even if already at latest version",
110
+ default: false,
111
+ });
112
+ },
113
+ handler: async ({ beta, targetVersion, force }) => {
114
+ beta ??= shouldUseBetaApps();
115
+ let app = await loadApplication({ packageName, dir });
116
+ const npm = await getNpmTgzInfo(packageName, { beta, version: targetVersion });
117
+ if (!app || force || npm.version !== app.version) {
118
+ if (force)
119
+ await rm(dir, { force: true, recursive: true });
120
+ await installApp({ packageName, dir, beta, version: targetVersion });
121
+ app = await loadApplication({ dir, packageName, install: true });
122
+ console.log(`\n✅ Upgraded ${packageName} to version ${app.version}`);
123
+ return;
105
124
  }
106
- console.log(`\n✅ ${name} is already at the latest version (${version})`);
125
+ console.log(`\n✅ ${packageName} is already at the latest version (${app.version})`);
107
126
  },
108
127
  });
109
128
  export const agentCommandModule = ({ dir, agent, }) => {
@@ -111,76 +130,76 @@ export const agentCommandModule = ({ dir, agent, }) => {
111
130
  command: agent.name,
112
131
  aliases: agent.alias || [],
113
132
  describe: agent.description || "",
114
- builder: async (yargs) => withAgentInputSchema(yargs, agent),
133
+ builder: async (yargs) => {
134
+ return withAgentInputSchema(yargs, { inputSchema: jsonSchemaToZod(agent.inputSchema) });
135
+ },
115
136
  handler: async (options) => {
116
137
  if (options.logLevel)
117
138
  logger.level = options.logLevel;
118
- await invokeCLIAgentFromDir({ dir, agent: agent.name, input: options });
139
+ await runAIGNEInChildProcess("invokeCLIAgentFromDir", {
140
+ dir,
141
+ agent: agent.name,
142
+ input: options,
143
+ });
119
144
  process.exit(0);
120
145
  },
121
146
  };
122
147
  };
123
- export async function invokeCLIAgentFromDir(options) {
124
- const aigne = await loadAIGNE({
125
- path: options.dir,
126
- modelOptions: options.input,
127
- });
128
- try {
129
- const { chat } = aigne.cli;
130
- const agent = chat && chat.name === options.agent
131
- ? chat
132
- : aigne.cli.agents[options.agent] ||
133
- aigne.agents[options.agent] ||
134
- aigne.skills[options.agent] ||
135
- aigne.mcpServer.agents[options.agent];
136
- assert(agent, `Agent ${options.agent} not found in ${options.dir}`);
137
- const input = await parseAgentInput(options.input, agent);
138
- await runAgentWithAIGNE(aigne, agent, {
139
- ...options.input,
140
- input,
141
- chat: agent === chat || options.input.chat,
142
- });
143
- }
144
- finally {
145
- await aigne.shutdown();
146
- }
147
- }
148
- export async function loadApplication({ name, dir, forceUpgrade = false, }) {
149
- name = `@aigne/${name}`;
150
- dir ??= join(homedir(), ".aigne", "registry.npmjs.org", name);
151
- let check = forceUpgrade ? undefined : await isInstallationAvailable(dir);
152
- if (check?.available) {
153
- const aigne = await safeLoadAIGNE(dir).catch((error) => {
154
- console.warn(`⚠️ Failed to load ${name}, trying to reinstall:`, error.message);
148
+ export async function loadApplication(options) {
149
+ const { dir, packageName } = options;
150
+ const check = await checkInstallation(dir);
151
+ if (check && !check.expired) {
152
+ const aigne = await runAIGNEInChildProcess("loadAIGNE", dir).catch((error) => {
153
+ console.warn(`⚠️ Failed to load ${packageName}, trying to reinstall:`, error.message);
155
154
  });
156
155
  if (aigne) {
157
- return {
158
- aigne,
159
- dir,
160
- version: check.version,
161
- isCache: true,
162
- };
156
+ return { aigne, version: check.version, isCache: true };
163
157
  }
164
- check = undefined;
165
158
  }
166
- const result = await new Listr([
159
+ if (!options.install)
160
+ return null;
161
+ const result = await installApp({ dir, packageName, beta: check?.version?.includes("beta") });
162
+ return {
163
+ aigne: await runAIGNEInChildProcess("loadAIGNE", dir),
164
+ version: result.version,
165
+ };
166
+ }
167
+ async function readInstallationMetadata(dir) {
168
+ return safeParseJSON(await readFile(join(dir, ".aigne-cli.json"), "utf-8").catch(() => "{}"));
169
+ }
170
+ async function writeInstallationMetadata(dir, metadata) {
171
+ await writeFile(join(dir, ".aigne-cli.json"), JSON.stringify(metadata, null, 2));
172
+ }
173
+ async function checkInstallation(dir, { cacheTimeMs = NPM_PACKAGE_CACHE_TIME_MS } = {}) {
174
+ const s = await stat(join(dir, "package.json")).catch(() => null);
175
+ if (!s)
176
+ return null;
177
+ const version = safeParseJSON(await readFile(join(dir, "package.json"), "utf-8"))?.version;
178
+ if (!version)
179
+ return null;
180
+ const installedAt = (await readInstallationMetadata(dir))?.installedAt;
181
+ if (!installedAt)
182
+ return null;
183
+ const now = Date.now();
184
+ const expired = now - installedAt > cacheTimeMs;
185
+ return { version, expired };
186
+ }
187
+ export async function installApp({ dir, packageName, beta, version, }) {
188
+ return await new Listr([
167
189
  {
168
- title: `Fetching ${name} metadata`,
190
+ title: `Fetching ${packageName} metadata`,
169
191
  task: async (ctx, task) => {
170
- const info = await getNpmTgzInfo(name);
171
- Object.assign(ctx, info);
172
- const useBeta = shouldUseBetaApps();
173
- if (useBeta && ctx.version.includes("beta")) {
174
- task.title = `Fetching ${name} metadata (using beta version)`;
192
+ if (beta) {
193
+ task.title = `Fetching ${packageName} metadata (using beta version)`;
175
194
  }
195
+ const info = await getNpmTgzInfo(packageName, { beta, version });
196
+ Object.assign(ctx, info);
176
197
  },
177
198
  },
178
199
  {
179
- title: `Downloading ${name}`,
180
- skip: (ctx) => ctx.version === check?.version,
200
+ title: `Downloading ${packageName}`,
181
201
  task: async (ctx, task) => {
182
- task.title = `Downloading ${name}(v${ctx.version})`;
183
- await rm(dir, { force: true, recursive: true });
202
+ task.title = `Downloading ${packageName} (v${ctx.version})`;
184
203
  await mkdir(dir, { recursive: true });
185
204
  await downloadAndExtract(ctx.url, dir, { strip: 1 });
186
205
  },
@@ -195,6 +214,7 @@ export async function loadApplication({ name, dir, forceUpgrade = false, }) {
195
214
  task.output = last;
196
215
  },
197
216
  });
217
+ await writeInstallationMetadata(dir, { installedAt: Date.now() });
198
218
  },
199
219
  },
200
220
  ], {
@@ -204,25 +224,6 @@ export async function loadApplication({ name, dir, forceUpgrade = false, }) {
204
224
  timer: PRESET_TIMER,
205
225
  },
206
226
  }).run();
207
- return {
208
- aigne: await safeLoadAIGNE(dir),
209
- dir,
210
- version: result.version,
211
- };
212
- }
213
- async function isInstallationAvailable(dir, { cacheTimeMs = NPM_PACKAGE_CACHE_TIME_MS } = {}) {
214
- const s = await stat(join(dir, "package.json")).catch(() => null);
215
- if (!s)
216
- return null;
217
- const version = safeParseJSON(await readFile(join(dir, "package.json"), "utf-8"))?.version;
218
- if (!version)
219
- return null;
220
- const installedAt = safeParseJSON(await readFile(join(dir, ".aigne-cli.json"), "utf-8").catch(() => "{}"))?.installedAt;
221
- if (!installedAt)
222
- return null;
223
- const now = Date.now();
224
- const available = installedAt ? now - installedAt < cacheTimeMs : false;
225
- return { version, available };
226
227
  }
227
228
  async function installDependencies(dir, { log } = {}) {
228
229
  await new Promise((resolve, reject) => {
@@ -250,16 +251,20 @@ async function installDependencies(dir, { log } = {}) {
250
251
  }
251
252
  });
252
253
  });
253
- await writeFile(join(dir, ".aigne-cli.json"), JSON.stringify({ installedAt: Date.now() }, null, 2));
254
254
  }
255
- export async function getNpmTgzInfo(name) {
255
+ export async function getNpmTgzInfo(name, { version, beta } = {}) {
256
256
  const res = await fetch(joinURL("https://registry.npmjs.org", name));
257
257
  if (!res.ok)
258
258
  throw new Error(`Failed to fetch package info for ${name}: ${res.statusText}`);
259
259
  const data = await res.json();
260
- const useBeta = shouldUseBetaApps();
261
260
  let targetVersion;
262
- if (useBeta && data["dist-tags"].beta) {
261
+ if (version) {
262
+ if (!data.versions[version]) {
263
+ throw new Error(`Version ${version} of package ${name} not found`);
264
+ }
265
+ targetVersion = version;
266
+ }
267
+ else if (beta && data["dist-tags"].beta) {
263
268
  // Use beta version if available and beta flag is set
264
269
  targetVersion = data["dist-tags"].beta;
265
270
  }
@@ -10,6 +10,7 @@ import { isV1Package, toAIGNEPackage } from "../utils/agent-v1.js";
10
10
  import { downloadAndExtract } from "../utils/download.js";
11
11
  import { loadAIGNE } from "../utils/load-aigne.js";
12
12
  import { isUrl } from "../utils/url.js";
13
+ import { serializeAgent } from "../utils/workers/run-aigne-in-child-process.js";
13
14
  import { agentCommandModule } from "./app.js";
14
15
  export function createRunCommand({ aigneFilePath, } = {}) {
15
16
  return {
@@ -41,14 +42,14 @@ export function createRunCommand({ aigneFilePath, } = {}) {
41
42
  const subYargs = yargs().scriptName("").usage("aigne run <path> <agent> [...options]");
42
43
  if (aigne.cli.chat) {
43
44
  subYargs.command({
44
- ...agentCommandModule({ dir: path, agent: aigne.cli.chat }),
45
+ ...agentCommandModule({ dir: path, agent: serializeAgent(aigne.cli.chat) }),
45
46
  command: "$0",
46
47
  });
47
48
  }
48
49
  // Allow user to run all of agents in the AIGNE instances
49
50
  const allAgents = flat(aigne.cli.agents, aigne.agents, aigne.skills, aigne.cli.chat, aigne.mcpServer.agents);
50
51
  for (const agent of allAgents) {
51
- subYargs.command(agentCommandModule({ dir: path, agent }));
52
+ subYargs.command(agentCommandModule({ dir: path, agent: serializeAgent(agent) }));
52
53
  }
53
54
  const argv = process.argv.slice(aigneFilePath ? 3 : 2);
54
55
  if (argv[0] === "run")
@@ -102,7 +103,7 @@ async function loadApplication(path) {
102
103
  }
103
104
  // Load env files in the aigne directory
104
105
  config({ path: dir, silent: true });
105
- const aigne = await loadAIGNE({ path: dir });
106
+ const aigne = await loadAIGNE({ path: dir, printTips: false });
106
107
  return { aigne, path: dir };
107
108
  }
108
109
  async function downloadPackage(url, cacheDir) {
@@ -21,6 +21,33 @@ const chars = {
21
21
  "right-mid": borderColor("┤"),
22
22
  middle: borderColor("│"),
23
23
  };
24
+ const MAX_CELL_LENGTH = 300;
25
+ function renderPagedTable(list, { maxCols = 6, chars }) {
26
+ if (!list.length)
27
+ return [];
28
+ const tables = [];
29
+ const head = list[0]?.map((h) => h.header) ?? [];
30
+ const widths = list[0]?.map((h) => h.width ?? 20) ?? [];
31
+ for (let i = 0; i < head.length; i += maxCols) {
32
+ const subHead = head.slice(i, i + maxCols);
33
+ const subWidths = widths.slice(i, i + maxCols);
34
+ const table = new Table({
35
+ head: subHead,
36
+ colWidths: subWidths,
37
+ wordWrap: true,
38
+ chars,
39
+ });
40
+ for (const row of list) {
41
+ table.push(row
42
+ .slice(i, i + maxCols)
43
+ .map((h) => String(h.value).length > MAX_CELL_LENGTH
44
+ ? `${String(h.value).slice(0, MAX_CELL_LENGTH)}...`
45
+ : h.value));
46
+ }
47
+ tables.push(table.toString());
48
+ }
49
+ return tables;
50
+ }
24
51
  export class BaseReporter {
25
52
  name = "base";
26
53
  async report(_report) {
@@ -43,7 +70,6 @@ export class BaseReporter {
43
70
  width: 40,
44
71
  value: r.expected ? JSON.stringify(r.expected) : "-",
45
72
  },
46
- { header: "Error", key: "Error", width: 20, value: r.error ?? "-" },
47
73
  {
48
74
  header: "Evaluations",
49
75
  key: "Evaluations",
@@ -56,6 +82,7 @@ export class BaseReporter {
56
82
  width: 20,
57
83
  value: r.evaluations.map((e) => `${e.rating}`).join(", "),
58
84
  },
85
+ { header: "Error", key: "Error", width: 20, value: r.error ?? "-" },
59
86
  {
60
87
  header: "Reason",
61
88
  key: "Reason",
@@ -140,18 +167,10 @@ export class ConsoleReporter extends BaseReporter {
140
167
  if (!list.length)
141
168
  return;
142
169
  console.log("\n=== 📋 Detailed Results ===");
143
- const head = list[0]?.map((h) => h.header) ?? [];
144
- const colWidths = list[0]?.map((h) => h.width) ?? [];
145
- const detailTable = new Table({
146
- head,
147
- colWidths,
148
- wordWrap: true,
149
- chars,
150
- });
151
- for (const r of list) {
152
- detailTable.push(r.map((h) => h.value));
170
+ const pages = renderPagedTable(list, { maxCols: 5, chars });
171
+ for (const page of pages) {
172
+ console.log(page);
153
173
  }
154
- console.log(detailTable.toString());
155
174
  const failed = report.results.filter((r) => r.error);
156
175
  if (failed.length) {
157
176
  console.log(chalk.red("\n=== ❌ Failed Cases ==="));
@@ -7,7 +7,8 @@ export interface RunOptions extends AgentRunCommonOptions {
7
7
  cacheDir?: string;
8
8
  aigneHubUrl?: string;
9
9
  }
10
- export declare function loadAIGNE({ path, modelOptions, }: {
10
+ export declare function loadAIGNE({ path, modelOptions, printTips, }: {
11
11
  path?: string;
12
12
  modelOptions?: ChatModelInputOptions & LoadCredentialOptions;
13
+ printTips?: boolean;
13
14
  }): Promise<AIGNE<import("@aigne/core").UserContext>>;
@@ -8,9 +8,6 @@ import { loadChatModel, maskApiKey } from "./aigne-hub/model.js";
8
8
  import { getUrlOrigin } from "./get-url-origin.js";
9
9
  let printed = false;
10
10
  async function printChatModelInfoBox(model) {
11
- if (printed)
12
- return;
13
- printed = true;
14
11
  const credential = await model.credential;
15
12
  const lines = [`${chalk.cyan("Provider")}: ${chalk.green(model.name.replace("ChatModel", ""))}`];
16
13
  if (credential?.model) {
@@ -25,7 +22,7 @@ async function printChatModelInfoBox(model) {
25
22
  console.log(boxen(lines.join("\n"), { padding: 1, borderStyle: "classic", borderColor: "cyan" }));
26
23
  console.log("");
27
24
  }
28
- export async function loadAIGNE({ path, modelOptions, }) {
25
+ export async function loadAIGNE({ path, modelOptions, printTips = true, }) {
29
26
  let aigne;
30
27
  if (path) {
31
28
  aigne = await AIGNE.load(path, {
@@ -42,9 +39,12 @@ export async function loadAIGNE({ path, modelOptions, }) {
42
39
  const chatModel = await loadChatModel({ ...modelOptions });
43
40
  aigne = new AIGNE({ model: chatModel });
44
41
  }
45
- console.log(`${chalk.grey("TIPS:")} run ${chalk.cyan("aigne observe")} to start the observability server.\n`);
46
- if (aigne.model) {
47
- await printChatModelInfoBox(aigne.model);
42
+ if (printTips && !printed) {
43
+ printed = true;
44
+ console.log(`${chalk.grey("TIPS:")} run ${chalk.cyan("aigne observe")} to start the observability server.\n`);
45
+ if (aigne.model) {
46
+ await printChatModelInfoBox(aigne.model);
47
+ }
48
48
  }
49
49
  return aigne;
50
50
  }
@@ -0,0 +1,18 @@
1
+ import { AIGNE, type Message } from "@aigne/core";
2
+ import { type AgentRunCommonOptions } from "../yargs.js";
3
+ import { type AgentInChildProcess } from "./run-aigne-in-child-process.js";
4
+ export declare function loadAIGNEInChildProcess(...args: Parameters<typeof AIGNE.load>): Promise<{
5
+ agents?: AgentInChildProcess[];
6
+ cli?: {
7
+ chat?: AgentInChildProcess;
8
+ agents?: AgentInChildProcess[];
9
+ };
10
+ mcpServer?: {
11
+ agents?: AgentInChildProcess[];
12
+ };
13
+ }>;
14
+ export declare function invokeCLIAgentFromDirInChildProcess(options: {
15
+ dir: string;
16
+ agent: string;
17
+ input: Message & AgentRunCommonOptions;
18
+ }): Promise<void>;
@@ -0,0 +1,72 @@
1
+ import assert from "node:assert";
2
+ import { AIGNE } from "@aigne/core";
3
+ import { loadAIGNE } from "../load-aigne.js";
4
+ import { runAgentWithAIGNE } from "../run-with-aigne.js";
5
+ import { parseAgentInput } from "../yargs.js";
6
+ import { serializeAgent } from "./run-aigne-in-child-process.js";
7
+ const METHODS = {
8
+ loadAIGNE: loadAIGNEInChildProcess,
9
+ invokeCLIAgentFromDir: invokeCLIAgentFromDirInChildProcess,
10
+ };
11
+ process.on("message", async ({ method, args }) => {
12
+ const send = (message) => new Promise((resolve, reject) => {
13
+ assert(process.send);
14
+ process.send(message, undefined, undefined, (error) => {
15
+ if (error)
16
+ reject(error);
17
+ else
18
+ resolve(true);
19
+ });
20
+ });
21
+ try {
22
+ const handler = METHODS[method];
23
+ if (!handler)
24
+ throw new Error(`Unknown method: ${method}`);
25
+ const result = await handler(...args);
26
+ await send({ method, result });
27
+ }
28
+ catch (error) {
29
+ await send({ method, error: { message: error.message } });
30
+ }
31
+ finally {
32
+ process.exit(0);
33
+ }
34
+ });
35
+ export async function loadAIGNEInChildProcess(...args) {
36
+ const aigne = await AIGNE.load(...args);
37
+ return {
38
+ agents: aigne.agents.map(serializeAgent),
39
+ cli: {
40
+ chat: aigne.cli.chat ? serializeAgent(aigne.cli.chat) : undefined,
41
+ agents: aigne.cli.agents.map(serializeAgent),
42
+ },
43
+ mcpServer: {
44
+ agents: aigne.mcpServer.agents.map(serializeAgent),
45
+ },
46
+ };
47
+ }
48
+ export async function invokeCLIAgentFromDirInChildProcess(options) {
49
+ const aigne = await loadAIGNE({
50
+ path: options.dir,
51
+ modelOptions: options.input,
52
+ });
53
+ try {
54
+ const { chat } = aigne.cli;
55
+ const agent = chat && chat.name === options.agent
56
+ ? chat
57
+ : aigne.cli.agents[options.agent] ||
58
+ aigne.agents[options.agent] ||
59
+ aigne.skills[options.agent] ||
60
+ aigne.mcpServer.agents[options.agent];
61
+ assert(agent, `Agent ${options.agent} not found in ${options.dir}`);
62
+ const input = await parseAgentInput(options.input, agent);
63
+ await runAgentWithAIGNE(aigne, agent, {
64
+ ...options.input,
65
+ input,
66
+ chat: agent === chat || options.input.chat,
67
+ });
68
+ }
69
+ finally {
70
+ await aigne.shutdown();
71
+ }
72
+ }
@@ -0,0 +1,14 @@
1
+ import type { Agent } from "@aigne/core";
2
+ import type { JsonSchema } from "@aigne/json-schema-to-zod";
3
+ import type { invokeCLIAgentFromDirInChildProcess, loadAIGNEInChildProcess } from "./run-aigne-in-child-process-worker.js";
4
+ export type LoadAIGNEInChildProcessResult = Awaited<ReturnType<typeof loadAIGNEInChildProcess>>;
5
+ export interface AgentInChildProcess extends Pick<Agent, "name" | "description" | "alias"> {
6
+ inputSchema: JsonSchema;
7
+ outputSchema: JsonSchema;
8
+ }
9
+ export declare function serializeAgent(agent: Agent): AgentInChildProcess;
10
+ export interface ChildProcessAIGNEMethods {
11
+ loadAIGNE: typeof loadAIGNEInChildProcess;
12
+ invokeCLIAgentFromDir: typeof invokeCLIAgentFromDirInChildProcess;
13
+ }
14
+ export declare function runAIGNEInChildProcess<M extends keyof ChildProcessAIGNEMethods>(method: M, ...args: Parameters<ChildProcessAIGNEMethods[M]>): Promise<ReturnType<ChildProcessAIGNEMethods[M]>>;
@@ -0,0 +1,30 @@
1
+ import { fork } from "node:child_process";
2
+ import { dirname, join } from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+ import { zodToJsonSchema } from "zod-to-json-schema";
5
+ export function serializeAgent(agent) {
6
+ return {
7
+ name: agent.name,
8
+ description: agent.description,
9
+ alias: agent.alias,
10
+ inputSchema: zodToJsonSchema(agent.inputSchema),
11
+ outputSchema: zodToJsonSchema(agent.outputSchema),
12
+ };
13
+ }
14
+ export async function runAIGNEInChildProcess(method, ...args) {
15
+ return await new Promise((resolve, reject) => {
16
+ const child = fork(join(dirname(fileURLToPath(import.meta.url)), "./run-aigne-in-child-process-worker.js"));
17
+ child.on("message", (event) => {
18
+ if (event.method !== method)
19
+ reject(new Error(`Unknown method: ${event.method} expected: ${method}`));
20
+ else if (event.error)
21
+ reject(new Error(`Failed to execute ${method}: ${event.error.message}`));
22
+ else
23
+ resolve(event.result);
24
+ });
25
+ child.on("exit", (code) => {
26
+ reject(new Error(`Child process exited with code ${code}`));
27
+ });
28
+ child.send({ method, args });
29
+ });
30
+ }
@@ -50,7 +50,7 @@ export declare function inferZodType(type: ZodType, opts?: {
50
50
  array?: boolean;
51
51
  optional?: boolean;
52
52
  };
53
- export declare function withAgentInputSchema(yargs: Argv, agent: Agent): Argv<{
53
+ export declare function withAgentInputSchema(yargs: Argv, agent: Pick<Agent, "inputSchema">): Argv<{
54
54
  chat: boolean;
55
55
  } & {
56
56
  model: string | undefined;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aigne/cli",
3
- "version": "1.49.0-beta.8",
3
+ "version": "1.49.0",
4
4
  "description": "Your command center for agent development",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -45,6 +45,7 @@
45
45
  }
46
46
  },
47
47
  "dependencies": {
48
+ "@aigne/json-schema-to-zod": "^1.3.3",
48
49
  "@aigne/listr2": "^1.0.10",
49
50
  "@aigne/marked-terminal": "^7.3.2",
50
51
  "@fast-csv/format": "^5.0.5",
@@ -82,13 +83,14 @@
82
83
  "yargs": "^18.0.0",
83
84
  "yoctocolors-cjs": "^2.1.3",
84
85
  "zod": "^3.25.67",
85
- "@aigne/agent-library": "^1.21.46-beta.8",
86
- "@aigne/agentic-memory": "^1.0.46-beta.8",
87
- "@aigne/core": "^1.61.0-beta.7",
88
- "@aigne/aigne-hub": "^0.10.0-beta.8",
89
- "@aigne/default-memory": "^1.2.9-beta.8",
90
- "@aigne/observability-api": "^0.11.0-beta",
91
- "@aigne/openai": "^0.16.0-beta.8"
86
+ "zod-to-json-schema": "^3.24.6",
87
+ "@aigne/agent-library": "^1.21.46",
88
+ "@aigne/agentic-memory": "^1.0.46",
89
+ "@aigne/aigne-hub": "^0.10.0",
90
+ "@aigne/core": "^1.61.0",
91
+ "@aigne/default-memory": "^1.2.9",
92
+ "@aigne/openai": "^0.16.0",
93
+ "@aigne/observability-api": "^0.11.0"
92
94
  },
93
95
  "devDependencies": {
94
96
  "@inquirer/testing": "^2.1.50",
@@ -105,7 +107,7 @@
105
107
  "rimraf": "^6.0.1",
106
108
  "typescript": "^5.9.2",
107
109
  "ufo": "^1.6.1",
108
- "@aigne/test-utils": "^0.5.53-beta.7"
110
+ "@aigne/test-utils": "^0.5.53"
109
111
  },
110
112
  "scripts": {
111
113
  "lint": "tsc --noEmit",
@@ -1 +0,0 @@
1
- export {};
@@ -1,13 +0,0 @@
1
- import { AIGNE } from "@aigne/core";
2
- process.on("message", async ({ method, args }) => {
3
- try {
4
- if (method !== "AIGNE.load")
5
- throw new Error(`Unknown method: ${method}`);
6
- await AIGNE.load(...args);
7
- process.send?.({ method, status: "success" });
8
- }
9
- catch (error) {
10
- process.send?.({ method, status: "error", message: error.message });
11
- }
12
- process.exit(0);
13
- });
@@ -1,2 +0,0 @@
1
- import { AIGNE } from "@aigne/core";
2
- export declare function safeLoadAIGNE(...args: Parameters<typeof AIGNE.load>): Promise<ReturnType<typeof AIGNE.load>>;
@@ -1,27 +0,0 @@
1
- import { fork } from "node:child_process";
2
- import { dirname, join } from "node:path";
3
- import { fileURLToPath } from "node:url";
4
- import { AIGNE } from "@aigne/core";
5
- export async function safeLoadAIGNE(...args) {
6
- await new Promise((resolve, reject) => {
7
- const child = fork(join(dirname(fileURLToPath(import.meta.url)), "./load-aigne-worker.js"), {
8
- timeout: 600e3,
9
- });
10
- child.on("message", ({ method, message, status }) => {
11
- if (method !== "AIGNE.load")
12
- reject(new Error(`Unknown method: ${method}`));
13
- else if (status === "error")
14
- reject(new Error(`Failed to load AIGNE: ${message}`));
15
- else if (status === "success")
16
- resolve();
17
- });
18
- child.on("exit", (code) => {
19
- if (code !== 0)
20
- reject(new Error(`Child process exited with code ${code}`));
21
- else
22
- resolve();
23
- });
24
- child.send({ method: "AIGNE.load", args });
25
- });
26
- return AIGNE.load(...args);
27
- }