@trading-boy/cli 2.0.1 → 2.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/api-client.d.ts +15 -1
- package/dist/api-client.js +57 -14
- package/dist/cli.bundle.js +764 -104
- package/dist/index.d.ts +2 -1
- package/dist/index.js +1 -1
- package/package.json +15 -14
- package/LICENSE +0 -22
package/dist/cli.bundle.js
CHANGED
|
@@ -19,11 +19,20 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
|
|
|
19
19
|
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
20
20
|
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
21
21
|
});
|
|
22
|
-
var __esm = (fn, res) => function __init() {
|
|
23
|
-
|
|
22
|
+
var __esm = (fn, res, err) => function __init() {
|
|
23
|
+
if (err) throw err[0];
|
|
24
|
+
try {
|
|
25
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
26
|
+
} catch (e) {
|
|
27
|
+
throw err = [e], e;
|
|
28
|
+
}
|
|
24
29
|
};
|
|
25
30
|
var __commonJS = (cb, mod) => function __require2() {
|
|
26
|
-
|
|
31
|
+
try {
|
|
32
|
+
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
33
|
+
} catch (e) {
|
|
34
|
+
throw mod = 0, e;
|
|
35
|
+
}
|
|
27
36
|
};
|
|
28
37
|
var __export = (target, all) => {
|
|
29
38
|
for (var name in all)
|
|
@@ -6979,13 +6988,16 @@ var init_credentials = __esm({
|
|
|
6979
6988
|
// dist/api-client.js
|
|
6980
6989
|
var api_client_exports = {};
|
|
6981
6990
|
__export(api_client_exports, {
|
|
6991
|
+
ApiCredentialConflictError: () => ApiCredentialConflictError,
|
|
6992
|
+
ApiCredentialMissingError: () => ApiCredentialMissingError,
|
|
6982
6993
|
ApiError: () => ApiError,
|
|
6983
6994
|
apiRequest: () => apiRequest,
|
|
6984
6995
|
getApiBase: () => getApiBase,
|
|
6985
6996
|
isDevMode: () => isDevMode,
|
|
6986
6997
|
isRemoteMode: () => isRemoteMode,
|
|
6987
6998
|
redactApiKey: () => redactApiKey,
|
|
6988
|
-
resolveApiKey: () => resolveApiKey
|
|
6999
|
+
resolveApiKey: () => resolveApiKey,
|
|
7000
|
+
resolveApiKeyWithSource: () => resolveApiKeyWithSource
|
|
6989
7001
|
});
|
|
6990
7002
|
function isDevMode() {
|
|
6991
7003
|
if (process.env.NODE_ENV !== "development")
|
|
@@ -7000,22 +7012,50 @@ function isDevMode() {
|
|
|
7000
7012
|
return false;
|
|
7001
7013
|
}
|
|
7002
7014
|
}
|
|
7003
|
-
|
|
7004
|
-
const
|
|
7015
|
+
function normalizeCandidateKey(value) {
|
|
7016
|
+
const trimmed = value?.trim();
|
|
7017
|
+
return trimmed ? trimmed : null;
|
|
7018
|
+
}
|
|
7019
|
+
function assertNoCredentialConflicts(candidates) {
|
|
7020
|
+
if (candidates.length <= 1)
|
|
7021
|
+
return;
|
|
7022
|
+
const first = candidates[0].apiKey;
|
|
7023
|
+
const conflictingSources = candidates.filter((candidate) => candidate.apiKey !== first).map((candidate) => candidate.source);
|
|
7024
|
+
if (conflictingSources.length === 0)
|
|
7025
|
+
return;
|
|
7026
|
+
throw new ApiCredentialConflictError([
|
|
7027
|
+
candidates[0].source,
|
|
7028
|
+
...conflictingSources
|
|
7029
|
+
]);
|
|
7030
|
+
}
|
|
7031
|
+
async function resolveApiKeyWithSource(flagKey) {
|
|
7032
|
+
const candidates = [];
|
|
7033
|
+
const envKey = normalizeCandidateKey(process.env.TRADING_BOY_API_KEY);
|
|
7005
7034
|
if (envKey) {
|
|
7006
|
-
|
|
7007
|
-
return envKey;
|
|
7035
|
+
candidates.push({ apiKey: envKey, source: "TRADING_BOY_API_KEY env var" });
|
|
7008
7036
|
}
|
|
7009
|
-
|
|
7010
|
-
|
|
7011
|
-
|
|
7037
|
+
const normalizedFlagKey = normalizeCandidateKey(flagKey);
|
|
7038
|
+
if (normalizedFlagKey) {
|
|
7039
|
+
candidates.push({ apiKey: normalizedFlagKey, source: "--api-key flag" });
|
|
7012
7040
|
}
|
|
7013
7041
|
const stored = await loadCredentials();
|
|
7014
7042
|
if (stored?.apiKey) {
|
|
7015
|
-
|
|
7016
|
-
|
|
7043
|
+
candidates.push({
|
|
7044
|
+
apiKey: stored.apiKey,
|
|
7045
|
+
source: "stored credentials",
|
|
7046
|
+
storedCredentials: stored
|
|
7047
|
+
});
|
|
7048
|
+
}
|
|
7049
|
+
assertNoCredentialConflicts(candidates);
|
|
7050
|
+
const resolved = candidates[0];
|
|
7051
|
+
if (!resolved) {
|
|
7052
|
+
throw new ApiCredentialMissingError();
|
|
7017
7053
|
}
|
|
7018
|
-
|
|
7054
|
+
logger2.debug({ source: resolved.source }, "Using API key");
|
|
7055
|
+
return resolved;
|
|
7056
|
+
}
|
|
7057
|
+
async function resolveApiKey(flagKey) {
|
|
7058
|
+
return (await resolveApiKeyWithSource(flagKey)).apiKey;
|
|
7019
7059
|
}
|
|
7020
7060
|
function enforceHttps(url) {
|
|
7021
7061
|
try {
|
|
@@ -7036,7 +7076,7 @@ function getApiBase() {
|
|
|
7036
7076
|
}
|
|
7037
7077
|
async function apiRequest(path3, options = {}) {
|
|
7038
7078
|
const dev = isDevMode();
|
|
7039
|
-
const apiKey = dev ? void 0 :
|
|
7079
|
+
const apiKey = dev ? void 0 : await resolveApiKey(options.apiKey);
|
|
7040
7080
|
const apiBase = getApiBase();
|
|
7041
7081
|
const url = `${apiBase}${path3}`;
|
|
7042
7082
|
const headers = {
|
|
@@ -7109,14 +7149,14 @@ async function isRemoteMode() {
|
|
|
7109
7149
|
const stored = await loadCredentials();
|
|
7110
7150
|
return !!stored?.apiKey;
|
|
7111
7151
|
}
|
|
7112
|
-
var logger2, DEFAULT_API_BASE, ApiError;
|
|
7152
|
+
var logger2, DEFAULT_API_BASE, ApiError, ApiCredentialMissingError, ApiCredentialConflictError;
|
|
7113
7153
|
var init_api_client = __esm({
|
|
7114
7154
|
"dist/api-client.js"() {
|
|
7115
7155
|
"use strict";
|
|
7116
7156
|
init_logger();
|
|
7117
7157
|
init_credentials();
|
|
7118
7158
|
logger2 = createLogger2("cli-api-client");
|
|
7119
|
-
DEFAULT_API_BASE = "https://api.
|
|
7159
|
+
DEFAULT_API_BASE = "https://api.tradingboy.ai";
|
|
7120
7160
|
ApiError = class extends Error {
|
|
7121
7161
|
status;
|
|
7122
7162
|
body;
|
|
@@ -7127,6 +7167,20 @@ var init_api_client = __esm({
|
|
|
7127
7167
|
this.name = "ApiError";
|
|
7128
7168
|
}
|
|
7129
7169
|
};
|
|
7170
|
+
ApiCredentialMissingError = class extends Error {
|
|
7171
|
+
constructor() {
|
|
7172
|
+
super("Not authenticated. Run `trading-boy login` to set up your API key.");
|
|
7173
|
+
this.name = "ApiCredentialMissingError";
|
|
7174
|
+
}
|
|
7175
|
+
};
|
|
7176
|
+
ApiCredentialConflictError = class extends Error {
|
|
7177
|
+
sources;
|
|
7178
|
+
constructor(sources) {
|
|
7179
|
+
super(`Conflicting API credentials found in ${sources.join(", ")}. Unset one credential source or make them match before running this command.`);
|
|
7180
|
+
this.sources = sources;
|
|
7181
|
+
this.name = "ApiCredentialConflictError";
|
|
7182
|
+
}
|
|
7183
|
+
};
|
|
7130
7184
|
}
|
|
7131
7185
|
});
|
|
7132
7186
|
|
|
@@ -21425,6 +21479,39 @@ function createLogger(_name) {
|
|
|
21425
21479
|
}
|
|
21426
21480
|
|
|
21427
21481
|
// src/public-core-shim.ts
|
|
21482
|
+
var LLM_REASONING_EFFORTS = ["minimal", "low", "medium", "high", "xhigh"];
|
|
21483
|
+
var EXIT_REASONER_MODES = ["off", "observe", "notify", "protect", "manage", "full"];
|
|
21484
|
+
var EXIT_STYLES = ["scalp", "swing", "runner", "defensive", "manual"];
|
|
21485
|
+
var EXIT_TIMEFRAMES = ["scalp", "swing", "runner"];
|
|
21486
|
+
var CUSTOMER_API_KEY_V0_PATTERN = /^(tb_(?:live|test|free)_)([a-f0-9]{32})$/;
|
|
21487
|
+
var CUSTOMER_API_KEY_V1_PATTERN = /^(tb_(live|test)_v1_)([A-Za-z0-9_-]{16})\.([A-Za-z0-9_-]{32})$/;
|
|
21488
|
+
function legacyEnvironmentFromPrefix(prefix) {
|
|
21489
|
+
return prefix === "tb_live_" ? "live" : "test";
|
|
21490
|
+
}
|
|
21491
|
+
function parseCustomerApiKey(apiKey) {
|
|
21492
|
+
if (apiKey.trim() !== apiKey) return null;
|
|
21493
|
+
const v1 = apiKey.match(CUSTOMER_API_KEY_V1_PATTERN);
|
|
21494
|
+
if (v1) {
|
|
21495
|
+
const environment = v1[2];
|
|
21496
|
+
const keyId = v1[3];
|
|
21497
|
+
const secret = v1[4];
|
|
21498
|
+
return {
|
|
21499
|
+
version: 1,
|
|
21500
|
+
environment,
|
|
21501
|
+
keyId,
|
|
21502
|
+
secret,
|
|
21503
|
+
keyPrefix: `${v1[1]}${keyId}`,
|
|
21504
|
+
last4: secret.slice(-4)
|
|
21505
|
+
};
|
|
21506
|
+
}
|
|
21507
|
+
const legacy = apiKey.match(CUSTOMER_API_KEY_V0_PATTERN);
|
|
21508
|
+
if (!legacy) return null;
|
|
21509
|
+
return {
|
|
21510
|
+
version: 0,
|
|
21511
|
+
environment: legacyEnvironmentFromPrefix(legacy[1]),
|
|
21512
|
+
keyPrefix: legacy[1] + legacy[2].substring(0, 8)
|
|
21513
|
+
};
|
|
21514
|
+
}
|
|
21428
21515
|
function normalizeWatchlistSymbol(value) {
|
|
21429
21516
|
const trimmed = value.trim();
|
|
21430
21517
|
if (trimmed.length === 0) return trimmed;
|
|
@@ -22208,8 +22295,8 @@ function formatPnl(pnl) {
|
|
|
22208
22295
|
if (pnl === null) {
|
|
22209
22296
|
return source_default.dim("-");
|
|
22210
22297
|
}
|
|
22211
|
-
const sign = pnl >= 0 ? "+" : "";
|
|
22212
|
-
const str = `${sign}$${pnl.toFixed(2)}`;
|
|
22298
|
+
const sign = pnl >= 0 ? "+" : "-";
|
|
22299
|
+
const str = `${sign}$${Math.abs(pnl).toFixed(2)}`;
|
|
22213
22300
|
return pnl > 0 ? source_default.green(str) : pnl < 0 ? source_default.red(str) : source_default.dim(str);
|
|
22214
22301
|
}
|
|
22215
22302
|
function formatPercent(pct) {
|
|
@@ -22472,6 +22559,7 @@ init_utils();
|
|
|
22472
22559
|
init_api_client();
|
|
22473
22560
|
init_esm15();
|
|
22474
22561
|
var logger9 = createLogger("cli-trader");
|
|
22562
|
+
var ALIAS_PATTERN = /^[a-zA-Z0-9_-]{3,30}$/;
|
|
22475
22563
|
function formatTraderOutput(trader, wallets) {
|
|
22476
22564
|
const lines = [];
|
|
22477
22565
|
lines.push("");
|
|
@@ -22495,6 +22583,10 @@ function formatTraderOutput(trader, wallets) {
|
|
|
22495
22583
|
lines.push(` ${source_default.dim("\u2022")} ${source_default.white(w.address)} ${source_default.dim(`(${w.chain})`)} ${source_default.dim(`since ${w.since}`)}`);
|
|
22496
22584
|
}
|
|
22497
22585
|
}
|
|
22586
|
+
lines.push(` ${source_default.gray("Public Board:")} ${trader.benchmarkOptIn ? source_default.green("visible") : source_default.dim("private")}`);
|
|
22587
|
+
if (trader.publicAlias) {
|
|
22588
|
+
lines.push(` ${source_default.gray("Public Alias:")} ${source_default.white(trader.publicAlias)}`);
|
|
22589
|
+
}
|
|
22498
22590
|
lines.push("");
|
|
22499
22591
|
lines.push(` ${source_default.gray("Created:")} ${source_default.dim(trader.createdAt)}`);
|
|
22500
22592
|
lines.push(` ${source_default.gray("Updated:")} ${source_default.dim(trader.updatedAt)}`);
|
|
@@ -22526,14 +22618,26 @@ function formatTraderListOutput(traders) {
|
|
|
22526
22618
|
}
|
|
22527
22619
|
function registerTraderCommand(program2) {
|
|
22528
22620
|
const trader = program2.command("trader").description("Manage trader profiles");
|
|
22529
|
-
trader.command("register").description("Register a new trader profile").requiredOption("--name <name>", "Trader display name").option("--wallet <address>", "Initial Solana wallet address").option("--max-drawdown <pct>", "Max acceptable drawdown percentage", parseFloatOption).addOption(new Option("--format <format>", "Output format").choices(["text", "json"]).default("text")).action(async (options) => {
|
|
22621
|
+
trader.command("register").description("Register a new trader profile").requiredOption("--name <name>", "Trader display name").option("--wallet <address>", "Initial Solana wallet address").option("--max-drawdown <pct>", "Max acceptable drawdown percentage", parseFloatOption).option("--public-leaderboard", "Opt this trader into the public leaderboard").option("--alias <alias>", "Public leaderboard alias for --public-leaderboard").addOption(new Option("--format <format>", "Output format").choices(["text", "json"]).default("text")).action(async (options) => {
|
|
22622
|
+
if (options.publicLeaderboard && !options.alias) {
|
|
22623
|
+
console.error(source_default.red("Error: --alias is required with --public-leaderboard."));
|
|
22624
|
+
process.exitCode = 1;
|
|
22625
|
+
return;
|
|
22626
|
+
}
|
|
22627
|
+
if (options.alias && !ALIAS_PATTERN.test(options.alias)) {
|
|
22628
|
+
console.error(source_default.red("Error: Invalid alias. Must be 3-30 characters, alphanumeric with underscores and hyphens."));
|
|
22629
|
+
process.exitCode = 1;
|
|
22630
|
+
return;
|
|
22631
|
+
}
|
|
22530
22632
|
try {
|
|
22531
22633
|
const result = await apiRequest("/api/v1/traders", {
|
|
22532
22634
|
method: "POST",
|
|
22533
22635
|
body: {
|
|
22534
22636
|
name: options.name,
|
|
22535
22637
|
wallet: options.wallet,
|
|
22536
|
-
maxDrawdown: options.maxDrawdown
|
|
22638
|
+
maxDrawdown: options.maxDrawdown,
|
|
22639
|
+
benchmarkOptIn: options.publicLeaderboard === true,
|
|
22640
|
+
publicAlias: options.alias
|
|
22537
22641
|
}
|
|
22538
22642
|
});
|
|
22539
22643
|
const traderId = result.name ?? result.id;
|
|
@@ -22549,8 +22653,11 @@ function registerTraderCommand(program2) {
|
|
|
22549
22653
|
} else {
|
|
22550
22654
|
console.log(formatTraderOutput(result));
|
|
22551
22655
|
console.log(source_default.green(" Trader registered successfully."));
|
|
22552
|
-
if (result.
|
|
22553
|
-
console.log(` ${source_default.gray("Leaderboard alias:")} ${source_default.white(result.
|
|
22656
|
+
if (result.publicAlias) {
|
|
22657
|
+
console.log(` ${source_default.gray("Leaderboard alias:")} ${source_default.white(result.publicAlias)} ${source_default.dim("(change with: trading-boy trader set-alias <name> <alias>)")}`);
|
|
22658
|
+
} else {
|
|
22659
|
+
console.log(` ${source_default.gray("Public leaderboard:")} ${source_default.dim("private by default")}`);
|
|
22660
|
+
console.log(` ${source_default.dim("Opt in later:")} ${source_default.white("trading-boy trader leaderboard opt-in <name> <alias>")}`);
|
|
22554
22661
|
}
|
|
22555
22662
|
console.log("");
|
|
22556
22663
|
console.log(source_default.bold(" Next: Set up your trading identity"));
|
|
@@ -22636,7 +22743,46 @@ function registerTraderCommand(program2) {
|
|
|
22636
22743
|
process.exitCode = error2 instanceof ApiError ? 2 : 1;
|
|
22637
22744
|
}
|
|
22638
22745
|
});
|
|
22639
|
-
const
|
|
22746
|
+
const leaderboard = trader.command("leaderboard").description("Manage public leaderboard visibility");
|
|
22747
|
+
leaderboard.command("opt-in").description("Show a trader on the public leaderboard").argument("<name-or-id>", "Trader name or ID").argument("<alias>", "Public alias (3-30 chars, alphanumeric/underscores/hyphens)").addOption(new Option("--format <format>", "Output format").choices(["text", "json"]).default("text")).action(async (nameOrId, alias, options) => {
|
|
22748
|
+
const jsonMode = options.format === "json";
|
|
22749
|
+
if (!ALIAS_PATTERN.test(alias)) {
|
|
22750
|
+
const msg = "Invalid alias. Must be 3-30 characters, alphanumeric with underscores and hyphens.";
|
|
22751
|
+
if (jsonMode)
|
|
22752
|
+
console.error(JSON.stringify({ error: msg }));
|
|
22753
|
+
else
|
|
22754
|
+
console.error(source_default.red(` ${msg}`));
|
|
22755
|
+
process.exitCode = 1;
|
|
22756
|
+
return;
|
|
22757
|
+
}
|
|
22758
|
+
try {
|
|
22759
|
+
const result = await apiRequest(`/api/v1/traders/${encodeURIComponent(nameOrId)}/public-profile`, { method: "PATCH", body: { benchmarkOptIn: true, publicAlias: alias } });
|
|
22760
|
+
if (jsonMode) {
|
|
22761
|
+
console.log(JSON.stringify(result));
|
|
22762
|
+
} else {
|
|
22763
|
+
console.log("");
|
|
22764
|
+
console.log(source_default.green(` Public leaderboard enabled as: ${source_default.white(result.publicAlias)}`));
|
|
22765
|
+
console.log("");
|
|
22766
|
+
}
|
|
22767
|
+
} catch (error2) {
|
|
22768
|
+
handlePublicProfileError(error2, jsonMode, "enable public leaderboard");
|
|
22769
|
+
}
|
|
22770
|
+
});
|
|
22771
|
+
leaderboard.command("opt-out").description("Hide a trader from the public leaderboard").argument("<name-or-id>", "Trader name or ID").addOption(new Option("--format <format>", "Output format").choices(["text", "json"]).default("text")).action(async (nameOrId, options) => {
|
|
22772
|
+
const jsonMode = options.format === "json";
|
|
22773
|
+
try {
|
|
22774
|
+
const result = await apiRequest(`/api/v1/traders/${encodeURIComponent(nameOrId)}/public-profile`, { method: "PATCH", body: { benchmarkOptIn: false } });
|
|
22775
|
+
if (jsonMode) {
|
|
22776
|
+
console.log(JSON.stringify(result));
|
|
22777
|
+
} else {
|
|
22778
|
+
console.log("");
|
|
22779
|
+
console.log(source_default.green(" Public leaderboard disabled. This trader is private."));
|
|
22780
|
+
console.log("");
|
|
22781
|
+
}
|
|
22782
|
+
} catch (error2) {
|
|
22783
|
+
handlePublicProfileError(error2, jsonMode, "disable public leaderboard");
|
|
22784
|
+
}
|
|
22785
|
+
});
|
|
22640
22786
|
trader.command("set-alias").description("Set a public leaderboard alias").argument("<name-or-id>", "Trader name or ID").argument("<alias>", "Leaderboard alias (3-30 chars, alphanumeric/underscores/hyphens)").addOption(new Option("--format <format>", "Output format").choices(["text", "json"]).default("text")).action(async (nameOrId, alias, options) => {
|
|
22641
22787
|
const jsonMode = options.format === "json";
|
|
22642
22788
|
if (!ALIAS_PATTERN.test(alias)) {
|
|
@@ -23210,6 +23356,19 @@ function handleAgentError(error2, jsonMode, agentId, action) {
|
|
|
23210
23356
|
}
|
|
23211
23357
|
process.exitCode = error2 instanceof ApiError ? 2 : 1;
|
|
23212
23358
|
}
|
|
23359
|
+
function handlePublicProfileError(error2, jsonMode, action) {
|
|
23360
|
+
let message = error2 instanceof Error ? error2.message : String(error2);
|
|
23361
|
+
if (error2 instanceof ApiError && error2.status === 409) {
|
|
23362
|
+
message = "Alias already taken. Try a different name.";
|
|
23363
|
+
}
|
|
23364
|
+
logger9.error({ error: message }, `Failed to ${action}`);
|
|
23365
|
+
if (jsonMode) {
|
|
23366
|
+
console.error(JSON.stringify({ error: message }));
|
|
23367
|
+
} else {
|
|
23368
|
+
console.error(source_default.red(`Error: ${message}`));
|
|
23369
|
+
}
|
|
23370
|
+
process.exitCode = error2 instanceof ApiError ? 2 : 1;
|
|
23371
|
+
}
|
|
23213
23372
|
function parseFloatOption(value) {
|
|
23214
23373
|
return parseFloat(value);
|
|
23215
23374
|
}
|
|
@@ -24408,6 +24567,9 @@ init_logger();
|
|
|
24408
24567
|
init_api_client();
|
|
24409
24568
|
init_utils();
|
|
24410
24569
|
var logger14 = createLogger2("cli-public-config");
|
|
24570
|
+
function formatModelReasoning(model, reasoningEffort) {
|
|
24571
|
+
return reasoningEffort ? `${model} (${reasoningEffort})` : model;
|
|
24572
|
+
}
|
|
24411
24573
|
function printLlmConfig(result) {
|
|
24412
24574
|
console.log("");
|
|
24413
24575
|
console.log(source_default.bold.cyan(" LLM Configuration"));
|
|
@@ -24416,21 +24578,21 @@ function printLlmConfig(result) {
|
|
|
24416
24578
|
if (result.effectiveProvider && (result.effectiveProvider !== result.provider || result.effectiveModel !== result.model)) {
|
|
24417
24579
|
console.log(` ${source_default.gray("Effective:")} ${result.effectiveProvider} / ${result.effectiveModel ?? result.model}`);
|
|
24418
24580
|
}
|
|
24419
|
-
console.log(` ${source_default.gray("Model:")} ${result.model}`);
|
|
24420
|
-
if (result.scanProvider || result.scanModel) {
|
|
24421
|
-
console.log(` ${source_default.gray("Scan:")} ${result.scanProvider ?? result.provider} / ${result.scanModel ?? result.model}`);
|
|
24581
|
+
console.log(` ${source_default.gray("Model:")} ${formatModelReasoning(result.model, result.reasoningEffort)}`);
|
|
24582
|
+
if (result.scanProvider || result.scanModel || result.scanReasoningEffort) {
|
|
24583
|
+
console.log(` ${source_default.gray("Scan:")} ${result.scanProvider ?? result.provider} / ${formatModelReasoning(result.scanModel ?? result.model, result.scanReasoningEffort ?? result.reasoningEffort)}`);
|
|
24422
24584
|
}
|
|
24423
|
-
if (result.analyzeProvider || result.analyzeModel) {
|
|
24424
|
-
console.log(` ${source_default.gray("Analyze:")} ${result.analyzeProvider ?? result.provider} / ${result.analyzeModel ?? result.model}`);
|
|
24585
|
+
if (result.analyzeProvider || result.analyzeModel || result.analyzeReasoningEffort) {
|
|
24586
|
+
console.log(` ${source_default.gray("Analyze:")} ${result.analyzeProvider ?? result.provider} / ${formatModelReasoning(result.analyzeModel ?? result.model, result.analyzeReasoningEffort ?? result.reasoningEffort)}`);
|
|
24425
24587
|
}
|
|
24426
|
-
if (result.decideProvider || result.decideModel) {
|
|
24427
|
-
console.log(` ${source_default.gray("Decide:")} ${result.decideProvider ?? result.provider} / ${result.decideModel ?? result.model}`);
|
|
24588
|
+
if (result.decideProvider || result.decideModel || result.decideReasoningEffort) {
|
|
24589
|
+
console.log(` ${source_default.gray("Decide:")} ${result.decideProvider ?? result.provider} / ${formatModelReasoning(result.decideModel ?? result.model, result.decideReasoningEffort ?? result.reasoningEffort)}`);
|
|
24428
24590
|
}
|
|
24429
|
-
if (result.exitHeartbeatModel) {
|
|
24430
|
-
console.log(` ${source_default.gray("Exit HB:")} ${result.exitHeartbeatModel}`);
|
|
24591
|
+
if (result.exitHeartbeatModel || result.exitHeartbeatReasoningEffort) {
|
|
24592
|
+
console.log(` ${source_default.gray("Exit HB:")} ${formatModelReasoning(result.exitHeartbeatModel ?? result.model, result.exitHeartbeatReasoningEffort ?? result.reasoningEffort)}`);
|
|
24431
24593
|
}
|
|
24432
|
-
if (result.exitEventModel) {
|
|
24433
|
-
console.log(` ${source_default.gray("Exit Event:")} ${result.exitEventModel}`);
|
|
24594
|
+
if (result.exitEventModel || result.exitEventReasoningEffort) {
|
|
24595
|
+
console.log(` ${source_default.gray("Exit Event:")} ${formatModelReasoning(result.exitEventModel ?? result.model, result.exitEventReasoningEffort ?? result.reasoningEffort)}`);
|
|
24434
24596
|
}
|
|
24435
24597
|
if (result.baseUrl) {
|
|
24436
24598
|
console.log(` ${source_default.gray("Base URL:")} ${result.baseUrl}`);
|
|
@@ -24494,7 +24656,44 @@ function registerConfigCommand(program2) {
|
|
|
24494
24656
|
}
|
|
24495
24657
|
printLlmConfig(llmConfig);
|
|
24496
24658
|
});
|
|
24497
|
-
configCmd.command("set-llm-key <apiKey>").description("Store your LLM provider API key for agents, thesis extraction, and coaching (BYOK)").addOption(new Option("-p, --provider <provider>", "LLM provider (auto-detected from key prefix if omitted)").choices([
|
|
24659
|
+
configCmd.command("set-llm-key <apiKey>").description("Store your LLM provider API key for agents, thesis extraction, and coaching (BYOK)").addOption(new Option("-p, --provider <provider>", "LLM provider (auto-detected from key prefix if omitted)").choices([
|
|
24660
|
+
"anthropic",
|
|
24661
|
+
"openai",
|
|
24662
|
+
"openrouter",
|
|
24663
|
+
"ollama",
|
|
24664
|
+
"gemini",
|
|
24665
|
+
"groq",
|
|
24666
|
+
"deepseek",
|
|
24667
|
+
"codex",
|
|
24668
|
+
"custom"
|
|
24669
|
+
])).option("-m, --model <model>", "Model name (default for all phases)").option("--base-url <url>", "Custom base URL (for openrouter/ollama/custom providers)").option("--scan-model <model>", "Model for market scanning").option("--analyze-model <model>", "Model for deep analysis").option("--decide-model <model>", "Model for trade decisions").addOption(new Option("--scan-provider <provider>", "Provider for scan phase").choices([
|
|
24670
|
+
"anthropic",
|
|
24671
|
+
"openai",
|
|
24672
|
+
"openrouter",
|
|
24673
|
+
"ollama",
|
|
24674
|
+
"gemini",
|
|
24675
|
+
"groq",
|
|
24676
|
+
"deepseek",
|
|
24677
|
+
"custom"
|
|
24678
|
+
])).option("--scan-key <key>", "LLM provider API key for the scan phase").addOption(new Option("--analyze-provider <provider>", "Provider for analyze phase").choices([
|
|
24679
|
+
"anthropic",
|
|
24680
|
+
"openai",
|
|
24681
|
+
"openrouter",
|
|
24682
|
+
"ollama",
|
|
24683
|
+
"gemini",
|
|
24684
|
+
"groq",
|
|
24685
|
+
"deepseek",
|
|
24686
|
+
"custom"
|
|
24687
|
+
])).option("--analyze-key <key>", "LLM provider API key for the analyze phase").addOption(new Option("--decide-provider <provider>", "Provider for decide phase").choices([
|
|
24688
|
+
"anthropic",
|
|
24689
|
+
"openai",
|
|
24690
|
+
"openrouter",
|
|
24691
|
+
"ollama",
|
|
24692
|
+
"gemini",
|
|
24693
|
+
"groq",
|
|
24694
|
+
"deepseek",
|
|
24695
|
+
"custom"
|
|
24696
|
+
])).option("--decide-key <key>", "LLM provider API key for the decide phase").action(async (apiKey, opts) => {
|
|
24498
24697
|
if (!await ensureRemote())
|
|
24499
24698
|
return;
|
|
24500
24699
|
try {
|
|
@@ -24543,12 +24742,14 @@ function registerConfigCommand(program2) {
|
|
|
24543
24742
|
process.exitCode = error2 instanceof ApiError ? 2 : 1;
|
|
24544
24743
|
}
|
|
24545
24744
|
});
|
|
24546
|
-
configCmd.command("set-models").description("Update per-stage model assignments (works with BYOK or a ChatGPT connection)").option("-m, --model <model>", "Default model for all phases").
|
|
24745
|
+
configCmd.command("set-models").description("Update per-stage model assignments (works with BYOK or a ChatGPT connection)").option("-m, --model <model>", "Default model for all phases").addOption(new Option("--reasoning-effort <effort>", "Default reasoning effort").choices([
|
|
24746
|
+
...LLM_REASONING_EFFORTS
|
|
24747
|
+
])).option("--scan-model <model>", "Model for market scanning").addOption(new Option("--scan-reasoning-effort <effort>", "Reasoning effort for market scanning").choices([...LLM_REASONING_EFFORTS])).option("--analyze-model <model>", "Model for deep analysis").addOption(new Option("--analyze-reasoning-effort <effort>", "Reasoning effort for deep analysis").choices([...LLM_REASONING_EFFORTS])).option("--decide-model <model>", "Model for trade decisions").addOption(new Option("--decide-reasoning-effort <effort>", "Reasoning effort for trade decisions").choices([...LLM_REASONING_EFFORTS])).option("--exit-heartbeat-model <model>", "Model for exit heartbeat checks").addOption(new Option("--exit-heartbeat-reasoning-effort <effort>", "Reasoning effort for exit heartbeat checks").choices([...LLM_REASONING_EFFORTS])).option("--exit-event-model <model>", "Model for exit event-driven analysis").addOption(new Option("--exit-event-reasoning-effort <effort>", "Reasoning effort for exit event-driven analysis").choices([...LLM_REASONING_EFFORTS])).action(async (opts) => {
|
|
24547
24748
|
if (!await ensureRemote())
|
|
24548
24749
|
return;
|
|
24549
|
-
if (!opts.model && !opts.scanModel && !opts.analyzeModel && !opts.decideModel && !opts.exitHeartbeatModel && !opts.exitEventModel) {
|
|
24550
|
-
console.error(source_default.red(" Error: At least one model flag is required."));
|
|
24551
|
-
console.log(source_default.dim(" Example: trading-boy config set-models --
|
|
24750
|
+
if (!opts.model && !opts.reasoningEffort && !opts.scanModel && !opts.scanReasoningEffort && !opts.analyzeModel && !opts.analyzeReasoningEffort && !opts.decideModel && !opts.decideReasoningEffort && !opts.exitHeartbeatModel && !opts.exitHeartbeatReasoningEffort && !opts.exitEventModel && !opts.exitEventReasoningEffort) {
|
|
24751
|
+
console.error(source_default.red(" Error: At least one model or reasoning flag is required."));
|
|
24752
|
+
console.log(source_default.dim(" Example: trading-boy config set-models --model gpt-5.5 --reasoning-effort low"));
|
|
24552
24753
|
process.exitCode = 1;
|
|
24553
24754
|
return;
|
|
24554
24755
|
}
|
|
@@ -24557,27 +24758,33 @@ function registerConfigCommand(program2) {
|
|
|
24557
24758
|
method: "PATCH",
|
|
24558
24759
|
body: {
|
|
24559
24760
|
...opts.model ? { model: opts.model } : {},
|
|
24761
|
+
...opts.reasoningEffort ? { reasoningEffort: opts.reasoningEffort } : {},
|
|
24560
24762
|
...opts.scanModel ? { scanModel: opts.scanModel } : {},
|
|
24763
|
+
...opts.scanReasoningEffort ? { scanReasoningEffort: opts.scanReasoningEffort } : {},
|
|
24561
24764
|
...opts.analyzeModel ? { analyzeModel: opts.analyzeModel } : {},
|
|
24765
|
+
...opts.analyzeReasoningEffort ? { analyzeReasoningEffort: opts.analyzeReasoningEffort } : {},
|
|
24562
24766
|
...opts.decideModel ? { decideModel: opts.decideModel } : {},
|
|
24767
|
+
...opts.decideReasoningEffort ? { decideReasoningEffort: opts.decideReasoningEffort } : {},
|
|
24563
24768
|
...opts.exitHeartbeatModel ? { exitHeartbeatModel: opts.exitHeartbeatModel } : {},
|
|
24564
|
-
...opts.
|
|
24769
|
+
...opts.exitHeartbeatReasoningEffort ? { exitHeartbeatReasoningEffort: opts.exitHeartbeatReasoningEffort } : {},
|
|
24770
|
+
...opts.exitEventModel ? { exitEventModel: opts.exitEventModel } : {},
|
|
24771
|
+
...opts.exitEventReasoningEffort ? { exitEventReasoningEffort: opts.exitEventReasoningEffort } : {}
|
|
24565
24772
|
}
|
|
24566
24773
|
});
|
|
24567
24774
|
console.log("");
|
|
24568
|
-
console.log(source_default.green(" Stage
|
|
24775
|
+
console.log(source_default.green(" Stage LLM settings updated"));
|
|
24569
24776
|
console.log(source_default.gray(" " + "\u2500".repeat(40)));
|
|
24570
|
-
console.log(` ${source_default.gray("Default:")} ${result.model}`);
|
|
24571
|
-
if (result.scanModel)
|
|
24572
|
-
console.log(` ${source_default.gray("Scan:")} ${result.scanModel}`);
|
|
24573
|
-
if (result.analyzeModel)
|
|
24574
|
-
console.log(` ${source_default.gray("Analyze:")} ${result.analyzeModel}`);
|
|
24575
|
-
if (result.decideModel)
|
|
24576
|
-
console.log(` ${source_default.gray("Decide:")} ${result.decideModel}`);
|
|
24577
|
-
if (result.exitHeartbeatModel)
|
|
24578
|
-
console.log(` ${source_default.gray("Exit heartbeat:")} ${result.exitHeartbeatModel}`);
|
|
24579
|
-
if (result.exitEventModel)
|
|
24580
|
-
console.log(` ${source_default.gray("Exit event:")} ${result.exitEventModel}`);
|
|
24777
|
+
console.log(` ${source_default.gray("Default:")} ${formatModelReasoning(result.model, result.reasoningEffort)}`);
|
|
24778
|
+
if (result.scanModel || result.scanReasoningEffort)
|
|
24779
|
+
console.log(` ${source_default.gray("Scan:")} ${formatModelReasoning(result.scanModel ?? result.model, result.scanReasoningEffort ?? result.reasoningEffort)}`);
|
|
24780
|
+
if (result.analyzeModel || result.analyzeReasoningEffort)
|
|
24781
|
+
console.log(` ${source_default.gray("Analyze:")} ${formatModelReasoning(result.analyzeModel ?? result.model, result.analyzeReasoningEffort ?? result.reasoningEffort)}`);
|
|
24782
|
+
if (result.decideModel || result.decideReasoningEffort)
|
|
24783
|
+
console.log(` ${source_default.gray("Decide:")} ${formatModelReasoning(result.decideModel ?? result.model, result.decideReasoningEffort ?? result.reasoningEffort)}`);
|
|
24784
|
+
if (result.exitHeartbeatModel || result.exitHeartbeatReasoningEffort)
|
|
24785
|
+
console.log(` ${source_default.gray("Exit heartbeat:")} ${formatModelReasoning(result.exitHeartbeatModel ?? result.model, result.exitHeartbeatReasoningEffort ?? result.reasoningEffort)}`);
|
|
24786
|
+
if (result.exitEventModel || result.exitEventReasoningEffort)
|
|
24787
|
+
console.log(` ${source_default.gray("Exit event:")} ${formatModelReasoning(result.exitEventModel ?? result.model, result.exitEventReasoningEffort ?? result.reasoningEffort)}`);
|
|
24581
24788
|
console.log("");
|
|
24582
24789
|
console.log(source_default.dim(" Agents will use these models on their next tick."));
|
|
24583
24790
|
console.log("");
|
|
@@ -24640,9 +24847,9 @@ init_source();
|
|
|
24640
24847
|
init_credentials();
|
|
24641
24848
|
init_api_client();
|
|
24642
24849
|
var logger15 = createLogger("cli-login");
|
|
24643
|
-
var
|
|
24850
|
+
var API_KEY_FORMAT_HELP = "Expected: tb_live_v1_<keyId>.<secret>, tb_test_v1_<keyId>.<secret>, or legacy tb_live_<32hex>/tb_test_<32hex>/tb_free_<32hex>";
|
|
24644
24851
|
function validateApiKeyFormat(key) {
|
|
24645
|
-
return
|
|
24852
|
+
return parseCustomerApiKey(key) !== null;
|
|
24646
24853
|
}
|
|
24647
24854
|
async function verifyApiKey(apiKey) {
|
|
24648
24855
|
const apiBase = getApiBase();
|
|
@@ -24704,14 +24911,14 @@ function registerLoginCommand(program2) {
|
|
|
24704
24911
|
if (!input)
|
|
24705
24912
|
return "Trading Boy API key is required";
|
|
24706
24913
|
if (!validateApiKeyFormat(input)) {
|
|
24707
|
-
return
|
|
24914
|
+
return `Invalid Trading Boy API key format. ${API_KEY_FORMAT_HELP}`;
|
|
24708
24915
|
}
|
|
24709
24916
|
return true;
|
|
24710
24917
|
}
|
|
24711
24918
|
});
|
|
24712
24919
|
}
|
|
24713
24920
|
if (!validateApiKeyFormat(apiKey)) {
|
|
24714
|
-
console.error(source_default.red(
|
|
24921
|
+
console.error(source_default.red(` Invalid Trading Boy API key format. ${API_KEY_FORMAT_HELP}`));
|
|
24715
24922
|
process.exitCode = 1;
|
|
24716
24923
|
return;
|
|
24717
24924
|
}
|
|
@@ -24843,34 +25050,31 @@ init_credentials();
|
|
|
24843
25050
|
init_api_client();
|
|
24844
25051
|
var logger17 = createLogger("cli-whoami");
|
|
24845
25052
|
async function executeWhoami() {
|
|
24846
|
-
|
|
24847
|
-
|
|
24848
|
-
|
|
24849
|
-
|
|
24850
|
-
|
|
24851
|
-
|
|
24852
|
-
}
|
|
24853
|
-
|
|
24854
|
-
const creds = await loadCredentials();
|
|
24855
|
-
if (!creds) {
|
|
24856
|
-
return { authenticated: false };
|
|
25053
|
+
let resolved;
|
|
25054
|
+
try {
|
|
25055
|
+
resolved = await resolveApiKeyWithSource();
|
|
25056
|
+
} catch (error2) {
|
|
25057
|
+
if (error2 instanceof ApiCredentialMissingError) {
|
|
25058
|
+
return { authenticated: false };
|
|
25059
|
+
}
|
|
25060
|
+
throw error2;
|
|
24857
25061
|
}
|
|
25062
|
+
const creds = resolved.source === "stored credentials" ? resolved.storedCredentials ?? await loadCredentials() : null;
|
|
24858
25063
|
const result = {
|
|
24859
25064
|
authenticated: true,
|
|
24860
|
-
email: creds
|
|
24861
|
-
plan: creds
|
|
24862
|
-
keyId: creds
|
|
24863
|
-
redactedKey: redactApiKey(
|
|
24864
|
-
storageMethod: creds.
|
|
24865
|
-
storedAt: creds
|
|
25065
|
+
email: creds?.email,
|
|
25066
|
+
plan: creds?.plan,
|
|
25067
|
+
keyId: creds?.keyId,
|
|
25068
|
+
redactedKey: redactApiKey(resolved.apiKey),
|
|
25069
|
+
storageMethod: resolved.source === "stored credentials" ? creds?.storageMethod : resolved.source,
|
|
25070
|
+
storedAt: creds?.storedAt
|
|
24866
25071
|
};
|
|
24867
25072
|
try {
|
|
24868
|
-
const apiKey = await resolveApiKey();
|
|
24869
25073
|
const response = await fetch(`${getApiBase()}/api/v1/auth/verify`, {
|
|
24870
25074
|
method: "POST",
|
|
24871
25075
|
headers: {
|
|
24872
25076
|
"Content-Type": "application/json",
|
|
24873
|
-
"Authorization": `Bearer ${apiKey}`
|
|
25077
|
+
"Authorization": `Bearer ${resolved.apiKey}`
|
|
24874
25078
|
},
|
|
24875
25079
|
body: "{}"
|
|
24876
25080
|
});
|
|
@@ -24939,16 +25143,9 @@ function registerWhoamiCommand(program2) {
|
|
|
24939
25143
|
try {
|
|
24940
25144
|
const result = await executeWhoami();
|
|
24941
25145
|
if (options.showKey && result.authenticated) {
|
|
24942
|
-
const
|
|
24943
|
-
|
|
24944
|
-
|
|
24945
|
-
return;
|
|
24946
|
-
}
|
|
24947
|
-
const creds = await loadCredentials();
|
|
24948
|
-
if (creds) {
|
|
24949
|
-
console.log(creds.apiKey);
|
|
24950
|
-
return;
|
|
24951
|
-
}
|
|
25146
|
+
const resolved = await resolveApiKeyWithSource();
|
|
25147
|
+
console.log(resolved.apiKey);
|
|
25148
|
+
return;
|
|
24952
25149
|
}
|
|
24953
25150
|
if (options.format === "json") {
|
|
24954
25151
|
console.log(JSON.stringify({ ...result, apiUrl: getApiBase() }, null, 2));
|
|
@@ -25369,6 +25566,12 @@ async function openBrowser(url) {
|
|
|
25369
25566
|
// dist/commands/onboarding.js
|
|
25370
25567
|
var DEFAULT_FIRST_AGENT_AUTONOMY = "FULLY_AUTONOMOUS";
|
|
25371
25568
|
var MIN_SCAN_INTERVAL_MS = 6e4;
|
|
25569
|
+
var LEADERBOARD_ALIAS_PATTERN = /^[a-zA-Z0-9_-]{3,30}$/;
|
|
25570
|
+
function defaultLeaderboardAlias(name) {
|
|
25571
|
+
const normalized = name.trim().replace(/[^a-zA-Z0-9_-]+/g, "-").replace(/^-+|-+$/g, "");
|
|
25572
|
+
const alias = normalized || "trader";
|
|
25573
|
+
return alias.slice(0, 24);
|
|
25574
|
+
}
|
|
25372
25575
|
function trackOnboardingEvent(eventType, metadata = {}) {
|
|
25373
25576
|
try {
|
|
25374
25577
|
emitCliProductEvent(eventType, {
|
|
@@ -25442,17 +25645,37 @@ async function runOnboarding() {
|
|
|
25442
25645
|
return true;
|
|
25443
25646
|
}
|
|
25444
25647
|
});
|
|
25648
|
+
const benchmarkOptIn = await confirm({
|
|
25649
|
+
message: "Show this trader on the public leaderboard? You can opt in later from the CLI.",
|
|
25650
|
+
default: false
|
|
25651
|
+
});
|
|
25652
|
+
let publicAlias;
|
|
25653
|
+
if (benchmarkOptIn) {
|
|
25654
|
+
publicAlias = await input({
|
|
25655
|
+
message: "Public leaderboard alias (3-30 letters, numbers, underscores, or hyphens)",
|
|
25656
|
+
default: defaultLeaderboardAlias(name),
|
|
25657
|
+
validate: (v) => LEADERBOARD_ALIAS_PATTERN.test(v.trim()) ? true : "Alias must be 3-30 characters using letters, numbers, underscores, or hyphens."
|
|
25658
|
+
});
|
|
25659
|
+
}
|
|
25445
25660
|
try {
|
|
25446
25661
|
if (await isRemoteMode()) {
|
|
25447
25662
|
const result = await apiRequest("/api/v1/traders", {
|
|
25448
25663
|
method: "POST",
|
|
25449
|
-
body: {
|
|
25664
|
+
body: {
|
|
25665
|
+
name: name.trim(),
|
|
25666
|
+
maxDrawdown: parseFloat(maxDrawdown),
|
|
25667
|
+
benchmarkOptIn,
|
|
25668
|
+
publicAlias: publicAlias?.trim()
|
|
25669
|
+
}
|
|
25450
25670
|
});
|
|
25451
25671
|
console.log(source_default.green(` \u2713 Trader "${result.name}" registered (id: ${result.id})`));
|
|
25452
25672
|
if (result.publicAlias) {
|
|
25453
25673
|
console.log(source_default.dim(` Leaderboard alias: ${result.publicAlias}`));
|
|
25454
25674
|
console.log(source_default.dim(" This alias is public on the leaderboard. Change it anytime:"));
|
|
25455
25675
|
console.log(source_default.dim(" trading-boy trader set-alias <name> <new-alias>"));
|
|
25676
|
+
} else {
|
|
25677
|
+
console.log(source_default.dim(" Public leaderboard: private. Opt in later with:"));
|
|
25678
|
+
console.log(source_default.dim(" trading-boy trader leaderboard opt-in <name> <alias>"));
|
|
25456
25679
|
}
|
|
25457
25680
|
traderName = name.trim();
|
|
25458
25681
|
traderId = result.id;
|
|
@@ -25637,7 +25860,7 @@ function printExploreQuickReference() {
|
|
|
25637
25860
|
console.log(` ${source_default.white("trading-boy stats")} ${source_default.dim("Track performance")}`);
|
|
25638
25861
|
console.log("");
|
|
25639
25862
|
console.log(source_default.dim(" Build an agent later: trading-boy onboarding"));
|
|
25640
|
-
console.log(source_default.dim(" Full docs: https://api.
|
|
25863
|
+
console.log(source_default.dim(" Full docs: https://api.tradingboy.ai/docs"));
|
|
25641
25864
|
console.log("");
|
|
25642
25865
|
}
|
|
25643
25866
|
function printAgentRuntimeOverview() {
|
|
@@ -25681,7 +25904,7 @@ function printAgentQuickReference(traderRegistered) {
|
|
|
25681
25904
|
console.log(` ${source_default.white("trading-boy behavioral profile --trader <trader-id>")} ${source_default.dim("Behavioral analysis")}`);
|
|
25682
25905
|
}
|
|
25683
25906
|
console.log("");
|
|
25684
|
-
console.log(source_default.dim(" Full docs: https://api.
|
|
25907
|
+
console.log(source_default.dim(" Full docs: https://api.tradingboy.ai/docs"));
|
|
25685
25908
|
console.log("");
|
|
25686
25909
|
}
|
|
25687
25910
|
async function resolveTraderId(nameOrId) {
|
|
@@ -26110,7 +26333,7 @@ async function pollForApiKey(token, onTick) {
|
|
|
26110
26333
|
if (result.status === "expired" || result.status === "not_found") {
|
|
26111
26334
|
return {
|
|
26112
26335
|
success: false,
|
|
26113
|
-
error: "Provisioning token expired.
|
|
26336
|
+
error: "Provisioning token expired or was not found. Run `trading-boy forgot-key -e <email>` to request a one-time HTTPS recovery link. Full API keys are never emailed."
|
|
26114
26337
|
};
|
|
26115
26338
|
}
|
|
26116
26339
|
if (result.status === "already_retrieved") {
|
|
@@ -26127,7 +26350,7 @@ async function pollForApiKey(token, onTick) {
|
|
|
26127
26350
|
}
|
|
26128
26351
|
return {
|
|
26129
26352
|
success: false,
|
|
26130
|
-
error: "Timed out waiting for payment confirmation.
|
|
26353
|
+
error: "Timed out waiting for payment confirmation. Check your payment status, rerun `trading-boy subscribe`, or use `trading-boy forgot-key -e <email>` after activation. Full API keys are never emailed."
|
|
26131
26354
|
};
|
|
26132
26355
|
}
|
|
26133
26356
|
async function saveApiKey(apiKey, metadata) {
|
|
@@ -26439,7 +26662,7 @@ function sleep2(ms) {
|
|
|
26439
26662
|
var ALLOWED_CHECKOUT_DOMAINS = /* @__PURE__ */ new Set([
|
|
26440
26663
|
"checkout.stripe.com",
|
|
26441
26664
|
"billing.stripe.com",
|
|
26442
|
-
"api.
|
|
26665
|
+
"api.tradingboy.ai"
|
|
26443
26666
|
]);
|
|
26444
26667
|
function validateBrowserUrl(url) {
|
|
26445
26668
|
const parsed = new URL(url);
|
|
@@ -26595,7 +26818,7 @@ function formatElapsed2(ms) {
|
|
|
26595
26818
|
return `${seconds}s`;
|
|
26596
26819
|
}
|
|
26597
26820
|
function registerForgotKeyCommand(program2) {
|
|
26598
|
-
program2.command("forgot-key").description("Recover your API key
|
|
26821
|
+
program2.command("forgot-key").description("Recover your API key with a one-time HTTPS claim link").requiredOption("-e, --email <email>", "Your account email address").action(async (options) => {
|
|
26599
26822
|
const { email } = options;
|
|
26600
26823
|
if (!isValidEmail2(email)) {
|
|
26601
26824
|
console.error(source_default.red(" Invalid email address."));
|
|
@@ -26610,6 +26833,7 @@ function registerForgotKeyCommand(program2) {
|
|
|
26610
26833
|
const recovery = await requestKeyRecovery(email);
|
|
26611
26834
|
console.log(source_default.white(" Recovery email sent! Check your inbox."));
|
|
26612
26835
|
console.log(source_default.dim(" Click the link in the email to provision a new key."));
|
|
26836
|
+
console.log(source_default.dim(" Full API keys are never emailed."));
|
|
26613
26837
|
console.log("");
|
|
26614
26838
|
let pollResult;
|
|
26615
26839
|
try {
|
|
@@ -26744,9 +26968,9 @@ function formatAttributionOutput(data) {
|
|
|
26744
26968
|
}
|
|
26745
26969
|
lines.push(source_default.bold(" Summary"));
|
|
26746
26970
|
lines.push(` ${source_default.gray("Total PnL:")} ${colorPnl(s.totalPnlUsd ?? 0)}`);
|
|
26747
|
-
lines.push(` ${source_default.gray("Signal Alpha:")} ${
|
|
26748
|
-
lines.push(` ${source_default.gray("Execution Cost:")} ${
|
|
26749
|
-
lines.push(` ${source_default.gray("Timing Variance:")} ${
|
|
26971
|
+
lines.push(` ${source_default.gray("Signal Alpha:")} ${formatPctPoints(s.avgSignalAlphaPct ?? 0)}`);
|
|
26972
|
+
lines.push(` ${source_default.gray("Execution Cost:")} ${formatPctPoints(s.avgExecutionCostPct ?? 0)}`);
|
|
26973
|
+
lines.push(` ${source_default.gray("Timing Variance:")} ${formatPctPoints(s.avgTimingVariancePct ?? 0)}`);
|
|
26750
26974
|
lines.push(` ${source_default.gray("Trade Count:")} ${s.trades ?? 0}`);
|
|
26751
26975
|
const setupEntries = Object.entries(data.analysis.bySetupType ?? {});
|
|
26752
26976
|
if (setupEntries.length > 0) {
|
|
@@ -26755,7 +26979,7 @@ function formatAttributionOutput(data) {
|
|
|
26755
26979
|
lines.push(` ${source_default.gray("Setup".padEnd(20))}${"Signal%".padStart(10)}${"Exec%".padStart(10)}${"Timing%".padStart(10)}${"N".padStart(5)}`);
|
|
26756
26980
|
lines.push(source_default.gray(" " + "\u2500".repeat(55)));
|
|
26757
26981
|
for (const [setup, v] of setupEntries) {
|
|
26758
|
-
lines.push(` ${setup.padEnd(20)}${
|
|
26982
|
+
lines.push(` ${setup.padEnd(20)}${formatPctPoints(v.avgSignalAlphaPct).padStart(10)}${formatPctPoints(v.avgExecutionCostPct).padStart(10)}${formatPctPoints(v.avgTimingVariancePct).padStart(10)}${String(v.trades).padStart(5)}`);
|
|
26759
26983
|
}
|
|
26760
26984
|
}
|
|
26761
26985
|
if (data.analysis.attributions.length > 0) {
|
|
@@ -26790,13 +27014,17 @@ function colorPnl(usd) {
|
|
|
26790
27014
|
}
|
|
26791
27015
|
function formatUsd4(val) {
|
|
26792
27016
|
const v = val ?? 0;
|
|
26793
|
-
const sign = v >= 0 ? "+" : "";
|
|
26794
|
-
return `${sign}$${v.toFixed(2)}`;
|
|
27017
|
+
const sign = v >= 0 ? "+" : "-";
|
|
27018
|
+
return `${sign}$${Math.abs(v).toFixed(2)}`;
|
|
26795
27019
|
}
|
|
26796
27020
|
function formatPct2(val) {
|
|
26797
27021
|
const v = val ?? 0;
|
|
26798
27022
|
return `${v >= 0 ? "+" : ""}${(v * 100).toFixed(1)}%`;
|
|
26799
27023
|
}
|
|
27024
|
+
function formatPctPoints(val) {
|
|
27025
|
+
const v = val ?? 0;
|
|
27026
|
+
return `${v >= 0 ? "+" : ""}${v.toFixed(1)}%`;
|
|
27027
|
+
}
|
|
26800
27028
|
function registerEdgeCommand(program2) {
|
|
26801
27029
|
program2.command("edge <traderId>").description("Analyze trade quality \u2014 edge ratio and PnL attribution").option("--attribution", "Show PnL attribution breakdown instead of edge ratio").option("--token <symbol>", "Filter by token symbol").option("--limit <n>", "Number of trades to analyze (1-500)", "100").addOption(new Option("--format <format>", "Output format").choices(["text", "json"]).default("text")).action(async (traderId, options) => {
|
|
26802
27030
|
try {
|
|
@@ -28149,6 +28377,8 @@ var AUTONOMY_HELP_UPDATE = "Autonomy mode. Choose Fully auto (FULLY_AUTONOMOUS),
|
|
|
28149
28377
|
var MIN_CONFIDENCE_HELP = "Minimum confidence threshold (0-1, so 0.70 = 70%)";
|
|
28150
28378
|
var EXIT_REASONER_HELP = "Enable LLM-powered exit reasoning for open positions (hold, exit, tighten stop, or extend take profit)";
|
|
28151
28379
|
var DISABLE_EXIT_REASONER_HELP = "Disable LLM-powered exit reasoning for open positions";
|
|
28380
|
+
var EXIT_REASONER_MODE_HELP = "Exit reasoner authority mode for open positions";
|
|
28381
|
+
var URGENT_EVENT_EXIT_MODE_HELP = "Urgent event exit review mode; cannot exceed the normal exit reasoner mode";
|
|
28152
28382
|
var SHARED_SCAN_CACHE_INTERNAL_HELP = "Internal/load-test only: bypass shared scan cache for this agent";
|
|
28153
28383
|
var ENABLE_SHARED_SCAN_CACHE_HELP = "Internal/load-test only: re-enable shared scan cache for this agent";
|
|
28154
28384
|
function formatShortDate5(isoString) {
|
|
@@ -28213,7 +28443,7 @@ function parseHumanInterval2(value) {
|
|
|
28213
28443
|
var MIN_SCAN_INTERVAL_MS2 = 6e4;
|
|
28214
28444
|
function registerAgentCommand(program2) {
|
|
28215
28445
|
const agent = program2.command("agent").description("Manage autonomous trading agents");
|
|
28216
|
-
agent.command("create").description("Create a new agent").option("--trader-id <traderId>", "Trader ID").option("--strategy-id <strategyId>", "Strategy ID (optional \u2014 auto-creates if omitted)").option("--name <name>", "Agent name").option("--autonomy <level>", AUTONOMY_HELP_CREATE, "FULLY_AUTONOMOUS").option("--scan-interval <ms>", "Scan interval in raw milliseconds (min 60000; e.g. 300000 = 5m)", "300000").option("--scan-interval-human <duration>", "Scan interval in human-readable format (e.g. 1m, 5m, 15m, 30m, 1h). Overrides --scan-interval").option("--watchlist <symbols>", "Comma-separated token symbols").option("--max-daily-trades <n>", "Max daily trades", "10").option("--max-daily-loss <usd>", "Max daily loss in USD", "500").option("--max-position-size <pct>", "Max position size as decimal (0.10 = 10%)", "0.10").option("--min-confidence <n>", MIN_CONFIDENCE_HELP, "0.60").option("--scan-model <model>", "LLM model for market scanning").option("--analyze-model <model>", "LLM model for deep analysis").option("--decide-model <model>", "LLM model for trade decisions").option("--disable-shared-scan-cache", SHARED_SCAN_CACHE_INTERNAL_HELP).addOption(new Option("--asset-class <class>", "Asset class for this agent").choices(["crypto", "commodities", "mixed"]).default("crypto")).option("--soul-override <text>", "Custom soul/personality for this agent").option("--purpose-override <text>", "Custom purpose/mission for this agent").option("--soul-file <path>", "Load soul from a file").option("--purpose-file <path>", "Load purpose from a file").option("--exit-reasoner", EXIT_REASONER_HELP).addOption(new Option("--format <format>", "Output format").choices(["text", "json"]).default("text")).action(async (options) => {
|
|
28446
|
+
agent.command("create").description("Create a new agent").option("--trader-id <traderId>", "Trader ID").option("--strategy-id <strategyId>", "Strategy ID (optional \u2014 auto-creates if omitted)").option("--name <name>", "Agent name").option("--autonomy <level>", AUTONOMY_HELP_CREATE, "FULLY_AUTONOMOUS").option("--scan-interval <ms>", "Scan interval in raw milliseconds (min 60000; e.g. 300000 = 5m)", "300000").option("--scan-interval-human <duration>", "Scan interval in human-readable format (e.g. 1m, 5m, 15m, 30m, 1h). Overrides --scan-interval").option("--watchlist <symbols>", "Comma-separated token symbols").option("--max-daily-trades <n>", "Max daily trades", "10").option("--max-daily-loss <usd>", "Max daily loss in USD", "500").option("--max-position-size <pct>", "Max position size as decimal (0.10 = 10%)", "0.10").option("--min-confidence <n>", MIN_CONFIDENCE_HELP, "0.60").option("--scan-model <model>", "LLM model for market scanning").option("--analyze-model <model>", "LLM model for deep analysis").option("--decide-model <model>", "LLM model for trade decisions").option("--disable-shared-scan-cache", SHARED_SCAN_CACHE_INTERNAL_HELP).addOption(new Option("--asset-class <class>", "Asset class for this agent").choices(["crypto", "commodities", "mixed"]).default("crypto")).option("--soul-override <text>", "Custom soul/personality for this agent").option("--purpose-override <text>", "Custom purpose/mission for this agent").option("--soul-file <path>", "Load soul from a file").option("--purpose-file <path>", "Load purpose from a file").option("--exit-reasoner", EXIT_REASONER_HELP).addOption(new Option("--exit-reasoner-mode <mode>", EXIT_REASONER_MODE_HELP).choices([...EXIT_REASONER_MODES])).addOption(new Option("--urgent-event-exit-mode <mode>", URGENT_EVENT_EXIT_MODE_HELP).choices([...EXIT_REASONER_MODES])).addOption(new Option("--exit-style <style>", "Exit management preset").choices([...EXIT_STYLES])).addOption(new Option("--exit-timeframe <timeframe>", "Strategy exit timing preset").choices([...EXIT_TIMEFRAMES])).addOption(new Option("--format <format>", "Output format").choices(["text", "json"]).default("text")).action(async (options) => {
|
|
28217
28447
|
if (!await ensureRemote())
|
|
28218
28448
|
return;
|
|
28219
28449
|
if (!options.traderId) {
|
|
@@ -28269,6 +28499,14 @@ function registerAgentCommand(program2) {
|
|
|
28269
28499
|
body.assetClass = options.assetClass;
|
|
28270
28500
|
if (options.exitReasoner)
|
|
28271
28501
|
body.exitReasonerEnabled = true;
|
|
28502
|
+
if (options.exitReasonerMode)
|
|
28503
|
+
body.exitReasonerMode = options.exitReasonerMode;
|
|
28504
|
+
if (options.urgentEventExitMode)
|
|
28505
|
+
body.urgentEventExitReviewMode = options.urgentEventExitMode;
|
|
28506
|
+
if (options.exitStyle)
|
|
28507
|
+
body.exitStyle = options.exitStyle;
|
|
28508
|
+
if (options.exitTimeframe)
|
|
28509
|
+
body.exitTimingPolicy = { timeframe: options.exitTimeframe };
|
|
28272
28510
|
if (options.soulFile) {
|
|
28273
28511
|
const path3 = resolve(options.soulFile);
|
|
28274
28512
|
if (!existsSync2(path3)) {
|
|
@@ -28306,7 +28544,8 @@ function registerAgentCommand(program2) {
|
|
|
28306
28544
|
console.log(` ${source_default.gray("Trader:")} ${result.traderId}`);
|
|
28307
28545
|
console.log(` ${source_default.gray("Strategy:")} ${result.strategyId}${result.autoStrategyCreated ? source_default.dim(" (auto-created)") : ""}`);
|
|
28308
28546
|
console.log(` ${source_default.gray("Autonomy:")} ${formatAutonomy(result.autonomyLevel)}`);
|
|
28309
|
-
console.log(` ${source_default.gray("Exit reasoner:")} ${result.exitReasonerEnabled ? source_default.green("enabled") : source_default.dim("disabled")}`);
|
|
28547
|
+
console.log(` ${source_default.gray("Exit reasoner:")} ${result.exitReasonerEnabled ? source_default.green("enabled") : source_default.dim("disabled")} (${result.exitReasonerMode ?? "off"})`);
|
|
28548
|
+
console.log(` ${source_default.gray("Exit preset:")} ${result.exitStyle ?? "balanced"} / ${result.exitTimingPolicy?.timeframe ?? "swing"}`);
|
|
28310
28549
|
console.log(` ${source_default.gray("Interval:")} ${formatInterval2(result.scanIntervalMs)}`);
|
|
28311
28550
|
console.log(` ${source_default.gray("Next scan:")} ${formatShortDate5(result.nextScanAt)}`);
|
|
28312
28551
|
console.log("");
|
|
@@ -28376,7 +28615,8 @@ function registerAgentCommand(program2) {
|
|
|
28376
28615
|
if (a.decideModel)
|
|
28377
28616
|
console.log(` ${source_default.gray("Decide model:")} ${a.decideModel}`);
|
|
28378
28617
|
console.log(` ${source_default.gray("Shared scan cache:")} ${a.disableSharedScanCache ? source_default.yellow("bypassed") : source_default.dim("enabled")}`);
|
|
28379
|
-
console.log(` ${source_default.gray("Exit reasoner:")} ${a.exitReasonerEnabled ? source_default.green("enabled") : source_default.dim("disabled")}`);
|
|
28618
|
+
console.log(` ${source_default.gray("Exit reasoner:")} ${a.exitReasonerEnabled ? source_default.green("enabled") : source_default.dim("disabled")} (${a.exitReasonerMode ?? "off"})`);
|
|
28619
|
+
console.log(` ${source_default.gray("Exit preset:")} ${a.exitStyle ?? "balanced"} / ${a.exitTimingPolicy?.timeframe ?? "swing"}`);
|
|
28380
28620
|
console.log(` ${source_default.gray("Scan interval:")} ${formatInterval2(a.scanIntervalMs)}`);
|
|
28381
28621
|
console.log(` ${source_default.gray("Max daily trades:")} ${a.maxDailyTrades}`);
|
|
28382
28622
|
console.log(` ${source_default.gray("Max daily loss:")} $${a.maxDailyLossUsd}`);
|
|
@@ -28500,7 +28740,7 @@ function registerAgentCommand(program2) {
|
|
|
28500
28740
|
handleApiError(error2, "Position exit failed", logger30);
|
|
28501
28741
|
}
|
|
28502
28742
|
});
|
|
28503
|
-
agent.command("update <agentId>").description("Update agent config").option("--name <name>", "Agent name").option("--autonomy <level>", AUTONOMY_HELP_UPDATE).option("--scan-interval <ms>", "Scan interval in raw milliseconds (e.g. 300000 = 5m)").option("--scan-interval-human <duration>", "Scan interval in human-readable format (e.g. 1m, 5m, 15m, 30m, 1h). Overrides --scan-interval").option("--watchlist <symbols>", "Comma-separated token symbols").option("--max-daily-trades <n>", "Max daily trades").option("--max-daily-loss <usd>", "Max daily loss in USD").option("--max-position-size <pct>", "Max position size as decimal").option("--min-confidence <n>", MIN_CONFIDENCE_HELP).option("--scan-model <model>", "LLM model for market scanning").option("--analyze-model <model>", "LLM model for deep analysis").option("--decide-model <model>", "LLM model for trade decisions").option("--disable-shared-scan-cache", SHARED_SCAN_CACHE_INTERNAL_HELP).option("--enable-shared-scan-cache", ENABLE_SHARED_SCAN_CACHE_HELP).addOption(new Option("--asset-class <class>", "Asset class for this agent").choices(["crypto", "commodities", "mixed"])).option("--soul-override <text>", "Custom soul/personality for this agent").option("--purpose-override <text>", "Custom purpose/mission for this agent").option("--soul-file <path>", "Load soul from a file").option("--purpose-file <path>", "Load purpose from a file").option("--exit-reasoner", EXIT_REASONER_HELP).option("--disable-exit-reasoner", DISABLE_EXIT_REASONER_HELP).addOption(new Option("--format <format>", "Output format").choices(["text", "json"]).default("text")).action(async (agentId, options) => {
|
|
28743
|
+
agent.command("update <agentId>").description("Update agent config").option("--name <name>", "Agent name").option("--autonomy <level>", AUTONOMY_HELP_UPDATE).option("--scan-interval <ms>", "Scan interval in raw milliseconds (e.g. 300000 = 5m)").option("--scan-interval-human <duration>", "Scan interval in human-readable format (e.g. 1m, 5m, 15m, 30m, 1h). Overrides --scan-interval").option("--watchlist <symbols>", "Comma-separated token symbols").option("--max-daily-trades <n>", "Max daily trades").option("--max-daily-loss <usd>", "Max daily loss in USD").option("--max-position-size <pct>", "Max position size as decimal").option("--min-confidence <n>", MIN_CONFIDENCE_HELP).option("--scan-model <model>", "LLM model for market scanning").option("--analyze-model <model>", "LLM model for deep analysis").option("--decide-model <model>", "LLM model for trade decisions").option("--disable-shared-scan-cache", SHARED_SCAN_CACHE_INTERNAL_HELP).option("--enable-shared-scan-cache", ENABLE_SHARED_SCAN_CACHE_HELP).addOption(new Option("--asset-class <class>", "Asset class for this agent").choices(["crypto", "commodities", "mixed"])).option("--soul-override <text>", "Custom soul/personality for this agent").option("--purpose-override <text>", "Custom purpose/mission for this agent").option("--soul-file <path>", "Load soul from a file").option("--purpose-file <path>", "Load purpose from a file").option("--exit-reasoner", EXIT_REASONER_HELP).option("--disable-exit-reasoner", DISABLE_EXIT_REASONER_HELP).addOption(new Option("--exit-reasoner-mode <mode>", EXIT_REASONER_MODE_HELP).choices([...EXIT_REASONER_MODES])).addOption(new Option("--urgent-event-exit-mode <mode>", URGENT_EVENT_EXIT_MODE_HELP).choices([...EXIT_REASONER_MODES])).addOption(new Option("--exit-style <style>", "Exit management preset").choices([...EXIT_STYLES])).addOption(new Option("--exit-timeframe <timeframe>", "Strategy exit timing preset").choices([...EXIT_TIMEFRAMES])).addOption(new Option("--format <format>", "Output format").choices(["text", "json"]).default("text")).action(async (agentId, options) => {
|
|
28504
28744
|
if (!await ensureRemote())
|
|
28505
28745
|
return;
|
|
28506
28746
|
const body = {};
|
|
@@ -28558,6 +28798,14 @@ function registerAgentCommand(program2) {
|
|
|
28558
28798
|
body.exitReasonerEnabled = true;
|
|
28559
28799
|
if (options.disableExitReasoner)
|
|
28560
28800
|
body.exitReasonerEnabled = false;
|
|
28801
|
+
if (options.exitReasonerMode)
|
|
28802
|
+
body.exitReasonerMode = options.exitReasonerMode;
|
|
28803
|
+
if (options.urgentEventExitMode)
|
|
28804
|
+
body.urgentEventExitReviewMode = options.urgentEventExitMode;
|
|
28805
|
+
if (options.exitStyle)
|
|
28806
|
+
body.exitStyle = options.exitStyle;
|
|
28807
|
+
if (options.exitTimeframe)
|
|
28808
|
+
body.exitTimingPolicy = { timeframe: options.exitTimeframe };
|
|
28561
28809
|
if (options.assetClass)
|
|
28562
28810
|
body.assetClass = options.assetClass;
|
|
28563
28811
|
if (options.soulFile) {
|
|
@@ -28603,6 +28851,417 @@ function registerAgentCommand(program2) {
|
|
|
28603
28851
|
});
|
|
28604
28852
|
}
|
|
28605
28853
|
|
|
28854
|
+
// dist/commands/prediction-market-paper.js
|
|
28855
|
+
init_source();
|
|
28856
|
+
init_api_client();
|
|
28857
|
+
init_utils();
|
|
28858
|
+
var PREDICTION_MARKET_PAPER_RESULTS_CLI_FLAG = "PREDICTION_MARKET_PAPER_RESULTS_CLI_ENABLED";
|
|
28859
|
+
var DEFAULT_PAPER_POSITION_LIMIT = 50;
|
|
28860
|
+
var MAX_PAPER_POSITION_LIMIT = 100;
|
|
28861
|
+
var MAX_PAPER_POSITION_OFFSET = 1e4;
|
|
28862
|
+
var SAFE_IDENTIFIER_PATTERN = /^[A-Za-z0-9_.:@-]+$/;
|
|
28863
|
+
var PAPER_POSITION_STATUSES = [
|
|
28864
|
+
"OPEN",
|
|
28865
|
+
"CLOSING",
|
|
28866
|
+
"CLOSED",
|
|
28867
|
+
"EXPIRED",
|
|
28868
|
+
"RESOLVED_WON",
|
|
28869
|
+
"RESOLVED_LOST",
|
|
28870
|
+
"INVALID",
|
|
28871
|
+
"CANCELED",
|
|
28872
|
+
"SETTLED"
|
|
28873
|
+
];
|
|
28874
|
+
function isPredictionMarketPaperCliEnabled(env2 = process.env) {
|
|
28875
|
+
return env2[PREDICTION_MARKET_PAPER_RESULTS_CLI_FLAG] === "true";
|
|
28876
|
+
}
|
|
28877
|
+
function printDisabled(format2) {
|
|
28878
|
+
const payload = {
|
|
28879
|
+
disabled: true,
|
|
28880
|
+
featureFlag: PREDICTION_MARKET_PAPER_RESULTS_CLI_FLAG,
|
|
28881
|
+
mode: "paper",
|
|
28882
|
+
label: "Paper / Simulated",
|
|
28883
|
+
noVenueOrderPlaced: true,
|
|
28884
|
+
message: "Prediction-market paper result inspection is disabled."
|
|
28885
|
+
};
|
|
28886
|
+
if (format2 === "json") {
|
|
28887
|
+
console.log(JSON.stringify(payload, null, 2));
|
|
28888
|
+
return;
|
|
28889
|
+
}
|
|
28890
|
+
console.log(source_default.yellow("Prediction-market paper result inspection is disabled."));
|
|
28891
|
+
console.log(source_default.dim("Paper / Simulated. No venue order placed. Read-only inspection is unavailable in this CLI environment."));
|
|
28892
|
+
}
|
|
28893
|
+
function validateIdentifier(label, value) {
|
|
28894
|
+
if (!value)
|
|
28895
|
+
return null;
|
|
28896
|
+
if (value.length > 300)
|
|
28897
|
+
return `${label} must be 300 characters or fewer.`;
|
|
28898
|
+
if (!SAFE_IDENTIFIER_PATTERN.test(value)) {
|
|
28899
|
+
return `${label} may contain only letters, numbers, underscore, dot, colon, at, or dash.`;
|
|
28900
|
+
}
|
|
28901
|
+
return null;
|
|
28902
|
+
}
|
|
28903
|
+
function parseTimestamp(label, value) {
|
|
28904
|
+
if (!value)
|
|
28905
|
+
return { value: null, error: null };
|
|
28906
|
+
const parsed = new Date(value);
|
|
28907
|
+
if (Number.isNaN(parsed.getTime())) {
|
|
28908
|
+
return { value: null, error: `${label} must be a valid timestamp.` };
|
|
28909
|
+
}
|
|
28910
|
+
return { value: parsed.toISOString(), error: null };
|
|
28911
|
+
}
|
|
28912
|
+
function parseIntegerOption(label, value, fallback, min, max) {
|
|
28913
|
+
if (value == null)
|
|
28914
|
+
return { value: fallback, error: null };
|
|
28915
|
+
const parsed = Number(value);
|
|
28916
|
+
if (!Number.isInteger(parsed)) {
|
|
28917
|
+
return { value: fallback, error: `${label} must be an integer.` };
|
|
28918
|
+
}
|
|
28919
|
+
if (parsed < min || parsed > max) {
|
|
28920
|
+
return { value: fallback, error: `${label} must be between ${min} and ${max}.` };
|
|
28921
|
+
}
|
|
28922
|
+
return { value: parsed, error: null };
|
|
28923
|
+
}
|
|
28924
|
+
function validateWindow(from, to) {
|
|
28925
|
+
if (!from || !to)
|
|
28926
|
+
return null;
|
|
28927
|
+
return new Date(from) < new Date(to) ? null : "--from must be before --to.";
|
|
28928
|
+
}
|
|
28929
|
+
function printValidationError(message) {
|
|
28930
|
+
console.error(source_default.red(`Error: ${message}`));
|
|
28931
|
+
process.exitCode = 1;
|
|
28932
|
+
}
|
|
28933
|
+
function buildQuery(options, includePagination) {
|
|
28934
|
+
for (const [label, value] of [
|
|
28935
|
+
["--agent", options.agent],
|
|
28936
|
+
["--venue", options.venue],
|
|
28937
|
+
["--market-id", options.marketId],
|
|
28938
|
+
["--instrument-key", options.instrumentKey]
|
|
28939
|
+
]) {
|
|
28940
|
+
const error2 = validateIdentifier(label, value);
|
|
28941
|
+
if (error2) {
|
|
28942
|
+
printValidationError(error2);
|
|
28943
|
+
return null;
|
|
28944
|
+
}
|
|
28945
|
+
}
|
|
28946
|
+
const from = parseTimestamp("--from", options.from);
|
|
28947
|
+
if (from.error) {
|
|
28948
|
+
printValidationError(from.error);
|
|
28949
|
+
return null;
|
|
28950
|
+
}
|
|
28951
|
+
const to = parseTimestamp("--to", options.to);
|
|
28952
|
+
if (to.error) {
|
|
28953
|
+
printValidationError(to.error);
|
|
28954
|
+
return null;
|
|
28955
|
+
}
|
|
28956
|
+
const windowError = validateWindow(from.value, to.value);
|
|
28957
|
+
if (windowError) {
|
|
28958
|
+
printValidationError(windowError);
|
|
28959
|
+
return null;
|
|
28960
|
+
}
|
|
28961
|
+
const params = new URLSearchParams();
|
|
28962
|
+
if (options.agent)
|
|
28963
|
+
params.set("agentId", options.agent);
|
|
28964
|
+
if ("status" in options && options.status)
|
|
28965
|
+
params.set("status", options.status);
|
|
28966
|
+
if (options.venue)
|
|
28967
|
+
params.set("venue", options.venue);
|
|
28968
|
+
if (options.marketId)
|
|
28969
|
+
params.set("marketId", options.marketId);
|
|
28970
|
+
if (options.instrumentKey)
|
|
28971
|
+
params.set("instrumentKey", options.instrumentKey);
|
|
28972
|
+
if (from.value)
|
|
28973
|
+
params.set("from", from.value);
|
|
28974
|
+
if (to.value)
|
|
28975
|
+
params.set("to", to.value);
|
|
28976
|
+
if (includePagination) {
|
|
28977
|
+
const queryOptions = options;
|
|
28978
|
+
const limit = parseIntegerOption("--limit", queryOptions.limit, DEFAULT_PAPER_POSITION_LIMIT, 1, MAX_PAPER_POSITION_LIMIT);
|
|
28979
|
+
if (limit.error) {
|
|
28980
|
+
printValidationError(limit.error);
|
|
28981
|
+
return null;
|
|
28982
|
+
}
|
|
28983
|
+
const offset = parseIntegerOption("--offset", queryOptions.offset, 0, 0, MAX_PAPER_POSITION_OFFSET);
|
|
28984
|
+
if (offset.error) {
|
|
28985
|
+
printValidationError(offset.error);
|
|
28986
|
+
return null;
|
|
28987
|
+
}
|
|
28988
|
+
params.set("limit", String(limit.value));
|
|
28989
|
+
params.set("offset", String(offset.value));
|
|
28990
|
+
}
|
|
28991
|
+
return params;
|
|
28992
|
+
}
|
|
28993
|
+
function withQuery(path3, params) {
|
|
28994
|
+
const query = params.toString();
|
|
28995
|
+
return query ? `${path3}?${query}` : path3;
|
|
28996
|
+
}
|
|
28997
|
+
function formatUsd6(value) {
|
|
28998
|
+
if (value == null || !Number.isFinite(value))
|
|
28999
|
+
return source_default.dim("-");
|
|
29000
|
+
return `$${value.toLocaleString("en-US", { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`;
|
|
29001
|
+
}
|
|
29002
|
+
function formatSignedUsd(value) {
|
|
29003
|
+
if (value == null || !Number.isFinite(value))
|
|
29004
|
+
return source_default.dim("-");
|
|
29005
|
+
const formatted = formatUsd6(Math.abs(value));
|
|
29006
|
+
if (value > 0)
|
|
29007
|
+
return source_default.green(`+${formatted}`);
|
|
29008
|
+
if (value < 0)
|
|
29009
|
+
return source_default.red(`-${formatted}`);
|
|
29010
|
+
return formatted;
|
|
29011
|
+
}
|
|
29012
|
+
function formatProbability(value) {
|
|
29013
|
+
if (value == null || !Number.isFinite(value))
|
|
29014
|
+
return source_default.dim("-");
|
|
29015
|
+
return `${(value * 100).toFixed(1)}%`;
|
|
29016
|
+
}
|
|
29017
|
+
function formatQuantity(value) {
|
|
29018
|
+
if (value == null || !Number.isFinite(value))
|
|
29019
|
+
return source_default.dim("-");
|
|
29020
|
+
return value.toLocaleString("en-US", { maximumFractionDigits: 4 });
|
|
29021
|
+
}
|
|
29022
|
+
function formatTimestamp(value) {
|
|
29023
|
+
if (!value)
|
|
29024
|
+
return source_default.dim("-");
|
|
29025
|
+
try {
|
|
29026
|
+
return new Date(value).toISOString().slice(0, 19).replace("T", " ");
|
|
29027
|
+
} catch {
|
|
29028
|
+
return value;
|
|
29029
|
+
}
|
|
29030
|
+
}
|
|
29031
|
+
function latestLifecycleTime(position) {
|
|
29032
|
+
return position.closedAt ?? position.settledAt ?? position.resolvedAt ?? position.lastMonitoredAt ?? position.latestSnapshotAt ?? null;
|
|
29033
|
+
}
|
|
29034
|
+
function formatPaperSummary(summary) {
|
|
29035
|
+
const lines = [];
|
|
29036
|
+
lines.push("");
|
|
29037
|
+
lines.push(source_default.bold.cyan(" Prediction Market Paper Results"));
|
|
29038
|
+
lines.push(source_default.gray(" Paper / Simulated"));
|
|
29039
|
+
lines.push(source_default.gray(" No venue order placed"));
|
|
29040
|
+
lines.push(source_default.gray(" Read-only inspection"));
|
|
29041
|
+
lines.push(source_default.gray(" " + "-".repeat(52)));
|
|
29042
|
+
lines.push(` ${source_default.gray("Open positions:")} ${summary.openPositions}`);
|
|
29043
|
+
lines.push(` ${source_default.gray("Closed positions:")} ${summary.closedPositions}`);
|
|
29044
|
+
lines.push(` ${source_default.gray("Resolved won:")} ${summary.resolvedWon}`);
|
|
29045
|
+
lines.push(` ${source_default.gray("Resolved lost:")} ${summary.resolvedLost}`);
|
|
29046
|
+
lines.push(` ${source_default.gray("Invalid / canceled:")} ${summary.invalidOrCanceled}`);
|
|
29047
|
+
lines.push(` ${source_default.gray("Total notional:")} ${formatUsd6(summary.totalNotionalUsd)}`);
|
|
29048
|
+
lines.push(` ${source_default.gray("Realized PnL:")} ${formatSignedUsd(summary.realizedPnlUsd)}`);
|
|
29049
|
+
lines.push(` ${source_default.gray("Unrealized PnL:")} ${formatSignedUsd(summary.unrealizedPnlUsd)}`);
|
|
29050
|
+
lines.push(` ${source_default.gray("Last updated:")} ${formatTimestamp(summary.lastUpdatedAt)}`);
|
|
29051
|
+
lines.push("");
|
|
29052
|
+
return lines.join("\n");
|
|
29053
|
+
}
|
|
29054
|
+
function formatPaperPositions(positions) {
|
|
29055
|
+
const lines = [];
|
|
29056
|
+
lines.push("");
|
|
29057
|
+
lines.push(source_default.bold.cyan(" Prediction Market Paper Positions"));
|
|
29058
|
+
lines.push(source_default.gray(" Paper / Simulated"));
|
|
29059
|
+
lines.push(source_default.gray(" No venue order placed"));
|
|
29060
|
+
lines.push(source_default.gray(" Read-only inspection"));
|
|
29061
|
+
lines.push(source_default.gray(" " + "-".repeat(132)));
|
|
29062
|
+
if (positions.length === 0) {
|
|
29063
|
+
lines.push(` ${source_default.dim("No paper prediction-market positions found.")}`);
|
|
29064
|
+
lines.push(` ${source_default.dim("Paper PM results appear only after paper runtime and paper writes are enabled.")}`);
|
|
29065
|
+
lines.push("");
|
|
29066
|
+
return lines.join("\n");
|
|
29067
|
+
}
|
|
29068
|
+
lines.push(` ${source_default.gray("Position".padEnd(14))}${source_default.gray("Agent".padEnd(14))}${source_default.gray("Venue".padEnd(12))}${source_default.gray("Outcome".padEnd(10))}${source_default.gray("Side".padEnd(10))}${source_default.gray("Qty".padStart(10))}${source_default.gray("Entry".padStart(10))}${source_default.gray("Mark".padStart(10))}${source_default.gray("Notional".padStart(12))}${source_default.gray("Realized".padStart(12))}${source_default.gray("Unrealized".padStart(12))}${source_default.gray("Status".padStart(14))}`);
|
|
29069
|
+
lines.push(source_default.gray(" " + "-".repeat(132)));
|
|
29070
|
+
for (const position of positions) {
|
|
29071
|
+
lines.push(` ${truncate(position.positionId, 13).padEnd(14)}${truncate(position.agentId ?? "-", 13).padEnd(14)}${truncate(position.venue ?? "-", 11).padEnd(12)}${truncate(position.outcomeSide ?? "-", 9).padEnd(10)}${truncate(position.positionSide, 9).padEnd(10)}${formatQuantity(position.quantity).padStart(10)}${formatProbability(position.averageEntryPrice).padStart(10)}${formatProbability(position.markPrice).padStart(10)}${formatUsd6(position.notionalUsd).padStart(12)}${formatSignedUsd(position.realizedPnlUsd).padStart(12)}${formatSignedUsd(position.unrealizedPnlUsd).padStart(12)}${truncate(position.status, 13).padStart(14)}`);
|
|
29072
|
+
lines.push(` ${source_default.dim("Market:")} ${truncate(position.marketQuestion ?? position.marketId ?? position.instrumentKey, 92)} ${source_default.dim("Opened:")} ${formatTimestamp(position.openedAt)} ${source_default.dim("Latest:")} ${formatTimestamp(latestLifecycleTime(position))} ` + source_default.dim("paper / no venue order placed"));
|
|
29073
|
+
}
|
|
29074
|
+
lines.push("");
|
|
29075
|
+
return lines.join("\n");
|
|
29076
|
+
}
|
|
29077
|
+
function formatPaperPositionDetail(position) {
|
|
29078
|
+
const lines = [];
|
|
29079
|
+
lines.push("");
|
|
29080
|
+
lines.push(source_default.bold.cyan(` Prediction Market Paper Position - ${position.positionId}`));
|
|
29081
|
+
lines.push(source_default.gray(" Paper / Simulated"));
|
|
29082
|
+
lines.push(source_default.gray(" No venue order placed"));
|
|
29083
|
+
lines.push(source_default.gray(" Read-only inspection"));
|
|
29084
|
+
lines.push(source_default.gray(" " + "-".repeat(68)));
|
|
29085
|
+
lines.push(` ${source_default.gray("Agent:")} ${position.agentId ?? "-"}`);
|
|
29086
|
+
lines.push(` ${source_default.gray("Trader:")} ${position.traderId ?? "-"}`);
|
|
29087
|
+
lines.push(` ${source_default.gray("Instrument key:")} ${position.instrumentKey}`);
|
|
29088
|
+
lines.push(` ${source_default.gray("Instrument type:")} ${position.instrumentType}`);
|
|
29089
|
+
lines.push(` ${source_default.gray("Venue:")} ${position.venue ?? "-"}`);
|
|
29090
|
+
lines.push(` ${source_default.gray("Market ID:")} ${position.marketId ?? "-"}`);
|
|
29091
|
+
lines.push(` ${source_default.gray("Market question:")} ${position.marketQuestion ?? "-"}`);
|
|
29092
|
+
lines.push(` ${source_default.gray("Outcome side:")} ${position.outcomeSide ?? "-"}`);
|
|
29093
|
+
lines.push(` ${source_default.gray("Position side:")} ${position.positionSide}`);
|
|
29094
|
+
lines.push(` ${source_default.gray("Quantity:")} ${formatQuantity(position.quantity)}`);
|
|
29095
|
+
lines.push(` ${source_default.gray("Average entry:")} ${formatProbability(position.averageEntryPrice)}`);
|
|
29096
|
+
lines.push(` ${source_default.gray("Mark:")} ${formatProbability(position.markPrice)}`);
|
|
29097
|
+
lines.push(` ${source_default.gray("Notional USD:")} ${formatUsd6(position.notionalUsd)}`);
|
|
29098
|
+
lines.push(` ${source_default.gray("Realized PnL:")} ${formatSignedUsd(position.realizedPnlUsd)}`);
|
|
29099
|
+
lines.push(` ${source_default.gray("Unrealized PnL:")} ${formatSignedUsd(position.unrealizedPnlUsd)}`);
|
|
29100
|
+
lines.push(` ${source_default.gray("Status:")} ${position.status}`);
|
|
29101
|
+
lines.push(` ${source_default.gray("Opened:")} ${formatTimestamp(position.openedAt)}`);
|
|
29102
|
+
lines.push(` ${source_default.gray("Closed:")} ${formatTimestamp(position.closedAt)}`);
|
|
29103
|
+
lines.push(` ${source_default.gray("Expiry:")} ${formatTimestamp(position.expiryAt)}`);
|
|
29104
|
+
lines.push(` ${source_default.gray("Resolved:")} ${formatTimestamp(position.resolvedAt)}`);
|
|
29105
|
+
lines.push(` ${source_default.gray("Settled:")} ${formatTimestamp(position.settledAt)}`);
|
|
29106
|
+
lines.push(` ${source_default.gray("Settlement ID:")} ${position.settlementId ?? "-"}`);
|
|
29107
|
+
lines.push(` ${source_default.gray("Execution mode:")} ${position.executionMode}`);
|
|
29108
|
+
lines.push(` ${source_default.gray("Source:")} ${position.source}`);
|
|
29109
|
+
lines.push(` ${source_default.gray("No venue order:")} ${String(position.noVenueOrderPlaced)}`);
|
|
29110
|
+
lines.push("");
|
|
29111
|
+
return lines.join("\n");
|
|
29112
|
+
}
|
|
29113
|
+
async function readSummary(options) {
|
|
29114
|
+
const query = buildQuery(options, false);
|
|
29115
|
+
if (!query)
|
|
29116
|
+
return null;
|
|
29117
|
+
const path3 = withQuery("/api/v1/prediction-market-paper/summary", query);
|
|
29118
|
+
return apiRequest(path3);
|
|
29119
|
+
}
|
|
29120
|
+
async function readPositions(options) {
|
|
29121
|
+
const query = buildQuery(options, true);
|
|
29122
|
+
if (!query)
|
|
29123
|
+
return null;
|
|
29124
|
+
const path3 = withQuery("/api/v1/prediction-market-paper/positions", query);
|
|
29125
|
+
return apiRequest(path3);
|
|
29126
|
+
}
|
|
29127
|
+
async function readAgentSummary(agentId, options) {
|
|
29128
|
+
const idError = validateIdentifier("agentId", agentId);
|
|
29129
|
+
if (idError) {
|
|
29130
|
+
printValidationError(idError);
|
|
29131
|
+
return null;
|
|
29132
|
+
}
|
|
29133
|
+
const query = buildQuery({ ...options, agent: void 0 }, false);
|
|
29134
|
+
if (!query)
|
|
29135
|
+
return null;
|
|
29136
|
+
const path3 = withQuery(`/api/v1/agents/${encodeURIComponent(agentId)}/prediction-market-paper/summary`, query);
|
|
29137
|
+
return apiRequest(path3);
|
|
29138
|
+
}
|
|
29139
|
+
async function readAgentPositions(agentId, options) {
|
|
29140
|
+
const idError = validateIdentifier("agentId", agentId);
|
|
29141
|
+
if (idError) {
|
|
29142
|
+
printValidationError(idError);
|
|
29143
|
+
return null;
|
|
29144
|
+
}
|
|
29145
|
+
const query = buildQuery({ ...options, agent: void 0 }, true);
|
|
29146
|
+
if (!query)
|
|
29147
|
+
return null;
|
|
29148
|
+
const path3 = withQuery(`/api/v1/agents/${encodeURIComponent(agentId)}/prediction-market-paper/positions`, query);
|
|
29149
|
+
return apiRequest(path3);
|
|
29150
|
+
}
|
|
29151
|
+
async function readPosition(positionId) {
|
|
29152
|
+
const idError = validateIdentifier("positionId", positionId);
|
|
29153
|
+
if (idError) {
|
|
29154
|
+
printValidationError(idError);
|
|
29155
|
+
return null;
|
|
29156
|
+
}
|
|
29157
|
+
return apiRequest(`/api/v1/prediction-market-paper/positions/${encodeURIComponent(positionId)}`);
|
|
29158
|
+
}
|
|
29159
|
+
function isBackendDisabled(error2) {
|
|
29160
|
+
if (!(error2 instanceof ApiError))
|
|
29161
|
+
return false;
|
|
29162
|
+
const body = error2.body;
|
|
29163
|
+
return error2.status === 404 && (error2.message.toLowerCase().includes("paper result reads are disabled") || typeof body === "object" && body !== null && body.code === "PREDICTION_MARKET_PAPER_RESULTS_READ_DISABLED");
|
|
29164
|
+
}
|
|
29165
|
+
function handlePaperError(error2, format2) {
|
|
29166
|
+
if (isBackendDisabled(error2)) {
|
|
29167
|
+
const payload = {
|
|
29168
|
+
disabled: true,
|
|
29169
|
+
mode: "paper",
|
|
29170
|
+
label: "Paper / Simulated",
|
|
29171
|
+
noVenueOrderPlaced: true,
|
|
29172
|
+
message: "Prediction-market paper result reads are disabled by the API."
|
|
29173
|
+
};
|
|
29174
|
+
if (format2 === "json") {
|
|
29175
|
+
console.log(JSON.stringify(payload, null, 2));
|
|
29176
|
+
} else {
|
|
29177
|
+
console.log(source_default.yellow("Prediction-market paper result reads are disabled by the API."));
|
|
29178
|
+
console.log(source_default.dim("Paper / Simulated. No venue order placed. Read-only inspection only."));
|
|
29179
|
+
}
|
|
29180
|
+
return;
|
|
29181
|
+
}
|
|
29182
|
+
const message = error2 instanceof Error ? error2.message : String(error2);
|
|
29183
|
+
console.error(source_default.red(`Error: ${message}`));
|
|
29184
|
+
process.exitCode = error2 instanceof ApiError ? 2 : 1;
|
|
29185
|
+
}
|
|
29186
|
+
async function runReadAction(format2, action) {
|
|
29187
|
+
if (!isPredictionMarketPaperCliEnabled()) {
|
|
29188
|
+
printDisabled(format2);
|
|
29189
|
+
return;
|
|
29190
|
+
}
|
|
29191
|
+
if (!await ensureRemote())
|
|
29192
|
+
return;
|
|
29193
|
+
try {
|
|
29194
|
+
await action();
|
|
29195
|
+
} catch (error2) {
|
|
29196
|
+
handlePaperError(error2, format2);
|
|
29197
|
+
}
|
|
29198
|
+
}
|
|
29199
|
+
function registerPredictionMarketPaperCommand(program2) {
|
|
29200
|
+
const command = program2.command("prediction-market-paper").alias("pm-paper").description("Inspect paper prediction-market positions and results");
|
|
29201
|
+
const addSummaryFilters = (cmd) => cmd.option("--agent <agentId>", "Optional agent ID filter").option("--venue <venue>", "Venue filter").option("--market-id <marketId>", "Prediction-market ID filter").option("--instrument-key <instrumentKey>", "Instrument key filter").option("--from <timestamp>", "Opened-at window start").option("--to <timestamp>", "Opened-at window end").addOption(new Option("--format <format>", "Output format").choices(["text", "json"]).default("text"));
|
|
29202
|
+
const addPositionFilters = (cmd) => addSummaryFilters(cmd).addOption(new Option("--status <status>", "Position status filter").choices([...PAPER_POSITION_STATUSES])).option("--limit <n>", `Maximum rows, 1-${MAX_PAPER_POSITION_LIMIT}`, String(DEFAULT_PAPER_POSITION_LIMIT)).option("--offset <n>", `Rows to skip, 0-${MAX_PAPER_POSITION_OFFSET}`, "0");
|
|
29203
|
+
addSummaryFilters(command.command("summary").description("Show read-only paper prediction-market result summary")).action(async (options) => {
|
|
29204
|
+
await runReadAction(options.format, async () => {
|
|
29205
|
+
const data = await readSummary(options);
|
|
29206
|
+
if (!data)
|
|
29207
|
+
return;
|
|
29208
|
+
if (options.format === "json") {
|
|
29209
|
+
console.log(JSON.stringify(data, null, 2));
|
|
29210
|
+
} else {
|
|
29211
|
+
console.log(formatPaperSummary(data.summary));
|
|
29212
|
+
}
|
|
29213
|
+
});
|
|
29214
|
+
});
|
|
29215
|
+
addPositionFilters(command.command("positions").description("List read-only paper prediction-market positions")).action(async (options) => {
|
|
29216
|
+
await runReadAction(options.format, async () => {
|
|
29217
|
+
const data = await readPositions(options);
|
|
29218
|
+
if (!data)
|
|
29219
|
+
return;
|
|
29220
|
+
if (options.format === "json") {
|
|
29221
|
+
console.log(JSON.stringify(data, null, 2));
|
|
29222
|
+
} else {
|
|
29223
|
+
console.log(formatPaperPositions(data.positions));
|
|
29224
|
+
}
|
|
29225
|
+
});
|
|
29226
|
+
});
|
|
29227
|
+
command.command("position").description("Show one read-only paper prediction-market position").argument("<positionId>", "Paper prediction-market position ID").addOption(new Option("--format <format>", "Output format").choices(["text", "json"]).default("text")).action(async (positionId, options) => {
|
|
29228
|
+
await runReadAction(options.format, async () => {
|
|
29229
|
+
const data = await readPosition(positionId);
|
|
29230
|
+
if (!data)
|
|
29231
|
+
return;
|
|
29232
|
+
if (options.format === "json") {
|
|
29233
|
+
console.log(JSON.stringify(data, null, 2));
|
|
29234
|
+
} else {
|
|
29235
|
+
console.log(formatPaperPositionDetail(data.position));
|
|
29236
|
+
}
|
|
29237
|
+
});
|
|
29238
|
+
});
|
|
29239
|
+
addSummaryFilters(command.command("agent-summary").description("Show read-only paper prediction-market result summary for one agent").argument("<agentId>", "Agent ID")).action(async (agentId, options) => {
|
|
29240
|
+
await runReadAction(options.format, async () => {
|
|
29241
|
+
const data = await readAgentSummary(agentId, options);
|
|
29242
|
+
if (!data)
|
|
29243
|
+
return;
|
|
29244
|
+
if (options.format === "json") {
|
|
29245
|
+
console.log(JSON.stringify(data, null, 2));
|
|
29246
|
+
} else {
|
|
29247
|
+
console.log(formatPaperSummary(data.summary));
|
|
29248
|
+
}
|
|
29249
|
+
});
|
|
29250
|
+
});
|
|
29251
|
+
addPositionFilters(command.command("agent-positions").description("List read-only paper prediction-market positions for one agent").argument("<agentId>", "Agent ID")).action(async (agentId, options) => {
|
|
29252
|
+
await runReadAction(options.format, async () => {
|
|
29253
|
+
const data = await readAgentPositions(agentId, options);
|
|
29254
|
+
if (!data)
|
|
29255
|
+
return;
|
|
29256
|
+
if (options.format === "json") {
|
|
29257
|
+
console.log(JSON.stringify(data, null, 2));
|
|
29258
|
+
} else {
|
|
29259
|
+
console.log(formatPaperPositions(data.positions));
|
|
29260
|
+
}
|
|
29261
|
+
});
|
|
29262
|
+
});
|
|
29263
|
+
}
|
|
29264
|
+
|
|
28606
29265
|
// dist/cli.js
|
|
28607
29266
|
import { readFileSync as readFileSync5 } from "node:fs";
|
|
28608
29267
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
@@ -28654,6 +29313,7 @@ function createCli() {
|
|
|
28654
29313
|
registerSuggestionsCommand(program2);
|
|
28655
29314
|
registerCronCommand(program2);
|
|
28656
29315
|
registerAgentCommand(program2);
|
|
29316
|
+
registerPredictionMarketPaperCommand(program2);
|
|
28657
29317
|
registerConfigCommand(program2);
|
|
28658
29318
|
const GROUPS = {
|
|
28659
29319
|
"Core": ["context", "query", "watch"],
|
|
@@ -28662,7 +29322,7 @@ function createCli() {
|
|
|
28662
29322
|
"Edge & Safety": ["edge", "edge-guard", "coaching", "thesis"],
|
|
28663
29323
|
"Strategy & Benchmarking": ["strategy", "replay", "benchmark", "suggestions"],
|
|
28664
29324
|
"Scheduling": ["cron"],
|
|
28665
|
-
"Agents": ["agent"],
|
|
29325
|
+
"Agents": ["agent", "prediction-market-paper"],
|
|
28666
29326
|
"Account": ["login", "logout", "whoami", "billing", "subscribe", "rotate-key", "forgot-key", "connect-chatgpt", "config"]
|
|
28667
29327
|
};
|
|
28668
29328
|
program2.addHelpText("before", "");
|