@aigne/cli 1.49.0-beta.10 → 1.49.0-beta.5

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,105 +1,12 @@
1
1
  # Changelog
2
2
 
3
- ## [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)
4
-
5
-
6
- ### Bug Fixes
7
-
8
- * **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))
9
-
10
- ## [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)
11
-
12
-
13
- ### Features
14
-
15
- * **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))
16
-
17
-
18
- ### Bug Fixes
19
-
20
- * **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))
21
- * **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))
22
-
23
-
24
- ### Dependencies
25
-
26
- * The following workspace dependencies were updated
27
- * dependencies
28
- * @aigne/agent-library bumped to 1.21.46-beta.9
29
- * @aigne/agentic-memory bumped to 1.0.46-beta.9
30
- * @aigne/aigne-hub bumped to 0.10.0-beta.9
31
- * @aigne/core bumped to 1.61.0-beta.8
32
- * @aigne/default-memory bumped to 1.2.9-beta.9
33
- * @aigne/observability-api bumped to 0.11.0-beta.1
34
- * @aigne/openai bumped to 0.16.0-beta.9
35
- * devDependencies
36
- * @aigne/test-utils bumped to 0.5.53-beta.8
37
-
38
- ## [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)
39
-
40
-
41
- ### Dependencies
42
-
43
- * The following workspace dependencies were updated
44
- * dependencies
45
- * @aigne/agent-library bumped to 1.21.46-beta.8
46
- * @aigne/agentic-memory bumped to 1.0.46-beta.8
47
- * @aigne/aigne-hub bumped to 0.10.0-beta.8
48
- * @aigne/core bumped to 1.61.0-beta.7
49
- * @aigne/default-memory bumped to 1.2.9-beta.8
50
- * @aigne/openai bumped to 0.16.0-beta.8
51
- * devDependencies
52
- * @aigne/test-utils bumped to 0.5.53-beta.7
53
-
54
- ## [1.49.0-beta.7](https://github.com/AIGNE-io/aigne-framework/compare/cli-v1.49.0-beta.6...cli-v1.49.0-beta.7) (2025-09-26)
55
-
56
-
57
- ### Bug Fixes
58
-
59
- * **cli:** options.prompts should always available ([44ca0a6](https://github.com/AIGNE-io/aigne-framework/commit/44ca0a65d910fbd327b89d2f3dfe38ab7d1be7df))
60
-
61
-
62
- ### Dependencies
63
-
64
- * The following workspace dependencies were updated
65
- * dependencies
66
- * @aigne/agent-library bumped to 1.21.46-beta.7
67
- * @aigne/agentic-memory bumped to 1.0.46-beta.7
68
- * @aigne/aigne-hub bumped to 0.10.0-beta.7
69
- * @aigne/core bumped to 1.61.0-beta.6
70
- * @aigne/default-memory bumped to 1.2.9-beta.7
71
- * @aigne/openai bumped to 0.16.0-beta.7
72
- * devDependencies
73
- * @aigne/test-utils bumped to 0.5.53-beta.6
74
-
75
- ## [1.49.0-beta.6](https://github.com/AIGNE-io/aigne-framework/compare/cli-v1.49.0-beta.5...cli-v1.49.0-beta.6) (2025-09-25)
76
-
77
-
78
- ### Features
79
-
80
- * **blocklet:** add token and cost summary for tracing list ([#543](https://github.com/AIGNE-io/aigne-framework/issues/543)) ([5e78919](https://github.com/AIGNE-io/aigne-framework/commit/5e789199b8183cf9c48339ec8163faec001ca64c))
81
-
82
-
83
- ### Dependencies
84
-
85
- * The following workspace dependencies were updated
86
- * dependencies
87
- * @aigne/agent-library bumped to 1.21.46-beta.6
88
- * @aigne/agentic-memory bumped to 1.0.46-beta.6
89
- * @aigne/aigne-hub bumped to 0.10.0-beta.6
90
- * @aigne/core bumped to 1.61.0-beta.5
91
- * @aigne/default-memory bumped to 1.2.9-beta.6
92
- * @aigne/observability-api bumped to 0.11.0-beta
93
- * @aigne/openai bumped to 0.16.0-beta.6
94
- * devDependencies
95
- * @aigne/test-utils bumped to 0.5.53-beta.5
96
-
97
3
  ## [1.49.0-beta.5](https://github.com/AIGNE-io/aigne-framework/compare/cli-v1.48.4-beta.5...cli-v1.49.0-beta.5) (2025-09-25)
98
4
 
99
5
 
100
6
  ### Features
101
7
 
102
8
  * **cli:** add new eval command for assessing AI agent performance using custom datasets ([#535](https://github.com/AIGNE-io/aigne-framework/issues/535)) ([9da967b](https://github.com/AIGNE-io/aigne-framework/commit/9da967b01ef9eeee4c5e1242934cf08e14815753))
9
+ * **cli:** add new eval command for assessing AI agent performance using custom datasets ([#535](https://github.com/AIGNE-io/aigne-framework/issues/535)) ([9da967b](https://github.com/AIGNE-io/aigne-framework/commit/9da967b01ef9eeee4c5e1242934cf08e14815753))
103
10
 
104
11
 
105
12
  ### Dependencies
@@ -1,41 +1,27 @@
1
+ import type { Agent, AIGNE, Message } from "@aigne/core";
1
2
  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: AgentInChildProcess;
7
+ agent: Agent;
8
8
  }) => CommandModule<unknown, AgentRunCommonOptions>;
9
- interface LoadApplicationOptions {
10
- packageName: string;
9
+ export declare function invokeCLIAgentFromDir(options: {
11
10
  dir: string;
12
- install?: boolean;
13
- }
14
- interface LoadApplicationResult {
15
- aigne: LoadAIGNEInChildProcessResult;
16
- version: string;
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;
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;
30
18
  }): Promise<{
31
- url: string;
19
+ aigne: AIGNE;
20
+ dir: string;
32
21
  version: string;
22
+ isCache?: boolean;
33
23
  }>;
34
- export declare function getNpmTgzInfo(name: string, { version, beta }?: {
35
- version?: string;
36
- beta?: boolean;
37
- }): Promise<{
24
+ export declare function getNpmTgzInfo(name: string): Promise<{
38
25
  version: string;
39
- url: string;
26
+ url: any;
40
27
  }>;
41
- export {};
@@ -1,14 +1,16 @@
1
+ import assert from "node:assert";
1
2
  import { spawn } from "node:child_process";
2
3
  import { mkdir, readFile, rm, stat, writeFile } from "node:fs/promises";
3
4
  import { homedir } from "node:os";
4
5
  import { join } from "node:path";
5
6
  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 { runAIGNEInChildProcess, } from "../utils/workers/run-aigne-in-child-process.js";
11
- import { withAgentInputSchema } from "../utils/yargs.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";
12
14
  import { serveMCPServerFromDir } from "./serve-mcp.js";
13
15
  const NPM_PACKAGE_CACHE_TIME_MS = 1000 * 60 * 60 * 24; // 1 day
14
16
  /**
@@ -21,13 +23,11 @@ function shouldUseBetaApps() {
21
23
  const builtinApps = [
22
24
  {
23
25
  name: "doc-smith",
24
- packageName: "@aigne/doc-smith",
25
26
  describe: "Generate and maintain project docs — powered by agents.",
26
27
  aliases: ["docsmith", "doc"],
27
28
  },
28
29
  {
29
30
  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,28 +38,30 @@ export function createAppCommands() {
38
38
  describe: app.describe,
39
39
  aliases: app.aliases,
40
40
  builder: async (yargs) => {
41
- const dir = join(homedir(), ".aigne", "registry.npmjs.org", app.packageName);
42
- const { aigne, version } = await loadApplication({
43
- dir,
44
- packageName: app.packageName,
45
- install: true,
41
+ const { aigne, dir, version, isCache } = await loadApplication({
42
+ name: app.name,
46
43
  });
47
- if (aigne.cli?.chat) {
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,
52
+ dir,
53
+ isLatest: !isCache,
54
+ version,
55
+ }));
56
+ if (aigne.cli.chat) {
48
57
  yargs.command({
49
58
  ...agentCommandModule({ dir, agent: aigne.cli.chat }),
50
59
  command: "$0",
51
60
  });
52
61
  }
53
- for (const agent of aigne.cli?.agents ?? []) {
62
+ for (const agent of aigne.cli.agents) {
54
63
  yargs.command(agentCommandModule({ dir, agent }));
55
64
  }
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 }));
63
65
  yargs.version(`${app.name} v${version}`).alias("version", "v");
64
66
  return yargs.demandCommand();
65
67
  },
@@ -90,39 +92,18 @@ const serveMcpCommandModule = ({ name, dir, }) => ({
90
92
  await serveMCPServerFromDir({ ...options, dir });
91
93
  },
92
94
  });
93
- const upgradeCommandModule = ({ packageName, dir, }) => ({
95
+ const upgradeCommandModule = ({ name, dir, isLatest, version, }) => ({
94
96
  command: "upgrade",
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;
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
+ }
124
105
  }
125
- console.log(`\n✅ ${packageName} is already at the latest version (${app.version})`);
106
+ console.log(`\n✅ ${name} is already at the latest version (${version})`);
126
107
  },
127
108
  });
128
109
  export const agentCommandModule = ({ dir, agent, }) => {
@@ -130,76 +111,76 @@ export const agentCommandModule = ({ dir, agent, }) => {
130
111
  command: agent.name,
131
112
  aliases: agent.alias || [],
132
113
  describe: agent.description || "",
133
- builder: async (yargs) => {
134
- return withAgentInputSchema(yargs, { inputSchema: jsonSchemaToZod(agent.inputSchema) });
135
- },
114
+ builder: async (yargs) => withAgentInputSchema(yargs, agent),
136
115
  handler: async (options) => {
137
116
  if (options.logLevel)
138
117
  logger.level = options.logLevel;
139
- await runAIGNEInChildProcess("invokeCLIAgentFromDir", {
140
- dir,
141
- agent: agent.name,
142
- input: options,
143
- });
118
+ await invokeCLIAgentFromDir({ dir, agent: agent.name, input: options });
144
119
  process.exit(0);
145
120
  },
146
121
  };
147
122
  };
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);
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);
154
155
  });
155
156
  if (aigne) {
156
- return { aigne, version: check.version, isCache: true };
157
+ return {
158
+ aigne,
159
+ dir,
160
+ version: check.version,
161
+ isCache: true,
162
+ };
157
163
  }
164
+ check = undefined;
158
165
  }
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([
166
+ const result = await new Listr([
189
167
  {
190
- title: `Fetching ${packageName} metadata`,
168
+ title: `Fetching ${name} metadata`,
191
169
  task: async (ctx, task) => {
192
- if (beta) {
193
- task.title = `Fetching ${packageName} metadata (using beta version)`;
194
- }
195
- const info = await getNpmTgzInfo(packageName, { beta, version });
170
+ const info = await getNpmTgzInfo(name);
196
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)`;
175
+ }
197
176
  },
198
177
  },
199
178
  {
200
- title: `Downloading ${packageName}`,
179
+ title: `Downloading ${name}`,
180
+ skip: (ctx) => ctx.version === check?.version,
201
181
  task: async (ctx, task) => {
202
- task.title = `Downloading ${packageName} (v${ctx.version})`;
182
+ task.title = `Downloading ${name}(v${ctx.version})`;
183
+ await rm(dir, { force: true, recursive: true });
203
184
  await mkdir(dir, { recursive: true });
204
185
  await downloadAndExtract(ctx.url, dir, { strip: 1 });
205
186
  },
@@ -214,7 +195,6 @@ export async function installApp({ dir, packageName, beta, version, }) {
214
195
  task.output = last;
215
196
  },
216
197
  });
217
- await writeInstallationMetadata(dir, { installedAt: Date.now() });
218
198
  },
219
199
  },
220
200
  ], {
@@ -224,6 +204,25 @@ export async function installApp({ dir, packageName, beta, version, }) {
224
204
  timer: PRESET_TIMER,
225
205
  },
226
206
  }).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 };
227
226
  }
228
227
  async function installDependencies(dir, { log } = {}) {
229
228
  await new Promise((resolve, reject) => {
@@ -251,20 +250,16 @@ async function installDependencies(dir, { log } = {}) {
251
250
  }
252
251
  });
253
252
  });
253
+ await writeFile(join(dir, ".aigne-cli.json"), JSON.stringify({ installedAt: Date.now() }, null, 2));
254
254
  }
255
- export async function getNpmTgzInfo(name, { version, beta } = {}) {
255
+ export async function getNpmTgzInfo(name) {
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();
260
261
  let targetVersion;
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) {
262
+ if (useBeta && data["dist-tags"].beta) {
268
263
  // Use beta version if available and beta flag is set
269
264
  targetVersion = data["dist-tags"].beta;
270
265
  }
@@ -10,7 +10,6 @@ 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";
14
13
  import { agentCommandModule } from "./app.js";
15
14
  export function createRunCommand({ aigneFilePath, } = {}) {
16
15
  return {
@@ -42,14 +41,14 @@ export function createRunCommand({ aigneFilePath, } = {}) {
42
41
  const subYargs = yargs().scriptName("").usage("aigne run <path> <agent> [...options]");
43
42
  if (aigne.cli.chat) {
44
43
  subYargs.command({
45
- ...agentCommandModule({ dir: path, agent: serializeAgent(aigne.cli.chat) }),
44
+ ...agentCommandModule({ dir: path, agent: aigne.cli.chat }),
46
45
  command: "$0",
47
46
  });
48
47
  }
49
48
  // Allow user to run all of agents in the AIGNE instances
50
49
  const allAgents = flat(aigne.cli.agents, aigne.agents, aigne.skills, aigne.cli.chat, aigne.mcpServer.agents);
51
50
  for (const agent of allAgents) {
52
- subYargs.command(agentCommandModule({ dir: path, agent: serializeAgent(agent) }));
51
+ subYargs.command(agentCommandModule({ dir: path, agent }));
53
52
  }
54
53
  const argv = process.argv.slice(aigneFilePath ? 3 : 2);
55
54
  if (argv[0] === "run")
@@ -103,7 +102,7 @@ async function loadApplication(path) {
103
102
  }
104
103
  // Load env files in the aigne directory
105
104
  config({ path: dir, silent: true });
106
- const aigne = await loadAIGNE({ path: dir, printTips: false });
105
+ const aigne = await loadAIGNE({ path: dir });
107
106
  return { aigne, path: dir };
108
107
  }
109
108
  async function downloadPackage(url, cacheDir) {
@@ -36,14 +36,13 @@ export class TerminalTracer {
36
36
  const collapsedMap = new Map();
37
37
  const hideContextIds = new Set();
38
38
  const onStart = async ({ context, agent, ...event }) => {
39
- const result = { options: { prompts: this.proxiedPrompts } };
40
39
  if (agent instanceof UserAgent)
41
- return result;
40
+ return;
42
41
  if (agent.taskRenderMode === "hide") {
43
42
  hideContextIds.add(context.id);
44
- return result;
43
+ return;
45
44
  }
46
- if (agent.taskRenderMode === "collapse") {
45
+ else if (agent.taskRenderMode === "collapse") {
47
46
  collapsedMap.set(context.id, {
48
47
  ancestor: { contextId: context.id },
49
48
  usage: newEmptyContextUsage(),
@@ -53,12 +52,12 @@ export class TerminalTracer {
53
52
  if (context.parentId) {
54
53
  if (hideContextIds.has(context.parentId)) {
55
54
  hideContextIds.add(context.id);
56
- return result;
55
+ return;
57
56
  }
58
57
  const collapsed = collapsedMap.get(context.parentId);
59
58
  if (collapsed) {
60
59
  collapsedMap.set(context.id, collapsed);
61
- return result;
60
+ return;
62
61
  }
63
62
  }
64
63
  const contextId = context.id;
@@ -93,7 +92,7 @@ export class TerminalTracer {
93
92
  else {
94
93
  listr.add(listrTask);
95
94
  }
96
- return result;
95
+ return { options: { prompts: this.proxiedPrompts } };
97
96
  };
98
97
  const onSuccess = async ({ context, agent, output, ...event }) => {
99
98
  const contextId = context.id;
@@ -21,33 +21,6 @@ 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
- }
51
24
  export class BaseReporter {
52
25
  name = "base";
53
26
  async report(_report) {
@@ -70,6 +43,7 @@ export class BaseReporter {
70
43
  width: 40,
71
44
  value: r.expected ? JSON.stringify(r.expected) : "-",
72
45
  },
46
+ { header: "Error", key: "Error", width: 20, value: r.error ?? "-" },
73
47
  {
74
48
  header: "Evaluations",
75
49
  key: "Evaluations",
@@ -82,7 +56,6 @@ export class BaseReporter {
82
56
  width: 20,
83
57
  value: r.evaluations.map((e) => `${e.rating}`).join(", "),
84
58
  },
85
- { header: "Error", key: "Error", width: 20, value: r.error ?? "-" },
86
59
  {
87
60
  header: "Reason",
88
61
  key: "Reason",
@@ -167,10 +140,18 @@ export class ConsoleReporter extends BaseReporter {
167
140
  if (!list.length)
168
141
  return;
169
142
  console.log("\n=== 📋 Detailed Results ===");
170
- const pages = renderPagedTable(list, { maxCols: 5, chars });
171
- for (const page of pages) {
172
- console.log(page);
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));
173
153
  }
154
+ console.log(detailTable.toString());
174
155
  const failed = report.results.filter((r) => r.error);
175
156
  if (failed.length) {
176
157
  console.log(chalk.red("\n=== ❌ Failed Cases ==="));
@@ -7,8 +7,7 @@ export interface RunOptions extends AgentRunCommonOptions {
7
7
  cacheDir?: string;
8
8
  aigneHubUrl?: string;
9
9
  }
10
- export declare function loadAIGNE({ path, modelOptions, printTips, }: {
10
+ export declare function loadAIGNE({ path, modelOptions, }: {
11
11
  path?: string;
12
12
  modelOptions?: ChatModelInputOptions & LoadCredentialOptions;
13
- printTips?: boolean;
14
13
  }): Promise<AIGNE<import("@aigne/core").UserContext>>;
@@ -8,6 +8,9 @@ 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;
11
14
  const credential = await model.credential;
12
15
  const lines = [`${chalk.cyan("Provider")}: ${chalk.green(model.name.replace("ChatModel", ""))}`];
13
16
  if (credential?.model) {
@@ -22,7 +25,7 @@ async function printChatModelInfoBox(model) {
22
25
  console.log(boxen(lines.join("\n"), { padding: 1, borderStyle: "classic", borderColor: "cyan" }));
23
26
  console.log("");
24
27
  }
25
- export async function loadAIGNE({ path, modelOptions, printTips = true, }) {
28
+ export async function loadAIGNE({ path, modelOptions, }) {
26
29
  let aigne;
27
30
  if (path) {
28
31
  aigne = await AIGNE.load(path, {
@@ -39,12 +42,9 @@ export async function loadAIGNE({ path, modelOptions, printTips = true, }) {
39
42
  const chatModel = await loadChatModel({ ...modelOptions });
40
43
  aigne = new AIGNE({ model: chatModel });
41
44
  }
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
- }
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);
48
48
  }
49
49
  return aigne;
50
50
  }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,13 @@
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
+ });
@@ -0,0 +1,2 @@
1
+ import { AIGNE } from "@aigne/core";
2
+ export declare function safeLoadAIGNE(...args: Parameters<typeof AIGNE.load>): Promise<ReturnType<typeof AIGNE.load>>;
@@ -0,0 +1,27 @@
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
+ }
@@ -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: Pick<Agent, "inputSchema">): Argv<{
53
+ export declare function withAgentInputSchema(yargs: Argv, agent: Agent): 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.10",
3
+ "version": "1.49.0-beta.5",
4
4
  "description": "Your command center for agent development",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -45,7 +45,6 @@
45
45
  }
46
46
  },
47
47
  "dependencies": {
48
- "@aigne/json-schema-to-zod": "^1.3.3",
49
48
  "@aigne/listr2": "^1.0.10",
50
49
  "@aigne/marked-terminal": "^7.3.2",
51
50
  "@fast-csv/format": "^5.0.5",
@@ -83,14 +82,13 @@
83
82
  "yargs": "^18.0.0",
84
83
  "yoctocolors-cjs": "^2.1.3",
85
84
  "zod": "^3.25.67",
86
- "zod-to-json-schema": "^3.24.6",
87
- "@aigne/agent-library": "^1.21.46-beta.9",
88
- "@aigne/agentic-memory": "^1.0.46-beta.9",
89
- "@aigne/core": "^1.61.0-beta.8",
90
- "@aigne/default-memory": "^1.2.9-beta.9",
91
- "@aigne/aigne-hub": "^0.10.0-beta.9",
92
- "@aigne/observability-api": "^0.11.0-beta.1",
93
- "@aigne/openai": "^0.16.0-beta.9"
85
+ "@aigne/agent-library": "^1.21.46-beta.5",
86
+ "@aigne/agentic-memory": "^1.0.46-beta.5",
87
+ "@aigne/aigne-hub": "^0.10.0-beta.5",
88
+ "@aigne/core": "^1.61.0-beta.4",
89
+ "@aigne/default-memory": "^1.2.9-beta.5",
90
+ "@aigne/observability-api": "^0.10.5-beta",
91
+ "@aigne/openai": "^0.16.0-beta.5"
94
92
  },
95
93
  "devDependencies": {
96
94
  "@inquirer/testing": "^2.1.50",
@@ -107,7 +105,7 @@
107
105
  "rimraf": "^6.0.1",
108
106
  "typescript": "^5.9.2",
109
107
  "ufo": "^1.6.1",
110
- "@aigne/test-utils": "^0.5.53-beta.8"
108
+ "@aigne/test-utils": "^0.5.53-beta.4"
111
109
  },
112
110
  "scripts": {
113
111
  "lint": "tsc --noEmit",
@@ -1,18 +0,0 @@
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>;
@@ -1,72 +0,0 @@
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
- }
@@ -1,14 +0,0 @@
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]>>;
@@ -1,30 +0,0 @@
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
- }