openyida 2026.8.17 → 2026.8.19-1

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 (70) hide show
  1. package/README.md +17 -7
  2. package/bin/yida.js +78 -11
  3. package/docs/capabilities.md +3 -3
  4. package/lib/app/app-lifecycle.js +1 -2
  5. package/lib/app/builder-ai-source.js +39 -0
  6. package/lib/app/check-prd-completeness.js +631 -0
  7. package/lib/app/create-app.js +2 -1
  8. package/lib/app/create-form.js +3 -4
  9. package/lib/app/create-page.js +2 -4
  10. package/lib/app/display-page-readback.js +187 -0
  11. package/lib/app/form-detail-style.js +5 -15
  12. package/lib/app/import-app.js +7 -15
  13. package/lib/app/publish.js +73 -243
  14. package/lib/app/update-app.js +30 -6
  15. package/lib/auth/oauth-loopback.js +15 -3
  16. package/lib/auth/org.js +164 -25
  17. package/lib/auth/profile.js +226 -0
  18. package/lib/auth/token-auth.js +161 -19
  19. package/lib/auth/token-store.js +734 -68
  20. package/lib/core/agent-capabilities.js +240 -19
  21. package/lib/core/command-manifest.js +12 -5
  22. package/lib/core/copy.js +55 -20
  23. package/lib/core/env.js +36 -2
  24. package/lib/core/locales/en.js +44 -27
  25. package/lib/core/locales/zh.js +41 -24
  26. package/lib/core/utils.js +663 -257
  27. package/lib/core/yida-client.js +21 -58
  28. package/lib/report/append.js +1 -1
  29. package/package.json +1 -1
  30. package/scripts/postinstall.js +26 -10
  31. package/yida-skills/SKILL.md +3 -1
  32. package/yida-skills/references/field-and-url-reference.md +21 -3
  33. package/yida-skills/references/setup-and-env.md +10 -1
  34. package/yida-skills/references/task-retrospective.md +1 -1
  35. package/yida-skills/skills/yida-app/SKILL.md +1 -1
  36. package/yida-skills/skills/yida-app/workflow/step-7-page-code.md +4 -2
  37. package/yida-skills/skills/yida-app/workflow/step-8-publish-navigation.md +1 -0
  38. package/yida-skills/skills/yida-app/workflow/step-9-output-finish.md +28 -2
  39. package/yida-skills/skills/yida-canvas-custom-page/SKILL.md +4 -4
  40. package/yida-skills/skills/yida-canvas-custom-page/references/canvas-style-implementation-guide.md +2 -2
  41. package/yida-skills/skills/yida-canvas-custom-page/references/navigation-and-entry-guide.md +20 -2
  42. package/yida-skills/skills/yida-canvas-custom-page/references/page-generation-guide.md +21 -3
  43. package/yida-skills/skills/yida-canvas-custom-page/references/theme-runtime-helpers.md +1 -1
  44. package/yida-skills/skills/yida-create-page/SKILL.md +1 -1
  45. package/yida-skills/skills/yida-custom-page/SKILL.md +3 -3
  46. package/yida-skills/skills/yida-custom-page/references/coding-guide.md +1 -1
  47. package/yida-skills/skills/yida-dashboard/SKILL.md +1 -1
  48. package/yida-skills/skills/yida-dashboard/references/interaction-patterns.md +6 -5
  49. package/yida-skills/skills/yida-dashboard/references/structure-and-layout.md +1 -1
  50. package/yida-skills/skills/yida-design/SKILL.md +3 -4
  51. package/yida-skills/skills/yida-design/references/app/blueprint.md +10 -1
  52. package/yida-skills/skills/yida-design/references/app/navigation-patterns.md +13 -3
  53. package/yida-skills/skills/yida-design/references/page-quality-gates.md +1 -1
  54. package/yida-skills/skills/yida-design/references/style-design-selection.md +2 -2
  55. package/yida-skills/skills/yida-design/references/visual-decision-engine.md +1 -1
  56. package/yida-skills/skills/yida-design/sub_skill/page-design/SKILL.md +2 -2
  57. package/yida-skills/skills/yida-design/workflow/output-design.md +1 -1
  58. package/yida-skills/skills/yida-design/workflow/output-prd.md +3 -3
  59. package/yida-skills/skills/yida-design/workflow/step-2-theme-system.md +2 -2
  60. package/yida-skills/skills/yida-design/workflow/step-3-information-architecture.md +18 -6
  61. package/yida-skills/skills/yida-design/workflow/step-4-wireframe-interaction.md +3 -3
  62. package/yida-skills/skills/yida-login/SKILL.md +19 -4
  63. package/yida-skills/skills/yida-logout/SKILL.md +24 -13
  64. package/yida-skills/skills/yida-nav-shell/SKILL.md +40 -132
  65. package/yida-skills/skills/yida-nav-shell/references/nav-shell-patterns.md +18 -10
  66. package/yida-skills/skills/yida-page-config/SKILL.md +10 -3
  67. package/yida-skills/skills/yida-ppt-slider/SKILL.md +1 -1
  68. package/yida-skills/skills/yida-ppt-slider/references/examples.md +1 -1
  69. package/yida-skills/skills/yida-publish-page/SKILL.md +7 -7
  70. package/yida-skills/skills-index.json +1 -1
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  <div align="center">
2
2
 
3
- ![OpenYida](https://img.alicdn.com/imgextra/i2/O1CN01wTOPxK1nEA3rWDp6I_!!6000000005057-2-tps-1672-941.png)
3
+ ![OpenYida](https://img.alicdn.com/imgextra/i2/O1CN01fwUxry9qUtJ3OTaP_!!6000000008165-2-tps-1672-941.png)
4
4
 
5
5
  # OpenYida
6
6
 
@@ -68,9 +68,9 @@ OpenYida returns a compact machine-readable summary with the version, login stat
68
68
  openyida login
69
69
  ```
70
70
 
71
- OpenYida login defaults to OAuth token mode. It opens the DingTalk OAuth authorization page, receives the local loopback callback, exchanges `code` / `authCode` with the Yida server, and stores `access_token` / `refresh_token` in the current project cache.
71
+ OpenYida login defaults to OAuth token mode. It opens the DingTalk OAuth authorization page, receives the local loopback callback, exchanges `code` / `authCode` with the Yida server, and stores `access_token` / `refresh_token` in the user auth store when available. If the user auth store is not writable, OpenYida explicitly falls back to the current project cache and reports that narrower persistence scope.
72
72
 
73
- When the user names a target Yida entry URL, pass it to the login command so OpenYida can select the matching environment and token session file. For example, Alibaba intranet Yida uses `auth-token-alibaba.json`:
73
+ When the user names a target Yida entry URL, pass it to the login command so OpenYida can select the matching environment and auth profile. For example:
74
74
 
75
75
  ```bash
76
76
  openyida login https://yida-group.alibaba-inc.com/
@@ -84,6 +84,15 @@ openyida login --check-only --json
84
84
  openyida auth status
85
85
  ```
86
86
 
87
+ To reuse an existing shared login profile for the current project, switch first instead of starting a new OAuth login:
88
+
89
+ ```bash
90
+ openyida auth profiles
91
+ openyida auth profile switch <auth_profile>
92
+ ```
93
+
94
+ If the target profile is not listed, run `openyida login` to add it, then switch to the new profile.
95
+
87
96
  OpenYida does not install Playwright by default.
88
97
 
89
98
  ### 4. Build With an AI Agent
@@ -356,9 +365,9 @@ Run `openyida --help` or `openyida <command> --help` for detailed usage.
356
365
  | Command | Description |
357
366
  |---------|-------------|
358
367
  | `openyida login [target-url] [--env <name>\|--intl\|--overseas\|--global\|--yidaapps\|--alibaba] [--client-id <clientId>] [--endpoint <url>] [--no-browser]` | Login with OAuth token mode |
359
- | `openyida logout` | Logout / clear token |
360
- | `openyida auth <status\|login\|refresh\|logout>` | Token login state management |
361
- | `openyida org <list\|switch> [--json] [--corp-id <corpId>]` | Organization management (list / switch by OAuth re-login) |
368
+ | `openyida logout` | Logout / unbind current project auth |
369
+ | `openyida auth <status\|login\|refresh\|logout\|profiles\|profile switch>` | Token login state and profile management |
370
+ | `openyida org <list\|switch> [--json] [--corp-id <corpId>]` | Organization management (list / switch existing profiles first) |
362
371
  | `openyida env [--json\|setup\|list\|show\|switch\|add\|remove] [options]` | Detect AI tool environment & token login state |
363
372
 
364
373
  ### App Management
@@ -368,7 +377,7 @@ Run `openyida --help` or `openyida <command> --help` for detailed usage.
368
377
  | `openyida app-list [--size N]` | List my Yida apps |
369
378
  | `openyida corp-efficiency [overview\|details\|detail\|groups\|notify] [options] [--open\|--no-open]` | Query enterprise efficiency overview and detail reports |
370
379
  | `openyida create-app "<name>"\|--name <name> [options] [--locale zh_CN\|en_US\|ja_JP] [--open\|--no-open]` | Create a Yida app |
371
- | `openyida update-app <appType> [--name "..."] [--layout slide\|ver] [--theme deepBlue]` | Update app info |
380
+ | `openyida update-app <appType> [--name "..."] [--layout slide\|ver] [--theme deepBlue] [--hide-app-nav\|--show-app-nav]` | Update app info |
372
381
  | `openyida app-online <appType> [--to-ding-app-center] [--show-app-center]` | Enable a Yida app |
373
382
  | `openyida app-offline <appType> [--to-ding-app-center] [--show-app-center]` | Disable a Yida app |
374
383
  | `openyida nav-group <list\|create\|rename\|delete\|move\|order\|auto-order\|hide\|show> <appType> ...` | Manage app sidebar navigation groups |
@@ -393,6 +402,7 @@ Run `openyida --help` or `openyida <command> --help` for detailed usage.
393
402
  | `openyida list-forms <appType> [--keyword <text>]` | List forms/pages in an app |
394
403
  | `openyida aggregate-table <list\|create-empty\|inspect\|preview\|save\|publish\|status> <appType> ...` | Manage aggregate tables (virtualView) |
395
404
  | `openyida get-schema <appType> <formUuid\|--all> [--summary-json\|--field-map-json]` | Get one form Schema or all form Schemas |
405
+ | `openyida check-prd-completeness <prd.md> --app-type <appType> [--build-manifest <file>] [--json]` | Check PRD page/resource count risk |
396
406
  | `openyida er <appType> [--format mermaid\|json] [--output file] [--include-system] [--include-pages]` | Export app entity relationship diagram |
397
407
  | `openyida create-page <appType> "<name>" [--mode dashboard] [--hide-nav] [--locale zh_CN\|en_US\|ja_JP] [--open\|--no-open]` | Create a custom display page |
398
408
  | `openyida build-page <sourceFile> [--output file\|--write]` | Build Yida-compatible page source |
package/bin/yida.js CHANGED
@@ -30,13 +30,22 @@ function isAgentEnvironment(env) {
30
30
  env.CLAUDE_CODE_ENTRYPOINT ||
31
31
  env.MULERUN_CHAT_ID ||
32
32
  env.MULE_DATA_DIR ||
33
+ env.MULE_WORKSPACE_DIR ||
33
34
  env.OPENCODE ||
34
35
  env.OPENCODE_CLIENT ||
35
36
  env.QODER_IDE ||
36
37
  env.QODER_AGENT ||
37
38
  env.QODERCLI_INTEGRATION_MODE ||
39
+ env.QODER_WORK_INTEGRATION_PRODUCT ||
38
40
  env.QWENWORK_INTEGRATION_MODE ||
39
41
  env.QWENWORKCN_INTEGRATION_MODE ||
42
+ env.QWENWORK ||
43
+ env.QWENWORK_CLIENT ||
44
+ env.QWENWORK_WORKSPACE_DIR ||
45
+ env.QWENWORK_SANDBOX_ID ||
46
+ env.QWENWORK_PREVIEW_URL ||
47
+ env.QWENWORK_VNC_URL ||
48
+ (env.AGENT_PLATFORM || '').toLowerCase().includes('qwenwork') ||
40
49
  env.CURSOR_TRACE_ID ||
41
50
  env.AGENT_WORK_ROOT ||
42
51
  env.OPENYIDA_AGENT_MODE ||
@@ -266,6 +275,12 @@ function printLoginResult(result) {
266
275
  status: result.status || (tokenUsable ? 'ok' : 'token_not_issued'),
267
276
  auth_mode: 'token',
268
277
  auth_source: result.auth_source || result.authSource,
278
+ auth_store: result.auth_store || result.authStore,
279
+ auth_profile: result.auth_profile || result.authProfile,
280
+ persistence_scope: result.persistence_scope || result.persistenceScope,
281
+ user_auth_store_writable: result.user_auth_store_writable !== undefined
282
+ ? result.user_auth_store_writable
283
+ : result.userAuthStoreWritable,
269
284
  can_auto_use: result.can_auto_use !== undefined ? !!result.can_auto_use : tokenUsable,
270
285
  token_type: result.token_type || 'Bearer',
271
286
  access_token: maskSensitiveAuthOutput({ access_token: result.access_token }).access_token,
@@ -274,8 +289,12 @@ function printLoginResult(result) {
274
289
  corp_id: result.corp_id,
275
290
  user_id: result.user_id,
276
291
  user_name: result.user_name,
292
+ already_logged_in: result.already_logged_in,
293
+ login_action: result.login_action,
294
+ previous_status: result.previous_status,
277
295
  failure_reason: result.failure_reason,
278
296
  message: result.message,
297
+ warning: result.warning,
279
298
  raw: tokenUsable ? undefined : result.raw,
280
299
  };
281
300
  console.log(JSON.stringify(summary));
@@ -320,6 +339,29 @@ function getArgValue(cliArgs, name) {
320
339
  return cliArgs[index + 1];
321
340
  }
322
341
 
342
+ function getFirstPositionalArg(cliArgs, startIndex = 0) {
343
+ const valueFlags = new Set([
344
+ '--client-id',
345
+ '--corp-id',
346
+ '--endpoint',
347
+ '--base-url',
348
+ '--login-url',
349
+ '--profile',
350
+ '--user-id',
351
+ ]);
352
+ for (let index = startIndex; index < cliArgs.length; index++) {
353
+ const arg = cliArgs[index];
354
+ if (valueFlags.has(arg)) {
355
+ index++;
356
+ continue;
357
+ }
358
+ if (!arg.startsWith('--')) {
359
+ return arg;
360
+ }
361
+ }
362
+ return null;
363
+ }
364
+
323
365
  const UNSUPPORTED_LEGACY_LOGIN_FLAGS = new Set([
324
366
  '--qr',
325
367
  '--qr-code',
@@ -412,6 +454,7 @@ function applyLoginEnvironmentFlags(cliArgs, options = {}) {
412
454
  const valuePassthroughFlags = new Set([
413
455
  '--corp-id',
414
456
  '--client-id',
457
+ '--profile',
415
458
  '--user-id',
416
459
  ]);
417
460
  const targetUrlFlags = new Set([
@@ -523,11 +566,21 @@ function printLoginHelp() {
523
566
  function buildTokenLoginOptions(loginArgs) {
524
567
  return {
525
568
  clientId: getArgValue(loginArgs, '--client-id'),
569
+ corpId: getArgValue(loginArgs, '--corp-id'),
570
+ userId: getArgValue(loginArgs, '--user-id'),
571
+ authProfile: getArgValue(loginArgs, '--profile'),
526
572
  quiet: process.env.YIDA_QUIET === '1' || loginArgs.includes('--quiet'),
527
573
  noBrowser: loginArgs.includes('--no-browser'),
528
574
  };
529
575
  }
530
576
 
577
+ function buildLogoutOptions(logoutArgs) {
578
+ return {
579
+ authProfile: getArgValue(logoutArgs, '--profile'),
580
+ allProfiles: logoutArgs.includes('--all'),
581
+ };
582
+ }
583
+
531
584
  function printAuthHelp() {
532
585
  printCommandUsage(t('cli.auth_usage'), t('cli.auth_example'));
533
586
  }
@@ -620,15 +673,13 @@ async function main() {
620
673
 
621
674
  case 'login': {
622
675
  const loginArgs = applyLoginEnvironmentFlags(args, { inferTargetUrl: true });
623
- const { getAuthStatus, isEnvAuthMode } = require('../lib/core/utils');
676
+ const { getAuthStatus } = require('../lib/core/utils');
624
677
  if (hasHelpFlag(loginArgs)) {
625
678
  printLoginHelp();
626
679
  } else {
627
680
  assertNoUnsupportedLegacyLoginFlags(rawArgs, loginArgs);
628
681
  if (loginArgs.includes('--check-only')) {
629
- console.log(JSON.stringify(getAuthStatus(), null, 2));
630
- } else if (isEnvAuthMode()) {
631
- printLoginResult(getAuthStatus());
682
+ console.log(JSON.stringify(getAuthStatus(buildTokenLoginOptions(loginArgs)), null, 2));
632
683
  } else {
633
684
  const { tokenLogin } = require('../lib/auth/token-auth');
634
685
  const result = await tokenLogin(buildTokenLoginOptions(loginArgs));
@@ -640,33 +691,43 @@ async function main() {
640
691
 
641
692
  case 'logout': {
642
693
  const { tokenLogout } = require('../lib/auth/token-auth');
643
- console.log(JSON.stringify(await tokenLogout(), null, 2));
694
+ console.log(JSON.stringify(await tokenLogout(buildLogoutOptions(args)), null, 2));
644
695
  break;
645
696
  }
646
697
 
647
698
  case 'auth': {
648
699
  const subCommand = args[0];
649
700
  const authArgs = applyLoginEnvironmentFlags(args.slice(1), { inferTargetUrl: true });
650
- const { getAuthStatus, isEnvAuthMode } = require('../lib/core/utils');
701
+ const { getAuthStatus } = require('../lib/core/utils');
651
702
  const { tokenLogin, tokenLogout, tokenRefresh } = require('../lib/auth/token-auth');
652
703
  if (!subCommand || subCommand === '--help' || subCommand === '-h') {
653
704
  printAuthHelp();
654
705
  } else if (subCommand === 'status') {
655
- console.log(JSON.stringify(getAuthStatus(), null, 2));
706
+ console.log(JSON.stringify(getAuthStatus(buildTokenLoginOptions(authArgs)), null, 2));
707
+ } else if (subCommand === 'profiles') {
708
+ const { listAuthProfiles } = require('../lib/auth/profile');
709
+ console.log(JSON.stringify(listAuthProfiles(buildTokenLoginOptions(authArgs)), null, 2));
710
+ } else if (subCommand === 'profile') {
711
+ const profileSubCommand = authArgs[0];
712
+ if (profileSubCommand === 'switch') {
713
+ const target = getFirstPositionalArg(authArgs, 1);
714
+ const { switchAuthProfile } = require('../lib/auth/profile');
715
+ console.log(JSON.stringify(switchAuthProfile(target, buildTokenLoginOptions(authArgs)), null, 2));
716
+ } else {
717
+ throwCliUsage(t('cli.auth_usage'), t('cli.auth_example'));
718
+ }
656
719
  } else if (subCommand === 'login') {
657
720
  if (hasHelpFlag(authArgs)) {
658
721
  printLoginHelp();
659
722
  } else {
660
723
  assertNoUnsupportedLegacyLoginFlags(rawArgs.slice(1), authArgs);
661
- const result = isEnvAuthMode()
662
- ? getAuthStatus()
663
- : await tokenLogin(buildTokenLoginOptions(authArgs));
724
+ const result = await tokenLogin(buildTokenLoginOptions(authArgs));
664
725
  printLoginResult(result);
665
726
  }
666
727
  } else if (subCommand === 'refresh') {
667
728
  console.log(JSON.stringify(maskSensitiveAuthOutput(await tokenRefresh()), null, 2));
668
729
  } else if (subCommand === 'logout') {
669
- console.log(JSON.stringify(await tokenLogout(), null, 2));
730
+ console.log(JSON.stringify(await tokenLogout(buildLogoutOptions(authArgs)), null, 2));
670
731
  } else {
671
732
  throwCliUsage(t('cli.auth_usage'), t('cli.auth_example'));
672
733
  }
@@ -734,6 +795,12 @@ async function main() {
734
795
  break;
735
796
  }
736
797
 
798
+ case 'check-prd-completeness': {
799
+ const { run } = require('../lib/app/check-prd-completeness');
800
+ await run(args);
801
+ break;
802
+ }
803
+
737
804
  case 'er': {
738
805
  const { run } = require('../lib/app/er');
739
806
  await run(args);
@@ -1,6 +1,6 @@
1
1
  # OpenYida 功能完整列表
2
2
 
3
- 这份清单面向宜搭使用者和 AI Agent,按本地 OpenYida `2026.8.12-1` 的 101 条命令和技能路由整理。参数细节可以继续查看 `openyida --help`、`openyida <command> --help` 或 `openyida commands --json`。
3
+ 这份清单面向宜搭使用者和 AI Agent,按本地 OpenYida `2026.8.19` 的 101 条命令和技能路由整理。参数细节可以继续查看 `openyida --help`、`openyida <command> --help` 或 `openyida commands --json`。
4
4
 
5
5
  <Note>
6
6
  日常使用建议先运行 `openyida agent-capabilities --summary-json`,它会轻量返回版本、登录态、组织、工作目录和命令清单摘要。只有排查命令契约、权限元数据或登录异常时,再使用完整的 `openyida agent-capabilities --json`。
@@ -30,12 +30,12 @@
30
30
  |---|---|
31
31
  | 查询我的应用 | `openyida app-list [--size N]` |
32
32
  | 创建应用 | `openyida create-app "<应用名称>"` |
33
- | 更新应用名称、布局、主题 | `openyida update-app <appType> [--name "..."] [--layout slide\|ver] [--theme deepBlue]` |
33
+ | 更新应用名称、布局、主题、访问态应用导航显示 | `openyida update-app <appType> [--name "..."] [--layout slide\|ver] [--theme deepBlue] [--hide-app-nav\|--show-app-nav]` |
34
34
  | 启用应用 / 上线应用 | `openyida app-online <appType> [--to-ding-app-center] [--show-app-center]` |
35
35
  | 停用应用 / 下线应用 | `openyida app-offline <appType> [--to-ding-app-center] [--show-app-center]` |
36
36
  | 导出应用迁移包 | `openyida export <appType> [output]` |
37
37
  | 导入应用迁移包 | `openyida import <file> [name]` |
38
- | 管理左侧导航分组 | `openyida nav-group <list\|create\|rename\|delete\|move\|order\|hide\|show> <appType> ...` |
38
+ | 管理左侧导航分组 | `openyida nav-group <list\|create\|rename\|delete\|move\|order\|auto-order\|hide\|show> <appType> ...` |
39
39
  | 管理应用管理员 | `openyida app-permission <get\|set\|add\|remove\|search-user> ...` |
40
40
  | 管理应用多语言 | `openyida i18n <overview\|config\|languages\|list\|upsert\|delete\|translate\|translate-all\|upgrade> <appType> ...` |
41
41
  | 查询组织基础信息、容量、额度、域名 | `openyida basic-info <overview\|commodity\|grant\|capacity\|quota\|abs-path\|dataflow\|i18n\|domain>` |
@@ -66,8 +66,7 @@ async function changeAppLifecycle(action, params, authRef = createAuthRef()) {
66
66
  const response = await requestWithAutoLogin((auth) => httpPost(
67
67
  auth.baseUrl,
68
68
  buildRequestPath(action, params.appType),
69
- buildPostData(params, auth),
70
- auth.cookies
69
+ buildPostData(params, auth)
71
70
  ), authRef);
72
71
 
73
72
  if (!response || response.success !== true || response.content !== true) {
@@ -0,0 +1,39 @@
1
+ 'use strict';
2
+
3
+ const { detectActiveTool } = require('../core/utils');
4
+
5
+ const BUILDER_AI_SOURCE_FALLBACK = 'local';
6
+ const SUPPORTED_BUILDER_AI_SOURCES = new Set([
7
+ BUILDER_AI_SOURCE_FALLBACK,
8
+ 'codex',
9
+ 'qwenwork',
10
+ 'qoderwork',
11
+ 'qoder',
12
+ 'wukong',
13
+ 'mulerun',
14
+ 'claude-code',
15
+ 'opencode',
16
+ 'cursor',
17
+ 'aone-copilot',
18
+ ]);
19
+
20
+ function normalizeBuilderAiSource(source) {
21
+ const normalized = String(source || '').trim().toLowerCase();
22
+ return SUPPORTED_BUILDER_AI_SOURCES.has(normalized) ? normalized : null;
23
+ }
24
+
25
+ function resolveBuilderAiSource() {
26
+ try {
27
+ const activeTool = detectActiveTool();
28
+ return normalizeBuilderAiSource(activeTool && activeTool.tool) || BUILDER_AI_SOURCE_FALLBACK;
29
+ } catch (err) {
30
+ return BUILDER_AI_SOURCE_FALLBACK;
31
+ }
32
+ }
33
+
34
+ module.exports = {
35
+ BUILDER_AI_SOURCE_FALLBACK,
36
+ SUPPORTED_BUILDER_AI_SOURCES,
37
+ normalizeBuilderAiSource,
38
+ resolveBuilderAiSource,
39
+ };