@aigne/cli 1.5.1 → 1.7.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,28 @@
1
1
  # Changelog
2
2
 
3
+ ## [1.7.0](https://github.com/AIGNE-io/aigne-framework/compare/cli-v1.6.0...cli-v1.7.0) (2025-04-23)
4
+
5
+
6
+ ### Features
7
+
8
+ * **core:** enhance ClaudeChatModel to support streaming responses ([#85](https://github.com/AIGNE-io/aigne-framework/issues/85)) ([5433240](https://github.com/AIGNE-io/aigne-framework/commit/5433240e7b663ec9e9f4a79dffa05038088d54fc))
9
+ * support set memory in agent yaml ([#90](https://github.com/AIGNE-io/aigne-framework/issues/90)) ([215118f](https://github.com/AIGNE-io/aigne-framework/commit/215118f1dc55f02322d59a3f18395a459198e031))
10
+ * **tests:** add example tests and update the ci configuration ([#81](https://github.com/AIGNE-io/aigne-framework/issues/81)) ([777bb8d](https://github.com/AIGNE-io/aigne-framework/commit/777bb8d184c21e74b3eb9bbb4a1003708409a338))
11
+
12
+
13
+ ### Dependencies
14
+
15
+ * The following workspace dependencies were updated
16
+ * dependencies
17
+ * @aigne/core bumped to 1.11.0
18
+
19
+ ## [1.6.0](https://github.com/AIGNE-io/aigne-framework/compare/cli-v1.5.1...cli-v1.6.0) (2025-04-22)
20
+
21
+
22
+ ### Features
23
+
24
+ * **cli:** add --verbose option for run command ([#82](https://github.com/AIGNE-io/aigne-framework/issues/82)) ([7adf8be](https://github.com/AIGNE-io/aigne-framework/commit/7adf8be34963e714268457ab8b2ffeb945da5721))
25
+
3
26
  ## [1.5.1](https://github.com/AIGNE-io/aigne-framework/compare/cli-v1.5.0...cli-v1.5.1) (2025-04-22)
4
27
 
5
28
 
package/LICENSE ADDED
@@ -0,0 +1,93 @@
1
+ Elastic License 2.0
2
+
3
+ URL: https://www.elastic.co/licensing/elastic-license
4
+
5
+ ## Acceptance
6
+
7
+ By using the software, you agree to all of the terms and conditions below.
8
+
9
+ ## Copyright License
10
+
11
+ The licensor grants you a non-exclusive, royalty-free, worldwide,
12
+ non-sublicensable, non-transferable license to use, copy, distribute, make
13
+ available, and prepare derivative works of the software, in each case subject to
14
+ the limitations and conditions below.
15
+
16
+ ## Limitations
17
+
18
+ You may not provide the software to third parties as a hosted or managed
19
+ service, where the service provides users with access to any substantial set of
20
+ the features or functionality of the software.
21
+
22
+ You may not move, change, disable, or circumvent the license key functionality
23
+ in the software, and you may not remove or obscure any functionality in the
24
+ software that is protected by the license key.
25
+
26
+ You may not alter, remove, or obscure any licensing, copyright, or other notices
27
+ of the licensor in the software. Any use of the licensor’s trademarks is subject
28
+ to applicable law.
29
+
30
+ ## Patents
31
+
32
+ The licensor grants you a license, under any patent claims the licensor can
33
+ license, or becomes able to license, to make, have made, use, sell, offer for
34
+ sale, import and have imported the software, in each case subject to the
35
+ limitations and conditions in this license. This license does not cover any
36
+ patent claims that you cause to be infringed by modifications or additions to
37
+ the software. If you or your company make any written claim that the software
38
+ infringes or contributes to infringement of any patent, your patent license for
39
+ the software granted under these terms ends immediately. If your company makes
40
+ such a claim, your patent license ends immediately for work on behalf of your
41
+ company.
42
+
43
+ ## Notices
44
+
45
+ You must ensure that anyone who gets a copy of any part of the software from you
46
+ also gets a copy of these terms.
47
+
48
+ If you modify the software, you must include in any modified copies of the
49
+ software prominent notices stating that you have modified the software.
50
+
51
+ ## No Other Rights
52
+
53
+ These terms do not imply any licenses other than those expressly granted in
54
+ these terms.
55
+
56
+ ## Termination
57
+
58
+ If you use the software in violation of these terms, such use is not licensed,
59
+ and your licenses will automatically terminate. If the licensor provides you
60
+ with a notice of your violation, and you cease all violation of this license no
61
+ later than 30 days after you receive that notice, your licenses will be
62
+ reinstated retroactively. However, if you violate these terms after such
63
+ reinstatement, any additional violation of these terms will cause your licenses
64
+ to terminate automatically and permanently.
65
+
66
+ ## No Liability
67
+
68
+ *As far as the law allows, the software comes as is, without any warranty or
69
+ condition, and the licensor will not be liable to you for any damages arising
70
+ out of these terms or the use or nature of the software, under any kind of
71
+ legal claim.*
72
+
73
+ ## Definitions
74
+
75
+ The **licensor** is the entity offering these terms, and the **software** is the
76
+ software the licensor makes available under these terms, including any portion
77
+ of it.
78
+
79
+ **you** refers to the individual or entity agreeing to these terms.
80
+
81
+ **your company** is any legal entity, sole proprietorship, or other kind of
82
+ organization that you work for, plus all organizations that have control over,
83
+ are under the control of, or are under common control with that
84
+ organization. **control** means ownership of substantially all the assets of an
85
+ entity, or the power to direct its management and policies by vote, contract, or
86
+ otherwise. Control can be direct or indirect.
87
+
88
+ **your licenses** are all the licenses granted to you for the software under
89
+ these terms.
90
+
91
+ **use** means anything you do with the software requiring one of your licenses.
92
+
93
+ **trademark** means trademarks, service marks, and similar rights.
package/README.md ADDED
@@ -0,0 +1,135 @@
1
+ # @aigne/cli
2
+
3
+ [![GitHub star chart](https://img.shields.io/github/stars/AIGNE-io/aigne-framework?style=flat-square)](https://star-history.com/#AIGNE-io/aigne-framework)
4
+ [![Open Issues](https://img.shields.io/github/issues-raw/AIGNE-io/aigne-framework?style=flat-square)](https://github.com/AIGNE-io/aigne-framework/issues)
5
+ [![codecov](https://codecov.io/gh/AIGNE-io/aigne-framework/graph/badge.svg?token=DO07834RQL)](https://codecov.io/gh/AIGNE-io/aigne-framework)
6
+ [![NPM Version](https://img.shields.io/npm/v/@aigne/cli)](https://www.npmjs.com/package/@aigne/cli)
7
+ [![Elastic-2.0 licensed](https://img.shields.io/npm/l/@aigne/cli)](https://github.com/AIGNE-io/aigne-framework/blob/main/LICENSE)
8
+
9
+ **English** | [中文](README.zh.md)
10
+
11
+ Command-line tool for [AIGNE Framework](https://github.com/AIGNE-io/aigne-framework), providing convenient development and management capabilities.
12
+
13
+ ## Introduction
14
+
15
+ `@aigne/cli` is the official command-line tool for [AIGNE Framework](https://github.com/AIGNE-io/aigne-framework), designed to simplify the development, testing, and deployment processes for AIGNE applications. It provides a series of useful commands to help developers quickly create projects, run agents, test code, and deploy applications.
16
+
17
+ ## Features
18
+
19
+ - **Project Creation**: Quickly create new AIGNE projects with predefined file structures and configurations
20
+ - **Agent Running**: Easily run and test AIGNE agents
21
+ - **Testing Support**: Built-in test command for unit testing and integration testing
22
+ - **MCP Services**: Support for launching agents as MCP servers for integration with external systems
23
+ - **Interactive Interface**: Beautiful command-line interface providing an intuitive user experience
24
+ - **Multi-model Support**: Support for OpenAI, Claude, XAI, and other model providers
25
+
26
+ ## Installation
27
+
28
+ ```bash
29
+ # Using npm
30
+ npm install -g @aigne/cli
31
+
32
+ # Using yarn
33
+ yarn global add @aigne/cli
34
+
35
+ # Using pnpm
36
+ pnpm add -g @aigne/cli
37
+ ```
38
+
39
+ ## Basic Commands
40
+
41
+ AIGNE CLI provides the following main commands:
42
+
43
+ ```bash
44
+ # Display help information
45
+ aigne --help
46
+
47
+ # Create a new project
48
+ aigne create [path]
49
+
50
+ # Run an agent
51
+ aigne run [path]
52
+
53
+ # Run tests
54
+ aigne test [path]
55
+
56
+ # Start MCP server
57
+ aigne serve [path] --mcp
58
+ ```
59
+
60
+ ## Create Command
61
+
62
+ Create a new AIGNE project with agent configuration files.
63
+
64
+ ```bash
65
+ # Create a project in the current directory (will prompt for project name)
66
+ aigne create
67
+
68
+ # Create a project at the specified path
69
+ aigne create my-project
70
+ ```
71
+
72
+ The interactive creation process will ask for:
73
+ - Project name
74
+ - Project template (currently supports the default template)
75
+
76
+ ## Run Command
77
+
78
+ Launch a chat loop with the specified agent.
79
+
80
+ ```bash
81
+ # Run the agent in the current directory
82
+ aigne run
83
+
84
+ # Run the agent at the specified path
85
+ aigne run path/to/agents
86
+
87
+ # Run the agent from a remote URL
88
+ aigne run https://example.com/aigne-project
89
+ ```
90
+
91
+ Available options:
92
+ - `--agent <agent>` - Specify the agent name to use (defaults to the first agent found)
93
+ - `--download-dir <dir>` - Specify the directory to download the package to (used in URL mode)
94
+ - `--model-provider <provider>` - Specify the model provider (openai, claude, xai)
95
+ - `--model-name <model>` - Specify the model name
96
+ - `--verbose` - Enable verbose logging
97
+
98
+ ## Test Command
99
+
100
+ Run tests in the specified agents directory.
101
+
102
+ ```bash
103
+ # Test the agents in the current directory
104
+ aigne test
105
+
106
+ # Test the agents at the specified path
107
+ aigne test path/to/agents
108
+ ```
109
+
110
+ ## Serve Command
111
+
112
+ Serve the agents in the specified directory as a MCP server.
113
+
114
+ ```bash
115
+ # Start MCP server on default port 3000
116
+ aigne serve --mcp
117
+
118
+ # Start MCP server on specified port
119
+ aigne serve --mcp --port 3001
120
+
121
+ # Start MCP server for agents at specified path
122
+ aigne serve path/to/agents --mcp
123
+ ```
124
+
125
+ ## Documentation
126
+
127
+ For more detailed CLI usage guides, please refer to:
128
+
129
+ - [CLI Guide](../../docs/cli.md)
130
+ - [Agent Development Guide](../../docs/agent-development.md)
131
+ - [Cookbook](../../docs/cookbook.md)
132
+
133
+ ## License
134
+
135
+ Elastic-2.0
package/README.zh.md ADDED
@@ -0,0 +1,135 @@
1
+ # @aigne/cli
2
+
3
+ [![GitHub star chart](https://img.shields.io/github/stars/AIGNE-io/aigne-framework?style=flat-square)](https://star-history.com/#AIGNE-io/aigne-framework)
4
+ [![Open Issues](https://img.shields.io/github/issues-raw/AIGNE-io/aigne-framework?style=flat-square)](https://github.com/AIGNE-io/aigne-framework/issues)
5
+ [![codecov](https://codecov.io/gh/AIGNE-io/aigne-framework/graph/badge.svg?token=DO07834RQL)](https://codecov.io/gh/AIGNE-io/aigne-framework)
6
+ [![NPM Version](https://img.shields.io/npm/v/@aigne/cli)](https://www.npmjs.com/package/@aigne/cli)
7
+ [![Elastic-2.0 licensed](https://img.shields.io/npm/l/@aigne/cli)](https://github.com/AIGNE-io/aigne-framework/blob/main/LICENSE)
8
+
9
+ [English](README.md) | **中文**
10
+
11
+ [AIGNE 框架](https://github.com/AIGNE-io/aigne-framework)的命令行工具,提供便捷的开发和管理功能。
12
+
13
+ ## 简介
14
+
15
+ `@aigne/cli` 是 [AIGNE 框架](https://github.com/AIGNE-io/aigne-framework)的官方命令行工具,旨在简化 AIGNE 应用的开发、测试和部署流程。它提供了一系列实用命令,帮助开发者快速创建项目、运行代理、测试代码,以及部署应用等。
16
+
17
+ ## 特性
18
+
19
+ - **项目创建**:快速创建新的 AIGNE 项目,包含预设的文件结构和配置
20
+ - **代理运行**:轻松运行和测试 AIGNE 代理
21
+ - **测试支持**:内置测试命令,方便进行单元测试和集成测试
22
+ - **MCP 服务**:支持将代理作为 MCP 服务器启动,与外部系统集成
23
+ - **交互式界面**:美观的命令行界面,提供直观的使用体验
24
+ - **多模型支持**:支持 OpenAI、Claude、XAI 等多种模型提供商
25
+
26
+ ## 安装
27
+
28
+ ```bash
29
+ # 使用 npm
30
+ npm install -g @aigne/cli
31
+
32
+ # 使用 yarn
33
+ yarn global add @aigne/cli
34
+
35
+ # 使用 pnpm
36
+ pnpm add -g @aigne/cli
37
+ ```
38
+
39
+ ## 基本命令
40
+
41
+ AIGNE CLI 提供了以下主要命令:
42
+
43
+ ```bash
44
+ # 显示帮助信息
45
+ aigne --help
46
+
47
+ # 创建新项目
48
+ aigne create [path]
49
+
50
+ # 运行代理
51
+ aigne run [path]
52
+
53
+ # 运行测试
54
+ aigne test [path]
55
+
56
+ # 启动 MCP 服务器
57
+ aigne serve [path] --mcp
58
+ ```
59
+
60
+ ## 创建命令 (create)
61
+
62
+ 创建一个带有代理配置文件的新 AIGNE 项目。
63
+
64
+ ```bash
65
+ # 在当前目录创建项目(会提示输入项目名称)
66
+ aigne create
67
+
68
+ # 在指定路径创建项目
69
+ aigne create my-project
70
+ ```
71
+
72
+ 交互式创建过程会询问:
73
+ - 项目名称
74
+ - 项目模板(目前支持 default 模板)
75
+
76
+ ## 运行命令 (run)
77
+
78
+ 启动与指定代理的聊天循环。
79
+
80
+ ```bash
81
+ # 运行当前目录中的代理
82
+ aigne run
83
+
84
+ # 运行指定路径中的代理
85
+ aigne run path/to/agents
86
+
87
+ # 运行远程 URL 中的代理
88
+ aigne run https://example.com/aigne-project
89
+ ```
90
+
91
+ 可用选项:
92
+ - `--agent <agent>` - 指定要使用的代理名称(默认为找到的第一个代理)
93
+ - `--download-dir <dir>` - 指定下载包的目录(URL模式下使用)
94
+ - `--model-provider <provider>` - 指定模型提供商(openai、claude、xai)
95
+ - `--model-name <model>` - 指定模型名称
96
+ - `--verbose` - 启用详细日志记录
97
+
98
+ ## 测试命令 (test)
99
+
100
+ 在指定的代理目录中运行测试。
101
+
102
+ ```bash
103
+ # 测试当前目录中的代理
104
+ aigne test
105
+
106
+ # 测试指定路径中的代理
107
+ aigne test path/to/agents
108
+ ```
109
+
110
+ ## 服务命令 (serve)
111
+
112
+ 将指定目录中的代理作为 MCP 服务器提供服务。
113
+
114
+ ```bash
115
+ # 在默认端口 3000 启动 MCP 服务器
116
+ aigne serve --mcp
117
+
118
+ # 在指定端口启动 MCP 服务器
119
+ aigne serve --mcp --port 3001
120
+
121
+ # 为指定路径的代理启动 MCP 服务器
122
+ aigne serve path/to/agents --mcp
123
+ ```
124
+
125
+ ## 文档
126
+
127
+ 更多详细的 CLI 使用指南,请参考:
128
+
129
+ - [CLI 指南](../../docs/cli.zh.md)
130
+ - [代理开发指南](../../docs/agent-development.zh.md)
131
+ - [Cookbook](../../docs/cookbook.zh.md)
132
+
133
+ ## 协议
134
+
135
+ Elastic-2.0
@@ -4,6 +4,7 @@ import { homedir } from "node:os";
4
4
  import { isAbsolute, join, resolve } from "node:path";
5
5
  import { ExecutionEngine } from "@aigne/core";
6
6
  import { loadModel } from "@aigne/core/loader/index.js";
7
+ import { logger } from "@aigne/core/utils/logger.js";
7
8
  import { isNonNullable } from "@aigne/core/utils/type-utils.js";
8
9
  import { Listr, PRESET_TIMER } from "@aigne/listr2";
9
10
  import { Command } from "commander";
@@ -18,7 +19,10 @@ export function createRunCommand() {
18
19
  .option("--download-dir <dir>", "Directory to download the package to (defaults to the ~/.aigne/xxx)")
19
20
  .option("--model-provider <provider>", "Model provider to use, available providers: openai, claude, xai (defaults to the aigne.yaml definition or openai)")
20
21
  .option("--model-name <model>", "Model name to use, available models depend on the provider (defaults to the aigne.yaml definition or gpt-4o-mini)")
22
+ .option("--verbose", "Enable verbose logging", false)
21
23
  .action(async (path, options) => {
24
+ if (options.verbose)
25
+ logger.enable("*");
22
26
  const { downloadDir, dir } = prepareDirs(path, options);
23
27
  const { engine, agent } = await new Listr([
24
28
  {
@@ -78,7 +82,7 @@ export function createRunCommand() {
78
82
  assert(engine);
79
83
  assert(agent);
80
84
  const user = engine.call(agent);
81
- await runChatLoopInTerminal(user, {});
85
+ await runChatLoopInTerminal(user);
82
86
  await engine.shutdown();
83
87
  })
84
88
  .showHelpAfterError(true)
@@ -3,7 +3,6 @@ import type { ContextUsage } from "@aigne/core/execution-engine/usage";
3
3
  import { type DefaultRenderer, Listr, type ListrRenderer, type ListrTaskWrapper } from "@aigne/listr2";
4
4
  import { promiseWithResolvers } from "../utils/promise-with-resolvers.js";
5
5
  export interface TerminalTracerOptions {
6
- verbose?: boolean;
7
6
  aiResponsePrefix?: (context: Context) => string;
8
7
  }
9
8
  export declare class TerminalTracer {
@@ -16,11 +15,6 @@ export declare class TerminalTracer {
16
15
  result: Message;
17
16
  context: Context;
18
17
  }>;
19
- protected wrap(str: string): string;
20
- formatAgentStartedOutput(agent: Agent, data: Message): string;
21
- formatAgentSucceedOutput(agent: Agent, data: Message): string;
22
- formatAgentFailedOutput(agent: Agent, data: Error): string;
23
- formatMessage(data: unknown): string;
24
18
  formatTokenUsage(usage: Partial<ContextUsage>, extra?: {
25
19
  [key: string]: string;
26
20
  }): string;
@@ -1,16 +1,15 @@
1
1
  import { EOL } from "node:os";
2
- import { inspect } from "node:util";
2
+ import { format, inspect } from "node:util";
3
3
  import { ChatModel, MESSAGE_KEY, } from "@aigne/core";
4
+ import { logger } from "@aigne/core/utils/logger.js";
4
5
  import { mergeAgentResponseChunk, readableStreamToAsyncIterator, } from "@aigne/core/utils/stream-utils.js";
5
- import { Listr, ListrDefaultRendererLogLevels, Spinner, figures, } from "@aigne/listr2";
6
+ import { Listr, ListrDefaultRendererLogLevels, Spinner, } from "@aigne/listr2";
7
+ import { markedTerminal } from "@aigne/marked-terminal";
6
8
  import chalk from "chalk";
7
9
  import { Marked } from "marked";
8
- import { markedTerminal } from "marked-terminal";
9
10
  import wrap from "wrap-ansi";
10
- import { z } from "zod";
11
11
  import { promiseWithResolvers } from "../utils/promise-with-resolvers.js";
12
12
  import { parseDuration } from "../utils/time.js";
13
- const DEBUG_DEPTH = z.number().int().default(2).safeParse(Number(process.env.DEBUG_DEPTH)).data;
14
13
  export class TerminalTracer {
15
14
  context;
16
15
  options;
@@ -25,14 +24,10 @@ export class TerminalTracer {
25
24
  const context = this.context.newContext({ reset: true });
26
25
  const listr = new AIGNEListr({
27
26
  formatResult: (result) => {
28
- return [
29
- this.wrap(this.options.aiResponsePrefix?.(context) || ""),
30
- this.wrap(this.formatAIResponse(result)),
31
- ];
27
+ return [this.options.aiResponsePrefix?.(context) || "", this.formatAIResponse(result)];
32
28
  },
33
29
  }, [], {
34
30
  concurrent: true,
35
- forceTTY: true,
36
31
  rendererOptions: {
37
32
  collapseSubtasks: false,
38
33
  writeBottomBarDirectly: true,
@@ -42,7 +37,7 @@ export class TerminalTracer {
42
37
  },
43
38
  },
44
39
  });
45
- const onAgentStarted = async ({ contextId, parentContextId, agent, input, timestamp, }) => {
40
+ const onAgentStarted = async ({ contextId, parentContextId, agent, timestamp, }) => {
46
41
  const task = {
47
42
  ...promiseWithResolvers(),
48
43
  listr: promiseWithResolvers(),
@@ -71,10 +66,6 @@ export class TerminalTracer {
71
66
  else {
72
67
  listr.add(listrTask);
73
68
  }
74
- const { taskWrapper } = await task.listr.promise;
75
- if (this.options.verbose) {
76
- taskWrapper.output = this.formatAgentStartedOutput(agent, input);
77
- }
78
69
  };
79
70
  const onAgentSucceed = async ({ agent, contextId, parentContextId, output, timestamp, }) => {
80
71
  const task = this.tasks[contextId];
@@ -90,9 +81,6 @@ export class TerminalTracer {
90
81
  task.extraTitleMetadata.model = model;
91
82
  }
92
83
  taskWrapper.title = this.formatTaskTitle(agent, { task, usage: true, time: true });
93
- if (this.options.verbose) {
94
- taskWrapper.output = this.formatAgentSucceedOutput(agent, output);
95
- }
96
84
  if (!parentContextId || !this.tasks[parentContextId]) {
97
85
  Object.assign(ctx, output);
98
86
  }
@@ -105,7 +93,6 @@ export class TerminalTracer {
105
93
  task.endTime = timestamp;
106
94
  const { taskWrapper } = await task.listr.promise;
107
95
  taskWrapper.title = this.formatTaskTitle(agent, { task, usage: true, time: true });
108
- taskWrapper.output = this.formatAgentFailedOutput(agent, error);
109
96
  task.reject(error);
110
97
  };
111
98
  context.on("agentStarted", onAgentStarted);
@@ -123,30 +110,6 @@ export class TerminalTracer {
123
110
  context.off("agentFailed", onAgentFailed);
124
111
  }
125
112
  }
126
- wrap(str) {
127
- return wrap(str, process.stdout.columns ?? 80, {
128
- hard: true,
129
- trim: false,
130
- });
131
- }
132
- formatAgentStartedOutput(agent, data) {
133
- return `\
134
- ${chalk.grey(figures.pointer)} call agent ${agent.name} started with input:
135
- ${this.formatMessage(data)}`;
136
- }
137
- formatAgentSucceedOutput(agent, data) {
138
- return `\
139
- ${chalk.grey(figures.tick)} call agent ${agent.name} succeed with output:
140
- ${this.formatMessage(data)}`;
141
- }
142
- formatAgentFailedOutput(agent, data) {
143
- return `\
144
- ${chalk.grey(figures.cross)} call agent ${agent.name} failed with error:
145
- ${this.formatMessage(data)}`;
146
- }
147
- formatMessage(data) {
148
- return inspect(data, { colors: true, depth: DEBUG_DEPTH });
149
- }
150
113
  formatTokenUsage(usage, extra) {
151
114
  const items = [
152
115
  [chalk.yellow(usage.inputTokens), chalk.grey("input tokens")],
@@ -173,7 +136,7 @@ ${this.formatMessage(data)}`;
173
136
  title += ` ${this.formatTimeUsage(task.startTime, task.endTime)}`;
174
137
  return title;
175
138
  }
176
- marked = new Marked().use(markedTerminal());
139
+ marked = new Marked().use(markedTerminal({ forceHyperLink: false }));
177
140
  formatAIResponse({ [MESSAGE_KEY]: msg, ...message } = {}) {
178
141
  const text = msg && typeof msg === "string" ? this.marked.parse(msg, { async: false }).trim() : undefined;
179
142
  const json = Object.keys(message).length > 0 ? inspect(message, { colors: true }) : undefined;
@@ -184,6 +147,7 @@ class AIGNEListr extends Listr {
184
147
  myOptions;
185
148
  result = {};
186
149
  isStreamRunning = false;
150
+ logs = [];
187
151
  constructor(myOptions, ...args) {
188
152
  super(...args);
189
153
  this.myOptions = myOptions;
@@ -197,17 +161,24 @@ class AIGNEListr extends Listr {
197
161
  "",
198
162
  tasks,
199
163
  "",
200
- ...[this.myOptions.formatResult(this.result)].flat(),
164
+ ...this.myOptions.formatResult(this.result).map((i) => this.wrap(i)),
201
165
  this.isStreamRunning ? spinner.fetch() : "",
202
166
  ];
203
- return [l.join(EOL), output];
167
+ return [l.join(EOL), [output, ...this.logs.splice(0)].filter(Boolean).join(EOL)];
204
168
  };
205
169
  // @ts-ignore initialize the renderer
206
170
  this.renderer = renderer;
207
171
  }
208
172
  async run(stream) {
209
- this.add({ task: () => this.extractStream(stream) });
210
- return await super.run().then(() => ({ ...this.result }));
173
+ const originalLog = logger.log;
174
+ try {
175
+ logger.log = (...args) => this.logs.push(format(...args));
176
+ this.add({ task: () => this.extractStream(stream) });
177
+ return await super.run().then(() => ({ ...this.result }));
178
+ }
179
+ finally {
180
+ logger.log = originalLog;
181
+ }
211
182
  }
212
183
  async extractStream(stream) {
213
184
  this.isStreamRunning = true;
@@ -218,4 +189,10 @@ class AIGNEListr extends Listr {
218
189
  this.isStreamRunning = false;
219
190
  return this.result;
220
191
  }
192
+ wrap(str) {
193
+ return wrap(str, process.stdout.columns ?? 80, {
194
+ hard: true,
195
+ trim: false,
196
+ });
197
+ }
221
198
  }
@@ -4,7 +4,6 @@ export interface ChatLoopOptions {
4
4
  welcome?: string;
5
5
  defaultQuestion?: string;
6
6
  inputKey?: string;
7
- verbose?: boolean;
8
7
  skipLoop?: boolean;
9
8
  }
10
9
  export declare function runChatLoopInTerminal(userAgent: input, options?: ChatLoopOptions): Promise<void>;
@@ -1,14 +1,10 @@
1
1
  import { createMessage } from "@aigne/core";
2
- import { logger } from "@aigne/core/utils/logger.js";
3
2
  import { figures } from "@aigne/listr2";
4
3
  import chalk from "chalk";
5
4
  import inquirer from "inquirer";
6
5
  import { TerminalTracer } from "../tracer/terminal.js";
7
6
  export async function runChatLoopInTerminal(userAgent, options = {}) {
8
7
  const { initialCall = process.env.INITIAL_CALL, skipLoop = process.env.SKIP_LOOP === "true" } = options;
9
- options.verbose ??= logger.enabled("aigne:core");
10
- // Disable the logger, use TerminalTracer instead
11
- logger.disable();
12
8
  let prompt;
13
9
  if (options?.welcome)
14
10
  console.log(options.welcome);
@@ -49,7 +45,6 @@ export async function runChatLoopInTerminal(userAgent, options = {}) {
49
45
  }
50
46
  async function callAgent(userAgent, input, options) {
51
47
  const tracer = new TerminalTracer(userAgent.context, {
52
- verbose: options.verbose,
53
48
  aiResponsePrefix: (context) => {
54
49
  return `${chalk.grey(figures.tick)} 🤖 ${tracer.formatTokenUsage(context.usage)}`;
55
50
  },
package/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "@aigne/cli",
3
- "version": "1.5.1",
3
+ "version": "1.7.0",
4
4
  "description": "cli for AIGNE framework",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
8
8
  "author": "Arcblock <blocklet@arcblock.io> https://github.com/blocklet",
9
9
  "homepage": "https://github.com/AIGNE-io/aigne-framework",
10
- "license": "ISC",
10
+ "license": "Elastic-2.0",
11
11
  "repository": {
12
12
  "type": "git",
13
13
  "url": "git+https://github.com/AIGNE-io/aigne-framework"
@@ -36,6 +36,7 @@
36
36
  },
37
37
  "dependencies": {
38
38
  "@aigne/listr2": "^1.0.8",
39
+ "@aigne/marked-terminal": "^7.3.1",
39
40
  "@modelcontextprotocol/sdk": "^1.9.0",
40
41
  "chalk": "^5.4.1",
41
42
  "commander": "^13.1.0",
@@ -44,13 +45,12 @@
44
45
  "gradient-string": "^3.0.0",
45
46
  "inquirer": "^12.5.2",
46
47
  "marked": "^15.0.9",
47
- "marked-terminal": "^7.3.0",
48
48
  "openai": "^4.94.0",
49
49
  "prettier": "^3.5.3",
50
50
  "pretty-error": "^4.0.0",
51
51
  "tar": "^7.4.3",
52
52
  "zod": "^3.24.2",
53
- "@aigne/core": "^1.10.0"
53
+ "@aigne/core": "^1.11.0"
54
54
  },
55
55
  "devDependencies": {
56
56
  "@types/archiver": "^6.0.3",
@@ -3,5 +3,8 @@ description: Chat agent
3
3
  instructions: |
4
4
  You are a helpful assistant that can answer questions and provide information on a wide range of topics.
5
5
  Your goal is to assist users in finding the information they need and to engage in friendly conversation.
6
+ memory:
7
+ subscribeTopic:
8
+ - chat
6
9
  tools:
7
10
  - sandbox.js