@genex-ai/cli-demo 1.35.0-dev.741 → 1.35.0-dev.742

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
@@ -23304,7 +23304,9 @@ async function readRuntimeLane(apiUrl, token) {
23304
23304
  state,
23305
23305
  models: null,
23306
23306
  recommendedDeclaredHeadroomBps: null,
23307
- externalProviders: null
23307
+ externalProviders: null,
23308
+ total: null,
23309
+ featuredCount: null
23308
23310
  });
23309
23311
  try {
23310
23312
  const res = await apiFetch(`${apiUrl}/api/runtime/models`, {
@@ -23320,7 +23322,9 @@ async function readRuntimeLane(apiUrl, token) {
23320
23322
  state: "live",
23321
23323
  models: body.models,
23322
23324
  recommendedDeclaredHeadroomBps: typeof body.recommendedDeclaredHeadroomBps === "number" && Number.isFinite(body.recommendedDeclaredHeadroomBps) ? body.recommendedDeclaredHeadroomBps : null,
23323
- externalProviders: Array.isArray(body.externalProviders) ? body.externalProviders : null
23325
+ externalProviders: Array.isArray(body.externalProviders) ? body.externalProviders : null,
23326
+ total: typeof body.total === "number" && Number.isFinite(body.total) ? body.total : null,
23327
+ featuredCount: typeof body.featuredCount === "number" && Number.isFinite(body.featuredCount) ? body.featuredCount : null
23324
23328
  };
23325
23329
  } catch {
23326
23330
  return empty("unknown");
@@ -23457,6 +23461,8 @@ async function reportModels(apiUrl, token, opts, log, toolsOnly = false) {
23457
23461
  models: null,
23458
23462
  externalProviders: null,
23459
23463
  recommendedDeclaredHeadroomBps: null,
23464
+ total: null,
23465
+ featuredCount: null,
23460
23466
  convertHint: toolsOnly ? LLM_TOOLS_CONVERT_HINT.join(" ") : null
23461
23467
  });
23462
23468
  }
@@ -23470,9 +23476,14 @@ async function reportModels(apiUrl, token, opts, log, toolsOnly = false) {
23470
23476
  status: lane.state,
23471
23477
  error: null,
23472
23478
  enabled: lane.state === "live",
23479
+ // --json ALWAYS carries every row with its `featured` flag. The short
23480
+ // list is a rendering decision for a person reading a terminal; a program
23481
+ // reading this object gets the whole catalog and decides for itself.
23473
23482
  models: lane.models,
23474
23483
  externalProviders: lane.externalProviders,
23475
23484
  recommendedDeclaredHeadroomBps: lane.recommendedDeclaredHeadroomBps,
23485
+ total: lane.total ?? lane.models?.length ?? null,
23486
+ featuredCount: lane.featuredCount ?? (lane.models ? lane.models.filter((m) => m.featured).length : null),
23476
23487
  // Always present, `null` off a tools workspace — the same
23477
23488
  // every-key-always-present rule the other keys follow, so a reader can
23478
23489
  // tell "no hint" from "a CLI that predates the hint".
@@ -23507,12 +23518,21 @@ async function reportModels(apiUrl, token, opts, log, toolsOnly = false) {
23507
23518
  process.exitCode = 1;
23508
23519
  return;
23509
23520
  }
23510
- log.plain(` ${lane.models.length} model${lane.models.length === 1 ? "" : "s"} live:`);
23511
- for (const m of lane.models) {
23521
+ const featured = lane.models.filter((m) => m.featured);
23522
+ const shown = opts.all || featured.length === 0 ? lane.models : featured;
23523
+ const hiddenCount = lane.models.length - shown.length;
23524
+ log.plain(
23525
+ shown === lane.models ? ` ${lane.models.length} model${lane.models.length === 1 ? "" : "s"} live:` : ` ${shown.length} featured model${shown.length === 1 ? "" : "s"} of ${lane.models.length} live:`
23526
+ );
23527
+ for (const m of shown) {
23528
+ const plan = m.personalPlan ? ` \xB7 personal plan: ${m.personalPlan}` : "";
23512
23529
  log.plain(
23513
- ` ${c.cyan(m.id)} ${m.label} \u2014 ${usdPerMillion(m.inputUsdPerMillion)} in / ${usdPerMillion(m.outputUsdPerMillion)} out per million tokens`
23530
+ ` ${c.cyan(m.id)} ${m.label} \u2014 ${usdPerMillion(m.inputUsdPerMillion)} in / ${usdPerMillion(m.outputUsdPerMillion)} out per million tokens${plan}`
23514
23531
  );
23515
23532
  }
23533
+ if (hiddenCount > 0) {
23534
+ log.dim(` ${hiddenCount} more available \u2014 ${c.cyan("genex llm models --all")} to list them.`);
23535
+ }
23516
23536
  if (lane.externalProviders && lane.externalProviders.length > 0) {
23517
23537
  log.plain("");
23518
23538
  log.plain(` Personal plans offered here: ${lane.externalProviders.map((p) => p.label).join(", ")}`);
@@ -26520,6 +26540,7 @@ ${c.bold("Examples")}
26520
26540
  genex shop test sku_123
26521
26541
  genex shop remove sku_123
26522
26542
  genex llm models
26543
+ genex llm models --all
26523
26544
  genex llm bench "Reply with one short taunt." --samples 5 --max-coins 20 --user-approved
26524
26545
  genex llm price
26525
26546
  genex player install
@@ -26758,11 +26779,13 @@ ${c.bold("How the allowance works")}
26758
26779
  llm: `${c.bold("genex llm")} \u2014 in-game model calls: is the lane live, what does one call cost, what should the game declare?
26759
26780
 
26760
26781
  ${c.bold("Usage")}
26761
- genex llm models [--json] Which models this stand serves, their provider rates per
26782
+ genex llm models [--all] [--json] Which models this stand serves, their provider rates per
26762
26783
  million tokens, and the headroom it recommends over a
26763
- benchmark. Off on this stand: it says so and exits 0 \u2014
26764
- build the feature without a model rather than promising
26765
- a 404.
26784
+ benchmark. The catalog is synced from OpenRouter, so the
26785
+ FEATURED short list is printed by default and --all
26786
+ prints every row (--json always carries every row). Off
26787
+ on this stand: it says so and exits 0 \u2014 build the feature
26788
+ without a model rather than promising a 404.
26766
26789
  genex llm bench "<prompt>" --max-coins <n> --user-approved [options]
26767
26790
  Run the real model <n> times through the development
26768
26791
  lane and report what each attempt was CHARGED. Refused
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@genex-ai/cli-demo",
3
- "version": "1.35.0-dev.741",
3
+ "version": "1.35.0-dev.742",
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": {
@@ -31,24 +31,36 @@ or two per session means a grant.
31
31
  npx genex llm models
32
32
  ```
33
33
 
34
- - **live** — it prints the models this stand serves. Build the feature.
34
+ - **live** — it prints the FEATURED models this stand serves, and how many more
35
+ there are. Build the feature.
35
36
  - **off on this stand** — the routes answer 404. Build the feature behind a
36
37
  graceful `unavailable` state (the NPC uses its authored lines, the quest falls
37
38
  back to the written one) and **say so plainly in the handoff**. Never promise
38
39
  the player something that 404s.
39
40
  - **misconfigured** — say that too; it is an operator fix, not a game bug.
40
41
 
42
+ The stand's catalog is synced and filtered, so it can hold far more rows than
43
+ anyone wants to read. **Offer the featured set. Run `npx genex llm models --all`
44
+ only when the user asks for more**, and put the full list in front of them
45
+ rather than picking an obscure row for them.
46
+
41
47
  Model ids come from that command and from `getGenerationModels()` at runtime.
42
48
  Never write one into the game's source: they differ per stand, and a hardcoded
43
- id is a feature that dies on somebody else's environment.
49
+ id is a feature that dies on somebody else's environment. **A picker's label
50
+ must be the model's own `label`** — a name you invent for a row ("Fast", "Smart")
51
+ is a label that differs from the model the player is billed for.
44
52
 
45
53
  ## The SDK surface (exact — do not invent methods)
46
54
 
47
55
  From `@genex-ai/embed-sdk`, already installed. `initEmbed()` must have run and
48
56
  identity must be resolved first — `$genex-threejs-embed-auth`.
49
57
 
50
- - `getGenerationModels()` — the models this stand serves. Any picker renders
51
- from this, never from a list you wrote.
58
+ - `getGenerationModels()` — `{ models, featuredCount, … }`, featured first. Any
59
+ picker renders from this, never from a list you wrote: show the rows where
60
+ `featured` is true (or all of them when `featuredCount` is 0) and offer the
61
+ rest only if the player asks. Each row carries `label`, `vendor`,
62
+ `contextLength`, `personalPlan` and `structuredOutputs`; render `label`
63
+ verbatim, so the name on screen is the model that gets billed.
52
64
  - `generate({ modelId, prompt, outputFormat, schema?, estimateCoins,
53
65
  allowExternal?, idempotencyKey?, grantId?, timeoutMs? })` →
54
66
  `{ status, generationId, output, source, error }` plus billing fields
@@ -222,6 +234,7 @@ These are source contracts, not a claim that every stand runs this lane —
222
234
 
223
235
  - [ ] `npx genex llm models` was run and its verdict is in the handoff
224
236
  - [ ] Model ids come from `getGenerationModels()`, never from source
237
+ - [ ] The picker offers the featured set, labelled with the server's own `label`
225
238
  - [ ] `estimateCoins` came from `npx genex llm bench`, not from judgement
226
239
  - [ ] `generate()` / `requestSpendGrant()` is the first statement of a click handler
227
240
  - [ ] A repeated-call feature uses a grant; a one-off uses `generate()`
@@ -53,7 +53,11 @@ expand the offer into a pitch — one line, one question.
53
53
  which models. It answers in this folder as it is, before anything is
54
54
  converted, so it comes first: if it says the lane is off, in-game calls
55
55
  answer 404 here — tell the user so plainly, build the graceful fallback, and
56
- do not convert a folder for a feature the stand does not serve.
56
+ do not convert a folder for a feature the stand does not serve. It prints
57
+ the FEATURED models; `--all` lists the whole catalog, and you run that only
58
+ when the user asks for more. Whatever they pick, the picker in the game
59
+ shows the server's own label for it — a name you invent is a name that
60
+ differs from the model they are billed for.
57
61
  2. `npx genex init --convert` — it connects this folder to a hosted Genex game
58
62
  in place. The code, the files and this toolkit stay exactly as they are, and
59
63
  generations still land in `./assets`. It is the user's yes that runs it, so