@thinkingai/ae-cli 6.1.23 → 6.1.25
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -1
- package/README.zh.md +7 -1
- package/dist/{auth-XZNXFRJS.js → auth-LHM7NQPR.js} +167 -7
- package/dist/{capability-FYTU3X6L.js → capability-SJI5KOCK.js} +11 -6
- package/dist/{chunk-CCS66K4K.js → chunk-2FJM4HRV.js} +3 -3
- package/dist/{chunk-57RRFUEZ.js → chunk-5XRQ3CZR.js} +4 -4
- package/dist/{chunk-EQ255HKO.js → chunk-7WZACOAI.js} +2 -2
- package/dist/{chunk-DX5CDO34.js → chunk-BW7JUDEI.js} +84 -19
- package/dist/{chunk-7XGFSUOM.js → chunk-DU72X2IO.js} +271 -76
- package/dist/{chunk-V2NUHPXF.js → chunk-GK7WDY7E.js} +1 -1
- package/dist/{chunk-7FTTULED.js → chunk-IG3DYEIR.js} +4 -1
- package/dist/{chunk-HBGADCKA.js → chunk-KJDOTPYU.js} +3 -3
- package/dist/{chunk-4NRCTUZJ.js → chunk-KS4DE3MX.js} +4 -4
- package/dist/{chunk-JOCDD4ON.js → chunk-N4BLPJC7.js} +1 -1
- package/dist/{chunk-HFGZGYCG.js → chunk-QYXDJOLA.js} +252 -6
- package/dist/{chunk-DVMLWQD4.js → chunk-SO5LKIWP.js} +2 -2
- package/dist/{chunk-VYXXOKYS.js → chunk-XKIW3QMF.js} +7 -4
- package/dist/{chunk-MAPZ7VB6.js → chunk-YVGXGTD6.js} +13 -0
- package/dist/{community-report-client-CU22W53K.js → community-report-client-6VJDDMJJ.js} +1 -1
- package/dist/{config-XO3LI3SA.js → config-XQWOPDHN.js} +25 -6
- package/dist/{context-IFJI3LIT.js → context-M3HDGEIR.js} +4 -4
- package/dist/{data-integration-HNGUKFIC.js → data-integration-XBTCGXQT.js} +6 -6
- package/dist/index.js +78 -41
- package/dist/{local-data-upload-client-GTRIT64F.js → local-data-upload-client-3P7NIVQ4.js} +1 -1
- package/dist/{memory-QGPSNCQS.js → memory-6APEB2JB.js} +4 -4
- package/dist/{metadata-DI5BMYFU.js → metadata-JRYKNUS5.js} +7 -7
- package/dist/{model-RNPQXIBI.js → model-ZS7HVGKN.js} +4 -4
- package/dist/{personal-semantic-preference-5C3WUXFI.js → personal-semantic-preference-IDE2GE5T.js} +8 -6
- package/dist/project-semantic-36KOCYN7.js +356 -0
- package/dist/{sync-O45NXEQY.js → sync-EQLSTUS7.js} +7 -7
- package/dist/{te-agent-K5MSPNHJ.js → te-agent-Z3HCTKR7.js} +348 -55
- package/dist/{te-analysis-AISWCOOZ.js → te-analysis-5ZZ6YHVH.js} +940 -144
- package/dist/{te-community-4OYU3BDA.js → te-community-Z7JACGF3.js} +3 -3
- package/dist/{te-dataops-NFIPB6FX.js → te-dataops-F7GQOIS6.js} +644 -276
- package/dist/{te-engage-BAM3GBFX.js → te-engage-RNRMYDO3.js} +6 -6
- package/dist/{te-experiment-GUTZXZ5Z.js → te-experiment-BTAC2UNK.js} +6 -6
- package/dist/{te-kb-3TS73NO6.js → te-kb-QJLJEX5K.js} +323 -181
- package/dist/{te-system-STMHLS5J.js → te-system-IXC43QHZ.js} +6 -6
- package/dist/{te-team-3I5AOX3N.js → te-team-BIZIKIHZ.js} +6 -6
- package/dist/{update-RZXLPCRH.js → update-W2SGQNKT.js} +4 -4
- package/package.json +11 -4
- package/skills/ae-agent/SKILL.md +9 -4
- package/skills/ae-agent/references/notification.md +40 -0
- package/skills/ae-analysis/SKILL.md +44 -21
- package/skills/ae-analysis/references/adhoc_export.md +1 -1
- package/skills/ae-analysis/references/adhoc_run.md +1 -1
- package/skills/ae-analysis/references/agent_review_submit_to_page.md +3 -1
- package/skills/ae-analysis/references/ai_models/event.md +6 -1
- package/skills/ae-analysis/references/ai_models/funnel.md +7 -1
- package/skills/ae-analysis/references/ai_models/heat_map.md +23 -0
- package/skills/ae-analysis/references/ai_models/interval.md +24 -0
- package/skills/ae-analysis/references/ai_models/path.md +20 -0
- package/skills/ae-analysis/references/ai_models/prop_analysis.md +2 -0
- package/skills/ae-analysis/references/ai_models/rank_list.md +30 -0
- package/skills/ae-analysis/references/ai_models/retention.md +45 -1
- package/skills/ae-analysis/references/ai_models/revenue.md +20 -2
- package/skills/ae-analysis/references/ai_models/session.md +76 -0
- package/skills/ae-analysis/references/ai_models/tag.md +2 -0
- package/skills/ae-analysis/references/ai_models.md +76 -6
- package/skills/ae-analysis/references/analysis_data_retrieval.md +4 -0
- package/skills/ae-analysis/references/analysis_drilldown_contract.md +4 -1
- package/skills/ae-analysis/references/asset_batch_info_export.md +10 -0
- package/skills/ae-analysis/references/asset_batch_sql_export.md +13 -1
- package/skills/ae-analysis/references/asset_export.md +12 -1
- package/skills/ae-analysis/references/asset_list.md +1 -0
- package/skills/ae-analysis/references/asset_search.md +11 -5
- package/skills/ae-analysis/references/bi_panel_list.md +1 -1
- package/skills/ae-analysis/references/catalog_list.md +1 -1
- package/skills/ae-analysis/references/collaboration.md +48 -0
- package/skills/ae-analysis/references/command_index.md +19 -17
- package/skills/ae-analysis/references/dashboard_list.md +4 -4
- package/skills/ae-analysis/references/dashboard_report_data_export.md +2 -0
- package/skills/ae-analysis/references/drilldown_session_details_run.md +41 -0
- package/skills/ae-analysis/references/event_export.md +3 -1
- package/skills/ae-analysis/references/governance_recommendation_auto_review.md +77 -0
- package/skills/ae-analysis/references/governance_recommendation_export.md +11 -0
- package/skills/ae-analysis/references/metadata_resolution.md +3 -3
- package/skills/ae-analysis/references/metric_export.md +3 -1
- package/skills/ae-analysis/references/metric_list.md +1 -1
- package/skills/ae-analysis/references/operation_record_export.md +10 -0
- package/skills/ae-analysis/references/personal_semantic_preference_add.md +2 -2
- package/skills/ae-analysis/references/personal_semantic_preference_get.md +4 -4
- package/skills/ae-analysis/references/personal_semantic_preference_list.md +4 -4
- package/skills/ae-analysis/references/project_semantic_knowledge_wiki.md +30 -12
- package/skills/ae-analysis/references/project_semantic_knowledge_wiki_plan_schema.md +59 -0
- package/skills/ae-analysis/references/property_export.md +3 -1
- package/skills/ae-analysis/references/report_create.md +5 -1
- package/skills/ae-analysis/references/report_data_export.md +6 -0
- package/skills/ae-analysis/references/report_get.md +2 -0
- package/skills/ae-analysis/references/report_list.md +5 -5
- package/skills/ae-analysis/references/report_update.md +7 -1
- package/skills/ae-analysis/references/sql_table_columns.md +4 -4
- package/skills/ae-analysis/references/sql_table_list.md +5 -5
- package/skills/ae-analysis/references/user_cluster_models.md +8 -0
- package/skills/ae-analysis/references/user_tag_create.md +7 -1
- package/skills/ae-analysis/references/user_tag_get.md +1 -1
- package/skills/ae-analysis/references/user_tag_models.md +18 -2
- package/skills/ae-analysis/references/user_tag_refresh.md +1 -1
- package/skills/ae-analysis/references/user_tag_update.md +2 -2
- package/skills/ae-analysis/scripts/project-semantic-knowledge-wiki/build-project-semantic-wiki.mjs +337 -12
- package/skills/ae-analysis/scripts/project-semantic-knowledge-wiki/default-compile-rules.md +8 -3
- package/skills/ae-analysis/scripts/project-semantic-knowledge-wiki/generate-build-ir.mjs +284 -24
- package/skills/ae-analysis/scripts/project-semantic-knowledge-wiki/package-wiki-source-zip.mjs +185 -22
- package/skills/ae-analysis/scripts/project-semantic-knowledge-wiki/precompiled-source.mjs +46 -2
- package/skills/ae-capability/SKILL.md +63 -1
- package/skills/ae-capability/references/collaboration.md +48 -0
- package/skills/ae-community/SKILL.md +5 -1
- package/skills/ae-community/references/collaboration.md +48 -0
- package/skills/ae-data-integration/SKILL.md +4 -0
- package/skills/ae-data-integration/references/collaboration.md +48 -0
- package/skills/ae-data-integration-helper/references/cpp_server_sdk_faq.md +2 -2
- package/skills/ae-data-integration-helper/references/logbus2_parser_plugin.md +6 -6
- package/skills/ae-data-integration-helper/references/sdk_log_guide.md +4 -4
- package/skills/ae-dataops/SKILL.md +54 -74
- package/skills/ae-dataops/references/collaboration.md +48 -0
- package/skills/ae-dataops/references/dataops-backfill.md +23 -18
- package/skills/ae-dataops/references/dataops-flow-create.md +74 -23
- package/skills/ae-dataops/references/dataops-flow-monitor.md +45 -13
- package/skills/ae-dataops/references/dataops-integration.md +57 -30
- package/skills/ae-dataops/references/dataops-query.md +21 -4
- package/skills/ae-dataops/references/dataops-table.md +143 -11
- package/skills/ae-engage/SKILL.md +21 -6
- package/skills/ae-engage/references/add-channel.md +3 -3
- package/skills/ae-engage/references/channel-mgmt.md +3 -3
- package/skills/ae-engage/references/collaboration.md +48 -0
- package/skills/ae-engage/references/common-metric.md +2 -2
- package/skills/ae-engage/references/save-task.md +2 -2
- package/skills/ae-engage/references/scene-config-channel.md +4 -4
- package/skills/ae-generate-tracking-code/SKILL.md +1 -1
- package/skills/ae-generate-tracking-plan/SKILL.md +4 -0
- package/skills/ae-generate-tracking-plan/references/collaboration.md +48 -0
- package/skills/ae-kb/SKILL.md +9 -1
- package/skills/ae-kb/references/collaboration.md +48 -0
- package/skills/ae-kb/references/schema-import.md +30 -0
- package/skills/ae-kb-discovery/SKILL.md +7 -2
- package/skills/ae-kb-discovery/references/collaboration.md +48 -0
- package/skills/ae-metadata/SKILL.md +20 -12
- package/skills/ae-metadata/references/collaboration.md +48 -0
- package/dist/project-semantic-3LF6Q6JZ.js +0 -1119
- package/skills/ae-project-semantic/SKILL.md +0 -193
- package/skills/ae-project-semantic/references/query-routing-v5.md +0 -165
- package/skills/ae-project-semantic/references/recommendation-quality.md +0 -68
|
@@ -6,11 +6,11 @@ import {
|
|
|
6
6
|
normalizeUrl,
|
|
7
7
|
safeJsonParse,
|
|
8
8
|
safeReadJsonFile
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-IG3DYEIR.js";
|
|
10
10
|
import {
|
|
11
11
|
PermissionError,
|
|
12
12
|
logger
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-YVGXGTD6.js";
|
|
14
14
|
|
|
15
15
|
// src/core/secure-store.ts
|
|
16
16
|
import crypto from "crypto";
|
|
@@ -28,7 +28,7 @@ var NONCE_LEN = 12;
|
|
|
28
28
|
function getMachineId() {
|
|
29
29
|
if (process.platform === "darwin") {
|
|
30
30
|
try {
|
|
31
|
-
const out = execFileSync("ioreg", ["-rd1", "-c", "IOPlatformExpertDevice"], {
|
|
31
|
+
const out = execFileSync("/usr/sbin/ioreg", ["-rd1", "-c", "IOPlatformExpertDevice"], {
|
|
32
32
|
encoding: "utf8",
|
|
33
33
|
timeout: 3e3
|
|
34
34
|
});
|
|
@@ -47,36 +47,42 @@ function getMachineId() {
|
|
|
47
47
|
}
|
|
48
48
|
}
|
|
49
49
|
if (process.platform === "win32") {
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
50
|
+
const systemRoot = process.env.SystemRoot || process.env.WINDIR;
|
|
51
|
+
const commands = systemRoot && path.win32.isAbsolute(systemRoot) ? [path.win32.join(systemRoot, "System32", "reg.exe"), "reg"] : ["reg"];
|
|
52
|
+
for (const command of commands) {
|
|
53
|
+
try {
|
|
54
|
+
const out = execFileSync(
|
|
55
|
+
command,
|
|
56
|
+
["query", "HKLM\\SOFTWARE\\Microsoft\\Cryptography", "/v", "MachineGuid"],
|
|
57
|
+
{ encoding: "utf8", timeout: 3e3 }
|
|
58
|
+
);
|
|
59
|
+
const match = out.match(/MachineGuid\s+REG_SZ\s+([0-9a-f-]+)/i);
|
|
60
|
+
if (match?.[1]) return `win32:${match[1]}`;
|
|
61
|
+
} catch {
|
|
62
|
+
}
|
|
59
63
|
}
|
|
60
64
|
}
|
|
61
65
|
logger.warn("secure-store: using fallback machine-id (HOME+hostname+platform)");
|
|
66
|
+
return getFallbackMachineId();
|
|
67
|
+
}
|
|
68
|
+
function getFallbackMachineId() {
|
|
62
69
|
return `fallback:${os.homedir()}|${os.hostname()}|${os.platform()}`;
|
|
63
70
|
}
|
|
64
|
-
var
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
cachedKey = crypto.scryptSync(cachedMachineId, SCRYPT_SALT, KEY_LEN, {
|
|
71
|
+
var cachedKeys;
|
|
72
|
+
function getKeys() {
|
|
73
|
+
if (!cachedKeys) {
|
|
74
|
+
const machineIds = [.../* @__PURE__ */ new Set([getMachineId(), getFallbackMachineId()])];
|
|
75
|
+
cachedKeys = machineIds.map((machineId) => crypto.scryptSync(machineId, SCRYPT_SALT, KEY_LEN, {
|
|
70
76
|
N: SCRYPT_N,
|
|
71
77
|
r: SCRYPT_R,
|
|
72
78
|
p: SCRYPT_P
|
|
73
|
-
});
|
|
79
|
+
}));
|
|
74
80
|
}
|
|
75
|
-
return
|
|
81
|
+
return cachedKeys;
|
|
76
82
|
}
|
|
77
|
-
function encrypt(plaintext) {
|
|
83
|
+
function encrypt(plaintext, key) {
|
|
78
84
|
const nonce = crypto.randomBytes(NONCE_LEN);
|
|
79
|
-
const cipher = crypto.createCipheriv("aes-256-gcm",
|
|
85
|
+
const cipher = crypto.createCipheriv("aes-256-gcm", key, nonce);
|
|
80
86
|
const data = Buffer.concat([cipher.update(plaintext, "utf8"), cipher.final()]);
|
|
81
87
|
return {
|
|
82
88
|
nonce: nonce.toString("hex"),
|
|
@@ -84,8 +90,8 @@ function encrypt(plaintext) {
|
|
|
84
90
|
data: data.toString("hex")
|
|
85
91
|
};
|
|
86
92
|
}
|
|
87
|
-
function decrypt(blob) {
|
|
88
|
-
const decipher = crypto.createDecipheriv("aes-256-gcm",
|
|
93
|
+
function decrypt(blob, key) {
|
|
94
|
+
const decipher = crypto.createDecipheriv("aes-256-gcm", key, Buffer.from(blob.nonce, "hex"));
|
|
89
95
|
decipher.setAuthTag(Buffer.from(blob.tag, "hex"));
|
|
90
96
|
return Buffer.concat([
|
|
91
97
|
decipher.update(Buffer.from(blob.data, "hex")),
|
|
@@ -112,41 +118,81 @@ function ensureStoreDir() {
|
|
|
112
118
|
} catch {
|
|
113
119
|
}
|
|
114
120
|
}
|
|
115
|
-
function
|
|
121
|
+
function stageFile(filePath, contents) {
|
|
116
122
|
ensureStoreDir();
|
|
117
123
|
const tempPath = `${filePath}.${process.pid}.${crypto.randomBytes(6).toString("hex")}.tmp`;
|
|
118
|
-
const blob = encrypt(JSON.stringify(value));
|
|
119
124
|
try {
|
|
120
|
-
fs.writeFileSync(tempPath,
|
|
125
|
+
fs.writeFileSync(tempPath, contents, { encoding: "utf8", mode: 384, flag: "wx" });
|
|
121
126
|
try {
|
|
122
127
|
fs.chmodSync(tempPath, 384);
|
|
123
128
|
} catch {
|
|
124
129
|
}
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
+
return tempPath;
|
|
131
|
+
} catch (error) {
|
|
132
|
+
removeFile(tempPath);
|
|
133
|
+
throw error;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
function prepareEncrypted(filePath, value, companionPath) {
|
|
137
|
+
const existing = readEncryptedFile(filePath);
|
|
138
|
+
const companion = companionPath ? readEncryptedFile(companionPath) : null;
|
|
139
|
+
const key = existing?.key ?? companion?.key ?? getKeys()[0];
|
|
140
|
+
const blob = encrypt(JSON.stringify(value), key);
|
|
141
|
+
return { tempPath: stageFile(filePath, JSON.stringify(blob, null, 2)), previous: existing?.raw ?? null };
|
|
142
|
+
}
|
|
143
|
+
function replaceFile(tempPath, filePath) {
|
|
144
|
+
fs.renameSync(tempPath, filePath);
|
|
145
|
+
try {
|
|
146
|
+
fs.chmodSync(filePath, 384);
|
|
147
|
+
} catch {
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
function atomicWriteEncrypted(filePath, value, companionPath) {
|
|
151
|
+
const { tempPath } = prepareEncrypted(filePath, value, companionPath);
|
|
152
|
+
try {
|
|
153
|
+
replaceFile(tempPath, filePath);
|
|
130
154
|
} finally {
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
155
|
+
removeFile(tempPath);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
function readEncryptedFile(filePath) {
|
|
159
|
+
let raw;
|
|
160
|
+
try {
|
|
161
|
+
raw = fs.readFileSync(filePath, "utf8");
|
|
162
|
+
} catch (error) {
|
|
163
|
+
if (error.code === "ENOENT") {
|
|
164
|
+
try {
|
|
165
|
+
if (!fs.lstatSync(filePath, { throwIfNoEntry: false })) return null;
|
|
166
|
+
} catch {
|
|
167
|
+
}
|
|
134
168
|
}
|
|
169
|
+
throw new CredentialStoreUnreadableError(filePath);
|
|
135
170
|
}
|
|
171
|
+
return decodeEncryptedFile(filePath, raw);
|
|
136
172
|
}
|
|
137
|
-
function
|
|
138
|
-
if (!fs.existsSync(filePath)) return null;
|
|
173
|
+
function decodeEncryptedFile(filePath, raw) {
|
|
139
174
|
try {
|
|
140
|
-
const blob = safeJsonParse(
|
|
141
|
-
if (
|
|
142
|
-
|
|
143
|
-
return null;
|
|
175
|
+
const blob = safeJsonParse(raw);
|
|
176
|
+
if (typeof blob?.nonce !== "string" || !/^[0-9a-f]{24}$/i.test(blob.nonce) || typeof blob?.tag !== "string" || !/^[0-9a-f]{32}$/i.test(blob.tag) || typeof blob?.data !== "string" || !/^(?:[0-9a-f]{2})+$/i.test(blob.data)) {
|
|
177
|
+
throw new Error("Malformed encrypted credential");
|
|
144
178
|
}
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
179
|
+
for (const key of getKeys()) {
|
|
180
|
+
try {
|
|
181
|
+
return { value: safeJsonParse(decrypt(blob, key)), key, raw };
|
|
182
|
+
} catch {
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
} catch {
|
|
186
|
+
}
|
|
187
|
+
throw new CredentialStoreUnreadableError(filePath);
|
|
188
|
+
}
|
|
189
|
+
function readEncrypted(filePath) {
|
|
190
|
+
const result = readEncryptedFile(filePath);
|
|
191
|
+
if (!result) return null;
|
|
192
|
+
if (!result.value || typeof result.value !== "object" || Array.isArray(result.value)) {
|
|
193
|
+
throw new CredentialStoreUnreadableError(filePath);
|
|
149
194
|
}
|
|
195
|
+
return result.value;
|
|
150
196
|
}
|
|
151
197
|
function tokenFingerprint(token) {
|
|
152
198
|
return crypto.createHash("sha256").update(token).digest("hex").slice(0, 24);
|
|
@@ -162,23 +208,139 @@ function legacyProjectionPayload(cliToken) {
|
|
|
162
208
|
cliToken
|
|
163
209
|
};
|
|
164
210
|
}
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
return {
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
211
|
+
var activeWrites = /* @__PURE__ */ new Set();
|
|
212
|
+
function recoveryFilePath(host) {
|
|
213
|
+
return `${vaultFilePath(host)}.rollback`;
|
|
214
|
+
}
|
|
215
|
+
function restoreFile(filePath, previous) {
|
|
216
|
+
let current;
|
|
217
|
+
try {
|
|
218
|
+
current = fs.readFileSync(filePath, "utf8");
|
|
219
|
+
} catch (error) {
|
|
220
|
+
if (error.code !== "ENOENT") throw error;
|
|
221
|
+
current = null;
|
|
222
|
+
}
|
|
223
|
+
if (current === previous) return;
|
|
224
|
+
if (previous === null) {
|
|
225
|
+
fs.rmSync(filePath, { force: true });
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
const tempPath = stageFile(filePath, previous);
|
|
229
|
+
try {
|
|
230
|
+
replaceFile(tempPath, filePath);
|
|
231
|
+
} finally {
|
|
232
|
+
removeFile(tempPath);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
function restoreCredentialWrite(host, recovery) {
|
|
236
|
+
restoreFile(legacyFilePath(host), recovery.legacy);
|
|
237
|
+
restoreFile(vaultFilePath(host), recovery.vault);
|
|
238
|
+
for (const name of [recovery.legacyTemp, recovery.vaultTemp]) {
|
|
239
|
+
fs.rmSync(path.join(storeDir(), name), { force: true });
|
|
240
|
+
}
|
|
241
|
+
fs.unlinkSync(recoveryFilePath(host));
|
|
242
|
+
}
|
|
243
|
+
function isRecoveryTemp(name, destination, pid) {
|
|
244
|
+
const prefix = `${path.basename(destination)}.${pid}.`;
|
|
245
|
+
return typeof name === "string" && name.startsWith(prefix) && /^[0-9a-f]{12}\.tmp$/.test(name.slice(prefix.length));
|
|
246
|
+
}
|
|
247
|
+
function recoverCredentialWrite(host) {
|
|
248
|
+
const filePath = recoveryFilePath(host);
|
|
249
|
+
let raw;
|
|
250
|
+
try {
|
|
251
|
+
raw = fs.readFileSync(filePath, "utf8");
|
|
252
|
+
} catch (error) {
|
|
253
|
+
if (error.code === "ENOENT") {
|
|
254
|
+
try {
|
|
255
|
+
if (!fs.lstatSync(filePath, { throwIfNoEntry: false })) return;
|
|
256
|
+
} catch {
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
throw new CredentialStoreUnreadableError(filePath);
|
|
260
|
+
}
|
|
261
|
+
try {
|
|
262
|
+
const recovery = safeJsonParse(raw);
|
|
263
|
+
if (recovery?.version !== 1 || !Number.isSafeInteger(recovery.pid) || recovery.pid <= 0 || !(recovery.legacy === null || typeof recovery.legacy === "string") || !(recovery.vault === null || typeof recovery.vault === "string") || !isRecoveryTemp(recovery.legacyTemp, legacyFilePath(host), recovery.pid) || !isRecoveryTemp(recovery.vaultTemp, vaultFilePath(host), recovery.pid) || activeWrites.has(filePath)) throw new Error("Invalid or active credential recovery");
|
|
264
|
+
if (recovery.pid !== process.pid) {
|
|
265
|
+
let ownerExited = false;
|
|
266
|
+
try {
|
|
267
|
+
process.kill(recovery.pid, 0);
|
|
268
|
+
} catch (error) {
|
|
269
|
+
ownerExited = error.code === "ESRCH";
|
|
270
|
+
}
|
|
271
|
+
if (!ownerExited) throw new Error("Credential writer is still running");
|
|
272
|
+
}
|
|
273
|
+
if (recovery.legacy !== null) decodeEncryptedFile(legacyFilePath(host), recovery.legacy);
|
|
274
|
+
if (recovery.vault !== null) decodeEncryptedFile(vaultFilePath(host), recovery.vault);
|
|
275
|
+
restoreCredentialWrite(host, recovery);
|
|
276
|
+
} catch {
|
|
277
|
+
throw new CredentialStoreUnreadableError(filePath);
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
function writeVaultAndProjection(host, vault) {
|
|
281
|
+
const active = vault.credentials.find((entry) => entry.id === vault.activeCredentialId);
|
|
282
|
+
vault.legacyProjection = { credentialId: active.id, tokenFingerprint: tokenFingerprint(active.cliToken) };
|
|
283
|
+
const legacyPath = legacyFilePath(host);
|
|
284
|
+
const vaultPath = vaultFilePath(host);
|
|
285
|
+
const recoveryPath = recoveryFilePath(host);
|
|
286
|
+
const staged = [];
|
|
287
|
+
try {
|
|
288
|
+
const legacy = prepareEncrypted(legacyPath, legacyProjectionPayload(active.cliToken), vaultPath);
|
|
289
|
+
staged.push(legacy.tempPath);
|
|
290
|
+
const nextVault = prepareEncrypted(vaultPath, vault, legacyPath);
|
|
291
|
+
staged.push(nextVault.tempPath);
|
|
292
|
+
const recovery = {
|
|
293
|
+
version: 1,
|
|
294
|
+
pid: process.pid,
|
|
295
|
+
legacy: legacy.previous,
|
|
296
|
+
vault: nextVault.previous,
|
|
297
|
+
legacyTemp: path.basename(legacy.tempPath),
|
|
298
|
+
vaultTemp: path.basename(nextVault.tempPath)
|
|
299
|
+
};
|
|
300
|
+
const fd = fs.openSync(recoveryPath, "wx", 384);
|
|
301
|
+
try {
|
|
302
|
+
try {
|
|
303
|
+
fs.writeFileSync(fd, JSON.stringify(recovery), "utf8");
|
|
304
|
+
fs.fsyncSync(fd);
|
|
305
|
+
} finally {
|
|
306
|
+
fs.closeSync(fd);
|
|
307
|
+
}
|
|
308
|
+
} catch (error) {
|
|
309
|
+
removeFile(recoveryPath);
|
|
310
|
+
throw error;
|
|
311
|
+
}
|
|
312
|
+
activeWrites.add(recoveryPath);
|
|
313
|
+
try {
|
|
314
|
+
replaceFile(legacy.tempPath, legacyPath);
|
|
315
|
+
replaceFile(nextVault.tempPath, vaultPath);
|
|
316
|
+
fs.unlinkSync(recoveryPath);
|
|
317
|
+
} catch (error) {
|
|
318
|
+
try {
|
|
319
|
+
restoreCredentialWrite(host, recovery);
|
|
320
|
+
} catch {
|
|
321
|
+
throw new CredentialStoreUnreadableError(recoveryPath);
|
|
322
|
+
}
|
|
323
|
+
throw error;
|
|
324
|
+
} finally {
|
|
325
|
+
activeWrites.delete(recoveryPath);
|
|
326
|
+
}
|
|
327
|
+
} finally {
|
|
328
|
+
for (const tempPath of staged) removeFile(tempPath);
|
|
329
|
+
}
|
|
171
330
|
}
|
|
172
331
|
function readVaultRaw(host) {
|
|
173
332
|
const normalizedHost = normalizeUrl(host);
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
const
|
|
177
|
-
if (
|
|
178
|
-
|
|
333
|
+
recoverCredentialWrite(normalizedHost);
|
|
334
|
+
const filePath = vaultFilePath(normalizedHost);
|
|
335
|
+
const vault = readEncrypted(filePath);
|
|
336
|
+
if (!vault) return null;
|
|
337
|
+
if (vault.version !== 1 || !Array.isArray(vault.credentials) || vault.credentials.length === 0 || !vault.credentials.every((entry) => typeof entry?.id === "string" && entry.id && typeof entry.cliToken === "string" && entry.cliToken.trim()) || !vault.credentials.some((entry) => entry.id === vault.activeCredentialId) || vault.legacyProjection !== void 0 && (!vault.legacyProjection || typeof vault.legacyProjection.credentialId !== "string" || typeof vault.legacyProjection.tokenFingerprint !== "string")) {
|
|
338
|
+
throw new CredentialStoreUnreadableError(filePath);
|
|
339
|
+
}
|
|
340
|
+
return { ...vault, host: normalizedHost };
|
|
179
341
|
}
|
|
180
342
|
function writeVault(host, vault) {
|
|
181
|
-
atomicWriteEncrypted(vaultFilePath(host), vault);
|
|
343
|
+
atomicWriteEncrypted(vaultFilePath(host), vault, legacyFilePath(host));
|
|
182
344
|
}
|
|
183
345
|
function removeFile(filePath) {
|
|
184
346
|
try {
|
|
@@ -187,12 +349,23 @@ function removeFile(filePath) {
|
|
|
187
349
|
}
|
|
188
350
|
}
|
|
189
351
|
function load(host) {
|
|
190
|
-
|
|
352
|
+
recoverCredentialWrite(host);
|
|
353
|
+
const filePath = legacyFilePath(host);
|
|
354
|
+
const payload = readEncrypted(filePath);
|
|
355
|
+
if (payload && (typeof payload.accessToken !== "string" || typeof payload.refreshToken !== "string" || typeof payload.accessExpiresAt !== "string" || payload.cliToken !== void 0 && typeof payload.cliToken !== "string")) {
|
|
356
|
+
throw new CredentialStoreUnreadableError(filePath);
|
|
357
|
+
}
|
|
358
|
+
return payload;
|
|
359
|
+
}
|
|
360
|
+
function assertCredentialsReadable(host) {
|
|
361
|
+
readVaultRaw(host);
|
|
362
|
+
load(host);
|
|
191
363
|
}
|
|
192
364
|
function loadCredentialVault(host) {
|
|
193
365
|
const normalizedHost = normalizeUrl(host);
|
|
194
366
|
let vault = readVaultRaw(normalizedHost);
|
|
195
|
-
const
|
|
367
|
+
const legacy = load(normalizedHost);
|
|
368
|
+
const legacyToken = legacy?.cliToken?.trim();
|
|
196
369
|
if (!vault) {
|
|
197
370
|
if (!legacyToken) return null;
|
|
198
371
|
const imported = { id: credentialId(legacyToken), cliToken: legacyToken };
|
|
@@ -228,7 +401,7 @@ function loadCredentialVault(host) {
|
|
|
228
401
|
if (changed) writeVault(normalizedHost, vault);
|
|
229
402
|
return vault;
|
|
230
403
|
}
|
|
231
|
-
if (vault.legacyProjection) {
|
|
404
|
+
if (vault.legacyProjection && !legacy) {
|
|
232
405
|
const projection = vault.legacyProjection;
|
|
233
406
|
const projected = vault.credentials.find((entry) => entry.id === projection.credentialId && tokenFingerprint(entry.cliToken) === projection.tokenFingerprint);
|
|
234
407
|
if (projected) {
|
|
@@ -244,9 +417,7 @@ function loadCredentialVault(host) {
|
|
|
244
417
|
vault.activeCredentialId = vault.credentials[0].id;
|
|
245
418
|
}
|
|
246
419
|
}
|
|
247
|
-
|
|
248
|
-
vault.legacyProjection = writeLegacyProjection(normalizedHost, active);
|
|
249
|
-
writeVault(normalizedHost, vault);
|
|
420
|
+
writeVaultAndProjection(normalizedHost, vault);
|
|
250
421
|
return vault;
|
|
251
422
|
}
|
|
252
423
|
function getActiveCredential(host) {
|
|
@@ -261,7 +432,7 @@ function saveCredential(host, credential, options = {}) {
|
|
|
261
432
|
const existingVault = loadCredentialVault(normalizedHost);
|
|
262
433
|
if (options.add && !credential.account) {
|
|
263
434
|
throw new SecureStoreAuthError(
|
|
264
|
-
`This host does not return account identity from CLI token validation. Upgrade the server before
|
|
435
|
+
`This host does not return account identity from CLI token validation. Upgrade the server before adding another account for ${normalizedHost}.`
|
|
265
436
|
);
|
|
266
437
|
}
|
|
267
438
|
const sameAccount = credential.account ? existingVault?.credentials.find((entry) => entry.account?.openId === credential.account.openId || entry.account?.loginName === credential.account.loginName) : void 0;
|
|
@@ -277,13 +448,11 @@ function saveCredential(host, credential, options = {}) {
|
|
|
277
448
|
} else {
|
|
278
449
|
credentials = [saved];
|
|
279
450
|
}
|
|
280
|
-
|
|
281
|
-
writeVault(normalizedHost, {
|
|
451
|
+
writeVaultAndProjection(normalizedHost, {
|
|
282
452
|
version: 1,
|
|
283
453
|
host: normalizedHost,
|
|
284
454
|
activeCredentialId: saved.id,
|
|
285
|
-
credentials
|
|
286
|
-
legacyProjection
|
|
455
|
+
credentials
|
|
287
456
|
});
|
|
288
457
|
logger.info(`secure-store: saved CLI credential for ${normalizedHost}`);
|
|
289
458
|
return saved;
|
|
@@ -322,8 +491,7 @@ function activateCredential(host, account) {
|
|
|
322
491
|
}
|
|
323
492
|
const selected = matches[0];
|
|
324
493
|
vault.activeCredentialId = selected.id;
|
|
325
|
-
|
|
326
|
-
writeVault(normalizedHost, vault);
|
|
494
|
+
writeVaultAndProjection(normalizedHost, vault);
|
|
327
495
|
return selected;
|
|
328
496
|
}
|
|
329
497
|
function removeActiveCredential(host) {
|
|
@@ -339,12 +507,12 @@ function removeActiveCredential(host) {
|
|
|
339
507
|
}
|
|
340
508
|
const active = vault.credentials[0];
|
|
341
509
|
vault.activeCredentialId = active.id;
|
|
342
|
-
|
|
343
|
-
writeVault(normalizedHost, vault);
|
|
510
|
+
writeVaultAndProjection(normalizedHost, vault);
|
|
344
511
|
return { removed, active };
|
|
345
512
|
}
|
|
346
513
|
function clearAllCredentials(host) {
|
|
347
514
|
const normalizedHost = normalizeUrl(host);
|
|
515
|
+
recoverCredentialWrite(normalizedHost);
|
|
348
516
|
removeFile(legacyFilePath(normalizedHost));
|
|
349
517
|
removeFile(vaultFilePath(normalizedHost));
|
|
350
518
|
logger.info(`secure-store: all CLI credentials cleared for ${normalizedHost}`);
|
|
@@ -358,6 +526,14 @@ var SecureStoreAuthError = class extends Error {
|
|
|
358
526
|
this.name = "SecureStoreAuthError";
|
|
359
527
|
}
|
|
360
528
|
};
|
|
529
|
+
var CredentialStoreUnreadableError = class extends Error {
|
|
530
|
+
code = "CREDENTIAL_STORE_UNREADABLE";
|
|
531
|
+
hint = "Keep the existing credential files. Retry in the original OS user and runtime with access to the machine identifier and credential directory. Do not log in again, replace tokens, or log out to fix a local credential read failure.";
|
|
532
|
+
constructor(filePath) {
|
|
533
|
+
super(`Cannot read or decrypt the existing credential file: ${filePath}`);
|
|
534
|
+
this.name = "CredentialStoreUnreadableError";
|
|
535
|
+
}
|
|
536
|
+
};
|
|
361
537
|
|
|
362
538
|
// src/core/cli-token.ts
|
|
363
539
|
import crypto2 from "crypto";
|
|
@@ -377,6 +553,15 @@ function isExplicitCliTokenRejection(data, responseText) {
|
|
|
377
553
|
const message = String(data?.return_message ?? data?.message ?? data?.error?.message ?? responseText);
|
|
378
554
|
return /cli[_-]?token[_-]?(invalid|expired)/i.test(code) || /cli[-_\s]?token.*\b(invalid|expired)\b/i.test(message) || /\b(invalid|expired)\b.*cli[-_\s]?token/i.test(message);
|
|
379
555
|
}
|
|
556
|
+
function cliAccessDisabledDetails(data, responseText) {
|
|
557
|
+
const code = String(data?.code ?? data?.error?.code ?? "");
|
|
558
|
+
const message = String(data?.return_message ?? data?.message ?? data?.error?.message ?? responseText);
|
|
559
|
+
if (code !== "CLI_ACCESS_DISABLED" && !message.includes("CLI_ACCESS_DISABLED")) return void 0;
|
|
560
|
+
return {
|
|
561
|
+
message: message || "CLI access is disabled for this account.",
|
|
562
|
+
hint: data?.hint ?? data?.error?.hint
|
|
563
|
+
};
|
|
564
|
+
}
|
|
380
565
|
function optionalNonEmptyString(...values) {
|
|
381
566
|
return values.find((value) => typeof value === "string" && value.trim());
|
|
382
567
|
}
|
|
@@ -511,10 +696,12 @@ async function validateCliTokenOnServer(hostUrl, cliToken) {
|
|
|
511
696
|
} catch {
|
|
512
697
|
body = void 0;
|
|
513
698
|
}
|
|
699
|
+
const accessDisabled = cliAccessDisabledDetails(body, responseText);
|
|
700
|
+
if (accessDisabled) {
|
|
701
|
+
throw new PermissionError(accessDisabled.message, "CLI_ACCESS_DISABLED", accessDisabled.hint);
|
|
702
|
+
}
|
|
514
703
|
if (isExplicitCliTokenRejection(body, responseText)) {
|
|
515
|
-
throw new SecureStoreAuthError(
|
|
516
|
-
`CLI token is invalid or expired for ${hostUrl}. Run: ae-cli auth logout --host ${hostUrl}, then ae-cli auth login --host ${hostUrl}`
|
|
517
|
-
);
|
|
704
|
+
throw new SecureStoreAuthError(`CLI token is invalid or expired for ${hostUrl}.`);
|
|
518
705
|
}
|
|
519
706
|
if (!resp.ok) {
|
|
520
707
|
throw new CliTokenValidationUnavailableError(
|
|
@@ -578,7 +765,13 @@ function peekCliToken(hostOverride) {
|
|
|
578
765
|
const hostUrl = hostOverride || getActiveHost();
|
|
579
766
|
if (!hostUrl) return void 0;
|
|
580
767
|
const normalizedHost = normalizeUrl(hostUrl);
|
|
581
|
-
|
|
768
|
+
let stored;
|
|
769
|
+
try {
|
|
770
|
+
stored = loadCliToken(normalizedHost);
|
|
771
|
+
} catch (error) {
|
|
772
|
+
if (error instanceof CredentialStoreUnreadableError) return void 0;
|
|
773
|
+
throw error;
|
|
774
|
+
}
|
|
582
775
|
if (stored) {
|
|
583
776
|
cliTokenCache.set(normalizedHost, stored);
|
|
584
777
|
return stored;
|
|
@@ -606,6 +799,7 @@ async function mintCliToken(hostUrl, accessToken) {
|
|
|
606
799
|
}
|
|
607
800
|
|
|
608
801
|
export {
|
|
802
|
+
assertCredentialsReadable,
|
|
609
803
|
getActiveCredential,
|
|
610
804
|
listCredentials,
|
|
611
805
|
saveCredential,
|
|
@@ -614,6 +808,7 @@ export {
|
|
|
614
808
|
removeActiveCredential,
|
|
615
809
|
clearAllCredentials,
|
|
616
810
|
SecureStoreAuthError,
|
|
811
|
+
CredentialStoreUnreadableError,
|
|
617
812
|
CliTokenValidationUnavailableError,
|
|
618
813
|
clearCliTokenCache,
|
|
619
814
|
validateCliTokenOnServer,
|
|
@@ -2,7 +2,7 @@ import { createRequire as __createRequire } from 'node:module'; const require =
|
|
|
2
2
|
import {
|
|
3
3
|
__commonJS,
|
|
4
4
|
__require
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-YVGXGTD6.js";
|
|
6
6
|
|
|
7
7
|
// node_modules/process-nextick-args/index.js
|
|
8
8
|
var require_process_nextick_args = __commonJS({
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createRequire as __createRequire } from 'node:module'; const require = __createRequire(import.meta.url);
|
|
2
2
|
import {
|
|
3
3
|
logger
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-YVGXGTD6.js";
|
|
5
5
|
|
|
6
6
|
// src/core/url-utils.ts
|
|
7
7
|
function normalizeUrl(url) {
|
|
@@ -76,6 +76,9 @@ function isAeSandboxRuntime() {
|
|
|
76
76
|
if (process.env.SANDBOX_RUNTIME_ROOT) {
|
|
77
77
|
return true;
|
|
78
78
|
}
|
|
79
|
+
if (process.platform !== "linux") {
|
|
80
|
+
return false;
|
|
81
|
+
}
|
|
79
82
|
try {
|
|
80
83
|
if (fs2.existsSync(getSandboxCliTokenFilePath())) {
|
|
81
84
|
return true;
|
|
@@ -4,14 +4,14 @@ import {
|
|
|
4
4
|
} from "./chunk-Y74WTIKJ.js";
|
|
5
5
|
import {
|
|
6
6
|
getCliToken
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-DU72X2IO.js";
|
|
8
8
|
import {
|
|
9
9
|
getActiveHost,
|
|
10
10
|
getSandboxRuntimeRoot
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-IG3DYEIR.js";
|
|
12
12
|
import {
|
|
13
13
|
PermissionError
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-YVGXGTD6.js";
|
|
15
15
|
|
|
16
16
|
// src/core/te-agent-credentials.ts
|
|
17
17
|
import { readFileSync } from "fs";
|
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
import { createRequire as __createRequire } from 'node:module'; const require = __createRequire(import.meta.url);
|
|
2
2
|
import {
|
|
3
3
|
require_lib
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-SO5LKIWP.js";
|
|
5
5
|
import {
|
|
6
6
|
require_archiver,
|
|
7
7
|
require_string_decoder
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-7WZACOAI.js";
|
|
9
9
|
import {
|
|
10
10
|
require_inherits,
|
|
11
11
|
require_node
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-GK7WDY7E.js";
|
|
13
13
|
import {
|
|
14
14
|
__commonJS,
|
|
15
15
|
__require,
|
|
16
16
|
__toESM
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-YVGXGTD6.js";
|
|
18
18
|
|
|
19
19
|
// node_modules/exceljs/lib/utils/under-dash.js
|
|
20
20
|
var require_under_dash = __commonJS({
|