@lingjingai/anime-cli-pre 0.1.5 → 0.1.7

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lingjingai/anime-cli-pre",
3
- "version": "0.1.5",
3
+ "version": "0.1.7",
4
4
  "description": "Standard CLI for Anime Workbench script, asset, and video output controllers.",
5
5
  "bin": {
6
6
  "anime-cli": "./bin/anime-cli.js"
package/src/anime-cli.js CHANGED
@@ -49,7 +49,7 @@ function parseArgs(argv = process.argv.slice(2), env = process.env) {
49
49
  authPath: env.ANIME_CLI_AUTH_PATH || defaultAuthPath(env),
50
50
  legacyAuthPath: env.ANIME_CLI_LEGACY_AUTH_PATH || legacyAuthPath(env),
51
51
  headers: [],
52
- format: 'text',
52
+ format: 'json',
53
53
  timeout: 30000,
54
54
  retry: 0,
55
55
  };
@@ -92,6 +92,8 @@ function parseGlobalOptions(args, tokens) {
92
92
  args.format = parseOutputFormat(takeValue(tokens, token));
93
93
  } else if (token === '--json') {
94
94
  args.format = 'json';
95
+ } else if (token === '--text') {
96
+ args.format = 'text';
95
97
  } else if (token === '--raw') {
96
98
  args.raw = true;
97
99
  } else if (token === '--dry-run') {
@@ -134,6 +136,7 @@ function parseCommandOptions(args, tokens) {
134
136
  if (isOutputFormat(value)) args.format = value;
135
137
  else args.inputFile = value;
136
138
  } else if (token === '--json') args.format = 'json';
139
+ else if (token === '--text') args.format = 'text';
137
140
  else if (token === '--raw') args.raw = true;
138
141
  else if (token === '--dry-run') args.dryRun = true;
139
142
  else if (token === '--base-url') args.baseUrl = takeValue(tokens, token);
@@ -371,7 +374,7 @@ function helpText(args = {}) {
371
374
  function rootHelp() {
372
375
  return `anime-cli v${VERSION}
373
376
 
374
- 灵境 Anime Workbench 最终产物命令行工具。默认输出精简文本;需要 JSON 时传 -f json
377
+ 灵境 Anime Workbench 最终产物命令行工具。默认输出 JSON;需要人读文本时传 --text
375
378
 
376
379
  Usage:
377
380
  anime-cli <domain> <command> [options]
@@ -400,8 +403,9 @@ More help:
400
403
 
401
404
  Global options:
402
405
  -f, --format json|text|compact
403
- 输出格式;默认 text,compact 为单行 JSON
406
+ 输出格式;默认 json,compact 为单行 JSON
404
407
  --json 等同于 -f json
408
+ --text 等同于 -f text,输出人读文案
405
409
  --base-url <url> 服务地址,默认按 ANIME_CLI_ENV 或打包环境选择;当前默认 ${DEFAULT_BASE_URL}
406
410
  --access-key <key> Access key;默认读取 ANIME_CLI_ACCESS_KEY 或 lj-awb 本地认证
407
411
  --no-access-key 不自动发送 access-key
@@ -467,6 +471,8 @@ Usage:
467
471
  Options:
468
472
  ${command.options.map((line) => ` ${line}`).join('\n') || ' (none)'}
469
473
  -f, --format json|text|compact
474
+ --text
475
+ --json
470
476
  --dry-run
471
477
  -h, --help
472
478
 
@@ -486,27 +492,149 @@ function exampleFor(command) {
486
492
  }
487
493
 
488
494
  function writeOutput(stream, value, args) {
489
- const text = formatOutput(value, args.format);
495
+ const text = formatOutput(value, args);
490
496
  if (args.outputFile) fs.writeFileSync(args.outputFile, text);
491
497
  else stream.write(text);
492
498
  }
493
499
 
494
- function formatOutput(value, format = 'text') {
500
+ function formatOutput(value, argsOrFormat = 'text') {
501
+ const args = typeof argsOrFormat === 'string' ? { format: argsOrFormat } : (argsOrFormat || {});
502
+ const format = args.format || 'text';
495
503
  if (format === 'json') return `${JSON.stringify(value, null, 2)}\n`;
496
504
  if (format === 'compact') return `${JSON.stringify(value)}\n`;
505
+ if (!args.raw && args.domain === 'asset' && args.command === 'name-states') {
506
+ return assetNameStatesText(value);
507
+ }
497
508
  return textSummary(value);
498
509
  }
499
510
 
511
+ function assetNameStatesText(value) {
512
+ if (!value || typeof value !== 'object' || Array.isArray(value)) return textSummary(value);
513
+ const sections = [
514
+ { title: '角色', items: value.actors, key: 'actor_key', altKey: 'actorKey', name: 'actor_name', altName: 'actorName' },
515
+ { title: '道具', items: value.props, key: 'prop_key', altKey: 'propKey', name: 'prop_name', altName: 'propName' },
516
+ { title: '场景', items: value.locations, key: 'location_key', altKey: 'locationKey', name: 'location_name', altName: 'locationName' },
517
+ ];
518
+ const lines = [];
519
+ for (const section of sections) {
520
+ const items = Array.isArray(section.items) ? section.items : [];
521
+ lines.push(`${section.title}: ${items.length}`);
522
+ for (const item of items) {
523
+ const key = item[section.key] || item[section.altKey] || '';
524
+ const name = item[section.name] || item[section.altName] || key || '(未命名)';
525
+ lines.push(`- ${name}${key ? ` (${key})` : ''}`);
526
+ const states = Array.isArray(item.states) ? item.states : [];
527
+ for (const state of states) {
528
+ const stateKey = state.state_key || state.stateKey || '';
529
+ const stateName = state.state_name || state.stateName || stateKey || '(未命名状态)';
530
+ lines.push(` - ${stateName}${stateKey && stateKey !== stateName ? ` (${stateKey})` : ''}`);
531
+ }
532
+ }
533
+ lines.push('');
534
+ }
535
+ return `${lines.join('\n').trimEnd()}\n`;
536
+ }
537
+
500
538
  function textSummary(value) {
501
539
  if (value === undefined || value === null) return 'OK\n';
502
- if (Array.isArray(value)) return `${value.length} items\n`;
503
- if (typeof value === 'object') {
504
- if ('id' in value) return `id: ${value.id}\n`;
505
- return `${JSON.stringify(value, null, 2)}\n`;
506
- }
540
+ if (Array.isArray(value) || typeof value === 'object') return `${renderTextValue(value)}\n`;
507
541
  return `${String(value)}\n`;
508
542
  }
509
543
 
544
+ function renderTextValue(value, indent = 0) {
545
+ if (value === undefined || value === null) return 'null';
546
+ if (Array.isArray(value)) return renderTextArray(value, indent);
547
+ if (typeof value === 'object') return renderTextObject(value, indent);
548
+ return scalarText(value);
549
+ }
550
+
551
+ function renderTextArray(items, indent = 0) {
552
+ const pad = ' '.repeat(indent);
553
+ if (items.length === 0) return `${pad}0 items`;
554
+ const lines = [`${pad}${items.length} items`];
555
+ for (const item of items) {
556
+ if (item && typeof item === 'object' && !Array.isArray(item)) {
557
+ lines.push(`${pad}- ${objectTitle(item)}`);
558
+ const nested = objectDetailLines(item, indent + 2);
559
+ if (nested.length > 0) lines.push(...nested);
560
+ } else {
561
+ lines.push(`${pad}- ${scalarText(item)}`);
562
+ }
563
+ }
564
+ return lines.join('\n');
565
+ }
566
+
567
+ function renderTextObject(value, indent = 0) {
568
+ const lines = objectDetailLines(value, indent);
569
+ if (lines.length === 0) return `${' '.repeat(indent)}${objectTitle(value)}`;
570
+ return lines.join('\n');
571
+ }
572
+
573
+ function objectDetailLines(value, indent = 0) {
574
+ const pad = ' '.repeat(indent);
575
+ const lines = [];
576
+ for (const [key, item] of Object.entries(value)) {
577
+ if (item === undefined || item === null || item === '') continue;
578
+ if (Array.isArray(item)) {
579
+ lines.push(`${pad}${key}: ${item.length} items`);
580
+ for (const child of item) {
581
+ if (child && typeof child === 'object' && !Array.isArray(child)) {
582
+ lines.push(`${pad} - ${objectTitle(child)}`);
583
+ } else {
584
+ lines.push(`${pad} - ${scalarText(child)}`);
585
+ }
586
+ }
587
+ } else if (typeof item === 'object') {
588
+ lines.push(`${pad}${key}:`);
589
+ lines.push(renderTextValue(item, indent + 2));
590
+ } else {
591
+ lines.push(`${pad}${key}: ${scalarText(item)}`);
592
+ }
593
+ }
594
+ return lines;
595
+ }
596
+
597
+ function objectTitle(value) {
598
+ const preferred = [
599
+ 'name',
600
+ 'title',
601
+ 'actorName',
602
+ 'actor_name',
603
+ 'propName',
604
+ 'prop_name',
605
+ 'locationName',
606
+ 'location_name',
607
+ 'stateName',
608
+ 'state_name',
609
+ 'episodeName',
610
+ 'episode_name',
611
+ 'sceneName',
612
+ 'scene_name',
613
+ 'clipName',
614
+ 'clip_name',
615
+ 'assetName',
616
+ 'asset_name',
617
+ ];
618
+ const nameKey = preferred.find((key) => value[key] !== undefined && value[key] !== null && value[key] !== '');
619
+ const name = nameKey ? value[nameKey] : undefined;
620
+ const idKey = ['id', 'key', 'uid', 'actorKey', 'actor_key', 'propKey', 'prop_key', 'locationKey', 'location_key', 'stateKey', 'state_key', 'episodeId', 'episode_id', 'sceneId', 'scene_id', 'clipId', 'clip_id']
621
+ .find((key) => value[key] !== undefined && value[key] !== null && value[key] !== '');
622
+ const id = idKey ? value[idKey] : undefined;
623
+ if (name !== undefined && id !== undefined && String(name) !== String(id)) return `${scalarText(name)} (${scalarText(id)})`;
624
+ if (name !== undefined) return scalarText(name);
625
+ if (id !== undefined) return scalarText(id);
626
+ const firstScalar = Object.entries(value).find(([, item]) => item !== undefined && item !== null && item !== '' && typeof item !== 'object');
627
+ if (firstScalar) return `${firstScalar[0]}: ${scalarText(firstScalar[1])}`;
628
+ return 'item';
629
+ }
630
+
631
+ function scalarText(value) {
632
+ if (value === undefined || value === null) return 'null';
633
+ if (typeof value === 'string') return value.length > 240 ? `${value.slice(0, 237)}...` : value;
634
+ if (typeof value === 'number' || typeof value === 'boolean' || typeof value === 'bigint') return String(value);
635
+ return JSON.stringify(value);
636
+ }
637
+
510
638
  function writeDryRun(stream, request, args) {
511
639
  const payload = {
512
640
  method: request.method,
@@ -166,6 +166,7 @@ const WHITELIST_BODY_FIELDS = bodyFields([
166
166
  const commands = [
167
167
  cmd('asset', 'get', '查询项目组全部资产产物', ['--project-group-no <no>'], (a) => get(assetRoot(a))),
168
168
  cmd('asset', 'output', '查询资产详情视图', ['--project-group-no <no>'], (a) => get([...assetRoot(a), 'output'])),
169
+ cmd('asset', 'name-states', '查询角色、道具、场景名称与状态', ['--project-group-no <no>'], (a) => get([...assetRoot(a), 'asset-name-states'])),
169
170
  cmd('asset', 'style', '查询项目资产风格配置', ['--project-group-no <no>'], (a) => get([...assetRoot(a), 'style'])),
170
171
  cmd('asset', 'upsert-style', '新增或更新项目资产风格配置', bodyCommandOptions(PROJECT_STYLE_BODY_FIELDS), (a) => post([...assetRoot(a), 'style'], a, PROJECT_STYLE_BODY_FIELDS)),
171
172
  cmd('asset', 'delete-style', '逻辑删除项目资产风格配置', ['--project-group-no <no>'], (a) => post([...assetRoot(a), 'style', 'delete'])),