@genex-ai/cli-demo 1.35.2-dev.749 → 1.35.3-dev.750
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/{blender-mcp-HKT7N5BQ.js → blender-mcp-ATHMMRDU.js} +1 -1
- package/dist/{chunk-FYHYZYBC.js → chunk-2SCXGPZY.js} +1 -1
- package/dist/index.js +444 -213
- package/package.json +1 -1
- package/templates/skills/genex-game-director/SKILL.md +1 -1
- package/templates/skills/genex-llm-in-games/SKILL.md +127 -68
- package/templates/skills/genex-llm-in-games/references/pricing.md +126 -85
- package/templates/skills/genex-tool-llm/SKILL.md +11 -9
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@genex-ai/cli-demo",
|
|
3
|
-
"version": "1.35.
|
|
3
|
+
"version": "1.35.3-dev.750",
|
|
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": {
|
|
@@ -156,7 +156,7 @@ vendored code from memory of another engine.
|
|
|
156
156
|
| sound effect, one looping music bed, or a short spoken line | `$genex-ai-sfx`, `$genex-ai-music`, or `$genex-ai-voice` |
|
|
157
157
|
| requested UI/HUD/menu/interface work, a visible UI problem, or an interface you decided this game wants built with generated art | `$genex-threejs-game-ui` |
|
|
158
158
|
| selling anything for platform coin: a shop, an item catalog, boosts, cosmetics, "make it earn"; also any request for a loot box, gacha, wager, casino mechanic or donation prompt, which that skill refuses and replaces | `$genex-monetization` |
|
|
159
|
-
| the game calls a language model AT RUNTIME on the player's
|
|
159
|
+
| the game calls a language model AT RUNTIME on the player's credits, billed as used under a per-call ceiling the game benchmarks with `npx genex llm bench`: NPCs that answer in their own words, dialogue or quests written per save, a judge reading what the player typed — one-time calls, or a standing budget the player approves once. Check the lane with `npx genex llm models` before designing it in | `$genex-llm-in-games` |
|
|
160
160
|
| cinematic menu/title/pause/victory/defeat/lobby/credits video treatment | `$genex-ai-menu` |
|
|
161
161
|
| drawn HUD chrome the game's style wants—one element or a matched set of frames, masks, and icons | `$genex-ai-hud` |
|
|
162
162
|
| the game works but feels flat, floaty, or unresponsive: input response, camera, impacts, cooldowns, difficulty, fail/retry | `$genex-threejs-game-feel` |
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: genex-llm-in-games
|
|
3
|
-
description: Call a language model from inside a running game — an NPC that answers in its own words, a quest written for this save, a judge that reads what the player typed. The PLAYER pays and approves, on a Genex surface the game cannot forge. Covers the two modes (a popup per call, or one standing budget then many silent calls), benchmarking the
|
|
3
|
+
description: Call a language model from inside a running game — an NPC that answers in its own words, a quest written for this save, a judge that reads what the player typed. The PLAYER pays and approves, on a Genex surface the game cannot forge. Covers the two modes (a popup per call, or one standing budget then many silent calls), benchmarking the per-call ceiling before declaring it, the receiver pattern, and honest handling of every refusal.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Genex LLM in Games
|
|
@@ -8,10 +8,11 @@ description: Call a language model from inside a running game — an NPC that an
|
|
|
8
8
|
A Genex game can call a language model **while the player is playing** and get
|
|
9
9
|
back text or JSON. Nothing else: no images, no code execution, no tools.
|
|
10
10
|
|
|
11
|
-
**The player pays, and the player approves.** Funding is
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
11
|
+
**The player pays, and the player approves.** Funding is their Genex credits —
|
|
12
|
+
billed as used, never past the per-call ceiling your game declares — or their
|
|
13
|
+
own Claude / ChatGPT plan, chosen on a Genex-drawn surface your game cannot
|
|
14
|
+
render, skin or bypass. The game holds no provider key, sees no credential, and
|
|
15
|
+
never talks to a model vendor.
|
|
15
16
|
|
|
16
17
|
Two modes. Picking the wrong one is the most expensive mistake on this lane:
|
|
17
18
|
|
|
@@ -31,7 +32,7 @@ the scene on a scale — and not to produce words, ask the grant's classifier wi
|
|
|
31
32
|
`judge()` instead of asking `generate()` for a label. It answers typed questions
|
|
32
33
|
(`choice`, `score`, `noul`) with calibrated probabilities in about a third of a
|
|
33
34
|
second, writes no prose and cannot drift out of your options. It is grant-only
|
|
34
|
-
and billed as used: each call is a small fraction of a
|
|
35
|
+
and billed as used: each call is a small fraction of a credit and accrues on the
|
|
35
36
|
budget, so a check every turn is affordable where a generate every turn is not.
|
|
36
37
|
`generate()` for words, `judge()` for decisions; a feature often wants both —
|
|
37
38
|
the judge picks the branch, generate writes the line.
|
|
@@ -78,16 +79,19 @@ identity must be resolved first — `$genex-threejs-embed-auth`.
|
|
|
78
79
|
rest only if the player asks. Each row carries `label`, `vendor`,
|
|
79
80
|
`contextLength`, `personalPlan` and `structuredOutputs`; render `label`
|
|
80
81
|
verbatim, so the name on screen is the model that gets billed.
|
|
81
|
-
- `generate({ modelId, prompt, outputFormat, schema?,
|
|
82
|
+
- `generate({ modelId, prompt, outputFormat, schema?, maxCredits,
|
|
82
83
|
allowExternal?, idempotencyKey?, grantId?, timeoutMs? })` →
|
|
83
84
|
`{ status, generationId, output, source, error }` plus billing fields
|
|
84
|
-
(`billingStatus`, `
|
|
85
|
-
- `
|
|
86
|
-
|
|
85
|
+
(`billingStatus`, `maxCredits`, `reservedCredits`, `chargedCredits`, their
|
|
86
|
+
display-USD twins). `maxCredits` is the call's CEILING, never a price.
|
|
87
|
+
- `requestSpendGrant({ models, perCallMaxCredits, perCallEstimateCredits?,
|
|
88
|
+
disclosure: { periodLabel, estimatedCallsPerPeriod, estimatedCreditsPerPeriod },
|
|
87
89
|
maxConcurrent?, maxCallsPerMinute?, allowExternal?, judge?: { enabled,
|
|
88
90
|
estimatedCallsPerPeriod }, idempotencyKey? })` →
|
|
89
91
|
`{ status, grantId, … the limits the player approved }`; status is `active` |
|
|
90
|
-
`canceled` | `expired` | `failed` | `pending`.
|
|
92
|
+
`canceled` | `expired` | `failed` | `pending`. `perCallEstimateCredits` is the
|
|
93
|
+
honest per-call figure the disclosure is built on; left out, it is the
|
|
94
|
+
ceiling.
|
|
91
95
|
- `judge({ grantId, state, questions, idempotencyKey?, timeoutMs? })` →
|
|
92
96
|
`{ status, generationId, answers, error, billing }` — the grant's classifier,
|
|
93
97
|
answered in the same response. `questions` is 1–64 named `choice`
|
|
@@ -109,13 +113,22 @@ identity must be resolved first — `$genex-threejs-embed-auth`.
|
|
|
109
113
|
- `waitForGeneration(id)` / `getGeneration(id)` — re-attach to a call already
|
|
110
114
|
started, including after a reload.
|
|
111
115
|
- `generationErrorMessage(code)` — one player-facing sentence for an error code.
|
|
116
|
+
- `requestWorkflow(…)` — a registered workflow's own door, unchanged: keep
|
|
117
|
+
sending what that workflow's offerings ask for.
|
|
118
|
+
|
|
119
|
+
The credit names arrived in `@genex-ai/embed-sdk` 0.27.0. On `generate()`,
|
|
120
|
+
`generateStream()` and `requestSpendGrant()` the coin spellings —
|
|
121
|
+
`estimateCoins`, `perCallMaxCoins`, `perCallEstimateCoins` and
|
|
122
|
+
`disclosure.estimatedCoinsPerPeriod` — are deprecated: still accepted, and read
|
|
123
|
+
as the same numbers in credits. Write the credit names in anything new, and
|
|
124
|
+
rename them when you touch old code.
|
|
112
125
|
|
|
113
126
|
```ts
|
|
114
127
|
askButton.addEventListener('click', async () => { // a real click
|
|
115
128
|
const res = await generate({ // FIRST statement, no await before it
|
|
116
129
|
modelId, outputFormat: 'json', schema: ANSWER_SCHEMA,
|
|
117
130
|
prompt: askPrompt(npc, playerLine),
|
|
118
|
-
|
|
131
|
+
maxCredits: NPC_CALL_MAX, // benchmarked — see below
|
|
119
132
|
idempotencyKey: `npc:${npc.id}:${turnId}`,
|
|
120
133
|
});
|
|
121
134
|
applyGeneration(res); // the one writer — see below
|
|
@@ -127,40 +140,55 @@ handler, before any `await`.** The approval popup is reserved synchronously off
|
|
|
127
140
|
the gesture; an `await` in front of it loses the gesture and nothing opens.
|
|
128
141
|
`generate({ grantId })` needs no gesture at all — that is what a grant buys.
|
|
129
142
|
|
|
130
|
-
## `
|
|
143
|
+
## `maxCredits` is a ceiling, not a price
|
|
144
|
+
|
|
145
|
+
The player is billed **as used**: the call's real provider cost plus the
|
|
146
|
+
platform fee, in credits. A one-time call is captured rounded UP to a whole
|
|
147
|
+
credit when it settles; a call under a budget adds its exact fraction to the
|
|
148
|
+
budget, and the player's credits move one whole credit at a time. A failed or
|
|
149
|
+
canceled attempt is billed the work the model did; one with no model work at
|
|
150
|
+
all costs nothing.
|
|
131
151
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
152
|
+
So the game declares no price. It declares a per-call **ceiling** — `maxCredits`
|
|
153
|
+
on `generate()`, `perCallMaxCredits` on a budget — and no call is ever billed
|
|
154
|
+
past it. The ceiling has a second job: **it also decides how long the answer
|
|
155
|
+
may be**, because each call's room to answer is funded from it. A number picked
|
|
156
|
+
by feel either cuts answers off or asks the player to approve far more than a
|
|
157
|
+
call ever costs.
|
|
136
158
|
|
|
137
159
|
**Benchmark, then declare:**
|
|
138
160
|
|
|
139
161
|
```bash
|
|
140
162
|
npx genex llm bench "<the real prompt, with a real example filled in>" \
|
|
141
|
-
--schema ./answer.schema.json --samples 3 --max-
|
|
163
|
+
--schema ./answer.schema.json --samples 3 --max-credits <n> --user-approved
|
|
142
164
|
```
|
|
143
165
|
|
|
144
|
-
It runs on **your own
|
|
145
|
-
sample
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
166
|
+
It runs on **your own credits**, on the development lane, and prints what each
|
|
167
|
+
sample really cost and was charged, then the numbers to declare:
|
|
168
|
+
|
|
169
|
+
- `Declare maxCredits` — the p95 real cost with the platform fee and the
|
|
170
|
+
server's own recommended headroom applied, never below the room the answer's
|
|
171
|
+
length needs. That is `maxCredits` on every call of this prompt.
|
|
172
|
+
- `Grant perCallMaxCredits` — the same over the worst sample. That is a
|
|
173
|
+
budget's `perCallMaxCredits`; declare it verbatim rather than deriving a
|
|
174
|
+
ceiling from the charged `max`, which carries neither the headroom nor the
|
|
175
|
+
answer's length and gets the budget's calls refused.
|
|
176
|
+
- `Per-call estimate: about … credits per call` and
|
|
177
|
+
`Grant perCallEstimateCredits` — the measured average, fee included, and that
|
|
178
|
+
average rounded up to a whole credit: the honest figures a budget's disclosure
|
|
179
|
+
is built on.
|
|
180
|
+
|
|
181
|
+
Declare the printed numbers. Never guess them, never work them out from a
|
|
182
|
+
vendor's price list, never add a margin of your own. Full procedure — reading
|
|
183
|
+
p50/p95, turning the loop into disclosure numbers, re-benchmarking after a
|
|
184
|
+
prompt change — is in [references/pricing.md](references/pricing.md).
|
|
185
|
+
|
|
186
|
+
A sample cut off at your `--max-credits` is not a sample: re-run with a higher
|
|
187
|
+
one. When the bench says the answer is longer than one call on this stand may
|
|
188
|
+
produce, ask for a shorter answer. `--max-coins` is the old name of
|
|
189
|
+
`--max-credits` and still works, with a line saying so.
|
|
190
|
+
|
|
191
|
+
Only samples that **succeeded and settled** are measured. A sample the
|
|
164
192
|
provider refused at its door (`provider_http_<status>`) ran no inference and
|
|
165
193
|
cost nothing; the bench prints the code, the provider's own message and, for a
|
|
166
194
|
401 or 403, that this is the stand's provider configuration refusing the model
|
|
@@ -200,12 +228,12 @@ same object — a schema that passed the bench passes the game.
|
|
|
200
228
|
```ts
|
|
201
229
|
const grant = await requestSpendGrant({ // inside the click handler
|
|
202
230
|
models: [modelId],
|
|
203
|
-
|
|
204
|
-
|
|
231
|
+
perCallMaxCredits: NPC_GRANT_MAX, // the bench's "Grant perCallMaxCredits"
|
|
232
|
+
perCallEstimateCredits: NPC_CALL_ESTIMATE, // its "Grant perCallEstimateCredits"
|
|
205
233
|
disclosure: {
|
|
206
234
|
periodLabel: 'minute',
|
|
207
235
|
estimatedCallsPerPeriod: 10, // 5 NPCs, one decision each per 30s
|
|
208
|
-
|
|
236
|
+
estimatedCreditsPerPeriod: Math.ceil(10 * NPC_CALL_AVERAGE), // calls × the measured average
|
|
209
237
|
},
|
|
210
238
|
maxConcurrent: 2,
|
|
211
239
|
maxCallsPerMinute: 30,
|
|
@@ -217,15 +245,22 @@ await savePlayerState({ ...state, grantId: grant.grantId });
|
|
|
217
245
|
**The disclosure is computed from this game's own loop, never wished for.** Five
|
|
218
246
|
NPCs deciding once every thirty seconds is ten calls a minute — write that
|
|
219
247
|
arithmetic into `DESIGN.md` beside the feature. The player sees your estimate
|
|
220
|
-
attributed to the game, beside the platform's own worst case
|
|
221
|
-
is transparently low is a grant that dies
|
|
248
|
+
attributed to the game, beside the platform's own worst case built from
|
|
249
|
+
`perCallMaxCredits`; an estimate that is transparently low is a grant that dies
|
|
250
|
+
mid-session. Each call under the budget still declares its own `maxCredits`,
|
|
251
|
+
and it may not be above the budget's `perCallMaxCredits`:
|
|
252
|
+
|
|
253
|
+
```
|
|
254
|
+
perCallEstimateCredits ≤ perCallMaxCredits ≤ the limit the player approves
|
|
255
|
+
maxCredits on each call ≤ perCallMaxCredits
|
|
256
|
+
```
|
|
222
257
|
|
|
223
258
|
**Using the judge too?** Add `judge: { enabled: true, estimatedCallsPerPeriod }`
|
|
224
259
|
to the same request — the checks you really expect per `periodLabel`, from the
|
|
225
260
|
same loop arithmetic. The sheet tells the player the game also uses a fast
|
|
226
261
|
classifier billed as used, with the platform's own worst case beside your count.
|
|
227
|
-
A judge-only feature passes `models: []`. A budget with the judge is
|
|
228
|
-
only, and judge calls share the budget's `maxConcurrent` and
|
|
262
|
+
A judge-only feature passes `models: []`. A budget with the judge is paid from
|
|
263
|
+
the player's credits only, and judge calls share the budget's `maxConcurrent` and
|
|
229
264
|
`maxCallsPerMinute`: batch questions into one call (up to 64) rather than one
|
|
230
265
|
call per question.
|
|
231
266
|
|
|
@@ -234,7 +269,7 @@ call per question.
|
|
|
234
269
|
```ts
|
|
235
270
|
const res = await generateStream({
|
|
236
271
|
grantId, modelId, outputFormat: 'json', schema: LINE_SCHEMA, // `line` is its first property
|
|
237
|
-
prompt: npcPrompt(npc, playerLine),
|
|
272
|
+
prompt: npcPrompt(npc, playerLine), maxCredits: NPC_CALL_MAX,
|
|
238
273
|
idempotencyKey: `npc:${npc.id}:${turnId}`,
|
|
239
274
|
onPartialField: (_name, soFar) => npc.bubble.show(soFar), // provisional
|
|
240
275
|
});
|
|
@@ -244,8 +279,8 @@ applyGeneration(res); // the answer i
|
|
|
244
279
|
The pieces are provisional: a call can still fail after text has shown (the
|
|
245
280
|
model broke off, the JSON missed the schema), so the bubble shows them and
|
|
246
281
|
`applyGeneration` decides what the game keeps — the same one writer as always.
|
|
247
|
-
|
|
248
|
-
|
|
282
|
+
Ceiling, benchmark and receipt are `generate()`'s: a started stream is billed the
|
|
283
|
+
work it did even when the player walks away mid-sentence. A stream holds one
|
|
249
284
|
of the budget's `maxConcurrent` slots until it has settled. Sometimes the reply
|
|
250
285
|
arrives whole — a busy stand, a retried call, a budget on the player's own plan —
|
|
251
286
|
and `onDelta` then gets the whole text once; the game needs no second path.
|
|
@@ -263,10 +298,10 @@ Grant endings are ordinary game states with in-fiction copy, never an error toas
|
|
|
263
298
|
| `grant_stopped` | the player pressed Stop | accept silently, keep playing |
|
|
264
299
|
| `grant_expired` | 24h passed, or the session ended | as stopped; re-request on the next deliberate click |
|
|
265
300
|
| `waiting_for_plan` | their own plan is rate-limited | wait out the stated time — not a failure, and there is no paid fallback |
|
|
266
|
-
| `grant_insufficient_funds` | the
|
|
301
|
+
| `grant_insufficient_funds` | the player's credits ran out before the next call | pause the thinking NPCs, say it once, stay playable |
|
|
267
302
|
|
|
268
|
-
Draw the readout from `getSpendGrant(grantId)` — calls made,
|
|
269
|
-
remains — never from a counter the game keeps itself. A finished grant may be
|
|
303
|
+
Draw the readout from `getSpendGrant(grantId)` — calls made, credits settled,
|
|
304
|
+
what remains — never from a counter the game keeps itself. A finished grant may be
|
|
270
305
|
re-requested, but only from a **fresh deliberate click**: a silent auto-renew is
|
|
271
306
|
the exact shape a standing approval exists to prevent.
|
|
272
307
|
|
|
@@ -294,18 +329,18 @@ function applyGeneration(res) { // THE only place output becomes game state
|
|
|
294
329
|
`modelProvenance: 'unverified'` because it is user-supplied — check it exactly
|
|
295
330
|
as you would check typed player input.
|
|
296
331
|
|
|
297
|
-
## Errors land on the player's
|
|
332
|
+
## Errors land on the player's credits
|
|
298
333
|
|
|
299
334
|
There is no compensation lane, so this is all work you do before the call:
|
|
300
335
|
|
|
301
|
-
- **Validate inputs first** — a malformed prompt is still
|
|
336
|
+
- **Validate inputs first** — a malformed prompt is still billed.
|
|
302
337
|
- **Always set `schema` for `outputFormat: 'json'`** — unschema'd JSON is the
|
|
303
338
|
commonest way a call is charged and the result is unusable. Write it in the
|
|
304
339
|
accepted dialect above; a refused schema is `invalid_schema` and costs
|
|
305
340
|
nothing, but it is a feature that never runs.
|
|
306
|
-
- **Keep prompts short.** Long context is the
|
|
341
|
+
- **Keep prompts short.** Long context is most of the bill.
|
|
307
342
|
- **Never loop `generate()` without a grant**, and never retry in a loop — each
|
|
308
|
-
attempt is a separate charge.
|
|
343
|
+
attempt is a separate charge, and a one-time call is at least one whole credit.
|
|
309
344
|
- **Map every code through `generationErrorMessage(code)`** into in-fiction
|
|
310
345
|
copy. A player should never read a raw error code inside your game.
|
|
311
346
|
- **`status: 'unknown'` is not a failure.** It means the charge is not known
|
|
@@ -314,12 +349,12 @@ There is no compensation lane, so this is all work you do before the call:
|
|
|
314
349
|
|
|
315
350
|
## What the Genex side already does — do not rebuild it
|
|
316
351
|
|
|
317
|
-
The approval sheet shows the model, the prompt, the
|
|
352
|
+
The approval sheet shows the model, the prompt, the ceiling and the terms; the
|
|
318
353
|
game renders no price sheet. **Subscription funding is chosen only there** —
|
|
319
354
|
never add a "Your plan" row to the game's model picker, because a game cannot
|
|
320
355
|
offer a funding source. When the player's own watcher is online the personal-plan
|
|
321
356
|
answer arrives by itself and the game just waits, exactly as it waits for a
|
|
322
|
-
|
|
357
|
+
credit-funded call. The Genex dashboard header shows progress, active grants with
|
|
323
358
|
their spend, and a Stop; a Stop pressed there reaches the game as `grant_stopped`.
|
|
324
359
|
|
|
325
360
|
## Never
|
|
@@ -330,7 +365,8 @@ their spend, and a Stop; a Stop pressed there reaches the game as `grant_stopped
|
|
|
330
365
|
on your machine, never something a shipped build does.
|
|
331
366
|
- **Never hand-roll fetch to the runtime API** — the SDK owns the approval
|
|
332
367
|
handshake, and a hand-rolled call cannot obtain one.
|
|
333
|
-
- **Never hardcode a
|
|
368
|
+
- **Never hardcode a ceiling the bench did not print, a model id, a stand URL,
|
|
369
|
+
or a margin.**
|
|
334
370
|
- **Never let the model be an authority over money, items or rewards**
|
|
335
371
|
(`$genex-monetization` owns what may move a wallet).
|
|
336
372
|
|
|
@@ -342,14 +378,15 @@ These are source contracts, not a claim that every stand runs this lane —
|
|
|
342
378
|
- [ ] `npx genex llm models` was run and its verdict is in the handoff
|
|
343
379
|
- [ ] Model ids come from `getGenerationModels()`, never from source
|
|
344
380
|
- [ ] The picker offers the featured set, labelled with the server's own `label`
|
|
345
|
-
- [ ] `
|
|
381
|
+
- [ ] `maxCredits` — and a budget's `perCallMaxCredits` / `perCallEstimateCredits` — are the figures `npx genex llm bench` printed, verbatim — never a charged number
|
|
382
|
+
- [ ] No coin spelling (`estimateCoins`, `perCallMaxCoins`, `estimatedCoinsPerPeriod`) in new code
|
|
346
383
|
- [ ] The schema uses only the accepted dialect (no `$ref`, `pattern`, `format`, `anyOf`, `default`)
|
|
347
384
|
- [ ] A bench refused as `generation_limit` was answered with `npx genex llm status`, never a retry
|
|
348
385
|
- [ ] `generate()` / `requestSpendGrant()` is the first statement of a click handler
|
|
349
386
|
- [ ] A repeated-call feature uses a grant; a one-off uses `generate()`
|
|
350
387
|
- [ ] A decision (a label, a yes/no, a level) is a `judge()` question under the grant, not a `generate()` asked for a word
|
|
351
388
|
- [ ] Dialogue the player watches appear uses `generateStream()` under the grant; the resolved result, not the pieces, goes to `applyGeneration()`
|
|
352
|
-
- [ ] Disclosure numbers derive from the real loop and are written in `DESIGN.md`
|
|
389
|
+
- [ ] Disclosure numbers derive from the real loop and the bench's measured average, and are written in `DESIGN.md`
|
|
353
390
|
- [ ] Calls are batched and cached; nothing fires on an invisible timer
|
|
354
391
|
- [ ] Every grant-ending code has in-fiction copy and a playable fallback
|
|
355
392
|
- [ ] The in-game readout comes from `getSpendGrant()`
|
|
@@ -369,7 +406,7 @@ and the gesture was lost. Move the call to the first line of the handler.
|
|
|
369
406
|
|
|
370
407
|
**`player_wallet_required`** — ONE code for the two early dead ends: the lane
|
|
371
408
|
refuses a guest and a PREVIEW build on the same line. `waitForPlayer()` tells
|
|
372
|
-
them apart. `guest: true` — guests play but
|
|
409
|
+
them apart. `guest: true` — guests play but have no credits to spend, so show the feature
|
|
373
410
|
as sign-in-to-use rather than hiding it (`$genex-threejs-embed-auth`). Signed
|
|
374
411
|
in and still refused — this is a `genex preview` draft, which never spends:
|
|
375
412
|
check the layout there, and the call itself only after `genex promote`. The
|
|
@@ -377,13 +414,31 @@ SDK's stock sentence for this code is "Sign in to Genex to use this", which is
|
|
|
377
414
|
right for the guest and wrong on a draft, so write the in-fiction line per
|
|
378
415
|
cause rather than showing it for both.
|
|
379
416
|
|
|
380
|
-
**`grant_price_unreasonable`** —
|
|
381
|
-
|
|
417
|
+
**`grant_price_unreasonable`** — a call under the budget declared a `maxCredits`
|
|
418
|
+
above the budget's `perCallMaxCredits` (or a judge call's worst case is above
|
|
419
|
+
it). Declare the bench's `Declare maxCredits` on each call and its
|
|
420
|
+
`Grant perCallMaxCredits` on the budget — the second is never below the first.
|
|
421
|
+
|
|
422
|
+
**`insufficient_credits`** — the player's credits cannot cover this one-time
|
|
423
|
+
call's ceiling. Say it once in-fiction, keep the authored fallback, and never
|
|
424
|
+
retry in a loop; the Genex sheet already offers them a top-up. From
|
|
425
|
+
`npx genex llm bench` it is YOUR balance: the bench prints what it can spend.
|
|
426
|
+
|
|
427
|
+
**`credits_unverified`** — the player's Genex email is not verified, and credits
|
|
428
|
+
pay only for a verified account. Show the feature as verify-to-use rather than
|
|
429
|
+
hiding it; nothing was charged.
|
|
430
|
+
|
|
431
|
+
**`generation_paused`** — the platform has paused paid generation for now. Not
|
|
432
|
+
the game's fault and not the player's: keep the authored fallback, try again
|
|
433
|
+
on a later deliberate click, never in a loop.
|
|
382
434
|
|
|
383
435
|
**`judge_not_enabled`** — the budget was approved without the judge. Request a
|
|
384
436
|
new one with `judge` from the next deliberate click; never auto-renew.
|
|
385
437
|
**`judge_requires_grant`** — the judge's model was sent to `generate()` with no
|
|
386
438
|
budget; the judge is grant-only and is called with `judge()`.
|
|
439
|
+
**`judge_requires_credits`** — a judge call under a budget that is not paid
|
|
440
|
+
from the player's credits (their own plan cannot pay the judge). Request the
|
|
441
|
+
budget with `judge` and let it be credit-funded; keep the authored branch.
|
|
387
442
|
**`judge_period_limit`** — the checks reached the ceiling the player approved for
|
|
388
443
|
the period (your own `estimatedCallsPerPeriod` at the largest size): wait, and
|
|
389
444
|
if it keeps happening your declared rate is too low — fix the loop or the
|
|
@@ -408,9 +463,9 @@ stand's provider configuration refusing the model — tell the operator, and
|
|
|
408
463
|
build nothing around it in the game.
|
|
409
464
|
|
|
410
465
|
**`provider_token_limit`** — the answer was cut off: the model ran out of room
|
|
411
|
-
before it finished, and the attempt is still
|
|
412
|
-
low for the answer's length — re-benchmark and declare what the bench
|
|
413
|
-
never
|
|
466
|
+
before it finished, and the attempt is still billed. The declared `maxCredits`
|
|
467
|
+
is too low for the answer's length — re-benchmark and declare what the bench
|
|
468
|
+
prints, never a charged number — or the answer is longer than one call on this
|
|
414
469
|
stand may produce, and the fix is a shorter answer (fewer fields, shorter
|
|
415
470
|
strings, a length the prompt states).
|
|
416
471
|
|
|
@@ -422,13 +477,17 @@ the subset above; `description` and `title` are allowed.
|
|
|
422
477
|
**`grant_concurrency` / `grant_rate_limited`** — the game calls faster than the
|
|
423
478
|
grant's own limits. Batch and cache; do not raise the limits to hide it.
|
|
424
479
|
|
|
480
|
+
**`payer_busy`** — the player's account was busy on Genex for a moment and
|
|
481
|
+
nothing was charged or started. Retry once after a short pause, from the same
|
|
482
|
+
action; it is not a refusal.
|
|
483
|
+
|
|
425
484
|
**`grant_not_active`** — the saved `grantId` is finished. Clear the stored id
|
|
426
485
|
and re-request from a fresh click.
|
|
427
486
|
|
|
428
487
|
**`external_request_active`** — that player already has one personal-plan
|
|
429
|
-
request running. Wait for it; never fall back to charging
|
|
488
|
+
request running. Wait for it; never fall back to charging credits instead.
|
|
430
489
|
|
|
431
|
-
**The call is
|
|
490
|
+
**The call is billed but the result is unusable** — `outputFormat: 'json'`
|
|
432
491
|
without a `schema`. Add one; the charge already happened.
|
|
433
492
|
|
|
434
493
|
**A reload lost the answer** — `generationId` was not saved before the await, or
|