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

Dify 工作流构建 newbieYi/dsh-dify-builder

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

在 DeepSeek Harness 中通过对话实时构建本地 Dify 工作流。右侧直接显示 Dify…

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

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

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

状态速览

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

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

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

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

展开查看检查明细 ↓

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

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

验证方式:npm registry 存在性 + package.json 静态校验 · 最后检查 2026/11/1 00:46:31

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

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

可执行外部命令读写/删除本地文件读取剪贴板或密钥环境变量发起外部网络请求
查看扫描证据(共 102 处,展示前 88 条)
  • 读取本地文件
    configure-model.mjs:7
    const localConfig = JSON.parse(readFileSync(join(dshHome, 'dify-builder', 'config.json'), 'utf8'))
  • 读取密钥环境变量
    configure-model.mjs:10
    const password = process.env.DIFY_PASSWORD || localConfig.password
  • 读取本地文件
    configure-model.mjs:12
    const credText = readFileSync(join(dshHome, '.credentials.yaml'), 'utf8')
  • 发起网络请求
    configure-model.mjs:27
    const providers = await client.request('GET', '/console/api/workspaces/current/model-providers')
  • 发起网络请求
    configure-model.mjs:34
    const res = await client.request(
  • 发起网络请求
    configure-model.mjs:46
    const after = await client.request('GET', '/console/api/workspaces/current/model-providers')
  • 读取本地文件
    installer/lib/dify.js:32
    await access(path)
  • 写入本地文件
    installer/lib/dify.js:67
    await mkdir(difyDir, { recursive: true })
  • 写入本地文件
    installer/lib/dify.js:71
    await writeFile(archive, Buffer.from(await response.arrayBuffer()))
  • 删除本地文件
    installer/lib/dify.js:75
    await rm(archive, { force: true })
  • 写入本地文件
    installer/lib/dify.js:83
    if (!await exists(envFile)) await copyFile(join(composeDir, '.env.example'), envFile)
  • 读取本地文件
    installer/lib/dify.js:90
    const current = await readFile(envFile, 'utf8')
  • 写入本地文件
    installer/lib/dify.js:103
    await writeFile(envFile, next, { mode: 0o600 })
  • 发起网络请求
    installer/lib/dify.js:200
    const response = await client.request('GET', `/console/api/workspaces/current/plugin/tasks/${taskId}`)
  • 发起网络请求
    installer/lib/dify.js:224
    let providers = await client.request('GET', '/console/api/workspaces/current/model-providers')
  • 发起网络请求
    installer/lib/dify.js:227
    const started = await client.request('POST', '/console/api/workspaces/current/plugin/install/marketplace', {
  • 发起网络请求
    installer/lib/dify.js:235
    providers = await client.request('GET', '/console/api/workspaces/current/model-providers')
  • 发起网络请求
    installer/lib/dify.js:256
    await client.request('PUT', credentialPath, {
  • 发起网络请求
    installer/lib/dify.js:262
    await client.request('POST', credentialPath, {
  • 读取本地文件
    installer/lib/doctor.js:8
    try { await access(file); return true } catch { return false }
  • 读取本地文件
    installer/lib/doctor.js:12
    return JSON.parse(await readFile(file, 'utf8'))
  • 读取本地文件
    installer/lib/dsh.js:22
    text = await readFile(file, 'utf8')
  • 写入本地文件
    installer/lib/dsh.js:39
    await mkdir(dirname(file), { recursive: true })
  • 写入本地文件
    installer/lib/dsh.js:40
    await writeFile(file, `${JSON.stringify(config, null, 2)}\n`, { mode: 0o600 })
  • 写入本地文件
    installer/lib/dsh.js:41
    await chmod(file, 0o600)
  • 读取本地文件
    installer/lib/dsh.js:49
    try { return JSON.parse(await readFile(file, 'utf8')) } catch { return fallback }
  • 写入本地文件
    installer/lib/dsh.js:54
    await mkdir(destination, { recursive: true })
  • 读取本地文件
    installer/lib/install.js:34
    try { return JSON.parse(await readFile(file, 'utf8')) } catch { return {} }
  • 执行外部命令来自配置/变量
    installer/lib/process.js:15
    const child = spawn(command, args, {
  • 读取密钥环境变量
    packages/dsh-dify/e2e-test.mjs:8
    password: process.env.DIFY_PASSWORD,
  • 发起网络请求
    packages/dsh-dify/lib/dify-client.js:146
    return this.request('GET', `/console/api/apps?${params.toString()}`)
  • 发起网络请求
    packages/dsh-dify/lib/dify-client.js:150
    return this.request('POST', '/console/api/apps', { name, mode })
  • 发起网络请求
    packages/dsh-dify/lib/dify-client.js:154
    return this.request('DELETE', `/console/api/apps/${appId}`)
  • 发起网络请求
    packages/dsh-dify/lib/dify-client.js:160
    return this.request('GET', `/console/api/apps/${appId}/workflows/draft`).catch((error) => {
  • 发起网络请求
    packages/dsh-dify/lib/dify-client.js:177
    return this.request('POST', `/console/api/apps/${appId}/workflows/draft`, payload)
  • 发起网络请求
    packages/dsh-dify/lib/dify-client.js:190
    return this.request('POST', '/console/api/workflow-generate', payload)
  • 读取本地文件
    packages/dsh-dify/lib/index.js:45
    stored = JSON.parse(readFileSync(configFile, 'utf8'))
  • 发起网络请求
    packages/dsh-dify/lib/index.js:120
    const res = await fetch(`${baseUrl}/signin`, { redirect: 'manual', signal: AbortSignal.timeout(5000) })
  • 执行外部命令来自配置/变量
    packages/dsh-dify/lib/index.js:132
    child = spawn(command, args, { cwd, env: process.env, stdio: ['ignore', 'pipe', 'pipe'] })
  • 读取密钥环境变量
    packages/dsh-dify/lib/index.js:221
    const password = cfg.password || process.env.DIFY_PASSWORD || ''
  • 发起网络请求
    packages/dsh-dify-panel/lib/client.js:28
    return fetch(url, {
  • 发起网络请求
    packages/dsh-dify-panel/lib/client.js:44
    var response = await fetch(baseUrl + "/console/api/setup", {
  • 发起网络请求
    packages/dsh-dify-panel/lib/client.js:59
    fetch("http://127.0.0.1:8080/__dify_probe/" + tag + "?t=" + Date.now()).catch(function () {});
  • 读取本地文件
    packages/dsh-dify-panel/lib/index.js:25
    stored = JSON.parse(readFileSync(configFile, 'utf8'))
  • 发起网络请求
    packages/dsh-dify-sidebar/lib/client-terminal.js:7854
    response = await fetch(`/sidebar/api/${method}`, {
  • 读取本地文件
    packages/dsh-dify-sidebar/lib/index.js:181
    level = await opendir(path);
  • 读取本地文件
    packages/dsh-dify-sidebar/lib/index.js:225
    const info = await stat(row.path).catch(() => void 0);
  • 读取本地文件
    packages/dsh-dify-sidebar/lib/index.js:318
    const level = await opendir(dir).catch(() => void 0);
  • 读取本地文件
    packages/dsh-dify-sidebar/lib/index.js:519
    const info = await stat(path);
  • 读取本地文件
    packages/dsh-dify-sidebar/lib/index.js:522
    const etag = `"${shortHash(await readFile(path))}"`;
  • 读取本地文件
    packages/dsh-dify-sidebar/lib/index.js:572
    const body = await readFile(join(chunkDir, `client-${name}.js`));
  • 执行外部命令固定命令
    packages/dsh-dify-sidebar/lib/index.js:664
    const child = spawn("git", full, {
  • 写入本地文件
    packages/dsh-dify-sidebar/lib/index.js:1044
    for (const helper of candidates) if (existsSync(helper)) chmodSync(helper, 493);
  • 启用终端会话(PTY)
    packages/dsh-dify-sidebar/lib/index.js:1101
    pty: this.nodePty.spawn(shell ?? this.shell, shellSpawnArgs(shellArgs ?? this.shellArgs), {
  • 启用终端会话(PTY)
    packages/dsh-dify-sidebar/lib/index.js:1373
    const pty = this.nodePty.spawn(shell ?? this.shell, shellSpawnArgs(shellArgs ?? this.shellArgs), {
  • 写入本地文件
    packages/dsh-dify-sidebar/lib/index.js:2532
    await mkdir(dirname(path), { recursive: true });
  • 写入本地文件
    packages/dsh-dify-sidebar/lib/index.js:2533
    await writeFile(tmp, content, "utf8");
  • 写入本地文件
    packages/dsh-dify-sidebar/lib/index.js:2534
    await rename(tmp, path);
  • 删除本地文件
    packages/dsh-dify-sidebar/lib/index.js:2536
    await rm(tmp, { force: true }).catch(() => {});
  • 发起网络请求
    packages/dsh-dify-sidebar/lib/index.js:2659
    let response = await fetch(parsed, {
  • 发起网络请求
    packages/dsh-dify-sidebar/lib/index.js:2664
    if (response.status === 405 || response.status === 501) response = await fetch(parsed, {
  • 启用终端会话(PTY)
    packages/dsh-dify-sidebar/src/agent-pty.ts:222
    const pty = this.nodePty.spawn(shell ?? this.shell, shellSpawnArgs(shellArgs ?? this.shellArgs), {
  • 读取本地文件
    packages/dsh-dify-sidebar/src/bundle-route.ts:51
    const info = await stat(path)
  • 读取本地文件
    packages/dsh-dify-sidebar/src/bundle-route.ts:56
    const etag = `"${shortHash(await readFile(path))}"`
  • 读取本地文件
    packages/dsh-dify-sidebar/src/bundle-route.ts:107
    const body = await readFile(join(chunkDir, `client-${name}.js`))
  • 读取本地文件
    packages/dsh-dify-sidebar/src/fs-search.ts:58
    const level = await opendir(dir).catch(() => undefined)
  • 读取本地文件
    packages/dsh-dify-sidebar/src/fs-tree.ts:49
    level = await opendir(path)
  • 读取本地文件
    packages/dsh-dify-sidebar/src/fs-tree.ts:100
    const info = await stat(row.path).catch(() => undefined)
  • 执行外部命令固定命令
    packages/dsh-dify-sidebar/src/git.ts:97
    const child = spawn('git', full, {
  • 读取本地文件
    packages/dsh-dify-sidebar/src/index.ts:144
    const info = await stat(path).catch((error: unknown) => {
  • 写入本地文件
    packages/dsh-dify-sidebar/src/index.ts:269
    await mkdir(dirname(path), { recursive: true })
  • 写入本地文件
    packages/dsh-dify-sidebar/src/index.ts:270
    await writeFile(tmp, content, 'utf8')
  • 写入本地文件
    packages/dsh-dify-sidebar/src/index.ts:271
    await rename(tmp, path)
  • 删除本地文件
    packages/dsh-dify-sidebar/src/index.ts:273
    await rm(tmp, { force: true }).catch(() => {})
  • 发起网络请求
    packages/dsh-dify-sidebar/src/index.ts:448
    let response = await fetch(parsed, { method: 'HEAD', redirect: 'follow', signal: controller.signal })
  • 发起网络请求
    packages/dsh-dify-sidebar/src/index.ts:452
    response = await fetch(parsed, { method: 'GET', redirect: 'follow', signal: controller.signal })
  • 读取本地文件
    packages/dsh-dify-sidebar/src/index.ts:660
    const info = await stat(path)
  • 读取本地文件
    packages/dsh-dify-sidebar/src/index.ts:665
    const body = await readFile(path)
  • 读取本地文件
    packages/dsh-dify-sidebar/src/index.ts:721
    const info = await stat(absolute)
  • 读取本地文件
    packages/dsh-dify-sidebar/src/index.ts:726
    const body = await readFile(absolute)
  • 读取本地文件
    packages/dsh-dify-sidebar/src/pty-deps.ts:124
    return existsSync(join(dir, 'package.json')) && existsSync(join(dir, 'pnpm-workspace.yaml'))
  • 读取本地文件
    packages/dsh-dify-sidebar/src/pty-deps.ts:147
    if (!existsSync(file)) return false
  • 读取本地文件
    packages/dsh-dify-sidebar/src/pty-deps.ts:149
    const parsed = JSON.parse(readFileSync(file, 'utf8')) as { name?: unknown }
  • 读取本地文件
    packages/dsh-dify-sidebar/src/pty-deps.ts:188
    if (existsSync(script)) {
  • 读取本地文件
    packages/dsh-dify-sidebar/src/pty-deps.ts:193
    if (existsSync(script)) {
  • 写入本地文件
    packages/dsh-dify-sidebar/src/pty-manager.ts:38
    if (existsSync(helper)) chmodSync(helper, 0o755)
  • 读取本地文件
    packages/dsh-dify-sidebar/src/pty-manager.ts:38
    if (existsSync(helper)) chmodSync(helper, 0o755)
  • 启用终端会话(PTY)
    packages/dsh-dify-sidebar/src/pty-manager.ts:134
    pty: this.nodePty.spawn(shell ?? this.shell, shellSpawnArgs(shellArgs ?? this.shellArgs), {
扫描于 2026/11/2(1 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库

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

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

界面预览

1 张 · 点击查看大图

功能亮点

  • 对话构建工作流
  • 本地Dify工作流
  • 右侧实时显示

在 DeepSeek Harness 里实时对话,构建本地 Dify 工作流

README

由 DeepSeek 最新模型翻译生成
dsh-dify-builder 在 DeepSeek Harness 中通过对话实时构建本地 Dify 工作流。右侧直接显示 Dify 画布,节点和连线原地更新,不反复刷新页面。 效果演示 对话实时生成 Dify 工作流演示 左侧通过对话描述需求,右侧 Dify 画布会同步创建和修改节点。点击上方动画可播放完整演示视频(约 1 分 51 秒,默认静音,可在播放器中开启声音)。 安装前检查 1. Node.js 20+ 检查: node --version npx --version 如果命令不存在,先从 Node.js 官网 安装 LTS 版本,再重新打开终端。版本低于 20 时也需要先升级。 2. DeepSeek Harness 检查: dsh --version 如果命令不存在,执行: npm install -g @deepseek-ai/dsh@latest dsh --version 首次使用可运行 dsh web,浏览器会打开 DSH。请先确认 DSH 可以正常对话。若 DSH 已配置 DeepSeek API Key,安装器会尝试将其同步到 Dify;密钥不会写入仓库或打印到日志。没有 DeepSeek Key 也可以完成安装并使用非模型工作流。更多信息见 DeepSeek Harness 官方项目。
展开完整文档(README 剩余 1 节)
dsh-dify-builder

在 DeepSeek Harness 中通过对话实时构建本地 Dify 工作流。右侧直接显示 Dify 画布,节点和连线原地更新,不反复刷新页面。

效果演示

对话实时生成 Dify 工作流演示

左侧通过对话描述需求,右侧 Dify 画布会同步创建和修改节点。点击上方动画可播放完整演示视频(约 1 分 51 秒,默认静音,可在播放器中开启声音)。

安装前检查

1. Node.js 20+

检查:

node --version
npx --version

如果命令不存在,先从 Node.js 官网 安装 LTS 版本,再重新打开终端。版本低于 20 时也需要先升级。

2. DeepSeek Harness

检查:

dsh --version

如果命令不存在,执行:

npm install -g @deepseek-ai/dsh@latest
dsh --version

首次使用可运行 dsh web,浏览器会打开 DSH。请先确认 DSH 可以正常对话。若 DSH 已配置 DeepSeek API Key,安装器会尝试将其同步到 Dify;密钥不会写入仓库或打印到日志。没有 DeepSeek Key 也可以完成安装并使用非模型工作流。更多信息见 DeepSeek Harness 官方项目。

3. Docker

检查:

docker --version

如果命令不存在,请先安装 Docker Desktop。macOS 上安装后无需提前启动,安装器会自动打开并等待 Docker 就绪;Linux 需要确保 Docker Engine 可以正常运行。

快速安装

无需克隆仓库,直接从 GitHub Release 安装:

npx --yes "https://github.com/newbieYi/dsh-dify-builder/archive/refs/tags/v0.2.4.tar.gz" install

该命令固定使用经过验证的 v0.2.4,只需要 npx,不要求本机安装 Git。项目源码、版本记录和问题反馈位于 newbieYi/dsh-dify-builder。

看到“安装完成”后,重新打开 DSH Web,新建会话并选择「Dify 工作流构建」。不需要手动下载 Dify、编写 Docker 配置、安装 Sidebar 或创建管理员账号。

安装器会在下载 Dify 前检查 DSH CLI 和 Docker。前置条件不满足时会停止并显示对应安装命令,不会执行到一半才提示。

安装器会做什么

安装器自动完成并逐项验收:

1. 检查 DSH CLI 和 Docker;macOS 上 Docker 未启动时自动打开 Docker Desktop。
2. 下载经过验证的固定版本 Dify。
3. 配置 iframe 和 Dify 原生协作通道。
4. 启动并检查 Dify 容器,初始化本地管理员。
5. 尝试安装 Dify 官方 DeepSeek 模型插件;存在 DSH DeepSeek Key 时同步凭据并选择可用模型。
6. 安装 DSH runtime、内置 Sidebar、右侧 panel 和 Agent preset。
7. 检查插件冲突、Dify setup 和实时协作端点;默认模型缺失只显示警告,不会阻断安装。

首次安装会使用 admin@dify.local,密码随机生成并仅保存在本机私有配置中。重复执行安装命令是安全的,不会重建管理员或更换已有 Dify 密钥。

日常使用

1. 在空白新会话中选择「Dify 工作流构建」。
2. 如果 Docker 或 Dify 没有运行,插件会自动检查并拉起。
3. 在左侧描述要创建或修改的工作流,右侧 Dify 画布会实时更新。
4. 空白会话切换到其他模式时,Dify 标签和右侧栏会自动关闭。

遇到问题

运行只读诊断:

npx --yes "https://github.com/newbieYi/dsh-dify-builder/archive/refs/tags/v0.2.4.tar.gz" doctor

诊断会检查 DSH CLI、Docker、三个插件、Sidebar 冲突、Dify setup 和 Socket.IO 协作通道,不会修改配置或重启服务。默认模型缺失会显示 WARN,但诊断仍可通过。

常见情况:

| 现象 | 处理方式 |
| 提示找不到 Docker | 先安装 Docker Desktop,再重新执行安装命令 |
| 安装完成但看不到新模式 | 重新启动 DSH Web 后再新建会话 |
| 提示默认模型未配置 | 非模型工作流仍可使用;需要大模型节点时,在 Dify 中配置并选择模型 |
| 大模型节点不可选 | 在 Dify 的模型供应商设置中配置可用模型,再为节点选择该模型 |
| 已有 Dify,管理员登录验证失败 | 使用下方高级参数提供现有账号和密码 |
| 安装在管理员初始化后中断 | 直接再次执行安装命令,安装器会恢复默认管理员凭据并继续 |

高级安装参数

使用已有账号或指定访问地址:

npx --yes "https://github.com/newbieYi/dsh-dify-builder/archive/refs/tags/v0.2.4.tar.gz" install \
--email owner@example.com \
--password 'YourStrongPassword123!' \
--name Owner \
--base-url http://127.0.0.1:8080

默认数据目录:

| 内容 | 默认位置 |
| Dify 源码和数据入口 | ~/.dsh/dify-builder/dify |
| 私有配置 | ~/.dsh/dify-builder/config.json |
| 打包后的 DSH 插件 | ~/.dsh/dify-builder/packages |
| Agent preset | ~/.dsh/.agent-presets/dify-builder |

可用 DSH_HOME 修改 DSH 根目录,用 DSH_DIFY_HOME 单独修改 Dify 部署目录。

从源码开发和验证

仅项目开发者需要使用:

node ./bin/dsh-dify-builder.js install
npm test

普通用户不需要进入 packages/,也不需要单独安装或阅读 Sidebar 子项目。

技术说明

- Dify 固定在经过验证的上游 commit;本项目不修改 Dify 源码。
- 草稿保存使用 Dify 原生 collaboration 模式和 Socket.IO workflow_update。
- 创建应用后右侧只导航一次,普通节点修改不会刷新 iframe。
- dsh-dify-sidebar 随安装器发行,安装时会移除冲突的原版 Sidebar。
- 私密账号和密码只写入权限为 owner-only 的本地配置,不进入 preset 或公开仓库。

平台与许可

当前完成 macOS 和 Linux 支持;Windows 尚未完成端到端验证。

主项目使用 MIT License。packages/dsh-dify-sidebar 派生自 MIT 许可的 DSH-better-sidebar,原始 LICENSE 已保留,归属信息见 NOTICE。
预览分享卡片长什么样 ↓newbieYi/dsh-dify-builder
分享 · DeepSeek Harness Hub
newbieYi/dsh-dify-builder

在 DeepSeek Harness 中通过对话实时构建本地 Dify 工作流。右侧直接显示 Dify…

这是你的仓库?认领条目

回到顶部