deepseeker-code 1.0.55 → 1.0.56
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.mjs +560 -196
- package/package.json +1 -1
package/dist/cli.mjs
CHANGED
|
@@ -225,6 +225,33 @@ ${cwd}
|
|
|
225
225
|
DeepSeeker-Code \u5C06\u5728\u6B64\u76EE\u5F55\u8BFB\u53D6\u3001\u7F16\u8F91\u548C\u6267\u884C\u6587\u4EF6\u3002`,
|
|
226
226
|
optTrust: "\u4FE1\u4EFB\u6B64\u76EE\u5F55",
|
|
227
227
|
optExit: "\u9000\u51FA",
|
|
228
|
+
trustEmpty: "\u5DF2\u4FE1\u4EFB\u76EE\u5F55\uFF1A\uFF08\u65E0\uFF09\u3002\u9996\u6B21\u8FDB\u5165\u67D0\u76EE\u5F55\u65F6\u4F1A\u8BE2\u95EE\u662F\u5426\u4FE1\u4EFB\u3002",
|
|
229
|
+
trustList: (list) => `\u5DF2\u4FE1\u4EFB\u76EE\u5F55\uFF08\u64A4\u9500\u7528 /trust <\u5E8F\u53F7 \u6216 \u8DEF\u5F84>\uFF09\uFF1A
|
|
230
|
+
${list}
|
|
231
|
+
|
|
232
|
+
\u64A4\u9500\u540E\u9700\u91CD\u542F CLI \u751F\u6548\uFF08\u9879\u76EE\u7EA7\u914D\u7F6E\u4EC5\u5728\u542F\u52A8\u65F6\u52A0\u8F7D\uFF09\u3002`,
|
|
233
|
+
trustRemoved: (target) => `\u5DF2\u64A4\u9500\u4FE1\u4EFB\uFF1A${target}
|
|
234
|
+
\uFF08\u91CD\u542F CLI \u540E\u751F\u6548\u2014\u2014\u9879\u76EE\u7EA7\u914D\u7F6E\u4EC5\u5728\u542F\u52A8\u65F6\u52A0\u8F7D\uFF09`,
|
|
235
|
+
trustNotFound: (target) => `\u672A\u627E\u5230\u8BE5\u4FE1\u4EFB\u76EE\u5F55\uFF1A${target}`,
|
|
236
|
+
archiveSummary: (s) => `\u{1F4DC} \u6700\u8FD1\u4E00\u6B21\u538B\u7F29\u7684\u5F52\u6863\u6458\u8981\uFF1A
|
|
237
|
+
${s}`,
|
|
238
|
+
archiveNone: "\u672C\u4F1A\u8BDD\u542F\u52A8\u4EE5\u6765\u5C1A\u672A\u53D1\u751F\u8FC7\u538B\u7F29\uFF08\u6458\u8981\u4EC5\u4FDD\u7559\u8FD0\u884C\u65F6\u6700\u8FD1\u4E00\u6B21\uFF09\u3002",
|
|
239
|
+
planModeSet: (on) => `\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"}`,
|
|
240
|
+
budgetView: (budget, last) => `\u{1F4B0} \u9884\u7B97\uFF1A${budget != null ? `\xA5${budget}/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"}`,
|
|
241
|
+
budgetOff: "\u{1F4B0} \u9884\u7B97\u5DF2\u5173\u95ED\uFF08\u4E0D\u9650\u82B1\u8D39\uFF09\u3002",
|
|
242
|
+
budgetUsage: "\u7528\u6CD5\uFF1A/budget 0.5\uFF08\u5143/run\uFF09\xB7 /budget off \xB7 /budget \u67E5\u770B",
|
|
243
|
+
budgetSet: (n) => `\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`,
|
|
244
|
+
autoModeSet: (on) => `\u81EA\u52A8\u6A21\u5F0F\uFF1A${on ? "\u5F00\uFF08\u5DE5\u4F5C\u533A\u5185\u6587\u4EF6\u7F16\u8F91\u7531\u5206\u7C7B\u5668\u81EA\u52A8\u653E\u884C\uFF0C\u9AD8\u5371\u8F6C\u4EBA\u5DE5\uFF09" : "\u5173"}`,
|
|
245
|
+
thinkingInvalid: (arg) => `\u65E0\u6548\u7B49\u7EA7\uFF1A${arg}\uFF08\u53EF\u9009\uFF1Aoff \u5173\u95ED / high \u5E38\u89C4 / max \u6DF1\u5EA6\uFF09`,
|
|
246
|
+
thinkingCurrent: (level) => `\u5F53\u524D\u601D\u8003\u7B49\u7EA7\uFF1A${level}\uFF08off \u5173\u95ED / high \u5E38\u89C4 / max \u6DF1\u5EA6\uFF09`,
|
|
247
|
+
thinkingSet: (lvl) => `\u601D\u8003\u7B49\u7EA7\uFF1A${lvl}${lvl === "off" ? "\uFF08\u5173\u95ED\uFF0C\u7B80\u5355\u4EFB\u52A1\u66F4\u5FEB\u66F4\u7701\uFF09" : lvl === "max" ? "\uFF08\u6DF1\u5EA6\uFF0C\u590D\u6742\u4EFB\u52A1\uFF09" : "\uFF08\u5E38\u89C4\uFF09"}`,
|
|
248
|
+
engineLoading: "\u23F3 \u5F15\u64CE\u52A0\u8F7D\u4E2D\uFF08MCP/skills/commands\uFF09\u2026",
|
|
249
|
+
unknownCmd: (name) => `\u672A\u77E5\u547D\u4EE4\uFF1A/${name || "(\u7A7A)"}\uFF08\u8F93\u5165 / \u67E5\u770B\u53EF\u7528\u547D\u4EE4\uFF09`,
|
|
250
|
+
bangUsage: "\u7528\u6CD5\uFF1A!<shell \u547D\u4EE4>\uFF08\u5982 !git status\uFF09\uFF1B\u8F93\u51FA\u4F1A\u5E26\u5165\u4E0B\u8F6E\u5BF9\u8BDD\u4E0A\u4E0B\u6587\u3002",
|
|
251
|
+
bangHead: (timedOut, ok, exitCode) => timedOut ? "\u23F1 \u8D85\u65F6\u4E2D\u6B62" : ok ? "\u2705 \u9000\u51FA\u7801 0" : exitCode != null ? `\u274C \u9000\u51FA\u7801 ${exitCode}` : "\u274C \u5DF2\u4E2D\u6B62",
|
|
252
|
+
bangNoOutput: "(\u65E0\u8F93\u51FA)",
|
|
253
|
+
visionDowngraded: (model) => `\u{1F5BC} \u6A21\u578B ${model} \u4E0D\u652F\u6301\u56FE\u7247\uFF0C\u5DF2\u81EA\u52A8\u964D\u7EA7\u4E3A\u6587\u672C\u5904\u7406\uFF08\u5DF2\u8BB0\u4F4F\uFF0C\u540E\u7EED\u6D88\u606F\u76F4\u63A5\u6309\u6587\u672C\u53D1\u9001\uFF09`,
|
|
254
|
+
planEnterSwitched: (reason) => `\u{1F4CB} \u6A21\u578B\u8BF7\u6C42\u8FDB\u5165\u8BA1\u5212\u6A21\u5F0F${reason ? `\uFF1A${reason}` : ""}\uFF0C\u5DF2\u5207\u6362\u2026`,
|
|
228
255
|
helpText: (model, thinking, locale2) => [
|
|
229
256
|
"/help \xB7 /status \xB7 /clear \xB7 /exit",
|
|
230
257
|
"/plan \u2014 \u5207\u6362\u8BA1\u5212\u6A21\u5F0F\uFF08\u53EA\u8BFB\u8C03\u7814 \u2192 \u65B9\u6848\u5BA1\u6279 \u2192 \u5B9E\u73B0\uFF09",
|
|
@@ -380,6 +407,33 @@ ${cwd}
|
|
|
380
407
|
DeepSeeker-Code will read, edit, and execute files here.`,
|
|
381
408
|
optTrust: "Yes, I trust this folder",
|
|
382
409
|
optExit: "No, exit",
|
|
410
|
+
trustEmpty: "Trusted dirs: (none). You'll be asked on first entry to a directory.",
|
|
411
|
+
trustList: (list) => `Trusted dirs (revoke with /trust <index or path>):
|
|
412
|
+
${list}
|
|
413
|
+
|
|
414
|
+
Revocation takes effect after a CLI restart (project config loads at startup only).`,
|
|
415
|
+
trustRemoved: (target) => `Trust revoked: ${target}
|
|
416
|
+
(takes effect after a CLI restart \u2014 project config loads at startup only)`,
|
|
417
|
+
trustNotFound: (target) => `No such trusted dir: ${target}`,
|
|
418
|
+
archiveSummary: (s) => `\u{1F4DC} Latest compaction summary:
|
|
419
|
+
${s}`,
|
|
420
|
+
archiveNone: "No compaction has happened since this session started (only the latest runtime summary is kept).",
|
|
421
|
+
planModeSet: (on) => `Plan mode: ${on ? "on (next question starts read-only research, plan review, then implementation)" : "off"}`,
|
|
422
|
+
budgetView: (budget, last) => `\u{1F4B0} Budget: ${budget != null ? `\xA5${budget}/run` : "not set (/budget 0.5 to cap per-run cost)"}${last != null ? ` \xB7 last run cost \xA5${last.toFixed(3)}` : " \xB7 no completed run yet"}`,
|
|
423
|
+
budgetOff: "\u{1F4B0} Budget disabled (no cap).",
|
|
424
|
+
budgetUsage: "Usage: /budget 0.5 (\xA5/run) \xB7 /budget off \xB7 /budget to view",
|
|
425
|
+
budgetSet: (n) => `\u{1F4B0} Budget set: \xA5${n} per run (soft nudge on breach, hard truncation at 120%).`,
|
|
426
|
+
autoModeSet: (on) => `Auto mode: ${on ? "on (in-workspace file edits auto-approved by classifier, risky ops to human)" : "off"}`,
|
|
427
|
+
thinkingInvalid: (arg) => `Invalid level: ${arg} (choose: off / high / max)`,
|
|
428
|
+
thinkingCurrent: (level) => `Current thinking level: ${level} (off / high / max)`,
|
|
429
|
+
thinkingSet: (lvl) => `Thinking level: ${lvl}${lvl === "off" ? " (off \u2014 faster and cheaper for simple tasks)" : lvl === "max" ? " (deep, for complex tasks)" : " (standard)"}`,
|
|
430
|
+
engineLoading: "\u23F3 Loading engine (MCP/skills/commands)\u2026",
|
|
431
|
+
unknownCmd: (name) => `Unknown command: /${name || "(empty)"} (type / to list commands)`,
|
|
432
|
+
bangUsage: "Usage: !<shell command> (e.g. !git status); output joins the next turn's context.",
|
|
433
|
+
bangHead: (timedOut, ok, exitCode) => timedOut ? "\u23F1 timed out" : ok ? "\u2705 exit code 0" : exitCode != null ? `\u274C exit code ${exitCode}` : "\u274C aborted",
|
|
434
|
+
bangNoOutput: "(no output)",
|
|
435
|
+
visionDowngraded: (model) => `\u{1F5BC} Model ${model} doesn't support images; downgraded to text this turn (remembered \u2014 future messages send as text)`,
|
|
436
|
+
planEnterSwitched: (reason) => `\u{1F4CB} Model requested plan mode${reason ? `: ${reason}` : ""}; switched\u2026`,
|
|
383
437
|
helpText: (model, thinking, locale2) => [
|
|
384
438
|
"/help \xB7 /status \xB7 /clear \xB7 /exit",
|
|
385
439
|
"/plan \u2014 Toggle plan mode (read-only research \u2192 review \u2192 implement)",
|
|
@@ -796,10 +850,33 @@ var init_trust = __esm({
|
|
|
796
850
|
|
|
797
851
|
// ../core/src/batch/ticket.ts
|
|
798
852
|
import fs4 from "fs/promises";
|
|
799
|
-
var generateBatchId, parseToolsValue, parsePositiveNumber, parseBatchTicket, readBatchTicket;
|
|
853
|
+
var TICKET_MSG, ticketMsg, generateBatchId, parseToolsValue, parsePositiveNumber, parseBatchTicket, readBatchTicket;
|
|
800
854
|
var init_ticket = __esm({
|
|
801
855
|
"../core/src/batch/ticket.ts"() {
|
|
802
856
|
"use strict";
|
|
857
|
+
TICKET_MSG = {
|
|
858
|
+
zh: {
|
|
859
|
+
noFrontmatter: "\u7F3A\u5C11 frontmatter\uFF08--- \u5305\u88F9\u7684\u5934\u90E8\u5757\uFF09\u3002\u5DE5\u5355\u683C\u5F0F\u89C1 batch add \u5E2E\u52A9\u3002",
|
|
860
|
+
noAccept: "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",
|
|
861
|
+
badBudget: (v) => `budget-yuan \u975E\u6CD5\uFF08"${v}"\uFF09\uFF1A\u987B\u4E3A\u6B63\u6570\uFF08\u5143\uFF09\u3002`,
|
|
862
|
+
badTimeout: (v) => `timeout-min \u975E\u6CD5\uFF08"${v}"\uFF09\uFF1A\u987B\u4E3A\u6B63\u6574\u6570\uFF08\u5206\u949F\uFF09\u3002`,
|
|
863
|
+
badTools: "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",
|
|
864
|
+
emptyBody: "\u4EFB\u52A1\u6B63\u6587\u4E3A\u7A7A\uFF1Afrontmatter \u4E4B\u540E\u5E94\u5199\u4EFB\u52A1\u63CF\u8FF0\u3002",
|
|
865
|
+
untitled: "(\u672A\u547D\u540D\u4EFB\u52A1)",
|
|
866
|
+
readFail: (e) => `\u8BFB\u5DE5\u5355\u5931\u8D25\uFF1A${e}`
|
|
867
|
+
},
|
|
868
|
+
en: {
|
|
869
|
+
noFrontmatter: "Missing frontmatter (a --- delimited header block). See `batch add` help for the ticket format.",
|
|
870
|
+
noAccept: "Frontmatter is missing `accept` (acceptance command). Batch tasks must carry an executable acceptance check \u2014 rejected without one.",
|
|
871
|
+
badBudget: (v) => `Invalid budget-yuan ("${v}"): must be a positive number (yuan).`,
|
|
872
|
+
badTimeout: (v) => `Invalid timeout-min ("${v}"): must be a positive integer (minutes).`,
|
|
873
|
+
badTools: "Empty tools: either remove the line (use the default denylist) or list tool names (comma-separated).",
|
|
874
|
+
emptyBody: "Empty task body: write the task description after the frontmatter.",
|
|
875
|
+
untitled: "(untitled task)",
|
|
876
|
+
readFail: (e) => `Failed to read ticket: ${e}`
|
|
877
|
+
}
|
|
878
|
+
};
|
|
879
|
+
ticketMsg = (locale2, key) => (TICKET_MSG[locale2] ?? TICKET_MSG.zh)[key] ?? TICKET_MSG.zh[key] ?? key;
|
|
803
880
|
generateBatchId = (now = /* @__PURE__ */ new Date()) => {
|
|
804
881
|
const p = (n, w = 2) => String(n).padStart(w, "0");
|
|
805
882
|
const rand = Math.random().toString(36).slice(2, 6);
|
|
@@ -810,9 +887,9 @@ var init_ticket = __esm({
|
|
|
810
887
|
const n = Number(raw.trim());
|
|
811
888
|
return Number.isFinite(n) && n > 0 ? n : null;
|
|
812
889
|
};
|
|
813
|
-
parseBatchTicket = (source) => {
|
|
890
|
+
parseBatchTicket = (source, locale2 = "zh") => {
|
|
814
891
|
const m = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?([\s\S]*)$/.exec(source);
|
|
815
|
-
if (!m) return { ok: false, error:
|
|
892
|
+
if (!m) return { ok: false, error: ticketMsg(locale2, "noFrontmatter") };
|
|
816
893
|
const [, fmRaw, bodyRaw] = m;
|
|
817
894
|
const fm = {};
|
|
818
895
|
for (const line of fmRaw.split(/\r?\n/)) {
|
|
@@ -821,34 +898,34 @@ var init_ticket = __esm({
|
|
|
821
898
|
fm[kv[1].toLowerCase()] = kv[2].trim();
|
|
822
899
|
}
|
|
823
900
|
const accept = (fm["accept"] ?? "").trim();
|
|
824
|
-
if (!accept) return { ok: false, error:
|
|
901
|
+
if (!accept) return { ok: false, error: ticketMsg(locale2, "noAccept") };
|
|
825
902
|
let budgetYuan;
|
|
826
903
|
if (fm["budget-yuan"] !== void 0) {
|
|
827
904
|
const n = parsePositiveNumber(fm["budget-yuan"]);
|
|
828
|
-
if (n === null) return { ok: false, error:
|
|
905
|
+
if (n === null) return { ok: false, error: ticketMsg(locale2, "badBudget")(fm["budget-yuan"]) };
|
|
829
906
|
budgetYuan = n;
|
|
830
907
|
}
|
|
831
908
|
let timeoutMin;
|
|
832
909
|
if (fm["timeout-min"] !== void 0) {
|
|
833
910
|
const n = parsePositiveNumber(fm["timeout-min"]);
|
|
834
|
-
if (n === null) return { ok: false, error:
|
|
911
|
+
if (n === null) return { ok: false, error: ticketMsg(locale2, "badTimeout")(fm["timeout-min"]) };
|
|
835
912
|
timeoutMin = n;
|
|
836
913
|
}
|
|
837
914
|
const tools = fm["tools"] !== void 0 ? parseToolsValue(fm["tools"]) : void 0;
|
|
838
|
-
if (tools && tools.length === 0) return { ok: false, error:
|
|
915
|
+
if (tools && tools.length === 0) return { ok: false, error: ticketMsg(locale2, "badTools") };
|
|
839
916
|
const body = bodyRaw.trim();
|
|
840
|
-
if (!body) return { ok: false, error:
|
|
841
|
-
const title = (fm["title"] ?? "").trim() || body.split(/\r?\n/).find((l) => l.trim())?.slice(0, 40) || "
|
|
917
|
+
if (!body) return { ok: false, error: ticketMsg(locale2, "emptyBody") };
|
|
918
|
+
const title = (fm["title"] ?? "").trim() || body.split(/\r?\n/).find((l) => l.trim())?.slice(0, 40) || ticketMsg(locale2, "untitled");
|
|
842
919
|
return { ok: true, ticket: { title, accept, budgetYuan, timeoutMin, tools: tools && tools.length > 0 ? tools : void 0, body } };
|
|
843
920
|
};
|
|
844
|
-
readBatchTicket = async (filePath) => {
|
|
921
|
+
readBatchTicket = async (filePath, locale2 = "zh") => {
|
|
845
922
|
let source;
|
|
846
923
|
try {
|
|
847
924
|
source = await fs4.readFile(filePath, "utf-8");
|
|
848
925
|
} catch (e) {
|
|
849
|
-
return { ok: false, error:
|
|
926
|
+
return { ok: false, error: ticketMsg(locale2, "readFail")(e?.message ?? e) };
|
|
850
927
|
}
|
|
851
|
-
return parseBatchTicket(source);
|
|
928
|
+
return parseBatchTicket(source, locale2);
|
|
852
929
|
};
|
|
853
930
|
}
|
|
854
931
|
});
|
|
@@ -856,11 +933,21 @@ var init_ticket = __esm({
|
|
|
856
933
|
// ../core/src/batch/queue.ts
|
|
857
934
|
import fs5 from "fs/promises";
|
|
858
935
|
import path6 from "path";
|
|
859
|
-
var batchQueueRoot, stateDir, lockPath, listState, snapshotQueue, reportPath, enqueueTicketFile, takeNextTicket, requeueStaleRunning, finishTicket, cleanDone, pidAlive, acquireRunLock, releaseRunLock;
|
|
936
|
+
var LOCK_MSG, batchQueueRoot, stateDir, lockPath, listState, snapshotQueue, reportPath, enqueueTicketFile, takeNextTicket, requeueStaleRunning, finishTicket, cleanDone, pidAlive, acquireRunLock, releaseRunLock;
|
|
860
937
|
var init_queue = __esm({
|
|
861
938
|
"../core/src/batch/queue.ts"() {
|
|
862
939
|
"use strict";
|
|
863
940
|
init_ticket();
|
|
941
|
+
LOCK_MSG = {
|
|
942
|
+
zh: {
|
|
943
|
+
createFail: (e) => `\u9501\u521B\u5EFA\u5931\u8D25\uFF1A${e}`,
|
|
944
|
+
held: (pid) => `\u5DF2\u6709 batch runner \u5728\u8FD0\u884C\uFF08pid ${pid}\uFF09\u3002\u6302\u673A\u6A21\u5F0F\u4E32\u884C\uFF0C\u52FF\u5E76\u53D1\u8DD1\u4E24\u4E2A runner\u3002`
|
|
945
|
+
},
|
|
946
|
+
en: {
|
|
947
|
+
createFail: (e) => `Failed to create the lock file: ${e}`,
|
|
948
|
+
held: (pid) => `Another batch runner is already running (pid ${pid}). Batch mode is serial \u2014 don't run two runners at once.`
|
|
949
|
+
}
|
|
950
|
+
};
|
|
864
951
|
batchQueueRoot = () => process.env.DEEPSEEKER_CODE_BATCH_DIR || path6.join(process.cwd(), ".deepseeker-code", "batch");
|
|
865
952
|
stateDir = (s) => path6.join(batchQueueRoot(), s);
|
|
866
953
|
lockPath = () => path6.join(batchQueueRoot(), ".lock");
|
|
@@ -877,8 +964,8 @@ var init_queue = __esm({
|
|
|
877
964
|
done: (await listState("done")).map((f) => f.replace(/\.md$/, ""))
|
|
878
965
|
});
|
|
879
966
|
reportPath = (id) => path6.join(stateDir("done"), `${id}.report.md`);
|
|
880
|
-
enqueueTicketFile = async (srcPath) => {
|
|
881
|
-
const parsed = await readBatchTicket(srcPath);
|
|
967
|
+
enqueueTicketFile = async (srcPath, locale2 = "zh") => {
|
|
968
|
+
const parsed = await readBatchTicket(srcPath, locale2);
|
|
882
969
|
if (!parsed.ok) return parsed;
|
|
883
970
|
const source = await fs5.readFile(srcPath, "utf-8");
|
|
884
971
|
const id = generateBatchId();
|
|
@@ -935,18 +1022,18 @@ var init_queue = __esm({
|
|
|
935
1022
|
return e?.code === "EPERM";
|
|
936
1023
|
}
|
|
937
1024
|
};
|
|
938
|
-
acquireRunLock = async () => {
|
|
1025
|
+
acquireRunLock = async (locale2 = "zh") => {
|
|
939
1026
|
await fs5.mkdir(batchQueueRoot(), { recursive: true });
|
|
940
1027
|
const payload = `${process.pid} ${(/* @__PURE__ */ new Date()).toISOString()}`;
|
|
941
1028
|
try {
|
|
942
1029
|
await fs5.writeFile(lockPath(), payload, { flag: "wx" });
|
|
943
1030
|
return { ok: true };
|
|
944
1031
|
} catch (e) {
|
|
945
|
-
if (e?.code !== "EEXIST") return { ok: false, error:
|
|
1032
|
+
if (e?.code !== "EEXIST") return { ok: false, error: LOCK_MSG[locale2].createFail(e?.message ?? e) };
|
|
946
1033
|
const raw = await fs5.readFile(lockPath(), "utf-8").catch(() => "");
|
|
947
1034
|
const ownerPid = parseInt(raw.split(" ")[0], 10);
|
|
948
1035
|
if (Number.isFinite(ownerPid) && pidAlive(ownerPid)) {
|
|
949
|
-
return { ok: false, error:
|
|
1036
|
+
return { ok: false, error: LOCK_MSG[locale2].held(ownerPid) };
|
|
950
1037
|
}
|
|
951
1038
|
await fs5.writeFile(lockPath(), payload).catch(() => {
|
|
952
1039
|
});
|
|
@@ -963,6 +1050,211 @@ var init_queue = __esm({
|
|
|
963
1050
|
}
|
|
964
1051
|
});
|
|
965
1052
|
|
|
1053
|
+
// src/batchStrings.ts
|
|
1054
|
+
var ZH, EN, DICT, batchT;
|
|
1055
|
+
var init_batchStrings = __esm({
|
|
1056
|
+
"src/batchStrings.ts"() {
|
|
1057
|
+
"use strict";
|
|
1058
|
+
ZH = {
|
|
1059
|
+
// —— batchAdmin(add / list / clean / help) ——
|
|
1060
|
+
usage: `deepseeker-code batch \u2014\u2014 \u6302\u673A\u6279\u5904\u7406\uFF08\u6210\u672C\u4FE1\u4EFB\u94FE\u7B2C\u56DB\u73AF\uFF09
|
|
1061
|
+
|
|
1062
|
+
\u7528\u6CD5\uFF1Adeepseeker-code batch <\u5B50\u547D\u4EE4>
|
|
1063
|
+
add <\u5DE5\u5355.md> [...] \u6295\u9012\u4EFB\u52A1\uFF08\u53EF\u4E00\u6B21\u591A\u4E2A\u6587\u4EF6\uFF09
|
|
1064
|
+
list \u67E5\u770B pending / running / done \u4E09\u6001\u961F\u5217
|
|
1065
|
+
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
|
|
1066
|
+
clean \u6E05\u7A7A done/\uFF08\u5DF2\u8BFB\u8FC7\u7684\u62A5\u544A\u4E0E\u5DE5\u5355\u5B58\u6863\uFF09
|
|
1067
|
+
|
|
1068
|
+
\u5DE5\u5355\u683C\u5F0F\uFF08Markdown\uFF0Cfrontmatter \u7684 accept \u5FC5\u586B\u2014\u2014\u7F3A\u9A8C\u6536\u62D2\u7EDD\u5165\u961F\uFF09\uFF1A
|
|
1069
|
+
---
|
|
1070
|
+
title: \u4FEE\u590D\u65E5\u671F\u89E3\u6790 bug
|
|
1071
|
+
accept: npm test
|
|
1072
|
+
budget-yuan: 0.5 # \u53EF\u9009\uFF1A\u672C\u4EFB\u52A1\u82B1\u8D39\u4E0A\u9650\uFF08\u5143\uFF09
|
|
1073
|
+
timeout-min: 30 # \u53EF\u9009\uFF1Aagent \u9636\u6BB5\u8D85\u65F6\uFF08\u5206\u949F\uFF0C\u7F3A\u7701 30\uFF09
|
|
1074
|
+
tools: run_command # \u53EF\u9009\uFF1A\u663E\u5F0F\u89E3\u9501\u9AD8\u5371\u5DE5\u5177\uFF08\u7F3A\u7701\u7981 run_command/delete_path\uFF09
|
|
1075
|
+
---
|
|
1076
|
+
\u4EFB\u52A1\u63CF\u8FF0\u6B63\u6587\uFF08Markdown\uFF09\u2026
|
|
1077
|
+
|
|
1078
|
+
\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
|
|
1079
|
+
\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`,
|
|
1080
|
+
adminAddUsage: "\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",
|
|
1081
|
+
readFileFail: (e) => `\u8BFB\u6587\u4EF6\u5931\u8D25\uFF1A${e}`,
|
|
1082
|
+
enqueued: (id, title) => `\u{1F4E5} \u5DF2\u5165\u961F [${id}] ${title}`,
|
|
1083
|
+
addRejected: (name, err) => `\u{1F6AB} \u62D2\u7EDD ${name}\uFF1A${err}`,
|
|
1084
|
+
nextStepRun: "\n\u8DD1\u6279\uFF1Adeepseeker-code batch run",
|
|
1085
|
+
adminQueueEmpty: "\u961F\u5217\u7A7A\u3002\u6295\u9012\uFF1Adeepseeker-code batch add <\u5DE5\u5355.md>\uFF08\u683C\u5F0F\u89C1 batch help\uFF09",
|
|
1086
|
+
listRunningHead: "\u25B6 \u8FD0\u884C\u4E2D\uFF1A",
|
|
1087
|
+
listPendingHead: (n) => `\u23F3 \u5F85\u8DD1 ${n}\uFF1A`,
|
|
1088
|
+
listDoneHead: (n) => `\u2714 \u5DF2\u5B8C\u6210 ${n}\uFF1A`,
|
|
1089
|
+
cleaned: (n) => `\u{1F9F9} \u5DF2\u6E05\u7A7A done/\uFF08${n} \u4E2A\u4EFB\u52A1\u5B58\u6863\uFF09\u3002pending/running \u4E0D\u53D7\u5F71\u54CD\u3002`,
|
|
1090
|
+
reportMissing: "\uFF08\u62A5\u544A\u7F3A\u5931\uFF09",
|
|
1091
|
+
// —— batchRunner 控制台进度 ——
|
|
1092
|
+
ticketRejected: (id, err) => `\u{1F6AB} [${id}] \u5DE5\u5355\u88AB\u62D2\uFF1A${err}`,
|
|
1093
|
+
taskMeta: (budget, timeoutMin, accept) => ` \u9884\u7B97 ${budget !== void 0 ? `\xA5${budget}` : "\u4E0D\u9650"} \xB7 \u8D85\u65F6 ${timeoutMin}min \xB7 \u9A8C\u6536 \`${accept}\``,
|
|
1094
|
+
roundLine: (ts2, round) => ` [${ts2}] \u8F6E ${round}`,
|
|
1095
|
+
wtCreateFail: (e) => `\u521B\u5EFA worktree \u5931\u8D25\uFF08\u9700\u8981\u4E3B\u5DE5\u4F5C\u533A\u662F git \u4ED3\u5E93\uFF09\uFF1A${e}`,
|
|
1096
|
+
agentErrorLine: (id, err) => `\u{1F4A5} [${id}] agent \u5F02\u5E38\uFF1A${err}`,
|
|
1097
|
+
timeoutLine: (id, min) => `\u23F1\uFE0F [${id}] \u8D85\u65F6\uFF08${min}min\uFF09\uFF0C\u622A\u65AD\u6536\u5C3E\uFF08\u9A8C\u6536\u4E0D\u8DD1\uFF09`,
|
|
1098
|
+
acceptLine: (passed, id, code) => `${passed ? "\u2705" : "\u274C"} [${id}] \u9A8C\u6536 exit ${code}`,
|
|
1099
|
+
acceptKilledSuffix: "\uFF08\u8D85\u65F6\u88AB\u6740\uFF09",
|
|
1100
|
+
timeoutAbort: (min) => `\u4EFB\u52A1\u8D85\u65F6\uFF08${min} \u5206\u949F\uFF09`,
|
|
1101
|
+
artifactLine: (p, branch) => ` \u4EA7\u7269\uFF1A${p}\uFF08\u5206\u652F ${branch}\uFF0C\u4FDD\u7559\u5F85\u4EBA\u5DE5\u5904\u7F6E\uFF09`,
|
|
1102
|
+
inWindowNow: (hhmm) => `\u23F0 \u5F53\u524D ${hhmm} \u5DF2\u5728\u7A97\u53E3\u5185\uFF0C\u7ACB\u5373\u5F00\u8DD1\u3002`,
|
|
1103
|
+
waitWindowWait: (h, m) => `\u23F0 --wait-window\uFF1A${h} \u5C0F\u65F6 ${m} \u5206\u540E\uFF08\u7A97\u53E3\u8D77\u70B9\uFF09\u5F00\u8DD1\u3002\u6302\u673A\u7B49\u5F85\u4E2D\uFF0CCtrl+C \u53EF\u53D6\u6D88\u3002`,
|
|
1104
|
+
waitWindowInvalid: (s) => `\u274C --wait-window \u683C\u5F0F\u975E\u6CD5\uFF1A"${s}"\uFF08\u5E94\u4E3A HH:MM-HH:MM\uFF0C\u5982 23:30-06:30\uFF09`,
|
|
1105
|
+
runnerQueueEmpty: "\u961F\u5217\u7A7A\uFF1Apending/ \u65E0\u4EFB\u52A1\u3002\u6295\u9012\uFF1Adeepseeker-code batch add <\u5DE5\u5355.md>",
|
|
1106
|
+
summaryDone: (total, passed, mins) => `\u{1F319} \u6302\u673A\u7ED3\u675F\uFF1A${total} \u4EFB\u52A1 \xB7 ${passed} \u8FC7 \xB7 ${total - passed} \u672A\u8FC7\uFF08\u8017\u65F6 ${mins}min\uFF09`,
|
|
1107
|
+
summaryCost: (sum, tasks) => `\u{1F4B0} \u603B\u82B1\u8D39\uFF1A\xA5${sum}\uFF08${tasks} \u4E2A\u4EFB\u52A1\u8BA1\u4EF7\uFF09`,
|
|
1108
|
+
summaryCostFree: "\u{1F4B0} \u603B\u82B1\u8D39\uFF1A\u5168\u90E8\u65E0\u4EF7\u6A21\u578B\uFF0C\u672A\u8BA1\u94B1",
|
|
1109
|
+
failedHead: "\u26A0\uFE0F \u672A\u8FC7\u6E05\u5355\uFF1A",
|
|
1110
|
+
artifactsDir: "\u62A5\u544A\u4E0E\u6539\u52A8\uFF1A.deepseeker-code/batch/done/\uFF08worktree \u5747\u4FDD\u7559\u5F85\u4EBA\u5DE5\u5904\u7F6E\uFF09",
|
|
1111
|
+
// —— 状态标签(控制台与报告共用) ——
|
|
1112
|
+
statusLabel: (s) => ({
|
|
1113
|
+
passed: "\u2705 \u901A\u8FC7\u9A8C\u6536",
|
|
1114
|
+
"accept-failed": "\u274C \u9A8C\u6536\u672A\u8FC7",
|
|
1115
|
+
timeout: "\u23F1\uFE0F \u8D85\u65F6\u622A\u65AD",
|
|
1116
|
+
error: "\u{1F4A5} agent \u5F02\u5E38",
|
|
1117
|
+
rejected: "\u{1F6AB} \u5DE5\u5355\u88AB\u62D2"
|
|
1118
|
+
})[s],
|
|
1119
|
+
// —— 验收命令执行(输出嵌入报告) ——
|
|
1120
|
+
spawnFail: (e) => `\u542F\u52A8\u5931\u8D25\uFF1A${e}`,
|
|
1121
|
+
execFail: (e) => `\u6267\u884C\u5931\u8D25\uFF1A${e}`,
|
|
1122
|
+
tailOmitted: (n) => `\uFF08\u524D ${n} \u884C\u5DF2\u7701\u7565\uFF09`,
|
|
1123
|
+
noOutput: "\uFF08\u65E0\u8F93\u51FA\uFF09",
|
|
1124
|
+
// —— 结算单聚合与 receipt 行(报告内嵌) ——
|
|
1125
|
+
costFree: "\uFF08\u65E0\u4EF7\u6A21\u578B\uFF0C\u4E0D\u8BA1\u94B1\uFF09",
|
|
1126
|
+
costSummary: (c) => {
|
|
1127
|
+
const money = c.costYuan !== null ? `\xA5${c.costYuan.toFixed(4)}` : "\uFF08\u65E0\u4EF7\u6A21\u578B\uFF0C\u4E0D\u8BA1\u94B1\uFF09";
|
|
1128
|
+
const hit = c.promptTokens > 0 ? Math.round(c.cachedTokens / c.promptTokens * 100) : 0;
|
|
1129
|
+
const mins = Math.round(c.durationMs / 6e3) / 10;
|
|
1130
|
+
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` : ""}`;
|
|
1131
|
+
},
|
|
1132
|
+
noReceipt: "\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",
|
|
1133
|
+
receiptLine: (r) => `${r.rounds} \u8F6E \xB7 ${r.costYuan !== null ? `\xA5${r.costYuan.toFixed(4)}` : "\u65E0\u4EF7"} \xB7 \u7F13\u5B58\u547D\u4E2D ${Math.round(r.cacheHitRate * 100)}% \xB7 ${(r.durationMs / 1e3).toFixed(0)}s`,
|
|
1134
|
+
// —— 报告骨架 ——
|
|
1135
|
+
rejectedTitle: "# \u6302\u673A\u4EFB\u52A1\u88AB\u62D2",
|
|
1136
|
+
reportTitle: (title) => `# \u6302\u673A\u4EFB\u52A1\u62A5\u544A\uFF1A${title}`,
|
|
1137
|
+
statusEntry: (v) => `- \u72B6\u6001\uFF1A${v}`,
|
|
1138
|
+
budgetTruncNote: "\uFF08\u26A0\uFE0F \u9884\u7B97\u622A\u65AD\u540E\u6536\u5C3E\uFF09",
|
|
1139
|
+
costEntry: (v) => `- \u7ED3\u7B97\u5355\uFF1A${v}`,
|
|
1140
|
+
receiptEntry: (v) => `- \u672C\u8F6E receipt\uFF1A${v}`,
|
|
1141
|
+
errorEntry: (v) => `- \u5F02\u5E38\uFF1A${v}
|
|
1142
|
+
`,
|
|
1143
|
+
notCreated: "\uFF08\u672A\u521B\u5EFA\uFF09",
|
|
1144
|
+
taskH: "## \u4EFB\u52A1",
|
|
1145
|
+
finalH: "## \u6A21\u578B\u6536\u5C3E\u6C47\u62A5",
|
|
1146
|
+
noFinal: "\uFF08\u65E0\u8F93\u51FA\u2014\u2014run \u5728\u4EA7\u51FA\u6B63\u6587\u524D\u88AB\u622A\u65AD/\u5F02\u5E38\uFF09",
|
|
1147
|
+
acceptH: "## \u9A8C\u6536",
|
|
1148
|
+
acceptCmdLine: (cmd, code) => `\u547D\u4EE4\uFF1A\`${cmd}\` \u2192 exit ${code}`,
|
|
1149
|
+
acceptTimeoutSuffix: "\uFF08\u23F1\uFE0F \u9A8C\u6536\u8D85\u65F6\u88AB\u6740\uFF09",
|
|
1150
|
+
acceptTail: "\u8F93\u51FA\u5C3E\u90E8\uFF1A",
|
|
1151
|
+
noAccept: "\n\uFF08\u672A\u6267\u884C\u9A8C\u6536\u2014\u2014\u6539\u52A8\u4E0D\u5B8C\u6574\uFF0C\u8DD1\u4E86\u4E5F\u662F\u566A\u58F0\uFF09",
|
|
1152
|
+
deniedH: "## \u88AB\u62D2\u5DE5\u5177\u8C03\u7528\uFF08fail-closed \u8BB0\u5F55\uFF09",
|
|
1153
|
+
deniedNone: "\u65E0\u3002",
|
|
1154
|
+
diffH: "## Diff \u6458\u8981\uFF08worktree \u76F8\u5BF9\u57FA\u5EA7\uFF0C\u672A\u63D0\u4EA4\uFF0C\u5F85\u4EBA\u5DE5\u5904\u7F6E\uFF09",
|
|
1155
|
+
diffNote: (branch, p) => `\u6539\u52A8\u5728\u72EC\u7ACB worktree\uFF08\u5206\u652F \`${branch}\`\uFF0C\u8DEF\u5F84 ${p}\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`,
|
|
1156
|
+
diffNone: "\uFF08\u65E0\uFF09"
|
|
1157
|
+
};
|
|
1158
|
+
EN = {
|
|
1159
|
+
usage: `deepseeker-code batch \u2014 unattended batch runs (cost trust chain)
|
|
1160
|
+
|
|
1161
|
+
Usage: deepseeker-code batch <subcommand>
|
|
1162
|
+
add <ticket.md> [...] Enqueue tasks (multiple files at once)
|
|
1163
|
+
list Show the pending / running / done queue
|
|
1164
|
+
run [--wait-window HH:MM-HH:MM] Run the queue (serial, one report per task; --wait-window waits for the window)
|
|
1165
|
+
clean Clear done/ (reports and ticket archives you've read)
|
|
1166
|
+
|
|
1167
|
+
Ticket format (Markdown; frontmatter \`accept\` is required \u2014 no acceptance, no enqueue):
|
|
1168
|
+
---
|
|
1169
|
+
title: Fix date parsing bug
|
|
1170
|
+
accept: npm test # required: acceptance command (exit 0 = pass)
|
|
1171
|
+
budget-yuan: 0.5 # optional: per-task cost cap (yuan)
|
|
1172
|
+
timeout-min: 30 # optional: agent-phase timeout (minutes, default 30)
|
|
1173
|
+
tools: run_command # optional: unlock risky tools (run_command/delete_path denied by default)
|
|
1174
|
+
---
|
|
1175
|
+
|
|
1176
|
+
Task description body (Markdown)\u2026
|
|
1177
|
+
|
|
1178
|
+
Artifacts: <project>/.deepseeker-code/batch/done/<id>.report.md (status / receipt / acceptance output / diff summary);
|
|
1179
|
+
changes are harvested onto an isolated git worktree (temp branch), kept for manual merge or disposal.`,
|
|
1180
|
+
adminAddUsage: "Usage: deepseeker-code batch add <ticket.md> [...] (tickets without an acceptance command are rejected)\nDetails: deepseeker-code batch help",
|
|
1181
|
+
readFileFail: (e) => `Failed to read file: ${e}`,
|
|
1182
|
+
enqueued: (id, title) => `\u{1F4E5} Enqueued [${id}] ${title}`,
|
|
1183
|
+
addRejected: (name, err) => `\u{1F6AB} Rejected ${name}: ${err}`,
|
|
1184
|
+
nextStepRun: "\nRun the queue: deepseeker-code batch run",
|
|
1185
|
+
adminQueueEmpty: "Queue is empty. Enqueue: deepseeker-code batch add <ticket.md> (format: batch help)",
|
|
1186
|
+
listRunningHead: "\u25B6 Running:",
|
|
1187
|
+
listPendingHead: (n) => `\u23F3 Pending ${n}:`,
|
|
1188
|
+
listDoneHead: (n) => `\u2714 Done ${n}:`,
|
|
1189
|
+
cleaned: (n) => `\u{1F9F9} Cleared done/ (${n} task archives). pending/running untouched.`,
|
|
1190
|
+
reportMissing: "(report missing)",
|
|
1191
|
+
ticketRejected: (id, err) => `\u{1F6AB} [${id}] Ticket rejected: ${err}`,
|
|
1192
|
+
taskMeta: (budget, timeoutMin, accept) => ` Budget ${budget !== void 0 ? `\xA5${budget}` : "uncapped"} \xB7 timeout ${timeoutMin}min \xB7 accept \`${accept}\``,
|
|
1193
|
+
roundLine: (ts2, round) => ` [${ts2}] round ${round}`,
|
|
1194
|
+
wtCreateFail: (e) => `Failed to create worktree (the main workspace must be a git repo): ${e}`,
|
|
1195
|
+
agentErrorLine: (id, err) => `\u{1F4A5} [${id}] agent error: ${err}`,
|
|
1196
|
+
timeoutLine: (id, min) => `\u23F1\uFE0F [${id}] Timed out (${min}min); wrapped up truncated (acceptance skipped)`,
|
|
1197
|
+
acceptLine: (passed, id, code) => `${passed ? "\u2705" : "\u274C"} [${id}] acceptance exit ${code}`,
|
|
1198
|
+
acceptKilledSuffix: " (killed on timeout)",
|
|
1199
|
+
timeoutAbort: (min) => `Task timed out (${min} minutes)`,
|
|
1200
|
+
artifactLine: (p, branch) => ` Artifact: ${p} (branch ${branch}, kept for manual handling)`,
|
|
1201
|
+
inWindowNow: (hhmm) => `\u23F0 It's ${hhmm}, already inside the window \u2014 starting now.`,
|
|
1202
|
+
waitWindowWait: (h, m) => `\u23F0 --wait-window: starting in ${h}h ${m}m (at the window start). Waiting \u2014 Ctrl+C to cancel.`,
|
|
1203
|
+
waitWindowInvalid: (s) => `\u274C Invalid --wait-window: "${s}" (expected HH:MM-HH:MM, e.g. 23:30-06:30)`,
|
|
1204
|
+
runnerQueueEmpty: "Queue empty: no tasks in pending/. Enqueue: deepseeker-code batch add <ticket.md>",
|
|
1205
|
+
summaryDone: (total, passed, mins) => `\u{1F319} Batch finished: ${total} tasks \xB7 ${passed} passed \xB7 ${total - passed} failed (${mins}min)`,
|
|
1206
|
+
summaryCost: (sum, tasks) => `\u{1F4B0} Total cost: \xA5${sum} (${tasks} tasks priced)`,
|
|
1207
|
+
summaryCostFree: "\u{1F4B0} Total cost: all records unpriced, no money counted",
|
|
1208
|
+
failedHead: "\u26A0\uFE0F Failed tasks:",
|
|
1209
|
+
artifactsDir: "Reports and changes: .deepseeker-code/batch/done/ (worktrees kept for manual handling)",
|
|
1210
|
+
statusLabel: (s) => ({
|
|
1211
|
+
passed: "\u2705 acceptance passed",
|
|
1212
|
+
"accept-failed": "\u274C acceptance failed",
|
|
1213
|
+
timeout: "\u23F1\uFE0F timed out",
|
|
1214
|
+
error: "\u{1F4A5} agent error",
|
|
1215
|
+
rejected: "\u{1F6AB} ticket rejected"
|
|
1216
|
+
})[s],
|
|
1217
|
+
spawnFail: (e) => `Spawn failed: ${e}`,
|
|
1218
|
+
execFail: (e) => `Execution failed: ${e}`,
|
|
1219
|
+
tailOmitted: (n) => `(first ${n} lines omitted)`,
|
|
1220
|
+
noOutput: "(no output)",
|
|
1221
|
+
costFree: "(unpriced model, no money counted)",
|
|
1222
|
+
costSummary: (c) => {
|
|
1223
|
+
const money = c.costYuan !== null ? `\xA5${c.costYuan.toFixed(4)}` : "(unpriced model, no money counted)";
|
|
1224
|
+
const hit = c.promptTokens > 0 ? Math.round(c.cachedTokens / c.promptTokens * 100) : 0;
|
|
1225
|
+
const mins = Math.round(c.durationMs / 6e3) / 10;
|
|
1226
|
+
return `${c.rounds} rounds \xB7 ${money} \xB7 cache hit ${hit}% \xB7 ${mins}min${c.partialPrice ? " (some records unpriced; money is a partial sum)" : ""}${c.subRuns > 0 ? ` \xB7 ${c.subRuns} sub-runs included` : ""}`;
|
|
1227
|
+
},
|
|
1228
|
+
noReceipt: "(no receipt \u2014 the run was truncated before finishing; cost per the usageLog aggregate above)",
|
|
1229
|
+
receiptLine: (r) => `${r.rounds} rounds \xB7 ${r.costYuan !== null ? `\xA5${r.costYuan.toFixed(4)}` : "unpriced"} \xB7 cache hit ${Math.round(r.cacheHitRate * 100)}% \xB7 ${(r.durationMs / 1e3).toFixed(0)}s`,
|
|
1230
|
+
rejectedTitle: "# Batch task rejected",
|
|
1231
|
+
reportTitle: (title) => `# Batch task report: ${title}`,
|
|
1232
|
+
statusEntry: (v) => `- Status: ${v}`,
|
|
1233
|
+
budgetTruncNote: " (\u26A0\uFE0F wrapped up after budget truncation)",
|
|
1234
|
+
costEntry: (v) => `- Receipt: ${v}`,
|
|
1235
|
+
receiptEntry: (v) => `- This run's receipt: ${v}`,
|
|
1236
|
+
errorEntry: (v) => `- Error: ${v}
|
|
1237
|
+
`,
|
|
1238
|
+
notCreated: "(not created)",
|
|
1239
|
+
taskH: "## Task",
|
|
1240
|
+
finalH: "## Model final report",
|
|
1241
|
+
noFinal: "(no output \u2014 the run was truncated/errored before producing any text)",
|
|
1242
|
+
acceptH: "## Acceptance",
|
|
1243
|
+
acceptCmdLine: (cmd, code) => `Command: \`${cmd}\` \u2192 exit ${code}`,
|
|
1244
|
+
acceptTimeoutSuffix: " (\u23F1\uFE0F acceptance timed out, killed)",
|
|
1245
|
+
acceptTail: "Output tail:",
|
|
1246
|
+
noAccept: "\n(Acceptance not run \u2014 changes incomplete, running it would be noise.)",
|
|
1247
|
+
deniedH: "## Denied tool calls (fail-closed log)",
|
|
1248
|
+
deniedNone: "None.",
|
|
1249
|
+
diffH: "## Diff summary (worktree vs base, uncommitted, awaiting manual handling)",
|
|
1250
|
+
diffNote: (branch, p) => `Changes live in an isolated worktree (branch \`${branch}\`, path ${p}). To keep: commit inside the worktree and merge back. To discard: delete the worktree directory + \`git worktree prune\` + \`git branch -D <branch>\`.`,
|
|
1251
|
+
diffNone: "(none)"
|
|
1252
|
+
};
|
|
1253
|
+
DICT = { zh: ZH, en: EN };
|
|
1254
|
+
batchT = (locale2) => DICT[locale2] ?? ZH;
|
|
1255
|
+
}
|
|
1256
|
+
});
|
|
1257
|
+
|
|
966
1258
|
// src/batchAdmin.ts
|
|
967
1259
|
var batchAdmin_exports = {};
|
|
968
1260
|
__export(batchAdmin_exports, {
|
|
@@ -971,11 +1263,14 @@ __export(batchAdmin_exports, {
|
|
|
971
1263
|
});
|
|
972
1264
|
import fs6 from "fs/promises";
|
|
973
1265
|
import path7 from "path";
|
|
974
|
-
var emit, parseBatchArgv,
|
|
1266
|
+
var emit, parseBatchArgv, handleBatchAdmin, describeDone;
|
|
975
1267
|
var init_batchAdmin = __esm({
|
|
976
1268
|
"src/batchAdmin.ts"() {
|
|
977
1269
|
"use strict";
|
|
978
1270
|
init_queue();
|
|
1271
|
+
init_batchStrings();
|
|
1272
|
+
init_strings();
|
|
1273
|
+
init_prefs();
|
|
979
1274
|
emit = (s = "") => {
|
|
980
1275
|
process.stdout.write(s + "\n");
|
|
981
1276
|
};
|
|
@@ -992,62 +1287,45 @@ var init_batchAdmin = __esm({
|
|
|
992
1287
|
if (sub === "clean") return { sub: "clean" };
|
|
993
1288
|
return { sub: "help" };
|
|
994
1289
|
};
|
|
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
1290
|
handleBatchAdmin = async (b) => {
|
|
1291
|
+
const saved = await readLocale();
|
|
1292
|
+
if (saved) setLocale(saved);
|
|
1293
|
+
const T = batchT(getLocale());
|
|
1016
1294
|
if (b.sub === "help") {
|
|
1017
|
-
emit(
|
|
1295
|
+
emit(T.usage);
|
|
1018
1296
|
return;
|
|
1019
1297
|
}
|
|
1020
1298
|
if (b.sub === "add") {
|
|
1021
1299
|
if (b.files.length === 0) {
|
|
1022
|
-
emit(
|
|
1300
|
+
emit(T.adminAddUsage);
|
|
1023
1301
|
return;
|
|
1024
1302
|
}
|
|
1025
1303
|
for (const f of b.files) {
|
|
1026
1304
|
const abs = path7.resolve(f);
|
|
1027
|
-
const r = await enqueueTicketFile(abs).catch((e) => ({ ok: false, error:
|
|
1028
|
-
if (r.ok) emit(
|
|
1029
|
-
else emit(
|
|
1305
|
+
const r = await enqueueTicketFile(abs, getLocale()).catch((e) => ({ ok: false, error: T.readFileFail(e?.message ?? e) }));
|
|
1306
|
+
if (r.ok) emit(T.enqueued(r.id, r.title));
|
|
1307
|
+
else emit(T.addRejected(path7.basename(abs), r.error));
|
|
1030
1308
|
}
|
|
1031
|
-
emit(
|
|
1309
|
+
emit(T.nextStepRun);
|
|
1032
1310
|
return;
|
|
1033
1311
|
}
|
|
1034
1312
|
if (b.sub === "list") {
|
|
1035
1313
|
const q = await snapshotQueue();
|
|
1036
1314
|
if (q.pending.length + q.running.length + q.done.length === 0) {
|
|
1037
|
-
emit(
|
|
1315
|
+
emit(T.adminQueueEmpty);
|
|
1038
1316
|
return;
|
|
1039
1317
|
}
|
|
1040
|
-
if (q.running.length > 0) emit(
|
|
1318
|
+
if (q.running.length > 0) emit(T.listRunningHead);
|
|
1041
1319
|
for (const f of q.running) emit(` ${f.replace(/\.md$/, "")}`);
|
|
1042
|
-
if (q.pending.length > 0) emit(
|
|
1320
|
+
if (q.pending.length > 0) emit(T.listPendingHead(q.pending.length));
|
|
1043
1321
|
for (const f of q.pending) emit(` ${f.replace(/\.md$/, "")}`);
|
|
1044
|
-
if (q.done.length > 0) emit(
|
|
1322
|
+
if (q.done.length > 0) emit(T.listDoneHead(q.done.length));
|
|
1045
1323
|
for (const id of q.done) emit(` ${id} ${await describeDone(id)}`);
|
|
1046
1324
|
return;
|
|
1047
1325
|
}
|
|
1048
1326
|
if (b.sub === "clean") {
|
|
1049
1327
|
const n = await cleanDone();
|
|
1050
|
-
emit(
|
|
1328
|
+
emit(T.cleaned(n));
|
|
1051
1329
|
return;
|
|
1052
1330
|
}
|
|
1053
1331
|
};
|
|
@@ -1056,7 +1334,7 @@ var init_batchAdmin = __esm({
|
|
|
1056
1334
|
try {
|
|
1057
1335
|
text = await fs6.readFile(reportPath(id), "utf-8");
|
|
1058
1336
|
} catch {
|
|
1059
|
-
return
|
|
1337
|
+
return batchT(getLocale()).reportMissing;
|
|
1060
1338
|
}
|
|
1061
1339
|
const fm = (key) => {
|
|
1062
1340
|
const m = new RegExp(`^${key}:\\s*(.+)$`, "m").exec(text);
|
|
@@ -15390,7 +15668,7 @@ var init_useChatState = __esm({
|
|
|
15390
15668
|
break;
|
|
15391
15669
|
}
|
|
15392
15670
|
case "vision.downgraded":
|
|
15393
|
-
pushInfo(
|
|
15671
|
+
pushInfo(S.visionDowngraded(String(obj.model ?? "")));
|
|
15394
15672
|
break;
|
|
15395
15673
|
default:
|
|
15396
15674
|
break;
|
|
@@ -15535,7 +15813,7 @@ ${finalPlan}`, false, res.autoExecute);
|
|
|
15535
15813
|
} else {
|
|
15536
15814
|
const enterReason = takeEnterPlanRequest();
|
|
15537
15815
|
if (enterReason != null) {
|
|
15538
|
-
pushInfo(
|
|
15816
|
+
pushInfo(S.planEnterSwitched(enterReason));
|
|
15539
15817
|
planModeRef.current = true;
|
|
15540
15818
|
const kept = await runPlanStage(sid, ENTER_PLAN_RESEARCH_PROMPT);
|
|
15541
15819
|
if (kept) planModeRef.current = false;
|
|
@@ -15549,7 +15827,7 @@ ${finalPlan}`, false, res.autoExecute);
|
|
|
15549
15827
|
const runBangCommand = useCallback(async (raw) => {
|
|
15550
15828
|
const cmd = raw.replace(/^!/, "").trim();
|
|
15551
15829
|
if (!cmd) {
|
|
15552
|
-
pushInfo(
|
|
15830
|
+
pushInfo(S.bangUsage);
|
|
15553
15831
|
return;
|
|
15554
15832
|
}
|
|
15555
15833
|
pushUser(raw);
|
|
@@ -15557,9 +15835,9 @@ ${finalPlan}`, false, res.autoExecute);
|
|
|
15557
15835
|
sessionIdRef.current = await getOrCreateSessionId(initialSessionId ?? void 0);
|
|
15558
15836
|
}
|
|
15559
15837
|
const r = await runBashDirect(cmd, getActiveWorkspaceRoot());
|
|
15560
|
-
const head = r.timedOut
|
|
15838
|
+
const head = S.bangHead(r.timedOut, r.ok, r.exitCode ?? null);
|
|
15561
15839
|
pushInfo(`${head} \xB7 ${Math.round(r.durationMs / 100) / 10}s
|
|
15562
|
-
${r.output.trim() ||
|
|
15840
|
+
${r.output.trim() || S.bangNoOutput}`);
|
|
15563
15841
|
await recordBashEntry(sessionIdRef.current, formatBashEntry(cmd, r));
|
|
15564
15842
|
}, [initialSessionId, pushUser, pushInfo]);
|
|
15565
15843
|
const abortCurrent = useCallback(() => {
|
|
@@ -16854,7 +17132,7 @@ var init_TopPanel = __esm({
|
|
|
16854
17132
|
|
|
16855
17133
|
// ../core/src/observability/inspect.ts
|
|
16856
17134
|
import fs48 from "fs";
|
|
16857
|
-
var CWD, fmt, readTrace,
|
|
17135
|
+
var OBS, obsT, CWD, fmt, readTrace, fmtK, inspectUsage, inspectContext, inspectPermissions, inspectMcp, inspectHooks, inspectDebug;
|
|
16858
17136
|
var init_inspect = __esm({
|
|
16859
17137
|
"../core/src/observability/inspect.ts"() {
|
|
16860
17138
|
"use strict";
|
|
@@ -16870,6 +17148,104 @@ var init_inspect = __esm({
|
|
|
16870
17148
|
init_truncate();
|
|
16871
17149
|
init_recall();
|
|
16872
17150
|
init_createModel();
|
|
17151
|
+
OBS = {
|
|
17152
|
+
zh: {
|
|
17153
|
+
usageNoData: "\u{1F4CA} Token \u7528\u91CF\uFF1A\u6682\u65E0\u6570\u636E\uFF08\u672C\u4F1A\u8BDD\u5C1A\u65E0 LLM \u54CD\u5E94\u843D\u76D8\uFF09\u3002",
|
|
17154
|
+
usageHead: (rounds) => `\u{1F4CA} Token \u7528\u91CF\uFF08\u672C\u4F1A\u8BDD\uFF0C${rounds} \u6B21 LLM \u54CD\u5E94\uFF09`,
|
|
17155
|
+
usageTokens: (prompt, completion, total) => ` \u8F93\u5165(prompt): ${prompt} | \u8F93\u51FA(completion): ${completion} | \u5408\u8BA1: ${total}`,
|
|
17156
|
+
usageCache: (hit, rate, miss) => ` \u7F13\u5B58\u547D\u4E2D: ${hit}\uFF08${rate}%\uFF09 | \u7F13\u5B58\u672A\u547D\u4E2D: ${miss}`,
|
|
17157
|
+
usageSplit: (main2, sub) => ` \u4E3B agent: ${main2} | \u5B50 agent(spawn/workflow): ${sub}`,
|
|
17158
|
+
usageSessionRuns: (runs, rounds, avg, aborted, pct) => ` \u258E\u672C\u4F1A\u8BDD ${runs} \u4E2A run\uFF1A${rounds} \u8F6E\uFF08\u5747 ${avg} \u8F6E/run\uFF09\xB7 \u4E2D\u6B62 ${aborted}/${runs}\uFF08${pct}%\uFF09`,
|
|
17159
|
+
usageNoTools: "\uFF08\u65E0\u5DE5\u5177\u8C03\u7528\uFF09",
|
|
17160
|
+
usageRunLine: (ts2, rounds, tok, stop, tools) => ` ${ts2} ${rounds}\u8F6E ${tok} tok ${stop} ${tools}`,
|
|
17161
|
+
stopLabel: { normal: "\u5B8C\u6210", aborted: "\u4E2D\u6B62", error: "\u9519\u8BEF", repeat: "\u7194\u65AD", limit: "\u8D85\u9650" },
|
|
17162
|
+
usageWeek: (runs, rounds, avg, abortPct, tokens, hitPct) => ` \u258E\u8FD1 7 \u5929\uFF08\u4F7F\u7528\u65E5\u5FD7 \xB7 \u5168\u9879\u76EE\uFF09\uFF1A${runs} runs \xB7 ${rounds} \u8F6E\uFF08\u5747 ${avg} \u8F6E/run\uFF09\xB7 \u4E2D\u6B62 ${abortPct}% \xB7 ${tokens} tok\uFF08\u7F13\u5B58\u547D\u4E2D ${hitPct}%\uFF09`,
|
|
17163
|
+
usageTopTools: (tools) => ` \u5E38\u7528\u5DE5\u5177: ${tools.join("\u3001") || "\uFF08\u65E0\uFF09"}`,
|
|
17164
|
+
usageWeekCost: (cost, saved, unpriced) => ` \u8FD1 7 \u5929\u82B1\u8D39 \xA5${cost}\uFF08\u7F13\u5B58\u547D\u4E2D\u5DF2\u7701 \xA5${saved}\uFF09${unpriced > 0 ? ` \xB7 ${unpriced} \u6761\u65E0\u4EF7\u8BB0\u5F55\u672A\u8BA1` : ""}`,
|
|
17165
|
+
usageTopSessions: (tops) => ` \u8D39\u7528 top \u4F1A\u8BDD: ${tops}`,
|
|
17166
|
+
usageTip: " \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",
|
|
17167
|
+
ctxHead: "\u{1F9E0} \u4E0A\u4E0B\u6587\u6CBB\u7406",
|
|
17168
|
+
ctxWindow: (window, threshold, ratio, keep) => ` \u7A97\u53E3\u4E0A\u9650: ${window} | \u538B\u7F29\u9608\u503C: ${threshold}\uFF08${ratio}\xD7\uFF09 | \u4FDD\u7559\u6700\u8FD1: ${keep} \u5BF9\u8BDD\u5355\u5143`,
|
|
17169
|
+
ctxLastPrompt: (p, fillRate) => ` \u6700\u8FD1 prompt: ${p ?? "\uFF08\u5C1A\u65E0\uFF09"}${fillRate ? `\uFF08\u5360\u7A97\u53E3 ${fillRate}%\uFF09` : ""}`,
|
|
17170
|
+
ctxArchived: (n) => ` \u5DF2\u5F52\u6863(\u538B\u7F29)\u6D88\u606F\u6761\u6570: ${n}`,
|
|
17171
|
+
ctxEntities: (n) => ` \u672C\u4F1A\u8BDD\u5DF2\u5F52\u6863\u5B9E\u4F53: ${n} \u4E2A\uFF08\u6458\u8981\u69FD\u7D22\u5F15\uFF09`,
|
|
17172
|
+
ctxRecall: (n) => ` \u53EC\u56DE\u547D\u4E2D: ${n} \u6B21\uFF08recall \u5DE5\u5177\uFF0C\u672C\u6B21\u8FDB\u7A0B\u5185\u8BA1\u6570\uFF09`,
|
|
17173
|
+
ctxSidecar: (n) => ` \u4FA7\u8F66\u5B58\u6863: ${n} \u6761\uFF08\u8D85\u957F\u5DE5\u5177\u7ED3\u679C\u539F\u6587\uFF0Crecall with_full \u53D6\u56DE\uFF09`,
|
|
17174
|
+
ctxTip: (pct) => ` \u8D85\u8FC7\u9608\u503C\u5373\u89E6\u53D1\u6EDA\u52A8\u538B\u7F29\uFF1BfillRate \u63A5\u8FD1 ${pct}% \u65F6\u5373\u5C06\u538B\u7F29\u3002`,
|
|
17175
|
+
permEmpty: "\u{1F512} \u6743\u9650\u89C4\u5219\uFF1A\u65E0\uFF08\u5168\u90E8\u8D70\u9ED8\u8BA4 safetyLevel\uFF1ASAFE \u514D\u5BA1 / MUTATION\xB7DANGER \u5BA1\u6279\uFF09\u3002",
|
|
17176
|
+
permHead: "\u{1F512} \u6743\u9650\u89C4\u5219\uFF08\u4F18\u5148\u7EA7 deny > ask > allow\uFF1B\u672A\u5339\u914D\u8D70\u9ED8\u8BA4 safetyLevel\uFF09",
|
|
17177
|
+
permNone: "(\u65E0)",
|
|
17178
|
+
permGroup: (icon, label, n) => ` ${icon} ${label}\uFF08${n}\uFF09:`,
|
|
17179
|
+
mcpEmpty: "\u{1F50C} MCP\uFF1A\u65E0\u5DF2\u8FDE\u63A5 server\uFF08\u5728 ~/.deepseeker-code/mcp.json \u914D\u7F6E\uFF09\u3002",
|
|
17180
|
+
mcpHead: (n, tools) => `\u{1F50C} MCP server\uFF08${n} \u4E2A\uFF0C\u5171 ${tools} \u4E2A\u5DE5\u5177\uFF09`,
|
|
17181
|
+
mcpLine: (name, tools) => ` \u2022 ${name}\uFF08${tools}\uFF09`,
|
|
17182
|
+
mcpToolCount: (n) => `${n} \u4E2A\u5DE5\u5177`,
|
|
17183
|
+
mcpToolCountFail: "\u5DE5\u5177\u6570\u83B7\u53D6\u5931\u8D25",
|
|
17184
|
+
hooksEmpty: "\u{1FA9D} Hooks\uFF1A\u65E0\uFF08\u5728 ~/.deepseeker-code/settings.json \u7684 hooks \u6BB5\u914D\u7F6E\uFF09\u3002",
|
|
17185
|
+
hooksHead: (n) => `\u{1FA9D} Hooks\uFF08\u5171 ${n} \u6761\uFF0C\u6309\u4E8B\u4EF6\u5206\u7EC4\uFF09`,
|
|
17186
|
+
hooksGroup: (evt, n) => ` \u2022 ${evt}\uFF08${n}\uFF09:`,
|
|
17187
|
+
dbgHead: "\u{1F41E} Debug \u5FEB\u7167",
|
|
17188
|
+
dbgSessionNone: "(\u672A\u521D\u59CB\u5316)",
|
|
17189
|
+
dbgModels: (main2, aux) => ` \u4E3B\u6A21\u578B: ${main2} | \u8F85\u52A9\u6A21\u578B: ${aux}`,
|
|
17190
|
+
dbgAuxNone: "(\u672A\u914D\u7F6E)",
|
|
17191
|
+
dbgOn: "\u5F00",
|
|
17192
|
+
dbgOff: "\u5173",
|
|
17193
|
+
dbgParallel: (on, conc, steps) => ` \u5E76\u884C\u5DE5\u5177: ${on} | workflow \u5E76\u53D1\u4E0A\u9650: ${conc} | workflow \u6700\u5927\u6B65\u6570: ${steps}`,
|
|
17194
|
+
dbgUndo: (on, search) => ` undo: ${on} | \u641C\u7D22\u540E\u7AEF: ${search}`,
|
|
17195
|
+
dbgSearchAuto: "(\u81EA\u52A8)",
|
|
17196
|
+
dbgPlatform: (node, platform) => ` Node: ${node} | \u5E73\u53F0: ${platform}`
|
|
17197
|
+
},
|
|
17198
|
+
en: {
|
|
17199
|
+
usageNoData: "\u{1F4CA} Token usage: no data yet (no LLM responses logged for this session).",
|
|
17200
|
+
usageHead: (rounds) => `\u{1F4CA} Token usage (this session, ${rounds} LLM responses)`,
|
|
17201
|
+
usageTokens: (prompt, completion, total) => ` Input (prompt): ${prompt} | Output (completion): ${completion} | Total: ${total}`,
|
|
17202
|
+
usageCache: (hit, rate, miss) => ` Cache hit: ${hit} (${rate}%) | Cache miss: ${miss}`,
|
|
17203
|
+
usageSplit: (main2, sub) => ` Main agent: ${main2} | Sub agents (spawn/workflow): ${sub}`,
|
|
17204
|
+
usageSessionRuns: (runs, rounds, avg, aborted, pct) => ` \u258EThis session: ${runs} runs, ${rounds} rounds (avg ${avg}/run) \xB7 aborted ${aborted}/${runs} (${pct}%)`,
|
|
17205
|
+
usageNoTools: "(no tool calls)",
|
|
17206
|
+
usageRunLine: (ts2, rounds, tok, stop, tools) => ` ${ts2} ${rounds} rounds ${tok} tok ${stop} ${tools}`,
|
|
17207
|
+
stopLabel: { normal: "done", aborted: "aborted", error: "error", repeat: "fuse", limit: "limit" },
|
|
17208
|
+
usageWeek: (runs, rounds, avg, abortPct, tokens, hitPct) => ` \u258ELast 7 days (usage log \xB7 all projects): ${runs} runs \xB7 ${rounds} rounds (avg ${avg}/run) \xB7 aborted ${abortPct}% \xB7 ${tokens} tok (cache hit ${hitPct}%)`,
|
|
17209
|
+
usageTopTools: (tools) => ` Top tools: ${tools.join(", ") || "(none)"}`,
|
|
17210
|
+
usageWeekCost: (cost, saved, unpriced) => ` 7-day spend \xA5${cost} (cache hits saved \xA5${saved})${unpriced > 0 ? ` \xB7 ${unpriced} unpriced records excluded` : ""}`,
|
|
17211
|
+
usageTopSessions: (tops) => ` Costliest sessions: ${tops}`,
|
|
17212
|
+
usageTip: " Tip: parallel workflows multiply sub-agent usage; higher cache hit rate means lower input cost.",
|
|
17213
|
+
ctxHead: "\u{1F9E0} Context governance",
|
|
17214
|
+
ctxWindow: (window, threshold, ratio, keep) => ` Window cap: ${window} | Compact threshold: ${threshold} (${ratio}\xD7) | Keep recent: ${keep} dialogue units`,
|
|
17215
|
+
ctxLastPrompt: (p, fillRate) => ` Last prompt: ${p ?? "(none yet)"}${fillRate ? ` (${fillRate}% of window)` : ""}`,
|
|
17216
|
+
ctxArchived: (n) => ` Archived (compacted) messages: ${n}`,
|
|
17217
|
+
ctxEntities: (n) => ` Archived entities this session: ${n} (summary-slot index)`,
|
|
17218
|
+
ctxRecall: (n) => ` Recall hits: ${n} (recall tool, in-process count)`,
|
|
17219
|
+
ctxSidecar: (n) => ` Sidecar archives: ${n} (full tool outputs, retrievable via recall with_full)`,
|
|
17220
|
+
ctxTip: (pct) => ` Rolling compaction triggers past the threshold; fillRate near ${pct}% means compaction is imminent.`,
|
|
17221
|
+
permEmpty: "\u{1F512} Permission rules: none (everything uses default safetyLevel: SAFE auto-approve / MUTATION\xB7DANGER gated).",
|
|
17222
|
+
permHead: "\u{1F512} Permission rules (priority deny > ask > allow; unmatched uses default safetyLevel)",
|
|
17223
|
+
permNone: "(none)",
|
|
17224
|
+
permGroup: (icon, label, n) => ` ${icon} ${label} (${n}):`,
|
|
17225
|
+
mcpEmpty: "\u{1F50C} MCP: no connected servers (configure in ~/.deepseeker-code/mcp.json).",
|
|
17226
|
+
mcpHead: (n, tools) => `\u{1F50C} MCP servers (${n}, ${tools} tools total)`,
|
|
17227
|
+
mcpLine: (name, tools) => ` \u2022 ${name} (${tools})`,
|
|
17228
|
+
mcpToolCount: (n) => `${n} tools`,
|
|
17229
|
+
mcpToolCountFail: "failed to count tools",
|
|
17230
|
+
hooksEmpty: "\u{1FA9D} Hooks: none (configure under the hooks key in ~/.deepseeker-code/settings.json).",
|
|
17231
|
+
hooksHead: (n) => `\u{1FA9D} Hooks (${n} total, grouped by event)`,
|
|
17232
|
+
hooksGroup: (evt, n) => ` \u2022 ${evt} (${n}):`,
|
|
17233
|
+
dbgHead: "\u{1F41E} Debug snapshot",
|
|
17234
|
+
dbgSessionNone: "(not initialized)",
|
|
17235
|
+
dbgModels: (main2, aux) => ` Main model: ${main2} | Aux model: ${aux}`,
|
|
17236
|
+
dbgAuxNone: "(not configured)",
|
|
17237
|
+
dbgOn: "on",
|
|
17238
|
+
dbgOff: "off",
|
|
17239
|
+
dbgParallel: (on, conc, steps) => ` Parallel tools: ${on} | Workflow concurrency cap: ${conc} | Workflow max steps: ${steps}`,
|
|
17240
|
+
dbgUndo: (on, search) => ` undo: ${on} | Search backend: ${search}`,
|
|
17241
|
+
dbgSearchAuto: "(auto)",
|
|
17242
|
+
dbgPlatform: (node, platform) => ` Node: ${node} | Platform: ${platform}`
|
|
17243
|
+
}
|
|
17244
|
+
};
|
|
17245
|
+
obsT = (locale2) => {
|
|
17246
|
+
const dict = OBS[locale2] ?? OBS.zh;
|
|
17247
|
+
return (key) => dict[key] ?? OBS.zh[key] ?? key;
|
|
17248
|
+
};
|
|
16873
17249
|
CWD = process.cwd();
|
|
16874
17250
|
fmt = (n) => typeof n === "number" && Number.isFinite(n) ? n.toLocaleString("en-US") : "-";
|
|
16875
17251
|
readTrace = async (sessionId) => {
|
|
@@ -16890,13 +17266,13 @@ var init_inspect = __esm({
|
|
|
16890
17266
|
return [];
|
|
16891
17267
|
}
|
|
16892
17268
|
};
|
|
16893
|
-
STOP_LABEL = { normal: "\u5B8C\u6210", aborted: "\u4E2D\u6B62", error: "\u9519\u8BEF", repeat: "\u7194\u65AD", limit: "\u8D85\u9650" };
|
|
16894
17269
|
fmtK = (n) => n >= 1e4 ? `${(n / 1e3).toFixed(1)}k` : fmt(n);
|
|
16895
|
-
inspectUsage = async (sessionId) => {
|
|
17270
|
+
inspectUsage = async (sessionId, locale2 = "zh") => {
|
|
17271
|
+
const t = obsT(locale2);
|
|
16896
17272
|
const trace = await readTrace(sessionId);
|
|
16897
|
-
const responses = trace.filter((
|
|
17273
|
+
const responses = trace.filter((x) => x?.eventType === "llm.response" && x?.usage);
|
|
16898
17274
|
const sessionRuns = (await readUsageRecords()).filter((r) => r.sessionId === sessionId);
|
|
16899
|
-
if (responses.length === 0 && sessionRuns.length === 0) return
|
|
17275
|
+
if (responses.length === 0 && sessionRuns.length === 0) return t("usageNoData");
|
|
16900
17276
|
let prompt = 0, completion = 0, total = 0, cacheHit = 0, cacheMiss = 0;
|
|
16901
17277
|
let mainTotal = 0, subTotal = 0;
|
|
16902
17278
|
for (const r of responses) {
|
|
@@ -16912,20 +17288,21 @@ var init_inspect = __esm({
|
|
|
16912
17288
|
}
|
|
16913
17289
|
const cacheRate = prompt > 0 ? (cacheHit / prompt * 100).toFixed(1) : "0.0";
|
|
16914
17290
|
const rounds = responses.length;
|
|
17291
|
+
const stopLabel = t("stopLabel");
|
|
16915
17292
|
const lines = [
|
|
16916
|
-
|
|
16917
|
-
|
|
16918
|
-
|
|
16919
|
-
|
|
17293
|
+
t("usageHead")(rounds),
|
|
17294
|
+
t("usageTokens")(fmt(prompt), fmt(completion), fmt(total)),
|
|
17295
|
+
t("usageCache")(fmt(cacheHit), cacheRate, fmt(cacheMiss)),
|
|
17296
|
+
t("usageSplit")(fmt(mainTotal), fmt(subTotal))
|
|
16920
17297
|
];
|
|
16921
17298
|
if (sessionRuns.length > 0) {
|
|
16922
17299
|
const ss = summarizeUsage(sessionRuns);
|
|
16923
17300
|
const abortedPct = ss.mainRuns > 0 ? Math.round(ss.stopReasons.aborted / ss.mainRuns * 100) : 0;
|
|
16924
17301
|
const avgRounds = ss.mainRuns > 0 ? (ss.mainRounds / ss.mainRuns).toFixed(1) : "0";
|
|
16925
|
-
lines.push(
|
|
17302
|
+
lines.push(t("usageSessionRuns")(ss.mainRuns, ss.mainRounds, avgRounds, ss.stopReasons.aborted, abortedPct));
|
|
16926
17303
|
for (const r of sessionRuns.filter((x) => x.depth === 0).slice(-6)) {
|
|
16927
|
-
const tools = topTools(r.tools, 3).map(([n, c]) => `${n}\xD7${c}`).join(" ") || "
|
|
16928
|
-
lines.push(
|
|
17304
|
+
const tools = topTools(r.tools, 3).map(([n, c]) => `${n}\xD7${c}`).join(" ") || t("usageNoTools");
|
|
17305
|
+
lines.push(t("usageRunLine")(String(r.ts).slice(5, 16).replace("T", " "), r.rounds, fmtK(r.totalTokens ?? 0), stopLabel[r.stopReason] ?? r.stopReason, tools));
|
|
16929
17306
|
}
|
|
16930
17307
|
}
|
|
16931
17308
|
const weekRecords = await readUsageRecords(7);
|
|
@@ -16934,10 +17311,10 @@ var init_inspect = __esm({
|
|
|
16934
17311
|
const weekHit = week.promptTokens > 0 ? (week.cachedTokens / week.promptTokens * 100).toFixed(1) : "0.0";
|
|
16935
17312
|
const weekAbort = week.mainRuns > 0 ? Math.round(week.stopReasons.aborted / week.mainRuns * 100) : 0;
|
|
16936
17313
|
const weekAvg = week.mainRuns > 0 ? (week.mainRounds / week.mainRuns).toFixed(1) : "0";
|
|
16937
|
-
const tools = topTools(week.tools, 4).map(([n, c]) => `${n}\xD7${c}`)
|
|
17314
|
+
const tools = topTools(week.tools, 4).map(([n, c]) => `${n}\xD7${c}`);
|
|
16938
17315
|
lines.push(
|
|
16939
|
-
|
|
16940
|
-
|
|
17316
|
+
t("usageWeek")(week.mainRuns, week.mainRounds, weekAvg, weekAbort, fmtK(week.totalTokens), weekHit),
|
|
17317
|
+
t("usageTopTools")(tools)
|
|
16941
17318
|
);
|
|
16942
17319
|
const bySession = /* @__PURE__ */ new Map();
|
|
16943
17320
|
let weekCost = 0, weekSaved = 0, pricedRuns = 0;
|
|
@@ -16953,14 +17330,15 @@ var init_inspect = __esm({
|
|
|
16953
17330
|
if (pricedRuns > 0) {
|
|
16954
17331
|
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
17332
|
const unpaid = week.runs - pricedRuns;
|
|
16956
|
-
lines.push(
|
|
16957
|
-
if (tops) lines.push(
|
|
17333
|
+
lines.push(t("usageWeekCost")(weekCost.toFixed(3), weekSaved.toFixed(3), unpaid));
|
|
17334
|
+
if (tops) lines.push(t("usageTopSessions")(tops));
|
|
16958
17335
|
}
|
|
16959
17336
|
}
|
|
16960
|
-
lines.push(
|
|
17337
|
+
lines.push(t("usageTip"));
|
|
16961
17338
|
return lines.join("\n");
|
|
16962
17339
|
};
|
|
16963
|
-
inspectContext = async (sessionId) => {
|
|
17340
|
+
inspectContext = async (sessionId, locale2 = "zh") => {
|
|
17341
|
+
const t = obsT(locale2);
|
|
16964
17342
|
const trace = await readTrace(sessionId);
|
|
16965
17343
|
let lastPrompt;
|
|
16966
17344
|
for (let i = trace.length - 1; i >= 0; i--) {
|
|
@@ -16988,38 +17366,40 @@ var init_inspect = __esm({
|
|
|
16988
17366
|
const threshold = Math.round(window * ratio);
|
|
16989
17367
|
const fillRate = lastPrompt ? (lastPrompt / window * 100).toFixed(1) : null;
|
|
16990
17368
|
return [
|
|
16991
|
-
|
|
16992
|
-
|
|
16993
|
-
|
|
16994
|
-
|
|
16995
|
-
|
|
16996
|
-
|
|
16997
|
-
|
|
16998
|
-
|
|
17369
|
+
t("ctxHead"),
|
|
17370
|
+
t("ctxWindow")(fmt(window), fmt(threshold), ratio, appConfig.KEEP_RECENT_UNITS),
|
|
17371
|
+
t("ctxLastPrompt")(lastPrompt ? fmt(lastPrompt) : null, fillRate),
|
|
17372
|
+
t("ctxArchived")(archived),
|
|
17373
|
+
t("ctxEntities")(archivedEntities),
|
|
17374
|
+
t("ctxRecall")(getRecallHitCount(sessionId)),
|
|
17375
|
+
t("ctxSidecar")(sidecarCount),
|
|
17376
|
+
t("ctxTip")(Math.round(ratio * 100))
|
|
16999
17377
|
].join("\n");
|
|
17000
17378
|
};
|
|
17001
|
-
inspectPermissions = () => {
|
|
17379
|
+
inspectPermissions = (locale2 = "zh") => {
|
|
17380
|
+
const t = obsT(locale2);
|
|
17002
17381
|
const r = listPermissionRules();
|
|
17003
17382
|
const total = r.allow.length + r.deny.length + r.ask.length;
|
|
17004
|
-
if (total === 0) return
|
|
17383
|
+
if (total === 0) return t("permEmpty");
|
|
17005
17384
|
const render2 = (label, kind, icon) => {
|
|
17006
17385
|
const list = r[kind];
|
|
17007
|
-
if (list.length === 0) return ` ${icon} ${label}: (
|
|
17008
|
-
return `
|
|
17009
|
-
` + list.map((x) => ` ${x.toolName}${x.raw && x.raw !== x.toolName ? ` \u2190 ${x.raw}` : ""}`).join("\n");
|
|
17386
|
+
if (list.length === 0) return ` ${icon} ${label}: ${t("permNone")}`;
|
|
17387
|
+
return t("permGroup")(icon, label, list.length) + "\n" + list.map((x) => ` ${x.toolName}${x.raw && x.raw !== x.toolName ? ` \u2190 ${x.raw}` : ""}`).join("\n");
|
|
17010
17388
|
};
|
|
17011
|
-
return [
|
|
17389
|
+
return [t("permHead"), render2("Deny", "deny", "\u{1F6AB}"), render2("Ask", "ask", "\u2753"), render2("Allow", "allow", "\u2705")].join("\n");
|
|
17012
17390
|
};
|
|
17013
|
-
inspectMcp = async () => {
|
|
17391
|
+
inspectMcp = async (locale2 = "zh") => {
|
|
17392
|
+
const t = obsT(locale2);
|
|
17014
17393
|
const clients2 = await listMcpClients();
|
|
17015
|
-
if (clients2.length === 0) return
|
|
17016
|
-
const lines = clients2.map((c) =>
|
|
17394
|
+
if (clients2.length === 0) return t("mcpEmpty");
|
|
17395
|
+
const lines = clients2.map((c) => t("mcpLine")(c.serverName, c.toolCount >= 0 ? t("mcpToolCount")(c.toolCount) : t("mcpToolCountFail")));
|
|
17017
17396
|
const totalTools = clients2.reduce((s, c) => s + (c.toolCount > 0 ? c.toolCount : 0), 0);
|
|
17018
|
-
return [
|
|
17397
|
+
return [t("mcpHead")(clients2.length, totalTools), ...lines].join("\n");
|
|
17019
17398
|
};
|
|
17020
|
-
inspectHooks = () => {
|
|
17399
|
+
inspectHooks = (locale2 = "zh") => {
|
|
17400
|
+
const t = obsT(locale2);
|
|
17021
17401
|
const hooks = listHooks();
|
|
17022
|
-
if (hooks.length === 0) return
|
|
17402
|
+
if (hooks.length === 0) return t("hooksEmpty");
|
|
17023
17403
|
const byEvent = /* @__PURE__ */ new Map();
|
|
17024
17404
|
for (const h of hooks) {
|
|
17025
17405
|
const arr = byEvent.get(h.event) ?? [];
|
|
@@ -17027,21 +17407,21 @@ var init_inspect = __esm({
|
|
|
17027
17407
|
byEvent.set(h.event, arr);
|
|
17028
17408
|
}
|
|
17029
17409
|
const lines = [...byEvent.entries()].map(([evt, arr]) => {
|
|
17030
|
-
return
|
|
17031
|
-
` + arr.map((h) => ` matcher=${h.matcher} source=${h.source}${h.onError ? ` onError=${h.onError}` : ""}`).join("\n");
|
|
17410
|
+
return t("hooksGroup")(evt, arr.length) + "\n" + arr.map((h) => ` matcher=${h.matcher} source=${h.source}${h.onError ? ` onError=${h.onError}` : ""}`).join("\n");
|
|
17032
17411
|
});
|
|
17033
|
-
return [
|
|
17412
|
+
return [t("hooksHead")(hooks.length), ...lines].join("\n");
|
|
17034
17413
|
};
|
|
17035
|
-
inspectDebug = (sessionId) => {
|
|
17414
|
+
inspectDebug = (sessionId, locale2 = "zh") => {
|
|
17415
|
+
const t = obsT(locale2);
|
|
17036
17416
|
return [
|
|
17037
|
-
|
|
17038
|
-
` session: ${sessionId || "
|
|
17417
|
+
t("dbgHead"),
|
|
17418
|
+
` session: ${sessionId || t("dbgSessionNone")}`,
|
|
17039
17419
|
` cwd: ${CWD}`,
|
|
17040
|
-
|
|
17420
|
+
t("dbgModels")(MODEL_NAME, AUX_MODEL_NAME ?? t("dbgAuxNone")),
|
|
17041
17421
|
` dataDir: ${appConfig.dataDir}`,
|
|
17042
|
-
|
|
17043
|
-
|
|
17044
|
-
|
|
17422
|
+
t("dbgParallel")(appConfig.parallelSafeTools ? t("dbgOn") : t("dbgOff"), appConfig.workflowConcurrency, appConfig.workflowMaxSteps),
|
|
17423
|
+
t("dbgUndo")(appConfig.undoEnabled ? t("dbgOn") : t("dbgOff"), appConfig.searchProvider || t("dbgSearchAuto")),
|
|
17424
|
+
t("dbgPlatform")(process.version, process.platform)
|
|
17045
17425
|
].join("\n");
|
|
17046
17426
|
};
|
|
17047
17427
|
}
|
|
@@ -17340,54 +17720,49 @@ var init_App = __esm({
|
|
|
17340
17720
|
state.pushInfo(S.statusText(modelDisplay, state.getThinkingLevel(), state.getPlanMode(), getLocale(), CWD2));
|
|
17341
17721
|
return true;
|
|
17342
17722
|
case "/usage":
|
|
17343
|
-
state.pushInfo(await inspectUsage(state.sessionIdRef.current ?? ""));
|
|
17723
|
+
state.pushInfo(await inspectUsage(state.sessionIdRef.current ?? "", getLocale()));
|
|
17344
17724
|
return true;
|
|
17345
17725
|
case "/context":
|
|
17346
|
-
state.pushInfo(await inspectContext(state.sessionIdRef.current ?? ""));
|
|
17726
|
+
state.pushInfo(await inspectContext(state.sessionIdRef.current ?? "", getLocale()));
|
|
17347
17727
|
return true;
|
|
17348
17728
|
case "/permissions":
|
|
17349
|
-
state.pushInfo(inspectPermissions());
|
|
17729
|
+
state.pushInfo(inspectPermissions(getLocale()));
|
|
17350
17730
|
return true;
|
|
17351
17731
|
case "/mcp":
|
|
17352
|
-
state.pushInfo(await inspectMcp());
|
|
17732
|
+
state.pushInfo(await inspectMcp(getLocale()));
|
|
17353
17733
|
return true;
|
|
17354
17734
|
case "/hooks":
|
|
17355
|
-
state.pushInfo(inspectHooks());
|
|
17735
|
+
state.pushInfo(inspectHooks(getLocale()));
|
|
17356
17736
|
return true;
|
|
17357
17737
|
case "/trust": {
|
|
17358
17738
|
const trusted = await readTrustedDirs();
|
|
17359
17739
|
if (!arg) {
|
|
17360
17740
|
if (trusted.length === 0) {
|
|
17361
|
-
state.pushInfo(
|
|
17741
|
+
state.pushInfo(S.trustEmpty);
|
|
17362
17742
|
return true;
|
|
17363
17743
|
}
|
|
17364
17744
|
const list = trusted.map((d, i) => ` [${i}] ${d}`).join("\n");
|
|
17365
|
-
state.pushInfo(
|
|
17366
|
-
${list}
|
|
17367
|
-
|
|
17368
|
-
\u64A4\u9500\u540E\u9700\u91CD\u542F CLI \u751F\u6548\uFF08\u9879\u76EE\u7EA7\u914D\u7F6E\u4EC5\u5728\u542F\u52A8\u65F6\u52A0\u8F7D\uFF09\u3002`);
|
|
17745
|
+
state.pushInfo(S.trustList(list));
|
|
17369
17746
|
return true;
|
|
17370
17747
|
}
|
|
17371
17748
|
const idx = Number(arg);
|
|
17372
17749
|
const target = Number.isInteger(idx) && idx >= 0 && idx < trusted.length ? trusted[idx] : arg;
|
|
17373
17750
|
const removed = await untrustDir(target);
|
|
17374
|
-
state.pushInfo(removed ?
|
|
17375
|
-
\uFF08\u91CD\u542F CLI \u540E\u751F\u6548\u2014\u2014\u9879\u76EE\u7EA7\u914D\u7F6E\u4EC5\u5728\u542F\u52A8\u65F6\u52A0\u8F7D\uFF09` : `\u672A\u627E\u5230\u8BE5\u4FE1\u4EFB\u76EE\u5F55\uFF1A${target}`);
|
|
17751
|
+
state.pushInfo(removed ? S.trustRemoved(target) : S.trustNotFound(target));
|
|
17376
17752
|
return true;
|
|
17377
17753
|
}
|
|
17378
17754
|
case "/debug":
|
|
17379
|
-
state.pushInfo(inspectDebug(state.sessionIdRef.current ?? ""));
|
|
17755
|
+
state.pushInfo(inspectDebug(state.sessionIdRef.current ?? "", getLocale()));
|
|
17380
17756
|
return true;
|
|
17381
17757
|
case "/archive": {
|
|
17382
17758
|
const s = state.getArchivedSummary();
|
|
17383
|
-
state.pushInfo(s ?
|
|
17384
|
-
${s}` : "\u672C\u4F1A\u8BDD\u542F\u52A8\u4EE5\u6765\u5C1A\u672A\u53D1\u751F\u8FC7\u538B\u7F29\uFF08\u6458\u8981\u4EC5\u4FDD\u7559\u8FD0\u884C\u65F6\u6700\u8FD1\u4E00\u6B21\uFF09\u3002");
|
|
17759
|
+
state.pushInfo(s ? S.archiveSummary(s) : S.archiveNone);
|
|
17385
17760
|
return true;
|
|
17386
17761
|
}
|
|
17387
17762
|
case "/plan": {
|
|
17388
17763
|
const on = !state.getPlanMode();
|
|
17389
17764
|
state.setPlanMode(on);
|
|
17390
|
-
state.pushInfo(
|
|
17765
|
+
state.pushInfo(S.planModeSet(on));
|
|
17391
17766
|
return true;
|
|
17392
17767
|
}
|
|
17393
17768
|
case "/budget": {
|
|
@@ -17395,27 +17770,27 @@ ${s}` : "\u672C\u4F1A\u8BDD\u542F\u52A8\u4EE5\u6765\u5C1A\u672A\u53D1\u751F\u8FC
|
|
|
17395
17770
|
if (!v) {
|
|
17396
17771
|
const b = state.getBudgetYuan();
|
|
17397
17772
|
const last = state.getLastRunCostYuan();
|
|
17398
|
-
state.pushInfo(
|
|
17773
|
+
state.pushInfo(S.budgetView(b, last));
|
|
17399
17774
|
return true;
|
|
17400
17775
|
}
|
|
17401
17776
|
if (v === "off" || v === "0") {
|
|
17402
17777
|
state.setBudgetYuan(void 0);
|
|
17403
|
-
state.pushInfo(
|
|
17778
|
+
state.pushInfo(S.budgetOff);
|
|
17404
17779
|
return true;
|
|
17405
17780
|
}
|
|
17406
17781
|
const n = Number(v);
|
|
17407
17782
|
if (!Number.isFinite(n) || n <= 0) {
|
|
17408
|
-
state.pushInfo(
|
|
17783
|
+
state.pushInfo(S.budgetUsage);
|
|
17409
17784
|
return true;
|
|
17410
17785
|
}
|
|
17411
17786
|
state.setBudgetYuan(n);
|
|
17412
|
-
state.pushInfo(
|
|
17787
|
+
state.pushInfo(S.budgetSet(n));
|
|
17413
17788
|
return true;
|
|
17414
17789
|
}
|
|
17415
17790
|
case "/auto": {
|
|
17416
17791
|
const on = !state.getAutoMode();
|
|
17417
17792
|
state.setAutoMode(on);
|
|
17418
|
-
state.pushInfo(
|
|
17793
|
+
state.pushInfo(S.autoModeSet(on));
|
|
17419
17794
|
return true;
|
|
17420
17795
|
}
|
|
17421
17796
|
case "/model":
|
|
@@ -17435,15 +17810,15 @@ ${s}` : "\u672C\u4F1A\u8BDD\u542F\u52A8\u4EE5\u6765\u5C1A\u672A\u53D1\u751F\u8FC
|
|
|
17435
17810
|
case "/thinking": {
|
|
17436
17811
|
const lvl = arg.toLowerCase();
|
|
17437
17812
|
if (arg && lvl !== "off" && lvl !== "high" && lvl !== "max") {
|
|
17438
|
-
state.pushInfo(
|
|
17813
|
+
state.pushInfo(S.thinkingInvalid(arg));
|
|
17439
17814
|
return true;
|
|
17440
17815
|
}
|
|
17441
17816
|
if (!arg) {
|
|
17442
|
-
state.pushInfo(
|
|
17817
|
+
state.pushInfo(S.thinkingCurrent(state.getThinkingLevel()));
|
|
17443
17818
|
return true;
|
|
17444
17819
|
}
|
|
17445
17820
|
state.setThinkingLevel(lvl);
|
|
17446
|
-
state.pushInfo(
|
|
17821
|
+
state.pushInfo(S.thinkingSet(lvl));
|
|
17447
17822
|
return true;
|
|
17448
17823
|
}
|
|
17449
17824
|
case "/lang": {
|
|
@@ -17497,7 +17872,7 @@ ${listText}`);
|
|
|
17497
17872
|
};
|
|
17498
17873
|
const ensureEngine = async () => {
|
|
17499
17874
|
if (engineReadyFlag) return;
|
|
17500
|
-
state.pushInfo(
|
|
17875
|
+
state.pushInfo(S.engineLoading);
|
|
17501
17876
|
await engineReady;
|
|
17502
17877
|
};
|
|
17503
17878
|
const executeSlash = async (fullText) => {
|
|
@@ -17513,7 +17888,7 @@ ${listText}`);
|
|
|
17513
17888
|
await state.submit(text);
|
|
17514
17889
|
return;
|
|
17515
17890
|
}
|
|
17516
|
-
state.pushInfo(
|
|
17891
|
+
state.pushInfo(S.unknownCmd(name));
|
|
17517
17892
|
};
|
|
17518
17893
|
const onSubmit = async () => {
|
|
17519
17894
|
const v = inputRef.current.trim();
|
|
@@ -17793,7 +18168,7 @@ __export(batchRunner_exports, {
|
|
|
17793
18168
|
});
|
|
17794
18169
|
import fs49 from "fs";
|
|
17795
18170
|
import { spawn as spawn6 } from "child_process";
|
|
17796
|
-
var BATCH_EDIT_TOOLS, BATCH_DEFAULT_DENYLIST, ACCEPT_TIMEOUT_MIN, ACCEPT_TAIL_LINES, emit2, ts,
|
|
18171
|
+
var BATCH_EDIT_TOOLS, BATCH_DEFAULT_DENYLIST, ACCEPT_TIMEOUT_MIN, ACCEPT_TAIL_LINES, emit2, ts, runAcceptCommand, collectSessionCost, buildReport, runOneTask, parseWaitWindow, nowMinutes, sleep, waitUntilWindow, runBatchQueue;
|
|
17797
18172
|
var init_batchRunner = __esm({
|
|
17798
18173
|
"src/batchRunner.ts"() {
|
|
17799
18174
|
"use strict";
|
|
@@ -17807,6 +18182,8 @@ var init_batchRunner = __esm({
|
|
|
17807
18182
|
init_usageLog();
|
|
17808
18183
|
init_ticket();
|
|
17809
18184
|
init_queue();
|
|
18185
|
+
init_batchStrings();
|
|
18186
|
+
init_strings();
|
|
17810
18187
|
BATCH_EDIT_TOOLS = /* @__PURE__ */ new Set(["edit_file", "create_file", "write_file", "move_file", "notebook_edit"]);
|
|
17811
18188
|
BATCH_DEFAULT_DENYLIST = /* @__PURE__ */ new Set(["run_command", "delete_path"]);
|
|
17812
18189
|
ACCEPT_TIMEOUT_MIN = 10;
|
|
@@ -17815,14 +18192,8 @@ var init_batchRunner = __esm({
|
|
|
17815
18192
|
process.stdout.write(s + "\n");
|
|
17816
18193
|
};
|
|
17817
18194
|
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
18195
|
runAcceptCommand = async (cmd, cwd) => {
|
|
18196
|
+
const T = batchT(getLocale());
|
|
17826
18197
|
const isWin = process.platform === "win32";
|
|
17827
18198
|
return new Promise((resolve) => {
|
|
17828
18199
|
let child;
|
|
@@ -17835,7 +18206,7 @@ var init_batchRunner = __esm({
|
|
|
17835
18206
|
// 剔除 agent 自身凭证(同 run_command 红线)
|
|
17836
18207
|
});
|
|
17837
18208
|
} catch (e) {
|
|
17838
|
-
resolve({ code: null, output:
|
|
18209
|
+
resolve({ code: null, output: T.spawnFail(e?.message ?? e), timedOut: false });
|
|
17839
18210
|
return;
|
|
17840
18211
|
}
|
|
17841
18212
|
const chunks = [];
|
|
@@ -17851,15 +18222,15 @@ var init_batchRunner = __esm({
|
|
|
17851
18222
|
}, ACCEPT_TIMEOUT_MIN * 6e4);
|
|
17852
18223
|
child.on("error", (e) => {
|
|
17853
18224
|
clearTimeout(killer);
|
|
17854
|
-
resolve({ code: null, output:
|
|
18225
|
+
resolve({ code: null, output: T.execFail(e?.message ?? e), timedOut });
|
|
17855
18226
|
});
|
|
17856
18227
|
child.on("close", (code) => {
|
|
17857
18228
|
clearTimeout(killer);
|
|
17858
18229
|
const text = decodeProcessOutput(Buffer.concat(chunks)).trim();
|
|
17859
18230
|
const lines = text.split("\n");
|
|
17860
|
-
const tail = lines.length > ACCEPT_TAIL_LINES ?
|
|
18231
|
+
const tail = lines.length > ACCEPT_TAIL_LINES ? `${T.tailOmitted(lines.length - ACCEPT_TAIL_LINES)}
|
|
17861
18232
|
${lines.slice(-ACCEPT_TAIL_LINES).join("\n")}` : text;
|
|
17862
|
-
resolve({ code, output: tail ||
|
|
18233
|
+
resolve({ code, output: tail || T.noOutput, timedOut });
|
|
17863
18234
|
});
|
|
17864
18235
|
});
|
|
17865
18236
|
};
|
|
@@ -17880,19 +18251,10 @@ ${lines.slice(-ACCEPT_TAIL_LINES).join("\n")}` : text;
|
|
|
17880
18251
|
if (c.costYuan === null) c.partialPrice = false;
|
|
17881
18252
|
return c;
|
|
17882
18253
|
};
|
|
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
18254
|
buildReport = (args) => {
|
|
17894
18255
|
const { id, ticket, status, budgetTruncated, cost, receipt, finalText, accept, deniedTools, diff, wt } = args;
|
|
17895
|
-
const
|
|
18256
|
+
const T = batchT(getLocale());
|
|
18257
|
+
const budgetNote = budgetTruncated ? T.budgetTruncNote : "";
|
|
17896
18258
|
return `---
|
|
17897
18259
|
id: ${id}
|
|
17898
18260
|
title: ${ticket.title}
|
|
@@ -17901,43 +18263,42 @@ cost-yuan: ${cost.costYuan !== null ? cost.costYuan.toFixed(4) : "null"}
|
|
|
17901
18263
|
rounds: ${cost.rounds}
|
|
17902
18264
|
budget-truncated: ${budgetTruncated}
|
|
17903
18265
|
session: batch-${id}
|
|
17904
|
-
worktree: ${wt?.path ??
|
|
17905
|
-
branch: ${wt?.branch ??
|
|
18266
|
+
worktree: ${wt?.path ?? T.notCreated}
|
|
18267
|
+
branch: ${wt?.branch ?? T.notCreated}
|
|
17906
18268
|
---
|
|
17907
18269
|
|
|
17908
|
-
|
|
18270
|
+
${T.reportTitle(ticket.title)}
|
|
17909
18271
|
|
|
17910
|
-
|
|
17911
|
-
|
|
17912
|
-
|
|
17913
|
-
${args.errorMessage ?
|
|
17914
|
-
|
|
17915
|
-
## \u4EFB\u52A1
|
|
18272
|
+
${T.statusEntry(`${T.statusLabel(status)}${budgetNote}`)}
|
|
18273
|
+
${T.costEntry(T.costSummary(cost))}
|
|
18274
|
+
${T.receiptEntry(receipt ? T.receiptLine(receipt) : T.noReceipt)}
|
|
18275
|
+
${args.errorMessage ? T.errorEntry(args.errorMessage) : ""}
|
|
18276
|
+
${T.taskH}
|
|
17916
18277
|
|
|
17917
18278
|
${ticket.body}
|
|
17918
18279
|
|
|
17919
|
-
|
|
18280
|
+
${T.finalH}
|
|
17920
18281
|
|
|
17921
|
-
${finalText.trim() ||
|
|
18282
|
+
${finalText.trim() || T.noFinal}
|
|
17922
18283
|
|
|
17923
|
-
|
|
18284
|
+
${T.acceptH}
|
|
17924
18285
|
${accept ? `
|
|
17925
|
-
|
|
18286
|
+
${T.acceptCmdLine(accept.cmd, accept.code)}${accept.timedOut ? T.acceptTimeoutSuffix : ""}
|
|
17926
18287
|
|
|
17927
|
-
|
|
18288
|
+
${T.acceptTail}
|
|
17928
18289
|
|
|
17929
18290
|
\`\`\`
|
|
17930
18291
|
${accept.output}
|
|
17931
18292
|
\`\`\`
|
|
17932
|
-
` :
|
|
18293
|
+
` : T.noAccept}
|
|
17933
18294
|
|
|
17934
|
-
|
|
18295
|
+
${T.deniedH}
|
|
17935
18296
|
|
|
17936
|
-
${deniedTools.length === 0 ?
|
|
18297
|
+
${deniedTools.length === 0 ? T.deniedNone : deniedTools.map((d) => `- **${d.tool}** \u2014 ${d.detail}`).join("\n")}
|
|
17937
18298
|
|
|
17938
|
-
|
|
18299
|
+
${T.diffH}
|
|
17939
18300
|
|
|
17940
|
-
|
|
18301
|
+
${T.diffNote(wt?.branch ?? "?", wt?.path ?? "?")}
|
|
17941
18302
|
|
|
17942
18303
|
\`\`\`\`\`diff
|
|
17943
18304
|
${diff}
|
|
@@ -17945,8 +18306,9 @@ ${diff}
|
|
|
17945
18306
|
`;
|
|
17946
18307
|
};
|
|
17947
18308
|
runOneTask = async (task) => {
|
|
18309
|
+
const T = batchT(getLocale());
|
|
17948
18310
|
const source = await fs49.promises.readFile(task.path, "utf-8");
|
|
17949
|
-
const parsed = parseBatchTicket(source);
|
|
18311
|
+
const parsed = parseBatchTicket(source, getLocale());
|
|
17950
18312
|
if (!parsed.ok) {
|
|
17951
18313
|
const cost2 = { rounds: 0, mainRounds: 0, subRuns: 0, promptTokens: 0, completionTokens: 0, cachedTokens: 0, costYuan: 0, partialPrice: false, durationMs: 0 };
|
|
17952
18314
|
await finishTicket(task.id, `---
|
|
@@ -17955,17 +18317,17 @@ title: ${task.id}
|
|
|
17955
18317
|
status: rejected
|
|
17956
18318
|
---
|
|
17957
18319
|
|
|
17958
|
-
|
|
18320
|
+
${T.rejectedTitle}
|
|
17959
18321
|
|
|
17960
18322
|
${parsed.error}`);
|
|
17961
|
-
emit2(
|
|
18323
|
+
emit2(T.ticketRejected(task.id, parsed.error));
|
|
17962
18324
|
return { status: "rejected", cost: cost2, budgetTruncated: false };
|
|
17963
18325
|
}
|
|
17964
18326
|
const t = parsed.ticket;
|
|
17965
18327
|
const sessionId = `batch-${task.id}`;
|
|
17966
18328
|
const timeoutMin = t.timeoutMin ?? 30;
|
|
17967
18329
|
emit2(`\u25B6 [${task.id}] ${t.title}`);
|
|
17968
|
-
emit2(
|
|
18330
|
+
emit2(T.taskMeta(t.budgetYuan, timeoutMin, t.accept));
|
|
17969
18331
|
const unlocked = new Set(t.tools ?? []);
|
|
17970
18332
|
const denySchemas = new Set([...BATCH_DEFAULT_DENYLIST].filter((n) => !unlocked.has(n)));
|
|
17971
18333
|
const toolSchemas = agentTools.filter((x) => !denySchemas.has(x?.function?.name));
|
|
@@ -17975,7 +18337,7 @@ ${parsed.error}`);
|
|
|
17975
18337
|
try {
|
|
17976
18338
|
wt = await createWorktree(sessionId, task.id);
|
|
17977
18339
|
} catch (e) {
|
|
17978
|
-
const msg =
|
|
18340
|
+
const msg = T.wtCreateFail(e?.message ?? e);
|
|
17979
18341
|
const cost2 = await collectSessionCost(sessionId);
|
|
17980
18342
|
await finishTicket(task.id, buildReport({
|
|
17981
18343
|
id: task.id,
|
|
@@ -17987,7 +18349,7 @@ ${parsed.error}`);
|
|
|
17987
18349
|
finalText: "",
|
|
17988
18350
|
accept: null,
|
|
17989
18351
|
deniedTools: [],
|
|
17990
|
-
diff:
|
|
18352
|
+
diff: T.diffNone,
|
|
17991
18353
|
wt: null,
|
|
17992
18354
|
errorMessage: msg
|
|
17993
18355
|
}));
|
|
@@ -17996,7 +18358,7 @@ ${parsed.error}`);
|
|
|
17996
18358
|
}
|
|
17997
18359
|
setSessionWorktree(sessionId, wt);
|
|
17998
18360
|
const ac = new AbortController();
|
|
17999
|
-
const timer = setTimeout(() => ac.abort(new Error(
|
|
18361
|
+
const timer = setTimeout(() => ac.abort(new Error(T.timeoutAbort(timeoutMin))), timeoutMin * 6e4);
|
|
18000
18362
|
let receipt;
|
|
18001
18363
|
let finalText = "";
|
|
18002
18364
|
let agentError;
|
|
@@ -18009,7 +18371,7 @@ ${parsed.error}`);
|
|
|
18009
18371
|
if (evt?.type === "text.delta") finalText += evt.text;
|
|
18010
18372
|
else if (evt?.type === "text.reset") finalText = "";
|
|
18011
18373
|
else if (evt?.type === "final") finalText = evt.text || finalText;
|
|
18012
|
-
else if (evt?.type === "round.start") emit2(
|
|
18374
|
+
else if (evt?.type === "round.start") emit2(T.roundLine(ts(), evt.round));
|
|
18013
18375
|
},
|
|
18014
18376
|
ac.signal,
|
|
18015
18377
|
{
|
|
@@ -18037,15 +18399,15 @@ ${parsed.error}`);
|
|
|
18037
18399
|
let accept = null;
|
|
18038
18400
|
if (agentError) {
|
|
18039
18401
|
status = "error";
|
|
18040
|
-
emit2(
|
|
18402
|
+
emit2(T.agentErrorLine(task.id, agentError));
|
|
18041
18403
|
} else if (timedOut) {
|
|
18042
18404
|
status = "timeout";
|
|
18043
|
-
emit2(
|
|
18405
|
+
emit2(T.timeoutLine(task.id, timeoutMin));
|
|
18044
18406
|
} else {
|
|
18045
18407
|
const r = await runAcceptCommand(t.accept, wt.path);
|
|
18046
18408
|
accept = { cmd: t.accept, code: r.code, output: r.output, timedOut: r.timedOut };
|
|
18047
18409
|
status = r.code === 0 && !r.timedOut ? "passed" : "accept-failed";
|
|
18048
|
-
emit2(
|
|
18410
|
+
emit2(T.acceptLine(status === "passed", task.id, r.code) + (r.timedOut ? T.acceptKilledSuffix : ""));
|
|
18049
18411
|
}
|
|
18050
18412
|
await killBackgroundTasksUnder(wt.path).catch(() => {
|
|
18051
18413
|
});
|
|
@@ -18065,8 +18427,8 @@ ${parsed.error}`);
|
|
|
18065
18427
|
wt,
|
|
18066
18428
|
errorMessage: agentError
|
|
18067
18429
|
}));
|
|
18068
|
-
emit2(` ${
|
|
18069
|
-
emit2(
|
|
18430
|
+
emit2(` ${T.statusLabel(status)} \xB7 ${T.costSummary(cost)}`);
|
|
18431
|
+
emit2(T.artifactLine(wt.path, wt.branch));
|
|
18070
18432
|
return { status, cost, budgetTruncated };
|
|
18071
18433
|
};
|
|
18072
18434
|
parseWaitWindow = (s) => {
|
|
@@ -18084,14 +18446,15 @@ ${parsed.error}`);
|
|
|
18084
18446
|
};
|
|
18085
18447
|
sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
18086
18448
|
waitUntilWindow = async (w) => {
|
|
18449
|
+
const T = batchT(getLocale());
|
|
18087
18450
|
const now = nowMinutes();
|
|
18088
18451
|
let waitMin = 0;
|
|
18089
18452
|
if (now >= w.startMin && now < w.endMin) {
|
|
18090
|
-
emit2(
|
|
18453
|
+
emit2(T.inWindowNow(`${Math.floor(now / 60)}:${String(now % 60).padStart(2, "0")}`));
|
|
18091
18454
|
return;
|
|
18092
18455
|
}
|
|
18093
18456
|
waitMin = now < w.startMin ? w.startMin - now : 24 * 60 - now + w.startMin;
|
|
18094
|
-
emit2(
|
|
18457
|
+
emit2(T.waitWindowWait(Math.floor(waitMin / 60), waitMin % 60));
|
|
18095
18458
|
while (waitMin > 0) {
|
|
18096
18459
|
const chunkMin = Math.min(waitMin, 30);
|
|
18097
18460
|
await sleep(chunkMin * 6e4);
|
|
@@ -18099,14 +18462,15 @@ ${parsed.error}`);
|
|
|
18099
18462
|
}
|
|
18100
18463
|
};
|
|
18101
18464
|
runBatchQueue = async (opts) => {
|
|
18465
|
+
const T = batchT(getLocale());
|
|
18102
18466
|
const window = parseWaitWindow(opts?.waitWindow);
|
|
18103
18467
|
if (opts?.waitWindow && !window) {
|
|
18104
|
-
emit2(
|
|
18468
|
+
emit2(T.waitWindowInvalid(opts.waitWindow));
|
|
18105
18469
|
process.exitCode = 2;
|
|
18106
18470
|
return;
|
|
18107
18471
|
}
|
|
18108
18472
|
if (window) await waitUntilWindow(window);
|
|
18109
|
-
const lock = await acquireRunLock();
|
|
18473
|
+
const lock = await acquireRunLock(getLocale());
|
|
18110
18474
|
if (!lock.ok) {
|
|
18111
18475
|
emit2(`\u{1F6AB} ${lock.error}`);
|
|
18112
18476
|
process.exitCode = 1;
|
|
@@ -18125,7 +18489,7 @@ ${parsed.error}`);
|
|
|
18125
18489
|
total++;
|
|
18126
18490
|
const r = await runOneTask(task);
|
|
18127
18491
|
if (r.status === "passed") passed++;
|
|
18128
|
-
else failedIds.push(`[${task.id}] ${
|
|
18492
|
+
else failedIds.push(`[${task.id}] ${T.statusLabel(r.status)}`);
|
|
18129
18493
|
if (r.cost.costYuan !== null) {
|
|
18130
18494
|
costSum += r.cost.costYuan;
|
|
18131
18495
|
costTasks++;
|
|
@@ -18135,16 +18499,16 @@ ${parsed.error}`);
|
|
|
18135
18499
|
await releaseRunLock();
|
|
18136
18500
|
}
|
|
18137
18501
|
if (total === 0) {
|
|
18138
|
-
emit2(
|
|
18502
|
+
emit2(T.runnerQueueEmpty);
|
|
18139
18503
|
return;
|
|
18140
18504
|
}
|
|
18141
18505
|
emit2("");
|
|
18142
18506
|
emit2("\u2501".repeat(56));
|
|
18143
|
-
emit2(
|
|
18144
|
-
emit2(
|
|
18145
|
-
if (failedIds.length > 0) emit2(
|
|
18507
|
+
emit2(T.summaryDone(total, passed, `${Math.round((Date.now() - startedAt) / 6e3) / 10}`));
|
|
18508
|
+
emit2(costTasks > 0 ? T.summaryCost(costSum.toFixed(4), costTasks) : T.summaryCostFree);
|
|
18509
|
+
if (failedIds.length > 0) emit2(`${T.failedHead}
|
|
18146
18510
|
${failedIds.join("\n ")}`);
|
|
18147
|
-
emit2(
|
|
18511
|
+
emit2(T.artifactsDir);
|
|
18148
18512
|
};
|
|
18149
18513
|
}
|
|
18150
18514
|
});
|