@lingjingai/lj-awb-cli-pre 0.3.18 → 0.4.5

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.
Files changed (35) hide show
  1. package/README.md +57 -8
  2. package/build/_shared.mjs +54 -5
  3. package/build/prod.mjs +12 -3
  4. package/package.json +6 -2
  5. package/packages/awb-cli/package.json +2 -2
  6. package/packages/awb-core/package.json +6 -2
  7. package/packages/awb-core/src/api.js +22 -0
  8. package/packages/awb-core/src/commands.js +112 -39
  9. package/packages/awb-core/src/common.js +8 -0
  10. package/packages/awb-core/src/output.js +2030 -8
  11. package/packages/awb-core/src/services.js +1835 -205
  12. package/packages/awb-core/src/standalone.js +472 -136
  13. package/packages/awb-core/src/update.js +327 -0
  14. package/skills/lj-awb/SKILL.md +35 -12
  15. package/skills/lj-awb/VERSION +1 -1
  16. package/skills/lj-awb/compat.json +3 -3
  17. package/skills/lj-awb/modules/artifact/asset.md +1 -1
  18. package/skills/lj-awb/modules/artifact/clip.md +1 -1
  19. package/skills/lj-awb/modules/artifact/script.md +1 -1
  20. package/skills/lj-awb/modules/artifact/video.md +1 -1
  21. package/skills/lj-awb/modules/asset.md +10 -1
  22. package/skills/lj-awb/modules/auth.md +9 -1
  23. package/skills/lj-awb/modules/create-contract.md +5 -2
  24. package/skills/lj-awb/modules/create.md +4 -2
  25. package/skills/lj-awb/modules/driver.md +12 -6
  26. package/skills/lj-awb/modules/image.md +3 -1
  27. package/skills/lj-awb/modules/model.md +12 -9
  28. package/skills/lj-awb/modules/task.md +4 -1
  29. package/skills/lj-awb/modules/upload.md +1 -1
  30. package/skills/lj-awb/modules/video.md +11 -2
  31. package/skills/lj-awb/modules/workflows.md +3 -1
  32. package/skills/lj-awb/references/error-codes.md +24 -0
  33. package/skills/lj-awb/references/model-options-read.md +16 -10
  34. package/skills/lj-awb/references/output-fields.md +10 -7
  35. package/skills/lj-awb/scripts/resolve-lj-awb-cmd.sh +106 -4
@@ -2,6 +2,7 @@ import { fetchProjectGroupUsers, fetchTeams, fetchUserInfo } from './api.js';
2
2
  import * as artifact from './artifact.js';
3
3
  import { clearAuth, loadAuth, saveAccessKey, summarizeAuth } from './auth.js';
4
4
  import { LingjingAwbCliError, maskSecret, toBool, trimSecret } from './common.js';
5
+ import { runCliUpdate } from './update.js';
5
6
  import {
6
7
  assetGroupCreate,
7
8
  assetGroupGet,
@@ -10,6 +11,8 @@ import {
10
11
  assetMatchActor,
11
12
  assetReviewModels,
12
13
  assetRegister,
14
+ authLogin,
15
+ authLogout,
13
16
  creditsBalance,
14
17
  creditsUsageSummary,
15
18
  createProjectGroupCommand,
@@ -39,6 +42,9 @@ import {
39
42
  subjectWait,
40
43
  subtitleRemove,
41
44
  subtitleStatus,
45
+ videoSuperResolution,
46
+ videoSuperResolutionFee,
47
+ videoSuperResolutionStatus,
42
48
  taskList,
43
49
  taskRecordPoll,
44
50
  taskRecords,
@@ -85,6 +91,9 @@ const MODEL_LIST_ARGS = [
85
91
  const TASK_RECORD_ARG = { name: 'task-record-file', valueName: 'path', description: '任务台账 JSONL 文件;也可用 LINGJING_AWB_TASK_RECORD_FILE' };
86
92
  const RESOURCE_ARG = { name: 'resource', valueName: 'spec', description: '统一素材,格式 type:usage[:key]=path|url|asset,可重复传;音频参考用 audio:reference=./music.mp3' };
87
93
  const RESOURCES_JSON_ARG = { name: 'resources-json', valueName: 'json|path', description: 'resources 数组 JSON 或 JSON 文件路径' };
94
+ const MODEL_PARAM_ARG = { name: 'model-param', valueName: 'key=value', description: '通用模型配置参数,可重复传;key 来自 model options.params[],例如 generation_effort=high' };
95
+ const MODEL_PARAMS_JSON_ARG = { name: 'model-params-json', valueName: 'json|path', description: '通用模型配置参数对象 JSON 或 JSON 文件路径;显式 --ratio/--quality 等命令参数优先' };
96
+ const MODEL_PARAM_ARGS = [MODEL_PARAM_ARG, MODEL_PARAMS_JSON_ARG];
88
97
  const CREATE_WAIT_ARGS = [
89
98
  { name: 'wait-seconds', valueName: 'seconds', description: '提交后顺带等待结果的秒数;默认 0 不等待' },
90
99
  { name: 'poll-interval-ms', valueName: 'ms', description: '任务轮询间隔毫秒数,默认 5000' },
@@ -125,6 +134,25 @@ export function registerAwbCommands(cli) {
125
134
  func: async (_ctx, kwargs) => doctor(kwargs),
126
135
  });
127
136
 
137
+ cli({
138
+ name: 'update',
139
+ description: commandHelp('检查并更新 CLI 到最新版本;默认只在需要时安装新版本', {
140
+ examples: [
141
+ 'lj-awb update --check',
142
+ 'lj-awb update',
143
+ 'lj-awb update --force',
144
+ ],
145
+ hint: '普通命令只会做非阻塞更新检查;真正安装请显式运行 update。',
146
+ }),
147
+ args: [
148
+ { name: 'check', description: '只检查是否有新版本,不安装' },
149
+ { name: 'force', description: '强制重新检查并执行安装,忽略缓存' },
150
+ { name: 'registry', valueName: 'url', description: 'npm registry 地址;默认读取环境变量或 npm 默认 registry' },
151
+ { name: 'package-name', valueName: 'name', description: '要更新的包名;默认自动识别当前 CLI 包' },
152
+ ],
153
+ func: async (_ctx, kwargs) => runCliUpdate(kwargs),
154
+ });
155
+
128
156
  cli({
129
157
  name: 'auth status',
130
158
  description: commandHelp('查看本地 access key 是否已配置;不联网', {
@@ -163,50 +191,27 @@ export function registerAwbCommands(cli) {
163
191
 
164
192
  cli({
165
193
  name: 'auth login',
166
- description: commandHelp('登录:使用 access key 校验身份,并保存到本地认证文件', {
194
+ description: commandHelp('登录:默认走浏览器授权登录;也支持直接传 access key 保存', {
167
195
  examples: [
196
+ 'lj-awb auth login',
197
+ 'lj-awb auth login --no-wait',
198
+ 'lj-awb auth login --flow-id <flowId>',
168
199
  'lj-awb auth login --access-key <key>',
169
200
  'LINGJING_AWB_ACCESS_KEY=<key> lj-awb auth login',
170
201
  'lj-awb auth login --access-key <key> --skip-verify',
171
202
  ],
172
- hint: '不要写成 lj-awb auth <key>。不传 --access-key 时只读取 LINGJING_AWB_ACCESS_KEY 环境变量。',
203
+ hint: '不传 --access-key(且无 LINGJING_AWB_ACCESS_KEY 环境变量)时走浏览器授权:创建登录任务、展示链接、轮询直到授权成功并自动保存 access key。命令最长阻塞约 10 分钟;AI agent 可先用 --no-wait --json flow_id,再用 --flow-id <id> 续轮询,不要重复发起新的 login。',
173
204
  }),
174
205
  args: [
175
- { name: 'access-key', valueName: 'key', description: '平台 access key;不传时读取环境变量' },
206
+ { name: 'access-key', valueName: 'key', description: '平台 access key;传了则跳过浏览器授权直接保存,不传时读取环境变量' },
207
+ { name: 'flow-id', valueName: 'flowId', description: '复用已有登录任务的 flow_id 继续轮询;不传则新建登录任务' },
208
+ { name: 'no-wait', description: '只创建登录任务并返回 flow_id / verify_url,不阻塞轮询;适合 AI agent / 脚本' },
209
+ { name: 'wait-seconds', valueName: 'seconds', description: '浏览器授权最长轮询秒数,默认 600' },
210
+ { name: 'poll-interval-ms', valueName: 'ms', description: '授权状态轮询间隔毫秒数,默认 3000' },
176
211
  { name: 'skip-verify', description: '只保存 key,不调用 userInfo 校验;仅用于本地调试' },
177
212
  DRY_RUN_ARG,
178
213
  ],
179
- func: async (_ctx, kwargs) => {
180
- const skipVerify = toBool(kwargs.skipVerify);
181
- const accessKey = trimSecret(kwargs.accessKey || process.env.LINGJING_AWB_ACCESS_KEY || '');
182
- if (!accessKey) {
183
- throw new LingjingAwbCliError('缺少 access key', {
184
- type: 'argument_error',
185
- exitCode: 2,
186
- hint: '传 --access-key <key>,或设置 LINGJING_AWB_ACCESS_KEY 环境变量。',
187
- });
188
- }
189
- if (toBool(kwargs.dryRun)) {
190
- return {
191
- dryRun: true,
192
- saved: false,
193
- verified: false,
194
- accessKey: maskSecret(accessKey),
195
- };
196
- }
197
- let user = null;
198
- if (!skipVerify) {
199
- process.env.LINGJING_AWB_ACCESS_KEY = accessKey;
200
- user = normalizeUserInfo(await fetchUserInfo());
201
- }
202
- const { auth } = await saveAccessKey(accessKey, { verified: !skipVerify });
203
- return {
204
- auth: summarizeAuth(auth, { accessKey, source: 'saved', sourceName: 'auth' }),
205
- accessKey: maskSecret(accessKey),
206
- verified: !skipVerify,
207
- user,
208
- };
209
- },
214
+ func: async (_ctx, kwargs) => authLogin(kwargs),
210
215
  });
211
216
 
212
217
  cli({
@@ -224,6 +229,16 @@ export function registerAwbCommands(cli) {
224
229
  },
225
230
  });
226
231
 
232
+ cli({
233
+ name: 'auth logout',
234
+ description: commandHelp('退出登录:清除本地保存的 access key', {
235
+ examples: ['lj-awb auth logout'],
236
+ hint: '只清本地认证文件,不清当前 shell 中的 LINGJING_AWB_ACCESS_KEY 环境变量;下次使用前重新运行 lj-awb auth login。',
237
+ }),
238
+ args: [],
239
+ func: async () => authLogout(),
240
+ });
241
+
227
242
  cli({
228
243
  name: 'account info',
229
244
  description: commandHelp('查看当前 AWB 用户、团队、项目组和积分摘要', {
@@ -497,10 +512,12 @@ export function registerAwbCommands(cli) {
497
512
  { name: 'ratio', valueName: 'ratio', description: '画幅比例,如 9:16' },
498
513
  { name: 'quality', valueName: 'quality', description: '清晰度,如 2K' },
499
514
  { name: 'generate-num', valueName: 'n', description: '生成张数' },
515
+ ...MODEL_PARAM_ARGS,
500
516
  RESOURCE_ARG,
501
517
  RESOURCES_JSON_ARG,
502
518
  FEE_DRY_RUN_ARG,
503
519
  ],
520
+ allowDynamicModelParams: true,
504
521
  func: async (_ctx, kwargs) => imageFee(kwargs),
505
522
  });
506
523
 
@@ -521,6 +538,7 @@ export function registerAwbCommands(cli) {
521
538
  { name: 'ratio', valueName: 'ratio', description: '画幅比例' },
522
539
  { name: 'quality', valueName: 'quality', description: '清晰度' },
523
540
  { name: 'generate-num', valueName: 'n', description: '生成张数' },
541
+ ...MODEL_PARAM_ARGS,
524
542
  RESOURCE_ARG,
525
543
  RESOURCES_JSON_ARG,
526
544
  TASK_RECORD_ARG,
@@ -528,6 +546,7 @@ export function registerAwbCommands(cli) {
528
546
  DRY_RUN_ARG,
529
547
  YES_ARG,
530
548
  ],
549
+ allowDynamicModelParams: true,
531
550
  func: async (_ctx, kwargs) => imageCreate(kwargs),
532
551
  });
533
552
 
@@ -538,17 +557,19 @@ export function registerAwbCommands(cli) {
538
557
  'lj-awb create image-batch --input-file ./prompts.txt --model-group-code <code> --dry-run',
539
558
  'lj-awb create image-batch --input-file ./image-input.jsonl --model-group-code <code> --concurrency 3 --yes',
540
559
  ],
541
- hint: 'JSON/JSONL 每项只写任务差异字段:prompt、ratio、quality、generate_num、resources、resource、customBizId',
560
+ hint: 'JSON/JSONL 每项只写任务差异字段:prompt、ratio、quality、generate_num、resources、resource、model_params、customBizId;新增模型配置参数也可直接写入每项。',
542
561
  }),
543
562
  args: [
544
563
  { name: 'input-file', valueName: 'path', description: '批量输入文件' },
545
564
  MODEL_GROUP_ARG,
546
565
  PROJECT_GROUP_ARG,
566
+ ...MODEL_PARAM_ARGS,
547
567
  { name: 'concurrency', valueName: 'n', description: '并发数,默认 1' },
548
568
  TASK_RECORD_ARG,
549
569
  DRY_RUN_ARG,
550
570
  YES_ARG,
551
571
  ],
572
+ allowDynamicModelParams: true,
552
573
  func: async (_ctx, kwargs) => imageCreateBatch(kwargs),
553
574
  });
554
575
 
@@ -577,10 +598,12 @@ export function registerAwbCommands(cli) {
577
598
  { name: 'quality', valueName: 'quality', description: '清晰度,如 720' },
578
599
  { name: 'duration', valueName: 'seconds', description: '生成时长秒数' },
579
600
  { name: 'need-audio', valueName: 'bool', description: '输出音效开关:是否让模型在视频中生成音效(true/false)。不接收音频文件;参考音频请用 --resource audio:reference=...' },
601
+ ...MODEL_PARAM_ARGS,
580
602
  RESOURCE_ARG,
581
603
  RESOURCES_JSON_ARG,
582
604
  FEE_DRY_RUN_ARG,
583
605
  ],
606
+ allowDynamicModelParams: true,
584
607
  func: async (_ctx, kwargs) => videoFee(kwargs),
585
608
  });
586
609
 
@@ -604,6 +627,7 @@ export function registerAwbCommands(cli) {
604
627
  { name: 'quality', valueName: 'quality', description: '清晰度' },
605
628
  { name: 'duration', valueName: 'seconds', description: '生成时长秒数' },
606
629
  { name: 'need-audio', valueName: 'bool', description: '输出音效开关:是否让模型在视频中生成音效(true/false)。不接收音频文件;参考音频请用 --resource audio:reference=...' },
630
+ ...MODEL_PARAM_ARGS,
607
631
  RESOURCE_ARG,
608
632
  RESOURCES_JSON_ARG,
609
633
  TASK_RECORD_ARG,
@@ -611,6 +635,7 @@ export function registerAwbCommands(cli) {
611
635
  DRY_RUN_ARG,
612
636
  YES_ARG,
613
637
  ],
638
+ allowDynamicModelParams: true,
614
639
  func: async (_ctx, kwargs) => videoCreate(kwargs),
615
640
  });
616
641
 
@@ -621,17 +646,19 @@ export function registerAwbCommands(cli) {
621
646
  'lj-awb create video-batch --input-file ./prompts.txt --model-group-code <code> --dry-run',
622
647
  'lj-awb create video-batch --input-file ./video-input.jsonl --model-group-code <code> --concurrency 2 --yes',
623
648
  ],
624
- hint: 'JSON/JSONL 每项只写任务差异字段:prompt、ratio、quality、duration、need_audio、resources、resource、customBizId',
649
+ hint: 'JSON/JSONL 每项只写任务差异字段:prompt、ratio、quality、duration、need_audio、resources、resource、model_params、customBizId;新增模型配置参数也可直接写入每项。',
625
650
  }),
626
651
  args: [
627
652
  { name: 'input-file', valueName: 'path', description: '批量输入文件' },
628
653
  MODEL_GROUP_ARG,
629
654
  PROJECT_GROUP_ARG,
655
+ ...MODEL_PARAM_ARGS,
630
656
  { name: 'concurrency', valueName: 'n', description: '并发数,默认 1' },
631
657
  TASK_RECORD_ARG,
632
658
  DRY_RUN_ARG,
633
659
  YES_ARG,
634
660
  ],
661
+ allowDynamicModelParams: true,
635
662
  func: async (_ctx, kwargs) => videoCreateBatch(kwargs),
636
663
  });
637
664
 
@@ -660,6 +687,35 @@ export function registerAwbCommands(cli) {
660
687
  func: async (_ctx, kwargs) => subtitleRemove(kwargs),
661
688
  });
662
689
 
690
+ cli({
691
+ name: 'create video-super-resolution-fee',
692
+ description: commandHelp('计算视频超分预计积分;传入 objectName', {
693
+ examples: ['lj-awb create video-super-resolution-fee --object-name material/video-super/example.mp4 --project-group-no <no>'],
694
+ hint: 'objectName 通常是 material backendPath 或 COS 对象路径;正式超分前先看一次估价。',
695
+ }),
696
+ args: [
697
+ { name: 'object-name', valueName: 'path', description: '视频对象路径;通常是 material backendPath 或 COS 对象路径' },
698
+ PROJECT_GROUP_ARG,
699
+ ],
700
+ func: async (_ctx, kwargs) => videoSuperResolutionFee(kwargs),
701
+ });
702
+
703
+ cli({
704
+ name: 'create video-super-resolution',
705
+ description: commandHelp('基于 objectName 提交视频超分任务', {
706
+ examples: ['lj-awb create video-super-resolution --object-name material/video-super/example.mp4 --project-group-no <no> --dry-run'],
707
+ hint: '正式执行需要 --yes;会先按 objectName 读取视频信息,再选择 1080P / 2K 模型组。',
708
+ }),
709
+ args: [
710
+ { name: 'object-name', valueName: 'path', description: '视频对象路径;通常是 material backendPath 或 COS 对象路径' },
711
+ PROJECT_GROUP_ARG,
712
+ TASK_RECORD_ARG,
713
+ DRY_RUN_ARG,
714
+ YES_ARG,
715
+ ],
716
+ func: async (_ctx, kwargs) => videoSuperResolution(kwargs),
717
+ });
718
+
663
719
  cli({
664
720
  name: 'task video-subtitle-status',
665
721
  description: commandHelp('查询 material 去字幕任务状态', {
@@ -672,13 +728,25 @@ export function registerAwbCommands(cli) {
672
728
  func: async (_ctx, kwargs) => subtitleStatus(kwargs),
673
729
  });
674
730
 
731
+ cli({
732
+ name: 'task video-super-resolution-status',
733
+ description: commandHelp('查询 material 视频超分任务状态', {
734
+ examples: ['lj-awb task video-super-resolution-status --task-id <superResolutionTaskId>'],
735
+ }),
736
+ args: [
737
+ { name: 'task-id', valueName: 'id', description: 'material 视频超分任务 ID' },
738
+ PROJECT_GROUP_ARG,
739
+ ],
740
+ func: async (_ctx, kwargs) => videoSuperResolutionStatus(kwargs),
741
+ });
742
+
675
743
  cli({
676
744
  name: 'task list',
677
745
  description: commandHelp('查询项目组近期任务流', {
678
746
  examples: ['lj-awb task list --task-type IMAGE_CREATE --project-group-no <no>'],
679
747
  }),
680
748
  args: [
681
- { name: 'task-type', valueName: 'type', description: 'IMAGE_CREATE / IMAGE_EDIT / VIDEO_GROUP' },
749
+ { name: 'task-type', valueName: 'type', description: 'IMAGE_CREATE / IMAGE_EDIT / VIDEO_GROUP / VIDEO_SUPER_RESOLUTION / VIDEO_SUBTITLE_REMOVAL' },
682
750
  PROJECT_GROUP_ARG,
683
751
  { name: 'page-size', valueName: 'n', description: '每页任务数' },
684
752
  { name: 'min-time', valueName: 'ms', description: '任务流 minTime,默认当前时间' },
@@ -694,7 +762,7 @@ export function registerAwbCommands(cli) {
694
762
  }),
695
763
  args: [
696
764
  { name: 'task-id', valueName: 'id', description: '任务 ID' },
697
- { name: 'task-type', valueName: 'type', description: 'IMAGE_CREATE / VIDEO_GROUP' },
765
+ { name: 'task-type', valueName: 'type', description: 'IMAGE_CREATE / VIDEO_GROUP;material 扩展任务优先用 task video-subtitle-status / task video-super-resolution-status' },
698
766
  PROJECT_GROUP_ARG,
699
767
  ...TASK_WAIT_ARGS,
700
768
  ],
@@ -811,7 +879,11 @@ export function registerAwbCommands(cli) {
811
879
  cli({
812
880
  name: 'create asset',
813
881
  description: commandHelp('把 COS 路径 / URL / 本地文件注册成平台素材', {
814
- examples: ['lj-awb create asset --group-id <id> --platform JIMENG --url "asset-review/upload/a.png" --name "女主正面" --dry-run'],
882
+ examples: [
883
+ 'lj-awb create asset --group-id <id> --platform JIMENG --url "asset-review/upload/a.png" --name "女主正面" --dry-run',
884
+ 'lj-awb create asset --group-id <id> --platform JIMENG --file ./clip.mp4 --name "参考视频" --dry-run',
885
+ ],
886
+ hint: 'CLI 会按扩展名自动设置 assetType=Image/Video/Audio;本地文件会用 ffprobe 预校验图片/视频尺寸、视频时长/FPS/像素数和音频时长,缺少 ffprobe/ffmpeg 时 macOS + Homebrew 会自动安装 ffmpeg。',
815
887
  }),
816
888
  args: [
817
889
  { name: 'group-id', valueName: 'id', description: '素材组 ID' },
@@ -819,6 +891,7 @@ export function registerAwbCommands(cli) {
819
891
  { name: 'file', valueName: 'path', description: '本地素材文件;会先上传' },
820
892
  { name: 'url', valueName: 'url', description: '素材 URL 或 COS 路径' },
821
893
  { name: 'backend-path', valueName: 'path', description: 'upload files 返回的 backendPath' },
894
+ { name: 'auto-convert', description: '本地素材不符合加白规格时自动转换为合法规格后继续' },
822
895
  ASSET_PLATFORM_ARG,
823
896
  DRY_RUN_ARG,
824
897
  YES_ARG,
@@ -318,11 +318,19 @@ export function guessMimeType(filePath) {
318
318
  return 'image/png';
319
319
  case '.jpg':
320
320
  case '.jpeg':
321
+ case '.jfif':
321
322
  return 'image/jpeg';
323
+ case '.tif':
324
+ case '.tiff':
325
+ return 'image/tiff';
322
326
  case '.webp':
323
327
  return 'image/webp';
324
328
  case '.gif':
325
329
  return 'image/gif';
330
+ case '.heic':
331
+ return 'image/heic';
332
+ case '.heif':
333
+ return 'image/heif';
326
334
  case '.mp3':
327
335
  return 'audio/mpeg';
328
336
  case '.wav':