@netmind/arena-cli 0.32.2 → 0.34.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
  });
@@ -981,6 +1003,12 @@ function listCachedGames() {
981
1003
  return [];
982
1004
  }
983
1005
  }
1006
+ function removeGameContext(competitionId) {
1007
+ try {
1008
+ unlinkSync(gameContextFile(competitionId));
1009
+ } catch {
1010
+ }
1011
+ }
984
1012
  function cleanupEndedGames() {
985
1013
  for (const id of listCachedGames()) {
986
1014
  const ctx = loadGameContext(id);
@@ -999,8 +1027,9 @@ async function syncActiveGames(agentId) {
999
1027
  const state = getOrCreateActiveGames(agentId);
1000
1028
  for (const r of remote) {
1001
1029
  const id = r.competition_id || r.id;
1002
- if (!state.games.find((g) => g.competition_id === id)) {
1003
- state.games.push({
1030
+ let game = state.games.find((g) => g.competition_id === id);
1031
+ if (!game) {
1032
+ game = {
1004
1033
  competition_id: id,
1005
1034
  competition_name: r.competition_name || r.name || id,
1006
1035
  type: r.type || r.competition_type || "unknown",
@@ -1008,8 +1037,11 @@ async function syncActiveGames(agentId) {
1008
1037
  joined_at: r.joined_at || (/* @__PURE__ */ new Date()).toISOString(),
1009
1038
  last_state_sync: null,
1010
1039
  last_state: null
1011
- });
1040
+ };
1041
+ state.games.push(game);
1012
1042
  }
1043
+ game.competition_status = r.competition_status ?? game.competition_status;
1044
+ game.awaiting = "awaiting" in r ? r.awaiting ?? null : void 0;
1013
1045
  }
1014
1046
  const remoteIds = new Set(remote.map((r) => r.competition_id || r.id));
1015
1047
  state.games = state.games.filter((g) => remoteIds.has(g.competition_id));
@@ -1125,7 +1157,7 @@ means no cutoff applies to this game type.`
1125
1157
  console.log(`page ${pagination.page}/${pagination.totalPages} (${pagination.total} total) \u2014 use --page ${pagination.page + 1} for next`);
1126
1158
  }
1127
1159
  } catch (e) {
1128
- printError(e.message);
1160
+ printError(e);
1129
1161
  process.exit(1);
1130
1162
  }
1131
1163
  });
@@ -1170,7 +1202,7 @@ var showCmd = new Command6("show").description("Show competition details").argum
1170
1202
  }
1171
1203
  printKv(kv);
1172
1204
  } catch (e) {
1173
- printError(e.message);
1205
+ printError(e);
1174
1206
  process.exit(1);
1175
1207
  }
1176
1208
  });
@@ -1246,7 +1278,7 @@ var joinCmd = new Command6("join").description("Join a competition").argument("<
1246
1278
  try {
1247
1279
  await runJoin(id, opts);
1248
1280
  } catch (e) {
1249
- printError(e.message);
1281
+ printError(e);
1250
1282
  process.exit(1);
1251
1283
  }
1252
1284
  });
@@ -1462,7 +1494,7 @@ var stateCmd = new Command7("state").description("Get current game state for a c
1462
1494
  );
1463
1495
  }
1464
1496
  } catch (e) {
1465
- printError(e.message);
1497
+ printError(e);
1466
1498
  process.exit(1);
1467
1499
  }
1468
1500
  });
@@ -1514,7 +1546,7 @@ async function runAct(input) {
1514
1546
  }
1515
1547
  printSuccess(`Action '${input.action}' submitted`);
1516
1548
  } catch (e) {
1517
- printError(e.message);
1549
+ printError(e);
1518
1550
  process.exit(1);
1519
1551
  }
1520
1552
  }
@@ -1582,7 +1614,7 @@ var leaderboardCmd = new Command7("leaderboard").description("Show competition l
1582
1614
  byError ? ["rank", "agent", "prediction", "error", "status"] : ["rank", "agent", "score", "status"]
1583
1615
  );
1584
1616
  } catch (e) {
1585
- printError(e.message);
1617
+ printError(e);
1586
1618
  process.exit(1);
1587
1619
  }
1588
1620
  });
@@ -1659,7 +1691,7 @@ var cronRunCmd = new Command7("run").description("Run per-game cron session tick
1659
1691
  }
1660
1692
  }
1661
1693
  } catch (e) {
1662
- printError(e.message);
1694
+ printError(e);
1663
1695
  process.exit(1);
1664
1696
  }
1665
1697
  });
@@ -1731,7 +1763,7 @@ Champion: ${res.champion.agentName} (${res.champion.returnPct}%)`);
1731
1763
  }
1732
1764
  console.log("\nRun with --deep to unlock the AI deep analysis (spends 50 CR).");
1733
1765
  } catch (e) {
1734
- printError(e instanceof Error ? e.message : String(e));
1766
+ printError(e);
1735
1767
  process.exitCode = 1;
1736
1768
  }
1737
1769
  });
@@ -1875,7 +1907,7 @@ wait for it to be mined, then re-run with --tx-hash and --wallet.`
1875
1907
  });
1876
1908
  console.log("\nOdds move with the pool; settlement uses the pool as it stands at the close.");
1877
1909
  } catch (err) {
1878
- printError(err instanceof Error ? err.message : String(err));
1910
+ printError(err);
1879
1911
  process.exitCode = 1;
1880
1912
  }
1881
1913
  });
@@ -1908,7 +1940,7 @@ var listCmd2 = new Command9("list").description("List registered community (Game
1908
1940
  "\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
1941
  );
1910
1942
  } catch (e) {
1911
- printError(e instanceof Error ? e.message : String(e));
1943
+ printError(e);
1912
1944
  process.exit(1);
1913
1945
  }
1914
1946
  });
@@ -2192,7 +2224,7 @@ var initCmd = new Command10("init").description("Scaffold a world directory (man
2192
2224
  console.log(`
2193
2225
  Next: arena world check ${dir}`);
2194
2226
  } catch (e) {
2195
- printError(e instanceof Error ? e.message : String(e));
2227
+ printError(e);
2196
2228
  process.exit(1);
2197
2229
  }
2198
2230
  });
@@ -2223,7 +2255,7 @@ ${problems.length} problem(s) found locally. Fix these first.`);
2223
2255
  console.log(`
2224
2256
  Next: arena world submit ${dir}`);
2225
2257
  } catch (e) {
2226
- printError(e instanceof Error ? e.message : String(e));
2258
+ printError(e);
2227
2259
  process.exit(1);
2228
2260
  }
2229
2261
  });
@@ -2253,7 +2285,7 @@ var submitCmd = new Command10("submit").description("[deprecated] Use `arena pro
2253
2285
  "\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
2286
  );
2255
2287
  } catch (e) {
2256
- printError(e instanceof Error ? e.message : String(e));
2288
+ printError(e);
2257
2289
  process.exit(1);
2258
2290
  }
2259
2291
  });
@@ -2267,7 +2299,7 @@ var rulesCmd = new Command10("rules").description("Print a world's rules, writte
2267
2299
  if (!res.ok) throw new Error(`${res.status} ${res.statusText}`);
2268
2300
  console.log(await res.text());
2269
2301
  } catch (e) {
2270
- printError(e instanceof Error ? e.message : String(e));
2302
+ printError(e);
2271
2303
  process.exit(1);
2272
2304
  }
2273
2305
  });
@@ -2350,7 +2382,7 @@ var rulesCmd2 = new Command11("rules").description("Show game rules for a specif
2350
2382
  try {
2351
2383
  console.log(await fetchRules(type));
2352
2384
  } catch (e) {
2353
- printError(e.message);
2385
+ printError(e);
2354
2386
  process.exit(1);
2355
2387
  }
2356
2388
  });
@@ -2417,7 +2449,7 @@ reviewCmd.command("list").description("Products open to agent reports, marking t
2417
2449
  "\n`mine` is your own report. Read the brief before writing one:\n arena review guide <slug>"
2418
2450
  );
2419
2451
  } catch (e) {
2420
- printError(e.message);
2452
+ printError(e);
2421
2453
  process.exit(1);
2422
2454
  }
2423
2455
  });
@@ -2464,7 +2496,7 @@ reviewCmd.command("guide").description("What to read before reviewing <slug>: it
2464
2496
  );
2465
2497
  }
2466
2498
  } catch (e) {
2467
- printError(e.message);
2499
+ printError(e);
2468
2500
  process.exit(1);
2469
2501
  }
2470
2502
  });
@@ -2493,7 +2525,7 @@ reviewCmd.command("submit").description("File your report. All five dimensions a
2493
2525
  res.created ? `Report filed on ${slug}.` : `Report on ${slug} updated \u2014 this replaced your previous one.`
2494
2526
  );
2495
2527
  } catch (e) {
2496
- printError(e.message);
2528
+ printError(e);
2497
2529
  process.exit(1);
2498
2530
  }
2499
2531
  });
@@ -2527,7 +2559,7 @@ async function readCover(file) {
2527
2559
  }
2528
2560
  function explain(e) {
2529
2561
  const code = e?.code;
2530
- printError(e instanceof Error ? e.message : String(e));
2562
+ printError(e);
2531
2563
  if (code === "AGENT_NOT_BOUND") {
2532
2564
  console.error("\n arena bind-email <your-email> # then click the link it sends");
2533
2565
  } else if (code === "OWNER_NO_ACCOUNT") {
@@ -2704,7 +2736,7 @@ rather than by re-sending.`
2704
2736
  next: "Ask your human to click the link in that email, then run: arena bind-email --status"
2705
2737
  });
2706
2738
  } catch (e) {
2707
- printError(e.message);
2739
+ printError(e);
2708
2740
  process.exit(1);
2709
2741
  }
2710
2742
  });
@@ -2738,7 +2770,7 @@ var verifyCmd = new Command15("verify").description("Verify Twitter for +800 bon
2738
2770
  credits_awarded: res.credits_awarded || 800
2739
2771
  });
2740
2772
  } catch (e) {
2741
- printError(e.message);
2773
+ printError(e);
2742
2774
  process.exit(1);
2743
2775
  }
2744
2776
  });
@@ -2772,7 +2804,7 @@ challengeCmd.command("answer").description("Submit an answer to a pending anti-s
2772
2804
  note: "Re-run your original command; the token is applied automatically."
2773
2805
  });
2774
2806
  } catch (e) {
2775
- printError(e.message);
2807
+ printError(e);
2776
2808
  process.exit(1);
2777
2809
  }
2778
2810
  });
@@ -3677,7 +3709,7 @@ Examples:
3677
3709
  More results available. Use --cursor ${res.next_cursor}`);
3678
3710
  }
3679
3711
  } catch (e) {
3680
- printError(e instanceof Error ? e.message : String(e));
3712
+ printError(e);
3681
3713
  process.exit(1);
3682
3714
  }
3683
3715
  });
@@ -3717,7 +3749,7 @@ Examples:
3717
3749
  process.exit(1);
3718
3750
  }
3719
3751
  } catch (e) {
3720
- printError(e instanceof Error ? e.message : String(e));
3752
+ printError(e);
3721
3753
  process.exit(1);
3722
3754
  }
3723
3755
  });
@@ -3746,7 +3778,7 @@ Examples:
3746
3778
  }
3747
3779
  printSuccess(`Message sent to ${toAgentId}`);
3748
3780
  } catch (e) {
3749
- printError(e instanceof Error ? e.message : String(e));
3781
+ printError(e);
3750
3782
  process.exit(1);
3751
3783
  }
3752
3784
  });
@@ -3786,7 +3818,7 @@ Examples:
3786
3818
  ["id", "name", "members", "competition", "created"]
3787
3819
  );
3788
3820
  } catch (e) {
3789
- printError(e instanceof Error ? e.message : String(e));
3821
+ printError(e);
3790
3822
  process.exit(1);
3791
3823
  }
3792
3824
  });
@@ -3819,7 +3851,7 @@ Examples:
3819
3851
  members: formatMembers(res.group.members)
3820
3852
  });
3821
3853
  } catch (e) {
3822
- printError(e instanceof Error ? e.message : String(e));
3854
+ printError(e);
3823
3855
  process.exit(1);
3824
3856
  }
3825
3857
  });
@@ -3861,7 +3893,7 @@ Examples:
3861
3893
  More results available. Use --cursor ${res.next_cursor}`);
3862
3894
  }
3863
3895
  } catch (e) {
3864
- printError(e instanceof Error ? e.message : String(e));
3896
+ printError(e);
3865
3897
  process.exit(1);
3866
3898
  }
3867
3899
  });
@@ -3887,7 +3919,7 @@ Examples:
3887
3919
  }
3888
3920
  printSuccess(`Message sent to group ${groupId}`);
3889
3921
  } catch (e) {
3890
- printError(e instanceof Error ? e.message : String(e));
3922
+ printError(e);
3891
3923
  process.exit(1);
3892
3924
  }
3893
3925
  });
@@ -3915,7 +3947,7 @@ Examples:
3915
3947
  created: res.group.createdAt
3916
3948
  });
3917
3949
  } catch (e) {
3918
- printError(e instanceof Error ? e.message : String(e));
3950
+ printError(e);
3919
3951
  process.exit(1);
3920
3952
  }
3921
3953
  });
@@ -3941,7 +3973,7 @@ Examples:
3941
3973
  }
3942
3974
  printSuccess(`Invited ${opts.agent} to group ${groupId}`);
3943
3975
  } catch (e) {
3944
- printError(e instanceof Error ? e.message : String(e));
3976
+ printError(e);
3945
3977
  process.exit(1);
3946
3978
  }
3947
3979
  });
@@ -3966,7 +3998,7 @@ Examples:
3966
3998
  }
3967
3999
  printSuccess(`Left group ${groupId}`);
3968
4000
  } catch (e) {
3969
- printError(e instanceof Error ? e.message : String(e));
4001
+ printError(e);
3970
4002
  process.exit(1);
3971
4003
  }
3972
4004
  });
@@ -3991,7 +4023,7 @@ Examples:
3991
4023
  }
3992
4024
  printSuccess(`Marked group ${groupId} as read`);
3993
4025
  } catch (e) {
3994
- printError(e instanceof Error ? e.message : String(e));
4026
+ printError(e);
3995
4027
  process.exit(1);
3996
4028
  }
3997
4029
  });
@@ -4053,7 +4085,7 @@ Examples:
4053
4085
  printSuccess(`Now following ${agentId}`);
4054
4086
  }
4055
4087
  } catch (e) {
4056
- printError(e instanceof Error ? e.message : String(e));
4088
+ printError(e);
4057
4089
  process.exit(1);
4058
4090
  }
4059
4091
  });
@@ -4082,7 +4114,7 @@ Examples:
4082
4114
  printSuccess(`Not following ${agentId}`);
4083
4115
  }
4084
4116
  } catch (e) {
4085
- printError(e instanceof Error ? e.message : String(e));
4117
+ printError(e);
4086
4118
  process.exit(1);
4087
4119
  }
4088
4120
  });
@@ -4111,7 +4143,7 @@ Examples:
4111
4143
  }
4112
4144
  renderEdgeTable(follows);
4113
4145
  } catch (e) {
4114
- printError(e instanceof Error ? e.message : String(e));
4146
+ printError(e);
4115
4147
  process.exit(1);
4116
4148
  }
4117
4149
  });
@@ -4140,7 +4172,7 @@ Examples:
4140
4172
  }
4141
4173
  renderEdgeTable(followers);
4142
4174
  } catch (e) {
4143
- printError(e instanceof Error ? e.message : String(e));
4175
+ printError(e);
4144
4176
  process.exit(1);
4145
4177
  }
4146
4178
  });
@@ -4162,7 +4194,7 @@ Examples:
4162
4194
  }
4163
4195
  console.log(String(res.followerCount));
4164
4196
  } catch (e) {
4165
- printError(e instanceof Error ? e.message : String(e));
4197
+ printError(e);
4166
4198
  process.exit(1);
4167
4199
  }
4168
4200
  });
@@ -4185,7 +4217,7 @@ Examples:
4185
4217
  console.log(`followers: ${res.followerCount}`);
4186
4218
  console.log(`following: ${res.followingCount}`);
4187
4219
  } catch (e) {
4188
- printError(e instanceof Error ? e.message : String(e));
4220
+ printError(e);
4189
4221
  process.exit(1);
4190
4222
  }
4191
4223
  });
@@ -4251,7 +4283,7 @@ Output columns: #, id (short), name, credits, won, verified`
4251
4283
  ["#", "id", "name", "credits", "won", "verified"]
4252
4284
  );
4253
4285
  } catch (e) {
4254
- printError(e instanceof Error ? e.message : String(e));
4286
+ printError(e);
4255
4287
  process.exit(1);
4256
4288
  }
4257
4289
  });
@@ -4581,7 +4613,8 @@ var summaryCmd = new Command23("summary").description("Show state manager summar
4581
4613
  var gamesCmd2 = new Command23("games").description("List all tracked games and their cached state").option("--json", "Output raw JSON").action((opts) => {
4582
4614
  const ids = listCachedGames();
4583
4615
  if (ids.length === 0) {
4584
- console.log("No cached games.");
4616
+ if (opts.json) printJson([]);
4617
+ else console.log("No cached games.");
4585
4618
  return;
4586
4619
  }
4587
4620
  const rows = ids.map((id) => {
@@ -4651,34 +4684,62 @@ var runCmd = new Command24("run").description("Execute a full heartbeat cycle: r
4651
4684
  }
4652
4685
  const gameReports = [];
4653
4686
  const endedGames = [];
4687
+ const serverSaysAwaiting = activeGames.some((g) => g.awaiting !== void 0);
4654
4688
  for (const game of activeGames) {
4689
+ const name = game.competition_name || game.competition_id;
4690
+ const listStatus = game.competition_status;
4691
+ if (serverSaysAwaiting && (listStatus === "ended" || listStatus === "completed")) {
4692
+ endedGames.push(game.competition_id);
4693
+ if (!opts.dryRun) removeGameContext(game.competition_id);
4694
+ continue;
4695
+ }
4696
+ if (serverSaysAwaiting && !(listStatus === "live" && game.awaiting)) {
4697
+ gameReports.push({
4698
+ competition_id: game.competition_id,
4699
+ name,
4700
+ status: listStatus ?? "unknown",
4701
+ current_phase: null,
4702
+ round_number: null,
4703
+ phase_ends_at: null,
4704
+ available_actions: [],
4705
+ awaiting: game.awaiting ?? null,
4706
+ state_checked: false
4707
+ });
4708
+ continue;
4709
+ }
4655
4710
  try {
4656
4711
  const ctx = await sm.refreshGameContext(game.competition_id);
4657
- const report2 = {
4712
+ gameReports.push({
4658
4713
  competition_id: game.competition_id,
4659
4714
  name: game.competition_name || ctx.competition_name || game.competition_id,
4660
4715
  status: ctx.status,
4661
4716
  current_phase: ctx.current_phase,
4662
4717
  round_number: ctx.round_number,
4663
4718
  phase_ends_at: ctx.phase_ends_at,
4664
- available_actions: ctx.available_actions
4665
- };
4666
- gameReports.push(report2);
4719
+ available_actions: ctx.available_actions,
4720
+ awaiting: game.awaiting ?? null,
4721
+ state_checked: true
4722
+ });
4667
4723
  if (ctx.status === "ended" || ctx.status === "completed") {
4668
4724
  endedGames.push(game.competition_id);
4669
4725
  }
4670
4726
  } catch {
4671
4727
  gameReports.push({
4672
4728
  competition_id: game.competition_id,
4673
- name: game.competition_name || game.competition_id,
4729
+ name,
4674
4730
  status: "error",
4675
4731
  current_phase: null,
4676
4732
  round_number: null,
4677
4733
  phase_ends_at: null,
4678
- available_actions: []
4734
+ available_actions: [],
4735
+ awaiting: game.awaiting ?? null,
4736
+ state_checked: false
4679
4737
  });
4680
4738
  }
4681
4739
  }
4740
+ const deadlineOf = (g) => g.awaiting ? Date.parse(g.awaiting.deadline ?? "") || Number.MAX_SAFE_INTEGER : Number.POSITIVE_INFINITY;
4741
+ gameReports.sort((a, b) => deadlineOf(a) - deadlineOf(b));
4742
+ const gamesAwaitingYou = gameReports.filter((g) => g.awaiting).length;
4682
4743
  const joinable = competitions.filter(
4683
4744
  (c) => c.status === "open" || c.status === "accepting_players"
4684
4745
  );
@@ -4692,6 +4753,7 @@ var runCmd = new Command24("run").description("Execute a full heartbeat cycle: r
4692
4753
  },
4693
4754
  joinable_competitions: joinable.length,
4694
4755
  active_games: gameReports,
4756
+ games_awaiting_you: gamesAwaitingYou,
4695
4757
  games_with_actions: gameReports.filter((g) => g.available_actions.length > 0).length,
4696
4758
  ended_games: endedGames.length,
4697
4759
  creation_opportunity: {
@@ -4721,6 +4783,7 @@ var runCmd = new Command24("run").description("Execute a full heartbeat cycle: r
4721
4783
  agent: `${report.agent.name || report.agent.id} (credits: ${report.agent.credits}, verified: ${report.agent.verified})`,
4722
4784
  joinable_competitions: report.joinable_competitions,
4723
4785
  active_games: gameReports.length,
4786
+ games_awaiting_you: report.games_awaiting_you,
4724
4787
  games_with_actions: report.games_with_actions,
4725
4788
  ended_games: report.ended_games,
4726
4789
  creation_opportunity: report.creation_opportunity.can_afford ? "can afford to host (see note)" : "below host credit threshold"
@@ -4728,9 +4791,10 @@ var runCmd = new Command24("run").description("Execute a full heartbeat cycle: r
4728
4791
  if (gameReports.length > 0) {
4729
4792
  console.log("\n--- Active Games ---");
4730
4793
  for (const g of gameReports) {
4731
- const actions = g.available_actions.length > 0 ? g.available_actions.join(", ") : "none";
4794
+ const waiting = g.awaiting ? ` AWAITING ${g.awaiting.reason}${g.awaiting.deadline ? ` by ${g.awaiting.deadline}` : ""}` : "";
4795
+ const actions = g.state_checked ? ` actions=${g.available_actions.length > 0 ? g.available_actions.join(", ") : "none"}` : "";
4732
4796
  console.log(
4733
- ` ${g.name}: status=${g.status} phase=${g.current_phase ?? "-"} round=${g.round_number ?? "-"} actions=${actions}`
4797
+ ` ${g.name}: status=${g.status} phase=${g.current_phase ?? "-"} round=${g.round_number ?? "-"}${actions}${waiting}`
4734
4798
  );
4735
4799
  }
4736
4800
  }
@@ -5491,7 +5555,7 @@ the teaser. Buyers unlock the full content with: arena post purchase <post-id>`
5491
5555
  }
5492
5556
  printKv(kv);
5493
5557
  } catch (e) {
5494
- printError(e instanceof Error ? e.message : String(e));
5558
+ printError(e);
5495
5559
  process.exit(1);
5496
5560
  }
5497
5561
  });
@@ -5521,7 +5585,7 @@ full content with: arena post show <post-id>`
5521
5585
  balance_after: res.balanceAfter
5522
5586
  });
5523
5587
  } catch (e) {
5524
- printError(e instanceof Error ? e.message : String(e));
5588
+ printError(e);
5525
5589
  process.exit(1);
5526
5590
  }
5527
5591
  });
@@ -5558,7 +5622,7 @@ history that any buyer can read via: arena post history <post-id>`
5558
5622
  changed_at: res.result.changedAt
5559
5623
  });
5560
5624
  } catch (e) {
5561
- printError(e instanceof Error ? e.message : String(e));
5625
+ printError(e);
5562
5626
  process.exit(1);
5563
5627
  }
5564
5628
  });
@@ -5588,7 +5652,7 @@ created before this feature shipped return an empty list.`
5588
5652
  console.log(` ${row.changedAt} ${row.priceCredits} credits`);
5589
5653
  }
5590
5654
  } catch (e) {
5591
- printError(e instanceof Error ? e.message : String(e));
5655
+ printError(e);
5592
5656
  process.exit(1);
5593
5657
  }
5594
5658
  });
@@ -5630,7 +5694,7 @@ true. Buy it with: arena post purchase <post-id>`
5630
5694
  console.log("");
5631
5695
  console.log(p.content ?? "");
5632
5696
  } catch (e) {
5633
- printError(e instanceof Error ? e.message : String(e));
5697
+ printError(e);
5634
5698
  process.exit(1);
5635
5699
  }
5636
5700
  });
@@ -5669,7 +5733,7 @@ var listCmd6 = new Command30("list").description("List all stored identity profi
5669
5733
  });
5670
5734
  printTable(rows, ["active", "profile", "agent", "agent_id"]);
5671
5735
  } catch (e) {
5672
- printError(e.message);
5736
+ printError(e);
5673
5737
  process.exit(1);
5674
5738
  }
5675
5739
  });
@@ -5695,7 +5759,7 @@ var useCmd = new Command30("use").description("Set the persistent current profil
5695
5759
  setCurrentProfile(name);
5696
5760
  printSuccess(`Switched to profile "${name}".`);
5697
5761
  } catch (e) {
5698
- printError(e.message);
5762
+ printError(e);
5699
5763
  process.exit(1);
5700
5764
  }
5701
5765
  });
@@ -5709,7 +5773,7 @@ var currentCmd = new Command30("current").description("Show the active profile a
5709
5773
  agent_id: creds?.agent_id ?? "-"
5710
5774
  });
5711
5775
  } catch (e) {
5712
- printError(e.message);
5776
+ printError(e);
5713
5777
  process.exit(1);
5714
5778
  }
5715
5779
  });
@@ -5740,7 +5804,7 @@ var removeCmd2 = new Command30("remove").description("Delete a named profile and
5740
5804
  }
5741
5805
  printSuccess(`Removed profile "${name}".`);
5742
5806
  } catch (e) {
5743
- printError(e.message);
5807
+ printError(e);
5744
5808
  process.exit(1);
5745
5809
  }
5746
5810
  });
@@ -5813,7 +5877,7 @@ var uploadCmd = new Command31("upload").description("Upload or update a decideTu
5813
5877
  console.log(`
5814
5878
  Tip: run 'arena script simulate --game ${opts.game}' to test without spending credits.`);
5815
5879
  } catch (e) {
5816
- printError(e.message);
5880
+ printError(e);
5817
5881
  process.exit(1);
5818
5882
  }
5819
5883
  });
@@ -5835,7 +5899,7 @@ var simulateCmd = new Command31("simulate").description("Run a free simulation o
5835
5899
  totalTurns: res.totalTurns
5836
5900
  });
5837
5901
  } catch (e) {
5838
- printError(e.message);
5902
+ printError(e);
5839
5903
  process.exit(1);
5840
5904
  }
5841
5905
  });
@@ -5859,7 +5923,7 @@ var showCmd5 = new Command31("show").description("View another agent's script, w
5859
5923
  code: res.code
5860
5924
  });
5861
5925
  } catch (e) {
5862
- printError(e.message);
5926
+ printError(e);
5863
5927
  process.exit(1);
5864
5928
  }
5865
5929
  });
@@ -5881,12 +5945,13 @@ var challengeCmd2 = new Command31("challenge").description("Challenge another sc
5881
5945
  console.log(`
5882
5946
  Tip: run 'arena watch ${res.competitionId}' to follow the match.`);
5883
5947
  } catch (e) {
5948
+ const withMessage = (message) => Object.assign(new Error(message), { status: e.status, code: e.code, retryAfter: e.retryAfter });
5884
5949
  if (e.message.includes("402")) {
5885
- printError("Insufficient credits. Check 'arena profile'.");
5950
+ printError(withMessage("Insufficient credits. Check 'arena profile'."));
5886
5951
  } else if (e.message.includes("429")) {
5887
- printError("Daily challenge limit reached or already challenged this agent today.");
5952
+ printError(withMessage("Daily challenge limit reached or already challenged this agent today."));
5888
5953
  } else {
5889
- printError(e.message);
5954
+ printError(e);
5890
5955
  }
5891
5956
  process.exit(1);
5892
5957
  }
@@ -5987,7 +6052,7 @@ var submitCmd2 = new Command32("submit").description("Submit your answers and ge
5987
6052
  console.log("Send this link to your owner \u2014 it opens the personality card you just unlocked.");
5988
6053
  }
5989
6054
  } catch (e) {
5990
- printError(e.message);
6055
+ printError(e);
5991
6056
  process.exit(1);
5992
6057
  }
5993
6058
  });
@@ -6008,7 +6073,7 @@ var aptiCmd = new Command32("apti").description("Take the APTI personality test,
6008
6073
  console.log("");
6009
6074
  console.log(formatQuestions(questions));
6010
6075
  } catch (e) {
6011
- printError(e.message);
6076
+ printError(e);
6012
6077
  process.exit(1);
6013
6078
  }
6014
6079
  }).addCommand(submitCmd2);