zencode-cli 0.1.0 → 0.2.1
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/DESIGN.md +613 -0
- package/README.md +400 -0
- package/dist/bin/zencode.js +309 -57
- package/dist/bin/zencode.js.map +1 -1
- package/package.json +4 -2
package/dist/bin/zencode.js
CHANGED
|
@@ -446,6 +446,10 @@ var init_write_file = __esm({
|
|
|
446
446
|
content: {
|
|
447
447
|
type: "string",
|
|
448
448
|
description: "\u8981\u5199\u5165\u7684\u6587\u4EF6\u5185\u5BB9"
|
|
449
|
+
},
|
|
450
|
+
overwrite: {
|
|
451
|
+
type: "boolean",
|
|
452
|
+
description: "\u6587\u4EF6\u5DF2\u5B58\u5728\u65F6\u662F\u5426\u786E\u8BA4\u8986\u76D6\uFF0C\u9ED8\u8BA4 false"
|
|
449
453
|
}
|
|
450
454
|
},
|
|
451
455
|
required: ["path", "content"]
|
|
@@ -564,7 +568,7 @@ var init_bash = __esm({
|
|
|
564
568
|
async execute(params) {
|
|
565
569
|
const command = params["command"];
|
|
566
570
|
const timeout = params["timeout"] || DEFAULT_TIMEOUT;
|
|
567
|
-
return new Promise((
|
|
571
|
+
return new Promise((resolve8) => {
|
|
568
572
|
exec(
|
|
569
573
|
command,
|
|
570
574
|
{
|
|
@@ -585,7 +589,7 @@ ${stderr}`;
|
|
|
585
589
|
} else if (error && !stdout && !stderr) {
|
|
586
590
|
output = `\u547D\u4EE4\u6267\u884C\u5931\u8D25\uFF1A${error.message}`;
|
|
587
591
|
}
|
|
588
|
-
|
|
592
|
+
resolve8({ content: output || "\uFF08\u65E0\u8F93\u51FA\uFF09" });
|
|
589
593
|
}
|
|
590
594
|
);
|
|
591
595
|
});
|
|
@@ -929,6 +933,108 @@ var init_conversation = __esm({
|
|
|
929
933
|
}
|
|
930
934
|
});
|
|
931
935
|
|
|
936
|
+
// src/core/auto-memo.ts
|
|
937
|
+
function extractExports(code) {
|
|
938
|
+
const names = [];
|
|
939
|
+
for (const m of code.matchAll(/export\s+(?:default\s+)?(?:function|class|const|let|var)\s+(\w+)/g)) {
|
|
940
|
+
names.push(m[1]);
|
|
941
|
+
}
|
|
942
|
+
for (const m of code.matchAll(/^(?:async\s+)?function\s+(\w+)/gm)) {
|
|
943
|
+
if (!names.includes(m[1])) names.push(m[1]);
|
|
944
|
+
}
|
|
945
|
+
for (const m of code.matchAll(/(?:^|\n)\s{0,4}(?:async\s+)?function\s+(\w+)/g)) {
|
|
946
|
+
if (!names.includes(m[1])) names.push(m[1]);
|
|
947
|
+
}
|
|
948
|
+
return [...new Set(names)].slice(0, 8).join(", ");
|
|
949
|
+
}
|
|
950
|
+
function autoMemoForTool(memoStore, toolName, params, result) {
|
|
951
|
+
if (!memoStore) return;
|
|
952
|
+
if (toolName === "write-file") {
|
|
953
|
+
const path8 = params["path"];
|
|
954
|
+
const content = params["content"] || "";
|
|
955
|
+
const lines = content.split("\n").length;
|
|
956
|
+
const exports = extractExports(content);
|
|
957
|
+
memoStore.write(
|
|
958
|
+
`file:${path8}`,
|
|
959
|
+
content,
|
|
960
|
+
"auto",
|
|
961
|
+
`\u65B0\u5EFA ${lines}\u884C${exports ? " | \u5BFC\u51FA: " + exports : ""}`
|
|
962
|
+
);
|
|
963
|
+
}
|
|
964
|
+
if (toolName === "edit-file") {
|
|
965
|
+
const path8 = params["path"];
|
|
966
|
+
const newStr = params["new_string"] || "";
|
|
967
|
+
const oldStr = params["old_string"] || "";
|
|
968
|
+
const changeLines = newStr.split("\n").length;
|
|
969
|
+
memoStore.write(
|
|
970
|
+
`file:${path8}`,
|
|
971
|
+
`--- \u65E7 ---
|
|
972
|
+
${oldStr}
|
|
973
|
+
--- \u65B0 ---
|
|
974
|
+
${newStr}`,
|
|
975
|
+
"auto",
|
|
976
|
+
`\u7F16\u8F91 ${changeLines}\u884C\u53D8\u66F4`
|
|
977
|
+
);
|
|
978
|
+
}
|
|
979
|
+
if (toolName === "read-file") {
|
|
980
|
+
const path8 = params["path"];
|
|
981
|
+
const lines = result.split("\n").length;
|
|
982
|
+
const exports = extractExports(result);
|
|
983
|
+
memoStore.write(
|
|
984
|
+
`file:${path8}`,
|
|
985
|
+
result,
|
|
986
|
+
"auto",
|
|
987
|
+
`\u5DF2\u8BFB ${lines}\u884C${exports ? " | \u5BFC\u51FA: " + exports : ""}`
|
|
988
|
+
);
|
|
989
|
+
}
|
|
990
|
+
}
|
|
991
|
+
var init_auto_memo = __esm({
|
|
992
|
+
"src/core/auto-memo.ts"() {
|
|
993
|
+
"use strict";
|
|
994
|
+
}
|
|
995
|
+
});
|
|
996
|
+
|
|
997
|
+
// src/core/read-tracker.ts
|
|
998
|
+
import * as fs6 from "fs";
|
|
999
|
+
import * as path6 from "path";
|
|
1000
|
+
var ReadTracker;
|
|
1001
|
+
var init_read_tracker = __esm({
|
|
1002
|
+
"src/core/read-tracker.ts"() {
|
|
1003
|
+
"use strict";
|
|
1004
|
+
ReadTracker = class {
|
|
1005
|
+
files = /* @__PURE__ */ new Set();
|
|
1006
|
+
/** 标记文件已被读取 */
|
|
1007
|
+
markRead(filePath) {
|
|
1008
|
+
this.files.add(this.normalize(filePath));
|
|
1009
|
+
}
|
|
1010
|
+
/** 标记文件已被写入(新建/重写,agent 已知内容) */
|
|
1011
|
+
markWritten(filePath) {
|
|
1012
|
+
this.files.add(this.normalize(filePath));
|
|
1013
|
+
}
|
|
1014
|
+
/** 检查文件是否已读取 */
|
|
1015
|
+
hasRead(filePath) {
|
|
1016
|
+
return this.files.has(this.normalize(filePath));
|
|
1017
|
+
}
|
|
1018
|
+
/**
|
|
1019
|
+
* 检查 write-file 是否会覆盖已有文件
|
|
1020
|
+
* @returns 警告消息(需要拦截),或 null(可以继续执行)
|
|
1021
|
+
*/
|
|
1022
|
+
checkWriteOverwrite(filePath, overwrite) {
|
|
1023
|
+
const resolved = path6.resolve(filePath);
|
|
1024
|
+
if (!overwrite && fs6.existsSync(resolved)) {
|
|
1025
|
+
return `\u26A0 \u6587\u4EF6\u5DF2\u5B58\u5728\uFF1A${filePath}
|
|
1026
|
+
\u4FEE\u6539\u5DF2\u6709\u6587\u4EF6\u8BF7\u7528 read-file + edit-file\uFF08\u66F4\u7CBE\u786E\u5B89\u5168\uFF09\u3002
|
|
1027
|
+
\u5982\u786E\u9700\u5B8C\u6574\u91CD\u5199\uFF0C\u8BF7\u91CD\u65B0\u8C03\u7528 write-file \u5E76\u8BBE\u7F6E overwrite: true\u3002`;
|
|
1028
|
+
}
|
|
1029
|
+
return null;
|
|
1030
|
+
}
|
|
1031
|
+
normalize(filePath) {
|
|
1032
|
+
return filePath.replace(/\\/g, "/").replace(/^\.\//, "");
|
|
1033
|
+
}
|
|
1034
|
+
};
|
|
1035
|
+
}
|
|
1036
|
+
});
|
|
1037
|
+
|
|
932
1038
|
// src/core/agent.ts
|
|
933
1039
|
var Agent;
|
|
934
1040
|
var init_agent = __esm({
|
|
@@ -936,19 +1042,24 @@ var init_agent = __esm({
|
|
|
936
1042
|
"use strict";
|
|
937
1043
|
init_permission();
|
|
938
1044
|
init_conversation();
|
|
1045
|
+
init_auto_memo();
|
|
1046
|
+
init_read_tracker();
|
|
939
1047
|
Agent = class {
|
|
940
1048
|
conversation;
|
|
941
1049
|
client;
|
|
942
1050
|
registry;
|
|
943
1051
|
config;
|
|
944
1052
|
fixedTools;
|
|
945
|
-
|
|
1053
|
+
memoStore;
|
|
1054
|
+
readTracker = new ReadTracker();
|
|
1055
|
+
constructor(client, registry, config, systemPrompt, tools, memoStore) {
|
|
946
1056
|
this.client = client;
|
|
947
1057
|
this.registry = registry;
|
|
948
1058
|
this.config = config;
|
|
949
1059
|
this.conversation = new Conversation();
|
|
950
1060
|
this.conversation.setSystemPrompt(systemPrompt);
|
|
951
1061
|
this.fixedTools = tools;
|
|
1062
|
+
this.memoStore = memoStore;
|
|
952
1063
|
}
|
|
953
1064
|
/**
|
|
954
1065
|
* 执行一轮完整的 agent 循环
|
|
@@ -978,6 +1089,26 @@ var init_agent = __esm({
|
|
|
978
1089
|
continue;
|
|
979
1090
|
}
|
|
980
1091
|
try {
|
|
1092
|
+
if (toolName === "edit-file") {
|
|
1093
|
+
const editPath = params["path"];
|
|
1094
|
+
if (!this.readTracker.hasRead(editPath)) {
|
|
1095
|
+
this.conversation.addToolResult(
|
|
1096
|
+
toolCall.id,
|
|
1097
|
+
`\u26A0 \u7981\u6B62\u7F16\u8F91\u672A\u8BFB\u53D6\u7684\u6587\u4EF6\u3002\u8BF7\u5148 read-file "${editPath}" \u4E86\u89E3\u5F53\u524D\u5185\u5BB9\uFF0C\u518D edit-file\u3002`
|
|
1098
|
+
);
|
|
1099
|
+
continue;
|
|
1100
|
+
}
|
|
1101
|
+
}
|
|
1102
|
+
if (toolName === "write-file") {
|
|
1103
|
+
const warn = this.readTracker.checkWriteOverwrite(
|
|
1104
|
+
params["path"],
|
|
1105
|
+
params["overwrite"]
|
|
1106
|
+
);
|
|
1107
|
+
if (warn) {
|
|
1108
|
+
this.conversation.addToolResult(toolCall.id, warn);
|
|
1109
|
+
continue;
|
|
1110
|
+
}
|
|
1111
|
+
}
|
|
981
1112
|
const permLevel = this.registry.getPermissionLevel(toolName);
|
|
982
1113
|
if (permLevel === "deny") {
|
|
983
1114
|
callbacks.onDenied?.(toolName);
|
|
@@ -998,6 +1129,12 @@ var init_agent = __esm({
|
|
|
998
1129
|
}
|
|
999
1130
|
const result = await this.registry.execute(toolName, params, this.config.max_tool_output);
|
|
1000
1131
|
callbacks.onToolResult?.(toolName, result.content, result.truncated ?? false);
|
|
1132
|
+
autoMemoForTool(this.memoStore, toolName, params, result.content);
|
|
1133
|
+
if (toolName === "read-file") {
|
|
1134
|
+
this.readTracker.markRead(params["path"]);
|
|
1135
|
+
} else if (toolName === "write-file") {
|
|
1136
|
+
this.readTracker.markWritten(params["path"]);
|
|
1137
|
+
}
|
|
1001
1138
|
this.conversation.addToolResult(toolCall.id, result.content);
|
|
1002
1139
|
} catch (err) {
|
|
1003
1140
|
const msg = err instanceof Error ? err.message : String(err);
|
|
@@ -1027,18 +1164,22 @@ var init_coder = __esm({
|
|
|
1027
1164
|
"use strict";
|
|
1028
1165
|
init_conversation();
|
|
1029
1166
|
init_permission();
|
|
1167
|
+
init_auto_memo();
|
|
1168
|
+
init_read_tracker();
|
|
1030
1169
|
Coder = class {
|
|
1031
1170
|
client;
|
|
1032
1171
|
registry;
|
|
1033
1172
|
config;
|
|
1034
1173
|
systemPrompt;
|
|
1035
1174
|
tools;
|
|
1036
|
-
|
|
1175
|
+
memoStore;
|
|
1176
|
+
constructor(client, registry, config, systemPrompt, tools, memoStore) {
|
|
1037
1177
|
this.client = client;
|
|
1038
1178
|
this.registry = registry;
|
|
1039
1179
|
this.config = config;
|
|
1040
1180
|
this.systemPrompt = systemPrompt;
|
|
1041
1181
|
this.tools = tools;
|
|
1182
|
+
this.memoStore = memoStore;
|
|
1042
1183
|
}
|
|
1043
1184
|
/**
|
|
1044
1185
|
* 执行编码任务(短生命周期,每次新建会话)
|
|
@@ -1051,6 +1192,7 @@ var init_coder = __esm({
|
|
|
1051
1192
|
const conversation = new Conversation();
|
|
1052
1193
|
conversation.setSystemPrompt(this.systemPrompt);
|
|
1053
1194
|
conversation.addUserMessage(taskMessage);
|
|
1195
|
+
const readTracker = new ReadTracker();
|
|
1054
1196
|
let lastContent = "";
|
|
1055
1197
|
while (true) {
|
|
1056
1198
|
const assistantMsg = await this.client.chatStream(
|
|
@@ -1073,6 +1215,26 @@ var init_coder = __esm({
|
|
|
1073
1215
|
continue;
|
|
1074
1216
|
}
|
|
1075
1217
|
try {
|
|
1218
|
+
if (toolName === "edit-file") {
|
|
1219
|
+
const editPath = params["path"];
|
|
1220
|
+
if (!readTracker.hasRead(editPath)) {
|
|
1221
|
+
conversation.addToolResult(
|
|
1222
|
+
toolCall.id,
|
|
1223
|
+
`\u26A0 \u7981\u6B62\u7F16\u8F91\u672A\u8BFB\u53D6\u7684\u6587\u4EF6\u3002\u8BF7\u5148 read-file "${editPath}" \u4E86\u89E3\u5F53\u524D\u5185\u5BB9\uFF0C\u518D edit-file\u3002`
|
|
1224
|
+
);
|
|
1225
|
+
continue;
|
|
1226
|
+
}
|
|
1227
|
+
}
|
|
1228
|
+
if (toolName === "write-file") {
|
|
1229
|
+
const warn = readTracker.checkWriteOverwrite(
|
|
1230
|
+
params["path"],
|
|
1231
|
+
params["overwrite"]
|
|
1232
|
+
);
|
|
1233
|
+
if (warn) {
|
|
1234
|
+
conversation.addToolResult(toolCall.id, warn);
|
|
1235
|
+
continue;
|
|
1236
|
+
}
|
|
1237
|
+
}
|
|
1076
1238
|
const permLevel = this.registry.getPermissionLevel(toolName);
|
|
1077
1239
|
if (permLevel === "deny") {
|
|
1078
1240
|
callbacks.onDenied?.(toolName);
|
|
@@ -1093,6 +1255,12 @@ var init_coder = __esm({
|
|
|
1093
1255
|
}
|
|
1094
1256
|
const result = await this.registry.execute(toolName, params, this.config.max_tool_output);
|
|
1095
1257
|
callbacks.onToolResult?.(toolName, result.content, result.truncated ?? false);
|
|
1258
|
+
autoMemoForTool(this.memoStore, toolName, params, result.content);
|
|
1259
|
+
if (toolName === "read-file") {
|
|
1260
|
+
readTracker.markRead(params["path"]);
|
|
1261
|
+
} else if (toolName === "write-file") {
|
|
1262
|
+
readTracker.markWritten(params["path"]);
|
|
1263
|
+
}
|
|
1096
1264
|
conversation.addToolResult(toolCall.id, result.content);
|
|
1097
1265
|
} catch (err) {
|
|
1098
1266
|
const msg = err instanceof Error ? err.message : String(err);
|
|
@@ -1126,21 +1294,34 @@ var CODER_IDENTITY, DELEGATED_MODE, AUTONOMOUS_MODE, CONTROLLED_MODE;
|
|
|
1126
1294
|
var init_modes = __esm({
|
|
1127
1295
|
"src/core/dual-agent/modes.ts"() {
|
|
1128
1296
|
"use strict";
|
|
1129
|
-
CODER_IDENTITY = `\u4F60\u662F\u7F16\u7801\u5B50 Agent\u3002
|
|
1297
|
+
CODER_IDENTITY = `\u4F60\u662F\u7F16\u7801\u5B50 Agent\u3002
|
|
1130
1298
|
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
- \
|
|
1134
|
-
- \
|
|
1135
|
-
|
|
1136
|
-
|
|
1299
|
+
## \u5DE5\u4F5C\u6D41\u7A0B
|
|
1300
|
+
1. \u67E5\u770B\u4EFB\u52A1\u672B\u5C3E\u7684 [\u5171\u4EAB\u5907\u5FD8\u5F55] \u4E86\u89E3\u5DF2\u6709\u6587\u4EF6\u548C\u51FD\u6570
|
|
1301
|
+
- \u6BCF\u884C\u683C\u5F0F\uFF1A[file:\u8DEF\u5F84] \u6458\u8981 | \u5BFC\u51FA: \u51FD\u6570\u540D\u5217\u8868
|
|
1302
|
+
- \u9700\u8981\u5B8C\u6574\u6587\u4EF6\u5185\u5BB9\u6216 diff \u8BE6\u60C5 \u2192 memo read <key>
|
|
1303
|
+
2. \u7F16\u7801\uFF1A
|
|
1304
|
+
- \u65B0\u5EFA\u6587\u4EF6 \u2192 write-file
|
|
1305
|
+
- \u4FEE\u6539\u6587\u4EF6 \u2192 \u5FC5\u987B\u5148 read-file \u9605\u8BFB \u2192 \u518D edit-file \u4FEE\u6539
|
|
1306
|
+
- \u26A0\uFE0F \u7CFB\u7EDF\u5F3A\u5236\uFF1A\u672A read-file \u7684\u6587\u4EF6\u65E0\u6CD5 edit-file\uFF0C\u4F1A\u88AB\u62E6\u622A
|
|
1307
|
+
- \u5F15\u7528\u5DF2\u6709\u6587\u4EF6\u7684\u51FD\u6570\u65F6\uFF0C\u52A1\u5FC5\u4F7F\u7528 memo \u4E2D\u5217\u51FA\u7684\u51C6\u786E\u540D\u79F0
|
|
1308
|
+
3. \u4E00\u53E5\u8BDD\u8BF4\u660E\u7ED3\u679C
|
|
1309
|
+
|
|
1310
|
+
\u6CE8\u610F\uFF1A\u6587\u4EF6\u64CD\u4F5C\uFF08write-file\u3001edit-file\uFF09\u4F1A\u81EA\u52A8\u8BB0\u5F55\u5230 memo\uFF0C\u4E0D\u9700\u8981\u624B\u52A8 memo write \u6587\u4EF6\u4FE1\u606F\u3002
|
|
1311
|
+
\u5982\u6709\u9700\u8981\uFF0C\u4ECD\u53EF memo write \u8BB0\u5F55\u975E\u6587\u4EF6\u7C7B\u4FE1\u606F\uFF08\u67B6\u6784\u51B3\u7B56\u3001\u6CE8\u610F\u4E8B\u9879\u7B49\uFF09\u3002
|
|
1312
|
+
|
|
1313
|
+
## edit-file \u51C6\u786E\u6027\u89C4\u5219
|
|
1314
|
+
- old_string \u5FC5\u987B\u4ECE read-file \u8FD4\u56DE\u7684\u5185\u5BB9\u4E2D**\u7CBE\u786E\u590D\u5236**\uFF0C\u4E0D\u80FD\u51ED\u8BB0\u5FC6\u624B\u5199
|
|
1315
|
+
- old_string \u5305\u542B\u8DB3\u591F\u4E0A\u4E0B\u6587\u884C\uFF083-5 \u884C\uFF09\u786E\u4FDD\u552F\u4E00\u5339\u914D
|
|
1316
|
+
- \u7F29\u8FDB\u3001\u7A7A\u683C\u3001\u6362\u884C\u7B26\u5FC5\u987B\u5B8C\u5168\u4E00\u81F4
|
|
1317
|
+
- \u5982\u679C\u4E0D\u786E\u5B9A\u6587\u4EF6\u5185\u5BB9\uFF0C\u5148 read-file \u518D\u64CD\u4F5C
|
|
1137
1318
|
|
|
1138
1319
|
## \u7981\u6B62
|
|
1139
|
-
- \u274C \u7F16\u7801\u524D\u505A\u63A2\u7D22\uFF08bash ls/dir/pwd\u3001glob\u3001grep\uFF09\u2014 \
|
|
1320
|
+
- \u274C \u7F16\u7801\u524D\u505A\u63A2\u7D22\uFF08bash ls/dir/pwd\u3001glob\u3001grep\uFF09\u2014 \u4E0A\u4E0B\u6587\u5DF2\u5728 memo \u4E2D
|
|
1140
1321
|
- \u274C \u8F93\u51FA\u8BA1\u5212\u3001\u5206\u6790\u3001\u601D\u8DEF\u8BF4\u660E \u2014 \u76F4\u63A5\u52A8\u624B
|
|
1141
1322
|
- \u274C \u505A\u4EFB\u52A1\u8303\u56F4\u5916\u7684\u6539\u52A8
|
|
1142
|
-
- \u274C \
|
|
1143
|
-
- \u274C \
|
|
1323
|
+
- \u274C \u8FC7\u5EA6\u5DE5\u7A0B\u5316
|
|
1324
|
+
- \u274C \u51ED\u8BB0\u5FC6\u731C\u6D4B\u6587\u4EF6\u5185\u5BB9\u7528\u4E8E edit-file \u7684 old_string`;
|
|
1144
1325
|
DELEGATED_MODE = {
|
|
1145
1326
|
name: "delegated",
|
|
1146
1327
|
description: "A\u6536\u96C6\u4E0A\u4E0B\u6587\u5E76\u59D4\u6D3E\uFF0CB\u62E5\u6709\u5B8C\u6574\u5DE5\u5177\u72EC\u7ACB\u6267\u884C",
|
|
@@ -1175,6 +1356,8 @@ var init_orchestrator = __esm({
|
|
|
1175
1356
|
init_permission();
|
|
1176
1357
|
init_coder();
|
|
1177
1358
|
init_modes();
|
|
1359
|
+
init_auto_memo();
|
|
1360
|
+
init_read_tracker();
|
|
1178
1361
|
SEND_TO_CODER_TOOL = {
|
|
1179
1362
|
type: "function",
|
|
1180
1363
|
function: {
|
|
@@ -1201,6 +1384,7 @@ var init_orchestrator = __esm({
|
|
|
1201
1384
|
mode;
|
|
1202
1385
|
baseSystemPrompt;
|
|
1203
1386
|
memoStore;
|
|
1387
|
+
readTracker = new ReadTracker();
|
|
1204
1388
|
constructor(registry, config, systemPrompt, memoStore) {
|
|
1205
1389
|
this.registry = registry;
|
|
1206
1390
|
this.config = config;
|
|
@@ -1246,31 +1430,29 @@ var init_orchestrator = __esm({
|
|
|
1246
1430
|
|
|
1247
1431
|
\u534F\u4F5C\u6A21\u5F0F\uFF1A${modeInfo.name} - ${modeInfo.description}
|
|
1248
1432
|
|
|
1249
|
-
\u4F60\u662F\u4FA6\u5BDF\u5175 + \u6307\u6325\u5B98\u3002\u4F60\u81EA\u5DF1\u4E0D\u5199\u4EE3\u7801\uFF0C\u4F60\u7684\u804C\u8D23\u662F\uFF1A\u6536\u96C6\u60C5\u62A5 \u2192 \
|
|
1433
|
+
\u4F60\u662F\u4FA6\u5BDF\u5175 + \u6307\u6325\u5B98\u3002\u4F60\u81EA\u5DF1\u4E0D\u5199\u4EE3\u7801\uFF0C\u4F60\u7684\u804C\u8D23\u662F\uFF1A\u6536\u96C6\u60C5\u62A5 \u2192 \u59D4\u6D3E\u7F16\u7801 Agent\u3002
|
|
1250
1434
|
|
|
1251
1435
|
## \u6838\u5FC3\u6D41\u7A0B
|
|
1252
1436
|
|
|
1253
1437
|
1. **\u8BC4\u4F30**\uFF1A\u4EFB\u52A1\u662F\u5426\u9700\u8981\u4E86\u89E3\u73B0\u6709\u4EE3\u7801\uFF1F
|
|
1254
|
-
- \u9700\u8981\u4FEE\u6539\u73B0\u6709\u6587\u4EF6\u3001\u9700\u8981\
|
|
1255
|
-
- \u9700\u6C42\
|
|
1438
|
+
- \u9700\u8981\u4FEE\u6539\u73B0\u6709\u6587\u4EF6\u3001\u9700\u8981\u7406\u89E3\u4F9D\u8D56\u5173\u7CFB \u2192 \u5148\u6536\u96C6
|
|
1439
|
+
- \u9700\u6C42\u81EA\u5305\u542B\u3001\u76EE\u6807\u8DEF\u5F84\u660E\u786E \u2192 \u8DF3\u5230\u7B2C 3 \u6B65
|
|
1256
1440
|
|
|
1257
1441
|
2. **\u6536\u96C6\u4E0A\u4E0B\u6587**\uFF08\u9AD8\u6548\uFF0C\u4E0D\u91CD\u590D\uFF09
|
|
1258
|
-
- \u7528 glob/grep \u5B9A\u4F4D\
|
|
1259
|
-
- \
|
|
1260
|
-
-
|
|
1261
|
-
\u4F8B\uFF1Amemo write key="demo-structure" value="demo/ \u4E0B\u6709 weather.html\uFF08\u5929\u6C14\u7EC4\u4EF6\u793A\u4F8B\uFF09\uFF0C\u4F7F\u7528\u7EAF HTML+CSS+JS \u5355\u6587\u4EF6\u7ED3\u6784"
|
|
1262
|
-
- \u7CBE\u70BC\u6458\u8981\uFF0C\u4E0D\u8981\u590D\u5236\u6574\u4E2A\u6587\u4EF6\u5185\u5BB9
|
|
1442
|
+
- \u7528 glob/grep \u5B9A\u4F4D + read-file \u6216 spawn-agents \u5E76\u884C\u8BFB\u53D6
|
|
1443
|
+
- \u6587\u4EF6\u64CD\u4F5C\uFF08read-file \u7B49\uFF09\u4F1A\u81EA\u52A8\u8BB0\u5F55\u5230 memo\uFF0C\u4E0D\u9700\u8981\u624B\u52A8 memo write \u6587\u4EF6\u5185\u5BB9
|
|
1444
|
+
- \u4ECD\u53EF memo write \u8BB0\u5F55\u5206\u6790\u7ED3\u8BBA\u3001\u67B6\u6784\u51B3\u7B56\u7B49\u975E\u6587\u4EF6\u4FE1\u606F
|
|
1263
1445
|
|
|
1264
1446
|
3. **\u59D4\u6D3E\u7F16\u7801**\uFF1Asend-to-coder
|
|
1265
|
-
- task \u4E2D\u5199\u6E05\uFF1A\u505A\u4EC0\u4E48 + \u76EE\u6807\u8DEF\u5F84
|
|
1266
|
-
|
|
1447
|
+
- task \u4E2D\u5199\u6E05\uFF1A\u505A\u4EC0\u4E48 + \u76EE\u6807\u8DEF\u5F84
|
|
1448
|
+
- \u7F16\u7801 Agent \u4F1A\u81EA\u52A8\u770B\u5230 memo \u4E2D\u7684\u6587\u4EF6\u7D22\u5F15\uFF08\u5305\u62EC\u5DF2\u521B\u5EFA\u7684\u6587\u4EF6\u548C\u5BFC\u51FA\u7684\u51FD\u6570\u540D\uFF09
|
|
1267
1449
|
- \u6BCF\u6B21\u53EA\u53D1\u4E00\u4E2A\u5177\u4F53\u6B65\u9AA4
|
|
1268
1450
|
|
|
1269
1451
|
4. **\u8FED\u4EE3/\u9A8C\u8BC1**\uFF1A\u9700\u8981\u65F6\u7EE7\u7EED\u59D4\u6D3E\u6216\u7528 bash \u8FD0\u884C\u9A8C\u8BC1
|
|
1270
1452
|
|
|
1271
1453
|
## \u91CD\u8981
|
|
1272
1454
|
|
|
1273
|
-
- memo \
|
|
1455
|
+
- memo \u7D22\u5F15\u4F1A\u81EA\u52A8\u6CE8\u5165\u7ED9\u7F16\u7801 Agent\uFF0C\u5305\u542B\u6240\u6709\u5DF2\u64CD\u4F5C\u6587\u4EF6\u7684\u6458\u8981\u548C\u5BFC\u51FA\u51FD\u6570\u540D
|
|
1274
1456
|
- \u4E0D\u8981\u91CD\u590D\u63A2\u7D22\uFF08glob \u67E5\u8FC7\u5C31\u4E0D\u8981\u518D bash ls \u540C\u4E00\u76EE\u5F55\uFF09
|
|
1275
1457
|
- bash \u7528\u4E8E\u6267\u884C\u547D\u4EE4\uFF08\u6784\u5EFA\u3001\u6D4B\u8BD5\uFF09\uFF0C\u4E0D\u9700\u8981\u59D4\u6D3E
|
|
1276
1458
|
- \u5B8C\u6210\u6240\u6709\u6B65\u9AA4\u540E\u7B80\u8981\u544A\u77E5\u7528\u6237\u7ED3\u679C`;
|
|
@@ -1317,6 +1499,26 @@ var init_orchestrator = __esm({
|
|
|
1317
1499
|
this.conversation.addToolResult(toolCall.id, coderResponse);
|
|
1318
1500
|
continue;
|
|
1319
1501
|
}
|
|
1502
|
+
if (toolName === "edit-file") {
|
|
1503
|
+
const editPath = params["path"];
|
|
1504
|
+
if (!this.readTracker.hasRead(editPath)) {
|
|
1505
|
+
this.conversation.addToolResult(
|
|
1506
|
+
toolCall.id,
|
|
1507
|
+
`\u26A0 \u7981\u6B62\u7F16\u8F91\u672A\u8BFB\u53D6\u7684\u6587\u4EF6\u3002\u8BF7\u5148 read-file "${editPath}" \u4E86\u89E3\u5F53\u524D\u5185\u5BB9\uFF0C\u518D edit-file\u3002`
|
|
1508
|
+
);
|
|
1509
|
+
continue;
|
|
1510
|
+
}
|
|
1511
|
+
}
|
|
1512
|
+
if (toolName === "write-file") {
|
|
1513
|
+
const warn = this.readTracker.checkWriteOverwrite(
|
|
1514
|
+
params["path"],
|
|
1515
|
+
params["overwrite"]
|
|
1516
|
+
);
|
|
1517
|
+
if (warn) {
|
|
1518
|
+
this.conversation.addToolResult(toolCall.id, warn);
|
|
1519
|
+
continue;
|
|
1520
|
+
}
|
|
1521
|
+
}
|
|
1320
1522
|
const permLevel = this.registry.getPermissionLevel(toolName);
|
|
1321
1523
|
if (permLevel === "deny") {
|
|
1322
1524
|
callbacks.onDenied?.(toolName);
|
|
@@ -1337,6 +1539,12 @@ var init_orchestrator = __esm({
|
|
|
1337
1539
|
}
|
|
1338
1540
|
const result = await this.registry.execute(toolName, params, this.config.max_tool_output);
|
|
1339
1541
|
callbacks.onToolResult?.(toolName, result.content, result.truncated ?? false);
|
|
1542
|
+
autoMemoForTool(this.memoStore, toolName, params, result.content);
|
|
1543
|
+
if (toolName === "read-file") {
|
|
1544
|
+
this.readTracker.markRead(params["path"]);
|
|
1545
|
+
} else if (toolName === "write-file") {
|
|
1546
|
+
this.readTracker.markWritten(params["path"]);
|
|
1547
|
+
}
|
|
1340
1548
|
this.conversation.addToolResult(toolCall.id, result.content);
|
|
1341
1549
|
} catch (err) {
|
|
1342
1550
|
const msg = err instanceof Error ? err.message : String(err);
|
|
@@ -1375,7 +1583,8 @@ ${index}`;
|
|
|
1375
1583
|
this.registry,
|
|
1376
1584
|
this.config,
|
|
1377
1585
|
modeInfo.coderSystemPrompt,
|
|
1378
|
-
coderTools
|
|
1586
|
+
coderTools,
|
|
1587
|
+
this.memoStore
|
|
1379
1588
|
);
|
|
1380
1589
|
const response = await coder.execute(taskWithMemo, {
|
|
1381
1590
|
onContent: callbacks.onContent,
|
|
@@ -1410,14 +1619,19 @@ function buildCorePrompt() {
|
|
|
1410
1619
|
\u4F60\u6709\u4EE5\u4E0B\u5DE5\u5177\u53EF\u7528\uFF0C\u8BF7\u6839\u636E\u4EFB\u52A1\u9009\u62E9\u6700\u5408\u9002\u7684\u5DE5\u5177\uFF1A
|
|
1411
1620
|
|
|
1412
1621
|
- **read-file**\uFF1A\u8BFB\u53D6\u6587\u4EF6\u5185\u5BB9\u3002\u4FEE\u6539\u4EE3\u7801\u524D\u5FC5\u987B\u5148\u8BFB\u53D6\u76EE\u6807\u6587\u4EF6\u3002\u652F\u6301 offset/limit \u8BFB\u53D6\u5927\u6587\u4EF6\u7684\u7279\u5B9A\u90E8\u5206\u3002
|
|
1413
|
-
- **edit-file**\uFF1A\u901A\u8FC7\u5B57\u7B26\u4E32\u66FF\u6362\u7F16\u8F91\u6587\u4EF6\u3002\u4F18\u5148\u4F7F\u7528 edit-file \u800C\u975E write-file \u4FEE\u6539\u5DF2\u6709\u6587\u4EF6\u2014\u2014\u5B83\u66F4\u7CBE\u786E\u3001\u66F4\u5B89\u5168\
|
|
1622
|
+
- **edit-file**\uFF1A\u901A\u8FC7\u5B57\u7B26\u4E32\u66FF\u6362\u7F16\u8F91\u6587\u4EF6\u3002\u4F18\u5148\u4F7F\u7528 edit-file \u800C\u975E write-file \u4FEE\u6539\u5DF2\u6709\u6587\u4EF6\u2014\u2014\u5B83\u66F4\u7CBE\u786E\u3001\u66F4\u5B89\u5168\u3002
|
|
1623
|
+
- \u26A0\uFE0F \u7CFB\u7EDF\u5F3A\u5236\uFF1A\u672A\u7528 read-file \u8BFB\u53D6\u8FC7\u7684\u6587\u4EF6\u65E0\u6CD5 edit-file\uFF0C\u4F1A\u88AB\u62E6\u622A
|
|
1624
|
+
- old_string \u5FC5\u987B\u4E0E\u6587\u4EF6\u4E2D\u7684\u5185\u5BB9**\u5B8C\u5168\u4E00\u81F4**\uFF08\u5305\u62EC\u7F29\u8FDB\u3001\u7A7A\u683C\u3001\u6362\u884C\u7B26\uFF09
|
|
1625
|
+
- old_string \u4E0D\u552F\u4E00\u65F6\uFF0C\u5305\u542B\u66F4\u591A\u4E0A\u4E0B\u6587\u884C\uFF08\u5EFA\u8BAE 3-5 \u884C\uFF09\u4F7F\u5176\u552F\u4E00
|
|
1626
|
+
- \u4E0D\u8981\u51ED\u8BB0\u5FC6\u731C\u6D4B\u6587\u4EF6\u5185\u5BB9\uFF0C\u5FC5\u987B\u57FA\u4E8E read-file \u7684\u5B9E\u9645\u8FD4\u56DE\u503C
|
|
1414
1627
|
- **write-file**\uFF1A\u521B\u5EFA\u65B0\u6587\u4EF6\u6216\u5B8C\u6574\u91CD\u5199\u6587\u4EF6\u3002\u4EC5\u5728\u521B\u5EFA\u65B0\u6587\u4EF6\u6216\u9700\u8981\u5927\u5E45\u91CD\u5199\u65F6\u4F7F\u7528\u3002
|
|
1415
1628
|
- **glob**\uFF1A\u6309\u6A21\u5F0F\u641C\u7D22\u6587\u4EF6\u8DEF\u5F84\u3002\u7528\u4E8E\u67E5\u627E\u6587\u4EF6\u4F4D\u7F6E\uFF08\u5982 \`**/*.ts\`\u3001\`src/**/config.*\`\uFF09\u3002
|
|
1416
1629
|
- **grep**\uFF1A\u5728\u6587\u4EF6\u5185\u5BB9\u4E2D\u641C\u7D22\u6B63\u5219\u8868\u8FBE\u5F0F\u3002\u7528\u4E8E\u67E5\u627E\u51FD\u6570\u5B9A\u4E49\u3001\u5F15\u7528\u3001\u7279\u5B9A\u4EE3\u7801\u6A21\u5F0F\u3002
|
|
1417
1630
|
- **bash**\uFF1A\u6267\u884C shell \u547D\u4EE4\u3002\u7528\u4E8E\u8FD0\u884C\u6784\u5EFA\u3001\u6D4B\u8BD5\u3001git \u64CD\u4F5C\u7B49\u3002\u4E0D\u8981\u7528 bash \u505A\u80FD\u7528\u4E0A\u8FF0\u5DE5\u5177\u5B8C\u6210\u7684\u4E8B\uFF08\u5982\u4E0D\u8981\u7528 cat \u8BFB\u6587\u4EF6\u3001\u4E0D\u8981\u7528 sed \u7F16\u8F91\u6587\u4EF6\u3001\u4E0D\u8981\u7528 find \u641C\u7D22\u6587\u4EF6\uFF09\u3002
|
|
1418
1631
|
|
|
1419
1632
|
\u5173\u952E\u89C4\u5219\uFF1A
|
|
1420
|
-
- \u4FEE\u6539\
|
|
1633
|
+
- **\u5148\u8BFB\u540E\u6539**\uFF1A\u4FEE\u6539\u6587\u4EF6\u524D\u5FC5\u987B read-file \u8BFB\u53D6\u8BE5\u6587\u4EF6\uFF08\u7CFB\u7EDF\u4F1A\u62E6\u622A\u672A\u8BFB\u53D6\u5C31 edit \u7684\u64CD\u4F5C\uFF09
|
|
1634
|
+
- edit-file \u7684 old_string \u5FC5\u987B\u4ECE read-file \u8FD4\u56DE\u7684\u5185\u5BB9\u4E2D\u7CBE\u786E\u590D\u5236\uFF0C\u4E0D\u8981\u624B\u52A8\u8F93\u5165\u6216\u51ED\u8BB0\u5FC6
|
|
1421
1635
|
- \u4F18\u5148 edit-file \u7F16\u8F91\u5DF2\u6709\u6587\u4EF6\uFF0C\u800C\u975E write-file \u91CD\u5199
|
|
1422
1636
|
- \u4E0D\u8981\u521B\u5EFA\u4E0D\u5FC5\u8981\u7684\u65B0\u6587\u4EF6\uFF0C\u4F18\u5148\u5728\u73B0\u6709\u6587\u4EF6\u4E2D\u4FEE\u6539
|
|
1423
1637
|
- \u53EA\u505A\u5FC5\u8981\u7684\u6700\u5C0F\u6539\u52A8\uFF0C\u4E0D\u505A\u989D\u5916"\u6539\u8FDB"
|
|
@@ -1515,11 +1729,11 @@ var init_git = __esm({
|
|
|
1515
1729
|
});
|
|
1516
1730
|
|
|
1517
1731
|
// src/core/prompt/layers/project.ts
|
|
1518
|
-
import * as
|
|
1519
|
-
import * as
|
|
1732
|
+
import * as fs7 from "fs/promises";
|
|
1733
|
+
import * as path7 from "path";
|
|
1520
1734
|
async function buildProjectPrompt() {
|
|
1521
1735
|
try {
|
|
1522
|
-
const content = await
|
|
1736
|
+
const content = await fs7.readFile(path7.resolve("ZENCODE.md"), "utf-8");
|
|
1523
1737
|
return content.trim() || null;
|
|
1524
1738
|
} catch {
|
|
1525
1739
|
return null;
|
|
@@ -1529,8 +1743,8 @@ async function loadUserPrompts(paths) {
|
|
|
1529
1743
|
const prompts = [];
|
|
1530
1744
|
for (const p of paths) {
|
|
1531
1745
|
try {
|
|
1532
|
-
const resolved = p.startsWith("~") ?
|
|
1533
|
-
const content = await
|
|
1746
|
+
const resolved = p.startsWith("~") ? path7.join(process.env["HOME"] || process.env["USERPROFILE"] || "", p.slice(1)) : path7.resolve(p);
|
|
1747
|
+
const content = await fs7.readFile(resolved, "utf-8");
|
|
1534
1748
|
if (content.trim()) {
|
|
1535
1749
|
prompts.push(content.trim());
|
|
1536
1750
|
}
|
|
@@ -1546,10 +1760,10 @@ var init_project = __esm({
|
|
|
1546
1760
|
});
|
|
1547
1761
|
|
|
1548
1762
|
// src/core/prompt/builder.ts
|
|
1549
|
-
import * as
|
|
1763
|
+
import * as fs8 from "fs";
|
|
1550
1764
|
function isGitRepo() {
|
|
1551
1765
|
try {
|
|
1552
|
-
|
|
1766
|
+
fs8.statSync(".git");
|
|
1553
1767
|
return true;
|
|
1554
1768
|
} catch {
|
|
1555
1769
|
return false;
|
|
@@ -1649,9 +1863,15 @@ var init_memo_store = __esm({
|
|
|
1649
1863
|
MAX_CONTENT_LENGTH = 3e3;
|
|
1650
1864
|
MemoStore = class {
|
|
1651
1865
|
entries = /* @__PURE__ */ new Map();
|
|
1652
|
-
write(key, content, author = "agent") {
|
|
1866
|
+
write(key, content, author = "agent", summary) {
|
|
1653
1867
|
const trimmed = content.slice(0, MAX_CONTENT_LENGTH);
|
|
1654
|
-
const entry = {
|
|
1868
|
+
const entry = {
|
|
1869
|
+
key,
|
|
1870
|
+
summary: summary || content.slice(0, 80).replace(/\n/g, " "),
|
|
1871
|
+
content: trimmed,
|
|
1872
|
+
author,
|
|
1873
|
+
updatedAt: Date.now()
|
|
1874
|
+
};
|
|
1655
1875
|
if (!this.entries.has(key) && this.entries.size >= MAX_ENTRIES) {
|
|
1656
1876
|
let oldest = null;
|
|
1657
1877
|
let oldestTime = Infinity;
|
|
@@ -1673,7 +1893,7 @@ var init_memo_store = __esm({
|
|
|
1673
1893
|
return [...this.entries.values()].map((e) => ({
|
|
1674
1894
|
key: e.key,
|
|
1675
1895
|
author: e.author,
|
|
1676
|
-
|
|
1896
|
+
summary: e.summary
|
|
1677
1897
|
}));
|
|
1678
1898
|
}
|
|
1679
1899
|
delete(key) {
|
|
@@ -1683,15 +1903,13 @@ var init_memo_store = __esm({
|
|
|
1683
1903
|
this.entries.clear();
|
|
1684
1904
|
}
|
|
1685
1905
|
/**
|
|
1686
|
-
*
|
|
1687
|
-
*
|
|
1906
|
+
* 生成备忘录索引(注入 Coder 任务中)
|
|
1907
|
+
* 只输出 key + summary,清爽紧凑
|
|
1908
|
+
* Coder 需要详情时用 memo read <key> 获取完整内容
|
|
1688
1909
|
*/
|
|
1689
1910
|
buildIndex() {
|
|
1690
1911
|
if (this.entries.size === 0) return null;
|
|
1691
|
-
|
|
1692
|
-
(e) => `- ${e.key}: ${e.content.slice(0, 50)}`
|
|
1693
|
-
);
|
|
1694
|
-
return lines.join("\n");
|
|
1912
|
+
return [...this.entries.values()].map((e) => `[${e.key}] ${e.summary}`).join("\n");
|
|
1695
1913
|
}
|
|
1696
1914
|
};
|
|
1697
1915
|
}
|
|
@@ -1703,6 +1921,8 @@ var init_sub_agent = __esm({
|
|
|
1703
1921
|
"src/core/sub-agent.ts"() {
|
|
1704
1922
|
"use strict";
|
|
1705
1923
|
init_conversation();
|
|
1924
|
+
init_auto_memo();
|
|
1925
|
+
init_read_tracker();
|
|
1706
1926
|
DEFAULT_TIMEOUT_MS = 12e4;
|
|
1707
1927
|
SubAgent = class {
|
|
1708
1928
|
client;
|
|
@@ -1739,6 +1959,7 @@ var init_sub_agent = __esm({
|
|
|
1739
1959
|
}
|
|
1740
1960
|
async execute() {
|
|
1741
1961
|
const conversation = new Conversation();
|
|
1962
|
+
const readTracker = new ReadTracker();
|
|
1742
1963
|
let systemPrompt = `\u4F60\u662F ZenCode \u5B50 Agent\u3002\u4F60\u7684\u4EFB\u52A1\uFF1A${this.task}
|
|
1743
1964
|
\u5B8C\u6210\u540E\u76F4\u63A5\u8FD4\u56DE\u7ED3\u679C\uFF0C\u4E0D\u8981\u591A\u4F59\u89E3\u91CA\u3002`;
|
|
1744
1965
|
if (this.memoStore) {
|
|
@@ -1781,11 +2002,37 @@ ${index}`;
|
|
|
1781
2002
|
continue;
|
|
1782
2003
|
}
|
|
1783
2004
|
try {
|
|
2005
|
+
if (toolName === "edit-file") {
|
|
2006
|
+
const editPath = params["path"];
|
|
2007
|
+
if (!readTracker.hasRead(editPath)) {
|
|
2008
|
+
conversation.addToolResult(
|
|
2009
|
+
toolCall.id,
|
|
2010
|
+
`\u26A0 \u7981\u6B62\u7F16\u8F91\u672A\u8BFB\u53D6\u7684\u6587\u4EF6\u3002\u8BF7\u5148 read-file "${editPath}" \u4E86\u89E3\u5F53\u524D\u5185\u5BB9\uFF0C\u518D edit-file\u3002`
|
|
2011
|
+
);
|
|
2012
|
+
continue;
|
|
2013
|
+
}
|
|
2014
|
+
}
|
|
2015
|
+
if (toolName === "write-file") {
|
|
2016
|
+
const warn = readTracker.checkWriteOverwrite(
|
|
2017
|
+
params["path"],
|
|
2018
|
+
params["overwrite"]
|
|
2019
|
+
);
|
|
2020
|
+
if (warn) {
|
|
2021
|
+
conversation.addToolResult(toolCall.id, warn);
|
|
2022
|
+
continue;
|
|
2023
|
+
}
|
|
2024
|
+
}
|
|
1784
2025
|
const result = await this.registry.execute(
|
|
1785
2026
|
toolName,
|
|
1786
2027
|
params,
|
|
1787
2028
|
this.config.max_tool_output
|
|
1788
2029
|
);
|
|
2030
|
+
autoMemoForTool(this.memoStore, toolName, params, result.content);
|
|
2031
|
+
if (toolName === "read-file") {
|
|
2032
|
+
readTracker.markRead(params["path"]);
|
|
2033
|
+
} else if (toolName === "write-file") {
|
|
2034
|
+
readTracker.markWritten(params["path"]);
|
|
2035
|
+
}
|
|
1789
2036
|
conversation.addToolResult(toolCall.id, result.content);
|
|
1790
2037
|
} catch (err) {
|
|
1791
2038
|
const msg = err instanceof Error ? err.message : String(err);
|
|
@@ -2031,7 +2278,11 @@ function createMemoTool(store) {
|
|
|
2031
2278
|
},
|
|
2032
2279
|
content: {
|
|
2033
2280
|
type: "string",
|
|
2034
|
-
description: "write \u65F6\u5FC5\u586B\uFF1A\u8981\u5199\u5165\u7684\u5185\u5BB9\uFF08\
|
|
2281
|
+
description: "write \u65F6\u5FC5\u586B\uFF1A\u8981\u5199\u5165\u7684\u5185\u5BB9\uFF08\u6700\u591A 3000 \u5B57\u7B26\uFF09"
|
|
2282
|
+
},
|
|
2283
|
+
summary: {
|
|
2284
|
+
type: "string",
|
|
2285
|
+
description: "write \u65F6\u53EF\u9009\uFF1A\u4E00\u884C\u6458\u8981\uFF08\u4E0D\u586B\u5219\u81EA\u52A8\u622A\u53D6 content \u524D 80 \u5B57\u7B26\uFF09"
|
|
2035
2286
|
}
|
|
2036
2287
|
},
|
|
2037
2288
|
required: ["action"]
|
|
@@ -2043,10 +2294,11 @@ function createMemoTool(store) {
|
|
|
2043
2294
|
case "write": {
|
|
2044
2295
|
const key = params["key"];
|
|
2045
2296
|
const content = params["content"];
|
|
2297
|
+
const summary = params["summary"];
|
|
2046
2298
|
if (!key || !content) {
|
|
2047
2299
|
return { content: "\u9519\u8BEF\uFF1Awrite \u9700\u8981\u63D0\u4F9B key \u548C content" };
|
|
2048
2300
|
}
|
|
2049
|
-
const entry = store.write(key, content);
|
|
2301
|
+
const entry = store.write(key, content, "agent", summary);
|
|
2050
2302
|
return { content: `\u5DF2\u5199\u5165 memo [${entry.key}]\uFF08${entry.content.length} \u5B57\u7B26\uFF09` };
|
|
2051
2303
|
}
|
|
2052
2304
|
case "read": {
|
|
@@ -2067,7 +2319,7 @@ ${entry.content}` };
|
|
|
2067
2319
|
return { content: "\u5907\u5FD8\u5F55\u4E3A\u7A7A" };
|
|
2068
2320
|
}
|
|
2069
2321
|
const lines = items.map(
|
|
2070
|
-
(item) => `[${item.key}] (${item.author}) ${item.
|
|
2322
|
+
(item) => `[${item.key}] (${item.author}) ${item.summary}`
|
|
2071
2323
|
);
|
|
2072
2324
|
return { content: `\u5171 ${items.length} \u6761\u5907\u5FD8\u5F55\uFF1A
|
|
2073
2325
|
${lines.join("\n")}` };
|
|
@@ -3420,7 +3672,7 @@ function App({ config, client, agent, orchestrator, registry, todoStore, memoSto
|
|
|
3420
3672
|
);
|
|
3421
3673
|
useEffect(() => {
|
|
3422
3674
|
setStructuredConfirmHandler((toolName, params) => {
|
|
3423
|
-
return new Promise((
|
|
3675
|
+
return new Promise((resolve8) => {
|
|
3424
3676
|
const id = `confirm-${Date.now()}`;
|
|
3425
3677
|
registerConfirmToolId(toolName, id);
|
|
3426
3678
|
dispatch({
|
|
@@ -3431,13 +3683,13 @@ function App({ config, client, agent, orchestrator, registry, todoStore, memoSto
|
|
|
3431
3683
|
resolve: (result) => {
|
|
3432
3684
|
if (result === "always") {
|
|
3433
3685
|
registry.addAutoApprove(toolName);
|
|
3434
|
-
|
|
3686
|
+
resolve8({ approved: true });
|
|
3435
3687
|
} else if (result === "allow") {
|
|
3436
|
-
|
|
3688
|
+
resolve8({ approved: true });
|
|
3437
3689
|
} else if (result === "deny") {
|
|
3438
|
-
|
|
3690
|
+
resolve8({ approved: false });
|
|
3439
3691
|
} else {
|
|
3440
|
-
|
|
3692
|
+
resolve8({ approved: false, feedback: result.feedback });
|
|
3441
3693
|
}
|
|
3442
3694
|
}
|
|
3443
3695
|
});
|
|
@@ -3707,7 +3959,7 @@ async function startTui(options) {
|
|
|
3707
3959
|
registry.register(createTodoTool(todoStore));
|
|
3708
3960
|
}
|
|
3709
3961
|
registry.register(createMemoTool(memoStore));
|
|
3710
|
-
const agent = new Agent(client, registry, config, systemPrompt);
|
|
3962
|
+
const agent = new Agent(client, registry, config, systemPrompt, void 0, memoStore);
|
|
3711
3963
|
const orchestrator = new Orchestrator(registry, config, systemPrompt, memoStore);
|
|
3712
3964
|
const { waitUntilExit } = render(
|
|
3713
3965
|
/* @__PURE__ */ jsx9(
|
|
@@ -3959,13 +4211,13 @@ async function startRepl(options) {
|
|
|
3959
4211
|
historySize: 100
|
|
3960
4212
|
});
|
|
3961
4213
|
setConfirmHandler(async (promptText) => {
|
|
3962
|
-
return new Promise((
|
|
4214
|
+
return new Promise((resolve8) => {
|
|
3963
4215
|
process.stdout.write(promptText);
|
|
3964
4216
|
const onData = (data) => {
|
|
3965
4217
|
process.stdin.removeListener("data", onData);
|
|
3966
4218
|
process.stdin.pause();
|
|
3967
4219
|
const answer = data.toString().trim().toLowerCase();
|
|
3968
|
-
|
|
4220
|
+
resolve8(answer === "y");
|
|
3969
4221
|
};
|
|
3970
4222
|
process.stdin.resume();
|
|
3971
4223
|
process.stdin.once("data", onData);
|
|
@@ -4131,7 +4383,7 @@ async function runOnce(prompt, config) {
|
|
|
4131
4383
|
};
|
|
4132
4384
|
try {
|
|
4133
4385
|
if (config.agent_mode === "single") {
|
|
4134
|
-
const agent = new Agent(client, registry, config, systemPrompt);
|
|
4386
|
+
const agent = new Agent(client, registry, config, systemPrompt, void 0, memoStore);
|
|
4135
4387
|
await agent.run(prompt, callbacks);
|
|
4136
4388
|
} else {
|
|
4137
4389
|
const orchestrator = new Orchestrator(registry, config, systemPrompt, memoStore);
|
|
@@ -4148,7 +4400,7 @@ async function runOnce(prompt, config) {
|
|
|
4148
4400
|
}
|
|
4149
4401
|
function createCli() {
|
|
4150
4402
|
const program2 = new Command();
|
|
4151
|
-
program2.name("zencode").description("\u6781\u7B80 CLI AI \u7F16\u7A0B\u5DE5\u5177").version("0.1
|
|
4403
|
+
program2.name("zencode").description("\u6781\u7B80 CLI AI \u7F16\u7A0B\u5DE5\u5177").version("0.2.1").option("-m, --model <model>", "\u6307\u5B9A\u6A21\u578B\u540D\u79F0").option("-k, --api-key <key>", "API \u5BC6\u94A5").option("-u, --base-url <url>", "API \u57FA\u7840 URL").option("--single", "\u4F7F\u7528\u5355 Agent \u6A21\u5F0F").option("--dual", "\u4F7F\u7528\u53CC Agent \u6A21\u5F0F").option("--mode <mode>", "\u534F\u4F5C\u6A21\u5F0F (delegated/autonomous/controlled)").option("--simple", "\u4F7F\u7528\u7B80\u5355 REPL \u6A21\u5F0F\uFF08\u975E\u5168\u5C4F TUI\uFF09").argument("[prompt...]", "\u76F4\u63A5\u6267\u884C\u7684\u63D0\u793A\u8BCD\uFF08\u975E\u4EA4\u4E92\u5F0F\uFF09").action(async (promptParts, opts) => {
|
|
4152
4404
|
const config = loadConfig(opts);
|
|
4153
4405
|
if (!config.api_key) {
|
|
4154
4406
|
printError("\u672A\u8BBE\u7F6E API \u5BC6\u94A5\u3002\u8BF7\u901A\u8FC7\u4EE5\u4E0B\u65B9\u5F0F\u4E4B\u4E00\u8BBE\u7F6E\uFF1A");
|