@okx_ai/okx-trade-cli 1.3.2-beta.3 → 1.3.2-beta.4

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
  }
@@ -1926,6 +2076,23 @@ function privateRateLimit(key, rps = 10) {
1926
2076
  refillPerSecond: rps
1927
2077
  };
1928
2078
  }
2079
+ var CURSOR_PROPS = {
2080
+ after: { type: "string", description: "Cursor: return older records" },
2081
+ before: { type: "string", description: "Cursor: return newer records" }
2082
+ };
2083
+ var TIME_RANGE_PROPS = {
2084
+ begin: { type: "string", description: "Start time (ms)" },
2085
+ end: { type: "string", description: "End time (ms)" }
2086
+ };
2087
+ function readPaginationParams(args, readStr, readNum) {
2088
+ return {
2089
+ after: readStr(args, "after"),
2090
+ before: readStr(args, "before"),
2091
+ begin: readStr(args, "begin"),
2092
+ end: readStr(args, "end"),
2093
+ limit: readNum(args, "limit")
2094
+ };
2095
+ }
1929
2096
  function assertNotDemo(config, endpoint) {
1930
2097
  if (config.demo) {
1931
2098
  throw new ConfigError(
@@ -2197,7 +2364,7 @@ var OKX_SITES = {
2197
2364
  },
2198
2365
  us: {
2199
2366
  label: "US",
2200
- apiBaseUrl: "https://app.okx.com",
2367
+ apiBaseUrl: "https://us.okx.com",
2201
2368
  webUrl: "https://app.okx.com"
2202
2369
  }
2203
2370
  };
@@ -3744,7 +3911,7 @@ function safeWriteFile(targetDir, fileName, data) {
3744
3911
  throw new Error(`Invalid file name: "${fileName}"`);
3745
3912
  }
3746
3913
  const resolvedDir = resolve(targetDir);
3747
- const filePath = join3(resolvedDir, safeName);
3914
+ const filePath = join4(resolvedDir, safeName);
3748
3915
  const resolvedPath = resolve(filePath);
3749
3916
  if (!resolvedPath.startsWith(resolvedDir + sep)) {
3750
3917
  throw new Error(`Path traversal detected: "${fileName}" resolves outside target directory`);
@@ -3872,7 +4039,7 @@ async function extractSkillZip(zipPath, targetDir, limits) {
3872
4039
  });
3873
4040
  }
3874
4041
  function readMetaJson(contentDir) {
3875
- const metaPath = join4(contentDir, "_meta.json");
4042
+ const metaPath = join5(contentDir, "_meta.json");
3876
4043
  if (!existsSync(metaPath)) {
3877
4044
  throw new Error(`_meta.json not found in ${contentDir}. Invalid skill package.`);
3878
4045
  }
@@ -3898,12 +4065,12 @@ function readMetaJson(contentDir) {
3898
4065
  };
3899
4066
  }
3900
4067
  function validateSkillMdExists(contentDir) {
3901
- const skillMdPath = join4(contentDir, "SKILL.md");
4068
+ const skillMdPath = join5(contentDir, "SKILL.md");
3902
4069
  if (!existsSync(skillMdPath)) {
3903
4070
  throw new Error(`SKILL.md not found in ${contentDir}. Invalid skill package.`);
3904
4071
  }
3905
4072
  }
3906
- var DEFAULT_REGISTRY_PATH = join5(homedir3(), ".okx", "skills", "registry.json");
4073
+ var DEFAULT_REGISTRY_PATH = join6(homedir4(), ".okx", "skills", "registry.json");
3907
4074
  function readRegistry(registryPath = DEFAULT_REGISTRY_PATH) {
3908
4075
  if (!existsSync2(registryPath)) {
3909
4076
  return { version: 1, skills: {} };
@@ -6341,37 +6508,45 @@ function registerEventContractTools() {
6341
6508
  {
6342
6509
  name: "event_get_orders",
6343
6510
  module: "event",
6344
- description: "Query event contract orders. state=live for open orders; omit for history. outcome pre-translated (YES/NO/UP/DOWN).",
6511
+ description: "Query event contract orders (open, 7d history, or 3-month archive). outcome pre-translated (YES/NO/UP/DOWN). Do NOT use for trade executions \u2014 use event_get_fills for fill records and settlement outcomes.",
6345
6512
  isWrite: false,
6346
6513
  inputSchema: {
6347
6514
  type: "object",
6348
6515
  properties: {
6349
- instId: {
6516
+ status: {
6350
6517
  type: "string",
6351
- description: "Event contract instrument ID"
6518
+ enum: ["open", "history", "archive"],
6519
+ description: "open=active, history=7d (default), archive=3mo"
6352
6520
  },
6353
- state: {
6521
+ instId: {
6354
6522
  type: "string",
6355
- description: "live=pending orders; omit for history"
6523
+ description: "Event contract instrument ID"
6356
6524
  },
6357
- limit: {
6358
- type: "number",
6359
- description: "Max results (default 20)"
6360
- }
6525
+ ordType: { type: "string", description: "Order type filter" },
6526
+ state: { type: "string", description: "canceled|filled (only for history/archive)" },
6527
+ ...CURSOR_PROPS,
6528
+ ...TIME_RANGE_PROPS,
6529
+ limit: { type: "number", description: "Max results (default 100)" }
6361
6530
  }
6362
6531
  },
6363
6532
  handler: async (rawArgs, context) => {
6364
6533
  const args = asRecord(rawArgs);
6365
- const state = readString(args, "state");
6366
- const isPending = state === "live";
6367
- const endpoint = isPending ? "/api/v5/trade/orders-pending" : "/api/v5/trade/orders-history";
6534
+ const status = readString(args, "status") ?? "history";
6535
+ const endpointMap = {
6536
+ open: "/api/v5/trade/orders-pending",
6537
+ archive: "/api/v5/trade/orders-history-archive"
6538
+ };
6539
+ const endpoint = endpointMap[status] ?? "/api/v5/trade/orders-history";
6540
+ const params = compactObject({
6541
+ instType: "EVENTS",
6542
+ instId: readString(args, "instId"),
6543
+ ordType: readString(args, "ordType"),
6544
+ state: readString(args, "state"),
6545
+ ...readPaginationParams(args, readString, readNumber)
6546
+ });
6368
6547
  const response = await context.client.privateGet(
6369
6548
  endpoint,
6370
- compactObject({
6371
- instType: "EVENTS",
6372
- instId: readString(args, "instId"),
6373
- limit: readNumber(args, "limit")
6374
- }),
6549
+ params,
6375
6550
  privateRateLimit("event_get_orders", 20)
6376
6551
  );
6377
6552
  const base = normalizeResponse(response);
@@ -6385,41 +6560,51 @@ function registerEventContractTools() {
6385
6560
  stateLabel: mapOrderState(String(item["state"] ?? ""))
6386
6561
  };
6387
6562
  }) : base["data"];
6388
- return { ...base, data };
6563
+ return { ...base, data, requestParams: params };
6389
6564
  }
6390
6565
  },
6391
6566
  {
6392
6567
  name: "event_get_fills",
6393
6568
  module: "event",
6394
- description: "Get event contract fill history. outcome pre-translated (YES/NO/UP/DOWN). Each record includes a 'type' field: 'fill' (subType 410, opening trade) or 'settlement' (subType 414 win / subType 415 loss, contract expiry payout). Settlement records include 'settlementResult' (win/loss) and 'pnl' fields \u2014 no separate market lookup needed to determine outcome.",
6569
+ description: "Get event contract fill history (trade executions and settlement payouts). archive=true for up to 3mo, false (default) for last 3d. outcome pre-translated (YES/NO/UP/DOWN). Each record includes a 'type' field: 'fill' (opening trade) or 'settlement' (expiry payout with settlementResult win/loss and pnl). Do NOT use for order status \u2014 use event_get_orders instead.",
6395
6570
  isWrite: false,
6396
6571
  inputSchema: {
6397
6572
  type: "object",
6398
6573
  properties: {
6574
+ archive: {
6575
+ type: "boolean",
6576
+ description: "true=up to 3mo, false=3d (default)"
6577
+ },
6399
6578
  instId: {
6400
6579
  type: "string",
6401
6580
  description: "Event contract instrument ID"
6402
6581
  },
6403
- limit: {
6404
- type: "number",
6405
- description: "Max results (default 20)"
6406
- }
6582
+ ordId: { type: "string", description: "Order ID filter" },
6583
+ ...CURSOR_PROPS,
6584
+ ...TIME_RANGE_PROPS,
6585
+ limit: { type: "number", description: "Max results (default 100 or 20 for archive)" }
6407
6586
  }
6408
6587
  },
6409
6588
  handler: async (rawArgs, context) => {
6410
6589
  const args = asRecord(rawArgs);
6590
+ const archive = readBoolean(args, "archive") ?? false;
6591
+ const path42 = archive ? "/api/v5/trade/fills-history" : "/api/v5/trade/fills";
6592
+ const paging = readPaginationParams(args, readString, readNumber);
6593
+ const params = compactObject({
6594
+ instType: "EVENTS",
6595
+ instId: readString(args, "instId"),
6596
+ ordId: readString(args, "ordId"),
6597
+ ...paging,
6598
+ limit: paging.limit ?? (archive ? 20 : void 0)
6599
+ });
6411
6600
  const response = await context.client.privateGet(
6412
- "/api/v5/trade/fills",
6413
- compactObject({
6414
- instType: "EVENTS",
6415
- instId: readString(args, "instId"),
6416
- limit: readNumber(args, "limit")
6417
- }),
6601
+ path42,
6602
+ params,
6418
6603
  privateRateLimit("event_get_fills", 20)
6419
6604
  );
6420
6605
  const base = normalizeResponse(response);
6421
6606
  const data = Array.isArray(base["data"]) ? base["data"].map(enrichFill) : base["data"];
6422
- return { ...base, data };
6607
+ return { ...base, data, requestParams: params };
6423
6608
  }
6424
6609
  },
6425
6610
  // -----------------------------------------------------------------------
@@ -6503,7 +6688,7 @@ function registerEventContractTools() {
6503
6688
  {
6504
6689
  name: "event_amend_order",
6505
6690
  module: "event",
6506
- description: "Amend a pending event contract order (change price or size). [CAUTION] Modifies a real order. Before amending, call event_get_orders(state=live) to obtain the ordId and confirm the order is still pending. Only limit/post_only orders can be amended.",
6691
+ description: "Amend a pending event contract order (change price or size). [CAUTION] Modifies a real order. Before amending, call event_get_orders(status=open) to obtain the ordId and confirm the order is still pending. Only limit/post_only orders can be amended.",
6507
6692
  isWrite: true,
6508
6693
  inputSchema: {
6509
6694
  type: "object",
@@ -6534,7 +6719,7 @@ function registerEventContractTools() {
6534
6719
  {
6535
6720
  name: "event_cancel_order",
6536
6721
  module: "event",
6537
- description: "Cancel a pending event contract order. [CAUTION] Cancels a real order. Before cancelling, call event_get_orders(state=live) to obtain the ordId and confirm the order is still pending. instId must be the full event contract instrument ID (e.g. BTC-ABOVE-DAILY-260224-1600-69700), NOT a spot trading pair.",
6722
+ description: "Cancel a pending event contract order. [CAUTION] Cancels a real order. Before cancelling, call event_get_orders(status=open) to obtain the ordId and confirm the order is still pending. instId must be the full event contract instrument ID (e.g. BTC-ABOVE-DAILY-260224-1600-69700), NOT a spot trading pair.",
6538
6723
  isWrite: true,
6539
6724
  inputSchema: {
6540
6725
  type: "object",
@@ -6582,27 +6767,27 @@ var PATH_SIGNAL_HISTORY = "/api/v5/journal/smartmoney/signal-history";
6582
6767
  var SIGNAL_POOL_FILTER_PROPS = {
6583
6768
  sortType: {
6584
6769
  type: "string",
6585
- description: "pnl or pnlRatio"
6770
+ description: "Pool ranking: pnl|pnlRatio (default pnl)"
6586
6771
  },
6587
6772
  period: {
6588
6773
  type: "string",
6589
- description: "3|7|30|90 days"
6774
+ description: "Win-rate window days: 3|7|30|90 (default 90). Not snapshot range."
6590
6775
  },
6591
6776
  pnl: {
6592
6777
  type: "string",
6593
- description: "PNL_ANY|PNL_TOP50|PNL_TOP20|PNL_TOP5"
6778
+ description: "Top N% by PnL: PNL_ANY|PNL_TOP50|PNL_TOP20|PNL_TOP5 (default PNL_ANY)"
6594
6779
  },
6595
6780
  winRatio: {
6596
6781
  type: "string",
6597
- description: "WR_ANY|WR_GE_50|WR_GE_80"
6782
+ description: "Min win-rate: WR_ANY|WR_GE_50|WR_GE_80 (default WR_ANY)"
6598
6783
  },
6599
6784
  maxRetreat: {
6600
6785
  type: "string",
6601
- description: "MR_ANY|MR_LE_20|MR_LE_50"
6786
+ description: "Max drawdown: MR_ANY|MR_LE_20|MR_LE_50 (default MR_ANY)"
6602
6787
  },
6603
6788
  asset: {
6604
6789
  type: "string",
6605
- description: "AUM_ANY|AUM_TOP50|AUM_TOP20|AUM_TOP5"
6790
+ description: "Top N% by AUM: AUM_ANY|AUM_TOP50|AUM_TOP20|AUM_TOP5 (default AUM_ANY)"
6606
6791
  }
6607
6792
  };
6608
6793
  var LEADERBOARD_POOL_FILTER_PROPS = {
@@ -6654,39 +6839,39 @@ function registerSmartmoneyTools() {
6654
6839
  {
6655
6840
  name: "smartmoney_get_overview",
6656
6841
  module: "smartmoney",
6657
- description: "Multi-currency smart money overview ranked by most-watched currencies. Pass ts=Date.now() for latest data, or dataVersion (yyyyMMddHHmm) from a prior call. For single-currency signal with entry prices and trend, use smartmoney_get_signal.",
6842
+ description: "Multi-currency smart money overview, ranked by tradersWithPosition DESC (most-watched first). Requires either ts (recommended, Date.now()) or dataVersion (yyyyMMddHHmm UTC) \u2014 at least one must be set; ts wins when both are sent. For single-currency signal with entry prices and trend, use smartmoney_get_signal.",
6658
6843
  isWrite: false,
6659
6844
  inputSchema: {
6660
6845
  type: "object",
6661
6846
  properties: {
6662
- dataVersion: {
6847
+ ts: {
6663
6848
  type: "string",
6664
- description: "yyyyMMddHHmm UTC (or use ts)"
6849
+ description: "Recommended. Timestamp ms \u2014 use Date.now() for latest."
6665
6850
  },
6666
- ts: {
6851
+ dataVersion: {
6667
6852
  type: "string",
6668
- description: "Timestamp ms (or use dataVersion)"
6853
+ description: "Alternative. yyyyMMddHHmm UTC for prior snapshot. If both sent, ts wins."
6669
6854
  },
6670
6855
  instType: {
6671
6856
  type: "string",
6672
- description: "SPOT|MARGIN|FUTURES|SWAP|OPTION"
6857
+ description: "SPOT|MARGIN|FUTURES|SWAP|OPTION (default SWAP)"
6673
6858
  },
6674
6859
  ...SIGNAL_POOL_FILTER_PROPS,
6675
6860
  lmtNum: {
6676
6861
  type: "string",
6677
- description: "Trader pool size 1-500"
6862
+ description: "Trader pool size 1-500 (default 100)"
6678
6863
  },
6679
6864
  instCcyList: {
6680
6865
  type: "string",
6681
- description: "Comma-separated e.g. BTC,ETH,SOL"
6866
+ description: "Comma-separated currency codes e.g. BTC,ETH,SOL (prefix-matched against instId)"
6682
6867
  },
6683
6868
  instCcy: {
6684
6869
  type: "string",
6685
- description: "Single currency e.g. BTC"
6870
+ description: "Single currency e.g. BTC; alias for instCcyList (instCcyList wins if both set)"
6686
6871
  },
6687
6872
  topInstruments: {
6688
6873
  type: "string",
6689
- description: "Top N instruments 1-100"
6874
+ description: "Top N instruments 1-100 (default 20)"
6690
6875
  }
6691
6876
  }
6692
6877
  },
@@ -6718,35 +6903,35 @@ function registerSmartmoneyTools() {
6718
6903
  {
6719
6904
  name: "smartmoney_get_signal",
6720
6905
  module: "smartmoney",
6721
- description: "Single-currency consensus signal: long/short ratio, entry prices, trend, capital flow. Requires instId or instCcy. Pass ts=Date.now() for latest data, or dataVersion from a prior call. For multi-currency overview, use smartmoney_get_overview. For timeline, use smartmoney_get_signal_history.",
6906
+ description: "Single-currency consensus signal: long/short ratio, entry prices, trend, capital flow. Requires either instId (e.g. BTC-USDT-SWAP, recommended) or instCcy (SPOT/SWAP only) \u2014 instId wins when both are sent. Requires either ts (recommended, Date.now()) or dataVersion (yyyyMMddHHmm UTC) \u2014 at least one must be set; ts wins when both are sent. For multi-currency overview, use smartmoney_get_overview. For timeline, use smartmoney_get_signal_history.",
6722
6907
  isWrite: false,
6723
6908
  inputSchema: {
6724
6909
  type: "object",
6725
6910
  properties: {
6726
6911
  instId: {
6727
6912
  type: "string",
6728
- description: "e.g. BTC-USDT-SWAP (or use instCcy)"
6913
+ description: "Recommended. e.g. BTC-USDT-SWAP"
6729
6914
  },
6730
6915
  instCcy: {
6731
6916
  type: "string",
6732
- description: "e.g. BTC, SPOT/SWAP only (or use instId)"
6917
+ description: "e.g. BTC (SPOT/SWAP only); instId takes precedence if both set"
6733
6918
  },
6734
- dataVersion: {
6919
+ ts: {
6735
6920
  type: "string",
6736
- description: "yyyyMMddHHmm UTC (or use ts)"
6921
+ description: "Recommended. Timestamp ms \u2014 use Date.now() for latest."
6737
6922
  },
6738
- ts: {
6923
+ dataVersion: {
6739
6924
  type: "string",
6740
- description: "Timestamp ms (or use dataVersion)"
6925
+ description: "Alternative. yyyyMMddHHmm UTC for prior snapshot. If both sent, ts wins."
6741
6926
  },
6742
6927
  ...SIGNAL_POOL_FILTER_PROPS,
6743
6928
  lmtNum: {
6744
6929
  type: "string",
6745
- description: "Trader pool size 1-500"
6930
+ description: "Trader pool size 1-500 (default 100)"
6746
6931
  },
6747
6932
  authorIds: {
6748
6933
  type: "string",
6749
- description: "Comma-separated user IDs e.g. 1001,1002"
6934
+ description: "Comma-separated user IDs e.g. 1001,1002 \u2014 restricts the trader pool to these IDs only (precise filter)"
6750
6935
  }
6751
6936
  }
6752
6937
  },
@@ -6782,7 +6967,7 @@ function registerSmartmoneyTools() {
6782
6967
  {
6783
6968
  name: "smartmoney_get_signal_history",
6784
6969
  module: "smartmoney",
6785
- description: "Signal history timeline sorted by ts DESC for trend analysis. Requires instId. Pass ts=Date.now() for latest data, or dataVersion from a prior call. For current snapshot, use smartmoney_get_signal.",
6970
+ description: "Signal history timeline sorted by ts DESC for trend analysis. Requires instId. Requires either ts (recommended, Date.now()) or dataVersion (yyyyMMddHHmm UTC) \u2014 at least one must be set; ts wins when both are sent. For current snapshot, use smartmoney_get_signal.",
6786
6971
  isWrite: false,
6787
6972
  inputSchema: {
6788
6973
  type: "object",
@@ -6791,13 +6976,13 @@ function registerSmartmoneyTools() {
6791
6976
  type: "string",
6792
6977
  description: "e.g. BTC-USDT-SWAP"
6793
6978
  },
6794
- dataVersion: {
6979
+ ts: {
6795
6980
  type: "string",
6796
- description: "yyyyMMddHHmm UTC (or use ts)"
6981
+ description: "Recommended. Timestamp ms \u2014 use Date.now() for latest."
6797
6982
  },
6798
- ts: {
6983
+ dataVersion: {
6799
6984
  type: "string",
6800
- description: "Timestamp ms (or use dataVersion)"
6985
+ description: "Alternative. yyyyMMddHHmm UTC for prior snapshot. If both sent, ts wins."
6801
6986
  },
6802
6987
  granularity: {
6803
6988
  type: "string",
@@ -10300,7 +10485,7 @@ function createToolRunner(client, config) {
10300
10485
  };
10301
10486
  }
10302
10487
  function configFilePath() {
10303
- return join6(homedir4(), ".okx", "config.toml");
10488
+ return join7(homedir5(), ".okx", "config.toml");
10304
10489
  }
10305
10490
  function readFullConfig() {
10306
10491
  const path42 = configFilePath();
@@ -10319,11 +10504,6 @@ Or re-run: okx config init`
10319
10504
  );
10320
10505
  }
10321
10506
  }
10322
- function readTomlProfile(profileName) {
10323
- const config = readFullConfig();
10324
- const name = profileName ?? config.default_profile ?? "default";
10325
- return config.profiles?.[name] ?? {};
10326
- }
10327
10507
  var CONFIG_HEADER = `# OKX Trade Kit Configuration
10328
10508
  # If editing manually, wrap values containing special chars in quotes:
10329
10509
  # passphrase = 'value' (if value contains # \\ ")
@@ -10372,18 +10552,24 @@ function parseModuleList(rawModules) {
10372
10552
  }
10373
10553
  return Array.from(deduped);
10374
10554
  }
10375
- function loadCredentials(toml) {
10555
+ async function loadCredentials(toml) {
10376
10556
  const apiKey = process.env.OKX_API_KEY?.trim() ?? toml.api_key;
10377
10557
  const secretKey = process.env.OKX_SECRET_KEY?.trim() ?? toml.secret_key;
10378
10558
  const passphrase = process.env.OKX_PASSPHRASE?.trim() ?? toml.passphrase;
10379
- const hasAuth = Boolean(apiKey && secretKey && passphrase);
10559
+ const hasApiKey = Boolean(apiKey && secretKey && passphrase);
10380
10560
  const partialAuth = Boolean(apiKey) || Boolean(secretKey) || Boolean(passphrase);
10381
- if (partialAuth && !hasAuth) {
10561
+ if (partialAuth && !hasApiKey) {
10382
10562
  throw new ConfigError(
10383
10563
  "Partial API credentials detected.",
10384
10564
  "Set OKX_API_KEY, OKX_SECRET_KEY and OKX_PASSPHRASE together (env vars or config.toml profile)."
10385
10565
  );
10386
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;
10387
10573
  return { apiKey, secretKey, passphrase, hasAuth };
10388
10574
  }
10389
10575
  function resolveSite(cliSite, tomlSite) {
@@ -10417,9 +10603,11 @@ function resolveDemo(cli, toml) {
10417
10603
  if (cli.demo === true) return true;
10418
10604
  return process.env.OKX_DEMO === "1" || process.env.OKX_DEMO === "true" || (toml.demo ?? false);
10419
10605
  }
10420
- function loadConfig(cli) {
10421
- const toml = readTomlProfile(cli.profile);
10422
- 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);
10423
10611
  const demo = resolveDemo(cli, toml);
10424
10612
  const site = resolveSite(cli.site, toml.site);
10425
10613
  const baseUrl = resolveBaseUrl(site, toml.base_url);
@@ -10439,6 +10627,7 @@ function loadConfig(cli) {
10439
10627
  }
10440
10628
  return {
10441
10629
  ...creds,
10630
+ profile: profileName,
10442
10631
  baseUrl,
10443
10632
  timeoutMs: Math.floor(rawTimeout),
10444
10633
  modules: parseModuleList(cli.modules),
@@ -10451,7 +10640,7 @@ function loadConfig(cli) {
10451
10640
  verbose: cli.verbose ?? false
10452
10641
  };
10453
10642
  }
10454
- var CACHE_FILE = join7(homedir5(), ".okx", "update-check.json");
10643
+ var CACHE_FILE = join8(homedir6(), ".okx", "update-check.json");
10455
10644
  var CHECK_INTERVAL_MS = 24 * 60 * 60 * 1e3;
10456
10645
  function readCache2() {
10457
10646
  try {
@@ -10464,7 +10653,7 @@ function readCache2() {
10464
10653
  }
10465
10654
  function writeCache2(cache) {
10466
10655
  try {
10467
- mkdirSync6(join7(homedir5(), ".okx"), { recursive: true });
10656
+ mkdirSync6(join8(homedir6(), ".okx"), { recursive: true });
10468
10657
  writeFileSync5(CACHE_FILE, JSON.stringify(cache, null, 2), "utf-8");
10469
10658
  } catch {
10470
10659
  }
@@ -10634,13 +10823,13 @@ function findMsStoreClaudePath() {
10634
10823
  }
10635
10824
  function getConfigPath(client) {
10636
10825
  const home = os3.homedir();
10637
- const platform2 = process.platform;
10826
+ const platform3 = process.platform;
10638
10827
  switch (client) {
10639
10828
  case "claude-desktop":
10640
- if (platform2 === "win32") {
10829
+ if (platform3 === "win32") {
10641
10830
  return findMsStoreClaudePath() ?? path3.join(appData(), "Claude", CLAUDE_CONFIG_FILE);
10642
10831
  }
10643
- if (platform2 === "darwin") {
10832
+ if (platform3 === "darwin") {
10644
10833
  return path3.join(home, "Library", "Application Support", "Claude", CLAUDE_CONFIG_FILE);
10645
10834
  }
10646
10835
  return path3.join(process.env.XDG_CONFIG_HOME ?? path3.join(home, ".config"), "Claude", CLAUDE_CONFIG_FILE);
@@ -10752,7 +10941,7 @@ var DOWNLOAD_TIMEOUT_MS = 3e4;
10752
10941
  var PLATFORM_MAP = {
10753
10942
  "darwin-arm64": "darwin-arm64",
10754
10943
  "darwin-x64": "darwin-x64",
10755
- "linux-arm64": "linux-arm64",
10944
+ "linux-arm64": "linux-x64",
10756
10945
  "linux-x64": "linux-x64",
10757
10946
  "win32-arm64": "win32-arm64",
10758
10947
  "win32-x64": "win32-x64"
@@ -10884,7 +11073,7 @@ async function installPilotBinary(destPath, sources = CDN_SOURCES, onProgress) {
10884
11073
  if (earlyResult) return earlyResult;
10885
11074
  const platformDir = getPlatformDir();
10886
11075
  const binaryName = getBinaryName();
10887
- const resolvedDest = destPath ?? join9(homedir7(), ".okx", "bin", binaryName);
11076
+ const resolvedDest = destPath ?? join10(homedir8(), ".okx", "bin", binaryName);
10888
11077
  const tmpPath = resolvedDest + ".tmp";
10889
11078
  mkdirSync8(dirname6(resolvedDest), { recursive: true });
10890
11079
  const localHash = existsSync6(resolvedDest) ? hashFile(resolvedDest) : null;
@@ -11007,107 +11196,646 @@ function downloadText(url, timeoutMs) {
11007
11196
  })
11008
11197
  );
11009
11198
  }
11010
-
11011
- // src/commands/diagnose.ts
11012
- import dns from "dns/promises";
11013
- import net from "net";
11014
- import os5 from "os";
11015
- import tls from "tls";
11016
-
11017
- // src/commands/diagnose-utils.ts
11018
- import fs4 from "fs";
11019
- import { createRequire } from "module";
11020
-
11021
- // src/formatter.ts
11022
- import { EOL } from "os";
11023
- var stdioOutput = {
11024
- out: (message) => process.stdout.write(message),
11025
- err: (message) => process.stderr.write(message)
11026
- };
11027
- var activeOutput = stdioOutput;
11028
- function setOutput(impl) {
11029
- activeOutput = impl;
11030
- }
11031
- var envContext = null;
11032
- function setEnvContext(ctx) {
11033
- envContext = ctx;
11034
- }
11035
- function output(message) {
11036
- activeOutput.out(message);
11037
- }
11038
- function errorOutput(message) {
11039
- activeOutput.err(message);
11040
- }
11041
- function outputLine(message) {
11042
- activeOutput.out(message + EOL);
11043
- }
11044
- function errorLine(message) {
11045
- activeOutput.err(message + EOL);
11046
- }
11047
- var jsonEnvEnabled = false;
11048
- function setJsonEnvEnabled(enabled) {
11049
- jsonEnvEnabled = enabled;
11050
- }
11051
- function printJson(data) {
11052
- const payload = jsonEnvEnabled && envContext ? {
11053
- env: envContext.demo ? "demo" : "live",
11054
- profile: envContext.profile,
11055
- data
11056
- } : data;
11057
- activeOutput.out(JSON.stringify(payload, null, 2) + EOL);
11199
+ var AUTH_CDN_PATH_PREFIX = "/upgradeapp/tools/oauth";
11200
+ function getAuthBinaryName() {
11201
+ return platform2() === "win32" ? "okx-auth.exe" : "okx-auth";
11058
11202
  }
11059
- function printTable(rows) {
11060
- if (envContext) {
11061
- const envLabel = envContext.demo ? "demo (simulated trading)" : "live";
11062
- activeOutput.out(`Environment: ${envLabel}` + EOL + EOL);
11063
- }
11064
- if (rows.length === 0) {
11065
- activeOutput.out("(no data)" + EOL);
11066
- return;
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 };
11067
11208
  }
11068
- const keys = Object.keys(rows[0]);
11069
- const widths = keys.map(
11070
- (k) => Math.max(k.length, ...rows.map((r) => String(r[k] ?? "").length))
11071
- );
11072
- const header = keys.map((k, i) => k.padEnd(widths[i])).join(" ");
11073
- const divider = widths.map((w) => "-".repeat(w)).join(" ");
11074
- activeOutput.out(header + EOL + divider + EOL);
11075
- for (const row of rows) {
11076
- activeOutput.out(keys.map((k, i) => String(row[k] ?? "").padEnd(widths[i])).join(" ") + EOL);
11209
+ if (opts?.skipHash) {
11210
+ return { binaryPath: resolvedPath, exists: true, platform: platformDir };
11077
11211
  }
11212
+ const { size, sha256 } = hashFile(resolvedPath);
11213
+ return { binaryPath: resolvedPath, exists: true, platform: platformDir, fileSize: size, sha256 };
11078
11214
  }
11079
- function printKv(obj, indent = 0) {
11080
- const pad = " ".repeat(indent);
11081
- for (const [k, v] of Object.entries(obj)) {
11082
- if (v !== null && typeof v === "object" && !Array.isArray(v)) {
11083
- activeOutput.out(`${pad}${k}:${EOL}`);
11084
- printKv(v, indent + 2);
11085
- } else {
11086
- activeOutput.out(`${pad}${k.padEnd(20 - indent)} ${v}${EOL}`);
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 {
11087
11229
  }
11088
11230
  }
11231
+ return null;
11089
11232
  }
11090
- function extractData(result) {
11091
- if (result && typeof result === "object") {
11092
- const data = result["data"];
11093
- if (Array.isArray(data)) return data;
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");
11094
11240
  }
11095
- return [];
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 };
11096
11245
  }
11097
- function markFailedIfSCodeError(data) {
11098
- if (!Array.isArray(data)) return;
11099
- for (const item of data) {
11100
- if (item !== null && typeof item === "object") {
11101
- const sCode = item["sCode"];
11102
- if (sCode !== void 0 && sCode !== "0" && sCode !== 0) {
11103
- process.exitCode = 1;
11104
- return;
11105
- }
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 {
11106
11263
  }
11107
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
+ }
11108
11464
  }
11109
11465
 
11466
+ // src/commands/auth.ts
11467
+ import { spawn as spawn2 } from "child_process";
11468
+ import readline from "readline";
11469
+
11470
+ // src/formatter.ts
11471
+ import { EOL } from "os";
11472
+ var stdioOutput = {
11473
+ out: (message) => process.stdout.write(message),
11474
+ err: (message) => process.stderr.write(message)
11475
+ };
11476
+ var activeOutput = stdioOutput;
11477
+ function setOutput(impl) {
11478
+ activeOutput = impl;
11479
+ }
11480
+ var envContext = null;
11481
+ function setEnvContext(ctx) {
11482
+ envContext = ctx;
11483
+ }
11484
+ function output(message) {
11485
+ activeOutput.out(message);
11486
+ }
11487
+ function errorOutput(message) {
11488
+ activeOutput.err(message);
11489
+ }
11490
+ function outputLine(message) {
11491
+ activeOutput.out(message + EOL);
11492
+ }
11493
+ function errorLine(message) {
11494
+ activeOutput.err(message + EOL);
11495
+ }
11496
+ var jsonEnvEnabled = false;
11497
+ function setJsonEnvEnabled(enabled) {
11498
+ jsonEnvEnabled = enabled;
11499
+ }
11500
+ function printJson(data) {
11501
+ const payload = jsonEnvEnabled && envContext ? {
11502
+ env: envContext.demo ? "demo" : "live",
11503
+ profile: envContext.profile,
11504
+ data
11505
+ } : data;
11506
+ activeOutput.out(JSON.stringify(payload, null, 2) + EOL);
11507
+ }
11508
+ function printTable(rows) {
11509
+ if (envContext) {
11510
+ const envLabel = envContext.demo ? "demo (simulated trading)" : "live";
11511
+ activeOutput.out(`Environment: ${envLabel}` + EOL + EOL);
11512
+ }
11513
+ if (rows.length === 0) {
11514
+ activeOutput.out("(no data)" + EOL);
11515
+ return;
11516
+ }
11517
+ const keys = Object.keys(rows[0]);
11518
+ const widths = keys.map(
11519
+ (k) => Math.max(k.length, ...rows.map((r) => String(r[k] ?? "").length))
11520
+ );
11521
+ const header = keys.map((k, i) => k.padEnd(widths[i])).join(" ");
11522
+ const divider = widths.map((w) => "-".repeat(w)).join(" ");
11523
+ activeOutput.out(header + EOL + divider + EOL);
11524
+ for (const row of rows) {
11525
+ activeOutput.out(keys.map((k, i) => String(row[k] ?? "").padEnd(widths[i])).join(" ") + EOL);
11526
+ }
11527
+ }
11528
+ function printKv(obj, indent = 0) {
11529
+ const pad = " ".repeat(indent);
11530
+ for (const [k, v] of Object.entries(obj)) {
11531
+ if (v !== null && typeof v === "object" && !Array.isArray(v)) {
11532
+ activeOutput.out(`${pad}${k}:${EOL}`);
11533
+ printKv(v, indent + 2);
11534
+ } else {
11535
+ activeOutput.out(`${pad}${k.padEnd(20 - indent)} ${v}${EOL}`);
11536
+ }
11537
+ }
11538
+ }
11539
+ function extractData(result) {
11540
+ if (result && typeof result === "object") {
11541
+ const data = result["data"];
11542
+ if (Array.isArray(data)) return data;
11543
+ }
11544
+ return [];
11545
+ }
11546
+ function markFailedIfSCodeError(data) {
11547
+ if (!Array.isArray(data)) return;
11548
+ for (const item of data) {
11549
+ if (item !== null && typeof item === "object") {
11550
+ const sCode = item["sCode"];
11551
+ if (sCode !== void 0 && sCode !== "0" && sCode !== 0) {
11552
+ process.exitCode = 1;
11553
+ return;
11554
+ }
11555
+ }
11556
+ }
11557
+ }
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
+
11110
11836
  // src/commands/diagnose-utils.ts
11837
+ import fs4 from "fs";
11838
+ import { createRequire } from "module";
11111
11839
  var _require = createRequire(import.meta.url);
11112
11840
  function readCliVersion() {
11113
11841
  for (const rel of ["../package.json", "../../package.json"]) {
@@ -11193,7 +11921,7 @@ function sanitize2(value) {
11193
11921
  import fs5 from "fs";
11194
11922
  import path4 from "path";
11195
11923
  import os4 from "os";
11196
- import { spawnSync, spawn } from "child_process";
11924
+ import { spawnSync, spawn as spawn3 } from "child_process";
11197
11925
  import { createRequire as createRequire2 } from "module";
11198
11926
  import { fileURLToPath } from "url";
11199
11927
  var _require2 = createRequire2(import.meta.url);
@@ -11527,7 +12255,7 @@ async function checkStdioHandshake(entryPath, report) {
11527
12255
  clearTimeout(timer);
11528
12256
  resolve3(passed);
11529
12257
  };
11530
- const child = spawn(process.execPath, [entryPath], {
12258
+ const child = spawn3(process.execPath, [entryPath], {
11531
12259
  stdio: ["pipe", "pipe", "pipe"],
11532
12260
  env: { ...process.env }
11533
12261
  });
@@ -11646,7 +12374,7 @@ async function cmdDiagnoseMcp(options = {}) {
11646
12374
 
11647
12375
  // src/commands/diagnose.ts
11648
12376
  var CLI_VERSION = readCliVersion();
11649
- var GIT_HASH = true ? "330e727a" : "dev";
12377
+ var GIT_HASH = true ? "a4277b3" : "dev";
11650
12378
  function maskKey2(key) {
11651
12379
  if (!key) return "(not set)";
11652
12380
  if (key.length <= 8) return "****";
@@ -12007,24 +12735,24 @@ function suggestSubcommand(action, knownActions) {
12007
12735
 
12008
12736
  // src/commands/upgrade.ts
12009
12737
  import { spawnSync as spawnSync2 } from "child_process";
12010
- import { readFileSync as readFileSync8, writeFileSync as writeFileSync7, mkdirSync as mkdirSync9 } from "fs";
12011
- import { dirname as dirname7, join as join10 } from "path";
12012
- 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";
12013
12741
  var PACKAGES = ["@okx_ai/okx-trade-mcp", "@okx_ai/okx-trade-cli"];
12014
- var CACHE_FILE2 = join10(homedir8(), ".okx", "last_check");
12742
+ var CACHE_FILE2 = join13(homedir11(), ".okx", "last_check");
12015
12743
  var THROTTLE_MS = 12 * 60 * 60 * 1e3;
12016
- 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");
12017
12745
  function readLastCheck() {
12018
12746
  try {
12019
- return parseInt(readFileSync8(CACHE_FILE2, "utf-8").trim(), 10) || 0;
12747
+ return parseInt(readFileSync9(CACHE_FILE2, "utf-8").trim(), 10) || 0;
12020
12748
  } catch {
12021
12749
  return 0;
12022
12750
  }
12023
12751
  }
12024
12752
  function writeLastCheck() {
12025
12753
  try {
12026
- mkdirSync9(join10(homedir8(), ".okx"), { recursive: true });
12027
- 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");
12028
12756
  } catch {
12029
12757
  }
12030
12758
  }
@@ -12938,12 +13666,12 @@ var CLI_REGISTRY = {
12938
13666
  },
12939
13667
  orders: {
12940
13668
  toolName: "event_get_orders",
12941
- usage: "okx event orders [--instId <id>] [--state live] [--limit <n>] [--json]",
13669
+ usage: "okx event orders [--status <open|history|archive>] [--instId <id>] [--ordType <type>] [--state <canceled|filled>] [--after <id>] [--before <id>] [--begin <ms>] [--end <ms>] [--limit <n>] [--json]",
12942
13670
  description: "Query event contract orders"
12943
13671
  },
12944
13672
  fills: {
12945
13673
  toolName: "event_get_fills",
12946
- usage: "okx event fills [--instId <id>] [--limit <n>] [--json]",
13674
+ usage: "okx event fills [--archive] [--instId <id>] [--ordId <id>] [--after <id>] [--before <id>] [--begin <ms>] [--end <ms>] [--limit <n>] [--json]",
12947
13675
  description: "Get event contract fill history"
12948
13676
  }
12949
13677
  }
@@ -12954,18 +13682,18 @@ var CLI_REGISTRY = {
12954
13682
  commands: {
12955
13683
  overview: {
12956
13684
  toolName: "smartmoney_get_overview",
12957
- usage: "okx smartmoney overview [--dataVersion <ver>] [--ts <ms>] [--instType <SWAP|SPOT>] [--sortType <pnl|pnlRatio>] [--period <3|7|30|90>] [--pnl <tier>] [--winRatio <tier>] [--maxRetreat <tier>] [--asset <tier>] [--lmtNum <n>] [--instCcyList <ccys>] [--instCcy <ccy>] [--topInstruments <n>] [--json]",
12958
- description: "Multi-currency smart money overview with aggregated signals"
13685
+ usage: "okx smartmoney overview [--ts <ms> | --dataVersion <ver>] [--instType <SWAP|SPOT>] [--sortType <pnl|pnlRatio>] [--period <3|7|30|90>] [--pnl <tier>] [--winRatio <tier>] [--maxRetreat <tier>] [--asset <tier>] [--lmtNum <n>] [--instCcyList <ccys>] [--instCcy <ccy>] [--topInstruments <n>] [--json]",
13686
+ description: "Multi-currency smart money overview ranked by tradersWithPosition DESC (requires --ts or --dataVersion; --ts takes precedence)"
12959
13687
  },
12960
13688
  signal: {
12961
13689
  toolName: "smartmoney_get_signal",
12962
- usage: "okx smartmoney signal [--instId <id>] [--instCcy <ccy>] [--dataVersion <ver>] [--ts <ms>] [--sortType <pnl|pnlRatio>] [--period <3|7|30|90>] [--pnl <tier>] [--winRatio <tier>] [--maxRetreat <tier>] [--asset <tier>] [--lmtNum <n>] [--authorIds <ids>] [--json]",
12963
- description: "Single-currency aggregated consensus signal"
13690
+ usage: "okx smartmoney signal [--instId <id>] [--instCcy <ccy>] [--ts <ms> | --dataVersion <ver>] [--sortType <pnl|pnlRatio>] [--period <3|7|30|90>] [--pnl <tier>] [--winRatio <tier>] [--maxRetreat <tier>] [--asset <tier>] [--lmtNum <n>] [--authorIds <ids>] [--json]",
13691
+ description: "Single-currency aggregated consensus signal (requires --instId or --instCcy, and --ts or --dataVersion; --instId / --ts take precedence)"
12964
13692
  },
12965
13693
  "signal-history": {
12966
13694
  toolName: "smartmoney_get_signal_history",
12967
- usage: "okx smartmoney signal-history --instId <id> [--dataVersion <ver>] [--ts <ms>] [--granularity <1h|1d>] [--limit <n>] [--sortType <pnl|pnlRatio>] [--period <3|7|30|90>] [--pnl <tier>] [--winRatio <tier>] [--maxRetreat <tier>] [--asset <tier>] [--json]",
12968
- description: "Signal history timeline for trend analysis"
13695
+ usage: "okx smartmoney signal-history --instId <id> [--ts <ms> | --dataVersion <ver>] [--granularity <1h|1d>] [--limit <n>] [--sortType <pnl|pnlRatio>] [--period <3|7|30|90>] [--pnl <tier>] [--winRatio <tier>] [--maxRetreat <tier>] [--asset <tier>] [--json]",
13696
+ description: "Signal history timeline sorted by ts DESC (requires --instId and --ts/--dataVersion)"
12969
13697
  },
12970
13698
  traders: {
12971
13699
  toolName: "smartmoney_get_traders",
@@ -13489,7 +14217,7 @@ async function cmdNewsSentimentRank(run, opts) {
13489
14217
  }
13490
14218
 
13491
14219
  // src/config/loader.ts
13492
- function loadProfileConfig(opts) {
14220
+ async function loadProfileConfig(opts) {
13493
14221
  return loadConfig({
13494
14222
  profile: opts.profile,
13495
14223
  modules: opts.modules,
@@ -13826,6 +14554,9 @@ var CLI_OPTIONS = {
13826
14554
  dir: { type: "string" },
13827
14555
  page: { type: "string" },
13828
14556
  format: { type: "string" },
14557
+ // auth
14558
+ site: { type: "string" },
14559
+ manual: { type: "boolean", default: false },
13829
14560
  // event contract
13830
14561
  underlying: { type: "string" },
13831
14562
  seriesId: { type: "string" },
@@ -17049,14 +17780,14 @@ async function cmdDcdQuoteAndBuy(run, opts) {
17049
17780
  }
17050
17781
 
17051
17782
  // src/commands/skill.ts
17052
- import { tmpdir, homedir as homedir10 } from "os";
17053
- import { join as join12, dirname as dirname8 } from "path";
17054
- 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";
17055
17786
  import { execFileSync as execFileSync2 } from "child_process";
17056
17787
  import { randomUUID as randomUUID2 } from "crypto";
17057
17788
  function resolveNpx() {
17058
- const sibling = join12(dirname8(process.execPath), "npx");
17059
- if (existsSync8(sibling)) return sibling;
17789
+ const sibling = join15(dirname9(process.execPath), "npx");
17790
+ if (existsSync10(sibling)) return sibling;
17060
17791
  return "npx";
17061
17792
  }
17062
17793
  var THIRD_PARTY_INSTALL_NOTICE = "Note: This skill was created by a third-party developer, not by OKX. Review SKILL.md before use.";
@@ -17109,13 +17840,13 @@ async function cmdSkillCategories(run, json) {
17109
17840
  outputLine("");
17110
17841
  }
17111
17842
  async function cmdSkillAdd(name, config, json) {
17112
- const tmpBase = join12(tmpdir(), `okx-skill-${randomUUID2()}`);
17113
- mkdirSync10(tmpBase, { recursive: true });
17843
+ const tmpBase = join15(tmpdir(), `okx-skill-${randomUUID2()}`);
17844
+ mkdirSync12(tmpBase, { recursive: true });
17114
17845
  try {
17115
17846
  outputLine(`Downloading ${name}...`);
17116
17847
  const client = new OkxRestClient(config);
17117
17848
  const zipPath = await downloadSkillZip(client, name, tmpBase);
17118
- const contentDir = await extractSkillZip(zipPath, join12(tmpBase, "content"));
17849
+ const contentDir = await extractSkillZip(zipPath, join15(tmpBase, "content"));
17119
17850
  const meta = readMetaJson(contentDir);
17120
17851
  validateSkillMdExists(contentDir);
17121
17852
  outputLine("Installing to detected agents...");
@@ -17125,7 +17856,7 @@ async function cmdSkillAdd(name, config, json) {
17125
17856
  timeout: 6e4
17126
17857
  });
17127
17858
  } catch (e) {
17128
- const savedZip = join12(process.cwd(), `${name}.zip`);
17859
+ const savedZip = join15(process.cwd(), `${name}.zip`);
17129
17860
  try {
17130
17861
  copyFileSync2(zipPath, savedZip);
17131
17862
  } catch {
@@ -17164,7 +17895,7 @@ function cmdSkillRemove(name, json) {
17164
17895
  timeout: 6e4
17165
17896
  });
17166
17897
  } catch {
17167
- const agentsPath = join12(homedir10(), ".agents", "skills", name);
17898
+ const agentsPath = join15(homedir13(), ".agents", "skills", name);
17168
17899
  try {
17169
17900
  rmSync(agentsPath, { recursive: true, force: true });
17170
17901
  } catch {
@@ -17238,14 +17969,14 @@ function printSkillInstallResult(meta, json) {
17238
17969
  }
17239
17970
 
17240
17971
  // src/commands/pilot.ts
17241
- import readline from "readline";
17242
- function resolveChecksumMatch(local, cdnChecksum, cdnError) {
17972
+ import readline2 from "readline";
17973
+ function resolveChecksumMatch2(local, cdnChecksum, cdnError) {
17243
17974
  if (!local.exists) return "not-installed";
17244
17975
  if (cdnError || !cdnChecksum) return "unavailable";
17245
17976
  if (cdnChecksum.sha256 === local.sha256) return "match";
17246
17977
  return "mismatch";
17247
17978
  }
17248
- function checksumMatchLabel(match) {
17979
+ function checksumMatchLabel2(match) {
17249
17980
  if (match === "match") return "\u2713 match";
17250
17981
  if (match === "mismatch") return "\u2717 mismatch (update available)";
17251
17982
  return "CDN unreachable";
@@ -17258,9 +17989,9 @@ function formatStatusText(local, checksumMatch, cdnChecksum, runtimeMode) {
17258
17989
  outputLine(` Installed : ${local.exists ? "yes" : "no"}`);
17259
17990
  outputLine(` Platform : ${local.platform ?? "(unsupported)"}`);
17260
17991
  if (local.exists) {
17261
- outputLine(` File size : ${formatBytes(local.fileSize)}`);
17992
+ outputLine(` File size : ${formatBytes2(local.fileSize)}`);
17262
17993
  outputLine(` SHA-256 : ${local.sha256 ?? "(unknown)"}`);
17263
- outputLine(` CDN check : ${checksumMatchLabel(checksumMatch)}`);
17994
+ outputLine(` CDN check : ${checksumMatchLabel2(checksumMatch)}`);
17264
17995
  if (cdnChecksum) {
17265
17996
  outputLine(` CDN source : ${cdnChecksum.source}`);
17266
17997
  }
@@ -17287,7 +18018,7 @@ async function cmdPilotStatus(json, binaryPath) {
17287
18018
  cdnError = err instanceof Error ? err.message : String(err);
17288
18019
  }
17289
18020
  }
17290
- const checksumMatch = resolveChecksumMatch(local, cdnChecksum, cdnError);
18021
+ const checksumMatch = resolveChecksumMatch2(local, cdnChecksum, cdnError);
17291
18022
  if (json) {
17292
18023
  outputLine(
17293
18024
  JSON.stringify({
@@ -17353,7 +18084,7 @@ async function cmdPilotRemove(force, json, binaryPath) {
17353
18084
  process.exitCode = 1;
17354
18085
  return;
17355
18086
  }
17356
- const confirmed = await askConfirmation(
18087
+ const confirmed = await askConfirmation2(
17357
18088
  ` Remove Pilot at ${local.binaryPath}? [y/N] `
17358
18089
  );
17359
18090
  if (!confirmed) {
@@ -17372,14 +18103,14 @@ async function cmdPilotRemove(force, json, binaryPath) {
17372
18103
  outputLine(" Pilot is not installed.");
17373
18104
  }
17374
18105
  }
17375
- function formatBytes(bytes) {
18106
+ function formatBytes2(bytes) {
17376
18107
  if (bytes < 1024) return `${bytes} B`;
17377
18108
  if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
17378
18109
  return `${(bytes / (1024 * 1024)).toFixed(2)} MB`;
17379
18110
  }
17380
- function askConfirmation(prompt2) {
18111
+ function askConfirmation2(prompt2) {
17381
18112
  return new Promise((resolve3) => {
17382
- const rl = readline.createInterface({
18113
+ const rl = readline2.createInterface({
17383
18114
  input: process.stdin,
17384
18115
  output: process.stdout
17385
18116
  });
@@ -17627,8 +18358,14 @@ async function cmdEventMarkets(run, opts) {
17627
18358
  }
17628
18359
  async function cmdEventOrders(run, opts) {
17629
18360
  const result = await run("event_get_orders", {
18361
+ status: opts.status,
17630
18362
  instId: opts.instId,
18363
+ ordType: opts.ordType,
17631
18364
  state: opts.state,
18365
+ after: opts.after,
18366
+ before: opts.before,
18367
+ begin: opts.begin,
18368
+ end: opts.end,
17632
18369
  limit: opts.limit
17633
18370
  });
17634
18371
  const data = getData9(result);
@@ -17647,7 +18384,13 @@ async function cmdEventOrders(run, opts) {
17647
18384
  }
17648
18385
  async function cmdEventFills(run, opts) {
17649
18386
  const result = await run("event_get_fills", {
18387
+ archive: opts.archive,
17650
18388
  instId: opts.instId,
18389
+ ordId: opts.ordId,
18390
+ after: opts.after,
18391
+ before: opts.before,
18392
+ begin: opts.begin,
18393
+ end: opts.end,
17651
18394
  limit: opts.limit
17652
18395
  });
17653
18396
  const data = getData9(result);
@@ -17836,7 +18579,7 @@ async function cmdEventCancel(run, opts) {
17836
18579
  // src/index.ts
17837
18580
  var _require3 = createRequire3(import.meta.url);
17838
18581
  var CLI_VERSION2 = _require3("../package.json").version;
17839
- var GIT_HASH2 = true ? "330e727a" : "dev";
18582
+ var GIT_HASH2 = true ? "a4277b3" : "dev";
17840
18583
  function handlePilotCommand(action, json, force, binaryPath) {
17841
18584
  if (action === "status") return cmdPilotStatus(json, binaryPath);
17842
18585
  if (action === "install") return cmdPilotInstall(json, binaryPath);
@@ -18879,13 +19622,13 @@ function handleNewsCommand(run, action, rest, v, json) {
18879
19622
  const period = v.period;
18880
19623
  const points = v.points !== void 0 ? Number(v.points) : 24;
18881
19624
  const sortBy = v["sort-by"];
18882
- const platform2 = v.platform;
18883
- const searchOpts = { coins: v.coins, importance: v.importance, platform: platform2, sentiment: v.sentiment, sortBy, begin, end, language, detailLvl, limit, after, json };
18884
- 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 };
18885
19628
  const dispatch = {
18886
19629
  latest: () => cmdNewsLatest(run, listOpts),
18887
- important: () => cmdNewsImportant(run, { coins: v.coins, platform: platform2, begin, end, language, detailLvl, limit, json }),
18888
- "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 }),
18889
19632
  search: () => cmdNewsSearch(run, v.keyword ?? rest[0], searchOpts),
18890
19633
  detail: () => cmdNewsDetail(run, rest[0], { language, json }),
18891
19634
  platforms: () => cmdNewsPlatforms(run, { json }),
@@ -18959,8 +19702,29 @@ function handleEventCommand(run, action, rest, v, json) {
18959
19702
  }),
18960
19703
  amend: () => cmdEventAmend(run, { instId: v.instId ?? rest[0], ordId: v.ordId ?? rest[1], px: v.px, sz: v.sz, json }),
18961
19704
  cancel: () => cmdEventCancel(run, { instId: v.instId ?? rest[0], ordId: v.ordId ?? rest[1], json }),
18962
- orders: () => cmdEventOrders(run, { instId: v.instId, state: v.state, limit, json }),
18963
- fills: () => cmdEventFills(run, { instId: v.instId, limit, json })
19705
+ orders: () => cmdEventOrders(run, {
19706
+ status: v.status,
19707
+ instId: v.instId,
19708
+ ordType: v.ordType,
19709
+ state: v.state,
19710
+ after: v.after,
19711
+ before: v.before,
19712
+ begin: v.begin,
19713
+ end: v.end,
19714
+ limit,
19715
+ json
19716
+ }),
19717
+ fills: () => cmdEventFills(run, {
19718
+ archive: v.archive ?? false,
19719
+ instId: v.instId,
19720
+ ordId: v.ordId,
19721
+ after: v.after,
19722
+ before: v.before,
19723
+ begin: v.begin,
19724
+ end: v.end,
19725
+ limit,
19726
+ json
19727
+ })
18964
19728
  };
18965
19729
  const handler = handlers[action];
18966
19730
  if (handler) return handler();
@@ -19005,7 +19769,7 @@ function wrapRunnerWithLogger(baseRunner, logger, verbose = false) {
19005
19769
  async function runDiagnose(v) {
19006
19770
  let config;
19007
19771
  try {
19008
- config = loadProfileConfig({ profile: v.profile, demo: v.demo, live: v.live, verbose: v.verbose, userAgent: `okx-trade-cli/${CLI_VERSION2}`, sourceTag: "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" });
19009
19773
  } catch {
19010
19774
  }
19011
19775
  return cmdDiagnose(config, v.profile ?? "default", { mcp: v.mcp, cli: v.cli, all: v.all, output: v.output });
@@ -19028,6 +19792,7 @@ function routeManagementCommand(module, action, rest, json, v) {
19028
19792
  handleSetupCommand(v);
19029
19793
  return true;
19030
19794
  }
19795
+ if (module === "auth") return handleAuthCommand(action, rest, v);
19031
19796
  if (module === "upgrade") return cmdUpgrade(CLI_VERSION2, { beta: v.beta, check: v.check, force: v.force }, json);
19032
19797
  if (module === "pilot") {
19033
19798
  const r = handlePilotCommand(action, json, v.force ?? false);
@@ -19060,7 +19825,7 @@ async function main() {
19060
19825
  const json = v.json ?? false;
19061
19826
  const mgmt = routeManagementCommand(module, action, rest, json, v);
19062
19827
  if (mgmt !== void 0) return mgmt === true ? void 0 : mgmt;
19063
- const config = loadProfileConfig({ profile: v.profile, demo: v.demo, live: v.live, verbose: v.verbose, userAgent: `okx-trade-cli/${CLI_VERSION2}`, sourceTag: "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" });
19064
19829
  setEnvContext({ demo: config.demo, profile: v.profile ?? "default" });
19065
19830
  setJsonEnvEnabled(v.env ?? false);
19066
19831
  const client = new OkxRestClient(config);