@mindscraft/branch-video-agent-cli 0.3.4 → 0.3.6
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 +20 -7
- package/dist/bin.js +21 -1
- package/dist/commands/aiGateway.js +2 -0
- package/dist/lib/autoUpdate.d.ts +26 -0
- package/dist/lib/autoUpdate.js +90 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -10,12 +10,6 @@
|
|
|
10
10
|
npm exec --yes --package=@mindscraft/branch-video-agent-cli branch-video-agent -- --help
|
|
11
11
|
```
|
|
12
12
|
|
|
13
|
-
中国大陆用户如果希望更稳定、更快地安装,可以走 npm 的公开镜像:
|
|
14
|
-
|
|
15
|
-
```powershell
|
|
16
|
-
npm exec --yes --registry=https://registry.npmmirror.com --package=@mindscraft/branch-video-agent-cli branch-video-agent -- --help
|
|
17
|
-
```
|
|
18
|
-
|
|
19
13
|
如果你更喜欢简写,从 `0.1.2` 开始也支持:
|
|
20
14
|
|
|
21
15
|
```powershell
|
|
@@ -25,10 +19,13 @@ npx -y @mindscraft/branch-video-agent-cli --help
|
|
|
25
19
|
也可以全局安装:
|
|
26
20
|
|
|
27
21
|
```powershell
|
|
28
|
-
npm install -g @mindscraft/branch-video-agent-cli
|
|
22
|
+
npm install -g @mindscraft/branch-video-agent-cli@latest --registry=https://registry.npmjs.org/
|
|
29
23
|
branch-video-agent --help
|
|
24
|
+
branch-video-agent --version
|
|
30
25
|
```
|
|
31
26
|
|
|
27
|
+
从 `0.3.6` 开始,发布版 CLI 在每次执行命令前查询 npm 官方 registry 的 `latest`,发现新版本时先全局安装该精确版本,再用原参数重新执行命令。registry 查询或安装失败时命令会 fail closed,不会继续提交业务请求。仅在明确接受旧版风险的紧急诊断中设置 `BRANCH_VIDEO_AGENT_DISABLE_AUTO_UPDATE=1` 跳过检查。
|
|
28
|
+
|
|
32
29
|
环境变量:
|
|
33
30
|
|
|
34
31
|
- `AIHUB_AGENT_TOKEN`
|
|
@@ -127,6 +124,22 @@ AI Gateway 图片生成示例:
|
|
|
127
124
|
'@ | npm exec --yes --package=@mindscraft/branch-video-agent-cli branch-video-agent -- ai-gateway image-generate -- --raw
|
|
128
125
|
```
|
|
129
126
|
|
|
127
|
+
AI Gateway Banana Pro 同步生成示例(实际模型值为 `gemini-3-pro-image-preview`):
|
|
128
|
+
|
|
129
|
+
```powershell
|
|
130
|
+
@'
|
|
131
|
+
{
|
|
132
|
+
"model": "gemini-3-pro-image-preview",
|
|
133
|
+
"prompt": "一幅写实风格的山水画,远处有云雾缭绕的山峰",
|
|
134
|
+
"size": "16:9",
|
|
135
|
+
"image_size_ratios": "2K",
|
|
136
|
+
"output_format": "image/png"
|
|
137
|
+
}
|
|
138
|
+
'@ | npm exec --yes --package=@mindscraft/branch-video-agent-cli branch-video-agent -- ai-gateway image-generate -- --raw
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
Banana Pro 图片编辑继续使用 `ai-gateway image-edit`,请求体为 JSON,`image` 是 HTTP(S) URL 字符串数组;GPT Image 2 编辑仍使用 multipart 文件描述。Banana Pro 当前只支持同步调用,不使用 `--wait`。响应通常包含 `data[].b64_json`,不要把完整 base64 写进 Agent 回复或持久化日志。
|
|
142
|
+
|
|
130
143
|
AI Gateway 视频生成并等待示例:
|
|
131
144
|
|
|
132
145
|
```powershell
|
package/dist/bin.js
CHANGED
|
@@ -1,3 +1,23 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import { readFileSync } from 'node:fs';
|
|
2
3
|
import { main } from './index.js';
|
|
3
|
-
|
|
4
|
+
import { autoUpdateAndReexec } from './lib/autoUpdate.js';
|
|
5
|
+
const packageJson = JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf8'));
|
|
6
|
+
const argv = process.argv.slice(2);
|
|
7
|
+
const update = await autoUpdateAndReexec({
|
|
8
|
+
currentVersion: packageJson.version,
|
|
9
|
+
argv,
|
|
10
|
+
executablePath: process.argv[1],
|
|
11
|
+
env: process.env,
|
|
12
|
+
platform: process.platform,
|
|
13
|
+
writeStderr: (text) => process.stderr.write(text),
|
|
14
|
+
});
|
|
15
|
+
if (update.handled) {
|
|
16
|
+
process.exitCode = update.exitCode;
|
|
17
|
+
}
|
|
18
|
+
else if (argv.length === 1 && ['--version', '-v'].includes(argv[0])) {
|
|
19
|
+
process.stdout.write(`${packageJson.version}\n`);
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
process.exitCode = await main(argv);
|
|
23
|
+
}
|
|
@@ -98,6 +98,8 @@ async function waitForGatewayTask(context, submit, poll) {
|
|
|
98
98
|
throw new CliCommandError('AI Gateway wait timed out', 'TIMEOUT', { submit });
|
|
99
99
|
}
|
|
100
100
|
function normalizeImageEditPayload(payload) {
|
|
101
|
+
if (payload.model === 'gemini-3-pro-image-preview')
|
|
102
|
+
return payload;
|
|
101
103
|
if (payload.fields || payload.files)
|
|
102
104
|
return payload;
|
|
103
105
|
const files = {};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export interface AutoUpdateRunResult {
|
|
2
|
+
status: number | null;
|
|
3
|
+
stdout: string;
|
|
4
|
+
stderr: string;
|
|
5
|
+
}
|
|
6
|
+
export interface AutoUpdateRunOptions {
|
|
7
|
+
env?: Record<string, string | undefined>;
|
|
8
|
+
inheritStdio?: boolean;
|
|
9
|
+
timeoutMs?: number;
|
|
10
|
+
}
|
|
11
|
+
export type AutoUpdateRunner = (command: string, args: string[], options?: AutoUpdateRunOptions) => Promise<AutoUpdateRunResult>;
|
|
12
|
+
export interface AutoUpdateOptions {
|
|
13
|
+
currentVersion: string;
|
|
14
|
+
argv: string[];
|
|
15
|
+
executablePath: string;
|
|
16
|
+
env: Record<string, string | undefined>;
|
|
17
|
+
platform: NodeJS.Platform;
|
|
18
|
+
run?: AutoUpdateRunner;
|
|
19
|
+
writeStderr: (text: string) => void;
|
|
20
|
+
}
|
|
21
|
+
export interface AutoUpdateResult {
|
|
22
|
+
handled: boolean;
|
|
23
|
+
exitCode: number;
|
|
24
|
+
latestVersion: string;
|
|
25
|
+
}
|
|
26
|
+
export declare function autoUpdateAndReexec(options: AutoUpdateOptions): Promise<AutoUpdateResult>;
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { spawnSync } from 'node:child_process';
|
|
2
|
+
const PACKAGE_NAME = '@mindscraft/branch-video-agent-cli';
|
|
3
|
+
const OFFICIAL_REGISTRY = 'https://registry.npmjs.org/';
|
|
4
|
+
const REEXEC_ENV = 'BRANCH_VIDEO_AGENT_AUTO_UPDATE_REEXEC';
|
|
5
|
+
const DISABLE_ENV = 'BRANCH_VIDEO_AGENT_DISABLE_AUTO_UPDATE';
|
|
6
|
+
function runProcess(command, args, options) {
|
|
7
|
+
const result = spawnSync(command, args, {
|
|
8
|
+
encoding: 'utf8',
|
|
9
|
+
env: options?.env,
|
|
10
|
+
stdio: options?.inheritStdio ? 'inherit' : 'pipe',
|
|
11
|
+
timeout: options?.timeoutMs,
|
|
12
|
+
});
|
|
13
|
+
return Promise.resolve({
|
|
14
|
+
status: result.status,
|
|
15
|
+
stdout: result.stdout || '',
|
|
16
|
+
stderr: result.stderr || '',
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
function failedResult(options, message, latestVersion) {
|
|
20
|
+
options.writeStderr(`[branch-video-agent] ${message}\n`);
|
|
21
|
+
return { handled: true, exitCode: 1, latestVersion };
|
|
22
|
+
}
|
|
23
|
+
function compareVersions(left, right) {
|
|
24
|
+
const [leftCore, leftPrerelease] = left.split('-', 2);
|
|
25
|
+
const [rightCore, rightPrerelease] = right.split('-', 2);
|
|
26
|
+
const leftParts = leftCore.split('.').map(Number);
|
|
27
|
+
const rightParts = rightCore.split('.').map(Number);
|
|
28
|
+
for (let index = 0; index < 3; index += 1) {
|
|
29
|
+
const difference = leftParts[index] - rightParts[index];
|
|
30
|
+
if (difference !== 0)
|
|
31
|
+
return difference;
|
|
32
|
+
}
|
|
33
|
+
if (leftPrerelease === rightPrerelease)
|
|
34
|
+
return 0;
|
|
35
|
+
if (!leftPrerelease)
|
|
36
|
+
return 1;
|
|
37
|
+
if (!rightPrerelease)
|
|
38
|
+
return -1;
|
|
39
|
+
return leftPrerelease.localeCompare(rightPrerelease);
|
|
40
|
+
}
|
|
41
|
+
export async function autoUpdateAndReexec(options) {
|
|
42
|
+
if (options.env[DISABLE_ENV] === '1' || options.env[REEXEC_ENV] === '1') {
|
|
43
|
+
return { handled: false, exitCode: 0, latestVersion: options.currentVersion };
|
|
44
|
+
}
|
|
45
|
+
const run = options.run || runProcess;
|
|
46
|
+
const npmCommand = options.platform === 'win32'
|
|
47
|
+
? options.env.ComSpec || options.env.COMSPEC || 'cmd.exe'
|
|
48
|
+
: 'npm';
|
|
49
|
+
const npmArgsPrefix = options.platform === 'win32' ? ['/d', '/s', '/c', 'npm'] : [];
|
|
50
|
+
const viewResult = await run(npmCommand, [
|
|
51
|
+
...npmArgsPrefix,
|
|
52
|
+
'view',
|
|
53
|
+
`${PACKAGE_NAME}@latest`,
|
|
54
|
+
'version',
|
|
55
|
+
'--registry',
|
|
56
|
+
OFFICIAL_REGISTRY,
|
|
57
|
+
], { timeoutMs: 15_000 });
|
|
58
|
+
const latestVersion = viewResult.stdout.trim();
|
|
59
|
+
if (viewResult.status !== 0 || !/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/.test(latestVersion)) {
|
|
60
|
+
return failedResult(options, `cannot verify ${PACKAGE_NAME}@latest from ${OFFICIAL_REGISTRY}; refusing to run an unverified CLI`, latestVersion || options.currentVersion);
|
|
61
|
+
}
|
|
62
|
+
if (compareVersions(latestVersion, options.currentVersion) <= 0) {
|
|
63
|
+
return { handled: false, exitCode: 0, latestVersion };
|
|
64
|
+
}
|
|
65
|
+
options.writeStderr(`[branch-video-agent] upgrading ${PACKAGE_NAME} ${options.currentVersion} -> ${latestVersion}\n`);
|
|
66
|
+
const installResult = await run(npmCommand, [
|
|
67
|
+
...npmArgsPrefix,
|
|
68
|
+
'install',
|
|
69
|
+
'-g',
|
|
70
|
+
`${PACKAGE_NAME}@${latestVersion}`,
|
|
71
|
+
'--registry',
|
|
72
|
+
OFFICIAL_REGISTRY,
|
|
73
|
+
], { inheritStdio: true, env: options.env, timeoutMs: 120_000 });
|
|
74
|
+
if (installResult.status !== 0) {
|
|
75
|
+
return failedResult(options, `automatic upgrade to ${latestVersion} failed; command was not executed`, latestVersion);
|
|
76
|
+
}
|
|
77
|
+
const childEnv = {
|
|
78
|
+
...options.env,
|
|
79
|
+
[REEXEC_ENV]: '1',
|
|
80
|
+
};
|
|
81
|
+
const reexecResult = await run(process.execPath, [options.executablePath, ...options.argv], {
|
|
82
|
+
inheritStdio: true,
|
|
83
|
+
env: childEnv,
|
|
84
|
+
});
|
|
85
|
+
return {
|
|
86
|
+
handled: true,
|
|
87
|
+
exitCode: reexecResult.status ?? 1,
|
|
88
|
+
latestVersion,
|
|
89
|
+
};
|
|
90
|
+
}
|