openyida 2026.7.18 → 2026.7.21

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 (200) hide show
  1. package/README.md +37 -2
  2. package/bin/yida.js +113 -18
  3. package/docs/capabilities.md +202 -0
  4. package/lib/agent-center/agent-center.js +2 -3
  5. package/lib/app/app-list.js +3 -4
  6. package/lib/app/build-page.js +13 -6
  7. package/lib/app/check-page.js +16 -6
  8. package/lib/app/compile.js +17 -7
  9. package/lib/app/create-app.js +14 -2
  10. package/lib/app/create-form/api-path.js +25 -0
  11. package/lib/app/create-form/args.js +13 -0
  12. package/lib/app/create-form/commands.js +4 -0
  13. package/lib/app/create-form/definition-reader.js +23 -23
  14. package/lib/app/create-form/field-normalizers.js +26 -7
  15. package/lib/app/create-form/schema-patch.js +4 -1
  16. package/lib/app/create-form.js +155 -68
  17. package/lib/app/create-page.js +47 -10
  18. package/lib/app/generate-page.js +20 -1
  19. package/lib/app/get-form-config.js +2 -1
  20. package/lib/app/get-schema.js +67 -15
  21. package/lib/app/import-app.js +94 -42
  22. package/lib/app/list-forms.js +4 -8
  23. package/lib/app/page-ir.js +140 -0
  24. package/lib/app/publish.js +289 -556
  25. package/lib/app/schema-field-resolution.js +370 -0
  26. package/lib/app/services/app-reader.js +85 -0
  27. package/lib/app/services/app-service.js +235 -0
  28. package/lib/app/services/canvas-page-compiler.js +91 -0
  29. package/lib/app/services/canvas-page-schema-builder.js +149 -0
  30. package/lib/app/services/field-bindings.js +68 -0
  31. package/lib/app/services/form-compiler.js +1922 -0
  32. package/lib/app/services/form-mode-service.js +182 -0
  33. package/lib/app/services/form-schema-patcher.js +333 -0
  34. package/lib/app/services/form-schema-reader.js +59 -0
  35. package/lib/app/services/form-service.js +379 -0
  36. package/lib/app/services/form-validation.js +562 -0
  37. package/lib/app/services/native-page-compiler.js +92 -0
  38. package/lib/app/services/native-page-schema-builder.js +428 -0
  39. package/lib/app/services/page-resource-service.js +185 -0
  40. package/lib/app/update-app.js +22 -9
  41. package/lib/app/update-form-config.js +4 -2
  42. package/lib/asset/asset-cmd.js +19 -6
  43. package/lib/auth/oauth-loopback.js +376 -15
  44. package/lib/auth/token-auth.js +34 -3
  45. package/lib/auth/token-store.js +22 -4
  46. package/lib/basic-info/basic-info.js +2 -1
  47. package/lib/bridge/bridge.js +43 -18
  48. package/lib/core/agent-capabilities.js +5 -3
  49. package/lib/core/command-errors.js +38 -0
  50. package/lib/core/command-manifest.js +59 -1
  51. package/lib/core/copy.js +12 -0
  52. package/lib/core/doctor.js +15 -4
  53. package/lib/core/env-cmd.js +1 -1
  54. package/lib/core/env.js +7 -6
  55. package/lib/core/i18n.js +66 -8
  56. package/lib/core/legacy-schema-guard.js +408 -0
  57. package/lib/core/locales/en.js +38 -46
  58. package/lib/core/locales/zh.js +30 -46
  59. package/lib/core/sample.js +12 -2
  60. package/lib/core/utils.js +334 -66
  61. package/lib/core/yida-client.js +108 -5
  62. package/lib/corp-efficiency/corp-efficiency.js +2 -2
  63. package/lib/corp-manager/corp-manager.js +3 -3
  64. package/lib/formula/evaluate.js +11 -68
  65. package/lib/formula/field-refs.js +83 -0
  66. package/lib/i18n-management/i18n-management.js +2 -3
  67. package/lib/process/configure-process.js +44 -1992
  68. package/lib/process/create-process.js +54 -87
  69. package/lib/process/preview-process.js +20 -8
  70. package/lib/process/services/process-compiler.js +2056 -0
  71. package/lib/process/services/process-reader.js +232 -0
  72. package/lib/process/services/process-resource-service.js +571 -0
  73. package/lib/process/services/process-service.js +122 -0
  74. package/lib/process/services/process-stage-checkpoint.js +246 -0
  75. package/lib/report/append.js +7 -26
  76. package/lib/report/http.js +31 -5
  77. package/lib/report/index.js +10 -2
  78. package/lib/samples/yida-canvas-custom-page/business-list.canvas.jsx +63 -14
  79. package/lib/samples/yida-canvas-custom-page/dashboard-overview.canvas.jsx +176 -32
  80. package/lib/samples/yida-canvas-custom-page/dashboard-starter.canvas.jsx +5 -2
  81. package/lib/samples/yida-canvas-custom-page/data-management.canvas.jsx +228 -14
  82. package/lib/samples/yida-canvas-custom-page/portal-shell-home.canvas.jsx +2 -2
  83. package/lib/samples/yida-canvas-custom-page/split-pane-detail.canvas.jsx +206 -10
  84. package/lib/samples/yida-custom-page/data-management.oyd.jsx +14 -3
  85. package/lib/samples/yida-custom-page/design-tokens.js +2 -2
  86. package/lib/samples/yida-custom-page/detail-profile.oyd.jsx +1 -1
  87. package/lib/samples/yida-custom-page/portal-shell-home.oyd.jsx +7 -2
  88. package/lib/samples/yida-custom-page/split-pane-detail.oyd.jsx +2 -1
  89. package/lib/schema/adapters/app-adapter.js +210 -0
  90. package/lib/schema/adapters/form-adapter.js +1362 -0
  91. package/lib/schema/adapters/keys.js +19 -0
  92. package/lib/schema/adapters/page-adapter.js +566 -0
  93. package/lib/schema/adapters/process-adapter.js +519 -0
  94. package/lib/schema/applier.js +1878 -0
  95. package/lib/schema/apply-store.js +1083 -0
  96. package/lib/schema/command.js +645 -0
  97. package/lib/schema/dependency-graph.js +83 -0
  98. package/lib/schema/errors.js +481 -0
  99. package/lib/schema/hash.js +9 -0
  100. package/lib/schema/manifest-limits.js +177 -0
  101. package/lib/schema/manifest-loader.js +309 -0
  102. package/lib/schema/manifest-schema-v1.json +193 -0
  103. package/lib/schema/normalize-manifest.js +281 -0
  104. package/lib/schema/page-canvas-foundation.js +447 -0
  105. package/lib/schema/page-data-source-builder.js +561 -0
  106. package/lib/schema/page-foundation.js +556 -0
  107. package/lib/schema/page-source-loader.js +314 -0
  108. package/lib/schema/planner.js +691 -0
  109. package/lib/schema/remote-dispatch-boundary.js +39 -0
  110. package/lib/schema/remote-missing.js +21 -0
  111. package/lib/schema/remote-reader.js +189 -0
  112. package/lib/schema/resource-registry.js +157 -0
  113. package/lib/schema/server-revision.js +71 -0
  114. package/lib/schema/sort.js +28 -0
  115. package/lib/schema/state-store.js +589 -0
  116. package/package.json +10 -8
  117. package/scripts/check-release-risks.js +254 -0
  118. package/scripts/generate-command-docs.js +6 -1
  119. package/scripts/i18n-baseline.json +11 -11
  120. package/scripts/postinstall.js +8 -12
  121. package/scripts/validate-ci.sh +15 -11
  122. package/scripts/validate-i18n.js +30 -9
  123. package/scripts/validate-package-size.js +5 -2
  124. package/scripts/validate-skills.js +4 -0
  125. package/scripts/validate-structure.js +15 -0
  126. package/yida-skills/SKILL.md +117 -30
  127. package/yida-skills/references/schema-as-code-phase1.md +99 -0
  128. package/yida-skills/references/setup-and-env.md +59 -59
  129. package/yida-skills/references/task-retrospective.md +6 -6
  130. package/yida-skills/skills/yida-app/SKILL.md +78 -17
  131. package/yida-skills/skills/yida-canvas-custom-page/SKILL.md +18 -7
  132. package/yida-skills/skills/yida-canvas-custom-page/references/data-bridge-guide.md +3 -3
  133. package/yida-skills/skills/yida-canvas-custom-page/references/page-generation-guide.md +15 -0
  134. package/yida-skills/skills/yida-create-app/SKILL.md +21 -3
  135. package/yida-skills/skills/yida-create-form-page/SKILL.md +19 -1
  136. package/yida-skills/skills/yida-create-page/SKILL.md +16 -3
  137. package/yida-skills/skills/yida-create-process/SKILL.md +100 -4
  138. package/yida-skills/skills/yida-custom-page/SKILL.md +19 -4
  139. package/yida-skills/skills/yida-dashboard/SKILL.md +1 -1
  140. package/yida-skills/skills/yida-dashboard/references/pitfalls.md +1 -1
  141. package/yida-skills/skills/yida-get-schema/SKILL.md +49 -5
  142. package/yida-skills/skills/yida-i18n/SKILL.md +1 -1
  143. package/yida-skills/skills/yida-integration/SKILL.md +7 -1
  144. package/yida-skills/skills/yida-login/SKILL.md +50 -99
  145. package/yida-skills/skills/yida-page-config/SKILL.md +7 -1
  146. package/yida-skills/skills/yida-page-uiux/references/app/blueprint.md +0 -1
  147. package/yida-skills/skills/yida-page-uiux/references/app/navigation-patterns.md +0 -1
  148. package/yida-skills/skills/yida-page-uiux/references/app/role-journey.md +0 -1
  149. package/yida-skills/skills/yida-page-uiux/references/dashboard/app-blueprint.md +0 -1
  150. package/yida-skills/skills/yida-page-uiux/references/dashboard/chart-contracts.md +0 -1
  151. package/yida-skills/skills/yida-page-uiux/references/dashboard/component-contracts.md +0 -1
  152. package/yida-skills/skills/yida-page-uiux/references/dashboard/layout-patterns.md +0 -1
  153. package/yida-skills/skills/yida-page-uiux/references/dashboard/theme-recipes.md +0 -1
  154. package/yida-skills/skills/yida-page-uiux/references/detail/object-narrative.md +0 -1
  155. package/yida-skills/skills/yida-page-uiux/references/detail/section-patterns.md +0 -1
  156. package/yida-skills/skills/yida-page-uiux/references/detail/timeline-and-related.md +0 -1
  157. package/yida-skills/skills/yida-page-uiux/references/landing/assets-workflow.md +0 -1
  158. package/yida-skills/skills/yida-page-uiux/references/landing/industry-playbooks.md +0 -1
  159. package/yida-skills/skills/yida-page-uiux/references/landing/research-levels.md +0 -1
  160. package/yida-skills/skills/yida-page-uiux/references/landing/section-patterns.md +0 -1
  161. package/yida-skills/skills/yida-page-uiux/references/list/drawer-detail.md +0 -1
  162. package/yida-skills/skills/yida-page-uiux/references/list/empty-loading-error.md +0 -1
  163. package/yida-skills/skills/yida-page-uiux/references/list/filter-patterns.md +0 -1
  164. package/yida-skills/skills/yida-page-uiux/references/list/table-patterns.md +0 -1
  165. package/yida-skills/skills/yida-page-uiux/references/scenes/screen.md +0 -1
  166. package/yida-skills/skills/yida-page-uiux/references/workbench/entry-patterns.md +0 -1
  167. package/yida-skills/skills/yida-page-uiux/references/workbench/portal-layouts.md +0 -1
  168. package/yida-skills/skills/yida-page-uiux/references/workbench/task-feed.md +0 -1
  169. package/yida-skills/skills/yida-page-uiux/workflow/output-decision-block.md +1 -1
  170. package/yida-skills/skills/yida-process-rule/SKILL.md +35 -1
  171. package/yida-skills/skills/yida-publish-page/SKILL.md +46 -4
  172. package/yida-skills/skills/yida-report/SKILL.md +9 -235
  173. package/yida-skills/skills/yida-report/references/schema-builder-details.md +239 -0
  174. package/yida-skills/skills/yida-skill-evaluator/SKILL.md +170 -0
  175. package/yida-skills/skills-index.json +238 -54
  176. package/lib/core/locales/ar.js +0 -834
  177. package/lib/core/locales/de.js +0 -834
  178. package/lib/core/locales/es.js +0 -834
  179. package/lib/core/locales/fr.js +0 -834
  180. package/lib/core/locales/hi.js +0 -834
  181. package/lib/core/locales/ja.js +0 -1227
  182. package/lib/core/locales/ko.js +0 -836
  183. package/lib/core/locales/pt.js +0 -834
  184. package/lib/core/locales/vi.js +0 -834
  185. package/lib/core/locales/zh-HK.js +0 -1263
  186. package/project/pages/src/demo-birthday-game.oyd.jsx +0 -832
  187. package/project/pages/src/demo-chip-insight.oyd.jsx +0 -983
  188. package/project/pages/src/demo-compat-smoke.oyd.jsx +0 -58
  189. package/project/pages/src/demo-crm-batch-entry.oyd.jsx +0 -805
  190. package/project/pages/src/demo-crm-dashboard.oyd.jsx +0 -677
  191. package/project/pages/src/demo-future-vision-2026.oyd.jsx +0 -1102
  192. package/project/pages/src/demo-ppt.oyd.jsx +0 -1192
  193. package/project/pages/src/demo-salary-calculator.oyd.jsx +0 -904
  194. package/project/pages/src/openyida-knowledge-doc.oyd.jsx +0 -1714
  195. package/yida-skills/skills/large-file-write/SKILL.md +0 -93
  196. package/yida-skills/skills/large-file-write/references/write-patterns.md +0 -147
  197. package/yida-skills/skills/large-file-write/scripts/write.js +0 -157
  198. package/yida-skills/skills/sls-log-workbench/SKILL.md +0 -134
  199. package/yida-skills/skills/sls-log-workbench/references/workbench-reference.md +0 -130
  200. package/yida-skills/skills/sls-log-workbench/sls-query.js +0 -295
@@ -6,6 +6,7 @@ const {
6
6
  resolveBaseUrl,
7
7
  } = require('../core/utils');
8
8
  const { createYidaClient } = require('../core/yida-client');
9
+ const { throwUsage } = require('../core/command-errors');
9
10
 
10
11
  const API = {
11
12
  commodityInfo: '/query/commodity/getCommodityInfo.json',
@@ -351,7 +352,7 @@ async function run(args = []) {
351
352
  }
352
353
  default:
353
354
  printUsage();
354
- process.exit(1);
355
+ throwUsage('Unsupported basic-info command: ' + subcommand, 'Run openyida basic-info --help for usage.');
355
356
  }
356
357
  }
357
358
 
@@ -6,6 +6,7 @@ const path = require('path');
6
6
  const { spawn } = require('child_process');
7
7
 
8
8
  const { parseOpenOption } = require('../core/browser-handoff');
9
+ const { resolveBrowserLauncher } = require('../auth/oauth-loopback');
9
10
  const { banner, label, success, hint, fail } = require('../core/chalk');
10
11
 
11
12
  const DEFAULT_HOST = '127.0.0.1';
@@ -515,6 +516,7 @@ function sanitizeLoginResult(result = {}) {
515
516
  canAutoUse: !!(result.can_auto_use || result.canAutoUse),
516
517
  loggedIn: status === 'ok',
517
518
  authMode: result.auth_mode || result.authMode,
519
+ authSource: result.auth_source || result.authSource,
518
520
  baseUrlOrigin: originFromUrl(result.base_url || result.baseUrl),
519
521
  corpId: maskId(result.corp_id || result.corpId),
520
522
  userId: maskId(result.user_id || result.userId),
@@ -536,6 +538,36 @@ function sanitizeQrLoginStart(result = {}, loginSessionId) {
536
538
  };
537
539
  }
538
540
 
541
+ function isTokenLoginStartResult(result = {}) {
542
+ const authMode = result.auth_mode || result.authMode;
543
+ return authMode === 'token' || result.status === 'token_login_required';
544
+ }
545
+
546
+ function sanitizeTokenLoginStart(result = {}) {
547
+ const status = result.status || 'token_login_required';
548
+ return {
549
+ status,
550
+ canAutoUse: !!(result.can_auto_use || result.canAutoUse),
551
+ loggedIn: status === 'ok',
552
+ authMode: result.auth_mode || result.authMode || 'token',
553
+ authSource: result.auth_source || result.authSource,
554
+ baseUrlOrigin: originFromUrl(result.base_url || result.baseUrl),
555
+ corpId: maskId(result.corp_id || result.corpId),
556
+ userId: maskId(result.user_id || result.userId),
557
+ diagnostics: sanitizeDiagnostics(result.diagnostics || {}),
558
+ pollable: false,
559
+ loginSessionId: null,
560
+ message: result.message ? String(result.message).slice(0, 300) : undefined,
561
+ };
562
+ }
563
+
564
+ function sanitizeLoginStart(result = {}, loginSessionId) {
565
+ if (isTokenLoginStartResult(result)) {
566
+ return sanitizeTokenLoginStart(result);
567
+ }
568
+ return sanitizeQrLoginStart(result, loginSessionId);
569
+ }
570
+
539
571
  function getBridgeInfo(state) {
540
572
  return {
541
573
  ok: true,
@@ -559,8 +591,8 @@ function getBridgeInfo(state) {
559
591
  }
560
592
 
561
593
  function defaultCheckLogin() {
562
- const { tokenStatus } = require('../auth/token-auth');
563
- return tokenStatus({ includeSecrets: false });
594
+ const { getAuthStatus } = require('../core/utils');
595
+ return getAuthStatus({ includeSecrets: false });
564
596
  }
565
597
 
566
598
  async function defaultStartLogin() {
@@ -765,8 +797,9 @@ async function handleLoginStart(req, res, state) {
765
797
 
766
798
  const startLogin = getHandler(state, 'startLogin', defaultStartLogin);
767
799
  const result = await startLogin(body);
768
- const loginSessionId = randomToken();
769
- if (result.session_file) {
800
+ const tokenLoginStart = isTokenLoginStartResult(result);
801
+ const loginSessionId = tokenLoginStart ? null : randomToken();
802
+ if (!tokenLoginStart && result && result.session_file) {
770
803
  state.loginSessions.set(loginSessionId, {
771
804
  sessionFile: result.session_file,
772
805
  createdAt: new Date().toISOString(),
@@ -775,7 +808,7 @@ async function handleLoginStart(req, res, state) {
775
808
 
776
809
  respondJson(req, res, state, 200, {
777
810
  ok: true,
778
- login: sanitizeQrLoginStart(result, loginSessionId),
811
+ login: sanitizeLoginStart(result, loginSessionId),
779
812
  });
780
813
  }
781
814
 
@@ -1128,19 +1161,11 @@ async function startBridgeServer(options = {}) {
1128
1161
  }
1129
1162
 
1130
1163
  function openExternalUrl(url) {
1131
- const platform = process.platform;
1132
- let command;
1133
- let args;
1134
- if (platform === 'darwin') {
1135
- command = 'open';
1136
- args = [url];
1137
- } else if (platform === 'win32') {
1138
- command = 'cmd';
1139
- args = ['/c', 'start', '', url];
1140
- } else {
1141
- command = 'xdg-open';
1142
- args = [url];
1143
- }
1164
+ // Reuse the shared launcher so the URL is passed as a single argument.
1165
+ // On Windows this avoids `cmd /c start` splitting the URL on `&`, which
1166
+ // would drop the bridge params carried in the URL hash
1167
+ // (oy_bridge_url / oy_bridge_token) and break bridge pairing.
1168
+ const { command, args } = resolveBrowserLauncher(url);
1144
1169
 
1145
1170
  const child = spawn(command, args, {
1146
1171
  detached: true,
@@ -6,7 +6,7 @@ const { version } = require('../../package.json');
6
6
  const { t } = require('./i18n');
7
7
  const { buildCommandManifest } = require('./command-manifest');
8
8
  const { buildEnvironmentSnapshot } = require('./env');
9
- const { tokenStatus } = require('../auth/token-auth');
9
+ const { getAuthStatus } = require('./utils');
10
10
 
11
11
  function redactLogin(login) {
12
12
  const redacted = { ...login };
@@ -18,6 +18,8 @@ function redactLogin(login) {
18
18
  function compactLogin(login) {
19
19
  return {
20
20
  status: login.status,
21
+ auth_mode: login.auth_mode,
22
+ auth_source: login.auth_source,
21
23
  can_auto_use: login.can_auto_use === true,
22
24
  };
23
25
  }
@@ -68,9 +70,9 @@ function buildCommandManifestDigest(manifest) {
68
70
 
69
71
  function buildAgentCapabilitiesSummary() {
70
72
  const envSnapshot = buildEnvironmentSnapshot();
71
- const loginStatus = tokenStatus({ includeSecrets: false });
72
73
  const manifest = buildCommandManifest({ t, version });
73
74
  const projectRoot = envSnapshot.active.projectRoot;
75
+ const loginStatus = getAuthStatus({ projectRoot, includeSecrets: false });
74
76
 
75
77
  return {
76
78
  schema_version: 1,
@@ -90,9 +92,9 @@ function buildAgentCapabilitiesSummary() {
90
92
 
91
93
  function buildAgentCapabilities() {
92
94
  const envSnapshot = buildEnvironmentSnapshot();
93
- const loginStatus = redactLogin(tokenStatus({ includeSecrets: false }));
94
95
  const manifest = buildCommandManifest({ t, version });
95
96
  const projectRoot = envSnapshot.active.projectRoot;
97
+ const loginStatus = redactLogin(getAuthStatus({ projectRoot, includeSecrets: false }));
96
98
 
97
99
  return {
98
100
  schema_version: 1,
@@ -0,0 +1,38 @@
1
+ 'use strict';
2
+
3
+ const { CliError } = require('./cli-error');
4
+
5
+ function joinMessage(lines) {
6
+ return lines.filter(Boolean).join('\n');
7
+ }
8
+
9
+ function throwUsage(usage, example, options = {}) {
10
+ throw new CliError(joinMessage([usage, example]), {
11
+ code: options.code || 'CLI_INVALID_ARGUMENTS',
12
+ exitCode: options.exitCode || 1,
13
+ usage: example,
14
+ details: options.details,
15
+ });
16
+ }
17
+
18
+ function throwCommandError(message, options = {}) {
19
+ throw new CliError(message, {
20
+ code: options.code || 'CLI_COMMAND_FAILED',
21
+ exitCode: options.exitCode || 1,
22
+ details: options.details,
23
+ usage: options.usage,
24
+ });
25
+ }
26
+
27
+ function throwStatus(message, exitCode, options = {}) {
28
+ throwCommandError(message, {
29
+ ...options,
30
+ exitCode,
31
+ });
32
+ }
33
+
34
+ module.exports = {
35
+ throwUsage,
36
+ throwCommandError,
37
+ throwStatus,
38
+ };
@@ -193,8 +193,13 @@ const COMMAND_SIDE_EFFECTS = new Map([
193
193
  'dingtalk-link',
194
194
  'formula.evaluate',
195
195
  'integration.diagnose',
196
+ 'schema.validate',
196
197
  ], sideEffect('local_read')),
197
198
 
199
+ ...sideEffectEntries([
200
+ 'schema.plan',
201
+ ], sideEffect('remote_read')),
202
+
198
203
  ...sideEffectEntries([
199
204
  'build-page',
200
205
  'cdn-config',
@@ -212,6 +217,13 @@ const COMMAND_SIDE_EFFECTS = new Map([
212
217
  'update',
213
218
  ], sideEffect('local_write')),
214
219
 
220
+ ...sideEffectEntries([
221
+ 'eval',
222
+ ], sideEffect('mixed', {
223
+ read_actions: ['doc-quality', 'coverage', 'routing', 'safety', 'comprehensive', 'baseline', 'pipeline'],
224
+ mutating_actions: ['e2e', 'generate'],
225
+ })),
226
+
215
227
  ...sideEffectEntries([
216
228
  'app-list',
217
229
  'connector.detail',
@@ -233,7 +245,7 @@ const COMMAND_SIDE_EFFECTS = new Map([
233
245
  ['asset', sideEffect('mixed', {
234
246
  mutates_yida: false,
235
247
  mutates_local: true,
236
- read_actions: ['status', 'verify-url', 'generate', 'resolve without --upload-assets'],
248
+ read_actions: ['status', 'verify-url', 'generate', 'resolve'],
237
249
  mutating_actions: ['resolve --upload-assets', 'resolve --mirror-external'],
238
250
  })],
239
251
 
@@ -279,6 +291,12 @@ const COMMAND_SIDE_EFFECTS = new Map([
279
291
  read_actions: ['text', 'image --image-url'],
280
292
  mutating_actions: ['image --file'],
281
293
  })],
294
+ ['schema.apply', sideEffect('mixed', {
295
+ mutates_yida: true,
296
+ mutates_local: true,
297
+ read_actions: [],
298
+ mutating_actions: ['apply'],
299
+ })],
282
300
  ['ai-form-setting', sideEffect('mixed', {
283
301
  mutates_yida: true,
284
302
  mutates_local: false,
@@ -445,11 +463,20 @@ const COMMAND_PERMISSIONS = new Map([
445
463
  'integration.list',
446
464
  'list-forms',
447
465
  'process.preview',
466
+ 'schema.plan',
467
+ 'schema.validate',
448
468
  'verify-short-url',
449
469
  ], permission('allow', 'read', {
450
470
  reason: 'Read-only, diagnostic, validation, or manifest discovery command.',
451
471
  })),
452
472
 
473
+ ...permissionEntries([
474
+ 'eval',
475
+ ], actionDependentPermission({
476
+ preauthorized_actions: ['doc-quality', 'coverage', 'routing', 'safety', 'comprehensive', 'baseline', 'pipeline'],
477
+ ask_actions: ['e2e', 'generate'],
478
+ })),
479
+
453
480
  ...permissionEntries([
454
481
  'add-validation',
455
482
  'append-chart',
@@ -496,6 +523,17 @@ const COMMAND_PERMISSIONS = new Map([
496
523
  reason: ALLOW_WRITE_REASON,
497
524
  })),
498
525
 
526
+ ['schema.apply', permission('allow', 'write', {
527
+ reason: ALLOW_WRITE_REASON,
528
+ action_dependent: true,
529
+ read_actions: [],
530
+ preauthorized_actions: ['apply'],
531
+ preauthorized_patterns: [],
532
+ ask_actions: [],
533
+ ask_patterns: [],
534
+ unknown_action_mode: 'ask',
535
+ })],
536
+
499
537
  ...permissionEntries([
500
538
  'login',
501
539
  'logout',
@@ -785,6 +823,22 @@ const COMMAND_GROUPS = [
785
823
  command('get-form-config', ['get-form-config'], 'get-form-config <appType> <formUuid> [--json]', 'help.cmd_get_form_config', { output: 'json' }),
786
824
  ],
787
825
  },
826
+ {
827
+ id: 'schema',
828
+ titleKey: 'help.group_schema',
829
+ commands: [
830
+ command('schema.validate', ['schema', 'validate'], 'schema validate <manifest> --json --quiet', 'help.cmd_schema_validate', {
831
+ requiresLogin: false,
832
+ output: 'json',
833
+ }),
834
+ command('schema.plan', ['schema', 'plan'], 'schema plan <manifest> --state <path> --json --quiet', 'help.cmd_schema_plan', {
835
+ output: 'json',
836
+ }),
837
+ command('schema.apply', ['schema', 'apply'], 'schema apply <manifest> --state <path> --plan-id <planId> --json --quiet', 'help.cmd_schema_apply', {
838
+ output: 'json',
839
+ }),
840
+ ],
841
+ },
788
842
  {
789
843
  id: 'data',
790
844
  titleKey: 'help.group_data',
@@ -907,6 +961,10 @@ const COMMAND_GROUPS = [
907
961
  command('copy', ['copy'], 'copy [--force]', 'help.cmd_copy', { requiresLogin: false }),
908
962
  command('sample', ['sample'], 'sample [--list]', 'help.cmd_sample', { requiresLogin: false }),
909
963
  command('doctor', ['doctor'], 'doctor [--fix]', 'help.cmd_doctor', { requiresLogin: false }),
964
+ command('eval', ['eval'], 'eval --mode <mode> [--skill <name>] [--runs N]', 'help.cmd_eval', {
965
+ requiresLogin: false,
966
+ output: 'text|json',
967
+ }),
910
968
  command('db-seq-fix', ['db-seq-fix'], 'db-seq-fix [--fix]', 'help.cmd_db_seq_fix'),
911
969
  command('formula.evaluate', ['formula', 'evaluate'], 'formula evaluate <formula|file> [--schema file]', 'help.cmd_formula_evaluate', {
912
970
  requiresLogin: false,
package/lib/core/copy.js CHANGED
@@ -36,6 +36,10 @@ const PROJECT_COPY_IGNORE_PATHS = [
36
36
  path.join('pages', 'dist'),
37
37
  ];
38
38
 
39
+ const PROJECT_WORKSPACE_DIRS = [
40
+ path.join('pages', 'src'),
41
+ ];
42
+
39
43
  /**
40
44
  * 查找 npm 全局安装包根目录。
41
45
  * 优先通过 require.resolve 定位(适用于正式全局安装),
@@ -150,6 +154,12 @@ function forceCopyDir(sourceDir, destDir, options = {}) {
150
154
  return mergeCopyDir(sourceDir, destDir, options);
151
155
  }
152
156
 
157
+ function ensureProjectWorkspaceDirs(projectDir) {
158
+ PROJECT_WORKSPACE_DIRS.forEach((relativeDir) => {
159
+ fs.mkdirSync(path.join(projectDir, relativeDir), { recursive: true });
160
+ });
161
+ }
162
+
153
163
  /**
154
164
  * 删除已有的 yida-skills 软链接或目录(悟空环境专用)。
155
165
  * 悟空通过手动上传技能,不需要软链,执行 -skills 时只做清理。
@@ -305,6 +315,7 @@ function run(args = process.argv.slice(3)) {
305
315
  ignorePaths: PROJECT_COPY_IGNORE_PATHS,
306
316
  sourceRoot: packageProjectDir,
307
317
  });
318
+ ensureProjectWorkspaceDirs(projectDestDir);
308
319
  results.push({ label: 'project/', dest: projectDestDir, count, type: 'copy' });
309
320
  }
310
321
 
@@ -391,6 +402,7 @@ module.exports = {
391
402
  run,
392
403
  _internal: {
393
404
  forceCopyDir,
405
+ ensureProjectWorkspaceDirs,
394
406
  resolveDestBaseFromEnv,
395
407
  },
396
408
  };
@@ -202,7 +202,7 @@ class EnvironmentChecker {
202
202
  label: '可选浏览器能力(Playwright 已安装)',
203
203
  passed: true,
204
204
  severity: Severity.INFO,
205
- message: '当前 CLI 默认使用 OAuth token 登录;Playwright 仅用于少量浏览器预览或兼容场景',
205
+ message: '当前 CLI 默认使用 OAuth token 登录;Playwright 仅用于少量浏览器预览或截图评测',
206
206
  fixType: null,
207
207
  };
208
208
  } catch {
@@ -254,10 +254,21 @@ class EnvironmentChecker {
254
254
  }
255
255
 
256
256
  checkLoginStatus() {
257
- const { tokenStatus } = require('../auth/token-auth');
258
- const status = tokenStatus({ projectRoot: this.projectRoot });
257
+ const { getAuthStatus, isEnvAuthMode } = require('./utils');
258
+ const status = getAuthStatus({ projectRoot: this.projectRoot });
259
259
 
260
- if (status.status !== 'ok') {
260
+ if (!status.ok) {
261
+ if (isEnvAuthMode()) {
262
+ return {
263
+ id: 'env-login',
264
+ label: '宜搭宿主 token 注入登录态',
265
+ passed: false,
266
+ severity: Severity.WARNING,
267
+ message: `宿主 token 注入不可用(${status.failure_reason || status.status}),请回到宿主环境注入 OPENYIDA_ACCESS_TOKEN 或 OPENYIDA_REFRESH_TOKEN`,
268
+ fixType: null,
269
+ fixCommand: null,
270
+ };
271
+ }
261
272
  return {
262
273
  id: 'env-login',
263
274
  label: '宜搭 token 登录态',
@@ -145,7 +145,7 @@ function switchToEnv(envName) {
145
145
  console.log(` 地址:${config.environments[resolvedEnvName].baseUrl}`);
146
146
  console.log(` 登录:${getLoginHost(config.environments[resolvedEnvName].loginUrl)}`);
147
147
  console.log('');
148
- console.log(`${DIM}下一步:运行 openyida login;在悟空中可运行 openyida login --wukong${RESET}`);
148
+ console.log(`${DIM}下一步:运行 openyida login;在宿主注入 token 模式中请先确认宿主已注入 OPENYIDA_ACCESS_TOKEN 或 OPENYIDA_REFRESH_TOKEN${RESET}`);
149
149
  console.log('');
150
150
  }
151
151
 
package/lib/core/env.js CHANGED
@@ -12,6 +12,7 @@ const os = require('os');
12
12
  const {
13
13
  detectActiveTool,
14
14
  findProjectRoot,
15
+ getAuthStatus,
15
16
  resolveWukongWorkspaceRoot,
16
17
  } = require('./utils');
17
18
  const { t } = require('./i18n');
@@ -98,29 +99,29 @@ function getTokenDiagnostics(projectRoot) {
98
99
  * 检测登录态信息。
99
100
  */
100
101
  function detectLoginStatus(projectRoot) {
101
- const tokenDiagnostics = getTokenDiagnostics(projectRoot);
102
- const { tokenStatus } = require('../auth/token-auth');
103
- const status = tokenStatus({ projectRoot });
102
+ const status = getAuthStatus({ projectRoot });
104
103
  const loggedIn = status.status === 'ok';
105
104
 
105
+ const tokenDiagnostics = getTokenDiagnostics(projectRoot);
106
106
  return {
107
107
  loggedIn,
108
108
  canAutoUse: !!status.can_auto_use,
109
109
  corpId: status.corp_id || null,
110
110
  userId: status.user_id || null,
111
111
  baseUrl: status.base_url || null,
112
- authSource: 'token',
112
+ authSource: status.auth_source || 'token',
113
113
  authMode: 'token',
114
114
  tokenFile: status.token_file || tokenDiagnostics.tokenFile,
115
115
  diagnostics: {
116
116
  ...tokenDiagnostics,
117
- authSource: 'token',
117
+ authSource: status.auth_source || 'token',
118
+ authMode: 'token',
118
119
  cacheReadable: tokenDiagnostics.tokenFileFound,
119
120
  tokenFound: loggedIn,
120
121
  corpIdFound: !!status.corp_id,
121
122
  userIdFound: !!status.user_id,
122
123
  baseUrlFound: !!status.base_url,
123
- failureReason: loggedIn ? null : status.status,
124
+ failureReason: loggedIn ? null : (status.failure_reason || status.status),
124
125
  },
125
126
  };
126
127
  }
package/lib/core/i18n.js CHANGED
@@ -28,8 +28,15 @@
28
28
 
29
29
  'use strict';
30
30
 
31
+ const fs = require('fs');
32
+ const path = require('path');
33
+
31
34
  const SUPPORTED_LANGUAGES = ['zh', 'zh-HK', 'en', 'ja', 'ko', 'fr', 'de', 'es', 'pt', 'vi', 'hi', 'ar'];
35
+ const CORE_LANGUAGES = ['zh', 'en'];
36
+ const OPTIONAL_LANGUAGES = SUPPORTED_LANGUAGES.filter(lang => !CORE_LANGUAGES.includes(lang));
32
37
  const DEFAULT_LANGUAGE = 'zh';
38
+ const CORE_LOCALE_DIR = path.join(__dirname, 'locales');
39
+ const SOURCE_EXTRA_LOCALE_DIR = path.resolve(__dirname, '..', '..', 'locales-extra', 'core');
33
40
 
34
41
  /**
35
42
  * 将系统 locale 代码映射到支持的语言代码。
@@ -91,18 +98,57 @@ function detectLanguage() {
91
98
  let currentLanguage = detectLanguage();
92
99
  let translations = null;
93
100
 
101
+ function getLocaleSearchDirs() {
102
+ const dirs = [CORE_LOCALE_DIR];
103
+ const extraDirs = String(process.env.OPENYIDA_LOCALE_DIR || '')
104
+ .split(path.delimiter)
105
+ .map(item => item.trim())
106
+ .filter(Boolean);
107
+ dirs.push(...extraDirs);
108
+ dirs.push(SOURCE_EXTRA_LOCALE_DIR);
109
+ return [...new Set(dirs)];
110
+ }
111
+
112
+ function resolveLocaleFile(lang) {
113
+ if (!SUPPORTED_LANGUAGES.includes(lang)) {
114
+ return null;
115
+ }
116
+
117
+ for (const dir of getLocaleSearchDirs()) {
118
+ const direct = path.join(dir, `${lang}.js`);
119
+ if (fs.existsSync(direct)) {
120
+ return direct;
121
+ }
122
+ const nested = path.join(dir, 'core', `${lang}.js`);
123
+ if (fs.existsSync(nested)) {
124
+ return nested;
125
+ }
126
+ }
127
+
128
+ return null;
129
+ }
130
+
131
+ function loadLocaleForLanguage(lang) {
132
+ const file = resolveLocaleFile(lang);
133
+ if (!file) {
134
+ return null;
135
+ }
136
+ return require(file);
137
+ }
138
+
139
+ function getAvailableLanguages() {
140
+ return SUPPORTED_LANGUAGES.filter(lang => !!resolveLocaleFile(lang));
141
+ }
142
+
94
143
  /**
95
144
  * 懒加载翻译文件。
96
145
  * @returns {object} 翻译字典
97
146
  */
98
147
  function loadTranslations() {
99
148
  if (translations) {return translations;}
100
- try {
101
- translations = require(`./locales/${currentLanguage}`);
102
- } catch {
103
- // 加载失败时回退到中文
104
- translations = require('./locales/zh');
105
- }
149
+ translations = loadLocaleForLanguage(currentLanguage)
150
+ || loadLocaleForLanguage('en')
151
+ || loadLocaleForLanguage('zh');
106
152
  return translations;
107
153
  }
108
154
 
@@ -127,7 +173,8 @@ function t(key, ...args) {
127
173
  if (currentLanguage !== 'en') { fallbackLangs.push('en'); }
128
174
  if (currentLanguage !== 'zh') { fallbackLangs.push('zh'); }
129
175
  for (const lang of fallbackLangs) {
130
- const fbDict = require(`./locales/${lang}`);
176
+ const fbDict = loadLocaleForLanguage(lang);
177
+ if (!fbDict) { continue; }
131
178
  const fbValue = key.split('.').reduce((obj, segment) => {
132
179
  return obj && typeof obj === 'object' ? obj[segment] : undefined;
133
180
  }, fbDict);
@@ -178,4 +225,15 @@ function setLanguage(lang) {
178
225
  }
179
226
  }
180
227
 
181
- module.exports = { t, getLanguage, setLanguage, detectLanguage, SUPPORTED_LANGUAGES };
228
+ module.exports = {
229
+ t,
230
+ getLanguage,
231
+ setLanguage,
232
+ detectLanguage,
233
+ SUPPORTED_LANGUAGES,
234
+ CORE_LANGUAGES,
235
+ OPTIONAL_LANGUAGES,
236
+ getAvailableLanguages,
237
+ loadLocaleForLanguage,
238
+ resolveLocaleFile,
239
+ };