@okx_ai/okx-trade-cli 1.3.8-beta.5 → 1.3.8-beta.7
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 +319 -46
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2277,10 +2277,60 @@ function buildAlgoConditionalCommonFields(args) {
|
|
|
2277
2277
|
slOrdPx: readString(args, "slOrdPx"),
|
|
2278
2278
|
slTriggerPxType: readString(args, "slTriggerPxType"),
|
|
2279
2279
|
slTriggerRatio: readString(args, "slTriggerRatio"),
|
|
2280
|
-
|
|
2280
|
+
// NOTE: closeFraction intentionally excluded - only valid for FUTURES/SWAP
|
|
2281
|
+
// conditional/oco ordTypes. Spot must not forward this field. The swap/futures
|
|
2282
|
+
// handlers manage closeFraction via resolveAlgoSzOrCloseFraction() (issue #200).
|
|
2281
2283
|
activePx: readString(args, "activePx")
|
|
2282
2284
|
};
|
|
2283
2285
|
}
|
|
2286
|
+
var CLOSE_FRACTION_VALID_ORD_TYPES = /* @__PURE__ */ new Set(["conditional", "oco"]);
|
|
2287
|
+
function isNonMarketOrdPx(px) {
|
|
2288
|
+
return px !== void 0 && px !== "-1";
|
|
2289
|
+
}
|
|
2290
|
+
function assertCloseFractionConstraints(args, ordType, sz, closeFraction) {
|
|
2291
|
+
if (!CLOSE_FRACTION_VALID_ORD_TYPES.has(ordType)) {
|
|
2292
|
+
throw new ValidationError(
|
|
2293
|
+
`closeFraction is only valid for ordType conditional or oco (got "${ordType}").`
|
|
2294
|
+
);
|
|
2295
|
+
}
|
|
2296
|
+
if (closeFraction !== "1") {
|
|
2297
|
+
throw new ValidationError(
|
|
2298
|
+
`closeFraction must be "1" (only full-position close is supported). Got "${closeFraction}".`
|
|
2299
|
+
);
|
|
2300
|
+
}
|
|
2301
|
+
if (sz !== void 0 && sz.length > 0) {
|
|
2302
|
+
throw new ValidationError(
|
|
2303
|
+
`Provide sz OR closeFraction, not both. sz="${sz}", closeFraction="${closeFraction}".`
|
|
2304
|
+
);
|
|
2305
|
+
}
|
|
2306
|
+
if (isNonMarketOrdPx(readString(args, "tpOrdPx")) || isNonMarketOrdPx(readString(args, "slOrdPx"))) {
|
|
2307
|
+
throw new ValidationError(
|
|
2308
|
+
`closeFraction only applies to market TP/SL orders - tpOrdPx/slOrdPx must be "-1" (market) when provided.`
|
|
2309
|
+
);
|
|
2310
|
+
}
|
|
2311
|
+
if (readString(args, "posSide") === "net" && args["reduceOnly"] !== true) {
|
|
2312
|
+
throw new ValidationError(
|
|
2313
|
+
`When closeFraction is used with posSide="net", reduceOnly must be true.`
|
|
2314
|
+
);
|
|
2315
|
+
}
|
|
2316
|
+
}
|
|
2317
|
+
function resolveAlgoSzOrCloseFraction(args, ordType) {
|
|
2318
|
+
const sz = readString(args, "sz");
|
|
2319
|
+
const closeFraction = readString(args, "closeFraction");
|
|
2320
|
+
if (closeFraction !== void 0) {
|
|
2321
|
+
assertCloseFractionConstraints(args, ordType, sz, closeFraction);
|
|
2322
|
+
return { sz: void 0, closeFraction: "1" };
|
|
2323
|
+
}
|
|
2324
|
+
if (!sz || sz.length === 0) {
|
|
2325
|
+
if (CLOSE_FRACTION_VALID_ORD_TYPES.has(ordType)) {
|
|
2326
|
+
throw new ValidationError(
|
|
2327
|
+
`sz or closeFraction is required for ordType "${ordType}".`
|
|
2328
|
+
);
|
|
2329
|
+
}
|
|
2330
|
+
throw new ValidationError(`Missing required parameter "sz".`);
|
|
2331
|
+
}
|
|
2332
|
+
return { sz, closeFraction: void 0 };
|
|
2333
|
+
}
|
|
2284
2334
|
function buildAttachAlgoOrds(source) {
|
|
2285
2335
|
const tpLevels = source["tpLevels"];
|
|
2286
2336
|
if (Array.isArray(tpLevels) && tpLevels.length > 0) {
|
|
@@ -3714,7 +3764,12 @@ function registerAlgoTradeTools() {
|
|
|
3714
3764
|
},
|
|
3715
3765
|
sz: {
|
|
3716
3766
|
type: "string",
|
|
3717
|
-
description: "Number of contracts to close (NOT USDT amount). Use market_get_instruments to get ctVal for conversion."
|
|
3767
|
+
description: "Number of contracts to close (NOT USDT amount). Use market_get_instruments to get ctVal for conversion. Required unless closeFraction is provided (conditional/oco only)."
|
|
3768
|
+
},
|
|
3769
|
+
closeFraction: {
|
|
3770
|
+
type: "string",
|
|
3771
|
+
enum: ["1"],
|
|
3772
|
+
description: 'Close 100% of position (full close). Use instead of sz for conditional/oco ordTypes only. Must be "1" (only full-position close is supported). When posSide=net, reduceOnly must also be true.'
|
|
3718
3773
|
},
|
|
3719
3774
|
tpTriggerPx: {
|
|
3720
3775
|
type: "string",
|
|
@@ -3759,28 +3814,29 @@ function registerAlgoTradeTools() {
|
|
|
3759
3814
|
},
|
|
3760
3815
|
reduceOnly: {
|
|
3761
3816
|
type: "boolean",
|
|
3762
|
-
description: "Ensure order only reduces position"
|
|
3817
|
+
description: "Ensure order only reduces position. Required when closeFraction is used with posSide=net."
|
|
3763
3818
|
},
|
|
3764
|
-
|
|
3819
|
+
algoClOrdId: {
|
|
3765
3820
|
type: "string",
|
|
3766
|
-
description: "Client order ID (
|
|
3821
|
+
description: "Client-assigned algo order ID (1-32 alphanumeric chars). Legacy alias clOrdId is also accepted."
|
|
3767
3822
|
}
|
|
3768
3823
|
},
|
|
3769
|
-
required: ["instId", "tdMode", "side", "ordType"
|
|
3824
|
+
required: ["instId", "tdMode", "side", "ordType"]
|
|
3770
3825
|
},
|
|
3771
3826
|
handler: async (rawArgs, context) => {
|
|
3772
3827
|
const args = asRecord(rawArgs);
|
|
3773
3828
|
const reduceOnly = args.reduceOnly;
|
|
3774
3829
|
const cxlOnClosePos = args.cxlOnClosePos;
|
|
3775
3830
|
const ordType = requireString(args, "ordType");
|
|
3776
|
-
const
|
|
3831
|
+
const szOrCf = resolveAlgoSzOrCloseFraction(args, ordType);
|
|
3832
|
+
const resolved = szOrCf.sz !== void 0 ? await resolveQuoteCcySz(
|
|
3777
3833
|
requireString(args, "instId"),
|
|
3778
|
-
|
|
3834
|
+
szOrCf.sz,
|
|
3779
3835
|
readString(args, "tgtCcy"),
|
|
3780
3836
|
"SWAP",
|
|
3781
3837
|
context.client,
|
|
3782
3838
|
readString(args, "tdMode")
|
|
3783
|
-
);
|
|
3839
|
+
) : { sz: void 0, tgtCcy: void 0, conversionNote: void 0 };
|
|
3784
3840
|
const base = compactObject({
|
|
3785
3841
|
instId: requireString(args, "instId"),
|
|
3786
3842
|
tdMode: requireString(args, "tdMode"),
|
|
@@ -3788,11 +3844,12 @@ function registerAlgoTradeTools() {
|
|
|
3788
3844
|
posSide: readString(args, "posSide"),
|
|
3789
3845
|
ordType,
|
|
3790
3846
|
sz: resolved.sz,
|
|
3847
|
+
closeFraction: szOrCf.closeFraction,
|
|
3791
3848
|
tgtCcy: resolved.tgtCcy,
|
|
3792
3849
|
stpMode: readString(args, "stpMode"),
|
|
3793
3850
|
cxlOnClosePos: typeof cxlOnClosePos === "boolean" ? String(cxlOnClosePos) : void 0,
|
|
3794
3851
|
reduceOnly: typeof reduceOnly === "boolean" ? String(reduceOnly) : void 0,
|
|
3795
|
-
|
|
3852
|
+
algoClOrdId: readString(args, "algoClOrdId") ?? readString(args, "clOrdId"),
|
|
3796
3853
|
// Phase 3a+c CLI power-user flags (issue #182, CLI-only no MCP/skill exposure)
|
|
3797
3854
|
pxAmendType: readString(args, "pxAmendType"),
|
|
3798
3855
|
tag: context.config.sourceTag
|
|
@@ -3877,9 +3934,9 @@ function registerAlgoTradeTools() {
|
|
|
3877
3934
|
type: "boolean",
|
|
3878
3935
|
description: "Ensure order only reduces position"
|
|
3879
3936
|
},
|
|
3880
|
-
|
|
3937
|
+
algoClOrdId: {
|
|
3881
3938
|
type: "string",
|
|
3882
|
-
description: "Client order ID (
|
|
3939
|
+
description: "Client-assigned algo order ID (1-32 alphanumeric chars). Legacy alias clOrdId is also accepted."
|
|
3883
3940
|
}
|
|
3884
3941
|
},
|
|
3885
3942
|
required: ["instId", "tdMode", "side", "sz"]
|
|
@@ -3900,7 +3957,7 @@ function registerAlgoTradeTools() {
|
|
|
3900
3957
|
callBackSpread: readString(args, "callbackSpread"),
|
|
3901
3958
|
activePx: readString(args, "activePx"),
|
|
3902
3959
|
reduceOnly: typeof reduceOnly === "boolean" ? String(reduceOnly) : void 0,
|
|
3903
|
-
|
|
3960
|
+
algoClOrdId: readString(args, "algoClOrdId") ?? readString(args, "clOrdId")
|
|
3904
3961
|
}),
|
|
3905
3962
|
privateRateLimit("swap_place_move_stop_order", 20)
|
|
3906
3963
|
);
|
|
@@ -4081,7 +4138,12 @@ function registerFuturesAlgoTools() {
|
|
|
4081
4138
|
},
|
|
4082
4139
|
sz: {
|
|
4083
4140
|
type: "string",
|
|
4084
|
-
description: "Number of contracts (NOT USDT amount)."
|
|
4141
|
+
description: "Number of contracts (NOT USDT amount). Required unless closeFraction is provided (conditional/oco only)."
|
|
4142
|
+
},
|
|
4143
|
+
closeFraction: {
|
|
4144
|
+
type: "string",
|
|
4145
|
+
enum: ["1"],
|
|
4146
|
+
description: 'Close 100% of position (full close). Use instead of sz for conditional/oco ordTypes only. Must be "1" (only full-position close is supported). When posSide=net, reduceOnly must also be true.'
|
|
4085
4147
|
},
|
|
4086
4148
|
tpTriggerPx: {
|
|
4087
4149
|
type: "string",
|
|
@@ -4126,28 +4188,29 @@ function registerFuturesAlgoTools() {
|
|
|
4126
4188
|
},
|
|
4127
4189
|
reduceOnly: {
|
|
4128
4190
|
type: "boolean",
|
|
4129
|
-
description: "Ensure order only reduces position"
|
|
4191
|
+
description: "Ensure order only reduces position. Required when closeFraction is used with posSide=net."
|
|
4130
4192
|
},
|
|
4131
|
-
|
|
4193
|
+
algoClOrdId: {
|
|
4132
4194
|
type: "string",
|
|
4133
|
-
description: "Client order ID (
|
|
4195
|
+
description: "Client-assigned algo order ID (1-32 alphanumeric chars). Legacy alias clOrdId is also accepted."
|
|
4134
4196
|
}
|
|
4135
4197
|
},
|
|
4136
|
-
required: ["instId", "tdMode", "side", "ordType"
|
|
4198
|
+
required: ["instId", "tdMode", "side", "ordType"]
|
|
4137
4199
|
},
|
|
4138
4200
|
handler: async (rawArgs, context) => {
|
|
4139
4201
|
const args = asRecord(rawArgs);
|
|
4140
4202
|
const reduceOnly = args.reduceOnly;
|
|
4141
4203
|
const cxlOnClosePos = args.cxlOnClosePos;
|
|
4142
4204
|
const ordType = requireString(args, "ordType");
|
|
4143
|
-
const
|
|
4205
|
+
const szOrCf = resolveAlgoSzOrCloseFraction(args, ordType);
|
|
4206
|
+
const resolved = szOrCf.sz !== void 0 ? await resolveQuoteCcySz(
|
|
4144
4207
|
requireString(args, "instId"),
|
|
4145
|
-
|
|
4208
|
+
szOrCf.sz,
|
|
4146
4209
|
readString(args, "tgtCcy"),
|
|
4147
4210
|
"FUTURES",
|
|
4148
4211
|
context.client,
|
|
4149
4212
|
readString(args, "tdMode")
|
|
4150
|
-
);
|
|
4213
|
+
) : { sz: void 0, tgtCcy: void 0, conversionNote: void 0 };
|
|
4151
4214
|
const base = compactObject({
|
|
4152
4215
|
instId: requireString(args, "instId"),
|
|
4153
4216
|
tdMode: requireString(args, "tdMode"),
|
|
@@ -4155,11 +4218,12 @@ function registerFuturesAlgoTools() {
|
|
|
4155
4218
|
posSide: readString(args, "posSide"),
|
|
4156
4219
|
ordType,
|
|
4157
4220
|
sz: resolved.sz,
|
|
4221
|
+
closeFraction: szOrCf.closeFraction,
|
|
4158
4222
|
tgtCcy: resolved.tgtCcy,
|
|
4159
4223
|
stpMode: readString(args, "stpMode"),
|
|
4160
4224
|
cxlOnClosePos: typeof cxlOnClosePos === "boolean" ? String(cxlOnClosePos) : void 0,
|
|
4161
4225
|
reduceOnly: typeof reduceOnly === "boolean" ? String(reduceOnly) : void 0,
|
|
4162
|
-
|
|
4226
|
+
algoClOrdId: readString(args, "algoClOrdId") ?? readString(args, "clOrdId"),
|
|
4163
4227
|
// Phase 3a+c CLI power-user flags (issue #182, CLI-only no MCP/skill exposure)
|
|
4164
4228
|
pxAmendType: readString(args, "pxAmendType"),
|
|
4165
4229
|
tag: context.config.sourceTag
|
|
@@ -4244,9 +4308,9 @@ function registerFuturesAlgoTools() {
|
|
|
4244
4308
|
type: "boolean",
|
|
4245
4309
|
description: "Ensure order only reduces position"
|
|
4246
4310
|
},
|
|
4247
|
-
|
|
4311
|
+
algoClOrdId: {
|
|
4248
4312
|
type: "string",
|
|
4249
|
-
description: "Client order ID (
|
|
4313
|
+
description: "Client-assigned algo order ID (1-32 alphanumeric chars). Legacy alias clOrdId is also accepted."
|
|
4250
4314
|
}
|
|
4251
4315
|
},
|
|
4252
4316
|
required: ["instId", "tdMode", "side", "sz"]
|
|
@@ -4267,7 +4331,7 @@ function registerFuturesAlgoTools() {
|
|
|
4267
4331
|
callBackSpread: readString(args, "callbackSpread"),
|
|
4268
4332
|
activePx: readString(args, "activePx"),
|
|
4269
4333
|
reduceOnly: typeof reduceOnly === "boolean" ? String(reduceOnly) : void 0,
|
|
4270
|
-
|
|
4334
|
+
algoClOrdId: readString(args, "algoClOrdId") ?? readString(args, "clOrdId")
|
|
4271
4335
|
}),
|
|
4272
4336
|
privateRateLimit("futures_place_move_stop_order", 20)
|
|
4273
4337
|
);
|
|
@@ -11145,9 +11209,9 @@ function registerOptionAlgoTools() {
|
|
|
11145
11209
|
type: "boolean",
|
|
11146
11210
|
description: "Ensure order only reduces position"
|
|
11147
11211
|
},
|
|
11148
|
-
|
|
11212
|
+
algoClOrdId: {
|
|
11149
11213
|
type: "string",
|
|
11150
|
-
description: "Client order ID (
|
|
11214
|
+
description: "Client-assigned algo order ID (1-32 alphanumeric chars). Legacy alias clOrdId is also accepted."
|
|
11151
11215
|
}
|
|
11152
11216
|
},
|
|
11153
11217
|
required: ["instId", "tdMode", "side", "ordType", "sz"]
|
|
@@ -11179,7 +11243,7 @@ function registerOptionAlgoTools() {
|
|
|
11179
11243
|
slOrdPx: readString(args, "slOrdPx"),
|
|
11180
11244
|
slTriggerPxType: readString(args, "slTriggerPxType"),
|
|
11181
11245
|
reduceOnly: reduceOnly !== void 0 ? String(reduceOnly) : void 0,
|
|
11182
|
-
|
|
11246
|
+
algoClOrdId: readString(args, "algoClOrdId") ?? readString(args, "clOrdId"),
|
|
11183
11247
|
tag: context.config.sourceTag
|
|
11184
11248
|
}),
|
|
11185
11249
|
privateRateLimit("option_place_algo_order", 20)
|
|
@@ -12087,6 +12151,10 @@ function registerSpotTradeTools() {
|
|
|
12087
12151
|
},
|
|
12088
12152
|
slTriggerPxType: SL_TRIGGER_PX_TYPE_SCHEMA,
|
|
12089
12153
|
stpMode: STP_MODE_SCHEMA,
|
|
12154
|
+
algoClOrdId: {
|
|
12155
|
+
type: "string",
|
|
12156
|
+
description: "Client-assigned algo order ID (1-32 alphanumeric chars). Legacy alias clOrdId is also accepted."
|
|
12157
|
+
},
|
|
12090
12158
|
tgtCcy: {
|
|
12091
12159
|
type: "string",
|
|
12092
12160
|
enum: ["base_ccy", "quote_ccy"],
|
|
@@ -12121,6 +12189,7 @@ function registerSpotTradeTools() {
|
|
|
12121
12189
|
sz: requireString(args, "sz"),
|
|
12122
12190
|
tgtCcy: readString(args, "tgtCcy"),
|
|
12123
12191
|
stpMode: readString(args, "stpMode"),
|
|
12192
|
+
algoClOrdId: readString(args, "algoClOrdId") ?? readString(args, "clOrdId"),
|
|
12124
12193
|
// Phase 3a+c CLI power-user flags (issue #182, CLI-only no MCP/skill exposure)
|
|
12125
12194
|
pxAmendType: readString(args, "pxAmendType"),
|
|
12126
12195
|
tag: context.config.sourceTag
|
|
@@ -14193,6 +14262,115 @@ async function handleAuthCommand(action, _rest, v) {
|
|
|
14193
14262
|
}
|
|
14194
14263
|
}
|
|
14195
14264
|
|
|
14265
|
+
// src/commands/outcomes.ts
|
|
14266
|
+
import { spawn as spawn4 } from "child_process";
|
|
14267
|
+
import { existsSync as existsSync9 } from "fs";
|
|
14268
|
+
import { delimiter, join as join15 } from "path";
|
|
14269
|
+
var OUTCOMES_BINARY_NAME = process.platform === "win32" ? "okx-outcomes.exe" : "okx-outcomes";
|
|
14270
|
+
function resolveOutcomesBinaryPath() {
|
|
14271
|
+
const override = process.env.OKX_OUTCOMES_BIN;
|
|
14272
|
+
if (override) {
|
|
14273
|
+
if (existsSync9(override)) return override;
|
|
14274
|
+
errorLine(
|
|
14275
|
+
`Warning: OKX_OUTCOMES_BIN is set to '${override}' but no file exists there; falling back to PATH search.`
|
|
14276
|
+
);
|
|
14277
|
+
}
|
|
14278
|
+
const paths = (process.env.PATH ?? "").split(delimiter);
|
|
14279
|
+
for (const dir of paths) {
|
|
14280
|
+
if (!dir) continue;
|
|
14281
|
+
const full = join15(dir, OUTCOMES_BINARY_NAME);
|
|
14282
|
+
if (existsSync9(full)) return full;
|
|
14283
|
+
}
|
|
14284
|
+
return null;
|
|
14285
|
+
}
|
|
14286
|
+
function printInstallHint() {
|
|
14287
|
+
errorLine("Error: okx-outcomes binary not found in PATH.");
|
|
14288
|
+
errorLine("");
|
|
14289
|
+
errorLine("Install (macOS / Linux):");
|
|
14290
|
+
errorLine(" curl -fsSL https://raw.githubusercontent.com/okx/outcomes-cli/main/install.sh | sh");
|
|
14291
|
+
errorLine("");
|
|
14292
|
+
errorLine("Install (Windows): download okx-outcomes.exe from");
|
|
14293
|
+
errorLine(" https://github.com/okx/outcomes-cli/releases");
|
|
14294
|
+
errorLine("and place it on your PATH.");
|
|
14295
|
+
errorLine("");
|
|
14296
|
+
errorLine("Or set OKX_OUTCOMES_BIN env var to a custom binary path.");
|
|
14297
|
+
}
|
|
14298
|
+
function runOkxOutcomes(args) {
|
|
14299
|
+
const binPath = resolveOutcomesBinaryPath();
|
|
14300
|
+
if (!binPath) {
|
|
14301
|
+
printInstallHint();
|
|
14302
|
+
return Promise.resolve(127);
|
|
14303
|
+
}
|
|
14304
|
+
return new Promise((resolve4, reject) => {
|
|
14305
|
+
const child = spawn4(binPath, args, { stdio: "inherit" });
|
|
14306
|
+
child.on(
|
|
14307
|
+
"error",
|
|
14308
|
+
(err) => reject(new Error(`Failed to spawn okx-outcomes: ${err.message}`))
|
|
14309
|
+
);
|
|
14310
|
+
child.on("close", (code) => resolve4(code ?? 1));
|
|
14311
|
+
});
|
|
14312
|
+
}
|
|
14313
|
+
function printOutcomesHelp() {
|
|
14314
|
+
const lines = [
|
|
14315
|
+
"Usage: okx outcomes <command> [args...]",
|
|
14316
|
+
"",
|
|
14317
|
+
"OKX Outcomes - YES/NO event contract trading via the okx-outcomes binary.",
|
|
14318
|
+
"",
|
|
14319
|
+
"Common commands:",
|
|
14320
|
+
" data events List outcome events",
|
|
14321
|
+
" data event <eventId> Get event detail",
|
|
14322
|
+
" data event-markets <eventId> Event + all its markets (returns asset ids)",
|
|
14323
|
+
" data market <marketId> Get single market detail",
|
|
14324
|
+
" data trending List trending events",
|
|
14325
|
+
" data ticker <assetId> 24h ticker for an outcome asset",
|
|
14326
|
+
" data candles <assetId> OHLCV candles for an outcome asset",
|
|
14327
|
+
" search <keyword> Search events/markets",
|
|
14328
|
+
" (Note: events/event/market etc. live UNDER the `data` namespace \u2014 calling them",
|
|
14329
|
+
" as top-level commands prints the binary's help instead of returning JSON.)",
|
|
14330
|
+
"",
|
|
14331
|
+
" clob price/prices/midpoint(s)/spread(s)/book(s) --asset <id>",
|
|
14332
|
+
" CLOB read-side market data",
|
|
14333
|
+
" clob create-order Place limit order (EIP-712 signed)",
|
|
14334
|
+
" clob market-order Cross book immediately (IOC/FOK)",
|
|
14335
|
+
" clob cancel-oid | cancel-all | heartbeat",
|
|
14336
|
+
"",
|
|
14337
|
+
" ctf split/merge/redeem Conditional token operations",
|
|
14338
|
+
"",
|
|
14339
|
+
" account balance/order/orders/positions/trades",
|
|
14340
|
+
" Account queries (OAuth sign-in; closed = positions --status closed)",
|
|
14341
|
+
"",
|
|
14342
|
+
" auth login --manual [--json] OAuth device-code sign-in (prints URL+code; agent-friendly)",
|
|
14343
|
+
" auth login [--site global|us] OAuth sign-in, browser-foreground (user at a terminal)",
|
|
14344
|
+
" auth refresh | auth status Verify/refresh session; show sign-in state",
|
|
14345
|
+
" setup status|region|bind Step-by-step onboarding (all non-interactive; agent-runnable)",
|
|
14346
|
+
"",
|
|
14347
|
+
" wallet show Show derived wallet address",
|
|
14348
|
+
" status Health check",
|
|
14349
|
+
" setup Interactive setup wizard (region -> OAuth -> wallet bind)",
|
|
14350
|
+
"",
|
|
14351
|
+
"Run 'okx outcomes <command> --help' for command-specific help.",
|
|
14352
|
+
"",
|
|
14353
|
+
"Note: place flags after the subcommand, e.g. 'okx outcomes events --json'",
|
|
14354
|
+
" (or before the module: 'okx --json outcomes events'). Writing",
|
|
14355
|
+
" 'okx outcomes --json events' is not supported.",
|
|
14356
|
+
"",
|
|
14357
|
+
"Requires: curl -fsSL https://raw.githubusercontent.com/okx/outcomes-cli/main/install.sh | sh"
|
|
14358
|
+
];
|
|
14359
|
+
for (const line of lines) outputLine(line);
|
|
14360
|
+
}
|
|
14361
|
+
async function handleOutcomesCommand(action, rest, v) {
|
|
14362
|
+
if (!action || action === "--help" || action === "-h" || action === "help") {
|
|
14363
|
+
printOutcomesHelp();
|
|
14364
|
+
return;
|
|
14365
|
+
}
|
|
14366
|
+
const forwardArgs = [action, ...rest];
|
|
14367
|
+
if (v.json && !forwardArgs.includes("--json") && !forwardArgs.includes("-j")) {
|
|
14368
|
+
forwardArgs.push("--json");
|
|
14369
|
+
}
|
|
14370
|
+
const code = await runOkxOutcomes(forwardArgs);
|
|
14371
|
+
if (code !== 0) process.exitCode = code;
|
|
14372
|
+
}
|
|
14373
|
+
|
|
14196
14374
|
// src/commands/diagnose.ts
|
|
14197
14375
|
import dns from "dns/promises";
|
|
14198
14376
|
import net from "net";
|
|
@@ -14287,7 +14465,7 @@ function sanitize2(value) {
|
|
|
14287
14465
|
import fs5 from "fs";
|
|
14288
14466
|
import path4 from "path";
|
|
14289
14467
|
import os4 from "os";
|
|
14290
|
-
import { spawnSync, spawn as
|
|
14468
|
+
import { spawnSync, spawn as spawn5 } from "child_process";
|
|
14291
14469
|
import { createRequire as createRequire2 } from "module";
|
|
14292
14470
|
import { fileURLToPath } from "url";
|
|
14293
14471
|
var _require2 = createRequire2(import.meta.url);
|
|
@@ -14621,7 +14799,7 @@ async function checkStdioHandshake(entryPath, report) {
|
|
|
14621
14799
|
clearTimeout(timer);
|
|
14622
14800
|
resolve4(passed);
|
|
14623
14801
|
};
|
|
14624
|
-
const child =
|
|
14802
|
+
const child = spawn5(process.execPath, [entryPath], {
|
|
14625
14803
|
stdio: ["pipe", "pipe", "pipe"],
|
|
14626
14804
|
env: { ...process.env }
|
|
14627
14805
|
});
|
|
@@ -14740,7 +14918,7 @@ async function cmdDiagnoseMcp(options = {}) {
|
|
|
14740
14918
|
|
|
14741
14919
|
// src/commands/diagnose.ts
|
|
14742
14920
|
var CLI_VERSION = readCliVersion();
|
|
14743
|
-
var GIT_HASH = true ? "
|
|
14921
|
+
var GIT_HASH = true ? "c102867d" : "dev";
|
|
14744
14922
|
function maskKey2(key) {
|
|
14745
14923
|
if (!key) return "(not set)";
|
|
14746
14924
|
if (key.length <= 8) return "****";
|
|
@@ -15102,12 +15280,12 @@ function suggestSubcommand(action, knownActions, knownPaths = []) {
|
|
|
15102
15280
|
// src/commands/upgrade.ts
|
|
15103
15281
|
import { spawnSync as spawnSync2 } from "child_process";
|
|
15104
15282
|
import { readFileSync as readFileSync11, writeFileSync as writeFileSync8, mkdirSync as mkdirSync11 } from "fs";
|
|
15105
|
-
import { dirname as dirname8, join as
|
|
15283
|
+
import { dirname as dirname8, join as join16 } from "path";
|
|
15106
15284
|
import { homedir as homedir11 } from "os";
|
|
15107
15285
|
var PACKAGES = ["@okx_ai/okx-trade-mcp", "@okx_ai/okx-trade-cli"];
|
|
15108
|
-
var CACHE_FILE2 =
|
|
15286
|
+
var CACHE_FILE2 = join16(homedir11(), ".okx", "last_check");
|
|
15109
15287
|
var THROTTLE_MS = 12 * 60 * 60 * 1e3;
|
|
15110
|
-
var NPM_BIN =
|
|
15288
|
+
var NPM_BIN = join16(dirname8(process.execPath), process.platform === "win32" ? "npm.cmd" : "npm");
|
|
15111
15289
|
function readLastCheck() {
|
|
15112
15290
|
try {
|
|
15113
15291
|
return parseInt(readFileSync11(CACHE_FILE2, "utf-8").trim(), 10) || 0;
|
|
@@ -15117,7 +15295,7 @@ function readLastCheck() {
|
|
|
15117
15295
|
}
|
|
15118
15296
|
function writeLastCheck() {
|
|
15119
15297
|
try {
|
|
15120
|
-
mkdirSync11(
|
|
15298
|
+
mkdirSync11(join16(homedir11(), ".okx"), { recursive: true });
|
|
15121
15299
|
writeFileSync8(CACHE_FILE2, String(Math.floor(Date.now() / 1e3)), "utf-8");
|
|
15122
15300
|
} catch {
|
|
15123
15301
|
}
|
|
@@ -16278,6 +16456,68 @@ var CLI_REGISTRY = {
|
|
|
16278
16456
|
description: "Upgrade okx CLI and MCP server to the latest stable version",
|
|
16279
16457
|
usage: "okx upgrade [--check] [--beta] [--force] [--json]"
|
|
16280
16458
|
},
|
|
16459
|
+
// ── outcomes ───────────────────────────────────────────────────────────────
|
|
16460
|
+
// External binary wrapper - forwards to the okx-outcomes binary (formerly okx-predict).
|
|
16461
|
+
// All toolName=null because outcomes commands are not exposed as MCP tools.
|
|
16462
|
+
outcomes: {
|
|
16463
|
+
description: "OKX Outcomes markets (YES/NO event contracts) via external okx-outcomes binary",
|
|
16464
|
+
commands: {
|
|
16465
|
+
// Note: events / event / event-markets / market / trending / ticker /
|
|
16466
|
+
// candles live UNDER the `data` namespace in the upstream binary.
|
|
16467
|
+
// Calling them as top-level commands prints the binary's help text
|
|
16468
|
+
// instead of returning JSON. Always invoke as `okx outcomes data <cmd>`.
|
|
16469
|
+
data: {
|
|
16470
|
+
toolName: null,
|
|
16471
|
+
usage: "okx outcomes data <events|event|event-markets|market|trending|ticker|candles> [args...]",
|
|
16472
|
+
description: "Public market data namespace: events, event(-markets), market, trending, ticker, candles"
|
|
16473
|
+
},
|
|
16474
|
+
search: {
|
|
16475
|
+
toolName: null,
|
|
16476
|
+
usage: "okx outcomes search <keyword> [--limit <n>] [--cursor <c>]",
|
|
16477
|
+
description: "Search events/markets by keyword (OAuth)"
|
|
16478
|
+
},
|
|
16479
|
+
account: {
|
|
16480
|
+
toolName: null,
|
|
16481
|
+
usage: "okx outcomes account <balance|order|orders|positions|trades> (closed = positions --status closed)",
|
|
16482
|
+
description: "Account queries (OAuth)"
|
|
16483
|
+
},
|
|
16484
|
+
auth: {
|
|
16485
|
+
toolName: null,
|
|
16486
|
+
usage: "okx outcomes auth <login|refresh|status> [--manual] [--site global|us] [--json]",
|
|
16487
|
+
description: "OAuth sign-in / token refresh / session status (login --manual = agent-friendly device-code flow)"
|
|
16488
|
+
},
|
|
16489
|
+
clob: {
|
|
16490
|
+
toolName: null,
|
|
16491
|
+
usage: "okx outcomes clob <price|prices|midpoint|midpoints|spread|spreads|book|books|order|orders|trades|create-order|market-order|cancel-oid|cancel-all|heartbeat>",
|
|
16492
|
+
description: "CLOB market data (--asset) + EIP-712 signed order operations"
|
|
16493
|
+
},
|
|
16494
|
+
ctf: {
|
|
16495
|
+
toolName: null,
|
|
16496
|
+
usage: "okx outcomes ctf <split|merge|redeem> --market <id> [--amount <xp>]",
|
|
16497
|
+
description: "Conditional Token Framework: split xp into YES/NO, merge, redeem"
|
|
16498
|
+
},
|
|
16499
|
+
wallet: {
|
|
16500
|
+
toolName: null,
|
|
16501
|
+
usage: "okx outcomes wallet show",
|
|
16502
|
+
description: "Show derived wallet address (from the signing key)"
|
|
16503
|
+
},
|
|
16504
|
+
status: {
|
|
16505
|
+
toolName: null,
|
|
16506
|
+
usage: "okx outcomes status [--json]",
|
|
16507
|
+
description: "Health check: API + balance reachability"
|
|
16508
|
+
},
|
|
16509
|
+
setup: {
|
|
16510
|
+
toolName: null,
|
|
16511
|
+
usage: "okx outcomes setup [status|region|bind]",
|
|
16512
|
+
description: "Setup wizard (region -> OAuth sign-in -> wallet bind); subcommands: status/region/bind"
|
|
16513
|
+
},
|
|
16514
|
+
shell: {
|
|
16515
|
+
toolName: null,
|
|
16516
|
+
usage: "okx outcomes shell",
|
|
16517
|
+
description: "Interactive REPL (do not invoke from agent context)"
|
|
16518
|
+
}
|
|
16519
|
+
}
|
|
16520
|
+
},
|
|
16281
16521
|
// ── list-tools ──────────────────────────────────────────────────────────────
|
|
16282
16522
|
"list-tools": {
|
|
16283
16523
|
description: "List all available tools and their parameters (use --json for machine-readable output)",
|
|
@@ -17152,6 +17392,30 @@ function parseCli(argv) {
|
|
|
17152
17392
|
}
|
|
17153
17393
|
return { values, positionals };
|
|
17154
17394
|
}
|
|
17395
|
+
function peekFirstPositional(argv) {
|
|
17396
|
+
const booleanFlags = /* @__PURE__ */ new Set();
|
|
17397
|
+
for (const [name, opt] of Object.entries(CLI_OPTIONS)) {
|
|
17398
|
+
const o = opt;
|
|
17399
|
+
if (o.type === "boolean") {
|
|
17400
|
+
booleanFlags.add(name);
|
|
17401
|
+
if (o.short) booleanFlags.add(o.short);
|
|
17402
|
+
}
|
|
17403
|
+
}
|
|
17404
|
+
for (let i = 0; i < argv.length; i++) {
|
|
17405
|
+
const tok = argv[i];
|
|
17406
|
+
if (tok === "--") {
|
|
17407
|
+
const next2 = argv[i + 1];
|
|
17408
|
+
return next2 === void 0 ? void 0 : { module: next2, idx: i + 1 };
|
|
17409
|
+
}
|
|
17410
|
+
if (!tok.startsWith("-")) return { module: tok, idx: i };
|
|
17411
|
+
if (tok.includes("=")) continue;
|
|
17412
|
+
const name = tok.replace(/^--?/, "");
|
|
17413
|
+
if (booleanFlags.has(name)) continue;
|
|
17414
|
+
const next = argv[i + 1];
|
|
17415
|
+
if (next !== void 0 && !next.startsWith("-")) i++;
|
|
17416
|
+
}
|
|
17417
|
+
return void 0;
|
|
17418
|
+
}
|
|
17155
17419
|
|
|
17156
17420
|
// src/commands/market.ts
|
|
17157
17421
|
var NO_INDICATOR_VALUES_HINT = "No indicator values returned. This indicator may require a period \u2014 try --params (e.g. --params 14).";
|
|
@@ -20643,20 +20907,20 @@ async function cmdDcdQuoteAndBuy(run, opts) {
|
|
|
20643
20907
|
|
|
20644
20908
|
// src/commands/skill.ts
|
|
20645
20909
|
import { tmpdir, homedir as homedir13 } from "os";
|
|
20646
|
-
import { join as
|
|
20647
|
-
import { mkdirSync as mkdirSync12, rmSync, existsSync as
|
|
20910
|
+
import { join as join18, dirname as dirname9 } from "path";
|
|
20911
|
+
import { mkdirSync as mkdirSync12, rmSync, existsSync as existsSync11, copyFileSync as copyFileSync2 } from "fs";
|
|
20648
20912
|
import { execFileSync as execFileSync2 } from "child_process";
|
|
20649
20913
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
20650
20914
|
function resolveNpx() {
|
|
20651
|
-
const sibling =
|
|
20652
|
-
if (
|
|
20915
|
+
const sibling = join18(dirname9(process.execPath), "npx");
|
|
20916
|
+
if (existsSync11(sibling)) return sibling;
|
|
20653
20917
|
return "npx";
|
|
20654
20918
|
}
|
|
20655
20919
|
function npxEnv() {
|
|
20656
20920
|
return { ...process.env, NO_COLOR: "1", FORCE_COLOR: "0" };
|
|
20657
20921
|
}
|
|
20658
20922
|
function getSkillContentDir(name) {
|
|
20659
|
-
return
|
|
20923
|
+
return join18(homedir13(), ".agents", "skills", name);
|
|
20660
20924
|
}
|
|
20661
20925
|
var THIRD_PARTY_INSTALL_NOTICE = "Note: This skill was created by a third-party developer, not by OKX. Review SKILL.md before use.";
|
|
20662
20926
|
async function cmdSkillSearch(run, opts) {
|
|
@@ -20722,13 +20986,13 @@ async function wrapVerify(fn) {
|
|
|
20722
20986
|
async function cmdSkillAdd(name, config, json, force = false, exec = execFileSync2, _deps) {
|
|
20723
20987
|
const _download = _deps?.download ?? downloadSkillZip;
|
|
20724
20988
|
const _extract = _deps?.extract ?? extractSkillZip;
|
|
20725
|
-
const tmpBase =
|
|
20989
|
+
const tmpBase = join18(tmpdir(), `okx-skill-${randomUUID2()}`);
|
|
20726
20990
|
mkdirSync12(tmpBase, { recursive: true });
|
|
20727
20991
|
try {
|
|
20728
20992
|
outputLine(`Downloading ${name}...`);
|
|
20729
20993
|
const client = new OkxRestClient(config);
|
|
20730
20994
|
const zipPath = await _download(client, name, tmpBase);
|
|
20731
|
-
const contentDir = await _extract(zipPath,
|
|
20995
|
+
const contentDir = await _extract(zipPath, join18(tmpBase, "content"));
|
|
20732
20996
|
const meta = readMetaJson(contentDir);
|
|
20733
20997
|
validateSkillMdExists(contentDir);
|
|
20734
20998
|
outputLine("Verifying signature...");
|
|
@@ -20765,7 +21029,7 @@ async function cmdSkillAdd(name, config, json, force = false, exec = execFileSyn
|
|
|
20765
21029
|
env: npxEnv()
|
|
20766
21030
|
});
|
|
20767
21031
|
} catch (e) {
|
|
20768
|
-
const savedZip =
|
|
21032
|
+
const savedZip = join18(process.cwd(), `${name}.zip`);
|
|
20769
21033
|
try {
|
|
20770
21034
|
copyFileSync2(zipPath, savedZip);
|
|
20771
21035
|
} catch {
|
|
@@ -20878,7 +21142,7 @@ async function cmdSkillVerify(name, config, json) {
|
|
|
20878
21142
|
return;
|
|
20879
21143
|
}
|
|
20880
21144
|
const contentDir = getSkillContentDir(name);
|
|
20881
|
-
if (!
|
|
21145
|
+
if (!existsSync11(contentDir)) {
|
|
20882
21146
|
errorLine(`Skill content directory not found: ${contentDir}`);
|
|
20883
21147
|
errorLine(`Try reinstalling with: okx skill add ${name}`);
|
|
20884
21148
|
process.exitCode = 1;
|
|
@@ -21543,7 +21807,7 @@ async function cmdEventCancel(run, opts) {
|
|
|
21543
21807
|
// src/index.ts
|
|
21544
21808
|
var _require3 = createRequire3(import.meta.url);
|
|
21545
21809
|
var CLI_VERSION2 = _require3("../package.json").version;
|
|
21546
|
-
var GIT_HASH2 = true ? "
|
|
21810
|
+
var GIT_HASH2 = true ? "c102867d" : "dev";
|
|
21547
21811
|
function handlePilotCommand(action, json, force, binaryPath) {
|
|
21548
21812
|
if (action === "status") return cmdPilotStatus(json, binaryPath);
|
|
21549
21813
|
if (action === "install") return cmdPilotInstall(json, binaryPath);
|
|
@@ -23025,7 +23289,16 @@ async function main() {
|
|
|
23025
23289
|
err: (m) => process.stderr.write(m)
|
|
23026
23290
|
});
|
|
23027
23291
|
checkForUpdates("@okx_ai/okx-trade-cli", CLI_VERSION2);
|
|
23028
|
-
const
|
|
23292
|
+
const rawArgv = process.argv.slice(2);
|
|
23293
|
+
const peek = peekFirstPositional(rawArgv);
|
|
23294
|
+
if (peek?.module === "outcomes") {
|
|
23295
|
+
const after = rawArgv.slice(peek.idx + 1);
|
|
23296
|
+
const action2 = after[0];
|
|
23297
|
+
const rest2 = after.slice(1);
|
|
23298
|
+
const json2 = rawArgv.includes("--json") || rawArgv.includes("-j");
|
|
23299
|
+
return handleOutcomesCommand(action2, rest2, { json: json2 });
|
|
23300
|
+
}
|
|
23301
|
+
const { values, positionals } = parseCli(rawArgv);
|
|
23029
23302
|
if (values.version) {
|
|
23030
23303
|
printVersion();
|
|
23031
23304
|
return;
|