@genex-ai/cli-demo 1.9.0-dev.513 → 1.9.2-dev.515
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 +104 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -4640,6 +4640,78 @@ async function uiAudit(opts, log) {
|
|
|
4640
4640
|
if (opts.strict || hard.length > 0) process.exitCode = 1;
|
|
4641
4641
|
}
|
|
4642
4642
|
|
|
4643
|
+
// src/lib/terms.ts
|
|
4644
|
+
import readline2 from "readline";
|
|
4645
|
+
var TERMS_ERROR_CODE = "terms_acceptance_required";
|
|
4646
|
+
async function isTermsRefusal(res) {
|
|
4647
|
+
if (res.status !== 403) return false;
|
|
4648
|
+
try {
|
|
4649
|
+
const body = await res.clone().json();
|
|
4650
|
+
return body?.error === TERMS_ERROR_CODE;
|
|
4651
|
+
} catch {
|
|
4652
|
+
return false;
|
|
4653
|
+
}
|
|
4654
|
+
}
|
|
4655
|
+
function reportTermsRefusal(log, authUrl) {
|
|
4656
|
+
log.error("Your account needs to accept the current Terms before publishing.");
|
|
4657
|
+
log.dim(" Nothing was deployed, and nothing on your game changed.");
|
|
4658
|
+
if (!inHostedSession()) {
|
|
4659
|
+
log.dim(` Run ${c.cyan("npx genex accept")} to read them and agree here.`);
|
|
4660
|
+
}
|
|
4661
|
+
log.dim(` Open ${c.cyan(`${getAuthUrl(authUrl)}/terms`)} and agree, then try again.`);
|
|
4662
|
+
}
|
|
4663
|
+
function askOnStdin(question) {
|
|
4664
|
+
const rl = readline2.createInterface({ input: process.stdin, output: process.stdout });
|
|
4665
|
+
return new Promise((resolve) => {
|
|
4666
|
+
rl.question(question, (answer) => {
|
|
4667
|
+
rl.close();
|
|
4668
|
+
resolve(answer);
|
|
4669
|
+
});
|
|
4670
|
+
});
|
|
4671
|
+
}
|
|
4672
|
+
async function runAccept(opts) {
|
|
4673
|
+
const { token, log } = opts;
|
|
4674
|
+
const interactive = opts.interactive ?? Boolean(process.stdin.isTTY);
|
|
4675
|
+
const apiUrl = getApiUrl(opts.apiUrl);
|
|
4676
|
+
const web = getAuthUrl();
|
|
4677
|
+
const status = await apiFetch(`${apiUrl}/api/legal/status`, {
|
|
4678
|
+
headers: { Authorization: `Bearer ${token}` }
|
|
4679
|
+
}).catch(() => null);
|
|
4680
|
+
if (status?.ok) {
|
|
4681
|
+
const body = await status.json().catch(() => null);
|
|
4682
|
+
if (body?.accepted) {
|
|
4683
|
+
log.success("Already accepted \u2014 nothing to do.");
|
|
4684
|
+
return true;
|
|
4685
|
+
}
|
|
4686
|
+
log.plain("Before publishing, please read and agree to:");
|
|
4687
|
+
for (const doc of body?.documents ?? []) log.plain(` ${doc.title} ${c.cyan(doc.url)}`);
|
|
4688
|
+
log.plain("");
|
|
4689
|
+
}
|
|
4690
|
+
if (!interactive) {
|
|
4691
|
+
log.error("Accepting the Terms needs a person, so this cannot run unattended.");
|
|
4692
|
+
log.dim(" Agreeing is a contract, and an agent cannot do it on your behalf.");
|
|
4693
|
+
log.dim(` Open ${c.cyan(`${web}/terms`)} and agree there, then re-run your command.`);
|
|
4694
|
+
return false;
|
|
4695
|
+
}
|
|
4696
|
+
const ask = opts.ask ?? askOnStdin;
|
|
4697
|
+
const answer = (await ask("Type 'agree' to accept: ")).trim().toLowerCase();
|
|
4698
|
+
if (answer !== "agree") {
|
|
4699
|
+
log.error("Not accepted \u2014 nothing was recorded.");
|
|
4700
|
+
return false;
|
|
4701
|
+
}
|
|
4702
|
+
const res = await apiFetch(`${apiUrl}/api/legal/accept`, {
|
|
4703
|
+
method: "POST",
|
|
4704
|
+
headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/json" },
|
|
4705
|
+
body: JSON.stringify({ surface: "cli" })
|
|
4706
|
+
}).catch(() => null);
|
|
4707
|
+
if (!res?.ok) {
|
|
4708
|
+
log.error(`Couldn't record your acceptance (HTTP ${res?.status ?? "no response"}).`);
|
|
4709
|
+
return false;
|
|
4710
|
+
}
|
|
4711
|
+
log.success("Accepted. Re-run your command.");
|
|
4712
|
+
return true;
|
|
4713
|
+
}
|
|
4714
|
+
|
|
4643
4715
|
// src/lib/deploy.ts
|
|
4644
4716
|
function printMobilePreflight(files, log) {
|
|
4645
4717
|
try {
|
|
@@ -5220,6 +5292,10 @@ async function fetchPushUrl(ctx, log, expectStagingCommit) {
|
|
|
5220
5292
|
log.error(`Rate limited authorizing the source push (HTTP 429).${retryAfterHint(res)}`);
|
|
5221
5293
|
return null;
|
|
5222
5294
|
}
|
|
5295
|
+
if (await isTermsRefusal(res)) {
|
|
5296
|
+
reportTermsRefusal(log);
|
|
5297
|
+
return null;
|
|
5298
|
+
}
|
|
5223
5299
|
if (!res.ok) {
|
|
5224
5300
|
log.error(`Couldn't authorize the source push (HTTP ${res.status}).`);
|
|
5225
5301
|
return null;
|
|
@@ -6391,6 +6467,26 @@ async function runPromote(opts) {
|
|
|
6391
6467
|
await verifyGamePage({ apiUrl, slug: meta.slug, published: meta.status === "published", log });
|
|
6392
6468
|
}
|
|
6393
6469
|
|
|
6470
|
+
// src/commands/accept.ts
|
|
6471
|
+
async function runAcceptCommand(opts) {
|
|
6472
|
+
const log = createLogger({ quiet: opts.quiet });
|
|
6473
|
+
log.plain(c.bold("genex accept"));
|
|
6474
|
+
log.plain("");
|
|
6475
|
+
const token = await readUserToken(opts.envPath);
|
|
6476
|
+
if (!token) {
|
|
6477
|
+
log.error(`Not signed in. Run ${c.cyan("npx genex auth")} first.`);
|
|
6478
|
+
process.exitCode = 1;
|
|
6479
|
+
return;
|
|
6480
|
+
}
|
|
6481
|
+
const meta = await readProject();
|
|
6482
|
+
const ok = await runAccept({
|
|
6483
|
+
token,
|
|
6484
|
+
log,
|
|
6485
|
+
...meta?.apiUrl ? { apiUrl: meta.apiUrl } : {}
|
|
6486
|
+
});
|
|
6487
|
+
if (!ok) process.exitCode = 1;
|
|
6488
|
+
}
|
|
6489
|
+
|
|
6394
6490
|
// src/lib/rollback.ts
|
|
6395
6491
|
async function readPreviousVersion(apiUrl, projectId, token, log) {
|
|
6396
6492
|
let res;
|
|
@@ -6484,6 +6580,7 @@ function when(iso) {
|
|
|
6484
6580
|
const ms = Date.now() - new Date(iso).getTime();
|
|
6485
6581
|
if (!Number.isFinite(ms) || ms < 0) return "recently";
|
|
6486
6582
|
const mins = Math.round(ms / 6e4);
|
|
6583
|
+
if (mins < 1) return "just now";
|
|
6487
6584
|
if (mins < 60) return `${mins} minute${mins === 1 ? "" : "s"} ago`;
|
|
6488
6585
|
const hours = Math.round(mins / 60);
|
|
6489
6586
|
if (hours < 48) return `${hours} hour${hours === 1 ? "" : "s"} ago`;
|
|
@@ -20406,6 +20503,10 @@ ${c.bold("Usage")}
|
|
|
20406
20503
|
genex promote [options] Make the previewed build live for players. No
|
|
20407
20504
|
rebuild \u2014 the exact build you previewed.
|
|
20408
20505
|
genex publish [options] Build + push + make live, then list it in the gallery.
|
|
20506
|
+
genex accept Read the current Terms, Privacy and Content
|
|
20507
|
+
policies and agree, so publishing is allowed.
|
|
20508
|
+
Needs a real terminal: agreeing is a contract,
|
|
20509
|
+
and an agent cannot do it for you.
|
|
20409
20510
|
genex rollback [--yes] Put players back on the previous version. One
|
|
20410
20511
|
version back, instantly \u2014 your code is not
|
|
20411
20512
|
changed, only what the play URL serves.
|
|
@@ -21500,6 +21601,9 @@ async function main() {
|
|
|
21500
21601
|
case "promote":
|
|
21501
21602
|
await runPromote(parsed.options);
|
|
21502
21603
|
break;
|
|
21604
|
+
case "accept":
|
|
21605
|
+
await runAcceptCommand(parsed.options);
|
|
21606
|
+
break;
|
|
21503
21607
|
case "rollback":
|
|
21504
21608
|
await runRollback(parsed.options);
|
|
21505
21609
|
break;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@genex-ai/cli-demo",
|
|
3
|
-
"version": "1.9.
|
|
3
|
+
"version": "1.9.2-dev.515",
|
|
4
4
|
"description": "Set up your project's agent workspace (.claude/.codex/.cursor in the game folder), authorize, create a game project, generate AI assets, and publish (genex CLI).",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|