@demicodes/provider-openai-api 0.1.0 → 0.2.0
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/index.d.mts +0 -1
- package/dist/index.mjs +43 -20
- package/package.json +4 -4
package/dist/index.d.mts
CHANGED
package/dist/index.mjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { isAbortError, isRecord, normalizeBaseUrl, numberOrZero, parseJsonObject, parseJsonOrString,
|
|
1
|
+
import { isAbortError, isRecord, normalizeBaseUrl, numberOrZero, parseJsonObject, parseJsonOrString, stringOrNull } from "@demicodes/utils";
|
|
2
2
|
import { Buffer } from "node:buffer";
|
|
3
3
|
import process from "node:process";
|
|
4
4
|
import { zeroUsage } from "@demicodes/core";
|
|
5
|
-
import { authStatusFromKey, clampPromptCacheKey, defineProvider, httpRequestFailedEvent, normalizeErrorCode, providerErrorFromUnknown, withProviderId } from "@demicodes/provider";
|
|
5
|
+
import { authStatusFromKey, clampPromptCacheKey, defineProvider, httpRequestFailedEvent, normalizeErrorCode, providerErrorFromUnknown, toolResultContentToText, withProviderId } from "@demicodes/provider";
|
|
6
6
|
//#region src/models.ts
|
|
7
7
|
const SOURCE_FETCHED_AT = "1970-01-01T00:00:00.000Z";
|
|
8
8
|
function openAIApiDefaultModels(providerId = "openai") {
|
|
@@ -331,10 +331,13 @@ function* mapOpenAIResponseEvent(event, state = newOpenAIResponseStreamState())
|
|
|
331
331
|
}
|
|
332
332
|
return;
|
|
333
333
|
case "response.output_text.delta":
|
|
334
|
-
if (typeof event.delta === "string")
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
334
|
+
if (typeof event.delta === "string") {
|
|
335
|
+
state.textDeltaSeen = true;
|
|
336
|
+
yield {
|
|
337
|
+
type: "text_delta",
|
|
338
|
+
text: event.delta
|
|
339
|
+
};
|
|
340
|
+
}
|
|
338
341
|
return;
|
|
339
342
|
case "response.function_call_arguments.delta": {
|
|
340
343
|
const key = event.item_id ?? state.currentFunctionCall?.id;
|
|
@@ -363,11 +366,14 @@ function* mapOpenAIResponseEvent(event, state = newOpenAIResponseStreamState())
|
|
|
363
366
|
if (state.currentReasoning === item) state.currentReasoning = null;
|
|
364
367
|
state.reasoningDeltaSeen = false;
|
|
365
368
|
} else if (isOpenAIResponseMessageItem(item)) {
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
369
|
+
if (!state.textDeltaSeen) {
|
|
370
|
+
const text = openAIResponseMessageText(item);
|
|
371
|
+
if (text) yield {
|
|
372
|
+
type: "text_delta",
|
|
373
|
+
text
|
|
374
|
+
};
|
|
375
|
+
}
|
|
376
|
+
state.textDeltaSeen = false;
|
|
371
377
|
} else if (isOpenAIResponseFunctionCallItem(item)) {
|
|
372
378
|
const itemId = item.id ?? event.item_id;
|
|
373
379
|
const callId = item.call_id ?? event.call_id;
|
|
@@ -583,9 +589,6 @@ function userContentToOpenAI(content) {
|
|
|
583
589
|
if (parts.every((part) => part.type === "text")) return parts.map((part) => part.text).join("\n");
|
|
584
590
|
return parts;
|
|
585
591
|
}
|
|
586
|
-
function toolResultContentToText(output) {
|
|
587
|
-
return output.map((block) => block.type === "text" ? block.text : `[image:${block.source.mediaType}]`).join("\n");
|
|
588
|
-
}
|
|
589
592
|
function toolToOpenAITool(tool) {
|
|
590
593
|
return {
|
|
591
594
|
type: "function",
|
|
@@ -641,9 +644,7 @@ function inferenceItemToOpenAIResponseInput(item, index) {
|
|
|
641
644
|
type: "output_text",
|
|
642
645
|
text: item.text,
|
|
643
646
|
annotations: []
|
|
644
|
-
}]
|
|
645
|
-
id: `msg_${shortHash(`${index}:${item.modelId}:${item.text}`)}`,
|
|
646
|
-
status: "completed"
|
|
647
|
+
}]
|
|
647
648
|
}];
|
|
648
649
|
case "assistant_thinking": {
|
|
649
650
|
const reasoning = parseOpenAIReasoningSignature(item.signature);
|
|
@@ -662,11 +663,24 @@ function inferenceItemToOpenAIResponseInput(item, index) {
|
|
|
662
663
|
}
|
|
663
664
|
case "tool_result": {
|
|
664
665
|
const { callId } = splitOpenAIResponseToolUseId(item.toolUseId);
|
|
665
|
-
|
|
666
|
+
const items = [{
|
|
666
667
|
type: "function_call_output",
|
|
667
668
|
call_id: callId,
|
|
668
669
|
output: toolResultContentToText(item.output)
|
|
669
670
|
}];
|
|
671
|
+
const images = item.output.filter((block) => block.type === "image");
|
|
672
|
+
if (images.length > 0) items.push({
|
|
673
|
+
role: "user",
|
|
674
|
+
content: [{
|
|
675
|
+
type: "input_text",
|
|
676
|
+
text: `[media returned by tool call ${callId}]`
|
|
677
|
+
}, ...images.map((block) => ({
|
|
678
|
+
type: "input_image",
|
|
679
|
+
image_url: `data:${block.source.mediaType};base64,${block.source.data}`,
|
|
680
|
+
detail: "auto"
|
|
681
|
+
}))]
|
|
682
|
+
});
|
|
683
|
+
return items;
|
|
670
684
|
}
|
|
671
685
|
}
|
|
672
686
|
}
|
|
@@ -728,7 +742,15 @@ function parseOpenAIReasoningSignature(signature) {
|
|
|
728
742
|
if (!signature) return null;
|
|
729
743
|
try {
|
|
730
744
|
const parsed = JSON.parse(signature);
|
|
731
|
-
|
|
745
|
+
if (!isOpenAIResponseReasoningItem(parsed)) return null;
|
|
746
|
+
const { id, summary, content, encrypted_content } = parsed;
|
|
747
|
+
return {
|
|
748
|
+
type: "reasoning",
|
|
749
|
+
...id ? { id } : {},
|
|
750
|
+
...summary ? { summary } : {},
|
|
751
|
+
...content ? { content } : {},
|
|
752
|
+
...encrypted_content ? { encrypted_content } : {}
|
|
753
|
+
};
|
|
732
754
|
} catch {
|
|
733
755
|
return null;
|
|
734
756
|
}
|
|
@@ -771,7 +793,8 @@ function newOpenAIResponseStreamState() {
|
|
|
771
793
|
currentReasoning: null,
|
|
772
794
|
currentFunctionCall: null,
|
|
773
795
|
functionArguments: /* @__PURE__ */ new Map(),
|
|
774
|
-
reasoningDeltaSeen: false
|
|
796
|
+
reasoningDeltaSeen: false,
|
|
797
|
+
textDeltaSeen: false
|
|
775
798
|
};
|
|
776
799
|
}
|
|
777
800
|
function isOpenAIResponseReasoningItem(item) {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@demicodes/provider-openai-api",
|
|
3
3
|
"description": "OpenAI API provider adapter for Demi.",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.2.0",
|
|
5
5
|
"private": false,
|
|
6
6
|
"type": "module",
|
|
7
7
|
"exports": {
|
|
@@ -12,9 +12,9 @@
|
|
|
12
12
|
}
|
|
13
13
|
},
|
|
14
14
|
"dependencies": {
|
|
15
|
-
"@demicodes/core": "
|
|
16
|
-
"@demicodes/provider": "
|
|
17
|
-
"@demicodes/utils": "
|
|
15
|
+
"@demicodes/core": "0.2.0",
|
|
16
|
+
"@demicodes/provider": "0.2.0",
|
|
17
|
+
"@demicodes/utils": "0.2.0"
|
|
18
18
|
},
|
|
19
19
|
"license": "Apache-2.0",
|
|
20
20
|
"main": "./dist/index.mjs",
|