deepseeker-code 1.0.42 → 1.0.45
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 +4 -0
- package/dist/cli.mjs +263 -101
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -70,12 +70,16 @@ deepseeker-code --plan
|
|
|
70
70
|
| `/lang <zh\|en>` | 切换语言 |
|
|
71
71
|
| `/output-style <名称>` | 切换输出风格(人格) |
|
|
72
72
|
| `/sessions` | 列出并续接历史会话 |
|
|
73
|
+
| `/fork` | 从当前会话某轮回复处分叉出新会话 |
|
|
73
74
|
| `/clear` | 新会话 |
|
|
74
75
|
| `/status` / `/usage` / `/context` | 查看状态 / 用量 / 上下文 |
|
|
75
76
|
| `/permissions` / `/mcp` / `/hooks` | 查看已加载的权限规则 / MCP / Hooks |
|
|
77
|
+
| `/trust` | 管理已信任目录(列出 / 撤销) |
|
|
76
78
|
| `/debug` | 调试信息 |
|
|
77
79
|
| `/exit` / `/quit` | 退出 |
|
|
78
80
|
|
|
81
|
+
> 菜单超出屏高时随选中项滚动(底栏显示 `n/m 条`);`commands/` 目录下的自定义命令引擎就绪后自动并入菜单。启动时界面先行渲染,引擎(MCP/skills/命令)后台加载,首次提交前自动等待就绪。
|
|
82
|
+
|
|
79
83
|
**快捷键**:`Ctrl+C` 退出 · `Esc` 中止/清输入 · `Ctrl+G` 中止当前轮 · `Ctrl+T` 展开/收起思考 · 模态/菜单 `↑↓ Enter`。
|
|
80
84
|
|
|
81
85
|
---
|
package/dist/cli.mjs
CHANGED
|
@@ -569,7 +569,7 @@ import { randomUUID } from "node:crypto";
|
|
|
569
569
|
import fs from "fs/promises";
|
|
570
570
|
import { execFile } from "node:child_process";
|
|
571
571
|
import { promisify } from "node:util";
|
|
572
|
-
var getFileName, createUUID, SAFE_SESSION_ID_RE, isSafeSessionId, assertSafeSessionId, readJSONFile, atomicWriteJSON, createSemaphore, injectMarkedBlock, decodeProcessOutput, execFileSmart;
|
|
572
|
+
var getFileName, createUUID, SAFE_SESSION_ID_RE, isSafeSessionId, assertSafeSessionId, detectTextLocale, readJSONFile, atomicWriteJSON, createSemaphore, injectMarkedBlock, decodeProcessOutput, execFileSmart;
|
|
573
573
|
var init_common = __esm({
|
|
574
574
|
"../core/src/common/index.ts"() {
|
|
575
575
|
"use strict";
|
|
@@ -592,6 +592,15 @@ var init_common = __esm({
|
|
|
592
592
|
throw new Error(`\u{1F6D1} [SECURITY] \u975E\u6CD5 ${label}: ${JSON.stringify(sessionId.slice(0, 48))}\uFF08\u4EC5\u5141\u8BB8\u5B57\u6BCD/\u6570\u5B57/\u4E0B\u5212\u7EBF/\u8FDE\u5B57\u7B26\uFF09`);
|
|
593
593
|
}
|
|
594
594
|
};
|
|
595
|
+
detectTextLocale = (text) => {
|
|
596
|
+
const stripped = (text || "").replace(/```[\s\S]*?```/g, " ").replace(/`[^`]*`/g, " ").replace(/\s+/g, " ");
|
|
597
|
+
const cjk = (stripped.match(/[㐀-䶿一-鿿]/g) || []).length;
|
|
598
|
+
const latin = (stripped.match(/[A-Za-z]/g) || []).length;
|
|
599
|
+
if (cjk === 0 && latin === 0) return null;
|
|
600
|
+
if (cjk === 0) return "en";
|
|
601
|
+
if (latin === 0) return "zh";
|
|
602
|
+
return cjk / (cjk + latin) >= 0.2 ? "zh" : "en";
|
|
603
|
+
};
|
|
595
604
|
readJSONFile = async (file, fallback = null) => {
|
|
596
605
|
try {
|
|
597
606
|
const raw = await fs.readFile(file, "utf-8");
|
|
@@ -2805,12 +2814,13 @@ task_id: ${taskId}
|
|
|
2805
2814
|
type: "function",
|
|
2806
2815
|
function: {
|
|
2807
2816
|
name: "get_background_output",
|
|
2808
|
-
description: "\u67E5\u770B\u6307\u5B9A\u540E\u53F0\u4EFB\u52A1\u7684\u6700\u8FD1\u8F93\u51FA\u65E5\u5FD7\u4E0E\u8FD0\u884C\u72B6\u6001\uFF08running/exited/killed + \u9000\u51FA\u7801\uFF09\u3002\u7EAF\u8BFB\uFF0C\u514D\u5BA1\u6279\u3002\u7528\u4E8E\u786E\u8BA4 dev server \u662F\u5426\u542F\u52A8\u6210\u529F\u3001\u67E5\u770B\u62A5\u9519\u7B49\u3002",
|
|
2817
|
+
description: "\u67E5\u770B\u6307\u5B9A\u540E\u53F0\u4EFB\u52A1\u7684\u6700\u8FD1\u8F93\u51FA\u65E5\u5FD7\u4E0E\u8FD0\u884C\u72B6\u6001\uFF08running/exited/killed + \u9000\u51FA\u7801\uFF09\u3002\u7EAF\u8BFB\uFF0C\u514D\u5BA1\u6279\u3002\u7528\u4E8E\u786E\u8BA4 dev server \u662F\u5426\u542F\u52A8\u6210\u529F\u3001\u67E5\u770B\u62A5\u9519\u7B49\u3002\u7B49\u957F\u4EFB\u52A1\uFF08\u6784\u5EFA/\u6D4B\u8BD5\uFF09\u8DD1\u5B8C\uFF1A\u5E26 wait_seconds \u963B\u585E\u7B49\u5F85\u4EFB\u52A1\u9000\u51FA\u540E\u518D\u8FD4\u56DE\uFF08\u4ECD\u5728\u8DD1\u5219\u7B49\u5230\u8D85\u65F6\u8FD4\u56DE\u5F53\u524D\u72B6\u6001\uFF09\u2014\u2014\u7528\u5B83\u7B49\uFF0C\u4E0D\u8981\u4E0D\u5E26 wait \u53CD\u590D\u8F6E\u8BE2\u67E5\u8BE2\u3002",
|
|
2809
2818
|
parameters: {
|
|
2810
2819
|
type: "object",
|
|
2811
2820
|
properties: {
|
|
2812
2821
|
task_id: { type: "string", description: "run_in_background \u8FD4\u56DE\u7684 task_id" },
|
|
2813
|
-
tail_lines: { type: "number", description: "\u53EA\u8FD4\u56DE\u6700\u540E N \u884C\u65E5\u5FD7\uFF08\u9ED8\u8BA4 50\uFF0C\u907F\u514D\u4E00\u6B21\u704C\u5165\u8FC7\u591A\uFF09" }
|
|
2822
|
+
tail_lines: { type: "number", description: "\u53EA\u8FD4\u56DE\u6700\u540E N \u884C\u65E5\u5FD7\uFF08\u9ED8\u8BA4 50\uFF0C\u907F\u514D\u4E00\u6B21\u704C\u5165\u8FC7\u591A\uFF09" },
|
|
2823
|
+
wait_seconds: { type: "number", description: "\u963B\u585E\u7B49\u5F85\u4EFB\u52A1\u9000\u51FA\uFF08\u6216\u5230\u8FBE\u6B64\u65F6\u957F\uFF09\u540E\u518D\u8FD4\u56DE\uFF0C\u4E0A\u9650 120 \u79D2\uFF1B\u4EFB\u52A1\u5DF2\u5728\u8DD1\u4E14\u9700\u8981\u7B49\u7ED3\u679C\u65F6\u4F7F\u7528\uFF0C\u4E0D\u9700\u8981\u7B49\u5C31\u7701\u7565" }
|
|
2814
2824
|
},
|
|
2815
2825
|
required: ["task_id"]
|
|
2816
2826
|
},
|
|
@@ -2821,6 +2831,13 @@ task_id: ${taskId}
|
|
|
2821
2831
|
if (!task || task.sessionId !== ctx?.sessionId) {
|
|
2822
2832
|
return `\u274C [\u67E5\u8BE2\u5931\u8D25]\uFF1A\u672A\u627E\u5230 task_id=${args.task_id}\uFF08\u53EF\u80FD\u5DF2\u968F\u670D\u52A1\u91CD\u542F\u4E22\u5931\uFF0C\u6216\u4E0D\u5C5E\u4E8E\u5F53\u524D\u4F1A\u8BDD\uFF09\u3002`;
|
|
2823
2833
|
}
|
|
2834
|
+
const waitMs = Math.min(Math.max(0, args.wait_seconds ?? 0), 120) * 1e3;
|
|
2835
|
+
if (waitMs > 0 && task.status === "running") {
|
|
2836
|
+
const deadline = Date.now() + waitMs;
|
|
2837
|
+
while (task.status === "running" && Date.now() < deadline && !ctx?.abortSignal?.aborted) {
|
|
2838
|
+
await new Promise((r) => setTimeout(r, 500));
|
|
2839
|
+
}
|
|
2840
|
+
}
|
|
2824
2841
|
const tail = Math.max(1, args.tail_lines ?? 50);
|
|
2825
2842
|
const allLines = task.outputBuffer.split("\n");
|
|
2826
2843
|
const tailText = allLines.slice(-tail).join("\n").trim();
|
|
@@ -3883,26 +3900,31 @@ var init_repeatBreaker = __esm({
|
|
|
3883
3900
|
const recentSignatures = [];
|
|
3884
3901
|
const recentPollTargets = [];
|
|
3885
3902
|
const POLL_TARGET_KEYS = { get_background_output: ["task_id"] };
|
|
3903
|
+
const parseArgs2 = (tc) => {
|
|
3904
|
+
try {
|
|
3905
|
+
return JSON.parse(tc?.function?.arguments || "{}") ?? {};
|
|
3906
|
+
} catch {
|
|
3907
|
+
return {};
|
|
3908
|
+
}
|
|
3909
|
+
};
|
|
3886
3910
|
const pollTarget = (tc) => {
|
|
3887
3911
|
const name = tc?.function?.name;
|
|
3888
3912
|
const keys = name ? POLL_TARGET_KEYS[name] : void 0;
|
|
3889
3913
|
if (!keys) return null;
|
|
3890
|
-
|
|
3891
|
-
try {
|
|
3892
|
-
args = JSON.parse(tc?.function?.arguments || "{}");
|
|
3893
|
-
} catch {
|
|
3894
|
-
}
|
|
3914
|
+
const args = parseArgs2(tc);
|
|
3895
3915
|
const picked = {};
|
|
3896
3916
|
for (const k of keys) if (k in args) picked[k] = args[k];
|
|
3897
3917
|
return `${name}:${JSON.stringify(picked)}`;
|
|
3898
3918
|
};
|
|
3919
|
+
const isWaitPoll = (tc) => tc?.function?.name === "get_background_output" && Number(parseArgs2(tc).wait_seconds ?? 0) > 0;
|
|
3899
3920
|
const check = (toolCalls, round, lastContent) => {
|
|
3900
|
-
const
|
|
3921
|
+
const effCalls = toolCalls.filter((t) => !isWaitPoll(t));
|
|
3922
|
+
const sig = effCalls.map((t) => `${t.function.name}:${t.function.arguments}`).join("|");
|
|
3901
3923
|
const tooName = toolCalls.map((t) => `${t.function.name}`).join("|");
|
|
3902
3924
|
recentSignatures.push(sig);
|
|
3903
3925
|
if (recentSignatures.length > 6) recentSignatures.shift();
|
|
3904
3926
|
const last3 = recentSignatures.slice(-3);
|
|
3905
|
-
if (last3.length === 3 && last3.every((s) => s ===
|
|
3927
|
+
if (sig && last3.length === 3 && last3.every((s) => s === sig)) {
|
|
3906
3928
|
const text = (lastContent || "") + "\n\uFF08\u68C0\u6D4B\u5230\u91CD\u590D\u5DE5\u5177\u8C03\u7528\uFF0C\u5DF2\u505C\u6B62\uFF09";
|
|
3907
3929
|
events({
|
|
3908
3930
|
sessionId,
|
|
@@ -3921,31 +3943,28 @@ var init_repeatBreaker = __esm({
|
|
|
3921
3943
|
});
|
|
3922
3944
|
return { tripped: true, kind: "full", text, toolName: tooName };
|
|
3923
3945
|
}
|
|
3924
|
-
const
|
|
3925
|
-
|
|
3926
|
-
|
|
3927
|
-
|
|
3928
|
-
|
|
3929
|
-
const
|
|
3930
|
-
|
|
3931
|
-
|
|
3932
|
-
|
|
3933
|
-
|
|
3934
|
-
|
|
3935
|
-
|
|
3936
|
-
|
|
3937
|
-
|
|
3938
|
-
|
|
3939
|
-
|
|
3940
|
-
|
|
3941
|
-
|
|
3942
|
-
|
|
3943
|
-
|
|
3944
|
-
|
|
3945
|
-
|
|
3946
|
-
});
|
|
3947
|
-
return { tripped: true, kind: "names", text, toolName: tooName };
|
|
3948
|
-
}
|
|
3946
|
+
const pollSig = effCalls.map(pollTarget).filter(Boolean).join("|");
|
|
3947
|
+
recentPollTargets.push(pollSig);
|
|
3948
|
+
if (recentPollTargets.length > 8) recentPollTargets.shift();
|
|
3949
|
+
const last4 = recentPollTargets.slice(-4);
|
|
3950
|
+
if (pollSig && last4.length === 4 && last4.every((s) => s === pollSig)) {
|
|
3951
|
+
const text = (lastContent || "") + "\n\uFF08\u68C0\u6D4B\u5230\u540E\u53F0\u4EFB\u52A1\u8F6E\u8BE2\u6B7B\u5FAA\u73AF\uFF08\u53CD\u590D\u67E5\u8BE2\u540C\u4E00\u4EFB\u52A1\uFF09\uFF0C\u5DF2\u505C\u6B62\uFF09";
|
|
3952
|
+
events({
|
|
3953
|
+
sessionId,
|
|
3954
|
+
eventType: "tool.repeat_break",
|
|
3955
|
+
metadata: {
|
|
3956
|
+
depth,
|
|
3957
|
+
decisionSource: llmDecisionSource,
|
|
3958
|
+
durationMs: performance.now() - startTime,
|
|
3959
|
+
round,
|
|
3960
|
+
toolName: tooName,
|
|
3961
|
+
toolSource: "builtin",
|
|
3962
|
+
ok: false,
|
|
3963
|
+
attempt: round
|
|
3964
|
+
},
|
|
3965
|
+
payload: { output: text }
|
|
3966
|
+
});
|
|
3967
|
+
return { tripped: true, kind: "names", text, toolName: tooName };
|
|
3949
3968
|
}
|
|
3950
3969
|
events({
|
|
3951
3970
|
sessionId,
|
|
@@ -4363,10 +4382,23 @@ var init_systemInjections = __esm({
|
|
|
4363
4382
|
function: { name: t.function.name, description: t.function.description, parameters: t.function.parameters }
|
|
4364
4383
|
}));
|
|
4365
4384
|
ensureSummarySlot(message);
|
|
4366
|
-
|
|
4367
|
-
|
|
4368
|
-
|
|
4369
|
-
}
|
|
4385
|
+
const LOCALE_HINTS = {
|
|
4386
|
+
zh: "\u59CB\u7EC8\u7528\u4E2D\u6587\u8F93\u51FA\u6240\u6709\u9762\u5411\u7528\u6237\u7684\u5185\u5BB9\uFF1A\u4F60\u7684\u56DE\u590D\u3001\u4E2D\u95F4\u53D9\u8FF0\u3001todo \u4EFB\u52A1\u9879\u6807\u9898\u3001\u901A\u8FC7 exit_plan_mode \u63D0\u4EA4\u7684\u65B9\u6848\u6587\u672C\u3001\u4EE3\u7801\u6CE8\u91CA\u4E0E\u63D0\u4EA4\u4FE1\u606F\u3002\u4EE3\u7801\u6807\u8BC6\u7B26\u4FDD\u6301\u539F\u6837\uFF1B\u5DE5\u5177\u7ED3\u679C\u4E0E\u7CFB\u7EDF\u6307\u4EE4\u53EF\u80FD\u5939\u6742\u5176\u4ED6\u8BED\u8A00\u2014\u2014\u5FC5\u8981\u65F6\u7167\u5F15\u539F\u6587\uFF0C\u4F46\u4F60\u81EA\u5DF1\u7684\u53D9\u8FF0\u4E0E\u89E3\u91CA\u4E00\u5F8B\u7528\u4E2D\u6587\u3002",
|
|
4387
|
+
en: "Always produce ALL user-facing output in English: your replies, interim narration, todo item titles, the plan text you submit via exit_plan_mode, code comments, and commit messages. Keep code identifiers as-is; tool results and system instructions may arrive in Chinese \u2014 quote them verbatim where needed, but your own narration and explanations must stay in English."
|
|
4388
|
+
};
|
|
4389
|
+
const lastUserText = (() => {
|
|
4390
|
+
for (let i = message.length - 1; i >= 0; i--) {
|
|
4391
|
+
const m = message[i];
|
|
4392
|
+
if (m?.role !== "user") continue;
|
|
4393
|
+
const c = m.content;
|
|
4394
|
+
if (typeof c === "string") return c;
|
|
4395
|
+
if (Array.isArray(c)) return c.filter((p) => typeof p?.text === "string").map((p) => p.text).join(" ");
|
|
4396
|
+
return "";
|
|
4397
|
+
}
|
|
4398
|
+
return "";
|
|
4399
|
+
})();
|
|
4400
|
+
const effLocale = detectTextLocale(lastUserText) ?? locale2;
|
|
4401
|
+
if (effLocale) injectMarkedBlock(message, "\u27E6DSC:LOCALE\u27E7", LOCALE_HINTS[effLocale]);
|
|
4370
4402
|
injectOutputStyle(message, outputStyle);
|
|
4371
4403
|
injectSkillCatalog(message);
|
|
4372
4404
|
injectAgentCatalog(message);
|
|
@@ -4389,13 +4421,14 @@ var init_agent = __esm({
|
|
|
4389
4421
|
type: "function",
|
|
4390
4422
|
function: {
|
|
4391
4423
|
name: "spawn_agent",
|
|
4392
|
-
description: "\u521B\u5EFA\u4E00\u4E2A\u62E5\u6709\u72EC\u7ACB\u6267\u884C\u73AF\u5883\u7684\u5B50 agent \u5904\u7406\u9694\u79BB\u7684\u7279\u5B9A\u5B50\u4EFB\u52A1\uFF0C\u5B50\u4EFB\u52A1\u5B8C\u6210\u540E\u81EA\u52A8\u6C47\u603B\u6539\u52A8\u70B9\u4E0E\u7ED3\u8BBA\u8FD4\u56DE\u3002\u53EF\u901A\u8FC7 name \u6307\u5B9A\u58F0\u660E\u5F0F\u5B50 Agent\uFF08\u89C1\u7CFB\u7EDF\u63D0\u793A\u8BCD\u3010\u53EF\u7528\u5B50 Agent \u76EE\u5F55\u3011\uFF09\u4EE5\u5957\u7528\u5176\u4E13\u957F\u7CFB\u7EDF\u8BCD/\u5DE5\u5177\u767D\u540D\u5355/model\uFF1B\u4E0D\u4F20 name \u8D70\u9ED8\u8BA4\u901A\u7528\u5B50 agent\u3002",
|
|
4424
|
+
description: "\u521B\u5EFA\u4E00\u4E2A\u62E5\u6709\u72EC\u7ACB\u6267\u884C\u73AF\u5883\u7684\u5B50 agent \u5904\u7406\u9694\u79BB\u7684\u7279\u5B9A\u5B50\u4EFB\u52A1\uFF0C\u5B50\u4EFB\u52A1\u5B8C\u6210\u540E\u81EA\u52A8\u6C47\u603B\u6539\u52A8\u70B9\u4E0E\u7ED3\u8BBA\u8FD4\u56DE\u3002\u53EF\u901A\u8FC7 name \u6307\u5B9A\u58F0\u660E\u5F0F\u5B50 Agent\uFF08\u89C1\u7CFB\u7EDF\u63D0\u793A\u8BCD\u3010\u53EF\u7528\u5B50 Agent \u76EE\u5F55\u3011\uFF09\u4EE5\u5957\u7528\u5176\u4E13\u957F\u7CFB\u7EDF\u8BCD/\u5DE5\u5177\u767D\u540D\u5355/model\uFF1B\u4E0D\u4F20 name \u8D70\u9ED8\u8BA4\u901A\u7528\u5B50 agent\u3002\u652F\u6301\u7EED\u8DD1\uFF1A\u4F20 resume_session_id\uFF08\u6B64\u524D\u8FD4\u56DE\u7684 agent_id\uFF09\u590D\u7528\u8BE5\u5B50 Agent \u7684\u5B8C\u6574\u5386\u53F2\u8BB0\u5FC6\uFF0C\u9002\u5408\u8FFD\u95EE\u3001\u7EE7\u7EED\u672A\u5B8C\u6210\u7684\u4EFB\u52A1\u3002",
|
|
4393
4425
|
parameters: {
|
|
4394
4426
|
type: "object",
|
|
4395
4427
|
properties: {
|
|
4396
|
-
task: { type: "string", description: "\u4EA4\u7ED9\u5B50 agent \u7684\u5177\u4F53\u5FAE\u89C2\u4EFB\u52A1\u63CF\u8FF0\uFF08\u5982 '\u7F16\u5199 Button \u7EC4\u4EF6\u7684\u5355\u5143\u6D4B\u8BD5'\uFF09" },
|
|
4428
|
+
task: { type: "string", description: "\u4EA4\u7ED9\u5B50 agent \u7684\u5177\u4F53\u5FAE\u89C2\u4EFB\u52A1\u63CF\u8FF0\uFF08\u5982 '\u7F16\u5199 Button \u7EC4\u4EF6\u7684\u5355\u5143\u6D4B\u8BD5'\uFF09\uFF1B\u7EED\u8DD1\u65F6\u4E3A\u65B0\u6307\u4EE4\uFF08\u5982 '\u7EE7\u7EED\u5B8C\u6210\u5269\u4F59\u7528\u4F8B'\uFF09" },
|
|
4397
4429
|
name: { type: "string", description: "\u58F0\u660E\u5F0F\u5B50 Agent \u540D\u79F0\uFF08\u987B\u4E0E\u7CFB\u7EDF\u63D0\u793A\u8BCD\u4E2D\u3010\u53EF\u7528\u5B50 Agent \u76EE\u5F55\u3011\u4E00\u81F4\uFF09\u3002\u63D0\u4F9B\u65F6\u6309\u5176\u58F0\u660E\u52A0\u8F7D\u7CFB\u7EDF\u8BCD/\u5DE5\u5177\u767D\u540D\u5355/model\uFF1B\u4E0D\u63D0\u4F9B\u5219\u8D70\u9ED8\u8BA4\u901A\u7528\u5B50 agent\u3002" },
|
|
4398
|
-
role: { type: "string", description: "\u5B50 agent \u7684\u89D2\u8272/\u4E13\u957F\uFF08\u53EF\u9009\uFF0C\u5982 '\u6D4B\u8BD5\u4E13\u5BB6'\u3001'\u91CD\u6784\u5148\u950B'\uFF09\u3002\u58F0\u660E\u5F0F agent \u81EA\u5E26 role \u65F6\u4F5C\u8865\u5145\u3002" }
|
|
4430
|
+
role: { type: "string", description: "\u5B50 agent \u7684\u89D2\u8272/\u4E13\u957F\uFF08\u53EF\u9009\uFF0C\u5982 '\u6D4B\u8BD5\u4E13\u5BB6'\u3001'\u91CD\u6784\u5148\u950B'\uFF09\u3002\u58F0\u660E\u5F0F agent \u81EA\u5E26 role \u65F6\u4F5C\u8865\u5145\u3002" },
|
|
4431
|
+
resume_session_id: { type: "string", description: "\u7EED\u8DD1\u65E2\u6709\u5B50 Agent\uFF1A\u4F20\u6B64\u524D spawn_agent \u8FD4\u56DE\u7684 agent_id\uFF0C\u5176\u78C1\u76D8\u4E0A\u7684\u5386\u53F2\u4E0E\u8BB0\u5FC6\u5C06\u5B8C\u6574\u6062\u590D\u3002\u6CE8\u610F\uFF1A\u5B50 Agent \u72B6\u6001\u4E0D\u968F\u4E3B\u4F1A\u8BDD fork \u56DE\u6EDA\u2014\u2014fork \u53EA\u5206\u53C9\u5BF9\u8BDD\uFF0C\u7EED\u8DD1\u62FF\u5230\u7684\u662F\u5B50\u4F1A\u8BDD\u78C1\u76D8\u6700\u65B0\u72B6\u6001\u3002\u7F3A\u7701\u5219\u65B0\u5EFA\u5B50 Agent\u3002" }
|
|
4399
4432
|
},
|
|
4400
4433
|
required: ["task"]
|
|
4401
4434
|
},
|
|
@@ -4403,10 +4436,17 @@ var init_agent = __esm({
|
|
|
4403
4436
|
isSync: true,
|
|
4404
4437
|
async execute(args, ctx) {
|
|
4405
4438
|
if (!ctx) return "\u274C [\u6D3E\u751F\u5931\u8D25]\uFF1Aspawn_agent \u7F3A\u5C11\u5FC5\u987B\u7684\u667A\u80FD\u4F53\u8FD0\u884C\u4E0A\u4E0B\u6587\u3002";
|
|
4406
|
-
const res = await runSubagent(
|
|
4439
|
+
const res = await runSubagent(
|
|
4440
|
+
{ task: args.task, name: args.name, role: args.role, resumeSessionId: args.resume_session_id },
|
|
4441
|
+
ctx,
|
|
4442
|
+
getGlobalTools
|
|
4443
|
+
);
|
|
4407
4444
|
if (!res.ok) return res.output;
|
|
4408
4445
|
return [
|
|
4409
|
-
`\u{1F389} [\u5B50 Agent \u6267\u884C\u5B8C\u6BD5] \u6D3E\u751F\u5B50\u4EFB\u52A1\u6C47\u62A5\u5982\u4E0B\uFF1A
|
|
4446
|
+
`\u{1F389} [\u5B50 Agent \u6267\u884C\u5B8C\u6BD5${args.resume_session_id ? "\xB7\u7EED\u8DD1" : ""}] \u6D3E\u751F\u5B50\u4EFB\u52A1\u6C47\u62A5\u5982\u4E0B\uFF1A
|
|
4447
|
+
`,
|
|
4448
|
+
`\u{1F194} agent_id: ${res.sessionId}
|
|
4449
|
+
\uFF08\u9700\u8981\u7EE7\u7EED\u8BE5\u5B50 Agent \u7684\u4EFB\u52A1\u6216\u8FFD\u95EE\u65F6\uFF0C\u8C03\u7528 spawn_agent \u4F20 resume_session_id=${res.sessionId}\uFF0C\u5176\u5386\u53F2\u8BB0\u5FC6\u5B8C\u6574\u4FDD\u7559\uFF09
|
|
4410
4450
|
`,
|
|
4411
4451
|
`==================================================
|
|
4412
4452
|
`,
|
|
@@ -9978,6 +10018,7 @@ var init_agentNudges = __esm({
|
|
|
9978
10018
|
createNudgeScheduler = (opts = {}) => {
|
|
9979
10019
|
const firstPrompt = opts.firstPrompt ?? "";
|
|
9980
10020
|
const planMode = !!opts.planMode;
|
|
10021
|
+
const noEarlyFinal = !!opts.noEarlyFinal;
|
|
9981
10022
|
let phantomRetries = 0;
|
|
9982
10023
|
let phantomPending = null;
|
|
9983
10024
|
let earlyFinalNudges = 0;
|
|
@@ -10040,7 +10081,7 @@ ${TOOL_DIGEST_TEXT}` };
|
|
|
10040
10081
|
${PHANTOM_TEXT}` };
|
|
10041
10082
|
return true;
|
|
10042
10083
|
}
|
|
10043
|
-
if (text !== "" && round <= EARLY_FINAL_TURN_THRESHOLD && earlyFinalNudges < EARLY_FINAL_MAX && !looksComplete(finalText)) {
|
|
10084
|
+
if (!noEarlyFinal && text !== "" && round <= EARLY_FINAL_TURN_THRESHOLD && earlyFinalNudges < EARLY_FINAL_MAX && !looksComplete(finalText)) {
|
|
10044
10085
|
earlyFinalNudges++;
|
|
10045
10086
|
earlyFinalPending = { role: "system", content: `${EARLY_FINAL_FENCE}
|
|
10046
10087
|
${EARLY_FINAL_TEXT(round)}` };
|
|
@@ -10125,7 +10166,7 @@ async function* runAgent(message, options) {
|
|
|
10125
10166
|
const m = message.find((x) => x?.role === "user");
|
|
10126
10167
|
return typeof m?.content === "string" ? m.content : "";
|
|
10127
10168
|
})();
|
|
10128
|
-
const nudges = createNudgeScheduler({ firstPrompt, planMode: !!options.planMode });
|
|
10169
|
+
const nudges = createNudgeScheduler({ firstPrompt, planMode: !!options.planMode, noEarlyFinal: !!options.noEarlyFinal });
|
|
10129
10170
|
const userDecisionSource = depth > 0 ? "spawn_agent" : "user";
|
|
10130
10171
|
const llmDecisionSource = depth > 0 ? "llm_spawn_agent" : "llm";
|
|
10131
10172
|
const startTime = performance.now();
|
|
@@ -10254,7 +10295,6 @@ async function* runAgent(message, options) {
|
|
|
10254
10295
|
if (assistantMessage.content) {
|
|
10255
10296
|
lastContent = assistantMessage.content;
|
|
10256
10297
|
}
|
|
10257
|
-
const tcCount = assistantMessage.tool_calls?.length ?? 0;
|
|
10258
10298
|
if (!assistantMessage.tool_calls || assistantMessage.tool_calls.length === 0) {
|
|
10259
10299
|
await appendEvent(sessionId, { dscEvent: "round.end", runId, round, usage: infResult.usage });
|
|
10260
10300
|
const finalText = (typeof assistantMessage.content === "string" ? assistantMessage.content : "") || "";
|
|
@@ -10499,8 +10539,61 @@ var init_content = __esm({
|
|
|
10499
10539
|
}
|
|
10500
10540
|
});
|
|
10501
10541
|
|
|
10542
|
+
// ../core/src/session/lineage.ts
|
|
10543
|
+
import fs27 from "node:fs";
|
|
10544
|
+
var parentOfSubsession, stringAncestorsOf, readForkedFromSync, lineageClosureOf, ownerCanApprove;
|
|
10545
|
+
var init_lineage = __esm({
|
|
10546
|
+
"../core/src/session/lineage.ts"() {
|
|
10547
|
+
"use strict";
|
|
10548
|
+
init_store();
|
|
10549
|
+
parentOfSubsession = (sessionId) => {
|
|
10550
|
+
const i = sessionId.lastIndexOf("__sub__");
|
|
10551
|
+
return i > 0 ? sessionId.slice(0, i) : void 0;
|
|
10552
|
+
};
|
|
10553
|
+
stringAncestorsOf = (sessionId) => {
|
|
10554
|
+
const out = [sessionId];
|
|
10555
|
+
let cur = sessionId;
|
|
10556
|
+
for (; ; ) {
|
|
10557
|
+
const p = parentOfSubsession(cur);
|
|
10558
|
+
if (p === void 0) break;
|
|
10559
|
+
out.push(p);
|
|
10560
|
+
cur = p;
|
|
10561
|
+
}
|
|
10562
|
+
return out;
|
|
10563
|
+
};
|
|
10564
|
+
readForkedFromSync = (sessionId) => {
|
|
10565
|
+
try {
|
|
10566
|
+
const raw = fs27.readFileSync(getStatePath(sessionId), "utf-8");
|
|
10567
|
+
const v = JSON.parse(raw)?.forkedFrom;
|
|
10568
|
+
return typeof v === "string" && v.length > 0 ? v : void 0;
|
|
10569
|
+
} catch {
|
|
10570
|
+
return void 0;
|
|
10571
|
+
}
|
|
10572
|
+
};
|
|
10573
|
+
lineageClosureOf = (sessionId) => {
|
|
10574
|
+
const closure = /* @__PURE__ */ new Set();
|
|
10575
|
+
const expand = (id) => {
|
|
10576
|
+
if (closure.has(id)) return;
|
|
10577
|
+
const ancestors = stringAncestorsOf(id);
|
|
10578
|
+
for (const a of ancestors) closure.add(a);
|
|
10579
|
+
const root = ancestors[ancestors.length - 1];
|
|
10580
|
+
const from = readForkedFromSync(root);
|
|
10581
|
+
if (from && !closure.has(from)) expand(from);
|
|
10582
|
+
};
|
|
10583
|
+
expand(sessionId);
|
|
10584
|
+
return closure;
|
|
10585
|
+
};
|
|
10586
|
+
ownerCanApprove = (entrySessionId, approverSessionId) => {
|
|
10587
|
+
if (entrySessionId === approverSessionId) return true;
|
|
10588
|
+
if (!entrySessionId.includes("__sub__")) return false;
|
|
10589
|
+
const closure = lineageClosureOf(approverSessionId);
|
|
10590
|
+
return stringAncestorsOf(entrySessionId).some((a, i) => i > 0 && closure.has(a));
|
|
10591
|
+
};
|
|
10592
|
+
}
|
|
10593
|
+
});
|
|
10594
|
+
|
|
10502
10595
|
// ../core/src/agent/subagent.ts
|
|
10503
|
-
var SUBAGENT_DENYLIST, runSubagent;
|
|
10596
|
+
var SUBAGENT_DENYLIST, activeSubagents, RESUME_NOTE, runSubagent;
|
|
10504
10597
|
var init_subagent = __esm({
|
|
10505
10598
|
"../core/src/agent/subagent.ts"() {
|
|
10506
10599
|
"use strict";
|
|
@@ -10511,9 +10604,18 @@ var init_subagent = __esm({
|
|
|
10511
10604
|
init_type();
|
|
10512
10605
|
init_registry4();
|
|
10513
10606
|
init_hooks();
|
|
10607
|
+
init_lineage();
|
|
10514
10608
|
SUBAGENT_DENYLIST = /* @__PURE__ */ new Set(["run_command", "delete_path"]);
|
|
10609
|
+
activeSubagents = /* @__PURE__ */ new Set();
|
|
10610
|
+
RESUME_NOTE = [
|
|
10611
|
+
`
|
|
10612
|
+
# \u3010\u7EED\u8DD1\u8BF4\u660E\u3011`,
|
|
10613
|
+
`\u4F60\u6B64\u524D\u7684\u5DE5\u4F5C\u5386\u53F2\u5DF2\u5B8C\u6574\u6062\u590D\u5230\u672C\u6B21\u4E0A\u4E0B\u6587\uFF08\u78C1\u76D8\u6700\u65B0\u72B6\u6001\uFF0C\u53EF\u80FD\u6BD4\u4F60\u4E0A\u6B21\u8BB0\u5FC6\u66F4\u65B0\uFF09\u3002`,
|
|
10614
|
+
`\u8BF7\u5148\u5BF9\u7167\u5386\u53F2\u7B80\u8981\u56DE\u987E\u5DF2\u5B8C\u6210 / \u672A\u5B8C\u6210\u90E8\u5206\uFF0C\u518D\u7EE7\u7EED\u6267\u884C\u65B0\u4EFB\u52A1\uFF1B\u6700\u7EC8\u6C47\u62A5\u4E5F\u8BF7\u5148\u6982\u8FF0\u6B64\u524D\u8FDB\u5C55\u3002`
|
|
10615
|
+
].join("\n");
|
|
10515
10616
|
runSubagent = async (spec, ctx, getGlobalTools) => {
|
|
10516
|
-
const { task, name, role } = spec;
|
|
10617
|
+
const { task, name, role, resumeSessionId } = spec;
|
|
10618
|
+
const resuming = typeof resumeSessionId === "string" && resumeSessionId.length > 0;
|
|
10517
10619
|
if (ctx.depth >= MAX_AGENT_DEPTH) {
|
|
10518
10620
|
return {
|
|
10519
10621
|
ok: false,
|
|
@@ -10521,7 +10623,39 @@ var init_subagent = __esm({
|
|
|
10521
10623
|
sessionId: ""
|
|
10522
10624
|
};
|
|
10523
10625
|
}
|
|
10524
|
-
|
|
10626
|
+
if (resuming) {
|
|
10627
|
+
const target = resumeSessionId;
|
|
10628
|
+
if (!target.includes("__sub__")) {
|
|
10629
|
+
return {
|
|
10630
|
+
ok: false,
|
|
10631
|
+
output: `\u274C [\u7EED\u8DD1\u5931\u8D25]\uFF1A${target} \u4E0D\u662F\u5B50 Agent \u4F1A\u8BDD ID\uFF08\u5E94\u5F62\u5982 <\u4F1A\u8BDD>__sub__<uuid>\uFF0C\u6765\u81EA\u6B64\u524D spawn_agent \u8FD4\u56DE\u7684 agent_id\uFF09\u3002`,
|
|
10632
|
+
sessionId: ""
|
|
10633
|
+
};
|
|
10634
|
+
}
|
|
10635
|
+
if (!ownerCanApprove(target, ctx.sessionId)) {
|
|
10636
|
+
return {
|
|
10637
|
+
ok: false,
|
|
10638
|
+
output: `\u274C [\u7EED\u8DD1\u5931\u8D25]\uFF1A\u5B50\u4F1A\u8BDD ${target} \u4E0D\u5C5E\u4E8E\u5F53\u524D\u4F1A\u8BDD\uFF08\u53CA\u5176 fork \u8840\u7F18\uFF09\uFF0C\u7981\u6B62\u8DE8\u4F1A\u8BDD\u590D\u6D3B\u3002\u8BF7\u6838\u5BF9 agent_id \u6216\u6539\u7528\u65B0\u5EFA\u6D3E\u751F\u3002`,
|
|
10639
|
+
sessionId: ""
|
|
10640
|
+
};
|
|
10641
|
+
}
|
|
10642
|
+
if (activeSubagents.has(target)) {
|
|
10643
|
+
return {
|
|
10644
|
+
ok: false,
|
|
10645
|
+
output: `\u274C [\u7EED\u8DD1\u5931\u8D25]\uFF1A\u5B50 Agent ${target} \u6B63\u5728\u6267\u884C\u4E2D\uFF0C\u7981\u6B62\u5E76\u53D1\u7EED\u8DD1\u540C\u4E00\u5B50\u4F1A\u8BDD\uFF08\u4F1A\u4EA4\u53C9\u5199\u574F\u8F6C\u5F55\uFF09\u3002\u8BF7\u7B49\u5F85\u5176\u5B8C\u6210\u540E\u518D\u8BD5\u3002`,
|
|
10646
|
+
sessionId: ""
|
|
10647
|
+
};
|
|
10648
|
+
}
|
|
10649
|
+
const existing = await readTranscriptLines(target);
|
|
10650
|
+
if (existing.length === 0) {
|
|
10651
|
+
return {
|
|
10652
|
+
ok: false,
|
|
10653
|
+
output: `\u274C [\u7EED\u8DD1\u5931\u8D25]\uFF1A\u5B50\u4F1A\u8BDD ${target} \u7684\u8F6C\u5F55\u4E0D\u5B58\u5728\u6216\u4E3A\u7A7A\uFF0C\u65E0\u6CD5\u7EED\u8DD1\u3002\u8BF7\u6539\u7528\u65B0\u5EFA\u6D3E\u751F\u3002`,
|
|
10654
|
+
sessionId: ""
|
|
10655
|
+
};
|
|
10656
|
+
}
|
|
10657
|
+
}
|
|
10658
|
+
const subSessionId = resuming ? resumeSessionId : `${ctx.sessionId}__sub__${createUUID()}`;
|
|
10525
10659
|
const parentSystemPrompt = ctx.parentSystemPrompt || "";
|
|
10526
10660
|
const manifest = name ? getAgent(name) : void 0;
|
|
10527
10661
|
if (name && !manifest) {
|
|
@@ -10531,7 +10665,7 @@ var init_subagent = __esm({
|
|
|
10531
10665
|
sessionId: ""
|
|
10532
10666
|
};
|
|
10533
10667
|
}
|
|
10534
|
-
const subSystem = manifest ? [
|
|
10668
|
+
const subSystem = (manifest ? [
|
|
10535
10669
|
`# \u5B50 Agent \u8EAB\u4EFD\uFF1A${manifest.name}`,
|
|
10536
10670
|
manifest.body,
|
|
10537
10671
|
`
|
|
@@ -10554,11 +10688,12 @@ var init_subagent = __esm({
|
|
|
10554
10688
|
`
|
|
10555
10689
|
# \u3010\u7EE7\u627F\u7684\u5168\u5C40\u4EE3\u7801\u89C4\u8303\u3011`,
|
|
10556
10690
|
parentSystemPrompt
|
|
10557
|
-
].join("\n");
|
|
10691
|
+
].join("\n")) + (resuming ? RESUME_NOTE : "");
|
|
10558
10692
|
const allTools = getGlobalTools();
|
|
10559
10693
|
const wantsMcp = manifest?.tools.some((t) => t === "mcp_call" || t === "mcp_list_tools" || t.startsWith("mcp__")) ?? false;
|
|
10560
10694
|
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));
|
|
10561
|
-
console.log(
|
|
10695
|
+
console.log(`${resuming ? "\u{1F501} \u7EED\u8DD1" : "\u{1F423} \u6D3E\u751F"}\u5B50 Agent [\u6DF1\u5EA6: ${ctx.depth + 1}/${MAX_AGENT_DEPTH}][${subSessionId}]${manifest ? ` \u58F0\u660E\u5F0F=${manifest.name}` : ""} \u4EFB\u52A1: "${task.slice(0, 50)}..."`);
|
|
10696
|
+
activeSubagents.add(subSessionId);
|
|
10562
10697
|
try {
|
|
10563
10698
|
const subMessages = await buildContextMessages(subSessionId, { role: "user", content: task }, subSystem);
|
|
10564
10699
|
await appendMessage({ sessionId: subSessionId, role: "user", content: task });
|
|
@@ -10582,6 +10717,8 @@ var init_subagent = __esm({
|
|
|
10582
10717
|
// ★ 同步透传宿主审批钩子,子 agent 高危工具仍走同一审批通道
|
|
10583
10718
|
permissionMode: ctx.permissionMode,
|
|
10584
10719
|
// ★ P1-6 透传:子 agent 工作区文件编辑也走 auto 分类器
|
|
10720
|
+
noEarlyFinal: true,
|
|
10721
|
+
// ★ 子 agent final 是交付父级的汇报,EARLY_FINAL 误推一轮纯浪费;父可经续跑纠错
|
|
10585
10722
|
model: manifest?.model
|
|
10586
10723
|
// ★ per-agent 模型覆盖;undefined 时 model.ts 回退全局 MODEL_NAME
|
|
10587
10724
|
};
|
|
@@ -10615,13 +10752,15 @@ var init_subagent = __esm({
|
|
|
10615
10752
|
return result ?? { ok: false, output: `\u274C [\u6D3E\u751F\u6267\u884C\u5931\u8D25]: \u672A\u77E5\u9519\u8BEF`, sessionId: subSessionId, manifestName: manifest?.name };
|
|
10616
10753
|
} catch (error) {
|
|
10617
10754
|
return { ok: false, output: `\u274C [\u6D3E\u751F\u6267\u884C\u5931\u8D25]: ${error.message}`, sessionId: subSessionId, manifestName: manifest?.name };
|
|
10755
|
+
} finally {
|
|
10756
|
+
activeSubagents.delete(subSessionId);
|
|
10618
10757
|
}
|
|
10619
10758
|
};
|
|
10620
10759
|
}
|
|
10621
10760
|
});
|
|
10622
10761
|
|
|
10623
10762
|
// ../core/src/hooks/loader.ts
|
|
10624
|
-
import
|
|
10763
|
+
import fs28 from "fs/promises";
|
|
10625
10764
|
import path30 from "path";
|
|
10626
10765
|
var readHooksConfig, appendValidated, validateRule, parseStdoutDecision, parseAgentDecision, compileRule2, loadHooks, initHooks;
|
|
10627
10766
|
var init_loader4 = __esm({
|
|
@@ -10645,7 +10784,7 @@ var init_loader4 = __esm({
|
|
|
10645
10784
|
for (const configPath of paths) {
|
|
10646
10785
|
let raw;
|
|
10647
10786
|
try {
|
|
10648
|
-
raw = await
|
|
10787
|
+
raw = await fs28.readFile(configPath, "utf-8");
|
|
10649
10788
|
} catch {
|
|
10650
10789
|
continue;
|
|
10651
10790
|
}
|
|
@@ -10975,7 +11114,7 @@ ${m.context}`;
|
|
|
10975
11114
|
});
|
|
10976
11115
|
|
|
10977
11116
|
// ../core/src/skills/loader.ts
|
|
10978
|
-
import
|
|
11117
|
+
import fs29 from "fs/promises";
|
|
10979
11118
|
import path31 from "path";
|
|
10980
11119
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
10981
11120
|
var BUILTIN_DIR, SOURCES2, MAX_SKILL_BODY_BYTES, splitList, parseSkillAt, loadSkills, initSkills;
|
|
@@ -10998,7 +11137,7 @@ var init_loader5 = __esm({
|
|
|
10998
11137
|
parseSkillAt = async (skillFile, dir, source) => {
|
|
10999
11138
|
let raw;
|
|
11000
11139
|
try {
|
|
11001
|
-
raw = await
|
|
11140
|
+
raw = await fs29.readFile(skillFile, "utf-8");
|
|
11002
11141
|
} catch {
|
|
11003
11142
|
return null;
|
|
11004
11143
|
}
|
|
@@ -11068,7 +11207,7 @@ var init_loader5 = __esm({
|
|
|
11068
11207
|
});
|
|
11069
11208
|
|
|
11070
11209
|
// ../core/src/agents/loader.ts
|
|
11071
|
-
import
|
|
11210
|
+
import fs30 from "fs/promises";
|
|
11072
11211
|
import path32 from "path";
|
|
11073
11212
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
11074
11213
|
var BUILTIN_DIR2, SOURCES3, parseAgentAt, initAgents;
|
|
@@ -11088,7 +11227,7 @@ var init_loader6 = __esm({
|
|
|
11088
11227
|
parseAgentAt = async (file, dir, source) => {
|
|
11089
11228
|
let raw;
|
|
11090
11229
|
try {
|
|
11091
|
-
raw = await
|
|
11230
|
+
raw = await fs30.readFile(file, "utf-8");
|
|
11092
11231
|
} catch {
|
|
11093
11232
|
return null;
|
|
11094
11233
|
}
|
|
@@ -11160,7 +11299,7 @@ var init_registry7 = __esm({
|
|
|
11160
11299
|
});
|
|
11161
11300
|
|
|
11162
11301
|
// ../core/src/commands/loader.ts
|
|
11163
|
-
import
|
|
11302
|
+
import fs31 from "fs/promises";
|
|
11164
11303
|
import path33 from "path";
|
|
11165
11304
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
11166
11305
|
var BUILTIN_DIR3, SOURCES4, MAX_COMMAND_BODY_BYTES, parseCommandAt, loadCommands, initCommands;
|
|
@@ -11181,7 +11320,7 @@ var init_loader7 = __esm({
|
|
|
11181
11320
|
parseCommandAt = async (file, _dir, source) => {
|
|
11182
11321
|
let raw;
|
|
11183
11322
|
try {
|
|
11184
|
-
raw = await
|
|
11323
|
+
raw = await fs31.readFile(file, "utf-8");
|
|
11185
11324
|
} catch {
|
|
11186
11325
|
return null;
|
|
11187
11326
|
}
|
|
@@ -11236,7 +11375,7 @@ var init_loader7 = __esm({
|
|
|
11236
11375
|
});
|
|
11237
11376
|
|
|
11238
11377
|
// ../core/src/outputStyles/loader.ts
|
|
11239
|
-
import
|
|
11378
|
+
import fs32 from "fs/promises";
|
|
11240
11379
|
import path34 from "path";
|
|
11241
11380
|
import { fileURLToPath as fileURLToPath5 } from "url";
|
|
11242
11381
|
var BUILTIN_DIR4, MAX_STYLE_BODY_BYTES, SOURCES5, parseStyleAt, loadOutputStyles, initOutputStyles;
|
|
@@ -11257,7 +11396,7 @@ var init_loader8 = __esm({
|
|
|
11257
11396
|
parseStyleAt = async (file, _dir, source) => {
|
|
11258
11397
|
let raw;
|
|
11259
11398
|
try {
|
|
11260
|
-
raw = await
|
|
11399
|
+
raw = await fs32.readFile(file, "utf-8");
|
|
11261
11400
|
} catch {
|
|
11262
11401
|
return null;
|
|
11263
11402
|
}
|
|
@@ -11370,7 +11509,7 @@ var init_bootstrap = __esm({
|
|
|
11370
11509
|
});
|
|
11371
11510
|
|
|
11372
11511
|
// ../core/src/statusLine/config.ts
|
|
11373
|
-
import
|
|
11512
|
+
import fs33 from "fs/promises";
|
|
11374
11513
|
import path35 from "path";
|
|
11375
11514
|
var parseBlock, readStatusLineConfig;
|
|
11376
11515
|
var init_config2 = __esm({
|
|
@@ -11396,7 +11535,7 @@ var init_config2 = __esm({
|
|
|
11396
11535
|
for (const configPath of paths) {
|
|
11397
11536
|
let raw;
|
|
11398
11537
|
try {
|
|
11399
|
-
raw = await
|
|
11538
|
+
raw = await fs33.readFile(configPath, "utf-8");
|
|
11400
11539
|
} catch {
|
|
11401
11540
|
continue;
|
|
11402
11541
|
}
|
|
@@ -11416,7 +11555,7 @@ var init_config2 = __esm({
|
|
|
11416
11555
|
|
|
11417
11556
|
// ../core/src/statusLine/runner.ts
|
|
11418
11557
|
import { spawn as spawn5 } from "child_process";
|
|
11419
|
-
import
|
|
11558
|
+
import fs34 from "fs";
|
|
11420
11559
|
import path36 from "path";
|
|
11421
11560
|
import { fileURLToPath as fileURLToPath6 } from "url";
|
|
11422
11561
|
var STATUSLINE_TIMEOUT_MS, cachedVersion, runStatusLine;
|
|
@@ -11435,7 +11574,7 @@ var init_runner = __esm({
|
|
|
11435
11574
|
];
|
|
11436
11575
|
for (const p of candidates) {
|
|
11437
11576
|
try {
|
|
11438
|
-
const pkg = JSON.parse(
|
|
11577
|
+
const pkg = JSON.parse(fs34.readFileSync(p, "utf-8"));
|
|
11439
11578
|
if (typeof pkg.version === "string" && pkg.version) {
|
|
11440
11579
|
cachedVersion = pkg.version;
|
|
11441
11580
|
break;
|
|
@@ -11495,7 +11634,7 @@ var init_createModel = __esm({
|
|
|
11495
11634
|
|
|
11496
11635
|
// ../core/src/observability/store.ts
|
|
11497
11636
|
import path37 from "path";
|
|
11498
|
-
import
|
|
11637
|
+
import fs35 from "fs/promises";
|
|
11499
11638
|
var getTraceDirPath, getTracePath, tracePathCache, ensuredTraceDirs, ensureTraceDir, getGlobalClockPath, getTraceStorePath;
|
|
11500
11639
|
var init_store3 = __esm({
|
|
11501
11640
|
"../core/src/observability/store.ts"() {
|
|
@@ -11515,7 +11654,7 @@ var init_store3 = __esm({
|
|
|
11515
11654
|
ensureTraceDir = async (mainTraceId) => {
|
|
11516
11655
|
const dir = getTraceDirPath(mainTraceId);
|
|
11517
11656
|
if (ensuredTraceDirs.has(dir)) return;
|
|
11518
|
-
await
|
|
11657
|
+
await fs35.mkdir(dir, { recursive: true });
|
|
11519
11658
|
ensuredTraceDirs.add(dir);
|
|
11520
11659
|
};
|
|
11521
11660
|
getGlobalClockPath = () => {
|
|
@@ -11528,7 +11667,7 @@ var init_store3 = __esm({
|
|
|
11528
11667
|
if (cached2) return cached2;
|
|
11529
11668
|
await ensureTraceDir(rootId);
|
|
11530
11669
|
const dir = getTraceDirPath(rootId);
|
|
11531
|
-
const files = await
|
|
11670
|
+
const files = await fs35.readdir(dir);
|
|
11532
11671
|
const existedFile = files.find((f) => f.endsWith(`__${rootId}.jsonl`));
|
|
11533
11672
|
let fileName = "";
|
|
11534
11673
|
if (existedFile) {
|
|
@@ -11545,7 +11684,7 @@ var init_store3 = __esm({
|
|
|
11545
11684
|
});
|
|
11546
11685
|
|
|
11547
11686
|
// ../core/src/observability/trace.ts
|
|
11548
|
-
import
|
|
11687
|
+
import fs36 from "fs/promises";
|
|
11549
11688
|
import path38 from "path";
|
|
11550
11689
|
async function emitTrace(base) {
|
|
11551
11690
|
const event = {
|
|
@@ -11568,7 +11707,7 @@ async function emitTrace(base) {
|
|
|
11568
11707
|
async function appendTraceEvent(event) {
|
|
11569
11708
|
const p = await getTraceStorePath(event.sessionId);
|
|
11570
11709
|
const line = JSON.stringify(event) + "\n";
|
|
11571
|
-
await
|
|
11710
|
+
await fs36.appendFile(p, line, "utf-8");
|
|
11572
11711
|
if (workspaceTraceBytes < 0) {
|
|
11573
11712
|
workspaceTraceBytes = await getDirBytes(getTracePath());
|
|
11574
11713
|
}
|
|
@@ -11600,8 +11739,8 @@ async function maybeCleanupAfterAppend(sessionId) {
|
|
|
11600
11739
|
lastSizeCleanupAt2 = now;
|
|
11601
11740
|
diskLastCleanupAt2 = now;
|
|
11602
11741
|
const clockPath = getGlobalClockPath();
|
|
11603
|
-
await
|
|
11604
|
-
await
|
|
11742
|
+
await fs36.mkdir(path38.dirname(clockPath), { recursive: true });
|
|
11743
|
+
await fs36.writeFile(clockPath, JSON.stringify({ lastCleanupAt: now, updatedAt: (/* @__PURE__ */ new Date()).toISOString() }, null, 2), "utf-8");
|
|
11605
11744
|
if (deletedCount > 0) {
|
|
11606
11745
|
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`);
|
|
11607
11746
|
}
|
|
@@ -11621,7 +11760,7 @@ async function cleanupOldTraceFiles() {
|
|
|
11621
11760
|
let deleted = 0;
|
|
11622
11761
|
let relativePaths;
|
|
11623
11762
|
try {
|
|
11624
|
-
relativePaths = await
|
|
11763
|
+
relativePaths = await fs36.readdir(dir, { recursive: true });
|
|
11625
11764
|
} catch {
|
|
11626
11765
|
return 0;
|
|
11627
11766
|
}
|
|
@@ -11634,9 +11773,9 @@ async function cleanupOldTraceFiles() {
|
|
|
11634
11773
|
if (fileBornDay >= cutoff) continue;
|
|
11635
11774
|
const fullPath = path38.join(dir, relativePath);
|
|
11636
11775
|
try {
|
|
11637
|
-
const st = await
|
|
11776
|
+
const st = await fs36.stat(fullPath);
|
|
11638
11777
|
if (now - st.mtimeMs < ACTIVE_GRACE_MS2) continue;
|
|
11639
|
-
await
|
|
11778
|
+
await fs36.unlink(fullPath);
|
|
11640
11779
|
deleted += 1;
|
|
11641
11780
|
} catch {
|
|
11642
11781
|
}
|
|
@@ -11647,7 +11786,7 @@ async function evictOldestForSize2(targetBytes) {
|
|
|
11647
11786
|
const dir = getTracePath();
|
|
11648
11787
|
let relativePaths;
|
|
11649
11788
|
try {
|
|
11650
|
-
relativePaths = await
|
|
11789
|
+
relativePaths = await fs36.readdir(dir, { recursive: true });
|
|
11651
11790
|
} catch {
|
|
11652
11791
|
return 0;
|
|
11653
11792
|
}
|
|
@@ -11657,7 +11796,7 @@ async function evictOldestForSize2(targetBytes) {
|
|
|
11657
11796
|
const fileName = path38.basename(relativePath);
|
|
11658
11797
|
if (!re.test(fileName)) continue;
|
|
11659
11798
|
try {
|
|
11660
|
-
const st = await
|
|
11799
|
+
const st = await fs36.stat(path38.join(dir, relativePath));
|
|
11661
11800
|
candidates.push({ mtime: st.mtimeMs, fullPath: path38.join(dir, relativePath), size: st.size });
|
|
11662
11801
|
} catch {
|
|
11663
11802
|
}
|
|
@@ -11668,7 +11807,7 @@ async function evictOldestForSize2(targetBytes) {
|
|
|
11668
11807
|
for (const c of candidates) {
|
|
11669
11808
|
if (totalBytes <= targetBytes) break;
|
|
11670
11809
|
try {
|
|
11671
|
-
await
|
|
11810
|
+
await fs36.unlink(c.fullPath);
|
|
11672
11811
|
totalBytes -= c.size;
|
|
11673
11812
|
deleted += 1;
|
|
11674
11813
|
} catch {
|
|
@@ -11700,7 +11839,7 @@ var init_trace = __esm({
|
|
|
11700
11839
|
if (clockLoaded2) return;
|
|
11701
11840
|
clockLoaded2 = true;
|
|
11702
11841
|
try {
|
|
11703
|
-
const rawClock = await
|
|
11842
|
+
const rawClock = await fs36.readFile(getGlobalClockPath(), "utf-8");
|
|
11704
11843
|
diskLastCleanupAt2 = JSON.parse(rawClock).lastCleanupAt || 0;
|
|
11705
11844
|
} catch {
|
|
11706
11845
|
diskLastCleanupAt2 = 0;
|
|
@@ -11719,6 +11858,7 @@ var pendingLocks, waitForUserApproval, resolveUserApprovalLock;
|
|
|
11719
11858
|
var init_approvalGate = __esm({
|
|
11720
11859
|
"../core/src/tool/approvalGate.ts"() {
|
|
11721
11860
|
"use strict";
|
|
11861
|
+
init_lineage();
|
|
11722
11862
|
pendingLocks = /* @__PURE__ */ new Map();
|
|
11723
11863
|
waitForUserApproval = async (sessionId, toolsId, signal) => {
|
|
11724
11864
|
if (signal?.aborted) return "deny";
|
|
@@ -11746,7 +11886,7 @@ var init_approvalGate = __esm({
|
|
|
11746
11886
|
resolveUserApprovalLock = (sessionId, toolsId, decision) => {
|
|
11747
11887
|
const entry = pendingLocks.get(toolsId);
|
|
11748
11888
|
if (!entry) return false;
|
|
11749
|
-
const isOwner = entry.sessionId
|
|
11889
|
+
const isOwner = ownerCanApprove(entry.sessionId, sessionId);
|
|
11750
11890
|
if (!isOwner) return false;
|
|
11751
11891
|
entry.resolver(decision);
|
|
11752
11892
|
pendingLocks.delete(toolsId);
|
|
@@ -11846,7 +11986,7 @@ ${PLAN_MODE_AUTO_ENTER_HINT}
|
|
|
11846
11986
|
|
|
11847
11987
|
// ../core/src/serve/chatProcessing.ts
|
|
11848
11988
|
import path39 from "path";
|
|
11849
|
-
import
|
|
11989
|
+
import fs37 from "fs";
|
|
11850
11990
|
var handleUnifiedChat;
|
|
11851
11991
|
var init_chatProcessing = __esm({
|
|
11852
11992
|
"../core/src/serve/chatProcessing.ts"() {
|
|
@@ -11900,7 +12040,7 @@ ${inject}`;
|
|
|
11900
12040
|
if (roots.length > 1) {
|
|
11901
12041
|
let activeReal = getActiveWorkspaceRoot();
|
|
11902
12042
|
try {
|
|
11903
|
-
activeReal =
|
|
12043
|
+
activeReal = fs37.realpathSync(activeReal);
|
|
11904
12044
|
} catch {
|
|
11905
12045
|
}
|
|
11906
12046
|
const lines = roots.map((r) => `- ${path39.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"}`);
|
|
@@ -11997,7 +12137,7 @@ ${lines.join("\n")}
|
|
|
11997
12137
|
});
|
|
11998
12138
|
|
|
11999
12139
|
// ../core/src/session/fork.ts
|
|
12000
|
-
import
|
|
12140
|
+
import fs38 from "fs/promises";
|
|
12001
12141
|
var listForkAnchors, derivePrefix, forkSession;
|
|
12002
12142
|
var init_fork = __esm({
|
|
12003
12143
|
"../core/src/session/fork.ts"() {
|
|
@@ -12069,7 +12209,7 @@ var init_fork = __esm({
|
|
|
12069
12209
|
const prefix = derivePrefix(lines, upToLineId);
|
|
12070
12210
|
const newId = createUUID();
|
|
12071
12211
|
await ensureSessionsDir(newId);
|
|
12072
|
-
const rawText = await
|
|
12212
|
+
const rawText = await fs38.readFile(getTranscriptPath(sourceId), "utf-8");
|
|
12073
12213
|
const kept = [];
|
|
12074
12214
|
let good = 0;
|
|
12075
12215
|
for (const s of rawText.split("\n")) {
|
|
@@ -12085,7 +12225,7 @@ var init_fork = __esm({
|
|
|
12085
12225
|
}
|
|
12086
12226
|
let payload = kept.join("\n");
|
|
12087
12227
|
if (payload.length > 0 && !payload.endsWith("\n")) payload += "\n";
|
|
12088
|
-
await
|
|
12228
|
+
await fs38.writeFile(getTranscriptPath(newId), payload, "utf-8");
|
|
12089
12229
|
const srcState = await readStore(sourceId);
|
|
12090
12230
|
const srcRolling = await getRollingState(sourceId);
|
|
12091
12231
|
const legacy = !lines.some(isEventLine);
|
|
@@ -12101,6 +12241,9 @@ var init_fork = __esm({
|
|
|
12101
12241
|
rollingSummary,
|
|
12102
12242
|
consecutiveFailures: 0,
|
|
12103
12243
|
title: `${srcTitle}(\u5206\u53C9)`.slice(0, 200),
|
|
12244
|
+
// ★ fork 血缘元数据:新 ID 是纯 UUID(字符串上无痕),血缘回溯全靠此字段
|
|
12245
|
+
// (session/lineage.ts 消费:审批网关归属 / 子 Agent 续跑归属)。
|
|
12246
|
+
forkedFrom: sourceId,
|
|
12104
12247
|
// ★ 校准数据透传:fork 首轮压缩判定不从 1.4 重来(纯收益,语义同源会话续接)
|
|
12105
12248
|
calibRatio: srcRolling.calibRatio,
|
|
12106
12249
|
lastRealPromptTokens: srcRolling.lastRealPromptTokens,
|
|
@@ -13661,8 +13804,8 @@ var init_SlashMenu = __esm({
|
|
|
13661
13804
|
init_theme();
|
|
13662
13805
|
MAX_ROWS = 10;
|
|
13663
13806
|
SlashMenu = ({ entries, selectedIndex, cols }) => {
|
|
13664
|
-
const
|
|
13665
|
-
const
|
|
13807
|
+
const start = entries.length <= MAX_ROWS ? 0 : Math.max(0, Math.min(selectedIndex - MAX_ROWS + 1, selectedIndex, entries.length - MAX_ROWS));
|
|
13808
|
+
const visible = entries.slice(start, start + MAX_ROWS);
|
|
13666
13809
|
const cmdW = Math.min(22, Math.max(8, ...visible.map((e) => e.name.length)) + 1);
|
|
13667
13810
|
const descMax = Math.max(12, cols - cmdW - 6);
|
|
13668
13811
|
return /* @__PURE__ */ jsxs12(Box12, { flexDirection: "column", borderStyle: "round", borderColor: THEME.coral, paddingX: 1, paddingY: 0, marginTop: 1, children: [
|
|
@@ -13680,9 +13823,11 @@ var init_SlashMenu = __esm({
|
|
|
13680
13823
|
/* @__PURE__ */ jsx14(Text14, { color: active ? THEME.gray : THEME.grayDim, children: desc })
|
|
13681
13824
|
] }, e.name);
|
|
13682
13825
|
}),
|
|
13683
|
-
|
|
13684
|
-
"\
|
|
13685
|
-
|
|
13826
|
+
entries.length > MAX_ROWS ? /* @__PURE__ */ jsxs12(Text14, { color: THEME.coralMuted, children: [
|
|
13827
|
+
"\u2191\u2193 \u6EDA\u52A8 \xB7 ",
|
|
13828
|
+
selectedIndex + 1,
|
|
13829
|
+
"/",
|
|
13830
|
+
entries.length,
|
|
13686
13831
|
" \u6761"
|
|
13687
13832
|
] }) : null
|
|
13688
13833
|
] });
|
|
@@ -13778,11 +13923,11 @@ var init_TopPanel = __esm({
|
|
|
13778
13923
|
}
|
|
13779
13924
|
});
|
|
13780
13925
|
|
|
13781
|
-
// src/inspect.ts
|
|
13782
|
-
import
|
|
13926
|
+
// ../core/src/observability/inspect.ts
|
|
13927
|
+
import fs39 from "fs";
|
|
13783
13928
|
var CWD, fmt, readTrace, inspectUsage, inspectContext, inspectPermissions, inspectMcp, inspectHooks, inspectDebug;
|
|
13784
13929
|
var init_inspect = __esm({
|
|
13785
|
-
"src/inspect.ts"() {
|
|
13930
|
+
"../core/src/observability/inspect.ts"() {
|
|
13786
13931
|
"use strict";
|
|
13787
13932
|
init_config();
|
|
13788
13933
|
init_permissions();
|
|
@@ -13797,7 +13942,7 @@ var init_inspect = __esm({
|
|
|
13797
13942
|
if (!sessionId) return [];
|
|
13798
13943
|
try {
|
|
13799
13944
|
const p = await getTraceStorePath(sessionId);
|
|
13800
|
-
const text = await
|
|
13945
|
+
const text = await fs39.promises.readFile(p, "utf8");
|
|
13801
13946
|
const out = [];
|
|
13802
13947
|
for (const line of text.split("\n")) {
|
|
13803
13948
|
if (!line.trim()) continue;
|
|
@@ -13967,7 +14112,7 @@ var init_App = __esm({
|
|
|
13967
14112
|
return /* @__PURE__ */ jsx17(MessageBlock, { row, wrapW, streamTail });
|
|
13968
14113
|
};
|
|
13969
14114
|
isDynamicRow = (r) => r.kind === "assistant" && !!r.streaming || r.kind === "thinking" && !!r.streaming || r.kind === "tool" && r.status === "running" || r.kind === "todos" && !!r.active;
|
|
13970
|
-
App = ({ resumeSessionId, initialPlanMode, initialAutoMode, initialIncludeProject }) => {
|
|
14115
|
+
App = ({ resumeSessionId, initialPlanMode, initialAutoMode, initialIncludeProject, engineReady }) => {
|
|
13971
14116
|
const state = useChatState(resumeSessionId, initialPlanMode, initialAutoMode);
|
|
13972
14117
|
const { exit } = useApp();
|
|
13973
14118
|
const { stdout } = useStdout();
|
|
@@ -13979,6 +14124,16 @@ var init_App = __esm({
|
|
|
13979
14124
|
const [selectIdx, setSelectIdx] = useState4(0);
|
|
13980
14125
|
const [modelDisplay, setModelDisplay] = useState4(MODEL_NAME);
|
|
13981
14126
|
const [tick, setTick] = useState4(0);
|
|
14127
|
+
const [engineReadyFlag, setEngineReadyFlag] = useState4(false);
|
|
14128
|
+
useEffect4(() => {
|
|
14129
|
+
let alive = true;
|
|
14130
|
+
void engineReady.then(() => {
|
|
14131
|
+
if (alive) setEngineReadyFlag(true);
|
|
14132
|
+
});
|
|
14133
|
+
return () => {
|
|
14134
|
+
alive = false;
|
|
14135
|
+
};
|
|
14136
|
+
}, [engineReady]);
|
|
13982
14137
|
const [planEditing, setPlanEditing] = useState4(false);
|
|
13983
14138
|
const [planDraft, setPlanDraft] = useState4("");
|
|
13984
14139
|
const [planCursor, setPlanCursor] = useState4(0);
|
|
@@ -14092,7 +14247,7 @@ var init_App = __esm({
|
|
|
14092
14247
|
for (const name of LOCAL_COMMAND_NAMES) map.set(name, { name, description: descOf(name) });
|
|
14093
14248
|
for (const c of listCommands()) if (!map.has(c.name)) map.set(c.name, { name: c.name, description: c.description });
|
|
14094
14249
|
return [...map.values()];
|
|
14095
|
-
}, [tick]);
|
|
14250
|
+
}, [tick, engineReadyFlag]);
|
|
14096
14251
|
const filteredCommands = useMemo(() => {
|
|
14097
14252
|
if (!input.startsWith("/")) return [];
|
|
14098
14253
|
const q = input.slice(1).toLowerCase();
|
|
@@ -14256,12 +14411,18 @@ ${listText}`);
|
|
|
14256
14411
|
return false;
|
|
14257
14412
|
}
|
|
14258
14413
|
};
|
|
14414
|
+
const ensureEngine = async () => {
|
|
14415
|
+
if (engineReadyFlag) return;
|
|
14416
|
+
state.pushInfo("\u23F3 \u5F15\u64CE\u52A0\u8F7D\u4E2D\uFF08MCP/skills/commands\uFF09\u2026");
|
|
14417
|
+
await engineReady;
|
|
14418
|
+
};
|
|
14259
14419
|
const executeSlash = async (fullText) => {
|
|
14260
14420
|
const text = fullText.trim();
|
|
14261
14421
|
if (!text.startsWith("/")) {
|
|
14262
14422
|
await state.submit(text);
|
|
14263
14423
|
return;
|
|
14264
14424
|
}
|
|
14425
|
+
await ensureEngine();
|
|
14265
14426
|
if (await runLocalSlash(text)) return;
|
|
14266
14427
|
const name = text.slice(1).split(/\s+/)[0] ?? "";
|
|
14267
14428
|
if (listCommands().some((c) => c.name === name)) {
|
|
@@ -14288,6 +14449,7 @@ ${listText}`);
|
|
|
14288
14449
|
await executeSlash(v);
|
|
14289
14450
|
return;
|
|
14290
14451
|
}
|
|
14452
|
+
await ensureEngine();
|
|
14291
14453
|
await state.submit(v);
|
|
14292
14454
|
};
|
|
14293
14455
|
const confirmPlanEdit = () => {
|
|
@@ -14657,9 +14819,9 @@ var main = async () => {
|
|
|
14657
14819
|
Promise.resolve().then(() => (init_App(), App_exports)),
|
|
14658
14820
|
Promise.resolve().then(() => (init_config(), config_exports))
|
|
14659
14821
|
]);
|
|
14660
|
-
const
|
|
14822
|
+
const engineReady = initEngine2(agentTools2, { includeProject });
|
|
14661
14823
|
const onExit = () => {
|
|
14662
|
-
dispose();
|
|
14824
|
+
void engineReady.then((dispose) => dispose());
|
|
14663
14825
|
};
|
|
14664
14826
|
process.on("SIGINT", () => {
|
|
14665
14827
|
onExit();
|
|
@@ -14691,7 +14853,7 @@ var main = async () => {
|
|
|
14691
14853
|
resumeId = await getMostRecentSessionId2() ?? void 0;
|
|
14692
14854
|
}
|
|
14693
14855
|
const { waitUntilExit } = render(
|
|
14694
|
-
/* @__PURE__ */ jsx18(App2, { resumeSessionId: resumeId, initialPlanMode: args.plan, initialAutoMode: args.auto, initialIncludeProject: includeProject }),
|
|
14856
|
+
/* @__PURE__ */ jsx18(App2, { resumeSessionId: resumeId, initialPlanMode: args.plan, initialAutoMode: args.auto, initialIncludeProject: includeProject, engineReady }),
|
|
14695
14857
|
// exitOnCtrlC:false:Ctrl+C 交由 App useInput 处理(统一退出/中止语义);
|
|
14696
14858
|
// patchConsole:false:避免 console 劫持与全屏重绘叠加闪屏。
|
|
14697
14859
|
{ exitOnCtrlC: false, patchConsole: false }
|