@thinkingai/ae-cli 6.1.27 → 6.1.29
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 +52 -6
- package/README.zh.md +52 -6
- package/bin/ae-cli.js +5 -0
- package/bin/runtime-capabilities.json +5 -0
- package/cli-installation-guide.md +24 -3
- package/dist/{auth-WA7YGGRT.js → auth-OBQ5KVQM.js} +175 -45
- package/dist/{automation-VAAQBM7Y.js → automation-NAR5DDGL.js} +94 -38
- package/dist/{capability-GAAYJ3IQ.js → capability-LFSVNI5B.js} +57 -28
- package/dist/chunk-2UW3Y463.js +2289 -0
- package/dist/{chunk-VZZNLV3I.js → chunk-3SDHJOCR.js} +68 -18
- package/dist/chunk-6HAUVWOQ.js +132 -0
- package/dist/{chunk-5XJYLEVC.js → chunk-72NJKS7O.js} +4 -4
- package/dist/{chunk-Q5US7JC5.js → chunk-7JAVT5TK.js} +3 -3
- package/dist/{chunk-7KU2WNQE.js → chunk-CVCTFLSO.js} +37 -15
- package/dist/{chunk-GHXZK54S.js → chunk-H3K5UGYC.js} +41 -13
- package/dist/{chunk-OP44TT4H.js → chunk-IN7KKL6K.js} +4 -2
- package/dist/{chunk-S6M42KND.js → chunk-JEUXDY3B.js} +1 -1
- package/dist/{chunk-ZL7SGNIA.js → chunk-JNVVJ273.js} +58 -46
- package/dist/chunk-N6XBLRB7.js +105 -0
- package/dist/{chunk-AP7YP2NX.js → chunk-OAWPT7VP.js} +2 -2
- package/dist/{chunk-AQJPNWZF.js → chunk-PWXDWMCW.js} +7 -7
- package/dist/{chunk-CT7QDJS6.js → chunk-QVRIDN42.js} +2 -2
- package/dist/chunk-QZLRHGVH.js +222 -0
- package/dist/{chunk-RPBOAQQQ.js → chunk-QZUVLFNR.js} +1 -1
- package/dist/{chunk-3YVEAZUN.js → chunk-RJHGDWSC.js} +32 -21
- package/dist/{chunk-MWIA43UJ.js → chunk-VCZE3IWO.js} +10 -8
- package/dist/chunk-YVG6QD3V.js +233 -0
- package/dist/{chunk-WNGFSIOB.js → chunk-Z3Q2AEIN.js} +237 -86
- package/dist/{community-report-client-PEERQCX2.js → community-report-client-TJVCLZ3K.js} +1 -1
- package/dist/compat-check-CII6B74E.js +32 -0
- package/dist/{config-JOD5DOPE.js → config-YZ6O2UQ2.js} +40 -7
- package/dist/{context-NGVFPCBK.js → context-F6FCGTF3.js} +4 -4
- package/dist/{data-integration-BCLQFTGU.js → data-integration-6UAZO4GG.js} +207 -24
- package/dist/evaluation-4LO2O4AF.js +3714 -0
- package/dist/index.js +352 -81
- package/dist/{local-data-upload-client-TWMHFLUA.js → local-data-upload-client-KCMG6J62.js} +1 -1
- package/dist/{memory-CQKH2JAV.js → memory-HHPX3NF2.js} +6 -6
- package/dist/{metadata-NR3PHR23.js → metadata-TIFY24LW.js} +17 -9
- package/dist/{model-VX5M2CJ6.js → model-7UHGWYVR.js} +4 -4
- package/dist/{personal-semantic-preference-2RAI36P3.js → personal-semantic-preference-WKJEGPTM.js} +7 -6
- package/dist/{project-semantic-3BUGP3ZM.js → project-semantic-EIQVZNHW.js} +11 -10
- package/dist/{sync-RZIAV37C.js → sync-RV3OPCTI.js} +8 -7
- package/dist/{te-agent-AORRE2FM.js → te-agent-5ENVZJUH.js} +757 -94
- package/dist/{te-analysis-GP7DSQ7Q.js → te-analysis-USIK6ZZG.js} +584 -100
- package/dist/{te-community-42M7ICDO.js → te-community-WE2UU4XV.js} +722 -228
- package/dist/{te-dataops-BNKNZ4F2.js → te-dataops-XNMO7MBF.js} +9 -6
- package/dist/{te-engage-2CO6LRCX.js → te-engage-6C3HCFQR.js} +13 -12
- package/dist/{te-experiment-652CLXMU.js → te-experiment-LVTRI3QK.js} +55 -21
- package/dist/{te-kb-ULATOTQ3.js → te-kb-TUPGMVBY.js} +409 -85
- package/dist/{te-system-UGHVKBVV.js → te-system-YM657FKO.js} +6 -6
- package/dist/{te-team-YA6SNOJ3.js → te-team-G4VEJJNL.js} +64 -41
- package/dist/{things-DTCOQIQB.js → things-22KQWC23.js} +7 -7
- package/dist/{update-ESNYKUVR.js → update-XX4ILU7X.js} +11 -7
- package/dist/{workspace-JEOHKFPX.js → workspace-LYDAP647.js} +6 -6
- package/package.json +26 -11
- package/skills/ae-agent/SKILL.md +22 -3
- package/skills/ae-agent/references/command_index.md +8 -0
- package/skills/ae-agent/references/resource-package.md +57 -0
- package/skills/ae-analysis/SKILL.md +23 -10
- package/skills/ae-analysis/references/adhoc_export.md +1 -1
- package/skills/ae-analysis/references/agent_review_preflight.md +55 -10
- package/skills/ae-analysis/references/agent_review_priorities_comparisons.md +5 -3
- package/skills/ae-analysis/references/agent_review_submit_to_page.md +60 -24
- package/skills/ae-analysis/references/ai_models/event.md +58 -2
- package/skills/ae-analysis/references/ai_models/rank_list.md +1 -0
- package/skills/ae-analysis/references/ai_models/retention.md +2 -0
- package/skills/ae-analysis/references/ai_models/revenue.md +2 -0
- package/skills/ae-analysis/references/analysis_data_export.md +11 -1
- package/skills/ae-analysis/references/asset_batch_info_export.md +2 -2
- package/skills/ae-analysis/references/asset_batch_sql_export.md +2 -2
- package/skills/ae-analysis/references/asset_export.md +1 -1
- package/skills/ae-analysis/references/bi_panel_page_data_export.md +1 -1
- package/skills/ae-analysis/references/check_export.md +1 -1
- package/skills/ae-analysis/references/command_index.md +39 -26
- package/skills/ae-analysis/references/dashboard_report_data_export.md +2 -0
- package/skills/ae-analysis/references/dashboard_report_get.md +6 -2
- package/skills/ae-analysis/references/dashboard_report_update.md +24 -5
- package/skills/ae-analysis/references/feedback_submit.md +1 -1
- package/skills/ae-analysis/references/governance_recommendation_export.md +40 -18
- package/skills/ae-analysis/references/governance_recommendation_run_update.md +13 -0
- package/skills/ae-analysis/references/live_data_export.md +1 -1
- package/skills/ae-analysis/references/metric_create.md +29 -0
- package/skills/ae-analysis/references/metric_get.md +2 -0
- package/skills/ae-analysis/references/metric_update.md +2 -0
- package/skills/ae-analysis/references/operation_record_export.md +1 -1
- package/skills/ae-analysis/references/plan_change_log_export.md +1 -1
- package/skills/ae-analysis/references/plan_export.md +1 -1
- package/skills/ae-analysis/references/project_info_get.md +4 -0
- package/skills/ae-analysis/references/project_member_group_add_members.md +35 -0
- package/skills/ae-analysis/references/project_member_group_create.md +25 -0
- package/skills/ae-analysis/references/project_member_group_delete.md +34 -0
- package/skills/ae-analysis/references/project_member_group_list.md +29 -0
- package/skills/ae-analysis/references/project_member_group_members.md +28 -0
- package/skills/ae-analysis/references/project_member_group_remove_members.md +35 -0
- package/skills/ae-analysis/references/project_member_group_rename.md +26 -0
- package/skills/ae-analysis/references/project_semantic_knowledge_wiki.md +9 -1
- package/skills/ae-analysis/references/project_semantic_knowledge_wiki_plan_schema.md +6 -1
- package/skills/ae-analysis/references/report_data_export.md +1 -1
- package/skills/ae-analysis/references/scenario_append.md +31 -0
- package/skills/ae-analysis/references/scenario_begin.md +11 -0
- package/skills/ae-analysis/references/scenario_collect.md +43 -0
- package/skills/ae-analysis/references/scenario_evaluation.md +18 -0
- package/skills/ae-analysis/references/scenario_get.md +15 -0
- package/skills/ae-analysis/references/scenario_list.md +64 -0
- package/skills/ae-analysis/scripts/project-semantic-knowledge-wiki/build-project-semantic-wiki.mjs +73 -4
- package/skills/ae-analysis/scripts/project-semantic-knowledge-wiki/company-kb.mjs +14 -1
- package/skills/ae-analysis/scripts/project-semantic-knowledge-wiki/default-compile-schema.md +5 -1
- package/skills/ae-analysis/scripts/project-semantic-knowledge-wiki/execution-contract.mjs +173 -0
- package/skills/ae-analysis/scripts/project-semantic-knowledge-wiki/generate-build-ir.mjs +109 -64
- package/skills/ae-automation/SKILL.md +2 -2
- package/skills/ae-automation/references/cli.md +18 -1
- package/skills/ae-capability/SKILL.md +7 -3
- package/skills/ae-community/SKILL.md +77 -27
- package/skills/ae-community/references/community-analyzing-theme-comment.md +10 -8
- package/skills/ae-community/references/community-data-quality.md +68 -0
- package/skills/ae-community/references/community-query-evidence.md +85 -0
- package/skills/ae-community/references/community-scenario-capabilities.md +137 -0
- package/skills/ae-community/references/community-weekly-report.md +6 -3
- package/skills/ae-community/references/get_channel_info.md +7 -4
- package/skills/ae-community/references/get_comment_tag_analysis.md +3 -3
- package/skills/ae-community/references/get_comments_summary.md +4 -4
- package/skills/ae-community/references/get_corpus_tags.md +3 -3
- package/skills/ae-community/references/get_daily_summary.md +3 -3
- package/skills/ae-community/references/get_hot_topics.md +3 -3
- package/skills/ae-community/references/get_livestream_analysis.md +3 -3
- package/skills/ae-community/references/get_livestream_detail.md +4 -4
- package/skills/ae-community/references/get_livestream_list.md +3 -3
- package/skills/ae-community/references/get_livestream_overview.md +3 -3
- package/skills/ae-community/references/get_livestream_room_metrics.md +3 -3
- package/skills/ae-community/references/get_livestream_rooms.md +3 -3
- package/skills/ae-community/references/get_overview_metrics.md +3 -3
- package/skills/ae-community/references/get_post_detail.md +4 -4
- package/skills/ae-community/references/get_risk_content.md +5 -5
- package/skills/ae-community/references/get_sentiment_overview.md +4 -4
- package/skills/ae-community/references/get_tag_trends.md +3 -3
- package/skills/ae-community/references/get_topic_detail.md +3 -3
- package/skills/ae-community/references/list_sources.md +28 -0
- package/skills/ae-community/references/list_spaces.md +39 -0
- package/skills/ae-community/references/search_posts.md +21 -7
- package/skills/ae-data-integration/SKILL.md +6 -4
- package/skills/ae-data-integration/references/error-handling.md +1 -0
- package/skills/ae-data-integration/references/handoff.md +1 -1
- package/skills/ae-data-integration/references/sink-upload.md +11 -0
- package/skills/ae-data-integration/references/source-inspect.md +2 -1
- package/skills/ae-data-integration/references/transform.md +1 -1
- package/skills/ae-data-integration/references/ue-mapping.md +1 -1
- package/skills/ae-evaluation/SKILL.md +83 -0
- package/skills/ae-evaluation/references/access-and-members.md +55 -0
- package/skills/ae-evaluation/references/connections.md +78 -0
- package/skills/ae-evaluation/references/datasets.md +57 -0
- package/skills/ae-evaluation/references/evaluators.md +81 -0
- package/skills/ae-evaluation/references/files.md +33 -0
- package/skills/ae-evaluation/references/integrations.md +39 -0
- package/skills/ae-evaluation/references/runs.md +160 -0
- package/skills/ae-evaluation/references/schedules.md +31 -0
- package/skills/ae-experiment/SKILL.md +7 -1
- package/skills/ae-experiment/references/manage_experiment.md +18 -1
- package/skills/ae-experiment/references/query_experiment_detail.md +7 -0
- package/skills/ae-experiment/references/save_experiment.md +76 -2
- package/skills/ae-experiment/references/save_submit_experiment.md +7 -0
- package/skills/ae-kb/SKILL.md +33 -7
- package/skills/ae-kb/references/publication.md +81 -0
- package/skills/ae-kb/references/query-workflow.md +14 -1
- package/skills/ae-metadata/SKILL.md +3 -2
- package/skills/ae-metadata/references/metadata_data_table_download.md +7 -1
- package/skills/ae-metadata/references/metadata_data_table_get.md +37 -0
- package/skills/ae-system/SKILL.md +1 -1
- package/skills/ae-team/SKILL.md +2 -2
- package/skills/ae-team/references/run-start.md +1 -0
- package/skills/ae-team/references/run-watch.md +7 -5
- package/skills/ae-things/SKILL.md +53 -51
- package/skills/ae-things/references/cli.md +56 -54
- package/skills/ae-things-progress/SKILL.md +20 -20
- package/skills/ae-things-review/SKILL.md +19 -19
- package/skills/ae-workspace/SKILL.md +1 -1
- package/dist/chunk-6VNIR4AP.js +0 -1422
- package/dist/chunk-CI24BDR2.js +0 -43
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
import { createRequire as __createRequire } from 'node:module'; const require = __createRequire(import.meta.url);
|
|
2
|
+
import {
|
|
3
|
+
invalidateBusinessSkillSynchronization,
|
|
4
|
+
refreshEnvironmentAfterLogin
|
|
5
|
+
} from "./chunk-6HAUVWOQ.js";
|
|
2
6
|
import {
|
|
3
7
|
MultiselectCancelled,
|
|
4
8
|
promptSingleSelect
|
|
@@ -9,13 +13,15 @@ import {
|
|
|
9
13
|
} from "./chunk-6ZIQV5GW.js";
|
|
10
14
|
import {
|
|
11
15
|
resolveHost
|
|
12
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-IN7KKL6K.js";
|
|
13
17
|
import {
|
|
14
|
-
getLocalCliPackageInfo,
|
|
15
18
|
printError,
|
|
16
|
-
printOutput
|
|
19
|
+
printOutput
|
|
20
|
+
} from "./chunk-QZLRHGVH.js";
|
|
21
|
+
import {
|
|
22
|
+
getLocalCliPackageInfo,
|
|
17
23
|
runHostCompatCheck
|
|
18
|
-
} from "./chunk-
|
|
24
|
+
} from "./chunk-2UW3Y463.js";
|
|
19
25
|
import {
|
|
20
26
|
CliTokenValidationUnavailableError,
|
|
21
27
|
CredentialStoreUnreadableError,
|
|
@@ -31,25 +37,54 @@ import {
|
|
|
31
37
|
saveCredential,
|
|
32
38
|
updateCredentialMetadata,
|
|
33
39
|
validateCliTokenOnServer
|
|
34
|
-
} from "./chunk-
|
|
40
|
+
} from "./chunk-H3K5UGYC.js";
|
|
35
41
|
import {
|
|
36
42
|
getFallbackCliToken,
|
|
37
43
|
loadConfig,
|
|
38
|
-
normalizeUrl,
|
|
39
44
|
saveConfig
|
|
40
|
-
} from "./chunk-
|
|
45
|
+
} from "./chunk-JNVVJ273.js";
|
|
41
46
|
import {
|
|
47
|
+
ExternalCliTokenError,
|
|
42
48
|
PermissionError,
|
|
43
|
-
logger
|
|
44
|
-
|
|
49
|
+
logger,
|
|
50
|
+
normalizeUrl,
|
|
51
|
+
readExternalCliToken
|
|
52
|
+
} from "./chunk-Z3Q2AEIN.js";
|
|
45
53
|
|
|
46
54
|
// src/core/device-auth.ts
|
|
47
55
|
import { execFileSync } from "child_process";
|
|
56
|
+
function deviceApiPath(protocol, action) {
|
|
57
|
+
return protocol === "uba" ? `/v1/ta/cli/auth/device/${action}` : `/api/auth/device/${action}`;
|
|
58
|
+
}
|
|
59
|
+
function ubaAuthorizationDenial(code) {
|
|
60
|
+
if (code === "CLI_ACCESS_DISABLED") return {
|
|
61
|
+
code,
|
|
62
|
+
message: "CLI access is disabled for this account.",
|
|
63
|
+
hint: "Contact your administrator."
|
|
64
|
+
};
|
|
65
|
+
if (code === "ACCOUNT_UNAVAILABLE") return {
|
|
66
|
+
code,
|
|
67
|
+
message: "This account is unavailable.",
|
|
68
|
+
hint: "Contact your administrator or sign in with an active account."
|
|
69
|
+
};
|
|
70
|
+
if (code === "ORIGIN_DENIED") return {
|
|
71
|
+
code,
|
|
72
|
+
message: "Authorization must be approved from the trusted platform page.",
|
|
73
|
+
hint: "Open the verification URL on the configured AE host and sign in there."
|
|
74
|
+
};
|
|
75
|
+
return {
|
|
76
|
+
code: "AUTHORIZATION_DENIED",
|
|
77
|
+
message: "Device authorization was denied.",
|
|
78
|
+
hint: "Check your account status with your administrator before requesting authorization again."
|
|
79
|
+
};
|
|
80
|
+
}
|
|
48
81
|
var DeviceFlowUnsupportedError = class extends Error {
|
|
49
|
-
constructor() {
|
|
82
|
+
constructor(httpStatus) {
|
|
50
83
|
super("This AE server does not support device code login (it may be an older server version).");
|
|
84
|
+
this.httpStatus = httpStatus;
|
|
51
85
|
this.name = "DeviceFlowUnsupportedError";
|
|
52
86
|
}
|
|
87
|
+
httpStatus;
|
|
53
88
|
};
|
|
54
89
|
function looksLikeMissingEndpoint(status, contentType, body) {
|
|
55
90
|
if (status === 404) return true;
|
|
@@ -83,29 +118,46 @@ function openBrowser(url, _execFile) {
|
|
|
83
118
|
exec("xdg-open", [url], { timeout: 5e3 });
|
|
84
119
|
return true;
|
|
85
120
|
} catch (e) {
|
|
86
|
-
logger.warn(`openBrowser: failed to open ${safeLogUrl}
|
|
121
|
+
logger.warn(`openBrowser: failed to open ${safeLogUrl}`);
|
|
87
122
|
return false;
|
|
88
123
|
}
|
|
89
124
|
}
|
|
90
|
-
async function authorizeDevice(host) {
|
|
125
|
+
async function authorizeDevice(host, protocol = "legacy") {
|
|
91
126
|
const base = host.replace(/\/+$/, "");
|
|
92
|
-
const url = `${base}
|
|
127
|
+
const url = `${base}${deviceApiPath(protocol, "authorize")}`;
|
|
93
128
|
let resp;
|
|
94
129
|
try {
|
|
95
130
|
resp = await fetch(url, {
|
|
96
131
|
method: "POST",
|
|
97
|
-
headers: {
|
|
132
|
+
headers: {
|
|
133
|
+
"Content-Type": "application/json",
|
|
134
|
+
...protocol === "uba" ? { "X-CLI-Verification-Origin": new URL(host).origin } : {}
|
|
135
|
+
},
|
|
136
|
+
redirect: "error",
|
|
137
|
+
signal: AbortSignal.timeout(1e4)
|
|
98
138
|
});
|
|
99
139
|
} catch (e) {
|
|
100
|
-
throw new Error(
|
|
140
|
+
throw new Error("Device authorize request failed. Check the AE host and network, then retry.");
|
|
101
141
|
}
|
|
102
142
|
const contentType = resp.headers.get("content-type");
|
|
103
143
|
const text = await resp.text().catch(() => "");
|
|
104
144
|
if (looksLikeMissingEndpoint(resp.status, contentType, text)) {
|
|
105
|
-
throw new DeviceFlowUnsupportedError();
|
|
145
|
+
throw new DeviceFlowUnsupportedError(resp.status);
|
|
106
146
|
}
|
|
107
147
|
if (!resp.ok) {
|
|
108
|
-
|
|
148
|
+
if (resp.status === 403) {
|
|
149
|
+
if (protocol === "uba") {
|
|
150
|
+
let code;
|
|
151
|
+
try {
|
|
152
|
+
code = JSON.parse(text)?.code;
|
|
153
|
+
} catch {
|
|
154
|
+
}
|
|
155
|
+
const denial = ubaAuthorizationDenial(code);
|
|
156
|
+
throw new PermissionError(denial.message, denial.code, denial.hint);
|
|
157
|
+
}
|
|
158
|
+
throw new PermissionError("CLI authorization is not allowed.", "CLI_ACCESS_DISABLED", "Contact your administrator.");
|
|
159
|
+
}
|
|
160
|
+
throw new Error(`Device authorize returned HTTP ${resp.status}`);
|
|
109
161
|
}
|
|
110
162
|
let body;
|
|
111
163
|
try {
|
|
@@ -113,23 +165,28 @@ async function authorizeDevice(host) {
|
|
|
113
165
|
} catch {
|
|
114
166
|
throw new Error("Device authorize returned invalid JSON");
|
|
115
167
|
}
|
|
116
|
-
if (!body.device_code || !body.user_code) {
|
|
168
|
+
if (typeof body.device_code !== "string" || !body.device_code || typeof body.user_code !== "string" || !body.user_code) {
|
|
117
169
|
throw new Error("Device authorize response missing required fields");
|
|
118
170
|
}
|
|
171
|
+
if (protocol === "uba" && (!Number.isInteger(body.expires_in) || body.expires_in < 1 || body.expires_in > 300 || !Number.isInteger(body.interval) || body.interval < 1 || body.interval > body.expires_in)) {
|
|
172
|
+
throw new Error("UBA authorization returned invalid polling limits. Check the server deployment.");
|
|
173
|
+
}
|
|
119
174
|
return body;
|
|
120
175
|
}
|
|
121
|
-
async function pollDeviceToken(host, deviceCode) {
|
|
176
|
+
async function pollDeviceToken(host, deviceCode, protocol = "legacy") {
|
|
122
177
|
const base = host.replace(/\/+$/, "");
|
|
123
|
-
const url = `${base}
|
|
178
|
+
const url = `${base}${deviceApiPath(protocol, "token")}`;
|
|
124
179
|
let resp;
|
|
125
180
|
try {
|
|
126
181
|
resp = await fetch(url, {
|
|
127
182
|
method: "POST",
|
|
128
183
|
headers: { "Content-Type": "application/json" },
|
|
129
|
-
body: JSON.stringify({ device_code: deviceCode })
|
|
184
|
+
body: JSON.stringify({ device_code: deviceCode }),
|
|
185
|
+
redirect: "error",
|
|
186
|
+
signal: AbortSignal.timeout(1e4)
|
|
130
187
|
});
|
|
131
188
|
} catch (e) {
|
|
132
|
-
return { status: "error", message:
|
|
189
|
+
return { status: "error", message: "Network error while polling authorization." };
|
|
133
190
|
}
|
|
134
191
|
if (resp.status === 200) {
|
|
135
192
|
let body;
|
|
@@ -138,7 +195,7 @@ async function pollDeviceToken(host, deviceCode) {
|
|
|
138
195
|
} catch {
|
|
139
196
|
return { status: "error", message: "Token response is not valid JSON" };
|
|
140
197
|
}
|
|
141
|
-
if (!body.access_token) {
|
|
198
|
+
if (typeof body.access_token !== "string" || !body.access_token) {
|
|
142
199
|
return { status: "error", message: "Token response missing access_token" };
|
|
143
200
|
}
|
|
144
201
|
return { status: "approved", tokens: body };
|
|
@@ -154,7 +211,13 @@ async function pollDeviceToken(host, deviceCode) {
|
|
|
154
211
|
if (err === "authorization_pending") return { status: "pending" };
|
|
155
212
|
if (err === "slow_down") return { status: "slow_down" };
|
|
156
213
|
if (err === "expired_token") return { status: "expired" };
|
|
157
|
-
|
|
214
|
+
if (err === "access_denied") return {
|
|
215
|
+
status: "denied",
|
|
216
|
+
code: "AUTHORIZATION_DENIED",
|
|
217
|
+
message: "Device authorization was denied.",
|
|
218
|
+
hint: "Run ae-cli auth login again only when you want to request authorization."
|
|
219
|
+
};
|
|
220
|
+
return { status: "error", message: "Token endpoint returned an unrecognized authorization error." };
|
|
158
221
|
}
|
|
159
222
|
if (resp.status === 403) {
|
|
160
223
|
let errorBody = {};
|
|
@@ -162,6 +225,7 @@ async function pollDeviceToken(host, deviceCode) {
|
|
|
162
225
|
errorBody = await resp.json();
|
|
163
226
|
} catch {
|
|
164
227
|
}
|
|
228
|
+
if (protocol === "uba") return { status: "denied", ...ubaAuthorizationDenial(errorBody.code) };
|
|
165
229
|
return {
|
|
166
230
|
status: "denied",
|
|
167
231
|
code: errorBody.code ?? "CLI_ACCESS_DISABLED",
|
|
@@ -176,7 +240,10 @@ async function pollDeviceToken(host, deviceCode) {
|
|
|
176
240
|
}
|
|
177
241
|
return { status: "error", message: `Unexpected HTTP ${resp.status} from token endpoint` };
|
|
178
242
|
}
|
|
179
|
-
function buildVerificationUrl(host, userCode) {
|
|
243
|
+
function buildVerificationUrl(host, userCode, protocol = "legacy") {
|
|
244
|
+
if (protocol === "uba") {
|
|
245
|
+
return `${host.replace(/\/+$/, "")}/#/cli/device-activate?user_code=${encodeURIComponent(userCode)}`;
|
|
246
|
+
}
|
|
180
247
|
return `${host.replace(/\/+$/, "")}/device-activate?user_code=${encodeURIComponent(userCode)}`;
|
|
181
248
|
}
|
|
182
249
|
async function pollDeviceFlow(host, deviceCode, options = {}, onStatus) {
|
|
@@ -190,7 +257,7 @@ async function pollDeviceFlow(host, deviceCode, options = {}, onStatus) {
|
|
|
190
257
|
while (Date.now() < deadline) {
|
|
191
258
|
await sleep(intervalMs);
|
|
192
259
|
pollCount++;
|
|
193
|
-
const result = await pollDeviceToken(host, deviceCode);
|
|
260
|
+
const result = await pollDeviceToken(host, deviceCode, options.protocol);
|
|
194
261
|
if (result.status === "approved") {
|
|
195
262
|
emit(`Authorization successful! (polled ${pollCount} time(s))`);
|
|
196
263
|
return result.tokens;
|
|
@@ -237,9 +304,9 @@ async function runDeviceFlow(host, options = {}, onStatus) {
|
|
|
237
304
|
if (onStatus) onStatus(msg);
|
|
238
305
|
};
|
|
239
306
|
emit("Requesting authorization code from server...");
|
|
240
|
-
const auth = await authorizeDevice(host);
|
|
307
|
+
const auth = options.authorization ?? await authorizeDevice(host, options.protocol);
|
|
241
308
|
const userCode = auth.user_code;
|
|
242
|
-
const verifyUrl = buildVerificationUrl(host, userCode);
|
|
309
|
+
const verifyUrl = buildVerificationUrl(host, userCode, options.protocol);
|
|
243
310
|
const expiresIn = auth.expires_in ?? 300;
|
|
244
311
|
emit("");
|
|
245
312
|
emit(`Verification code: ${userCode}`);
|
|
@@ -255,21 +322,47 @@ async function runDeviceFlow(host, options = {}, onStatus) {
|
|
|
255
322
|
}
|
|
256
323
|
emit("");
|
|
257
324
|
}
|
|
258
|
-
return pollDeviceFlow(host, auth.device_code, { intervalMs: (auth.interval ?? 5) * 1e3, expiresIn }, onStatus);
|
|
325
|
+
return pollDeviceFlow(host, auth.device_code, { intervalMs: (auth.interval ?? 5) * 1e3, expiresIn, protocol: options.protocol }, onStatus);
|
|
259
326
|
}
|
|
260
327
|
function sleep(ms) {
|
|
261
328
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
262
329
|
}
|
|
263
330
|
|
|
331
|
+
// src/core/login-device-flow.ts
|
|
332
|
+
function resolveLegacyLoginBase(host) {
|
|
333
|
+
const base = host.replace(/\/+$/, "");
|
|
334
|
+
const basePath = process.env.TE_CLAUDE_BASE_PATH || "/agent";
|
|
335
|
+
return base.endsWith(basePath) ? base : base + basePath;
|
|
336
|
+
}
|
|
337
|
+
function resolveDeviceSessionRoute(host, deviceCode) {
|
|
338
|
+
return deviceCode.startsWith("uba_") ? { baseUrl: host, protocol: "uba" } : { baseUrl: resolveLegacyLoginBase(host), protocol: "legacy" };
|
|
339
|
+
}
|
|
340
|
+
async function authorizeLoginDevice(host) {
|
|
341
|
+
try {
|
|
342
|
+
const authorization = await authorizeDevice(host, "uba");
|
|
343
|
+
if (!/^uba_[A-Za-z0-9_-]+$/.test(authorization.device_code)) {
|
|
344
|
+
throw new Error("UBA authorization returned an unsupported device-code format. Check the server deployment.");
|
|
345
|
+
}
|
|
346
|
+
return { baseUrl: host, protocol: "uba", authorization };
|
|
347
|
+
} catch (error) {
|
|
348
|
+
if (!(error instanceof DeviceFlowUnsupportedError) || error.httpStatus !== 404) throw error;
|
|
349
|
+
const baseUrl = resolveLegacyLoginBase(host);
|
|
350
|
+
return { baseUrl, protocol: "legacy", authorization: await authorizeDevice(baseUrl) };
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
|
|
264
354
|
// src/commands/auth.ts
|
|
265
355
|
var HOST_OPTION_DESC = "Override active AE host URL (e.g., https://ta.thinkingdata.cn)";
|
|
356
|
+
function shellArgument(value) {
|
|
357
|
+
return `'${value.replace(/'/g, `'\\''`)}'`;
|
|
358
|
+
}
|
|
266
359
|
function getExplicitAuthHostOverride(program, opts) {
|
|
267
360
|
return opts.host || program.opts().host;
|
|
268
361
|
}
|
|
269
362
|
function resolveAuthHost(program, opts) {
|
|
270
363
|
return resolveHost(getExplicitAuthHostOverride(program, opts));
|
|
271
364
|
}
|
|
272
|
-
async function validateExistingCliToken(host, cliToken) {
|
|
365
|
+
async function validateExistingCliToken(host, cliToken, external = false) {
|
|
273
366
|
try {
|
|
274
367
|
return { valid: true, trusted: false, details: await validateCliTokenOnServer(host, cliToken) };
|
|
275
368
|
} catch (error) {
|
|
@@ -286,7 +379,7 @@ async function validateExistingCliToken(host, cliToken) {
|
|
|
286
379
|
printError(
|
|
287
380
|
"auth",
|
|
288
381
|
error.message,
|
|
289
|
-
`Run: ae-cli auth logout --host ${host}, then ae-cli auth login --host ${host}`
|
|
382
|
+
external ? "Replace the external CLI token with a valid token for this host." : `Run: ae-cli auth logout --host ${host}, then ae-cli auth login --host ${host}`
|
|
290
383
|
);
|
|
291
384
|
process.exitCode = 1;
|
|
292
385
|
return { valid: false, trusted: false, details: {} };
|
|
@@ -349,6 +442,7 @@ function promptHiddenCliToken() {
|
|
|
349
442
|
});
|
|
350
443
|
}
|
|
351
444
|
function activateHostAfterLogin(host, explicitHostOverride) {
|
|
445
|
+
invalidateBusinessSkillSynchronization();
|
|
352
446
|
if (!explicitHostOverride) return;
|
|
353
447
|
const normalized = normalizeUrl(host);
|
|
354
448
|
const config = loadConfig();
|
|
@@ -426,12 +520,15 @@ async function switchActiveAccount(program, opts) {
|
|
|
426
520
|
}
|
|
427
521
|
}
|
|
428
522
|
try {
|
|
523
|
+
invalidateBusinessSkillSynchronization();
|
|
429
524
|
const selected = activateCredential(host, account);
|
|
430
525
|
clearCliTokenCache(host);
|
|
526
|
+
const environment = await refreshEnvironmentAfterLogin(host);
|
|
431
527
|
await printOutput({
|
|
432
528
|
host,
|
|
433
529
|
active: true,
|
|
434
|
-
account: accountOutput(selected.account)
|
|
530
|
+
account: accountOutput(selected.account),
|
|
531
|
+
...environment ? { environment } : {}
|
|
435
532
|
}, program.opts().format || "json");
|
|
436
533
|
} catch (error) {
|
|
437
534
|
if (error instanceof CredentialStoreUnreadableError) throw error;
|
|
@@ -455,6 +552,7 @@ async function persistDeviceTokens(host, tokens, options = {}) {
|
|
|
455
552
|
}
|
|
456
553
|
let saved;
|
|
457
554
|
try {
|
|
555
|
+
invalidateBusinessSkillSynchronization();
|
|
458
556
|
saved = saveCredential(host, {
|
|
459
557
|
cliToken,
|
|
460
558
|
...validation.account ? { account: validation.account } : {},
|
|
@@ -473,6 +571,7 @@ async function persistManualCliToken(host, cliToken, options = {}) {
|
|
|
473
571
|
const validation = await validateCliTokenOnServer(host, cliToken);
|
|
474
572
|
let saved;
|
|
475
573
|
try {
|
|
574
|
+
invalidateBusinessSkillSynchronization();
|
|
476
575
|
saved = saveCredential(host, {
|
|
477
576
|
cliToken,
|
|
478
577
|
...validation.account ? { account: validation.account } : {},
|
|
@@ -506,12 +605,16 @@ function manualTokenSummary(host, credential) {
|
|
|
506
605
|
};
|
|
507
606
|
}
|
|
508
607
|
function resolveLoginTeClaudeBase(host) {
|
|
509
|
-
|
|
510
|
-
const basePath = process.env.TE_CLAUDE_BASE_PATH || "/agent";
|
|
511
|
-
return base.endsWith(basePath) ? base : base + basePath;
|
|
608
|
+
return resolveLegacyLoginBase(host);
|
|
512
609
|
}
|
|
513
610
|
function registerAuth(program) {
|
|
514
611
|
const auth = program.command("auth").description("Manage authentication or switch the active account interactively").hook("preAction", (_command, actionCommand) => {
|
|
612
|
+
if (["auth", "login", "set-token", "use", "logout"].includes(actionCommand.name()) && readExternalCliToken()) {
|
|
613
|
+
throw new ExternalCliTokenError(
|
|
614
|
+
"Stored-account changes are unavailable while an external CLI token is selected.",
|
|
615
|
+
"EXTERNAL_CLI_TOKEN_ACTIVE"
|
|
616
|
+
);
|
|
617
|
+
}
|
|
515
618
|
if (["login", "set-token"].includes(actionCommand.name())) {
|
|
516
619
|
const host = resolveAuthHost(program, actionCommand.opts());
|
|
517
620
|
if (host) assertCredentialsReadable(host);
|
|
@@ -536,36 +639,43 @@ function registerAuth(program) {
|
|
|
536
639
|
}
|
|
537
640
|
const noBrowser = !opts.browser;
|
|
538
641
|
const format = program.opts().format || "json";
|
|
539
|
-
const teClaudeBase = resolveLoginTeClaudeBase(host);
|
|
540
642
|
const emit = (message) => process.stderr.write(`[ae-cli] ${message}
|
|
541
643
|
`);
|
|
542
644
|
try {
|
|
543
645
|
if (opts.deviceCode) {
|
|
544
|
-
const
|
|
646
|
+
const route = resolveDeviceSessionRoute(host, opts.deviceCode);
|
|
647
|
+
const tokens2 = await pollDeviceFlow(route.baseUrl, opts.deviceCode, { protocol: route.protocol }, emit);
|
|
545
648
|
const saved2 = await persistDeviceTokens(host, tokens2, { add: opts.add });
|
|
546
649
|
activateHostAfterLogin(host, explicitHost);
|
|
650
|
+
const environment2 = await refreshEnvironmentAfterLogin(host);
|
|
547
651
|
emit("Login successful! CLI token saved securely.");
|
|
548
|
-
await printOutput(loginSummary(host, saved2), format);
|
|
652
|
+
await printOutput({ ...loginSummary(host, saved2), ...environment2 ? { environment: environment2 } : {} }, format);
|
|
549
653
|
return;
|
|
550
654
|
}
|
|
655
|
+
const session = await authorizeLoginDevice(host);
|
|
656
|
+
const authResp = session.authorization;
|
|
551
657
|
if (opts.wait === false) {
|
|
552
|
-
const authResp = await authorizeDevice(teClaudeBase);
|
|
553
658
|
const addFlag = opts.add ? " --add" : "";
|
|
554
659
|
await printOutput({
|
|
555
660
|
device_code: authResp.device_code,
|
|
556
661
|
user_code: authResp.user_code,
|
|
557
|
-
verification_url: buildVerificationUrl(
|
|
662
|
+
verification_url: buildVerificationUrl(session.baseUrl, authResp.user_code, session.protocol),
|
|
558
663
|
interval: authResp.interval,
|
|
559
664
|
expires_in: authResp.expires_in,
|
|
560
|
-
next: `Open verification_url in a browser to authorize, then run: ae-cli auth login${addFlag} --device-code ${authResp.device_code}`
|
|
665
|
+
next: `Open verification_url in a browser to authorize, then run: ae-cli auth login${addFlag} --host ${shellArgument(host)} --device-code ${shellArgument(authResp.device_code)}`
|
|
561
666
|
}, format);
|
|
562
667
|
return;
|
|
563
668
|
}
|
|
564
|
-
const tokens = await runDeviceFlow(
|
|
669
|
+
const tokens = await runDeviceFlow(session.baseUrl, {
|
|
670
|
+
noBrowser,
|
|
671
|
+
protocol: session.protocol,
|
|
672
|
+
authorization: authResp
|
|
673
|
+
}, emit);
|
|
565
674
|
const saved = await persistDeviceTokens(host, tokens, { add: opts.add });
|
|
566
675
|
activateHostAfterLogin(host, explicitHost);
|
|
676
|
+
const environment = await refreshEnvironmentAfterLogin(host);
|
|
567
677
|
emit("Login successful! CLI token saved securely.");
|
|
568
|
-
await printOutput(loginSummary(host, saved), format);
|
|
678
|
+
await printOutput({ ...loginSummary(host, saved), ...environment ? { environment } : {} }, format);
|
|
569
679
|
} catch (error) {
|
|
570
680
|
if (error instanceof CredentialStoreUnreadableError) throw error;
|
|
571
681
|
if (error instanceof DeviceFlowUnsupportedError) {
|
|
@@ -608,9 +718,10 @@ function registerAuth(program) {
|
|
|
608
718
|
try {
|
|
609
719
|
const saved = await persistManualCliToken(host, cliToken, { add: opts.add });
|
|
610
720
|
activateHostAfterLogin(host, explicitHost);
|
|
721
|
+
const environment = await refreshEnvironmentAfterLogin(host);
|
|
611
722
|
process.stderr.write(`[ae-cli] CLI token verified and saved securely for ${host}
|
|
612
723
|
`);
|
|
613
|
-
await printOutput(manualTokenSummary(host, saved), program.opts().format || "json");
|
|
724
|
+
await printOutput({ ...manualTokenSummary(host, saved), ...environment ? { environment } : {} }, program.opts().format || "json");
|
|
614
725
|
} catch (error) {
|
|
615
726
|
if (error instanceof CredentialStoreUnreadableError) throw error;
|
|
616
727
|
if (error instanceof PermissionError) {
|
|
@@ -644,6 +755,22 @@ function registerAuth(program) {
|
|
|
644
755
|
}, program.opts().format || "json");
|
|
645
756
|
return;
|
|
646
757
|
}
|
|
758
|
+
const external = readExternalCliToken(host);
|
|
759
|
+
if (external) {
|
|
760
|
+
const state = await validateExistingCliToken(host, external.token, true);
|
|
761
|
+
if (!state.valid) return;
|
|
762
|
+
await printOutput({
|
|
763
|
+
authenticated: true,
|
|
764
|
+
host,
|
|
765
|
+
source: external.source,
|
|
766
|
+
cli_token: {
|
|
767
|
+
status: state.trusted ? "trusted" : "valid",
|
|
768
|
+
...state.details.cliTokenExpiresAt ? { expires_at: state.details.cliTokenExpiresAt } : {}
|
|
769
|
+
},
|
|
770
|
+
...state.details.account ? { account: accountOutput(state.details.account) } : {}
|
|
771
|
+
}, program.opts().format || "json");
|
|
772
|
+
return;
|
|
773
|
+
}
|
|
647
774
|
const active = getActiveCredential(host);
|
|
648
775
|
if (active) {
|
|
649
776
|
const state = await validateExistingCliToken(host, active.cliToken);
|
|
@@ -706,18 +833,21 @@ function registerAuth(program) {
|
|
|
706
833
|
process.exit(1);
|
|
707
834
|
}
|
|
708
835
|
clearCliTokenCache(host);
|
|
836
|
+
invalidateBusinessSkillSynchronization();
|
|
709
837
|
if (opts.all) {
|
|
710
838
|
clearAllCredentials(host);
|
|
711
839
|
await printOutput({ cleared: true, all: true, host }, program.opts().format || "json");
|
|
712
840
|
return;
|
|
713
841
|
}
|
|
714
842
|
const result = removeActiveCredential(host);
|
|
843
|
+
const environment = result.active ? await refreshEnvironmentAfterLogin(host) : void 0;
|
|
715
844
|
await printOutput({
|
|
716
845
|
cleared: !!result.removed,
|
|
717
846
|
all: false,
|
|
718
847
|
host,
|
|
719
848
|
remaining_accounts: listCredentials(host).length,
|
|
720
|
-
...result.active?.account ? { active_account: accountOutput(result.active.account) } : {}
|
|
849
|
+
...result.active?.account ? { active_account: accountOutput(result.active.account) } : {},
|
|
850
|
+
...environment ? { environment } : {}
|
|
721
851
|
}, program.opts().format || "json");
|
|
722
852
|
});
|
|
723
853
|
}
|