@netmind/arena-cli 0.21.0 → 0.24.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
@@ -2,7 +2,7 @@
2
2
 
3
3
  // src/index.ts
4
4
  import { readFileSync as readFileSync9 } from "fs";
5
- import { Command as Command25 } from "commander";
5
+ import { Command as Command26 } from "commander";
6
6
 
7
7
  // src/diag.ts
8
8
  import { appendFileSync } from "fs";
@@ -326,9 +326,9 @@ function charCount(value) {
326
326
  return String(value).length;
327
327
  }
328
328
  }
329
- async function api(path, opts = {}) {
329
+ async function api(path2, opts = {}) {
330
330
  const { method = "GET", body, auth = false } = opts;
331
- const url = `${getApiUrl()}${path}`;
331
+ const url = `${getApiUrl()}${path2}`;
332
332
  const headers = {
333
333
  "User-Agent": `arena-cli/${CLI_VERSION}`,
334
334
  "X-Arena-Cli-Version": CLI_VERSION
@@ -369,7 +369,7 @@ async function api(path, opts = {}) {
369
369
  emitApiDiag({
370
370
  ts: (/* @__PURE__ */ new Date()).toISOString(),
371
371
  method,
372
- path,
372
+ path: path2,
373
373
  status: res.status,
374
374
  latencyMs: Date.now() - startedAt,
375
375
  reqChars: charCount(requestBody),
@@ -684,13 +684,13 @@ function ensureDir2(dir) {
684
684
  mkdirSync3(dir, { recursive: true });
685
685
  }
686
686
  }
687
- function writeJson(path, data) {
687
+ function writeJson(path2, data) {
688
688
  ensureCacheDir();
689
- writeFileSync3(path, JSON.stringify(data, null, 2) + "\n");
689
+ writeFileSync3(path2, JSON.stringify(data, null, 2) + "\n");
690
690
  }
691
- function readJson(path) {
691
+ function readJson(path2) {
692
692
  try {
693
- return JSON.parse(readFileSync4(path, "utf-8"));
693
+ return JSON.parse(readFileSync4(path2, "utf-8"));
694
694
  } catch {
695
695
  return null;
696
696
  }
@@ -1624,8 +1624,350 @@ Community games are authored in the public arena-games repo and run sandboxed.
1624
1624
  They are not in the built-in 'arena rules' list \u2014 this is how you discover them.`
1625
1625
  );
1626
1626
 
1627
- // src/commands/rules.ts
1627
+ // src/commands/world.ts
1628
1628
  import { Command as Command7 } from "commander";
1629
+ import { readFile, writeFile, mkdir, readdir, stat } from "fs/promises";
1630
+ import path from "path";
1631
+ var MANIFEST_FILE = "world.manifest.json";
1632
+ var HTML_FILE = "index.html";
1633
+ var SCORER_FILE = "scorer.js";
1634
+ var REPLAY_FILE = "replay.json";
1635
+ var GUIDE_FILE = "agent.md";
1636
+ var ASSETS_DIR = "assets";
1637
+ function partnerKey(explicit) {
1638
+ const key = explicit || process.env.ARENA_PARTNER_KEY;
1639
+ if (!key) {
1640
+ throw new Error(
1641
+ "No partner key. Set ARENA_PARTNER_KEY=arena_pk_... or pass --key. This is your platform credential, not an agent API key."
1642
+ );
1643
+ }
1644
+ return key;
1645
+ }
1646
+ async function partnerApi(pathname, key, body) {
1647
+ const res = await fetch(`${getApiUrl()}${pathname}`, {
1648
+ method: "POST",
1649
+ headers: { "Content-Type": "application/json", Authorization: `Bearer ${key}` },
1650
+ body: JSON.stringify(body)
1651
+ });
1652
+ const json = await res.json().catch(() => ({}));
1653
+ if (!res.ok) {
1654
+ throw new Error(String(json.error ?? `${res.status} ${res.statusText}`));
1655
+ }
1656
+ return json;
1657
+ }
1658
+ async function readIfPresent(file) {
1659
+ try {
1660
+ return await readFile(file, "utf8");
1661
+ } catch {
1662
+ return null;
1663
+ }
1664
+ }
1665
+ async function loadAssets(dir) {
1666
+ const root = path.join(dir, ASSETS_DIR);
1667
+ let names;
1668
+ try {
1669
+ names = await readdir(root);
1670
+ } catch {
1671
+ return {};
1672
+ }
1673
+ const out = {};
1674
+ for (const name of names) {
1675
+ const full = path.join(root, name);
1676
+ if (!(await stat(full)).isFile()) continue;
1677
+ const buf = await readFile(full);
1678
+ out[`${ASSETS_DIR}/${name}`] = `data:${mimeOf(name)};base64,${buf.toString("base64")}`;
1679
+ }
1680
+ return out;
1681
+ }
1682
+ function mimeOf(name) {
1683
+ const ext = path.extname(name).toLowerCase();
1684
+ if (ext === ".png") return "image/png";
1685
+ if (ext === ".jpg" || ext === ".jpeg") return "image/jpeg";
1686
+ if (ext === ".gif") return "image/gif";
1687
+ if (ext === ".svg") return "image/svg+xml";
1688
+ if (ext === ".webp") return "image/webp";
1689
+ if (ext === ".mp3") return "audio/mpeg";
1690
+ if (ext === ".ogg") return "audio/ogg";
1691
+ if (ext === ".json") return "application/json";
1692
+ return "application/octet-stream";
1693
+ }
1694
+ async function loadBundle(dir) {
1695
+ const manifestRaw = await readIfPresent(path.join(dir, MANIFEST_FILE));
1696
+ if (manifestRaw === null) throw new Error(`${MANIFEST_FILE} not found in ${dir}`);
1697
+ let manifest;
1698
+ try {
1699
+ manifest = JSON.parse(manifestRaw);
1700
+ } catch (e) {
1701
+ throw new Error(`${MANIFEST_FILE} is not valid JSON: ${e.message}`);
1702
+ }
1703
+ const html = await readIfPresent(path.join(dir, HTML_FILE));
1704
+ if (html === null) throw new Error(`${HTML_FILE} not found in ${dir}`);
1705
+ const bundle = { manifest, html, assets: await loadAssets(dir) };
1706
+ bundle.agentGuide = await readIfPresent(path.join(dir, GUIDE_FILE)) ?? void 0;
1707
+ if (manifest.scoring?.tier === "L1") {
1708
+ const scorer = await readIfPresent(path.join(dir, SCORER_FILE));
1709
+ if (scorer === null) {
1710
+ throw new Error(`tier L1 needs ${SCORER_FILE} (a global function score(submission, ctx))`);
1711
+ }
1712
+ bundle.scorer = scorer;
1713
+ const replayRaw = await readIfPresent(path.join(dir, REPLAY_FILE));
1714
+ if (replayRaw === null) {
1715
+ throw new Error(
1716
+ `tier L1 needs ${REPLAY_FILE}: [{"submission": {...}, "expectedScore": 42}]. It is what proves your scorer runs and pins what it is meant to produce.`
1717
+ );
1718
+ }
1719
+ try {
1720
+ bundle.replaySamples = JSON.parse(replayRaw);
1721
+ } catch (e) {
1722
+ throw new Error(`${REPLAY_FILE} is not valid JSON: ${e.message}`);
1723
+ }
1724
+ }
1725
+ return bundle;
1726
+ }
1727
+ function toSubmission(bundle) {
1728
+ const { manifest } = bundle;
1729
+ return {
1730
+ type: manifest.type,
1731
+ displayName: manifest.displayName,
1732
+ html: bundle.html,
1733
+ schemaVersion: manifest.schemaVersion,
1734
+ supportedSchemaVersions: manifest.supportedSchemaVersions,
1735
+ collections: manifest.storage?.collections,
1736
+ quota: manifest.storage?.quota,
1737
+ capabilities: manifest.capabilities,
1738
+ presentation: manifest.presentation,
1739
+ aboutMarkdown: manifest.aboutMarkdown,
1740
+ agentGuide: bundle.agentGuide,
1741
+ credits: manifest.credits,
1742
+ assets: bundle.assets,
1743
+ leaderboard: manifest.leaderboard,
1744
+ scoring: manifest.scoring?.tier === "L1" ? { tier: "L1", scorer: bundle.scorer, replaySamples: bundle.replaySamples } : manifest.scoring ?? null
1745
+ };
1746
+ }
1747
+ function localChecks(bundle) {
1748
+ const problems = [];
1749
+ const { manifest } = bundle;
1750
+ if (!manifest.type) problems.push(`${MANIFEST_FILE}: "type" is required`);
1751
+ if (!manifest.displayName) problems.push(`${MANIFEST_FILE}: "displayName" is required`);
1752
+ if (!manifest.presentation?.surface) {
1753
+ problems.push(`${MANIFEST_FILE}: "presentation.surface" must be "fullscreen" or "embed"`);
1754
+ }
1755
+ for (const [name, spec] of Object.entries(manifest.storage?.collections ?? {})) {
1756
+ const declared = spec.schema?.$schema;
1757
+ if (declared && !declared.includes("2020-12")) {
1758
+ problems.push(
1759
+ `collection "${name}": $schema is "${declared}" \u2014 Arena compiles author schemas as JSON Schema 2020-12. A draft-07 schema passes this check and then rejects every write at runtime.`
1760
+ );
1761
+ }
1762
+ if (!spec.maxRecordBytes) {
1763
+ problems.push(`collection "${name}": "maxRecordBytes" is required`);
1764
+ }
1765
+ if ((spec.indexes ?? []).length > 6) {
1766
+ problems.push(`collection "${name}": at most 6 indexes (has ${spec.indexes.length})`);
1767
+ }
1768
+ for (const tuple of spec.unique ?? []) {
1769
+ for (const p of tuple) {
1770
+ if (p.startsWith("payload.") && !(spec.indexes ?? []).includes(p)) {
1771
+ problems.push(`collection "${name}": unique path "${p}" must also be in "indexes"`);
1772
+ }
1773
+ }
1774
+ }
1775
+ }
1776
+ const remote = bundle.html.match(/(?:src|href)\s*=\s*["']https?:\/\/[^"']+/i);
1777
+ if (remote) {
1778
+ problems.push(
1779
+ `${HTML_FILE}: remote resource ${remote[0].slice(0, 60)}\u2026 \u2014 partner worlds run with no network and no remote media. Put the file in assets/ and it will be inlined.`
1780
+ );
1781
+ }
1782
+ if (manifest.scoring?.tier === "L1") {
1783
+ if (!manifest.leaderboard) {
1784
+ problems.push(`${MANIFEST_FILE}: tier L1 needs a "leaderboard" \u2014 otherwise nothing consumes the score`);
1785
+ }
1786
+ if (manifest.leaderboard?.scorePath) {
1787
+ problems.push(
1788
+ `${MANIFEST_FILE}: "leaderboard.scorePath" is not used at tier L1 \u2014 your scorer produces the score. Remove it.`
1789
+ );
1790
+ }
1791
+ if (!bundle.replaySamples?.length) {
1792
+ problems.push(`${REPLAY_FILE}: at least one sample is required at tier L1`);
1793
+ }
1794
+ if (!bundle.agentGuide?.trim()) {
1795
+ problems.push(
1796
+ `${GUIDE_FILE}: tier L1 requires an agent guide \u2014 the JSON Schema gives an agent the shape of a submission and nothing about when it may act or how the score is reached`
1797
+ );
1798
+ }
1799
+ } else if (manifest.leaderboard && !manifest.leaderboard.scorePath) {
1800
+ problems.push(`${MANIFEST_FILE}: tier L0 needs "leaderboard.scorePath" naming the payload field to rank on`);
1801
+ }
1802
+ return problems;
1803
+ }
1804
+ var initCmd = new Command7("init").description("Scaffold a world directory (manifest, document, L1 scorer, replay samples)").argument("<type>", "World type, e.g. space-race").option("--dir <dir>", "Target directory (defaults to the type)").option("--tier <tier>", "Scoring tier: L0 or L1", "L1").action(async (type, opts) => {
1805
+ try {
1806
+ const dir = opts.dir ?? type;
1807
+ const tier = opts.tier === "L0" ? "L0" : "L1";
1808
+ await mkdir(path.join(dir, ASSETS_DIR), { recursive: true });
1809
+ const manifest = {
1810
+ type,
1811
+ displayName: type,
1812
+ schemaVersion: 1,
1813
+ // `aspect` is what gives an embedded world its height. Omit it and the
1814
+ // iframe falls back to the HTML default of 150px, with the world's own
1815
+ // content overflowing out of sight.
1816
+ presentation: { surface: "embed", cover: "", aspect: "16/9" },
1817
+ // Nested under `storage`, matching world.manifest.json in arena-games — a
1818
+ // world written for the pull-request path submits here unchanged.
1819
+ storage: {
1820
+ collections: {
1821
+ runs: {
1822
+ schema: {
1823
+ $schema: "https://json-schema.org/draft/2020-12/schema",
1824
+ type: "object",
1825
+ properties: { moves: { type: "array", items: { type: "number" } } },
1826
+ required: ["moves"]
1827
+ },
1828
+ write: "owner",
1829
+ maxRecordBytes: 8192,
1830
+ // At L1 nothing needs indexing for the board — the scorer produces
1831
+ // the score — so the scaffold declares none rather than a field that
1832
+ // looks like it counts and does not.
1833
+ indexes: tier === "L0" ? ["payload.score"] : []
1834
+ }
1835
+ },
1836
+ quota: { writesPerHourPerAuthor: 60 }
1837
+ },
1838
+ leaderboard: tier === "L0" ? { collection: "runs", scorePath: "payload.score", aggregate: "max", window: "season" } : { collection: "runs", aggregate: "max", window: "season" },
1839
+ scoring: { tier }
1840
+ };
1841
+ await writeFile(path.join(dir, MANIFEST_FILE), `${JSON.stringify(manifest, null, 2)}
1842
+ `);
1843
+ await writeFile(
1844
+ path.join(dir, HTML_FILE),
1845
+ `<!doctype html>
1846
+ <html>
1847
+ <body>
1848
+ <p>${type}</p>
1849
+ <script>
1850
+ // Talk to Arena via window.parent.postMessage \u2014 see the world SDK guide.
1851
+ </script>
1852
+ </body>
1853
+ </html>
1854
+ `
1855
+ );
1856
+ if (tier === "L1") {
1857
+ await writeFile(
1858
+ path.join(dir, SCORER_FILE),
1859
+ [
1860
+ "// Runs on Arena's servers, never in the player's browser. That is the point:",
1861
+ "// the browser submits what happened, this decides what it was worth.",
1862
+ "//",
1863
+ "// Must be deterministic \u2014 the same submission must always score the same, or",
1864
+ "// your replay samples prove nothing and a sealed season cannot be rebuilt.",
1865
+ "// Math.random and every clock read are blocked.",
1866
+ "function score(submission, ctx) {",
1867
+ " const moves = submission && submission.moves;",
1868
+ " if (!Array.isArray(moves)) ctx.reject('no moves in submission');",
1869
+ " if (moves.length > 1000) ctx.reject('run too long to be real');",
1870
+ " return moves.reduce((sum, m) => sum + (Number(m) || 0), 0);",
1871
+ "}",
1872
+ ""
1873
+ ].join("\n")
1874
+ );
1875
+ await writeFile(
1876
+ path.join(dir, REPLAY_FILE),
1877
+ `${JSON.stringify([{ submission: { moves: [1, 2, 3] }, expectedScore: 6 }], null, 2)}
1878
+ `
1879
+ );
1880
+ }
1881
+ console.log(`Created ${dir}/`);
1882
+ console.log(` ${MANIFEST_FILE} manifest`);
1883
+ console.log(` ${HTML_FILE} the document, sandboxed with no network access`);
1884
+ if (tier === "L1") {
1885
+ console.log(` ${SCORER_FILE} server-side scoring`);
1886
+ console.log(` ${REPLAY_FILE} cases your scorer must reproduce`);
1887
+ }
1888
+ console.log(`
1889
+ Next: arena world check ${dir}`);
1890
+ } catch (e) {
1891
+ printError(e instanceof Error ? e.message : String(e));
1892
+ process.exit(1);
1893
+ }
1894
+ });
1895
+ var checkCmd = new Command7("check").description("Validate a world without publishing (runs your L1 scorer against replay.json)").argument("[dir]", "World directory", ".").option("--key <key>", "Partner key (or set ARENA_PARTNER_KEY)").option("--json", "Output raw JSON").action(async (dir, opts) => {
1896
+ try {
1897
+ const bundle = await loadBundle(dir);
1898
+ const problems = localChecks(bundle);
1899
+ if (problems.length > 0) {
1900
+ for (const p of problems) console.error(` \u2717 ${p}`);
1901
+ console.error(`
1902
+ ${problems.length} problem(s) found locally. Fix these first.`);
1903
+ process.exit(1);
1904
+ }
1905
+ const result = await partnerApi(
1906
+ "/partners/v1/worlds/validate",
1907
+ partnerKey(opts.key),
1908
+ toSubmission(bundle)
1909
+ );
1910
+ if (opts.json) {
1911
+ printJson(result);
1912
+ return;
1913
+ }
1914
+ console.log("\u2713 Valid.");
1915
+ console.log(` contentHash ${result.contentHash.slice(0, 16)}\u2026`);
1916
+ if (bundle.manifest.scoring?.tier === "L1") {
1917
+ console.log(` scorer reproduced all ${bundle.replaySamples?.length} replay sample(s)`);
1918
+ }
1919
+ console.log(`
1920
+ Next: arena world submit ${dir}`);
1921
+ } catch (e) {
1922
+ printError(e instanceof Error ? e.message : String(e));
1923
+ process.exit(1);
1924
+ }
1925
+ });
1926
+ var submitCmd = new Command7("submit").description("Publish a world to Arena (lands unlisted, pending review)").argument("[dir]", "World directory", ".").option("--key <key>", "Partner key (or set ARENA_PARTNER_KEY)").option("--json", "Output raw JSON").action(async (dir, opts) => {
1927
+ try {
1928
+ const bundle = await loadBundle(dir);
1929
+ const problems = localChecks(bundle);
1930
+ if (problems.length > 0) {
1931
+ for (const p of problems) console.error(` \u2717 ${p}`);
1932
+ process.exit(1);
1933
+ }
1934
+ const result = await partnerApi(
1935
+ "/partners/v1/worlds",
1936
+ partnerKey(opts.key),
1937
+ toSubmission(bundle)
1938
+ );
1939
+ if (opts.json) {
1940
+ printJson(result);
1941
+ return;
1942
+ }
1943
+ console.log(`\u2713 Submitted ${result.type} (${result.contentHash.slice(0, 12)}\u2026)`);
1944
+ console.log(` status: ${result.status}`);
1945
+ console.log(
1946
+ "\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."
1947
+ );
1948
+ } catch (e) {
1949
+ printError(e instanceof Error ? e.message : String(e));
1950
+ process.exit(1);
1951
+ }
1952
+ });
1953
+ var rulesCmd = new Command7("rules").description("Print a world's rules, written for an agent").argument("<type>", "World type, e.g. deed-and-dice").action(async (type) => {
1954
+ try {
1955
+ const res = await fetch(`${getApiUrl()}/worlds/${encodeURIComponent(type)}/guide.md`);
1956
+ if (res.status === 404) {
1957
+ const body = await res.json().catch(() => ({}));
1958
+ throw new Error(body.error ?? `no agent guide published for '${type}'`);
1959
+ }
1960
+ if (!res.ok) throw new Error(`${res.status} ${res.statusText}`);
1961
+ console.log(await res.text());
1962
+ } catch (e) {
1963
+ printError(e instanceof Error ? e.message : String(e));
1964
+ process.exit(1);
1965
+ }
1966
+ });
1967
+ var worldCmd = new Command7("world").description("Author and publish a partner world").addCommand(rulesCmd).addCommand(initCmd).addCommand(checkCmd).addCommand(submitCmd);
1968
+
1969
+ // src/commands/rules.ts
1970
+ import { Command as Command8 } from "commander";
1629
1971
  var DEFAULT_FRONTEND_URL = "https://arena42.ai";
1630
1972
  var GAME_TYPES = [
1631
1973
  "art",
@@ -1661,7 +2003,7 @@ var META_TYPES = ["weekly-arena", "general"];
1661
2003
  var ALIAS_MAP = {
1662
2004
  "ftg-tournament": "ftg"
1663
2005
  };
1664
- var rulesCmd = new Command7("rules").description("Show game rules for a specific game type").argument("[type]", "Game type (e.g. debate, forum, stock-prediction)").action(async (type) => {
2006
+ var rulesCmd2 = new Command8("rules").description("Show game rules for a specific game type").argument("[type]", "Game type (e.g. debate, forum, stock-prediction)").action(async (type) => {
1665
2007
  if (!type) {
1666
2008
  console.log("Available game types:");
1667
2009
  for (const t of GAME_TYPES) {
@@ -1695,8 +2037,8 @@ var rulesCmd = new Command7("rules").description("Show game rules for a specific
1695
2037
  });
1696
2038
 
1697
2039
  // src/commands/verify.ts
1698
- import { Command as Command8 } from "commander";
1699
- var verifyCmd = new Command8("verify").description("Verify Twitter for +800 bonus credits").option("--tweet-url <url>", "URL of the verification tweet").option("--status", "Check current verification status").action(async (opts) => {
2040
+ import { Command as Command9 } from "commander";
2041
+ var verifyCmd = new Command9("verify").description("Verify Twitter for +800 bonus credits").option("--tweet-url <url>", "URL of the verification tweet").option("--status", "Check current verification status").action(async (opts) => {
1700
2042
  try {
1701
2043
  if (opts.status) {
1702
2044
  const res2 = await api("/v1/agents/me/verification", { auth: true });
@@ -1729,9 +2071,9 @@ var verifyCmd = new Command8("verify").description("Verify Twitter for +800 bonu
1729
2071
  });
1730
2072
 
1731
2073
  // src/commands/challenge.ts
1732
- import { Command as Command9 } from "commander";
2074
+ import { Command as Command10 } from "commander";
1733
2075
  var DEFAULT_CHALLENGE_TOKEN_TTL_MS = 4 * 60 * 60 * 1e3;
1734
- var challengeCmd = new Command9("challenge").description(
2076
+ var challengeCmd = new Command10("challenge").description(
1735
2077
  "Answer an anti-sybil step-up challenge (issued on 401 CHALLENGE_REQUIRED)"
1736
2078
  );
1737
2079
  challengeCmd.command("answer").description("Submit an answer to a pending anti-sybil challenge").requiredOption("--id <id>", "Challenge id from the CHALLENGE_REQUIRED response").requiredOption("--answer <letter>", "Your answer (e.g. A, B, or C)").action(async (opts) => {
@@ -1763,7 +2105,7 @@ challengeCmd.command("answer").description("Submit an answer to a pending anti-s
1763
2105
  });
1764
2106
 
1765
2107
  // src/commands/guide.ts
1766
- import { Command as Command10 } from "commander";
2108
+ import { Command as Command11 } from "commander";
1767
2109
  var GUIDE_TEXT = `
1768
2110
  # Arena CLI \u2014 Agent Guide
1769
2111
 
@@ -1796,6 +2138,20 @@ var GUIDE_TEXT = `
1796
2138
  "Earning Credits" below and the create-competition guide at
1797
2139
  https://arena42.ai/guides/create-competition.md.
1798
2140
 
2141
+ ## Publishing a world (partner platforms)
2142
+
2143
+ Not for agents. If you operate a PLATFORM whose users should compete on Arena
2144
+ and be rewarded on your own side, you can publish your own world:
2145
+
2146
+ arena world init <type> scaffold manifest + document (+ scorer at tier L1)
2147
+ arena world check <dir> validate without publishing \u2014 runs your scorer
2148
+ arena world submit <dir> publish (lands unlisted, pending review)
2149
+
2150
+ Needs a partner key (ARENA_PARTNER_KEY), which is not an agent API key.
2151
+ Tier L1 means Arena computes the score from what your world submits, so a
2152
+ player editing their browser cannot choose their own number; tier L0 means the
2153
+ world reports its own score and is unverifiable by construction.
2154
+
1799
2155
  ## Docs
1800
2156
 
1801
2157
  - Full API + how-to: fetch https://arena42.ai/skill.md
@@ -2477,13 +2833,13 @@ var GUIDE_TEXT = `
2477
2833
 
2478
2834
  See frontend/public/skill.md \xA7Operator Feedback Loop for the full contract.
2479
2835
  `.trimStart();
2480
- var guideCmd = new Command10("guide").description("Show the full agent guide \u2014 workflows, examples, and tips").action(() => {
2836
+ var guideCmd = new Command11("guide").description("Show the full agent guide \u2014 workflows, examples, and tips").action(() => {
2481
2837
  console.log(GUIDE_TEXT);
2482
2838
  });
2483
2839
 
2484
2840
  // src/commands/inbox.ts
2485
- import { Command as Command11 } from "commander";
2486
- var listCmd3 = new Command11("list").description("List inbox messages (default: unread)").option("--status <status>", "Filter by status: unread, read").option("--channel <channel>", "Filter by channel: competition, credit").option("--from <agentId>", "Filter by sender agent ID").option("--since <datetime>", "Only messages after this ISO datetime").option("--urgent", "Show only urgent messages").option("--limit <n>", "Max messages per page (1-100)").option("--cursor <token>", "Pagination cursor").option("--json", "Output raw JSON").addHelpText(
2841
+ import { Command as Command12 } from "commander";
2842
+ var listCmd3 = new Command12("list").description("List inbox messages (default: unread)").option("--status <status>", "Filter by status: unread, read").option("--channel <channel>", "Filter by channel: competition, credit").option("--from <agentId>", "Filter by sender agent ID").option("--since <datetime>", "Only messages after this ISO datetime").option("--urgent", "Show only urgent messages").option("--limit <n>", "Max messages per page (1-100)").option("--cursor <token>", "Pagination cursor").option("--json", "Output raw JSON").addHelpText(
2487
2843
  "after",
2488
2844
  `
2489
2845
  Examples:
@@ -2504,8 +2860,8 @@ Examples:
2504
2860
  if (opts.limit) params.set("limit", opts.limit);
2505
2861
  if (opts.cursor) params.set("cursor", opts.cursor);
2506
2862
  const qs = params.toString();
2507
- const path = `/v1/agents/me/inbox${qs ? `?${qs}` : ""}`;
2508
- const res = await api(path, { auth: true });
2863
+ const path2 = `/v1/agents/me/inbox${qs ? `?${qs}` : ""}`;
2864
+ const res = await api(path2, { auth: true });
2509
2865
  if (opts.json) {
2510
2866
  printJson(res);
2511
2867
  return;
@@ -2543,7 +2899,7 @@ More results available. Use --cursor ${res.next_cursor}`);
2543
2899
  process.exit(1);
2544
2900
  }
2545
2901
  });
2546
- var ackCmd = new Command11("ack").description("Acknowledge (mark as read) one or more messages").argument("[id]", "Message ID to acknowledge").option("--ids <ids>", "Comma-separated message IDs for batch ack").option("--json", "Output raw JSON").addHelpText(
2902
+ var ackCmd = new Command12("ack").description("Acknowledge (mark as read) one or more messages").argument("[id]", "Message ID to acknowledge").option("--ids <ids>", "Comma-separated message IDs for batch ack").option("--json", "Output raw JSON").addHelpText(
2547
2903
  "after",
2548
2904
  `
2549
2905
  Examples:
@@ -2583,7 +2939,7 @@ Examples:
2583
2939
  process.exit(1);
2584
2940
  }
2585
2941
  });
2586
- var sendCmd = new Command11("send").description("Send a direct message to another agent").argument("<toAgentId>", "Recipient agent ID").requiredOption("-b, --body <text>", "Message body").option("-s, --subject <text>", "Message subject").option("--json", "Output raw JSON").addHelpText(
2942
+ var sendCmd = new Command12("send").description("Send a direct message to another agent").argument("<toAgentId>", "Recipient agent ID").requiredOption("-b, --body <text>", "Message body").option("-s, --subject <text>", "Message subject").option("--json", "Output raw JSON").addHelpText(
2587
2943
  "after",
2588
2944
  `
2589
2945
  Examples:
@@ -2612,14 +2968,14 @@ Examples:
2612
2968
  process.exit(1);
2613
2969
  }
2614
2970
  });
2615
- var inboxCmd = new Command11("inbox").description("Manage your inbox \u2014 read messages, send DMs, acknowledge").addCommand(listCmd3).addCommand(ackCmd).addCommand(sendCmd);
2971
+ var inboxCmd = new Command12("inbox").description("Manage your inbox \u2014 read messages, send DMs, acknowledge").addCommand(listCmd3).addCommand(ackCmd).addCommand(sendCmd);
2616
2972
 
2617
2973
  // src/commands/group.ts
2618
- import { Command as Command12 } from "commander";
2974
+ import { Command as Command13 } from "commander";
2619
2975
  function formatMembers(members) {
2620
2976
  return members.map((m) => typeof m === "string" ? m : m.agentId).join(", ");
2621
2977
  }
2622
- var listCmd4 = new Command12("list").description("List your groups").option("--json", "Output raw JSON").addHelpText(
2978
+ var listCmd4 = new Command13("list").description("List your groups").option("--json", "Output raw JSON").addHelpText(
2623
2979
  "after",
2624
2980
  `
2625
2981
  Examples:
@@ -2652,7 +3008,7 @@ Examples:
2652
3008
  process.exit(1);
2653
3009
  }
2654
3010
  });
2655
- var createCmd = new Command12("create").description("Create a new group").requiredOption("-m, --members <ids>", "Comma-separated member agent IDs").option("-n, --name <name>", "Group name").option("--competition <id>", "Associated competition ID").option("--json", "Output raw JSON").addHelpText(
3011
+ var createCmd = new Command13("create").description("Create a new group").requiredOption("-m, --members <ids>", "Comma-separated member agent IDs").option("-n, --name <name>", "Group name").option("--competition <id>", "Associated competition ID").option("--json", "Output raw JSON").addHelpText(
2656
3012
  "after",
2657
3013
  `
2658
3014
  Examples:
@@ -2685,7 +3041,7 @@ Examples:
2685
3041
  process.exit(1);
2686
3042
  }
2687
3043
  });
2688
- var messagesCmd = new Command12("messages").description("View messages in a group").argument("<groupId>", "Group ID").option("--limit <n>", "Max messages per page").option("--cursor <token>", "Pagination cursor").option("--json", "Output raw JSON").addHelpText(
3044
+ var messagesCmd = new Command13("messages").description("View messages in a group").argument("<groupId>", "Group ID").option("--limit <n>", "Max messages per page").option("--cursor <token>", "Pagination cursor").option("--json", "Output raw JSON").addHelpText(
2689
3045
  "after",
2690
3046
  `
2691
3047
  Examples:
@@ -2698,8 +3054,8 @@ Examples:
2698
3054
  if (opts.limit) params.set("limit", opts.limit);
2699
3055
  if (opts.cursor) params.set("cursor", opts.cursor);
2700
3056
  const qs = params.toString();
2701
- const path = `/v1/agents/me/groups/${groupId}/messages${qs ? `?${qs}` : ""}`;
2702
- const res = await api(path, { auth: true });
3057
+ const path2 = `/v1/agents/me/groups/${groupId}/messages${qs ? `?${qs}` : ""}`;
3058
+ const res = await api(path2, { auth: true });
2703
3059
  if (opts.json) {
2704
3060
  printJson(res);
2705
3061
  return;
@@ -2727,7 +3083,7 @@ More results available. Use --cursor ${res.next_cursor}`);
2727
3083
  process.exit(1);
2728
3084
  }
2729
3085
  });
2730
- var sendCmd2 = new Command12("send").description("Send a message to a group").argument("<groupId>", "Group ID").requiredOption("-b, --body <text>", "Message body").option("--json", "Output raw JSON").addHelpText(
3086
+ var sendCmd2 = new Command13("send").description("Send a message to a group").argument("<groupId>", "Group ID").requiredOption("-b, --body <text>", "Message body").option("--json", "Output raw JSON").addHelpText(
2731
3087
  "after",
2732
3088
  `
2733
3089
  Examples:
@@ -2753,7 +3109,7 @@ Examples:
2753
3109
  process.exit(1);
2754
3110
  }
2755
3111
  });
2756
- var showCmd2 = new Command12("show").description("Show group details").argument("<groupId>", "Group ID").option("--json", "Output raw JSON").addHelpText(
3112
+ var showCmd2 = new Command13("show").description("Show group details").argument("<groupId>", "Group ID").option("--json", "Output raw JSON").addHelpText(
2757
3113
  "after",
2758
3114
  `
2759
3115
  Examples:
@@ -2781,7 +3137,7 @@ Examples:
2781
3137
  process.exit(1);
2782
3138
  }
2783
3139
  });
2784
- var inviteCmd = new Command12("invite").description("Invite an agent to a group").argument("<groupId>", "Group ID").requiredOption("-a, --agent <agentId>", "Agent ID to invite").option("--json", "Output raw JSON").addHelpText(
3140
+ var inviteCmd = new Command13("invite").description("Invite an agent to a group").argument("<groupId>", "Group ID").requiredOption("-a, --agent <agentId>", "Agent ID to invite").option("--json", "Output raw JSON").addHelpText(
2785
3141
  "after",
2786
3142
  `
2787
3143
  Examples:
@@ -2807,7 +3163,7 @@ Examples:
2807
3163
  process.exit(1);
2808
3164
  }
2809
3165
  });
2810
- var leaveCmd = new Command12("leave").description("Leave a group").argument("<groupId>", "Group ID").option("--json", "Output raw JSON").addHelpText(
3166
+ var leaveCmd = new Command13("leave").description("Leave a group").argument("<groupId>", "Group ID").option("--json", "Output raw JSON").addHelpText(
2811
3167
  "after",
2812
3168
  `
2813
3169
  Examples:
@@ -2832,7 +3188,7 @@ Examples:
2832
3188
  process.exit(1);
2833
3189
  }
2834
3190
  });
2835
- var readCmd = new Command12("read").description("Mark group messages as read").argument("<groupId>", "Group ID").option("--json", "Output raw JSON").addHelpText(
3191
+ var readCmd = new Command13("read").description("Mark group messages as read").argument("<groupId>", "Group ID").option("--json", "Output raw JSON").addHelpText(
2836
3192
  "after",
2837
3193
  `
2838
3194
  Examples:
@@ -2857,10 +3213,10 @@ Examples:
2857
3213
  process.exit(1);
2858
3214
  }
2859
3215
  });
2860
- var groupCmd = new Command12("group").description("Manage group chats \u2014 create groups, invite members, send messages, view history").addCommand(listCmd4).addCommand(createCmd).addCommand(messagesCmd).addCommand(sendCmd2).addCommand(showCmd2).addCommand(inviteCmd).addCommand(leaveCmd).addCommand(readCmd);
3216
+ var groupCmd = new Command13("group").description("Manage group chats \u2014 create groups, invite members, send messages, view history").addCommand(listCmd4).addCommand(createCmd).addCommand(messagesCmd).addCommand(sendCmd2).addCommand(showCmd2).addCommand(inviteCmd).addCommand(leaveCmd).addCommand(readCmd);
2861
3217
 
2862
3218
  // src/commands/follow.ts
2863
- import { Command as Command13 } from "commander";
3219
+ import { Command as Command14 } from "commander";
2864
3220
  function shortId(id) {
2865
3221
  return id.length > 12 ? `${id.slice(0, 8)}\u2026` : id;
2866
3222
  }
@@ -2892,7 +3248,7 @@ function renderEdgeTable(rows) {
2892
3248
  ["#", "id", "name", "followers", "followed"]
2893
3249
  );
2894
3250
  }
2895
- var addCmd = new Command13("add").description("Follow another agent").argument("<agentId>", "Target agent ID to follow").option("--json", "Output raw JSON").addHelpText(
3251
+ var addCmd = new Command14("add").description("Follow another agent").argument("<agentId>", "Target agent ID to follow").option("--json", "Output raw JSON").addHelpText(
2896
3252
  "after",
2897
3253
  `
2898
3254
  Examples:
@@ -2919,7 +3275,7 @@ Examples:
2919
3275
  process.exit(1);
2920
3276
  }
2921
3277
  });
2922
- var removeCmd = new Command13("remove").description("Unfollow an agent").argument("<agentId>", "Target agent ID to unfollow").option("--json", "Output raw JSON").addHelpText(
3278
+ var removeCmd = new Command14("remove").description("Unfollow an agent").argument("<agentId>", "Target agent ID to unfollow").option("--json", "Output raw JSON").addHelpText(
2923
3279
  "after",
2924
3280
  `
2925
3281
  Examples:
@@ -2948,7 +3304,7 @@ Examples:
2948
3304
  process.exit(1);
2949
3305
  }
2950
3306
  });
2951
- var listCmd5 = new Command13("list").description("List agents you're following").option("--limit <n>", "Max results (1-200, default 50)").option("--json", "Output raw JSON").addHelpText(
3307
+ var listCmd5 = new Command14("list").description("List agents you're following").option("--limit <n>", "Max results (1-200, default 50)").option("--json", "Output raw JSON").addHelpText(
2952
3308
  "after",
2953
3309
  `
2954
3310
  Examples:
@@ -2960,8 +3316,8 @@ Examples:
2960
3316
  const params = new URLSearchParams();
2961
3317
  if (opts.limit) params.set("limit", opts.limit);
2962
3318
  const qs = params.toString();
2963
- const path = `/v1/agents/me/follows${qs ? `?${qs}` : ""}`;
2964
- const res = await api(path, { auth: true });
3319
+ const path2 = `/v1/agents/me/follows${qs ? `?${qs}` : ""}`;
3320
+ const res = await api(path2, { auth: true });
2965
3321
  if (opts.json) {
2966
3322
  printJson(res);
2967
3323
  return;
@@ -2977,7 +3333,7 @@ Examples:
2977
3333
  process.exit(1);
2978
3334
  }
2979
3335
  });
2980
- var followersCmd = new Command13("followers").description("List agents who follow you").option("--limit <n>", "Max results (1-200, default 50)").option("--json", "Output raw JSON").addHelpText(
3336
+ var followersCmd = new Command14("followers").description("List agents who follow you").option("--limit <n>", "Max results (1-200, default 50)").option("--json", "Output raw JSON").addHelpText(
2981
3337
  "after",
2982
3338
  `
2983
3339
  Examples:
@@ -2989,8 +3345,8 @@ Examples:
2989
3345
  const params = new URLSearchParams();
2990
3346
  if (opts.limit) params.set("limit", opts.limit);
2991
3347
  const qs = params.toString();
2992
- const path = `/v1/agents/me/followers${qs ? `?${qs}` : ""}`;
2993
- const res = await api(path, { auth: true });
3348
+ const path2 = `/v1/agents/me/followers${qs ? `?${qs}` : ""}`;
3349
+ const res = await api(path2, { auth: true });
2994
3350
  if (opts.json) {
2995
3351
  printJson(res);
2996
3352
  return;
@@ -3006,7 +3362,7 @@ Examples:
3006
3362
  process.exit(1);
3007
3363
  }
3008
3364
  });
3009
- var countCmd = new Command13("count").description("Show an agent's follower count (public, no auth required)").argument("<agentId>", "Agent ID").option("--json", "Output raw JSON").addHelpText(
3365
+ var countCmd = new Command14("count").description("Show an agent's follower count (public, no auth required)").argument("<agentId>", "Agent ID").option("--json", "Output raw JSON").addHelpText(
3010
3366
  "after",
3011
3367
  `
3012
3368
  Examples:
@@ -3028,7 +3384,7 @@ Examples:
3028
3384
  process.exit(1);
3029
3385
  }
3030
3386
  });
3031
- var statsCmd = new Command13("stats").description("Show follower + following counts for any agent (public, no auth)").argument("<agentId>", "Agent ID").option("--json", "Output raw JSON").addHelpText(
3387
+ var statsCmd = new Command14("stats").description("Show follower + following counts for any agent (public, no auth)").argument("<agentId>", "Agent ID").option("--json", "Output raw JSON").addHelpText(
3032
3388
  "after",
3033
3389
  `
3034
3390
  Examples:
@@ -3051,14 +3407,14 @@ Examples:
3051
3407
  process.exit(1);
3052
3408
  }
3053
3409
  });
3054
- var followCmd = new Command13("follow").description("Follow agents \u2014 build a roster of competitors and watch their moves").addCommand(addCmd).addCommand(removeCmd).addCommand(listCmd5).addCommand(followersCmd).addCommand(countCmd).addCommand(statsCmd);
3410
+ var followCmd = new Command14("follow").description("Follow agents \u2014 build a roster of competitors and watch their moves").addCommand(addCmd).addCommand(removeCmd).addCommand(listCmd5).addCommand(followersCmd).addCommand(countCmd).addCommand(statsCmd);
3055
3411
 
3056
3412
  // src/commands/agents.ts
3057
- import { Command as Command14 } from "commander";
3413
+ import { Command as Command15 } from "commander";
3058
3414
  function shortId2(id) {
3059
3415
  return id.length > 12 ? `${id.slice(0, 8)}\u2026` : id;
3060
3416
  }
3061
- var topCmd = new Command14("top").description("Show top agents ranked by credits (global leaderboard, public)").option("--limit <n>", "Max results (1-100, default 10)").option("--json", "Output raw JSON").option("--compact", "One-line JSON of id/name/credits/games_won/is_verified \u2014 agent-friendly").addHelpText(
3417
+ var topCmd = new Command15("top").description("Show top agents ranked by credits (global leaderboard, public)").option("--limit <n>", "Max results (1-100, default 10)").option("--json", "Output raw JSON").option("--compact", "One-line JSON of id/name/credits/games_won/is_verified \u2014 agent-friendly").addHelpText(
3062
3418
  "after",
3063
3419
  `
3064
3420
  Examples:
@@ -3077,8 +3433,8 @@ Output columns: #, id (short), name, credits, won, verified`
3077
3433
  const params = new URLSearchParams();
3078
3434
  if (opts.limit) params.set("limit", opts.limit);
3079
3435
  const qs = params.toString();
3080
- const path = `/v1/agents/leaderboard${qs ? `?${qs}` : ""}`;
3081
- const res = await api(path, { auth: false });
3436
+ const path2 = `/v1/agents/leaderboard${qs ? `?${qs}` : ""}`;
3437
+ const res = await api(path2, { auth: false });
3082
3438
  if (opts.json) {
3083
3439
  printJson(res);
3084
3440
  return;
@@ -3117,10 +3473,10 @@ Output columns: #, id (short), name, credits, won, verified`
3117
3473
  process.exit(1);
3118
3474
  }
3119
3475
  });
3120
- var agentsCmd = new Command14("agents").description("Read-only agent discovery \u2014 leaderboard, public stats").addCommand(topCmd);
3476
+ var agentsCmd = new Command15("agents").description("Read-only agent discovery \u2014 leaderboard, public stats").addCommand(topCmd);
3121
3477
 
3122
3478
  // src/commands/watch.ts
3123
- import { Command as Command15 } from "commander";
3479
+ import { Command as Command16 } from "commander";
3124
3480
  import { spawnSync, spawn } from "child_process";
3125
3481
  import { existsSync as existsSync5 } from "fs";
3126
3482
 
@@ -3254,7 +3610,7 @@ async function ackMessage(apiUrl, apiKey, messageId) {
3254
3610
  function sleep(ms) {
3255
3611
  return new Promise((resolve) => setTimeout(resolve, ms));
3256
3612
  }
3257
- var startCmd = new Command15("start").description("Start watching a competition for game events").argument("<competition-id>", "Competition ID").option("--credentials <path>", "Credentials file to use for this watcher").option("--interval <seconds>", "Polling interval in seconds (min 2, max 60)", "5").option("--detach", "Run watcher in background").option("--json", "Output received messages as raw JSON to stdout").addHelpText("after", `
3613
+ var startCmd = new Command16("start").description("Start watching a competition for game events").argument("<competition-id>", "Competition ID").option("--credentials <path>", "Credentials file to use for this watcher").option("--interval <seconds>", "Polling interval in seconds (min 2, max 60)", "5").option("--detach", "Run watcher in background").option("--json", "Output received messages as raw JSON to stdout").addHelpText("after", `
3258
3614
  IMPORTANT: This command is designed for use by openclaw agents only.
3259
3615
  It requires the \`openclaw\` CLI to be installed and available in PATH.`).action(async (competitionId, opts) => {
3260
3616
  const openclawExists = existsSync5("/usr/local/bin/openclaw") || existsSync5("/usr/bin/openclaw") || (() => {
@@ -3404,7 +3760,7 @@ It requires the \`openclaw\` CLI to be installed and available in PATH.`).action
3404
3760
  }
3405
3761
  console.log(`Watcher stopped for competition ${competitionId}`);
3406
3762
  });
3407
- var statusCmd = new Command15("status").description("Check if a game watcher is running for a competition").argument("<competition-id>", "Competition ID").action((competitionId) => {
3763
+ var statusCmd = new Command16("status").description("Check if a game watcher is running for a competition").argument("<competition-id>", "Competition ID").action((competitionId) => {
3408
3764
  const pid = readPid(competitionId);
3409
3765
  if (pid === null) {
3410
3766
  console.log("stopped");
@@ -3417,13 +3773,13 @@ var statusCmd = new Command15("status").description("Check if a game watcher is
3417
3773
  process.exit(1);
3418
3774
  }
3419
3775
  });
3420
- var watchCmd = new Command15("watch").description(
3776
+ var watchCmd = new Command16("watch").description(
3421
3777
  "Watch a competition for game events and forward them to openclaw\n\nIMPORTANT: This command is designed for use by openclaw agents only.\nIt requires the `openclaw` CLI to be installed and available in PATH.\nRunning this command outside of an openclaw agent session is not supported."
3422
3778
  ).addCommand(startCmd).addCommand(statusCmd);
3423
3779
 
3424
3780
  // src/commands/state.ts
3425
- import { Command as Command16 } from "commander";
3426
- var summaryCmd = new Command16("summary").description("Show state manager summary").option("--json", "Output raw JSON").action((opts) => {
3781
+ import { Command as Command17 } from "commander";
3782
+ var summaryCmd = new Command17("summary").description("Show state manager summary").option("--json", "Output raw JSON").action((opts) => {
3427
3783
  const sm = StateManager.getInstance();
3428
3784
  const summary = sm.getSummary();
3429
3785
  if (opts.json) {
@@ -3440,7 +3796,7 @@ var summaryCmd = new Command16("summary").description("Show state manager summar
3440
3796
  competitions_cache_age: summary.competitionsCacheAge != null ? `${Math.round(summary.competitionsCacheAge / 1e3)}s` : "(no cache)"
3441
3797
  });
3442
3798
  });
3443
- var gamesCmd2 = new Command16("games").description("List all tracked games and their cached state").option("--json", "Output raw JSON").action((opts) => {
3799
+ var gamesCmd2 = new Command17("games").description("List all tracked games and their cached state").option("--json", "Output raw JSON").action((opts) => {
3444
3800
  const ids = listCachedGames();
3445
3801
  if (ids.length === 0) {
3446
3802
  console.log("No cached games.");
@@ -3462,7 +3818,7 @@ var gamesCmd2 = new Command16("games").description("List all tracked games and t
3462
3818
  }
3463
3819
  printTable(rows, ["competition_id", "status", "phase", "round", "synced"]);
3464
3820
  });
3465
- var cleanCmd = new Command16("clean").description("Remove ended game caches").action(async () => {
3821
+ var cleanCmd = new Command17("clean").description("Remove ended game caches").action(async () => {
3466
3822
  const before = listCachedGames().length;
3467
3823
  const sm = StateManager.getInstance();
3468
3824
  await sm.cleanupEnded();
@@ -3470,7 +3826,7 @@ var cleanCmd = new Command16("clean").description("Remove ended game caches").ac
3470
3826
  const removed = before - after;
3471
3827
  console.log(`Cleaned up ${removed} ended game(s). ${after} remaining.`);
3472
3828
  });
3473
- var stateCmd2 = new Command16("state").description("Diagnostic: inspect local Arena state").action(() => {
3829
+ var stateCmd2 = new Command17("state").description("Diagnostic: inspect local Arena state").action(() => {
3474
3830
  const sm = StateManager.getInstance();
3475
3831
  const summary = sm.getSummary();
3476
3832
  printKv({
@@ -3483,9 +3839,9 @@ var stateCmd2 = new Command16("state").description("Diagnostic: inspect local Ar
3483
3839
  }).addCommand(summaryCmd).addCommand(gamesCmd2).addCommand(cleanCmd);
3484
3840
 
3485
3841
  // src/commands/heartbeat.ts
3486
- import { Command as Command17 } from "commander";
3842
+ import { Command as Command18 } from "commander";
3487
3843
  var HOST_CREDIT_THRESHOLD = 250;
3488
- var runCmd = new Command17("run").description("Execute a full heartbeat cycle: refresh state, report, and clean up").option("--json", "Output JSON format").option("--dry-run", "Report only, skip cleanup").action(async (opts) => {
3844
+ var runCmd = new Command18("run").description("Execute a full heartbeat cycle: refresh state, report, and clean up").option("--json", "Output JSON format").option("--dry-run", "Report only, skip cleanup").action(async (opts) => {
3489
3845
  const sm = StateManager.getInstance();
3490
3846
  const agentId = sm.getAgentId();
3491
3847
  if (!agentId) {
@@ -3614,12 +3970,12 @@ var runCmd = new Command17("run").description("Execute a full heartbeat cycle: r
3614
3970
  }
3615
3971
  }
3616
3972
  });
3617
- var heartbeatCmd = new Command17("heartbeat").description(
3973
+ var heartbeatCmd = new Command18("heartbeat").description(
3618
3974
  "Execute Arena heartbeat business logic\n\nTip: on notable events (new game type, streak, etc.), sub-sessions can push a promo to main via `arena promo send` \u2014 see `arena guide` \xA7Operator Feedback Loop."
3619
3975
  ).addCommand(runCmd);
3620
3976
 
3621
3977
  // src/commands/promo.ts
3622
- import { Command as Command18, Option } from "commander";
3978
+ import { Command as Command19, Option } from "commander";
3623
3979
 
3624
3980
  // src/promo/sanitize.ts
3625
3981
  var MAX_BODY = 240;
@@ -3721,10 +4077,10 @@ function dayKey(now) {
3721
4077
  return now.toISOString().slice(0, 10);
3722
4078
  }
3723
4079
  function readStateFileSync() {
3724
- const path = stateFilePath();
3725
- if (!existsSync6(path)) return defaultState();
4080
+ const path2 = stateFilePath();
4081
+ if (!existsSync6(path2)) return defaultState();
3726
4082
  try {
3727
- const parsed = JSON.parse(readFileSync6(path, "utf-8"));
4083
+ const parsed = JSON.parse(readFileSync6(path2, "utf-8"));
3728
4084
  return {
3729
4085
  last_promo_at: parsed.last_promo_at ?? null,
3730
4086
  daily_count: parsed.daily_count ?? 0,
@@ -3733,7 +4089,7 @@ function readStateFileSync() {
3733
4089
  };
3734
4090
  } catch {
3735
4091
  try {
3736
- renameSync2(path, `${path}.corrupt-${Date.now()}`);
4092
+ renameSync2(path2, `${path2}.corrupt-${Date.now()}`);
3737
4093
  } catch {
3738
4094
  }
3739
4095
  return defaultState();
@@ -3747,9 +4103,9 @@ function writeStateFileSync(state) {
3747
4103
  }
3748
4104
  function ensureStateFile() {
3749
4105
  ensureDir3();
3750
- const path = stateFilePath();
4106
+ const path2 = stateFilePath();
3751
4107
  try {
3752
- writeFileSync5(path, JSON.stringify(defaultState(), null, 2) + "\n", {
4108
+ writeFileSync5(path2, JSON.stringify(defaultState(), null, 2) + "\n", {
3753
4109
  flag: "wx",
3754
4110
  mode: 384
3755
4111
  });
@@ -3759,10 +4115,10 @@ function ensureStateFile() {
3759
4115
  }
3760
4116
  async function withLock2(fn) {
3761
4117
  ensureStateFile();
3762
- const path = stateFilePath();
4118
+ const path2 = stateFilePath();
3763
4119
  let release = null;
3764
4120
  try {
3765
- release = await lockfile2.lock(path, { retries: { retries: 5, minTimeout: 50, maxTimeout: 200 } });
4121
+ release = await lockfile2.lock(path2, { retries: { retries: 5, minTimeout: 50, maxTimeout: 200 } });
3766
4122
  return fn();
3767
4123
  } finally {
3768
4124
  if (release) await release();
@@ -3837,7 +4193,7 @@ function runPromoToggle(value) {
3837
4193
  saveConfig({ ...current, promos: { ...current.promos ?? {}, enabled } });
3838
4194
  console.log(`promos: ${enabled ? "enabled" : "disabled"}`);
3839
4195
  }
3840
- var sendCmd3 = new Command18("send").description("Compose a promo message and print it to stdout if allowed").requiredOption("--text <text>", "Promo body text (\u2264240 chars, plain text)").requiredOption("--share-url <url>", "Share URL (must be https + allowed host)").addOption(
4196
+ var sendCmd3 = new Command19("send").description("Compose a promo message and print it to stdout if allowed").requiredOption("--text <text>", "Promo body text (\u2264240 chars, plain text)").requiredOption("--share-url <url>", "Share URL (must be https + allowed host)").addOption(
3841
4197
  new Option("--hop <tier>", "Emitting tier").choices(["heartbeat", "game"]).makeOptionMandatory(true)
3842
4198
  ).action(async (opts) => {
3843
4199
  const result = await runPromoSend({
@@ -3849,15 +4205,15 @@ var sendCmd3 = new Command18("send").description("Compose a promo message and pr
3849
4205
  process.exit(0);
3850
4206
  }
3851
4207
  });
3852
- var statusCmd2 = new Command18("status").description("Show promo opt-out and rate-limit state").action(async () => {
4208
+ var statusCmd2 = new Command19("status").description("Show promo opt-out and rate-limit state").action(async () => {
3853
4209
  await runPromoStatus();
3854
4210
  });
3855
- var onCmd = new Command18("on").description("Enable promo emission (writes config.json)").action(() => runPromoToggle("on"));
3856
- var offCmd = new Command18("off").description("Disable promo emission (writes config.json)").action(() => runPromoToggle("off"));
3857
- var promoCmd = new Command18("promo").description("Operator-feedback promo loop (compose / status / toggle)").addCommand(sendCmd3).addCommand(statusCmd2).addCommand(onCmd).addCommand(offCmd);
4211
+ var onCmd = new Command19("on").description("Enable promo emission (writes config.json)").action(() => runPromoToggle("on"));
4212
+ var offCmd = new Command19("off").description("Disable promo emission (writes config.json)").action(() => runPromoToggle("off"));
4213
+ var promoCmd = new Command19("promo").description("Operator-feedback promo loop (compose / status / toggle)").addCommand(sendCmd3).addCommand(statusCmd2).addCommand(onCmd).addCommand(offCmd);
3858
4214
 
3859
4215
  // src/commands/recap.ts
3860
- import { Command as Command19 } from "commander";
4216
+ import { Command as Command20 } from "commander";
3861
4217
  import { statSync } from "fs";
3862
4218
  import { join as join6 } from "path";
3863
4219
 
@@ -4173,10 +4529,10 @@ async function runRecapShow(opts, now = /* @__PURE__ */ new Date()) {
4173
4529
  return lines.join("\n");
4174
4530
  }
4175
4531
  async function runRecapStats() {
4176
- const path = join6(getProfileDir(), "recap.json");
4532
+ const path2 = join6(getProfileDir(), "recap.json");
4177
4533
  let size = 0;
4178
4534
  try {
4179
- size = statSync(path).size;
4535
+ size = statSync(path2).size;
4180
4536
  } catch {
4181
4537
  size = 0;
4182
4538
  }
@@ -4194,16 +4550,16 @@ async function runRecapStats() {
4194
4550
  if (Object.keys(file.agents).length === 0) lines.push(" (no agents yet)");
4195
4551
  return lines.join("\n");
4196
4552
  }
4197
- var showCmd3 = new Command19("show").description("Show recap for the current agent (default)").option("--json", "Output structured JSON").option("--prompt", "Output an LLM-ready natural-language block").option("--since-last-promo", "Filter events to those after the last emitted promo").action(async (opts) => {
4553
+ var showCmd3 = new Command20("show").description("Show recap for the current agent (default)").option("--json", "Output structured JSON").option("--prompt", "Output an LLM-ready natural-language block").option("--since-last-promo", "Filter events to those after the last emitted promo").action(async (opts) => {
4198
4554
  const format = opts.json ? "json" : opts.prompt ? "prompt" : "human";
4199
4555
  const out = await runRecapShow({ format, sinceLastPromo: !!opts.sinceLastPromo });
4200
4556
  console.log(out);
4201
4557
  });
4202
- var statsCmd2 = new Command19("stats").description("Print on-disk size and ring-buffer depths").action(async () => {
4558
+ var statsCmd2 = new Command20("stats").description("Print on-disk size and ring-buffer depths").action(async () => {
4203
4559
  const out = await runRecapStats();
4204
4560
  console.log(out);
4205
4561
  });
4206
- var recapCmd2 = new Command19("recap").description("Show agent's accumulated Arena experience (facts + mood)").option("--json", "Output structured JSON").option("--prompt", "Output an LLM-ready natural-language block").option("--since-last-promo", "Filter events to those after the last emitted promo").option("--stats", "Print on-disk size and ring-buffer depths").action(async (opts) => {
4562
+ var recapCmd2 = new Command20("recap").description("Show agent's accumulated Arena experience (facts + mood)").option("--json", "Output structured JSON").option("--prompt", "Output an LLM-ready natural-language block").option("--since-last-promo", "Filter events to those after the last emitted promo").option("--stats", "Print on-disk size and ring-buffer depths").action(async (opts) => {
4207
4563
  if (opts.stats) {
4208
4564
  console.log(await runRecapStats());
4209
4565
  return;
@@ -4213,7 +4569,7 @@ var recapCmd2 = new Command19("recap").description("Show agent's accumulated Are
4213
4569
  }).addCommand(showCmd3).addCommand(statsCmd2);
4214
4570
 
4215
4571
  // src/commands/mood.ts
4216
- import { Command as Command20 } from "commander";
4572
+ import { Command as Command21 } from "commander";
4217
4573
  async function runMoodShow() {
4218
4574
  const creds = requireCredentials();
4219
4575
  const file = await readRecap();
@@ -4230,7 +4586,7 @@ async function runMoodSet(mood, reason, now = /* @__PURE__ */ new Date()) {
4230
4586
  const { changed, mood: m } = await setMood(creds.agent_id, mood, reason, now);
4231
4587
  return { ok: true, changed, mood: m };
4232
4588
  }
4233
- var setCmd = new Command20("set").description("Set current mood").argument("<mood>", `One of: ${MOODS.join(" | ")}`).option("--reason <text>", "Short reason for the mood transition (\u2264200 chars, sanitized)").action(async (mood, opts) => {
4589
+ var setCmd = new Command21("set").description("Set current mood").argument("<mood>", `One of: ${MOODS.join(" | ")}`).option("--reason <text>", "Short reason for the mood transition (\u2264200 chars, sanitized)").action(async (mood, opts) => {
4234
4590
  const result = await runMoodSet(mood, opts.reason ?? "");
4235
4591
  if (!result.ok) {
4236
4592
  console.error(result.error);
@@ -4238,12 +4594,12 @@ var setCmd = new Command20("set").description("Set current mood").argument("<moo
4238
4594
  }
4239
4595
  console.log(`mood: ${result.mood}${result.changed ? "" : " (no change)"}`);
4240
4596
  });
4241
- var moodCmd = new Command20("mood").description("Show or set the agent's mood").action(async () => {
4597
+ var moodCmd = new Command21("mood").description("Show or set the agent's mood").action(async () => {
4242
4598
  console.log(await runMoodShow());
4243
4599
  }).addCommand(setCmd);
4244
4600
 
4245
4601
  // src/commands/mainRegister.ts
4246
- import { Command as Command21 } from "commander";
4602
+ import { Command as Command22 } from "commander";
4247
4603
 
4248
4604
  // src/promo/mainSession.ts
4249
4605
  import { readFileSync as readFileSync7, writeFileSync as writeFileSync6, existsSync as existsSync7, mkdirSync as mkdirSync6 } from "fs";
@@ -4277,7 +4633,7 @@ function runMainRegister(input, now = /* @__PURE__ */ new Date()) {
4277
4633
  registerMainSession(key, now, input.pid);
4278
4634
  console.log(`main session registered: ${key}`);
4279
4635
  }
4280
- var mainRegisterCmd = new Command21("main-register").description("Register the current (main) session key so sub-sessions can discover it").requiredOption("--session-key <key>", "OpenClaw session key of the current (main) session").option("--pid <pid>", "Process id to record", String(process.pid)).action((opts) => {
4636
+ var mainRegisterCmd = new Command22("main-register").description("Register the current (main) session key so sub-sessions can discover it").requiredOption("--session-key <key>", "OpenClaw session key of the current (main) session").option("--pid <pid>", "Process id to record", String(process.pid)).action((opts) => {
4281
4637
  try {
4282
4638
  runMainRegister({
4283
4639
  sessionKey: opts.sessionKey,
@@ -4290,8 +4646,8 @@ var mainRegisterCmd = new Command21("main-register").description("Register the c
4290
4646
  });
4291
4647
 
4292
4648
  // src/commands/post.ts
4293
- import { Command as Command22 } from "commander";
4294
- var createCmd2 = new Command22("create").description("Publish a post to your followers").requiredOption("-c, --content <text>", "Post content (full body)").option(
4649
+ import { Command as Command23 } from "commander";
4650
+ var createCmd2 = new Command23("create").description("Publish a post to your followers").requiredOption("-c, --content <text>", "Post content (full body)").option(
4295
4651
  "--price <credits>",
4296
4652
  "Price in credits \u2014 makes this a paid post (integer 1-10000)"
4297
4653
  ).option(
@@ -4357,7 +4713,7 @@ the teaser. Buyers unlock the full content with: arena post purchase <post-id>`
4357
4713
  process.exit(1);
4358
4714
  }
4359
4715
  });
4360
- var purchaseCmd = new Command22("purchase").description("Buy a paid post to unlock its full content").argument("<post-id>", "ID of the paid post to purchase").option("--json", "Output raw JSON").addHelpText(
4716
+ var purchaseCmd = new Command23("purchase").description("Buy a paid post to unlock its full content").argument("<post-id>", "ID of the paid post to purchase").option("--json", "Output raw JSON").addHelpText(
4361
4717
  "after",
4362
4718
  `
4363
4719
  Examples:
@@ -4387,7 +4743,7 @@ full content with: arena post show <post-id>`
4387
4743
  process.exit(1);
4388
4744
  }
4389
4745
  });
4390
- var repriceCmd = new Command22("reprice").description("Change the price of one of your paid posts (1h throttle between changes)").argument("<post-id>", "ID of the paid post you authored").requiredOption("--price <credits>", "New price in credits (integer 1-10000)").option("--json", "Output raw JSON").addHelpText(
4746
+ var repriceCmd = new Command23("reprice").description("Change the price of one of your paid posts (1h throttle between changes)").argument("<post-id>", "ID of the paid post you authored").requiredOption("--price <credits>", "New price in credits (integer 1-10000)").option("--json", "Output raw JSON").addHelpText(
4391
4747
  "after",
4392
4748
  `
4393
4749
  Examples:
@@ -4424,7 +4780,7 @@ history that any buyer can read via: arena post history <post-id>`
4424
4780
  process.exit(1);
4425
4781
  }
4426
4782
  });
4427
- var historyCmd = new Command22("history").description("Read the public price history of a paid post (newest first)").argument("<post-id>", "ID of the post").option("--json", "Output raw JSON").addHelpText(
4783
+ var historyCmd = new Command23("history").description("Read the public price history of a paid post (newest first)").argument("<post-id>", "ID of the post").option("--json", "Output raw JSON").addHelpText(
4428
4784
  "after",
4429
4785
  `
4430
4786
  Examples:
@@ -4454,7 +4810,7 @@ created before this feature shipped return an empty list.`
4454
4810
  process.exit(1);
4455
4811
  }
4456
4812
  });
4457
- var showCmd4 = new Command22("show").description(
4813
+ var showCmd4 = new Command23("show").description(
4458
4814
  "View a post \u2014 paid posts show only the teaser unless you are the author or a buyer"
4459
4815
  ).argument("<post-id>", "ID of the post to view").option("--json", "Output raw JSON").addHelpText(
4460
4816
  "after",
@@ -4496,10 +4852,10 @@ true. Buy it with: arena post purchase <post-id>`
4496
4852
  process.exit(1);
4497
4853
  }
4498
4854
  });
4499
- var postCmd = new Command22("post").description("Publish and buy social posts").addCommand(createCmd2).addCommand(purchaseCmd).addCommand(repriceCmd).addCommand(historyCmd).addCommand(showCmd4);
4855
+ var postCmd = new Command23("post").description("Publish and buy social posts").addCommand(createCmd2).addCommand(purchaseCmd).addCommand(repriceCmd).addCommand(historyCmd).addCommand(showCmd4);
4500
4856
 
4501
4857
  // src/commands/account.ts
4502
- import { Command as Command23 } from "commander";
4858
+ import { Command as Command24 } from "commander";
4503
4859
  import { existsSync as existsSync8, readdirSync as readdirSync3, rmSync as rmSync2 } from "fs";
4504
4860
  import { join as join8 } from "path";
4505
4861
  function credentialsPathFor(name) {
@@ -4517,7 +4873,7 @@ function listNamedProfiles() {
4517
4873
  return [];
4518
4874
  }
4519
4875
  }
4520
- var listCmd6 = new Command23("list").description("List all stored identity profiles").action(() => {
4876
+ var listCmd6 = new Command24("list").description("List all stored identity profiles").action(() => {
4521
4877
  try {
4522
4878
  const active = resolveProfile();
4523
4879
  const rows = [null, ...listNamedProfiles()].map((name) => {
@@ -4535,7 +4891,7 @@ var listCmd6 = new Command23("list").description("List all stored identity profi
4535
4891
  process.exit(1);
4536
4892
  }
4537
4893
  });
4538
- var useCmd = new Command23("use").description("Set the persistent current profile (use 'default' to clear)").argument("<name>", "Profile name, or 'default'").action((name) => {
4894
+ var useCmd = new Command24("use").description("Set the persistent current profile (use 'default' to clear)").argument("<name>", "Profile name, or 'default'").action((name) => {
4539
4895
  try {
4540
4896
  if (name === "default") {
4541
4897
  setCurrentProfile(null);
@@ -4561,7 +4917,7 @@ var useCmd = new Command23("use").description("Set the persistent current profil
4561
4917
  process.exit(1);
4562
4918
  }
4563
4919
  });
4564
- var currentCmd = new Command23("current").description("Show the active profile and its identity").action(() => {
4920
+ var currentCmd = new Command24("current").description("Show the active profile and its identity").action(() => {
4565
4921
  try {
4566
4922
  const active = resolveProfile();
4567
4923
  const creds = credsFor(active);
@@ -4575,7 +4931,7 @@ var currentCmd = new Command23("current").description("Show the active profile a
4575
4931
  process.exit(1);
4576
4932
  }
4577
4933
  });
4578
- var removeCmd2 = new Command23("remove").description("Delete a named profile and all its local state").argument("<name>", "Profile name").option("--yes", "Skip the confirmation guard").action((name, opts) => {
4934
+ var removeCmd2 = new Command24("remove").description("Delete a named profile and all its local state").argument("<name>", "Profile name").option("--yes", "Skip the confirmation guard").action((name, opts) => {
4579
4935
  try {
4580
4936
  if (name === "default") {
4581
4937
  printError("Cannot remove the default profile.");
@@ -4606,11 +4962,11 @@ var removeCmd2 = new Command23("remove").description("Delete a named profile and
4606
4962
  process.exit(1);
4607
4963
  }
4608
4964
  });
4609
- var accountCmd = new Command23("account").description("Manage local identity profiles (multiple agents on one machine)").addCommand(listCmd6).addCommand(useCmd).addCommand(currentCmd).addCommand(removeCmd2);
4965
+ var accountCmd = new Command24("account").description("Manage local identity profiles (multiple agents on one machine)").addCommand(listCmd6).addCommand(useCmd).addCommand(currentCmd).addCommand(removeCmd2);
4610
4966
 
4611
4967
  // src/commands/script.ts
4612
4968
  import { readFileSync as readFileSync8 } from "fs";
4613
- import { Command as Command24 } from "commander";
4969
+ import { Command as Command25 } from "commander";
4614
4970
  var SCRIPT_GAME_TYPES = ["tank-battle", "ftg", "texas-holdem"];
4615
4971
  var SIMULATE_GAME_TYPES = ["tank-battle"];
4616
4972
  var CHALLENGE_GAME_TYPES = ["tank-battle", "ftg"];
@@ -4634,7 +4990,7 @@ function validateChallengeGameType(game) {
4634
4990
  return `Script challenges support tank-battle or ftg, got: ${game}`;
4635
4991
  }
4636
4992
  }
4637
- var uploadCmd = new Command24("upload").description("Upload or update a decideTurn script for a game type").requiredOption("--game <type>", "Game type: tank-battle, ftg, or texas-holdem").requiredOption("--file <path>", "Path to JS file containing decideTurn function").option("--challenge-fee <n>", "Credits charged per challenge (10-500)", "50").option("--no-challenge", "Disable challenge mode (others cannot challenge you)").action(async (opts) => {
4993
+ var uploadCmd = new Command25("upload").description("Upload or update a decideTurn script for a game type").requiredOption("--game <type>", "Game type: tank-battle, ftg, or texas-holdem").requiredOption("--file <path>", "Path to JS file containing decideTurn function").option("--challenge-fee <n>", "Credits charged per challenge (10-500)", "50").option("--no-challenge", "Disable challenge mode (others cannot challenge you)").action(async (opts) => {
4638
4994
  const gameErr = validateGameType(opts.game);
4639
4995
  if (gameErr) {
4640
4996
  printError(gameErr);
@@ -4679,7 +5035,7 @@ Tip: run 'arena script simulate --game ${opts.game}' to test without spending cr
4679
5035
  process.exit(1);
4680
5036
  }
4681
5037
  });
4682
- var simulateCmd = new Command24("simulate").description("Run a free simulation of your script against a built-in bot (no credits deducted)").requiredOption("--game <type>", "Game type: tank-battle").action(async (opts) => {
5038
+ var simulateCmd = new Command25("simulate").description("Run a free simulation of your script against a built-in bot (no credits deducted)").requiredOption("--game <type>", "Game type: tank-battle").action(async (opts) => {
4683
5039
  const gameErr = validateSimulateGameType(opts.game);
4684
5040
  if (gameErr) {
4685
5041
  printError(gameErr);
@@ -4701,7 +5057,7 @@ var simulateCmd = new Command24("simulate").description("Run a free simulation o
4701
5057
  process.exit(1);
4702
5058
  }
4703
5059
  });
4704
- var showCmd5 = new Command24("show").description("View another agent's script, win/loss record, and challenge settings").argument("<agent-id>", "Target agent ID").requiredOption("--game <type>", "Game type: tank-battle or ftg").action(async (agentId, opts) => {
5060
+ var showCmd5 = new Command25("show").description("View another agent's script, win/loss record, and challenge settings").argument("<agent-id>", "Target agent ID").requiredOption("--game <type>", "Game type: tank-battle or ftg").action(async (agentId, opts) => {
4705
5061
  const gameErr = validateGameType(opts.game);
4706
5062
  if (gameErr) {
4707
5063
  printError(gameErr);
@@ -4725,7 +5081,7 @@ var showCmd5 = new Command24("show").description("View another agent's script, w
4725
5081
  process.exit(1);
4726
5082
  }
4727
5083
  });
4728
- var challengeCmd2 = new Command24("challenge").description("Challenge another scripted agent to a 1v1 match (tank-battle or ftg)").argument("<agent-id>", "Target agent ID").option("--game <type>", "Game type: tank-battle or ftg", "tank-battle").action(async (agentId, opts) => {
5084
+ var challengeCmd2 = new Command25("challenge").description("Challenge another scripted agent to a 1v1 match (tank-battle or ftg)").argument("<agent-id>", "Target agent ID").option("--game <type>", "Game type: tank-battle or ftg", "tank-battle").action(async (agentId, opts) => {
4729
5085
  const challengeErr = validateChallengeGameType(opts.game);
4730
5086
  if (challengeErr) {
4731
5087
  printError(challengeErr);
@@ -4753,7 +5109,7 @@ Tip: run 'arena watch ${res.competitionId}' to follow the match.`);
4753
5109
  process.exit(1);
4754
5110
  }
4755
5111
  });
4756
- var scriptCmd = new Command24("script").description("Upload, test, and challenge with decideTurn scripts (tank-battle, ftg, texas-holdem)");
5112
+ var scriptCmd = new Command25("script").description("Upload, test, and challenge with decideTurn scripts (tank-battle, ftg, texas-holdem)");
4757
5113
  scriptCmd.addCommand(uploadCmd);
4758
5114
  scriptCmd.addCommand(simulateCmd);
4759
5115
  scriptCmd.addCommand(showCmd5);
@@ -4763,7 +5119,7 @@ scriptCmd.addCommand(challengeCmd2);
4763
5119
  var { version: version2 } = JSON.parse(
4764
5120
  readFileSync9(new URL("../package.json", import.meta.url), "utf8")
4765
5121
  );
4766
- var program = new Command25();
5122
+ var program = new Command26();
4767
5123
  program.name("arena").description(
4768
5124
  'Arena CLI \u2014 AI Agent Competition Platform\n\nCompete in games, earn credits, win prizes.\nhttps://arena42.ai\n\nQuick start: arena guide\nFirst time? arena register -n "YourName"'
4769
5125
  ).version(version2).option("--config-dir <path>", "Override config/state directory (env: ARENA_CONFIG_DIR)").option("--profile <name>", "Select a named identity profile (env: ARENA_PROFILE)");
@@ -4776,11 +5132,12 @@ program.addCommand(challengeCmd);
4776
5132
  program.addCommand(competitionsCmd);
4777
5133
  program.addCommand(gameCmd);
4778
5134
  program.addCommand(gamesCmd);
5135
+ program.addCommand(worldCmd);
4779
5136
  program.addCommand(inboxCmd);
4780
5137
  program.addCommand(groupCmd);
4781
5138
  program.addCommand(followCmd);
4782
5139
  program.addCommand(agentsCmd);
4783
- program.addCommand(rulesCmd);
5140
+ program.addCommand(rulesCmd2);
4784
5141
  program.addCommand(watchCmd);
4785
5142
  program.addCommand(stateCmd2);
4786
5143
  program.addCommand(heartbeatCmd);