@thinkingai/ae-cli 6.1.27 → 6.1.28
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 +29 -3
- package/README.zh.md +29 -3
- package/dist/{auth-WA7YGGRT.js → auth-NKD5Z5BQ.js} +150 -38
- package/dist/{automation-VAAQBM7Y.js → automation-K32V2NKP.js} +94 -38
- package/dist/{capability-GAAYJ3IQ.js → capability-4CGSL7PK.js} +9 -8
- package/dist/{chunk-CT7QDJS6.js → chunk-2IYIYSUO.js} +2 -2
- package/dist/{chunk-3YVEAZUN.js → chunk-2UWS5CUP.js} +32 -21
- package/dist/{chunk-6VNIR4AP.js → chunk-ELCR235M.js} +26 -19
- package/dist/{chunk-RPBOAQQQ.js → chunk-GI5BMEZO.js} +1 -1
- package/dist/{chunk-7KU2WNQE.js → chunk-GTPWDLTE.js} +7 -6
- package/dist/chunk-JJJIP2XQ.js +105 -0
- package/dist/{chunk-5XJYLEVC.js → chunk-KHS64JZQ.js} +4 -4
- package/dist/{chunk-ZL7SGNIA.js → chunk-LMCYSVVA.js} +11 -13
- package/dist/{chunk-OP44TT4H.js → chunk-P6VFCH3P.js} +4 -2
- package/dist/{chunk-GHXZK54S.js → chunk-P7KL7IOH.js} +41 -13
- package/dist/{chunk-AP7YP2NX.js → chunk-QSAR3GHY.js} +2 -2
- package/dist/{chunk-VZZNLV3I.js → chunk-QW3R6O7L.js} +14 -6
- package/dist/{chunk-S6M42KND.js → chunk-T44M3PLZ.js} +1 -1
- package/dist/{chunk-AQJPNWZF.js → chunk-UF244C5C.js} +3 -3
- package/dist/{chunk-MWIA43UJ.js → chunk-UJ7UPRXK.js} +3 -3
- package/dist/{chunk-Q5US7JC5.js → chunk-UUD5RB36.js} +3 -3
- package/dist/chunk-X7DRLE62.js +233 -0
- package/dist/{chunk-WNGFSIOB.js → chunk-ZW4VMY5H.js} +103 -6
- package/dist/{community-report-client-PEERQCX2.js → community-report-client-S2K3A3Q6.js} +1 -1
- package/dist/{config-JOD5DOPE.js → config-ASSAAIOI.js} +6 -5
- package/dist/{context-NGVFPCBK.js → context-6RWLVOM5.js} +4 -4
- package/dist/{data-integration-BCLQFTGU.js → data-integration-EXSUPUDZ.js} +6 -6
- package/dist/evaluation-5YT4QLCL.js +3714 -0
- package/dist/index.js +96 -52
- package/dist/{local-data-upload-client-TWMHFLUA.js → local-data-upload-client-7HCPGIS3.js} +1 -1
- package/dist/{memory-CQKH2JAV.js → memory-VCYLVPMI.js} +6 -6
- package/dist/{metadata-NR3PHR23.js → metadata-YGI5M6OF.js} +8 -8
- package/dist/{model-VX5M2CJ6.js → model-DPJHSD73.js} +4 -4
- package/dist/{personal-semantic-preference-2RAI36P3.js → personal-semantic-preference-76TBKAPY.js} +6 -6
- package/dist/{project-semantic-3BUGP3ZM.js → project-semantic-XOEBO2Q5.js} +6 -6
- package/dist/{sync-RZIAV37C.js → sync-7PP6KQ75.js} +7 -7
- package/dist/{te-agent-AORRE2FM.js → te-agent-PJVAPKBD.js} +753 -94
- package/dist/{te-analysis-GP7DSQ7Q.js → te-analysis-OX62G5VD.js} +411 -79
- package/dist/{te-community-42M7ICDO.js → te-community-QN3WMPNT.js} +6 -4
- package/dist/{te-dataops-BNKNZ4F2.js → te-dataops-UKD2XN3E.js} +8 -6
- package/dist/{te-engage-2CO6LRCX.js → te-engage-X3DIXPRA.js} +6 -6
- package/dist/{te-experiment-652CLXMU.js → te-experiment-MEIIK3DP.js} +6 -6
- package/dist/{te-kb-ULATOTQ3.js → te-kb-73EWDFDF.js} +7 -7
- package/dist/{te-system-UGHVKBVV.js → te-system-IE7NCKC3.js} +6 -6
- package/dist/{te-team-YA6SNOJ3.js → te-team-MGQ5CNRW.js} +63 -41
- package/dist/{things-DTCOQIQB.js → things-4JIBCA55.js} +7 -7
- package/dist/{update-ESNYKUVR.js → update-AX66IFMJ.js} +4 -4
- package/dist/{workspace-JEOHKFPX.js → workspace-Q5NMEKEN.js} +6 -6
- package/package.json +13 -8
- 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 +53 -0
- package/skills/ae-analysis/SKILL.md +12 -3
- package/skills/ae-analysis/references/adhoc_export.md +1 -1
- package/skills/ae-analysis/references/agent_review_preflight.md +4 -0
- package/skills/ae-analysis/references/agent_review_submit_to_page.md +4 -0
- 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 +34 -25
- 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 +10 -2
- 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_plan_schema.md +6 -1
- package/skills/ae-analysis/references/report_data_export.md +1 -1
- package/skills/ae-analysis/references/scenario_append.md +25 -0
- package/skills/ae-analysis/references/scenario_collect.md +35 -0
- package/skills/ae-analysis/references/scenario_evaluation.md +30 -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/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-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-kb/SKILL.md +1 -2
- package/skills/ae-metadata/SKILL.md +2 -1
- package/skills/ae-metadata/references/metadata_data_table_download.md +7 -1
- package/skills/ae-metadata/references/metadata_data_table_get.md +2 -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-CI24BDR2.js +0 -43
package/README.md
CHANGED
|
@@ -62,11 +62,11 @@ ae-cli update --dry-run
|
|
|
62
62
|
|
|
63
63
|
Updates use the same global Skills installation and verification as `install`. Older packages need no installer or generated manifest: their bundled Skills define the expected contents. If Skills fail after the CLI installs, the result reports partial completion and can be retried.
|
|
64
64
|
|
|
65
|
-
Automatic synchronization runs during normal commands after login; host version checks are cached for up to
|
|
65
|
+
Automatic synchronization runs during normal commands after login; host version checks are cached for up to one hour. `ae-cli update --host <AE_HOST>` checks immediately. After a downgrade, future updates run the older CLI's own updater, including its historical limitations. To use the new installer logic while following an older host, run `npx @thinkingai/ae-cli@latest update --host <AE_HOST>`; the target remains the host-required version.
|
|
66
66
|
|
|
67
67
|
`ae-cli update` installs the exact version required by the active host rather than npm `latest`. It synchronizes Skills from the installed npm package first and uses the matching GitHub tag only as a fallback.
|
|
68
68
|
|
|
69
|
-
Starting with the `6.0.37` and `6.1.9` release lines, ordinary business commands can automatically upgrade or downgrade the CLI to the host-required version. After a successful synchronization, the old process exits with `AE_CLI_VERSION_SYNCED`; re-run the original command so it executes with the new CLI and Skills. Installation failures are reported without replacing the business command's JSON output.
|
|
69
|
+
Starting with the `6.0.37` and `6.1.9` release lines, ordinary business commands can automatically upgrade or downgrade the CLI to the host-required version, including switching from `6.0.x` to `6.1.x`. Automatic synchronization requires stable `major.minor.patch` versions at both ends; development and other nonstandard versions are skipped. After a successful synchronization, the old process exits with `AE_CLI_VERSION_SYNCED`; re-run the original command so it executes with the new CLI and Skills. Installation failures are reported without replacing the business command's JSON output.
|
|
70
70
|
|
|
71
71
|
Useful controls:
|
|
72
72
|
|
|
@@ -144,6 +144,7 @@ The table covers every current root command individually. Use `ae-cli --help` fo
|
|
|
144
144
|
| Agent platform | `context` | Read the current product-page context authorized for the active Agent Run |
|
|
145
145
|
| Agent platform | `memory` | AgentSpace memory, drafts, shared review, extraction jobs, revisions, and state transitions |
|
|
146
146
|
| Agent platform | `team` | Agent Team and TeamRun execution, chat, results, and artifacts |
|
|
147
|
+
| Agent platform | `evaluation` | Agent Evaluation datasets, LLM judge evaluators, runs, case results, exports, schedules, and model/agent configs |
|
|
147
148
|
| Agent platform | `system` | Root/admin management of members, sandboxes, tools, models, usage, quotas, and channels |
|
|
148
149
|
| General tools | `capability` | Capability discovery, schema inspection, validation, dry-run, and generic execution |
|
|
149
150
|
| General tools | `auth` | Host-scoped login, status, and multi-account management |
|
|
@@ -157,6 +158,8 @@ The table covers every current root command individually. Use `ae-cli --help` fo
|
|
|
157
158
|
| Agent platform | `automation` | Automation configuration, execution, history, and results |
|
|
158
159
|
<!-- root-command-surface:end -->
|
|
159
160
|
|
|
161
|
+
Evaluation commands follow the current AE Host in personal terminals and sandboxes; use `--host` to select another host. Evaluation requests use the HTTP or HTTPS scheme configured for that AE Host, consistent with other AE commands. Legacy `--endpoint` and `AE_EVAL_BASE_URL` values may only match the current AE Host; other values fail before credentials are sent. Remove these settings and use `--host` to select a host. Outside a sandbox, export `AE_EVAL_ACCESS_TOKEN` with a platform session token; sandboxes can obtain a session automatically. See [endpoint and authentication rules](skills/ae-evaluation/SKILL.md#endpoint-and-authentication).
|
|
162
|
+
|
|
160
163
|
## Capability Gateway
|
|
161
164
|
|
|
162
165
|
Capability Gateway is the preferred entry point for operations that do not need a dedicated curated command:
|
|
@@ -170,6 +173,10 @@ ae-cli capability dry-run analysis.report.list --input input.json
|
|
|
170
173
|
ae-cli capability run analysis.report.list --input input.json
|
|
171
174
|
```
|
|
172
175
|
|
|
176
|
+
Administrators can set each member's daily CLI call limit in External Access Management.
|
|
177
|
+
|
|
178
|
+
For asynchronous exports, omit `--timeout-seconds` to use the server's default timeout. See the [export guide](skills/ae-analysis/references/analysis_data_export.md) for submitting, waiting for, and downloading results.
|
|
179
|
+
|
|
173
180
|
`--input` accepts inline JSON, a JSON file path, `@<path>`, or `-` for stdin.
|
|
174
181
|
|
|
175
182
|
Use `validate` while fixing complex nested input. Use `dry-run` when you need the final risk, output mode, cancellation support, or delete confirmation preview. Do not stack `validate` and `dry-run` for the same final payload by default; `dry-run` already validates it.
|
|
@@ -195,7 +202,7 @@ ae-cli auth status --host https://host-a.example.com
|
|
|
195
202
|
# Import a CLI token copied from External Access Management (hidden prompt)
|
|
196
203
|
ae-cli auth set-token --host https://host-a.example.com
|
|
197
204
|
# Non-interactive input for local scripts or tests
|
|
198
|
-
printf '%s' "$
|
|
205
|
+
printf '%s' "$IMPORTED_CLI_TOKEN" | ae-cli auth set-token --host https://host-a.example.com --token-stdin
|
|
199
206
|
# For the uncommon case where one Host needs multiple accounts
|
|
200
207
|
ae-cli auth login --host https://host-a.example.com --add
|
|
201
208
|
ae-cli auth list --host https://host-a.example.com
|
|
@@ -217,9 +224,28 @@ A regular `auth login` keeps the simple one-Host/one-account behavior and replac
|
|
|
217
224
|
|
|
218
225
|
`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.
|
|
219
226
|
|
|
227
|
+
Inject credentials into the current CLI invocation through environment variables or a specified file without changing stored machine accounts. This supports automation scripts, CI/CD, shared Agents, and other workflows:
|
|
228
|
+
|
|
229
|
+
```bash
|
|
230
|
+
AE_CLI_TOKEN="$CALLER_CLI_TOKEN" AE_CLI_TOKEN_HOST=https://host-a.example.com ae-cli auth status
|
|
231
|
+
AE_CLI_TOKEN_FILE=/secure/caller-token.json ae-cli auth status
|
|
232
|
+
ae-cli --cli-token-file /secure/caller-token.json auth status
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
The token file is a read-only JSON object: `{"url":"https://host-a.example.com","token":"cli_REPLACE_WITH_USER_TOKEN"}`. The historical `cli-token` key is also accepted. Keep the file private to its owner (for example, mode `600`). Files must be regular JSON files no larger than 64 KiB. The file URL or `AE_CLI_TOKEN_HOST` selects the host for this invocation; an explicit `--host` must match it. External tokens are sent only to that origin; alternate service origins and HTTP redirects are rejected.
|
|
236
|
+
|
|
237
|
+
Credential precedence is `--cli-token-file` > `AE_CLI_TOKEN` with required `AE_CLI_TOKEN_HOST` > `AE_CLI_TOKEN_FILE` > the existing stored-account/sandbox sources. An explicitly selected source that is empty, malformed, unreadable, or bound to a different host returns `EXTERNAL_CLI_TOKEN_INVALID`; it never falls back to another identity. External credentials also take precedence over sandbox identity headers for Agent calls. `auth status` reports `environment-cli-token` or `file-cli-token`, account and expiration when available, and never reveals the token. Authentication failures do not replace or delete stored credentials.
|
|
238
|
+
|
|
239
|
+
External mode does not write the token or renewal state to the local credential vault. Renewal is best effort, uses the `cli-token` header, and is limited per host/token per process day; older servers without header-based renewal can still authenticate business calls but cannot automatically extend external tokens. `auth`, `auth login`, `auth set-token`, `auth use`, and `auth logout` return `EXTERNAL_CLI_TOKEN_ACTIVE` while external credentials are selected. Remove these process settings before managing machine accounts; `auth list` continues to list local accounts.
|
|
240
|
+
|
|
220
241
|
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.
|
|
221
242
|
|
|
222
243
|
Login uses a cross-platform device-code flow. Use `--no-browser` when the environment cannot open a browser.
|
|
244
|
+
|
|
245
|
+
On upgraded 6.1 deployments, authorization always uses the UBA device endpoints and the platform `/#/cli/device-activate` page, independently of Kubernetes or Agent state. Only an explicit missing authorization endpoint (HTTP 404) selects the supported legacy Agent flow; network failures, HTML responses and permission denials never change the issuer. Use `auth login --no-wait`, then resume with the returned `--device-code` and the same `--host` for non-interactive authorization. Existing host accounts, CLI tokens and command flags remain compatible.
|
|
246
|
+
|
|
247
|
+
The CLI calls business endpoints directly; services enforce product License and user/project permissions. An unavailable component returns the actual API error. HTTP 404 can also mean a missing resource or an unsupported route, so it does not by itself establish that a component is not deployed.
|
|
248
|
+
|
|
223
249
|
Trial guidance is emitted only when no Host is configured; normal commands and authentication flows for configured environments do not display it.
|
|
224
250
|
|
|
225
251
|
## Output and Safety
|
package/README.zh.md
CHANGED
|
@@ -66,11 +66,11 @@ ae-cli update --dry-run
|
|
|
66
66
|
|
|
67
67
|
更新与 `install` 复用全局 Skills 安装和校验。旧包无需包含安装器或生成的清单,直接以目标包内置 Skills 为准。CLI 安装后 Skills 失败会返回部分成功信息,修复后可重复执行。
|
|
68
68
|
|
|
69
|
-
自动同步在登录后的普通命令中触发,集群版本检查最长缓存
|
|
69
|
+
自动同步在登录后的普通命令中触发,集群版本检查最长缓存 1 小时;`ae-cli update --host <AE_HOST>` 可立即查询。降级后,后续更新由旧版 CLI 自身执行,也受旧版实现限制。需要用新安装逻辑匹配旧集群时,可运行 `npx @thinkingai/ae-cli@latest update --host <AE_HOST>`,目标仍是集群要求的版本。
|
|
70
70
|
|
|
71
71
|
`ae-cli update` 安装当前 Host 要求的精确版本,不依赖 npm `latest`。更新时优先从已安装的 npm 包同步 Skills,本地来源失败后才回退到对应的 GitHub tag。
|
|
72
72
|
|
|
73
|
-
从 `6.0.37` 和 `6.1.9`
|
|
73
|
+
从 `6.0.37` 和 `6.1.9` 维护线开始,普通业务命令可以自动升级或降级到环境要求的版本,包括从 `6.0.x` 切换到 `6.1.x`。自动同步要求本地和目标均为 `主版本.次版本.补丁号` 格式的正式版本,开发版等不规则版本会跳过。同步成功后,旧进程会返回 `AE_CLI_VERSION_SYNCED`;重新执行原命令,即可使用新的 CLI 和 Skills。安装失败会给出提示,但不会用安装输出污染业务命令的 JSON 结果。
|
|
74
74
|
|
|
75
75
|
常用控制方式:
|
|
76
76
|
|
|
@@ -148,6 +148,7 @@ ae-cli capability list --domain analysis --jq '.data.capabilities[] | .id'
|
|
|
148
148
|
| Agent 平台 | `context` | 读取当前 Agent Run 已授权的产品页面上下文 |
|
|
149
149
|
| Agent 平台 | `memory` | AgentSpace 记忆、草稿、共享审核、提取任务、版本与状态治理 |
|
|
150
150
|
| Agent 平台 | `team` | Agent Team 和 TeamRun 的执行、对话、结果及产物 |
|
|
151
|
+
| Agent 平台 | `evaluation` | Agent Evaluation 评测数据集、LLM 裁判、评测任务、用例结果、导出、调度,以及模型/Agent 配置 |
|
|
151
152
|
| Agent 平台 | `system` | root/admin 的成员、沙盒、工具、模型、用量、配额和渠道管理 |
|
|
152
153
|
| 通用工具 | `capability` | 能力发现、Schema 查看、参数校验、dry-run 和通用执行 |
|
|
153
154
|
| 通用工具 | `auth` | 按 Host 登录、查看状态及管理同一 Host 的多个账号 |
|
|
@@ -161,6 +162,8 @@ ae-cli capability list --domain analysis --jq '.data.capabilities[] | .id'
|
|
|
161
162
|
| Agent 平台 | `automation` | 自动化配置、执行、历史和结果 |
|
|
162
163
|
<!-- root-command-surface:end -->
|
|
163
164
|
|
|
165
|
+
评测命令在普通终端和沙箱中均跟随当前 AE Host,可通过 `--host` 切换。评测请求沿用该 AE Host 配置的 HTTP 或 HTTPS 协议,与其他 AE 命令一致。旧 `--endpoint` 和 `AE_EVAL_BASE_URL` 只能与当前 AE Host 一致,其他值会在发送凭证前报错;请移除这些配置,统一使用 `--host` 切换。沙箱外需设置 `AE_EVAL_ACCESS_TOKEN` 平台 session token,沙箱内可自动获取会话。详见 [地址与鉴权规则](skills/ae-evaluation/SKILL.md#endpoint-and-authentication)。
|
|
166
|
+
|
|
164
167
|
## Capability Gateway
|
|
165
168
|
|
|
166
169
|
不需要独立精选命令的能力,应优先通过 Capability Gateway 调用:
|
|
@@ -174,6 +177,10 @@ ae-cli capability dry-run analysis.report.list --input input.json
|
|
|
174
177
|
ae-cli capability run analysis.report.list --input input.json
|
|
175
178
|
```
|
|
176
179
|
|
|
180
|
+
管理员可在“外部访问管理”为成员配置每日 CLI 调用限额。
|
|
181
|
+
|
|
182
|
+
异步导出时,省略 `--timeout-seconds` 即使用服务端默认超时。提交、等待和下载结果的方法见[导出使用指南](skills/ae-analysis/references/analysis_data_export.md)。
|
|
183
|
+
|
|
177
184
|
`--input` 支持内联 JSON、JSON 文件路径、`@<path>`,或通过 `-` 从 stdin 读取。
|
|
178
185
|
|
|
179
186
|
复杂嵌套参数尚在调整时使用 `validate`;需要确认最终风险等级、输出模式、取消能力或删除门禁时使用 `dry-run`。默认不要对同一份最终入参连续执行 `validate` 和 `dry-run`,因为 `dry-run` 已包含参数校验。
|
|
@@ -199,7 +206,7 @@ ae-cli auth status --host https://host-a.example.com
|
|
|
199
206
|
# 导入从“外部访问管理”复制的 CLI Token(隐藏输入)
|
|
200
207
|
ae-cli auth set-token --host https://host-a.example.com
|
|
201
208
|
# 本地脚本或测试使用非交互输入
|
|
202
|
-
printf '%s' "$
|
|
209
|
+
printf '%s' "$IMPORTED_CLI_TOKEN" | ae-cli auth set-token --host https://host-a.example.com --token-stdin
|
|
203
210
|
# 少量需要同一 Host 多账号的场景
|
|
204
211
|
ae-cli auth login --host https://host-a.example.com --add
|
|
205
212
|
ae-cli auth list --host https://host-a.example.com
|
|
@@ -221,9 +228,28 @@ ae-cli config remove pre-production --yes
|
|
|
221
228
|
|
|
222
229
|
`auth set-token` 用于在本地导入从“外部访问管理”复制的 `cli_` Token。默认使用不回显的隐藏输入,`--token-stdin` 支持本地测试等非交互场景。CLI 会先向目标 Host 校验 Token,再替换本地凭证,并写入现有的按 Host 加密凭据库;命令输出不会包含 Token。需要保留同一 Host 的其他账号时增加 `--add`。
|
|
223
230
|
|
|
231
|
+
支持通过环境变量或指定文件,为当前 CLI 调用注入凭证,不改变机器上已保存的账号;适用于自动化脚本、CI/CD、公共Agent等场景。
|
|
232
|
+
|
|
233
|
+
```bash
|
|
234
|
+
AE_CLI_TOKEN="$CALLER_CLI_TOKEN" AE_CLI_TOKEN_HOST=https://host-a.example.com ae-cli auth status
|
|
235
|
+
AE_CLI_TOKEN_FILE=/secure/caller-token.json ae-cli auth status
|
|
236
|
+
ae-cli --cli-token-file /secure/caller-token.json auth status
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
Token 文件是只读 JSON 对象:`{"url":"https://host-a.example.com","token":"cli_REPLACE_WITH_USER_TOKEN"}`,也兼容历史字段 `cli-token`。文件应仅允许所有者读取,例如权限 `600`;必须是大小不超过 64 KiB 的普通 JSON 文件。文件中的 URL 或 `AE_CLI_TOKEN_HOST` 决定本次调用的 Host;显式 `--host` 必须与之匹配。外部 Token 仅发送到该 Origin,拒绝其他服务 Origin 和 HTTP 重定向。
|
|
240
|
+
|
|
241
|
+
凭证优先级为 `--cli-token-file` > `AE_CLI_TOKEN`(必须同时提供 `AE_CLI_TOKEN_HOST`)> `AE_CLI_TOKEN_FILE` > 现有本地账号或沙箱来源。显式来源为空、格式错误、无法读取或 Host 不匹配时返回 `EXTERNAL_CLI_TOKEN_INVALID`,不会回退到其他身份。外部凭证也优先于 Agent 调用的沙箱身份头。`auth status` 的来源为 `environment-cli-token` 或 `file-cli-token`,并在后端支持时展示账号与到期时间,不输出 Token。认证失败不会替换或删除本地凭证。
|
|
242
|
+
|
|
243
|
+
外部模式不将 Token 或续期状态写入本地凭据库。自动续期使用 `cli-token` 请求头,失败不阻断业务请求,每个进程按 Host、Token 和当天日期限频;旧后端不支持请求头续期时仍可认证业务请求,但不能自动延长外部 Token。选择外部凭证时,`auth`、`auth login`、`auth set-token`、`auth use` 和 `auth logout` 返回 `EXTERNAL_CLI_TOKEN_ACTIVE`。管理机器账号前先移除这些进程设置;`auth list` 仍只列出本地账号。
|
|
244
|
+
|
|
224
245
|
新版 CLI 只持久化 CLI Token,不保存 access token 或 refresh token。多账号保存在加密的 V1 凭据文件中,同时维护旧文件格式的当前账号投影,保证 CLI 自动降级后仍可登录;再次升级时会合并旧 CLI 对投影的登录、切换或退出变更。
|
|
225
246
|
|
|
226
247
|
登录使用跨平台设备码流程。当前环境无法打开浏览器时,可使用 `--no-browser`。
|
|
248
|
+
|
|
249
|
+
已改造的 6.1 环境统一使用 UBA 设备授权接口与平台 `/#/cli/device-activate` 页面,不随 K8s 或 Agent 状态切换。只有授权端点明确不存在(HTTP 404)时才兼容旧 Agent 流程;网络失败、HTML 响应和权限拒绝均不会更换授权方。非交互环境使用 `auth login --no-wait`,再携带返回的 `--device-code` 和同一个 `--host` 继续授权。原有 Host 多账号、CLI Token 与命令参数保持兼容。
|
|
250
|
+
|
|
251
|
+
CLI 直接请求对应业务接口,由服务端校验产品 License 和用户/项目权限。组件不可用时会返回实际接口错误;HTTP 404 也可能表示资源不存在或路由不支持,不能据此直接判断组件未部署。
|
|
252
|
+
|
|
227
253
|
试用引导仅在尚未配置 Host 时出现;已配置环境的正常命令和认证流程不会展示该提示。
|
|
228
254
|
|
|
229
255
|
## 输出与安全
|
|
@@ -9,13 +9,13 @@ import {
|
|
|
9
9
|
} from "./chunk-6ZIQV5GW.js";
|
|
10
10
|
import {
|
|
11
11
|
resolveHost
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-P6VFCH3P.js";
|
|
13
13
|
import {
|
|
14
14
|
getLocalCliPackageInfo,
|
|
15
15
|
printError,
|
|
16
16
|
printOutput,
|
|
17
17
|
runHostCompatCheck
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-ELCR235M.js";
|
|
19
19
|
import {
|
|
20
20
|
CliTokenValidationUnavailableError,
|
|
21
21
|
CredentialStoreUnreadableError,
|
|
@@ -31,25 +31,54 @@ import {
|
|
|
31
31
|
saveCredential,
|
|
32
32
|
updateCredentialMetadata,
|
|
33
33
|
validateCliTokenOnServer
|
|
34
|
-
} from "./chunk-
|
|
34
|
+
} from "./chunk-P7KL7IOH.js";
|
|
35
35
|
import {
|
|
36
36
|
getFallbackCliToken,
|
|
37
37
|
loadConfig,
|
|
38
|
-
normalizeUrl,
|
|
39
38
|
saveConfig
|
|
40
|
-
} from "./chunk-
|
|
39
|
+
} from "./chunk-LMCYSVVA.js";
|
|
41
40
|
import {
|
|
41
|
+
ExternalCliTokenError,
|
|
42
42
|
PermissionError,
|
|
43
|
-
logger
|
|
44
|
-
|
|
43
|
+
logger,
|
|
44
|
+
normalizeUrl,
|
|
45
|
+
readExternalCliToken
|
|
46
|
+
} from "./chunk-ZW4VMY5H.js";
|
|
45
47
|
|
|
46
48
|
// src/core/device-auth.ts
|
|
47
49
|
import { execFileSync } from "child_process";
|
|
50
|
+
function deviceApiPath(protocol, action) {
|
|
51
|
+
return protocol === "uba" ? `/v1/ta/cli/auth/device/${action}` : `/api/auth/device/${action}`;
|
|
52
|
+
}
|
|
53
|
+
function ubaAuthorizationDenial(code) {
|
|
54
|
+
if (code === "CLI_ACCESS_DISABLED") return {
|
|
55
|
+
code,
|
|
56
|
+
message: "CLI access is disabled for this account.",
|
|
57
|
+
hint: "Contact your administrator."
|
|
58
|
+
};
|
|
59
|
+
if (code === "ACCOUNT_UNAVAILABLE") return {
|
|
60
|
+
code,
|
|
61
|
+
message: "This account is unavailable.",
|
|
62
|
+
hint: "Contact your administrator or sign in with an active account."
|
|
63
|
+
};
|
|
64
|
+
if (code === "ORIGIN_DENIED") return {
|
|
65
|
+
code,
|
|
66
|
+
message: "Authorization must be approved from the trusted platform page.",
|
|
67
|
+
hint: "Open the verification URL on the configured AE host and sign in there."
|
|
68
|
+
};
|
|
69
|
+
return {
|
|
70
|
+
code: "AUTHORIZATION_DENIED",
|
|
71
|
+
message: "Device authorization was denied.",
|
|
72
|
+
hint: "Check your account status with your administrator before requesting authorization again."
|
|
73
|
+
};
|
|
74
|
+
}
|
|
48
75
|
var DeviceFlowUnsupportedError = class extends Error {
|
|
49
|
-
constructor() {
|
|
76
|
+
constructor(httpStatus) {
|
|
50
77
|
super("This AE server does not support device code login (it may be an older server version).");
|
|
78
|
+
this.httpStatus = httpStatus;
|
|
51
79
|
this.name = "DeviceFlowUnsupportedError";
|
|
52
80
|
}
|
|
81
|
+
httpStatus;
|
|
53
82
|
};
|
|
54
83
|
function looksLikeMissingEndpoint(status, contentType, body) {
|
|
55
84
|
if (status === 404) return true;
|
|
@@ -83,29 +112,46 @@ function openBrowser(url, _execFile) {
|
|
|
83
112
|
exec("xdg-open", [url], { timeout: 5e3 });
|
|
84
113
|
return true;
|
|
85
114
|
} catch (e) {
|
|
86
|
-
logger.warn(`openBrowser: failed to open ${safeLogUrl}
|
|
115
|
+
logger.warn(`openBrowser: failed to open ${safeLogUrl}`);
|
|
87
116
|
return false;
|
|
88
117
|
}
|
|
89
118
|
}
|
|
90
|
-
async function authorizeDevice(host) {
|
|
119
|
+
async function authorizeDevice(host, protocol = "legacy") {
|
|
91
120
|
const base = host.replace(/\/+$/, "");
|
|
92
|
-
const url = `${base}
|
|
121
|
+
const url = `${base}${deviceApiPath(protocol, "authorize")}`;
|
|
93
122
|
let resp;
|
|
94
123
|
try {
|
|
95
124
|
resp = await fetch(url, {
|
|
96
125
|
method: "POST",
|
|
97
|
-
headers: {
|
|
126
|
+
headers: {
|
|
127
|
+
"Content-Type": "application/json",
|
|
128
|
+
...protocol === "uba" ? { "X-CLI-Verification-Origin": new URL(host).origin } : {}
|
|
129
|
+
},
|
|
130
|
+
redirect: "error",
|
|
131
|
+
signal: AbortSignal.timeout(1e4)
|
|
98
132
|
});
|
|
99
133
|
} catch (e) {
|
|
100
|
-
throw new Error(
|
|
134
|
+
throw new Error("Device authorize request failed. Check the AE host and network, then retry.");
|
|
101
135
|
}
|
|
102
136
|
const contentType = resp.headers.get("content-type");
|
|
103
137
|
const text = await resp.text().catch(() => "");
|
|
104
138
|
if (looksLikeMissingEndpoint(resp.status, contentType, text)) {
|
|
105
|
-
throw new DeviceFlowUnsupportedError();
|
|
139
|
+
throw new DeviceFlowUnsupportedError(resp.status);
|
|
106
140
|
}
|
|
107
141
|
if (!resp.ok) {
|
|
108
|
-
|
|
142
|
+
if (resp.status === 403) {
|
|
143
|
+
if (protocol === "uba") {
|
|
144
|
+
let code;
|
|
145
|
+
try {
|
|
146
|
+
code = JSON.parse(text)?.code;
|
|
147
|
+
} catch {
|
|
148
|
+
}
|
|
149
|
+
const denial = ubaAuthorizationDenial(code);
|
|
150
|
+
throw new PermissionError(denial.message, denial.code, denial.hint);
|
|
151
|
+
}
|
|
152
|
+
throw new PermissionError("CLI authorization is not allowed.", "CLI_ACCESS_DISABLED", "Contact your administrator.");
|
|
153
|
+
}
|
|
154
|
+
throw new Error(`Device authorize returned HTTP ${resp.status}`);
|
|
109
155
|
}
|
|
110
156
|
let body;
|
|
111
157
|
try {
|
|
@@ -113,23 +159,28 @@ async function authorizeDevice(host) {
|
|
|
113
159
|
} catch {
|
|
114
160
|
throw new Error("Device authorize returned invalid JSON");
|
|
115
161
|
}
|
|
116
|
-
if (!body.device_code || !body.user_code) {
|
|
162
|
+
if (typeof body.device_code !== "string" || !body.device_code || typeof body.user_code !== "string" || !body.user_code) {
|
|
117
163
|
throw new Error("Device authorize response missing required fields");
|
|
118
164
|
}
|
|
165
|
+
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)) {
|
|
166
|
+
throw new Error("UBA authorization returned invalid polling limits. Check the server deployment.");
|
|
167
|
+
}
|
|
119
168
|
return body;
|
|
120
169
|
}
|
|
121
|
-
async function pollDeviceToken(host, deviceCode) {
|
|
170
|
+
async function pollDeviceToken(host, deviceCode, protocol = "legacy") {
|
|
122
171
|
const base = host.replace(/\/+$/, "");
|
|
123
|
-
const url = `${base}
|
|
172
|
+
const url = `${base}${deviceApiPath(protocol, "token")}`;
|
|
124
173
|
let resp;
|
|
125
174
|
try {
|
|
126
175
|
resp = await fetch(url, {
|
|
127
176
|
method: "POST",
|
|
128
177
|
headers: { "Content-Type": "application/json" },
|
|
129
|
-
body: JSON.stringify({ device_code: deviceCode })
|
|
178
|
+
body: JSON.stringify({ device_code: deviceCode }),
|
|
179
|
+
redirect: "error",
|
|
180
|
+
signal: AbortSignal.timeout(1e4)
|
|
130
181
|
});
|
|
131
182
|
} catch (e) {
|
|
132
|
-
return { status: "error", message:
|
|
183
|
+
return { status: "error", message: "Network error while polling authorization." };
|
|
133
184
|
}
|
|
134
185
|
if (resp.status === 200) {
|
|
135
186
|
let body;
|
|
@@ -138,7 +189,7 @@ async function pollDeviceToken(host, deviceCode) {
|
|
|
138
189
|
} catch {
|
|
139
190
|
return { status: "error", message: "Token response is not valid JSON" };
|
|
140
191
|
}
|
|
141
|
-
if (!body.access_token) {
|
|
192
|
+
if (typeof body.access_token !== "string" || !body.access_token) {
|
|
142
193
|
return { status: "error", message: "Token response missing access_token" };
|
|
143
194
|
}
|
|
144
195
|
return { status: "approved", tokens: body };
|
|
@@ -154,7 +205,13 @@ async function pollDeviceToken(host, deviceCode) {
|
|
|
154
205
|
if (err === "authorization_pending") return { status: "pending" };
|
|
155
206
|
if (err === "slow_down") return { status: "slow_down" };
|
|
156
207
|
if (err === "expired_token") return { status: "expired" };
|
|
157
|
-
|
|
208
|
+
if (err === "access_denied") return {
|
|
209
|
+
status: "denied",
|
|
210
|
+
code: "AUTHORIZATION_DENIED",
|
|
211
|
+
message: "Device authorization was denied.",
|
|
212
|
+
hint: "Run ae-cli auth login again only when you want to request authorization."
|
|
213
|
+
};
|
|
214
|
+
return { status: "error", message: "Token endpoint returned an unrecognized authorization error." };
|
|
158
215
|
}
|
|
159
216
|
if (resp.status === 403) {
|
|
160
217
|
let errorBody = {};
|
|
@@ -162,6 +219,7 @@ async function pollDeviceToken(host, deviceCode) {
|
|
|
162
219
|
errorBody = await resp.json();
|
|
163
220
|
} catch {
|
|
164
221
|
}
|
|
222
|
+
if (protocol === "uba") return { status: "denied", ...ubaAuthorizationDenial(errorBody.code) };
|
|
165
223
|
return {
|
|
166
224
|
status: "denied",
|
|
167
225
|
code: errorBody.code ?? "CLI_ACCESS_DISABLED",
|
|
@@ -176,7 +234,10 @@ async function pollDeviceToken(host, deviceCode) {
|
|
|
176
234
|
}
|
|
177
235
|
return { status: "error", message: `Unexpected HTTP ${resp.status} from token endpoint` };
|
|
178
236
|
}
|
|
179
|
-
function buildVerificationUrl(host, userCode) {
|
|
237
|
+
function buildVerificationUrl(host, userCode, protocol = "legacy") {
|
|
238
|
+
if (protocol === "uba") {
|
|
239
|
+
return `${host.replace(/\/+$/, "")}/#/cli/device-activate?user_code=${encodeURIComponent(userCode)}`;
|
|
240
|
+
}
|
|
180
241
|
return `${host.replace(/\/+$/, "")}/device-activate?user_code=${encodeURIComponent(userCode)}`;
|
|
181
242
|
}
|
|
182
243
|
async function pollDeviceFlow(host, deviceCode, options = {}, onStatus) {
|
|
@@ -190,7 +251,7 @@ async function pollDeviceFlow(host, deviceCode, options = {}, onStatus) {
|
|
|
190
251
|
while (Date.now() < deadline) {
|
|
191
252
|
await sleep(intervalMs);
|
|
192
253
|
pollCount++;
|
|
193
|
-
const result = await pollDeviceToken(host, deviceCode);
|
|
254
|
+
const result = await pollDeviceToken(host, deviceCode, options.protocol);
|
|
194
255
|
if (result.status === "approved") {
|
|
195
256
|
emit(`Authorization successful! (polled ${pollCount} time(s))`);
|
|
196
257
|
return result.tokens;
|
|
@@ -237,9 +298,9 @@ async function runDeviceFlow(host, options = {}, onStatus) {
|
|
|
237
298
|
if (onStatus) onStatus(msg);
|
|
238
299
|
};
|
|
239
300
|
emit("Requesting authorization code from server...");
|
|
240
|
-
const auth = await authorizeDevice(host);
|
|
301
|
+
const auth = options.authorization ?? await authorizeDevice(host, options.protocol);
|
|
241
302
|
const userCode = auth.user_code;
|
|
242
|
-
const verifyUrl = buildVerificationUrl(host, userCode);
|
|
303
|
+
const verifyUrl = buildVerificationUrl(host, userCode, options.protocol);
|
|
243
304
|
const expiresIn = auth.expires_in ?? 300;
|
|
244
305
|
emit("");
|
|
245
306
|
emit(`Verification code: ${userCode}`);
|
|
@@ -255,21 +316,47 @@ async function runDeviceFlow(host, options = {}, onStatus) {
|
|
|
255
316
|
}
|
|
256
317
|
emit("");
|
|
257
318
|
}
|
|
258
|
-
return pollDeviceFlow(host, auth.device_code, { intervalMs: (auth.interval ?? 5) * 1e3, expiresIn }, onStatus);
|
|
319
|
+
return pollDeviceFlow(host, auth.device_code, { intervalMs: (auth.interval ?? 5) * 1e3, expiresIn, protocol: options.protocol }, onStatus);
|
|
259
320
|
}
|
|
260
321
|
function sleep(ms) {
|
|
261
322
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
262
323
|
}
|
|
263
324
|
|
|
325
|
+
// src/core/login-device-flow.ts
|
|
326
|
+
function resolveLegacyLoginBase(host) {
|
|
327
|
+
const base = host.replace(/\/+$/, "");
|
|
328
|
+
const basePath = process.env.TE_CLAUDE_BASE_PATH || "/agent";
|
|
329
|
+
return base.endsWith(basePath) ? base : base + basePath;
|
|
330
|
+
}
|
|
331
|
+
function resolveDeviceSessionRoute(host, deviceCode) {
|
|
332
|
+
return deviceCode.startsWith("uba_") ? { baseUrl: host, protocol: "uba" } : { baseUrl: resolveLegacyLoginBase(host), protocol: "legacy" };
|
|
333
|
+
}
|
|
334
|
+
async function authorizeLoginDevice(host) {
|
|
335
|
+
try {
|
|
336
|
+
const authorization = await authorizeDevice(host, "uba");
|
|
337
|
+
if (!/^uba_[A-Za-z0-9_-]+$/.test(authorization.device_code)) {
|
|
338
|
+
throw new Error("UBA authorization returned an unsupported device-code format. Check the server deployment.");
|
|
339
|
+
}
|
|
340
|
+
return { baseUrl: host, protocol: "uba", authorization };
|
|
341
|
+
} catch (error) {
|
|
342
|
+
if (!(error instanceof DeviceFlowUnsupportedError) || error.httpStatus !== 404) throw error;
|
|
343
|
+
const baseUrl = resolveLegacyLoginBase(host);
|
|
344
|
+
return { baseUrl, protocol: "legacy", authorization: await authorizeDevice(baseUrl) };
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
|
|
264
348
|
// src/commands/auth.ts
|
|
265
349
|
var HOST_OPTION_DESC = "Override active AE host URL (e.g., https://ta.thinkingdata.cn)";
|
|
350
|
+
function shellArgument(value) {
|
|
351
|
+
return `'${value.replace(/'/g, `'\\''`)}'`;
|
|
352
|
+
}
|
|
266
353
|
function getExplicitAuthHostOverride(program, opts) {
|
|
267
354
|
return opts.host || program.opts().host;
|
|
268
355
|
}
|
|
269
356
|
function resolveAuthHost(program, opts) {
|
|
270
357
|
return resolveHost(getExplicitAuthHostOverride(program, opts));
|
|
271
358
|
}
|
|
272
|
-
async function validateExistingCliToken(host, cliToken) {
|
|
359
|
+
async function validateExistingCliToken(host, cliToken, external = false) {
|
|
273
360
|
try {
|
|
274
361
|
return { valid: true, trusted: false, details: await validateCliTokenOnServer(host, cliToken) };
|
|
275
362
|
} catch (error) {
|
|
@@ -286,7 +373,7 @@ async function validateExistingCliToken(host, cliToken) {
|
|
|
286
373
|
printError(
|
|
287
374
|
"auth",
|
|
288
375
|
error.message,
|
|
289
|
-
`Run: ae-cli auth logout --host ${host}, then ae-cli auth login --host ${host}`
|
|
376
|
+
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
377
|
);
|
|
291
378
|
process.exitCode = 1;
|
|
292
379
|
return { valid: false, trusted: false, details: {} };
|
|
@@ -506,12 +593,16 @@ function manualTokenSummary(host, credential) {
|
|
|
506
593
|
};
|
|
507
594
|
}
|
|
508
595
|
function resolveLoginTeClaudeBase(host) {
|
|
509
|
-
|
|
510
|
-
const basePath = process.env.TE_CLAUDE_BASE_PATH || "/agent";
|
|
511
|
-
return base.endsWith(basePath) ? base : base + basePath;
|
|
596
|
+
return resolveLegacyLoginBase(host);
|
|
512
597
|
}
|
|
513
598
|
function registerAuth(program) {
|
|
514
599
|
const auth = program.command("auth").description("Manage authentication or switch the active account interactively").hook("preAction", (_command, actionCommand) => {
|
|
600
|
+
if (["auth", "login", "set-token", "use", "logout"].includes(actionCommand.name()) && readExternalCliToken()) {
|
|
601
|
+
throw new ExternalCliTokenError(
|
|
602
|
+
"Stored-account changes are unavailable while an external CLI token is selected.",
|
|
603
|
+
"EXTERNAL_CLI_TOKEN_ACTIVE"
|
|
604
|
+
);
|
|
605
|
+
}
|
|
515
606
|
if (["login", "set-token"].includes(actionCommand.name())) {
|
|
516
607
|
const host = resolveAuthHost(program, actionCommand.opts());
|
|
517
608
|
if (host) assertCredentialsReadable(host);
|
|
@@ -536,32 +627,37 @@ function registerAuth(program) {
|
|
|
536
627
|
}
|
|
537
628
|
const noBrowser = !opts.browser;
|
|
538
629
|
const format = program.opts().format || "json";
|
|
539
|
-
const teClaudeBase = resolveLoginTeClaudeBase(host);
|
|
540
630
|
const emit = (message) => process.stderr.write(`[ae-cli] ${message}
|
|
541
631
|
`);
|
|
542
632
|
try {
|
|
543
633
|
if (opts.deviceCode) {
|
|
544
|
-
const
|
|
634
|
+
const route = resolveDeviceSessionRoute(host, opts.deviceCode);
|
|
635
|
+
const tokens2 = await pollDeviceFlow(route.baseUrl, opts.deviceCode, { protocol: route.protocol }, emit);
|
|
545
636
|
const saved2 = await persistDeviceTokens(host, tokens2, { add: opts.add });
|
|
546
637
|
activateHostAfterLogin(host, explicitHost);
|
|
547
638
|
emit("Login successful! CLI token saved securely.");
|
|
548
639
|
await printOutput(loginSummary(host, saved2), format);
|
|
549
640
|
return;
|
|
550
641
|
}
|
|
642
|
+
const session = await authorizeLoginDevice(host);
|
|
643
|
+
const authResp = session.authorization;
|
|
551
644
|
if (opts.wait === false) {
|
|
552
|
-
const authResp = await authorizeDevice(teClaudeBase);
|
|
553
645
|
const addFlag = opts.add ? " --add" : "";
|
|
554
646
|
await printOutput({
|
|
555
647
|
device_code: authResp.device_code,
|
|
556
648
|
user_code: authResp.user_code,
|
|
557
|
-
verification_url: buildVerificationUrl(
|
|
649
|
+
verification_url: buildVerificationUrl(session.baseUrl, authResp.user_code, session.protocol),
|
|
558
650
|
interval: authResp.interval,
|
|
559
651
|
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}`
|
|
652
|
+
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
653
|
}, format);
|
|
562
654
|
return;
|
|
563
655
|
}
|
|
564
|
-
const tokens = await runDeviceFlow(
|
|
656
|
+
const tokens = await runDeviceFlow(session.baseUrl, {
|
|
657
|
+
noBrowser,
|
|
658
|
+
protocol: session.protocol,
|
|
659
|
+
authorization: authResp
|
|
660
|
+
}, emit);
|
|
565
661
|
const saved = await persistDeviceTokens(host, tokens, { add: opts.add });
|
|
566
662
|
activateHostAfterLogin(host, explicitHost);
|
|
567
663
|
emit("Login successful! CLI token saved securely.");
|
|
@@ -644,6 +740,22 @@ function registerAuth(program) {
|
|
|
644
740
|
}, program.opts().format || "json");
|
|
645
741
|
return;
|
|
646
742
|
}
|
|
743
|
+
const external = readExternalCliToken(host);
|
|
744
|
+
if (external) {
|
|
745
|
+
const state = await validateExistingCliToken(host, external.token, true);
|
|
746
|
+
if (!state.valid) return;
|
|
747
|
+
await printOutput({
|
|
748
|
+
authenticated: true,
|
|
749
|
+
host,
|
|
750
|
+
source: external.source,
|
|
751
|
+
cli_token: {
|
|
752
|
+
status: state.trusted ? "trusted" : "valid",
|
|
753
|
+
...state.details.cliTokenExpiresAt ? { expires_at: state.details.cliTokenExpiresAt } : {}
|
|
754
|
+
},
|
|
755
|
+
...state.details.account ? { account: accountOutput(state.details.account) } : {}
|
|
756
|
+
}, program.opts().format || "json");
|
|
757
|
+
return;
|
|
758
|
+
}
|
|
647
759
|
const active = getActiveCredential(host);
|
|
648
760
|
if (active) {
|
|
649
761
|
const state = await validateExistingCliToken(host, active.cliToken);
|