@okx_ai/okx-trade-cli 1.3.2-beta.5 → 1.3.2-beta.6

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/index.js CHANGED
@@ -21,23 +21,26 @@ import {
21
21
  import { homedir as homedir2 } from "os";
22
22
  import { join as join2, dirname } from "path";
23
23
  import { createHmac } from "crypto";
24
+ import { spawn, execFile as execFile2 } from "child_process";
25
+ import { homedir as homedir3 } from "os";
26
+ import { join as join3 } from "path";
24
27
  import fs from "fs";
25
28
  import path from "path";
26
29
  import os from "os";
27
30
  import { writeFileSync as writeFileSync2, renameSync as renameSync2, unlinkSync as unlinkSync2, mkdirSync as mkdirSync2 } from "fs";
28
- import { join as join3, resolve, basename, sep } from "path";
31
+ import { join as join4, resolve, basename, sep } from "path";
29
32
  import { randomUUID } from "crypto";
30
33
  import yauzl from "yauzl";
31
34
  import { createWriteStream, mkdirSync as mkdirSync3 } from "fs";
32
35
  import { resolve as resolve2, dirname as dirname2 } from "path";
33
36
  import { readFileSync as readFileSync2, existsSync } from "fs";
34
- import { join as join4 } from "path";
37
+ import { join as join5 } from "path";
35
38
  import { readFileSync as readFileSync3, writeFileSync as writeFileSync3, mkdirSync as mkdirSync4, existsSync as existsSync2 } from "fs";
36
- import { join as join5, dirname as dirname3 } from "path";
37
- import { homedir as homedir3 } from "os";
38
- import { readFileSync as readFileSync4, writeFileSync as writeFileSync4, mkdirSync as mkdirSync5, existsSync as existsSync3 } from "fs";
39
- import { join as join6, dirname as dirname4 } from "path";
39
+ import { join as join6, dirname as dirname3 } from "path";
40
40
  import { homedir as homedir4 } from "os";
41
+ import { readFileSync as readFileSync4, writeFileSync as writeFileSync4, mkdirSync as mkdirSync5, existsSync as existsSync3 } from "fs";
42
+ import { join as join7, dirname as dirname4 } from "path";
43
+ import { homedir as homedir5 } from "os";
41
44
 
42
45
  // ../../node_modules/.pnpm/smol-toml@1.6.0/node_modules/smol-toml/dist/error.js
43
46
  function getLineColFromPtr(string, ptr) {
@@ -867,8 +870,8 @@ function stringify(obj, { maxDepth = 1e3, numbersAsFloat = false } = {}) {
867
870
 
868
871
  // ../core/dist/index.js
869
872
  import { readFileSync as readFileSync5, writeFileSync as writeFileSync5, mkdirSync as mkdirSync6, existsSync as existsSync4 } from "fs";
870
- import { join as join7 } from "path";
871
- import { homedir as homedir5 } from "os";
873
+ import { join as join8 } from "path";
874
+ import { homedir as homedir6 } from "os";
872
875
  import fs2 from "fs";
873
876
  import path2 from "path";
874
877
  import os2 from "os";
@@ -876,6 +879,18 @@ import * as fs3 from "fs";
876
879
  import * as path3 from "path";
877
880
  import * as os3 from "os";
878
881
  import { execFileSync } from "child_process";
882
+ import {
883
+ createWriteStream as createWriteStream3,
884
+ mkdirSync as mkdirSync9,
885
+ chmodSync as chmodSync2,
886
+ existsSync as existsSync7,
887
+ unlinkSync as unlinkSync4,
888
+ renameSync as renameSync4
889
+ } from "fs";
890
+ import { homedir as homedir9, platform as platform2 } from "os";
891
+ import { join as join11, dirname as dirname7 } from "path";
892
+ import { get as httpsGet2 } from "https";
893
+ import { get as httpGet2 } from "http";
879
894
  import {
880
895
  readFileSync as readFileSync7,
881
896
  createWriteStream as createWriteStream2,
@@ -886,10 +901,13 @@ import {
886
901
  renameSync as renameSync3
887
902
  } from "fs";
888
903
  import { createHash } from "crypto";
889
- import { homedir as homedir7, platform, arch } from "os";
890
- import { join as join9, dirname as dirname6 } from "path";
904
+ import { homedir as homedir8, platform, arch } from "os";
905
+ import { join as join10, dirname as dirname6 } from "path";
891
906
  import { get as httpsGet } from "https";
892
907
  import { get as httpGet } from "http";
908
+ import { readFileSync as readFileSync8, writeFileSync as writeFileSync7, mkdirSync as mkdirSync10, unlinkSync as unlinkSync5, existsSync as existsSync8 } from "fs";
909
+ import { join as join12 } from "path";
910
+ import { homedir as homedir10 } from "os";
893
911
  var EXEC_TIMEOUT_MS = 3e4;
894
912
  var ALLOWED_DOMAIN_RE = /^[\w.-]+\.okx\.com$/;
895
913
  var PILOT_BIN_DIR = join(homedir(), ".okx", "bin");
@@ -1201,6 +1219,11 @@ var ConfigError = class extends OkxMcpError {
1201
1219
  super("ConfigError", message, { suggestion });
1202
1220
  }
1203
1221
  };
1222
+ var NotLoggedInError = class extends ConfigError {
1223
+ constructor(suggestion = "Run `okx auth login` to authenticate.") {
1224
+ super("Not logged in.", suggestion);
1225
+ }
1226
+ };
1204
1227
  var ValidationError = class extends OkxMcpError {
1205
1228
  constructor(message, suggestion) {
1206
1229
  super("ValidationError", message, { suggestion });
@@ -1253,6 +1276,97 @@ function toToolErrorPayload(error, fallbackEndpoint) {
1253
1276
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
1254
1277
  };
1255
1278
  }
1279
+ var EXIT_CODES = {
1280
+ SUCCESS: 0,
1281
+ UNAUTHORIZED_CALLER: 1,
1282
+ NOT_LOGGED_IN: 2,
1283
+ REFRESH_FAILED: 3
1284
+ };
1285
+ var EXEC_TIMEOUT_MS2 = 5e3;
1286
+ var AUTH_BIN_DIR = join3(homedir3(), ".okx", "bin");
1287
+ function getAuthBinaryPath() {
1288
+ if (process.env.OKX_AUTH_BIN) {
1289
+ return process.env.OKX_AUTH_BIN;
1290
+ }
1291
+ const ext = process.platform === "win32" ? ".exe" : "";
1292
+ return join3(AUTH_BIN_DIR, `okx-auth${ext}`);
1293
+ }
1294
+ function execAuthToken() {
1295
+ const binPath = getAuthBinaryPath();
1296
+ return new Promise((resolve3, reject) => {
1297
+ const child = spawn(binPath, ["token"], {
1298
+ stdio: ["ignore", "ignore", "inherit", "pipe"]
1299
+ // stdin stdout stderr fd3 (pipe)
1300
+ });
1301
+ const chunks = [];
1302
+ const fd3 = child.stdio[3];
1303
+ fd3.on("data", (chunk) => chunks.push(chunk));
1304
+ child.on("error", (err) => {
1305
+ reject(new ConfigError(
1306
+ `Failed to spawn okx-auth: ${err.message}`,
1307
+ "Ensure the okx-auth binary exists and is executable."
1308
+ ));
1309
+ });
1310
+ child.on("close", (code) => {
1311
+ if (code === EXIT_CODES.SUCCESS) {
1312
+ const token = Buffer.concat(chunks).toString("utf-8").trim();
1313
+ if (!token) {
1314
+ reject(new AuthenticationError(
1315
+ "okx-auth returned empty token.",
1316
+ "Run `okx auth login` to re-authenticate."
1317
+ ));
1318
+ return;
1319
+ }
1320
+ resolve3(token);
1321
+ return;
1322
+ }
1323
+ if (code === EXIT_CODES.NOT_LOGGED_IN) {
1324
+ reject(new NotLoggedInError());
1325
+ return;
1326
+ }
1327
+ if (code === EXIT_CODES.UNAUTHORIZED_CALLER) {
1328
+ reject(new AuthenticationError(
1329
+ "okx-auth rejected the caller (unauthorized).",
1330
+ "Ensure you are running from a trusted OKX tool."
1331
+ ));
1332
+ return;
1333
+ }
1334
+ if (code === EXIT_CODES.REFRESH_FAILED) {
1335
+ reject(new AuthenticationError(
1336
+ "Token refresh failed.",
1337
+ "Run `okx auth login` to re-authenticate."
1338
+ ));
1339
+ return;
1340
+ }
1341
+ reject(new AuthenticationError(
1342
+ `okx-auth token exited with code ${code}.`,
1343
+ "Run `okx auth login` to re-authenticate."
1344
+ ));
1345
+ });
1346
+ });
1347
+ }
1348
+ function execAuthStatus() {
1349
+ const binPath = getAuthBinaryPath();
1350
+ return new Promise((resolve3) => {
1351
+ execFile2(
1352
+ binPath,
1353
+ ["status", "--json"],
1354
+ { timeout: EXEC_TIMEOUT_MS2, encoding: "utf-8" },
1355
+ (error, stdout) => {
1356
+ if (error) {
1357
+ resolve3(null);
1358
+ return;
1359
+ }
1360
+ try {
1361
+ const result = JSON.parse(stdout);
1362
+ resolve3(result);
1363
+ } catch {
1364
+ resolve3(null);
1365
+ }
1366
+ }
1367
+ );
1368
+ });
1369
+ }
1256
1370
  function sleep(ms) {
1257
1371
  return new Promise((resolve3) => {
1258
1372
  setTimeout(resolve3, ms);
@@ -1384,6 +1498,7 @@ function maskKey(key) {
1384
1498
  if (key.length <= 8) return "***";
1385
1499
  return `${key.slice(0, 3)}***${key.slice(-3)}`;
1386
1500
  }
1501
+ var TOKEN_CACHE_TTL_MS = 6e4;
1387
1502
  function vlog2(message) {
1388
1503
  process.stderr.write(`[verbose] ${message}
1389
1504
  `);
@@ -1392,6 +1507,8 @@ var OkxRestClient = class _OkxRestClient {
1392
1507
  config;
1393
1508
  rateLimiter;
1394
1509
  dispatcher;
1510
+ cachedAccessToken;
1511
+ cachedAccessTokenAt = 0;
1395
1512
  pilot;
1396
1513
  constructor(config) {
1397
1514
  this.config = config;
@@ -1406,6 +1523,51 @@ var OkxRestClient = class _OkxRestClient {
1406
1523
  hasCustomProxy: !!config.proxyUrl
1407
1524
  });
1408
1525
  }
1526
+ /**
1527
+ * Resolve OAuth access token via the okx-auth binary (fd3 pipe).
1528
+ * Caches the token for 60 s to avoid spawning the binary on every
1529
+ * request. The binary handles refresh internally (300s TTL lead),
1530
+ * so periodic re-calls let it serve a fresh token when needed.
1531
+ * Returns null when not logged in.
1532
+ */
1533
+ async resolveAccessToken() {
1534
+ if (this.cachedAccessToken && Date.now() - this.cachedAccessTokenAt < TOKEN_CACHE_TTL_MS) {
1535
+ return this.cachedAccessToken;
1536
+ }
1537
+ try {
1538
+ const token = await execAuthToken();
1539
+ this.cachedAccessToken = token;
1540
+ this.cachedAccessTokenAt = Date.now();
1541
+ return token;
1542
+ } catch (e) {
1543
+ if (e instanceof NotLoggedInError) {
1544
+ return null;
1545
+ }
1546
+ throw e;
1547
+ }
1548
+ }
1549
+ /**
1550
+ * Dynamic auth — determines auth method per request.
1551
+ *
1552
+ * 1. API key in config → HMAC signing (no OAuth fallback)
1553
+ * 2. OAuth token via okx-auth binary → Bearer token
1554
+ * 3. Neither → throw ConfigError
1555
+ */
1556
+ async applyAuth(headers, method, requestPath, bodyJson, timestamp) {
1557
+ if (this.config.apiKey && this.config.secretKey && this.config.passphrase) {
1558
+ this.setAuthHeaders(headers, method, requestPath, bodyJson, timestamp);
1559
+ return;
1560
+ }
1561
+ const accessToken = await this.resolveAccessToken();
1562
+ if (accessToken) {
1563
+ headers.set("Authorization", `Bearer ${accessToken}`);
1564
+ return;
1565
+ }
1566
+ throw new ConfigError(
1567
+ "No credentials found.",
1568
+ "Run `okx auth login` to authenticate, or configure API key credentials."
1569
+ );
1570
+ }
1409
1571
  /** The canonical base URL for this client (e.g. https://www.okx.com). */
1410
1572
  get baseUrl() {
1411
1573
  return this.config.baseUrl;
@@ -1464,18 +1626,6 @@ var OkxRestClient = class _OkxRestClient {
1464
1626
  });
1465
1627
  }
1466
1628
  setAuthHeaders(headers, method, requestPath, bodyJson, timestamp) {
1467
- if (!this.config.hasAuth) {
1468
- throw new ConfigError(
1469
- "Private endpoint requires API credentials.",
1470
- "Configure OKX_API_KEY, OKX_SECRET_KEY and OKX_PASSPHRASE."
1471
- );
1472
- }
1473
- if (!this.config.apiKey || !this.config.secretKey || !this.config.passphrase) {
1474
- throw new ConfigError(
1475
- "Invalid private API credentials state.",
1476
- "Ensure all OKX credentials are set."
1477
- );
1478
- }
1479
1629
  const payload = `${timestamp}${method.toUpperCase()}${requestPath}${bodyJson}`;
1480
1630
  const signature = signOkxPayload(payload, this.config.secretKey);
1481
1631
  headers.set("OK-ACCESS-KEY", this.config.apiKey);
@@ -1590,7 +1740,7 @@ var OkxRestClient = class _OkxRestClient {
1590
1740
  const conn = this.pilot.getConnectionParams();
1591
1741
  this.logRequest("POST", `${conn.baseUrl}${path42}`, "private");
1592
1742
  const reqConfig = { method: "POST", path: path42, auth: "private" };
1593
- const headers = this.buildHeaders(reqConfig, path42, bodyJson, getNow());
1743
+ const headers = await this.buildHeaders(reqConfig, path42, bodyJson, getNow());
1594
1744
  if (conn.userAgent) {
1595
1745
  headers.set("User-Agent", conn.userAgent);
1596
1746
  }
@@ -1711,7 +1861,7 @@ var OkxRestClient = class _OkxRestClient {
1711
1861
  // Header building
1712
1862
  // ---------------------------------------------------------------------------
1713
1863
  /** Build HTTP headers. reqConfig.extraHeaders must NOT contain auth keys (OK-ACCESS-*). */
1714
- buildHeaders(reqConfig, requestPath, bodyJson, timestamp) {
1864
+ async buildHeaders(reqConfig, requestPath, bodyJson, timestamp) {
1715
1865
  const headers = new Headers({
1716
1866
  "Content-Type": "application/json",
1717
1867
  Accept: "application/json"
@@ -1720,7 +1870,7 @@ var OkxRestClient = class _OkxRestClient {
1720
1870
  headers.set("User-Agent", this.config.userAgent);
1721
1871
  }
1722
1872
  if (reqConfig.auth === "private") {
1723
- this.setAuthHeaders(headers, reqConfig.method, requestPath, bodyJson, timestamp);
1873
+ await this.applyAuth(headers, reqConfig.method, requestPath, bodyJson, timestamp);
1724
1874
  }
1725
1875
  const useSimulated = reqConfig.simulatedTrading !== void 0 ? reqConfig.simulatedTrading : this.config.demo;
1726
1876
  if (useSimulated) {
@@ -1774,7 +1924,7 @@ var OkxRestClient = class _OkxRestClient {
1774
1924
  if (reqConfig.rateLimit) {
1775
1925
  await this.rateLimiter.consume(reqConfig.rateLimit);
1776
1926
  }
1777
- const headers = this.buildHeaders(reqConfig, requestPath, bodyJson, timestamp);
1927
+ const headers = await this.buildHeaders(reqConfig, requestPath, bodyJson, timestamp);
1778
1928
  if (conn.userAgent) {
1779
1929
  headers.set("User-Agent", conn.userAgent);
1780
1930
  }
@@ -2201,8 +2351,6 @@ function registerIndicatorTools() {
2201
2351
  ];
2202
2352
  }
2203
2353
  var DEFAULT_SOURCE_TAG = "MCP";
2204
- var TOKEN_REGEX = /^[A-Z2-7]{12}$/;
2205
- var TAG_JOIN = "";
2206
2354
  var OKX_SITES = {
2207
2355
  global: {
2208
2356
  label: "Global",
@@ -2216,7 +2364,7 @@ var OKX_SITES = {
2216
2364
  },
2217
2365
  us: {
2218
2366
  label: "US",
2219
- apiBaseUrl: "https://app.okx.com",
2367
+ apiBaseUrl: "https://us.okx.com",
2220
2368
  webUrl: "https://app.okx.com"
2221
2369
  }
2222
2370
  };
@@ -3160,8 +3308,7 @@ function registerAlgoTradeTools() {
3160
3308
  callBackSpread: readString(args, "callbackSpread"),
3161
3309
  activePx: readString(args, "activePx"),
3162
3310
  reduceOnly: typeof reduceOnly === "boolean" ? String(reduceOnly) : void 0,
3163
- clOrdId: readString(args, "clOrdId"),
3164
- tag: context.config.sourceTag
3311
+ clOrdId: readString(args, "clOrdId")
3165
3312
  }),
3166
3313
  privateRateLimit("swap_place_move_stop_order", 20)
3167
3314
  );
@@ -3506,8 +3653,7 @@ function registerFuturesAlgoTools() {
3506
3653
  callBackSpread: readString(args, "callbackSpread"),
3507
3654
  activePx: readString(args, "activePx"),
3508
3655
  reduceOnly: typeof reduceOnly === "boolean" ? String(reduceOnly) : void 0,
3509
- clOrdId: readString(args, "clOrdId"),
3510
- tag: context.config.sourceTag
3656
+ clOrdId: readString(args, "clOrdId")
3511
3657
  }),
3512
3658
  privateRateLimit("futures_place_move_stop_order", 20)
3513
3659
  );
@@ -3765,7 +3911,7 @@ function safeWriteFile(targetDir, fileName, data) {
3765
3911
  throw new Error(`Invalid file name: "${fileName}"`);
3766
3912
  }
3767
3913
  const resolvedDir = resolve(targetDir);
3768
- const filePath = join3(resolvedDir, safeName);
3914
+ const filePath = join4(resolvedDir, safeName);
3769
3915
  const resolvedPath = resolve(filePath);
3770
3916
  if (!resolvedPath.startsWith(resolvedDir + sep)) {
3771
3917
  throw new Error(`Path traversal detected: "${fileName}" resolves outside target directory`);
@@ -3893,7 +4039,7 @@ async function extractSkillZip(zipPath, targetDir, limits) {
3893
4039
  });
3894
4040
  }
3895
4041
  function readMetaJson(contentDir) {
3896
- const metaPath = join4(contentDir, "_meta.json");
4042
+ const metaPath = join5(contentDir, "_meta.json");
3897
4043
  if (!existsSync(metaPath)) {
3898
4044
  throw new Error(`_meta.json not found in ${contentDir}. Invalid skill package.`);
3899
4045
  }
@@ -3919,12 +4065,12 @@ function readMetaJson(contentDir) {
3919
4065
  };
3920
4066
  }
3921
4067
  function validateSkillMdExists(contentDir) {
3922
- const skillMdPath = join4(contentDir, "SKILL.md");
4068
+ const skillMdPath = join5(contentDir, "SKILL.md");
3923
4069
  if (!existsSync(skillMdPath)) {
3924
4070
  throw new Error(`SKILL.md not found in ${contentDir}. Invalid skill package.`);
3925
4071
  }
3926
4072
  }
3927
- var DEFAULT_REGISTRY_PATH = join5(homedir3(), ".okx", "skills", "registry.json");
4073
+ var DEFAULT_REGISTRY_PATH = join6(homedir4(), ".okx", "skills", "registry.json");
3928
4074
  function readRegistry(registryPath = DEFAULT_REGISTRY_PATH) {
3929
4075
  if (!existsSync2(registryPath)) {
3930
4076
  return { version: 1, skills: {} };
@@ -10339,7 +10485,7 @@ function createToolRunner(client, config) {
10339
10485
  };
10340
10486
  }
10341
10487
  function configFilePath() {
10342
- return join6(homedir4(), ".okx", "config.toml");
10488
+ return join7(homedir5(), ".okx", "config.toml");
10343
10489
  }
10344
10490
  function readFullConfig() {
10345
10491
  const path42 = configFilePath();
@@ -10358,11 +10504,6 @@ Or re-run: okx config init`
10358
10504
  );
10359
10505
  }
10360
10506
  }
10361
- function readTomlProfile(profileName) {
10362
- const config = readFullConfig();
10363
- const name = profileName ?? config.default_profile ?? "default";
10364
- return config.profiles?.[name] ?? {};
10365
- }
10366
10507
  var CONFIG_HEADER = `# OKX Trade Kit Configuration
10367
10508
  # If editing manually, wrap values containing special chars in quotes:
10368
10509
  # passphrase = 'value' (if value contains # \\ ")
@@ -10411,18 +10552,24 @@ function parseModuleList(rawModules) {
10411
10552
  }
10412
10553
  return Array.from(deduped);
10413
10554
  }
10414
- function loadCredentials(toml) {
10555
+ async function loadCredentials(toml) {
10415
10556
  const apiKey = process.env.OKX_API_KEY?.trim() ?? toml.api_key;
10416
10557
  const secretKey = process.env.OKX_SECRET_KEY?.trim() ?? toml.secret_key;
10417
10558
  const passphrase = process.env.OKX_PASSPHRASE?.trim() ?? toml.passphrase;
10418
- const hasAuth = Boolean(apiKey && secretKey && passphrase);
10559
+ const hasApiKey = Boolean(apiKey && secretKey && passphrase);
10419
10560
  const partialAuth = Boolean(apiKey) || Boolean(secretKey) || Boolean(passphrase);
10420
- if (partialAuth && !hasAuth) {
10561
+ if (partialAuth && !hasApiKey) {
10421
10562
  throw new ConfigError(
10422
10563
  "Partial API credentials detected.",
10423
10564
  "Set OKX_API_KEY, OKX_SECRET_KEY and OKX_PASSPHRASE together (env vars or config.toml profile)."
10424
10565
  );
10425
10566
  }
10567
+ let hasOAuth = false;
10568
+ if (!hasApiKey) {
10569
+ const status = await execAuthStatus();
10570
+ hasOAuth = status?.status === "logged_in";
10571
+ }
10572
+ const hasAuth = hasOAuth || hasApiKey;
10426
10573
  return { apiKey, secretKey, passphrase, hasAuth };
10427
10574
  }
10428
10575
  function resolveSite(cliSite, tomlSite) {
@@ -10445,30 +10592,6 @@ function resolveBaseUrl(site, tomlBaseUrl) {
10445
10592
  }
10446
10593
  return rawBaseUrl.replace(/\/+$/, "");
10447
10594
  }
10448
- function resolveSourceTag(cli, defaultTag, opts = {}) {
10449
- const readEnv = opts.readEnv !== false;
10450
- const cliSkill = cli.skill?.trim();
10451
- if (cliSkill) {
10452
- if (isValidToken(cliSkill)) return composeTag(defaultTag, cliSkill);
10453
- console.warn("--skill value format invalid (expected 12-char Base32), ignoring");
10454
- }
10455
- if (readEnv) {
10456
- const envToken = process.env.OKX_SKILL_TOKEN?.trim();
10457
- if (envToken) {
10458
- if (isValidToken(envToken)) return composeTag(defaultTag, envToken);
10459
- console.warn("OKX_SKILL_TOKEN format invalid, ignoring");
10460
- }
10461
- }
10462
- const sourceTag = cli.sourceTag?.trim();
10463
- if (sourceTag) return sourceTag;
10464
- return defaultTag;
10465
- }
10466
- function composeTag(defaultTag, token) {
10467
- return `${defaultTag}${TAG_JOIN}${token}`;
10468
- }
10469
- function isValidToken(s) {
10470
- return TOKEN_REGEX.test(s);
10471
- }
10472
10595
  function resolveDemo(cli, toml) {
10473
10596
  if (cli.demo && cli.live) {
10474
10597
  throw new ConfigError(
@@ -10480,9 +10603,11 @@ function resolveDemo(cli, toml) {
10480
10603
  if (cli.demo === true) return true;
10481
10604
  return process.env.OKX_DEMO === "1" || process.env.OKX_DEMO === "true" || (toml.demo ?? false);
10482
10605
  }
10483
- function loadConfig(cli, opts = {}) {
10484
- const toml = readTomlProfile(cli.profile);
10485
- const creds = loadCredentials(toml);
10606
+ async function loadConfig(cli) {
10607
+ const config = readFullConfig();
10608
+ const profileName = cli.profile ?? config.default_profile ?? "default";
10609
+ const toml = config.profiles?.[profileName] ?? {};
10610
+ const creds = await loadCredentials(toml);
10486
10611
  const demo = resolveDemo(cli, toml);
10487
10612
  const site = resolveSite(cli.site, toml.site);
10488
10613
  const baseUrl = resolveBaseUrl(site, toml.base_url);
@@ -10500,9 +10625,9 @@ function loadConfig(cli, opts = {}) {
10500
10625
  "proxy_url must start with http:// or https://. SOCKS proxies are not supported."
10501
10626
  );
10502
10627
  }
10503
- const defaultTag = opts.entryPrefix ?? DEFAULT_SOURCE_TAG;
10504
10628
  return {
10505
10629
  ...creds,
10630
+ profile: profileName,
10506
10631
  baseUrl,
10507
10632
  timeoutMs: Math.floor(rawTimeout),
10508
10633
  modules: parseModuleList(cli.modules),
@@ -10510,14 +10635,12 @@ function loadConfig(cli, opts = {}) {
10510
10635
  demo,
10511
10636
  site,
10512
10637
  userAgent: cli.userAgent,
10513
- // sourceTag resolution: --skill > OKX_SKILL_TOKEN > --source-tag > defaultTag
10514
- // MCP entry passes { readEnv: false } to honour the "MCP path not attributed" contract.
10515
- sourceTag: resolveSourceTag(cli, defaultTag, { readEnv: opts.readEnv }),
10638
+ sourceTag: cli.sourceTag ?? DEFAULT_SOURCE_TAG,
10516
10639
  proxyUrl: rawProxyUrl || void 0,
10517
10640
  verbose: cli.verbose ?? false
10518
10641
  };
10519
10642
  }
10520
- var CACHE_FILE = join7(homedir5(), ".okx", "update-check.json");
10643
+ var CACHE_FILE = join8(homedir6(), ".okx", "update-check.json");
10521
10644
  var CHECK_INTERVAL_MS = 24 * 60 * 60 * 1e3;
10522
10645
  function readCache2() {
10523
10646
  try {
@@ -10530,7 +10653,7 @@ function readCache2() {
10530
10653
  }
10531
10654
  function writeCache2(cache) {
10532
10655
  try {
10533
- mkdirSync6(join7(homedir5(), ".okx"), { recursive: true });
10656
+ mkdirSync6(join8(homedir6(), ".okx"), { recursive: true });
10534
10657
  writeFileSync5(CACHE_FILE, JSON.stringify(cache, null, 2), "utf-8");
10535
10658
  } catch {
10536
10659
  }
@@ -10700,13 +10823,13 @@ function findMsStoreClaudePath() {
10700
10823
  }
10701
10824
  function getConfigPath(client) {
10702
10825
  const home = os3.homedir();
10703
- const platform2 = process.platform;
10826
+ const platform3 = process.platform;
10704
10827
  switch (client) {
10705
10828
  case "claude-desktop":
10706
- if (platform2 === "win32") {
10829
+ if (platform3 === "win32") {
10707
10830
  return findMsStoreClaudePath() ?? path3.join(appData(), "Claude", CLAUDE_CONFIG_FILE);
10708
10831
  }
10709
- if (platform2 === "darwin") {
10832
+ if (platform3 === "darwin") {
10710
10833
  return path3.join(home, "Library", "Application Support", "Claude", CLAUDE_CONFIG_FILE);
10711
10834
  }
10712
10835
  return path3.join(process.env.XDG_CONFIG_HOME ?? path3.join(home, ".config"), "Claude", CLAUDE_CONFIG_FILE);
@@ -10818,7 +10941,7 @@ var DOWNLOAD_TIMEOUT_MS = 3e4;
10818
10941
  var PLATFORM_MAP = {
10819
10942
  "darwin-arm64": "darwin-arm64",
10820
10943
  "darwin-x64": "darwin-x64",
10821
- "linux-arm64": "linux-arm64",
10944
+ "linux-arm64": "linux-x64",
10822
10945
  "linux-x64": "linux-x64",
10823
10946
  "win32-arm64": "win32-arm64",
10824
10947
  "win32-x64": "win32-x64"
@@ -10950,7 +11073,7 @@ async function installPilotBinary(destPath, sources = CDN_SOURCES, onProgress) {
10950
11073
  if (earlyResult) return earlyResult;
10951
11074
  const platformDir = getPlatformDir();
10952
11075
  const binaryName = getBinaryName();
10953
- const resolvedDest = destPath ?? join9(homedir7(), ".okx", "bin", binaryName);
11076
+ const resolvedDest = destPath ?? join10(homedir8(), ".okx", "bin", binaryName);
10954
11077
  const tmpPath = resolvedDest + ".tmp";
10955
11078
  mkdirSync8(dirname6(resolvedDest), { recursive: true });
10956
11079
  const localHash = existsSync6(resolvedDest) ? hashFile(resolvedDest) : null;
@@ -11073,16 +11196,276 @@ function downloadText(url, timeoutMs) {
11073
11196
  })
11074
11197
  );
11075
11198
  }
11199
+ var AUTH_CDN_PATH_PREFIX = "/upgradeapp/tools/oauth";
11200
+ function getAuthBinaryName() {
11201
+ return platform2() === "win32" ? "okx-auth.exe" : "okx-auth";
11202
+ }
11203
+ function getAuthStatus(binaryPath, opts) {
11204
+ const resolvedPath = binaryPath ?? getAuthBinaryPath();
11205
+ const platformDir = getPlatformDir();
11206
+ if (!existsSync7(resolvedPath)) {
11207
+ return { binaryPath: resolvedPath, exists: false, platform: platformDir };
11208
+ }
11209
+ if (opts?.skipHash) {
11210
+ return { binaryPath: resolvedPath, exists: true, platform: platformDir };
11211
+ }
11212
+ const { size, sha256 } = hashFile(resolvedPath);
11213
+ return { binaryPath: resolvedPath, exists: true, platform: platformDir, fileSize: size, sha256 };
11214
+ }
11215
+ async function fetchAuthCdnChecksum(sources = CDN_SOURCES, timeoutMs = DOWNLOAD_TIMEOUT_MS) {
11216
+ const platformDir = getPlatformDir();
11217
+ if (!platformDir) return null;
11218
+ const checksumPath = `${AUTH_CDN_PATH_PREFIX}/${platformDir}/checksum.json`;
11219
+ for (const { host, protocol } of sources) {
11220
+ try {
11221
+ const url = `${protocol}://${host}${checksumPath}`;
11222
+ const raw = await downloadText2(url, timeoutMs);
11223
+ const data = JSON.parse(raw);
11224
+ if (typeof data.sha256 !== "string" || typeof data.size !== "number" || typeof data.target !== "string") {
11225
+ continue;
11226
+ }
11227
+ return { sha256: data.sha256, size: data.size, target: data.target, source: host };
11228
+ } catch {
11229
+ }
11230
+ }
11231
+ return null;
11232
+ }
11233
+ async function fetchAndValidateChecksum2(host, protocol, checksumPath, platformDir, timeoutMs, onProgress) {
11234
+ const checksumUrl = `${protocol}://${host}${checksumPath}`;
11235
+ onProgress?.(`Fetching checksum from ${host}...`);
11236
+ const raw = await downloadText2(checksumUrl, timeoutMs);
11237
+ const checksum = JSON.parse(raw);
11238
+ if (typeof checksum.sha256 !== "string" || typeof checksum.size !== "number" || typeof checksum.target !== "string") {
11239
+ throw new Error("Invalid checksum.json: missing sha256, size, or target");
11240
+ }
11241
+ if (checksum.target !== platformDir) {
11242
+ throw new Error(`Target mismatch: expected ${platformDir}, got ${checksum.target}`);
11243
+ }
11244
+ return { sha256: checksum.sha256, size: checksum.size, target: checksum.target };
11245
+ }
11246
+ async function downloadAndVerify2(host, protocol, binaryPath, tmpPath, checksum, timeoutMs, onProgress) {
11247
+ const binaryUrl = `${protocol}://${host}${binaryPath}`;
11248
+ onProgress?.(`Downloading binary from ${host}...`);
11249
+ await download2(binaryUrl, tmpPath, timeoutMs);
11250
+ const actual = hashFile(tmpPath);
11251
+ if (actual.size !== checksum.size) {
11252
+ throw new Error(`Size mismatch: expected ${checksum.size}, got ${actual.size}`);
11253
+ }
11254
+ if (actual.sha256 !== checksum.sha256) {
11255
+ throw new Error(`SHA-256 mismatch: expected ${checksum.sha256}, got ${actual.sha256}`);
11256
+ }
11257
+ }
11258
+ function atomicReplace2(tmpPath, resolvedDest) {
11259
+ if (platform2() === "win32") {
11260
+ try {
11261
+ unlinkSync4(resolvedDest);
11262
+ } catch {
11263
+ }
11264
+ }
11265
+ renameSync4(tmpPath, resolvedDest);
11266
+ if (platform2() !== "win32") {
11267
+ chmodSync2(resolvedDest, 493);
11268
+ }
11269
+ }
11270
+ function installPreChecks2(destPath, sources) {
11271
+ if (!destPath && process.env.OKX_AUTH_BIN) {
11272
+ return { status: "up-to-date", source: "(env override)" };
11273
+ }
11274
+ if (!getPlatformDir()) {
11275
+ return { status: "failed", error: "Unsupported platform" };
11276
+ }
11277
+ if (sources.length === 0) {
11278
+ return { status: "failed", error: "No CDN sources available" };
11279
+ }
11280
+ return null;
11281
+ }
11282
+ function isLocalUpToDate2(localHash, checksum) {
11283
+ return localHash !== null && localHash.size === checksum.size && localHash.sha256 === checksum.sha256;
11284
+ }
11285
+ async function installAuthBinary(destPath, sources = CDN_SOURCES, onProgress) {
11286
+ const earlyResult = installPreChecks2(destPath, sources);
11287
+ if (earlyResult) return earlyResult;
11288
+ const platformDir = getPlatformDir();
11289
+ const binaryName = getAuthBinaryName();
11290
+ const resolvedDest = destPath ?? join11(homedir9(), ".okx", "bin", binaryName);
11291
+ const tmpPath = resolvedDest + ".tmp";
11292
+ mkdirSync9(dirname7(resolvedDest), { recursive: true });
11293
+ const localHash = existsSync7(resolvedDest) ? hashFile(resolvedDest) : null;
11294
+ const checksumPath = `${AUTH_CDN_PATH_PREFIX}/${platformDir}/checksum.json`;
11295
+ const binaryPath = `${AUTH_CDN_PATH_PREFIX}/${platformDir}/${binaryName}`;
11296
+ const errors = [];
11297
+ for (const { host, protocol } of sources) {
11298
+ try {
11299
+ const checksum = await fetchAndValidateChecksum2(
11300
+ host,
11301
+ protocol,
11302
+ checksumPath,
11303
+ platformDir,
11304
+ DOWNLOAD_TIMEOUT_MS,
11305
+ onProgress
11306
+ );
11307
+ if (isLocalUpToDate2(localHash, checksum)) {
11308
+ onProgress?.("Already up to date (checksum match)");
11309
+ return { status: "up-to-date", source: host };
11310
+ }
11311
+ await downloadAndVerify2(host, protocol, binaryPath, tmpPath, checksum, DOWNLOAD_TIMEOUT_MS, onProgress);
11312
+ atomicReplace2(tmpPath, resolvedDest);
11313
+ onProgress?.(`Downloaded and verified from ${host}`);
11314
+ return { status: "installed", source: host };
11315
+ } catch (err) {
11316
+ try {
11317
+ unlinkSync4(tmpPath);
11318
+ } catch {
11319
+ }
11320
+ const msg = err instanceof Error ? err.message : String(err);
11321
+ errors.push(`${host}: ${msg}`);
11322
+ onProgress?.(`${host} failed: ${msg}`);
11323
+ }
11324
+ }
11325
+ return { status: "failed", error: `All CDN sources failed:
11326
+ ${errors.join("\n")}` };
11327
+ }
11328
+ function removeAuthBinary(binaryPath) {
11329
+ const resolvedPath = binaryPath ?? getAuthBinaryPath();
11330
+ try {
11331
+ unlinkSync4(resolvedPath);
11332
+ return { status: "removed" };
11333
+ } catch (err) {
11334
+ if (err.code === "ENOENT") {
11335
+ return { status: "not-found" };
11336
+ }
11337
+ const msg = err instanceof Error ? err.message : String(err);
11338
+ throw new Error(`Failed to remove ${resolvedPath}: ${msg}`);
11339
+ }
11340
+ }
11341
+ function isRedirect2(statusCode) {
11342
+ return statusCode !== void 0 && statusCode >= 300 && statusCode < 400;
11343
+ }
11344
+ function validateRedirect2(res, requestUrl, redirectCount, maxRedirects) {
11345
+ if (redirectCount > maxRedirects) {
11346
+ throw new Error(`Too many redirects (${maxRedirects})`);
11347
+ }
11348
+ const location = res.headers.location;
11349
+ if (requestUrl.startsWith("https") && !location.startsWith("https")) {
11350
+ throw new Error("Refused HTTPS \u2192 HTTP redirect downgrade");
11351
+ }
11352
+ return location;
11353
+ }
11354
+ function fetchResponse2(url, timeoutMs) {
11355
+ return new Promise((resolve3, reject) => {
11356
+ let redirects = 0;
11357
+ const maxRedirects = 5;
11358
+ function doRequest(requestUrl) {
11359
+ const reqFn = requestUrl.startsWith("https") ? httpsGet2 : httpGet2;
11360
+ const req = reqFn(requestUrl, { timeout: timeoutMs }, (res) => {
11361
+ if (isRedirect2(res.statusCode) && res.headers.location) {
11362
+ redirects++;
11363
+ try {
11364
+ const location = validateRedirect2(res, requestUrl, redirects, maxRedirects);
11365
+ res.resume();
11366
+ doRequest(location);
11367
+ } catch (err) {
11368
+ reject(err);
11369
+ }
11370
+ return;
11371
+ }
11372
+ if (res.statusCode !== 200) {
11373
+ reject(new Error(`HTTP ${res.statusCode ?? "unknown"}`));
11374
+ return;
11375
+ }
11376
+ resolve3(res);
11377
+ });
11378
+ req.on("error", reject);
11379
+ req.on("timeout", () => {
11380
+ req.destroy();
11381
+ reject(new Error("Download timed out"));
11382
+ });
11383
+ }
11384
+ doRequest(url);
11385
+ });
11386
+ }
11387
+ function download2(url, destPath, timeoutMs) {
11388
+ return fetchResponse2(url, timeoutMs).then(
11389
+ (res) => new Promise((resolve3, reject) => {
11390
+ const file = createWriteStream3(destPath);
11391
+ res.pipe(file);
11392
+ file.on("finish", () => file.close(() => resolve3()));
11393
+ file.on("error", (err) => {
11394
+ try {
11395
+ unlinkSync4(destPath);
11396
+ } catch {
11397
+ }
11398
+ reject(err);
11399
+ });
11400
+ })
11401
+ );
11402
+ }
11403
+ function downloadText2(url, timeoutMs) {
11404
+ return fetchResponse2(url, timeoutMs).then(
11405
+ (res) => new Promise((resolve3, reject) => {
11406
+ const chunks = [];
11407
+ res.on("data", (chunk) => chunks.push(chunk));
11408
+ res.on("end", () => resolve3(Buffer.concat(chunks).toString("utf8")));
11409
+ res.on("error", reject);
11410
+ })
11411
+ );
11412
+ }
11413
+ var CACHE_PATH = join12(homedir10(), ".okx", "auth-binary-check.json");
11414
+ var CHECK_INTERVAL_MS2 = 2 * 60 * 60 * 1e3;
11415
+ function readCache3() {
11416
+ try {
11417
+ if (!existsSync8(CACHE_PATH)) return null;
11418
+ const data = JSON.parse(readFileSync8(CACHE_PATH, "utf-8"));
11419
+ if (typeof data.cdnSha256 !== "string" || typeof data.checkedAt !== "number") return null;
11420
+ return { cdnSha256: data.cdnSha256, checkedAt: data.checkedAt };
11421
+ } catch {
11422
+ return null;
11423
+ }
11424
+ }
11425
+ function writeCache3(cdnSha256) {
11426
+ try {
11427
+ mkdirSync10(join12(homedir10(), ".okx"), { recursive: true });
11428
+ writeFileSync7(CACHE_PATH, JSON.stringify({ cdnSha256, checkedAt: Date.now() }, null, 2), "utf-8");
11429
+ } catch {
11430
+ }
11431
+ }
11432
+ async function ensureAuthBinaryLatest(onProgress) {
11433
+ if (process.env.OKX_AUTH_BIN) return;
11434
+ const cache = readCache3();
11435
+ if (cache && Date.now() - cache.checkedAt < CHECK_INTERVAL_MS2) return;
11436
+ try {
11437
+ const cdn = await fetchAuthCdnChecksum(void 0, 5e3);
11438
+ if (!cdn) return;
11439
+ const local = getAuthStatus();
11440
+ if (local.exists && local.sha256 === cdn.sha256) {
11441
+ writeCache3(cdn.sha256);
11442
+ return;
11443
+ }
11444
+ onProgress?.("Updating okx-auth binary...");
11445
+ const result = await installAuthBinary(void 0, void 0, onProgress);
11446
+ if (result.status === "installed" || result.status === "up-to-date") {
11447
+ const updated = getAuthStatus();
11448
+ if (updated.sha256) writeCache3(updated.sha256);
11449
+ if (result.status === "installed") {
11450
+ onProgress?.("\u2713 okx-auth updated successfully");
11451
+ }
11452
+ }
11453
+ } catch {
11454
+ }
11455
+ }
11456
+ function updateAuthBinaryCache(sha256) {
11457
+ writeCache3(sha256);
11458
+ }
11459
+ function clearAuthBinaryCache() {
11460
+ try {
11461
+ unlinkSync5(CACHE_PATH);
11462
+ } catch {
11463
+ }
11464
+ }
11076
11465
 
11077
- // src/commands/diagnose.ts
11078
- import dns from "dns/promises";
11079
- import net from "net";
11080
- import os5 from "os";
11081
- import tls from "tls";
11082
-
11083
- // src/commands/diagnose-utils.ts
11084
- import fs4 from "fs";
11085
- import { createRequire } from "module";
11466
+ // src/commands/auth.ts
11467
+ import { spawn as spawn2 } from "child_process";
11468
+ import readline from "readline";
11086
11469
 
11087
11470
  // src/formatter.ts
11088
11471
  import { EOL } from "os";
@@ -11173,7 +11556,286 @@ function markFailedIfSCodeError(data) {
11173
11556
  }
11174
11557
  }
11175
11558
 
11559
+ // src/commands/auth.ts
11560
+ function runOkxAuth(args) {
11561
+ const binPath = getAuthBinaryPath();
11562
+ return new Promise((resolve3, reject) => {
11563
+ const child = spawn2(binPath, args, {
11564
+ stdio: "inherit"
11565
+ });
11566
+ child.on("error", (err) => {
11567
+ reject(new Error(`Failed to spawn okx-auth: ${err.message}`));
11568
+ });
11569
+ child.on("close", (code) => {
11570
+ resolve3(code ?? 1);
11571
+ });
11572
+ });
11573
+ }
11574
+ function runOkxAuthCapture(args) {
11575
+ const binPath = getAuthBinaryPath();
11576
+ return new Promise((resolve3, reject) => {
11577
+ const child = spawn2(binPath, args, {
11578
+ stdio: ["inherit", "pipe", "inherit"]
11579
+ });
11580
+ const chunks = [];
11581
+ child.stdout.on("data", (chunk) => chunks.push(chunk));
11582
+ child.on("error", (err) => {
11583
+ reject(new Error(`Failed to spawn okx-auth: ${err.message}`));
11584
+ });
11585
+ child.on("close", (code) => {
11586
+ resolve3({
11587
+ code: code ?? 1,
11588
+ stdout: Buffer.concat(chunks).toString("utf-8")
11589
+ });
11590
+ });
11591
+ });
11592
+ }
11593
+ function findApiKeyProfile() {
11594
+ let config;
11595
+ try {
11596
+ config = readFullConfig();
11597
+ } catch {
11598
+ return null;
11599
+ }
11600
+ for (const [name, profile] of Object.entries(config.profiles ?? {})) {
11601
+ if (profile?.api_key) return name;
11602
+ }
11603
+ return null;
11604
+ }
11605
+ async function cmdAuthLogin(args) {
11606
+ const apiKeyProfile = findApiKeyProfile();
11607
+ if (apiKeyProfile) {
11608
+ if (args.manual) {
11609
+ outputLine(JSON.stringify({
11610
+ status: "skipped",
11611
+ reason: "api_key_configured",
11612
+ profile: apiKeyProfile,
11613
+ message: `API key already configured (profile: ${apiKeyProfile}). OAuth login skipped \u2014 API key will be used automatically.`
11614
+ }));
11615
+ } else {
11616
+ outputLine(`API key already configured (profile: ${apiKeyProfile}). OAuth login skipped \u2014 API key will be used automatically.`);
11617
+ }
11618
+ return;
11619
+ }
11620
+ const cliArgs = ["login"];
11621
+ if (args.site) cliArgs.push("--site", args.site);
11622
+ if (args.manual) cliArgs.push("--manual");
11623
+ const code = await runOkxAuth(cliArgs);
11624
+ if (code !== 0) {
11625
+ process.exitCode = code;
11626
+ }
11627
+ }
11628
+ async function cmdAuthLogout() {
11629
+ const code = await runOkxAuth(["logout"]);
11630
+ if (code !== 0) {
11631
+ process.exitCode = code;
11632
+ }
11633
+ }
11634
+ async function cmdAuthStatus(args) {
11635
+ const cliArgs = ["status"];
11636
+ if (args.json) cliArgs.push("--json");
11637
+ const result = await runOkxAuthCapture(cliArgs);
11638
+ if (result.stdout) {
11639
+ process.stdout.write(result.stdout);
11640
+ }
11641
+ if (result.code !== 0) {
11642
+ process.exitCode = result.code;
11643
+ }
11644
+ }
11645
+ function resolveChecksumMatch(local, cdnChecksum, cdnError) {
11646
+ if (!local.exists) return "not-installed";
11647
+ if (cdnError || !cdnChecksum) return "unavailable";
11648
+ if (cdnChecksum.sha256 === local.sha256) return "match";
11649
+ return "mismatch";
11650
+ }
11651
+ function checksumMatchLabel(match) {
11652
+ if (match === "match") return "\u2713 match";
11653
+ if (match === "mismatch") return "\u2717 mismatch (update available)";
11654
+ return "CDN unreachable";
11655
+ }
11656
+ function formatBytes(bytes) {
11657
+ if (bytes < 1024) return `${bytes} B`;
11658
+ if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
11659
+ return `${(bytes / (1024 * 1024)).toFixed(2)} MB`;
11660
+ }
11661
+ async function cmdAuthInstallStatus(json) {
11662
+ const local = getAuthStatus();
11663
+ let cdnChecksum = null;
11664
+ let cdnError = null;
11665
+ if (local.exists) {
11666
+ try {
11667
+ cdnChecksum = await fetchAuthCdnChecksum(void 0, 5e3);
11668
+ } catch (err) {
11669
+ cdnError = err instanceof Error ? err.message : String(err);
11670
+ }
11671
+ }
11672
+ const checksumMatch = resolveChecksumMatch(local, cdnChecksum, cdnError);
11673
+ if (json) {
11674
+ outputLine(
11675
+ JSON.stringify({
11676
+ binaryPath: local.binaryPath,
11677
+ exists: local.exists,
11678
+ platform: local.platform,
11679
+ fileSize: local.fileSize ?? null,
11680
+ sha256: local.sha256 ?? null,
11681
+ cdnMatch: checksumMatch,
11682
+ cdnSha256: cdnChecksum?.sha256 ?? null,
11683
+ cdnSource: cdnChecksum?.source ?? null
11684
+ })
11685
+ );
11686
+ return;
11687
+ }
11688
+ outputLine("");
11689
+ outputLine(" okx-auth Binary Status");
11690
+ outputLine(" " + "\u2500".repeat(40));
11691
+ outputLine(` Binary path : ${local.binaryPath}`);
11692
+ outputLine(` Installed : ${local.exists ? "yes" : "no"}`);
11693
+ outputLine(` Platform : ${local.platform ?? "(unsupported)"}`);
11694
+ if (local.exists) {
11695
+ outputLine(` File size : ${formatBytes(local.fileSize)}`);
11696
+ outputLine(` SHA-256 : ${local.sha256 ?? "(unknown)"}`);
11697
+ outputLine(` CDN check : ${checksumMatchLabel(checksumMatch)}`);
11698
+ if (cdnChecksum) {
11699
+ outputLine(` CDN source : ${cdnChecksum.source}`);
11700
+ }
11701
+ }
11702
+ outputLine("");
11703
+ }
11704
+ async function cmdAuthInstall(json) {
11705
+ const messages2 = [];
11706
+ const onProgress = (msg) => {
11707
+ if (!json) {
11708
+ outputLine(` ${msg}`);
11709
+ }
11710
+ messages2.push(msg);
11711
+ };
11712
+ if (!json) {
11713
+ outputLine("");
11714
+ outputLine(" Installing okx-auth...");
11715
+ }
11716
+ const result = await installAuthBinary(void 0, void 0, onProgress);
11717
+ if (json) {
11718
+ outputLine(JSON.stringify({ status: result.status, source: result.source ?? null, error: result.error ?? null, messages: messages2 }));
11719
+ if (result.status === "failed") {
11720
+ process.exitCode = 1;
11721
+ }
11722
+ return;
11723
+ }
11724
+ if (result.status === "installed" || result.status === "up-to-date") {
11725
+ const local = getAuthStatus();
11726
+ if (local.sha256) updateAuthBinaryCache(local.sha256);
11727
+ }
11728
+ if (result.status === "installed") {
11729
+ outputLine(` \u2713 okx-auth installed successfully (${result.source ?? ""})`);
11730
+ } else if (result.status === "up-to-date") {
11731
+ outputLine(" \u2713 okx-auth is already up to date");
11732
+ } else {
11733
+ errorLine(` \u2717 Installation failed: ${result.error ?? "unknown error"}`);
11734
+ errorLine(" Hint: check network connectivity or try again later");
11735
+ process.exitCode = 1;
11736
+ }
11737
+ outputLine("");
11738
+ }
11739
+ async function cmdAuthRemove(force, json) {
11740
+ const local = getAuthStatus(void 0, { skipHash: true });
11741
+ if (!local.exists) {
11742
+ if (json) {
11743
+ outputLine(JSON.stringify({ status: "not-installed" }));
11744
+ } else {
11745
+ outputLine(" okx-auth is not installed.");
11746
+ }
11747
+ return;
11748
+ }
11749
+ if (!await confirmRemoval(force, local.binaryPath)) return;
11750
+ let result;
11751
+ try {
11752
+ result = removeAuthBinary();
11753
+ } catch (err) {
11754
+ const msg = err instanceof Error ? err.message : String(err);
11755
+ if (json) {
11756
+ outputLine(JSON.stringify({ status: "failed", error: msg }));
11757
+ } else {
11758
+ errorLine(` \u2717 Failed to remove: ${msg}`);
11759
+ }
11760
+ process.exitCode = 1;
11761
+ return;
11762
+ }
11763
+ if (json) {
11764
+ outputLine(JSON.stringify({ status: result.status, path: local.binaryPath }));
11765
+ return;
11766
+ }
11767
+ if (result.status === "removed") {
11768
+ clearAuthBinaryCache();
11769
+ outputLine(` \u2713 Removed: ${local.binaryPath}`);
11770
+ } else {
11771
+ outputLine(" okx-auth is not installed.");
11772
+ }
11773
+ }
11774
+ async function confirmRemoval(force, binaryPath) {
11775
+ if (force) return true;
11776
+ if (!process.stdin.isTTY) {
11777
+ errorLine(" Error: stdin is not a TTY. Use --force to skip confirmation.");
11778
+ process.exitCode = 1;
11779
+ return false;
11780
+ }
11781
+ const confirmed = await askConfirmation(
11782
+ ` Remove okx-auth at ${binaryPath}? [y/N] `
11783
+ );
11784
+ if (!confirmed) {
11785
+ outputLine(" Cancelled.");
11786
+ return false;
11787
+ }
11788
+ return true;
11789
+ }
11790
+ function askConfirmation(prompt2) {
11791
+ return new Promise((resolve3) => {
11792
+ const rl = readline.createInterface({
11793
+ input: process.stdin,
11794
+ output: process.stdout
11795
+ });
11796
+ rl.question(prompt2, (answer) => {
11797
+ rl.close();
11798
+ resolve3(answer.trim().toLowerCase() === "y");
11799
+ });
11800
+ });
11801
+ }
11802
+ async function handleAuthCommand(action, _rest, v) {
11803
+ const site = v.site;
11804
+ const json = v.json;
11805
+ const manual = v.manual;
11806
+ const force = v.force;
11807
+ if (["login", "logout", "status"].includes(action)) {
11808
+ await ensureAuthBinaryLatest((msg) => errorLine(` ${msg}`));
11809
+ }
11810
+ switch (action) {
11811
+ case "login":
11812
+ return cmdAuthLogin({ site, manual });
11813
+ case "logout":
11814
+ return cmdAuthLogout();
11815
+ case "status":
11816
+ return cmdAuthStatus({ json });
11817
+ case "install":
11818
+ return cmdAuthInstall(json ?? false);
11819
+ case "install-status":
11820
+ return cmdAuthInstallStatus(json ?? false);
11821
+ case "remove":
11822
+ return cmdAuthRemove(force ?? false, json ?? false);
11823
+ default:
11824
+ errorLine(`Unknown auth command: ${action}`);
11825
+ errorLine("Available: login, logout, status, install, install-status, remove");
11826
+ process.exitCode = 1;
11827
+ }
11828
+ }
11829
+
11830
+ // src/commands/diagnose.ts
11831
+ import dns from "dns/promises";
11832
+ import net from "net";
11833
+ import os5 from "os";
11834
+ import tls from "tls";
11835
+
11176
11836
  // src/commands/diagnose-utils.ts
11837
+ import fs4 from "fs";
11838
+ import { createRequire } from "module";
11177
11839
  var _require = createRequire(import.meta.url);
11178
11840
  function readCliVersion() {
11179
11841
  for (const rel of ["../package.json", "../../package.json"]) {
@@ -11259,7 +11921,7 @@ function sanitize2(value) {
11259
11921
  import fs5 from "fs";
11260
11922
  import path4 from "path";
11261
11923
  import os4 from "os";
11262
- import { spawnSync, spawn } from "child_process";
11924
+ import { spawnSync, spawn as spawn3 } from "child_process";
11263
11925
  import { createRequire as createRequire2 } from "module";
11264
11926
  import { fileURLToPath } from "url";
11265
11927
  var _require2 = createRequire2(import.meta.url);
@@ -11593,7 +12255,7 @@ async function checkStdioHandshake(entryPath, report) {
11593
12255
  clearTimeout(timer);
11594
12256
  resolve3(passed);
11595
12257
  };
11596
- const child = spawn(process.execPath, [entryPath], {
12258
+ const child = spawn3(process.execPath, [entryPath], {
11597
12259
  stdio: ["pipe", "pipe", "pipe"],
11598
12260
  env: { ...process.env }
11599
12261
  });
@@ -11712,7 +12374,7 @@ async function cmdDiagnoseMcp(options = {}) {
11712
12374
 
11713
12375
  // src/commands/diagnose.ts
11714
12376
  var CLI_VERSION = readCliVersion();
11715
- var GIT_HASH = true ? "7acf49fb" : "dev";
12377
+ var GIT_HASH = true ? "3331141" : "dev";
11716
12378
  function maskKey2(key) {
11717
12379
  if (!key) return "(not set)";
11718
12380
  if (key.length <= 8) return "****";
@@ -12047,10 +12709,10 @@ async function runCliChecks(config, profile, outputPath) {
12047
12709
  }
12048
12710
 
12049
12711
  // src/unknown-command.ts
12050
- function unknownSubcommand(module, action, knownActions) {
12712
+ function unknownSubcommand(module, action, knownActions, knownPaths = []) {
12051
12713
  const actionStr = action ?? "(missing)";
12052
12714
  errorLine(`Unknown command: okx ${module} ${actionStr}`);
12053
- const hint = suggestSubcommand(action, knownActions);
12715
+ const hint = suggestSubcommand(action, knownActions, knownPaths);
12054
12716
  if (hint) {
12055
12717
  errorLine(` Did you mean: okx ${module} ${hint} ?`);
12056
12718
  }
@@ -12060,12 +12722,12 @@ function unknownSubcommand(module, action, knownActions) {
12060
12722
  errorLine(` Run 'okx ${module} --help' for full usage.`);
12061
12723
  process.exitCode = 1;
12062
12724
  }
12063
- function suggestSubcommand(action, knownActions) {
12725
+ function suggestSubcommand(action, knownActions, knownPaths = []) {
12064
12726
  if (!action || !action.includes("-")) return void 0;
12065
12727
  const parts = action.split("-");
12066
12728
  if (parts.length !== 2) return void 0;
12067
12729
  const [a, b] = parts;
12068
- if (knownActions.includes(b)) {
12730
+ if (knownActions.includes(b) && knownPaths.includes(`${b} ${a}`)) {
12069
12731
  return `${b} ${a}`;
12070
12732
  }
12071
12733
  return void 0;
@@ -12073,24 +12735,24 @@ function suggestSubcommand(action, knownActions) {
12073
12735
 
12074
12736
  // src/commands/upgrade.ts
12075
12737
  import { spawnSync as spawnSync2 } from "child_process";
12076
- import { readFileSync as readFileSync8, writeFileSync as writeFileSync7, mkdirSync as mkdirSync9 } from "fs";
12077
- import { dirname as dirname7, join as join10 } from "path";
12078
- import { homedir as homedir8 } from "os";
12738
+ import { readFileSync as readFileSync9, writeFileSync as writeFileSync8, mkdirSync as mkdirSync11 } from "fs";
12739
+ import { dirname as dirname8, join as join13 } from "path";
12740
+ import { homedir as homedir11 } from "os";
12079
12741
  var PACKAGES = ["@okx_ai/okx-trade-mcp", "@okx_ai/okx-trade-cli"];
12080
- var CACHE_FILE2 = join10(homedir8(), ".okx", "last_check");
12742
+ var CACHE_FILE2 = join13(homedir11(), ".okx", "last_check");
12081
12743
  var THROTTLE_MS = 12 * 60 * 60 * 1e3;
12082
- var NPM_BIN = join10(dirname7(process.execPath), process.platform === "win32" ? "npm.cmd" : "npm");
12744
+ var NPM_BIN = join13(dirname8(process.execPath), process.platform === "win32" ? "npm.cmd" : "npm");
12083
12745
  function readLastCheck() {
12084
12746
  try {
12085
- return parseInt(readFileSync8(CACHE_FILE2, "utf-8").trim(), 10) || 0;
12747
+ return parseInt(readFileSync9(CACHE_FILE2, "utf-8").trim(), 10) || 0;
12086
12748
  } catch {
12087
12749
  return 0;
12088
12750
  }
12089
12751
  }
12090
12752
  function writeLastCheck() {
12091
12753
  try {
12092
- mkdirSync9(join10(homedir8(), ".okx"), { recursive: true });
12093
- writeFileSync7(CACHE_FILE2, String(Math.floor(Date.now() / 1e3)), "utf-8");
12754
+ mkdirSync11(join13(homedir11(), ".okx"), { recursive: true });
12755
+ writeFileSync8(CACHE_FILE2, String(Math.floor(Date.now() / 1e3)), "utf-8");
12094
12756
  } catch {
12095
12757
  }
12096
12758
  }
@@ -13555,22 +14217,18 @@ async function cmdNewsSentimentRank(run, opts) {
13555
14217
  }
13556
14218
 
13557
14219
  // src/config/loader.ts
13558
- function loadProfileConfig(opts) {
13559
- return loadConfig(
13560
- {
13561
- profile: opts.profile,
13562
- modules: opts.modules,
13563
- readOnly: opts.readOnly ?? false,
13564
- demo: opts.demo,
13565
- live: opts.live,
13566
- site: opts.site,
13567
- userAgent: opts.userAgent,
13568
- sourceTag: opts.sourceTag,
13569
- skill: opts.skill,
13570
- verbose: opts.verbose
13571
- },
13572
- { entryPrefix: opts.entryPrefix, readEnv: opts.readEnv }
13573
- );
14220
+ async function loadProfileConfig(opts) {
14221
+ return loadConfig({
14222
+ profile: opts.profile,
14223
+ modules: opts.modules,
14224
+ readOnly: opts.readOnly ?? false,
14225
+ demo: opts.demo,
14226
+ live: opts.live,
14227
+ site: opts.site,
14228
+ userAgent: opts.userAgent,
14229
+ sourceTag: opts.sourceTag,
14230
+ verbose: opts.verbose
14231
+ });
13574
14232
  }
13575
14233
 
13576
14234
  // src/help.ts
@@ -13579,13 +14237,12 @@ var HELP_TREE = generateHelpTree();
13579
14237
  function printGlobalHelp() {
13580
14238
  const lines = [
13581
14239
  "",
13582
- `Usage: okx [--profile <name>] [--demo | --live] [--skill <token>] [--json] <module> <action> [args...]`,
14240
+ `Usage: okx [--profile <name>] [--demo | --live] [--json] <module> <action> [args...]`,
13583
14241
  "",
13584
14242
  "Global Options:",
13585
14243
  ` --profile <name> Use a named profile from ${configFilePath()}`,
13586
14244
  " --demo Use simulated trading (demo) mode",
13587
14245
  " --live Force live trading mode (overrides profile demo=true; mutually exclusive with --demo)",
13588
- " --skill <token> OKX skill token for order tagging (from SKILL.md)",
13589
14246
  " --json Output raw JSON",
13590
14247
  " --env With --json, wrap output as {env, profile, data}",
13591
14248
  " --verbose Show detailed network request/response info (stderr)",
@@ -13718,7 +14375,6 @@ import { parseArgs } from "util";
13718
14375
  var CLI_OPTIONS = {
13719
14376
  profile: { type: "string" },
13720
14377
  demo: { type: "boolean", default: false },
13721
- skill: { type: "string" },
13722
14378
  json: { type: "boolean", default: false },
13723
14379
  env: { type: "boolean", default: false },
13724
14380
  help: { type: "boolean", default: false },
@@ -13898,6 +14554,9 @@ var CLI_OPTIONS = {
13898
14554
  dir: { type: "string" },
13899
14555
  page: { type: "string" },
13900
14556
  format: { type: "string" },
14557
+ // auth
14558
+ site: { type: "string" },
14559
+ manual: { type: "boolean", default: false },
13901
14560
  // event contract
13902
14561
  underlying: { type: "string" },
13903
14562
  seriesId: { type: "string" },
@@ -17121,14 +17780,14 @@ async function cmdDcdQuoteAndBuy(run, opts) {
17121
17780
  }
17122
17781
 
17123
17782
  // src/commands/skill.ts
17124
- import { tmpdir, homedir as homedir10 } from "os";
17125
- import { join as join12, dirname as dirname8 } from "path";
17126
- import { mkdirSync as mkdirSync10, rmSync, existsSync as existsSync8, copyFileSync as copyFileSync2 } from "fs";
17783
+ import { tmpdir, homedir as homedir13 } from "os";
17784
+ import { join as join15, dirname as dirname9 } from "path";
17785
+ import { mkdirSync as mkdirSync12, rmSync, existsSync as existsSync10, copyFileSync as copyFileSync2 } from "fs";
17127
17786
  import { execFileSync as execFileSync2 } from "child_process";
17128
17787
  import { randomUUID as randomUUID2 } from "crypto";
17129
17788
  function resolveNpx() {
17130
- const sibling = join12(dirname8(process.execPath), "npx");
17131
- if (existsSync8(sibling)) return sibling;
17789
+ const sibling = join15(dirname9(process.execPath), "npx");
17790
+ if (existsSync10(sibling)) return sibling;
17132
17791
  return "npx";
17133
17792
  }
17134
17793
  var THIRD_PARTY_INSTALL_NOTICE = "Note: This skill was created by a third-party developer, not by OKX. Review SKILL.md before use.";
@@ -17181,13 +17840,13 @@ async function cmdSkillCategories(run, json) {
17181
17840
  outputLine("");
17182
17841
  }
17183
17842
  async function cmdSkillAdd(name, config, json) {
17184
- const tmpBase = join12(tmpdir(), `okx-skill-${randomUUID2()}`);
17185
- mkdirSync10(tmpBase, { recursive: true });
17843
+ const tmpBase = join15(tmpdir(), `okx-skill-${randomUUID2()}`);
17844
+ mkdirSync12(tmpBase, { recursive: true });
17186
17845
  try {
17187
17846
  outputLine(`Downloading ${name}...`);
17188
17847
  const client = new OkxRestClient(config);
17189
17848
  const zipPath = await downloadSkillZip(client, name, tmpBase);
17190
- const contentDir = await extractSkillZip(zipPath, join12(tmpBase, "content"));
17849
+ const contentDir = await extractSkillZip(zipPath, join15(tmpBase, "content"));
17191
17850
  const meta = readMetaJson(contentDir);
17192
17851
  validateSkillMdExists(contentDir);
17193
17852
  outputLine("Installing to detected agents...");
@@ -17197,7 +17856,7 @@ async function cmdSkillAdd(name, config, json) {
17197
17856
  timeout: 6e4
17198
17857
  });
17199
17858
  } catch (e) {
17200
- const savedZip = join12(process.cwd(), `${name}.zip`);
17859
+ const savedZip = join15(process.cwd(), `${name}.zip`);
17201
17860
  try {
17202
17861
  copyFileSync2(zipPath, savedZip);
17203
17862
  } catch {
@@ -17236,7 +17895,7 @@ function cmdSkillRemove(name, json) {
17236
17895
  timeout: 6e4
17237
17896
  });
17238
17897
  } catch {
17239
- const agentsPath = join12(homedir10(), ".agents", "skills", name);
17898
+ const agentsPath = join15(homedir13(), ".agents", "skills", name);
17240
17899
  try {
17241
17900
  rmSync(agentsPath, { recursive: true, force: true });
17242
17901
  } catch {
@@ -17310,14 +17969,14 @@ function printSkillInstallResult(meta, json) {
17310
17969
  }
17311
17970
 
17312
17971
  // src/commands/pilot.ts
17313
- import readline from "readline";
17314
- function resolveChecksumMatch(local, cdnChecksum, cdnError) {
17972
+ import readline2 from "readline";
17973
+ function resolveChecksumMatch2(local, cdnChecksum, cdnError) {
17315
17974
  if (!local.exists) return "not-installed";
17316
17975
  if (cdnError || !cdnChecksum) return "unavailable";
17317
17976
  if (cdnChecksum.sha256 === local.sha256) return "match";
17318
17977
  return "mismatch";
17319
17978
  }
17320
- function checksumMatchLabel(match) {
17979
+ function checksumMatchLabel2(match) {
17321
17980
  if (match === "match") return "\u2713 match";
17322
17981
  if (match === "mismatch") return "\u2717 mismatch (update available)";
17323
17982
  return "CDN unreachable";
@@ -17330,9 +17989,9 @@ function formatStatusText(local, checksumMatch, cdnChecksum, runtimeMode) {
17330
17989
  outputLine(` Installed : ${local.exists ? "yes" : "no"}`);
17331
17990
  outputLine(` Platform : ${local.platform ?? "(unsupported)"}`);
17332
17991
  if (local.exists) {
17333
- outputLine(` File size : ${formatBytes(local.fileSize)}`);
17992
+ outputLine(` File size : ${formatBytes2(local.fileSize)}`);
17334
17993
  outputLine(` SHA-256 : ${local.sha256 ?? "(unknown)"}`);
17335
- outputLine(` CDN check : ${checksumMatchLabel(checksumMatch)}`);
17994
+ outputLine(` CDN check : ${checksumMatchLabel2(checksumMatch)}`);
17336
17995
  if (cdnChecksum) {
17337
17996
  outputLine(` CDN source : ${cdnChecksum.source}`);
17338
17997
  }
@@ -17359,7 +18018,7 @@ async function cmdPilotStatus(json, binaryPath) {
17359
18018
  cdnError = err instanceof Error ? err.message : String(err);
17360
18019
  }
17361
18020
  }
17362
- const checksumMatch = resolveChecksumMatch(local, cdnChecksum, cdnError);
18021
+ const checksumMatch = resolveChecksumMatch2(local, cdnChecksum, cdnError);
17363
18022
  if (json) {
17364
18023
  outputLine(
17365
18024
  JSON.stringify({
@@ -17425,7 +18084,7 @@ async function cmdPilotRemove(force, json, binaryPath) {
17425
18084
  process.exitCode = 1;
17426
18085
  return;
17427
18086
  }
17428
- const confirmed = await askConfirmation(
18087
+ const confirmed = await askConfirmation2(
17429
18088
  ` Remove Pilot at ${local.binaryPath}? [y/N] `
17430
18089
  );
17431
18090
  if (!confirmed) {
@@ -17444,14 +18103,14 @@ async function cmdPilotRemove(force, json, binaryPath) {
17444
18103
  outputLine(" Pilot is not installed.");
17445
18104
  }
17446
18105
  }
17447
- function formatBytes(bytes) {
18106
+ function formatBytes2(bytes) {
17448
18107
  if (bytes < 1024) return `${bytes} B`;
17449
18108
  if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
17450
18109
  return `${(bytes / (1024 * 1024)).toFixed(2)} MB`;
17451
18110
  }
17452
- function askConfirmation(prompt2) {
18111
+ function askConfirmation2(prompt2) {
17453
18112
  return new Promise((resolve3) => {
17454
- const rl = readline.createInterface({
18113
+ const rl = readline2.createInterface({
17455
18114
  input: process.stdin,
17456
18115
  output: process.stdout
17457
18116
  });
@@ -17920,7 +18579,7 @@ async function cmdEventCancel(run, opts) {
17920
18579
  // src/index.ts
17921
18580
  var _require3 = createRequire3(import.meta.url);
17922
18581
  var CLI_VERSION2 = _require3("../package.json").version;
17923
- var GIT_HASH2 = true ? "7acf49fb" : "dev";
18582
+ var GIT_HASH2 = true ? "3331141" : "dev";
17924
18583
  function handlePilotCommand(action, json, force, binaryPath) {
17925
18584
  if (action === "status") return cmdPilotStatus(json, binaryPath);
17926
18585
  if (action === "install") return cmdPilotInstall(json, binaryPath);
@@ -18250,7 +18909,7 @@ function handleSpotCommand(run, action, rest, v, json) {
18250
18909
  "algo",
18251
18910
  "batch",
18252
18911
  "leverage"
18253
- ]);
18912
+ ], ["algo place", "algo cancel", "algo amend", "algo trail", "algo orders"]);
18254
18913
  }
18255
18914
  function handleSwapAlgoCommand(run, subAction, v, json) {
18256
18915
  if (subAction === "trail")
@@ -18395,7 +19054,7 @@ function handleSwapCommand(run, action, rest, v, json) {
18395
19054
  "leverage",
18396
19055
  "algo",
18397
19056
  "batch"
18398
- ]);
19057
+ ], ["algo place", "algo cancel", "algo amend", "algo trail", "algo orders"]);
18399
19058
  }
18400
19059
  function handleOptionAlgoCommand(run, subAction, v, json) {
18401
19060
  if (subAction === "place")
@@ -18497,7 +19156,7 @@ function handleOptionCommand(run, action, rest, v, json) {
18497
19156
  "amend",
18498
19157
  "batch-cancel",
18499
19158
  "algo"
18500
- ]);
19159
+ ], ["algo place", "algo cancel", "algo amend", "algo orders"]);
18501
19160
  }
18502
19161
  function handleFuturesAlgoCommand(run, subAction, v, json) {
18503
19162
  if (subAction === "trail")
@@ -18642,7 +19301,7 @@ function handleFuturesCommand(run, action, rest, v, json) {
18642
19301
  "leverage",
18643
19302
  "batch",
18644
19303
  "algo"
18645
- ]);
19304
+ ], ["algo place", "algo cancel", "algo amend", "algo trail", "algo orders"]);
18646
19305
  }
18647
19306
  function handleBotGridCommand(run, v, rest, json) {
18648
19307
  const subAction = rest[0];
@@ -18963,13 +19622,13 @@ function handleNewsCommand(run, action, rest, v, json) {
18963
19622
  const period = v.period;
18964
19623
  const points = v.points !== void 0 ? Number(v.points) : 24;
18965
19624
  const sortBy = v["sort-by"];
18966
- const platform2 = v.platform;
18967
- const searchOpts = { coins: v.coins, importance: v.importance, platform: platform2, sentiment: v.sentiment, sortBy, begin, end, language, detailLvl, limit, after, json };
18968
- const listOpts = { coins: v.coins, importance: v.importance, platform: platform2, begin, end, language, detailLvl, limit, after, json };
19625
+ const platform3 = v.platform;
19626
+ const searchOpts = { coins: v.coins, importance: v.importance, platform: platform3, sentiment: v.sentiment, sortBy, begin, end, language, detailLvl, limit, after, json };
19627
+ const listOpts = { coins: v.coins, importance: v.importance, platform: platform3, begin, end, language, detailLvl, limit, after, json };
18969
19628
  const dispatch = {
18970
19629
  latest: () => cmdNewsLatest(run, listOpts),
18971
- important: () => cmdNewsImportant(run, { coins: v.coins, platform: platform2, begin, end, language, detailLvl, limit, json }),
18972
- "by-coin": () => cmdNewsByCoin(run, v.coins ?? rest[0], { importance: v.importance, platform: platform2, begin, end, language, detailLvl, limit, json }),
19630
+ important: () => cmdNewsImportant(run, { coins: v.coins, platform: platform3, begin, end, language, detailLvl, limit, json }),
19631
+ "by-coin": () => cmdNewsByCoin(run, v.coins ?? rest[0], { importance: v.importance, platform: platform3, begin, end, language, detailLvl, limit, json }),
18973
19632
  search: () => cmdNewsSearch(run, v.keyword ?? rest[0], searchOpts),
18974
19633
  detail: () => cmdNewsDetail(run, rest[0], { language, json }),
18975
19634
  platforms: () => cmdNewsPlatforms(run, { json }),
@@ -19110,7 +19769,7 @@ function wrapRunnerWithLogger(baseRunner, logger, verbose = false) {
19110
19769
  async function runDiagnose(v) {
19111
19770
  let config;
19112
19771
  try {
19113
- config = loadProfileConfig({ profile: v.profile, demo: v.demo, live: v.live, verbose: v.verbose, userAgent: `okx-trade-cli/${CLI_VERSION2}`, sourceTag: "CLI", skill: v.skill, entryPrefix: "CLI" });
19772
+ config = await loadProfileConfig({ profile: v.profile, demo: v.demo, live: v.live, verbose: v.verbose, userAgent: `okx-trade-cli/${CLI_VERSION2}`, sourceTag: "CLI" });
19114
19773
  } catch {
19115
19774
  }
19116
19775
  return cmdDiagnose(config, v.profile ?? "default", { mcp: v.mcp, cli: v.cli, all: v.all, output: v.output });
@@ -19133,6 +19792,7 @@ function routeManagementCommand(module, action, rest, json, v) {
19133
19792
  handleSetupCommand(v);
19134
19793
  return true;
19135
19794
  }
19795
+ if (module === "auth") return handleAuthCommand(action, rest, v);
19136
19796
  if (module === "upgrade") return cmdUpgrade(CLI_VERSION2, { beta: v.beta, check: v.check, force: v.force }, json);
19137
19797
  if (module === "pilot") {
19138
19798
  const r = handlePilotCommand(action, json, v.force ?? false);
@@ -19165,7 +19825,7 @@ async function main() {
19165
19825
  const json = v.json ?? false;
19166
19826
  const mgmt = routeManagementCommand(module, action, rest, json, v);
19167
19827
  if (mgmt !== void 0) return mgmt === true ? void 0 : mgmt;
19168
- const config = loadProfileConfig({ profile: v.profile, demo: v.demo, live: v.live, verbose: v.verbose, userAgent: `okx-trade-cli/${CLI_VERSION2}`, sourceTag: "CLI", skill: v.skill, entryPrefix: "CLI" });
19828
+ const config = await loadProfileConfig({ profile: v.profile, demo: v.demo, live: v.live, verbose: v.verbose, userAgent: `okx-trade-cli/${CLI_VERSION2}`, sourceTag: "CLI" });
19169
19829
  setEnvContext({ demo: config.demo, profile: v.profile ?? "default" });
19170
19830
  setJsonEnvEnabled(v.env ?? false);
19171
19831
  const client = new OkxRestClient(config);