@thinkingai/ae-cli 6.0.38 → 6.0.39

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 (193) hide show
  1. package/README.md +25 -3
  2. package/README.zh.md +25 -3
  3. package/dist/{auth-56Z45UVR.js → auth-GDV3H5I4.js} +18 -8
  4. package/dist/{auth-ENM3FE6L.js → auth-NN55553T.js} +3 -3
  5. package/dist/{capability-2H6PAOA3.js → capability-TPORIKRQ.js} +19 -15
  6. package/dist/{capability-YPOQX6PL.js → capability-VQNC5CF7.js} +19 -15
  7. package/dist/chunk-4NN5IWVN.js +26 -0
  8. package/dist/{chunk-DB4Q3ANU.js → chunk-6A2FUCIS.js} +3 -3
  9. package/dist/{chunk-PVBYJWC2.js → chunk-7KQWSBSL.js} +4 -4
  10. package/dist/{chunk-24BAVOX3.js → chunk-AXDXJTPC.js} +3 -1
  11. package/dist/{chunk-CPVTECJ3.js → chunk-DT6Y3TD7.js} +5 -5
  12. package/dist/{chunk-EGEIXA2Z.js → chunk-DWO43OIB.js} +0 -248
  13. package/dist/{chunk-V6FR6WTW.js → chunk-GJJA4CQZ.js} +34 -2
  14. package/dist/{chunk-RGXCNC4N.js → chunk-GS2P7LFD.js} +50 -17
  15. package/dist/{chunk-LYVNONC4.js → chunk-JHENBQ5B.js} +35 -0
  16. package/dist/{chunk-3P3562ZX.js → chunk-MVDZ7DBQ.js} +5 -5
  17. package/dist/{chunk-LCXU3AAT.js → chunk-NBPKWKRA.js} +2 -2
  18. package/dist/{chunk-HQ2A7ITL.js → chunk-RBNKI5ZW.js} +50 -17
  19. package/dist/{chunk-LHVM35J4.js → chunk-TS6BUGUY.js} +4 -4
  20. package/dist/chunk-TUKQZTMI.js +250 -0
  21. package/dist/{chunk-J7MZHDHQ.js → chunk-VKD5WQKN.js} +5 -5
  22. package/dist/{chunk-3KI3RRXX.js → chunk-VTXHDCBW.js} +3 -3
  23. package/dist/{chunk-KTYR3U6D.js → chunk-YTG6Q75E.js} +10 -6
  24. package/dist/{chunk-IR4ZLVPW.js → chunk-YV52FB5G.js} +25 -3
  25. package/dist/{chunk-E7UXXHO3.js → chunk-Z3OXWCIA.js} +3 -3
  26. package/dist/{cli-token-4SBMXAUK.js → cli-token-GL5MS5FK.js} +4 -4
  27. package/dist/{client-PP5FETMW.js → client-DAIPF7XN.js} +4 -4
  28. package/dist/{community-report-client-KK2QBANO.js → community-report-client-M2RW4MXD.js} +2 -2
  29. package/dist/config-4VZNLBKF.js +489 -0
  30. package/dist/index.js +96 -37
  31. package/dist/memory-RWJW4XFO.js +892 -0
  32. package/dist/memory-VO2ZJCRT.js +892 -0
  33. package/dist/{metadata-JIQ77HFY.js → metadata-YGTHR2XJ.js} +8 -8
  34. package/dist/{metadata-AN3YFZEV.js → metadata-ZRN2GHPN.js} +8 -8
  35. package/dist/{model-JASQVOFD.js → model-CLUIK3K5.js} +7 -5
  36. package/dist/{raw-XJCAT3HX.js → raw-52B4UKO4.js} +8 -7
  37. package/dist/sync-3REDHGY6.js +10259 -0
  38. package/dist/{te-agent-JHUG6DVV.js → te-agent-XNPELAKX.js} +580 -84
  39. package/dist/{te-analysis-ITKTO6JS.js → te-analysis-GJI5FZUL.js} +1152 -13
  40. package/dist/{te-analysis-RAC67YYD.js → te-analysis-N2BRDJZ5.js} +1152 -13
  41. package/dist/{te-community-QOYIYEJI.js → te-community-SQXKE5OO.js} +7 -7
  42. package/dist/{te-community-UFKI6ONP.js → te-community-TYSNU3NQ.js} +7 -7
  43. package/dist/{te-dataops-PZQ5NQLY.js → te-dataops-5TM7WZDI.js} +370 -189
  44. package/dist/{te-dataops-XTWVTJCA.js → te-dataops-OWIADNSM.js} +370 -189
  45. package/dist/{te-engage-NLZUPSBK.js → te-engage-F7V55KVW.js} +333 -105
  46. package/dist/{te-engage-E7F4HTXU.js → te-engage-FMYAYCNV.js} +333 -105
  47. package/dist/{te-kb-E7NSCBRB.js → te-kb-VRMEY3D4.js} +6 -6
  48. package/dist/{te-meta-GBDTMPEL.js → te-meta-53BVXPFI.js} +7 -7
  49. package/dist/{te-meta-ZTLTSHXC.js → te-meta-TOCBPBXI.js} +7 -7
  50. package/dist/{te-system-AH7DMCAQ.js → te-system-XGS5EQIQ.js} +4 -4
  51. package/dist/{te-team-BQ3SKSZV.js → te-team-BZRDV2CM.js} +7 -7
  52. package/dist/{update-DKG6UXEM.js → update-HEDXGOJH.js} +8 -6
  53. package/package.json +4 -1
  54. package/skills/ae-agent/SKILL.md +178 -16
  55. package/skills/ae-agent/references/add-skill.md +22 -10
  56. package/skills/ae-agent/references/edit-skill.md +24 -14
  57. package/skills/ae-agent/references/find-archived-conversations.md +82 -0
  58. package/skills/ae-agent/references/restore-conversation.md +54 -0
  59. package/skills/ae-agent/references/upload-skill.md +24 -14
  60. package/skills/ae-analysis/SKILL.md +1 -1
  61. package/skills/ae-analysis/references/command_index.md +104 -42
  62. package/skills/ae-analysis/references/entity_id_import_options.md +1 -1
  63. package/skills/ae-analysis/references/project_access_detail_get.md +3 -3
  64. package/skills/ae-analysis/references/project_data_power_delete.md +3 -3
  65. package/skills/ae-analysis/references/project_data_power_get.md +3 -3
  66. package/skills/ae-analysis/references/project_data_power_list.md +3 -3
  67. package/skills/ae-analysis/references/project_data_power_upsert.md +3 -3
  68. package/skills/ae-analysis/references/project_entity_create.md +3 -3
  69. package/skills/ae-analysis/references/project_entity_delete.md +3 -3
  70. package/skills/ae-analysis/references/project_entity_event_list.md +3 -3
  71. package/skills/ae-analysis/references/project_entity_get.md +3 -3
  72. package/skills/ae-analysis/references/project_entity_list.md +3 -3
  73. package/skills/ae-analysis/references/project_entity_update.md +3 -3
  74. package/skills/ae-analysis/references/project_function_list.md +3 -3
  75. package/skills/ae-analysis/references/project_info_create.md +25 -0
  76. package/skills/ae-analysis/references/project_info_delete.md +24 -0
  77. package/skills/ae-analysis/references/project_info_get.md +3 -3
  78. package/skills/ae-analysis/references/project_info_list.md +3 -3
  79. package/skills/ae-analysis/references/project_info_update.md +3 -3
  80. package/skills/ae-analysis/references/project_mark_time_create.md +3 -3
  81. package/skills/ae-analysis/references/project_mark_time_delete.md +3 -3
  82. package/skills/ae-analysis/references/project_mark_time_list.md +3 -3
  83. package/skills/ae-analysis/references/project_mark_time_update.md +3 -3
  84. package/skills/ae-analysis/references/project_member_add.md +3 -3
  85. package/skills/ae-analysis/references/project_member_batch_update.md +3 -3
  86. package/skills/ae-analysis/references/project_member_candidate_list.md +3 -3
  87. package/skills/ae-analysis/references/project_member_handover_export.md +3 -3
  88. package/skills/ae-analysis/references/project_member_handover_run.md +3 -3
  89. package/skills/ae-analysis/references/project_member_import.md +3 -3
  90. package/skills/ae-analysis/references/project_member_list.md +3 -3
  91. package/skills/ae-analysis/references/project_member_receiver_list.md +3 -3
  92. package/skills/ae-analysis/references/project_member_remove.md +3 -3
  93. package/skills/ae-analysis/references/project_member_update.md +3 -3
  94. package/skills/ae-analysis/references/project_owner_update.md +3 -3
  95. package/skills/ae-analysis/references/project_permission_binding_list.md +3 -3
  96. package/skills/ae-analysis/references/project_receive_status_update.md +3 -3
  97. package/skills/ae-analysis/references/project_role_delete.md +3 -3
  98. package/skills/ae-analysis/references/project_role_function_list.md +3 -3
  99. package/skills/ae-analysis/references/project_role_get.md +3 -3
  100. package/skills/ae-analysis/references/project_role_list.md +3 -3
  101. package/skills/ae-analysis/references/project_role_upsert.md +3 -3
  102. package/skills/ae-analysis/references/project_role_user_list.md +3 -3
  103. package/skills/ae-analysis/references/project_space_list.md +1 -1
  104. package/skills/ae-analysis/references/project_timezone_get.md +3 -3
  105. package/skills/ae-analysis/references/project_timezone_overview.md +3 -3
  106. package/skills/ae-analysis/references/project_timezone_update.md +3 -3
  107. package/skills/ae-analysis/references/project_user_id_items_update.md +3 -3
  108. package/skills/ae-analysis/references/system_admin_function_list.md +22 -0
  109. package/skills/ae-analysis/references/system_admin_function_update.md +26 -0
  110. package/skills/ae-analysis/references/system_admin_list.md +21 -0
  111. package/skills/ae-analysis/references/system_admin_remove.md +25 -0
  112. package/skills/ae-analysis/references/system_admin_upsert.md +25 -0
  113. package/skills/ae-analysis/references/system_function_list.md +21 -0
  114. package/skills/ae-analysis/references/system_member_add.md +25 -0
  115. package/skills/ae-analysis/references/system_member_candidate_list.md +22 -0
  116. package/skills/ae-analysis/references/system_member_delete.md +25 -0
  117. package/skills/ae-analysis/references/system_member_list.md +24 -0
  118. package/skills/ae-analysis/references/system_member_mfa_unbind.md +25 -0
  119. package/skills/ae-analysis/references/system_member_password_reset.md +32 -0
  120. package/skills/ae-analysis/references/system_member_project_batch_update.md +27 -0
  121. package/skills/ae-analysis/references/system_member_status_update.md +26 -0
  122. package/skills/ae-analysis/references/system_member_update.md +23 -0
  123. package/skills/ae-analysis/references/system_mfa_get.md +21 -0
  124. package/skills/ae-analysis/references/system_mfa_update.md +25 -0
  125. package/skills/ae-analysis/references/system_node_monitor_list.md +24 -0
  126. package/skills/ae-analysis/references/system_oauth2_update.md +22 -0
  127. package/skills/ae-analysis/references/system_ops_alert_contact_delete.md +25 -0
  128. package/skills/ae-analysis/references/system_ops_alert_contact_list.md +23 -0
  129. package/skills/ae-analysis/references/system_ops_alert_contact_test.md +29 -0
  130. package/skills/ae-analysis/references/system_ops_alert_contact_upsert.md +39 -0
  131. package/skills/ae-analysis/references/system_preference_get.md +21 -0
  132. package/skills/ae-analysis/references/system_preference_update.md +22 -0
  133. package/skills/ae-analysis/references/system_project_usage_list.md +28 -0
  134. package/skills/ae-analysis/references/system_query_alert_rule_list.md +21 -0
  135. package/skills/ae-analysis/references/system_query_alert_rule_update.md +26 -0
  136. package/skills/ae-analysis/references/system_query_monitor_overview.md +26 -0
  137. package/skills/ae-analysis/references/system_query_task_cancel.md +25 -0
  138. package/skills/ae-analysis/references/system_query_task_export.md +49 -0
  139. package/skills/ae-analysis/references/system_query_task_get.md +23 -0
  140. package/skills/ae-analysis/references/system_query_task_list.md +35 -0
  141. package/skills/ae-analysis/references/system_query_task_options.md +27 -0
  142. package/skills/ae-analysis/references/system_receiver_address_delete.md +26 -0
  143. package/skills/ae-analysis/references/system_receiver_address_overview.md +21 -0
  144. package/skills/ae-analysis/references/system_receiver_address_project_list.md +21 -0
  145. package/skills/ae-analysis/references/system_receiver_address_promote.md +24 -0
  146. package/skills/ae-analysis/references/system_receiver_address_upsert.md +27 -0
  147. package/skills/ae-analysis/references/system_receiver_detection_get.md +22 -0
  148. package/skills/ae-analysis/references/system_receiver_detection_run.md +22 -0
  149. package/skills/ae-analysis/references/system_receiver_detection_update.md +25 -0
  150. package/skills/ae-analysis/references/system_role_delete.md +26 -0
  151. package/skills/ae-analysis/references/system_role_function_list.md +22 -0
  152. package/skills/ae-analysis/references/system_role_get.md +22 -0
  153. package/skills/ae-analysis/references/system_role_list.md +24 -0
  154. package/skills/ae-analysis/references/system_role_upsert.md +27 -0
  155. package/skills/ae-analysis/references/system_role_user_list.md +22 -0
  156. package/skills/ae-analysis/references/system_seat_list.md +25 -0
  157. package/skills/ae-analysis/references/system_seat_update.md +26 -0
  158. package/skills/ae-analysis/references/system_smtp_delete.md +24 -0
  159. package/skills/ae-analysis/references/system_smtp_get.md +21 -0
  160. package/skills/ae-analysis/references/system_smtp_test.md +22 -0
  161. package/skills/ae-analysis/references/system_smtp_upsert.md +31 -0
  162. package/skills/ae-analysis/references/system_third_party_login_disable.md +25 -0
  163. package/skills/ae-analysis/references/system_third_party_login_list.md +21 -0
  164. package/skills/ae-analysis/references/system_third_party_login_upsert.md +33 -0
  165. package/skills/ae-analysis/references/system_usage_overview.md +21 -0
  166. package/skills/ae-analysis/references/system_usage_trend_export.md +44 -0
  167. package/skills/ae-analysis/references/system_usage_trend_query.md +28 -0
  168. package/skills/ae-dataops/SKILL.md +1 -1
  169. package/skills/ae-dataops/references/dataops-flow-create.md +51 -16
  170. package/skills/ae-engage/SKILL.md +56 -26
  171. package/skills/ae-engage/references/activity-activity.md +3 -0
  172. package/skills/ae-engage/references/activity-approval.md +12 -4
  173. package/skills/ae-engage/references/activity-task.md +21 -6
  174. package/skills/ae-engage/references/activity-topic.md +31 -13
  175. package/skills/ae-engage/references/add-channel.md +170 -41
  176. package/skills/ae-engage/references/build-task-save-guide.md +40 -27
  177. package/skills/ae-engage/references/channel-update-config.md +3 -2
  178. package/skills/ae-engage/references/common-metric.md +48 -120
  179. package/skills/ae-engage/references/flow-detail.md +13 -0
  180. package/skills/ae-engage/references/preset-event.md +12 -32
  181. package/skills/ae-engage/references/save-flow.md +127 -64
  182. package/skills/ae-engage/references/save-task.md +197 -59
  183. package/skills/ae-engage/references/scene-config-metric.md +3 -0
  184. package/skills/ae-engage/references/scene-preset-metric.md +8 -37
  185. package/skills/ae-engage/references/scene-strategy-audience.md +51 -643
  186. package/skills/ae-engage/references/scene-strategy.md +6 -6
  187. package/skills/ae-engage/references/task-detail.md +10 -0
  188. package/skills/ae-engage/references/task-submit-approval.md +45 -0
  189. package/skills/ae-engage/references/validate-flow-node-config.md +1 -1
  190. package/skills/ae-generate-tracking-code/SKILL.md +2 -2
  191. package/skills/ae-metadata/SKILL.md +1 -1
  192. package/dist/config-BSSALXEN.js +0 -128
  193. package/dist/sync-QFP4XFN3.js +0 -485
@@ -0,0 +1,489 @@
1
+ import {
2
+ MultiselectCancelled,
3
+ promptSingleSelect
4
+ } from "./chunk-TUKQZTMI.js";
5
+ import {
6
+ GLOBAL_QUERY_CONFIG_KEY,
7
+ getAnalysisMappingPathForClusterMode,
8
+ getClusterInfoFilePath,
9
+ isGlobalQueryModeEnabled,
10
+ setGlobalQueryModeEnabled
11
+ } from "./chunk-NBPKWKRA.js";
12
+ import {
13
+ printError,
14
+ printOutput
15
+ } from "./chunk-YTG6Q75E.js";
16
+ import "./chunk-Z3OXWCIA.js";
17
+ import {
18
+ AE_TRIAL_URL,
19
+ missingAeHostHint
20
+ } from "./chunk-YV52FB5G.js";
21
+ import {
22
+ addHost,
23
+ listHosts,
24
+ loadConfig,
25
+ normalizeUrl,
26
+ removeHost,
27
+ resolveHostSelector,
28
+ setActiveHost,
29
+ updateHostLabel
30
+ } from "./chunk-GJJA4CQZ.js";
31
+ import "./chunk-JHENBQ5B.js";
32
+
33
+ // src/commands/config.ts
34
+ import * as readline2 from "readline";
35
+
36
+ // src/commands/config-ui.ts
37
+ import * as readline from "readline";
38
+ async function runConfigUI() {
39
+ if (!process.stdin.isTTY || !process.stderr.isTTY) {
40
+ throw new Error("Interactive config requires a TTY.");
41
+ }
42
+ if (listHosts().length === 0) {
43
+ process.stderr.write("\n\x1B[1mNo AE environments configured.\x1B[0m\n\n");
44
+ process.stderr.write("Use the AE URL provided by your AgenticEngine administrator.\n");
45
+ process.stderr.write(`No AgenticEngine environment? Request a trial: ${AE_TRIAL_URL}
46
+
47
+ `);
48
+ await promptAddEnvironment();
49
+ return;
50
+ }
51
+ while (true) {
52
+ const hosts = listHosts();
53
+ const items = [
54
+ ...hosts.map((host) => ({ type: "host", host })),
55
+ { type: "add" }
56
+ ];
57
+ const activeIndex = Math.max(0, hosts.findIndex((host) => host.active));
58
+ const result = await promptEnvironmentAction(items, activeIndex);
59
+ const item = items[result.index];
60
+ if (result.action === "quit") return;
61
+ if (result.action === "add" || item.type === "add") {
62
+ await promptAddEnvironment();
63
+ continue;
64
+ }
65
+ if (!item.host) continue;
66
+ if (result.action === "select") {
67
+ if (item.host.active) {
68
+ process.stderr.write(`
69
+ Already active: \x1B[1m${item.host.label}\x1B[0m
70
+ `);
71
+ return;
72
+ }
73
+ setActiveHost(item.host.url);
74
+ process.stderr.write(`
75
+ \x1B[32m\u2713\x1B[0m Active environment: \x1B[1m${item.host.label}\x1B[0m ${item.host.url}
76
+ `);
77
+ process.stderr.write(` Authenticate if needed: ae-cli auth login --host ${item.host.url}
78
+ `);
79
+ return;
80
+ }
81
+ if (result.action === "rename") {
82
+ await promptRenameEnvironment(item.host);
83
+ continue;
84
+ }
85
+ if (result.action === "remove") {
86
+ await promptRemoveEnvironment(item.host);
87
+ }
88
+ }
89
+ }
90
+ async function promptAddEnvironment() {
91
+ const urlInput = await ask("Host URL: ");
92
+ if (!urlInput) {
93
+ process.stderr.write("Cancelled.\n");
94
+ return;
95
+ }
96
+ const url = normalizeUrl(urlInput);
97
+ const existing = listHosts().find((host) => host.url === url);
98
+ if (existing) {
99
+ process.stderr.write(`\x1B[31m\u2717\x1B[0m Environment already configured as ${existing.label}: ${url}
100
+ `);
101
+ return;
102
+ }
103
+ const defaultLabel = defaultLabelForUrl(url);
104
+ const labelInput = await ask(`Label [${defaultLabel}]: `);
105
+ const label = labelInput || defaultLabel;
106
+ try {
107
+ addHost(url, label);
108
+ const active = listHosts().find((host) => host.url === url)?.active;
109
+ process.stderr.write(
110
+ `
111
+ \x1B[32m\u2713\x1B[0m Added${active ? " and activated" : ""}: \x1B[1m${label}\x1B[0m ${url}
112
+ `
113
+ );
114
+ if (active) {
115
+ process.stderr.write(` Authenticate if needed: ae-cli auth login --host ${url}
116
+ `);
117
+ }
118
+ } catch (err) {
119
+ process.stderr.write(`\x1B[31m\u2717\x1B[0m ${err.message}
120
+ `);
121
+ }
122
+ }
123
+ async function promptRenameEnvironment(host) {
124
+ const input = await ask(`New label [${host.label}]: `);
125
+ const label = input || host.label;
126
+ if (label === host.label) return;
127
+ try {
128
+ updateHostLabel(host.url, label);
129
+ process.stderr.write(`\x1B[32m\u2713\x1B[0m Renamed: ${host.label} \u2192 ${label}
130
+ `);
131
+ } catch (err) {
132
+ process.stderr.write(`\x1B[31m\u2717\x1B[0m ${err.message}
133
+ `);
134
+ }
135
+ }
136
+ async function promptRemoveEnvironment(host) {
137
+ const hosts = listHosts();
138
+ let replacement;
139
+ if (host.active && hosts.length > 1) {
140
+ try {
141
+ const replacementUrl = await promptSingleSelect({
142
+ title: `Select the environment to activate after removing ${host.label}:`,
143
+ items: hosts.filter((candidate) => candidate.url !== host.url).map((candidate) => ({
144
+ value: candidate.url,
145
+ label: `${candidate.label} ${candidate.url}`
146
+ }))
147
+ });
148
+ replacement = hosts.find((candidate) => candidate.url === replacementUrl);
149
+ } catch (err) {
150
+ if (err instanceof MultiselectCancelled) return;
151
+ throw err;
152
+ }
153
+ }
154
+ const confirmed = await confirm(`Remove ${host.label} (${host.url})?`);
155
+ if (!confirmed) {
156
+ process.stderr.write("Cancelled.\n");
157
+ return;
158
+ }
159
+ if (replacement) setActiveHost(replacement.url);
160
+ removeHost(host.url);
161
+ process.stderr.write(`\x1B[32m\u2713\x1B[0m Removed: ${host.label}
162
+ `);
163
+ if (replacement) {
164
+ process.stderr.write(` Active environment: ${replacement.label} ${replacement.url}
165
+ `);
166
+ } else if (listHosts().length === 0) {
167
+ process.stderr.write(" No AE environments remain.\n");
168
+ }
169
+ }
170
+ function promptEnvironmentAction(items, initialIndex) {
171
+ const stdin = process.stdin;
172
+ const stderr = process.stderr;
173
+ let cursor = initialIndex;
174
+ let renderCount = 0;
175
+ const lineCount = items.length + 4;
176
+ function render() {
177
+ if (renderCount > 0) stderr.write(`\x1B[${lineCount}A`);
178
+ const active = items.find((item) => item.host?.active)?.host;
179
+ stderr.write("\x1B[1mAE Environment Manager\x1B[0m\x1B[K\n");
180
+ stderr.write(`Active: ${active ? `${active.label} ${active.url}` : "none"}\x1B[K
181
+ `);
182
+ stderr.write("\u2191\u2193 select \xB7 Enter activate \xB7 e rename \xB7 d delete \xB7 a add \xB7 q quit\x1B[K\n");
183
+ stderr.write("\x1B[K\n");
184
+ items.forEach((item, index) => {
185
+ const pointer = index === cursor ? "\x1B[36m\u276F\x1B[0m" : " ";
186
+ if (item.type === "add") {
187
+ stderr.write(`${pointer} \x1B[2m+ Add environment...\x1B[0m\x1B[K
188
+ `);
189
+ return;
190
+ }
191
+ const host = item.host;
192
+ const marker = host.active ? "\x1B[32m\u25CF\x1B[0m" : "\x1B[2m\u25CB\x1B[0m";
193
+ const label = host.active ? `\x1B[1;32m${host.label}\x1B[0m` : `\x1B[1m${host.label}\x1B[0m`;
194
+ const badge = host.active ? " \x1B[32m[active]\x1B[0m" : "";
195
+ stderr.write(`${pointer} ${marker} ${label} ${host.url}${badge}\x1B[K
196
+ `);
197
+ });
198
+ renderCount++;
199
+ }
200
+ return new Promise((resolve) => {
201
+ stderr.write("\n\x1B[?25l");
202
+ stdin.setRawMode(true);
203
+ stdin.resume();
204
+ stdin.setEncoding("utf8");
205
+ function cleanup() {
206
+ stdin.setRawMode(false);
207
+ stdin.pause();
208
+ stdin.removeListener("data", onData);
209
+ stderr.write("\x1B[?25h");
210
+ }
211
+ function finish(action) {
212
+ cleanup();
213
+ resolve({ action, index: cursor });
214
+ }
215
+ function onData(key) {
216
+ if (key === "\x1B[A" || key === "k") {
217
+ cursor = (cursor - 1 + items.length) % items.length;
218
+ render();
219
+ } else if (key === "\x1B[B" || key === "j") {
220
+ cursor = (cursor + 1) % items.length;
221
+ render();
222
+ } else if (key === "\r" || key === "\n") {
223
+ finish("select");
224
+ } else if ((key === "e" || key === "E") && items[cursor].type === "host") {
225
+ finish("rename");
226
+ } else if ((key === "d" || key === "D") && items[cursor].type === "host") {
227
+ finish("remove");
228
+ } else if (key === "a" || key === "A") {
229
+ finish("add");
230
+ } else if (key === "q" || key === "Q" || key === "\x1B" || key === "") {
231
+ finish("quit");
232
+ }
233
+ }
234
+ stdin.on("data", onData);
235
+ render();
236
+ });
237
+ }
238
+ function defaultLabelForUrl(url) {
239
+ try {
240
+ return new URL(url).hostname.split(".")[0] || url;
241
+ } catch {
242
+ return url;
243
+ }
244
+ }
245
+ async function ask(question) {
246
+ const rl = readline.createInterface({ input: process.stdin, output: process.stderr });
247
+ return new Promise((resolve) => {
248
+ rl.question(question, (answer) => {
249
+ rl.close();
250
+ resolve(answer.trim());
251
+ });
252
+ });
253
+ }
254
+ async function confirm(question) {
255
+ const answer = await ask(`${question} [y/N] `);
256
+ return answer.toLowerCase() === "y" || answer.toLowerCase() === "yes";
257
+ }
258
+
259
+ // src/commands/config.ts
260
+ function registerConfig(program) {
261
+ const configCmd = program.command("config").description("Manage AE host environments interactively or with subcommands").action(async () => {
262
+ if (!process.stdin.isTTY || !process.stderr.isTTY) {
263
+ failConfig(
264
+ "Interactive config requires a TTY.",
265
+ "Run: ae-cli config list, ae-cli config add <url> --label <label>, or ae-cli config --help"
266
+ );
267
+ return;
268
+ }
269
+ await runConfigUI();
270
+ });
271
+ configCmd.command("list").description("List configured AE environments").action(async () => {
272
+ await printConfigList(program);
273
+ });
274
+ configCmd.command("current").description("Show the active AE environment").action(async () => {
275
+ await printCurrentConfig(program);
276
+ });
277
+ configCmd.command("use <env>").description("Switch active AE environment by exact URL or unique label").action(async (env) => {
278
+ await useConfigEnv(program, env);
279
+ });
280
+ configCmd.command("add <url>").description("Add an AE environment").requiredOption("--label <label>", "Unique display label for this environment").option("--use", "Set the new environment as active").action(async (url, opts) => {
281
+ await addConfigEnv(program, url, opts);
282
+ });
283
+ configCmd.command("rename <env> <label>").description("Rename an AE environment selected by exact URL or unique label").action(async (env, label) => {
284
+ await renameConfigEnv(program, env, label);
285
+ });
286
+ configCmd.command("remove <env>").alias("delete").description("Remove an AE environment selected by exact URL or unique label").option("--yes", "Skip the deletion confirmation").action(async (env, opts) => {
287
+ await removeConfigEnv(program, env, Boolean(opts.yes || program.opts().yes));
288
+ });
289
+ configCmd.command("set-host <url>").description("Compatibility command: add or update an AE host and set it active").option("--label <label>", "Display label for this host (defaults to the host URL)").action(async (url, opts) => {
290
+ try {
291
+ const normalized = normalizeUrl(url);
292
+ const label = opts.label || normalized;
293
+ addHost(normalized, label);
294
+ setActiveHost(normalized);
295
+ await printOutput(
296
+ { activeHost: normalized, label: label.trim() },
297
+ program.opts().format || "json",
298
+ program.opts().jq
299
+ );
300
+ } catch (err) {
301
+ failConfig(err.message, "Run: ae-cli config list");
302
+ }
303
+ });
304
+ const clusterMode = configCmd.command("cluster-mode").description("Manage local multi-cluster analysis MCP mode").action(async () => {
305
+ await printClusterModeStatus(program);
306
+ });
307
+ clusterMode.command("status").description("Show local multi-cluster analysis MCP mode").action(async () => {
308
+ await printClusterModeStatus(program);
309
+ });
310
+ clusterMode.command("enable").description("Enable local multi-cluster analysis MCP mode").action(async () => {
311
+ setGlobalQueryModeEnabled(true);
312
+ await printClusterModeStatus(program);
313
+ });
314
+ clusterMode.command("disable").description("Disable local multi-cluster analysis MCP mode").action(async () => {
315
+ setGlobalQueryModeEnabled(false);
316
+ await printClusterModeStatus(program);
317
+ });
318
+ }
319
+ async function printClusterModeStatus(program) {
320
+ const enabled = isGlobalQueryModeEnabled();
321
+ await printOutput({
322
+ [GLOBAL_QUERY_CONFIG_KEY]: enabled,
323
+ path: getClusterInfoFilePath(),
324
+ analysisMappingPath: getAnalysisMappingPathForClusterMode(enabled)
325
+ }, program.opts().format || "json", program.opts().jq);
326
+ }
327
+ function readHostViews() {
328
+ const config = loadConfig();
329
+ const hosts = Object.entries(config.hosts).map(([url, entry]) => ({
330
+ url,
331
+ label: entry.label,
332
+ active: url === config.activeHost
333
+ }));
334
+ return { activeHost: config.activeHost, hosts };
335
+ }
336
+ async function printConfigList(program) {
337
+ const { activeHost, hosts } = readHostViews();
338
+ const activeLabel = hosts.find((host) => host.active)?.label || "";
339
+ await printOutput(
340
+ { activeHost, activeLabel, hosts },
341
+ program.opts().format || "json",
342
+ program.opts().jq
343
+ );
344
+ }
345
+ async function printCurrentConfig(program) {
346
+ const { activeHost, hosts } = readHostViews();
347
+ const current = hosts.find((h) => h.url === activeHost);
348
+ if (!current) {
349
+ failConfig("No active AE environment configured.", missingAeHostHint("Run ae-cli config list to inspect saved environments."));
350
+ return;
351
+ }
352
+ await printOutput({ activeHost: current.url, label: current.label }, program.opts().format || "json", program.opts().jq);
353
+ }
354
+ async function useConfigEnv(program, env) {
355
+ const target = resolveHostSelector(env);
356
+ if (target.status === "not-found") {
357
+ failHostResolution(env, target);
358
+ return;
359
+ }
360
+ if (target.status === "duplicate-label") {
361
+ failHostResolution(env, target);
362
+ return;
363
+ }
364
+ setActiveHost(target.host.url);
365
+ await printOutput({ activeHost: target.host.url, label: target.host.label }, program.opts().format || "json", program.opts().jq);
366
+ }
367
+ async function addConfigEnv(program, url, opts) {
368
+ const normalized = normalizeUrl(url);
369
+ const config = loadConfig();
370
+ if (config.hosts[normalized]) {
371
+ failConfig(
372
+ `AE environment is already configured: ${normalized}`,
373
+ `Run: ae-cli config rename ${quoteSelector(config.hosts[normalized].label)} <label> or ae-cli config use ${quoteSelector(config.hosts[normalized].label)}`
374
+ );
375
+ return;
376
+ }
377
+ try {
378
+ addHost(normalized, opts.label);
379
+ if (opts.use) setActiveHost(normalized);
380
+ const saved = loadConfig();
381
+ await printOutput(
382
+ {
383
+ url: normalized,
384
+ label: saved.hosts[normalized].label,
385
+ active: saved.activeHost === normalized
386
+ },
387
+ program.opts().format || "json",
388
+ program.opts().jq
389
+ );
390
+ } catch (err) {
391
+ failConfig(err.message, "Choose a non-empty, unique label and run the command again.");
392
+ }
393
+ }
394
+ async function renameConfigEnv(program, env, label) {
395
+ const target = resolveHostSelector(env);
396
+ if (target.status !== "found") {
397
+ failHostResolution(env, target);
398
+ return;
399
+ }
400
+ try {
401
+ updateHostLabel(target.host.url, label);
402
+ await printOutput(
403
+ { url: target.host.url, label: label.trim(), active: target.host.active },
404
+ program.opts().format || "json",
405
+ program.opts().jq
406
+ );
407
+ } catch (err) {
408
+ failConfig(err.message, "Choose a non-empty, unique label and run the command again.");
409
+ }
410
+ }
411
+ async function removeConfigEnv(program, env, skipConfirmation) {
412
+ const target = resolveHostSelector(env);
413
+ if (target.status !== "found") {
414
+ failHostResolution(env, target);
415
+ return;
416
+ }
417
+ const hosts = readHostViews().hosts;
418
+ if (target.host.active && hosts.length > 1) {
419
+ failConfig(
420
+ `Cannot remove the active AE environment: ${target.host.label}`,
421
+ "Switch first with: ae-cli config use <env>"
422
+ );
423
+ return;
424
+ }
425
+ if (!skipConfirmation) {
426
+ if (!process.stdin.isTTY) {
427
+ failConfig(
428
+ "Deletion confirmation requires a TTY.",
429
+ `Re-run with --yes: ae-cli config remove ${quoteSelector(env)} --yes`
430
+ );
431
+ return;
432
+ }
433
+ const confirmed = await confirm2(`Remove ${target.host.label} (${target.host.url})?`);
434
+ if (!confirmed) {
435
+ await printOutput(
436
+ { removed: false, url: target.host.url, label: target.host.label },
437
+ program.opts().format || "json",
438
+ program.opts().jq
439
+ );
440
+ return;
441
+ }
442
+ }
443
+ removeHost(target.host.url);
444
+ await printOutput(
445
+ {
446
+ removed: true,
447
+ url: target.host.url,
448
+ label: target.host.label,
449
+ activeHost: loadConfig().activeHost
450
+ },
451
+ program.opts().format || "json",
452
+ program.opts().jq
453
+ );
454
+ }
455
+ function failHostResolution(env, target) {
456
+ if (target.status === "duplicate-label") {
457
+ failConfig(
458
+ `Duplicate label: ${env}`,
459
+ `Rename duplicate labels first. Run: ae-cli config list \u2014 ${formatHostOptions(target.matches)}`
460
+ );
461
+ return;
462
+ }
463
+ failConfig(
464
+ `No AE environment matched: ${env}`,
465
+ target.hosts.length > 0 ? `Available environments: ${formatHostOptions(target.hosts)}` : missingAeHostHint()
466
+ );
467
+ }
468
+ function formatHostOptions(hosts) {
469
+ return hosts.map((h) => `${h.label} (${h.url})`).join(", ");
470
+ }
471
+ function quoteSelector(value) {
472
+ return JSON.stringify(value);
473
+ }
474
+ async function confirm2(message) {
475
+ const rl = readline2.createInterface({ input: process.stdin, output: process.stderr });
476
+ return new Promise((resolve) => {
477
+ rl.question(`${message} [y/N] `, (answer) => {
478
+ rl.close();
479
+ resolve(answer.trim().toLowerCase() === "y" || answer.trim().toLowerCase() === "yes");
480
+ });
481
+ });
482
+ }
483
+ function failConfig(message, hint) {
484
+ printError("config", message, hint);
485
+ process.exitCode = 1;
486
+ }
487
+ export {
488
+ registerConfig
489
+ };