@lingjingai/lj-awb-cli-pre 0.3.15 → 0.3.16

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.
@@ -28,6 +28,8 @@ const OPTION_SYNONYMS = {
28
28
  in: ['inputFile'],
29
29
  dry: ['dryRun'],
30
30
  force: ['yes'],
31
+ remoteTaskId: ['taskId'],
32
+ publicId: ['taskId'],
31
33
  };
32
34
 
33
35
  function levenshtein(a, b) {
@@ -202,14 +204,14 @@ const VIRTUAL_COMMANDS = [
202
204
  '',
203
205
  'Examples:',
204
206
  ' lj-awb schema -f json',
205
- ' lj-awb schema --domain video -f json',
206
- ' lj-awb schema --domain image --command create -f json',
207
+ ' lj-awb schema --domain create -f json',
208
+ ' lj-awb schema --domain create --command image -f json',
207
209
  '',
208
210
  'Hint: Agent 应优先读取 schema,而不是解析自然语言 help。',
209
211
  ].join('\n'),
210
212
  args: [
211
- { name: 'domain', valueName: 'name', description: '按命令域过滤,如 image / video / task / system' },
212
- { name: 'command', valueName: 'name', description: '按子命令过滤,如 create / wait / doctor' },
213
+ { name: 'domain', valueName: 'name', description: '按命令域过滤,如 create / task / artifact / system' },
214
+ { name: 'command', valueName: 'name', description: '按子命令过滤,如 image / video / wait / doctor' },
213
215
  ],
214
216
  },
215
217
  ];
@@ -295,13 +297,10 @@ const GROUP_DESCRIPTIONS = {
295
297
  project: '项目:查看、切换、创建和更新项目组',
296
298
  credits: '积分:查询可扣积分余额、项目组预算和用量统计',
297
299
  model: '模型:查询生图 / 生视频模型、参数约束和创建用法',
300
+ create: '创建:统一提交图片、视频、主体、音色、素材和视频去字幕任务',
298
301
  upload: '上传:把本地文件上传为平台可访问素材',
299
- image: '图片:估价、提交、批量提交和查询生图任务',
300
- video: '视频:估价、提交、批量提交、查询和去字幕',
301
302
  task: '任务:任务列表、等待和本地任务台账',
302
- asset: '资产:素材库匹配、素材组和素材注册',
303
303
  artifact: '最终产物:剧本、资产、视频、剪辑 CRUD 与本地 JSON 导入',
304
- subject: '主体:发布和查询可复用主体资产',
305
304
  };
306
305
 
307
306
  const SUBGROUP_DESCRIPTIONS = {
@@ -341,7 +340,7 @@ const GROUP_EXAMPLES = {
341
340
  'lj-awb doctor',
342
341
  'lj-awb doctor --verify',
343
342
  'lj-awb schema -f json',
344
- 'lj-awb schema --domain video -f json',
343
+ 'lj-awb schema --domain create -f json',
345
344
  ],
346
345
  auth: [
347
346
  'lj-awb auth status',
@@ -375,36 +374,30 @@ const GROUP_EXAMPLES = {
375
374
  upload: [
376
375
  'lj-awb upload files --files ./a.png,./b.mp4 --dry-run',
377
376
  ],
378
- image: [
379
- 'lj-awb image fee --model-group-code <code> --prompt "一只小狗"',
380
- 'lj-awb image create --model-group-code <code> --prompt "一只小狗" --dry-run',
381
- 'lj-awb image status --task-id <id>',
382
- ],
383
- video: [
384
- 'lj-awb video fee --model-group-code <code> --prompt "雨夜奔跑" --duration 5',
385
- 'lj-awb video create --model-group-code <code> --prompt "镜头推进" --resource image:first_frame=./actor.png --dry-run',
386
- 'lj-awb video create --model-group-code <code> --prompt "镜头推进" --resource image:first_frame=asset:<assetId> --dry-run',
387
- 'lj-awb video subtitle-status --remote-task-id <id>',
377
+ create: [
378
+ 'lj-awb create image --model-group-code <code> --prompt "一只小狗" --dry-run',
379
+ 'lj-awb create image-fee --model-group-code <code> --prompt "一只小狗"',
380
+ 'lj-awb create video --model-group-code <code> --prompt "镜头推进" --resource image:first_frame=./actor.png --dry-run',
381
+ 'lj-awb create video-fee --model-group-code <code> --prompt "雨夜奔跑" --duration 5',
382
+ 'lj-awb create subject --model-code tx --name 女主 --resource primary:./three-view.png --dry-run',
383
+ 'lj-awb create subject-wait --element-id <elementId> --wait-seconds 300',
384
+ 'lj-awb create asset --group-id <id> --file ./actor.png --name "女主正面" --dry-run',
385
+ 'lj-awb create asset-groups --name "女主"',
388
386
  ],
389
387
  task: [
390
388
  'lj-awb task list --task-type IMAGE_CREATE --project-group-no <no>',
389
+ 'lj-awb task image-status --task-id <imageTaskId>',
390
+ 'lj-awb task video-status --task-id <videoTaskId>',
391
+ 'lj-awb task video-subtitle-status --task-id <subtitleTaskId>',
391
392
  'lj-awb task wait --task-id <id> --task-type IMAGE_CREATE --wait-seconds 180',
392
393
  'lj-awb task records --task-record-file .awb/tasks.jsonl',
393
394
  ],
394
- asset: [
395
- 'lj-awb asset match-actor --description "十八岁少女,古风" --tags-json \'{"gender":"女"}\'',
396
- 'lj-awb asset group-create --name "女主素材组" --dry-run',
397
- ],
398
395
  artifact: [
399
396
  'lj-awb artifact script import --project-id <projectId> --input-file 1_script/output/script.json --dry-run',
400
397
  'lj-awb artifact asset import --project-id <projectId> --input-dir 2_asset/output --dry-run',
401
398
  'lj-awb artifact video import-storyboard --project-id <projectId> --input-file 3_footage/output/ep001/ep001_storyboard.json --dry-run',
402
399
  'lj-awb artifact clip upsert-episode --project-id <projectId> --input-file 4_clip/output/ep001_clip_output.json --dry-run',
403
400
  ],
404
- subject: [
405
- 'lj-awb subject list --name "女主"',
406
- 'lj-awb subject publish --name 女主 --resource primary:./three-view.png --dry-run',
407
- ],
408
401
  };
409
402
 
410
403
  const COMMAND_REQUIRED_OPTIONS = {
@@ -413,21 +406,21 @@ const COMMAND_REQUIRED_OPTIONS = {
413
406
  'project ensure': ['name'],
414
407
  'model options': ['modelGroupCode'],
415
408
  'model create-spec': ['modelGroupCode'],
416
- 'image fee': ['modelGroupCode', 'prompt'],
417
- 'image create': ['modelGroupCode', 'prompt'],
418
- 'image create-batch': ['inputFile', 'modelGroupCode'],
419
- 'image status': ['taskId'],
420
- 'video fee': ['modelGroupCode'],
421
- 'video create': ['modelGroupCode'],
422
- 'video create-batch': ['inputFile', 'modelGroupCode'],
423
- 'video status': ['taskId'],
424
- 'video subtitle-remove': ['videoUrl'],
409
+ 'create image-fee': ['modelGroupCode', 'prompt'],
410
+ 'create image': ['modelGroupCode', 'prompt'],
411
+ 'create image-batch': ['inputFile', 'modelGroupCode'],
412
+ 'task image-status': ['taskId'],
413
+ 'create video-fee': ['modelGroupCode'],
414
+ 'create video': ['modelGroupCode'],
415
+ 'create video-batch': ['inputFile', 'modelGroupCode'],
416
+ 'task video-status': ['taskId'],
417
+ 'task video-subtitle-status': ['taskId'],
425
418
  'task wait': ['taskId', 'taskType'],
426
- 'asset match-actor': ['description'],
427
- 'asset group': ['groupId'],
428
- 'asset group-create': ['name'],
429
- 'asset group-update': ['groupId'],
430
- 'asset register': ['groupId', 'name'],
419
+ 'create asset-match-actor': ['description'],
420
+ 'create asset-group-get': ['groupId'],
421
+ 'create asset-group': ['name'],
422
+ 'create asset-group-update': ['groupId'],
423
+ 'create asset': ['groupId', 'name'],
431
424
  'artifact script row': ['rowKind', 'entityKey'],
432
425
  'artifact script children': ['parentKey'],
433
426
  'artifact script delete-row': ['rowKind', 'entityKey'],
@@ -459,18 +452,20 @@ const COMMAND_REQUIRED_OPTIONS = {
459
452
  'artifact clip episode-by-id': ['episodeId'],
460
453
  'artifact clip update-status': ['videoEpisodeId', 'status'],
461
454
  'artifact clip delete-episode': ['videoEpisodeId'],
462
- 'subject publish': ['name'],
463
- 'subject wait': ['elementId'],
464
- 'subject publish-batch': ['inputFile'],
455
+ 'create subject': ['name'],
456
+ 'create subject-wait': ['elementId'],
457
+ 'create subject-voice': ['name'],
458
+ 'create subject-batch': ['inputFile'],
465
459
  };
466
460
 
467
461
  const COMMAND_REQUIRED_ANY_OPTIONS = {
468
462
  'project update': [['name', 'point']],
469
463
  'upload files': [['file', 'files', 'filesJson']],
470
- 'video fee': [['prompt', 'resource', 'resourcesJson']],
471
- 'video create': [['prompt', 'resource', 'resourcesJson']],
472
- 'asset group-update': [['name', 'description', 'projectName']],
473
- 'asset register': [['file', 'url', 'backendPath']],
464
+ 'create video-fee': [['prompt', 'resource', 'resourcesJson']],
465
+ 'create video': [['prompt', 'resource', 'resourcesJson']],
466
+ 'create video-subtitle-removal': [['sourceTaskId']],
467
+ 'create asset-group-update': [['name', 'description', 'projectName']],
468
+ 'create asset': [['file', 'url', 'backendPath']],
474
469
  'artifact script upsert-row': [['bodyJson', 'inputFile']],
475
470
  'artifact asset upsert-actor': [['bodyJson', 'inputFile']],
476
471
  'artifact asset upsert-prop': [['bodyJson', 'inputFile']],
@@ -483,7 +478,10 @@ const COMMAND_REQUIRED_ANY_OPTIONS = {
483
478
  'artifact video upsert-clip': [['bodyJson', 'inputFile']],
484
479
  'artifact clip upsert-episode': [['bodyJson', 'inputFile']],
485
480
  'artifact clip upsert-batch': [['bodyJson', 'inputFile']],
486
- 'subject publish': [['resource']],
481
+ 'create subject': [['resource'], ['modelCode']],
482
+ 'create subject-batch': [['modelCode']],
483
+ 'create subject-voice': [['file', 'voiceUrl', 'audioUrl', 'videoId']],
484
+ 'create subject-voice-wait': [['voiceRecordId', 'reqTaskId']],
487
485
  };
488
486
 
489
487
  const ARTIFACT_WRITE_COMMANDS = [
@@ -526,24 +524,26 @@ const CONFIRMATION_COMMANDS = new Set([
526
524
  'project create',
527
525
  'project update',
528
526
  'project ensure',
529
- 'image create',
530
- 'image create-batch',
531
- 'video create',
532
- 'video create-batch',
533
- 'video subtitle-remove',
534
- 'asset group-create',
535
- 'asset group-update',
536
- 'asset register',
527
+ 'create image',
528
+ 'create image-batch',
529
+ 'create video',
530
+ 'create video-batch',
531
+ 'create video-subtitle-removal',
532
+ 'create asset-group',
533
+ 'create asset-group-update',
534
+ 'create asset',
537
535
  ...ARTIFACT_WRITE_COMMANDS,
538
- 'subject publish',
539
- 'subject publish-batch',
536
+ 'create subject',
537
+ 'create subject-voice',
538
+ 'create subject-batch',
540
539
  ]);
541
540
 
542
541
  const COST_COMMANDS = new Set([
543
- 'image create',
544
- 'image create-batch',
545
- 'video create',
546
- 'video create-batch',
542
+ 'create image',
543
+ 'create image-batch',
544
+ 'create video',
545
+ 'create video-batch',
546
+ 'create video-subtitle-removal',
547
547
  ]);
548
548
 
549
549
  const REMOTE_WRITE_COMMANDS = new Set([
@@ -553,17 +553,18 @@ const REMOTE_WRITE_COMMANDS = new Set([
553
553
  'project update',
554
554
  'project ensure',
555
555
  'upload files',
556
- 'image create',
557
- 'image create-batch',
558
- 'video create',
559
- 'video create-batch',
560
- 'video subtitle-remove',
561
- 'asset group-create',
562
- 'asset group-update',
563
- 'asset register',
556
+ 'create image',
557
+ 'create image-batch',
558
+ 'create video',
559
+ 'create video-batch',
560
+ 'create video-subtitle-removal',
561
+ 'create asset-group',
562
+ 'create asset-group-update',
563
+ 'create asset',
564
564
  ...ARTIFACT_WRITE_COMMANDS,
565
- 'subject publish',
566
- 'subject publish-batch',
565
+ 'create subject',
566
+ 'create subject-voice',
567
+ 'create subject-batch',
567
568
  ]);
568
569
 
569
570
  const LOCAL_STATE_WRITE_COMMANDS = new Set([
@@ -575,7 +576,7 @@ const LOCAL_STATE_WRITE_COMMANDS = new Set([
575
576
  ]);
576
577
 
577
578
  const DESTRUCTIVE_COMMANDS = new Set(['auth clear', ...ARTIFACT_DELETE_COMMANDS]);
578
- const LONG_RUNNING_COMMANDS = new Set(['task wait', 'task record-poll', 'subject wait']);
579
+ const LONG_RUNNING_COMMANDS = new Set(['task wait', 'task record-poll', 'create subject-wait', 'create subject-voice-wait']);
579
580
  const NETWORK_NONE_COMMANDS = new Set(['schema', 'auth status', 'auth clear', 'model input-guide', 'task records']);
580
581
  const NETWORK_CONDITIONAL_COMMANDS = new Set(['doctor', 'auth login']);
581
582
 
@@ -598,30 +599,33 @@ const OUTPUT_KIND_BY_COMMAND = {
598
599
  'model create-spec': 'model_create_spec',
599
600
  'model input-guide': 'model_input_guide',
600
601
  'upload files': 'upload_result',
601
- 'image fee': 'fee_estimate',
602
- 'image create': 'task_submission',
603
- 'image create-batch': 'batch_task_submission',
604
- 'image status': 'task_status',
605
- 'video fee': 'fee_estimate',
606
- 'video create': 'task_submission',
607
- 'video create-batch': 'batch_task_submission',
608
- 'video status': 'task_status',
609
- 'video subtitle-remove': 'subtitle_task_submission',
610
- 'video subtitle-status': 'subtitle_task_status',
602
+ 'create image-fee': 'fee_estimate',
603
+ 'create image': 'task_submission',
604
+ 'create image-batch': 'batch_task_submission',
605
+ 'task image-status': 'task_status',
606
+ 'create video-fee': 'fee_estimate',
607
+ 'create video': 'task_submission',
608
+ 'create video-batch': 'batch_task_submission',
609
+ 'task video-status': 'task_status',
610
+ 'create video-subtitle-removal': 'subtitle_task_submission',
611
+ 'task video-subtitle-status': 'subtitle_task_status',
611
612
  'task list': 'task_list',
612
613
  'task wait': 'task_status',
613
614
  'task records': 'local_task_records',
614
615
  'task record-poll': 'batch_task_status',
615
- 'asset match-actor': 'asset_match_list',
616
- 'asset groups': 'asset_group_list',
617
- 'asset group': 'asset_group_detail',
618
- 'asset group-create': 'asset_group_write_result',
619
- 'asset group-update': 'asset_group_write_result',
620
- 'asset register': 'asset_register_result',
621
- 'subject list': 'subject_list',
622
- 'subject publish': 'subject_publish_result',
623
- 'subject wait': 'subject_status',
624
- 'subject publish-batch': 'batch_subject_publish_result',
616
+ 'create asset-match-actor': 'asset_match_list',
617
+ 'create asset-groups': 'asset_group_list',
618
+ 'create asset-group-get': 'asset_group_detail',
619
+ 'create asset-group': 'asset_group_write_result',
620
+ 'create asset-group-update': 'asset_group_write_result',
621
+ 'create asset': 'asset_register_result',
622
+ 'create subject-list': 'subject_list',
623
+ 'create subject': 'subject_publish_result',
624
+ 'create subject-wait': 'subject_status',
625
+ 'create subject-voice-list': 'subject_voice_list',
626
+ 'create subject-voice': 'subject_voice_create_result',
627
+ 'create subject-voice-wait': 'subject_voice_status',
628
+ 'create subject-batch': 'batch_subject_publish_result',
625
629
  'artifact script get': 'artifact_full',
626
630
  'artifact script document': 'artifact_record',
627
631
  'artifact script rows': 'artifact_list',
@@ -676,16 +680,16 @@ const OUTPUT_KIND_BY_COMMAND = {
676
680
  };
677
681
 
678
682
  const PREFLIGHTS_BY_COMMAND = {
679
- 'image create': ['doctor --verify', 'model image-models', 'model options', 'model create-spec', 'confirm missing key params', 'image fee', 'image create --dry-run'],
680
- 'image create-batch': ['doctor --verify', 'model image-models', 'model options', 'model create-spec', 'prepare JSONL input', 'image create-batch --dry-run'],
681
- 'video create': ['doctor --verify', 'model video-models', 'model options', 'model create-spec', 'confirm missing key params', 'video fee', 'video create --dry-run'],
682
- 'video create-batch': ['doctor --verify', 'model video-models', 'model options', 'model create-spec', 'prepare JSONL input', 'video create-batch --dry-run'],
683
- 'subject publish': ['doctor --verify', 'subject publish --dry-run'],
684
- 'subject publish-batch': ['doctor --verify', 'prepare JSONL input', 'subject publish-batch --dry-run'],
685
- 'video subtitle-remove': ['doctor --verify', 'video subtitle-remove --dry-run'],
686
- 'asset group-create': ['asset group-create --dry-run'],
687
- 'asset group-update': ['asset group-update --dry-run'],
688
- 'asset register': ['asset register --dry-run'],
683
+ 'create image': ['doctor --verify', 'model image-models', 'model options', 'model create-spec', 'confirm missing key params', 'create image-fee', 'create image --dry-run'],
684
+ 'create image-batch': ['doctor --verify', 'model image-models', 'model options', 'model create-spec', 'prepare JSONL input', 'create image-batch --dry-run'],
685
+ 'create video': ['doctor --verify', 'model video-models', 'model options', 'model create-spec', 'confirm missing key params', 'create video-fee', 'create video --dry-run'],
686
+ 'create video-batch': ['doctor --verify', 'model video-models', 'model options', 'model create-spec', 'prepare JSONL input', 'create video-batch --dry-run'],
687
+ 'create subject': ['doctor --verify', 'create subject --model-code tx|vidu --dry-run'],
688
+ 'create subject-batch': ['doctor --verify', 'prepare JSONL input with modelCode', 'create subject-batch --dry-run'],
689
+ 'create video-subtitle-removal': ['doctor --verify', 'create video-subtitle-removal --source-task-id <videoTaskId> --dry-run'],
690
+ 'create asset-group': ['create asset-group --dry-run'],
691
+ 'create asset-group-update': ['create asset-group-update --dry-run'],
692
+ 'create asset': ['create asset --dry-run'],
689
693
  'upload files': ['upload files --dry-run'],
690
694
  };
691
695
 
@@ -760,13 +764,25 @@ function buildCommandSafety(command, optionKeys) {
760
764
  function buildCommandWorkflow(command) {
761
765
  const outputKind = OUTPUT_KIND_BY_COMMAND[command.name] || 'generic';
762
766
  const next = [];
763
- if (['image create', 'video create'].includes(command.name)) {
764
- next.push('读取 data.taskId 和 data.nextCommand', '运行 task wait 等待结果');
767
+ if (command.name === 'create image') {
768
+ next.push('读取 data.taskId 和 data.nextCommand', '立即运行响应里的 nextCommand,或 task wait --task-type IMAGE_CREATE 等待结果');
769
+ }
770
+ if (command.name === 'create video') {
771
+ next.push('读取 data.taskId 和 data.nextCommand', '立即运行响应里的 nextCommand,或 task wait --task-type VIDEO_GROUP 等待结果');
772
+ }
773
+ if (command.name === 'create video-subtitle-removal') {
774
+ next.push('读取 data.taskId 和 data.nextCommand', '运行 task video-subtitle-status 或响应里的 nextCommand 等待结果');
775
+ }
776
+ if (command.name === 'create subject') {
777
+ next.push('读取 data.elementId / data.externalId', 'externalId 为空时立刻运行 create subject-wait 获取 nextRefSubject');
778
+ }
779
+ if (command.name === 'create subject-voice') {
780
+ next.push('读取 data.voiceRecordId / data.externalId', 'externalId 为空时立刻运行 create subject-voice-wait 获取 nextVoiceArg');
765
781
  }
766
- if (command.name === 'subject publish') {
767
- next.push('读取 data.elementId', '运行 subject wait 获取 externalId / nextRefSubject');
782
+ if (command.name === 'create asset') {
783
+ next.push('读取 data.assetPath', '若后端返回审核 taskId,再运行 task wait --task-type ASSET_REGISTER');
768
784
  }
769
- if (['image create-batch', 'video create-batch', 'subject publish-batch'].includes(command.name)) {
785
+ if (['create image-batch', 'create video-batch', 'create subject-batch'].includes(command.name)) {
770
786
  next.push('读取每项 status / taskId / error', '使用 task record-poll 或对应 wait 命令恢复批量结果');
771
787
  }
772
788
  return {
@@ -781,6 +797,28 @@ function buildAgentContract() {
781
797
  defaultOutputFormat: 'compact-text',
782
798
  jsonFlag: '-f json',
783
799
  outputPolicy: '默认输出精简 key=value 文本,只保留决策字段;需要稳定 JSON、嵌套结构或脚本严格解析时显式传 -f json 或 --json。JSON envelope 字段已做归一化,见 canonicalFields。',
800
+ statePolicy: {
801
+ purpose: 'Agent 应在同一轮 / 同一项目中维护 AWB 上下文账本,减少重复查询和重复提交。',
802
+ cacheKeys: [
803
+ 'schema version / domains / commands',
804
+ 'auth / account / team / current projectGroup',
805
+ 'modelCandidates by taskKind + keyword',
806
+ 'modelOptions / modelCreateSpec by modelGroupCode',
807
+ 'uploaded backendPath by local file path or remote URL',
808
+ 'taskId -> taskType / projectGroupNo / resultUrls / errorMessage',
809
+ 'subject name + modelCode -> elementId / externalId / nextRefSubject',
810
+ 'subject voice name + source -> voiceRecordId / externalId / nextVoiceArg',
811
+ 'artifact projectId and imported file paths',
812
+ ],
813
+ invalidation: '用户切换账号、团队、项目组、模型、素材、prompt 或关键参数后,只刷新受影响的缓存;不要重复跑未变化的 model options / create-spec / fee。',
814
+ },
815
+ workflowPolicy: [
816
+ '模型探索阶段只读 model list / options / create-spec;fee 只在用户确认关键参数后跑一次。',
817
+ 'supportsDryRun=true 的写入 / 扣费命令先 dry-run,确认后 yes;不要把 dry-run 当参数探索工具反复跑。',
818
+ '用户给出多条同模型同参数任务时优先 batch + task-record-file,不要单条循环 create。',
819
+ '命令返回 nextCommand / nextRefSubject / nextVoiceArg 时优先复用返回值,不手拼等价命令。',
820
+ '旧根域 image / video / asset / subject 已移除;只使用 create / task / artifact 等 schema 暴露的 domain。',
821
+ ],
784
822
  canonicalFields: {
785
823
  purpose: 'CLI 输出对上游平台多版本字段做了归一化。Agent 只识别 canonical 列,遇到 aliases 列出的旧字段名时说明是上游原始返回,CLI 已在 text / 归一化层做了 fallback。不要把旧名当成独立新字段对外报告。',
786
824
  fields: [
@@ -797,7 +835,7 @@ function buildAgentContract() {
797
835
  dryRunPolicy: 'schema.commands[].safety.supportsDryRun=true 的写入 / 扣费命令,正式执行前优先跑 --dry-run。',
798
836
  resourceShortcut: {
799
837
  flag: '--resource',
800
- syntax: 'type:usage[:reference_key]=path|url|asset:<id>; image create uses image:reference=... without key',
838
+ syntax: 'type:usage[:reference_key]=path|url|asset:<id>; create image uses image:reference=... without key',
801
839
  examples: [
802
840
  'image:reference=./ref.png',
803
841
  'image:first_frame=./hero.png',
@@ -811,7 +849,7 @@ function buildAgentContract() {
811
849
  {
812
850
  type: 'image|video|audio|subject',
813
851
  usage: 'reference|first_frame|last_frame|keyframe',
814
- reference_key: 'video reference placeholder key; not used by image create image:reference',
852
+ reference_key: 'video reference placeholder key; not used by create image image:reference',
815
853
  source: { kind: 'url|asset_id', value: '<local-file-or-http-url-or-material-backendPath-or-asset-id>' },
816
854
  },
817
855
  ],
@@ -820,14 +858,14 @@ function buildAgentContract() {
820
858
  command: `${commandPrefix()} model options --model-group-code <code>`,
821
859
  jsonCommand: `${commandPrefix()} model options --model-group-code <code> -f json`,
822
860
  purpose: '查询指定模型支持的 CLI 参数、枚举值、默认值、素材约束和条件约束。',
823
- useBefore: ['model create-spec', 'image fee', 'image create', 'video fee', 'video create'],
861
+ useBefore: ['model create-spec', 'create image-fee', 'create image', 'create video-fee', 'create video'],
824
862
  keyFields: ['params[].values', 'params[].defaultValue', 'resources[].mediaType', 'resources[].usage', 'resources[].fileTypes', 'resources[].maxFiles', 'resources[].supportLastFrameOnly', 'resources[].minDurationMs', 'resources[].maxDurationMs', 'constraints[].target', 'constraints[].conditions', 'constraints[].effect'],
825
863
  },
826
864
  modelCreateSpec: {
827
865
  command: `${commandPrefix()} model create-spec --model-group-code <code>`,
828
866
  jsonCommand: `${commandPrefix()} model create-spec --model-group-code <code> -f json`,
829
867
  purpose: '查看指定模型如何组织 create 命令:输入模式、素材绑定规则、示例和创建前检查项。',
830
- useBefore: ['image fee', 'image create', 'video fee', 'video create'],
868
+ useBefore: ['create image-fee', 'create image', 'create video-fee', 'create video'],
831
869
  keyFields: ['inputRequirement', 'supportedIntents', 'validationRules', 'agentGuidance', 'preflight', 'examples'],
832
870
  },
833
871
  modelInputGuide: {
@@ -839,6 +877,8 @@ function buildAgentContract() {
839
877
  taskTypes: {
840
878
  image: 'IMAGE_CREATE',
841
879
  video: 'VIDEO_GROUP',
880
+ subtitleRemoval: 'VIDEO_SUBTITLE_REMOVAL',
881
+ assetRegister: 'ASSET_REGISTER',
842
882
  },
843
883
  exitCodes: [
844
884
  { code: 0, type: 'success', meaning: '命令成功' },
@@ -846,8 +886,11 @@ function buildAgentContract() {
846
886
  { code: 2, type: 'argument_error|unknown_command|unknown_option', meaning: '参数或命令错误' },
847
887
  { code: 3, type: 'auth_required|auth_failed', meaning: '缺少认证或认证失败' },
848
888
  { code: 10, type: 'confirmation_required', meaning: '需要用户确认后追加 --yes' },
889
+ { code: 1, type: 'subject_failed', meaning: '主体创建任务已失败(error.type=subject_failed)。查看 error.details.errorMessage 后调整参考资源或模型重新创建。' },
890
+ { code: 1, type: 'subject_voice_failed', meaning: '主体音色创建任务已失败(error.type=subject_voice_failed)。查看 error.details.errorMessage 后调整音频或视频来源重新创建。' },
849
891
  { code: 20, type: 'task_still_running', meaning: '生图 / 生视频任务仍在运行,本轮等待窗口结束(error.type=task_still_running)。可继续 task wait 或 record-poll 续等。' },
850
- { code: 20, type: 'subject_still_pending', meaning: '主体 externalId 尚未回填,本轮等待窗口结束(error.type=subject_still_pending)。可继续 subject wait 续等。' },
892
+ { code: 20, type: 'subject_still_pending', meaning: '主体 externalId 尚未回填,本轮等待窗口结束(error.type=subject_still_pending)。可继续 create subject-wait 续等。' },
893
+ { code: 20, type: 'subject_voice_still_pending', meaning: '主体音色 externalId 尚未回填,本轮等待窗口结束(error.type=subject_voice_still_pending)。可继续 create subject-voice-wait 续等。' },
851
894
  { code: 30, type: 'network_error', meaning: '网络、TLS、HTTP 或外部平台不可用' },
852
895
  ],
853
896
  };
@@ -960,7 +1003,7 @@ function printRootHelp(commands, version) {
960
1003
  ` ${commandPrefix()} model input-guide`,
961
1004
  ` ${commandPrefix()} model options --model-group-code <code>`,
962
1005
  ` ${commandPrefix()} model create-spec --model-group-code <code>`,
963
- ` ${commandPrefix()} image create --model-group-code <code> --prompt "一只小狗" --dry-run`,
1006
+ ` ${commandPrefix()} create image --model-group-code <code> --prompt "一只小狗" --dry-run`,
964
1007
  '',
965
1008
  'Command groups:',
966
1009
  ];
@@ -988,6 +1031,7 @@ function printGroupHelp(group, commands, version) {
988
1031
  const items = commands.filter((command) => commandGroup(command) === group);
989
1032
  const subgroupMap = SUBGROUP_DESCRIPTIONS[group];
990
1033
  const hasSubgroups = Boolean(subgroupMap && Object.keys(subgroupMap).length);
1034
+ const directItems = hasSubgroups ? items.filter((command) => !commandSubgroupTokens(command)) : [];
991
1035
 
992
1036
  const lines = [
993
1037
  `lj-awb v${version}`,
@@ -999,6 +1043,7 @@ function printGroupHelp(group, commands, version) {
999
1043
  if (group === 'system') {
1000
1044
  lines.push(` ${commandPrefix()} <command> [options]`);
1001
1045
  } else if (hasSubgroups) {
1046
+ if (directItems.length) lines.push(` ${commandPrefix()} ${group} <command> [options]`);
1002
1047
  lines.push(` ${commandPrefix()} ${group} <subdomain> <command> [options]`);
1003
1048
  } else {
1004
1049
  lines.push(` ${commandPrefix()} ${group} <command> [options]`);
@@ -1025,6 +1070,13 @@ function printGroupHelp(group, commands, version) {
1025
1070
  if (!presentSubgroups.has(subgroup)) continue;
1026
1071
  lines.push(` ${subgroup.padEnd(10)} ${description}`);
1027
1072
  }
1073
+ if (directItems.length) {
1074
+ lines.push('', 'Commands:');
1075
+ for (const command of directItems) {
1076
+ const subcommand = commandSubcommand(command);
1077
+ lines.push(` ${subcommand.padEnd(28)} ${summaryOf(command)}`);
1078
+ }
1079
+ }
1028
1080
  } else {
1029
1081
  lines.push('Commands:');
1030
1082
  for (const command of items) {
@@ -1163,8 +1215,15 @@ export async function runStandaloneCli(argv = process.argv.slice(2)) {
1163
1215
  printSubgroupHelp(group, subgroup, commands, version);
1164
1216
  } else if (isCommandGroupName(parsed.commandName, commands)) {
1165
1217
  printGroupHelp(parsed.commandName, commands, version);
1166
- } else {
1218
+ } else if (!parsed.commandName) {
1167
1219
  printRootHelp(commands, version);
1220
+ } else {
1221
+ printError(new LingjingAwbCliError(`未知命令: ${parsed.commandName}`, {
1222
+ type: 'unknown_command',
1223
+ exitCode: 2,
1224
+ hint: unknownCommandHint(parsed.commandName),
1225
+ }), parsed.format, { command: parsed.commandName });
1226
+ process.exitCode = 2;
1168
1227
  }
1169
1228
  return;
1170
1229
  }