@saber2pr/ai-agent 0.0.19 → 0.0.20

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.
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
@@ -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_graph_1 = __importDefault(require("./core/agent-graph"));
8
+ const agent = new agent_graph_1.default();
9
+ agent.start();
@@ -0,0 +1,52 @@
1
+ import { BaseMessage } from "@langchain/core/messages";
2
+ import { AgentOptions } from "../types/type";
3
+ export declare const CONFIG_FILE: string;
4
+ declare const AgentState: import("@langchain/langgraph").AnnotationRoot<{
5
+ messages: import("@langchain/langgraph").BinaryOperatorAggregate<BaseMessage[], BaseMessage[]>;
6
+ auditedFiles: import("@langchain/langgraph").BinaryOperatorAggregate<string[], string[]>;
7
+ targetCount: import("@langchain/langgraph").BinaryOperatorAggregate<number, number>;
8
+ mode: import("@langchain/langgraph").BinaryOperatorAggregate<"chat" | "auto", "chat" | "auto">;
9
+ }>;
10
+ export default class McpGraphAgent {
11
+ private model;
12
+ private toolNode;
13
+ private targetDir;
14
+ private options;
15
+ private checkpointer;
16
+ private langchainTools;
17
+ private spinner;
18
+ constructor(options?: AgentOptions);
19
+ private askForConfig;
20
+ private getModel;
21
+ chat(query?: string): Promise<void>;
22
+ start(): Promise<void>;
23
+ private renderOutput;
24
+ callModel(state: typeof AgentState.State): Promise<{
25
+ messages: unknown[];
26
+ }>;
27
+ trackProgress(state: typeof AgentState.State): Promise<{
28
+ auditedFiles: string[];
29
+ }>;
30
+ createGraph(): Promise<import("@langchain/langgraph").CompiledStateGraph<import("@langchain/langgraph").StateType<{
31
+ messages: import("@langchain/langgraph").BinaryOperatorAggregate<BaseMessage[], BaseMessage[]>;
32
+ auditedFiles: import("@langchain/langgraph").BinaryOperatorAggregate<string[], string[]>;
33
+ targetCount: import("@langchain/langgraph").BinaryOperatorAggregate<number, number>;
34
+ mode: import("@langchain/langgraph").BinaryOperatorAggregate<"chat" | "auto", "chat" | "auto">;
35
+ }>, import("@langchain/langgraph").UpdateType<{
36
+ messages: import("@langchain/langgraph").BinaryOperatorAggregate<BaseMessage[], BaseMessage[]>;
37
+ auditedFiles: import("@langchain/langgraph").BinaryOperatorAggregate<string[], string[]>;
38
+ targetCount: import("@langchain/langgraph").BinaryOperatorAggregate<number, number>;
39
+ mode: import("@langchain/langgraph").BinaryOperatorAggregate<"chat" | "auto", "chat" | "auto">;
40
+ }>, "tools" | "agent" | "__start__" | "progress", {
41
+ messages: import("@langchain/langgraph").BinaryOperatorAggregate<BaseMessage[], BaseMessage[]>;
42
+ auditedFiles: import("@langchain/langgraph").BinaryOperatorAggregate<string[], string[]>;
43
+ targetCount: import("@langchain/langgraph").BinaryOperatorAggregate<number, number>;
44
+ mode: import("@langchain/langgraph").BinaryOperatorAggregate<"chat" | "auto", "chat" | "auto">;
45
+ }, {
46
+ messages: import("@langchain/langgraph").BinaryOperatorAggregate<BaseMessage[], BaseMessage[]>;
47
+ auditedFiles: import("@langchain/langgraph").BinaryOperatorAggregate<string[], string[]>;
48
+ targetCount: import("@langchain/langgraph").BinaryOperatorAggregate<number, number>;
49
+ mode: import("@langchain/langgraph").BinaryOperatorAggregate<"chat" | "auto", "chat" | "auto">;
50
+ }, import("@langchain/langgraph").StateDefinition>>;
51
+ }
52
+ export {};
@@ -0,0 +1,220 @@
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 openai_1 = require("@langchain/openai");
8
+ const messages_1 = require("@langchain/core/messages");
9
+ const langgraph_1 = require("@langchain/langgraph");
10
+ const prebuilt_1 = require("@langchain/langgraph/prebuilt");
11
+ const prompts_1 = require("@langchain/core/prompts");
12
+ const readline_1 = __importDefault(require("readline"));
13
+ const fs_1 = __importDefault(require("fs"));
14
+ const path_1 = __importDefault(require("path"));
15
+ const os_1 = __importDefault(require("os"));
16
+ const ora_1 = __importDefault(require("ora")); // 用于显示 Loading 动画
17
+ const builtin_1 = require("../tools/builtin");
18
+ const convertToLangChainTool_1 = require("../utils/convertToLangChainTool");
19
+ exports.CONFIG_FILE = path_1.default.join(os_1.default.homedir(), ".saber2pr-agent.json");
20
+ // --- 1. 定义状态 (State) ---
21
+ const AgentState = langgraph_1.Annotation.Root({
22
+ messages: (0, langgraph_1.Annotation)({
23
+ reducer: (x, y) => x.concat(y),
24
+ default: () => [],
25
+ }),
26
+ auditedFiles: (0, langgraph_1.Annotation)({
27
+ reducer: (x, y) => Array.from(new Set([...x, ...y])),
28
+ default: () => [],
29
+ }),
30
+ targetCount: (0, langgraph_1.Annotation)({
31
+ reducer: (x, y) => y !== null && y !== void 0 ? y : x,
32
+ default: () => 4,
33
+ }),
34
+ mode: (0, langgraph_1.Annotation)({
35
+ reducer: (x, y) => y !== null && y !== void 0 ? y : x,
36
+ default: () => "chat",
37
+ }),
38
+ });
39
+ class McpGraphAgent {
40
+ constructor(options = {}) {
41
+ this.checkpointer = new langgraph_1.MemorySaver();
42
+ this.langchainTools = [];
43
+ this.spinner = (0, ora_1.default)({ color: "cyan" });
44
+ this.options = options;
45
+ this.targetDir = options.targetDir || process.cwd();
46
+ process.setMaxListeners(50); // 防止 AbortSignal 监听器过多的警告
47
+ const builtinToolInfos = (0, builtin_1.createDefaultBuiltinTools)({ options });
48
+ const externalToolInfos = options.tools || [];
49
+ this.langchainTools = [...builtinToolInfos, ...externalToolInfos].map((t) => (0, convertToLangChainTool_1.convertToLangChainTool)(t));
50
+ this.toolNode = new prebuilt_1.ToolNode(this.langchainTools);
51
+ }
52
+ async askForConfig() {
53
+ let config = {};
54
+ if (fs_1.default.existsSync(exports.CONFIG_FILE)) {
55
+ try {
56
+ config = JSON.parse(fs_1.default.readFileSync(exports.CONFIG_FILE, "utf-8"));
57
+ }
58
+ catch (e) { }
59
+ }
60
+ if (!config.baseURL || !config.apiKey) {
61
+ const rl = readline_1.default.createInterface({ input: process.stdin, output: process.stdout });
62
+ const question = (q) => new Promise((res) => rl.question(q, res));
63
+ console.log(`💡 首次运行请配置信息:`);
64
+ config.baseURL = config.baseURL || await question(`? API Base URL: `);
65
+ config.apiKey = config.apiKey || await question(`? API Key: `);
66
+ config.model = config.model || await question(`? Model Name: `) || "gpt-4o";
67
+ fs_1.default.writeFileSync(exports.CONFIG_FILE, JSON.stringify(config, null, 2));
68
+ rl.close();
69
+ }
70
+ return config;
71
+ }
72
+ async getModel() {
73
+ if (this.model)
74
+ return this.model;
75
+ let modelInstance = this.options.apiModel;
76
+ if (!modelInstance) {
77
+ const config = await this.askForConfig();
78
+ modelInstance = new openai_1.ChatOpenAI({
79
+ openAIApiKey: config.apiKey,
80
+ configuration: { baseURL: config.baseURL },
81
+ modelName: config.model,
82
+ temperature: 0,
83
+ });
84
+ }
85
+ this.model = modelInstance.bindTools(this.langchainTools);
86
+ return this.model;
87
+ }
88
+ async chat(query = "开始代码审计") {
89
+ await this.getModel();
90
+ const app = await this.createGraph();
91
+ const stream = await app.stream({
92
+ messages: [new messages_1.HumanMessage(query)],
93
+ mode: "auto",
94
+ targetCount: 4
95
+ }, { configurable: { thread_id: "auto_worker" }, recursionLimit: 100 });
96
+ for await (const output of stream)
97
+ this.renderOutput(output);
98
+ console.log("✅ 任务执行完毕。");
99
+ }
100
+ async start() {
101
+ await this.getModel();
102
+ const app = await this.createGraph();
103
+ const rl = readline_1.default.createInterface({ input: process.stdin, output: process.stdout });
104
+ const threadId = `session_${Date.now()}`;
105
+ console.log(`\n💬 已进入交互审计模式 (Thread: ${threadId})`);
106
+ const ask = () => {
107
+ rl.question("> ", async (input) => {
108
+ if (input.toLowerCase() === "exit") {
109
+ rl.close();
110
+ return;
111
+ }
112
+ const stream = await app.stream({ messages: [new messages_1.HumanMessage(input)], mode: "chat" }, { configurable: { thread_id: threadId }, recursionLimit: 50 });
113
+ for await (const output of stream)
114
+ this.renderOutput(output);
115
+ ask();
116
+ });
117
+ };
118
+ ask();
119
+ }
120
+ renderOutput(output) {
121
+ var _a, _b;
122
+ // 每次渲染输出前,确保停止 Spinner
123
+ if (this.spinner.isSpinning)
124
+ this.spinner.stop();
125
+ const agentNode = output.agent;
126
+ if (agentNode) {
127
+ const msg = agentNode.messages[0];
128
+ // 1. 打印思考过程
129
+ const reasoning = (_a = msg.additional_kwargs) === null || _a === void 0 ? void 0 : _a.reasoning;
130
+ if (reasoning) {
131
+ console.log("\n🧠 [思考过程]:\n" + "─".repeat(50) + "\n" + reasoning + "\n" + "─".repeat(50) + "\n");
132
+ }
133
+ // 2. 打印正式回答
134
+ if (msg.content)
135
+ console.log("🤖 [AI]:", msg.content);
136
+ // 3. 打印工具调用
137
+ if ((_b = msg.tool_calls) === null || _b === void 0 ? void 0 : _b.length) {
138
+ msg.tool_calls.forEach((call) => {
139
+ console.log(`🛠️ [调用工具]: ${call.name} 📦 参数: ${JSON.stringify(call.args)}`);
140
+ });
141
+ }
142
+ }
143
+ }
144
+ // --- 节点逻辑 ---
145
+ async callModel(state) {
146
+ // 处理变量序列化,防止 [object Object]
147
+ const auditedListStr = state.auditedFiles.length > 0
148
+ ? state.auditedFiles.map(f => `\n - ${f}`).join("")
149
+ : "暂无";
150
+ const extraPromptStr = typeof this.options.extraSystemPrompt === 'object'
151
+ ? JSON.stringify(this.options.extraSystemPrompt, null, 2)
152
+ : (this.options.extraSystemPrompt || "");
153
+ // 使用变量占位符 {extraPrompt} 避免内容中的 {} 引发模板解析错误
154
+ const prompt = prompts_1.ChatPromptTemplate.fromMessages([
155
+ ["system", `你是一个代码审计专家。工作目录:${this.targetDir}。
156
+ 当前模式:{mode}。
157
+ KPI进度:{doneCount}/{targetCount}。已审计文件:{auditedList}
158
+
159
+ # 附加指令
160
+ {extraPrompt}`],
161
+ new prompts_1.MessagesPlaceholder("messages"),
162
+ ]);
163
+ // ✅ 显示 Loading
164
+ this.spinner.start("AI 正在思考并分析代码...");
165
+ try {
166
+ const chain = prompt.pipe(this.model);
167
+ const response = await chain.invoke({
168
+ messages: state.messages,
169
+ mode: state.mode,
170
+ targetCount: state.targetCount,
171
+ doneCount: state.auditedFiles.length,
172
+ auditedList: auditedListStr,
173
+ extraPrompt: extraPromptStr, // 变量方式传入更安全
174
+ });
175
+ this.spinner.stop(); // 得到响应即停止
176
+ return { messages: [response] };
177
+ }
178
+ catch (error) {
179
+ this.spinner.fail("AI 响应异常");
180
+ throw error;
181
+ }
182
+ }
183
+ async trackProgress(state) {
184
+ const lastAiMsg = state.messages[state.messages.length - 1];
185
+ const newFiles = [];
186
+ if (lastAiMsg === null || lastAiMsg === void 0 ? void 0 : lastAiMsg.tool_calls) {
187
+ for (const tc of lastAiMsg.tool_calls) {
188
+ // 追踪涉及写、修复、生成审计报告的文件
189
+ const toolsToTrack = ["write_text_file", "apply_fix", "generate_review"];
190
+ if (toolsToTrack.includes(tc.name)) {
191
+ const file = tc.args.path || tc.args.filePath || tc.args.file;
192
+ if (file && typeof file === 'string')
193
+ newFiles.push(file);
194
+ }
195
+ }
196
+ }
197
+ return { auditedFiles: newFiles };
198
+ }
199
+ async createGraph() {
200
+ const workflow = new langgraph_1.StateGraph(AgentState)
201
+ .addNode("agent", (state) => this.callModel(state))
202
+ .addNode("tools", this.toolNode)
203
+ .addNode("progress", (state) => this.trackProgress(state))
204
+ .addEdge(langgraph_1.START, "agent")
205
+ .addConditionalEdges("agent", (state) => {
206
+ var _a;
207
+ const lastMsg = state.messages[state.messages.length - 1];
208
+ if ((_a = lastMsg.tool_calls) === null || _a === void 0 ? void 0 : _a.length)
209
+ return "tools";
210
+ // 自动模式下且未达标时继续
211
+ if (state.mode === "auto" && state.auditedFiles.length < state.targetCount)
212
+ return "agent";
213
+ return langgraph_1.END;
214
+ })
215
+ .addEdge("tools", "progress")
216
+ .addEdge("progress", "agent");
217
+ return workflow.compile({ checkpointer: this.checkpointer });
218
+ }
219
+ }
220
+ exports.default = McpGraphAgent;
package/lib/index.d.ts CHANGED
@@ -3,3 +3,5 @@ export { default as McpChainAgent } from './core/agent-chain';
3
3
  export { default } from './core/agent';
4
4
  export { createTool } from './utils/createTool';
5
5
  export { AgentChainModel } from './model/AgentChainModel';
6
+ export { AgentGraphModel, AgentGraphLLMResponse } from './model/AgentGraphModel';
7
+ export { default as McpGraphAgent } from './core/agent-graph';
package/lib/index.js CHANGED
@@ -17,7 +17,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
17
17
  return (mod && mod.__esModule) ? mod : { "default": mod };
18
18
  };
19
19
  Object.defineProperty(exports, "__esModule", { value: true });
20
- exports.AgentChainModel = exports.createTool = exports.default = exports.McpChainAgent = void 0;
20
+ exports.McpGraphAgent = exports.AgentGraphModel = exports.AgentChainModel = exports.createTool = exports.default = exports.McpChainAgent = void 0;
21
21
  __exportStar(require("./core/agent"), exports);
22
22
  var agent_chain_1 = require("./core/agent-chain");
23
23
  Object.defineProperty(exports, "McpChainAgent", { enumerable: true, get: function () { return __importDefault(agent_chain_1).default; } });
@@ -27,3 +27,7 @@ var createTool_1 = require("./utils/createTool");
27
27
  Object.defineProperty(exports, "createTool", { enumerable: true, get: function () { return createTool_1.createTool; } });
28
28
  var AgentChainModel_1 = require("./model/AgentChainModel");
29
29
  Object.defineProperty(exports, "AgentChainModel", { enumerable: true, get: function () { return AgentChainModel_1.AgentChainModel; } });
30
+ var AgentGraphModel_1 = require("./model/AgentGraphModel");
31
+ Object.defineProperty(exports, "AgentGraphModel", { enumerable: true, get: function () { return AgentGraphModel_1.AgentGraphModel; } });
32
+ var agent_graph_1 = require("./core/agent-graph");
33
+ Object.defineProperty(exports, "McpGraphAgent", { enumerable: true, get: function () { return __importDefault(agent_graph_1).default; } });
@@ -1,12 +1,12 @@
1
1
  import { BaseChatModel } from '@langchain/core/language_models/chat_models';
2
2
  import { AIMessage, MessageFieldWithRole } from '@langchain/core/messages';
3
3
  interface AgentChainModelImpl {
4
- generateAgentChainResponse: (messages: MessageFieldWithRole[]) => Promise<string>;
4
+ generateResponse: (messages: MessageFieldWithRole[]) => Promise<string>;
5
5
  }
6
6
  export declare abstract class AgentChainModel extends BaseChatModel implements AgentChainModelImpl {
7
7
  bind(args: any): any;
8
8
  constructor(fields?: any);
9
- generateAgentChainResponse(messages: MessageFieldWithRole[]): Promise<string>;
9
+ generateResponse(messages: MessageFieldWithRole[]): Promise<string>;
10
10
  _generate(messages: any): Promise<{
11
11
  generations: {
12
12
  text: string;
@@ -11,11 +11,11 @@ class AgentChainModel extends chat_models_1.BaseChatModel {
11
11
  return (super.bind ? super.bind(args) : this);
12
12
  }
13
13
  constructor(fields) { super(fields || {}); }
14
- async generateAgentChainResponse(messages) {
14
+ async generateResponse(messages) {
15
15
  return '';
16
16
  }
17
17
  async _generate(messages) {
18
- let text = await this.generateAgentChainResponse(messages);
18
+ let text = await this.generateResponse(messages);
19
19
  return { generations: [{ text, message: new messages_1.AIMessage(text) }] };
20
20
  }
21
21
  _llmType() { return "my_private_llm"; }
@@ -0,0 +1,21 @@
1
+ import { BaseChatModel, BaseChatModelParams } from '@langchain/core/language_models/chat_models';
2
+ import { BaseMessage } from '@langchain/core/messages';
3
+ import { ChatResult } from '@langchain/core/outputs';
4
+ export interface AgentGraphLLMResponse {
5
+ text: string;
6
+ reasoning?: string;
7
+ chatId?: string;
8
+ }
9
+ export declare abstract class AgentGraphModel extends BaseChatModel {
10
+ protected boundTools?: any[];
11
+ protected chatId?: string;
12
+ constructor(fields?: BaseChatModelParams & {
13
+ chatId?: string;
14
+ });
15
+ bindTools(tools: any[]): any;
16
+ abstract callApi(prompt: string, chatId?: string): Promise<AgentGraphLLMResponse>;
17
+ _generate(messages: BaseMessage[]): Promise<ChatResult>;
18
+ private serializeMessages;
19
+ private parseToolCalls;
20
+ _llmType(): string;
21
+ }
@@ -0,0 +1,96 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AgentGraphModel = void 0;
4
+ const chat_models_1 = require("@langchain/core/language_models/chat_models");
5
+ const messages_1 = require("@langchain/core/messages");
6
+ const function_calling_1 = require("@langchain/core/utils/function_calling");
7
+ class AgentGraphModel extends chat_models_1.BaseChatModel {
8
+ constructor(fields) {
9
+ super(fields || {});
10
+ this.chatId = fields === null || fields === void 0 ? void 0 : fields.chatId;
11
+ }
12
+ bindTools(tools) {
13
+ this.boundTools = tools.map(t => (0, function_calling_1.convertToOpenAITool)(t));
14
+ return this;
15
+ }
16
+ async _generate(messages) {
17
+ const fullPrompt = this.serializeMessages(messages);
18
+ const response = await this.callApi(fullPrompt, this.chatId);
19
+ if (response.chatId)
20
+ this.chatId = response.chatId;
21
+ let { text, reasoning } = response;
22
+ // ✅ 通用逻辑:解析 <think> 标签
23
+ if (!reasoning && text.includes("<think>")) {
24
+ const match = text.match(/<think>([\s\S]*?)<\/think>/);
25
+ if (match) {
26
+ reasoning = match[1].trim();
27
+ text = text.replace(/<think>[\s\S]*?<\/think>/, "").trim();
28
+ }
29
+ }
30
+ const toolCalls = this.parseToolCalls(text);
31
+ return {
32
+ generations: [{
33
+ text,
34
+ message: new messages_1.AIMessage({
35
+ content: text,
36
+ tool_calls: toolCalls,
37
+ additional_kwargs: { reasoning: reasoning || "" }
38
+ })
39
+ }]
40
+ };
41
+ }
42
+ serializeMessages(messages) {
43
+ const systemMsg = messages.find(m => m._getType() === 'system');
44
+ const lastMsg = messages[messages.length - 1];
45
+ const format = (m) => {
46
+ const content = typeof m.content === 'string' ? m.content : JSON.stringify(m.content, null, 2);
47
+ return `${m._getType().toUpperCase()}: ${content}`;
48
+ };
49
+ const toolsContext = this.boundTools ? `\n[Tools]\n${JSON.stringify(this.boundTools, null, 2)}` : "";
50
+ return `
51
+ ${format(systemMsg)}
52
+ ${toolsContext}
53
+ # Current Progress
54
+ ${format(lastMsg)}
55
+ # Output Requirement
56
+ 1. Reasoning in <think> tags.
57
+ 2. Action: Name
58
+ 3. Arguments: {JSON}
59
+ `.trim();
60
+ }
61
+ parseToolCalls(text) {
62
+ const actionMatch = text.match(/Action:\s*(\w+)/);
63
+ const argsMatch = text.match(/Arguments:\s*({[\s\S]*})/);
64
+ if (!actionMatch)
65
+ return [];
66
+ let args = {};
67
+ if (argsMatch) {
68
+ try {
69
+ // 强力解析逻辑,处理物理换行
70
+ const rawArgs = argsMatch[1].trim().replace(/\n/g, "\\n");
71
+ args = JSON.parse(rawArgs);
72
+ // 参数映射
73
+ const anyArgs = args;
74
+ if (anyArgs.file_path && !anyArgs.path)
75
+ anyArgs.path = anyArgs.file_path;
76
+ if (anyArgs.filePath && !anyArgs.path)
77
+ anyArgs.path = anyArgs.filePath;
78
+ if (anyArgs.path && !anyArgs.filePath)
79
+ anyArgs.filePath = anyArgs.path;
80
+ if (anyArgs.file && !anyArgs.filePath)
81
+ anyArgs.filePath = anyArgs.file;
82
+ }
83
+ catch (e) {
84
+ console.warn("JSON Parse Error", e);
85
+ }
86
+ }
87
+ return [{
88
+ name: actionMatch[1],
89
+ args,
90
+ id: `call_${Date.now()}`,
91
+ type: "tool_call",
92
+ }];
93
+ }
94
+ _llmType() { return "agent_graph_model"; }
95
+ }
96
+ exports.AgentGraphModel = AgentGraphModel;
@@ -46,4 +46,16 @@ export interface AgentOptions {
46
46
  * only for chain agent
47
47
  */
48
48
  verbose?: boolean;
49
+ /**
50
+ * only for graph agent
51
+ */
52
+ baseURL?: string;
53
+ /**
54
+ * only for graph agent
55
+ */
56
+ apiKey?: string;
57
+ /**
58
+ * only for graph agent
59
+ */
60
+ modelName?: string;
49
61
  }
@@ -0,0 +1,3 @@
1
+ import { DynamicStructuredTool } from "@langchain/core/tools";
2
+ import { z } from "zod";
3
+ export declare function convertToLangChainTool(info: any): DynamicStructuredTool<z.ZodRecord<z.ZodString, z.ZodAny>>;
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.convertToLangChainTool = convertToLangChainTool;
4
+ const tools_1 = require("@langchain/core/tools");
5
+ const zod_1 = require("zod");
6
+ function convertToLangChainTool(info) {
7
+ return new tools_1.DynamicStructuredTool({
8
+ name: info.function.name,
9
+ description: info.function.description || "",
10
+ schema: zod_1.z.record(zod_1.z.any()),
11
+ func: async (args) => {
12
+ if (info._handler)
13
+ return await info._handler(args);
14
+ if (info._client && info._originalName) {
15
+ const result = await info._client.callTool({
16
+ name: info._originalName,
17
+ arguments: args,
18
+ });
19
+ return JSON.stringify(result);
20
+ }
21
+ return "Error: No tool execution handler found.";
22
+ },
23
+ });
24
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@saber2pr/ai-agent",
3
- "version": "0.0.19",
3
+ "version": "0.0.20",
4
4
  "description": "AI Assistant CLI.",
5
5
  "author": "saber2pr",
6
6
  "license": "ISC",
@@ -9,7 +9,8 @@
9
9
  ],
10
10
  "bin": {
11
11
  "sagent": "./lib/cli.js",
12
- "sagent-chain": "./lib/cli-chain.js"
12
+ "sagent-chain": "./lib/cli-chain.js",
13
+ "sagent-graph": "./lib/cli-graph.js"
13
14
  },
14
15
  "publishConfig": {
15
16
  "access": "public",
@@ -22,18 +23,20 @@
22
23
  "prepublishOnly": "tsc"
23
24
  },
24
25
  "dependencies": {
26
+ "@langchain/core": "0.3.39",
27
+ "@langchain/langgraph": "^0.2.39",
28
+ "@langchain/openai": "0.4.0",
25
29
  "@modelcontextprotocol/sdk": "^1.25.3",
26
30
  "@saber2pr/ts-context-mcp": "^0.0.8",
27
31
  "diff": "^8.0.3",
28
32
  "glob": "^10.5.0",
29
33
  "js-tiktoken": "^1.0.21",
34
+ "langchain": "0.3.15",
30
35
  "minimatch": "^10.0.1",
31
36
  "openai": "^6.16.0",
32
- "zod-to-json-schema": "3.23.2",
33
- "langchain": "0.3.15",
34
- "@langchain/core": "0.3.39",
35
- "@langchain/openai": "0.4.0",
36
- "zod": "3.23.8"
37
+ "ora": "^9.3.0",
38
+ "zod": "3.23.8",
39
+ "zod-to-json-schema": "3.23.2"
37
40
  },
38
41
  "resolutions": {
39
42
  "@langchain/core": "0.3.39"