dsh-vscode-mode 0.21.1 → 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 +5 -3
- package/lib/client.js +66 -59
- package/lib/client.js.map +2 -2
- package/lib/index.js +1330 -1293
- package/lib/index.js.map +1 -1
- package/package.json +1 -1
- package/src/client/addToConversation.ts +70 -45
- package/src/mcpDiagnostic.ts +42 -0
- package/src/mcpPool.ts +5 -1
- package/src/mcpRuntime.ts +11 -2
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.2** 的新版 DSH 会话 Controller 与 MCP 公开工具目录适配:任务发送按目标会话持有生命周期,受理不明时不跨通道重发;文件范围引用的剪贴板与降级文本保留行区间;MCP 初始化失败增加脱敏持久化诊断。当前 Web Host 已完成真实 CodeGraph 调用,但首次连接偶发超时根因尚未证实,不宣称已修复,见 [0.21.2 发布说明](docs/release-0.21.2.md)。保留以下历史版本能力与验收边界:
|
|
480
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,7 @@ 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)。
|
|
832
834
|
- **v0.21.1**:缺失历史文件读取完整快照并整文件显示删除行;Keep 保留删除,Undo 安全恢复当前展示快照,不覆盖重新出现的文件。删除预览只读,单文件和批量操作统一处理,记录变化或证据不足时停止。真实 GUI 验收缺口已获用户接受;发布不自动部署,升级后重启 DSH 并刷新页面。见 [发布说明](docs/release-0.21.1.md)。
|
|
833
835
|
- **v0.21.0**:新增 XLSX 基础编辑、多工作表与浏览器导出副本,原件不自动写回;不支持结构只读预览,高级应用经官方 Host 打开原件。编辑状态仅在当前页面内保留,不承诺刷新或崩溃恢复。官方差异定位统一 BOM 与 LF/CRLF/混合行尾口径,区分内容缺失与多处命中,保持原始字节及写回校验边界;不扩展 CRLF patch Undo 能力,目标官方记录 ↑/↓ 的真实点击仍未验收。升级后重启 DSH 并刷新页面;发布不自动部署当前实例。
|
|
834
836
|
- **v0.20.5**:**跨实例官方审查数据只读互通**——桌面端与 Web 端各自运行独立 DSH 宿主时,会话只存在于创建它的宿主内存里,插件原先一律用本进程的活跃会话解析工作区,另一端打开官方差异栏会拿到「会话不存在」并退化成历史改动栏。现在官方审查列表/详情与工作区只读接口(文件读取、原始字节、分页文本、记录桶、归档列表、目录列表、界面状态镜像)改为按持久化会话头的 cwd 解析:只要会话在共享的 `~/.dsh/sessions` 下留有会话头,其他实例即可只读访问它的官方审查数据;写入类接口(保存、回滚、采纳/拒绝、批量决策)仍要求本端活跃会话,避免两个宿主并发写同一工作区的审查库。已知限制:会话内 `cd` 过的记录只能按创建时的 cwd 冷读;桌面端本版本未重新部署,反向仍不可用。升级后重启 DSH 并刷新页面。
|
package/lib/client.js
CHANGED
|
@@ -384408,25 +384408,57 @@ td.UniverTableCell, th.UniverTableCell{mso-padding-alt:0cm 5.4pt 0cm 5.4pt;}
|
|
|
384408
384408
|
if (!range || range.endLine < range.startLine) return mention;
|
|
384409
384409
|
return range.startLine === range.endLine ? `${mention} L${range.startLine}` : `${mention} L${range.startLine}-${range.endLine}`;
|
|
384410
384410
|
}
|
|
384411
|
-
/** 构造 DSH
|
|
384411
|
+
/** 构造 DSH 文件引用插入载荷,模型文本、剪贴板投影与降级文本共用完整行区间。
|
|
384412
|
+
* @public
|
|
384413
|
+
* @author ddj 2026年10月28号
|
|
384414
|
+
* @returns 引用载荷与含可选行区间的完整引用文本
|
|
384412
384415
|
* @param path 目标路径(相对 cwd 或绝对)
|
|
384413
384416
|
* @param cwd 会话工作区目录(可选)
|
|
384414
384417
|
* @param range 行区间(可选)
|
|
384415
384418
|
* @param appearance 引用外观:'file'(默认)| 'folder'
|
|
384416
384419
|
*/
|
|
384417
384420
|
function buildFileRef(path, cwd, range, appearance = "file") {
|
|
384418
|
-
const mention = mentionOf(path, cwd);
|
|
384421
|
+
const mention = refOf(mentionOf(path, cwd), range);
|
|
384419
384422
|
return {
|
|
384420
384423
|
mention,
|
|
384421
384424
|
reference: {
|
|
384422
384425
|
source: REF_SOURCE,
|
|
384423
|
-
ref:
|
|
384426
|
+
ref: mention,
|
|
384424
384427
|
label: labelOf(path, range),
|
|
384425
384428
|
appearance,
|
|
384426
384429
|
clipboardText: mention
|
|
384427
384430
|
}
|
|
384428
384431
|
};
|
|
384429
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
|
+
}
|
|
384430
384462
|
/** apiproxy wire 端点(POST /api/<method>;浏览器同源 fetch 自带 cookie 鉴权;实证 401=未鉴权而非 404)。 */
|
|
384431
384463
|
const SESSION_CREATE_PATH = "/api/session/create";
|
|
384432
384464
|
/** apiproxy wire 端点:发送任务(session/prompt;点击即发送方案)。 */
|
|
@@ -384525,8 +384557,9 @@ td.UniverTableCell, th.UniverTableCell{mso-padding-alt:0cm 5.4pt 0cm 5.4pt;}
|
|
|
384525
384557
|
}
|
|
384526
384558
|
/**
|
|
384527
384559
|
* 新建独立会话承载旁路任务(02-deep-session-prompt:深度分析不污染当前对话)。
|
|
384528
|
-
*
|
|
384529
|
-
*
|
|
384560
|
+
* 优先公开 sessions.create;旧 Host 按能力选择 remote 或 wire,调用后不换通道重试。
|
|
384561
|
+
* 受理状态不明时返回 ok:false,不重复创建会话。
|
|
384562
|
+
* @author ddj 2026年10月28号
|
|
384530
384563
|
* @author ddj 2026年09月23号
|
|
384531
384564
|
* @param ctx 客户端服务上下文(remote.session + sessions,仅回落用)
|
|
384532
384565
|
* @param cwd 新会话工作区目录(与当前会话同工作区)
|
|
@@ -384543,32 +384576,25 @@ td.UniverTableCell, th.UniverTableCell{mso-padding-alt:0cm 5.4pt 0cm 5.4pt;}
|
|
|
384543
384576
|
id
|
|
384544
384577
|
};
|
|
384545
384578
|
}
|
|
384546
|
-
|
|
384579
|
+
if (typeof sessions?.create === "function") return { ok: false };
|
|
384580
|
+
} catch {
|
|
384581
|
+
return { ok: false };
|
|
384582
|
+
}
|
|
384547
384583
|
try {
|
|
384548
384584
|
const remote = ctx.get("remote.session");
|
|
384549
384585
|
if (typeof remote?.create === "function") {
|
|
384550
384586
|
const payload = cwd ? { cwd } : {};
|
|
384551
|
-
|
|
384552
|
-
|
|
384553
|
-
|
|
384554
|
-
|
|
384555
|
-
|
|
384556
|
-
|
|
384557
|
-
|
|
384558
|
-
rpcId: mintRpcId(),
|
|
384559
|
-
payload
|
|
384560
|
-
},
|
|
384561
|
-
payload
|
|
384562
|
-
]) try {
|
|
384563
|
-
const r = rpcOk(await remote.create(arg));
|
|
384564
|
-
const id = r.value;
|
|
384565
|
-
if (r.ok && typeof id?.sessionId === "string") return {
|
|
384566
|
-
ok: true,
|
|
384567
|
-
id: id.sessionId
|
|
384568
|
-
};
|
|
384569
|
-
} 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 };
|
|
384570
384594
|
}
|
|
384571
|
-
} catch {
|
|
384595
|
+
} catch {
|
|
384596
|
+
return { ok: false };
|
|
384597
|
+
}
|
|
384572
384598
|
try {
|
|
384573
384599
|
const id = await apiSessionCreate(cwd);
|
|
384574
384600
|
if (id) return {
|
|
@@ -384590,7 +384616,7 @@ td.UniverTableCell, th.UniverTableCell{mso-padding-alt:0cm 5.4pt 0cm 5.4pt;}
|
|
|
384590
384616
|
try {
|
|
384591
384617
|
const sessions = ctx.get("sessions");
|
|
384592
384618
|
const conversation = ctx.get("conversation");
|
|
384593
|
-
const actx = sessions?.scope?.(sessionId);
|
|
384619
|
+
const actx = typeof sessions?.binding === "function" ? sessions.binding(sessionId)?.ctx : sessions?.scope?.(sessionId);
|
|
384594
384620
|
const shell = actx && conversation?.input?.for?.(actx);
|
|
384595
384621
|
return shell && typeof shell.insertReference === "function" ? shell : void 0;
|
|
384596
384622
|
} catch {
|
|
@@ -384707,13 +384733,15 @@ td.UniverTableCell, th.UniverTableCell{mso-padding-alt:0cm 5.4pt 0cm 5.4pt;}
|
|
|
384707
384733
|
/**
|
|
384708
384734
|
* 新建独立会话(02-deep-session-prompt:旁路任务不污染当前对话)。
|
|
384709
384735
|
* 闭包持有真服务 ctx(面板 SidebarCtx 无 .get,会话操作必须经此门面);
|
|
384710
|
-
*
|
|
384736
|
+
* 新版仅返回已登记身份,视图选择由宿主负责;旧版保留可用的 open/select。
|
|
384737
|
+
* @author ddj 2026年10月28号
|
|
384711
384738
|
* @author ddj 2026年09月23号
|
|
384712
384739
|
* @param cwd 新会话工作区目录(与当前会话同工作区)
|
|
384713
384740
|
* @returns 新会话结果(失败供降级)
|
|
384714
384741
|
*/
|
|
384715
384742
|
const startDraftSession = async (cwd) => {
|
|
384716
384743
|
const result = await newDraftSession(ctx, cwd);
|
|
384744
|
+
if (typeof ctx.get("sessions")?.retain === "function") return result;
|
|
384717
384745
|
if (result.ok && result.id) try {
|
|
384718
384746
|
const sessions = ctx.get("sessions");
|
|
384719
384747
|
sessions?.materializeScope?.(result.id);
|
|
@@ -384726,30 +384754,23 @@ td.UniverTableCell, th.UniverTableCell{mso-padding-alt:0cm 5.4pt 0cm 5.4pt;}
|
|
|
384726
384754
|
};
|
|
384727
384755
|
/**
|
|
384728
384756
|
* 发送任务给目标会话 agent(点击即发送方案:任务落地会话即非 blank,列表可见)。
|
|
384729
|
-
*
|
|
384730
|
-
* @author ddj 2026年09月23号
|
|
384757
|
+
* 新版持有目标 Controller 到 prompt 结束;旧版按能力选择唯一通道,不跨通道重发。
|
|
384758
|
+
* @author ddj 2026年09月23号 / 2026年10月28号
|
|
384731
384759
|
* @param sessionId 目标会话 id
|
|
384732
384760
|
* @param text 任务文本
|
|
384733
384761
|
* @returns 是否受理
|
|
384734
384762
|
*/
|
|
384735
384763
|
const sendTask = async (sessionId, text) => {
|
|
384736
384764
|
if (!sessionId) return false;
|
|
384737
|
-
|
|
384765
|
+
try {
|
|
384766
|
+
const sessions = ctx.get("sessions");
|
|
384767
|
+
if (typeof sessions?.retain === "function") return await sendOwned(ctx, sessions, sessionId, text);
|
|
384738
384768
|
const input = inputFor(ctx, sessionId);
|
|
384739
|
-
if (
|
|
384769
|
+
if (typeof input?.setDraft === "function" && typeof input.submit === "function") {
|
|
384740
384770
|
input.setDraft(text);
|
|
384741
384771
|
input.submit();
|
|
384742
384772
|
return true;
|
|
384743
384773
|
}
|
|
384744
|
-
return false;
|
|
384745
|
-
};
|
|
384746
|
-
try {
|
|
384747
|
-
for (let attempt = 3; attempt > 0; attempt--) {
|
|
384748
|
-
if (await composerOnce()) return true;
|
|
384749
|
-
if (attempt > 1) await new Promise((resolve) => setTimeout(resolve, 500));
|
|
384750
|
-
}
|
|
384751
|
-
} catch {}
|
|
384752
|
-
try {
|
|
384753
384774
|
const remote = ctx.get("remote.session");
|
|
384754
384775
|
if (typeof remote?.prompt === "function") {
|
|
384755
384776
|
const payload = {
|
|
@@ -384760,26 +384781,12 @@ td.UniverTableCell, th.UniverTableCell{mso-padding-alt:0cm 5.4pt 0cm 5.4pt;}
|
|
|
384760
384781
|
text
|
|
384761
384782
|
}]
|
|
384762
384783
|
};
|
|
384763
|
-
|
|
384764
|
-
slotArg(payload),
|
|
384765
|
-
{ request: {
|
|
384766
|
-
rpcId: mintRpcId(),
|
|
384767
|
-
payload
|
|
384768
|
-
} },
|
|
384769
|
-
{
|
|
384770
|
-
rpcId: mintRpcId(),
|
|
384771
|
-
payload
|
|
384772
|
-
},
|
|
384773
|
-
payload
|
|
384774
|
-
]) try {
|
|
384775
|
-
if (rpcOk(await remote.prompt(arg)).ok) return true;
|
|
384776
|
-
} catch {}
|
|
384784
|
+
return rpcOk(await remote.prompt(slotArg(payload))).ok;
|
|
384777
384785
|
}
|
|
384778
|
-
} catch {}
|
|
384779
|
-
try {
|
|
384780
384786
|
return await apiSessionPrompt(sessionId, text);
|
|
384781
|
-
} catch {
|
|
384782
|
-
|
|
384787
|
+
} catch {
|
|
384788
|
+
return false;
|
|
384789
|
+
}
|
|
384783
384790
|
};
|
|
384784
384791
|
return {
|
|
384785
384792
|
appendReference,
|
package/lib/client.js.map
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
[diffend] Oversized file quarantined before diffing.
|
|
2
2
|
name: package/lib/client.js.map
|
|
3
|
-
size:
|
|
4
|
-
sha256:
|
|
3
|
+
size: 35441122 bytes
|
|
4
|
+
sha256: 7a0cd42b2d95ee169d929a0582c16b5732f1e05419aebc39c8d665bf7785e490
|