@saber2pr/ai-agent 0.0.9 → 0.0.11
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/README.md +9 -1
- package/lib/cli-chain.js +3 -3
- package/lib/cli.js +3 -3
- package/lib/config/config.d.ts +1 -0
- package/lib/config/config.js +9 -0
- package/lib/core/agent-chain.d.ts +27 -0
- package/lib/{agent-chain.js → core/agent-chain.js} +81 -112
- package/lib/{agent.d.ts → core/agent.d.ts} +4 -26
- package/lib/{agent.js → core/agent.js} +32 -160
- package/lib/index.d.ts +4 -3
- package/lib/index.js +6 -4
- package/lib/tools/builtin.d.ts +5 -0
- package/lib/tools/builtin.js +12 -0
- package/lib/tools/filesystem/index.d.ts +1 -0
- package/lib/tools/filesystem/index.js +338 -0
- package/lib/tools/filesystem/lib.d.ts +34 -0
- package/lib/tools/filesystem/lib.js +330 -0
- package/lib/tools/filesystem/path-utils.d.ts +18 -0
- package/lib/tools/filesystem/path-utils.js +111 -0
- package/lib/tools/filesystem/path-validation.d.ts +9 -0
- package/lib/tools/filesystem/path-validation.js +81 -0
- package/lib/tools/filesystem/roots-utils.d.ts +12 -0
- package/lib/tools/filesystem/roots-utils.js +76 -0
- package/lib/tools/ts-lsp/index.d.ts +1 -0
- package/lib/tools/ts-lsp/index.js +56 -0
- package/lib/types/type.d.ts +38 -0
- package/lib/types/type.js +2 -0
- package/lib/utils/createTool.d.ts +9 -0
- package/lib/utils/createTool.js +36 -0
- package/lib/utils/jsonSchemaToZod.d.ts +2 -0
- package/lib/utils/jsonSchemaToZod.js +33 -0
- package/package.json +5 -2
- package/lib/agent-chain.d.ts +0 -48
package/README.md
CHANGED
|
@@ -19,6 +19,14 @@ A high-performance AI Agent toolkit designed for automated code auditing, reposi
|
|
|
19
19
|
## 🛠️ Installation
|
|
20
20
|
|
|
21
21
|
```bash
|
|
22
|
+
sudo npm i -g @saber2pr/ai-agent
|
|
23
|
+
|
|
24
|
+
# call openapi
|
|
25
|
+
sagent
|
|
26
|
+
|
|
27
|
+
# call third api
|
|
28
|
+
sagent-chain
|
|
29
|
+
|
|
22
30
|
# Clone the repository
|
|
23
31
|
git clone https://github.com/saber2pr/ai-agent.git
|
|
24
32
|
cd ai-agent
|
|
@@ -103,7 +111,7 @@ class MyPrivateLLM extends BaseChatModel {
|
|
|
103
111
|
| ----------------- | ------------------------------------------------------------------------ |
|
|
104
112
|
| `generate_review` | Finalizes the process by submitting a structured violation report. |
|
|
105
113
|
| `get_repo_map` | Generates a high-level map of the project files and exports. |
|
|
106
|
-
| `
|
|
114
|
+
| `read_text_file` | Reads file content with line numbers for precise auditing. |
|
|
107
115
|
| `read_skeleton` | Extracts class/function signatures without full logic (Token efficient). |
|
|
108
116
|
|
|
109
117
|
---
|
package/lib/cli-chain.js
CHANGED
|
@@ -4,6 +4,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
5
5
|
};
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
-
const agent_chain_1 = __importDefault(require("./agent-chain"));
|
|
8
|
-
const
|
|
9
|
-
|
|
7
|
+
const agent_chain_1 = __importDefault(require("./core/agent-chain"));
|
|
8
|
+
const agent = new agent_chain_1.default();
|
|
9
|
+
agent.start();
|
package/lib/cli.js
CHANGED
|
@@ -4,6 +4,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
5
5
|
};
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
-
const agent_1 = __importDefault(require("./agent"));
|
|
8
|
-
const
|
|
9
|
-
|
|
7
|
+
const agent_1 = __importDefault(require("./core/agent"));
|
|
8
|
+
const agent = new agent_1.default();
|
|
9
|
+
agent.start();
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const CONFIG_FILE: string;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.CONFIG_FILE = void 0;
|
|
7
|
+
const path_1 = __importDefault(require("path"));
|
|
8
|
+
const os_1 = __importDefault(require("os"));
|
|
9
|
+
exports.CONFIG_FILE = path_1.default.join(os_1.default.homedir(), ".saber2pr-agent.json");
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { AgentOptions } from '../types/type';
|
|
2
|
+
export default class McpChainAgent {
|
|
3
|
+
private allTools;
|
|
4
|
+
private messages;
|
|
5
|
+
private encoder;
|
|
6
|
+
private extraTools;
|
|
7
|
+
private maxTokens;
|
|
8
|
+
private executor?;
|
|
9
|
+
private apiConfig;
|
|
10
|
+
private maxIterations;
|
|
11
|
+
private apiModel?;
|
|
12
|
+
private targetDir;
|
|
13
|
+
private verbose;
|
|
14
|
+
constructor(options?: AgentOptions);
|
|
15
|
+
/**
|
|
16
|
+
* 工具处理器包装逻辑:增加日志打印和 Token 监控
|
|
17
|
+
*/
|
|
18
|
+
private wrapHandler;
|
|
19
|
+
private initTools;
|
|
20
|
+
private calculateTokens;
|
|
21
|
+
private pruneMessages;
|
|
22
|
+
init(): Promise<void>;
|
|
23
|
+
chat(input: string): Promise<string>;
|
|
24
|
+
private showLoading;
|
|
25
|
+
start(): Promise<void>;
|
|
26
|
+
private ensureApiConfig;
|
|
27
|
+
}
|
|
@@ -37,35 +37,35 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
37
37
|
};
|
|
38
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
39
|
const fs_1 = __importDefault(require("fs"));
|
|
40
|
-
const path_1 = __importDefault(require("path"));
|
|
41
|
-
const os_1 = __importDefault(require("os"));
|
|
42
|
-
const readline = __importStar(require("readline"));
|
|
43
|
-
const ts_context_mcp_1 = require("@saber2pr/ts-context-mcp");
|
|
44
40
|
const js_tiktoken_1 = require("js-tiktoken");
|
|
45
|
-
const openai_1 = require("@langchain/openai");
|
|
46
|
-
const tools_1 = require("@langchain/core/tools");
|
|
47
41
|
const agents_1 = require("langchain/agents");
|
|
42
|
+
const readline = __importStar(require("readline"));
|
|
48
43
|
const prompts_1 = require("@langchain/core/prompts");
|
|
49
|
-
const
|
|
44
|
+
const tools_1 = require("@langchain/core/tools");
|
|
45
|
+
const openai_1 = require("@langchain/openai");
|
|
46
|
+
const config_1 = require("../config/config");
|
|
47
|
+
const jsonSchemaToZod_1 = require("../utils/jsonSchemaToZod");
|
|
48
|
+
const builtin_1 = require("../tools/builtin");
|
|
50
49
|
class McpChainAgent {
|
|
51
50
|
constructor(options) {
|
|
52
51
|
this.allTools = [];
|
|
53
52
|
this.messages = [];
|
|
54
53
|
this.encoder = (0, js_tiktoken_1.getEncoding)("cl100k_base");
|
|
55
54
|
this.extraTools = [];
|
|
56
|
-
this.engine = new ts_context_mcp_1.PromptEngine((options === null || options === void 0 ? void 0 : options.targetDir) || process.cwd());
|
|
57
55
|
this.extraTools = (options === null || options === void 0 ? void 0 : options.tools) || [];
|
|
58
56
|
this.maxTokens = (options === null || options === void 0 ? void 0 : options.maxTokens) || 100000;
|
|
59
57
|
this.apiConfig = options === null || options === void 0 ? void 0 : options.apiConfig;
|
|
60
58
|
this.maxIterations = (options === null || options === void 0 ? void 0 : options.maxIterations) || 20;
|
|
61
59
|
this.apiModel = options === null || options === void 0 ? void 0 : options.apiModel;
|
|
60
|
+
this.targetDir = (options === null || options === void 0 ? void 0 : options.targetDir) || process.cwd();
|
|
61
|
+
this.verbose = (options === null || options === void 0 ? void 0 : options.verbose) || false;
|
|
62
62
|
const baseSystemPrompt = `你是一个专业的 AI 代码架构师,具备深度的源码分析与工程化处理能力。
|
|
63
63
|
|
|
64
64
|
### 核心操作规范:
|
|
65
65
|
1. **全局扫描(强制首选)**:在开始任何分析任务前,你【必须】首先调用 'get_repo_map'。这是理解项目结构、技术栈及模块关系的唯一来源。
|
|
66
66
|
2. **循序渐进的分析路径**:
|
|
67
67
|
- 优先使用 'read_skeleton' 提取接口和函数签名。
|
|
68
|
-
- 仅在需要分析具体逻辑或准备修复代码时,才使用 '
|
|
68
|
+
- 仅在需要分析具体逻辑或准备修复代码时,才使用 'read_text_file'。
|
|
69
69
|
3. **真实性原则**:所有的代码分析必须基于工具返回的真实内容,严禁虚假猜测。`;
|
|
70
70
|
this.messages.push({
|
|
71
71
|
role: "system",
|
|
@@ -73,8 +73,7 @@ class McpChainAgent {
|
|
|
73
73
|
? `${baseSystemPrompt}\n\n[额外指令]:\n${JSON.stringify(options.extraSystemPrompt)}`
|
|
74
74
|
: baseSystemPrompt,
|
|
75
75
|
});
|
|
76
|
-
this.
|
|
77
|
-
this.injectCustomTools();
|
|
76
|
+
this.initTools(options);
|
|
78
77
|
}
|
|
79
78
|
/**
|
|
80
79
|
* 工具处理器包装逻辑:增加日志打印和 Token 监控
|
|
@@ -95,72 +94,23 @@ class McpChainAgent {
|
|
|
95
94
|
return content;
|
|
96
95
|
};
|
|
97
96
|
}
|
|
98
|
-
|
|
99
|
-
const
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
this
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
{
|
|
109
|
-
type: "function",
|
|
110
|
-
function: {
|
|
111
|
-
name: "read_skeleton",
|
|
112
|
-
description: "读取代码骨架(接口、类定义等),非常节省 Token",
|
|
113
|
-
parameters: { type: "object", properties: { filePath: { type: "string" } } },
|
|
114
|
-
},
|
|
115
|
-
_handler: this.wrapHandler("read_skeleton", async ({ filePath }) => this.engine.getSkeleton(filePath)),
|
|
116
|
-
},
|
|
117
|
-
{
|
|
118
|
-
type: "function",
|
|
119
|
-
function: {
|
|
120
|
-
name: "read_full_code",
|
|
121
|
-
description: "读取完整源码。注意:仅在需要具体行号或精细逻辑时使用",
|
|
122
|
-
parameters: { type: "object", properties: { filePath: { type: "string" } } },
|
|
123
|
-
},
|
|
124
|
-
_handler: this.wrapHandler("read_full_code", async ({ filePath }) => {
|
|
125
|
-
// --- 新增:Token 守卫 ---
|
|
126
|
-
const currentTokens = this.calculateTokens();
|
|
127
|
-
if (currentTokens > this.maxTokens) {
|
|
128
|
-
return `[SYSTEM WARNING]: 当前上下文已达到 ${currentTokens} tokens (上限 ${this.maxTokens})。为了保证系统稳定,已拦截 read_full_code。请立即根据已知信息进行总结或停止阅读更多代码。`;
|
|
129
|
-
}
|
|
130
|
-
try {
|
|
131
|
-
if (typeof filePath !== 'string' || !filePath) {
|
|
132
|
-
return "Error: filePath 不能为空";
|
|
133
|
-
}
|
|
134
|
-
// 拼合绝对路径
|
|
135
|
-
const fullPath = path_1.default.resolve(this.engine.getRootDir(), filePath);
|
|
136
|
-
// 安全检查:防止 AI 尝试读取项目外的敏感文件
|
|
137
|
-
if (!fullPath.startsWith(this.engine.getRootDir())) {
|
|
138
|
-
return "Error: 权限拒绝,禁止访问项目目录外的文件。";
|
|
139
|
-
}
|
|
140
|
-
if (!fs_1.default.existsSync(fullPath)) {
|
|
141
|
-
return `Error: 文件不存在: ${filePath}`;
|
|
142
|
-
}
|
|
143
|
-
const content = fs_1.default.readFileSync(fullPath, "utf-8");
|
|
144
|
-
// 加上行号,AI 就能在 generate_review 里给出准确的 line 参数
|
|
145
|
-
return content.split('\n')
|
|
146
|
-
.map((line, i) => `${i + 1} | ${line}`)
|
|
147
|
-
.join('\n');
|
|
148
|
-
}
|
|
149
|
-
catch (err) {
|
|
150
|
-
return `Error: 读取文件失败: ${err.message}`;
|
|
151
|
-
}
|
|
152
|
-
}),
|
|
153
|
-
}
|
|
97
|
+
initTools(options) {
|
|
98
|
+
const allTools = [
|
|
99
|
+
// 注册内置工具
|
|
100
|
+
...(0, builtin_1.createDefaultBuiltinTools)({
|
|
101
|
+
options: {
|
|
102
|
+
...options,
|
|
103
|
+
...this
|
|
104
|
+
}
|
|
105
|
+
}),
|
|
106
|
+
...this.extraTools
|
|
154
107
|
];
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
function: { name: tool.name, description: tool.description, parameters: tool.parameters },
|
|
162
|
-
_handler: this.wrapHandler(tool.name, tool.handler),
|
|
163
|
-
});
|
|
108
|
+
if (allTools === null || allTools === void 0 ? void 0 : allTools.length) {
|
|
109
|
+
this.allTools.push(...allTools.map((t) => ({
|
|
110
|
+
type: t.type,
|
|
111
|
+
function: t.function,
|
|
112
|
+
_handler: this.wrapHandler(t.function.name, t._handler),
|
|
113
|
+
})));
|
|
164
114
|
}
|
|
165
115
|
}
|
|
166
116
|
calculateTokens() {
|
|
@@ -196,11 +146,20 @@ class McpChainAgent {
|
|
|
196
146
|
streaming: false
|
|
197
147
|
});
|
|
198
148
|
}
|
|
199
|
-
const langchainTools = this.allTools.map(t =>
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
149
|
+
const langchainTools = this.allTools.map(t => {
|
|
150
|
+
return new tools_1.DynamicStructuredTool({
|
|
151
|
+
name: t.function.name,
|
|
152
|
+
description: t.function.description || "",
|
|
153
|
+
// 定义 schema 告诉 LangChain 这是一个对象输入
|
|
154
|
+
// passthrough() 允许接收未在 schema 中显式定义的其他字段
|
|
155
|
+
schema: (0, jsonSchemaToZod_1.jsonSchemaToZod)(t.function.parameters),
|
|
156
|
+
func: async (args) => {
|
|
157
|
+
// 这里的 args 已经被 LangChain 自动解析为对象
|
|
158
|
+
return await t._handler(args);
|
|
159
|
+
},
|
|
160
|
+
});
|
|
161
|
+
});
|
|
162
|
+
// src/core/agent-chain.ts 中的 prompt 修改
|
|
204
163
|
const prompt = prompts_1.PromptTemplate.fromTemplate(`
|
|
205
164
|
{system_prompt}
|
|
206
165
|
|
|
@@ -208,39 +167,32 @@ class McpChainAgent {
|
|
|
208
167
|
--------------------
|
|
209
168
|
{tools}
|
|
210
169
|
|
|
170
|
+
工具名称列表: [{tool_names}]
|
|
171
|
+
|
|
211
172
|
### 📝 交互协议格式 (PROTOCOL)
|
|
212
173
|
--------------------
|
|
213
|
-
|
|
174
|
+
你必须严格遵守以下回复格式:
|
|
214
175
|
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
2. **反馈阶段 (Observation)**:
|
|
223
|
-
Observation: 工具返回的真实数据。
|
|
224
|
-
|
|
225
|
-
3. **最终结论阶段 (Final Answer)**:
|
|
226
|
-
当且仅当你已经从工具中获得了足够信息并完成所有审计任务时:
|
|
227
|
-
Thought: 我已经完成了所有分析,可以生成最终报告。
|
|
228
|
-
Final Answer: 任务总结陈述。
|
|
176
|
+
Thought: 首先,我会[此处用中文简述你的分析思路和下一步目标]。
|
|
177
|
+
\`\`\`json
|
|
178
|
+
{{
|
|
179
|
+
"action": "工具名称",
|
|
180
|
+
"action_input": {{ "参数名": "参数值" }}
|
|
181
|
+
}}
|
|
182
|
+
\`\`\`
|
|
229
183
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
-
|
|
233
|
-
- **严禁冲突**:严禁在同一次回复中同时出现 "Action" 和 "Final Answer"。
|
|
234
|
-
- **严禁对话**:不要向用户提问或进行闲聊,你的唯一目标是完成审计并调用 'generate_review'。
|
|
184
|
+
注意:
|
|
185
|
+
- 严禁直接输出 JSON,必须先写 Thought。
|
|
186
|
+
- Thought 必须包含具体的分析意图,不少于 10 个字。
|
|
235
187
|
|
|
236
188
|
Begin!
|
|
237
189
|
Question: {input}
|
|
238
190
|
Thought: {agent_scratchpad}`);
|
|
239
|
-
const agent = await (0, agents_1.
|
|
191
|
+
const agent = await (0, agents_1.createStructuredChatAgent)({ llm: model, tools: langchainTools, prompt });
|
|
240
192
|
this.executor = new agents_1.AgentExecutor({
|
|
241
193
|
agent,
|
|
242
194
|
tools: langchainTools,
|
|
243
|
-
verbose:
|
|
195
|
+
verbose: this.verbose, // 我们已经有了 wrapHandler 日志,关闭原生 verbose 以保持整洁
|
|
244
196
|
handleParsingErrors: true,
|
|
245
197
|
maxIterations: this.maxIterations
|
|
246
198
|
});
|
|
@@ -261,17 +213,34 @@ Thought: {agent_scratchpad}`);
|
|
|
261
213
|
// --- 新增:使用回调函数捕获 Thought ---
|
|
262
214
|
callbacks: [{
|
|
263
215
|
handleAgentAction: (action, runId) => {
|
|
264
|
-
// 在 ReAct Agent 中,thought 通常包含在 log 字段中,且在 Action 之前
|
|
265
216
|
if (action.log) {
|
|
266
|
-
const
|
|
267
|
-
|
|
268
|
-
|
|
217
|
+
const log = action.log.trim();
|
|
218
|
+
// 1. 提取 Thought 部分:取 Thought: 之后,直到遇到 ```json 或 { 之前的内容
|
|
219
|
+
const thoughtMatch = log.match(/Thought:\s*([\s\S]*?)(?=(?:```json|\{|Action:|$))/i);
|
|
220
|
+
let thought = "";
|
|
221
|
+
if (thoughtMatch && thoughtMatch[1]) {
|
|
222
|
+
thought = thoughtMatch[1].trim();
|
|
223
|
+
}
|
|
224
|
+
else {
|
|
225
|
+
// 备选方案:如果没有 Thought 标签,直接截取 JSON 之前的文本
|
|
226
|
+
thought = log.split(/```json|\{/)[0].replace(/Thought:/i, "").trim();
|
|
227
|
+
}
|
|
228
|
+
// 2. 只有当 thought 真的有文字内容(且不是 JSON)时才打印
|
|
229
|
+
if (thought && thought.length > 0 && !thought.startsWith('{')) {
|
|
230
|
+
// 进一步清洗:如果 thought 包含多行,只取非空的第一行,避免打印太长
|
|
231
|
+
const displayThought = thought.split('\n').find(line => line.trim().length > 0);
|
|
232
|
+
if (displayThought) {
|
|
233
|
+
console.log(`\n💭 [思考]: ${displayThought}`);
|
|
234
|
+
}
|
|
269
235
|
}
|
|
270
236
|
}
|
|
271
237
|
}
|
|
272
238
|
}]
|
|
273
239
|
});
|
|
274
|
-
|
|
240
|
+
// 修复点:确保 output 是字符串
|
|
241
|
+
let output = typeof response.output === 'string'
|
|
242
|
+
? response.output
|
|
243
|
+
: JSON.stringify(response.output);
|
|
275
244
|
// 清洗 ReAct 冗余标签
|
|
276
245
|
if (output.includes("Final Answer:")) {
|
|
277
246
|
output = ((_a = output.split("Final Answer:").pop()) === null || _a === void 0 ? void 0 : _a.trim()) || output;
|
|
@@ -299,7 +268,7 @@ Thought: {agent_scratchpad}`);
|
|
|
299
268
|
await this.init();
|
|
300
269
|
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
301
270
|
console.log(`\n🚀 AI 助手启动 (LangChain 核心)`);
|
|
302
|
-
console.log(`📂 目标目录: ${this.
|
|
271
|
+
console.log(`📂 目标目录: ${this.targetDir}`);
|
|
303
272
|
const chatLoop = () => {
|
|
304
273
|
rl.question("\n👤 你: ", async (input) => {
|
|
305
274
|
if (!input.trim())
|
|
@@ -321,8 +290,8 @@ Thought: {agent_scratchpad}`);
|
|
|
321
290
|
async ensureApiConfig() {
|
|
322
291
|
if (this.apiConfig)
|
|
323
292
|
return this.apiConfig;
|
|
324
|
-
if (fs_1.default.existsSync(CONFIG_FILE)) {
|
|
325
|
-
return JSON.parse(fs_1.default.readFileSync(CONFIG_FILE, "utf-8"));
|
|
293
|
+
if (fs_1.default.existsSync(config_1.CONFIG_FILE)) {
|
|
294
|
+
return JSON.parse(fs_1.default.readFileSync(config_1.CONFIG_FILE, "utf-8"));
|
|
326
295
|
}
|
|
327
296
|
const rl = readline.createInterface({
|
|
328
297
|
input: process.stdin,
|
|
@@ -335,7 +304,7 @@ Thought: {agent_scratchpad}`);
|
|
|
335
304
|
apiKey: await question("? API Key: "),
|
|
336
305
|
model: await question("? Model Name (如 gpt-4o): "),
|
|
337
306
|
};
|
|
338
|
-
fs_1.default.writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2));
|
|
307
|
+
fs_1.default.writeFileSync(config_1.CONFIG_FILE, JSON.stringify(config, null, 2));
|
|
339
308
|
rl.close();
|
|
340
309
|
return config;
|
|
341
310
|
}
|
|
@@ -1,44 +1,23 @@
|
|
|
1
|
-
|
|
2
|
-
baseURL: string;
|
|
3
|
-
apiKey: string;
|
|
4
|
-
model: string;
|
|
5
|
-
}
|
|
6
|
-
export interface CustomTool {
|
|
7
|
-
name: string;
|
|
8
|
-
description: string;
|
|
9
|
-
parameters: any;
|
|
10
|
-
handler: (args: any) => Promise<any>;
|
|
11
|
-
}
|
|
12
|
-
export interface AgentOptions {
|
|
13
|
-
targetDir?: string;
|
|
14
|
-
/** 自定义工具扩展 */
|
|
15
|
-
tools?: any[];
|
|
16
|
-
/** 注入到 System Prompt 中的额外指令/规则/上下文 */
|
|
17
|
-
extraSystemPrompt?: any;
|
|
18
|
-
maxTokens?: number;
|
|
19
|
-
apiConfig?: ApiConfig;
|
|
20
|
-
}
|
|
1
|
+
import { AgentOptions } from '../types/type';
|
|
21
2
|
export default class McpAgent {
|
|
22
3
|
private openai;
|
|
23
4
|
private modelName;
|
|
24
|
-
private clients;
|
|
25
5
|
private allTools;
|
|
26
6
|
private messages;
|
|
27
|
-
private engine;
|
|
28
7
|
private encoder;
|
|
29
8
|
private extraTools;
|
|
30
9
|
private maxTokens;
|
|
31
10
|
private apiConfig;
|
|
11
|
+
private targetDir;
|
|
32
12
|
constructor(options?: AgentOptions);
|
|
33
13
|
/**
|
|
34
14
|
* 计算当前消息列表的总 Token 消耗
|
|
35
15
|
* 兼容多模态内容 (Content Parts) 和 工具调用 (Tool Calls)
|
|
36
16
|
*/
|
|
37
17
|
private calculateTokens;
|
|
38
|
-
private
|
|
18
|
+
private initTools;
|
|
39
19
|
/**
|
|
40
|
-
*
|
|
41
|
-
* 这里的逻辑直接调用 PromptEngine,不走网络请求,效率极高
|
|
20
|
+
* 核心功能:内置代码分析工具(基于 engine/targetDir,可被外部通过 createDefaultBuiltinTools 替代)
|
|
42
21
|
*/
|
|
43
22
|
private registerBuiltinTools;
|
|
44
23
|
private ensureApiConfig;
|
|
@@ -62,4 +41,3 @@ export default class McpAgent {
|
|
|
62
41
|
chat(input: string): Promise<string>;
|
|
63
42
|
start(): Promise<void>;
|
|
64
43
|
}
|
|
65
|
-
export {};
|