@byte_fluffy/nexra-sdk 0.1.0-alpha.5 → 0.1.0-alpha.50
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 +524 -15
- package/dist/catalog.d.ts +47 -1
- package/dist/catalog.js +10 -3
- package/dist/chunk-BS3B6F7W.js +943 -0
- package/dist/chunk-WXPCZYOK.js +62321 -0
- package/dist/errors-DJZuAKoO.d.ts +33 -0
- package/dist/index.d.ts +76 -1056
- package/dist/index.js +127 -1279
- package/dist/json-Cz0MkWQn.d.ts +11 -0
- package/dist/language.d.ts +38 -0
- package/dist/language.js +933 -0
- package/dist/media-DzOxLGs-.d.ts +343 -0
- package/dist/{index-FyUOK0F-.d.ts → media-geometry-COln1N_2.d.ts} +124 -99
- package/dist/media.d.ts +2 -0
- package/dist/media.js +26 -0
- package/dist/types.d.ts +5 -0
- package/dist/types.js +0 -0
- package/dist/voices-xyPqhQqR.d.ts +348 -0
- package/package.json +48 -1
- package/dist/chunk-2C2ZZKUC.js +0 -6724
package/README.md
CHANGED
|
@@ -9,18 +9,14 @@ npm install @byte_fluffy/nexra-sdk@next
|
|
|
9
9
|
```
|
|
10
10
|
|
|
11
11
|
```ts
|
|
12
|
-
import { createNexra, getModelSpec,
|
|
12
|
+
import { createNexra, getModelSpec, type NexraImageGenerateInput } from "@byte_fluffy/nexra-sdk";
|
|
13
13
|
|
|
14
14
|
const nexra = createNexra({ apiKey: process.env.NEXRA_API_KEY });
|
|
15
15
|
const spec = getModelSpec("openai/gpt-image-2");
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
model: spec!.id,
|
|
21
|
-
prompt: "A paper boat on a blue table",
|
|
22
|
-
resolution: "1K",
|
|
23
|
-
ratio: "1:1",
|
|
16
|
+
const input: NexraImageGenerateInput = {
|
|
17
|
+
content: [{ type: "text", text: "A paper boat on a blue table", role: "prompt" }],
|
|
18
|
+
resolution: "1k",
|
|
19
|
+
aspect_ratio: "1:1",
|
|
24
20
|
quality: "medium",
|
|
25
21
|
};
|
|
26
22
|
const quote = await nexra.catalog.quote({
|
|
@@ -28,18 +24,531 @@ const quote = await nexra.catalog.quote({
|
|
|
28
24
|
operation: "image.generate",
|
|
29
25
|
input,
|
|
30
26
|
});
|
|
31
|
-
const result = await nexra.run(spec!.id,
|
|
27
|
+
const result = await nexra.run(spec!.id, input, { quoteToken: quote.quoteToken });
|
|
32
28
|
```
|
|
33
29
|
|
|
34
|
-
|
|
30
|
+
Media apps send the versioned Nexra category contract: ordered `content` parts plus
|
|
31
|
+
the common parameters for `image.generate`, `video.generate`, `audio.generate` or
|
|
32
|
+
`image.upscale` or `video.upscale`. The server resolves the selected model component and explicitly
|
|
33
|
+
adapts that input to the channel Provider. The SDK does not expose or emulate
|
|
34
|
+
Provider-native endpoints. Protocol constants, schemas and types are also
|
|
35
|
+
available from `@byte_fluffy/nexra-sdk/media`.
|
|
35
36
|
|
|
36
37
|
The default API base URL is `https://api.nexra-ai.com/v1`. When overriding
|
|
37
38
|
`baseUrl`, include the `/v1` API prefix.
|
|
38
39
|
|
|
40
|
+
## Image and video upscale
|
|
41
|
+
|
|
42
|
+
`0.1.0-alpha.42` adds `bytedance/image-enhancement` and
|
|
43
|
+
`bytedance/video-super-resolution`. Both use the Task API and the existing
|
|
44
|
+
asset delivery lifecycle. Read the stored result from `result.assets`; wait for
|
|
45
|
+
delivery to finish before treating an output URL as permanent.
|
|
46
|
+
|
|
47
|
+
```ts
|
|
48
|
+
const image = await nexra.run("bytedance/image-enhancement", {
|
|
49
|
+
content: [{ type: "image", role: "source", source: "https://example.com/input.png" }],
|
|
50
|
+
resolution: "2k",
|
|
51
|
+
});
|
|
52
|
+
const video = await nexra.run("bytedance/video-super-resolution", {
|
|
53
|
+
content: [{ type: "video", role: "source", source: "https://example.com/input.mp4" }],
|
|
54
|
+
source_duration: 5, // Upper bound in seconds; checked before enhancement.
|
|
55
|
+
resolution: "1080p",
|
|
56
|
+
});
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Image upscale supports `144p`, `240p`, `360p`, `480p`, `540p`, `720p`,
|
|
60
|
+
`1080p`, and `2k` (default). Video upscale supports `720p`, `1080p` (default),
|
|
61
|
+
`2k`, and `4k`.
|
|
62
|
+
|
|
63
|
+
The migrated task input also accepts the existing image fields
|
|
64
|
+
`image_url`, `resolution_boundary`, `enable_hdr`, and `enable_wb`, or the video
|
|
65
|
+
fields `video_url`/`vid`, `config`, and `target.res`. Use one input contract per
|
|
66
|
+
request. Credentials, VOD space, and playback signing belong to the server channel.
|
|
67
|
+
|
|
68
|
+
## Image layer decomposition
|
|
69
|
+
|
|
70
|
+
Seedream Pro accepts one source image in `output_mode: "layers"`. Resolution is
|
|
71
|
+
`1K`, `1.5K`, or `2K`; `prompt_optimization` selects `standard` or `fast`.
|
|
72
|
+
Layers retain the source aspect ratio and use PNG for transparency.
|
|
73
|
+
|
|
74
|
+
```ts
|
|
75
|
+
import type { NexraImageLayerDecompositionOutput } from "@byte_fluffy/nexra-sdk";
|
|
76
|
+
|
|
77
|
+
const result = await nexra.tasks.run<NexraImageLayerDecompositionOutput>(
|
|
78
|
+
"bytedance/doubao-seedream-5-0-pro-260628",
|
|
79
|
+
{
|
|
80
|
+
content: [{ type: "image", source: "https://example.com/poster.png", role: "source" }],
|
|
81
|
+
output_mode: "layers",
|
|
82
|
+
resolution: "2K",
|
|
83
|
+
prompt_optimization: "standard",
|
|
84
|
+
output_format: "png",
|
|
85
|
+
},
|
|
86
|
+
{ idempotencyKey: "poster-layers-1" },
|
|
87
|
+
);
|
|
88
|
+
for (const layer of result.output.layer_decomposition.layers) {
|
|
89
|
+
const url = result.output.images[layer.image_index];
|
|
90
|
+
console.log(layer.z_index, layer.name, layer.bounding_box, url);
|
|
91
|
+
}
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
`image_index` associates metadata with the image array; `z_index` defines stacking
|
|
95
|
+
order, with zero for the background. Use `tasks.wait` when recovering an accepted
|
|
96
|
+
task. A background-delivery task is usable only when `deliveryStatus` is `ready`;
|
|
97
|
+
the stored image URLs can be reused without uploading them again. The provider's
|
|
98
|
+
Native request format remains available on its existing endpoint.
|
|
99
|
+
|
|
100
|
+
## Dolphin Seedance
|
|
101
|
+
|
|
102
|
+
`0.1.0-alpha.41` adds the independently addressable models
|
|
103
|
+
`dolphin/seedance-2-0` and `dolphin/seedance-2-5`. Each model has its own
|
|
104
|
+
availability, channel routes and prices. Select its public ID when submitting a task.
|
|
105
|
+
|
|
106
|
+
```ts
|
|
107
|
+
const nexra = createNexra({
|
|
108
|
+
apiKey: process.env.NEXRA_API_KEY,
|
|
109
|
+
baseUrl: "https://test-api.nexra-ai.com/v1",
|
|
110
|
+
});
|
|
111
|
+
const task = await nexra.tasks.create("dolphin/seedance-2-0", {
|
|
112
|
+
content: [{ type: "text", role: "prompt", text: "A paper boat on calm water" }],
|
|
113
|
+
duration: 4,
|
|
114
|
+
resolution: "480p",
|
|
115
|
+
generate_audio: false,
|
|
116
|
+
});
|
|
117
|
+
const result = await nexra.tasks.wait(task.id);
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Seedance 2.0 supports 4–15 seconds and Seedance 2.5 supports 4–30 seconds.
|
|
121
|
+
The existing ByteDance model IDs retain their own supplies and prices.
|
|
122
|
+
|
|
123
|
+
## MiniMax H3 Max
|
|
124
|
+
|
|
125
|
+
`0.1.0-alpha.49` adds the official `minimax/MiniMax-H3-Max` model. It supports
|
|
126
|
+
480P/768P output, 5–15 seconds, and image, video and audio references.
|
|
127
|
+
|
|
128
|
+
```ts
|
|
129
|
+
const model = "minimax/MiniMax-H3-Max";
|
|
130
|
+
const state = await nexra.catalog.model(model, "video.generate");
|
|
131
|
+
// The selected environment owns availability and current sale prices.
|
|
132
|
+
console.log(state.available, state.prices);
|
|
133
|
+
|
|
134
|
+
const task = await nexra.tasks.create(model, {
|
|
135
|
+
content: [{ type: "text", role: "prompt", text: "A paper boat drifts across a rain puddle." }],
|
|
136
|
+
duration: 5,
|
|
137
|
+
resolution: "480P",
|
|
138
|
+
aspect_ratio: "16:9",
|
|
139
|
+
});
|
|
140
|
+
const result = await nexra.tasks.wait(task.id);
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
Use the selected environment's published prices for estimates. The SDK's bundled
|
|
144
|
+
catalog describes the model contract; channel costs and sale prices remain in
|
|
145
|
+
the live catalog.
|
|
146
|
+
|
|
147
|
+
## Banana 2.1
|
|
148
|
+
|
|
149
|
+
Use `google/gemini-nano-banana-2.1` for Banana 2.1. The model supports
|
|
150
|
+
`1K` (default), `2K`, and `4K`, fifteen aspect ratios, and up to fourteen
|
|
151
|
+
source/reference images. It does not support `512`, `count`, or `seed`.
|
|
152
|
+
|
|
153
|
+
```ts
|
|
154
|
+
const modelId = "google/gemini-nano-banana-2.1";
|
|
155
|
+
const input: NexraImageGenerateInput = {
|
|
156
|
+
content: [{ type: "text", text: "A paper boat on a blue table", role: "prompt" }],
|
|
157
|
+
resolution: "2K",
|
|
158
|
+
aspect_ratio: "16:9",
|
|
159
|
+
};
|
|
160
|
+
const quote = await nexra.catalog.quote({ modelId, operation: "image.generate", input });
|
|
161
|
+
const result = await nexra.run(modelId, input, { quoteToken: quote.quoteToken });
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
The server also exposes the Google Native `generateContent` endpoint at
|
|
165
|
+
`/v1/projects/{project}/locations/global/publishers/google/models/gemini-nano-banana-2.1:generateContent`.
|
|
166
|
+
Use the Native `contents` and `generationConfig` payload for direct HTTP calls;
|
|
167
|
+
SDK media calls use the Nexra contract shown above.
|
|
168
|
+
|
|
169
|
+
## DeepSeek model identity correction
|
|
170
|
+
|
|
171
|
+
`0.1.0-alpha.36` replaces `ctyun/deepseek-v4-1-flash` with
|
|
172
|
+
`deepseek/deepseek-v4-1-flash`. Update model IDs in SDK calls, direct HTTP
|
|
173
|
+
requests, persisted selections and catalog caches. Upgrading the SDK does not
|
|
174
|
+
rewrite a hardcoded model ID. The previous public ID and `deepseek-v4.1-flash`
|
|
175
|
+
alias are retired; neither resolves in the new catalog.
|
|
176
|
+
|
|
177
|
+
The server rollout must apply migration `0056_deepseek_model_identity` before
|
|
178
|
+
syncing the new model definition. The model UUID, channel-specific upstream IDs,
|
|
179
|
+
routes, prices and original request history remain attached to the same model.
|
|
180
|
+
The API paths and native payload shapes remain unchanged.
|
|
181
|
+
|
|
182
|
+
## Error contract migration
|
|
183
|
+
|
|
184
|
+
`0.1.0-alpha.30` introduces the flat public error response and matching SDK
|
|
185
|
+
types and exception getters. Existing HTTP envelopes and historical Task
|
|
186
|
+
objects remain supported as described below.
|
|
187
|
+
|
|
188
|
+
New Nexra responses keep one platform request context at the root:
|
|
189
|
+
`nexraRequestId` and `nexraHttpStatus`. Platform classification is
|
|
190
|
+
`nexraError: { code, message, param? }`. Provider context uses the independent
|
|
191
|
+
root fields `upstreamHttpStatus`, `upstreamRequestId` and `upstreamError`.
|
|
192
|
+
Successful Task receipts and results can carry the platform context without
|
|
193
|
+
an error. New Task results do not duplicate the old `requestId` or `error`
|
|
194
|
+
wrapper. The SDK's exported `Task` and `TaskPage` types describe these public
|
|
195
|
+
results, not the server's internal Task read model.
|
|
196
|
+
|
|
197
|
+
`NexraApiError.status` remains the actual fetch response status. Its read-only
|
|
198
|
+
`code` getter and inherited `message` expose the server's platform classification;
|
|
199
|
+
`nexraError` retains that classification object. Both exception types expose
|
|
200
|
+
`nexraHttpStatus`, `nexraRequestId`, `upstreamHttpStatus`, `upstreamRequestId` and
|
|
201
|
+
`upstreamError`. `NexraTaskError` derives these fields and `taskId` from its
|
|
202
|
+
retained `task`, and has no fetch `status`.
|
|
203
|
+
|
|
204
|
+
Platform HTTP status and request ID describe the same originating request.
|
|
205
|
+
A failed Task can retain its original creation HTTP 202 while a later GET
|
|
206
|
+
returns HTTP 200; its provider might separately return HTTP 400. Missing origin
|
|
207
|
+
evidence is omitted, not inferred from Task failure or a later query. The
|
|
208
|
+
SDK preserves server messages and unknown code strings without localizing or
|
|
209
|
+
reclassifying them. Set `Accept-Language: zh-CN` or `en` through existing client
|
|
210
|
+
`headers` when needed.
|
|
211
|
+
|
|
212
|
+
The SDK accepts old HTTP envelopes and Task error fields internally. Deprecated
|
|
213
|
+
`requestId` and `details` exception getters return `nexraRequestId` and the
|
|
214
|
+
parameter context, without adding serialized aliases. Use `nexraError.param`
|
|
215
|
+
for new parameter handling. Public retry/category hints are removed; the SDK
|
|
216
|
+
no longer exposes `NexraApiError.retryable`.
|
|
217
|
+
|
|
218
|
+
`upstreamErrorMessage` is the original provider error text, preserving its
|
|
219
|
+
language and line breaks. It is independent of the platform classification and
|
|
220
|
+
is omitted when captured diagnostics contain no supported error text. Both SDK
|
|
221
|
+
exception types expose this field. For older stored diagnostic bodies,
|
|
222
|
+
`extractUpstreamErrorMessage(body)` uses the same extraction rules as the server.
|
|
223
|
+
|
|
224
|
+
`upstreamError` contains captured provider error content. When an older captured
|
|
225
|
+
body has its own `error` member, input normalization selects that member once;
|
|
226
|
+
otherwise it retains the complete captured error body. An already canonical
|
|
227
|
+
`upstreamError` is not unwrapped again. Provider fields named `requestId`,
|
|
228
|
+
`httpStatus`, `retryable` or `category` remain unchanged. Diagnostic flags such
|
|
229
|
+
as `upstreamRedacted`, `upstreamTruncated`, `upstreamUnavailableReason`,
|
|
230
|
+
`upstreamFormat` and `upstreamEvent` remain available when supplied by the server.
|
|
231
|
+
This diagnostic projection does not rewrite original Native HTTP responses or
|
|
232
|
+
Task outputs.
|
|
233
|
+
|
|
234
|
+
Against older servers, `tasks.get`, `list`, `watch`, `wait` and
|
|
235
|
+
`NexraTaskError.task` retain original Task/Event objects and their historical
|
|
236
|
+
fields. Only exception getters adapt the input shape; the SDK does not clean
|
|
237
|
+
returned objects or manufacture context for old successful responses.
|
|
238
|
+
|
|
239
|
+
HTTP retry behavior is unchanged: eligible HTTP 503 requests make at most three
|
|
240
|
+
attempts by default, and `maxRetries: 0` makes one attempt. Retry decisions use
|
|
241
|
+
the actual fetch status rather than platform or provider payload metadata.
|
|
242
|
+
Retried Task creation keeps the same idempotency key and payload; failed Tasks
|
|
243
|
+
throw `NexraTaskError` without submitting another generation.
|
|
244
|
+
`NexraWaitTimeoutError` remains a local wait timeout with the original `taskId`
|
|
245
|
+
and does not mean generation failed.
|
|
246
|
+
|
|
247
|
+
## Model display names
|
|
248
|
+
|
|
249
|
+
`getModelSpec`, `listModelSpecs`, `nexra.models.search`, `nexra.models.get`, and
|
|
250
|
+
`nexra.catalog.model` use the existing VibePaper product labels for known model
|
|
251
|
+
IDs, such as `Banana Pro`, `Grok Imagine`, `GPT-5.4`, and `MiniMax H3 Local`.
|
|
252
|
+
Spelling and punctuation follow the Superegg/global VibePaper catalogs rather
|
|
253
|
+
than upstream manufacturer labels. Model detail family versions follow the same
|
|
254
|
+
mapping. Models without an existing product label retain generic word spacing
|
|
255
|
+
and capitalization.
|
|
256
|
+
|
|
257
|
+
Use `formatModelDisplayName(name, { modelId })` to apply the same mapping to other
|
|
258
|
+
display labels. The one-argument form preserves known product labels and formats
|
|
259
|
+
other labels generically; it does not guess model identity from an upstream name.
|
|
260
|
+
It is available from the package root and `/catalog`. Formatting affects only
|
|
261
|
+
`displayName`: use the static catalog's `id`, model discovery's `slug`, or the
|
|
262
|
+
live catalog's `modelId` for requests, never the formatted display name.
|
|
263
|
+
|
|
264
|
+
## Live model catalog
|
|
265
|
+
|
|
266
|
+
`getModelSpec` and `listModelSpecs` read the catalog bundled with this SDK release.
|
|
267
|
+
Use `catalog.model(publicId, operation)` to read the currently published database
|
|
268
|
+
input schema, display name, sale prices and actual model revision. A successful
|
|
269
|
+
`available: false` response authoritatively confirms an unavailable or retired
|
|
270
|
+
public identity; HTTP failures throw and must preserve the last successful value.
|
|
271
|
+
An unknown identity returns 404. Model IDs are URL-encoded by the SDK.
|
|
272
|
+
|
|
273
|
+
`catalog.changes` lists lightweight public model/operation identities and their
|
|
274
|
+
latest revisions. Start with `after: "0"` for initial alignment. Keep the first
|
|
275
|
+
page's `revision` as `upper` for every remaining page and pass its opaque
|
|
276
|
+
`nextCursor`. The cursor is bound to that `after`/`upper` window. Revisions are
|
|
277
|
+
64-bit decimal strings; compare them with `BigInt`, not JavaScript numbers.
|
|
278
|
+
|
|
279
|
+
```ts
|
|
280
|
+
let after = "0";
|
|
281
|
+
let cursor: string | undefined;
|
|
282
|
+
let upper: string | undefined;
|
|
283
|
+
do {
|
|
284
|
+
const page = await nexra.catalog.changes({ after, upper, cursor });
|
|
285
|
+
upper ??= page.revision;
|
|
286
|
+
// Record changed identities for independent background model reads.
|
|
287
|
+
enqueueChanges(page.data);
|
|
288
|
+
cursor = page.nextCursor;
|
|
289
|
+
} while (cursor);
|
|
290
|
+
after = upper!;
|
|
291
|
+
|
|
292
|
+
for await (const event of nexra.catalog.events({ after, signal })) {
|
|
293
|
+
enqueueChanges(event.data);
|
|
294
|
+
after = event.revision;
|
|
295
|
+
}
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
`enqueueChanges` is application code that records the affected identities before
|
|
299
|
+
advancing the receiving cursor; it does not block on all model reads. Each model
|
|
300
|
+
response carries its own actual revision. Do not label an older response with the
|
|
301
|
+
requested target revision or let it overwrite newer state. An identity updated
|
|
302
|
+
beyond a page window's fixed upper bound appears in the next window, including
|
|
303
|
+
when its index row was replaced during pagination.
|
|
304
|
+
|
|
305
|
+
`catalog.events` opens one authenticated SSE stream, ignores heartbeats, and
|
|
306
|
+
emits complete `catalog.quote-context.changed` windows with `{ revision,
|
|
307
|
+
changedAt, data }`. Notifications wake the API instance immediately; a per-instance
|
|
308
|
+
60-second revision check recovers silent notification loss. When a stream ends or
|
|
309
|
+
throws, the application reconnects using its retained `after` cursor; the SDK
|
|
310
|
+
does not reconnect automatically. Abort the supplied signal to stop an active
|
|
311
|
+
read. Leaving the iterator cancels and releases the response stream. Keep cached
|
|
312
|
+
values and cursors separate for different API sources and authorization identities.
|
|
313
|
+
No credentials, channel costs or user discounts are included in the public events.
|
|
314
|
+
|
|
315
|
+
## Private ElevenLabs voices
|
|
316
|
+
|
|
317
|
+
Voice design uses `elevenlabs/eleven_multilingual_ttv_v2`, with exactly one prompt
|
|
318
|
+
and one script content part. Preview IDs remain in `task.output.previews`; the
|
|
319
|
+
corresponding audio is returned in the ordered persisted `task.assets` list.
|
|
320
|
+
|
|
321
|
+
```ts
|
|
322
|
+
const design = await nexra.run("elevenlabs/eleven_multilingual_ttv_v2", {
|
|
323
|
+
content: [
|
|
324
|
+
{ type: "text", role: "prompt", text: "A warm, clear and natural narrator voice." },
|
|
325
|
+
{ type: "text", role: "script", text: previewScript },
|
|
326
|
+
],
|
|
327
|
+
}, { idempotencyKey: designKey });
|
|
328
|
+
const creation = await nexra.voices.create({
|
|
329
|
+
name: "Narrator",
|
|
330
|
+
source: { kind: "design", taskId: design.task.id, previewId: selectedPreviewId },
|
|
331
|
+
}, { idempotencyKey: saveKey });
|
|
332
|
+
await nexra.tasks.wait(creation.taskId);
|
|
333
|
+
const voice = await nexra.voices.get(creation.voice.id);
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
Cloning is a voice-resource operation, not a separate vendor model. Upload owned
|
|
337
|
+
audio through `nexra.assets.upload`, then call `nexra.voices.create` with
|
|
338
|
+
`source: { kind: "clone", samples: [sample.id] }`. The service accepts one to five
|
|
339
|
+
stored audio samples totaling at most 25 MiB. Retain the sample IDs and the same
|
|
340
|
+
idempotency key when retrying a creation.
|
|
341
|
+
|
|
342
|
+
`nexra.voices.list` and `get` read current authenticated resource state. Only an
|
|
343
|
+
active voice can be used for `elevenlabs/eleven_multilingual_v2` speech, using its
|
|
344
|
+
public `voice_` ID. Creation and synthesis settle separately; creation does not
|
|
345
|
+
imply verification or support for renewal, deletion, or voice conversion.
|
|
346
|
+
|
|
347
|
+
Applications using a shared API key must enforce their own end-user ownership
|
|
348
|
+
before reading or consuming a resource; API-key ownership covers the Nexra
|
|
349
|
+
account, not an application's individual users. Published model choices are
|
|
350
|
+
available through `nexra.models.resources(modelId, resource)`.
|
|
351
|
+
|
|
39
352
|
Static catalog APIs are also available from `@byte_fluffy/nexra-sdk/catalog`.
|
|
40
353
|
Exact non-negative decimal helpers are available from
|
|
41
354
|
`@byte_fluffy/nexra-sdk/decimal`.
|
|
42
355
|
|
|
356
|
+
The static catalog includes 14 Agnes and CTYun image/video model
|
|
357
|
+
contracts. A catalog entry describes parameters; it does not grant access to a
|
|
358
|
+
private model or publish a sale price. Check the selected environment's model
|
|
359
|
+
listing and current prices before submitting a task.
|
|
360
|
+
|
|
361
|
+
Agnes Video 2.5 Flash uses the same video Task input format as Seedance, with
|
|
362
|
+
model-specific limits: `resolution: "720P"`, integer `duration` from 4 to 12,
|
|
363
|
+
up to 5 reference images and 3 reference audio clips, and no video references.
|
|
364
|
+
Keyframes use image content parts with `role: "first_frame"` or `"last_frame"`;
|
|
365
|
+
they cannot be combined with reference media in the same request.
|
|
366
|
+
|
|
367
|
+
```ts
|
|
368
|
+
const flashInput = {
|
|
369
|
+
content: [{ type: "text", text: "A paper boat floats across a sunlit pond", role: "prompt" }],
|
|
370
|
+
duration: 4,
|
|
371
|
+
resolution: "720P",
|
|
372
|
+
aspect_ratio: "16:9",
|
|
373
|
+
};
|
|
374
|
+
const flashQuote = await nexra.catalog.quote({
|
|
375
|
+
modelId: "agnes/agnes-video-2-5-flash",
|
|
376
|
+
operation: "video.generate",
|
|
377
|
+
input: flashInput,
|
|
378
|
+
});
|
|
379
|
+
const flashResult = await nexra.run("agnes/agnes-video-2-5-flash", flashInput, {
|
|
380
|
+
quoteToken: flashQuote.quoteToken,
|
|
381
|
+
});
|
|
382
|
+
```
|
|
383
|
+
|
|
384
|
+
## Native language models
|
|
385
|
+
|
|
386
|
+
The optional `@byte_fluffy/nexra-sdk/language` entrypoint returns AI SDK
|
|
387
|
+
`LanguageModelV4` models. Install its optional provider peers when using this
|
|
388
|
+
entrypoint; the core SDK and media entrypoints do not load them. These provider
|
|
389
|
+
versions require Node.js 22 or a supported Bun runtime:
|
|
390
|
+
|
|
391
|
+
```sh
|
|
392
|
+
npm install @ai-sdk/provider@^4.0.2 @ai-sdk/provider-utils@^5.0.21 \
|
|
393
|
+
@ai-sdk/openai@^4.0.11 @ai-sdk/anthropic@^4.0.30 @ai-sdk/google@^4.0.12 ai@^7
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
```ts
|
|
397
|
+
import { generateText, streamText } from "ai";
|
|
398
|
+
import { getLanguageModelBinding } from "@byte_fluffy/nexra-sdk/catalog";
|
|
399
|
+
import { createNexraLanguageModel } from "@byte_fluffy/nexra-sdk/language";
|
|
400
|
+
|
|
401
|
+
const modelId = "openai/gpt-6-sol";
|
|
402
|
+
const binding = getLanguageModelBinding(modelId);
|
|
403
|
+
const model = createNexraLanguageModel(modelId, {
|
|
404
|
+
apiKey: process.env.NEXRA_API_KEY!,
|
|
405
|
+
});
|
|
406
|
+
|
|
407
|
+
if (binding.supportsStreaming) {
|
|
408
|
+
const result = streamText({ model, prompt: "Explain a paper boat", maxRetries: 0 });
|
|
409
|
+
for await (const text of result.textStream) process.stdout.write(text);
|
|
410
|
+
} else {
|
|
411
|
+
const result = await generateText({ model, prompt: "Explain a paper boat", maxRetries: 0 });
|
|
412
|
+
console.log(result.text);
|
|
413
|
+
}
|
|
414
|
+
```
|
|
415
|
+
|
|
416
|
+
The binding selects a declared native endpoint, preferring Gemini, Responses,
|
|
417
|
+
Chat Completions, then Messages. Pass `protocol` to choose another endpoint
|
|
418
|
+
declared by that model. Native endpoint `inputSchema` and `outputSchema` describe
|
|
419
|
+
wire parameters; language operation schemas may describe Playground inputs.
|
|
420
|
+
`binding.maxOutputTokens` is the lower of the model capability and selected
|
|
421
|
+
native endpoint limit. Messages requests validate the combined visible and
|
|
422
|
+
thinking token budget before sending; explicit budgets are never clamped.
|
|
423
|
+
The SDK does not wrap text requests in media Tasks or retry generations.
|
|
424
|
+
|
|
425
|
+
Messages, tool history and ordered content parts use the AI SDK prompt contract.
|
|
426
|
+
Chat Completions supports declared image/video/audio URLs and inline MP3, WAV,
|
|
427
|
+
AAC and M4A audio without downloading URLs or changing codecs. Native model results and stream finish events retain `usage.raw`, including
|
|
428
|
+
cache and modality details. With AI SDK 7, read `result.finalStep.usage.raw`
|
|
429
|
+
or each step callback's usage. Aggregate `result.usage` and `totalUsage` do not
|
|
430
|
+
retain raw records.
|
|
431
|
+
|
|
432
|
+
Chat native extension fields are passed under `providerOptions.nexra`;
|
|
433
|
+
Responses uses `openai`, Messages uses `anthropic`, and Gemini uses `google`.
|
|
434
|
+
Explicit provider options are preserved. Model identity and prompt/stream
|
|
435
|
+
fields stay owned by the SDK. Kimi K2.5 currently declares synchronous Chat
|
|
436
|
+
Completions only, so use `generateText` for that model.
|
|
437
|
+
|
|
438
|
+
Responses defaults to `store: false` in this SDK so each request replays the full
|
|
439
|
+
conversation and encrypted reasoning instead of relying on stored item IDs.
|
|
440
|
+
Pass `providerOptions.openai.store: true` explicitly for a stored conversation.
|
|
441
|
+
The current Responses provider cannot preserve sampling parameters alongside
|
|
442
|
+
reasoning for canonical Nexra IDs. Explicit `temperature` or `topP` therefore
|
|
443
|
+
fails before sending instead of being silently discarded. A caller may select
|
|
444
|
+
`forceReasoning: false` for sampling without explicit reasoning controls.
|
|
445
|
+
The documented provider version floors are tested; Anthropic budget validation
|
|
446
|
+
uses its exported capability helper and the shared provider budget mapper.
|
|
447
|
+
|
|
448
|
+
Use `resolveNexraLanguageReasoning(modelId, { enabled: false })` from `/catalog`
|
|
449
|
+
for a quiet generation policy. Its `providerOptions` select a declared off mode
|
|
450
|
+
or the model's minimum reasoning effort; `canDisable` distinguishes those cases.
|
|
451
|
+
An explicit AI SDK `reasoning: "none"` is rejected when the native model requires
|
|
452
|
+
reasoning, rather than being changed silently. Explicit provider options take
|
|
453
|
+
precedence over shared reasoning defaults.
|
|
454
|
+
|
|
455
|
+
GPT-6 Sol and GPT-6 Luna are included in the language model catalog. Sale prices
|
|
456
|
+
are not bundled into the SDK; use the current prices published by the selected
|
|
457
|
+
Nexra environment:
|
|
458
|
+
|
|
459
|
+
```ts
|
|
460
|
+
const { prices } = await nexra.catalog.listPrices();
|
|
461
|
+
const gpt6Prices = prices.filter(({ modelId }) =>
|
|
462
|
+
modelId === "openai/gpt-6-sol" || modelId === "openai/gpt-6-luna"
|
|
463
|
+
);
|
|
464
|
+
```
|
|
465
|
+
|
|
466
|
+
## Ark web search (Responses)
|
|
467
|
+
|
|
468
|
+
Available since SDK `0.1.0-alpha.47` (`npm install @byte_fluffy/nexra-sdk@next`).
|
|
469
|
+
|
|
470
|
+
DeepSeek V4.1 Flash (`deepseek/deepseek-v4-1-flash`), GLM 5.3 Flash
|
|
471
|
+
(`z-ai/glm-5-3-flash`), Doubao Seed 2.1 Lite
|
|
472
|
+
(`bytedance/doubao-seed-2-1-lite-260915`), and Kimi K3.1 Pro
|
|
473
|
+
(`moonshot-ai/kimi-k3-1-pro`) support the Ark online content plugin through
|
|
474
|
+
`/v1/responses`. The default SDK binding selects this endpoint. All four retain
|
|
475
|
+
explicit Chat Completions bindings; DeepSeek also retains Messages.
|
|
476
|
+
Search is a provider-executed tool, rather than a Chat `web_search_options` flag.
|
|
477
|
+
|
|
478
|
+
```ts
|
|
479
|
+
import { generateText } from "ai";
|
|
480
|
+
import { openai } from "@ai-sdk/openai";
|
|
481
|
+
import { createNexraLanguageModel } from "@byte_fluffy/nexra-sdk/language";
|
|
482
|
+
|
|
483
|
+
const result = await generateText({
|
|
484
|
+
model: createNexraLanguageModel("deepseek/deepseek-v4-1-flash", {
|
|
485
|
+
apiKey: process.env.NEXRA_API_KEY!,
|
|
486
|
+
baseUrl: "https://vip-api.nexra-ai.com/v1",
|
|
487
|
+
}),
|
|
488
|
+
prompt: "Search for the official DeepSeek website and cite its URL.",
|
|
489
|
+
tools: { web_search: openai.tools.webSearch() },
|
|
490
|
+
providerOptions: {
|
|
491
|
+
openai: { maxToolCalls: 1 },
|
|
492
|
+
nexra: { web_search: { sources: ["search_engine"], max_keyword: 1, limit: 3 } },
|
|
493
|
+
},
|
|
494
|
+
maxOutputTokens: 512,
|
|
495
|
+
maxRetries: 0,
|
|
496
|
+
});
|
|
497
|
+
console.log(result.text, result.sources);
|
|
498
|
+
```
|
|
499
|
+
|
|
500
|
+
`providerOptions.nexra.web_search` preserves native tool fields such as `sources`,
|
|
501
|
+
`max_keyword`, `limit`, and `user_location`; it requires the `web_search` tool.
|
|
502
|
+
The same options work with `streamText`. Unpositioned native citations become
|
|
503
|
+
URL sources; original Native bodies, raw stream events, and
|
|
504
|
+
`finalStep.usage.raw.tool_usage_details.web_search` remain available.
|
|
505
|
+
|
|
506
|
+
VIP configured search prices (CNY, checked 2026-11-01):
|
|
507
|
+
|
|
508
|
+
| Content source | Channel cost / 1,000 uses | Nexra sale / 1,000 uses |
|
|
509
|
+
| --- | ---: | ---: |
|
|
510
|
+
| `search_engine` (default) | ¥4 | **¥4.4** |
|
|
511
|
+
| `toutiao`, `douyin`, `moji` (each additional source) | ¥6 | ¥6.6 |
|
|
512
|
+
|
|
513
|
+
A use is an actual upstream content-source search, **not an HTTP request or a
|
|
514
|
+
returned result**. Multiple rounds, keywords, or content sources can incur
|
|
515
|
+
multiple uses. Token charges are additional, including retrieved context.
|
|
516
|
+
Declaring a tool does not itself incur a search fee if the model does not use
|
|
517
|
+
it. Preauthorization reserves the configured search ceiling and settles the
|
|
518
|
+
actual evidenced usage; set `maxToolCalls` and `max_keyword` to control that
|
|
519
|
+
ceiling. Missing search evidence is not treated as free search.
|
|
520
|
+
|
|
521
|
+
Current VIP token sale prices per million tokens:
|
|
522
|
+
|
|
523
|
+
| Model | Input | Cached input | Output |
|
|
524
|
+
| --- | ---: | ---: | ---: |
|
|
525
|
+
| DeepSeek V4.1 Flash | ¥2.2 | ¥0.044 | ¥8.8 |
|
|
526
|
+
| GLM 5.3 Flash | ¥0.88 | ¥0.253 | ¥3.08 |
|
|
527
|
+
| Kimi K3.1 Pro | ¥14.3 | ¥1.43 | ¥74.8 |
|
|
528
|
+
| Doubao Seed 2.1 Lite (non-audio input) | ¥0.88 | ¥0.176 | ¥2.97 |
|
|
529
|
+
|
|
530
|
+
Seed audio input is ¥13.2/million tokens; cached audio input is ¥2.64/million.
|
|
531
|
+
For Ark audio/video prompts in the AI SDK adapter, select
|
|
532
|
+
`protocol: "openai-chat-completions"`; its native media parts retain their order. Kimi media requires bytes or Base64
|
|
533
|
+
data URLs; the Chat binding derives URL support from the Native schema.
|
|
534
|
+
The Responses search example above uses text. Native Responses media fields
|
|
535
|
+
remain documented by each model's selected endpoint schema.
|
|
536
|
+
|
|
537
|
+
GLM and Kimi K3.1 Pro thinking is always on. Use `reasoning: "low"` for minimum effort;
|
|
538
|
+
`reasoning: "none"` fails locally. Native `none`/`minimal` effort aliases do not
|
|
539
|
+
mean that these models can turn thinking off. Kimi does not use a `thinking`
|
|
540
|
+
parameter. Its Responses endpoint permits `toolChoice: "auto"` (default) or
|
|
541
|
+
`"none"`; forcing a particular tool or requiring a tool is rejected before
|
|
542
|
+
fetch. With auto selection, search is billed only when actually used.
|
|
543
|
+
|
|
544
|
+
These are the configured channel prices;
|
|
545
|
+
the SDK does not dynamically apply upstream off-peak discounts. Provider account
|
|
546
|
+
free quotas do not automatically make Nexra requests free. The selected plugin
|
|
547
|
+
is separate from Doubao Search Custom; no Custom search service is used here.
|
|
548
|
+
Always read the selected environment's live catalog prices before estimating
|
|
549
|
+
charges. Official references: [online content plugin pricing](https://ark.volcengine.com/region:cn-beijing/docs/online-content-plugin-pricing)
|
|
550
|
+
and [model pricing](https://console.volcengine.com/ark/region:cn-beijing/docs/model-pricing).
|
|
551
|
+
|
|
43
552
|
## Directory layout
|
|
44
553
|
|
|
45
554
|
```
|
|
@@ -48,7 +557,8 @@ src/
|
|
|
48
557
|
catalog/
|
|
49
558
|
index.ts CatalogClient, getModelSpec, listModelSpecs
|
|
50
559
|
generated/ Generated artifacts (committed; required to publish)
|
|
51
|
-
image.generated.json
|
|
560
|
+
image.generated.json Image model specs
|
|
561
|
+
language.generated.json Text/language model specs
|
|
52
562
|
index.ts Imports every kind JSON and exports the merged array
|
|
53
563
|
generated/
|
|
54
564
|
version.generated.ts SDK_VERSION used by the transport
|
|
@@ -58,12 +568,11 @@ scripts/
|
|
|
58
568
|
src/catalog/generated/*
|
|
59
569
|
```
|
|
60
570
|
|
|
61
|
-
### Adding a
|
|
571
|
+
### Adding a model spec
|
|
62
572
|
|
|
63
|
-
1. Add its ID to `
|
|
573
|
+
1. Add its ID to `SDK_MODEL_IDS` in `scripts/generate-public-catalog.ts`.
|
|
64
574
|
2. Run `bun run generate` (from `packages/sdk`).
|
|
65
575
|
3. The script groups projected models by `model.kind`, writes one
|
|
66
576
|
`src/catalog/generated/<kind>.generated.json` per kind (new kinds appear
|
|
67
577
|
automatically), regenerates the merging `index.ts`, and bumps
|
|
68
578
|
`src/generated/version.generated.ts`. No hand-written code changes.
|
|
69
|
-
|
package/dist/catalog.d.ts
CHANGED
|
@@ -1 +1,47 @@
|
|
|
1
|
-
|
|
1
|
+
import { a as JsonObject } from './json-Cz0MkWQn.js';
|
|
2
|
+
import { H as HttpTransport, N as NexraCatalogChangeParams, a as NexraCatalogChangePage, b as NexraCatalogModelState, c as NexraSalePriceList, C as CreateNexraQuoteRequest, d as NexraQuote, e as CreateNexraDisplayQuoteBatchRequest, f as NexraDisplayQuoteBatch, g as NexraCatalogRevision, h as NexraModelSpec, i as NexraModelEndpointSpec, j as NexraModelSpecFilter } from './media-geometry-COln1N_2.js';
|
|
3
|
+
export { M as MediaGeometryField, k as MediaGeometryProjection, l as NexraBillingCurrency, m as NexraCatalogModelIdentity, n as NexraModelOperation, o as NexraSalePrice, p as NexraSettlement, U as UnifiedMediaGeometry, q as applyMediaGeometry, r as decodeMediaGeometry, s as encodeMediaGeometry, t as projectMediaGeometry } from './media-geometry-COln1N_2.js';
|
|
4
|
+
|
|
5
|
+
declare function formatModelDisplayName(displayName: string, identity?: {
|
|
6
|
+
modelId: string;
|
|
7
|
+
}): string;
|
|
8
|
+
|
|
9
|
+
declare class CatalogClient {
|
|
10
|
+
private readonly transport;
|
|
11
|
+
constructor(transport: HttpTransport);
|
|
12
|
+
changes(params?: NexraCatalogChangeParams, signal?: AbortSignal): Promise<NexraCatalogChangePage>;
|
|
13
|
+
model(modelId: string, operation: string, signal?: AbortSignal): Promise<NexraCatalogModelState>;
|
|
14
|
+
events(options?: {
|
|
15
|
+
after?: string;
|
|
16
|
+
signal?: AbortSignal;
|
|
17
|
+
}): AsyncGenerator<NexraCatalogChangePage>;
|
|
18
|
+
listPrices(signal?: AbortSignal): Promise<NexraSalePriceList>;
|
|
19
|
+
quote(request: CreateNexraQuoteRequest, signal?: AbortSignal): Promise<NexraQuote>;
|
|
20
|
+
quoteBatch(request: CreateNexraDisplayQuoteBatchRequest, signal?: AbortSignal): Promise<NexraDisplayQuoteBatch>;
|
|
21
|
+
revision(signal?: AbortSignal): Promise<NexraCatalogRevision>;
|
|
22
|
+
}
|
|
23
|
+
declare function getModelSpec(modelId: string): NexraModelSpec | undefined;
|
|
24
|
+
declare function listModelSpecs(filter?: NexraModelSpecFilter): readonly NexraModelSpec[];
|
|
25
|
+
type NexraLanguageProtocol = "gemini-generate-content" | "openai-responses" | "openai-chat-completions" | "anthropic-messages";
|
|
26
|
+
type NexraLanguageModelBinding = Readonly<{
|
|
27
|
+
spec: NexraModelSpec;
|
|
28
|
+
endpoint: NexraModelEndpointSpec & {
|
|
29
|
+
protocol: NexraLanguageProtocol;
|
|
30
|
+
};
|
|
31
|
+
supportsStreaming: boolean;
|
|
32
|
+
maxOutputTokens?: number;
|
|
33
|
+
}>;
|
|
34
|
+
declare function getLanguageModelBinding(modelId: string, options?: {
|
|
35
|
+
protocol?: NexraLanguageProtocol;
|
|
36
|
+
stream?: boolean;
|
|
37
|
+
}): NexraLanguageModelBinding;
|
|
38
|
+
type NexraLanguageReasoning = Readonly<{
|
|
39
|
+
providerOptions: Record<string, JsonObject>;
|
|
40
|
+
canDisable: boolean;
|
|
41
|
+
}>;
|
|
42
|
+
declare function resolveNexraLanguageReasoning(modelId: string, options: {
|
|
43
|
+
enabled: boolean;
|
|
44
|
+
protocol?: NexraLanguageProtocol;
|
|
45
|
+
}): NexraLanguageReasoning;
|
|
46
|
+
|
|
47
|
+
export { CatalogClient, CreateNexraDisplayQuoteBatchRequest, CreateNexraQuoteRequest, NexraCatalogChangePage, NexraCatalogChangeParams, NexraCatalogModelState, NexraCatalogRevision, NexraDisplayQuoteBatch, type NexraLanguageModelBinding, type NexraLanguageProtocol, type NexraLanguageReasoning, NexraModelEndpointSpec, NexraModelSpec, NexraModelSpecFilter, NexraQuote, NexraSalePriceList, formatModelDisplayName, getLanguageModelBinding, getModelSpec, listModelSpecs, resolveNexraLanguageReasoning };
|
package/dist/catalog.js
CHANGED
|
@@ -3,16 +3,23 @@ import {
|
|
|
3
3
|
applyMediaGeometry,
|
|
4
4
|
decodeMediaGeometry,
|
|
5
5
|
encodeMediaGeometry,
|
|
6
|
+
formatModelDisplayName,
|
|
7
|
+
getLanguageModelBinding,
|
|
6
8
|
getModelSpec,
|
|
7
9
|
listModelSpecs,
|
|
8
|
-
projectMediaGeometry
|
|
9
|
-
|
|
10
|
+
projectMediaGeometry,
|
|
11
|
+
resolveNexraLanguageReasoning
|
|
12
|
+
} from "./chunk-WXPCZYOK.js";
|
|
13
|
+
import "./chunk-BS3B6F7W.js";
|
|
10
14
|
export {
|
|
11
15
|
CatalogClient,
|
|
12
16
|
applyMediaGeometry,
|
|
13
17
|
decodeMediaGeometry,
|
|
14
18
|
encodeMediaGeometry,
|
|
19
|
+
formatModelDisplayName,
|
|
20
|
+
getLanguageModelBinding,
|
|
15
21
|
getModelSpec,
|
|
16
22
|
listModelSpecs,
|
|
17
|
-
projectMediaGeometry
|
|
23
|
+
projectMediaGeometry,
|
|
24
|
+
resolveNexraLanguageReasoning
|
|
18
25
|
};
|