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

自媒体工作台 Harzva/dsh-wemedia-workbench

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

本地整理稿件并审批发布到多个内容渠道

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

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

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

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:需留意
是什么[目录]—
dsh 原生插件 · market
暂无时间戳·判据 →
装得上吗[实装验证]!
作者未把包发布到 npm,只能用源码安装
插件本身没问题,是分发方式不同
数据截至 2026/09/25·判据 →
安全吗[自动扫描]—
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
数据截至 2026/11/04·判据 →
还在维护吗[仓库]—
更新放缓:最近一次提交在 52 天前
暂无时间戳·判据 →
图例:✓ 通过! 需注意— 未判定 / 无数据· 「未判定」= 本站尚无数据,不代表插件有问题
档位由哪些信号合成

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

验证判据与等级说明 →

可信度证据

安装兼容性检查需源码安装

仓库 package.json 标记 private,未发布到 npm,需从源码安装

展开查看检查明细 ↓

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

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

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

验证方式:npm registry 存在性 + package.json 静态校验 · 最后检查 2026/9/21 23:55:28

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

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

可执行外部命令读写/删除本地文件发起外部网络请求
查看扫描证据(共 97 处,展示前 94 条)
  • 发起网络请求
    src/application/channelPublishingService.ts:242
    const decision = await approval.request(intent, controller.signal);
  • 发起网络请求
    src/application/workbenchService.ts:292
    return this.draftBatches.request(request, caller, signal);
  • 发起网络请求
    src/application/workbenchService.ts:296
    return this.references.request(request, signal);
  • 发起网络请求
    src/application/workbenchService.ts:300
    return this.accounts.request(request, caller, signal);
  • 发起网络请求
    src/application/workbenchService.ts:306
    return this.channelService.request(request, caller, signal);
  • 发起网络请求
    src/application/workbenchService.ts:778
    const decision = await approval.request(saved.intent, controller.signal);
  • 发起网络请求
    src/client/content-library-controller.ts:220
    const page = await this.request(input, owner.signal) as LibraryPage;
  • 发起网络请求
    src/client/content-library-controller.ts:253
    const result = await this.request({ operation: "batch_preflight", contentRefs: this.state.checked.map(value => value.contentRef), channels: [...this.s
  • 发起网络请求
    src/client/content-library-controller.ts:267
    const detail = await this.request({ operation: "library_read", itemId }, owner.signal) as LibraryDetail;
  • 发起网络请求
    src/client/content-library-controller.ts:279
    const chunk = await this.request({ operation: "library_media", itemId, offset, length: CONTENT_MEDIA_CHUNK, revisionDigest: item.revisionDigest }, own
  • 发起网络请求
    src/client/controller.ts:221
    const result = await this.remote.request(request, signal);
  • 发起网络请求
    src/host/approval.ts:29
    const outcome = await approval.request({ agent, toolName: exec.name, callId: exec.callId, signal, reason: `${intent.targetSummary}\n内容:${intent.conten
  • 写入本地文件
    src/host/compose.ts:72
    await mkdir(config.dataDir, { recursive: true, mode: 0o700 });
  • 读取本地文件
    src/host/compose.ts:108
    const script = await realpath(adapterConfig.command);
  • 读取本地文件
    src/host/compose.ts:109
    if (basename(script) !== "wemedia_bridge.mjs" || !(await stat(script)).isFile()) throw new Error("bridge");
  • 读取本地文件
    src/host/compose.ts:122
    const script = await realpath(entry.command);
  • 读取本地文件
    src/host/compose.ts:123
    if (basename(script) !== "wemedia_bridge.mjs" || !(await stat(script)).isFile()) throw new Error("bridge");
  • 发起网络请求
    src/host/tools.ts:106
    return await workbench.request({ ...args, operation: spec.operation }, binding.caller, exec.signal);
  • 写入本地文件
    src/infrastructure/accountApiLogin.ts:130
    await mkdir(dirname(config.secretPath), { recursive: true, mode: 0o700 });
  • 读取本地文件
    src/infrastructure/accountApiLogin.ts:131
    if (await realpath(dirname(config.secretPath)) !== dirname(config.secretPath)) throw new Error("Credential directory changed");
  • 写入本地文件
    src/infrastructure/accountApiLogin.ts:143
    writeFileSync(fd, `${JSON.stringify(stored, null, 2)}\n`); fsyncSync(fd); closeSync(fd); fd = undefined;
  • 写入本地文件
    src/infrastructure/accountApiLogin.ts:144
    renameSync(temporary, config.secretPath);
  • 删除本地文件
    src/infrastructure/accountApiLogin.ts:145
    } finally { if (fd !== undefined) closeSync(fd); try { unlinkSync(temporary); } catch {} }
  • 读取本地文件
    src/infrastructure/accountApiLogin.ts:189
    const command = await realpath(entry.command);
  • 读取本地文件
    src/infrastructure/accountApiLogin.ts:190
    if (basename(command) !== "wemedia_bridge.mjs" || !(await lstat(command)).isFile() || basename(dirname(command)) !== "src") throw new Error("X bridge
  • 读取本地文件
    src/infrastructure/accountApiLogin.ts:193
    for (const file of ["oauth.js", "store.js", "config.js"]) if (!(await lstat(resolve(project, "src", file))).isFile()) throw new Error("X OAuth unavail
  • 读取本地文件
    src/infrastructure/accountApiLogin.ts:206
    const command = await realpath(adapter.command);
  • 读取本地文件
    src/infrastructure/accountApiLogin.ts:229
    const command = await realpath(adapter.command);
  • 发起网络请求
    src/infrastructure/accountLogin.ts:73
    const response = await fetch(url, { method: "GET", headers, redirect: "error", signal: AbortSignal.any([signal, AbortSignal.timeout(timeout)]) });
  • 读取本地文件
    src/infrastructure/accountLogin.ts:181
    const bytes = await handle.readFile(); const after = await handle.stat(); const named = await lstat(file);
  • 读取本地文件
    src/infrastructure/accountLogin.ts:201
    const parent = dirname(file); check(await realpath(parent) === parent, "知乎凭据目录已变化,原凭据已保留。");
  • 读取本地文件
    src/infrastructure/accountLogin.ts:208
    active(signal); await checkCurrent(); check(await realpath(parent) === parent, "知乎凭据目录已变化,原凭据已保留。"); active(signal);
  • 写入本地文件
    src/infrastructure/accountLogin.ts:211
    renameSync(temp, file); created = false;
  • 删除本地文件
    src/infrastructure/accountLogin.ts:213
    } finally { if (created) await unlink(temp).catch(() => {}); }
  • 读取本地文件
    src/infrastructure/accountLogin.ts:227
    const executablePath = await stat(chrome).then(info => info.isFile() ? chrome : undefined).catch(() => undefined);
  • 读取本地文件
    src/infrastructure/accountLogin.ts:272
    const path = await realpath(config!.command!); check(basename(path) === "wemedia_bridge.mjs" && (await stat(path)).isFile(), "登录适配器入口无效。"); return pat
  • 读取本地文件
    src/infrastructure/accountLogin.ts:272
    const path = await realpath(config!.command!); check(basename(path) === "wemedia_bridge.mjs" && (await stat(path)).isFile(), "登录适配器入口无效。"); return pat
  • 读取本地文件
    src/infrastructure/contentLibrary.ts:86
    const rootInfo = await lstat(root.realPath);
  • 读取本地文件
    src/infrastructure/contentLibrary.ts:91
    const info = await lstat(current);
  • 读取本地文件
    src/infrastructure/contentLibrary.ts:109
    const latest = await lstat(absolute, { bigint: true });
  • 读取本地文件
    src/infrastructure/contentLibrary.ts:383
    const entries = await readdir(resolve(root.realPath, path), { withFileTypes: true });
  • 读取本地文件
    src/infrastructure/contentLibrary.ts:394
    const info = await lstat(resolve(root.realPath, child));
  • 读取本地文件
    src/infrastructure/contentLibrary.ts:404
    const info = await lstat(root.realPath);
  • 写入本地文件
    src/infrastructure/fileCommitLock.ts:13
    try { await mkdir(dirname(filePath), { recursive: true, mode: 0o700 }); }
  • 读取本地文件
    src/infrastructure/fileCommitLock.ts:30
    const current = await lstat(lockPath, { bigint: true }).catch(() => null);
  • 删除本地文件
    src/infrastructure/fileCommitLock.ts:31
    if (identity && current?.isFile() && !current.isSymbolicLink() && current.dev === identity.dev && current.ino === identity.ino) await unlink(lockPath)
  • 写入本地文件
    src/infrastructure/indexCacheRepository.ts:21
    await mkdir(directory, { recursive: true, mode: 0o700 });
  • 写入本地文件
    src/infrastructure/indexCacheRepository.ts:31
    await rename(temporary, path);
  • 删除本地文件
    src/infrastructure/indexCacheRepository.ts:39
    await unlink(temporary).catch(() => undefined);
  • 读取本地文件
    src/infrastructure/indexCacheRepository.ts:51
    const raw = await readFile(this.filePath, "utf8");
  • 删除本地文件
    src/infrastructure/indexCacheRepository.ts:82
    await unlink(this.filePath);
  • 读取本地文件
    src/infrastructure/ledgerRepository.ts:43
    raw = await readFile(this.filePath, "utf8");
  • 读取本地文件
    src/infrastructure/legacyLedgerReader.ts:53
    raw = await readFile(absolutePath, "utf8");
  • 读取本地文件
    src/infrastructure/localPublications.ts:88
    if (!path || await realpath(this.root) !== this.root) throw new Error("rejected");
  • 读取本地文件
    src/infrastructure/localPublications.ts:89
    const rootInfo = await lstat(this.root);
  • 读取本地文件
    src/infrastructure/localPublications.ts:94
    const info = await lstat(current);
  • 读取本地文件
    src/infrastructure/localPublications.ts:97
    if (await realpath(path) !== path) throw new Error("rejected");
  • 读取本地文件
    src/infrastructure/localPublications.ts:114
    const entry = await lstat(path, { bigint: true });
  • 读取本地文件
    src/infrastructure/localSetup.ts:33
    const first = await lstat(normalized, { bigint: true });
  • 读取本地文件
    src/infrastructure/localSetup.ts:34
    const canonical = await realpath(normalized);
  • 读取本地文件
    src/infrastructure/localSetup.ts:38
    await access(normalized, constants.R_OK | (writable ? constants.W_OK : 0));
  • 读取本地文件
    src/infrastructure/localSetup.ts:39
    const final = await lstat(normalized, { bigint: true });
  • 写入本地文件
    src/infrastructure/manifest.ts:88
    await mkdir(target.value.absolutePath, { recursive: false, mode: 0o700 });
  • 写入本地文件
    src/infrastructure/manifest.ts:90
    await mkdir(resolve(writeRoot.realPath, directory), { recursive: false, mode: 0o700 });
  • 写入本地文件
    src/infrastructure/overlayRepository.ts:27
    await mkdir(directory, { recursive: true, mode: 0o700 });
  • 写入本地文件
    src/infrastructure/overlayRepository.ts:38
    await rename(temporary, path);
  • 删除本地文件
    src/infrastructure/overlayRepository.ts:41
    await unlink(temporary).catch(() => undefined);
  • 读取本地文件
    src/infrastructure/overlayRepository.ts:77
    const raw = await readFile(this.filePath, "utf8");
  • 读取本地文件
    src/infrastructure/pathPolicy.ts:100
    entries = await readdir(current);
  • 读取本地文件
    src/infrastructure/pathPolicy.ts:120
    const resolved = await realpath(descriptor.path);
  • 读取本地文件
    src/infrastructure/pathPolicy.ts:121
    const info = await stat(resolved);
  • 读取本地文件
    src/infrastructure/pathPolicy.ts:135
    const resolved = await realpath(exact.value);
  • 读取本地文件
    src/infrastructure/pathPolicy.ts:139
    const info = await stat(resolved);
  • 读取本地文件
    src/infrastructure/pathPolicy.ts:169
    const entries = await readdir(parent.value.absolutePath);
  • 执行外部命令来自配置/变量
    src/infrastructure/processRunner.ts:126
    const child = spawn(policy.path, command.argv, {
  • 读取本地文件
    src/infrastructure/publicationDrafts.ts:60
    const before = await lstat(root.realPath, { bigint: true });
  • 读取本地文件
    src/infrastructure/publicationDrafts.ts:61
    if (!before.isDirectory() || before.isSymbolicLink() || await realpath(root.realPath) !== root.realPath) return fail("PUBLICATION_ROOT_CHANGED", "内容写入
  • 读取本地文件
    src/infrastructure/publicationDrafts.ts:62
    const after = await lstat(root.realPath, { bigint: true });
  • 读取本地文件
    src/infrastructure/publicationDrafts.ts:80
    const info = await lstat(current);
  • 读取本地文件
    src/infrastructure/publicationDrafts.ts:86
    const file = await this.exact(path), named = await lstat(file, { bigint: true });
  • 读取本地文件
    src/infrastructure/publicationDrafts.ts:98
    const after = await handle.stat({ bigint: true }), current = await lstat(await this.exact(path), { bigint: true });
  • 写入本地文件
    src/infrastructure/publicationDrafts.ts:236
    await mkdir(created.value.absolutePath, { mode: 0o700 });
  • 写入本地文件
    src/infrastructure/publicationDrafts.ts:237
    await mkdir(resolve(await this.exact(folder), "assets"), { mode: 0o700 });
  • 读取本地文件
    src/infrastructure/scanner.ts:151
    const info = await stat(resolved.value.absolutePath, { bigint: true });
  • 读取本地文件
    src/infrastructure/scanner.ts:228
    const entries = await readdir(directory, { withFileTypes: true });
  • 读取本地文件
    src/infrastructure/watcher.ts:32
    const entries = await readdir(directory, { withFileTypes: true });
  • 读取本地文件
    src/infrastructure/watcher.ts:39
    const info = await stat(resolve(directory, entry.name), { bigint: true });
  • 发起网络请求
    src/infrastructure/wechatCollector.ts:176
    const pending = fetch(url.href, { method: "GET", redirect: "manual", credentials: "omit", referrerPolicy: "no-referrer", signal, headers: { Accept: "t
  • 读取本地文件
    src/infrastructure/workbenchDocuments.ts:162
    const namedBefore = await lstat(path.value.absolutePath, { bigint: true });
  • 读取本地文件
    src/infrastructure/workbenchDocuments.ts:171
    if (!current.ok || current.value.kind !== "file" || current.value.absolutePath !== path.value.absolutePath || !sameFileState(before, await lstat(curre
  • 写入本地文件
    src/infrastructure/workbenchDocuments.ts:377
    await mkdir(created.value.absolutePath, { mode: 0o700 });
  • 写入本地文件
    src/infrastructure/workbenchDocuments.ts:381
    await mkdir(resolve(created.value.absolutePath, "assets"), { mode: 0o700 });
  • 发起网络请求
    src/infrastructure/xhsCollector.ts:53
    const response = await runtime.fetch(new URL(`/api/v1/${route}`, runtime.endpoint), {
  • 发起网络请求
    src/remote/service.ts:13
    return this.workbench.request(request, { kind: "user" }, signal);
扫描于 2026/11/4(1 天前) · 范围 全包扫描(包内未声明入口) · 来源 GitHub 仓库

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

社区实装还没有人打卡 · 装过的第一个就是你
依赖的 DSH / Cordis 模块
@deepseek-ai/schemastery@deepseek-ai/cordis@deepseek-ai/cordis-plugin-loader@deepseek-ai/dsh@deepseek-ai/dsh-agent@deepseek-ai/dsh-api-gateway@deepseek-ai/dsh-api-remotes@deepseek-ai/dsh-client-connection@deepseek-ai/dsh-client-locale@deepseek-ai/dsh-client-runtime@deepseek-ai/dsh-client-ui-layout@deepseek-ai/dsh-client-ui-primitives
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

功能亮点

  • 本地整理稿件
  • 审批发布多渠道
  • AI辅助工作流

DeepSeek Harness 的本地优先媒体工作台:AI 辅助工作流、绑定版本的评审、原生审批和持久任务。

README

由 DeepSeek 最新模型翻译生成
dsh-wemedia-workbench 面向 DeepSeek Harness 的本地优先自媒体工作台:AI 整理内容,工作台管理修订、审阅证据、审批与渠道任务。 A local-first media workbench for DeepSeek Harness, with revision-bound reviews, explicit approvals and persistent delivery jobs. 状态:早期开发版源码。 当前锁定 DSH 0.1.1-rc.2 / Cordis 4.0.1,不承诺兼容其他版本。渠道桥接代码不等于真实账号发帖已验收;默认配置不包含内容目录、凭据或已启用的远端适配器。本项目不是 DeepSeek 官方产品。 当前能力 - 本地内容库:只读发现文章、图像和视频,支持筛选、来源映射和独立写根。 - 文章与媒体稿件:不可变修订、素材绑定、差异预览和未保存修改保护。 - 审阅证据:事实、编辑、图片与公式、手机视觉四类证据绑定具体修订和文件字节。 - DSH 协作:原生工具与 PTC 共用应用服务,沿用当前会话的模型和工具权限。 - 持久任务:预检、一次性操作意图、原生审批、Job 状态与目标回读;未知结果先核对,不盲目重发。
展开完整文档(README 剩余 1 节)
dsh-wemedia-workbench

面向 DeepSeek Harness 的本地优先自媒体工作台:AI 整理内容,工作台管理修订、审阅证据、审批与渠道任务。

A local-first media workbench for DeepSeek Harness, with revision-bound reviews,
explicit approvals and persistent delivery jobs.

状态:早期开发版源码。 当前锁定 DSH 0.1.1-rc.2 / Cordis 4.0.1,不承诺兼容其他版本。渠道桥接代码不等于真实账号发帖已验收;默认配置不包含内容目录、凭据或已启用的远端适配器。本项目不是 DeepSeek 官方产品。

当前能力

- 本地内容库:只读发现文章、图像和视频,支持筛选、来源映射和独立写根。
- 文章与媒体稿件:不可变修订、素材绑定、差异预览和未保存修改保护。
- 审阅证据:事实、编辑、图片与公式、手机视觉四类证据绑定具体修订和文件字节。
- DSH 协作:原生工具与 PTC 共用应用服务,沿用当前会话的模型和工具权限。
- 持久任务:预检、一次性操作意图、原生审批、Job 状态与目标回读;未知结果先核对,不盲目重发。
- 批量微信草稿:发送选中或全库待发送文章,先确认清单,再交给当前 Agent 逐篇审批和投递;可查看逐篇结果、停止队列。
- 多渠道接口:微信公众号、知乎、小红书、X 的适配器契约和工作台操作入口;运行桥、登录环境和账号由使用者另行配置。
- 素材辅助:确定性公式渲染与 PDF 图表裁剪脚本,保留来源及 SHA,不自动下载 MinerU 模型。

内容入口使用与当前 DSH 结构匹配的 DOM 兼容层,不是官方一级导航 Slot;结构不匹配时回退到附加入口。其他平台目录仅供接入研究,不代表发布能力。

工作流

1. 从授权的本地素材和论文来源整理内容,保留引用。
2. 通过原生工作流保存修订;原始文件保持只读。
3. 检查事实、措辞、图片和公式,实际查看手机预览,登记当前版本证据。
4. 冻结正文、素材和报告,逐篇预检并预览拟执行动作。
5. 对准确动作进行原生审批,再执行和跟踪同一个 Job。
6. 回读目标和当前修订。草稿箱成功不等于正式发布。

AI 参与整理应在文章中明确披露。模型名称不是默认必填的逐篇字段,失败稿件也无需额外维护模型归属表;但修订、任务和远端结果仍须保留必要记录,避免重复提交。可复用经验进入工作流文档,私有执行记录不随源码公开。
详见 AI 整理与工作流公开。

开发

需要 Node.js >=22.19.0 和 pnpm 10.16.1。

git clone https://github.com/Harzva/dsh-wemedia-workbench.git
cd dsh-wemedia-workbench
pnpm install --frozen-lockfile
pnpm build
pnpm check

prepare 会构建本地 lib/。不要在被运行中 DSH 直接加载的源码目录内升级、构建或验证发布包;使用独立检出和隔离 profile。仓库不分发账号桥、密钥、 Cookie、文章库、模型订阅或模型权重。安装源码也不会自动配置发布账号。

CLI 与 PTC

当前没有统一的 wemedia CLI。批量微信草稿通过工作台与同源原生工具提供,不是独立 CLI,也不是无审批的批量发布命令。
DSH 原生工具和 PTC 是工作流入口;PTC 需宿主已启用对应工具模式。
wemedia_batch_preflight 只做只读预检,不创建草稿或正式发布。
两个 Python 脚本是本地素材辅助工具,不是另一套发布引擎。

批量草稿每次最多 50 篇。“待发送”读取全库当前 ready 文章,不受当前页分页影响;超过上限会明确要求分批,不静默截断。已入箱、已有旧目标、审阅缺失或结果待核对的文章分别跳过或阻断。每次推进最多启动一个原生任务,版本和账号变化会阻断该项;拒绝审批、取消或不确定结果会停止后续队列。
批次 completed 只表示清单处理完毕,必须逐项统计成功与未发送的文章。

后续 CLI 应薄封装同一应用服务,沿用身份、版本、审批和 Job 契约,不能另建绕过审批的存储或执行路径。

可选 Python 工具

- scripts/render-formulas.py:使用独立安装的 Matplotlib 渲染公式。
- scripts/crop-pdf-asset.py:使用独立安装的 PyMuPDF 裁剪图表,支持明确的页面点、渲染像素、归一化和 MinerU 坐标。

这些依赖不随源码捆绑,也不会由脚本自动安装。依赖适用各自许可证,尤其 PyMuPDF 并非 MIT;详见 第三方说明。

文档

- 适配器契约
- PTC 工作流
- 执行经验与恢复边界
- PDF 图表裁剪
- 公式排版
- AI 整理与工作流公开
- 贡献指南 / 安全说明

许可证

项目源码采用 MIT。保留已有贡献者和复用代码的版权声明。
外部依赖、平台服务、论文、图片、字体和模型权重不因本仓库开源而变成 MIT。
预览分享卡片长什么样 ↓Harzva/dsh-wemedia-workbench
分享 · DeepSeek Harness Hub
Harzva/dsh-wemedia-workbench

本地整理稿件并审批发布到多个内容渠道

这个插件是你维护的吗?
作者本人可认领并核对本条目;认领通过后,详情页会显示「作者已认领」标记。
认领条目 →
回到顶部