@byte_fluffy/nexra-sdk 0.1.0-alpha.31 → 0.1.0-alpha.33

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/catalog.js CHANGED
@@ -9,7 +9,7 @@ import {
9
9
  listModelSpecs,
10
10
  projectMediaGeometry,
11
11
  resolveNexraLanguageReasoning
12
- } from "./chunk-QXEDXMFI.js";
12
+ } from "./chunk-FEMICSXW.js";
13
13
  import "./chunk-QBW7OCT3.js";
14
14
  export {
15
15
  CatalogClient,
@@ -30539,6 +30539,455 @@ var video_generated_default = [
30539
30539
  ],
30540
30540
  endpoints: []
30541
30541
  },
30542
+ {
30543
+ id: "minimax/minimax-h3-local-reference",
30544
+ contractVersion: 1,
30545
+ developer: "minimax",
30546
+ displayName: "MiniMax H3 Local Reference",
30547
+ summary: "Generate video from a prompt with reference images, videos and audio.",
30548
+ kind: "video",
30549
+ family: "H3 Local",
30550
+ versionLabel: "H3 Local Reference",
30551
+ aliases: [],
30552
+ capabilities: {
30553
+ inputModalities: [
30554
+ "text",
30555
+ "image",
30556
+ "video",
30557
+ "audio"
30558
+ ],
30559
+ outputModalities: [
30560
+ "video"
30561
+ ],
30562
+ inputModes: [
30563
+ "image-to-video",
30564
+ "video-to-video",
30565
+ "audio-to-video"
30566
+ ],
30567
+ features: [
30568
+ "reference-image",
30569
+ "reference-video",
30570
+ "reference-audio",
30571
+ "omni-reference"
30572
+ ]
30573
+ },
30574
+ operations: [
30575
+ {
30576
+ operation: "video.generate",
30577
+ inputModalities: [
30578
+ "text",
30579
+ "image",
30580
+ "video",
30581
+ "audio"
30582
+ ],
30583
+ outputModalities: [
30584
+ "video"
30585
+ ],
30586
+ inputSchema: {
30587
+ $schema: "https://json-schema.org/draft/2020-12/schema",
30588
+ type: "object",
30589
+ properties: {
30590
+ content: {
30591
+ type: "array",
30592
+ minItems: 2,
30593
+ items: {
30594
+ oneOf: [
30595
+ {
30596
+ type: "object",
30597
+ properties: {
30598
+ type: {
30599
+ const: "text"
30600
+ },
30601
+ text: {
30602
+ type: "string",
30603
+ minLength: 1
30604
+ },
30605
+ role: {
30606
+ type: "string",
30607
+ enum: [
30608
+ "prompt",
30609
+ "negative_prompt"
30610
+ ]
30611
+ }
30612
+ },
30613
+ required: [
30614
+ "type",
30615
+ "text",
30616
+ "role"
30617
+ ],
30618
+ additionalProperties: false,
30619
+ allOf: [
30620
+ {
30621
+ if: {
30622
+ type: "object",
30623
+ properties: {
30624
+ role: {
30625
+ const: "prompt"
30626
+ }
30627
+ },
30628
+ required: [
30629
+ "role"
30630
+ ]
30631
+ },
30632
+ then: {
30633
+ type: "object",
30634
+ properties: {
30635
+ text: {
30636
+ type: "string",
30637
+ maxLength: 2e4,
30638
+ minLength: 1,
30639
+ title: "Prompt"
30640
+ }
30641
+ }
30642
+ }
30643
+ },
30644
+ {
30645
+ if: {
30646
+ type: "object",
30647
+ properties: {
30648
+ role: {
30649
+ const: "negative_prompt"
30650
+ }
30651
+ },
30652
+ required: [
30653
+ "role"
30654
+ ]
30655
+ },
30656
+ then: {
30657
+ type: "object",
30658
+ properties: {
30659
+ text: {
30660
+ type: "string",
30661
+ maxLength: 1e4,
30662
+ title: "Negative Prompt",
30663
+ default: ""
30664
+ }
30665
+ }
30666
+ }
30667
+ }
30668
+ ]
30669
+ },
30670
+ {
30671
+ type: "object",
30672
+ properties: {
30673
+ type: {
30674
+ const: "image"
30675
+ },
30676
+ source: {
30677
+ oneOf: [
30678
+ {
30679
+ type: "string",
30680
+ minLength: 1,
30681
+ pattern: "^(?:https://|data:[^;,]+;base64,)"
30682
+ },
30683
+ {
30684
+ type: "object",
30685
+ properties: {
30686
+ assetId: {
30687
+ type: "string",
30688
+ minLength: 1
30689
+ }
30690
+ },
30691
+ required: [
30692
+ "assetId"
30693
+ ],
30694
+ additionalProperties: false
30695
+ }
30696
+ ]
30697
+ },
30698
+ role: {
30699
+ type: "string",
30700
+ const: "reference"
30701
+ }
30702
+ },
30703
+ required: [
30704
+ "type",
30705
+ "source",
30706
+ "role"
30707
+ ],
30708
+ additionalProperties: false
30709
+ },
30710
+ {
30711
+ type: "object",
30712
+ properties: {
30713
+ type: {
30714
+ const: "video"
30715
+ },
30716
+ source: {
30717
+ oneOf: [
30718
+ {
30719
+ type: "string",
30720
+ minLength: 1,
30721
+ pattern: "^(?:https://|data:[^;,]+;base64,)"
30722
+ },
30723
+ {
30724
+ type: "object",
30725
+ properties: {
30726
+ assetId: {
30727
+ type: "string",
30728
+ minLength: 1
30729
+ }
30730
+ },
30731
+ required: [
30732
+ "assetId"
30733
+ ],
30734
+ additionalProperties: false
30735
+ }
30736
+ ]
30737
+ },
30738
+ role: {
30739
+ type: "string",
30740
+ const: "reference"
30741
+ }
30742
+ },
30743
+ required: [
30744
+ "type",
30745
+ "source",
30746
+ "role"
30747
+ ],
30748
+ additionalProperties: false
30749
+ },
30750
+ {
30751
+ type: "object",
30752
+ properties: {
30753
+ type: {
30754
+ const: "audio"
30755
+ },
30756
+ source: {
30757
+ oneOf: [
30758
+ {
30759
+ type: "string",
30760
+ minLength: 1,
30761
+ pattern: "^(?:https://|data:[^;,]+;base64,)"
30762
+ },
30763
+ {
30764
+ type: "object",
30765
+ properties: {
30766
+ assetId: {
30767
+ type: "string",
30768
+ minLength: 1
30769
+ }
30770
+ },
30771
+ required: [
30772
+ "assetId"
30773
+ ],
30774
+ additionalProperties: false
30775
+ }
30776
+ ]
30777
+ },
30778
+ role: {
30779
+ type: "string",
30780
+ const: "reference"
30781
+ }
30782
+ },
30783
+ required: [
30784
+ "type",
30785
+ "source",
30786
+ "role"
30787
+ ],
30788
+ additionalProperties: false
30789
+ }
30790
+ ]
30791
+ },
30792
+ "x-ui": {
30793
+ control: "content-parts",
30794
+ order: 0
30795
+ },
30796
+ maxItems: 17,
30797
+ description: "Provide a prompt and at least one image, video or audio reference.",
30798
+ allOf: [
30799
+ {
30800
+ contains: {
30801
+ type: "object",
30802
+ properties: {
30803
+ type: {
30804
+ const: "text"
30805
+ },
30806
+ role: {
30807
+ const: "prompt"
30808
+ }
30809
+ },
30810
+ required: [
30811
+ "type",
30812
+ "role"
30813
+ ]
30814
+ },
30815
+ minContains: 1,
30816
+ maxContains: 1
30817
+ },
30818
+ {
30819
+ contains: {
30820
+ type: "object",
30821
+ properties: {
30822
+ type: {
30823
+ const: "text"
30824
+ },
30825
+ role: {
30826
+ const: "negative_prompt"
30827
+ }
30828
+ },
30829
+ required: [
30830
+ "type",
30831
+ "role"
30832
+ ]
30833
+ },
30834
+ minContains: 0,
30835
+ maxContains: 1
30836
+ },
30837
+ {
30838
+ contains: {
30839
+ type: "object",
30840
+ properties: {
30841
+ type: {
30842
+ const: "image"
30843
+ },
30844
+ role: {
30845
+ const: "reference"
30846
+ }
30847
+ },
30848
+ required: [
30849
+ "type",
30850
+ "role"
30851
+ ]
30852
+ },
30853
+ minContains: 0,
30854
+ maxContains: 9
30855
+ },
30856
+ {
30857
+ contains: {
30858
+ type: "object",
30859
+ properties: {
30860
+ type: {
30861
+ const: "video"
30862
+ },
30863
+ role: {
30864
+ const: "reference"
30865
+ }
30866
+ },
30867
+ required: [
30868
+ "type",
30869
+ "role"
30870
+ ]
30871
+ },
30872
+ minContains: 0,
30873
+ maxContains: 3
30874
+ },
30875
+ {
30876
+ contains: {
30877
+ type: "object",
30878
+ properties: {
30879
+ type: {
30880
+ const: "audio"
30881
+ },
30882
+ role: {
30883
+ const: "reference"
30884
+ }
30885
+ },
30886
+ required: [
30887
+ "type",
30888
+ "role"
30889
+ ]
30890
+ },
30891
+ minContains: 0,
30892
+ maxContains: 3
30893
+ },
30894
+ {
30895
+ contains: {
30896
+ type: "object",
30897
+ properties: {
30898
+ type: {
30899
+ enum: [
30900
+ "image",
30901
+ "video",
30902
+ "audio"
30903
+ ]
30904
+ }
30905
+ },
30906
+ required: [
30907
+ "type"
30908
+ ]
30909
+ },
30910
+ minContains: 1
30911
+ }
30912
+ ]
30913
+ },
30914
+ aspect_ratio: {
30915
+ type: "string",
30916
+ title: "Aspect Ratio",
30917
+ default: "16:9",
30918
+ pattern: "^(?:1:1|2:3|3:2|3:4|4:3|9:16|16:9|21:9)(?: \\([^)]+\\))?$",
30919
+ "x-ui": {
30920
+ order: 10
30921
+ },
30922
+ enum: [
30923
+ "1:1",
30924
+ "2:3",
30925
+ "3:2",
30926
+ "3:4",
30927
+ "4:3",
30928
+ "9:16",
30929
+ "16:9",
30930
+ "21:9"
30931
+ ]
30932
+ },
30933
+ duration: {
30934
+ type: "number",
30935
+ maximum: 15,
30936
+ title: "\u89C6\u9891\u65F6\u957F",
30937
+ default: 5,
30938
+ minimum: 0.2,
30939
+ "x-ui": {
30940
+ order: 12,
30941
+ control: "range",
30942
+ unit: "\u79D2"
30943
+ }
30944
+ },
30945
+ seed: {
30946
+ type: "integer",
30947
+ minimum: 0,
30948
+ title: "\u968F\u673A\u79CD\u5B50",
30949
+ "x-ui": {
30950
+ order: 13,
30951
+ control: "number"
30952
+ }
30953
+ },
30954
+ resolution: {
30955
+ type: "string",
30956
+ title: "\u5206\u8FA8\u7387",
30957
+ enum: [
30958
+ "480P",
30959
+ "768P"
30960
+ ],
30961
+ "x-ui": {
30962
+ order: 11,
30963
+ control: "segmented"
30964
+ }
30965
+ }
30966
+ },
30967
+ required: [
30968
+ "content"
30969
+ ],
30970
+ additionalProperties: false
30971
+ },
30972
+ outputSchema: {},
30973
+ metering: {
30974
+ schemaVersion: 1,
30975
+ kind: "non_token",
30976
+ metrics: [
30977
+ {
30978
+ metric: "requests",
30979
+ requirement: "required"
30980
+ },
30981
+ {
30982
+ metric: "output_video_seconds",
30983
+ requirement: "required"
30984
+ }
30985
+ ]
30986
+ }
30987
+ }
30988
+ ],
30989
+ endpoints: []
30990
+ },
30542
30991
  {
30543
30992
  id: "agnes/agnes-video-v2-0",
30544
30993
  contractVersion: 1,
@@ -50448,7 +50897,7 @@ var NexraWaitTimeoutError = class extends Error {
50448
50897
  };
50449
50898
 
50450
50899
  // src/generated/version.generated.ts
50451
- var SDK_VERSION = "0.1.0-alpha.31";
50900
+ var SDK_VERSION = "0.1.0-alpha.33";
50452
50901
 
50453
50902
  // src/transport.ts
50454
50903
  var DEFAULT_BASE_URL = "https://api.nexra-ai.com/v1";
@@ -50599,37 +51048,56 @@ async function* parseServerSentEvents(response, options = {}) {
50599
51048
  }
50600
51049
  }
50601
51050
  function createServerSentEventDecoder() {
51051
+ const decode = createServerSentEventFrameDecoder();
51052
+ return (bytes, done) => decode(bytes, done).flatMap((frame) => frame.event ? [frame.event] : []);
51053
+ }
51054
+ function createServerSentEventFrameDecoder() {
50602
51055
  const decoder = new TextDecoder();
50603
- let buffer = "";
51056
+ let buffer = new Uint8Array();
51057
+ let cursor = 0;
51058
+ let lineStart = 0;
50604
51059
  let current = emptyEvent();
51060
+ const line = (value) => {
51061
+ if (value.startsWith(":")) return;
51062
+ const separator = value.indexOf(":");
51063
+ const field2 = separator === -1 ? value : value.slice(0, separator);
51064
+ let content = separator === -1 ? "" : value.slice(separator + 1);
51065
+ if (content.startsWith(" ")) content = content.slice(1);
51066
+ if (field2 === "data") current.data.push(content);
51067
+ else if (field2 === "event") current.event = content;
51068
+ else if (field2 === "id") current.id = content;
51069
+ else if (field2 === "retry") current.retry = Number(content);
51070
+ };
50605
51071
  return (bytes, done = false) => {
50606
- const events = [];
50607
- buffer += decoder.decode(bytes, { stream: !done });
50608
- const lines = buffer.split(/\r?\n/);
50609
- buffer = done ? "" : lines.pop() ?? "";
50610
- for (const line of lines) {
50611
- if (line === "") {
50612
- const event = buildEvent(current);
51072
+ const frames = [];
51073
+ if (bytes?.length) {
51074
+ const joined = new Uint8Array(buffer.length + bytes.length);
51075
+ joined.set(buffer);
51076
+ joined.set(bytes, buffer.length);
51077
+ buffer = joined;
51078
+ }
51079
+ let frameStart = 0;
51080
+ for (; cursor < buffer.length; cursor++) {
51081
+ if (buffer[cursor] !== 10) continue;
51082
+ const lineEnd = buffer[cursor - 1] === 13 ? cursor - 1 : cursor;
51083
+ if (lineEnd === lineStart) {
51084
+ frames.push({ event: buildEvent(current), bytes: buffer.slice(frameStart, cursor + 1) });
50613
51085
  current = emptyEvent();
50614
- if (event) events.push(event);
50615
- continue;
50616
- }
50617
- if (line.startsWith(":")) continue;
50618
- const separator = line.indexOf(":");
50619
- const field2 = separator === -1 ? line : line.slice(0, separator);
50620
- let content = separator === -1 ? "" : line.slice(separator + 1);
50621
- if (content.startsWith(" ")) content = content.slice(1);
50622
- if (field2 === "data") current.data.push(content);
50623
- else if (field2 === "event") current.event = content;
50624
- else if (field2 === "id") current.id = content;
50625
- else if (field2 === "retry") current.retry = Number(content);
51086
+ frameStart = cursor + 1;
51087
+ } else line(decoder.decode(buffer.subarray(lineStart, lineEnd)));
51088
+ lineStart = cursor + 1;
50626
51089
  }
51090
+ buffer = buffer.slice(frameStart);
51091
+ cursor -= frameStart;
51092
+ lineStart -= frameStart;
50627
51093
  if (done) {
50628
- const event = buildEvent(current);
51094
+ if (lineStart < buffer.length) line(decoder.decode(buffer.subarray(lineStart)));
51095
+ if (buffer.length) frames.push({ event: buildEvent(current), bytes: buffer });
51096
+ buffer = new Uint8Array();
51097
+ cursor = lineStart = 0;
50629
51098
  current = emptyEvent();
50630
- if (event) events.push(event);
50631
51099
  }
50632
- return events;
51100
+ return frames;
50633
51101
  };
50634
51102
  }
50635
51103
  function emptyEvent() {
@@ -50838,7 +51306,7 @@ export {
50838
51306
  applyMediaGeometry,
50839
51307
  applyNoWatermark,
50840
51308
  parseServerSentEvents,
50841
- createServerSentEventDecoder,
51309
+ createServerSentEventFrameDecoder,
50842
51310
  formatModelDisplayName,
50843
51311
  CatalogClient,
50844
51312
  getModelSpec,
package/dist/index.js CHANGED
@@ -20,7 +20,7 @@ import {
20
20
  projectMediaGeometry,
21
21
  queryString,
22
22
  sleep
23
- } from "./chunk-QXEDXMFI.js";
23
+ } from "./chunk-FEMICSXW.js";
24
24
  import {
25
25
  MEDIA_KINDS,
26
26
  TASK_STATUSES,
package/dist/language.js CHANGED
@@ -1,12 +1,12 @@
1
1
  import {
2
2
  HttpTransport,
3
3
  SDK_VERSION,
4
- createServerSentEventDecoder,
4
+ createServerSentEventFrameDecoder,
5
5
  getLanguageModelBinding,
6
6
  jsonBody,
7
7
  parseServerSentEvents,
8
8
  resolveNexraLanguageReasoning
9
- } from "./chunk-QXEDXMFI.js";
9
+ } from "./chunk-FEMICSXW.js";
10
10
  import {
11
11
  isPublicErrorCode,
12
12
  publicErrorMessage,
@@ -212,7 +212,7 @@ var NexraNativeError = class extends APICallError {
212
212
  const locale = resolvePublicErrorLocale(context.acceptLanguage ?? headers.get("content-language"));
213
213
  const nexraError = code && isPublicErrorCode(code) ? { code, message: publicErrorMessage(code, locale) } : void 0;
214
214
  const body = record(context.body);
215
- const originalMessage = record(body.error).message ?? body.message;
215
+ const originalMessage = record(body.error).message ?? record(record(body.response).error).message ?? body.message;
216
216
  const message = nexraError?.message ?? (typeof originalMessage === "string" ? originalMessage : typeof context.body === "string" ? context.body : "The native model request failed.");
217
217
  super({
218
218
  message,
@@ -259,31 +259,68 @@ function createNexraNativeFetch(options = {}) {
259
259
  }
260
260
  function guardNativeErrorFrames(response, context) {
261
261
  if (!response.body || !response.headers.get("content-type")?.includes("text/event-stream")) return response;
262
- const decode = createServerSentEventDecoder();
263
- const inspect = (events) => {
264
- for (const event of events) {
265
- let body;
266
- try {
267
- body = JSON.parse(event.data);
268
- } catch {
269
- if (event.event === "error") throw new NexraNativeError({ ...context, body: event.data, responseBody: event.data });
270
- continue;
271
- }
272
- const payload = record(body);
273
- if (event.event === "error" || payload.type === "error" || payload.type === "response.failed" || payload.error) {
274
- throw new NexraNativeError({ ...context, body, responseBody: event.data });
275
- }
262
+ const decode = createServerSentEventFrameDecoder();
263
+ const reader = response.body.getReader();
264
+ const pending = [];
265
+ let finished = false;
266
+ let released = false;
267
+ let failure;
268
+ const release = () => {
269
+ if (!released) {
270
+ reader.releaseLock();
271
+ released = true;
272
+ }
273
+ };
274
+ const inspect = (event) => {
275
+ if (!event) return;
276
+ let body;
277
+ try {
278
+ body = JSON.parse(event.data);
279
+ } catch {
280
+ return event.event === "error" ? new NexraNativeError({ ...context, body: event.data, responseBody: event.data }) : void 0;
281
+ }
282
+ const payload = record(body);
283
+ if (event.event === "error" || payload.type === "error" || payload.type === "response.failed" || payload.error) {
284
+ return new NexraNativeError({ ...context, body, responseBody: event.data });
276
285
  }
277
286
  };
278
- const stream = response.body.pipeThrough(new TransformStream({
279
- transform(bytes, controller) {
280
- inspect(decode(bytes));
281
- controller.enqueue(bytes);
287
+ const stream = new ReadableStream({
288
+ async pull(controller) {
289
+ try {
290
+ while (!pending.length && !finished) {
291
+ const { value, done } = await reader.read();
292
+ for (const frame of decode(value, done)) {
293
+ failure = inspect(frame.event);
294
+ if (failure) {
295
+ finished = true;
296
+ await reader.cancel(failure).catch(() => void 0);
297
+ release();
298
+ break;
299
+ }
300
+ pending.push(frame.bytes);
301
+ }
302
+ if (done) {
303
+ finished = true;
304
+ release();
305
+ }
306
+ }
307
+ if (pending.length) controller.enqueue(pending.shift());
308
+ else if (failure) controller.error(failure);
309
+ else controller.close();
310
+ } catch (error) {
311
+ await reader.cancel(error).catch(() => void 0);
312
+ release();
313
+ controller.error(error);
314
+ }
282
315
  },
283
- flush() {
284
- inspect(decode(void 0, true));
316
+ async cancel(reason) {
317
+ pending.length = 0;
318
+ if (!released) {
319
+ await reader.cancel(reason);
320
+ release();
321
+ }
285
322
  }
286
- }));
323
+ }, { highWaterMark: 0 });
287
324
  return new Response(stream, { status: response.status, statusText: response.statusText, headers: response.headers });
288
325
  }
289
326
 
@@ -500,15 +537,33 @@ function createNexraLanguageModel(modelId, options) {
500
537
  if (binding.endpoint.protocol === "gemini-generate-content") {
501
538
  model = createGoogleGenerativeAI({ ...common, name: "nexra.google", baseURL: `${root}/v1beta/models` })(binding.spec.id);
502
539
  } else if (binding.endpoint.protocol === "openai-responses") {
503
- model = createOpenAI({ ...common, name: "nexra.openai", baseURL: `${root}/v1` }).responses(binding.spec.id);
540
+ const responsesFetch = (input, init) => fetch(
541
+ input,
542
+ typeof init?.body === "string" ? { ...init, body: JSON.stringify(explicitResponsesMessages(JSON.parse(init.body))) } : init
543
+ );
544
+ model = createOpenAI({ ...common, name: "nexra.openai", baseURL: `${root}/v1`, fetch: responsesFetch }).responses(binding.spec.id);
504
545
  } else {
505
546
  model = createAnthropic({ ...common, name: "nexra.anthropic", baseURL: `${root}/v1` })(binding.spec.id);
506
547
  }
507
- return withNativeUsage(model, binding);
548
+ return withNativeContract(model, binding);
508
549
  }
509
550
  function object3(value) {
510
551
  return value && typeof value === "object" && !Array.isArray(value) ? value : {};
511
552
  }
553
+ function explicitResponsesMessages(value) {
554
+ const body = object3(value);
555
+ if (!Array.isArray(body.input)) return value;
556
+ return { ...body, input: body.input.map((value2) => {
557
+ const item = object3(value2);
558
+ return item.type === void 0 && ["system", "developer", "user", "assistant"].includes(String(item.role)) && (typeof item.content === "string" || Array.isArray(item.content)) ? { ...item, type: "message" } : value2;
559
+ }) };
560
+ }
561
+ function nativeRequest(protocol, request, stream = false) {
562
+ return protocol === "openai-responses" && request ? {
563
+ ...request,
564
+ body: explicitResponsesMessages(stream ? { ...object3(request.body), stream: true } : request.body)
565
+ } : request;
566
+ }
512
567
  function prepare(options, binding, stream) {
513
568
  options = prepareLanguageReasoning(options, binding);
514
569
  const properties = object3(binding.endpoint.inputSchema?.properties);
@@ -572,7 +627,7 @@ function mergeRecords(previous, next) {
572
627
  }
573
628
  return merged;
574
629
  }
575
- function withNativeUsage(model, binding) {
630
+ function withNativeContract(model, binding) {
576
631
  return {
577
632
  specificationVersion: "v4",
578
633
  provider: model.provider,
@@ -581,7 +636,11 @@ function withNativeUsage(model, binding) {
581
636
  async doGenerate(options) {
582
637
  const result = await model.doGenerate(prepare(options, binding, false));
583
638
  const raw = nativeUsage(binding.endpoint.protocol, result.response?.body);
584
- return raw ? { ...result, usage: { ...result.usage, raw } } : result;
639
+ return {
640
+ ...result,
641
+ request: nativeRequest(binding.endpoint.protocol, result.request),
642
+ ...raw ? { usage: { ...result.usage, raw } } : {}
643
+ };
585
644
  },
586
645
  async doStream(options) {
587
646
  if (!binding.supportsStreaming) throw new Error(`Nexra model does not support streaming: ${binding.spec.id}`);
@@ -592,35 +651,39 @@ function withNativeUsage(model, binding) {
592
651
  let finish;
593
652
  const textMetadata = /* @__PURE__ */ new Map();
594
653
  const reasoningMetadata2 = /* @__PURE__ */ new Map();
595
- return { ...result, stream: result.stream.pipeThrough(new TransformStream({
596
- transform(part, controller) {
597
- if (part.type === "raw") {
598
- const payload = object3(part.rawValue);
599
- terminal ||= binding.endpoint.protocol === "anthropic-messages" ? payload.type === "message_stop" : binding.endpoint.protocol === "openai-responses" ? ["response.completed", "response.incomplete", "response.failed"].includes(String(payload.type)) : Array.isArray(payload.candidates) && payload.candidates.some((candidate) => typeof object3(candidate).finishReason === "string");
600
- const next = nativeUsage(binding.endpoint.protocol, part.rawValue);
601
- if (next) raw = mergeRecords(raw, next);
602
- if (options.includeRawChunks) controller.enqueue(part);
603
- } else if (part.type === "finish") finish = part;
604
- else {
605
- if (part.type === "error") failed = true;
606
- if (part.type === "text-start" || part.type === "text-delta" || part.type === "text-end" || part.type === "reasoning-start" || part.type === "reasoning-delta" || part.type === "reasoning-end") {
607
- const metadata = part.type.startsWith("text-") ? textMetadata : reasoningMetadata2;
608
- if (part.providerMetadata) metadata.set(part.id, mergeRecords(metadata.get(part.id), part.providerMetadata));
609
- if (part.type === "text-end" || part.type === "reasoning-end") {
610
- const retained = metadata.get(part.id);
611
- metadata.delete(part.id);
612
- if (retained) part = { ...part, providerMetadata: retained };
654
+ return {
655
+ ...result,
656
+ request: nativeRequest(binding.endpoint.protocol, result.request, true),
657
+ stream: result.stream.pipeThrough(new TransformStream({
658
+ transform(part, controller) {
659
+ if (part.type === "raw") {
660
+ const payload = object3(part.rawValue);
661
+ terminal ||= binding.endpoint.protocol === "anthropic-messages" ? payload.type === "message_stop" : binding.endpoint.protocol === "openai-responses" ? ["response.completed", "response.incomplete", "response.failed"].includes(String(payload.type)) : Array.isArray(payload.candidates) && payload.candidates.some((candidate) => typeof object3(candidate).finishReason === "string");
662
+ const next = nativeUsage(binding.endpoint.protocol, part.rawValue);
663
+ if (next) raw = mergeRecords(raw, next);
664
+ if (options.includeRawChunks) controller.enqueue(part);
665
+ } else if (part.type === "finish") finish = part;
666
+ else {
667
+ if (part.type === "error") failed = true;
668
+ if (part.type === "text-start" || part.type === "text-delta" || part.type === "text-end" || part.type === "reasoning-start" || part.type === "reasoning-delta" || part.type === "reasoning-end") {
669
+ const metadata = part.type.startsWith("text-") ? textMetadata : reasoningMetadata2;
670
+ if (part.providerMetadata) metadata.set(part.id, mergeRecords(metadata.get(part.id), part.providerMetadata));
671
+ if (part.type === "text-end" || part.type === "reasoning-end") {
672
+ const retained = metadata.get(part.id);
673
+ metadata.delete(part.id);
674
+ if (retained) part = { ...part, providerMetadata: retained };
675
+ }
613
676
  }
677
+ controller.enqueue(part);
614
678
  }
615
- controller.enqueue(part);
679
+ },
680
+ flush(controller) {
681
+ if (failed) return;
682
+ if (!terminal || !finish) controller.enqueue({ type: "error", error: new Error(`Nexra ${binding.endpoint.protocol} stream ended before its terminal response`) });
683
+ else controller.enqueue(raw ? { ...finish, usage: { ...finish.usage, raw } } : finish);
616
684
  }
617
- },
618
- flush(controller) {
619
- if (failed) return;
620
- if (!terminal || !finish) controller.enqueue({ type: "error", error: new Error(`Nexra ${binding.endpoint.protocol} stream ended before its terminal response`) });
621
- else controller.enqueue(raw ? { ...finish, usage: { ...finish.usage, raw } } : finish);
622
- }
623
- })) };
685
+ }))
686
+ };
624
687
  }
625
688
  };
626
689
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@byte_fluffy/nexra-sdk",
3
- "version": "0.1.0-alpha.31",
3
+ "version": "0.1.0-alpha.33",
4
4
  "type": "module",
5
5
  "types": "./dist/index.d.ts",
6
6
  "sideEffects": false,
@@ -72,10 +72,20 @@
72
72
  "@ai-sdk/provider-utils": "^5.0.21"
73
73
  },
74
74
  "peerDependenciesMeta": {
75
- "@ai-sdk/anthropic": { "optional": true },
76
- "@ai-sdk/google": { "optional": true },
77
- "@ai-sdk/openai": { "optional": true },
78
- "@ai-sdk/provider": { "optional": true },
79
- "@ai-sdk/provider-utils": { "optional": true }
75
+ "@ai-sdk/anthropic": {
76
+ "optional": true
77
+ },
78
+ "@ai-sdk/google": {
79
+ "optional": true
80
+ },
81
+ "@ai-sdk/openai": {
82
+ "optional": true
83
+ },
84
+ "@ai-sdk/provider": {
85
+ "optional": true
86
+ },
87
+ "@ai-sdk/provider-utils": {
88
+ "optional": true
89
+ }
80
90
  }
81
91
  }