@mindscraft/branch-video-agent-cli 0.3.2 → 0.3.4

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
@@ -140,6 +140,23 @@ AI Gateway 视频生成并等待示例:
140
140
  '@ | npm exec --yes --package=@mindscraft/branch-video-agent-cli branch-video-agent -- ai-gateway video-create -- --wait --raw
141
141
  ```
142
142
 
143
+ AI Gateway Seed Audio 音频生成并等待示例:
144
+
145
+ ```powershell
146
+ @'
147
+ {
148
+ "model": "seed-audio-1.0",
149
+ "text_prompt": "温柔的女声朗读:欢迎使用豆包语音合成服务。背景加入轻柔科技感铺底音乐。",
150
+ "audio_config": {
151
+ "format": "mp3",
152
+ "sample_rate": 24000
153
+ }
154
+ }
155
+ '@ | npm exec --yes --package=@mindscraft/branch-video-agent-cli branch-video-agent -- ai-gateway seed-audio-create -- --wait --raw
156
+ ```
157
+
158
+ `tts-create` / `tts-get` 是 Seed Audio 的历史兼容别名;新脚本优先使用 `seed-audio-create` / `seed-audio-get`。
159
+
143
160
  ## 在仓库内构建发布包
144
161
 
145
162
  从仓库根目录执行:
@@ -43,6 +43,39 @@ function extractFailureMessage(value) {
43
43
  || record.error
44
44
  || 'AI Gateway task failed');
45
45
  }
46
+ function isJsonRecord(value) {
47
+ return Boolean(value) && typeof value === 'object' && !Array.isArray(value);
48
+ }
49
+ function isHttpUrl(value) {
50
+ return typeof value === 'string' && /^https?:\/\//i.test(value);
51
+ }
52
+ function extractMusicAudioUrl(value) {
53
+ if (Array.isArray(value)) {
54
+ for (const item of value) {
55
+ const audioUrl = extractMusicAudioUrl(item);
56
+ if (audioUrl)
57
+ return audioUrl;
58
+ }
59
+ return '';
60
+ }
61
+ if (!isJsonRecord(value))
62
+ return '';
63
+ for (const key of ['audioUrl', 'streamAudioUrl']) {
64
+ if (isHttpUrl(value[key]))
65
+ return String(value[key]);
66
+ }
67
+ for (const item of Object.values(value)) {
68
+ const audioUrl = extractMusicAudioUrl(item);
69
+ if (audioUrl)
70
+ return audioUrl;
71
+ }
72
+ return '';
73
+ }
74
+ function withStableMusicAudioUrl(data, audioUrl) {
75
+ return isJsonRecord(data)
76
+ ? { ...data, audioUrl }
77
+ : { status: data, audioUrl };
78
+ }
46
79
  async function waitForGatewayTask(context, submit, poll) {
47
80
  const startedAt = context.runtime.now();
48
81
  while (context.runtime.now() - startedAt <= context.flags.timeoutMs) {
@@ -97,6 +130,26 @@ async function getMusicStatus(context, operation, id) {
97
130
  query: { id },
98
131
  });
99
132
  }
133
+ async function createSeedAudio(context) {
134
+ const result = await context.client.request('/api/agent/ai-gateway/tts/create', {
135
+ method: 'POST',
136
+ body: context.payload,
137
+ });
138
+ if (!context.flags.wait) {
139
+ return { data: result.data, requestId: result.requestId };
140
+ }
141
+ const taskId = extractTaskId(result.data);
142
+ const query = pickDefined(context.payload, ['model']);
143
+ return waitForGatewayTask(context, result.data, () => context.client.request(`/api/agent/ai-gateway/tts/query/${encodeURIComponent(taskId)}`, { method: 'GET', query }));
144
+ }
145
+ async function getSeedAudio({ client, payload }) {
146
+ const taskId = getRequiredString(payload, 'taskId');
147
+ const result = await client.request(`/api/agent/ai-gateway/tts/query/${encodeURIComponent(taskId)}`, {
148
+ method: 'GET',
149
+ query: pickDefined(payload, ['model']),
150
+ });
151
+ return { data: result.data, requestId: result.requestId };
152
+ }
100
153
  export const aiGatewayCommands = {
101
154
  capabilities: async ({ client }) => {
102
155
  const result = await client.request('/api/agent/ai-gateway/capabilities', {
@@ -153,6 +206,10 @@ export const aiGatewayCommands = {
153
206
  });
154
207
  return { data: result.data, requestId: result.requestId };
155
208
  },
209
+ 'seed-audio-create': createSeedAudio,
210
+ 'seed-audio-get': getSeedAudio,
211
+ 'tts-create': createSeedAudio,
212
+ 'tts-get': getSeedAudio,
156
213
  'music-submit': async (context) => {
157
214
  const operation = normalizeOperation(getRequiredString(context.payload, 'operation'));
158
215
  const body = context.payload.body === undefined
@@ -167,7 +224,18 @@ export const aiGatewayCommands = {
167
224
  }
168
225
  const taskId = extractTaskId(result.data);
169
226
  const queryOperation = normalizeOperation(getOptionalString(context.payload, 'queryOperation') || inferMusicQueryOperation(operation));
170
- return waitForGatewayTask(context, result.data, () => getMusicStatus(context, queryOperation, taskId));
227
+ const waitResult = await waitForGatewayTask(context, result.data, () => getMusicStatus(context, queryOperation, taskId));
228
+ if (queryOperation !== 'query')
229
+ return waitResult;
230
+ const statusData = isJsonRecord(waitResult.data) ? waitResult.data.status : undefined;
231
+ const audioUrl = extractMusicAudioUrl(statusData);
232
+ if (!audioUrl) {
233
+ throw new CliCommandError('AI Gateway music task completed without an audio URL', 'VALIDATION_ERROR', waitResult.data, waitResult.requestId || null);
234
+ }
235
+ return {
236
+ ...waitResult,
237
+ data: withStableMusicAudioUrl(waitResult.data, audioUrl),
238
+ };
171
239
  },
172
240
  'music-get': async ({ client, payload }) => {
173
241
  const id = getRequiredString(payload, 'id');
@@ -176,6 +244,14 @@ export const aiGatewayCommands = {
176
244
  method: 'GET',
177
245
  query: { id },
178
246
  });
247
+ const status = extractStatus(result.data);
248
+ const audioUrl = extractMusicAudioUrl(result.data);
249
+ if (gatewaySuccessStatuses.has(status) && operation === 'query' && !audioUrl) {
250
+ throw new CliCommandError('AI Gateway music task completed without an audio URL', 'VALIDATION_ERROR', result.data, result.requestId);
251
+ }
252
+ if (audioUrl) {
253
+ return { data: withStableMusicAudioUrl(result.data, audioUrl), requestId: result.requestId };
254
+ }
179
255
  return { data: result.data, requestId: result.requestId };
180
256
  },
181
257
  };
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 | music-submit | music-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',
104
104
  '',
105
105
  'Config precedence:',
106
106
  ' AIHUB_AGENT_TOKEN / BRANCH_VIDEO_AGENT_BASE_URL > stdin JSON or --token-file > command flags',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mindscraft/branch-video-agent-cli",
3
- "version": "0.3.2",
3
+ "version": "0.3.4",
4
4
  "description": "Published CLI for branch-video and AIHub agent APIs.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -33,4 +33,4 @@
33
33
  "prepack": "npm run build",
34
34
  "smoke:help": "npm run build && node dist/bin.js --help"
35
35
  }
36
- }
36
+ }