@cnbcool/cnb-api-generate 1.2.7 → 2.0.0

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 (36) hide show
  1. package/built/codegen/printer/printer-skills-client-core.js +10 -0
  2. package/built/utils/clean-array-desc.js +9 -0
  3. package/built/utils/collect-used-keys.js +16 -0
  4. package/built/utils/flat-option.js +2 -0
  5. package/built/utils/flatten-array-object-options.js +35 -0
  6. package/built/utils/flatten-nested-object-options.js +40 -0
  7. package/built/utils/flatten-tool-options.js +108 -0
  8. package/built/utils/generate-flat-options.js +50 -0
  9. package/built/utils/is-array-of-objects.js +10 -0
  10. package/built/utils/is-nested-object.js +9 -0
  11. package/built/utils/option-value-flag.js +14 -0
  12. package/built/utils/to-display-key.js +10 -0
  13. package/built/utils/trim-summary.js +12 -0
  14. package/client/index.ts +29 -504
  15. package/client/lib/execute-action.ts +126 -0
  16. package/client/lib/extra-help.ts +15 -0
  17. package/client/lib/flat-options-data.ts +13 -0
  18. package/client/lib/format-output.ts +78 -0
  19. package/client/lib/format-params.ts +220 -0
  20. package/client/lib/help-data.ts +13 -0
  21. package/client/lib/key-mapping-data.ts +13 -0
  22. package/client/lib/parsers.ts +130 -0
  23. package/client/lib/register-fallback.ts +14 -0
  24. package/client/lib/register-modules.ts +121 -0
  25. package/client/lib/summary-extractors.ts +189 -0
  26. package/client/lib/trim-summary.ts +11 -0
  27. package/client/shortcuts.ts +10 -198
  28. package/client/utils/build-nested-field-map.ts +38 -0
  29. package/client/utils/flat-key-from-segments.ts +8 -0
  30. package/client/utils/match-array-object-field.ts +19 -0
  31. package/client/utils/restore-original-keys.ts +23 -0
  32. package/package.json +3 -2
  33. package/skills-template/SKILL.md +28 -15
  34. package/client/modules.help.ts +0 -49
  35. package/client/schemaToJson.ts +0 -26
  36. package/client/tools.help.ts +0 -124
@@ -43,6 +43,7 @@ const debug_1 = __importDefault(require("debug"));
43
43
  const get_skills_codegen_target_1 = require("../../utils/get-skills-codegen-target");
44
44
  const glob_1 = require("glob");
45
45
  const printer_ts_ast_to_js_file_1 = require("./printer-ts-ast-to-js-file");
46
+ const generate_flat_options_1 = require("../../utils/generate-flat-options");
46
47
  const logger = (0, debug_1.default)('csg:cli-core');
47
48
  async function printerSkillsClientCore(helpData) {
48
49
  const packageDir = path.resolve(__dirname, '../../../');
@@ -66,4 +67,13 @@ async function printerSkillsClientCore(helpData) {
66
67
  const helpFile = path.join(skillScriptCoreDir, 'help.json');
67
68
  fs.writeFileSync(helpFile, JSON.stringify(helpData, null, 2));
68
69
  logger(`print ${helpFile}`);
70
+ // 输出扁平化参数数据
71
+ const { flatOptions, keyMapping } = (0, generate_flat_options_1.generateFlatOptions)(helpData);
72
+ const flatOptionsFile = path.join(skillScriptCoreDir, 'flat-options.json');
73
+ fs.writeFileSync(flatOptionsFile, JSON.stringify(flatOptions, null, 2));
74
+ logger(`print ${flatOptionsFile}`);
75
+ // 输出 key 映射表(displayKey → originalKey)
76
+ const keyMappingFile = path.join(skillScriptCoreDir, 'key-mapping.json');
77
+ fs.writeFileSync(keyMappingFile, JSON.stringify(keyMapping, null, 2));
78
+ logger(`print ${keyMappingFile}`);
69
79
  }
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.cleanArrayDesc = cleanArrayDesc;
4
+ /** 当参数为数组类型时,清理描述中的 JSON 数组示例 */
5
+ function cleanArrayDesc(desc) {
6
+ let cleaned = desc.replace(/`?\[("[^"]*"(?:\s*,\s*"[^"]*")*)\]`?/g, '');
7
+ cleaned = cleaned.replace(/[,,]?\s*(?:示例|例如|如|example)\s*[::]\s*$/i, '');
8
+ return cleaned.trim();
9
+ }
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.collectUsedKeys = collectUsedKeys;
4
+ /** 收集 path 和 query 中已使用的 key */
5
+ function collectUsedKeys(pathDef, queryDef) {
6
+ const keys = new Set();
7
+ if (pathDef) {
8
+ for (const key of Object.keys(pathDef))
9
+ keys.add(key);
10
+ }
11
+ if (queryDef) {
12
+ for (const key of Object.keys(queryDef))
13
+ keys.add(key);
14
+ }
15
+ return keys;
16
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.flattenArrayObjectOptions = flattenArrayObjectOptions;
4
+ const trim_summary_1 = require("./trim-summary");
5
+ const option_value_flag_1 = require("./option-value-flag");
6
+ const to_display_key_1 = require("./to-display-key");
7
+ /** 扁平化 array<object> 类型的子属性 */
8
+ function flattenArrayObjectOptions(arrayKey, prop, isRequired, usedKeys) {
9
+ const options = [];
10
+ const itemProps = prop.items.properties;
11
+ const arrayDesc = (0, trim_summary_1.trimSummary)(prop.description || '');
12
+ const subPropNames = Object.keys(itemProps);
13
+ for (const [subKey, subProp] of Object.entries(itemProps)) {
14
+ const flatKey = `${arrayKey}@${subKey}`;
15
+ const optKey = usedKeys.has(flatKey) ? `d-${flatKey}` : flatKey;
16
+ const valuePlaceholder = (0, option_value_flag_1.optionValueFlag)(subProp.type || 'string');
17
+ const rawDesc = (0, trim_summary_1.trimSummary)(subProp.description || '') || subKey;
18
+ const peerHint = subPropNames
19
+ .filter((k) => k !== subKey)
20
+ .map((k) => `--${(0, to_display_key_1.toDisplayKey)(`${arrayKey}@${k}`)}`)
21
+ .join(', ');
22
+ const hint = `${rawDesc} (${arrayDesc},可多次传入,按顺序与 ${peerHint} 对齐)`;
23
+ const desc = isRequired ? `[必填] ${hint}` : hint;
24
+ options.push({
25
+ optKey,
26
+ valuePlaceholder,
27
+ description: desc,
28
+ required: isRequired,
29
+ isArray: true,
30
+ source: 'body',
31
+ isArrayObject: true,
32
+ });
33
+ }
34
+ return options;
35
+ }
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.flattenNestedObjectOptions = flattenNestedObjectOptions;
4
+ const trim_summary_1 = require("./trim-summary");
5
+ const option_value_flag_1 = require("./option-value-flag");
6
+ const is_nested_object_1 = require("./is-nested-object");
7
+ const is_array_of_objects_1 = require("./is-array-of-objects");
8
+ const flatten_array_object_options_1 = require("./flatten-array-object-options");
9
+ /** 递归扁平化嵌套对象类型的子属性 */
10
+ function flattenNestedObjectOptions(objectKey, prop, isRequired, usedKeys) {
11
+ const options = [];
12
+ const subProps = prop.properties;
13
+ const objectDesc = (0, trim_summary_1.trimSummary)(prop.description || '');
14
+ for (const [subKey, subProp] of Object.entries(subProps)) {
15
+ const flatKey = `${objectKey}@${subKey}`;
16
+ if ((0, is_nested_object_1.isNestedObject)(subProp)) {
17
+ options.push(...flattenNestedObjectOptions(flatKey, subProp, isRequired, usedKeys));
18
+ continue;
19
+ }
20
+ if ((0, is_array_of_objects_1.isArrayOfObjects)(subProp)) {
21
+ options.push(...(0, flatten_array_object_options_1.flattenArrayObjectOptions)(flatKey, subProp, isRequired, usedKeys));
22
+ continue;
23
+ }
24
+ const optKey = usedKeys.has(flatKey) ? `d-${flatKey}` : flatKey;
25
+ const valuePlaceholder = (0, option_value_flag_1.optionValueFlag)(subProp.type || 'string');
26
+ const rawDesc = (0, trim_summary_1.trimSummary)(subProp.description || '') || subKey;
27
+ const hint = `${rawDesc} (${objectDesc} 的子字段)`;
28
+ const desc = isRequired ? `[必填] ${hint}` : hint;
29
+ options.push({
30
+ optKey,
31
+ valuePlaceholder,
32
+ description: desc,
33
+ required: isRequired,
34
+ isArray: false,
35
+ source: 'body',
36
+ isNestedField: true,
37
+ });
38
+ }
39
+ return options;
40
+ }
@@ -0,0 +1,108 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.flattenToolOptions = flattenToolOptions;
4
+ const trim_summary_1 = require("./trim-summary");
5
+ const option_value_flag_1 = require("./option-value-flag");
6
+ const clean_array_desc_1 = require("./clean-array-desc");
7
+ const is_array_of_objects_1 = require("./is-array-of-objects");
8
+ const is_nested_object_1 = require("./is-nested-object");
9
+ const collect_used_keys_1 = require("./collect-used-keys");
10
+ const flatten_array_object_options_1 = require("./flatten-array-object-options");
11
+ const flatten_nested_object_options_1 = require("./flatten-nested-object-options");
12
+ /**
13
+ * 将单个 tool 的参数扁平化为 FlatOption 列表
14
+ * 逻辑与 register-modules.ts 中 registerToolOptions 完全一致
15
+ */
16
+ function flattenToolOptions(toolInfo) {
17
+ var _a, _b, _c;
18
+ const options = [];
19
+ const parameter = (_a = toolInfo.help) === null || _a === void 0 ? void 0 : _a.parameter;
20
+ if (!parameter)
21
+ return options;
22
+ const { path: pathDef, query: queryDef, body: bodyDef } = parameter;
23
+ // path 参数
24
+ if (pathDef) {
25
+ for (const [key, param] of Object.entries(pathDef)) {
26
+ const valuePlaceholder = (0, option_value_flag_1.optionValueFlag)(param.type);
27
+ const rawDesc = (0, trim_summary_1.trimSummary)(param.description || '');
28
+ const desc = param.required ? `[必填] ${rawDesc}` : rawDesc;
29
+ options.push({
30
+ optKey: key,
31
+ valuePlaceholder,
32
+ description: desc,
33
+ required: !!param.required,
34
+ isArray: false,
35
+ source: 'path',
36
+ });
37
+ }
38
+ }
39
+ // query 参数
40
+ if (queryDef) {
41
+ for (const [key, param] of Object.entries(queryDef)) {
42
+ const valuePlaceholder = (0, option_value_flag_1.optionValueFlag)(param.type);
43
+ const rawDesc = (0, trim_summary_1.trimSummary)(param.description || '');
44
+ const desc = param.required ? `[必填] ${rawDesc}` : rawDesc;
45
+ const opt = {
46
+ optKey: key,
47
+ valuePlaceholder,
48
+ description: desc,
49
+ required: !!param.required,
50
+ isArray: false,
51
+ source: 'query',
52
+ };
53
+ if (param.enum)
54
+ opt.choices = param.enum;
55
+ if (param.default !== undefined)
56
+ opt.defaultValue = param.default;
57
+ options.push(opt);
58
+ }
59
+ }
60
+ // body 参数扁平化
61
+ if ((_b = bodyDef === null || bodyDef === void 0 ? void 0 : bodyDef.schema) === null || _b === void 0 ? void 0 : _b.properties) {
62
+ const usedKeys = (0, collect_used_keys_1.collectUsedKeys)(pathDef, queryDef);
63
+ const bodyRequired = new Set(bodyDef.schema.required || []);
64
+ for (const [key, prop] of Object.entries(bodyDef.schema.properties)) {
65
+ const isRequired = bodyRequired.has(key) || prop.required;
66
+ if ((0, is_array_of_objects_1.isArrayOfObjects)(prop)) {
67
+ options.push(...(0, flatten_array_object_options_1.flattenArrayObjectOptions)(key, prop, isRequired, usedKeys));
68
+ continue;
69
+ }
70
+ if ((0, is_nested_object_1.isNestedObject)(prop)) {
71
+ options.push(...(0, flatten_nested_object_options_1.flattenNestedObjectOptions)(key, prop, isRequired, usedKeys));
72
+ continue;
73
+ }
74
+ const optKey = usedKeys.has(key) ? `d-${key}` : key;
75
+ const isArray = prop.type === 'array';
76
+ const itemType = isArray ? ((_c = prop.items) === null || _c === void 0 ? void 0 : _c.type) || 'string' : prop.type;
77
+ const valuePlaceholder = (0, option_value_flag_1.optionValueFlag)(itemType);
78
+ const rawDesc = isArray
79
+ ? (0, clean_array_desc_1.cleanArrayDesc)((0, trim_summary_1.trimSummary)(prop.description || ''))
80
+ : (0, trim_summary_1.trimSummary)(prop.description || '');
81
+ const arrayHint = isArray ? ' (可多次传入)' : '';
82
+ const desc = isRequired
83
+ ? `[必填] ${rawDesc}${arrayHint}`
84
+ : `${rawDesc}${arrayHint}`;
85
+ const opt = {
86
+ optKey,
87
+ valuePlaceholder,
88
+ description: desc,
89
+ required: !!isRequired,
90
+ isArray,
91
+ source: 'body',
92
+ };
93
+ options.push(opt);
94
+ }
95
+ }
96
+ // body 存在时添加 --data fallback
97
+ if (bodyDef) {
98
+ options.push({
99
+ optKey: 'data',
100
+ valuePlaceholder: '<json>',
101
+ description: 'Request body (JSON 字符串或 @file 引用,可替代逐个 body 字段)',
102
+ required: false,
103
+ isArray: false,
104
+ source: 'body',
105
+ });
106
+ }
107
+ return options;
108
+ }
@@ -0,0 +1,50 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.generateFlatOptions = generateFlatOptions;
4
+ const to_display_key_1 = require("./to-display-key");
5
+ const flatten_tool_options_1 = require("./flatten-tool-options");
6
+ /**
7
+ * 模拟 Commander 对 --long-option 的 camelCase 转换
8
+ * 例如 "page-size" => "pageSize", "d-ext-type" => "dExtType"
9
+ */
10
+ function commanderCamelCase(str) {
11
+ return str.replace(/-([a-z0-9])/g, (_, c) => c.toUpperCase());
12
+ }
13
+ /**
14
+ * 将 helpData 中所有 module 的 tool 参数预先扁平化
15
+ * 生成 flat-options.json,供 registerToolOptions 直接读取使用
16
+ * 同时生成 key-mapping.json,记录 Commander camelCase key → originalKey 的映射
17
+ * 格式: { moduleName: { toolName: { optKey: FlatOption, ... }, ... }, ... }
18
+ */
19
+ function generateFlatOptions(helpData) {
20
+ const flatOptions = {};
21
+ const keyMapping = {};
22
+ const modulesHelp = helpData.modulesHelp || {};
23
+ for (const [moduleName, tools] of Object.entries(modulesHelp)) {
24
+ flatOptions[moduleName] = {};
25
+ keyMapping[moduleName] = {};
26
+ for (const [toolName, toolInfo] of Object.entries(tools)) {
27
+ const optionsList = (0, flatten_tool_options_1.flattenToolOptions)(toolInfo);
28
+ const optionsMap = {};
29
+ const toolKeyMapping = {};
30
+ for (const opt of optionsList) {
31
+ const originalKey = opt.optKey;
32
+ const displayKey = (0, to_display_key_1.toDisplayKey)(originalKey);
33
+ // Commander 会对 --page-size 做 camelCase 转换为 pageSize
34
+ const camelKey = commanderCamelCase(displayKey);
35
+ // 用 displayKey 作为 optKey 展示给用户
36
+ opt.optKey = displayKey;
37
+ optionsMap[displayKey] = opt;
38
+ // 仅当 camelKey 与 originalKey 不同时才记录映射
39
+ if (camelKey !== originalKey) {
40
+ toolKeyMapping[camelKey] = originalKey;
41
+ }
42
+ }
43
+ flatOptions[moduleName][toolName] = optionsMap;
44
+ if (Object.keys(toolKeyMapping).length > 0) {
45
+ keyMapping[moduleName][toolName] = toolKeyMapping;
46
+ }
47
+ }
48
+ }
49
+ return { flatOptions, keyMapping };
50
+ }
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isArrayOfObjects = isArrayOfObjects;
4
+ /** 判断 body 属性是否为 array<object> 类型 */
5
+ function isArrayOfObjects(prop) {
6
+ if (prop.type !== 'array' || !prop.items)
7
+ return false;
8
+ const { items } = prop;
9
+ return !!(items.properties && Object.keys(items.properties).length > 0);
10
+ }
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isNestedObject = isNestedObject;
4
+ /** 判断 body 属性是否为嵌套对象类型 */
5
+ function isNestedObject(prop) {
6
+ if (prop.type !== 'object')
7
+ return false;
8
+ return !!(prop.properties && Object.keys(prop.properties).length > 0);
9
+ }
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.optionValueFlag = optionValueFlag;
4
+ /** 将参数类型映射为 option 的值占位符 */
5
+ function optionValueFlag(type) {
6
+ switch (type) {
7
+ case 'number':
8
+ return '<number>';
9
+ case 'boolean':
10
+ return '';
11
+ default:
12
+ return '<string>';
13
+ }
14
+ }
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.toDisplayKey = toDisplayKey;
4
+ /**
5
+ * 将 optKey 中的 '_' 和 '@' 统一替换为 '-',生成 CLI 展示用的 key
6
+ * 例如 "page_size" => "page-size", "ext@type" => "ext-type"
7
+ */
8
+ function toDisplayKey(optKey) {
9
+ return optKey.replace(/[_@]/g, '-');
10
+ }
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.trimSummary = trimSummary;
4
+ /** 去除 summary 中的英文部分(保留中文句号前的内容) */
5
+ function trimSummary(summary) {
6
+ if (!summary)
7
+ return '';
8
+ const match = summary.match(/^(.*?[\u4e00-\u9fff].*?)[。.]\s*[A-Z]/);
9
+ if (match)
10
+ return match[1];
11
+ return summary;
12
+ }