@trading-boy/cli 1.11.0 → 1.12.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.
@@ -20186,7 +20186,7 @@ var require_atomic_sleep = __commonJS({
20186
20186
  "../../node_modules/.pnpm/atomic-sleep@1.0.0/node_modules/atomic-sleep/index.js"(exports, module) {
20187
20187
  "use strict";
20188
20188
  if (typeof SharedArrayBuffer !== "undefined" && typeof Atomics !== "undefined") {
20189
- let sleep6 = function(ms) {
20189
+ let sleep5 = function(ms) {
20190
20190
  const valid = ms > 0 && ms < Infinity;
20191
20191
  if (valid === false) {
20192
20192
  if (typeof ms !== "number" && typeof ms !== "bigint") {
@@ -20197,9 +20197,9 @@ var require_atomic_sleep = __commonJS({
20197
20197
  Atomics.wait(nil, 0, 0, Number(ms));
20198
20198
  };
20199
20199
  const nil = new Int32Array(new SharedArrayBuffer(4));
20200
- module.exports = sleep6;
20200
+ module.exports = sleep5;
20201
20201
  } else {
20202
- let sleep6 = function(ms) {
20202
+ let sleep5 = function(ms) {
20203
20203
  const valid = ms > 0 && ms < Infinity;
20204
20204
  if (valid === false) {
20205
20205
  if (typeof ms !== "number" && typeof ms !== "bigint") {
@@ -20211,7 +20211,7 @@ var require_atomic_sleep = __commonJS({
20211
20211
  while (target > Date.now()) {
20212
20212
  }
20213
20213
  };
20214
- module.exports = sleep6;
20214
+ module.exports = sleep5;
20215
20215
  }
20216
20216
  }
20217
20217
  });
@@ -20224,7 +20224,7 @@ var require_sonic_boom = __commonJS({
20224
20224
  var EventEmitter = __require("events");
20225
20225
  var inherits = __require("util").inherits;
20226
20226
  var path5 = __require("path");
20227
- var sleep6 = require_atomic_sleep();
20227
+ var sleep5 = require_atomic_sleep();
20228
20228
  var assert2 = __require("assert");
20229
20229
  var BUSY_WRITE_TIMEOUT = 100;
20230
20230
  var kEmptyBuffer = Buffer.allocUnsafe(0);
@@ -20370,7 +20370,7 @@ var require_sonic_boom = __commonJS({
20370
20370
  if ((err.code === "EAGAIN" || err.code === "EBUSY") && this.retryEAGAIN(err, this._writingBuf.length, this._len - this._writingBuf.length)) {
20371
20371
  if (this.sync) {
20372
20372
  try {
20373
- sleep6(BUSY_WRITE_TIMEOUT);
20373
+ sleep5(BUSY_WRITE_TIMEOUT);
20374
20374
  this.release(void 0, 0);
20375
20375
  } catch (err2) {
20376
20376
  this.release(err2);
@@ -20683,7 +20683,7 @@ var require_sonic_boom = __commonJS({
20683
20683
  if (shouldRetry && !this.retryEAGAIN(err, buf.length, this._len - buf.length)) {
20684
20684
  throw err;
20685
20685
  }
20686
- sleep6(BUSY_WRITE_TIMEOUT);
20686
+ sleep5(BUSY_WRITE_TIMEOUT);
20687
20687
  }
20688
20688
  }
20689
20689
  try {
@@ -20720,7 +20720,7 @@ var require_sonic_boom = __commonJS({
20720
20720
  if (shouldRetry && !this.retryEAGAIN(err, buf.length, this._len - buf.length)) {
20721
20721
  throw err;
20722
20722
  }
20723
- sleep6(BUSY_WRITE_TIMEOUT);
20723
+ sleep5(BUSY_WRITE_TIMEOUT);
20724
20724
  }
20725
20725
  }
20726
20726
  }
@@ -21457,7 +21457,7 @@ var require_transport = __commonJS({
21457
21457
  var getCallers = require_caller();
21458
21458
  var { join: join2, isAbsolute, sep } = __require("node:path");
21459
21459
  var { fileURLToPath: fileURLToPath3 } = __require("node:url");
21460
- var sleep6 = require_atomic_sleep();
21460
+ var sleep5 = require_atomic_sleep();
21461
21461
  var onExit2 = require_on_exit_leak_free();
21462
21462
  var ThreadStream = require_thread_stream();
21463
21463
  function setupOnExit(stream) {
@@ -21580,7 +21580,7 @@ var require_transport = __commonJS({
21580
21580
  return;
21581
21581
  }
21582
21582
  stream.flushSync();
21583
- sleep6(100);
21583
+ sleep5(100);
21584
21584
  stream.end();
21585
21585
  }
21586
21586
  return stream;
@@ -24521,30 +24521,30 @@ var init_line = __esm({
24521
24521
  // ../../node_modules/.pnpm/openai@6.27.0_ws@8.19.0_bufferutil@4.1.0_utf-8-validate@6.0.6__zod@4.3.6/node_modules/openai/internal/utils/log.mjs
24522
24522
  function noop() {
24523
24523
  }
24524
- function makeLogFn(fnLevel, logger33, logLevel) {
24525
- if (!logger33 || levelNumbers[fnLevel] > levelNumbers[logLevel]) {
24524
+ function makeLogFn(fnLevel, logger32, logLevel) {
24525
+ if (!logger32 || levelNumbers[fnLevel] > levelNumbers[logLevel]) {
24526
24526
  return noop;
24527
24527
  } else {
24528
- return logger33[fnLevel].bind(logger33);
24528
+ return logger32[fnLevel].bind(logger32);
24529
24529
  }
24530
24530
  }
24531
24531
  function loggerFor(client) {
24532
- const logger33 = client.logger;
24532
+ const logger32 = client.logger;
24533
24533
  const logLevel = client.logLevel ?? "off";
24534
- if (!logger33) {
24534
+ if (!logger32) {
24535
24535
  return noopLogger;
24536
24536
  }
24537
- const cachedLogger = cachedLoggers.get(logger33);
24537
+ const cachedLogger = cachedLoggers.get(logger32);
24538
24538
  if (cachedLogger && cachedLogger[0] === logLevel) {
24539
24539
  return cachedLogger[1];
24540
24540
  }
24541
24541
  const levelLogger = {
24542
- error: makeLogFn("error", logger33, logLevel),
24543
- warn: makeLogFn("warn", logger33, logLevel),
24544
- info: makeLogFn("info", logger33, logLevel),
24545
- debug: makeLogFn("debug", logger33, logLevel)
24542
+ error: makeLogFn("error", logger32, logLevel),
24543
+ warn: makeLogFn("warn", logger32, logLevel),
24544
+ info: makeLogFn("info", logger32, logLevel),
24545
+ debug: makeLogFn("debug", logger32, logLevel)
24546
24546
  };
24547
- cachedLoggers.set(logger33, [logLevel, levelLogger]);
24547
+ cachedLoggers.set(logger32, [logLevel, levelLogger]);
24548
24548
  return levelLogger;
24549
24549
  }
24550
24550
  var levelNumbers, parseLogLevel, noopLogger, cachedLoggers, formatRequestDetails;
@@ -24671,7 +24671,7 @@ var init_streaming = __esm({
24671
24671
  }
24672
24672
  static fromSSEResponse(response, controller, client, synthesizeEventData) {
24673
24673
  let consumed = false;
24674
- const logger33 = client ? loggerFor(client) : console;
24674
+ const logger32 = client ? loggerFor(client) : console;
24675
24675
  async function* iterator() {
24676
24676
  if (consumed) {
24677
24677
  throw new OpenAIError("Cannot iterate over a consumed stream, use `.tee()` to split the stream.");
@@ -24691,8 +24691,8 @@ var init_streaming = __esm({
24691
24691
  try {
24692
24692
  data = JSON.parse(sse.data);
24693
24693
  } catch (e) {
24694
- logger33.error(`Could not parse message into JSON:`, sse.data);
24695
- logger33.error(`From chunk:`, sse.raw);
24694
+ logger32.error(`Could not parse message into JSON:`, sse.data);
24695
+ logger32.error(`From chunk:`, sse.raw);
24696
24696
  throw e;
24697
24697
  }
24698
24698
  if (data && data.error) {
@@ -31632,30 +31632,30 @@ var init_sleep2 = __esm({
31632
31632
  // ../../node_modules/.pnpm/@anthropic-ai+sdk@0.52.0/node_modules/@anthropic-ai/sdk/internal/utils/log.mjs
31633
31633
  function noop2() {
31634
31634
  }
31635
- function makeLogFn2(fnLevel, logger33, logLevel) {
31636
- if (!logger33 || levelNumbers2[fnLevel] > levelNumbers2[logLevel]) {
31635
+ function makeLogFn2(fnLevel, logger32, logLevel) {
31636
+ if (!logger32 || levelNumbers2[fnLevel] > levelNumbers2[logLevel]) {
31637
31637
  return noop2;
31638
31638
  } else {
31639
- return logger33[fnLevel].bind(logger33);
31639
+ return logger32[fnLevel].bind(logger32);
31640
31640
  }
31641
31641
  }
31642
31642
  function loggerFor2(client) {
31643
- const logger33 = client.logger;
31643
+ const logger32 = client.logger;
31644
31644
  const logLevel = client.logLevel ?? "off";
31645
- if (!logger33) {
31645
+ if (!logger32) {
31646
31646
  return noopLogger2;
31647
31647
  }
31648
- const cachedLogger = cachedLoggers2.get(logger33);
31648
+ const cachedLogger = cachedLoggers2.get(logger32);
31649
31649
  if (cachedLogger && cachedLogger[0] === logLevel) {
31650
31650
  return cachedLogger[1];
31651
31651
  }
31652
31652
  const levelLogger = {
31653
- error: makeLogFn2("error", logger33, logLevel),
31654
- warn: makeLogFn2("warn", logger33, logLevel),
31655
- info: makeLogFn2("info", logger33, logLevel),
31656
- debug: makeLogFn2("debug", logger33, logLevel)
31653
+ error: makeLogFn2("error", logger32, logLevel),
31654
+ warn: makeLogFn2("warn", logger32, logLevel),
31655
+ info: makeLogFn2("info", logger32, logLevel),
31656
+ debug: makeLogFn2("debug", logger32, logLevel)
31657
31657
  };
31658
- cachedLoggers2.set(logger33, [logLevel, levelLogger]);
31658
+ cachedLoggers2.set(logger32, [logLevel, levelLogger]);
31659
31659
  return levelLogger;
31660
31660
  }
31661
31661
  var levelNumbers2, parseLogLevel2, noopLogger2, cachedLoggers2, formatRequestDetails2;
@@ -35669,6 +35669,41 @@ var init_llm = __esm({
35669
35669
  }
35670
35670
  });
35671
35671
 
35672
+ // ../core/dist/strategy-utils.js
35673
+ function generateRegimeBehavior(setupTypes = ["BREAKOUT", "MOMENTUM", "MEAN-REVERSION", "CATALYST"]) {
35674
+ return {
35675
+ MARKUP: {
35676
+ enabled: true,
35677
+ maxPositionSize: 0.5,
35678
+ confidenceThreshold: 0,
35679
+ preferredSetups: setupTypes
35680
+ },
35681
+ ACCUMULATION: {
35682
+ enabled: true,
35683
+ maxPositionSize: 0.25,
35684
+ confidenceThreshold: 0,
35685
+ preferredSetups: setupTypes
35686
+ },
35687
+ DISTRIBUTION: {
35688
+ enabled: true,
35689
+ maxPositionSize: 0.15,
35690
+ confidenceThreshold: 0,
35691
+ preferredSetups: setupTypes
35692
+ },
35693
+ MARKDOWN: {
35694
+ enabled: true,
35695
+ maxPositionSize: 0.1,
35696
+ confidenceThreshold: 0,
35697
+ preferredSetups: setupTypes
35698
+ }
35699
+ };
35700
+ }
35701
+ var init_strategy_utils = __esm({
35702
+ "../core/dist/strategy-utils.js"() {
35703
+ "use strict";
35704
+ }
35705
+ });
35706
+
35672
35707
  // ../core/dist/index.js
35673
35708
  var init_dist2 = __esm({
35674
35709
  "../core/dist/index.js"() {
@@ -35688,6 +35723,7 @@ var init_dist2 = __esm({
35688
35723
  init_errors3();
35689
35724
  init_crypto();
35690
35725
  init_llm();
35726
+ init_strategy_utils();
35691
35727
  }
35692
35728
  });
35693
35729
 
@@ -39040,7 +39076,7 @@ function parseIntOption(value) {
39040
39076
  function isApiError(error49) {
39041
39077
  return error49 instanceof Error && error49.name === "ApiError" && "status" in error49;
39042
39078
  }
39043
- function handleApiError(error49, context, logger33) {
39079
+ function handleApiError(error49, context, logger32) {
39044
39080
  if (isApiError(error49)) {
39045
39081
  switch (error49.status) {
39046
39082
  case 401:
@@ -39063,7 +39099,7 @@ function handleApiError(error49, context, logger33) {
39063
39099
  }
39064
39100
  } else {
39065
39101
  const message = error49 instanceof Error ? error49.message : String(error49);
39066
- logger33.error({ error: message }, context);
39102
+ logger32.error({ error: message }, context);
39067
39103
  console.error(source_default.red(`Error: ${message}`));
39068
39104
  }
39069
39105
  process.exitCode = isApiError(error49) ? 2 : 1;
@@ -57322,255 +57358,6 @@ async function openBrowser(url2) {
57322
57358
  }
57323
57359
  }
57324
57360
 
57325
- // dist/commands/connect-claude.js
57326
- init_source();
57327
- init_dist2();
57328
- init_api_client();
57329
- init_utils3();
57330
- import http2 from "node:http";
57331
- import { URL as URL3 } from "node:url";
57332
- var logger24 = createLogger("cli-connect-claude");
57333
- var CALLBACK_PORT2 = 1456;
57334
- var CALLBACK_PATH2 = "/callback";
57335
- var AUTH_TIMEOUT_MS2 = 3 * 60 * 1e3;
57336
- var POLL_INTERVAL_MS2 = 2e3;
57337
- function registerConnectClaudeCommand(program2) {
57338
- program2.command("connect-claude").description("Connect your Claude subscription as your LLM provider (no API key needed)").option("--disconnect", "Disconnect your Claude account").action(async (options) => {
57339
- try {
57340
- if (!await isRemoteMode()) {
57341
- console.error(source_default.yellow(" Requires API connection. Run: trading-boy login"));
57342
- process.exitCode = 1;
57343
- return;
57344
- }
57345
- if (options.disconnect) {
57346
- await handleDisconnect2();
57347
- } else {
57348
- await handleConnect2();
57349
- }
57350
- } catch (error49) {
57351
- const msg = error49 instanceof Error ? error49.message : String(error49);
57352
- logger24.error({ error: msg }, "connect-claude failed");
57353
- const connHelp = formatConnectionError(msg);
57354
- if (connHelp) {
57355
- console.error(source_default.red(`
57356
- Connection failed.
57357
- `));
57358
- console.error(connHelp);
57359
- } else {
57360
- console.error(source_default.red(`
57361
- Error: ${msg}`));
57362
- }
57363
- process.exitCode = error49 instanceof ApiError ? 2 : 1;
57364
- }
57365
- });
57366
- }
57367
- async function handleConnect2() {
57368
- try {
57369
- const current = await apiRequest("/api/v1/llm-config");
57370
- if (current.anthropicOAuthConnected) {
57371
- console.log("");
57372
- console.log(source_default.green(" \u2713 Claude is already connected"));
57373
- console.log(source_default.dim(` Provider: anthropic / ${current.model}`));
57374
- console.log("");
57375
- console.log(source_default.dim(" To disconnect: trading-boy connect-claude --disconnect"));
57376
- return;
57377
- }
57378
- } catch {
57379
- }
57380
- console.log("");
57381
- console.log(source_default.bold.cyan(" Connect Claude"));
57382
- console.log(source_default.gray(" " + "\u2500".repeat(50)));
57383
- console.log(source_default.dim(" Use your Claude subscription to power your trading agents."));
57384
- console.log(source_default.dim(" No API key needed \u2014 authenticates via your Anthropic account."));
57385
- console.log("");
57386
- const { authUrl, state } = await apiRequest("/api/v1/anthropic-oauth/auth-url");
57387
- const result = await raceForAuth2(authUrl, state);
57388
- if (result.via === "local") {
57389
- console.log(source_default.dim(" Exchanging authorization code..."));
57390
- await apiRequest("/api/v1/anthropic-oauth/callback", {
57391
- method: "POST",
57392
- body: { code: result.code, state: result.state }
57393
- });
57394
- printSuccess2(null);
57395
- } else {
57396
- printSuccess2(result.config.model);
57397
- }
57398
- }
57399
- function printSuccess2(model) {
57400
- console.log("");
57401
- console.log(source_default.green(" \u2713 Claude connected!"));
57402
- console.log("");
57403
- console.log(` ${source_default.gray("Provider:")} anthropic`);
57404
- if (model)
57405
- console.log(` ${source_default.gray("Model:")} ${model}`);
57406
- console.log("");
57407
- console.log(source_default.dim(" Your agents will now use your Claude subscription for LLM calls."));
57408
- console.log(source_default.dim(" Change model: trading-boy config set-llm-key --provider anthropic --model <model>"));
57409
- }
57410
- async function raceForAuth2(authUrl, state) {
57411
- const controller = new AbortController();
57412
- const localCallback = startLocalCallbackServer2(state, controller.signal);
57413
- const polling = pollForConnection2(controller.signal);
57414
- console.log(source_default.white(" Opening Claude login in your browser..."));
57415
- await openBrowser2(authUrl);
57416
- console.log(source_default.dim(" Complete sign-in in your browser to continue."));
57417
- console.log(source_default.dim(" Waiting for authentication..."));
57418
- console.log("");
57419
- try {
57420
- const result = await Promise.race([localCallback, polling]);
57421
- controller.abort();
57422
- return result;
57423
- } catch (err) {
57424
- controller.abort();
57425
- throw err;
57426
- }
57427
- }
57428
- function startLocalCallbackServer2(state, signal) {
57429
- return new Promise((resolve4, reject) => {
57430
- if (signal.aborted) {
57431
- reject(new Error("Cancelled"));
57432
- return;
57433
- }
57434
- const timeout = setTimeout(() => {
57435
- server.close();
57436
- reject(new Error("Timed out waiting for Claude authentication (3 minutes)"));
57437
- }, AUTH_TIMEOUT_MS2);
57438
- signal.addEventListener("abort", () => {
57439
- clearTimeout(timeout);
57440
- server.close();
57441
- }, { once: true });
57442
- const server = http2.createServer((req, res) => {
57443
- const url2 = new URL3(req.url ?? "/", `http://localhost:${CALLBACK_PORT2}`);
57444
- if (url2.pathname !== CALLBACK_PATH2) {
57445
- res.writeHead(404, { "Content-Type": "text/plain" });
57446
- res.end("Not found");
57447
- return;
57448
- }
57449
- const errorParam = url2.searchParams.get("error");
57450
- const errorDesc = url2.searchParams.get("error_description");
57451
- const codeParam = url2.searchParams.get("code");
57452
- if (errorParam) {
57453
- res.writeHead(200, { "Content-Type": "text/html" });
57454
- res.end(callbackHtml2(false, errorDesc || errorParam));
57455
- clearTimeout(timeout);
57456
- server.close();
57457
- reject(new Error(`Anthropic returned error: ${errorDesc || errorParam}`));
57458
- return;
57459
- }
57460
- if (!codeParam) {
57461
- res.writeHead(200, { "Content-Type": "text/html" });
57462
- res.end(callbackHtml2(false, "Missing authorization code"));
57463
- clearTimeout(timeout);
57464
- server.close();
57465
- reject(new Error("No authorization code in callback"));
57466
- return;
57467
- }
57468
- res.writeHead(200, { "Content-Type": "text/html" });
57469
- res.end(callbackHtml2(true));
57470
- clearTimeout(timeout);
57471
- server.close();
57472
- resolve4({ via: "local", code: codeParam, state });
57473
- });
57474
- server.on("error", (err) => {
57475
- clearTimeout(timeout);
57476
- if (err.code === "EADDRINUSE") {
57477
- logger24.debug("Port %d in use, falling back to polling only", CALLBACK_PORT2);
57478
- return;
57479
- }
57480
- reject(err);
57481
- });
57482
- server.listen(CALLBACK_PORT2, "127.0.0.1");
57483
- });
57484
- }
57485
- async function pollForConnection2(signal) {
57486
- const deadline = Date.now() + AUTH_TIMEOUT_MS2;
57487
- while (Date.now() < deadline) {
57488
- if (signal.aborted)
57489
- throw new Error("Cancelled");
57490
- await sleep4(POLL_INTERVAL_MS2);
57491
- if (signal.aborted)
57492
- throw new Error("Cancelled");
57493
- try {
57494
- const config2 = await apiRequest("/api/v1/llm-config");
57495
- if (config2.anthropicOAuthConnected) {
57496
- return { via: "poll", config: config2 };
57497
- }
57498
- } catch {
57499
- logger24.debug("Poll attempt failed, retrying...");
57500
- }
57501
- }
57502
- throw new Error("Timed out waiting for Claude authentication (3 minutes)");
57503
- }
57504
- async function handleDisconnect2() {
57505
- const { confirm } = await Promise.resolve().then(() => (init_esm15(), esm_exports));
57506
- const yes = await confirm({
57507
- message: "Disconnect your Claude account?",
57508
- default: false
57509
- });
57510
- if (!yes) {
57511
- console.log(source_default.dim(" Cancelled."));
57512
- return;
57513
- }
57514
- await apiRequest("/api/v1/anthropic-oauth/disconnect", {
57515
- method: "POST"
57516
- });
57517
- console.log(source_default.green(" \u2713 Claude disconnected."));
57518
- console.log(source_default.dim(" Your agents will need an API key to continue. Set one:"));
57519
- console.log(source_default.dim(" trading-boy config set-llm-key <your-api-key>"));
57520
- }
57521
- function callbackHtml2(success3, errorMsg) {
57522
- const title = success3 ? "Claude Connected" : "Connection Failed";
57523
- const icon = success3 ? "&#10003;" : "&#10007;";
57524
- const color = success3 ? "#22c55e" : "#ef4444";
57525
- const message = success3 ? "Your Claude subscription is now connected to Trading Boy.<br>You can close this tab." : `Something went wrong: ${escapeHtml2(errorMsg ?? "Unknown error")}.<br>Please try again.`;
57526
- return `<!DOCTYPE html>
57527
- <html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
57528
- <title>${title} \u2014 Trading Boy</title>
57529
- <style>*{margin:0;padding:0;box-sizing:border-box}body{font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;display:flex;align-items:center;justify-content:center;min-height:100vh;background:#0a0a0a;color:#e5e5e5}
57530
- .card{text-align:center;padding:3rem;max-width:480px}.icon{font-size:4rem;color:${color};margin-bottom:1rem}h1{font-size:1.5rem;margin-bottom:1rem}p{color:#a3a3a3;line-height:1.6}</style>
57531
- </head><body><div class="card"><div class="icon">${icon}</div><h1>${title}</h1><p>${message}</p></div></body></html>`;
57532
- }
57533
- function escapeHtml2(str2) {
57534
- return str2.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
57535
- }
57536
- function sleep4(ms) {
57537
- return new Promise((resolve4) => setTimeout(resolve4, ms));
57538
- }
57539
- var ALLOWED_AUTH_DOMAINS2 = /* @__PURE__ */ new Set([
57540
- "platform.claude.com",
57541
- "claude.ai",
57542
- "claude.com"
57543
- ]);
57544
- function validateAuthUrl2(url2) {
57545
- const parsed = new URL3(url2);
57546
- if (parsed.protocol !== "https:") {
57547
- throw new Error(`Refusing to open non-HTTPS URL: ${url2}`);
57548
- }
57549
- if (!ALLOWED_AUTH_DOMAINS2.has(parsed.hostname)) {
57550
- throw new Error(`Refusing to open URL with untrusted domain: ${parsed.hostname}`);
57551
- }
57552
- }
57553
- async function openBrowser2(url2) {
57554
- try {
57555
- validateAuthUrl2(url2);
57556
- const { default: open2 } = await Promise.resolve().then(() => (init_open(), open_exports));
57557
- await open2(url2);
57558
- } catch (err) {
57559
- const message = err instanceof Error ? err.message : String(err);
57560
- if (message.startsWith("Refusing to open")) {
57561
- console.error(source_default.red(`
57562
- ${message}`));
57563
- throw err;
57564
- }
57565
- console.log(source_default.yellow(`
57566
- Could not open browser automatically.`));
57567
- console.log(source_default.yellow(` Please open this URL manually:
57568
- `));
57569
- console.log(` ${source_default.cyan.underline(url2)}
57570
- `);
57571
- }
57572
- }
57573
-
57574
57361
  // dist/commands/onboarding.js
57575
57362
  async function runOnboarding() {
57576
57363
  const { confirm, input } = await Promise.resolve().then(() => (init_esm15(), esm_exports));
@@ -57678,11 +57465,6 @@ async function runOnboarding() {
57678
57465
  const llmChoice = await select({
57679
57466
  message: "How do you want to power your agent?",
57680
57467
  choices: [
57681
- {
57682
- name: "Use my Claude subscription (no API key needed)",
57683
- value: "claude",
57684
- description: "Sign in with your Anthropic account \u2014 uses your existing Claude Pro/Max/Team plan"
57685
- },
57686
57468
  {
57687
57469
  name: "Use my ChatGPT subscription (no API key needed)",
57688
57470
  value: "chatgpt",
@@ -57699,15 +57481,7 @@ async function runOnboarding() {
57699
57481
  }
57700
57482
  ]
57701
57483
  });
57702
- if (llmChoice === "claude") {
57703
- try {
57704
- await handleConnect2();
57705
- } catch (error49) {
57706
- const msg = error49 instanceof Error ? error49.message : String(error49);
57707
- console.log(source_default.yellow(` Could not connect Claude: ${msg}`));
57708
- console.log(source_default.dim(" Try later: trading-boy connect-claude"));
57709
- }
57710
- } else if (llmChoice === "chatgpt") {
57484
+ if (llmChoice === "chatgpt") {
57711
57485
  try {
57712
57486
  await handleConnect();
57713
57487
  } catch (error49) {
@@ -57749,8 +57523,7 @@ async function runOnboarding() {
57749
57523
  console.log("");
57750
57524
  console.log(source_default.yellow(" \u26A0 Without an LLM provider, agents can scan prices but cannot"));
57751
57525
  console.log(source_default.yellow(" analyze markets or make trade decisions."));
57752
- console.log(source_default.dim(" Set it later: trading-boy connect-claude"));
57753
- console.log(source_default.dim(" Or ChatGPT: trading-boy connect-chatgpt"));
57526
+ console.log(source_default.dim(" Set it later: trading-boy connect-chatgpt"));
57754
57527
  console.log(source_default.dim(" Or BYOK: trading-boy config set-llm-key <your-api-key>"));
57755
57528
  }
57756
57529
  } catch (error49) {
@@ -57826,8 +57599,8 @@ function isUserAbort(error49) {
57826
57599
  }
57827
57600
 
57828
57601
  // dist/commands/subscribe.js
57829
- var logger25 = createLogger("cli-subscribe");
57830
- var POLL_INTERVAL_MS3 = 3e3;
57602
+ var logger24 = createLogger("cli-subscribe");
57603
+ var POLL_INTERVAL_MS2 = 3e3;
57831
57604
  var POLL_TIMEOUT_MS = 5 * 60 * 1e3;
57832
57605
  async function createCheckoutSession(email3, plan = "starter") {
57833
57606
  const response = await fetch(`${getApiBase()}/api/v1/billing/checkout`, {
@@ -57890,9 +57663,9 @@ async function pollCryptoPayment(reference, provisioningToken, onTick) {
57890
57663
  return { success: false, error: "Payment expired or not found. Please try again." };
57891
57664
  }
57892
57665
  } catch (err) {
57893
- logger25.debug({ error: err }, "Crypto poll attempt failed, retrying");
57666
+ logger24.debug({ error: err }, "Crypto poll attempt failed, retrying");
57894
57667
  }
57895
- await sleep5(CRYPTO_POLL_INTERVAL);
57668
+ await sleep4(CRYPTO_POLL_INTERVAL);
57896
57669
  }
57897
57670
  if (Date.now() - start >= POLL_TIMEOUT_MS) {
57898
57671
  return { success: false, error: "Timed out waiting for USDC payment. If you sent the payment, contact support." };
@@ -57908,9 +57681,9 @@ async function pollCryptoPayment(reference, provisioningToken, onTick) {
57908
57681
  return { success: false, error: "Provisioning token expired after payment. Contact support." };
57909
57682
  }
57910
57683
  } catch (err) {
57911
- logger25.debug({ error: err }, "Provision poll attempt failed, retrying");
57684
+ logger24.debug({ error: err }, "Provision poll attempt failed, retrying");
57912
57685
  }
57913
- await sleep5(POLL_INTERVAL_MS3);
57686
+ await sleep4(POLL_INTERVAL_MS2);
57914
57687
  }
57915
57688
  return { success: false, error: "Timed out waiting for API key provisioning. Contact support." };
57916
57689
  }
@@ -57943,9 +57716,9 @@ async function pollForApiKey(token, onTick) {
57943
57716
  };
57944
57717
  }
57945
57718
  } catch (err) {
57946
- logger25.debug({ error: err }, "Poll attempt failed, retrying");
57719
+ logger24.debug({ error: err }, "Poll attempt failed, retrying");
57947
57720
  }
57948
- await sleep5(POLL_INTERVAL_MS3);
57721
+ await sleep4(POLL_INTERVAL_MS2);
57949
57722
  elapsed = Date.now() - start;
57950
57723
  }
57951
57724
  return {
@@ -58069,7 +57842,7 @@ function registerSubscribeCommand(program2) {
58069
57842
  return;
58070
57843
  }
58071
57844
  const message = error49 instanceof Error ? error49.message : String(error49);
58072
- logger25.error({ error: message }, "Subscribe command failed");
57845
+ logger24.error({ error: message }, "Subscribe command failed");
58073
57846
  console.error(source_default.red(` Error: ${message}`));
58074
57847
  process.exitCode = 1;
58075
57848
  }
@@ -58120,7 +57893,7 @@ async function handleStripeCheckout(email3, plan) {
58120
57893
  return;
58121
57894
  }
58122
57895
  console.log(source_default.white(" Opening Stripe Checkout in your browser..."));
58123
- await openBrowser3(checkout.checkoutUrl);
57896
+ await openBrowser2(checkout.checkoutUrl);
58124
57897
  console.log(source_default.dim(" Complete payment in your browser to continue."));
58125
57898
  console.log("");
58126
57899
  let pollResult;
@@ -58225,7 +57998,7 @@ async function storeAndDisplayKey(pollResult) {
58225
57998
  console.error(source_default.yellow(" Warning: Could not save API key automatically."));
58226
57999
  console.error(source_default.yellow(` Your API key: ${pollResult.apiKey}`));
58227
58000
  console.error(source_default.yellow(" Save this key and run: trading-boy login --api-key <key>"));
58228
- logger25.error({ error: err }, "Failed to save credentials");
58001
+ logger24.error({ error: err }, "Failed to save credentials");
58229
58002
  process.exitCode = 1;
58230
58003
  return;
58231
58004
  }
@@ -58238,7 +58011,7 @@ async function storeAndDisplayKey(pollResult) {
58238
58011
  function isValidEmail(email3) {
58239
58012
  return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email3);
58240
58013
  }
58241
- function sleep5(ms) {
58014
+ function sleep4(ms) {
58242
58015
  return new Promise((resolve4) => setTimeout(resolve4, ms));
58243
58016
  }
58244
58017
  var ALLOWED_CHECKOUT_DOMAINS = /* @__PURE__ */ new Set([
@@ -58255,7 +58028,7 @@ function validateBrowserUrl(url2) {
58255
58028
  throw new Error(`Refusing to open URL with untrusted domain: ${parsed.hostname}`);
58256
58029
  }
58257
58030
  }
58258
- async function openBrowser3(url2) {
58031
+ async function openBrowser2(url2) {
58259
58032
  try {
58260
58033
  validateBrowserUrl(url2);
58261
58034
  const { default: open2 } = await Promise.resolve().then(() => (init_open(), open_exports));
@@ -58610,7 +58383,7 @@ init_source();
58610
58383
  init_dist2();
58611
58384
  init_api_client();
58612
58385
  init_utils3();
58613
- var logger26 = createLogger("cli-coaching");
58386
+ var logger25 = createLogger("cli-coaching");
58614
58387
  var BYOK_HINT = `LLM API key required. Run: ${source_default.white("trading-boy config set-llm-key <key>")}`;
58615
58388
  function isByokError(error49) {
58616
58389
  if (error49 instanceof ApiError && error49.status === 422)
@@ -58705,7 +58478,7 @@ function registerCoachingCommand(program2) {
58705
58478
  return;
58706
58479
  }
58707
58480
  const message = error49 instanceof ApiError ? error49.message : error49 instanceof Error ? error49.message : String(error49);
58708
- logger26.error({ error: message }, "Pre-trade coaching failed");
58481
+ logger25.error({ error: message }, "Pre-trade coaching failed");
58709
58482
  console.error(source_default.red(`Error: ${message}`));
58710
58483
  process.exitCode = error49 instanceof ApiError ? 2 : 1;
58711
58484
  }
@@ -58746,7 +58519,7 @@ function registerCoachingCommand(program2) {
58746
58519
  return;
58747
58520
  }
58748
58521
  const message = error49 instanceof ApiError ? error49.message : error49 instanceof Error ? error49.message : String(error49);
58749
- logger26.error({ error: message }, "Post-trade coaching failed");
58522
+ logger25.error({ error: message }, "Post-trade coaching failed");
58750
58523
  console.error(source_default.red(`Error: ${message}`));
58751
58524
  process.exitCode = error49 instanceof ApiError ? 2 : 1;
58752
58525
  }
@@ -58762,7 +58535,7 @@ function registerCoachingCommand(program2) {
58762
58535
  console.log("");
58763
58536
  } catch (error49) {
58764
58537
  const message = error49 instanceof ApiError ? error49.message : error49 instanceof Error ? error49.message : String(error49);
58765
- logger26.error({ error: message }, "Acknowledge failed");
58538
+ logger25.error({ error: message }, "Acknowledge failed");
58766
58539
  console.error(source_default.red(`Error: ${message}`));
58767
58540
  process.exitCode = error49 instanceof ApiError ? 2 : 1;
58768
58541
  }
@@ -58777,7 +58550,7 @@ function registerCoachingCommand(program2) {
58777
58550
  console.log("");
58778
58551
  } catch (error49) {
58779
58552
  const message = error49 instanceof ApiError ? error49.message : error49 instanceof Error ? error49.message : String(error49);
58780
- logger26.error({ error: message }, "Reset failed");
58553
+ logger25.error({ error: message }, "Reset failed");
58781
58554
  console.error(source_default.red(`Error: ${message}`));
58782
58555
  process.exitCode = error49 instanceof ApiError ? 2 : 1;
58783
58556
  }
@@ -58789,7 +58562,7 @@ init_source();
58789
58562
  init_dist2();
58790
58563
  init_api_client();
58791
58564
  init_utils3();
58792
- var logger27 = createLogger("cli-thesis");
58565
+ var logger26 = createLogger("cli-thesis");
58793
58566
  var BYOK_HINT2 = `LLM API key required. Run: ${source_default.white("trading-boy config set-llm-key <key>")}`;
58794
58567
  function formatThesisOutput(response) {
58795
58568
  const lines = [];
@@ -58890,7 +58663,7 @@ function registerThesisCommand(program2) {
58890
58663
  return;
58891
58664
  }
58892
58665
  const message = error49 instanceof ApiError ? error49.message : error49 instanceof Error ? error49.message : String(error49);
58893
- logger27.error({ error: message }, "Thesis extraction failed");
58666
+ logger26.error({ error: message }, "Thesis extraction failed");
58894
58667
  console.error(source_default.red(`Error: ${message}`));
58895
58668
  process.exitCode = error49 instanceof ApiError ? 2 : 1;
58896
58669
  }
@@ -58902,7 +58675,7 @@ init_source();
58902
58675
  init_dist2();
58903
58676
  init_api_client();
58904
58677
  init_utils3();
58905
- var logger28 = createLogger("cli-strategy");
58678
+ var logger27 = createLogger("cli-strategy");
58906
58679
  function formatShortDate2(isoString) {
58907
58680
  try {
58908
58681
  return new Date(isoString).toISOString().slice(0, 16).replace("T", " ");
@@ -59012,12 +58785,7 @@ function registerStrategyCommand(program2) {
59012
58785
  agentId: options.agentId,
59013
58786
  tokens,
59014
58787
  setupTypes,
59015
- regimeBehavior: {
59016
- ACCUMULATION: { enabled: true, maxPositionSize: 0.25, confidenceThreshold: 0.6, preferredSetups: setupTypes },
59017
- MARKUP: { enabled: true, maxPositionSize: 0.5, confidenceThreshold: 0.5, preferredSetups: setupTypes },
59018
- DISTRIBUTION: { enabled: true, maxPositionSize: 0.15, confidenceThreshold: 0.7, preferredSetups: setupTypes },
59019
- MARKDOWN: { enabled: false, maxPositionSize: 0.1, confidenceThreshold: 0.8, preferredSetups: setupTypes }
59020
- },
58788
+ regimeBehavior: generateRegimeBehavior(setupTypes),
59021
58789
  riskLimits: {
59022
58790
  maxDrawdown: 0.2,
59023
58791
  maxConcurrentPositions: 5,
@@ -59038,7 +58806,7 @@ function registerStrategyCommand(program2) {
59038
58806
  console.log(formatStrategyDetail(result));
59039
58807
  }
59040
58808
  } catch (error49) {
59041
- handleApiError(error49, "Strategy create failed", logger28);
58809
+ handleApiError(error49, "Strategy create failed", logger27);
59042
58810
  }
59043
58811
  });
59044
58812
  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) => {
@@ -59058,7 +58826,7 @@ function registerStrategyCommand(program2) {
59058
58826
  console.log(formatStrategyList(result));
59059
58827
  }
59060
58828
  } catch (error49) {
59061
- handleApiError(error49, "Strategy list failed", logger28);
58829
+ handleApiError(error49, "Strategy list failed", logger27);
59062
58830
  }
59063
58831
  });
59064
58832
  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) => {
@@ -59072,7 +58840,7 @@ function registerStrategyCommand(program2) {
59072
58840
  console.log(formatStrategyDetail(result));
59073
58841
  }
59074
58842
  } catch (error49) {
59075
- handleApiError(error49, "Strategy show failed", logger28);
58843
+ handleApiError(error49, "Strategy show failed", logger27);
59076
58844
  }
59077
58845
  });
59078
58846
  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) => {
@@ -59101,7 +58869,7 @@ function registerStrategyCommand(program2) {
59101
58869
  console.log(formatStrategyDetail(result));
59102
58870
  }
59103
58871
  } catch (error49) {
59104
- handleApiError(error49, "Strategy update failed", logger28);
58872
+ handleApiError(error49, "Strategy update failed", logger27);
59105
58873
  }
59106
58874
  });
59107
58875
  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) => {
@@ -59115,7 +58883,7 @@ function registerStrategyCommand(program2) {
59115
58883
  console.log(formatHistoryList(result));
59116
58884
  }
59117
58885
  } catch (error49) {
59118
- handleApiError(error49, "Strategy history failed", logger28);
58886
+ handleApiError(error49, "Strategy history failed", logger27);
59119
58887
  }
59120
58888
  });
59121
58889
  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) => {
@@ -59141,7 +58909,7 @@ function registerStrategyCommand(program2) {
59141
58909
  console.log(output);
59142
58910
  }
59143
58911
  } catch (error49) {
59144
- handleApiError(error49, "Strategy export failed", logger28);
58912
+ handleApiError(error49, "Strategy export failed", logger27);
59145
58913
  }
59146
58914
  });
59147
58915
  }
@@ -59151,7 +58919,7 @@ init_source();
59151
58919
  init_dist2();
59152
58920
  init_api_client();
59153
58921
  init_utils3();
59154
- var logger29 = createLogger("cli-replay");
58922
+ var logger28 = createLogger("cli-replay");
59155
58923
  function formatPercent2(val) {
59156
58924
  const sign = val >= 0 ? "+" : "";
59157
58925
  const str2 = `${sign}${val.toFixed(2)}%`;
@@ -59217,7 +58985,7 @@ function formatWinRate2(rate) {
59217
58985
  return source_default.yellow(str2);
59218
58986
  return source_default.red(str2);
59219
58987
  }
59220
- var POLL_INTERVAL_MS4 = 2e3;
58988
+ var POLL_INTERVAL_MS3 = 2e3;
59221
58989
  var POLL_TIMEOUT_MS2 = 6e4;
59222
58990
  async function pollReplayJob(jobId) {
59223
58991
  const deadline = Date.now() + POLL_TIMEOUT_MS2;
@@ -59226,7 +58994,7 @@ async function pollReplayJob(jobId) {
59226
58994
  if (status.status === "COMPLETE" || status.status === "FAILED") {
59227
58995
  return status;
59228
58996
  }
59229
- await new Promise((resolve4) => setTimeout(resolve4, POLL_INTERVAL_MS4));
58997
+ await new Promise((resolve4) => setTimeout(resolve4, POLL_INTERVAL_MS3));
59230
58998
  }
59231
58999
  throw new Error(`Replay job ${jobId} did not complete within ${POLL_TIMEOUT_MS2 / 1e3}s timeout.`);
59232
59000
  }
@@ -59268,7 +59036,7 @@ function registerReplayCommand(program2) {
59268
59036
  submitSpinner.succeed(source_default.dim(`Job submitted: ${jobId}`));
59269
59037
  } catch (error49) {
59270
59038
  submitSpinner.fail("Failed to submit replay job");
59271
- handleApiError(error49, "Replay submit failed", logger29);
59039
+ handleApiError(error49, "Replay submit failed", logger28);
59272
59040
  return;
59273
59041
  }
59274
59042
  const pollSpinner = (await createSpinner2("Running replay\u2026")).start();
@@ -59278,7 +59046,7 @@ function registerReplayCommand(program2) {
59278
59046
  pollSpinner.stop();
59279
59047
  } catch (error49) {
59280
59048
  pollSpinner.fail("Replay timed out or encountered an error");
59281
- handleApiError(error49, "Replay polling failed", logger29);
59049
+ handleApiError(error49, "Replay polling failed", logger28);
59282
59050
  return;
59283
59051
  }
59284
59052
  if (!finalStatus.result) {
@@ -59451,7 +59219,7 @@ init_source();
59451
59219
  init_dist2();
59452
59220
  init_api_client();
59453
59221
  init_utils3();
59454
- var logger30 = createLogger("cli-suggestions");
59222
+ var logger29 = createLogger("cli-suggestions");
59455
59223
  function formatSuggestionsList(data) {
59456
59224
  const lines = [];
59457
59225
  lines.push("");
@@ -59513,7 +59281,7 @@ function registerSuggestionsCommand(program2) {
59513
59281
  }
59514
59282
  } catch (error49) {
59515
59283
  const message = error49 instanceof ApiError ? error49.message : error49 instanceof Error ? error49.message : String(error49);
59516
- logger30.error({ error: message }, "Failed to list suggestions");
59284
+ logger29.error({ error: message }, "Failed to list suggestions");
59517
59285
  console.error(source_default.red(`Error: ${message}`));
59518
59286
  process.exitCode = error49 instanceof ApiError ? 2 : 1;
59519
59287
  }
@@ -59532,7 +59300,7 @@ function registerSuggestionsCommand(program2) {
59532
59300
  }
59533
59301
  } catch (error49) {
59534
59302
  const message = error49 instanceof ApiError ? error49.message : error49 instanceof Error ? error49.message : String(error49);
59535
- logger30.error({ error: message }, "Failed to approve suggestion");
59303
+ logger29.error({ error: message }, "Failed to approve suggestion");
59536
59304
  console.error(source_default.red(`Error: ${message}`));
59537
59305
  process.exitCode = error49 instanceof ApiError ? 2 : 1;
59538
59306
  }
@@ -59551,7 +59319,7 @@ function registerSuggestionsCommand(program2) {
59551
59319
  }
59552
59320
  } catch (error49) {
59553
59321
  const message = error49 instanceof ApiError ? error49.message : error49 instanceof Error ? error49.message : String(error49);
59554
- logger30.error({ error: message }, "Failed to reject suggestion");
59322
+ logger29.error({ error: message }, "Failed to reject suggestion");
59555
59323
  console.error(source_default.red(`Error: ${message}`));
59556
59324
  process.exitCode = error49 instanceof ApiError ? 2 : 1;
59557
59325
  }
@@ -59563,7 +59331,7 @@ init_source();
59563
59331
  init_dist2();
59564
59332
  init_api_client();
59565
59333
  init_utils3();
59566
- var logger31 = createLogger("cli-cron");
59334
+ var logger30 = createLogger("cli-cron");
59567
59335
  function formatShortDate4(isoString) {
59568
59336
  if (!isoString)
59569
59337
  return source_default.dim("\u2014");
@@ -59635,7 +59403,7 @@ function registerCronCommand(program2) {
59635
59403
  console.log("");
59636
59404
  }
59637
59405
  } catch (error49) {
59638
- handleApiError(error49, "Cron create failed", logger31);
59406
+ handleApiError(error49, "Cron create failed", logger30);
59639
59407
  }
59640
59408
  });
59641
59409
  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) => {
@@ -59662,7 +59430,7 @@ function registerCronCommand(program2) {
59662
59430
  console.log(source_default.dim(` ${result.count} job(s)`));
59663
59431
  console.log("");
59664
59432
  } catch (error49) {
59665
- handleApiError(error49, "Cron list failed", logger31);
59433
+ handleApiError(error49, "Cron list failed", logger30);
59666
59434
  }
59667
59435
  });
59668
59436
  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) => {
@@ -59690,7 +59458,7 @@ function registerCronCommand(program2) {
59690
59458
  console.log(` ${source_default.gray("Created:")} ${formatShortDate4(job.createdAt)}`);
59691
59459
  console.log("");
59692
59460
  } catch (error49) {
59693
- handleApiError(error49, "Cron show failed", logger31);
59461
+ handleApiError(error49, "Cron show failed", logger30);
59694
59462
  }
59695
59463
  });
59696
59464
  cron.command("pause <jobId>").description("Pause a cron job").action(async (jobId) => {
@@ -59703,7 +59471,7 @@ function registerCronCommand(program2) {
59703
59471
  });
59704
59472
  console.log(source_default.green(` Job ${jobId} paused`));
59705
59473
  } catch (error49) {
59706
- handleApiError(error49, "Cron pause failed", logger31);
59474
+ handleApiError(error49, "Cron pause failed", logger30);
59707
59475
  }
59708
59476
  });
59709
59477
  cron.command("resume <jobId>").description("Resume a paused cron job").action(async (jobId) => {
@@ -59716,7 +59484,7 @@ function registerCronCommand(program2) {
59716
59484
  });
59717
59485
  console.log(source_default.green(` Job ${jobId} resumed`));
59718
59486
  } catch (error49) {
59719
- handleApiError(error49, "Cron resume failed", logger31);
59487
+ handleApiError(error49, "Cron resume failed", logger30);
59720
59488
  }
59721
59489
  });
59722
59490
  cron.command("delete <jobId>").description("Delete a cron job").action(async (jobId) => {
@@ -59728,7 +59496,7 @@ function registerCronCommand(program2) {
59728
59496
  });
59729
59497
  console.log(source_default.green(` Job ${jobId} deleted`));
59730
59498
  } catch (error49) {
59731
- handleApiError(error49, "Cron delete failed", logger31);
59499
+ handleApiError(error49, "Cron delete failed", logger30);
59732
59500
  }
59733
59501
  });
59734
59502
  cron.command("run <jobId>").description("Trigger immediate execution of a cron job").action(async (jobId) => {
@@ -59740,7 +59508,7 @@ function registerCronCommand(program2) {
59740
59508
  });
59741
59509
  console.log(source_default.green(` Job ${jobId} execution triggered`));
59742
59510
  } catch (error49) {
59743
- handleApiError(error49, "Cron run failed", logger31);
59511
+ handleApiError(error49, "Cron run failed", logger30);
59744
59512
  }
59745
59513
  });
59746
59514
  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) => {
@@ -59768,7 +59536,7 @@ function registerCronCommand(program2) {
59768
59536
  console.log(source_default.dim(` ${result.count} run(s)`));
59769
59537
  console.log("");
59770
59538
  } catch (error49) {
59771
- handleApiError(error49, "Cron history failed", logger31);
59539
+ handleApiError(error49, "Cron history failed", logger30);
59772
59540
  }
59773
59541
  });
59774
59542
  }
@@ -59780,7 +59548,7 @@ init_source();
59780
59548
  init_dist2();
59781
59549
  init_api_client();
59782
59550
  init_utils3();
59783
- var logger32 = createLogger("cli-agent");
59551
+ var logger31 = createLogger("cli-agent");
59784
59552
  function formatShortDate5(isoString) {
59785
59553
  if (!isoString)
59786
59554
  return source_default.dim("\u2014");
@@ -59843,7 +59611,7 @@ function parseHumanInterval(value) {
59843
59611
  var MIN_SCAN_INTERVAL_MS = 6e4;
59844
59612
  function registerAgentCommand(program2) {
59845
59613
  const agent = program2.command("agent").description("Manage autonomous trading agents");
59846
- 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").option("--exit-reasoner", "Enable LLM-powered exit reasoning for this agent").addOption(new Option("--format <format>", "Output format").choices(["text", "json"]).default("text")).action(async (options) => {
59614
+ 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 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").option("--exit-reasoner", "Enable LLM-powered exit reasoning for this agent").addOption(new Option("--format <format>", "Output format").choices(["text", "json"]).default("text")).action(async (options) => {
59847
59615
  if (!await ensureRemote())
59848
59616
  return;
59849
59617
  if (!options.traderId) {
@@ -59852,16 +59620,11 @@ function registerAgentCommand(program2) {
59852
59620
  process.exitCode = 1;
59853
59621
  return;
59854
59622
  }
59855
- if (!options.strategyId) {
59856
- console.error(source_default.red("Error: --strategy-id is required."));
59857
- console.log(source_default.dim(" Find yours with: trading-boy strategy list"));
59858
- process.exitCode = 1;
59859
- return;
59860
- }
59861
59623
  const body = {
59862
- traderId: options.traderId,
59863
- strategyId: options.strategyId
59624
+ traderId: options.traderId
59864
59625
  };
59626
+ if (options.strategyId)
59627
+ body.strategyId = options.strategyId;
59865
59628
  if (options.name)
59866
59629
  body.name = options.name;
59867
59630
  if (options.autonomy)
@@ -59937,14 +59700,14 @@ function registerAgentCommand(program2) {
59937
59700
  console.log(` ${source_default.gray("ID:")} ${result.id}`);
59938
59701
  console.log(` ${source_default.gray("Name:")} ${result.name}`);
59939
59702
  console.log(` ${source_default.gray("Trader:")} ${result.traderId}`);
59940
- console.log(` ${source_default.gray("Strategy:")} ${result.strategyId}`);
59703
+ console.log(` ${source_default.gray("Strategy:")} ${result.strategyId}${result.autoStrategyCreated ? source_default.dim(" (auto-created)") : ""}`);
59941
59704
  console.log(` ${source_default.gray("Autonomy:")} ${formatAutonomy(result.autonomyLevel)}`);
59942
59705
  console.log(` ${source_default.gray("Interval:")} ${formatInterval(result.scanIntervalMs)}`);
59943
59706
  console.log(` ${source_default.gray("Next scan:")} ${formatShortDate5(result.nextScanAt)}`);
59944
59707
  console.log("");
59945
59708
  }
59946
59709
  } catch (error49) {
59947
- handleApiError(error49, "Agent create failed", logger32);
59710
+ handleApiError(error49, "Agent create failed", logger31);
59948
59711
  }
59949
59712
  });
59950
59713
  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) => {
@@ -59977,7 +59740,7 @@ function registerAgentCommand(program2) {
59977
59740
  console.log(source_default.dim(` ${result.count} agent(s)`));
59978
59741
  console.log("");
59979
59742
  } catch (error49) {
59980
- handleApiError(error49, "Agent list failed", logger32);
59743
+ handleApiError(error49, "Agent list failed", logger31);
59981
59744
  }
59982
59745
  });
59983
59746
  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) => {
@@ -60050,7 +59813,7 @@ function registerAgentCommand(program2) {
60050
59813
  }
60051
59814
  console.log("");
60052
59815
  } catch (error49) {
60053
- handleApiError(error49, "Agent show failed", logger32);
59816
+ handleApiError(error49, "Agent show failed", logger31);
60054
59817
  }
60055
59818
  });
60056
59819
  agent.command("pause <agentId>").description("Pause an agent").addOption(new Option("--format <format>", "Output format").choices(["text", "json"]).default("text")).action(async (agentId, options) => {
@@ -60066,7 +59829,7 @@ function registerAgentCommand(program2) {
60066
59829
  console.log(source_default.green(` Agent ${agentId} paused`));
60067
59830
  }
60068
59831
  } catch (error49) {
60069
- handleApiError(error49, "Agent pause failed", logger32);
59832
+ handleApiError(error49, "Agent pause failed", logger31);
60070
59833
  }
60071
59834
  });
60072
59835
  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) => {
@@ -60082,7 +59845,7 @@ function registerAgentCommand(program2) {
60082
59845
  console.log(source_default.green(` Agent ${agentId} resumed`));
60083
59846
  }
60084
59847
  } catch (error49) {
60085
- handleApiError(error49, "Agent resume failed", logger32);
59848
+ handleApiError(error49, "Agent resume failed", logger31);
60086
59849
  }
60087
59850
  });
60088
59851
  agent.command("delete <agentId>").description("Delete an agent").addOption(new Option("--format <format>", "Output format").choices(["text", "json"]).default("text")).action(async (agentId, options) => {
@@ -60098,7 +59861,7 @@ function registerAgentCommand(program2) {
60098
59861
  console.log(source_default.green(` Agent ${agentId} deleted`));
60099
59862
  }
60100
59863
  } catch (error49) {
60101
- handleApiError(error49, "Agent delete failed", logger32);
59864
+ handleApiError(error49, "Agent delete failed", logger31);
60102
59865
  }
60103
59866
  });
60104
59867
  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) => {
@@ -60127,7 +59890,7 @@ function registerAgentCommand(program2) {
60127
59890
  console.log("");
60128
59891
  }
60129
59892
  } catch (error49) {
60130
- handleApiError(error49, "Position exit failed", logger32);
59893
+ handleApiError(error49, "Position exit failed", logger31);
60131
59894
  }
60132
59895
  });
60133
59896
  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").option("--exit-reasoner", "Enable LLM-powered exit reasoning for this agent").addOption(new Option("--format <format>", "Output format").choices(["text", "json"]).default("text")).action(async (agentId, options) => {
@@ -60212,7 +59975,7 @@ function registerAgentCommand(program2) {
60212
59975
  console.log(source_default.green(` Agent ${agentId} updated`));
60213
59976
  }
60214
59977
  } catch (error49) {
60215
- handleApiError(error49, "Agent update failed", logger32);
59978
+ handleApiError(error49, "Agent update failed", logger31);
60216
59979
  }
60217
59980
  });
60218
59981
  }
@@ -60258,7 +60021,6 @@ function createCli() {
60258
60021
  registerBillingCommand(program2);
60259
60022
  registerSubscribeCommand(program2);
60260
60023
  registerConnectChatgptCommand(program2);
60261
- registerConnectClaudeCommand(program2);
60262
60024
  registerCoachingCommand(program2);
60263
60025
  registerThesisCommand(program2);
60264
60026
  registerStrategyCommand(program2);
package/dist/cli.js CHANGED
@@ -43,7 +43,7 @@ import { registerSuggestionsCommand } from './commands/suggestions-cmd.js';
43
43
  import { registerCronCommand } from './commands/cron-cmd.js';
44
44
  import { registerAgentCommand } from './commands/agent-cmd.js';
45
45
  import { registerConnectChatgptCommand } from './commands/connect-chatgpt.js';
46
- import { registerConnectClaudeCommand } from './commands/connect-claude.js';
46
+ // import { registerConnectClaudeCommand } from './commands/connect-claude.js'; // Hidden — Anthropic ToS prohibits OAuth for third-party use
47
47
  import { readFileSync } from 'node:fs';
48
48
  import { fileURLToPath } from 'node:url';
49
49
  import { dirname, resolve } from 'node:path';
@@ -87,7 +87,7 @@ export function createCli() {
87
87
  registerBillingCommand(program);
88
88
  registerSubscribeCommand(program);
89
89
  registerConnectChatgptCommand(program);
90
- registerConnectClaudeCommand(program);
90
+ // registerConnectClaudeCommand(program); // Hidden — Anthropic ToS prohibits OAuth for third-party use
91
91
  // Learning & coaching
92
92
  registerCoachingCommand(program);
93
93
  registerThesisCommand(program);
@@ -79,7 +79,7 @@ export function registerAgentCommand(program) {
79
79
  .command('create')
80
80
  .description('Create a new agent')
81
81
  .option('--trader-id <traderId>', 'Trader ID')
82
- .option('--strategy-id <strategyId>', 'Strategy ID')
82
+ .option('--strategy-id <strategyId>', 'Strategy ID (optional — auto-creates if omitted)')
83
83
  .option('--name <name>', 'Agent name')
84
84
  .option('--autonomy <level>', 'Autonomy level: OBSERVE_ONLY, SUGGEST, AUTO_WITH_APPROVAL, FULLY_AUTONOMOUS', 'OBSERVE_ONLY')
85
85
  .option('--scan-interval <ms>', 'Scan interval in ms (min 60000)', '300000')
@@ -108,16 +108,11 @@ export function registerAgentCommand(program) {
108
108
  process.exitCode = 1;
109
109
  return;
110
110
  }
111
- if (!options.strategyId) {
112
- console.error(chalk.red('Error: --strategy-id is required.'));
113
- console.log(chalk.dim(' Find yours with: trading-boy strategy list'));
114
- process.exitCode = 1;
115
- return;
116
- }
117
111
  const body = {
118
112
  traderId: options.traderId,
119
- strategyId: options.strategyId,
120
113
  };
114
+ if (options.strategyId)
115
+ body.strategyId = options.strategyId;
121
116
  if (options.name)
122
117
  body.name = options.name;
123
118
  if (options.autonomy)
@@ -200,7 +195,7 @@ export function registerAgentCommand(program) {
200
195
  console.log(` ${chalk.gray('ID:')} ${result.id}`);
201
196
  console.log(` ${chalk.gray('Name:')} ${result.name}`);
202
197
  console.log(` ${chalk.gray('Trader:')} ${result.traderId}`);
203
- console.log(` ${chalk.gray('Strategy:')} ${result.strategyId}`);
198
+ console.log(` ${chalk.gray('Strategy:')} ${result.strategyId}${result.autoStrategyCreated ? chalk.dim(' (auto-created)') : ''}`);
204
199
  console.log(` ${chalk.gray('Autonomy:')} ${formatAutonomy(result.autonomyLevel)}`);
205
200
  console.log(` ${chalk.gray('Interval:')} ${formatInterval(result.scanIntervalMs)}`);
206
201
  console.log(` ${chalk.gray('Next scan:')} ${formatShortDate(result.nextScanAt)}`);
@@ -11,7 +11,6 @@ import chalk from 'chalk';
11
11
  import { isRemoteMode, apiRequest, ApiError } from '../api-client.js';
12
12
  import { runSoulWizardAndUpload } from './soul-wizard.js';
13
13
  import { connectChatgpt } from './connect-chatgpt.js';
14
- import { connectClaude } from './connect-claude.js';
15
14
  // ─── Onboarding Flow ───
16
15
  /**
17
16
  * Run the interactive onboarding wizard.
@@ -135,11 +134,6 @@ export async function runOnboarding() {
135
134
  const llmChoice = await select({
136
135
  message: 'How do you want to power your agent?',
137
136
  choices: [
138
- {
139
- name: 'Use my Claude subscription (no API key needed)',
140
- value: 'claude',
141
- description: 'Sign in with your Anthropic account — uses your existing Claude Pro/Max/Team plan',
142
- },
143
137
  {
144
138
  name: 'Use my ChatGPT subscription (no API key needed)',
145
139
  value: 'chatgpt',
@@ -156,17 +150,7 @@ export async function runOnboarding() {
156
150
  },
157
151
  ],
158
152
  });
159
- if (llmChoice === 'claude') {
160
- try {
161
- await connectClaude();
162
- }
163
- catch (error) {
164
- const msg = error instanceof Error ? error.message : String(error);
165
- console.log(chalk.yellow(` Could not connect Claude: ${msg}`));
166
- console.log(chalk.dim(' Try later: trading-boy connect-claude'));
167
- }
168
- }
169
- else if (llmChoice === 'chatgpt') {
153
+ if (llmChoice === 'chatgpt') {
170
154
  try {
171
155
  await connectChatgpt();
172
156
  }
@@ -213,8 +197,7 @@ export async function runOnboarding() {
213
197
  console.log('');
214
198
  console.log(chalk.yellow(' ⚠ Without an LLM provider, agents can scan prices but cannot'));
215
199
  console.log(chalk.yellow(' analyze markets or make trade decisions.'));
216
- console.log(chalk.dim(' Set it later: trading-boy connect-claude'));
217
- console.log(chalk.dim(' Or ChatGPT: trading-boy connect-chatgpt'));
200
+ console.log(chalk.dim(' Set it later: trading-boy connect-chatgpt'));
218
201
  console.log(chalk.dim(' Or BYOK: trading-boy config set-llm-key <your-api-key>'));
219
202
  }
220
203
  }
@@ -1,6 +1,6 @@
1
1
  import { Option } from 'commander';
2
2
  import chalk from 'chalk';
3
- import { createLogger } from '@trading-boy/core';
3
+ import { createLogger, generateRegimeBehavior } from '@trading-boy/core';
4
4
  import { apiRequest } from '../api-client.js';
5
5
  import { padRight, handleApiError, ensureRemote } from '../utils.js';
6
6
  // ─── Logger ───
@@ -155,12 +155,7 @@ export function registerStrategyCommand(program) {
155
155
  agentId: options.agentId,
156
156
  tokens,
157
157
  setupTypes,
158
- regimeBehavior: {
159
- ACCUMULATION: { enabled: true, maxPositionSize: 0.25, confidenceThreshold: 0.6, preferredSetups: setupTypes },
160
- MARKUP: { enabled: true, maxPositionSize: 0.5, confidenceThreshold: 0.5, preferredSetups: setupTypes },
161
- DISTRIBUTION: { enabled: true, maxPositionSize: 0.15, confidenceThreshold: 0.7, preferredSetups: setupTypes },
162
- MARKDOWN: { enabled: false, maxPositionSize: 0.1, confidenceThreshold: 0.8, preferredSetups: setupTypes },
163
- },
158
+ regimeBehavior: generateRegimeBehavior(setupTypes),
164
159
  riskLimits: {
165
160
  maxDrawdown: 0.2,
166
161
  maxConcurrentPositions: 5,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trading-boy/cli",
3
- "version": "1.11.0",
3
+ "version": "1.12.0",
4
4
  "description": "Trading Boy CLI — crypto context intelligence for traders and AI agents. Query real-time prices, funding rates, whale activity, and DeFi risk for 100+ Solana tokens and 229 Hyperliquid perpetuals.",
5
5
  "homepage": "https://cabal.ventures",
6
6
  "repository": {