@thinkingai/ae-cli 6.0.18 → 6.0.22

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 (110) hide show
  1. package/README.md +8 -10
  2. package/README.zh.md +9 -11
  3. package/dist/{auth-DYC2BGLM.js → auth-I2G7OAU2.js} +2 -4
  4. package/dist/{auth-GHBMJ5ZR.js → auth-RDN6D5HU.js} +32 -104
  5. package/dist/{chunk-5OC7CYCG.js → chunk-2W7HULUD.js} +14 -14
  6. package/dist/chunk-4EUZRJPO.js +163 -0
  7. package/dist/{chunk-DMMEPCST.js → chunk-5FBLRSMU.js} +25 -115
  8. package/dist/{chunk-BJX3GXWC.js → chunk-E34XH4GW.js} +2 -2
  9. package/dist/chunk-FPE5LGVU.js +105 -0
  10. package/dist/{chunk-I5CRVM2S.js → chunk-H52CSLJW.js} +44 -17
  11. package/dist/{chunk-RSHMZ3LG.js → chunk-U6QPKCN3.js} +6 -20
  12. package/dist/{chunk-6W4QOZAL.js → chunk-WPXHCP4A.js} +23 -13
  13. package/dist/{chunk-PN3OS34E.js → chunk-XE2PI5DS.js} +1 -1
  14. package/dist/{chunk-2DUEAXV3.js → chunk-YACCPUNQ.js} +1 -1
  15. package/dist/cli-token-6AGEDJF4.js +14 -0
  16. package/dist/{client-2UJ63MVQ.js → client-VTJMUZ4O.js} +3 -3
  17. package/dist/{config-NCUGK6NS.js → config-2SDTLGOC.js} +3 -3
  18. package/dist/index.js +314 -197
  19. package/dist/metadata-JZ2OTWBK.js +420 -0
  20. package/dist/{model-SJSOZTRS.js → model-ZYMRN4VS.js} +2 -2
  21. package/dist/{raw-7NVWSVJP.js → raw-NGYHAL3F.js} +4 -4
  22. package/dist/{sync-GRVO4K3U.js → sync-JVLX6TGW.js} +3 -3
  23. package/dist/{te-agent-KZRIEN4N.js → te-agent-QPZTLHPH.js} +545 -21
  24. package/dist/{te-analysis-VAR4KUOK.js → te-analysis-WWX3Z6RP.js} +352 -52
  25. package/dist/te-audience-UXGHUVBB.js +599 -0
  26. package/dist/{te-common-WNCZB7R7.js → te-common-7XXH73MF.js} +5 -4
  27. package/dist/{te-community-JEEFXPB3.js → te-community-QKE67HR2.js} +5 -4
  28. package/dist/te-dataops-6W7NNYST.js +1841 -0
  29. package/dist/{te-engage-4XHCTS6I.js → te-engage-NCFAQFX3.js} +5 -4
  30. package/dist/{te-kb-B62KFP2A.js → te-kb-K5BQYUCM.js} +50 -26
  31. package/dist/{te-meta-EPZGQN56.js → te-meta-LJZBOSMO.js} +48 -24
  32. package/dist/{te-team-YY24VORI.js → te-team-DHK5R7MV.js} +5 -6
  33. package/package.json +3 -2
  34. package/skills/ae-agent/SKILL.md +103 -4
  35. package/skills/ae-analysis/SKILL.md +75 -21
  36. package/skills/ae-analysis/references/build_attribution_analysis_qp.md +62 -0
  37. package/skills/ae-analysis/references/build_cluster_definition.md +62 -0
  38. package/skills/ae-analysis/references/build_distribution_analysis_qp.md +67 -0
  39. package/skills/ae-analysis/references/build_event_analysis_qp.md +2 -0
  40. package/skills/ae-analysis/references/build_funnel_analysis_qp.md +2 -0
  41. package/skills/ae-analysis/references/build_heat_map_analysis_qp.md +54 -0
  42. package/skills/ae-analysis/references/build_interval_analysis_qp.md +60 -0
  43. package/skills/ae-analysis/references/build_path_analysis_qp.md +53 -0
  44. package/skills/ae-analysis/references/build_prop_analysis_qp.md +2 -0
  45. package/skills/ae-analysis/references/build_rank_list_analysis_qp.md +63 -0
  46. package/skills/ae-analysis/references/build_retention_analysis_qp.md +2 -0
  47. package/skills/ae-analysis/references/build_tag_definition.md +65 -0
  48. package/skills/ae-analysis/references/cancel_query.md +2 -3
  49. package/skills/ae-analysis/references/copy_dashboard.md +33 -0
  50. package/skills/ae-analysis/references/create_id_cluster.md +40 -0
  51. package/skills/ae-analysis/references/create_id_tag.md +39 -0
  52. package/skills/ae-analysis/references/delete_alert.md +27 -0
  53. package/skills/ae-analysis/references/delete_cluster.md +27 -0
  54. package/skills/ae-analysis/references/delete_dashboard.md +30 -0
  55. package/skills/ae-analysis/references/delete_metric.md +27 -0
  56. package/skills/ae-analysis/references/delete_report.md +27 -0
  57. package/skills/ae-analysis/references/delete_tag.md +27 -0
  58. package/skills/ae-analysis/references/drilldown_user_events.md +4 -4
  59. package/skills/ae-analysis/references/drilldown_users.md +3 -3
  60. package/skills/ae-analysis/references/freeze_dashboards.md +29 -0
  61. package/skills/ae-analysis/references/get_table_columns.md +11 -12
  62. package/skills/ae-analysis/references/list_cluster_members.md +4 -4
  63. package/skills/ae-analysis/references/list_clusters.md +5 -3
  64. package/skills/ae-analysis/references/list_dashboards.md +3 -3
  65. package/skills/ae-analysis/references/list_entities.md +1 -1
  66. package/skills/ae-analysis/references/list_events.md +7 -4
  67. package/skills/ae-analysis/references/list_metrics.md +5 -3
  68. package/skills/ae-analysis/references/list_properties.md +6 -4
  69. package/skills/ae-analysis/references/list_reports.md +3 -3
  70. package/skills/ae-analysis/references/list_spaces.md +27 -0
  71. package/skills/ae-analysis/references/list_tag_members.md +4 -4
  72. package/skills/ae-analysis/references/list_tags.md +4 -2
  73. package/skills/ae-analysis/references/move_dashboard.md +33 -0
  74. package/skills/ae-analysis/references/query_adhoc.md +2 -2
  75. package/skills/ae-analysis/references/query_bi_panel_data.md +2 -2
  76. package/skills/ae-analysis/references/query_dashboard_report_data.md +4 -4
  77. package/skills/ae-analysis/references/query_entity_details.md +4 -4
  78. package/skills/ae-analysis/references/query_event_details.md +3 -3
  79. package/skills/ae-analysis/references/query_report_data.md +37 -3
  80. package/skills/ae-analysis/references/update_id_cluster.md +36 -0
  81. package/skills/ae-analysis/references/update_id_tag.md +37 -0
  82. package/skills/ae-analysis/references/update_report.md +35 -0
  83. package/skills/ae-analysis-intent/SKILL.md +1 -1
  84. package/skills/ae-dataops/SKILL.md +54 -522
  85. package/skills/ae-dataops/references/dataops-flow-create.md +78 -75
  86. package/skills/ae-dataops/references/dataops-flow-monitor.md +58 -51
  87. package/skills/ae-dataops/references/dataops-integration.md +80 -41
  88. package/skills/ae-dataops/references/dataops-query.md +54 -53
  89. package/skills/ae-dataops/references/dataops-table.md +28 -59
  90. package/skills/ae-generate-tracking-code/SKILL.md +68 -31
  91. package/skills/ae-generate-tracking-code/references/snippet-delivery.md +26 -1
  92. package/skills/ae-generate-tracking-code/references/te-api.md +47 -164
  93. package/skills/ae-generate-tracking-plan/SKILL.md +109 -32
  94. package/skills/ae-generate-tracking-plan/references/te-api.md +57 -27
  95. package/skills/ae-metadata/SKILL.md +90 -0
  96. package/skills/ae-metadata/references/metadata_data_table_csv_delete.md +15 -0
  97. package/skills/ae-metadata/references/metadata_data_table_csv_write.md +29 -0
  98. package/skills/ae-metadata/references/metadata_data_table_download.md +17 -0
  99. package/skills/ae-metadata/references/metadata_data_table_get.md +24 -0
  100. package/skills/ae-metadata/references/metadata_data_table_list.md +27 -0
  101. package/skills/ae-metadata/references/metadata_data_table_property_bindings_update.md +17 -0
  102. package/skills/ae-metadata/references/metadata_data_table_sql_delete.md +15 -0
  103. package/skills/ae-metadata/references/metadata_data_table_sql_write.md +31 -0
  104. package/skills/ae-metadata/references/metadata_event_get.md +52 -0
  105. package/skills/ae-metadata/references/metadata_input_file_upload.md +29 -0
  106. package/skills/ae-metadata/references/metadata_property_dimension_table_bind_existing.md +27 -0
  107. package/skills/ae-metadata/references/metadata_property_dimension_table_create_and_bind_csv.md +30 -0
  108. package/skills/ae-metadata/references/metadata_property_get.md +54 -0
  109. package/dist/te-audience-KMKYI2YJ.js +0 -400
  110. package/dist/te-dataops-GD3XBYCS.js +0 -1830
package/dist/index.js CHANGED
@@ -1,28 +1,32 @@
1
1
  import {
2
2
  TeAgentApiError,
3
3
  TeAgentCredentialsError
4
- } from "./chunk-I5CRVM2S.js";
4
+ } from "./chunk-H52CSLJW.js";
5
5
  import {
6
6
  printError,
7
7
  printOutput
8
- } from "./chunk-2DUEAXV3.js";
8
+ } from "./chunk-YACCPUNQ.js";
9
9
  import {
10
- httpGet
11
- } from "./chunk-BJX3GXWC.js";
10
+ executeCapability,
11
+ uploadInputFileBytes
12
+ } from "./chunk-4EUZRJPO.js";
12
13
  import {
13
14
  PermissionError
14
15
  } from "./chunk-NOO24N7W.js";
16
+ import {
17
+ clearCliToken,
18
+ getCliToken
19
+ } from "./chunk-FPE5LGVU.js";
15
20
  import {
16
21
  SecureStoreAuthError,
17
- getToken,
18
22
  resolveHost
19
- } from "./chunk-RSHMZ3LG.js";
23
+ } from "./chunk-U6QPKCN3.js";
20
24
  import {
21
25
  getActiveHost,
22
26
  getConfigDir,
23
27
  logger,
24
28
  safeJsonParse
25
- } from "./chunk-6W4QOZAL.js";
29
+ } from "./chunk-WPXHCP4A.js";
26
30
 
27
31
  // src/index.ts
28
32
  import { Command as CommanderCommand } from "commander";
@@ -33,13 +37,13 @@ import * as readline from "readline";
33
37
  async function runCommand(cmd, opts, globalOpts) {
34
38
  try {
35
39
  const ctx = createRuntimeContext(cmd, opts, globalOpts);
36
- const cmdName = `${cmd.service} ${cmd.command}`;
40
+ const cmdName = cmd.resource ? `${cmd.service} ${cmd.resource} ${cmd.command}` : `${cmd.service} ${cmd.command}`;
37
41
  logger.command(cmdName, opts);
38
42
  for (const flag of cmd.flags) {
39
43
  if (flag.required) {
40
44
  const val = opts[camelCase(flag.name)];
41
45
  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>`);
46
+ printError("validation", `Missing required flag: --${flag.name}`, `Usage: ae-cli ${cmdName} --${flag.name} <value>`);
43
47
  process.exit(1);
44
48
  }
45
49
  }
@@ -71,7 +75,7 @@ async function runCommand(cmd, opts, globalOpts) {
71
75
  return;
72
76
  }
73
77
  if (cmd.risk === "write" && !globalOpts.yes) {
74
- const confirmed = await confirm(`This is a write operation (${cmd.service} ${cmd.command}). Continue?`);
78
+ const confirmed = await confirm(`This is a write operation (${cmdName}). Continue?`);
75
79
  if (!confirmed) {
76
80
  process.stderr.write("Aborted.\n");
77
81
  process.exit(0);
@@ -113,7 +117,7 @@ function createRuntimeContext(cmd, opts, globalOpts) {
113
117
  let _clientModule = null;
114
118
  async function getClient() {
115
119
  if (!_clientModule) {
116
- _clientModule = await import("./client-2UJ63MVQ.js");
120
+ _clientModule = await import("./client-VTJMUZ4O.js");
117
121
  }
118
122
  return _clientModule;
119
123
  }
@@ -125,6 +129,11 @@ function createRuntimeContext(cmd, opts, globalOpts) {
125
129
  const val = opts[camelCase(name)];
126
130
  return val !== void 0 ? Number(val) : 0;
127
131
  },
132
+ optionalNum(name) {
133
+ const val = opts[camelCase(name)];
134
+ if (val === void 0 || val === null || val === "") return void 0;
135
+ return Number(val);
136
+ },
128
137
  bool(name) {
129
138
  return Boolean(opts[camelCase(name)]);
130
139
  },
@@ -156,8 +165,8 @@ function createRuntimeContext(cmd, opts, globalOpts) {
156
165
  return client.queryReportData(projectId, reportId, qp, eventModel, options, ctx.host());
157
166
  },
158
167
  async token() {
159
- const { getToken: getToken2 } = await import("./auth-DYC2BGLM.js");
160
- return getToken2(ctx.host());
168
+ const { getToken } = await import("./auth-I2G7OAU2.js");
169
+ return getToken(ctx.host());
161
170
  },
162
171
  host() {
163
172
  if (globalOpts.host) return globalOpts.host;
@@ -180,10 +189,10 @@ function camelCase(str) {
180
189
  }
181
190
  async function confirm(message) {
182
191
  const rl = readline.createInterface({ input: process.stdin, output: process.stderr });
183
- return new Promise((resolve2) => {
192
+ return new Promise((resolve3) => {
184
193
  rl.question(`${message} [y/N] `, (answer) => {
185
194
  rl.close();
186
- resolve2(answer.toLowerCase() === "y" || answer.toLowerCase() === "yes");
195
+ resolve3(answer.toLowerCase() === "y" || answer.toLowerCase() === "yes");
187
196
  });
188
197
  });
189
198
  }
@@ -202,7 +211,15 @@ function registerCommands(program2, commands) {
202
211
  serviceCmd = program2.command(service).description(`${service} domain commands`);
203
212
  }
204
213
  for (const cmd of cmds) {
205
- const sub = serviceCmd.command(cmd.command).description(cmd.description);
214
+ let parent = serviceCmd;
215
+ if (cmd.resource) {
216
+ let resourceCmd = serviceCmd.commands.find((c) => c.name() === cmd.resource);
217
+ if (!resourceCmd) {
218
+ resourceCmd = serviceCmd.command(cmd.resource).description(`${cmd.resource} commands`);
219
+ }
220
+ parent = resourceCmd;
221
+ }
222
+ const sub = parent.command(cmd.command).description(cmd.description);
206
223
  for (const flag of cmd.flags) {
207
224
  const flagStr = buildFlagString(flag);
208
225
  if (flag.type === "boolean") {
@@ -398,7 +415,7 @@ function notifyIfUpdateAvailable(pkg2) {
398
415
 
399
416
  // src/commands/tracking/plan.ts
400
417
  import { readFile, writeFile, cp } from "fs/promises";
401
- import path3, { resolve } from "path";
418
+ import path3, { resolve as resolve2 } from "path";
402
419
 
403
420
  // src/tracking/xlsx/write.ts
404
421
  import ExcelJS from "exceljs";
@@ -1011,30 +1028,13 @@ async function writeDraftXlsx(d, outPath, locale = "zh") {
1011
1028
  await workbook.xlsx.writeFile(outPath);
1012
1029
  }
1013
1030
 
1014
- // src/tracking/i18n/ae-locale.ts
1015
- function aeLocaleToCli(raw) {
1016
- const normalized = raw.trim().replace("-", "_").toLowerCase();
1017
- if (normalized.startsWith("zh")) return "zh";
1018
- if (normalized.startsWith("en")) return "en";
1019
- if (normalized.startsWith("ja")) return "ja";
1020
- if (normalized.startsWith("ko")) return "ko";
1021
- return null;
1022
- }
1023
- function cliLocaleToAE(locale) {
1024
- switch (locale) {
1025
- case "zh":
1026
- return "zh_CN";
1027
- case "en":
1028
- return "en_US";
1029
- case "ja":
1030
- return "ja_JP";
1031
- case "ko":
1032
- return "ko_KR";
1033
- }
1034
- }
1035
-
1036
1031
  // src/core/tracking-client.ts
1037
1032
  var DEBUG_BASE = "/v1/ta/bury/manage/debug";
1033
+ var TRACK_CAPABILITY_DOMAIN = "analysis";
1034
+ var TRACK_PROGRAM_QUERY = "track.program.query";
1035
+ var TRACK_PROGRAM_DELETE = "track.program.delete";
1036
+ var TRACK_PROGRAM_EXCEL_SAVE = "track.program.excel_save";
1037
+ var TRACK_PROGRAM_XLSX_PURPOSE = "track.program.xlsx";
1038
1038
  function buildUrl(host, modulePath, params = {}) {
1039
1039
  const base = host.replace(/\/$/, "");
1040
1040
  const p = modulePath.startsWith("/") ? modulePath : `/${modulePath}`;
@@ -1044,89 +1044,185 @@ function buildUrl(host, modulePath, params = {}) {
1044
1044
  }
1045
1045
  return url.toString();
1046
1046
  }
1047
- function extractLangFromConfig(data) {
1047
+ function record(value) {
1048
+ return value && typeof value === "object" && !Array.isArray(value) ? value : null;
1049
+ }
1050
+ function pick(source, camelKey, snakeKey) {
1051
+ return source[camelKey] ?? source[snakeKey];
1052
+ }
1053
+ function stringArray(value) {
1054
+ return Array.isArray(value) ? value.filter((item) => typeof item === "string") : [];
1055
+ }
1056
+ function mapArray(value, mapper) {
1057
+ return Array.isArray(value) ? value.map(record).filter((item) => item !== null).map(mapper) : [];
1058
+ }
1059
+ function normalizeProperty(value) {
1060
+ return {
1061
+ name: value.name,
1062
+ displayName: pick(value, "displayName", "display_name"),
1063
+ type: value.type,
1064
+ desc: value.desc,
1065
+ createTime: pick(value, "createTime", "create_time"),
1066
+ creator: value.creator,
1067
+ lastUpdateAuth: pick(value, "lastUpdateAuth", "last_update_auth"),
1068
+ lastUpdateTime: pick(value, "lastUpdateTime", "last_update_time"),
1069
+ hasReported: pick(value, "hasReported", "has_reported")
1070
+ };
1071
+ }
1072
+ function normalizeUserProperty(value) {
1073
+ return {
1074
+ ...normalizeProperty(value),
1075
+ propTag: pick(value, "propTag", "prop_tag"),
1076
+ updateType: pick(value, "updateType", "update_type") ?? "user_set",
1077
+ updateTypeName: pick(value, "updateTypeName", "update_type_name")
1078
+ };
1079
+ }
1080
+ function normalizeEvent(value) {
1081
+ return {
1082
+ eventName: pick(value, "eventName", "event_name") ?? "",
1083
+ displayName: pick(value, "displayName", "display_name"),
1084
+ eventDesc: pick(value, "eventDesc", "event_desc"),
1085
+ eventTag: pick(value, "eventTag", "event_tag"),
1086
+ createTime: pick(value, "createTime", "create_time"),
1087
+ creator: value.creator,
1088
+ lastUpdateAuth: pick(value, "lastUpdateAuth", "last_update_auth"),
1089
+ lastUpdateTime: pick(value, "lastUpdateTime", "last_update_time"),
1090
+ hasReported: pick(value, "hasReported", "has_reported"),
1091
+ props: stringArray(value.props),
1092
+ propInfosOnEvent: pick(value, "propInfosOnEvent", "prop_infos_on_event")
1093
+ };
1094
+ }
1095
+ function normalizeProgram(value) {
1096
+ const data = record(value);
1048
1097
  if (!data) return null;
1049
- const raw = typeof data.lang === "string" && data.lang || typeof data.umi_locale === "string" && data.umi_locale || typeof data.locale === "string" && data.locale || null;
1050
- return raw ? aeLocaleToCli(raw) : null;
1098
+ return {
1099
+ projectId: pick(data, "projectId", "project_id") ?? 0,
1100
+ createTime: pick(data, "createTime", "create_time"),
1101
+ events: mapArray(data.events, normalizeEvent),
1102
+ eventProps: mapArray(pick(data, "eventProps", "event_props"), normalizeProperty),
1103
+ commonEventProps: mapArray(pick(data, "commonEventProps", "common_event_props"), normalizeProperty),
1104
+ userProps: mapArray(pick(data, "userProps", "user_props"), normalizeUserProperty)
1105
+ };
1106
+ }
1107
+ function normalizeUploadError(value) {
1108
+ return {
1109
+ errorType: pick(value, "errorType", "error_type") ?? "",
1110
+ errorTypeDesc: pick(value, "errorTypeDesc", "error_type_desc") ?? "",
1111
+ cellName: pick(value, "cellName", "cell_name") ?? "",
1112
+ row: Number(value.row ?? 0),
1113
+ value: String(value.value ?? "")
1114
+ };
1115
+ }
1116
+ function normalizeUploadErrorMap(value) {
1117
+ const data = record(value);
1118
+ if (!data) return void 0;
1119
+ const result = {};
1120
+ for (const [key, items] of Object.entries(data)) {
1121
+ result[key] = mapArray(items, normalizeUploadError);
1122
+ }
1123
+ return result;
1124
+ }
1125
+ function normalizeUploadResponse(value) {
1126
+ const data = record(value);
1127
+ if (!data) return { return_code: 0, return_message: "success" };
1128
+ const responseData = record(data.data);
1129
+ const uploadErrors = record(pick(data, "uploadErrors", "upload_errors")) ?? record(pick(responseData ?? {}, "uploadErrors", "upload_errors"));
1130
+ const errorSource = uploadErrors ?? responseData ?? data;
1131
+ const eventErrorMap = normalizeUploadErrorMap(pick(errorSource, "eventErrorMap", "event_error_map"));
1132
+ const userErrorMap = normalizeUploadErrorMap(pick(errorSource, "userErrorMap", "user_error_map"));
1133
+ const hasErrors = Boolean(
1134
+ eventErrorMap && Object.keys(eventErrorMap).length > 0 || userErrorMap && Object.keys(userErrorMap).length > 0
1135
+ );
1136
+ return {
1137
+ return_code: typeof data.return_code === "number" ? data.return_code : 0,
1138
+ return_message: typeof data.return_message === "string" ? data.return_message : hasErrors ? "validation errors" : "success",
1139
+ data: hasErrors ? { eventErrorMap, userErrorMap } : void 0
1140
+ };
1051
1141
  }
1052
1142
  var TrackingClient = class {
1053
- constructor(host, token) {
1143
+ constructor(host, cliToken) {
1054
1144
  this.host = host;
1055
- this.token = token;
1145
+ this.cliToken = cliToken;
1056
1146
  }
1057
1147
  host;
1058
- token;
1059
- async resolveToken() {
1060
- return this.token ?? getToken(this.host);
1148
+ cliToken;
1149
+ async resolveCliToken() {
1150
+ return this.cliToken ?? getCliToken(this.host);
1151
+ }
1152
+ async requestJson(modulePath, params = {}, body, method = body === void 0 ? "GET" : "POST", retry = true) {
1153
+ const token = await this.resolveCliToken();
1154
+ const url = buildUrl(this.host, modulePath, params);
1155
+ const headers = {
1156
+ "cli-token": token,
1157
+ accept: "application/json"
1158
+ };
1159
+ const init = { method, headers };
1160
+ if (body !== void 0 && method !== "GET") {
1161
+ headers["content-type"] = "application/json";
1162
+ init.body = JSON.stringify(body);
1163
+ }
1164
+ const resp = await fetch(url, init);
1165
+ const env = safeJsonParse(await resp.text());
1166
+ logger.api(method, url, resp.status, body, env);
1167
+ if (resp.status === 401 && retry) {
1168
+ clearCliToken(this.host);
1169
+ this.cliToken = await getCliToken(this.host);
1170
+ return this.requestJson(modulePath, params, body, method, false);
1171
+ }
1172
+ if (resp.status === 403) {
1173
+ throw new Error(env?.return_message || "Permission denied");
1174
+ }
1175
+ if (!resp.ok) {
1176
+ throw new Error(`AE API HTTP error: ${resp.status} ${resp.statusText}`);
1177
+ }
1178
+ if (env?.return_code === -1001 && retry) {
1179
+ clearCliToken(this.host);
1180
+ this.cliToken = await getCliToken(this.host);
1181
+ return this.requestJson(modulePath, params, body, method, false);
1182
+ }
1183
+ if (env?.return_code !== 0 && env?.return_code !== void 0) {
1184
+ throw new Error(env.return_message || `AE API error (code: ${env.return_code})`);
1185
+ }
1186
+ return env?.data;
1061
1187
  }
1062
1188
  async getProgram(projectId) {
1063
- const data = await httpGet(
1064
- "/v1/ta/bury/manage/program/query",
1065
- { projectId, "@t": Date.now() },
1066
- this.host
1067
- );
1068
- return data ?? null;
1189
+ const data = await executeCapability(this.host, TRACK_CAPABILITY_DOMAIN, TRACK_PROGRAM_QUERY, {
1190
+ project_id: projectId
1191
+ });
1192
+ return normalizeProgram(data);
1069
1193
  }
1070
1194
  async deleteProgram(projectId) {
1071
- const token = await this.resolveToken();
1072
- const url = buildUrl(this.host, "/v1/ta/bury/manage/program/delete", {
1073
- projectId,
1074
- "@t": Date.now()
1195
+ await executeCapability(this.host, TRACK_CAPABILITY_DOMAIN, TRACK_PROGRAM_DELETE, {
1196
+ project_id: projectId
1075
1197
  });
1076
- const resp = await fetch(url, {
1077
- method: "GET",
1078
- headers: {
1079
- authorization: `bearer ${token}`,
1080
- accept: "application/json"
1081
- }
1082
- });
1083
- const env = safeJsonParse(await resp.text());
1084
- if (env.return_code !== 0) {
1085
- throw new Error(env.return_message || `AE API error (code: ${env.return_code})`);
1086
- }
1087
- return { return_code: env.return_code, return_message: env.return_message };
1198
+ return { return_code: 0, return_message: "success" };
1088
1199
  }
1089
1200
  async uploadProgramExcel(args) {
1090
- const token = await this.resolveToken();
1091
- const form = new FormData();
1092
- form.append(
1093
- "file",
1094
- new Blob([new Uint8Array(args.file)], {
1095
- type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
1096
- }),
1097
- args.filename
1201
+ const inputFile = await uploadInputFileBytes(
1202
+ this.host,
1203
+ TRACK_CAPABILITY_DOMAIN,
1204
+ args.projectId,
1205
+ TRACK_PROGRAM_XLSX_PURPOSE,
1206
+ args.file,
1207
+ args.filename,
1208
+ "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
1098
1209
  );
1099
- form.append("projectId", String(args.projectId));
1100
- form.append("access_token", token);
1101
- const url = buildUrl(this.host, "/v1/ta/bury/manage/program/excel-save");
1102
- const resp = await fetch(url, { method: "POST", body: form });
1103
- const env = safeJsonParse(await resp.text());
1210
+ const inputFileId = inputFile?.input_file_id ?? inputFile?.inputFileId ?? inputFile?.id;
1211
+ if (!inputFileId) {
1212
+ throw new Error("Capability gateway input-file upload did not return input_file_id");
1213
+ }
1214
+ const data = await executeCapability(this.host, TRACK_CAPABILITY_DOMAIN, TRACK_PROGRAM_EXCEL_SAVE, {
1215
+ project_id: args.projectId,
1216
+ input_file_id: inputFileId
1217
+ });
1218
+ const env = normalizeUploadResponse(data);
1104
1219
  if (env.return_code !== 0 && env.return_code !== void 0 && !env.data?.eventErrorMap && !env.data?.userErrorMap) {
1105
1220
  logger.error(`Upload failed: ${env.return_message || `AE API error (code: ${env.return_code})`}`);
1106
1221
  }
1107
1222
  return env;
1108
1223
  }
1109
- async getUserAutoConfig() {
1110
- const data = await httpGet(
1111
- "/v1/ta/auto/config/getUserAutoConfig",
1112
- { "@t": Date.now() },
1113
- this.host
1114
- );
1115
- if (data && typeof data === "object") {
1116
- return data;
1117
- }
1118
- return null;
1119
- }
1120
- async getServerLang() {
1121
- const config = await this.getUserAutoConfig();
1122
- return extractLangFromConfig(config);
1123
- }
1124
- /** lang format: zh_CN, en_US, ja_JP, ko_KR */
1125
- async saveUserAutoConfig(langCode) {
1126
- await httpGet("/v1/ta/auto/config/getUserAutoConfig", { "@t": Date.now(), lang: langCode }, this.host);
1127
- }
1128
1224
  async debugGet(path5, params) {
1129
- const data = await httpGet(`${DEBUG_BASE}${path5}`, { ...params, "@t": Date.now() }, this.host);
1225
+ const data = await this.requestJson(`${DEBUG_BASE}${path5}`, { ...params, "@t": Date.now() });
1130
1226
  return data;
1131
1227
  }
1132
1228
  async listDevice(projectId) {
@@ -1152,8 +1248,7 @@ var TrackingClient = class {
1152
1248
  }
1153
1249
  };
1154
1250
  async function createTrackingClient(host) {
1155
- const token = await getToken(host);
1156
- return new TrackingClient(host, token);
1251
+ return new TrackingClient(host);
1157
1252
  }
1158
1253
 
1159
1254
  // src/tracking/te-plan/fetch.ts
@@ -1741,23 +1836,70 @@ function formatConflictReport(result, existingSummary) {
1741
1836
  }
1742
1837
 
1743
1838
  // src/commands/tracking/plan.ts
1839
+ import { existsSync as existsSync5 } from "fs";
1840
+
1841
+ // src/tracking/templates.ts
1744
1842
  import { readdir } from "fs/promises";
1745
- import { existsSync as existsSync4 } from "fs";
1843
+ import { existsSync as existsSync3 } from "fs";
1844
+ import { resolve } from "path";
1845
+ function getTemplateDirs() {
1846
+ return [
1847
+ resolve(getPackageRoot(), "tracking-plan-template"),
1848
+ resolve(getConfigDir(), "templates")
1849
+ ];
1850
+ }
1851
+ async function listTrackingTemplates() {
1852
+ const found = [];
1853
+ for (const dir of getTemplateDirs()) {
1854
+ if (!existsSync3(dir)) continue;
1855
+ let entries = [];
1856
+ try {
1857
+ entries = await readdir(dir);
1858
+ } catch {
1859
+ continue;
1860
+ }
1861
+ for (const f of entries) {
1862
+ if (!f.endsWith(".xlsx")) continue;
1863
+ const base = f.replace(/\.xlsx$/i, "");
1864
+ const mdPath = resolve(dir, base + ".md");
1865
+ const hasMd = existsSync3(mdPath);
1866
+ found.push({
1867
+ path: hasMd ? mdPath : resolve(dir, f),
1868
+ name: base,
1869
+ hasMd
1870
+ });
1871
+ }
1872
+ }
1873
+ return found;
1874
+ }
1875
+ async function resolveTrackingTemplateByName(name) {
1876
+ const normalized = name.trim().replace(/\.(md|xlsx)$/i, "");
1877
+ const templates = await listTrackingTemplates();
1878
+ const template = templates.find((item) => item.name === normalized);
1879
+ if (!template) {
1880
+ const available = templates.map((item) => item.name).join(", ");
1881
+ throw new Error(
1882
+ available ? `Template not found: ${name}. Available templates: ${available}` : `Template not found: ${name}. No tracking plan templates are available.`
1883
+ );
1884
+ }
1885
+ return template;
1886
+ }
1746
1887
 
1747
1888
  // src/commands/tracking/shared.ts
1748
- import { existsSync as existsSync3, statSync } from "fs";
1889
+ import { existsSync as existsSync4, statSync } from "fs";
1749
1890
  var HOST_OPTION_DESC = "Override active AE host URL";
1750
1891
  function resolveTrackingHost(program2, opts) {
1751
1892
  const root = program2.root ?? program2;
1752
1893
  const globalHost = root.opts()?.host;
1753
- const host = resolveHost(opts.host || globalHost);
1894
+ const explicitHost = opts.host || globalHost;
1895
+ const host = resolveHost(explicitHost);
1754
1896
  if (!host) {
1755
1897
  throw new Error("No active AE host configured. Run: ae-cli auth login");
1756
1898
  }
1757
1899
  return host;
1758
1900
  }
1759
1901
  function isExistingDirectory(path5) {
1760
- if (!existsSync3(path5)) return false;
1902
+ if (!existsSync4(path5)) return false;
1761
1903
  try {
1762
1904
  return statSync(path5).isDirectory();
1763
1905
  } catch {
@@ -1773,7 +1915,7 @@ function assertOutputFilePath(path5, optionName = "--out") {
1773
1915
  }
1774
1916
  function assertInputFilePath(path5, optionName = "--in") {
1775
1917
  const trimmed = path5.trim();
1776
- if (!existsSync3(trimmed)) {
1918
+ if (!existsSync4(trimmed)) {
1777
1919
  console.error(t("error.input_path_not_found", { path: trimmed, option: optionName }));
1778
1920
  process.exit(1);
1779
1921
  }
@@ -1785,10 +1927,6 @@ function assertInputFilePath(path5, optionName = "--in") {
1785
1927
 
1786
1928
  // src/commands/tracking/plan.ts
1787
1929
  var MAX_FIX_RETRIES = 3;
1788
- var TEMPLATE_DIRS = [
1789
- resolve(getPackageRoot(), "tracking-plan-template"),
1790
- resolve(getConfigDir(), "templates")
1791
- ];
1792
1930
  function registerPlan(cmd, rootProgram) {
1793
1931
  cmd.description("manage AE tracking plans");
1794
1932
  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) => {
@@ -1866,27 +2004,12 @@ function registerPlan(cmd, rootProgram) {
1866
2004
  }
1867
2005
  }
1868
2006
  });
1869
- 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) => {
2007
+ 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) => {
1870
2008
  assertInputFilePath(opts.draft, "--draft");
1871
2009
  assertInputFilePath(opts.xlsx, "--xlsx");
1872
2010
  const host = resolveTrackingHost(rootProgram, opts);
1873
2011
  let client = await createTrackingClient(host);
1874
2012
  const draftPre = JSON.parse(await readFile(opts.draft, "utf8"));
1875
- const xlsxLocale = opts.lang ?? draftPre.meta.lang ?? detectCliLocale();
1876
- const aeLocale = await client.getServerLang();
1877
- if (aeLocale && aeLocale !== xlsxLocale) {
1878
- console.log("\n" + t("plan.ae_lang_mismatch", { aeLang: aeLocale, xlsxLang: xlsxLocale }));
1879
- if (opts.switchLang) {
1880
- const aeLangCode = cliLocaleToAE(xlsxLocale);
1881
- await client.saveUserAutoConfig(aeLangCode);
1882
- console.log(t("plan.ae_lang_switched", { aeLang: aeLangCode }));
1883
- await new Promise((r) => setTimeout(r, 2e3));
1884
- client = await createTrackingClient(host);
1885
- } else {
1886
- console.log(t("plan.ae_lang_switch_hint"));
1887
- process.exit(13);
1888
- }
1889
- }
1890
2013
  if (!opts.replace) {
1891
2014
  console.log(t("plan.checking_conflicts"));
1892
2015
  try {
@@ -1926,7 +2049,7 @@ function registerPlan(cmd, rootProgram) {
1926
2049
  if (opts.replace) {
1927
2050
  const del = await client.deleteProgram(opts.project);
1928
2051
  console.log(t("plan.deleted_existing_plan", { message: del.return_message }));
1929
- await new Promise((resolve2) => setTimeout(resolve2, 5e3));
2052
+ await new Promise((resolve3) => setTimeout(resolve3, 5e3));
1930
2053
  }
1931
2054
  let retryCount = 0;
1932
2055
  let draft = JSON.parse(await readFile(opts.draft, "utf8"));
@@ -1974,8 +2097,8 @@ function registerPlan(cmd, rootProgram) {
1974
2097
  const msg = lastRes?.return_message ?? "";
1975
2098
  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");
1976
2099
  if (lastRes && lastRes.return_code !== 0 && isLangMismatch) {
1977
- const xlsxLocale2 = opts.lang ?? draft.meta.lang ?? detectCliLocale();
1978
- console.log("\n" + t("plan.language_mismatch_hint", { locale: xlsxLocale2 }));
2100
+ const xlsxLocale = opts.lang ?? draft.meta.lang ?? detectCliLocale();
2101
+ console.log("\n" + t("plan.language_mismatch_hint", { locale: xlsxLocale }));
1979
2102
  }
1980
2103
  });
1981
2104
  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) => {
@@ -1987,12 +2110,12 @@ function registerPlan(cmd, rootProgram) {
1987
2110
  await writeFile(opts.out, s, "utf8");
1988
2111
  } else process.stdout.write(s);
1989
2112
  });
1990
- 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) => {
2113
+ 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) => {
1991
2114
  assertInputFilePath(opts.draft, "--draft");
1992
2115
  assertInputFilePath(opts.xlsx, "--xlsx");
1993
2116
  const stamp = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
1994
- const dest = resolve(opts.plansDir, `${stamp}-${opts.name}.xlsx`);
1995
- if (existsSync4(dest)) {
2117
+ const dest = resolve2(opts.plansDir, `${stamp}-${opts.name}.xlsx`);
2118
+ if (existsSync5(dest)) {
1996
2119
  console.error(t("plan.archive_exists", { path: dest }));
1997
2120
  console.error(t("plan.remove_or_rename"));
1998
2121
  return;
@@ -2020,30 +2143,14 @@ function registerPlan(cmd, rootProgram) {
2020
2143
  const res = await client.deleteProgram(opts.project);
2021
2144
  console.log(JSON.stringify(res, null, 2));
2022
2145
  });
2023
- cmd.command("list-templates").description("List bundled and user tracking plan templates (xlsx/md)").action(async () => {
2024
- const found = [];
2025
- for (const dir of TEMPLATE_DIRS) {
2026
- if (!existsSync4(dir)) continue;
2027
- let entries = [];
2028
- try {
2029
- entries = await readdir(dir);
2030
- } catch {
2031
- continue;
2032
- }
2033
- for (const f of entries) {
2034
- if (!f.endsWith(".xlsx")) continue;
2035
- const base = f.replace(/\.xlsx$/i, "");
2036
- const mdPath = resolve(dir, base + ".md");
2037
- const hasMd = existsSync4(mdPath);
2038
- found.push({
2039
- path: hasMd ? mdPath : resolve(dir, f),
2040
- name: base,
2041
- hasMd
2042
- });
2043
- }
2146
+ 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) => {
2147
+ const found = await listTrackingTemplates();
2148
+ if (opts.json) {
2149
+ console.log(JSON.stringify(found, null, 2));
2150
+ return;
2044
2151
  }
2045
2152
  if (found.length === 0) {
2046
- console.log(t("plan.no_templates_found", { dirs: TEMPLATE_DIRS.join(", ") }));
2153
+ console.log(t("plan.no_templates_found", { dirs: getTemplateDirs().join(", ") }));
2047
2154
  return;
2048
2155
  }
2049
2156
  console.log(t("plan.templates_found", { count: found.length }) + "\n");
@@ -2737,10 +2844,17 @@ function inferSdkMode(events) {
2737
2844
  }
2738
2845
  function registerCode(cmd) {
2739
2846
  cmd.description("tooling for ae-generate-tracking-code skill");
2740
- 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) => {
2741
- assertInputFilePath(opts.template, "--template");
2847
+ 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) => {
2848
+ if (!opts.template && !opts.templateName) {
2849
+ throw new Error("Either --template or --template-name is required");
2850
+ }
2851
+ if (opts.template && opts.templateName) {
2852
+ throw new Error("Use only one of --template or --template-name");
2853
+ }
2742
2854
  assertOutputFilePath(opts.out, "--out");
2743
- const draft = opts.template.endsWith(".md") ? await readTemplateMd(opts.template) : await readTemplateXlsx(opts.template);
2855
+ const templatePath = opts.templateName ? (await resolveTrackingTemplateByName(opts.templateName)).path : opts.template;
2856
+ assertInputFilePath(templatePath, opts.templateName ? "--template-name" : "--template");
2857
+ const draft = templatePath.endsWith(".md") ? await readTemplateMd(templatePath) : await readTemplateXlsx(templatePath);
2744
2858
  const inferredMode = inferSdkMode(draft.events);
2745
2859
  if (inferredMode) {
2746
2860
  draft.meta.sdk_integration_mode = inferredMode;
@@ -2798,12 +2912,12 @@ function registerCode(cmd) {
2798
2912
  }
2799
2913
 
2800
2914
  // src/tracking/wiki-query/query.ts
2801
- import { readFileSync as readFileSync3, existsSync as existsSync5 } from "fs";
2915
+ import { readFileSync as readFileSync3, existsSync as existsSync6 } from "fs";
2802
2916
  import { join as join4 } from "path";
2803
2917
  var WIKI_ROOT = join4(getPackageRoot(), "wiki/te-docs");
2804
2918
  function searchIndex(keyword) {
2805
2919
  const indexPath = join4(WIKI_ROOT, "index.md");
2806
- if (!existsSync5(indexPath)) return [];
2920
+ if (!existsSync6(indexPath)) return [];
2807
2921
  const lines = readFileSync3(indexPath, "utf8").split("\n");
2808
2922
  const kw = keyword.toLowerCase();
2809
2923
  const hits = [];
@@ -2835,36 +2949,34 @@ function registerWiki(cmd) {
2835
2949
  // src/commands/tracking/lang.ts
2836
2950
  var SUPPORTED = ["zh", "en", "ja", "ko"];
2837
2951
  var SUPPORTED_LABELS = {
2838
- zh: "\u4E2D\u6587 (Chinese)",
2952
+ zh: "Chinese",
2839
2953
  en: "English",
2840
- ja: "\u65E5\u672C\u8A9E (Japanese)",
2841
- ko: "\uD55C\uAD6D\uC5B4 (Korean)"
2954
+ ja: "Japanese",
2955
+ ko: "Korean"
2842
2956
  };
2843
- function registerLang(cmd, rootProgram) {
2844
- cmd.description("manage AE server language for tracking commands");
2845
- 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) => {
2957
+ function registerLang(cmd, _rootProgram) {
2958
+ cmd.description("manage local language hints for tracking commands");
2959
+ cmd.command("status").description("show local language settings for tracking commands").action(() => {
2960
+ const aeLang = process.env.AE_LANG?.trim() || "(unset)";
2961
+ const lang = process.env.LANG?.trim() || "(unset)";
2962
+ console.log("CLI language settings:");
2963
+ console.log(`- AE_LANG: ${aeLang}`);
2964
+ console.log(`- LANG: ${lang}`);
2965
+ console.log(`- resolved: ${detectCliLocale()}`);
2966
+ });
2967
+ cmd.command("set").description("print the AE_LANG value to use for subsequent commands").argument("<locale>", "language code: zh / en / ja / ko").action((locale) => {
2846
2968
  const normalized = locale.trim().toLowerCase();
2847
2969
  if (!SUPPORTED.includes(normalized)) {
2848
2970
  console.error(`Unsupported language: "${locale}"`);
2849
2971
  console.error("Supported languages:");
2850
2972
  for (const code of SUPPORTED) {
2851
- console.error(` ${code} \u2014 ${SUPPORTED_LABELS[code]}`);
2973
+ console.error(` ${code} - ${SUPPORTED_LABELS[code]}`);
2852
2974
  }
2853
2975
  process.exit(1);
2854
2976
  }
2855
- const host = resolveTrackingHost(rootProgram, opts);
2856
- const client = await createTrackingClient(host);
2857
- const aeCode = cliLocaleToAE(normalized);
2858
- await client.saveUserAutoConfig(aeCode);
2859
- process.stderr.write(`[ae-cli] Server language saved: ${aeCode}
2860
- `);
2861
- const config = await client.getUserAutoConfig();
2862
- if (config) {
2863
- const serverLang = config.lang ?? config.umi_locale ?? config.locale;
2864
- console.log(`Server response: ${JSON.stringify({ lang: serverLang })}`);
2865
- } else {
2866
- console.log("Server response: (empty)");
2867
- }
2977
+ console.log("Use this environment variable for subsequent commands:");
2978
+ console.log(`export AE_LANG=${normalized}`);
2979
+ console.log(`AE_LANG=${normalized} ae-cli tracking plan draft --in .ae-cli/draft.json --out .ae-cli/draft.xlsx`);
2868
2980
  });
2869
2981
  }
2870
2982
 
@@ -2886,88 +2998,93 @@ program.name("ae-cli").version(version).description("CLI tool for ThinkingAI (AE
2886
2998
  async function loadCommands() {
2887
2999
  const commands = [];
2888
3000
  try {
2889
- const teAnalysis = await import("./te-analysis-VAR4KUOK.js");
3001
+ const teAnalysis = await import("./te-analysis-WWX3Z6RP.js");
2890
3002
  commands.push(...teAnalysis.default);
2891
3003
  } catch {
2892
3004
  }
2893
3005
  try {
2894
- const teAudience = await import("./te-audience-KMKYI2YJ.js");
3006
+ const teAudience = await import("./te-audience-UXGHUVBB.js");
2895
3007
  commands.push(...teAudience.default);
2896
3008
  } catch {
2897
3009
  }
2898
3010
  try {
2899
- const teMeta = await import("./te-meta-EPZGQN56.js");
3011
+ const teMeta = await import("./te-meta-LJZBOSMO.js");
2900
3012
  commands.push(...teMeta.default);
2901
3013
  } catch {
2902
3014
  }
2903
3015
  try {
2904
- const teCommon = await import("./te-common-WNCZB7R7.js");
3016
+ const teCommon = await import("./te-common-7XXH73MF.js");
2905
3017
  commands.push(...teCommon.default);
2906
3018
  } catch {
2907
3019
  }
2908
3020
  try {
2909
- const engage = await import("./te-engage-4XHCTS6I.js");
3021
+ const engage = await import("./te-engage-NCFAQFX3.js");
2910
3022
  commands.push(...engage.default);
2911
3023
  } catch {
2912
3024
  }
2913
3025
  try {
2914
- const community = await import("./te-community-JEEFXPB3.js");
3026
+ const community = await import("./te-community-QKE67HR2.js");
2915
3027
  commands.push(...community.default);
2916
3028
  } catch {
2917
3029
  }
2918
3030
  try {
2919
- const dataops = await import("./te-dataops-GD3XBYCS.js");
3031
+ const dataops = await import("./te-dataops-6W7NNYST.js");
2920
3032
  commands.push(...dataops.default);
2921
3033
  } catch {
2922
3034
  }
2923
3035
  try {
2924
- const teKb = await import("./te-kb-B62KFP2A.js");
3036
+ const teKb = await import("./te-kb-K5BQYUCM.js");
2925
3037
  commands.push(...teKb.default);
2926
3038
  } catch {
2927
3039
  }
2928
3040
  try {
2929
- const teTeam = await import("./te-team-YY24VORI.js");
3041
+ const teTeam = await import("./te-team-DHK5R7MV.js");
2930
3042
  commands.push(...teTeam.default);
2931
3043
  } catch {
2932
3044
  }
2933
3045
  try {
2934
- const teAgent = await import("./te-agent-KZRIEN4N.js");
3046
+ const teAgent = await import("./te-agent-QPZTLHPH.js");
2935
3047
  commands.push(...teAgent.default);
2936
3048
  } catch {
2937
3049
  }
3050
+ try {
3051
+ const metadata = await import("./metadata-JZ2OTWBK.js");
3052
+ commands.push(...metadata.default);
3053
+ } catch {
3054
+ }
2938
3055
  return commands;
2939
3056
  }
2940
3057
  async function registerAuthCommands() {
2941
3058
  try {
2942
- const { registerAuth } = await import("./auth-GHBMJ5ZR.js");
3059
+ const { registerAuth } = await import("./auth-RDN6D5HU.js");
2943
3060
  registerAuth(program);
2944
3061
  } catch {
2945
3062
  }
2946
3063
  }
2947
3064
  async function registerConfigCommands() {
2948
3065
  try {
2949
- const { registerConfig } = await import("./config-NCUGK6NS.js");
3066
+ const { registerConfig } = await import("./config-2SDTLGOC.js");
2950
3067
  registerConfig(program);
2951
3068
  } catch {
2952
3069
  }
2953
3070
  }
2954
3071
  async function registerApiCommand() {
2955
3072
  try {
2956
- const { registerApi } = await import("./raw-7NVWSVJP.js");
3073
+ const { registerApi } = await import("./raw-NGYHAL3F.js");
2957
3074
  registerApi(program);
2958
3075
  } catch {
2959
3076
  }
2960
3077
  }
2961
3078
  async function registerSyncCommand() {
2962
3079
  try {
2963
- const { registerSync } = await import("./sync-GRVO4K3U.js");
3080
+ const { registerSync } = await import("./sync-JVLX6TGW.js");
2964
3081
  registerSync(program);
2965
3082
  } catch {
2966
3083
  }
2967
3084
  }
2968
3085
  async function registerModelCommand() {
2969
3086
  try {
2970
- const { registerModel } = await import("./model-SJSOZTRS.js");
3087
+ const { registerModel } = await import("./model-ZYMRN4VS.js");
2971
3088
  registerModel(program);
2972
3089
  } catch {
2973
3090
  }