@aigne/cli 1.22.5 → 1.22.7

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,37 @@
1
1
  # Changelog
2
2
 
3
+ ## [1.22.7](https://github.com/AIGNE-io/aigne-framework/compare/cli-v1.22.6...cli-v1.22.7) (2025-07-14)
4
+
5
+
6
+ ### Bug Fixes
7
+
8
+ * **cli:** print pretty error message for cli ([#249](https://github.com/AIGNE-io/aigne-framework/issues/249)) ([d68e0f7](https://github.com/AIGNE-io/aigne-framework/commit/d68e0f7151259a05696de77d9f00793b6f5b36b2))
9
+ * **deps:** update deps to latest version ([#247](https://github.com/AIGNE-io/aigne-framework/issues/247)) ([3972f88](https://github.com/AIGNE-io/aigne-framework/commit/3972f887a9abff20c26da6b51c1071cbd54c0bf1))
10
+
11
+
12
+ ### Dependencies
13
+
14
+ * The following workspace dependencies were updated
15
+ * dependencies
16
+ * @aigne/agent-library bumped to 1.20.4
17
+ * @aigne/anthropic bumped to 0.8.1
18
+ * @aigne/bedrock bumped to 0.7.4
19
+ * @aigne/core bumped to 1.33.1
20
+ * @aigne/deepseek bumped to 0.6.4
21
+ * @aigne/gemini bumped to 0.7.1
22
+ * @aigne/observability-api bumped to 0.7.2
23
+ * @aigne/ollama bumped to 0.6.4
24
+ * @aigne/open-router bumped to 0.6.4
25
+ * @aigne/openai bumped to 0.9.1
26
+ * @aigne/xai bumped to 0.6.5
27
+
28
+ ## [1.22.6](https://github.com/AIGNE-io/aigne-framework/compare/cli-v1.22.5...cli-v1.22.6) (2025-07-10)
29
+
30
+
31
+ ### Bug Fixes
32
+
33
+ * **cli:** reduce excessive console output to improve cli performance ([#246](https://github.com/AIGNE-io/aigne-framework/issues/246)) ([4430504](https://github.com/AIGNE-io/aigne-framework/commit/4430504b643bba92775e5a908ca1c1153d90a402))
34
+
3
35
  ## [1.22.5](https://github.com/AIGNE-io/aigne-framework/compare/cli-v1.22.4...cli-v1.22.5) (2025-07-10)
4
36
 
5
37
 
package/dist/cli.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import { existsSync, realpathSync, statSync } from "node:fs";
3
+ import chalk from "chalk";
3
4
  import { config } from "dotenv-flow";
4
- import PrettyError from "pretty-error";
5
5
  import { createAIGNECommand } from "./commands/aigne.js";
6
6
  config({ silent: true });
7
7
  function getAIGNEFilePath() {
@@ -18,6 +18,7 @@ const aigneFilePath = getAIGNEFilePath();
18
18
  createAIGNECommand({ aigneFilePath })
19
19
  .parseAsync(["", "", ...process.argv.slice(aigneFilePath ? 3 : 2)])
20
20
  .catch((error) => {
21
- console.error(new PrettyError().render(error));
21
+ console.log(""); // Add an empty line for better readability
22
+ console.error(`${chalk.red("Error:")} ${error.message}`);
22
23
  process.exit(1);
23
24
  });
@@ -61,18 +61,18 @@ export function createRunCommand({ aigneFilePath } = {}) {
61
61
  if (options.entryAgent) {
62
62
  entryAgent = aigne.agents[options.entryAgent];
63
63
  if (!entryAgent) {
64
- console.error(`Agent "${options.entryAgent}" not found in ${path}`);
65
- console.log("Available agents:");
66
- for (const agent of aigne.agents) {
67
- console.log(`- ${agent.name}`);
68
- }
69
- throw new Error(`Agent "${options.entryAgent}" not found in ${path}`);
64
+ throw new Error(`\
65
+ Agent "${options.entryAgent}" not found in ${aigne.rootDir}
66
+
67
+ Available agents:
68
+ ${aigne.agents.map((agent) => ` - ${agent.name}`).join("\n")}
69
+ `);
70
70
  }
71
71
  }
72
72
  else {
73
73
  entryAgent = aigne.agents[0];
74
74
  if (!entryAgent)
75
- throw new Error(`No agents found in ${path}`);
75
+ throw new Error(`No any agent found in ${aigne.rootDir}`);
76
76
  }
77
77
  ctx.agent = entryAgent;
78
78
  },
@@ -80,6 +80,7 @@ export function createRunCommand({ aigneFilePath } = {}) {
80
80
  ], {
81
81
  rendererOptions: {
82
82
  collapseSubtasks: false,
83
+ showErrorMessage: false,
83
84
  timer: PRESET_TIMER,
84
85
  },
85
86
  }).run();
@@ -1,6 +1,9 @@
1
+ import assert from "node:assert";
1
2
  import { spawnSync } from "node:child_process";
2
3
  import { isAbsolute, resolve } from "node:path";
4
+ import { AIGNE } from "@aigne/core";
3
5
  import { Command } from "commander";
6
+ import { availableMemories, availableModels } from "../constants.js";
4
7
  export function createTestCommand({ aigneFilePath } = {}) {
5
8
  return new Command("test")
6
9
  .description("Run tests in the specified agents directory")
@@ -8,7 +11,12 @@ export function createTestCommand({ aigneFilePath } = {}) {
8
11
  .action(async (options) => {
9
12
  const path = aigneFilePath || options.path;
10
13
  const absolutePath = isAbsolute(path) ? path : resolve(process.cwd(), path);
11
- spawnSync("node", ["--test"], { cwd: absolutePath, stdio: "inherit" });
14
+ const aigne = await AIGNE.load(absolutePath, {
15
+ models: availableModels(),
16
+ memories: availableMemories,
17
+ });
18
+ assert(aigne.rootDir);
19
+ spawnSync("node", ["--test"], { cwd: aigne.rootDir, stdio: "inherit" });
12
20
  })
13
21
  .showHelpAfterError(true)
14
22
  .showSuggestionAfterError(true);
@@ -1,3 +1,4 @@
1
+ import { type InspectOptions } from "node:util";
1
2
  import { type Agent, type Context, type ContextUsage, type Message } from "@aigne/core";
2
3
  import { promiseWithResolvers } from "@aigne/core/utils/promise.js";
3
4
  import { type Listr } from "@aigne/listr2";
@@ -26,8 +27,13 @@ export declare class TerminalTracer {
26
27
  }): string;
27
28
  private marked;
28
29
  get outputKey(): string;
29
- formatRequest(agent: Agent, _context: Context, m?: Message): string | undefined;
30
- formatResult(agent: Agent, context: Context, m?: Message): string;
30
+ formatRequest(agent: Agent, _context: Context, m?: Message, { running }?: {
31
+ running?: boolean | undefined;
32
+ }): string | undefined;
33
+ formatResult(agent: Agent, context: Context, m?: Message, { running }?: {
34
+ running?: boolean | undefined;
35
+ }): string;
36
+ protected runningInspectOptions: InspectOptions;
31
37
  }
32
38
  type Task = ReturnType<typeof promiseWithResolvers<void>> & {
33
39
  listr: ReturnType<typeof promiseWithResolvers<{
@@ -22,8 +22,10 @@ export class TerminalTracer {
22
22
  await this.context.observer?.serve();
23
23
  const context = this.context.newContext({ reset: true });
24
24
  const listr = new AIGNEListr({
25
- formatRequest: () => this.options.printRequest ? this.formatRequest(agent, context, input) : undefined,
26
- formatResult: (result) => [this.formatResult(agent, context, result)].filter(Boolean),
25
+ formatRequest: (options) => this.options.printRequest
26
+ ? this.formatRequest(agent, context, input, options)
27
+ : undefined,
28
+ formatResult: (result, options) => [this.formatResult(agent, context, result, options)].filter(Boolean),
27
29
  }, [], { concurrent: true });
28
30
  const onAgentStarted = async ({ contextId, parentContextId, agent, timestamp, }) => {
29
31
  const task = {
@@ -135,7 +137,7 @@ export class TerminalTracer {
135
137
  get outputKey() {
136
138
  return this.options.outputKey || DEFAULT_OUTPUT_KEY;
137
139
  }
138
- formatRequest(agent, _context, m = {}) {
140
+ formatRequest(agent, _context, m = {}, { running = false } = {}) {
139
141
  if (!logger.enabled(LogLevel.INFO))
140
142
  return;
141
143
  const prefix = `${chalk.grey(figures.pointer)} 💬 `;
@@ -143,10 +145,12 @@ export class TerminalTracer {
143
145
  const msg = inputKey ? m[inputKey] : undefined;
144
146
  const message = inputKey ? omit(m, inputKey) : m;
145
147
  const text = msg && typeof msg === "string" ? this.marked.parse(msg, { async: false }).trim() : undefined;
146
- const json = Object.keys(message).length > 0 ? inspect(message, { colors: true }) : undefined;
148
+ const json = Object.keys(message).length > 0
149
+ ? inspect(message, { colors: true, ...(running ? this.runningInspectOptions : undefined) })
150
+ : undefined;
147
151
  return [prefix, [text, json].filter(Boolean).join(EOL)].join(" ");
148
152
  }
149
- formatResult(agent, context, m = {}) {
153
+ formatResult(agent, context, m = {}, { running = false } = {}) {
150
154
  const { isTTY } = process.stdout;
151
155
  const outputKey = this.outputKey || (agent instanceof AIAgent ? agent.outputKey : undefined);
152
156
  const prefix = logger.enabled(LogLevel.INFO)
@@ -159,7 +163,13 @@ export class TerminalTracer {
159
163
  ? this.marked.parse(msg, { async: false }).trim()
160
164
  : msg
161
165
  : undefined;
162
- const json = Object.keys(message).length > 0 ? inspect(message, { colors: isTTY }) : undefined;
166
+ const json = Object.keys(message).length > 0
167
+ ? inspect(message, { colors: isTTY, ...(running ? this.runningInspectOptions : undefined) })
168
+ : undefined;
163
169
  return [prefix, text, json].filter(Boolean).join(EOL);
164
170
  }
171
+ runningInspectOptions = {
172
+ maxArrayLength: 3,
173
+ maxStringLength: 200,
174
+ };
165
175
  }
@@ -6,14 +6,18 @@ export type AIGNEListrTaskWrapper = ListrTaskWrapper<unknown, typeof AIGNEListrR
6
6
  export declare class AIGNEListr extends Listr<object, typeof AIGNEListrRenderer, typeof AIGNEListrFallbackRenderer> {
7
7
  myOptions: {
8
8
  formatRequest: () => string | undefined;
9
- formatResult: (result: Message) => string[];
9
+ formatResult: (result: Message, options?: {
10
+ running?: boolean;
11
+ }) => string[];
10
12
  };
11
13
  private result;
12
14
  private logs;
13
15
  private spinner;
14
16
  constructor(myOptions: {
15
17
  formatRequest: () => string | undefined;
16
- formatResult: (result: Message) => string[];
18
+ formatResult: (result: Message, options?: {
19
+ running?: boolean;
20
+ }) => string[];
17
21
  }, ...[task, options, parentTask]: ConstructorParameters<typeof Listr<object, typeof AIGNEListrRenderer, typeof AIGNEListrFallbackRenderer>>);
18
22
  run(stream: () => PromiseOrValue<AgentResponseStream<Message>>): Promise<Message>;
19
23
  private extractStream;
@@ -21,7 +25,9 @@ export declare class AIGNEListr extends Listr<object, typeof AIGNEListrRenderer,
21
25
  export interface AIGNEListrRendererOptions extends ListrDefaultRendererOptions {
22
26
  aigne?: {
23
27
  getStdoutLogs?: () => string[];
24
- getBottomBarLogs?: () => string[];
28
+ getBottomBarLogs?: (options?: {
29
+ running?: boolean;
30
+ }) => string[];
25
31
  };
26
32
  }
27
33
  export declare class AIGNEListrRenderer extends DefaultRenderer {
@@ -14,8 +14,8 @@ export class AIGNEListr extends Listr {
14
14
  getStdoutLogs: () => {
15
15
  return this.logs.splice(0);
16
16
  },
17
- getBottomBarLogs: () => {
18
- return this.myOptions.formatResult(this.result);
17
+ getBottomBarLogs: (options) => {
18
+ return this.myOptions.formatResult(this.result, options);
19
19
  },
20
20
  };
21
21
  super(task, {
@@ -78,20 +78,16 @@ export class AIGNEListrRenderer extends DefaultRenderer {
78
78
  ...DefaultRenderer.rendererOptions,
79
79
  };
80
80
  get _updater() {
81
- // @ts-ignore `updater` is a private property
82
- return this.updater;
81
+ return this["updater"];
83
82
  }
84
83
  get _logger() {
85
- // @ts-ignore `logger` is a private property
86
- return this.logger;
84
+ return this["logger"];
87
85
  }
88
86
  get _options() {
89
- // @ts-ignore `options` is a private property
90
- return this.options;
87
+ return this["options"];
91
88
  }
92
89
  get _spinner() {
93
- // @ts-ignore `spinner` is a private property
94
- return this.spinner;
90
+ return this["spinner"];
95
91
  }
96
92
  update() {
97
93
  this._updater(this.create({ running: true }));
@@ -102,12 +98,25 @@ export class AIGNEListrRenderer extends DefaultRenderer {
102
98
  this._updater.clear();
103
99
  this._logger.toStdout(logs.join(EOL));
104
100
  }
105
- const tasks = [super.create(options)];
106
- const bottomBar = this._options.aigne?.getBottomBarLogs?.();
101
+ let tasks = super.create(options);
102
+ const bottomBar = this._options.aigne?.getBottomBarLogs?.({ running });
107
103
  if (bottomBar?.length) {
108
- tasks.push([...bottomBar, running ? this._spinner.fetch() : ""].map((i) => this._wrap(i)).join(EOL));
104
+ tasks += EOL.repeat(2);
105
+ const output = [...bottomBar, running ? this._spinner.fetch() : ""]
106
+ .map((i) => this._wrap(i))
107
+ .join(EOL);
108
+ // If the task is not running, we show all lines
109
+ if (!running) {
110
+ tasks += output;
111
+ }
112
+ // For running tasks, we only show the last few lines
113
+ else {
114
+ const { rows } = process.stdout;
115
+ const lines = rows - tasks.split(EOL).length - 2;
116
+ tasks += output.split(EOL).slice(-Math.max(4, lines)).join(EOL);
117
+ }
109
118
  }
110
- return tasks.join(EOL.repeat(2));
119
+ return tasks;
111
120
  }
112
121
  _wrap(str) {
113
122
  return wrap(str, process.stdout.columns ?? 80, {
@@ -121,12 +130,10 @@ export class AIGNEListrFallbackRenderer extends SimpleRenderer {
121
130
  ...SimpleRenderer.rendererOptions,
122
131
  };
123
132
  get _logger() {
124
- // @ts-ignore `logger` is a private property
125
- return this.logger;
133
+ return this["logger"];
126
134
  }
127
135
  get _options() {
128
- // @ts-ignore `options` is a private property
129
- return this.options;
136
+ return this["options"];
130
137
  }
131
138
  end() {
132
139
  const logs = [this._options.aigne?.getStdoutLogs?.(), this._options.aigne?.getBottomBarLogs?.()]
@@ -9,8 +9,8 @@ import { AIGNE, DEFAULT_OUTPUT_KEY, readAllString, UserAgent, } from "@aigne/cor
9
9
  import { loadModel } from "@aigne/core/loader/index.js";
10
10
  import { getLevelFromEnv, LogLevel, logger } from "@aigne/core/utils/logger.js";
11
11
  import { isEmpty, isNonNullable, tryOrThrow, } from "@aigne/core/utils/type-utils.js";
12
+ import chalk from "chalk";
12
13
  import { Command } from "commander";
13
- import PrettyError from "pretty-error";
14
14
  import { parse } from "yaml";
15
15
  import { ZodError, ZodObject, z } from "zod";
16
16
  import { availableModels } from "../constants.js";
@@ -137,7 +137,7 @@ export async function runWithAIGNE(agentCreator, { argv = process.argv, chatLoop
137
137
  })
138
138
  .parseAsync(argv)
139
139
  .catch((error) => {
140
- console.error(new PrettyError().render(error));
140
+ console.error(`${chalk.red("Error:")} ${error.message}`);
141
141
  process.exit(1);
142
142
  });
143
143
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aigne/cli",
3
- "version": "1.22.5",
3
+ "version": "1.22.7",
4
4
  "description": "cli for AIGNE framework",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -36,9 +36,9 @@
36
36
  },
37
37
  "dependencies": {
38
38
  "@aigne/listr2": "^1.0.10",
39
- "@aigne/marked-terminal": "^7.3.1",
40
- "@modelcontextprotocol/sdk": "^1.13.3",
41
- "@smithy/node-http-handler": "^4.0.6",
39
+ "@aigne/marked-terminal": "^7.3.2",
40
+ "@modelcontextprotocol/sdk": "^1.15.0",
41
+ "@smithy/node-http-handler": "^4.1.0",
42
42
  "chalk": "^5.4.1",
43
43
  "commander": "^14.0.0",
44
44
  "detect-port": "^2.1.0",
@@ -50,30 +50,29 @@
50
50
  "inquirer": "^12.7.0",
51
51
  "marked": "^16.0.0",
52
52
  "prettier": "^3.6.2",
53
- "pretty-error": "^4.0.0",
54
53
  "tar": "^7.4.3",
55
54
  "wrap-ansi": "^9.0.0",
56
55
  "yaml": "^2.8.0",
57
56
  "zod": "^3.25.67",
58
- "@aigne/agent-library": "^1.20.3",
59
- "@aigne/anthropic": "^0.8.0",
60
- "@aigne/bedrock": "^0.7.3",
61
- "@aigne/core": "^1.33.0",
62
- "@aigne/gemini": "^0.7.0",
63
- "@aigne/deepseek": "^0.6.3",
64
- "@aigne/ollama": "^0.6.3",
65
- "@aigne/open-router": "^0.6.3",
66
- "@aigne/observability-api": "^0.7.1",
67
- "@aigne/openai": "^0.9.0",
68
- "@aigne/xai": "^0.6.4"
57
+ "@aigne/agent-library": "^1.20.4",
58
+ "@aigne/bedrock": "^0.7.4",
59
+ "@aigne/anthropic": "^0.8.1",
60
+ "@aigne/core": "^1.33.1",
61
+ "@aigne/deepseek": "^0.6.4",
62
+ "@aigne/observability-api": "^0.7.2",
63
+ "@aigne/ollama": "^0.6.4",
64
+ "@aigne/open-router": "^0.6.4",
65
+ "@aigne/openai": "^0.9.1",
66
+ "@aigne/xai": "^0.6.5",
67
+ "@aigne/gemini": "^0.7.1"
69
68
  },
70
69
  "devDependencies": {
71
70
  "@types/archiver": "^6.0.3",
72
- "@types/bun": "^1.2.17",
71
+ "@types/bun": "^1.2.18",
73
72
  "@types/express": "^5.0.3",
74
73
  "@types/glob": "^9.0.0",
75
74
  "@types/gradient-string": "^1.1.6",
76
- "@types/node": "^24.0.10",
75
+ "@types/node": "^24.0.12",
77
76
  "archiver": "^7.0.1",
78
77
  "npm-run-all": "^4.1.5",
79
78
  "rimraf": "^6.0.1",