@thinkingai/ae-cli 6.1.24 → 6.1.25

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 (135) hide show
  1. package/README.md +7 -1
  2. package/README.zh.md +7 -1
  3. package/dist/{auth-XZNXFRJS.js → auth-LHM7NQPR.js} +167 -7
  4. package/dist/{capability-FYTU3X6L.js → capability-SJI5KOCK.js} +11 -6
  5. package/dist/{chunk-CCS66K4K.js → chunk-2FJM4HRV.js} +3 -3
  6. package/dist/{chunk-57RRFUEZ.js → chunk-5XRQ3CZR.js} +4 -4
  7. package/dist/{chunk-EQ255HKO.js → chunk-7WZACOAI.js} +2 -2
  8. package/dist/{chunk-DX5CDO34.js → chunk-BW7JUDEI.js} +84 -19
  9. package/dist/{chunk-7XGFSUOM.js → chunk-DU72X2IO.js} +271 -76
  10. package/dist/{chunk-V2NUHPXF.js → chunk-GK7WDY7E.js} +1 -1
  11. package/dist/{chunk-7FTTULED.js → chunk-IG3DYEIR.js} +4 -1
  12. package/dist/{chunk-HBGADCKA.js → chunk-KJDOTPYU.js} +3 -3
  13. package/dist/{chunk-4NRCTUZJ.js → chunk-KS4DE3MX.js} +4 -4
  14. package/dist/{chunk-JOCDD4ON.js → chunk-N4BLPJC7.js} +1 -1
  15. package/dist/{chunk-HFGZGYCG.js → chunk-QYXDJOLA.js} +252 -6
  16. package/dist/{chunk-DVMLWQD4.js → chunk-SO5LKIWP.js} +2 -2
  17. package/dist/{chunk-VYXXOKYS.js → chunk-XKIW3QMF.js} +7 -4
  18. package/dist/{chunk-MAPZ7VB6.js → chunk-YVGXGTD6.js} +13 -0
  19. package/dist/{community-report-client-CU22W53K.js → community-report-client-6VJDDMJJ.js} +1 -1
  20. package/dist/{config-XO3LI3SA.js → config-XQWOPDHN.js} +25 -6
  21. package/dist/{context-IFJI3LIT.js → context-M3HDGEIR.js} +4 -4
  22. package/dist/{data-integration-HNGUKFIC.js → data-integration-XBTCGXQT.js} +6 -6
  23. package/dist/index.js +78 -41
  24. package/dist/{local-data-upload-client-GTRIT64F.js → local-data-upload-client-3P7NIVQ4.js} +1 -1
  25. package/dist/{memory-QGPSNCQS.js → memory-6APEB2JB.js} +4 -4
  26. package/dist/{metadata-DI5BMYFU.js → metadata-JRYKNUS5.js} +7 -7
  27. package/dist/{model-RNPQXIBI.js → model-ZS7HVGKN.js} +4 -4
  28. package/dist/{personal-semantic-preference-5C3WUXFI.js → personal-semantic-preference-IDE2GE5T.js} +8 -6
  29. package/dist/project-semantic-36KOCYN7.js +356 -0
  30. package/dist/{sync-O45NXEQY.js → sync-EQLSTUS7.js} +7 -7
  31. package/dist/{te-agent-K5MSPNHJ.js → te-agent-Z3HCTKR7.js} +348 -55
  32. package/dist/{te-analysis-AISWCOOZ.js → te-analysis-5ZZ6YHVH.js} +940 -144
  33. package/dist/{te-community-4OYU3BDA.js → te-community-Z7JACGF3.js} +3 -3
  34. package/dist/{te-dataops-NFIPB6FX.js → te-dataops-F7GQOIS6.js} +644 -276
  35. package/dist/{te-engage-BAM3GBFX.js → te-engage-RNRMYDO3.js} +6 -6
  36. package/dist/{te-experiment-GUTZXZ5Z.js → te-experiment-BTAC2UNK.js} +6 -6
  37. package/dist/{te-kb-3TS73NO6.js → te-kb-QJLJEX5K.js} +323 -181
  38. package/dist/{te-system-STMHLS5J.js → te-system-IXC43QHZ.js} +6 -6
  39. package/dist/{te-team-3I5AOX3N.js → te-team-BIZIKIHZ.js} +6 -6
  40. package/dist/{update-RZXLPCRH.js → update-W2SGQNKT.js} +4 -4
  41. package/package.json +11 -4
  42. package/skills/ae-agent/SKILL.md +9 -4
  43. package/skills/ae-agent/references/notification.md +40 -0
  44. package/skills/ae-analysis/SKILL.md +43 -20
  45. package/skills/ae-analysis/references/adhoc_export.md +1 -1
  46. package/skills/ae-analysis/references/adhoc_run.md +1 -1
  47. package/skills/ae-analysis/references/agent_review_submit_to_page.md +2 -0
  48. package/skills/ae-analysis/references/ai_models/event.md +6 -1
  49. package/skills/ae-analysis/references/ai_models/funnel.md +7 -1
  50. package/skills/ae-analysis/references/ai_models/heat_map.md +23 -0
  51. package/skills/ae-analysis/references/ai_models/interval.md +24 -0
  52. package/skills/ae-analysis/references/ai_models/path.md +20 -0
  53. package/skills/ae-analysis/references/ai_models/prop_analysis.md +2 -0
  54. package/skills/ae-analysis/references/ai_models/rank_list.md +30 -0
  55. package/skills/ae-analysis/references/ai_models/retention.md +45 -1
  56. package/skills/ae-analysis/references/ai_models/revenue.md +20 -2
  57. package/skills/ae-analysis/references/ai_models/session.md +76 -0
  58. package/skills/ae-analysis/references/ai_models/tag.md +2 -0
  59. package/skills/ae-analysis/references/ai_models.md +73 -3
  60. package/skills/ae-analysis/references/analysis_data_retrieval.md +4 -0
  61. package/skills/ae-analysis/references/analysis_drilldown_contract.md +4 -1
  62. package/skills/ae-analysis/references/asset_batch_info_export.md +10 -0
  63. package/skills/ae-analysis/references/asset_batch_sql_export.md +13 -1
  64. package/skills/ae-analysis/references/asset_export.md +12 -1
  65. package/skills/ae-analysis/references/asset_list.md +1 -0
  66. package/skills/ae-analysis/references/asset_search.md +11 -5
  67. package/skills/ae-analysis/references/bi_panel_list.md +1 -1
  68. package/skills/ae-analysis/references/catalog_list.md +1 -1
  69. package/skills/ae-analysis/references/collaboration.md +48 -0
  70. package/skills/ae-analysis/references/command_index.md +19 -17
  71. package/skills/ae-analysis/references/dashboard_list.md +4 -4
  72. package/skills/ae-analysis/references/dashboard_report_data_export.md +2 -0
  73. package/skills/ae-analysis/references/drilldown_session_details_run.md +41 -0
  74. package/skills/ae-analysis/references/event_export.md +3 -1
  75. package/skills/ae-analysis/references/governance_recommendation_auto_review.md +77 -0
  76. package/skills/ae-analysis/references/governance_recommendation_export.md +11 -0
  77. package/skills/ae-analysis/references/metadata_resolution.md +3 -3
  78. package/skills/ae-analysis/references/metric_export.md +3 -1
  79. package/skills/ae-analysis/references/metric_list.md +1 -1
  80. package/skills/ae-analysis/references/operation_record_export.md +10 -0
  81. package/skills/ae-analysis/references/personal_semantic_preference_add.md +2 -2
  82. package/skills/ae-analysis/references/personal_semantic_preference_get.md +4 -4
  83. package/skills/ae-analysis/references/personal_semantic_preference_list.md +4 -4
  84. package/skills/ae-analysis/references/project_semantic_knowledge_wiki.md +29 -11
  85. package/skills/ae-analysis/references/project_semantic_knowledge_wiki_plan_schema.md +59 -0
  86. package/skills/ae-analysis/references/property_export.md +3 -1
  87. package/skills/ae-analysis/references/report_create.md +5 -1
  88. package/skills/ae-analysis/references/report_data_export.md +6 -0
  89. package/skills/ae-analysis/references/report_get.md +2 -0
  90. package/skills/ae-analysis/references/report_list.md +5 -5
  91. package/skills/ae-analysis/references/report_update.md +7 -1
  92. package/skills/ae-analysis/references/sql_table_columns.md +4 -4
  93. package/skills/ae-analysis/references/sql_table_list.md +5 -5
  94. package/skills/ae-analysis/references/user_cluster_models.md +8 -0
  95. package/skills/ae-analysis/references/user_tag_create.md +7 -1
  96. package/skills/ae-analysis/references/user_tag_get.md +1 -1
  97. package/skills/ae-analysis/references/user_tag_models.md +18 -2
  98. package/skills/ae-analysis/references/user_tag_refresh.md +1 -1
  99. package/skills/ae-analysis/references/user_tag_update.md +2 -2
  100. package/skills/ae-analysis/scripts/project-semantic-knowledge-wiki/build-project-semantic-wiki.mjs +337 -12
  101. package/skills/ae-analysis/scripts/project-semantic-knowledge-wiki/default-compile-rules.md +7 -2
  102. package/skills/ae-analysis/scripts/project-semantic-knowledge-wiki/generate-build-ir.mjs +284 -24
  103. package/skills/ae-analysis/scripts/project-semantic-knowledge-wiki/package-wiki-source-zip.mjs +185 -22
  104. package/skills/ae-analysis/scripts/project-semantic-knowledge-wiki/precompiled-source.mjs +46 -2
  105. package/skills/ae-capability/SKILL.md +63 -1
  106. package/skills/ae-capability/references/collaboration.md +48 -0
  107. package/skills/ae-community/SKILL.md +5 -1
  108. package/skills/ae-community/references/collaboration.md +48 -0
  109. package/skills/ae-data-integration/SKILL.md +4 -0
  110. package/skills/ae-data-integration/references/collaboration.md +48 -0
  111. package/skills/ae-dataops/SKILL.md +54 -74
  112. package/skills/ae-dataops/references/collaboration.md +48 -0
  113. package/skills/ae-dataops/references/dataops-backfill.md +23 -18
  114. package/skills/ae-dataops/references/dataops-flow-create.md +74 -23
  115. package/skills/ae-dataops/references/dataops-flow-monitor.md +45 -13
  116. package/skills/ae-dataops/references/dataops-integration.md +57 -30
  117. package/skills/ae-dataops/references/dataops-query.md +21 -4
  118. package/skills/ae-dataops/references/dataops-table.md +143 -11
  119. package/skills/ae-engage/SKILL.md +21 -6
  120. package/skills/ae-engage/references/channel-mgmt.md +3 -3
  121. package/skills/ae-engage/references/collaboration.md +48 -0
  122. package/skills/ae-engage/references/scene-config-channel.md +4 -4
  123. package/skills/ae-generate-tracking-plan/SKILL.md +4 -0
  124. package/skills/ae-generate-tracking-plan/references/collaboration.md +48 -0
  125. package/skills/ae-kb/SKILL.md +9 -1
  126. package/skills/ae-kb/references/collaboration.md +48 -0
  127. package/skills/ae-kb/references/schema-import.md +30 -0
  128. package/skills/ae-kb-discovery/SKILL.md +7 -2
  129. package/skills/ae-kb-discovery/references/collaboration.md +48 -0
  130. package/skills/ae-metadata/SKILL.md +20 -12
  131. package/skills/ae-metadata/references/collaboration.md +48 -0
  132. package/dist/project-semantic-3LF6Q6JZ.js +0 -1119
  133. package/skills/ae-project-semantic/SKILL.md +0 -193
  134. package/skills/ae-project-semantic/references/query-routing-v5.md +0 -165
  135. package/skills/ae-project-semantic/references/recommendation-quality.md +0 -68
package/README.md CHANGED
@@ -127,7 +127,7 @@ The table covers every current root command individually. Use `ae-cli --help` fo
127
127
  | Engage | `engage-workbench` | Engage workbench and to-do management |
128
128
  | Engage | `engage-query` | Engage queries, asynchronous exports, and artifact management |
129
129
  | DataOps | `dataops_repo` | Data-warehouse and data-source management |
130
- | DataOps | `dataops_datatable` | Data-table lifecycle management |
130
+ | DataOps | `dataops_datatable` | Table/view lifecycle management, including recycling, recycle-bin discovery, and permanent deletion |
131
131
  | DataOps | `dataops_flow` | Development flows, scheduling, and backfill-job management |
132
132
  | DataOps | `dataops_ide` | IDE queries and result downloads |
133
133
  | DataOps | `dataops_integration` | Data-integration task management |
@@ -177,6 +177,10 @@ For scripts and agents, use the non-interactive subcommands:
177
177
  ```bash
178
178
  ae-cli auth login --host https://host-a.example.com
179
179
  ae-cli auth status --host https://host-a.example.com
180
+ # Import a CLI token copied from External Access Management (hidden prompt)
181
+ ae-cli auth set-token --host https://host-a.example.com
182
+ # Non-interactive input for local scripts or tests
183
+ printf '%s' "$AE_CLI_TOKEN" | ae-cli auth set-token --host https://host-a.example.com --token-stdin
180
184
  # For the uncommon case where one Host needs multiple accounts
181
185
  ae-cli auth login --host https://host-a.example.com --add
182
186
  ae-cli auth list --host https://host-a.example.com
@@ -196,6 +200,8 @@ ae-cli config remove pre-production --yes
196
200
 
197
201
  A regular `auth login` keeps the simple one-Host/one-account behavior and replaces credentials for that Host; use `--add` only when other accounts must be retained. `auth status` reports CLI-token state only. A new backend can also provide account identity and expiration; when an older backend does not support `/validate`, the CLI preserves the historical behavior of trusting the stored CLI token and omits `account` instead of returning null fields.
198
202
 
203
+ `auth set-token` is for local use with a `cli_` token copied from External Access Management. It prompts without echo by default; `--token-stdin` supports non-interactive local testing. The CLI validates the token against the target Host before replacing the stored credential, encrypts it in the existing per-Host vault, and never includes the value in command output. Add `--add` to retain other accounts for the same Host.
204
+
199
205
  The new CLI persists only CLI tokens, never access or refresh tokens. Multiple accounts live in an encrypted V1 vault while the active account is projected into the historical file shape for automatic downgrades. When the CLI upgrades again, it reconciles login, switch, or logout changes made by the old CLI.
200
206
 
201
207
  Login uses a cross-platform device-code flow. Use `--no-browser` when the environment cannot open a browser.
package/README.zh.md CHANGED
@@ -131,7 +131,7 @@ ae-cli capability list --domain analysis --jq '.data.capabilities[] | .id'
131
131
  | 运营 | `engage-workbench` | 运营工作台和待办管理 |
132
132
  | 运营 | `engage-query` | 运营查询、异步导出和产物管理 |
133
133
  | DataOps | `dataops_repo` | 数仓和数据源管理 |
134
- | DataOps | `dataops_datatable` | 数据表生命周期管理 |
134
+ | DataOps | `dataops_datatable` | 表/视图生命周期管理,包括回收、查询回收站与彻底删除 |
135
135
  | DataOps | `dataops_flow` | 开发流程、调度和补数作业管理 |
136
136
  | DataOps | `dataops_ide` | IDE 查询及结果下载 |
137
137
  | DataOps | `dataops_integration` | 数据集成任务管理 |
@@ -181,6 +181,10 @@ Gateway 命令遵循 [Capability 命令收录规则](docs/capability-command-adm
181
181
  ```bash
182
182
  ae-cli auth login --host https://host-a.example.com
183
183
  ae-cli auth status --host https://host-a.example.com
184
+ # 导入从“外部访问管理”复制的 CLI Token(隐藏输入)
185
+ ae-cli auth set-token --host https://host-a.example.com
186
+ # 本地脚本或测试使用非交互输入
187
+ printf '%s' "$AE_CLI_TOKEN" | ae-cli auth set-token --host https://host-a.example.com --token-stdin
184
188
  # 少量需要同一 Host 多账号的场景
185
189
  ae-cli auth login --host https://host-a.example.com --add
186
190
  ae-cli auth list --host https://host-a.example.com
@@ -200,6 +204,8 @@ ae-cli config remove pre-production --yes
200
204
 
201
205
  普通 `auth login` 保持一个 Host 一个账号的简单语义,并替换该 Host 已保存的账号;仅在需要时使用 `--add` 保留其他账号。`auth status` 只展示 CLI Token 状态;新版后端可同时返回账号和到期时间,旧版后端不支持 `/validate` 时仍按历史行为信任本地 CLI Token,且不会输出含 null 字段的 `account`。
202
206
 
207
+ `auth set-token` 用于在本地导入从“外部访问管理”复制的 `cli_` Token。默认使用不回显的隐藏输入,`--token-stdin` 支持本地测试等非交互场景。CLI 会先向目标 Host 校验 Token,再替换本地凭证,并写入现有的按 Host 加密凭据库;命令输出不会包含 Token。需要保留同一 Host 的其他账号时增加 `--add`。
208
+
203
209
  新版 CLI 只持久化 CLI Token,不保存 access token 或 refresh token。多账号保存在加密的 V1 凭据文件中,同时维护旧文件格式的当前账号投影,保证 CLI 自动降级后仍可登录;再次升级时会合并旧 CLI 对投影的登录、切换或退出变更。
204
210
 
205
211
  登录使用跨平台设备码流程。当前环境无法打开浏览器时,可使用 `--no-browser`。
@@ -12,16 +12,18 @@ import {
12
12
  } from "./chunk-E2JKXMVO.js";
13
13
  import {
14
14
  resolveHost
15
- } from "./chunk-JOCDD4ON.js";
15
+ } from "./chunk-N4BLPJC7.js";
16
16
  import {
17
17
  printError,
18
18
  printOutput,
19
19
  runHostCompatCheck
20
- } from "./chunk-DX5CDO34.js";
20
+ } from "./chunk-BW7JUDEI.js";
21
21
  import {
22
22
  CliTokenValidationUnavailableError,
23
+ CredentialStoreUnreadableError,
23
24
  SecureStoreAuthError,
24
25
  activateCredential,
26
+ assertCredentialsReadable,
25
27
  clearAllCredentials,
26
28
  clearCliTokenCache,
27
29
  getActiveCredential,
@@ -31,17 +33,17 @@ import {
31
33
  saveCredential,
32
34
  updateCredentialMetadata,
33
35
  validateCliTokenOnServer
34
- } from "./chunk-7XGFSUOM.js";
36
+ } from "./chunk-DU72X2IO.js";
35
37
  import {
36
38
  getFallbackCliToken,
37
39
  loadConfig,
38
40
  normalizeUrl,
39
41
  saveConfig
40
- } from "./chunk-7FTTULED.js";
42
+ } from "./chunk-IG3DYEIR.js";
41
43
  import {
42
44
  PermissionError,
43
45
  logger
44
- } from "./chunk-MAPZ7VB6.js";
46
+ } from "./chunk-YVGXGTD6.js";
45
47
 
46
48
  // src/core/device-auth.ts
47
49
  import { execFileSync } from "child_process";
@@ -277,12 +279,77 @@ async function validateExistingCliToken(host, cliToken) {
277
279
  logger.warn(`auth status: ${error.message}; trusting the stored CLI token for compatibility`);
278
280
  return { valid: true, trusted: true, details: {} };
279
281
  }
282
+ if (error instanceof PermissionError) {
283
+ printError("permission", error.message, error.hint, error.code);
284
+ process.exitCode = 1;
285
+ return { valid: false, trusted: false, details: {} };
286
+ }
280
287
  if (!(error instanceof SecureStoreAuthError)) throw error;
281
- printError("auth", error.message);
288
+ printError(
289
+ "auth",
290
+ error.message,
291
+ `Run: ae-cli auth logout --host ${host}, then ae-cli auth login --host ${host}`
292
+ );
282
293
  process.exitCode = 1;
283
294
  return { valid: false, trusted: false, details: {} };
284
295
  }
285
296
  }
297
+ async function readCliTokenFromStdin() {
298
+ let value = "";
299
+ process.stdin.setEncoding("utf8");
300
+ for await (const chunk of process.stdin) value += chunk;
301
+ return value.trim();
302
+ }
303
+ function promptHiddenCliToken() {
304
+ const stdin = process.stdin;
305
+ const stderr = process.stderr;
306
+ if (!stdin.isTTY || !stderr.isTTY) {
307
+ return Promise.reject(new Error(
308
+ "Interactive CLI token input requires a TTY. Pipe the token and add --token-stdin."
309
+ ));
310
+ }
311
+ return new Promise((resolve, reject) => {
312
+ let value = "";
313
+ let settled = false;
314
+ stdin.setRawMode(true);
315
+ stdin.resume();
316
+ stdin.setEncoding("utf8");
317
+ stderr.write("CLI token: ");
318
+ function cleanup() {
319
+ if (settled) return;
320
+ settled = true;
321
+ stdin.setRawMode(false);
322
+ stdin.pause();
323
+ stdin.removeListener("data", onData);
324
+ stderr.write("\n");
325
+ }
326
+ function onData(chunk) {
327
+ for (const key of chunk) {
328
+ if (key === "\r" || key === "\n") {
329
+ cleanup();
330
+ resolve(value.trim());
331
+ return;
332
+ }
333
+ if (key === "" || key === "\x1B") {
334
+ cleanup();
335
+ reject(new Error("CLI token input cancelled."));
336
+ return;
337
+ }
338
+ if (key === "") {
339
+ cleanup();
340
+ resolve(value.trim());
341
+ return;
342
+ }
343
+ if (key === "\x7F" || key === "\b") {
344
+ value = value.slice(0, -1);
345
+ continue;
346
+ }
347
+ if (key >= " ") value += key;
348
+ }
349
+ }
350
+ stdin.on("data", onData);
351
+ });
352
+ }
286
353
  function activateHostAfterLogin(host, explicitHostOverride) {
287
354
  if (!explicitHostOverride) return;
288
355
  const normalized = normalizeUrl(host);
@@ -369,11 +436,13 @@ async function switchActiveAccount(program, opts) {
369
436
  account: accountOutput(selected.account)
370
437
  }, program.opts().format || "json");
371
438
  } catch (error) {
439
+ if (error instanceof CredentialStoreUnreadableError) throw error;
372
440
  printError("auth", error.message);
373
441
  process.exitCode = 1;
374
442
  }
375
443
  }
376
444
  async function persistDeviceTokens(host, tokens, options = {}) {
445
+ assertCredentialsReadable(host);
377
446
  const cliToken = await mintCliToken(host, tokens.access_token);
378
447
  let validation = {};
379
448
  try {
@@ -401,6 +470,24 @@ async function persistDeviceTokens(host, tokens, options = {}) {
401
470
  await runHostCompatCheck(getLocalCliPackageInfo(), host);
402
471
  return saved;
403
472
  }
473
+ async function persistManualCliToken(host, cliToken, options = {}) {
474
+ assertCredentialsReadable(host);
475
+ const validation = await validateCliTokenOnServer(host, cliToken);
476
+ let saved;
477
+ try {
478
+ saved = saveCredential(host, {
479
+ cliToken,
480
+ ...validation.account ? { account: validation.account } : {},
481
+ ...validation.cliTokenExpiresAt ? { cliTokenExpiresAt: validation.cliTokenExpiresAt } : {}
482
+ }, options);
483
+ } catch (error) {
484
+ clearCliTokenCache(host);
485
+ throw error;
486
+ }
487
+ clearCliTokenCache(host);
488
+ await runHostCompatCheck(getLocalCliPackageInfo(), host);
489
+ return saved;
490
+ }
404
491
  function loginSummary(host, credential) {
405
492
  return {
406
493
  authenticated: true,
@@ -408,13 +495,30 @@ function loginSummary(host, credential) {
408
495
  ...credential.account ? { account: accountOutput(credential.account) } : {}
409
496
  };
410
497
  }
498
+ function manualTokenSummary(host, credential) {
499
+ return {
500
+ authenticated: true,
501
+ host,
502
+ source: "manual-cli-token",
503
+ ...credential.account ? { account: accountOutput(credential.account) } : {},
504
+ cli_token: {
505
+ status: "valid",
506
+ ...credential.cliTokenExpiresAt ? { expires_at: credential.cliTokenExpiresAt } : {}
507
+ }
508
+ };
509
+ }
411
510
  function resolveLoginTeClaudeBase(host) {
412
511
  const base = host.replace(/\/+$/, "");
413
512
  const basePath = process.env.TE_CLAUDE_BASE_PATH || "/agent";
414
513
  return base.endsWith(basePath) ? base : base + basePath;
415
514
  }
416
515
  function registerAuth(program) {
417
- const auth = program.command("auth").description("Manage authentication or switch the active account interactively").action(async () => {
516
+ const auth = program.command("auth").description("Manage authentication or switch the active account interactively").hook("preAction", (_command, actionCommand) => {
517
+ if (["login", "set-token"].includes(actionCommand.name())) {
518
+ const host = resolveAuthHost(program, actionCommand.opts());
519
+ if (host) assertCredentialsReadable(host);
520
+ }
521
+ }).action(async () => {
418
522
  await switchActiveAccount(program, {});
419
523
  });
420
524
  auth.command("login").description("Log in to AE; by default replaces this host credentials, --add keeps existing accounts").option("--host <url>", HOST_OPTION_DESC).option("--add", "Add another account for the host and keep existing accounts").option("--no-browser", "Do not auto-open the browser; only print the authorization URL").option("--no-wait", "Print device authorization data and exit; resume with --device-code").option("--device-code <code>", "Resume a split-flow login with the given device code").action(async (opts) => {
@@ -465,6 +569,7 @@ function registerAuth(program) {
465
569
  emit("Login successful! CLI token saved securely.");
466
570
  await printOutput(loginSummary(host, saved), format);
467
571
  } catch (error) {
572
+ if (error instanceof CredentialStoreUnreadableError) throw error;
468
573
  if (error instanceof DeviceFlowUnsupportedError) {
469
574
  printError("auth", error.message, "Upgrade the AE server to a version that supports device login.");
470
575
  process.exit(1);
@@ -477,6 +582,59 @@ function registerAuth(program) {
477
582
  process.exit(1);
478
583
  }
479
584
  });
585
+ auth.command("set-token").description("Validate and securely store a CLI token copied from External Access Management").option("--host <url>", HOST_OPTION_DESC).option("--token-stdin", "Read the CLI token from stdin instead of prompting").option("--add", "Add another account for the host and keep existing accounts").action(async (opts) => {
586
+ const explicitHost = getExplicitAuthHostOverride(program, opts);
587
+ const host = resolveAuthHost(program, opts);
588
+ if (!host) {
589
+ printError("config", "No AE host configured.", missingAeHostHint());
590
+ process.exitCode = 1;
591
+ return;
592
+ }
593
+ let cliToken;
594
+ try {
595
+ cliToken = opts.tokenStdin ? await readCliTokenFromStdin() : await promptHiddenCliToken();
596
+ } catch (error) {
597
+ printError("validation", error.message);
598
+ process.exitCode = 1;
599
+ return;
600
+ }
601
+ if (!/^cli_\S+$/.test(cliToken)) {
602
+ printError(
603
+ "validation",
604
+ "Invalid CLI token format.",
605
+ "Copy a current CLI token from External Access Management; the value must start with cli_."
606
+ );
607
+ process.exitCode = 1;
608
+ return;
609
+ }
610
+ try {
611
+ const saved = await persistManualCliToken(host, cliToken, { add: opts.add });
612
+ activateHostAfterLogin(host, explicitHost);
613
+ process.stderr.write(`[ae-cli] CLI token verified and saved securely for ${host}
614
+ `);
615
+ await printOutput(manualTokenSummary(host, saved), program.opts().format || "json");
616
+ } catch (error) {
617
+ if (error instanceof CredentialStoreUnreadableError) throw error;
618
+ if (error instanceof PermissionError) {
619
+ printError("permission", error.message, error.hint, error.code);
620
+ } else if (error instanceof SecureStoreAuthError) {
621
+ printError(
622
+ "auth",
623
+ error.message,
624
+ "Copy a current CLI token from External Access Management and try again."
625
+ );
626
+ } else if (error instanceof CliTokenValidationUnavailableError) {
627
+ printError(
628
+ "api",
629
+ error.message,
630
+ "Verify the AE host and deployment, then retry. The token was not saved."
631
+ );
632
+ } else {
633
+ printError("api", error.message);
634
+ }
635
+ process.exitCode = 1;
636
+ }
637
+ });
480
638
  auth.command("status").description("Show the active CLI-token authentication status for a host").option("--host <url>", HOST_OPTION_DESC).action(async (opts) => {
481
639
  const host = resolveAuthHost(program, opts);
482
640
  if (!host) {
@@ -569,6 +727,8 @@ export {
569
727
  activateHostAfterLogin,
570
728
  buildAccountSelectionItems,
571
729
  persistDeviceTokens,
730
+ persistManualCliToken,
731
+ promptHiddenCliToken,
572
732
  registerAuth,
573
733
  resolveLoginTeClaudeBase
574
734
  };
@@ -11,7 +11,7 @@ import {
11
11
  inspectCapabilityWithEnvelope,
12
12
  listCapabilitiesWithEnvelope,
13
13
  validateCapabilityWithEnvelope
14
- } from "./chunk-HFGZGYCG.js";
14
+ } from "./chunk-QYXDJOLA.js";
15
15
  import {
16
16
  findGatewayDomain,
17
17
  listCapabilityDiscoveryPrefixes,
@@ -20,23 +20,24 @@ import {
20
20
  } from "./chunk-KPQY44JQ.js";
21
21
  import {
22
22
  resolveHost
23
- } from "./chunk-JOCDD4ON.js";
23
+ } from "./chunk-N4BLPJC7.js";
24
24
  import {
25
25
  printError,
26
26
  printOutput,
27
27
  withOutputMetadata
28
- } from "./chunk-DX5CDO34.js";
28
+ } from "./chunk-BW7JUDEI.js";
29
29
  import "./chunk-Y74WTIKJ.js";
30
30
  import {
31
+ CredentialStoreUnreadableError,
31
32
  SecureStoreAuthError
32
- } from "./chunk-7XGFSUOM.js";
33
+ } from "./chunk-DU72X2IO.js";
33
34
  import {
34
35
  safeJsonParse
35
- } from "./chunk-7FTTULED.js";
36
+ } from "./chunk-IG3DYEIR.js";
36
37
  import {
37
38
  CliValidationError,
38
39
  PermissionError
39
- } from "./chunk-MAPZ7VB6.js";
40
+ } from "./chunk-YVGXGTD6.js";
40
41
 
41
42
  // src/commands/capability/index.ts
42
43
  import * as readline from "readline";
@@ -367,6 +368,10 @@ function printCapabilityError(error, host) {
367
368
  );
368
369
  return;
369
370
  }
371
+ if (error instanceof CredentialStoreUnreadableError) {
372
+ printError("config", error.message, error.hint, error.code);
373
+ return;
374
+ }
370
375
  if (error instanceof SecureStoreAuthError) {
371
376
  printError("auth", error.message, "Run: ae-cli auth login");
372
377
  return;
@@ -3,16 +3,16 @@ import {
3
3
  dryRunCapability,
4
4
  executeCapabilityWithEnvelope,
5
5
  validateCapability
6
- } from "./chunk-HFGZGYCG.js";
6
+ } from "./chunk-QYXDJOLA.js";
7
7
  import {
8
8
  resolveGatewayDomain
9
9
  } from "./chunk-KPQY44JQ.js";
10
10
  import {
11
11
  withOutputMetadata
12
- } from "./chunk-DX5CDO34.js";
12
+ } from "./chunk-BW7JUDEI.js";
13
13
  import {
14
14
  CliValidationError
15
- } from "./chunk-MAPZ7VB6.js";
15
+ } from "./chunk-YVGXGTD6.js";
16
16
 
17
17
  // src/core/definition-intent.ts
18
18
  import { createHash } from "crypto";
@@ -1,17 +1,17 @@
1
1
  import { createRequire as __createRequire } from 'node:module'; const require = __createRequire(import.meta.url);
2
2
  import {
3
3
  CapabilityGatewayError
4
- } from "./chunk-HFGZGYCG.js";
4
+ } from "./chunk-QYXDJOLA.js";
5
5
  import {
6
6
  SecureStoreAuthError,
7
7
  getCliToken
8
- } from "./chunk-7XGFSUOM.js";
8
+ } from "./chunk-DU72X2IO.js";
9
9
  import {
10
10
  safeJsonParse
11
- } from "./chunk-7FTTULED.js";
11
+ } from "./chunk-IG3DYEIR.js";
12
12
  import {
13
13
  PermissionError
14
- } from "./chunk-MAPZ7VB6.js";
14
+ } from "./chunk-YVGXGTD6.js";
15
15
 
16
16
  // src/core/mcp-access.ts
17
17
  function buildUrl(host, path, params = {}) {
@@ -5,14 +5,14 @@ import {
5
5
  require_node,
6
6
  require_process_nextick_args,
7
7
  require_util
8
- } from "./chunk-V2NUHPXF.js";
8
+ } from "./chunk-GK7WDY7E.js";
9
9
  import {
10
10
  __commonJS,
11
11
  __esm,
12
12
  __export,
13
13
  __require,
14
14
  __toCommonJS
15
- } from "./chunk-MAPZ7VB6.js";
15
+ } from "./chunk-YVGXGTD6.js";
16
16
 
17
17
  // node_modules/readdir-glob/node_modules/minimatch/lib/path.js
18
18
  var require_path = __commonJS({
@@ -1,16 +1,16 @@
1
1
  import { createRequire as __createRequire } from 'node:module'; const require = __createRequire(import.meta.url);
2
2
  import {
3
3
  peekCliToken
4
- } from "./chunk-7XGFSUOM.js";
4
+ } from "./chunk-DU72X2IO.js";
5
5
  import {
6
6
  getActiveHost,
7
7
  getConfigDir,
8
8
  isAeSandboxRuntime,
9
9
  normalizeUrl
10
- } from "./chunk-7FTTULED.js";
10
+ } from "./chunk-IG3DYEIR.js";
11
11
  import {
12
12
  logger
13
- } from "./chunk-MAPZ7VB6.js";
13
+ } from "./chunk-YVGXGTD6.js";
14
14
 
15
15
  // src/core/version-sync.ts
16
16
  import { spawnSync } from "child_process";
@@ -579,31 +579,91 @@ function autoSyncDirection(current, expected) {
579
579
  return "switch";
580
580
  }
581
581
 
582
- // src/core/compat-check.ts
582
+ // src/core/feature-config.ts
583
+ import crypto from "crypto";
583
584
  import fs2 from "fs";
584
585
  import path2 from "path";
586
+ var FEATURE_TTL_MS = 24 * 60 * 60 * 1e3;
587
+ var UNAVAILABLE_TTL_MS = 5 * 60 * 1e3;
588
+ function cachePath() {
589
+ return path2.join(getConfigDir(), "feature-config.json");
590
+ }
591
+ function cacheKey(host, token) {
592
+ const fingerprint = crypto.createHash("sha256").update(token).digest("hex");
593
+ return `${normalizeUrl(host)}#${fingerprint}`;
594
+ }
595
+ function readStore() {
596
+ try {
597
+ const value = JSON.parse(fs2.readFileSync(cachePath(), "utf8"));
598
+ return value?.entries && typeof value.entries === "object" ? value : { entries: {} };
599
+ } catch {
600
+ return { entries: {} };
601
+ }
602
+ }
603
+ function writeStore(store) {
604
+ const target = cachePath();
605
+ const temp = `${target}.${process.pid}.${crypto.randomBytes(6).toString("hex")}.tmp`;
606
+ try {
607
+ fs2.mkdirSync(path2.dirname(target), { recursive: true });
608
+ fs2.writeFileSync(temp, JSON.stringify(store), { encoding: "utf8", mode: 384 });
609
+ fs2.renameSync(temp, target);
610
+ fs2.chmodSync(target, 384);
611
+ } catch {
612
+ try {
613
+ fs2.rmSync(temp, { force: true });
614
+ } catch {
615
+ }
616
+ }
617
+ }
618
+ function remember(host, token, entry) {
619
+ const store = readStore();
620
+ store.entries[cacheKey(host, token)] = entry;
621
+ writeStore(store);
622
+ }
623
+ function rememberKbAutoDiscoveryFeature(host, token, enabled) {
624
+ remember(host, token, { enabled, available: true, fetchedAt: Date.now() });
625
+ }
626
+ async function resolveKbAutoDiscoveryFeature(host, token, fetchRemote) {
627
+ const entry = readStore().entries[cacheKey(host, token)];
628
+ const ttl = entry?.available ? FEATURE_TTL_MS : UNAVAILABLE_TTL_MS;
629
+ if (entry && Date.now() >= entry.fetchedAt && Date.now() - entry.fetchedAt < ttl) {
630
+ return { enabled: entry.enabled, source: entry.available ? "cache" : "unavailable" };
631
+ }
632
+ const remote = await fetchRemote().catch(() => null);
633
+ if (!remote) {
634
+ remember(host, token, { enabled: false, available: false, fetchedAt: Date.now() });
635
+ return { enabled: false, source: "unavailable" };
636
+ }
637
+ const enabled = remote.projectSemanticKbAutoDiscovery === true;
638
+ remember(host, token, { enabled, available: true, fetchedAt: Date.now() });
639
+ return { enabled, source: "remote" };
640
+ }
641
+
642
+ // src/core/compat-check.ts
643
+ import fs3 from "fs";
644
+ import path3 from "path";
585
645
  var CHECK_INTERVAL_MS = 24 * 60 * 60 * 1e3;
586
646
  var FETCH_TIMEOUT_MS = 3e3;
587
647
  var CLI_CONFIG_PATH = "/v1/ta/cli/config";
588
648
  function cacheFilePath() {
589
- return path2.join(getConfigDir(), "compat-check.json");
649
+ return path3.join(getConfigDir(), "compat-check.json");
590
650
  }
591
- function readStore() {
651
+ function readStore2() {
592
652
  try {
593
653
  const file = cacheFilePath();
594
- if (!fs2.existsSync(file)) return { hosts: {} };
595
- const raw = JSON.parse(fs2.readFileSync(file, "utf8"));
654
+ if (!fs3.existsSync(file)) return { hosts: {} };
655
+ const raw = JSON.parse(fs3.readFileSync(file, "utf8"));
596
656
  if (!raw || typeof raw !== "object" || !raw.hosts) return { hosts: {} };
597
657
  return raw;
598
658
  } catch {
599
659
  return { hosts: {} };
600
660
  }
601
661
  }
602
- function writeStore(store) {
662
+ function writeStore2(store) {
603
663
  try {
604
664
  const dir = getConfigDir();
605
- if (!fs2.existsSync(dir)) fs2.mkdirSync(dir, { recursive: true });
606
- fs2.writeFileSync(cacheFilePath(), JSON.stringify(store, null, 2));
665
+ if (!fs3.existsSync(dir)) fs3.mkdirSync(dir, { recursive: true });
666
+ fs3.writeFileSync(cacheFilePath(), JSON.stringify(store, null, 2));
607
667
  } catch {
608
668
  }
609
669
  }
@@ -663,7 +723,8 @@ async function fetchCliConfig(host, cliToken) {
663
723
  const aeCliVersion = versions.aeCliVersion ?? versions.ae_cli_version ?? null;
664
724
  return {
665
725
  clusterVersion: clusterVersion?.trim() || null,
666
- aeCliVersion: aeCliVersion?.trim() || null
726
+ aeCliVersion: aeCliVersion?.trim() || null,
727
+ ...typeof data.features?.projectSemanticKbAutoDiscovery === "boolean" ? { projectSemanticKbAutoDiscovery: data.features.projectSemanticKbAutoDiscovery } : {}
667
728
  };
668
729
  } catch {
669
730
  return null;
@@ -684,7 +745,7 @@ function getPendingUpdateNotice() {
684
745
  return pendingUpdateNotice;
685
746
  }
686
747
  function getCachedCompatForHost(host) {
687
- return readStore().hosts[hostKey(host)];
748
+ return readStore2().hosts[hostKey(host)];
688
749
  }
689
750
  function formatCapabilityMissCompatHint(host) {
690
751
  if (shouldSkipCompatCheck()) return void 0;
@@ -725,7 +786,7 @@ function setUpdateNotice(pkg, expected, cluster, verdict, state, stage, message)
725
786
  async function refreshAndMaybeNotify(host, pkg, allowAutoSync) {
726
787
  const token = peekCliToken(host);
727
788
  if (!token) return { status: "continue" };
728
- const store = readStore();
789
+ const store = readStore2();
729
790
  const key = hostKey(host);
730
791
  const existing = store.hosts[key];
731
792
  let expected = existing?.expectedVersion;
@@ -733,6 +794,7 @@ async function refreshAndMaybeNotify(host, pkg, allowAutoSync) {
733
794
  let fetchedAt = existing?.lastFetchedAt;
734
795
  if (isStale(existing)) {
735
796
  const remote = await fetchCliConfig(host, token);
797
+ if (remote) rememberKbAutoDiscoveryFeature(host, token, remote.projectSemanticKbAutoDiscovery ?? false);
736
798
  if (!remote?.aeCliVersion) {
737
799
  return { status: "continue" };
738
800
  }
@@ -747,7 +809,7 @@ async function refreshAndMaybeNotify(host, pkg, allowAutoSync) {
747
809
  lastFetchedAt: fetchedAt,
748
810
  lastNotifiedAt: existing?.lastNotifiedAt
749
811
  };
750
- writeStore(store);
812
+ writeStore2(store);
751
813
  }
752
814
  if (!expected) return { status: "continue" };
753
815
  let verdict = evaluateCompat(pkg.version, expected, cluster);
@@ -770,6 +832,7 @@ async function refreshAndMaybeNotify(host, pkg, allowAutoSync) {
770
832
  const canAutoSync = allowAutoSync && isPublicAeCliPackage(pkg.name) && isAutoSyncTargetEligible(expected);
771
833
  if (canAutoSync) {
772
834
  const confirmed = await fetchCliConfig(host, token);
835
+ if (confirmed) rememberKbAutoDiscoveryFeature(host, token, confirmed.projectSemanticKbAutoDiscovery ?? false);
773
836
  if (confirmed?.aeCliVersion) {
774
837
  expected = confirmed.aeCliVersion;
775
838
  cluster = confirmed.clusterVersion ?? cluster ?? "";
@@ -783,7 +846,7 @@ async function refreshAndMaybeNotify(host, pkg, allowAutoSync) {
783
846
  lastFetchedAt: (/* @__PURE__ */ new Date()).toISOString()
784
847
  };
785
848
  store.hosts[key] = entry;
786
- writeStore(store);
849
+ writeStore2(store);
787
850
  if (verdict.kind === "ok" && !pendingSkills) {
788
851
  pendingHostCompatNotice = void 0;
789
852
  pendingUpdateNotice = void 0;
@@ -823,7 +886,7 @@ async function refreshAndMaybeNotify(host, pkg, allowAutoSync) {
823
886
  setUpdateNotice(pkg, expected, cluster || "", verdict, state, result.stage, failure);
824
887
  entry.lastNotifiedAt = (/* @__PURE__ */ new Date()).toISOString();
825
888
  store.hosts[key] = entry;
826
- writeStore(store);
889
+ writeStore2(store);
827
890
  return { status: "continue" };
828
891
  }
829
892
  }
@@ -837,7 +900,7 @@ async function refreshAndMaybeNotify(host, pkg, allowAutoSync) {
837
900
  pendingHostCompatNotice = void 0;
838
901
  pendingUpdateNotice = void 0;
839
902
  store.hosts[key] = entry;
840
- writeStore(store);
903
+ writeStore2(store);
841
904
  return { status: "continue" };
842
905
  }
843
906
  setUpdateNotice(
@@ -852,7 +915,7 @@ async function refreshAndMaybeNotify(host, pkg, allowAutoSync) {
852
915
  printNotice(notice);
853
916
  entry.lastNotifiedAt = (/* @__PURE__ */ new Date()).toISOString();
854
917
  store.hosts[key] = entry;
855
- writeStore(store);
918
+ writeStore2(store);
856
919
  return { status: "continue" };
857
920
  }
858
921
  async function runHostCompatCheck(pkg, hostOverride, argv = process.argv) {
@@ -1044,6 +1107,8 @@ export {
1044
1107
  buildVersionInstallPlan,
1045
1108
  friendlyVersionSyncFailure,
1046
1109
  installVersion,
1110
+ resolveKbAutoDiscoveryFeature,
1111
+ shouldSkipAutoSync,
1047
1112
  fetchCliConfig,
1048
1113
  getCachedCompatForHost,
1049
1114
  formatCapabilityMissCompatHint,