@aigne/cli 1.6.0 → 1.8.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,40 @@
1
1
  # Changelog
2
2
 
3
+ ## [1.8.0](https://github.com/AIGNE-io/aigne-framework/compare/cli-v1.7.0...cli-v1.8.0) (2025-04-27)
4
+
5
+
6
+ ### Features
7
+
8
+ * support TeamAgent and finalize API naming ([#91](https://github.com/AIGNE-io/aigne-framework/issues/91)) ([033d1b6](https://github.com/AIGNE-io/aigne-framework/commit/033d1b6a7dc5460807476abb35a413ba89a2a664))
9
+
10
+
11
+ ### Bug Fixes
12
+
13
+ * upgrade to streamable api for serve mcp command ([#98](https://github.com/AIGNE-io/aigne-framework/issues/98)) ([ae32bda](https://github.com/AIGNE-io/aigne-framework/commit/ae32bda20e57c2a2eb8b49fad034b0b2a5ebb15e))
14
+
15
+
16
+ ### Dependencies
17
+
18
+ * The following workspace dependencies were updated
19
+ * dependencies
20
+ * @aigne/core bumped to 1.12.0
21
+
22
+ ## [1.7.0](https://github.com/AIGNE-io/aigne-framework/compare/cli-v1.6.0...cli-v1.7.0) (2025-04-23)
23
+
24
+
25
+ ### Features
26
+
27
+ * **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))
28
+ * 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))
29
+ * **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))
30
+
31
+
32
+ ### Dependencies
33
+
34
+ * The following workspace dependencies were updated
35
+ * dependencies
36
+ * @aigne/core bumped to 1.11.0
37
+
3
38
  ## [1.6.0](https://github.com/AIGNE-io/aigne-framework/compare/cli-v1.5.1...cli-v1.6.0) (2025-04-22)
4
39
 
5
40
 
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
@@ -1,5 +1,5 @@
1
1
  import { Command } from "commander";
2
- import pkg from "../../package.json" with { type: "json" };
2
+ import { AIGNE_CLI_VERSION } from "../constants.js";
3
3
  import { asciiLogo } from "../utils/ascii-logo.js";
4
4
  import { createCreateCommand } from "./create.js";
5
5
  import { createRunCommand } from "./run.js";
@@ -10,7 +10,7 @@ export function createAIGNECommand() {
10
10
  return new Command()
11
11
  .name("aigne")
12
12
  .description("CLI for AIGNE framework")
13
- .version(pkg.version)
13
+ .version(AIGNE_CLI_VERSION)
14
14
  .addCommand(createRunCommand())
15
15
  .addCommand(createTestCommand())
16
16
  .addCommand(createCreateCommand())
@@ -2,7 +2,7 @@ import assert from "node:assert";
2
2
  import { cp, mkdir, rm } from "node:fs/promises";
3
3
  import { homedir } from "node:os";
4
4
  import { isAbsolute, join, resolve } from "node:path";
5
- import { ExecutionEngine } from "@aigne/core";
5
+ import { AIGNE } from "@aigne/core";
6
6
  import { loadModel } from "@aigne/core/loader/index.js";
7
7
  import { logger } from "@aigne/core/utils/logger.js";
8
8
  import { isNonNullable } from "@aigne/core/utils/type-utils.js";
@@ -24,7 +24,7 @@ export function createRunCommand() {
24
24
  if (options.verbose)
25
25
  logger.enable("*");
26
26
  const { downloadDir, dir } = prepareDirs(path, options);
27
- const { engine, agent } = await new Listr([
27
+ const { aigne, agent } = await new Listr([
28
28
  {
29
29
  title: "Prepare environment",
30
30
  task: (_, task) => {
@@ -43,30 +43,30 @@ export function createRunCommand() {
43
43
  },
44
44
  },
45
45
  {
46
- title: "Initialize execution engine",
46
+ title: "Initialize AIGNE",
47
47
  task: async (ctx) => {
48
- const engine = await runEngine(dir, options);
49
- ctx.engine = engine;
48
+ const aigne = await loadAIGNE(dir, options);
49
+ ctx.aigne = aigne;
50
50
  },
51
51
  },
52
52
  {
53
53
  task: (ctx) => {
54
- const { engine } = ctx;
55
- assert(engine);
54
+ const { aigne } = ctx;
55
+ assert(aigne);
56
56
  let agent;
57
57
  if (options.agent) {
58
- agent = engine.agents[options.agent];
58
+ agent = aigne.agents[options.agent];
59
59
  if (!agent) {
60
60
  console.error(`Agent "${options.agent}" not found in ${path}`);
61
61
  console.log("Available agents:");
62
- for (const agent of engine.agents) {
62
+ for (const agent of aigne.agents) {
63
63
  console.log(`- ${agent.name}`);
64
64
  }
65
65
  throw new Error(`Agent "${options.agent}" not found in ${path}`);
66
66
  }
67
67
  }
68
68
  else {
69
- agent = engine.agents[0];
69
+ agent = aigne.agents[0];
70
70
  if (!agent)
71
71
  throw new Error(`No agents found in ${path}`);
72
72
  }
@@ -79,23 +79,23 @@ export function createRunCommand() {
79
79
  timer: PRESET_TIMER,
80
80
  },
81
81
  }).run();
82
- assert(engine);
82
+ assert(aigne);
83
83
  assert(agent);
84
- const user = engine.call(agent);
84
+ const user = aigne.invoke(agent);
85
85
  await runChatLoopInTerminal(user);
86
- await engine.shutdown();
86
+ await aigne.shutdown();
87
87
  })
88
88
  .showHelpAfterError(true)
89
89
  .showSuggestionAfterError(true);
90
90
  }
91
- async function runEngine(path, options) {
91
+ async function loadAIGNE(path, options) {
92
92
  if (options.modelName && !options.modelProvider) {
93
93
  throw new Error("please specify --model-provider when using the --model-name option");
94
94
  }
95
95
  const model = options.modelProvider
96
96
  ? await loadModel({ provider: options.modelProvider, name: options.modelName })
97
97
  : undefined;
98
- return await ExecutionEngine.load({ path, model });
98
+ return await AIGNE.load({ path, model });
99
99
  }
100
100
  async function downloadPackage(url, downloadDir) {
101
101
  await rm(downloadDir, { recursive: true, force: true });
@@ -1,5 +1,5 @@
1
1
  import { isAbsolute, resolve } from "node:path";
2
- import { ExecutionEngine } from "@aigne/core";
2
+ import { AIGNE } from "@aigne/core";
3
3
  import { tryOrThrow } from "@aigne/core/utils/type-utils.js";
4
4
  import { Command } from "commander";
5
5
  import { serveMCPServer } from "../utils/serve-mcp.js";
@@ -17,15 +17,23 @@ export function createServeCommand() {
17
17
  .description("Serve the agents in the specified directory as a MCP server")
18
18
  .argument("[path]", "Path to the agents directory", ".")
19
19
  .option("--mcp", "Serve the agents as a MCP server")
20
+ .option("--host <host>", "Host to run the MCP server on, use 0.0.0.0 to publicly expose the server", "localhost")
20
21
  .option("--port <port>", "Port to run the MCP server on", (s) => Number.parseInt(s))
22
+ .option("--pathname <pathname>", "Pathname to the service", "/mcp")
21
23
  .action(async (path, options) => {
22
24
  const absolutePath = isAbsolute(path) ? path : resolve(process.cwd(), path);
23
25
  const port = options.port || DEFAULT_PORT();
24
- const engine = await ExecutionEngine.load({ path: absolutePath });
26
+ const aigne = await AIGNE.load({ path: absolutePath });
25
27
  if (options.mcp)
26
- await serveMCPServer({ engine, port });
28
+ await serveMCPServer({
29
+ aigne,
30
+ host: options.host,
31
+ port,
32
+ pathname: options.pathname,
33
+ });
27
34
  else
28
35
  throw new Error("Default server is not supported yet. Please use --mcp option");
36
+ console.log(`MCP server is running on http://${options.host}:${port}${options.pathname}`);
29
37
  })
30
38
  .showHelpAfterError(true)
31
39
  .showSuggestionAfterError(true);
@@ -0,0 +1 @@
1
+ export declare const AIGNE_CLI_VERSION: string;
@@ -0,0 +1,2 @@
1
+ import pkg from "../package.json" with { type: "json" };
2
+ export const AIGNE_CLI_VERSION = pkg.version;
@@ -1,5 +1,4 @@
1
- import { type Agent, type Context, MESSAGE_KEY, type Message } from "@aigne/core";
2
- import type { ContextUsage } from "@aigne/core/execution-engine/usage";
1
+ import { type Agent, type Context, type ContextUsage, MESSAGE_KEY, type Message } from "@aigne/core";
3
2
  import { type DefaultRenderer, Listr, type ListrRenderer, type ListrTaskWrapper } from "@aigne/listr2";
4
3
  import { promiseWithResolvers } from "../utils/promise-with-resolvers.js";
5
4
  export interface TerminalTracerOptions {
@@ -28,7 +28,6 @@ export class TerminalTracer {
28
28
  },
29
29
  }, [], {
30
30
  concurrent: true,
31
- forceTTY: true,
32
31
  rendererOptions: {
33
32
  collapseSubtasks: false,
34
33
  writeBottomBarDirectly: true,
@@ -100,7 +99,7 @@ export class TerminalTracer {
100
99
  context.on("agentSucceed", onAgentSucceed);
101
100
  context.on("agentFailed", onAgentFailed);
102
101
  try {
103
- const stream = await context.call(agent, input, { streaming: true });
102
+ const stream = await context.invoke(agent, input, { streaming: true });
104
103
  const result = await listr.run(stream);
105
104
  return { result, context };
106
105
  }
@@ -130,7 +129,7 @@ export class TerminalTracer {
130
129
  return chalk.grey(`[${parseDuration(duration)}]`);
131
130
  }
132
131
  formatTaskTitle(agent, { task, usage, time } = {}) {
133
- let title = `call agent ${agent.name}`;
132
+ let title = `invoke agent ${agent.name}`;
134
133
  if (usage && task?.usage)
135
134
  title += ` ${this.formatTokenUsage(task.usage, task.extraTitleMetadata)}`;
136
135
  if (time && task?.startTime && task.endTime)
@@ -43,15 +43,15 @@ async function loadAgentV1Package(path) {
43
43
  return definition;
44
44
  }
45
45
  function assistantToAigneV2(agent, project) {
46
- const converter = RUNNABLE_MAP[agent.type];
46
+ const converter = AGENT_MAP[agent.type];
47
47
  if (!converter)
48
- throw new Error(`Unsupported runnable type: ${agent.type}`);
48
+ throw new Error(`Unsupported agent type: ${agent.type}`);
49
49
  return converter(agent, project);
50
50
  }
51
- const RUNNABLE_MAP = {
51
+ const AGENT_MAP = {
52
52
  prompt: (agent) => {
53
53
  if (agent.type !== "prompt")
54
- throw new Error(`Expected runnable type 'prompt', but got '${agent.type}'`);
54
+ throw new Error(`Expected agent type 'prompt', but got '${agent.type}'`);
55
55
  const obj = {
56
56
  name: agent.name || agent.id,
57
57
  description: agent.description,
@@ -68,7 +68,7 @@ const RUNNABLE_MAP = {
68
68
  },
69
69
  function: async (agent) => {
70
70
  if (agent.type !== "function")
71
- throw new Error(`Expected runnable type 'function', but got '${agent.type}'`);
71
+ throw new Error(`Expected agent type 'function', but got '${agent.type}'`);
72
72
  const inputNames = agent.parameters?.map((i) => i.key).filter(Boolean) ?? [];
73
73
  return {
74
74
  content: await formatCode(`\
@@ -88,7 +88,7 @@ agent.output_schema = ${JSON.stringify(convertOutputSchema(agent))};
88
88
  },
89
89
  router: (agent, project) => {
90
90
  if (agent.type !== "router")
91
- throw new Error(`Expected runnable type 'router', but got '${agent.type}'`);
91
+ throw new Error(`Expected agent type 'router', but got '${agent.type}'`);
92
92
  return {
93
93
  content: stringify({
94
94
  name: agent.name || agent.id,
@@ -96,7 +96,7 @@ agent.output_schema = ${JSON.stringify(convertOutputSchema(agent))};
96
96
  instructions: agent.prompt,
97
97
  input_schema: convertInputSchema(agent),
98
98
  output_schema: convertOutputSchema(agent),
99
- tools: agent.routes?.map((i) => {
99
+ skills: agent.routes?.map((i) => {
100
100
  const tool = project.agents.find((j) => j.id === i.id);
101
101
  if (!tool)
102
102
  throw new Error(`Tool ${i.id} not found in project definition`);
@@ -1,5 +1,9 @@
1
- import { type ExecutionEngine } from "@aigne/core";
2
- export declare function serveMCPServer({ engine, port }: {
3
- engine: ExecutionEngine;
1
+ import { type AIGNE } from "@aigne/core";
2
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
3
+ export declare function serveMCPServer({ pathname, aigne, host, port, }: {
4
+ pathname?: string;
5
+ aigne: AIGNE;
6
+ host?: string;
4
7
  port: number;
5
8
  }): Promise<import("http").Server<typeof import("http").IncomingMessage, typeof import("http").ServerResponse>>;
9
+ export declare function createMcpServer(aigne: AIGNE): McpServer;
@@ -1,23 +1,83 @@
1
1
  import { getMessage } from "@aigne/core";
2
2
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
3
- import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";
4
- import express from "express";
3
+ import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
4
+ import express, { Router, json } from "express";
5
5
  import { ZodObject } from "zod";
6
+ import { AIGNE_CLI_VERSION } from "../constants.js";
6
7
  import { promiseWithResolvers } from "./promise-with-resolvers.js";
7
- export async function serveMCPServer({ engine, port }) {
8
+ export async function serveMCPServer({ pathname = "/mcp", aigne, host = "localhost", port, }) {
9
+ const app = express();
10
+ app.use(json());
11
+ const router = Router();
12
+ app.use(router);
13
+ router.post(pathname, async (req, res) => {
14
+ try {
15
+ const server = createMcpServer(aigne);
16
+ const transport = new StreamableHTTPServerTransport({ sessionIdGenerator: undefined });
17
+ await server.connect(transport);
18
+ await transport.handleRequest(req, res, req.body);
19
+ res.on("close", async () => {
20
+ await transport.close();
21
+ await server.close();
22
+ });
23
+ }
24
+ catch (error) {
25
+ console.error("Error handling MCP request:", error);
26
+ if (!res.headersSent) {
27
+ res.status(500).json({
28
+ jsonrpc: "2.0",
29
+ error: {
30
+ code: -32603,
31
+ message: error.message,
32
+ },
33
+ id: null,
34
+ });
35
+ }
36
+ }
37
+ });
38
+ router.get(pathname, async (_, res) => {
39
+ res.writeHead(405).end(JSON.stringify({
40
+ jsonrpc: "2.0",
41
+ error: {
42
+ code: -32000,
43
+ message: "Method not allowed.",
44
+ },
45
+ id: null,
46
+ }));
47
+ });
48
+ router.delete(pathname, async (_, res) => {
49
+ res.writeHead(405).end(JSON.stringify({
50
+ jsonrpc: "2.0",
51
+ error: {
52
+ code: -32000,
53
+ message: "Method not allowed.",
54
+ },
55
+ id: null,
56
+ }));
57
+ });
58
+ const { promise, resolve, reject } = promiseWithResolvers();
59
+ const httpServer = app.listen(port, host, (error) => {
60
+ if (error)
61
+ reject(error);
62
+ resolve();
63
+ });
64
+ await promise;
65
+ return httpServer;
66
+ }
67
+ export function createMcpServer(aigne) {
8
68
  const server = new McpServer({
9
- name: engine.name || "aigne-mcp-server",
10
- version: "1.0.0",
69
+ name: aigne.name || "aigne-mcp-server",
70
+ version: AIGNE_CLI_VERSION,
11
71
  }, {
12
72
  capabilities: { tools: {} },
13
- instructions: engine.description,
73
+ instructions: aigne.description,
14
74
  });
15
- for (const agent of engine.agents) {
75
+ for (const agent of aigne.agents) {
16
76
  const schema = agent.inputSchema;
17
77
  if (!(schema instanceof ZodObject))
18
78
  throw new Error("Agent input schema must be a ZodObject");
19
79
  server.tool(agent.name, agent.description || "", schema.shape, async (input) => {
20
- const result = await engine.call(agent, input);
80
+ const result = await aigne.invoke(agent, input);
21
81
  return {
22
82
  content: [
23
83
  {
@@ -28,45 +88,5 @@ export async function serveMCPServer({ engine, port }) {
28
88
  };
29
89
  });
30
90
  }
31
- const app = express();
32
- const transports = {};
33
- app.get("/sse", async (req, res) => {
34
- const transport = new SSEServerTransport("/messages", res);
35
- transports[transport.sessionId] = transport;
36
- req.on("close", () => {
37
- delete transports[transport.sessionId];
38
- });
39
- await server.connect(transport);
40
- });
41
- app.post("/messages", async (req, res) => {
42
- const sessionId = req.query.sessionId;
43
- const transport = transports[sessionId];
44
- if (transport) {
45
- await transport.handlePostMessage(req, res);
46
- }
47
- else {
48
- throw new HttpError(400, "No transport found for sessionId");
49
- }
50
- });
51
- app.use(((error, _req, res, _next) => {
52
- console.error("handle route error", { error });
53
- res
54
- .status(error instanceof HttpError ? error.status : 500)
55
- .json({ error: { message: error.message } });
56
- }));
57
- const { promise, resolve, reject } = promiseWithResolvers();
58
- const httpServer = app.listen(port, (error) => {
59
- if (error)
60
- reject(error);
61
- resolve();
62
- });
63
- await promise;
64
- return httpServer;
65
- }
66
- class HttpError extends Error {
67
- status;
68
- constructor(status, message) {
69
- super(message);
70
- this.status = status;
71
- }
91
+ return server;
72
92
  }
package/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "@aigne/cli",
3
- "version": "1.6.0",
3
+ "version": "1.8.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"
@@ -50,7 +50,7 @@
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.12.0"
54
54
  },
55
55
  "devDependencies": {
56
56
  "@types/archiver": "^6.0.3",
@@ -5,7 +5,7 @@ This is the default project template for the Aigne framework, providing a basic
5
5
  ## Template Structure
6
6
 
7
7
  - `aigne.yaml` - Project configuration file that defines the chat model used and references to agents
8
- - `chat.yaml` - Chat agent configuration, including agent instructions and tools used
8
+ - `chat.yaml` - Chat agent configuration, including agent instructions and skills used
9
9
  - `sandbox.js` - JavaScript code execution tool for running JavaScript code within conversations
10
10
  - `sandbox.test.js` - Test file to verify the functionality of the code execution tool
11
11
 
@@ -3,5 +3,6 @@ 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: true
6
7
  tools:
7
8
  - sandbox.js