@okx_ai/okx-trade-cli 1.2.8 → 1.2.9-beta.2

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
@@ -2191,6 +2191,59 @@ function registerAccountTools() {
2191
2191
  }
2192
2192
  ];
2193
2193
  }
2194
+ async function resolveQuoteCcySz(instId, sz, tgtCcy, instType, client) {
2195
+ if (tgtCcy !== "quote_ccy") {
2196
+ return { sz, tgtCcy, conversionNote: void 0 };
2197
+ }
2198
+ const [instrumentsRes, tickerRes] = await Promise.all([
2199
+ client.publicGet("/api/v5/public/instruments", {
2200
+ instType,
2201
+ instId
2202
+ }),
2203
+ client.publicGet("/api/v5/market/ticker", { instId })
2204
+ ]);
2205
+ const instruments = Array.isArray(instrumentsRes.data) ? instrumentsRes.data : [];
2206
+ if (instruments.length === 0) {
2207
+ throw new Error(
2208
+ `Failed to fetch instrument info for ${instId}: empty instrument list. Cannot determine ctVal for quote_ccy conversion.`
2209
+ );
2210
+ }
2211
+ const ctValStr = String(instruments[0].ctVal ?? "");
2212
+ const ctVal = parseFloat(ctValStr);
2213
+ if (!isFinite(ctVal) || ctVal <= 0) {
2214
+ throw new Error(
2215
+ `Invalid ctVal "${ctValStr}" for ${instId}. ctVal must be a positive number for quote_ccy conversion.`
2216
+ );
2217
+ }
2218
+ const tickers = Array.isArray(tickerRes.data) ? tickerRes.data : [];
2219
+ if (tickers.length === 0) {
2220
+ throw new Error(
2221
+ `Failed to fetch ticker price for ${instId}: empty ticker response. Cannot determine last price for quote_ccy conversion.`
2222
+ );
2223
+ }
2224
+ const lastStr = String(tickers[0].last ?? "");
2225
+ const lastPx = parseFloat(lastStr);
2226
+ if (!isFinite(lastPx) || lastPx <= 0) {
2227
+ throw new Error(
2228
+ `Invalid last price "${lastStr}" for ${instId}. Last price must be a positive number for quote_ccy conversion.`
2229
+ );
2230
+ }
2231
+ const usdtAmount = parseFloat(sz);
2232
+ const contractValue = ctVal * lastPx;
2233
+ const contracts = Math.floor(usdtAmount / contractValue);
2234
+ if (contracts <= 0) {
2235
+ const minUsdt = contractValue.toFixed(2);
2236
+ throw new Error(
2237
+ `sz=${sz} USDT is too small to buy even 1 contract of ${instId}. Minimum amount required is at least ${minUsdt} USDT (ctVal=${ctValStr}, lastPx=${lastStr}, 1 contract = ${minUsdt} USDT).`
2238
+ );
2239
+ }
2240
+ const conversionNote = `Converting ${sz} USDT \u2192 ${contracts} contracts (ctVal=${ctValStr}, lastPx=${lastStr}, formula: floor(${sz} / (${ctValStr} \xD7 ${lastStr})) = ${contracts})`;
2241
+ return {
2242
+ sz: String(contracts),
2243
+ tgtCcy: void 0,
2244
+ conversionNote
2245
+ };
2246
+ }
2194
2247
  function registerAlgoTradeTools() {
2195
2248
  return [
2196
2249
  {
@@ -2286,6 +2339,13 @@ function registerAlgoTradeTools() {
2286
2339
  handler: async (rawArgs, context) => {
2287
2340
  const args = asRecord(rawArgs);
2288
2341
  const reduceOnly = args.reduceOnly;
2342
+ const resolved = await resolveQuoteCcySz(
2343
+ requireString(args, "instId"),
2344
+ requireString(args, "sz"),
2345
+ readString(args, "tgtCcy"),
2346
+ "SWAP",
2347
+ context.client
2348
+ );
2289
2349
  const response = await context.client.privatePost(
2290
2350
  "/api/v5/trade/order-algo",
2291
2351
  compactObject({
@@ -2294,8 +2354,8 @@ function registerAlgoTradeTools() {
2294
2354
  side: requireString(args, "side"),
2295
2355
  posSide: readString(args, "posSide"),
2296
2356
  ordType: requireString(args, "ordType"),
2297
- sz: requireString(args, "sz"),
2298
- tgtCcy: readString(args, "tgtCcy"),
2357
+ sz: resolved.sz,
2358
+ tgtCcy: resolved.tgtCcy,
2299
2359
  tpTriggerPx: readString(args, "tpTriggerPx"),
2300
2360
  tpOrdPx: readString(args, "tpOrdPx"),
2301
2361
  tpTriggerPxType: readString(args, "tpTriggerPxType"),
@@ -2311,7 +2371,11 @@ function registerAlgoTradeTools() {
2311
2371
  }),
2312
2372
  privateRateLimit("swap_place_algo_order", 20)
2313
2373
  );
2314
- return normalizeResponse(response);
2374
+ const result = normalizeResponse(response);
2375
+ if (resolved.conversionNote) {
2376
+ result._conversion = resolved.conversionNote;
2377
+ }
2378
+ return result;
2315
2379
  }
2316
2380
  },
2317
2381
  {
@@ -2619,6 +2683,13 @@ function registerFuturesAlgoTools() {
2619
2683
  handler: async (rawArgs, context) => {
2620
2684
  const args = asRecord(rawArgs);
2621
2685
  const reduceOnly = args.reduceOnly;
2686
+ const resolved = await resolveQuoteCcySz(
2687
+ requireString(args, "instId"),
2688
+ requireString(args, "sz"),
2689
+ readString(args, "tgtCcy"),
2690
+ "FUTURES",
2691
+ context.client
2692
+ );
2622
2693
  const response = await context.client.privatePost(
2623
2694
  "/api/v5/trade/order-algo",
2624
2695
  compactObject({
@@ -2627,8 +2698,8 @@ function registerFuturesAlgoTools() {
2627
2698
  side: requireString(args, "side"),
2628
2699
  posSide: readString(args, "posSide"),
2629
2700
  ordType: requireString(args, "ordType"),
2630
- sz: requireString(args, "sz"),
2631
- tgtCcy: readString(args, "tgtCcy"),
2701
+ sz: resolved.sz,
2702
+ tgtCcy: resolved.tgtCcy,
2632
2703
  tpTriggerPx: readString(args, "tpTriggerPx"),
2633
2704
  tpOrdPx: readString(args, "tpOrdPx"),
2634
2705
  tpTriggerPxType: readString(args, "tpTriggerPxType"),
@@ -2644,7 +2715,11 @@ function registerFuturesAlgoTools() {
2644
2715
  }),
2645
2716
  privateRateLimit("futures_place_algo_order", 20)
2646
2717
  );
2647
- return normalizeResponse(response);
2718
+ const result = normalizeResponse(response);
2719
+ if (resolved.conversionNote) {
2720
+ result._conversion = resolved.conversionNote;
2721
+ }
2722
+ return result;
2648
2723
  }
2649
2724
  },
2650
2725
  {
@@ -3209,7 +3284,7 @@ function registerSkillsTools() {
3209
3284
  {
3210
3285
  name: "skills_download",
3211
3286
  module: "skills",
3212
- 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: This only downloads the zip \u2014 it 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.",
3287
+ 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.",
3213
3288
  inputSchema: {
3214
3289
  type: "object",
3215
3290
  properties: {
@@ -4730,6 +4805,13 @@ function buildContractTradeTools(cfg) {
4730
4805
  const args = asRecord(rawArgs);
4731
4806
  const reduceOnly = args.reduceOnly;
4732
4807
  const attachAlgoOrds = buildAttachAlgoOrds(args);
4808
+ const resolved = await resolveQuoteCcySz(
4809
+ requireString(args, "instId"),
4810
+ requireString(args, "sz"),
4811
+ readString(args, "tgtCcy"),
4812
+ defaultType,
4813
+ context.client
4814
+ );
4733
4815
  const response = await context.client.privatePost(
4734
4816
  "/api/v5/trade/order",
4735
4817
  compactObject({
@@ -4738,8 +4820,8 @@ function buildContractTradeTools(cfg) {
4738
4820
  side: requireString(args, "side"),
4739
4821
  posSide: readString(args, "posSide"),
4740
4822
  ordType: requireString(args, "ordType"),
4741
- sz: requireString(args, "sz"),
4742
- tgtCcy: readString(args, "tgtCcy"),
4823
+ sz: resolved.sz,
4824
+ tgtCcy: resolved.tgtCcy,
4743
4825
  px: readString(args, "px"),
4744
4826
  reduceOnly: typeof reduceOnly === "boolean" ? String(reduceOnly) : void 0,
4745
4827
  clOrdId: readString(args, "clOrdId"),
@@ -4748,7 +4830,11 @@ function buildContractTradeTools(cfg) {
4748
4830
  }),
4749
4831
  privateRateLimit(n("place_order"), 60)
4750
4832
  );
4751
- return normalizeResponse(response);
4833
+ const result = normalizeResponse(response);
4834
+ if (resolved.conversionNote) {
4835
+ result._conversion = resolved.conversionNote;
4836
+ }
4837
+ return result;
4752
4838
  }
4753
4839
  },
4754
4840
  // ── cancel_order ─────────────────────────────────────────────────────────
@@ -5823,7 +5909,7 @@ function registerOptionAlgoTools() {
5823
5909
  tgtCcy: {
5824
5910
  type: "string",
5825
5911
  enum: ["base_ccy", "quote_ccy"],
5826
- description: "Size unit. base_ccy(default): sz in contracts, quote_ccy: sz in USDT (may not be supported for options)"
5912
+ description: "Size unit. base_ccy(default): sz in contracts, quote_ccy: sz in USDT (auto-converted to contracts)"
5827
5913
  },
5828
5914
  reduceOnly: {
5829
5915
  type: "boolean",
@@ -5839,6 +5925,13 @@ function registerOptionAlgoTools() {
5839
5925
  handler: async (rawArgs, context) => {
5840
5926
  const args = asRecord(rawArgs);
5841
5927
  const reduceOnly = readBoolean(args, "reduceOnly");
5928
+ const resolved = await resolveQuoteCcySz(
5929
+ requireString(args, "instId"),
5930
+ requireString(args, "sz"),
5931
+ readString(args, "tgtCcy"),
5932
+ "OPTION",
5933
+ context.client
5934
+ );
5842
5935
  const response = await context.client.privatePost(
5843
5936
  "/api/v5/trade/order-algo",
5844
5937
  compactObject({
@@ -5846,8 +5939,8 @@ function registerOptionAlgoTools() {
5846
5939
  tdMode: requireString(args, "tdMode"),
5847
5940
  side: requireString(args, "side"),
5848
5941
  ordType: requireString(args, "ordType"),
5849
- sz: requireString(args, "sz"),
5850
- tgtCcy: readString(args, "tgtCcy"),
5942
+ sz: resolved.sz,
5943
+ tgtCcy: resolved.tgtCcy,
5851
5944
  tpTriggerPx: readString(args, "tpTriggerPx"),
5852
5945
  tpOrdPx: readString(args, "tpOrdPx"),
5853
5946
  tpTriggerPxType: readString(args, "tpTriggerPxType"),
@@ -8248,7 +8341,7 @@ async function cmdDiagnoseMcp(options = {}) {
8248
8341
 
8249
8342
  // src/commands/diagnose.ts
8250
8343
  var CLI_VERSION = readCliVersion();
8251
- var GIT_HASH = true ? "0b9b3b7" : "dev";
8344
+ var GIT_HASH = true ? "5f833a2" : "dev";
8252
8345
  function maskKey2(key) {
8253
8346
  if (!key) return "(not set)";
8254
8347
  if (key.length <= 8) return "****";
@@ -12270,6 +12363,7 @@ function resolveNpx() {
12270
12363
  if (existsSync7(sibling)) return sibling;
12271
12364
  return "npx";
12272
12365
  }
12366
+ var THIRD_PARTY_INSTALL_NOTICE = "Note: This skill was created by a third-party developer, not by OKX. Review SKILL.md before use.";
12273
12367
  async function cmdSkillSearch(run, opts) {
12274
12368
  const args = {};
12275
12369
  if (opts.keyword) args.keyword = opts.keyword;
@@ -12345,11 +12439,7 @@ async function cmdSkillAdd(name, config, json) {
12345
12439
  throw e;
12346
12440
  }
12347
12441
  upsertSkillRecord(meta);
12348
- if (json) {
12349
- outputLine(JSON.stringify({ name: meta.name, version: meta.version, status: "installed" }, null, 2));
12350
- } else {
12351
- outputLine(`\u2713 Skill "${meta.name}" v${meta.version} installed`);
12352
- }
12442
+ printSkillInstallResult(meta, json);
12353
12443
  } finally {
12354
12444
  rmSync(tmpBase, { recursive: true, force: true });
12355
12445
  }
@@ -12442,11 +12532,19 @@ function cmdSkillList(json) {
12442
12532
  outputLine("");
12443
12533
  outputLine(`${skills.length} skills installed.`);
12444
12534
  }
12535
+ function printSkillInstallResult(meta, json) {
12536
+ if (json) {
12537
+ outputLine(JSON.stringify({ name: meta.name, version: meta.version, status: "installed" }, null, 2));
12538
+ } else {
12539
+ outputLine(`\u2713 Skill "${meta.name}" v${meta.version} installed`);
12540
+ outputLine(` ${THIRD_PARTY_INSTALL_NOTICE}`);
12541
+ }
12542
+ }
12445
12543
 
12446
12544
  // src/index.ts
12447
12545
  var _require3 = createRequire3(import.meta.url);
12448
12546
  var CLI_VERSION2 = _require3("../package.json").version;
12449
- var GIT_HASH2 = true ? "0b9b3b7" : "dev";
12547
+ var GIT_HASH2 = true ? "5f833a2" : "dev";
12450
12548
  function handleConfigCommand(action, rest, json, lang, force) {
12451
12549
  if (action === "init") return cmdConfigInit(lang === "zh" ? "zh" : "en");
12452
12550
  if (action === "show") return cmdConfigShow(json);