@mindscraft/branch-video-agent-cli 0.5.0 → 0.5.1

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
@@ -252,61 +252,61 @@ AI Gateway Seed Audio 音频生成并等待示例:
252
252
  '@ | npm exec --yes --package=@mindscraft/branch-video-agent-cli branch-video-agent -- ai-gateway seed-audio-create -- --wait --raw
253
253
  ```
254
254
 
255
- `tts-create` / `tts-get` 是 Seed Audio 的历史兼容别名;新脚本优先使用 `seed-audio-create` / `seed-audio-get`。
256
-
257
- ## RPG2 生产工作台
258
-
259
- 工作台 CLI 只提交调用方显式登记的项目、产物和归档清单;它不会扫描 RPG 阶段目录,也不会根据文件名推断版本关系。认证仍使用 `AIHUB_AGENT_TOKEN` 与 `BRANCH_VIDEO_AGENT_BASE_URL`,不要在 JSON、命令行或日志中保存 token。
260
-
261
- 项目、生产记录和外部 CDN 产物可使用 JSON 文件提交:
262
-
263
- ```powershell
264
- branch-video-agent workbench project create --file .\project.json --raw
265
- branch-video-agent workbench record put --project wb_project_id --file .\record.json --raw
266
- branch-video-agent workbench submit --file .\artifact-external.json --raw
267
- branch-video-agent workbench annotation put --project wb_project_id --file .\annotation.json --raw
268
- ```
269
-
270
- 同一产物用稳定的 `artifactKey` 和由流程侧持久维护的递增 `sourceRevision`。`idempotencyKey` 由流程侧保存并在重试时复用。已有持久媒体使用 `content.type: "external"`;本地文档、脱敏 session 或其他需要长期保存的文件使用 `content.type: "local"` 与 `sourcePath`。CLI 会先计算 SHA-256、声明 blob,再以原始二进制流上传;服务端只收到 blob 描述,绝不会收到本地路径。单文件上限为 64 MiB。
271
-
272
- ```json
273
- {
274
- "schemaVersion": "workbench.artifact/1",
275
- "projectId": "wb_project_id",
276
- "artifactKey": "document:director-program",
277
- "sourceRevision": 2,
278
- "idempotencyKey": "persisted-event-uuid",
279
- "kind": "markdown",
280
- "stageKey": "04",
281
- "title": "导演稿",
282
- "content": {
283
- "type": "local",
284
- "sourcePath": "C:/production/canonical/director.md",
285
- "mime": "text/markdown"
286
- },
287
- "source": {
288
- "productionRecordId": "record_id",
289
- "archiveGeneration": 0,
290
- "sourceSchema": "director-program/4"
291
- }
292
- }
293
- ```
294
-
295
- 上传响应在网络中丢失时,CLI 会先查询同一个已声明 blob;ready 状态不会重传,也不会重新登记业务版本。失败交给流程侧持久待传队列用相同事件重试。
296
-
297
- `sync` 只读取 `--manifest` 中显式的 `items`。每个 item 为 `type: "artifact"`(默认)或 `type: "annotation"`,可直接携带提交字段或放进 `submission`;不会递归任何工作目录。
298
-
299
- ```powershell
300
- branch-video-agent workbench sync --manifest .\.workbench\pending-items.json --raw
301
- branch-video-agent workbench archive prepare --manifest .\.workbench\archive-wrapper.json --raw
302
- branch-video-agent workbench archive finalize --project wb_project_id --record record_id --revision 1 --manifest-hash <sha256> --raw
303
- branch-video-agent workbench archive status --project wb_project_id --record record_id --raw
304
- branch-video-agent workbench archive download --project wb_project_id --record record_id --revision 1 --file .\entry.json --output .\session.jsonl.zst --raw
305
- ```
306
-
307
- `archive prepare` 的文件是调用方维护的 wrapper:`{ manifest, manifestHash, expectedPreviousRevision }`;CLI 原样提交规范化清单和 hash。`archive finalize` 只校验已经提交的清单,不补扫文件。下载的 `entry.json` 至少包含 `{ "entryId": "..." }`;受权限保护的字节写入 `--output`,stdout 仍只输出 JSON 回执。
308
-
309
- `record put` 的路径参数是稳定的流程 `recordKey`,返回对象的 `id` 才是后续 `end-intent`、`reopen` 和所有 `archive` 命令使用的 `productionRecordId`(也可传给 `--record`)。不要把 `recordKey` 当成归档路由 ID。
255
+ `tts-create` / `tts-get` 是 Seed Audio 的历史兼容别名;新脚本优先使用 `seed-audio-create` / `seed-audio-get`。
256
+
257
+ ## RPG2 生产工作台
258
+
259
+ 工作台 CLI 只提交调用方显式登记的项目、产物和归档清单;它不会扫描 RPG 阶段目录,也不会根据文件名推断版本关系。认证仍使用 `AIHUB_AGENT_TOKEN` 与 `BRANCH_VIDEO_AGENT_BASE_URL`,不要在 JSON、命令行或日志中保存 token。
260
+
261
+ 项目、生产记录和外部 CDN 产物可使用 JSON 文件提交:
262
+
263
+ ```powershell
264
+ branch-video-agent workbench project create --file .\project.json --raw
265
+ branch-video-agent workbench record put --project wb_project_id --file .\record.json --raw
266
+ branch-video-agent workbench submit --file .\artifact-external.json --raw
267
+ branch-video-agent workbench annotation put --project wb_project_id --file .\annotation.json --raw
268
+ ```
269
+
270
+ 同一产物用稳定的 `artifactKey` 和由流程侧持久维护的递增 `sourceRevision`。`idempotencyKey` 由流程侧保存并在重试时复用。已有持久媒体使用 `content.type: "external"`;本地文档、脱敏 session 或其他需要长期保存的文件使用 `content.type: "local"` 与 `sourcePath`。CLI 会先计算原文件 SHA-256、声明 blob,再流式 gzip 压缩上传(包括媒体与 session)。传输使用 `Content-Type: application/gzip` 和 `x-workbench-upload-format: gzip`,不使用 `Content-Encoding`;服务端流式解压后校验原始大小与 SHA-256,原 MIME、版本和幂等键不变,下载返回原文件字节。原文件上限为 64 MiB,压缩传输上限为 65 MiB。损坏、截断或超限上传不会成为 ready,CLI 不会自动回退 rawCLI 生成单个 gzip member;服务端支持受限 gzip 字节流并统一校验解压后的总字节,无目录或多文件提取。服务端仍兼容未带传输标识的旧 raw 请求(原生 gzip 文件也保持原样);部署时应先更新服务端再发布 CLI。服务端只收到 blob 描述,绝不会收到本地路径。
271
+
272
+ ```json
273
+ {
274
+ "schemaVersion": "workbench.artifact/1",
275
+ "projectId": "wb_project_id",
276
+ "artifactKey": "document:director-program",
277
+ "sourceRevision": 2,
278
+ "idempotencyKey": "persisted-event-uuid",
279
+ "kind": "markdown",
280
+ "stageKey": "04",
281
+ "title": "导演稿",
282
+ "content": {
283
+ "type": "local",
284
+ "sourcePath": "C:/production/canonical/director.md",
285
+ "mime": "text/markdown"
286
+ },
287
+ "source": {
288
+ "productionRecordId": "record_id",
289
+ "archiveGeneration": 0,
290
+ "sourceSchema": "director-program/4"
291
+ }
292
+ }
293
+ ```
294
+
295
+ 上传响应在网络中丢失时,CLI 会先查询同一个已声明 blob;ready 状态不会重传,也不会重新登记业务版本。失败交给流程侧持久待传队列用相同事件重试。
296
+
297
+ `sync` 只读取 `--manifest` 中显式的 `items`。每个 item 为 `type: "artifact"`(默认)或 `type: "annotation"`,可直接携带提交字段或放进 `submission`;不会递归任何工作目录。
298
+
299
+ ```powershell
300
+ branch-video-agent workbench sync --manifest .\.workbench\pending-items.json --raw
301
+ branch-video-agent workbench archive prepare --manifest .\.workbench\archive-wrapper.json --raw
302
+ branch-video-agent workbench archive finalize --project wb_project_id --record record_id --revision 1 --manifest-hash <sha256> --raw
303
+ branch-video-agent workbench archive status --project wb_project_id --record record_id --raw
304
+ branch-video-agent workbench archive download --project wb_project_id --record record_id --revision 1 --file .\entry.json --output .\session.jsonl.zst --raw
305
+ ```
306
+
307
+ `archive prepare` 的文件是调用方维护的 wrapper:`{ manifest, manifestHash, expectedPreviousRevision }`;CLI 原样提交规范化清单和 hash。`archive finalize` 只校验已经提交的清单,不补扫文件。下载的 `entry.json` 至少包含 `{ "entryId": "..." }`;受权限保护的字节写入 `--output`,stdout 仍只输出 JSON 回执。
308
+
309
+ `record put` 的路径参数是稳定的流程 `recordKey`,返回对象的 `id` 才是后续 `end-intent`、`reopen` 和所有 `archive` 命令使用的 `productionRecordId`(也可传给 `--record`)。不要把 `recordKey` 当成归档路由 ID。
310
310
 
311
311
  ## 在仓库内构建发布包
312
312
 
@@ -314,16 +314,16 @@ branch-video-agent workbench archive download --project wb_project_id --record r
314
314
 
315
315
  ```powershell
316
316
  npm run agent:cli:package:build
317
- npm run agent:cli:package:smoke
318
- ```
319
-
320
- 需要运行会启动 standalone Mongo、真实 CLI HTTP 流、Python adapter 或 Chromium 的 Production Workbench 集成验收时,使用专用命令;常规 `npm test` 会排除这些外部运行时依赖。adapter E2E 需要相邻的 rpg2 adapter checkout,或显式设置 `RPG2_WORKBENCH_ADAPTER_ROOT`;缺失 checkout、`zstd` 或 Chromium 时命令应失败。
321
-
322
- ```powershell
323
- npm run test:workbench-cli-integration
324
- npm run test:workbench-adapter-e2e
325
- npm run test:workbench-integration
326
- ```
317
+ npm run agent:cli:package:smoke
318
+ ```
319
+
320
+ 需要运行会启动 standalone Mongo、真实 CLI HTTP 流、Python adapter 或 Chromium 的 Production Workbench 集成验收时,使用专用命令;常规 `npm test` 会排除这些外部运行时依赖。adapter E2E 需要相邻的 rpg2 adapter checkout,或显式设置 `RPG2_WORKBENCH_ADAPTER_ROOT`;缺失 checkout、`zstd` 或 Chromium 时命令应失败。
321
+
322
+ ```powershell
323
+ npm run test:workbench-cli-integration
324
+ npm run test:workbench-adapter-e2e
325
+ npm run test:workbench-integration
326
+ ```
327
327
 
328
328
  产物输出到:
329
329
 
@@ -1,3 +1,5 @@
1
+ import { createGzip } from 'node:zlib';
2
+ import { pipeline } from 'node:stream/promises';
1
3
  import { createHash } from 'node:crypto';
2
4
  import { createReadStream } from 'node:fs';
3
5
  import { stat, writeFile } from 'node:fs/promises';
@@ -70,17 +72,28 @@ async function uploadLocalContent(context, sourcePath, content) {
70
72
  const blobId = getRequiredString(declared.data, 'id');
71
73
  if (declared.data.state !== 'ready') {
72
74
  let uploadError;
75
+ const source = createReadStream(sourcePath), compressed = createGzip();
76
+ const compressing = pipeline(source, compressed);
77
+ // Fetch consumes the compressed readable; prevent an unhandled rejection
78
+ // until its stream error reaches requestStream. Always close both below.
79
+ void compressing.catch(() => undefined);
73
80
  try {
74
81
  await context.client.requestStream(`${workbenchPath}/projects/${encodeURIComponent(projectId(context.payload, context.flags.project))}/blobs/${encodeURIComponent(blobId)}/content`, {
75
82
  method: 'PUT',
76
- body: Readable.toWeb(createReadStream(sourcePath)),
77
- contentType: mime,
83
+ body: Readable.toWeb(compressed),
84
+ contentType: 'application/gzip',
85
+ uploadFormat: 'gzip',
78
86
  timeoutMs: context.flags.timeoutMs,
79
87
  });
80
88
  }
81
89
  catch (error) {
82
90
  uploadError = error;
83
91
  }
92
+ finally {
93
+ source.destroy();
94
+ compressed.destroy();
95
+ await compressing.catch(() => undefined);
96
+ }
84
97
  if (uploadError) {
85
98
  const status = await context.client.request(`${workbenchPath}/projects/${encodeURIComponent(projectId(context.payload, context.flags.project))}/blobs/${encodeURIComponent(blobId)}`, {
86
99
  method: 'GET',
@@ -13,6 +13,7 @@ type StreamRequestOptions = {
13
13
  method: string;
14
14
  body: ReadableStream<Uint8Array>;
15
15
  contentType: string;
16
+ uploadFormat?: 'gzip';
16
17
  timeoutMs?: number;
17
18
  };
18
19
  type BinaryRequestResult = {
package/dist/lib/http.js CHANGED
@@ -93,6 +93,7 @@ export class CliHttpClient {
93
93
  headers: {
94
94
  Authorization: `Bearer ${this.token}`,
95
95
  'content-type': options.contentType,
96
+ ...(options.uploadFormat ? { 'x-workbench-upload-format': options.uploadFormat } : {}),
96
97
  },
97
98
  body: options.body,
98
99
  duplex: 'half',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mindscraft/branch-video-agent-cli",
3
- "version": "0.5.0",
3
+ "version": "0.5.1",
4
4
  "description": "Published CLI for branch-video and AIHub agent APIs.",
5
5
  "type": "module",
6
6
  "bin": {