@thinkingai/ae-cli 6.1.17 → 6.1.18
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/dist/{auth-2WTQOP77.js → auth-GBMV6TEJ.js} +3 -3
- package/dist/{auth-77BUFLGC.js → auth-ROB2EDYV.js} +12 -13
- package/dist/{capability-72DTW5M2.js → capability-DKMYUTLC.js} +50 -13
- package/dist/{capability-PJHNI4GJ.js → capability-HYVVPG25.js} +49 -12
- package/dist/chunk-3FY3RJ26.js +293 -0
- package/dist/{chunk-PTE56QPL.js → chunk-3KWQYGYI.js} +4 -0
- package/dist/{chunk-UOUS37JQ.js → chunk-4XXOWOTA.js} +3 -3
- package/dist/{chunk-GT46FPXN.js → chunk-BYYS3ANB.js} +17 -8
- package/dist/{chunk-YA6SMTXG.js → chunk-EFH4XWYC.js} +3 -3
- package/dist/{chunk-4SGZG4XY.js → chunk-J2DEBMRF.js} +9 -7
- package/dist/{chunk-LYVNONC4.js → chunk-JHENBQ5B.js} +35 -0
- package/dist/{chunk-VR3LCBHW.js → chunk-JRJY5DMJ.js} +5 -5
- package/dist/{chunk-ILIU36SU.js → chunk-OMPRXM3V.js} +3 -3
- package/dist/{chunk-VPKZ7I72.js → chunk-QNOLN2LJ.js} +2 -2
- package/dist/{chunk-SAU3QFIQ.js → chunk-QZ3AS4KK.js} +3 -3
- package/dist/chunk-RJDU7NYP.js +1198 -0
- package/dist/{chunk-4KVPKXFX.js → chunk-RNAALWJK.js} +2 -2
- package/dist/{chunk-C4MGVGJW.js → chunk-SERWF6G5.js} +1 -1
- package/dist/{chunk-RGKJGKT7.js → chunk-Y3LOALAV.js} +5 -5
- package/dist/{chunk-P3FGXJTU.js → chunk-ZQ47LWTI.js} +4 -4
- package/dist/chunk-ZQKDZXDO.js +317 -0
- package/dist/{client-TKG4WBHN.js → client-L2YDMHQ6.js} +5 -4
- package/dist/{community-report-client-FI4LNVYS.js → community-report-client-C7WDGET3.js} +1 -2
- package/dist/{config-RE6CMGPK.js → config-BMYZX2UE.js} +7 -6
- package/dist/{data-integration-XQYB4X4F.js → data-integration-QEKDWQDY.js} +1601 -192
- package/dist/index.js +131 -1241
- package/dist/{local-data-upload-client-BWHSUQQK.js → local-data-upload-client-4YYHSYD6.js} +1 -2
- package/dist/{memory-CHRU2F7W.js → memory-3ORCR7JH.js} +6 -6
- package/dist/{memory-YK33G4T7.js → memory-I2WXDTV2.js} +5 -5
- package/dist/{metadata-XXR34N5P.js → metadata-I4C2EWUN.js} +10 -10
- package/dist/{metadata-UILXHBWF.js → metadata-VUOQJE26.js} +9 -9
- package/dist/{model-NR3JHFSJ.js → model-HLHIEFMU.js} +5 -5
- package/dist/{model-K3KLWIW6.js → model-UGRDX4MW.js} +6 -6
- package/dist/personal-semantic-preference-LIPACBDX.js +239 -0
- package/dist/personal-semantic-preference-OEISBRHM.js +239 -0
- package/dist/project-semantic-FFPWFPIW.js +1114 -0
- package/dist/project-semantic-RT3R2VQD.js +1114 -0
- package/dist/{sync-FCKOVWWS.js → sync-HKIOZXQE.js} +6 -6
- package/dist/{sync-DAVKYVMW.js → sync-TFHU2UTG.js} +7 -7
- package/dist/{te-agent-HLW4VTQK.js → te-agent-BR6VDBNX.js} +9 -8
- package/dist/{te-agent-4BKBODMF.js → te-agent-VLYOV7S4.js} +8 -7
- package/dist/{te-analysis-ZMNGOVNW.js → te-analysis-4YGQL5RC.js} +437 -38
- package/dist/{te-analysis-O6DCO6BS.js → te-analysis-7VUNUYWZ.js} +436 -37
- package/dist/{te-community-HLC43QKH.js → te-community-5DMNKJWY.js} +5 -5
- package/dist/{te-community-6HPBWJUZ.js → te-community-ISDQWJU7.js} +6 -6
- package/dist/{te-dataops-HDRUXY4K.js → te-dataops-6P5IKWNJ.js} +8 -7
- package/dist/{te-dataops-EJP56W3K.js → te-dataops-CVULXNVB.js} +7 -6
- package/dist/{te-engage-RAK5PESW.js → te-engage-KZPR5R22.js} +9 -9
- package/dist/{te-engage-FGBGQ4IY.js → te-engage-N5WI32H6.js} +8 -8
- package/dist/{te-experiment-SO5MPDMJ.js → te-experiment-6BITX4RD.js} +226 -8
- package/dist/{te-experiment-VZF7BT6G.js → te-experiment-UVR4HLND.js} +227 -9
- package/dist/{te-kb-SQCLHG6X.js → te-kb-RCLSSH2Q.js} +7 -7
- package/dist/{te-system-Z77IKZFN.js → te-system-FXITO2JG.js} +5 -5
- package/dist/{te-system-YARIK4S5.js → te-system-K2GYMCTB.js} +6 -6
- package/dist/{te-team-EFKWYKMK.js → te-team-ADOC2ROP.js} +6 -6
- package/dist/{update-OGPSZM5A.js → update-YCYCKJOO.js} +7 -6
- package/package.json +1 -1
- package/skills/ae-agent/SKILL.md +3 -4
- package/skills/ae-agent/references/edit-skill.md +3 -0
- package/skills/ae-agent/references/get-skill-content.md +1 -1
- package/skills/ae-agent/references/rescan-skills.md +15 -13
- package/skills/ae-agent/references/upload-skill.md +7 -4
- package/skills/ae-analysis/SKILL.md +45 -4
- package/skills/ae-analysis/metadata_resolution.md +38 -4
- package/skills/ae-analysis/references/analysis_data_retrieval.md +29 -0
- package/skills/ae-analysis/references/asset_authentication_export.md +22 -0
- package/skills/ae-analysis/references/asset_authentication_list.md +18 -14
- package/skills/ae-analysis/references/asset_authentication_update.md +29 -14
- package/skills/ae-analysis/references/command_index.md +17 -9
- package/skills/ae-analysis/references/dashboard_get.md +18 -1
- package/skills/ae-analysis/references/dashboard_update.md +3 -0
- package/skills/ae-analysis/references/personal_semantic_preference_add.md +23 -0
- package/skills/ae-analysis/references/personal_semantic_preference_delete.md +17 -0
- package/skills/ae-analysis/references/personal_semantic_preference_get.md +19 -0
- package/skills/ae-analysis/references/personal_semantic_preference_list.md +21 -0
- package/skills/ae-analysis/references/personal_semantic_preference_update.md +19 -0
- package/skills/ae-data-integration/SKILL.md +23 -4
- package/skills/ae-data-integration/references/custom-layer.md +93 -0
- package/skills/ae-data-integration/references/error-handling.md +92 -0
- package/skills/ae-data-integration/references/handoff.md +77 -18
- package/skills/ae-data-integration/references/local-analysis.md +1 -1
- package/skills/ae-data-integration/references/reuse.md +9 -5
- package/skills/ae-data-integration/references/sink-upload.md +1 -1
- package/skills/ae-data-integration/references/source-inspect.md +18 -12
- package/skills/ae-data-integration/references/tracking-plan.md +7 -5
- package/skills/ae-data-integration/references/transform.md +10 -10
- package/skills/ae-data-integration/references/ue-mapping.md +33 -11
- package/skills/ae-engage/references/build-task-save-guide.md +9 -0
- package/skills/ae-engage/references/save-task.md +82 -0
- package/skills/ae-experiment/SKILL.md +8 -2
- package/skills/ae-experiment/references/manage_feature_whitelist.md +66 -0
- package/skills/ae-experiment/references/manage_guardrail_metrics.md +26 -0
- package/skills/ae-experiment/references/save_experiment.md +1 -1
- package/skills/ae-kb/SKILL.md +1 -1
- package/skills/ae-project-semantic/SKILL.md +193 -0
- package/skills/ae-project-semantic/references/query-routing-v5.md +165 -0
- package/skills/ae-project-semantic/references/recommendation-quality.md +68 -0
- package/dist/chunk-QGM4M3NI.js +0 -37
- package/dist/chunk-ZZUOD757.js +0 -598
package/dist/chunk-ZZUOD757.js
DELETED
|
@@ -1,598 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
logger
|
|
3
|
-
} from "./chunk-LYVNONC4.js";
|
|
4
|
-
|
|
5
|
-
// src/core/config.ts
|
|
6
|
-
import fs3 from "fs";
|
|
7
|
-
import path from "path";
|
|
8
|
-
|
|
9
|
-
// src/core/json-utils.ts
|
|
10
|
-
import fs from "fs";
|
|
11
|
-
import { createRequire } from "module";
|
|
12
|
-
var require2 = createRequire(import.meta.url);
|
|
13
|
-
var JSONbig = require2("json-bigint");
|
|
14
|
-
var jsonParser = JSONbig({ storeAsString: true });
|
|
15
|
-
var INTEGER_TOKEN = /^-?(?:0|[1-9]\d*)$/;
|
|
16
|
-
function normalizeParsedNumbers(lossless, native) {
|
|
17
|
-
if (typeof lossless === "string" && typeof native === "number") {
|
|
18
|
-
if (INTEGER_TOKEN.test(lossless) && !Number.isSafeInteger(native)) {
|
|
19
|
-
return lossless;
|
|
20
|
-
}
|
|
21
|
-
return native;
|
|
22
|
-
}
|
|
23
|
-
if (Array.isArray(lossless) && Array.isArray(native)) {
|
|
24
|
-
for (let index = 0; index < lossless.length; index++) {
|
|
25
|
-
lossless[index] = normalizeParsedNumbers(lossless[index], native[index]);
|
|
26
|
-
}
|
|
27
|
-
return lossless;
|
|
28
|
-
}
|
|
29
|
-
if (lossless !== null && native !== null && typeof lossless === "object" && typeof native === "object") {
|
|
30
|
-
for (const key of Object.keys(lossless)) {
|
|
31
|
-
lossless[key] = normalizeParsedNumbers(lossless[key], native[key]);
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
return lossless;
|
|
35
|
-
}
|
|
36
|
-
function safeJsonParse(text) {
|
|
37
|
-
const lossless = jsonParser.parse(text);
|
|
38
|
-
return normalizeParsedNumbers(lossless, JSON.parse(text));
|
|
39
|
-
}
|
|
40
|
-
function safeReadJsonFile(filePath) {
|
|
41
|
-
const content = fs.readFileSync(filePath, "utf-8");
|
|
42
|
-
return safeJsonParse(content);
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
// src/core/url-utils.ts
|
|
46
|
-
function normalizeUrl(url) {
|
|
47
|
-
if (!url) return url;
|
|
48
|
-
if (!url.startsWith("http://") && !url.startsWith("https://")) {
|
|
49
|
-
url = `https://${url}`;
|
|
50
|
-
}
|
|
51
|
-
return url.replace(/\/$/, "");
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
// src/core/sandbox-runtime.ts
|
|
55
|
-
import { homedir } from "os";
|
|
56
|
-
import { join } from "path";
|
|
57
|
-
import fs2 from "fs";
|
|
58
|
-
var LINUX_SANDBOX_RUNTIME_ROOT = "/home/ta/te_agent_ta";
|
|
59
|
-
function getDefaultSandboxRuntimeRoot() {
|
|
60
|
-
if (process.platform === "linux") {
|
|
61
|
-
return LINUX_SANDBOX_RUNTIME_ROOT;
|
|
62
|
-
}
|
|
63
|
-
return homedir();
|
|
64
|
-
}
|
|
65
|
-
function getSandboxRuntimeRoot() {
|
|
66
|
-
return process.env.SANDBOX_RUNTIME_ROOT || getDefaultSandboxRuntimeRoot();
|
|
67
|
-
}
|
|
68
|
-
function getSandboxAeConfigDir() {
|
|
69
|
-
return join(getSandboxRuntimeRoot(), ".ae-config");
|
|
70
|
-
}
|
|
71
|
-
function getSandboxCliTokenFilePath() {
|
|
72
|
-
return join(getSandboxAeConfigDir(), "cli-token.json");
|
|
73
|
-
}
|
|
74
|
-
function isAeSandboxRuntime() {
|
|
75
|
-
if (process.env.SANDBOX_RUNTIME_ROOT) {
|
|
76
|
-
return true;
|
|
77
|
-
}
|
|
78
|
-
try {
|
|
79
|
-
if (fs2.existsSync(getSandboxCliTokenFilePath())) {
|
|
80
|
-
return true;
|
|
81
|
-
}
|
|
82
|
-
} catch {
|
|
83
|
-
}
|
|
84
|
-
return false;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
// src/core/config.ts
|
|
88
|
-
var CONFIG_DIR = path.join(process.env.HOME || "", ".ae-cli");
|
|
89
|
-
var CONFIG_FILE = path.join(CONFIG_DIR, "config.json");
|
|
90
|
-
function sandboxCliTokenCandidatePaths() {
|
|
91
|
-
const paths = [getSandboxCliTokenFilePath()];
|
|
92
|
-
const homeFallback = path.join(process.env.HOME || "", ".ae-config", "cli-token.json");
|
|
93
|
-
if (!paths.includes(homeFallback)) {
|
|
94
|
-
paths.push(homeFallback);
|
|
95
|
-
}
|
|
96
|
-
return paths;
|
|
97
|
-
}
|
|
98
|
-
function readSandboxCliTokenEntry() {
|
|
99
|
-
for (const file of sandboxCliTokenCandidatePaths()) {
|
|
100
|
-
if (!fs3.existsSync(file)) continue;
|
|
101
|
-
try {
|
|
102
|
-
const data = safeReadJsonFile(file);
|
|
103
|
-
if (data && typeof data === "object" && !Array.isArray(data)) {
|
|
104
|
-
const url = data.url;
|
|
105
|
-
const token = data.token ?? data["cli-token"];
|
|
106
|
-
if (url && token) {
|
|
107
|
-
return { url, token };
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
} catch {
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
return null;
|
|
114
|
-
}
|
|
115
|
-
function forceMigrateFromFallback() {
|
|
116
|
-
const entry = readSandboxCliTokenEntry();
|
|
117
|
-
if (!entry) return null;
|
|
118
|
-
return { [entry.url]: entry.token };
|
|
119
|
-
}
|
|
120
|
-
function getFallbackCliToken(hostUrl) {
|
|
121
|
-
const store = forceMigrateFromFallback();
|
|
122
|
-
if (!store) return null;
|
|
123
|
-
if (hostUrl && store[hostUrl]) return store[hostUrl];
|
|
124
|
-
const entries = Object.values(store);
|
|
125
|
-
if (entries.length === 1) return entries[0];
|
|
126
|
-
return null;
|
|
127
|
-
}
|
|
128
|
-
function ensureDir() {
|
|
129
|
-
if (!fs3.existsSync(CONFIG_DIR)) fs3.mkdirSync(CONFIG_DIR, { recursive: true });
|
|
130
|
-
}
|
|
131
|
-
function dedupeNormalizedHosts(config) {
|
|
132
|
-
const hosts = {};
|
|
133
|
-
for (const [url, entry] of Object.entries(config.hosts)) {
|
|
134
|
-
const key = normalizeUrl(url);
|
|
135
|
-
if (!hosts[key]) {
|
|
136
|
-
hosts[key] = entry;
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
return {
|
|
140
|
-
activeHost: config.activeHost ? normalizeUrl(config.activeHost) : "",
|
|
141
|
-
hosts
|
|
142
|
-
};
|
|
143
|
-
}
|
|
144
|
-
function configNeedsNormalization(config) {
|
|
145
|
-
if (config.activeHost && normalizeUrl(config.activeHost) !== config.activeHost) return true;
|
|
146
|
-
const keys = Object.keys(config.hosts);
|
|
147
|
-
if (keys.some((url) => normalizeUrl(url) !== url)) return true;
|
|
148
|
-
return new Set(keys.map(normalizeUrl)).size !== keys.length;
|
|
149
|
-
}
|
|
150
|
-
function loadConfig() {
|
|
151
|
-
try {
|
|
152
|
-
if (fs3.existsSync(CONFIG_FILE)) {
|
|
153
|
-
const raw = safeReadJsonFile(CONFIG_FILE);
|
|
154
|
-
if (raw.defaultHost && !raw.activeHost) {
|
|
155
|
-
const migrated = dedupeNormalizedHosts(migrateConfig(raw));
|
|
156
|
-
saveConfig(migrated);
|
|
157
|
-
return migrated;
|
|
158
|
-
}
|
|
159
|
-
const rawConfig = raw;
|
|
160
|
-
if (configNeedsNormalization(rawConfig)) {
|
|
161
|
-
const config = dedupeNormalizedHosts(rawConfig);
|
|
162
|
-
saveConfig(config);
|
|
163
|
-
return config;
|
|
164
|
-
}
|
|
165
|
-
return rawConfig;
|
|
166
|
-
}
|
|
167
|
-
} catch (err) {
|
|
168
|
-
logger.error(`Error loading config: ${err.message}`);
|
|
169
|
-
console.error(`Error loading config: ${err.message}`);
|
|
170
|
-
}
|
|
171
|
-
return { activeHost: "", hosts: {} };
|
|
172
|
-
}
|
|
173
|
-
function migrateConfig(old) {
|
|
174
|
-
const hosts = {};
|
|
175
|
-
const oldHost = old.defaultHost;
|
|
176
|
-
if (old.hosts) {
|
|
177
|
-
for (const [key, val] of Object.entries(old.hosts)) {
|
|
178
|
-
const url = normalizeUrl(key.startsWith("http") ? key : `https://${key}`);
|
|
179
|
-
hosts[url] = val;
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
const activeHost = normalizeUrl(oldHost.startsWith("http") ? oldHost : `https://${oldHost}`);
|
|
183
|
-
if (!hosts[activeHost]) {
|
|
184
|
-
hosts[activeHost] = { label: "default" };
|
|
185
|
-
}
|
|
186
|
-
return { activeHost, hosts };
|
|
187
|
-
}
|
|
188
|
-
function saveConfig(config) {
|
|
189
|
-
ensureDir();
|
|
190
|
-
fs3.writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2));
|
|
191
|
-
logger.info(`Config saved: activeHost=${config.activeHost}, hosts=${Object.keys(config.hosts).length}`);
|
|
192
|
-
}
|
|
193
|
-
function getActiveHost() {
|
|
194
|
-
const sandboxHost = readSandboxCliTokenEntry()?.url;
|
|
195
|
-
if (sandboxHost) return sandboxHost;
|
|
196
|
-
const config = loadConfig();
|
|
197
|
-
return config.activeHost || "";
|
|
198
|
-
}
|
|
199
|
-
function setActiveHost(url) {
|
|
200
|
-
url = normalizeUrl(url);
|
|
201
|
-
const config = loadConfig();
|
|
202
|
-
if (!config.hosts[url]) {
|
|
203
|
-
throw new Error(`Host ${url} is not in the configured hosts list. Add it first.`);
|
|
204
|
-
}
|
|
205
|
-
config.activeHost = url;
|
|
206
|
-
saveConfig(config);
|
|
207
|
-
}
|
|
208
|
-
function addHost(url, label) {
|
|
209
|
-
url = normalizeUrl(url);
|
|
210
|
-
label = normalizeLabel(label);
|
|
211
|
-
const config = loadConfig();
|
|
212
|
-
assertUniqueHostLabel(config, label, url);
|
|
213
|
-
config.hosts[url] = { label };
|
|
214
|
-
if (!config.activeHost) {
|
|
215
|
-
config.activeHost = url;
|
|
216
|
-
}
|
|
217
|
-
saveConfig(config);
|
|
218
|
-
}
|
|
219
|
-
function updateHostLabel(url, label) {
|
|
220
|
-
url = normalizeUrl(url);
|
|
221
|
-
label = normalizeLabel(label);
|
|
222
|
-
const config = loadConfig();
|
|
223
|
-
if (!config.hosts[url]) {
|
|
224
|
-
throw new Error(`Host is not configured: ${url}`);
|
|
225
|
-
}
|
|
226
|
-
assertUniqueHostLabel(config, label, url);
|
|
227
|
-
config.hosts[url].label = label;
|
|
228
|
-
saveConfig(config);
|
|
229
|
-
}
|
|
230
|
-
function normalizeLabel(label) {
|
|
231
|
-
const normalized = label.trim();
|
|
232
|
-
if (!normalized) {
|
|
233
|
-
throw new Error("Label cannot be empty.");
|
|
234
|
-
}
|
|
235
|
-
return normalized;
|
|
236
|
-
}
|
|
237
|
-
function assertUniqueHostLabel(config, label, excludeUrl) {
|
|
238
|
-
const duplicate = Object.entries(config.hosts).find(([url, entry]) => url !== excludeUrl && entry.label === label);
|
|
239
|
-
if (duplicate) {
|
|
240
|
-
throw new Error(`Label already exists: ${label}. Rename the existing label first: ${duplicate[0]}`);
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
function removeHost(url) {
|
|
244
|
-
url = normalizeUrl(url);
|
|
245
|
-
const config = loadConfig();
|
|
246
|
-
delete config.hosts[url];
|
|
247
|
-
if (config.activeHost === url) {
|
|
248
|
-
const remaining = Object.keys(config.hosts);
|
|
249
|
-
config.activeHost = remaining.length > 0 ? remaining[0] : "";
|
|
250
|
-
}
|
|
251
|
-
saveConfig(config);
|
|
252
|
-
}
|
|
253
|
-
function listHosts() {
|
|
254
|
-
const config = loadConfig();
|
|
255
|
-
return Object.entries(config.hosts).map(([url, entry]) => ({
|
|
256
|
-
url,
|
|
257
|
-
label: entry.label,
|
|
258
|
-
active: url === config.activeHost
|
|
259
|
-
}));
|
|
260
|
-
}
|
|
261
|
-
function resolveHostSelector(env) {
|
|
262
|
-
const raw = env.trim();
|
|
263
|
-
const selector = raw.startsWith("http://") || raw.startsWith("https://") ? normalizeUrl(raw) : raw;
|
|
264
|
-
const hosts = listHosts();
|
|
265
|
-
const byUrl = hosts.find((host) => host.url === selector);
|
|
266
|
-
if (byUrl) return { status: "found", host: byUrl };
|
|
267
|
-
const byLabel = hosts.filter((host) => host.label === raw);
|
|
268
|
-
if (byLabel.length === 1) return { status: "found", host: byLabel[0] };
|
|
269
|
-
if (byLabel.length > 1) return { status: "duplicate-label", matches: byLabel };
|
|
270
|
-
return { status: "not-found", hosts };
|
|
271
|
-
}
|
|
272
|
-
function getConfigDir() {
|
|
273
|
-
return CONFIG_DIR;
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
// src/core/secure-store.ts
|
|
277
|
-
import crypto from "crypto";
|
|
278
|
-
import fs4 from "fs";
|
|
279
|
-
import os from "os";
|
|
280
|
-
import path2 from "path";
|
|
281
|
-
import { execFileSync } from "child_process";
|
|
282
|
-
var STORE_DIR_SUFFIX = "secure-tokens";
|
|
283
|
-
var SCRYPT_SALT = Buffer.from("ae-cli-secure-store-v1");
|
|
284
|
-
var SCRYPT_N = 16384;
|
|
285
|
-
var SCRYPT_R = 8;
|
|
286
|
-
var SCRYPT_P = 1;
|
|
287
|
-
var KEY_LEN = 32;
|
|
288
|
-
var NONCE_LEN = 12;
|
|
289
|
-
var REFRESH_TOKEN_PATH = "/v1/oauth/refreshForToken";
|
|
290
|
-
function getMachineId() {
|
|
291
|
-
if (process.platform === "darwin") {
|
|
292
|
-
try {
|
|
293
|
-
const out = execFileSync(
|
|
294
|
-
"ioreg",
|
|
295
|
-
["-rd1", "-c", "IOPlatformExpertDevice"],
|
|
296
|
-
{ encoding: "utf8", timeout: 3e3 }
|
|
297
|
-
);
|
|
298
|
-
const m = out.match(/IOPlatformUUID.*?=.*?"([0-9A-F-]{36})"/i);
|
|
299
|
-
if (m?.[1]) return `darwin:${m[1]}`;
|
|
300
|
-
} catch {
|
|
301
|
-
}
|
|
302
|
-
}
|
|
303
|
-
if (process.platform === "linux") {
|
|
304
|
-
for (const p of ["/etc/machine-id", "/var/lib/dbus/machine-id"]) {
|
|
305
|
-
try {
|
|
306
|
-
const id = fs4.readFileSync(p, "utf8").trim();
|
|
307
|
-
if (id) return `linux:${id}`;
|
|
308
|
-
} catch {
|
|
309
|
-
}
|
|
310
|
-
}
|
|
311
|
-
}
|
|
312
|
-
if (process.platform === "win32") {
|
|
313
|
-
try {
|
|
314
|
-
const out = execFileSync(
|
|
315
|
-
"reg",
|
|
316
|
-
["query", "HKLM\\SOFTWARE\\Microsoft\\Cryptography", "/v", "MachineGuid"],
|
|
317
|
-
{ encoding: "utf8", timeout: 3e3 }
|
|
318
|
-
);
|
|
319
|
-
const m = out.match(/MachineGuid\s+REG_SZ\s+([0-9a-f-]+)/i);
|
|
320
|
-
if (m?.[1]) return `win32:${m[1]}`;
|
|
321
|
-
} catch {
|
|
322
|
-
}
|
|
323
|
-
}
|
|
324
|
-
const fallback = `${os.homedir()}|${os.hostname()}|${os.platform()}`;
|
|
325
|
-
logger.warn("secure-store: using fallback machine-id (HOME+hostname+platform)");
|
|
326
|
-
return `fallback:${fallback}`;
|
|
327
|
-
}
|
|
328
|
-
var _cachedMachineId;
|
|
329
|
-
function getCachedMachineId() {
|
|
330
|
-
if (!_cachedMachineId) _cachedMachineId = getMachineId();
|
|
331
|
-
return _cachedMachineId;
|
|
332
|
-
}
|
|
333
|
-
function deriveKey(machineId) {
|
|
334
|
-
return crypto.scryptSync(machineId, SCRYPT_SALT, KEY_LEN, {
|
|
335
|
-
N: SCRYPT_N,
|
|
336
|
-
r: SCRYPT_R,
|
|
337
|
-
p: SCRYPT_P
|
|
338
|
-
});
|
|
339
|
-
}
|
|
340
|
-
var _cachedKey;
|
|
341
|
-
function getKey() {
|
|
342
|
-
if (!_cachedKey) _cachedKey = deriveKey(getCachedMachineId());
|
|
343
|
-
return _cachedKey;
|
|
344
|
-
}
|
|
345
|
-
function encrypt(plaintext) {
|
|
346
|
-
const key = getKey();
|
|
347
|
-
const nonce = crypto.randomBytes(NONCE_LEN);
|
|
348
|
-
const cipher = crypto.createCipheriv("aes-256-gcm", key, nonce);
|
|
349
|
-
const encrypted = Buffer.concat([cipher.update(plaintext, "utf8"), cipher.final()]);
|
|
350
|
-
const tag = cipher.getAuthTag();
|
|
351
|
-
return {
|
|
352
|
-
nonce: nonce.toString("hex"),
|
|
353
|
-
tag: tag.toString("hex"),
|
|
354
|
-
data: encrypted.toString("hex")
|
|
355
|
-
};
|
|
356
|
-
}
|
|
357
|
-
function decrypt(blob) {
|
|
358
|
-
const key = getKey();
|
|
359
|
-
const nonce = Buffer.from(blob.nonce, "hex");
|
|
360
|
-
const tag = Buffer.from(blob.tag, "hex");
|
|
361
|
-
const data = Buffer.from(blob.data, "hex");
|
|
362
|
-
const decipher = crypto.createDecipheriv("aes-256-gcm", key, nonce);
|
|
363
|
-
decipher.setAuthTag(tag);
|
|
364
|
-
const decrypted = Buffer.concat([decipher.update(data), decipher.final()]);
|
|
365
|
-
return decrypted.toString("utf8");
|
|
366
|
-
}
|
|
367
|
-
function storeDir() {
|
|
368
|
-
return path2.join(getConfigDir(), STORE_DIR_SUFFIX);
|
|
369
|
-
}
|
|
370
|
-
function tokenFilePath(host) {
|
|
371
|
-
const safe = host.replace(/^https?:\/\//, "").replace(/[^a-zA-Z0-9._-]/g, "_");
|
|
372
|
-
return path2.join(storeDir(), `${safe}.enc.json`);
|
|
373
|
-
}
|
|
374
|
-
function ensureStoreDir() {
|
|
375
|
-
const dir = storeDir();
|
|
376
|
-
if (!fs4.existsSync(dir)) {
|
|
377
|
-
fs4.mkdirSync(dir, { recursive: true });
|
|
378
|
-
try {
|
|
379
|
-
fs4.chmodSync(dir, 448);
|
|
380
|
-
} catch {
|
|
381
|
-
}
|
|
382
|
-
}
|
|
383
|
-
}
|
|
384
|
-
function save(host, payload) {
|
|
385
|
-
ensureStoreDir();
|
|
386
|
-
const plaintext = JSON.stringify(payload);
|
|
387
|
-
const blob = encrypt(plaintext);
|
|
388
|
-
const filePath = tokenFilePath(host);
|
|
389
|
-
fs4.writeFileSync(filePath, JSON.stringify(blob, null, 2), { encoding: "utf8" });
|
|
390
|
-
try {
|
|
391
|
-
fs4.chmodSync(filePath, 384);
|
|
392
|
-
} catch {
|
|
393
|
-
}
|
|
394
|
-
logger.info(`secure-store: token saved for ${host}`);
|
|
395
|
-
}
|
|
396
|
-
function load(host) {
|
|
397
|
-
const filePath = tokenFilePath(host);
|
|
398
|
-
if (!fs4.existsSync(filePath)) return null;
|
|
399
|
-
try {
|
|
400
|
-
const raw = fs4.readFileSync(filePath, "utf8");
|
|
401
|
-
const blob = safeJsonParse(raw);
|
|
402
|
-
if (!blob?.nonce || !blob?.tag || !blob?.data) {
|
|
403
|
-
logger.warn(`secure-store: malformed blob for ${host}`);
|
|
404
|
-
return null;
|
|
405
|
-
}
|
|
406
|
-
const plaintext = decrypt(blob);
|
|
407
|
-
return JSON.parse(plaintext);
|
|
408
|
-
} catch (e) {
|
|
409
|
-
logger.error(`secure-store: decrypt failed for ${host}: ${e.message}`);
|
|
410
|
-
return null;
|
|
411
|
-
}
|
|
412
|
-
}
|
|
413
|
-
function clear(host) {
|
|
414
|
-
const filePath = tokenFilePath(host);
|
|
415
|
-
if (fs4.existsSync(filePath)) {
|
|
416
|
-
fs4.rmSync(filePath);
|
|
417
|
-
logger.info(`secure-store: token cleared for ${host}`);
|
|
418
|
-
}
|
|
419
|
-
}
|
|
420
|
-
async function getValidAccessToken(host) {
|
|
421
|
-
const payload = load(host);
|
|
422
|
-
if (!payload) {
|
|
423
|
-
throw new SecureStoreAuthError(
|
|
424
|
-
`No stored token for ${host}. Please run: ae-cli auth login`
|
|
425
|
-
);
|
|
426
|
-
}
|
|
427
|
-
const expiresAt = new Date(payload.accessExpiresAt).getTime();
|
|
428
|
-
const now = Date.now();
|
|
429
|
-
const needsRefresh = expiresAt - now < 6e4;
|
|
430
|
-
if (!needsRefresh) {
|
|
431
|
-
return payload.accessToken;
|
|
432
|
-
}
|
|
433
|
-
if (payload.refreshToken) {
|
|
434
|
-
logger.info(`secure-store: access token past local expiry for ${host}, refreshing\u2026`);
|
|
435
|
-
const refreshed = await doRefresh(host, payload.refreshToken);
|
|
436
|
-
save(host, { ...refreshed, cliToken: payload.cliToken });
|
|
437
|
-
logger.info(`secure-store: token refreshed for ${host}`);
|
|
438
|
-
return refreshed.accessToken;
|
|
439
|
-
}
|
|
440
|
-
logger.info(`secure-store: ${host} past static local expiry, no refresh token \u2014 returning stored token, server validates (lazy)`);
|
|
441
|
-
return payload.accessToken;
|
|
442
|
-
}
|
|
443
|
-
function loadCliToken(host) {
|
|
444
|
-
return load(host)?.cliToken ?? null;
|
|
445
|
-
}
|
|
446
|
-
async function doRefresh(host, refreshToken) {
|
|
447
|
-
const base = host.replace(/\/+$/, "");
|
|
448
|
-
const url = `${base}${REFRESH_TOKEN_PATH}`;
|
|
449
|
-
let resp;
|
|
450
|
-
try {
|
|
451
|
-
resp = await fetch(url, {
|
|
452
|
-
method: "POST",
|
|
453
|
-
headers: { "Content-Type": "application/json" },
|
|
454
|
-
body: JSON.stringify({ refreshToken })
|
|
455
|
-
});
|
|
456
|
-
} catch (e) {
|
|
457
|
-
throw new SecureStoreAuthError(
|
|
458
|
-
`Token refresh network error for ${host}: ${e.message}. Please run: ae-cli auth login`
|
|
459
|
-
);
|
|
460
|
-
}
|
|
461
|
-
if (!resp.ok) {
|
|
462
|
-
throw new SecureStoreAuthError(
|
|
463
|
-
`Token refresh failed (HTTP ${resp.status}) for ${host}. Please run: ae-cli auth login`
|
|
464
|
-
);
|
|
465
|
-
}
|
|
466
|
-
let body;
|
|
467
|
-
try {
|
|
468
|
-
body = safeJsonParse(await resp.text());
|
|
469
|
-
} catch {
|
|
470
|
-
throw new SecureStoreAuthError(
|
|
471
|
-
`Token refresh returned invalid JSON for ${host}. Please run: ae-cli auth login`
|
|
472
|
-
);
|
|
473
|
-
}
|
|
474
|
-
if (body.return_code !== 0) {
|
|
475
|
-
throw new SecureStoreAuthError(
|
|
476
|
-
`Token refresh error (${body.return_code}: ${body.return_message ?? "unknown"}) for ${host}. Please run: ae-cli auth login`
|
|
477
|
-
);
|
|
478
|
-
}
|
|
479
|
-
const d = body.data;
|
|
480
|
-
const newAccess = d?.accessToken ?? d?.access_token ?? "";
|
|
481
|
-
const newRefresh = d?.refreshToken ?? d?.refresh_token ?? refreshToken;
|
|
482
|
-
const expiresIn = d?.expiresIn ?? d?.expires_in ?? 72e3;
|
|
483
|
-
if (!newAccess) {
|
|
484
|
-
throw new SecureStoreAuthError(
|
|
485
|
-
`Token refresh returned empty accessToken for ${host}. Please run: ae-cli auth login`
|
|
486
|
-
);
|
|
487
|
-
}
|
|
488
|
-
return {
|
|
489
|
-
accessToken: newAccess,
|
|
490
|
-
refreshToken: newRefresh,
|
|
491
|
-
accessExpiresAt: new Date(Date.now() + expiresIn * 1e3).toISOString()
|
|
492
|
-
};
|
|
493
|
-
}
|
|
494
|
-
var SecureStoreAuthError = class extends Error {
|
|
495
|
-
constructor(message) {
|
|
496
|
-
super(message);
|
|
497
|
-
this.name = "SecureStoreAuthError";
|
|
498
|
-
}
|
|
499
|
-
};
|
|
500
|
-
|
|
501
|
-
// src/core/host-guidance.ts
|
|
502
|
-
var AE_TRIAL_URL = "https://thinkingai.cn/request-demo";
|
|
503
|
-
var AE_HOST_SETUP_COMMAND = "ae-cli config set-host <url>";
|
|
504
|
-
function missingAeHostHint(additionalAction) {
|
|
505
|
-
const actions = [
|
|
506
|
-
`If your organization already uses AgenticEngine, ask your administrator for its AE URL, then run: ${AE_HOST_SETUP_COMMAND}.`,
|
|
507
|
-
`If you do not have an AgenticEngine environment, request a trial: ${AE_TRIAL_URL}`
|
|
508
|
-
];
|
|
509
|
-
if (additionalAction) actions.push(additionalAction);
|
|
510
|
-
return actions.join(" ");
|
|
511
|
-
}
|
|
512
|
-
function missingAeHostGuidance() {
|
|
513
|
-
return {
|
|
514
|
-
configure_host: AE_HOST_SETUP_COMMAND,
|
|
515
|
-
existing_customer: "Ask your AgenticEngine administrator for the AE environment URL.",
|
|
516
|
-
request_trial_url: AE_TRIAL_URL
|
|
517
|
-
};
|
|
518
|
-
}
|
|
519
|
-
|
|
520
|
-
// src/core/auth.ts
|
|
521
|
-
function resolveHost(hostOverride) {
|
|
522
|
-
if (hostOverride) return normalizeUrl(hostOverride);
|
|
523
|
-
return getActiveHost();
|
|
524
|
-
}
|
|
525
|
-
async function validateToken(token, hostUrl) {
|
|
526
|
-
const url = `${hostUrl}/v1/oauth/checkToken`;
|
|
527
|
-
try {
|
|
528
|
-
const resp = await fetch(url, {
|
|
529
|
-
method: "POST",
|
|
530
|
-
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
531
|
-
body: new URLSearchParams({ accessToken: token }).toString()
|
|
532
|
-
});
|
|
533
|
-
const respJson = safeJsonParse(await resp.text());
|
|
534
|
-
return respJson?.return_code === 0;
|
|
535
|
-
} catch {
|
|
536
|
-
return false;
|
|
537
|
-
}
|
|
538
|
-
}
|
|
539
|
-
function invalidateAccessTokenForRetry(hostUrl) {
|
|
540
|
-
const payload = load(hostUrl);
|
|
541
|
-
if (!payload) return;
|
|
542
|
-
save(hostUrl, { ...payload, accessExpiresAt: (/* @__PURE__ */ new Date(0)).toISOString() });
|
|
543
|
-
logger.info(`auth: marked access token stale for retry on ${hostUrl}`);
|
|
544
|
-
}
|
|
545
|
-
async function getToken(hostUrl) {
|
|
546
|
-
if (!hostUrl) {
|
|
547
|
-
throw new Error(
|
|
548
|
-
`No AE host configured.
|
|
549
|
-
` + missingAeHostHint()
|
|
550
|
-
);
|
|
551
|
-
}
|
|
552
|
-
try {
|
|
553
|
-
const secureToken = await getValidAccessToken(hostUrl);
|
|
554
|
-
logger.info(`Using secure-store token for ${hostUrl}`);
|
|
555
|
-
return secureToken;
|
|
556
|
-
} catch (e) {
|
|
557
|
-
if (e instanceof SecureStoreAuthError) {
|
|
558
|
-
logger.info(`secure-store: ${e.message}`);
|
|
559
|
-
} else {
|
|
560
|
-
logger.warn(`secure-store unexpected error: ${e.message}`);
|
|
561
|
-
}
|
|
562
|
-
}
|
|
563
|
-
throw new Error(
|
|
564
|
-
`Cannot obtain token for ${hostUrl}.
|
|
565
|
-
Run: ae-cli auth login (device code flow, cross-platform)`
|
|
566
|
-
);
|
|
567
|
-
}
|
|
568
|
-
|
|
569
|
-
export {
|
|
570
|
-
safeJsonParse,
|
|
571
|
-
safeReadJsonFile,
|
|
572
|
-
normalizeUrl,
|
|
573
|
-
getSandboxRuntimeRoot,
|
|
574
|
-
isAeSandboxRuntime,
|
|
575
|
-
getFallbackCliToken,
|
|
576
|
-
loadConfig,
|
|
577
|
-
saveConfig,
|
|
578
|
-
getActiveHost,
|
|
579
|
-
setActiveHost,
|
|
580
|
-
addHost,
|
|
581
|
-
updateHostLabel,
|
|
582
|
-
removeHost,
|
|
583
|
-
listHosts,
|
|
584
|
-
resolveHostSelector,
|
|
585
|
-
getConfigDir,
|
|
586
|
-
save,
|
|
587
|
-
load,
|
|
588
|
-
clear,
|
|
589
|
-
loadCliToken,
|
|
590
|
-
SecureStoreAuthError,
|
|
591
|
-
AE_TRIAL_URL,
|
|
592
|
-
missingAeHostHint,
|
|
593
|
-
missingAeHostGuidance,
|
|
594
|
-
resolveHost,
|
|
595
|
-
validateToken,
|
|
596
|
-
invalidateAccessTokenForRetry,
|
|
597
|
-
getToken
|
|
598
|
-
};
|