@genex-ai/cli-demo 1.34.6-dev.713 → 1.34.6-dev.717
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 +172 -38
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -9046,7 +9046,7 @@ async function reportGlassTerminal(view, outDir, log, json) {
|
|
|
9046
9046
|
process.exitCode = 1;
|
|
9047
9047
|
}
|
|
9048
9048
|
}
|
|
9049
|
-
async function awaitAndReport(apiUrl, token, id, kind, log, open = false, json = false, local) {
|
|
9049
|
+
async function awaitAndReport(apiUrl, token, id, kind, log, open = false, json = false, local, bound) {
|
|
9050
9050
|
if (!json) log.step(waitCopy(kind));
|
|
9051
9051
|
const started = Date.now();
|
|
9052
9052
|
const view = await waitForTerminalView(
|
|
@@ -9058,9 +9058,11 @@ async function awaitAndReport(apiUrl, token, id, kind, log, open = false, json =
|
|
|
9058
9058
|
} : (p) => {
|
|
9059
9059
|
const minutes = Math.floor((Date.now() - started) / 6e4);
|
|
9060
9060
|
log.dim(` ${p}%${minutes >= 1 ? ` (${minutes} min)` : ""}`);
|
|
9061
|
-
}
|
|
9061
|
+
},
|
|
9062
|
+
bound?.timeoutMs
|
|
9062
9063
|
);
|
|
9063
9064
|
if (!view) {
|
|
9065
|
+
if (bound) return bound.onExpiry();
|
|
9064
9066
|
if (json) writeJson({ kind, id, status: "failed", error: "Timed out waiting for the generation." });
|
|
9065
9067
|
else log.error("Timed out waiting for the generation.");
|
|
9066
9068
|
process.exitCode = 1;
|
|
@@ -9088,11 +9090,18 @@ function waitCopy(kind) {
|
|
|
9088
9090
|
}
|
|
9089
9091
|
}
|
|
9090
9092
|
async function waitForTerminalView(apiUrl, token, id, kind, onProgress = () => {
|
|
9091
|
-
}) {
|
|
9092
|
-
const timeoutMs = waitTimeoutFor(kind);
|
|
9093
|
+
}, boundMs) {
|
|
9094
|
+
const timeoutMs = boundMs ?? waitTimeoutFor(kind);
|
|
9093
9095
|
const deadline = Date.now() + timeoutMs;
|
|
9094
9096
|
const streamed = await waitViaSSE(apiUrl, token, id, onProgress, deadline);
|
|
9095
|
-
|
|
9097
|
+
if (streamed !== "unsupported") return streamed;
|
|
9098
|
+
return poll(
|
|
9099
|
+
apiUrl,
|
|
9100
|
+
token,
|
|
9101
|
+
id,
|
|
9102
|
+
onProgress,
|
|
9103
|
+
boundMs === void 0 ? timeoutMs : Math.max(0, deadline - Date.now())
|
|
9104
|
+
);
|
|
9096
9105
|
}
|
|
9097
9106
|
async function reportTerminal(kind, view, log, open = false, json = false, local) {
|
|
9098
9107
|
if (view.status !== "completed") {
|
|
@@ -9378,7 +9387,9 @@ async function poll(apiUrl, token, id, onProgress, timeoutMs) {
|
|
|
9378
9387
|
}
|
|
9379
9388
|
} catch {
|
|
9380
9389
|
}
|
|
9381
|
-
|
|
9390
|
+
const remaining = deadline - Date.now();
|
|
9391
|
+
if (remaining <= 0) break;
|
|
9392
|
+
await sleep3(Math.min(3e3, remaining));
|
|
9382
9393
|
}
|
|
9383
9394
|
return null;
|
|
9384
9395
|
}
|
|
@@ -9825,6 +9836,8 @@ async function runModelAnimate(opts) {
|
|
|
9825
9836
|
|
|
9826
9837
|
// src/commands/wait.ts
|
|
9827
9838
|
import path27 from "path";
|
|
9839
|
+
var MAX_TIMEOUT_SEC = 2e6;
|
|
9840
|
+
var STILL_RUNNING_EXIT = 2;
|
|
9828
9841
|
var TERMINAL2 = /* @__PURE__ */ new Set(["completed", "failed"]);
|
|
9829
9842
|
async function runWait(opts) {
|
|
9830
9843
|
if (opts.all) return runWaitAll(opts);
|
|
@@ -9832,7 +9845,7 @@ async function runWait(opts) {
|
|
|
9832
9845
|
const id = opts.id?.trim();
|
|
9833
9846
|
if (!id) {
|
|
9834
9847
|
log.error(
|
|
9835
|
-
`Missing generation id. Usage: ${c.cyan("genex wait <id>")} \u2014 the id printed when you enqueued with --no-wait. For one status line per generation this project enqueued: ${c.cyan("genex wait --all")}.`
|
|
9848
|
+
`Missing generation id. Usage: ${c.cyan("genex wait <id>")} \u2014 the id printed when you enqueued with --no-wait. Add ${c.cyan("--status")} for one snapshot instead of a wait, or ${c.cyan("--timeout <seconds>")} to bound the wait. For one status line per generation this project enqueued: ${c.cyan("genex wait --all")}.`
|
|
9836
9849
|
);
|
|
9837
9850
|
process.exitCode = 1;
|
|
9838
9851
|
return;
|
|
@@ -9885,6 +9898,29 @@ async function runWait(opts) {
|
|
|
9885
9898
|
log.plain(c.bold("genex wait"));
|
|
9886
9899
|
log.dim(` ${kind} ${id}`);
|
|
9887
9900
|
log.plain("");
|
|
9901
|
+
const rowFor = (v) => viewRow(v, {
|
|
9902
|
+
id,
|
|
9903
|
+
kind,
|
|
9904
|
+
// A generation enqueued in some OTHER folder isn't in this ledger, so the
|
|
9905
|
+
// kind stands in for the prompt — the same substitution the local
|
|
9906
|
+
// delivery above makes.
|
|
9907
|
+
prompt: ledgerEntry?.prompt || kind,
|
|
9908
|
+
queuedAt: ledgerEntry?.queuedAt ?? ""
|
|
9909
|
+
});
|
|
9910
|
+
if (opts.status) {
|
|
9911
|
+
const row = rowFor(view);
|
|
9912
|
+
if (opts.json) {
|
|
9913
|
+
writeJson(row);
|
|
9914
|
+
} else {
|
|
9915
|
+
printStatusRow(row, log);
|
|
9916
|
+
log.plain("");
|
|
9917
|
+
log.dim(
|
|
9918
|
+
view.status === "failed" ? ` It failed \u2014 there is nothing to collect. See why with: ${c.cyan(`npx genex wait ${id}`)}` : TERMINAL2.has(view.status) ? ` Pick the asset up (URLs, and the files in a Genex Tools workspace) with: ${c.cyan(`npx genex wait ${id}`)}` : ` Still running server-side. Block until it lands with ${c.cyan(`npx genex wait ${id}`)}, or bound that with ${c.cyan("--timeout <seconds>")}.`
|
|
9919
|
+
);
|
|
9920
|
+
}
|
|
9921
|
+
if (!TERMINAL2.has(view.status)) process.exitCode = STILL_RUNNING_EXIT;
|
|
9922
|
+
return;
|
|
9923
|
+
}
|
|
9888
9924
|
if (TERMINAL2.has(view.status)) {
|
|
9889
9925
|
await reportTerminal(kind, view, log, opts.open, opts.json, local);
|
|
9890
9926
|
return;
|
|
@@ -9898,8 +9934,51 @@ async function runWait(opts) {
|
|
|
9898
9934
|
` \u23F3 Motion batches take several minutes server-side (each clip is its own job; a 16-clip walk + run set ten or more) \u2014 you don't have to sit here. Keep building and check back with ${c.cyan("genex wait --all")}.`
|
|
9899
9935
|
);
|
|
9900
9936
|
}
|
|
9937
|
+
if (opts.timeoutSec !== void 0) {
|
|
9938
|
+
const seconds = Math.min(opts.timeoutSec, MAX_TIMEOUT_SEC);
|
|
9939
|
+
const startedAt = Date.now();
|
|
9940
|
+
await awaitAndReport(apiUrl, token, id, kind, log, opts.open, opts.json, local, {
|
|
9941
|
+
timeoutMs: seconds * 1e3,
|
|
9942
|
+
onExpiry: () => reportStillRunning(apiUrl, token, id, kind, view, rowFor, log, opts, local, seconds, startedAt)
|
|
9943
|
+
});
|
|
9944
|
+
return;
|
|
9945
|
+
}
|
|
9901
9946
|
await awaitAndReport(apiUrl, token, id, kind, log, opts.open, opts.json, local);
|
|
9902
9947
|
}
|
|
9948
|
+
async function reportStillRunning(apiUrl, token, id, kind, lastKnown, rowFor, log, opts, local, seconds, startedAt) {
|
|
9949
|
+
const view = await peekGeneration(apiUrl, token, id) ?? lastKnown;
|
|
9950
|
+
if (TERMINAL2.has(view.status)) {
|
|
9951
|
+
await reportTerminal(kind, view, log, opts.open, opts.json, local);
|
|
9952
|
+
return;
|
|
9953
|
+
}
|
|
9954
|
+
const row = rowFor(view);
|
|
9955
|
+
if (opts.json) {
|
|
9956
|
+
writeJson({ ...row, timedOut: true });
|
|
9957
|
+
} else {
|
|
9958
|
+
printStatusRow(row, log);
|
|
9959
|
+
log.plain("");
|
|
9960
|
+
const waited = Math.max(0, Date.now() - startedAt) / 1e3;
|
|
9961
|
+
const shown = waited < 10 ? waited.toFixed(1) : Math.round(waited).toString();
|
|
9962
|
+
log.warn(
|
|
9963
|
+
`Stopped waiting after ${shown}s (ceiling ${seconds}s) \u2014 ${c.bold("the generation is STILL RUNNING")} server-side. Nothing was cancelled, and nothing extra was billed.`
|
|
9964
|
+
);
|
|
9965
|
+
log.dim(` Resume waiting: ${c.cyan(`npx genex wait ${id}`)}`);
|
|
9966
|
+
log.dim(` One snapshot, no waiting: ${c.cyan(`npx genex wait ${id} --status`)}`);
|
|
9967
|
+
}
|
|
9968
|
+
process.exitCode = STILL_RUNNING_EXIT;
|
|
9969
|
+
}
|
|
9970
|
+
async function peekGeneration(apiUrl, token, id) {
|
|
9971
|
+
try {
|
|
9972
|
+
const res = await apiFetch(`${apiUrl}/api/generations/${id}`, {
|
|
9973
|
+
headers: { Authorization: `Bearer ${token}` }
|
|
9974
|
+
});
|
|
9975
|
+
if (!res.ok) return null;
|
|
9976
|
+
const { generation } = await res.json();
|
|
9977
|
+
return generation;
|
|
9978
|
+
} catch {
|
|
9979
|
+
return null;
|
|
9980
|
+
}
|
|
9981
|
+
}
|
|
9903
9982
|
async function runWaitAll(opts) {
|
|
9904
9983
|
const log = createLogger({ quiet: opts.quiet || opts.json });
|
|
9905
9984
|
const cwd = opts.cwd ?? process.cwd();
|
|
@@ -9980,20 +10059,7 @@ async function runWaitAll(opts) {
|
|
|
9980
10059
|
}
|
|
9981
10060
|
log.plain(c.bold("genex wait --all"));
|
|
9982
10061
|
log.plain("");
|
|
9983
|
-
for (const r of rows)
|
|
9984
|
-
const mark = r.partial ? c.yellow("\u26A0") : r.status === "done" ? c.green("\u2713") : r.status === "failed" ? c.red("\u2717") : c.yellow("\u2026");
|
|
9985
|
-
const label = r.status === "running" && typeof r.progress === "number" ? `running ${r.progress}%` : r.partial ? "partial" : r.status;
|
|
9986
|
-
log.plain(` ${mark} ${label.padEnd(12)} ${r.kind.padEnd(8)} ${r.id} ${c.dim(`"${r.prompt.slice(0, 56)}"`)}`);
|
|
9987
|
-
if (r.partial) {
|
|
9988
|
-
log.plain(
|
|
9989
|
-
` ${c.yellow(`${r.partial.installed} of ${r.partial.requested} clips landed`)} \u2014 missing: ${r.partial.failed.join(", ")}. ${c.dim(`genex wait ${r.id}`)} names the fix.`
|
|
9990
|
-
);
|
|
9991
|
-
}
|
|
9992
|
-
if (r.status === "failed" && r.error) {
|
|
9993
|
-
for (const line of describeGenerationFailure(r.kind, r.error).lines) log.plain(` ${line}`);
|
|
9994
|
-
}
|
|
9995
|
-
if (r.status === "done" && r.mocked) log.dim(` ${MOCKED_LINE}`);
|
|
9996
|
-
}
|
|
10062
|
+
for (const r of rows) printStatusRow(r, log);
|
|
9997
10063
|
const count = (s) => rows.filter((r) => r.status === s).length;
|
|
9998
10064
|
const partial = rows.filter((r) => r.partial).length;
|
|
9999
10065
|
const billingFailed = rows.filter(
|
|
@@ -10037,6 +10103,39 @@ async function runWaitAll(opts) {
|
|
|
10037
10103
|
mode === "tools" || mode === "remix" ? " \u{1F4DC} Resumed or compacted? Re-read AGENTS.md before building on." : " \u{1F4DC} Resumed or compacted? Re-read AGENTS.md + DESIGN.md (continue from its Now: line) before building on."
|
|
10038
10104
|
);
|
|
10039
10105
|
}
|
|
10106
|
+
function printStatusRow(r, log) {
|
|
10107
|
+
const mark = r.partial ? c.yellow("\u26A0") : r.status === "done" ? c.green("\u2713") : r.status === "failed" ? c.red("\u2717") : c.yellow("\u2026");
|
|
10108
|
+
const label = r.status === "running" && typeof r.progress === "number" ? `running ${r.progress}%` : r.partial ? "partial" : r.status;
|
|
10109
|
+
log.plain(` ${mark} ${label.padEnd(12)} ${r.kind.padEnd(8)} ${r.id} ${c.dim(`"${r.prompt.slice(0, 56)}"`)}`);
|
|
10110
|
+
if (r.partial) {
|
|
10111
|
+
log.plain(
|
|
10112
|
+
` ${c.yellow(`${r.partial.installed} of ${r.partial.requested} clips landed`)} \u2014 missing: ${r.partial.failed.join(", ")}. ${c.dim(`genex wait ${r.id}`)} names the fix.`
|
|
10113
|
+
);
|
|
10114
|
+
}
|
|
10115
|
+
if (r.status === "failed" && r.error) {
|
|
10116
|
+
for (const line of describeGenerationFailure(r.kind, r.error).lines) log.plain(` ${line}`);
|
|
10117
|
+
}
|
|
10118
|
+
if (r.status === "done" && r.mocked) log.dim(` ${MOCKED_LINE}`);
|
|
10119
|
+
}
|
|
10120
|
+
function viewRow(v, base) {
|
|
10121
|
+
switch (v.status) {
|
|
10122
|
+
case "completed": {
|
|
10123
|
+
const batch = motionBatchOutcome(v);
|
|
10124
|
+
return {
|
|
10125
|
+
...base,
|
|
10126
|
+
status: "done",
|
|
10127
|
+
...v.mocked === true ? { mocked: true } : {},
|
|
10128
|
+
...batch?.partial ? { partial: { installed: batch.installed, requested: batch.requested, failed: batch.failures.map((f) => f.clip) } } : {}
|
|
10129
|
+
};
|
|
10130
|
+
}
|
|
10131
|
+
case "failed":
|
|
10132
|
+
return { ...base, status: "failed", error: v.error };
|
|
10133
|
+
case "processing":
|
|
10134
|
+
return { ...base, status: "running", progress: v.progress };
|
|
10135
|
+
default:
|
|
10136
|
+
return { ...base, status: "queued" };
|
|
10137
|
+
}
|
|
10138
|
+
}
|
|
10040
10139
|
async function toRow(e, v, cwd) {
|
|
10041
10140
|
const base = { id: e.id, kind: e.kind, prompt: e.prompt, queuedAt: e.queuedAt };
|
|
10042
10141
|
if (v) {
|
|
@@ -10049,23 +10148,7 @@ async function toRow(e, v, cwd) {
|
|
|
10049
10148
|
).catch(() => {
|
|
10050
10149
|
});
|
|
10051
10150
|
}
|
|
10052
|
-
|
|
10053
|
-
case "completed": {
|
|
10054
|
-
const batch = motionBatchOutcome(v);
|
|
10055
|
-
return {
|
|
10056
|
-
...base,
|
|
10057
|
-
status: "done",
|
|
10058
|
-
...v.mocked === true ? { mocked: true } : {},
|
|
10059
|
-
...batch?.partial ? { partial: { installed: batch.installed, requested: batch.requested, failed: batch.failures.map((f) => f.clip) } } : {}
|
|
10060
|
-
};
|
|
10061
|
-
}
|
|
10062
|
-
case "failed":
|
|
10063
|
-
return { ...base, status: "failed", error: v.error };
|
|
10064
|
-
case "processing":
|
|
10065
|
-
return { ...base, status: "running", progress: v.progress };
|
|
10066
|
-
default:
|
|
10067
|
-
return { ...base, status: "queued" };
|
|
10068
|
-
}
|
|
10151
|
+
return viewRow(v, base);
|
|
10069
10152
|
}
|
|
10070
10153
|
return { ...base, status: e.status === "completed" ? "done" : e.status === "failed" ? "failed" : "queued" };
|
|
10071
10154
|
}
|
|
@@ -23931,6 +24014,12 @@ ${c.bold("Usage")}
|
|
|
23931
24014
|
genex wait <id> Attach to a generation enqueued with --no-wait and
|
|
23932
24015
|
print its asset URL(s) when it finishes. Safe to
|
|
23933
24016
|
re-run \u2014 it never creates a new generation.
|
|
24017
|
+
--timeout <seconds> stops waiting at that ceiling:
|
|
24018
|
+
the generation keeps running, and you get its
|
|
24019
|
+
current row, the resume command, and exit 2.
|
|
24020
|
+
--status takes ONE snapshot instead of waiting at
|
|
24021
|
+
all \u2014 exit 0 if it finished, 2 if it is still going.
|
|
24022
|
+
Full page: genex wait --help.
|
|
23934
24023
|
genex wait --all One status line per generation this project has
|
|
23935
24024
|
enqueued (done/running/queued/failed) \u2014 a single
|
|
23936
24025
|
API refresh, never blocks, never bills.
|
|
@@ -24298,6 +24387,8 @@ ${c.bold("Workflow")}
|
|
|
24298
24387
|
--user-approved raises it (player's say-so first).
|
|
24299
24388
|
genex wait <id> Pick up a generation enqueued with --no-wait.
|
|
24300
24389
|
Never bills \u2014 re-running a generate command does.
|
|
24390
|
+
--timeout <seconds> bounds the wait (it keeps
|
|
24391
|
+
running; exit 2); --status is one snapshot and out.
|
|
24301
24392
|
genex wait --all One status line per generation from this folder.
|
|
24302
24393
|
genex auth [--force] Connect this machine (or switch accounts).
|
|
24303
24394
|
genex tools Re-run setup here (refresh skills + rules).
|
|
@@ -24486,6 +24577,46 @@ ${c.bold("Content filter")}
|
|
|
24486
24577
|
a body) as body horror \u2014 describe the object or machine instead: "a
|
|
24487
24578
|
statue-like figure threaded into the wall" passes where "cables entering her
|
|
24488
24579
|
spine" fails. Rejections are never retryable; reword and re-run.
|
|
24580
|
+
`,
|
|
24581
|
+
wait: `${c.bold("genex wait")} \u2014 attach to a generation already running, or just ask how it is doing.
|
|
24582
|
+
|
|
24583
|
+
${c.bold("Usage")}
|
|
24584
|
+
genex wait <id> Block until it finishes, then print its asset URL(s)
|
|
24585
|
+
(and save the files, in a Genex Tools workspace).
|
|
24586
|
+
Never creates and never bills a generation \u2014 safe
|
|
24587
|
+
to re-run.
|
|
24588
|
+
genex wait <id> --timeout <secs> The same wait, with a ceiling. On expiry it prints
|
|
24589
|
+
the generation's current row, says it is STILL
|
|
24590
|
+
RUNNING server-side, prints the command that resumes
|
|
24591
|
+
the wait, and exits 2. Nothing is cancelled.
|
|
24592
|
+
genex wait <id> --status ONE snapshot and out \u2014 no polling, no sleeping.
|
|
24593
|
+
Prints the same row. Exits 0 if the generation is
|
|
24594
|
+
terminal (completed OR failed), 2 if it is still
|
|
24595
|
+
running. Reach for this instead of hand-polling.
|
|
24596
|
+
genex wait --all One status line per generation this folder enqueued
|
|
24597
|
+
\u2014 a single API refresh, never blocks, never bills.
|
|
24598
|
+
|
|
24599
|
+
${c.bold("Exit codes")}
|
|
24600
|
+
0 finished \u2014 or, with --status, terminal (completed OR failed)
|
|
24601
|
+
1 something went wrong: unknown id, not authorized, unreachable API, or (without
|
|
24602
|
+
--status) the generation itself failed
|
|
24603
|
+
2 still running \u2014 you stopped waiting, or you only asked
|
|
24604
|
+
|
|
24605
|
+
${c.bold("Flags")}
|
|
24606
|
+
--status Wins over --timeout: it is already a zero-wait mode, so the two
|
|
24607
|
+
together is not an error, it is --status. With --all it changes
|
|
24608
|
+
nothing \u2014 that surface never blocks either way.
|
|
24609
|
+
--timeout <seconds> Bounds a blocking wait only. Ignored by --status and by --all.
|
|
24610
|
+
--json One machine-readable object: the status row for --status and for a
|
|
24611
|
+
--timeout expiry (which adds "timedOut": true), the terminal
|
|
24612
|
+
result otherwise.
|
|
24613
|
+
--open Open the finished asset in your browser.
|
|
24614
|
+
--out-dir <dir> (Genex Tools) where the saved files land. --no-download: URL only.
|
|
24615
|
+
|
|
24616
|
+
${c.bold("Why --status exists")}
|
|
24617
|
+
Without a bound this command blocks for the per-kind ceiling \u2014 up to 30 minutes on a
|
|
24618
|
+
character stage. Callers hand-polled around that, and hand-polling loses every line
|
|
24619
|
+
the wait path prints. Ask once, act on the answer, keep building.
|
|
24489
24620
|
`
|
|
24490
24621
|
};
|
|
24491
24622
|
function parseArgs(argv) {
|
|
@@ -24740,6 +24871,9 @@ function parseArgs(argv) {
|
|
|
24740
24871
|
case "--all":
|
|
24741
24872
|
parsed.options.all = true;
|
|
24742
24873
|
break;
|
|
24874
|
+
case "--status":
|
|
24875
|
+
parsed.options.status = true;
|
|
24876
|
+
break;
|
|
24743
24877
|
default: {
|
|
24744
24878
|
if (needsValue.has(arg)) {
|
|
24745
24879
|
const value = argv[i++];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@genex-ai/cli-demo",
|
|
3
|
-
"version": "1.34.6-dev.
|
|
3
|
+
"version": "1.34.6-dev.717",
|
|
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": {
|