@yourgpt/llm-sdk 2.6.0-beta.1 → 2.6.0-beta.3
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 +146 -0
- package/dist/adapters/index.d.mts +5 -5
- package/dist/adapters/index.d.ts +5 -5
- package/dist/adapters/index.js +437 -39
- package/dist/adapters/index.mjs +437 -39
- package/dist/audio-BBSwnjo8.d.mts +92 -0
- package/dist/audio-BBSwnjo8.d.ts +92 -0
- package/dist/{base-CkeT7u-O.d.mts → base-BICaQaRS.d.mts} +7 -3
- package/dist/{base-BdTpUAWI.d.ts → base-CpRPB8u8.d.ts} +7 -3
- package/dist/fallback/index.d.mts +4 -4
- package/dist/fallback/index.d.ts +4 -4
- package/dist/index.d.mts +20 -36
- package/dist/index.d.ts +20 -36
- package/dist/index.js +327 -69
- package/dist/index.mjs +325 -70
- package/dist/providers/anthropic/index.d.mts +3 -3
- package/dist/providers/anthropic/index.d.ts +3 -3
- package/dist/providers/anthropic/index.js +116 -7
- package/dist/providers/anthropic/index.mjs +116 -7
- package/dist/providers/azure/index.d.mts +3 -3
- package/dist/providers/azure/index.d.ts +3 -3
- package/dist/providers/azure/index.js +101 -4
- package/dist/providers/azure/index.mjs +101 -4
- package/dist/providers/fireworks/index.d.mts +3 -3
- package/dist/providers/fireworks/index.d.ts +3 -3
- package/dist/providers/fireworks/index.js +393 -31
- package/dist/providers/fireworks/index.mjs +393 -31
- package/dist/providers/google/index.d.mts +3 -3
- package/dist/providers/google/index.d.ts +3 -3
- package/dist/providers/google/index.js +393 -31
- package/dist/providers/google/index.mjs +393 -31
- package/dist/providers/ollama/index.d.mts +4 -4
- package/dist/providers/ollama/index.d.ts +4 -4
- package/dist/providers/ollama/index.js +87 -2
- package/dist/providers/ollama/index.mjs +87 -2
- package/dist/providers/openai/index.d.mts +25 -6
- package/dist/providers/openai/index.d.ts +25 -6
- package/dist/providers/openai/index.js +822 -40
- package/dist/providers/openai/index.mjs +821 -41
- package/dist/providers/openrouter/index.d.mts +3 -3
- package/dist/providers/openrouter/index.d.ts +3 -3
- package/dist/providers/openrouter/index.js +393 -31
- package/dist/providers/openrouter/index.mjs +393 -31
- package/dist/providers/togetherai/index.d.mts +3 -3
- package/dist/providers/togetherai/index.d.ts +3 -3
- package/dist/providers/togetherai/index.js +393 -31
- package/dist/providers/togetherai/index.mjs +393 -31
- package/dist/providers/xai/index.d.mts +3 -3
- package/dist/providers/xai/index.d.ts +3 -3
- package/dist/providers/xai/index.js +393 -31
- package/dist/providers/xai/index.mjs +393 -31
- package/dist/{types-BWRYIvl_.d.mts → types-C3RgRbEC.d.mts} +1 -1
- package/dist/{types-CpXcT-tY.d.ts → types-DCFqkJAy.d.ts} +1 -1
- package/dist/{types-NOswlhm9.d.mts → types-DHQEMFHA.d.mts} +3 -3
- package/dist/{types-BW3csYo5.d.mts → types-Dg1Bcg1k.d.mts} +106 -3
- package/dist/{types-BW3csYo5.d.ts → types-Dg1Bcg1k.d.ts} +106 -3
- package/dist/{types-DA54bSmX.d.ts → types-Dikj3En4.d.ts} +3 -3
- package/dist/yourgpt/index.d.mts +1 -1
- package/dist/yourgpt/index.d.ts +1 -1
- package/docs/multimodal-and-audio.md +170 -0
- package/package.json +3 -2
|
@@ -1,5 +1,90 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
// src/core/tool-output.ts
|
|
4
|
+
var imageTypes = /* @__PURE__ */ new Set([
|
|
5
|
+
"image/png",
|
|
6
|
+
"image/jpeg",
|
|
7
|
+
"image/webp",
|
|
8
|
+
"image/gif"
|
|
9
|
+
]);
|
|
10
|
+
function normalizeToolOutput(value) {
|
|
11
|
+
const output = value;
|
|
12
|
+
if (output?.type !== "content" || !Array.isArray(output.content) || !output.content.length) {
|
|
13
|
+
throw new Error("Tool model output must contain a nonempty content array");
|
|
14
|
+
}
|
|
15
|
+
return {
|
|
16
|
+
type: "content",
|
|
17
|
+
content: output.content.map((part) => {
|
|
18
|
+
if (part?.type === "text" && typeof part.text === "string")
|
|
19
|
+
return { type: "text", text: part.text };
|
|
20
|
+
if (part?.type !== "image")
|
|
21
|
+
throw new Error("Unsupported tool output content type");
|
|
22
|
+
const sources = ["data", "url", "fileId"].filter((key) => key in part);
|
|
23
|
+
if (sources.length !== 1)
|
|
24
|
+
throw new Error(
|
|
25
|
+
"Tool image requires exactly one of data, url, or fileId"
|
|
26
|
+
);
|
|
27
|
+
if ("fileId" in part) {
|
|
28
|
+
if (part.provider !== "openai" || typeof part.fileId !== "string" || !part.fileId.trim())
|
|
29
|
+
throw new Error(
|
|
30
|
+
"Tool image file references must name the openai provider and fileId"
|
|
31
|
+
);
|
|
32
|
+
return { type: "image", fileId: part.fileId, provider: "openai" };
|
|
33
|
+
}
|
|
34
|
+
if ("url" in part) {
|
|
35
|
+
let url;
|
|
36
|
+
try {
|
|
37
|
+
url = new URL(part.url);
|
|
38
|
+
} catch {
|
|
39
|
+
throw new Error("Invalid tool image URL");
|
|
40
|
+
}
|
|
41
|
+
if (!["https:", "http:"].includes(url.protocol) || url.username || url.password)
|
|
42
|
+
throw new Error(
|
|
43
|
+
"Tool image URL must use HTTP(S) without credentials"
|
|
44
|
+
);
|
|
45
|
+
return { type: "image", url: url.href };
|
|
46
|
+
}
|
|
47
|
+
if (!("data" in part) || !imageTypes.has(part.mediaType))
|
|
48
|
+
throw new Error("Unsupported tool image media type");
|
|
49
|
+
let data = part.data instanceof Uint8Array ? Buffer.from(part.data).toString("base64") : part.data;
|
|
50
|
+
if (typeof data !== "string")
|
|
51
|
+
throw new Error("Tool image data must be base64 or bytes");
|
|
52
|
+
if (data.startsWith("data:")) {
|
|
53
|
+
const match = /^data:([^;,]+);base64,(.+)$/.exec(data);
|
|
54
|
+
if (!match || match[1] !== part.mediaType)
|
|
55
|
+
throw new Error(
|
|
56
|
+
"Tool image data URL media type does not match mediaType"
|
|
57
|
+
);
|
|
58
|
+
data = match[2];
|
|
59
|
+
}
|
|
60
|
+
if (!data.length || data.length % 4 !== 0 || !/^[A-Za-z0-9+/]+={0,2}$/.test(data))
|
|
61
|
+
throw new Error("Invalid tool image base64 data");
|
|
62
|
+
if (Buffer.byteLength(data, "base64") > 20 * 1024 * 1024)
|
|
63
|
+
throw new Error("Tool image exceeds 20 MiB");
|
|
64
|
+
if (Buffer.from(data, "base64").toString("base64") !== data)
|
|
65
|
+
throw new Error("Invalid tool image base64 data");
|
|
66
|
+
return { type: "image", data, mediaType: part.mediaType };
|
|
67
|
+
})
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
function toolOutputForProvider(value, provider) {
|
|
71
|
+
const output = normalizeToolOutput(value);
|
|
72
|
+
return output.content.map((part) => {
|
|
73
|
+
if (part.type === "text")
|
|
74
|
+
return {
|
|
75
|
+
type: "text",
|
|
76
|
+
text: part.text
|
|
77
|
+
};
|
|
78
|
+
throw new Error(
|
|
79
|
+
"Image tool results require OpenAI Responses or Anthropic; this endpoint is not supported"
|
|
80
|
+
);
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
function textToolOutput(value, fallback) {
|
|
84
|
+
if (value === void 0) return fallback;
|
|
85
|
+
return toolOutputForProvider(value).map((part) => part.text).join("\n");
|
|
86
|
+
}
|
|
87
|
+
|
|
3
88
|
// src/core/utils.ts
|
|
4
89
|
function generateId(prefix = "id") {
|
|
5
90
|
return `${prefix}_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;
|
|
@@ -150,7 +235,7 @@ async function formatMessagesForOllama(messages, systemPrompt) {
|
|
|
150
235
|
for (const msg of messages) {
|
|
151
236
|
const baseMessage = {
|
|
152
237
|
role: msg.role,
|
|
153
|
-
content: msg.content ?? ""
|
|
238
|
+
content: msg.role === "tool" ? textToolOutput(msg.modelOutput, msg.content ?? "") : msg.content ?? ""
|
|
154
239
|
};
|
|
155
240
|
if (msg.role === "user" && msg.metadata?.attachments) {
|
|
156
241
|
const images = await extractImagesFromAttachments(
|
|
@@ -187,7 +272,7 @@ async function processRawMessagesForOllama(rawMessages, systemPrompt) {
|
|
|
187
272
|
for (const msg of rawMessages) {
|
|
188
273
|
const baseMessage = {
|
|
189
274
|
role: msg.role,
|
|
190
|
-
content: msg.content ?? ""
|
|
275
|
+
content: msg.role === "tool" ? textToolOutput(msg.modelOutput, String(msg.content ?? "")) : msg.content ?? ""
|
|
191
276
|
};
|
|
192
277
|
if (msg.role === "user" && msg.attachments && Array.isArray(msg.attachments)) {
|
|
193
278
|
const attachments = msg.attachments;
|
|
@@ -1,3 +1,88 @@
|
|
|
1
|
+
// src/core/tool-output.ts
|
|
2
|
+
var imageTypes = /* @__PURE__ */ new Set([
|
|
3
|
+
"image/png",
|
|
4
|
+
"image/jpeg",
|
|
5
|
+
"image/webp",
|
|
6
|
+
"image/gif"
|
|
7
|
+
]);
|
|
8
|
+
function normalizeToolOutput(value) {
|
|
9
|
+
const output = value;
|
|
10
|
+
if (output?.type !== "content" || !Array.isArray(output.content) || !output.content.length) {
|
|
11
|
+
throw new Error("Tool model output must contain a nonempty content array");
|
|
12
|
+
}
|
|
13
|
+
return {
|
|
14
|
+
type: "content",
|
|
15
|
+
content: output.content.map((part) => {
|
|
16
|
+
if (part?.type === "text" && typeof part.text === "string")
|
|
17
|
+
return { type: "text", text: part.text };
|
|
18
|
+
if (part?.type !== "image")
|
|
19
|
+
throw new Error("Unsupported tool output content type");
|
|
20
|
+
const sources = ["data", "url", "fileId"].filter((key) => key in part);
|
|
21
|
+
if (sources.length !== 1)
|
|
22
|
+
throw new Error(
|
|
23
|
+
"Tool image requires exactly one of data, url, or fileId"
|
|
24
|
+
);
|
|
25
|
+
if ("fileId" in part) {
|
|
26
|
+
if (part.provider !== "openai" || typeof part.fileId !== "string" || !part.fileId.trim())
|
|
27
|
+
throw new Error(
|
|
28
|
+
"Tool image file references must name the openai provider and fileId"
|
|
29
|
+
);
|
|
30
|
+
return { type: "image", fileId: part.fileId, provider: "openai" };
|
|
31
|
+
}
|
|
32
|
+
if ("url" in part) {
|
|
33
|
+
let url;
|
|
34
|
+
try {
|
|
35
|
+
url = new URL(part.url);
|
|
36
|
+
} catch {
|
|
37
|
+
throw new Error("Invalid tool image URL");
|
|
38
|
+
}
|
|
39
|
+
if (!["https:", "http:"].includes(url.protocol) || url.username || url.password)
|
|
40
|
+
throw new Error(
|
|
41
|
+
"Tool image URL must use HTTP(S) without credentials"
|
|
42
|
+
);
|
|
43
|
+
return { type: "image", url: url.href };
|
|
44
|
+
}
|
|
45
|
+
if (!("data" in part) || !imageTypes.has(part.mediaType))
|
|
46
|
+
throw new Error("Unsupported tool image media type");
|
|
47
|
+
let data = part.data instanceof Uint8Array ? Buffer.from(part.data).toString("base64") : part.data;
|
|
48
|
+
if (typeof data !== "string")
|
|
49
|
+
throw new Error("Tool image data must be base64 or bytes");
|
|
50
|
+
if (data.startsWith("data:")) {
|
|
51
|
+
const match = /^data:([^;,]+);base64,(.+)$/.exec(data);
|
|
52
|
+
if (!match || match[1] !== part.mediaType)
|
|
53
|
+
throw new Error(
|
|
54
|
+
"Tool image data URL media type does not match mediaType"
|
|
55
|
+
);
|
|
56
|
+
data = match[2];
|
|
57
|
+
}
|
|
58
|
+
if (!data.length || data.length % 4 !== 0 || !/^[A-Za-z0-9+/]+={0,2}$/.test(data))
|
|
59
|
+
throw new Error("Invalid tool image base64 data");
|
|
60
|
+
if (Buffer.byteLength(data, "base64") > 20 * 1024 * 1024)
|
|
61
|
+
throw new Error("Tool image exceeds 20 MiB");
|
|
62
|
+
if (Buffer.from(data, "base64").toString("base64") !== data)
|
|
63
|
+
throw new Error("Invalid tool image base64 data");
|
|
64
|
+
return { type: "image", data, mediaType: part.mediaType };
|
|
65
|
+
})
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
function toolOutputForProvider(value, provider) {
|
|
69
|
+
const output = normalizeToolOutput(value);
|
|
70
|
+
return output.content.map((part) => {
|
|
71
|
+
if (part.type === "text")
|
|
72
|
+
return {
|
|
73
|
+
type: "text",
|
|
74
|
+
text: part.text
|
|
75
|
+
};
|
|
76
|
+
throw new Error(
|
|
77
|
+
"Image tool results require OpenAI Responses or Anthropic; this endpoint is not supported"
|
|
78
|
+
);
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
function textToolOutput(value, fallback) {
|
|
82
|
+
if (value === void 0) return fallback;
|
|
83
|
+
return toolOutputForProvider(value).map((part) => part.text).join("\n");
|
|
84
|
+
}
|
|
85
|
+
|
|
1
86
|
// src/core/utils.ts
|
|
2
87
|
function generateId(prefix = "id") {
|
|
3
88
|
return `${prefix}_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;
|
|
@@ -148,7 +233,7 @@ async function formatMessagesForOllama(messages, systemPrompt) {
|
|
|
148
233
|
for (const msg of messages) {
|
|
149
234
|
const baseMessage = {
|
|
150
235
|
role: msg.role,
|
|
151
|
-
content: msg.content ?? ""
|
|
236
|
+
content: msg.role === "tool" ? textToolOutput(msg.modelOutput, msg.content ?? "") : msg.content ?? ""
|
|
152
237
|
};
|
|
153
238
|
if (msg.role === "user" && msg.metadata?.attachments) {
|
|
154
239
|
const images = await extractImagesFromAttachments(
|
|
@@ -185,7 +270,7 @@ async function processRawMessagesForOllama(rawMessages, systemPrompt) {
|
|
|
185
270
|
for (const msg of rawMessages) {
|
|
186
271
|
const baseMessage = {
|
|
187
272
|
role: msg.role,
|
|
188
|
-
content: msg.content ?? ""
|
|
273
|
+
content: msg.role === "tool" ? textToolOutput(msg.modelOutput, String(msg.content ?? "")) : msg.content ?? ""
|
|
189
274
|
};
|
|
190
275
|
if (msg.role === "user" && msg.attachments && Array.isArray(msg.attachments)) {
|
|
191
276
|
const attachments = msg.attachments;
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export {
|
|
3
|
-
import { O as OpenAIProviderConfig, A as AIProvider } from '../../types-
|
|
1
|
+
import { ae as OpenAIParameterOptions, O as OpenAITransportOptions, L as LanguageModel } from '../../types-Dg1Bcg1k.mjs';
|
|
2
|
+
export { h as OpenAIReasoningEffort, ab as OpenAIResponseItem, ac as OpenAIResponseMetadata, aa as OpenAIResponsesOptions, P as ProviderMetadata } from '../../types-Dg1Bcg1k.mjs';
|
|
3
|
+
import { O as OpenAIProviderConfig, A as AIProvider } from '../../types-DHQEMFHA.mjs';
|
|
4
|
+
import { S as SpeechModel, T as TranscriptionModel } from '../../audio-BBSwnjo8.mjs';
|
|
4
5
|
import 'zod';
|
|
5
|
-
import '../../base-
|
|
6
|
+
import '../../base-BICaQaRS.mjs';
|
|
6
7
|
|
|
7
|
-
interface OpenAIProviderOptions extends OpenAIParameterOptions {
|
|
8
|
+
interface OpenAIProviderOptions extends OpenAIParameterOptions, OpenAITransportOptions {
|
|
8
9
|
/** API key (defaults to OPENAI_API_KEY env var) */
|
|
9
10
|
apiKey?: string;
|
|
10
11
|
/** Base URL for API (defaults to https://api.openai.com/v1) */
|
|
@@ -35,6 +36,24 @@ interface OpenAIProviderOptions extends OpenAIParameterOptions {
|
|
|
35
36
|
*/
|
|
36
37
|
declare function openai(modelId: string, options?: OpenAIProviderOptions): LanguageModel;
|
|
37
38
|
|
|
39
|
+
interface OpenAIAudioProviderOptions {
|
|
40
|
+
apiKey?: string;
|
|
41
|
+
baseUrl?: string;
|
|
42
|
+
organization?: string;
|
|
43
|
+
project?: string;
|
|
44
|
+
/** Custom fetch for proxies and tests. */
|
|
45
|
+
fetch?: typeof globalThis.fetch;
|
|
46
|
+
}
|
|
47
|
+
interface OpenAITranscriptionOptions {
|
|
48
|
+
timestampGranularities?: Array<"word" | "segment">;
|
|
49
|
+
includeLogprobs?: boolean;
|
|
50
|
+
chunkingStrategy?: "auto";
|
|
51
|
+
}
|
|
52
|
+
/** Server-side, buffered text-to-speech. No microphone or realtime session. */
|
|
53
|
+
declare function openaiSpeech(modelId?: string, config?: OpenAIAudioProviderOptions): SpeechModel;
|
|
54
|
+
/** Recorded-file transcription. Timestamp and diarization options are model-gated. */
|
|
55
|
+
declare function openaiTranscription(modelId?: string, config?: OpenAIAudioProviderOptions): TranscriptionModel;
|
|
56
|
+
|
|
38
57
|
/**
|
|
39
58
|
* OpenAI Provider
|
|
40
59
|
*
|
|
@@ -67,4 +86,4 @@ declare function openai(modelId: string, options?: OpenAIProviderOptions): Langu
|
|
|
67
86
|
declare function createOpenAI(config?: OpenAIProviderConfig): AIProvider;
|
|
68
87
|
declare const createOpenAIProvider: typeof createOpenAI;
|
|
69
88
|
|
|
70
|
-
export { OpenAIParameterOptions, type OpenAIProviderOptions, createOpenAI, openai as createOpenAIModel, createOpenAIProvider, openai };
|
|
89
|
+
export { type OpenAIAudioProviderOptions, OpenAIParameterOptions, type OpenAIProviderOptions, type OpenAITranscriptionOptions, OpenAITransportOptions, createOpenAI, openai as createOpenAIModel, createOpenAIProvider, openai, openaiSpeech, openaiTranscription };
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export {
|
|
3
|
-
import { O as OpenAIProviderConfig, A as AIProvider } from '../../types-
|
|
1
|
+
import { ae as OpenAIParameterOptions, O as OpenAITransportOptions, L as LanguageModel } from '../../types-Dg1Bcg1k.js';
|
|
2
|
+
export { h as OpenAIReasoningEffort, ab as OpenAIResponseItem, ac as OpenAIResponseMetadata, aa as OpenAIResponsesOptions, P as ProviderMetadata } from '../../types-Dg1Bcg1k.js';
|
|
3
|
+
import { O as OpenAIProviderConfig, A as AIProvider } from '../../types-Dikj3En4.js';
|
|
4
|
+
import { S as SpeechModel, T as TranscriptionModel } from '../../audio-BBSwnjo8.js';
|
|
4
5
|
import 'zod';
|
|
5
|
-
import '../../base-
|
|
6
|
+
import '../../base-CpRPB8u8.js';
|
|
6
7
|
|
|
7
|
-
interface OpenAIProviderOptions extends OpenAIParameterOptions {
|
|
8
|
+
interface OpenAIProviderOptions extends OpenAIParameterOptions, OpenAITransportOptions {
|
|
8
9
|
/** API key (defaults to OPENAI_API_KEY env var) */
|
|
9
10
|
apiKey?: string;
|
|
10
11
|
/** Base URL for API (defaults to https://api.openai.com/v1) */
|
|
@@ -35,6 +36,24 @@ interface OpenAIProviderOptions extends OpenAIParameterOptions {
|
|
|
35
36
|
*/
|
|
36
37
|
declare function openai(modelId: string, options?: OpenAIProviderOptions): LanguageModel;
|
|
37
38
|
|
|
39
|
+
interface OpenAIAudioProviderOptions {
|
|
40
|
+
apiKey?: string;
|
|
41
|
+
baseUrl?: string;
|
|
42
|
+
organization?: string;
|
|
43
|
+
project?: string;
|
|
44
|
+
/** Custom fetch for proxies and tests. */
|
|
45
|
+
fetch?: typeof globalThis.fetch;
|
|
46
|
+
}
|
|
47
|
+
interface OpenAITranscriptionOptions {
|
|
48
|
+
timestampGranularities?: Array<"word" | "segment">;
|
|
49
|
+
includeLogprobs?: boolean;
|
|
50
|
+
chunkingStrategy?: "auto";
|
|
51
|
+
}
|
|
52
|
+
/** Server-side, buffered text-to-speech. No microphone or realtime session. */
|
|
53
|
+
declare function openaiSpeech(modelId?: string, config?: OpenAIAudioProviderOptions): SpeechModel;
|
|
54
|
+
/** Recorded-file transcription. Timestamp and diarization options are model-gated. */
|
|
55
|
+
declare function openaiTranscription(modelId?: string, config?: OpenAIAudioProviderOptions): TranscriptionModel;
|
|
56
|
+
|
|
38
57
|
/**
|
|
39
58
|
* OpenAI Provider
|
|
40
59
|
*
|
|
@@ -67,4 +86,4 @@ declare function openai(modelId: string, options?: OpenAIProviderOptions): Langu
|
|
|
67
86
|
declare function createOpenAI(config?: OpenAIProviderConfig): AIProvider;
|
|
68
87
|
declare const createOpenAIProvider: typeof createOpenAI;
|
|
69
88
|
|
|
70
|
-
export { OpenAIParameterOptions, type OpenAIProviderOptions, createOpenAI, openai as createOpenAIModel, createOpenAIProvider, openai };
|
|
89
|
+
export { type OpenAIAudioProviderOptions, OpenAIParameterOptions, type OpenAIProviderOptions, type OpenAITranscriptionOptions, OpenAITransportOptions, createOpenAI, openai as createOpenAIModel, createOpenAIProvider, openai, openaiSpeech, openaiTranscription };
|