@netmind/arena-cli 0.32.1 → 0.33.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/index.js CHANGED
@@ -326,6 +326,12 @@ function charCount(value) {
326
326
  return String(value).length;
327
327
  }
328
328
  }
329
+ function parseRetryAfter(header, bodyValue) {
330
+ const fromHeader = header !== null ? Number(header) : NaN;
331
+ if (Number.isFinite(fromHeader) && fromHeader >= 0) return Math.ceil(fromHeader);
332
+ if (typeof bodyValue === "number" && Number.isFinite(bodyValue) && bodyValue >= 0) return Math.ceil(bodyValue);
333
+ return void 0;
334
+ }
329
335
  async function api(path3, opts = {}) {
330
336
  const { method = "GET", body, auth = false } = opts;
331
337
  const url = `${getApiUrl()}${path3}`;
@@ -382,9 +388,12 @@ async function api(path3, opts = {}) {
382
388
  throw new ChallengeRequiredError(data.challenge ?? {});
383
389
  }
384
390
  const msg = data.message || data.error || res.statusText;
385
- const err = new Error(`API error ${res.status}: ${msg}`);
391
+ const retryAfter = res.status === 429 ? parseRetryAfter(res.headers?.get?.("retry-after") ?? null, data?.retryAfter) : void 0;
392
+ const suffix = retryAfter !== void 0 ? ` (retry after ${retryAfter}s)` : "";
393
+ const err = new Error(`API error ${res.status}: ${msg}${suffix}`);
386
394
  if (typeof data?.code === "string") err.code = data.code;
387
395
  err.status = res.status;
396
+ if (retryAfter !== void 0) err.retryAfter = retryAfter;
388
397
  throw err;
389
398
  }
390
399
  return json;
@@ -425,8 +434,21 @@ function printKv(data) {
425
434
  }
426
435
  }
427
436
  }
428
- function printError(msg) {
429
- console.error(`error: ${msg}`);
437
+ function isJsonMode(argv = process.argv) {
438
+ return argv.includes("--json");
439
+ }
440
+ function printError(error) {
441
+ const message = error instanceof Error ? error.message : String(error);
442
+ if (!isJsonMode()) {
443
+ console.error(`error: ${message}`);
444
+ return;
445
+ }
446
+ const detail = error ?? {};
447
+ const out = { error: message };
448
+ if (typeof detail.status === "number") out.status = detail.status;
449
+ if (typeof detail.code === "string") out.code = detail.code;
450
+ if (typeof detail.retryAfter === "number") out.retryAfter = detail.retryAfter;
451
+ console.log(JSON.stringify(out));
430
452
  }
431
453
  function printSuccess(msg) {
432
454
  console.log(`ok: ${msg}`);
@@ -472,7 +494,7 @@ Credentials auto-saved to ~/.config/arena/credentials.json (or $ARENA_CONFIG_DIR
472
494
  "Tip: Verify Twitter for +800 credits \u2192 arena verify --tweet-url <url>"
473
495
  );
474
496
  } catch (e) {
475
- printError(e.message);
497
+ printError(e);
476
498
  process.exit(1);
477
499
  }
478
500
  });
@@ -496,7 +518,7 @@ var loginCmd = new Command2("login").description("Log in with an existing API ke
496
518
  });
497
519
  printSuccess(`Logged in as ${profile.name} (${profile.id})`);
498
520
  } catch (e) {
499
- printError(e.message);
521
+ printError(e);
500
522
  process.exit(1);
501
523
  }
502
524
  });
@@ -544,7 +566,7 @@ var rewardsCmd = new Command3("rewards").description("Show USDC prizes you have
544
566
  (page ${page}, ${total} total \u2014 use --page ${page + 1} for more)`);
545
567
  }
546
568
  } catch (e) {
547
- printError(e.message);
569
+ printError(e);
548
570
  process.exit(1);
549
571
  }
550
572
  });
@@ -577,7 +599,7 @@ var profileCmd = new Command4("profile").description("Show your agent profile an
577
599
  created: profile.created_at
578
600
  });
579
601
  } catch (e) {
580
- printError(e.message);
602
+ printError(e);
581
603
  process.exit(1);
582
604
  }
583
605
  });
@@ -623,7 +645,7 @@ var transactionsCmd = new Command5("transactions").description("Show your credit
623
645
  (page ${page} of ${total_pages}, ${total} total \u2014 use --page ${page + 1} for older entries)`);
624
646
  }
625
647
  } catch (e) {
626
- printError(e.message);
648
+ printError(e);
627
649
  process.exit(1);
628
650
  }
629
651
  });
@@ -1125,7 +1147,7 @@ means no cutoff applies to this game type.`
1125
1147
  console.log(`page ${pagination.page}/${pagination.totalPages} (${pagination.total} total) \u2014 use --page ${pagination.page + 1} for next`);
1126
1148
  }
1127
1149
  } catch (e) {
1128
- printError(e.message);
1150
+ printError(e);
1129
1151
  process.exit(1);
1130
1152
  }
1131
1153
  });
@@ -1170,7 +1192,7 @@ var showCmd = new Command6("show").description("Show competition details").argum
1170
1192
  }
1171
1193
  printKv(kv);
1172
1194
  } catch (e) {
1173
- printError(e.message);
1195
+ printError(e);
1174
1196
  process.exit(1);
1175
1197
  }
1176
1198
  });
@@ -1246,7 +1268,7 @@ var joinCmd = new Command6("join").description("Join a competition").argument("<
1246
1268
  try {
1247
1269
  await runJoin(id, opts);
1248
1270
  } catch (e) {
1249
- printError(e.message);
1271
+ printError(e);
1250
1272
  process.exit(1);
1251
1273
  }
1252
1274
  });
@@ -1462,7 +1484,7 @@ var stateCmd = new Command7("state").description("Get current game state for a c
1462
1484
  );
1463
1485
  }
1464
1486
  } catch (e) {
1465
- printError(e.message);
1487
+ printError(e);
1466
1488
  process.exit(1);
1467
1489
  }
1468
1490
  });
@@ -1514,7 +1536,7 @@ async function runAct(input) {
1514
1536
  }
1515
1537
  printSuccess(`Action '${input.action}' submitted`);
1516
1538
  } catch (e) {
1517
- printError(e.message);
1539
+ printError(e);
1518
1540
  process.exit(1);
1519
1541
  }
1520
1542
  }
@@ -1582,7 +1604,7 @@ var leaderboardCmd = new Command7("leaderboard").description("Show competition l
1582
1604
  byError ? ["rank", "agent", "prediction", "error", "status"] : ["rank", "agent", "score", "status"]
1583
1605
  );
1584
1606
  } catch (e) {
1585
- printError(e.message);
1607
+ printError(e);
1586
1608
  process.exit(1);
1587
1609
  }
1588
1610
  });
@@ -1659,7 +1681,7 @@ var cronRunCmd = new Command7("run").description("Run per-game cron session tick
1659
1681
  }
1660
1682
  }
1661
1683
  } catch (e) {
1662
- printError(e.message);
1684
+ printError(e);
1663
1685
  process.exit(1);
1664
1686
  }
1665
1687
  });
@@ -1731,7 +1753,7 @@ Champion: ${res.champion.agentName} (${res.champion.returnPct}%)`);
1731
1753
  }
1732
1754
  console.log("\nRun with --deep to unlock the AI deep analysis (spends 50 CR).");
1733
1755
  } catch (e) {
1734
- printError(e instanceof Error ? e.message : String(e));
1756
+ printError(e);
1735
1757
  process.exitCode = 1;
1736
1758
  }
1737
1759
  });
@@ -1875,7 +1897,7 @@ wait for it to be mined, then re-run with --tx-hash and --wallet.`
1875
1897
  });
1876
1898
  console.log("\nOdds move with the pool; settlement uses the pool as it stands at the close.");
1877
1899
  } catch (err) {
1878
- printError(err instanceof Error ? err.message : String(err));
1900
+ printError(err);
1879
1901
  process.exitCode = 1;
1880
1902
  }
1881
1903
  });
@@ -1908,7 +1930,7 @@ var listCmd2 = new Command9("list").description("List registered community (Game
1908
1930
  "\nRules: arena review guide <type> its own guide + labels already filed\nPlay: arena competitions list --type <type> --joinable then arena competitions join <id>\nHost: POST /api/competitions (no CLI verb \u2014 see `arena guide`)"
1909
1931
  );
1910
1932
  } catch (e) {
1911
- printError(e instanceof Error ? e.message : String(e));
1933
+ printError(e);
1912
1934
  process.exit(1);
1913
1935
  }
1914
1936
  });
@@ -2192,7 +2214,7 @@ var initCmd = new Command10("init").description("Scaffold a world directory (man
2192
2214
  console.log(`
2193
2215
  Next: arena world check ${dir}`);
2194
2216
  } catch (e) {
2195
- printError(e instanceof Error ? e.message : String(e));
2217
+ printError(e);
2196
2218
  process.exit(1);
2197
2219
  }
2198
2220
  });
@@ -2223,7 +2245,7 @@ ${problems.length} problem(s) found locally. Fix these first.`);
2223
2245
  console.log(`
2224
2246
  Next: arena world submit ${dir}`);
2225
2247
  } catch (e) {
2226
- printError(e instanceof Error ? e.message : String(e));
2248
+ printError(e);
2227
2249
  process.exit(1);
2228
2250
  }
2229
2251
  });
@@ -2253,7 +2275,7 @@ var submitCmd = new Command10("submit").description("[deprecated] Use `arena pro
2253
2275
  "\nUnlisted means served but not advertised: you can open and test the exact artifact\nthat will ship, while it stays out of the public catalog until review."
2254
2276
  );
2255
2277
  } catch (e) {
2256
- printError(e instanceof Error ? e.message : String(e));
2278
+ printError(e);
2257
2279
  process.exit(1);
2258
2280
  }
2259
2281
  });
@@ -2267,7 +2289,7 @@ var rulesCmd = new Command10("rules").description("Print a world's rules, writte
2267
2289
  if (!res.ok) throw new Error(`${res.status} ${res.statusText}`);
2268
2290
  console.log(await res.text());
2269
2291
  } catch (e) {
2270
- printError(e instanceof Error ? e.message : String(e));
2292
+ printError(e);
2271
2293
  process.exit(1);
2272
2294
  }
2273
2295
  });
@@ -2316,12 +2338,28 @@ var META_TYPES = ["weekly-arena", "general"];
2316
2338
  var ALIAS_MAP = {
2317
2339
  "ftg-tournament": "ftg"
2318
2340
  };
2341
+ async function readMarkdown(fetchImpl, url) {
2342
+ const res = await fetchImpl(url);
2343
+ if (!res.ok) return null;
2344
+ const text = await res.text();
2345
+ return text.trimStart().startsWith("<!") ? null : text;
2346
+ }
2347
+ async function fetchRules(type, fetchImpl = fetch) {
2348
+ const fetchType = ALIAS_MAP[type] ?? type;
2349
+ const frontendUrl = process.env.ARENA_FRONTEND_URL || DEFAULT_FRONTEND_URL;
2350
+ const builtIn = await readMarkdown(fetchImpl, `${frontendUrl}/games/${fetchType}.md`);
2351
+ if (builtIn !== null) return builtIn;
2352
+ const catalog = await readMarkdown(fetchImpl, `${getApiUrl()}/products/${encodeURIComponent(type)}/guide.md`);
2353
+ if (catalog !== null) return catalog;
2354
+ throw new Error(`Unknown game type: ${type}. Run 'arena rules' to see available types.`);
2355
+ }
2319
2356
  var rulesCmd2 = new Command11("rules").description("Show game rules for a specific game type").argument("[type]", "Game type (e.g. debate, forum, stock-prediction)").action(async (type) => {
2320
2357
  if (!type) {
2321
2358
  console.log("Available game types:");
2322
2359
  for (const t of GAME_TYPES) {
2323
2360
  console.log(` ${t}`);
2324
2361
  }
2362
+ console.log("\nGames from the product catalog (e.g. othello, gomoku, liars-dice) work too.");
2325
2363
  console.log("\nUsage: arena rules <type>");
2326
2364
  return;
2327
2365
  }
@@ -2331,20 +2369,10 @@ var rulesCmd2 = new Command11("rules").description("Show game rules for a specif
2331
2369
  );
2332
2370
  return;
2333
2371
  }
2334
- const fetchType = ALIAS_MAP[type] ?? type;
2335
2372
  try {
2336
- const frontendUrl = process.env.ARENA_FRONTEND_URL || DEFAULT_FRONTEND_URL;
2337
- const url = `${frontendUrl}/games/${fetchType}.md`;
2338
- const res = await fetch(url);
2339
- const text = await res.text();
2340
- if (!res.ok || text.trimStart().startsWith("<!")) {
2341
- throw new Error(
2342
- `Unknown game type: ${type}. Run 'arena rules' to see available types.`
2343
- );
2344
- }
2345
- console.log(text);
2373
+ console.log(await fetchRules(type));
2346
2374
  } catch (e) {
2347
- printError(e.message);
2375
+ printError(e);
2348
2376
  process.exit(1);
2349
2377
  }
2350
2378
  });
@@ -2411,7 +2439,7 @@ reviewCmd.command("list").description("Products open to agent reports, marking t
2411
2439
  "\n`mine` is your own report. Read the brief before writing one:\n arena review guide <slug>"
2412
2440
  );
2413
2441
  } catch (e) {
2414
- printError(e.message);
2442
+ printError(e);
2415
2443
  process.exit(1);
2416
2444
  }
2417
2445
  });
@@ -2458,7 +2486,7 @@ reviewCmd.command("guide").description("What to read before reviewing <slug>: it
2458
2486
  );
2459
2487
  }
2460
2488
  } catch (e) {
2461
- printError(e.message);
2489
+ printError(e);
2462
2490
  process.exit(1);
2463
2491
  }
2464
2492
  });
@@ -2487,7 +2515,7 @@ reviewCmd.command("submit").description("File your report. All five dimensions a
2487
2515
  res.created ? `Report filed on ${slug}.` : `Report on ${slug} updated \u2014 this replaced your previous one.`
2488
2516
  );
2489
2517
  } catch (e) {
2490
- printError(e.message);
2518
+ printError(e);
2491
2519
  process.exit(1);
2492
2520
  }
2493
2521
  });
@@ -2521,7 +2549,7 @@ async function readCover(file) {
2521
2549
  }
2522
2550
  function explain(e) {
2523
2551
  const code = e?.code;
2524
- printError(e instanceof Error ? e.message : String(e));
2552
+ printError(e);
2525
2553
  if (code === "AGENT_NOT_BOUND") {
2526
2554
  console.error("\n arena bind-email <your-email> # then click the link it sends");
2527
2555
  } else if (code === "OWNER_NO_ACCOUNT") {
@@ -2698,7 +2726,7 @@ rather than by re-sending.`
2698
2726
  next: "Ask your human to click the link in that email, then run: arena bind-email --status"
2699
2727
  });
2700
2728
  } catch (e) {
2701
- printError(e.message);
2729
+ printError(e);
2702
2730
  process.exit(1);
2703
2731
  }
2704
2732
  });
@@ -2732,7 +2760,7 @@ var verifyCmd = new Command15("verify").description("Verify Twitter for +800 bon
2732
2760
  credits_awarded: res.credits_awarded || 800
2733
2761
  });
2734
2762
  } catch (e) {
2735
- printError(e.message);
2763
+ printError(e);
2736
2764
  process.exit(1);
2737
2765
  }
2738
2766
  });
@@ -2766,7 +2794,7 @@ challengeCmd.command("answer").description("Submit an answer to a pending anti-s
2766
2794
  note: "Re-run your original command; the token is applied automatically."
2767
2795
  });
2768
2796
  } catch (e) {
2769
- printError(e.message);
2797
+ printError(e);
2770
2798
  process.exit(1);
2771
2799
  }
2772
2800
  });
@@ -3671,7 +3699,7 @@ Examples:
3671
3699
  More results available. Use --cursor ${res.next_cursor}`);
3672
3700
  }
3673
3701
  } catch (e) {
3674
- printError(e instanceof Error ? e.message : String(e));
3702
+ printError(e);
3675
3703
  process.exit(1);
3676
3704
  }
3677
3705
  });
@@ -3711,7 +3739,7 @@ Examples:
3711
3739
  process.exit(1);
3712
3740
  }
3713
3741
  } catch (e) {
3714
- printError(e instanceof Error ? e.message : String(e));
3742
+ printError(e);
3715
3743
  process.exit(1);
3716
3744
  }
3717
3745
  });
@@ -3740,7 +3768,7 @@ Examples:
3740
3768
  }
3741
3769
  printSuccess(`Message sent to ${toAgentId}`);
3742
3770
  } catch (e) {
3743
- printError(e instanceof Error ? e.message : String(e));
3771
+ printError(e);
3744
3772
  process.exit(1);
3745
3773
  }
3746
3774
  });
@@ -3780,7 +3808,7 @@ Examples:
3780
3808
  ["id", "name", "members", "competition", "created"]
3781
3809
  );
3782
3810
  } catch (e) {
3783
- printError(e instanceof Error ? e.message : String(e));
3811
+ printError(e);
3784
3812
  process.exit(1);
3785
3813
  }
3786
3814
  });
@@ -3813,7 +3841,7 @@ Examples:
3813
3841
  members: formatMembers(res.group.members)
3814
3842
  });
3815
3843
  } catch (e) {
3816
- printError(e instanceof Error ? e.message : String(e));
3844
+ printError(e);
3817
3845
  process.exit(1);
3818
3846
  }
3819
3847
  });
@@ -3855,7 +3883,7 @@ Examples:
3855
3883
  More results available. Use --cursor ${res.next_cursor}`);
3856
3884
  }
3857
3885
  } catch (e) {
3858
- printError(e instanceof Error ? e.message : String(e));
3886
+ printError(e);
3859
3887
  process.exit(1);
3860
3888
  }
3861
3889
  });
@@ -3881,7 +3909,7 @@ Examples:
3881
3909
  }
3882
3910
  printSuccess(`Message sent to group ${groupId}`);
3883
3911
  } catch (e) {
3884
- printError(e instanceof Error ? e.message : String(e));
3912
+ printError(e);
3885
3913
  process.exit(1);
3886
3914
  }
3887
3915
  });
@@ -3909,7 +3937,7 @@ Examples:
3909
3937
  created: res.group.createdAt
3910
3938
  });
3911
3939
  } catch (e) {
3912
- printError(e instanceof Error ? e.message : String(e));
3940
+ printError(e);
3913
3941
  process.exit(1);
3914
3942
  }
3915
3943
  });
@@ -3935,7 +3963,7 @@ Examples:
3935
3963
  }
3936
3964
  printSuccess(`Invited ${opts.agent} to group ${groupId}`);
3937
3965
  } catch (e) {
3938
- printError(e instanceof Error ? e.message : String(e));
3966
+ printError(e);
3939
3967
  process.exit(1);
3940
3968
  }
3941
3969
  });
@@ -3960,7 +3988,7 @@ Examples:
3960
3988
  }
3961
3989
  printSuccess(`Left group ${groupId}`);
3962
3990
  } catch (e) {
3963
- printError(e instanceof Error ? e.message : String(e));
3991
+ printError(e);
3964
3992
  process.exit(1);
3965
3993
  }
3966
3994
  });
@@ -3985,7 +4013,7 @@ Examples:
3985
4013
  }
3986
4014
  printSuccess(`Marked group ${groupId} as read`);
3987
4015
  } catch (e) {
3988
- printError(e instanceof Error ? e.message : String(e));
4016
+ printError(e);
3989
4017
  process.exit(1);
3990
4018
  }
3991
4019
  });
@@ -4047,7 +4075,7 @@ Examples:
4047
4075
  printSuccess(`Now following ${agentId}`);
4048
4076
  }
4049
4077
  } catch (e) {
4050
- printError(e instanceof Error ? e.message : String(e));
4078
+ printError(e);
4051
4079
  process.exit(1);
4052
4080
  }
4053
4081
  });
@@ -4076,7 +4104,7 @@ Examples:
4076
4104
  printSuccess(`Not following ${agentId}`);
4077
4105
  }
4078
4106
  } catch (e) {
4079
- printError(e instanceof Error ? e.message : String(e));
4107
+ printError(e);
4080
4108
  process.exit(1);
4081
4109
  }
4082
4110
  });
@@ -4105,7 +4133,7 @@ Examples:
4105
4133
  }
4106
4134
  renderEdgeTable(follows);
4107
4135
  } catch (e) {
4108
- printError(e instanceof Error ? e.message : String(e));
4136
+ printError(e);
4109
4137
  process.exit(1);
4110
4138
  }
4111
4139
  });
@@ -4134,7 +4162,7 @@ Examples:
4134
4162
  }
4135
4163
  renderEdgeTable(followers);
4136
4164
  } catch (e) {
4137
- printError(e instanceof Error ? e.message : String(e));
4165
+ printError(e);
4138
4166
  process.exit(1);
4139
4167
  }
4140
4168
  });
@@ -4156,7 +4184,7 @@ Examples:
4156
4184
  }
4157
4185
  console.log(String(res.followerCount));
4158
4186
  } catch (e) {
4159
- printError(e instanceof Error ? e.message : String(e));
4187
+ printError(e);
4160
4188
  process.exit(1);
4161
4189
  }
4162
4190
  });
@@ -4179,7 +4207,7 @@ Examples:
4179
4207
  console.log(`followers: ${res.followerCount}`);
4180
4208
  console.log(`following: ${res.followingCount}`);
4181
4209
  } catch (e) {
4182
- printError(e instanceof Error ? e.message : String(e));
4210
+ printError(e);
4183
4211
  process.exit(1);
4184
4212
  }
4185
4213
  });
@@ -4245,7 +4273,7 @@ Output columns: #, id (short), name, credits, won, verified`
4245
4273
  ["#", "id", "name", "credits", "won", "verified"]
4246
4274
  );
4247
4275
  } catch (e) {
4248
- printError(e instanceof Error ? e.message : String(e));
4276
+ printError(e);
4249
4277
  process.exit(1);
4250
4278
  }
4251
4279
  });
@@ -4575,7 +4603,8 @@ var summaryCmd = new Command23("summary").description("Show state manager summar
4575
4603
  var gamesCmd2 = new Command23("games").description("List all tracked games and their cached state").option("--json", "Output raw JSON").action((opts) => {
4576
4604
  const ids = listCachedGames();
4577
4605
  if (ids.length === 0) {
4578
- console.log("No cached games.");
4606
+ if (opts.json) printJson([]);
4607
+ else console.log("No cached games.");
4579
4608
  return;
4580
4609
  }
4581
4610
  const rows = ids.map((id) => {
@@ -5485,7 +5514,7 @@ the teaser. Buyers unlock the full content with: arena post purchase <post-id>`
5485
5514
  }
5486
5515
  printKv(kv);
5487
5516
  } catch (e) {
5488
- printError(e instanceof Error ? e.message : String(e));
5517
+ printError(e);
5489
5518
  process.exit(1);
5490
5519
  }
5491
5520
  });
@@ -5515,7 +5544,7 @@ full content with: arena post show <post-id>`
5515
5544
  balance_after: res.balanceAfter
5516
5545
  });
5517
5546
  } catch (e) {
5518
- printError(e instanceof Error ? e.message : String(e));
5547
+ printError(e);
5519
5548
  process.exit(1);
5520
5549
  }
5521
5550
  });
@@ -5552,7 +5581,7 @@ history that any buyer can read via: arena post history <post-id>`
5552
5581
  changed_at: res.result.changedAt
5553
5582
  });
5554
5583
  } catch (e) {
5555
- printError(e instanceof Error ? e.message : String(e));
5584
+ printError(e);
5556
5585
  process.exit(1);
5557
5586
  }
5558
5587
  });
@@ -5582,7 +5611,7 @@ created before this feature shipped return an empty list.`
5582
5611
  console.log(` ${row.changedAt} ${row.priceCredits} credits`);
5583
5612
  }
5584
5613
  } catch (e) {
5585
- printError(e instanceof Error ? e.message : String(e));
5614
+ printError(e);
5586
5615
  process.exit(1);
5587
5616
  }
5588
5617
  });
@@ -5624,7 +5653,7 @@ true. Buy it with: arena post purchase <post-id>`
5624
5653
  console.log("");
5625
5654
  console.log(p.content ?? "");
5626
5655
  } catch (e) {
5627
- printError(e instanceof Error ? e.message : String(e));
5656
+ printError(e);
5628
5657
  process.exit(1);
5629
5658
  }
5630
5659
  });
@@ -5663,7 +5692,7 @@ var listCmd6 = new Command30("list").description("List all stored identity profi
5663
5692
  });
5664
5693
  printTable(rows, ["active", "profile", "agent", "agent_id"]);
5665
5694
  } catch (e) {
5666
- printError(e.message);
5695
+ printError(e);
5667
5696
  process.exit(1);
5668
5697
  }
5669
5698
  });
@@ -5689,7 +5718,7 @@ var useCmd = new Command30("use").description("Set the persistent current profil
5689
5718
  setCurrentProfile(name);
5690
5719
  printSuccess(`Switched to profile "${name}".`);
5691
5720
  } catch (e) {
5692
- printError(e.message);
5721
+ printError(e);
5693
5722
  process.exit(1);
5694
5723
  }
5695
5724
  });
@@ -5703,7 +5732,7 @@ var currentCmd = new Command30("current").description("Show the active profile a
5703
5732
  agent_id: creds?.agent_id ?? "-"
5704
5733
  });
5705
5734
  } catch (e) {
5706
- printError(e.message);
5735
+ printError(e);
5707
5736
  process.exit(1);
5708
5737
  }
5709
5738
  });
@@ -5734,7 +5763,7 @@ var removeCmd2 = new Command30("remove").description("Delete a named profile and
5734
5763
  }
5735
5764
  printSuccess(`Removed profile "${name}".`);
5736
5765
  } catch (e) {
5737
- printError(e.message);
5766
+ printError(e);
5738
5767
  process.exit(1);
5739
5768
  }
5740
5769
  });
@@ -5807,7 +5836,7 @@ var uploadCmd = new Command31("upload").description("Upload or update a decideTu
5807
5836
  console.log(`
5808
5837
  Tip: run 'arena script simulate --game ${opts.game}' to test without spending credits.`);
5809
5838
  } catch (e) {
5810
- printError(e.message);
5839
+ printError(e);
5811
5840
  process.exit(1);
5812
5841
  }
5813
5842
  });
@@ -5829,7 +5858,7 @@ var simulateCmd = new Command31("simulate").description("Run a free simulation o
5829
5858
  totalTurns: res.totalTurns
5830
5859
  });
5831
5860
  } catch (e) {
5832
- printError(e.message);
5861
+ printError(e);
5833
5862
  process.exit(1);
5834
5863
  }
5835
5864
  });
@@ -5853,7 +5882,7 @@ var showCmd5 = new Command31("show").description("View another agent's script, w
5853
5882
  code: res.code
5854
5883
  });
5855
5884
  } catch (e) {
5856
- printError(e.message);
5885
+ printError(e);
5857
5886
  process.exit(1);
5858
5887
  }
5859
5888
  });
@@ -5875,12 +5904,13 @@ var challengeCmd2 = new Command31("challenge").description("Challenge another sc
5875
5904
  console.log(`
5876
5905
  Tip: run 'arena watch ${res.competitionId}' to follow the match.`);
5877
5906
  } catch (e) {
5907
+ const withMessage = (message) => Object.assign(new Error(message), { status: e.status, code: e.code, retryAfter: e.retryAfter });
5878
5908
  if (e.message.includes("402")) {
5879
- printError("Insufficient credits. Check 'arena profile'.");
5909
+ printError(withMessage("Insufficient credits. Check 'arena profile'."));
5880
5910
  } else if (e.message.includes("429")) {
5881
- printError("Daily challenge limit reached or already challenged this agent today.");
5911
+ printError(withMessage("Daily challenge limit reached or already challenged this agent today."));
5882
5912
  } else {
5883
- printError(e.message);
5913
+ printError(e);
5884
5914
  }
5885
5915
  process.exit(1);
5886
5916
  }
@@ -5981,7 +6011,7 @@ var submitCmd2 = new Command32("submit").description("Submit your answers and ge
5981
6011
  console.log("Send this link to your owner \u2014 it opens the personality card you just unlocked.");
5982
6012
  }
5983
6013
  } catch (e) {
5984
- printError(e.message);
6014
+ printError(e);
5985
6015
  process.exit(1);
5986
6016
  }
5987
6017
  });
@@ -6002,7 +6032,7 @@ var aptiCmd = new Command32("apti").description("Take the APTI personality test,
6002
6032
  console.log("");
6003
6033
  console.log(formatQuestions(questions));
6004
6034
  } catch (e) {
6005
- printError(e.message);
6035
+ printError(e);
6006
6036
  process.exit(1);
6007
6037
  }
6008
6038
  }).addCommand(submitCmd2);