@aigne/cli 1.35.0 → 1.36.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,43 @@
1
1
  # Changelog
2
2
 
3
+ ## [1.36.0](https://github.com/AIGNE-io/aigne-framework/compare/cli-v1.35.1...cli-v1.36.0) (2025-08-14)
4
+
5
+
6
+ ### Features
7
+
8
+ * **core:** add priority support for agent hooks ([#358](https://github.com/AIGNE-io/aigne-framework/issues/358)) ([9196141](https://github.com/AIGNE-io/aigne-framework/commit/91961413aea171048a6afae87ffc8dc53e20fca8))
9
+
10
+
11
+ ### Bug Fixes
12
+
13
+ * **cli:** alwasy print useage information after agent processed ([58da143](https://github.com/AIGNE-io/aigne-framework/commit/58da143329a6748005c7812723c6b3f986e07e08))
14
+ * **cli:** clean app folder before upgrade ([#362](https://github.com/AIGNE-io/aigne-framework/issues/362)) ([0553c50](https://github.com/AIGNE-io/aigne-framework/commit/0553c504f5d0a446397bdccb20c91921cc618167))
15
+ * **cli:** improve feedback in AIGNE Hub commands ([#361](https://github.com/AIGNE-io/aigne-framework/issues/361)) ([ff29a4b](https://github.com/AIGNE-io/aigne-framework/commit/ff29a4b3c7bb828ef9894482586c8c4df41a2122))
16
+ * **cli:** improve markdown terminal theme styling ([#360](https://github.com/AIGNE-io/aigne-framework/issues/360)) ([dc9efbb](https://github.com/AIGNE-io/aigne-framework/commit/dc9efbb477e6792f51090c4fdd6e129e90821263))
17
+ * **cli:** log only once in loadAIGNE ([#357](https://github.com/AIGNE-io/aigne-framework/issues/357)) ([6e6d968](https://github.com/AIGNE-io/aigne-framework/commit/6e6d96814fbc87f210522ae16daf94c1f84f311a))
18
+ * **cli:** prevent multiple simultaneous buy credits prompts ([#363](https://github.com/AIGNE-io/aigne-framework/issues/363)) ([b8fb459](https://github.com/AIGNE-io/aigne-framework/commit/b8fb459261fe327bcc9bfb4d163e66863cb797ec))
19
+
20
+
21
+ ### Dependencies
22
+
23
+ * The following workspace dependencies were updated
24
+ * dependencies
25
+ * @aigne/agent-library bumped to 1.21.20
26
+ * @aigne/agentic-memory bumped to 1.0.20
27
+ * @aigne/aigne-hub bumped to 0.5.2
28
+ * @aigne/core bumped to 1.50.0
29
+ * @aigne/default-memory bumped to 1.1.2
30
+ * @aigne/openai bumped to 0.11.2
31
+
32
+ ## [1.35.1](https://github.com/AIGNE-io/aigne-framework/compare/cli-v1.35.0...cli-v1.35.1) (2025-08-13)
33
+
34
+
35
+ ### Dependencies
36
+
37
+ * The following workspace dependencies were updated
38
+ * dependencies
39
+ * @aigne/aigne-hub bumped to 0.5.1
40
+
3
41
  ## [1.35.0](https://github.com/AIGNE-io/aigne-framework/compare/cli-v1.34.1...cli-v1.35.0) (2025-08-13)
4
42
 
5
43
 
@@ -1,4 +1,3 @@
1
- import chalk from "chalk";
2
1
  import yargs from "yargs";
3
2
  import { AIGNE_CLI_VERSION } from "../constants.js";
4
3
  import { asciiLogo } from "../utils/ascii-logo.js";
@@ -11,7 +10,6 @@ import { createServeMCPCommand } from "./serve-mcp.js";
11
10
  import { createTestCommand } from "./test.js";
12
11
  export function createAIGNECommand(options) {
13
12
  console.log(asciiLogo);
14
- console.log(`${chalk.grey("TIPS:")} run ${chalk.cyan("aigne observe")} to start the observability server.\n`);
15
13
  return yargs()
16
14
  .scriptName("aigne")
17
15
  .usage("CLI for AIGNE framework")
@@ -1,6 +1,6 @@
1
1
  import assert from "node:assert";
2
2
  import { spawn } from "node:child_process";
3
- import { readFile, stat, writeFile } from "node:fs/promises";
3
+ import { mkdir, readFile, rm, stat, writeFile } from "node:fs/promises";
4
4
  import { homedir } from "node:os";
5
5
  import { extname, join } from "node:path";
6
6
  import { isatty } from "node:tty";
@@ -216,13 +216,21 @@ export async function loadApplication({ name, dir, forceUpgrade = false, }) {
216
216
  title: `Downloading ${name}`,
217
217
  skip: (ctx) => ctx.version === check?.version,
218
218
  task: async (ctx) => {
219
+ await rm(dir, { force: true, recursive: true });
220
+ await mkdir(dir, { recursive: true });
219
221
  await downloadAndExtract(ctx.url, dir, { strip: 1 });
220
222
  },
221
223
  },
222
224
  {
223
225
  title: "Installing dependencies",
224
- task: async () => {
225
- await installDependencies(dir);
226
+ task: async (_, task) => {
227
+ await installDependencies(dir, {
228
+ log: (log) => {
229
+ const last = log.split("\n").findLast((i) => !!i);
230
+ if (last)
231
+ task.output = last;
232
+ },
233
+ });
226
234
  },
227
235
  },
228
236
  ], {
@@ -252,12 +260,20 @@ async function isInstallationAvailable(dir, { cacheTimeMs = NPM_PACKAGE_CACHE_TI
252
260
  const available = installedAt ? now - installedAt < cacheTimeMs : false;
253
261
  return { version, available };
254
262
  }
255
- async function installDependencies(dir) {
263
+ async function installDependencies(dir, { log } = {}) {
256
264
  await new Promise((resolve, reject) => {
257
- const child = spawn("npm", ["install", "--omit", "dev"], { cwd: dir, stdio: "pipe" });
265
+ const child = spawn("npm", ["install", "--omit", "dev", "--verbose"], {
266
+ cwd: dir,
267
+ stdio: "pipe",
268
+ });
269
+ child.stdout.on("data", (data) => {
270
+ log?.(data.toString());
271
+ });
258
272
  let stderr = "";
259
273
  child.stderr.on("data", (data) => {
260
- stderr += data.toString();
274
+ const str = data.toString();
275
+ log?.(str);
276
+ stderr += str;
261
277
  });
262
278
  child.on("error", (error) => reject(error));
263
279
  child.on("exit", (code) => {
@@ -24,13 +24,19 @@ function printHubStatus(data) {
24
24
  console.log(` ${chalk.bold("DID:".padEnd(8))} ${data.user.did}`);
25
25
  console.log(` ${chalk.bold("Email:".padEnd(8))} ${data.user.email}`);
26
26
  console.log("");
27
- console.log(chalk.bold("Credits:"));
28
- console.log(` ${chalk.bold("Used:".padEnd(8))} ${data.credits.used.toLocaleString()}`);
29
- console.log(` ${chalk.bold("Total:".padEnd(8))} ${data.credits.total.toLocaleString()}`);
30
- console.log("");
31
- console.log(chalk.bold("Links:"));
32
- console.log(` ${chalk.bold("Payment:".padEnd(8))} ${data.links.payment}`);
33
- console.log(` ${chalk.bold("Profile:".padEnd(8))} ${data.links.profile}`);
27
+ if (data.enableCredit) {
28
+ console.log(chalk.bold("Credits:"));
29
+ console.log(` ${chalk.bold("Used:".padEnd(8))} ${data.credits.used.toLocaleString()}`);
30
+ console.log(` ${chalk.bold("Total:".padEnd(8))} ${data.credits.total.toLocaleString()}`);
31
+ console.log("");
32
+ console.log(chalk.bold("Links:"));
33
+ if (data.links.payment) {
34
+ console.log(` ${chalk.bold("Payment:".padEnd(8))} ${data.links.payment}`);
35
+ }
36
+ if (data.links.profile) {
37
+ console.log(` ${chalk.bold("Profile:".padEnd(8))} ${data.links.profile}`);
38
+ }
39
+ }
34
40
  }
35
41
  async function getHubs() {
36
42
  if (!existsSync(AIGNE_ENV_FILE)) {
@@ -61,29 +67,26 @@ const getDefaultHub = async () => {
61
67
  };
62
68
  async function formatHubsList(statusList) {
63
69
  if (statusList?.length === 0) {
64
- console.log(chalk.yellow("No AIGNE Hub configured."));
70
+ console.log(chalk.yellow("No AIGNE Hub connected."));
65
71
  console.log("Use 'aigne hub connect' to connect to a hub.");
66
72
  return;
67
73
  }
68
74
  const defaultHub = await getDefaultHub();
69
75
  const table = new Table({
70
- head: ["URL", "ACTIVE", "STATUS"],
71
- colWidths: [50, 10, 20],
76
+ head: ["URL", "ACTIVE"],
77
+ colWidths: [70, 10],
72
78
  style: {
73
79
  head: ["cyan"],
74
80
  border: ["grey"],
75
81
  },
76
82
  });
77
- console.log(chalk.blue("AIGNE Hubs:\n"));
83
+ console.log(chalk.blue("Connected AIGNE Hubs:\n"));
78
84
  for (const status of statusList) {
79
85
  const isConnected = new URL(status.apiUrl).origin === new URL(defaultHub).origin;
80
- table.push([
81
- status.apiUrl,
82
- isConnected ? "*" : "-",
83
- isConnected ? "Connected" : "Not connected",
84
- ]);
86
+ table.push([status.apiUrl, isConnected ? "YES" : "NO"]);
85
87
  }
86
88
  console.log(table.toString());
89
+ console.log(chalk.blue("Use 'aigne hub use' to switch to a different hub."));
87
90
  }
88
91
  export function createHubCommand() {
89
92
  return {
@@ -91,7 +94,23 @@ export function createHubCommand() {
91
94
  describe: "Manage AIGNE Hub connections",
92
95
  builder: (yargs) => yargs
93
96
  .command(["list", "ls"], "List all connected AIGNE Hubs", listHubs)
94
- .command("connect", "Connect to an AIGNE Hub", connectHub)
97
+ .command({
98
+ command: "connect [url]",
99
+ describe: "Connect to an AIGNE Hub",
100
+ builder: (yargs) => yargs.positional("url", {
101
+ type: "string",
102
+ describe: "The URL of the AIGNE Hub to connect to",
103
+ default: null,
104
+ }),
105
+ handler: (args) => {
106
+ if (args.url) {
107
+ saveAndConnect(args.url);
108
+ }
109
+ else {
110
+ connectHub();
111
+ }
112
+ },
113
+ })
95
114
  .command("use", "Switch to a different AIGNE Hub", useHub)
96
115
  .command(["status", "st"], "Show current active hub", showStatus)
97
116
  .command(["remove", "rm"], "Remove a connected hub", removeHub)
@@ -131,7 +150,7 @@ async function connectHub() {
131
150
  async function useHub() {
132
151
  const hubs = await getHubs();
133
152
  if (!hubs.length) {
134
- console.log(chalk.yellow("No AIGNE Hub configured."));
153
+ console.log(chalk.yellow("No AIGNE Hub connected."));
135
154
  return;
136
155
  }
137
156
  const { hubApiKey } = await inquirer.prompt({
@@ -156,7 +175,7 @@ async function showStatus() {
156
175
  async function removeHub() {
157
176
  const hubs = await getHubs();
158
177
  if (!hubs.length) {
159
- console.log(chalk.yellow("No AIGNE Hub configured."));
178
+ console.log(chalk.yellow("No AIGNE Hub connected."));
160
179
  return;
161
180
  }
162
181
  const { hubApiKey } = await inquirer.prompt({
@@ -173,7 +192,7 @@ async function removeHub() {
173
192
  async function showInfo() {
174
193
  const hubs = await getHubs();
175
194
  if (!hubs.length) {
176
- console.log(chalk.yellow("No AIGNE Hub configured."));
195
+ console.log(chalk.yellow("No AIGNE Hub connected."));
177
196
  return;
178
197
  }
179
198
  const { hubApiKey } = await inquirer.prompt({
@@ -267,5 +286,6 @@ async function printHubDetails(url) {
267
286
  payment: userInfo?.paymentLink || "",
268
287
  profile: userInfo?.profileLink || "",
269
288
  },
289
+ enableCredit: userInfo?.enableCredit || false,
270
290
  });
271
291
  }
@@ -1,3 +1,4 @@
1
1
  import { DefaultMemory } from "@aigne/default-memory";
2
2
  export declare const AIGNE_CLI_VERSION: any;
3
3
  export declare const availableMemories: (typeof DefaultMemory)[];
4
+ export declare const AIGNE_HUB_CREDITS_NOT_ENOUGH_ERROR_TYPE = "NOT_ENOUGH";
package/dist/constants.js CHANGED
@@ -4,3 +4,4 @@ import { DefaultMemory } from "@aigne/default-memory";
4
4
  const require = createRequire(import.meta.url);
5
5
  export const AIGNE_CLI_VERSION = require("../package.json").version;
6
6
  export const availableMemories = [DefaultMemory, AgenticMemory];
7
+ export const AIGNE_HUB_CREDITS_NOT_ENOUGH_ERROR_TYPE = "NOT_ENOUGH";
@@ -4,7 +4,6 @@ import { promiseWithResolvers } from "@aigne/core/utils/promise.js";
4
4
  import { type Listr } from "@aigne/listr2";
5
5
  import { type AIGNEListrTaskWrapper } from "../utils/listr.js";
6
6
  export interface TerminalTracerOptions {
7
- printRequest?: boolean;
8
7
  outputKey?: string;
9
8
  }
10
9
  export declare class TerminalTracer {
@@ -16,6 +15,10 @@ export declare class TerminalTracer {
16
15
  result: Message;
17
16
  context: Context<import("@aigne/core").UserContext>;
18
17
  }>;
18
+ private listr?;
19
+ private proxiedPrompts;
20
+ private buyCreditsPromptPromise;
21
+ private promptBuyCredits;
19
22
  formatTokenUsage(usage: Partial<ContextUsage>, extra?: {
20
23
  [key: string]: string;
21
24
  }): string;
@@ -1,7 +1,6 @@
1
1
  import { EOL } from "node:os";
2
2
  import { inspect } from "node:util";
3
3
  import { AIAgent, ChatModel, DEFAULT_OUTPUT_KEY, UserAgent, } from "@aigne/core";
4
- import { LogLevel, logger } from "@aigne/core/utils/logger.js";
5
4
  import { promiseWithResolvers } from "@aigne/core/utils/promise.js";
6
5
  import { flat, omit } from "@aigne/core/utils/type-utils.js";
7
6
  import { figures } from "@aigne/listr2";
@@ -9,6 +8,7 @@ import { markedTerminal } from "@aigne/marked-terminal";
9
8
  import * as prompts from "@inquirer/prompts";
10
9
  import chalk from "chalk";
11
10
  import { Marked } from "marked";
11
+ import { AIGNE_HUB_CREDITS_NOT_ENOUGH_ERROR_TYPE } from "../constants.js";
12
12
  import { AIGNEListr, AIGNEListrRenderer } from "../utils/listr.js";
13
13
  import { highlightUrl } from "../utils/string-utils.js";
14
14
  import { parseDuration } from "../utils/time.js";
@@ -24,29 +24,10 @@ export class TerminalTracer {
24
24
  await this.context.observer?.serve();
25
25
  const context = this.context.newContext({ reset: true });
26
26
  const listr = new AIGNEListr({
27
- formatRequest: (options) => this.options.printRequest
28
- ? this.formatRequest(agent, context, input, options)
29
- : undefined,
27
+ formatRequest: (options) => this.formatRequest(agent, context, input, options),
30
28
  formatResult: (result, options) => [this.formatResult(agent, context, result, options)].filter(Boolean),
31
29
  }, [], { concurrent: true });
32
- const proxiedPrompts = new Proxy({}, {
33
- get: (_target, prop) => {
34
- // biome-ignore lint/performance/noDynamicNamespaceImportAccess: we need to access prompts dynamically
35
- const method = prompts[prop];
36
- if (typeof method !== "function")
37
- return undefined;
38
- return async (config) => {
39
- const renderer = listr["renderer"] instanceof AIGNEListrRenderer ? listr["renderer"] : undefined;
40
- await renderer?.pause();
41
- try {
42
- return await method({ ...config });
43
- }
44
- finally {
45
- await renderer?.resume();
46
- }
47
- };
48
- },
49
- });
30
+ this.listr = listr;
50
31
  const onStart = async ({ context, agent, ...event }) => {
51
32
  if (agent instanceof UserAgent)
52
33
  return;
@@ -80,7 +61,7 @@ export class TerminalTracer {
80
61
  else {
81
62
  listr.add(listrTask);
82
63
  }
83
- return { options: { prompts: proxiedPrompts } };
64
+ return { options: { prompts: this.proxiedPrompts } };
84
65
  };
85
66
  const onSuccess = async ({ context, agent, output, ...event }) => {
86
67
  const contextId = context.id;
@@ -109,20 +90,8 @@ export class TerminalTracer {
109
90
  task.resolve();
110
91
  };
111
92
  const onError = async ({ context, agent, error, ...event }) => {
112
- if ("type" in error && error.type === "NOT_ENOUGH") {
113
- const retry = await proxiedPrompts.select({
114
- message: highlightUrl(error.message),
115
- choices: [
116
- {
117
- name: "I have bought some credits, try again",
118
- value: "retry",
119
- },
120
- {
121
- name: "Exit",
122
- value: "exit",
123
- },
124
- ],
125
- });
93
+ if ("type" in error && error.type === AIGNE_HUB_CREDITS_NOT_ENOUGH_ERROR_TYPE) {
94
+ const retry = await this.promptBuyCredits(error);
126
95
  console.log("");
127
96
  if (retry === "retry") {
128
97
  return { retry: true };
@@ -145,6 +114,7 @@ export class TerminalTracer {
145
114
  const result = await listr.run(() => context.invoke(agent, input, {
146
115
  ...options,
147
116
  hooks: flat({
117
+ priority: "high",
148
118
  onStart,
149
119
  onSuccess,
150
120
  onError,
@@ -154,6 +124,51 @@ export class TerminalTracer {
154
124
  }));
155
125
  return { result, context };
156
126
  }
127
+ listr;
128
+ proxiedPrompts = new Proxy({}, {
129
+ get: (_target, prop) => {
130
+ // biome-ignore lint/performance/noDynamicNamespaceImportAccess: we need to access prompts dynamically
131
+ const method = prompts[prop];
132
+ if (typeof method !== "function")
133
+ return undefined;
134
+ return async (config) => {
135
+ const renderer = this.listr?.["renderer"] instanceof AIGNEListrRenderer
136
+ ? this.listr["renderer"]
137
+ : undefined;
138
+ await renderer?.pause();
139
+ try {
140
+ return await method({ ...config });
141
+ }
142
+ finally {
143
+ await renderer?.resume();
144
+ }
145
+ };
146
+ },
147
+ });
148
+ buyCreditsPromptPromise;
149
+ async promptBuyCredits(error) {
150
+ // Avoid multiple agents asking for credits, we will only show the prompt once
151
+ this.buyCreditsPromptPromise ??= (async () => {
152
+ const retry = await this.proxiedPrompts.select({
153
+ message: highlightUrl(error.message),
154
+ choices: [
155
+ {
156
+ name: "I have bought some credits, try again",
157
+ value: "retry",
158
+ },
159
+ {
160
+ name: "Exit",
161
+ value: "exit",
162
+ },
163
+ ],
164
+ });
165
+ return retry;
166
+ })();
167
+ return this.buyCreditsPromptPromise.finally(() => {
168
+ // Clear the promise so that we can show the prompt again if needed
169
+ this.buyCreditsPromptPromise = undefined;
170
+ });
171
+ }
157
172
  formatTokenUsage(usage, extra) {
158
173
  const items = [
159
174
  [chalk.yellow(usage.inputTokens), chalk.grey("input tokens")],
@@ -192,13 +207,15 @@ export class TerminalTracer {
192
207
  }
193
208
  }
194
209
  },
195
- }, markedTerminal({ forceHyperLink: false }));
210
+ }, markedTerminal({ forceHyperLink: false }, {
211
+ theme: {
212
+ string: chalk.green,
213
+ },
214
+ }));
196
215
  get outputKey() {
197
216
  return this.options.outputKey || DEFAULT_OUTPUT_KEY;
198
217
  }
199
218
  formatRequest(agent, _context, m = {}, { running = false } = {}) {
200
- if (!logger.enabled(LogLevel.INFO))
201
- return;
202
219
  const prefix = `${chalk.grey(figures.pointer)} 💬 `;
203
220
  const inputKey = agent instanceof AIAgent ? agent.inputKey : undefined;
204
221
  const msg = inputKey ? m[inputKey] : undefined;
@@ -207,14 +224,15 @@ export class TerminalTracer {
207
224
  const json = Object.keys(message).length > 0
208
225
  ? inspect(message, { colors: true, ...(running ? this.runningInspectOptions : undefined) })
209
226
  : undefined;
210
- return [prefix, [text, json].filter(Boolean).join(EOL)].join(" ");
227
+ const r = [text, json].filter(Boolean).join(EOL).trim();
228
+ if (!r)
229
+ return undefined;
230
+ return `${prefix}${r}`;
211
231
  }
212
232
  formatResult(agent, context, m = {}, { running = false } = {}) {
213
233
  const { isTTY } = process.stdout;
214
234
  const outputKey = this.outputKey || (agent instanceof AIAgent ? agent.outputKey : undefined);
215
- const prefix = logger.enabled(LogLevel.INFO)
216
- ? `${chalk.grey(figures.tick)} 🤖 ${this.formatTokenUsage(context.usage)}`
217
- : null;
235
+ const prefix = `${chalk.grey(figures.tick)} 🤖 ${this.formatTokenUsage(context.usage)}`;
218
236
  const msg = outputKey ? m[outputKey] : undefined;
219
237
  const message = outputKey ? omit(m, outputKey) : m;
220
238
  const text = msg && typeof msg === "string"
@@ -225,7 +243,7 @@ export class TerminalTracer {
225
243
  const json = Object.keys(message).length > 0
226
244
  ? inspect(message, { colors: isTTY, ...(running ? this.runningInspectOptions : undefined) })
227
245
  : undefined;
228
- return [prefix, text, json].filter(Boolean).join(EOL);
246
+ return [prefix, text, json].filter(Boolean).join(EOL.repeat(2));
229
247
  }
230
248
  runningInspectOptions = {
231
249
  maxArrayLength: 3,
@@ -51,11 +51,9 @@ export class AIGNEListr extends Listr {
51
51
  try {
52
52
  this.ctx = {};
53
53
  this.spinner.start();
54
- if (logger.enabled(LogLevel.INFO)) {
55
- const request = this.myOptions.formatRequest();
56
- if (request)
57
- console.log(request);
58
- }
54
+ const request = this.myOptions.formatRequest();
55
+ if (request)
56
+ console.log(request);
59
57
  logger.logMessage = (...args) => this.logs.push(format(...args));
60
58
  for (const method of ["debug", "log", "info", "warn", "error"]) {
61
59
  console[method] = (...args) => {
@@ -2,14 +2,35 @@ import { existsSync, mkdirSync } from "node:fs";
2
2
  import { readFile } from "node:fs/promises";
3
3
  import { homedir } from "node:os";
4
4
  import { join } from "node:path";
5
- import { AIGNE_ENV_FILE, checkConnectionStatus, AIGNE_HUB_URL as DEFAULT_AIGNE_HUB_URL, formatModelName, loadModel, parseModelOption, } from "@aigne/aigne-hub";
5
+ import { AIGNE_ENV_FILE, checkConnectionStatus, AIGNE_HUB_URL as DEFAULT_AIGNE_HUB_URL, formatModelName, loadModel, maskApiKey, parseModelOption, } from "@aigne/aigne-hub";
6
6
  import { AIGNE } from "@aigne/core";
7
7
  import { loadAIGNEFile } from "@aigne/core/loader/index.js";
8
+ import boxen from "boxen";
9
+ import chalk from "chalk";
8
10
  import inquirer from "inquirer";
9
11
  import { parse, stringify } from "yaml";
10
12
  import { availableMemories } from "../constants.js";
11
13
  const isTest = process.env.CI || process.env.NODE_ENV === "test";
12
14
  const mockInquirerPrompt = (() => Promise.resolve({ useAigneHub: true }));
15
+ let printed = false;
16
+ function printChatModelInfoBox(model) {
17
+ if (printed)
18
+ return;
19
+ printed = true;
20
+ const credential = model.getCredential();
21
+ const lines = [`${chalk.cyan("Provider")}: ${chalk.green(model.name.replace("ChatModel", ""))}`];
22
+ if (credential?.model) {
23
+ lines.push(`${chalk.cyan("Model")}: ${chalk.green(credential?.model)}`);
24
+ }
25
+ if (credential?.url) {
26
+ lines.push(`${chalk.cyan("API URL")}: ${chalk.green(credential?.url || "N/A")}`);
27
+ }
28
+ if (credential?.apiKey) {
29
+ lines.push(`${chalk.cyan("API Key")}: ${chalk.green(maskApiKey(credential?.apiKey))}`);
30
+ }
31
+ console.log(boxen(lines.join("\n"), { padding: 1, borderStyle: "classic", borderColor: "cyan" }));
32
+ console.log("");
33
+ }
13
34
  async function prepareAIGNEConfig(options, inquirerPromptFn) {
14
35
  const aigneDir = join(homedir(), ".aigne");
15
36
  if (!existsSync(aigneDir)) {
@@ -40,6 +61,7 @@ export async function loadAIGNE({ path, options, modelOptions, actionOptions, })
40
61
  const model = await loadModel(parseModelOption(formattedModelName));
41
62
  return await AIGNE.load(path, { loadModel, memories: availableMemories, model });
42
63
  }
64
+ console.log(`${chalk.grey("TIPS:")} run ${chalk.cyan("aigne observe")} to start the observability server.\n`);
43
65
  const model = await loadModel({
44
66
  ...parseModelOption(formattedModelName),
45
67
  temperature,
@@ -47,6 +69,9 @@ export async function loadAIGNE({ path, options, modelOptions, actionOptions, })
47
69
  presencePenalty,
48
70
  frequencyPenalty,
49
71
  }, modelOptions, { aigneHubUrl: AIGNE_HUB_URL, inquirerPromptFn: actionOptions?.inquirerPromptFn });
72
+ if (model) {
73
+ printChatModelInfoBox(model);
74
+ }
50
75
  if (path) {
51
76
  return await AIGNE.load(path, { loadModel, memories: availableMemories, model });
52
77
  }
@@ -203,10 +203,7 @@ export async function runAgentWithAIGNE(aigne, agent, { outputKey, chatLoopOptio
203
203
  });
204
204
  return;
205
205
  }
206
- const tracer = new TerminalTracer(aigne.newContext(), {
207
- printRequest: logger.enabled(LogLevel.INFO),
208
- outputKey,
209
- });
206
+ const tracer = new TerminalTracer(aigne.newContext(), { outputKey });
210
207
  const { result } = await tracer.run(agent, options.input ?? {});
211
208
  if (options.output) {
212
209
  const message = result[outputKey || DEFAULT_OUTPUT_KEY];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aigne/cli",
3
- "version": "1.35.0",
3
+ "version": "1.36.0",
4
4
  "description": "Your command center for agent development",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -52,6 +52,7 @@
52
52
  "@listr2/prompt-adapter-inquirer": "^3.0.1",
53
53
  "@modelcontextprotocol/sdk": "^1.15.0",
54
54
  "@smithy/node-http-handler": "^4.1.0",
55
+ "boxen": "^8.0.1",
55
56
  "chalk": "^5.4.1",
56
57
  "cli-table3": "^0.6.5",
57
58
  "detect-port": "^2.1.0",
@@ -71,13 +72,13 @@
71
72
  "yaml": "^2.8.0",
72
73
  "yargs": "^18.0.0",
73
74
  "zod": "^3.25.67",
74
- "@aigne/agent-library": "^1.21.19",
75
- "@aigne/agentic-memory": "^1.0.19",
76
- "@aigne/aigne-hub": "^0.5.0",
77
- "@aigne/default-memory": "^1.1.1",
78
- "@aigne/observability-api": "^0.9.0",
79
- "@aigne/core": "^1.49.1",
80
- "@aigne/openai": "^0.11.1"
75
+ "@aigne/aigne-hub": "^0.5.2",
76
+ "@aigne/agentic-memory": "^1.0.20",
77
+ "@aigne/agent-library": "^1.21.20",
78
+ "@aigne/core": "^1.50.0",
79
+ "@aigne/default-memory": "^1.1.2",
80
+ "@aigne/openai": "^0.11.2",
81
+ "@aigne/observability-api": "^0.9.0"
81
82
  },
82
83
  "devDependencies": {
83
84
  "@types/archiver": "^6.0.3",