@saber2pr/ai-agent 0.0.5 → 0.0.6
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/lib/agent.d.ts +22 -1
- package/lib/agent.js +57 -10
- package/lib/cli.d.ts +2 -0
- package/lib/cli.js +9 -0
- package/lib/index.d.ts +2 -2
- package/lib/index.js +18 -4
- package/package.json +2 -2
package/lib/agent.d.ts
CHANGED
|
@@ -1,3 +1,16 @@
|
|
|
1
|
+
export interface CustomTool {
|
|
2
|
+
name: string;
|
|
3
|
+
description: string;
|
|
4
|
+
parameters: any;
|
|
5
|
+
handler: (args: any) => Promise<any>;
|
|
6
|
+
}
|
|
7
|
+
export interface AgentOptions {
|
|
8
|
+
targetDir?: string;
|
|
9
|
+
/** 自定义工具扩展 */
|
|
10
|
+
tools?: any[];
|
|
11
|
+
/** 注入到 System Prompt 中的额外指令/规则/上下文 */
|
|
12
|
+
extraSystemPrompt?: any;
|
|
13
|
+
}
|
|
1
14
|
export default class McpAgent {
|
|
2
15
|
private openai;
|
|
3
16
|
private modelName;
|
|
@@ -6,12 +19,14 @@ export default class McpAgent {
|
|
|
6
19
|
private messages;
|
|
7
20
|
private engine;
|
|
8
21
|
private encoder;
|
|
9
|
-
|
|
22
|
+
private extraTools;
|
|
23
|
+
constructor(options?: AgentOptions);
|
|
10
24
|
/**
|
|
11
25
|
* 计算当前消息列表的总 Token 消耗
|
|
12
26
|
* 兼容多模态内容 (Content Parts) 和 工具调用 (Tool Calls)
|
|
13
27
|
*/
|
|
14
28
|
private calculateTokens;
|
|
29
|
+
private injectCustomTools;
|
|
15
30
|
/**
|
|
16
31
|
* 核心功能:内置代码分析工具
|
|
17
32
|
* 这里的逻辑直接调用 PromptEngine,不走网络请求,效率极高
|
|
@@ -25,5 +40,11 @@ export default class McpAgent {
|
|
|
25
40
|
* 简易 Loading 动画辅助函数
|
|
26
41
|
*/
|
|
27
42
|
private showLoading;
|
|
43
|
+
/**
|
|
44
|
+
* 编程式对话入口
|
|
45
|
+
* @param input 用户指令
|
|
46
|
+
* @returns AI 的最终答复内容
|
|
47
|
+
*/
|
|
48
|
+
chat(input: string): Promise<string>;
|
|
28
49
|
start(): Promise<void>;
|
|
29
50
|
}
|
package/lib/agent.js
CHANGED
|
@@ -47,24 +47,34 @@ const ts_context_mcp_1 = require("@saber2pr/ts-context-mcp"); // 引入我们的
|
|
|
47
47
|
const js_tiktoken_1 = require("js-tiktoken");
|
|
48
48
|
const CONFIG_FILE = path_1.default.join(os_1.default.homedir(), ".saber2pr-agent.json");
|
|
49
49
|
class McpAgent {
|
|
50
|
-
constructor() {
|
|
50
|
+
constructor(options) {
|
|
51
51
|
this.modelName = "";
|
|
52
52
|
this.clients = [];
|
|
53
53
|
this.allTools = [];
|
|
54
54
|
this.messages = [];
|
|
55
55
|
this.encoder = (0, js_tiktoken_1.getEncoding)("cl100k_base");
|
|
56
|
-
|
|
57
|
-
this.engine = new ts_context_mcp_1.PromptEngine(process.cwd());
|
|
58
|
-
this.
|
|
59
|
-
|
|
60
|
-
content: `你是一个专业的 AI 代码架构师。
|
|
56
|
+
this.extraTools = [];
|
|
57
|
+
this.engine = new ts_context_mcp_1.PromptEngine((options === null || options === void 0 ? void 0 : options.targetDir) || process.cwd());
|
|
58
|
+
this.extraTools = (options === null || options === void 0 ? void 0 : options.tools) || []; // 接收外部传入的工具
|
|
59
|
+
let baseSystemPrompt = `你是一个专业的 AI 代码架构师。
|
|
61
60
|
你可以访问本地文件系统并利用 AST (抽象语法树) 技术分析代码。
|
|
62
61
|
你的核心目标是提供准确的代码结构、依赖关系和逻辑分析。
|
|
63
62
|
请先使用 get_repo_map 查看项目整体代码结构。
|
|
64
|
-
请优先使用 read_skeleton 查看结构,只有在必要时才使用 read_full_code 或 get_method_body
|
|
63
|
+
请优先使用 read_skeleton 查看结构,只有在必要时才使用 read_full_code 或 get_method_body。`;
|
|
64
|
+
// 2. 拼接额外指令
|
|
65
|
+
if (options === null || options === void 0 ? void 0 : options.extraSystemPrompt) {
|
|
66
|
+
const extra = typeof options.extraSystemPrompt === 'string'
|
|
67
|
+
? options.extraSystemPrompt
|
|
68
|
+
: JSON.stringify(options.extraSystemPrompt, null, 2);
|
|
69
|
+
baseSystemPrompt += `\n\n[额外执行指令]:\n${extra}`;
|
|
70
|
+
}
|
|
71
|
+
this.messages.push({
|
|
72
|
+
role: "system",
|
|
73
|
+
content: baseSystemPrompt,
|
|
65
74
|
});
|
|
66
75
|
// 初始化内置工具
|
|
67
76
|
this.registerBuiltinTools();
|
|
77
|
+
this.injectCustomTools(); // 注入外部工具
|
|
68
78
|
}
|
|
69
79
|
/**
|
|
70
80
|
* 计算当前消息列表的总 Token 消耗
|
|
@@ -108,6 +118,19 @@ class McpAgent {
|
|
|
108
118
|
}
|
|
109
119
|
return total;
|
|
110
120
|
}
|
|
121
|
+
injectCustomTools() {
|
|
122
|
+
for (const tool of this.extraTools) {
|
|
123
|
+
this.allTools.push({
|
|
124
|
+
type: "function",
|
|
125
|
+
function: {
|
|
126
|
+
name: tool.name,
|
|
127
|
+
description: tool.description,
|
|
128
|
+
parameters: tool.parameters,
|
|
129
|
+
},
|
|
130
|
+
_handler: tool.handler,
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
}
|
|
111
134
|
/**
|
|
112
135
|
* 核心功能:内置代码分析工具
|
|
113
136
|
* 这里的逻辑直接调用 PromptEngine,不走网络请求,效率极高
|
|
@@ -218,7 +241,11 @@ class McpAgent {
|
|
|
218
241
|
if (!fs_1.default.existsSync(fullPath)) {
|
|
219
242
|
return `Error: 文件不存在: ${filePath}`;
|
|
220
243
|
}
|
|
221
|
-
|
|
244
|
+
const content = fs_1.default.readFileSync(fullPath, "utf-8");
|
|
245
|
+
// 加上行号,AI 就能在 generate_review 里给出准确的 line 参数
|
|
246
|
+
return content.split('\n')
|
|
247
|
+
.map((line, i) => `${i + 1} | ${line}`)
|
|
248
|
+
.join('\n');
|
|
222
249
|
}
|
|
223
250
|
catch (err) {
|
|
224
251
|
return `Error: 读取文件失败: ${err.message}`;
|
|
@@ -376,8 +403,27 @@ class McpAgent {
|
|
|
376
403
|
process.stdout.write('\r\x1b[K'); // 清除当前行
|
|
377
404
|
};
|
|
378
405
|
}
|
|
406
|
+
/**
|
|
407
|
+
* 编程式对话入口
|
|
408
|
+
* @param input 用户指令
|
|
409
|
+
* @returns AI 的最终答复内容
|
|
410
|
+
*/
|
|
411
|
+
async chat(input) {
|
|
412
|
+
if (!this.openai) {
|
|
413
|
+
await this.init();
|
|
414
|
+
}
|
|
415
|
+
// 调用现有的处理逻辑
|
|
416
|
+
// 假设你的 processChat 已经处理了所有的 tool_calls 循环
|
|
417
|
+
await this.processChat(input);
|
|
418
|
+
// 返回消息列表中的最后一条 AI 回复
|
|
419
|
+
const lastMsg = this.messages[this.messages.length - 1];
|
|
420
|
+
return lastMsg.role === 'assistant' ? lastMsg.content : '';
|
|
421
|
+
}
|
|
422
|
+
// 修改原来的 start 方法,使其内部也调用 chat
|
|
379
423
|
async start() {
|
|
380
|
-
|
|
424
|
+
if (!this.openai) {
|
|
425
|
+
await this.init();
|
|
426
|
+
}
|
|
381
427
|
const rl = readline.createInterface({
|
|
382
428
|
input: process.stdin,
|
|
383
429
|
output: process.stdout,
|
|
@@ -388,7 +434,8 @@ class McpAgent {
|
|
|
388
434
|
if (input.toLowerCase() === "exit")
|
|
389
435
|
process.exit(0);
|
|
390
436
|
try {
|
|
391
|
-
|
|
437
|
+
// 这里统一调用 chat 或核心逻辑
|
|
438
|
+
await this.chat(input);
|
|
392
439
|
}
|
|
393
440
|
catch (err) {
|
|
394
441
|
console.error("\n❌ 系统错误:", err.message);
|
package/lib/cli.d.ts
ADDED
package/lib/cli.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
4
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
5
|
+
};
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
const agent_1 = __importDefault(require("./agent"));
|
|
8
|
+
const manager = new agent_1.default();
|
|
9
|
+
manager.start();
|
package/lib/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
export {};
|
|
1
|
+
export * from './agent';
|
|
2
|
+
export { default } from './agent';
|
package/lib/index.js
CHANGED
|
@@ -1,9 +1,23 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
3
16
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
4
17
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
5
18
|
};
|
|
6
19
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
20
|
+
exports.default = void 0;
|
|
21
|
+
__exportStar(require("./agent"), exports);
|
|
22
|
+
var agent_1 = require("./agent");
|
|
23
|
+
Object.defineProperty(exports, "default", { enumerable: true, get: function () { return __importDefault(agent_1).default; } });
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@saber2pr/ai-agent",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.6",
|
|
4
4
|
"description": "AI Assistant CLI.",
|
|
5
5
|
"author": "saber2pr",
|
|
6
6
|
"license": "ISC",
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"lib"
|
|
9
9
|
],
|
|
10
10
|
"bin": {
|
|
11
|
-
"sagent": "./lib/
|
|
11
|
+
"sagent": "./lib/cli.js"
|
|
12
12
|
},
|
|
13
13
|
"publishConfig": {
|
|
14
14
|
"access": "public",
|