openyida 2026.7.27 → 2026.7.29-beta.2

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 (53) hide show
  1. package/lib/app/canvas-compile.js +122 -4
  2. package/lib/app/publish.js +47 -3
  3. package/lib/core/agent-capabilities.js +1 -1
  4. package/lib/core/command-manifest.js +4 -2
  5. package/lib/core/sample.js +6 -0
  6. package/lib/samples/yida-canvas-table-form/table-form-batch-submit.canvas.jsx +511 -0
  7. package/lib/samples/yida-rechart/trend-combo.canvas.jsx +253 -0
  8. package/package.json +1 -1
  9. package/scripts/build-skills-package.js +12 -8
  10. package/scripts/postinstall.js +9 -5
  11. package/scripts/validate-skills.js +91 -30
  12. package/yida-skills/SKILL.md +22 -12
  13. package/yida-skills/references/development-rules.md +1 -1
  14. package/yida-skills/skills/yida-app/SKILL.md +23 -13
  15. package/yida-skills/skills/yida-app/references/app-build-contract.md +1 -1
  16. package/yida-skills/skills/yida-canvas-custom-page/SKILL.md +17 -16
  17. package/yida-skills/skills/yida-canvas-custom-page/references/canvas-authoring-examples.md +6 -6
  18. package/yida-skills/skills/yida-canvas-custom-page/references/canvas-design-system.md +8 -8
  19. package/yida-skills/skills/yida-canvas-custom-page/references/component-library-guide.md +45 -27
  20. package/yida-skills/skills/yida-canvas-custom-page/references/data-bridge-guide.md +13 -13
  21. package/yida-skills/skills/yida-canvas-custom-page/references/dependencies-and-cdn.md +24 -21
  22. package/yida-skills/skills/yida-canvas-custom-page/references/employeefield-verification.md +5 -5
  23. package/yida-skills/skills/yida-canvas-custom-page/references/native-components-bridge.md +16 -16
  24. package/yida-skills/skills/yida-canvas-custom-page/references/page-generation-guide.md +5 -5
  25. package/yida-skills/skills/yida-canvas-table-form/SKILL.md +151 -0
  26. package/yida-skills/skills/yida-custom-page/SKILL.md +4 -4
  27. package/yida-skills/skills/yida-dashboard/SKILL.md +143 -147
  28. package/yida-skills/skills/yida-dashboard/references/interaction-patterns.md +4 -2
  29. package/yida-skills/skills/yida-dashboard/references/pitfalls.md +2 -0
  30. package/yida-skills/skills/yida-dashboard/references/structure-and-layout.md +97 -320
  31. package/yida-skills/skills/yida-dashboard/references/theme-presets.md +1 -1
  32. package/yida-skills/skills/yida-data-management/SKILL.md +32 -2
  33. package/yida-skills/skills/yida-data-source-connectors/SKILL.md +106 -64
  34. package/yida-skills/skills/yida-density/SKILL.md +118 -110
  35. package/yida-skills/skills/yida-flash-note-to-prd/SKILL.md +3 -1
  36. package/yida-skills/skills/yida-nav-shell/SKILL.md +125 -74
  37. package/yida-skills/skills/yida-nav-shell/references/nav-shell-patterns.md +43 -32
  38. package/yida-skills/skills/yida-page-uiux/SKILL.md +24 -3
  39. package/yida-skills/skills/yida-page-uiux/references/dashboard/chart-contracts.md +1 -0
  40. package/yida-skills/skills/yida-page-uiux/references/scenes/dashboard.md +2 -2
  41. package/yida-skills/skills/yida-page-uiux/references/visual-decision-engine.md +1 -1
  42. package/yida-skills/skills/yida-page-uiux/workflow/output-decision-block.md +3 -3
  43. package/yida-skills/skills/yida-page-uiux/workflow/step-0-nav-shape.md +4 -4
  44. package/yida-skills/skills/yida-page-uiux/workflow/step-5-icon-and-assets.md +2 -2
  45. package/yida-skills/skills/yida-page-uiux/workflow/step-6-deai-selfcheck.md +1 -1
  46. package/yida-skills/skills/yida-ppt-slider/SKILL.md +185 -113
  47. package/yida-skills/skills/yida-ppt-slider/references/dark-tech-theme.md +7 -4
  48. package/yida-skills/skills/yida-ppt-slider/references/echarts-race-example.md +2 -0
  49. package/yida-skills/skills/yida-ppt-slider/references/examples.md +29 -7
  50. package/yida-skills/skills/yida-rechart/SKILL.md +134 -0
  51. package/yida-skills/skills/yida-tingji/SKILL.md +4 -3
  52. package/yida-skills/skills-index.json +131 -38
  53. package/yida-skills/skills/yida-ppt/SKILL.md +0 -46
@@ -33,6 +33,7 @@ const {
33
33
  assertNoEmojiInArtifactName,
34
34
  assertNoEmojiInText,
35
35
  } = require('../core/no-emoji-guard');
36
+ const { CliError, isCliError } = require('../core/cli-error');
36
37
 
37
38
  /**
38
39
  * 依赖 → window 别名白名单。
@@ -59,6 +60,10 @@ const MODULE_ALIAS_MAP = {
59
60
  'framer-motion': 'FramerMotion',
60
61
  };
61
62
 
63
+ const LUCIDE_REACT_PACKAGE = 'lucide-react';
64
+ const LUCIDE_DYNAMIC_ICON_ALIAS = 'DynamicIcon';
65
+ const LUCIDE_MODULE_ALIAS = 'LucideReact';
66
+
62
67
  const IMPORT_PATTERN = /import\s+(?:[\w*\s{},]+\s+from\s+)?['"]([^'"]+)['"]/g;
63
68
  const IMPORT_SIDE_EFFECT_PATTERN = /import\s+['"]([^'"]+)['"]/g;
64
69
  const REQUIRE_PATTERN = /require\(\s*['"]([^'"]+)['"]\s*\)/g;
@@ -77,6 +82,11 @@ function packageTempName(pkg) {
77
82
  return String(pkg || 'module').replace(/[^A-Za-z0-9_$]+/g, '_') || 'module';
78
83
  }
79
84
 
85
+ function packageBaseName(pkg) {
86
+ const segments = String(pkg || '').split('/');
87
+ return pkg.startsWith('@') ? segments.slice(0, 2).join('/') : segments[0];
88
+ }
89
+
80
90
  function stripJsComments(code) {
81
91
  return String(code || '')
82
92
  .replace(/\/\*[\s\S]*?\*\//g, '')
@@ -116,11 +126,14 @@ function resolveWindowAlias(pkg) {
116
126
  if (MODULE_ALIAS_MAP[pkg]) {
117
127
  return MODULE_ALIAS_MAP[pkg];
118
128
  }
119
- const segments = pkg.split('/');
120
- const base = pkg.startsWith('@') ? segments.slice(0, 2).join('/') : segments[0];
129
+ const base = packageBaseName(pkg);
121
130
  return MODULE_ALIAS_MAP[base] || null;
122
131
  }
123
132
 
133
+ function isLucideReactPackage(pkg) {
134
+ return packageBaseName(pkg) === LUCIDE_REACT_PACKAGE;
135
+ }
136
+
124
137
  /**
125
138
  * Babel 插件:把 ESM import/export 改写成画布运行时约定。
126
139
  * import X from 'react' → var _r = window.React; var X = _r && _r.__esModule ? _r.default : _r;
@@ -141,6 +154,76 @@ function esmToWindowPlugin({ types: t }, options = {}) {
141
154
  return t.memberExpression(t.identifier('window'), t.stringLiteral(pkg), true);
142
155
  }
143
156
 
157
+ function buildLucideImportDeclarations(path, specifiers) {
158
+ const decls = [];
159
+ let dynamicIconTmp = null;
160
+ let lucideReactTmp = null;
161
+
162
+ function ensureDynamicIconTmp() {
163
+ if (!dynamicIconTmp) {
164
+ dynamicIconTmp = path.scope.generateUidIdentifier(LUCIDE_DYNAMIC_ICON_ALIAS);
165
+ decls.push(t.variableDeclarator(
166
+ t.cloneNode(dynamicIconTmp),
167
+ moduleExpr(LUCIDE_REACT_PACKAGE, LUCIDE_DYNAMIC_ICON_ALIAS)
168
+ ));
169
+ }
170
+ return dynamicIconTmp;
171
+ }
172
+
173
+ function ensureLucideReactTmp() {
174
+ if (!lucideReactTmp) {
175
+ lucideReactTmp = path.scope.generateUidIdentifier(LUCIDE_MODULE_ALIAS);
176
+ decls.push(t.variableDeclarator(
177
+ t.cloneNode(lucideReactTmp),
178
+ moduleExpr(LUCIDE_REACT_PACKAGE, LUCIDE_MODULE_ALIAS)
179
+ ));
180
+ }
181
+ return lucideReactTmp;
182
+ }
183
+
184
+ const namedIconProps = [];
185
+ for (const spec of specifiers) {
186
+ if (t.isImportDefaultSpecifier(spec)) {
187
+ decls.push(t.variableDeclarator(
188
+ t.identifier(spec.local.name),
189
+ t.cloneNode(ensureDynamicIconTmp())
190
+ ));
191
+ } else if (t.isImportNamespaceSpecifier(spec)) {
192
+ decls.push(t.variableDeclarator(
193
+ t.identifier(spec.local.name),
194
+ t.cloneNode(ensureLucideReactTmp())
195
+ ));
196
+ } else if (t.isImportSpecifier(spec)) {
197
+ const importedName = t.isIdentifier(spec.imported) ? spec.imported.name : spec.imported.value;
198
+ const localName = spec.local.name;
199
+ if (importedName === LUCIDE_DYNAMIC_ICON_ALIAS) {
200
+ decls.push(t.variableDeclarator(
201
+ t.identifier(localName),
202
+ t.cloneNode(ensureDynamicIconTmp())
203
+ ));
204
+ } else {
205
+ namedIconProps.push(
206
+ t.objectProperty(
207
+ t.identifier(importedName),
208
+ t.identifier(localName),
209
+ false,
210
+ importedName === localName
211
+ )
212
+ );
213
+ }
214
+ }
215
+ }
216
+
217
+ if (namedIconProps.length) {
218
+ decls.push(t.variableDeclarator(
219
+ t.objectPattern(namedIconProps),
220
+ t.cloneNode(ensureLucideReactTmp())
221
+ ));
222
+ }
223
+
224
+ return t.variableDeclaration('var', decls);
225
+ }
226
+
144
227
  function buildUnsupportedBareImportError(path, pkg) {
145
228
  return path.buildCodeFrameError(
146
229
  `Code Canvas 不支持从裸包 "${pkg}" 导入绑定。`
@@ -183,6 +266,11 @@ function esmToWindowPlugin({ types: t }, options = {}) {
183
266
  throw buildUnsupportedBareImportError(path, pkg);
184
267
  }
185
268
 
269
+ if (isLucideReactPackage(pkg)) {
270
+ path.replaceWith(buildLucideImportDeclarations(path, specifiers));
271
+ return;
272
+ }
273
+
186
274
  const decls = [];
187
275
  const tmp = path.scope.generateUidIdentifier(alias || packageTempName(pkg));
188
276
  decls.push(t.variableDeclarator(t.cloneNode(tmp), moduleExpr(pkg, alias)));
@@ -382,14 +470,44 @@ function compileCanvasLocal(source, options = {}) {
382
470
  function compileCanvas(source, options = {}) {
383
471
  return new Promise((resolve, reject) => {
384
472
  if (typeof source !== 'string' || source.trim() === '') {
385
- reject(new Error('canvas 编译源码为空'));
473
+ reject(new CliError('canvas 编译源码为空', {
474
+ code: 'OPENYIDA_CANVAS_COMPILE_EMPTY_SOURCE',
475
+ details: {
476
+ stage: 'canvas_compile',
477
+ sourcePath: options.sourcePath,
478
+ },
479
+ }));
386
480
  return;
387
481
  }
388
482
  try {
389
483
  resolve(compileCanvasLocal(source, options));
390
484
  } catch (compileError) {
485
+ if (isCliError(compileError)) {
486
+ reject(compileError);
487
+ return;
488
+ }
391
489
  const detail = compileError && compileError.message ? compileError.message : String(compileError);
392
- reject(new Error(`Code Canvas 本地编译失败: ${detail}`));
490
+ if (
491
+ compileError &&
492
+ /^OPENYIDA_/.test(String(compileError.code || '')) &&
493
+ compileError.details !== undefined
494
+ ) {
495
+ reject(new CliError(`Code Canvas 本地编译失败: ${detail}`, {
496
+ code: compileError.code,
497
+ details: compileError.details,
498
+ }));
499
+ return;
500
+ }
501
+ reject(new CliError(`Code Canvas 本地编译失败: ${detail}`, {
502
+ code: 'OPENYIDA_CANVAS_COMPILE_FAILED',
503
+ details: {
504
+ stage: 'canvas_compile',
505
+ sourcePath: options.sourcePath,
506
+ causeCode: compileError && compileError.code,
507
+ causeName: compileError && compileError.name,
508
+ loc: compileError && compileError.loc,
509
+ },
510
+ }));
393
511
  }
394
512
  });
395
513
  }
@@ -32,6 +32,7 @@ const { createAuthRef, isTokenAuthRef } = require('../core/yida-client');
32
32
  const { requireSchemaServerRevision } = require('../core/server-revision');
33
33
  const { t } = require('../core/i18n');
34
34
  const { banner, step, label, success, fail, warn, info, error, result, usage, hint } = require('../core/chalk');
35
+ const { CliError } = require('../core/cli-error');
35
36
  const { compileSource } = require('./page-compiler');
36
37
  const { compileCanvas } = require('./canvas-compile');
37
38
  const { runLintCheck } = require('./page-linter');
@@ -97,7 +98,7 @@ function parseArgs(argv = process.argv.slice(2)) {
97
98
  const force = args.includes('--force');
98
99
  const canvas = args.includes('--canvas');
99
100
  const help = args.includes('--help') || args.includes('-h');
100
- const filteredArgs = args.filter(arg => arg !== '--skip-lint' && arg !== '--health-check' && arg !== '--check' && arg !== '--compat' && arg !== '--modern' && arg !== '--force' && arg !== '--canvas' && arg !== '--help' && arg !== '-h');
101
+ const filteredArgs = args.filter(arg => arg !== '--skip-lint' && arg !== '--health-check' && arg !== '--check' && arg !== '--compat' && arg !== '--modern' && arg !== '--force' && arg !== '--canvas' && arg !== '--json' && arg !== '--help' && arg !== '-h');
101
102
 
102
103
  if (help) {
103
104
  usage(t('publish.usage'), t('publish.example'));
@@ -122,6 +123,40 @@ function parseArgs(argv = process.argv.slice(2)) {
122
123
  };
123
124
  }
124
125
 
126
+ function buildCanvasCompileCliError(errorObject, sourcePath) {
127
+ const code = errorObject && errorObject.code
128
+ ? errorObject.code
129
+ : 'OPENYIDA_CANVAS_COMPILE_FAILED';
130
+ const detail = errorObject && errorObject.message ? errorObject.message : String(errorObject);
131
+ const baseDetails = errorObject && errorObject.details && typeof errorObject.details === 'object'
132
+ ? { ...errorObject.details }
133
+ : {};
134
+
135
+ return new CliError(`${t('publish.canvas_compile_failed', detail)}\nError Code: ${code}`, {
136
+ code,
137
+ details: {
138
+ ...baseDetails,
139
+ stage: 'canvas_compile',
140
+ sourcePath,
141
+ },
142
+ });
143
+ }
144
+
145
+ function enableQuietForJson(argv = []) {
146
+ if (!Array.isArray(argv) || !argv.includes('--json')) {
147
+ return () => {};
148
+ }
149
+ const previousQuiet = process.env.YIDA_QUIET;
150
+ process.env.YIDA_QUIET = '1';
151
+ return () => {
152
+ if (previousQuiet === undefined) {
153
+ delete process.env.YIDA_QUIET;
154
+ } else {
155
+ process.env.YIDA_QUIET = previousQuiet;
156
+ }
157
+ };
158
+ }
159
+
125
160
  function normalizeSourcePathForHint(sourceFile) {
126
161
  return String(sourceFile || '')
127
162
  .replace(/\\/g, '/')
@@ -686,6 +721,16 @@ function sendHealthCheckRequest(pageUrl, cookies) {
686
721
  // ── 主流程 ────────────────────────────────────────────
687
722
 
688
723
  async function main(argv) {
724
+ const rawArgv = argv || process.argv.slice(2);
725
+ const restoreQuiet = enableQuietForJson(rawArgv);
726
+ try {
727
+ return await runMain(rawArgv);
728
+ } finally {
729
+ restoreQuiet();
730
+ }
731
+ }
732
+
733
+ async function runMain(argv) {
689
734
  const options = parseArgs(argv);
690
735
  if (options.help) {
691
736
  return options;
@@ -722,8 +767,7 @@ async function main(argv) {
722
767
  try {
723
768
  canvasResult = await compileCanvas(initialSourceCode, { sourcePath });
724
769
  } catch (canvasCompileError) {
725
- fail(t('publish.canvas_compile_failed', canvasCompileError.message));
726
- process.exit(1);
770
+ throw buildCanvasCompileCliError(canvasCompileError, sourcePath);
727
771
  }
728
772
  success(t('publish.canvas_compile_done'));
729
773
  } else {
@@ -402,7 +402,7 @@ function buildAgentCapabilities() {
402
402
  ],
403
403
  retry_policy: 'Do not repeat the same failed command without changing login state, organization, parameters, files, or field IDs.',
404
404
  completion_contracts: {
405
- full_app: 'Default fast_build is complete after creating the app, core forms, primary page, publishing it, and returning an access URL.',
405
+ full_app: 'Default fast_build is complete after creating the app, core forms, primary page, publishing it, and returning access URLs. If three or more resources/links are returned, present them in a Markdown table with type, purpose/name, URL, and status.',
406
406
  },
407
407
  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.',
408
408
  },
@@ -1302,8 +1302,10 @@ function summarizeLocalizedCommands(commands) {
1302
1302
  mode: 'fast_build',
1303
1303
  trigger_phrases: ['默认方案', '不要追问', '直接创建', '尽快搭建'],
1304
1304
  default_page_skill_id: 'yida-canvas-custom-page',
1305
+ default_ui_guidance_skill_id: 'yida-page-uiux',
1305
1306
  ordinary_jsx_skill_id: 'yida-custom-page',
1306
1307
  page_skill_policy: 'Use Code Canvas by default for the primary custom page. Choose yida-custom-page when the user explicitly asks for the ordinary custom page JSX/Jsx component chain, or when the page strongly depends on this.$(fieldId), this.utils.yida.*, this.dataSourceMap, form submission, or deep field two-way binding.',
1308
+ ui_guidance_policy: 'Default full-app primary page creation includes yida-page-uiux lightweight UI guidance to decide page type, template route, visualProfile, and sample-avoidance checks. This is not deep_design and must not pull yida-app-uiux, theme, navigation, demo data, screenshots, or long PRD work by default.',
1307
1309
  required_command_ids: [
1308
1310
  'agent-capabilities',
1309
1311
  'create-app',
@@ -1326,13 +1328,13 @@ function summarizeLocalizedCommands(commands) {
1326
1328
  'append-chart',
1327
1329
  ],
1328
1330
  do_not_default_skill_ids: [
1329
- 'yida-page-uiux',
1331
+ 'yida-app-uiux',
1330
1332
  'yida-data-source-connectors',
1331
1333
  'yida-data-management',
1332
1334
  'yida-nav-group',
1333
1335
  'yida-dashboard',
1334
1336
  ],
1335
- completion_contract: 'Create app, core forms, primary page, publish it, and return an access URL.',
1337
+ completion_contract: 'Create app, core forms, primary page, publish it, and return access URLs. If three or more resources/links are returned, present them in a Markdown table with type, purpose/name, URL, and status.',
1336
1338
  },
1337
1339
  },
1338
1340
  };
@@ -60,6 +60,9 @@ const SAMPLES = {
60
60
  'todo-mvc': 'todo-mvc.canvas.jsx',
61
61
  'workbench-home': 'workbench-home.canvas.jsx',
62
62
  },
63
+ 'yida-rechart': {
64
+ 'trend-combo': 'trend-combo.canvas.jsx',
65
+ },
63
66
  'yida-create-app': {
64
67
  'ipd-app-template': 'ipd-app-template.js',
65
68
  },
@@ -69,6 +72,9 @@ const SAMPLES = {
69
72
  'yida-density': {
70
73
  'density-switch-page': 'density-switch-page.js',
71
74
  },
75
+ 'yida-canvas-table-form': {
76
+ 'table-form-batch-submit': 'table-form-batch-submit.canvas.jsx',
77
+ },
72
78
  'yida-table-form': {
73
79
  'table-form-batch-submit': 'table-form-batch-submit.js',
74
80
  },