@mindscraft/branch-video-agent-cli 0.4.0 → 0.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -31,7 +31,9 @@ branch-video-agent --version
31
31
  - `AIHUB_AGENT_TOKEN`
32
32
  - `BRANCH_VIDEO_AGENT_BASE_URL`
33
33
 
34
- AI Gateway 调用同样只传 `AIHUB_AGENT_TOKEN`;CLI 不读取、不传递 `AiGatewayKey` 或 AIHub `projectKey`,上游鉴权由服务端处理。
34
+ AI Gateway 调用同样只传 `AIHUB_AGENT_TOKEN`;CLI 不读取、不传递 `AiGatewayKey` 或 AIHub `projectKey`,上游鉴权由服务端处理。
35
+
36
+ AI Gateway 生产媒体验收使用 `ai-gateway media-understand --raw`。P0 模型固定为 `doubao-seed-2-0-mini-260215`,输入为带 SHA-256 的公共 HTTPS 图片/视频 URL、一个 candidate、可选 reference、prompt 与 criteria;输出为 `media_acceptance_review.v1`。该能力只判断可见画面,不声称分析视频音轨。`kimi-k3` 和 `MiniMax-M3` 在真实 payload Canary 通过前不可调用。
35
37
 
36
38
  最小调用示例:
37
39
 
@@ -42,55 +44,55 @@ AI Gateway 调用同样只传 `AIHUB_AGENT_TOKEN`;CLI 不读取、不传递 `A
42
44
  "page": 1,
43
45
  "limit": 20
44
46
  }
45
- '@ | npm exec --yes --package=@mindscraft/branch-video-agent-cli branch-video-agent -- project list
46
- ```
47
-
48
- ## BV V3 全分支可播放性测试
49
-
50
- `playtest run` 从 `0.4.0` 起提供,使用 Playwright Chromium 驱动真实播放器。命令只读草稿或已发布版本,不会保存测试副本或自动发布;运行前仍应先通过 V3 静态 self-test。
51
-
52
- ```powershell
53
- @'
54
- {
55
- "source": { "kind": "draft", "projectId": "project-id" },
56
- "contractPath": "project.playtest.json",
57
- "reportDir": "playtest-results",
58
- "concurrency": 2,
59
- "limits": {
60
- "scenarioTimeoutMs": 60000,
61
- "maxStepsPerScenario": 100,
62
- "maxScenarios": 500,
63
- "maxNodeVisits": 3
64
- }
65
- }
66
- '@ | branch-video-agent playtest run
67
- ```
68
-
69
- 发布版把 `source` 改为 `{ "kind": "published", "projectId": "...", "version": 3, "playUrl": "<发布接口返回值>" }`。CLI 会先读回精确版本并比较规范化内容摘要,再直接使用 `playUrl`;漂移返回 `PUBLISHED_SCRIPT_MISMATCH`。该 SHA-256 摘要只由 sidecar 绑定、发布读回比较和报告追踪消费,不是身份认证、数字签名或 HMAC。
70
-
71
- sidecar 使用 `branch-video-playtest/1`,Web 结果必须提供 iframe 内的真实操作,不接受测试侧消息注入:
72
-
73
- ```json
74
- {
75
- "schemaVersion": "branch-video-playtest/1",
76
- "scriptFingerprint": "sha256:...",
77
- "webResults": [{
78
- "nodeId": "web_quiz",
79
- "routeValue": "success",
80
- "rawMessage": { "eventName": "ActivityData", "value": "1" },
81
- "steps": [{
82
- "action": "click",
83
- "locator": { "by": "role", "role": "button", "name": "正确答案" }
84
- }]
85
- }]
86
- }
87
- ```
88
-
89
- 支持 `click`、`fill`、`selectOption`、`check`、`press`、`dragTo`、`setInputFiles` 和 `waitFor`。只要输入中有合法 `reportDir`,静态门禁、契约、版本漂移和浏览器启动等前置失败也会输出 `branch-video-playtest-report.json`、`junit.xml`;失败场景另存截图、trace、视频和浏览器日志。若 Chromium 缺失,执行 `npx playwright install chromium`。
90
-
91
- CI 顺序应固定为:V3 静态 self-test → 草稿 `playtest run` → 外部发布步骤 → `version get` 读回 → 发布版 `playtest run`。`playtest run` 自身始终只读,不承担发布。
92
-
93
- AIHub 导入公共库示例:
47
+ '@ | npm exec --yes --package=@mindscraft/branch-video-agent-cli branch-video-agent -- project list
48
+ ```
49
+
50
+ ## BV V3 全分支可播放性测试
51
+
52
+ `playtest run` 从 `0.4.0` 起提供,使用 Playwright Chromium 驱动真实播放器。命令只读草稿或已发布版本,不会保存测试副本或自动发布;运行前仍应先通过 V3 静态 self-test。
53
+
54
+ ```powershell
55
+ @'
56
+ {
57
+ "source": { "kind": "draft", "projectId": "project-id" },
58
+ "contractPath": "project.playtest.json",
59
+ "reportDir": "playtest-results",
60
+ "concurrency": 2,
61
+ "limits": {
62
+ "scenarioTimeoutMs": 60000,
63
+ "maxStepsPerScenario": 100,
64
+ "maxScenarios": 500,
65
+ "maxNodeVisits": 3
66
+ }
67
+ }
68
+ '@ | branch-video-agent playtest run
69
+ ```
70
+
71
+ 发布版把 `source` 改为 `{ "kind": "published", "projectId": "...", "version": 3, "playUrl": "<发布接口返回值>" }`。CLI 会先读回精确版本并比较规范化内容摘要,再直接使用 `playUrl`;漂移返回 `PUBLISHED_SCRIPT_MISMATCH`。该 SHA-256 摘要只由 sidecar 绑定、发布读回比较和报告追踪消费,不是身份认证、数字签名或 HMAC。
72
+
73
+ sidecar 使用 `branch-video-playtest/1`,Web 结果必须提供 iframe 内的真实操作,不接受测试侧消息注入:
74
+
75
+ ```json
76
+ {
77
+ "schemaVersion": "branch-video-playtest/1",
78
+ "scriptFingerprint": "sha256:...",
79
+ "webResults": [{
80
+ "nodeId": "web_quiz",
81
+ "routeValue": "success",
82
+ "rawMessage": { "eventName": "ActivityData", "value": "1" },
83
+ "steps": [{
84
+ "action": "click",
85
+ "locator": { "by": "role", "role": "button", "name": "正确答案" }
86
+ }]
87
+ }]
88
+ }
89
+ ```
90
+
91
+ 支持 `click`、`fill`、`selectOption`、`check`、`press`、`dragTo`、`setInputFiles` 和 `waitFor`。只要输入中有合法 `reportDir`,静态门禁、契约、版本漂移和浏览器启动等前置失败也会输出 `branch-video-playtest-report.json`、`junit.xml`;失败场景另存截图、trace、视频和浏览器日志。若 Chromium 缺失,执行 `npx playwright install chromium`。
92
+
93
+ CI 顺序应固定为:V3 静态 self-test → 草稿 `playtest run` → 外部发布步骤 → `version get` 读回 → 发布版 `playtest run`。`playtest run` 自身始终只读,不承担发布。
94
+
95
+ AIHub 导入公共库示例:
94
96
 
95
97
  ```powershell
96
98
  @'
@@ -114,7 +116,7 @@ AIHub 导入公共库示例:
114
116
  "name": "判断题-增强版",
115
117
  "defaultThemeId": "cat",
116
118
  "urlsByTheme": {
117
- "cat": "https://aic-view.sdp.101.com/view/judge-base-v2"
119
+ "cat": "https://aic-view.sdp.cn.ndhy.com/view/judge-base-v2"
118
120
  },
119
121
  "configTemplate": {
120
122
  "waitForPageReady": true
@@ -187,17 +189,30 @@ Banana Pro 图片编辑继续使用 `ai-gateway image-edit`,请求体为 JSON
187
189
 
188
190
  AI Gateway 视频生成并等待示例:
189
191
 
192
+ Seedance 2.5 必须使用完整模型名 `doubao-seedance-2-5-260628`。使用 `--wait --raw` 时,CLI 会始终轮询创建响应中的 task ID,并原样保留最终 `video_url` 与 `last_frame_url`。
193
+
190
194
  ```powershell
191
195
  @'
192
196
  {
193
- "model": "doubao-seedance-2-0-260128",
194
- "input": {
195
- "prompt": "镜头推进到实验台,卡通猫老师点亮一个小灯泡"
196
- }
197
+ "model": "doubao-seedance-2-5-260628",
198
+ "content": [
199
+ {
200
+ "type": "text",
201
+ "text": "镜头推进到实验台,卡通猫老师点亮一个小灯泡"
202
+ }
203
+ ],
204
+ "omni_reference_task_type": "auto",
205
+ "duration": 4,
206
+ "resolution": "720p",
207
+ "output_format": "mp4",
208
+ "return_last_frame": true,
209
+ "generate_audio": false
197
210
  }
198
211
  '@ | npm exec --yes --package=@mindscraft/branch-video-agent-cli branch-video-agent -- ai-gateway video-create -- --wait --raw
199
212
  ```
200
213
 
214
+ Seedance 2.5 支持 480p、720p、1080p 和 4–30 秒生成;在播放器兼容性完成验证前,推荐 480p/720p + MP4。完整的多图片/视频/音频参考数量限制,以及 `reference`、`edit`、`extend` 的差异,见仓库 Skill 的 `references/ai-gateway-parameters.md`。
215
+
201
216
  AI Gateway Seed Audio 音频生成并等待示例:
202
217
 
203
218
  ```powershell
@@ -8,6 +8,21 @@ function ensureObject(value, fieldName) {
8
8
  }
9
9
  return value;
10
10
  }
11
+ function validateMediaUnderstandingPayload(payload) {
12
+ for (const field of ['production_task_id', 'model', 'profile', 'prompt']) {
13
+ getRequiredString(payload, field);
14
+ }
15
+ if (!Array.isArray(payload.media) || payload.media.length === 0) {
16
+ throw new CliCommandError('media must be a non-empty JSON array', 'VALIDATION_ERROR');
17
+ }
18
+ if (!Array.isArray(payload.criteria) || payload.criteria.length === 0) {
19
+ throw new CliCommandError('criteria must be a non-empty JSON array', 'VALIDATION_ERROR');
20
+ }
21
+ const candidates = payload.media.filter((item) => isJsonRecord(item) && item.role === 'candidate');
22
+ if (candidates.length !== 1) {
23
+ throw new CliCommandError('media must contain exactly one candidate', 'VALIDATION_ERROR');
24
+ }
25
+ }
11
26
  function normalizeOperation(value) {
12
27
  return value.trim().replace(/^\/+/, '');
13
28
  }
@@ -174,6 +189,14 @@ export const aiGatewayCommands = {
174
189
  });
175
190
  return { data: result.data, requestId: result.requestId };
176
191
  },
192
+ 'media-understand': async ({ client, payload }) => {
193
+ validateMediaUnderstandingPayload(payload);
194
+ const result = await client.request('/api/agent/ai-gateway/media/understand', {
195
+ method: 'POST',
196
+ body: payload,
197
+ });
198
+ return { data: result.data, requestId: result.requestId };
199
+ },
177
200
  'image-generate': async ({ client, payload }) => {
178
201
  const result = await client.request('/api/agent/ai-gateway/images/generations', {
179
202
  method: 'POST',
package/dist/lib/flags.js CHANGED
@@ -100,7 +100,7 @@ export function getCliHelpText() {
100
100
  ' agent-production create | status | cancel | finalize | autopilot-binding | events | metrics | multica-comment-payload | node claim|inputs|complete|submit|block|fail|retry|expire | blocker resolve | artifact submit|list | asset-job poll|retry|revise|attach-artifact|fail | gate evaluate|results',
101
101
  ' aihub-production schema | start | status | retry',
102
102
  ' character search | create | get',
103
- ' ai-gateway capabilities | request | image-generate | image-edit | video-create | video-get | seed-audio-create | seed-audio-get | music-submit | music-get | tts-create | tts-get',
103
+ ' ai-gateway capabilities | request | media-understand | image-generate | image-edit | video-create | video-get | seed-audio-create | seed-audio-get | music-submit | music-get | tts-create | tts-get',
104
104
  ' playtest run',
105
105
  '',
106
106
  'Config precedence:',
@@ -86,6 +86,22 @@ async function waitForPlayerFrame(page, playerUrl, timeout) {
86
86
  }
87
87
  throw new PlaytestError('PLAYER_LOAD_FAILED', `Player iframe did not load ${playerUrl}`);
88
88
  }
89
+ async function assertPlayerProtocol(frame, timeout) {
90
+ const root = frame.locator('[data-bv-playtest-protocol]').first();
91
+ try {
92
+ await root.waitFor({ state: 'attached', timeout: Math.min(timeout, 5000) });
93
+ }
94
+ catch {
95
+ throw new PlaytestError('PLAYER_PLAYTEST_PROTOCOL_UNSUPPORTED', 'Player does not expose the BV playtest protocol');
96
+ }
97
+ const protocol = await root.getAttribute('data-bv-playtest-protocol');
98
+ if (protocol !== '1') {
99
+ throw new PlaytestError('PLAYER_PLAYTEST_PROTOCOL_UNSUPPORTED', `Unsupported BV playtest protocol: ${protocol || 'missing'}`, { protocol });
100
+ }
101
+ if (await root.getAttribute('data-bv-player-state') === 'error') {
102
+ throw new PlaytestError('PLAYER_INIT_FAILED', 'Player entered the error state before playback started');
103
+ }
104
+ }
89
105
  async function waitForNode(frame, nodeId, timeout) {
90
106
  try {
91
107
  await frame.waitForFunction((expectedNodeId) => (globalThis.document.querySelector('[data-bv-node-id]')?.getAttribute('data-bv-node-id') === expectedNodeId), nodeId, { timeout });
@@ -472,6 +488,7 @@ async function runScenario(browser, scenario, options) {
472
488
  await page.setContent('<!doctype html><html><body style="margin:0"><iframe title="BV playtest player" style="border:0;width:1280px;height:720px"></iframe></body></html>');
473
489
  await page.locator('iframe[title="BV playtest player"]').evaluate((element, url) => { element.src = url; }, options.playerUrl);
474
490
  const playerFrame = await waitForPlayerFrame(page, options.playerUrl, options.limits.scenarioTimeoutMs);
491
+ await assertPlayerProtocol(playerFrame, options.limits.scenarioTimeoutMs);
475
492
  const entryNodeId = String(options.script.graph?.entryNodeId || '');
476
493
  await startPlayback(playerFrame, entryNodeId, String(getNode(options.script, entryNodeId).type || ''), options.limits.scenarioTimeoutMs);
477
494
  playerReady = true;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mindscraft/branch-video-agent-cli",
3
- "version": "0.4.0",
3
+ "version": "0.4.2",
4
4
  "description": "Published CLI for branch-video and AIHub agent APIs.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -15,12 +15,12 @@
15
15
  "dist",
16
16
  "README.md"
17
17
  ],
18
- "engines": {
19
- "node": ">=18"
20
- },
21
- "dependencies": {
22
- "playwright": "^1.57.0"
23
- },
18
+ "engines": {
19
+ "node": ">=18"
20
+ },
21
+ "dependencies": {
22
+ "playwright": "^1.57.0"
23
+ },
24
24
  "publishConfig": {
25
25
  "access": "public",
26
26
  "registry": "https://registry.npmjs.org/"