@saber2pr/ai-agent 0.0.57 → 0.0.59
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/adapters/llm.d.ts +1 -3
- package/lib/adapters/llm.js +4 -7
- package/lib/core/agent-graph.js +1 -1
- package/lib/core/agent.js +1 -1
- package/lib/model/AgentGraphModel.d.ts +6 -1
- package/lib/model/AgentGraphModel.js +25 -2
- package/lib/tools/builtin.js +2 -0
- package/lib/tools/loader/get_all_tools_schema.d.ts +1 -0
- package/lib/tools/loader/get_all_tools_schema.js +33 -0
- package/lib/types/type.d.ts +3 -1
- package/lib/utils/convertToLangChainTool.d.ts +3 -1
- package/lib/utils/convertToLangChainTool.js +2 -2
- package/lib/utils/createTool.d.ts +3 -1
- package/lib/utils/createTool.js +2 -2
- package/lib/utils/getRepoMapPrompt.d.ts +1 -0
- package/lib/utils/getRepoMapPrompt.js +40 -0
- package/package.json +1 -1
package/lib/adapters/llm.d.ts
CHANGED
|
@@ -1,11 +1,9 @@
|
|
|
1
|
-
import { AgentGraphLLMResponse, AgentGraphModel, StreamChunkCallback } from '../model/AgentGraphModel';
|
|
2
1
|
import { BaseMessage } from '@langchain/core/messages';
|
|
2
|
+
import { AgentGraphLLMResponse, AgentGraphModel, StreamChunkCallback } from '../model/AgentGraphModel';
|
|
3
3
|
import { CreateAgentOptions } from '../types/type';
|
|
4
4
|
export declare class LLMModel extends AgentGraphModel {
|
|
5
|
-
private chatId;
|
|
6
5
|
private options;
|
|
7
6
|
constructor(options: CreateAgentOptions);
|
|
8
|
-
resetChat(): void;
|
|
9
7
|
callApi(prompt: string): Promise<AgentGraphLLMResponse>;
|
|
10
8
|
/**
|
|
11
9
|
* 流式调用 API:发送 stream: true,自动适配多种响应格式(SSE / NDJSON / 普通 JSON)。
|
package/lib/adapters/llm.js
CHANGED
|
@@ -3,16 +3,13 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.LLMModel = void 0;
|
|
4
4
|
const AgentGraphModel_1 = require("../model/AgentGraphModel");
|
|
5
5
|
class LLMModel extends AgentGraphModel_1.AgentGraphModel {
|
|
6
|
-
chatId;
|
|
7
6
|
options;
|
|
8
7
|
constructor(options) {
|
|
9
|
-
super(
|
|
10
|
-
|
|
8
|
+
super({
|
|
9
|
+
targetDir: options.targetDir,
|
|
10
|
+
});
|
|
11
11
|
this.options = options;
|
|
12
12
|
}
|
|
13
|
-
resetChat() {
|
|
14
|
-
this.chatId = '';
|
|
15
|
-
}
|
|
16
13
|
async callApi(prompt) {
|
|
17
14
|
const response = await fetch(this.options.apiUrl, {
|
|
18
15
|
method: 'POST',
|
|
@@ -172,7 +169,7 @@ class LLMModel extends AgentGraphModel_1.AgentGraphModel {
|
|
|
172
169
|
text: fullText,
|
|
173
170
|
reasoning,
|
|
174
171
|
token,
|
|
175
|
-
duration
|
|
172
|
+
duration,
|
|
176
173
|
};
|
|
177
174
|
}
|
|
178
175
|
}
|
package/lib/core/agent-graph.js
CHANGED
|
@@ -175,7 +175,7 @@ class McpGraphAgent {
|
|
|
175
175
|
const mcpToolInfos = await this.initMcpTools();
|
|
176
176
|
// 合并内置、手动传入和 MCP 工具
|
|
177
177
|
const allToolInfos = [...builtinToolInfos, ...(this.options.tools || []), ...mcpToolInfos];
|
|
178
|
-
this.langchainTools = allToolInfos.map(t => (0, convertToLangChainTool_1.convertToLangChainTool)(t));
|
|
178
|
+
this.langchainTools = allToolInfos.map(t => (0, convertToLangChainTool_1.convertToLangChainTool)(t, { allTools: allToolInfos }));
|
|
179
179
|
this.toolNode = new prebuilt_1.ToolNode(this.langchainTools);
|
|
180
180
|
return {
|
|
181
181
|
builtinToolInfos,
|
package/lib/core/agent.js
CHANGED
|
@@ -306,7 +306,7 @@ class McpAgent {
|
|
|
306
306
|
console.log(` 📦 传入参数: \x1b[2m${JSON.stringify(args)}\x1b[0m`);
|
|
307
307
|
let result;
|
|
308
308
|
if (tool?._handler) {
|
|
309
|
-
result = await tool._handler(args);
|
|
309
|
+
result = await tool._handler(args, { allTools: this.allTools });
|
|
310
310
|
}
|
|
311
311
|
else if (tool?._client && tool._originalName) {
|
|
312
312
|
const mcpRes = await tool._client.callTool({
|
|
@@ -13,12 +13,17 @@ export declare abstract class AgentGraphModel extends BaseChatModel {
|
|
|
13
13
|
protected boundTools?: any[];
|
|
14
14
|
private mcpEnabled?;
|
|
15
15
|
private mcpTools?;
|
|
16
|
+
protected chatId: string;
|
|
17
|
+
protected targetDir?: string;
|
|
18
|
+
resetChat(): void;
|
|
16
19
|
setMcpTools(tools: any[]): void;
|
|
17
20
|
setMcpEnabled(enabled?: boolean): void;
|
|
18
21
|
getMcpEnabled(): boolean;
|
|
19
22
|
getMcpTools(): any[];
|
|
20
23
|
private isMcpTool;
|
|
21
|
-
constructor(fields?: BaseChatModelParams
|
|
24
|
+
constructor(fields?: BaseChatModelParams & {
|
|
25
|
+
targetDir?: string;
|
|
26
|
+
});
|
|
22
27
|
bindTools(tools: any[]): any;
|
|
23
28
|
abstract callApi(prompt: string, lastMsg: BaseMessage): Promise<AgentGraphLLMResponse>;
|
|
24
29
|
/**
|
|
@@ -6,10 +6,16 @@ const messages_1 = require("@langchain/core/messages");
|
|
|
6
6
|
const function_calling_1 = require("@langchain/core/utils/function_calling");
|
|
7
7
|
const generateToolMarkdown_1 = require("../utils/generateToolMarkdown");
|
|
8
8
|
const kit_1 = require("../utils/kit");
|
|
9
|
+
const getRepoMapPrompt_1 = require("../utils/getRepoMapPrompt");
|
|
9
10
|
class AgentGraphModel extends chat_models_1.BaseChatModel {
|
|
10
11
|
boundTools;
|
|
11
12
|
mcpEnabled = true;
|
|
12
13
|
mcpTools = [];
|
|
14
|
+
chatId = '';
|
|
15
|
+
targetDir;
|
|
16
|
+
resetChat() {
|
|
17
|
+
this.chatId = '';
|
|
18
|
+
}
|
|
13
19
|
setMcpTools(tools) {
|
|
14
20
|
this.mcpTools = tools;
|
|
15
21
|
}
|
|
@@ -28,6 +34,10 @@ class AgentGraphModel extends chat_models_1.BaseChatModel {
|
|
|
28
34
|
}
|
|
29
35
|
constructor(fields) {
|
|
30
36
|
super(fields || {});
|
|
37
|
+
this.chatId = '';
|
|
38
|
+
this.mcpTools = [];
|
|
39
|
+
this.mcpEnabled = true;
|
|
40
|
+
this.targetDir = fields?.targetDir;
|
|
31
41
|
}
|
|
32
42
|
bindTools(tools) {
|
|
33
43
|
this.boundTools = tools.map(t => (0, function_calling_1.convertToOpenAITool)(t));
|
|
@@ -170,6 +180,7 @@ class AgentGraphModel extends chat_models_1.BaseChatModel {
|
|
|
170
180
|
serializeMessages(messages) {
|
|
171
181
|
const systemMsg = messages.find(m => m._getType() === 'system');
|
|
172
182
|
const lastMsg = messages[messages.length - 1];
|
|
183
|
+
const isFirstMessage = this.chatId === '';
|
|
173
184
|
const format = (m) => {
|
|
174
185
|
const content = typeof m.content === 'string' ? m.content : JSON.stringify(m.content, null, 2);
|
|
175
186
|
return `${m._getType().toUpperCase()}: ${content}`;
|
|
@@ -178,9 +189,21 @@ class AgentGraphModel extends chat_models_1.BaseChatModel {
|
|
|
178
189
|
const toolsContext = tools.length
|
|
179
190
|
? `${(0, generateToolMarkdown_1.generateToolMarkdown)(tools)}`
|
|
180
191
|
: '';
|
|
181
|
-
|
|
182
|
-
${format(systemMsg)}
|
|
192
|
+
const systemContext = isFirstMessage ? `
|
|
193
|
+
${isFirstMessage ? format(systemMsg) : ''}
|
|
183
194
|
${toolsContext}
|
|
195
|
+
${(0, getRepoMapPrompt_1.getIncrementalRepoMapPrompt)(this.targetDir, isFirstMessage)}
|
|
196
|
+
`.trim() : `
|
|
197
|
+
## Active Tools (Summary)
|
|
198
|
+
Available: ${(0, kit_1.getArray)(tools).map(t => t.function.name).join(', ')}
|
|
199
|
+
|
|
200
|
+
**Self-Correction**: If you encounter "tool not found" or need parameter details, you MUST call:
|
|
201
|
+
- \`get_all_tools_schema\`: Retrieve full tool definitions and schemas.
|
|
202
|
+
|
|
203
|
+
${(0, getRepoMapPrompt_1.getIncrementalRepoMapPrompt)(this.targetDir, isFirstMessage)}
|
|
204
|
+
`.trim();
|
|
205
|
+
return `
|
|
206
|
+
${systemContext}
|
|
184
207
|
# Current Progress
|
|
185
208
|
${format(lastMsg)}
|
|
186
209
|
# Output Requirement
|
package/lib/tools/builtin.js
CHANGED
|
@@ -2,11 +2,13 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.createDefaultBuiltinTools = createDefaultBuiltinTools;
|
|
4
4
|
const filesystem_1 = require("./filesystem");
|
|
5
|
+
const get_all_tools_schema_1 = require("./loader/get_all_tools_schema");
|
|
5
6
|
const ts_lsp_1 = require("./ts-lsp");
|
|
6
7
|
function createDefaultBuiltinTools(context) {
|
|
7
8
|
const { options } = context;
|
|
8
9
|
return [
|
|
9
10
|
...(0, ts_lsp_1.getTsLspTools)(options?.targetDir || process.cwd()),
|
|
10
11
|
...(0, filesystem_1.getFilesystemTools)(options?.targetDir || process.cwd()),
|
|
12
|
+
get_all_tools_schema_1.getAllToolsSchema,
|
|
11
13
|
];
|
|
12
14
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const getAllToolsSchema: import("../..").ToolInfo;
|
|
@@ -0,0 +1,33 @@
|
|
|
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.getAllToolsSchema = void 0;
|
|
7
|
+
const zod_1 = require("zod");
|
|
8
|
+
const zod_to_json_schema_1 = __importDefault(require("zod-to-json-schema"));
|
|
9
|
+
const createTool_1 = require("../../utils/createTool");
|
|
10
|
+
const generateToolMarkdown_1 = require("../../utils/generateToolMarkdown");
|
|
11
|
+
const kit_1 = require("../../utils/kit");
|
|
12
|
+
exports.getAllToolsSchema = (0, createTool_1.createTool)({
|
|
13
|
+
name: 'get_all_tools_schema',
|
|
14
|
+
description: 'Use this tool when you encounter a "tool not found" error or are unsure about the parameter schema. It retrieves the full definitions and JSON schemas for all available tools in the current environment.',
|
|
15
|
+
parameters: zod_1.z.object({
|
|
16
|
+
toolName: zod_1.z.string().optional().describe('Optional: Specify a tool name to get its detailed schema. If omitted, returns all available tools.')
|
|
17
|
+
}),
|
|
18
|
+
// 增加第二个参数 context
|
|
19
|
+
handler: async ({ toolName }, context) => {
|
|
20
|
+
// 这里的 context.allTools 是在运行时从 Agent 实例传入的
|
|
21
|
+
const availableTools = (0, kit_1.getArray)(context?.allTools);
|
|
22
|
+
const targetTools = toolName
|
|
23
|
+
? availableTools.filter(t => t.function.name === toolName)
|
|
24
|
+
: availableTools;
|
|
25
|
+
return (0, generateToolMarkdown_1.generateToolMarkdown)(targetTools.map(item => ({
|
|
26
|
+
...item,
|
|
27
|
+
function: {
|
|
28
|
+
...item.function,
|
|
29
|
+
parameters: (0, zod_to_json_schema_1.default)(item.function.parameters)
|
|
30
|
+
}
|
|
31
|
+
})));
|
|
32
|
+
}
|
|
33
|
+
});
|
package/lib/types/type.d.ts
CHANGED
|
@@ -13,7 +13,9 @@ export interface ToolInfo {
|
|
|
13
13
|
description?: string;
|
|
14
14
|
parameters: z.ZodObject<any>;
|
|
15
15
|
};
|
|
16
|
-
_handler?: (args: any
|
|
16
|
+
_handler?: (args: any, context: {
|
|
17
|
+
allTools: ToolInfo[];
|
|
18
|
+
}) => Promise<any>;
|
|
17
19
|
_client?: Client;
|
|
18
20
|
_originalName?: string;
|
|
19
21
|
}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { DynamicStructuredTool } from '@langchain/core/tools';
|
|
2
2
|
import { ToolInfo } from '../types/type';
|
|
3
|
-
export declare function convertToLangChainTool(info: ToolInfo
|
|
3
|
+
export declare function convertToLangChainTool(info: ToolInfo, context: {
|
|
4
|
+
allTools: ToolInfo[];
|
|
5
|
+
}): DynamicStructuredTool<import("zod").ZodObject<any, import("zod").UnknownKeysParam, import("zod").ZodTypeAny, {
|
|
4
6
|
[x: string]: any;
|
|
5
7
|
}, {
|
|
6
8
|
[x: string]: any;
|
|
@@ -2,14 +2,14 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.convertToLangChainTool = convertToLangChainTool;
|
|
4
4
|
const tools_1 = require("@langchain/core/tools");
|
|
5
|
-
function convertToLangChainTool(info) {
|
|
5
|
+
function convertToLangChainTool(info, context) {
|
|
6
6
|
return new tools_1.DynamicStructuredTool({
|
|
7
7
|
name: info.function.name,
|
|
8
8
|
description: info.function.description || '',
|
|
9
9
|
schema: info.function.parameters,
|
|
10
10
|
func: async (args) => {
|
|
11
11
|
if (info._handler)
|
|
12
|
-
return await info._handler(args);
|
|
12
|
+
return await info._handler(args, context);
|
|
13
13
|
if (info._client && info._originalName) {
|
|
14
14
|
const result = await info._client.callTool({
|
|
15
15
|
name: info._originalName,
|
|
@@ -7,6 +7,8 @@ export interface CreateToolOptions {
|
|
|
7
7
|
* zod@3.25
|
|
8
8
|
*/
|
|
9
9
|
parameters: z.ZodObject<any>;
|
|
10
|
-
handler: (args: any
|
|
10
|
+
handler: (args: any, context: {
|
|
11
|
+
allTools: ToolInfo[];
|
|
12
|
+
}) => Promise<string>;
|
|
11
13
|
}
|
|
12
14
|
export declare function createTool(options: CreateToolOptions): ToolInfo;
|
package/lib/utils/createTool.js
CHANGED
|
@@ -9,7 +9,7 @@ function createTool(options) {
|
|
|
9
9
|
description: options.description,
|
|
10
10
|
parameters: options.parameters,
|
|
11
11
|
},
|
|
12
|
-
_handler: async (input) => {
|
|
12
|
+
_handler: async (input, context) => {
|
|
13
13
|
// 兼容处理:如果 input 是字符串,尝试解析为 JSON 对象
|
|
14
14
|
let args = input;
|
|
15
15
|
if (typeof input === 'string') {
|
|
@@ -20,7 +20,7 @@ function createTool(options) {
|
|
|
20
20
|
args = input;
|
|
21
21
|
}
|
|
22
22
|
}
|
|
23
|
-
return options.handler(args);
|
|
23
|
+
return options.handler(args, context);
|
|
24
24
|
},
|
|
25
25
|
};
|
|
26
26
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const getIncrementalRepoMapPrompt: (targetDir: string, isFirstTurn: boolean) => string;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getIncrementalRepoMapPrompt = void 0;
|
|
4
|
+
const ts_context_mcp_1 = require("@saber2pr/ts-context-mcp");
|
|
5
|
+
let lastRepoMapContent = '';
|
|
6
|
+
const getIncrementalRepoMapPrompt = (targetDir, isFirstTurn) => {
|
|
7
|
+
try {
|
|
8
|
+
const engine = new ts_context_mcp_1.PromptEngine(targetDir);
|
|
9
|
+
const currentContent = engine.getRepoMap();
|
|
10
|
+
// 1. 第一轮对话:必须全量发送
|
|
11
|
+
if (isFirstTurn || !lastRepoMapContent) {
|
|
12
|
+
lastRepoMapContent = currentContent;
|
|
13
|
+
return `\n# Initial Project Repository Map\n\`\`\`text\n${currentContent}\n\`\`\``;
|
|
14
|
+
}
|
|
15
|
+
// 2. 如果完全没变:发送静默占位符
|
|
16
|
+
if (currentContent === lastRepoMapContent) {
|
|
17
|
+
return "\n\n(Note: Project structure remains unchanged.)";
|
|
18
|
+
}
|
|
19
|
+
// 3. 如果变了:计算增量 (Incremental Diff)
|
|
20
|
+
const lastLines = lastRepoMapContent.split('\n');
|
|
21
|
+
const currentLines = currentContent.split('\n');
|
|
22
|
+
// 找出发生变化的行 (简单示例:找出在 current 中但不在 last 中的行)
|
|
23
|
+
const changes = currentLines.filter(line => !lastLines.includes(line));
|
|
24
|
+
lastRepoMapContent = currentContent;
|
|
25
|
+
if (changes.length > 0) {
|
|
26
|
+
return `
|
|
27
|
+
# 🆕 Project Map Updates (Incremental)
|
|
28
|
+
The project structure has changed. Key updates:
|
|
29
|
+
\`\`\`text
|
|
30
|
+
${changes.join('\n')}
|
|
31
|
+
\`\`\`
|
|
32
|
+
*(Refer to previous messages for the rest of the map)*`;
|
|
33
|
+
}
|
|
34
|
+
return "\n\n(Note: Minor internal structure changes detected.)";
|
|
35
|
+
}
|
|
36
|
+
catch (error) {
|
|
37
|
+
return '';
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
exports.getIncrementalRepoMapPrompt = getIncrementalRepoMapPrompt;
|