openyida 2026.7.12-1 → 2026.7.13
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/README.md +3 -5
- package/lib/app/get-schema.js +109 -9
- package/lib/core/agent-capabilities.js +6 -0
- package/lib/core/command-manifest.js +405 -26
- package/package.json +1 -1
- package/scripts/postinstall.js +3 -1
- package/scripts/validate-command-manifest.js +163 -0
- package/yida-skills/SKILL.md +2 -1
- package/yida-skills/skills/yida-app/SKILL.md +7 -0
- package/yida-skills/skills/yida-custom-page/SKILL.md +63 -16
- package/yida-skills/skills/yida-get-schema/SKILL.md +32 -8
- package/yida-skills/skills/yida-publish-page/SKILL.md +6 -0
- package/yida-skills/skills-index.json +5 -5
package/README.md
CHANGED
|
@@ -343,8 +343,7 @@ Run `openyida --help` or `openyida <command> --help` for detailed usage.
|
|
|
343
343
|
| `openyida logout` | Logout / switch account |
|
|
344
344
|
| `openyida auth <status\|login\|refresh\|logout>` | Login state management |
|
|
345
345
|
| `openyida org <list\|switch>` | Organization management (list / switch) |
|
|
346
|
-
| `openyida env [--json]` | Detect AI tool environment & login state |
|
|
347
|
-
| `openyida env <setup\|list\|show\|switch\|add\|remove>` | Manage public/private Yida environment profiles |
|
|
346
|
+
| `openyida env [--json\|setup\|list\|show\|switch\|add\|remove] [options]` | Detect AI tool environment & login state |
|
|
348
347
|
|
|
349
348
|
### App Management
|
|
350
349
|
|
|
@@ -374,7 +373,7 @@ Run `openyida --help` or `openyida <command> --help` for detailed usage.
|
|
|
374
373
|
| `openyida create-form add-option <appType> <formUuid> <fieldLabel> <option1> [option2] ...` | Update a form page |
|
|
375
374
|
| `openyida list-forms <appType> [--keyword <text>]` | List forms/pages in an app |
|
|
376
375
|
| `openyida aggregate-table <list\|create-empty\|inspect\|preview\|save\|publish\|status> <appType> ...` | Manage aggregate tables (virtualView) |
|
|
377
|
-
| `openyida get-schema <appType> <formUuid\|--all
|
|
376
|
+
| `openyida get-schema <appType> <formUuid\|--all> [--summary-json\|--field-map-json]` | Get one form Schema or all form Schemas |
|
|
378
377
|
| `openyida er <appType> [--format mermaid\|json] [--output file] [--include-system] [--include-pages]` | Export app entity relationship diagram |
|
|
379
378
|
| `openyida create-page <appType> "<name>" [--mode dashboard] [--locale zh_CN\|en_US\|ja_JP] [--open\|--no-open]` | Create a custom display page |
|
|
380
379
|
| `openyida generate-page <template>` | Generate page from curated template |
|
|
@@ -469,8 +468,7 @@ Run `openyida --help` or `openyida <command> --help` for detailed usage.
|
|
|
469
468
|
| `openyida update` | Check and update to latest version |
|
|
470
469
|
| `openyida export-conversation [options]` | Export AI conversation records |
|
|
471
470
|
| `openyida feedback <setup\|url\|dismiss\|status> [options]` | Configure experience feedback form and local reminder state |
|
|
472
|
-
| `openyida batch <file
|
|
473
|
-
| `openyida batch --commands "cmd1 ; cmd2" [--stop-on-error] [--json]` | Run OpenYida commands in batch |
|
|
471
|
+
| `openyida batch <file>\|--commands "cmd1 ; cmd2" [--stop-on-error] [--json]` | Run OpenYida commands in batch |
|
|
474
472
|
| `openyida flash-to-prd --file <path> --name "<project>"` | Convert flash notes or meeting notes to a PRD prompt |
|
|
475
473
|
| `openyida ai <text\|image> [options]` | Call Yida AI text and image recognition APIs |
|
|
476
474
|
| `openyida cdn-config [options]` | Configure CDN / OSS upload |
|
package/lib/app/get-schema.js
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
* get-schema.js - 宜搭表单 Schema 获取命令
|
|
3
3
|
*
|
|
4
4
|
* 用法:
|
|
5
|
-
* openyida get-schema <appType> <formUuid>
|
|
6
|
-
* openyida get-schema <appType> --all [--output-dir <dir>] [--concurrency N] [--retries N]
|
|
5
|
+
* openyida get-schema <appType> <formUuid> [--summary-json|--field-map-json]
|
|
6
|
+
* openyida get-schema <appType> --all [--summary-json] [--output-dir <dir>] [--concurrency N] [--retries N]
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
'use strict';
|
|
@@ -31,7 +31,7 @@ const FIELD_TYPES_NEEDING_VALUE_SUFFIX = new Set([
|
|
|
31
31
|
/**
|
|
32
32
|
* 从 Schema 中提取字段摘要,列出每个字段的真实 fieldId、组件别名和报表用 reportFieldCode。
|
|
33
33
|
* @param {object} schemaResult - getFormSchema API 返回结果
|
|
34
|
-
* @returns {Array<{label, componentName, fieldId, alias, reportFieldCode}>}
|
|
34
|
+
* @returns {Array<{label, componentName, fieldId, alias, reportFieldCode, options}>}
|
|
35
35
|
*/
|
|
36
36
|
function extractFieldSummary(schemaResult) {
|
|
37
37
|
const fields = [];
|
|
@@ -62,12 +62,17 @@ function extractFieldSummary(schemaResult) {
|
|
|
62
62
|
? `${fieldId}_value`
|
|
63
63
|
: fieldId;
|
|
64
64
|
if (fieldId) {
|
|
65
|
+
const options = extractOptionSummary(props);
|
|
66
|
+
const optionSource = getOptionSource(props) || [];
|
|
65
67
|
fields.push({
|
|
66
68
|
label,
|
|
67
69
|
componentName: node.componentName,
|
|
68
70
|
fieldId,
|
|
69
71
|
alias: aliasMaps.aliasByFieldId[fieldId] || '',
|
|
70
72
|
reportFieldCode,
|
|
73
|
+
options,
|
|
74
|
+
optionCount: optionSource.length,
|
|
75
|
+
optionsTruncated: optionSource.length > options.length,
|
|
71
76
|
});
|
|
72
77
|
}
|
|
73
78
|
}
|
|
@@ -87,6 +92,70 @@ function extractFieldSummary(schemaResult) {
|
|
|
87
92
|
return fields;
|
|
88
93
|
}
|
|
89
94
|
|
|
95
|
+
function normalizeOptionLabel(value) {
|
|
96
|
+
if (value === null || value === undefined) {
|
|
97
|
+
return '';
|
|
98
|
+
}
|
|
99
|
+
if (typeof value === 'object') {
|
|
100
|
+
return value.zh_CN || value.zh_HK || value.en_US || value.ja_JP || value.text || value.label || value.value || '';
|
|
101
|
+
}
|
|
102
|
+
return String(value);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function firstPresent(values) {
|
|
106
|
+
return values.find(value => value !== undefined && value !== null);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function normalizeOptionValue(value, fallback) {
|
|
110
|
+
if (value === null || value === undefined || value === '') {
|
|
111
|
+
return fallback;
|
|
112
|
+
}
|
|
113
|
+
if (typeof value === 'object') {
|
|
114
|
+
return value.value || value.label || value.text || fallback;
|
|
115
|
+
}
|
|
116
|
+
return String(value);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function optionArrayFromDataSource(dataSource) {
|
|
120
|
+
if (!dataSource) {
|
|
121
|
+
return null;
|
|
122
|
+
}
|
|
123
|
+
if (Array.isArray(dataSource)) {
|
|
124
|
+
return dataSource;
|
|
125
|
+
}
|
|
126
|
+
const candidates = [
|
|
127
|
+
dataSource.options,
|
|
128
|
+
dataSource.data,
|
|
129
|
+
dataSource.list,
|
|
130
|
+
dataSource.values,
|
|
131
|
+
];
|
|
132
|
+
return candidates.find(Array.isArray) || null;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function getOptionSource(props = {}) {
|
|
136
|
+
return Array.isArray(props.options)
|
|
137
|
+
? props.options
|
|
138
|
+
: optionArrayFromDataSource(props.dataSource);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
function extractOptionSummary(props = {}) {
|
|
142
|
+
const source = getOptionSource(props);
|
|
143
|
+
if (!source) {
|
|
144
|
+
return [];
|
|
145
|
+
}
|
|
146
|
+
return source.slice(0, 50).map((item, index) => {
|
|
147
|
+
if (typeof item === 'string' || typeof item === 'number' || typeof item === 'boolean') {
|
|
148
|
+
const text = String(item);
|
|
149
|
+
return { label: text, value: text };
|
|
150
|
+
}
|
|
151
|
+
const label = normalizeOptionLabel(firstPresent([item.label, item.text, item.name, item.title, item.value]));
|
|
152
|
+
return {
|
|
153
|
+
label,
|
|
154
|
+
value: normalizeOptionValue(firstPresent([item.value, item.key, item.id]), label || String(index)),
|
|
155
|
+
};
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
|
|
90
159
|
function buildComponentAliasMaps(schemaResult) {
|
|
91
160
|
const aliasByFieldId = {};
|
|
92
161
|
const fieldIdByAlias = {};
|
|
@@ -136,6 +205,7 @@ function parseArgs(args) {
|
|
|
136
205
|
// 仅返回目标字段的 {componentName, fieldId, label, props}
|
|
137
206
|
field: '',
|
|
138
207
|
json: false,
|
|
208
|
+
summaryJson: false,
|
|
139
209
|
};
|
|
140
210
|
|
|
141
211
|
for (let index = 1; index < args.length; index++) {
|
|
@@ -159,6 +229,8 @@ function parseArgs(args) {
|
|
|
159
229
|
index++;
|
|
160
230
|
} else if (arg === '--json') {
|
|
161
231
|
parsed.json = true;
|
|
232
|
+
} else if (arg === '--summary-json' || arg === '--field-map-json') {
|
|
233
|
+
parsed.summaryJson = true;
|
|
162
234
|
} else if (!arg.startsWith('--') && !parsed.formUuid) {
|
|
163
235
|
parsed.formUuid = arg;
|
|
164
236
|
}
|
|
@@ -303,6 +375,18 @@ function printFieldSummary(result) {
|
|
|
303
375
|
process.stderr.write(` ${c.dim}注:SelectField/EmployeeField 在报表中需加 _value 后缀${c.reset}\n\n`);
|
|
304
376
|
}
|
|
305
377
|
|
|
378
|
+
function buildSchemaSummary(appType, formUuid, schemaResult, meta = {}) {
|
|
379
|
+
const fields = extractFieldSummary(schemaResult);
|
|
380
|
+
return {
|
|
381
|
+
success: true,
|
|
382
|
+
appType,
|
|
383
|
+
formUuid,
|
|
384
|
+
...meta,
|
|
385
|
+
fieldCount: fields.length,
|
|
386
|
+
fields,
|
|
387
|
+
};
|
|
388
|
+
}
|
|
389
|
+
|
|
306
390
|
function filterForms(forms, keyword) {
|
|
307
391
|
if (!keyword) {
|
|
308
392
|
return forms;
|
|
@@ -373,9 +457,19 @@ async function fetchSchemaRecord(appType, form, authRef, retries) {
|
|
|
373
457
|
};
|
|
374
458
|
}
|
|
375
459
|
|
|
376
|
-
function
|
|
460
|
+
function summarizeRecord(record) {
|
|
461
|
+
if (!record.success) {
|
|
462
|
+
return record;
|
|
463
|
+
}
|
|
464
|
+
const { schema, ...summary } = record;
|
|
465
|
+
void schema;
|
|
466
|
+
return summary;
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
function writeBatchOutput(outputDir, records, options = {}) {
|
|
470
|
+
const compact = !!options.compact;
|
|
377
471
|
if (!outputDir) {
|
|
378
|
-
return records;
|
|
472
|
+
return compact ? records.map(summarizeRecord) : records;
|
|
379
473
|
}
|
|
380
474
|
|
|
381
475
|
const resolvedDir = path.resolve(outputDir);
|
|
@@ -391,10 +485,8 @@ function writeBatchOutput(outputDir, records) {
|
|
|
391
485
|
const filePath = path.join(resolvedDir, fileName);
|
|
392
486
|
fs.writeFileSync(filePath, JSON.stringify(record.schema, null, 2), 'utf-8');
|
|
393
487
|
|
|
394
|
-
const { schema, ...summary } = record;
|
|
395
|
-
void schema;
|
|
396
488
|
return {
|
|
397
|
-
...
|
|
489
|
+
...summarizeRecord(record),
|
|
398
490
|
schemaFile: filePath,
|
|
399
491
|
};
|
|
400
492
|
});
|
|
@@ -452,6 +544,11 @@ async function runSingle(parsed, authRef) {
|
|
|
452
544
|
return;
|
|
453
545
|
}
|
|
454
546
|
|
|
547
|
+
if (parsed.summaryJson) {
|
|
548
|
+
console.log(JSON.stringify(buildSchemaSummary(parsed.appType, parsed.formUuid, result), null, 2));
|
|
549
|
+
return;
|
|
550
|
+
}
|
|
551
|
+
|
|
455
552
|
chalkSuccess(t('get_schema.success'));
|
|
456
553
|
printFieldSummary(result);
|
|
457
554
|
console.log(JSON.stringify(result, null, 2));
|
|
@@ -494,7 +591,7 @@ async function runBatch(parsed, authRef) {
|
|
|
494
591
|
return record;
|
|
495
592
|
});
|
|
496
593
|
|
|
497
|
-
const outputRecords = writeBatchOutput(parsed.outputDir, records);
|
|
594
|
+
const outputRecords = writeBatchOutput(parsed.outputDir, records, { compact: parsed.summaryJson });
|
|
498
595
|
const successCount = records.filter(record => record.success).length;
|
|
499
596
|
const failedCount = records.length - successCount;
|
|
500
597
|
|
|
@@ -509,6 +606,7 @@ async function runBatch(parsed, authRef) {
|
|
|
509
606
|
total: records.length,
|
|
510
607
|
successCount,
|
|
511
608
|
failedCount,
|
|
609
|
+
summaryOnly: parsed.summaryJson || undefined,
|
|
512
610
|
outputDir: parsed.outputDir ? path.resolve(parsed.outputDir) : undefined,
|
|
513
611
|
forms: outputRecords,
|
|
514
612
|
}, null, 2));
|
|
@@ -527,6 +625,8 @@ async function run(args) {
|
|
|
527
625
|
|
|
528
626
|
module.exports = {
|
|
529
627
|
extractFieldSummary,
|
|
628
|
+
extractOptionSummary,
|
|
629
|
+
buildSchemaSummary,
|
|
530
630
|
buildComponentAliasMaps,
|
|
531
631
|
parseArgs,
|
|
532
632
|
filterForms,
|
|
@@ -48,8 +48,12 @@ function buildAgentCapabilities() {
|
|
|
48
48
|
count: manifest.summary.command_count,
|
|
49
49
|
group_count: manifest.summary.group_count,
|
|
50
50
|
side_effect_counts: manifest.summary.side_effect_counts,
|
|
51
|
+
permission_mode_counts: manifest.summary.permission_mode_counts,
|
|
51
52
|
read_only_command_ids: manifest.summary.read_only_command_ids,
|
|
52
53
|
mutating_command_ids: manifest.summary.mutating_command_ids,
|
|
54
|
+
allow_command_ids: manifest.summary.allow_command_ids,
|
|
55
|
+
ask_command_ids: manifest.summary.ask_command_ids,
|
|
56
|
+
deny_command_ids: manifest.summary.deny_command_ids,
|
|
53
57
|
core_workflows: manifest.summary.core_workflows,
|
|
54
58
|
},
|
|
55
59
|
sideEffects: {
|
|
@@ -63,11 +67,13 @@ function buildAgentCapabilities() {
|
|
|
63
67
|
completion_contracts: {
|
|
64
68
|
full_app: 'Default fast_build is complete after creating the app, core forms, primary page, publishing it, and returning an access URL.',
|
|
65
69
|
},
|
|
70
|
+
fast_build_data_contract: 'Default fast_build page code must not call this.dataSourceMap.* unless the same run created and bound a designer data source; use this.utils.yida.* or an entry-only page by default.',
|
|
66
71
|
},
|
|
67
72
|
command_manifest: {
|
|
68
73
|
schema_version: manifest.schema_version,
|
|
69
74
|
groups: manifest.groups,
|
|
70
75
|
side_effect_schema: manifest.side_effect_schema,
|
|
76
|
+
permission_schema: manifest.permission_schema,
|
|
71
77
|
summary: manifest.summary,
|
|
72
78
|
commands: manifest.commands,
|
|
73
79
|
},
|