Dingpenghui-good/dsh-tool-agnes

dsh-tool-agnes

Agnes AI media generation plugins for DeepSeek Harness

未分類dsh

dsh-tool-agnes

Agnes AI 媒体生成插件集,为 DeepSeek Harness (DSH) 提供文生图 / 文生视频 / 图生视频三种能力。

当前版本:1.6.0 —— 适配 DSH 0.2.0-rc.2(SDK 0.2.0-rc.2),新增官方"一个 bundle + 三个组件"形态(@dingpenghui/agnes);针对 Agnes API 的真实行为做过调用验证,并完成三轮优化;默认模型为两个最新的免费模型。

插件包名工具
dsh-tool-agnes-image@dingpenghui/agnes-imagegenerate_image
dsh-tool-agnes-video@dingpenghui/agnes-videogenerate_video、get_video_task
dsh-tool-agnes-img2vid@dingpenghui/agnes-img2vidgenerate_img2vid

三个包共用 _core/ 中的协议实现(凭据、HTTP、错误分类、图片、视频状态机、后台任务),构建时内联进各自的 lib/,因此运行时不引入第四个包,也不存在协议逻辑的多份副本。


1. 1.6.0 / 1.5.1 / 1.5.0 / 1.4.0 / 1.3.0 / 1.2.0 做了什么

1.6.0:SDK 升到 0.2.0-rc.2 + 官方 bundle 形态

  • 所有 @deepseek-ai/* 依赖从 ^0.1.7-rc.2 升到 ^0.2.0-rc.2(与 DSH 桌面端 0.2.0-rc.2 的 next 线对齐;API 契约与 0.1.7 一致,typecheck / 构建 / 全部测试通过)。
  • 新增 bundle 壳包 @dingpenghui/agnes(dsh-tool-agnes-profile/),对齐官方 dsh-base / dsh-experimental-agent-team-profile 的"一个 bundle + N 组件"模式:lib/index.js 空壳 + cordis.patch.yml 一次性 insert 3 个组件行,UI 里一个开关同时启用三套工具。
  • 4 个包纳入同一 pnpm-workspace.yaml,新增 .gitignore 与 _verify/bundle-shell-check.mjs。
  • 发布到 npm 的包名:@dingpenghui/agnes(bundle 壳)、@dingpenghui/agnes-image、@dingpenghui/agnes-video、@dingpenghui/agnes-img2vid。

1.5.1:适配 DSH 0.2.0(SDK 0.1.7)

DSH 主线从 0.1.5-rc.2 推进到 0.2.0-rc.2(SDK 包 0.1.7-rc.2),插件随同升级:

变更说明
dsh-jobs 服务定义重写新版 producer 契约改为同步 run(job) 返回 { cancel, done };owner 由 Agent 改为裸 SessionId;终值经 JobOutcome.result 传递,读侧从 { snapshot, text } 改为 JobRead { chunks, result, job }。_core/video-job.ts 已按新契约重写,get_video_task 读侧行为不变。
消息源声明dsh-llm 移除了共享的 kind: 'plugin' 消息源,生产者需在自己的模块里合并 MessageSourceMap。三个插件各自声明 kind: 'tool-agnes-*',deferContext 语义不变。
依赖所有 @deepseek-ai/* 依赖从 0.1.5-rc.1 升到 ^0.1.7-rc.2,schemastery 升到 ^3.18.4。

行为、默认模型、工具参数均与 1.5.0 保持一致。

1.5.0:默认切到最新一代免费模型

默认模型说明
agnes-image-2.5-flash最新一代图像模型,当前免费
agnes-video-2.5-flash最新一代视频模型,实测现价 $0/秒(原 $0.025/秒)

切换过程中实测确认了三件此前只是猜测的事:

  1. 2.5 系列的图生视频形状与 v2.0 完全不同:它要求 mode: "reference" 并携带 images 数组;传 mode: "image" 或裸 image 字段会被 400 invalid mode 拒绝。请求构造已按族分开。
  2. 2.5 系列完成时 internal_status 仍停留在 pending、internal_progress 仍停留在 0,只有 status / completed_at / progress 会推进。状态机本就优先判定 completed_at,因此无需改动即兼容。
  3. agnes-video-2.5-flash 的 size 仅接受 720P(Flash 专属限制),这正好是默认值。

顺带实测:2.5-flash 渲染一段 5 秒 720P 视频耗时 191 秒,比 v2.0 的 8 秒 1080P(272 秒)快。

免费额度仍有速率限制:短时间连续创建任务会返回 429,等待窗口重置即可,并非模型不可用。

1.4.0:GUI 里粘贴的图片可以直接用

模型能看到用户粘贴的图片,却拿不到它的 attachmentId(那是 host 元数据),所以无法指名这张图。现在插件自己解决:

  • 订阅 session/event,记住每条用户消息带来的图片引用(按会话分桶,最近 8 张 / 32 个会话)
  • generate_img2vid 的 image 参数变为可选:省略(或传 latest/recent/last)时,自动使用当前会话最近一张图
  • 解析出的引用会回填进结果(attachment:<id>),模型由此第一次知道这张图的 id

于是"粘贴图片 → 说把它动起来"直接可用,模型不需要 id:

用户:[粘贴一张图] 把它变成视频,镜头慢慢推近
AI  :generate_img2vid { prompt: "slow push in" }   ← 不带 image
      → 插件自动取到刚粘贴的那张图 → 真实任务创建成功

readImage 走的是附件服务的正式接口(拿到的是完整 ref,字节由服务校验后返回),不依赖存储布局;只有模型显式传 attachment:<id> 时才需要推导路径。

1.3.0:解除「图片必须公网可访问」的限制

实测发现 POST /v1/videos 的 image 字段接受 data: URL,与公网 URL 等价。因此 generate_img2vid 的图片来源扩展为四类,本地图片会被自动内联进请求:

来源写法说明
公网 URLhttps://…原样透传
DSH 附件attachment:<id>generate_image 会返回这个引用;直接复制即可
本地文件E:\path\to\img.jpg 或 @ 引用读文件 → 转 data URL
内联数据data:image/…;base64,…原样透传

配套改动:generate_image 的摘要里现在输出可复制的 attachment:<id>;img2vid 在创建 provider 任务之前先解析图片,读不到就立即失败,不会产生一个已计费的空任务。

1.2.0:可靠性与可维护性

方向改动效果
视频异步化generate_video / generate_img2vid 默认不再阻塞,改为注册 DSH 后台任务并立即返回单次调用从实测 272 秒降到约 1 秒;不再占用 agent 回合
任务查询新增 get_video_task 工具模型可在后续回合取回结构化结果(URL + 本地副本),幂等可重复读
产物落盘视频完成后自动下载进 DSH 附件存储不再依赖第三方 CDN 链接的隐含有效期
错误可行动化新增错误分类层,每种失败附带 Next step: 建议429 明确告知「不要立即重试」;400 ... is not supported 直接指出字段已不被接受
工具卡片三个工具都声明了 presentCall / presentResult待执行卡片显示模型与关键参数,而不是裸 JSON
消除重复抽出 _core/,video 与 img2vid 不再各自维护一份 12 KB 的客户端协议修正只需改一处
工程化零依赖单元测试 + 运行时验收 + 能力探测脚本回归有据可依

2. 环境要求

项要求
DSH0.2.0-rc.2(依赖声明 ^0.2.0-rc.2,运行期解析到 profile 实际安装的版本)
Node.js>= 22(开发机 24.x)
凭据AGNES_AI_API_KEY(旧名 AGNES_API_KEY 仍兼容)

凭据写入 $DSH_HOME/.credentials.yaml:

refs:
  AGNES_AI_API_KEY: sk-xxxxxxxx

或使用同名环境变量。


3. 接入 DSH

方式一:Bundle 整体接入(推荐,对齐官方"一个插件 + N 组件"模式)

仓库里有一个 bundle 壳包 @dingpenghui/agnes(dsh-tool-agnes-profile/), 它本身不导出运行时代码,只通过 cordis.patch.yml 把 3 个组件包一次性 insert 进 profile——UI 里"一个开关"即可同时启用三套工具,和官方 dsh-base、dsh-experimental-agent-team-profile 是同一种形态。

$DSH_HOME/profiles/web/package.json:

{
  "dependencies": {
    "@dingpenghui/agnes": "link:E:/dsh-workspace/dsh-tool-agnes/dsh-tool-agnes-profile"
  }
}
cd $env:DSH_HOME\profiles\web
pnpm install            # 建立 link

重启 DSH 后,"插件列表"里会出现一条 @dingpenghui/agnes,下面挂 3 个组件 (generate_image / generate_video+get_video_task / generate_img2vid), 整体勾选或单独关闭某个组件行即可。

方式二:组件分别接入(需要只装其中一部分工具)

{
  "dependencies": {
    "@dingpenghui/agnes-image": "link:E:/dsh-workspace/dsh-tool-agnes/dsh-tool-agnes-image",
    "@dingpenghui/agnes-video": "link:E:/dsh-workspace/dsh-tool-agnes/dsh-tool-agnes-video",
    "@dingpenghui/agnes-img2vid": "link:E:/dsh-workspace/dsh-tool-agnes/dsh-tool-agnes-img2vid"
  }
}

$DSH_HOME/profiles/web/cordis.patch.yml(组件各自的 dsh.bundle.patch 已带默认 config,profile 里只需按需覆写要改的行;patch 替换整行 config, 覆写时要重述全部保留的键):

- insert:
    - id: tool-agnes-image
      name: '@dingpenghui/agnes-image'
      config:
        model: agnes-image-2.5-flash
        defaultSize: 1K
        defaultRatio: 1:1
        persistAttachment: true
        ferryContext: true
        timeoutMs: 240000
    - id: tool-agnes-video
      name: '@dingpenghui/agnes-video'
      config:
        model: agnes-video-2.5-flash
        pollIntervalMs: 5000
        timeoutMs: 900000
        maxConsecutiveFailures: 4
        ferryContext: true
        awaitCompletion: false     # 后台任务模式(推荐)
        persistVideo: true
    - id: tool-agnes-img2vid
      name: '@dingpenghui/agnes-img2vid'
      config:
        model: agnes-video-2.5-flash
        pollIntervalMs: 5000
        timeoutMs: 900000
        maxConsecutiveFailures: 4
        ferryContext: true
        awaitCompletion: false
        persistVideo: true
        maxInlineImageBytes: 8388608   # 本地图片内联上限(8 MB)

然后:

cd $env:DSH_HOME\profiles\web
pnpm install            # 建立 link
cd E:\deepseek-harness
pnpm dsh web            # 重启后生效

必须重启:patchReload: live 只对已挂载行的 config 变更做热重载;新增插件行需要重启进程才会装载。


4. 工具参考

generate_image — 文生图

参数类型必填默认说明
promptstring✅-图像描述;英文、具体(主体/构图/光线/风格)效果最好
sizestring❌1K1K / 2K / 3K / 4K
ratiostring❌1:11:1 16:9 9:16 4:3 3:4 3:2 2:3 21:9

返回 url + attachment,并在对话中内联渲染图片。产物可直接作为 generate_img2vid 的输入来源(需为公网 URL)。

generate_video — 文生视频

参数类型默认适用模型
promptstring-全部(必填)
modelstringagnes-video-2.5-flash全部
durationinteger8全部(秒)
width / heightinteger1920 / 1080仅 V2.0
frameRateinteger24仅 V2.0
sizestring720P仅 2.5 系列
aspectRatiostring16:9仅 2.5 系列
seed / negativePrompt--全部

默认非阻塞:立即返回 taskId 与 jobId,渲染在后台进行。

get_video_task — 读取后台任务

参数类型必填
jobIdstring✅

读取是幂等的:任务未结束返回 processing,结束后返回 completed + videoUrl + 本地 attachment。

generate_img2vid — 图生视频

参数类型必填说明
imagestring❌省略即用当前会话最近一张图(用户刚粘贴/上传的那张)。也可显式传:公网 http(s):// URL、attachment:<id>、本地文件路径、data: URL。本地/附件/会话来源都会自动内联进请求
promptstring❌运动描述
其余-❌同 generate_video

返回里带 imageResolution(remote-url / inline),说明该图片是 provider 自己去取还是被内联进请求;image 字段回填实际使用的引用,便于后续再次使用。

两个视频工具职责互斥:纯文本驱动用 generate_video,动画化已有图片用 generate_img2vid。


5. 实测 API 事实(2026-09 线上)

代码按这些实测结论实现,而非按文档推断:

事实影响
/v1/images/generations 拒绝 stream、format旧版硬编码 stream:false,必然 400
该端点拒绝 images(图生图)与 n != 1图生图/图像编辑在当前网关不可用,插件不提供该工具
图片响应只有 data[].url / data[].b64_json,没有 width/height/size/ratio摘要不能依赖这些字段
视频轮询早期没有 status,只有 internal_status状态需多字段联合判定
视频完成时 URL 在顶层 url,不是 metadata.url旧版永远取不到视频地址
8n+1 帧数按最近值取整(8s@24fps → 193 帧),上限 441向下取整会得到偏短的视频
视频推理实测 272 秒(193 帧 @1080p)这是异步化的直接依据
POST /v1/videos 带 image 字段有效(mode=ti2vid)generate_img2vid 可用
POST /v1/videos 的 image 接受 data: URL,与公网 URL 等价本地图片/DSH 附件可直接内联,无需图床
/v1/files 上传端点不存在(被路由到通配 chat 路径)只能走 URL 或 data URL,不能上传换 file id
请求 1920x1080 被吸附为 1920x1088正常行为,返回值带 sizeAdjustment 说明
agnes-video-2.5-flash 现价 $0/秒2.5 代已成为免费档,默认视频模型切到它
2.5 系列的图生视频是 mode: "reference" + images: [...]传 mode: "image" 或裸 image 字段会 400 invalid mode
2.5 系列完成时 internal_status 停在 pending、internal_progress 停在 0状态判定必须优先看 completed_at(已如此实现)
免费 Key 有速率限制短时间连续创建任务会 429,需等窗口重置,不是模型不可用
图片接口当前免费2.5 视频现价 $0/秒

6. 验证

# 先构建
cd E:\dsh-workspace\dsh-tool-agnes\dsh-tool-agnes-image
pnpm install && pnpm build      # 三个包各执行一次

# 单元测试(零依赖)
node --test E:\dsh-workspace\dsh-tool-agnes\_verify\core.test.mjs

# 运行时验收:真实生图一次,并校验输出 schema
node E:\dsh-workspace\dsh-tool-agnes\_verify\runtime-acceptance.mjs

# 会话图片链路:真实创建一次视频任务
node E:\dsh-workspace\dsh-tool-agnes\_verify\session-image-check.mjs

# 图片来源解析:URL / 附件 / 本地路径
node E:\dsh-workspace\dsh-tool-agnes\_verify\image-source-check.mjs

脚本从任意目录可运行:它们按绝对路径加载构建产物,并从包自身的 node_modules 解析依赖。

构建与类型检查:

cd E:\dsh-workspace\dsh-tool-agnes\dsh-tool-agnes-image
pnpm install
pnpm build                              # -> lib/
npx tsc -p tsconfig.json --noEmit

详见 _verify/README.md。


7. 目录结构

dsh-tool-agnes/
├── _core/                       # 三个包共享的协议实现(构建时内联)
│   ├── credential.ts            # AGNES_AI_API_KEY / AGNES_API_KEY 解析
│   ├── errors.ts                # 错误分类 + 可行动建议
│   ├── http.ts                  # 统一请求、超时、下载、可取消 sleep
│   ├── image.ts                 # 图片端点客户端
│   ├── image-source.ts          # 图片来源解析:URL / 附件 / 本地路径 / data URL
│   ├── media.ts                 # 魔数探测、data URL 编码、MP4 识别、字节格式化
│   ├── recent-images.ts         # 会话图片索引(用户粘贴/上传的图,按会话分桶)
│   ├── types.ts                 # 线上报文类型
│   ├── video.ts                 # 视频任务创建 + 轮询状态机
│   └── video-job.ts             # DSH 后台任务(异步渲染 + 落盘 + 读取)
├── dsh-tool-agnes-image/        # 组件1:文生图(src/index.ts + cordis.yml + lib/)
├── dsh-tool-agnes-video/        # 组件2:文生视频 + 任务查询
├── dsh-tool-agnes-img2vid/      # 组件3:图生视频
├── dsh-tool-agnes-profile/      # Bundle 壳:官方"1 插件 + 3 组件"模式,组合上面 3 个组件
│   ├── package.json             #   dsh.bundle.patch -> cordis.patch.yml;依赖 3 组件
│   ├── cordis.patch.yml         #   insert 3 行(tool-agnes-image / -video / -img2vid)
│   └── lib/index.js             #   空壳 export {}
├── pnpm-workspace.yaml          # 4 个包纳入同一 workspace(bundle 依赖组件走 link)
├── _verify/                     # 单元测试、运行时验收、能力探测
├── README.md
└── OPTIMIZATION.md              # 优化方案与实施状态

8. 已知限制

  1. 图生图 / 图像编辑不可用:网关的文本图像队列实测拒绝 images 与 image 形状,插件不提供该能力。
  2. 免费额度有速率限制:短时间连续创建任务会返回 429 rate_limit_exceeded,等窗口重置即可恢复,并非模型不可用。
  3. agnes-video-2.5-flash 的 size 仅支持 720P:这是 Flash 的专属限制,其它档位会被 400 拒绝。
  4. 后台任务依赖 base bundle 的 dsh-jobs-local:缺失时会退化为「只报 taskId、不自动跟踪」,工具仍可用。
  5. 内联图片有体积上限:默认 8 MB(maxInlineImageBytes)。base64 会膨胀约 33%,超过上限的图片请先压缩或改用公网 URL。
  6. 会话图片窗口只覆盖本次进程内到达的图片:DSH 重启后,重启之前粘贴的图片不再被索引(重启后新粘贴的图正常)。这是刻意的——该功能回答的是"把刚给我的这张图动起来"。
  7. 视频 URL 有效期未公开:已通过落盘缓解,但落盘可被 persistVideo: false 关闭。

License

MIT