kim1232aa/dsh-mxpage

dsh-mxpage

DeepSeek Harness plugin: MxPage ecommerce product-image pipeline (analyze → plan → VPA → generate).

待分类deepseek-harnessdsh

dsh-mxpage

English | 简体中文

把 MxPage 的电商商品图工作台做成 DeepSeek Harness 原生插件,装进官方 web profile:

登记商品图 → 分析卖点 → 规划头图/详情 → Visual Prompt Agent → 生成 → 编辑 → 导出

这不是通用图库,也不是一层薄薄的提示词包装。社区插件如 dsh-imagegen 注册的是一次性 generate_image。本插件不注册。 工具名全部 mxpage_*,模型必须走 分析 → 规划 → VPA → 分镜生成,把一张商品图做成叙事完整的详情页套图,而不是互不相关的散图。

已对照 DSH 0.1.2-rc.1 host 包验证。必须装进官方 web profile(不要用 sdk-minimal)。

不是 DeepSeek 官方产品,与 DeepSeek AI 无隶属关系。MxPage 提示词/schema 仍为 MIT(灵矩绘境),见 NOTICE。


架构 —— "换芯留壳"

v0.1 手工重写了 MxPage 的流水线,丢掉了让它成为产品的部分。v0.2 反过来:上游内核被整体移植,DSH 适配层尽量薄,上游 UI 也在移植范围内。v0.3 把上游剩余的产品面(分析工作台、批量 SKU、用量监控、导出面板、整页翻译)全部补齐。

src/core/     上游 lib/ 的宿主无关移植   (永不 import @deepseek-ai/*)
   └── ports/   Repository · ProviderResolver · Logger · StorageDriver · TaskRunner
src/host/     五个端口实现(JSON 仓库、fs 存储、渠道、jobs 任务运行器)
src/shared/   host 与浏览器共享的路由路径
src/tools/    core 服务之上的薄 mxpage_* 包装
src/client/   浏览器面板

src/core/** 不允许 import @deepseek-ai/*、schemastery、Next.js、Prisma 或 React,也不允许碰 process.cwd() / process.env —— 由测试强制保证。

长任务走 ctx.jobs(@deepseek-ai/dsh-jobs-local),由 shell 掌管 job 身份、会话作用域、生命周期状态、完成通知和 owner 销毁取消。src/host/task-runner.ts 是没有 registry 的宿主上的兜底 —— 插件两种情况下都能启动,因为 jobs 是通过可选的 ctx.get('jobs') 访问器读取的。

为什么抽取这么便宜,有据可查:

事实证据
上游 lib/ 内零 next/* import唯一例外 provider-runtime.ts 引入 NextRequest 只为读两个 header
@prisma/client 出现 9 次两次纯类型;四次只用 Prisma 命名空间
1344 行的 OpenAI adapter 只有一处硬耦合import { inferCategory, logApiUsage } from "@/lib/monitor/api-usage"

完整接缝清单见 src/core/README.md。


配置 —— 渠道列表,不是环境变量

v0.1 要求 MXPAGE_IMAGE_API_KEY。v0.2 起改用渠道列表,可以配置多个端点并轮换:

设置 → 插件 → MxPage → 渠道,或在 cordis.patch.yml 中:

- insert:
    - id: mxpage
      name: dsh-mxpage
      config:
        channels:
          - id: xai
            label: xAI (Grok)
            baseUrl: https://api.example.com/v1
            apiKeyEnv: MXPAGE_XAI_KEY   # 推荐:让密钥不进文档
            models: [grok-imagine-image-2.0]
            textModel: grok-4
            imageModel: grok-imagine-image-2.0
        rotateChannelOnQuotaExhausted: true
字段含义
id / label轮换键与显示名
baseUrlOpenAI 兼容 base URL;缺 /v1 会自动重试
apiKey / apiKeyEnv明文密钥,或(推荐)环境变量名
models显式图像模型 id;留空则通过 GET /models 发现
textModel / imageModel该渠道上 分析+规划 / 生图 的首选模型
disabled跳过该渠道而不删除

出问题时先跑 mxpage_channels —— 它会报告当前激活渠道、模型目录、以及是否找到了具备图像能力的模型。

模型能力是从模型名推断的。 上游刻意不做真实端点探测,避免白白烧掉图像配额,所以"名字像图像模型"并不证明网关真能出图。一个宣称有某模型却供不了的网关,会在失败时被发现。


付费图像 API —— 先读

生成与编辑工具调用 OpenAI 兼容 Images API(/images/generations、/images/edits)。这是付费接口。每次 mxpage_generate_section、mxpage_generate_page、mxpage_edit_section 都消耗配额。随包 Skill 会提醒模型在整页 job 前先与你确认。

密钥从不出现在工具输出、日志或会话事件中 —— sk- 和 Bearer 令牌会被脱敏(src/util/redact.ts)。


安装

# 从本地检出
dsh plugin add link:/absolute/path/to/mxpage

# 或从构建好的 tarball
dsh plugin add ./dsh-mxpage-0.3.0.tgz

dsh plugin add 会把 bundle 登记进 profile 的 dsh.profile.bundles。然后配置一个渠道(见上),重启 profile 让新层生效。

Skill 目录

Skill 随包分发。把它们拷到 DSH 目录旁,才能被发现:

mkdir -p "${DSH_HOME:-$HOME/.dsh}/skills"
cp -R skills/mxpage-ecommerce-page skills/mxpage-xiaohongshu skills/mxpage-batch-sku \
      "${DSH_HOME:-$HOME/.dsh}/skills/"

对话示例

附上一张商品图,说:

根据这张商品图出一套淘宝详情页

期望:Agent 走 create → analyze → plan → generate,产出一套头图加详情分镜,每次都是新版本(从不覆盖),存到 $DSH_HOME/mxpage/projects/<projectId>/ 并作为附件返回。


面板 —— 八个界面

插件带一个浏览器半包(lib/client.js),挂载到 DSH 中栏的工作台,带侧栏开关。这才是上游 MxPage 真正赖以存在的东西:一个有状态的工作区,而不是提示词包装。

界面作用
分析项目元信息(名称 / 平台 / 风格、删除项目)、商品素材网格(上传、排序、设主图、删除)、结构化分析编辑器,一键分析 / 保存分析
规划输出配置(头图/详情数量、比例、图内语言)、analyze → plan、项目级视觉风格指南、分镜列表(逐镜生成 + 整页 job),以及把整页翻译成目标语言
编辑逐镜预览,标题/目标/文案/visualPrompt 行内编辑,生成 / 重绘 / 精修 / 翻译,版本列表与激活
导出一键导出 ZIP / JSON、导出说明、模型快照、当前可导出内容画廊
小红书四步连环画流程:规划 → 逐页确认 imagePrompt → 生图 → 编辑,逐页下载
批量 SKU每批最多 20 张商品图 —— 一 SKU 一项目,可选后台 analyze+plan,单 SKU 失败互相隔离
监控API 用量账本:调用/Token 总量、Top 模型 / 项目、额度状态分类、逐条删除 / 清空,另有任务历史与失败任务重试
渠道渠道诊断:激活渠道、模型目录、图像/视觉/文本计数、各渠道密钥在位情况、连接测试与模型发现(含角色推荐)、额度轮换说明

重新规划有显式确认保护,因为它会删除项目里所有分镜、版本和已生成图片。

构建格式说明。 DSH web shell 不以 ESM 加载客户端半包。它给每个 bundle 一个 window.__ModuleLoader__.load({ id, factory }) 门面,和一个解析 shell 实时模块表的 require。因此 tsdown 把浏览器半包产出为 CJS(lib/client.raw.cjs),再由 scripts/wrap-client.mjs 包进信封。test/client-bundle.test.ts 通过模拟门面加载构建产物并断言 apply + inject 返回 —— 这个测试存在是因为 ESM bundle 会静默地永远不 apply。

面板的数据 API 在 /api/dsh-mxpage/*(src/host/routes.ts),注册在宿主 webServer 上,并限定只接受 loopback 请求。


工具(仅 mxpage_*)

工具作用
mxpage_create_project用对话 attachment_ids 和/或 image_paths 从 1–10 张图创建项目
mxpage_add_asset追加图片;role: "main" 替换主参考图
mxpage_project_status只读:分析、分镜、版本、进行中的任务
mxpage_analyze_product视觉分析 → 类目、材质、卖点、建议规划
mxpage_plan_page分镜规划 + 项目级 visualStyleGuide。重新规划会删除现有分镜和图片
mxpage_generate_section生成一镜;未给 prompt_override 时先跑 VPA
mxpage_edit_sectionrepaint / enhance / translate;写新版本,从不覆盖
mxpage_generate_page整页后台 job;mode: "missing" 只补缺口
mxpage_job_status / mxpage_job_canceljob 控制;已完成的分镜保留在磁盘上
mxpage_export_pageZIP(00-头图/ + 01-详情页/ + export-manifest.json)或项目 JSON
mxpage_xiaohongshu_plan小红书第 1 步 —— 有完全本地化的中文兜底规划
mxpage_xiaohongshu_generate第 3 步 —— 一页一图,VPA 把关
mxpage_xiaohongshu_edit第 4 步 —— 就地编辑一页
mxpage_translate_page整页翻译后台 job —— 对每个已生成分镜做一次 translate 编辑
mxpage_update_project重命名项目或修改平台 / 风格
mxpage_delete_project删除项目及其工作区;必须 confirm: true
mxpage_set_main_asset按素材 id 或图片路径替换主参考图
mxpage_usage_stats用量账本摘要:调用、Token、额度事件、Top 模型 / 项目、近期错误
mxpage_channels渠道诊断

Skill

Skill何时用
mxpage-ecommerce-page淘宝 / 天猫 / 京东 / Shopee 头图 + 详情页
mxpage-xiaohongshu四步连环画流程
mxpage-batch-sku一 SKU 一项目;绝不混用参考图

与上游的差异,及移植中修掉的 bug

已修复(每处都在调用点有注释):

  1. Visual Prompt Agent 重试 bug。 上游 requestRaw 写的是 if (urls.length === 1 || options?.suppressUsageLog),把"跳过用量记录"和"跳过 base-URL 重试"混为一谈。VPA 是唯一传 suppressUsageLog: true 的调用方,于是它悄悄丢了 /v1-vs-根路径兜底,在需要带版本号 base URL 的网关上退化成模板提示词。
  2. 路径穿越。 上游 /api/files/[...path] 路由把 rootDir() 和未校验的相对路径直接 join。存储端口拒绝逃逸(normalizeRelPath),该路由整体移除。
  3. 跨平台路径。 上游存的是 path.join 的输出(Windows 上是反斜杠),而 URL 构造器用 split(path.sep) 转换回来。
  4. 生产环境无法取消。 上游 abort 注册表被 process.env.NODE_ENV !== "production" 守卫,生产构建取消不了。
  5. 删掉死值: ProjectStatus.COMPLETED 和 GenerationStatus.QUEUED 上游没有任何服务会写入。

刻意保留(标注出来,不悄悄改):

  • 额度用尽不轮换模型。 上游 shouldFallbackToNextImageModel 对 429 / quota / 403 / 401 返回 false,渠道耗尽即中止,而不是试下一个候选。通过 rotateChannelOnQuotaExhausted 配置项暴露。
  • editSectionImage 不可取消 —— 上游从未在这条路径上注册 abort controller。
  • archiver 被替换为零依赖 ZIP 写入器,顺带移除了上游的 process.cwd() 临时文件。

开发

npm install
npm run build     # tsdown → lib/index.js(存在 src/client 时还有 lib/client.js)
npm test          # node --experimental-strip-types --test
npx tsc --noEmit  # 期望 0 错误

值得了解的测试:

  • test/bundle.test.ts —— 包清单健全性,以及 src/core/** 的宿主无关不变量
  • test/core.test.ts —— ZIP 头/CRC 格式、仓库语义(终态粘性、系统项目隐藏、陈旧恢复)、存储路径围堵、任务取消
  • test/smoke.test.ts —— 加载构建产物 lib/index.js,对 mock Cordis context 跑真实 apply(),断言全部 20 个工具完成注册

许可

MIT。MxPage 提示词、schema 与流水线逻辑为 MIT(灵矩绘境)—— 见 NOTICE 与 LICENSE。

Topics: dsh-plugin · dsh · deepseek-harness · mxpage · ecommerce