bukesiyi-cli 0.3.0 → 0.3.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 +5 -3
- package/dist/main.js +128 -27
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -26,7 +26,7 @@ npm install -g bukesiyi-cli
|
|
|
26
26
|
|
|
27
27
|
```console
|
|
28
28
|
$ buke --version
|
|
29
|
-
bukesiyi-cli/0.3.
|
|
29
|
+
bukesiyi-cli/0.3.1
|
|
30
30
|
```
|
|
31
31
|
|
|
32
32
|
不想全局安装时,可以用 npx 临时运行,写法是 `npx bukesiyi-cli <命令>`,例如 `npx bukesiyi-cli whoami`。下面的例子都直接写 `buke`。
|
|
@@ -107,6 +107,8 @@ $ buke login bk_test_0123456789abcdef_……
|
|
|
107
107
|
|
|
108
108
|
短剧的确认开拍(`buke drama confirm`)要先取一次当前报价摆出来给人看:不加 `--yes` 只看,退出码 2;加了 `--yes` 才提交这笔布支出,并且用服务端认可的报价哈希核对,报价变过就不会扣费。`buke drama status --wait` 会在终态或停靠时停下:拿到成片退出 0;失败、取消退出 9;停在「要人处理」或「有镜没拍成、可补拍」时退出 0,输出里带原因、缺口与下一步。
|
|
109
109
|
|
|
110
|
+
等待失败、超时或轮询断网时,先查询原任务。`--json` 错误文档的 `recovery` 保留任务编号、最后状态及查询命令;`shorts order` 还保留本次幂等键。自定义服务的查询命令会带回原来的 `--base-url`。若提交结果还无法确认,`recovery.acceptance` 为 `unknown`,只保留请求的键和服务地址,不虚构已受理或任务编号。先在 Studio 核对原请求,不要换键重新下单;CLI 不会自动重试。
|
|
111
|
+
|
|
110
112
|
通用选项:
|
|
111
113
|
|
|
112
114
|
| 选项 | 作用 |
|
|
@@ -213,8 +215,8 @@ export NO_PROXY='localhost,127.0.0.1,[::1]'
|
|
|
213
215
|
| `CLI_TIMEOUT` | 5 | 等了 15 秒,服务端没有回完。稍后重试;总是超时就检查网络,或者中间有没有代理、防火墙拦着 |
|
|
214
216
|
| `CLI_REDIRECT` | 5 | 服务器要求跳转到别处;为了不把密钥带过去,没有跟随。核对服务地址(报错的括号里是跳转指向的地方),用正确的地址重新登录 |
|
|
215
217
|
| `CLI_BAD_RESPONSE` | 5 | 收到的回应不是约定的格式,多半是中间的网关或别的网站回的,括号里是 HTTP 状态码。状态码是 429 或 5xx 时稍后重试;其余的先核对服务地址,重试多半没有用 |
|
|
216
|
-
| `CLI_WAIT_TIMEOUT` | 8 | `--wait`
|
|
217
|
-
| `CLI_TASK_FAILED` | 9 |
|
|
218
|
+
| `CLI_WAIT_TIMEOUT` | 8 | `--wait` 等到时限任务还在跑,任务本身没有失败。按恢复信息查询原任务,给查询加 `--wait --timeout <秒数>` 继续等待,不要重新下单 |
|
|
219
|
+
| `CLI_TASK_FAILED` | 9 | 原任务到了失败的终态,话里是服务端记的原因。先按恢复信息查询原任务并核对原因、已完成内容和账目;新制作需要另行报价与授权 |
|
|
218
220
|
| `CLI_INTERRUPTED` | 130 | 命令被打断了:按了 Ctrl-C,或者收到了 SIGTERM、SIGHUP(这两种的退出码是 143、129)。需要时重新运行 |
|
|
219
221
|
| `CLI_INTERNAL` | 5 | 工具自己出了没有料到的错,正常使用不应该遇到。把完整的报错和运行的命令(不要带密钥)发给客服,联系方式见文末「联系我们」 |
|
|
220
222
|
|
package/dist/main.js
CHANGED
|
@@ -89,6 +89,7 @@ var CliError = class _CliError extends Error {
|
|
|
89
89
|
retryAfterSeconds;
|
|
90
90
|
httpStatus;
|
|
91
91
|
hints;
|
|
92
|
+
recovery;
|
|
92
93
|
constructor(init) {
|
|
93
94
|
super(redactKeys(init.message));
|
|
94
95
|
this.name = "CliError";
|
|
@@ -99,6 +100,7 @@ var CliError = class _CliError extends Error {
|
|
|
99
100
|
if (init.retryAfterSeconds !== void 0) this.retryAfterSeconds = init.retryAfterSeconds;
|
|
100
101
|
if (init.httpStatus !== void 0) this.httpStatus = init.httpStatus;
|
|
101
102
|
this.hints = init.hints ?? [];
|
|
103
|
+
if (init.recovery !== void 0) this.recovery = init.recovery;
|
|
102
104
|
}
|
|
103
105
|
withHint(hint) {
|
|
104
106
|
return new _CliError({
|
|
@@ -109,7 +111,21 @@ var CliError = class _CliError extends Error {
|
|
|
109
111
|
traceId: this.traceId,
|
|
110
112
|
retryAfterSeconds: this.retryAfterSeconds,
|
|
111
113
|
httpStatus: this.httpStatus,
|
|
112
|
-
hints: [...this.hints, hint]
|
|
114
|
+
hints: [...this.hints, hint],
|
|
115
|
+
recovery: this.recovery
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
withRecovery(recovery) {
|
|
119
|
+
return new _CliError({
|
|
120
|
+
code: this.code,
|
|
121
|
+
message: this.message,
|
|
122
|
+
exitCode: this.exitCode,
|
|
123
|
+
retryable: this.retryable,
|
|
124
|
+
traceId: this.traceId,
|
|
125
|
+
retryAfterSeconds: this.retryAfterSeconds,
|
|
126
|
+
httpStatus: this.httpStatus,
|
|
127
|
+
hints: this.hints,
|
|
128
|
+
recovery
|
|
113
129
|
});
|
|
114
130
|
}
|
|
115
131
|
};
|
|
@@ -396,12 +412,58 @@ async function readNewKey(io) {
|
|
|
396
412
|
|
|
397
413
|
// package.json
|
|
398
414
|
var name = "bukesiyi-cli";
|
|
399
|
-
var version = "0.3.
|
|
415
|
+
var version = "0.3.1";
|
|
400
416
|
|
|
401
417
|
// src/version.ts
|
|
402
418
|
var PACKAGE_NAME = name;
|
|
403
419
|
var VERSION = version;
|
|
404
420
|
|
|
421
|
+
// src/task-recovery.ts
|
|
422
|
+
function shellArgument(value) {
|
|
423
|
+
return /^[A-Za-z0-9_][A-Za-z0-9_.:-]*$/.test(value) ? value : `'${value.replace(/'/g, `'"'"'`)}'`;
|
|
424
|
+
}
|
|
425
|
+
function taskRecovery(taskType, taskId, status4, baseUrl, failureCode) {
|
|
426
|
+
const customOrigin = baseUrl !== DEFAULT_BASE_URL;
|
|
427
|
+
return {
|
|
428
|
+
taskType,
|
|
429
|
+
acceptance: "confirmed",
|
|
430
|
+
taskId,
|
|
431
|
+
status: status4,
|
|
432
|
+
...customOrigin ? { baseUrl } : {},
|
|
433
|
+
...failureCode === void 0 || failureCode === "" ? {} : { failureCode },
|
|
434
|
+
nextAction: "query",
|
|
435
|
+
statusCommand: `buke ${taskType} status ${shellArgument(taskId)}` + (customOrigin ? ` --base-url ${shellArgument(baseUrl)}` : "")
|
|
436
|
+
};
|
|
437
|
+
}
|
|
438
|
+
async function retainTaskOnError(recovery, operation) {
|
|
439
|
+
try {
|
|
440
|
+
return await operation();
|
|
441
|
+
} catch (error) {
|
|
442
|
+
const failure = toCliError(error);
|
|
443
|
+
throw failure.withRecovery({ ...recovery(), ...failure.recovery });
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
async function retainSubmissionOnError(taskType, idempotencyKey, baseUrl, operation) {
|
|
447
|
+
try {
|
|
448
|
+
return await operation();
|
|
449
|
+
} catch (error) {
|
|
450
|
+
const failure = toCliError(error);
|
|
451
|
+
const rejectedResponse = failure.httpStatus !== void 0 && failure.httpStatus >= 400 && failure.httpStatus < 500 && failure.httpStatus !== 408;
|
|
452
|
+
const uncertainResponse = failure.httpStatus === 408 || failure.httpStatus !== void 0 && failure.httpStatus >= 500 && failure.httpStatus < 600;
|
|
453
|
+
const uncertainTransport = ["CLI_NETWORK", "CLI_TIMEOUT", "CLI_BAD_RESPONSE", "CLI_INTERRUPTED"].includes(failure.code);
|
|
454
|
+
if (!rejectedResponse && (uncertainResponse || uncertainTransport)) {
|
|
455
|
+
throw failure.withRecovery({
|
|
456
|
+
taskType,
|
|
457
|
+
acceptance: "unknown",
|
|
458
|
+
idempotencyKey,
|
|
459
|
+
nextAction: "query",
|
|
460
|
+
...baseUrl !== DEFAULT_BASE_URL ? { baseUrl } : {}
|
|
461
|
+
});
|
|
462
|
+
}
|
|
463
|
+
throw failure;
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
|
|
405
467
|
// src/client.ts
|
|
406
468
|
var DEFAULT_REQUEST_TIMEOUT_MS = 15e3;
|
|
407
469
|
var DEFAULT_DOWNLOAD_TIMEOUT_MS = 12e4;
|
|
@@ -441,6 +503,7 @@ function unreadableResponse(status4) {
|
|
|
441
503
|
code: "CLI_BAD_RESPONSE",
|
|
442
504
|
exitCode: EXIT.SERVER,
|
|
443
505
|
retryable,
|
|
506
|
+
httpStatus: status4,
|
|
444
507
|
message: `\u670D\u52A1\u5668\u56DE\u4E86\u4E00\u4E2A\u770B\u4E0D\u61C2\u7684\u56DE\u5E94\uFF08HTTP ${status4}\uFF09\uFF0C${advice}`,
|
|
445
508
|
hints: status4 === 404 ? [NOT_FOUND_HINT] : []
|
|
446
509
|
});
|
|
@@ -1215,9 +1278,11 @@ async function awaitTemplateShortOrder(baseUrl, apiKey, start, deps, wait) {
|
|
|
1215
1278
|
for (; ; ) {
|
|
1216
1279
|
const remaining = deadline - wait.now().getTime();
|
|
1217
1280
|
if (remaining <= 0) return { value: current, timedOut: true };
|
|
1218
|
-
await
|
|
1219
|
-
|
|
1220
|
-
|
|
1281
|
+
current = await retainTaskOnError(() => taskRecovery("shorts", current.view.id, current.view.status, baseUrl), async () => {
|
|
1282
|
+
await wait.sleep(Math.max(Math.min(interval, remaining), 1));
|
|
1283
|
+
interval = Math.min(Math.ceil(interval * 1.5), MAX_POLL_INTERVAL_MS);
|
|
1284
|
+
return getTemplateShortOrder(baseUrl, apiKey, current.view.id, deps);
|
|
1285
|
+
});
|
|
1221
1286
|
if (current.view.status !== said) {
|
|
1222
1287
|
wait.note?.(`\u72B6\u6001\u53D8\u6210 ${current.view.status}`);
|
|
1223
1288
|
said = current.view.status;
|
|
@@ -1235,9 +1300,11 @@ async function awaitVideoRun(baseUrl, apiKey, start, deps, wait) {
|
|
|
1235
1300
|
const remaining = deadline - wait.now().getTime();
|
|
1236
1301
|
if (remaining <= 0) return { value: current, timedOut: true };
|
|
1237
1302
|
const preferred = current.view.pollAfterMs !== null && current.view.pollAfterMs > 0 ? current.view.pollAfterMs : interval;
|
|
1238
|
-
await
|
|
1239
|
-
|
|
1240
|
-
|
|
1303
|
+
current = await retainTaskOnError(() => taskRecovery("videos", current.view.rootRunId, current.view.status, baseUrl, current.view.failure?.code), async () => {
|
|
1304
|
+
await wait.sleep(Math.max(Math.min(preferred, remaining), 1));
|
|
1305
|
+
interval = Math.min(Math.ceil(interval * 1.5), MAX_POLL_INTERVAL_MS);
|
|
1306
|
+
return getVideoRun(baseUrl, apiKey, current.view.rootRunId, deps);
|
|
1307
|
+
});
|
|
1241
1308
|
if (current.view.status !== said) {
|
|
1242
1309
|
wait.note?.(`\u72B6\u6001\u53D8\u6210 ${current.view.status}`);
|
|
1243
1310
|
said = current.view.status;
|
|
@@ -1257,9 +1324,11 @@ async function awaitDramaOrder(baseUrl, apiKey, start, deps, wait) {
|
|
|
1257
1324
|
for (; ; ) {
|
|
1258
1325
|
const remaining = deadline - wait.now().getTime();
|
|
1259
1326
|
if (remaining <= 0) return { value: current, timedOut: true };
|
|
1260
|
-
await
|
|
1261
|
-
|
|
1262
|
-
|
|
1327
|
+
current = await retainTaskOnError(() => taskRecovery("drama", current.view.id, current.view.status, baseUrl), async () => {
|
|
1328
|
+
await wait.sleep(Math.max(Math.min(interval, remaining), 1));
|
|
1329
|
+
interval = Math.min(Math.ceil(interval * 1.5), MAX_POLL_INTERVAL_MS);
|
|
1330
|
+
return getDramaOrder(baseUrl, apiKey, current.view.id, deps);
|
|
1331
|
+
});
|
|
1263
1332
|
if (current.view.status !== said) {
|
|
1264
1333
|
wait.note?.(`\u72B6\u6001\u53D8\u6210 ${current.view.status}`);
|
|
1265
1334
|
said = current.view.status;
|
|
@@ -1732,20 +1801,23 @@ function waitControls(io, values, note) {
|
|
|
1732
1801
|
note
|
|
1733
1802
|
};
|
|
1734
1803
|
}
|
|
1735
|
-
function settleOrder(outcome) {
|
|
1804
|
+
function settleOrder(outcome, baseUrl) {
|
|
1736
1805
|
const order2 = outcome.value.view;
|
|
1806
|
+
const recovery = taskRecovery("shorts", order2.id, order2.status, baseUrl);
|
|
1737
1807
|
if (outcome.timedOut) {
|
|
1738
1808
|
throw new CliError({
|
|
1739
1809
|
code: "CLI_WAIT_TIMEOUT",
|
|
1740
1810
|
exitCode: EXIT.WAIT_TIMEOUT,
|
|
1741
|
-
message: `\u7B49\u4E86\u8FD9\u4E48\u4E45\u8FD8\u5728 ${order2.status}\uFF1A\u518D\u67E5\u7528
|
|
1811
|
+
message: `\u7B49\u4E86\u8FD9\u4E48\u4E45\u8FD8\u5728 ${order2.status}\uFF1A\u518D\u67E5\u7528 ${recovery.statusCommand}\uFF0C\u7ED9\u8BE5\u67E5\u8BE2\u52A0 --wait --timeout <\u79D2\u6570> \u53EF\u7EE7\u7EED\u7B49\u5F85`,
|
|
1812
|
+
recovery
|
|
1742
1813
|
});
|
|
1743
1814
|
}
|
|
1744
1815
|
if (order2.status === "failed" || order2.status === "canceled") {
|
|
1745
1816
|
throw new CliError({
|
|
1746
1817
|
code: "CLI_TASK_FAILED",
|
|
1747
1818
|
exitCode: EXIT.TASK_FAILED,
|
|
1748
|
-
message: order2.error === void 0 ? `\u8FD9\u6761\u77ED\u7247${order2.status === "canceled" ? "\u5DF2\u53D6\u6D88" : "\u6CA1\u6709\u6E32\u67D3\u6210\u529F"}` : singleLine(order2.error)
|
|
1819
|
+
message: order2.error === void 0 ? `\u8FD9\u6761\u77ED\u7247${order2.status === "canceled" ? "\u5DF2\u53D6\u6D88" : "\u6CA1\u6709\u6E32\u67D3\u6210\u529F"}` : singleLine(order2.error),
|
|
1820
|
+
recovery
|
|
1749
1821
|
});
|
|
1750
1822
|
}
|
|
1751
1823
|
return outcome.value;
|
|
@@ -1822,8 +1894,16 @@ async function order(context) {
|
|
|
1822
1894
|
const shouldWait = values.wait === true;
|
|
1823
1895
|
const controls = shouldWait ? waitControls(io, values, (line) => out.notice(line)) : void 0;
|
|
1824
1896
|
const { apiKey, baseUrl } = await resolveApiKey(context);
|
|
1825
|
-
const accepted = await
|
|
1826
|
-
|
|
1897
|
+
const accepted = await retainSubmissionOnError(
|
|
1898
|
+
"shorts",
|
|
1899
|
+
idempotencyKey,
|
|
1900
|
+
baseUrl,
|
|
1901
|
+
() => createTemplateShortOrder(baseUrl, apiKey, templateId, props, quoteHash, idempotencyKey, io)
|
|
1902
|
+
);
|
|
1903
|
+
const final = shouldWait ? await retainTaskOnError(
|
|
1904
|
+
() => ({ ...taskRecovery("shorts", accepted.view.id, accepted.view.status, baseUrl), idempotencyKey }),
|
|
1905
|
+
async () => settleOrder(await awaitTemplateShortOrder(baseUrl, apiKey, accepted, io, controls), baseUrl)
|
|
1906
|
+
) : accepted;
|
|
1827
1907
|
out.result([...orderLines(final.view), `\u5E42\u7B49\u952E\uFF1A${idempotencyKey}`], {
|
|
1828
1908
|
order: final.raw.order,
|
|
1829
1909
|
idempotencyKey,
|
|
@@ -1837,7 +1917,7 @@ async function status(context, rawId) {
|
|
|
1837
1917
|
const controls = shouldWait ? waitControls(io, values, (line) => out.notice(line)) : void 0;
|
|
1838
1918
|
const { apiKey, baseUrl } = await resolveApiKey(context);
|
|
1839
1919
|
const current = await getTemplateShortOrder(baseUrl, apiKey, orderId, io);
|
|
1840
|
-
const final = shouldWait ? settleOrder(await awaitTemplateShortOrder(baseUrl, apiKey, current, io, controls)) : current;
|
|
1920
|
+
const final = shouldWait ? settleOrder(await awaitTemplateShortOrder(baseUrl, apiKey, current, io, controls), baseUrl) : current;
|
|
1841
1921
|
out.result(orderLines(final.view), { order: final.raw.order, ...shouldWait ? { waited: true } : {} });
|
|
1842
1922
|
}
|
|
1843
1923
|
async function cancel(context, rawId) {
|
|
@@ -1905,27 +1985,31 @@ function waitControls2(io, values, note) {
|
|
|
1905
1985
|
note
|
|
1906
1986
|
};
|
|
1907
1987
|
}
|
|
1908
|
-
function settleOrder2(outcome) {
|
|
1988
|
+
function settleOrder2(outcome, baseUrl) {
|
|
1909
1989
|
const order2 = outcome.value.view;
|
|
1990
|
+
const recovery = taskRecovery("drama", order2.id, order2.status, baseUrl);
|
|
1910
1991
|
if (outcome.timedOut) {
|
|
1911
1992
|
throw new CliError({
|
|
1912
1993
|
code: "CLI_WAIT_TIMEOUT",
|
|
1913
1994
|
exitCode: EXIT.WAIT_TIMEOUT,
|
|
1914
|
-
message: `\u7B49\u4E86\u8FD9\u4E48\u4E45\u8FD8\u5728 ${order2.status}\uFF1A\u518D\u67E5\u7528
|
|
1995
|
+
message: `\u7B49\u4E86\u8FD9\u4E48\u4E45\u8FD8\u5728 ${order2.status}\uFF1A\u518D\u67E5\u7528 ${recovery.statusCommand}\uFF0C\u7ED9\u8BE5\u67E5\u8BE2\u52A0 --wait --timeout <\u79D2\u6570> \u53EF\u7EE7\u7EED\u7B49\u5F85`,
|
|
1996
|
+
recovery
|
|
1915
1997
|
});
|
|
1916
1998
|
}
|
|
1917
1999
|
if (order2.status === "failed") {
|
|
1918
2000
|
throw new CliError({
|
|
1919
2001
|
code: "CLI_TASK_FAILED",
|
|
1920
2002
|
exitCode: EXIT.TASK_FAILED,
|
|
1921
|
-
message: order2.reason === void 0 || order2.reason.trim() === "" ? "\u8FD9\u5355\u77ED\u5267\u6CA1\u6709\u62CD\u6210" : singleLine(order2.reason)
|
|
2003
|
+
message: order2.reason === void 0 || order2.reason.trim() === "" ? "\u8FD9\u5355\u77ED\u5267\u6CA1\u6709\u62CD\u6210" : singleLine(order2.reason),
|
|
2004
|
+
recovery
|
|
1922
2005
|
});
|
|
1923
2006
|
}
|
|
1924
2007
|
if (order2.status === "canceled") {
|
|
1925
2008
|
throw new CliError({
|
|
1926
2009
|
code: "CLI_TASK_FAILED",
|
|
1927
2010
|
exitCode: EXIT.TASK_FAILED,
|
|
1928
|
-
message: "\u8FD9\u5355\u77ED\u5267\u5DF2\u53D6\u6D88\uFF1A\u6CA1\u62CD\u7684\u955C\u5934\u9000\u56DE\u51BB\u7ED3\u989D\u5EA6\uFF0C\u5DF2\u7ECF\u62CD\u6210\u7684\u4FDD\u7559\u7167\u6263"
|
|
2011
|
+
message: "\u8FD9\u5355\u77ED\u5267\u5DF2\u53D6\u6D88\uFF1A\u6CA1\u62CD\u7684\u955C\u5934\u9000\u56DE\u51BB\u7ED3\u989D\u5EA6\uFF0C\u5DF2\u7ECF\u62CD\u6210\u7684\u4FDD\u7559\u7167\u6263",
|
|
2012
|
+
recovery
|
|
1929
2013
|
});
|
|
1930
2014
|
}
|
|
1931
2015
|
return outcome.value;
|
|
@@ -2033,7 +2117,7 @@ async function status2(context, rawId) {
|
|
|
2033
2117
|
const controls = shouldWait ? waitControls2(io, values, (line) => out.notice(line)) : void 0;
|
|
2034
2118
|
const { apiKey, baseUrl } = await resolveApiKey(context);
|
|
2035
2119
|
const current = await getDramaOrder(baseUrl, apiKey, orderId, io);
|
|
2036
|
-
const final = shouldWait ? settleOrder2(await awaitDramaOrder(baseUrl, apiKey, current, io, controls)) : current;
|
|
2120
|
+
const final = shouldWait ? settleOrder2(await awaitDramaOrder(baseUrl, apiKey, current, io, controls), baseUrl) : current;
|
|
2037
2121
|
out.result([...orderLines2(final.view), ...guidanceLines(final.view)], {
|
|
2038
2122
|
order: final.raw.order,
|
|
2039
2123
|
...shouldWait ? { waited: true } : {}
|
|
@@ -2124,13 +2208,27 @@ function errorDocument(error) {
|
|
|
2124
2208
|
};
|
|
2125
2209
|
if (error.retryAfterSeconds !== void 0) document.error.retryAfterSeconds = error.retryAfterSeconds;
|
|
2126
2210
|
if (error.httpStatus !== void 0) document.error.httpStatus = error.httpStatus;
|
|
2211
|
+
if (error.recovery !== void 0) document.recovery = error.recovery;
|
|
2127
2212
|
return document;
|
|
2128
2213
|
}
|
|
2129
2214
|
function errorLines(error) {
|
|
2130
2215
|
const details = [`\u9519\u8BEF\u7801 ${singleLine(error.code)}`];
|
|
2131
2216
|
if (error.traceId) details.push(`\u8BF7\u6C42\u7F16\u53F7 ${singleLine(error.traceId)}`);
|
|
2132
2217
|
if (error.retryAfterSeconds !== void 0) details.push(`${error.retryAfterSeconds} \u79D2\u540E\u53EF\u4EE5\u91CD\u8BD5`);
|
|
2133
|
-
|
|
2218
|
+
const recovery = error.recovery;
|
|
2219
|
+
return [
|
|
2220
|
+
`\u9519\u8BEF\uFF1A${singleLine(error.message)}`,
|
|
2221
|
+
`\uFF08${details.join("\uFF1B")}\uFF09`,
|
|
2222
|
+
...error.hints,
|
|
2223
|
+
...recovery === void 0 ? [] : [
|
|
2224
|
+
recovery.acceptance === "confirmed" ? `\u5DF2\u53D7\u7406\u4EFB\u52A1\uFF1A${singleLine(recovery.taskId ?? "")}` : "\u63D0\u4EA4\u7ED3\u679C\u5C1A\u672A\u786E\u8BA4\uFF0C\u8BF7\u5148\u5728 Studio \u6838\u5BF9\u539F\u8BF7\u6C42\uFF1B\u4E0D\u8981\u91CD\u65B0\u4E0B\u5355",
|
|
2225
|
+
...recovery.baseUrl === void 0 ? [] : [`\u670D\u52A1\u5730\u5740\uFF1A${singleLine(recovery.baseUrl)}`],
|
|
2226
|
+
...recovery.status === void 0 ? [] : [`\u6700\u540E\u72B6\u6001\uFF1A${singleLine(recovery.status)}`],
|
|
2227
|
+
...recovery.failureCode === void 0 ? [] : [`\u4EFB\u52A1\u5931\u8D25\u7801\uFF1A${singleLine(recovery.failureCode)}`],
|
|
2228
|
+
...recovery.idempotencyKey === void 0 ? [] : [`\u5E42\u7B49\u952E\uFF1A${singleLine(recovery.idempotencyKey)}`],
|
|
2229
|
+
...recovery.statusCommand === void 0 ? [] : [`\u53EA\u67E5\u8BE2\u539F\u4EFB\u52A1\uFF1A${singleLine(recovery.statusCommand)}`]
|
|
2230
|
+
]
|
|
2231
|
+
];
|
|
2134
2232
|
}
|
|
2135
2233
|
function createOutput(streams, json) {
|
|
2136
2234
|
const secrets = [];
|
|
@@ -2393,20 +2491,23 @@ function waitControls3(io, values) {
|
|
|
2393
2491
|
sleep: io.sleep ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms)))
|
|
2394
2492
|
};
|
|
2395
2493
|
}
|
|
2396
|
-
function settleRun(outcome) {
|
|
2494
|
+
function settleRun(outcome, baseUrl) {
|
|
2397
2495
|
const run2 = outcome.value.view;
|
|
2496
|
+
const recovery = taskRecovery("videos", run2.rootRunId, run2.status, baseUrl, run2.failure?.code);
|
|
2398
2497
|
if (outcome.timedOut) {
|
|
2399
2498
|
throw new CliError({
|
|
2400
2499
|
code: "CLI_WAIT_TIMEOUT",
|
|
2401
2500
|
exitCode: EXIT.WAIT_TIMEOUT,
|
|
2402
|
-
message: `\u7B49\u4E86\u8FD9\u4E48\u4E45\u8FD8\u5728 ${run2.status}\uFF08${run2.stage}\uFF09\uFF1A\u518D\u67E5\u7528
|
|
2501
|
+
message: `\u7B49\u4E86\u8FD9\u4E48\u4E45\u8FD8\u5728 ${run2.status}\uFF08${run2.stage}\uFF09\uFF1A\u518D\u67E5\u7528 ${recovery.statusCommand}\uFF0C\u7ED9\u8BE5\u67E5\u8BE2\u52A0 --wait --timeout <\u79D2\u6570> \u53EF\u7EE7\u7EED\u7B49\u5F85`,
|
|
2502
|
+
recovery
|
|
2403
2503
|
});
|
|
2404
2504
|
}
|
|
2405
2505
|
if (run2.status === "failed" || run2.status === "canceled") {
|
|
2406
2506
|
throw new CliError({
|
|
2407
2507
|
code: "CLI_TASK_FAILED",
|
|
2408
2508
|
exitCode: EXIT.TASK_FAILED,
|
|
2409
|
-
message: run2.failure === null ? `\u8FD9\u6761\u89C6\u9891${run2.status === "canceled" ? "\u5DF2\u53D6\u6D88" : "\u6CA1\u6709\u505A\u6210"}` : singleLine(run2.failure.title) + (run2.failure.detail === "" ? "" : `\uFF1A${singleLine(run2.failure.detail)}`)
|
|
2509
|
+
message: run2.failure === null ? `\u8FD9\u6761\u89C6\u9891${run2.status === "canceled" ? "\u5DF2\u53D6\u6D88" : "\u6CA1\u6709\u505A\u6210"}` : singleLine(run2.failure.title) + (run2.failure.detail === "" ? "" : `\uFF1A${singleLine(run2.failure.detail)}`),
|
|
2510
|
+
recovery
|
|
2410
2511
|
});
|
|
2411
2512
|
}
|
|
2412
2513
|
return outcome.value;
|
|
@@ -2483,7 +2584,7 @@ async function status3(context, rawId) {
|
|
|
2483
2584
|
const controls = shouldWait ? waitControls3(io, values) : void 0;
|
|
2484
2585
|
const { apiKey, baseUrl } = await resolveApiKey(context);
|
|
2485
2586
|
const current = await getVideoRun(baseUrl, apiKey, runId, io);
|
|
2486
|
-
const final = shouldWait ? settleRun(await awaitVideoRun(baseUrl, apiKey, current, io, controls)) : current;
|
|
2587
|
+
const final = shouldWait ? settleRun(await awaitVideoRun(baseUrl, apiKey, current, io, controls), baseUrl) : current;
|
|
2487
2588
|
const lastDirectorLine = [...final.view.messages].reverse().find((message2) => message2.role === "assistant" && message2.text.trim() !== "");
|
|
2488
2589
|
out.result(
|
|
2489
2590
|
[
|