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

飞书桥接 wanwang416/DSH-Wing

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

在飞书里流式查看思考过程并随时插话

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

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

该插件未发布到 npm,按作者文档从 GitHub 源安装即可(静态检查只覆盖 npm 路径,不代表插件不可用)。
安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add wanwang416/DSH-Wing
该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:需留意
是什么
dsh 原生插件 · platform
装得上吗
作者未把包发布到 npm,只能用源码安装
插件本身没问题,是分发方式不同
L4 · 真实安装等级说明 →
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
更新放缓:最近一次提交在 31 天前
档位由哪些信号合成

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

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

engines.node 要求 >=24.0.0,不满足 Node 22.19.0

展开查看检查明细 ↓

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

✗npm 包dsh-wing(未发布到 npm,仅可源码安装)
✗Node 引擎要求 >=24.0.0 · 基线 Node 22.19 不满足
✓dsh CLI 依赖未声明 dsh 版本约束
✓入口文件main/exports/bin 已声明

源码安装时若 pnpm 拦截 prepare 脚本,按其提示在 pnpm-workspace.yaml 的 allowBuilds 中放行后重跑。

验证方式:npm registry 存在性 + package.json 静态校验 · 最后检查 2026/10/21 15:44:08

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

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

读写/删除本地文件读取剪贴板或密钥环境变量发起外部网络请求
查看扫描证据(共 83 处,展示前 83 条)
  • 写入本地文件
    src/agent/experience.ts:54
    appendFileSync(path, `${new Date().toISOString()} ${msg}\n`);
  • 读取密钥环境变量
    src/config/defaults.ts:102
    secret: process.env.WECOM_BOT_SECRET || undefined,
  • 读取本地文件
    src/doctor/package.ts:80
    if (existsSync(join(dir, "package.json"))) return dir;
  • 读取本地文件
    src/doctor/package.ts:94
    if (!existsSync(p)) return "unknown";
  • 读取本地文件
    src/doctor/package.ts:95
    return (JSON.parse(readFileSync(p, "utf8")) as { version?: string }).version ?? "unknown";
  • 读取本地文件
    src/doctor/package.ts:113
    if (!existsSync(path)) return undefined;
  • 读取本地文件
    src/doctor/package.ts:114
    const size = statSync(path).size;
  • 读取本地文件
    src/doctor/package.ts:119
    raw = readFileSync(path, "utf8");
  • 写入本地文件
    src/doctor/package.ts:224
    mkdirSync(opts.stateDir, { recursive: true });
  • 写入本地文件
    src/doctor/package.ts:227
    writeFileSync(zipPath, buf);
  • 发起网络请求
    src/host/client.ts:142
    const res = (await sdkClient.request({
  • 发起网络请求
    src/host/client.ts:171
    const res = (await sdkClient.request({
  • 发起网络请求
    src/host/client.ts:182
    return sdkClient.request({
  • 读取本地文件
    src/host/quota.ts:22
    history = readFileSync(historyFile, "utf8")
  • 写入本地文件
    src/host/quota.ts:38
    mkdirSync(join(historyFile, ".."), { recursive: true });
  • 写入本地文件
    src/host/quota.ts:39
    writeFileSync(historyFile, history.slice(-500).map((r) => JSON.stringify(r)).join("\n") + "\n", { mode: 0o600 });
  • 读取本地文件
    src/host/status.ts:38
    const raw = readFileSync(file, "utf8");
  • 写入本地文件
    src/host/status.ts:45
    writeFileSync(file, JSON.stringify(status, null, 2), { mode: 0o600 });
  • 写入本地文件
    src/host/websocket.ts:60
    mkdirSync(lockDir, { recursive: true });
  • 写入本地文件
    src/host/websocket.ts:69
    mkdirSync(lockPath, { recursive: false });
  • 写入本地文件
    src/host/websocket.ts:74
    writeFileSync(pidFile, String(process.pid), { mode: 0o600 });
  • 删除本地文件递归
    src/host/websocket.ts:81
    rmSync(lockPath, { recursive: true, force: true });
  • 写入本地文件
    src/host/websocket.ts:91
    mkdirSync(lockPath, { recursive: false });
  • 写入本地文件
    src/host/websocket.ts:93
    writeFileSync(pidFile, String(process.pid), { mode: 0o600 });
  • 删除本地文件递归
    src/host/websocket.ts:100
    rmSync(lockPath, { recursive: true, force: true });
  • 读取本地文件
    src/host/websocket.ts:110
    if (existsSync(pidFile)) {
  • 读取本地文件
    src/host/websocket.ts:111
    const pid = Number(readFileSync(pidFile, "utf8"));
  • 删除本地文件递归
    src/host/websocket.ts:117
    rmSync(lockPath, { recursive: true, force: true });
  • 删除本地文件递归
    src/host/websocket.ts:122
    rmSync(lockPath, { recursive: true, force: true });
  • 读取本地文件
    src/host/websocket.ts:130
    const st = statSync(lockPath);
  • 删除本地文件递归
    src/host/websocket.ts:132
    rmSync(lockPath, { recursive: true, force: true });
  • 读取本地文件
    src/inbound/dedup.ts:29
    const raw = readFileSync(file, "utf8");
  • 读取本地文件
    src/inbound/dedup.ts:32
    if (existsSync(file)) {
  • 写入本地文件
    src/inbound/dedup.ts:36
    copyFileSync(file, `${file}.bak`);
  • 写入本地文件
    src/inbound/dedup.ts:53
    writeFileSync(tmp, JSON.stringify(records.slice(-LRU_MAX), null, 2), { mode: 0o600 });
  • 写入本地文件
    src/inbound/dedup.ts:54
    renameSync(tmp, file);
  • 写入本地文件
    src/inbound/wal.ts:35
    mkdirSync(dir, { recursive: true });
  • 读取本地文件
    src/inbound/wal.ts:42
    segs = readdirSync(dir).filter((f) => /^seg-.*\.jsonl$/.test(f)).sort();
  • 读取本地文件
    src/inbound/wal.ts:48
    const lines = readFileSync(join(dir, seg), "utf8").split("\n").filter(Boolean);
  • 写入本地文件
    src/inbound/wal.ts:72
    writeFileSync(tmp, lines.length > 0 ? lines.join("\n") + "\n" : "", { mode: 0o600 });
  • 写入本地文件
    src/inbound/wal.ts:73
    renameSync(tmp, segFile);
  • 读取本地文件
    src/inbound/wal.ts:79
    for (const f of readdirSync(dir)) {
  • 删除本地文件
    src/inbound/wal.ts:82
    rmSync(join(dir, f));
  • 读取本地文件
    src/inbound/wal.ts:114
    const segCount = readdirSync(dir).filter((f) => /^seg-.*\.jsonl$/.test(f)).length;
  • 写入本地文件
    src/index.ts:95
    mkdirSync(dir, { recursive: true });
  • 写入本地文件
    src/index.ts:114
    writeFileSync(join(home, ".dsh-wing-loaded"), `loaded at ${new Date().toISOString()}\n`, { mode: 0o600 });
  • 读取本地文件
    src/index.ts:1107
    if (!existsSync(path) || !statSync(path).isDirectory()) return false;
  • 读取本地文件
    src/index.ts:1107
    if (!existsSync(path) || !statSync(path).isDirectory()) return false;
  • 读取本地文件
    src/interactive/approval.ts:36
    const raw = readFileSync(deps.file, "utf8");
  • 写入本地文件
    src/interactive/approval.ts:53
    writeFileSync(tmp, JSON.stringify(Object.fromEntries([...always].map(([k, v]) => [k, [...v]])), null, 2), { mode: 0o600 });
  • 写入本地文件
    src/interactive/approval.ts:54
    renameSync(tmp, deps.file);
  • 读取本地文件
    src/interactive/approval.ts:58
    if (existsSync(tmp)) rmSync(tmp);
  • 删除本地文件
    src/interactive/approval.ts:58
    if (existsSync(tmp)) rmSync(tmp);
  • 读取本地文件
    src/log/archive-retention.ts:46
    entries = readdirSync(dir);
  • 读取本地文件
    src/log/archive-retention.ts:60
    const st = statSync(full);
  • 删除本地文件递归
    src/log/archive-retention.ts:62
    rmSync(full, { force: true, recursive: true });
  • 读取本地文件
    src/log/rotation.ts:69
    size = statSync(file).size;
  • 读取本地文件
    src/log/rotation.ts:77
    if (existsSync(oldest)) rmSync(oldest, { force: true });
  • 删除本地文件
    src/log/rotation.ts:77
    if (existsSync(oldest)) rmSync(oldest, { force: true });
  • 读取本地文件
    src/log/rotation.ts:84
    if (!existsSync(from)) continue;
  • 写入本地文件
    src/log/rotation.ts:86
    renameSync(from, `${file}.${i + 1}`);
  • 写入本地文件
    src/log/rotation.ts:93
    renameSync(file, `${file}.1`);
  • 写入本地文件
    src/log/rotation.ts:103
    appendFileSync(file, line);
  • 写入本地文件
    src/outbound/outbox.ts:156
    mkdirSync(deps.dir, { recursive: true });
  • 写入本地文件
    src/outbound/outbox.ts:162
    appendFileSync(segPath(), JSON.stringify(env) + "\n", { mode: 0o600 });
  • 读取本地文件
    src/outbound/outbox.ts:178
    segs = readdirSync(deps.dir)
  • 读取本地文件
    src/outbound/outbox.ts:195
    const lines = readFileSync(join(deps.dir, seg), "utf8").split("\n").filter(Boolean);
  • 读取本地文件
    src/outbound/outbox.ts:221
    while (existsSync(join(deps.dir, `seg-${sec}.jsonl`))) sec += 1;
  • 写入本地文件
    src/outbound/outbox.ts:225
    writeFileSync(join(deps.dir, candidate), lines.join("\n") + "\n", { mode: 0o600 });
  • 删除本地文件
    src/outbound/outbox.ts:238
    rmSync(join(deps.dir, seg));
  • 读取本地文件
    src/session/model-overrides.ts:13
    const raw = readFileSync(file, "utf8");
  • 写入本地文件
    src/session/model-overrides.ts:22
    writeFileSync(file, JSON.stringify(Object.fromEntries(overrides), null, 2), { mode: 0o600 });
  • 读取本地文件
    src/session/permission-overrides.ts:21
    const raw = readFileSync(file, "utf8");
  • 读取本地文件
    src/session/permission-overrides.ts:31
    if (existsSync(file)) {
  • 删除本地文件
    src/session/permission-overrides.ts:33
    rmSync(`${file}.bak`, { force: true });
  • 写入本地文件
    src/session/permission-overrides.ts:34
    renameSync(file, `${file}.bak`);
  • 写入本地文件
    src/session/permission-overrides.ts:45
    writeFileSync(tmp, JSON.stringify(Object.fromEntries(overrides), null, 2), { mode: 0o600 });
  • 写入本地文件
    src/session/permission-overrides.ts:46
    renameSync(tmp, file);
  • 读取本地文件
    src/session/persistence.ts:21
    const raw = readFileSync(file, "utf8");
  • 写入本地文件
    src/session/persistence.ts:30
    writeFileSync(file, JSON.stringify([...routes.values()], null, 2), { mode: 0o600 });
  • 读取本地文件
    src/session/workspace-overrides.ts:15
    const raw = readFileSync(file, "utf8");
  • 写入本地文件
    src/session/workspace-overrides.ts:24
    writeFileSync(file, JSON.stringify(Object.fromEntries(overrides), null, 2), { mode: 0o600 });
  • 发起网络请求
    src/setup/register-app.ts:62
    res = await fetch(url, {
扫描于 2026/11/2(1 天前) · 范围 全包扫描(包内未声明入口) · 来源 GitHub 仓库

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

依赖的 DSH / Cordis 模块
@deepseek-ai/cordis@deepseek-ai/dsh-agent@deepseek-ai/dsh-commands@deepseek-ai/dsh-credentials@deepseek-ai/dsh-llm@deepseek-ai/dsh-session@deepseek-ai/dsh-storage-domain@deepseek-ai/dsh-system-prompt@deepseek-ai/dsh-tools
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

功能亮点

  • 流式查看思考过程
  • 随时插话

README

由 DeepSeek 最新模型翻译生成
DSH-Wing DeepSeek Harness 的飞书原生插件 — 过程透明 · 插话不打断 · 完整桥能力 DeepSeek Harness 飞书原生插件 — 过程透明 · 插话不打断 · 完整桥能力 ✨ Core Features / 核心特性 🎯 Transparent Streaming / 过程透明 智能体的思考过程流式呈现,单卡打字机效果,告别黑盒。CardKit 流式引擎支持三级降级:CardKit 打字机 → 整卡更新 → 纯文本消息,任何环境下都能稳定输出。 思考过程流式呈现,单卡打字机效果,告别黑盒。CardKit 流式引擎支持三级降级。 💬 Non-Interruptive Follow-ups / 插话不打断 任务进行中可随时插话,主任务不丢上下文。四类中断分类器智能识别:任务进行中可随时插话,主任务不丢上下文。
展开完整文档(README 剩余 1 节)
DSH-Wing

DeepSeek Harness 的飞书原生插件 — 过程透明 · 插话不打断 · 完整桥能力

DeepSeek Harness 飞书原生插件 — 过程透明 · 插话不打断 · 完整桥能力

✨ Core Features / 核心特性

🎯 Transparent Streaming / 过程透明

智能体的思考过程流式呈现,单卡打字机效果,告别黑盒。CardKit 流式引擎支持三级降级:CardKit 打字机 → 整卡更新 → 纯文本消息,任何环境下都能稳定输出。
思考过程流式呈现,单卡打字机效果,告别黑盒。CardKit 流式引擎支持三级降级。

💬 Non-Interruptive Follow-ups / 插话不打断

任务进行中可随时插话,主任务不丢上下文。四类中断分类器智能识别:任务进行中可随时插话,主任务不丢上下文。四类中断分类器智能识别:
- COMMAND(停止 / 改向)→ 立即中断 / 立即中断
- QUESTION / CONFIRM(疑问 / 确认)→ 排队注入,不打断主任务 / 排队注入,不打断主任务
- ORDINARY(推进词 / 纯确认)→ 推进词注入,纯确认仅回执 / 推进词注入,纯确认仅回执
- 设置 DSH_WING_INTERRUPT_CLASSIFIER=0 可回退经典模式 / 可通过环境变量回退经典模式

🎛️ Interactive Cards / 交互卡片

- 单选卡 — /preset /model /mode /permission 一键切换 / 单选卡一键切换
- 审批卡 — 危险操作四个按钮(仅本次允许 / 本会话允许 / 始终允许 / 拒绝),支持老板 open_id 限定,防止群聊他人越权批准 / 审批卡四按钮,支持老板 open_id 限定,防止群聊他人越权批准

🔒 Permission System / 权限控制

三档权限粒度,默认保守 / 三档权限粒度,默认保守:

| Mode / 模式 | Description / 说明 |
| read-only | 只读,禁止任何写操作 / 只读,禁止任何写操作 |
| workspace-write | 默认,仅允许工作区内写入 / 默认,仅允许工作区内写入 |
| danger-full-access | 完全访问,危险操作弹审批卡 |

🧭 意图路由

群聊命令、提问、闲聊智能分流,纯寒暄不误触发智能体。支持四种群聊触发策略:open / mention / keywords / reply。

🛡️ 可靠性

- 断线补偿 —— WS 断连期间消息不丢,重连后自动补偿
- 撤回即停 —— 用户撤回消息,立即取消对应智能体任务
- WAL 留痕 —— 入站消息预写日志,崩溃可恢复
- 连接自愈 —— WS 假死检测(60s ping 超时)+ 自动重连
- Outbox 重试 —— 出站消息失败自动重试,指数退避

🏗️ 架构设计

三层架构

┌─────────────────────────────────────────────────────────┐
│ Platform Adapter Layer / 平台接入层 │ │ ┌──────────┐ ┌──────────┐ ┌──────────────────────┐ │ │ │ Feishu │ │ WebSocket│ │ Event Dispatcher │ │ │ │ SDK │ │ Client │ │ │ │ │ └──────────┘ └──────────┘ └──────────────────────┘ │ ├─────────────────────────────────────────────────────────┤ │ Core Engine Layer / 核心层 (platform-agnostic / 平台无关)│ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌───────────┐ │ │ │ Inbound │ │ Session │ │ Experience│ │ Outbound │ │ │ │ Pipeline │ │ Manager │ │ Layer │ │ Outbox │ │ │ │(parse/ │ │(map/ │ │(stream/ │ │(retry/ │ │ │ │ dedup/ │ │ persist/ │ │ interject│ │ degrade/ │ │ │ │ batch) │ │ serialize)│ │ /tools) │ │ shard) │ │ │ └──────────┘ └──────────┘ └──────────┘ └───────────┘ │ ├─────────────────────────────────────────────────────────┤ │ Agent Driver Layer / Agent 驱动层 (DSH-native / DSH 原生)│ │ ┌──────────┐ ┌──────────┐ ┌──────────────────────┐ │ │ │ DSH Agent│ │ Tool Call│ │ LLM / Reasoning │ │ │ │ Driver │ │ Stream │ │ │ │ │ └──────────┘ └──────────┘ └──────────────────────┘ │ └─────────────────────────────────────────────────────────┘

消息链路

Feishu message → WS → Dispatcher → Session Mapper → DSH Agent
→ Session Events (6 types) → Forwarder → Experience
→ Sender / Outbox → Feishu reply

🚀 快速开始

前置要求

- Node.js >= 24.0.0
- DeepSeek Harness (DSH) 运行环境
- 飞书自建应用(App ID + App Secret)

安装

Clone the repository / 克隆仓库bash
git clone https://github.com/wanwang416/DSH-Wing.git
cd DSH-Wing

Install dependencies / 安装依赖

npm install

Build (host tsc + client tsdown) / 构建

npm run build

Configuration / 配置 bash

1. Copy the config template / 复制配置模板

cp cordis.patch.example.yml cordis.patch.yml

2. Edit the config / 编辑配置

- workspaceRoot: your workspace path / 你的工作区路径

- groupPolicy: group-chat trigger strategy (open/mention/keywords/reply) / 群聊触发策略

- permissionMode: permission mode (read-only/workspace-write/danger-full-access) / 权限模式

Credential configuration (choose one) / 凭据配置(二选一):

Option A — DSH credential system (recommended) / 方式 A — DSH 凭据系统(推荐):bash

Register in the DSH credential system / 在 DSH 凭据系统中注册

credentialRef: WING_LARK_APP

value: {"appId":"cli_xxx","appSecret":"xxx","domain":"feishu"}

Option B — Environment variables / 方式 B — 环境变量:bash
export DSH_WING_APP_ID=cli_xxxxxxxxxxxx
export DSH_WING_APP_SECRET=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Setup Feishu Application / 初始化飞书应用 bash

Run interactive setup (generates a QR code, scan to register the Feishu app)

运行交互式 setup(生成 QR 码,扫码注册飞书应用)

npx dsh-wing setup

Or trigger via the /setup command in a Feishu chat

或使用 /setup 命令在飞书聊天中触发

Diagnostics / 诊断 bash

Environment check / 环境检查

npx dsh-wing doctor

WebSocket connection test / WebSocket 连接测试

node scripts/diag-ws.mjs

Message listener test / 消息监听测试

node scripts/diag-listen.mjs

💬 WeCom (WeChat Work) Intelligent Bot Line / 企业微信智能机器人线路

长连接(WebSocket)双向对话,与飞书线路并存;单聊(p2p)直通为主场景,群聊走 groupPolicy(@机器人名精确触发)。

Enable / 启用(二选一)

1. 扫码绑定(默认):浏览器打开 GET /plugins/dsh-wing/wecom/qr(无活跃流程自动发起扫码;已绑定返回 409,?force=1 重新绑定)→ 企微 App 扫码 → 凭据写入 WING_WECOM_BOT → 自动重启桥生效(无需重启宿主)。
2. 手填兜底:配置 wecom.botId / wecom.secret,或环境变量 WECOM_BOT_ID / WECOM_BOT_SECRET。

Config / 配置 yaml wecom: enabled: true # true=开;缺省=有凭据即开;false=显式关闭 botName: '' # 群聊 @机器人名(精确触发,需与企微后台显示名一致) source: dsh-wing # 扫码绑定来源标识(多 Agent 隔离) welcomeText: '你好,我是 DSH 智能助手。直接发消息即可开始对话。'

Notes / 说明

- 群聊仅「@机器人名」触发(未配置 botName 时维持宽松并提示);首条群聊消息输出诊断日志核对名字拼写。
- 帧回复按字节分片(4000B/片,超 13 片截断提示);流式单帧 19000B,仅末片 finish;欢迎语受企微 5 秒窗口约束保持单片。
- 单会话限频 30 条/分钟,长回答自动分片共用配额。
- Web 面板前端企微入口(D7b)另立工单。

📋 Command Reference / 命令参考

| Command / 命令 | Description / 说明 |
| /preset | Switch Agent Preset (code / general / ...) / 切换 Agent Preset |
| /model | Switch LLM model / 切换 LLM 模型 |
| /mode | Switch runtime mode / 切换运行模式 |
| /permission | Switch permission mode / 切换权限模式 |
| /resume | Resume a historical session / 恢复历史会话 |
| /workspace | View / switch workspace / 查看/切换工作区 |
| /steer | Gently interrupt the current task / 温和打断当前任务 |
| /stop | Immediately stop the current task / 立即停止当前任务 |
| /setup | Initialize Feishu application config / 初始化飞书应用配置 |
| /status | View current status / 查看当前状态 |
| /doctor | 环境诊断检查 |
| /new | 开启新会话 |
| /help | 显示帮助 |

⚙️ 配置详解

cordis.patch.yml
yaml
- insert:
- id: wing
name: 'dsh-wing'
config:
enabled: true
credentialRef: WING_LARK_APP # DSH 凭据引用名 appId: '' # 或环境变量 DSH_WING_APP_ID appSecret: '' # 或环境变量 DSH_WING_APP_SECRET groupPolicy: mention # open/mention/keywords/reply workspaceRoot: /path/to/workspace # 工作区根目录 streaming: enabled: true # 默认开启流式 flushMs: 500 # 流式刷新间隔 permissionMode: workspace-write # 默认保守权限 turnTimeoutMs: 600000 # 轮次超时(10分钟) agentPreset: code # 默认 Agent Preset bossOpenId: '' # 老板 open_id(审批卡片限制) steerDiagLogPath: '' # steer 诊断日志路径(默认关闭)

环境变量

| 变量 | 说明 | Default |
| DSH_WING_APP_ID | 飞书 App ID 覆盖 | — |
| DSH_WING_APP_SECRET | 飞书 App Secret 覆盖 | — |
| DSH_WING_INTERRUPT_CLASSIFIER | 中断分类器开关(0=关闭) | 1 |
| DSH_WING_SDK_LOG | 飞书 SDK 日志文件路径 | — |
| DSH_HOME | DSH 主目录(诊断脚本用) | — |

🛠️ 开发 bash

类型检查

npm run typecheck

仅构建 host

npm run build:host

仅构建 client

npm run build:client

完整构建(host + client)

npm run build

运行测试

npm test

监听模式测试

npm run test:watch

覆盖率报告

npm run coverage

项目结构

DSH-Wing/
├── src/
│ ├── index.ts # 插件入口,组装所有模块 │ ├── agent/ # Agent 驱动层 │ │ ├── caller.ts # Agent 调用封装 │ │ ├── experience.ts # 体验契约(stream/interject/tool-visible) │ │ ├── forwarder.ts # 事件转发器 │ │ ├── intent.ts # 意图识别 │ │ ├── model.ts # 模型管理 │ │ ├── permission.ts # 权限判断 │ │ ├── preset.ts # Preset 管理 │ │ ├── turn-supervisor.ts # 轮次监督器 │ │ └── user-questions.ts # 用户问题处理 │ ├── client/ # 前端客户端(DSH ModuleLoader) │ │ ├── index.ts │ │ └── icons.ts │ ├── commands/ # 斜杠命令 │ ├── config/ # 配置默认值 │ ├── doctor/ # 环境诊断 │ ├── host/ # 平台接入层 │ │ ├── client.ts # 飞书 SDK 客户端 │ │ ├── credentials.ts # 凭据管理 │ │ ├── quota.ts # 配额治理 │ │ ├── status.ts # 状态存储 │ │ ├── supervisor.ts # 连接监督器 │ │ └── websocket.ts # WebSocket 传输 │ ├── inbound/ # 入站管道 │ │ ├── batching.ts # 消息批处理 │ │ ├── chat-type.ts # 聊天类型判断 │ │ ├── compensation.ts # 断线补偿 │ │ ├── dedup.ts # 消息去重 │ │ ├── dispatcher.ts # 事件分发 │ │ ├── event-handler.ts # 事件处理器 │ │ ├── group-policy.ts # 群聊策略 │ │ ├── interrupt-classify.ts # 中断分类器 │ │ ├── parser.ts # 消息解析 │ │ └── wal.ts # 预写日志 │ ├── interactive/ # 交互卡片 │ │ ├── approval.ts # 审批卡 │ │ ├── reaction.ts # 表情回应 │ │ ├── router.ts # 交互路由 │ │ └── selector.ts # 单选卡 │ ├── outbound/ # 出站管道 │ │ ├── cardkit.ts # CardKit 封装 │ │ ├── chunker.ts # 消息分片 │ │ ├── fallback.ts # 降级策略 │ │ ├── outbox.ts # 出站队列 │ │ ├── sender.ts # 消息发送 │ │ ├── streaming-card.ts # 流式卡片引擎 │ │ └── tool-step.ts # 工具步骤渲染 │ ├── session/ # 会话管理 │ ├── setup/ # 初始化流程 │ └── web/ # Web 面板 ├── tests/ # 562 个单元测试 ├── scripts/ # 诊断脚本 ├── docs/assets/ # 文档素材 ├── .github/workflows/ci.yml # CI 配置 ├── package.json ├── tsconfig.json ├── tsdown.config.ts └── cordis.patch.example.yml

🗺️ 路线图

| 里程碑 | 内容 | 状态 |
| M0 | 骨架 + API 签名 + 插话验证 | ✅ 完成 |
| M1 | 最小可用 + 体验先行(流式 / 插话 / 保守权限 / Outbox) | ✅ 完成 |
| M2 | 可靠性 + 富文本 + 全事件 | ✅ 完成 |
| M3 | 交互 + 权限 + 插话增强(CardKit 流式 / ToolStep 富卡片) | ✅ 完成 |
| M4 | 易用性 + 诊断 + 完整度补齐 | ✅ 完成 |
| M4.1 | 单选卡 + 审批卡 + 意图桥 + 第二批命令 | ✅ 完成 · 562 项测试 |
| M4.2 | /doctor 诊断包 + Web 扫码面板 | ✅ 完成 |
| M5 | 多平台扩展(Discord / Telegram / Slack) | 📋 规划中 |
| M6 | 插件市场 + 可视化配置面板 | 📋 规划中 |

🤝 贡献

欢迎提交 Issue 和 Pull Request!

1. Fork 本仓库
2. 创建特性分支(git checkout -b feature/AmazingFeature)
3. 提交更改(git commit -m 'Add some AmazingFeature')
4. 推送到分支(git push origin feature/AmazingFeature)
5. 开启 Pull Request

📄 许可证

本项目采用 MIT License 开源协议。

用 ❤️ 和 TypeScript 构建

由 DeepSeek Harness 驱动 · 飞书开放平台
预览分享卡片长什么样 ↓wanwang416/DSH-Wing
分享 · DeepSeek Harness Hub
wanwang416/DSH-Wing

在飞书里流式查看思考过程并随时插话

这是你的仓库?认领条目

回到顶部