traderclaw-cli 1.0.62 → 1.0.65

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.
@@ -1303,7 +1303,12 @@ function resolveLlmModelSelection(provider, requestedModel) {
1303
1303
  return { model: chosen || availableModels[0], source: "provider_default", availableModels, warnings };
1304
1304
  }
1305
1305
 
1306
- warnings.push(`No discoverable model list found for provider '${provider}'. Falling back to '${fallbackModelForProvider(provider)}'.`);
1306
+ warnings.push(
1307
+ `[ALERT] No discoverable model list found for provider '${provider}'. ` +
1308
+ `Auto-selecting hardcoded default '${fallbackModelForProvider(provider)}' — ` +
1309
+ `this model will be billed to your API key. ` +
1310
+ `To use a different model, after finishing setup, use openclaw config and set the model manually.`,
1311
+ );
1307
1312
  return { model: fallbackModelForProvider(provider), source: "fallback_guess", availableModels, warnings };
1308
1313
  }
1309
1314
 
@@ -1503,6 +1508,7 @@ export class InstallerStepEngine {
1503
1508
  xAccessTokenCtoSecret: typeof options.xAccessTokenCtoSecret === "string" ? options.xAccessTokenCtoSecret : "",
1504
1509
  xAccessTokenIntern: typeof options.xAccessTokenIntern === "string" ? options.xAccessTokenIntern : "",
1505
1510
  xAccessTokenInternSecret: typeof options.xAccessTokenInternSecret === "string" ? options.xAccessTokenInternSecret : "",
1511
+ referralCode: typeof options.referralCode === "string" ? options.referralCode.trim() : "",
1506
1512
  };
1507
1513
  this.hooks = {
1508
1514
  onStepEvent: typeof hooks.onStepEvent === "function" ? hooks.onStepEvent : () => {},
@@ -1788,6 +1794,11 @@ export class InstallerStepEngine {
1788
1794
  args.push("--gateway-base-url", gatewayBaseUrl);
1789
1795
  }
1790
1796
 
1797
+ const ref = String(this.options.referralCode || "").trim();
1798
+ if (ref) {
1799
+ args.push("--referral-code", ref);
1800
+ }
1801
+
1791
1802
  const command = [this.modeConfig.cliName, ...args].join(" ");
1792
1803
  const docs =
1793
1804
  "https://docs.traderclaw.ai/docs/installation#troubleshooting-session-expired-auth-errors-or-the-agent-logged-out";
@@ -14,18 +14,19 @@ import { resolvePluginPackageRoot } from "./resolve-plugin-root.mjs";
14
14
 
15
15
  const execFileAsync = promisify(execFile);
16
16
 
17
- /** Fast wizard catalog lookup: prefer one full list, then only probe key providers. */
18
- const OPENCLAW_MODELS_FLAT_TIMEOUT_MS = 7_500;
19
- const OPENCLAW_MODELS_PER_PROVIDER_TIMEOUT_MS = 4_500;
17
+ /**
18
+ * Fast wizard catalog lookup: prefer one full list, then only probe key providers.
19
+ * Timeouts are intentionally short — on a fresh install the CLI can't reach providers
20
+ * (no credentials yet) so we want to fail fast and show the curated fallback list
21
+ * rather than making the user wait 10+ seconds. Target total: ≤ 5 s.
22
+ */
23
+ const OPENCLAW_MODELS_FLAT_TIMEOUT_MS = 3_000;
24
+ const OPENCLAW_MODELS_PER_PROVIDER_TIMEOUT_MS = 2_500;
20
25
  const WIZARD_PRIORITY_PROVIDERS = [
21
26
  "anthropic",
22
27
  "openai",
23
- "openrouter",
24
28
  "google",
25
- "xai",
26
- "deepseek",
27
- "groq",
28
- "mistral",
29
+ "openrouter",
29
30
  ];
30
31
  const WIZARD_PROVIDER_PRIORITY = [
31
32
  ...WIZARD_PRIORITY_PROVIDERS,
@@ -520,15 +521,22 @@ function signChallengeLocally(challengeText, privateKeyBase58) {
520
521
  return b58Encode(new Uint8Array(sig));
521
522
  }
522
523
 
523
- async function doSignup(orchestratorUrl, externalUserId) {
524
+ async function doSignup(orchestratorUrl, externalUserId, referralCode = "") {
524
525
  printInfo(` Signing up as: ${externalUserId}`);
526
+ const body = { externalUserId };
527
+ const ref = String(referralCode || "").trim();
528
+ if (ref) body.referralCode = ref;
525
529
  const res = await httpRequest(`${orchestratorUrl}/api/auth/signup`, {
526
530
  method: "POST",
527
- body: { externalUserId },
531
+ body,
528
532
  });
529
533
 
530
534
  if (!res.ok) {
531
- throw new Error(`Signup failed (HTTP ${res.status}): ${JSON.stringify(res.data)}`);
535
+ const payload = res.data && typeof res.data === "object" ? res.data : {};
536
+ const apiMsg = typeof payload.message === "string" ? payload.message : JSON.stringify(res.data);
537
+ const err = new Error(`Signup failed (HTTP ${res.status}): ${apiMsg}`);
538
+ if (typeof payload.code === "string") err.code = payload.code;
539
+ throw err;
532
540
  }
533
541
 
534
542
  return res.data;
@@ -700,6 +708,8 @@ async function cmdSetup(args) {
700
708
  let noEnsureGatewayPersistent = false;
701
709
  let signupRecoverySecret = undefined;
702
710
  let forwardTelegramRecipientArg = "";
711
+ let referralCodeArg = "";
712
+ let referralInvalidRetries = 0;
703
713
 
704
714
  for (let i = 0; i < args.length; i++) {
705
715
  if ((args[i] === "--api-key" || args[i] === "-k") && args[i + 1]) {
@@ -746,6 +756,9 @@ async function cmdSetup(args) {
746
756
  ) {
747
757
  forwardTelegramRecipientArg = args[++i];
748
758
  }
759
+ if ((args[i] === "--referral-code" || args[i] === "-r") && args[i + 1]) {
760
+ referralCodeArg = args[++i];
761
+ }
749
762
  }
750
763
  const runtimeWalletPrivateKey = getRuntimeWalletPrivateKey(walletPrivateKey);
751
764
 
@@ -763,6 +776,16 @@ async function cmdSetup(args) {
763
776
  }
764
777
  }
765
778
 
779
+ if (doSignupFlow && !referralCodeArg) {
780
+ printInfo(
781
+ "\n Optional: enter a referral code for bonus access time (24h extra when valid). Press Enter to skip.\n",
782
+ );
783
+ printInfo(
784
+ " Benefits: extra trial time now; referring others later earns +8h per user who completes at least one trade with the agent.\n",
785
+ );
786
+ referralCodeArg = await prompt("Referral code (optional)", "");
787
+ }
788
+
766
789
  if (doSignupFlow) {
767
790
  print("\n Signing up for a new account...\n");
768
791
  if (!externalUserId) {
@@ -771,7 +794,7 @@ async function cmdSetup(args) {
771
794
 
772
795
  for (let signupAttempt = 0; ; signupAttempt++) {
773
796
  try {
774
- const signupResult = await doSignup(orchestratorUrl, externalUserId);
797
+ const signupResult = await doSignup(orchestratorUrl, externalUserId, referralCodeArg);
775
798
  apiKey = signupResult.apiKey;
776
799
  if (signupResult.recoverySecret) {
777
800
  signupRecoverySecret = signupResult.recoverySecret;
@@ -783,6 +806,22 @@ async function cmdSetup(args) {
783
806
  break;
784
807
  } catch (err) {
785
808
  const msg = err.message || String(err);
809
+ const apiCode = err.code;
810
+ const referralRejected =
811
+ apiCode === "REFERRAL_CODE_INVALID" ||
812
+ msg.includes("REFERRAL_CODE_INVALID") ||
813
+ msg.includes("Unknown referral code");
814
+ if (referralRejected) {
815
+ referralInvalidRetries += 1;
816
+ if (referralInvalidRetries > 30) {
817
+ printError("Too many invalid referral attempts. Aborting.");
818
+ process.exit(1);
819
+ }
820
+ printWarn(" That referral code was not accepted (unknown or invalid).");
821
+ printInfo(" Leave it blank or enter a different code, then try again.");
822
+ referralCodeArg = await prompt("Referral code (optional, leave empty to skip)", "");
823
+ continue;
824
+ }
786
825
  if (msg.includes("SIGNUP_ALREADY_COMPLETED") || msg.includes("409")) {
787
826
  printWarn(` User "${externalUserId}" is already registered.`);
788
827
  if (signupAttempt >= 2) {
@@ -2176,6 +2215,7 @@ function wizardHtml(defaults) {
2176
2215
  .spinner { width:14px; height:14px; border:2px solid #334a87; border-top-color:#8daeff; border-radius:50%; animation:spin 0.8s linear infinite; flex:0 0 auto; }
2177
2216
  .muted a { color:#9fd3ff; }
2178
2217
  .muted a:hover { color:#c5e5ff; }
2218
+ .info-dot { display:inline-flex; align-items:center; justify-content:center; width:18px; height:18px; border-radius:50%; background:#22315a; color:#9cb0de; font-size:11px; font-weight:700; cursor:help; flex-shrink:0; }
2179
2219
  @keyframes spin { to { transform:rotate(360deg); } }
2180
2220
  </style>
2181
2221
  </head>
@@ -2253,6 +2293,13 @@ function wizardHtml(defaults) {
2253
2293
  <p class="muted">Already have a TraderClaw account? Paste your API key here. New users: leave empty.</p>
2254
2294
  </div>
2255
2295
  </div>
2296
+ <div style="margin-top:12px;">
2297
+ <label style="display:flex;align-items:center;gap:8px;">Referral code (optional)
2298
+ <span class="info-dot" title="Included access: 24 hours for every new account. Add a valid referral code for an extra 24 hours. Refer others: when they complete at least one trade with the agent, you earn +8 hours per active referral. When your access window ends, you will need to stake or keep referring to continue.">i</span>
2299
+ </label>
2300
+ <input id="referralCode" type="text" maxlength="16" autocomplete="off" placeholder="e.g. ABCD1234" />
2301
+ <p class="muted">If you have a friend’s code, enter it here. The setup command below will include it for <code>traderclaw setup</code>. If the server rejects the code, clear this field or fix it and copy the updated command — or run <code>traderclaw setup</code> again and enter a valid code or leave referral blank when prompted.</p>
2302
+ </div>
2256
2303
  <button id="start" disabled>Start Installation</button>
2257
2304
  </div>
2258
2305
  <div class="card" id="statusCard">
@@ -2361,6 +2408,7 @@ function wizardHtml(defaults) {
2361
2408
  let llmLoadStartedAt = 0;
2362
2409
  let announcedTailscaleUrl = "";
2363
2410
  let announcedFunnelAdminUrl = "";
2411
+ let lastReferralFailFingerprint = "";
2364
2412
  let pollTimer = null;
2365
2413
  let pollIntervalMs = 1200;
2366
2414
  let installLocked = false;
@@ -2551,10 +2599,11 @@ function wizardHtml(defaults) {
2551
2599
 
2552
2600
  const payload = {
2553
2601
  llmProvider: llmProviderEl.value.trim(),
2554
- llmModel: llmModelManualEl.checked ? llmModelEl.value.trim() : "",
2602
+ llmModel: llmModelEl.value.trim(),
2555
2603
  llmCredential: llmCredentialEl.value.trim(),
2556
2604
  apiKey: document.getElementById("apiKey").value.trim(),
2557
2605
  telegramToken: document.getElementById("telegramToken").value.trim(),
2606
+ referralCode: document.getElementById("referralCode").value.trim(),
2558
2607
  xConsumerKey: xConsumerKeyEl.value.trim(),
2559
2608
  xConsumerSecret: xConsumerSecretEl.value.trim(),
2560
2609
  xAccessTokenMain: xAccessTokenMainEl.value.trim(),
@@ -2716,9 +2765,30 @@ function wizardHtml(defaults) {
2716
2765
  }
2717
2766
 
2718
2767
  const errors = data.errors || [];
2719
- manualEl.textContent = errors.length > 0
2768
+ let manualText = errors.length > 0
2720
2769
  ? errors.map((e) => "Step " + (e.stepId || "unknown") + ":\\n" + (e.error || "")).join("\\n\\n")
2721
2770
  : "";
2771
+ const combinedErr = errors.map((e) => e.error || "").join("\\n");
2772
+ if (
2773
+ data.status === "failed"
2774
+ && /REFERRAL_CODE_INVALID|Unknown referral code/i.test(combinedErr)
2775
+ ) {
2776
+ manualText +=
2777
+ (manualText ? "\\n\\n" : "") +
2778
+ "Referral code was rejected. Clear or fix the referral field above, then click Start Installation again.";
2779
+ const fp = combinedErr.slice(0, 240);
2780
+ if (fp && fp !== lastReferralFailFingerprint) {
2781
+ lastReferralFailFingerprint = fp;
2782
+ try {
2783
+ window.alert(
2784
+ "Referral code was not accepted. Update or clear the referral field, then click Start Installation again.",
2785
+ );
2786
+ } catch {
2787
+ /* ignore */
2788
+ }
2789
+ }
2790
+ }
2791
+ manualEl.textContent = manualText;
2722
2792
  stepsEl.innerHTML = "";
2723
2793
  steps.forEach((row) => {
2724
2794
  const tr = document.createElement("tr");
@@ -2938,6 +3008,7 @@ async function cmdInstall(args) {
2938
3008
  enableTelegram: true,
2939
3009
  telegramToken: body.telegramToken || defaults.telegramToken,
2940
3010
  autoInstallDeps: true,
3011
+ referralCode: typeof body.referralCode === "string" ? body.referralCode.trim() : "",
2941
3012
  xConsumerKey: body.xConsumerKey ?? defaults.xConsumerKey,
2942
3013
  xConsumerSecret: body.xConsumerSecret ?? defaults.xConsumerSecret,
2943
3014
  xAccessTokenMain: body.xAccessTokenMain ?? defaults.xAccessTokenMain,
@@ -2973,6 +3044,7 @@ async function cmdInstall(args) {
2973
3044
  enableTelegram: true,
2974
3045
  telegramToken: body.telegramToken || defaults.telegramToken,
2975
3046
  autoInstallDeps: true,
3047
+ referralCode: wizardOpts.referralCode,
2976
3048
  xConsumerKey: wizardOpts.xConsumerKey,
2977
3049
  xConsumerSecret: wizardOpts.xConsumerSecret,
2978
3050
  xAccessTokenMain: wizardOpts.xAccessTokenMain,
@@ -3311,6 +3383,7 @@ Setup options:
3311
3383
  --gateway-base-url, -g Gateway public HTTPS URL for orchestrator callbacks
3312
3384
  --gateway-token, -t Gateway bearer token (defaults to API key)
3313
3385
  --telegram-recipient Telegram @username or chat id (aliases: --forward-telegram-chat-id, --telegram-chat-id)
3386
+ --referral-code, -r Optional referral code for new signups (extra trial time when valid)
3314
3387
  --skip-gateway-registration Skip gateway URL registration with orchestrator
3315
3388
  --show-api-key Extra hint after signup (full key is always shown once; confirm with API_KEY_STORED)
3316
3389
  --show-wallet-private-key Reveal full wallet private key in setup output
@@ -3340,7 +3413,7 @@ Examples:
3340
3413
  traderclaw install --wizard
3341
3414
  traderclaw install --wizard --lane quick-local
3342
3415
  traderclaw gateway ensure-persistent
3343
- traderclaw setup --signup --user-id my_agent_001
3416
+ traderclaw setup --signup --user-id my_agent_001 --referral-code ABCD1234
3344
3417
  traderclaw setup --api-key oc_xxx --url https://api.traderclaw.ai
3345
3418
  traderclaw setup --gateway-base-url https://gateway.myhost.ts.net
3346
3419
  traderclaw setup --telegram-recipient @myusername
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "traderclaw-cli",
3
- "version": "1.0.62",
3
+ "version": "1.0.65",
4
4
  "description": "Global TraderClaw CLI (install --wizard, setup, precheck). Installs solana-traderclaw as a dependency for OpenClaw plugin files.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -17,7 +17,7 @@
17
17
  "node": ">=22"
18
18
  },
19
19
  "dependencies": {
20
- "solana-traderclaw": "^1.0.62"
20
+ "solana-traderclaw": "^1.0.65"
21
21
  },
22
22
  "keywords": [
23
23
  "traderclaw",