@thinkingai/ae-cli 6.0.20 → 6.0.24

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 (129) hide show
  1. package/README.md +1 -4
  2. package/README.zh.md +1 -4
  3. package/dist/{auth-GHBMJ5ZR.js → auth-A2XXG5K4.js} +34 -110
  4. package/dist/auth-IDPKDFSY.js +13 -0
  5. package/dist/chunk-2OW2RENH.js +193 -0
  6. package/dist/{chunk-I5CRVM2S.js → chunk-4FQ36OGO.js} +44 -17
  7. package/dist/{chunk-6W4QOZAL.js → chunk-65DKFJZB.js} +26 -16
  8. package/dist/chunk-AKORWVHJ.js +59 -0
  9. package/dist/{chunk-BJX3GXWC.js → chunk-F3ZDMC2W.js} +8 -8
  10. package/dist/chunk-FIT4CFIN.js +59 -0
  11. package/dist/{chunk-5OC7CYCG.js → chunk-IDXW6MEJ.js} +14 -14
  12. package/dist/{chunk-DMMEPCST.js → chunk-NGJDCOYA.js} +25 -115
  13. package/dist/chunk-NXJP4CES.js +209 -0
  14. package/dist/chunk-OCQPQYHZ.js +105 -0
  15. package/dist/{chunk-2DUEAXV3.js → chunk-ONOA6DYB.js} +1 -1
  16. package/dist/{chunk-RSHMZ3LG.js → chunk-PFJFZVCK.js} +13 -134
  17. package/dist/chunk-V5R5UIRM.js +195 -0
  18. package/dist/{chunk-PN3OS34E.js → chunk-WXBCP6SD.js} +1 -1
  19. package/dist/cli-token-OZXHC3U2.js +14 -0
  20. package/dist/{client-2UJ63MVQ.js → client-7L735LVY.js} +3 -3
  21. package/dist/{config-NCUGK6NS.js → config-SXD2JKSL.js} +3 -3
  22. package/dist/index.js +312 -197
  23. package/dist/metadata-QWUAX625.js +411 -0
  24. package/dist/metadata-XWTEGEN2.js +411 -0
  25. package/dist/{model-SJSOZTRS.js → model-3OVX42DA.js} +2 -2
  26. package/dist/{raw-7NVWSVJP.js → raw-IANB4AV5.js} +4 -4
  27. package/dist/{sync-GRVO4K3U.js → sync-4HQ3CXSK.js} +3 -3
  28. package/dist/{te-agent-CYZUC4US.js → te-agent-OYNNTJDU.js} +2 -2
  29. package/dist/{te-analysis-HJ22TUAA.js → te-analysis-CRPFK3LX.js} +1114 -358
  30. package/dist/te-analysis-JX3V76OI.js +2281 -0
  31. package/dist/{te-audience-MYDE5WEH.js → te-audience-77FGNG5E.js} +27 -18
  32. package/dist/te-audience-RO2IZOUC.js +599 -0
  33. package/dist/{te-common-WNCZB7R7.js → te-common-4TRJPRC5.js} +5 -4
  34. package/dist/te-common-PUXBUPOL.js +130 -0
  35. package/dist/{te-community-JEEFXPB3.js → te-community-NPDZQKMY.js} +5 -4
  36. package/dist/te-community-XKE526DS.js +687 -0
  37. package/dist/te-dataops-6KWLFNV4.js +1841 -0
  38. package/dist/{te-dataops-ZTS7XMXM.js → te-dataops-PW74WP76.js} +5 -5
  39. package/dist/{te-engage-4XHCTS6I.js → te-engage-HTLMUN7G.js} +5 -4
  40. package/dist/te-engage-YPQIVF5H.js +1510 -0
  41. package/dist/{te-kb-OWM3RQRH.js → te-kb-DOGDQIU4.js} +4 -5
  42. package/dist/{te-meta-JVO4QJBH.js → te-meta-5ESSQ5B3.js} +26 -19
  43. package/dist/te-meta-Z47X4VT3.js +595 -0
  44. package/dist/{te-team-YY24VORI.js → te-team-SOVKZIDD.js} +5 -6
  45. package/package.json +3 -2
  46. package/skills/ae-analysis/SKILL.md +60 -27
  47. package/skills/ae-analysis/references/analysis_gateway_assets.md +114 -0
  48. package/skills/ae-analysis/references/bi_panel_copy.md +15 -0
  49. package/skills/ae-analysis/references/bi_panel_create.md +15 -0
  50. package/skills/ae-analysis/references/bi_panel_delete.md +15 -0
  51. package/skills/ae-analysis/references/bi_panel_get.md +18 -0
  52. package/skills/ae-analysis/references/bi_panel_list.md +15 -0
  53. package/skills/ae-analysis/references/bi_panel_page_data_export.md +15 -0
  54. package/skills/ae-analysis/references/bi_panel_page_data_run.md +15 -0
  55. package/skills/ae-analysis/references/bi_panel_share.md +15 -0
  56. package/skills/ae-analysis/references/bi_panel_update.md +15 -0
  57. package/skills/ae-analysis/references/build_attribution_analysis_qp.md +2 -0
  58. package/skills/ae-analysis/references/build_cluster_definition.md +2 -0
  59. package/skills/ae-analysis/references/build_distribution_analysis_qp.md +2 -0
  60. package/skills/ae-analysis/references/build_event_analysis_qp.md +2 -0
  61. package/skills/ae-analysis/references/build_funnel_analysis_qp.md +2 -0
  62. package/skills/ae-analysis/references/build_heat_map_analysis_qp.md +2 -0
  63. package/skills/ae-analysis/references/build_interval_analysis_qp.md +2 -0
  64. package/skills/ae-analysis/references/build_path_analysis_qp.md +2 -0
  65. package/skills/ae-analysis/references/build_prop_analysis_qp.md +2 -0
  66. package/skills/ae-analysis/references/build_rank_list_analysis_qp.md +2 -0
  67. package/skills/ae-analysis/references/build_retention_analysis_qp.md +2 -0
  68. package/skills/ae-analysis/references/build_tag_definition.md +2 -0
  69. package/skills/ae-analysis/references/dashboard_abnormal_get.md +15 -0
  70. package/skills/ae-analysis/references/dashboard_copy.md +15 -0
  71. package/skills/ae-analysis/references/dashboard_create.md +15 -0
  72. package/skills/ae-analysis/references/dashboard_daily_report_send.md +15 -0
  73. package/skills/ae-analysis/references/dashboard_daily_report_update.md +15 -0
  74. package/skills/ae-analysis/references/dashboard_definition_export.md +15 -0
  75. package/skills/ae-analysis/references/dashboard_definition_import.md +15 -0
  76. package/skills/ae-analysis/references/dashboard_delete.md +15 -0
  77. package/skills/ae-analysis/references/dashboard_freeze.md +15 -0
  78. package/skills/ae-analysis/references/dashboard_get.md +15 -0
  79. package/skills/ae-analysis/references/dashboard_handover.md +15 -0
  80. package/skills/ae-analysis/references/dashboard_list.md +15 -0
  81. package/skills/ae-analysis/references/dashboard_report_data_export.md +15 -0
  82. package/skills/ae-analysis/references/dashboard_report_data_run.md +15 -0
  83. package/skills/ae-analysis/references/dashboard_share.md +15 -0
  84. package/skills/ae-analysis/references/dashboard_share_info.md +15 -0
  85. package/skills/ae-analysis/references/dashboard_task_status.md +15 -0
  86. package/skills/ae-analysis/references/dashboard_update.md +16 -0
  87. package/skills/ae-analysis/references/favorite_add.md +15 -0
  88. package/skills/ae-analysis/references/favorite_remove.md +15 -0
  89. package/skills/ae-analysis/references/folder_create.md +15 -0
  90. package/skills/ae-analysis/references/folder_delete.md +15 -0
  91. package/skills/ae-analysis/references/folder_members.md +15 -0
  92. package/skills/ae-analysis/references/folder_share.md +15 -0
  93. package/skills/ae-analysis/references/list_clusters.md +3 -1
  94. package/skills/ae-analysis/references/list_events.md +5 -2
  95. package/skills/ae-analysis/references/list_metrics.md +4 -2
  96. package/skills/ae-analysis/references/list_properties.md +4 -2
  97. package/skills/ae-analysis/references/list_tags.md +3 -1
  98. package/skills/ae-analysis/references/project_space_create.md +15 -0
  99. package/skills/ae-analysis/references/project_space_delete.md +15 -0
  100. package/skills/ae-analysis/references/project_space_get.md +18 -0
  101. package/skills/ae-analysis/references/project_space_list.md +15 -0
  102. package/skills/ae-analysis/references/project_space_members.md +15 -0
  103. package/skills/ae-analysis/references/project_space_share.md +15 -0
  104. package/skills/ae-analysis/references/public_link_create.md +15 -0
  105. package/skills/ae-analysis/references/public_link_delete.md +15 -0
  106. package/skills/ae-analysis/references/public_link_list.md +15 -0
  107. package/skills/ae-analysis/references/public_link_offline.md +15 -0
  108. package/skills/ae-analysis/references/public_link_update.md +15 -0
  109. package/skills/ae-analysis/references/query_cancel.md +15 -0
  110. package/skills/ae-generate-tracking-code/SKILL.md +68 -31
  111. package/skills/ae-generate-tracking-code/references/snippet-delivery.md +26 -1
  112. package/skills/ae-generate-tracking-code/references/te-api.md +47 -164
  113. package/skills/ae-generate-tracking-plan/SKILL.md +109 -32
  114. package/skills/ae-generate-tracking-plan/references/te-api.md +57 -27
  115. package/skills/ae-metadata/SKILL.md +90 -0
  116. package/skills/ae-metadata/references/metadata_data_table_csv_delete.md +15 -0
  117. package/skills/ae-metadata/references/metadata_data_table_csv_write.md +31 -0
  118. package/skills/ae-metadata/references/metadata_data_table_download.md +17 -0
  119. package/skills/ae-metadata/references/metadata_data_table_get.md +24 -0
  120. package/skills/ae-metadata/references/metadata_data_table_list.md +27 -0
  121. package/skills/ae-metadata/references/metadata_data_table_property_bindings_update.md +17 -0
  122. package/skills/ae-metadata/references/metadata_data_table_sql_delete.md +15 -0
  123. package/skills/ae-metadata/references/metadata_data_table_sql_write.md +32 -0
  124. package/skills/ae-metadata/references/metadata_event_get.md +52 -0
  125. package/skills/ae-metadata/references/metadata_input_file_upload.md +29 -0
  126. package/skills/ae-metadata/references/metadata_property_dimension_table_bind_existing.md +27 -0
  127. package/skills/ae-metadata/references/metadata_property_dimension_table_create_and_bind_csv.md +32 -0
  128. package/skills/ae-metadata/references/metadata_property_get.md +54 -0
  129. package/dist/auth-DYC2BGLM.js +0 -21
package/dist/index.js CHANGED
@@ -1,28 +1,33 @@
1
1
  import {
2
2
  TeAgentApiError,
3
3
  TeAgentCredentialsError
4
- } from "./chunk-I5CRVM2S.js";
4
+ } from "./chunk-4FQ36OGO.js";
5
5
  import {
6
6
  printError,
7
7
  printOutput
8
- } from "./chunk-2DUEAXV3.js";
8
+ } from "./chunk-ONOA6DYB.js";
9
9
  import {
10
- httpGet
11
- } from "./chunk-BJX3GXWC.js";
10
+ CapabilityGatewayError,
11
+ executeCapability,
12
+ uploadInputFileBytes
13
+ } from "./chunk-2OW2RENH.js";
12
14
  import {
13
15
  PermissionError
14
16
  } from "./chunk-NOO24N7W.js";
17
+ import {
18
+ clearCliToken,
19
+ getCliToken
20
+ } from "./chunk-OCQPQYHZ.js";
15
21
  import {
16
22
  SecureStoreAuthError,
17
- getToken,
18
23
  resolveHost
19
- } from "./chunk-RSHMZ3LG.js";
24
+ } from "./chunk-PFJFZVCK.js";
20
25
  import {
21
26
  getActiveHost,
22
27
  getConfigDir,
23
28
  logger,
24
29
  safeJsonParse
25
- } from "./chunk-6W4QOZAL.js";
30
+ } from "./chunk-65DKFJZB.js";
26
31
 
27
32
  // src/index.ts
28
33
  import { Command as CommanderCommand } from "commander";
@@ -33,13 +38,13 @@ import * as readline from "readline";
33
38
  async function runCommand(cmd, opts, globalOpts) {
34
39
  try {
35
40
  const ctx = createRuntimeContext(cmd, opts, globalOpts);
36
- const cmdName = `${cmd.service} ${cmd.command}`;
41
+ const cmdName = cmd.resource ? `${cmd.service} ${cmd.resource} ${cmd.command}` : `${cmd.service} ${cmd.command}`;
37
42
  logger.command(cmdName, opts);
38
43
  for (const flag of cmd.flags) {
39
44
  if (flag.required) {
40
45
  const val = opts[camelCase(flag.name)];
41
46
  if (val === void 0 || val === null || val === "") {
42
- printError("validation", `Missing required flag: --${flag.name}`, `Usage: ae-cli ${cmd.service} ${cmd.command} --${flag.name} <value>`);
47
+ printError("validation", `Missing required flag: --${flag.name}`, `Usage: ae-cli ${cmdName} --${flag.name} <value>`);
43
48
  process.exit(1);
44
49
  }
45
50
  }
@@ -71,7 +76,7 @@ async function runCommand(cmd, opts, globalOpts) {
71
76
  return;
72
77
  }
73
78
  if (cmd.risk === "write" && !globalOpts.yes) {
74
- const confirmed = await confirm(`This is a write operation (${cmd.service} ${cmd.command}). Continue?`);
79
+ const confirmed = await confirm(`This is a write operation (${cmdName}). Continue?`);
75
80
  if (!confirmed) {
76
81
  process.stderr.write("Aborted.\n");
77
82
  process.exit(0);
@@ -86,6 +91,8 @@ async function runCommand(cmd, opts, globalOpts) {
86
91
  printError("config", message, err.hint);
87
92
  } else if (err instanceof PermissionError) {
88
93
  printError("permission", message);
94
+ } else if (err instanceof CapabilityGatewayError) {
95
+ printError("api", message, err.hint, err.code);
89
96
  } else if (err instanceof SecureStoreAuthError) {
90
97
  printError("auth", message, "Run: ae-cli auth login");
91
98
  } else if (err instanceof TeAgentApiError) {
@@ -113,7 +120,7 @@ function createRuntimeContext(cmd, opts, globalOpts) {
113
120
  let _clientModule = null;
114
121
  async function getClient() {
115
122
  if (!_clientModule) {
116
- _clientModule = await import("./client-2UJ63MVQ.js");
123
+ _clientModule = await import("./client-7L735LVY.js");
117
124
  }
118
125
  return _clientModule;
119
126
  }
@@ -161,8 +168,8 @@ function createRuntimeContext(cmd, opts, globalOpts) {
161
168
  return client.queryReportData(projectId, reportId, qp, eventModel, options, ctx.host());
162
169
  },
163
170
  async token() {
164
- const { getToken: getToken2 } = await import("./auth-DYC2BGLM.js");
165
- return getToken2(ctx.host());
171
+ const { getToken } = await import("./auth-IDPKDFSY.js");
172
+ return getToken(ctx.host());
166
173
  },
167
174
  host() {
168
175
  if (globalOpts.host) return globalOpts.host;
@@ -185,10 +192,10 @@ function camelCase(str) {
185
192
  }
186
193
  async function confirm(message) {
187
194
  const rl = readline.createInterface({ input: process.stdin, output: process.stderr });
188
- return new Promise((resolve2) => {
195
+ return new Promise((resolve3) => {
189
196
  rl.question(`${message} [y/N] `, (answer) => {
190
197
  rl.close();
191
- resolve2(answer.toLowerCase() === "y" || answer.toLowerCase() === "yes");
198
+ resolve3(answer.toLowerCase() === "y" || answer.toLowerCase() === "yes");
192
199
  });
193
200
  });
194
201
  }
@@ -207,7 +214,15 @@ function registerCommands(program2, commands) {
207
214
  serviceCmd = program2.command(service).description(`${service} domain commands`);
208
215
  }
209
216
  for (const cmd of cmds) {
210
- const sub = serviceCmd.command(cmd.command).description(cmd.description);
217
+ let parent = serviceCmd;
218
+ if (cmd.resource) {
219
+ let resourceCmd = serviceCmd.commands.find((c) => c.name() === cmd.resource);
220
+ if (!resourceCmd) {
221
+ resourceCmd = serviceCmd.command(cmd.resource).description(`${cmd.resource} commands`);
222
+ }
223
+ parent = resourceCmd;
224
+ }
225
+ const sub = parent.command(cmd.command).description(cmd.description);
211
226
  for (const flag of cmd.flags) {
212
227
  const flagStr = buildFlagString(flag);
213
228
  if (flag.type === "boolean") {
@@ -403,7 +418,7 @@ function notifyIfUpdateAvailable(pkg2) {
403
418
 
404
419
  // src/commands/tracking/plan.ts
405
420
  import { readFile, writeFile, cp } from "fs/promises";
406
- import path3, { resolve } from "path";
421
+ import path3, { resolve as resolve2 } from "path";
407
422
 
408
423
  // src/tracking/xlsx/write.ts
409
424
  import ExcelJS from "exceljs";
@@ -1016,30 +1031,13 @@ async function writeDraftXlsx(d, outPath, locale = "zh") {
1016
1031
  await workbook.xlsx.writeFile(outPath);
1017
1032
  }
1018
1033
 
1019
- // src/tracking/i18n/ae-locale.ts
1020
- function aeLocaleToCli(raw) {
1021
- const normalized = raw.trim().replace("-", "_").toLowerCase();
1022
- if (normalized.startsWith("zh")) return "zh";
1023
- if (normalized.startsWith("en")) return "en";
1024
- if (normalized.startsWith("ja")) return "ja";
1025
- if (normalized.startsWith("ko")) return "ko";
1026
- return null;
1027
- }
1028
- function cliLocaleToAE(locale) {
1029
- switch (locale) {
1030
- case "zh":
1031
- return "zh_CN";
1032
- case "en":
1033
- return "en_US";
1034
- case "ja":
1035
- return "ja_JP";
1036
- case "ko":
1037
- return "ko_KR";
1038
- }
1039
- }
1040
-
1041
1034
  // src/core/tracking-client.ts
1042
1035
  var DEBUG_BASE = "/v1/ta/bury/manage/debug";
1036
+ var TRACK_CAPABILITY_DOMAIN = "analysis";
1037
+ var TRACK_PROGRAM_QUERY = "track.program.query";
1038
+ var TRACK_PROGRAM_DELETE = "track.program.delete";
1039
+ var TRACK_PROGRAM_EXCEL_SAVE = "track.program.excel_save";
1040
+ var TRACK_PROGRAM_XLSX_PURPOSE = "track.program.xlsx";
1043
1041
  function buildUrl(host, modulePath, params = {}) {
1044
1042
  const base = host.replace(/\/$/, "");
1045
1043
  const p = modulePath.startsWith("/") ? modulePath : `/${modulePath}`;
@@ -1049,89 +1047,185 @@ function buildUrl(host, modulePath, params = {}) {
1049
1047
  }
1050
1048
  return url.toString();
1051
1049
  }
1052
- function extractLangFromConfig(data) {
1050
+ function record(value) {
1051
+ return value && typeof value === "object" && !Array.isArray(value) ? value : null;
1052
+ }
1053
+ function pick(source, camelKey, snakeKey) {
1054
+ return source[camelKey] ?? source[snakeKey];
1055
+ }
1056
+ function stringArray(value) {
1057
+ return Array.isArray(value) ? value.filter((item) => typeof item === "string") : [];
1058
+ }
1059
+ function mapArray(value, mapper) {
1060
+ return Array.isArray(value) ? value.map(record).filter((item) => item !== null).map(mapper) : [];
1061
+ }
1062
+ function normalizeProperty(value) {
1063
+ return {
1064
+ name: value.name,
1065
+ displayName: pick(value, "displayName", "display_name"),
1066
+ type: value.type,
1067
+ desc: value.desc,
1068
+ createTime: pick(value, "createTime", "create_time"),
1069
+ creator: value.creator,
1070
+ lastUpdateAuth: pick(value, "lastUpdateAuth", "last_update_auth"),
1071
+ lastUpdateTime: pick(value, "lastUpdateTime", "last_update_time"),
1072
+ hasReported: pick(value, "hasReported", "has_reported")
1073
+ };
1074
+ }
1075
+ function normalizeUserProperty(value) {
1076
+ return {
1077
+ ...normalizeProperty(value),
1078
+ propTag: pick(value, "propTag", "prop_tag"),
1079
+ updateType: pick(value, "updateType", "update_type") ?? "user_set",
1080
+ updateTypeName: pick(value, "updateTypeName", "update_type_name")
1081
+ };
1082
+ }
1083
+ function normalizeEvent(value) {
1084
+ return {
1085
+ eventName: pick(value, "eventName", "event_name") ?? "",
1086
+ displayName: pick(value, "displayName", "display_name"),
1087
+ eventDesc: pick(value, "eventDesc", "event_desc"),
1088
+ eventTag: pick(value, "eventTag", "event_tag"),
1089
+ createTime: pick(value, "createTime", "create_time"),
1090
+ creator: value.creator,
1091
+ lastUpdateAuth: pick(value, "lastUpdateAuth", "last_update_auth"),
1092
+ lastUpdateTime: pick(value, "lastUpdateTime", "last_update_time"),
1093
+ hasReported: pick(value, "hasReported", "has_reported"),
1094
+ props: stringArray(value.props),
1095
+ propInfosOnEvent: pick(value, "propInfosOnEvent", "prop_infos_on_event")
1096
+ };
1097
+ }
1098
+ function normalizeProgram(value) {
1099
+ const data = record(value);
1053
1100
  if (!data) return null;
1054
- const raw = typeof data.lang === "string" && data.lang || typeof data.umi_locale === "string" && data.umi_locale || typeof data.locale === "string" && data.locale || null;
1055
- return raw ? aeLocaleToCli(raw) : null;
1101
+ return {
1102
+ projectId: pick(data, "projectId", "project_id") ?? 0,
1103
+ createTime: pick(data, "createTime", "create_time"),
1104
+ events: mapArray(data.events, normalizeEvent),
1105
+ eventProps: mapArray(pick(data, "eventProps", "event_props"), normalizeProperty),
1106
+ commonEventProps: mapArray(pick(data, "commonEventProps", "common_event_props"), normalizeProperty),
1107
+ userProps: mapArray(pick(data, "userProps", "user_props"), normalizeUserProperty)
1108
+ };
1109
+ }
1110
+ function normalizeUploadError(value) {
1111
+ return {
1112
+ errorType: pick(value, "errorType", "error_type") ?? "",
1113
+ errorTypeDesc: pick(value, "errorTypeDesc", "error_type_desc") ?? "",
1114
+ cellName: pick(value, "cellName", "cell_name") ?? "",
1115
+ row: Number(value.row ?? 0),
1116
+ value: String(value.value ?? "")
1117
+ };
1118
+ }
1119
+ function normalizeUploadErrorMap(value) {
1120
+ const data = record(value);
1121
+ if (!data) return void 0;
1122
+ const result = {};
1123
+ for (const [key, items] of Object.entries(data)) {
1124
+ result[key] = mapArray(items, normalizeUploadError);
1125
+ }
1126
+ return result;
1127
+ }
1128
+ function normalizeUploadResponse(value) {
1129
+ const data = record(value);
1130
+ if (!data) return { return_code: 0, return_message: "success" };
1131
+ const responseData = record(data.data);
1132
+ const uploadErrors = record(pick(data, "uploadErrors", "upload_errors")) ?? record(pick(responseData ?? {}, "uploadErrors", "upload_errors"));
1133
+ const errorSource = uploadErrors ?? responseData ?? data;
1134
+ const eventErrorMap = normalizeUploadErrorMap(pick(errorSource, "eventErrorMap", "event_error_map"));
1135
+ const userErrorMap = normalizeUploadErrorMap(pick(errorSource, "userErrorMap", "user_error_map"));
1136
+ const hasErrors = Boolean(
1137
+ eventErrorMap && Object.keys(eventErrorMap).length > 0 || userErrorMap && Object.keys(userErrorMap).length > 0
1138
+ );
1139
+ return {
1140
+ return_code: typeof data.return_code === "number" ? data.return_code : 0,
1141
+ return_message: typeof data.return_message === "string" ? data.return_message : hasErrors ? "validation errors" : "success",
1142
+ data: hasErrors ? { eventErrorMap, userErrorMap } : void 0
1143
+ };
1056
1144
  }
1057
1145
  var TrackingClient = class {
1058
- constructor(host, token) {
1146
+ constructor(host, cliToken) {
1059
1147
  this.host = host;
1060
- this.token = token;
1148
+ this.cliToken = cliToken;
1061
1149
  }
1062
1150
  host;
1063
- token;
1064
- async resolveToken() {
1065
- return this.token ?? getToken(this.host);
1151
+ cliToken;
1152
+ async resolveCliToken() {
1153
+ return this.cliToken ?? getCliToken(this.host);
1154
+ }
1155
+ async requestJson(modulePath, params = {}, body, method = body === void 0 ? "GET" : "POST", retry = true) {
1156
+ const token = await this.resolveCliToken();
1157
+ const url = buildUrl(this.host, modulePath, params);
1158
+ const headers = {
1159
+ "cli-token": token,
1160
+ accept: "application/json"
1161
+ };
1162
+ const init = { method, headers };
1163
+ if (body !== void 0 && method !== "GET") {
1164
+ headers["content-type"] = "application/json";
1165
+ init.body = JSON.stringify(body);
1166
+ }
1167
+ const resp = await fetch(url, init);
1168
+ const env = safeJsonParse(await resp.text());
1169
+ logger.api(method, url, resp.status, body, env);
1170
+ if (resp.status === 401 && retry) {
1171
+ clearCliToken(this.host);
1172
+ this.cliToken = await getCliToken(this.host);
1173
+ return this.requestJson(modulePath, params, body, method, false);
1174
+ }
1175
+ if (resp.status === 403) {
1176
+ throw new Error(env?.return_message || "Permission denied");
1177
+ }
1178
+ if (!resp.ok) {
1179
+ throw new Error(`AE API HTTP error: ${resp.status} ${resp.statusText}`);
1180
+ }
1181
+ if (env?.return_code === -1001 && retry) {
1182
+ clearCliToken(this.host);
1183
+ this.cliToken = await getCliToken(this.host);
1184
+ return this.requestJson(modulePath, params, body, method, false);
1185
+ }
1186
+ if (env?.return_code !== 0 && env?.return_code !== void 0) {
1187
+ throw new Error(env.return_message || `AE API error (code: ${env.return_code})`);
1188
+ }
1189
+ return env?.data;
1066
1190
  }
1067
1191
  async getProgram(projectId) {
1068
- const data = await httpGet(
1069
- "/v1/ta/bury/manage/program/query",
1070
- { projectId, "@t": Date.now() },
1071
- this.host
1072
- );
1073
- return data ?? null;
1192
+ const data = await executeCapability(this.host, TRACK_CAPABILITY_DOMAIN, TRACK_PROGRAM_QUERY, {
1193
+ project_id: projectId
1194
+ });
1195
+ return normalizeProgram(data);
1074
1196
  }
1075
1197
  async deleteProgram(projectId) {
1076
- const token = await this.resolveToken();
1077
- const url = buildUrl(this.host, "/v1/ta/bury/manage/program/delete", {
1078
- projectId,
1079
- "@t": Date.now()
1198
+ await executeCapability(this.host, TRACK_CAPABILITY_DOMAIN, TRACK_PROGRAM_DELETE, {
1199
+ project_id: projectId
1080
1200
  });
1081
- const resp = await fetch(url, {
1082
- method: "GET",
1083
- headers: {
1084
- authorization: `bearer ${token}`,
1085
- accept: "application/json"
1086
- }
1087
- });
1088
- const env = safeJsonParse(await resp.text());
1089
- if (env.return_code !== 0) {
1090
- throw new Error(env.return_message || `AE API error (code: ${env.return_code})`);
1091
- }
1092
- return { return_code: env.return_code, return_message: env.return_message };
1201
+ return { return_code: 0, return_message: "success" };
1093
1202
  }
1094
1203
  async uploadProgramExcel(args) {
1095
- const token = await this.resolveToken();
1096
- const form = new FormData();
1097
- form.append(
1098
- "file",
1099
- new Blob([new Uint8Array(args.file)], {
1100
- type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
1101
- }),
1102
- args.filename
1204
+ const inputFile = await uploadInputFileBytes(
1205
+ this.host,
1206
+ TRACK_CAPABILITY_DOMAIN,
1207
+ args.projectId,
1208
+ TRACK_PROGRAM_XLSX_PURPOSE,
1209
+ args.file,
1210
+ args.filename,
1211
+ "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
1103
1212
  );
1104
- form.append("projectId", String(args.projectId));
1105
- form.append("access_token", token);
1106
- const url = buildUrl(this.host, "/v1/ta/bury/manage/program/excel-save");
1107
- const resp = await fetch(url, { method: "POST", body: form });
1108
- const env = safeJsonParse(await resp.text());
1213
+ const inputFileId = inputFile?.input_file_id ?? inputFile?.inputFileId ?? inputFile?.id;
1214
+ if (!inputFileId) {
1215
+ throw new Error("Capability gateway input-file upload did not return input_file_id");
1216
+ }
1217
+ const data = await executeCapability(this.host, TRACK_CAPABILITY_DOMAIN, TRACK_PROGRAM_EXCEL_SAVE, {
1218
+ project_id: args.projectId,
1219
+ input_file_id: inputFileId
1220
+ });
1221
+ const env = normalizeUploadResponse(data);
1109
1222
  if (env.return_code !== 0 && env.return_code !== void 0 && !env.data?.eventErrorMap && !env.data?.userErrorMap) {
1110
1223
  logger.error(`Upload failed: ${env.return_message || `AE API error (code: ${env.return_code})`}`);
1111
1224
  }
1112
1225
  return env;
1113
1226
  }
1114
- async getUserAutoConfig() {
1115
- const data = await httpGet(
1116
- "/v1/ta/auto/config/getUserAutoConfig",
1117
- { "@t": Date.now() },
1118
- this.host
1119
- );
1120
- if (data && typeof data === "object") {
1121
- return data;
1122
- }
1123
- return null;
1124
- }
1125
- async getServerLang() {
1126
- const config = await this.getUserAutoConfig();
1127
- return extractLangFromConfig(config);
1128
- }
1129
- /** lang format: zh_CN, en_US, ja_JP, ko_KR */
1130
- async saveUserAutoConfig(langCode) {
1131
- await httpGet("/v1/ta/auto/config/getUserAutoConfig", { "@t": Date.now(), lang: langCode }, this.host);
1132
- }
1133
1227
  async debugGet(path5, params) {
1134
- const data = await httpGet(`${DEBUG_BASE}${path5}`, { ...params, "@t": Date.now() }, this.host);
1228
+ const data = await this.requestJson(`${DEBUG_BASE}${path5}`, { ...params, "@t": Date.now() });
1135
1229
  return data;
1136
1230
  }
1137
1231
  async listDevice(projectId) {
@@ -1157,8 +1251,7 @@ var TrackingClient = class {
1157
1251
  }
1158
1252
  };
1159
1253
  async function createTrackingClient(host) {
1160
- const token = await getToken(host);
1161
- return new TrackingClient(host, token);
1254
+ return new TrackingClient(host);
1162
1255
  }
1163
1256
 
1164
1257
  // src/tracking/te-plan/fetch.ts
@@ -1746,23 +1839,70 @@ function formatConflictReport(result, existingSummary) {
1746
1839
  }
1747
1840
 
1748
1841
  // src/commands/tracking/plan.ts
1842
+ import { existsSync as existsSync5 } from "fs";
1843
+
1844
+ // src/tracking/templates.ts
1749
1845
  import { readdir } from "fs/promises";
1750
- import { existsSync as existsSync4 } from "fs";
1846
+ import { existsSync as existsSync3 } from "fs";
1847
+ import { resolve } from "path";
1848
+ function getTemplateDirs() {
1849
+ return [
1850
+ resolve(getPackageRoot(), "tracking-plan-template"),
1851
+ resolve(getConfigDir(), "templates")
1852
+ ];
1853
+ }
1854
+ async function listTrackingTemplates() {
1855
+ const found = [];
1856
+ for (const dir of getTemplateDirs()) {
1857
+ if (!existsSync3(dir)) continue;
1858
+ let entries = [];
1859
+ try {
1860
+ entries = await readdir(dir);
1861
+ } catch {
1862
+ continue;
1863
+ }
1864
+ for (const f of entries) {
1865
+ if (!f.endsWith(".xlsx")) continue;
1866
+ const base = f.replace(/\.xlsx$/i, "");
1867
+ const mdPath = resolve(dir, base + ".md");
1868
+ const hasMd = existsSync3(mdPath);
1869
+ found.push({
1870
+ path: hasMd ? mdPath : resolve(dir, f),
1871
+ name: base,
1872
+ hasMd
1873
+ });
1874
+ }
1875
+ }
1876
+ return found;
1877
+ }
1878
+ async function resolveTrackingTemplateByName(name) {
1879
+ const normalized = name.trim().replace(/\.(md|xlsx)$/i, "");
1880
+ const templates = await listTrackingTemplates();
1881
+ const template = templates.find((item) => item.name === normalized);
1882
+ if (!template) {
1883
+ const available = templates.map((item) => item.name).join(", ");
1884
+ throw new Error(
1885
+ available ? `Template not found: ${name}. Available templates: ${available}` : `Template not found: ${name}. No tracking plan templates are available.`
1886
+ );
1887
+ }
1888
+ return template;
1889
+ }
1751
1890
 
1752
1891
  // src/commands/tracking/shared.ts
1753
- import { existsSync as existsSync3, statSync } from "fs";
1892
+ import { existsSync as existsSync4, statSync } from "fs";
1754
1893
  var HOST_OPTION_DESC = "Override active AE host URL";
1755
1894
  function resolveTrackingHost(program2, opts) {
1756
1895
  const root = program2.root ?? program2;
1757
1896
  const globalHost = root.opts()?.host;
1758
- const host = resolveHost(opts.host || globalHost);
1897
+ const explicitHost = opts.host || globalHost;
1898
+ const host = resolveHost(explicitHost);
1759
1899
  if (!host) {
1760
1900
  throw new Error("No active AE host configured. Run: ae-cli auth login");
1761
1901
  }
1762
1902
  return host;
1763
1903
  }
1764
1904
  function isExistingDirectory(path5) {
1765
- if (!existsSync3(path5)) return false;
1905
+ if (!existsSync4(path5)) return false;
1766
1906
  try {
1767
1907
  return statSync(path5).isDirectory();
1768
1908
  } catch {
@@ -1778,7 +1918,7 @@ function assertOutputFilePath(path5, optionName = "--out") {
1778
1918
  }
1779
1919
  function assertInputFilePath(path5, optionName = "--in") {
1780
1920
  const trimmed = path5.trim();
1781
- if (!existsSync3(trimmed)) {
1921
+ if (!existsSync4(trimmed)) {
1782
1922
  console.error(t("error.input_path_not_found", { path: trimmed, option: optionName }));
1783
1923
  process.exit(1);
1784
1924
  }
@@ -1790,10 +1930,6 @@ function assertInputFilePath(path5, optionName = "--in") {
1790
1930
 
1791
1931
  // src/commands/tracking/plan.ts
1792
1932
  var MAX_FIX_RETRIES = 3;
1793
- var TEMPLATE_DIRS = [
1794
- resolve(getPackageRoot(), "tracking-plan-template"),
1795
- resolve(getConfigDir(), "templates")
1796
- ];
1797
1933
  function registerPlan(cmd, rootProgram) {
1798
1934
  cmd.description("manage AE tracking plans");
1799
1935
  cmd.command("draft").description("Generate xlsx from draft.json (inject autotrack events; use --fix to auto-repair validation errors)").requiredOption("--in <path>", "draft JSON input").requiredOption("--out <path>", "xlsx output").option("--fix", "auto fix validation errors", false).action(async (opts) => {
@@ -1871,27 +2007,12 @@ function registerPlan(cmd, rootProgram) {
1871
2007
  }
1872
2008
  }
1873
2009
  });
1874
- cmd.command("upload").description("Upload xlsx tracking plan to AE (conflict check, auto-fix retry, optional --switch-lang)").requiredOption("-p, --project <id>", "AE projectId", (v) => parseInt(v, 10)).requiredOption("--xlsx <path>", "xlsx file").requiredOption("--draft <path>", "draft JSON (for auto-fix)").option("--host <url>", HOST_OPTION_DESC).option("--lang <locale>", "xlsx language: zh / en / ja / ko").option("--replace", "delete existing plan first", false).option("--auto-fix", "auto fix upload errors and retry", true).option("--switch-lang", "auto switch AE project language to match xlsx", false).action(async (opts) => {
2010
+ cmd.command("upload").description("Upload xlsx tracking plan to AE (conflict check, auto-fix retry)").requiredOption("-p, --project <id>", "AE projectId", (v) => parseInt(v, 10)).requiredOption("--xlsx <path>", "xlsx file").requiredOption("--draft <path>", "draft JSON (for auto-fix)").option("--host <url>", HOST_OPTION_DESC).option("--lang <locale>", "xlsx language: zh / en / ja / ko").option("--replace", "delete existing plan first", false).option("--auto-fix", "auto fix upload errors and retry", true).action(async (opts) => {
1875
2011
  assertInputFilePath(opts.draft, "--draft");
1876
2012
  assertInputFilePath(opts.xlsx, "--xlsx");
1877
2013
  const host = resolveTrackingHost(rootProgram, opts);
1878
2014
  let client = await createTrackingClient(host);
1879
2015
  const draftPre = JSON.parse(await readFile(opts.draft, "utf8"));
1880
- const xlsxLocale = opts.lang ?? draftPre.meta.lang ?? detectCliLocale();
1881
- const aeLocale = await client.getServerLang();
1882
- if (aeLocale && aeLocale !== xlsxLocale) {
1883
- console.log("\n" + t("plan.ae_lang_mismatch", { aeLang: aeLocale, xlsxLang: xlsxLocale }));
1884
- if (opts.switchLang) {
1885
- const aeLangCode = cliLocaleToAE(xlsxLocale);
1886
- await client.saveUserAutoConfig(aeLangCode);
1887
- console.log(t("plan.ae_lang_switched", { aeLang: aeLangCode }));
1888
- await new Promise((r) => setTimeout(r, 2e3));
1889
- client = await createTrackingClient(host);
1890
- } else {
1891
- console.log(t("plan.ae_lang_switch_hint"));
1892
- process.exit(13);
1893
- }
1894
- }
1895
2016
  if (!opts.replace) {
1896
2017
  console.log(t("plan.checking_conflicts"));
1897
2018
  try {
@@ -1931,7 +2052,7 @@ function registerPlan(cmd, rootProgram) {
1931
2052
  if (opts.replace) {
1932
2053
  const del = await client.deleteProgram(opts.project);
1933
2054
  console.log(t("plan.deleted_existing_plan", { message: del.return_message }));
1934
- await new Promise((resolve2) => setTimeout(resolve2, 5e3));
2055
+ await new Promise((resolve3) => setTimeout(resolve3, 5e3));
1935
2056
  }
1936
2057
  let retryCount = 0;
1937
2058
  let draft = JSON.parse(await readFile(opts.draft, "utf8"));
@@ -1979,8 +2100,8 @@ function registerPlan(cmd, rootProgram) {
1979
2100
  const msg = lastRes?.return_message ?? "";
1980
2101
  const isLangMismatch = msg.includes("\u65E0\u6CD5\u8BC6\u522B\u8868\u683C\u5185\u5BB9") || msg.includes("The content of the form cannot be recognized") || msg.includes("\u30C6\u30FC\u30D6\u30EB\u306E\u5185\u5BB9\u3092\u8A8D\u8B58\u3067\u304D\u307E\u305B\u3093") || msg.includes("\uD2B8\uB798\uD0B9 \uBC29\uC548\uC744 \uC2E4\uBCC4 \uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4");
1981
2102
  if (lastRes && lastRes.return_code !== 0 && isLangMismatch) {
1982
- const xlsxLocale2 = opts.lang ?? draft.meta.lang ?? detectCliLocale();
1983
- console.log("\n" + t("plan.language_mismatch_hint", { locale: xlsxLocale2 }));
2103
+ const xlsxLocale = opts.lang ?? draft.meta.lang ?? detectCliLocale();
2104
+ console.log("\n" + t("plan.language_mismatch_hint", { locale: xlsxLocale }));
1984
2105
  }
1985
2106
  });
1986
2107
  cmd.command("fetch").description("Fetch tracking plan from AE and output draft.json").requiredOption("-p, --project <id>", "AE projectId", (v) => parseInt(v, 10)).option("--host <url>", HOST_OPTION_DESC).option("--out <path>", "write to file instead of stdout").action(async (opts) => {
@@ -1992,12 +2113,12 @@ function registerPlan(cmd, rootProgram) {
1992
2113
  await writeFile(opts.out, s, "utf8");
1993
2114
  } else process.stdout.write(s);
1994
2115
  });
1995
- cmd.command("archive").description("Copy draft.xlsx to plans/ and record archive metadata in draft.json").requiredOption("--draft <path>", "draft.json path").requiredOption("--xlsx <path>", "draft.xlsx path").requiredOption("--name <name>", "plan name for filename").option("--plans-dir <dir>", "plans output directory", resolve(process.cwd(), "plans")).action(async (opts) => {
2116
+ cmd.command("archive").description("Copy draft.xlsx to plans/ and record archive metadata in draft.json").requiredOption("--draft <path>", "draft.json path").requiredOption("--xlsx <path>", "draft.xlsx path").requiredOption("--name <name>", "plan name for filename").option("--plans-dir <dir>", "plans output directory", resolve2(process.cwd(), "plans")).action(async (opts) => {
1996
2117
  assertInputFilePath(opts.draft, "--draft");
1997
2118
  assertInputFilePath(opts.xlsx, "--xlsx");
1998
2119
  const stamp = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
1999
- const dest = resolve(opts.plansDir, `${stamp}-${opts.name}.xlsx`);
2000
- if (existsSync4(dest)) {
2120
+ const dest = resolve2(opts.plansDir, `${stamp}-${opts.name}.xlsx`);
2121
+ if (existsSync5(dest)) {
2001
2122
  console.error(t("plan.archive_exists", { path: dest }));
2002
2123
  console.error(t("plan.remove_or_rename"));
2003
2124
  return;
@@ -2025,30 +2146,14 @@ function registerPlan(cmd, rootProgram) {
2025
2146
  const res = await client.deleteProgram(opts.project);
2026
2147
  console.log(JSON.stringify(res, null, 2));
2027
2148
  });
2028
- cmd.command("list-templates").description("List bundled and user tracking plan templates (xlsx/md)").action(async () => {
2029
- const found = [];
2030
- for (const dir of TEMPLATE_DIRS) {
2031
- if (!existsSync4(dir)) continue;
2032
- let entries = [];
2033
- try {
2034
- entries = await readdir(dir);
2035
- } catch {
2036
- continue;
2037
- }
2038
- for (const f of entries) {
2039
- if (!f.endsWith(".xlsx")) continue;
2040
- const base = f.replace(/\.xlsx$/i, "");
2041
- const mdPath = resolve(dir, base + ".md");
2042
- const hasMd = existsSync4(mdPath);
2043
- found.push({
2044
- path: hasMd ? mdPath : resolve(dir, f),
2045
- name: base,
2046
- hasMd
2047
- });
2048
- }
2149
+ cmd.command("list-templates").description("List bundled and user tracking plan templates (xlsx/md)").option("--json", "print machine-readable template list", false).action(async (opts) => {
2150
+ const found = await listTrackingTemplates();
2151
+ if (opts.json) {
2152
+ console.log(JSON.stringify(found, null, 2));
2153
+ return;
2049
2154
  }
2050
2155
  if (found.length === 0) {
2051
- console.log(t("plan.no_templates_found", { dirs: TEMPLATE_DIRS.join(", ") }));
2156
+ console.log(t("plan.no_templates_found", { dirs: getTemplateDirs().join(", ") }));
2052
2157
  return;
2053
2158
  }
2054
2159
  console.log(t("plan.templates_found", { count: found.length }) + "\n");
@@ -2742,10 +2847,17 @@ function inferSdkMode(events) {
2742
2847
  }
2743
2848
  function registerCode(cmd) {
2744
2849
  cmd.description("tooling for ae-generate-tracking-code skill");
2745
- const importTemplateCmd = cmd.command("import-template").description("Import a template file (md or xlsx) to draft.json, inferring sdk_integration_mode from events").requiredOption("--template <path>", "Path to template file (.md or .xlsx)").requiredOption("--out <path>", "Output path for draft.json").option("--sdk-type <type>", "Client SDK type (android/ios/openharmony/javascript/etc.)").option("--languages <langs>", "Client languages comma-separated (e.g., java,kotlin for android)").option("--server <lang>", "Server language (java/python/go/etc.)").action(async (opts) => {
2746
- assertInputFilePath(opts.template, "--template");
2850
+ const importTemplateCmd = cmd.command("import-template").description("Import a template file (md or xlsx) to draft.json, inferring sdk_integration_mode from events").option("--template <path>", "Path to template file (.md or .xlsx)").option("--template-name <name>", "Built-in or user template name from tracking plan list-templates").requiredOption("--out <path>", "Output path for draft.json").option("--sdk-type <type>", "Client SDK type (android/ios/openharmony/javascript/etc.)").option("--languages <langs>", "Client languages comma-separated (e.g., java,kotlin for android)").option("--server <lang>", "Server language (java/python/go/etc.)").action(async (opts) => {
2851
+ if (!opts.template && !opts.templateName) {
2852
+ throw new Error("Either --template or --template-name is required");
2853
+ }
2854
+ if (opts.template && opts.templateName) {
2855
+ throw new Error("Use only one of --template or --template-name");
2856
+ }
2747
2857
  assertOutputFilePath(opts.out, "--out");
2748
- const draft = opts.template.endsWith(".md") ? await readTemplateMd(opts.template) : await readTemplateXlsx(opts.template);
2858
+ const templatePath = opts.templateName ? (await resolveTrackingTemplateByName(opts.templateName)).path : opts.template;
2859
+ assertInputFilePath(templatePath, opts.templateName ? "--template-name" : "--template");
2860
+ const draft = templatePath.endsWith(".md") ? await readTemplateMd(templatePath) : await readTemplateXlsx(templatePath);
2749
2861
  const inferredMode = inferSdkMode(draft.events);
2750
2862
  if (inferredMode) {
2751
2863
  draft.meta.sdk_integration_mode = inferredMode;
@@ -2803,12 +2915,12 @@ function registerCode(cmd) {
2803
2915
  }
2804
2916
 
2805
2917
  // src/tracking/wiki-query/query.ts
2806
- import { readFileSync as readFileSync3, existsSync as existsSync5 } from "fs";
2918
+ import { readFileSync as readFileSync3, existsSync as existsSync6 } from "fs";
2807
2919
  import { join as join4 } from "path";
2808
2920
  var WIKI_ROOT = join4(getPackageRoot(), "wiki/te-docs");
2809
2921
  function searchIndex(keyword) {
2810
2922
  const indexPath = join4(WIKI_ROOT, "index.md");
2811
- if (!existsSync5(indexPath)) return [];
2923
+ if (!existsSync6(indexPath)) return [];
2812
2924
  const lines = readFileSync3(indexPath, "utf8").split("\n");
2813
2925
  const kw = keyword.toLowerCase();
2814
2926
  const hits = [];
@@ -2840,36 +2952,34 @@ function registerWiki(cmd) {
2840
2952
  // src/commands/tracking/lang.ts
2841
2953
  var SUPPORTED = ["zh", "en", "ja", "ko"];
2842
2954
  var SUPPORTED_LABELS = {
2843
- zh: "\u4E2D\u6587 (Chinese)",
2955
+ zh: "Chinese",
2844
2956
  en: "English",
2845
- ja: "\u65E5\u672C\u8A9E (Japanese)",
2846
- ko: "\uD55C\uAD6D\uC5B4 (Korean)"
2957
+ ja: "Japanese",
2958
+ ko: "Korean"
2847
2959
  };
2848
- function registerLang(cmd, rootProgram) {
2849
- cmd.description("manage AE server language for tracking commands");
2850
- cmd.command("set").description("set the AE server language").argument("<locale>", "language code: zh / en / ja / ko").option("--host <url>", HOST_OPTION_DESC).action(async (locale, opts) => {
2960
+ function registerLang(cmd, _rootProgram) {
2961
+ cmd.description("manage local language hints for tracking commands");
2962
+ cmd.command("status").description("show local language settings for tracking commands").action(() => {
2963
+ const aeLang = process.env.AE_LANG?.trim() || "(unset)";
2964
+ const lang = process.env.LANG?.trim() || "(unset)";
2965
+ console.log("CLI language settings:");
2966
+ console.log(`- AE_LANG: ${aeLang}`);
2967
+ console.log(`- LANG: ${lang}`);
2968
+ console.log(`- resolved: ${detectCliLocale()}`);
2969
+ });
2970
+ cmd.command("set").description("print the AE_LANG value to use for subsequent commands").argument("<locale>", "language code: zh / en / ja / ko").action((locale) => {
2851
2971
  const normalized = locale.trim().toLowerCase();
2852
2972
  if (!SUPPORTED.includes(normalized)) {
2853
2973
  console.error(`Unsupported language: "${locale}"`);
2854
2974
  console.error("Supported languages:");
2855
2975
  for (const code of SUPPORTED) {
2856
- console.error(` ${code} \u2014 ${SUPPORTED_LABELS[code]}`);
2976
+ console.error(` ${code} - ${SUPPORTED_LABELS[code]}`);
2857
2977
  }
2858
2978
  process.exit(1);
2859
2979
  }
2860
- const host = resolveTrackingHost(rootProgram, opts);
2861
- const client = await createTrackingClient(host);
2862
- const aeCode = cliLocaleToAE(normalized);
2863
- await client.saveUserAutoConfig(aeCode);
2864
- process.stderr.write(`[ae-cli] Server language saved: ${aeCode}
2865
- `);
2866
- const config = await client.getUserAutoConfig();
2867
- if (config) {
2868
- const serverLang = config.lang ?? config.umi_locale ?? config.locale;
2869
- console.log(`Server response: ${JSON.stringify({ lang: serverLang })}`);
2870
- } else {
2871
- console.log("Server response: (empty)");
2872
- }
2980
+ console.log("Use this environment variable for subsequent commands:");
2981
+ console.log(`export AE_LANG=${normalized}`);
2982
+ console.log(`AE_LANG=${normalized} ae-cli tracking plan draft --in .ae-cli/draft.json --out .ae-cli/draft.xlsx`);
2873
2983
  });
2874
2984
  }
2875
2985
 
@@ -2891,88 +3001,93 @@ program.name("ae-cli").version(version).description("CLI tool for ThinkingAI (AE
2891
3001
  async function loadCommands() {
2892
3002
  const commands = [];
2893
3003
  try {
2894
- const teAnalysis = await import("./te-analysis-HJ22TUAA.js");
3004
+ const teAnalysis = await import("./te-analysis-CRPFK3LX.js");
2895
3005
  commands.push(...teAnalysis.default);
2896
3006
  } catch {
2897
3007
  }
2898
3008
  try {
2899
- const teAudience = await import("./te-audience-MYDE5WEH.js");
3009
+ const teAudience = await import("./te-audience-RO2IZOUC.js");
2900
3010
  commands.push(...teAudience.default);
2901
3011
  } catch {
2902
3012
  }
2903
3013
  try {
2904
- const teMeta = await import("./te-meta-JVO4QJBH.js");
3014
+ const teMeta = await import("./te-meta-5ESSQ5B3.js");
2905
3015
  commands.push(...teMeta.default);
2906
3016
  } catch {
2907
3017
  }
2908
3018
  try {
2909
- const teCommon = await import("./te-common-WNCZB7R7.js");
3019
+ const teCommon = await import("./te-common-PUXBUPOL.js");
2910
3020
  commands.push(...teCommon.default);
2911
3021
  } catch {
2912
3022
  }
2913
3023
  try {
2914
- const engage = await import("./te-engage-4XHCTS6I.js");
3024
+ const engage = await import("./te-engage-YPQIVF5H.js");
2915
3025
  commands.push(...engage.default);
2916
3026
  } catch {
2917
3027
  }
2918
3028
  try {
2919
- const community = await import("./te-community-JEEFXPB3.js");
3029
+ const community = await import("./te-community-NPDZQKMY.js");
2920
3030
  commands.push(...community.default);
2921
3031
  } catch {
2922
3032
  }
2923
3033
  try {
2924
- const dataops = await import("./te-dataops-ZTS7XMXM.js");
3034
+ const dataops = await import("./te-dataops-6KWLFNV4.js");
2925
3035
  commands.push(...dataops.default);
2926
3036
  } catch {
2927
3037
  }
2928
3038
  try {
2929
- const teKb = await import("./te-kb-OWM3RQRH.js");
3039
+ const teKb = await import("./te-kb-DOGDQIU4.js");
2930
3040
  commands.push(...teKb.default);
2931
3041
  } catch {
2932
3042
  }
2933
3043
  try {
2934
- const teTeam = await import("./te-team-YY24VORI.js");
3044
+ const teTeam = await import("./te-team-SOVKZIDD.js");
2935
3045
  commands.push(...teTeam.default);
2936
3046
  } catch {
2937
3047
  }
2938
3048
  try {
2939
- const teAgent = await import("./te-agent-CYZUC4US.js");
3049
+ const teAgent = await import("./te-agent-OYNNTJDU.js");
2940
3050
  commands.push(...teAgent.default);
2941
3051
  } catch {
2942
3052
  }
3053
+ try {
3054
+ const metadata = await import("./metadata-XWTEGEN2.js");
3055
+ commands.push(...metadata.default);
3056
+ } catch {
3057
+ }
2943
3058
  return commands;
2944
3059
  }
2945
3060
  async function registerAuthCommands() {
2946
3061
  try {
2947
- const { registerAuth } = await import("./auth-GHBMJ5ZR.js");
3062
+ const { registerAuth } = await import("./auth-A2XXG5K4.js");
2948
3063
  registerAuth(program);
2949
3064
  } catch {
2950
3065
  }
2951
3066
  }
2952
3067
  async function registerConfigCommands() {
2953
3068
  try {
2954
- const { registerConfig } = await import("./config-NCUGK6NS.js");
3069
+ const { registerConfig } = await import("./config-SXD2JKSL.js");
2955
3070
  registerConfig(program);
2956
3071
  } catch {
2957
3072
  }
2958
3073
  }
2959
3074
  async function registerApiCommand() {
2960
3075
  try {
2961
- const { registerApi } = await import("./raw-7NVWSVJP.js");
3076
+ const { registerApi } = await import("./raw-IANB4AV5.js");
2962
3077
  registerApi(program);
2963
3078
  } catch {
2964
3079
  }
2965
3080
  }
2966
3081
  async function registerSyncCommand() {
2967
3082
  try {
2968
- const { registerSync } = await import("./sync-GRVO4K3U.js");
3083
+ const { registerSync } = await import("./sync-4HQ3CXSK.js");
2969
3084
  registerSync(program);
2970
3085
  } catch {
2971
3086
  }
2972
3087
  }
2973
3088
  async function registerModelCommand() {
2974
3089
  try {
2975
- const { registerModel } = await import("./model-SJSOZTRS.js");
3090
+ const { registerModel } = await import("./model-3OVX42DA.js");
2976
3091
  registerModel(program);
2977
3092
  } catch {
2978
3093
  }