@byte_fluffy/nexra-sdk 0.1.0-alpha.46.1 → 0.1.0-alpha.48
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 +86 -0
- package/dist/catalog.js +1 -1
- package/dist/{chunk-JK6LUGM5.js → chunk-2IWCEEDI.js} +4623 -415
- package/dist/index.js +1 -1
- package/dist/language.js +242 -27
- package/package.json +16 -6
package/dist/index.js
CHANGED
package/dist/language.js
CHANGED
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
jsonBody,
|
|
7
7
|
parseServerSentEvents,
|
|
8
8
|
resolveNexraLanguageReasoning
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-2IWCEEDI.js";
|
|
10
10
|
import {
|
|
11
11
|
isPublicErrorCode,
|
|
12
12
|
publicErrorMessage,
|
|
@@ -17,7 +17,6 @@ import {
|
|
|
17
17
|
import { createAnthropic } from "@ai-sdk/anthropic";
|
|
18
18
|
import { getModelCapabilities as getAnthropicModelCapabilities } from "@ai-sdk/anthropic/internal";
|
|
19
19
|
import { createGoogleGenerativeAI } from "@ai-sdk/google";
|
|
20
|
-
import { createOpenAI } from "@ai-sdk/openai";
|
|
21
20
|
import { mapReasoningToProviderBudget } from "@ai-sdk/provider-utils";
|
|
22
21
|
|
|
23
22
|
// src/language/chat-model.ts
|
|
@@ -72,6 +71,30 @@ function nativeOptions(part) {
|
|
|
72
71
|
const value = part.providerOptions?.nexra;
|
|
73
72
|
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
74
73
|
}
|
|
74
|
+
function nativeMediaUrlPatterns(binding, kind) {
|
|
75
|
+
const field = kind === "audio" ? "input_audio" : `${kind}_url`;
|
|
76
|
+
const messages2 = asObject(asObject(binding.endpoint.inputSchema?.properties).messages);
|
|
77
|
+
const content = asObject(asObject(asObject(messages2.items).properties).content);
|
|
78
|
+
const patterns = /* @__PURE__ */ new Set();
|
|
79
|
+
const visit = (value) => {
|
|
80
|
+
if (Array.isArray(value)) {
|
|
81
|
+
value.forEach(visit);
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
const node = asObject(value);
|
|
85
|
+
const properties = asObject(node.properties);
|
|
86
|
+
if (asObject(properties.type).const === field) {
|
|
87
|
+
const url = asObject(asObject(asObject(properties[field]).properties).url);
|
|
88
|
+
if (typeof url.pattern === "string") patterns.add(url.pattern);
|
|
89
|
+
}
|
|
90
|
+
for (const child of Object.values(node)) if (child && typeof child === "object") visit(child);
|
|
91
|
+
};
|
|
92
|
+
visit(content);
|
|
93
|
+
return patterns.size ? [...patterns].map((pattern) => new RegExp(pattern)) : void 0;
|
|
94
|
+
}
|
|
95
|
+
function chatSupportedUrls(binding) {
|
|
96
|
+
return Object.fromEntries(binding.spec.capabilities.inputModalities.filter((kind) => ["image", "audio", "video"].includes(kind)).map((kind) => [`${kind}/*`, nativeMediaUrlPatterns(binding, kind) ?? [/^https?:\/\//]]));
|
|
97
|
+
}
|
|
75
98
|
function filePart(part, binding) {
|
|
76
99
|
const kind = part.mediaType.split("/")[0];
|
|
77
100
|
if (["image", "audio", "video"].includes(kind) && !binding.spec.capabilities.inputModalities.includes(kind)) {
|
|
@@ -83,6 +106,10 @@ function filePart(part, binding) {
|
|
|
83
106
|
throw new UnsupportedFunctionalityError({ functionality: "file reference without a Nexra reference" });
|
|
84
107
|
}
|
|
85
108
|
const url = part.data.type === "url" ? part.data.url.toString() : void 0;
|
|
109
|
+
const patterns = nativeMediaUrlPatterns(binding, kind);
|
|
110
|
+
if (url && patterns && !patterns.some((pattern) => pattern.test(url))) {
|
|
111
|
+
throw new UnsupportedFunctionalityError({ functionality: `native media URL for ${binding.spec.id}; provide bytes or a matching data URL` });
|
|
112
|
+
}
|
|
86
113
|
const data = part.data.type === "data" ? convertToBase64(part.data.data) : void 0;
|
|
87
114
|
if (kind === "image" || kind === "video") {
|
|
88
115
|
const field = kind === "image" ? "image_url" : "video_url";
|
|
@@ -380,7 +407,7 @@ function createChatLanguageModel(binding, transport) {
|
|
|
380
407
|
specificationVersion: "v4",
|
|
381
408
|
provider: "nexra.chat",
|
|
382
409
|
modelId: binding.spec.id,
|
|
383
|
-
supportedUrls:
|
|
410
|
+
supportedUrls: chatSupportedUrls(binding),
|
|
384
411
|
async doGenerate(options) {
|
|
385
412
|
const body = chatRequest(binding, options, false);
|
|
386
413
|
const response = await transport.response("/chat/completions", { method: "POST", ...jsonBody(body), headers: combineHeaders(options), signal: options.abortSignal }, { retryable: false });
|
|
@@ -528,6 +555,190 @@ function combineHeaders(options) {
|
|
|
528
555
|
return headers;
|
|
529
556
|
}
|
|
530
557
|
|
|
558
|
+
// src/language/responses-model.ts
|
|
559
|
+
import { createOpenAI } from "@ai-sdk/openai";
|
|
560
|
+
function object3(value) {
|
|
561
|
+
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
562
|
+
}
|
|
563
|
+
function isUnpositionedCitation(value) {
|
|
564
|
+
const node = object3(value);
|
|
565
|
+
return node.type === "url_citation" && typeof node.url === "string" && !Object.hasOwn(node, "start_index") && !Object.hasOwn(node, "end_index");
|
|
566
|
+
}
|
|
567
|
+
function project(value) {
|
|
568
|
+
if (Array.isArray(value)) return value.map(project);
|
|
569
|
+
if (!value || typeof value !== "object") return value;
|
|
570
|
+
const projected = Object.fromEntries(Object.entries(value).map(([key, item]) => [
|
|
571
|
+
key,
|
|
572
|
+
key === "annotations" && Array.isArray(item) ? item.filter((annotation) => !isUnpositionedCitation(annotation)).map(project) : project(item)
|
|
573
|
+
]));
|
|
574
|
+
if (projected.type === "output_text" && projected.annotations === void 0) projected.annotations = [];
|
|
575
|
+
return projected;
|
|
576
|
+
}
|
|
577
|
+
function citations(value) {
|
|
578
|
+
if (Array.isArray(value)) return value.flatMap(citations);
|
|
579
|
+
const node = object3(value);
|
|
580
|
+
if (isUnpositionedCitation(node)) return [node];
|
|
581
|
+
return Object.values(node).flatMap((item) => item && typeof item === "object" ? citations(item) : []);
|
|
582
|
+
}
|
|
583
|
+
function nativeSearchBody(value, call) {
|
|
584
|
+
const extension = call.providerOptions?.nexra?.web_search;
|
|
585
|
+
if (extension === void 0) return value;
|
|
586
|
+
if (!extension || typeof extension !== "object" || Array.isArray(extension)) throw new Error("Nexra web_search options must be a native tool object");
|
|
587
|
+
const body = object3(value);
|
|
588
|
+
if (!Array.isArray(body.tools) || !body.tools.some((tool) => object3(tool).type === "web_search")) {
|
|
589
|
+
throw new Error("Nexra web_search options require an enabled web_search tool");
|
|
590
|
+
}
|
|
591
|
+
return { ...body, tools: body.tools.map((tool) => object3(tool).type === "web_search" ? { ...object3(tool), ...extension, type: "web_search" } : tool) };
|
|
592
|
+
}
|
|
593
|
+
function nativeSearchRequest(init, call) {
|
|
594
|
+
return typeof init?.body === "string" ? { ...init, body: JSON.stringify(nativeSearchBody(JSON.parse(init.body), call)) } : init;
|
|
595
|
+
}
|
|
596
|
+
function createResponsesLanguageModel(options) {
|
|
597
|
+
const factory = (fetch) => createOpenAI({
|
|
598
|
+
apiKey: options.apiKey,
|
|
599
|
+
headers: options.headers,
|
|
600
|
+
name: "nexra.openai",
|
|
601
|
+
baseURL: options.baseUrl,
|
|
602
|
+
fetch
|
|
603
|
+
}).responses(options.modelId);
|
|
604
|
+
const base = factory(options.fetch);
|
|
605
|
+
return {
|
|
606
|
+
specificationVersion: "v4",
|
|
607
|
+
provider: base.provider,
|
|
608
|
+
modelId: base.modelId,
|
|
609
|
+
supportedUrls: base.supportedUrls,
|
|
610
|
+
async doGenerate(call) {
|
|
611
|
+
let original;
|
|
612
|
+
const fetch = async (input, init) => {
|
|
613
|
+
const response = await options.fetch(input, nativeSearchRequest(init, call));
|
|
614
|
+
if (!response.ok || !response.headers.get("content-type")?.includes("application/json")) return response;
|
|
615
|
+
const text = await response.text();
|
|
616
|
+
try {
|
|
617
|
+
original = JSON.parse(text);
|
|
618
|
+
} catch {
|
|
619
|
+
return new Response(text, response);
|
|
620
|
+
}
|
|
621
|
+
return new Response(JSON.stringify(project(original)), response);
|
|
622
|
+
};
|
|
623
|
+
const result = await factory(fetch).doGenerate(call);
|
|
624
|
+
const seen = /* @__PURE__ */ new Set();
|
|
625
|
+
const sources = sourceParts(original, seen);
|
|
626
|
+
return {
|
|
627
|
+
...result,
|
|
628
|
+
content: [...result.content, ...sources],
|
|
629
|
+
request: result.request ? { ...result.request, body: nativeSearchBody(result.request.body, call) } : void 0,
|
|
630
|
+
response: { ...result.response, ...original === void 0 ? {} : { body: original } }
|
|
631
|
+
};
|
|
632
|
+
},
|
|
633
|
+
async doStream(call) {
|
|
634
|
+
const entries = /* @__PURE__ */ new Map();
|
|
635
|
+
let before = [];
|
|
636
|
+
const canceled = new AbortController();
|
|
637
|
+
const fetch = async (input, init) => {
|
|
638
|
+
const response = await options.fetch(input, nativeSearchRequest(init, call));
|
|
639
|
+
if (!response.ok || !response.headers.get("content-type")?.includes("text/event-stream")) return response;
|
|
640
|
+
const signal = init?.signal ? AbortSignal.any([init.signal, canceled.signal]) : canceled.signal;
|
|
641
|
+
const iterator = parseServerSentEvents(response, { signal });
|
|
642
|
+
const encoder = new TextEncoder();
|
|
643
|
+
const body = new ReadableStream({
|
|
644
|
+
async pull(controller) {
|
|
645
|
+
try {
|
|
646
|
+
while (true) {
|
|
647
|
+
const next = await iterator.next();
|
|
648
|
+
if (next.done) {
|
|
649
|
+
controller.close();
|
|
650
|
+
return;
|
|
651
|
+
}
|
|
652
|
+
const frame = next.value;
|
|
653
|
+
let native;
|
|
654
|
+
try {
|
|
655
|
+
native = JSON.parse(frame.data);
|
|
656
|
+
} catch {
|
|
657
|
+
controller.enqueue(encoder.encode(`${frame.event ? `event: ${frame.event}
|
|
658
|
+
` : ""}data: ${frame.data}
|
|
659
|
+
|
|
660
|
+
`));
|
|
661
|
+
return;
|
|
662
|
+
}
|
|
663
|
+
if (object3(native).type === "response.output_text.annotation.added" && isUnpositionedCitation(object3(native).annotation)) {
|
|
664
|
+
before.push(native);
|
|
665
|
+
continue;
|
|
666
|
+
}
|
|
667
|
+
const projected = project(native);
|
|
668
|
+
const key = JSON.stringify(projected);
|
|
669
|
+
const queue = entries.get(key) ?? [];
|
|
670
|
+
queue.push({ original: native, before });
|
|
671
|
+
before = [];
|
|
672
|
+
entries.set(key, queue);
|
|
673
|
+
controller.enqueue(encoder.encode(`${frame.id ? `id: ${frame.id}
|
|
674
|
+
` : ""}${frame.event ? `event: ${frame.event}
|
|
675
|
+
` : ""}${frame.retry !== void 0 ? `retry: ${frame.retry}
|
|
676
|
+
` : ""}data: ${key}
|
|
677
|
+
|
|
678
|
+
`));
|
|
679
|
+
return;
|
|
680
|
+
}
|
|
681
|
+
} catch (error) {
|
|
682
|
+
controller.error(error);
|
|
683
|
+
await iterator.return(void 0);
|
|
684
|
+
}
|
|
685
|
+
},
|
|
686
|
+
async cancel(reason) {
|
|
687
|
+
canceled.abort(reason);
|
|
688
|
+
await iterator.return(void 0);
|
|
689
|
+
}
|
|
690
|
+
});
|
|
691
|
+
return new Response(body, response);
|
|
692
|
+
};
|
|
693
|
+
const result = await factory(fetch).doStream({ ...call, includeRawChunks: true });
|
|
694
|
+
const seen = /* @__PURE__ */ new Set();
|
|
695
|
+
return {
|
|
696
|
+
...result,
|
|
697
|
+
request: result.request ? { ...result.request, body: nativeSearchBody(result.request.body, call) } : void 0,
|
|
698
|
+
stream: result.stream.pipeThrough(new TransformStream({
|
|
699
|
+
transform(part, controller) {
|
|
700
|
+
if (part.type !== "raw") {
|
|
701
|
+
controller.enqueue(part);
|
|
702
|
+
return;
|
|
703
|
+
}
|
|
704
|
+
const key = JSON.stringify(part.rawValue);
|
|
705
|
+
const queue = entries.get(key);
|
|
706
|
+
const entry = queue?.shift();
|
|
707
|
+
if (queue?.length === 0) entries.delete(key);
|
|
708
|
+
const native = entry?.original ?? part.rawValue;
|
|
709
|
+
for (const frame of [...entry?.before ?? [], native]) {
|
|
710
|
+
for (const source of sourceParts(frame, seen)) controller.enqueue(source);
|
|
711
|
+
if (call.includeRawChunks) controller.enqueue({ type: "raw", rawValue: frame });
|
|
712
|
+
}
|
|
713
|
+
},
|
|
714
|
+
flush(controller) {
|
|
715
|
+
for (const frame of before) {
|
|
716
|
+
for (const source of sourceParts(frame, seen)) controller.enqueue(source);
|
|
717
|
+
if (call.includeRawChunks) controller.enqueue({ type: "raw", rawValue: frame });
|
|
718
|
+
}
|
|
719
|
+
entries.clear();
|
|
720
|
+
before = [];
|
|
721
|
+
}
|
|
722
|
+
}))
|
|
723
|
+
};
|
|
724
|
+
}
|
|
725
|
+
};
|
|
726
|
+
}
|
|
727
|
+
function sourceParts(value, seen) {
|
|
728
|
+
return citations(value).flatMap((annotation) => {
|
|
729
|
+
const key = JSON.stringify([annotation.url, annotation.title]);
|
|
730
|
+
if (seen.has(key)) return [];
|
|
731
|
+
seen.add(key);
|
|
732
|
+
return [{
|
|
733
|
+
type: "source",
|
|
734
|
+
sourceType: "url",
|
|
735
|
+
id: `native-source-${seen.size}`,
|
|
736
|
+
url: annotation.url,
|
|
737
|
+
...typeof annotation.title === "string" ? { title: annotation.title } : {}
|
|
738
|
+
}];
|
|
739
|
+
});
|
|
740
|
+
}
|
|
741
|
+
|
|
531
742
|
// src/language/index.ts
|
|
532
743
|
function createNexraLanguageModel(modelId, options) {
|
|
533
744
|
const binding = getLanguageModelBinding(modelId, options);
|
|
@@ -553,30 +764,30 @@ function createNexraLanguageModel(modelId, options) {
|
|
|
553
764
|
input,
|
|
554
765
|
typeof init?.body === "string" ? { ...init, body: JSON.stringify(explicitResponsesMessages(JSON.parse(init.body))) } : init
|
|
555
766
|
);
|
|
556
|
-
model =
|
|
767
|
+
model = createResponsesLanguageModel({ modelId: binding.spec.id, apiKey, headers: common.headers, baseUrl: `${root}/v1`, fetch: responsesFetch });
|
|
557
768
|
} else {
|
|
558
769
|
model = createAnthropic({ ...common, name: "nexra.anthropic", baseURL: `${root}/v1` })(binding.spec.id);
|
|
559
770
|
}
|
|
560
771
|
return withNativeContract(model, binding);
|
|
561
772
|
}
|
|
562
|
-
function
|
|
773
|
+
function object4(value) {
|
|
563
774
|
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
564
775
|
}
|
|
565
776
|
function explicitResponsesMessages(value) {
|
|
566
|
-
const body =
|
|
777
|
+
const body = object4(value);
|
|
567
778
|
if (!Array.isArray(body.input)) return value;
|
|
568
779
|
return { ...body, input: body.input.map((value2) => {
|
|
569
|
-
const item =
|
|
780
|
+
const item = object4(value2);
|
|
570
781
|
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;
|
|
571
782
|
}) };
|
|
572
783
|
}
|
|
573
784
|
function googleNativeBody(binding, value) {
|
|
574
|
-
const body =
|
|
575
|
-
const config =
|
|
576
|
-
const thinking =
|
|
577
|
-
const fields =
|
|
578
|
-
const nativeThinking =
|
|
579
|
-
const values =
|
|
785
|
+
const body = object4(value);
|
|
786
|
+
const config = object4(body.generationConfig);
|
|
787
|
+
const thinking = object4(config.thinkingConfig);
|
|
788
|
+
const fields = object4(binding.endpoint.inputSchema?.properties);
|
|
789
|
+
const nativeThinking = object4(object4(object4(object4(fields.generationConfig).properties).thinkingConfig).properties);
|
|
790
|
+
const values = object4(nativeThinking.thinkingLevel).enum;
|
|
580
791
|
const level = typeof thinking.thinkingLevel === "string" && Array.isArray(values) ? values.find((value2) => typeof value2 === "string" && value2.toLowerCase() === String(thinking.thinkingLevel).toLowerCase()) : void 0;
|
|
581
792
|
return level === void 0 || level === thinking.thinkingLevel ? value : { ...body, generationConfig: { ...config, thinkingConfig: { ...thinking, thinkingLevel: level } } };
|
|
582
793
|
}
|
|
@@ -584,25 +795,29 @@ function nativeRequest(binding, request, stream = false) {
|
|
|
584
795
|
if (!request) return request;
|
|
585
796
|
return binding.endpoint.protocol === "openai-responses" ? {
|
|
586
797
|
...request,
|
|
587
|
-
body: explicitResponsesMessages(stream ? { ...
|
|
798
|
+
body: explicitResponsesMessages(stream ? { ...object4(request.body), stream: true } : request.body)
|
|
588
799
|
} : binding.endpoint.protocol === "gemini-generate-content" ? { ...request, body: googleNativeBody(binding, request.body) } : request;
|
|
589
800
|
}
|
|
590
801
|
function prepare(options, binding, stream) {
|
|
591
802
|
binding = getLanguageModelBinding(binding.spec.id, { protocol: binding.endpoint.protocol, stream });
|
|
592
803
|
options = prepareLanguageReasoning(options, binding);
|
|
593
|
-
const properties =
|
|
594
|
-
const
|
|
804
|
+
const properties = object4(binding.endpoint.inputSchema?.properties);
|
|
805
|
+
const choices2 = object4(properties.tool_choice).enum;
|
|
806
|
+
if (options.toolChoice && Array.isArray(choices2) && !choices2.includes(options.toolChoice.type)) {
|
|
807
|
+
throw new Error(`Nexra tool choice is outside the native contract for ${binding.spec.id}: ${options.toolChoice.type}`);
|
|
808
|
+
}
|
|
809
|
+
const tokenField = object4(binding.endpoint.protocol === "gemini-generate-content" ? object4(object4(properties.generationConfig).properties).maxOutputTokens : properties.max_output_tokens ?? properties.max_tokens);
|
|
595
810
|
if (options.maxOutputTokens !== void 0 && (!Number.isInteger(options.maxOutputTokens) || typeof tokenField.minimum === "number" && options.maxOutputTokens < tokenField.minimum || binding.maxOutputTokens !== void 0 && options.maxOutputTokens > binding.maxOutputTokens)) throw new Error(`Nexra output token limit is outside the native contract for ${binding.spec.id}`);
|
|
596
811
|
if (options.tools?.length && !binding.endpoint.capabilities.includes("tool_call")) throw new Error(`Nexra model does not support tools: ${binding.spec.id}`);
|
|
597
812
|
const providerOptions = { ...options.providerOptions };
|
|
598
813
|
if (binding.endpoint.protocol === "openai-responses") {
|
|
599
|
-
const current =
|
|
814
|
+
const current = object4(providerOptions.openai);
|
|
600
815
|
providerOptions.openai = {
|
|
601
816
|
store: false,
|
|
602
817
|
forceReasoning: binding.endpoint.capabilities.includes("reasoning"),
|
|
603
818
|
...current
|
|
604
819
|
};
|
|
605
|
-
const reasoning =
|
|
820
|
+
const reasoning = object4(providerOptions.openai);
|
|
606
821
|
if (reasoning.forceReasoning === true && (options.temperature !== void 0 || options.topP !== void 0)) {
|
|
607
822
|
throw new Error(`Nexra Responses adapter cannot preserve explicit sampling parameters with reasoning for ${binding.spec.id}`);
|
|
608
823
|
}
|
|
@@ -612,8 +827,8 @@ function prepare(options, binding, stream) {
|
|
|
612
827
|
}
|
|
613
828
|
if (binding.endpoint.protocol === "anthropic-messages") {
|
|
614
829
|
const capabilities = getAnthropicModelCapabilities(binding.spec.id);
|
|
615
|
-
const native = { ...
|
|
616
|
-
let thinking =
|
|
830
|
+
const native = { ...object4(providerOptions.anthropic), ...object4(providerOptions.nexra) };
|
|
831
|
+
let thinking = object4(native.thinking);
|
|
617
832
|
if (!native.thinking && native.effort == null && options.reasoning && options.reasoning !== "provider-default") {
|
|
618
833
|
thinking = options.reasoning === "none" ? { type: "disabled" } : capabilities.supportsAdaptiveThinking ? { type: "adaptive" } : { type: "enabled", budgetTokens: mapReasoningToProviderBudget({
|
|
619
834
|
reasoning: options.reasoning,
|
|
@@ -634,20 +849,20 @@ function prepare(options, binding, stream) {
|
|
|
634
849
|
options = { ...options, maxOutputTokens: visible };
|
|
635
850
|
}
|
|
636
851
|
if (stream && binding.endpoint.protocol === "gemini-generate-content" && binding.endpoint.capabilities.includes("reasoning")) {
|
|
637
|
-
const google =
|
|
638
|
-
providerOptions.google = { ...google, thinkingConfig: { includeThoughts: true, ...
|
|
852
|
+
const google = object4(providerOptions.google);
|
|
853
|
+
providerOptions.google = { ...google, thinkingConfig: { includeThoughts: true, ...object4(google.thinkingConfig) } };
|
|
639
854
|
}
|
|
640
855
|
return { ...options, providerOptions };
|
|
641
856
|
}
|
|
642
857
|
function nativeUsage(protocol, value) {
|
|
643
|
-
const payload =
|
|
644
|
-
const raw = protocol === "gemini-generate-content" ? payload.usageMetadata : protocol === "anthropic-messages" ?
|
|
858
|
+
const payload = object4(value);
|
|
859
|
+
const raw = protocol === "gemini-generate-content" ? payload.usageMetadata : protocol === "anthropic-messages" ? object4(payload.message).usage ?? payload.usage : object4(payload.response).usage ?? payload.usage;
|
|
645
860
|
return raw && typeof raw === "object" && !Array.isArray(raw) ? raw : void 0;
|
|
646
861
|
}
|
|
647
862
|
function mergeRecords(previous, next) {
|
|
648
863
|
const merged = { ...previous, ...next };
|
|
649
864
|
for (const [key, value] of Object.entries(next)) {
|
|
650
|
-
if (value && typeof value === "object" && !Array.isArray(value)) merged[key] = { ...
|
|
865
|
+
if (value && typeof value === "object" && !Array.isArray(value)) merged[key] = { ...object4(previous?.[key]), ...object4(value) };
|
|
651
866
|
}
|
|
652
867
|
return merged;
|
|
653
868
|
}
|
|
@@ -681,8 +896,8 @@ function withNativeContract(model, binding) {
|
|
|
681
896
|
stream: result.stream.pipeThrough(new TransformStream({
|
|
682
897
|
transform(part, controller) {
|
|
683
898
|
if (part.type === "raw") {
|
|
684
|
-
const payload =
|
|
685
|
-
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
|
|
899
|
+
const payload = object4(part.rawValue);
|
|
900
|
+
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 object4(candidate).finishReason === "string");
|
|
686
901
|
const next = nativeUsage(binding.endpoint.protocol, part.rawValue);
|
|
687
902
|
if (next) raw = mergeRecords(raw, next);
|
|
688
903
|
if (options.includeRawChunks) controller.enqueue(part);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@byte_fluffy/nexra-sdk",
|
|
3
|
-
"version": "0.1.0-alpha.
|
|
3
|
+
"version": "0.1.0-alpha.48",
|
|
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": {
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
"@ai-sdk/
|
|
79
|
-
|
|
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
|
}
|