deepseeker-code 1.0.54 → 1.0.55
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/README.md +20 -0
- package/dist/cli.mjs +1493 -581
- package/package.json +1 -1
package/dist/cli.mjs
CHANGED
|
@@ -171,6 +171,7 @@ ${dim} \u8FD0\u884C npm i -g deepseeker-code@latest \u66F4\u65B0${reset}
|
|
|
171
171
|
cmdExit: "\u9000\u51FA CLI",
|
|
172
172
|
cmdSessions: "\u9009\u62E9\u5E76\u8F7D\u5165\u5386\u53F2\u4F1A\u8BDD\uFF08\u7EED\u63A5\u5BF9\u8BDD\uFF09",
|
|
173
173
|
cmdUsage: "\u67E5\u770B\u672C\u4F1A\u8BDD token \u7528\u91CF\uFF08\u4E3B/\u5B50 agent\u3001\u7F13\u5B58\u547D\u4E2D\uFF09",
|
|
174
|
+
cmdBudget: "\u9884\u7B97\u5236\u8FD0\u884C\uFF1A/budget 0.5 \u8BBE\u7F6E\u6BCF run \u4E0A\u9650 \xB7 /budget off \u5173\u95ED \xB7 /budget \u67E5\u770B",
|
|
174
175
|
cmdContext: "\u67E5\u770B\u4E0A\u4E0B\u6587\u7A97\u53E3\u6CBB\u7406\uFF08\u9608\u503C\u3001\u586B\u5145\u7387\u3001\u5DF2\u5F52\u6863\uFF09",
|
|
175
176
|
cmdPermissions: "\u67E5\u770B\u5DF2\u52A0\u8F7D\u7684\u6743\u9650\u89C4\u5219\uFF08allow/ask/deny\uFF09",
|
|
176
177
|
cmdMcp: "\u67E5\u770B\u5DF2\u8FDE\u63A5\u7684 MCP server \u4E0E\u5DE5\u5177\u6570",
|
|
@@ -325,6 +326,7 @@ ${dim} Run npm i -g deepseeker-code@latest to update${reset}
|
|
|
325
326
|
cmdExit: "Quit the CLI",
|
|
326
327
|
cmdSessions: "Pick a past session to resume",
|
|
327
328
|
cmdUsage: "Show this session's token usage (main/sub agent, cache hit)",
|
|
329
|
+
cmdBudget: "Budget mode: /budget 0.5 set per-run cap \xB7 /budget off disable \xB7 /budget view",
|
|
328
330
|
cmdContext: "Show context window governance (threshold, fill, archived)",
|
|
329
331
|
cmdPermissions: "Show loaded permission rules (allow/ask/deny)",
|
|
330
332
|
cmdMcp: "Show connected MCP servers and tool counts",
|
|
@@ -409,7 +411,7 @@ DeepSeeker-Code will read, edit, and execute files here.`,
|
|
|
409
411
|
S = new Proxy({}, {
|
|
410
412
|
get: (_t, k) => typeof k === "string" ? STRINGS[locale][k] : void 0
|
|
411
413
|
});
|
|
412
|
-
LOCAL_COMMAND_NAMES = ["help", "status", "plan", "auto", "model", "switch", "thinking", "lang", "output-style", "new", "sessions", "fork", "usage", "context", "permissions", "mcp", "hooks", "trust", "debug", "clear", "exit"];
|
|
414
|
+
LOCAL_COMMAND_NAMES = ["help", "status", "plan", "auto", "model", "switch", "thinking", "lang", "output-style", "new", "sessions", "fork", "usage", "budget", "context", "permissions", "mcp", "hooks", "trust", "debug", "clear", "exit"];
|
|
413
415
|
}
|
|
414
416
|
});
|
|
415
417
|
|
|
@@ -792,6 +794,279 @@ var init_trust = __esm({
|
|
|
792
794
|
}
|
|
793
795
|
});
|
|
794
796
|
|
|
797
|
+
// ../core/src/batch/ticket.ts
|
|
798
|
+
import fs4 from "fs/promises";
|
|
799
|
+
var generateBatchId, parseToolsValue, parsePositiveNumber, parseBatchTicket, readBatchTicket;
|
|
800
|
+
var init_ticket = __esm({
|
|
801
|
+
"../core/src/batch/ticket.ts"() {
|
|
802
|
+
"use strict";
|
|
803
|
+
generateBatchId = (now = /* @__PURE__ */ new Date()) => {
|
|
804
|
+
const p = (n, w = 2) => String(n).padStart(w, "0");
|
|
805
|
+
const rand = Math.random().toString(36).slice(2, 6);
|
|
806
|
+
return `${now.getFullYear()}${p(now.getMonth() + 1)}${p(now.getDate())}-${p(now.getHours())}${p(now.getMinutes())}${p(now.getSeconds())}-${rand}`;
|
|
807
|
+
};
|
|
808
|
+
parseToolsValue = (raw) => raw.replace(/^\[|\]$/g, "").split(",").map((s) => s.trim().replace(/^["']|["']$/g, "")).filter(Boolean);
|
|
809
|
+
parsePositiveNumber = (raw) => {
|
|
810
|
+
const n = Number(raw.trim());
|
|
811
|
+
return Number.isFinite(n) && n > 0 ? n : null;
|
|
812
|
+
};
|
|
813
|
+
parseBatchTicket = (source) => {
|
|
814
|
+
const m = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?([\s\S]*)$/.exec(source);
|
|
815
|
+
if (!m) return { ok: false, error: "\u7F3A\u5C11 frontmatter\uFF08--- \u5305\u88F9\u7684\u5934\u90E8\u5757\uFF09\u3002\u5DE5\u5355\u683C\u5F0F\u89C1 batch add \u5E2E\u52A9\u3002" };
|
|
816
|
+
const [, fmRaw, bodyRaw] = m;
|
|
817
|
+
const fm = {};
|
|
818
|
+
for (const line of fmRaw.split(/\r?\n/)) {
|
|
819
|
+
const kv = /^([A-Za-z][\w-]*)\s*:\s*(.*)$/.exec(line.trim());
|
|
820
|
+
if (!kv) continue;
|
|
821
|
+
fm[kv[1].toLowerCase()] = kv[2].trim();
|
|
822
|
+
}
|
|
823
|
+
const accept = (fm["accept"] ?? "").trim();
|
|
824
|
+
if (!accept) return { ok: false, error: "frontmatter \u7F3A accept\uFF08\u9A8C\u6536\u547D\u4EE4\uFF09\u3002\u6302\u673A\u4EFB\u52A1\u5FC5\u987B\u5E26\u53EF\u6267\u884C\u9A8C\u6536\uFF0C\u7F3A\u9A8C\u6536\u62D2\u7EDD\u5165\u961F\u3002" };
|
|
825
|
+
let budgetYuan;
|
|
826
|
+
if (fm["budget-yuan"] !== void 0) {
|
|
827
|
+
const n = parsePositiveNumber(fm["budget-yuan"]);
|
|
828
|
+
if (n === null) return { ok: false, error: `budget-yuan \u975E\u6CD5\uFF08"${fm["budget-yuan"]}"\uFF09\uFF1A\u987B\u4E3A\u6B63\u6570\uFF08\u5143\uFF09\u3002` };
|
|
829
|
+
budgetYuan = n;
|
|
830
|
+
}
|
|
831
|
+
let timeoutMin;
|
|
832
|
+
if (fm["timeout-min"] !== void 0) {
|
|
833
|
+
const n = parsePositiveNumber(fm["timeout-min"]);
|
|
834
|
+
if (n === null) return { ok: false, error: `timeout-min \u975E\u6CD5\uFF08"${fm["timeout-min"]}"\uFF09\uFF1A\u987B\u4E3A\u6B63\u6574\u6570\uFF08\u5206\u949F\uFF09\u3002` };
|
|
835
|
+
timeoutMin = n;
|
|
836
|
+
}
|
|
837
|
+
const tools = fm["tools"] !== void 0 ? parseToolsValue(fm["tools"]) : void 0;
|
|
838
|
+
if (tools && tools.length === 0) return { ok: false, error: "tools \u4E3A\u7A7A\uFF1A\u8981\u4E48\u5220\u6389\u8BE5\u884C\uFF08\u7528\u7F3A\u7701\u7981\u7528\u6E05\u5355\uFF09\uFF0C\u8981\u4E48\u5217\u5DE5\u5177\u540D\uFF08\u9017\u53F7\u5206\u9694\uFF09\u3002" };
|
|
839
|
+
const body = bodyRaw.trim();
|
|
840
|
+
if (!body) return { ok: false, error: "\u4EFB\u52A1\u6B63\u6587\u4E3A\u7A7A\uFF1Afrontmatter \u4E4B\u540E\u5E94\u5199\u4EFB\u52A1\u63CF\u8FF0\u3002" };
|
|
841
|
+
const title = (fm["title"] ?? "").trim() || body.split(/\r?\n/).find((l) => l.trim())?.slice(0, 40) || "(\u672A\u547D\u540D\u4EFB\u52A1)";
|
|
842
|
+
return { ok: true, ticket: { title, accept, budgetYuan, timeoutMin, tools: tools && tools.length > 0 ? tools : void 0, body } };
|
|
843
|
+
};
|
|
844
|
+
readBatchTicket = async (filePath) => {
|
|
845
|
+
let source;
|
|
846
|
+
try {
|
|
847
|
+
source = await fs4.readFile(filePath, "utf-8");
|
|
848
|
+
} catch (e) {
|
|
849
|
+
return { ok: false, error: `\u8BFB\u5DE5\u5355\u5931\u8D25\uFF1A${e?.message ?? e}` };
|
|
850
|
+
}
|
|
851
|
+
return parseBatchTicket(source);
|
|
852
|
+
};
|
|
853
|
+
}
|
|
854
|
+
});
|
|
855
|
+
|
|
856
|
+
// ../core/src/batch/queue.ts
|
|
857
|
+
import fs5 from "fs/promises";
|
|
858
|
+
import path6 from "path";
|
|
859
|
+
var batchQueueRoot, stateDir, lockPath, listState, snapshotQueue, reportPath, enqueueTicketFile, takeNextTicket, requeueStaleRunning, finishTicket, cleanDone, pidAlive, acquireRunLock, releaseRunLock;
|
|
860
|
+
var init_queue = __esm({
|
|
861
|
+
"../core/src/batch/queue.ts"() {
|
|
862
|
+
"use strict";
|
|
863
|
+
init_ticket();
|
|
864
|
+
batchQueueRoot = () => process.env.DEEPSEEKER_CODE_BATCH_DIR || path6.join(process.cwd(), ".deepseeker-code", "batch");
|
|
865
|
+
stateDir = (s) => path6.join(batchQueueRoot(), s);
|
|
866
|
+
lockPath = () => path6.join(batchQueueRoot(), ".lock");
|
|
867
|
+
listState = async (s) => {
|
|
868
|
+
try {
|
|
869
|
+
return (await fs5.readdir(stateDir(s))).filter((f) => f.endsWith(".md") && !f.endsWith(".report.md")).sort();
|
|
870
|
+
} catch {
|
|
871
|
+
return [];
|
|
872
|
+
}
|
|
873
|
+
};
|
|
874
|
+
snapshotQueue = async () => ({
|
|
875
|
+
pending: await listState("pending"),
|
|
876
|
+
running: await listState("running"),
|
|
877
|
+
done: (await listState("done")).map((f) => f.replace(/\.md$/, ""))
|
|
878
|
+
});
|
|
879
|
+
reportPath = (id) => path6.join(stateDir("done"), `${id}.report.md`);
|
|
880
|
+
enqueueTicketFile = async (srcPath) => {
|
|
881
|
+
const parsed = await readBatchTicket(srcPath);
|
|
882
|
+
if (!parsed.ok) return parsed;
|
|
883
|
+
const source = await fs5.readFile(srcPath, "utf-8");
|
|
884
|
+
const id = generateBatchId();
|
|
885
|
+
await fs5.mkdir(stateDir("pending"), { recursive: true });
|
|
886
|
+
await fs5.writeFile(path6.join(stateDir("pending"), `${id}.md`), source, "utf-8");
|
|
887
|
+
return { ok: true, id, title: parsed.ticket.title };
|
|
888
|
+
};
|
|
889
|
+
takeNextTicket = async () => {
|
|
890
|
+
await requeueStaleRunning();
|
|
891
|
+
const pending = await listState("pending");
|
|
892
|
+
if (pending.length === 0) return null;
|
|
893
|
+
const file = pending[0];
|
|
894
|
+
const from = path6.join(stateDir("pending"), file);
|
|
895
|
+
const to = path6.join(stateDir("running"), file);
|
|
896
|
+
await fs5.mkdir(stateDir("running"), { recursive: true });
|
|
897
|
+
await fs5.rename(from, to);
|
|
898
|
+
return { id: file.replace(/\.md$/, ""), path: to };
|
|
899
|
+
};
|
|
900
|
+
requeueStaleRunning = async () => {
|
|
901
|
+
const stale = await listState("running");
|
|
902
|
+
if (stale.length === 0) return 0;
|
|
903
|
+
await fs5.mkdir(stateDir("pending"), { recursive: true });
|
|
904
|
+
for (const f of stale) {
|
|
905
|
+
await fs5.rename(path6.join(stateDir("running"), f), path6.join(stateDir("pending"), f)).catch(() => {
|
|
906
|
+
});
|
|
907
|
+
}
|
|
908
|
+
return stale.length;
|
|
909
|
+
};
|
|
910
|
+
finishTicket = async (id, reportMd) => {
|
|
911
|
+
try {
|
|
912
|
+
await fs5.mkdir(stateDir("done"), { recursive: true });
|
|
913
|
+
await fs5.writeFile(reportPath(id), reportMd, "utf-8");
|
|
914
|
+
await fs5.rename(path6.join(stateDir("running"), `${id}.md`), path6.join(stateDir("done"), `${id}.md`)).catch(() => {
|
|
915
|
+
});
|
|
916
|
+
} catch (e) {
|
|
917
|
+
console.warn(`\u26A0\uFE0F [batch] \u62A5\u544A\u843D\u76D8\u5931\u8D25\uFF08\u4EFB\u52A1\u7ED3\u679C\u4EE5\u63A7\u5236\u53F0\u8F93\u51FA\u4E3A\u51C6\uFF09: ${e?.message ?? e}`);
|
|
918
|
+
}
|
|
919
|
+
};
|
|
920
|
+
cleanDone = async () => {
|
|
921
|
+
const files = await listState("done");
|
|
922
|
+
for (const f of await fs5.readdir(stateDir("done")).catch(() => [])) {
|
|
923
|
+
if (f.endsWith(".md") || f.endsWith(".report.md")) {
|
|
924
|
+
await fs5.rm(path6.join(stateDir("done"), f), { force: true }).catch(() => {
|
|
925
|
+
});
|
|
926
|
+
}
|
|
927
|
+
}
|
|
928
|
+
return files.length;
|
|
929
|
+
};
|
|
930
|
+
pidAlive = (pid) => {
|
|
931
|
+
try {
|
|
932
|
+
process.kill(pid, 0);
|
|
933
|
+
return true;
|
|
934
|
+
} catch (e) {
|
|
935
|
+
return e?.code === "EPERM";
|
|
936
|
+
}
|
|
937
|
+
};
|
|
938
|
+
acquireRunLock = async () => {
|
|
939
|
+
await fs5.mkdir(batchQueueRoot(), { recursive: true });
|
|
940
|
+
const payload = `${process.pid} ${(/* @__PURE__ */ new Date()).toISOString()}`;
|
|
941
|
+
try {
|
|
942
|
+
await fs5.writeFile(lockPath(), payload, { flag: "wx" });
|
|
943
|
+
return { ok: true };
|
|
944
|
+
} catch (e) {
|
|
945
|
+
if (e?.code !== "EEXIST") return { ok: false, error: `\u9501\u521B\u5EFA\u5931\u8D25\uFF1A${e?.message ?? e}` };
|
|
946
|
+
const raw = await fs5.readFile(lockPath(), "utf-8").catch(() => "");
|
|
947
|
+
const ownerPid = parseInt(raw.split(" ")[0], 10);
|
|
948
|
+
if (Number.isFinite(ownerPid) && pidAlive(ownerPid)) {
|
|
949
|
+
return { ok: false, error: `\u5DF2\u6709 batch runner \u5728\u8FD0\u884C\uFF08pid ${ownerPid}\uFF09\u3002\u6302\u673A\u6A21\u5F0F\u4E32\u884C\uFF0C\u52FF\u5E76\u53D1\u8DD1\u4E24\u4E2A runner\u3002` };
|
|
950
|
+
}
|
|
951
|
+
await fs5.writeFile(lockPath(), payload).catch(() => {
|
|
952
|
+
});
|
|
953
|
+
return { ok: true };
|
|
954
|
+
}
|
|
955
|
+
};
|
|
956
|
+
releaseRunLock = async () => {
|
|
957
|
+
const raw = await fs5.readFile(lockPath(), "utf-8").catch(() => "");
|
|
958
|
+
if (parseInt(raw.split(" ")[0], 10) === process.pid) {
|
|
959
|
+
await fs5.rm(lockPath(), { force: true }).catch(() => {
|
|
960
|
+
});
|
|
961
|
+
}
|
|
962
|
+
};
|
|
963
|
+
}
|
|
964
|
+
});
|
|
965
|
+
|
|
966
|
+
// src/batchAdmin.ts
|
|
967
|
+
var batchAdmin_exports = {};
|
|
968
|
+
__export(batchAdmin_exports, {
|
|
969
|
+
handleBatchAdmin: () => handleBatchAdmin,
|
|
970
|
+
parseBatchArgv: () => parseBatchArgv
|
|
971
|
+
});
|
|
972
|
+
import fs6 from "fs/promises";
|
|
973
|
+
import path7 from "path";
|
|
974
|
+
var emit, parseBatchArgv, USAGE, handleBatchAdmin, describeDone;
|
|
975
|
+
var init_batchAdmin = __esm({
|
|
976
|
+
"src/batchAdmin.ts"() {
|
|
977
|
+
"use strict";
|
|
978
|
+
init_queue();
|
|
979
|
+
emit = (s = "") => {
|
|
980
|
+
process.stdout.write(s + "\n");
|
|
981
|
+
};
|
|
982
|
+
parseBatchArgv = (argv) => {
|
|
983
|
+
if (argv[0] !== "batch") return null;
|
|
984
|
+
const sub = argv[1];
|
|
985
|
+
if (sub === "add") return { sub: "add", files: argv.slice(2) };
|
|
986
|
+
if (sub === "run") {
|
|
987
|
+
const wi = argv.indexOf("--wait-window");
|
|
988
|
+
const waitWindow = wi !== -1 ? argv[wi + 1] : void 0;
|
|
989
|
+
return { sub: "run", waitWindow };
|
|
990
|
+
}
|
|
991
|
+
if (sub === "list") return { sub: "list" };
|
|
992
|
+
if (sub === "clean") return { sub: "clean" };
|
|
993
|
+
return { sub: "help" };
|
|
994
|
+
};
|
|
995
|
+
USAGE = `deepseeker-code batch \u2014\u2014 \u6302\u673A\u6279\u5904\u7406\uFF08\u6210\u672C\u4FE1\u4EFB\u94FE\u7B2C\u56DB\u73AF\uFF09
|
|
996
|
+
|
|
997
|
+
\u7528\u6CD5\uFF1Adeepseeker-code batch <\u5B50\u547D\u4EE4>
|
|
998
|
+
add <\u5DE5\u5355.md> [...] \u6295\u9012\u4EFB\u52A1\uFF08\u53EF\u4E00\u6B21\u591A\u4E2A\u6587\u4EF6\uFF09
|
|
999
|
+
list \u67E5\u770B pending / running / done \u4E09\u6001\u961F\u5217
|
|
1000
|
+
run [--wait-window HH:MM-HH:MM] \u6267\u884C\u961F\u5217\uFF08\u4E32\u884C\uFF0C\u9010\u4EFB\u52A1\u51FA\u62A5\u544A\uFF1B--wait-window \u5230\u70B9\u518D\u5F00\u8DD1\uFF09
|
|
1001
|
+
clean \u6E05\u7A7A done/\uFF08\u5DF2\u8BFB\u8FC7\u7684\u62A5\u544A\u4E0E\u5DE5\u5355\u5B58\u6863\uFF09
|
|
1002
|
+
|
|
1003
|
+
\u5DE5\u5355\u683C\u5F0F\uFF08Markdown\uFF0Cfrontmatter \u7684 accept \u5FC5\u586B\u2014\u2014\u7F3A\u9A8C\u6536\u62D2\u7EDD\u5165\u961F\uFF09\uFF1A
|
|
1004
|
+
---
|
|
1005
|
+
title: \u4FEE\u590D\u65E5\u671F\u89E3\u6790 bug
|
|
1006
|
+
accept: npm test
|
|
1007
|
+
budget-yuan: 0.5 # \u53EF\u9009\uFF1A\u672C\u4EFB\u52A1\u82B1\u8D39\u4E0A\u9650\uFF08\u5143\uFF09
|
|
1008
|
+
timeout-min: 30 # \u53EF\u9009\uFF1Aagent \u9636\u6BB5\u8D85\u65F6\uFF08\u5206\u949F\uFF0C\u7F3A\u7701 30\uFF09
|
|
1009
|
+
tools: run_command # \u53EF\u9009\uFF1A\u663E\u5F0F\u89E3\u9501\u9AD8\u5371\u5DE5\u5177\uFF08\u7F3A\u7701\u7981 run_command/delete_path\uFF09
|
|
1010
|
+
---
|
|
1011
|
+
\u4EFB\u52A1\u63CF\u8FF0\u6B63\u6587\uFF08Markdown\uFF09\u2026
|
|
1012
|
+
|
|
1013
|
+
\u4EA7\u7269\uFF1A<\u9879\u76EE>/.deepseeker-code/batch/done/<id>.report.md\uFF08\u72B6\u6001/\u7ED3\u7B97\u5355/\u9A8C\u6536\u8F93\u51FA/diff \u6458\u8981\uFF09\uFF1B
|
|
1014
|
+
\u6539\u52A8\u6536\u5272\u5728\u72EC\u7ACB git worktree\uFF08\u4E34\u65F6\u5206\u652F\uFF09\u4E0A\uFF0C\u4FDD\u7559\u5F85\u4EBA\u5DE5 merge \u6216\u4E22\u5F03\u3002`;
|
|
1015
|
+
handleBatchAdmin = async (b) => {
|
|
1016
|
+
if (b.sub === "help") {
|
|
1017
|
+
emit(USAGE);
|
|
1018
|
+
return;
|
|
1019
|
+
}
|
|
1020
|
+
if (b.sub === "add") {
|
|
1021
|
+
if (b.files.length === 0) {
|
|
1022
|
+
emit("\u7528\u6CD5\uFF1Adeepseeker-code batch add <\u5DE5\u5355.md> [...]\uFF08\u7F3A\u9A8C\u6536\u547D\u4EE4\u7684\u5DE5\u5355\u4F1A\u88AB\u62D2\u7EDD\uFF09\n\u8BE6\u60C5\uFF1Adeepseeker-code batch help");
|
|
1023
|
+
return;
|
|
1024
|
+
}
|
|
1025
|
+
for (const f of b.files) {
|
|
1026
|
+
const abs = path7.resolve(f);
|
|
1027
|
+
const r = await enqueueTicketFile(abs).catch((e) => ({ ok: false, error: `\u8BFB\u6587\u4EF6\u5931\u8D25\uFF1A${e?.message ?? e}` }));
|
|
1028
|
+
if (r.ok) emit(`\u{1F4E5} \u5DF2\u5165\u961F [${r.id}] ${r.title}`);
|
|
1029
|
+
else emit(`\u{1F6AB} \u62D2\u7EDD ${path7.basename(abs)}\uFF1A${r.error}`);
|
|
1030
|
+
}
|
|
1031
|
+
emit("\n\u8DD1\u6279\uFF1Adeepseeker-code batch run");
|
|
1032
|
+
return;
|
|
1033
|
+
}
|
|
1034
|
+
if (b.sub === "list") {
|
|
1035
|
+
const q = await snapshotQueue();
|
|
1036
|
+
if (q.pending.length + q.running.length + q.done.length === 0) {
|
|
1037
|
+
emit("\u961F\u5217\u7A7A\u3002\u6295\u9012\uFF1Adeepseeker-code batch add <\u5DE5\u5355.md>\uFF08\u683C\u5F0F\u89C1 batch help\uFF09");
|
|
1038
|
+
return;
|
|
1039
|
+
}
|
|
1040
|
+
if (q.running.length > 0) emit(`\u25B6 \u8FD0\u884C\u4E2D\uFF1A`);
|
|
1041
|
+
for (const f of q.running) emit(` ${f.replace(/\.md$/, "")}`);
|
|
1042
|
+
if (q.pending.length > 0) emit(`\u23F3 \u5F85\u8DD1 ${q.pending.length}\uFF1A`);
|
|
1043
|
+
for (const f of q.pending) emit(` ${f.replace(/\.md$/, "")}`);
|
|
1044
|
+
if (q.done.length > 0) emit(`\u2714 \u5DF2\u5B8C\u6210 ${q.done.length}\uFF1A`);
|
|
1045
|
+
for (const id of q.done) emit(` ${id} ${await describeDone(id)}`);
|
|
1046
|
+
return;
|
|
1047
|
+
}
|
|
1048
|
+
if (b.sub === "clean") {
|
|
1049
|
+
const n = await cleanDone();
|
|
1050
|
+
emit(`\u{1F9F9} \u5DF2\u6E05\u7A7A done/\uFF08${n} \u4E2A\u4EFB\u52A1\u5B58\u6863\uFF09\u3002pending/running \u4E0D\u53D7\u5F71\u54CD\u3002`);
|
|
1051
|
+
return;
|
|
1052
|
+
}
|
|
1053
|
+
};
|
|
1054
|
+
describeDone = async (id) => {
|
|
1055
|
+
let text;
|
|
1056
|
+
try {
|
|
1057
|
+
text = await fs6.readFile(reportPath(id), "utf-8");
|
|
1058
|
+
} catch {
|
|
1059
|
+
return "\uFF08\u62A5\u544A\u7F3A\u5931\uFF09";
|
|
1060
|
+
}
|
|
1061
|
+
const fm = (key) => {
|
|
1062
|
+
const m = new RegExp(`^${key}:\\s*(.+)$`, "m").exec(text);
|
|
1063
|
+
return m ? m[1].trim() : "";
|
|
1064
|
+
};
|
|
1065
|
+
return `[${fm("status") || "?"}] ${fm("title")}`;
|
|
1066
|
+
};
|
|
1067
|
+
}
|
|
1068
|
+
});
|
|
1069
|
+
|
|
795
1070
|
// ../core/src/tool/type.ts
|
|
796
1071
|
var MAX_AGENT_DEPTH, ToolSafetyLevel, ToolExecutionResultStatus, asToolFailure, toolFailure;
|
|
797
1072
|
var init_type = __esm({
|
|
@@ -1090,15 +1365,15 @@ var init_createModel = __esm({
|
|
|
1090
1365
|
});
|
|
1091
1366
|
|
|
1092
1367
|
// ../core/src/llm/visionCapability.ts
|
|
1093
|
-
import
|
|
1094
|
-
import
|
|
1368
|
+
import path8 from "path";
|
|
1369
|
+
import fs7 from "fs/promises";
|
|
1095
1370
|
var CAP_FILE, MAX_ENTRIES, mem, loadPromise, ensureVisionCacheLoaded, peekVisionCapability, writeChain, persistLatest, learnVisionCapability;
|
|
1096
1371
|
var init_visionCapability = __esm({
|
|
1097
1372
|
"../core/src/llm/visionCapability.ts"() {
|
|
1098
1373
|
"use strict";
|
|
1099
1374
|
init_config();
|
|
1100
1375
|
init_common();
|
|
1101
|
-
CAP_FILE =
|
|
1376
|
+
CAP_FILE = path8.join(appConfig.dataDir, "model-capabilities.json");
|
|
1102
1377
|
MAX_ENTRIES = 100;
|
|
1103
1378
|
mem = {};
|
|
1104
1379
|
loadPromise = (async () => {
|
|
@@ -1115,7 +1390,7 @@ var init_visionCapability = __esm({
|
|
|
1115
1390
|
persistLatest = () => {
|
|
1116
1391
|
writeChain = writeChain.then(async () => {
|
|
1117
1392
|
try {
|
|
1118
|
-
await
|
|
1393
|
+
await fs7.mkdir(appConfig.dataDir, { recursive: true });
|
|
1119
1394
|
await atomicWriteJSON(CAP_FILE, mem);
|
|
1120
1395
|
} catch {
|
|
1121
1396
|
}
|
|
@@ -1456,7 +1731,7 @@ var init_contextCore = __esm({
|
|
|
1456
1731
|
return messagesArr.reduce((total, m) => total + messageTokens(m), 0);
|
|
1457
1732
|
};
|
|
1458
1733
|
cleanMsg = (m) => {
|
|
1459
|
-
const { id, sessionId, ts, ...rest } = m;
|
|
1734
|
+
const { id, sessionId, ts: ts2, ...rest } = m;
|
|
1460
1735
|
return rest;
|
|
1461
1736
|
};
|
|
1462
1737
|
groupUnits = (messagesArr) => {
|
|
@@ -1514,8 +1789,8 @@ __export(store_exports, {
|
|
|
1514
1789
|
updateCalibration: () => updateCalibration,
|
|
1515
1790
|
writeStore: () => writeStore
|
|
1516
1791
|
});
|
|
1517
|
-
import
|
|
1518
|
-
import
|
|
1792
|
+
import fs8 from "fs/promises";
|
|
1793
|
+
import path9 from "path";
|
|
1519
1794
|
async function getRollingState(sessionId) {
|
|
1520
1795
|
const store = await readStore(sessionId);
|
|
1521
1796
|
if (!store) {
|
|
@@ -1563,22 +1838,22 @@ var init_store = __esm({
|
|
|
1563
1838
|
getSessionsDirPath = (mainSessionId) => {
|
|
1564
1839
|
assertSafeSessionId(mainSessionId);
|
|
1565
1840
|
const fileName = getFileName(mainSessionId);
|
|
1566
|
-
return
|
|
1841
|
+
return path9.join(appConfig.dataDir, "sessions", appConfig.userWorkspaceDir, fileName);
|
|
1567
1842
|
};
|
|
1568
|
-
getWorkspaceSessionsDir = () =>
|
|
1843
|
+
getWorkspaceSessionsDir = () => path9.join(appConfig.dataDir, "sessions", appConfig.userWorkspaceDir);
|
|
1569
1844
|
getStatePath = (sessionId) => {
|
|
1570
1845
|
assertSafeSessionId(sessionId);
|
|
1571
|
-
return
|
|
1846
|
+
return path9.join(getSessionsDirPath(sessionId), `${sessionId}.state.json`);
|
|
1572
1847
|
};
|
|
1573
1848
|
getTranscriptPath = (sessionId) => {
|
|
1574
1849
|
assertSafeSessionId(sessionId);
|
|
1575
|
-
return
|
|
1850
|
+
return path9.join(getSessionsDirPath(sessionId), `${sessionId}.jsonl`);
|
|
1576
1851
|
};
|
|
1577
1852
|
ensuredSessionDirs = /* @__PURE__ */ new Set();
|
|
1578
1853
|
ensureSessionsDir = async (sessionId) => {
|
|
1579
1854
|
const dir = getSessionsDirPath(sessionId);
|
|
1580
1855
|
if (ensuredSessionDirs.has(dir)) return;
|
|
1581
|
-
await
|
|
1856
|
+
await fs8.mkdir(dir, { recursive: true });
|
|
1582
1857
|
await migrateLegacyFiles(sessionId).catch(() => {
|
|
1583
1858
|
});
|
|
1584
1859
|
ensuredSessionDirs.add(dir);
|
|
@@ -1586,23 +1861,23 @@ var init_store = __esm({
|
|
|
1586
1861
|
migrateLegacyFiles = async (sessionId) => {
|
|
1587
1862
|
assertSafeSessionId(sessionId);
|
|
1588
1863
|
const dir = getSessionsDirPath(sessionId);
|
|
1589
|
-
const legacy =
|
|
1864
|
+
const legacy = path9.join(dir, `${sessionId}.json`);
|
|
1590
1865
|
const transcriptPath = getTranscriptPath(sessionId);
|
|
1591
1866
|
const statePath = getStatePath(sessionId);
|
|
1592
1867
|
let legacyText;
|
|
1593
1868
|
try {
|
|
1594
|
-
legacyText = await
|
|
1869
|
+
legacyText = await fs8.readFile(legacy, "utf-8");
|
|
1595
1870
|
} catch {
|
|
1596
1871
|
return;
|
|
1597
1872
|
}
|
|
1598
1873
|
try {
|
|
1599
|
-
await
|
|
1874
|
+
await fs8.access(transcriptPath);
|
|
1600
1875
|
return;
|
|
1601
1876
|
} catch {
|
|
1602
1877
|
}
|
|
1603
1878
|
const raw = legacyText.trim();
|
|
1604
1879
|
if (raw.length === 0) {
|
|
1605
|
-
await
|
|
1880
|
+
await fs8.rename(legacy, transcriptPath);
|
|
1606
1881
|
return;
|
|
1607
1882
|
}
|
|
1608
1883
|
const lines = raw.split("\n");
|
|
@@ -1615,13 +1890,13 @@ var init_store = __esm({
|
|
|
1615
1890
|
}
|
|
1616
1891
|
});
|
|
1617
1892
|
if (isJsonl) {
|
|
1618
|
-
await
|
|
1893
|
+
await fs8.rename(legacy, transcriptPath);
|
|
1619
1894
|
return;
|
|
1620
1895
|
}
|
|
1621
1896
|
try {
|
|
1622
1897
|
const v = JSON.parse(raw);
|
|
1623
1898
|
if (typeof v === "object" && v !== null) {
|
|
1624
|
-
await
|
|
1899
|
+
await fs8.rename(legacy, statePath);
|
|
1625
1900
|
return;
|
|
1626
1901
|
}
|
|
1627
1902
|
} catch {
|
|
@@ -1632,8 +1907,8 @@ var init_store = __esm({
|
|
|
1632
1907
|
await ensureSessionsDir(sessionId);
|
|
1633
1908
|
const finalPath = getStatePath(sessionId);
|
|
1634
1909
|
const tmpPath = `${finalPath}.${Date.now()}.tmp`;
|
|
1635
|
-
await
|
|
1636
|
-
await
|
|
1910
|
+
await fs8.writeFile(tmpPath, JSON.stringify(store, null, 2), "utf-8");
|
|
1911
|
+
await fs8.rename(tmpPath, finalPath);
|
|
1637
1912
|
};
|
|
1638
1913
|
storeLocks = /* @__PURE__ */ new Map();
|
|
1639
1914
|
withStoreLock = (sessionId, fn) => {
|
|
@@ -1673,7 +1948,7 @@ var init_store = __esm({
|
|
|
1673
1948
|
await ensureSessionsDir(sessionId);
|
|
1674
1949
|
const p = getStatePath(sessionId);
|
|
1675
1950
|
try {
|
|
1676
|
-
const raw = (await
|
|
1951
|
+
const raw = (await fs8.readFile(p, "utf-8")).trim();
|
|
1677
1952
|
if (raw.length === 0) {
|
|
1678
1953
|
return {};
|
|
1679
1954
|
}
|
|
@@ -1702,7 +1977,7 @@ var init_store = __esm({
|
|
|
1702
1977
|
const root = getWorkspaceSessionsDir();
|
|
1703
1978
|
let entries;
|
|
1704
1979
|
try {
|
|
1705
|
-
entries = await
|
|
1980
|
+
entries = await fs8.readdir(root, { withFileTypes: true });
|
|
1706
1981
|
} catch {
|
|
1707
1982
|
return [];
|
|
1708
1983
|
}
|
|
@@ -1711,12 +1986,12 @@ var init_store = __esm({
|
|
|
1711
1986
|
if (!entry.isDirectory()) continue;
|
|
1712
1987
|
const sessionId = entry.name;
|
|
1713
1988
|
if (!isSafeSessionId(sessionId)) continue;
|
|
1714
|
-
const dirPath =
|
|
1989
|
+
const dirPath = path9.join(root, sessionId);
|
|
1715
1990
|
const state = await readJSONFile(getStatePath(sessionId));
|
|
1716
1991
|
let messageCount = 0;
|
|
1717
1992
|
let preview = "";
|
|
1718
1993
|
try {
|
|
1719
|
-
const raw = await
|
|
1994
|
+
const raw = await fs8.readFile(getTranscriptPath(sessionId), "utf-8");
|
|
1720
1995
|
for (const s of raw.split("\n")) {
|
|
1721
1996
|
const line = s.trim();
|
|
1722
1997
|
if (!line) continue;
|
|
@@ -1743,7 +2018,7 @@ var init_store = __esm({
|
|
|
1743
2018
|
let updatedAt = state?.updatedAt;
|
|
1744
2019
|
if (!updatedAt) {
|
|
1745
2020
|
try {
|
|
1746
|
-
updatedAt = (await
|
|
2021
|
+
updatedAt = (await fs8.stat(dirPath)).mtime.toISOString();
|
|
1747
2022
|
} catch {
|
|
1748
2023
|
}
|
|
1749
2024
|
}
|
|
@@ -1763,7 +2038,7 @@ var init_store = __esm({
|
|
|
1763
2038
|
const root = getWorkspaceSessionsDir();
|
|
1764
2039
|
let entries;
|
|
1765
2040
|
try {
|
|
1766
|
-
entries = await
|
|
2041
|
+
entries = await fs8.readdir(root, { withFileTypes: true });
|
|
1767
2042
|
} catch {
|
|
1768
2043
|
return null;
|
|
1769
2044
|
}
|
|
@@ -1773,11 +2048,12 @@ var init_store = __esm({
|
|
|
1773
2048
|
if (!entry.isDirectory()) continue;
|
|
1774
2049
|
const sessionId = entry.name;
|
|
1775
2050
|
if (!isSafeSessionId(sessionId)) continue;
|
|
2051
|
+
if (sessionId.startsWith("batch-")) continue;
|
|
1776
2052
|
const state = await readJSONFile(getStatePath(sessionId));
|
|
1777
2053
|
let updatedAt = state?.updatedAt;
|
|
1778
2054
|
if (!updatedAt) {
|
|
1779
2055
|
try {
|
|
1780
|
-
updatedAt = (await
|
|
2056
|
+
updatedAt = (await fs8.stat(path9.join(root, sessionId))).mtime.toISOString();
|
|
1781
2057
|
} catch {
|
|
1782
2058
|
}
|
|
1783
2059
|
}
|
|
@@ -1802,14 +2078,14 @@ var init_store = __esm({
|
|
|
1802
2078
|
deleteSession = async (sessionId) => {
|
|
1803
2079
|
assertSafeSessionId(sessionId);
|
|
1804
2080
|
const dir = getSessionsDirPath(sessionId);
|
|
1805
|
-
await
|
|
2081
|
+
await fs8.rm(dir, { recursive: true, force: true });
|
|
1806
2082
|
ensuredSessionDirs.delete(dir);
|
|
1807
2083
|
};
|
|
1808
2084
|
}
|
|
1809
2085
|
});
|
|
1810
2086
|
|
|
1811
2087
|
// ../core/src/session/transcript.ts
|
|
1812
|
-
import
|
|
2088
|
+
import fs9 from "fs/promises";
|
|
1813
2089
|
var isEventLine, readTranscriptLines, appendSizeCache, appendLineWithRetry, appendMessage, appendMessages, appendEvent;
|
|
1814
2090
|
var init_transcript = __esm({
|
|
1815
2091
|
"../core/src/session/transcript.ts"() {
|
|
@@ -1822,7 +2098,7 @@ var init_transcript = __esm({
|
|
|
1822
2098
|
await ensureSessionsDir(sessionId);
|
|
1823
2099
|
const p = getTranscriptPath(sessionId);
|
|
1824
2100
|
try {
|
|
1825
|
-
const text = await
|
|
2101
|
+
const text = await fs9.readFile(p, "utf-8");
|
|
1826
2102
|
const lines = [];
|
|
1827
2103
|
for (const s of text.split("\n")) {
|
|
1828
2104
|
const line = s.trim();
|
|
@@ -1848,18 +2124,18 @@ var init_transcript = __esm({
|
|
|
1848
2124
|
if (beforeSize === void 0) {
|
|
1849
2125
|
beforeSize = 0;
|
|
1850
2126
|
try {
|
|
1851
|
-
beforeSize = (await
|
|
2127
|
+
beforeSize = (await fs9.stat(p)).size;
|
|
1852
2128
|
} catch {
|
|
1853
2129
|
}
|
|
1854
2130
|
}
|
|
1855
2131
|
try {
|
|
1856
2132
|
if (handle) await handle.appendFile(payload, "utf-8");
|
|
1857
|
-
else await
|
|
2133
|
+
else await fs9.appendFile(p, payload, "utf-8");
|
|
1858
2134
|
appendSizeCache.set(p, beforeSize + payloadBytes);
|
|
1859
2135
|
return;
|
|
1860
2136
|
} catch (e) {
|
|
1861
2137
|
try {
|
|
1862
|
-
await
|
|
2138
|
+
await fs9.truncate(p, beforeSize);
|
|
1863
2139
|
} catch {
|
|
1864
2140
|
}
|
|
1865
2141
|
appendSizeCache.set(p, beforeSize);
|
|
@@ -1900,7 +2176,7 @@ var init_transcript = __esm({
|
|
|
1900
2176
|
let handle = null;
|
|
1901
2177
|
let i = 0;
|
|
1902
2178
|
try {
|
|
1903
|
-
handle = await
|
|
2179
|
+
handle = await fs9.open(p, "a");
|
|
1904
2180
|
for (; i < payloads.length; i++) await appendLineWithRetry(p, payloads[i], handle);
|
|
1905
2181
|
} catch (e) {
|
|
1906
2182
|
console.warn(`[transcript] \u6279\u91CF\u843D\u76D8\u7B2C ${i + 1}/${payloads.length} \u6761\u5931\u8D25\uFF0C\u8BE5\u6761\u8D77\u56DE\u843D\u9010\u6761\u65E7\u8DEF\u5F84:`, e instanceof Error ? e.message : e);
|
|
@@ -2070,17 +2346,118 @@ var init_content = __esm({
|
|
|
2070
2346
|
const archivedMessageCount = recovery.compaction.archivedMessageCount;
|
|
2071
2347
|
const messageAll = all.slice(archivedMessageCount);
|
|
2072
2348
|
if (messageAll.length === 0) {
|
|
2073
|
-
result.push(currentUserMsg);
|
|
2349
|
+
if (currentUserMsg) result.push(currentUserMsg);
|
|
2074
2350
|
return enforceVisionGate(result, modelId);
|
|
2075
2351
|
}
|
|
2076
2352
|
const repair = repairOrphanToolCalls(messageAll, recovery.interruption.kind === "crashed");
|
|
2077
2353
|
result.push(...decayOldToolResults(repair.msgs));
|
|
2078
|
-
result.push(currentUserMsg);
|
|
2354
|
+
if (currentUserMsg) result.push(currentUserMsg);
|
|
2079
2355
|
return enforceVisionGate(result, modelId);
|
|
2080
2356
|
};
|
|
2081
2357
|
}
|
|
2082
2358
|
});
|
|
2083
2359
|
|
|
2360
|
+
// ../core/src/agent/planMode.ts
|
|
2361
|
+
function filterToolsForPlanMode(tools) {
|
|
2362
|
+
const allowed = tools.filter((t) => t.function.planAllowed === true);
|
|
2363
|
+
return [...allowed, exitPlanModeToolSchema];
|
|
2364
|
+
}
|
|
2365
|
+
function appendPlanControlTools(tools) {
|
|
2366
|
+
return [
|
|
2367
|
+
...tools,
|
|
2368
|
+
enterPlanModeToolSchema,
|
|
2369
|
+
exitPlanModeToolSchema
|
|
2370
|
+
];
|
|
2371
|
+
}
|
|
2372
|
+
var exitPlanModeToolSchema, enterPlanModeToolSchema, PLAN_MODE_AUTO_ENTER_HINT;
|
|
2373
|
+
var init_planMode = __esm({
|
|
2374
|
+
"../core/src/agent/planMode.ts"() {
|
|
2375
|
+
"use strict";
|
|
2376
|
+
exitPlanModeToolSchema = {
|
|
2377
|
+
type: "function",
|
|
2378
|
+
function: {
|
|
2379
|
+
name: "exit_plan_mode",
|
|
2380
|
+
description: "\u8BA1\u5212\u6A21\u5F0F\u4E13\u7528\uFF1A\u5B8C\u6210\u53EA\u8BFB\u8C03\u7814\u3001\u5F62\u6210\u660E\u786E\u5B9E\u73B0\u65B9\u6848\u540E\u8C03\u7528\u672C\u5DE5\u5177\u63D0\u4EA4\u65B9\u6848\u3002\u63D0\u4EA4\u540E\u65B9\u6848\u4F1A\u5448\u73B0\u7ED9\u7528\u6237\u5BA1\u6279\uFF1B\u5BA1\u6279\u901A\u8FC7\u540E\u624D\u8FDB\u5165\u5B9E\u73B0\u9636\u6BB5\uFF08\u5C4A\u65F6\u624D\u5141\u8BB8\u4FEE\u6539\u6587\u4EF6/\u6267\u884C\u547D\u4EE4\uFF09\u3002\u5728\u8BA1\u5212\u6A21\u5F0F\u4E0B\u4F60\u53EA\u80FD\u8BFB\u53D6\u4E0E\u641C\u7D22\uFF0C\u4E0D\u80FD\u505A\u4EFB\u4F55\u4FEE\u6539\u3002",
|
|
2381
|
+
parameters: {
|
|
2382
|
+
type: "object",
|
|
2383
|
+
properties: {
|
|
2384
|
+
plan: { type: "string", description: "\u5B8C\u6574\u7684\u5B9E\u73B0\u65B9\u6848\uFF1A\u8981\u6539\u54EA\u4E9B\u6587\u4EF6\u3001\u5177\u4F53\u600E\u4E48\u6539\u3001\u4E3A\u4EC0\u4E48\u8FD9\u4E48\u505A\u3001\u6709\u4EC0\u4E48\u98CE\u9669\u4E0E\u53D6\u820D" }
|
|
2385
|
+
},
|
|
2386
|
+
required: ["plan"]
|
|
2387
|
+
}
|
|
2388
|
+
}
|
|
2389
|
+
};
|
|
2390
|
+
enterPlanModeToolSchema = {
|
|
2391
|
+
type: "function",
|
|
2392
|
+
function: {
|
|
2393
|
+
name: "enter_plan_mode",
|
|
2394
|
+
description: "\u81EA\u4E3B\u8FDB\u5165\u8BA1\u5212\u6A21\u5F0F\uFF1A\u5F53\u4EFB\u52A1\u662F\u975E\u5E73\u51E1\u7684\u5B9E\u73B0\u4EFB\u52A1\uFF08\u591A\u6587\u4EF6\u6539\u52A8\u3001\u67B6\u6784\u51B3\u7B56\u3001\u4E0D\u786E\u5B9A\u8DEF\u5F84\u3001\u9AD8\u98CE\u9669\u64CD\u4F5C\uFF09\u65F6\u8C03\u7528\u3002\u8C03\u7528\u540E\u672C\u8F6E\u7ED3\u675F\u5E76\u8FDB\u5165\u53EA\u8BFB\u8C03\u7814\u9636\u6BB5\u2014\u2014\u4F60\u53EA\u80FD\u8BFB\u53D6\u4E0E\u641C\u7D22\uFF0C\u4EA7\u51FA\u5B8C\u6574\u5B9E\u73B0\u65B9\u6848\uFF08\u8981\u6539\u54EA\u4E9B\u6587\u4EF6\u3001\u600E\u4E48\u6539\u3001\u4E3A\u4F55\u3001\u98CE\u9669\uFF09\u7ECF\u7528\u6237\u5BA1\u6279\u540E\u518D\u5B9E\u73B0\u3002\u7B80\u5355\u4EFB\u52A1\u65E0\u9700\u8C03\u7528\uFF0C\u76F4\u63A5\u5B9E\u73B0\u3002",
|
|
2395
|
+
parameters: {
|
|
2396
|
+
type: "object",
|
|
2397
|
+
properties: {
|
|
2398
|
+
reason: { type: "string", description: "\u4E3A\u4F55\u8981\u8FDB\u5165\u8BA1\u5212\u6A21\u5F0F\uFF08\u4EFB\u52A1\u7684\u590D\u6742\u70B9\u3001\u9700\u5148\u5398\u6E05\u7684\u5173\u952E\u95EE\u9898\uFF09" }
|
|
2399
|
+
},
|
|
2400
|
+
required: ["reason"]
|
|
2401
|
+
}
|
|
2402
|
+
}
|
|
2403
|
+
};
|
|
2404
|
+
PLAN_MODE_AUTO_ENTER_HINT = `\u3010\u4EFB\u52A1\u5206\u7C7B\uFF08\u6536\u5230\u5B9E\u73B0\u7C7B\u8BF7\u6C42\u65F6\u7684\u9996\u4E2A\u52A8\u4F5C\uFF09\u3011\u5148\u5224\u65AD\u590D\u6742\u5EA6\uFF0C\u518D\u51B3\u5B9A\u662F\u5426\u5148\u89C4\u5212\uFF1A
|
|
2405
|
+
- **\u975E\u5E73\u51E1\u4EFB\u52A1**\uFF08\u6EE1\u8DB3\u4EFB\u4E00\u5373\u7B97\uFF1A\u6D89\u53CA\u591A\u4E2A\u6587\u4EF6\u6539\u52A8 / \u9700\u8981\u67B6\u6784\u51B3\u7B56 / \u5B9E\u73B0\u8DEF\u5F84\u4E0D\u786E\u5B9A / \u9AD8\u98CE\u9669\u64CD\u4F5C / \u9884\u4F30 \u22653 \u4E2A\u6B65\u9AA4\uFF09\u2192 **\u9ED8\u8BA4\u5148\u8C03\u7528 enter_plan_mode \u8FDB\u5165\u8BA1\u5212\u6A21\u5F0F**\uFF1A\u4EE5\u53EA\u8BFB\u65B9\u5F0F\u4E13\u6CE8\u8C03\u7814\u3001\u7406\u6E05\u73B0\u72B6\u4E0E\u6539\u9020\u70B9\uFF0C\u518D\u8C03\u7528 exit_plan_mode \u63D0\u4EA4\u5B8C\u6574\u5B9E\u73B0\u65B9\u6848\uFF08\u8981\u6539\u54EA\u4E9B\u6587\u4EF6\u3001\u5177\u4F53\u600E\u4E48\u6539\u3001\u4E3A\u4F55\u8FD9\u4E48\u505A\u3001\u6709\u4EC0\u4E48\u98CE\u9669\u4E0E\u53D6\u820D\uFF09\uFF0C\u65B9\u6848\u7ECF\u7528\u6237\u5BA1\u6279\u540E\u624D\u8FDB\u5165\u5B9E\u73B0\u9636\u6BB5\u3002
|
|
2406
|
+
- **\u7B80\u5355\u4EFB\u52A1**\uFF08\u5355\u6587\u4EF6\u3001\u5355\u884C\u4FEE\u590D\u3001\u660E\u786E\u7684\u5C0F\u8C03\u6574\u3001\u7EAF\u67E5\u8BE2\u6216\u89E3\u91CA\uFF09\u2192 \u65E0\u9700\u89C4\u5212\uFF0C\u76F4\u63A5\u5B9E\u73B0\u6216\u4F5C\u7B54\u3002
|
|
2407
|
+
- \u5224\u636E\u793A\u4F8B\uFF1A\u300C\u65B0\u589E/\u5B9E\u73B0\u4E00\u4E2A\u529F\u80FD\u6A21\u5757\u300D\u300C\u91CD\u6784/\u6539\u9020 XX \u5B50\u7CFB\u7EDF\u300D\u300C\u628A A \u8FC1\u79FB\u5230 B\u300D\u300C\u8C03\u6574\u6574\u4F53\u6570\u636E\u6D41\u300D\u2192 \u975E\u5E73\u51E1\uFF0C\u5148\u89C4\u5212\uFF1B\u300C\u6539\u4E00\u4E0B\u7B2C N \u884C\u7684\u53D8\u91CF\u540D\u300D\u300C\u89E3\u91CA\u8FD9\u6BB5\u4EE3\u7801\u300D\u300C\u8DD1\u4E00\u4E0B\u6D4B\u8BD5\u300D\u2192 \u7B80\u5355\uFF0C\u76F4\u63A5\u505A\u3002`;
|
|
2408
|
+
}
|
|
2409
|
+
});
|
|
2410
|
+
|
|
2411
|
+
// ../core/src/agent/systemPrompt.ts
|
|
2412
|
+
var buildSystemPrompt;
|
|
2413
|
+
var init_systemPrompt = __esm({
|
|
2414
|
+
"../core/src/agent/systemPrompt.ts"() {
|
|
2415
|
+
"use strict";
|
|
2416
|
+
init_planMode();
|
|
2417
|
+
buildSystemPrompt = (p) => `\u4F60\u662F ${p.displayName}\u2014\u2014\u4E00\u4E2A\u57FA\u4E8E ${p.modelLabel} \u5927\u6A21\u578B\u7684\u7EC8\u7AEF AI \u7F16\u7A0B\u52A9\u624B\u3002\u4F60\u8FD0\u884C\u5728\u7528\u6237\u7684\u7EC8\u7AEF\u4E2D\uFF0C\u80FD\u8C03\u7528\u4E00\u7CFB\u5217\u5DE5\u5177\uFF08\u8BFB\u5199\u6587\u4EF6\u3001\u641C\u7D22\u4EE3\u7801\u3001\u6267\u884C\u547D\u4EE4\u3001\u8054\u7F51\u68C0\u7D22\u3001\u4EFB\u52A1\u7BA1\u7406\u7B49\uFF09\u76F4\u63A5\u5728\u7528\u6237\u5DE5\u4F5C\u533A\u5B8C\u6210\u5F00\u53D1\u4EFB\u52A1\u3002
|
|
2418
|
+
|
|
2419
|
+
\u3010\u8EAB\u4EFD\u3011
|
|
2420
|
+
- \u4F60\u7684\u540D\u5B57\u662F ${p.displayName}\uFF0C\u7531 ${p.modelLabel} \u6A21\u578B\u9A71\u52A8\u3002
|
|
2421
|
+
- \u88AB\u95EE"\u4F60\u662F\u8C01"\u65F6\u636E\u5B9E\u56DE\u7B54\uFF1A\u4F60\u662F ${p.displayName}\u3002\u5207\u52FF\u81EA\u79F0 ChatGPT\u3001GPT \u6216\u4EFB\u4F55\u5176\u4ED6\u516C\u53F8\u7684\u5927\u6A21\u578B/AI \u4EA7\u54C1\u3002
|
|
2422
|
+
|
|
2423
|
+
\u3010\u56DE\u7B54\u51C6\u5219 / \u5B8C\u6210\u5224\u5B9A\u3011
|
|
2424
|
+
- \u4EFB\u52A1\u5B8C\u6210\u540E\u76F4\u63A5\u7528\u81EA\u7136\u8BED\u8A00\u7ED9\u51FA\u6700\u7EC8\u7B54\u6848\uFF0C\u4E0D\u8981\u518D\u8C03\u7528\u5DE5\u5177\u3002**\u5B8C\u6210\u5224\u636E = \u7528\u6237\u7684\u6BCF\u4E2A\u5B50\u76EE\u6807\u90FD\u6709\u843D\u5730\u4EA7\u7269**\uFF08\u6240\u9700\u4FE1\u606F\u5DF2\u5230\u624B / \u8BE5\u6539\u7684\u6587\u4EF6\u5DF2\u6539\u5B8C / \u5DF2\u9A8C\u8BC1\u901A\u8FC7\uFF09\uFF0C\u800C\u975E"\u8C03\u7528\u8FC7\u5DE5\u5177"\u3002\u6BCF\u8F6E\u5DE5\u5177\u8FD4\u56DE\u540E\u5BF9\u7167\u539F\u59CB\u8BF7\u6C42\u4E0E todo \u6E05\u5355\uFF08\u82E5\u6709\uFF09\u9010\u9879\u6838\u5BF9\uFF1A\u8FD8\u6709\u672A\u843D\u5730\u9879\u5C31\u7EE7\u7EED\u63A8\u8FDB\uFF0C\u4E0D\u8981\u62FF\u90E8\u5206\u68C0\u7D22/\u8BFB\u53D6\u7ED3\u679C\u603B\u7ED3\u6536\u5C3E\u3002\u590D\u6742\u4EFB\u52A1\u7528 todo_write \u62C6\u89E3\u5E76\u9010\u9879\u52FE\u9009\uFF0C\u6BCF\u8F6E\u5BF9\u7167\u6E05\u5355\u6838\u5BF9\u8FDB\u5EA6\u3002
|
|
2425
|
+
- \u5DE5\u5177**\u6267\u884C\u5931\u8D25\u6216\u88AB\u7528\u6237\u62D2\u7EDD**\u65F6\uFF0C\u8BFB\u8FD4\u56DE\u7ED3\u679C\u5B9A\u4F4D\u539F\u56E0\uFF0C\u4FEE\u6B63\u53C2\u6570\u6216\u6362\u7B49\u6548\u65B9\u6848\u7EE7\u7EED\uFF0C\u4E0D\u8981\u9053\u6B49\u4E00\u4E24\u53E5\u5C31\u505C\u4E0B\uFF1B\u786E\u5B9E\u53D7\u963B\u9700\u8981\u7528\u6237\u51B3\u7B56\u65F6\uFF0C\u7528 ask_question \u8BF4\u660E**\u5177\u4F53**\u963B\u585E\u70B9\u3002**\u4E25\u7981**\u5728\u672A\u771F\u6B63\u6267\u884C\u6216\u672A\u9A8C\u8BC1\u7684\u60C5\u51B5\u4E0B\u58F0\u79F0"\u5DF2\u5B8C\u6210/\u5DF2\u4FEE\u6539/\u5DF2\u4FEE\u590D"\u2014\u2014\u6539\u52A8\u82E5\u53EF\u9A8C\u8BC1\uFF08\u91CD\u8BFB\u786E\u8BA4\u3001\u8DD1\u6D4B\u8BD5\u3001\u7C7B\u578B\u68C0\u67E5\uFF09\uFF0C\u5148\u9A8C\u8BC1\u518D\u6536\u5C3E\u3002
|
|
2426
|
+
|
|
2427
|
+
\u3010\u56DE\u7B54\u5F62\u5F0F\u3011
|
|
2428
|
+
- **\u5148\u7ED3\u8BBA\u540E\u7EC6\u8282**\uFF1A\u5148\u76F4\u63A5\u56DE\u7B54\u6216\u6C47\u62A5\u7ED3\u679C\uFF0C\u518D\u5C55\u5F00\u5FC5\u8981\u7684\u89E3\u91CA\uFF1B\u6536\u5C3E\u603B\u7ED3\u7B80\u77ED\uFF08\u51E0\u884C\u4EE5\u5185\uFF09\uFF0C\u4E0D\u9010\u6587\u4EF6\u6D41\u6C34\u8D26\u3002
|
|
2429
|
+
- **\u4E0D\u56DE\u8D34\u5927\u6BB5\u4EE3\u7801**\uFF1A\u6539\u52A8\u5185\u5BB9\u7528\u6237\u5728\u7F16\u8F91\u5668/diff \u91CC\u770B\u5F97\u5230\uFF0C\u6B63\u6587\u53EA\u9700\u4E00\u53E5\u8BDD\u8BF4\u660E\u6539\u4E86\u4EC0\u4E48\u3001\u4E3A\u4EC0\u4E48\uFF0C\u6216\u5F15\u7528\u5173\u952E\u51E0\u884C\u3002
|
|
2430
|
+
|
|
2431
|
+
\u3010\u5DE5\u5177\u4F7F\u7528\u51C6\u5219\u3011
|
|
2432
|
+
- \u4FEE\u6539\u6587\u4EF6**\u53EA\u80FD**\u7528 edit_file / create_file / write_file\u3002**\u4E25\u7981**\u7528 run_command \u901A\u8FC7 python/node/sed/awk/perl \u7B49\u811A\u672C\u8BFB\u5199\u6216\u4FEE\u6539\u6587\u4EF6\u2014\u2014\u811A\u672C\u8F6C\u4E49\u6781\u6613\u51FA\u9519\u3001\u6BCF\u6761\u547D\u4EE4\u90FD\u8981\u7528\u6237\u5BA1\u6279\u3001\u6548\u7387\u6781\u4F4E\uFF0C\u662F\u88AB\u660E\u786E\u7981\u6B62\u7684\u9000\u8DEF\u3002
|
|
2433
|
+
- edit_file \u5931\u8D25\u65F6**\u4E0D\u8981\u9000\u56DE shell**\uFF1A\u7528 read_file \u91CD\u65B0\u6838\u5BF9\u76EE\u6807\u7247\u6BB5\uFF08\u53BB\u6389\u300C<\u884C\u53F7>: \u300D\u524D\u7F00\u3001\u4FDD\u7559\u539F\u59CB Tab/\u7A7A\u683C\u7F29\u8FDB\u4E0E\u6362\u884C\uFF09\u540E\u518D\u6B21\u8C03\u7528 edit_file\uFF1B\u5B9A\u4F4D\u4E0D\u51C6\u5C31\u591A\u8BFB\u51E0\u884C\u4E0A\u4E0B\u6587\u5305\u88F9\u8FDB\u53BB\u3002\u672C\u5DE5\u5177\u5DF2\u6709\u591A\u7EA7\u7A7A\u767D/\u7F29\u8FDB\u5BB9\u9519\uFF0C\u591A\u6570\u5931\u914D\u53EA\u9700\u7CBE\u786E\u91CD\u8BFB\u5373\u53EF\u89E3\u51B3\u3002
|
|
2434
|
+
- \u4FEE\u6539\u65E2\u6709\u6587\u4EF6**\u4E00\u5F8B\u4F18\u5148 edit_file**\uFF08\u7CBE\u51C6\u5C40\u90E8\u66FF\u6362\u3001\u4FDD\u7559\u539F\u7F29\u8FDB\u3001\u6700\u5C0F diff\uFF09\uFF1Bwrite_file / create_file \u4EC5\u7528\u4E8E\u65B0\u5EFA\u6587\u4EF6\u6216\u5F7B\u5E95\u91CD\u5199\u6574\u4E2A\u6587\u4EF6\u3002\u2605 \u7528 write_file \u5168\u91CF\u8986\u76D6\u65E2\u6709\u6587\u4EF6\u4F1A\u4E22\u5931\u539F\u6709\u7F29\u8FDB\u4E0E\u683C\u5F0F\u3001\u4EA7\u751F\u5927\u91CF\u65E0\u5173 diff\uFF0C\u662F\u7528\u6237\u660E\u786E\u53CD\u611F\u7684\u53CD\u6A21\u5F0F\u2014\u2014\u5373\u4FBF\u8981\u6539\u7684\u5730\u65B9\u5F88\u591A\uFF0C\u4E5F\u7528\u591A\u6B21 edit_file \u800C\u975E\u4E00\u6B21 write_file \u8986\u76D6\u3002
|
|
2435
|
+
- \u8C03\u7528\u5DE5\u5177\u524D\u5148\u81EA\u95EE\uFF1A\u5DF2\u6709\u7684\u4FE1\u606F\u662F\u5426\u8DB3\u4EE5\u56DE\u7B54\u7528\u6237\uFF1F\u591F\u5C31\u4E0D\u518D\u8C03\u5DE5\u5177\uFF0C\u76F4\u63A5\u4F5C\u7B54\u3002
|
|
2436
|
+
- **\u5148\u8BFB\u5168\u518D\u52A8\u624B\uFF0C\u522B\u628A\u641C\u7D22\u5F53\u5B57\u5178\u67E5\uFF08\u53CD\u788E\u6B65\xB7\u91CD\u8981\uFF09**\uFF1A\u8981\u6539\u67D0\u4E2A\u6587\u4EF6/\u6A21\u5757\u524D\uFF0C\u5148\u7528 read_file \u628A\u76F8\u5173\u6587\u4EF6\u4E00\u6B21\u6027\u8BFB\u5168\uFF08\u7ED3\u6784\u3001\u5B57\u6BB5\u3001\u7528\u6CD5\u90FD\u5728\u6587\u4EF6\u91CC\uFF09\uFF0C\u4E0D\u8981\u9760 search_grep \u4E00\u4E2A\u5B57\u6BB5\u3001\u4E00\u4E2A\u7528\u6CD5\u5730\u8BD5\u63A2\u3002search_grep \u662F\u5B9A\u4F4D\u5DE5\u5177\u2014\u2014\u7528\u6765\u627E\u67D0\u7B26\u53F7\u5728\u54EA\u5B9A\u4E49/\u88AB\u8C01\u8C03\u7528\uFF0C\u627E\u5230\u540E\u7ACB\u5373\u8BFB\u5B8C\u6574\u6587\u4EF6\u7406\u89E3\u4E0A\u4E0B\u6587\uFF1B\u7EDD\u4E0D\u7528\u8FD1\u4E49\u5173\u952E\u8BCD\u53CD\u590D\u641C\u540C\u4E00\u4E2A\u610F\u56FE\u3002
|
|
2437
|
+
- **\u6279\u91CF\u89C4\u5212\u6539\u52A8\uFF0C\u4E00\u6B21\u6210\u578B\uFF08\u53CD\u788E\u6B65\xB7\u91CD\u8981\uFF09**\uFF1A\u52A8\u624B\u524D\u5148\u628A\u6240\u6709\u8981\u6539\u7684\u70B9\u60F3\u6E05\u695A\u3001\u5217\u51FA\u6765\uFF0C\u518D\u7528\u591A\u6B21 edit_file \u4E00\u53E3\u6C14\u6539\u5B8C\u3002\u4E0D\u8981"\u6539\u4E00\u5904 \u2192 \u770B\u4E00\u773C \u2192 \u53C8\u53D1\u73B0\u4E00\u5904 \u2192 \u518D\u6539"\u6765\u56DE\u4E03\u516B\u8D9F\u2014\u2014\u65E2\u70E7 token \u53C8\u6613\u9057\u6F0F\u3002\u6B63\u786E\u8282\u594F\uFF1A\u5148\u8BFB\u5168 \u2192 \u89C4\u5212 \u2192 \u6279\u91CF\u6539 \u2192 \u6700\u540E\u7EDF\u4E00\u9A8C\u8BC1\u3002
|
|
2438
|
+
- **\u6539\u5B8C\u52FF\u7ACB\u523B\u91CD\u8BFB\uFF08\u53CD\u788E\u6B65\xB7\u91CD\u8981\uFF09**\uFF1Aedit_file / write_file \u6210\u529F\u8FD4\u56DE\u540E\uFF0C\u5DE5\u5177\u7ED3\u679C\u5DF2\u8BF4\u660E\u6539\u4E86\u4EC0\u4E48\uFF0C\u4E0D\u8981\u9A6C\u4E0A read_file \u628A\u6574\u4E2A\u6587\u4EF6\u91CD\u8BFB\u4E00\u904D\u6765"\u786E\u8BA4"\u3002\u786E\u9700\u6838\u9A8C\u65F6\uFF0C\u53EA\u8BFB\u6539\u52A8\u9644\u8FD1\u51E0\u884C\u6216\u8DD1\u7C7B\u578B\u68C0\u67E5/\u6D4B\u8BD5\uFF0C\u800C\u975E\u6574\u6587\u4EF6\u91CD\u8BFB\u3002
|
|
2439
|
+
- \u4E0D\u91CD\u590D\u6293\u53D6\u5DF2\u6293\u53D6\u8FC7\u7684 URL\uFF1B\u4E0D\u7528\u8FD1\u4E49\u5173\u952E\u8BCD\u53CD\u590D\u641C\u7D22\u540C\u4E00\u4E2A\u610F\u56FE\u3002
|
|
2440
|
+
- \u8054\u7F51/\u641C\u7D22\u7C7B\u8C03\u7814\u4EFB\u52A1\uFF0C\u901A\u5E38 1~3 \u4E2A\u6765\u6E90\u5DF2\u8DB3\u591F\u652F\u6491\u56DE\u7B54\u2014\u2014\u62FF\u5230\u5373\u7EFC\u5408\u4F5C\u7B54\uFF0C\u4E0D\u8981\u4E3A\u8FFD\u6C42"\u66F4\u5168\u9762"\u800C\u65E0\u9650\u8FFD\u52A0\u68C0\u7D22\u8F6E\u6B21\u3002
|
|
2441
|
+
- **\u72EC\u7ACB\u8BFB\u64CD\u4F5C\u5E76\u884C\u6253\u5305\uFF08\u91CD\u8981\uFF09**\uFF1A\u591A\u4E2A\u4E92\u4E0D\u4F9D\u8D56\u7684\u53EA\u8BFB\u8C03\u7528\uFF08\u8BFB\u591A\u4E2A\u6587\u4EF6\u3001\u591A\u4E2A\u68C0\u7D22\u3001\u591A\u4E2A\u5B9A\u4E49\u67E5\u8BE2\uFF09\u5E94\u5728\u540C\u4E00\u6761\u6D88\u606F\u91CC\u4E00\u6B21\u6027\u5168\u90E8\u53D1\u51FA\uFF0C\u6267\u884C\u5C42\u4F1A\u81EA\u52A8\u5E76\u53D1\u6267\u884C\uFF0C\u4E00\u8F6E\u9876\u591A\u8F6E\uFF1B\u6709\u4F9D\u8D56\uFF08\u540E\u4E00\u6B65\u8981\u7528\u524D\u4E00\u6B65\u7ED3\u679C\uFF09\u6216\u4F1A\u6539\u72B6\u6001\u7684\u64CD\u4F5C\uFF0C\u5FC5\u987B\u7B49\u524D\u5E8F\u7ED3\u679C\u8FD4\u56DE\u518D\u53D1\u3002
|
|
2442
|
+
- \u591A\u6B65\u9AA4\u7684\u590D\u6742\u4EFB\u52A1\uFF08\u22653 \u6B65\u3001\u8DE8\u591A\u6587\u4EF6\u6216\u591A\u9636\u6BB5\uFF09\u5148\u8C03\u7528 todo_write \u628A\u8BA1\u5212\u62C6\u6210\u53EF\u52FE\u9009\u7684\u4EFB\u52A1\u6E05\u5355\uFF0C\u518D\u9010\u6B65\u63A8\u8FDB\u5E76\u5373\u65F6\u66F4\u65B0\u72B6\u6001\u2014\u2014\u8BA9\u4F60\u548C\u7528\u6237\u90FD\u770B\u6E05\u8FDB\u5EA6\u3001\u4E0D\u9057\u6F0F\u6B65\u9AA4\uFF1B\u7B80\u5355 1-2 \u6B65\u7684\u4EFB\u52A1\u65E0\u9700\u5EFA\u6E05\u5355\u3002
|
|
2443
|
+
|
|
2444
|
+
\u3010\u64CD\u4F5C\u786E\u8BA4\u7EA6\u5B9A\u3011
|
|
2445
|
+
- \u9047\u5230\u4F1A\u6539\u53D8\u72B6\u6001\u6216\u5177\u98CE\u9669\u7684\u5DE5\u5177\uFF08\u5199\u6587\u4EF6\u3001\u7F16\u8F91\u3001\u5220\u9664\u3001\u79FB\u52A8\u3001\u6267\u884C\u547D\u4EE4\u3001\u5BF9\u5916\u7F51\u7EDC\u8BF7\u6C42\u7B49\uFF09\uFF0C\u76F4\u63A5\u8C03\u7528\u8BE5\u5DE5\u5177\u5373\u53EF\uFF0C\u4E0D\u8981\u5148\u7528\u81EA\u7136\u8BED\u8A00\u5F81\u6C42\u786E\u8BA4\uFF08\u5982"\u6211\u53EF\u4EE5\u6267\u884C\u5417\uFF1F""\u662F\u5426\u7EE7\u7EED\uFF1F"\uFF09\u3002\u8FD9\u7C7B\u5DE5\u5177\u7531\u7CFB\u7EDF\u7EDF\u4E00\u62E6\u622A\u5E76\u5F39\u51FA\u5BA1\u6279\u754C\u9762\uFF0C\u7528\u6237\u4F1A\u4E00\u952E\u540C\u610F\u6216\u62D2\u7EDD\u2014\u2014\u4F60\u65E0\u9700\u4EE3\u66FF\u7CFB\u7EDF\u53D1\u95EE\uFF0C\u66F4\u4E0D\u8981\u505C\u4E0B\u7B49\u7528\u6237\u6253\u5B57\u786E\u8BA4\u3002
|
|
2446
|
+
- \u4EC5\u5F53\u5B58\u5728\u591A\u79CD\u660E\u663E\u4E0D\u540C\u7684\u5B9E\u73B0\u65B9\u6848\u3001\u9700\u8981\u7528\u6237\u5728\u65B9\u5411\u4E0A\u62CD\u677F\u65F6\uFF0C\u8C03\u7528 ask_question \u5DE5\u5177\u63D0\u51FA 2-4 \u4E2A\u7ED3\u6784\u5316\u9009\u9879\u8BA9\u7528\u6237\u9009\u62E9\uFF08\u7EC8\u7AEF\u4F1A\u5F39\u51FA\u591A\u9009\u6846\uFF0C\u6BD4\u7EAF\u6587\u5B57\u66F4\u6E05\u6670\u9AD8\u6548\uFF0C\u7528\u6237\u9009\u62E9\u4F1A\u81EA\u52A8\u56DE\u4F20\u7ED9\u4F60\uFF1B\u63D0\u95EE\u6846\u6052\u6709\u300COther\u300D\u81EA\u7531\u8F93\u5165\u6863\uFF0C\u9700\u8981\u7528\u6237\u63D0\u4F9B\u9009\u9879\u4E4B\u5916\u7684\u8D44\u6599\u2014\u2014\u5982\u767B\u5F55 token\u3001\u6587\u4EF6\u8DEF\u5F84\u2014\u2014\u4E5F\u7528 ask_question \u63D0\u51FA\uFF0C\u7528\u6237\u4F1A\u7ECF Other \u7C98\u8D34\u539F\u6587\u56DE\u4F20\uFF09\uFF1B\u5BF9"\u67D0\u4E2A\u5177\u4F53\u64CD\u4F5C\u662F\u5426\u6267\u884C"\u4E00\u5F8B\u76F4\u63A5\u8C03\u7528\u5DE5\u5177\u8D70\u5BA1\u6279\uFF0C\u4E0D\u8981\u7528 ask_question \u53BB\u95EE\u80FD\u5426\u6267\u884C\u67D0\u4E2A\u64CD\u4F5C\u3002
|
|
2447
|
+
|
|
2448
|
+
\u3010\u8BA1\u5212\u6A21\u5F0F\u3011
|
|
2449
|
+
${PLAN_MODE_AUTO_ENTER_HINT}
|
|
2450
|
+
- **\u8BA1\u5212\u6A21\u5F0F\u7684\u8BC6\u522B**\uFF1A\u5F53\u4F60\u53D1\u73B0\u5F53\u524D\u53EF\u7528\u5DE5\u5177\u4EC5\u5305\u542B\u8BFB\u53D6\u4E0E\u68C0\u7D22\u7C7B\uFF08read_file/search_grep/glob/git \u53EA\u8BFB/web \u7B49\uFF09\u3001\u4E0D\u542B\u4EFB\u4F55\u5199\u6587\u4EF6/\u6267\u884C\u547D\u4EE4/\u540E\u53F0\u4EFB\u52A1\u7C7B\u5DE5\u5177\u65F6\uFF0C\u8BF4\u660E\u5DF2\u8FDB\u5165\u8BA1\u5212\u6A21\u5F0F\u2014\u2014\u6B64\u65F6\u4E25\u7981\u4FEE\u6539\u4EFB\u4F55\u6587\u4EF6\u6216\u6267\u884C\u547D\u4EE4\uFF0C\u53EA\u80FD\u8C03\u7814\uFF0C\u5B8C\u6210\u540E\u5FC5\u987B\u8C03\u7528 exit_plan_mode \u63D0\u4EA4\u65B9\u6848\u3002
|
|
2451
|
+
- **\u63D0\u4EA4\u65B9\u6848\u5FC5\u987B\u7528\u5DE5\u5177**\uFF1A\u8FDB\u5165\u8BA1\u5212\u6A21\u5F0F\u540E\u7528 exit_plan_mode \u63D0\u4EA4\uFF1B\u82E5\u4F60\u5728\u6B63\u5E38\u8F6E\u5DF2\u81EA\u884C\u7528\u53EA\u8BFB\u5DE5\u5177\u5B8C\u6210\u8C03\u7814\uFF0C\u4E5F\u53EF\u76F4\u63A5\u8C03 exit_plan_mode \u63D0\u4EA4\u3002\u7EDD\u4E0D\u8981\u4EE5\u7EAF\u6587\u672C\u9648\u8FF0\u65B9\u6848\u7136\u540E\u505C\u4E0B\u7B49\u5F85\u5BA1\u6279\u2014\u2014\u7EAF\u6587\u672C\u65B9\u6848\u4E0D\u4F1A\u89E6\u53D1\u5BA1\u6279\u754C\u9762\uFF0C\u7528\u6237\u65E0\u6CD5\u4E00\u952E\u6279\u51C6/\u7F16\u8F91\uFF0C\u6D41\u7A0B\u4F1A\u5361\u6B7B\u3002
|
|
2452
|
+
|
|
2453
|
+
\u3010\u6301\u4E45\u8BB0\u5FC6\u3011
|
|
2454
|
+
- \u4F60\u62E5\u6709\u8DE8\u4F1A\u8BDD\u7684\u6301\u4E45\u8BB0\u5FC6\uFF1A\u7CFB\u7EDF\u63D0\u793A\u8BCD\u4E2D\u4EE5\u3010\u8BB0\u5FC6\u7D22\u5F15\u3011\u5217\u51FA\u5DF2\u5B58\u8BB0\u5FC6\uFF08\u4E00\u884C/\u6761\uFF1A\u540D\u79F0\u3001\u7C7B\u522B\u3001\u63CF\u8FF0\uFF09\u3002\u5F53\u7D22\u5F15\u4E2D\u67D0\u6761\u4E0E\u5F53\u524D\u4EFB\u52A1\u76F8\u5173\u3001\u9700\u8981\u7EC6\u8282\u65F6\uFF0C\u8C03\u7528 memory_read \u6309\u9700\u53EC\u56DE\u5168\u6587\uFF1B\u4E0D\u8981\u65E0\u5DEE\u522B\u5730\u5168\u91CF\u8BFB\u53D6\u3002
|
|
2455
|
+
- \u9047\u5230\u503C\u5F97\u8DE8\u4F1A\u8BDD\u4FDD\u7559\u7684\u4FE1\u606F\u65F6\uFF0C\u4E3B\u52A8\u7528 memory_save \u5B58\u6210\u8BB0\u5FC6\uFF0C\u4F8B\u5982\uFF1A\u7528\u6237\u7684\u957F\u671F\u504F\u597D\u4E0E\u89D2\u8272\u753B\u50CF\u3001\u7528\u6237\u7ED9\u51FA\u7684\u5DE5\u4F5C\u65B9\u5F0F\u53CD\u9988\uFF08\u542B\u539F\u56E0\u4E0E\u505A\u6CD5\uFF09\u3001\u9879\u76EE\u76EE\u6807\u4E0E\u9690\u542B\u7EA6\u675F\u3001\u5916\u90E8\u8D44\u6E90\u6307\u9488\uFF08URL/\u770B\u677F/\u5DE5\u5355\uFF09\u3002\u5373\u90A3\u4E9B\u300C\u4E0B\u6B21\u4E0D\u8BE5\u91CD\u65B0\u53D1\u73B0\u300D\u300C\u4EE3\u7801\u4E0E git \u4E0D\u4F1A\u76F4\u63A5\u544A\u8BC9\u4F60\u300D\u7684\u975E\u663E\u7136\u4E8B\u5B9E\u3002
|
|
2456
|
+
- \u4E0D\u8981\u4FDD\u5B58\uFF1A\u4EE3\u7801\u7ED3\u6784\u3001\u8FC7\u5F80\u4FEE\u590D\u3001git \u5386\u53F2\u7B49\u4ED3\u5E93\u672C\u8EAB\u5DF2\u8BB0\u5F55\u7684\u5185\u5BB9\uFF1B\u53EA\u5BF9\u672C\u6B21\u5BF9\u8BDD\u6709\u610F\u4E49\u3001\u4E0B\u4E0D\u4E3A\u4F8B\u7684\u4E34\u65F6\u4FE1\u606F\u3002\u82E5\u4E0D\u786E\u5B9A\u67D0\u6761\u4FE1\u606F\u662F\u5426\u503C\u5F97\u5B58\uFF0C\u5148\u95EE\u6E05\u5176\u975E\u663E\u7136\u4E4B\u5904\uFF0C\u5B58\u90A3\u4E00\u70B9\u800C\u975E\u6574\u6BB5\u6D41\u6C34\u3002
|
|
2457
|
+
- \u8BB0\u5FC6\u4F1A\u91CD\u590D\u51FA\u73B0\uFF0C\u53D1\u73B0\u5DF2\u5931\u6548\u6216\u6709\u8BEF\u7684\u8BB0\u5FC6\u7528 memory_delete \u6E05\u7406\u3002\u7C7B\u522B\u6309\u8BED\u4E49\u9009\uFF1Auser\uFF08\u7528\u6237\u753B\u50CF/\u504F\u597D\uFF09/ feedback\uFF08\u5DE5\u4F5C\u65B9\u5F0F\u53CD\u9988\uFF09/ project\uFF08\u9879\u76EE\u76EE\u6807/\u7EA6\u675F\uFF09/ reference\uFF08\u5916\u90E8\u8D44\u6E90\u6307\u9488\uFF09\u3002`;
|
|
2458
|
+
}
|
|
2459
|
+
});
|
|
2460
|
+
|
|
2084
2461
|
// ../core/src/hooks/types.ts
|
|
2085
2462
|
var INTERCEPTABLE_EVENTS, TOOL_EVENTS, ALL_EVENTS, DEFAULT_TIMEOUT_BY_EVENT;
|
|
2086
2463
|
var init_types = __esm({
|
|
@@ -2107,7 +2484,7 @@ var init_types = __esm({
|
|
|
2107
2484
|
|
|
2108
2485
|
// ../core/src/hooks/shellExecutor.ts
|
|
2109
2486
|
import { spawn } from "child_process";
|
|
2110
|
-
import
|
|
2487
|
+
import path10 from "path";
|
|
2111
2488
|
var MAX_OUTPUT, DEFAULT_TIMEOUT_MS, HARD_TIMEOUT_CAP_MS, ENV_WHITELIST, truncate, MAX_STDIN_FIELD, capFieldStrings, extractFilePath, executeHookCommand;
|
|
2112
2489
|
var init_shellExecutor = __esm({
|
|
2113
2490
|
"../core/src/hooks/shellExecutor.ts"() {
|
|
@@ -2153,7 +2530,7 @@ var init_shellExecutor = __esm({
|
|
|
2153
2530
|
if (typeof rel !== "string" || !rel.trim()) return void 0;
|
|
2154
2531
|
const base = typeof p.cwd === "string" && p.cwd || process.env.WORKSPACE_ROOT || process.cwd();
|
|
2155
2532
|
try {
|
|
2156
|
-
return
|
|
2533
|
+
return path10.resolve(base, rel);
|
|
2157
2534
|
} catch {
|
|
2158
2535
|
return void 0;
|
|
2159
2536
|
}
|
|
@@ -2370,7 +2747,7 @@ var init_hooks = __esm({
|
|
|
2370
2747
|
});
|
|
2371
2748
|
|
|
2372
2749
|
// ../core/src/agent/truncate.ts
|
|
2373
|
-
import
|
|
2750
|
+
import path11 from "path";
|
|
2374
2751
|
function stripAnsi(text) {
|
|
2375
2752
|
if (!text || !text.includes(ANSI_ESC_CHAR)) return text;
|
|
2376
2753
|
return text.replace(ANSI_ESCAPE, "");
|
|
@@ -2390,6 +2767,8 @@ var init_truncate = __esm({
|
|
|
2390
2767
|
init_contextCore();
|
|
2391
2768
|
init_contentParts();
|
|
2392
2769
|
init_content();
|
|
2770
|
+
init_systemPrompt();
|
|
2771
|
+
init_model();
|
|
2393
2772
|
init_store();
|
|
2394
2773
|
init_transcript();
|
|
2395
2774
|
init_hooks();
|
|
@@ -2409,10 +2788,10 @@ var init_truncate = __esm({
|
|
|
2409
2788
|
if (!text) return text;
|
|
2410
2789
|
const roots = /* @__PURE__ */ new Set();
|
|
2411
2790
|
try {
|
|
2412
|
-
roots.add(
|
|
2791
|
+
roots.add(path11.resolve(appConfig.userWorkspaceDir));
|
|
2413
2792
|
for (const r of getFileAccessRoots()) {
|
|
2414
2793
|
try {
|
|
2415
|
-
roots.add(
|
|
2794
|
+
roots.add(path11.resolve(r));
|
|
2416
2795
|
} catch {
|
|
2417
2796
|
}
|
|
2418
2797
|
}
|
|
@@ -2710,14 +3089,14 @@ ${lines}
|
|
|
2710
3089
|
const hitRate = event.lastRealPromptTokens && event.lastCachedTokens != null && event.lastRealPromptTokens > 0 ? event.lastCachedTokens / event.lastRealPromptTokens : null;
|
|
2711
3090
|
const cacheFactor = hitRate == null ? 1 : Math.min(1.1, Math.max(0.9, 0.9 + hitRate * 0.2));
|
|
2712
3091
|
const effectiveRatio = Math.min(event.compactRatio * cacheFactor, 0.82);
|
|
2713
|
-
if (estReal(event.messageArr) <= event.modelWindow * effectiveRatio) return;
|
|
3092
|
+
if (!event.forceCompact && estReal(event.messageArr) <= event.modelWindow * effectiveRatio) return;
|
|
2714
3093
|
const preDecaySize = estReal(event.messageArr);
|
|
2715
3094
|
const decayedArr = decayOldToolResults(event.messageArr);
|
|
2716
3095
|
if (decayedArr !== event.messageArr) {
|
|
2717
3096
|
event.messageArr.length = 0;
|
|
2718
3097
|
event.messageArr.push(...decayedArr);
|
|
2719
3098
|
}
|
|
2720
|
-
if (estReal(event.messageArr) <= event.modelWindow * effectiveRatio) {
|
|
3099
|
+
if (!event.forceCompact && estReal(event.messageArr) <= event.modelWindow * effectiveRatio) {
|
|
2721
3100
|
console.log(`\u{1F4C9} [\u7A97\u53E3\u6CBB\u7406] \u514D\u8D39\u8870\u51CF\uFF08\u65E7\u5DE5\u5177\u7ED3\u679C\u6298\u53E0\uFF09\u540E\u56DE\u5230\u9608\u503C\u5185\uFF08${Math.round(preDecaySize)} \u2192 ${Math.round(estReal(event.messageArr))} token\uFF09\uFF0C\u8DF3\u8FC7 LLM \u538B\u7F29`);
|
|
2722
3101
|
return;
|
|
2723
3102
|
}
|
|
@@ -2730,7 +3109,9 @@ ${lines}
|
|
|
2730
3109
|
const preCompactSize = Math.round(lastSize);
|
|
2731
3110
|
const startTime = performance.now();
|
|
2732
3111
|
let round = 0;
|
|
2733
|
-
|
|
3112
|
+
let forcedPass = event.forceCompact === true;
|
|
3113
|
+
while (forcedPass || lastSize > event.modelWindow * effectiveRatio) {
|
|
3114
|
+
forcedPass = false;
|
|
2734
3115
|
if (event.signal?.aborted) {
|
|
2735
3116
|
return;
|
|
2736
3117
|
}
|
|
@@ -2838,7 +3219,7 @@ ${lines}
|
|
|
2838
3219
|
tokensBefore: preCompactSize,
|
|
2839
3220
|
tokensAfter: afterSize,
|
|
2840
3221
|
durationMs: Math.round(performance.now() - startTime),
|
|
2841
|
-
trigger: "auto",
|
|
3222
|
+
trigger: event.compactTrigger ?? "auto",
|
|
2842
3223
|
summary
|
|
2843
3224
|
});
|
|
2844
3225
|
}
|
|
@@ -2853,8 +3234,8 @@ ${lines}
|
|
|
2853
3234
|
});
|
|
2854
3235
|
|
|
2855
3236
|
// ../core/src/tool/permissions.ts
|
|
2856
|
-
import
|
|
2857
|
-
import
|
|
3237
|
+
import fs10 from "fs/promises";
|
|
3238
|
+
import path12 from "path";
|
|
2858
3239
|
var rules2, trustedProject, globCache, globToRegex, DANGER_COMMAND_TOOLS, compileRule, readPermissionConfig, toolNameMatches, ruleMatches, initPermissions, checkPermission, listPermissionRules, buildScopedAllowRule, resolveSettingsPath, addPermissionRule;
|
|
2859
3240
|
var init_permissions = __esm({
|
|
2860
3241
|
"../core/src/tool/permissions.ts"() {
|
|
@@ -2900,15 +3281,15 @@ var init_permissions = __esm({
|
|
|
2900
3281
|
readPermissionConfig = async (includeProject) => {
|
|
2901
3282
|
const merged = { allow: [], deny: [], ask: [] };
|
|
2902
3283
|
const paths = [
|
|
2903
|
-
|
|
3284
|
+
path12.join(appConfig.dataDir, "settings.json"),
|
|
2904
3285
|
// 全局用户级
|
|
2905
|
-
...includeProject ? [
|
|
3286
|
+
...includeProject ? [path12.join(process.cwd(), ".deepseeker-code", "settings.json")] : []
|
|
2906
3287
|
// 项目级(叠加);未信任时省略
|
|
2907
3288
|
];
|
|
2908
3289
|
for (const configPath of paths) {
|
|
2909
3290
|
let raw;
|
|
2910
3291
|
try {
|
|
2911
|
-
raw = await
|
|
3292
|
+
raw = await fs10.readFile(configPath, "utf-8");
|
|
2912
3293
|
} catch {
|
|
2913
3294
|
continue;
|
|
2914
3295
|
}
|
|
@@ -2992,7 +3373,7 @@ var init_permissions = __esm({
|
|
|
2992
3373
|
}
|
|
2993
3374
|
return `${toolName}(${val})`;
|
|
2994
3375
|
};
|
|
2995
|
-
resolveSettingsPath = (scope) => scope === "global" ?
|
|
3376
|
+
resolveSettingsPath = (scope) => scope === "global" ? path12.join(appConfig.dataDir, "settings.json") : path12.join(process.cwd(), ".deepseeker-code", "settings.json");
|
|
2996
3377
|
addPermissionRule = async (scope, kind, ruleStr) => {
|
|
2997
3378
|
if (scope === "project" && !trustedProject) return false;
|
|
2998
3379
|
const compiled2 = compileRule(ruleStr, `runtime:addPermissionRule(${scope})`, kind);
|
|
@@ -3004,7 +3385,7 @@ var init_permissions = __esm({
|
|
|
3004
3385
|
const arr = Array.isArray(cfg.permissions[kind]) ? cfg.permissions[kind] : cfg.permissions[kind] = [];
|
|
3005
3386
|
if (!arr.includes(ruleStr)) {
|
|
3006
3387
|
arr.push(ruleStr);
|
|
3007
|
-
await
|
|
3388
|
+
await fs10.mkdir(path12.dirname(file), { recursive: true });
|
|
3008
3389
|
await atomicWriteJSON(file, cfg);
|
|
3009
3390
|
}
|
|
3010
3391
|
if (!rules2[kind].some((r) => r.raw === compiled2.raw)) rules2[kind].push(compiled2);
|
|
@@ -3042,9 +3423,9 @@ var init_sessionRegistry = __esm({
|
|
|
3042
3423
|
});
|
|
3043
3424
|
|
|
3044
3425
|
// ../core/src/tool/guard.ts
|
|
3045
|
-
import
|
|
3426
|
+
import fs11 from "fs/promises";
|
|
3046
3427
|
import fsSync from "fs";
|
|
3047
|
-
import
|
|
3428
|
+
import path13 from "path";
|
|
3048
3429
|
import ignore from "ignore";
|
|
3049
3430
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
3050
3431
|
var WORKSPACE_ROOT, workspaceAls, getActiveWorkspaceRoot, runWithWorkspaceRoot, runWithSessionContext, BUILTIN_IGNORE_RULES, ignoreCache, ignoreBuilding, allowedRootsReal, getAllowedWorkspaceRoots, realpathNativeSync, getContainingRoot, allowedBoundaryRoots, resolveSafePath, resolveReadablePath, assertWithinWorkspace, PROTECTED_WRITE_DIRS, COMMAND_ENV_DENYLIST, SENSITIVE_ENV_PATTERN, scrubCommandEnv, isProtectedWrite, SCAN_PRUNE_DIRS, scanIgnoreFilesRecursive, buildIgnoreEngine, getIgnoreForBase, initializeWorkspaceIgnore, checkIsPathIgnored, requestApproval;
|
|
@@ -3109,8 +3490,8 @@ var init_guard = __esm({
|
|
|
3109
3490
|
let best;
|
|
3110
3491
|
for (const r of allowedBoundaryRoots()) {
|
|
3111
3492
|
const rReal = realpathNativeSync(r);
|
|
3112
|
-
const rel =
|
|
3113
|
-
if (!rel.startsWith("..") && !
|
|
3493
|
+
const rel = path13.relative(rReal, target);
|
|
3494
|
+
if (!rel.startsWith("..") && !path13.isAbsolute(rel)) {
|
|
3114
3495
|
if (!best || rReal.length > best.length) best = rReal;
|
|
3115
3496
|
}
|
|
3116
3497
|
}
|
|
@@ -3127,16 +3508,16 @@ var init_guard = __esm({
|
|
|
3127
3508
|
};
|
|
3128
3509
|
resolveSafePath = (rel, base) => {
|
|
3129
3510
|
const root = base ?? getActiveWorkspaceRoot();
|
|
3130
|
-
const candidateAbsPath =
|
|
3511
|
+
const candidateAbsPath = path13.resolve(root, rel);
|
|
3131
3512
|
let truePhysicalPath = candidateAbsPath;
|
|
3132
3513
|
try {
|
|
3133
3514
|
if (fsSync.existsSync(candidateAbsPath)) {
|
|
3134
3515
|
truePhysicalPath = fsSync.realpathSync(candidateAbsPath);
|
|
3135
3516
|
} else {
|
|
3136
|
-
const parentDir =
|
|
3517
|
+
const parentDir = path13.dirname(candidateAbsPath);
|
|
3137
3518
|
if (fsSync.existsSync(parentDir)) {
|
|
3138
3519
|
const trueParentDir = fsSync.realpathSync(parentDir);
|
|
3139
|
-
truePhysicalPath =
|
|
3520
|
+
truePhysicalPath = path13.join(trueParentDir, path13.basename(candidateAbsPath));
|
|
3140
3521
|
}
|
|
3141
3522
|
}
|
|
3142
3523
|
} catch (e) {
|
|
@@ -3150,8 +3531,8 @@ var init_guard = __esm({
|
|
|
3150
3531
|
}
|
|
3151
3532
|
})() : allowedBoundaryRoots();
|
|
3152
3533
|
const escaped = boundaryRoots.every((r) => {
|
|
3153
|
-
const rel0 =
|
|
3154
|
-
return rel0.startsWith("..") ||
|
|
3534
|
+
const rel0 = path13.relative(r, truePhysicalPath);
|
|
3535
|
+
return rel0.startsWith("..") || path13.isAbsolute(rel0);
|
|
3155
3536
|
});
|
|
3156
3537
|
if (escaped) {
|
|
3157
3538
|
throw new Error(`\u{1F6D1} [SECURITY ALERT] \u68C0\u6D4B\u5230\u6076\u610F\u7684\u7269\u7406\u8DEF\u5F84\u8DE8\u754C\u9003\u9038\uFF01\u62D2\u7EDD\u8BBF\u95EE\uFF1A${rel}`);
|
|
@@ -3160,12 +3541,12 @@ var init_guard = __esm({
|
|
|
3160
3541
|
};
|
|
3161
3542
|
resolveReadablePath = (rel) => {
|
|
3162
3543
|
const root = getActiveWorkspaceRoot();
|
|
3163
|
-
const absPath =
|
|
3544
|
+
const absPath = path13.resolve(root, rel);
|
|
3164
3545
|
if (!fsSync.existsSync(absPath)) {
|
|
3165
|
-
const rootName =
|
|
3546
|
+
const rootName = path13.basename(root);
|
|
3166
3547
|
const firstSeg = rel.split(/[\\/]/)[0];
|
|
3167
3548
|
if (rootName && firstSeg === rootName) {
|
|
3168
|
-
const alt =
|
|
3549
|
+
const alt = path13.resolve(root, rel.slice(firstSeg.length + 1));
|
|
3169
3550
|
if (fsSync.existsSync(alt)) return alt;
|
|
3170
3551
|
}
|
|
3171
3552
|
}
|
|
@@ -3178,9 +3559,9 @@ var init_guard = __esm({
|
|
|
3178
3559
|
if (fsSync.existsSync(absPath)) {
|
|
3179
3560
|
truePhysicalPath = fsSync.realpathSync(absPath);
|
|
3180
3561
|
} else {
|
|
3181
|
-
const parentDir =
|
|
3562
|
+
const parentDir = path13.dirname(absPath);
|
|
3182
3563
|
if (fsSync.existsSync(parentDir)) {
|
|
3183
|
-
truePhysicalPath =
|
|
3564
|
+
truePhysicalPath = path13.join(fsSync.realpathSync(parentDir), path13.basename(absPath));
|
|
3184
3565
|
}
|
|
3185
3566
|
}
|
|
3186
3567
|
} catch (e) {
|
|
@@ -3194,8 +3575,8 @@ var init_guard = __esm({
|
|
|
3194
3575
|
}
|
|
3195
3576
|
})() : allowedBoundaryRoots();
|
|
3196
3577
|
const escaped = boundaryRoots.every((r) => {
|
|
3197
|
-
const rel0 =
|
|
3198
|
-
return rel0.startsWith("..") ||
|
|
3578
|
+
const rel0 = path13.relative(r, truePhysicalPath);
|
|
3579
|
+
return rel0.startsWith("..") || path13.isAbsolute(rel0);
|
|
3199
3580
|
});
|
|
3200
3581
|
if (escaped) {
|
|
3201
3582
|
throw new Error(`\u{1F6D1} [SECURITY ALERT] \u4E8C\u6B21\u56F4\u680F\u590D\u68C0\u53D1\u73B0\u8D8A\u754C\uFF08\u7591\u4F3C TOCTOU \u8F6F\u94FE\u63A5\u9003\u9038\uFF09\uFF1A${absPath}`);
|
|
@@ -3222,7 +3603,7 @@ var init_guard = __esm({
|
|
|
3222
3603
|
if (!relOrAbs) return false;
|
|
3223
3604
|
try {
|
|
3224
3605
|
const base = cwd || process.env.WORKSPACE_ROOT || process.cwd();
|
|
3225
|
-
const abs =
|
|
3606
|
+
const abs = path13.isAbsolute(relOrAbs) ? relOrAbs : path13.resolve(base, relOrAbs);
|
|
3226
3607
|
const lower = abs.replace(/\\/g, "/").toLowerCase();
|
|
3227
3608
|
return PROTECTED_WRITE_DIRS.some((d) => {
|
|
3228
3609
|
const seg = ("/" + d).toLowerCase();
|
|
@@ -3254,12 +3635,12 @@ var init_guard = __esm({
|
|
|
3254
3635
|
]);
|
|
3255
3636
|
scanIgnoreFilesRecursive = async (dirPath, base, engine) => {
|
|
3256
3637
|
try {
|
|
3257
|
-
const entries = await
|
|
3638
|
+
const entries = await fs11.readdir(dirPath, { withFileTypes: true });
|
|
3258
3639
|
for (const entry of entries) {
|
|
3259
3640
|
if (entry.isFile() && (entry.name === ".gitignore" || entry.name === ".agentignore")) {
|
|
3260
|
-
const fullPath =
|
|
3261
|
-
const content = await
|
|
3262
|
-
const relDir =
|
|
3641
|
+
const fullPath = path13.join(dirPath, entry.name);
|
|
3642
|
+
const content = await fs11.readFile(fullPath, "utf-8");
|
|
3643
|
+
const relDir = path13.relative(base, dirPath).replace(/\\/g, "/");
|
|
3263
3644
|
const rules3 = content.split(/\r?\n/).map((line) => {
|
|
3264
3645
|
const trimmed = line.trim();
|
|
3265
3646
|
if (!trimmed || trimmed.startsWith("#")) return "";
|
|
@@ -3270,7 +3651,7 @@ var init_guard = __esm({
|
|
|
3270
3651
|
}
|
|
3271
3652
|
for (const entry of entries) {
|
|
3272
3653
|
if (entry.isDirectory() && !SCAN_PRUNE_DIRS.has(entry.name)) {
|
|
3273
|
-
await scanIgnoreFilesRecursive(
|
|
3654
|
+
await scanIgnoreFilesRecursive(path13.join(dirPath, entry.name), base, engine);
|
|
3274
3655
|
}
|
|
3275
3656
|
}
|
|
3276
3657
|
} catch {
|
|
@@ -3383,7 +3764,7 @@ var init_inbox = __esm({
|
|
|
3383
3764
|
// ../core/src/tool/registry/background.ts
|
|
3384
3765
|
import { spawn as spawn2, execFileSync } from "child_process";
|
|
3385
3766
|
import fsSync2 from "fs";
|
|
3386
|
-
import
|
|
3767
|
+
import path14 from "path";
|
|
3387
3768
|
function appendOutput(task, chunk) {
|
|
3388
3769
|
task.outputBuffer += chunk;
|
|
3389
3770
|
if (task.outputBuffer.length > MAX_BUFFER_CHARS) {
|
|
@@ -3408,7 +3789,7 @@ async function killTree(proc) {
|
|
|
3408
3789
|
}
|
|
3409
3790
|
}
|
|
3410
3791
|
async function killBackgroundTasksUnder(dirPath) {
|
|
3411
|
-
const norm = (p) =>
|
|
3792
|
+
const norm = (p) => path14.resolve(p).replace(/\\/g, "/").replace(/\/+$/, "").toLowerCase();
|
|
3412
3793
|
const target = norm(dirPath);
|
|
3413
3794
|
let killed = 0;
|
|
3414
3795
|
for (const task of registry.values()) {
|
|
@@ -3454,9 +3835,9 @@ var init_background = __esm({
|
|
|
3454
3835
|
if (envShell && envShell.toLowerCase() !== "cmd") candidates.push(envShell);
|
|
3455
3836
|
const gitExe = whereLines("git")[0];
|
|
3456
3837
|
if (gitExe) {
|
|
3457
|
-
const dir =
|
|
3458
|
-
const root =
|
|
3459
|
-
candidates.push(
|
|
3838
|
+
const dir = path14.dirname(gitExe);
|
|
3839
|
+
const root = path14.dirname(dir);
|
|
3840
|
+
candidates.push(path14.join(root, "bin", "bash.exe"), path14.join(dir, "bash.exe"), path14.join(path14.dirname(root), "bin", "bash.exe"));
|
|
3460
3841
|
}
|
|
3461
3842
|
const bashHits = whereLines("bash").filter((p) => !/\\System32\\/i.test(p)).sort((a, b) => Number(/\\Git\\/i.test(b)) - Number(/\\Git\\/i.test(a)));
|
|
3462
3843
|
candidates.push(...bashHits);
|
|
@@ -4282,17 +4663,17 @@ ${capped || JSON.stringify(result)}`).content;
|
|
|
4282
4663
|
});
|
|
4283
4664
|
|
|
4284
4665
|
// ../core/src/tool/mcp/loader.ts
|
|
4285
|
-
import
|
|
4286
|
-
import
|
|
4666
|
+
import fs12 from "fs/promises";
|
|
4667
|
+
import path15 from "path";
|
|
4287
4668
|
import { homedir } from "os";
|
|
4288
4669
|
function sanitize(s) {
|
|
4289
4670
|
return s.replace(/[^a-zA-Z0-9_]/g, "_");
|
|
4290
4671
|
}
|
|
4291
4672
|
async function readMcpConfig() {
|
|
4292
|
-
const configPath = process.env.MCP_CONFIG ||
|
|
4673
|
+
const configPath = process.env.MCP_CONFIG || path15.join(appConfig.dataDir, "mcp.json");
|
|
4293
4674
|
let raw;
|
|
4294
4675
|
try {
|
|
4295
|
-
raw = await
|
|
4676
|
+
raw = await fs12.readFile(configPath, "utf-8");
|
|
4296
4677
|
} catch {
|
|
4297
4678
|
return {};
|
|
4298
4679
|
}
|
|
@@ -4617,8 +4998,8 @@ ${text}`;
|
|
|
4617
4998
|
for (const c of clients) {
|
|
4618
4999
|
if (server && c.serverName !== server) continue;
|
|
4619
5000
|
try {
|
|
4620
|
-
const
|
|
4621
|
-
for (const t of
|
|
5001
|
+
const ts2 = await c.listTools();
|
|
5002
|
+
for (const t of ts2) {
|
|
4622
5003
|
const props = t?.inputSchema?.properties && typeof t.inputSchema.properties === "object" ? Object.keys(t.inputSchema.properties) : [];
|
|
4623
5004
|
const required = Array.isArray(t?.inputSchema?.required) ? t.inputSchema.required : [];
|
|
4624
5005
|
const argList = props.map((p) => required.includes(p) ? `${p}*` : p).join(", ");
|
|
@@ -4833,57 +5214,6 @@ var init_repeatBreaker = __esm({
|
|
|
4833
5214
|
}
|
|
4834
5215
|
});
|
|
4835
5216
|
|
|
4836
|
-
// ../core/src/agent/planMode.ts
|
|
4837
|
-
function filterToolsForPlanMode(tools) {
|
|
4838
|
-
const allowed = tools.filter((t) => t.function.planAllowed === true);
|
|
4839
|
-
return [...allowed, exitPlanModeToolSchema];
|
|
4840
|
-
}
|
|
4841
|
-
function appendPlanControlTools(tools) {
|
|
4842
|
-
return [
|
|
4843
|
-
...tools,
|
|
4844
|
-
enterPlanModeToolSchema,
|
|
4845
|
-
exitPlanModeToolSchema
|
|
4846
|
-
];
|
|
4847
|
-
}
|
|
4848
|
-
var exitPlanModeToolSchema, enterPlanModeToolSchema, PLAN_MODE_AUTO_ENTER_HINT;
|
|
4849
|
-
var init_planMode = __esm({
|
|
4850
|
-
"../core/src/agent/planMode.ts"() {
|
|
4851
|
-
"use strict";
|
|
4852
|
-
exitPlanModeToolSchema = {
|
|
4853
|
-
type: "function",
|
|
4854
|
-
function: {
|
|
4855
|
-
name: "exit_plan_mode",
|
|
4856
|
-
description: "\u8BA1\u5212\u6A21\u5F0F\u4E13\u7528\uFF1A\u5B8C\u6210\u53EA\u8BFB\u8C03\u7814\u3001\u5F62\u6210\u660E\u786E\u5B9E\u73B0\u65B9\u6848\u540E\u8C03\u7528\u672C\u5DE5\u5177\u63D0\u4EA4\u65B9\u6848\u3002\u63D0\u4EA4\u540E\u65B9\u6848\u4F1A\u5448\u73B0\u7ED9\u7528\u6237\u5BA1\u6279\uFF1B\u5BA1\u6279\u901A\u8FC7\u540E\u624D\u8FDB\u5165\u5B9E\u73B0\u9636\u6BB5\uFF08\u5C4A\u65F6\u624D\u5141\u8BB8\u4FEE\u6539\u6587\u4EF6/\u6267\u884C\u547D\u4EE4\uFF09\u3002\u5728\u8BA1\u5212\u6A21\u5F0F\u4E0B\u4F60\u53EA\u80FD\u8BFB\u53D6\u4E0E\u641C\u7D22\uFF0C\u4E0D\u80FD\u505A\u4EFB\u4F55\u4FEE\u6539\u3002",
|
|
4857
|
-
parameters: {
|
|
4858
|
-
type: "object",
|
|
4859
|
-
properties: {
|
|
4860
|
-
plan: { type: "string", description: "\u5B8C\u6574\u7684\u5B9E\u73B0\u65B9\u6848\uFF1A\u8981\u6539\u54EA\u4E9B\u6587\u4EF6\u3001\u5177\u4F53\u600E\u4E48\u6539\u3001\u4E3A\u4EC0\u4E48\u8FD9\u4E48\u505A\u3001\u6709\u4EC0\u4E48\u98CE\u9669\u4E0E\u53D6\u820D" }
|
|
4861
|
-
},
|
|
4862
|
-
required: ["plan"]
|
|
4863
|
-
}
|
|
4864
|
-
}
|
|
4865
|
-
};
|
|
4866
|
-
enterPlanModeToolSchema = {
|
|
4867
|
-
type: "function",
|
|
4868
|
-
function: {
|
|
4869
|
-
name: "enter_plan_mode",
|
|
4870
|
-
description: "\u81EA\u4E3B\u8FDB\u5165\u8BA1\u5212\u6A21\u5F0F\uFF1A\u5F53\u4EFB\u52A1\u662F\u975E\u5E73\u51E1\u7684\u5B9E\u73B0\u4EFB\u52A1\uFF08\u591A\u6587\u4EF6\u6539\u52A8\u3001\u67B6\u6784\u51B3\u7B56\u3001\u4E0D\u786E\u5B9A\u8DEF\u5F84\u3001\u9AD8\u98CE\u9669\u64CD\u4F5C\uFF09\u65F6\u8C03\u7528\u3002\u8C03\u7528\u540E\u672C\u8F6E\u7ED3\u675F\u5E76\u8FDB\u5165\u53EA\u8BFB\u8C03\u7814\u9636\u6BB5\u2014\u2014\u4F60\u53EA\u80FD\u8BFB\u53D6\u4E0E\u641C\u7D22\uFF0C\u4EA7\u51FA\u5B8C\u6574\u5B9E\u73B0\u65B9\u6848\uFF08\u8981\u6539\u54EA\u4E9B\u6587\u4EF6\u3001\u600E\u4E48\u6539\u3001\u4E3A\u4F55\u3001\u98CE\u9669\uFF09\u7ECF\u7528\u6237\u5BA1\u6279\u540E\u518D\u5B9E\u73B0\u3002\u7B80\u5355\u4EFB\u52A1\u65E0\u9700\u8C03\u7528\uFF0C\u76F4\u63A5\u5B9E\u73B0\u3002",
|
|
4871
|
-
parameters: {
|
|
4872
|
-
type: "object",
|
|
4873
|
-
properties: {
|
|
4874
|
-
reason: { type: "string", description: "\u4E3A\u4F55\u8981\u8FDB\u5165\u8BA1\u5212\u6A21\u5F0F\uFF08\u4EFB\u52A1\u7684\u590D\u6742\u70B9\u3001\u9700\u5148\u5398\u6E05\u7684\u5173\u952E\u95EE\u9898\uFF09" }
|
|
4875
|
-
},
|
|
4876
|
-
required: ["reason"]
|
|
4877
|
-
}
|
|
4878
|
-
}
|
|
4879
|
-
};
|
|
4880
|
-
PLAN_MODE_AUTO_ENTER_HINT = `\u3010\u4EFB\u52A1\u5206\u7C7B\uFF08\u6536\u5230\u5B9E\u73B0\u7C7B\u8BF7\u6C42\u65F6\u7684\u9996\u4E2A\u52A8\u4F5C\uFF09\u3011\u5148\u5224\u65AD\u590D\u6742\u5EA6\uFF0C\u518D\u51B3\u5B9A\u662F\u5426\u5148\u89C4\u5212\uFF1A
|
|
4881
|
-
- **\u975E\u5E73\u51E1\u4EFB\u52A1**\uFF08\u6EE1\u8DB3\u4EFB\u4E00\u5373\u7B97\uFF1A\u6D89\u53CA\u591A\u4E2A\u6587\u4EF6\u6539\u52A8 / \u9700\u8981\u67B6\u6784\u51B3\u7B56 / \u5B9E\u73B0\u8DEF\u5F84\u4E0D\u786E\u5B9A / \u9AD8\u98CE\u9669\u64CD\u4F5C / \u9884\u4F30 \u22653 \u4E2A\u6B65\u9AA4\uFF09\u2192 **\u9ED8\u8BA4\u5148\u8C03\u7528 enter_plan_mode \u8FDB\u5165\u8BA1\u5212\u6A21\u5F0F**\uFF1A\u4EE5\u53EA\u8BFB\u65B9\u5F0F\u4E13\u6CE8\u8C03\u7814\u3001\u7406\u6E05\u73B0\u72B6\u4E0E\u6539\u9020\u70B9\uFF0C\u518D\u8C03\u7528 exit_plan_mode \u63D0\u4EA4\u5B8C\u6574\u5B9E\u73B0\u65B9\u6848\uFF08\u8981\u6539\u54EA\u4E9B\u6587\u4EF6\u3001\u5177\u4F53\u600E\u4E48\u6539\u3001\u4E3A\u4F55\u8FD9\u4E48\u505A\u3001\u6709\u4EC0\u4E48\u98CE\u9669\u4E0E\u53D6\u820D\uFF09\uFF0C\u65B9\u6848\u7ECF\u7528\u6237\u5BA1\u6279\u540E\u624D\u8FDB\u5165\u5B9E\u73B0\u9636\u6BB5\u3002
|
|
4882
|
-
- **\u7B80\u5355\u4EFB\u52A1**\uFF08\u5355\u6587\u4EF6\u3001\u5355\u884C\u4FEE\u590D\u3001\u660E\u786E\u7684\u5C0F\u8C03\u6574\u3001\u7EAF\u67E5\u8BE2\u6216\u89E3\u91CA\uFF09\u2192 \u65E0\u9700\u89C4\u5212\uFF0C\u76F4\u63A5\u5B9E\u73B0\u6216\u4F5C\u7B54\u3002
|
|
4883
|
-
- \u5224\u636E\u793A\u4F8B\uFF1A\u300C\u65B0\u589E/\u5B9E\u73B0\u4E00\u4E2A\u529F\u80FD\u6A21\u5757\u300D\u300C\u91CD\u6784/\u6539\u9020 XX \u5B50\u7CFB\u7EDF\u300D\u300C\u628A A \u8FC1\u79FB\u5230 B\u300D\u300C\u8C03\u6574\u6574\u4F53\u6570\u636E\u6D41\u300D\u2192 \u975E\u5E73\u51E1\uFF0C\u5148\u89C4\u5212\uFF1B\u300C\u6539\u4E00\u4E0B\u7B2C N \u884C\u7684\u53D8\u91CF\u540D\u300D\u300C\u89E3\u91CA\u8FD9\u6BB5\u4EE3\u7801\u300D\u300C\u8DD1\u4E00\u4E0B\u6D4B\u8BD5\u300D\u2192 \u7B80\u5355\uFF0C\u76F4\u63A5\u505A\u3002`;
|
|
4884
|
-
}
|
|
4885
|
-
});
|
|
4886
|
-
|
|
4887
5217
|
// ../core/src/agent/toolFilter.ts
|
|
4888
5218
|
async function filterByEnvironment(tools, ctx) {
|
|
4889
5219
|
const out = [];
|
|
@@ -4908,7 +5238,7 @@ var init_toolFilter = __esm({
|
|
|
4908
5238
|
});
|
|
4909
5239
|
|
|
4910
5240
|
// ../core/src/common/registry.ts
|
|
4911
|
-
import
|
|
5241
|
+
import fs13 from "fs/promises";
|
|
4912
5242
|
var createRegistry, filterSources, scanSources;
|
|
4913
5243
|
var init_registry2 = __esm({
|
|
4914
5244
|
"../core/src/common/registry.ts"() {
|
|
@@ -4938,7 +5268,7 @@ var init_registry2 = __esm({
|
|
|
4938
5268
|
for (const s of sources) {
|
|
4939
5269
|
let entries;
|
|
4940
5270
|
try {
|
|
4941
|
-
entries = await
|
|
5271
|
+
entries = await fs13.readdir(s.dir, { withFileTypes: true });
|
|
4942
5272
|
} catch {
|
|
4943
5273
|
continue;
|
|
4944
5274
|
}
|
|
@@ -5035,8 +5365,8 @@ ${AGENT_USAGE_HINT}`);
|
|
|
5035
5365
|
});
|
|
5036
5366
|
|
|
5037
5367
|
// ../core/src/projectGuide/loader.ts
|
|
5038
|
-
import
|
|
5039
|
-
import
|
|
5368
|
+
import fs14 from "fs/promises";
|
|
5369
|
+
import path16 from "path";
|
|
5040
5370
|
var CANDIDATES, MAX_GUIDE_BYTES, cached, initProjectGuide, getProjectGuide;
|
|
5041
5371
|
var init_loader2 = __esm({
|
|
5042
5372
|
"../core/src/projectGuide/loader.ts"() {
|
|
@@ -5053,7 +5383,7 @@ var init_loader2 = __esm({
|
|
|
5053
5383
|
try {
|
|
5054
5384
|
for (const name of CANDIDATES) {
|
|
5055
5385
|
try {
|
|
5056
|
-
const raw = await
|
|
5386
|
+
const raw = await fs14.readFile(path16.join(WORKSPACE_ROOT, name), "utf-8");
|
|
5057
5387
|
const body = raw.length > MAX_GUIDE_BYTES ? raw.slice(0, MAX_GUIDE_BYTES) + `
|
|
5058
5388
|
|
|
5059
5389
|
\u2026[\u9879\u76EE\u6307\u5F15\u8D85 ${MAX_GUIDE_BYTES} \u5B57\u8282\u5DF2\u622A\u65AD\uFF0C\u5B8C\u6574\u5185\u5BB9\u53EF\u8C03\u7528 read_project_guide \u83B7\u53D6]` : raw;
|
|
@@ -5378,9 +5708,9 @@ var init_agent = __esm({
|
|
|
5378
5708
|
});
|
|
5379
5709
|
|
|
5380
5710
|
// ../core/src/tool/worktree/manager.ts
|
|
5381
|
-
import
|
|
5711
|
+
import path17 from "path";
|
|
5382
5712
|
import os4 from "os";
|
|
5383
|
-
import
|
|
5713
|
+
import fs15 from "fs";
|
|
5384
5714
|
var runMainGit, worktreeRootDir, worktreeDir, isNotARepoError, createWorktree, harvestDiff, runInWorktree, removeWorktree, sweepOrphanedWorktrees, disposeAllSessionWorktrees;
|
|
5385
5715
|
var init_manager = __esm({
|
|
5386
5716
|
"../core/src/tool/worktree/manager.ts"() {
|
|
@@ -5391,8 +5721,8 @@ var init_manager = __esm({
|
|
|
5391
5721
|
init_background();
|
|
5392
5722
|
init_sessionRegistry();
|
|
5393
5723
|
runMainGit = (args, maxBuffer = 1024 * 1024 * 5) => execFileSmart("git", args, { cwd: WORKSPACE_ROOT, maxBuffer });
|
|
5394
|
-
worktreeRootDir = () =>
|
|
5395
|
-
worktreeDir = (sessionId, stepId) =>
|
|
5724
|
+
worktreeRootDir = () => path17.join(os4.tmpdir(), "deepseeker-code-worktrees", appConfig.userWorkspaceDir);
|
|
5725
|
+
worktreeDir = (sessionId, stepId) => path17.join(worktreeRootDir(), sessionId, stepId);
|
|
5396
5726
|
isNotARepoError = (e) => {
|
|
5397
5727
|
const text = `${e?.message || ""} ${e?.stderr || ""}`.toLowerCase();
|
|
5398
5728
|
return text.includes("not a git repository");
|
|
@@ -5403,12 +5733,12 @@ var init_manager = __esm({
|
|
|
5403
5733
|
const wtPath = worktreeDir(sessionId, stepId);
|
|
5404
5734
|
const shortId = sessionId.replace(/[^A-Za-z0-9-]/g, "").slice(0, 8) || "x";
|
|
5405
5735
|
const branch = `dsc-wt-${shortId}-${stepId}`;
|
|
5406
|
-
await
|
|
5736
|
+
await fs15.promises.mkdir(path17.dirname(wtPath), { recursive: true });
|
|
5407
5737
|
try {
|
|
5408
5738
|
await runMainGit(["worktree", "add", "-b", branch, wtPath, "HEAD"]);
|
|
5409
5739
|
} catch (e) {
|
|
5410
5740
|
if (e?.code === "ENOENT" || /already exists|not a working tree/i.test(`${e?.stderr || ""} ${e?.message || ""}`)) {
|
|
5411
|
-
await
|
|
5741
|
+
await fs15.promises.rm(wtPath, { recursive: true, force: true }).catch(() => {
|
|
5412
5742
|
});
|
|
5413
5743
|
await runMainGit(["worktree", "add", "-b", branch, wtPath, "HEAD"]);
|
|
5414
5744
|
} else {
|
|
@@ -5456,7 +5786,7 @@ var init_manager = __esm({
|
|
|
5456
5786
|
try {
|
|
5457
5787
|
await runMainGit(["worktree", "remove", "--force", wt.path]);
|
|
5458
5788
|
} catch (e) {
|
|
5459
|
-
await
|
|
5789
|
+
await fs15.promises.rm(wt.path, { recursive: true, force: true }).catch(() => {
|
|
5460
5790
|
});
|
|
5461
5791
|
}
|
|
5462
5792
|
try {
|
|
@@ -5473,30 +5803,30 @@ var init_manager = __esm({
|
|
|
5473
5803
|
const root = worktreeRootDir();
|
|
5474
5804
|
let entries;
|
|
5475
5805
|
try {
|
|
5476
|
-
entries = await
|
|
5806
|
+
entries = await fs15.promises.readdir(root);
|
|
5477
5807
|
} catch {
|
|
5478
5808
|
return;
|
|
5479
5809
|
}
|
|
5480
5810
|
let swept = 0;
|
|
5481
5811
|
for (const sessionIdDir of entries) {
|
|
5482
|
-
const sessionPath =
|
|
5812
|
+
const sessionPath = path17.join(root, sessionIdDir);
|
|
5483
5813
|
let stepDirs;
|
|
5484
5814
|
try {
|
|
5485
|
-
stepDirs = await
|
|
5815
|
+
stepDirs = await fs15.promises.readdir(sessionPath);
|
|
5486
5816
|
} catch {
|
|
5487
5817
|
continue;
|
|
5488
5818
|
}
|
|
5489
5819
|
for (const stepDir of stepDirs) {
|
|
5490
|
-
const wtPath =
|
|
5820
|
+
const wtPath = path17.join(sessionPath, stepDir);
|
|
5491
5821
|
try {
|
|
5492
5822
|
await runMainGit(["worktree", "remove", "--force", wtPath]);
|
|
5493
5823
|
} catch {
|
|
5494
|
-
await
|
|
5824
|
+
await fs15.promises.rm(wtPath, { recursive: true, force: true }).catch(() => {
|
|
5495
5825
|
});
|
|
5496
5826
|
}
|
|
5497
5827
|
swept++;
|
|
5498
5828
|
}
|
|
5499
|
-
await
|
|
5829
|
+
await fs15.promises.rm(sessionPath, { recursive: true, force: true }).catch(() => {
|
|
5500
5830
|
});
|
|
5501
5831
|
}
|
|
5502
5832
|
if (swept > 0) {
|
|
@@ -5765,7 +6095,7 @@ var init_workflow = __esm({
|
|
|
5765
6095
|
|
|
5766
6096
|
// ../core/src/tool/tsHost.ts
|
|
5767
6097
|
import fsSync3 from "fs";
|
|
5768
|
-
import
|
|
6098
|
+
import path18 from "path";
|
|
5769
6099
|
var _ts, _tsTried, getTs, buildDefaultOptions, findTsConfigBounded, tsconfigWalkCache, tsconfigParseCache, resolveTsConfig, createProjectHost, lsCache, getLanguageService, realpathNative, posToLineCol, SUPPORTED_SOURCE_EXTS, checkSupportedSourceExt, lineColToPos;
|
|
5770
6100
|
var init_tsHost = __esm({
|
|
5771
6101
|
"../core/src/tool/tsHost.ts"() {
|
|
@@ -5784,10 +6114,10 @@ var init_tsHost = __esm({
|
|
|
5784
6114
|
}
|
|
5785
6115
|
return _ts;
|
|
5786
6116
|
};
|
|
5787
|
-
buildDefaultOptions = (
|
|
5788
|
-
target:
|
|
5789
|
-
module:
|
|
5790
|
-
moduleResolution:
|
|
6117
|
+
buildDefaultOptions = (ts2) => ({
|
|
6118
|
+
target: ts2.ScriptTarget.ESNext,
|
|
6119
|
+
module: ts2.ModuleKind.ESNext,
|
|
6120
|
+
moduleResolution: ts2.ModuleResolutionKind.Bundler,
|
|
5791
6121
|
allowJs: true,
|
|
5792
6122
|
checkJs: false,
|
|
5793
6123
|
esModuleInterop: true,
|
|
@@ -5795,20 +6125,20 @@ var init_tsHost = __esm({
|
|
|
5795
6125
|
resolveJsonModule: true,
|
|
5796
6126
|
skipLibCheck: true,
|
|
5797
6127
|
noEmit: true,
|
|
5798
|
-
jsx:
|
|
6128
|
+
jsx: ts2.JsxEmit.ReactJSX,
|
|
5799
6129
|
strict: false
|
|
5800
6130
|
});
|
|
5801
|
-
findTsConfigBounded = (
|
|
5802
|
-
const root =
|
|
5803
|
-
let dir =
|
|
6131
|
+
findTsConfigBounded = (ts2, absPath) => {
|
|
6132
|
+
const root = path18.resolve(getContainingRoot(absPath));
|
|
6133
|
+
let dir = path18.dirname(absPath);
|
|
5804
6134
|
while (true) {
|
|
5805
|
-
const candidate =
|
|
6135
|
+
const candidate = path18.join(dir, "tsconfig.json");
|
|
5806
6136
|
try {
|
|
5807
6137
|
if (fsSync3.existsSync(candidate)) return candidate;
|
|
5808
6138
|
} catch {
|
|
5809
6139
|
}
|
|
5810
|
-
if (
|
|
5811
|
-
const parent =
|
|
6140
|
+
if (path18.resolve(dir) === root) break;
|
|
6141
|
+
const parent = path18.dirname(dir);
|
|
5812
6142
|
if (parent === dir) break;
|
|
5813
6143
|
dir = parent;
|
|
5814
6144
|
}
|
|
@@ -5816,15 +6146,15 @@ var init_tsHost = __esm({
|
|
|
5816
6146
|
};
|
|
5817
6147
|
tsconfigWalkCache = /* @__PURE__ */ new Map();
|
|
5818
6148
|
tsconfigParseCache = /* @__PURE__ */ new Map();
|
|
5819
|
-
resolveTsConfig = (
|
|
5820
|
-
const startDir =
|
|
6149
|
+
resolveTsConfig = (ts2, absPath) => {
|
|
6150
|
+
const startDir = path18.dirname(absPath);
|
|
5821
6151
|
let tsConfigPath = tsconfigWalkCache.get(startDir);
|
|
5822
6152
|
if (!tsConfigPath) {
|
|
5823
|
-
tsConfigPath = findTsConfigBounded(
|
|
6153
|
+
tsConfigPath = findTsConfigBounded(ts2, absPath) ?? "";
|
|
5824
6154
|
if (tsConfigPath) tsconfigWalkCache.set(startDir, tsConfigPath);
|
|
5825
6155
|
}
|
|
5826
6156
|
if (!tsConfigPath) {
|
|
5827
|
-
return { options: buildDefaultOptions(
|
|
6157
|
+
return { options: buildDefaultOptions(ts2), fileNames: [], projectRoot: getContainingRoot(absPath) };
|
|
5828
6158
|
}
|
|
5829
6159
|
let st;
|
|
5830
6160
|
try {
|
|
@@ -5837,22 +6167,22 @@ var init_tsHost = __esm({
|
|
|
5837
6167
|
if (!st) {
|
|
5838
6168
|
tsconfigParseCache.delete(tsConfigPath);
|
|
5839
6169
|
for (const [dir, p] of tsconfigWalkCache) if (p === tsConfigPath) tsconfigWalkCache.delete(dir);
|
|
5840
|
-
return resolveTsConfig(
|
|
6170
|
+
return resolveTsConfig(ts2, absPath);
|
|
5841
6171
|
}
|
|
5842
|
-
const basePath =
|
|
5843
|
-
const raw =
|
|
5844
|
-
if (raw.error) return { options: buildDefaultOptions(
|
|
5845
|
-
const parsed =
|
|
6172
|
+
const basePath = path18.dirname(tsConfigPath);
|
|
6173
|
+
const raw = ts2.readConfigFile(tsConfigPath, ts2.sys.readFile);
|
|
6174
|
+
if (raw.error) return { options: buildDefaultOptions(ts2), fileNames: [], projectRoot: basePath };
|
|
6175
|
+
const parsed = ts2.parseJsonConfigFileContent(raw.config, ts2.sys, basePath);
|
|
5846
6176
|
const resolved = { options: parsed.options, fileNames: parsed.fileNames, projectRoot: basePath };
|
|
5847
6177
|
tsconfigParseCache.set(tsConfigPath, { mtimeMs: st.mtimeMs, resolved });
|
|
5848
6178
|
return resolved;
|
|
5849
6179
|
};
|
|
5850
|
-
createProjectHost = (
|
|
6180
|
+
createProjectHost = (ts2, projectRoot, options, rootFileNames) => {
|
|
5851
6181
|
const cache = /* @__PURE__ */ new Map();
|
|
5852
6182
|
const roots = /* @__PURE__ */ new Set();
|
|
5853
|
-
const caseSensitive =
|
|
6183
|
+
const caseSensitive = ts2.sys.useCaseSensitiveFileNames;
|
|
5854
6184
|
const canonical = (f) => caseSensitive ? f : f.toLowerCase();
|
|
5855
|
-
const keyOf = (f) => canonical(
|
|
6185
|
+
const keyOf = (f) => canonical(path18.resolve(f)).replace(/\\/g, "/");
|
|
5856
6186
|
rootFileNames.forEach((f) => roots.add(keyOf(f)));
|
|
5857
6187
|
const fresh = (fileName) => {
|
|
5858
6188
|
const key = keyOf(fileName);
|
|
@@ -5873,7 +6203,7 @@ var init_tsHost = __esm({
|
|
|
5873
6203
|
}
|
|
5874
6204
|
const entry = {
|
|
5875
6205
|
version: (cached2?.version ?? 0) + 1,
|
|
5876
|
-
snapshot:
|
|
6206
|
+
snapshot: ts2.ScriptSnapshot.fromString(text),
|
|
5877
6207
|
mtimeMs: st.mtimeMs
|
|
5878
6208
|
};
|
|
5879
6209
|
cache.set(key, entry);
|
|
@@ -5888,14 +6218,14 @@ var init_tsHost = __esm({
|
|
|
5888
6218
|
},
|
|
5889
6219
|
getScriptSnapshot: (f) => fresh(f)?.snapshot,
|
|
5890
6220
|
getCurrentDirectory: () => projectRoot,
|
|
5891
|
-
getDefaultLibFileName: (o) =>
|
|
5892
|
-
useCaseSensitiveFileNames: () =>
|
|
6221
|
+
getDefaultLibFileName: (o) => ts2.getDefaultLibFilePath(o),
|
|
6222
|
+
useCaseSensitiveFileNames: () => ts2.sys.useCaseSensitiveFileNames,
|
|
5893
6223
|
// 模块解析委派 ts.sys(穿 node_modules 解析 import 必需)
|
|
5894
|
-
fileExists:
|
|
5895
|
-
readFile:
|
|
5896
|
-
directoryExists:
|
|
5897
|
-
getDirectories:
|
|
5898
|
-
realpath:
|
|
6224
|
+
fileExists: ts2.sys.fileExists,
|
|
6225
|
+
readFile: ts2.sys.readFile,
|
|
6226
|
+
directoryExists: ts2.sys.directoryExists,
|
|
6227
|
+
getDirectories: ts2.sys.getDirectories,
|
|
6228
|
+
realpath: ts2.sys.realpath,
|
|
5899
6229
|
// 自定义扩展:把查询目标登记为 program 根文件(确保被纳入分析)
|
|
5900
6230
|
addRoot: (absPath) => {
|
|
5901
6231
|
roots.add(keyOf(absPath));
|
|
@@ -5903,19 +6233,19 @@ var init_tsHost = __esm({
|
|
|
5903
6233
|
};
|
|
5904
6234
|
};
|
|
5905
6235
|
lsCache = /* @__PURE__ */ new Map();
|
|
5906
|
-
getLanguageService = async (
|
|
5907
|
-
const { options, fileNames, projectRoot } = resolveTsConfig(
|
|
6236
|
+
getLanguageService = async (ts2, absPath, opts) => {
|
|
6237
|
+
const { options, fileNames, projectRoot } = resolveTsConfig(ts2, absPath);
|
|
5908
6238
|
const checkJs = opts?.checkJs === true;
|
|
5909
6239
|
const key = `${projectRoot}::${checkJs}`;
|
|
5910
6240
|
let p = lsCache.get(key);
|
|
5911
6241
|
if (!p) {
|
|
5912
6242
|
p = (async () => {
|
|
5913
6243
|
const finalOptions = { ...options, ...checkJs ? { checkJs: true } : {} };
|
|
5914
|
-
if (!
|
|
6244
|
+
if (!ts2.sys.useCaseSensitiveFileNames) {
|
|
5915
6245
|
finalOptions.forceConsistentCasingInFileNames = false;
|
|
5916
6246
|
}
|
|
5917
|
-
const host = createProjectHost(
|
|
5918
|
-
const ls =
|
|
6247
|
+
const host = createProjectHost(ts2, projectRoot, finalOptions, fileNames);
|
|
6248
|
+
const ls = ts2.createLanguageService(host);
|
|
5919
6249
|
return { ls, host, projectRoot };
|
|
5920
6250
|
})();
|
|
5921
6251
|
lsCache.set(key, p);
|
|
@@ -5931,23 +6261,23 @@ var init_tsHost = __esm({
|
|
|
5931
6261
|
return p;
|
|
5932
6262
|
}
|
|
5933
6263
|
};
|
|
5934
|
-
posToLineCol = (
|
|
5935
|
-
const { line, character } =
|
|
6264
|
+
posToLineCol = (ts2, sf, pos) => {
|
|
6265
|
+
const { line, character } = ts2.getLineAndCharacterOfPosition(sf, pos);
|
|
5936
6266
|
return { line: line + 1, column: character + 1 };
|
|
5937
6267
|
};
|
|
5938
6268
|
SUPPORTED_SOURCE_EXTS = /* @__PURE__ */ new Set([".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"]);
|
|
5939
6269
|
checkSupportedSourceExt = (displayPath) => {
|
|
5940
|
-
const ext =
|
|
6270
|
+
const ext = path18.extname(displayPath).toLowerCase();
|
|
5941
6271
|
if (SUPPORTED_SOURCE_EXTS.has(ext)) return null;
|
|
5942
6272
|
return toolFailure(`[\u6587\u4EF6\u7C7B\u578B\u4E0D\u652F\u6301]\uFF1A[${displayPath}] \u7684\u6269\u5C55\u540D ${ext || "(\u65E0)"} \u4E0D\u5728 TS \u5F15\u64CE\u652F\u6301\u8303\u56F4\uFF08\u4EC5 .ts/.tsx/.js/.jsx/.mjs/.cjs\uFF09\u3002\u8BF7\u6539\u7528 read_file/grep \u67E5\u770B\u5185\u5BB9\uFF1B\u7F16\u8BD1/\u7C7B\u578B\u7C7B\u9A8C\u8BC1\u7528 run_command \u8DD1\u5BF9\u5E94\u8BED\u8A00\u5DE5\u5177\u94FE\uFF08\u5982 mvn compile / tsc --noEmit\uFF09\u3002`);
|
|
5943
6273
|
};
|
|
5944
|
-
lineColToPos = (
|
|
6274
|
+
lineColToPos = (ts2, sf, line1, col1) => ts2.getPositionOfLineAndCharacter(sf, Math.max(0, line1 - 1), Math.max(0, col1 - 1));
|
|
5945
6275
|
}
|
|
5946
6276
|
});
|
|
5947
6277
|
|
|
5948
6278
|
// ../core/src/tool/registry/fs.ts
|
|
5949
|
-
import
|
|
5950
|
-
import
|
|
6279
|
+
import fs16 from "fs/promises";
|
|
6280
|
+
import path19 from "path";
|
|
5951
6281
|
import { createReadStream } from "fs";
|
|
5952
6282
|
import * as readline from "readline";
|
|
5953
6283
|
var IMAGE_MIME_BY_EXT, isSensitiveReadTarget, stripReadFileLineNumbers, maskSecretsInContent, makeTmpPath, ATOMIC_TMP_RE, sweepStaleAtomicTmp, assertReadable, stripEdgeBlankLines, matchLineBlockWith, diagnoseOldStr, reindentToBase, alignIndentsByAnchor, applyOneEditToContent, fsTools;
|
|
@@ -6012,21 +6342,21 @@ var init_fs = __esm({
|
|
|
6012
6342
|
const walk = async (dir) => {
|
|
6013
6343
|
let entries;
|
|
6014
6344
|
try {
|
|
6015
|
-
entries = await
|
|
6345
|
+
entries = await fs16.readdir(dir, { withFileTypes: true });
|
|
6016
6346
|
} catch {
|
|
6017
6347
|
return;
|
|
6018
6348
|
}
|
|
6019
6349
|
for (const e of entries) {
|
|
6020
|
-
const full =
|
|
6350
|
+
const full = path19.join(dir, e.name);
|
|
6021
6351
|
if (e.isDirectory()) {
|
|
6022
6352
|
if (!skipDirs.has(e.name)) await walk(full);
|
|
6023
6353
|
continue;
|
|
6024
6354
|
}
|
|
6025
6355
|
if (!e.isFile() || !ATOMIC_TMP_RE.test(e.name)) continue;
|
|
6026
6356
|
try {
|
|
6027
|
-
const st = await
|
|
6357
|
+
const st = await fs16.stat(full);
|
|
6028
6358
|
if (st.mtimeMs > cutoff) continue;
|
|
6029
|
-
await
|
|
6359
|
+
await fs16.unlink(full);
|
|
6030
6360
|
removed++;
|
|
6031
6361
|
} catch {
|
|
6032
6362
|
}
|
|
@@ -6230,7 +6560,7 @@ var init_fs = __esm({
|
|
|
6230
6560
|
try {
|
|
6231
6561
|
const absPath = resolveReadablePath(args.path);
|
|
6232
6562
|
const lowerExt = absPath.toLowerCase();
|
|
6233
|
-
if (IMAGE_MIME_BY_EXT[
|
|
6563
|
+
if (IMAGE_MIME_BY_EXT[path19.extname(lowerExt)]) return `\u{1F5BC} [${args.path}] \u662F\u56FE\u7247\u6587\u4EF6\uFF0Cread_file \u8BFB\u4E0D\u51FA\u6709\u7528\u5185\u5BB9\u3002\u8BF7\u6539\u7528 read_image \u8BFB\u53D6\uFF08\u56FE\u50CF\u4F1A\u4EE5\u89C6\u89C9\u9644\u4EF6\u76F4\u63A5\u63D0\u4F9B\u7ED9\u6A21\u578B\u5206\u6790\uFF09\u3002`;
|
|
6234
6564
|
if (lowerExt.endsWith(".xlsx")) return `\u26A0\uFE0F [${args.path}] \u662F Excel \u4E8C\u8FDB\u5236\u6587\u4EF6\uFF0Cread_file \u8BFB\u4E0D\u4E86\uFF08UTF-8 \u89E3\u7801\u6EE1\u5C4F\u4E71\u7801\uFF09\u3002\u8BF7\u6539\u7528 read_xlsx\uFF08\u652F\u6301 sheet \u9009\u62E9 / \u7FFB\u9875 / Markdown \u8868\u683C\u8F93\u51FA\uFF09\u3002`;
|
|
6235
6565
|
if (lowerExt.endsWith(".docx")) return `\u26A0\uFE0F [${args.path}] \u662F Word \u4E8C\u8FDB\u5236\u6587\u6863\uFF0Cread_file \u8BFB\u4E0D\u4E86\u3002\u8BF7\u6539\u7528 read_docx \u63D0\u53D6\u6B63\u6587\u6587\u672C\u3002`;
|
|
6236
6566
|
if (lowerExt.endsWith(".pdf")) return `\u26A0\uFE0F [${args.path}] \u662F PDF \u4E8C\u8FDB\u5236\u6587\u6863\uFF0Cread_file \u8BFB\u4E0D\u4E86\u3002\u8BF7\u6539\u7528 read_pdf \u63D0\u53D6\u6587\u5B57\u5C42\u3002`;
|
|
@@ -6263,7 +6593,7 @@ var init_fs = __esm({
|
|
|
6263
6593
|
let readStamp = "";
|
|
6264
6594
|
if (toolCtx?.readTracker) {
|
|
6265
6595
|
try {
|
|
6266
|
-
const st = await
|
|
6596
|
+
const st = await fs16.stat(absPath);
|
|
6267
6597
|
const prev = toolCtx.readTracker.get(absPath);
|
|
6268
6598
|
const count = (prev?.count ?? 0) + 1;
|
|
6269
6599
|
const changed = prev !== void 0 && prev.mtimeMs !== st.mtimeMs;
|
|
@@ -6309,11 +6639,11 @@ ${formattedCode}${hasMore ? `
|
|
|
6309
6639
|
await initializeWorkspaceIgnore();
|
|
6310
6640
|
const buildTreeText = async (currentPath, currentDepth, prefix = "") => {
|
|
6311
6641
|
if (currentDepth > maxDepth || hitScanLimit) return "";
|
|
6312
|
-
const entries = await
|
|
6642
|
+
const entries = await fs16.readdir(currentPath, { withFileTypes: true });
|
|
6313
6643
|
const validEntries = entries.filter((entry) => {
|
|
6314
6644
|
if (entry.isSymbolicLink()) return false;
|
|
6315
|
-
const fullPath =
|
|
6316
|
-
const relPath =
|
|
6645
|
+
const fullPath = path19.join(currentPath, entry.name);
|
|
6646
|
+
const relPath = path19.relative(getActiveWorkspaceRoot(), fullPath).replace(/\\/g, "/");
|
|
6317
6647
|
return !checkIsPathIgnored(entry.isDirectory() ? `${relPath}/` : relPath);
|
|
6318
6648
|
});
|
|
6319
6649
|
let output = "";
|
|
@@ -6332,7 +6662,7 @@ ${formattedCode}${hasMore ? `
|
|
|
6332
6662
|
`;
|
|
6333
6663
|
if (entry.isDirectory()) {
|
|
6334
6664
|
const nextPrefix = prefix + (isLast ? " " : "\u2502 ");
|
|
6335
|
-
const fullPath =
|
|
6665
|
+
const fullPath = path19.join(currentPath, entry.name);
|
|
6336
6666
|
const subTree = await buildTreeText(fullPath, currentDepth + 1, nextPrefix);
|
|
6337
6667
|
output += subTree;
|
|
6338
6668
|
}
|
|
@@ -6400,7 +6730,7 @@ ${patches}`;
|
|
|
6400
6730
|
return toolFailure(`[\u53C2\u6570\u7F3A\u5931]\uFF1A\u8BF7\u4F20\u5165 edits \u6570\u7EC4\uFF08\u6BCF\u6761\u542B old_str/new_str\uFF09\u4E00\u6B21\u5B8C\u6210\u591A\u5904\u4FEE\u6539\uFF0C\u6216\u9876\u5C42 old_str + new_str \u4FEE\u6539\u5355\u5904\u3002old_str \u4E0D\u80FD\u4E3A\u7A7A\u3002`);
|
|
6401
6731
|
}
|
|
6402
6732
|
const absPath = resolveSafePath(args.path);
|
|
6403
|
-
const rawContent = await
|
|
6733
|
+
const rawContent = await fs16.readFile(absPath, "utf-8");
|
|
6404
6734
|
const isCRLF = rawContent.includes("\r\n");
|
|
6405
6735
|
let content = rawContent.replace(/\r\n/g, "\n");
|
|
6406
6736
|
const summaries = [];
|
|
@@ -6413,7 +6743,7 @@ ${patches}`;
|
|
|
6413
6743
|
summaries.push(editList.length === 1 ? r.summary : ` ${i + 1}. ${r.summary}`);
|
|
6414
6744
|
}
|
|
6415
6745
|
assertWithinWorkspace(absPath);
|
|
6416
|
-
await
|
|
6746
|
+
await fs16.writeFile(absPath, isCRLF ? content.replace(/\n/g, "\r\n") : content, "utf-8");
|
|
6417
6747
|
return editList.length === 1 ? `\u2705 [\u4EE3\u7801\u4FEE\u8865\u6210\u529F]\uFF1A\u6587\u4EF6 [${args.path}] ${summaries[0]}` : `\u2705 [\u4EE3\u7801\u4FEE\u8865\u6210\u529F]\uFF1A\u6587\u4EF6 [${args.path}] \u5DF2\u6309\u5E8F\u5B8C\u6210 ${editList.length} \u5904\u4FEE\u6539\uFF08\u5355\u6B21\u539F\u5B50\u5199\u5165\uFF09\uFF1A
|
|
6418
6748
|
${summaries.join("\n")}`;
|
|
6419
6749
|
} catch (error) {
|
|
@@ -6446,24 +6776,24 @@ ${summaries.join("\n")}`;
|
|
|
6446
6776
|
try {
|
|
6447
6777
|
const absPath = resolveSafePath(args.path);
|
|
6448
6778
|
try {
|
|
6449
|
-
await
|
|
6779
|
+
await fs16.access(absPath);
|
|
6450
6780
|
return toolFailure(`[\u521B\u5EFA\u5931\u8D25]\uFF1A\u6587\u4EF6 [${args.path}] \u5DF2\u5B58\u5728\u3002create_file \u4EC5\u7528\u4E8E\u65B0\u5EFA\u6587\u4EF6\uFF1B\u5982\u9700\u4FEE\u6539\u8BF7\u7528 edit_file\uFF0C\u5982\u9700\u8986\u76D6\u8BF7\u7528 write_file\u3002`);
|
|
6451
6781
|
} catch (e) {
|
|
6452
6782
|
if (e?.code !== "ENOENT") throw e;
|
|
6453
6783
|
}
|
|
6454
6784
|
const content = args.content ?? "";
|
|
6455
6785
|
assertWithinWorkspace(absPath);
|
|
6456
|
-
await
|
|
6786
|
+
await fs16.mkdir(path19.dirname(absPath), { recursive: true });
|
|
6457
6787
|
tmpPath = makeTmpPath(absPath);
|
|
6458
|
-
await
|
|
6459
|
-
await
|
|
6788
|
+
await fs16.writeFile(tmpPath, content, "utf-8");
|
|
6789
|
+
await fs16.rename(tmpPath, absPath);
|
|
6460
6790
|
return `\u2705 [\u521B\u5EFA\u6210\u529F]\uFF1A\u65B0\u6587\u4EF6 [${args.path}] \u5DF2\u521B\u5EFA\uFF0C\u5199\u5165 ${content.length} \u5B57\u7B26\u3002`;
|
|
6461
6791
|
} catch (error) {
|
|
6462
6792
|
return toolFailure(`\u64CD\u4F5C\u5931\u8D25: ${error.message}`);
|
|
6463
6793
|
} finally {
|
|
6464
6794
|
if (tmpPath) {
|
|
6465
6795
|
try {
|
|
6466
|
-
await
|
|
6796
|
+
await fs16.unlink(tmpPath);
|
|
6467
6797
|
} catch {
|
|
6468
6798
|
}
|
|
6469
6799
|
}
|
|
@@ -6495,7 +6825,7 @@ ${summaries.join("\n")}`;
|
|
|
6495
6825
|
}
|
|
6496
6826
|
let rel = "";
|
|
6497
6827
|
try {
|
|
6498
|
-
rel =
|
|
6828
|
+
rel = path19.relative(getActiveWorkspaceRoot(), resolveSafePath(cleanPath));
|
|
6499
6829
|
} catch {
|
|
6500
6830
|
}
|
|
6501
6831
|
if (rel === "" || rel === "src") {
|
|
@@ -6503,7 +6833,7 @@ ${summaries.join("\n")}`;
|
|
|
6503
6833
|
}
|
|
6504
6834
|
let label = "\u6587\u4EF6\u6216\u76EE\u5F55";
|
|
6505
6835
|
try {
|
|
6506
|
-
const stat = await
|
|
6836
|
+
const stat = await fs16.stat(resolveSafePath(cleanPath));
|
|
6507
6837
|
label = stat.isDirectory() ? "\u4E00\u6574\u4E2A\u6587\u4EF6\u5939\u76EE\u5F55" : "\u7EAF\u7269\u7406\u6587\u4EF6";
|
|
6508
6838
|
} catch {
|
|
6509
6839
|
}
|
|
@@ -6516,22 +6846,22 @@ ${summaries.join("\n")}`;
|
|
|
6516
6846
|
return toolFailure(`[\u5B89\u5168\u7194\u65AD]\uFF1A\u7981\u6B62\u901A\u8FC7\u672C\u5DE5\u5177\u76F4\u63A5\u6467\u6BC1\u9879\u76EE\u6839\u76EE\u5F55\u6216\u4F20\u5165\u7A7A\u8DEF\u5F84\uFF01`);
|
|
6517
6847
|
}
|
|
6518
6848
|
const absPath = resolveSafePath(cleanPath);
|
|
6519
|
-
const rel =
|
|
6520
|
-
if (!rel || rel === "" || rel === "src" || rel.startsWith("..") ||
|
|
6849
|
+
const rel = path19.relative(getActiveWorkspaceRoot(), absPath);
|
|
6850
|
+
if (!rel || rel === "" || rel === "src" || rel.startsWith("..") || path19.isAbsolute(rel)) {
|
|
6521
6851
|
return toolFailure(`[\u5B89\u5168\u7194\u65AD]\uFF1A\u62D2\u7EDD\u9500\u6BC1\u5DE5\u4F5C\u533A\u6839\u76EE\u5F55 / src \u6E90\u7801\u6839 / \u8D8A\u754C\u8DEF\u5F84 [${cleanPath}]\uFF01`);
|
|
6522
6852
|
}
|
|
6523
6853
|
let stat;
|
|
6524
6854
|
try {
|
|
6525
|
-
stat = await
|
|
6855
|
+
stat = await fs16.stat(absPath);
|
|
6526
6856
|
} catch {
|
|
6527
6857
|
return toolFailure(`[\u9500\u6BC1\u5931\u8D25]\uFF1A\u5728\u5DE5\u4F5C\u533A\u5185\u672A\u627E\u5230\u6307\u5B9A\u7684\u8DEF\u5F84 [${cleanPath}]\u3002`);
|
|
6528
6858
|
}
|
|
6529
6859
|
const isDirectory = stat.isDirectory();
|
|
6530
6860
|
assertWithinWorkspace(absPath);
|
|
6531
6861
|
if (isDirectory) {
|
|
6532
|
-
await
|
|
6862
|
+
await fs16.rm(absPath, { recursive: true, force: true });
|
|
6533
6863
|
} else {
|
|
6534
|
-
await
|
|
6864
|
+
await fs16.unlink(absPath);
|
|
6535
6865
|
}
|
|
6536
6866
|
const targetTypeLabel = isDirectory ? "\u4E00\u6574\u4E2A\u6587\u4EF6\u5939\u76EE\u5F55" : "\u7EAF\u7269\u7406\u6587\u4EF6";
|
|
6537
6867
|
return `\u2705 [\u8DEF\u5F84\u9500\u6BC1\u6210\u529F]\uFF1A\u5DF2\u6210\u529F\u6C38\u4E45\u9500\u6BC1${targetTypeLabel} [${cleanPath}]\u3002`;
|
|
@@ -6565,15 +6895,15 @@ ${summaries.join("\n")}`;
|
|
|
6565
6895
|
try {
|
|
6566
6896
|
const absPath = resolveSafePath(args.path);
|
|
6567
6897
|
assertWithinWorkspace(absPath);
|
|
6568
|
-
await
|
|
6898
|
+
await fs16.mkdir(path19.dirname(absPath), { recursive: true });
|
|
6569
6899
|
tmpPath = makeTmpPath(absPath);
|
|
6570
|
-
await
|
|
6571
|
-
await
|
|
6900
|
+
await fs16.writeFile(tmpPath, args.content, "utf-8");
|
|
6901
|
+
await fs16.rename(tmpPath, absPath);
|
|
6572
6902
|
return `\u2705 [\u6587\u4EF6\u5199\u5165\u6210\u529F]\uFF1A\u5DF2\u5168\u91CF\u5199\u5165 [${args.path}]\uFF08${args.content.length} \u5B57\u7B26\uFF09\u3002`;
|
|
6573
6903
|
} catch (error) {
|
|
6574
6904
|
if (tmpPath) {
|
|
6575
6905
|
try {
|
|
6576
|
-
await
|
|
6906
|
+
await fs16.unlink(tmpPath);
|
|
6577
6907
|
} catch {
|
|
6578
6908
|
}
|
|
6579
6909
|
}
|
|
@@ -6605,11 +6935,11 @@ ${summaries.join("\n")}`;
|
|
|
6605
6935
|
if (readBlock) return readBlock;
|
|
6606
6936
|
const extBlock = checkSupportedSourceExt(args.path);
|
|
6607
6937
|
if (extBlock) return extBlock;
|
|
6608
|
-
const statForSize = await
|
|
6938
|
+
const statForSize = await fs16.stat(absPath);
|
|
6609
6939
|
if (statForSize.size > 1024 * 1024) {
|
|
6610
6940
|
return `\u26A0\uFE0F [\u6587\u4EF6\u8FC7\u5927]\uFF1A[${args.path}] \u7EA6 ${Math.round(statForSize.size / 1024)}KB\uFF0C\u8D85\u8FC7\u7B26\u53F7\u5927\u7EB2\u5206\u6790\u7684 1MB \u4E0A\u9650\uFF08\u9632\u5168\u91CF readFile + AST \u9A7B\u7559\u5403\u5185\u5B58\uFF09\u3002\u8BF7\u6539\u7528 read_file \u5206\u7247\u67E5\u770B\uFF0C\u6216\u7F29\u5C0F\u76EE\u6807\u6587\u4EF6\u3002`;
|
|
6611
6941
|
}
|
|
6612
|
-
const fileContent = await
|
|
6942
|
+
const fileContent = await fs16.readFile(absPath, "utf-8");
|
|
6613
6943
|
const TS = await getTs();
|
|
6614
6944
|
if (!TS) {
|
|
6615
6945
|
return `\u26A0\uFE0F [\u7B26\u53F7\u5927\u7EB2\u4E0D\u53EF\u7528]\uFF1Atypescript \u6A21\u5757\u672A\u5B89\u88C5\uFF08CLI \u53D1\u5E03\u7248\u672A\u5185\u8054\uFF09\u3002\u8BF7\u6539\u7528 read_file \u67E5\u770B\u6587\u4EF6\u5185\u5BB9\u3002`;
|
|
@@ -6696,19 +7026,19 @@ ${summaries.join("\n")}`;
|
|
|
6696
7026
|
const srcAbs = resolveSafePath(args.source);
|
|
6697
7027
|
const dstAbs = resolveSafePath(args.destination);
|
|
6698
7028
|
try {
|
|
6699
|
-
await
|
|
7029
|
+
await fs16.access(srcAbs);
|
|
6700
7030
|
} catch {
|
|
6701
7031
|
return toolFailure(`[\u79FB\u52A8\u5931\u8D25]\uFF1A\u6E90\u8DEF\u5F84 [${args.source}] \u4E0D\u5B58\u5728\u3002`);
|
|
6702
7032
|
}
|
|
6703
7033
|
try {
|
|
6704
|
-
await
|
|
7034
|
+
await fs16.access(dstAbs);
|
|
6705
7035
|
return toolFailure(`[\u79FB\u52A8\u5931\u8D25]\uFF1A\u76EE\u6807 [${args.destination}] \u5DF2\u5B58\u5728\u3002\u5982\u9700\u8986\u76D6\u8BF7\u5148 delete_path \u518D move_file\u3002`);
|
|
6706
7036
|
} catch {
|
|
6707
7037
|
}
|
|
6708
7038
|
assertWithinWorkspace(srcAbs);
|
|
6709
7039
|
assertWithinWorkspace(dstAbs);
|
|
6710
|
-
await
|
|
6711
|
-
await
|
|
7040
|
+
await fs16.mkdir(path19.dirname(dstAbs), { recursive: true });
|
|
7041
|
+
await fs16.rename(srcAbs, dstAbs);
|
|
6712
7042
|
return `\u2705 [\u79FB\u52A8\u6210\u529F]\uFF1A[${args.source}] \u2192 [${args.destination}]\u3002`;
|
|
6713
7043
|
} catch (error) {
|
|
6714
7044
|
return toolFailure(`\u64CD\u4F5C\u5931\u8D25: ${error.message}`);
|
|
@@ -6738,9 +7068,9 @@ ${summaries.join("\n")}`;
|
|
|
6738
7068
|
const absPath = resolveReadablePath(args.path);
|
|
6739
7069
|
const readBlock = await assertReadable(absPath, args.path);
|
|
6740
7070
|
if (readBlock) return readBlock;
|
|
6741
|
-
const mime = IMAGE_MIME_BY_EXT[
|
|
7071
|
+
const mime = IMAGE_MIME_BY_EXT[path19.extname(absPath).toLowerCase()];
|
|
6742
7072
|
if (!mime) return toolFailure(`[read_image] \u4E0D\u652F\u6301\u7684\u56FE\u7247\u683C\u5F0F [${args.path}]\uFF1A\u4EC5\u652F\u6301 png/jpg/jpeg/gif/webp/bmp\u3002\u6587\u672C\u6587\u4EF6\u8BF7\u7528 read_file\u3002`);
|
|
6743
|
-
const st = await
|
|
7073
|
+
const st = await fs16.stat(absPath).catch(() => null);
|
|
6744
7074
|
if (!st || !st.isFile()) return toolFailure(`[read_image] \u56FE\u7247\u4E0D\u5B58\u5728\u6216\u4E0D\u662F\u6587\u4EF6\uFF1A${args.path}`);
|
|
6745
7075
|
if (st.size > MAX_IMAGE_BYTES) {
|
|
6746
7076
|
return toolFailure(`[read_image] \u56FE\u7247 ${(st.size / 1024 / 1024).toFixed(1)}MB \u8D85\u8FC7 ${Math.round(MAX_IMAGE_BYTES / 1024 / 1024)}MB \u4E0A\u9650\uFF1A\u8BF7\u538B\u7F29\u540E\u91CD\u8BD5\uFF0C\u6216\u88C1\u526A\u5230\u9700\u8981\u7684\u533A\u57DF\u3002`);
|
|
@@ -6748,11 +7078,11 @@ ${summaries.join("\n")}`;
|
|
|
6748
7078
|
if (!isVisionEnabled()) {
|
|
6749
7079
|
return toolFailure(`[read_image] \u5F53\u524D\u6A21\u578B\u4E0D\u652F\u6301\u56FE\u7247\u8F93\u5165\uFF08\u89C6\u89C9\u80FD\u529B\u6309\u7AEF\u70B9\u5B9E\u6D4B\u81EA\u52A8\u5224\u5B9A\uFF1B\u53EF\u5207\u6362 vision \u6A21\u578B\u6216\u8BBE DEEP_SEEK_VISION=1 \u5F3A\u5F00\u540E\u91CD\u8BD5\uFF09\u3002\u56FE\u7247\u672A\u8BFB\u53D6\uFF1A${args.path}`);
|
|
6750
7080
|
}
|
|
6751
|
-
const buf = await
|
|
7081
|
+
const buf = await fs16.readFile(absPath);
|
|
6752
7082
|
return {
|
|
6753
7083
|
content: `\u{1F5BC} [read_image] \u5DF2\u8BFB\u53D6\u56FE\u7247 ${args.path}\uFF08${mime}\uFF0C${st.size} \u5B57\u8282\uFF09\u3002\u56FE\u50CF\u5185\u5BB9\u89C1\u968F\u540E\u7684\u9644\u4EF6\u6D88\u606F\uFF0C\u8BF7\u76F4\u63A5\u5BF9\u56FE\u7247\u8FDB\u884C\u5206\u6790/\u5BF9\u7167\u3002`,
|
|
6754
7084
|
status: "success",
|
|
6755
|
-
images: [{ name:
|
|
7085
|
+
images: [{ name: path19.basename(absPath), mime, base64: buf.toString("base64") }]
|
|
6756
7086
|
};
|
|
6757
7087
|
} catch (error) {
|
|
6758
7088
|
return toolFailure(`\u8BFB\u53D6\u56FE\u7247\u5931\u8D25 [${args.path}]: ${error.message}`);
|
|
@@ -6766,8 +7096,8 @@ ${summaries.join("\n")}`;
|
|
|
6766
7096
|
|
|
6767
7097
|
// ../core/src/tool/registry/search.ts
|
|
6768
7098
|
import { rgPath } from "vscode-ripgrep";
|
|
6769
|
-
import
|
|
6770
|
-
import
|
|
7099
|
+
import path20 from "path";
|
|
7100
|
+
import fs17 from "fs/promises";
|
|
6771
7101
|
function escapeRegExp(string) {
|
|
6772
7102
|
return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
6773
7103
|
}
|
|
@@ -6811,10 +7141,10 @@ var init_search = __esm({
|
|
|
6811
7141
|
const resolveSearchRoot = () => {
|
|
6812
7142
|
if (!args.path) return ctx?.cwd ?? getActiveWorkspaceRoot();
|
|
6813
7143
|
const p = args.path.trim();
|
|
6814
|
-
const looksLikeBareName = !
|
|
7144
|
+
const looksLikeBareName = !path20.isAbsolute(p) && !p.includes("/") && !p.includes("\\");
|
|
6815
7145
|
if (looksLikeBareName) {
|
|
6816
7146
|
const hit = getAllowedWorkspaceRoots().find((r) => {
|
|
6817
|
-
const bn =
|
|
7147
|
+
const bn = path20.basename(r);
|
|
6818
7148
|
return bn === p || bn.toLowerCase() === p.toLowerCase();
|
|
6819
7149
|
});
|
|
6820
7150
|
if (hit) return hit;
|
|
@@ -6904,7 +7234,7 @@ var init_search = __esm({
|
|
|
6904
7234
|
const GUIDE_CANDIDATES = ["CLAUDE.md", "AGENTS.md", "AGENT.md"];
|
|
6905
7235
|
for (const name of GUIDE_CANDIDATES) {
|
|
6906
7236
|
try {
|
|
6907
|
-
const content = await
|
|
7237
|
+
const content = await fs17.readFile(path20.join(getActiveWorkspaceRoot(), name), "utf-8");
|
|
6908
7238
|
return `[Project Guide via ${name}]
|
|
6909
7239
|
|
|
6910
7240
|
${content}`;
|
|
@@ -7193,8 +7523,8 @@ ${AUTO_BG_NOTICE}
|
|
|
7193
7523
|
});
|
|
7194
7524
|
|
|
7195
7525
|
// ../core/src/tool/registry/glob.ts
|
|
7196
|
-
import
|
|
7197
|
-
import
|
|
7526
|
+
import fs18 from "fs/promises";
|
|
7527
|
+
import path21 from "path";
|
|
7198
7528
|
var findMatchingBrace, splitTopLevel, globToRegex2, globTools;
|
|
7199
7529
|
var init_glob = __esm({
|
|
7200
7530
|
"../core/src/tool/registry/glob.ts"() {
|
|
@@ -7300,18 +7630,18 @@ var init_glob = __esm({
|
|
|
7300
7630
|
const MAX_SCAN_LIMIT = 1e4;
|
|
7301
7631
|
const scan = async (dir) => {
|
|
7302
7632
|
if (scannedCount > MAX_SCAN_LIMIT) return;
|
|
7303
|
-
const entries = await
|
|
7633
|
+
const entries = await fs18.readdir(dir, { withFileTypes: true });
|
|
7304
7634
|
const validEntries = entries.filter((e) => {
|
|
7305
|
-
const full =
|
|
7306
|
-
const rel =
|
|
7635
|
+
const full = path21.join(dir, e.name);
|
|
7636
|
+
const rel = path21.relative(activeRoot, full).replace(/\\/g, "/");
|
|
7307
7637
|
return !checkIsPathIgnored(e.isDirectory() ? `${rel}/` : rel);
|
|
7308
7638
|
});
|
|
7309
7639
|
for (const e of validEntries) {
|
|
7310
7640
|
scannedCount++;
|
|
7311
7641
|
if (scannedCount > MAX_SCAN_LIMIT) break;
|
|
7312
7642
|
if (e.isSymbolicLink()) continue;
|
|
7313
|
-
const full =
|
|
7314
|
-
const rel =
|
|
7643
|
+
const full = path21.join(dir, e.name);
|
|
7644
|
+
const rel = path21.relative(activeRoot, full).replace(/\\/g, "/");
|
|
7315
7645
|
if (e.isDirectory()) {
|
|
7316
7646
|
if (cleanPattern.endsWith("/") && re.test(`${rel}/`)) {
|
|
7317
7647
|
hits.push(`${rel}/`);
|
|
@@ -7532,8 +7862,8 @@ ${summary}`;
|
|
|
7532
7862
|
});
|
|
7533
7863
|
|
|
7534
7864
|
// ../core/src/tool/registry/inspect_dependencies.ts
|
|
7535
|
-
import * as
|
|
7536
|
-
import * as
|
|
7865
|
+
import * as fs19 from "fs/promises";
|
|
7866
|
+
import * as path22 from "path";
|
|
7537
7867
|
var dependencyTools;
|
|
7538
7868
|
var init_inspect_dependencies = __esm({
|
|
7539
7869
|
"../core/src/tool/registry/inspect_dependencies.ts"() {
|
|
@@ -7554,8 +7884,8 @@ var init_inspect_dependencies = __esm({
|
|
|
7554
7884
|
isSync: true,
|
|
7555
7885
|
async execute() {
|
|
7556
7886
|
try {
|
|
7557
|
-
const pjsPath =
|
|
7558
|
-
const raw = await
|
|
7887
|
+
const pjsPath = path22.join(getActiveWorkspaceRoot(), "package.json");
|
|
7888
|
+
const raw = await fs19.readFile(pjsPath, "utf-8");
|
|
7559
7889
|
const pjs = JSON.parse(raw);
|
|
7560
7890
|
const result = {
|
|
7561
7891
|
dependencies: pjs.dependencies || {},
|
|
@@ -8291,8 +8621,8 @@ var init_http = __esm({
|
|
|
8291
8621
|
});
|
|
8292
8622
|
|
|
8293
8623
|
// ../core/src/tool/registry/typescript.ts
|
|
8294
|
-
import
|
|
8295
|
-
import
|
|
8624
|
+
import fs20 from "fs/promises";
|
|
8625
|
+
import path23 from "path";
|
|
8296
8626
|
var MAX_FILE_BYTES, toDisplayPath, isLibFile, precheck, MAX_DIAG_ENTRIES, MAX_DIAG_FILES, MAX_REF_ENTRIES, REF_SNIPPET_MAX, diagnoseOneFile, typescriptTools;
|
|
8297
8627
|
var init_typescript = __esm({
|
|
8298
8628
|
"../core/src/tool/registry/typescript.ts"() {
|
|
@@ -8303,8 +8633,8 @@ var init_typescript = __esm({
|
|
|
8303
8633
|
init_fs();
|
|
8304
8634
|
MAX_FILE_BYTES = 1024 * 1024;
|
|
8305
8635
|
toDisplayPath = (wsRoot, abs) => {
|
|
8306
|
-
const rel =
|
|
8307
|
-
if (rel && !rel.startsWith("..") && !
|
|
8636
|
+
const rel = path23.relative(wsRoot, abs);
|
|
8637
|
+
if (rel && !rel.startsWith("..") && !path23.isAbsolute(rel)) return rel.replace(/\\/g, "/");
|
|
8308
8638
|
return abs.replace(/\\/g, "/").split("/").slice(-3).join("/");
|
|
8309
8639
|
};
|
|
8310
8640
|
isLibFile = (abs) => /(?:^|\/)node_modules\//.test(abs.replace(/\\/g, "/")) || /\.d\.ts$/i.test(abs);
|
|
@@ -8313,7 +8643,7 @@ var init_typescript = __esm({
|
|
|
8313
8643
|
if (readBlock) return readBlock;
|
|
8314
8644
|
const extBlock = checkSupportedSourceExt(displayPath);
|
|
8315
8645
|
if (extBlock) return extBlock;
|
|
8316
|
-
const stat = await
|
|
8646
|
+
const stat = await fs20.stat(absPath);
|
|
8317
8647
|
if (stat.size > MAX_FILE_BYTES) {
|
|
8318
8648
|
return `\u26A0\uFE0F [\u6587\u4EF6\u8FC7\u5927]\uFF1A[${displayPath}] \u7EA6 ${Math.round(stat.size / 1024)}KB\uFF0C\u8D85\u8FC7 ${MAX_FILE_BYTES / 1024}KB \u4E0A\u9650\uFF08\u9632\u5168\u91CF type-check \u5403\u5185\u5B58\uFF09\u3002`;
|
|
8319
8649
|
}
|
|
@@ -8531,7 +8861,7 @@ ${out.join("\n")}`;
|
|
|
8531
8861
|
let lines = lineTextCache.get(abs);
|
|
8532
8862
|
if (!lines) {
|
|
8533
8863
|
try {
|
|
8534
|
-
lines = (await
|
|
8864
|
+
lines = (await fs20.readFile(abs, "utf-8")).split(/\r?\n/);
|
|
8535
8865
|
} catch {
|
|
8536
8866
|
lines = [];
|
|
8537
8867
|
}
|
|
@@ -8660,8 +8990,8 @@ var init_todo = __esm({
|
|
|
8660
8990
|
});
|
|
8661
8991
|
|
|
8662
8992
|
// ../core/src/observability/traceCalculate.ts
|
|
8663
|
-
import
|
|
8664
|
-
import
|
|
8993
|
+
import fs21 from "fs/promises";
|
|
8994
|
+
import path24 from "path";
|
|
8665
8995
|
var getDirBytes, getTodayDateString;
|
|
8666
8996
|
var init_traceCalculate = __esm({
|
|
8667
8997
|
"../core/src/observability/traceCalculate.ts"() {
|
|
@@ -8673,17 +9003,17 @@ var init_traceCalculate = __esm({
|
|
|
8673
9003
|
const cur = stack.pop();
|
|
8674
9004
|
let entries;
|
|
8675
9005
|
try {
|
|
8676
|
-
entries = await
|
|
9006
|
+
entries = await fs21.readdir(cur, { withFileTypes: true });
|
|
8677
9007
|
} catch {
|
|
8678
9008
|
continue;
|
|
8679
9009
|
}
|
|
8680
9010
|
for (const e of entries) {
|
|
8681
|
-
const p =
|
|
9011
|
+
const p = path24.join(cur, e.name);
|
|
8682
9012
|
if (e.isDirectory()) {
|
|
8683
9013
|
stack.push(p);
|
|
8684
9014
|
} else {
|
|
8685
9015
|
try {
|
|
8686
|
-
total += (await
|
|
9016
|
+
total += (await fs21.stat(p)).size;
|
|
8687
9017
|
} catch {
|
|
8688
9018
|
}
|
|
8689
9019
|
}
|
|
@@ -8702,8 +9032,8 @@ var init_traceCalculate = __esm({
|
|
|
8702
9032
|
});
|
|
8703
9033
|
|
|
8704
9034
|
// ../core/src/tool/undo/store.ts
|
|
8705
|
-
import
|
|
8706
|
-
import
|
|
9035
|
+
import path25 from "path";
|
|
9036
|
+
import fs22 from "fs/promises";
|
|
8707
9037
|
var getUndoRootPath, getUndoClockPath, getUndoDirPath, getUndoBackupRoot, ensureUndoDir, getUndoIndexPath;
|
|
8708
9038
|
var init_store2 = __esm({
|
|
8709
9039
|
"../core/src/tool/undo/store.ts"() {
|
|
@@ -8711,33 +9041,33 @@ var init_store2 = __esm({
|
|
|
8711
9041
|
init_config();
|
|
8712
9042
|
init_common();
|
|
8713
9043
|
init_traceCalculate();
|
|
8714
|
-
getUndoRootPath = () =>
|
|
8715
|
-
getUndoClockPath = () =>
|
|
9044
|
+
getUndoRootPath = () => path25.join(appConfig.dataDir, "undo");
|
|
9045
|
+
getUndoClockPath = () => path25.join(getUndoRootPath(), "undo-cleanup-clock.json");
|
|
8716
9046
|
getUndoDirPath = (mainSessionId) => {
|
|
8717
9047
|
const rootId = getFileName(mainSessionId);
|
|
8718
9048
|
assertSafeSessionId(rootId, "undoSessionId");
|
|
8719
|
-
return
|
|
9049
|
+
return path25.join(getUndoRootPath(), appConfig.userWorkspaceDir, rootId);
|
|
8720
9050
|
};
|
|
8721
|
-
getUndoBackupRoot = (mainSessionId) =>
|
|
9051
|
+
getUndoBackupRoot = (mainSessionId) => path25.join(getUndoDirPath(mainSessionId), "backups");
|
|
8722
9052
|
ensureUndoDir = async (mainSessionId) => {
|
|
8723
|
-
await
|
|
9053
|
+
await fs22.mkdir(getUndoDirPath(mainSessionId), { recursive: true, mode: 448 });
|
|
8724
9054
|
};
|
|
8725
9055
|
getUndoIndexPath = async (mainSessionId) => {
|
|
8726
9056
|
const rootId = getFileName(mainSessionId);
|
|
8727
9057
|
assertSafeSessionId(rootId, "undoSessionId");
|
|
8728
9058
|
const dir = getUndoDirPath(mainSessionId);
|
|
8729
|
-
await
|
|
8730
|
-
const files = await
|
|
9059
|
+
await fs22.mkdir(dir, { recursive: true, mode: 448 });
|
|
9060
|
+
const files = await fs22.readdir(dir);
|
|
8731
9061
|
const existedFile = files.find((f) => f.endsWith(`__${rootId}.jsonl`));
|
|
8732
9062
|
const fileName = existedFile ?? `undo-${getTodayDateString()}__${rootId}.jsonl`;
|
|
8733
|
-
return
|
|
9063
|
+
return path25.join(dir, fileName);
|
|
8734
9064
|
};
|
|
8735
9065
|
}
|
|
8736
9066
|
});
|
|
8737
9067
|
|
|
8738
9068
|
// ../core/src/tool/undo/index.ts
|
|
8739
|
-
import
|
|
8740
|
-
import
|
|
9069
|
+
import fs23 from "fs/promises";
|
|
9070
|
+
import path26 from "path";
|
|
8741
9071
|
var undoLocks, withUndoLock, appendUndoRecord, readUndoIndex, markRestored;
|
|
8742
9072
|
var init_undo = __esm({
|
|
8743
9073
|
"../core/src/tool/undo/index.ts"() {
|
|
@@ -8767,7 +9097,7 @@ var init_undo = __esm({
|
|
|
8767
9097
|
};
|
|
8768
9098
|
const p = await getUndoIndexPath(sessionId);
|
|
8769
9099
|
const line = JSON.stringify(enriched) + "\n";
|
|
8770
|
-
await
|
|
9100
|
+
await fs23.appendFile(p, line, { encoding: "utf-8", mode: 384 });
|
|
8771
9101
|
});
|
|
8772
9102
|
};
|
|
8773
9103
|
readUndoIndex = async (sessionId) => {
|
|
@@ -8779,7 +9109,7 @@ var init_undo = __esm({
|
|
|
8779
9109
|
}
|
|
8780
9110
|
let files;
|
|
8781
9111
|
try {
|
|
8782
|
-
files = await
|
|
9112
|
+
files = await fs23.readdir(dir);
|
|
8783
9113
|
} catch {
|
|
8784
9114
|
return [];
|
|
8785
9115
|
}
|
|
@@ -8787,7 +9117,7 @@ var init_undo = __esm({
|
|
|
8787
9117
|
for (const f of files) {
|
|
8788
9118
|
if (!f.startsWith("undo-") || !f.endsWith(".jsonl")) continue;
|
|
8789
9119
|
try {
|
|
8790
|
-
const raw = await
|
|
9120
|
+
const raw = await fs23.readFile(path26.join(dir, f), "utf-8");
|
|
8791
9121
|
for (const line of raw.split("\n")) {
|
|
8792
9122
|
const trimmed = line.trim();
|
|
8793
9123
|
if (!trimmed) continue;
|
|
@@ -8812,16 +9142,16 @@ var init_undo = __esm({
|
|
|
8812
9142
|
}
|
|
8813
9143
|
let files;
|
|
8814
9144
|
try {
|
|
8815
|
-
files = await
|
|
9145
|
+
files = await fs23.readdir(dir);
|
|
8816
9146
|
} catch {
|
|
8817
9147
|
return;
|
|
8818
9148
|
}
|
|
8819
9149
|
for (const f of files) {
|
|
8820
9150
|
if (!f.startsWith("undo-") || !f.endsWith(".jsonl")) continue;
|
|
8821
|
-
const fp =
|
|
9151
|
+
const fp = path26.join(dir, f);
|
|
8822
9152
|
let raw;
|
|
8823
9153
|
try {
|
|
8824
|
-
raw = await
|
|
9154
|
+
raw = await fs23.readFile(fp, "utf-8");
|
|
8825
9155
|
} catch {
|
|
8826
9156
|
continue;
|
|
8827
9157
|
}
|
|
@@ -8845,8 +9175,8 @@ var init_undo = __esm({
|
|
|
8845
9175
|
if (changed) {
|
|
8846
9176
|
const content = lines.join("\n").replace(/\n*$/, "\n");
|
|
8847
9177
|
const tmp = fp + ".tmp";
|
|
8848
|
-
await
|
|
8849
|
-
await
|
|
9178
|
+
await fs23.writeFile(tmp, content, { encoding: "utf-8", mode: 384 });
|
|
9179
|
+
await fs23.rename(tmp, fp);
|
|
8850
9180
|
}
|
|
8851
9181
|
}
|
|
8852
9182
|
});
|
|
@@ -8855,8 +9185,8 @@ var init_undo = __esm({
|
|
|
8855
9185
|
});
|
|
8856
9186
|
|
|
8857
9187
|
// ../core/src/tool/undo/cleanup.ts
|
|
8858
|
-
import
|
|
8859
|
-
import
|
|
9188
|
+
import fs24 from "fs/promises";
|
|
9189
|
+
import path27 from "path";
|
|
8860
9190
|
async function maybeCleanupAfterUndoAppend(_sessionId) {
|
|
8861
9191
|
if (cleanupInProgress) return;
|
|
8862
9192
|
cleanupInProgress = true;
|
|
@@ -8882,8 +9212,8 @@ async function maybeCleanupAfterUndoAppend(_sessionId) {
|
|
|
8882
9212
|
lastSizeCleanupAt = now;
|
|
8883
9213
|
diskLastCleanupAt = now;
|
|
8884
9214
|
const clockPath = getUndoClockPath();
|
|
8885
|
-
await
|
|
8886
|
-
await
|
|
9215
|
+
await fs24.mkdir(path27.dirname(clockPath), { recursive: true });
|
|
9216
|
+
await fs24.writeFile(clockPath, JSON.stringify({ lastCleanupAt: now, updatedAt: (/* @__PURE__ */ new Date()).toISOString() }, null, 2), "utf-8");
|
|
8887
9217
|
if (deleted > 0) console.log(`\u2728 [Undo\u8FD0\u7EF4] \u5171\u9500\u6BC1 ${deleted} \u4E2A undo \u8D44\u4EA7\uFF08\u7D22\u5F15 + \u5B64\u513F\u5185\u5BB9\uFF09\uFF0C\u78C1\u76D8\u6C34\u4F4D\u56DE\u843D\u3002`);
|
|
8888
9218
|
} catch (e) {
|
|
8889
9219
|
console.warn("\u26A0\uFE0F [Undo\u8FD0\u7EF4] \u81EA\u52A8\u6E05\u7406\u5F02\u5E38\uFF0C\u5DF2\u8DF3\u8FC7:", e?.message ?? e);
|
|
@@ -8900,23 +9230,23 @@ async function cleanupOldUndoFiles() {
|
|
|
8900
9230
|
const now = Date.now();
|
|
8901
9231
|
let relativePaths;
|
|
8902
9232
|
try {
|
|
8903
|
-
relativePaths = await
|
|
9233
|
+
relativePaths = await fs24.readdir(dir, { recursive: true });
|
|
8904
9234
|
} catch {
|
|
8905
9235
|
return 0;
|
|
8906
9236
|
}
|
|
8907
9237
|
const re = /^undo-(\d{4}-\d{2}-\d{2})__([\w-]+)\.jsonl$/;
|
|
8908
9238
|
let deleted = 0;
|
|
8909
9239
|
for (const rp of relativePaths) {
|
|
8910
|
-
const fileName =
|
|
9240
|
+
const fileName = path27.basename(rp);
|
|
8911
9241
|
const m = fileName.match(re);
|
|
8912
9242
|
if (!m) continue;
|
|
8913
9243
|
const fileBornDay = /* @__PURE__ */ new Date(`${m[1]}T00:00:00`);
|
|
8914
9244
|
if (fileBornDay >= cutoff) continue;
|
|
8915
|
-
const fullPath =
|
|
9245
|
+
const fullPath = path27.join(dir, rp);
|
|
8916
9246
|
try {
|
|
8917
|
-
const st = await
|
|
9247
|
+
const st = await fs24.stat(fullPath);
|
|
8918
9248
|
if (now - st.mtimeMs < ACTIVE_GRACE_MS) continue;
|
|
8919
|
-
await
|
|
9249
|
+
await fs24.unlink(fullPath);
|
|
8920
9250
|
deleted += 1;
|
|
8921
9251
|
} catch {
|
|
8922
9252
|
}
|
|
@@ -8927,17 +9257,17 @@ async function evictOldestForSize(targetBytes) {
|
|
|
8927
9257
|
const dir = getUndoRootPath();
|
|
8928
9258
|
let relativePaths;
|
|
8929
9259
|
try {
|
|
8930
|
-
relativePaths = await
|
|
9260
|
+
relativePaths = await fs24.readdir(dir, { recursive: true });
|
|
8931
9261
|
} catch {
|
|
8932
9262
|
return 0;
|
|
8933
9263
|
}
|
|
8934
9264
|
const re = /^undo-(\d{4}-\d{2}-\d{2})__([\w-]+)\.jsonl$/;
|
|
8935
9265
|
const candidates = [];
|
|
8936
9266
|
for (const rp of relativePaths) {
|
|
8937
|
-
if (!re.test(
|
|
9267
|
+
if (!re.test(path27.basename(rp))) continue;
|
|
8938
9268
|
try {
|
|
8939
|
-
const st = await
|
|
8940
|
-
candidates.push({ mtime: st.mtimeMs, fullPath:
|
|
9269
|
+
const st = await fs24.stat(path27.join(dir, rp));
|
|
9270
|
+
candidates.push({ mtime: st.mtimeMs, fullPath: path27.join(dir, rp), size: st.size });
|
|
8941
9271
|
} catch {
|
|
8942
9272
|
}
|
|
8943
9273
|
}
|
|
@@ -8947,7 +9277,7 @@ async function evictOldestForSize(targetBytes) {
|
|
|
8947
9277
|
for (const c of candidates) {
|
|
8948
9278
|
if (totalBytes <= targetBytes) break;
|
|
8949
9279
|
try {
|
|
8950
|
-
await
|
|
9280
|
+
await fs24.unlink(c.fullPath);
|
|
8951
9281
|
totalBytes -= c.size;
|
|
8952
9282
|
deleted += 1;
|
|
8953
9283
|
} catch {
|
|
@@ -8961,38 +9291,38 @@ async function gcOrphanBackups() {
|
|
|
8961
9291
|
let deleted = 0;
|
|
8962
9292
|
let workspaces;
|
|
8963
9293
|
try {
|
|
8964
|
-
workspaces = await
|
|
9294
|
+
workspaces = await fs24.readdir(root);
|
|
8965
9295
|
} catch {
|
|
8966
9296
|
return 0;
|
|
8967
9297
|
}
|
|
8968
9298
|
for (const ws of workspaces) {
|
|
8969
|
-
const wsDir =
|
|
9299
|
+
const wsDir = path27.join(root, ws);
|
|
8970
9300
|
let stWs;
|
|
8971
9301
|
try {
|
|
8972
|
-
stWs = await
|
|
9302
|
+
stWs = await fs24.stat(wsDir);
|
|
8973
9303
|
} catch {
|
|
8974
9304
|
continue;
|
|
8975
9305
|
}
|
|
8976
9306
|
if (!stWs.isDirectory()) continue;
|
|
8977
9307
|
let sessions2;
|
|
8978
9308
|
try {
|
|
8979
|
-
sessions2 = await
|
|
9309
|
+
sessions2 = await fs24.readdir(wsDir);
|
|
8980
9310
|
} catch {
|
|
8981
9311
|
continue;
|
|
8982
9312
|
}
|
|
8983
9313
|
for (const sess of sessions2) {
|
|
8984
|
-
const sessDir =
|
|
9314
|
+
const sessDir = path27.join(wsDir, sess);
|
|
8985
9315
|
const liveIds = /* @__PURE__ */ new Set();
|
|
8986
9316
|
let files;
|
|
8987
9317
|
try {
|
|
8988
|
-
files = await
|
|
9318
|
+
files = await fs24.readdir(sessDir);
|
|
8989
9319
|
} catch {
|
|
8990
9320
|
continue;
|
|
8991
9321
|
}
|
|
8992
9322
|
for (const f of files) {
|
|
8993
9323
|
if (!f.startsWith("undo-") || !f.endsWith(".jsonl")) continue;
|
|
8994
9324
|
try {
|
|
8995
|
-
const raw = await
|
|
9325
|
+
const raw = await fs24.readFile(path27.join(sessDir, f), "utf-8");
|
|
8996
9326
|
for (const line of raw.split("\n")) {
|
|
8997
9327
|
const t = line.trim();
|
|
8998
9328
|
if (!t) continue;
|
|
@@ -9005,17 +9335,17 @@ async function gcOrphanBackups() {
|
|
|
9005
9335
|
} catch {
|
|
9006
9336
|
}
|
|
9007
9337
|
}
|
|
9008
|
-
const backupsDir =
|
|
9338
|
+
const backupsDir = path27.join(sessDir, "backups");
|
|
9009
9339
|
let undoDirs;
|
|
9010
9340
|
try {
|
|
9011
|
-
undoDirs = await
|
|
9341
|
+
undoDirs = await fs24.readdir(backupsDir);
|
|
9012
9342
|
} catch {
|
|
9013
9343
|
continue;
|
|
9014
9344
|
}
|
|
9015
9345
|
for (const ud of undoDirs) {
|
|
9016
9346
|
if (liveIds.has(ud)) continue;
|
|
9017
9347
|
try {
|
|
9018
|
-
await
|
|
9348
|
+
await fs24.rm(path27.join(backupsDir, ud), { recursive: true, force: true });
|
|
9019
9349
|
deleted += 1;
|
|
9020
9350
|
} catch {
|
|
9021
9351
|
}
|
|
@@ -9043,7 +9373,7 @@ var init_cleanup = __esm({
|
|
|
9043
9373
|
if (clockLoaded) return;
|
|
9044
9374
|
clockLoaded = true;
|
|
9045
9375
|
try {
|
|
9046
|
-
const rawClock = await
|
|
9376
|
+
const rawClock = await fs24.readFile(getUndoClockPath(), "utf-8");
|
|
9047
9377
|
diskLastCleanupAt = JSON.parse(rawClock).lastCleanupAt || 0;
|
|
9048
9378
|
} catch {
|
|
9049
9379
|
diskLastCleanupAt = 0;
|
|
@@ -9053,17 +9383,17 @@ var init_cleanup = __esm({
|
|
|
9053
9383
|
let total = 0;
|
|
9054
9384
|
let entries;
|
|
9055
9385
|
try {
|
|
9056
|
-
entries = await
|
|
9386
|
+
entries = await fs24.readdir(dir, { withFileTypes: true });
|
|
9057
9387
|
} catch {
|
|
9058
9388
|
return 0;
|
|
9059
9389
|
}
|
|
9060
9390
|
for (const e of entries) {
|
|
9061
|
-
const full =
|
|
9391
|
+
const full = path27.join(dir, e.name);
|
|
9062
9392
|
if (e.isDirectory()) {
|
|
9063
9393
|
total += await getDirBytesRecursive(full);
|
|
9064
9394
|
} else if (e.isFile()) {
|
|
9065
9395
|
try {
|
|
9066
|
-
total += (await
|
|
9396
|
+
total += (await fs24.stat(full)).size;
|
|
9067
9397
|
} catch {
|
|
9068
9398
|
}
|
|
9069
9399
|
}
|
|
@@ -9074,8 +9404,8 @@ var init_cleanup = __esm({
|
|
|
9074
9404
|
});
|
|
9075
9405
|
|
|
9076
9406
|
// ../core/src/tool/undo/backup.ts
|
|
9077
|
-
import
|
|
9078
|
-
import
|
|
9407
|
+
import fs25 from "fs/promises";
|
|
9408
|
+
import path28 from "path";
|
|
9079
9409
|
import crypto from "crypto";
|
|
9080
9410
|
async function beforeMutationBackup(strategy, toolName, args, toolCallId, sessionId) {
|
|
9081
9411
|
if (appConfig.undoEnabled === false) return null;
|
|
@@ -9087,7 +9417,7 @@ async function beforeMutationBackup(strategy, toolName, args, toolCallId, sessio
|
|
|
9087
9417
|
}
|
|
9088
9418
|
await ensureUndoDir(sessionId);
|
|
9089
9419
|
const undoId = createUUID();
|
|
9090
|
-
const undoDir =
|
|
9420
|
+
const undoDir = path28.join(getUndoBackupRoot(sessionId), undoId);
|
|
9091
9421
|
const now = /* @__PURE__ */ new Date();
|
|
9092
9422
|
const common = {
|
|
9093
9423
|
undoId,
|
|
@@ -9120,7 +9450,7 @@ async function backupFileOverwrite(common, undoDir, args) {
|
|
|
9120
9450
|
const absPath = resolveSafePath(common.relativePath);
|
|
9121
9451
|
let exists = true;
|
|
9122
9452
|
try {
|
|
9123
|
-
await
|
|
9453
|
+
await fs25.access(absPath);
|
|
9124
9454
|
} catch {
|
|
9125
9455
|
exists = false;
|
|
9126
9456
|
}
|
|
@@ -9128,15 +9458,15 @@ async function backupFileOverwrite(common, undoDir, args) {
|
|
|
9128
9458
|
return { ...common, backupKind: "creation_marker", backupPath: "", fileSizeBefore: 0 };
|
|
9129
9459
|
}
|
|
9130
9460
|
assertWithinWorkspace(absPath);
|
|
9131
|
-
const fileStat = await
|
|
9461
|
+
const fileStat = await fs25.stat(absPath);
|
|
9132
9462
|
const maxPerOp = appConfig.undoMaxBytesPerOp ?? 100 * 1024 * 1024;
|
|
9133
9463
|
if (fileStat.size > maxPerOp) {
|
|
9134
9464
|
throw new Error(`\u6587\u4EF6 [${common.relativePath}] \u4F53\u79EF\u7EA6 ${fileStat.size} \u5B57\u8282\u8D85\u8FC7\u5355\u6B21\u5907\u4EFD\u4E0A\u9650 ${maxPerOp}\uFF0C\u5199\u5165\u5DF2\u963B\u65AD\uFF08\u9632\u5185\u5B58\u62D6\u57AE\uFF1B\u53EF\u8C03 undoMaxBytesPerOp\uFF09`);
|
|
9135
9465
|
}
|
|
9136
|
-
const content = await
|
|
9137
|
-
await
|
|
9138
|
-
const contentPath =
|
|
9139
|
-
await
|
|
9466
|
+
const content = await fs25.readFile(absPath);
|
|
9467
|
+
await fs25.mkdir(undoDir, { recursive: true, mode: 448 });
|
|
9468
|
+
const contentPath = path28.join(undoDir, "content");
|
|
9469
|
+
await fs25.writeFile(contentPath, content, { mode: 384 });
|
|
9140
9470
|
return {
|
|
9141
9471
|
...common,
|
|
9142
9472
|
backupKind: "file_content",
|
|
@@ -9156,9 +9486,9 @@ async function backupFileCreate(common) {
|
|
|
9156
9486
|
}
|
|
9157
9487
|
async function backupDelete(common, undoDir, relativePath) {
|
|
9158
9488
|
const absPath = resolveSafePath(relativePath);
|
|
9159
|
-
const st = await
|
|
9489
|
+
const st = await fs25.stat(absPath);
|
|
9160
9490
|
assertWithinWorkspace(absPath);
|
|
9161
|
-
await
|
|
9491
|
+
await fs25.mkdir(undoDir, { recursive: true, mode: 448 });
|
|
9162
9492
|
if (st.isDirectory()) {
|
|
9163
9493
|
const treeBytes = await getDirTreeBytes(absPath);
|
|
9164
9494
|
const maxPerOp2 = appConfig.undoMaxBytesPerOp ?? 100 * 1024 * 1024;
|
|
@@ -9173,15 +9503,15 @@ async function backupDelete(common, undoDir, relativePath) {
|
|
|
9173
9503
|
throw new Error(`\u76EE\u5F55 [${relativePath}] \u5185\u542B\u654F\u611F\u6587\u4EF6 ${sensitiveInTree.length} \u4E2A\uFF08\u5982 ${sensitiveInTree[0]}\uFF09\uFF0C\u6309\u7B56\u7565(undoBackupSensitive=deny)\u62D2\u7EDD\u5907\u4EFD\uFF0C\u5199\u5165\u5DF2\u963B\u65AD`);
|
|
9174
9504
|
}
|
|
9175
9505
|
}
|
|
9176
|
-
const treeDest =
|
|
9506
|
+
const treeDest = path28.join(undoDir, "tree");
|
|
9177
9507
|
const sensitiveSet = new Set(sensitiveInTree);
|
|
9178
|
-
await
|
|
9508
|
+
await fs25.cp(absPath, treeDest, {
|
|
9179
9509
|
recursive: true,
|
|
9180
9510
|
force: true,
|
|
9181
9511
|
preserveTimestamps: true,
|
|
9182
9512
|
filter: (src) => {
|
|
9183
9513
|
if (src === absPath) return true;
|
|
9184
|
-
const relWithin =
|
|
9514
|
+
const relWithin = path28.relative(absPath, src).replace(/\\/g, "/");
|
|
9185
9515
|
return !sensitiveSet.has(relWithin);
|
|
9186
9516
|
}
|
|
9187
9517
|
});
|
|
@@ -9197,9 +9527,9 @@ async function backupDelete(common, undoDir, relativePath) {
|
|
|
9197
9527
|
if (st.size > maxPerOp) {
|
|
9198
9528
|
throw new Error(`\u6587\u4EF6 [${relativePath}] \u4F53\u79EF\u7EA6 ${st.size} \u5B57\u8282\u8D85\u8FC7\u5355\u6B21\u5907\u4EFD\u4E0A\u9650 ${maxPerOp}\uFF0C\u5199\u5165\u5DF2\u963B\u65AD\uFF08\u9632\u5185\u5B58\u62D6\u57AE\uFF1B\u53EF\u8C03 undoMaxBytesPerOp\uFF09`);
|
|
9199
9529
|
}
|
|
9200
|
-
const content = await
|
|
9201
|
-
const contentPath =
|
|
9202
|
-
await
|
|
9530
|
+
const content = await fs25.readFile(absPath);
|
|
9531
|
+
const contentPath = path28.join(undoDir, "content");
|
|
9532
|
+
await fs25.writeFile(contentPath, content, { mode: 384 });
|
|
9203
9533
|
return {
|
|
9204
9534
|
...common,
|
|
9205
9535
|
backupKind: "file_content",
|
|
@@ -9242,21 +9572,21 @@ var init_backup = __esm({
|
|
|
9242
9572
|
const walk = async (d) => {
|
|
9243
9573
|
let entries;
|
|
9244
9574
|
try {
|
|
9245
|
-
entries = await
|
|
9575
|
+
entries = await fs25.readdir(d, { withFileTypes: true });
|
|
9246
9576
|
} catch {
|
|
9247
9577
|
return;
|
|
9248
9578
|
}
|
|
9249
9579
|
entries.sort((a, b) => a.name.localeCompare(b.name));
|
|
9250
9580
|
for (const e of entries) {
|
|
9251
|
-
const full =
|
|
9252
|
-
const rel =
|
|
9581
|
+
const full = path28.join(d, e.name);
|
|
9582
|
+
const rel = path28.relative(dir, full).replace(/\\/g, "/");
|
|
9253
9583
|
if (e.isDirectory()) {
|
|
9254
9584
|
h.update(`D ${rel}
|
|
9255
9585
|
`);
|
|
9256
9586
|
await walk(full);
|
|
9257
9587
|
} else if (e.isFile()) {
|
|
9258
9588
|
try {
|
|
9259
|
-
h.update(`F ${rel} ${sha1Buf(await
|
|
9589
|
+
h.update(`F ${rel} ${sha1Buf(await fs25.readFile(full))}
|
|
9260
9590
|
`);
|
|
9261
9591
|
} catch {
|
|
9262
9592
|
}
|
|
@@ -9270,16 +9600,16 @@ var init_backup = __esm({
|
|
|
9270
9600
|
let total = 0;
|
|
9271
9601
|
let entries;
|
|
9272
9602
|
try {
|
|
9273
|
-
entries = await
|
|
9603
|
+
entries = await fs25.readdir(dir, { withFileTypes: true });
|
|
9274
9604
|
} catch {
|
|
9275
9605
|
return 0;
|
|
9276
9606
|
}
|
|
9277
9607
|
for (const e of entries) {
|
|
9278
|
-
const full =
|
|
9608
|
+
const full = path28.join(dir, e.name);
|
|
9279
9609
|
if (e.isDirectory()) total += await getDirTreeBytes(full);
|
|
9280
9610
|
else if (e.isFile()) {
|
|
9281
9611
|
try {
|
|
9282
|
-
total += (await
|
|
9612
|
+
total += (await fs25.stat(full)).size;
|
|
9283
9613
|
} catch {
|
|
9284
9614
|
}
|
|
9285
9615
|
}
|
|
@@ -9291,16 +9621,16 @@ var init_backup = __esm({
|
|
|
9291
9621
|
const walk = async (d) => {
|
|
9292
9622
|
let entries;
|
|
9293
9623
|
try {
|
|
9294
|
-
entries = await
|
|
9624
|
+
entries = await fs25.readdir(d, { withFileTypes: true });
|
|
9295
9625
|
} catch {
|
|
9296
9626
|
return;
|
|
9297
9627
|
}
|
|
9298
9628
|
for (const e of entries) {
|
|
9299
|
-
const full =
|
|
9629
|
+
const full = path28.join(d, e.name);
|
|
9300
9630
|
if (e.isDirectory()) {
|
|
9301
9631
|
await walk(full);
|
|
9302
9632
|
} else if (e.isFile()) {
|
|
9303
|
-
const relWithin =
|
|
9633
|
+
const relWithin = path28.relative(dir, full).replace(/\\/g, "/");
|
|
9304
9634
|
if (isSensitivePath(`${wsRelDir}/${relWithin}`)) found.push(relWithin);
|
|
9305
9635
|
}
|
|
9306
9636
|
}
|
|
@@ -9312,21 +9642,21 @@ var init_backup = __esm({
|
|
|
9312
9642
|
});
|
|
9313
9643
|
|
|
9314
9644
|
// ../core/src/tool/undo/restore.ts
|
|
9315
|
-
import
|
|
9316
|
-
import
|
|
9645
|
+
import fs26 from "fs/promises";
|
|
9646
|
+
import path29 from "path";
|
|
9317
9647
|
import crypto2 from "crypto";
|
|
9318
|
-
async function doRestore(target, sessionId) {
|
|
9319
|
-
if (target.backupKind === "directory_tree") {
|
|
9648
|
+
async function doRestore(target, sessionId, opts) {
|
|
9649
|
+
if (!opts?.force && target.backupKind === "directory_tree") {
|
|
9320
9650
|
const abs = resolveSafePath(target.relativePath);
|
|
9321
9651
|
let exists = false;
|
|
9322
9652
|
try {
|
|
9323
|
-
await
|
|
9653
|
+
await fs26.access(abs);
|
|
9324
9654
|
exists = true;
|
|
9325
9655
|
} catch {
|
|
9326
9656
|
}
|
|
9327
9657
|
if (exists) return `\u274C [undo \u62D2\u7EDD]\uFF1A\u76EE\u6807\u8DEF\u5F84 [${target.relativePath}] \u5DF2\u5B58\u5728\uFF0C\u62D2\u7EDD\u8986\u76D6\u3002\u8BF7\u5148\u624B\u52A8\u5904\u7406\uFF08\u5220\u9664\u6216\u6539\u540D\uFF09\u540E\u91CD\u8BD5\u3002`;
|
|
9328
9658
|
}
|
|
9329
|
-
const newerWarning = await checkNewerChange(target, sessionId);
|
|
9659
|
+
const newerWarning = opts?.force ? "" : await checkNewerChange(target, sessionId);
|
|
9330
9660
|
const reverse = await ensureReverseBackup(target, sessionId);
|
|
9331
9661
|
let msg;
|
|
9332
9662
|
try {
|
|
@@ -9358,7 +9688,7 @@ async function ensureReverseBackup(target, sessionId) {
|
|
|
9358
9688
|
}
|
|
9359
9689
|
let exists = true;
|
|
9360
9690
|
try {
|
|
9361
|
-
await
|
|
9691
|
+
await fs26.access(absPath);
|
|
9362
9692
|
} catch {
|
|
9363
9693
|
exists = false;
|
|
9364
9694
|
}
|
|
@@ -9371,17 +9701,17 @@ async function ensureReverseBackup(target, sessionId) {
|
|
|
9371
9701
|
}
|
|
9372
9702
|
}
|
|
9373
9703
|
const reverseId = createUUID();
|
|
9374
|
-
const reverseDir =
|
|
9375
|
-
await
|
|
9704
|
+
const reverseDir = path29.join(getUndoBackupRoot(sessionId), reverseId);
|
|
9705
|
+
await fs26.mkdir(reverseDir, { recursive: true, mode: 448 });
|
|
9376
9706
|
assertWithinWorkspace(absPath);
|
|
9377
|
-
const st = await
|
|
9707
|
+
const st = await fs26.stat(absPath);
|
|
9378
9708
|
if (st.isDirectory()) {
|
|
9379
|
-
const dest2 =
|
|
9380
|
-
await
|
|
9709
|
+
const dest2 = path29.join(reverseDir, "tree");
|
|
9710
|
+
await fs26.cp(absPath, dest2, { recursive: true, force: true, preserveTimestamps: true });
|
|
9381
9711
|
return { reverseId, backupKind: "directory_tree", backupPath: dest2 };
|
|
9382
9712
|
}
|
|
9383
|
-
const dest =
|
|
9384
|
-
await
|
|
9713
|
+
const dest = path29.join(reverseDir, "content");
|
|
9714
|
+
await fs26.writeFile(dest, await fs26.readFile(absPath));
|
|
9385
9715
|
return { reverseId, backupKind: "file_content", backupPath: dest };
|
|
9386
9716
|
}
|
|
9387
9717
|
async function dispatchRestore(r) {
|
|
@@ -9389,20 +9719,20 @@ async function dispatchRestore(r) {
|
|
|
9389
9719
|
assertWithinWorkspace(absPath);
|
|
9390
9720
|
switch (r.backupKind) {
|
|
9391
9721
|
case "creation_marker": {
|
|
9392
|
-
await
|
|
9722
|
+
await fs26.rm(absPath, { force: true });
|
|
9393
9723
|
return `\u5DF2\u5220\u9664\u65B0\u5EFA\u6587\u4EF6 [${r.relativePath}]`;
|
|
9394
9724
|
}
|
|
9395
9725
|
case "file_content": {
|
|
9396
|
-
await
|
|
9397
|
-
const backupAbs =
|
|
9398
|
-
const content = await
|
|
9399
|
-
await
|
|
9726
|
+
await fs26.mkdir(path29.dirname(absPath), { recursive: true });
|
|
9727
|
+
const backupAbs = path29.join(getUndoBackupRoot(r.sessionId), r.undoId, "content");
|
|
9728
|
+
const content = await fs26.readFile(backupAbs);
|
|
9729
|
+
await fs26.writeFile(absPath, content);
|
|
9400
9730
|
return `\u5DF2\u6062\u590D [${r.relativePath}] \u81F3\u5907\u4EFD\u524D\u5185\u5BB9\uFF08${r.fileSizeBefore ?? content.byteLength} \u5B57\u8282\uFF09`;
|
|
9401
9731
|
}
|
|
9402
9732
|
case "directory_tree": {
|
|
9403
|
-
await
|
|
9404
|
-
const src =
|
|
9405
|
-
await
|
|
9733
|
+
await fs26.mkdir(path29.dirname(absPath), { recursive: true });
|
|
9734
|
+
const src = path29.join(getUndoBackupRoot(r.sessionId), r.undoId, "tree");
|
|
9735
|
+
await fs26.cp(src, absPath, { recursive: true, force: true, preserveTimestamps: true });
|
|
9406
9736
|
return `\u5DF2\u6062\u590D\u76EE\u5F55\u6811 [${r.relativePath}]\uFF08\u7EA6 ${r.fileSizeBefore ?? 0} \u5B57\u8282\uFF09`;
|
|
9407
9737
|
}
|
|
9408
9738
|
}
|
|
@@ -9435,7 +9765,7 @@ var init_restore = __esm({
|
|
|
9435
9765
|
init_common();
|
|
9436
9766
|
init_traceCalculate();
|
|
9437
9767
|
sha1File = async (absPath) => {
|
|
9438
|
-
const buf = await
|
|
9768
|
+
const buf = await fs26.readFile(absPath);
|
|
9439
9769
|
return crypto2.createHash("sha1").update(buf).digest("hex");
|
|
9440
9770
|
};
|
|
9441
9771
|
listUndoable = async (sessionId) => {
|
|
@@ -9717,7 +10047,7 @@ ${diff.slice(0, 1500)}` : "";
|
|
|
9717
10047
|
});
|
|
9718
10048
|
|
|
9719
10049
|
// ../core/src/tool/registry/notebook.ts
|
|
9720
|
-
import
|
|
10050
|
+
import fs27 from "fs/promises";
|
|
9721
10051
|
var toArraySource, encodeSource, makeCell, applyNotebookEdit, notebookTools;
|
|
9722
10052
|
var init_notebook = __esm({
|
|
9723
10053
|
"../core/src/tool/registry/notebook.ts"() {
|
|
@@ -9821,7 +10151,7 @@ ${String(args.new_source).slice(0, 500)}` : ""}`,
|
|
|
9821
10151
|
}
|
|
9822
10152
|
let raw;
|
|
9823
10153
|
try {
|
|
9824
|
-
raw = await
|
|
10154
|
+
raw = await fs27.readFile(absPath, "utf-8");
|
|
9825
10155
|
} catch (e) {
|
|
9826
10156
|
return toolFailure(`[notebook_edit] \u8BFB\u53D6\u5931\u8D25\uFF1A${e?.message ?? e}`);
|
|
9827
10157
|
}
|
|
@@ -9851,10 +10181,10 @@ ${String(args.new_source).slice(0, 500)}` : ""}`,
|
|
|
9851
10181
|
}
|
|
9852
10182
|
const tmpPath = makeTmpPath(absPath);
|
|
9853
10183
|
try {
|
|
9854
|
-
await
|
|
9855
|
-
await
|
|
10184
|
+
await fs27.writeFile(tmpPath, JSON.stringify(nb, null, 2), "utf-8");
|
|
10185
|
+
await fs27.rename(tmpPath, absPath);
|
|
9856
10186
|
} catch (e) {
|
|
9857
|
-
await
|
|
10187
|
+
await fs27.unlink(tmpPath).catch(() => {
|
|
9858
10188
|
});
|
|
9859
10189
|
return toolFailure(`[notebook_edit] \u5199\u5165\u5931\u8D25\uFF1A${e?.message ?? e}`);
|
|
9860
10190
|
}
|
|
@@ -9894,8 +10224,8 @@ var init_frontmatter = __esm({
|
|
|
9894
10224
|
});
|
|
9895
10225
|
|
|
9896
10226
|
// ../core/src/memory/loader.ts
|
|
9897
|
-
import
|
|
9898
|
-
import
|
|
10227
|
+
import fs28 from "fs/promises";
|
|
10228
|
+
import path30 from "path";
|
|
9899
10229
|
var GLOBAL_MEMORY_DIR, SOURCES, VALID_TYPES, parseMemoryAt, loadMemories, initMemories;
|
|
9900
10230
|
var init_loader3 = __esm({
|
|
9901
10231
|
"../core/src/memory/loader.ts"() {
|
|
@@ -9904,16 +10234,16 @@ var init_loader3 = __esm({
|
|
|
9904
10234
|
init_frontmatter();
|
|
9905
10235
|
init_registry6();
|
|
9906
10236
|
init_registry2();
|
|
9907
|
-
GLOBAL_MEMORY_DIR =
|
|
10237
|
+
GLOBAL_MEMORY_DIR = path30.join(appConfig.dataDir, "memory");
|
|
9908
10238
|
SOURCES = [
|
|
9909
10239
|
{ dir: GLOBAL_MEMORY_DIR, source: "global" },
|
|
9910
|
-
{ dir:
|
|
10240
|
+
{ dir: path30.join(process.cwd(), ".deepseeker-code", "memory"), source: "project" }
|
|
9911
10241
|
];
|
|
9912
10242
|
VALID_TYPES = ["user", "feedback", "project", "reference"];
|
|
9913
10243
|
parseMemoryAt = async (file, _dir, source) => {
|
|
9914
10244
|
let raw;
|
|
9915
10245
|
try {
|
|
9916
|
-
raw = await
|
|
10246
|
+
raw = await fs28.readFile(file, "utf-8");
|
|
9917
10247
|
} catch {
|
|
9918
10248
|
return null;
|
|
9919
10249
|
}
|
|
@@ -9947,7 +10277,7 @@ var init_loader3 = __esm({
|
|
|
9947
10277
|
clearMemories();
|
|
9948
10278
|
const picked = await scanSources(
|
|
9949
10279
|
filterSources(SOURCES, includeProject),
|
|
9950
|
-
(e, dir) => e.isFile() && e.name.endsWith(".md") ?
|
|
10280
|
+
(e, dir) => e.isFile() && e.name.endsWith(".md") ? path30.join(dir, e.name) : void 0,
|
|
9951
10281
|
parseMemoryAt
|
|
9952
10282
|
);
|
|
9953
10283
|
for (const { item } of picked) registerMemory(item);
|
|
@@ -9965,15 +10295,15 @@ var init_loader3 = __esm({
|
|
|
9965
10295
|
});
|
|
9966
10296
|
|
|
9967
10297
|
// ../core/src/memory/usage.ts
|
|
9968
|
-
import
|
|
9969
|
-
import
|
|
10298
|
+
import fs29 from "fs/promises";
|
|
10299
|
+
import path31 from "path";
|
|
9970
10300
|
var USAGE_FILE, readUsage, recordMemoryUse;
|
|
9971
10301
|
var init_usage = __esm({
|
|
9972
10302
|
"../core/src/memory/usage.ts"() {
|
|
9973
10303
|
"use strict";
|
|
9974
10304
|
init_loader3();
|
|
9975
10305
|
init_common();
|
|
9976
|
-
USAGE_FILE =
|
|
10306
|
+
USAGE_FILE = path31.join(GLOBAL_MEMORY_DIR, ".usage.json");
|
|
9977
10307
|
readUsage = async () => {
|
|
9978
10308
|
const raw = await readJSONFile(USAGE_FILE);
|
|
9979
10309
|
return raw && typeof raw === "object" && !Array.isArray(raw) ? raw : {};
|
|
@@ -9986,8 +10316,8 @@ var init_usage = __esm({
|
|
|
9986
10316
|
lastUsed: (/* @__PURE__ */ new Date()).toISOString(),
|
|
9987
10317
|
reads: (prev?.reads ?? 0) + (kind === "read" ? 1 : 0)
|
|
9988
10318
|
};
|
|
9989
|
-
await
|
|
9990
|
-
await
|
|
10319
|
+
await fs29.mkdir(GLOBAL_MEMORY_DIR, { recursive: true });
|
|
10320
|
+
await fs29.writeFile(USAGE_FILE, JSON.stringify(map, null, 2), "utf-8");
|
|
9991
10321
|
} catch (e) {
|
|
9992
10322
|
console.warn(`\u26A0\uFE0F [memory] \u4F7F\u7528\u753B\u50CF\u8BB0\u5F55\u5931\u8D25\uFF08\u5DF2\u5FFD\u7565\uFF09: ${e?.message ?? e}`);
|
|
9993
10323
|
}
|
|
@@ -9996,8 +10326,8 @@ var init_usage = __esm({
|
|
|
9996
10326
|
});
|
|
9997
10327
|
|
|
9998
10328
|
// ../core/src/tool/registry/memory.ts
|
|
9999
|
-
import
|
|
10000
|
-
import
|
|
10329
|
+
import fs30 from "fs/promises";
|
|
10330
|
+
import path32 from "path";
|
|
10001
10331
|
var MAX_BODY_BYTES, MAX_DESCRIPTION_CHARS, MEMORY_LIMITS, NAME_RE, VALID_TYPES2, memoryFilePath, sanitizeLine, buildMemoryMd, writeAndRegister, indexLineBytes, memoryTools;
|
|
10002
10332
|
var init_memory = __esm({
|
|
10003
10333
|
"../core/src/tool/registry/memory.ts"() {
|
|
@@ -10012,7 +10342,7 @@ var init_memory = __esm({
|
|
|
10012
10342
|
MEMORY_LIMITS = { maxCount: 200, maxIndexBytes: 16 * 1024 };
|
|
10013
10343
|
NAME_RE = /^[a-z0-9-]+$/;
|
|
10014
10344
|
VALID_TYPES2 = ["user", "feedback", "project", "reference"];
|
|
10015
|
-
memoryFilePath = (name, project) => project ?
|
|
10345
|
+
memoryFilePath = (name, project) => project ? path32.join(process.cwd(), ".deepseeker-code", "memory", `${name}.md`) : path32.join(GLOBAL_MEMORY_DIR, `${name}.md`);
|
|
10016
10346
|
sanitizeLine = (s) => String(s ?? "").replace(/[\r\n]+/g, " ").trim();
|
|
10017
10347
|
buildMemoryMd = (name, description, type, body) => `---
|
|
10018
10348
|
name: ${name}
|
|
@@ -10024,10 +10354,10 @@ ${body.trim()}
|
|
|
10024
10354
|
`;
|
|
10025
10355
|
writeAndRegister = async (name, description, type, body, project) => {
|
|
10026
10356
|
const file = memoryFilePath(name, project);
|
|
10027
|
-
await
|
|
10357
|
+
await fs30.mkdir(path32.dirname(file), { recursive: true });
|
|
10028
10358
|
const tmp = makeTmpPath(file);
|
|
10029
|
-
await
|
|
10030
|
-
await
|
|
10359
|
+
await fs30.writeFile(tmp, buildMemoryMd(name, description, type, body), "utf-8");
|
|
10360
|
+
await fs30.rename(tmp, file);
|
|
10031
10361
|
registerMemory({ name, description, type, body: body.trim(), source: project ? "project" : "global", file });
|
|
10032
10362
|
return file;
|
|
10033
10363
|
};
|
|
@@ -10162,7 +10492,7 @@ ${lines.join("\n")}`;
|
|
|
10162
10492
|
const m = getMemory(name);
|
|
10163
10493
|
if (!m) return toolFailure(`\u672A\u627E\u5230\u8BB0\u5FC6\uFF1A${name}\uFF08\u53EF\u80FD\u5DF2\u88AB\u5220\u9664\uFF09\u3002`);
|
|
10164
10494
|
try {
|
|
10165
|
-
await
|
|
10495
|
+
await fs30.unlink(m.file);
|
|
10166
10496
|
} catch {
|
|
10167
10497
|
}
|
|
10168
10498
|
unregisterMemory(name);
|
|
@@ -10174,9 +10504,9 @@ ${lines.join("\n")}`;
|
|
|
10174
10504
|
}
|
|
10175
10505
|
});
|
|
10176
10506
|
|
|
10177
|
-
// ../core/src/session/sidecar.ts
|
|
10178
|
-
import
|
|
10179
|
-
import
|
|
10507
|
+
// ../core/src/session/sidecar.ts
|
|
10508
|
+
import fs31 from "fs/promises";
|
|
10509
|
+
import path33 from "path";
|
|
10180
10510
|
var SIDECAR_ARCHIVED_MARK, sidecarArchivedNote, safeSidecarId, getToolOutputSidecarPath, getToolOutputSidecarDir, ensuredSidecarDirs, SIDECAR_SESSION_CAP_BYTES, listSidecarFiles, writeSidecarArchive;
|
|
10181
10511
|
var init_sidecar = __esm({
|
|
10182
10512
|
"../core/src/session/sidecar.ts"() {
|
|
@@ -10185,21 +10515,21 @@ var init_sidecar = __esm({
|
|
|
10185
10515
|
SIDECAR_ARCHIVED_MARK = "\u5B8C\u6574\u539F\u6587\u5DF2\u5B58\u6863";
|
|
10186
10516
|
sidecarArchivedNote = (toolCallId) => `${SIDECAR_ARCHIVED_MARK}\uFF0Crecall \u5DE5\u5177\u4F20 with_full="${toolCallId}" \u53EF\u53D6\u56DE`;
|
|
10187
10517
|
safeSidecarId = (id) => String(id).replace(/[^A-Za-z0-9_-]/g, "");
|
|
10188
|
-
getToolOutputSidecarPath = (sessionId, toolCallId) =>
|
|
10189
|
-
getToolOutputSidecarDir = (sessionId) =>
|
|
10518
|
+
getToolOutputSidecarPath = (sessionId, toolCallId) => path33.join(getSessionsDirPath(sessionId), "tool-outputs", `${safeSidecarId(toolCallId)}.txt`);
|
|
10519
|
+
getToolOutputSidecarDir = (sessionId) => path33.join(getSessionsDirPath(sessionId), "tool-outputs");
|
|
10190
10520
|
ensuredSidecarDirs = /* @__PURE__ */ new Set();
|
|
10191
10521
|
SIDECAR_SESSION_CAP_BYTES = 64 * 1024 * 1024;
|
|
10192
10522
|
listSidecarFiles = async (dir) => {
|
|
10193
10523
|
let names;
|
|
10194
10524
|
try {
|
|
10195
|
-
names = await
|
|
10525
|
+
names = await fs31.readdir(dir);
|
|
10196
10526
|
} catch {
|
|
10197
10527
|
return [];
|
|
10198
10528
|
}
|
|
10199
10529
|
const out = [];
|
|
10200
10530
|
for (const name of names) {
|
|
10201
10531
|
try {
|
|
10202
|
-
const st = await
|
|
10532
|
+
const st = await fs31.stat(path33.join(dir, name));
|
|
10203
10533
|
if (st.isFile()) out.push({ name, size: st.size, mtimeMs: st.mtimeMs });
|
|
10204
10534
|
} catch {
|
|
10205
10535
|
}
|
|
@@ -10210,7 +10540,7 @@ var init_sidecar = __esm({
|
|
|
10210
10540
|
try {
|
|
10211
10541
|
const dir = getToolOutputSidecarDir(sessionId);
|
|
10212
10542
|
if (!ensuredSidecarDirs.has(dir)) {
|
|
10213
|
-
await
|
|
10543
|
+
await fs31.mkdir(dir, { recursive: true });
|
|
10214
10544
|
ensuredSidecarDirs.add(dir);
|
|
10215
10545
|
}
|
|
10216
10546
|
const cap = opts?.capBytes ?? SIDECAR_SESSION_CAP_BYTES;
|
|
@@ -10223,13 +10553,13 @@ var init_sidecar = __esm({
|
|
|
10223
10553
|
for (const f of byOldest) {
|
|
10224
10554
|
if (total - freed + incoming <= cap) break;
|
|
10225
10555
|
try {
|
|
10226
|
-
await
|
|
10556
|
+
await fs31.unlink(path33.join(dir, f.name));
|
|
10227
10557
|
freed += f.size;
|
|
10228
10558
|
} catch {
|
|
10229
10559
|
}
|
|
10230
10560
|
}
|
|
10231
10561
|
}
|
|
10232
|
-
await
|
|
10562
|
+
await fs31.writeFile(getToolOutputSidecarPath(sessionId, toolCallId), content, "utf-8");
|
|
10233
10563
|
return sidecarArchivedNote(toolCallId);
|
|
10234
10564
|
} catch (e) {
|
|
10235
10565
|
console.warn("\u26A0\uFE0F [sidecar] \u5DE5\u5177\u539F\u6587\u5B58\u6863\u5931\u8D25\uFF08\u5DF2\u964D\u7EA7\u4E3A\u666E\u901A\u622A\u65AD\u63D0\u793A\uFF09:", e instanceof Error ? e.message : e);
|
|
@@ -10240,9 +10570,9 @@ var init_sidecar = __esm({
|
|
|
10240
10570
|
});
|
|
10241
10571
|
|
|
10242
10572
|
// ../core/src/tool/registry/recall.ts
|
|
10243
|
-
import
|
|
10244
|
-
import
|
|
10245
|
-
var escapeRegExp2, lineText, primaryPathArg, annotateStaleness, snippetAround, recallTools;
|
|
10573
|
+
import fs32 from "fs/promises";
|
|
10574
|
+
import path34 from "path";
|
|
10575
|
+
var escapeRegExp2, lineText, primaryPathArg, annotateStaleness, snippetAround, recallHitCounts, getRecallHitCount, recallTools;
|
|
10246
10576
|
var init_recall = __esm({
|
|
10247
10577
|
"../core/src/tool/registry/recall.ts"() {
|
|
10248
10578
|
"use strict";
|
|
@@ -10272,9 +10602,9 @@ var init_recall = __esm({
|
|
|
10272
10602
|
annotateStaleness = async (args, observedAt) => {
|
|
10273
10603
|
const p = primaryPathArg(args);
|
|
10274
10604
|
if (!p) return "\u5FEB\u7167\uFF08\u65E0\u8DEF\u5F84\u5B9E\u4F53\uFF0C\u672A\u7ECF\u91CD\u9A8C\u2014\u2014\u636E\u4EE5\u884C\u52A8\u524D\u8BF7\u91CD\u8DD1\u9A8C\u8BC1\uFF09";
|
|
10275
|
-
const abs =
|
|
10605
|
+
const abs = path34.isAbsolute(p) ? p : path34.resolve(getActiveWorkspaceRoot(), p);
|
|
10276
10606
|
try {
|
|
10277
|
-
const st = await
|
|
10607
|
+
const st = await fs32.stat(abs);
|
|
10278
10608
|
if (observedAt && st.mtime.toISOString() > observedAt) {
|
|
10279
10609
|
return `\u26A0\uFE0F \u89C2\u5BDF\u540E\u8BE5\u6587\u4EF6\u5DF2\u88AB\u4FEE\u6539\uFF08${p}\uFF09\u2014\u2014\u5FC5\u987B\u91CD\u65B0 read_file \u540E\u624D\u80FD\u636E\u4EE5\u4FEE\u6539`;
|
|
10280
10610
|
}
|
|
@@ -10291,6 +10621,8 @@ var init_recall = __esm({
|
|
|
10291
10621
|
const tailMark = start + maxChars < text.length ? "\u2026\uFF08\u7247\u6BB5\u622A\u65AD\uFF0C\u5B8C\u6574\u5185\u5BB9\u53EF\u7528 with_full\uFF09" : "";
|
|
10292
10622
|
return `${headMark}${slice}${tailMark}`;
|
|
10293
10623
|
};
|
|
10624
|
+
recallHitCounts = /* @__PURE__ */ new Map();
|
|
10625
|
+
getRecallHitCount = (sessionId) => recallHitCounts.get(sessionId) ?? 0;
|
|
10294
10626
|
recallTools = [
|
|
10295
10627
|
{
|
|
10296
10628
|
type: "function",
|
|
@@ -10322,7 +10654,7 @@ var init_recall = __esm({
|
|
|
10322
10654
|
const sidecar = getToolOutputSidecarPath(ctx.sessionId, args.with_full);
|
|
10323
10655
|
let full = "";
|
|
10324
10656
|
try {
|
|
10325
|
-
full = await
|
|
10657
|
+
full = await fs32.readFile(sidecar, "utf-8");
|
|
10326
10658
|
} catch {
|
|
10327
10659
|
return toolFailure(`[recall] \u672A\u627E\u5230\u8BE5 id \u7684\u5B58\u6863\u539F\u6587\uFF08\u53EF\u80FD\u672A\u66FE\u89E6\u53D1\u622A\u65AD\u5B58\u6863\u3001\u6216\u4F1A\u8BDD\u5DF2\u6E05\u7406\uFF09\uFF1A${args.with_full}`);
|
|
10328
10660
|
}
|
|
@@ -10376,12 +10708,12 @@ ${slice}${more}`;
|
|
|
10376
10708
|
}
|
|
10377
10709
|
const text = lineText(l);
|
|
10378
10710
|
if (!text || !re.test(text)) continue;
|
|
10379
|
-
const
|
|
10711
|
+
const ts2 = l.ts;
|
|
10380
10712
|
const roleDesc = role === "tool" ? `${info?.name ?? "tool"} \u8C03\u7528\u7ED3\u679C` : role === "assistant" ? "assistant\uFF08\u6587\u672C/\u5DE5\u5177\u8C03\u7528\u53C2\u6570\uFF09" : "\u7528\u6237\u6D88\u606F";
|
|
10381
|
-
let header = `\u2500\u2500 \u547D\u4E2D${blocks.length + 1} \xB7 run#${runN}${runId ? `(${runId.slice(0, 8)})` : ""} \xB7 ${roleDesc} \xB7 ${
|
|
10713
|
+
let header = `\u2500\u2500 \u547D\u4E2D${blocks.length + 1} \xB7 run#${runN}${runId ? `(${runId.slice(0, 8)})` : ""} \xB7 ${roleDesc} \xB7 ${ts2 ?? "\u65F6\u95F4\u672A\u77E5"} \u2500\u2500`;
|
|
10382
10714
|
if (role === "tool") {
|
|
10383
10715
|
header += `
|
|
10384
|
-
\u6821\u9A8C\uFF1A${await annotateStaleness(info?.args,
|
|
10716
|
+
\u6821\u9A8C\uFF1A${await annotateStaleness(info?.args, ts2)}`;
|
|
10385
10717
|
if (typeof l.content === "string" && l.content.includes(SIDECAR_ARCHIVED_MARK)) {
|
|
10386
10718
|
header += `
|
|
10387
10719
|
\u2702\uFE0F \u8BE5\u7ED3\u679C\u66FE\u88AB\u622A\u65AD\uFF0C\u4F20 with_full="${l.tool_call_id}" \u53EF\u53D6\u5B58\u6863\u5168\u6587`;
|
|
@@ -10399,6 +10731,7 @@ ${snippetAround(text, re, 700)}`);
|
|
|
10399
10731
|
"\xB7 \u8BB0\u5F97\u5F52\u6863\u533A\u5728\u6458\u8981\u69FD\u4E4B\u524D\u7684\u66F4\u65E9\u8F6E\u6B21\u2014\u2014\u7528\u66F4\u65E9\u9636\u6BB5\u51FA\u73B0\u8FC7\u7684\u8BCD"
|
|
10400
10732
|
].join("\n");
|
|
10401
10733
|
}
|
|
10734
|
+
recallHitCounts.set(ctx.sessionId, (recallHitCounts.get(ctx.sessionId) ?? 0) + 1);
|
|
10402
10735
|
return [
|
|
10403
10736
|
`[recall] \u672C\u4F1A\u8BDD\u5168\u91CF\u8F6C\u5F55\u547D\u4E2D ${blocks.length} \u6761\uFF08\u6309\u65F6\u95F4\u65E7\u2192\u65B0\uFF0C\u542B\u5DF2\u5F52\u6863\u6D88\u606F\uFF09\uFF1A`,
|
|
10404
10737
|
"",
|
|
@@ -10532,7 +10865,7 @@ var init_spreadsheet = __esm({
|
|
|
10532
10865
|
});
|
|
10533
10866
|
|
|
10534
10867
|
// ../core/src/tool/registry/document.ts
|
|
10535
|
-
import
|
|
10868
|
+
import fs33 from "fs/promises";
|
|
10536
10869
|
var getMammoth, getUnpdf, documentTools;
|
|
10537
10870
|
var init_document = __esm({
|
|
10538
10871
|
"../core/src/tool/registry/document.ts"() {
|
|
@@ -10622,7 +10955,7 @@ var init_document = __esm({
|
|
|
10622
10955
|
}
|
|
10623
10956
|
const start = args.start_char ? Math.max(0, Math.floor(args.start_char)) : 0;
|
|
10624
10957
|
const maxChars = Math.min(args.max_chars ? Math.max(1, Math.floor(args.max_chars)) : 3e4, 5e4);
|
|
10625
|
-
const buf = await
|
|
10958
|
+
const buf = await fs33.readFile(absPath);
|
|
10626
10959
|
const unpdf = await getUnpdf();
|
|
10627
10960
|
const pdf = await unpdf.getDocumentProxy(new Uint8Array(buf));
|
|
10628
10961
|
const { text, totalPages } = await unpdf.extractText(pdf, { mergePages: true });
|
|
@@ -10950,7 +11283,7 @@ var init_backgroundTool = __esm({
|
|
|
10950
11283
|
});
|
|
10951
11284
|
|
|
10952
11285
|
// ../core/src/tool/autoPermission.ts
|
|
10953
|
-
import
|
|
11286
|
+
import path35 from "path";
|
|
10954
11287
|
var isMcpTool, BUILTIN_AUTO_DENY, matchBuiltinDeny, COMMAND_DENY, matchCommandDeny, hasShellMetachars, READONLY_HEADS, PKG_MGR, SCRIPT_RUNNER_HEADS, SCRIPT_RUNNER_READONLY, isScriptRunnerCommand, hasWriteModifier, SENSITIVE_FILE_ARG_RE, hasSensitiveFileArg, isReadOnlyCommand, isWithinWorkspace, runAutoCheck;
|
|
10955
11288
|
var init_autoPermission = __esm({
|
|
10956
11289
|
"../core/src/tool/autoPermission.ts"() {
|
|
@@ -11095,9 +11428,9 @@ var init_autoPermission = __esm({
|
|
|
11095
11428
|
isWithinWorkspace = (p, cwd) => {
|
|
11096
11429
|
if (!p || !cwd) return false;
|
|
11097
11430
|
try {
|
|
11098
|
-
const abs =
|
|
11099
|
-
const rel =
|
|
11100
|
-
return rel === "" || !rel.startsWith("..") && !
|
|
11431
|
+
const abs = path35.isAbsolute(p) ? p : path35.resolve(cwd, p);
|
|
11432
|
+
const rel = path35.relative(cwd, abs);
|
|
11433
|
+
return rel === "" || !rel.startsWith("..") && !path35.isAbsolute(rel);
|
|
11101
11434
|
} catch {
|
|
11102
11435
|
return false;
|
|
11103
11436
|
}
|
|
@@ -11126,7 +11459,7 @@ var init_autoPermission = __esm({
|
|
|
11126
11459
|
});
|
|
11127
11460
|
|
|
11128
11461
|
// ../core/src/agent/toolExecution.ts
|
|
11129
|
-
import
|
|
11462
|
+
import path36 from "path";
|
|
11130
11463
|
var applyPrivacyMasking, scaleTruncBudget, processToolCall;
|
|
11131
11464
|
var init_toolExecution = __esm({
|
|
11132
11465
|
"../core/src/agent/toolExecution.ts"() {
|
|
@@ -11187,7 +11520,8 @@ var init_toolExecution = __esm({
|
|
|
11187
11520
|
compactRatio,
|
|
11188
11521
|
modelWindow,
|
|
11189
11522
|
parentSystemPrompt,
|
|
11190
|
-
readTracker
|
|
11523
|
+
readTracker,
|
|
11524
|
+
reportCost
|
|
11191
11525
|
} = ctx;
|
|
11192
11526
|
let calledName = "";
|
|
11193
11527
|
let calledArgs = {};
|
|
@@ -11225,7 +11559,7 @@ var init_toolExecution = __esm({
|
|
|
11225
11559
|
events({ sessionId, eventType: "tool.validation.failed", metadata: { depth, decisionSource: llmDecisionSource, durationMs: performance.now() - startTime, round, tools_id: toolCall.id, toolName: calledName, toolSource: "builtin", ok: false, attempt: round }, payload: { output: note } });
|
|
11226
11560
|
return { toolCallId: toolCall.id, calledName, calledArgs, resultForModel: note, resultForUser: note, ok: false };
|
|
11227
11561
|
}
|
|
11228
|
-
const toolCtx = { sessionId, cwd: getActiveWorkspaceRoot(), abortSignal: signal, depth, keepRecentUnits, compactRatio, modelWindow, parentSystemPrompt, events, onUIEvent, requestApproval: hostRequestApproval, requestQuestion: hostRequestQuestion, ideAction, emitProgress: (m) => onUIEvent?.({ type: "tool.progress", toolsId: toolCall.id, toolName: calledName, message: m }), permissionMode, readTracker };
|
|
11562
|
+
const toolCtx = { sessionId, cwd: getActiveWorkspaceRoot(), abortSignal: signal, depth, keepRecentUnits, compactRatio, modelWindow, parentSystemPrompt, events, onUIEvent, requestApproval: hostRequestApproval, requestQuestion: hostRequestQuestion, ideAction, emitProgress: (m) => onUIEvent?.({ type: "tool.progress", toolsId: toolCall.id, toolName: calledName, message: m }), permissionMode, readTracker, reportCost };
|
|
11229
11563
|
let result = "";
|
|
11230
11564
|
let resultStatus = "success";
|
|
11231
11565
|
let errorCategory;
|
|
@@ -11296,7 +11630,7 @@ var init_toolExecution = __esm({
|
|
|
11296
11630
|
const argCwd = typeof calledArgs?.cwd === "string" ? calledArgs.cwd.trim() : "";
|
|
11297
11631
|
const samePath = (a, b) => {
|
|
11298
11632
|
try {
|
|
11299
|
-
const ra =
|
|
11633
|
+
const ra = path36.resolve(a), rb = path36.resolve(b);
|
|
11300
11634
|
return process.platform === "win32" ? ra.toLowerCase() === rb.toLowerCase() : ra === rb;
|
|
11301
11635
|
} catch {
|
|
11302
11636
|
return false;
|
|
@@ -11870,7 +12204,7 @@ var init_streamInference = __esm({
|
|
|
11870
12204
|
});
|
|
11871
12205
|
|
|
11872
12206
|
// ../core/src/agent/agentNudges.ts
|
|
11873
|
-
var NUDGE_EVERY, NUDGE_FENCE, PHANTOM_FENCE, PHANTOM_RETRY_MAX, EARLY_FINAL_FENCE, EARLY_FINAL_TURN_THRESHOLD, EARLY_FINAL_MAX, TOOL_DIGEST_FENCE, TOOL_DIGEST_MAX, TOOL_DIGEST_WINDOW, TOOL_DIGEST_TEXT_MAX_LEN, PLAN_FIRST_FENCE, REPEAT_FENCE, READ_REPEAT_THRESHOLD, GREP_REPEAT_THRESHOLD, REPEAT_NUDGE_MAX, TODO_INCOMPLETE_FENCE, TODO_INCOMPLETE_MAX, PHANTOM_TEXT, EARLY_FINAL_TEXT, TOOL_DIGEST_TEXT, usageNoteText, NUDGE_TEXT, COMPLEX_VERBS, COMPLEX_OBJECTS, COMPLEX_MARKERS, QUERY_LEAD, looksComplex, PLAN_FIRST_TEXT, looksComplete, parseToolCall, normPath, normQuery, REPEAT_READ_TEXT, REPEAT_GREP_TEXT, TODO_INCOMPLETE_TEXT, createNudgeScheduler;
|
|
12207
|
+
var NUDGE_EVERY, NUDGE_FENCE, PHANTOM_FENCE, PHANTOM_RETRY_MAX, EARLY_FINAL_FENCE, EARLY_FINAL_TURN_THRESHOLD, EARLY_FINAL_MAX, TOOL_DIGEST_FENCE, TOOL_DIGEST_MAX, TOOL_DIGEST_WINDOW, TOOL_DIGEST_TEXT_MAX_LEN, PLAN_FIRST_FENCE, REPEAT_FENCE, READ_REPEAT_THRESHOLD, GREP_REPEAT_THRESHOLD, REPEAT_NUDGE_MAX, TODO_INCOMPLETE_FENCE, TODO_INCOMPLETE_MAX, BUDGET_FENCE, BUDGET_SOFT_TEXT, PHANTOM_TEXT, EARLY_FINAL_TEXT, TOOL_DIGEST_TEXT, usageNoteText, NUDGE_TEXT, COMPLEX_VERBS, COMPLEX_OBJECTS, COMPLEX_MARKERS, QUERY_LEAD, looksComplex, PLAN_FIRST_TEXT, looksComplete, parseToolCall, normPath, normQuery, REPEAT_READ_TEXT, REPEAT_GREP_TEXT, TODO_INCOMPLETE_TEXT, createNudgeScheduler;
|
|
11874
12208
|
var init_agentNudges = __esm({
|
|
11875
12209
|
"../core/src/agent/agentNudges.ts"() {
|
|
11876
12210
|
"use strict";
|
|
@@ -11892,6 +12226,11 @@ var init_agentNudges = __esm({
|
|
|
11892
12226
|
REPEAT_NUDGE_MAX = 3;
|
|
11893
12227
|
TODO_INCOMPLETE_FENCE = "\u27E6DSC:TODO_INCOMPLETE\u27E7";
|
|
11894
12228
|
TODO_INCOMPLETE_MAX = 1;
|
|
12229
|
+
BUDGET_FENCE = "\u27E6DSC:BUDGET\u27E7";
|
|
12230
|
+
BUDGET_SOFT_TEXT = (spent, budget) => {
|
|
12231
|
+
const pct = budget > 0 ? Math.round(spent / budget * 100) : 100;
|
|
12232
|
+
return `\u5DF2\u82B1\u8D39 \xA5${spent.toFixed(3)} / \u9884\u7B97 \xA5${budget.toFixed(3)}\uFF08${pct}%\uFF09\uFF1A\u8BF7\u6536\u655B\u6536\u5C3E\uFF0C\u4E0D\u518D\u5C55\u5F00\u65B0\u63A2\u7D22\uFF1B\u82E5\u786E\u9700\u7EE7\u7EED\uFF0C\u7528\u4E00\u6BB5\u8BF4\u660E\u5269\u4F59\u5DE5\u4F5C\u540E\u5373\u6B62\u3002`;
|
|
12233
|
+
};
|
|
11895
12234
|
PHANTOM_TEXT = "\u4F60\u7684\u4E0A\u4E00\u6761\u56DE\u590D\u6CA1\u6709\u4EFB\u4F55\u5185\u5BB9\u3001\u4E5F\u6CA1\u6709\u8C03\u7528\u4EFB\u4F55\u5DE5\u5177\uFF0C\u4F46\u4EFB\u52A1\u5C1A\u672A\u5B8C\u6210\u3002\u8BF7\u7EE7\u7EED\u63A8\u8FDB\uFF08\u8C03\u7528\u5DE5\u5177\u6216\u7ED9\u51FA\u5B9E\u8D28\u56DE\u7B54\uFF09\uFF1B\u82E5\u786E\u5B9E\u53D7\u963B\u3001\u9700\u8981\u7528\u6237\u51B3\u7B56\uFF0C\u7528 ask_question \u8BF4\u660E\u5177\u4F53\u963B\u585E\u70B9\u3002\u4E0D\u8981\u8FD4\u56DE\u7A7A\u56DE\u590D\u3002";
|
|
11896
12235
|
EARLY_FINAL_TEXT = (round) => `\u4F60\u4EC5 ${round} \u8F6E\u5C31\u51C6\u5907\u6536\u5C3E\uFF0C\u4E14\u56DE\u7B54\u4E2D\u6CA1\u6709\u660E\u786E\u7684\u5B8C\u6210\u58F0\u660E\u3002\u8BF7\u81EA\u68C0\uFF1A\u82E5\u7528\u6237\u8F93\u5165\u672C\u5C31\u65E0\u9700\u5DE5\u5177\uFF08\u5BD2\u6684/\u95F2\u804A/\u7EAF\u95EE\u7B54\uFF09\u3001\u6216\u4F60\u5728\u7B49\u7528\u6237\u6F84\u6E05\u51B3\u7B56\uFF0C\u76F4\u63A5\u6B63\u5E38\u56DE\u5E94\u5373\u53EF\uFF0C\u5FFD\u7565\u672C\u81EA\u68C0\u3001\u4E0D\u8981\u8F93\u51FA\u4EFB\u4F55\u81EA\u68C0\u8BF4\u660E\uFF1B\u82E5\u786E\u6709\u4EFB\u52A1\u672A\u843D\u5730\uFF08\u6240\u9700\u4FE1\u606F\u672A\u83B7\u53D6\u9F50 / \u8BE5\u6539\u7684\u6587\u4EF6\u672A\u6539\u5B8C / \u672A\u9A8C\u8BC1\uFF09\uFF0C\u7ACB\u5373\u7EE7\u7EED\u8C03\u7528\u5DE5\u5177\u63A8\u8FDB\uFF0C\u4E0D\u8981\u8349\u7387\u603B\u7ED3\u6536\u5C3E\uFF1B\u82E5\u786E\u5DF2\u5168\u90E8\u5B8C\u6210\uFF0C\u8BF7\u660E\u786E\u56DE\u590D\u300C\u5DF2\u5B8C\u6210\u300D\u5E76\u7B80\u8FF0\u6210\u679C\u3002`;
|
|
11897
12236
|
TOOL_DIGEST_TEXT = "\u4F60\u521A\u6267\u884C\u5B8C\u5DE5\u5177\u62FF\u5230\u7ED3\u679C\uFF0C\u5374\u672A\u57FA\u4E8E\u8BE5\u7ED3\u679C\u7ED9\u51FA\u5B9E\u8D28\u56DE\u5E94\u5C31\u51C6\u5907\u6536\u5C3E\u3002\u8BF7\u7ED3\u5408\u5DE5\u5177\u8FD4\u56DE\u7ED3\u679C\u7EE7\u7EED\u63A8\u8FDB\uFF1B\u82E5\u7ED3\u679C\u8868\u660E\u4EFB\u52A1\u5C1A\u672A\u5B8C\u6210\uFF08\u5982\u4ECD\u5728\u7F16\u8BD1/\u8FD0\u884C\u3001\u9700\u7EE7\u7EED\u8F6E\u8BE2\uFF09\uFF0C\u7ACB\u5373\u91C7\u53D6\u4E0B\u4E00\u6B65\u884C\u52A8\uFF0C\u4E0D\u8981\u7A7A\u624B\u6536\u5C3E\u3002\u82E5\u786E\u5DF2\u5168\u90E8\u5B8C\u6210\uFF0C\u8BF7\u660E\u786E\u56DE\u590D\u300C\u5DF2\u5B8C\u6210\u300D\u5E76\u7B80\u8FF0\u6210\u679C\u3002";
|
|
@@ -11956,6 +12295,7 @@ var init_agentNudges = __esm({
|
|
|
11956
12295
|
let lastTodos = [];
|
|
11957
12296
|
let todoNudges = 0;
|
|
11958
12297
|
let todoPending = null;
|
|
12298
|
+
let budgetSoftSent = false;
|
|
11959
12299
|
return {
|
|
11960
12300
|
pickNudge(round) {
|
|
11961
12301
|
if (!planFirstSent && round === 1 && !planMode && looksComplex(firstPrompt)) {
|
|
@@ -11983,6 +12323,14 @@ ${PLAN_FIRST_TEXT}` };
|
|
|
11983
12323
|
todoPending = null;
|
|
11984
12324
|
return m;
|
|
11985
12325
|
}
|
|
12326
|
+
if (!budgetSoftSent) {
|
|
12327
|
+
const st = opts.getBudgetStatus?.() ?? null;
|
|
12328
|
+
if (st && st.budget > 0 && st.spent >= st.budget) {
|
|
12329
|
+
budgetSoftSent = true;
|
|
12330
|
+
return { role: "system", content: `${BUDGET_FENCE}
|
|
12331
|
+
${BUDGET_SOFT_TEXT(st.spent, st.budget)}` };
|
|
12332
|
+
}
|
|
12333
|
+
}
|
|
11986
12334
|
if (repeatRetrievalPending) {
|
|
11987
12335
|
const m = repeatRetrievalPending;
|
|
11988
12336
|
repeatRetrievalPending = null;
|
|
@@ -12082,17 +12430,17 @@ ${REPEAT_GREP_TEXT(q, n)}` };
|
|
|
12082
12430
|
});
|
|
12083
12431
|
|
|
12084
12432
|
// ../core/src/observability/usageLog.ts
|
|
12085
|
-
import
|
|
12086
|
-
import
|
|
12433
|
+
import fs34 from "fs/promises";
|
|
12434
|
+
import path37 from "path";
|
|
12087
12435
|
var USAGE_DISABLED, usageDir, ensuredDir, getUsageLogPath, recordUsageRun, USAGE_FILE_RE, SYNTHETIC_SESSION_RE, readUsageRecords, summarizeUsage, topTools;
|
|
12088
12436
|
var init_usageLog = __esm({
|
|
12089
12437
|
"../core/src/observability/usageLog.ts"() {
|
|
12090
12438
|
"use strict";
|
|
12091
12439
|
init_config();
|
|
12092
12440
|
USAGE_DISABLED = process.env.DEEPSEEKER_CODE_USAGE_LOG === "0";
|
|
12093
|
-
usageDir = () =>
|
|
12441
|
+
usageDir = () => path37.join(appConfig.dataDir, "usage");
|
|
12094
12442
|
ensuredDir = null;
|
|
12095
|
-
getUsageLogPath = (month) =>
|
|
12443
|
+
getUsageLogPath = (month) => path37.join(usageDir(), `usage-${month}.jsonl`);
|
|
12096
12444
|
recordUsageRun = async (rec) => {
|
|
12097
12445
|
if (USAGE_DISABLED) return;
|
|
12098
12446
|
try {
|
|
@@ -12100,20 +12448,20 @@ var init_usageLog = __esm({
|
|
|
12100
12448
|
const month = (full.ts || (/* @__PURE__ */ new Date()).toISOString()).slice(0, 7);
|
|
12101
12449
|
const dir = usageDir();
|
|
12102
12450
|
if (ensuredDir !== dir) {
|
|
12103
|
-
await
|
|
12451
|
+
await fs34.mkdir(dir, { recursive: true });
|
|
12104
12452
|
ensuredDir = dir;
|
|
12105
12453
|
}
|
|
12106
|
-
await
|
|
12454
|
+
await fs34.appendFile(getUsageLogPath(month), JSON.stringify(full) + "\n", "utf-8");
|
|
12107
12455
|
} catch (e) {
|
|
12108
12456
|
console.warn("\u26A0\uFE0F [usageLog] \u4F7F\u7528\u65E5\u5FD7\u843D\u76D8\u5931\u8D25\uFF08\u4E0D\u5F71\u54CD\u4E3B\u4E1A\u52A1\uFF09:", e instanceof Error ? e.message : e);
|
|
12109
12457
|
}
|
|
12110
12458
|
};
|
|
12111
12459
|
USAGE_FILE_RE = /^usage-\d{4}-\d{2}\.jsonl$/;
|
|
12112
|
-
SYNTHETIC_SESSION_RE = /^(selftest-|eval-)/;
|
|
12460
|
+
SYNTHETIC_SESSION_RE = /^(selftest-|eval-|e2e-)/;
|
|
12113
12461
|
readUsageRecords = async (days) => {
|
|
12114
12462
|
let files;
|
|
12115
12463
|
try {
|
|
12116
|
-
files = (await
|
|
12464
|
+
files = (await fs34.readdir(usageDir())).filter((f) => USAGE_FILE_RE.test(f)).sort();
|
|
12117
12465
|
} catch {
|
|
12118
12466
|
return [];
|
|
12119
12467
|
}
|
|
@@ -12127,7 +12475,7 @@ var init_usageLog = __esm({
|
|
|
12127
12475
|
for (const f of files) {
|
|
12128
12476
|
let text;
|
|
12129
12477
|
try {
|
|
12130
|
-
text = await
|
|
12478
|
+
text = await fs34.readFile(path37.join(usageDir(), f), "utf-8");
|
|
12131
12479
|
} catch {
|
|
12132
12480
|
continue;
|
|
12133
12481
|
}
|
|
@@ -12188,6 +12536,48 @@ var init_usageLog = __esm({
|
|
|
12188
12536
|
}
|
|
12189
12537
|
});
|
|
12190
12538
|
|
|
12539
|
+
// ../core/src/config/prices.ts
|
|
12540
|
+
var MODEL_PRICES, envPrice, ENV_OVERRIDE, priceFor, calcCostYuan;
|
|
12541
|
+
var init_prices = __esm({
|
|
12542
|
+
"../core/src/config/prices.ts"() {
|
|
12543
|
+
"use strict";
|
|
12544
|
+
MODEL_PRICES = {
|
|
12545
|
+
"deepseek-flash": { input: 1, output: 2, cacheHit: 0.02 },
|
|
12546
|
+
"deepseek-v4-pro": { input: 3, output: 6, cacheHit: 0.025 }
|
|
12547
|
+
};
|
|
12548
|
+
envPrice = (name) => {
|
|
12549
|
+
const raw = process.env[name];
|
|
12550
|
+
if (!raw) return void 0;
|
|
12551
|
+
const n = Number(raw);
|
|
12552
|
+
return Number.isFinite(n) && n >= 0 ? n : void 0;
|
|
12553
|
+
};
|
|
12554
|
+
ENV_OVERRIDE = (() => {
|
|
12555
|
+
const input = envPrice("DEEP_SEEK_PRICE_INPUT");
|
|
12556
|
+
const output = envPrice("DEEP_SEEK_PRICE_OUTPUT");
|
|
12557
|
+
const cacheHit = envPrice("DEEP_SEEK_PRICE_CACHEHIT");
|
|
12558
|
+
if (input === void 0 && output === void 0 && cacheHit === void 0) return null;
|
|
12559
|
+
return { input, output, cacheHit };
|
|
12560
|
+
})();
|
|
12561
|
+
priceFor = (model) => {
|
|
12562
|
+
const base = MODEL_PRICES[model];
|
|
12563
|
+
if (!ENV_OVERRIDE) return base ?? null;
|
|
12564
|
+
const input = ENV_OVERRIDE.input ?? base?.input;
|
|
12565
|
+
const output = ENV_OVERRIDE.output ?? base?.output;
|
|
12566
|
+
const cacheHit = ENV_OVERRIDE.cacheHit ?? base?.cacheHit;
|
|
12567
|
+
if (input === void 0 || output === void 0 || cacheHit === void 0) return null;
|
|
12568
|
+
return { input, output, cacheHit };
|
|
12569
|
+
};
|
|
12570
|
+
calcCostYuan = (model, u) => {
|
|
12571
|
+
const p = priceFor(model);
|
|
12572
|
+
if (!p) return null;
|
|
12573
|
+
const cached2 = Math.max(0, u.cachedTokens ?? 0);
|
|
12574
|
+
const miss = Math.max(0, (u.promptTokens ?? 0) - cached2);
|
|
12575
|
+
const completion = Math.max(0, u.completionTokens ?? 0);
|
|
12576
|
+
return (miss * p.input + cached2 * p.cacheHit + completion * p.output) / 1e6;
|
|
12577
|
+
};
|
|
12578
|
+
}
|
|
12579
|
+
});
|
|
12580
|
+
|
|
12191
12581
|
// ../core/src/agent/runAgent.ts
|
|
12192
12582
|
async function* runAgent(message, options) {
|
|
12193
12583
|
const sessionId = options.sessionId;
|
|
@@ -12211,21 +12601,36 @@ async function* runAgent(message, options) {
|
|
|
12211
12601
|
let round = 0;
|
|
12212
12602
|
let lastContent = "";
|
|
12213
12603
|
let stopReason = "normal";
|
|
12604
|
+
let budgetTruncated = false;
|
|
12214
12605
|
const MAX_AGENT_ROUNDS = 500;
|
|
12215
12606
|
const firstPrompt = (() => {
|
|
12216
12607
|
if (depth !== 0) return "";
|
|
12217
12608
|
const m = message.find((x) => x?.role === "user");
|
|
12218
12609
|
return msgText(m?.content);
|
|
12219
12610
|
})();
|
|
12611
|
+
let budgetSpentYuan = 0;
|
|
12612
|
+
let runCompactCount = 0;
|
|
12220
12613
|
const nudges = createNudgeScheduler({
|
|
12221
12614
|
firstPrompt,
|
|
12222
12615
|
planMode: !!options.planMode,
|
|
12223
12616
|
noEarlyFinal: !!options.noEarlyFinal,
|
|
12224
|
-
getContextUsage: () => ({ usedTokens: Math.round(estimateTokens(message) * calibRatio + toolsTokens), windowTokens: modelWindow })
|
|
12617
|
+
getContextUsage: () => ({ usedTokens: Math.round(estimateTokens(message) * calibRatio + toolsTokens), windowTokens: modelWindow }),
|
|
12618
|
+
getBudgetStatus: depth === 0 && options.budgetYuan != null && options.budgetYuan > 0 ? () => ({ spent: budgetSpentYuan, budget: options.budgetYuan }) : void 0
|
|
12225
12619
|
});
|
|
12226
12620
|
const readTracker = /* @__PURE__ */ new Map();
|
|
12227
12621
|
const userDecisionSource = depth > 0 ? "spawn_agent" : "user";
|
|
12228
12622
|
const llmDecisionSource = depth > 0 ? "llm_spawn_agent" : "llm";
|
|
12623
|
+
const emitContextUsage = () => {
|
|
12624
|
+
if (depth !== 0 || !options.onUIEvent) return;
|
|
12625
|
+
const usedTokens = Math.round(estimateTokens(message) * calibRatio + toolsTokens);
|
|
12626
|
+
options.onUIEvent({
|
|
12627
|
+
type: "context.usage",
|
|
12628
|
+
usedTokens,
|
|
12629
|
+
windowTokens: modelWindow,
|
|
12630
|
+
fillRate: modelWindow > 0 ? usedTokens / modelWindow : 0,
|
|
12631
|
+
compactCount: runCompactCount
|
|
12632
|
+
});
|
|
12633
|
+
};
|
|
12229
12634
|
const startTime = performance.now();
|
|
12230
12635
|
const persistedCalib = await getRollingState(sessionId);
|
|
12231
12636
|
let calibRatio = persistedCalib.calibRatio ?? 1.4;
|
|
@@ -12233,6 +12638,9 @@ async function* runAgent(message, options) {
|
|
|
12233
12638
|
let lastCachedTokens = persistedCalib.lastCachedTokens;
|
|
12234
12639
|
const breaker = createRepeatBreaker({ sessionId, depth, llmDecisionSource, startTime, events });
|
|
12235
12640
|
let usageSum;
|
|
12641
|
+
const effectiveModel = options.model?.trim() || MODEL_NAME;
|
|
12642
|
+
let costYuanAcc = 0;
|
|
12643
|
+
let costKnown = true;
|
|
12236
12644
|
const addUsage = (u) => {
|
|
12237
12645
|
if (!u) return;
|
|
12238
12646
|
usageSum = {
|
|
@@ -12241,6 +12649,12 @@ async function* runAgent(message, options) {
|
|
|
12241
12649
|
total_tokens: (usageSum?.total_tokens ?? 0) + (u.total_tokens ?? 0),
|
|
12242
12650
|
cached_tokens: (usageSum?.cached_tokens ?? 0) + (u.cached_tokens ?? 0)
|
|
12243
12651
|
};
|
|
12652
|
+
const cost = calcCostYuan(effectiveModel, { promptTokens: u.prompt_tokens, completionTokens: u.completion_tokens, cachedTokens: u.cached_tokens });
|
|
12653
|
+
if (cost == null) costKnown = false;
|
|
12654
|
+
else {
|
|
12655
|
+
costYuanAcc += cost;
|
|
12656
|
+
budgetSpentYuan += cost;
|
|
12657
|
+
}
|
|
12244
12658
|
};
|
|
12245
12659
|
const toolCounts = {};
|
|
12246
12660
|
await appendEvent(sessionId, { dscEvent: "run.start", runId, depth });
|
|
@@ -12271,6 +12685,13 @@ async function* runAgent(message, options) {
|
|
|
12271
12685
|
yield { type: "final", text: lastContent || "\uFF08\u5DF2\u4E2D\u6B62\uFF09" };
|
|
12272
12686
|
return;
|
|
12273
12687
|
}
|
|
12688
|
+
if (depth === 0 && options.budgetYuan != null && options.budgetYuan > 0 && budgetSpentYuan >= options.budgetYuan * 1.2) {
|
|
12689
|
+
stopReason = "limit";
|
|
12690
|
+
budgetTruncated = true;
|
|
12691
|
+
yield { type: "final", text: (lastContent || "") + `
|
|
12692
|
+
\uFF08\u{1F4B0} \u9884\u7B97\u622A\u65AD\uFF1A\u672C run \u5DF2\u82B1\u8D39 \xA5${budgetSpentYuan.toFixed(3)} / \u9884\u7B97 \xA5${options.budgetYuan.toFixed(3)}\u3002/budget \u8C03\u6574\u9884\u7B97\u540E\u56DE\u590D"\u7EE7\u7EED"\u5373\u53EF\u63A5\u7EED\u3002\uFF09` };
|
|
12693
|
+
return;
|
|
12694
|
+
}
|
|
12274
12695
|
const inboxTexts = claimSessionInbox(sessionId);
|
|
12275
12696
|
if (inboxTexts.length > 0) {
|
|
12276
12697
|
for (const t of inboxTexts) {
|
|
@@ -12295,7 +12716,11 @@ async function* runAgent(message, options) {
|
|
|
12295
12716
|
lastRealPromptTokens,
|
|
12296
12717
|
lastCachedTokens,
|
|
12297
12718
|
toolsTokens,
|
|
12298
|
-
|
|
12719
|
+
// ★ H1:旁路数 compact.done 供 context.usage.compactCount(透传不拦截)
|
|
12720
|
+
onUIEvent: (evt) => {
|
|
12721
|
+
if (evt.type === "compact.done") runCompactCount++;
|
|
12722
|
+
options.onUIEvent?.(evt);
|
|
12723
|
+
}
|
|
12299
12724
|
}
|
|
12300
12725
|
);
|
|
12301
12726
|
} catch (e) {
|
|
@@ -12358,6 +12783,7 @@ async function* runAgent(message, options) {
|
|
|
12358
12783
|
}
|
|
12359
12784
|
if (!assistantMessage.tool_calls || assistantMessage.tool_calls.length === 0) {
|
|
12360
12785
|
await appendEvent(sessionId, { dscEvent: "round.end", runId, round, usage: infResult.usage });
|
|
12786
|
+
emitContextUsage();
|
|
12361
12787
|
const finalText = (typeof assistantMessage.content === "string" ? assistantMessage.content : "") || "";
|
|
12362
12788
|
const intercepted = nudges.interceptFinal(finalText, round);
|
|
12363
12789
|
if (intercepted) continue;
|
|
@@ -12405,8 +12831,13 @@ async function* runAgent(message, options) {
|
|
|
12405
12831
|
// processToolCall 据此收缩截断预算:最坏组合「上下文已 75% 满时跑大输出命令 → 16K 字符
|
|
12406
12832
|
// 进上下文 → 下一轮立刻压缩」被釜底抽薪;口径与 ensureFitsWindow/nudge 闭包同公式。
|
|
12407
12833
|
contextTokensEst: Math.round(estimateTokens(message) * calibRatio + toolsTokens),
|
|
12408
|
-
readTracker
|
|
12834
|
+
readTracker,
|
|
12409
12835
|
// ★ P3-8:run 级读取追踪(同一引用透传,跨轮累计)
|
|
12836
|
+
// ★ 子 run 成本回灌(成本信任链第二环 E1):runSubagent 经 toolCtx.reportCost 拿到闭包,
|
|
12837
|
+
// 子 run 结束时把总花费记进本 run 预算累计器——父预算自动继承约束(子花费计入父 spent)。
|
|
12838
|
+
reportCost: (yuan) => {
|
|
12839
|
+
if (Number.isFinite(yuan) && yuan > 0) budgetSpentYuan += yuan;
|
|
12840
|
+
}
|
|
12410
12841
|
};
|
|
12411
12842
|
const scheduleResult = yield* scheduleToolCalls(assistantMessage, message, toolCallCtx);
|
|
12412
12843
|
if (scheduleResult.kind === "aborted") {
|
|
@@ -12418,6 +12849,7 @@ async function* runAgent(message, options) {
|
|
|
12418
12849
|
return;
|
|
12419
12850
|
}
|
|
12420
12851
|
await appendEvent(sessionId, { dscEvent: "round.end", runId, round, usage: infResult.usage });
|
|
12852
|
+
emitContextUsage();
|
|
12421
12853
|
}
|
|
12422
12854
|
} catch (toolErr) {
|
|
12423
12855
|
if (signal?.aborted) {
|
|
@@ -12454,10 +12886,33 @@ async function* runAgent(message, options) {
|
|
|
12454
12886
|
completionTokens: usageSum?.completion_tokens,
|
|
12455
12887
|
totalTokens: usageSum?.total_tokens,
|
|
12456
12888
|
cachedTokens: usageSum?.cached_tokens,
|
|
12889
|
+
costYuan: costKnown ? Math.round(costYuanAcc * 1e6) / 1e6 : void 0,
|
|
12457
12890
|
tools: toolCounts
|
|
12458
12891
|
});
|
|
12459
12892
|
} catch {
|
|
12460
12893
|
}
|
|
12894
|
+
try {
|
|
12895
|
+
if (options.costSink && costKnown && costYuanAcc > 0) options.costSink(Math.round(costYuanAcc * 1e6) / 1e6);
|
|
12896
|
+
} catch {
|
|
12897
|
+
}
|
|
12898
|
+
try {
|
|
12899
|
+
if (depth === 0 && options.onUIEvent && usageSum) {
|
|
12900
|
+
const prompt = usageSum.prompt_tokens ?? 0;
|
|
12901
|
+
options.onUIEvent({
|
|
12902
|
+
type: "run.receipt",
|
|
12903
|
+
rounds: round,
|
|
12904
|
+
promptTokens: prompt,
|
|
12905
|
+
completionTokens: usageSum.completion_tokens ?? 0,
|
|
12906
|
+
cachedTokens: usageSum.cached_tokens ?? 0,
|
|
12907
|
+
cacheHitRate: prompt > 0 ? (usageSum.cached_tokens ?? 0) / prompt : 0,
|
|
12908
|
+
costYuan: costKnown ? Math.round(costYuanAcc * 1e6) / 1e6 : null,
|
|
12909
|
+
durationMs: Math.round(performance.now() - startTime),
|
|
12910
|
+
budgetTruncated: budgetTruncated || void 0
|
|
12911
|
+
// 预算截断标注(E2;undefined 自动省略)
|
|
12912
|
+
});
|
|
12913
|
+
}
|
|
12914
|
+
} catch {
|
|
12915
|
+
}
|
|
12461
12916
|
try {
|
|
12462
12917
|
const reason = signal?.aborted ? "aborted" : stopReason;
|
|
12463
12918
|
await dispatch("Stop", { sessionId, cwd, lastText: lastContent || "", reason });
|
|
@@ -12488,12 +12943,13 @@ var init_runAgent = __esm({
|
|
|
12488
12943
|
init_streamInference();
|
|
12489
12944
|
init_agentNudges();
|
|
12490
12945
|
init_usageLog();
|
|
12946
|
+
init_prices();
|
|
12491
12947
|
init_createModel();
|
|
12492
12948
|
}
|
|
12493
12949
|
});
|
|
12494
12950
|
|
|
12495
12951
|
// ../core/src/session/lineage.ts
|
|
12496
|
-
import
|
|
12952
|
+
import fs35 from "node:fs";
|
|
12497
12953
|
var parentOfSubsession, stringAncestorsOf, readForkedFromSync, lineageClosureOf, ownerCanApprove;
|
|
12498
12954
|
var init_lineage = __esm({
|
|
12499
12955
|
"../core/src/session/lineage.ts"() {
|
|
@@ -12516,7 +12972,7 @@ var init_lineage = __esm({
|
|
|
12516
12972
|
};
|
|
12517
12973
|
readForkedFromSync = (sessionId) => {
|
|
12518
12974
|
try {
|
|
12519
|
-
const raw =
|
|
12975
|
+
const raw = fs35.readFileSync(getStatePath(sessionId), "utf-8");
|
|
12520
12976
|
const v = JSON.parse(raw)?.forkedFrom;
|
|
12521
12977
|
return typeof v === "string" && v.length > 0 ? v : void 0;
|
|
12522
12978
|
} catch {
|
|
@@ -12637,30 +13093,30 @@ var init_subagent = __esm({
|
|
|
12637
13093
|
sessionId: ""
|
|
12638
13094
|
};
|
|
12639
13095
|
}
|
|
12640
|
-
const subSystem =
|
|
13096
|
+
const subSystem = manifest ? [
|
|
12641
13097
|
`# \u5B50 Agent \u8EAB\u4EFD\uFF1A${manifest.name}`,
|
|
12642
13098
|
manifest.body,
|
|
12643
13099
|
`
|
|
12644
13100
|
# \u4EFB\u52A1\u4E0A\u4E0B\u6587`,
|
|
12645
13101
|
`\u5F53\u524D\u6240\u5904\u7684\u4EFB\u52A1\u6267\u884C\u5D4C\u5957\u6DF1\u5EA6: Depth ${ctx.depth + 1} / ${MAX_AGENT_DEPTH}`,
|
|
12646
|
-
`\u4F60\u7684\u7236\u7EA7\u4EFB\u52A1\u5927\u7EB2\u53C2\u8003: ${task.slice(0, 150)}...`,
|
|
12647
|
-
role ? `
|
|
12648
|
-
# \u672C\u6B21\u89D2\u8272\u8865\u5145: ${role}` : "",
|
|
12649
13102
|
`
|
|
12650
13103
|
# \u3010\u7EE7\u627F\u7684\u5168\u5C40\u4EE3\u7801\u89C4\u8303\u3011`,
|
|
12651
13104
|
parentSystemPrompt
|
|
12652
13105
|
].filter(Boolean).join("\n") : [
|
|
12653
13106
|
`# \u4EFB\u52A1\u4E0A\u4E0B\u6587`,
|
|
12654
|
-
role ? `\u3010\u4F60\u7684\u4E13\u5C5E\u89D2\u8272\u3011: ${role}` : "\u3010\u4F60\u7684\u4E13\u5C5E\u89D2\u8272\u3011: \u4E13\u6CE8\u6267\u884C\u7279\u5B9A\u5C40\u90E8\u5B50\u4EFB\u52A1\u7684\u72EC\u7ACB\u667A\u80FD\u4F53\u52A9\u624B",
|
|
12655
13107
|
`\u5F53\u524D\u6240\u5904\u7684\u4EFB\u52A1\u6267\u884C\u5D4C\u5957\u6DF1\u5EA6: Depth ${ctx.depth + 1} / ${MAX_AGENT_DEPTH}`,
|
|
12656
|
-
`\u4F60\u7684\u7236\u7EA7\u4EFB\u52A1\u5927\u7EB2\u53C2\u8003: ${task.slice(0, 150)}...`,
|
|
12657
13108
|
`
|
|
12658
13109
|
# \u3010\u6838\u5FC3\u91CD\u6784\u94C1\u5F8B\u3011`,
|
|
12659
13110
|
`\u4F60\u76F4\u63A5\u5171\u4EAB\u5E76\u64CD\u4F5C\u672C\u5730\u6587\u4EF6\u7CFB\u7EDF\u3002\u5F53\u4F60\u5BF9\u6587\u4EF6\u5168\u91CF\u5199\u5165\u6216\u5C40\u90E8\u4FEE\u6539\u65F6\uFF0C\u5FC5\u987B\u786E\u4FDD\u64CD\u4F5C\u7684\u7EDD\u5BF9\u7CBE\u51C6\u3002\u5B8C\u6210\u6307\u5B9A\u5B50\u4EFB\u52A1\u540E\uFF0C\u8BF7\u4F7F\u7528\u6700\u7EC8\u7684\u6587\u672C\u603B\u7ED3\u5411\u7236\u7EA7 Agent \u4EA4\u4ED8\u7ED3\u679C\u3002`,
|
|
12660
13111
|
`
|
|
12661
13112
|
# \u3010\u7EE7\u627F\u7684\u5168\u5C40\u4EE3\u7801\u89C4\u8303\u3011`,
|
|
12662
13113
|
parentSystemPrompt
|
|
12663
|
-
].join("\n")
|
|
13114
|
+
].join("\n");
|
|
13115
|
+
const subTaskPrompt = [
|
|
13116
|
+
role ? manifest ? `# \u672C\u6B21\u89D2\u8272\u8865\u5145: ${role}` : `\u3010\u4F60\u7684\u4E13\u5C5E\u89D2\u8272\u3011: ${role}` : manifest ? "" : `\u3010\u4F60\u7684\u4E13\u5C5E\u89D2\u8272\u3011: \u4E13\u6CE8\u6267\u884C\u7279\u5B9A\u5C40\u90E8\u5B50\u4EFB\u52A1\u7684\u72EC\u7ACB\u667A\u80FD\u4F53\u52A9\u624B`,
|
|
13117
|
+
task,
|
|
13118
|
+
...resuming ? [RESUME_NOTE] : []
|
|
13119
|
+
].filter(Boolean).join("\n\n");
|
|
12664
13120
|
const allTools = getGlobalTools();
|
|
12665
13121
|
const wantsMcp = manifest?.tools.some((t) => t === "mcp_call" || t === "mcp_list_tools" || t.startsWith("mcp__")) ?? false;
|
|
12666
13122
|
const toolSchemas = manifest && manifest.tools.length > 0 ? allTools.filter((t) => manifest.tools.includes(t.function.name) || wantsMcp && (t.function.name === "mcp_call" || t.function.name === "mcp_list_tools")) : allTools.filter((t) => !SUBAGENT_DENYLIST.has(t.function.name));
|
|
@@ -12668,8 +13124,8 @@ var init_subagent = __esm({
|
|
|
12668
13124
|
activeSubagents.add(subSessionId);
|
|
12669
13125
|
ctx.onUIEvent?.({ type: "subagent.count", running: activeSubagents.size, phase: "start", name: manifest?.name, depth: ctx.depth + 1 });
|
|
12670
13126
|
try {
|
|
12671
|
-
const subMessages = await buildContextMessages(subSessionId, { role: "user", content:
|
|
12672
|
-
await appendMessage({ sessionId: subSessionId, role: "user", content:
|
|
13127
|
+
const subMessages = await buildContextMessages(subSessionId, { role: "user", content: subTaskPrompt }, subSystem, manifest?.model);
|
|
13128
|
+
await appendMessage({ sessionId: subSessionId, role: "user", content: subTaskPrompt });
|
|
12673
13129
|
let subResult = "";
|
|
12674
13130
|
let hasFinalResult = false;
|
|
12675
13131
|
const subOptions = {
|
|
@@ -12694,8 +13150,10 @@ var init_subagent = __esm({
|
|
|
12694
13150
|
// ★ P1-6 透传:子 agent 工作区文件编辑也走 auto 分类器
|
|
12695
13151
|
noEarlyFinal: true,
|
|
12696
13152
|
// ★ 子 agent final 是交付父级的汇报,EARLY_FINAL 误推一轮纯浪费;父可经续跑纠错
|
|
12697
|
-
model: manifest?.model
|
|
13153
|
+
model: manifest?.model,
|
|
12698
13154
|
// ★ per-agent 模型覆盖;undefined 时 model.ts 回退全局 MODEL_NAME
|
|
13155
|
+
costSink: ctx.reportCost
|
|
13156
|
+
// ★ 子 run 成本回灌父累计器(成本信任链第二环 E1):父预算自动继承约束
|
|
12699
13157
|
};
|
|
12700
13158
|
const startCtx = { sessionId: subSessionId, parentSessionId: ctx.sessionId, task, depth: ctx.depth + 1, name: manifest?.name, cwd: ctx.cwd };
|
|
12701
13159
|
await dispatch("SubagentStart", startCtx);
|
|
@@ -12743,15 +13201,15 @@ var init_subagent = __esm({
|
|
|
12743
13201
|
});
|
|
12744
13202
|
|
|
12745
13203
|
// ../core/src/hooks/trust.ts
|
|
12746
|
-
import
|
|
12747
|
-
import
|
|
13204
|
+
import path38 from "path";
|
|
13205
|
+
import fs36 from "fs/promises";
|
|
12748
13206
|
var TRUSTED_HOOKS_FILE, approved, loaded, ensureLoaded, isHookCommandApproved, approveHookCommand;
|
|
12749
13207
|
var init_trust2 = __esm({
|
|
12750
13208
|
"../core/src/hooks/trust.ts"() {
|
|
12751
13209
|
"use strict";
|
|
12752
13210
|
init_config();
|
|
12753
13211
|
init_common();
|
|
12754
|
-
TRUSTED_HOOKS_FILE =
|
|
13212
|
+
TRUSTED_HOOKS_FILE = path38.join(appConfig.dataDir, "trusted_hooks.json");
|
|
12755
13213
|
approved = /* @__PURE__ */ new Set();
|
|
12756
13214
|
loaded = false;
|
|
12757
13215
|
ensureLoaded = async () => {
|
|
@@ -12771,7 +13229,7 @@ var init_trust2 = __esm({
|
|
|
12771
13229
|
if (approved.has(ident)) return;
|
|
12772
13230
|
approved.add(ident);
|
|
12773
13231
|
try {
|
|
12774
|
-
await
|
|
13232
|
+
await fs36.mkdir(appConfig.dataDir, { recursive: true });
|
|
12775
13233
|
await atomicWriteJSON(TRUSTED_HOOKS_FILE, [...approved]);
|
|
12776
13234
|
} catch (e) {
|
|
12777
13235
|
console.warn(`\u26A0\uFE0F [hooks] \u5BA1\u6279\u8BB0\u5FC6\u843D\u76D8\u5931\u8D25\uFF08\u672C\u6B21\u5DF2\u653E\u884C\uFF0C\u4E0B\u6B21\u9996\u8DD1\u4F1A\u518D\u95EE\uFF09: ${e?.message ?? e}`);
|
|
@@ -12781,8 +13239,8 @@ var init_trust2 = __esm({
|
|
|
12781
13239
|
});
|
|
12782
13240
|
|
|
12783
13241
|
// ../core/src/hooks/loader.ts
|
|
12784
|
-
import
|
|
12785
|
-
import
|
|
13242
|
+
import fs37 from "fs/promises";
|
|
13243
|
+
import path39 from "path";
|
|
12786
13244
|
var slimHookContext, readHooksConfig, appendValidated, validateRule, parseStdoutDecision, parseAgentDecision, gateSeq, firstRunGate, compileRule2, loadHooks, initHooks;
|
|
12787
13245
|
var init_loader4 = __esm({
|
|
12788
13246
|
"../core/src/hooks/loader.ts"() {
|
|
@@ -12811,15 +13269,15 @@ var init_loader4 = __esm({
|
|
|
12811
13269
|
readHooksConfig = async (includeProject) => {
|
|
12812
13270
|
const merged = {};
|
|
12813
13271
|
const paths = [
|
|
12814
|
-
|
|
13272
|
+
path39.join(appConfig.dataDir, "settings.json"),
|
|
12815
13273
|
// 全局用户级
|
|
12816
|
-
...includeProject ? [
|
|
13274
|
+
...includeProject ? [path39.join(process.cwd(), ".deepseeker-code", "settings.json")] : []
|
|
12817
13275
|
// 项目级(叠加);未信任时省略
|
|
12818
13276
|
];
|
|
12819
13277
|
for (const configPath of paths) {
|
|
12820
13278
|
let raw;
|
|
12821
13279
|
try {
|
|
12822
|
-
raw = await
|
|
13280
|
+
raw = await fs37.readFile(configPath, "utf-8");
|
|
12823
13281
|
} catch {
|
|
12824
13282
|
continue;
|
|
12825
13283
|
}
|
|
@@ -13192,8 +13650,8 @@ ${m.context}`;
|
|
|
13192
13650
|
});
|
|
13193
13651
|
|
|
13194
13652
|
// ../core/src/skills/loader.ts
|
|
13195
|
-
import
|
|
13196
|
-
import
|
|
13653
|
+
import fs38 from "fs/promises";
|
|
13654
|
+
import path40 from "path";
|
|
13197
13655
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
13198
13656
|
var BUILTIN_DIR, SOURCES2, MAX_SKILL_BODY_BYTES, splitList, parseSkillAt, loadSkills, initSkills;
|
|
13199
13657
|
var init_loader5 = __esm({
|
|
@@ -13204,18 +13662,18 @@ var init_loader5 = __esm({
|
|
|
13204
13662
|
init_registry3();
|
|
13205
13663
|
init_skill();
|
|
13206
13664
|
init_registry2();
|
|
13207
|
-
BUILTIN_DIR =
|
|
13665
|
+
BUILTIN_DIR = path40.join(path40.dirname(fileURLToPath2(import.meta.url)), "builtin");
|
|
13208
13666
|
SOURCES2 = [
|
|
13209
13667
|
{ dir: BUILTIN_DIR, source: "builtin" },
|
|
13210
|
-
{ dir:
|
|
13211
|
-
{ dir:
|
|
13668
|
+
{ dir: path40.join(appConfig.dataDir, "skills"), source: "global" },
|
|
13669
|
+
{ dir: path40.join(process.cwd(), ".deepseeker-code", "skills"), source: "project" }
|
|
13212
13670
|
];
|
|
13213
13671
|
MAX_SKILL_BODY_BYTES = 64 * 1024;
|
|
13214
13672
|
splitList = (raw) => (raw ?? "").split(",").map((s) => s.trim()).filter(Boolean);
|
|
13215
13673
|
parseSkillAt = async (skillFile, dir, source) => {
|
|
13216
13674
|
let raw;
|
|
13217
13675
|
try {
|
|
13218
|
-
raw = await
|
|
13676
|
+
raw = await fs38.readFile(skillFile, "utf-8");
|
|
13219
13677
|
} catch {
|
|
13220
13678
|
return null;
|
|
13221
13679
|
}
|
|
@@ -13254,7 +13712,7 @@ var init_loader5 = __esm({
|
|
|
13254
13712
|
loadSkills = async (includeProject) => {
|
|
13255
13713
|
const picked = await scanSources(
|
|
13256
13714
|
filterSources(SOURCES2, includeProject),
|
|
13257
|
-
(e, dir) => e.isDirectory() ?
|
|
13715
|
+
(e, dir) => e.isDirectory() ? path40.join(dir, e.name, "SKILL.md") : void 0,
|
|
13258
13716
|
parseSkillAt
|
|
13259
13717
|
);
|
|
13260
13718
|
for (const { item } of picked) registerSkill(item);
|
|
@@ -13285,8 +13743,8 @@ var init_loader5 = __esm({
|
|
|
13285
13743
|
});
|
|
13286
13744
|
|
|
13287
13745
|
// ../core/src/agents/loader.ts
|
|
13288
|
-
import
|
|
13289
|
-
import
|
|
13746
|
+
import fs39 from "fs/promises";
|
|
13747
|
+
import path41 from "path";
|
|
13290
13748
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
13291
13749
|
var BUILTIN_DIR2, SOURCES3, parseAgentAt, initAgents;
|
|
13292
13750
|
var init_loader6 = __esm({
|
|
@@ -13296,16 +13754,16 @@ var init_loader6 = __esm({
|
|
|
13296
13754
|
init_frontmatter();
|
|
13297
13755
|
init_registry4();
|
|
13298
13756
|
init_registry2();
|
|
13299
|
-
BUILTIN_DIR2 =
|
|
13757
|
+
BUILTIN_DIR2 = path41.join(path41.dirname(fileURLToPath3(import.meta.url)), "builtin");
|
|
13300
13758
|
SOURCES3 = [
|
|
13301
13759
|
{ dir: BUILTIN_DIR2, source: "builtin" },
|
|
13302
|
-
{ dir:
|
|
13303
|
-
{ dir:
|
|
13760
|
+
{ dir: path41.join(appConfig.dataDir, "agents"), source: "global" },
|
|
13761
|
+
{ dir: path41.join(process.cwd(), ".deepseeker-code", "agents"), source: "project" }
|
|
13304
13762
|
];
|
|
13305
13763
|
parseAgentAt = async (file, dir, source) => {
|
|
13306
13764
|
let raw;
|
|
13307
13765
|
try {
|
|
13308
|
-
raw = await
|
|
13766
|
+
raw = await fs39.readFile(file, "utf-8");
|
|
13309
13767
|
} catch {
|
|
13310
13768
|
return null;
|
|
13311
13769
|
}
|
|
@@ -13340,7 +13798,7 @@ var init_loader6 = __esm({
|
|
|
13340
13798
|
const known = new Set(into.map((t) => t.function.name));
|
|
13341
13799
|
const picked = await scanSources(
|
|
13342
13800
|
filterSources(SOURCES3, includeProject),
|
|
13343
|
-
(e, dir) => e.isFile() && e.name.endsWith(".agent.md") ?
|
|
13801
|
+
(e, dir) => e.isFile() && e.name.endsWith(".agent.md") ? path41.join(dir, e.name) : void 0,
|
|
13344
13802
|
parseAgentAt
|
|
13345
13803
|
);
|
|
13346
13804
|
for (const { item: m, file, source } of picked) {
|
|
@@ -13377,8 +13835,8 @@ var init_registry7 = __esm({
|
|
|
13377
13835
|
});
|
|
13378
13836
|
|
|
13379
13837
|
// ../core/src/commands/loader.ts
|
|
13380
|
-
import
|
|
13381
|
-
import
|
|
13838
|
+
import fs40 from "fs/promises";
|
|
13839
|
+
import path42 from "path";
|
|
13382
13840
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
13383
13841
|
var BUILTIN_DIR3, SOURCES4, MAX_COMMAND_BODY_BYTES, parseCommandAt, loadCommands, initCommands;
|
|
13384
13842
|
var init_loader7 = __esm({
|
|
@@ -13388,17 +13846,17 @@ var init_loader7 = __esm({
|
|
|
13388
13846
|
init_frontmatter();
|
|
13389
13847
|
init_registry7();
|
|
13390
13848
|
init_registry2();
|
|
13391
|
-
BUILTIN_DIR3 =
|
|
13849
|
+
BUILTIN_DIR3 = path42.join(path42.dirname(fileURLToPath4(import.meta.url)), "builtin");
|
|
13392
13850
|
SOURCES4 = [
|
|
13393
13851
|
{ dir: BUILTIN_DIR3, source: "builtin" },
|
|
13394
|
-
{ dir:
|
|
13395
|
-
{ dir:
|
|
13852
|
+
{ dir: path42.join(appConfig.dataDir, "commands"), source: "global" },
|
|
13853
|
+
{ dir: path42.join(process.cwd(), ".deepseeker-code", "commands"), source: "project" }
|
|
13396
13854
|
];
|
|
13397
13855
|
MAX_COMMAND_BODY_BYTES = 64 * 1024;
|
|
13398
13856
|
parseCommandAt = async (file, _dir, source) => {
|
|
13399
13857
|
let raw;
|
|
13400
13858
|
try {
|
|
13401
|
-
raw = await
|
|
13859
|
+
raw = await fs40.readFile(file, "utf-8");
|
|
13402
13860
|
} catch {
|
|
13403
13861
|
return null;
|
|
13404
13862
|
}
|
|
@@ -13409,7 +13867,7 @@ var init_loader7 = __esm({
|
|
|
13409
13867
|
}
|
|
13410
13868
|
const name = parsed.frontmatter.name;
|
|
13411
13869
|
const description = parsed.frontmatter.description;
|
|
13412
|
-
const fallbackName =
|
|
13870
|
+
const fallbackName = path42.basename(file, ".md");
|
|
13413
13871
|
const finalName = name || fallbackName;
|
|
13414
13872
|
if (!description) {
|
|
13415
13873
|
console.warn(`\u26A0\uFE0F [commands] \u7F3A\u5C11 description\uFF08${file}\uFF09\uFF0C\u5DF2\u8DF3\u8FC7`);
|
|
@@ -13435,7 +13893,7 @@ var init_loader7 = __esm({
|
|
|
13435
13893
|
loadCommands = async (includeProject) => {
|
|
13436
13894
|
const picked = await scanSources(
|
|
13437
13895
|
filterSources(SOURCES4, includeProject),
|
|
13438
|
-
(e, dir) => e.isFile() && e.name.endsWith(".md") ?
|
|
13896
|
+
(e, dir) => e.isFile() && e.name.endsWith(".md") ? path42.join(dir, e.name) : void 0,
|
|
13439
13897
|
parseCommandAt
|
|
13440
13898
|
);
|
|
13441
13899
|
for (const { item } of picked) registerCommand(item);
|
|
@@ -13453,8 +13911,8 @@ var init_loader7 = __esm({
|
|
|
13453
13911
|
});
|
|
13454
13912
|
|
|
13455
13913
|
// ../core/src/outputStyles/loader.ts
|
|
13456
|
-
import
|
|
13457
|
-
import
|
|
13914
|
+
import fs41 from "fs/promises";
|
|
13915
|
+
import path43 from "path";
|
|
13458
13916
|
import { fileURLToPath as fileURLToPath5 } from "url";
|
|
13459
13917
|
var BUILTIN_DIR4, MAX_STYLE_BODY_BYTES, SOURCES5, parseStyleAt, loadOutputStyles, initOutputStyles;
|
|
13460
13918
|
var init_loader8 = __esm({
|
|
@@ -13464,17 +13922,17 @@ var init_loader8 = __esm({
|
|
|
13464
13922
|
init_frontmatter();
|
|
13465
13923
|
init_registry5();
|
|
13466
13924
|
init_registry2();
|
|
13467
|
-
BUILTIN_DIR4 =
|
|
13925
|
+
BUILTIN_DIR4 = path43.join(path43.dirname(fileURLToPath5(import.meta.url)), "builtin");
|
|
13468
13926
|
MAX_STYLE_BODY_BYTES = 64 * 1024;
|
|
13469
13927
|
SOURCES5 = [
|
|
13470
13928
|
{ dir: BUILTIN_DIR4, source: "builtin" },
|
|
13471
|
-
{ dir:
|
|
13472
|
-
{ dir:
|
|
13929
|
+
{ dir: path43.join(appConfig.dataDir, "output-styles"), source: "global" },
|
|
13930
|
+
{ dir: path43.join(process.cwd(), ".deepseeker-code", "output-styles"), source: "project" }
|
|
13473
13931
|
];
|
|
13474
13932
|
parseStyleAt = async (file, _dir, source) => {
|
|
13475
13933
|
let raw;
|
|
13476
13934
|
try {
|
|
13477
|
-
raw = await
|
|
13935
|
+
raw = await fs41.readFile(file, "utf-8");
|
|
13478
13936
|
} catch {
|
|
13479
13937
|
return null;
|
|
13480
13938
|
}
|
|
@@ -13506,7 +13964,7 @@ var init_loader8 = __esm({
|
|
|
13506
13964
|
loadOutputStyles = async (includeProject) => {
|
|
13507
13965
|
const picked = await scanSources(
|
|
13508
13966
|
filterSources(SOURCES5, includeProject),
|
|
13509
|
-
(e, dir) => e.isFile() && e.name.endsWith(".md") ?
|
|
13967
|
+
(e, dir) => e.isFile() && e.name.endsWith(".md") ? path43.join(dir, e.name) : void 0,
|
|
13510
13968
|
parseStyleAt
|
|
13511
13969
|
);
|
|
13512
13970
|
for (const { item } of picked) registerOutputStyle(item);
|
|
@@ -13587,8 +14045,8 @@ var init_bootstrap = __esm({
|
|
|
13587
14045
|
});
|
|
13588
14046
|
|
|
13589
14047
|
// ../core/src/statusLine/config.ts
|
|
13590
|
-
import
|
|
13591
|
-
import
|
|
14048
|
+
import fs42 from "fs/promises";
|
|
14049
|
+
import path44 from "path";
|
|
13592
14050
|
var parseBlock, readStatusLineConfig;
|
|
13593
14051
|
var init_config2 = __esm({
|
|
13594
14052
|
"../core/src/statusLine/config.ts"() {
|
|
@@ -13604,16 +14062,16 @@ var init_config2 = __esm({
|
|
|
13604
14062
|
};
|
|
13605
14063
|
readStatusLineConfig = async (includeProject) => {
|
|
13606
14064
|
const paths = [
|
|
13607
|
-
|
|
14065
|
+
path44.join(appConfig.dataDir, "settings.json"),
|
|
13608
14066
|
// 全局用户级
|
|
13609
|
-
...includeProject ? [
|
|
14067
|
+
...includeProject ? [path44.join(process.cwd(), ".deepseeker-code", "settings.json")] : []
|
|
13610
14068
|
// 项目级(覆盖);未信任时省略
|
|
13611
14069
|
];
|
|
13612
14070
|
let result = null;
|
|
13613
14071
|
for (const configPath of paths) {
|
|
13614
14072
|
let raw;
|
|
13615
14073
|
try {
|
|
13616
|
-
raw = await
|
|
14074
|
+
raw = await fs42.readFile(configPath, "utf-8");
|
|
13617
14075
|
} catch {
|
|
13618
14076
|
continue;
|
|
13619
14077
|
}
|
|
@@ -13633,8 +14091,8 @@ var init_config2 = __esm({
|
|
|
13633
14091
|
|
|
13634
14092
|
// ../core/src/statusLine/runner.ts
|
|
13635
14093
|
import { spawn as spawn5 } from "child_process";
|
|
13636
|
-
import
|
|
13637
|
-
import
|
|
14094
|
+
import fs43 from "fs";
|
|
14095
|
+
import path45 from "path";
|
|
13638
14096
|
import { fileURLToPath as fileURLToPath6 } from "url";
|
|
13639
14097
|
var STATUSLINE_TIMEOUT_MS, cachedVersion, runStatusLine;
|
|
13640
14098
|
var init_runner = __esm({
|
|
@@ -13643,16 +14101,16 @@ var init_runner = __esm({
|
|
|
13643
14101
|
init_guard();
|
|
13644
14102
|
STATUSLINE_TIMEOUT_MS = 3e3;
|
|
13645
14103
|
try {
|
|
13646
|
-
const here =
|
|
14104
|
+
const here = path45.dirname(fileURLToPath6(import.meta.url));
|
|
13647
14105
|
const candidates = [
|
|
13648
|
-
|
|
14106
|
+
path45.join(here, "../../../package.json"),
|
|
13649
14107
|
// src/core/package.json
|
|
13650
|
-
|
|
14108
|
+
path45.join(here, "../../../../package.json")
|
|
13651
14109
|
// 仓库根 package.json
|
|
13652
14110
|
];
|
|
13653
14111
|
for (const p of candidates) {
|
|
13654
14112
|
try {
|
|
13655
|
-
const pkg = JSON.parse(
|
|
14113
|
+
const pkg = JSON.parse(fs43.readFileSync(p, "utf-8"));
|
|
13656
14114
|
if (typeof pkg.version === "string" && pkg.version) {
|
|
13657
14115
|
cachedVersion = pkg.version;
|
|
13658
14116
|
break;
|
|
@@ -13703,8 +14161,8 @@ var init_runner = __esm({
|
|
|
13703
14161
|
});
|
|
13704
14162
|
|
|
13705
14163
|
// ../core/src/observability/store.ts
|
|
13706
|
-
import
|
|
13707
|
-
import
|
|
14164
|
+
import path46 from "path";
|
|
14165
|
+
import fs44 from "fs/promises";
|
|
13708
14166
|
var getTraceDirPath, getTracePath, tracePathCache, ensuredTraceDirs, ensureTraceDir, getGlobalClockPath, getTraceStorePath;
|
|
13709
14167
|
var init_store3 = __esm({
|
|
13710
14168
|
"../core/src/observability/store.ts"() {
|
|
@@ -13714,21 +14172,21 @@ var init_store3 = __esm({
|
|
|
13714
14172
|
init_common();
|
|
13715
14173
|
getTraceDirPath = (mainTraceId) => {
|
|
13716
14174
|
assertSafeSessionId(mainTraceId, "traceId");
|
|
13717
|
-
return
|
|
14175
|
+
return path46.join(appConfig.dataDir, "trace", appConfig.userWorkspaceDir, getFileName(mainTraceId));
|
|
13718
14176
|
};
|
|
13719
14177
|
getTracePath = () => {
|
|
13720
|
-
return
|
|
14178
|
+
return path46.join(appConfig.dataDir, "trace");
|
|
13721
14179
|
};
|
|
13722
14180
|
tracePathCache = /* @__PURE__ */ new Map();
|
|
13723
14181
|
ensuredTraceDirs = /* @__PURE__ */ new Set();
|
|
13724
14182
|
ensureTraceDir = async (mainTraceId) => {
|
|
13725
14183
|
const dir = getTraceDirPath(mainTraceId);
|
|
13726
14184
|
if (ensuredTraceDirs.has(dir)) return;
|
|
13727
|
-
await
|
|
14185
|
+
await fs44.mkdir(dir, { recursive: true });
|
|
13728
14186
|
ensuredTraceDirs.add(dir);
|
|
13729
14187
|
};
|
|
13730
14188
|
getGlobalClockPath = () => {
|
|
13731
|
-
return
|
|
14189
|
+
return path46.join(getTracePath(), "trace-cleanup-clock.json");
|
|
13732
14190
|
};
|
|
13733
14191
|
getTraceStorePath = async (mainTraceId) => {
|
|
13734
14192
|
assertSafeSessionId(mainTraceId, "traceId");
|
|
@@ -13737,7 +14195,7 @@ var init_store3 = __esm({
|
|
|
13737
14195
|
if (cached2) return cached2;
|
|
13738
14196
|
await ensureTraceDir(rootId);
|
|
13739
14197
|
const dir = getTraceDirPath(rootId);
|
|
13740
|
-
const files = await
|
|
14198
|
+
const files = await fs44.readdir(dir);
|
|
13741
14199
|
const existedFile = files.find((f) => f.endsWith(`__${rootId}.jsonl`));
|
|
13742
14200
|
let fileName = "";
|
|
13743
14201
|
if (existedFile) {
|
|
@@ -13746,7 +14204,7 @@ var init_store3 = __esm({
|
|
|
13746
14204
|
const todayStr = getTodayDateString();
|
|
13747
14205
|
fileName = `trace-${todayStr}__${rootId}.jsonl`;
|
|
13748
14206
|
}
|
|
13749
|
-
const resolved =
|
|
14207
|
+
const resolved = path46.join(dir, fileName);
|
|
13750
14208
|
tracePathCache.set(rootId, resolved);
|
|
13751
14209
|
return resolved;
|
|
13752
14210
|
};
|
|
@@ -13754,8 +14212,8 @@ var init_store3 = __esm({
|
|
|
13754
14212
|
});
|
|
13755
14213
|
|
|
13756
14214
|
// ../core/src/observability/trace.ts
|
|
13757
|
-
import
|
|
13758
|
-
import
|
|
14215
|
+
import fs45 from "fs/promises";
|
|
14216
|
+
import path47 from "path";
|
|
13759
14217
|
async function emitTrace(base) {
|
|
13760
14218
|
const event = {
|
|
13761
14219
|
sessionId: base.sessionId,
|
|
@@ -13777,7 +14235,7 @@ async function emitTrace(base) {
|
|
|
13777
14235
|
async function appendTraceEvent(event) {
|
|
13778
14236
|
const p = await getTraceStorePath(event.sessionId);
|
|
13779
14237
|
const line = JSON.stringify(event) + "\n";
|
|
13780
|
-
await
|
|
14238
|
+
await fs45.appendFile(p, line, "utf-8");
|
|
13781
14239
|
if (workspaceTraceBytes < 0) {
|
|
13782
14240
|
workspaceTraceBytes = await getDirBytes(getTracePath());
|
|
13783
14241
|
}
|
|
@@ -13809,8 +14267,8 @@ async function maybeCleanupAfterAppend(sessionId) {
|
|
|
13809
14267
|
lastSizeCleanupAt2 = now;
|
|
13810
14268
|
diskLastCleanupAt2 = now;
|
|
13811
14269
|
const clockPath = getGlobalClockPath();
|
|
13812
|
-
await
|
|
13813
|
-
await
|
|
14270
|
+
await fs45.mkdir(path47.dirname(clockPath), { recursive: true });
|
|
14271
|
+
await fs45.writeFile(clockPath, JSON.stringify({ lastCleanupAt: now, updatedAt: (/* @__PURE__ */ new Date()).toISOString() }, null, 2), "utf-8");
|
|
13814
14272
|
if (deletedCount > 0) {
|
|
13815
14273
|
console.log(`\u2728 [Trace\u8FD0\u7EF4] \u5171\u9500\u6BC1 ${deletedCount} \u4E2A\u4F1A\u8BDD\u65E5\u5FD7\uFF08\u8F6F\u89C4\u5219\u8FC7\u671F\u6E05\u7406 + \u5BB9\u91CF\u786C\u9A71\u9010\uFF09\uFF0C\u78C1\u76D8\u6C34\u4F4D\u56DE\u843D\u3002`);
|
|
13816
14274
|
}
|
|
@@ -13830,22 +14288,22 @@ async function cleanupOldTraceFiles() {
|
|
|
13830
14288
|
let deleted = 0;
|
|
13831
14289
|
let relativePaths;
|
|
13832
14290
|
try {
|
|
13833
|
-
relativePaths = await
|
|
14291
|
+
relativePaths = await fs45.readdir(dir, { recursive: true });
|
|
13834
14292
|
} catch {
|
|
13835
14293
|
return 0;
|
|
13836
14294
|
}
|
|
13837
14295
|
const re = /^trace-(\d{4}-\d{2}-\d{2})__([\w-]+)\.jsonl$/;
|
|
13838
14296
|
for (const relativePath of relativePaths) {
|
|
13839
|
-
const fileName =
|
|
14297
|
+
const fileName = path47.basename(relativePath);
|
|
13840
14298
|
const m = fileName.match(re);
|
|
13841
14299
|
if (!m) continue;
|
|
13842
14300
|
const fileBornDay = /* @__PURE__ */ new Date(`${m[1]}T00:00:00`);
|
|
13843
14301
|
if (fileBornDay >= cutoff) continue;
|
|
13844
|
-
const fullPath =
|
|
14302
|
+
const fullPath = path47.join(dir, relativePath);
|
|
13845
14303
|
try {
|
|
13846
|
-
const st = await
|
|
14304
|
+
const st = await fs45.stat(fullPath);
|
|
13847
14305
|
if (now - st.mtimeMs < ACTIVE_GRACE_MS2) continue;
|
|
13848
|
-
await
|
|
14306
|
+
await fs45.unlink(fullPath);
|
|
13849
14307
|
deleted += 1;
|
|
13850
14308
|
} catch {
|
|
13851
14309
|
}
|
|
@@ -13856,18 +14314,18 @@ async function evictOldestForSize2(targetBytes) {
|
|
|
13856
14314
|
const dir = getTracePath();
|
|
13857
14315
|
let relativePaths;
|
|
13858
14316
|
try {
|
|
13859
|
-
relativePaths = await
|
|
14317
|
+
relativePaths = await fs45.readdir(dir, { recursive: true });
|
|
13860
14318
|
} catch {
|
|
13861
14319
|
return 0;
|
|
13862
14320
|
}
|
|
13863
14321
|
const re = /^trace-(\d{4}-\d{2}-\d{2})__([\w-]+)\.jsonl$/;
|
|
13864
14322
|
const candidates = [];
|
|
13865
14323
|
for (const relativePath of relativePaths) {
|
|
13866
|
-
const fileName =
|
|
14324
|
+
const fileName = path47.basename(relativePath);
|
|
13867
14325
|
if (!re.test(fileName)) continue;
|
|
13868
14326
|
try {
|
|
13869
|
-
const st = await
|
|
13870
|
-
candidates.push({ mtime: st.mtimeMs, fullPath:
|
|
14327
|
+
const st = await fs45.stat(path47.join(dir, relativePath));
|
|
14328
|
+
candidates.push({ mtime: st.mtimeMs, fullPath: path47.join(dir, relativePath), size: st.size });
|
|
13871
14329
|
} catch {
|
|
13872
14330
|
}
|
|
13873
14331
|
}
|
|
@@ -13877,7 +14335,7 @@ async function evictOldestForSize2(targetBytes) {
|
|
|
13877
14335
|
for (const c of candidates) {
|
|
13878
14336
|
if (totalBytes <= targetBytes) break;
|
|
13879
14337
|
try {
|
|
13880
|
-
await
|
|
14338
|
+
await fs45.unlink(c.fullPath);
|
|
13881
14339
|
totalBytes -= c.size;
|
|
13882
14340
|
deleted += 1;
|
|
13883
14341
|
} catch {
|
|
@@ -13909,7 +14367,7 @@ var init_trace = __esm({
|
|
|
13909
14367
|
if (clockLoaded2) return;
|
|
13910
14368
|
clockLoaded2 = true;
|
|
13911
14369
|
try {
|
|
13912
|
-
const rawClock = await
|
|
14370
|
+
const rawClock = await fs45.readFile(getGlobalClockPath(), "utf-8");
|
|
13913
14371
|
diskLastCleanupAt2 = JSON.parse(rawClock).lastCleanupAt || 0;
|
|
13914
14372
|
} catch {
|
|
13915
14373
|
diskLastCleanupAt2 = 0;
|
|
@@ -14005,59 +14463,9 @@ var init_expand = __esm({
|
|
|
14005
14463
|
}
|
|
14006
14464
|
});
|
|
14007
14465
|
|
|
14008
|
-
// ../core/src/agent/systemPrompt.ts
|
|
14009
|
-
var buildSystemPrompt;
|
|
14010
|
-
var init_systemPrompt = __esm({
|
|
14011
|
-
"../core/src/agent/systemPrompt.ts"() {
|
|
14012
|
-
"use strict";
|
|
14013
|
-
init_planMode();
|
|
14014
|
-
buildSystemPrompt = (p) => `\u4F60\u662F ${p.displayName}\u2014\u2014\u4E00\u4E2A\u57FA\u4E8E ${p.modelLabel} \u5927\u6A21\u578B\u7684\u7EC8\u7AEF AI \u7F16\u7A0B\u52A9\u624B\u3002\u4F60\u8FD0\u884C\u5728\u7528\u6237\u7684\u7EC8\u7AEF\u4E2D\uFF0C\u80FD\u8C03\u7528\u4E00\u7CFB\u5217\u5DE5\u5177\uFF08\u8BFB\u5199\u6587\u4EF6\u3001\u641C\u7D22\u4EE3\u7801\u3001\u6267\u884C\u547D\u4EE4\u3001\u8054\u7F51\u68C0\u7D22\u3001\u4EFB\u52A1\u7BA1\u7406\u7B49\uFF09\u76F4\u63A5\u5728\u7528\u6237\u5DE5\u4F5C\u533A\u5B8C\u6210\u5F00\u53D1\u4EFB\u52A1\u3002
|
|
14015
|
-
|
|
14016
|
-
\u3010\u8EAB\u4EFD\u3011
|
|
14017
|
-
- \u4F60\u7684\u540D\u5B57\u662F ${p.displayName}\uFF0C\u7531 ${p.modelLabel} \u6A21\u578B\u9A71\u52A8\u3002
|
|
14018
|
-
- \u88AB\u95EE"\u4F60\u662F\u8C01"\u65F6\u636E\u5B9E\u56DE\u7B54\uFF1A\u4F60\u662F ${p.displayName}\u3002\u5207\u52FF\u81EA\u79F0 ChatGPT\u3001GPT \u6216\u4EFB\u4F55\u5176\u4ED6\u516C\u53F8\u7684\u5927\u6A21\u578B/AI \u4EA7\u54C1\u3002
|
|
14019
|
-
|
|
14020
|
-
\u3010\u56DE\u7B54\u51C6\u5219 / \u5B8C\u6210\u5224\u5B9A\u3011
|
|
14021
|
-
- \u4EFB\u52A1\u5B8C\u6210\u540E\u76F4\u63A5\u7528\u81EA\u7136\u8BED\u8A00\u7ED9\u51FA\u6700\u7EC8\u7B54\u6848\uFF0C\u4E0D\u8981\u518D\u8C03\u7528\u5DE5\u5177\u3002**\u5B8C\u6210\u5224\u636E = \u7528\u6237\u7684\u6BCF\u4E2A\u5B50\u76EE\u6807\u90FD\u6709\u843D\u5730\u4EA7\u7269**\uFF08\u6240\u9700\u4FE1\u606F\u5DF2\u5230\u624B / \u8BE5\u6539\u7684\u6587\u4EF6\u5DF2\u6539\u5B8C / \u5DF2\u9A8C\u8BC1\u901A\u8FC7\uFF09\uFF0C\u800C\u975E"\u8C03\u7528\u8FC7\u5DE5\u5177"\u3002\u6BCF\u8F6E\u5DE5\u5177\u8FD4\u56DE\u540E\u5BF9\u7167\u539F\u59CB\u8BF7\u6C42\u4E0E todo \u6E05\u5355\uFF08\u82E5\u6709\uFF09\u9010\u9879\u6838\u5BF9\uFF1A\u8FD8\u6709\u672A\u843D\u5730\u9879\u5C31\u7EE7\u7EED\u63A8\u8FDB\uFF0C\u4E0D\u8981\u62FF\u90E8\u5206\u68C0\u7D22/\u8BFB\u53D6\u7ED3\u679C\u603B\u7ED3\u6536\u5C3E\u3002\u590D\u6742\u4EFB\u52A1\u7528 todo_write \u62C6\u89E3\u5E76\u9010\u9879\u52FE\u9009\uFF0C\u6BCF\u8F6E\u5BF9\u7167\u6E05\u5355\u6838\u5BF9\u8FDB\u5EA6\u3002
|
|
14022
|
-
- \u5DE5\u5177**\u6267\u884C\u5931\u8D25\u6216\u88AB\u7528\u6237\u62D2\u7EDD**\u65F6\uFF0C\u8BFB\u8FD4\u56DE\u7ED3\u679C\u5B9A\u4F4D\u539F\u56E0\uFF0C\u4FEE\u6B63\u53C2\u6570\u6216\u6362\u7B49\u6548\u65B9\u6848\u7EE7\u7EED\uFF0C\u4E0D\u8981\u9053\u6B49\u4E00\u4E24\u53E5\u5C31\u505C\u4E0B\uFF1B\u786E\u5B9E\u53D7\u963B\u9700\u8981\u7528\u6237\u51B3\u7B56\u65F6\uFF0C\u7528 ask_question \u8BF4\u660E**\u5177\u4F53**\u963B\u585E\u70B9\u3002**\u4E25\u7981**\u5728\u672A\u771F\u6B63\u6267\u884C\u6216\u672A\u9A8C\u8BC1\u7684\u60C5\u51B5\u4E0B\u58F0\u79F0"\u5DF2\u5B8C\u6210/\u5DF2\u4FEE\u6539/\u5DF2\u4FEE\u590D"\u2014\u2014\u6539\u52A8\u82E5\u53EF\u9A8C\u8BC1\uFF08\u91CD\u8BFB\u786E\u8BA4\u3001\u8DD1\u6D4B\u8BD5\u3001\u7C7B\u578B\u68C0\u67E5\uFF09\uFF0C\u5148\u9A8C\u8BC1\u518D\u6536\u5C3E\u3002
|
|
14023
|
-
|
|
14024
|
-
\u3010\u56DE\u7B54\u5F62\u5F0F\u3011
|
|
14025
|
-
- **\u5148\u7ED3\u8BBA\u540E\u7EC6\u8282**\uFF1A\u5148\u76F4\u63A5\u56DE\u7B54\u6216\u6C47\u62A5\u7ED3\u679C\uFF0C\u518D\u5C55\u5F00\u5FC5\u8981\u7684\u89E3\u91CA\uFF1B\u6536\u5C3E\u603B\u7ED3\u7B80\u77ED\uFF08\u51E0\u884C\u4EE5\u5185\uFF09\uFF0C\u4E0D\u9010\u6587\u4EF6\u6D41\u6C34\u8D26\u3002
|
|
14026
|
-
- **\u4E0D\u56DE\u8D34\u5927\u6BB5\u4EE3\u7801**\uFF1A\u6539\u52A8\u5185\u5BB9\u7528\u6237\u5728\u7F16\u8F91\u5668/diff \u91CC\u770B\u5F97\u5230\uFF0C\u6B63\u6587\u53EA\u9700\u4E00\u53E5\u8BDD\u8BF4\u660E\u6539\u4E86\u4EC0\u4E48\u3001\u4E3A\u4EC0\u4E48\uFF0C\u6216\u5F15\u7528\u5173\u952E\u51E0\u884C\u3002
|
|
14027
|
-
|
|
14028
|
-
\u3010\u5DE5\u5177\u4F7F\u7528\u51C6\u5219\u3011
|
|
14029
|
-
- \u4FEE\u6539\u6587\u4EF6**\u53EA\u80FD**\u7528 edit_file / create_file / write_file\u3002**\u4E25\u7981**\u7528 run_command \u901A\u8FC7 python/node/sed/awk/perl \u7B49\u811A\u672C\u8BFB\u5199\u6216\u4FEE\u6539\u6587\u4EF6\u2014\u2014\u811A\u672C\u8F6C\u4E49\u6781\u6613\u51FA\u9519\u3001\u6BCF\u6761\u547D\u4EE4\u90FD\u8981\u7528\u6237\u5BA1\u6279\u3001\u6548\u7387\u6781\u4F4E\uFF0C\u662F\u88AB\u660E\u786E\u7981\u6B62\u7684\u9000\u8DEF\u3002
|
|
14030
|
-
- edit_file \u5931\u8D25\u65F6**\u4E0D\u8981\u9000\u56DE shell**\uFF1A\u7528 read_file \u91CD\u65B0\u6838\u5BF9\u76EE\u6807\u7247\u6BB5\uFF08\u53BB\u6389\u300C<\u884C\u53F7>: \u300D\u524D\u7F00\u3001\u4FDD\u7559\u539F\u59CB Tab/\u7A7A\u683C\u7F29\u8FDB\u4E0E\u6362\u884C\uFF09\u540E\u518D\u6B21\u8C03\u7528 edit_file\uFF1B\u5B9A\u4F4D\u4E0D\u51C6\u5C31\u591A\u8BFB\u51E0\u884C\u4E0A\u4E0B\u6587\u5305\u88F9\u8FDB\u53BB\u3002\u672C\u5DE5\u5177\u5DF2\u6709\u591A\u7EA7\u7A7A\u767D/\u7F29\u8FDB\u5BB9\u9519\uFF0C\u591A\u6570\u5931\u914D\u53EA\u9700\u7CBE\u786E\u91CD\u8BFB\u5373\u53EF\u89E3\u51B3\u3002
|
|
14031
|
-
- \u4FEE\u6539\u65E2\u6709\u6587\u4EF6**\u4E00\u5F8B\u4F18\u5148 edit_file**\uFF08\u7CBE\u51C6\u5C40\u90E8\u66FF\u6362\u3001\u4FDD\u7559\u539F\u7F29\u8FDB\u3001\u6700\u5C0F diff\uFF09\uFF1Bwrite_file / create_file \u4EC5\u7528\u4E8E\u65B0\u5EFA\u6587\u4EF6\u6216\u5F7B\u5E95\u91CD\u5199\u6574\u4E2A\u6587\u4EF6\u3002\u2605 \u7528 write_file \u5168\u91CF\u8986\u76D6\u65E2\u6709\u6587\u4EF6\u4F1A\u4E22\u5931\u539F\u6709\u7F29\u8FDB\u4E0E\u683C\u5F0F\u3001\u4EA7\u751F\u5927\u91CF\u65E0\u5173 diff\uFF0C\u662F\u7528\u6237\u660E\u786E\u53CD\u611F\u7684\u53CD\u6A21\u5F0F\u2014\u2014\u5373\u4FBF\u8981\u6539\u7684\u5730\u65B9\u5F88\u591A\uFF0C\u4E5F\u7528\u591A\u6B21 edit_file \u800C\u975E\u4E00\u6B21 write_file \u8986\u76D6\u3002
|
|
14032
|
-
- \u8C03\u7528\u5DE5\u5177\u524D\u5148\u81EA\u95EE\uFF1A\u5DF2\u6709\u7684\u4FE1\u606F\u662F\u5426\u8DB3\u4EE5\u56DE\u7B54\u7528\u6237\uFF1F\u591F\u5C31\u4E0D\u518D\u8C03\u5DE5\u5177\uFF0C\u76F4\u63A5\u4F5C\u7B54\u3002
|
|
14033
|
-
- **\u5148\u8BFB\u5168\u518D\u52A8\u624B\uFF0C\u522B\u628A\u641C\u7D22\u5F53\u5B57\u5178\u67E5\uFF08\u53CD\u788E\u6B65\xB7\u91CD\u8981\uFF09**\uFF1A\u8981\u6539\u67D0\u4E2A\u6587\u4EF6/\u6A21\u5757\u524D\uFF0C\u5148\u7528 read_file \u628A\u76F8\u5173\u6587\u4EF6\u4E00\u6B21\u6027\u8BFB\u5168\uFF08\u7ED3\u6784\u3001\u5B57\u6BB5\u3001\u7528\u6CD5\u90FD\u5728\u6587\u4EF6\u91CC\uFF09\uFF0C\u4E0D\u8981\u9760 search_grep \u4E00\u4E2A\u5B57\u6BB5\u3001\u4E00\u4E2A\u7528\u6CD5\u5730\u8BD5\u63A2\u3002search_grep \u662F\u5B9A\u4F4D\u5DE5\u5177\u2014\u2014\u7528\u6765\u627E\u67D0\u7B26\u53F7\u5728\u54EA\u5B9A\u4E49/\u88AB\u8C01\u8C03\u7528\uFF0C\u627E\u5230\u540E\u7ACB\u5373\u8BFB\u5B8C\u6574\u6587\u4EF6\u7406\u89E3\u4E0A\u4E0B\u6587\uFF1B\u7EDD\u4E0D\u7528\u8FD1\u4E49\u5173\u952E\u8BCD\u53CD\u590D\u641C\u540C\u4E00\u4E2A\u610F\u56FE\u3002
|
|
14034
|
-
- **\u6279\u91CF\u89C4\u5212\u6539\u52A8\uFF0C\u4E00\u6B21\u6210\u578B\uFF08\u53CD\u788E\u6B65\xB7\u91CD\u8981\uFF09**\uFF1A\u52A8\u624B\u524D\u5148\u628A\u6240\u6709\u8981\u6539\u7684\u70B9\u60F3\u6E05\u695A\u3001\u5217\u51FA\u6765\uFF0C\u518D\u7528\u591A\u6B21 edit_file \u4E00\u53E3\u6C14\u6539\u5B8C\u3002\u4E0D\u8981"\u6539\u4E00\u5904 \u2192 \u770B\u4E00\u773C \u2192 \u53C8\u53D1\u73B0\u4E00\u5904 \u2192 \u518D\u6539"\u6765\u56DE\u4E03\u516B\u8D9F\u2014\u2014\u65E2\u70E7 token \u53C8\u6613\u9057\u6F0F\u3002\u6B63\u786E\u8282\u594F\uFF1A\u5148\u8BFB\u5168 \u2192 \u89C4\u5212 \u2192 \u6279\u91CF\u6539 \u2192 \u6700\u540E\u7EDF\u4E00\u9A8C\u8BC1\u3002
|
|
14035
|
-
- **\u6539\u5B8C\u52FF\u7ACB\u523B\u91CD\u8BFB\uFF08\u53CD\u788E\u6B65\xB7\u91CD\u8981\uFF09**\uFF1Aedit_file / write_file \u6210\u529F\u8FD4\u56DE\u540E\uFF0C\u5DE5\u5177\u7ED3\u679C\u5DF2\u8BF4\u660E\u6539\u4E86\u4EC0\u4E48\uFF0C\u4E0D\u8981\u9A6C\u4E0A read_file \u628A\u6574\u4E2A\u6587\u4EF6\u91CD\u8BFB\u4E00\u904D\u6765"\u786E\u8BA4"\u3002\u786E\u9700\u6838\u9A8C\u65F6\uFF0C\u53EA\u8BFB\u6539\u52A8\u9644\u8FD1\u51E0\u884C\u6216\u8DD1\u7C7B\u578B\u68C0\u67E5/\u6D4B\u8BD5\uFF0C\u800C\u975E\u6574\u6587\u4EF6\u91CD\u8BFB\u3002
|
|
14036
|
-
- \u4E0D\u91CD\u590D\u6293\u53D6\u5DF2\u6293\u53D6\u8FC7\u7684 URL\uFF1B\u4E0D\u7528\u8FD1\u4E49\u5173\u952E\u8BCD\u53CD\u590D\u641C\u7D22\u540C\u4E00\u4E2A\u610F\u56FE\u3002
|
|
14037
|
-
- \u8054\u7F51/\u641C\u7D22\u7C7B\u8C03\u7814\u4EFB\u52A1\uFF0C\u901A\u5E38 1~3 \u4E2A\u6765\u6E90\u5DF2\u8DB3\u591F\u652F\u6491\u56DE\u7B54\u2014\u2014\u62FF\u5230\u5373\u7EFC\u5408\u4F5C\u7B54\uFF0C\u4E0D\u8981\u4E3A\u8FFD\u6C42"\u66F4\u5168\u9762"\u800C\u65E0\u9650\u8FFD\u52A0\u68C0\u7D22\u8F6E\u6B21\u3002
|
|
14038
|
-
- **\u72EC\u7ACB\u8BFB\u64CD\u4F5C\u5E76\u884C\u6253\u5305\uFF08\u91CD\u8981\uFF09**\uFF1A\u591A\u4E2A\u4E92\u4E0D\u4F9D\u8D56\u7684\u53EA\u8BFB\u8C03\u7528\uFF08\u8BFB\u591A\u4E2A\u6587\u4EF6\u3001\u591A\u4E2A\u68C0\u7D22\u3001\u591A\u4E2A\u5B9A\u4E49\u67E5\u8BE2\uFF09\u5E94\u5728\u540C\u4E00\u6761\u6D88\u606F\u91CC\u4E00\u6B21\u6027\u5168\u90E8\u53D1\u51FA\uFF0C\u6267\u884C\u5C42\u4F1A\u81EA\u52A8\u5E76\u53D1\u6267\u884C\uFF0C\u4E00\u8F6E\u9876\u591A\u8F6E\uFF1B\u6709\u4F9D\u8D56\uFF08\u540E\u4E00\u6B65\u8981\u7528\u524D\u4E00\u6B65\u7ED3\u679C\uFF09\u6216\u4F1A\u6539\u72B6\u6001\u7684\u64CD\u4F5C\uFF0C\u5FC5\u987B\u7B49\u524D\u5E8F\u7ED3\u679C\u8FD4\u56DE\u518D\u53D1\u3002
|
|
14039
|
-
- \u591A\u6B65\u9AA4\u7684\u590D\u6742\u4EFB\u52A1\uFF08\u22653 \u6B65\u3001\u8DE8\u591A\u6587\u4EF6\u6216\u591A\u9636\u6BB5\uFF09\u5148\u8C03\u7528 todo_write \u628A\u8BA1\u5212\u62C6\u6210\u53EF\u52FE\u9009\u7684\u4EFB\u52A1\u6E05\u5355\uFF0C\u518D\u9010\u6B65\u63A8\u8FDB\u5E76\u5373\u65F6\u66F4\u65B0\u72B6\u6001\u2014\u2014\u8BA9\u4F60\u548C\u7528\u6237\u90FD\u770B\u6E05\u8FDB\u5EA6\u3001\u4E0D\u9057\u6F0F\u6B65\u9AA4\uFF1B\u7B80\u5355 1-2 \u6B65\u7684\u4EFB\u52A1\u65E0\u9700\u5EFA\u6E05\u5355\u3002
|
|
14040
|
-
|
|
14041
|
-
\u3010\u64CD\u4F5C\u786E\u8BA4\u7EA6\u5B9A\u3011
|
|
14042
|
-
- \u9047\u5230\u4F1A\u6539\u53D8\u72B6\u6001\u6216\u5177\u98CE\u9669\u7684\u5DE5\u5177\uFF08\u5199\u6587\u4EF6\u3001\u7F16\u8F91\u3001\u5220\u9664\u3001\u79FB\u52A8\u3001\u6267\u884C\u547D\u4EE4\u3001\u5BF9\u5916\u7F51\u7EDC\u8BF7\u6C42\u7B49\uFF09\uFF0C\u76F4\u63A5\u8C03\u7528\u8BE5\u5DE5\u5177\u5373\u53EF\uFF0C\u4E0D\u8981\u5148\u7528\u81EA\u7136\u8BED\u8A00\u5F81\u6C42\u786E\u8BA4\uFF08\u5982"\u6211\u53EF\u4EE5\u6267\u884C\u5417\uFF1F""\u662F\u5426\u7EE7\u7EED\uFF1F"\uFF09\u3002\u8FD9\u7C7B\u5DE5\u5177\u7531\u7CFB\u7EDF\u7EDF\u4E00\u62E6\u622A\u5E76\u5F39\u51FA\u5BA1\u6279\u754C\u9762\uFF0C\u7528\u6237\u4F1A\u4E00\u952E\u540C\u610F\u6216\u62D2\u7EDD\u2014\u2014\u4F60\u65E0\u9700\u4EE3\u66FF\u7CFB\u7EDF\u53D1\u95EE\uFF0C\u66F4\u4E0D\u8981\u505C\u4E0B\u7B49\u7528\u6237\u6253\u5B57\u786E\u8BA4\u3002
|
|
14043
|
-
- \u4EC5\u5F53\u5B58\u5728\u591A\u79CD\u660E\u663E\u4E0D\u540C\u7684\u5B9E\u73B0\u65B9\u6848\u3001\u9700\u8981\u7528\u6237\u5728\u65B9\u5411\u4E0A\u62CD\u677F\u65F6\uFF0C\u8C03\u7528 ask_question \u5DE5\u5177\u63D0\u51FA 2-4 \u4E2A\u7ED3\u6784\u5316\u9009\u9879\u8BA9\u7528\u6237\u9009\u62E9\uFF08\u7EC8\u7AEF\u4F1A\u5F39\u51FA\u591A\u9009\u6846\uFF0C\u6BD4\u7EAF\u6587\u5B57\u66F4\u6E05\u6670\u9AD8\u6548\uFF0C\u7528\u6237\u9009\u62E9\u4F1A\u81EA\u52A8\u56DE\u4F20\u7ED9\u4F60\uFF1B\u63D0\u95EE\u6846\u6052\u6709\u300COther\u300D\u81EA\u7531\u8F93\u5165\u6863\uFF0C\u9700\u8981\u7528\u6237\u63D0\u4F9B\u9009\u9879\u4E4B\u5916\u7684\u8D44\u6599\u2014\u2014\u5982\u767B\u5F55 token\u3001\u6587\u4EF6\u8DEF\u5F84\u2014\u2014\u4E5F\u7528 ask_question \u63D0\u51FA\uFF0C\u7528\u6237\u4F1A\u7ECF Other \u7C98\u8D34\u539F\u6587\u56DE\u4F20\uFF09\uFF1B\u5BF9"\u67D0\u4E2A\u5177\u4F53\u64CD\u4F5C\u662F\u5426\u6267\u884C"\u4E00\u5F8B\u76F4\u63A5\u8C03\u7528\u5DE5\u5177\u8D70\u5BA1\u6279\uFF0C\u4E0D\u8981\u7528 ask_question \u53BB\u95EE\u80FD\u5426\u6267\u884C\u67D0\u4E2A\u64CD\u4F5C\u3002
|
|
14044
|
-
|
|
14045
|
-
\u3010\u8BA1\u5212\u6A21\u5F0F\u3011
|
|
14046
|
-
${PLAN_MODE_AUTO_ENTER_HINT}
|
|
14047
|
-
- **\u8BA1\u5212\u6A21\u5F0F\u7684\u8BC6\u522B**\uFF1A\u5F53\u4F60\u53D1\u73B0\u5F53\u524D\u53EF\u7528\u5DE5\u5177\u4EC5\u5305\u542B\u8BFB\u53D6\u4E0E\u68C0\u7D22\u7C7B\uFF08read_file/search_grep/glob/git \u53EA\u8BFB/web \u7B49\uFF09\u3001\u4E0D\u542B\u4EFB\u4F55\u5199\u6587\u4EF6/\u6267\u884C\u547D\u4EE4/\u540E\u53F0\u4EFB\u52A1\u7C7B\u5DE5\u5177\u65F6\uFF0C\u8BF4\u660E\u5DF2\u8FDB\u5165\u8BA1\u5212\u6A21\u5F0F\u2014\u2014\u6B64\u65F6\u4E25\u7981\u4FEE\u6539\u4EFB\u4F55\u6587\u4EF6\u6216\u6267\u884C\u547D\u4EE4\uFF0C\u53EA\u80FD\u8C03\u7814\uFF0C\u5B8C\u6210\u540E\u5FC5\u987B\u8C03\u7528 exit_plan_mode \u63D0\u4EA4\u65B9\u6848\u3002
|
|
14048
|
-
- **\u63D0\u4EA4\u65B9\u6848\u5FC5\u987B\u7528\u5DE5\u5177**\uFF1A\u8FDB\u5165\u8BA1\u5212\u6A21\u5F0F\u540E\u7528 exit_plan_mode \u63D0\u4EA4\uFF1B\u82E5\u4F60\u5728\u6B63\u5E38\u8F6E\u5DF2\u81EA\u884C\u7528\u53EA\u8BFB\u5DE5\u5177\u5B8C\u6210\u8C03\u7814\uFF0C\u4E5F\u53EF\u76F4\u63A5\u8C03 exit_plan_mode \u63D0\u4EA4\u3002\u7EDD\u4E0D\u8981\u4EE5\u7EAF\u6587\u672C\u9648\u8FF0\u65B9\u6848\u7136\u540E\u505C\u4E0B\u7B49\u5F85\u5BA1\u6279\u2014\u2014\u7EAF\u6587\u672C\u65B9\u6848\u4E0D\u4F1A\u89E6\u53D1\u5BA1\u6279\u754C\u9762\uFF0C\u7528\u6237\u65E0\u6CD5\u4E00\u952E\u6279\u51C6/\u7F16\u8F91\uFF0C\u6D41\u7A0B\u4F1A\u5361\u6B7B\u3002
|
|
14049
|
-
|
|
14050
|
-
\u3010\u6301\u4E45\u8BB0\u5FC6\u3011
|
|
14051
|
-
- \u4F60\u62E5\u6709\u8DE8\u4F1A\u8BDD\u7684\u6301\u4E45\u8BB0\u5FC6\uFF1A\u7CFB\u7EDF\u63D0\u793A\u8BCD\u4E2D\u4EE5\u3010\u8BB0\u5FC6\u7D22\u5F15\u3011\u5217\u51FA\u5DF2\u5B58\u8BB0\u5FC6\uFF08\u4E00\u884C/\u6761\uFF1A\u540D\u79F0\u3001\u7C7B\u522B\u3001\u63CF\u8FF0\uFF09\u3002\u5F53\u7D22\u5F15\u4E2D\u67D0\u6761\u4E0E\u5F53\u524D\u4EFB\u52A1\u76F8\u5173\u3001\u9700\u8981\u7EC6\u8282\u65F6\uFF0C\u8C03\u7528 memory_read \u6309\u9700\u53EC\u56DE\u5168\u6587\uFF1B\u4E0D\u8981\u65E0\u5DEE\u522B\u5730\u5168\u91CF\u8BFB\u53D6\u3002
|
|
14052
|
-
- \u9047\u5230\u503C\u5F97\u8DE8\u4F1A\u8BDD\u4FDD\u7559\u7684\u4FE1\u606F\u65F6\uFF0C\u4E3B\u52A8\u7528 memory_save \u5B58\u6210\u8BB0\u5FC6\uFF0C\u4F8B\u5982\uFF1A\u7528\u6237\u7684\u957F\u671F\u504F\u597D\u4E0E\u89D2\u8272\u753B\u50CF\u3001\u7528\u6237\u7ED9\u51FA\u7684\u5DE5\u4F5C\u65B9\u5F0F\u53CD\u9988\uFF08\u542B\u539F\u56E0\u4E0E\u505A\u6CD5\uFF09\u3001\u9879\u76EE\u76EE\u6807\u4E0E\u9690\u542B\u7EA6\u675F\u3001\u5916\u90E8\u8D44\u6E90\u6307\u9488\uFF08URL/\u770B\u677F/\u5DE5\u5355\uFF09\u3002\u5373\u90A3\u4E9B\u300C\u4E0B\u6B21\u4E0D\u8BE5\u91CD\u65B0\u53D1\u73B0\u300D\u300C\u4EE3\u7801\u4E0E git \u4E0D\u4F1A\u76F4\u63A5\u544A\u8BC9\u4F60\u300D\u7684\u975E\u663E\u7136\u4E8B\u5B9E\u3002
|
|
14053
|
-
- \u4E0D\u8981\u4FDD\u5B58\uFF1A\u4EE3\u7801\u7ED3\u6784\u3001\u8FC7\u5F80\u4FEE\u590D\u3001git \u5386\u53F2\u7B49\u4ED3\u5E93\u672C\u8EAB\u5DF2\u8BB0\u5F55\u7684\u5185\u5BB9\uFF1B\u53EA\u5BF9\u672C\u6B21\u5BF9\u8BDD\u6709\u610F\u4E49\u3001\u4E0B\u4E0D\u4E3A\u4F8B\u7684\u4E34\u65F6\u4FE1\u606F\u3002\u82E5\u4E0D\u786E\u5B9A\u67D0\u6761\u4FE1\u606F\u662F\u5426\u503C\u5F97\u5B58\uFF0C\u5148\u95EE\u6E05\u5176\u975E\u663E\u7136\u4E4B\u5904\uFF0C\u5B58\u90A3\u4E00\u70B9\u800C\u975E\u6574\u6BB5\u6D41\u6C34\u3002
|
|
14054
|
-
- \u8BB0\u5FC6\u4F1A\u91CD\u590D\u51FA\u73B0\uFF0C\u53D1\u73B0\u5DF2\u5931\u6548\u6216\u6709\u8BEF\u7684\u8BB0\u5FC6\u7528 memory_delete \u6E05\u7406\u3002\u7C7B\u522B\u6309\u8BED\u4E49\u9009\uFF1Auser\uFF08\u7528\u6237\u753B\u50CF/\u504F\u597D\uFF09/ feedback\uFF08\u5DE5\u4F5C\u65B9\u5F0F\u53CD\u9988\uFF09/ project\uFF08\u9879\u76EE\u76EE\u6807/\u7EA6\u675F\uFF09/ reference\uFF08\u5916\u90E8\u8D44\u6E90\u6307\u9488\uFF09\u3002`;
|
|
14055
|
-
}
|
|
14056
|
-
});
|
|
14057
|
-
|
|
14058
14466
|
// ../core/src/serve/chatProcessing.ts
|
|
14059
|
-
import
|
|
14060
|
-
import
|
|
14467
|
+
import path48 from "path";
|
|
14468
|
+
import fs46 from "fs";
|
|
14061
14469
|
var handleUnifiedChat;
|
|
14062
14470
|
var init_chatProcessing = __esm({
|
|
14063
14471
|
"../core/src/serve/chatProcessing.ts"() {
|
|
@@ -14113,17 +14521,17 @@ ${inject}`;
|
|
|
14113
14521
|
if (roots.length > 1) {
|
|
14114
14522
|
let activeReal = getActiveWorkspaceRoot();
|
|
14115
14523
|
try {
|
|
14116
|
-
activeReal =
|
|
14524
|
+
activeReal = fs46.realpathSync(activeReal);
|
|
14117
14525
|
} catch {
|
|
14118
14526
|
}
|
|
14119
|
-
const lines = roots.map((r) => `- ${
|
|
14527
|
+
const lines = roots.map((r) => `- ${path48.basename(r) || r}: ${r}${r === activeReal ? "\uFF08\u9ED8\u8BA4\u6839\uFF1A\u76F8\u5BF9\u8DEF\u5F84/\u547D\u4EE4\u57FA\u51C6\uFF09" : "\uFF08\u53EF\u76F4\u63A5\u8BFB\u5199\uFF09"}`);
|
|
14120
14528
|
sysPrompt = sysPrompt + `
|
|
14121
14529
|
|
|
14122
14530
|
\u3010\u5DE5\u4F5C\u533A\uFF08\u591A\u9879\u76EE\uFF09\u3011
|
|
14123
14531
|
\u65E0\u9700\u5207\u6362\u9879\u76EE\uFF0C\u4EE5\u4E0B\u6240\u6709\u6839\u90FD\u53EF\u76F4\u63A5\u7528\u7EDD\u5BF9\u8DEF\u5F84\u8BBF\u95EE\uFF1B\u8DE8\u9879\u76EE\u7528\u7EDD\u5BF9\u8DEF\u5F84\u6216\u76F8\u5BF9\u9ED8\u8BA4\u6839\u7684 ../<\u5144\u5F1F\u76EE\u5F55>:
|
|
14124
14532
|
${lines.join("\n")}
|
|
14125
|
-
\u2605 \u8DEF\u5F84\u951A\u5B9A\u94C1\u5F8B\uFF1A\u5DE5\u5177\u7F3A\u7701\u53EA\u4F5C\u7528\u4E8E\u9ED8\u8BA4\u6839\uFF08${
|
|
14126
|
-
\u6CE8\u610F\uFF1A\u9879\u76EE\u7EA7\u914D\u7F6E\uFF08.deepseeker-code/\uFF09\u4EC5\u5728\u9ED8\u8BA4\u6839 ${
|
|
14533
|
+
\u2605 \u8DEF\u5F84\u951A\u5B9A\u94C1\u5F8B\uFF1A\u5DE5\u5177\u7F3A\u7701\u53EA\u4F5C\u7528\u4E8E\u9ED8\u8BA4\u6839\uFF08${path48.basename(activeReal) || activeReal} = IDE \u5934\u90E8\u6240\u793A\u6839\uFF09\u3002\u5F53\u7528\u6237\u5728\u5BF9\u8BDD\u4E2D\u6307\u660E\u4E86\u67D0\u4E2A\u9879\u76EE\uFF08\u5982\u300C\u5728 A \u9879\u76EE\u300D\u300C\u6539\u524D\u7AEF\u7684 xxx\u300D\u300C\u641C\u540E\u7AEF\u300D\uFF09\uFF0C\u8BE5\u8F6E\u6240\u6709\u5E26 path \u53C2\u6570\u7684\u5DE5\u5177\u8C03\u7528\uFF08read_file / edit_file / search_grep / glob / list_dir / read_xlsx / read_docx \u7B49\uFF09\u5FC5\u987B\u628A\u5BF9\u5E94\u9879\u76EE\u6839\u4F5C\u4E3A path \u4F20\u5165\uFF08\u7EDD\u5BF9\u8DEF\u5F84\u3001../<\u5144\u5F1F\u76EE\u5F55>\u3001\u6216\u9879\u76EE\u76EE\u5F55\u540D\uFF09\uFF0C\u5426\u5219\u53EA\u4F1A\u8BFB\u5199/\u641C\u7D22\u9ED8\u8BA4\u6839\uFF0C\u4E0E\u7528\u6237\u610F\u56FE\u4E0D\u7B26\u3002
|
|
14534
|
+
\u6CE8\u610F\uFF1A\u9879\u76EE\u7EA7\u914D\u7F6E\uFF08.deepseeker-code/\uFF09\u4EC5\u5728\u9ED8\u8BA4\u6839 ${path48.basename(activeReal) || activeReal} \u751F\u6548\u3002`;
|
|
14127
14535
|
}
|
|
14128
14536
|
const osName = process.platform === "win32" ? "Windows" : process.platform === "darwin" ? "macOS" : "Linux";
|
|
14129
14537
|
const now = /* @__PURE__ */ new Date();
|
|
@@ -14167,7 +14575,8 @@ ${envLines.join("\n")}`;
|
|
|
14167
14575
|
const options = {
|
|
14168
14576
|
sessionId,
|
|
14169
14577
|
cwd: process.cwd(),
|
|
14170
|
-
toolSchemas: agentTools,
|
|
14578
|
+
toolSchemas: opts?.toolSchemas ?? agentTools,
|
|
14579
|
+
// 宿主可按需裁剪(挂机批处理);缺省全量,行为不变
|
|
14171
14580
|
abortSignal,
|
|
14172
14581
|
// ← 透传中止信号
|
|
14173
14582
|
modelWindow: appConfig.MAX_HISTORY_TOKENS,
|
|
@@ -14188,7 +14597,9 @@ ${envLines.join("\n")}`;
|
|
|
14188
14597
|
model: opts?.model,
|
|
14189
14598
|
thinkingLevel: opts?.thinkingLevel,
|
|
14190
14599
|
locale: opts?.locale,
|
|
14191
|
-
outputStyle: opts?.outputStyle
|
|
14600
|
+
outputStyle: opts?.outputStyle,
|
|
14601
|
+
budgetYuan: opts?.budgetYuan
|
|
14602
|
+
// ★ 预算制运行(成本信任链第二环 E1):主 run 传入,子 run 经 costSink 回灌
|
|
14192
14603
|
};
|
|
14193
14604
|
await runWithSessionContext(sessionId, async () => {
|
|
14194
14605
|
try {
|
|
@@ -14229,7 +14640,7 @@ ${envLines.join("\n")}`;
|
|
|
14229
14640
|
});
|
|
14230
14641
|
|
|
14231
14642
|
// ../core/src/session/fork.ts
|
|
14232
|
-
import
|
|
14643
|
+
import fs47 from "fs/promises";
|
|
14233
14644
|
var listForkAnchors, derivePrefix, forkSession;
|
|
14234
14645
|
var init_fork = __esm({
|
|
14235
14646
|
"../core/src/session/fork.ts"() {
|
|
@@ -14302,7 +14713,7 @@ var init_fork = __esm({
|
|
|
14302
14713
|
const prefix = derivePrefix(lines, upToLineId);
|
|
14303
14714
|
const newId = createUUID();
|
|
14304
14715
|
await ensureSessionsDir(newId);
|
|
14305
|
-
const rawText = await
|
|
14716
|
+
const rawText = await fs47.readFile(getTranscriptPath(sourceId), "utf-8");
|
|
14306
14717
|
const kept = [];
|
|
14307
14718
|
let good = 0;
|
|
14308
14719
|
for (const s of rawText.split("\n")) {
|
|
@@ -14318,7 +14729,7 @@ var init_fork = __esm({
|
|
|
14318
14729
|
}
|
|
14319
14730
|
let payload = kept.join("\n");
|
|
14320
14731
|
if (payload.length > 0 && !payload.endsWith("\n")) payload += "\n";
|
|
14321
|
-
await
|
|
14732
|
+
await fs47.writeFile(getTranscriptPath(newId), payload, "utf-8");
|
|
14322
14733
|
const srcState = await readStore(sourceId);
|
|
14323
14734
|
const srcRolling = await getRollingState(sourceId);
|
|
14324
14735
|
const legacy = !lines.some(isEventLine);
|
|
@@ -14664,6 +15075,11 @@ var init_useChatState = __esm({
|
|
|
14664
15075
|
!MODEL_THINKING_ENABLED ? "off" : MODEL_REASONING_EFFORT === "max" ? "max" : "high"
|
|
14665
15076
|
);
|
|
14666
15077
|
const archivedSummaryRef = useRef("");
|
|
15078
|
+
const lastRunCostRef = useRef(void 0);
|
|
15079
|
+
const sessionCostRef = useRef(void 0);
|
|
15080
|
+
const budgetYuanRef = useRef(void 0);
|
|
15081
|
+
const lastRunCacheHitRef = useRef(void 0);
|
|
15082
|
+
const contextUsageRef = useRef(void 0);
|
|
14667
15083
|
const compactProgressIdRef = useRef(null);
|
|
14668
15084
|
const dropCompactProgressRow = useCallback(() => {
|
|
14669
15085
|
const pid = compactProgressIdRef.current;
|
|
@@ -14841,6 +15257,34 @@ var init_useChatState = __esm({
|
|
|
14841
15257
|
}]);
|
|
14842
15258
|
break;
|
|
14843
15259
|
}
|
|
15260
|
+
case "run.receipt": {
|
|
15261
|
+
flush();
|
|
15262
|
+
const rounds = obj.rounds ?? 0;
|
|
15263
|
+
const promptT = obj.promptTokens ?? 0;
|
|
15264
|
+
const completionT = obj.completionTokens ?? 0;
|
|
15265
|
+
const hitPct = Math.round((obj.cacheHitRate ?? 0) * 100);
|
|
15266
|
+
const durMs = obj.durationMs ?? 0;
|
|
15267
|
+
const durText = durMs >= 6e4 ? `${Math.floor(durMs / 6e4)}m${Math.round(durMs % 6e4 / 1e3)}s` : `${(durMs / 1e3).toFixed(1)}s`;
|
|
15268
|
+
const cost = obj.costYuan;
|
|
15269
|
+
const tokTotal = promptT + completionT;
|
|
15270
|
+
const tokText = tokTotal >= 1e4 ? `${(tokTotal / 1e3).toFixed(1)}k` : String(tokTotal);
|
|
15271
|
+
const costText = typeof cost === "number" ? `\xA5${cost.toFixed(cost < 5e-3 ? 4 : 3)}` : `${tokText} tok`;
|
|
15272
|
+
setRows((prev) => [...prev, {
|
|
15273
|
+
id: newRowId(),
|
|
15274
|
+
kind: "meta",
|
|
15275
|
+
text: `\u{1F4B0} \u672C\u6B21 ${rounds} \u8F6E \xB7 ${costText} \xB7 \u7F13\u5B58\u547D\u4E2D ${hitPct}% \xB7 ${durText}${obj.budgetTruncated ? " \xB7 \u9884\u7B97\u622A\u65AD" : ""}`
|
|
15276
|
+
}]);
|
|
15277
|
+
lastRunCostRef.current = typeof cost === "number" ? cost : void 0;
|
|
15278
|
+
sessionCostRef.current = typeof cost === "number" ? (sessionCostRef.current ?? 0) + cost : sessionCostRef.current;
|
|
15279
|
+
lastRunCacheHitRef.current = typeof obj.cacheHitRate === "number" ? obj.cacheHitRate : void 0;
|
|
15280
|
+
break;
|
|
15281
|
+
}
|
|
15282
|
+
case "context.usage": {
|
|
15283
|
+
const used = obj.usedTokens ?? 0;
|
|
15284
|
+
const win = obj.windowTokens ?? 0;
|
|
15285
|
+
if (win > 0) contextUsageRef.current = { used_tokens: used, window_tokens: win, fill_rate: used / win };
|
|
15286
|
+
break;
|
|
15287
|
+
}
|
|
14844
15288
|
case "task.exit": {
|
|
14845
15289
|
flush();
|
|
14846
15290
|
const cmd = obj.command ?? "";
|
|
@@ -15006,7 +15450,9 @@ var init_useChatState = __esm({
|
|
|
15006
15450
|
model: modelRef.current || void 0,
|
|
15007
15451
|
thinkingLevel: thinkingLevelRef.current,
|
|
15008
15452
|
locale: getLocale(),
|
|
15009
|
-
outputStyle: outputStyleRef.current
|
|
15453
|
+
outputStyle: outputStyleRef.current,
|
|
15454
|
+
budgetYuan: budgetYuanRef.current
|
|
15455
|
+
// ★ 预算制运行(成本信任链第二环 E1):/budget 设置,超限 soft nudge + 120% 硬截断
|
|
15010
15456
|
};
|
|
15011
15457
|
try {
|
|
15012
15458
|
await handleUnifiedChat(
|
|
@@ -15143,6 +15589,10 @@ ${r.output.trim() || "(\u65E0\u8F93\u51FA)"}`);
|
|
|
15143
15589
|
}, [flush]);
|
|
15144
15590
|
const loadSession = useCallback(async (id) => {
|
|
15145
15591
|
sessionIdRef.current = id;
|
|
15592
|
+
lastRunCostRef.current = void 0;
|
|
15593
|
+
sessionCostRef.current = void 0;
|
|
15594
|
+
lastRunCacheHitRef.current = void 0;
|
|
15595
|
+
contextUsageRef.current = void 0;
|
|
15146
15596
|
clearRows();
|
|
15147
15597
|
try {
|
|
15148
15598
|
const lines = await readTranscriptLines(id);
|
|
@@ -15169,6 +15619,10 @@ ${r.output.trim() || "(\u65E0\u8F93\u51FA)"}`);
|
|
|
15169
15619
|
}, [pushInfo, loadSession]);
|
|
15170
15620
|
const newSession = useCallback(async () => {
|
|
15171
15621
|
sessionIdRef.current = await getOrCreateSessionId(void 0);
|
|
15622
|
+
lastRunCostRef.current = void 0;
|
|
15623
|
+
sessionCostRef.current = void 0;
|
|
15624
|
+
lastRunCacheHitRef.current = void 0;
|
|
15625
|
+
contextUsageRef.current = void 0;
|
|
15172
15626
|
clearRows();
|
|
15173
15627
|
pushInfo(S.sessionNew(truncateMiddle(sessionIdRef.current, 12)));
|
|
15174
15628
|
}, [clearRows, pushInfo]);
|
|
@@ -15238,6 +15692,14 @@ ${r.output.trim() || "(\u65E0\u8F93\u51FA)"}`);
|
|
|
15238
15692
|
}, []);
|
|
15239
15693
|
const getOutputStyle2 = useCallback(() => outputStyleRef.current, []);
|
|
15240
15694
|
const getArchivedSummary = useCallback(() => archivedSummaryRef.current, []);
|
|
15695
|
+
const getLastRunCostYuan = useCallback(() => lastRunCostRef.current, []);
|
|
15696
|
+
const getSessionCostYuan = useCallback(() => sessionCostRef.current, []);
|
|
15697
|
+
const getLastRunCacheHitRate = useCallback(() => lastRunCacheHitRef.current, []);
|
|
15698
|
+
const getLastContextUsage = useCallback(() => contextUsageRef.current, []);
|
|
15699
|
+
const setBudgetYuan = useCallback((v) => {
|
|
15700
|
+
budgetYuanRef.current = v;
|
|
15701
|
+
}, []);
|
|
15702
|
+
const getBudgetYuan = useCallback(() => budgetYuanRef.current, []);
|
|
15241
15703
|
return {
|
|
15242
15704
|
// 状态
|
|
15243
15705
|
rows,
|
|
@@ -15277,6 +15739,12 @@ ${r.output.trim() || "(\u65E0\u8F93\u51FA)"}`);
|
|
|
15277
15739
|
setOutputStyle,
|
|
15278
15740
|
getOutputStyle: getOutputStyle2,
|
|
15279
15741
|
getArchivedSummary,
|
|
15742
|
+
getLastRunCostYuan,
|
|
15743
|
+
getSessionCostYuan,
|
|
15744
|
+
setBudgetYuan,
|
|
15745
|
+
getBudgetYuan,
|
|
15746
|
+
getLastRunCacheHitRate,
|
|
15747
|
+
getLastContextUsage,
|
|
15280
15748
|
openSessionPicker,
|
|
15281
15749
|
resolveSession,
|
|
15282
15750
|
loadSession,
|
|
@@ -16385,7 +16853,7 @@ var init_TopPanel = __esm({
|
|
|
16385
16853
|
});
|
|
16386
16854
|
|
|
16387
16855
|
// ../core/src/observability/inspect.ts
|
|
16388
|
-
import
|
|
16856
|
+
import fs48 from "fs";
|
|
16389
16857
|
var CWD, fmt, readTrace, STOP_LABEL, fmtK, inspectUsage, inspectContext, inspectPermissions, inspectMcp, inspectHooks, inspectDebug;
|
|
16390
16858
|
var init_inspect = __esm({
|
|
16391
16859
|
"../core/src/observability/inspect.ts"() {
|
|
@@ -16396,7 +16864,11 @@ var init_inspect = __esm({
|
|
|
16396
16864
|
init_loader();
|
|
16397
16865
|
init_store3();
|
|
16398
16866
|
init_usageLog();
|
|
16867
|
+
init_prices();
|
|
16399
16868
|
init_store();
|
|
16869
|
+
init_sidecar();
|
|
16870
|
+
init_truncate();
|
|
16871
|
+
init_recall();
|
|
16400
16872
|
init_createModel();
|
|
16401
16873
|
CWD = process.cwd();
|
|
16402
16874
|
fmt = (n) => typeof n === "number" && Number.isFinite(n) ? n.toLocaleString("en-US") : "-";
|
|
@@ -16404,7 +16876,7 @@ var init_inspect = __esm({
|
|
|
16404
16876
|
if (!sessionId) return [];
|
|
16405
16877
|
try {
|
|
16406
16878
|
const p = await getTraceStorePath(sessionId);
|
|
16407
|
-
const text = await
|
|
16879
|
+
const text = await fs48.promises.readFile(p, "utf8");
|
|
16408
16880
|
const out = [];
|
|
16409
16881
|
for (const line of text.split("\n")) {
|
|
16410
16882
|
if (!line.trim()) continue;
|
|
@@ -16456,7 +16928,8 @@ var init_inspect = __esm({
|
|
|
16456
16928
|
lines.push(` ${String(r.ts).slice(5, 16).replace("T", " ")} ${r.rounds}\u8F6E ${fmtK(r.totalTokens ?? 0)} tok ${STOP_LABEL[r.stopReason] ?? r.stopReason} ${tools}`);
|
|
16457
16929
|
}
|
|
16458
16930
|
}
|
|
16459
|
-
const
|
|
16931
|
+
const weekRecords = await readUsageRecords(7);
|
|
16932
|
+
const week = summarizeUsage(weekRecords);
|
|
16460
16933
|
if (week.runs > 0) {
|
|
16461
16934
|
const weekHit = week.promptTokens > 0 ? (week.cachedTokens / week.promptTokens * 100).toFixed(1) : "0.0";
|
|
16462
16935
|
const weekAbort = week.mainRuns > 0 ? Math.round(week.stopReasons.aborted / week.mainRuns * 100) : 0;
|
|
@@ -16466,6 +16939,23 @@ var init_inspect = __esm({
|
|
|
16466
16939
|
` \u258E\u8FD1 7 \u5929\uFF08\u4F7F\u7528\u65E5\u5FD7 \xB7 \u5168\u9879\u76EE\uFF09\uFF1A${week.mainRuns} runs \xB7 ${week.mainRounds} \u8F6E\uFF08\u5747 ${weekAvg} \u8F6E/run\uFF09\xB7 \u4E2D\u6B62 ${weekAbort}% \xB7 ${fmtK(week.totalTokens)} tok\uFF08\u7F13\u5B58\u547D\u4E2D ${weekHit}%\uFF09`,
|
|
16467
16940
|
` \u5E38\u7528\u5DE5\u5177: ${tools || "\uFF08\u65E0\uFF09"}`
|
|
16468
16941
|
);
|
|
16942
|
+
const bySession = /* @__PURE__ */ new Map();
|
|
16943
|
+
let weekCost = 0, weekSaved = 0, pricedRuns = 0;
|
|
16944
|
+
for (const r of weekRecords) {
|
|
16945
|
+
const c = r.costYuan ?? calcCostYuan(r.model, r);
|
|
16946
|
+
if (c == null) continue;
|
|
16947
|
+
pricedRuns++;
|
|
16948
|
+
weekCost += c;
|
|
16949
|
+
bySession.set(r.sessionId, (bySession.get(r.sessionId) ?? 0) + c);
|
|
16950
|
+
const p = priceFor(r.model);
|
|
16951
|
+
if (p) weekSaved += (r.cachedTokens ?? 0) * (p.input - p.cacheHit) / 1e6;
|
|
16952
|
+
}
|
|
16953
|
+
if (pricedRuns > 0) {
|
|
16954
|
+
const tops = [...bySession.entries()].sort((a, b) => b[1] - a[1]).slice(0, 3).map(([sid, c]) => `${sid.slice(0, 8)} \xA5${c.toFixed(3)}`).join(" \xB7 ");
|
|
16955
|
+
const unpaid = week.runs - pricedRuns;
|
|
16956
|
+
lines.push(` \u8FD1 7 \u5929\u82B1\u8D39 \xA5${weekCost.toFixed(3)}\uFF08\u7F13\u5B58\u547D\u4E2D\u5DF2\u7701 \xA5${weekSaved.toFixed(3)}\uFF09${unpaid > 0 ? ` \xB7 ${unpaid} \u6761\u65E0\u4EF7\u8BB0\u5F55\u672A\u8BA1` : ""}`);
|
|
16957
|
+
if (tops) lines.push(` \u8D39\u7528 top \u4F1A\u8BDD: ${tops}`);
|
|
16958
|
+
}
|
|
16469
16959
|
}
|
|
16470
16960
|
lines.push(` \u63D0\u793A\uFF1A\u5E76\u884C workflow \u4F1A\u653E\u5927\u5B50 agent \u7528\u91CF\uFF1B\u7F13\u5B58\u547D\u4E2D\u7387\u8D8A\u9AD8\uFF0C\u8F93\u5165\u6210\u672C\u8D8A\u4F4E\u3002`);
|
|
16471
16961
|
return lines.join("\n");
|
|
@@ -16481,8 +16971,16 @@ var init_inspect = __esm({
|
|
|
16481
16971
|
}
|
|
16482
16972
|
}
|
|
16483
16973
|
let archived = 0;
|
|
16974
|
+
let archivedEntities = 0;
|
|
16975
|
+
try {
|
|
16976
|
+
const rolling = await getRollingState(sessionId);
|
|
16977
|
+
archived = rolling.archivedMessageCount ?? 0;
|
|
16978
|
+
archivedEntities = parseSummarySlot(rolling.rollingSummary ?? "").index.length;
|
|
16979
|
+
} catch {
|
|
16980
|
+
}
|
|
16981
|
+
let sidecarCount = 0;
|
|
16484
16982
|
try {
|
|
16485
|
-
|
|
16983
|
+
sidecarCount = (await fs48.promises.readdir(getToolOutputSidecarDir(sessionId))).filter((f) => f.endsWith(".txt")).length;
|
|
16486
16984
|
} catch {
|
|
16487
16985
|
}
|
|
16488
16986
|
const window = appConfig.MAX_HISTORY_TOKENS;
|
|
@@ -16494,6 +16992,9 @@ var init_inspect = __esm({
|
|
|
16494
16992
|
` \u7A97\u53E3\u4E0A\u9650: ${fmt(window)} | \u538B\u7F29\u9608\u503C: ${fmt(threshold)}\uFF08${ratio}\xD7\uFF09 | \u4FDD\u7559\u6700\u8FD1: ${appConfig.KEEP_RECENT_UNITS} \u5BF9\u8BDD\u5355\u5143`,
|
|
16495
16993
|
` \u6700\u8FD1 prompt: ${lastPrompt ? fmt(lastPrompt) : "\uFF08\u5C1A\u65E0\uFF09"}${fillRate ? `\uFF08\u5360\u7A97\u53E3 ${fillRate}%\uFF09` : ""}`,
|
|
16496
16994
|
` \u5DF2\u5F52\u6863(\u538B\u7F29)\u6D88\u606F\u6761\u6570: ${archived}`,
|
|
16995
|
+
` \u672C\u4F1A\u8BDD\u5DF2\u5F52\u6863\u5B9E\u4F53: ${archivedEntities} \u4E2A\uFF08\u6458\u8981\u69FD\u7D22\u5F15\uFF09`,
|
|
16996
|
+
` \u53EC\u56DE\u547D\u4E2D: ${getRecallHitCount(sessionId)} \u6B21\uFF08recall \u5DE5\u5177\uFF0C\u672C\u6B21\u8FDB\u7A0B\u5185\u8BA1\u6570\uFF09`,
|
|
16997
|
+
` \u4FA7\u8F66\u5B58\u6863: ${sidecarCount} \u6761\uFF08\u8D85\u957F\u5DE5\u5177\u7ED3\u679C\u539F\u6587\uFF0Crecall with_full \u53D6\u56DE\uFF09`,
|
|
16497
16998
|
` \u8D85\u8FC7\u9608\u503C\u5373\u89E6\u53D1\u6EDA\u52A8\u538B\u7F29\uFF1BfillRate \u63A5\u8FD1 ${Math.round(ratio * 100)}% \u65F6\u5373\u5C06\u538B\u7F29\u3002`
|
|
16498
16999
|
].join("\n");
|
|
16499
17000
|
};
|
|
@@ -16664,14 +17165,21 @@ var init_App = __esm({
|
|
|
16664
17165
|
plan_mode: state.getPlanMode(),
|
|
16665
17166
|
auto_mode: state.getAutoMode(),
|
|
16666
17167
|
output_style: state.getOutputStyle() ?? null,
|
|
16667
|
-
workspace: { current_dir: CWD2, project_dir: CWD2 }
|
|
17168
|
+
workspace: { current_dir: CWD2, project_dir: CWD2 },
|
|
17169
|
+
last_run_cost_yuan: state.getLastRunCostYuan(),
|
|
17170
|
+
// 结算单(成本信任链 D3):undefined 自动省略键
|
|
17171
|
+
session_cost_yuan: state.getSessionCostYuan(),
|
|
17172
|
+
last_run_cache_hit_rate: state.getLastRunCacheHitRate(),
|
|
17173
|
+
// H3:undefined 自动省略键
|
|
17174
|
+
context: state.getLastContextUsage()
|
|
17175
|
+
// H3 水位:undefined 自动省略键
|
|
16668
17176
|
};
|
|
16669
17177
|
const text = await runStatusLine(cfg, ctx);
|
|
16670
17178
|
if (text) setStatusLineText(text);
|
|
16671
17179
|
} finally {
|
|
16672
17180
|
statusLineRunRef.current = false;
|
|
16673
17181
|
}
|
|
16674
|
-
}, [modelDisplay, state.busy, state.aborting, state.getPlanMode, state.getAutoMode, state.getOutputStyle, state.sessionIdRef]);
|
|
17182
|
+
}, [modelDisplay, state.busy, state.aborting, state.getPlanMode, state.getAutoMode, state.getOutputStyle, state.sessionIdRef, state.getLastRunCostYuan, state.getSessionCostYuan, state.getLastRunCacheHitRate, state.getLastContextUsage]);
|
|
16675
17183
|
const refreshStatusLineRef = useRef2(refreshStatusLine);
|
|
16676
17184
|
refreshStatusLineRef.current = refreshStatusLine;
|
|
16677
17185
|
useEffect4(() => {
|
|
@@ -16731,6 +17239,8 @@ var init_App = __esm({
|
|
|
16731
17239
|
return S.cmdFork;
|
|
16732
17240
|
case "usage":
|
|
16733
17241
|
return S.cmdUsage;
|
|
17242
|
+
case "budget":
|
|
17243
|
+
return S.cmdBudget;
|
|
16734
17244
|
case "context":
|
|
16735
17245
|
return S.cmdContext;
|
|
16736
17246
|
case "permissions":
|
|
@@ -16880,6 +17390,28 @@ ${s}` : "\u672C\u4F1A\u8BDD\u542F\u52A8\u4EE5\u6765\u5C1A\u672A\u53D1\u751F\u8FC
|
|
|
16880
17390
|
state.pushInfo(`\u8BA1\u5212\u6A21\u5F0F\uFF1A${on ? "\u5F00\uFF08\u4E0B\u6B21\u63D0\u95EE\u5148\u53EA\u8BFB\u8C03\u7814\u5E76\u4EA7\u51FA\u65B9\u6848\uFF0C\u5BA1\u6279\u540E\u5B9E\u73B0\uFF09" : "\u5173"}`);
|
|
16881
17391
|
return true;
|
|
16882
17392
|
}
|
|
17393
|
+
case "/budget": {
|
|
17394
|
+
const v = arg.trim().toLowerCase();
|
|
17395
|
+
if (!v) {
|
|
17396
|
+
const b = state.getBudgetYuan();
|
|
17397
|
+
const last = state.getLastRunCostYuan();
|
|
17398
|
+
state.pushInfo(`\u{1F4B0} \u9884\u7B97\uFF1A${b != null ? `\xA5${b}/run` : "\u672A\u8BBE\u7F6E\uFF08/budget 0.5 \u8BBE\u7F6E\u6BCF\u4E2A run \u7684\u82B1\u8D39\u4E0A\u9650\uFF09"}${last != null ? ` \xB7 \u4E0A\u4E2A run \u5DF2\u82B1 \xA5${last.toFixed(3)}` : " \xB7 \u5C1A\u65E0\u5B8C\u6210 run"}`);
|
|
17399
|
+
return true;
|
|
17400
|
+
}
|
|
17401
|
+
if (v === "off" || v === "0") {
|
|
17402
|
+
state.setBudgetYuan(void 0);
|
|
17403
|
+
state.pushInfo("\u{1F4B0} \u9884\u7B97\u5DF2\u5173\u95ED\uFF08\u4E0D\u9650\u82B1\u8D39\uFF09\u3002");
|
|
17404
|
+
return true;
|
|
17405
|
+
}
|
|
17406
|
+
const n = Number(v);
|
|
17407
|
+
if (!Number.isFinite(n) || n <= 0) {
|
|
17408
|
+
state.pushInfo("\u7528\u6CD5\uFF1A/budget 0.5\uFF08\u5143/run\uFF09\xB7 /budget off \xB7 /budget \u67E5\u770B");
|
|
17409
|
+
return true;
|
|
17410
|
+
}
|
|
17411
|
+
state.setBudgetYuan(n);
|
|
17412
|
+
state.pushInfo(`\u{1F4B0} \u9884\u7B97\u5DF2\u8BBE\u7F6E\uFF1A\u6BCF run \xA5${n}\uFF08\u8D85\u9650\u5148\u63D0\u9192\u6536\u655B\uFF0C\u4ECD\u8D85 120% \u5C06\u622A\u65AD\u672C run\uFF09\u3002`);
|
|
17413
|
+
return true;
|
|
17414
|
+
}
|
|
16883
17415
|
case "/auto": {
|
|
16884
17416
|
const on = !state.getAutoMode();
|
|
16885
17417
|
state.setAutoMode(on);
|
|
@@ -17253,6 +17785,370 @@ ${listText}`);
|
|
|
17253
17785
|
}
|
|
17254
17786
|
});
|
|
17255
17787
|
|
|
17788
|
+
// src/batchRunner.ts
|
|
17789
|
+
var batchRunner_exports = {};
|
|
17790
|
+
__export(batchRunner_exports, {
|
|
17791
|
+
parseWaitWindow: () => parseWaitWindow,
|
|
17792
|
+
runBatchQueue: () => runBatchQueue
|
|
17793
|
+
});
|
|
17794
|
+
import fs49 from "fs";
|
|
17795
|
+
import { spawn as spawn6 } from "child_process";
|
|
17796
|
+
var BATCH_EDIT_TOOLS, BATCH_DEFAULT_DENYLIST, ACCEPT_TIMEOUT_MIN, ACCEPT_TAIL_LINES, emit2, ts, STATUS_LABEL, runAcceptCommand, collectSessionCost, fmtCost, fmtReceiptLine, buildReport, runOneTask, parseWaitWindow, nowMinutes, sleep, waitUntilWindow, runBatchQueue;
|
|
17797
|
+
var init_batchRunner = __esm({
|
|
17798
|
+
"src/batchRunner.ts"() {
|
|
17799
|
+
"use strict";
|
|
17800
|
+
init_chatProcessing();
|
|
17801
|
+
init_tool();
|
|
17802
|
+
init_manager();
|
|
17803
|
+
init_sessionRegistry();
|
|
17804
|
+
init_background();
|
|
17805
|
+
init_guard();
|
|
17806
|
+
init_common();
|
|
17807
|
+
init_usageLog();
|
|
17808
|
+
init_ticket();
|
|
17809
|
+
init_queue();
|
|
17810
|
+
BATCH_EDIT_TOOLS = /* @__PURE__ */ new Set(["edit_file", "create_file", "write_file", "move_file", "notebook_edit"]);
|
|
17811
|
+
BATCH_DEFAULT_DENYLIST = /* @__PURE__ */ new Set(["run_command", "delete_path"]);
|
|
17812
|
+
ACCEPT_TIMEOUT_MIN = 10;
|
|
17813
|
+
ACCEPT_TAIL_LINES = 60;
|
|
17814
|
+
emit2 = (s = "") => {
|
|
17815
|
+
process.stdout.write(s + "\n");
|
|
17816
|
+
};
|
|
17817
|
+
ts = () => (/* @__PURE__ */ new Date()).toLocaleTimeString("zh-CN", { hour12: false });
|
|
17818
|
+
STATUS_LABEL = {
|
|
17819
|
+
passed: "\u2705 \u901A\u8FC7\u9A8C\u6536",
|
|
17820
|
+
"accept-failed": "\u274C \u9A8C\u6536\u672A\u8FC7",
|
|
17821
|
+
timeout: "\u23F1\uFE0F \u8D85\u65F6\u622A\u65AD",
|
|
17822
|
+
error: "\u{1F4A5} agent \u5F02\u5E38",
|
|
17823
|
+
rejected: "\u{1F6AB} \u5DE5\u5355\u88AB\u62D2"
|
|
17824
|
+
};
|
|
17825
|
+
runAcceptCommand = async (cmd, cwd) => {
|
|
17826
|
+
const isWin = process.platform === "win32";
|
|
17827
|
+
return new Promise((resolve) => {
|
|
17828
|
+
let child;
|
|
17829
|
+
try {
|
|
17830
|
+
child = spawn6(cmd, {
|
|
17831
|
+
shell: isWin ? resolveWinShell() ?? true : true,
|
|
17832
|
+
cwd,
|
|
17833
|
+
windowsHide: true,
|
|
17834
|
+
env: scrubCommandEnv()
|
|
17835
|
+
// 剔除 agent 自身凭证(同 run_command 红线)
|
|
17836
|
+
});
|
|
17837
|
+
} catch (e) {
|
|
17838
|
+
resolve({ code: null, output: `\u542F\u52A8\u5931\u8D25\uFF1A${e?.message ?? e}`, timedOut: false });
|
|
17839
|
+
return;
|
|
17840
|
+
}
|
|
17841
|
+
const chunks = [];
|
|
17842
|
+
child.stdout?.on("data", (d) => chunks.push(d));
|
|
17843
|
+
child.stderr?.on("data", (d) => chunks.push(d));
|
|
17844
|
+
let timedOut = false;
|
|
17845
|
+
const killer = setTimeout(() => {
|
|
17846
|
+
timedOut = true;
|
|
17847
|
+
try {
|
|
17848
|
+
child.kill("SIGKILL");
|
|
17849
|
+
} catch {
|
|
17850
|
+
}
|
|
17851
|
+
}, ACCEPT_TIMEOUT_MIN * 6e4);
|
|
17852
|
+
child.on("error", (e) => {
|
|
17853
|
+
clearTimeout(killer);
|
|
17854
|
+
resolve({ code: null, output: `\u6267\u884C\u5931\u8D25\uFF1A${e?.message ?? e}`, timedOut });
|
|
17855
|
+
});
|
|
17856
|
+
child.on("close", (code) => {
|
|
17857
|
+
clearTimeout(killer);
|
|
17858
|
+
const text = decodeProcessOutput(Buffer.concat(chunks)).trim();
|
|
17859
|
+
const lines = text.split("\n");
|
|
17860
|
+
const tail = lines.length > ACCEPT_TAIL_LINES ? `\uFF08\u524D ${lines.length - ACCEPT_TAIL_LINES} \u884C\u5DF2\u7701\u7565\uFF09
|
|
17861
|
+
${lines.slice(-ACCEPT_TAIL_LINES).join("\n")}` : text;
|
|
17862
|
+
resolve({ code, output: tail || "\uFF08\u65E0\u8F93\u51FA\uFF09", timedOut });
|
|
17863
|
+
});
|
|
17864
|
+
});
|
|
17865
|
+
};
|
|
17866
|
+
collectSessionCost = async (sessionId) => {
|
|
17867
|
+
const recs = (await readUsageRecords(2)).filter((r) => r.sessionId === sessionId);
|
|
17868
|
+
const c = { rounds: 0, mainRounds: 0, subRuns: 0, promptTokens: 0, completionTokens: 0, cachedTokens: 0, costYuan: null, partialPrice: false, durationMs: 0 };
|
|
17869
|
+
for (const r of recs) {
|
|
17870
|
+
c.rounds += r.rounds || 0;
|
|
17871
|
+
if (r.depth === 0) c.mainRounds += r.rounds || 0;
|
|
17872
|
+
else c.subRuns++;
|
|
17873
|
+
c.promptTokens += r.promptTokens ?? 0;
|
|
17874
|
+
c.completionTokens += r.completionTokens ?? 0;
|
|
17875
|
+
c.cachedTokens += r.cachedTokens ?? 0;
|
|
17876
|
+
c.durationMs += r.durationMs || 0;
|
|
17877
|
+
if (typeof r.costYuan === "number") c.costYuan = (c.costYuan ?? 0) + r.costYuan;
|
|
17878
|
+
else c.partialPrice = true;
|
|
17879
|
+
}
|
|
17880
|
+
if (c.costYuan === null) c.partialPrice = false;
|
|
17881
|
+
return c;
|
|
17882
|
+
};
|
|
17883
|
+
fmtCost = (c) => {
|
|
17884
|
+
const money = c.costYuan !== null ? `\xA5${c.costYuan.toFixed(4)}` : "\uFF08\u65E0\u4EF7\u6A21\u578B\uFF0C\u4E0D\u8BA1\u94B1\uFF09";
|
|
17885
|
+
const hit = c.promptTokens > 0 ? Math.round(c.cachedTokens / c.promptTokens * 100) : 0;
|
|
17886
|
+
const mins = Math.round(c.durationMs / 6e3) / 10;
|
|
17887
|
+
return `${c.rounds} \u8F6E \xB7 ${money} \xB7 \u7F13\u5B58\u547D\u4E2D ${hit}% \xB7 ${mins}min${c.partialPrice ? "\uFF08\u90E8\u5206\u8BB0\u5F55\u65E0\u4EF7\uFF0C\u94B1\u4E3A\u90E8\u5206\u548C\uFF09" : ""}${c.subRuns > 0 ? ` \xB7 \u5B50 run ${c.subRuns} \u4E2A\u5DF2\u8BA1\u5165` : ""}`;
|
|
17888
|
+
};
|
|
17889
|
+
fmtReceiptLine = (receipt) => {
|
|
17890
|
+
if (!receipt) return "\uFF08\u65E0\u7ED3\u7B97\u5355\u2014\u2014run \u672A\u5230\u6536\u5C3E\u5373\u88AB\u622A\u65AD\uFF0C\u82B1\u8D39\u4EE5\u4E0A\u65B9 usageLog \u805A\u5408\u4E3A\u51C6\uFF09";
|
|
17891
|
+
return `${receipt.rounds} \u8F6E \xB7 ${receipt.costYuan !== null ? `\xA5${receipt.costYuan.toFixed(4)}` : "\u65E0\u4EF7"} \xB7 \u7F13\u5B58\u547D\u4E2D ${Math.round(receipt.cacheHitRate * 100)}% \xB7 ${(receipt.durationMs / 1e3).toFixed(0)}s`;
|
|
17892
|
+
};
|
|
17893
|
+
buildReport = (args) => {
|
|
17894
|
+
const { id, ticket, status, budgetTruncated, cost, receipt, finalText, accept, deniedTools, diff, wt } = args;
|
|
17895
|
+
const budgetNote = budgetTruncated ? "\uFF08\u26A0\uFE0F \u9884\u7B97\u622A\u65AD\u540E\u6536\u5C3E\uFF09" : "";
|
|
17896
|
+
return `---
|
|
17897
|
+
id: ${id}
|
|
17898
|
+
title: ${ticket.title}
|
|
17899
|
+
status: ${status}
|
|
17900
|
+
cost-yuan: ${cost.costYuan !== null ? cost.costYuan.toFixed(4) : "null"}
|
|
17901
|
+
rounds: ${cost.rounds}
|
|
17902
|
+
budget-truncated: ${budgetTruncated}
|
|
17903
|
+
session: batch-${id}
|
|
17904
|
+
worktree: ${wt?.path ?? "\uFF08\u672A\u521B\u5EFA\uFF09"}
|
|
17905
|
+
branch: ${wt?.branch ?? "\uFF08\u672A\u521B\u5EFA\uFF09"}
|
|
17906
|
+
---
|
|
17907
|
+
|
|
17908
|
+
# \u6302\u673A\u4EFB\u52A1\u62A5\u544A\uFF1A${ticket.title}
|
|
17909
|
+
|
|
17910
|
+
- \u72B6\u6001\uFF1A${STATUS_LABEL[status]}${budgetNote}
|
|
17911
|
+
- \u7ED3\u7B97\u5355\uFF1A${fmtCost(cost)}
|
|
17912
|
+
- \u672C\u8F6E receipt\uFF1A${fmtReceiptLine(receipt)}
|
|
17913
|
+
${args.errorMessage ? `- \u5F02\u5E38\uFF1A${args.errorMessage}
|
|
17914
|
+
` : ""}
|
|
17915
|
+
## \u4EFB\u52A1
|
|
17916
|
+
|
|
17917
|
+
${ticket.body}
|
|
17918
|
+
|
|
17919
|
+
## \u6A21\u578B\u6536\u5C3E\u6C47\u62A5
|
|
17920
|
+
|
|
17921
|
+
${finalText.trim() || "\uFF08\u65E0\u8F93\u51FA\u2014\u2014run \u5728\u4EA7\u51FA\u6B63\u6587\u524D\u88AB\u622A\u65AD/\u5F02\u5E38\uFF09"}
|
|
17922
|
+
|
|
17923
|
+
## \u9A8C\u6536
|
|
17924
|
+
${accept ? `
|
|
17925
|
+
\u547D\u4EE4\uFF1A\`${accept.cmd}\` \u2192 exit ${accept.code}${accept.timedOut ? "\uFF08\u23F1\uFE0F \u9A8C\u6536\u8D85\u65F6\u88AB\u6740\uFF09" : ""}
|
|
17926
|
+
|
|
17927
|
+
\u8F93\u51FA\u5C3E\u90E8\uFF1A
|
|
17928
|
+
|
|
17929
|
+
\`\`\`
|
|
17930
|
+
${accept.output}
|
|
17931
|
+
\`\`\`
|
|
17932
|
+
` : "\n\uFF08\u672A\u6267\u884C\u9A8C\u6536\u2014\u2014\u6539\u52A8\u4E0D\u5B8C\u6574\uFF0C\u8DD1\u4E86\u4E5F\u662F\u566A\u58F0\uFF09"}
|
|
17933
|
+
|
|
17934
|
+
## \u88AB\u62D2\u5DE5\u5177\u8C03\u7528\uFF08fail-closed \u8BB0\u5F55\uFF09
|
|
17935
|
+
|
|
17936
|
+
${deniedTools.length === 0 ? "\u65E0\u3002" : deniedTools.map((d) => `- **${d.tool}** \u2014 ${d.detail}`).join("\n")}
|
|
17937
|
+
|
|
17938
|
+
## Diff \u6458\u8981\uFF08worktree \u76F8\u5BF9\u57FA\u5EA7\uFF0C\u672A\u63D0\u4EA4\uFF0C\u5F85\u4EBA\u5DE5\u5904\u7F6E\uFF09
|
|
17939
|
+
|
|
17940
|
+
\u6539\u52A8\u5728\u72EC\u7ACB worktree\uFF08\u5206\u652F \`${wt?.branch ?? "?"}\`\uFF0C\u8DEF\u5F84 ${wt?.path ?? "?"}\uFF09\u3002\u5904\u7F6E\uFF1A\u68C0\u67E5\u6EE1\u610F \u2192 \u5728 worktree \u5185 commit \u5E76\u5408\u56DE\u4E3B\u4ED3\uFF1B\u4E22\u5F03 \u2192 \u5220\u9664\u8BE5 worktree \u76EE\u5F55 + \`git worktree prune\` + \`git branch -D <\u5206\u652F>\`\u3002
|
|
17941
|
+
|
|
17942
|
+
\`\`\`\`\`diff
|
|
17943
|
+
${diff}
|
|
17944
|
+
\`\`\`\`\`
|
|
17945
|
+
`;
|
|
17946
|
+
};
|
|
17947
|
+
runOneTask = async (task) => {
|
|
17948
|
+
const source = await fs49.promises.readFile(task.path, "utf-8");
|
|
17949
|
+
const parsed = parseBatchTicket(source);
|
|
17950
|
+
if (!parsed.ok) {
|
|
17951
|
+
const cost2 = { rounds: 0, mainRounds: 0, subRuns: 0, promptTokens: 0, completionTokens: 0, cachedTokens: 0, costYuan: 0, partialPrice: false, durationMs: 0 };
|
|
17952
|
+
await finishTicket(task.id, `---
|
|
17953
|
+
id: ${task.id}
|
|
17954
|
+
title: ${task.id}
|
|
17955
|
+
status: rejected
|
|
17956
|
+
---
|
|
17957
|
+
|
|
17958
|
+
# \u6302\u673A\u4EFB\u52A1\u88AB\u62D2
|
|
17959
|
+
|
|
17960
|
+
${parsed.error}`);
|
|
17961
|
+
emit2(`\u{1F6AB} [${task.id}] \u5DE5\u5355\u88AB\u62D2\uFF1A${parsed.error}`);
|
|
17962
|
+
return { status: "rejected", cost: cost2, budgetTruncated: false };
|
|
17963
|
+
}
|
|
17964
|
+
const t = parsed.ticket;
|
|
17965
|
+
const sessionId = `batch-${task.id}`;
|
|
17966
|
+
const timeoutMin = t.timeoutMin ?? 30;
|
|
17967
|
+
emit2(`\u25B6 [${task.id}] ${t.title}`);
|
|
17968
|
+
emit2(` \u9884\u7B97 ${t.budgetYuan !== void 0 ? `\xA5${t.budgetYuan}` : "\u4E0D\u9650"} \xB7 \u8D85\u65F6 ${timeoutMin}min \xB7 \u9A8C\u6536 \`${t.accept}\``);
|
|
17969
|
+
const unlocked = new Set(t.tools ?? []);
|
|
17970
|
+
const denySchemas = new Set([...BATCH_DEFAULT_DENYLIST].filter((n) => !unlocked.has(n)));
|
|
17971
|
+
const toolSchemas = agentTools.filter((x) => !denySchemas.has(x?.function?.name));
|
|
17972
|
+
const allowApproval = /* @__PURE__ */ new Set([...BATCH_EDIT_TOOLS, ...unlocked]);
|
|
17973
|
+
const deniedTools = [];
|
|
17974
|
+
let wt = null;
|
|
17975
|
+
try {
|
|
17976
|
+
wt = await createWorktree(sessionId, task.id);
|
|
17977
|
+
} catch (e) {
|
|
17978
|
+
const msg = `\u521B\u5EFA worktree \u5931\u8D25\uFF08\u9700\u8981\u4E3B\u5DE5\u4F5C\u533A\u662F git \u4ED3\u5E93\uFF09\uFF1A${e?.message ?? e}`;
|
|
17979
|
+
const cost2 = await collectSessionCost(sessionId);
|
|
17980
|
+
await finishTicket(task.id, buildReport({
|
|
17981
|
+
id: task.id,
|
|
17982
|
+
ticket: t,
|
|
17983
|
+
status: "error",
|
|
17984
|
+
budgetTruncated: false,
|
|
17985
|
+
cost: cost2,
|
|
17986
|
+
receipt: void 0,
|
|
17987
|
+
finalText: "",
|
|
17988
|
+
accept: null,
|
|
17989
|
+
deniedTools: [],
|
|
17990
|
+
diff: "\uFF08\u65E0\uFF09",
|
|
17991
|
+
wt: null,
|
|
17992
|
+
errorMessage: msg
|
|
17993
|
+
}));
|
|
17994
|
+
emit2(`\u{1F4A5} [${task.id}] ${msg}`);
|
|
17995
|
+
return { status: "error", cost: cost2, budgetTruncated: false };
|
|
17996
|
+
}
|
|
17997
|
+
setSessionWorktree(sessionId, wt);
|
|
17998
|
+
const ac = new AbortController();
|
|
17999
|
+
const timer = setTimeout(() => ac.abort(new Error(`\u4EFB\u52A1\u8D85\u65F6\uFF08${timeoutMin} \u5206\u949F\uFF09`)), timeoutMin * 6e4);
|
|
18000
|
+
let receipt;
|
|
18001
|
+
let finalText = "";
|
|
18002
|
+
let agentError;
|
|
18003
|
+
try {
|
|
18004
|
+
await handleUnifiedChat(
|
|
18005
|
+
{ sessionId, content: t.body },
|
|
18006
|
+
async () => {
|
|
18007
|
+
},
|
|
18008
|
+
(evt) => {
|
|
18009
|
+
if (evt?.type === "text.delta") finalText += evt.text;
|
|
18010
|
+
else if (evt?.type === "text.reset") finalText = "";
|
|
18011
|
+
else if (evt?.type === "final") finalText = evt.text || finalText;
|
|
18012
|
+
else if (evt?.type === "round.start") emit2(` [${ts()}] \u8F6E ${evt.round}`);
|
|
18013
|
+
},
|
|
18014
|
+
ac.signal,
|
|
18015
|
+
{
|
|
18016
|
+
requestApproval: async (detail, meta) => {
|
|
18017
|
+
if (allowApproval.has(meta.toolName)) return "allow-once";
|
|
18018
|
+
deniedTools.push({ tool: meta.toolName, detail: detail.replace(/\n+/g, " ").slice(0, 140) });
|
|
18019
|
+
return "deny";
|
|
18020
|
+
},
|
|
18021
|
+
onUIEvent: (evt) => {
|
|
18022
|
+
if (evt.type === "run.receipt") receipt = evt;
|
|
18023
|
+
},
|
|
18024
|
+
budgetYuan: t.budgetYuan,
|
|
18025
|
+
toolSchemas
|
|
18026
|
+
}
|
|
18027
|
+
);
|
|
18028
|
+
} catch (e) {
|
|
18029
|
+
agentError = e instanceof Error ? e.message : String(e);
|
|
18030
|
+
} finally {
|
|
18031
|
+
clearTimeout(timer);
|
|
18032
|
+
clearSessionWorktree(sessionId);
|
|
18033
|
+
}
|
|
18034
|
+
const timedOut = ac.signal.aborted;
|
|
18035
|
+
const budgetTruncated = receipt?.budgetTruncated === true;
|
|
18036
|
+
let status;
|
|
18037
|
+
let accept = null;
|
|
18038
|
+
if (agentError) {
|
|
18039
|
+
status = "error";
|
|
18040
|
+
emit2(`\u{1F4A5} [${task.id}] agent \u5F02\u5E38\uFF1A${agentError}`);
|
|
18041
|
+
} else if (timedOut) {
|
|
18042
|
+
status = "timeout";
|
|
18043
|
+
emit2(`\u23F1\uFE0F [${task.id}] \u8D85\u65F6\uFF08${timeoutMin}min\uFF09\uFF0C\u622A\u65AD\u6536\u5C3E\uFF08\u9A8C\u6536\u4E0D\u8DD1\uFF09`);
|
|
18044
|
+
} else {
|
|
18045
|
+
const r = await runAcceptCommand(t.accept, wt.path);
|
|
18046
|
+
accept = { cmd: t.accept, code: r.code, output: r.output, timedOut: r.timedOut };
|
|
18047
|
+
status = r.code === 0 && !r.timedOut ? "passed" : "accept-failed";
|
|
18048
|
+
emit2(`${status === "passed" ? "\u2705" : "\u274C"} [${task.id}] \u9A8C\u6536 exit ${r.code}${r.timedOut ? "\uFF08\u8D85\u65F6\u88AB\u6740\uFF09" : ""}`);
|
|
18049
|
+
}
|
|
18050
|
+
await killBackgroundTasksUnder(wt.path).catch(() => {
|
|
18051
|
+
});
|
|
18052
|
+
const diff = await harvestDiff(wt);
|
|
18053
|
+
const cost = await collectSessionCost(sessionId);
|
|
18054
|
+
await finishTicket(task.id, buildReport({
|
|
18055
|
+
id: task.id,
|
|
18056
|
+
ticket: t,
|
|
18057
|
+
status,
|
|
18058
|
+
budgetTruncated,
|
|
18059
|
+
cost,
|
|
18060
|
+
receipt,
|
|
18061
|
+
finalText,
|
|
18062
|
+
accept,
|
|
18063
|
+
deniedTools,
|
|
18064
|
+
diff,
|
|
18065
|
+
wt,
|
|
18066
|
+
errorMessage: agentError
|
|
18067
|
+
}));
|
|
18068
|
+
emit2(` ${STATUS_LABEL[status]} \xB7 ${fmtCost(cost)}`);
|
|
18069
|
+
emit2(` \u4EA7\u7269\uFF1A${wt.path}\uFF08\u5206\u652F ${wt.branch}\uFF0C\u4FDD\u7559\u5F85\u4EBA\u5DE5\u5904\u7F6E\uFF09`);
|
|
18070
|
+
return { status, cost, budgetTruncated };
|
|
18071
|
+
};
|
|
18072
|
+
parseWaitWindow = (s) => {
|
|
18073
|
+
if (!s) return null;
|
|
18074
|
+
const m = /^(\d{1,2}):(\d{2})-(\d{1,2}):(\d{2})$/.exec(s.trim());
|
|
18075
|
+
if (!m) return null;
|
|
18076
|
+
const startMin = parseInt(m[1], 10) * 60 + parseInt(m[2], 10);
|
|
18077
|
+
const endMin = parseInt(m[3], 10) * 60 + parseInt(m[4], 10);
|
|
18078
|
+
if (startMin === endMin) return null;
|
|
18079
|
+
return { startMin, endMin };
|
|
18080
|
+
};
|
|
18081
|
+
nowMinutes = () => {
|
|
18082
|
+
const d = /* @__PURE__ */ new Date();
|
|
18083
|
+
return d.getHours() * 60 + d.getMinutes();
|
|
18084
|
+
};
|
|
18085
|
+
sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
18086
|
+
waitUntilWindow = async (w) => {
|
|
18087
|
+
const now = nowMinutes();
|
|
18088
|
+
let waitMin = 0;
|
|
18089
|
+
if (now >= w.startMin && now < w.endMin) {
|
|
18090
|
+
emit2(`\u23F0 \u5F53\u524D ${Math.floor(now / 60)}:${String(now % 60).padStart(2, "0")} \u5DF2\u5728\u7A97\u53E3\u5185\uFF0C\u7ACB\u5373\u5F00\u8DD1\u3002`);
|
|
18091
|
+
return;
|
|
18092
|
+
}
|
|
18093
|
+
waitMin = now < w.startMin ? w.startMin - now : 24 * 60 - now + w.startMin;
|
|
18094
|
+
emit2(`\u23F0 --wait-window\uFF1A${Math.floor(waitMin / 60)} \u5C0F\u65F6 ${waitMin % 60} \u5206\u540E\uFF08\u7A97\u53E3\u8D77\u70B9\uFF09\u5F00\u8DD1\u3002\u6302\u673A\u7B49\u5F85\u4E2D\uFF0CCtrl+C \u53EF\u53D6\u6D88\u3002`);
|
|
18095
|
+
while (waitMin > 0) {
|
|
18096
|
+
const chunkMin = Math.min(waitMin, 30);
|
|
18097
|
+
await sleep(chunkMin * 6e4);
|
|
18098
|
+
waitMin -= chunkMin;
|
|
18099
|
+
}
|
|
18100
|
+
};
|
|
18101
|
+
runBatchQueue = async (opts) => {
|
|
18102
|
+
const window = parseWaitWindow(opts?.waitWindow);
|
|
18103
|
+
if (opts?.waitWindow && !window) {
|
|
18104
|
+
emit2(`\u274C --wait-window \u683C\u5F0F\u975E\u6CD5\uFF1A"${opts.waitWindow}"\uFF08\u5E94\u4E3A HH:MM-HH:MM\uFF0C\u5982 23:30-06:30\uFF09`);
|
|
18105
|
+
process.exitCode = 2;
|
|
18106
|
+
return;
|
|
18107
|
+
}
|
|
18108
|
+
if (window) await waitUntilWindow(window);
|
|
18109
|
+
const lock = await acquireRunLock();
|
|
18110
|
+
if (!lock.ok) {
|
|
18111
|
+
emit2(`\u{1F6AB} ${lock.error}`);
|
|
18112
|
+
process.exitCode = 1;
|
|
18113
|
+
return;
|
|
18114
|
+
}
|
|
18115
|
+
const startedAt = Date.now();
|
|
18116
|
+
let total = 0;
|
|
18117
|
+
let passed = 0;
|
|
18118
|
+
let costSum = 0;
|
|
18119
|
+
let costTasks = 0;
|
|
18120
|
+
const failedIds = [];
|
|
18121
|
+
try {
|
|
18122
|
+
for (; ; ) {
|
|
18123
|
+
const task = await takeNextTicket();
|
|
18124
|
+
if (!task) break;
|
|
18125
|
+
total++;
|
|
18126
|
+
const r = await runOneTask(task);
|
|
18127
|
+
if (r.status === "passed") passed++;
|
|
18128
|
+
else failedIds.push(`[${task.id}] ${STATUS_LABEL[r.status]}`);
|
|
18129
|
+
if (r.cost.costYuan !== null) {
|
|
18130
|
+
costSum += r.cost.costYuan;
|
|
18131
|
+
costTasks++;
|
|
18132
|
+
}
|
|
18133
|
+
}
|
|
18134
|
+
} finally {
|
|
18135
|
+
await releaseRunLock();
|
|
18136
|
+
}
|
|
18137
|
+
if (total === 0) {
|
|
18138
|
+
emit2("\u961F\u5217\u7A7A\uFF1Apending/ \u65E0\u4EFB\u52A1\u3002\u6295\u9012\uFF1Adeepseeker-code batch add <\u5DE5\u5355.md>");
|
|
18139
|
+
return;
|
|
18140
|
+
}
|
|
18141
|
+
emit2("");
|
|
18142
|
+
emit2("\u2501".repeat(56));
|
|
18143
|
+
emit2(`\u{1F319} \u6302\u673A\u7ED3\u675F\uFF1A${total} \u4EFB\u52A1 \xB7 ${passed} \u8FC7 \xB7 ${total - passed} \u672A\u8FC7\uFF08\u8017\u65F6 ${Math.round((Date.now() - startedAt) / 6e3) / 10}min\uFF09`);
|
|
18144
|
+
emit2(`\u{1F4B0} \u603B\u82B1\u8D39\uFF1A${costTasks > 0 ? `\xA5${costSum.toFixed(4)}\uFF08${costTasks} \u4E2A\u4EFB\u52A1\u8BA1\u4EF7\uFF09` : "\u5168\u90E8\u65E0\u4EF7\u6A21\u578B\uFF0C\u672A\u8BA1\u94B1"}`);
|
|
18145
|
+
if (failedIds.length > 0) emit2(`\u26A0\uFE0F \u672A\u8FC7\u6E05\u5355\uFF1A
|
|
18146
|
+
${failedIds.join("\n ")}`);
|
|
18147
|
+
emit2("\u62A5\u544A\u4E0E\u6539\u52A8\uFF1A.deepseeker-code/batch/done/\uFF08worktree \u5747\u4FDD\u7559\u5F85\u4EBA\u5DE5\u5904\u7F6E\uFF09");
|
|
18148
|
+
};
|
|
18149
|
+
}
|
|
18150
|
+
});
|
|
18151
|
+
|
|
17256
18152
|
// src/preload-config.ts
|
|
17257
18153
|
import { readFileSync } from "node:fs";
|
|
17258
18154
|
import path from "node:path";
|
|
@@ -17304,7 +18200,7 @@ init_updateCheck();
|
|
|
17304
18200
|
init_trust();
|
|
17305
18201
|
import { render } from "ink";
|
|
17306
18202
|
import os5 from "os";
|
|
17307
|
-
import
|
|
18203
|
+
import path49 from "path";
|
|
17308
18204
|
import { emitKeypressEvents } from "node:readline";
|
|
17309
18205
|
import { jsx as jsx19 } from "react/jsx-runtime";
|
|
17310
18206
|
var parseArgs = (argv) => {
|
|
@@ -17383,6 +18279,12 @@ var main = async () => {
|
|
|
17383
18279
|
`);
|
|
17384
18280
|
process.exit(0);
|
|
17385
18281
|
}
|
|
18282
|
+
const { parseBatchArgv: parseBatchArgv2 } = await Promise.resolve().then(() => (init_batchAdmin(), batchAdmin_exports));
|
|
18283
|
+
const batchArgv = parseBatchArgv2(process.argv.slice(2));
|
|
18284
|
+
if (batchArgv && batchArgv.sub !== "run") {
|
|
18285
|
+
await Promise.resolve().then(() => (init_batchAdmin(), batchAdmin_exports)).then((m) => m.handleBatchAdmin(batchArgv));
|
|
18286
|
+
process.exit(0);
|
|
18287
|
+
}
|
|
17386
18288
|
if (!process.env.DEEP_SEEK_API_KEY) {
|
|
17387
18289
|
console.error(S.noApiKey("DEEP_SEEK_API_KEY"));
|
|
17388
18290
|
process.exit(1);
|
|
@@ -17422,6 +18324,16 @@ var main = async () => {
|
|
|
17422
18324
|
Promise.resolve().then(() => (init_App(), App_exports)),
|
|
17423
18325
|
Promise.resolve().then(() => (init_config(), config_exports))
|
|
17424
18326
|
]);
|
|
18327
|
+
if (batchArgv?.sub === "run") {
|
|
18328
|
+
const dispose = await initEngine2(agentTools2, { includeProject });
|
|
18329
|
+
const { runBatchQueue: runBatchQueue2 } = await Promise.resolve().then(() => (init_batchRunner(), batchRunner_exports));
|
|
18330
|
+
try {
|
|
18331
|
+
await runBatchQueue2({ waitWindow: batchArgv.waitWindow });
|
|
18332
|
+
} finally {
|
|
18333
|
+
dispose();
|
|
18334
|
+
}
|
|
18335
|
+
process.exit(0);
|
|
18336
|
+
}
|
|
17425
18337
|
const engineReady = initEngine2(agentTools2, { includeProject });
|
|
17426
18338
|
const onExit = () => {
|
|
17427
18339
|
void engineReady.then((dispose) => dispose());
|
|
@@ -17437,7 +18349,7 @@ var main = async () => {
|
|
|
17437
18349
|
process.stdout.write("\x1B[2J\x1B[3J\x1B[1;1H");
|
|
17438
18350
|
const cwdIsHome = () => {
|
|
17439
18351
|
try {
|
|
17440
|
-
return
|
|
18352
|
+
return path49.resolve(cwd).toLowerCase() === path49.resolve(os5.homedir()).toLowerCase();
|
|
17441
18353
|
} catch {
|
|
17442
18354
|
return false;
|
|
17443
18355
|
}
|