@genex-ai/cli-demo 0.47.0-dev.74 → 0.47.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 +5 -86
- package/package.json +1 -1
- package/templates/skills/genex-ai-hud/SKILL.md +1 -1
- package/templates/skills/genex-ai-image/SKILL.md +1 -1
- package/templates/skills/genex-ai-menu/SKILL.md +1 -1
- package/templates/skills/genex-ai-model/SKILL.md +1 -1
- package/templates/skills/genex-ai-sfx/SKILL.md +1 -1
- package/templates/skills/genex-ai-skybox/SKILL.md +1 -1
- package/templates/skills/genex-ai-texture/SKILL.md +1 -1
- package/templates/skills/genex-ai-video/SKILL.md +1 -1
- package/templates/skills/genex-explore/SKILL.md +1 -1
- package/templates/skills/genex-getting-started/SKILL.md +2 -2
- package/templates/skills/genex-threejs-visual-validation/SKILL.md +5 -10
- package/templates/skills/genex-updates/SKILL.md +1 -1
package/dist/index.js
CHANGED
|
@@ -8,7 +8,7 @@ import fs from "fs";
|
|
|
8
8
|
import os from "os";
|
|
9
9
|
import path from "path";
|
|
10
10
|
import { fileURLToPath } from "url";
|
|
11
|
-
var RAW_CHANNEL = "
|
|
11
|
+
var RAW_CHANNEL = "latest";
|
|
12
12
|
var CLI_CHANNEL = RAW_CHANNEL === "dev" ? "dev" : "latest";
|
|
13
13
|
var STANDS = {
|
|
14
14
|
prod: { api: "https://api.genex.games", dashboard: "https://genex.games" },
|
|
@@ -868,49 +868,6 @@ async function writeGitignore(dir, log) {
|
|
|
868
868
|
await fs4.writeFile(file, next);
|
|
869
869
|
log.dim(`Updated .gitignore (${toAdd.join(", ")}).`);
|
|
870
870
|
}
|
|
871
|
-
var LFS_PATTERNS = [
|
|
872
|
-
// models
|
|
873
|
-
"*.glb",
|
|
874
|
-
"*.gltf",
|
|
875
|
-
"*.bin",
|
|
876
|
-
"*.vrm",
|
|
877
|
-
"*.fbx",
|
|
878
|
-
"*.obj",
|
|
879
|
-
// textures / images
|
|
880
|
-
"*.png",
|
|
881
|
-
"*.jpg",
|
|
882
|
-
"*.jpeg",
|
|
883
|
-
"*.webp",
|
|
884
|
-
"*.ktx2",
|
|
885
|
-
"*.basis",
|
|
886
|
-
"*.hdr",
|
|
887
|
-
"*.exr",
|
|
888
|
-
"*.tga",
|
|
889
|
-
// audio / video
|
|
890
|
-
"*.mp3",
|
|
891
|
-
"*.ogg",
|
|
892
|
-
"*.wav",
|
|
893
|
-
"*.m4a",
|
|
894
|
-
"*.mp4",
|
|
895
|
-
"*.webm"
|
|
896
|
-
];
|
|
897
|
-
async function writeGitattributes(dir, log) {
|
|
898
|
-
const file = path4.join(dir, ".gitattributes");
|
|
899
|
-
let content = "";
|
|
900
|
-
try {
|
|
901
|
-
content = await fs4.readFile(file, "utf8");
|
|
902
|
-
} catch {
|
|
903
|
-
}
|
|
904
|
-
const present = new Set(content.split("\n").map((l) => l.trim().split(/\s+/)[0]));
|
|
905
|
-
const toAdd = LFS_PATTERNS.filter((p) => !present.has(p));
|
|
906
|
-
if (toAdd.length === 0) return;
|
|
907
|
-
let next = content;
|
|
908
|
-
if (next.length > 0 && !next.endsWith("\n")) next += "\n";
|
|
909
|
-
if (!content.trim()) next += "# Binary game assets go to Git LFS (R2) \u2014 keeps the source push small\n";
|
|
910
|
-
next += toAdd.map((p) => `${p} filter=lfs diff=lfs merge=lfs -text`).join("\n") + "\n";
|
|
911
|
-
await fs4.writeFile(file, next);
|
|
912
|
-
log.dim(`Updated .gitattributes (${toAdd.length} binary globs \u2192 Git LFS).`);
|
|
913
|
-
}
|
|
914
871
|
|
|
915
872
|
// src/lib/store.ts
|
|
916
873
|
import fs6 from "fs/promises";
|
|
@@ -1555,28 +1512,6 @@ async function pushWorktree(cwd, pushUrl, managed, log) {
|
|
|
1555
1512
|
["node_modules/", "dist/", ".git/", ".genex/", ".env", ".env.*", "!.env.example", ""].join("\n")
|
|
1556
1513
|
);
|
|
1557
1514
|
const env = { ...base, GIT_WORK_TREE: cwd, GIT_INDEX_FILE: path10.join(gitDir, "index-source") };
|
|
1558
|
-
let lfs = (await run("git", ["lfs", "version"], base)).code !== 0 ? false : true;
|
|
1559
|
-
if (!lfs) {
|
|
1560
|
-
log.step("Installing git-lfs (keeps large binary assets out of the source push)\u2026");
|
|
1561
|
-
const [bin, args] = process.platform === "darwin" ? ["brew", ["install", "git-lfs"]] : ["sudo", ["-n", "apt-get", "install", "-y", "git-lfs"]];
|
|
1562
|
-
await run(bin, args, base);
|
|
1563
|
-
lfs = (await run("git", ["lfs", "version"], base)).code === 0;
|
|
1564
|
-
if (!lfs) {
|
|
1565
|
-
log.warn(
|
|
1566
|
-
"Couldn't install git-lfs \u2014 large binary assets won't be saved to your source (the game still publishes)."
|
|
1567
|
-
);
|
|
1568
|
-
}
|
|
1569
|
-
}
|
|
1570
|
-
if (lfs) {
|
|
1571
|
-
await writeGitattributes(cwd, log);
|
|
1572
|
-
const filters = [
|
|
1573
|
-
["filter.lfs.clean", "git-lfs clean -- %f"],
|
|
1574
|
-
["filter.lfs.smudge", "git-lfs smudge -- %f"],
|
|
1575
|
-
["filter.lfs.process", "git-lfs filter-process"],
|
|
1576
|
-
["filter.lfs.required", "true"]
|
|
1577
|
-
];
|
|
1578
|
-
for (const [key, value] of filters) await run("git", ["config", key, value], base);
|
|
1579
|
-
}
|
|
1580
1515
|
await run("git", ["add", "-A"], env);
|
|
1581
1516
|
const tree = (await run("git", ["ls-files"], env)).out.trim() ? (await run("git", ["write-tree"], env)).out.trim() : "";
|
|
1582
1517
|
if (!tree || tree === EMPTY_TREE) {
|
|
@@ -1585,10 +1520,6 @@ async function pushWorktree(cwd, pushUrl, managed, log) {
|
|
|
1585
1520
|
}
|
|
1586
1521
|
const commit = (await run("git", ["commit-tree", tree, "-m", "source"], { ...base, ...ident })).out.trim();
|
|
1587
1522
|
await run("git", ["update-ref", "refs/heads/main", commit], base);
|
|
1588
|
-
if (lfs && (await run("git", ["lfs", "push", "--all", pushUrl, "main"], base)).code !== 0) {
|
|
1589
|
-
log.error("Couldn't upload your game's binary assets to the source store.");
|
|
1590
|
-
return false;
|
|
1591
|
-
}
|
|
1592
1523
|
const push = await run(
|
|
1593
1524
|
"git",
|
|
1594
1525
|
["-c", "http.postBuffer=536870912", "push", "-q", pushUrl, "+refs/heads/main:main"],
|
|
@@ -1825,13 +1756,6 @@ function advisoryNudges(log, d) {
|
|
|
1825
1756
|
);
|
|
1826
1757
|
}
|
|
1827
1758
|
}
|
|
1828
|
-
async function firstPreviewNudge(log, cwd = process.cwd()) {
|
|
1829
|
-
const meta = await readProject(cwd);
|
|
1830
|
-
if (!meta || meta.lastDeployAt || meta.status === "published") return;
|
|
1831
|
-
log.dim(
|
|
1832
|
-
" \u279C Draft page still the placeholder? Ship the first rough build now: npx genex preview \u2014 then keep building."
|
|
1833
|
-
);
|
|
1834
|
-
}
|
|
1835
1759
|
|
|
1836
1760
|
// src/commands/publish.ts
|
|
1837
1761
|
async function runPublish(opts) {
|
|
@@ -1868,8 +1792,6 @@ async function runPublish(opts) {
|
|
|
1868
1792
|
process.exitCode = 1;
|
|
1869
1793
|
return;
|
|
1870
1794
|
}
|
|
1871
|
-
meta.lastDeployAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
1872
|
-
await writeProject(meta);
|
|
1873
1795
|
} else {
|
|
1874
1796
|
log.info("Skipping build + deploy (--no-push).");
|
|
1875
1797
|
}
|
|
@@ -1953,9 +1875,8 @@ async function runPreview(opts) {
|
|
|
1953
1875
|
const freshStatus = await fetchProjectStatus(apiUrl, token, meta.slug);
|
|
1954
1876
|
if (freshStatus && freshStatus !== meta.status) {
|
|
1955
1877
|
meta.status = freshStatus;
|
|
1878
|
+
await writeProject(meta);
|
|
1956
1879
|
}
|
|
1957
|
-
meta.lastDeployAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
1958
|
-
await writeProject(meta);
|
|
1959
1880
|
const published = meta.status === "published";
|
|
1960
1881
|
log.plain("");
|
|
1961
1882
|
if (published) {
|
|
@@ -2120,9 +2041,9 @@ async function awaitAndReport(apiUrl, token, id, kind, log) {
|
|
|
2120
2041
|
process.exitCode = 1;
|
|
2121
2042
|
return;
|
|
2122
2043
|
}
|
|
2123
|
-
|
|
2044
|
+
reportTerminal(kind, view, log);
|
|
2124
2045
|
}
|
|
2125
|
-
|
|
2046
|
+
function reportTerminal(kind, view, log) {
|
|
2126
2047
|
if (view.status !== "completed") {
|
|
2127
2048
|
log.error(`Generation ${view.status}${view.error ? `: ${view.error}` : ""}.`);
|
|
2128
2049
|
process.exitCode = 1;
|
|
@@ -2142,7 +2063,6 @@ async function reportTerminal(kind, view, log) {
|
|
|
2142
2063
|
}
|
|
2143
2064
|
log.plain("");
|
|
2144
2065
|
printHint(kind, files, log);
|
|
2145
|
-
await firstPreviewNudge(log);
|
|
2146
2066
|
}
|
|
2147
2067
|
var WAIT_TIMEOUT_MS = 10 * 60 * 1e3;
|
|
2148
2068
|
var KIND_WAIT_TIMEOUT_MS = {
|
|
@@ -2291,7 +2211,7 @@ async function runWait(opts) {
|
|
|
2291
2211
|
log.dim(` ${kind} ${id}`);
|
|
2292
2212
|
log.plain("");
|
|
2293
2213
|
if (TERMINAL2.has(view.status)) {
|
|
2294
|
-
|
|
2214
|
+
reportTerminal(kind, view, log);
|
|
2295
2215
|
return;
|
|
2296
2216
|
}
|
|
2297
2217
|
await awaitAndReport(apiUrl, token, id, kind, log);
|
|
@@ -2770,7 +2690,6 @@ async function runController(opts) {
|
|
|
2770
2690
|
for (const line of set.sketch) {
|
|
2771
2691
|
log.dim(` ${line}`);
|
|
2772
2692
|
}
|
|
2773
|
-
await firstPreviewNudge(log);
|
|
2774
2693
|
}
|
|
2775
2694
|
async function installOwnerAvatar(args) {
|
|
2776
2695
|
const { root, srcDir, apiUrl, token, log } = args;
|
package/package.json
CHANGED
|
@@ -346,7 +346,7 @@ after a bad single costs the whole chain).
|
|
|
346
346
|
|
|
347
347
|
## Troubleshooting
|
|
348
348
|
|
|
349
|
-
- **"Not authorized"** — run `npx @genex-ai/cli-demo@
|
|
349
|
+
- **"Not authorized"** — run `npx @genex-ai/cli-demo@latest init` first (it
|
|
350
350
|
writes your `GENEX_TOKEN`).
|
|
351
351
|
- **"Prompt rejected"** — the provider's content-safety filter blocked the
|
|
352
352
|
prompt. Non-retryable; rewrite the wording.
|
|
@@ -182,7 +182,7 @@ set belongs to `$genex-ai-hud` — both build on this command.
|
|
|
182
182
|
|
|
183
183
|
## Troubleshooting
|
|
184
184
|
|
|
185
|
-
- **"Not authorized"** — run `npx @genex-ai/cli-demo@
|
|
185
|
+
- **"Not authorized"** — run `npx @genex-ai/cli-demo@latest init` first (it writes your `GENEX_TOKEN`).
|
|
186
186
|
- **"Prompt rejected"** — the provider's content-safety filter blocked the prompt.
|
|
187
187
|
This is non-retryable; retrying the same wording fails again. Rewrite the prompt.
|
|
188
188
|
- **Decal is an opaque rectangle** — the image has no alpha. Regenerate with
|
|
@@ -272,7 +272,7 @@ upgrades, in order of effort:
|
|
|
272
272
|
|
|
273
273
|
## Troubleshooting
|
|
274
274
|
|
|
275
|
-
- **"Not authorized"** — run `npx @genex-ai/cli-demo@
|
|
275
|
+
- **"Not authorized"** — run `npx @genex-ai/cli-demo@latest init` first (it
|
|
276
276
|
writes your `GENEX_TOKEN`).
|
|
277
277
|
- **"Prompt rejected"** — the provider's content-safety filter blocked the
|
|
278
278
|
prompt. Non-retryable; rewrite the wording.
|
|
@@ -107,7 +107,7 @@ scene is a ghost: players and objects pass straight through it.
|
|
|
107
107
|
|
|
108
108
|
## Troubleshooting
|
|
109
109
|
|
|
110
|
-
- **"Not authorized"** — run `npx @genex-ai/cli-demo@
|
|
110
|
+
- **"Not authorized"** — run `npx @genex-ai/cli-demo@latest init` first (it writes your `GENEX_TOKEN`).
|
|
111
111
|
- **"Out of credits" (`insufficient_credits`)** — the account has no credits left for
|
|
112
112
|
this model generation. Tell the user the facts the CLI printed: their balance, this
|
|
113
113
|
generation's cost, and when their credits refill. Then offer to continue the build
|
|
@@ -72,7 +72,7 @@ Reuse one loaded `buffer` across many plays; create a fresh `Audio`/`PositionalA
|
|
|
72
72
|
|
|
73
73
|
## Troubleshooting
|
|
74
74
|
|
|
75
|
-
- **"Not authorized"** — run `npx @genex-ai/cli-demo@
|
|
75
|
+
- **"Not authorized"** — run `npx @genex-ai/cli-demo@latest init` first (it writes your `GENEX_TOKEN`).
|
|
76
76
|
- **"Out of credits" (`insufficient_credits`)** — the account has no credits left for
|
|
77
77
|
this sound generation. Tell the user the facts the CLI printed: their balance, this
|
|
78
78
|
generation's cost, and when their credits refill. Then offer to continue the build
|
|
@@ -76,7 +76,7 @@ scene.background = texture; // keep the raw texture for the visible sky
|
|
|
76
76
|
|
|
77
77
|
## Troubleshooting
|
|
78
78
|
|
|
79
|
-
- **"Not authorized"** — run `npx @genex-ai/cli-demo@
|
|
79
|
+
- **"Not authorized"** — run `npx @genex-ai/cli-demo@latest init` first (it writes your `GENEX_TOKEN`).
|
|
80
80
|
- **"Out of credits" (`insufficient_credits`)** — the account has no credits left for
|
|
81
81
|
this skybox generation. Tell the user the facts the CLI printed: their balance, this
|
|
82
82
|
generation's cost, and when their credits refill. Then offer to continue the build
|
|
@@ -81,7 +81,7 @@ scene.add(ground);
|
|
|
81
81
|
|
|
82
82
|
## Troubleshooting
|
|
83
83
|
|
|
84
|
-
- **"Not authorized"** — run `npx @genex-ai/cli-demo@
|
|
84
|
+
- **"Not authorized"** — run `npx @genex-ai/cli-demo@latest init` first (it writes your `GENEX_TOKEN`).
|
|
85
85
|
- **"Out of credits" (`insufficient_credits`)** — the account has no credits left for
|
|
86
86
|
this texture generation. Tell the user the facts the CLI printed: their balance,
|
|
87
87
|
this generation's cost, and when their credits refill. Then offer to continue the
|
|
@@ -145,7 +145,7 @@ set belongs to `$genex-ai-hud` — both build on `npx genex image`/`video`.
|
|
|
145
145
|
|
|
146
146
|
## Troubleshooting
|
|
147
147
|
|
|
148
|
-
- **"Not authorized"** — run `npx @genex-ai/cli-demo@
|
|
148
|
+
- **"Not authorized"** — run `npx @genex-ai/cli-demo@latest init` first (it writes your `GENEX_TOKEN`).
|
|
149
149
|
- **"Prompt rejected"** — the provider's content-safety filter blocked the prompt.
|
|
150
150
|
This is non-retryable; retrying the same wording fails again. Rewrite the prompt.
|
|
151
151
|
- **Nothing plays / black surface** — the first `video.play()` must run inside a user
|
|
@@ -43,7 +43,7 @@ Add `--json` for machine-readable output.
|
|
|
43
43
|
**As a NEW game (start from the whole project):**
|
|
44
44
|
|
|
45
45
|
1. `git clone <clone URL from the output> <name>` — pick a short one-word name.
|
|
46
|
-
2. `cd <name>`, then `npx @genex-ai/cli-demo@
|
|
46
|
+
2. `cd <name>`, then `npx @genex-ai/cli-demo@latest init <name>` — never use
|
|
47
47
|
`--force`. This creates your own project; the original is untouched.
|
|
48
48
|
3. `npm install`, keep `base: './'` in `vite.config`, then build your changes
|
|
49
49
|
and ship with `npx genex preview`.
|
|
@@ -125,7 +125,7 @@ and re-link the clone to the same live game:
|
|
|
125
125
|
```bash
|
|
126
126
|
git clone <the game's repo url> my-game && cd my-game
|
|
127
127
|
npm install
|
|
128
|
-
npx @genex-ai/cli-demo@
|
|
128
|
+
npx @genex-ai/cli-demo@latest link <slug> # slug = the name in the play URL
|
|
129
129
|
```
|
|
130
130
|
|
|
131
131
|
`link` never creates a project: it signs in if needed (the browser opens once)
|
|
@@ -148,7 +148,7 @@ Safe to run any time — genex-owned skills are refreshed to the latest version,
|
|
|
148
148
|
and your own files are never touched:
|
|
149
149
|
|
|
150
150
|
```bash
|
|
151
|
-
npx @genex-ai/cli-demo@
|
|
151
|
+
npx @genex-ai/cli-demo@latest init
|
|
152
152
|
```
|
|
153
153
|
|
|
154
154
|
Use `--force` only if you intentionally want your own existing files overwritten
|
|
@@ -26,16 +26,11 @@ evidence, temporal checks, budgets, and explicit rejection criteria.
|
|
|
26
26
|
|
|
27
27
|
For plain game tasks — nothing from the procedural/visual-system pack loaded —
|
|
28
28
|
this is the whole acceptance gate, and it is also the *ceiling*: a smoke check,
|
|
29
|
-
not a certification. Run it ONCE per milestone
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
tweaks (sounds, colors, tuning values), and don't try to exercise every button
|
|
35
|
-
and edge case yourself. This browser check is the only testing a game draft
|
|
36
|
-
needs: never add unit tests or a test framework to a game unless the user asks.
|
|
37
|
-
The player deciding "does it feel right?" is faster and truer than you clicking
|
|
38
|
-
everything twice.
|
|
29
|
+
not a certification. Run it ONCE per milestone to catch obvious breakage, fix
|
|
30
|
+
what's clearly broken, and hand the feel/polish judgment to the player — don't
|
|
31
|
+
loop re-testing the same build, and don't try to exercise every button and edge
|
|
32
|
+
case yourself. The player deciding "does it feel right?" is faster and truer
|
|
33
|
+
than you clicking everything twice.
|
|
39
34
|
|
|
40
35
|
1. Load the page in a real browser; the canvas renders (no black screen, no
|
|
41
36
|
console errors). For an unpublished draft, open the dev server in local
|
|
@@ -38,7 +38,7 @@ update, so update immediately.)
|
|
|
38
38
|
Run exactly the command the nudge printed, from the game project root:
|
|
39
39
|
|
|
40
40
|
```bash
|
|
41
|
-
npm i -D @genex-ai/cli-demo@
|
|
41
|
+
npm i -D @genex-ai/cli-demo@latest # the genex CLI (a dev dependency)
|
|
42
42
|
npm i @genex-ai/embed-sdk@latest # identity/saves SDK (ships inside the game)
|
|
43
43
|
npm i @genex-ai/multiplayer@latest # multiplayer SDK (only if the game uses it)
|
|
44
44
|
```
|