@netmind/arena-cli 0.7.1 → 0.7.3

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
@@ -177,8 +177,13 @@ function saveConfig(config) {
177
177
  const merged = { ...existing, ...config };
178
178
  writeFileSync(getConfigFile(), JSON.stringify(merged, null, 2) + "\n");
179
179
  }
180
+ function normalizeApiUrl(raw) {
181
+ const trimmed = raw.trim().replace(/\/+$/, "");
182
+ return /\/api$/.test(trimmed) ? trimmed : `${trimmed}/api`;
183
+ }
180
184
  function getApiUrl() {
181
- return process.env.ARENA_API_URL || loadConfig().api_url;
185
+ const raw = process.env.ARENA_API_URL || loadConfig().api_url;
186
+ return normalizeApiUrl(raw);
182
187
  }
183
188
  function requireCredentials(credentialsPath) {
184
189
  try {
@@ -2531,10 +2536,10 @@ import { join as join4 } from "path";
2531
2536
  function pidPath(competitionId) {
2532
2537
  return join4(getConfigDir(), `watch-${competitionId}.pid`);
2533
2538
  }
2534
- function writePid(competitionId) {
2539
+ function writePid(competitionId, pid) {
2535
2540
  const dir = getConfigDir();
2536
2541
  mkdirSync4(dir, { recursive: true });
2537
- writeFileSync4(pidPath(competitionId), String(process.pid), "utf-8");
2542
+ writeFileSync4(pidPath(competitionId), String(pid ?? process.pid), "utf-8");
2538
2543
  }
2539
2544
  function deletePid(competitionId) {
2540
2545
  const p = pidPath(competitionId);
@@ -2672,15 +2677,17 @@ It requires the \`openclaw\` CLI to be installed and available in PATH.`).action
2672
2677
  }
2673
2678
  const creds = requireCredentials(opts.credentials);
2674
2679
  const existingPid = readPid(competitionId);
2675
- if (existingPid !== null && checkPidAlive(existingPid)) {
2680
+ if (existingPid !== null && existingPid !== process.pid && checkPidAlive(existingPid)) {
2676
2681
  console.log(`Already watching competition ${competitionId} (PID: ${existingPid})`);
2677
2682
  process.exit(0);
2678
2683
  }
2679
2684
  const MAX_WATCHERS = 3;
2680
- const aliveCount = countAliveWatchers();
2681
- if (aliveCount >= MAX_WATCHERS) {
2682
- printError(`Maximum of ${MAX_WATCHERS} concurrent watchers reached (${aliveCount} running). Stop an existing watcher before starting a new one.`);
2683
- process.exit(1);
2685
+ if (existingPid !== process.pid) {
2686
+ const aliveCount = countAliveWatchers();
2687
+ if (aliveCount >= MAX_WATCHERS) {
2688
+ printError(`Maximum of ${MAX_WATCHERS} concurrent watchers reached (${aliveCount} running). Stop an existing watcher before starting a new one.`);
2689
+ process.exit(1);
2690
+ }
2684
2691
  }
2685
2692
  if (opts.detach) {
2686
2693
  const childArgs = [process.argv[1], "watch", "start", competitionId, "--interval", opts.interval];
@@ -2695,22 +2702,15 @@ It requires the \`openclaw\` CLI to be installed and available in PATH.`).action
2695
2702
  stdio: "ignore"
2696
2703
  });
2697
2704
  child.unref();
2705
+ if (typeof child.pid !== "number") {
2706
+ printError("Failed to start background watcher: unable to determine child PID");
2707
+ process.exit(1);
2708
+ }
2709
+ writePid(competitionId, child.pid);
2698
2710
  console.log(`Watcher started in background (PID: ${child.pid})`);
2699
2711
  console.log(`Stop with: kill ${child.pid}`);
2700
2712
  return;
2701
2713
  }
2702
- try {
2703
- dispatchBootstrapToOpenclaw(competitionId, creds);
2704
- } catch (err) {
2705
- const msg = err instanceof Error ? err.message : String(err);
2706
- printError(`bootstrap dispatch failed: ${msg}`);
2707
- process.exit(1);
2708
- }
2709
- try {
2710
- StateManager.getInstance().trackGame(competitionId, competitionId, "unknown");
2711
- } catch (e) {
2712
- console.warn(`[watch] warning: failed to persist game tracking: ${e instanceof Error ? e.message : e}`);
2713
- }
2714
2714
  writePid(competitionId);
2715
2715
  const handleSigterm = () => {
2716
2716
  cleanup();
@@ -2727,6 +2727,19 @@ It requires the \`openclaw\` CLI to be installed and available in PATH.`).action
2727
2727
  };
2728
2728
  process.on("SIGTERM", handleSigterm);
2729
2729
  process.on("SIGINT", handleSigint);
2730
+ try {
2731
+ dispatchBootstrapToOpenclaw(competitionId, creds);
2732
+ } catch (err) {
2733
+ const msg = err instanceof Error ? err.message : String(err);
2734
+ printError(`bootstrap dispatch failed: ${msg}`);
2735
+ cleanup();
2736
+ process.exit(1);
2737
+ }
2738
+ try {
2739
+ StateManager.getInstance().trackGame(competitionId, competitionId, "unknown");
2740
+ } catch (e) {
2741
+ console.warn(`[watch] warning: failed to persist game tracking: ${e instanceof Error ? e.message : e}`);
2742
+ }
2730
2743
  const apiUrl = getApiUrl();
2731
2744
  const intervalMs = Math.min(Math.max(parseInt(opts.interval, 10), 2), 60) * 1e3;
2732
2745
  console.log(`Watching competition ${competitionId} (interval: ${intervalMs / 1e3}s)`);