@trading-boy/cli 1.6.0 → 1.7.0
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/api-client.js +7 -2
- package/dist/cli.bundle.js +265 -350
- package/dist/commands/agent-cmd.js +42 -54
- package/dist/commands/benchmark-cmd.js +4 -9
- package/dist/commands/billing.js +21 -1
- package/dist/commands/coaching-cmd.js +6 -15
- package/dist/commands/context.js +3 -7
- package/dist/commands/cron-cmd.js +10 -46
- package/dist/commands/edge-cmd.js +3 -5
- package/dist/commands/edge-guard-cmd.js +4 -9
- package/dist/commands/onboarding.js +4 -4
- package/dist/commands/query.js +3 -7
- package/dist/commands/replay-cmd.js +5 -36
- package/dist/commands/risk.js +3 -7
- package/dist/commands/strategy-cmd.js +14 -51
- package/dist/commands/subscribe.js +4 -4
- package/dist/commands/suggestions-cmd.js +5 -17
- package/dist/commands/thesis-cmd.js +3 -6
- package/dist/commands/whoami.js +3 -1
- package/dist/utils.d.ts +12 -0
- package/dist/utils.js +51 -0
- package/package.json +1 -1
package/dist/cli.bundle.js
CHANGED
|
@@ -38623,98 +38623,6 @@ var init_ora = __esm({
|
|
|
38623
38623
|
}
|
|
38624
38624
|
});
|
|
38625
38625
|
|
|
38626
|
-
// dist/utils.js
|
|
38627
|
-
var utils_exports = {};
|
|
38628
|
-
__export(utils_exports, {
|
|
38629
|
-
colorChange: () => colorChange,
|
|
38630
|
-
colorRiskScore: () => colorRiskScore,
|
|
38631
|
-
colorSentiment: () => colorSentiment,
|
|
38632
|
-
createSpinner: () => createSpinner,
|
|
38633
|
-
formatConnectionError: () => formatConnectionError,
|
|
38634
|
-
formatDate: () => formatDate,
|
|
38635
|
-
formatUsd: () => formatUsd,
|
|
38636
|
-
isInteractive: () => isInteractive2,
|
|
38637
|
-
padRight: () => padRight,
|
|
38638
|
-
parseIntOption: () => parseIntOption,
|
|
38639
|
-
truncate: () => truncate
|
|
38640
|
-
});
|
|
38641
|
-
function isInteractive2() {
|
|
38642
|
-
return !!process.stdout.isTTY;
|
|
38643
|
-
}
|
|
38644
|
-
async function createSpinner(text) {
|
|
38645
|
-
const { default: ora2 } = await Promise.resolve().then(() => (init_ora(), ora_exports));
|
|
38646
|
-
return ora2({ text, isSilent: !isInteractive2() });
|
|
38647
|
-
}
|
|
38648
|
-
function formatConnectionError(message) {
|
|
38649
|
-
const lower = message.toLowerCase();
|
|
38650
|
-
const isConnectionError = lower.includes("econnrefused") || lower.includes("serviceunavailable") || lower.includes("failed to connect") || lower.includes("connection refused") || lower.includes("max retries per request limit exceeded") || lower.includes("enotfound");
|
|
38651
|
-
if (!isConnectionError)
|
|
38652
|
-
return null;
|
|
38653
|
-
return [
|
|
38654
|
-
source_default.dim(" \u2192 Is the infrastructure running? Try: trading-boy infra status"),
|
|
38655
|
-
source_default.dim(" \u2192 To start: pnpm infra:up")
|
|
38656
|
-
].join("\n");
|
|
38657
|
-
}
|
|
38658
|
-
function padRight(str2, len) {
|
|
38659
|
-
return str2.length >= len ? str2.slice(0, len) : str2 + " ".repeat(len - str2.length);
|
|
38660
|
-
}
|
|
38661
|
-
function truncate(str2, maxLen) {
|
|
38662
|
-
return str2.length > maxLen ? str2.slice(0, maxLen - 3) + "..." : str2;
|
|
38663
|
-
}
|
|
38664
|
-
function colorChange(value) {
|
|
38665
|
-
const sign = value >= 0 ? "+" : "";
|
|
38666
|
-
const str2 = `${sign}${value.toFixed(2)}%`;
|
|
38667
|
-
return value >= 0 ? source_default.green(str2) : source_default.red(str2);
|
|
38668
|
-
}
|
|
38669
|
-
function colorSentiment(value) {
|
|
38670
|
-
const sign = value >= 0 ? "+" : "";
|
|
38671
|
-
const str2 = `${sign}${value.toFixed(2)}`;
|
|
38672
|
-
if (value > 0.3)
|
|
38673
|
-
return source_default.green(str2);
|
|
38674
|
-
if (value < -0.3)
|
|
38675
|
-
return source_default.red(str2);
|
|
38676
|
-
return source_default.yellow(str2);
|
|
38677
|
-
}
|
|
38678
|
-
function colorRiskScore(score) {
|
|
38679
|
-
const label = `${score}/100`;
|
|
38680
|
-
if (score <= 30)
|
|
38681
|
-
return source_default.green(label);
|
|
38682
|
-
if (score <= 60)
|
|
38683
|
-
return source_default.yellow(label);
|
|
38684
|
-
return source_default.red(label);
|
|
38685
|
-
}
|
|
38686
|
-
function formatUsd(value) {
|
|
38687
|
-
if (Math.abs(value) >= 1e9) {
|
|
38688
|
-
return `$${(value / 1e9).toFixed(2)}B`;
|
|
38689
|
-
}
|
|
38690
|
-
if (Math.abs(value) >= 1e6) {
|
|
38691
|
-
return `$${(value / 1e6).toFixed(2)}M`;
|
|
38692
|
-
}
|
|
38693
|
-
if (Math.abs(value) >= 1e3) {
|
|
38694
|
-
return `$${(value / 1e3).toFixed(2)}K`;
|
|
38695
|
-
}
|
|
38696
|
-
return `$${value.toLocaleString("en-US", { minimumFractionDigits: 2, maximumFractionDigits: 6 })}`;
|
|
38697
|
-
}
|
|
38698
|
-
function formatDate(isoString) {
|
|
38699
|
-
if (!isoString) {
|
|
38700
|
-
return source_default.dim("no date");
|
|
38701
|
-
}
|
|
38702
|
-
try {
|
|
38703
|
-
return new Date(isoString).toISOString().slice(0, 10);
|
|
38704
|
-
} catch {
|
|
38705
|
-
return isoString;
|
|
38706
|
-
}
|
|
38707
|
-
}
|
|
38708
|
-
function parseIntOption(value) {
|
|
38709
|
-
return parseInt(value, 10);
|
|
38710
|
-
}
|
|
38711
|
-
var init_utils3 = __esm({
|
|
38712
|
-
"dist/utils.js"() {
|
|
38713
|
-
"use strict";
|
|
38714
|
-
init_source();
|
|
38715
|
-
}
|
|
38716
|
-
});
|
|
38717
|
-
|
|
38718
38626
|
// dist/credentials.js
|
|
38719
38627
|
import { homedir } from "node:os";
|
|
38720
38628
|
import { join } from "node:path";
|
|
@@ -38872,6 +38780,16 @@ var init_credentials = __esm({
|
|
|
38872
38780
|
});
|
|
38873
38781
|
|
|
38874
38782
|
// dist/api-client.js
|
|
38783
|
+
var api_client_exports = {};
|
|
38784
|
+
__export(api_client_exports, {
|
|
38785
|
+
ApiError: () => ApiError,
|
|
38786
|
+
apiRequest: () => apiRequest,
|
|
38787
|
+
getApiBase: () => getApiBase,
|
|
38788
|
+
isDevMode: () => isDevMode,
|
|
38789
|
+
isRemoteMode: () => isRemoteMode,
|
|
38790
|
+
redactApiKey: () => redactApiKey,
|
|
38791
|
+
resolveApiKey: () => resolveApiKey
|
|
38792
|
+
});
|
|
38875
38793
|
function isDevMode() {
|
|
38876
38794
|
if (process.env.NODE_ENV !== "development")
|
|
38877
38795
|
return false;
|
|
@@ -38957,8 +38875,12 @@ async function apiRequest(path5, options = {}) {
|
|
|
38957
38875
|
let message = "Subscription inactive. Run `trading-boy billing manage` to update your billing.";
|
|
38958
38876
|
try {
|
|
38959
38877
|
const body = await response.clone().json();
|
|
38960
|
-
if (typeof body.error === "string")
|
|
38961
|
-
|
|
38878
|
+
if (typeof body.error === "string") {
|
|
38879
|
+
const safePatterns = ["Plan ", "Subscription ", "plan ", "subscription ", "Trial ", "trial "];
|
|
38880
|
+
if (safePatterns.some((p) => body.error.startsWith(p))) {
|
|
38881
|
+
message = body.error;
|
|
38882
|
+
}
|
|
38883
|
+
}
|
|
38962
38884
|
} catch {
|
|
38963
38885
|
}
|
|
38964
38886
|
throw new ApiError(message, 403);
|
|
@@ -39012,6 +38934,141 @@ var init_api_client = __esm({
|
|
|
39012
38934
|
}
|
|
39013
38935
|
});
|
|
39014
38936
|
|
|
38937
|
+
// dist/utils.js
|
|
38938
|
+
var utils_exports = {};
|
|
38939
|
+
__export(utils_exports, {
|
|
38940
|
+
colorChange: () => colorChange,
|
|
38941
|
+
colorRiskScore: () => colorRiskScore,
|
|
38942
|
+
colorSentiment: () => colorSentiment,
|
|
38943
|
+
createSpinner: () => createSpinner,
|
|
38944
|
+
ensureRemote: () => ensureRemote,
|
|
38945
|
+
formatConnectionError: () => formatConnectionError,
|
|
38946
|
+
formatDate: () => formatDate,
|
|
38947
|
+
formatUsd: () => formatUsd,
|
|
38948
|
+
handleApiError: () => handleApiError,
|
|
38949
|
+
isInteractive: () => isInteractive2,
|
|
38950
|
+
padRight: () => padRight,
|
|
38951
|
+
parseIntOption: () => parseIntOption,
|
|
38952
|
+
truncate: () => truncate
|
|
38953
|
+
});
|
|
38954
|
+
function isInteractive2() {
|
|
38955
|
+
return !!process.stdout.isTTY;
|
|
38956
|
+
}
|
|
38957
|
+
async function createSpinner(text) {
|
|
38958
|
+
const { default: ora2 } = await Promise.resolve().then(() => (init_ora(), ora_exports));
|
|
38959
|
+
return ora2({ text, isSilent: !isInteractive2() });
|
|
38960
|
+
}
|
|
38961
|
+
function formatConnectionError(message) {
|
|
38962
|
+
const lower = message.toLowerCase();
|
|
38963
|
+
const isConnectionError = lower.includes("econnrefused") || lower.includes("serviceunavailable") || lower.includes("failed to connect") || lower.includes("connection refused") || lower.includes("max retries per request limit exceeded") || lower.includes("enotfound");
|
|
38964
|
+
if (!isConnectionError)
|
|
38965
|
+
return null;
|
|
38966
|
+
return [
|
|
38967
|
+
source_default.dim(" \u2192 Is the infrastructure running? Try: trading-boy infra status"),
|
|
38968
|
+
source_default.dim(" \u2192 To start: pnpm infra:up")
|
|
38969
|
+
].join("\n");
|
|
38970
|
+
}
|
|
38971
|
+
function padRight(str2, len) {
|
|
38972
|
+
return str2.length >= len ? str2.slice(0, len) : str2 + " ".repeat(len - str2.length);
|
|
38973
|
+
}
|
|
38974
|
+
function truncate(str2, maxLen) {
|
|
38975
|
+
return str2.length > maxLen ? str2.slice(0, maxLen - 3) + "..." : str2;
|
|
38976
|
+
}
|
|
38977
|
+
function colorChange(value) {
|
|
38978
|
+
const sign = value >= 0 ? "+" : "";
|
|
38979
|
+
const str2 = `${sign}${value.toFixed(2)}%`;
|
|
38980
|
+
return value >= 0 ? source_default.green(str2) : source_default.red(str2);
|
|
38981
|
+
}
|
|
38982
|
+
function colorSentiment(value) {
|
|
38983
|
+
const sign = value >= 0 ? "+" : "";
|
|
38984
|
+
const str2 = `${sign}${value.toFixed(2)}`;
|
|
38985
|
+
if (value > 0.3)
|
|
38986
|
+
return source_default.green(str2);
|
|
38987
|
+
if (value < -0.3)
|
|
38988
|
+
return source_default.red(str2);
|
|
38989
|
+
return source_default.yellow(str2);
|
|
38990
|
+
}
|
|
38991
|
+
function colorRiskScore(score) {
|
|
38992
|
+
const label = `${score}/100`;
|
|
38993
|
+
if (score <= 30)
|
|
38994
|
+
return source_default.green(label);
|
|
38995
|
+
if (score <= 60)
|
|
38996
|
+
return source_default.yellow(label);
|
|
38997
|
+
return source_default.red(label);
|
|
38998
|
+
}
|
|
38999
|
+
function formatUsd(value) {
|
|
39000
|
+
if (Math.abs(value) >= 1e9) {
|
|
39001
|
+
return `$${(value / 1e9).toFixed(2)}B`;
|
|
39002
|
+
}
|
|
39003
|
+
if (Math.abs(value) >= 1e6) {
|
|
39004
|
+
return `$${(value / 1e6).toFixed(2)}M`;
|
|
39005
|
+
}
|
|
39006
|
+
if (Math.abs(value) >= 1e3) {
|
|
39007
|
+
return `$${(value / 1e3).toFixed(2)}K`;
|
|
39008
|
+
}
|
|
39009
|
+
return `$${value.toLocaleString("en-US", { minimumFractionDigits: 2, maximumFractionDigits: 6 })}`;
|
|
39010
|
+
}
|
|
39011
|
+
function formatDate(isoString) {
|
|
39012
|
+
if (!isoString) {
|
|
39013
|
+
return source_default.dim("no date");
|
|
39014
|
+
}
|
|
39015
|
+
try {
|
|
39016
|
+
return new Date(isoString).toISOString().slice(0, 10);
|
|
39017
|
+
} catch {
|
|
39018
|
+
return isoString;
|
|
39019
|
+
}
|
|
39020
|
+
}
|
|
39021
|
+
function parseIntOption(value) {
|
|
39022
|
+
return parseInt(value, 10);
|
|
39023
|
+
}
|
|
39024
|
+
function isApiError(error49) {
|
|
39025
|
+
return error49 instanceof Error && error49.name === "ApiError" && "status" in error49;
|
|
39026
|
+
}
|
|
39027
|
+
function handleApiError(error49, context, logger31) {
|
|
39028
|
+
if (isApiError(error49)) {
|
|
39029
|
+
switch (error49.status) {
|
|
39030
|
+
case 401:
|
|
39031
|
+
console.error(source_default.red("Error: Not authenticated. Run `trading-boy login` or `trading-boy subscribe` to get started."));
|
|
39032
|
+
break;
|
|
39033
|
+
case 403:
|
|
39034
|
+
console.error(source_default.red(`Error: ${error49.message}`));
|
|
39035
|
+
break;
|
|
39036
|
+
case 404:
|
|
39037
|
+
console.error(source_default.red(`Error: Not found \u2014 ${error49.message}`));
|
|
39038
|
+
break;
|
|
39039
|
+
case 422:
|
|
39040
|
+
console.error(source_default.red(`Error: Validation failed \u2014 ${error49.message}`));
|
|
39041
|
+
break;
|
|
39042
|
+
case 429:
|
|
39043
|
+
console.error(source_default.red(`Error: Limit reached \u2014 ${error49.message}`));
|
|
39044
|
+
break;
|
|
39045
|
+
default:
|
|
39046
|
+
console.error(source_default.red(`Error: ${error49.message}`));
|
|
39047
|
+
}
|
|
39048
|
+
} else {
|
|
39049
|
+
const message = error49 instanceof Error ? error49.message : String(error49);
|
|
39050
|
+
logger31.error({ error: message }, context);
|
|
39051
|
+
console.error(source_default.red(`Error: ${message}`));
|
|
39052
|
+
}
|
|
39053
|
+
process.exitCode = isApiError(error49) ? 2 : 1;
|
|
39054
|
+
}
|
|
39055
|
+
async function ensureRemote() {
|
|
39056
|
+
const { isRemoteMode: isRemoteMode2 } = await Promise.resolve().then(() => (init_api_client(), api_client_exports));
|
|
39057
|
+
if (!await isRemoteMode2()) {
|
|
39058
|
+
console.error(source_default.yellow("This command requires a remote API connection."));
|
|
39059
|
+
console.error(source_default.dim(" Run: trading-boy login or trading-boy subscribe"));
|
|
39060
|
+
process.exitCode = 1;
|
|
39061
|
+
return false;
|
|
39062
|
+
}
|
|
39063
|
+
return true;
|
|
39064
|
+
}
|
|
39065
|
+
var init_utils3 = __esm({
|
|
39066
|
+
"dist/utils.js"() {
|
|
39067
|
+
"use strict";
|
|
39068
|
+
init_source();
|
|
39069
|
+
}
|
|
39070
|
+
});
|
|
39071
|
+
|
|
39015
39072
|
// ../../node_modules/.pnpm/@inquirer+core@10.3.2_@types+node@25.2.3/node_modules/@inquirer/core/dist/esm/lib/key.js
|
|
39016
39073
|
var isUpKey, isDownKey, isSpaceKey, isBackspaceKey, isTabKey, isNumberKey, isEnterKey;
|
|
39017
39074
|
var init_key = __esm({
|
|
@@ -53236,12 +53293,8 @@ function contextToQueryResult(pkg) {
|
|
|
53236
53293
|
function registerQueryCommand(program2) {
|
|
53237
53294
|
program2.command("query <symbol>").description("Query token info, price, funding rate, and whale activity").addOption(new Option("--format <format>", "Output format").choices(["text", "json"]).default("text")).action(async (symbol2, options) => {
|
|
53238
53295
|
try {
|
|
53239
|
-
if (!await
|
|
53240
|
-
console.error(source_default.yellow("This command requires a remote API connection."));
|
|
53241
|
-
console.error(source_default.dim(" Run: trading-boy login"));
|
|
53242
|
-
process.exitCode = 1;
|
|
53296
|
+
if (!await ensureRemote())
|
|
53243
53297
|
return;
|
|
53244
|
-
}
|
|
53245
53298
|
const pkg = await apiRequest(`/api/v1/tokens/${encodeURIComponent(symbol2.toUpperCase())}/context`);
|
|
53246
53299
|
const result = contextToQueryResult(pkg);
|
|
53247
53300
|
if (result.token.name === null && result.token.chains.length === 0 && result.price.price === null) {
|
|
@@ -53541,12 +53594,8 @@ function buildHistoryQueryParams(options) {
|
|
|
53541
53594
|
function registerContextCommand(program2) {
|
|
53542
53595
|
program2.command("context <symbol>").description("Assemble and display a full ContextPackage for a token").addOption(new Option("--format <format>", "Output format").choices(["text", "json"]).default("text")).option("--at <date>", "Fetch historical context at a specific date/time (e.g., 2026-01-15 or 2026-01-15T12:00:00Z)").option("--from <date>", "Start of time range for context history").option("--to <date>", "End of time range for context history").addOption(new Option("--interval <interval>", "Sampling interval for range queries").choices(["15m", "1h", "4h", "1d"])).option("--trader-id <id>", "Trader ID for personalized context").action(async (symbol2, options) => {
|
|
53543
53596
|
try {
|
|
53544
|
-
if (!await
|
|
53545
|
-
console.error(source_default.yellow("This command requires a remote API connection."));
|
|
53546
|
-
console.error(source_default.dim(" Run: trading-boy login"));
|
|
53547
|
-
process.exitCode = 1;
|
|
53597
|
+
if (!await ensureRemote())
|
|
53548
53598
|
return;
|
|
53549
|
-
}
|
|
53550
53599
|
if (options.from && !options.to || !options.from && options.to) {
|
|
53551
53600
|
console.error(source_default.red("Error: Both --from and --to must be provided for range queries."));
|
|
53552
53601
|
process.exitCode = 1;
|
|
@@ -53866,12 +53915,8 @@ function registerRiskCommand(program2) {
|
|
|
53866
53915
|
process.exitCode = 1;
|
|
53867
53916
|
return;
|
|
53868
53917
|
}
|
|
53869
|
-
if (!await
|
|
53870
|
-
console.error(source_default.yellow("This command requires a remote API connection."));
|
|
53871
|
-
console.error(source_default.dim(" Run: trading-boy login or trading-boy subscribe"));
|
|
53872
|
-
process.exitCode = 1;
|
|
53918
|
+
if (!await ensureRemote())
|
|
53873
53919
|
return;
|
|
53874
|
-
}
|
|
53875
53920
|
try {
|
|
53876
53921
|
const apiResult = await apiRequest(`/api/v1/protocols/${encodeURIComponent(protocol.toLowerCase())}/risk`);
|
|
53877
53922
|
const result = {
|
|
@@ -56734,6 +56779,7 @@ function registerLogoutCommand(program2) {
|
|
|
56734
56779
|
init_source();
|
|
56735
56780
|
init_dist2();
|
|
56736
56781
|
init_credentials();
|
|
56782
|
+
init_api_client();
|
|
56737
56783
|
var logger21 = createLogger("cli-whoami");
|
|
56738
56784
|
async function executeWhoami() {
|
|
56739
56785
|
const envKey = process.env.TRADING_BOY_API_KEY;
|
|
@@ -56788,6 +56834,7 @@ function formatWhoamiOutput(result) {
|
|
|
56788
56834
|
const date5 = new Date(result.storedAt).toLocaleString();
|
|
56789
56835
|
lines.push(` ${source_default.gray("Since:")} ${date5}`);
|
|
56790
56836
|
}
|
|
56837
|
+
lines.push(` ${source_default.gray("API:")} ${getApiBase()}`);
|
|
56791
56838
|
lines.push("");
|
|
56792
56839
|
return lines.join("\n");
|
|
56793
56840
|
}
|
|
@@ -56808,7 +56855,7 @@ function registerWhoamiCommand(program2) {
|
|
|
56808
56855
|
}
|
|
56809
56856
|
}
|
|
56810
56857
|
if (options.format === "json") {
|
|
56811
|
-
console.log(JSON.stringify(result, null, 2));
|
|
56858
|
+
console.log(JSON.stringify({ ...result, apiUrl: getApiBase() }, null, 2));
|
|
56812
56859
|
} else {
|
|
56813
56860
|
console.log(formatWhoamiOutput(result));
|
|
56814
56861
|
}
|
|
@@ -56827,6 +56874,10 @@ init_dist2();
|
|
|
56827
56874
|
init_api_client();
|
|
56828
56875
|
init_utils3();
|
|
56829
56876
|
var logger22 = createLogger("cli-billing");
|
|
56877
|
+
var ALLOWED_PORTAL_DOMAINS = /* @__PURE__ */ new Set([
|
|
56878
|
+
"billing.stripe.com",
|
|
56879
|
+
"checkout.stripe.com"
|
|
56880
|
+
]);
|
|
56830
56881
|
function formatStatusLabel(status) {
|
|
56831
56882
|
switch (status) {
|
|
56832
56883
|
case "active":
|
|
@@ -56892,6 +56943,9 @@ function registerBillingCommand(program2) {
|
|
|
56892
56943
|
if (portalUrl.protocol !== "https:") {
|
|
56893
56944
|
throw new Error(`Refusing to open non-HTTPS portal URL: ${result.url}`);
|
|
56894
56945
|
}
|
|
56946
|
+
if (!ALLOWED_PORTAL_DOMAINS.has(portalUrl.hostname)) {
|
|
56947
|
+
throw new Error(`Refusing to open URL with untrusted domain: ${portalUrl.hostname}`);
|
|
56948
|
+
}
|
|
56895
56949
|
const { default: open2 } = await Promise.resolve().then(() => (init_open(), open_exports));
|
|
56896
56950
|
await open2(result.url);
|
|
56897
56951
|
console.log("");
|
|
@@ -56915,6 +56969,17 @@ function registerBillingCommand(program2) {
|
|
|
56915
56969
|
console.log(formatBillingStatus(result));
|
|
56916
56970
|
}
|
|
56917
56971
|
} catch (error49) {
|
|
56972
|
+
if (error49 instanceof ApiError && error49.status === 404) {
|
|
56973
|
+
if (options.format === "json") {
|
|
56974
|
+
console.log(JSON.stringify({ plan: "starter", status: "free" }, null, 2));
|
|
56975
|
+
} else {
|
|
56976
|
+
console.log("");
|
|
56977
|
+
console.log(source_default.dim(" You're on the free Starter plan."));
|
|
56978
|
+
console.log(source_default.dim(" Run: trading-boy subscribe to upgrade."));
|
|
56979
|
+
console.log("");
|
|
56980
|
+
}
|
|
56981
|
+
return;
|
|
56982
|
+
}
|
|
56918
56983
|
const message = error49 instanceof Error ? error49.message : String(error49);
|
|
56919
56984
|
logger22.error({ error: message }, "Billing status failed");
|
|
56920
56985
|
console.error(source_default.red(` Error: ${message}`));
|
|
@@ -57037,13 +57102,13 @@ async function runOnboarding() {
|
|
|
57037
57102
|
});
|
|
57038
57103
|
if (wantsTelegram) {
|
|
57039
57104
|
console.log("");
|
|
57040
|
-
console.log(source_default.white("
|
|
57041
|
-
console.log(source_default.white(" Send ") + source_default.cyan("/start") + source_default.white("
|
|
57105
|
+
console.log(source_default.white(" Click to open the bot: ") + source_default.cyan.underline("https://t.me/TradingBoy1_Bot"));
|
|
57106
|
+
console.log(source_default.white(" Send ") + source_default.cyan("/start") + source_default.white(" and paste your API key to connect."));
|
|
57042
57107
|
console.log("");
|
|
57043
57108
|
console.log(source_default.dim(" The bot will send you a daily trading summary at 08:00 UTC."));
|
|
57044
|
-
console.log(source_default.dim(" You can also use /summary, /
|
|
57109
|
+
console.log(source_default.dim(" You can also use /summary, /agents, /positions, /pause, and /soul."));
|
|
57045
57110
|
} else {
|
|
57046
|
-
console.log(source_default.dim(" Skipped.
|
|
57111
|
+
console.log(source_default.dim(" Skipped. Connect anytime: ") + source_default.dim.underline("https://t.me/TradingBoy1_Bot"));
|
|
57047
57112
|
}
|
|
57048
57113
|
} catch (error49) {
|
|
57049
57114
|
if (isUserAbort(error49))
|
|
@@ -57180,7 +57245,7 @@ async function pollForApiKey(token, onTick) {
|
|
|
57180
57245
|
if (result.status === "expired" || result.status === "not_found") {
|
|
57181
57246
|
return {
|
|
57182
57247
|
success: false,
|
|
57183
|
-
error: "Provisioning token expired.
|
|
57248
|
+
error: "Provisioning token expired. Your API key will be emailed to you shortly. Then run: `trading-boy login`"
|
|
57184
57249
|
};
|
|
57185
57250
|
}
|
|
57186
57251
|
if (result.status === "already_retrieved") {
|
|
@@ -57197,7 +57262,7 @@ async function pollForApiKey(token, onTick) {
|
|
|
57197
57262
|
}
|
|
57198
57263
|
return {
|
|
57199
57264
|
success: false,
|
|
57200
|
-
error: "Timed out waiting for payment confirmation.
|
|
57265
|
+
error: "Timed out waiting for payment confirmation. Your API key will be emailed to you shortly. Then run: `trading-boy login`"
|
|
57201
57266
|
};
|
|
57202
57267
|
}
|
|
57203
57268
|
async function saveApiKey(apiKey, metadata) {
|
|
@@ -57234,8 +57299,8 @@ function formatSubscribeSuccess(result) {
|
|
|
57234
57299
|
lines.push(` ${source_default.bold("API Key:")} ${source_default.yellow(result.apiKey)}`);
|
|
57235
57300
|
lines.push("");
|
|
57236
57301
|
lines.push(source_default.dim(" \u26A0\uFE0F Copy this key now \u2014 it will not be shown again."));
|
|
57237
|
-
lines.push(source_default.dim("
|
|
57238
|
-
lines.push(source_default.dim(" and paste
|
|
57302
|
+
lines.push(source_default.dim(" Connect Telegram: ") + source_default.dim.underline("https://t.me/TradingBoy1_Bot"));
|
|
57303
|
+
lines.push(source_default.dim(" Send /start and paste this key when prompted."));
|
|
57239
57304
|
} else if (result.keyPrefix) {
|
|
57240
57305
|
lines.push(` ${source_default.bold("Key ID:")} ${result.keyPrefix}`);
|
|
57241
57306
|
}
|
|
@@ -57536,6 +57601,7 @@ function formatConnectionError2(message) {
|
|
|
57536
57601
|
// dist/commands/edge-cmd.js
|
|
57537
57602
|
init_source();
|
|
57538
57603
|
init_api_client();
|
|
57604
|
+
init_utils3();
|
|
57539
57605
|
function formatEdgeOutput(data) {
|
|
57540
57606
|
const lines = [];
|
|
57541
57607
|
lines.push("");
|
|
@@ -57665,11 +57731,8 @@ function formatPct2(val) {
|
|
|
57665
57731
|
function registerEdgeCommand(program2) {
|
|
57666
57732
|
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) => {
|
|
57667
57733
|
try {
|
|
57668
|
-
if (!await
|
|
57669
|
-
console.error(source_default.red("Error: edge command requires remote mode. Run `trading-boy login` first."));
|
|
57670
|
-
process.exitCode = 1;
|
|
57734
|
+
if (!await ensureRemote())
|
|
57671
57735
|
return;
|
|
57672
|
-
}
|
|
57673
57736
|
const query = new URLSearchParams();
|
|
57674
57737
|
if (options.token)
|
|
57675
57738
|
query.set("tokenSymbol", options.token.toUpperCase());
|
|
@@ -57702,6 +57765,7 @@ function registerEdgeCommand(program2) {
|
|
|
57702
57765
|
// dist/commands/edge-guard-cmd.js
|
|
57703
57766
|
init_source();
|
|
57704
57767
|
init_api_client();
|
|
57768
|
+
init_utils3();
|
|
57705
57769
|
function formatAssessmentOutput(data) {
|
|
57706
57770
|
const lines = [];
|
|
57707
57771
|
const a = data.assessment;
|
|
@@ -57810,11 +57874,8 @@ function registerEdgeGuardCommand(program2) {
|
|
|
57810
57874
|
});
|
|
57811
57875
|
cmd.command("check <traderId>").description("Assess negative edge status for a trader").option("--friction", "Check entry friction level only").addOption(new Option("--format <format>", "Output format").choices(["text", "json"]).default("text")).action(async (traderId, options) => {
|
|
57812
57876
|
try {
|
|
57813
|
-
if (!await
|
|
57814
|
-
console.error(source_default.red("Error: edge-guard command requires remote mode. Run `trading-boy login` first."));
|
|
57815
|
-
process.exitCode = 1;
|
|
57877
|
+
if (!await ensureRemote())
|
|
57816
57878
|
return;
|
|
57817
|
-
}
|
|
57818
57879
|
if (options.friction) {
|
|
57819
57880
|
const data = await apiRequest(`/api/v1/traders/${encodeURIComponent(traderId)}/edge-guard/friction`);
|
|
57820
57881
|
if (options.format === "json") {
|
|
@@ -57838,11 +57899,8 @@ function registerEdgeGuardCommand(program2) {
|
|
|
57838
57899
|
});
|
|
57839
57900
|
cmd.command("acknowledge <traderId>").description("Acknowledge negative edge warning to proceed with trade").addOption(new Option("--format <format>", "Output format").choices(["text", "json"]).default("text")).action(async (traderId, ackOptions) => {
|
|
57840
57901
|
try {
|
|
57841
|
-
if (!await
|
|
57842
|
-
console.error(source_default.red("Error: edge-guard command requires remote mode. Run `trading-boy login` first."));
|
|
57843
|
-
process.exitCode = 1;
|
|
57902
|
+
if (!await ensureRemote())
|
|
57844
57903
|
return;
|
|
57845
|
-
}
|
|
57846
57904
|
const data = await apiRequest(`/api/v1/traders/${encodeURIComponent(traderId)}/edge-guard/acknowledge`, { method: "POST" });
|
|
57847
57905
|
if (ackOptions.format === "json") {
|
|
57848
57906
|
console.log(JSON.stringify(data, null, 2));
|
|
@@ -57863,6 +57921,7 @@ function registerEdgeGuardCommand(program2) {
|
|
|
57863
57921
|
init_source();
|
|
57864
57922
|
init_dist2();
|
|
57865
57923
|
init_api_client();
|
|
57924
|
+
init_utils3();
|
|
57866
57925
|
var logger24 = createLogger("cli-coaching");
|
|
57867
57926
|
var BYOK_HINT = `LLM API key required. Run: ${source_default.white("trading-boy config set-llm-key <key>")}`;
|
|
57868
57927
|
function isByokError(error49) {
|
|
@@ -57876,15 +57935,6 @@ function isByokError(error49) {
|
|
|
57876
57935
|
}
|
|
57877
57936
|
return false;
|
|
57878
57937
|
}
|
|
57879
|
-
async function requireRemote() {
|
|
57880
|
-
if (!await isRemoteMode()) {
|
|
57881
|
-
console.error(source_default.yellow("Coaching requires a remote API connection."));
|
|
57882
|
-
console.error(source_default.dim(" Run: trading-boy login"));
|
|
57883
|
-
process.exitCode = 1;
|
|
57884
|
-
return false;
|
|
57885
|
-
}
|
|
57886
|
-
return true;
|
|
57887
|
-
}
|
|
57888
57938
|
function formatIntervention(response) {
|
|
57889
57939
|
const lines = [];
|
|
57890
57940
|
lines.push("");
|
|
@@ -57920,7 +57970,7 @@ function formatIntervention(response) {
|
|
|
57920
57970
|
function registerCoachingCommand(program2) {
|
|
57921
57971
|
const coaching = program2.command("coaching").description("Trading coach \u2014 pre/post-trade interventions (requires BYOK LLM key)");
|
|
57922
57972
|
coaching.command("pre-trade <traderId>").description("Get pre-trade coaching intervention check").option("--tilt-score <n>", "Tilt score (0-100)", parseFloat).option("--flags <flags>", "Active behavioral flags (comma-separated)").option("--token <symbol>", "Token being traded").option("--direction <dir>", "Trade direction (LONG or SHORT)").addOption(new Option("--format <format>", "Output format").choices(["text", "json"]).default("text")).action(async (traderId, options) => {
|
|
57923
|
-
if (!await
|
|
57973
|
+
if (!await ensureRemote())
|
|
57924
57974
|
return;
|
|
57925
57975
|
const extraction = {
|
|
57926
57976
|
decisionType: "TRADE_ENTRY",
|
|
@@ -57973,7 +58023,7 @@ function registerCoachingCommand(program2) {
|
|
|
57973
58023
|
}
|
|
57974
58024
|
});
|
|
57975
58025
|
coaching.command("post-trade <traderId>").description("Get post-trade coaching session reflection").option("--tilt-score <n>", "Tilt score (0-100)", parseFloat).option("--flags <flags>", "Active behavioral flags (comma-separated)").addOption(new Option("--format <format>", "Output format").choices(["text", "json"]).default("text")).action(async (traderId, options) => {
|
|
57976
|
-
if (!await
|
|
58026
|
+
if (!await ensureRemote())
|
|
57977
58027
|
return;
|
|
57978
58028
|
const body = {
|
|
57979
58029
|
tiltScore: options.tiltScore ?? 0,
|
|
@@ -58014,7 +58064,7 @@ function registerCoachingCommand(program2) {
|
|
|
58014
58064
|
}
|
|
58015
58065
|
});
|
|
58016
58066
|
coaching.command("acknowledge <traderId>").description("Acknowledge a coaching intervention").requiredOption("--reason <reason>", "Reason for acknowledgment").action(async (traderId, options) => {
|
|
58017
|
-
if (!await
|
|
58067
|
+
if (!await ensureRemote())
|
|
58018
58068
|
return;
|
|
58019
58069
|
try {
|
|
58020
58070
|
const result = await apiRequest(`/api/v1/traders/${encodeURIComponent(traderId)}/coaching/acknowledge`, { method: "POST", body: { reason: options.reason } });
|
|
@@ -58030,7 +58080,7 @@ function registerCoachingCommand(program2) {
|
|
|
58030
58080
|
}
|
|
58031
58081
|
});
|
|
58032
58082
|
coaching.command("reset <traderId>").description("Reset coaching session state").action(async (traderId) => {
|
|
58033
|
-
if (!await
|
|
58083
|
+
if (!await ensureRemote())
|
|
58034
58084
|
return;
|
|
58035
58085
|
try {
|
|
58036
58086
|
const result = await apiRequest(`/api/v1/traders/${encodeURIComponent(traderId)}/coaching/reset-session`, { method: "POST", body: {} });
|
|
@@ -58050,6 +58100,7 @@ function registerCoachingCommand(program2) {
|
|
|
58050
58100
|
init_source();
|
|
58051
58101
|
init_dist2();
|
|
58052
58102
|
init_api_client();
|
|
58103
|
+
init_utils3();
|
|
58053
58104
|
var logger25 = createLogger("cli-thesis");
|
|
58054
58105
|
var BYOK_HINT2 = `LLM API key required. Run: ${source_default.white("trading-boy config set-llm-key <key>")}`;
|
|
58055
58106
|
function formatThesisOutput(response) {
|
|
@@ -58109,12 +58160,8 @@ function formatThesisOutput(response) {
|
|
|
58109
58160
|
}
|
|
58110
58161
|
function registerThesisCommand(program2) {
|
|
58111
58162
|
program2.command("thesis <decisionId>").description("Extract structured thesis from trade decision text (requires BYOK LLM key)").requiredOption("--text <thesis>", "Thesis text to extract from").requiredOption("--trader <traderId>", "Trader ID").option("--token <symbol>", "Token symbol").option("--direction <dir>", "Trade direction (LONG or SHORT)").option("--entry-price <n>", "Entry price", parseFloat).addOption(new Option("--format <format>", "Output format").choices(["text", "json"]).default("text")).action(async (decisionId, options) => {
|
|
58112
|
-
if (!await
|
|
58113
|
-
console.error(source_default.yellow("Thesis extraction requires a remote API connection."));
|
|
58114
|
-
console.error(source_default.dim(" Run: trading-boy login"));
|
|
58115
|
-
process.exitCode = 1;
|
|
58163
|
+
if (!await ensureRemote())
|
|
58116
58164
|
return;
|
|
58117
|
-
}
|
|
58118
58165
|
if (options.direction && !["LONG", "SHORT"].includes(options.direction.toUpperCase())) {
|
|
58119
58166
|
console.error(source_default.red("Error: --direction must be LONG or SHORT"));
|
|
58120
58167
|
process.exitCode = 1;
|
|
@@ -58264,44 +58311,10 @@ function formatHistoryList(response) {
|
|
|
58264
58311
|
lines.push("");
|
|
58265
58312
|
return lines.join("\n");
|
|
58266
58313
|
}
|
|
58267
|
-
async function requireRemote2() {
|
|
58268
|
-
if (!await isRemoteMode()) {
|
|
58269
|
-
console.error(source_default.yellow("Strategy commands require a remote API connection."));
|
|
58270
|
-
console.error(source_default.dim(" Run: trading-boy login"));
|
|
58271
|
-
process.exitCode = 1;
|
|
58272
|
-
return false;
|
|
58273
|
-
}
|
|
58274
|
-
return true;
|
|
58275
|
-
}
|
|
58276
|
-
function handleApiError(error49, context) {
|
|
58277
|
-
if (error49 instanceof ApiError) {
|
|
58278
|
-
switch (error49.status) {
|
|
58279
|
-
case 401:
|
|
58280
|
-
console.error(source_default.red("Error: API key invalid or expired. Run `trading-boy login` to re-authenticate."));
|
|
58281
|
-
break;
|
|
58282
|
-
case 403:
|
|
58283
|
-
console.error(source_default.red("Error: Subscription inactive. Run `trading-boy billing manage` to update your billing."));
|
|
58284
|
-
break;
|
|
58285
|
-
case 404:
|
|
58286
|
-
console.error(source_default.red(`Error: Not found \u2014 ${error49.message}`));
|
|
58287
|
-
break;
|
|
58288
|
-
case 422:
|
|
58289
|
-
console.error(source_default.red(`Error: Validation failed \u2014 ${error49.message}`));
|
|
58290
|
-
break;
|
|
58291
|
-
default:
|
|
58292
|
-
console.error(source_default.red(`Error: ${error49.message}`));
|
|
58293
|
-
}
|
|
58294
|
-
} else {
|
|
58295
|
-
const message = error49 instanceof Error ? error49.message : String(error49);
|
|
58296
|
-
logger26.error({ error: message }, context);
|
|
58297
|
-
console.error(source_default.red(`Error: ${message}`));
|
|
58298
|
-
}
|
|
58299
|
-
process.exitCode = error49 instanceof ApiError ? 2 : 1;
|
|
58300
|
-
}
|
|
58301
58314
|
function registerStrategyCommand(program2) {
|
|
58302
58315
|
const strategy = program2.command("strategy").description("Manage agent strategies (token watch-lists, setup types, signal weights)");
|
|
58303
58316
|
strategy.command("create").description("Create a new agent strategy").requiredOption("--name <name>", "Strategy name").requiredOption("--trader-id <id>", "Trader ID").requiredOption("--agent-id <id>", "Agent ID").requiredOption("--tokens <tokens>", "Comma-separated token symbols").option("--setups <types>", "Comma-separated setup types").addOption(new Option("--format <format>", "Output format").choices(["text", "json"]).default("text")).action(async (options) => {
|
|
58304
|
-
if (!await
|
|
58317
|
+
if (!await ensureRemote())
|
|
58305
58318
|
return;
|
|
58306
58319
|
const tokens = options.tokens.split(",").map((t) => t.trim().toUpperCase()).filter(Boolean);
|
|
58307
58320
|
const setupTypes = options.setups ? options.setups.split(",").map((s) => s.trim().toUpperCase()).filter(Boolean) : ["BREAKOUT"];
|
|
@@ -58337,11 +58350,11 @@ function registerStrategyCommand(program2) {
|
|
|
58337
58350
|
console.log(formatStrategyDetail(result));
|
|
58338
58351
|
}
|
|
58339
58352
|
} catch (error49) {
|
|
58340
|
-
handleApiError(error49, "Strategy create failed");
|
|
58353
|
+
handleApiError(error49, "Strategy create failed", logger26);
|
|
58341
58354
|
}
|
|
58342
58355
|
});
|
|
58343
58356
|
strategy.command("list").description("List strategies for a trader").requiredOption("--trader-id <id>", "Trader ID").option("--agent-id <id>", "Filter by agent ID").option("--limit <n>", "Maximum results", "20").option("--offset <n>", "Pagination offset", "0").addOption(new Option("--format <format>", "Output format").choices(["text", "json"]).default("text")).action(async (options) => {
|
|
58344
|
-
if (!await
|
|
58357
|
+
if (!await ensureRemote())
|
|
58345
58358
|
return;
|
|
58346
58359
|
const params = new URLSearchParams();
|
|
58347
58360
|
params.set("traderId", options.traderId);
|
|
@@ -58357,11 +58370,11 @@ function registerStrategyCommand(program2) {
|
|
|
58357
58370
|
console.log(formatStrategyList(result));
|
|
58358
58371
|
}
|
|
58359
58372
|
} catch (error49) {
|
|
58360
|
-
handleApiError(error49, "Strategy list failed");
|
|
58373
|
+
handleApiError(error49, "Strategy list failed", logger26);
|
|
58361
58374
|
}
|
|
58362
58375
|
});
|
|
58363
58376
|
strategy.command("show <id>").description("Show full details for a strategy").addOption(new Option("--format <format>", "Output format").choices(["text", "json"]).default("text")).action(async (id, options) => {
|
|
58364
|
-
if (!await
|
|
58377
|
+
if (!await ensureRemote())
|
|
58365
58378
|
return;
|
|
58366
58379
|
try {
|
|
58367
58380
|
const result = await apiRequest(`/api/v1/strategies/${encodeURIComponent(id)}`);
|
|
@@ -58371,11 +58384,11 @@ function registerStrategyCommand(program2) {
|
|
|
58371
58384
|
console.log(formatStrategyDetail(result));
|
|
58372
58385
|
}
|
|
58373
58386
|
} catch (error49) {
|
|
58374
|
-
handleApiError(error49, "Strategy show failed");
|
|
58387
|
+
handleApiError(error49, "Strategy show failed", logger26);
|
|
58375
58388
|
}
|
|
58376
58389
|
});
|
|
58377
58390
|
strategy.command("update <id>").description("Update a strategy").option("--name <name>", "New strategy name").option("--tokens <tokens>", "New comma-separated token symbols (replaces existing)").option("--setups <types>", "New comma-separated setup types (replaces existing)").addOption(new Option("--format <format>", "Output format").choices(["text", "json"]).default("text")).action(async (id, options) => {
|
|
58378
|
-
if (!await
|
|
58391
|
+
if (!await ensureRemote())
|
|
58379
58392
|
return;
|
|
58380
58393
|
const body = {};
|
|
58381
58394
|
if (options.name) {
|
|
@@ -58400,11 +58413,11 @@ function registerStrategyCommand(program2) {
|
|
|
58400
58413
|
console.log(formatStrategyDetail(result));
|
|
58401
58414
|
}
|
|
58402
58415
|
} catch (error49) {
|
|
58403
|
-
handleApiError(error49, "Strategy update failed");
|
|
58416
|
+
handleApiError(error49, "Strategy update failed", logger26);
|
|
58404
58417
|
}
|
|
58405
58418
|
});
|
|
58406
58419
|
strategy.command("history <id>").description("Show version history for a strategy").addOption(new Option("--format <format>", "Output format").choices(["text", "json"]).default("text")).action(async (id, options) => {
|
|
58407
|
-
if (!await
|
|
58420
|
+
if (!await ensureRemote())
|
|
58408
58421
|
return;
|
|
58409
58422
|
try {
|
|
58410
58423
|
const result = await apiRequest(`/api/v1/strategies/${encodeURIComponent(id)}/history`);
|
|
@@ -58414,11 +58427,11 @@ function registerStrategyCommand(program2) {
|
|
|
58414
58427
|
console.log(formatHistoryList(result));
|
|
58415
58428
|
}
|
|
58416
58429
|
} catch (error49) {
|
|
58417
|
-
handleApiError(error49, "Strategy history failed");
|
|
58430
|
+
handleApiError(error49, "Strategy history failed", logger26);
|
|
58418
58431
|
}
|
|
58419
58432
|
});
|
|
58420
58433
|
strategy.command("export").description("Export a strategy in json, elizaos, or freqtrade format").requiredOption("--id <id>", "Strategy ID to export").addOption(new Option("--format <format>", "Export format").choices(["json", "elizaos", "freqtrade"]).default("json")).option("--output <file>", "Write output to a file instead of stdout").action(async (options) => {
|
|
58421
|
-
if (!await
|
|
58434
|
+
if (!await ensureRemote())
|
|
58422
58435
|
return;
|
|
58423
58436
|
try {
|
|
58424
58437
|
const result = await apiRequest(`/api/v1/strategies/${encodeURIComponent(options.id)}/export?format=${encodeURIComponent(options.format)}`);
|
|
@@ -58440,7 +58453,7 @@ function registerStrategyCommand(program2) {
|
|
|
58440
58453
|
console.log(output);
|
|
58441
58454
|
}
|
|
58442
58455
|
} catch (error49) {
|
|
58443
|
-
handleApiError(error49, "Strategy export failed");
|
|
58456
|
+
handleApiError(error49, "Strategy export failed", logger26);
|
|
58444
58457
|
}
|
|
58445
58458
|
});
|
|
58446
58459
|
}
|
|
@@ -58529,39 +58542,10 @@ async function pollReplayJob(jobId) {
|
|
|
58529
58542
|
}
|
|
58530
58543
|
throw new Error(`Replay job ${jobId} did not complete within ${POLL_TIMEOUT_MS2 / 1e3}s timeout.`);
|
|
58531
58544
|
}
|
|
58532
|
-
function handleApiError2(error49, context) {
|
|
58533
|
-
if (error49 instanceof ApiError) {
|
|
58534
|
-
switch (error49.status) {
|
|
58535
|
-
case 401:
|
|
58536
|
-
console.error(source_default.red("Error: API key invalid or expired. Run `trading-boy login` to re-authenticate."));
|
|
58537
|
-
break;
|
|
58538
|
-
case 403:
|
|
58539
|
-
console.error(source_default.red("Error: Subscription inactive. Run `trading-boy billing manage` to update your billing."));
|
|
58540
|
-
break;
|
|
58541
|
-
case 404:
|
|
58542
|
-
console.error(source_default.red(`Error: Not found \u2014 ${error49.message}`));
|
|
58543
|
-
break;
|
|
58544
|
-
case 422:
|
|
58545
|
-
console.error(source_default.red(`Error: Validation failed \u2014 ${error49.message}`));
|
|
58546
|
-
break;
|
|
58547
|
-
default:
|
|
58548
|
-
console.error(source_default.red(`Error: ${error49.message}`));
|
|
58549
|
-
}
|
|
58550
|
-
} else {
|
|
58551
|
-
const message = error49 instanceof Error ? error49.message : String(error49);
|
|
58552
|
-
logger27.error({ error: message }, context);
|
|
58553
|
-
console.error(source_default.red(`Error: ${message}`));
|
|
58554
|
-
}
|
|
58555
|
-
process.exitCode = error49 instanceof ApiError ? 2 : 1;
|
|
58556
|
-
}
|
|
58557
58545
|
function registerReplayCommand(program2) {
|
|
58558
58546
|
program2.command("replay").description("Run strategy replay (backtest) over a historical period").requiredOption("--strategy <id>", "Strategy ID").requiredOption("--token <symbol>", "Token symbol").requiredOption("--from <date>", "Start date (ISO-8601, e.g. 2025-01-01)").requiredOption("--to <date>", "End date (ISO-8601, e.g. 2025-03-01)").addOption(new Option("--format <format>", "Output format").choices(["text", "json"]).default("text")).action(async (options) => {
|
|
58559
|
-
if (!await
|
|
58560
|
-
console.error(source_default.yellow("Replay requires a remote API connection."));
|
|
58561
|
-
console.error(source_default.dim(" Run: trading-boy login"));
|
|
58562
|
-
process.exitCode = 1;
|
|
58547
|
+
if (!await ensureRemote())
|
|
58563
58548
|
return;
|
|
58564
|
-
}
|
|
58565
58549
|
const fromDate = new Date(options.from);
|
|
58566
58550
|
const toDate = new Date(options.to);
|
|
58567
58551
|
if (isNaN(fromDate.getTime())) {
|
|
@@ -58596,7 +58580,7 @@ function registerReplayCommand(program2) {
|
|
|
58596
58580
|
submitSpinner.succeed(source_default.dim(`Job submitted: ${jobId}`));
|
|
58597
58581
|
} catch (error49) {
|
|
58598
58582
|
submitSpinner.fail("Failed to submit replay job");
|
|
58599
|
-
|
|
58583
|
+
handleApiError(error49, "Replay submit failed", logger27);
|
|
58600
58584
|
return;
|
|
58601
58585
|
}
|
|
58602
58586
|
const pollSpinner = (await createSpinner2("Running replay\u2026")).start();
|
|
@@ -58606,7 +58590,7 @@ function registerReplayCommand(program2) {
|
|
|
58606
58590
|
pollSpinner.stop();
|
|
58607
58591
|
} catch (error49) {
|
|
58608
58592
|
pollSpinner.fail("Replay timed out or encountered an error");
|
|
58609
|
-
|
|
58593
|
+
handleApiError(error49, "Replay polling failed", logger27);
|
|
58610
58594
|
return;
|
|
58611
58595
|
}
|
|
58612
58596
|
if (!finalStatus.result) {
|
|
@@ -58629,6 +58613,7 @@ function registerReplayCommand(program2) {
|
|
|
58629
58613
|
// dist/commands/benchmark-cmd.js
|
|
58630
58614
|
init_source();
|
|
58631
58615
|
init_api_client();
|
|
58616
|
+
init_utils3();
|
|
58632
58617
|
function formatMetric(value, decimals = 2) {
|
|
58633
58618
|
if (value === null)
|
|
58634
58619
|
return source_default.dim("\u2014");
|
|
@@ -58713,11 +58698,8 @@ function registerBenchmarkCommand(program2) {
|
|
|
58713
58698
|
"timeWeightedReturn"
|
|
58714
58699
|
]).default("sharpeRatio")).addOption(new Option("--entity-type <type>", "Entity type").choices(["trader", "agent", "strategy"]).default("trader")).option("--setup <setupType>", "Filter by setup type").option("--regime <regime>", "Filter by market regime").option("--token <symbol>", "Filter by token symbol").option("--entity <entityId>", "Show single entity benchmark").option("--limit <n>", "Number of entries", "20").addOption(new Option("--format <format>", "Output format").choices(["text", "json"]).default("text")).action(async (options) => {
|
|
58715
58700
|
try {
|
|
58716
|
-
if (!await
|
|
58717
|
-
console.error(source_default.red("Error: benchmark command requires remote mode. Run `trading-boy login` first."));
|
|
58718
|
-
process.exitCode = 1;
|
|
58701
|
+
if (!await ensureRemote())
|
|
58719
58702
|
return;
|
|
58720
|
-
}
|
|
58721
58703
|
if (options.entity) {
|
|
58722
58704
|
const query = new URLSearchParams();
|
|
58723
58705
|
query.set("window", options.window);
|
|
@@ -58760,11 +58742,8 @@ function registerBenchmarkCommand(program2) {
|
|
|
58760
58742
|
});
|
|
58761
58743
|
benchCmd.command("recompute").description("Trigger on-demand benchmark recompute").action(async () => {
|
|
58762
58744
|
try {
|
|
58763
|
-
if (!await
|
|
58764
|
-
console.error(source_default.red("Error: benchmark recompute requires remote mode. Run `trading-boy login` first."));
|
|
58765
|
-
process.exitCode = 1;
|
|
58745
|
+
if (!await ensureRemote())
|
|
58766
58746
|
return;
|
|
58767
|
-
}
|
|
58768
58747
|
console.log(source_default.dim("Recomputing benchmarks..."));
|
|
58769
58748
|
const data = await apiRequest("/api/v1/benchmark/recompute", { method: "POST", body: {} });
|
|
58770
58749
|
console.log(source_default.green(`
|
|
@@ -58829,12 +58808,8 @@ function registerSuggestionsCommand(program2) {
|
|
|
58829
58808
|
cmd.help();
|
|
58830
58809
|
});
|
|
58831
58810
|
cmd.command("list").description("List strategy suggestions").option("--status <status>", "Filter by status: pending, approved, rejected", "pending").option("--strategy <id>", "Filter by strategy ID").option("--limit <n>", "Maximum results", parseInt, 20).option("--offset <n>", "Pagination offset", parseInt, 0).addOption(new Option("--format <format>", "Output format").choices(["text", "json"]).default("text")).action(async (options) => {
|
|
58832
|
-
if (!await
|
|
58833
|
-
console.error(source_default.yellow("This command requires a remote API connection."));
|
|
58834
|
-
console.error(source_default.dim(" Run: trading-boy login or trading-boy subscribe"));
|
|
58835
|
-
process.exitCode = 1;
|
|
58811
|
+
if (!await ensureRemote())
|
|
58836
58812
|
return;
|
|
58837
|
-
}
|
|
58838
58813
|
try {
|
|
58839
58814
|
const params = new URLSearchParams();
|
|
58840
58815
|
params.set("status", options.status);
|
|
@@ -58856,12 +58831,8 @@ function registerSuggestionsCommand(program2) {
|
|
|
58856
58831
|
}
|
|
58857
58832
|
});
|
|
58858
58833
|
cmd.command("approve <id>").description("Approve a suggestion and auto-apply to strategy").addOption(new Option("--format <format>", "Output format").choices(["text", "json"]).default("text")).action(async (id, options) => {
|
|
58859
|
-
if (!await
|
|
58860
|
-
console.error(source_default.yellow("This command requires a remote API connection."));
|
|
58861
|
-
console.error(source_default.dim(" Run: trading-boy login or trading-boy subscribe"));
|
|
58862
|
-
process.exitCode = 1;
|
|
58834
|
+
if (!await ensureRemote())
|
|
58863
58835
|
return;
|
|
58864
|
-
}
|
|
58865
58836
|
try {
|
|
58866
58837
|
const data = await apiRequest(`/api/v1/suggestions/${encodeURIComponent(id)}/approve`, { method: "POST" });
|
|
58867
58838
|
if (options.format === "json") {
|
|
@@ -58879,12 +58850,8 @@ function registerSuggestionsCommand(program2) {
|
|
|
58879
58850
|
}
|
|
58880
58851
|
});
|
|
58881
58852
|
cmd.command("reject <id>").description("Reject a suggestion").addOption(new Option("--format <format>", "Output format").choices(["text", "json"]).default("text")).action(async (id, options) => {
|
|
58882
|
-
if (!await
|
|
58883
|
-
console.error(source_default.yellow("This command requires a remote API connection."));
|
|
58884
|
-
console.error(source_default.dim(" Run: trading-boy login or trading-boy subscribe"));
|
|
58885
|
-
process.exitCode = 1;
|
|
58853
|
+
if (!await ensureRemote())
|
|
58886
58854
|
return;
|
|
58887
|
-
}
|
|
58888
58855
|
try {
|
|
58889
58856
|
const data = await apiRequest(`/api/v1/suggestions/${encodeURIComponent(id)}/reject`, { method: "POST" });
|
|
58890
58857
|
if (options.format === "json") {
|
|
@@ -58909,40 +58876,6 @@ init_dist2();
|
|
|
58909
58876
|
init_api_client();
|
|
58910
58877
|
init_utils3();
|
|
58911
58878
|
var logger29 = createLogger("cli-cron");
|
|
58912
|
-
function handleApiError3(error49, context) {
|
|
58913
|
-
if (error49 instanceof ApiError) {
|
|
58914
|
-
switch (error49.status) {
|
|
58915
|
-
case 401:
|
|
58916
|
-
console.error(source_default.red("Error: API key invalid or expired. Run `trading-boy login` to re-authenticate."));
|
|
58917
|
-
break;
|
|
58918
|
-
case 403:
|
|
58919
|
-
console.error(source_default.red("Error: Subscription inactive. Run `trading-boy billing manage` to update your billing."));
|
|
58920
|
-
break;
|
|
58921
|
-
case 404:
|
|
58922
|
-
console.error(source_default.red(`Error: Not found \u2014 ${error49.message}`));
|
|
58923
|
-
break;
|
|
58924
|
-
case 429:
|
|
58925
|
-
console.error(source_default.red(`Error: Limit reached \u2014 ${error49.message}`));
|
|
58926
|
-
break;
|
|
58927
|
-
default:
|
|
58928
|
-
console.error(source_default.red(`Error: ${error49.message}`));
|
|
58929
|
-
}
|
|
58930
|
-
} else {
|
|
58931
|
-
const message = error49 instanceof Error ? error49.message : String(error49);
|
|
58932
|
-
logger29.error({ error: message }, context);
|
|
58933
|
-
console.error(source_default.red(`Error: ${message}`));
|
|
58934
|
-
}
|
|
58935
|
-
process.exitCode = error49 instanceof ApiError ? 2 : 1;
|
|
58936
|
-
}
|
|
58937
|
-
async function ensureRemote() {
|
|
58938
|
-
if (!await isRemoteMode()) {
|
|
58939
|
-
console.error(source_default.yellow("Cron commands require a remote API connection."));
|
|
58940
|
-
console.error(source_default.dim(" Run: trading-boy login"));
|
|
58941
|
-
process.exitCode = 1;
|
|
58942
|
-
return false;
|
|
58943
|
-
}
|
|
58944
|
-
return true;
|
|
58945
|
-
}
|
|
58946
58879
|
function formatShortDate4(isoString) {
|
|
58947
58880
|
if (!isoString)
|
|
58948
58881
|
return source_default.dim("\u2014");
|
|
@@ -59014,7 +58947,7 @@ function registerCronCommand(program2) {
|
|
|
59014
58947
|
console.log("");
|
|
59015
58948
|
}
|
|
59016
58949
|
} catch (error49) {
|
|
59017
|
-
|
|
58950
|
+
handleApiError(error49, "Cron create failed", logger29);
|
|
59018
58951
|
}
|
|
59019
58952
|
});
|
|
59020
58953
|
cron.command("list").description("List cron jobs").option("--status <status>", "Filter by status: active, paused").addOption(new Option("--format <format>", "Output format").choices(["text", "json"]).default("text")).action(async (options) => {
|
|
@@ -59041,7 +58974,7 @@ function registerCronCommand(program2) {
|
|
|
59041
58974
|
console.log(source_default.dim(` ${result.count} job(s)`));
|
|
59042
58975
|
console.log("");
|
|
59043
58976
|
} catch (error49) {
|
|
59044
|
-
|
|
58977
|
+
handleApiError(error49, "Cron list failed", logger29);
|
|
59045
58978
|
}
|
|
59046
58979
|
});
|
|
59047
58980
|
cron.command("show <jobId>").description("Show details of a cron job").addOption(new Option("--format <format>", "Output format").choices(["text", "json"]).default("text")).action(async (jobId, options) => {
|
|
@@ -59069,7 +59002,7 @@ function registerCronCommand(program2) {
|
|
|
59069
59002
|
console.log(` ${source_default.gray("Created:")} ${formatShortDate4(job.createdAt)}`);
|
|
59070
59003
|
console.log("");
|
|
59071
59004
|
} catch (error49) {
|
|
59072
|
-
|
|
59005
|
+
handleApiError(error49, "Cron show failed", logger29);
|
|
59073
59006
|
}
|
|
59074
59007
|
});
|
|
59075
59008
|
cron.command("pause <jobId>").description("Pause a cron job").action(async (jobId) => {
|
|
@@ -59082,7 +59015,7 @@ function registerCronCommand(program2) {
|
|
|
59082
59015
|
});
|
|
59083
59016
|
console.log(source_default.green(` Job ${jobId} paused`));
|
|
59084
59017
|
} catch (error49) {
|
|
59085
|
-
|
|
59018
|
+
handleApiError(error49, "Cron pause failed", logger29);
|
|
59086
59019
|
}
|
|
59087
59020
|
});
|
|
59088
59021
|
cron.command("resume <jobId>").description("Resume a paused cron job").action(async (jobId) => {
|
|
@@ -59095,7 +59028,7 @@ function registerCronCommand(program2) {
|
|
|
59095
59028
|
});
|
|
59096
59029
|
console.log(source_default.green(` Job ${jobId} resumed`));
|
|
59097
59030
|
} catch (error49) {
|
|
59098
|
-
|
|
59031
|
+
handleApiError(error49, "Cron resume failed", logger29);
|
|
59099
59032
|
}
|
|
59100
59033
|
});
|
|
59101
59034
|
cron.command("delete <jobId>").description("Delete a cron job").action(async (jobId) => {
|
|
@@ -59107,7 +59040,7 @@ function registerCronCommand(program2) {
|
|
|
59107
59040
|
});
|
|
59108
59041
|
console.log(source_default.green(` Job ${jobId} deleted`));
|
|
59109
59042
|
} catch (error49) {
|
|
59110
|
-
|
|
59043
|
+
handleApiError(error49, "Cron delete failed", logger29);
|
|
59111
59044
|
}
|
|
59112
59045
|
});
|
|
59113
59046
|
cron.command("run <jobId>").description("Trigger immediate execution of a cron job").action(async (jobId) => {
|
|
@@ -59119,7 +59052,7 @@ function registerCronCommand(program2) {
|
|
|
59119
59052
|
});
|
|
59120
59053
|
console.log(source_default.green(` Job ${jobId} execution triggered`));
|
|
59121
59054
|
} catch (error49) {
|
|
59122
|
-
|
|
59055
|
+
handleApiError(error49, "Cron run failed", logger29);
|
|
59123
59056
|
}
|
|
59124
59057
|
});
|
|
59125
59058
|
cron.command("history <jobId>").description("View execution history for a cron job").option("--limit <n>", "Number of runs to show", "20").addOption(new Option("--format <format>", "Output format").choices(["text", "json"]).default("text")).action(async (jobId, options) => {
|
|
@@ -59147,7 +59080,7 @@ function registerCronCommand(program2) {
|
|
|
59147
59080
|
console.log(source_default.dim(` ${result.count} run(s)`));
|
|
59148
59081
|
console.log("");
|
|
59149
59082
|
} catch (error49) {
|
|
59150
|
-
|
|
59083
|
+
handleApiError(error49, "Cron history failed", logger29);
|
|
59151
59084
|
}
|
|
59152
59085
|
});
|
|
59153
59086
|
}
|
|
@@ -59160,40 +59093,6 @@ init_dist2();
|
|
|
59160
59093
|
init_api_client();
|
|
59161
59094
|
init_utils3();
|
|
59162
59095
|
var logger30 = createLogger("cli-agent");
|
|
59163
|
-
function handleApiError4(error49, context) {
|
|
59164
|
-
if (error49 instanceof ApiError) {
|
|
59165
|
-
switch (error49.status) {
|
|
59166
|
-
case 401:
|
|
59167
|
-
console.error(source_default.red("Error: API key invalid or expired. Run `trading-boy login` to re-authenticate."));
|
|
59168
|
-
break;
|
|
59169
|
-
case 403:
|
|
59170
|
-
console.error(source_default.red(`Error: ${error49.message}`));
|
|
59171
|
-
break;
|
|
59172
|
-
case 404:
|
|
59173
|
-
console.error(source_default.red(`Error: Not found \u2014 ${error49.message}`));
|
|
59174
|
-
break;
|
|
59175
|
-
case 429:
|
|
59176
|
-
console.error(source_default.red(`Error: Limit reached \u2014 ${error49.message}`));
|
|
59177
|
-
break;
|
|
59178
|
-
default:
|
|
59179
|
-
console.error(source_default.red(`Error: ${error49.message}`));
|
|
59180
|
-
}
|
|
59181
|
-
} else {
|
|
59182
|
-
const message = error49 instanceof Error ? error49.message : String(error49);
|
|
59183
|
-
logger30.error({ error: message }, context);
|
|
59184
|
-
console.error(source_default.red(`Error: ${message}`));
|
|
59185
|
-
}
|
|
59186
|
-
process.exitCode = error49 instanceof ApiError ? 2 : 1;
|
|
59187
|
-
}
|
|
59188
|
-
async function ensureRemote2() {
|
|
59189
|
-
if (!await isRemoteMode()) {
|
|
59190
|
-
console.error(source_default.yellow("Agent commands require a remote API connection."));
|
|
59191
|
-
console.error(source_default.dim(" Run: trading-boy login"));
|
|
59192
|
-
process.exitCode = 1;
|
|
59193
|
-
return false;
|
|
59194
|
-
}
|
|
59195
|
-
return true;
|
|
59196
|
-
}
|
|
59197
59096
|
function formatShortDate5(isoString) {
|
|
59198
59097
|
if (!isoString)
|
|
59199
59098
|
return source_default.dim("\u2014");
|
|
@@ -59257,7 +59156,7 @@ var MIN_SCAN_INTERVAL_MS = 6e4;
|
|
|
59257
59156
|
function registerAgentCommand(program2) {
|
|
59258
59157
|
const agent = program2.command("agent").description("Manage autonomous trading agents");
|
|
59259
59158
|
agent.command("create").description("Create a new agent").option("--trader-id <traderId>", "Trader ID").option("--strategy-id <strategyId>", "Strategy ID").option("--name <name>", "Agent name").option("--autonomy <level>", "Autonomy level: OBSERVE_ONLY, SUGGEST, AUTO_WITH_APPROVAL, FULLY_AUTONOMOUS", "OBSERVE_ONLY").option("--scan-interval <ms>", "Scan interval in ms (min 60000)", "300000").option("--scan-interval-human <duration>", "Scan interval in human-readable format (e.g. 1m, 5m, 15m, 30m, 1h)").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 threshold (0-1)", "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").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").addOption(new Option("--format <format>", "Output format").choices(["text", "json"]).default("text")).action(async (options) => {
|
|
59260
|
-
if (!await
|
|
59159
|
+
if (!await ensureRemote())
|
|
59261
59160
|
return;
|
|
59262
59161
|
if (!options.traderId) {
|
|
59263
59162
|
console.error(source_default.red("Error: --trader-id is required."));
|
|
@@ -59355,11 +59254,11 @@ function registerAgentCommand(program2) {
|
|
|
59355
59254
|
console.log("");
|
|
59356
59255
|
}
|
|
59357
59256
|
} catch (error49) {
|
|
59358
|
-
|
|
59257
|
+
handleApiError(error49, "Agent create failed", logger30);
|
|
59359
59258
|
}
|
|
59360
59259
|
});
|
|
59361
59260
|
agent.command("list").description("List agents").option("--status <status>", "Filter by status: active, paused").addOption(new Option("--format <format>", "Output format").choices(["text", "json"]).default("text")).action(async (options) => {
|
|
59362
|
-
if (!await
|
|
59261
|
+
if (!await ensureRemote())
|
|
59363
59262
|
return;
|
|
59364
59263
|
try {
|
|
59365
59264
|
const query = options.status ? `?status=${options.status}` : "";
|
|
@@ -59388,11 +59287,11 @@ function registerAgentCommand(program2) {
|
|
|
59388
59287
|
console.log(source_default.dim(` ${result.count} agent(s)`));
|
|
59389
59288
|
console.log("");
|
|
59390
59289
|
} catch (error49) {
|
|
59391
|
-
|
|
59290
|
+
handleApiError(error49, "Agent list failed", logger30);
|
|
59392
59291
|
}
|
|
59393
59292
|
});
|
|
59394
59293
|
agent.command("show <agentId>").description("Show agent details and live state").addOption(new Option("--format <format>", "Output format").choices(["text", "json"]).default("text")).action(async (agentId, options) => {
|
|
59395
|
-
if (!await
|
|
59294
|
+
if (!await ensureRemote())
|
|
59396
59295
|
return;
|
|
59397
59296
|
try {
|
|
59398
59297
|
const result = await apiRequest(`/api/v1/agents/${encodeURIComponent(agentId)}`);
|
|
@@ -59461,47 +59360,59 @@ function registerAgentCommand(program2) {
|
|
|
59461
59360
|
}
|
|
59462
59361
|
console.log("");
|
|
59463
59362
|
} catch (error49) {
|
|
59464
|
-
|
|
59363
|
+
handleApiError(error49, "Agent show failed", logger30);
|
|
59465
59364
|
}
|
|
59466
59365
|
});
|
|
59467
|
-
agent.command("pause <agentId>").description("Pause an agent").action(async (agentId) => {
|
|
59468
|
-
if (!await
|
|
59366
|
+
agent.command("pause <agentId>").description("Pause an agent").addOption(new Option("--format <format>", "Output format").choices(["text", "json"]).default("text")).action(async (agentId, options) => {
|
|
59367
|
+
if (!await ensureRemote())
|
|
59469
59368
|
return;
|
|
59470
59369
|
try {
|
|
59471
59370
|
await apiRequest(`/api/v1/agents/${encodeURIComponent(agentId)}/pause`, {
|
|
59472
59371
|
method: "POST"
|
|
59473
59372
|
});
|
|
59474
|
-
|
|
59373
|
+
if (options.format === "json") {
|
|
59374
|
+
console.log(JSON.stringify({ agentId, status: "paused" }, null, 2));
|
|
59375
|
+
} else {
|
|
59376
|
+
console.log(source_default.green(` Agent ${agentId} paused`));
|
|
59377
|
+
}
|
|
59475
59378
|
} catch (error49) {
|
|
59476
|
-
|
|
59379
|
+
handleApiError(error49, "Agent pause failed", logger30);
|
|
59477
59380
|
}
|
|
59478
59381
|
});
|
|
59479
|
-
agent.command("resume <agentId>").description("Resume a paused agent").action(async (agentId) => {
|
|
59480
|
-
if (!await
|
|
59382
|
+
agent.command("resume <agentId>").description("Resume a paused agent").addOption(new Option("--format <format>", "Output format").choices(["text", "json"]).default("text")).action(async (agentId, options) => {
|
|
59383
|
+
if (!await ensureRemote())
|
|
59481
59384
|
return;
|
|
59482
59385
|
try {
|
|
59483
59386
|
await apiRequest(`/api/v1/agents/${encodeURIComponent(agentId)}/resume`, {
|
|
59484
59387
|
method: "POST"
|
|
59485
59388
|
});
|
|
59486
|
-
|
|
59389
|
+
if (options.format === "json") {
|
|
59390
|
+
console.log(JSON.stringify({ agentId, status: "active" }, null, 2));
|
|
59391
|
+
} else {
|
|
59392
|
+
console.log(source_default.green(` Agent ${agentId} resumed`));
|
|
59393
|
+
}
|
|
59487
59394
|
} catch (error49) {
|
|
59488
|
-
|
|
59395
|
+
handleApiError(error49, "Agent resume failed", logger30);
|
|
59489
59396
|
}
|
|
59490
59397
|
});
|
|
59491
|
-
agent.command("delete <agentId>").description("Delete an agent").action(async (agentId) => {
|
|
59492
|
-
if (!await
|
|
59398
|
+
agent.command("delete <agentId>").description("Delete an agent").addOption(new Option("--format <format>", "Output format").choices(["text", "json"]).default("text")).action(async (agentId, options) => {
|
|
59399
|
+
if (!await ensureRemote())
|
|
59493
59400
|
return;
|
|
59494
59401
|
try {
|
|
59495
59402
|
await apiRequest(`/api/v1/agents/${encodeURIComponent(agentId)}`, {
|
|
59496
59403
|
method: "DELETE"
|
|
59497
59404
|
});
|
|
59498
|
-
|
|
59405
|
+
if (options.format === "json") {
|
|
59406
|
+
console.log(JSON.stringify({ agentId, status: "deleted" }, null, 2));
|
|
59407
|
+
} else {
|
|
59408
|
+
console.log(source_default.green(` Agent ${agentId} deleted`));
|
|
59409
|
+
}
|
|
59499
59410
|
} catch (error49) {
|
|
59500
|
-
|
|
59411
|
+
handleApiError(error49, "Agent delete failed", logger30);
|
|
59501
59412
|
}
|
|
59502
59413
|
});
|
|
59503
59414
|
agent.command("exit <agentId>").description("Exit/close an open position for an agent").requiredOption("--symbol <symbol>", "Token symbol to exit (e.g. xyz:NATGAS)").option("--reason <text>", "Reason for exit").addOption(new Option("--format <format>", "Output format").choices(["text", "json"]).default("text")).action(async (agentId, options) => {
|
|
59504
|
-
if (!await
|
|
59415
|
+
if (!await ensureRemote())
|
|
59505
59416
|
return;
|
|
59506
59417
|
try {
|
|
59507
59418
|
const body = {};
|
|
@@ -59526,11 +59437,11 @@ function registerAgentCommand(program2) {
|
|
|
59526
59437
|
console.log("");
|
|
59527
59438
|
}
|
|
59528
59439
|
} catch (error49) {
|
|
59529
|
-
|
|
59440
|
+
handleApiError(error49, "Position exit failed", logger30);
|
|
59530
59441
|
}
|
|
59531
59442
|
});
|
|
59532
|
-
agent.command("update <agentId>").description("Update agent config").option("--name <name>", "Agent name").option("--autonomy <level>", "Autonomy level").option("--scan-interval <ms>", "Scan interval in ms").option("--scan-interval-human <duration>", "Scan interval in human-readable format (e.g. 1m, 5m, 15m, 30m, 1h)").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 threshold").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").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").action(async (agentId, options) => {
|
|
59533
|
-
if (!await
|
|
59443
|
+
agent.command("update <agentId>").description("Update agent config").option("--name <name>", "Agent name").option("--autonomy <level>", "Autonomy level").option("--scan-interval <ms>", "Scan interval in ms").option("--scan-interval-human <duration>", "Scan interval in human-readable format (e.g. 1m, 5m, 15m, 30m, 1h)").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 threshold").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").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").addOption(new Option("--format <format>", "Output format").choices(["text", "json"]).default("text")).action(async (agentId, options) => {
|
|
59444
|
+
if (!await ensureRemote())
|
|
59534
59445
|
return;
|
|
59535
59446
|
const body = {};
|
|
59536
59447
|
if (options.name)
|
|
@@ -59599,13 +59510,17 @@ function registerAgentCommand(program2) {
|
|
|
59599
59510
|
return;
|
|
59600
59511
|
}
|
|
59601
59512
|
try {
|
|
59602
|
-
await apiRequest(`/api/v1/agents/${encodeURIComponent(agentId)}`, {
|
|
59513
|
+
const result = await apiRequest(`/api/v1/agents/${encodeURIComponent(agentId)}`, {
|
|
59603
59514
|
method: "PATCH",
|
|
59604
59515
|
body
|
|
59605
59516
|
});
|
|
59606
|
-
|
|
59517
|
+
if (options.format === "json") {
|
|
59518
|
+
console.log(JSON.stringify(result, null, 2));
|
|
59519
|
+
} else {
|
|
59520
|
+
console.log(source_default.green(` Agent ${agentId} updated`));
|
|
59521
|
+
}
|
|
59607
59522
|
} catch (error49) {
|
|
59608
|
-
|
|
59523
|
+
handleApiError(error49, "Agent update failed", logger30);
|
|
59609
59524
|
}
|
|
59610
59525
|
});
|
|
59611
59526
|
}
|