🎁 福利专区全网大模型免费应用 + 新用户福利 + 注册活动入口,低成本玩转 AI

VS Code 集成 HarcoChen/dsh-vsc-integration

DeepSeek Harness
HarcoChen13 天前有提交已提供中文文档扫描:含敏感能力

将 DeepSeek HarnessDSH带进 VS Code:结合IDE的上下文完成任务,查看原生Diff,通过…

43.9/100
综合分
19
GitHub 星标
—
npm 周下载
—/5
用户评分

数据截至 2026/10/21 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。

自动兼容检查有告警:未发布到 npm registry,仅可从源码安装。
安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add HarcoChen/dsh-vsc-integration
该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:已验证
是什么
dsh 原生插件 · dev
装得上吗
本站已真实安装成功
非静态推断
L4 · 真实安装等级说明 →
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 13 天前
档位由哪些信号合成

本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。

验证判据与等级说明 →
社区实装还没有人打卡 · 装过的第一个就是你
安装兼容性检查⚠ 装前注意

未发布到 npm registry,仅可从源码安装

展开查看检查明细 ↓

以下结论由程序自动检查 npm 包、engines 声明与入口文件得出,未做人工实机验证——能装不等于用着没问题。

✗npm 包dsh-vsc-integration(未发布到 npm,仅可源码安装)
✓Node 引擎未声明 engines.node
✓dsh CLI 依赖未声明 dsh 版本约束
✓入口文件main/exports/bin 已声明

验证方式:npm registry 存在性 + package.json 静态校验 · 最后检查 2026/10/30 04:32:55

安全扫描自动 · 静态分析源码
v2.7.0
🔵 扫描:含敏感能力尚无人工评估
展开查看扫描说明与证据 ↓

静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。

可执行外部命令读写/删除本地文件写入剪贴板(不计风险)发起外部网络请求
查看扫描证据(共 132 处,展示前 119 条)
  • 读取本地文件
    src/appShot.ts:23
    const metadata = await stat(path);
  • 读取本地文件
    src/appShot.ts:32
    const bytes = await readFile(path);
  • 删除本地文件
    src/appShot.ts:40
    await rm(path, { force: true });
  • 写入剪贴板
    src/chatView.ts:1572
    await vscode.env.clipboard.writeText(path);
  • 写入剪贴板
    src/codeBlockActions.ts:21
    await vscode.env.clipboard.writeText(text);
  • 读取本地文件
    src/codeBlockActions.ts:88
    realpath(folder.uri.fsPath),
  • 读取本地文件
    src/codeBlockActions.ts:89
    realpath(targetUri.fsPath),
  • 读取本地文件
    src/codeBlockActions.ts:123
    const latestRealTarget = await realpath(targetUri.fsPath);
  • 写入本地文件
    src/debugLaunch.ts:67
    await mkdir(options.directory, { recursive: true });
  • 写入本地文件
    src/debugLaunch.ts:68
    await writeFile(patchPath, patchBody(server.url), { encoding: "utf8", mode: 0o600 });
  • 删除本地文件
    src/debugLaunch.ts:85
    return this.server.stop().finally(() => rm(this.patchPath, { force: true }));
  • 读取本地文件
    src/debugLaunch.ts:117
    const entries = await readdir(directory).catch(() => [] as string[]);
  • 删除本地文件
    src/debugLaunch.ts:124
    await rm(path, { force: true }).catch(() => undefined);
  • 读取本地文件
    src/dshRuntime.ts:419
    await access(candidate, mode);
  • 发起网络请求
    src/dshRuntime.ts:2128
    response = await fetch(url, {
  • 写入本地文件
    src/dshRuntime.ts:3262
    await mkdir(this.recoveryLedger.directory, { recursive: true });
  • 写入本地文件
    src/dshRuntime.ts:3263
    await writeFile(
  • 发起网络请求
    src/dshRuntime.ts:3847
    const response = await fetch(launchUrl, {
  • 发起网络请求
    src/dshRuntime.ts:3887
    const response = await fetch(url, {
  • 发起网络请求
    src/dshRuntime.ts:3988
    const response = await fetch(remoteEndpointUrl(url, "session/list"), {
  • 写入剪贴板
    src/extension.ts:215
    await vscode.env.clipboard.writeText(path);
  • 读取本地文件
    src/fileLease.ts:42
    const stat = await lstat(path);
  • 读取本地文件
    src/fileLease.ts:45
    const contents = await readFile(path, "utf8");
  • 读取本地文件
    src/fileLease.ts:71
    const canonical = join(await realpath(dirname(path)), basename(path));
  • 删除本地文件
    src/fileLease.ts:148
    await unlink(staging);
  • 删除本地文件
    src/fileLease.ts:159
    await unlink(staging).catch(() => undefined);
  • 删除本地文件
    src/fileLease.ts:168
    try { await unlink(snapshot.path); return true; }
  • 读取本地文件
    src/jevIntegration.ts:366
    manifest = JSON.parse(await readFile(packageManifestPath, "utf8")) as PackageManifest;
  • 读取本地文件
    src/jevIntegration.ts:367
    await access(packageEntryPath);
  • 写入本地文件
    src/jevIntegration.ts:381
    await mkdir(options.outputDirectory, { recursive: true });
  • 写入本地文件
    src/jevIntegration.ts:392
    await writeFile(patchPath, `${JSON.stringify(patch, null, 2)}\n`, {
  • 读取本地文件
    src/localRuntimeUpgrade.ts:18
    const manifest = JSON.parse(await readFile(join(packageRoot, "package.json"), "utf8")) as {
  • 读取本地文件
    src/localRuntimeUpgrade.ts:23
    const entry = await realpath(resolve(packageRoot, bin));
  • 读取本地文件
    src/localRuntimeUpgrade.ts:24
    const withinPackage = relative(await realpath(packageRoot), entry);
  • 读取本地文件
    src/localRuntimeUpgrade.ts:26
    const commandPath = await realpath(command);
  • 读取本地文件
    src/localRuntimeUpgrade.ts:29
    const shim = (await readFile(command, "utf8")).replaceAll("\\", "/");
  • 读取本地文件
    src/localRuntimeUpgrade.ts:33
    ? await realpath(join(dirname(npm), "node_modules", "npm", "bin", "npm-cli.js"))
  • 写入剪贴板
    src/localRuntimeUpgrade.ts:115
    await vscode.env.clipboard.writeText(target);
  • 写入本地文件
    src/managedRuntime/cnbProvider.ts:345
    const writeStream = createWriteStream(destination);
  • 写入本地文件
    src/managedRuntime/index.ts:103
    await mkdir(tmpDir, { recursive: true });
  • 写入本地文件
    src/managedRuntime/index.ts:129
    await mkdir(dirname(targetVersionDir), { recursive: true });
  • 删除本地文件递归
    src/managedRuntime/index.ts:133
    await rm(targetVersionDir, { recursive: true, force: true });
  • 写入本地文件
    src/managedRuntime/index.ts:137
    await rename(stagingDir, targetVersionDir);
  • 删除本地文件递归
    src/managedRuntime/index.ts:140
    await rm(tmpDir, { recursive: true, force: true }).catch(() => undefined);
  • 读取本地文件
    src/managedRuntime/runtimeCache.ts:27
    const raw = await readFile(metadataPath(versionDirectory), "utf8");
  • 写入本地文件
    src/managedRuntime/runtimeCache.ts:46
    await mkdir(versionDirectory, { recursive: true });
  • 写入本地文件
    src/managedRuntime/runtimeCache.ts:47
    await writeFile(metadataPath(versionDirectory), JSON.stringify(metadata, null, 2), "utf8");
  • 读取本地文件
    src/managedRuntime/runtimeCache.ts:69
    await access(launcher, constants.X_OK);
  • 读取本地文件
    src/managedRuntime/runtimeCache.ts:75
    await access(runtimeDataDir(dir), constants.F_OK);
  • 写入本地文件
    src/managedRuntime/runtimeCache.ts:109
    await mkdir(locksDir, { recursive: true });
  • 删除本地文件
    src/managedRuntime/runtimeCache.ts:135
    await rm(lockPath, { force: true });
  • 删除本地文件
    src/managedRuntime/runtimeCache.ts:167
    await rm(lockPath, { force: true }).catch(() => undefined);
  • 读取本地文件
    src/managedRuntime/runtimeCache.ts:174
    const raw = await readFile(lockPath, "utf8");
  • 写入本地文件
    src/managedRuntime/runtimeDownloader.ts:56
    await rename(partPath, archivePath);
  • 写入本地文件
    src/managedRuntime/runtimeInstaller.ts:22
    await mkdir(stagingDir, { recursive: true });
  • 删除本地文件
    src/managedRuntime/runtimeInstaller.ts:39
    await rm(tarPath, { force: true }).catch(() => undefined);
  • 读取本地文件
    src/managedRuntime/runtimeInstaller.ts:45
    const source = createReadStream(sourcePath);
  • 写入本地文件
    src/managedRuntime/runtimeInstaller.ts:47
    const target = createWriteStream(targetPath);
  • 写入本地文件
    src/managedRuntime/runtimeInstaller.ts:108
    await mkdir(safeEntryPath(stagingDir, name), { recursive: true });
  • 写入本地文件
    src/managedRuntime/runtimeInstaller.ts:114
    await mkdir(dirname(entryPath), { recursive: true });
  • 写入本地文件
    src/managedRuntime/runtimeInstaller.ts:120
    await chmod(entryPath, filePermissions(mode));
  • 写入本地文件
    src/managedRuntime/runtimeInstaller.ts:171
    const writeStream = createWriteStream(targetPath);
  • 读取本地文件
    src/managedRuntime/runtimeInstaller.ts:310
    const source = createReadStream(archivePath, { start: dataOffset, end: dataOffset + compressedSize - 1 });
  • 读取本地文件
    src/managedRuntime/runtimeInstaller.ts:362
    const entries = await readdir(stagingDir, { withFileTypes: true });
  • 读取本地文件
    src/managedRuntime/runtimeInstaller.ts:369
    await access(launcher, constants.F_OK);
  • 读取本地文件
    src/managedRuntime/runtimeInstaller.ts:378
    await access(launcher, constants.X_OK);
  • 读取本地文件
    src/recovery/composition.ts:76
    const stat = await lstat(path);
  • 读取本地文件
    src/recovery/composition.ts:93
    return { ...fingerprint, contentHash: sha256(await readFile(path)) };
  • 读取本地文件
    src/recovery/composition.ts:142
    const value: unknown = JSON.parse(await readFile(path, "utf8"));
  • 写入本地文件
    src/recovery/diagnostics.ts:85
    await mkdir(directory, { recursive: true });
  • 写入本地文件
    src/recovery/diagnostics.ts:101
    await writeFile(path, contents, { encoding: "utf8", mode: 0o600 });
  • 写入本地文件
    src/recovery/diagnostics.ts:112
    await writeFile(path, contents, { encoding: "utf8", mode: 0o600 });
  • 写入本地文件
    src/recovery/diagnostics.ts:114
    await appendFile(path, line, { encoding: "utf8", mode: 0o600 });
  • 写入本地文件
    src/recovery/diagnostics.ts:138
    await writeFile(path, next.value, { encoding: "utf8", mode: 0o600 });
  • 写入本地文件
    src/recovery/diagnostics.ts:150
    await mkdir(join(target, "logs"), { recursive: true });
  • 读取本地文件
    src/recovery/diagnostics.ts:172
    await writeFile(join(target, "ledger-corrupt.txt"), redactRecoveryText(await readFile(corrupt.path, "utf8")),
  • 读取本地文件
    src/recovery/diagnostics.ts:182
    const files = await readdir(join(this.logsDirectory, session), { withFileTypes: true })
  • 读取本地文件
    src/recovery/diagnostics.ts:189
    const contents = await readFile(join(this.logsDirectory, session, file.name), "utf8")
  • 读取本地文件
    src/recovery/diagnostics.ts:199
    const entries = await readdir(this.logsDirectory, { withFileTypes: true }).catch(ignoreMissing) ?? [];
  • 读取本地文件
    src/recovery/diagnostics.ts:204
    const info = await stat(join(this.logsDirectory, entry.name)).catch(ignoreMissing);
  • 删除本地文件递归
    src/recovery/diagnostics.ts:212
    await rm(join(this.logsDirectory, item.name), { recursive: true, force: true }).catch(() => undefined);
  • 读取本地文件
    src/recovery/fixExecutor.ts:91
    const original = await readFile(manifestPath, "utf8");
  • 写入本地文件
    src/recovery/fixExecutor.ts:120
    await mkdir(this.backupsDirectory, { recursive: true });
  • 读取本地文件
    src/recovery/fixExecutor.ts:127
    if (sha256(await readFile(manifestPath, "utf8")) !== beforeHash) {
  • 读取本地文件
    src/recovery/fixExecutor.ts:169
    const current = await readFile(backup.target, "utf8");
  • 读取本地文件
    src/recovery/fixExecutor.ts:189
    const value: unknown = JSON.parse(await readFile(
  • 读取本地文件
    src/recovery/fixExecutor.ts:206
    const info = await lstat(path);
  • 发起网络请求
    src/recovery/healthOracle.ts:139
    const response = await fetch(endpoint.launchUrl, {
  • 写入本地文件
    src/recovery/ledger.ts:82
    await mkdir(this.directory, { recursive: true });
  • 写入本地文件
    src/recovery/ledger.ts:94
    await writeFile(this.leasePath, JSON.stringify({ pid: process.pid, ownerId }), { flag: "wx", mode: 0o600 });
  • 读取本地文件
    src/recovery/ledger.ts:117
    const contents = await readFile(this.path, "utf8");
  • 写入本地文件
    src/recovery/ledger.ts:339
    await mkdir(this.directory, { recursive: true });
  • 写入本地文件
    src/recovery/ledger.ts:350
    await mkdir(dirname(path), { recursive: true });
  • 写入本地文件
    src/recovery/ledger.ts:353
    await writeFile(temporary, contents, { encoding: "utf8", flag: "wx", mode: 0o600 });
  • 删除本地文件
    src/recovery/ledger.ts:356
    await rm(temporary, { force: true });
  • 写入本地文件
    src/recovery/ledger.ts:369
    await rename(source, target);
  • 读取本地文件
    src/recovery/sandbox.ts:88
    await lstat(path);
  • 写入本地文件
    src/recovery/sandbox.ts:98
    await mkdir(dirname(target), { recursive: true });
  • 写入本地文件
    src/recovery/sandbox.ts:104
    await mkdir(dirname(target), { recursive: true });
  • 读取本地文件
    src/recovery/sandbox.ts:126
    const parsed: unknown = JSON.parse(await readFile(source, "utf8"));
  • 写入本地文件
    src/recovery/sandbox.ts:143
    await mkdir(dirname(target), { recursive: true });
  • 写入本地文件
    src/recovery/sandbox.ts:144
    await writeFile(target, `${JSON.stringify(value, null, 2)}\n`, { encoding: "utf8", mode: 0o600 });
  • 写入本地文件
    src/recovery/sandbox.ts:161
    await mkdir(workspace, { recursive: true });
  • 写入本地文件
    src/recovery/sandbox.ts:162
    await mkdir(temp, { recursive: true });
  • 删除本地文件
    src/recovery/sandbox.ts:226
    await rm(path, { force: true });
  • 删除本地文件递归
    src/recovery/sandbox.ts:232
    await rm(root, { recursive: true, force: true });
  • 删除本地文件递归
    src/recovery/sandbox.ts:241
    await rm(root, { recursive: true, force: true });
  • 写入本地文件
    src/runtimeAdvertisement.ts:32
    await mkdir(runtimeAdvertisementDirectory(), { recursive: true, mode: 0o700 });
  • 写入本地文件
    src/runtimeAdvertisement.ts:35
    await writeFile(staging, JSON.stringify(record), { flag: "wx", mode: 0o600 });
  • 写入本地文件
    src/runtimeAdvertisement.ts:36
    await rename(staging, path);
  • 删除本地文件
    src/runtimeAdvertisement.ts:37
    } finally { await unlink(staging).catch(() => undefined); }
  • 删除本地文件
    src/runtimeAdvertisement.ts:41
    await unlink(advertisementPath(ownerId)).catch(() => undefined);
  • 读取本地文件
    src/runtimeAdvertisement.ts:69
    const names = await readdir(directory).catch(() => [] as string[]);
  • 读取本地文件
    src/runtimeAdvertisement.ts:74
    const stat = await lstat(path);
  • 读取本地文件
    src/runtimeAdvertisement.ts:76
    return { value: JSON.parse(await readFile(path, "utf8")) as unknown, time: stat.mtimeMs };
  • 执行外部命令来自配置/变量
    src/runtimeProcess.ts:11
    const child = spawn(command, args, { ...options, detached: group });
  • 读取本地文件
    src/workspaceNavigation.ts:32
    const realRoots = await Promise.all(roots.map((root) => realpath(root)));
  • 读取本地文件
    src/workspaceNavigation.ts:36
    const resolved = await realpath(candidate);
  • 读取本地文件
    src/workspaceNavigation.ts:37
    const metadata = await stat(resolved);
扫描于 2026/11/2(1 天前) · 范围 入口闭包 + 全包扫描 · 来源 GitHub 仓库

静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。

给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

界面预览

6 张 · 点击查看大图

功能亮点

  • IDE上下文任务
  • 原生Diff查看
  • 工具审批

README

由 DeepSeek 最新模型翻译生成
DeepSeek Harness for VS Code 将 DeepSeek Harness(DSH)带进 VS Code:结合IDE的上下文完成任务,查看原生Diff,通过 Trace 和用量面板了解Agent的执行过程。 安装到 VS Code · Open VSX ·下载 VSIX ·更新日志 独立社区项目,欢迎提 issue。 JetBrains IDE版本请见 dsh-intellij-integration。 为什么选择 DSH? - 看清代码改动:在 VS Code 原生并排 Diff 中审查工具编辑,非 Git 仓库也能使用。 - 在执行前做决定:审批卡展示命令与目标文件,受支持的文件写入可预览拟议改动。 - 带着上下文开始任务:引用文件、选区、Git Diff 或暂停时的调试状态,减少来回复制粘贴。 - 随时接着做:恢复持久会话,在活动面板查看工具执行、子代理、Todo 与 Token 用量。 - 更聪明的 Agent 决策,无需额外安装:打开内置的 Laya/Jev 集成,发现循环、精简冗长输出,并用证据核对“已完成”的说法。 快速开始 需要 VS Code 1.106.0 或更高版本,以及已配置的 DSH 模型服务与凭据。
展开完整文档(README 剩余 1 节)
DeepSeek Harness for VS Code

将 DeepSeek Harness(DSH)带进 VS Code:结合IDE的上下文完成任务,查看原生Diff,通过 Trace 和用量面板了解Agent的执行过程。

安装到 VS Code · Open VSX ·下载 VSIX ·更新日志

独立社区项目,欢迎提 issue。

JetBrains IDE版本请见 dsh-intellij-integration。

为什么选择 DSH?

- 看清代码改动:在 VS Code 原生并排 Diff 中审查工具编辑,非 Git 仓库也能使用。
- 在执行前做决定:审批卡展示命令与目标文件,受支持的文件写入可预览拟议改动。
- 带着上下文开始任务:引用文件、选区、Git Diff 或暂停时的调试状态,减少来回复制粘贴。
- 随时接着做:恢复持久会话,在活动面板查看工具执行、子代理、Todo 与 Token 用量。
- 更聪明的 Agent 决策,无需额外安装:打开内置的 Laya/Jev 集成,发现循环、精简冗长输出,并用证据核对“已完成”的说法。

快速开始

需要 VS Code 1.106.0 或更高版本,以及已配置的 DSH 模型服务与凭据。

1. 安装扩展:选择上方 Marketplace 或 Open VSX 入口,也可以在扩展面板搜索 harcochen.dsh-vsc-integration。
2. 打开聊天:安装并启动官方 DeepSeek Desktop,打开项目文件夹并确认信任,在命令面板运行 DSH: 打开聊天(DSH: Open Chat)。Desktop 会注册 dsh;命令不可用时,扩展会提供官方下载安装页。
3. 完成首次配置:通过 DSH: 配置 API Key(DSH: Configure API Key)设置 DeepSeek 凭据。其他 Provider 可在 DSH: 在浏览器中打开 dsh Web UI 中配置。选择或注册 DSH Workspace,再选择模型。
4. 开始一个任务:输入 @ 引用文件,或右键选区选择 DSH 操作。查看执行过程,在需要审批时确认操作,并通过工具卡打开 Diff 审查结果。
5. (可选)启用 Laya/Jev:打开 dsh.jev.enabled 及需要的功能开关,运行 DSH: 配置 Jev API Key,按提示重启 Runtime。详见 内置 Laya / Jev System One 决策。

从这些任务开始

| 你想做什么 | 可以这样开始 |
| 读懂一段代码 | 选中代码并右键使用 DSH 解释:“说明这段代码的执行流程和边界条件。” |
| 审查改动 | 对 Git Diff 使用 DSH 评审:“检查这些改动是否引入回归,并标出相关位置。” |
| 排查断点 | 调试暂停时运行 DSH: Explain Current Debug State,附加调用栈和局部变量等上下文。 |
| 继续之前的工作 | 切换到历史会话,通过对话大纲定位之前的讨论。 |

核心功能

逐次编辑皆有原生 Diff,无需 Git

write / edit 类工具调用完成后,打开目标文件即可查看 VS Code 原生并排 Diff。底层通过 Session 日志倒放 Hunks 重建历史,即使在非 Git 仓库或被 Git ignore 的文件中也能正常工作。

原生并排 Diff 预览

批准前预览

审批卡片会展示真实的命令行、工作目录以及写入的目标文件,对于受支持的文件写入工具,还可以在批准前打开原生 Diff,检查拟议改动。

若目标文件在编辑器中仍有未保存改动,审批不会被放行:卡片会列出这些文件并保持待处理,保存或还原后即可重新批准。

内置 Laya / Jev System One 决策

Jev 是 TypeSafe 推出的 System One 决策模型。它不生成文本,而是读取 Agent 状态,在毫秒级返回经过校准的结构化答案。Laya 是 Apache-2.0 协议的开源权重替代品,提供相同的 POST /v1/systemone 请求与响应格式。扩展随包携带 dsh-jev-integration Runtime 插件(与 JetBrains 版共用),并挂载到它启动的每个 Runtime 上。不需要另装插件,也不需要改 DSH profile。

| 功能 | 设置 | 作用 |
| 循环保护 | dsh.jev.loopGuard.enabled | 工具执行后识别语义上的死循环,引导 Agent 跳出。 |
| 结果整形 | dsh.jev.resultShaper.enabled | 对重复的大段工具输出分类折叠,保留警告与失败信息。 |
| 完成检查 | dsh.jev.doneGate.enabled | 用工具证据核对“已完成”的说法,必要时追加一轮验证。 |
| 工具裁剪 | dsh.jev.toolPruner.enabled | 对模型可见的工具 schema 排序,不改变 DSH 权限和工具注册。 |
| Skill 路由 | dsh.jev.skillRouter.enabled | 挑选相关 skill,并在上下文中加入有长度上限的建议。 |
| 决策工具 | dsh.jev.decisionTools.enabled | 向 Agent 暴露 jev_ask、jev_rank、jev_check 工具。 |
| 确定性安全检查 | dsh.jev.deterministicSafetyGuard.enabled | 在本地检查破坏性命令、提权和凭据泄露,检查数据不出本机。 |

使用 Jev:打开 dsh.jev.enabled 及需要的功能,运行 DSH: 配置 Jev API Key,按提示重启 Runtime。Key 加密保存在 VS Code SecretStorage。

使用 Laya:将 dsh.jev.baseUrl 指向提供 Laya System One 接口的 HTTPS 地址,dsh.jev.model 设为该服务要求的模型名,并配置 API Key;服务端不校验 Key 时填任意占位值即可。扩展只接受 https:// 地址,其他地址会回退到 TypeSafe 默认端点。

所有功能默认关闭。启用后,相关功能可能把所需样本发送到配置的端点。已有或外部托管的 Runtime 不会被修改。

会话、账号与定时提醒(dsh 0.2.0-rc.2)

- DSH: 管理会话 可置顶会话、恢复已归档会话;DSH: 归档会话 遇到仍在运行的任务时,会先询问是否停止。没有打开 VS Code 文件夹时也能使用 DSH Workspace。
- DSH: 管理 DeepSeek 账号 支持浏览器登录、登出,并查看账号资料和余额。
- DSH: 浏览 Runtime 工作区文件(也可在 /ide 中选择)浏览当前 DSH 会话的工作区,在编辑器打开上限为 1 MiB 的 UTF-8 文本只读预览。文件变化会刷新已打开的预览;不支持监听时可运行 DSH: 刷新 Runtime 文件预览。
- 启用官方 Schedule bundle 后,定时提醒面板可跨会话列出提醒、编辑规则、查看投递历史并删除提醒;未启用时面板会提示如何开启。

Runtime 终端、插件安装与 Problems(开发分支)

- DSH: 打开 Runtime 终端 连接当前 DSH 会话的 Host PTY,也可从聊天菜单打开。切换会话保留终端;重连恢复屏幕和输入控制权。关闭终端请求 Host 清理进程,失败时再次打开此入口重试。进程保留范围为 Host 生命周期;已有终端保留自己的工作目录。终端输入使用上游用户 Shell 权限。
- DSH: 安装或卸载 Runtime 插件 使用官方插件管理器检查包来源、版本和 Bundle,安装时可取消,并查看日志和生效/需重启状态。包路径按 Runtime 主机解析;构建脚本需单独批准。Settings 和聊天菜单也提供入口。
- 附件菜单或 @ 候选中的“当前文件的问题”可选择诊断后附加到下一条消息。手写 @diagnostics 会附加当前文件诊断;附件包含位置、来源和代码,显示大小与截断状态,不自动发送。
- DSH: 打开会话中心 标明会话所属 DSH Workspace,优先排列已观察到的审批、问题、错误和运行中任务,点击继续对应会话。
- 聊天显示当前有效目录。连接 alpha.2 时,目录变更不改变原始项目归属;历史工具 Diff 和文件链接使用历史目录,同轮跨目录改动通过逐次工具 Diff 审查。

斜杠命令

斜杠菜单会动态拉取当前会话 Runtime 注册的命令(/plan、/compact、/goal 等),并与扩展自有的 IDE 命令合并展示。

实时下拉斜杠命令

编辑器与 Git 上下文

- 右键菜单直接对当前文件、选区或 Git Diff 执行解释、修复、评审或文档生成。
- 资源管理器中右键 Ask about resource 即可提问。
- @ 菜单补全项目文件及历史 Session。
- DSH: Capture AppShot(仅 macOS)捕获窗口截图并作为草稿插入对话。

会话、Trace 与活动面板

侧栏提供原生对话大纲树视图;Trace、Token 用量、Todo 清单与子代理统一归集在活动面板。UI 适配 VS Code 深浅主题。

运行 DSH: 在编辑器标签页中打开聊天(DSH: Open Chat in Editor Tab)可以把同一份对话镜像到编辑器标签页,让聊天紧挨着正在改的文件。两个界面共用一个会话与一条流,切换不会重开或分叉。

Trace 和活动面板

自主调试(默认关闭)

开启 dsh.autonomousDebugging 后,扩展会在本窗口内起一个只监听回环地址的 MCP 端点,Agent 由此操作 VS Code 调试器:debug_start 启动工作区里已有的 launch 配置,debug_breakpoint 增加、删除、列出断点,debug_control 继续、单步并等待下一次暂停,debug_context 读取暂停时的调用栈、变量与源码。名字疑似密钥的变量在离开窗口前会替换为 [redacted by dsh-ide]。端点仅绑定 127.0.0.1,校验 Host 头与每次启动单独的令牌,也不允许模型自造 launch 配置。该能力只对本窗口自行启动的 Runtime 生效;切换设置后需重启 Runtime,扩展会在设置变更时提示。

凭据与余额

底部快速查看当前余额,支持峰谷定价显示,支持低余额采用醒目颜色警示。

余额指示器

常见问题

需要手动安装 DSH 吗? 请安装官方 DeepSeek Desktop。Desktop 会注册扩展使用的 dsh 命令;命令不可用时,扩展会提供官方下载安装页。独立托管 Runtime 下载已弃用。

Laya/Jev 是怎么集成的? 扩展安装包自带 IDE 无关的 dsh-jev-integration Runtime 包,并只挂载到本扩展自行启动的 Runtime;不会修改已有或外部托管的 Runtime。Laya 走同一套 System One 接口,修改 dsh.jev.baseUrl 即可(仅限 HTTPS)。Jev 默认关闭,dsh.jev.enabled 是总开关;循环保护、结果整形、完成证据检查、工具裁剪、skill 路由、决策工具和本地确定性安全检查分别提供开关。endpoint 和模型可配置,数值阈值使用内置默认值。API Key 通过 DSH:配置 Jev API Key 加密保存在 VS Code SecretStorage,也可从 TYPESAFE_API_KEY 或 $HOME/.dsh/.env 读取。启用的功能可能会将所需样本发送到 TypeSafe System One。设置变更需重启 Runtime。本版本提供 upstream dsh-jev 的共享 Runtime 子集,不包含完整 Agent Loop、Dashboard、浏览器或移动端 bundle。

可以连接已有 Runtime 吗? 可以,将 dsh.serverUrl 设置为正在运行的 dsh web 地址;如果地址中没有 Token,再将启动 Token 填入 dsh.serverToken。本扩展接受所有不低于 dsh 0.1.5-rc.1 的合法 SemVer,包括更新的预发布版本及正式版;默认下载及用户同意后的升级目标为 0.2.0-rc.2,本机已有兼容版本时直接复用,不降级。扩展通过公开 Remote 分页和 follow API 读取会话历史;日志存储格式及迁移由 Runtime 负责。

指定监听地址或 HTTPS: 已启动的 Runtime 使用自定义地址时,设置 dsh.serverUrl 即可直接连接,避免再次启动造成端口冲突。例如:

{
"dsh.serverUrl": "https://[::1]:3080",
"dsh.serverToken": "<Runtime 启动时提供的 token>" }

IPv4 地址也可使用,例如 http://100.64.0.1:3080,前提是该 IP 属于运行扩展的机器。远程地址必须使用 HTTPS;TLS 证书须受扩展宿主信任,扩展不会跳过证书校验。IPv6 地址须加方括号。自动发现会探测本机 IPv4/IPv6 网卡地址,但未登记实例的认证 Token 仍需通过上述设置提供。

本扩展的默认 Runtime 和 Remote 契约指向 dsh-v0.2.0-rc.2(639ed015397290b3745d163aafe02ffee4aa3f84)。RC.2 适配报告 记录联调结果及验证边界。Runtime 工作区文件已有只读浏览入口,权限预设通过独立目录获取,Settings 支持插件启停与 Bundle 选择,显示只读原因、保存/生效状态和重启提示。Schedule 需启用可选官方 bundle。Jobs 可实时查看输出、按字节游标重连续读并取消任务;限时问答支持前台等待、重连和 webview 重建后的回答草稿恢复。Team 面板展示 agentTeam 投影中的成员与任务,支持成员历史预览和任务筛选。Runtime 终端输入、resize 和屏幕恢复,以及插件安装/卸载已在开发分支接入。IDE 不调用桌面遥测 RPC。

默认 dsh.command: "auto" 依次探测 PATH 和 npm 全局目录中的 dsh --version。官方 Desktop 注册的兼容命令会直接使用;不兼容的本机 CLI 只对已确认的旧版 npm 全局安装提供升级确认。没有兼容命令时,扩展会引导安装官方 Desktop。诊断命令不会安装或下载独立 Runtime。显式本机路径遵循相同兼容性检查;高级用户仍可显式选择 pnpm/npx。

默认应用参数为 web --no-open,没有保存参数覆盖时会为显式 pnpm/npx 补齐启动前缀。已有包管理器参数配置保留。auto 模式选择兼容的本机或 Desktop 注册的 dsh,不会再启动第二个独立 Runtime。

独立 CNB Runtime 下载已弃用。没有 dsh 命令时,请从 DeepSeek 官方下载页 安装 Desktop。编译后可执行 node scripts/verify-runtime-discovery.mjs,在隔离 POSIX CLI 环境中验证本机命令选择及启动参数,不请求模型。

支持多根工作区吗? DSH 支持多个彼此独立的 Workspace,但每个 Session 只有一个工作目录(cwd)。VS Code 多根工作区启动 Runtime 时使用第一个 workspace folder;如果不同根目录需要不同工作目录,请分别建立 DSH Workspace 或 Session。

会自动识别密钥或个人信息吗? 不会。上下文目前只根据用户主动选择的文件、选区和附件计算大小与截断;不会把文件内容交给额外的秘密/个人信息分类器。

启动失败怎么办? 在命令面板运行 DSH: Diagnose Environment 查看诊断,再用 DSH: Show dsh Runtime Logs 查看日志。提交 issue 时请附上扩展版本、操作系统和脱敏后的错误信息。

如果启动报 error: unknown option '--no-open',但 dsh web --help 列出了这个参数,请检查 $DSH_HOME/profiles/web/package.json(默认为 ~/.dsh/profiles/web/package.json)。当 dsh.profile.bundles 同时包含 @deepseek-ai/dsh-web-app 和 @deepseek-ai/dsh-headless 时,两个应用都会解析同一组参数:Web 接受该参数,headless 随后拒绝它。备份文件,从 Web profile 中移除 headless bundle,再重启 Runtime。一次性 CLI 任务使用独立的 headless profile。

支持中文吗? 支持。命令、聊天、活动面板和 Trace 界面会跟随 VS Code 显示语言,提供英文与简体中文。

架构与运行机制

扩展通过 RC Remote RPC 连接 Runtime,使用 HTTP 调用和多路复用 WebSocket 获取实时会话更新。

多个 VS Code 窗口通过 Runtime 广告互相发现,再回退到端口 3080 及配置的 dsh.serverPort。每个候选都先做健康检查:认证及 session/list 调用成功才算可用,广告中低于最低要求的版本直接排除。外部服务不会归本扩展所有,断开连接不会停止它。需要认证但缺少凭据时,会提示将 dsh.serverUrl 设为完整启动 URL(包含 token)。

广告只是发现用的元数据,任何字段都不授予也不否决启动权限。广告缺失、过期或无法读取都不会阻塞启动,最坏情况只是多做一次失败的健康探测,然后本窗口启动自己的 Runtime。

每个窗口只发布自己那一份 <ownerId>.json,位于系统临时目录下的 dsh-runtime-advertisements-<user>,记录端点、启动 URL、版本、PID 和 composition hash。窗口只写自己的文件,从不回收别人的;旧的 dsh-runtime.lock 仅作只读提示,不再写入或删除。读取时只取最近 16 条,被遗弃的文件挤不掉仍然存活的。

广告生命周期:

- 只有已就绪的端点才发布。在产生 URL 之前失败的启动不留下任何文件。
- 启动时通过回环 mutex 做短暂协调——最多等 250 ms、最多持有 500 ms——并在 spawn 前重新检查是否已有共享 Runtime。抢不到从不阻塞启动,只意味着本窗口起自己的 Runtime。
- 显式 stop、dispose 以及启动失败都会撤回广告。
- 启动器意外退出时放弃所有权,但只要端点仍然应答就保留广告——包管理器包装进程经常自己退出而它拉起的 Runtime 仍在服务。只有明确被拒绝的回环连接才撤回;超时或主机名有歧义时一律保留。
- 启动固定 --host 127.0.0.1;未设置 dsh.serverPort 时使用操作系统分配的端口。指定端口在 bind 竞争中失败时,会用操作系统分配的端口重试一次。
- 退出时先停止本扩展拥有的进程树,再撤回广告。POSIX 使用独立进程组,Windows 在根进程身份仍可确认时使用限定 PID 的 taskkill /T。

运行 npm run compile 后,分别执行 node scripts/verify-runtime-discovery.mjs、node scripts/verify-runtime-shutdown.mjs,验证启动器/端口选择、广告、升级确认及退出清理;脚本仅使用隔离临时目录、子进程及回环监听器。

graph TD
A[VS Code Extension Host] <-->|RC Remote RPC| B[Standalone Harness Runtime]
A <-->|Typed Full-State Bridge| C[React Webview UI]
B <-->|官方 Desktop dsh 命令| D[DeepSeek Desktop]
A <-->|Process Lock| E[Multi-Window Shared Runtime]

配置

完整列表可在 VS Code 设置界面搜索 dsh。

| 设置项 | 默认值 | 说明 |
| dsh.serverUrl | "" | 已运行的 dsh web Runtime 地址,设置后扩展将直接连接;可在地址中附加 ?token=...,或单独设置 dsh.serverToken。 |
| dsh.serverToken | "" | dsh.serverUrl 对应的启动 Token;地址与 Token 分开配置时填写。 |
| dsh.autoStart | true | 扩展激活时自动启动或连接 dsh web。 |
| dsh.installWhenMissing | false | 已弃用的兼容设置;不再下载独立 Runtime。没有 dsh 时引导安装官方 Desktop。 |
| dsh.runtimeVersion | 0.2.0-rc.2 | 用户同意后的本机 CLI 升级兼容目标;独立下载行为已弃用。 |
| dsh.npmRegistry | https://registry.npmmirror.com | 下载后备重试的 Registry 镜像。 |
| dsh.npxTimeoutMs | 120000 | 等待包管理器下载与启动的超时时间。 |
| dsh.enableCompaction | true | 扩展自行启动 DSH Web server 时启用官方 /compact command。 |
| dsh.jev.enabled | false | 启用 Jev 总开关;受保护工具参数及已启用功能所需数据可能发送到 TypeSafe System One。请使用“DSH:配置 Jev API Key”配置密钥;修改后需重启 Runtime。 |
| dsh.jev.baseUrl | https://api.typesafe.ai/v1/systemone | Jev endpoint;远程地址请使用 HTTPS。 |
| dsh.jev.model | jev-latest | Jev 模型名。 |
| dsh.jev.loopGuard.enabled | false | 启用工具执行后的语义循环检测;轨迹样本可能发送给 Jev。 |
| dsh.jev.resultShaper.enabled | false | 启用大型工具结果重复文本的分类和整形;样本可能发送给 Jev。 |
| dsh.jev.doneGate.enabled | false | 让 Jev 根据工具证据检查完成声明。 |
| dsh.jev.toolPruner.enabled | false | 让 Jev 排序可见工具;不会改变 DSH 权限。 |
| dsh.jev.skillRouter.enabled | false | 让 Jev 选择相关 skill 并追加有界建议。 |
| dsh.jev.decisionTools.enabled | false | 暴露 Jev 提问/排序/检查工具;提交状态可能发送给 Jev。 |
| dsh.jev.deterministicSafetyGuard.enabled | true | 在本地检查危险命令和凭据泄漏。 |
| dsh.autonomousDebugging | false | 允许 Agent 通过本机回环 MCP 端点操作本窗口的调试器;只对本窗口自行启动的 Runtime 生效,切换后需重启 Runtime。 |
| dsh.maxContextBytes | 120000 | 单次请求中 <ide_context> 的最大 UTF-8 字节数。 |
| dsh.persistSession | true | 尽可能复用当前工作区上次的 Session ID。 |
| dsh.agentStatusLabels | 内置“大肥鱼”状态文案 | 每轮流式输出随机展示的文本提示,支持自定义。 |
| dsh.agentStatusLabel | "" | 设置后将固定显示该提示文案。 |
| dsh.enableEffortKnob | true | 推理强度滑块使用跑步 sprite 动画作为按钮。 |

其他安装方式

从 GitHub Releases 安装:下载 Releases 里的 .vsix,运行 Extensions: Install from VSIX...。预发布版本会带 pre-release 标记发到 Open VSX,同时挂在 GitHub Releases:在 Open VSX 上只有把该扩展切换到预发布版本的用户才会收到;它们不会进 VS Code Marketplace,那边不接受带 SemVer 预发布后缀的版本号。0.8.0 起正式版使用偶数 minor(0.8.x)、预发布使用更高的奇数 minor(0.9.x),因此正式版不会盖过更新的预发布版本。

从源码构建:

git submodule update --init --recursive
npm install
npm run check
npm run package

随后通过 Extensions: Install from VSIX... 安装生成的 .vsix。

扩展 API

其他 VS Code 扩展可以接入 DSH 导出的 API。

对话导航 API:注册自定义节点

const registration = api.registerConversationNavigation([
{ seq: 42, label: "检查 PPO 实现", detail: "训练配置" }, ]);
context.subscriptions.push(registration);

Agent Status Label API:自定义流式状态文案

const dsh = vscode.extensions.getExtension<import("dsh-vsc-integration").DshExtensionApi>(
"harcochen.dsh-vsc-integration",
);
const api = await dsh?.activate();
context.subscriptions.push(
api?.registerAgentStatusPresentation({ label: "🐋 深潜中" }),
);

开发与测试

npm install
npm run check # TypeScript 检查(宿主 + webview)
npm test # 发布门槛:webview 检查 + 编译 + 测试套件
npm run compile # 构建到 dist/
npm run package # 编译 + vsce 打包
npm run release # 测试 + 版本提升 + CHANGELOG 归档 + 打 tag

日常改动记录在 CHANGELOG.md 的 Unreleased 中;临时打包不提升版本、不归档日志、不打 tag。准备发布下一版预览版时,在当前奇数 minor 上执行 npm run release -- patch,由脚本统一提升版本、归档日志、提交并创建 tag;确认后使用 git push origin HEAD --follow-tags 触发发布。预览版手动打包使用 npm run package -- --pre-release。

Remote 冒烟脚本校验启动器的实际版本,通过公开 RPC 生成历史,验证鉴权、分页、评价、重连、流式输出、Goal、命令、可选 Schedule 以及 RC.2 timed 问题延迟回答。RC.2 适配报告 记录运行结果及账号、Schedule 修改、Jev、UI 等剩余验证。

对已安装的 0.2.1-rc.2 启动器运行 Remote 冒烟(验证上一版时增加 --expect-version 0.2.0-rc.2):

npm run compile
node scripts/verify-remote-runtime.mjs --launcher /absolute/path/to/dsh
node scripts/verify-remote-runtime.mjs --launcher /absolute/path/to/dsh --with-schedule-bundle
node scripts/verify-remote-runtime.mjs --launcher /absolute/path/to/dsh --timed-questions
node scripts/verify-remote-runtime.mjs --launcher /absolute/path/to/dsh --with-team-bundle

脚本使用临时 DSH_HOME、独立 DSH Workspace 和回环地址上的 Messages 模拟模型,不使用现有 Session 或外部模型凭据。Node.js 版本须满足所选 Runtime 的要求(^22.19.0 || >=24.0.0)。--with-schedule-bundle 检查 0.2.0 的可选 Schedule bundle(0.2.1 默认内置 Schedule);--workflow-controls 检查终端输入确认、重连、插件操作与历史目录 Diff;--with-jev 加载内置 overlay 并检查能力端点;--timed-questions 检查超时延续和延迟回答,--expect-version <version> 可显式指定其他验证目标,--keep 保留临时状态。

验证本机命令发现和启动参数:

node scripts/verify-runtime-discovery.mjs # 本机命令发现

更多信息

- 更新日志
- 产品 TODO
- 第三方资产说明

致谢

感谢 dsh-reasoning-effort 提供推理强度控件的"大肥鱼跑步"参考。对话大纲受 dsh-milestone 项目启发。

许可证

MIT
预览分享卡片长什么样 ↓HarcoChen/dsh-vsc-integration
分享 · DeepSeek Harness Hub
HarcoChen/dsh-vsc-integration

将 DeepSeek HarnessDSH带进 VS Code:结合IDE的上下文完成任务,查看原生Diff,通过…

这是你的仓库?认领条目

回到顶部