pyyol 1.3.0 → 1.4.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/cli.js +85 -9
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -233,6 +233,42 @@ async function loadAgentFromConfig(cfg) {
|
|
|
233
233
|
return asAgent(obj);
|
|
234
234
|
}
|
|
235
235
|
// ── commands ───────────────────────────────────────────────────────────────────
|
|
236
|
+
async function loginAndSave(api, dashboard, connect, provider) {
|
|
237
|
+
const c = await runLoginFlow({ dashboardUrl: dashboard, apiUrl: api, provider });
|
|
238
|
+
if (connect)
|
|
239
|
+
c.connectUrl = connect;
|
|
240
|
+
if (!c.apiKey && c.agentId && c.accessToken) {
|
|
241
|
+
const [st, resp] = await apiPost(`${api}/v1/agent/keys`, c.accessToken, { agent_id: c.agentId });
|
|
242
|
+
if (st === 201 && resp.api_key)
|
|
243
|
+
c.apiKey = resp.api_key;
|
|
244
|
+
}
|
|
245
|
+
creds.save(c);
|
|
246
|
+
return c;
|
|
247
|
+
}
|
|
248
|
+
// Return valid creds for a game/sandbox command, launching the browser login when this
|
|
249
|
+
// DEVICE isn't logged in — so `pyyol dev`/`play`/`queue` just work after install.
|
|
250
|
+
// Non-interactive (CI) → null with guidance so the caller errors cleanly.
|
|
251
|
+
async function ensureLogin(a) {
|
|
252
|
+
const c = creds.load();
|
|
253
|
+
if (c && (c.accessToken || c.apiKey))
|
|
254
|
+
return c;
|
|
255
|
+
const api = (str(a, "api") || DEFAULT_API_BASE).replace(/\/$/, "");
|
|
256
|
+
const dashboard = (str(a, "dashboard") || DEFAULT_DASHBOARD).replace(/\/$/, "");
|
|
257
|
+
if (!(process.stdin.isTTY && process.stdout.isTTY)) {
|
|
258
|
+
console.error(`${BAD} not logged in on this device. Run \`pyyol login\` (opens the browser) or set PYYOL_TOKEN, then retry.`);
|
|
259
|
+
return null;
|
|
260
|
+
}
|
|
261
|
+
console.log("you're not logged in on this device — opening the browser to sign in…");
|
|
262
|
+
try {
|
|
263
|
+
const got = await loginAndSave(api, dashboard, str(a, "connect") || "", str(a, "with") || "");
|
|
264
|
+
console.log(`${OK} logged in as ${got.agentId || "(no agent yet)"}. continuing…`);
|
|
265
|
+
return got;
|
|
266
|
+
}
|
|
267
|
+
catch (e) {
|
|
268
|
+
console.error(`${BAD} login failed: ${e} — run \`pyyol login\` and retry.`);
|
|
269
|
+
return null;
|
|
270
|
+
}
|
|
271
|
+
}
|
|
236
272
|
async function cmdLogin(a) {
|
|
237
273
|
const token = str(a, "token");
|
|
238
274
|
// API host serves /v1/*; dashboard host serves /cli-login — different in prod,
|
|
@@ -387,13 +423,11 @@ async function orchestrate(a, devLocked) {
|
|
|
387
423
|
console.error(`${BAD} no pyyol.toml here — run \`pyyol init <dir>\` first.`);
|
|
388
424
|
return 2;
|
|
389
425
|
}
|
|
390
|
-
|
|
391
|
-
//
|
|
392
|
-
|
|
393
|
-
if (!c
|
|
394
|
-
console.error(`${BAD} not logged in — run \`pyyol login\` first.`);
|
|
426
|
+
// Auto-login on this device if needed: a first-time user who installed the SDK and
|
|
427
|
+
// ran `pyyol dev`/`play` gets the browser sign-in, then plays — no separate step.
|
|
428
|
+
const c = await ensureLogin(a);
|
|
429
|
+
if (!c)
|
|
395
430
|
return 2;
|
|
396
|
-
}
|
|
397
431
|
const connectUrl = str(a, "url") || process.env.PYYOL_URL || c.connectUrl;
|
|
398
432
|
const base = httpBase(a, c);
|
|
399
433
|
// The agent id MUST be the one the token belongs to. The token comes from creds,
|
|
@@ -487,6 +521,42 @@ async function orchestrate(a, devLocked) {
|
|
|
487
521
|
console.log("\nstopped.");
|
|
488
522
|
return 0;
|
|
489
523
|
}
|
|
524
|
+
async function cmdGames(a) {
|
|
525
|
+
const base = httpBase(a, creds.load());
|
|
526
|
+
if (!base) {
|
|
527
|
+
console.error(`${BAD} no API url — pass --api or run \`pyyol login\`.`);
|
|
528
|
+
return 2;
|
|
529
|
+
}
|
|
530
|
+
const [st, resp] = await apiGet(`${base}/v1/games`);
|
|
531
|
+
if (st !== 200) {
|
|
532
|
+
console.error(`${BAD} could not fetch games (${st}): ${JSON.stringify(resp)}`);
|
|
533
|
+
return 1;
|
|
534
|
+
}
|
|
535
|
+
const games = resp.games ?? [];
|
|
536
|
+
if (!games.length) {
|
|
537
|
+
console.log("no games available.");
|
|
538
|
+
return 0;
|
|
539
|
+
}
|
|
540
|
+
console.log(` ${"GAME".padEnd(11)}${"LIVE".padStart(6)}${"PLAYING".padStart(9)}${"WAITING".padStart(9)} STATUS`);
|
|
541
|
+
console.log(` ${"─".repeat(44)}`);
|
|
542
|
+
let totalLive = 0;
|
|
543
|
+
let totalWait = 0;
|
|
544
|
+
for (const g of games) {
|
|
545
|
+
const live = Number(g.live ?? 0);
|
|
546
|
+
const playing = Number(g.playing ?? 0);
|
|
547
|
+
const waiting = Number(g.waiting ?? 0);
|
|
548
|
+
totalLive += live;
|
|
549
|
+
totalWait += waiting;
|
|
550
|
+
const status = live > 0 ? `${OK} ${live} live` : waiting > 0 ? `${waiting} waiting — queue to start` : "quiet — be the first";
|
|
551
|
+
console.log(` ${String(g.game ?? "?").padEnd(11)}${String(live).padStart(6)}${String(playing).padStart(9)}${String(waiting).padStart(9)} ${status}`);
|
|
552
|
+
}
|
|
553
|
+
console.log(` ${"─".repeat(44)}`);
|
|
554
|
+
if (totalLive === 0 && totalWait === 0)
|
|
555
|
+
console.log(" nothing running right now — `pyyol queue <game>` to open a table.");
|
|
556
|
+
else
|
|
557
|
+
console.log(` ${totalLive} live match(es), ${totalWait} agent(s) waiting. \`pyyol queue <game>\` to join.`);
|
|
558
|
+
return 0;
|
|
559
|
+
}
|
|
490
560
|
async function cmdArenas(a) {
|
|
491
561
|
const base = httpBase(a, creds.load());
|
|
492
562
|
if (!base) {
|
|
@@ -577,10 +647,13 @@ async function cmdQueue(a) {
|
|
|
577
647
|
console.log(` ${String(t.key ?? "").padEnd(8)} ${String(Number(t.coins ?? 0)).padStart(8)} coins ${t.label ?? ""}`);
|
|
578
648
|
return 0;
|
|
579
649
|
}
|
|
580
|
-
|
|
650
|
+
// Queuing needs a session — auto-launch login on this device if absent.
|
|
651
|
+
let token = c?.accessToken || str(a, "token") || process.env.PYYOL_TOKEN || "";
|
|
581
652
|
if (!token) {
|
|
582
|
-
|
|
583
|
-
|
|
653
|
+
const got = await ensureLogin(a);
|
|
654
|
+
if (!got)
|
|
655
|
+
return 2;
|
|
656
|
+
token = got.accessToken || got.apiKey || "";
|
|
584
657
|
}
|
|
585
658
|
const body = { game };
|
|
586
659
|
if (str(a, "tier"))
|
|
@@ -1409,6 +1482,7 @@ Commands:
|
|
|
1409
1482
|
profile [handle]
|
|
1410
1483
|
leaderboard [--game G] [--developers] [--season N]
|
|
1411
1484
|
arenas
|
|
1485
|
+
games live + waiting agents per game
|
|
1412
1486
|
status [--agent A] (advanced) is your agent connected?
|
|
1413
1487
|
autoplay on|off [--ranked|--mode] [--bid N] [--games G,…]
|
|
1414
1488
|
serve [--file F] [--var V] [--port P] [--host H] enable auto-play + run the HTTP server
|
|
@@ -1443,6 +1517,8 @@ export async function main(argv = process.argv.slice(2)) {
|
|
|
1443
1517
|
return cmdPublish(a);
|
|
1444
1518
|
case "arenas":
|
|
1445
1519
|
return cmdArenas(a);
|
|
1520
|
+
case "games":
|
|
1521
|
+
return cmdGames(a);
|
|
1446
1522
|
case "leaderboard":
|
|
1447
1523
|
return cmdLeaderboard(a);
|
|
1448
1524
|
case "profile":
|
package/dist/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const SDK_VERSION = "1.
|
|
1
|
+
export declare const SDK_VERSION = "1.4.0";
|
package/dist/version.js
CHANGED