jinzd-ai-cli 0.1.18 → 0.1.19
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/dist/index.js +88 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -129,7 +129,7 @@ var EnvLoader = class {
|
|
|
129
129
|
};
|
|
130
130
|
|
|
131
131
|
// src/core/constants.ts
|
|
132
|
-
var VERSION = "0.1.
|
|
132
|
+
var VERSION = "0.1.19";
|
|
133
133
|
var APP_NAME = "ai-cli";
|
|
134
134
|
var CONFIG_DIR_NAME = ".aicli";
|
|
135
135
|
var CONFIG_FILE_NAME = "config.json";
|
|
@@ -1033,6 +1033,13 @@ var ZhipuProvider = class extends OpenAICompatibleProvider {
|
|
|
1033
1033
|
};
|
|
1034
1034
|
|
|
1035
1035
|
// src/providers/kimi.ts
|
|
1036
|
+
var KIMI_TOOL_CALL_REMINDER = `
|
|
1037
|
+
|
|
1038
|
+
\u3010\u26A0\uFE0F \u5DE5\u5177\u8C03\u7528\u5F3A\u5236\u89C4\u8303 - \u6781\u5176\u91CD\u8981\u3011
|
|
1039
|
+
\u8C03\u7528\u4EFB\u4F55\u5DE5\u5177\uFF08write_file\u3001bash\u3001read_file \u7B49\uFF09\u65F6\uFF0C\u5FC5\u987B\u4E14\u53EA\u80FD\u4F7F\u7528 API \u7684 function calling \u7ED3\u6784\u5316\u63A5\u53E3\u3002
|
|
1040
|
+
\u4E25\u7981\u5728\u56DE\u590D\u6587\u672C\u4E2D\u8F93\u51FA XML \u683C\u5F0F\u7684\u4F2A\u5DE5\u5177\u8C03\u7528\u6807\u7B7E\uFF08\u5982 <write_file>\u3001<bash>\u3001<read_file> \u7B49\uFF09\u3002
|
|
1041
|
+
\u6587\u672C\u4E2D\u7684 XML \u6807\u7B7E\u4E0D\u4F1A\u88AB\u7CFB\u7EDF\u6267\u884C\uFF0C\u4F1A\u5BFC\u81F4\u6587\u4EF6\u672A\u5199\u5165\u3001\u547D\u4EE4\u672A\u8FD0\u884C\uFF0C\u4EFB\u52A1\u5F7B\u5E95\u5931\u8D25\u3002
|
|
1042
|
+
\u6BCF\u6B21\u9700\u8981\u5199\u6587\u4EF6\uFF0C\u5FC5\u987B\u8C03\u7528 write_file \u5DE5\u5177 API\uFF0C\u4E0D\u5141\u8BB8\u4EFB\u4F55\u4F8B\u5916\u3002`;
|
|
1036
1043
|
var KimiProvider = class extends OpenAICompatibleProvider {
|
|
1037
1044
|
defaultBaseUrl = "https://api.moonshot.ai/v1";
|
|
1038
1045
|
info = {
|
|
@@ -1096,6 +1103,86 @@ var KimiProvider = class extends OpenAICompatibleProvider {
|
|
|
1096
1103
|
}
|
|
1097
1104
|
]
|
|
1098
1105
|
};
|
|
1106
|
+
/**
|
|
1107
|
+
* 覆写 chatWithTools,叠加两道防线:
|
|
1108
|
+
*
|
|
1109
|
+
* 方案 B(预防):在 system prompt 末尾追加工具调用规范提示,
|
|
1110
|
+
* 指示 Kimi 必须使用 API function calling,禁止输出 XML 伪工具调用。
|
|
1111
|
+
*
|
|
1112
|
+
* 方案 A(兜底):若 Kimi 仍然在文本中输出了 XML 格式工具调用,
|
|
1113
|
+
* 自动检测并解析,转换为真实 ToolCall 对象送入执行器,
|
|
1114
|
+
* 确保文件写入等操作不会静默丢失。
|
|
1115
|
+
*/
|
|
1116
|
+
async chatWithTools(request, tools) {
|
|
1117
|
+
const enhancedRequest = {
|
|
1118
|
+
...request,
|
|
1119
|
+
systemPrompt: (request.systemPrompt ?? "") + KIMI_TOOL_CALL_REMINDER
|
|
1120
|
+
};
|
|
1121
|
+
const result = await super.chatWithTools(enhancedRequest, tools);
|
|
1122
|
+
if ("content" in result && result.content) {
|
|
1123
|
+
const xmlToolCalls = this.parseXmlToolCalls(result.content, tools);
|
|
1124
|
+
if (xmlToolCalls.length > 0) {
|
|
1125
|
+
process.stderr.write(
|
|
1126
|
+
`[kimi] \u26A0 \u68C0\u6D4B\u5230 ${xmlToolCalls.length} \u4E2A XML \u4F2A\u5DE5\u5177\u8C03\u7528\uFF08Kimi \u672A\u4F7F\u7528 API \u673A\u5236\uFF09\uFF0C\u5DF2\u81EA\u52A8\u8F6C\u6362\u4E3A\u771F\u5B9E\u5DE5\u5177\u8C03\u7528\u6267\u884C\u3002
|
|
1127
|
+
`
|
|
1128
|
+
);
|
|
1129
|
+
return { toolCalls: xmlToolCalls, usage: result.usage };
|
|
1130
|
+
}
|
|
1131
|
+
}
|
|
1132
|
+
return result;
|
|
1133
|
+
}
|
|
1134
|
+
/**
|
|
1135
|
+
* 方案 A 核心逻辑:从 Kimi 的文本响应中提取 XML 格式伪工具调用。
|
|
1136
|
+
*
|
|
1137
|
+
* Kimi 输出的 XML 格式为:
|
|
1138
|
+
* <tool_name>
|
|
1139
|
+
* <param1>value1</param1>
|
|
1140
|
+
* <param2>value2</param2>
|
|
1141
|
+
* </tool_name>
|
|
1142
|
+
*
|
|
1143
|
+
* 使用 indexOf 而非正则,避免大文件内容(14KB+ Markdown)时的性能问题。
|
|
1144
|
+
* 参数值的提取依据工具 schema 中已知的参数名,安全可靠。
|
|
1145
|
+
*/
|
|
1146
|
+
parseXmlToolCalls(content, tools) {
|
|
1147
|
+
if (!content.includes("</")) return [];
|
|
1148
|
+
const toolCalls = [];
|
|
1149
|
+
let callIndex = 0;
|
|
1150
|
+
for (const tool of tools) {
|
|
1151
|
+
const startTag = `<${tool.name}>`;
|
|
1152
|
+
const endTag = `</${tool.name}>`;
|
|
1153
|
+
const paramNames = Object.keys(tool.parameters);
|
|
1154
|
+
let searchFrom = 0;
|
|
1155
|
+
while (true) {
|
|
1156
|
+
const blockStart = content.indexOf(startTag, searchFrom);
|
|
1157
|
+
if (blockStart === -1) break;
|
|
1158
|
+
const blockEnd = content.indexOf(endTag, blockStart + startTag.length);
|
|
1159
|
+
if (blockEnd === -1) break;
|
|
1160
|
+
const innerContent = content.slice(blockStart + startTag.length, blockEnd);
|
|
1161
|
+
const args = {};
|
|
1162
|
+
for (const paramName of paramNames) {
|
|
1163
|
+
const openTag = `<${paramName}>`;
|
|
1164
|
+
const closeTag = `</${paramName}>`;
|
|
1165
|
+
const pStart = innerContent.indexOf(openTag);
|
|
1166
|
+
if (pStart !== -1) {
|
|
1167
|
+
const pEnd = innerContent.indexOf(closeTag, pStart + openTag.length);
|
|
1168
|
+
if (pEnd !== -1) {
|
|
1169
|
+
args[paramName] = innerContent.slice(pStart + openTag.length, pEnd);
|
|
1170
|
+
}
|
|
1171
|
+
}
|
|
1172
|
+
}
|
|
1173
|
+
if (Object.keys(args).length > 0) {
|
|
1174
|
+
toolCalls.push({
|
|
1175
|
+
// id 格式:xml-fallback-{时间戳}-{序号},便于调试日志追踪
|
|
1176
|
+
id: `xml-fallback-${Date.now()}-${callIndex++}`,
|
|
1177
|
+
name: tool.name,
|
|
1178
|
+
arguments: args
|
|
1179
|
+
});
|
|
1180
|
+
}
|
|
1181
|
+
searchFrom = blockEnd + endTag.length;
|
|
1182
|
+
}
|
|
1183
|
+
}
|
|
1184
|
+
return toolCalls;
|
|
1185
|
+
}
|
|
1099
1186
|
};
|
|
1100
1187
|
|
|
1101
1188
|
// src/providers/custom.ts
|