@thinkingai/ae-cli 6.1.14 → 6.1.17
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 +5 -2
- package/README.zh.md +5 -2
- package/dist/{auth-GBMV6TEJ.js → auth-2WTQOP77.js} +3 -3
- package/dist/{auth-NDSXE54J.js → auth-77BUFLGC.js} +57 -13
- package/dist/{capability-TAMDRZYV.js → capability-72DTW5M2.js} +9 -9
- package/dist/{capability-U7TDEEEG.js → capability-PJHNI4GJ.js} +9 -9
- package/dist/{chunk-AFXA7BRK.js → chunk-4KVPKXFX.js} +5 -5
- package/dist/chunk-4SGZG4XY.js +311 -0
- package/dist/chunk-6EIJSNBD.js +8 -0
- package/dist/chunk-C4MGVGJW.js +13 -0
- package/dist/{chunk-WZRX4KOH.js → chunk-GT46FPXN.js} +4 -6
- package/dist/{chunk-5XUSIK27.js → chunk-ILIU36SU.js} +10 -7
- package/dist/{chunk-JHENBQ5B.js → chunk-LYVNONC4.js} +0 -35
- package/dist/{chunk-JUW4AJXN.js → chunk-P3FGXJTU.js} +12 -7
- package/dist/chunk-QGM4M3NI.js +37 -0
- package/dist/{chunk-753BUTNZ.js → chunk-RGKJGKT7.js} +2 -2
- package/dist/{chunk-UIHQJK5E.js → chunk-SAU3QFIQ.js} +3 -3
- package/dist/{chunk-VLWOLBGZ.js → chunk-UOUS37JQ.js} +149 -161
- package/dist/{chunk-AXDXJTPC.js → chunk-UW5UN47B.js} +19 -2
- package/dist/chunk-VPKZ7I72.js +509 -0
- package/dist/{chunk-QATA32VR.js → chunk-VR3LCBHW.js} +2 -2
- package/dist/{chunk-IBH3LDAH.js → chunk-YA6SMTXG.js} +3 -3
- package/dist/chunk-ZZUOD757.js +598 -0
- package/dist/{client-L2YDMHQ6.js → client-TKG4WBHN.js} +4 -5
- package/dist/{community-report-client-M2RW4MXD.js → community-report-client-FI4LNVYS.js} +3 -2
- package/dist/{config-OL2LWGBV.js → config-RE6CMGPK.js} +7 -7
- package/dist/data-integration-XQYB4X4F.js +3503 -0
- package/dist/index.js +68 -34
- package/dist/local-data-upload-client-BWHSUQQK.js +167 -0
- package/dist/{memory-MUP7PPL7.js → memory-CHRU2F7W.js} +7 -6
- package/dist/{memory-U4O5PMXH.js → memory-YK33G4T7.js} +7 -6
- package/dist/{metadata-5MIMNIMT.js → metadata-UILXHBWF.js} +10 -9
- package/dist/{metadata-LERKDJN6.js → metadata-XXR34N5P.js} +10 -9
- package/dist/{model-JTUEO5M4.js → model-K3KLWIW6.js} +7 -3
- package/dist/model-NR3JHFSJ.js +139 -0
- package/dist/{sync-MOSFNBVR.js → sync-DAVKYVMW.js} +8 -6
- package/dist/sync-FCKOVWWS.js +10261 -0
- package/dist/{te-agent-IFKZDHZI.js → te-agent-4BKBODMF.js} +686 -71
- package/dist/te-agent-HLW4VTQK.js +3893 -0
- package/dist/{te-analysis-FCHRTNIY.js → te-analysis-O6DCO6BS.js} +36 -13
- package/dist/{te-analysis-QG7UKGDA.js → te-analysis-ZMNGOVNW.js} +36 -13
- package/dist/{te-community-HNKVTERD.js → te-community-6HPBWJUZ.js} +24 -19
- package/dist/{te-community-IWE5B7W6.js → te-community-HLC43QKH.js} +24 -20
- package/dist/{te-dataops-KXCEB4CS.js → te-dataops-EJP56W3K.js} +57 -34
- package/dist/{te-dataops-KQPYNAE3.js → te-dataops-HDRUXY4K.js} +59 -34
- package/dist/{te-engage-D6EG3NOR.js → te-engage-FGBGQ4IY.js} +9 -8
- package/dist/{te-engage-ZSMIJLUW.js → te-engage-RAK5PESW.js} +9 -8
- package/dist/{te-experiment-K5US7RMG.js → te-experiment-SO5MPDMJ.js} +9 -8
- package/dist/{te-experiment-WA7TFMEL.js → te-experiment-VZF7BT6G.js} +9 -8
- package/dist/{te-kb-OIH3T6CS.js → te-kb-SQCLHG6X.js} +250 -126
- package/dist/{te-system-AZ3URMUO.js → te-system-YARIK4S5.js} +7 -4
- package/dist/te-system-Z77IKZFN.js +2213 -0
- package/dist/{te-team-GZPU6UWA.js → te-team-EFKWYKMK.js} +7 -7
- package/dist/{update-TOBFXF2V.js → update-OGPSZM5A.js} +7 -7
- package/package.json +14 -3
- package/skills/ae-agent/SKILL.md +21 -11
- package/skills/ae-agent/references/approval-effect.md +44 -0
- package/skills/ae-agent/references/approval-request.md +46 -0
- package/skills/ae-agent/references/approval-task.md +45 -0
- package/skills/ae-agent/references/approval-type.md +32 -0
- package/skills/ae-agent/references/command_index.md +19 -0
- package/skills/ae-analysis/SKILL.md +11 -7
- package/skills/ae-analysis/references/adhoc_run.md +2 -0
- package/skills/ae-analysis/references/ai_models.md +27 -0
- package/skills/ae-analysis/references/analysis_gateway_assets.md +3 -2
- package/skills/ae-analysis/references/command_index.md +4 -1
- package/skills/ae-analysis/references/dashboard_get.md +8 -2
- package/skills/ae-analysis/references/dashboard_report_data_run.md +3 -1
- package/skills/ae-analysis/references/dashboard_update.md +4 -1
- package/skills/ae-analysis/references/project_space_business_filter_upsert.md +17 -0
- package/skills/ae-analysis/references/user_tag_models.md +4 -4
- package/skills/ae-data-integration/SKILL.md +54 -0
- package/skills/ae-data-integration/references/handoff.md +43 -0
- package/skills/ae-data-integration/references/local-analysis.md +27 -0
- package/skills/ae-data-integration/references/reuse.md +41 -0
- package/skills/ae-data-integration/references/sink-upload.md +58 -0
- package/skills/ae-data-integration/references/source-inspect.md +68 -0
- package/skills/ae-data-integration/references/sync-json-upload.md +60 -0
- package/skills/ae-data-integration/references/tracking-plan.md +35 -0
- package/skills/ae-data-integration/references/transform.md +65 -0
- package/skills/ae-data-integration/references/ue-mapping.md +142 -0
- package/skills/ae-data-integration/references/ue-routing.md +35 -0
- package/skills/ae-data-integration-helper/SKILL.md +1 -1
- package/skills/ae-dataops/SKILL.md +1 -1
- package/skills/ae-dataops/references/dataops-query.md +4 -4
- package/skills/ae-generate-tracking-plan/SKILL.md +54 -3
- package/skills/ae-kb/SKILL.md +55 -50
- package/skills/ae-kb/references/query-workflow.md +112 -0
- package/skills/ae-kb-discovery/SKILL.md +105 -0
- package/skills/ae-metadata/SKILL.md +0 -1
- package/dist/chunk-3FY3RJ26.js +0 -293
- package/dist/chunk-S5NTSDBS.js +0 -198
- package/dist/chunk-ZQKDZXDO.js +0 -317
- package/dist/cli-token-4UPER74P.js +0 -21
package/README.md
CHANGED
|
@@ -200,7 +200,10 @@ ae-cli kb +add --name engineering-handbook --files '["./docs/guide.md","https://
|
|
|
200
200
|
ae-cli kb +schema --name engineering-handbook
|
|
201
201
|
ae-cli kb +compile --name engineering-handbook
|
|
202
202
|
ae-cli kb +status --name engineering-handbook
|
|
203
|
-
ae-cli kb +
|
|
203
|
+
ae-cli kb +ask -q "How is the sandbox configured?"
|
|
204
|
+
# Submit only, poll later:
|
|
205
|
+
ae-cli kb +ask -q "Another question" --no-wait
|
|
206
|
+
ae-cli kb +ask-status --execution-id <id>
|
|
204
207
|
```
|
|
205
208
|
|
|
206
209
|
External Agents can use deterministic retrieval without a server-side LLM:
|
|
@@ -208,7 +211,7 @@ External Agents can use deterministic retrieval without a server-side LLM:
|
|
|
208
211
|
```bash
|
|
209
212
|
ae-cli kb +list
|
|
210
213
|
ae-cli kb +index --sources '[{"scope":"company","name":"engineering-handbook"}]'
|
|
211
|
-
ae-cli kb +grep -q "sandbox config" --sources '[{"scope":"company","name":"engineering-handbook"}]'
|
|
214
|
+
ae-cli kb +grep -q "sandbox config" --sources '[{"scope":"company","name":"engineering-handbook"}]' --paths '["wiki/sandbox.md"]'
|
|
212
215
|
ae-cli kb +read --source '{"scope":"company","name":"engineering-handbook"}' --path "wiki/sandbox.md"
|
|
213
216
|
```
|
|
214
217
|
|
package/README.zh.md
CHANGED
|
@@ -200,7 +200,10 @@ ae-cli kb +add --name engineering-handbook --files '["./docs/guide.md","https://
|
|
|
200
200
|
ae-cli kb +schema --name engineering-handbook
|
|
201
201
|
ae-cli kb +compile --name engineering-handbook
|
|
202
202
|
ae-cli kb +status --name engineering-handbook
|
|
203
|
-
ae-cli kb +
|
|
203
|
+
ae-cli kb +ask -q "如何配置沙盒?"
|
|
204
|
+
# 仅提交,后续轮询:
|
|
205
|
+
ae-cli kb +ask -q "另一个问题" --no-wait
|
|
206
|
+
ae-cli kb +ask-status --execution-id <id>
|
|
204
207
|
```
|
|
205
208
|
|
|
206
209
|
外部 Agent 可以使用不依赖服务端 LLM 的确定性检索:
|
|
@@ -208,7 +211,7 @@ ae-cli kb +query -q "如何配置沙盒?" --top-k 10
|
|
|
208
211
|
```bash
|
|
209
212
|
ae-cli kb +list
|
|
210
213
|
ae-cli kb +index --sources '[{"scope":"company","name":"engineering-handbook"}]'
|
|
211
|
-
ae-cli kb +grep -q "沙盒配置" --sources '[{"scope":"company","name":"engineering-handbook"}]'
|
|
214
|
+
ae-cli kb +grep -q "沙盒配置" --sources '[{"scope":"company","name":"engineering-handbook"}]' --paths '["wiki/sandbox.md"]'
|
|
212
215
|
ae-cli kb +read --source '{"scope":"company","name":"engineering-handbook"}' --path "wiki/sandbox.md"
|
|
213
216
|
```
|
|
214
217
|
|
|
@@ -3,9 +3,9 @@ import {
|
|
|
3
3
|
invalidateAccessTokenForRetry,
|
|
4
4
|
resolveHost,
|
|
5
5
|
validateToken
|
|
6
|
-
} from "./chunk-
|
|
7
|
-
import "./chunk-
|
|
8
|
-
import "./chunk-
|
|
6
|
+
} from "./chunk-ZZUOD757.js";
|
|
7
|
+
import "./chunk-LYVNONC4.js";
|
|
8
|
+
import "./chunk-QGM4M3NI.js";
|
|
9
9
|
export {
|
|
10
10
|
getToken,
|
|
11
11
|
invalidateAccessTokenForRetry,
|
|
@@ -5,29 +5,33 @@ import {
|
|
|
5
5
|
printError,
|
|
6
6
|
printOutput,
|
|
7
7
|
runHostCompatCheck
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-GT46FPXN.js";
|
|
9
9
|
import {
|
|
10
10
|
clearCliToken,
|
|
11
|
-
mintCliToken
|
|
12
|
-
|
|
11
|
+
mintCliToken,
|
|
12
|
+
validateCliTokenOnServer
|
|
13
|
+
} from "./chunk-4SGZG4XY.js";
|
|
13
14
|
import {
|
|
15
|
+
SecureStoreAuthError,
|
|
14
16
|
clear,
|
|
17
|
+
getFallbackCliToken,
|
|
15
18
|
load,
|
|
19
|
+
loadConfig,
|
|
16
20
|
missingAeHostGuidance,
|
|
17
21
|
missingAeHostHint,
|
|
18
|
-
resolveHost,
|
|
19
|
-
save
|
|
20
|
-
} from "./chunk-ZQKDZXDO.js";
|
|
21
|
-
import {
|
|
22
|
-
getFallbackCliToken,
|
|
23
|
-
loadConfig,
|
|
24
22
|
normalizeUrl,
|
|
25
23
|
removeHost,
|
|
24
|
+
resolveHost,
|
|
25
|
+
save,
|
|
26
26
|
saveConfig
|
|
27
|
-
} from "./chunk-
|
|
27
|
+
} from "./chunk-ZZUOD757.js";
|
|
28
|
+
import {
|
|
29
|
+
PermissionError
|
|
30
|
+
} from "./chunk-UW5UN47B.js";
|
|
28
31
|
import {
|
|
29
32
|
logger
|
|
30
|
-
} from "./chunk-
|
|
33
|
+
} from "./chunk-LYVNONC4.js";
|
|
34
|
+
import "./chunk-QGM4M3NI.js";
|
|
31
35
|
|
|
32
36
|
// src/core/device-auth.ts
|
|
33
37
|
import { execFileSync } from "child_process";
|
|
@@ -142,6 +146,19 @@ async function pollDeviceToken(host, deviceCode) {
|
|
|
142
146
|
if (err === "expired_token") return { status: "expired" };
|
|
143
147
|
return { status: "error", message: `Unknown error: ${err ?? "unknown"}` };
|
|
144
148
|
}
|
|
149
|
+
if (resp.status === 403) {
|
|
150
|
+
let errorBody = {};
|
|
151
|
+
try {
|
|
152
|
+
errorBody = await resp.json();
|
|
153
|
+
} catch {
|
|
154
|
+
}
|
|
155
|
+
return {
|
|
156
|
+
status: "denied",
|
|
157
|
+
code: errorBody.code ?? "CLI_ACCESS_DISABLED",
|
|
158
|
+
message: errorBody.message ?? errorBody.error ?? "CLI access is disabled for this account.",
|
|
159
|
+
hint: errorBody.hint
|
|
160
|
+
};
|
|
161
|
+
}
|
|
145
162
|
const contentType = resp.headers.get("content-type");
|
|
146
163
|
const text = await resp.text().catch(() => "");
|
|
147
164
|
if (looksLikeMissingEndpoint(resp.status, contentType, text)) {
|
|
@@ -186,6 +203,9 @@ async function pollDeviceFlow(host, deviceCode, options = {}, onStatus) {
|
|
|
186
203
|
`Device code has expired. Please run ae-cli auth login again to restart the authorization flow.`
|
|
187
204
|
);
|
|
188
205
|
}
|
|
206
|
+
if (result.status === "denied") {
|
|
207
|
+
throw new PermissionError(result.message, result.code, result.hint);
|
|
208
|
+
}
|
|
189
209
|
if (result.status === "unsupported") {
|
|
190
210
|
throw new DeviceFlowUnsupportedError();
|
|
191
211
|
}
|
|
@@ -239,6 +259,19 @@ function getExplicitAuthHostOverride(program, opts) {
|
|
|
239
259
|
function resolveAuthHost(program, opts) {
|
|
240
260
|
return resolveHost(getExplicitAuthHostOverride(program, opts));
|
|
241
261
|
}
|
|
262
|
+
async function validateExistingCliToken(host, cliToken) {
|
|
263
|
+
try {
|
|
264
|
+
await validateCliTokenOnServer(host, cliToken);
|
|
265
|
+
return true;
|
|
266
|
+
} catch (error) {
|
|
267
|
+
if (!(error instanceof SecureStoreAuthError)) {
|
|
268
|
+
throw error;
|
|
269
|
+
}
|
|
270
|
+
printError("auth", error.message);
|
|
271
|
+
process.exitCode = 1;
|
|
272
|
+
return false;
|
|
273
|
+
}
|
|
274
|
+
}
|
|
242
275
|
function activateHostAfterLogin(host, explicitHostOverride) {
|
|
243
276
|
if (!explicitHostOverride) return;
|
|
244
277
|
const normalized = normalizeUrl(host);
|
|
@@ -259,12 +292,13 @@ async function persistDeviceTokens(host, tokens) {
|
|
|
259
292
|
expiresInSeconds = DEFAULT_EXPIRES_IN;
|
|
260
293
|
}
|
|
261
294
|
const expiresAt = new Date(Date.now() + expiresInSeconds * 1e3).toISOString();
|
|
295
|
+
const cliToken = await mintCliToken(host, tokens.access_token, false);
|
|
262
296
|
save(host, {
|
|
263
297
|
accessToken: tokens.access_token,
|
|
264
298
|
refreshToken: tokens.refresh_token ?? "",
|
|
265
|
-
accessExpiresAt: expiresAt
|
|
299
|
+
accessExpiresAt: expiresAt,
|
|
300
|
+
cliToken
|
|
266
301
|
});
|
|
267
|
-
await mintCliToken(host);
|
|
268
302
|
await runHostCompatCheck(getLocalCliPackageInfo(), host);
|
|
269
303
|
}
|
|
270
304
|
function loginSummary(host, tokens) {
|
|
@@ -344,6 +378,10 @@ function registerAuth(program) {
|
|
|
344
378
|
);
|
|
345
379
|
process.exit(1);
|
|
346
380
|
}
|
|
381
|
+
if (err instanceof PermissionError) {
|
|
382
|
+
printError("permission", err.message, err.hint, err.code);
|
|
383
|
+
process.exit(1);
|
|
384
|
+
}
|
|
347
385
|
printError("auth", err.message);
|
|
348
386
|
process.exit(1);
|
|
349
387
|
}
|
|
@@ -364,6 +402,9 @@ function registerAuth(program) {
|
|
|
364
402
|
}
|
|
365
403
|
const secureEntry = load(host);
|
|
366
404
|
if (secureEntry) {
|
|
405
|
+
if (secureEntry.cliToken && !await validateExistingCliToken(host, secureEntry.cliToken)) {
|
|
406
|
+
return;
|
|
407
|
+
}
|
|
367
408
|
const pastStaticExpiry = new Date(secureEntry.accessExpiresAt).getTime() < Date.now();
|
|
368
409
|
await printOutput(
|
|
369
410
|
{
|
|
@@ -381,6 +422,9 @@ function registerAuth(program) {
|
|
|
381
422
|
}
|
|
382
423
|
const fallbackCliToken = getFallbackCliToken(host);
|
|
383
424
|
if (fallbackCliToken) {
|
|
425
|
+
if (!await validateExistingCliToken(host, fallbackCliToken)) {
|
|
426
|
+
return;
|
|
427
|
+
}
|
|
384
428
|
await printOutput(
|
|
385
429
|
{
|
|
386
430
|
authenticated: true,
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
import {
|
|
10
10
|
printError,
|
|
11
11
|
printOutput
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-GT46FPXN.js";
|
|
13
13
|
import {
|
|
14
14
|
CapabilityGatewayError,
|
|
15
15
|
dryRunCapability,
|
|
@@ -17,19 +17,19 @@ import {
|
|
|
17
17
|
inspectCapability,
|
|
18
18
|
listCapabilities,
|
|
19
19
|
validateCapability
|
|
20
|
-
} from "./chunk-
|
|
21
|
-
import "./chunk-
|
|
20
|
+
} from "./chunk-P3FGXJTU.js";
|
|
21
|
+
import "./chunk-C4MGVGJW.js";
|
|
22
|
+
import "./chunk-4SGZG4XY.js";
|
|
22
23
|
import {
|
|
23
24
|
SecureStoreAuthError,
|
|
24
|
-
resolveHost
|
|
25
|
-
} from "./chunk-ZQKDZXDO.js";
|
|
26
|
-
import {
|
|
25
|
+
resolveHost,
|
|
27
26
|
safeJsonParse
|
|
28
|
-
} from "./chunk-
|
|
27
|
+
} from "./chunk-ZZUOD757.js";
|
|
29
28
|
import {
|
|
30
29
|
PermissionError
|
|
31
|
-
} from "./chunk-
|
|
32
|
-
import "./chunk-
|
|
30
|
+
} from "./chunk-UW5UN47B.js";
|
|
31
|
+
import "./chunk-LYVNONC4.js";
|
|
32
|
+
import "./chunk-QGM4M3NI.js";
|
|
33
33
|
|
|
34
34
|
// src/commands/capability/index.ts
|
|
35
35
|
import * as readline from "readline";
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
import {
|
|
10
10
|
printError,
|
|
11
11
|
printOutput
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-GT46FPXN.js";
|
|
13
13
|
import {
|
|
14
14
|
CapabilityGatewayError,
|
|
15
15
|
dryRunCapability,
|
|
@@ -17,19 +17,19 @@ import {
|
|
|
17
17
|
inspectCapability,
|
|
18
18
|
listCapabilities,
|
|
19
19
|
validateCapability
|
|
20
|
-
} from "./chunk-
|
|
21
|
-
import "./chunk-
|
|
20
|
+
} from "./chunk-ILIU36SU.js";
|
|
21
|
+
import "./chunk-6EIJSNBD.js";
|
|
22
|
+
import "./chunk-4SGZG4XY.js";
|
|
22
23
|
import {
|
|
23
24
|
SecureStoreAuthError,
|
|
24
|
-
resolveHost
|
|
25
|
-
} from "./chunk-ZQKDZXDO.js";
|
|
26
|
-
import {
|
|
25
|
+
resolveHost,
|
|
27
26
|
safeJsonParse
|
|
28
|
-
} from "./chunk-
|
|
27
|
+
} from "./chunk-ZZUOD757.js";
|
|
29
28
|
import {
|
|
30
29
|
PermissionError
|
|
31
|
-
} from "./chunk-
|
|
32
|
-
import "./chunk-
|
|
30
|
+
} from "./chunk-UW5UN47B.js";
|
|
31
|
+
import "./chunk-LYVNONC4.js";
|
|
32
|
+
import "./chunk-QGM4M3NI.js";
|
|
33
33
|
|
|
34
34
|
// src/commands/capability/index.ts
|
|
35
35
|
import * as readline from "readline";
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
getCliToken
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-4SGZG4XY.js";
|
|
4
4
|
import {
|
|
5
5
|
safeJsonParse
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-ZZUOD757.js";
|
|
7
7
|
import {
|
|
8
8
|
PermissionError
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-UW5UN47B.js";
|
|
10
10
|
|
|
11
11
|
// src/core/mcp-access.ts
|
|
12
12
|
function buildUrl(host, path, params = {}) {
|
|
@@ -33,13 +33,13 @@ function parseKbResponse(resp, text) {
|
|
|
33
33
|
}
|
|
34
34
|
if (resp.status === 401) {
|
|
35
35
|
throw new Error(
|
|
36
|
-
`KB
|
|
36
|
+
`KB API token auth failed: HTTP ${resp.status} ${resp.statusText}`
|
|
37
37
|
);
|
|
38
38
|
}
|
|
39
39
|
const data = safeJsonParse(text);
|
|
40
40
|
if (data.return_code === -1001) {
|
|
41
41
|
throw new Error(
|
|
42
|
-
`KB
|
|
42
|
+
`KB API token auth failed: ${data.return_message || "unauthorized"} (code: ${data.return_code})`
|
|
43
43
|
);
|
|
44
44
|
}
|
|
45
45
|
if (data.return_code !== 0 && data.return_code !== void 0) {
|
|
@@ -0,0 +1,311 @@
|
|
|
1
|
+
import {
|
|
2
|
+
SecureStoreAuthError,
|
|
3
|
+
getActiveHost,
|
|
4
|
+
getConfigDir,
|
|
5
|
+
getFallbackCliToken,
|
|
6
|
+
getToken,
|
|
7
|
+
listHosts,
|
|
8
|
+
load,
|
|
9
|
+
loadCliToken,
|
|
10
|
+
normalizeUrl,
|
|
11
|
+
safeJsonParse,
|
|
12
|
+
safeReadJsonFile,
|
|
13
|
+
save
|
|
14
|
+
} from "./chunk-ZZUOD757.js";
|
|
15
|
+
import {
|
|
16
|
+
PermissionError
|
|
17
|
+
} from "./chunk-UW5UN47B.js";
|
|
18
|
+
import {
|
|
19
|
+
logger
|
|
20
|
+
} from "./chunk-LYVNONC4.js";
|
|
21
|
+
|
|
22
|
+
// src/core/cli-token.ts
|
|
23
|
+
import fs from "fs";
|
|
24
|
+
import path from "path";
|
|
25
|
+
var CLI_TOKEN_GENERATE_PATH = "/v1/ta/cli/token/generate";
|
|
26
|
+
var CLI_TOKEN_RENEW_PATH = "/v1/ta/cli/token/renew";
|
|
27
|
+
var CLI_TOKEN_VALIDATE_PATH = "/v1/ta/cli/token/validate";
|
|
28
|
+
var _cliTokenCache = /* @__PURE__ */ new Map();
|
|
29
|
+
var _renewedLocalDateByHost = /* @__PURE__ */ new Map();
|
|
30
|
+
var _renewInFlightByHost = /* @__PURE__ */ new Map();
|
|
31
|
+
function renewHostKey(hostUrl) {
|
|
32
|
+
return normalizeUrl(hostUrl);
|
|
33
|
+
}
|
|
34
|
+
function renewStateFilePath() {
|
|
35
|
+
return path.join(getConfigDir(), "cli-token-renew.json");
|
|
36
|
+
}
|
|
37
|
+
function localRenewDate(now = /* @__PURE__ */ new Date()) {
|
|
38
|
+
const y = now.getFullYear();
|
|
39
|
+
const m = String(now.getMonth() + 1).padStart(2, "0");
|
|
40
|
+
const d = String(now.getDate()).padStart(2, "0");
|
|
41
|
+
return `${y}-${m}-${d}`;
|
|
42
|
+
}
|
|
43
|
+
function loadRenewStore() {
|
|
44
|
+
try {
|
|
45
|
+
const file = renewStateFilePath();
|
|
46
|
+
if (!fs.existsSync(file)) return {};
|
|
47
|
+
const data = safeReadJsonFile(file);
|
|
48
|
+
if (!data || typeof data !== "object" || Array.isArray(data)) return {};
|
|
49
|
+
return data;
|
|
50
|
+
} catch {
|
|
51
|
+
return {};
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
function saveRenewStore(store) {
|
|
55
|
+
const dir = getConfigDir();
|
|
56
|
+
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
|
|
57
|
+
const file = renewStateFilePath();
|
|
58
|
+
if (Object.keys(store).length === 0) {
|
|
59
|
+
try {
|
|
60
|
+
fs.unlinkSync(file);
|
|
61
|
+
} catch {
|
|
62
|
+
}
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
fs.writeFileSync(file, JSON.stringify(store, null, 2), { encoding: "utf8" });
|
|
66
|
+
try {
|
|
67
|
+
fs.chmodSync(file, 384);
|
|
68
|
+
} catch {
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
function getPersistedRenewDate(hostUrl) {
|
|
72
|
+
const key = renewHostKey(hostUrl);
|
|
73
|
+
const store = loadRenewStore();
|
|
74
|
+
return store[key]?.date ?? (key !== hostUrl ? store[hostUrl]?.date : void 0) ?? null;
|
|
75
|
+
}
|
|
76
|
+
function markRenewSucceeded(hostUrl, date) {
|
|
77
|
+
const key = renewHostKey(hostUrl);
|
|
78
|
+
_renewedLocalDateByHost.set(key, date);
|
|
79
|
+
const store = loadRenewStore();
|
|
80
|
+
if (key !== hostUrl && store[hostUrl]) {
|
|
81
|
+
delete store[hostUrl];
|
|
82
|
+
}
|
|
83
|
+
store[key] = { date };
|
|
84
|
+
saveRenewStore(store);
|
|
85
|
+
}
|
|
86
|
+
function clearRenewState(hostUrl) {
|
|
87
|
+
if (hostUrl) {
|
|
88
|
+
const key = renewHostKey(hostUrl);
|
|
89
|
+
_renewedLocalDateByHost.delete(key);
|
|
90
|
+
_renewInFlightByHost.delete(key);
|
|
91
|
+
if (key !== hostUrl) {
|
|
92
|
+
_renewedLocalDateByHost.delete(hostUrl);
|
|
93
|
+
_renewInFlightByHost.delete(hostUrl);
|
|
94
|
+
}
|
|
95
|
+
const store = loadRenewStore();
|
|
96
|
+
let changed = false;
|
|
97
|
+
for (const k of /* @__PURE__ */ new Set([key, hostUrl])) {
|
|
98
|
+
if (store[k]) {
|
|
99
|
+
delete store[k];
|
|
100
|
+
changed = true;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
if (changed) {
|
|
104
|
+
saveRenewStore(store);
|
|
105
|
+
}
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
_renewedLocalDateByHost.clear();
|
|
109
|
+
_renewInFlightByHost.clear();
|
|
110
|
+
saveRenewStore({});
|
|
111
|
+
}
|
|
112
|
+
async function generateCliToken(hostUrl, accessTokenOverride) {
|
|
113
|
+
const accessToken = accessTokenOverride ?? await getToken(hostUrl);
|
|
114
|
+
const base = hostUrl.replace(/\/+$/, "");
|
|
115
|
+
const url = `${base}${CLI_TOKEN_GENERATE_PATH}`;
|
|
116
|
+
const resp = await fetch(url, {
|
|
117
|
+
method: "GET",
|
|
118
|
+
headers: {
|
|
119
|
+
"Authorization": `bearer ${accessToken}`
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
if (!resp.ok) {
|
|
123
|
+
if (resp.status === 403) {
|
|
124
|
+
const text = await resp.text();
|
|
125
|
+
let body = {};
|
|
126
|
+
try {
|
|
127
|
+
body = text ? safeJsonParse(text) : {};
|
|
128
|
+
} catch {
|
|
129
|
+
}
|
|
130
|
+
const message = body.message ?? body.return_message ?? "CLI access is disabled for this account.";
|
|
131
|
+
const code = body.code ?? (String(message).includes("CLI_ACCESS_DISABLED") ? "CLI_ACCESS_DISABLED" : void 0);
|
|
132
|
+
throw new PermissionError(message, code, body.hint);
|
|
133
|
+
}
|
|
134
|
+
throw new Error(`CLI token generate HTTP error: ${resp.status} ${resp.statusText}`);
|
|
135
|
+
}
|
|
136
|
+
const data = safeJsonParse(await resp.text());
|
|
137
|
+
if (data.return_code !== 0) {
|
|
138
|
+
const message = data.return_message || data.message || "unknown";
|
|
139
|
+
if (data.code === "CLI_ACCESS_DISABLED" || String(message).includes("CLI_ACCESS_DISABLED")) {
|
|
140
|
+
throw new PermissionError(message, "CLI_ACCESS_DISABLED", data.hint);
|
|
141
|
+
}
|
|
142
|
+
throw new Error(`CLI token generate error: ${message} (code: ${data.return_code})`);
|
|
143
|
+
}
|
|
144
|
+
const cliToken = data.data?.userSecret;
|
|
145
|
+
if (!cliToken) {
|
|
146
|
+
throw new Error("CLI token generate error: empty userSecret in response");
|
|
147
|
+
}
|
|
148
|
+
return cliToken;
|
|
149
|
+
}
|
|
150
|
+
async function validateCliTokenOnServer(hostUrl, cliToken) {
|
|
151
|
+
const base = hostUrl.replace(/\/+$/, "");
|
|
152
|
+
const url = `${base}${CLI_TOKEN_VALIDATE_PATH}`;
|
|
153
|
+
let resp;
|
|
154
|
+
try {
|
|
155
|
+
resp = await fetch(url, {
|
|
156
|
+
method: "GET",
|
|
157
|
+
headers: {
|
|
158
|
+
Accept: "application/json",
|
|
159
|
+
"cli-token": cliToken
|
|
160
|
+
}
|
|
161
|
+
});
|
|
162
|
+
} catch (e) {
|
|
163
|
+
throw new SecureStoreAuthError(`Unable to validate CLI token for ${hostUrl}: ${e.message}`);
|
|
164
|
+
}
|
|
165
|
+
const responseText = await resp.text();
|
|
166
|
+
let data;
|
|
167
|
+
try {
|
|
168
|
+
data = safeJsonParse(responseText);
|
|
169
|
+
} catch {
|
|
170
|
+
data = void 0;
|
|
171
|
+
}
|
|
172
|
+
if (resp.status === 401 || resp.status === 403 || data?.return_code !== void 0 && data.return_code !== 0) {
|
|
173
|
+
throw new SecureStoreAuthError(
|
|
174
|
+
`CLI token is invalid or expired for ${hostUrl}. Run: ae-cli auth logout --host ${hostUrl}, then ae-cli auth login --host ${hostUrl}`
|
|
175
|
+
);
|
|
176
|
+
}
|
|
177
|
+
if (!resp.ok) {
|
|
178
|
+
throw new SecureStoreAuthError(
|
|
179
|
+
`CLI token validation failed for ${hostUrl} (HTTP ${resp.status} ${resp.statusText})`
|
|
180
|
+
);
|
|
181
|
+
}
|
|
182
|
+
if (data?.return_code !== 0) {
|
|
183
|
+
throw new SecureStoreAuthError(`CLI token validation returned an invalid response for ${hostUrl}`);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
async function renewCliTokenOnServer(hostUrl, cliToken) {
|
|
187
|
+
const base = hostUrl.replace(/\/+$/, "");
|
|
188
|
+
const url = new URL(`${base}${CLI_TOKEN_RENEW_PATH}`);
|
|
189
|
+
url.searchParams.set("cli-token", cliToken);
|
|
190
|
+
const headers = {
|
|
191
|
+
Accept: "application/json"
|
|
192
|
+
};
|
|
193
|
+
try {
|
|
194
|
+
const accessToken = await getToken(hostUrl);
|
|
195
|
+
if (accessToken) {
|
|
196
|
+
headers.Authorization = `bearer ${accessToken}`;
|
|
197
|
+
}
|
|
198
|
+
} catch {
|
|
199
|
+
}
|
|
200
|
+
const resp = await fetch(url.toString(), { method: "GET", headers });
|
|
201
|
+
const text = await resp.text();
|
|
202
|
+
const data = safeJsonParse(text);
|
|
203
|
+
if (!resp.ok) {
|
|
204
|
+
throw new Error(`CLI token renew HTTP error: ${resp.status} ${resp.statusText}`);
|
|
205
|
+
}
|
|
206
|
+
if (data?.return_code !== void 0 && data.return_code !== 0) {
|
|
207
|
+
throw new Error(`CLI token renew error: ${data.return_message || "unknown"} (code: ${data.return_code})`);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
async function maybeRenewCliTokenDaily(hostUrl, cliToken) {
|
|
211
|
+
const hostKey = renewHostKey(hostUrl);
|
|
212
|
+
const today = localRenewDate();
|
|
213
|
+
if (_renewedLocalDateByHost.get(hostKey) === today) {
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
216
|
+
if (getPersistedRenewDate(hostUrl) === today) {
|
|
217
|
+
_renewedLocalDateByHost.set(hostKey, today);
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
const existing = _renewInFlightByHost.get(hostKey);
|
|
221
|
+
if (existing) {
|
|
222
|
+
await existing;
|
|
223
|
+
return;
|
|
224
|
+
}
|
|
225
|
+
const attempt = (async () => {
|
|
226
|
+
try {
|
|
227
|
+
await renewCliTokenOnServer(hostUrl, cliToken);
|
|
228
|
+
markRenewSucceeded(hostUrl, today);
|
|
229
|
+
logger.info(`cli-token: renewed for ${hostKey} (local day ${today})`);
|
|
230
|
+
} catch (e) {
|
|
231
|
+
logger.warn(`cli-token: renew failed for ${hostKey}: ${e?.message || e}; business call proceeds with cached token`);
|
|
232
|
+
} finally {
|
|
233
|
+
_renewInFlightByHost.delete(hostKey);
|
|
234
|
+
}
|
|
235
|
+
})();
|
|
236
|
+
_renewInFlightByHost.set(hostKey, attempt);
|
|
237
|
+
await attempt;
|
|
238
|
+
}
|
|
239
|
+
function persistCliTokenIfPossible(hostUrl, cliToken) {
|
|
240
|
+
const existing = load(hostUrl);
|
|
241
|
+
if (!existing) {
|
|
242
|
+
logger.info(`cli-token: no secure-store session for ${hostUrl}, keeping token in-process only`);
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
|
+
save(hostUrl, { ...existing, cliToken });
|
|
246
|
+
}
|
|
247
|
+
function clearPersistedCliToken(hostUrl) {
|
|
248
|
+
const existing = load(hostUrl);
|
|
249
|
+
if (existing?.cliToken) {
|
|
250
|
+
save(hostUrl, { ...existing, cliToken: void 0 });
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
function peekCliToken(hostOverride) {
|
|
254
|
+
const hostUrl = hostOverride || getActiveHost();
|
|
255
|
+
if (!hostUrl) return void 0;
|
|
256
|
+
return _cliTokenCache.get(hostUrl) || loadCliToken(hostUrl) || getFallbackCliToken(hostUrl) || void 0;
|
|
257
|
+
}
|
|
258
|
+
async function getCliToken(hostOverride) {
|
|
259
|
+
const hostUrl = hostOverride || getActiveHost();
|
|
260
|
+
let token = _cliTokenCache.get(hostUrl);
|
|
261
|
+
if (!token) {
|
|
262
|
+
const storedToken = loadCliToken(hostUrl);
|
|
263
|
+
if (storedToken) {
|
|
264
|
+
_cliTokenCache.set(hostUrl, storedToken);
|
|
265
|
+
logger.info(`Using persisted CLI token (secure-store) for ${hostUrl}`);
|
|
266
|
+
token = storedToken;
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
if (!token) {
|
|
270
|
+
const fallbackToken = getFallbackCliToken(hostUrl);
|
|
271
|
+
if (fallbackToken) {
|
|
272
|
+
_cliTokenCache.set(hostUrl, fallbackToken);
|
|
273
|
+
logger.info(`Using sandbox-provisioned CLI token (fallback file) for ${hostUrl}`);
|
|
274
|
+
token = fallbackToken;
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
if (!token) {
|
|
278
|
+
token = await mintCliToken(hostUrl);
|
|
279
|
+
}
|
|
280
|
+
await maybeRenewCliTokenDaily(hostUrl, token);
|
|
281
|
+
return token;
|
|
282
|
+
}
|
|
283
|
+
async function mintCliToken(hostUrl, accessTokenOverride, persist = true) {
|
|
284
|
+
logger.info(`Generating CLI token for ${hostUrl}`);
|
|
285
|
+
const cliToken = await generateCliToken(hostUrl, accessTokenOverride);
|
|
286
|
+
_cliTokenCache.set(hostUrl, cliToken);
|
|
287
|
+
if (persist) persistCliTokenIfPossible(hostUrl, cliToken);
|
|
288
|
+
logger.info(`CLI token generated and cached${persist ? " and persisted" : ""} for ${hostUrl}`);
|
|
289
|
+
return cliToken;
|
|
290
|
+
}
|
|
291
|
+
function clearCliToken(hostUrl) {
|
|
292
|
+
if (hostUrl) {
|
|
293
|
+
_cliTokenCache.delete(hostUrl);
|
|
294
|
+
clearPersistedCliToken(hostUrl);
|
|
295
|
+
clearRenewState(hostUrl);
|
|
296
|
+
return;
|
|
297
|
+
}
|
|
298
|
+
_cliTokenCache.clear();
|
|
299
|
+
clearRenewState();
|
|
300
|
+
for (const { url } of listHosts()) {
|
|
301
|
+
clearPersistedCliToken(url);
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
export {
|
|
306
|
+
validateCliTokenOnServer,
|
|
307
|
+
peekCliToken,
|
|
308
|
+
getCliToken,
|
|
309
|
+
mintCliToken,
|
|
310
|
+
clearCliToken
|
|
311
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import {
|
|
2
|
+
isAeSandboxRuntime
|
|
3
|
+
} from "./chunk-ZZUOD757.js";
|
|
4
|
+
|
|
5
|
+
// src/core/internal-call-source.ts
|
|
6
|
+
function internalCallSourceHeaders() {
|
|
7
|
+
const source = isAeSandboxRuntime() ? "te-agent" : "ae-cli";
|
|
8
|
+
return { "X-Source": source };
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export {
|
|
12
|
+
internalCallSourceHeaders
|
|
13
|
+
};
|
|
@@ -1,18 +1,16 @@
|
|
|
1
1
|
import {
|
|
2
2
|
peekCliToken
|
|
3
|
-
} from "./chunk-
|
|
4
|
-
import {
|
|
5
|
-
getToken
|
|
6
|
-
} from "./chunk-ZQKDZXDO.js";
|
|
3
|
+
} from "./chunk-4SGZG4XY.js";
|
|
7
4
|
import {
|
|
8
5
|
getActiveHost,
|
|
9
6
|
getConfigDir,
|
|
7
|
+
getToken,
|
|
10
8
|
isAeSandboxRuntime,
|
|
11
9
|
normalizeUrl
|
|
12
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-ZZUOD757.js";
|
|
13
11
|
import {
|
|
14
12
|
logger
|
|
15
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-LYVNONC4.js";
|
|
16
14
|
|
|
17
15
|
// src/core/version-sync.ts
|
|
18
16
|
import { spawnSync } from "child_process";
|