dsh-vscode-mode 0.21.0 → 0.21.2
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 +7 -4
- package/lib/client.js +312 -75
- package/lib/client.js.map +2 -2
- package/lib/index.js +1536 -1290
- package/lib/index.js.map +1 -1
- package/package.json +1 -1
- package/src/client/addToConversation.ts +70 -45
- package/src/client/missingReview.ts +40 -0
- package/src/client/ui/EditorView.ts +118 -14
- package/src/client/ui/SidecarDiffBar.tsx +4 -2
- package/src/mcpDiagnostic.ts +42 -0
- package/src/mcpPool.ts +5 -1
- package/src/mcpRuntime.ts +11 -2
- package/src/missingReview.ts +127 -0
- package/src/rpc.ts +32 -6
- package/src/shared/rpc.ts +5 -1
- package/src/shared/types.ts +9 -0
package/README.md
CHANGED
|
@@ -477,18 +477,19 @@ DSH 每次启动监听随机端口,`http://127.0.0.1:<port>` 就是浏览器 o
|
|
|
477
477
|
|
|
478
478
|
官方 `dsh plugin` 方式,三选一。下面以 `web` profile 为例;Desktop 或其他命名
|
|
479
479
|
profile 请替换为实际目标,不要把示例目录当成当前运行 profile。升级前可阅读
|
|
480
|
-
**v0.21.
|
|
480
|
+
**v0.21.2** 的新版 DSH 会话 Controller 与 MCP 公开工具目录适配:任务发送按目标会话持有生命周期,受理不明时不跨通道重发;文件范围引用的剪贴板与降级文本保留行区间;MCP 初始化失败增加脱敏持久化诊断。当前 Web Host 已完成真实 CodeGraph 调用,但首次连接偶发超时根因尚未证实,不宣称已修复,见 [0.21.2 发布说明](docs/release-0.21.2.md)。保留以下历史版本能力与验收边界:
|
|
481
|
+
**v0.21.1** 修复缺失历史文件:按完整快照显示整文件删除,Keep 保留删除、Undo 安全恢复快照,预览只读且拒绝覆盖重新出现的文件;真实 GUI 验收缺口已明确保留,见 [0.21.1 发布说明](docs/release-0.21.1.md)。保留 **v0.21.0** 新增 XLSX 基础编辑与浏览器导出副本,原件不自动写回,高级应用通过官方 Host 打开;官方差异定位统一 BOM 与 LF/CRLF/混合行尾口径,并区分内容缺失和多处命中。定位修复不扩展 CRLF patch Undo 能力,目标官方记录 ↑/↓ 的真实点击验收仍保留缺口。保留 **v0.20.5** 跨 DSH 实例只读互通——桌面端与 Web 端各自运行独立宿主时,官方审查列表/详情与工作区只读接口改按持久化会话头的 cwd 解析,另一实例创建的会话也能只读打开官方差异栏,写入类接口仍要求本端活跃会话。保留 **v0.20.4** 统一两套差异栏外观——非官方记录栏角标由内部术语「侧车记录」改为「历史改动」,悬停说明 Keep 只标记已看过、不改写磁盘,Undo 逐项校验后写回,两者都不影响官方审查;官方元数据不可用时给出可读原因与重试按钮,不再静默降级;「会话没在当前端激活」由红色告警改为中性说明。保留 v0.20.3 修复官方差异全部无法定位时差异栏无提示、上下箭头静默禁用(显示「无可跳转」与失效原因,Keep 说明只标记已采纳、不改写磁盘,会话缺失等宿主错误改为可读提示)、v0.20.2 的 MCP 状态告警收敛与原生确认弹窗,以及 v0.20.1 的文件内差异展示、块级/文件级安全审查和跨分页批量操作。升级后重启 DSH 并刷新页面;持久化与回退边界见 [0.20.0 发布说明](docs/release-0.20.0.md);从 0.14.2 或更旧版本升级还须阅读
|
|
481
482
|
[0.14.3 数据迁移与回退说明](docs/release-0.14.3.md)。
|
|
482
483
|
|
|
483
484
|
```bash
|
|
484
485
|
# ① Git 安装(clone + prepare 构建;推荐打固定 tag)
|
|
485
|
-
dsh plugin --profile web add github:Lenonss/DSH_VsCodeMode#v0.21.
|
|
486
|
+
dsh plugin --profile web add github:Lenonss/DSH_VsCodeMode#v0.21.2
|
|
486
487
|
|
|
487
488
|
# ② npm 注册表(发布到 npm 后)
|
|
488
|
-
dsh plugin --profile web add dsh-vscode-mode@0.21.
|
|
489
|
+
dsh plugin --profile web add dsh-vscode-mode@0.21.2
|
|
489
490
|
|
|
490
491
|
# ③ GitHub Release tgz 直装(Release asset 可用后)
|
|
491
|
-
dsh plugin --profile web add https://github.com/Lenonss/DSH_VsCodeMode/releases/download/v0.21.
|
|
492
|
+
dsh plugin --profile web add https://github.com/Lenonss/DSH_VsCodeMode/releases/download/v0.21.2/dsh-vscode-mode-0.21.2.tgz
|
|
492
493
|
```
|
|
493
494
|
|
|
494
495
|
> **DSH 版本政策(0.17.0 起)**:六项 DSH peer 仍统一声明为 `*`,另以
|
|
@@ -829,6 +830,8 @@ Keep All / Undo All 却是亮的。修复:单文件 Keep / Undo 覆盖冲突
|
|
|
829
830
|
完整变更见 [GitHub Releases](https://github.com/Lenonss/DSH_VsCodeMode/releases)。
|
|
830
831
|
近期关键版本:
|
|
831
832
|
|
|
833
|
+
- **v0.21.2**:适配新版 DSH Session Controller 与 MCP 公开工具目录;固定目标任务发送持有会话直到完成或卸载,受理不明时不跨通道重发。范围文件引用的模型文本、剪贴板与纯文本降级保持一致。MCP 初始化失败记录阶段、耗时和脱敏错误链;迁移官方 native/PTC 执行器集成测试并增加可选真实 CodeGraph stdio 验证。当前 Web Host 真实工具调用已通过,首次连接偶发超时根因仍未证实;不自动部署或重启。见 [发布说明](docs/release-0.21.2.md)。
|
|
834
|
+
- **v0.21.1**:缺失历史文件读取完整快照并整文件显示删除行;Keep 保留删除,Undo 安全恢复当前展示快照,不覆盖重新出现的文件。删除预览只读,单文件和批量操作统一处理,记录变化或证据不足时停止。真实 GUI 验收缺口已获用户接受;发布不自动部署,升级后重启 DSH 并刷新页面。见 [发布说明](docs/release-0.21.1.md)。
|
|
832
835
|
- **v0.21.0**:新增 XLSX 基础编辑、多工作表与浏览器导出副本,原件不自动写回;不支持结构只读预览,高级应用经官方 Host 打开原件。编辑状态仅在当前页面内保留,不承诺刷新或崩溃恢复。官方差异定位统一 BOM 与 LF/CRLF/混合行尾口径,区分内容缺失与多处命中,保持原始字节及写回校验边界;不扩展 CRLF patch Undo 能力,目标官方记录 ↑/↓ 的真实点击仍未验收。升级后重启 DSH 并刷新页面;发布不自动部署当前实例。
|
|
833
836
|
- **v0.20.5**:**跨实例官方审查数据只读互通**——桌面端与 Web 端各自运行独立 DSH 宿主时,会话只存在于创建它的宿主内存里,插件原先一律用本进程的活跃会话解析工作区,另一端打开官方差异栏会拿到「会话不存在」并退化成历史改动栏。现在官方审查列表/详情与工作区只读接口(文件读取、原始字节、分页文本、记录桶、归档列表、目录列表、界面状态镜像)改为按持久化会话头的 cwd 解析:只要会话在共享的 `~/.dsh/sessions` 下留有会话头,其他实例即可只读访问它的官方审查数据;写入类接口(保存、回滚、采纳/拒绝、批量决策)仍要求本端活跃会话,避免两个宿主并发写同一工作区的审查库。已知限制:会话内 `cd` 过的记录只能按创建时的 cwd 冷读;桌面端本版本未重新部署,反向仍不可用。升级后重启 DSH 并刷新页面。
|
|
834
837
|
- **v0.20.4**:**两套差异栏不再互相冒充,内部术语退出界面**——插件本来并存官方审查栏与另一条历史记录栏(旧机制把每次改动留痕写进工作区 `.dsh-edit-review.json`),过去两者外观相同、无任何标识,容易被误认为插件未升级。现在非官方栏使用与官方栏同一套版式,但角标改为「历史改动」并在悬浮说明里讲清:这些改动没有进入官方审查列表,Keep 只标记看过、不改文件,Undo 会校验后写回,两者都不影响官方审查;设置页的「侧车摘要」一并对齐为日常说法。官方元数据通道失败(`edrv.review.list` 报错,如 `会话不存在`,或宿主未提供官方文件导航)时,在栏上方给出可读原因与重试按钮,不再静默降级;其中「会话没在当前端激活」由红色告警改为中性说明并存原始详情,真正的磁盘/回滚冲突错误仍保持红色。仅调整展示层,未改动数据库结构、决策语义与回退校验。
|
package/lib/client.js
CHANGED
|
@@ -377810,6 +377810,44 @@ td.UniverTableCell, th.UniverTableCell{mso-padding-alt:0cm 5.4pt 0cm 5.4pt;}
|
|
|
377810
377810
|
return regions;
|
|
377811
377811
|
}
|
|
377812
377812
|
//#endregion
|
|
377813
|
+
//#region src/client/missingReview.ts
|
|
377814
|
+
/** @public @author ddj 2026年10月28号 @param review Frozen complete snapshot. @returns One whole-file deletion, including empty files; no invented current lines. */
|
|
377815
|
+
function missingRegion(review) {
|
|
377816
|
+
return {
|
|
377817
|
+
callId: review.callIds[0],
|
|
377818
|
+
idx: 0,
|
|
377819
|
+
start: 1,
|
|
377820
|
+
end: 1,
|
|
377821
|
+
oldStart: 1,
|
|
377822
|
+
oldLines: splitLines(review.content.replace(/\r\n/g, "\n")),
|
|
377823
|
+
newLines: [],
|
|
377824
|
+
whole: true,
|
|
377825
|
+
status: "pending",
|
|
377826
|
+
create: false,
|
|
377827
|
+
superseded: false,
|
|
377828
|
+
sourceKind: "missing"
|
|
377829
|
+
};
|
|
377830
|
+
}
|
|
377831
|
+
/** @public @author ddj 2026年10月28号 @param paths Batch paths. @param api Guarded Host access. @returns Missing paths handled once; a partial failure stops before legacy hunk writes. @throws Missing evidence, changed lifecycle or Host decision failure. */
|
|
377832
|
+
async function missingBatch(paths, api) {
|
|
377833
|
+
const candidates = [];
|
|
377834
|
+
for (const path of new Set(paths)) {
|
|
377835
|
+
api.guard();
|
|
377836
|
+
const result = await api.query(path);
|
|
377837
|
+
if (!result.ok) throw new Error(result.error);
|
|
377838
|
+
if (result.review) candidates.push(result.review);
|
|
377839
|
+
}
|
|
377840
|
+
const completed = /* @__PURE__ */ new Set();
|
|
377841
|
+
for (const review of candidates) {
|
|
377842
|
+
api.guard();
|
|
377843
|
+
const result = await api.decide(review, api.operation(review));
|
|
377844
|
+
if (!result.ok) throw new Error(`已处理 ${completed.size} 个删除文件,其余未处理。${result.error}`);
|
|
377845
|
+
completed.add(review.path);
|
|
377846
|
+
api.committed(review, result.callIds);
|
|
377847
|
+
}
|
|
377848
|
+
return completed;
|
|
377849
|
+
}
|
|
377850
|
+
//#endregion
|
|
377813
377851
|
//#region src/client/editorModelState.ts
|
|
377814
377852
|
/** Monaco 编辑器实例选择器(限定在插件编辑器行内,排除官方预览等其它 Monaco)。 */
|
|
377815
377853
|
const EDITOR_MODEL_SELECTOR = ".edrv-editor-row .monaco-editor";
|
|
@@ -382728,7 +382766,10 @@ td.UniverTableCell, th.UniverTableCell{mso-padding-alt:0cm 5.4pt 0cm 5.4pt;}
|
|
|
382728
382766
|
onUndoAll: props.onUndoAllFiles,
|
|
382729
382767
|
keepTitle: "把这批历史改动全部标记为已看过(只改记录,不动磁盘文件)",
|
|
382730
382768
|
undoTitle: "逐项撤销这些历史改动;缺少证据或遇到冲突即停止"
|
|
382731
|
-
}),
|
|
382769
|
+
}), props.missingDeletion ? /* @__PURE__ */ react$1.default.createElement("div", {
|
|
382770
|
+
className: "edrv-review-notice",
|
|
382771
|
+
role: "status"
|
|
382772
|
+
}, "文件已删除 · 展示最后记录快照。Keep 保留删除;Undo 恢复展示的完整快照。") : null, busy ? /* @__PURE__ */ react$1.default.createElement("div", {
|
|
382732
382773
|
className: "edrv-review-notice",
|
|
382733
382774
|
role: "status"
|
|
382734
382775
|
}, "正在处理历史改动…") : null, down ? /* @__PURE__ */ react$1.default.createElement("div", {
|
|
@@ -382766,7 +382807,7 @@ td.UniverTableCell, th.UniverTableCell{mso-padding-alt:0cm 5.4pt 0cm 5.4pt;}
|
|
|
382766
382807
|
icon: barIcon("undo"),
|
|
382767
382808
|
onClick: props.onUndoFile,
|
|
382768
382809
|
disabled: !canDecide,
|
|
382769
|
-
title: SIDECAR_UNDO_TITLE
|
|
382810
|
+
title: props.missingDeletion ? "恢复展示的完整历史快照(不会覆盖重新出现的文件)" : SIDECAR_UNDO_TITLE
|
|
382770
382811
|
}, "Undo"), /* @__PURE__ */ react$1.default.createElement(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
382771
382812
|
size: "sm",
|
|
382772
382813
|
variant: "primary",
|
|
@@ -382774,7 +382815,7 @@ td.UniverTableCell, th.UniverTableCell{mso-padding-alt:0cm 5.4pt 0cm 5.4pt;}
|
|
|
382774
382815
|
icon: barIcon("check"),
|
|
382775
382816
|
onClick: props.onAcceptFile,
|
|
382776
382817
|
disabled: !canDecide,
|
|
382777
|
-
title: SIDECAR_KEEP_TITLE
|
|
382818
|
+
title: props.missingDeletion ? "保持文件删除并结清覆盖的待审历史记录,不写文件" : SIDECAR_KEEP_TITLE
|
|
382778
382819
|
}, "Keep"), /* @__PURE__ */ react$1.default.createElement(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
382779
382820
|
size: "sm",
|
|
382780
382821
|
variant: "ghost",
|
|
@@ -384367,25 +384408,57 @@ td.UniverTableCell, th.UniverTableCell{mso-padding-alt:0cm 5.4pt 0cm 5.4pt;}
|
|
|
384367
384408
|
if (!range || range.endLine < range.startLine) return mention;
|
|
384368
384409
|
return range.startLine === range.endLine ? `${mention} L${range.startLine}` : `${mention} L${range.startLine}-${range.endLine}`;
|
|
384369
384410
|
}
|
|
384370
|
-
/** 构造 DSH
|
|
384411
|
+
/** 构造 DSH 文件引用插入载荷,模型文本、剪贴板投影与降级文本共用完整行区间。
|
|
384412
|
+
* @public
|
|
384413
|
+
* @author ddj 2026年10月28号
|
|
384414
|
+
* @returns 引用载荷与含可选行区间的完整引用文本
|
|
384371
384415
|
* @param path 目标路径(相对 cwd 或绝对)
|
|
384372
384416
|
* @param cwd 会话工作区目录(可选)
|
|
384373
384417
|
* @param range 行区间(可选)
|
|
384374
384418
|
* @param appearance 引用外观:'file'(默认)| 'folder'
|
|
384375
384419
|
*/
|
|
384376
384420
|
function buildFileRef(path, cwd, range, appearance = "file") {
|
|
384377
|
-
const mention = mentionOf(path, cwd);
|
|
384421
|
+
const mention = refOf(mentionOf(path, cwd), range);
|
|
384378
384422
|
return {
|
|
384379
384423
|
mention,
|
|
384380
384424
|
reference: {
|
|
384381
384425
|
source: REF_SOURCE,
|
|
384382
|
-
ref:
|
|
384426
|
+
ref: mention,
|
|
384383
384427
|
label: labelOf(path, range),
|
|
384384
384428
|
appearance,
|
|
384385
384429
|
clipboardText: mention
|
|
384386
384430
|
}
|
|
384387
384431
|
};
|
|
384388
384432
|
}
|
|
384433
|
+
/** @private @author ddj 2026年10月28号 @param ctx Lifecycle owner. @param sessions Public Controller. @param id Fixed target. @param text Task body. @returns Acceptance; failures never retry another transport. @sideEffects Retains one generation until completion or unload. */
|
|
384434
|
+
async function sendOwned(ctx, sessions, id, text) {
|
|
384435
|
+
const controller = new AbortController();
|
|
384436
|
+
const reference = sessions.retain(id, {
|
|
384437
|
+
source: "controllerOperation",
|
|
384438
|
+
signal: controller.signal
|
|
384439
|
+
});
|
|
384440
|
+
let released = false;
|
|
384441
|
+
/** @private @author ddj 2026年10月28号 Cancel pending admission and release this exact generation once. */
|
|
384442
|
+
function release() {
|
|
384443
|
+
if (released) return;
|
|
384444
|
+
released = true;
|
|
384445
|
+
controller.abort();
|
|
384446
|
+
reference.release();
|
|
384447
|
+
}
|
|
384448
|
+
let remove;
|
|
384449
|
+
try {
|
|
384450
|
+
remove = ctx.effect?.(() => release, "vscode-mode: task session reference");
|
|
384451
|
+
const binding = await reference.ready;
|
|
384452
|
+
if (controller.signal.aborted) return false;
|
|
384453
|
+
return (await binding.session.prompt([{
|
|
384454
|
+
type: "text",
|
|
384455
|
+
text
|
|
384456
|
+
}], "queue", controller.signal)).ok === true;
|
|
384457
|
+
} finally {
|
|
384458
|
+
release();
|
|
384459
|
+
remove?.();
|
|
384460
|
+
}
|
|
384461
|
+
}
|
|
384389
384462
|
/** apiproxy wire 端点(POST /api/<method>;浏览器同源 fetch 自带 cookie 鉴权;实证 401=未鉴权而非 404)。 */
|
|
384390
384463
|
const SESSION_CREATE_PATH = "/api/session/create";
|
|
384391
384464
|
/** apiproxy wire 端点:发送任务(session/prompt;点击即发送方案)。 */
|
|
@@ -384484,8 +384557,9 @@ td.UniverTableCell, th.UniverTableCell{mso-padding-alt:0cm 5.4pt 0cm 5.4pt;}
|
|
|
384484
384557
|
}
|
|
384485
384558
|
/**
|
|
384486
384559
|
* 新建独立会话承载旁路任务(02-deep-session-prompt:深度分析不污染当前对话)。
|
|
384487
|
-
*
|
|
384488
|
-
*
|
|
384560
|
+
* 优先公开 sessions.create;旧 Host 按能力选择 remote 或 wire,调用后不换通道重试。
|
|
384561
|
+
* 受理状态不明时返回 ok:false,不重复创建会话。
|
|
384562
|
+
* @author ddj 2026年10月28号
|
|
384489
384563
|
* @author ddj 2026年09月23号
|
|
384490
384564
|
* @param ctx 客户端服务上下文(remote.session + sessions,仅回落用)
|
|
384491
384565
|
* @param cwd 新会话工作区目录(与当前会话同工作区)
|
|
@@ -384502,32 +384576,25 @@ td.UniverTableCell, th.UniverTableCell{mso-padding-alt:0cm 5.4pt 0cm 5.4pt;}
|
|
|
384502
384576
|
id
|
|
384503
384577
|
};
|
|
384504
384578
|
}
|
|
384505
|
-
|
|
384579
|
+
if (typeof sessions?.create === "function") return { ok: false };
|
|
384580
|
+
} catch {
|
|
384581
|
+
return { ok: false };
|
|
384582
|
+
}
|
|
384506
384583
|
try {
|
|
384507
384584
|
const remote = ctx.get("remote.session");
|
|
384508
384585
|
if (typeof remote?.create === "function") {
|
|
384509
384586
|
const payload = cwd ? { cwd } : {};
|
|
384510
|
-
|
|
384511
|
-
|
|
384512
|
-
|
|
384513
|
-
|
|
384514
|
-
|
|
384515
|
-
|
|
384516
|
-
|
|
384517
|
-
rpcId: mintRpcId(),
|
|
384518
|
-
payload
|
|
384519
|
-
},
|
|
384520
|
-
payload
|
|
384521
|
-
]) try {
|
|
384522
|
-
const r = rpcOk(await remote.create(arg));
|
|
384523
|
-
const id = r.value;
|
|
384524
|
-
if (r.ok && typeof id?.sessionId === "string") return {
|
|
384525
|
-
ok: true,
|
|
384526
|
-
id: id.sessionId
|
|
384527
|
-
};
|
|
384528
|
-
} catch {}
|
|
384587
|
+
const receipt = rpcOk(await remote.create(slotArg(payload)));
|
|
384588
|
+
const created = receipt.value;
|
|
384589
|
+
if (receipt.ok && typeof created?.sessionId === "string") return {
|
|
384590
|
+
ok: true,
|
|
384591
|
+
id: created.sessionId
|
|
384592
|
+
};
|
|
384593
|
+
return { ok: false };
|
|
384529
384594
|
}
|
|
384530
|
-
} catch {
|
|
384595
|
+
} catch {
|
|
384596
|
+
return { ok: false };
|
|
384597
|
+
}
|
|
384531
384598
|
try {
|
|
384532
384599
|
const id = await apiSessionCreate(cwd);
|
|
384533
384600
|
if (id) return {
|
|
@@ -384549,7 +384616,7 @@ td.UniverTableCell, th.UniverTableCell{mso-padding-alt:0cm 5.4pt 0cm 5.4pt;}
|
|
|
384549
384616
|
try {
|
|
384550
384617
|
const sessions = ctx.get("sessions");
|
|
384551
384618
|
const conversation = ctx.get("conversation");
|
|
384552
|
-
const actx = sessions?.scope?.(sessionId);
|
|
384619
|
+
const actx = typeof sessions?.binding === "function" ? sessions.binding(sessionId)?.ctx : sessions?.scope?.(sessionId);
|
|
384553
384620
|
const shell = actx && conversation?.input?.for?.(actx);
|
|
384554
384621
|
return shell && typeof shell.insertReference === "function" ? shell : void 0;
|
|
384555
384622
|
} catch {
|
|
@@ -384666,13 +384733,15 @@ td.UniverTableCell, th.UniverTableCell{mso-padding-alt:0cm 5.4pt 0cm 5.4pt;}
|
|
|
384666
384733
|
/**
|
|
384667
384734
|
* 新建独立会话(02-deep-session-prompt:旁路任务不污染当前对话)。
|
|
384668
384735
|
* 闭包持有真服务 ctx(面板 SidebarCtx 无 .get,会话操作必须经此门面);
|
|
384669
|
-
*
|
|
384736
|
+
* 新版仅返回已登记身份,视图选择由宿主负责;旧版保留可用的 open/select。
|
|
384737
|
+
* @author ddj 2026年10月28号
|
|
384670
384738
|
* @author ddj 2026年09月23号
|
|
384671
384739
|
* @param cwd 新会话工作区目录(与当前会话同工作区)
|
|
384672
384740
|
* @returns 新会话结果(失败供降级)
|
|
384673
384741
|
*/
|
|
384674
384742
|
const startDraftSession = async (cwd) => {
|
|
384675
384743
|
const result = await newDraftSession(ctx, cwd);
|
|
384744
|
+
if (typeof ctx.get("sessions")?.retain === "function") return result;
|
|
384676
384745
|
if (result.ok && result.id) try {
|
|
384677
384746
|
const sessions = ctx.get("sessions");
|
|
384678
384747
|
sessions?.materializeScope?.(result.id);
|
|
@@ -384685,30 +384754,23 @@ td.UniverTableCell, th.UniverTableCell{mso-padding-alt:0cm 5.4pt 0cm 5.4pt;}
|
|
|
384685
384754
|
};
|
|
384686
384755
|
/**
|
|
384687
384756
|
* 发送任务给目标会话 agent(点击即发送方案:任务落地会话即非 blank,列表可见)。
|
|
384688
|
-
*
|
|
384689
|
-
* @author ddj 2026年09月23号
|
|
384757
|
+
* 新版持有目标 Controller 到 prompt 结束;旧版按能力选择唯一通道,不跨通道重发。
|
|
384758
|
+
* @author ddj 2026年09月23号 / 2026年10月28号
|
|
384690
384759
|
* @param sessionId 目标会话 id
|
|
384691
384760
|
* @param text 任务文本
|
|
384692
384761
|
* @returns 是否受理
|
|
384693
384762
|
*/
|
|
384694
384763
|
const sendTask = async (sessionId, text) => {
|
|
384695
384764
|
if (!sessionId) return false;
|
|
384696
|
-
|
|
384765
|
+
try {
|
|
384766
|
+
const sessions = ctx.get("sessions");
|
|
384767
|
+
if (typeof sessions?.retain === "function") return await sendOwned(ctx, sessions, sessionId, text);
|
|
384697
384768
|
const input = inputFor(ctx, sessionId);
|
|
384698
|
-
if (
|
|
384769
|
+
if (typeof input?.setDraft === "function" && typeof input.submit === "function") {
|
|
384699
384770
|
input.setDraft(text);
|
|
384700
384771
|
input.submit();
|
|
384701
384772
|
return true;
|
|
384702
384773
|
}
|
|
384703
|
-
return false;
|
|
384704
|
-
};
|
|
384705
|
-
try {
|
|
384706
|
-
for (let attempt = 3; attempt > 0; attempt--) {
|
|
384707
|
-
if (await composerOnce()) return true;
|
|
384708
|
-
if (attempt > 1) await new Promise((resolve) => setTimeout(resolve, 500));
|
|
384709
|
-
}
|
|
384710
|
-
} catch {}
|
|
384711
|
-
try {
|
|
384712
384774
|
const remote = ctx.get("remote.session");
|
|
384713
384775
|
if (typeof remote?.prompt === "function") {
|
|
384714
384776
|
const payload = {
|
|
@@ -384719,26 +384781,12 @@ td.UniverTableCell, th.UniverTableCell{mso-padding-alt:0cm 5.4pt 0cm 5.4pt;}
|
|
|
384719
384781
|
text
|
|
384720
384782
|
}]
|
|
384721
384783
|
};
|
|
384722
|
-
|
|
384723
|
-
slotArg(payload),
|
|
384724
|
-
{ request: {
|
|
384725
|
-
rpcId: mintRpcId(),
|
|
384726
|
-
payload
|
|
384727
|
-
} },
|
|
384728
|
-
{
|
|
384729
|
-
rpcId: mintRpcId(),
|
|
384730
|
-
payload
|
|
384731
|
-
},
|
|
384732
|
-
payload
|
|
384733
|
-
]) try {
|
|
384734
|
-
if (rpcOk(await remote.prompt(arg)).ok) return true;
|
|
384735
|
-
} catch {}
|
|
384784
|
+
return rpcOk(await remote.prompt(slotArg(payload))).ok;
|
|
384736
384785
|
}
|
|
384737
|
-
} catch {}
|
|
384738
|
-
try {
|
|
384739
384786
|
return await apiSessionPrompt(sessionId, text);
|
|
384740
|
-
} catch {
|
|
384741
|
-
|
|
384787
|
+
} catch {
|
|
384788
|
+
return false;
|
|
384789
|
+
}
|
|
384742
384790
|
};
|
|
384743
384791
|
return {
|
|
384744
384792
|
appendReference,
|
|
@@ -393389,6 +393437,9 @@ td.UniverTableCell, th.UniverTableCell{mso-padding-alt:0cm 5.4pt 0cm 5.4pt;}
|
|
|
393389
393437
|
const [dirtyMap, setDirtyMap] = react$1.default.useState({});
|
|
393390
393438
|
const [content, setContent] = react$1.default.useState(null);
|
|
393391
393439
|
const [contentPath, setContentPath] = react$1.default.useState(null);
|
|
393440
|
+
const [missingPreview, setMissingPreview] = react$1.default.useState(null);
|
|
393441
|
+
const missingRef = react$1.default.useRef(/* @__PURE__ */ new Map());
|
|
393442
|
+
const missingNow = missingPreview?.path === active && missingPreview?.sessionId === sessionId ? missingPreview : null;
|
|
393392
393443
|
const [receiptLoad, setReceiptLoad] = react$1.default.useState(null);
|
|
393393
393444
|
const [imageSrc, setImageSrc] = react$1.default.useState(null);
|
|
393394
393445
|
const [imgSize, setImgSize] = react$1.default.useState(null);
|
|
@@ -393751,7 +393802,10 @@ td.UniverTableCell, th.UniverTableCell{mso-padding-alt:0cm 5.4pt 0cm 5.4pt;}
|
|
|
393751
393802
|
const regions = react$1.default.useMemo(() => {
|
|
393752
393803
|
const trace = isDebug() && contentReady && currentRecords.length > 0;
|
|
393753
393804
|
const start = trace ? performance.now() : 0;
|
|
393754
|
-
|
|
393805
|
+
let next;
|
|
393806
|
+
if (officialDetail) next = reviewRegions(officialDetail.diff, officialDetail.item.id, officialDetail.blocks ?? [], contentReady ? content : null);
|
|
393807
|
+
else if (missingNow && contentReady) next = missingNow.resolved ? [] : [missingRegion(missingNow)];
|
|
393808
|
+
else next = diffRegions(currentRecords, contentReady ? content : null).filter((r) => !r.superseded);
|
|
393755
393809
|
if (trace) try {
|
|
393756
393810
|
dbg(sessionId, `[DEBUG diffRegions] records=${currentRecords.length} bytes=${content.length} regions=${next.length} ms=${(performance.now() - start).toFixed(1)}`);
|
|
393757
393811
|
} catch (e) {}
|
|
@@ -393761,7 +393815,16 @@ td.UniverTableCell, th.UniverTableCell{mso-padding-alt:0cm 5.4pt 0cm 5.4pt;}
|
|
|
393761
393815
|
content,
|
|
393762
393816
|
contentPath,
|
|
393763
393817
|
active,
|
|
393764
|
-
officialDetail
|
|
393818
|
+
officialDetail,
|
|
393819
|
+
missingNow
|
|
393820
|
+
]);
|
|
393821
|
+
react$1.default.useEffect(() => {
|
|
393822
|
+
editorRef.current?.updateOptions({ readOnly: !!missingNow });
|
|
393823
|
+
}, [
|
|
393824
|
+
missingNow,
|
|
393825
|
+
active,
|
|
393826
|
+
content,
|
|
393827
|
+
monaco
|
|
393765
393828
|
]);
|
|
393766
393829
|
const pendingRegions = react$1.default.useMemo(() => regions.filter((r) => r.status === ST.PENDING && !r.stale), [regions]);
|
|
393767
393830
|
const staleRegions = react$1.default.useMemo(() => regions.filter((r) => r.status === ST.PENDING && r.stale), [regions]);
|
|
@@ -394236,7 +394299,13 @@ td.UniverTableCell, th.UniverTableCell{mso-padding-alt:0cm 5.4pt 0cm 5.4pt;}
|
|
|
394236
394299
|
/** @author ddj 2026年09月28号 @param res Disk content for a still-clean cached model. */
|
|
394237
394300
|
const accept = (res) => {
|
|
394238
394301
|
if (!loadCurrent(path, sequence) || dirtyRef.current[path] || model.getValue() !== before) return;
|
|
394302
|
+
if (res?.code === "file-missing") {
|
|
394303
|
+
loadMissing(path, sid, sequence);
|
|
394304
|
+
return;
|
|
394305
|
+
}
|
|
394239
394306
|
if (!res?.ok) return;
|
|
394307
|
+
missingRef.current.delete(path);
|
|
394308
|
+
setMissingPreview(null);
|
|
394240
394309
|
mark(res.version);
|
|
394241
394310
|
if (res.content === before) return;
|
|
394242
394311
|
saveViewState(path);
|
|
@@ -394259,6 +394328,48 @@ td.UniverTableCell, th.UniverTableCell{mso-padding-alt:0cm 5.4pt 0cm 5.4pt;}
|
|
|
394259
394328
|
* @param force 强制走 RPC(reloadFile 用,跳过 model 复用)
|
|
394260
394329
|
* @param version 已知磁盘版本(缺省走 RPC 返回值)
|
|
394261
394330
|
*/
|
|
394331
|
+
/** @private @author ddj 2026年10月28号 @param path Missing text file. @param sid Owning session. @param seq Loader generation. @sideEffects Loads deletion evidence without creating or saving the file. */
|
|
394332
|
+
async function loadMissing(path, sid, seq) {
|
|
394333
|
+
try {
|
|
394334
|
+
const result = await rpc("edrv.missingReview", {
|
|
394335
|
+
sessionId: sid,
|
|
394336
|
+
path
|
|
394337
|
+
});
|
|
394338
|
+
if (!loadCurrent(path, seq)) return;
|
|
394339
|
+
if (!result.ok) {
|
|
394340
|
+
failLoad(path, sid, seq, result.error);
|
|
394341
|
+
return;
|
|
394342
|
+
}
|
|
394343
|
+
if (!result.review) {
|
|
394344
|
+
loadContent(path, sid, true);
|
|
394345
|
+
return;
|
|
394346
|
+
}
|
|
394347
|
+
if (dirtyRef.current[path] || savingRef.current.has(path)) {
|
|
394348
|
+
failLoad(path, sid, seq, "文件已删除,但有未保存编辑;请先处理本地缓冲");
|
|
394349
|
+
return;
|
|
394350
|
+
}
|
|
394351
|
+
const preview = {
|
|
394352
|
+
...result.review,
|
|
394353
|
+
sessionId: sid,
|
|
394354
|
+
keepId: crypto.randomUUID(),
|
|
394355
|
+
undoId: crypto.randomUUID()
|
|
394356
|
+
};
|
|
394357
|
+
missingRef.current.set(path, preview);
|
|
394358
|
+
setMissingPreview(preview);
|
|
394359
|
+
setContent("");
|
|
394360
|
+
setContentPath(path);
|
|
394361
|
+
setLoadError(null);
|
|
394362
|
+
setError(null);
|
|
394363
|
+
stampLoad(path, sid, seq);
|
|
394364
|
+
setLoadStage({
|
|
394365
|
+
progress: 100,
|
|
394366
|
+
message: "文件已删除 · 展示最后记录快照"
|
|
394367
|
+
});
|
|
394368
|
+
setStatus("文件已删除 · 展示最后记录快照(只读)");
|
|
394369
|
+
} catch (cause) {
|
|
394370
|
+
if (loadCurrent(path, seq)) failLoad(path, sid, seq, String(cause));
|
|
394371
|
+
}
|
|
394372
|
+
}
|
|
394262
394373
|
const loadContent = (path, sid, force, version) => {
|
|
394263
394374
|
const seq = ++loadSeqRef.current;
|
|
394264
394375
|
setReceiptLoad({
|
|
@@ -394319,7 +394430,7 @@ td.UniverTableCell, th.UniverTableCell{mso-padding-alt:0cm 5.4pt 0cm 5.4pt;}
|
|
|
394319
394430
|
loadPdf(path, sid, seq, force === true, version);
|
|
394320
394431
|
return;
|
|
394321
394432
|
}
|
|
394322
|
-
const cachedModel = force ? null : modelsRef.current.get(path);
|
|
394433
|
+
const cachedModel = force || missingRef.current.has(path) ? null : modelsRef.current.get(path);
|
|
394323
394434
|
if (cachedModel) {
|
|
394324
394435
|
setContent(cachedModel.getValue());
|
|
394325
394436
|
setContentPath(path);
|
|
@@ -394346,6 +394457,8 @@ td.UniverTableCell, th.UniverTableCell{mso-padding-alt:0cm 5.4pt 0cm 5.4pt;}
|
|
|
394346
394457
|
} catch (e) {}
|
|
394347
394458
|
if (!loadCurrent(path, seq)) return;
|
|
394348
394459
|
if (res && res.ok) {
|
|
394460
|
+
missingRef.current.delete(path);
|
|
394461
|
+
setMissingPreview(null);
|
|
394349
394462
|
mark(res.version, true);
|
|
394350
394463
|
setContent(res.content);
|
|
394351
394464
|
setContentPath(path);
|
|
@@ -394356,6 +394469,10 @@ td.UniverTableCell, th.UniverTableCell{mso-padding-alt:0cm 5.4pt 0cm 5.4pt;}
|
|
|
394356
394469
|
}));
|
|
394357
394470
|
setStatus("已加载");
|
|
394358
394471
|
} else {
|
|
394472
|
+
if (res?.code === "file-missing") {
|
|
394473
|
+
loadMissing(path, sid, seq);
|
|
394474
|
+
return;
|
|
394475
|
+
}
|
|
394359
394476
|
if (res?.code === "file-too-large") setLargeCandidate(JSON.stringify([
|
|
394360
394477
|
scope,
|
|
394361
394478
|
sid,
|
|
@@ -394606,6 +394723,7 @@ td.UniverTableCell, th.UniverTableCell{mso-padding-alt:0cm 5.4pt 0cm 5.4pt;}
|
|
|
394606
394723
|
});
|
|
394607
394724
|
return;
|
|
394608
394725
|
}
|
|
394726
|
+
if (change.kind === "deleted" && change.path === activeRef.current && !dirtyRef.current[change.path] && !savingRef.current.has(change.path)) loadContent(change.path, sessionId, true);
|
|
394609
394727
|
const kind = change.kind === "deleted" ? "deleted" : "conflict";
|
|
394610
394728
|
markDiskFlag(readSync(scope, change.path) ?? {
|
|
394611
394729
|
path: change.path,
|
|
@@ -395591,6 +395709,10 @@ td.UniverTableCell, th.UniverTableCell{mso-padding-alt:0cm 5.4pt 0cm 5.4pt;}
|
|
|
395591
395709
|
/** @private @author ddj 2026年10月14号 @param path Canonical path. @param manual Explicit save. @returns Guarded save, never another pane's content. */
|
|
395592
395710
|
function saveDocument(path, manual) {
|
|
395593
395711
|
if (isExcelPath(path)) return Promise.resolve({ ok: false });
|
|
395712
|
+
if (missingRef.current.has(path)) {
|
|
395713
|
+
setStatus("删除预览只读;请使用 Keep / Undo");
|
|
395714
|
+
return Promise.resolve({ ok: false });
|
|
395715
|
+
}
|
|
395594
395716
|
const model = modelsRef.current.get(path);
|
|
395595
395717
|
if (!model) return Promise.resolve({ ok: false });
|
|
395596
395718
|
const store = documents();
|
|
@@ -395662,7 +395784,7 @@ td.UniverTableCell, th.UniverTableCell{mso-padding-alt:0cm 5.4pt 0cm 5.4pt;}
|
|
|
395662
395784
|
const ed = editorRef.current;
|
|
395663
395785
|
const model = ed?.getModel();
|
|
395664
395786
|
const path = [...modelsRef.current].find(([, item]) => item === model)?.[0];
|
|
395665
|
-
if (!ed || !path) return;
|
|
395787
|
+
if (!ed || !path || missingRef.current.has(path)) return;
|
|
395666
395788
|
setDirtyMap((d) => Object.assign({}, d, { [path]: true }));
|
|
395667
395789
|
touchTab(path);
|
|
395668
395790
|
setStatus("编辑中…");
|
|
@@ -395796,6 +395918,7 @@ td.UniverTableCell, th.UniverTableCell{mso-padding-alt:0cm 5.4pt 0cm 5.4pt;}
|
|
|
395796
395918
|
const side = layoutRef.current === "side";
|
|
395797
395919
|
const ed = m.editor.create(node, {
|
|
395798
395920
|
value: "",
|
|
395921
|
+
readOnly: missingRef.current.has(activeRef.current),
|
|
395799
395922
|
language: "plaintext",
|
|
395800
395923
|
theme: themeNameOf(),
|
|
395801
395924
|
fontFamily: "var(--ds-font-family-code, ui-monospace, monospace)",
|
|
@@ -396443,6 +396566,7 @@ td.UniverTableCell, th.UniverTableCell{mso-padding-alt:0cm 5.4pt 0cm 5.4pt;}
|
|
|
396443
396566
|
* @returns Promise<boolean> 是否成功
|
|
396444
396567
|
*/
|
|
396445
396568
|
const actHunk = (region, reject, silent) => {
|
|
396569
|
+
if (region.sourceKind === "missing") return decideMissing(reject);
|
|
396446
396570
|
if (region.sourceKind === "official") return decideOfficial(reject, region.id);
|
|
396447
396571
|
const method = reject ? "edrv.reject" : "edrv.accept";
|
|
396448
396572
|
const trace = isDebug();
|
|
@@ -396612,7 +396736,57 @@ td.UniverTableCell, th.UniverTableCell{mso-padding-alt:0cm 5.4pt 0cm 5.4pt;}
|
|
|
396612
396736
|
batchBusyRef.current = false;
|
|
396613
396737
|
}
|
|
396614
396738
|
}
|
|
396739
|
+
/** @private @author ddj 2026年10月28号 @param reject Restore the shown snapshot instead of keeping absence. @returns Safe whole-file decision, never a hunk reversal. */
|
|
396740
|
+
async function decideMissing(reject) {
|
|
396741
|
+
if (batchBusyRef.current || !missingNow || missingNow.resolved) return false;
|
|
396742
|
+
const preview = missingNow;
|
|
396743
|
+
const lifetime = reviewLifeRef.current;
|
|
396744
|
+
batchBusyRef.current = true;
|
|
396745
|
+
setReviewBatchBusy(true);
|
|
396746
|
+
try {
|
|
396747
|
+
guardReviewAll(reject, lifetime);
|
|
396748
|
+
const result = await rpc("edrv.missingDecide", {
|
|
396749
|
+
sessionId,
|
|
396750
|
+
token: preview.token,
|
|
396751
|
+
operationId: reject ? preview.undoId : preview.keepId,
|
|
396752
|
+
undo: reject
|
|
396753
|
+
});
|
|
396754
|
+
if (!lifetime?.live) return false;
|
|
396755
|
+
if (!result.ok) {
|
|
396756
|
+
setError(result.error);
|
|
396757
|
+
return false;
|
|
396758
|
+
}
|
|
396759
|
+
setRecords((previous) => Object.fromEntries(Object.entries(previous).filter(([id]) => !result.callIds.includes(id))));
|
|
396760
|
+
missingRef.current.set(preview.path, {
|
|
396761
|
+
...preview,
|
|
396762
|
+
resolved: true
|
|
396763
|
+
});
|
|
396764
|
+
if (activeRef.current === preview.path) {
|
|
396765
|
+
if (reject) loadContent(preview.path, sessionId, true);
|
|
396766
|
+
else setMissingPreview({
|
|
396767
|
+
...preview,
|
|
396768
|
+
resolved: true
|
|
396769
|
+
});
|
|
396770
|
+
}
|
|
396771
|
+
refreshRecords();
|
|
396772
|
+
emitRefresh({
|
|
396773
|
+
scope,
|
|
396774
|
+
paths: [preview.path],
|
|
396775
|
+
kind: "structure"
|
|
396776
|
+
});
|
|
396777
|
+
setStatus(reject ? "已恢复展示的完整历史快照" : "已保留文件删除");
|
|
396778
|
+
setError(null);
|
|
396779
|
+
return true;
|
|
396780
|
+
} catch (cause) {
|
|
396781
|
+
if (lifetime?.live) setError(String(cause));
|
|
396782
|
+
return false;
|
|
396783
|
+
} finally {
|
|
396784
|
+
batchBusyRef.current = false;
|
|
396785
|
+
if (lifetime?.live) setReviewBatchBusy(false);
|
|
396786
|
+
}
|
|
396787
|
+
}
|
|
396615
396788
|
const acceptFile = () => {
|
|
396789
|
+
if (missingNow && !officialDetail) return decideMissing(false);
|
|
396616
396790
|
if (officialDetail) return decideOfficial(false);
|
|
396617
396791
|
if (batchBusyRef.current || !decideRegions.length) return;
|
|
396618
396792
|
batchBusyRef.current = true;
|
|
@@ -396631,6 +396805,7 @@ td.UniverTableCell, th.UniverTableCell{mso-padding-alt:0cm 5.4pt 0cm 5.4pt;}
|
|
|
396631
396805
|
});
|
|
396632
396806
|
};
|
|
396633
396807
|
const undoFile = () => {
|
|
396808
|
+
if (missingNow && !officialDetail) return decideMissing(true);
|
|
396634
396809
|
if (officialDetail) return decideOfficial(true);
|
|
396635
396810
|
if (batchBusyRef.current || !decideRegions.length) return;
|
|
396636
396811
|
batchBusyRef.current = true;
|
|
@@ -396668,24 +396843,85 @@ td.UniverTableCell, th.UniverTableCell{mso-padding-alt:0cm 5.4pt 0cm 5.4pt;}
|
|
|
396668
396843
|
* @author ddj 2026年08月20号
|
|
396669
396844
|
* @param reject true=全部不采纳(回滚),false=全部采纳
|
|
396670
396845
|
*/
|
|
396671
|
-
const actAllPending = (reject) => {
|
|
396846
|
+
const actAllPending = async (reject) => {
|
|
396672
396847
|
if (batchBusyRef.current || !allPending.length) return;
|
|
396848
|
+
const lifetime = reviewLifeRef.current;
|
|
396673
396849
|
batchBusyRef.current = true;
|
|
396674
396850
|
const list = reject ? [...allPending].sort((a, b) => a.at < b.at ? 1 : a.at > b.at ? -1 : b.idx - a.idx) : allPending;
|
|
396675
396851
|
const paths = [...new Set(list.map((r) => records[r.callId]?.path).filter(Boolean))];
|
|
396676
|
-
|
|
396677
|
-
|
|
396678
|
-
|
|
396852
|
+
try {
|
|
396853
|
+
const handled = await missingBatch(paths, {
|
|
396854
|
+
query: async (path) => {
|
|
396855
|
+
const cached = missingRef.current.get(path);
|
|
396856
|
+
if (cached?.sessionId === sessionId && !cached.resolved) return {
|
|
396857
|
+
ok: true,
|
|
396858
|
+
review: cached
|
|
396859
|
+
};
|
|
396860
|
+
const result = await rpc("edrv.missingReview", {
|
|
396861
|
+
sessionId,
|
|
396862
|
+
path
|
|
396863
|
+
});
|
|
396864
|
+
if (result.ok && result.review) {
|
|
396865
|
+
const preview = {
|
|
396866
|
+
...result.review,
|
|
396867
|
+
sessionId,
|
|
396868
|
+
keepId: crypto.randomUUID(),
|
|
396869
|
+
undoId: crypto.randomUUID()
|
|
396870
|
+
};
|
|
396871
|
+
missingRef.current.set(path, preview);
|
|
396872
|
+
return {
|
|
396873
|
+
ok: true,
|
|
396874
|
+
review: preview
|
|
396875
|
+
};
|
|
396876
|
+
}
|
|
396877
|
+
return result;
|
|
396878
|
+
},
|
|
396879
|
+
decide: (preview, operationId) => rpc("edrv.missingDecide", {
|
|
396880
|
+
sessionId,
|
|
396881
|
+
token: preview.token,
|
|
396882
|
+
operationId,
|
|
396883
|
+
undo: reject
|
|
396884
|
+
}),
|
|
396885
|
+
guard: () => guardReviewAll(reject, lifetime),
|
|
396886
|
+
operation: (preview) => reject ? preview.undoId : preview.keepId,
|
|
396887
|
+
committed: (preview, callIds) => {
|
|
396888
|
+
if (!lifetime?.live) return;
|
|
396889
|
+
missingRef.current.set(preview.path, {
|
|
396890
|
+
...preview,
|
|
396891
|
+
resolved: true
|
|
396892
|
+
});
|
|
396893
|
+
setRecords((previous) => Object.fromEntries(Object.entries(previous).filter(([id]) => !callIds.includes(id))));
|
|
396894
|
+
if (!reject && sameFile(activeRef.current, preview.path)) setMissingPreview({
|
|
396895
|
+
...preview,
|
|
396896
|
+
path: activeRef.current,
|
|
396897
|
+
sessionId,
|
|
396898
|
+
resolved: true
|
|
396899
|
+
});
|
|
396900
|
+
emitRefresh({
|
|
396901
|
+
scope,
|
|
396902
|
+
paths: [preview.path],
|
|
396903
|
+
kind: "structure"
|
|
396904
|
+
});
|
|
396905
|
+
}
|
|
396906
|
+
});
|
|
396907
|
+
guardReviewAll(reject, lifetime);
|
|
396908
|
+
const remaining = list.filter((item) => !handled.has(records[item.callId]?.path));
|
|
396909
|
+
const result = await actMany(remaining.map((item) => itemOf(item, reject)));
|
|
396910
|
+
if (!lifetime?.live) return;
|
|
396911
|
+
if (reject || !missingNow) reloadFile(true);
|
|
396679
396912
|
emitRefresh({
|
|
396680
396913
|
scope,
|
|
396681
|
-
paths
|
|
396914
|
+
paths,
|
|
396682
396915
|
kind: "structure"
|
|
396683
396916
|
});
|
|
396684
|
-
setStatus(decideStatus(reject ? "已不采纳 " : "已采纳 ", result));
|
|
396685
|
-
if (result.fail) setError(result.fail + "
|
|
396686
|
-
}
|
|
396917
|
+
setStatus(decideStatus(reject ? "已不采纳 " : "已采纳 ", result) + `;删除文件 ${handled.size} 个`);
|
|
396918
|
+
if (result.fail) setError(result.fail + " 处差异处理失败,可刷新后重试");
|
|
396919
|
+
} catch (cause) {
|
|
396920
|
+
if (lifetime?.live) setError(String(cause));
|
|
396921
|
+
} finally {
|
|
396687
396922
|
batchBusyRef.current = false;
|
|
396688
|
-
|
|
396923
|
+
if (lifetime?.live) refreshRecords();
|
|
396924
|
+
}
|
|
396689
396925
|
};
|
|
396690
396926
|
/** @private @author ddj 2026年10月27号 @param reject Undo requires every local buffer to be saved. @param token Starting session lifetime. @returns Throws before the next mutation when unsafe. */
|
|
396691
396927
|
function guardReviewAll(reject, token) {
|
|
@@ -398286,6 +398522,7 @@ td.UniverTableCell, th.UniverTableCell{mso-padding-alt:0cm 5.4pt 0cm 5.4pt;}
|
|
|
398286
398522
|
const reviewErrorText = !rawReviewError ? void 0 : sessionDown ? SESSION_DOWN_NOTICE : sessionErrorText(rawReviewError);
|
|
398287
398523
|
const buildDockSnapshot = () => ({
|
|
398288
398524
|
mode: editorDockMode(active),
|
|
398525
|
+
missingDeletion: !!missingNow,
|
|
398289
398526
|
official: officialFile ? {
|
|
398290
398527
|
sessionId,
|
|
398291
398528
|
page: review.page,
|