@okx_ai/okx-trade-cli 1.3.0-beta.4 → 1.3.0-beta.5

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
@@ -4,37 +4,25 @@
4
4
  import { createRequire as createRequire3 } from "module";
5
5
 
6
6
  // ../core/dist/index.js
7
- import { Agent, ProxyAgent } from "undici";
8
- import { execFile } from "child_process";
9
- import { homedir } from "os";
10
- import { join } from "path";
11
- import {
12
- readFileSync,
13
- writeFileSync,
14
- mkdirSync,
15
- unlinkSync,
16
- renameSync
17
- } from "fs";
18
- import { homedir as homedir2 } from "os";
19
- import { join as join2, dirname } from "path";
7
+ import { ProxyAgent } from "undici";
20
8
  import { createHmac } from "crypto";
21
9
  import fs from "fs";
22
10
  import path from "path";
23
11
  import os from "os";
24
- import { writeFileSync as writeFileSync2, renameSync as renameSync2, unlinkSync as unlinkSync2, mkdirSync as mkdirSync2 } from "fs";
25
- import { join as join3, resolve, basename, sep } from "path";
12
+ import { writeFileSync, renameSync, unlinkSync, mkdirSync } from "fs";
13
+ import { join, resolve, basename, sep } from "path";
26
14
  import { randomUUID } from "crypto";
27
15
  import yauzl from "yauzl";
28
- import { createWriteStream, mkdirSync as mkdirSync3 } from "fs";
29
- import { resolve as resolve2, dirname as dirname2 } from "path";
30
- import { readFileSync as readFileSync2, existsSync } from "fs";
31
- import { join as join4 } from "path";
32
- import { readFileSync as readFileSync3, writeFileSync as writeFileSync3, mkdirSync as mkdirSync4, existsSync as existsSync2 } from "fs";
33
- import { join as join5, dirname as dirname3 } from "path";
34
- import { homedir as homedir3 } from "os";
35
- import { readFileSync as readFileSync4, writeFileSync as writeFileSync4, mkdirSync as mkdirSync5, existsSync as existsSync3 } from "fs";
36
- import { join as join6, dirname as dirname4 } from "path";
37
- import { homedir as homedir4 } from "os";
16
+ import { createWriteStream, mkdirSync as mkdirSync2 } from "fs";
17
+ import { resolve as resolve2, dirname } from "path";
18
+ import { readFileSync, existsSync } from "fs";
19
+ import { join as join2 } from "path";
20
+ import { readFileSync as readFileSync2, writeFileSync as writeFileSync2, mkdirSync as mkdirSync3, existsSync as existsSync2 } from "fs";
21
+ import { join as join3, dirname as dirname2 } from "path";
22
+ import { homedir } from "os";
23
+ import { readFileSync as readFileSync3, writeFileSync as writeFileSync3, mkdirSync as mkdirSync4, existsSync as existsSync3 } from "fs";
24
+ import { join as join4, dirname as dirname3 } from "path";
25
+ import { homedir as homedir2 } from "os";
38
26
 
39
27
  // ../../node_modules/.pnpm/smol-toml@1.6.0/node_modules/smol-toml/dist/error.js
40
28
  function getLineColFromPtr(string, ptr) {
@@ -863,9 +851,9 @@ function stringify(obj, { maxDepth = 1e3, numbersAsFloat = false } = {}) {
863
851
  }
864
852
 
865
853
  // ../core/dist/index.js
866
- import { readFileSync as readFileSync5, writeFileSync as writeFileSync5, mkdirSync as mkdirSync6, existsSync as existsSync4 } from "fs";
867
- import { join as join7 } from "path";
868
- import { homedir as homedir5 } from "os";
854
+ import { readFileSync as readFileSync4, writeFileSync as writeFileSync4, mkdirSync as mkdirSync5, existsSync as existsSync4 } from "fs";
855
+ import { join as join5 } from "path";
856
+ import { homedir as homedir3 } from "os";
869
857
  import fs2 from "fs";
870
858
  import path2 from "path";
871
859
  import os2 from "os";
@@ -873,123 +861,6 @@ import * as fs3 from "fs";
873
861
  import * as path3 from "path";
874
862
  import * as os3 from "os";
875
863
  import { execFileSync } from "child_process";
876
- var EXEC_TIMEOUT_MS = 3e4;
877
- var DOH_BIN_DIR = join(homedir(), ".okx", "bin");
878
- function getDohBinaryPath() {
879
- if (process.env.OKX_DOH_BINARY_PATH) {
880
- return process.env.OKX_DOH_BINARY_PATH;
881
- }
882
- const ext = process.platform === "win32" ? ".exe" : "";
883
- return join(DOH_BIN_DIR, `okx-doh-resolver${ext}`);
884
- }
885
- function execDohBinary(domain, exclude = [], userAgent) {
886
- const binPath = getDohBinaryPath();
887
- const args = ["--domain", domain];
888
- if (exclude.length > 0) {
889
- args.push("--exclude", exclude.join(","));
890
- }
891
- if (userAgent) {
892
- args.push("--user-agent", userAgent);
893
- }
894
- return new Promise((resolve3) => {
895
- execFile(
896
- binPath,
897
- args,
898
- { timeout: EXEC_TIMEOUT_MS, encoding: "utf-8" },
899
- (error, stdout) => {
900
- if (error) {
901
- resolve3(null);
902
- return;
903
- }
904
- try {
905
- const result = JSON.parse(stdout);
906
- if (result.code === 0 && result.data) {
907
- resolve3(result.data);
908
- } else {
909
- resolve3(null);
910
- }
911
- } catch {
912
- resolve3(null);
913
- }
914
- }
915
- );
916
- });
917
- }
918
- var DOH_CACHE_PATH = join2(homedir2(), ".okx", "doh-node-cache.json");
919
- function readCache(hostname, cachePath = DOH_CACHE_PATH) {
920
- try {
921
- const raw = readFileSync(cachePath, "utf-8");
922
- const file = JSON.parse(raw);
923
- return file[hostname] ?? null;
924
- } catch {
925
- return null;
926
- }
927
- }
928
- function writeCache(hostname, entry, cachePath = DOH_CACHE_PATH) {
929
- try {
930
- const dir = dirname(cachePath);
931
- mkdirSync(dir, { recursive: true });
932
- let file = {};
933
- try {
934
- file = JSON.parse(readFileSync(cachePath, "utf-8"));
935
- } catch {
936
- }
937
- file[hostname] = entry;
938
- const tmpPath = `${cachePath}.tmp`;
939
- writeFileSync(tmpPath, JSON.stringify(file));
940
- renameSync(tmpPath, cachePath);
941
- } catch {
942
- }
943
- }
944
- var FAILED_NODE_TTL_MS = 60 * 60 * 1e3;
945
- function classifyAndCache(node, hostname, failedNodes, cachePath) {
946
- if (!node) {
947
- return { mode: null, node: null };
948
- }
949
- if (node.ip === hostname || node.host === hostname) {
950
- writeCache(hostname, {
951
- mode: "direct",
952
- node: null,
953
- failedNodes,
954
- updatedAt: Date.now()
955
- }, cachePath);
956
- return { mode: "direct", node: null };
957
- }
958
- writeCache(hostname, {
959
- mode: "proxy",
960
- node,
961
- failedNodes,
962
- updatedAt: Date.now()
963
- }, cachePath);
964
- return { mode: "proxy", node };
965
- }
966
- function getActiveFailedNodes(nodes) {
967
- if (!nodes || nodes.length === 0) return [];
968
- const now = Date.now();
969
- return nodes.filter((n) => now - n.failedAt < FAILED_NODE_TTL_MS);
970
- }
971
- function resolveDoh(hostname, cachePath) {
972
- const entry = readCache(hostname, cachePath);
973
- if (entry) {
974
- if (entry.mode === "direct") {
975
- return { mode: "direct", node: null };
976
- }
977
- if (entry.mode === "proxy" && entry.node) {
978
- return { mode: "proxy", node: entry.node };
979
- }
980
- }
981
- return { mode: null, node: null };
982
- }
983
- async function reResolveDoh(hostname, failedIp, userAgent, cachePath) {
984
- const entry = readCache(hostname, cachePath);
985
- const active = getActiveFailedNodes(entry?.failedNodes);
986
- const now = Date.now();
987
- const alreadyFailed = failedIp && active.some((n) => n.ip === failedIp);
988
- const failedNodes = failedIp && !alreadyFailed ? [...active, { ip: failedIp, failedAt: now }] : active;
989
- const excludeIps = failedNodes.map((n) => n.ip);
990
- const node = await execDohBinary(hostname, excludeIps, userAgent);
991
- return classifyAndCache(node, hostname, failedNodes, cachePath);
992
- }
993
864
  function getNow() {
994
865
  return (/* @__PURE__ */ new Date()).toISOString();
995
866
  }
@@ -1208,14 +1079,6 @@ var OkxRestClient = class _OkxRestClient {
1208
1079
  config;
1209
1080
  rateLimiter;
1210
1081
  dispatcher;
1211
- // DoH proxy state (lazy-resolved on first request)
1212
- dohResolved = false;
1213
- dohRetried = false;
1214
- directUnverified = false;
1215
- // The first direct connection has not yet been verified
1216
- dohNode = null;
1217
- dohAgent = null;
1218
- dohBaseUrl = null;
1219
1082
  constructor(config) {
1220
1083
  this.config = config;
1221
1084
  this.rateLimiter = new RateLimiter(3e4, config.verbose);
@@ -1223,98 +1086,6 @@ var OkxRestClient = class _OkxRestClient {
1223
1086
  this.dispatcher = new ProxyAgent(config.proxyUrl);
1224
1087
  }
1225
1088
  }
1226
- /**
1227
- * Lazily resolve the DoH proxy node on the first request.
1228
- * Uses cache-first strategy via the resolver.
1229
- */
1230
- ensureDoh() {
1231
- if (this.dohResolved || this.dispatcher) return;
1232
- this.dohResolved = true;
1233
- try {
1234
- const { hostname, protocol } = new URL(this.config.baseUrl);
1235
- const result = resolveDoh(hostname);
1236
- if (!result.mode) {
1237
- this.directUnverified = true;
1238
- if (this.config.verbose) {
1239
- vlog("DoH: no cache, trying direct connection first");
1240
- }
1241
- return;
1242
- }
1243
- if (result.mode === "direct") {
1244
- if (this.config.verbose) {
1245
- vlog("DoH: mode=direct (overseas or cached), using direct connection");
1246
- }
1247
- return;
1248
- }
1249
- if (result.node) {
1250
- this.applyDohNode(result.node, protocol);
1251
- }
1252
- } catch (err) {
1253
- if (this.config.verbose) {
1254
- const cause = err instanceof Error ? err.message : String(err);
1255
- vlog(`DoH resolution failed, falling back to direct: ${cause}`);
1256
- }
1257
- }
1258
- }
1259
- /** Apply a DoH node: set up the custom Agent + base URL. */
1260
- applyDohNode(node, protocol) {
1261
- this.dohNode = node;
1262
- this.dohBaseUrl = `${protocol}//${node.host}`;
1263
- this.dohAgent = new Agent({
1264
- connect: {
1265
- lookup: (_hostname, options, callback) => {
1266
- if (options?.all) {
1267
- callback(null, [{ address: node.ip, family: 4 }]);
1268
- } else {
1269
- callback(null, node.ip, 4);
1270
- }
1271
- }
1272
- }
1273
- });
1274
- if (this.config.verbose) {
1275
- vlog(`DoH proxy active: \u2192 ${node.host} (${node.ip}), ttl=${node.ttl}s`);
1276
- }
1277
- }
1278
- /**
1279
- * Handle network failure: re-resolve with --exclude and retry once.
1280
- * Returns true if retry should proceed, false if already retried.
1281
- */
1282
- async handleDohNetworkFailure() {
1283
- if (this.dohRetried) return false;
1284
- this.dohRetried = true;
1285
- const failedIp = this.dohNode?.ip ?? "";
1286
- const { hostname, protocol } = new URL(this.config.baseUrl);
1287
- this.dohNode = null;
1288
- this.dohAgent = null;
1289
- this.dohBaseUrl = null;
1290
- if (!failedIp) this.directUnverified = false;
1291
- if (this.config.verbose) {
1292
- vlog(failedIp ? `DoH: proxy node ${failedIp} failed, re-resolving with --exclude` : "DoH: direct connection failed, calling binary for DoH resolution");
1293
- }
1294
- try {
1295
- const result = await reResolveDoh(hostname, failedIp, this.dohUserAgent);
1296
- if (result.mode === "proxy" && result.node) {
1297
- this.applyDohNode(result.node, protocol);
1298
- this.dohRetried = false;
1299
- return true;
1300
- }
1301
- } catch {
1302
- }
1303
- if (this.config.verbose) {
1304
- vlog("DoH: re-resolution failed or switched to direct, retrying with direct connection");
1305
- }
1306
- return true;
1307
- }
1308
- get activeBaseUrl() {
1309
- return this.dohNode ? this.dohBaseUrl : this.config.baseUrl;
1310
- }
1311
- get activeDispatcher() {
1312
- return this.dispatcher ?? this.dohAgent ?? void 0;
1313
- }
1314
- /** User-Agent for DoH proxy requests: OKX/@okx_ai/{packageName}/{version} */
1315
- get dohUserAgent() {
1316
- return `OKX/@okx_ai/${this.config.userAgent ?? "unknown"}`;
1317
- }
1318
1089
  logRequest(method, url, auth) {
1319
1090
  if (!this.config.verbose) return;
1320
1091
  vlog(`\u2192 ${method} ${url}`);
@@ -1329,13 +1100,14 @@ var OkxRestClient = class _OkxRestClient {
1329
1100
  vlog(`\u2190 ${status} | code=${code ?? "0"} | ${rawLen}B | ${elapsed}ms | trace=${traceId ?? "-"}`);
1330
1101
  }
1331
1102
  }
1332
- async publicGet(path42, query, rateLimit) {
1103
+ async publicGet(path42, query, rateLimit, simulatedTrading) {
1333
1104
  return this.request({
1334
1105
  method: "GET",
1335
1106
  path: path42,
1336
1107
  auth: "public",
1337
1108
  query,
1338
- rateLimit
1109
+ rateLimit,
1110
+ simulatedTrading
1339
1111
  });
1340
1112
  }
1341
1113
  async privateGet(path42, query, rateLimit) {
@@ -1484,17 +1256,13 @@ var OkxRestClient = class _OkxRestClient {
1484
1256
  * Security: validates Content-Type and enforces maxBytes limit.
1485
1257
  */
1486
1258
  async privatePostBinary(path42, body, opts) {
1487
- this.ensureDoh();
1488
1259
  const maxBytes = opts?.maxBytes ?? _OkxRestClient.DEFAULT_MAX_BYTES;
1489
1260
  const expectedCT = opts?.expectedContentType ?? "application/octet-stream";
1490
1261
  const bodyJson = body ? JSON.stringify(body) : "";
1491
1262
  const endpoint = `POST ${path42}`;
1492
- this.logRequest("POST", `${this.activeBaseUrl}${path42}`, "private");
1263
+ this.logRequest("POST", `${this.config.baseUrl}${path42}`, "private");
1493
1264
  const reqConfig = { method: "POST", path: path42, auth: "private" };
1494
1265
  const headers = this.buildHeaders(reqConfig, path42, bodyJson, getNow());
1495
- if (this.dohNode) {
1496
- headers.set("User-Agent", this.dohUserAgent);
1497
- }
1498
1266
  const t0 = Date.now();
1499
1267
  const response = await this.fetchBinary(path42, endpoint, headers, bodyJson, t0);
1500
1268
  const elapsed = Date.now() - t0;
@@ -1528,10 +1296,10 @@ var OkxRestClient = class _OkxRestClient {
1528
1296
  method: "POST",
1529
1297
  headers,
1530
1298
  body: bodyJson || void 0,
1531
- signal: AbortSignal.timeout(this.config.timeoutMs),
1532
- dispatcher: this.activeDispatcher
1299
+ signal: AbortSignal.timeout(this.config.timeoutMs)
1533
1300
  };
1534
- return await fetch(`${this.activeBaseUrl}${path42}`, fetchOptions);
1301
+ if (this.dispatcher) fetchOptions.dispatcher = this.dispatcher;
1302
+ return await fetch(`${this.config.baseUrl}${path42}`, fetchOptions);
1535
1303
  } catch (error) {
1536
1304
  if (this.config.verbose) {
1537
1305
  vlog(`\u2717 NetworkError after ${Date.now() - t0}ms: ${error instanceof Error ? error.message : String(error)}`);
@@ -1553,7 +1321,8 @@ var OkxRestClient = class _OkxRestClient {
1553
1321
  if (reqConfig.auth === "private") {
1554
1322
  this.setAuthHeaders(headers, reqConfig.method, requestPath, bodyJson, timestamp);
1555
1323
  }
1556
- if (this.config.demo) {
1324
+ const useSimulated = reqConfig.simulatedTrading !== void 0 ? reqConfig.simulatedTrading : this.config.demo;
1325
+ if (useSimulated) {
1557
1326
  headers.set("x-simulated-trading", "1");
1558
1327
  }
1559
1328
  return headers;
@@ -1561,55 +1330,10 @@ var OkxRestClient = class _OkxRestClient {
1561
1330
  // ---------------------------------------------------------------------------
1562
1331
  // JSON request
1563
1332
  // ---------------------------------------------------------------------------
1564
- /**
1565
- * Handle network error during a JSON request: refresh DoH and maybe retry.
1566
- * Always either returns a retry result or throws NetworkError.
1567
- */
1568
- async handleRequestNetworkError(error, reqConfig, requestPath, t0) {
1569
- if (!this.dohRetried) {
1570
- if (this.config.verbose) {
1571
- const cause = error instanceof Error ? error.message : String(error);
1572
- vlog(`Network failure, refreshing DoH: ${cause}`);
1573
- }
1574
- const shouldRetry = await this.handleDohNetworkFailure();
1575
- if (shouldRetry && reqConfig.method === "GET") {
1576
- return this.request(reqConfig);
1577
- }
1578
- }
1579
- if (this.config.verbose) {
1580
- const elapsed = Date.now() - t0;
1581
- const cause = error instanceof Error ? error.message : String(error);
1582
- vlog(`\u2717 NetworkError after ${elapsed}ms: ${cause}`);
1583
- }
1584
- throw new NetworkError(
1585
- `Failed to call OKX endpoint ${reqConfig.method} ${requestPath}.`,
1586
- `${reqConfig.method} ${requestPath}`,
1587
- error
1588
- );
1589
- }
1590
- /**
1591
- * After a successful HTTP response on direct connection, cache mode=direct.
1592
- * (Even if the business response is an error, the network path is valid.)
1593
- */
1594
- cacheDirectConnectionIfNeeded() {
1595
- if (!this.directUnverified || this.dohNode) return;
1596
- this.directUnverified = false;
1597
- const { hostname } = new URL(this.config.baseUrl);
1598
- writeCache(hostname, {
1599
- mode: "direct",
1600
- node: null,
1601
- failedNodes: [],
1602
- updatedAt: Date.now()
1603
- });
1604
- if (this.config.verbose) {
1605
- vlog("DoH: direct connection succeeded, cached mode=direct");
1606
- }
1607
- }
1608
1333
  async request(reqConfig) {
1609
- this.ensureDoh();
1610
1334
  const queryString = buildQueryString(reqConfig.query);
1611
1335
  const requestPath = queryString.length > 0 ? `${reqConfig.path}?${queryString}` : reqConfig.path;
1612
- const url = `${this.activeBaseUrl}${requestPath}`;
1336
+ const url = `${this.config.baseUrl}${requestPath}`;
1613
1337
  const bodyJson = reqConfig.body ? JSON.stringify(reqConfig.body) : "";
1614
1338
  const timestamp = getNow();
1615
1339
  this.logRequest(reqConfig.method, url, reqConfig.auth);
@@ -1617,9 +1341,6 @@ var OkxRestClient = class _OkxRestClient {
1617
1341
  await this.rateLimiter.consume(reqConfig.rateLimit);
1618
1342
  }
1619
1343
  const headers = this.buildHeaders(reqConfig, requestPath, bodyJson, timestamp);
1620
- if (this.dohNode) {
1621
- headers.set("User-Agent", this.dohUserAgent);
1622
- }
1623
1344
  const t0 = Date.now();
1624
1345
  let response;
1625
1346
  try {
@@ -1627,17 +1348,27 @@ var OkxRestClient = class _OkxRestClient {
1627
1348
  method: reqConfig.method,
1628
1349
  headers,
1629
1350
  body: reqConfig.method === "POST" ? bodyJson : void 0,
1630
- signal: AbortSignal.timeout(this.config.timeoutMs),
1631
- dispatcher: this.activeDispatcher
1351
+ signal: AbortSignal.timeout(this.config.timeoutMs)
1632
1352
  };
1353
+ if (this.dispatcher) {
1354
+ fetchOptions.dispatcher = this.dispatcher;
1355
+ }
1633
1356
  response = await fetch(url, fetchOptions);
1634
1357
  } catch (error) {
1635
- return await this.handleRequestNetworkError(error, reqConfig, requestPath, t0);
1358
+ if (this.config.verbose) {
1359
+ const elapsed2 = Date.now() - t0;
1360
+ const cause = error instanceof Error ? error.message : String(error);
1361
+ vlog(`\u2717 NetworkError after ${elapsed2}ms: ${cause}`);
1362
+ }
1363
+ throw new NetworkError(
1364
+ `Failed to call OKX endpoint ${reqConfig.method} ${requestPath}.`,
1365
+ `${reqConfig.method} ${requestPath}`,
1366
+ error
1367
+ );
1636
1368
  }
1637
1369
  const rawText = await response.text();
1638
1370
  const elapsed = Date.now() - t0;
1639
1371
  const traceId = extractTraceId(response.headers);
1640
- this.cacheDirectConnectionIfNeeded();
1641
1372
  return this.processResponse(rawText, response, elapsed, traceId, reqConfig, requestPath);
1642
1373
  }
1643
1374
  };
@@ -3516,19 +3247,19 @@ function safeWriteFile(targetDir, fileName, data) {
3516
3247
  throw new Error(`Invalid file name: "${fileName}"`);
3517
3248
  }
3518
3249
  const resolvedDir = resolve(targetDir);
3519
- const filePath = join3(resolvedDir, safeName);
3250
+ const filePath = join(resolvedDir, safeName);
3520
3251
  const resolvedPath = resolve(filePath);
3521
3252
  if (!resolvedPath.startsWith(resolvedDir + sep)) {
3522
3253
  throw new Error(`Path traversal detected: "${fileName}" resolves outside target directory`);
3523
3254
  }
3524
- mkdirSync2(resolvedDir, { recursive: true });
3255
+ mkdirSync(resolvedDir, { recursive: true });
3525
3256
  const tmpPath = `${resolvedPath}.${randomUUID()}.tmp`;
3526
3257
  try {
3527
- writeFileSync2(tmpPath, data);
3528
- renameSync2(tmpPath, resolvedPath);
3258
+ writeFileSync(tmpPath, data);
3259
+ renameSync(tmpPath, resolvedPath);
3529
3260
  } catch (err) {
3530
3261
  try {
3531
- unlinkSync2(tmpPath);
3262
+ unlinkSync(tmpPath);
3532
3263
  } catch {
3533
3264
  }
3534
3265
  throw err;
@@ -3544,13 +3275,14 @@ function validateZipEntryPath(targetDir, entryName) {
3544
3275
  return resolvedEntry;
3545
3276
  }
3546
3277
  var MAX_DOWNLOAD_BYTES = 50 * 1024 * 1024;
3547
- async function downloadSkillZip(client, name, targetDir) {
3278
+ async function downloadSkillZip(client, name, targetDir, format = "zip") {
3548
3279
  const result = await client.privatePostBinary(
3549
3280
  "/api/v5/skill/download",
3550
3281
  { name },
3551
3282
  { maxBytes: MAX_DOWNLOAD_BYTES }
3552
3283
  );
3553
- const fileName = `${name}.zip`;
3284
+ const ext = format === "skill" ? "skill" : "zip";
3285
+ const fileName = `${name}.${ext}`;
3554
3286
  const filePath = safeWriteFile(targetDir, fileName, result.data);
3555
3287
  return filePath;
3556
3288
  }
@@ -3593,7 +3325,7 @@ async function extractSkillZip(zipPath, targetDir, limits) {
3593
3325
  const maxFiles = limits?.maxFiles ?? DEFAULT_MAX_FILES;
3594
3326
  const maxCompressionRatio = limits?.maxCompressionRatio ?? DEFAULT_MAX_COMPRESSION_RATIO;
3595
3327
  const resolvedTarget = resolve2(targetDir);
3596
- mkdirSync3(resolvedTarget, { recursive: true });
3328
+ mkdirSync2(resolvedTarget, { recursive: true });
3597
3329
  return new Promise((resolvePromise, reject) => {
3598
3330
  yauzl.open(zipPath, { lazyEntries: true }, (err, zipfile) => {
3599
3331
  if (err) return reject(err);
@@ -3616,7 +3348,7 @@ async function extractSkillZip(zipPath, targetDir, limits) {
3616
3348
  zipfile.close();
3617
3349
  return reject(streamErr);
3618
3350
  }
3619
- mkdirSync3(dirname2(resolvedPath), { recursive: true });
3351
+ mkdirSync2(dirname(resolvedPath), { recursive: true });
3620
3352
  const writeStream = createWriteStream(resolvedPath);
3621
3353
  readStream.pipe(writeStream);
3622
3354
  writeStream.on("close", () => zipfile.readEntry());
@@ -3632,11 +3364,11 @@ async function extractSkillZip(zipPath, targetDir, limits) {
3632
3364
  });
3633
3365
  }
3634
3366
  function readMetaJson(contentDir) {
3635
- const metaPath = join4(contentDir, "_meta.json");
3367
+ const metaPath = join2(contentDir, "_meta.json");
3636
3368
  if (!existsSync(metaPath)) {
3637
3369
  throw new Error(`_meta.json not found in ${contentDir}. Invalid skill package.`);
3638
3370
  }
3639
- const raw = readFileSync2(metaPath, "utf-8");
3371
+ const raw = readFileSync(metaPath, "utf-8");
3640
3372
  let parsed;
3641
3373
  try {
3642
3374
  parsed = JSON.parse(raw);
@@ -3658,26 +3390,26 @@ function readMetaJson(contentDir) {
3658
3390
  };
3659
3391
  }
3660
3392
  function validateSkillMdExists(contentDir) {
3661
- const skillMdPath = join4(contentDir, "SKILL.md");
3393
+ const skillMdPath = join2(contentDir, "SKILL.md");
3662
3394
  if (!existsSync(skillMdPath)) {
3663
3395
  throw new Error(`SKILL.md not found in ${contentDir}. Invalid skill package.`);
3664
3396
  }
3665
3397
  }
3666
- var DEFAULT_REGISTRY_PATH = join5(homedir3(), ".okx", "skills", "registry.json");
3398
+ var DEFAULT_REGISTRY_PATH = join3(homedir(), ".okx", "skills", "registry.json");
3667
3399
  function readRegistry(registryPath = DEFAULT_REGISTRY_PATH) {
3668
3400
  if (!existsSync2(registryPath)) {
3669
3401
  return { version: 1, skills: {} };
3670
3402
  }
3671
3403
  try {
3672
- const raw = readFileSync3(registryPath, "utf-8");
3404
+ const raw = readFileSync2(registryPath, "utf-8");
3673
3405
  return JSON.parse(raw);
3674
3406
  } catch {
3675
3407
  return { version: 1, skills: {} };
3676
3408
  }
3677
3409
  }
3678
3410
  function writeRegistry(registry, registryPath = DEFAULT_REGISTRY_PATH) {
3679
- mkdirSync4(dirname3(registryPath), { recursive: true });
3680
- writeFileSync3(registryPath, JSON.stringify(registry, null, 2) + "\n", "utf-8");
3411
+ mkdirSync3(dirname2(registryPath), { recursive: true });
3412
+ writeFileSync2(registryPath, JSON.stringify(registry, null, 2) + "\n", "utf-8");
3681
3413
  }
3682
3414
  function upsertSkillRecord(meta, registryPath = DEFAULT_REGISTRY_PATH) {
3683
3415
  const registry = readRegistry(registryPath);
@@ -3750,7 +3482,7 @@ function registerSkillsTools() {
3750
3482
  {
3751
3483
  name: "skills_download",
3752
3484
  module: "skills",
3753
- description: "Download a skill zip file from OKX Skills Marketplace to a local directory. Always call skills_search first to confirm the skill name exists. Downloads the latest approved version. NOTE: Downloads third-party developer content as a zip \u2014 does NOT install to agents. For full installation use CLI: okx skill add <name>. Use when the user wants to inspect or manually install a skill package.",
3485
+ description: "Download a skill package from OKX Skills Marketplace to a local directory. Always call skills_search first to confirm the skill name exists. Downloads the latest approved version. NOTE: Downloads third-party developer content \u2014 does NOT install to agents. For full installation use CLI: okx skill add <name>. Use when the user wants to inspect or manually install a skill package.",
3754
3486
  inputSchema: {
3755
3487
  type: "object",
3756
3488
  properties: {
@@ -3760,7 +3492,12 @@ function registerSkillsTools() {
3760
3492
  },
3761
3493
  targetDir: {
3762
3494
  type: "string",
3763
- description: "Directory path where the zip file will be saved"
3495
+ description: "Directory path where the file will be saved"
3496
+ },
3497
+ format: {
3498
+ type: "string",
3499
+ description: "Output file format: 'zip' or 'skill' (default: 'skill')",
3500
+ enum: ["zip", "skill"]
3764
3501
  }
3765
3502
  },
3766
3503
  required: ["name", "targetDir"],
@@ -3793,7 +3530,8 @@ async function handleSearch(args, ctx) {
3793
3530
  async function handleDownload(args, ctx) {
3794
3531
  const name = String(args.name);
3795
3532
  const targetDir = String(args.targetDir);
3796
- const filePath = await downloadSkillZip(ctx.client, name, targetDir);
3533
+ const format = args.format === "zip" ? "zip" : "skill";
3534
+ const filePath = await downloadSkillZip(ctx.client, name, targetDir, format);
3797
3535
  return {
3798
3536
  endpoint: "POST /api/v5/skill/download",
3799
3537
  requestTime: (/* @__PURE__ */ new Date()).toISOString(),
@@ -5940,6 +5678,12 @@ function registerFuturesTools() {
5940
5678
  ];
5941
5679
  }
5942
5680
  var TWO_DAYS_MS = 2 * 24 * 60 * 60 * 1e3;
5681
+ var DEMO_PROPERTY = {
5682
+ demo: {
5683
+ type: "boolean",
5684
+ description: "Query simulated trading (demo) market data. Default: false (live market data)."
5685
+ }
5686
+ };
5943
5687
  function registerMarketTools() {
5944
5688
  return [
5945
5689
  {
@@ -5953,7 +5697,8 @@ function registerMarketTools() {
5953
5697
  instId: {
5954
5698
  type: "string",
5955
5699
  description: "e.g. BTC-USDT, BTC-USDT-SWAP"
5956
- }
5700
+ },
5701
+ ...DEMO_PROPERTY
5957
5702
  },
5958
5703
  required: ["instId"]
5959
5704
  },
@@ -5962,7 +5707,8 @@ function registerMarketTools() {
5962
5707
  const response = await context.client.publicGet(
5963
5708
  "/api/v5/market/ticker",
5964
5709
  { instId: requireString(args, "instId") },
5965
- publicRateLimit("market_get_ticker", 20)
5710
+ publicRateLimit("market_get_ticker", 20),
5711
+ readBoolean(args, "demo") ?? false
5966
5712
  );
5967
5713
  return normalizeResponse(response);
5968
5714
  }
@@ -5986,7 +5732,8 @@ function registerMarketTools() {
5986
5732
  instFamily: {
5987
5733
  type: "string",
5988
5734
  description: "e.g. BTC-USD"
5989
- }
5735
+ },
5736
+ ...DEMO_PROPERTY
5990
5737
  },
5991
5738
  required: ["instType"]
5992
5739
  },
@@ -5999,7 +5746,8 @@ function registerMarketTools() {
5999
5746
  uly: readString(args, "uly"),
6000
5747
  instFamily: readString(args, "instFamily")
6001
5748
  }),
6002
- publicRateLimit("market_get_tickers", 20)
5749
+ publicRateLimit("market_get_tickers", 20),
5750
+ readBoolean(args, "demo") ?? false
6003
5751
  );
6004
5752
  return normalizeResponse(response);
6005
5753
  }
@@ -6019,7 +5767,8 @@ function registerMarketTools() {
6019
5767
  sz: {
6020
5768
  type: "number",
6021
5769
  description: "Depth per side, default 1, max 400"
6022
- }
5770
+ },
5771
+ ...DEMO_PROPERTY
6023
5772
  },
6024
5773
  required: ["instId"]
6025
5774
  },
@@ -6031,7 +5780,8 @@ function registerMarketTools() {
6031
5780
  instId: requireString(args, "instId"),
6032
5781
  sz: readNumber(args, "sz")
6033
5782
  }),
6034
- publicRateLimit("market_get_orderbook", 20)
5783
+ publicRateLimit("market_get_orderbook", 20),
5784
+ readBoolean(args, "demo") ?? false
6035
5785
  );
6036
5786
  return normalizeResponse(response);
6037
5787
  }
@@ -6064,7 +5814,8 @@ function registerMarketTools() {
6064
5814
  limit: {
6065
5815
  type: "number",
6066
5816
  description: "Max results (default 100)"
6067
- }
5817
+ },
5818
+ ...DEMO_PROPERTY
6068
5819
  },
6069
5820
  required: ["instId"]
6070
5821
  },
@@ -6072,6 +5823,7 @@ function registerMarketTools() {
6072
5823
  const args = asRecord(rawArgs);
6073
5824
  const afterTs = readString(args, "after");
6074
5825
  const beforeTs = readString(args, "before");
5826
+ const demo = readBoolean(args, "demo") ?? false;
6075
5827
  const query = compactObject({
6076
5828
  instId: requireString(args, "instId"),
6077
5829
  bar: readString(args, "bar"),
@@ -6083,9 +5835,9 @@ function registerMarketTools() {
6083
5835
  const hasTimestamp = afterTs !== void 0 || beforeTs !== void 0;
6084
5836
  const useHistory = afterTs !== void 0 && Number(afterTs) < Date.now() - TWO_DAYS_MS;
6085
5837
  const path42 = useHistory ? "/api/v5/market/history-candles" : "/api/v5/market/candles";
6086
- const response = await context.client.publicGet(path42, query, rateLimit);
5838
+ const response = await context.client.publicGet(path42, query, rateLimit, demo);
6087
5839
  if (!useHistory && hasTimestamp && Array.isArray(response.data) && response.data.length === 0) {
6088
- return normalizeResponse(await context.client.publicGet("/api/v5/market/history-candles", query, rateLimit));
5840
+ return normalizeResponse(await context.client.publicGet("/api/v5/market/history-candles", query, rateLimit, demo));
6089
5841
  }
6090
5842
  return normalizeResponse(response);
6091
5843
  }
@@ -6113,7 +5865,8 @@ function registerMarketTools() {
6113
5865
  instFamily: {
6114
5866
  type: "string",
6115
5867
  description: "e.g. BTC-USD"
6116
- }
5868
+ },
5869
+ ...DEMO_PROPERTY
6117
5870
  },
6118
5871
  required: ["instType"]
6119
5872
  },
@@ -6127,7 +5880,8 @@ function registerMarketTools() {
6127
5880
  uly: readString(args, "uly"),
6128
5881
  instFamily: readString(args, "instFamily")
6129
5882
  }),
6130
- publicRateLimit("market_get_instruments", 20)
5883
+ publicRateLimit("market_get_instruments", 20),
5884
+ readBoolean(args, "demo") ?? false
6131
5885
  );
6132
5886
  return normalizeResponse(response);
6133
5887
  }
@@ -6159,13 +5913,15 @@ function registerMarketTools() {
6159
5913
  limit: {
6160
5914
  type: "number",
6161
5915
  description: "History records (default 20, max 100)"
6162
- }
5916
+ },
5917
+ ...DEMO_PROPERTY
6163
5918
  },
6164
5919
  required: ["instId"]
6165
5920
  },
6166
5921
  handler: async (rawArgs, context) => {
6167
5922
  const args = asRecord(rawArgs);
6168
5923
  const isHistory = readBoolean(args, "history") ?? false;
5924
+ const demo = readBoolean(args, "demo") ?? false;
6169
5925
  if (isHistory) {
6170
5926
  const response2 = await context.client.publicGet(
6171
5927
  "/api/v5/public/funding-rate-history",
@@ -6175,14 +5931,16 @@ function registerMarketTools() {
6175
5931
  before: readString(args, "before"),
6176
5932
  limit: readNumber(args, "limit") ?? 20
6177
5933
  }),
6178
- publicRateLimit("market_get_funding_rate", 20)
5934
+ publicRateLimit("market_get_funding_rate", 20),
5935
+ demo
6179
5936
  );
6180
5937
  return normalizeResponse(response2);
6181
5938
  }
6182
5939
  const response = await context.client.publicGet(
6183
5940
  "/api/v5/public/funding-rate",
6184
5941
  { instId: requireString(args, "instId") },
6185
- publicRateLimit("market_get_funding_rate", 20)
5942
+ publicRateLimit("market_get_funding_rate", 20),
5943
+ demo
6186
5944
  );
6187
5945
  return normalizeResponse(response);
6188
5946
  }
@@ -6209,7 +5967,8 @@ function registerMarketTools() {
6209
5967
  },
6210
5968
  instFamily: {
6211
5969
  type: "string"
6212
- }
5970
+ },
5971
+ ...DEMO_PROPERTY
6213
5972
  },
6214
5973
  required: ["instType"]
6215
5974
  },
@@ -6223,7 +5982,8 @@ function registerMarketTools() {
6223
5982
  uly: readString(args, "uly"),
6224
5983
  instFamily: readString(args, "instFamily")
6225
5984
  }),
6226
- publicRateLimit("market_get_mark_price", 10)
5985
+ publicRateLimit("market_get_mark_price", 10),
5986
+ readBoolean(args, "demo") ?? false
6227
5987
  );
6228
5988
  return normalizeResponse(response);
6229
5989
  }
@@ -6243,7 +6003,8 @@ function registerMarketTools() {
6243
6003
  limit: {
6244
6004
  type: "number",
6245
6005
  description: "Default 20, max 500"
6246
- }
6006
+ },
6007
+ ...DEMO_PROPERTY
6247
6008
  },
6248
6009
  required: ["instId"]
6249
6010
  },
@@ -6255,7 +6016,8 @@ function registerMarketTools() {
6255
6016
  instId: requireString(args, "instId"),
6256
6017
  limit: readNumber(args, "limit") ?? 20
6257
6018
  }),
6258
- publicRateLimit("market_get_trades", 20)
6019
+ publicRateLimit("market_get_trades", 20),
6020
+ readBoolean(args, "demo") ?? false
6259
6021
  );
6260
6022
  return normalizeResponse(response);
6261
6023
  }
@@ -6275,7 +6037,8 @@ function registerMarketTools() {
6275
6037
  quoteCcy: {
6276
6038
  type: "string",
6277
6039
  description: "e.g. USD or USDT"
6278
- }
6040
+ },
6041
+ ...DEMO_PROPERTY
6279
6042
  }
6280
6043
  },
6281
6044
  handler: async (rawArgs, context) => {
@@ -6286,7 +6049,8 @@ function registerMarketTools() {
6286
6049
  instId: readString(args, "instId"),
6287
6050
  quoteCcy: readString(args, "quoteCcy")
6288
6051
  }),
6289
- publicRateLimit("market_get_index_ticker", 20)
6052
+ publicRateLimit("market_get_index_ticker", 20),
6053
+ readBoolean(args, "demo") ?? false
6290
6054
  );
6291
6055
  return normalizeResponse(response);
6292
6056
  }
@@ -6323,7 +6087,8 @@ function registerMarketTools() {
6323
6087
  history: {
6324
6088
  type: "boolean",
6325
6089
  description: "true=older historical data"
6326
- }
6090
+ },
6091
+ ...DEMO_PROPERTY
6327
6092
  },
6328
6093
  required: ["instId"]
6329
6094
  },
@@ -6340,7 +6105,8 @@ function registerMarketTools() {
6340
6105
  before: readString(args, "before"),
6341
6106
  limit: readNumber(args, "limit")
6342
6107
  }),
6343
- publicRateLimit("market_get_index_candles", 20)
6108
+ publicRateLimit("market_get_index_candles", 20),
6109
+ readBoolean(args, "demo") ?? false
6344
6110
  );
6345
6111
  return normalizeResponse(response);
6346
6112
  }
@@ -6356,7 +6122,8 @@ function registerMarketTools() {
6356
6122
  instId: {
6357
6123
  type: "string",
6358
6124
  description: "SWAP or FUTURES ID, e.g. BTC-USDT-SWAP"
6359
- }
6125
+ },
6126
+ ...DEMO_PROPERTY
6360
6127
  },
6361
6128
  required: ["instId"]
6362
6129
  },
@@ -6365,7 +6132,8 @@ function registerMarketTools() {
6365
6132
  const response = await context.client.publicGet(
6366
6133
  "/api/v5/public/price-limit",
6367
6134
  { instId: requireString(args, "instId") },
6368
- publicRateLimit("market_get_price_limit", 20)
6135
+ publicRateLimit("market_get_price_limit", 20),
6136
+ readBoolean(args, "demo") ?? false
6369
6137
  );
6370
6138
  return normalizeResponse(response);
6371
6139
  }
@@ -6392,7 +6160,8 @@ function registerMarketTools() {
6392
6160
  },
6393
6161
  instFamily: {
6394
6162
  type: "string"
6395
- }
6163
+ },
6164
+ ...DEMO_PROPERTY
6396
6165
  },
6397
6166
  required: ["instType"]
6398
6167
  },
@@ -6406,7 +6175,8 @@ function registerMarketTools() {
6406
6175
  uly: readString(args, "uly"),
6407
6176
  instFamily: readString(args, "instFamily")
6408
6177
  }),
6409
- publicRateLimit("market_get_open_interest", 20)
6178
+ publicRateLimit("market_get_open_interest", 20),
6179
+ readBoolean(args, "demo") ?? false
6410
6180
  );
6411
6181
  return normalizeResponse(response);
6412
6182
  }
@@ -6427,7 +6197,8 @@ function registerMarketTools() {
6427
6197
  instId: {
6428
6198
  type: "string",
6429
6199
  description: "Optional: filter by specific instrument ID, e.g. AAPL-USDT-SWAP"
6430
- }
6200
+ },
6201
+ ...DEMO_PROPERTY
6431
6202
  },
6432
6203
  required: []
6433
6204
  },
@@ -6438,7 +6209,8 @@ function registerMarketTools() {
6438
6209
  const response = await context.client.publicGet(
6439
6210
  "/api/v5/public/instruments",
6440
6211
  compactObject({ instType, instId }),
6441
- publicRateLimit("market_get_stock_tokens", 20)
6212
+ publicRateLimit("market_get_stock_tokens", 20),
6213
+ readBoolean(args, "demo") ?? false
6442
6214
  );
6443
6215
  const data = response.data;
6444
6216
  const filtered = Array.isArray(data) ? data.filter((item) => item.instCategory === "3") : data;
@@ -6448,7 +6220,7 @@ function registerMarketTools() {
6448
6220
  {
6449
6221
  name: "market_get_instruments_by_category",
6450
6222
  module: "market",
6451
- description: "Discover tradeable instruments by asset category. Stock tokens (instCategory=3, e.g. AAPL-USDT-SWAP, TSLA-USDT-SWAP), Metals (4, e.g. XAUUSDT-USDT-SWAP for gold), Commodities (5, e.g. OIL-USDT-SWAP for crude oil), Forex (6, e.g. EURUSDT-USDT-SWAP for EUR/USD), Bonds (7, e.g. US30Y-USDT-SWAP). Use this to find instIds before querying prices or placing orders. Filters client-side by instCategory.",
6223
+ description: "Discover tradeable instruments by asset category. Stock tokens (instCategory=3, e.g. AAPL-USDT-SWAP, TSLA-USDT-SWAP), Metals (4, e.g. XAUUSDT-USDT-SWAP for gold), Commodities (5, e.g. OIL-USDT-SWAP for crude oil), Forex (6, e.g. EURUSDT-USDT-SWAP for EUR/USD), Bonds (7, e.g. US30Y-USDT-SWAP for crude oil). Use this to find instIds before querying prices or placing orders. Filters client-side by instCategory.",
6452
6224
  isWrite: false,
6453
6225
  inputSchema: {
6454
6226
  type: "object",
@@ -6466,7 +6238,8 @@ function registerMarketTools() {
6466
6238
  instId: {
6467
6239
  type: "string",
6468
6240
  description: "Optional: filter by specific instrument ID"
6469
- }
6241
+ },
6242
+ ...DEMO_PROPERTY
6470
6243
  },
6471
6244
  required: ["instCategory"]
6472
6245
  },
@@ -6478,7 +6251,8 @@ function registerMarketTools() {
6478
6251
  const response = await context.client.publicGet(
6479
6252
  "/api/v5/public/instruments",
6480
6253
  compactObject({ instType, instId }),
6481
- publicRateLimit("market_get_instruments_by_category", 20)
6254
+ publicRateLimit("market_get_instruments_by_category", 20),
6255
+ readBoolean(args, "demo") ?? false
6482
6256
  );
6483
6257
  const data = response.data;
6484
6258
  const filtered = Array.isArray(data) ? data.filter((item) => item.instCategory === instCategory) : data;
@@ -8000,12 +7774,12 @@ function createToolRunner(client, config) {
8000
7774
  };
8001
7775
  }
8002
7776
  function configFilePath() {
8003
- return join6(homedir4(), ".okx", "config.toml");
7777
+ return join4(homedir2(), ".okx", "config.toml");
8004
7778
  }
8005
7779
  function readFullConfig() {
8006
7780
  const path42 = configFilePath();
8007
7781
  if (!existsSync3(path42)) return { profiles: {} };
8008
- const raw = readFileSync4(path42, "utf-8");
7782
+ const raw = readFileSync3(path42, "utf-8");
8009
7783
  try {
8010
7784
  return parse(raw);
8011
7785
  } catch (err) {
@@ -8033,11 +7807,11 @@ var CONFIG_HEADER = `# OKX Trade Kit Configuration
8033
7807
  `;
8034
7808
  function writeFullConfig(config) {
8035
7809
  const path42 = configFilePath();
8036
- const dir = dirname4(path42);
7810
+ const dir = dirname3(path42);
8037
7811
  if (!existsSync3(dir)) {
8038
- mkdirSync5(dir, { recursive: true });
7812
+ mkdirSync4(dir, { recursive: true });
8039
7813
  }
8040
- writeFileSync4(path42, CONFIG_HEADER + stringify(config), "utf-8");
7814
+ writeFileSync3(path42, CONFIG_HEADER + stringify(config), "utf-8");
8041
7815
  }
8042
7816
  function expandShorthand(moduleId) {
8043
7817
  if (moduleId === "all") return [...MODULES];
@@ -8151,21 +7925,21 @@ function loadConfig(cli) {
8151
7925
  verbose: cli.verbose ?? false
8152
7926
  };
8153
7927
  }
8154
- var CACHE_FILE = join7(homedir5(), ".okx", "update-check.json");
7928
+ var CACHE_FILE = join5(homedir3(), ".okx", "update-check.json");
8155
7929
  var CHECK_INTERVAL_MS = 24 * 60 * 60 * 1e3;
8156
- function readCache2() {
7930
+ function readCache() {
8157
7931
  try {
8158
7932
  if (existsSync4(CACHE_FILE)) {
8159
- return JSON.parse(readFileSync5(CACHE_FILE, "utf-8"));
7933
+ return JSON.parse(readFileSync4(CACHE_FILE, "utf-8"));
8160
7934
  }
8161
7935
  } catch {
8162
7936
  }
8163
7937
  return {};
8164
7938
  }
8165
- function writeCache2(cache) {
7939
+ function writeCache(cache) {
8166
7940
  try {
8167
- mkdirSync6(join7(homedir5(), ".okx"), { recursive: true });
8168
- writeFileSync5(CACHE_FILE, JSON.stringify(cache, null, 2), "utf-8");
7941
+ mkdirSync5(join5(homedir3(), ".okx"), { recursive: true });
7942
+ writeFileSync4(CACHE_FILE, JSON.stringify(cache, null, 2), "utf-8");
8169
7943
  } catch {
8170
7944
  }
8171
7945
  }
@@ -8212,14 +7986,14 @@ async function fetchLatestVersion(packageName) {
8212
7986
  function refreshCacheInBackground(packageName) {
8213
7987
  fetchLatestVersion(packageName).then((latest) => {
8214
7988
  if (!latest) return;
8215
- const cache = readCache2();
7989
+ const cache = readCache();
8216
7990
  cache[packageName] = { latestVersion: latest, checkedAt: Date.now() };
8217
- writeCache2(cache);
7991
+ writeCache(cache);
8218
7992
  }).catch(() => {
8219
7993
  });
8220
7994
  }
8221
7995
  function checkForUpdates(packageName, currentVersion) {
8222
- const cache = readCache2();
7996
+ const cache = readCache();
8223
7997
  const entry = cache[packageName];
8224
7998
  if (entry && isNewerVersion(currentVersion, entry.latestVersion)) {
8225
7999
  process.stderr.write(
@@ -9074,7 +8848,7 @@ async function cmdDiagnoseMcp(options = {}) {
9074
8848
 
9075
8849
  // src/commands/diagnose.ts
9076
8850
  var CLI_VERSION = readCliVersion();
9077
- var GIT_HASH = true ? "caa6dae" : "dev";
8851
+ var GIT_HASH = true ? "ee71999" : "dev";
9078
8852
  function maskKey2(key) {
9079
8853
  if (!key) return "(not set)";
9080
8854
  if (key.length <= 8) return "****";
@@ -9371,24 +9145,24 @@ async function runCliChecks(config, profile, outputPath) {
9371
9145
 
9372
9146
  // src/commands/upgrade.ts
9373
9147
  import { spawnSync as spawnSync2 } from "child_process";
9374
- import { readFileSync as readFileSync7, writeFileSync as writeFileSync7, mkdirSync as mkdirSync8 } from "fs";
9375
- import { dirname as dirname6, join as join9 } from "path";
9376
- import { homedir as homedir7 } from "os";
9148
+ import { readFileSync as readFileSync6, writeFileSync as writeFileSync6, mkdirSync as mkdirSync7 } from "fs";
9149
+ import { dirname as dirname5, join as join7 } from "path";
9150
+ import { homedir as homedir5 } from "os";
9377
9151
  var PACKAGES = ["@okx_ai/okx-trade-mcp", "@okx_ai/okx-trade-cli"];
9378
- var CACHE_FILE2 = join9(homedir7(), ".okx", "last_check");
9152
+ var CACHE_FILE2 = join7(homedir5(), ".okx", "last_check");
9379
9153
  var THROTTLE_MS = 12 * 60 * 60 * 1e3;
9380
- var NPM_BIN = join9(dirname6(process.execPath), process.platform === "win32" ? "npm.cmd" : "npm");
9154
+ var NPM_BIN = join7(dirname5(process.execPath), process.platform === "win32" ? "npm.cmd" : "npm");
9381
9155
  function readLastCheck() {
9382
9156
  try {
9383
- return parseInt(readFileSync7(CACHE_FILE2, "utf-8").trim(), 10) || 0;
9157
+ return parseInt(readFileSync6(CACHE_FILE2, "utf-8").trim(), 10) || 0;
9384
9158
  } catch {
9385
9159
  return 0;
9386
9160
  }
9387
9161
  }
9388
9162
  function writeLastCheck() {
9389
9163
  try {
9390
- mkdirSync8(join9(homedir7(), ".okx"), { recursive: true });
9391
- writeFileSync7(CACHE_FILE2, String(Math.floor(Date.now() / 1e3)), "utf-8");
9164
+ mkdirSync7(join7(homedir5(), ".okx"), { recursive: true });
9165
+ writeFileSync6(CACHE_FILE2, String(Math.floor(Date.now() / 1e3)), "utf-8");
9392
9166
  } catch {
9393
9167
  }
9394
9168
  }
@@ -10092,6 +9866,39 @@ var HELP_TREE = {
10092
9866
  description: "Run network / MCP server diagnostics",
10093
9867
  usage: "okx diagnose [--cli | --mcp | --all] [--profile <name>] [--demo | --live] [--output <file>]"
10094
9868
  },
9869
+ skill: {
9870
+ description: "OKX Skills Marketplace \u2014 search, install, and manage agent skills",
9871
+ commands: {
9872
+ search: {
9873
+ usage: "okx skill search [--keyword <kw>] [--categories <id>] [--page <n>] [--limit <n>]",
9874
+ description: "Search for skills in the marketplace"
9875
+ },
9876
+ categories: {
9877
+ usage: "okx skill categories",
9878
+ description: "List available skill categories"
9879
+ },
9880
+ add: {
9881
+ usage: "okx skill add <name>",
9882
+ description: "Download and install a skill to detected agents"
9883
+ },
9884
+ download: {
9885
+ usage: "okx skill download <name> [--dir <path>] [--format zip|skill]",
9886
+ description: "Download a skill package without installing"
9887
+ },
9888
+ remove: {
9889
+ usage: "okx skill remove <name>",
9890
+ description: "Remove an installed skill"
9891
+ },
9892
+ check: {
9893
+ usage: "okx skill check <name>",
9894
+ description: "Check if an installed skill has a newer version"
9895
+ },
9896
+ list: {
9897
+ usage: "okx skill list",
9898
+ description: "List all locally installed skills"
9899
+ }
9900
+ }
9901
+ },
10095
9902
  upgrade: {
10096
9903
  description: "Upgrade okx CLI and MCP server to the latest stable version",
10097
9904
  usage: "okx upgrade [--check] [--beta] [--force] [--json]"
@@ -10387,6 +10194,7 @@ var CLI_OPTIONS = {
10387
10194
  categories: { type: "string" },
10388
10195
  dir: { type: "string" },
10389
10196
  page: { type: "string" },
10197
+ format: { type: "string" },
10390
10198
  // diagnostics — cli/mcp/all/output are diagnose-specific; verbose is shared
10391
10199
  verbose: { type: "boolean", default: false },
10392
10200
  mcp: { type: "boolean", default: false },
@@ -10426,7 +10234,7 @@ function getData(result) {
10426
10234
  return result.data;
10427
10235
  }
10428
10236
  async function cmdMarketInstruments(run, opts) {
10429
- const result = await run("market_get_instruments", { instType: opts.instType, instId: opts.instId });
10237
+ const result = await run("market_get_instruments", { instType: opts.instType, instId: opts.instId, demo: opts.demo ?? false });
10430
10238
  const items = getData(result);
10431
10239
  if (opts.json) return printJson(items);
10432
10240
  printTable(
@@ -10441,7 +10249,7 @@ async function cmdMarketInstruments(run, opts) {
10441
10249
  );
10442
10250
  }
10443
10251
  async function cmdMarketFundingRate(run, instId, opts) {
10444
- const result = await run("market_get_funding_rate", { instId, history: opts.history, limit: opts.limit });
10252
+ const result = await run("market_get_funding_rate", { instId, history: opts.history, limit: opts.limit, demo: opts.demo ?? false });
10445
10253
  const items = getData(result);
10446
10254
  if (opts.json) return printJson(items);
10447
10255
  if (opts.history) {
@@ -10469,7 +10277,7 @@ async function cmdMarketFundingRate(run, instId, opts) {
10469
10277
  }
10470
10278
  }
10471
10279
  async function cmdMarketMarkPrice(run, opts) {
10472
- const result = await run("market_get_mark_price", { instType: opts.instType, instId: opts.instId });
10280
+ const result = await run("market_get_mark_price", { instType: opts.instType, instId: opts.instId, demo: opts.demo ?? false });
10473
10281
  const items = getData(result);
10474
10282
  if (opts.json) return printJson(items);
10475
10283
  printTable(
@@ -10482,7 +10290,7 @@ async function cmdMarketMarkPrice(run, opts) {
10482
10290
  );
10483
10291
  }
10484
10292
  async function cmdMarketTrades(run, instId, opts) {
10485
- const result = await run("market_get_trades", { instId, limit: opts.limit });
10293
+ const result = await run("market_get_trades", { instId, limit: opts.limit, demo: opts.demo ?? false });
10486
10294
  const items = getData(result);
10487
10295
  if (opts.json) return printJson(items);
10488
10296
  printTable(
@@ -10496,7 +10304,7 @@ async function cmdMarketTrades(run, instId, opts) {
10496
10304
  );
10497
10305
  }
10498
10306
  async function cmdMarketIndexTicker(run, opts) {
10499
- const result = await run("market_get_index_ticker", { instId: opts.instId, quoteCcy: opts.quoteCcy });
10307
+ const result = await run("market_get_index_ticker", { instId: opts.instId, quoteCcy: opts.quoteCcy, demo: opts.demo ?? false });
10500
10308
  const items = getData(result);
10501
10309
  if (opts.json) return printJson(items);
10502
10310
  printTable(
@@ -10510,7 +10318,7 @@ async function cmdMarketIndexTicker(run, opts) {
10510
10318
  );
10511
10319
  }
10512
10320
  async function cmdMarketIndexCandles(run, instId, opts) {
10513
- const result = await run("market_get_index_candles", { instId, bar: opts.bar, limit: opts.limit, history: opts.history });
10321
+ const result = await run("market_get_index_candles", { instId, bar: opts.bar, limit: opts.limit, history: opts.history, demo: opts.demo ?? false });
10514
10322
  const candles = getData(result);
10515
10323
  if (opts.json) return printJson(candles);
10516
10324
  printTable(
@@ -10523,8 +10331,8 @@ async function cmdMarketIndexCandles(run, instId, opts) {
10523
10331
  }))
10524
10332
  );
10525
10333
  }
10526
- async function cmdMarketPriceLimit(run, instId, json) {
10527
- const result = await run("market_get_price_limit", { instId });
10334
+ async function cmdMarketPriceLimit(run, instId, json, demo) {
10335
+ const result = await run("market_get_price_limit", { instId, demo: demo ?? false });
10528
10336
  const items = getData(result);
10529
10337
  if (json) return printJson(items);
10530
10338
  const r = items?.[0];
@@ -10540,7 +10348,7 @@ async function cmdMarketPriceLimit(run, instId, json) {
10540
10348
  });
10541
10349
  }
10542
10350
  async function cmdMarketOpenInterest(run, opts) {
10543
- const result = await run("market_get_open_interest", { instType: opts.instType, instId: opts.instId });
10351
+ const result = await run("market_get_open_interest", { instType: opts.instType, instId: opts.instId, demo: opts.demo ?? false });
10544
10352
  const items = getData(result);
10545
10353
  if (opts.json) return printJson(items);
10546
10354
  printTable(
@@ -10552,8 +10360,8 @@ async function cmdMarketOpenInterest(run, opts) {
10552
10360
  }))
10553
10361
  );
10554
10362
  }
10555
- async function cmdMarketTicker(run, instId, json) {
10556
- const result = await run("market_get_ticker", { instId });
10363
+ async function cmdMarketTicker(run, instId, json, demo) {
10364
+ const result = await run("market_get_ticker", { instId, demo: demo ?? false });
10557
10365
  const items = getData(result);
10558
10366
  if (json) return printJson(items);
10559
10367
  if (!items?.length) {
@@ -10576,8 +10384,8 @@ async function cmdMarketTicker(run, instId, json) {
10576
10384
  time: new Date(Number(t["ts"])).toLocaleString()
10577
10385
  });
10578
10386
  }
10579
- async function cmdMarketTickers(run, instType, json) {
10580
- const result = await run("market_get_tickers", { instType });
10387
+ async function cmdMarketTickers(run, instType, json, demo) {
10388
+ const result = await run("market_get_tickers", { instType, demo: demo ?? false });
10581
10389
  const items = getData(result);
10582
10390
  if (json) return printJson(items);
10583
10391
  printTable(
@@ -10590,8 +10398,8 @@ async function cmdMarketTickers(run, instType, json) {
10590
10398
  }))
10591
10399
  );
10592
10400
  }
10593
- async function cmdMarketOrderbook(run, instId, sz, json) {
10594
- const result = await run("market_get_orderbook", { instId, sz });
10401
+ async function cmdMarketOrderbook(run, instId, sz, json, demo) {
10402
+ const result = await run("market_get_orderbook", { instId, sz, demo: demo ?? false });
10595
10403
  const data = getData(result);
10596
10404
  if (json) return printJson(data);
10597
10405
  const book = data[0];
@@ -10608,7 +10416,7 @@ async function cmdMarketOrderbook(run, instId, sz, json) {
10608
10416
  for (const [p, s] of bids) outputLine(` ${p.padStart(16)} ${s}`);
10609
10417
  }
10610
10418
  async function cmdMarketCandles(run, instId, opts) {
10611
- const result = await run("market_get_candles", { instId, bar: opts.bar, limit: opts.limit, after: opts.after, before: opts.before });
10419
+ const result = await run("market_get_candles", { instId, bar: opts.bar, limit: opts.limit, after: opts.after, before: opts.before, demo: opts.demo ?? false });
10612
10420
  const candles = getData(result);
10613
10421
  if (opts.json) return printJson(candles);
10614
10422
  printTable(
@@ -10678,7 +10486,8 @@ async function cmdMarketInstrumentsByCategory(run, opts) {
10678
10486
  const result = await run("market_get_instruments_by_category", {
10679
10487
  instCategory: opts.instCategory,
10680
10488
  instType: opts.instType,
10681
- instId: opts.instId
10489
+ instId: opts.instId,
10490
+ demo: opts.demo ?? false
10682
10491
  });
10683
10492
  const items = getData(result);
10684
10493
  if (opts.json) return printJson(items);
@@ -10706,7 +10515,7 @@ async function cmdMarketInstrumentsByCategory(run, opts) {
10706
10515
  );
10707
10516
  }
10708
10517
  async function cmdMarketStockTokens(run, opts) {
10709
- const result = await run("market_get_stock_tokens", { instType: opts.instType, instId: opts.instId });
10518
+ const result = await run("market_get_stock_tokens", { instType: opts.instType, instId: opts.instId, demo: opts.demo ?? false });
10710
10519
  const items = getData(result);
10711
10520
  if (opts.json) return printJson(items);
10712
10521
  printTable(
@@ -13216,13 +13025,13 @@ async function cmdDcdQuoteAndBuy(run, opts) {
13216
13025
  }
13217
13026
 
13218
13027
  // src/commands/skill.ts
13219
- import { tmpdir, homedir as homedir9 } from "os";
13220
- import { join as join11, dirname as dirname7 } from "path";
13221
- import { mkdirSync as mkdirSync9, rmSync, existsSync as existsSync7, copyFileSync as copyFileSync2 } from "fs";
13028
+ import { tmpdir, homedir as homedir7 } from "os";
13029
+ import { join as join9, dirname as dirname6 } from "path";
13030
+ import { mkdirSync as mkdirSync8, rmSync, existsSync as existsSync7, copyFileSync as copyFileSync2 } from "fs";
13222
13031
  import { execFileSync as execFileSync2 } from "child_process";
13223
13032
  import { randomUUID as randomUUID2 } from "crypto";
13224
13033
  function resolveNpx() {
13225
- const sibling = join11(dirname7(process.execPath), "npx");
13034
+ const sibling = join9(dirname6(process.execPath), "npx");
13226
13035
  if (existsSync7(sibling)) return sibling;
13227
13036
  return "npx";
13228
13037
  }
@@ -13276,13 +13085,13 @@ async function cmdSkillCategories(run, json) {
13276
13085
  outputLine("");
13277
13086
  }
13278
13087
  async function cmdSkillAdd(name, config, json) {
13279
- const tmpBase = join11(tmpdir(), `okx-skill-${randomUUID2()}`);
13280
- mkdirSync9(tmpBase, { recursive: true });
13088
+ const tmpBase = join9(tmpdir(), `okx-skill-${randomUUID2()}`);
13089
+ mkdirSync8(tmpBase, { recursive: true });
13281
13090
  try {
13282
13091
  outputLine(`Downloading ${name}...`);
13283
13092
  const client = new OkxRestClient(config);
13284
13093
  const zipPath = await downloadSkillZip(client, name, tmpBase);
13285
- const contentDir = await extractSkillZip(zipPath, join11(tmpBase, "content"));
13094
+ const contentDir = await extractSkillZip(zipPath, join9(tmpBase, "content"));
13286
13095
  const meta = readMetaJson(contentDir);
13287
13096
  validateSkillMdExists(contentDir);
13288
13097
  outputLine("Installing to detected agents...");
@@ -13292,7 +13101,7 @@ async function cmdSkillAdd(name, config, json) {
13292
13101
  timeout: 6e4
13293
13102
  });
13294
13103
  } catch (e) {
13295
- const savedZip = join11(process.cwd(), `${name}.zip`);
13104
+ const savedZip = join9(process.cwd(), `${name}.zip`);
13296
13105
  try {
13297
13106
  copyFileSync2(zipPath, savedZip);
13298
13107
  } catch {
@@ -13307,14 +13116,14 @@ async function cmdSkillAdd(name, config, json) {
13307
13116
  rmSync(tmpBase, { recursive: true, force: true });
13308
13117
  }
13309
13118
  }
13310
- async function cmdSkillDownload(name, targetDir, config, json) {
13119
+ async function cmdSkillDownload(name, targetDir, config, json, format = "zip") {
13311
13120
  outputLine(`Downloading ${name}...`);
13312
13121
  const client = new OkxRestClient(config);
13313
- const filePath = await downloadSkillZip(client, name, targetDir);
13122
+ const filePath = await downloadSkillZip(client, name, targetDir, format);
13314
13123
  if (json) {
13315
13124
  outputLine(JSON.stringify({ name, filePath }, null, 2));
13316
13125
  } else {
13317
- outputLine(`\u2713 Downloaded ${name}.zip`);
13126
+ outputLine(`\u2713 Downloaded ${name}.${format}`);
13318
13127
  outputLine(` Path: ${filePath}`);
13319
13128
  }
13320
13129
  }
@@ -13331,7 +13140,7 @@ function cmdSkillRemove(name, json) {
13331
13140
  timeout: 6e4
13332
13141
  });
13333
13142
  } catch {
13334
- const agentsPath = join11(homedir9(), ".agents", "skills", name);
13143
+ const agentsPath = join9(homedir7(), ".agents", "skills", name);
13335
13144
  try {
13336
13145
  rmSync(agentsPath, { recursive: true, force: true });
13337
13146
  } catch {
@@ -13407,7 +13216,7 @@ function printSkillInstallResult(meta, json) {
13407
13216
  // src/index.ts
13408
13217
  var _require3 = createRequire3(import.meta.url);
13409
13218
  var CLI_VERSION2 = _require3("../package.json").version;
13410
- var GIT_HASH2 = true ? "caa6dae" : "dev";
13219
+ var GIT_HASH2 = true ? "ee71999" : "dev";
13411
13220
  function handleConfigCommand(action, rest, json, lang, force) {
13412
13221
  if (action === "init") return cmdConfigInit(lang === "zh" ? "zh" : "en");
13413
13222
  if (action === "show") return cmdConfigShow(json);
@@ -13437,25 +13246,26 @@ function handleSetupCommand(v) {
13437
13246
  });
13438
13247
  }
13439
13248
  function handleMarketPublicCommand(run, action, rest, v, json) {
13440
- if (action === "ticker") return cmdMarketTicker(run, rest[0], json);
13441
- if (action === "tickers") return cmdMarketTickers(run, rest[0], json);
13249
+ if (action === "ticker") return cmdMarketTicker(run, rest[0], json, v.demo);
13250
+ if (action === "tickers") return cmdMarketTickers(run, rest[0], json, v.demo);
13442
13251
  if (action === "instruments")
13443
- return cmdMarketInstruments(run, { instType: v.instType, instId: v.instId, json });
13252
+ return cmdMarketInstruments(run, { instType: v.instType, instId: v.instId, json, demo: v.demo });
13444
13253
  if (action === "mark-price")
13445
- return cmdMarketMarkPrice(run, { instType: v.instType, instId: v.instId, json });
13254
+ return cmdMarketMarkPrice(run, { instType: v.instType, instId: v.instId, json, demo: v.demo });
13446
13255
  if (action === "index-ticker")
13447
- return cmdMarketIndexTicker(run, { instId: v.instId, quoteCcy: v.quoteCcy, json });
13448
- if (action === "price-limit") return cmdMarketPriceLimit(run, rest[0], json);
13256
+ return cmdMarketIndexTicker(run, { instId: v.instId, quoteCcy: v.quoteCcy, json, demo: v.demo });
13257
+ if (action === "price-limit") return cmdMarketPriceLimit(run, rest[0], json, v.demo);
13449
13258
  if (action === "open-interest")
13450
- return cmdMarketOpenInterest(run, { instType: v.instType, instId: v.instId, json });
13259
+ return cmdMarketOpenInterest(run, { instType: v.instType, instId: v.instId, json, demo: v.demo });
13451
13260
  if (action === "stock-tokens")
13452
- return cmdMarketStockTokens(run, { instType: v.instType, instId: v.instId, json });
13261
+ return cmdMarketStockTokens(run, { instType: v.instType, instId: v.instId, json, demo: v.demo });
13453
13262
  if (action === "instruments-by-category")
13454
13263
  return cmdMarketInstrumentsByCategory(run, {
13455
13264
  instCategory: v.instCategory,
13456
13265
  instType: v.instType,
13457
13266
  instId: v.instId,
13458
- json
13267
+ json,
13268
+ demo: v.demo
13459
13269
  });
13460
13270
  if (action === "indicator") return handleIndicatorAction(run, rest, v, json);
13461
13271
  }
@@ -13475,15 +13285,15 @@ function handleIndicatorAction(run, rest, v, json) {
13475
13285
  function handleMarketDataCommand(run, action, rest, v, json) {
13476
13286
  const limit = v.limit !== void 0 ? Number(v.limit) : void 0;
13477
13287
  if (action === "orderbook")
13478
- return cmdMarketOrderbook(run, rest[0], v.sz !== void 0 ? Number(v.sz) : void 0, json);
13288
+ return cmdMarketOrderbook(run, rest[0], v.sz !== void 0 ? Number(v.sz) : void 0, json, v.demo);
13479
13289
  if (action === "candles")
13480
- return cmdMarketCandles(run, rest[0], { bar: v.bar, limit, after: v.after, before: v.before, json });
13290
+ return cmdMarketCandles(run, rest[0], { bar: v.bar, limit, after: v.after, before: v.before, json, demo: v.demo });
13481
13291
  if (action === "funding-rate")
13482
- return cmdMarketFundingRate(run, rest[0], { history: v.history ?? false, limit, json });
13292
+ return cmdMarketFundingRate(run, rest[0], { history: v.history ?? false, limit, json, demo: v.demo });
13483
13293
  if (action === "trades")
13484
- return cmdMarketTrades(run, rest[0], { limit, json });
13294
+ return cmdMarketTrades(run, rest[0], { limit, json, demo: v.demo });
13485
13295
  if (action === "index-candles")
13486
- return cmdMarketIndexCandles(run, rest[0], { bar: v.bar, limit, history: v.history ?? false, json });
13296
+ return cmdMarketIndexCandles(run, rest[0], { bar: v.bar, limit, history: v.history ?? false, json, demo: v.demo });
13487
13297
  }
13488
13298
  function handleMarketCommand(run, action, rest, v, json) {
13489
13299
  return handleMarketPublicCommand(run, action, rest, v, json) ?? handleMarketDataCommand(run, action, rest, v, json);
@@ -14192,8 +14002,9 @@ function handleSkillAdd(rest, config, json) {
14192
14002
  if (n) return cmdSkillAdd(n, config, json);
14193
14003
  }
14194
14004
  function handleSkillDownload(rest, v, config, json) {
14195
- const n = requireSkillName(rest, "Usage: okx skill download <name> [--dir <path>]");
14196
- if (n) return cmdSkillDownload(n, v.dir ?? process.cwd(), config, json);
14005
+ const n = requireSkillName(rest, "Usage: okx skill download <name> [--dir <path>] [--format zip|skill]");
14006
+ const format = v.format === "skill" ? "skill" : "zip";
14007
+ if (n) return cmdSkillDownload(n, v.dir ?? process.cwd(), config, json, format);
14197
14008
  }
14198
14009
  function handleSkillRemove(rest, json) {
14199
14010
  const n = requireSkillName(rest, "Usage: okx skill remove <name>");
@@ -14228,7 +14039,7 @@ function printHelpForLevel(positionals) {
14228
14039
  else if (!subgroup) printHelp(module);
14229
14040
  else printHelp(module, subgroup);
14230
14041
  }
14231
- function wrapRunnerWithLogger(baseRunner, logger) {
14042
+ function wrapRunnerWithLogger(baseRunner, logger, verbose = false) {
14232
14043
  const writeToolNames = new Set(allToolSpecs().filter((t) => t.isWrite).map((t) => t.name));
14233
14044
  return async (toolName, args) => {
14234
14045
  const startTime = Date.now();
@@ -14237,7 +14048,11 @@ function wrapRunnerWithLogger(baseRunner, logger) {
14237
14048
  if (writeToolNames.has(toolName)) {
14238
14049
  markFailedIfSCodeError(result.data);
14239
14050
  }
14240
- logger.log("info", toolName, args, result, Date.now() - startTime);
14051
+ const elapsed = Date.now() - startTime;
14052
+ logger.log("info", toolName, args, { status: "ok" }, elapsed);
14053
+ if (verbose) {
14054
+ logger.log("debug", toolName, args, result, elapsed);
14055
+ }
14241
14056
  return result;
14242
14057
  } catch (error) {
14243
14058
  logger.log("error", toolName, args, error, Date.now() - startTime);
@@ -14280,8 +14095,8 @@ async function main() {
14280
14095
  setJsonEnvEnabled(v.env ?? false);
14281
14096
  const client = new OkxRestClient(config);
14282
14097
  const baseRunner = createToolRunner(client, config);
14283
- const logger = new TradeLogger("info");
14284
- const run = wrapRunnerWithLogger(baseRunner, logger);
14098
+ const logger = new TradeLogger(v.verbose ? "debug" : "info");
14099
+ const run = wrapRunnerWithLogger(baseRunner, logger, v.verbose ?? false);
14285
14100
  const moduleHandlers = {
14286
14101
  market: () => handleMarketCommand(run, action, rest, v, json),
14287
14102
  account: () => handleAccountCommand(run, action, rest, v, json),