@okx_ai/okx-trade-cli 1.3.3-beta.2 → 1.3.3

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,9 +21,12 @@ 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";
24
+ import { spawn as spawn2, execFile as execFile2 } from "child_process";
25
25
  import { homedir as homedir3 } from "os";
26
26
  import { join as join3 } from "path";
27
+ import { spawn } from "child_process";
28
+ import { createServer } from "net";
29
+ import { randomBytes } from "crypto";
27
30
  import fs from "fs";
28
31
  import path from "path";
29
32
  import os from "os";
@@ -1279,6 +1282,105 @@ var EXIT_CODES = {
1279
1282
  NOT_LOGGED_IN: 2,
1280
1283
  REFRESH_FAILED: 3
1281
1284
  };
1285
+ function finalizeToken(code, token, resolve3, reject) {
1286
+ if (code === EXIT_CODES.SUCCESS) {
1287
+ if (!token) {
1288
+ reject(new AuthenticationError(
1289
+ "okx-auth returned empty token.",
1290
+ "Run `okx auth login` to re-authenticate."
1291
+ ));
1292
+ return;
1293
+ }
1294
+ resolve3(token);
1295
+ return;
1296
+ }
1297
+ if (code === EXIT_CODES.NOT_LOGGED_IN) {
1298
+ reject(new NotLoggedInError());
1299
+ return;
1300
+ }
1301
+ if (code === EXIT_CODES.UNAUTHORIZED_CALLER) {
1302
+ reject(new AuthenticationError(
1303
+ "okx-auth rejected the caller (unauthorized).",
1304
+ "Ensure you are running from a trusted OKX tool."
1305
+ ));
1306
+ return;
1307
+ }
1308
+ if (code === EXIT_CODES.REFRESH_FAILED) {
1309
+ reject(new AuthenticationError(
1310
+ "Token refresh failed.",
1311
+ "Run `okx auth login` to re-authenticate."
1312
+ ));
1313
+ return;
1314
+ }
1315
+ reject(new AuthenticationError(
1316
+ `okx-auth token exited with code ${code}.`,
1317
+ "Run `okx auth login` to re-authenticate."
1318
+ ));
1319
+ }
1320
+ function spawnFailedError(err) {
1321
+ return new ConfigError(
1322
+ `Failed to spawn okx-auth: ${err.message}`,
1323
+ "Ensure the okx-auth binary exists and is executable."
1324
+ );
1325
+ }
1326
+ var WIN_PIPE_PREFIX = String.raw`\\.\pipe\okx-auth-`;
1327
+ function defaultWindowsPipeName() {
1328
+ return WIN_PIPE_PREFIX + randomBytes(32).toString("hex");
1329
+ }
1330
+ function execAuthTokenWindows(binPath, makePipeName = defaultWindowsPipeName) {
1331
+ return new Promise((resolve3, reject) => {
1332
+ const pipeName = makePipeName();
1333
+ const server = createServer();
1334
+ const chunks = [];
1335
+ let connectionMade = false;
1336
+ let pipeClosed = false;
1337
+ let exitCode;
1338
+ let settled = false;
1339
+ const settle = (fn) => {
1340
+ if (settled) return;
1341
+ settled = true;
1342
+ try {
1343
+ server.close();
1344
+ } catch {
1345
+ }
1346
+ fn();
1347
+ };
1348
+ const tryFinalize = () => {
1349
+ if (!pipeClosed || exitCode === void 0) return;
1350
+ const token = Buffer.concat(chunks).toString("utf-8").trim();
1351
+ settle(() => finalizeToken(exitCode, token, resolve3, reject));
1352
+ };
1353
+ server.on("connection", (socket) => {
1354
+ connectionMade = true;
1355
+ socket.on("data", (c) => chunks.push(c));
1356
+ socket.on("end", () => {
1357
+ pipeClosed = true;
1358
+ tryFinalize();
1359
+ });
1360
+ socket.on("error", (err) => settle(() => reject(spawnFailedError(err))));
1361
+ });
1362
+ server.on("error", (err) => settle(() => reject(spawnFailedError(err))));
1363
+ server.listen(pipeName, () => {
1364
+ let child;
1365
+ try {
1366
+ child = spawn(binPath, ["token"], {
1367
+ stdio: ["ignore", "ignore", "inherit"],
1368
+ env: { ...process.env, OKX_AUTH_TOKEN_PIPE: pipeName },
1369
+ windowsHide: true
1370
+ });
1371
+ } catch (err) {
1372
+ settle(() => reject(spawnFailedError(err)));
1373
+ return;
1374
+ }
1375
+ child.on("error", (err) => settle(() => reject(spawnFailedError(err))));
1376
+ child.on("close", (code) => {
1377
+ exitCode = code;
1378
+ if (!connectionMade) pipeClosed = true;
1379
+ tryFinalize();
1380
+ });
1381
+ });
1382
+ });
1383
+ }
1282
1384
  var EXEC_TIMEOUT_MS2 = 5e3;
1283
1385
  var AUTH_BIN_DIR = join3(homedir3(), ".okx", "bin");
1284
1386
  function getAuthBinaryPath() {
@@ -1290,8 +1392,11 @@ function getAuthBinaryPath() {
1290
1392
  }
1291
1393
  function execAuthToken() {
1292
1394
  const binPath = getAuthBinaryPath();
1395
+ return process.platform === "win32" ? execAuthTokenWindows(binPath) : execAuthTokenUnix(binPath);
1396
+ }
1397
+ function execAuthTokenUnix(binPath) {
1293
1398
  return new Promise((resolve3, reject) => {
1294
- const child = spawn(binPath, ["token"], {
1399
+ const child = spawn2(binPath, ["token"], {
1295
1400
  stdio: ["ignore", "ignore", "inherit", "pipe"]
1296
1401
  // stdin stdout stderr fd3 (pipe)
1297
1402
  });
@@ -1299,46 +1404,11 @@ function execAuthToken() {
1299
1404
  const fd3 = child.stdio[3];
1300
1405
  fd3.on("data", (chunk) => chunks.push(chunk));
1301
1406
  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
- ));
1407
+ reject(spawnFailedError(err));
1306
1408
  });
1307
1409
  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
- ));
1410
+ const token = Buffer.concat(chunks).toString("utf-8").trim();
1411
+ finalizeToken(code, token, resolve3, reject);
1342
1412
  });
1343
1413
  });
1344
1414
  }
@@ -11830,12 +11900,47 @@ function sanitize(value) {
11830
11900
  }
11831
11901
  return value;
11832
11902
  }
11903
+ var PRUNE_MARKER = ".last-prune.json";
11904
+ var PRUNE_INTERVAL_MS = 24 * 60 * 60 * 1e3;
11905
+ var DEFAULT_RETENTION_DAYS = 30;
11906
+ var MS_PER_DAY = 864e5;
11907
+ var LOG_FILE_PATTERN = /^trade-.+\.log$/;
11908
+ function pruneOldLogs(logDir, retentionDays, now) {
11909
+ if (retentionDays === 0) return;
11910
+ try {
11911
+ const markerPath = path2.join(logDir, PRUNE_MARKER);
11912
+ let checkedAt = 0;
11913
+ try {
11914
+ const raw = fs2.readFileSync(markerPath, "utf8");
11915
+ const data = JSON.parse(raw);
11916
+ if (typeof data.checkedAt === "number") {
11917
+ checkedAt = data.checkedAt;
11918
+ }
11919
+ } catch {
11920
+ }
11921
+ if (checkedAt > 0 && now - checkedAt <= PRUNE_INTERVAL_MS) return;
11922
+ const cutoff = now - retentionDays * MS_PER_DAY;
11923
+ for (const name of fs2.readdirSync(logDir).filter((f) => LOG_FILE_PATTERN.test(f))) {
11924
+ try {
11925
+ if (fs2.statSync(path2.join(logDir, name)).mtimeMs < cutoff) {
11926
+ fs2.unlinkSync(path2.join(logDir, name));
11927
+ }
11928
+ } catch {
11929
+ }
11930
+ }
11931
+ fs2.writeFileSync(markerPath, JSON.stringify({ checkedAt: now }), "utf8");
11932
+ } catch {
11933
+ }
11934
+ }
11833
11935
  var TradeLogger = class {
11834
11936
  logLevel;
11835
11937
  logDir;
11836
11938
  constructor(logLevel = "info", logDir) {
11837
11939
  this.logLevel = logLevel;
11838
11940
  this.logDir = logDir ?? path2.join(os2.homedir(), ".okx", "logs");
11941
+ const parsed = parseInt(process.env.OKX_LOG_RETENTION_DAYS ?? "", 10);
11942
+ const retentionDays = isNaN(parsed) || parsed < 0 ? DEFAULT_RETENTION_DAYS : parsed;
11943
+ pruneOldLogs(this.logDir, retentionDays, Date.now());
11839
11944
  }
11840
11945
  getLogPath(date) {
11841
11946
  const d = date ?? /* @__PURE__ */ new Date();
@@ -12472,7 +12577,7 @@ function clearAuthBinaryCache() {
12472
12577
  }
12473
12578
 
12474
12579
  // src/commands/auth.ts
12475
- import { spawn as spawn2 } from "child_process";
12580
+ import { spawn as spawn3 } from "child_process";
12476
12581
  import readline from "readline";
12477
12582
 
12478
12583
  // src/formatter.ts
@@ -12568,7 +12673,7 @@ function markFailedIfSCodeError(data) {
12568
12673
  function runOkxAuth(args) {
12569
12674
  const binPath = getAuthBinaryPath();
12570
12675
  return new Promise((resolve3, reject) => {
12571
- const child = spawn2(binPath, args, {
12676
+ const child = spawn3(binPath, args, {
12572
12677
  stdio: "inherit"
12573
12678
  });
12574
12679
  child.on("error", (err) => {
@@ -12582,7 +12687,7 @@ function runOkxAuth(args) {
12582
12687
  function runOkxAuthCapture(args) {
12583
12688
  const binPath = getAuthBinaryPath();
12584
12689
  return new Promise((resolve3, reject) => {
12585
- const child = spawn2(binPath, args, {
12690
+ const child = spawn3(binPath, args, {
12586
12691
  stdio: ["inherit", "pipe", "inherit"]
12587
12692
  });
12588
12693
  const chunks = [];
@@ -12929,7 +13034,7 @@ function sanitize2(value) {
12929
13034
  import fs5 from "fs";
12930
13035
  import path4 from "path";
12931
13036
  import os4 from "os";
12932
- import { spawnSync, spawn as spawn3 } from "child_process";
13037
+ import { spawnSync, spawn as spawn4 } from "child_process";
12933
13038
  import { createRequire as createRequire2 } from "module";
12934
13039
  import { fileURLToPath } from "url";
12935
13040
  var _require2 = createRequire2(import.meta.url);
@@ -13263,7 +13368,7 @@ async function checkStdioHandshake(entryPath, report) {
13263
13368
  clearTimeout(timer);
13264
13369
  resolve3(passed);
13265
13370
  };
13266
- const child = spawn3(process.execPath, [entryPath], {
13371
+ const child = spawn4(process.execPath, [entryPath], {
13267
13372
  stdio: ["pipe", "pipe", "pipe"],
13268
13373
  env: { ...process.env }
13269
13374
  });
@@ -13382,7 +13487,7 @@ async function cmdDiagnoseMcp(options = {}) {
13382
13487
 
13383
13488
  // src/commands/diagnose.ts
13384
13489
  var CLI_VERSION = readCliVersion();
13385
- var GIT_HASH = true ? "e8a0930a" : "dev";
13490
+ var GIT_HASH = true ? "e6ad1d1e" : "dev";
13386
13491
  function maskKey2(key) {
13387
13492
  if (!key) return "(not set)";
13388
13493
  if (key.length <= 8) return "****";
@@ -14690,7 +14795,7 @@ var CLI_REGISTRY = {
14690
14795
  commands: {
14691
14796
  "traders-by-filter": {
14692
14797
  toolName: "smartmoney_get_traders_by_filter",
14693
- usage: "okx smartmoney traders-by-filter [--updateTime <yyyyMMddHHmmss UTC+8>] [--sortBy <pnl|pnlRatio, default pnl>] [--period <3|7|30|90, default 90>] [--minPnl <n>] [--minWinRate <r>] [--maxDrawdown <r>] [--minAum <n>] [--after <authorId>] [--before <authorId>] [--limit <n, default 10>] [--json]",
14798
+ usage: "okx smartmoney traders-by-filter [--updateTime <yyyyMMddHHmm UTC+8>] [--sortBy <pnl|pnlRatio, default pnl>] [--period <3|7|30|90, default 90>] [--minPnl <n>] [--minWinRate <r>] [--maxDrawdown <r>] [--minAum <n>] [--after <authorId>] [--before <authorId>] [--limit <n, default 10>] [--json]",
14694
14799
  description: "Leaderboard of top smart-money traders, ranked and filtered by pool conditions"
14695
14800
  },
14696
14801
  "performance-by-trader": {
@@ -18868,12 +18973,12 @@ function filterByStrike(data, ref) {
18868
18973
  });
18869
18974
  }
18870
18975
  function filterByTerm(data, termDays, minTermDays, maxTermDays) {
18871
- const MS_PER_DAY = 864e5;
18976
+ const MS_PER_DAY2 = 864e5;
18872
18977
  return data.filter((r) => {
18873
18978
  const exp = Number(r["expTime"]);
18874
18979
  const start = Number(r["interestAccrualTime"]);
18875
18980
  if (!exp || !start) return false;
18876
- const days = Math.round((exp - start) / MS_PER_DAY);
18981
+ const days = Math.round((exp - start) / MS_PER_DAY2);
18877
18982
  if (termDays !== void 0 && days !== termDays) return false;
18878
18983
  if (minTermDays !== void 0 && days < minTermDays) return false;
18879
18984
  if (maxTermDays !== void 0 && days > maxTermDays) return false;
@@ -19868,7 +19973,7 @@ async function cmdEventCancel(run, opts) {
19868
19973
  // src/index.ts
19869
19974
  var _require3 = createRequire3(import.meta.url);
19870
19975
  var CLI_VERSION2 = _require3("../package.json").version;
19871
- var GIT_HASH2 = true ? "e8a0930a" : "dev";
19976
+ var GIT_HASH2 = true ? "e6ad1d1e" : "dev";
19872
19977
  function handlePilotCommand(action, json, force, binaryPath) {
19873
19978
  if (action === "status") return cmdPilotStatus(json, binaryPath);
19874
19979
  if (action === "install") return cmdPilotInstall(json, binaryPath);