@okx_ai/okx-trade-cli 1.3.1-beta.8 → 1.3.1

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,26 +21,23 @@ 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";
27
24
  import fs from "fs";
28
25
  import path from "path";
29
26
  import os from "os";
30
27
  import { writeFileSync as writeFileSync2, renameSync as renameSync2, unlinkSync as unlinkSync2, mkdirSync as mkdirSync2 } from "fs";
31
- import { join as join4, resolve, basename, sep } from "path";
28
+ import { join as join3, resolve, basename, sep } from "path";
32
29
  import { randomUUID } from "crypto";
33
30
  import yauzl from "yauzl";
34
31
  import { createWriteStream, mkdirSync as mkdirSync3 } from "fs";
35
32
  import { resolve as resolve2, dirname as dirname2 } from "path";
36
33
  import { readFileSync as readFileSync2, existsSync } from "fs";
37
- import { join as join5 } from "path";
34
+ import { join as join4 } from "path";
38
35
  import { readFileSync as readFileSync3, writeFileSync as writeFileSync3, mkdirSync as mkdirSync4, existsSync as existsSync2 } from "fs";
39
- import { join as join6, dirname as dirname3 } from "path";
40
- import { homedir as homedir4 } from "os";
36
+ import { join as join5, dirname as dirname3 } from "path";
37
+ import { homedir as homedir3 } from "os";
41
38
  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";
39
+ import { join as join6, dirname as dirname4 } from "path";
40
+ import { homedir as homedir4 } from "os";
44
41
 
45
42
  // ../../node_modules/.pnpm/smol-toml@1.6.0/node_modules/smol-toml/dist/error.js
46
43
  function getLineColFromPtr(string, ptr) {
@@ -870,8 +867,8 @@ function stringify(obj, { maxDepth = 1e3, numbersAsFloat = false } = {}) {
870
867
 
871
868
  // ../core/dist/index.js
872
869
  import { readFileSync as readFileSync5, writeFileSync as writeFileSync5, mkdirSync as mkdirSync6, existsSync as existsSync4 } from "fs";
873
- import { join as join8 } from "path";
874
- import { homedir as homedir6 } from "os";
870
+ import { join as join7 } from "path";
871
+ import { homedir as homedir5 } from "os";
875
872
  import fs2 from "fs";
876
873
  import path2 from "path";
877
874
  import os2 from "os";
@@ -879,18 +876,6 @@ import * as fs3 from "fs";
879
876
  import * as path3 from "path";
880
877
  import * as os3 from "os";
881
878
  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";
894
879
  import {
895
880
  readFileSync as readFileSync7,
896
881
  createWriteStream as createWriteStream2,
@@ -901,8 +886,8 @@ import {
901
886
  renameSync as renameSync3
902
887
  } from "fs";
903
888
  import { createHash } from "crypto";
904
- import { homedir as homedir8, platform, arch } from "os";
905
- import { join as join10, dirname as dirname6 } from "path";
889
+ import { homedir as homedir7, platform, arch } from "os";
890
+ import { join as join9, dirname as dirname6 } from "path";
906
891
  import { get as httpsGet } from "https";
907
892
  import { get as httpGet } from "http";
908
893
  var EXEC_TIMEOUT_MS = 3e4;
@@ -913,7 +898,7 @@ function getDohBinaryPath() {
913
898
  return process.env.OKX_DOH_BINARY_PATH;
914
899
  }
915
900
  const ext = process.platform === "win32" ? ".exe" : "";
916
- return join(DOH_BIN_DIR, `okx-doh-resolver${ext}`);
901
+ return join(DOH_BIN_DIR, `okx-pilot${ext}`);
917
902
  }
918
903
  function execDohBinary(domain, exclude = [], userAgent) {
919
904
  if (!ALLOWED_DOMAIN_RE.test(domain)) {
@@ -984,7 +969,7 @@ function classifyAndCache(node, hostname, failedNodes, cachePath) {
984
969
  if (!node) {
985
970
  return { mode: null, node: null };
986
971
  }
987
- if (node.ip === hostname || node.host === hostname) {
972
+ if (node.ip === hostname && node.host === hostname) {
988
973
  writeCache(hostname, {
989
974
  mode: "direct",
990
975
  node: null,
@@ -1216,11 +1201,6 @@ var ConfigError = class extends OkxMcpError {
1216
1201
  super("ConfigError", message, { suggestion });
1217
1202
  }
1218
1203
  };
1219
- var NotLoggedInError = class extends ConfigError {
1220
- constructor(suggestion = "Run `okx auth login` to authenticate.") {
1221
- super("Not logged in.", suggestion);
1222
- }
1223
- };
1224
1204
  var ValidationError = class extends OkxMcpError {
1225
1205
  constructor(message, suggestion) {
1226
1206
  super("ValidationError", message, { suggestion });
@@ -1273,97 +1253,6 @@ function toToolErrorPayload(error, fallbackEndpoint) {
1273
1253
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
1274
1254
  };
1275
1255
  }
1276
- var EXIT_CODES = {
1277
- SUCCESS: 0,
1278
- UNAUTHORIZED_CALLER: 1,
1279
- NOT_LOGGED_IN: 2,
1280
- REFRESH_FAILED: 3
1281
- };
1282
- var EXEC_TIMEOUT_MS2 = 5e3;
1283
- var AUTH_BIN_DIR = join3(homedir3(), ".okx", "bin");
1284
- function getAuthBinaryPath() {
1285
- if (process.env.OKX_AUTH_BIN) {
1286
- return process.env.OKX_AUTH_BIN;
1287
- }
1288
- const ext = process.platform === "win32" ? ".exe" : "";
1289
- return join3(AUTH_BIN_DIR, `okx-auth${ext}`);
1290
- }
1291
- function execAuthToken() {
1292
- const binPath = getAuthBinaryPath();
1293
- return new Promise((resolve3, reject) => {
1294
- const child = spawn(binPath, ["token"], {
1295
- stdio: ["ignore", "ignore", "inherit", "pipe"]
1296
- // stdin stdout stderr fd3 (pipe)
1297
- });
1298
- const chunks = [];
1299
- const fd3 = child.stdio[3];
1300
- fd3.on("data", (chunk) => chunks.push(chunk));
1301
- child.on("error", (err) => {
1302
- reject(new ConfigError(
1303
- `Failed to spawn okx-auth: ${err.message}`,
1304
- "Ensure the okx-auth binary exists and is executable."
1305
- ));
1306
- });
1307
- child.on("close", (code) => {
1308
- if (code === EXIT_CODES.SUCCESS) {
1309
- const token = Buffer.concat(chunks).toString("utf-8").trim();
1310
- if (!token) {
1311
- reject(new AuthenticationError(
1312
- "okx-auth returned empty token.",
1313
- "Run `okx auth login` to re-authenticate."
1314
- ));
1315
- return;
1316
- }
1317
- resolve3(token);
1318
- return;
1319
- }
1320
- if (code === EXIT_CODES.NOT_LOGGED_IN) {
1321
- reject(new NotLoggedInError());
1322
- return;
1323
- }
1324
- if (code === EXIT_CODES.UNAUTHORIZED_CALLER) {
1325
- reject(new AuthenticationError(
1326
- "okx-auth rejected the caller (unauthorized).",
1327
- "Ensure you are running from a trusted OKX tool."
1328
- ));
1329
- return;
1330
- }
1331
- if (code === EXIT_CODES.REFRESH_FAILED) {
1332
- reject(new AuthenticationError(
1333
- "Token refresh failed.",
1334
- "Run `okx auth login` to re-authenticate."
1335
- ));
1336
- return;
1337
- }
1338
- reject(new AuthenticationError(
1339
- `okx-auth token exited with code ${code}.`,
1340
- "Run `okx auth login` to re-authenticate."
1341
- ));
1342
- });
1343
- });
1344
- }
1345
- function execAuthStatus() {
1346
- const binPath = getAuthBinaryPath();
1347
- return new Promise((resolve3) => {
1348
- execFile2(
1349
- binPath,
1350
- ["status", "--json"],
1351
- { timeout: EXEC_TIMEOUT_MS2, encoding: "utf-8" },
1352
- (error, stdout) => {
1353
- if (error) {
1354
- resolve3(null);
1355
- return;
1356
- }
1357
- try {
1358
- const result = JSON.parse(stdout);
1359
- resolve3(result);
1360
- } catch {
1361
- resolve3(null);
1362
- }
1363
- }
1364
- );
1365
- });
1366
- }
1367
1256
  function sleep(ms) {
1368
1257
  return new Promise((resolve3) => {
1369
1258
  setTimeout(resolve3, ms);
@@ -1442,10 +1331,10 @@ var OKX_CODE_BEHAVIORS = {
1442
1331
  "50011": { retry: true, suggestion: "Rate limited. Back off and retry after a delay." },
1443
1332
  "50061": { retry: true, suggestion: "Too many connections. Reduce request frequency and retry." },
1444
1333
  // Server temporarily unavailable → retryable
1445
- "50001": { retry: true, suggestion: "OKX system upgrade in progress. Retry in a few minutes." },
1446
- "50004": { retry: true, suggestion: "Endpoint temporarily unavailable. Retry later." },
1334
+ "50001": { retry: true, suggestion: "Service temporarily unavailable. Retry in a few minutes." },
1335
+ "50004": { retry: true, suggestion: "Endpoint request timeout. Retry later." },
1447
1336
  "50013": { retry: true, suggestion: "System busy. Retry after 1-2 seconds." },
1448
- "50026": { retry: true, suggestion: "Order book system upgrading. Retry in a few minutes." },
1337
+ "50026": { retry: true, suggestion: "System error. Retry in a few minutes." },
1449
1338
  // Region / compliance restriction → do not retry
1450
1339
  "51155": { retry: false, suggestion: "Feature unavailable in your region (site: {site}). Verify your site setting matches your account registration region. Available sites: global, eea, us. Do not retry." },
1451
1340
  "51734": { retry: false, suggestion: "Feature not supported for your KYC country (site: {site}). Verify your site setting matches your account registration region. Available sites: global, eea, us. Do not retry." },
@@ -1495,7 +1384,6 @@ function maskKey(key) {
1495
1384
  if (key.length <= 8) return "***";
1496
1385
  return `${key.slice(0, 3)}***${key.slice(-3)}`;
1497
1386
  }
1498
- var TOKEN_CACHE_TTL_MS = 6e4;
1499
1387
  function vlog2(message) {
1500
1388
  process.stderr.write(`[verbose] ${message}
1501
1389
  `);
@@ -1504,8 +1392,6 @@ var OkxRestClient = class _OkxRestClient {
1504
1392
  config;
1505
1393
  rateLimiter;
1506
1394
  dispatcher;
1507
- cachedAccessToken;
1508
- cachedAccessTokenAt = 0;
1509
1395
  doh;
1510
1396
  constructor(config) {
1511
1397
  this.config = config;
@@ -1520,51 +1406,6 @@ var OkxRestClient = class _OkxRestClient {
1520
1406
  hasCustomProxy: !!config.proxyUrl
1521
1407
  });
1522
1408
  }
1523
- /**
1524
- * Resolve OAuth access token via the okx-auth binary (fd3 pipe).
1525
- * Caches the token for 60 s to avoid spawning the binary on every
1526
- * request. The binary handles refresh internally (300s TTL lead),
1527
- * so periodic re-calls let it serve a fresh token when needed.
1528
- * Returns null when not logged in.
1529
- */
1530
- async resolveAccessToken() {
1531
- if (this.cachedAccessToken && Date.now() - this.cachedAccessTokenAt < TOKEN_CACHE_TTL_MS) {
1532
- return this.cachedAccessToken;
1533
- }
1534
- try {
1535
- const token = await execAuthToken();
1536
- this.cachedAccessToken = token;
1537
- this.cachedAccessTokenAt = Date.now();
1538
- return token;
1539
- } catch (e) {
1540
- if (e instanceof NotLoggedInError) {
1541
- return null;
1542
- }
1543
- throw e;
1544
- }
1545
- }
1546
- /**
1547
- * Dynamic auth — determines auth method per request.
1548
- *
1549
- * 1. API key in config → HMAC signing (no OAuth fallback)
1550
- * 2. OAuth token via okx-auth binary → Bearer token
1551
- * 3. Neither → throw ConfigError
1552
- */
1553
- async applyAuth(headers, method, requestPath, bodyJson, timestamp) {
1554
- if (this.config.apiKey && this.config.secretKey && this.config.passphrase) {
1555
- this.setAuthHeaders(headers, method, requestPath, bodyJson, timestamp);
1556
- return;
1557
- }
1558
- const accessToken = await this.resolveAccessToken();
1559
- if (accessToken) {
1560
- headers.set("Authorization", `Bearer ${accessToken}`);
1561
- return;
1562
- }
1563
- throw new ConfigError(
1564
- "No credentials found.",
1565
- "Run `okx auth login` to authenticate, or configure API key credentials."
1566
- );
1567
- }
1568
1409
  /** The canonical base URL for this client (e.g. https://www.okx.com). */
1569
1410
  get baseUrl() {
1570
1411
  return this.config.baseUrl;
@@ -1622,6 +1463,18 @@ var OkxRestClient = class _OkxRestClient {
1622
1463
  });
1623
1464
  }
1624
1465
  setAuthHeaders(headers, method, requestPath, bodyJson, timestamp) {
1466
+ if (!this.config.hasAuth) {
1467
+ throw new ConfigError(
1468
+ "Private endpoint requires API credentials.",
1469
+ "Configure OKX_API_KEY, OKX_SECRET_KEY and OKX_PASSPHRASE."
1470
+ );
1471
+ }
1472
+ if (!this.config.apiKey || !this.config.secretKey || !this.config.passphrase) {
1473
+ throw new ConfigError(
1474
+ "Invalid private API credentials state.",
1475
+ "Ensure all OKX credentials are set."
1476
+ );
1477
+ }
1625
1478
  const payload = `${timestamp}${method.toUpperCase()}${requestPath}${bodyJson}`;
1626
1479
  const signature = signOkxPayload(payload, this.config.secretKey);
1627
1480
  headers.set("OK-ACCESS-KEY", this.config.apiKey);
@@ -1736,7 +1589,7 @@ var OkxRestClient = class _OkxRestClient {
1736
1589
  const conn = this.doh.getConnectionParams();
1737
1590
  this.logRequest("POST", `${conn.baseUrl}${path42}`, "private");
1738
1591
  const reqConfig = { method: "POST", path: path42, auth: "private" };
1739
- const headers = await this.buildHeaders(reqConfig, path42, bodyJson, getNow());
1592
+ const headers = this.buildHeaders(reqConfig, path42, bodyJson, getNow());
1740
1593
  if (conn.userAgent) {
1741
1594
  headers.set("User-Agent", conn.userAgent);
1742
1595
  }
@@ -1853,7 +1706,7 @@ var OkxRestClient = class _OkxRestClient {
1853
1706
  // Header building
1854
1707
  // ---------------------------------------------------------------------------
1855
1708
  /** Build HTTP headers. reqConfig.extraHeaders must NOT contain auth keys (OK-ACCESS-*). */
1856
- async buildHeaders(reqConfig, requestPath, bodyJson, timestamp) {
1709
+ buildHeaders(reqConfig, requestPath, bodyJson, timestamp) {
1857
1710
  const headers = new Headers({
1858
1711
  "Content-Type": "application/json",
1859
1712
  Accept: "application/json"
@@ -1862,7 +1715,7 @@ var OkxRestClient = class _OkxRestClient {
1862
1715
  headers.set("User-Agent", this.config.userAgent);
1863
1716
  }
1864
1717
  if (reqConfig.auth === "private") {
1865
- await this.applyAuth(headers, reqConfig.method, requestPath, bodyJson, timestamp);
1718
+ this.setAuthHeaders(headers, reqConfig.method, requestPath, bodyJson, timestamp);
1866
1719
  }
1867
1720
  const useSimulated = reqConfig.simulatedTrading !== void 0 ? reqConfig.simulatedTrading : this.config.demo;
1868
1721
  if (useSimulated) {
@@ -1916,7 +1769,7 @@ var OkxRestClient = class _OkxRestClient {
1916
1769
  if (reqConfig.rateLimit) {
1917
1770
  await this.rateLimiter.consume(reqConfig.rateLimit);
1918
1771
  }
1919
- const headers = await this.buildHeaders(reqConfig, requestPath, bodyJson, timestamp);
1772
+ const headers = this.buildHeaders(reqConfig, requestPath, bodyJson, timestamp);
1920
1773
  if (conn.userAgent) {
1921
1774
  headers.set("User-Agent", conn.userAgent);
1922
1775
  }
@@ -2339,7 +2192,7 @@ var OKX_SITES = {
2339
2192
  },
2340
2193
  us: {
2341
2194
  label: "US",
2342
- apiBaseUrl: "https://us.okx.com",
2195
+ apiBaseUrl: "https://app.okx.com",
2343
2196
  webUrl: "https://app.okx.com"
2344
2197
  }
2345
2198
  };
@@ -3869,7 +3722,7 @@ function safeWriteFile(targetDir, fileName, data) {
3869
3722
  throw new Error(`Invalid file name: "${fileName}"`);
3870
3723
  }
3871
3724
  const resolvedDir = resolve(targetDir);
3872
- const filePath = join4(resolvedDir, safeName);
3725
+ const filePath = join3(resolvedDir, safeName);
3873
3726
  const resolvedPath = resolve(filePath);
3874
3727
  if (!resolvedPath.startsWith(resolvedDir + sep)) {
3875
3728
  throw new Error(`Path traversal detected: "${fileName}" resolves outside target directory`);
@@ -3997,7 +3850,7 @@ async function extractSkillZip(zipPath, targetDir, limits) {
3997
3850
  });
3998
3851
  }
3999
3852
  function readMetaJson(contentDir) {
4000
- const metaPath = join5(contentDir, "_meta.json");
3853
+ const metaPath = join4(contentDir, "_meta.json");
4001
3854
  if (!existsSync(metaPath)) {
4002
3855
  throw new Error(`_meta.json not found in ${contentDir}. Invalid skill package.`);
4003
3856
  }
@@ -4023,12 +3876,12 @@ function readMetaJson(contentDir) {
4023
3876
  };
4024
3877
  }
4025
3878
  function validateSkillMdExists(contentDir) {
4026
- const skillMdPath = join5(contentDir, "SKILL.md");
3879
+ const skillMdPath = join4(contentDir, "SKILL.md");
4027
3880
  if (!existsSync(skillMdPath)) {
4028
3881
  throw new Error(`SKILL.md not found in ${contentDir}. Invalid skill package.`);
4029
3882
  }
4030
3883
  }
4031
- var DEFAULT_REGISTRY_PATH = join6(homedir4(), ".okx", "skills", "registry.json");
3884
+ var DEFAULT_REGISTRY_PATH = join5(homedir3(), ".okx", "skills", "registry.json");
4032
3885
  function readRegistry(registryPath = DEFAULT_REGISTRY_PATH) {
4033
3886
  if (!existsSync2(registryPath)) {
4034
3887
  return { version: 1, skills: {} };
@@ -5366,7 +5219,7 @@ function registerOnchainEarnTools() {
5366
5219
  ];
5367
5220
  }
5368
5221
  var DCD_CODE_BEHAVIORS = {
5369
- "50001": { retry: true, suggestion: "DCD service is down. Retry in a few minutes." },
5222
+ "50001": { retry: true, suggestion: "Service temporarily unavailable. Retry in a few minutes." },
5370
5223
  "50002": { retry: false, suggestion: "Invalid JSON in request body. This is likely a bug \u2014 check request parameters." },
5371
5224
  "50014": { retry: false, suggestion: "Missing required parameter. Check that all required fields are provided." },
5372
5225
  "50016": { retry: false, suggestion: "notionalCcy does not match productId option type. Use baseCcy for CALL, quoteCcy for PUT." },
@@ -7984,38 +7837,40 @@ var NEWS_DETAIL = "/api/v5/orbit/news-detail";
7984
7837
  var NEWS_DOMAINS = "/api/v5/orbit/news-platform";
7985
7838
  var SENTIMENT_QUERY = "/api/v5/orbit/currency-sentiment-query";
7986
7839
  var SENTIMENT_RANKING = "/api/v5/orbit/currency-sentiment-ranking";
7987
- var NEWS_LANGUAGE = ["en_US", "zh_CN"];
7840
+ var NEWS_LANGUAGE = ["en-US", "zh-CN"];
7988
7841
  function langHeader(lang) {
7989
- const resolved = lang === "zh_CN" ? "zh_CN" : "en_US";
7990
- return { "Accept-Language": resolved };
7842
+ if (lang === "zh-CN" || lang === "zh_CN") return { "Accept-Language": "zh-CN" };
7843
+ return { "Accept-Language": "en-US" };
7991
7844
  }
7992
7845
  var NEWS_DETAIL_LVL = ["brief", "summary", "full"];
7993
- var NEWS_IMPORTANCE = ["high", "medium", "low"];
7846
+ var NEWS_IMPORTANCE = ["high", "low"];
7994
7847
  var NEWS_SENTIMENT = ["bullish", "bearish", "neutral"];
7995
7848
  var NEWS_SORT = ["latest", "relevant"];
7996
7849
  var SENTIMENT_PERIOD = ["1h", "4h", "24h"];
7997
7850
  var D_COINS_NEWS = 'Comma-separated uppercase ticker symbols (e.g. "BTC,ETH"). Normalize names/aliases to standard tickers.';
7998
7851
  var D_COINS_SENTIMENT = 'Comma-separated uppercase ticker symbols, max 20 (e.g. "BTC,ETH"). Normalize names/aliases to standard tickers.';
7999
- var D_LANGUAGE = "Content language: zh_CN or en_US. Infer from user's message. No server default.";
8000
- var D_BEGIN = "Start time, Unix epoch milliseconds. Parse relative time if given (e.g. 'yesterday', 'last 7 days').";
7852
+ var D_LANGUAGE = "Content language: zh-CN or en-US. Infer from user's message. No server default.";
7853
+ var D_BEGIN = "Start time, Unix epoch milliseconds. API defaults to 72 hours ago when omitted. Pass explicitly for older topics (e.g. 'last 30 days'). Max range: 180 days. Parse relative time if given.";
8001
7854
  var D_END = "End time, Unix epoch milliseconds. Parse relative time if given. Omit for no upper bound.";
8002
- var D_IMPORTANCE = "Importance filter: high (server default), medium, low. Omit unless user wants broader coverage.";
7855
+ var D_IMPORTANCE = "Importance filter: high (server default) or low. Omit unless user wants broader coverage.";
7856
+ var D_PLATFORM = "Filter by news source. Use values from news_get_domains (e.g. blockbeats, odaily_flash). Omit for all sources.";
8003
7857
  var D_LIMIT = "Number of results (default 10, max 50).";
8004
7858
  function registerNewsTools() {
8005
- return [
7859
+ const tools = [
8006
7860
  // -----------------------------------------------------------------------
8007
7861
  // News browsing tools
8008
7862
  // -----------------------------------------------------------------------
8009
7863
  {
8010
7864
  name: "news_get_latest",
8011
7865
  module: "news",
8012
- description: "Get crypto news sorted by time. Omitting importance still returns only high-importance news (server default). Pass importance='medium' or 'low' explicitly to broaden results. Use when user asks 'what happened recently', 'latest news', 'any big news today', or wants to browse without a keyword. For coin-specific news, use news_get_by_coin instead.",
7866
+ description: "Get crypto news sorted by time. Omitting importance still returns only high-importance news (server default). Pass importance='low' explicitly to broaden results. Use when user asks 'what happened recently', 'latest news', 'any big news today', or wants to browse without a keyword. For coin-specific news, use news_get_by_coin instead.",
8013
7867
  isWrite: false,
8014
7868
  inputSchema: {
8015
7869
  type: "object",
8016
7870
  properties: {
8017
7871
  coins: { type: "string", description: D_COINS_NEWS + " Optional." },
8018
7872
  importance: { type: "string", enum: [...NEWS_IMPORTANCE], description: D_IMPORTANCE },
7873
+ platform: { type: "string", description: D_PLATFORM },
8019
7874
  begin: { type: "number", description: D_BEGIN },
8020
7875
  end: { type: "number", description: D_END },
8021
7876
  language: { type: "string", enum: [...NEWS_LANGUAGE], description: D_LANGUAGE },
@@ -8036,6 +7891,7 @@ function registerNewsTools() {
8036
7891
  compactObject({
8037
7892
  sortBy: "latest",
8038
7893
  importance: readString(args, "importance"),
7894
+ platform: readString(args, "platform"),
8039
7895
  ccyList: readString(args, "coins"),
8040
7896
  begin: readNumber(args, "begin"),
8041
7897
  end: readNumber(args, "end"),
@@ -8059,6 +7915,7 @@ function registerNewsTools() {
8059
7915
  properties: {
8060
7916
  coins: { type: "string", description: D_COINS_NEWS + " Required." },
8061
7917
  importance: { type: "string", enum: [...NEWS_IMPORTANCE], description: D_IMPORTANCE },
7918
+ platform: { type: "string", description: D_PLATFORM },
8062
7919
  begin: { type: "number", description: D_BEGIN },
8063
7920
  end: { type: "number", description: D_END },
8064
7921
  language: { type: "string", enum: [...NEWS_LANGUAGE], description: D_LANGUAGE },
@@ -8079,6 +7936,7 @@ function registerNewsTools() {
8079
7936
  sortBy: "latest",
8080
7937
  ccyList: coins,
8081
7938
  importance: readString(args, "importance"),
7939
+ platform: readString(args, "platform"),
8082
7940
  begin: readNumber(args, "begin"),
8083
7941
  end: readNumber(args, "end"),
8084
7942
  detailLvl: readString(args, "detailLvl"),
@@ -8104,6 +7962,7 @@ function registerNewsTools() {
8104
7962
  },
8105
7963
  coins: { type: "string", description: D_COINS_NEWS + " Optional." },
8106
7964
  importance: { type: "string", enum: [...NEWS_IMPORTANCE], description: D_IMPORTANCE },
7965
+ platform: { type: "string", description: D_PLATFORM },
8107
7966
  sentiment: {
8108
7967
  type: "string",
8109
7968
  enum: [...NEWS_SENTIMENT],
@@ -8131,6 +7990,7 @@ function registerNewsTools() {
8131
7990
  keyword: readString(args, "keyword") || void 0,
8132
7991
  sortBy: readString(args, "sortBy") ?? "relevant",
8133
7992
  importance: readString(args, "importance"),
7993
+ platform: readString(args, "platform"),
8134
7994
  ccyList: readString(args, "coins"),
8135
7995
  sentiment: readString(args, "sentiment"),
8136
7996
  begin: readNumber(args, "begin"),
@@ -8276,6 +8136,24 @@ function registerNewsTools() {
8276
8136
  }
8277
8137
  }
8278
8138
  ];
8139
+ const domainsIdx = tools.findIndex((t) => t.name === "news_get_domains");
8140
+ if (domainsIdx === -1) throw new Error("news_get_domains not found in tools list");
8141
+ const [domainsTool] = tools.splice(domainsIdx, 1);
8142
+ return [...tools.map(withNewsDemoGuard), domainsTool];
8143
+ }
8144
+ var NEWS_DEMO_MESSAGE = "News features are not available in demo/simulated trading mode.";
8145
+ var NEWS_DEMO_SUGGESTION = "Switch to a live profile to use News features.";
8146
+ function withNewsDemoGuard(tool) {
8147
+ const originalHandler = tool.handler;
8148
+ return {
8149
+ ...tool,
8150
+ handler: async (args, context) => {
8151
+ if (context.config.demo) {
8152
+ throw new ConfigError(NEWS_DEMO_MESSAGE, NEWS_DEMO_SUGGESTION);
8153
+ }
8154
+ return originalHandler(args, context);
8155
+ }
8156
+ };
8279
8157
  }
8280
8158
  function registerOptionAlgoTools() {
8281
8159
  return [
@@ -9793,7 +9671,7 @@ function createToolRunner(client, config) {
9793
9671
  };
9794
9672
  }
9795
9673
  function configFilePath() {
9796
- return join7(homedir5(), ".okx", "config.toml");
9674
+ return join6(homedir4(), ".okx", "config.toml");
9797
9675
  }
9798
9676
  function readFullConfig() {
9799
9677
  const path42 = configFilePath();
@@ -9812,6 +9690,11 @@ Or re-run: okx config init`
9812
9690
  );
9813
9691
  }
9814
9692
  }
9693
+ function readTomlProfile(profileName) {
9694
+ const config = readFullConfig();
9695
+ const name = profileName ?? config.default_profile ?? "default";
9696
+ return config.profiles?.[name] ?? {};
9697
+ }
9815
9698
  var CONFIG_HEADER = `# OKX Trade Kit Configuration
9816
9699
  # If editing manually, wrap values containing special chars in quotes:
9817
9700
  # passphrase = 'value' (if value contains # \\ ")
@@ -9860,24 +9743,18 @@ function parseModuleList(rawModules) {
9860
9743
  }
9861
9744
  return Array.from(deduped);
9862
9745
  }
9863
- async function loadCredentials(toml) {
9746
+ function loadCredentials(toml) {
9864
9747
  const apiKey = process.env.OKX_API_KEY?.trim() ?? toml.api_key;
9865
9748
  const secretKey = process.env.OKX_SECRET_KEY?.trim() ?? toml.secret_key;
9866
9749
  const passphrase = process.env.OKX_PASSPHRASE?.trim() ?? toml.passphrase;
9867
- const hasApiKey = Boolean(apiKey && secretKey && passphrase);
9750
+ const hasAuth = Boolean(apiKey && secretKey && passphrase);
9868
9751
  const partialAuth = Boolean(apiKey) || Boolean(secretKey) || Boolean(passphrase);
9869
- if (partialAuth && !hasApiKey) {
9752
+ if (partialAuth && !hasAuth) {
9870
9753
  throw new ConfigError(
9871
9754
  "Partial API credentials detected.",
9872
9755
  "Set OKX_API_KEY, OKX_SECRET_KEY and OKX_PASSPHRASE together (env vars or config.toml profile)."
9873
9756
  );
9874
9757
  }
9875
- let hasOAuth = false;
9876
- if (!hasApiKey) {
9877
- const status = await execAuthStatus();
9878
- hasOAuth = status?.status === "logged_in";
9879
- }
9880
- const hasAuth = hasOAuth || hasApiKey;
9881
9758
  return { apiKey, secretKey, passphrase, hasAuth };
9882
9759
  }
9883
9760
  function resolveSite(cliSite, tomlSite) {
@@ -9911,11 +9788,9 @@ function resolveDemo(cli, toml) {
9911
9788
  if (cli.demo === true) return true;
9912
9789
  return process.env.OKX_DEMO === "1" || process.env.OKX_DEMO === "true" || (toml.demo ?? false);
9913
9790
  }
9914
- async function loadConfig(cli) {
9915
- const config = readFullConfig();
9916
- const profileName = cli.profile ?? config.default_profile ?? "default";
9917
- const toml = config.profiles?.[profileName] ?? {};
9918
- const creds = await loadCredentials(toml);
9791
+ function loadConfig(cli) {
9792
+ const toml = readTomlProfile(cli.profile);
9793
+ const creds = loadCredentials(toml);
9919
9794
  const demo = resolveDemo(cli, toml);
9920
9795
  const site = resolveSite(cli.site, toml.site);
9921
9796
  const baseUrl = resolveBaseUrl(site, toml.base_url);
@@ -9935,7 +9810,6 @@ async function loadConfig(cli) {
9935
9810
  }
9936
9811
  return {
9937
9812
  ...creds,
9938
- profile: profileName,
9939
9813
  baseUrl,
9940
9814
  timeoutMs: Math.floor(rawTimeout),
9941
9815
  modules: parseModuleList(cli.modules),
@@ -9948,7 +9822,7 @@ async function loadConfig(cli) {
9948
9822
  verbose: cli.verbose ?? false
9949
9823
  };
9950
9824
  }
9951
- var CACHE_FILE = join8(homedir6(), ".okx", "update-check.json");
9825
+ var CACHE_FILE = join7(homedir5(), ".okx", "update-check.json");
9952
9826
  var CHECK_INTERVAL_MS = 24 * 60 * 60 * 1e3;
9953
9827
  function readCache2() {
9954
9828
  try {
@@ -9961,7 +9835,7 @@ function readCache2() {
9961
9835
  }
9962
9836
  function writeCache2(cache) {
9963
9837
  try {
9964
- mkdirSync6(join8(homedir6(), ".okx"), { recursive: true });
9838
+ mkdirSync6(join7(homedir5(), ".okx"), { recursive: true });
9965
9839
  writeFileSync5(CACHE_FILE, JSON.stringify(cache, null, 2), "utf-8");
9966
9840
  } catch {
9967
9841
  }
@@ -10131,13 +10005,13 @@ function findMsStoreClaudePath() {
10131
10005
  }
10132
10006
  function getConfigPath(client) {
10133
10007
  const home = os3.homedir();
10134
- const platform3 = process.platform;
10008
+ const platform2 = process.platform;
10135
10009
  switch (client) {
10136
10010
  case "claude-desktop":
10137
- if (platform3 === "win32") {
10011
+ if (platform2 === "win32") {
10138
10012
  return findMsStoreClaudePath() ?? path3.join(appData(), "Claude", CLAUDE_CONFIG_FILE);
10139
10013
  }
10140
- if (platform3 === "darwin") {
10014
+ if (platform2 === "darwin") {
10141
10015
  return path3.join(home, "Library", "Application Support", "Claude", CLAUDE_CONFIG_FILE);
10142
10016
  }
10143
10017
  return path3.join(process.env.XDG_CONFIG_HOME ?? path3.join(home, ".config"), "Claude", CLAUDE_CONFIG_FILE);
@@ -10258,7 +10132,7 @@ function getPlatformDir() {
10258
10132
  return map[`${p}-${a}`] ?? null;
10259
10133
  }
10260
10134
  function getBinaryName() {
10261
- return platform() === "win32" ? "okx-doh-resolver.exe" : "okx-doh-resolver";
10135
+ return platform() === "win32" ? "okx-pilot.exe" : "okx-pilot";
10262
10136
  }
10263
10137
  function hashFile(filePath) {
10264
10138
  const buf = readFileSync7(filePath);
@@ -10379,7 +10253,7 @@ async function installDohBinary(destPath, sources = CDN_SOURCES, onProgress) {
10379
10253
  if (earlyResult) return earlyResult;
10380
10254
  const platformDir = getPlatformDir();
10381
10255
  const binaryName = getBinaryName();
10382
- const resolvedDest = destPath ?? join10(homedir8(), ".okx", "bin", binaryName);
10256
+ const resolvedDest = destPath ?? join9(homedir7(), ".okx", "bin", binaryName);
10383
10257
  const tmpPath = resolvedDest + ".tmp";
10384
10258
  mkdirSync8(dirname6(resolvedDest), { recursive: true });
10385
10259
  const localHash = existsSync6(resolvedDest) ? hashFile(resolvedDest) : null;
@@ -10502,224 +10376,16 @@ function downloadText(url, timeoutMs) {
10502
10376
  })
10503
10377
  );
10504
10378
  }
10505
- var AUTH_CDN_PATH_PREFIX = "/upgradeapp/tools/oauth";
10506
- function getAuthBinaryName() {
10507
- return platform2() === "win32" ? "okx-auth.exe" : "okx-auth";
10508
- }
10509
- function getAuthStatus(binaryPath, opts) {
10510
- const resolvedPath = binaryPath ?? getAuthBinaryPath();
10511
- const platformDir = getPlatformDir();
10512
- if (!existsSync7(resolvedPath)) {
10513
- return { binaryPath: resolvedPath, exists: false, platform: platformDir };
10514
- }
10515
- if (opts?.skipHash) {
10516
- return { binaryPath: resolvedPath, exists: true, platform: platformDir };
10517
- }
10518
- const { size, sha256 } = hashFile(resolvedPath);
10519
- return { binaryPath: resolvedPath, exists: true, platform: platformDir, fileSize: size, sha256 };
10520
- }
10521
- async function fetchAuthCdnChecksum(sources = CDN_SOURCES, timeoutMs = DOWNLOAD_TIMEOUT_MS) {
10522
- const platformDir = getPlatformDir();
10523
- if (!platformDir) return null;
10524
- const checksumPath = `${AUTH_CDN_PATH_PREFIX}/${platformDir}/checksum.json`;
10525
- for (const { host, protocol } of sources) {
10526
- try {
10527
- const url = `${protocol}://${host}${checksumPath}`;
10528
- const raw = await downloadText2(url, timeoutMs);
10529
- const data = JSON.parse(raw);
10530
- if (typeof data.sha256 !== "string" || typeof data.size !== "number" || typeof data.target !== "string") {
10531
- continue;
10532
- }
10533
- return { sha256: data.sha256, size: data.size, target: data.target, source: host };
10534
- } catch {
10535
- }
10536
- }
10537
- return null;
10538
- }
10539
- async function fetchAndValidateChecksum2(host, protocol, checksumPath, platformDir, timeoutMs, onProgress) {
10540
- const checksumUrl = `${protocol}://${host}${checksumPath}`;
10541
- onProgress?.(`Fetching checksum from ${host}...`);
10542
- const raw = await downloadText2(checksumUrl, timeoutMs);
10543
- const checksum = JSON.parse(raw);
10544
- if (typeof checksum.sha256 !== "string" || typeof checksum.size !== "number" || typeof checksum.target !== "string") {
10545
- throw new Error("Invalid checksum.json: missing sha256, size, or target");
10546
- }
10547
- if (checksum.target !== platformDir) {
10548
- throw new Error(`Target mismatch: expected ${platformDir}, got ${checksum.target}`);
10549
- }
10550
- return { sha256: checksum.sha256, size: checksum.size, target: checksum.target };
10551
- }
10552
- async function downloadAndVerify2(host, protocol, binaryPath, tmpPath, checksum, timeoutMs, onProgress) {
10553
- const binaryUrl = `${protocol}://${host}${binaryPath}`;
10554
- onProgress?.(`Downloading binary from ${host}...`);
10555
- await download2(binaryUrl, tmpPath, timeoutMs);
10556
- const actual = hashFile(tmpPath);
10557
- if (actual.size !== checksum.size) {
10558
- throw new Error(`Size mismatch: expected ${checksum.size}, got ${actual.size}`);
10559
- }
10560
- if (actual.sha256 !== checksum.sha256) {
10561
- throw new Error(`SHA-256 mismatch: expected ${checksum.sha256}, got ${actual.sha256}`);
10562
- }
10563
- }
10564
- function atomicReplace2(tmpPath, resolvedDest) {
10565
- if (platform2() === "win32") {
10566
- try {
10567
- unlinkSync4(resolvedDest);
10568
- } catch {
10569
- }
10570
- }
10571
- renameSync4(tmpPath, resolvedDest);
10572
- if (platform2() !== "win32") {
10573
- chmodSync2(resolvedDest, 493);
10574
- }
10575
- }
10576
- function installPreChecks2(destPath, sources) {
10577
- if (!destPath && process.env.OKX_AUTH_BIN) {
10578
- return { status: "up-to-date", source: "(env override)" };
10579
- }
10580
- if (!getPlatformDir()) {
10581
- return { status: "failed", error: "Unsupported platform" };
10582
- }
10583
- if (sources.length === 0) {
10584
- return { status: "failed", error: "No CDN sources available" };
10585
- }
10586
- return null;
10587
- }
10588
- function isLocalUpToDate2(localHash, checksum) {
10589
- return localHash !== null && localHash.size === checksum.size && localHash.sha256 === checksum.sha256;
10590
- }
10591
- async function installAuthBinary(destPath, sources = CDN_SOURCES, onProgress) {
10592
- const earlyResult = installPreChecks2(destPath, sources);
10593
- if (earlyResult) return earlyResult;
10594
- const platformDir = getPlatformDir();
10595
- const binaryName = getAuthBinaryName();
10596
- const resolvedDest = destPath ?? join11(homedir9(), ".okx", "bin", binaryName);
10597
- const tmpPath = resolvedDest + ".tmp";
10598
- mkdirSync9(dirname7(resolvedDest), { recursive: true });
10599
- const localHash = existsSync7(resolvedDest) ? hashFile(resolvedDest) : null;
10600
- const checksumPath = `${AUTH_CDN_PATH_PREFIX}/${platformDir}/checksum.json`;
10601
- const binaryPath = `${AUTH_CDN_PATH_PREFIX}/${platformDir}/${binaryName}`;
10602
- const errors = [];
10603
- for (const { host, protocol } of sources) {
10604
- try {
10605
- const checksum = await fetchAndValidateChecksum2(
10606
- host,
10607
- protocol,
10608
- checksumPath,
10609
- platformDir,
10610
- DOWNLOAD_TIMEOUT_MS,
10611
- onProgress
10612
- );
10613
- if (isLocalUpToDate2(localHash, checksum)) {
10614
- onProgress?.("Already up to date (checksum match)");
10615
- return { status: "up-to-date", source: host };
10616
- }
10617
- await downloadAndVerify2(host, protocol, binaryPath, tmpPath, checksum, DOWNLOAD_TIMEOUT_MS, onProgress);
10618
- atomicReplace2(tmpPath, resolvedDest);
10619
- onProgress?.(`Downloaded and verified from ${host}`);
10620
- return { status: "installed", source: host };
10621
- } catch (err) {
10622
- try {
10623
- unlinkSync4(tmpPath);
10624
- } catch {
10625
- }
10626
- const msg = err instanceof Error ? err.message : String(err);
10627
- errors.push(`${host}: ${msg}`);
10628
- onProgress?.(`${host} failed: ${msg}`);
10629
- }
10630
- }
10631
- return { status: "failed", error: `All CDN sources failed:
10632
- ${errors.join("\n")}` };
10633
- }
10634
- function removeAuthBinary(binaryPath) {
10635
- const resolvedPath = binaryPath ?? getAuthBinaryPath();
10636
- try {
10637
- unlinkSync4(resolvedPath);
10638
- return { status: "removed" };
10639
- } catch (err) {
10640
- if (err.code === "ENOENT") {
10641
- return { status: "not-found" };
10642
- }
10643
- const msg = err instanceof Error ? err.message : String(err);
10644
- throw new Error(`Failed to remove ${resolvedPath}: ${msg}`);
10645
- }
10646
- }
10647
- function isRedirect2(statusCode) {
10648
- return statusCode !== void 0 && statusCode >= 300 && statusCode < 400;
10649
- }
10650
- function validateRedirect2(res, requestUrl, redirectCount, maxRedirects) {
10651
- if (redirectCount > maxRedirects) {
10652
- throw new Error(`Too many redirects (${maxRedirects})`);
10653
- }
10654
- const location = res.headers.location;
10655
- if (requestUrl.startsWith("https") && !location.startsWith("https")) {
10656
- throw new Error("Refused HTTPS \u2192 HTTP redirect downgrade");
10657
- }
10658
- return location;
10659
- }
10660
- function fetchResponse2(url, timeoutMs) {
10661
- return new Promise((resolve3, reject) => {
10662
- let redirects = 0;
10663
- const maxRedirects = 5;
10664
- function doRequest(requestUrl) {
10665
- const reqFn = requestUrl.startsWith("https") ? httpsGet2 : httpGet2;
10666
- const req = reqFn(requestUrl, { timeout: timeoutMs }, (res) => {
10667
- if (isRedirect2(res.statusCode) && res.headers.location) {
10668
- redirects++;
10669
- try {
10670
- const location = validateRedirect2(res, requestUrl, redirects, maxRedirects);
10671
- res.resume();
10672
- doRequest(location);
10673
- } catch (err) {
10674
- reject(err);
10675
- }
10676
- return;
10677
- }
10678
- if (res.statusCode !== 200) {
10679
- reject(new Error(`HTTP ${res.statusCode ?? "unknown"}`));
10680
- return;
10681
- }
10682
- resolve3(res);
10683
- });
10684
- req.on("error", reject);
10685
- req.on("timeout", () => {
10686
- req.destroy();
10687
- reject(new Error("Download timed out"));
10688
- });
10689
- }
10690
- doRequest(url);
10691
- });
10692
- }
10693
- function download2(url, destPath, timeoutMs) {
10694
- return fetchResponse2(url, timeoutMs).then(
10695
- (res) => new Promise((resolve3, reject) => {
10696
- const file = createWriteStream3(destPath);
10697
- res.pipe(file);
10698
- file.on("finish", () => file.close(() => resolve3()));
10699
- file.on("error", (err) => {
10700
- try {
10701
- unlinkSync4(destPath);
10702
- } catch {
10703
- }
10704
- reject(err);
10705
- });
10706
- })
10707
- );
10708
- }
10709
- function downloadText2(url, timeoutMs) {
10710
- return fetchResponse2(url, timeoutMs).then(
10711
- (res) => new Promise((resolve3, reject) => {
10712
- const chunks = [];
10713
- res.on("data", (chunk) => chunks.push(chunk));
10714
- res.on("end", () => resolve3(Buffer.concat(chunks).toString("utf8")));
10715
- res.on("error", reject);
10716
- })
10717
- );
10718
- }
10719
10379
 
10720
- // src/commands/auth.ts
10721
- import { spawn as spawn2 } from "child_process";
10722
- import readline from "readline";
10380
+ // src/commands/diagnose.ts
10381
+ import dns from "dns/promises";
10382
+ import net from "net";
10383
+ import os5 from "os";
10384
+ import tls from "tls";
10385
+
10386
+ // src/commands/diagnose-utils.ts
10387
+ import fs4 from "fs";
10388
+ import { createRequire } from "module";
10723
10389
 
10724
10390
  // src/formatter.ts
10725
10391
  import { EOL } from "os";
@@ -10810,249 +10476,7 @@ function markFailedIfSCodeError(data) {
10810
10476
  }
10811
10477
  }
10812
10478
 
10813
- // src/commands/auth.ts
10814
- function runOkxAuth(args) {
10815
- const binPath = getAuthBinaryPath();
10816
- return new Promise((resolve3, reject) => {
10817
- const child = spawn2(binPath, args, {
10818
- stdio: "inherit"
10819
- });
10820
- child.on("error", (err) => {
10821
- reject(new Error(`Failed to spawn okx-auth: ${err.message}`));
10822
- });
10823
- child.on("close", (code) => {
10824
- resolve3(code ?? 1);
10825
- });
10826
- });
10827
- }
10828
- function runOkxAuthCapture(args) {
10829
- const binPath = getAuthBinaryPath();
10830
- return new Promise((resolve3, reject) => {
10831
- const child = spawn2(binPath, args, {
10832
- stdio: ["inherit", "pipe", "inherit"]
10833
- });
10834
- const chunks = [];
10835
- child.stdout.on("data", (chunk) => chunks.push(chunk));
10836
- child.on("error", (err) => {
10837
- reject(new Error(`Failed to spawn okx-auth: ${err.message}`));
10838
- });
10839
- child.on("close", (code) => {
10840
- resolve3({
10841
- code: code ?? 1,
10842
- stdout: Buffer.concat(chunks).toString("utf-8")
10843
- });
10844
- });
10845
- });
10846
- }
10847
- async function cmdAuthLogin(args) {
10848
- const cliArgs = ["login"];
10849
- if (args.site) cliArgs.push("--site", args.site);
10850
- if (args.manual) cliArgs.push("--manual");
10851
- const code = await runOkxAuth(cliArgs);
10852
- if (code !== 0) {
10853
- process.exitCode = code;
10854
- }
10855
- }
10856
- async function cmdAuthLogout() {
10857
- const code = await runOkxAuth(["logout"]);
10858
- if (code !== 0) {
10859
- process.exitCode = code;
10860
- }
10861
- }
10862
- async function cmdAuthStatus(args) {
10863
- const cliArgs = ["status"];
10864
- if (args.json) cliArgs.push("--json");
10865
- const result = await runOkxAuthCapture(cliArgs);
10866
- if (result.stdout) {
10867
- process.stdout.write(result.stdout);
10868
- }
10869
- if (result.code !== 0) {
10870
- process.exitCode = result.code;
10871
- }
10872
- }
10873
- function resolveChecksumMatch(local, cdnChecksum, cdnError) {
10874
- if (!local.exists) return "not-installed";
10875
- if (cdnError || !cdnChecksum) return "unavailable";
10876
- if (cdnChecksum.sha256 === local.sha256) return "match";
10877
- return "mismatch";
10878
- }
10879
- function checksumMatchLabel(match) {
10880
- if (match === "match") return "\u2713 match";
10881
- if (match === "mismatch") return "\u2717 mismatch (update available)";
10882
- return "CDN unreachable";
10883
- }
10884
- function formatBytes(bytes) {
10885
- if (bytes < 1024) return `${bytes} B`;
10886
- if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
10887
- return `${(bytes / (1024 * 1024)).toFixed(2)} MB`;
10888
- }
10889
- async function cmdAuthInstallStatus(json) {
10890
- const local = getAuthStatus();
10891
- let cdnChecksum = null;
10892
- let cdnError = null;
10893
- if (local.exists) {
10894
- try {
10895
- cdnChecksum = await fetchAuthCdnChecksum(void 0, 5e3);
10896
- } catch (err) {
10897
- cdnError = err instanceof Error ? err.message : String(err);
10898
- }
10899
- }
10900
- const checksumMatch = resolveChecksumMatch(local, cdnChecksum, cdnError);
10901
- if (json) {
10902
- outputLine(
10903
- JSON.stringify({
10904
- binaryPath: local.binaryPath,
10905
- exists: local.exists,
10906
- platform: local.platform,
10907
- fileSize: local.fileSize ?? null,
10908
- sha256: local.sha256 ?? null,
10909
- cdnMatch: checksumMatch,
10910
- cdnSha256: cdnChecksum?.sha256 ?? null,
10911
- cdnSource: cdnChecksum?.source ?? null
10912
- })
10913
- );
10914
- return;
10915
- }
10916
- outputLine("");
10917
- outputLine(" okx-auth Binary Status");
10918
- outputLine(" " + "\u2500".repeat(40));
10919
- outputLine(` Binary path : ${local.binaryPath}`);
10920
- outputLine(` Installed : ${local.exists ? "yes" : "no"}`);
10921
- outputLine(` Platform : ${local.platform ?? "(unsupported)"}`);
10922
- if (local.exists) {
10923
- outputLine(` File size : ${formatBytes(local.fileSize)}`);
10924
- outputLine(` SHA-256 : ${local.sha256 ?? "(unknown)"}`);
10925
- outputLine(` CDN check : ${checksumMatchLabel(checksumMatch)}`);
10926
- if (cdnChecksum) {
10927
- outputLine(` CDN source : ${cdnChecksum.source}`);
10928
- }
10929
- }
10930
- outputLine("");
10931
- }
10932
- async function cmdAuthInstall(json) {
10933
- const messages2 = [];
10934
- const onProgress = (msg) => {
10935
- if (!json) {
10936
- outputLine(` ${msg}`);
10937
- }
10938
- messages2.push(msg);
10939
- };
10940
- if (!json) {
10941
- outputLine("");
10942
- outputLine(" Installing okx-auth...");
10943
- }
10944
- const result = await installAuthBinary(void 0, void 0, onProgress);
10945
- if (json) {
10946
- outputLine(JSON.stringify({ status: result.status, source: result.source ?? null, error: result.error ?? null, messages: messages2 }));
10947
- if (result.status === "failed") {
10948
- process.exitCode = 1;
10949
- }
10950
- return;
10951
- }
10952
- if (result.status === "installed") {
10953
- outputLine(` \u2713 okx-auth installed successfully (${result.source ?? ""})`);
10954
- } else if (result.status === "up-to-date") {
10955
- outputLine(" \u2713 okx-auth is already up to date");
10956
- } else {
10957
- errorLine(` \u2717 Installation failed: ${result.error ?? "unknown error"}`);
10958
- errorLine(" Hint: check network connectivity or try again later");
10959
- process.exitCode = 1;
10960
- }
10961
- outputLine("");
10962
- }
10963
- async function cmdAuthRemove(force, json) {
10964
- const local = getAuthStatus(void 0, { skipHash: true });
10965
- if (!local.exists) {
10966
- if (json) {
10967
- outputLine(JSON.stringify({ status: "not-installed" }));
10968
- } else {
10969
- outputLine(" okx-auth is not installed.");
10970
- }
10971
- return;
10972
- }
10973
- if (!force) {
10974
- if (!process.stdin.isTTY) {
10975
- errorLine(" Error: stdin is not a TTY. Use --force to skip confirmation.");
10976
- process.exitCode = 1;
10977
- return;
10978
- }
10979
- const confirmed = await askConfirmation(
10980
- ` Remove okx-auth at ${local.binaryPath}? [y/N] `
10981
- );
10982
- if (!confirmed) {
10983
- outputLine(" Cancelled.");
10984
- return;
10985
- }
10986
- }
10987
- let result;
10988
- try {
10989
- result = removeAuthBinary();
10990
- } catch (err) {
10991
- const msg = err instanceof Error ? err.message : String(err);
10992
- if (json) {
10993
- outputLine(JSON.stringify({ status: "failed", error: msg }));
10994
- } else {
10995
- errorLine(` \u2717 Failed to remove: ${msg}`);
10996
- }
10997
- process.exitCode = 1;
10998
- return;
10999
- }
11000
- if (json) {
11001
- outputLine(JSON.stringify({ status: result.status, path: local.binaryPath }));
11002
- return;
11003
- }
11004
- if (result.status === "removed") {
11005
- outputLine(` \u2713 Removed: ${local.binaryPath}`);
11006
- } else {
11007
- outputLine(" okx-auth is not installed.");
11008
- }
11009
- }
11010
- function askConfirmation(prompt2) {
11011
- return new Promise((resolve3) => {
11012
- const rl = readline.createInterface({
11013
- input: process.stdin,
11014
- output: process.stdout
11015
- });
11016
- rl.question(prompt2, (answer) => {
11017
- rl.close();
11018
- resolve3(answer.trim().toLowerCase() === "y");
11019
- });
11020
- });
11021
- }
11022
- function handleAuthCommand(action, _rest, v) {
11023
- const site = v.site;
11024
- const json = v.json;
11025
- const manual = v.manual;
11026
- const force = v.force;
11027
- switch (action) {
11028
- case "login":
11029
- return cmdAuthLogin({ site, manual });
11030
- case "logout":
11031
- return cmdAuthLogout();
11032
- case "status":
11033
- return cmdAuthStatus({ json });
11034
- case "install":
11035
- return cmdAuthInstall(json ?? false);
11036
- case "install-status":
11037
- return cmdAuthInstallStatus(json ?? false);
11038
- case "remove":
11039
- return cmdAuthRemove(force ?? false, json ?? false);
11040
- default:
11041
- errorLine(`Unknown auth command: ${action}`);
11042
- errorLine("Available: login, logout, status, install, install-status, remove");
11043
- process.exitCode = 1;
11044
- }
11045
- }
11046
-
11047
- // src/commands/diagnose.ts
11048
- import dns from "dns/promises";
11049
- import net from "net";
11050
- import os5 from "os";
11051
- import tls from "tls";
11052
-
11053
10479
  // src/commands/diagnose-utils.ts
11054
- import fs4 from "fs";
11055
- import { createRequire } from "module";
11056
10480
  var _require = createRequire(import.meta.url);
11057
10481
  function readCliVersion() {
11058
10482
  for (const rel of ["../package.json", "../../package.json"]) {
@@ -11138,7 +10562,7 @@ function sanitize2(value) {
11138
10562
  import fs5 from "fs";
11139
10563
  import path4 from "path";
11140
10564
  import os4 from "os";
11141
- import { spawnSync, spawn as spawn3 } from "child_process";
10565
+ import { spawnSync, spawn } from "child_process";
11142
10566
  import { createRequire as createRequire2 } from "module";
11143
10567
  import { fileURLToPath } from "url";
11144
10568
  var _require2 = createRequire2(import.meta.url);
@@ -11472,7 +10896,7 @@ async function checkStdioHandshake(entryPath, report) {
11472
10896
  clearTimeout(timer);
11473
10897
  resolve3(passed);
11474
10898
  };
11475
- const child = spawn3(process.execPath, [entryPath], {
10899
+ const child = spawn(process.execPath, [entryPath], {
11476
10900
  stdio: ["pipe", "pipe", "pipe"],
11477
10901
  env: { ...process.env }
11478
10902
  });
@@ -11591,7 +11015,7 @@ async function cmdDiagnoseMcp(options = {}) {
11591
11015
 
11592
11016
  // src/commands/diagnose.ts
11593
11017
  var CLI_VERSION = readCliVersion();
11594
- var GIT_HASH = true ? "1431fd4" : "dev";
11018
+ var GIT_HASH = true ? "e9764c9" : "dev";
11595
11019
  function maskKey2(key) {
11596
11020
  if (!key) return "(not set)";
11597
11021
  if (key.length <= 8) return "****";
@@ -11927,13 +11351,13 @@ async function runCliChecks(config, profile, outputPath) {
11927
11351
 
11928
11352
  // src/commands/upgrade.ts
11929
11353
  import { spawnSync as spawnSync2 } from "child_process";
11930
- import { readFileSync as readFileSync8, writeFileSync as writeFileSync7, mkdirSync as mkdirSync10 } from "fs";
11931
- import { dirname as dirname8, join as join12 } from "path";
11932
- import { homedir as homedir10 } from "os";
11354
+ import { readFileSync as readFileSync8, writeFileSync as writeFileSync7, mkdirSync as mkdirSync9 } from "fs";
11355
+ import { dirname as dirname7, join as join10 } from "path";
11356
+ import { homedir as homedir8 } from "os";
11933
11357
  var PACKAGES = ["@okx_ai/okx-trade-mcp", "@okx_ai/okx-trade-cli"];
11934
- var CACHE_FILE2 = join12(homedir10(), ".okx", "last_check");
11358
+ var CACHE_FILE2 = join10(homedir8(), ".okx", "last_check");
11935
11359
  var THROTTLE_MS = 12 * 60 * 60 * 1e3;
11936
- var NPM_BIN = join12(dirname8(process.execPath), process.platform === "win32" ? "npm.cmd" : "npm");
11360
+ var NPM_BIN = join10(dirname7(process.execPath), process.platform === "win32" ? "npm.cmd" : "npm");
11937
11361
  function readLastCheck() {
11938
11362
  try {
11939
11363
  return parseInt(readFileSync8(CACHE_FILE2, "utf-8").trim(), 10) || 0;
@@ -11943,7 +11367,7 @@ function readLastCheck() {
11943
11367
  }
11944
11368
  function writeLastCheck() {
11945
11369
  try {
11946
- mkdirSync10(join12(homedir10(), ".okx"), { recursive: true });
11370
+ mkdirSync9(join10(homedir8(), ".okx"), { recursive: true });
11947
11371
  writeFileSync7(CACHE_FILE2, String(Math.floor(Date.now() / 1e3)), "utf-8");
11948
11372
  } catch {
11949
11373
  }
@@ -12915,29 +12339,29 @@ var CLI_REGISTRY = {
12915
12339
  commands: {
12916
12340
  latest: {
12917
12341
  toolName: "news_get_latest",
12918
- usage: "okx news latest [--coins BTC,ETH] [--lang zh_CN] [--limit 20]"
12342
+ usage: "okx news latest [--coins BTC,ETH] [--platform blockbeats] [--lang zh-CN] [--limit 20]"
12919
12343
  },
12920
12344
  important: {
12921
12345
  toolName: "news_get_latest",
12922
- usage: "okx news important [--coins BTC,ETH] [--lang zh_CN] [--limit 20]",
12346
+ usage: "okx news important [--coins BTC,ETH] [--lang zh-CN] [--limit 20]",
12923
12347
  description: "Get important/high-impact crypto news"
12924
12348
  },
12925
12349
  "by-coin": {
12926
12350
  toolName: "news_get_by_coin",
12927
- usage: "okx news by-coin --coins BTC [--importance high] [--lang zh_CN]"
12351
+ usage: "okx news by-coin --coins BTC [--importance high] [--platform blockbeats] [--lang zh-CN]"
12928
12352
  },
12929
12353
  search: {
12930
12354
  toolName: "news_search",
12931
- usage: "okx news search --keyword <term> [--coins BTC] [--sentiment bullish] [--lang zh_CN]"
12355
+ usage: "okx news search --keyword <term> [--coins BTC] [--sentiment bullish] [--platform blockbeats] [--lang zh-CN]"
12932
12356
  },
12933
12357
  detail: {
12934
12358
  toolName: "news_get_detail",
12935
- usage: "okx news detail <id> [--lang zh_CN]"
12359
+ usage: "okx news detail <id> [--lang zh-CN]"
12936
12360
  },
12937
- domains: {
12361
+ platforms: {
12938
12362
  toolName: "news_get_domains",
12939
- usage: "okx news domains",
12940
- description: "List available news source domains"
12363
+ usage: "okx news platforms",
12364
+ description: "List available news platforms"
12941
12365
  },
12942
12366
  "coin-sentiment": {
12943
12367
  toolName: "news_get_coin_sentiment",
@@ -12950,7 +12374,7 @@ var CLI_REGISTRY = {
12950
12374
  },
12951
12375
  "by-sentiment": {
12952
12376
  toolName: "news_search",
12953
- usage: "okx news by-sentiment --sentiment bullish [--coins BTC] [--sort-by latest]",
12377
+ usage: "okx news by-sentiment --sentiment bullish [--coins BTC] [--importance high] [--platform <source>] [--sort-by latest] [--begin <ms>] [--end <ms>]",
12954
12378
  description: "Browse news filtered by sentiment direction"
12955
12379
  },
12956
12380
  "sentiment-rank": {
@@ -13158,6 +12582,7 @@ async function cmdNewsLatest(run, opts) {
13158
12582
  const result = await run("news_get_latest", {
13159
12583
  coins: opts.coins,
13160
12584
  importance: opts.importance,
12585
+ platform: opts.platform,
13161
12586
  begin: opts.begin,
13162
12587
  end: opts.end,
13163
12588
  language: opts.language,
@@ -13184,6 +12609,7 @@ async function cmdNewsImportant(run, opts) {
13184
12609
  const result = await run("news_get_latest", {
13185
12610
  coins: opts.coins,
13186
12611
  importance: "high",
12612
+ platform: opts.platform,
13187
12613
  begin: opts.begin,
13188
12614
  end: opts.end,
13189
12615
  language: opts.language,
@@ -13208,6 +12634,7 @@ async function cmdNewsByCoin(run, coins, opts) {
13208
12634
  const result = await run("news_get_by_coin", {
13209
12635
  coins,
13210
12636
  importance: opts.importance,
12637
+ platform: opts.platform,
13211
12638
  begin: opts.begin,
13212
12639
  end: opts.end,
13213
12640
  language: opts.language,
@@ -13233,6 +12660,7 @@ async function cmdNewsSearch(run, keyword, opts) {
13233
12660
  keyword: keyword || void 0,
13234
12661
  coins: opts.coins,
13235
12662
  importance: opts.importance,
12663
+ platform: opts.platform,
13236
12664
  sentiment: opts.sentiment,
13237
12665
  sortBy: opts.sortBy,
13238
12666
  begin: opts.begin,
@@ -13285,12 +12713,12 @@ async function cmdNewsDetail(run, id, opts) {
13285
12713
  content
13286
12714
  });
13287
12715
  }
13288
- async function cmdNewsDomains(run, opts) {
12716
+ async function cmdNewsPlatforms(run, opts) {
13289
12717
  const result = await run("news_get_domains", {});
13290
12718
  const raw = getData(result);
13291
12719
  const items = raw?.[0]?.["platform"] ?? [];
13292
12720
  if (opts.json) return printJson(items);
13293
- outputLine("Available news source domains:");
12721
+ outputLine("Available news platforms:");
13294
12722
  items.forEach((d) => outputLine(` ${d}`));
13295
12723
  }
13296
12724
  async function cmdNewsCoinSentiment(run, coins, opts) {
@@ -13364,7 +12792,7 @@ async function cmdNewsSentimentRank(run, opts) {
13364
12792
  }
13365
12793
 
13366
12794
  // src/config/loader.ts
13367
- async function loadProfileConfig(opts) {
12795
+ function loadProfileConfig(opts) {
13368
12796
  return loadConfig({
13369
12797
  profile: opts.profile,
13370
12798
  modules: opts.modules,
@@ -13672,6 +13100,7 @@ var CLI_OPTIONS = {
13672
13100
  coins: { type: "string" },
13673
13101
  sentiment: { type: "string" },
13674
13102
  importance: { type: "string" },
13103
+ platform: { type: "string" },
13675
13104
  keyword: { type: "string" },
13676
13105
  "detail-lvl": { type: "string" },
13677
13106
  period: { type: "string" },
@@ -13682,9 +13111,6 @@ var CLI_OPTIONS = {
13682
13111
  dir: { type: "string" },
13683
13112
  page: { type: "string" },
13684
13113
  format: { type: "string" },
13685
- // auth
13686
- site: { type: "string" },
13687
- manual: { type: "boolean", default: false },
13688
13114
  // event contract
13689
13115
  underlying: { type: "string" },
13690
13116
  seriesId: { type: "string" },
@@ -16699,14 +16125,14 @@ async function cmdDcdQuoteAndBuy(run, opts) {
16699
16125
  }
16700
16126
 
16701
16127
  // src/commands/skill.ts
16702
- import { tmpdir, homedir as homedir12 } from "os";
16703
- import { join as join14, dirname as dirname9 } from "path";
16704
- import { mkdirSync as mkdirSync11, rmSync, existsSync as existsSync9, copyFileSync as copyFileSync2 } from "fs";
16128
+ import { tmpdir, homedir as homedir10 } from "os";
16129
+ import { join as join12, dirname as dirname8 } from "path";
16130
+ import { mkdirSync as mkdirSync10, rmSync, existsSync as existsSync8, copyFileSync as copyFileSync2 } from "fs";
16705
16131
  import { execFileSync as execFileSync2 } from "child_process";
16706
16132
  import { randomUUID as randomUUID2 } from "crypto";
16707
16133
  function resolveNpx() {
16708
- const sibling = join14(dirname9(process.execPath), "npx");
16709
- if (existsSync9(sibling)) return sibling;
16134
+ const sibling = join12(dirname8(process.execPath), "npx");
16135
+ if (existsSync8(sibling)) return sibling;
16710
16136
  return "npx";
16711
16137
  }
16712
16138
  var THIRD_PARTY_INSTALL_NOTICE = "Note: This skill was created by a third-party developer, not by OKX. Review SKILL.md before use.";
@@ -16759,13 +16185,13 @@ async function cmdSkillCategories(run, json) {
16759
16185
  outputLine("");
16760
16186
  }
16761
16187
  async function cmdSkillAdd(name, config, json) {
16762
- const tmpBase = join14(tmpdir(), `okx-skill-${randomUUID2()}`);
16763
- mkdirSync11(tmpBase, { recursive: true });
16188
+ const tmpBase = join12(tmpdir(), `okx-skill-${randomUUID2()}`);
16189
+ mkdirSync10(tmpBase, { recursive: true });
16764
16190
  try {
16765
16191
  outputLine(`Downloading ${name}...`);
16766
16192
  const client = new OkxRestClient(config);
16767
16193
  const zipPath = await downloadSkillZip(client, name, tmpBase);
16768
- const contentDir = await extractSkillZip(zipPath, join14(tmpBase, "content"));
16194
+ const contentDir = await extractSkillZip(zipPath, join12(tmpBase, "content"));
16769
16195
  const meta = readMetaJson(contentDir);
16770
16196
  validateSkillMdExists(contentDir);
16771
16197
  outputLine("Installing to detected agents...");
@@ -16775,7 +16201,7 @@ async function cmdSkillAdd(name, config, json) {
16775
16201
  timeout: 6e4
16776
16202
  });
16777
16203
  } catch (e) {
16778
- const savedZip = join14(process.cwd(), `${name}.zip`);
16204
+ const savedZip = join12(process.cwd(), `${name}.zip`);
16779
16205
  try {
16780
16206
  copyFileSync2(zipPath, savedZip);
16781
16207
  } catch {
@@ -16814,7 +16240,7 @@ function cmdSkillRemove(name, json) {
16814
16240
  timeout: 6e4
16815
16241
  });
16816
16242
  } catch {
16817
- const agentsPath = join14(homedir12(), ".agents", "skills", name);
16243
+ const agentsPath = join12(homedir10(), ".agents", "skills", name);
16818
16244
  try {
16819
16245
  rmSync(agentsPath, { recursive: true, force: true });
16820
16246
  } catch {
@@ -16888,14 +16314,14 @@ function printSkillInstallResult(meta, json) {
16888
16314
  }
16889
16315
 
16890
16316
  // src/commands/doh.ts
16891
- import readline2 from "readline";
16892
- function resolveChecksumMatch2(local, cdnChecksum, cdnError) {
16317
+ import readline from "readline";
16318
+ function resolveChecksumMatch(local, cdnChecksum, cdnError) {
16893
16319
  if (!local.exists) return "not-installed";
16894
16320
  if (cdnError || !cdnChecksum) return "unavailable";
16895
16321
  if (cdnChecksum.sha256 === local.sha256) return "match";
16896
16322
  return "mismatch";
16897
16323
  }
16898
- function checksumMatchLabel2(match) {
16324
+ function checksumMatchLabel(match) {
16899
16325
  if (match === "match") return "\u2713 match";
16900
16326
  if (match === "mismatch") return "\u2717 mismatch (update available)";
16901
16327
  return "CDN unreachable";
@@ -16908,9 +16334,9 @@ function formatStatusText(local, checksumMatch, cdnChecksum, runtimeMode) {
16908
16334
  outputLine(` Installed : ${local.exists ? "yes" : "no"}`);
16909
16335
  outputLine(` Platform : ${local.platform ?? "(unsupported)"}`);
16910
16336
  if (local.exists) {
16911
- outputLine(` File size : ${formatBytes2(local.fileSize)}`);
16337
+ outputLine(` File size : ${formatBytes(local.fileSize)}`);
16912
16338
  outputLine(` SHA-256 : ${local.sha256 ?? "(unknown)"}`);
16913
- outputLine(` CDN check : ${checksumMatchLabel2(checksumMatch)}`);
16339
+ outputLine(` CDN check : ${checksumMatchLabel(checksumMatch)}`);
16914
16340
  if (cdnChecksum) {
16915
16341
  outputLine(` CDN source : ${cdnChecksum.source}`);
16916
16342
  }
@@ -16937,7 +16363,7 @@ async function cmdDohStatus(json, binaryPath) {
16937
16363
  cdnError = err instanceof Error ? err.message : String(err);
16938
16364
  }
16939
16365
  }
16940
- const checksumMatch = resolveChecksumMatch2(local, cdnChecksum, cdnError);
16366
+ const checksumMatch = resolveChecksumMatch(local, cdnChecksum, cdnError);
16941
16367
  if (json) {
16942
16368
  outputLine(
16943
16369
  JSON.stringify({
@@ -17003,7 +16429,7 @@ async function cmdDohRemove(force, json, binaryPath) {
17003
16429
  process.exitCode = 1;
17004
16430
  return;
17005
16431
  }
17006
- const confirmed = await askConfirmation2(
16432
+ const confirmed = await askConfirmation(
17007
16433
  ` Remove DoH resolver at ${local.binaryPath}? [y/N] `
17008
16434
  );
17009
16435
  if (!confirmed) {
@@ -17022,14 +16448,14 @@ async function cmdDohRemove(force, json, binaryPath) {
17022
16448
  outputLine(" DoH resolver is not installed.");
17023
16449
  }
17024
16450
  }
17025
- function formatBytes2(bytes) {
16451
+ function formatBytes(bytes) {
17026
16452
  if (bytes < 1024) return `${bytes} B`;
17027
16453
  if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
17028
16454
  return `${(bytes / (1024 * 1024)).toFixed(2)} MB`;
17029
16455
  }
17030
- function askConfirmation2(prompt2) {
16456
+ function askConfirmation(prompt2) {
17031
16457
  return new Promise((resolve3) => {
17032
- const rl = readline2.createInterface({
16458
+ const rl = readline.createInterface({
17033
16459
  input: process.stdin,
17034
16460
  output: process.stdout
17035
16461
  });
@@ -17486,7 +16912,7 @@ async function cmdEventCancel(run, opts) {
17486
16912
  // src/index.ts
17487
16913
  var _require3 = createRequire3(import.meta.url);
17488
16914
  var CLI_VERSION2 = _require3("../package.json").version;
17489
- var GIT_HASH2 = true ? "1431fd4" : "dev";
16915
+ var GIT_HASH2 = true ? "e9764c9" : "dev";
17490
16916
  function handleDohCommand(action, json, force, binaryPath) {
17491
16917
  if (action === "status") return cmdDohStatus(json, binaryPath);
17492
16918
  if (action === "install") return cmdDohInstall(json, binaryPath);
@@ -18330,21 +17756,22 @@ function handleNewsCommand(run, action, rest, v, json) {
18330
17756
  const limit = v.limit !== void 0 ? Number(v.limit) : void 0;
18331
17757
  const begin = v.begin !== void 0 ? Number(v.begin) : void 0;
18332
17758
  const end = v.end !== void 0 ? Number(v.end) : void 0;
18333
- const language = v.lang ?? "en_US";
17759
+ const language = v.lang ?? "en-US";
18334
17760
  const detailLvl = v["detail-lvl"];
18335
17761
  const after = v.after;
18336
17762
  const period = v.period;
18337
17763
  const points = v.points !== void 0 ? Number(v.points) : 24;
18338
17764
  const sortBy = v["sort-by"];
18339
- const searchOpts = { coins: v.coins, importance: v.importance, sentiment: v.sentiment, sortBy, begin, end, language, detailLvl, limit, after, json };
18340
- const listOpts = { coins: v.coins, importance: v.importance, begin, end, language, detailLvl, limit, after, json };
17765
+ const platform2 = v.platform;
17766
+ const searchOpts = { coins: v.coins, importance: v.importance, platform: platform2, sentiment: v.sentiment, sortBy, begin, end, language, detailLvl, limit, after, json };
17767
+ const listOpts = { coins: v.coins, importance: v.importance, platform: platform2, begin, end, language, detailLvl, limit, after, json };
18341
17768
  const dispatch = {
18342
17769
  latest: () => cmdNewsLatest(run, listOpts),
18343
- important: () => cmdNewsImportant(run, { coins: v.coins, begin, end, language, detailLvl, limit, json }),
18344
- "by-coin": () => cmdNewsByCoin(run, v.coins ?? rest[0], { importance: v.importance, begin, end, language, detailLvl, limit, json }),
17770
+ important: () => cmdNewsImportant(run, { coins: v.coins, platform: platform2, begin, end, language, detailLvl, limit, json }),
17771
+ "by-coin": () => cmdNewsByCoin(run, v.coins ?? rest[0], { importance: v.importance, platform: platform2, begin, end, language, detailLvl, limit, json }),
18345
17772
  search: () => cmdNewsSearch(run, v.keyword ?? rest[0], searchOpts),
18346
17773
  detail: () => cmdNewsDetail(run, rest[0], { language, json }),
18347
- domains: () => cmdNewsDomains(run, { json }),
17774
+ platforms: () => cmdNewsPlatforms(run, { json }),
18348
17775
  "coin-sentiment": () => cmdNewsCoinSentiment(run, v.coins ?? rest[0], { period, json }),
18349
17776
  "coin-trend": () => cmdNewsCoinTrend(run, v.coins ?? rest[0], { period, points, json }),
18350
17777
  // by-sentiment is a convenience wrapper over news_search (no keyword, sentiment filter only)
@@ -18461,7 +17888,7 @@ function wrapRunnerWithLogger(baseRunner, logger, verbose = false) {
18461
17888
  async function runDiagnose(v) {
18462
17889
  let config;
18463
17890
  try {
18464
- config = await loadProfileConfig({ profile: v.profile, demo: v.demo, live: v.live, verbose: v.verbose, userAgent: `okx-trade-cli/${CLI_VERSION2}`, sourceTag: "CLI" });
17891
+ config = loadProfileConfig({ profile: v.profile, demo: v.demo, live: v.live, verbose: v.verbose, userAgent: `okx-trade-cli/${CLI_VERSION2}`, sourceTag: "CLI" });
18465
17892
  } catch {
18466
17893
  }
18467
17894
  return cmdDiagnose(config, v.profile ?? "default", { mcp: v.mcp, cli: v.cli, all: v.all, output: v.output });
@@ -18476,13 +17903,24 @@ function printVersion() {
18476
17903
  }
18477
17904
  }
18478
17905
  function routeManagementCommand(module, action, rest, json, v) {
18479
- if (module === "config") return handleConfigCommand(action, rest, json, v.lang, v.force);
18480
- if (module === "setup") return handleSetupCommand(v);
18481
- if (module === "auth") return handleAuthCommand(action, rest, v);
17906
+ if (module === "config") {
17907
+ const r = handleConfigCommand(action, rest, json, v.lang, v.force);
17908
+ return r ?? true;
17909
+ }
17910
+ if (module === "setup") {
17911
+ handleSetupCommand(v);
17912
+ return true;
17913
+ }
18482
17914
  if (module === "upgrade") return cmdUpgrade(CLI_VERSION2, { beta: v.beta, check: v.check, force: v.force }, json);
18483
- if (module === "doh") return handleDohCommand(action, json, v.force ?? false);
17915
+ if (module === "doh") {
17916
+ const r = handleDohCommand(action, json, v.force ?? false);
17917
+ return r ?? true;
17918
+ }
18484
17919
  if (module === "diagnose") return runDiagnose(v);
18485
- if (module === "list-tools") return cmdListTools(json);
17920
+ if (module === "list-tools") {
17921
+ cmdListTools(json);
17922
+ return true;
17923
+ }
18486
17924
  return void 0;
18487
17925
  }
18488
17926
  async function main() {
@@ -18504,8 +17942,8 @@ async function main() {
18504
17942
  const v = values;
18505
17943
  const json = v.json ?? false;
18506
17944
  const mgmt = routeManagementCommand(module, action, rest, json, v);
18507
- if (mgmt) return mgmt;
18508
- const config = await loadProfileConfig({ profile: v.profile, demo: v.demo, live: v.live, verbose: v.verbose, userAgent: `okx-trade-cli/${CLI_VERSION2}`, sourceTag: "CLI" });
17945
+ if (mgmt !== void 0) return mgmt === true ? void 0 : mgmt;
17946
+ const config = loadProfileConfig({ profile: v.profile, demo: v.demo, live: v.live, verbose: v.verbose, userAgent: `okx-trade-cli/${CLI_VERSION2}`, sourceTag: "CLI" });
18509
17947
  setEnvContext({ demo: config.demo, profile: v.profile ?? "default" });
18510
17948
  setJsonEnvEnabled(v.env ?? false);
18511
17949
  const client = new OkxRestClient(config);