@saber2pr/ai-agent 0.0.69 → 0.0.70

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.
@@ -36,6 +36,8 @@ export declare abstract class AgentGraphModel extends BaseChatModel {
36
36
  callApiStream(prompt: string, lastMsg: BaseMessage, onChunk: StreamChunkCallback): Promise<AgentGraphLLMResponse>;
37
37
  _generate(messages: BaseMessage[]): Promise<ChatResult>;
38
38
  private parseToolCalls;
39
+ /** 从 text[start] 开始,按括号配对提取完整的 JSON 对象字符串 */
40
+ private extractBalancedJson;
39
41
  /**
40
42
  * 流式生成:调用 callApiStream 进行流式输出,完成后构建完整的 ChatResult。
41
43
  * @param messages LangChain 消息列表
@@ -96,37 +96,38 @@ class AgentGraphModel extends chat_models_1.BaseChatModel {
96
96
  }
97
97
  parseToolCalls(text) {
98
98
  const actionMatch = text.match(/Action:\s*(\w+)/);
99
- const argsMatch = text.match(/Arguments:\s*({[\s\S]*?})(?=\n|$)/);
100
99
  if (!actionMatch)
101
100
  return [];
102
101
  let args = {};
103
- if (argsMatch) {
104
- try {
105
- let raw = argsMatch[1].trim();
106
- // 关键修复:递归解析,直到它变成真正的对象
107
- // 这能处理 "\"{\\\"path\\\":...}\"" 这种套娃字符串
108
- let safetyDepth = 0;
109
- while (typeof raw === 'string' && safetyDepth < 5) {
110
- try {
111
- const parsed = JSON.parse(raw);
112
- if (typeof parsed === 'object' && parsed !== null) {
102
+ const argsIdx = text.search(/Arguments:\s*\{/);
103
+ if (argsIdx !== -1) {
104
+ const jsonStart = text.indexOf('{', argsIdx);
105
+ const jsonStr = this.extractBalancedJson(text, jsonStart);
106
+ if (jsonStr) {
107
+ try {
108
+ let raw = jsonStr;
109
+ let safetyDepth = 0;
110
+ while (typeof raw === 'string' && safetyDepth < 5) {
111
+ try {
112
+ const parsed = JSON.parse(raw);
113
+ if (typeof parsed === 'object' && parsed !== null) {
114
+ raw = parsed;
115
+ break;
116
+ }
113
117
  raw = parsed;
118
+ }
119
+ catch {
114
120
  break;
115
121
  }
116
- raw = parsed; // 如果解析后还是 string,继续剥
117
- }
118
- catch {
119
- break; // 解析不动了,跳出
122
+ safetyDepth++;
120
123
  }
121
- safetyDepth++;
124
+ args = raw;
125
+ }
126
+ catch {
127
+ args = {};
122
128
  }
123
- args = raw;
124
- }
125
- catch (e) {
126
- args = {};
127
129
  }
128
130
  }
129
- // ✅ 此时返回的 args 必须是 object 类型
130
131
  return [
131
132
  {
132
133
  name: actionMatch[1],
@@ -136,6 +137,39 @@ class AgentGraphModel extends chat_models_1.BaseChatModel {
136
137
  },
137
138
  ];
138
139
  }
140
+ /** 从 text[start] 开始,按括号配对提取完整的 JSON 对象字符串 */
141
+ extractBalancedJson(text, start) {
142
+ if (start < 0 || start >= text.length || text[start] !== '{')
143
+ return null;
144
+ let depth = 0;
145
+ let inString = false;
146
+ let escape = false;
147
+ for (let i = start; i < text.length; i++) {
148
+ const ch = text[i];
149
+ if (escape) {
150
+ escape = false;
151
+ continue;
152
+ }
153
+ if (ch === '\\' && inString) {
154
+ escape = true;
155
+ continue;
156
+ }
157
+ if (ch === '"') {
158
+ inString = !inString;
159
+ continue;
160
+ }
161
+ if (inString)
162
+ continue;
163
+ if (ch === '{')
164
+ depth++;
165
+ else if (ch === '}') {
166
+ depth--;
167
+ if (depth === 0)
168
+ return text.substring(start, i + 1);
169
+ }
170
+ }
171
+ return null;
172
+ }
139
173
  /**
140
174
  * 流式生成:调用 callApiStream 进行流式输出,完成后构建完整的 ChatResult。
141
175
  * @param messages LangChain 消息列表
@@ -211,8 +245,8 @@ ${systemContext}
211
245
  ${format(lastMsg)}
212
246
  # Output Requirement
213
247
  1. Reasoning in <think> tags.
214
- 2. Action: Name
215
- 3. Arguments: {JSON}
248
+ 2. Action: ToolName
249
+ 3. Arguments: {"key": "value"} (MUST be a single-line compact JSON, no newlines inside)
216
250
  `.trim();
217
251
  }
218
252
  _llmType() {
@@ -15,7 +15,7 @@ Operating System: ${osPlatform}
15
15
  Before providing any output or calling a tool, you **MUST** conduct a deep logical analysis. Wrap your thought process within <think> tags.
16
16
 
17
17
  # Tool Call Specifications
18
- 1. **Pure JSON Arguments**: Arguments must be a valid JSON object. NEVER wrap the entire JSON object in a string or quotes.
18
+ 1. **Pure JSON Arguments**: Arguments MUST be a single-line compact JSON object (no newlines, no pretty-printing). NEVER wrap the entire JSON object in a string or quotes. Example: Arguments: {"path": "/foo", "content": "bar"}
19
19
  2. **No Double Escaping**: Do not double-escape characters within the JSON.
20
20
  3. **No Idle Operations**: If the task is complete or no tool is needed, DO NOT output any "Action" structure. Never use "None", "null", or empty strings as a tool name.
21
21
  4. **Important Note**: For optimal efficiency, when performing multiple operations, use batch_run_tools to invoke all relevant tools in parallel, rather than sequentially. Prioritize parallel tool invocation whenever possible. For example, when reading three files, run three tool invocations in parallel to read all three files into the context simultaneously. When running multiple read-only commands (such as read_file_range, grep_search, or read_text_file), always run all commands in parallel. Use parallel tool invocations whenever possible, rather than running too many tools sequentially.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@saber2pr/ai-agent",
3
- "version": "0.0.69",
3
+ "version": "0.0.70",
4
4
  "description": "AI Assistant CLI.",
5
5
  "author": "saber2pr",
6
6
  "license": "ISC",