@thinkingai/ae-cli 6.0.31 → 6.0.33

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 (255) hide show
  1. package/README.md +3 -2
  2. package/README.zh.md +3 -2
  3. package/dist/{auth-MEJ642P4.js → auth-ENM3FE6L.js} +3 -2
  4. package/dist/{auth-7H3HAAJ3.js → auth-UPGUOKTW.js} +13 -6
  5. package/dist/{capability-SEH3JWLN.js → capability-AJC5CBRT.js} +50 -18
  6. package/dist/{capability-SQ2IWKP3.js → capability-TQ5KU5Q6.js} +50 -18
  7. package/dist/chunk-24BAVOX3.js +51 -0
  8. package/dist/{chunk-MDJGDI6K.js → chunk-3KI3RRXX.js} +5 -5
  9. package/dist/{chunk-PKRD2IEM.js → chunk-3P3562ZX.js} +9 -7
  10. package/dist/{chunk-R77JT7XD.js → chunk-4Q5TNP4Q.js} +4 -4
  11. package/dist/{chunk-TKQJQXWT.js → chunk-6CHYBI64.js} +7 -4
  12. package/dist/{chunk-6LEYLOV3.js → chunk-CPVTECJ3.js} +9 -7
  13. package/dist/{chunk-KCA6BA5D.js → chunk-DB4Q3ANU.js} +5 -3
  14. package/dist/{chunk-2NDGFQHW.js → chunk-E7UXXHO3.js} +11 -3
  15. package/dist/{chunk-I4A62X3N.js → chunk-HQ2A7ITL.js} +23 -14
  16. package/dist/chunk-IMMGMU54.js +674 -0
  17. package/dist/{chunk-AJTH7LT3.js → chunk-IR4ZLVPW.js} +4 -2
  18. package/dist/{chunk-N2QORU5D.js → chunk-ISY6HMHM.js} +7 -4
  19. package/dist/{chunk-KGJQCYVC.js → chunk-LCXU3AAT.js} +4 -2
  20. package/dist/chunk-LYVNONC4.js +86 -0
  21. package/dist/{chunk-DYOS6YY7.js → chunk-RGXCNC4N.js} +23 -14
  22. package/dist/{chunk-YCLVYFK7.js → chunk-V6FR6WTW.js} +45 -87
  23. package/dist/chunk-VTWMIC5L.js +27 -0
  24. package/dist/{cli-token-TVQRSE46.js → cli-token-4SBMXAUK.js} +6 -3
  25. package/dist/{client-2643Z5AG.js → client-PP5FETMW.js} +4 -3
  26. package/dist/community-report-client-KK2QBANO.js +145 -0
  27. package/dist/{config-7UZWDE74.js → config-RCCGHHYA.js} +6 -3
  28. package/dist/index.js +541 -234
  29. package/dist/{metadata-W6JFFMBA.js → metadata-3M5F2AED.js} +15 -14
  30. package/dist/{metadata-X62TKIVK.js → metadata-W2MEOI4Z.js} +15 -14
  31. package/dist/{model-T3KZJWLW.js → model-OYQLXCQY.js} +3 -2
  32. package/dist/{raw-CN542NGT.js → raw-TPB7KSZO.js} +6 -4
  33. package/dist/{sync-ERNHDPB5.js → sync-EFJKFZK2.js} +6 -3
  34. package/dist/{te-agent-FCCWUDTJ.js → te-agent-K2OWMZXT.js} +3 -2
  35. package/dist/{te-analysis-NJGNWZFC.js → te-analysis-I73ZS4NK.js} +2196 -120
  36. package/dist/{te-analysis-YGV5V5EX.js → te-analysis-Q7AZCDU4.js} +2196 -120
  37. package/dist/te-common-ST3QPSXJ.js +61 -0
  38. package/dist/te-common-WSLIKKPC.js +61 -0
  39. package/dist/te-community-WXGB6IOX.js +1659 -0
  40. package/dist/te-community-X2AHXGCA.js +1659 -0
  41. package/dist/{te-dataops-ZNJBQ6VT.js → te-dataops-MJV54MNY.js} +10 -8
  42. package/dist/{te-dataops-F36T656A.js → te-dataops-OA7I6HBG.js} +10 -8
  43. package/dist/te-engage-GJRVQMK3.js +3895 -0
  44. package/dist/te-engage-JIXX3WBI.js +3895 -0
  45. package/dist/{te-kb-NT33UHAE.js → te-kb-CIZXRWMO.js} +105 -23
  46. package/dist/{te-meta-VKWNAWO4.js → te-meta-Q4L6EE3Q.js} +8 -240
  47. package/dist/{te-meta-MAAUHFQO.js → te-meta-VHCN4Q62.js} +8 -240
  48. package/dist/{te-team-OKCOX7OE.js → te-team-PDKKW7Q5.js} +7 -6
  49. package/dist/tracking/i18n/resources/cli/en.json +4 -3
  50. package/dist/tracking/i18n/resources/cli/ja.json +4 -3
  51. package/dist/tracking/i18n/resources/cli/ko.json +4 -3
  52. package/dist/tracking/i18n/resources/cli/zh.json +4 -3
  53. package/package.json +6 -2
  54. package/skills/ae-agent/SKILL.md +2 -1
  55. package/skills/ae-analysis/SKILL.md +21 -7
  56. package/skills/ae-analysis/references/adhoc_export.md +5 -6
  57. package/skills/ae-analysis/references/adhoc_run.md +7 -9
  58. package/skills/ae-analysis/references/ai_models.md +17 -1
  59. package/skills/ae-analysis/references/alert_create.md +25 -0
  60. package/skills/ae-analysis/references/alert_definition_schema_get.md +24 -0
  61. package/skills/ae-analysis/references/alert_delete.md +26 -0
  62. package/skills/ae-analysis/references/alert_detail_list.md +27 -0
  63. package/skills/ae-analysis/references/alert_get.md +25 -0
  64. package/skills/ae-analysis/references/alert_job_list.md +24 -0
  65. package/skills/ae-analysis/references/alert_list.md +27 -0
  66. package/skills/ae-analysis/references/alert_notice_config_list.md +24 -0
  67. package/skills/ae-analysis/references/alert_start.md +25 -0
  68. package/skills/ae-analysis/references/alert_stop.md +25 -0
  69. package/skills/ae-analysis/references/alert_update.md +26 -0
  70. package/skills/ae-analysis/references/analysis_data_retrieval.md +11 -11
  71. package/skills/ae-analysis/references/analysis_drilldown_contract.md +93 -0
  72. package/skills/ae-analysis/references/analysis_gateway_assets.md +9 -8
  73. package/skills/ae-analysis/references/asset_url_get.md +4 -3
  74. package/skills/ae-analysis/references/bi_panel_create.md +3 -3
  75. package/skills/ae-analysis/references/bi_panel_page_data_export.md +2 -2
  76. package/skills/ae-analysis/references/bi_panel_page_data_run.md +1 -1
  77. package/skills/ae-analysis/references/check_delete.md +27 -0
  78. package/skills/ae-analysis/references/check_export.md +27 -0
  79. package/skills/ae-analysis/references/check_get.md +27 -0
  80. package/skills/ae-analysis/references/check_list.md +24 -0
  81. package/skills/ae-analysis/references/check_retry.md +27 -0
  82. package/skills/ae-analysis/references/check_run.md +25 -0
  83. package/skills/ae-analysis/references/command_index.md +114 -46
  84. package/skills/ae-analysis/references/create_entity.md +2 -2
  85. package/skills/ae-analysis/references/dashboard_create.md +3 -3
  86. package/skills/ae-analysis/references/dashboard_daily_report_send.md +1 -0
  87. package/skills/ae-analysis/references/dashboard_daily_report_update.md +2 -0
  88. package/skills/ae-analysis/references/dashboard_report_data_export.md +4 -4
  89. package/skills/ae-analysis/references/dashboard_report_data_run.md +4 -4
  90. package/skills/ae-analysis/references/drilldown_entities_export.md +26 -0
  91. package/skills/ae-analysis/references/drilldown_entities_run.md +33 -0
  92. package/skills/ae-analysis/references/drilldown_events_export.md +21 -0
  93. package/skills/ae-analysis/references/drilldown_events_run.md +23 -0
  94. package/skills/ae-analysis/references/drilldown_user_events_export.md +6 -3
  95. package/skills/ae-analysis/references/drilldown_user_events_run.md +6 -6
  96. package/skills/ae-analysis/references/entity_detail_export.md +2 -0
  97. package/skills/ae-analysis/references/entity_detail_run.md +8 -1
  98. package/skills/ae-analysis/references/event_blacklist_add.md +25 -0
  99. package/skills/ae-analysis/references/event_blacklist_list.md +24 -0
  100. package/skills/ae-analysis/references/event_blacklist_update.md +26 -0
  101. package/skills/ae-analysis/references/event_detail_export.md +2 -0
  102. package/skills/ae-analysis/references/event_detail_run.md +2 -0
  103. package/skills/ae-analysis/references/event_list.md +10 -2
  104. package/skills/ae-analysis/references/ingest_error_list.md +27 -0
  105. package/skills/ae-analysis/references/ingest_summary.md +26 -0
  106. package/skills/ae-analysis/references/list_entities.md +1 -1
  107. package/skills/ae-analysis/references/live_data_export.md +27 -0
  108. package/skills/ae-analysis/references/live_data_list.md +27 -0
  109. package/skills/ae-analysis/references/metric_create.md +13 -4
  110. package/skills/ae-analysis/references/metric_delete.md +7 -0
  111. package/skills/ae-analysis/references/metric_get.md +6 -0
  112. package/skills/ae-analysis/references/metric_list.md +16 -3
  113. package/skills/ae-analysis/references/metric_update.md +12 -1
  114. package/skills/ae-analysis/references/plan_change_log_export.md +27 -0
  115. package/skills/ae-analysis/references/plan_change_log_list.md +24 -0
  116. package/skills/ae-analysis/references/plan_delete_items.md +30 -0
  117. package/skills/ae-analysis/references/plan_export.md +26 -0
  118. package/skills/ae-analysis/references/plan_generate.md +27 -0
  119. package/skills/ae-analysis/references/plan_get.md +24 -0
  120. package/skills/ae-analysis/references/plan_import_excel.md +26 -0
  121. package/skills/ae-analysis/references/plan_save_items.md +27 -0
  122. package/skills/ae-analysis/references/plan_sync_from_meta.md +24 -0
  123. package/skills/ae-analysis/references/project_access_detail_get.md +23 -0
  124. package/skills/ae-analysis/references/project_data_power_delete.md +26 -0
  125. package/skills/ae-analysis/references/project_data_power_get.md +24 -0
  126. package/skills/ae-analysis/references/project_data_power_list.md +23 -0
  127. package/skills/ae-analysis/references/project_data_power_upsert.md +24 -0
  128. package/skills/ae-analysis/references/project_entity_create.md +27 -0
  129. package/skills/ae-analysis/references/project_entity_delete.md +25 -0
  130. package/skills/ae-analysis/references/project_entity_event_list.md +24 -0
  131. package/skills/ae-analysis/references/project_entity_get.md +24 -0
  132. package/skills/ae-analysis/references/project_entity_list.md +28 -0
  133. package/skills/ae-analysis/references/project_entity_update.md +28 -0
  134. package/skills/ae-analysis/references/project_function_list.md +24 -0
  135. package/skills/ae-analysis/references/project_info_get.md +23 -0
  136. package/skills/ae-analysis/references/project_info_list.md +26 -0
  137. package/skills/ae-analysis/references/project_info_update.md +25 -0
  138. package/skills/ae-analysis/references/project_mark_time_create.md +27 -0
  139. package/skills/ae-analysis/references/project_mark_time_delete.md +25 -0
  140. package/skills/ae-analysis/references/project_mark_time_list.md +28 -0
  141. package/skills/ae-analysis/references/project_mark_time_update.md +28 -0
  142. package/skills/ae-analysis/references/project_member_add.md +25 -0
  143. package/skills/ae-analysis/references/project_member_batch_update.md +24 -0
  144. package/skills/ae-analysis/references/project_member_candidate_list.md +25 -0
  145. package/skills/ae-analysis/references/project_member_handover_export.md +27 -0
  146. package/skills/ae-analysis/references/project_member_handover_run.md +24 -0
  147. package/skills/ae-analysis/references/project_member_import.md +25 -0
  148. package/skills/ae-analysis/references/project_member_list.md +23 -0
  149. package/skills/ae-analysis/references/project_member_receiver_list.md +23 -0
  150. package/skills/ae-analysis/references/project_member_remove.md +26 -0
  151. package/skills/ae-analysis/references/project_member_update.md +25 -0
  152. package/skills/ae-analysis/references/project_owner_update.md +27 -0
  153. package/skills/ae-analysis/references/project_permission_binding_list.md +24 -0
  154. package/skills/ae-analysis/references/project_receive_status_update.md +25 -0
  155. package/skills/ae-analysis/references/project_role_delete.md +26 -0
  156. package/skills/ae-analysis/references/project_role_function_list.md +27 -0
  157. package/skills/ae-analysis/references/project_role_get.md +24 -0
  158. package/skills/ae-analysis/references/project_role_list.md +25 -0
  159. package/skills/ae-analysis/references/project_role_upsert.md +24 -0
  160. package/skills/ae-analysis/references/project_role_user_list.md +24 -0
  161. package/skills/ae-analysis/references/project_timezone_get.md +23 -0
  162. package/skills/ae-analysis/references/project_timezone_overview.md +23 -0
  163. package/skills/ae-analysis/references/project_timezone_update.md +25 -0
  164. package/skills/ae-analysis/references/project_user_id_items_update.md +24 -0
  165. package/skills/ae-analysis/references/property_list.md +21 -6
  166. package/skills/ae-analysis/references/public_link_create.md +1 -1
  167. package/skills/ae-analysis/references/query_create_result_cluster.md +15 -32
  168. package/skills/ae-analysis/references/report_create.md +1 -1
  169. package/skills/ae-analysis/references/report_data_export.md +5 -3
  170. package/skills/ae-analysis/references/report_data_run.md +13 -3
  171. package/skills/ae-analysis/references/report_get.md +2 -0
  172. package/skills/ae-analysis/references/report_update.md +1 -1
  173. package/skills/ae-analysis/references/sdk_sample_generate.md +24 -0
  174. package/skills/ae-analysis/references/user_cluster_create.md +5 -1
  175. package/skills/ae-analysis/references/user_cluster_create_id.md +2 -0
  176. package/skills/ae-analysis/references/user_cluster_get.md +4 -0
  177. package/skills/ae-analysis/references/user_cluster_refresh.md +4 -2
  178. package/skills/ae-analysis/references/user_cluster_update.md +5 -1
  179. package/skills/ae-analysis/references/user_cluster_update_id.md +2 -0
  180. package/skills/ae-analysis/references/user_tag_create.md +5 -1
  181. package/skills/ae-analysis/references/user_tag_create_id.md +2 -0
  182. package/skills/ae-analysis/references/user_tag_get.md +4 -0
  183. package/skills/ae-analysis/references/user_tag_refresh.md +4 -2
  184. package/skills/ae-analysis/references/user_tag_update.md +5 -1
  185. package/skills/ae-analysis/references/user_tag_update_id.md +2 -0
  186. package/skills/ae-analysis/references/virtual_event_create.md +22 -3
  187. package/skills/ae-analysis/references/virtual_property_create.md +23 -2
  188. package/skills/ae-analysis-global/SKILL.md +2 -0
  189. package/skills/ae-capability/SKILL.md +7 -5
  190. package/skills/ae-community/SKILL.md +72 -8
  191. package/skills/ae-community/references/community-chat-analysis.md +341 -0
  192. package/skills/ae-community/references/community-data-report.md +301 -0
  193. package/skills/ae-dataops/SKILL.md +2 -1
  194. package/skills/ae-engage/SKILL.md +204 -8
  195. package/skills/ae-engage/references/activity-activity-type.md +42 -0
  196. package/skills/ae-engage/references/activity-activity.md +70 -0
  197. package/skills/ae-engage/references/activity-approval.md +53 -0
  198. package/skills/ae-engage/references/activity-task.md +87 -0
  199. package/skills/ae-engage/references/activity-topic.md +98 -0
  200. package/skills/ae-engage/references/approval-approver-delete.md +26 -0
  201. package/skills/ae-engage/references/channel-test-send.md +37 -0
  202. package/skills/ae-engage/references/channel-touch-limits-batch-update.md +28 -0
  203. package/skills/ae-engage/references/channel-touch-limits-save.md +37 -0
  204. package/skills/ae-engage/references/channel-touch-limits-toggle.md +28 -0
  205. package/skills/ae-engage/references/channel-update-config.md +36 -0
  206. package/skills/ae-engage/references/client-param.md +58 -0
  207. package/skills/ae-engage/references/common-metric.md +75 -0
  208. package/skills/ae-engage/references/config-table.md +92 -0
  209. package/skills/ae-engage/references/engage-scene-config-item.md +69 -0
  210. package/skills/ae-engage/references/operation-log-query.md +1 -1
  211. package/skills/ae-engage/references/preset-event.md +42 -0
  212. package/skills/ae-engage/references/push-language.md +39 -0
  213. package/skills/ae-engage/references/scene-config-channel.md +58 -0
  214. package/skills/ae-engage/references/scene-config-group.md +62 -0
  215. package/skills/ae-engage/references/scene-config-item.md +68 -0
  216. package/skills/ae-engage/references/scene-config-metric.md +79 -0
  217. package/skills/ae-engage/references/scene-config-param.md +72 -0
  218. package/skills/ae-engage/references/scene-preset-metric.md +45 -0
  219. package/skills/ae-engage/references/scene-strategy.md +47 -0
  220. package/skills/ae-engage/references/scene-template.md +71 -0
  221. package/skills/ae-engage/references/{ops-delete.md → task-delete.md} +3 -3
  222. package/skills/ae-engage/references/whitelist.md +72 -0
  223. package/skills/ae-engage/references/workbench-workbench.md +48 -0
  224. package/skills/ae-generate-tracking-code/SKILL.md +4 -4
  225. package/skills/ae-generate-tracking-plan/SKILL.md +140 -16
  226. package/skills/ae-generate-tracking-plan/references/business-dimension-mapping.md +98 -33
  227. package/skills/ae-generate-tracking-plan/references/te-api.md +1 -1
  228. package/skills/ae-generate-tracking-plan/references/xlsx-schema.md +16 -14
  229. package/skills/ae-kb/SKILL.md +36 -9
  230. package/skills/ae-metadata/SKILL.md +3 -2
  231. package/skills/ae-metadata/references/metadata_event_get.md +4 -4
  232. package/skills/ae-metadata/references/metadata_property_dimension_table_bind_existing.md +1 -1
  233. package/skills/ae-metadata/references/metadata_property_get.md +4 -4
  234. package/skills/ae-team/SKILL.md +2 -1
  235. package/dist/chunk-NOO24N7W.js +0 -11
  236. package/dist/chunk-TNW2CI4W.js +0 -129
  237. package/dist/te-common-5NJLF3XG.js +0 -130
  238. package/dist/te-common-7VTJZPII.js +0 -130
  239. package/dist/te-community-PEZ2VEF7.js +0 -687
  240. package/dist/te-community-TSKJ652U.js +0 -687
  241. package/dist/te-engage-BUWVSSSK.js +0 -1912
  242. package/dist/te-engage-EPE3QKDE.js +0 -1912
  243. package/skills/ae-analysis/references/create_metric.md +0 -58
  244. package/skills/ae-analysis/references/create_virtual_event.md +0 -60
  245. package/skills/ae-analysis/references/create_virtual_property.md +0 -69
  246. package/skills/ae-analysis/references/delete_metric.md +0 -32
  247. package/skills/ae-analysis/references/drilldown_users_export.md +0 -17
  248. package/skills/ae-analysis/references/drilldown_users_run.md +0 -61
  249. package/skills/ae-analysis/references/get_metric.md +0 -38
  250. package/skills/ae-analysis/references/get_resource_url.md +0 -33
  251. package/skills/ae-analysis/references/list_events.md +0 -46
  252. package/skills/ae-analysis/references/list_metrics.md +0 -52
  253. package/skills/ae-analysis/references/list_properties.md +0 -47
  254. package/skills/ae-analysis/references/update_metric.md +0 -58
  255. package/dist/{chunk-HL2AJQ4Q.js → chunk-PTE56QPL.js} +3 -3
package/dist/index.js CHANGED
@@ -4,33 +4,43 @@ import {
4
4
  import {
5
5
  TeAgentApiError,
6
6
  TeAgentCredentialsError
7
- } from "./chunk-R77JT7XD.js";
7
+ } from "./chunk-4Q5TNP4Q.js";
8
+ import {
9
+ getLocalCliPackageInfo
10
+ } from "./chunk-VTWMIC5L.js";
8
11
  import {
9
12
  CapabilityGatewayError,
10
13
  executeCapability,
11
14
  uploadInputFileBytes
12
- } from "./chunk-I4A62X3N.js";
15
+ } from "./chunk-HQ2A7ITL.js";
13
16
  import {
17
+ formatCapabilityMissCompatHint,
18
+ notifyIfUpdateAvailable,
14
19
  printError,
15
- printOutput
16
- } from "./chunk-TNW2CI4W.js";
17
- import {
18
- PermissionError
19
- } from "./chunk-NOO24N7W.js";
20
+ printOutput,
21
+ runHostCompatCheck
22
+ } from "./chunk-IMMGMU54.js";
20
23
  import {
21
24
  clearCliToken,
22
25
  getCliToken
23
- } from "./chunk-2NDGFQHW.js";
26
+ } from "./chunk-E7UXXHO3.js";
24
27
  import {
25
28
  SecureStoreAuthError,
26
29
  resolveHost
27
- } from "./chunk-AJTH7LT3.js";
30
+ } from "./chunk-IR4ZLVPW.js";
28
31
  import {
29
32
  getActiveHost,
30
33
  getConfigDir,
31
- logger,
32
34
  safeJsonParse
33
- } from "./chunk-YCLVYFK7.js";
35
+ } from "./chunk-V6FR6WTW.js";
36
+ import {
37
+ CliValidationError,
38
+ CommunityReportError,
39
+ PermissionError
40
+ } from "./chunk-24BAVOX3.js";
41
+ import {
42
+ logger
43
+ } from "./chunk-LYVNONC4.js";
34
44
 
35
45
  // src/index.ts
36
46
  import { Command as CommanderCommand } from "commander";
@@ -38,27 +48,46 @@ import { createRequire } from "module";
38
48
 
39
49
  // src/framework/runner.ts
40
50
  import * as readline from "readline";
51
+ function missingRequiredFlagsError(cmdName, missing) {
52
+ const names = missing.map((flag) => `--${flag.name}`);
53
+ const message = missing.length === 1 ? `Missing required flag: ${names[0]}` : `Missing required flags: ${names.join(", ")}`;
54
+ const hintParts = missing.map((flag) => flag.hint?.trim()).filter((hint2) => Boolean(hint2));
55
+ const hint = hintParts.length > 0 ? hintParts.join(" ") : `Usage: ae-cli ${cmdName} ${names.map((name) => `${name} <value>`).join(" ")}`;
56
+ return { message, hint };
57
+ }
41
58
  async function runCommand(cmd, opts, globalOpts) {
42
59
  try {
43
60
  const ctx = createRuntimeContext(cmd, opts, globalOpts);
44
61
  const cmdName = cmd.resource ? `${cmd.service} ${cmd.resource} ${cmd.command}` : `${cmd.service} ${cmd.command}`;
45
- logger.command(cmdName, opts);
46
- for (const flag of cmd.flags) {
47
- if (flag.required) {
48
- const val = opts[camelCase(flag.name)];
49
- if (val === void 0 || val === null || val === "") {
50
- printError("validation", `Missing required flag: --${flag.name}`, `Usage: ae-cli ${cmdName} --${flag.name} <value>`);
51
- process.exit(1);
52
- }
53
- }
62
+ logger.command(
63
+ cmdName,
64
+ opts,
65
+ cmd.flags.filter((flag) => flag.sensitive).map((flag) => flag.name)
66
+ );
67
+ const missingRequired = cmd.flags.filter((flag) => {
68
+ if (!flag.required) return false;
69
+ const val = opts[camelCase(flag.name)];
70
+ return val === void 0 || val === null || val === "";
71
+ });
72
+ if (missingRequired.length > 0) {
73
+ const { message, hint } = missingRequiredFlagsError(cmdName, missingRequired);
74
+ printError("validation", message, hint);
75
+ process.exit(1);
54
76
  }
55
77
  if (cmd.validate) {
56
78
  cmd.validate(ctx);
57
79
  }
58
80
  const LIMIT_FLAG_PATTERNS = [/limit/i, /page_size/i, /pagesize/i, /row_limit/i, /block_limit/i, /top[-_]?k/i];
59
81
  for (const flag of cmd.flags) {
60
- if (flag.type !== "number") continue;
61
82
  const val = opts[camelCase(flag.name)];
83
+ if (flag.type === "boolean") {
84
+ if (val !== void 0 && typeof val !== "boolean") {
85
+ printError("validation", `Invalid boolean for --${flag.name}: ${val}. Use true/false.`);
86
+ process.exit(1);
87
+ }
88
+ continue;
89
+ }
90
+ if (flag.type !== "number") continue;
62
91
  if (val === void 0 || val === null || val === "") continue;
63
92
  const num = Number(val);
64
93
  if (!Number.isFinite(num)) {
@@ -84,6 +113,16 @@ async function runCommand(cmd, opts, globalOpts) {
84
113
  }
85
114
  }
86
115
  }
116
+ for (const flag of cmd.flags) {
117
+ if (flag.type !== "string") continue;
118
+ const val = opts[camelCase(flag.name)];
119
+ if (val === void 0 || val === null || val === "") continue;
120
+ const error = stringFlagValidationError(flag, String(val));
121
+ if (error) {
122
+ printError("validation", error.message, error.hint);
123
+ process.exit(1);
124
+ }
125
+ }
87
126
  if (globalOpts.validate && globalOpts.dryRun) {
88
127
  printError(
89
128
  "validation",
@@ -113,11 +152,14 @@ async function runCommand(cmd, opts, globalOpts) {
113
152
  }
114
153
  return;
115
154
  }
116
- if (requiresConfirmation(cmd.risk) && !globalOpts.yes) {
117
- const confirmed = await confirm(`This is a high-risk-write operation (${cmdName}). Continue?`);
118
- if (!confirmed) {
119
- process.stderr.write("Aborted.\n");
120
- process.exit(0);
155
+ if (requiresConfirmation(cmd.risk)) {
156
+ cmd.preflight?.(ctx);
157
+ if (!globalOpts.yes) {
158
+ const confirmed = await confirm(`This is a high-risk-write operation (${cmdName}). Continue?`);
159
+ if (!confirmed) {
160
+ process.stderr.write("Aborted.\n");
161
+ process.exit(0);
162
+ }
121
163
  }
122
164
  }
123
165
  const result = await cmd.execute(ctx);
@@ -128,13 +170,25 @@ async function runCommand(cmd, opts, globalOpts) {
128
170
  process.exit(1);
129
171
  }
130
172
  const message = err.message || String(err);
131
- logger.error(`Command failed: ${message}`);
132
- if (err instanceof TeAgentCredentialsError) {
173
+ if (!(err instanceof CommunityReportError)) {
174
+ logger.error(`Command failed: ${message}`);
175
+ }
176
+ if (err instanceof CliValidationError) {
177
+ printError(
178
+ "validation",
179
+ message,
180
+ err.hint,
181
+ err.code,
182
+ err.location ? { location: err.location } : void 0
183
+ );
184
+ } else if (err instanceof TeAgentCredentialsError) {
133
185
  printError("config", message, err.hint);
134
186
  } else if (err instanceof PermissionError) {
135
187
  printError("permission", message);
136
188
  } else if (err instanceof CapabilityGatewayError) {
137
189
  printError("api", message, err.hint ?? capabilityGatewayHint(err), err.code, err.meta);
190
+ } else if (err instanceof CommunityReportError) {
191
+ printError("api", message, err.hint, err.code, err.meta, { log: false });
138
192
  } else if (err instanceof SecureStoreAuthError) {
139
193
  printError("auth", message, "Run: ae-cli auth login");
140
194
  } else if (err instanceof TeAgentApiError) {
@@ -153,12 +207,33 @@ async function runCommand(cmd, opts, globalOpts) {
153
207
  process.exit(1);
154
208
  }
155
209
  }
210
+ function stringFlagValidationError(flag, value) {
211
+ if (flag.type !== "string") return void 0;
212
+ if (flag.minLength !== void 0 && value.length < flag.minLength) {
213
+ return { message: `--${flag.name} must contain at least ${flag.minLength} characters` };
214
+ }
215
+ if (flag.maxLength !== void 0 && value.length > flag.maxLength) {
216
+ return { message: `--${flag.name} must not exceed ${flag.maxLength} characters (got: ${value.length})` };
217
+ }
218
+ if (flag.pattern !== void 0 && !new RegExp(flag.pattern).test(value)) {
219
+ return { message: `--${flag.name} has an invalid format`, hint: `Expected pattern: ${flag.pattern}` };
220
+ }
221
+ return void 0;
222
+ }
156
223
  function capabilityGatewayHint(err) {
224
+ if (err.code === "UPLOAD_NOT_EXIST" && (err.meta?.capability_id === "engage-setting.config-table.save" || err.meta?.capability_id === "engage-setting.config-table.update-data")) {
225
+ return "Run config-table upload first with the same --project-id and --request-id, then retry this command within 10 minutes. The upload cache is consumed after a successful save/update.";
226
+ }
227
+ const compatExtra = formatCapabilityMissCompatHint();
157
228
  if (err.code === "CAPABILITY_NOT_FOUND") {
158
- return "The current host does not expose this capability. Do not retry with different parameters; use a supported command path or ask the platform/backend owner to enable the capability.";
229
+ const base = "The current host does not expose this capability. Do not retry with different parameters; use a supported command path or ask the platform/backend owner to enable the capability.";
230
+ return compatExtra ? `${base}
231
+ ${compatExtra}` : base;
159
232
  }
160
233
  if (err.httpStatus === 404 && !err.code) {
161
- return "The current host returned 404 for this capability route. Do not keep retrying the same command; verify the backend route/capability deployment.";
234
+ const base = "The current host returned 404 for this capability route. Do not keep retrying the same command; verify the backend route/capability deployment.";
235
+ return compatExtra ? `${base}
236
+ ${compatExtra}` : base;
162
237
  }
163
238
  return void 0;
164
239
  }
@@ -171,10 +246,17 @@ function createRuntimeContext(cmd, opts, globalOpts) {
171
246
  let _clientModule = null;
172
247
  async function getClient() {
173
248
  if (!_clientModule) {
174
- _clientModule = await import("./client-2643Z5AG.js");
249
+ _clientModule = await import("./client-PP5FETMW.js");
175
250
  }
176
251
  return _clientModule;
177
252
  }
253
+ let _communityReportModule = null;
254
+ async function getCommunityReportClient() {
255
+ if (!_communityReportModule) {
256
+ _communityReportModule = await import("./community-report-client-KK2QBANO.js");
257
+ }
258
+ return _communityReportModule;
259
+ }
178
260
  const ctx = {
179
261
  str(name) {
180
262
  return String(opts[camelCase(name)] ?? "");
@@ -202,14 +284,18 @@ function createRuntimeContext(cmd, opts, globalOpts) {
202
284
  process.exit(1);
203
285
  }
204
286
  },
205
- async api(method, path5, params, data) {
287
+ async api(method, path4, params, data) {
206
288
  const client = await getClient();
207
289
  if (method.toUpperCase() === "GET") {
208
- return client.httpGet(path5, params, ctx.host());
290
+ return client.httpGet(path4, params, ctx.host());
209
291
  } else {
210
- return client.httpRequest(method, path5, params, data, ctx.host());
292
+ return client.httpRequest(method, path4, params, data, ctx.host());
211
293
  }
212
294
  },
295
+ async communityReport(endpoint, rawBody) {
296
+ const client = await getCommunityReportClient();
297
+ return client.communityReport(endpoint, rawBody);
298
+ },
213
299
  async querySql(projectId, sql) {
214
300
  const client = await getClient();
215
301
  return client.querySql(projectId, sql, ctx.host());
@@ -219,7 +305,7 @@ function createRuntimeContext(cmd, opts, globalOpts) {
219
305
  return client.queryReportData(projectId, reportId, qp, eventModel, options, ctx.host());
220
306
  },
221
307
  async token() {
222
- const { getToken } = await import("./auth-MEJ642P4.js");
308
+ const { getToken } = await import("./auth-ENM3FE6L.js");
223
309
  return getToken(ctx.host());
224
310
  },
225
311
  host() {
@@ -288,9 +374,16 @@ function registerCommands(program2, commands) {
288
374
  sub.option(flagStr, flag.desc);
289
375
  }
290
376
  }
291
- sub.option("--host <url>", "Override active AE host URL for this command");
377
+ if (cmd.usesAeHost !== false) {
378
+ sub.option("--host <url>", "Override active AE host URL for this command");
379
+ }
292
380
  sub.option("--format <format>", "Output format: json | table. Default: json.");
293
381
  sub.option("--jq <expr>", "jq 1.8 filter over command payload, applied before output envelope wrapping.");
382
+ if (cmd.helpText) {
383
+ sub.addHelpText("after", `
384
+ ${cmd.helpText}
385
+ `);
386
+ }
294
387
  sub.action(async (opts) => {
295
388
  const globalOpts = extractGlobalOptions(program2);
296
389
  if (opts.host) globalOpts.host = opts.host;
@@ -320,7 +413,7 @@ function parseBooleanValue(value, flagName) {
320
413
  if (normalized === "false" || normalized === "0" || normalized === "no" || normalized === "n" || normalized === "off") {
321
414
  return false;
322
415
  }
323
- throw new Error(`Invalid boolean for --${flagName}: ${value}. Use true/false.`);
416
+ return value;
324
417
  }
325
418
  function extractGlobalOptions(program2) {
326
419
  const opts = program2.opts();
@@ -335,150 +428,9 @@ function extractGlobalOptions(program2) {
335
428
  };
336
429
  }
337
430
 
338
- // src/core/update-check.ts
339
- import fs from "fs";
340
- import path from "path";
341
- var CONFIG_DIR = path.join(process.env.HOME || "", ".ae-cli");
342
- var CACHE_FILE = path.join(CONFIG_DIR, "update-check.json");
343
- var CHECK_INTERVAL_MS = 24 * 60 * 60 * 1e3;
344
- var FETCH_TIMEOUT_MS = 3e3;
345
- var REGISTRY_BY_PACKAGE = {
346
- "@thinkingai/ae-cli": "https://registry.npmjs.org"
347
- };
348
- var UPDATE_CHECK_PACKAGE = "@thinkingai/ae-cli";
349
- function isUpdateCheckEnabled(packageName) {
350
- return packageName === UPDATE_CHECK_PACKAGE;
351
- }
352
- var DEFAULT_REGISTRY = "https://registry.npmjs.org";
353
- function parseVersion(version2) {
354
- const core = version2.trim().split("-")[0];
355
- return core.split(".").map((part) => {
356
- const n = Number.parseInt(part, 10);
357
- return Number.isFinite(n) ? n : 0;
358
- });
359
- }
360
- function isNewer(latest, current) {
361
- const a = parseVersion(latest);
362
- const b = parseVersion(current);
363
- const len = Math.max(a.length, b.length, 3);
364
- for (let i = 0; i < len; i += 1) {
365
- const av = a[i] ?? 0;
366
- const bv = b[i] ?? 0;
367
- if (av > bv) return true;
368
- if (av < bv) return false;
369
- }
370
- return false;
371
- }
372
- function resolveRegistry(packageName) {
373
- if (REGISTRY_BY_PACKAGE[packageName]) {
374
- return REGISTRY_BY_PACKAGE[packageName];
375
- }
376
- const envRegistry = process.env.npm_config_registry?.replace(/\/$/, "");
377
- return envRegistry || DEFAULT_REGISTRY;
378
- }
379
- function buildInstallCommand(packageName, registry) {
380
- const base = `npm install -g ${packageName}@latest`;
381
- if (registry === DEFAULT_REGISTRY) {
382
- return base;
383
- }
384
- return `${base} --registry=${registry}`;
385
- }
386
- function shouldSkipUpdateCheck(argv = process.argv) {
387
- if (process.env.AE_CLI_NO_UPDATE_CHECK === "1") return true;
388
- if (process.env.CI === "true" || process.env.CI === "1") return true;
389
- return argv.slice(2).some((arg) => {
390
- if (arg === "--no-update-check") return true;
391
- if (arg === "--version" || arg === "-V" || arg === "--help" || arg === "-h") return true;
392
- return false;
393
- });
394
- }
395
- function ensureConfigDir() {
396
- if (!fs.existsSync(CONFIG_DIR)) {
397
- fs.mkdirSync(CONFIG_DIR, { recursive: true });
398
- }
399
- }
400
- function readCache() {
401
- try {
402
- if (!fs.existsSync(CACHE_FILE)) return null;
403
- const raw = fs.readFileSync(CACHE_FILE, "utf8");
404
- const data = JSON.parse(raw);
405
- if (!data.packageName || !data.latestVersion || !data.lastCheckedAt) return null;
406
- return data;
407
- } catch {
408
- return null;
409
- }
410
- }
411
- function writeCache(cache) {
412
- try {
413
- ensureConfigDir();
414
- fs.writeFileSync(CACHE_FILE, JSON.stringify(cache, null, 2));
415
- } catch {
416
- }
417
- }
418
- function cacheIsStale(cache, packageName) {
419
- if (!cache || cache.packageName !== packageName) return true;
420
- const age = Date.now() - new Date(cache.lastCheckedAt).getTime();
421
- return age >= CHECK_INTERVAL_MS;
422
- }
423
- function printUpdateNotice(current, latest, installCommand) {
424
- process.stderr.write(`[ae-cli] Update available: ${current} \u2192 ${latest}
425
- `);
426
- process.stderr.write(` Run: ${installCommand}
427
- `);
428
- }
429
- async function fetchLatestVersion(packageName, registry) {
430
- const url = `${registry.replace(/\/$/, "")}/${encodeURIComponent(packageName)}`;
431
- const controller = new AbortController();
432
- const timer = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);
433
- try {
434
- const resp = await fetch(url, {
435
- signal: controller.signal,
436
- headers: { Accept: "application/json" }
437
- });
438
- if (!resp.ok) return null;
439
- const data = await resp.json();
440
- const latest = data["dist-tags"]?.latest;
441
- return typeof latest === "string" && latest.trim() ? latest.trim() : null;
442
- } catch {
443
- return null;
444
- } finally {
445
- clearTimeout(timer);
446
- }
447
- }
448
- async function refreshCache(pkg2, registry) {
449
- const latest = await fetchLatestVersion(pkg2.name, registry);
450
- if (!latest) return readCache();
451
- const cache = {
452
- packageName: pkg2.name,
453
- currentVersion: pkg2.version,
454
- latestVersion: latest,
455
- lastCheckedAt: (/* @__PURE__ */ new Date()).toISOString()
456
- };
457
- writeCache(cache);
458
- return cache;
459
- }
460
- function maybeNotifyFromCache(pkg2, cache, registry) {
461
- if (!cache || cache.packageName !== pkg2.name) return;
462
- if (!isNewer(cache.latestVersion, pkg2.version)) return;
463
- printUpdateNotice(pkg2.version, cache.latestVersion, buildInstallCommand(pkg2.name, registry));
464
- }
465
- function notifyIfUpdateAvailable(pkg2) {
466
- if (!isUpdateCheckEnabled(pkg2.name)) return;
467
- if (shouldSkipUpdateCheck()) return;
468
- const registry = resolveRegistry(pkg2.name);
469
- const cache = readCache();
470
- maybeNotifyFromCache(pkg2, cache, registry);
471
- if (!cacheIsStale(cache, pkg2.name)) return;
472
- void refreshCache(pkg2, registry).then((fresh) => {
473
- if (!fresh) return;
474
- if (cache && fresh.latestVersion === cache.latestVersion) return;
475
- maybeNotifyFromCache(pkg2, fresh, registry);
476
- });
477
- }
478
-
479
431
  // src/commands/tracking/plan.ts
480
432
  import { readFile, writeFile, cp } from "fs/promises";
481
- import path3, { resolve as resolve2 } from "path";
433
+ import path2, { resolve as resolve2 } from "path";
482
434
 
483
435
  // src/tracking/xlsx/write.ts
484
436
  import ExcelJS from "exceljs";
@@ -698,13 +650,13 @@ function allHeaderNames(key) {
698
650
 
699
651
  // src/tracking/i18n/resources/xlsx/types.ts
700
652
  var PROP_TYPE_DISPLAY = {
701
- string: { zh: "\u6587\u672C", en: "string", ja: "\u30B9\u30C8\u30EA\u30F3\u30B0", ko: "string" },
702
- number: { zh: "\u6570\u503C", en: "number", ja: "\u6570\u5024", ko: "number" },
703
- bool: { zh: "\u5E03\u5C14", en: "boolean", ja: "\u30D6\u30FC\u30EB\u5024", ko: "boolean" },
704
- datetime: { zh: "\u65F6\u95F4", en: "datetime", ja: "\u6642\u9593", ko: "time" },
705
- object: { zh: "\u5BF9\u8C61", en: "object", ja: "\u30AA\u30D6\u30B8\u30A7\u30AF\u30C8", ko: "object" },
706
- array_row: { zh: "\u5BF9\u8C61\u7EC4", en: "object[]", ja: "\u30AA\u30D6\u30B8\u30A7\u30AF\u30C8\u914D\u5217", ko: "object_array" },
707
- array_string: { zh: "\u5217\u8868", en: "string[]", ja: "\u914D\u5217", ko: "string_array" }
653
+ string: { zh: "\u6587\u672C", en: "String", ja: "\u30B9\u30C8\u30EA\u30F3\u30B0", ko: "String" },
654
+ number: { zh: "\u6570\u503C", en: "Number", ja: "\u6570\u5024", ko: "Number" },
655
+ bool: { zh: "\u5E03\u5C14", en: "Boolean", ja: "\u30D6\u30FC\u30EB\u5024", ko: "Boolean" },
656
+ datetime: { zh: "\u65F6\u95F4", en: "Date", ja: "\u6642\u9593", ko: "Date" },
657
+ object: { zh: "\u5BF9\u8C61", en: "Row", ja: "\u30AA\u30D6\u30B8\u30A7\u30AF\u30C8", ko: "Row" },
658
+ array_row: { zh: "\u5BF9\u8C61\u7EC4", en: "Array Row", ja: "\u30AA\u30D6\u30B8\u30A7\u30AF\u30C8\u30B0\u30EB\u30FC\u30D7", ko: "Array Row" },
659
+ array_string: { zh: "\u5217\u8868", en: "List", ja: "\u30EA\u30B9\u30C8", ko: "List" }
708
660
  };
709
661
  function typeToDisplay(type, locale) {
710
662
  return PROP_TYPE_DISPLAY[type][locale];
@@ -718,24 +670,29 @@ for (const [canonical, locales] of Object.entries(PROP_TYPE_DISPLAY)) {
718
670
  var ALIASES = {
719
671
  // zh alias(行业模板)
720
672
  "\u5B57\u7B26\u4E32": "string",
721
- "\u5BF9\u8C61": "object",
722
- // en alias
723
- "String": "string",
724
- "Number": "number",
725
- "Boolean": "bool",
673
+ // en alias(旧值兼容 — 2026-07-15 前生成的老 xlsx)
674
+ "string": "string",
675
+ "number": "number",
676
+ "boolean": "bool",
677
+ "datetime": "datetime",
678
+ "object": "object",
679
+ "object[]": "array_row",
680
+ "string[]": "array_string",
681
+ // en 额外 alias
726
682
  "Bool": "bool",
727
683
  "DateTime": "datetime",
728
684
  "Time": "datetime",
729
685
  "Object": "object",
730
- "Row": "object",
731
686
  "Object Array": "array_row",
732
- "List": "array_string",
733
687
  "String Array": "array_string",
734
688
  // ja alias
735
689
  "\u6587\u5B57\u5217": "string",
736
690
  "\u30C6\u30AD\u30B9\u30C8": "string",
737
691
  "\u30D6\u30FC\u30EB": "bool",
738
692
  "\u65E5\u6642": "datetime",
693
+ // ja 旧值兼容
694
+ "\u30AA\u30D6\u30B8\u30A7\u30AF\u30C8\u914D\u5217": "array_row",
695
+ "\u914D\u5217": "array_string",
739
696
  // ko alias
740
697
  "\uD14D\uC2A4\uD2B8": "string",
741
698
  "\uBB38\uC790\uC5F4": "string",
@@ -743,7 +700,11 @@ var ALIASES = {
743
700
  "\uBD80\uC6B8": "bool",
744
701
  "\uB0A0\uC9DC\uC2DC\uAC04": "datetime",
745
702
  "\uAC1D\uCCB4 \uBC30\uC5F4": "array_row",
746
- "\uB9AC\uC2A4\uD2B8": "array_string"
703
+ "\uB9AC\uC2A4\uD2B8": "array_string",
704
+ // ko 旧值兼容
705
+ "time": "datetime",
706
+ "object_array": "array_row",
707
+ "string_array": "array_string"
747
708
  };
748
709
  Object.assign(ALL_DISPLAY_TO_TYPE, ALIASES);
749
710
  function displayToType(raw) {
@@ -823,6 +784,193 @@ function t(key, params, locale) {
823
784
  return node;
824
785
  }
825
786
 
787
+ // src/tracking/xlsx/tag-priority.ts
788
+ var TAG_PRIORITY = {
789
+ // Account lifecycle
790
+ "Basic": 1,
791
+ // Core gameplay
792
+ "Battle": 10,
793
+ "Stage": 11,
794
+ "Dungeon": 12,
795
+ "Gacha": 13,
796
+ // Progression & economy
797
+ "Growth": 20,
798
+ "Resource": 21,
799
+ // Monetization
800
+ "Ads": 30,
801
+ "Payment": 31,
802
+ "Subscription": 32,
803
+ // Supporting systems
804
+ "Shop": 40,
805
+ "Quest": 41,
806
+ "Achievement": 42,
807
+ "Check-in": 43,
808
+ "Leaderboard": 44,
809
+ "Guild": 45,
810
+ "Social": 46,
811
+ // Genre-specific (game)
812
+ "Building": 50,
813
+ "Alliance": 51,
814
+ "Equipment": 52,
815
+ "Trade": 53,
816
+ "Revive": 54,
817
+ "Slots": 55,
818
+ "Lottery": 56,
819
+ "Reward": 57,
820
+ // Non-game
821
+ "Discovery": 60,
822
+ "Product": 61,
823
+ "Order": 62,
824
+ "After-sales": 63,
825
+ "Content": 64,
826
+ "Interaction": 65,
827
+ "Relationship": 66,
828
+ "Live": 67,
829
+ "Onboarding": 68,
830
+ "Course": 69,
831
+ "Enrollment": 70,
832
+ "Quiz": 71,
833
+ "Creation": 72,
834
+ "Material": 73,
835
+ "Export": 74,
836
+ "Playback": 75,
837
+ "Withdraw": 76
838
+ };
839
+ var DEFAULT_TAG_PRIORITY = 80;
840
+ var CANONICAL_TAG = {
841
+ // zh
842
+ "\u57FA\u7840\u4E8B\u4EF6": "Basic",
843
+ "\u6218\u6597": "Battle",
844
+ "\u5173\u5361": "Stage",
845
+ "\u526F\u672C": "Dungeon",
846
+ "\u62BD\u5361": "Gacha",
847
+ "\u517B\u6210": "Growth",
848
+ "\u6210\u957F": "Growth",
849
+ "\u8D44\u6E90": "Resource",
850
+ "\u5E7F\u544A": "Ads",
851
+ "\u652F\u4ED8": "Payment",
852
+ "\u8BA2\u9605": "Subscription",
853
+ "\u5546\u57CE": "Shop",
854
+ "\u4EFB\u52A1": "Quest",
855
+ "\u6210\u5C31": "Achievement",
856
+ "\u7B7E\u5230": "Check-in",
857
+ "\u6392\u884C\u699C": "Leaderboard",
858
+ "\u516C\u4F1A": "Guild",
859
+ "\u793E\u4EA4": "Social",
860
+ "\u5EFA\u7B51": "Building",
861
+ "\u8054\u76DF": "Alliance",
862
+ "\u88C5\u5907": "Equipment",
863
+ "\u4EA4\u6613": "Trade",
864
+ "\u590D\u6D3B": "Revive",
865
+ "\u62BD\u5956": "Lottery",
866
+ "\u5956\u52B1": "Reward",
867
+ "\u63D0\u73B0": "Withdraw",
868
+ "\u53D1\u73B0": "Discovery",
869
+ "\u5546\u54C1": "Product",
870
+ "\u8BA2\u5355": "Order",
871
+ "\u552E\u540E": "After-sales",
872
+ "\u5185\u5BB9": "Content",
873
+ "\u4E92\u52A8": "Interaction",
874
+ "\u5173\u7CFB": "Relationship",
875
+ "\u76F4\u64AD": "Live",
876
+ "\u5F15\u5BFC": "Onboarding",
877
+ "\u8BFE\u7A0B": "Course",
878
+ "\u62A5\u540D": "Enrollment",
879
+ "\u6D4B\u9A8C": "Quiz",
880
+ "\u521B\u4F5C": "Creation",
881
+ "\u7D20\u6750": "Material",
882
+ "\u5BFC\u51FA": "Export",
883
+ "\u5185\u5BB9\u64AD\u653E": "Playback",
884
+ // ja
885
+ "\u57FA\u672C\u30A4\u30D9\u30F3\u30C8": "Basic",
886
+ "\u6226\u95D8": "Battle",
887
+ "\u30B9\u30C6\u30FC\u30B8": "Stage",
888
+ "\u30C0\u30F3\u30B8\u30E7\u30F3": "Dungeon",
889
+ "\u30AC\u30C1\u30E3": "Gacha",
890
+ "\u80B2\u6210": "Growth",
891
+ "\u30EA\u30BD\u30FC\u30B9": "Resource",
892
+ "\u5E83\u544A": "Ads",
893
+ "\u652F\u6255\u3044": "Payment",
894
+ "\u30B5\u30D6\u30B9\u30AF\u30EA\u30D7\u30B7\u30E7\u30F3": "Subscription",
895
+ "\u30B7\u30E7\u30C3\u30D7": "Shop",
896
+ "\u30AF\u30A8\u30B9\u30C8": "Quest",
897
+ "\u5B9F\u7E3E": "Achievement",
898
+ "\u30C1\u30A7\u30C3\u30AF\u30A4\u30F3": "Check-in",
899
+ "\u30E9\u30F3\u30AD\u30F3\u30B0": "Leaderboard",
900
+ "\u30AE\u30EB\u30C9": "Guild",
901
+ "\u30BD\u30FC\u30B7\u30E3\u30EB": "Social",
902
+ "\u5EFA\u7BC9": "Building",
903
+ "\u540C\u76DF": "Alliance",
904
+ "\u88C5\u5099": "Equipment",
905
+ "\u30C8\u30EC\u30FC\u30C9": "Trade",
906
+ "\u5FA9\u6D3B": "Revive",
907
+ "\u30B9\u30ED\u30C3\u30C8": "Slots",
908
+ "\u62BD\u9078": "Lottery",
909
+ "\u5831\u916C": "Reward",
910
+ "\u5F15\u304D\u51FA\u3057": "Withdraw",
911
+ "\u767A\u898B": "Discovery",
912
+ "\u6CE8\u6587": "Order",
913
+ "\u30A2\u30D5\u30BF\u30FC\u30B5\u30FC\u30D3\u30B9": "After-sales",
914
+ "\u30B3\u30F3\u30C6\u30F3\u30C4": "Content",
915
+ "\u30A4\u30F3\u30BF\u30E9\u30AF\u30B7\u30E7\u30F3": "Interaction",
916
+ "\u95A2\u4FC2": "Relationship",
917
+ "\u30E9\u30A4\u30D6": "Live",
918
+ "\u30AA\u30F3\u30DC\u30FC\u30C7\u30A3\u30F3\u30B0": "Onboarding",
919
+ "\u30B3\u30FC\u30B9": "Course",
920
+ "\u7533\u3057\u8FBC\u307F": "Enrollment",
921
+ "\u30AF\u30A4\u30BA": "Quiz",
922
+ "\u5275\u4F5C": "Creation",
923
+ "\u30A8\u30AF\u30B9\u30DD\u30FC\u30C8": "Export",
924
+ "\u518D\u751F": "Playback",
925
+ // ko
926
+ "\uAE30\uBCF8 \uC774\uBCA4\uD2B8": "Basic",
927
+ "\uC804\uD22C": "Battle",
928
+ "\uC2A4\uD14C\uC774\uC9C0": "Stage",
929
+ "\uB358\uC804": "Dungeon",
930
+ "\uAC00\uCC60": "Gacha",
931
+ "\uC721\uC131": "Growth",
932
+ "\uB9AC\uC18C\uC2A4": "Resource",
933
+ "\uAD11\uACE0": "Ads",
934
+ "\uACB0\uC81C": "Payment",
935
+ "\uAD6C\uB3C5": "Subscription",
936
+ "\uC0C1\uC810": "Shop",
937
+ "\uD018\uC2A4\uD2B8": "Quest",
938
+ "\uC5C5\uC801": "Achievement",
939
+ "\uCD9C\uC11D\uCCB4\uD06C": "Check-in",
940
+ "\uB9AC\uB354\uBCF4\uB4DC": "Leaderboard",
941
+ "\uAE38\uB4DC": "Guild",
942
+ "\uC18C\uC15C": "Social",
943
+ "\uAC74\uC124": "Building",
944
+ "\uC5F0\uB9F9": "Alliance",
945
+ "\uC7A5\uBE44": "Equipment",
946
+ "\uAC70\uB798": "Trade",
947
+ "\uBD80\uD65C": "Revive",
948
+ "\uC2AC\uB86F": "Slots",
949
+ "\uCD94\uCCA8": "Lottery",
950
+ "\uBCF4\uC0C1": "Reward",
951
+ "\uCD9C\uAE08": "Withdraw",
952
+ "\uBC1C\uACAC": "Discovery",
953
+ "\uC0C1\uD488": "Product",
954
+ "\uC8FC\uBB38": "Order",
955
+ "A/S": "After-sales",
956
+ "\uCF58\uD150\uCE20": "Content",
957
+ "\uC778\uD130\uB799\uC158": "Interaction",
958
+ "\uAD00\uACC4": "Relationship",
959
+ "\uB77C\uC774\uBE0C": "Live",
960
+ "\uC628\uBCF4\uB529": "Onboarding",
961
+ "\uCF54\uC2A4": "Course",
962
+ "\uC2E0\uCCAD": "Enrollment",
963
+ "\uD034\uC988": "Quiz",
964
+ "\uCC3D\uC791": "Creation",
965
+ "\uC18C\uC7AC": "Material",
966
+ "\uB0B4\uBCF4\uB0B4\uAE30": "Export",
967
+ "\uC7AC\uC0DD": "Playback"
968
+ };
969
+ function getTagPriority(tag) {
970
+ const canonical = CANONICAL_TAG[tag] ?? tag;
971
+ return TAG_PRIORITY[canonical] ?? DEFAULT_TAG_PRIORITY;
972
+ }
973
+
826
974
  // src/tracking/xlsx/write.ts
827
975
  var PLATFORM_TO_XLSX = {
828
976
  "client": "client",
@@ -833,6 +981,49 @@ var VALID_PROP_TYPES = /* @__PURE__ */ new Set(["string", "number", "bool", "dat
833
981
  var VALID_UPDATE_TYPES = /* @__PURE__ */ new Set(["user_set", "user_setOnce", "user_add"]);
834
982
  var SNAKE_CASE_RE = /^[a-z][a-z0-9_]*$/;
835
983
  var PROP_NAME_RE = /^[a-zA-Z#][a-zA-Z0-9_.]*$/;
984
+ var MIN_COL_WIDTH = 10;
985
+ var PADDING = 3;
986
+ function isWideChar(code) {
987
+ return code >= 19968 && code <= 40959 || // CJK Unified Ideographs
988
+ code >= 13312 && code <= 19903 || // CJK Ext-A
989
+ code >= 12352 && code <= 12447 || // Hiragana
990
+ code >= 12448 && code <= 12543 || // Katakana
991
+ code >= 44032 && code <= 55215 || // Hangul
992
+ code >= 65280 && code <= 65519;
993
+ }
994
+ function displayWidth(s) {
995
+ let w = 0;
996
+ for (const ch of s) {
997
+ w += isWideChar(ch.charCodeAt(0)) ? 2 : 1;
998
+ }
999
+ return w;
1000
+ }
1001
+ function autoFitSheet(ws, maxWidth = 55) {
1002
+ const colCount = ws.columnCount;
1003
+ if (colCount === 0) return;
1004
+ for (let i = 1; i <= colCount; i++) {
1005
+ const col = ws.getColumn(i);
1006
+ let maxDisplay = 0;
1007
+ let needsWrap = false;
1008
+ col.eachCell({ includeEmpty: false }, (cell) => {
1009
+ const text = String(cell.value ?? "");
1010
+ if (!text) return;
1011
+ const dw = displayWidth(text);
1012
+ if (dw > maxDisplay) maxDisplay = dw;
1013
+ });
1014
+ if (maxDisplay === 0) {
1015
+ col.width = MIN_COL_WIDTH;
1016
+ continue;
1017
+ }
1018
+ const capped = maxDisplay + PADDING > maxWidth;
1019
+ col.width = Math.max(MIN_COL_WIDTH, Math.min(maxWidth, maxDisplay + PADDING));
1020
+ if (capped) {
1021
+ col.eachCell({ includeEmpty: false }, (cell) => {
1022
+ cell.alignment = { ...cell.alignment, wrapText: true };
1023
+ });
1024
+ }
1025
+ }
1026
+ }
836
1027
  function validateDraft(d) {
837
1028
  const errors = [];
838
1029
  const eventNames = /* @__PURE__ */ new Set();
@@ -1006,7 +1197,26 @@ async function writeDraftXlsx(d, outPath, locale = "zh") {
1006
1197
  headerName("prop_desc", locale)
1007
1198
  ]);
1008
1199
  const propByName = new Map(d.event_properties.map((p) => [p.name, p]));
1009
- for (const evt of d.events) {
1200
+ const autotrackEvents = d.events.filter((e) => e.source === "autotrack");
1201
+ const businessEvents = d.events.filter((e) => e.source !== "autotrack");
1202
+ const tagGroups = /* @__PURE__ */ new Map();
1203
+ const tagOrder = [];
1204
+ for (const evt of businessEvents) {
1205
+ const tag = evt.event_tag || "";
1206
+ if (!tagGroups.has(tag)) {
1207
+ tagGroups.set(tag, []);
1208
+ tagOrder.push(tag);
1209
+ }
1210
+ tagGroups.get(tag).push(evt);
1211
+ }
1212
+ tagOrder.sort((a, b) => getTagPriority(a) - getTagPriority(b));
1213
+ const sorted = [...autotrackEvents];
1214
+ for (const tag of tagOrder) {
1215
+ for (const evt of tagGroups.get(tag)) {
1216
+ sorted.push(evt);
1217
+ }
1218
+ }
1219
+ for (const evt of sorted) {
1010
1220
  const startRow = eventSheet.rowCount + 1;
1011
1221
  const platformStr = evt.platform ? PLATFORM_TO_XLSX[evt.platform] : "";
1012
1222
  if (evt.prop_names.length === 0) {
@@ -1041,9 +1251,17 @@ async function writeDraftXlsx(d, outPath, locale = "zh") {
1041
1251
  for (const col of ["A", "B", "C", "D", "E"]) {
1042
1252
  eventSheet.mergeCells(`${col}${startRow}:${col}${endRow}`);
1043
1253
  }
1254
+ for (let r = startRow; r <= endRow; r++) {
1255
+ const row = eventSheet.getRow(r);
1256
+ for (const col of ["A", "B", "C", "D", "E"]) {
1257
+ const cell = row.getCell(col);
1258
+ cell.alignment = { ...cell.alignment, vertical: "middle" };
1259
+ }
1260
+ }
1044
1261
  }
1045
1262
  }
1046
1263
  }
1264
+ autoFitSheet(eventSheet, 50);
1047
1265
  const commonSheet = workbook.addWorksheet(sheetName("common_props", locale));
1048
1266
  commonSheet.addRow([
1049
1267
  headerName("common_prop_name", locale),
@@ -1059,6 +1277,7 @@ async function writeDraftXlsx(d, outPath, locale = "zh") {
1059
1277
  prop.desc ?? ""
1060
1278
  ]);
1061
1279
  }
1280
+ autoFitSheet(commonSheet, 50);
1062
1281
  const userSheet = workbook.addWorksheet(sheetName("user_data", locale));
1063
1282
  userSheet.addRow([
1064
1283
  headerName("user_prop_name", locale),
@@ -1079,6 +1298,7 @@ async function writeDraftXlsx(d, outPath, locale = "zh") {
1079
1298
  prop.prop_tag ?? ""
1080
1299
  ]);
1081
1300
  }
1301
+ autoFitSheet(userSheet, 50);
1082
1302
  const userIdSheet = workbook.addWorksheet(sheetName("user_id", locale));
1083
1303
  userIdSheet.addRow([
1084
1304
  headerName("user_id_prop_name", locale),
@@ -1088,11 +1308,13 @@ async function writeDraftXlsx(d, outPath, locale = "zh") {
1088
1308
  ]);
1089
1309
  userIdSheet.addRow(["#account_id", t("user_id.account_id_display", {}, locale), t("user_id.system_property", {}, locale), t("user_id.set_to", { field: d.meta.user_identity?.account_id_field ?? "account ID" }, locale)]);
1090
1310
  userIdSheet.addRow(["#distinct_id", t("user_id.distinct_id_display", {}, locale), t("user_id.system_property", {}, locale), t("user_id.auto_generated", {}, locale)]);
1311
+ autoFitSheet(userIdSheet, 50);
1091
1312
  await workbook.xlsx.writeFile(outPath);
1092
1313
  }
1093
1314
 
1094
1315
  // src/core/tracking-client.ts
1095
1316
  var DEBUG_BASE = "/v1/ta/bury/manage/debug";
1317
+ var TRACK_LOCAL_HOST = "http://localhost:8992";
1096
1318
  var TRACK_CAPABILITY_DOMAIN = "analysis";
1097
1319
  var TRACK_PROGRAM_QUERY = "track.program.query";
1098
1320
  var TRACK_PROGRAM_DELETE = "track.program.delete";
@@ -1285,8 +1507,8 @@ var TrackingClient = class {
1285
1507
  }
1286
1508
  return env;
1287
1509
  }
1288
- async debugGet(path5, params) {
1289
- const data = await this.requestJson(`${DEBUG_BASE}${path5}`, { ...params, "@t": Date.now() });
1510
+ async debugGet(path4, params) {
1511
+ const data = await this.requestJson(`${DEBUG_BASE}${path4}`, { ...params, "@t": Date.now() });
1290
1512
  return data;
1291
1513
  }
1292
1514
  async listDevice(projectId) {
@@ -1312,7 +1534,7 @@ var TrackingClient = class {
1312
1534
  }
1313
1535
  };
1314
1536
  async function createTrackingClient(host) {
1315
- return new TrackingClient(host);
1537
+ return new TrackingClient(host || TRACK_LOCAL_HOST);
1316
1538
  }
1317
1539
 
1318
1540
  // src/tracking/te-plan/fetch.ts
@@ -1362,8 +1584,8 @@ function normalize2(data) {
1362
1584
  }
1363
1585
 
1364
1586
  // src/tracking/plan/draft.ts
1365
- import fs2 from "fs";
1366
- import path2 from "path";
1587
+ import fs from "fs";
1588
+ import path from "path";
1367
1589
 
1368
1590
  // src/tracking/plan/autotrack.ts
1369
1591
  var TAG = {
@@ -1691,6 +1913,43 @@ function fixDisplayNameDuplicates(draft) {
1691
1913
  }
1692
1914
  return fixed;
1693
1915
  }
1916
+ function fixCrossPoolDisplayNameInconsistency(draft) {
1917
+ const fixed = [];
1918
+ const commonProps = draft.common_event_properties ?? [];
1919
+ const eventProps = draft.event_properties ?? [];
1920
+ for (const cp2 of commonProps) {
1921
+ if (!cp2.display_name) continue;
1922
+ const ep = eventProps.find((p) => p.name === cp2.name);
1923
+ if (!ep) continue;
1924
+ if (ep.display_name && ep.display_name !== cp2.display_name) {
1925
+ const oldName = ep.display_name;
1926
+ ep.display_name = cp2.display_name;
1927
+ fixed.push(
1928
+ `Aligned display_name for "${cp2.name}" in event_properties: "${oldName}" \u2192 "${cp2.display_name}" (from common_event_properties)`
1929
+ );
1930
+ }
1931
+ }
1932
+ return fixed;
1933
+ }
1934
+ function fixEventPlatforms(draft) {
1935
+ const fixed = [];
1936
+ const mode = draft.meta.sdk_integration_mode;
1937
+ if (mode !== "client_only" && mode !== "server_only") return fixed;
1938
+ const targetPlatform = mode === "client_only" ? "client" : "server";
1939
+ let count = 0;
1940
+ for (const event of draft.events) {
1941
+ if (!event.platform) {
1942
+ event.platform = targetPlatform;
1943
+ count++;
1944
+ }
1945
+ }
1946
+ if (count > 0) {
1947
+ fixed.push(
1948
+ `Auto-filled platform="${targetPlatform}" for ${count} event(s) based on sdk_integration_mode="${mode}"`
1949
+ );
1950
+ }
1951
+ return fixed;
1952
+ }
1694
1953
  function fixEventPropNameInvalid(draft, errors) {
1695
1954
  const invalidNames = /* @__PURE__ */ new Set();
1696
1955
  for (const error of errors) {
@@ -1768,6 +2027,14 @@ function validateAndFix(draft) {
1768
2027
  if (displayFixes.length > 0) {
1769
2028
  fixed.push(t("fix.display_name_dedup"));
1770
2029
  }
2030
+ const crossPoolFixes = fixCrossPoolDisplayNameInconsistency(draft);
2031
+ if (crossPoolFixes.length > 0) {
2032
+ fixed.push(`Cross-pool display_name consistency: ${crossPoolFixes.length} property(s) aligned`);
2033
+ }
2034
+ const platformFixes = fixEventPlatforms(draft);
2035
+ if (platformFixes.length > 0) {
2036
+ fixed.push(...platformFixes);
2037
+ }
1771
2038
  const compositeChildren = /* @__PURE__ */ new Map();
1772
2039
  const evProps = draft.event_properties ?? draft.common_properties ?? [];
1773
2040
  for (const prop of evProps) {
@@ -1925,10 +2192,13 @@ async function listTrackingTemplates() {
1925
2192
  for (const f of entries) {
1926
2193
  if (!f.endsWith(".xlsx")) continue;
1927
2194
  const base = f.replace(/\.xlsx$/i, "");
2195
+ const xlsxPath = resolve(dir, f);
1928
2196
  const mdPath = resolve(dir, base + ".md");
1929
2197
  const hasMd = existsSync3(mdPath);
1930
2198
  found.push({
1931
- path: hasMd ? mdPath : resolve(dir, f),
2199
+ path: hasMd ? mdPath : xlsxPath,
2200
+ xlsxPath,
2201
+ ...hasMd ? { mdPath } : {},
1932
2202
  name: base,
1933
2203
  hasMd
1934
2204
  });
@@ -1962,23 +2232,23 @@ function resolveTrackingHost(program2, opts) {
1962
2232
  }
1963
2233
  return host;
1964
2234
  }
1965
- function isExistingDirectory(path5) {
1966
- if (!existsSync4(path5)) return false;
2235
+ function isExistingDirectory(path4) {
2236
+ if (!existsSync4(path4)) return false;
1967
2237
  try {
1968
- return statSync(path5).isDirectory();
2238
+ return statSync(path4).isDirectory();
1969
2239
  } catch {
1970
2240
  return false;
1971
2241
  }
1972
2242
  }
1973
- function assertOutputFilePath(path5, optionName = "--out") {
1974
- const trimmed = path5.trim();
2243
+ function assertOutputFilePath(path4, optionName = "--out") {
2244
+ const trimmed = path4.trim();
1975
2245
  if (trimmed.endsWith("/") || trimmed.endsWith("\\") || isExistingDirectory(trimmed)) {
1976
2246
  console.error(t("error.output_path_is_directory", { path: trimmed, option: optionName }));
1977
2247
  process.exit(1);
1978
2248
  }
1979
2249
  }
1980
- function assertInputFilePath(path5, optionName = "--in") {
1981
- const trimmed = path5.trim();
2250
+ function assertInputFilePath(path4, optionName = "--in") {
2251
+ const trimmed = path4.trim();
1982
2252
  if (!existsSync4(trimmed)) {
1983
2253
  console.error(t("error.input_path_not_found", { path: trimmed, option: optionName }));
1984
2254
  process.exit(1);
@@ -2048,7 +2318,7 @@ function registerPlan(cmd, rootProgram) {
2048
2318
  console.log(t("plan.validate_passed"));
2049
2319
  } catch (e) {
2050
2320
  const errorMsg = e instanceof Error ? e.message : String(e);
2051
- console.log(t("plan.validate_failed") + "\n" + errorMsg);
2321
+ console.error(t("plan.validate_failed") + "\n" + errorMsg);
2052
2322
  if (opts.fix) {
2053
2323
  console.log("\n" + t("plan.attempting_auto_fix") + "...");
2054
2324
  const fixed = validateAndFix(draft);
@@ -2060,11 +2330,15 @@ function registerPlan(cmd, rootProgram) {
2060
2330
  validateDraft(draft);
2061
2331
  console.log(t("plan.validate_passed_after_fix"));
2062
2332
  } catch (e2) {
2063
- console.log(t("plan.validate_still_errors_after_fix", { error: e2 instanceof Error ? e2.message : String(e2) }));
2333
+ console.error(t("plan.validate_still_errors_after_fix", { error: e2 instanceof Error ? e2.message : String(e2) }));
2334
+ process.exitCode = 1;
2064
2335
  }
2065
2336
  } else {
2066
2337
  console.log(t("plan.no_auto_fix_available"));
2338
+ process.exitCode = 1;
2067
2339
  }
2340
+ } else {
2341
+ process.exitCode = 1;
2068
2342
  }
2069
2343
  }
2070
2344
  });
@@ -2125,7 +2399,7 @@ function registerPlan(cmd, rootProgram) {
2125
2399
  lastRes = await client.uploadProgramExcel({
2126
2400
  projectId: opts.project,
2127
2401
  file,
2128
- filename: path3.basename(opts.xlsx),
2402
+ filename: path2.basename(opts.xlsx),
2129
2403
  lang: locale
2130
2404
  });
2131
2405
  console.log(JSON.stringify(lastRes, null, 2));
@@ -2330,7 +2604,7 @@ async function detectProject(cwd) {
2330
2604
 
2331
2605
  // src/tracking/xlsx/read.ts
2332
2606
  import XLSXMod from "xlsx";
2333
- import path4 from "path";
2607
+ import path3 from "path";
2334
2608
  var XLSX = XLSXMod.default ?? XLSXMod;
2335
2609
  var VALID_PROP_TYPES2 = /* @__PURE__ */ new Set(["string", "number", "bool", "datetime", "object", "array_row", "array_string"]);
2336
2610
  var VALID_UPDATE_TYPES2 = /* @__PURE__ */ new Set(["user_set", "user_setOnce", "user_add"]);
@@ -2617,6 +2891,22 @@ function parseUserDataSheet(rows, source, sheetName2) {
2617
2891
  }
2618
2892
  return props;
2619
2893
  }
2894
+ function fillDownMergedCells(rows, merges) {
2895
+ for (const merge of merges) {
2896
+ const { s, e } = merge;
2897
+ const topLeftValue = rows[s.r]?.[s.c];
2898
+ if (topLeftValue === null || topLeftValue === void 0) continue;
2899
+ for (let r = s.r; r <= e.r; r++) {
2900
+ if (!rows[r]) continue;
2901
+ for (let c = s.c; c <= e.c; c++) {
2902
+ if (r === s.r && c === s.c) continue;
2903
+ if (rows[r][c] === null || rows[r][c] === void 0) {
2904
+ rows[r][c] = topLeftValue;
2905
+ }
2906
+ }
2907
+ }
2908
+ }
2909
+ }
2620
2910
  async function readTemplateXlsx(filePath) {
2621
2911
  let wb;
2622
2912
  try {
@@ -2624,7 +2914,7 @@ async function readTemplateXlsx(filePath) {
2624
2914
  } catch (err) {
2625
2915
  throw new Error(t("error.xlsx_read_failed", { path: filePath, error: String(err) }));
2626
2916
  }
2627
- const planName = path4.basename(filePath, path4.extname(filePath));
2917
+ const planName = path3.basename(filePath, path3.extname(filePath));
2628
2918
  const source = "template";
2629
2919
  let events = [];
2630
2920
  let event_properties = [];
@@ -2639,6 +2929,10 @@ async function readTemplateXlsx(filePath) {
2639
2929
  raw: false,
2640
2930
  defval: null
2641
2931
  });
2932
+ const merges = ws["!merges"];
2933
+ if (merges && merges.length > 0) {
2934
+ fillDownMergedCells(rows, merges);
2935
+ }
2642
2936
  if (allSheetNames("event_data").includes(sName)) {
2643
2937
  const result = parseEventSheet(rows, source, sName);
2644
2938
  events = result.events;
@@ -2920,6 +3214,9 @@ function registerCode(cmd) {
2920
3214
  const templatePath = opts.templateName ? (await resolveTrackingTemplateByName(opts.templateName)).path : opts.template;
2921
3215
  assertInputFilePath(templatePath, opts.templateName ? "--template-name" : "--template");
2922
3216
  const draft = templatePath.endsWith(".md") ? await readTemplateMd(templatePath) : await readTemplateXlsx(templatePath);
3217
+ if (!templatePath.endsWith(".md") && draft.events.length === 0) {
3218
+ process.stderr.write(t("code.xlsx_import_empty_warning", { path: templatePath }) + "\n");
3219
+ }
2923
3220
  const inferredMode = inferSdkMode(draft.events);
2924
3221
  if (inferredMode) {
2925
3222
  draft.meta.sdk_integration_mode = inferredMode;
@@ -3047,11 +3344,19 @@ function registerLang(cmd, _rootProgram) {
3047
3344
 
3048
3345
  // src/commands/tracking/index.ts
3049
3346
  function registerTracking(program2) {
3050
- const tracking = program2.command("tracking").description("AE tracking plan lifecycle (xlsx, debug, wiki)");
3051
- registerPlan(tracking.command("plan"), program2);
3052
- registerCode(tracking.command("code"));
3053
- registerWiki(tracking.command("wiki"));
3054
- registerLang(tracking.command("lang"), program2);
3347
+ const tracking = getOrCreateCommand(program2, "tracking", "AE tracking plan lifecycle (xlsx, debug, wiki)");
3348
+ registerPlan(getOrCreateCommand(tracking, "plan", "manage AE tracking plans"), program2);
3349
+ registerCode(getOrCreateCommand(tracking, "code", "tracking code commands"));
3350
+ registerWiki(getOrCreateCommand(tracking, "wiki", "tracking wiki commands"));
3351
+ registerLang(getOrCreateCommand(tracking, "lang", "tracking language commands"), program2);
3352
+ }
3353
+ function getOrCreateCommand(parent, name, description) {
3354
+ const existing = parent.commands.find((command) => command.name() === name);
3355
+ if (existing) {
3356
+ existing.description(description);
3357
+ return existing;
3358
+ }
3359
+ return parent.command(name).description(description);
3055
3360
  }
3056
3361
 
3057
3362
  // src/index.ts
@@ -3071,52 +3376,52 @@ program.name("ae-cli").version(version).description("CLI tool for ThinkingAI (AE
3071
3376
  async function loadCommands() {
3072
3377
  const commands = [];
3073
3378
  try {
3074
- const teAnalysis = await import("./te-analysis-NJGNWZFC.js");
3379
+ const teAnalysis = await import("./te-analysis-Q7AZCDU4.js");
3075
3380
  commands.push(...teAnalysis.default);
3076
3381
  } catch {
3077
3382
  }
3078
3383
  try {
3079
- const teMeta = await import("./te-meta-MAAUHFQO.js");
3384
+ const teMeta = await import("./te-meta-VHCN4Q62.js");
3080
3385
  commands.push(...teMeta.default);
3081
3386
  } catch {
3082
3387
  }
3083
3388
  try {
3084
- const teCommon = await import("./te-common-7VTJZPII.js");
3389
+ const teCommon = await import("./te-common-ST3QPSXJ.js");
3085
3390
  commands.push(...teCommon.default);
3086
3391
  } catch {
3087
3392
  }
3088
3393
  try {
3089
- const engage = await import("./te-engage-BUWVSSSK.js");
3394
+ const engage = await import("./te-engage-JIXX3WBI.js");
3090
3395
  commands.push(...engage.default);
3091
3396
  } catch {
3092
3397
  }
3093
3398
  try {
3094
- const community = await import("./te-community-TSKJ652U.js");
3399
+ const community = await import("./te-community-X2AHXGCA.js");
3095
3400
  commands.push(...community.default);
3096
3401
  } catch {
3097
3402
  }
3098
3403
  try {
3099
- const dataops = await import("./te-dataops-F36T656A.js");
3404
+ const dataops = await import("./te-dataops-OA7I6HBG.js");
3100
3405
  commands.push(...dataops.default);
3101
3406
  } catch {
3102
3407
  }
3103
3408
  try {
3104
- const teKb = await import("./te-kb-NT33UHAE.js");
3409
+ const teKb = await import("./te-kb-CIZXRWMO.js");
3105
3410
  commands.push(...teKb.default);
3106
3411
  } catch {
3107
3412
  }
3108
3413
  try {
3109
- const teTeam = await import("./te-team-OKCOX7OE.js");
3414
+ const teTeam = await import("./te-team-PDKKW7Q5.js");
3110
3415
  commands.push(...teTeam.default);
3111
3416
  } catch {
3112
3417
  }
3113
3418
  try {
3114
- const teAgent = await import("./te-agent-FCCWUDTJ.js");
3419
+ const teAgent = await import("./te-agent-K2OWMZXT.js");
3115
3420
  commands.push(...teAgent.default);
3116
3421
  } catch {
3117
3422
  }
3118
3423
  try {
3119
- const metadata = await import("./metadata-W6JFFMBA.js");
3424
+ const metadata = await import("./metadata-3M5F2AED.js");
3120
3425
  commands.push(...metadata.default);
3121
3426
  } catch {
3122
3427
  }
@@ -3124,48 +3429,50 @@ async function loadCommands() {
3124
3429
  }
3125
3430
  async function registerAuthCommands() {
3126
3431
  try {
3127
- const { registerAuth } = await import("./auth-7H3HAAJ3.js");
3432
+ const { registerAuth } = await import("./auth-UPGUOKTW.js");
3128
3433
  registerAuth(program);
3129
3434
  } catch {
3130
3435
  }
3131
3436
  }
3132
3437
  async function registerConfigCommands() {
3133
3438
  try {
3134
- const { registerConfig } = await import("./config-7UZWDE74.js");
3439
+ const { registerConfig } = await import("./config-RCCGHHYA.js");
3135
3440
  registerConfig(program);
3136
3441
  } catch {
3137
3442
  }
3138
3443
  }
3139
3444
  async function registerApiCommand() {
3140
3445
  try {
3141
- const { registerApi } = await import("./raw-CN542NGT.js");
3446
+ const { registerApi } = await import("./raw-TPB7KSZO.js");
3142
3447
  registerApi(program);
3143
3448
  } catch {
3144
3449
  }
3145
3450
  }
3146
3451
  async function registerCapabilityCommands() {
3147
3452
  try {
3148
- const { registerCapability } = await import("./capability-SEH3JWLN.js");
3453
+ const { registerCapability } = await import("./capability-AJC5CBRT.js");
3149
3454
  registerCapability(program);
3150
3455
  } catch {
3151
3456
  }
3152
3457
  }
3153
3458
  async function registerSyncCommand() {
3154
3459
  try {
3155
- const { registerSync } = await import("./sync-ERNHDPB5.js");
3460
+ const { registerSync } = await import("./sync-EFJKFZK2.js");
3156
3461
  registerSync(program);
3157
3462
  } catch {
3158
3463
  }
3159
3464
  }
3160
3465
  async function registerModelCommand() {
3161
3466
  try {
3162
- const { registerModel } = await import("./model-T3KZJWLW.js");
3467
+ const { registerModel } = await import("./model-OYQLXCQY.js");
3163
3468
  registerModel(program);
3164
3469
  } catch {
3165
3470
  }
3166
3471
  }
3167
3472
  async function main() {
3473
+ const pkgInfo = getLocalCliPackageInfo();
3168
3474
  notifyIfUpdateAvailable({ name: pkg.name, version: pkg.version });
3475
+ await runHostCompatCheck(pkgInfo);
3169
3476
  const commands = await loadCommands();
3170
3477
  registerCommands(program, commands);
3171
3478
  await registerAuthCommands();