@lingjingai/lj-awb-cli-pre 0.4.0 → 0.4.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.
@@ -47,12 +47,12 @@ lj-awb model options --model-group-code <modelGroupCode> -f text
47
47
 
48
48
  Agent 读取这些字段:
49
49
 
50
- - `params[]`:模型暴露的参数 key 和约束;创建命令 flag `model create-spec`。
50
+ - `params[]`:模型暴露的参数 key 和约束;创建命令写法看 `params[].cliArg` `model create-spec`。新增通用模型配置参数会带 `genericModelParam=true`,用 `--model-param key=value` 或 `--model-params-json` 传入。
51
51
  - `params[].values`:枚举取值,创建任务时只能从这里选。
52
- - `params[].defaultValue`:模型默认值;关键参数不能静默采用默认值,用户选择或确认“按默认”后才继续 fee / dry-run
52
+ - `params[].defaultValue`:模型默认值;关键参数和有可选值的新增参数不能静默采用默认值,用户选择或确认“按默认”后才继续 fee / dry-run,并在创建命令中显式传入。
53
53
  - `params[].maxLength`:prompt 等文本参数的长度限制。
54
54
  - `resources[]`:素材媒体约束,包含 `mode`、`mediaType`、`usage`、`valueShapes`、`fileTypes`、数量 / 大小 / 时长限制;frames 资源的 `usage` 可同时包含 `first_frame|last_frame`。`valueShapes` 描述允许的 value 形状(`file|url|platformPath|asset`),与 `source.kind` 的两值枚举不同,详见 [`../references/model-options-read.md`](../references/model-options-read.md)。
55
- - `media=IMAGE` 的 `fileTypes` 是特殊语义:空列表表示不支持 webp,CLI 会把本地 webp 自动转成 jpg;仅 `webp` 表示普通图片格式外也支持 webp;多值列表才是强控制允许格式。pretty/text 会把它翻译成 `formats=...` 和 `webpInput=accepted|autoConvertToJPG`。
55
+ - `media=IMAGE` 的 `fileTypes` 是特殊语义:空列表表示不支持 webp,CLI 会把本地或可下载远端 webp 自动转成 jpg;仅 `webp` 表示普通图片格式外也支持 webp;多值列表才是强控制允许格式。pretty/text 会把它翻译成 `formats=...` 和 `webpInput=accepted|autoConvertToJPG`。
56
56
  - `constraints[]`:条件约束全景,描述某个输入或参数出现后,会限制哪个目标参数或资源能力;例如 `target=ratio` 且 `when=resource.image.frame=present`、`effect=no_selectable_values` 表示首帧 / 首尾帧输入后不要让用户继续选择比例;`effect=resource_limit_overrides` 表示某类素材的数量、大小或时长随条件收紧,读取 `limits`。
57
57
 
58
58
  ## 获取创建规格
@@ -86,6 +86,7 @@ Agent 读取这些字段:
86
86
  | `frames` | `--resource image:first_frame=...` / `image:last_frame=...`,可传文件/URL/backendPath/`asset:<assetId>` | 视频首尾帧 |
87
87
  | `multi_param` | `--resource image/video/audio:reference[:key]=...` / `subject:reference:<key>=asset:<id>` | 多参考素材 / 音频参考 / 主体引用 |
88
88
  | `generated_mode` | 不传 | 由资源类型推导 |
89
+ | 其他 `params[]` 中带 `cliArg` 的 key | `--model-param <key>=...` / `--model-params-json` / 同名下划线长参数 | 通用模型配置参数,例如 `generation_effort` |
89
90
 
90
91
  规则:
91
92
 
@@ -93,7 +94,7 @@ Agent 读取这些字段:
93
94
  - `supportLastFrameOnly` 只表示模型是否支持「仅尾帧」输入;首尾帧过渡能力看 frames 资源的 `usage` 是否包含 `last_frame` 和数量约束。
94
95
  - 用户说「上传音频 / 使用音乐 / 配音 / 音频参考」是**素材输入**,先看 `options.resources[]` 有没有 `mediaType=AUDIO usage=reference`;**不要先去找 `needAudio`**(那是输出音效开关)。具体使用规则、`reference_key` / `<<<key>>>` 对齐和 `--need-audio` 不是音频入口等都见 [`create-contract.md`](create-contract.md) §素材组织 + §Prompt 组装原则。
95
96
  - 用户要走素材加白 / 素材库过审时,先跑 `model asset-review-models --model-group-code <code>` 判断该模型是否支持以及平台值;不要根据模型名称猜平台,也不要把 `modelGroupCode` 放进资产组或素材创建命令。
96
- - 关键参数选择、`fee` / `create --dry-run` 前的追问流程、`inputRequirement.visualInputRequired` 检查等创建前校验见 [`create-contract.md`](create-contract.md) §创建前校验。
97
+ - 关键参数选择、`fee` / `create --dry-run` 前的追问流程、`inputRequirement.visualInputRequired` 检查等创建前校验见 [`create-contract.md`](create-contract.md) §创建前校验。`defaultValue` 只用于展示候选默认,不是 Agent 自动代选的依据。
97
98
  - 输出字段速查见 [`../references/output-fields.md`](../references/output-fields.md) 的"模型"小节。
98
99
 
99
100
  ## 下一步
@@ -1,6 +1,6 @@
1
1
  # Task Module
2
2
 
3
- 任务模块负责图片 / 视频 / 字幕等异步任务的等待、查询和台账恢复。图片 / 视频 / 去字幕任务先用 `create ...` 拿到 `taskId`,主体 / 音色回填用 `create subject-wait` / `create subject-voice-wait`,不要误走 `task wait`。
3
+ 任务模块负责图片 / 视频 / 字幕 / 超分等异步任务的等待、查询和台账恢复。图片 / 视频任务可用 `task wait`,去字幕和视频超分优先使用创建响应里的专用 `nextCommand`;主体 / 音色回填用 `create subject-wait` / `create subject-voice-wait`,不要误走 `task wait`。
4
4
 
5
5
  ## 命令
6
6
 
@@ -8,6 +8,8 @@
8
8
  |------|------|
9
9
  | `lj-awb task list --task-type IMAGE_CREATE --project-group-no <no>` | 列出远端任务(按类型过滤) |
10
10
  | `lj-awb task wait --task-id <id> --task-type IMAGE_CREATE --wait-seconds 180` | 等待单个任务进入终态 |
11
+ | `lj-awb task video-subtitle-status --task-id <id>` | 查询去字幕 material 任务 |
12
+ | `lj-awb task video-super-resolution-status --task-id <id>` | 查询视频超分 material 任务 |
11
13
  | `lj-awb task records --task-record-file .awb/tasks.jsonl` | 读本地任务台账(未指定 `--task-record-file` 默认 `.awb/tasks.jsonl`) |
12
14
  | `lj-awb task records --pending-only --task-record-file .awb/tasks.jsonl` | 只看未终态记录 |
13
15
  | `lj-awb task record-poll --task-record-file .awb/tasks.jsonl --wait-seconds 180` | 一次性轮询台账里所有未终态任务 |
@@ -72,6 +74,7 @@ CLI 当前**不暴露 task cancel**;用户问"能不能停掉这个任务"时
72
74
  - `task wait` 返回 `task_still_running` 时复述 hint,不要误报失败;`taskStatus=FAILED` 或 `errorMessage` 非空才是真失败。
73
75
  - **`task wait` 成功 ≠ 素材库立刻可读**:后端在事务提交后**异步**执行 `saveResourceToMaterial`(`afterCommit` 钩子),即使 `taskStatus=SUCCESS` 拿到 `resultUrls`,对应的 `material` / `asset` 行也可能还没落库。需要立刻复用结果时,优先使用 `resultUrls` / `assetPath` / `taskRecordId` 直接推进;非要查素材库时先 sleep 2-3 秒,不要靠 list 接口密集轮询。
74
76
  - 输出字段只提取 `taskId / taskStatus / isTerminal / resultUrls / errorMessage`,详见 [`../references/output-fields.md`](../references/output-fields.md) 的"生图 / 生视频"和"任务台账"小节。
77
+ - `create video-subtitle-removal` / `create video-super-resolution` 返回 `nextCommand` 时直接执行该命令;不要把它改写成通用 `task wait`。
75
78
  - 不要把大型 raw JSON 整段塞回上下文。
76
79
  - `task list` 是远端查询、`task records` 是本地台账;两者覆盖范围不同(台账只有本机创建的任务)。
77
80
 
@@ -29,6 +29,6 @@
29
29
  - 生视频首帧 / 尾帧 / 参考图:`lj-awb create video ... --resource image:first_frame=material/...`
30
30
  - 视频参考音频:`lj-awb create video ... --resource audio:reference=material/...`
31
31
  - 主体发布参考图:`lj-awb create subject ... --resource primary:material/...`
32
- - 注册到素材库(素材加白):优先让 `lj-awb create asset --group-id <id> --platform <platform> --file ./a.png --name "..." --yes` 自动上传到 `asset-review` 场景;若已单独上传,使用 `--backend-path asset-review/...` 或 `--url asset-review/...`。
32
+ - 注册到素材库(素材加白):优先让 `lj-awb create asset --group-id <id> --platform <platform> --file ./a.png --name "..." --yes` 自动上传到 `asset-review` 场景;CLI 会按文件类型传 `assetType=Image|Video|Audio`,并对本地文件做图片/视频/音频加白规格预检。不合法时正式执行会询问是否转码,非交互脚本可用 `--auto-convert --yes`。若已单独上传,使用 `--backend-path asset-review/...` 或 `--url asset-review/...`,这类远程路径只能按扩展名推断类型,尺寸 / 帧率 / 时长交给后端校验。
33
33
 
34
34
  > `create image` / `create video` / `create subject` 传 `--file` / 本地路径时**会自动 upload**——只有需要"先看 backendPath / 跨任务复用同一份素材"时才单独跑 `upload files`。
@@ -14,6 +14,9 @@
14
14
  | `lj-awb create video-batch --input-file ./video.jsonl --model-group-code <code> --yes` | 批量生视频 |
15
15
  | `lj-awb task video-status --task-id <id>` | 查询生视频任务 |
16
16
  | `lj-awb task wait --task-id <id> --task-type VIDEO_GROUP --wait-seconds 300` | 等待生视频结果 |
17
+ | `lj-awb create video-super-resolution --object-name <objectName> --yes` | 基于 material objectName 提交视频超分任务 |
18
+ | `lj-awb create video-super-resolution-fee --object-name <objectName>` | 计算视频超分预计积分 |
19
+ | `lj-awb task video-super-resolution-status --task-id <id>` | 查询视频超分任务 |
17
20
  | `lj-awb create video-subtitle-removal --source-task-id <videoTaskId> --yes` | 基于来源视频任务提交去字幕任务 |
18
21
  | `lj-awb task video-subtitle-status --task-id <subtitleTaskId>` | 查询去字幕任务 |
19
22
 
@@ -26,6 +29,7 @@
26
29
  | `--ratio` | 指定画幅比例 | `model options.params[key=ratio].values`,并受 `model options.constraints[]` 联动限制 |
27
30
  | `--quality` | 指定清晰度 | `model options.params[key=quality].values` |
28
31
  | `--need-audio` | 是否需要输出音效 | 仅 `model options.params[key=needAudio]` 存在,且用户明确要求输出音效时 |
32
+ | `--model-param key=value` / `--model-params-json` | 新增通用模型配置参数,如 `generation_effort` | `model options.params[]` 中带 `cliArg` / `genericModelParam` 的参数 |
29
33
  | `--resource image:reference[:key]=...` | 参考图生视频 | `model create-spec.supportedIntents.mode=reference` 必须存在,格式 / 数量约束看 `model options.resources[]` |
30
34
  | `--resource audio:reference=...` | 参考音频 / 配乐 / 配音 / 节奏参考 | `model options.resources[]` 中必须存在 `mediaType=AUDIO usage=reference` |
31
35
  | `--resource image:first_frame=...` | 首帧生视频 | `model create-spec.supportedIntents.mode=frames` 必须存在,且 usage 包含 `first_frame` |
@@ -71,25 +75,30 @@ lj-awb create video \
71
75
  - 创建前先看 `inputRequirement.visualInputRequired`。如果为 `true`,必须选择 `supportedIntents` 中的一种素材输入,不能纯 prompt 创建。
72
76
  - Agent 向用户解释模型能力时,默认说“支持参考图 / 首帧 / 首尾帧 / 主体引用”等正向能力;不要默认列“无音频参数、无多条数参数”。
73
77
  - `fee` 和 `create --dry-run` 前必须确认缺失的关键参数;不要把 `model options.params[].defaultValue` 当成用户选择。用户说“按默认”后才继续。
78
+ - `generation_effort` 这类新增模型配置参数如果出现在 `model options.params[]`,先把可选值 / `defaultValue` 展示给用户;用户确认后用 `--model-param generation_effort=<value>` 或 `--model-params-json` 传入,不要等专用 CLI flag。
74
79
  - 面向用户列参数时,`needAudio` 说成“音效:是否需要输出音效”;不要用 CLI flag 加技术解释的写法。只有展示最终命令时才写 `--need-audio true/false`。
75
80
  - 音频参考:必须先确认 `model options.resources[]` 暴露 `mediaType=AUDIO usage=reference`,否则不要硬传;统一用 `--resource audio:reference=...` 或 JSON `{ "type": "audio", "usage": "reference" }`。
76
81
  - `--need-audio` / `audio:reference` / 资源模式互斥 / `reference_key` 对齐 / `<<<key>>>` 等创建协议统一见 [`create-contract.md`](create-contract.md) §素材组织 + §参数含义,不在本文重复。
77
82
  - 使用首帧 / 首尾帧等资源后,如果 `model options.constraints[]` 对 `ratio` 等目标参数返回 `effect=no_selectable_values`,不要再追问或传该参数。
78
- - `media=IMAGE` 的 `fileTypes` 不要机械理解成唯一允许格式:空列表表示不支持 webp,本地 webp 会自动转 jpg;仅 `webp` 表示普通图片格式外也支持 webp;多值列表才按允许列表强校验并尝试转换。默认 text 里看 `formats` 和 `webpInput`,不要把 `formats=...|webp` 理解成"只支持 webp"。
83
+ - `media=IMAGE` 的 `fileTypes` 不要机械理解成唯一允许格式:空列表表示不支持 webp,本地或可下载远端 webp 会自动转 jpg;仅 `webp` 表示普通图片格式外也支持 webp;多值列表才按允许列表强校验并尝试转换。默认 text 里看 `formats` 和 `webpInput`,不要把 `formats=...|webp` 理解成"只支持 webp"。
79
84
  - `supportLastFrameOnly=false` 只表示不支持"仅尾帧";不要据此判断不支持首尾帧过渡。是否可传 `image:last_frame` 看 `model options.resources[].usage` / `model create-spec.supportedIntents[].usage` 是否包含 `last_frame`。
80
85
  - 视频素材(参考图 / 首帧 / 尾帧 / 关键帧 / 音频)source.value 取值优先级、不要复用 myqcloud 完整 URL 规则统一在 [`create-contract.md`](create-contract.md) §素材组织。`image:reference=asset:<assetId>` / `image:first_frame=asset:<assetId>` / `image:last_frame=asset:<assetId>` 是素材引用;`subject:reference:<key>=asset:<subjectId>` 是主体引用。主体引用必须先 `create subject` + `create subject-wait` 得到 `externalId`。
81
- - 批量 JSON/JSONL 每项只写 `prompt`、`ratio`、`quality`、`duration`、`need_audio`、`resources`、`resource`、`customBizId`;其中 `need_audio` 表示是否需要输出音效,音频素材仍写入 `resources`。
86
+ - 批量 JSON/JSONL 每项只写 `prompt`、`ratio`、`quality`、`duration`、`need_audio`、`resources`、`resource`、`model_params`、`customBizId`,也可直接写模型配置下划线参数;其中 `need_audio` 表示是否需要输出音效,音频素材仍写入 `resources`。
82
87
  - **批量是 best-effort**:`create-batch` 子任务**单条失败不会回滚整批**,已成功项依然扣分并产生 taskId。提交后必读响应里每项的 `status` / `taskId` / `error`,给用户汇总"成功 N / 失败 M",对失败项单独 fix + 重跑(不要全批重跑)。
83
88
  - 视频任务默认可能耗时较长,批量和复杂任务应异步提交并记录 task id。
89
+ - 视频超分直接传 `objectName`,通常是 material backendPath 或 COS 对象路径;正式提交前先跑 `create video-super-resolution-fee`,再 `--dry-run`,确认后 `--yes`,返回后按 `nextCommand` 或 `task video-super-resolution-status` 查询。
84
90
  - **多镜头 / 多分镜时主动建议并行**:用户一次给出 ≥2 个同模型同参数的视频任务(典型场景:分镜流水线、批量首尾帧动画)时,Agent 必须先告知"这批可以用 `create video-batch --concurrency N` 并行执行(n 个任务,预计耗时 / 单次估价 × n)",并询问用户是否要并行。用户同意 → 走 batch;用户希望逐条审稿 → 继续单条 create。**不要默认一条一条串行还不告知**。
91
+ - 视频超分不走 model options/create-spec;它是 material 的对象路径任务,和生视频模型选择链路分离。
85
92
  - 去字幕统一走 material 任务体系:用已成功的视频来源任务 ID `create video-subtitle-removal --source-task-id <videoTaskId> --dry-run`,不要直连外部服务;`task video-subtitle-status` 只接收 material 去字幕任务的 `--task-id`。
86
93
  - 输出字段速查见 [`../references/output-fields.md`](../references/output-fields.md) 的"生图 / 生视频"小节;错误恢复(积分 / 模型 / 资源约束)见 [`../references/error-codes.md`](../references/error-codes.md)。
87
94
 
88
95
  ## 下一步
89
96
 
90
97
  - `create video` 返回 `taskId` + `nextCommand` → 立刻 `task wait --task-id <id> --task-type VIDEO_GROUP --wait-seconds 300`。
98
+ - `create video-super-resolution` 返回 `taskId` + `nextCommand` → 立刻运行返回的 `task video-super-resolution-status --task-id <id>`。
91
99
  - `create video-batch` 写 `.awb/tasks.jsonl`,用 [`task.md`](task.md) → `task record-poll` 批量等。
92
100
  - 任务终态 `resultUrls` → 通常按集 / 场 / 镜头回写到 [`artifact/video.md`](artifact/video.md):`artifact video update-clip-urls --project-id <id> --episode-id ... --scene-id ... --clip-id ... --video-urls-json '[...]'`。
93
101
  - 任务 `SUCCESS` 后**立刻**用素材库接口找这条视频时可能查不到——后端 `saveResourceToMaterial` 是事务提交后异步执行,详见 [`task.md`](task.md) 规则。优先用 `resultUrls` 直接消费;非要列素材库时先 sleep 2-3 秒。
94
102
  - Seedance 原始视频带英文字幕 → 对成功的视频任务运行 `create video-subtitle-removal --source-task-id <videoTaskId> --yes` → `task video-subtitle-status --task-id <subtitleTaskId>`。
103
+ - 需要对现有视频做清晰度提升 → 先确认 `objectName`(material backendPath 或 COS 对象路径),再 `create video-super-resolution-fee` 和 `create video-super-resolution`。
95
104
  - 想长期复用同一角色(避免每次都传图) → [`subject.md`](subject.md) 先 `create subject` + `wait` 拿 externalId。
@@ -238,7 +238,9 @@ lj-awb create asset-groups --platform JIMENG --name "项目X-角色"
238
238
  lj-awb create asset-group --platform JIMENG --name "项目X-角色" --dry-run
239
239
  lj-awb create asset-group --platform JIMENG --name "项目X-角色" --yes
240
240
 
241
- # 2. 注册参考图(本地文件版,--file 在 --yes 阶段自动上传 + 注册一步完成)
241
+ # 2. 注册参考素材(本地文件版,--file 在 --yes 阶段自动上传 + 注册一步完成)
242
+ # CLI 会自动按扩展名传 assetType=Image/Video/Audio;本地文件会先校验加白规格。
243
+ # 不合法素材正式执行时会询问是否转码;非交互脚本可追加 --auto-convert。
242
244
  lj-awb create asset \
243
245
  --group-id <groupId> \
244
246
  --platform JIMENG \
@@ -16,14 +16,20 @@ CLI 失败时 envelope 形如:
16
16
  | `1` | `runtime_error` / `api_error` | 平台业务失败或一般运行异常 | 看 `message` / `details`;不要自动重试相同请求 |
17
17
  | `1` | `subject_failed` | 主体创建任务已失败 | 看 `details.errorMessage`,调整参考资源 / 模型后重新创建 |
18
18
  | `1` | `subject_voice_failed` | 主体音色创建任务已失败 | 看 `details.errorMessage`,调整音频 / 视频来源后重新创建 |
19
+ | `1` | `redeem_failed` | 兑换码兑换失败(平台 `code != 200`) | 看 `message`(平台原始提示),确认兑换码是否正确 / 已被使用;持续失败联系平台处理 |
19
20
  | `2` | `argument_error` | 必填参数缺失、参数格式 / 枚举不合法 | 按 `hint` 补参数;用 `lj-awb schema --command <name> -f json` 查 `requiredOptions / requiredAnyOptions` |
20
21
  | `2` | `unknown_command` / `unknown_option` | 命令名 / 参数名打错 | 跑 `lj-awb -h` 或对应子域 `lj-awb <domain> -h` 重查命令 |
21
22
  | `3` | `auth_required` | 缺少 access key | 提示用户 `lj-awb auth login --access-key <key>` 或设置 `LINGJING_AWB_ACCESS_KEY` |
22
23
  | `3` | `auth_failed` | access key 无效 / 已过期(HTTP 401) | 跑 `auth verify` 确认;提示重新登录 |
24
+ | `3` | `auth_flow_expired` | 浏览器授权链接已过期 | 重新跑 `auth login` 获取新链接 |
25
+ | `3` | `auth_flow_canceled` | 用户在浏览器取消了授权 | 重新跑 `auth login` 重新发起 |
26
+ | `3` | `auth_flow_failed` | 创建登录任务失败 / 授权成功但未返回 accessKey | 看 `details`,稍后重试 `auth login`;持续失败联系平台 |
23
27
  | `10` | `confirmation_required` | 写入 / 扣费 / 切换上下文动作未确认 | 向用户复述 `details.action` 后追加 `--yes` 重跑 |
24
28
  | `20` | `task_still_running` | 等待窗口结束但任务未终态 | 直接续跑 `task wait --task-id ... --wait-seconds <n>`,**不代表失败** |
25
29
  | `20` | `subject_still_pending` | 主体 externalId 尚未回填 | 续跑 `create subject-wait --element-id ... --wait-seconds <n>` |
26
30
  | `20` | `subject_voice_still_pending` | 主体音色 externalId 尚未回填 | 续跑 `create subject-voice-wait --voice-record-id ... --wait-seconds <n>` |
31
+ | `20` | `auth_flow_pending` | 浏览器授权等待窗口结束但用户尚未授权 | 用 `details.flowId` 续跑 `auth login --flow-id <flowId>`,**不要重发新 login**,**不代表失败** |
32
+ | `20` | `redeem_timeout` | 交互式等待输入兑换码超时(默认约 10 分钟) | 重新跑 `credits redeem` 并及时输入,或直接 `credits redeem --code <code>` 传入 |
27
33
  | `30` | `network_error` | TLS / DNS / 连接失败 / 平台 5xx | 检查网络;macOS 证书问题用 `lj-awb`(shell wrapper)而不是直接 `node bin/lj-awb.js` |
28
34
  | `30` | `http_error` | 非 401 的 HTTP 错误(4xx / 5xx) | 看 `message`;429 等限流时退避重试 |
29
35
  | `30` | `upload_failed` | COS 上传失败 | 重试一次;持续失败检查文件大小 / mimeType / 网络 |
@@ -107,3 +113,38 @@ lj-awb auth verify # 实际打一次平台 API
107
113
  - **reference 模式**:`image:reference` / `audio:reference` / `video:reference` / `subject:reference`
108
114
 
109
115
  恢复路径:把 `image:first_frame=<source>` 改成 `image:reference=<source>`,让所有素材都在 reference 模式(保留 audio / video / subject 参考),再 `--dry-run` 复核后重跑。不要简单删掉某个素材,应该统一模式。
116
+
117
+ ### 场景 9:浏览器授权登录(auth_flow_*)
118
+
119
+ 浏览器授权登录(`auth login` 不带 `--access-key`)的几种结果:
120
+
121
+ - `auth_flow_pending`(exit 20):等待窗口结束、用户还没授权。**不是失败**。用 `details.flowId` 续跑,不要重发新 login:
122
+
123
+ ```bash
124
+ lj-awb auth login --flow-id <flowId>
125
+ ```
126
+
127
+ - `auth_flow_expired`(exit 3):授权链接过期 → 重新 `auth login` 拿新链接。
128
+ - `auth_flow_canceled`(exit 3):用户在浏览器取消 → 重新 `auth login`。
129
+
130
+ AI agent / 无法实时看输出时的标准流程:
131
+
132
+ ```bash
133
+ lj-awb auth login --no-wait --json # 拿 flowId + verifyUrl,发给用户去浏览器授权
134
+ lj-awb auth login --flow-id <flowId> # 用户授权后续轮询,拿到并保存 accessKey
135
+ ```
136
+
137
+ ### 场景 10:兑换码兑换(redeem_*)
138
+
139
+ `credits redeem` 的几种结果:
140
+
141
+ - `redeem_failed`(exit 1):平台返回 `code != 200`,兑换没成功。`message` 是平台原始提示,如实复述给用户,让其确认兑换码是否正确 / 已被使用;持续失败建议联系平台处理。**不要自动重试相同兑换码**。
142
+ - `redeem_timeout`(exit 20):交互式等待输入超时(默认约 10 分钟)。重新发起并提醒用户及时输入。
143
+
144
+ AI agent / 非交互终端**不要裸跑 `credits redeem`**(会因为无法读取输入直接报 `argument_error`),应让用户提供兑换码后用 `--code` 传入:
145
+
146
+ ```bash
147
+ lj-awb credits redeem --code <code> # 兑换成功后会顺带展示最新积分余额
148
+ ```
149
+
150
+ 兑换是会改账户积分的写操作,执行前先与用户确认;可先 `--dry-run` 预览将要提交的兑换码。
@@ -10,14 +10,14 @@
10
10
  ## `-f text` 怎么读
11
11
 
12
12
  - text 是“分区 key=value”:先看 `summary:`,再看 `params:`、`resources:`、`constraints:`,最后看 `next:`。每个分区的 `count` 表示列表数量,列表项使用 `[0]: key=value ...`。
13
- - `params[]`:模型暴露的可控参数和约束;这里只给参数 key,不给 create 命令 flag。
13
+ - `params[]`:模型暴露的可控参数和约束;优先看 `key`、`cliArg`、`values`、`defaultValue`。已知参数会给专用 flag,新增通用模型配置参数会显示 `cliArg=--model-param / --model-params-json` 和 `genericModelParam=true`。
14
14
  - `values`:枚举取值,只能从这里选。
15
- - `default`:模型默认值;用户没明确指定时通常不必显式传,但清晰度、比例、时长这类关键项仍要确认。
15
+ - `default` / `defaultValue`:模型默认值,只能作为候选默认展示。带可选值或 `defaultValue` 的关键参数不应静默采用;用户明确选择或说“按默认”后才继续 fee / dry-run。
16
16
  - `resources[]`:模型暴露的素材媒体约束;这里只给媒体类型、用途和文件限制,不给 `--resource` 写法。
17
17
  - `media`:素材媒体类型,例如 `IMAGE`、`VIDEO`、`AUDIO`、`SUBJECT`。
18
18
  - `usage`:素材用途,例如 `reference`、`first_frame`、`last_frame`、`keyframe`;同一个资源约束可同时列出 `first_frame|last_frame`。
19
19
  - `valueShapes=file|url|platformPath|asset`:声明这个资源 **value 的形状**,可接受本地文件、公网 URL、平台上传后返回的 `backendPath`、平台资产 ID。注意:这不是 `source.kind` 的枚举;`source.kind` 永远只有 `url`、`asset_id` 两种取值——前三种形状统一传 `kind=url`(CLI 按 value 自动识别),最后一种传 `kind=asset_id`。
20
- - `formats`:文件后缀白名单。
20
+ - `formats`:文件后缀白名单;当 `webpInput=autoConvertToJPG` 时,本地或可下载远端 webp 会在提交前转成 jpg。
21
21
  - `files=<=N` / `files=1`:素材数量约束。
22
22
  - `lastFrameOnly` / JSON `supportLastFrameOnly`:只表示是否支持“仅尾帧”这种特殊输入;不用于判断 `first_frame + last_frame` 是否成立。没有该能力时,尾帧应和首帧成对使用。
23
23
  - `durationMs` / `totalDurationMs`:单个素材和总素材时长约束。
@@ -31,7 +31,7 @@
31
31
  lj-awb model options --model-group-code <code> -f json
32
32
  ```
33
33
 
34
- JSON 里会保留更完整的参数 / 资源 / 条件约束字段,但仍不承担 create 命令写法。`--resource` 语法、prompt key 绑定和示例统一看 `model create-spec`。
34
+ JSON 里会保留更完整的参数 / 资源 / 条件约束字段。`params[].cliArg` 可直接告诉你创建写法;通用模型配置参数用 `--model-param key=value`、`--model-params-json '{"key":"value"}'`,或同名下划线长参数(如 `--generation-effort high`)传入。`--resource` 语法、prompt key 绑定和示例统一看 `model create-spec`。
35
35
 
36
36
  ## 使用顺序
37
37
 
@@ -46,11 +46,12 @@ JSON 里会保留更完整的参数 / 资源 / 条件约束字段,但仍不承
46
46
 
47
47
  ## 判断口径
48
48
 
49
- - 不在 `params[]` 里的 CLI 参数不要传。
49
+ - 不在 `params[]` 里的模型配置参数不要传;新增参数如果已出现在 `params[]` 且有 `cliArg`,无需等待 skill/CLI 硬编码专用 flag。
50
+ - `params[].defaultValue` 不是用户选择;把它展示给用户,用户确认后再通过专用 flag 或 `--model-param` 显式传入。
50
51
  - 不在 `resources[]` 里的媒体类型 / 用途不要硬拼。
51
52
  - 当前用户输入满足 `constraints[].conditions` 时,按 `allowValues` 收窄目标参数;`effect=no_selectable_values` 时不要传该目标参数;`effect=resource_limit_overrides` 时按 `limits` 覆盖对应 `resources[]` 的数量 / 时长等限制。
52
53
  - 主体参考看 `media=SUBJECT usage=reference valueShapes=asset`;reference_key 和 externalId 写法看 `model create-spec` / `model input-guide`。
53
54
  - 图片生图参考图不使用 reference_key;只传 `image:reference=...`,prompt 里用图一、图二、参考图等自然描述。
54
55
  - 音频素材参考看 `media=AUDIO usage=reference`;`needAudio` / `--need-audio` 表示是否需要输出音效。
55
- - `media=IMAGE` 的 `supportedFileTypes` 是 webp 能力标记:空表示不支持 webp,单独 `webp` 表示普通图片格式外也支持 webp,多值才表示强允许列表。pretty/text 里 `WebP=accepted` 或 `webpInput=accepted` 表示可直接传 webp;`autoConvertToJPG` 表示本地 webp 会先转成 jpg。
56
+ - `media=IMAGE` 的 `supportedFileTypes` 是 webp 能力标记:空表示不支持 webp,单独 `webp` 表示普通图片格式外也支持 webp,多值才表示强允许列表。pretty/text 里 `WebP=accepted` 或 `webpInput=accepted` 表示可直接传 webp;`autoConvertToJPG` 表示本地或可下载远端 webp 会先转成 jpg。
56
57
  - 首帧 / 尾帧不使用 reference_key;是否可传尾帧看 `usage` 是否包含 `last_frame`,具体创建方式看 `model create-spec`。
@@ -31,6 +31,8 @@
31
31
  |------------|------|-----------|--------------|--------|
32
32
  | `credits_balance` | `credits balance` | `billingPointBalance`、`projectBudgetBalance`、`projectBudgetMax` | — | `currentProjectGroupNo` |
33
33
  | `credits_usage` | `credits usage` | `pointTotal`、`scannedTaskCount`、`buckets[]` 汇总 | `tasks[]`(若 `--include-tasks`) | sinceMs/untilMs 原值 |
34
+ | `purchase_guide` | `credits buy` | `purchaseUrl` | — | — |
35
+ | `redeem_result` | `credits redeem` | `redeemed`、`billingPointBalance` | `redemptionCode` | `currentProjectGroupNo` |
34
36
 
35
37
  > 永远优先看 `billingPointBalance`(可扣积分);`projectBudgetBalance` 是项目预算 / ROI 约束,不要混为一谈。
36
38
 
@@ -39,8 +41,8 @@
39
41
  | outputKind | 命令 | 必报给用户 | agent 内部用 | 可丢弃 |
40
42
  |------------|------|-----------|--------------|--------|
41
43
  | `model_list` | `model image-models` / `video-models` | 模型名、`modelGroupCode`、`taskQueueNum`(排队数)、`successRate`(成功率) | `modelGroupCode`(下游 create 必填) | 完整 modelList 嵌套 |
42
- | `model_options` | `model options` | `params[].label/values/defaultValue`、`resources[]`、`constraints[]` | 全部字段(决定 create 入参)。JSON 形状:`params[].{key,label,valueType,values,defaultValue,defaultName}`(参数名是 `key`,**不是** `name`);`resources[].{media,usage,valueShapes,formats,...}`;`constraints[].{target,when,allowedValues,effect,limits}`,其中 `resource_limit_overrides` 表示素材数量 / 时长联动限制 | — |
43
- | `model_create_spec` | `model create-spec` | `intents[]`、`requiredArgs`、`examples` | 全部 | — |
44
+ | `model_options` | `model options` | `params[].label/values/defaultValue/cliArg`、`resources[]`、`constraints[]` | 全部字段(决定 create 入参)。JSON 形状:`params[].{key,label,valueType,values,defaultValue,defaultName,cliArg,genericModelParam}`(参数名是 `key`,**不是** `name`);通用参数用 `--model-param key=value`;`resources[].{media,usage,valueShapes,formats,...}`;`constraints[].{target,when,allowedValues,effect,limits}`,其中 `resource_limit_overrides` 表示素材数量 / 时长联动限制 | — |
45
+ | `model_create_spec` | `model create-spec` | `intents[]`、`requiredArgs`、`examples`、`parameterControls.userParams[]` | 全部 | — |
44
46
  | `model_input_guide` | `model input-guide` | `supportedIntents`、`promptParams`、`resourceUsages` | 全部 | — |
45
47
 
46
48
  ## 文件上传
@@ -54,13 +56,15 @@
54
56
  | outputKind | 命令 | 必报给用户 | agent 内部用 | 可丢弃 |
55
57
  |------------|------|-----------|--------------|--------|
56
58
  | `fee_estimate` | `create image-fee` / `create video-fee` | `pointCost`、`billingPointBalance`、`billingPointRemainingAfter` | — | budget 嵌套 |
57
- | `task_submission` | `create image` / `create video` | `taskId`、`pointCost`、`billingPointRemainingAfter`、`nextCommand` | `taskId`、`taskType`(喂给 `task wait`) | uploads 数组、modelGroupCode |
59
+ | `task_submission` | `create image` / `create video` | `taskId`、`pointCost`、`billingPointRemainingAfter`、`nextCommand`、`statusCommand` | `taskId`、`taskType`(喂给 `task wait`) | uploads 数组、modelGroupCode |
58
60
  | `batch_task_submission` | `create image-batch` / `create video-batch` | 成功 / 失败计数、首条 `taskId` 用于追踪 | `tasks[]` 每条 taskId + status | localFiles 详情 |
61
+ | `fee_estimate` | `create video-super-resolution-fee` | `pointCost`、`billingPointBalance`、`billingPointRemainingAfter` | — | budget 嵌套 |
62
+ | `task_submission` | `create video-super-resolution` | `taskId`、`pointCost`、`billingPointRemainingAfter`、`nextCommand` | `taskId`、`nextCommand`(喂给 `task video-super-resolution-status`) | request 嵌套 |
59
63
  | `task_status` | `task wait` / `task image-status` / `task video-status` | `taskStatus`、`isTerminal`、`resultUrls`、`errorMessage` | `isTerminal`(false → 续 wait)、`timedOut` | `waitedMs`、`gmtCreate` |
60
64
  | `subtitle_task_submission` | `create video-subtitle-removal` | `submitted`、`taskId`、`pointCost`、`nextCommand` | `taskId`、`sourceTaskId` | budget 嵌套 |
61
65
  | `subtitle_task_status` | `task video-subtitle-status` | `taskStatus`、`isTerminal`、`resultUrls`、`errorMessage` | `taskId` | `gmtCreate` |
62
66
 
63
- > `task_submission.nextCommand` 是平台给出的下一步建议命令(通常是 `task wait --task-id ...`)。看到就直接接着跑。
67
+ > `task_submission.nextCommand` 是平台给出的下一步建议命令(通常是 `task wait --task-id ...`);`task_submission.statusCommand` 是单次状态查询命令(通常是 `task image-status` / `task video-status`)。
64
68
 
65
69
  ## 任务台账
66
70
 
@@ -94,7 +98,7 @@
94
98
  | `asset_group_list` | `create asset-groups` | `platform`、`count` + 组名 | `groupId`(下游 register 必填) | — |
95
99
  | `asset_group_detail` | `create asset-group-get` | `platform`、组名、成员数 | `groupId` | — |
96
100
  | `asset_group_write_result` | `create asset-group / group-update` | `created/updated`、`groupId`、`platform` | — | — |
97
- | `asset_register_result` | `create asset` | `registered`、`assetId`、`assetPath`、`platform` | `assetId`(下游引用) | upload 嵌套 |
101
+ | `asset_register_result` | `create asset` | `registered`、`assetId`、`assetPath`、`platform`、`assetType` | `assetId`(下游引用) | upload 嵌套 |
98
102
 
99
103
  ## Artifact(产物 CRUD)
100
104
 
@@ -107,6 +111,7 @@
107
111
  | `artifact_delete_result` | `delete-*` | `deleted`、`key`、级联 | — | — |
108
112
  | `artifact_import_result` | `* import` / `import-storyboard` / `upsert-batch` | `imported`、`rowCount/actorCount/...`、文件计数 | `rowsByKind`(用于断言) | `batch` 数组 |
109
113
  | `artifact_status_update` | `artifact clip update-status` | `updated`、`status` | — | messageCount |
114
+ | `update_result` | `update` / `update --check` | `updateAvailable`、`currentVersion`、`latestVersion`、`command` | `skillUpdated`、`restartRecommended` | 安装日志 |
110
115
 
111
116
  ## Dry-run
112
117
 
@@ -1,10 +1,112 @@
1
1
  #!/usr/bin/env bash
2
2
  set -euo pipefail
3
3
 
4
- if command -v lj-awb >/dev/null 2>&1; then
5
- printf 'lj-awb\n'
6
- exit 0
4
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"
5
+ SKILL_DIR="$(cd "$SCRIPT_DIR/.." >/dev/null 2>&1 && pwd)"
6
+ VERSION_FILE="$SKILL_DIR/VERSION"
7
+ COMPAT_FILE="$SKILL_DIR/compat.json"
8
+
9
+ read_json_string() {
10
+ local key="$1"
11
+ local file="$2"
12
+ sed -n "s/.*\"$key\"[[:space:]]*:[[:space:]]*\"\([^\"]*\)\".*/\1/p" "$file" 2>/dev/null | head -1
13
+ }
14
+
15
+ normalize_version() {
16
+ local version="${1#v}"
17
+ version="${version%%[-+]*}"
18
+ printf '%s' "$version"
19
+ }
20
+
21
+ semver_ge() {
22
+ local current required
23
+ current="$(normalize_version "$1")"
24
+ required="$(normalize_version "$2")"
25
+
26
+ local current_major current_minor current_patch
27
+ local required_major required_minor required_patch
28
+ IFS=. read -r current_major current_minor current_patch <<< "$current"
29
+ IFS=. read -r required_major required_minor required_patch <<< "$required"
30
+
31
+ current_major="${current_major:-0}"
32
+ current_minor="${current_minor:-0}"
33
+ current_patch="${current_patch:-0}"
34
+ required_major="${required_major:-0}"
35
+ required_minor="${required_minor:-0}"
36
+ required_patch="${required_patch:-0}"
37
+
38
+ if (( current_major != required_major )); then
39
+ (( current_major > required_major ))
40
+ return
41
+ fi
42
+ if (( current_minor != required_minor )); then
43
+ (( current_minor > required_minor ))
44
+ return
45
+ fi
46
+ (( current_patch >= required_patch ))
47
+ }
48
+
49
+ find_lj_awb() {
50
+ if command -v lj-awb >/dev/null 2>&1; then
51
+ command -v lj-awb
52
+ return 0
53
+ fi
54
+
55
+ if command -v npm >/dev/null 2>&1; then
56
+ local npm_prefix npm_bin
57
+ npm_prefix="$(npm prefix -g 2>/dev/null || true)"
58
+ npm_bin="$npm_prefix/bin/lj-awb"
59
+ if [ -n "$npm_prefix" ] && [ -x "$npm_bin" ]; then
60
+ printf '%s\n' "$npm_bin"
61
+ return 0
62
+ fi
63
+ fi
64
+
65
+ return 1
66
+ }
67
+
68
+ command_version() {
69
+ local cmd="$1"
70
+ "$cmd" --version 2>/dev/null | grep -Eo 'v?[0-9]+(\.[0-9]+){2}([-+][0-9A-Za-z.-]+)?' | head -1
71
+ }
72
+
73
+ SKILL_VERSION="$(cat "$VERSION_FILE" 2>/dev/null || printf '0.4.0')"
74
+ MIN_CLI_VERSION="$(read_json_string minCliVersion "$COMPAT_FILE")"
75
+ MIN_CLI_VERSION="${MIN_CLI_VERSION:-$SKILL_VERSION}"
76
+ CLI_VERSION="${LINGJING_AWB_CLI_VERSION:-$MIN_CLI_VERSION}"
77
+ CLI_PACKAGE="${LINGJING_AWB_CLI_PACKAGE:-@lingjingai/lj-awb-cli}"
78
+ CLI_PACKAGE_SPEC="${LINGJING_AWB_CLI_PACKAGE_SPEC:-$CLI_PACKAGE@$CLI_VERSION}"
79
+
80
+ if LJ_AWB_CMD="$(find_lj_awb)"; then
81
+ INSTALLED_VERSION="$(command_version "$LJ_AWB_CMD" || true)"
82
+ if [ -n "$INSTALLED_VERSION" ] && semver_ge "$INSTALLED_VERSION" "$MIN_CLI_VERSION"; then
83
+ printf '%s\n' "$LJ_AWB_CMD"
84
+ exit 0
85
+ fi
86
+
87
+ printf 'Found lj-awb %s, but this skill requires >= %s.\n' "${INSTALLED_VERSION:-unknown}" "$MIN_CLI_VERSION" >&2
88
+ fi
89
+
90
+ if [ "${LINGJING_AWB_AUTO_INSTALL:-1}" = "0" ]; then
91
+ printf 'No compatible lj-awb CLI found. Install it first: npm install -g %s\n' "$CLI_PACKAGE_SPEC" >&2
92
+ exit 1
93
+ fi
94
+
95
+ if ! command -v npm >/dev/null 2>&1; then
96
+ printf 'No compatible lj-awb CLI found, and npm is unavailable. Install Node.js >=20 and npm, then run: npm install -g %s\n' "$CLI_PACKAGE_SPEC" >&2
97
+ exit 1
98
+ fi
99
+
100
+ printf 'Installing lj-awb CLI: npm install -g %s\n' "$CLI_PACKAGE_SPEC" >&2
101
+ npm install -g "$CLI_PACKAGE_SPEC" >&2
102
+
103
+ if LJ_AWB_CMD="$(find_lj_awb)"; then
104
+ INSTALLED_VERSION="$(command_version "$LJ_AWB_CMD" || true)"
105
+ if [ -n "$INSTALLED_VERSION" ] && semver_ge "$INSTALLED_VERSION" "$MIN_CLI_VERSION"; then
106
+ printf '%s\n' "$LJ_AWB_CMD"
107
+ exit 0
108
+ fi
7
109
  fi
8
110
 
9
- printf 'No usable lj-awb CLI found. Install `@lingjingai/lj-awb-cli` first.\n' >&2
111
+ printf 'Installed %s, but lj-awb is still not available on PATH. Check npm global bin path, then retry.\n' "$CLI_PACKAGE_SPEC" >&2
10
112
  exit 1