@genex-ai/embed-sdk 0.17.0 → 0.21.1
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/README.md +250 -0
- package/dist/{chunk-DNLXNEPL.js → chunk-CKFZQ7AP.js} +223 -250
- package/dist/chunk-Q476GJHI.js +249 -0
- package/dist/development.d.ts +44 -0
- package/dist/development.js +99 -0
- package/dist/index.d.ts +73 -1
- package/dist/index.js +16 -1
- package/dist/sentry.js +2 -1
- package/package.json +8 -2
package/README.md
ADDED
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
# Genex embed SDK
|
|
2
|
+
|
|
3
|
+
`@genex-ai/embed-sdk` connects a game to player identity, saves, commerce and
|
|
4
|
+
player-funded generation. Initialize it with your game's slug, API URL and
|
|
5
|
+
trusted dashboard origins before using player APIs. See
|
|
6
|
+
[the play-identity contract](../../CLI_INTEGRATION.md#6-durable-game-state--leaderboards--play-identity)
|
|
7
|
+
for identity and storage.
|
|
8
|
+
|
|
9
|
+
## Generate during play
|
|
10
|
+
|
|
11
|
+
Runtime generation requires a signed-in player in a production game and an
|
|
12
|
+
enabled Genex runtime service. Each player approves their own payment on Genex.
|
|
13
|
+
The game never handles an OpenRouter key or confirms a charge itself.
|
|
14
|
+
|
|
15
|
+
```ts
|
|
16
|
+
import { generate, getGenerationModels } from '@genex-ai/embed-sdk';
|
|
17
|
+
|
|
18
|
+
// After initEmbed() and player sign-in, populate your model picker from Genex.
|
|
19
|
+
const { models } = await getGenerationModels();
|
|
20
|
+
const model = models[0];
|
|
21
|
+
|
|
22
|
+
generateButton.addEventListener('click', async () => {
|
|
23
|
+
if (!model) return;
|
|
24
|
+
const result = await generate({
|
|
25
|
+
modelId: model.id,
|
|
26
|
+
estimateCoins: 5, // Fixed price for a started attempt, chosen after benchmarking.
|
|
27
|
+
prompt: 'Invent a friendly creature. Return its name and color as JSON.',
|
|
28
|
+
outputFormat: 'json',
|
|
29
|
+
schema: {
|
|
30
|
+
type: 'object',
|
|
31
|
+
properties: { name: { type: 'string' }, color: { type: 'string' } },
|
|
32
|
+
required: ['name', 'color'],
|
|
33
|
+
additionalProperties: false,
|
|
34
|
+
},
|
|
35
|
+
allowExternal: true,
|
|
36
|
+
});
|
|
37
|
+
if (result.status === 'succeeded') {
|
|
38
|
+
// Validate the shape your game expects before rendering it as data.
|
|
39
|
+
showCreature(result.output);
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Call `generate()` directly inside the click handler: a standalone game must
|
|
45
|
+
reserve a confirmation popup before asynchronous work. Embedded games ask the
|
|
46
|
+
trusted Genex parent to show its modal. Native WebViews and local-test identity
|
|
47
|
+
return `native_unsupported` and `local_test_unsupported` until they have supported
|
|
48
|
+
confirmation surfaces.
|
|
49
|
+
|
|
50
|
+
`GenerateOptions` requires `estimateCoins` (an integer from 0 to 1,000,000), `modelId`, `prompt`, `outputFormat: 'text' | 'json'`,
|
|
51
|
+
optional bounded `schema`, `allowExternal` (default false), `idempotencyKey` and
|
|
52
|
+
`timeoutMs` (default ten minutes). Reuse an idempotency key only for the same
|
|
53
|
+
operation; store it if you need retries to survive a reload. Only models returned
|
|
54
|
+
by Genex are accepted. This first adapter generates text and JSON, including
|
|
55
|
+
creature descriptions, dialogue, rules and other structured game data.
|
|
56
|
+
|
|
57
|
+
SDK **0.21.0+** returns the execution `status`, optional `generationId`, and
|
|
58
|
+
`output` plus `source` on success. Cancellation is a normal `canceled` result,
|
|
59
|
+
but it does not imply that consumed work was free. `pending` with
|
|
60
|
+
`error: 'wait_timeout'` means the SDK stopped waiting; it does not cancel or charge
|
|
61
|
+
again. Persist `generationId` and resume with `waitForGeneration(id)`, or inspect
|
|
62
|
+
the current server state with `getGeneration(id)`. Results also carry the
|
|
63
|
+
server's `billingStatus: 'pending'|'final'`, `chargedCoins`,
|
|
64
|
+
`chargedDisplayUsdCents`, `reservedCoins` and `reservedDisplayUsdCents` when
|
|
65
|
+
available, including on failures. These USD amounts use the frozen coin value;
|
|
66
|
+
never derive them from an estimate or the current catalog. An execution can end
|
|
67
|
+
while billing remains pending. `waitForGeneration()` waits for execution;
|
|
68
|
+
continue reading `getGeneration(id)` for later billing settlement. Missing
|
|
69
|
+
receipt fields mean unavailable information, not zero cost.
|
|
70
|
+
|
|
71
|
+
The Genex modal shows the fixed attempt price, its USD equivalent, the game and
|
|
72
|
+
the frozen request before approval. New public quotes carry
|
|
73
|
+
`quote.billingPolicy: 'declared-v1'` and `kind: 'fixed'`, with
|
|
74
|
+
`maxCoins = priceCoins = estimateCoins`. Despite its name, `estimateCoins`
|
|
75
|
+
is the developer-declared **fixed price of a started attempt**: declaring 5 coins
|
|
76
|
+
charges 5 even when actual usage would cost 2. Failure, cancellation or reaching
|
|
77
|
+
the budget limit after work starts also charges the full price; a usable result
|
|
78
|
+
is not guaranteed. No model work means zero charge. Zero is accepted only for a
|
|
79
|
+
server-authorized free or personal-only option.
|
|
80
|
+
|
|
81
|
+
The provider hard budget is derived from that price after the frozen platform
|
|
82
|
+
tariff, then capped by operator limits. Output is clipped to remaining funding;
|
|
83
|
+
an input that cannot fit is refused before a call. Unresolved provider expense
|
|
84
|
+
keeps billing pending and the reservation held until verified. The trusted UI
|
|
85
|
+
must acknowledge the quote's exact `billingPolicy` at confirmation; an old UI
|
|
86
|
+
cannot approve new terms. Previously issued `consumed-v1` quotes keep actual-
|
|
87
|
+
usage billing and quotes without a policy keep their original promise.
|
|
88
|
+
|
|
89
|
+
With `allowExternal: true`, Genex can offer the configured personal plan matching
|
|
90
|
+
the selected model alongside coins: Claude for `anthropic/` models, ChatGPT for
|
|
91
|
+
`openai/` models, and neither for other models. This choice appears only in the
|
|
92
|
+
trusted Genex approval modal; never add a "Your Plan" model row in the game.
|
|
93
|
+
Each personal choice costs zero coin and its own plan and usage limits apply.
|
|
94
|
+
New quotes freeze the matching choices; connector metadata stays server-owned.
|
|
95
|
+
Old unapproved quotes are narrowed to the matching provider before confirmation;
|
|
96
|
+
approved personal requests retain their connector for recovery. Once chosen,
|
|
97
|
+
funding never switches providers or falls back to paid generation. Historical
|
|
98
|
+
personal-only offerings never gain free coin execution. Genex neither collects
|
|
99
|
+
nor hosts subscription credentials.
|
|
100
|
+
|
|
101
|
+
`source: 'external'` means user-supplied output, not proof that a particular model
|
|
102
|
+
generated it; `modelProvenance: 'unverified'` makes that explicit. Treat every generated output as data. Never execute returned code
|
|
103
|
+
or use a claimed model/source as authority to mint coins, rewards or items.
|
|
104
|
+
|
|
105
|
+
## Registered generation workflows
|
|
106
|
+
|
|
107
|
+
SDK **0.21.0+** supports multi-step generation and usage receipts through an
|
|
108
|
+
operator-registered workflow. This requires the game's trusted server executor;
|
|
109
|
+
an ordinary creator API key cannot register a workflow or dispatch its steps.
|
|
110
|
+
`generate()` and `requestWorkflow()` both require the fixed `estimateCoins`
|
|
111
|
+
price and use the declared-attempt policy above.
|
|
112
|
+
|
|
113
|
+
```ts
|
|
114
|
+
import { getWorkflowOfferings, requestWorkflow, getEmbedToken } from '@genex-ai/embed-sdk';
|
|
115
|
+
|
|
116
|
+
// Load from this game's registered workflow before enabling the model picker.
|
|
117
|
+
const catalog = await getWorkflowOfferings(configuredWorkflowId);
|
|
118
|
+
// Public offerings contain API/model rows, including sponsored free models.
|
|
119
|
+
// Personal plan funding is offered only by the trusted Genex approval modal.
|
|
120
|
+
// Keep the complete selected offering: availability, funding, model and prices.
|
|
121
|
+
renderModelPicker(catalog.offerings);
|
|
122
|
+
|
|
123
|
+
createButton.addEventListener('click', async () => {
|
|
124
|
+
// Save the selected offering, exact input and benchmarked fixed price together.
|
|
125
|
+
const { offeringId, input, estimateCoins, idempotencyKey } = pendingCreation;
|
|
126
|
+
const approval = await requestWorkflow({
|
|
127
|
+
workflowId: catalog.workflowId, offeringId, input, estimateCoins, allowExternal: true, idempotencyKey,
|
|
128
|
+
});
|
|
129
|
+
if (approval.generationId) saveGenerationId(approval.generationId);
|
|
130
|
+
if (approval.status !== 'authorized' || !approval.generationId) return;
|
|
131
|
+
// Application-specific endpoint: the game backend verifies and claims the
|
|
132
|
+
// approved Genex run, binds it to one durable job, and enqueues its executor.
|
|
133
|
+
await enqueueApprovedWorkflow({
|
|
134
|
+
generationId: approval.generationId, embedToken: getEmbedToken(), input,
|
|
135
|
+
});
|
|
136
|
+
});
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
Call `requestWorkflow()` directly from the click, before an earlier `await`, so
|
|
140
|
+
the SDK can reserve the standalone popup. It returns **approval**, not the
|
|
141
|
+
finished creature: `{ status: 'authorized'|'canceled'|'expired'|'failed'|'pending',
|
|
142
|
+
generationId?, funding?, error? }`, plus available billing receipt fields.
|
|
143
|
+
Waiting for completion before the backend
|
|
144
|
+
claims and enqueues the run would deadlock. Authorized replay also covers an
|
|
145
|
+
already-completed run, allowing the backend to recover the same job or artifact.
|
|
146
|
+
Personal-provider instructions remain open after authorization.
|
|
147
|
+
|
|
148
|
+
`input` is `{ operation: 'create'|'refactor', description, bundleId, creatureId?,
|
|
149
|
+
revisionDigest? }`; refactors require both creature identity and its revision
|
|
150
|
+
digest. Persist this input, offering and idempotency key before submission; reuse
|
|
151
|
+
them only for the same operation after sign-in or reload. Persist the returned
|
|
152
|
+
generation ID. Read with `getGeneration(id)` and wait with
|
|
153
|
+
`waitForGeneration(id)` after enqueueing. A wait timeout does not cancel work.
|
|
154
|
+
Recovering local state never starts a fresh charge without another player click.
|
|
155
|
+
Read a fresh embed token when sending an approved run to the game backend; never
|
|
156
|
+
persist or log the token.
|
|
157
|
+
|
|
158
|
+
The catalog's `estimatedCoins` and `priceCoins` are suggested price aliases,
|
|
159
|
+
and its maximum describes operator limits. Choose the game's fixed attempt price
|
|
160
|
+
after development benchmarks, pass it as `estimateCoins`, and show coin plus USD.
|
|
161
|
+
The player's final approval always uses the server quote. Preserve the selected
|
|
162
|
+
model, bundle, funding, availability and operator-owned tariff; the game cannot
|
|
163
|
+
change provider prices, dispatch costs or settlement.
|
|
164
|
+
|
|
165
|
+
For new public workflow quotes, `maxCoins` is the same fixed amount as
|
|
166
|
+
`priceCoins`, not a promise to bill actual usage. The operator-owned multiplier
|
|
167
|
+
(2 or 3, default 3) determines how much model work that fixed price can fund.
|
|
168
|
+
The whole started attempt is charged once, including failed or canceled work;
|
|
169
|
+
no model work is zero and unknown expense keeps the hold pending. Only the
|
|
170
|
+
selected model is admitted. The trusted executor validates and delivers the
|
|
171
|
+
artifact; the browser cannot settle it.
|
|
172
|
+
|
|
173
|
+
Use `resumeWorkflow(generationId, { timeoutMs? })` directly from a click to
|
|
174
|
+
reopen a saved approval. It reads the original request without creating a quote
|
|
175
|
+
or requiring a new price, including pre-0.21 consumed and legacy approvals.
|
|
176
|
+
Use `requestWorkflow()` with required `estimateCoins` for new operations.
|
|
177
|
+
|
|
178
|
+
Legacy quotes without `billingPolicy` retain their original fixed-price and
|
|
179
|
+
refund terms. Never replace a saved quote's policy with the current catalog's
|
|
180
|
+
policy, infer a missing multiplier, or reprice an approved operation.
|
|
181
|
+
|
|
182
|
+
The designated `google/gemini-3.8-flash` and `z-ai/glm-5.3-flash` offerings
|
|
183
|
+
cost **0 coins**. Personal Claude/ChatGPT funding choices in the Genex approval
|
|
184
|
+
modal also cost **0 coins** and use the player's own account through Genex-owned
|
|
185
|
+
MCP connectors. Claude uses `/player/mcp`; ChatGPT uses `/player/chatgpt/mcp`.
|
|
186
|
+
ChatGPT connector availability depends on account and workspace policy. One
|
|
187
|
+
external request may be active per player across both providers. Follow the
|
|
188
|
+
trusted instructions to fetch and submit each exact stage and attempt; no
|
|
189
|
+
subscription credentials pass through the game and no paid fallback is allowed.
|
|
190
|
+
Submitted results remain user-supplied; the executor must validate them before
|
|
191
|
+
delivery. Both APIs restrict personal funding to the selected model's provider.
|
|
192
|
+
|
|
193
|
+
These workflow endpoints still require signed-in production play, including
|
|
194
|
+
zero-coin offerings. Airena's existing sponsored free guest path is separate;
|
|
195
|
+
do not weaken the workflow's player/session checks to reproduce it.
|
|
196
|
+
|
|
197
|
+
The [runtime API contract](../../CLI_INTEGRATION.md#10-player-funded-runtime-generation)
|
|
198
|
+
describes both APIs, executor authorization, recovery and connector endpoints.
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
## Benchmark your own coin costs on the server
|
|
202
|
+
|
|
203
|
+
SDK **0.21.0+** provides `@genex-ai/embed-sdk/development`. Use it only in a
|
|
204
|
+
local Node script or trusted server with your own full creator bearer credential
|
|
205
|
+
and an owned `projectId`. It needs no production play token and cannot choose a
|
|
206
|
+
player wallet. Restricted API keys and personal-only offerings are refused.
|
|
207
|
+
Keep the credential out of game code, browser environment variables and logs;
|
|
208
|
+
the subpath is disabled for browser resolution and rejects browser execution.
|
|
209
|
+
|
|
210
|
+
`maxCoins` is an explicit positive maximum from your own wallet. Development
|
|
211
|
+
uses `consumed-v1`: actual model usage at the frozen normal tariff, including
|
|
212
|
+
failed usage, up to that maximum. Public-sponsored Gemini/GLM models also use
|
|
213
|
+
this normal paid tariff when benchmarking. Actual zero cost is zero coin;
|
|
214
|
+
unknown expense remains held. No personal or paid fallback occurs.
|
|
215
|
+
|
|
216
|
+
```ts
|
|
217
|
+
import { developmentGenerate } from '@genex-ai/embed-sdk/development';
|
|
218
|
+
|
|
219
|
+
const receipt = await developmentGenerate({
|
|
220
|
+
apiUrl: process.env.GENEX_API_URL!,
|
|
221
|
+
creatorToken: process.env.GENEX_CREATOR_TOKEN!,
|
|
222
|
+
projectId: process.env.GENEX_PROJECT_ID!,
|
|
223
|
+
maxCoins: 5,
|
|
224
|
+
request: {
|
|
225
|
+
modelId: 'your-configured-model-id',
|
|
226
|
+
prompt: 'Invent a friendly creature name.',
|
|
227
|
+
outputFormat: 'text',
|
|
228
|
+
idempotencyKey: 'calibration-sample-001',
|
|
229
|
+
},
|
|
230
|
+
});
|
|
231
|
+
// A 5-coin maximum can return chargedCoins: 2. Use repeated samples to choose
|
|
232
|
+
// the public fixed estimateCoins price; public fixed 5 still charges 5.
|
|
233
|
+
if (receipt.billingStatus === 'final') useForCalibration(receipt.chargedCoins, receipt.usage);
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
The full receipt includes execution status, output on success, charged/reserved
|
|
237
|
+
coins and USD, plus development-only `usage: { costUsdPicos, costUsd,
|
|
238
|
+
maxProviderUsdPicos, unknownProviderUsdPicos }`. Unknown cost is null rather
|
|
239
|
+
than zero; workflow cost aggregates known actual step costs and reports remaining
|
|
240
|
+
unknown exposure separately. No token counts are inferred.
|
|
241
|
+
|
|
242
|
+
For a registered workflow, call `developmentRequestWorkflow({ apiUrl,
|
|
243
|
+
creatorToken, projectId, workflowId, maxCoins, request: { offeringId, input,
|
|
244
|
+
idempotencyKey? } })`. It returns the accepted, claimed workflow immediately so
|
|
245
|
+
your trusted executor can enqueue it. After enqueueing, call
|
|
246
|
+
`waitForDevelopmentGeneration(config, id, timeoutMs?)`. Both generic and workflow
|
|
247
|
+
benchmarks are recoverable with `getDevelopmentGeneration(config, id)` and
|
|
248
|
+
`cancelDevelopmentGeneration(config, id)`. The wait ends at execution plus final
|
|
249
|
+
billing, or returns the latest server view at timeout; timeout does not cancel
|
|
250
|
+
or claim a refund. Save the operation ID and idempotency key for recovery.
|