# DSH md2wechat 插件 `@geekjourneyx/md2wechat` 为 DeepSeek Harness(DSH)提供受保护的 Markdown 到微信公众号草稿工作流。它不会改写原始 Markdown,流程止于微信草稿创建。 插件仓库首发版本是 `v1.0.0`,配套的主包与 CLI 版本是 `3.3.0`。这两个版本分别表示插件发布历史和 md2wechat CLI 发布历史,不应互相替换。 ## 前提与安装 需要已安装带 Web profile 的 DSH `0.1.0-rc.5`。本次首发只通过 GitHub 提供,不发布 npm:从 [v1.0.0 Release](https://github.com/geekjourneyx/dsh-md2wechat/releases/tag/v1.0.0) 下载主包 `geekjourneyx-md2wechat-3.3.0.tgz`,再下载一个与本机匹配的平台包。 以 macOS Apple Silicon 为例,在下载目录执行: ```bash dsh plugin --profile web add --ignore-scripts --save-exact \ ./geekjourneyx-md2wechat-darwin-arm64-3.3.0.tgz \ ./geekjourneyx-md2wechat-3.3.0.tgz ``` 其他机器选择对应的 `darwin-x64`、`linux-x64`、`linux-arm64` 或 `win32-x64` 包。主包和平台包必须一起安装。没有安装脚本(no install scripts):`preinstall`、`install`、`postinstall` 都不会下载或执行额外安装逻辑。 在写入工作流前,先配置 md2wechat 的 API、图片服务和默认或命名公众号账号。下面给出 DSH 密钥存储和 `credentialRefs` 的准确配置;不要把密钥写进文章或提示词。 ## 凭据与 md2wechat 配置 DSH 的受管凭据文件是 `$DSH_HOME/.credentials.yaml`;未设置 `DSH_HOME` 时是 `~/.dsh/.credentials.yaml`。它只存放密钥值,插件配置只保存引用名。先在本机创建并编辑 owner-only 文件: 插件预览和草稿流程要求把 `MD2WECHAT_API_KEY` 放入 DSH 受管凭据并通过 `credentialRefs` 映射。只在 md2wechat 自身配置里保存该 Key 不满足插件要求;这是有意采用的更严格隔离,避免插件静默继承未明确授权的现有密钥。 ```bash export DSH_HOME="${DSH_HOME:-$HOME/.dsh}" mkdir -p "$DSH_HOME" chmod 700 "$DSH_HOME" touch "$DSH_HOME/.credentials.yaml" chmod 600 "$DSH_HOME/.credentials.yaml" "${EDITOR:-vi}" "$DSH_HOME/.credentials.yaml" ``` 文件是 YAML 映射,只写实际需要的值: ```yaml MD2WECHAT_API_KEY: "替换为 md2wechat API Key" WECHAT_APPID: "替换为公众号 AppID" WECHAT_SECRET: "替换为公众号 AppSecret" IMAGE_API_KEY: "替换为图片服务 Key" ``` 在 Web profile 的 `cordis.patch.yml` 中,把这些名称连接到插件。下面是完整支持的引用集合: ```yaml - id: md2wechat config: layoutBaseUrl: "https://www.md2wechat.cn" credentialRefs: MD2WECHAT_API_KEY: MD2WECHAT_API_KEY WECHAT_APPID: WECHAT_APPID WECHAT_SECRET: WECHAT_SECRET IMAGE_API_KEY: IMAGE_API_KEY ``` `MD2WECHAT_API_KEY is required for preview`,创建草稿也需要它。`WECHAT_APPID` 与 `WECHAT_SECRET` 是 `md2wechat_create_draft` 以及后备 `md2wechat_generate_images` 上传微信时可由 DSH 提供的公众号凭据;如果目标 md2wechat 账号已在自身配置中提供它们,就不必映射。DSH 自己生成图片时不需要 `IMAGE_API_KEY`。后备图片服务需要 Key 时,如果 md2wechat 自身配置没有提供 `IMAGE_API_KEY`,就在 `credentialRefs` 中映射它;映射后,DSH 的值会覆盖 md2wechat 配置中的该值。 插件配置的 `layoutBaseUrl` 决定 DSH 预览使用的排版服务,并在预览调用中显式注入 `MD2WECHAT_BASE_URL`。md2wechat 自己的配置(默认 `~/.config/md2wechat/config.yaml`)仍负责图片 provider/base URL/model 和直接或命名公众号账号定义;DSH 密钥存储只向已配置引用提供或覆盖密钥,不能替代这些账号和图片服务配置。先运行 `md2wechat config validate --json`、`md2wechat config wechat-accounts --json`,再在 DSH 中运行 `md2wechat_doctor`。 ## 八个工具 | 工具 | 作用 | 外部影响 | | --- | --- | --- | | `md2wechat_doctor` | 读取本地 CLI、配置、图片服务和公众号候选项。 | 无 | | `md2wechat_start_article` | 创建版本化工作副本并记录渲染和账号输入。 | 无 | | `md2wechat_improve_article` | 为当前 DSH Agent 返回针对当前文章的改进任务。 | 无 | | `md2wechat_plan_images` | 保存封面、信息图和正文配图计划。 | 无 | | `md2wechat_generate_images` | 仅在 DSH 没有生图能力时调用已配置的 md2wechat 图片服务。 | 授权后生成图片并上传微信 | | `md2wechat_preview` | 为当前工作版本生成已确认、不可变的 HTML 预览。 | 授权后请求排版服务 | | `md2wechat_create_draft` | 根据已确认预览上传图片并创建一次微信草稿。 | 授权后上传并创建草稿 | | `md2wechat_export` | 把当前版本归属的结果复制到工作区目标位置。 | 仅本地文件 | ## 从源文件到草稿 1. 先运行 `md2wechat_doctor`,处理其中的配置阻止项。 2. 用工作区 Markdown 文件作为 `sourcePath` 调用 `md2wechat_start_article`,保存返回的 `manifestPath`;原始文件不会被修改。 3. 需要改稿时,用 `md2wechat_improve_article` 把任务交给当前 DSH Agent。 4. 用 `md2wechat_plan_images` 保存封面和配图计划。DSH 自己能生图时,优先用它,并将结果保存到计划项的 `targetPath`。 5. 当前 DSH 没有图片生成能力时,才在 fallback 开启且一次性授权后调用 `md2wechat_generate_images`。 6. 用 `md2wechat_preview` 生成并查看预览。 7. 仅在用户明确要求创建微信草稿时,用同一个 `manifestPath` 调用 `md2wechat_create_draft`。 预览和草稿必须来自同一个版本(preview and draft must match the same revision)。草稿工具会在唯一一次草稿请求前再次核对已确认预览、账号、封面、工作文章和请求文件。已经成功的草稿默认不能重复创建;状态不明确时也会阻止再次创建。 ## 图片、产物与账号 正常规则是 DSH 优先生图。`md2wechat_generate_images` 是后备能力:只有当前 DSH Agent 没有生图能力时,才调用 md2wechat 已配置的图片服务;它不会启动另一个 Agent。 默认产物目录是工作区中的 `.dsh/md2wechat`。每个版本会保存文章工作副本、`article.json`、操作记录、图片计划/结果、预览 HTML/回执;请求草稿时还会保存草稿请求、授权和结果。需要复制文件到其他位置时,使用 `md2wechat_export`;插件不会覆盖原始 Markdown。 在 `md2wechat_start_article` 的可选 `account` 参数中选择账号。`md2wechat_doctor` 会列出账号候选项。预览和草稿会绑定所选账号身份;之后改成不同或已变化的账号会被拒绝。 ## 授权与无界面运行 每个外部操作都需要绑定该次工具调用的一次性 DSH 授权。预览在请求排版前授权;图片后备在生成/上传前授权;草稿在上传和创建草稿前授权。拒绝、取消或没有授权答复都不会被视为同意。 在 Web 中,对本次操作的授权卡作答即可。在 ACP 或其他无界面会话中,headless without an approval answerer fails closed:没有明确的授权答复器就会安全停止。只有自动化被明确允许执行相应外部操作时,才配置授权答复器。 ## 管理员开关 管理员可在 profile 的 `cordis.patch.yml` 中关闭微信写入工具,而不影响文章: ```yaml - id: md2wechat config: enableWechatWriteTools: false ``` 这会同时隐藏 `md2wechat_generate_images` 和 `md2wechat_create_draft`,其余六个本地/读取工具仍可用。`enableFallbackImageTool: false` 只关闭图片后备;微信写入工具开启时,草稿创建仍可用。 ## 排障与卸载 - `md2wechat_doctor` 提示配置不完整:运行 `md2wechat config validate --json`,补齐账号或图片服务后重新检查。 - 预览被阻止:修正当前工作版本后重新预览,不要复用旧预览回执。 - 草稿提示账号不匹配:以目标命名账号重新开始或重新预览。草稿状态不明确时,先到微信后台确认,再由人工决定是否建立新版本。 - npm 命令找不到:按准确版本重新安装根包,确保 registry 有对应平台 optional package;这不依赖 npm 生命周期脚本。 卸载: ```bash dsh plugin --profile web remove @geekjourneyx/md2wechat ``` ## 明确不做什么 插件只创建草稿:the plugin stops at draft creation and never publishes。它不会发起微信公众号发布请求、定时发布,也不会修改原始 Markdown。