@thinkingai/ae-cli 6.1.23 → 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.
- package/README.md +7 -1
- package/README.zh.md +7 -1
- package/dist/{auth-XZNXFRJS.js → auth-LHM7NQPR.js} +167 -7
- package/dist/{capability-FYTU3X6L.js → capability-SJI5KOCK.js} +11 -6
- package/dist/{chunk-CCS66K4K.js → chunk-2FJM4HRV.js} +3 -3
- package/dist/{chunk-57RRFUEZ.js → chunk-5XRQ3CZR.js} +4 -4
- package/dist/{chunk-EQ255HKO.js → chunk-7WZACOAI.js} +2 -2
- package/dist/{chunk-DX5CDO34.js → chunk-BW7JUDEI.js} +84 -19
- package/dist/{chunk-7XGFSUOM.js → chunk-DU72X2IO.js} +271 -76
- package/dist/{chunk-V2NUHPXF.js → chunk-GK7WDY7E.js} +1 -1
- package/dist/{chunk-7FTTULED.js → chunk-IG3DYEIR.js} +4 -1
- package/dist/{chunk-HBGADCKA.js → chunk-KJDOTPYU.js} +3 -3
- package/dist/{chunk-4NRCTUZJ.js → chunk-KS4DE3MX.js} +4 -4
- package/dist/{chunk-JOCDD4ON.js → chunk-N4BLPJC7.js} +1 -1
- package/dist/{chunk-HFGZGYCG.js → chunk-QYXDJOLA.js} +252 -6
- package/dist/{chunk-DVMLWQD4.js → chunk-SO5LKIWP.js} +2 -2
- package/dist/{chunk-VYXXOKYS.js → chunk-XKIW3QMF.js} +7 -4
- package/dist/{chunk-MAPZ7VB6.js → chunk-YVGXGTD6.js} +13 -0
- package/dist/{community-report-client-CU22W53K.js → community-report-client-6VJDDMJJ.js} +1 -1
- package/dist/{config-XO3LI3SA.js → config-XQWOPDHN.js} +25 -6
- package/dist/{context-IFJI3LIT.js → context-M3HDGEIR.js} +4 -4
- package/dist/{data-integration-HNGUKFIC.js → data-integration-XBTCGXQT.js} +6 -6
- package/dist/index.js +78 -41
- package/dist/{local-data-upload-client-GTRIT64F.js → local-data-upload-client-3P7NIVQ4.js} +1 -1
- package/dist/{memory-QGPSNCQS.js → memory-6APEB2JB.js} +4 -4
- package/dist/{metadata-DI5BMYFU.js → metadata-JRYKNUS5.js} +7 -7
- package/dist/{model-RNPQXIBI.js → model-ZS7HVGKN.js} +4 -4
- package/dist/{personal-semantic-preference-5C3WUXFI.js → personal-semantic-preference-IDE2GE5T.js} +8 -6
- package/dist/project-semantic-36KOCYN7.js +356 -0
- package/dist/{sync-O45NXEQY.js → sync-EQLSTUS7.js} +7 -7
- package/dist/{te-agent-K5MSPNHJ.js → te-agent-Z3HCTKR7.js} +348 -55
- package/dist/{te-analysis-AISWCOOZ.js → te-analysis-5ZZ6YHVH.js} +940 -144
- package/dist/{te-community-4OYU3BDA.js → te-community-Z7JACGF3.js} +3 -3
- package/dist/{te-dataops-NFIPB6FX.js → te-dataops-F7GQOIS6.js} +644 -276
- package/dist/{te-engage-BAM3GBFX.js → te-engage-RNRMYDO3.js} +6 -6
- package/dist/{te-experiment-GUTZXZ5Z.js → te-experiment-BTAC2UNK.js} +6 -6
- package/dist/{te-kb-3TS73NO6.js → te-kb-QJLJEX5K.js} +323 -181
- package/dist/{te-system-STMHLS5J.js → te-system-IXC43QHZ.js} +6 -6
- package/dist/{te-team-3I5AOX3N.js → te-team-BIZIKIHZ.js} +6 -6
- package/dist/{update-RZXLPCRH.js → update-W2SGQNKT.js} +4 -4
- package/package.json +11 -4
- package/skills/ae-agent/SKILL.md +9 -4
- package/skills/ae-agent/references/notification.md +40 -0
- package/skills/ae-analysis/SKILL.md +44 -21
- package/skills/ae-analysis/references/adhoc_export.md +1 -1
- package/skills/ae-analysis/references/adhoc_run.md +1 -1
- package/skills/ae-analysis/references/agent_review_submit_to_page.md +3 -1
- package/skills/ae-analysis/references/ai_models/event.md +6 -1
- package/skills/ae-analysis/references/ai_models/funnel.md +7 -1
- package/skills/ae-analysis/references/ai_models/heat_map.md +23 -0
- package/skills/ae-analysis/references/ai_models/interval.md +24 -0
- package/skills/ae-analysis/references/ai_models/path.md +20 -0
- package/skills/ae-analysis/references/ai_models/prop_analysis.md +2 -0
- package/skills/ae-analysis/references/ai_models/rank_list.md +30 -0
- package/skills/ae-analysis/references/ai_models/retention.md +45 -1
- package/skills/ae-analysis/references/ai_models/revenue.md +20 -2
- package/skills/ae-analysis/references/ai_models/session.md +76 -0
- package/skills/ae-analysis/references/ai_models/tag.md +2 -0
- package/skills/ae-analysis/references/ai_models.md +76 -6
- package/skills/ae-analysis/references/analysis_data_retrieval.md +4 -0
- package/skills/ae-analysis/references/analysis_drilldown_contract.md +4 -1
- package/skills/ae-analysis/references/asset_batch_info_export.md +10 -0
- package/skills/ae-analysis/references/asset_batch_sql_export.md +13 -1
- package/skills/ae-analysis/references/asset_export.md +12 -1
- package/skills/ae-analysis/references/asset_list.md +1 -0
- package/skills/ae-analysis/references/asset_search.md +11 -5
- package/skills/ae-analysis/references/bi_panel_list.md +1 -1
- package/skills/ae-analysis/references/catalog_list.md +1 -1
- package/skills/ae-analysis/references/collaboration.md +48 -0
- package/skills/ae-analysis/references/command_index.md +19 -17
- package/skills/ae-analysis/references/dashboard_list.md +4 -4
- package/skills/ae-analysis/references/dashboard_report_data_export.md +2 -0
- package/skills/ae-analysis/references/drilldown_session_details_run.md +41 -0
- package/skills/ae-analysis/references/event_export.md +3 -1
- package/skills/ae-analysis/references/governance_recommendation_auto_review.md +77 -0
- package/skills/ae-analysis/references/governance_recommendation_export.md +11 -0
- package/skills/ae-analysis/references/metadata_resolution.md +3 -3
- package/skills/ae-analysis/references/metric_export.md +3 -1
- package/skills/ae-analysis/references/metric_list.md +1 -1
- package/skills/ae-analysis/references/operation_record_export.md +10 -0
- package/skills/ae-analysis/references/personal_semantic_preference_add.md +2 -2
- package/skills/ae-analysis/references/personal_semantic_preference_get.md +4 -4
- package/skills/ae-analysis/references/personal_semantic_preference_list.md +4 -4
- package/skills/ae-analysis/references/project_semantic_knowledge_wiki.md +30 -12
- package/skills/ae-analysis/references/project_semantic_knowledge_wiki_plan_schema.md +59 -0
- package/skills/ae-analysis/references/property_export.md +3 -1
- package/skills/ae-analysis/references/report_create.md +5 -1
- package/skills/ae-analysis/references/report_data_export.md +6 -0
- package/skills/ae-analysis/references/report_get.md +2 -0
- package/skills/ae-analysis/references/report_list.md +5 -5
- package/skills/ae-analysis/references/report_update.md +7 -1
- package/skills/ae-analysis/references/sql_table_columns.md +4 -4
- package/skills/ae-analysis/references/sql_table_list.md +5 -5
- package/skills/ae-analysis/references/user_cluster_models.md +8 -0
- package/skills/ae-analysis/references/user_tag_create.md +7 -1
- package/skills/ae-analysis/references/user_tag_get.md +1 -1
- package/skills/ae-analysis/references/user_tag_models.md +18 -2
- package/skills/ae-analysis/references/user_tag_refresh.md +1 -1
- package/skills/ae-analysis/references/user_tag_update.md +2 -2
- package/skills/ae-analysis/scripts/project-semantic-knowledge-wiki/build-project-semantic-wiki.mjs +337 -12
- package/skills/ae-analysis/scripts/project-semantic-knowledge-wiki/default-compile-rules.md +8 -3
- package/skills/ae-analysis/scripts/project-semantic-knowledge-wiki/generate-build-ir.mjs +284 -24
- package/skills/ae-analysis/scripts/project-semantic-knowledge-wiki/package-wiki-source-zip.mjs +185 -22
- package/skills/ae-analysis/scripts/project-semantic-knowledge-wiki/precompiled-source.mjs +46 -2
- package/skills/ae-capability/SKILL.md +63 -1
- package/skills/ae-capability/references/collaboration.md +48 -0
- package/skills/ae-community/SKILL.md +5 -1
- package/skills/ae-community/references/collaboration.md +48 -0
- package/skills/ae-data-integration/SKILL.md +4 -0
- package/skills/ae-data-integration/references/collaboration.md +48 -0
- package/skills/ae-data-integration-helper/references/cpp_server_sdk_faq.md +2 -2
- package/skills/ae-data-integration-helper/references/logbus2_parser_plugin.md +6 -6
- package/skills/ae-data-integration-helper/references/sdk_log_guide.md +4 -4
- package/skills/ae-dataops/SKILL.md +54 -74
- package/skills/ae-dataops/references/collaboration.md +48 -0
- package/skills/ae-dataops/references/dataops-backfill.md +23 -18
- package/skills/ae-dataops/references/dataops-flow-create.md +74 -23
- package/skills/ae-dataops/references/dataops-flow-monitor.md +45 -13
- package/skills/ae-dataops/references/dataops-integration.md +57 -30
- package/skills/ae-dataops/references/dataops-query.md +21 -4
- package/skills/ae-dataops/references/dataops-table.md +143 -11
- package/skills/ae-engage/SKILL.md +21 -6
- package/skills/ae-engage/references/add-channel.md +3 -3
- package/skills/ae-engage/references/channel-mgmt.md +3 -3
- package/skills/ae-engage/references/collaboration.md +48 -0
- package/skills/ae-engage/references/common-metric.md +2 -2
- package/skills/ae-engage/references/save-task.md +2 -2
- package/skills/ae-engage/references/scene-config-channel.md +4 -4
- package/skills/ae-generate-tracking-code/SKILL.md +1 -1
- package/skills/ae-generate-tracking-plan/SKILL.md +4 -0
- package/skills/ae-generate-tracking-plan/references/collaboration.md +48 -0
- package/skills/ae-kb/SKILL.md +9 -1
- package/skills/ae-kb/references/collaboration.md +48 -0
- package/skills/ae-kb/references/schema-import.md +30 -0
- package/skills/ae-kb-discovery/SKILL.md +7 -2
- package/skills/ae-kb-discovery/references/collaboration.md +48 -0
- package/skills/ae-metadata/SKILL.md +20 -12
- package/skills/ae-metadata/references/collaboration.md +48 -0
- package/dist/project-semantic-3LF6Q6JZ.js +0 -1119
- package/skills/ae-project-semantic/SKILL.md +0 -193
- package/skills/ae-project-semantic/references/query-routing-v5.md +0 -165
- 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` |
|
|
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-
|
|
15
|
+
} from "./chunk-N4BLPJC7.js";
|
|
16
16
|
import {
|
|
17
17
|
printError,
|
|
18
18
|
printOutput,
|
|
19
19
|
runHostCompatCheck
|
|
20
|
-
} from "./chunk-
|
|
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-
|
|
36
|
+
} from "./chunk-DU72X2IO.js";
|
|
35
37
|
import {
|
|
36
38
|
getFallbackCliToken,
|
|
37
39
|
loadConfig,
|
|
38
40
|
normalizeUrl,
|
|
39
41
|
saveConfig
|
|
40
|
-
} from "./chunk-
|
|
42
|
+
} from "./chunk-IG3DYEIR.js";
|
|
41
43
|
import {
|
|
42
44
|
PermissionError,
|
|
43
45
|
logger
|
|
44
|
-
} from "./chunk-
|
|
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(
|
|
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").
|
|
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-
|
|
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-
|
|
23
|
+
} from "./chunk-N4BLPJC7.js";
|
|
24
24
|
import {
|
|
25
25
|
printError,
|
|
26
26
|
printOutput,
|
|
27
27
|
withOutputMetadata
|
|
28
|
-
} from "./chunk-
|
|
28
|
+
} from "./chunk-BW7JUDEI.js";
|
|
29
29
|
import "./chunk-Y74WTIKJ.js";
|
|
30
30
|
import {
|
|
31
|
+
CredentialStoreUnreadableError,
|
|
31
32
|
SecureStoreAuthError
|
|
32
|
-
} from "./chunk-
|
|
33
|
+
} from "./chunk-DU72X2IO.js";
|
|
33
34
|
import {
|
|
34
35
|
safeJsonParse
|
|
35
|
-
} from "./chunk-
|
|
36
|
+
} from "./chunk-IG3DYEIR.js";
|
|
36
37
|
import {
|
|
37
38
|
CliValidationError,
|
|
38
39
|
PermissionError
|
|
39
|
-
} from "./chunk-
|
|
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-
|
|
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-
|
|
12
|
+
} from "./chunk-BW7JUDEI.js";
|
|
13
13
|
import {
|
|
14
14
|
CliValidationError
|
|
15
|
-
} from "./chunk-
|
|
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-
|
|
4
|
+
} from "./chunk-QYXDJOLA.js";
|
|
5
5
|
import {
|
|
6
6
|
SecureStoreAuthError,
|
|
7
7
|
getCliToken
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-DU72X2IO.js";
|
|
9
9
|
import {
|
|
10
10
|
safeJsonParse
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-IG3DYEIR.js";
|
|
12
12
|
import {
|
|
13
13
|
PermissionError
|
|
14
|
-
} from "./chunk-
|
|
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-
|
|
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-
|
|
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-
|
|
4
|
+
} from "./chunk-DU72X2IO.js";
|
|
5
5
|
import {
|
|
6
6
|
getActiveHost,
|
|
7
7
|
getConfigDir,
|
|
8
8
|
isAeSandboxRuntime,
|
|
9
9
|
normalizeUrl
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-IG3DYEIR.js";
|
|
11
11
|
import {
|
|
12
12
|
logger
|
|
13
|
-
} from "./chunk-
|
|
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/
|
|
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
|
|
649
|
+
return path3.join(getConfigDir(), "compat-check.json");
|
|
590
650
|
}
|
|
591
|
-
function
|
|
651
|
+
function readStore2() {
|
|
592
652
|
try {
|
|
593
653
|
const file = cacheFilePath();
|
|
594
|
-
if (!
|
|
595
|
-
const raw = JSON.parse(
|
|
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
|
|
662
|
+
function writeStore2(store) {
|
|
603
663
|
try {
|
|
604
664
|
const dir = getConfigDir();
|
|
605
|
-
if (!
|
|
606
|
-
|
|
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
|
|
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 =
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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,
|