@aigne/cli 1.30.3 → 1.31.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,50 @@
1
1
  # Changelog
2
2
 
3
+ ## [1.31.0](https://github.com/AIGNE-io/aigne-framework/compare/cli-v1.30.4...cli-v1.31.0) (2025-08-06)
4
+
5
+
6
+ ### Features
7
+
8
+ * **cli:** support custom task title of agent in cli ([#328](https://github.com/AIGNE-io/aigne-framework/issues/328)) ([128d75f](https://github.com/AIGNE-io/aigne-framework/commit/128d75fb42ca470b47a2793d79c92d7bb64cfedb))
9
+
10
+
11
+ ### Bug Fixes
12
+
13
+ * **cli:** nunjucks should import as cjs module ([432b9e1](https://github.com/AIGNE-io/aigne-framework/commit/432b9e1e436bd5b02427a5effea907be1f589c31))
14
+ * **core:** improve hook handling in agent and context ([#325](https://github.com/AIGNE-io/aigne-framework/issues/325)) ([c858fec](https://github.com/AIGNE-io/aigne-framework/commit/c858fecb08453c2daca9708f4b8a9c135fac40b0))
15
+
16
+
17
+ ### Dependencies
18
+
19
+ * The following workspace dependencies were updated
20
+ * dependencies
21
+ * @aigne/agent-library bumped to 1.21.14
22
+ * @aigne/agentic-memory bumped to 1.0.14
23
+ * @aigne/aigne-hub bumped to 0.4.5
24
+ * @aigne/core bumped to 1.46.0
25
+ * @aigne/default-memory bumped to 1.0.14
26
+ * @aigne/openai bumped to 0.10.14
27
+
28
+ ## [1.30.4](https://github.com/AIGNE-io/aigne-framework/compare/cli-v1.30.3...cli-v1.30.4) (2025-08-06)
29
+
30
+
31
+ ### Bug Fixes
32
+
33
+ * **cli:** improve help display and command handling ([#319](https://github.com/AIGNE-io/aigne-framework/issues/319)) ([306ca5f](https://github.com/AIGNE-io/aigne-framework/commit/306ca5f251d6de356131b11909293be3904d0675))
34
+ * create connect add app info ([#321](https://github.com/AIGNE-io/aigne-framework/issues/321)) ([f0094a3](https://github.com/AIGNE-io/aigne-framework/commit/f0094a3f891617a9822df90918445639cd8c1a90))
35
+
36
+
37
+ ### Dependencies
38
+
39
+ * The following workspace dependencies were updated
40
+ * dependencies
41
+ * @aigne/agent-library bumped to 1.21.13
42
+ * @aigne/agentic-memory bumped to 1.0.13
43
+ * @aigne/aigne-hub bumped to 0.4.4
44
+ * @aigne/openai bumped to 0.10.13
45
+ * @aigne/core bumped to 1.45.0
46
+ * @aigne/default-memory bumped to 1.0.13
47
+
3
48
  ## [1.30.3](https://github.com/AIGNE-io/aigne-framework/compare/cli-v1.30.2...cli-v1.30.3) (2025-08-05)
4
49
 
5
50
 
package/dist/cli.js CHANGED
@@ -17,7 +17,13 @@ function getAIGNEFilePath() {
17
17
  }
18
18
  const aigneFilePath = getAIGNEFilePath();
19
19
  export default createAIGNECommand({ aigneFilePath })
20
- .fail(() => { })
20
+ .fail((message, error, yargs) => {
21
+ // We catch all errors below, here just print the help message non-error case like demandCommand
22
+ if (!error) {
23
+ yargs.showHelp();
24
+ console.error(`\n${message}`);
25
+ }
26
+ })
21
27
  .parseAsync(hideBin([...process.argv.slice(0, 2), ...process.argv.slice(aigneFilePath ? 3 : 2)]))
22
28
  .catch((error) => {
23
29
  console.log(""); // Add an empty line for better readability
@@ -11,7 +11,7 @@ import { createServeMCPCommand } from "./serve-mcp.js";
11
11
  import { createTestCommand } from "./test.js";
12
12
  export function createAIGNECommand(options) {
13
13
  console.log(asciiLogo);
14
- console.log(`${chalk.grey("TIPS:")} use ${chalk.greenBright("aigne observe")} to start the observability server.\n`);
14
+ console.log(`${chalk.grey("TIPS:")} run ${chalk.blue("aigne observe")} to start the observability server.\n`);
15
15
  return yargs()
16
16
  .scriptName("aigne")
17
17
  .usage("CLI for AIGNE framework")
@@ -23,6 +23,7 @@ export function createAIGNECommand(options) {
23
23
  .command(createObservabilityCommand())
24
24
  .command(createConnectCommand())
25
25
  .command(createAppCommands())
26
+ .demandCommand()
26
27
  .alias("help", "h")
27
28
  .alias("version", "v")
28
29
  .strict();
@@ -40,7 +40,7 @@ export function createAppCommands() {
40
40
  for (const agent of aigne.cli?.agents ?? []) {
41
41
  yargs.command(agentCommandModule({ dir, agent }));
42
42
  }
43
- yargs.version(`${app.name} v${version}`);
43
+ yargs.version(`${app.name} v${version}`).alias("version", "v");
44
44
  return yargs.demandCommand();
45
45
  },
46
46
  handler: () => { },
@@ -77,7 +77,7 @@ const upgradeCommandModule = ({ name, dir, isLatest, version, }) => ({
77
77
  if (!isLatest) {
78
78
  const result = await loadApplication({ name, dir, forceUpgrade: true });
79
79
  if (version !== result.version) {
80
- console.log(`\n✅ Upgraded ${name} to version ${version}`);
80
+ console.log(`\n✅ Upgraded ${name} to version ${result.version}`);
81
81
  return;
82
82
  }
83
83
  }
@@ -20,10 +20,11 @@ export declare class TerminalTracer {
20
20
  [key: string]: string;
21
21
  }): string;
22
22
  formatTimeUsage(startTime: number, endTime: number): string;
23
- formatTaskTitle(agent: Agent, { task, usage, time }?: {
23
+ formatTaskTitle(agent: Agent, { task, usage, time, input }: {
24
24
  task?: Task;
25
25
  usage?: boolean;
26
26
  time?: boolean;
27
+ input: Message;
27
28
  }): string;
28
29
  private marked;
29
30
  get outputKey(): string;
@@ -1,6 +1,6 @@
1
1
  import { EOL } from "node:os";
2
2
  import { inspect } from "node:util";
3
- import { AIAgent, ChatModel, DEFAULT_OUTPUT_KEY, } from "@aigne/core";
3
+ import { AIAgent, ChatModel, DEFAULT_OUTPUT_KEY, UserAgent, } from "@aigne/core";
4
4
  import { LogLevel, logger } from "@aigne/core/utils/logger.js";
5
5
  import { promiseWithResolvers } from "@aigne/core/utils/promise.js";
6
6
  import { flat, omit } from "@aigne/core/utils/type-utils.js";
@@ -9,6 +9,7 @@ import { markedTerminal } from "@aigne/marked-terminal";
9
9
  import * as prompts from "@inquirer/prompts";
10
10
  import chalk from "chalk";
11
11
  import { Marked } from "marked";
12
+ import nunjucks from "nunjucks";
12
13
  import { AIGNEListr, AIGNEListrRenderer } from "../utils/listr.js";
13
14
  import { parseDuration } from "../utils/time.js";
14
15
  export class TerminalTracer {
@@ -28,7 +29,9 @@ export class TerminalTracer {
28
29
  : undefined,
29
30
  formatResult: (result, options) => [this.formatResult(agent, context, result, options)].filter(Boolean),
30
31
  }, [], { concurrent: true });
31
- const onStart = async ({ context, agent }) => {
32
+ const onStart = async ({ context, agent, ...event }) => {
33
+ if (agent instanceof UserAgent)
34
+ return;
32
35
  const contextId = context.id;
33
36
  const parentContextId = context.parentId;
34
37
  const task = {
@@ -38,7 +41,7 @@ export class TerminalTracer {
38
41
  };
39
42
  this.tasks[contextId] = task;
40
43
  const listrTask = {
41
- title: this.formatTaskTitle(agent),
44
+ title: this.formatTaskTitle(agent, { ...event }),
42
45
  task: (ctx, taskWrapper) => {
43
46
  const subtask = taskWrapper.newListr([{ task: () => task.promise }]);
44
47
  task.listr.resolve({ subtask, taskWrapper, ctx });
@@ -82,7 +85,7 @@ export class TerminalTracer {
82
85
  },
83
86
  };
84
87
  };
85
- const onSuccess = async ({ context, agent, output }) => {
88
+ const onSuccess = async ({ context, agent, output, ...event }) => {
86
89
  const contextId = context.id;
87
90
  const parentContextId = context.parentId;
88
91
  const task = this.tasks[contextId];
@@ -97,20 +100,20 @@ export class TerminalTracer {
97
100
  if (model)
98
101
  task.extraTitleMetadata.model = model;
99
102
  }
100
- taskWrapper.title = this.formatTaskTitle(agent, { task, usage: true, time: true });
103
+ taskWrapper.title = this.formatTaskTitle(agent, { ...event, task, usage: true, time: true });
101
104
  if (!parentContextId || !this.tasks[parentContextId]) {
102
105
  Object.assign(ctx, output);
103
106
  }
104
107
  task.resolve();
105
108
  };
106
- const onError = async ({ context, agent, error }) => {
109
+ const onError = async ({ context, agent, error, ...event }) => {
107
110
  const contextId = context.id;
108
111
  const task = this.tasks[contextId];
109
112
  if (!task)
110
113
  return;
111
114
  task.endTime = Date.now();
112
115
  const { taskWrapper } = await task.listr.promise;
113
- taskWrapper.title = this.formatTaskTitle(agent, { task, usage: true, time: true });
116
+ taskWrapper.title = this.formatTaskTitle(agent, { ...event, task, usage: true, time: true });
114
117
  task.reject(error);
115
118
  };
116
119
  const result = await listr.run(() => context.invoke(agent, input, {
@@ -143,8 +146,11 @@ export class TerminalTracer {
143
146
  const duration = endTime - startTime;
144
147
  return chalk.grey(`[${parseDuration(duration)}]`);
145
148
  }
146
- formatTaskTitle(agent, { task, usage, time } = {}) {
147
- let title = `invoke agent ${agent.name}`;
149
+ formatTaskTitle(agent, { task, usage, time, input }) {
150
+ let title = agent.name;
151
+ if (agent.taskTitle) {
152
+ title += ` ${chalk.cyan(nunjucks.renderString(agent.taskTitle, { ...input }))}`;
153
+ }
148
154
  if (usage && task?.usage)
149
155
  title += ` ${this.formatTokenUsage(task.usage, task.extraTitleMetadata)}`;
150
156
  if (time && task?.startTime && task.endTime)
@@ -30,6 +30,8 @@ interface CreateConnectOptions {
30
30
  retry?: number;
31
31
  source?: string;
32
32
  connectAction?: string;
33
+ appName?: string;
34
+ appLogo?: string;
33
35
  wrapSpinner?: typeof baseWrapSpinner;
34
36
  prettyUrl?: (url: string) => string;
35
37
  closeOnSuccess?: boolean;
@@ -39,7 +41,7 @@ interface CreateConnectOptions {
39
41
  fetchTimeout: number;
40
42
  }) => Promise<FetchResult>;
41
43
  }
42
- export declare function createConnect({ connectUrl, openPage, fetchInterval, retry, source, connectAction, wrapSpinner, closeOnSuccess, intervalFetchConfig, }: CreateConnectOptions): Promise<FetchResult>;
44
+ export declare function createConnect({ connectUrl, openPage, fetchInterval, retry, source, connectAction, wrapSpinner, closeOnSuccess, intervalFetchConfig, appName, appLogo, }: CreateConnectOptions): Promise<FetchResult>;
43
45
  export declare const formatModelName: (models: ReturnType<typeof availableModels>, model: string, inquirerPrompt: typeof inquirer.prompt) => Promise<string>;
44
46
  export declare function connectToAIGNEHub(url: string): Promise<{
45
47
  accessKey: string;
@@ -60,7 +60,7 @@ export const fetchConfigs = async ({ connectUrl, sessionId, fetchInterval, fetch
60
60
  function baseWrapSpinner(_, waiting) {
61
61
  return Promise.resolve(waiting());
62
62
  }
63
- export async function createConnect({ connectUrl, openPage, fetchInterval = 3 * 1000, retry = 1500, source = "Blocklet CLI", connectAction = "connect-cli", wrapSpinner = baseWrapSpinner, closeOnSuccess, intervalFetchConfig, }) {
63
+ export async function createConnect({ connectUrl, openPage, fetchInterval = 3 * 1000, retry = 1500, source = "Blocklet CLI", connectAction = "connect-cli", wrapSpinner = baseWrapSpinner, closeOnSuccess, intervalFetchConfig, appName = "AIGNE CLI", appLogo = "https://www.aigne.io/favicon.ico?imageFilter=resize&w=32", }) {
64
64
  try {
65
65
  const startSessionURL = joinURL(connectUrl, ACCESS_KEY_SESSION_API);
66
66
  const { data: session } = await request({ url: startSessionURL, method: "POST" });
@@ -70,8 +70,8 @@ export async function createConnect({ connectUrl, openPage, fetchInterval = 3 *
70
70
  source,
71
71
  closeOnSuccess,
72
72
  cli: true,
73
- appName: " AIGNE CLI",
74
- appLogo: "https://www.aigne.io/favicon.ico?imageFilter=resize&w=32",
73
+ appName: ` ${appName}`,
74
+ appLogo,
75
75
  });
76
76
  openPage?.(pageUrl);
77
77
  return await wrapSpinner(`Waiting for connection: ${connectUrl}`, async () => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aigne/cli",
3
- "version": "1.30.3",
3
+ "version": "1.31.0",
4
4
  "description": "Command-line interface for AIGNE Framework - A functional AI application development framework for building scalable AI-powered applications with workflow patterns, MCP protocol integration, and multi-model support",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -64,6 +64,7 @@
64
64
  "inquirer": "^12.7.0",
65
65
  "log-update": "^6.1.0",
66
66
  "marked": "^16.0.0",
67
+ "nunjucks": "^3.2.4",
67
68
  "open": "10.1.2",
68
69
  "openai": "^5.8.3",
69
70
  "p-wait-for": "^5.0.2",
@@ -73,13 +74,13 @@
73
74
  "yaml": "^2.8.0",
74
75
  "yargs": "^18.0.0",
75
76
  "zod": "^3.25.67",
76
- "@aigne/agent-library": "^1.21.12",
77
- "@aigne/aigne-hub": "^0.4.3",
78
- "@aigne/core": "^1.44.0",
79
- "@aigne/default-memory": "^1.0.12",
77
+ "@aigne/agent-library": "^1.21.14",
78
+ "@aigne/agentic-memory": "^1.0.14",
79
+ "@aigne/aigne-hub": "^0.4.5",
80
+ "@aigne/core": "^1.46.0",
81
+ "@aigne/default-memory": "^1.0.14",
80
82
  "@aigne/observability-api": "^0.9.0",
81
- "@aigne/agentic-memory": "^1.0.12",
82
- "@aigne/openai": "^0.10.12"
83
+ "@aigne/openai": "^0.10.14"
83
84
  },
84
85
  "devDependencies": {
85
86
  "@types/archiver": "^6.0.3",
@@ -88,6 +89,7 @@
88
89
  "@types/glob": "^9.0.0",
89
90
  "@types/gradient-string": "^1.1.6",
90
91
  "@types/node": "^24.0.12",
92
+ "@types/nunjucks": "^3.2.6",
91
93
  "@types/yargs": "^17.0.33",
92
94
  "archiver": "^7.0.1",
93
95
  "hono": "4.8.4",