@galdor/provider-openai 0.3.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/convert.d.ts +165 -0
- package/dist/convert.d.ts.map +1 -0
- package/dist/convert.js +302 -0
- package/dist/convert.js.map +1 -0
- package/dist/embed.d.ts +72 -0
- package/dist/embed.d.ts.map +1 -0
- package/dist/embed.js +126 -0
- package/dist/embed.js.map +1 -0
- package/dist/errors.d.ts +46 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +89 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +97 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +149 -0
- package/dist/index.js.map +1 -0
- package/dist/stream.d.ts +40 -0
- package/dist/stream.d.ts.map +1 -0
- package/dist/stream.js +178 -0
- package/dist/stream.js.map +1 -0
- package/package.json +36 -0
- package/src/convert.ts +429 -0
- package/src/embed.test.ts +89 -0
- package/src/embed.ts +162 -0
- package/src/errors.ts +103 -0
- package/src/index.ts +198 -0
- package/src/openai.test.ts +184 -0
- package/src/stream.ts +245 -0
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Conversion between galdor's shared schema and the OpenAI Chat Completions API
|
|
3
|
+
* wire shape.
|
|
4
|
+
*
|
|
5
|
+
* On the wire OpenAI carries the system prompt as a `role: system` message and
|
|
6
|
+
* tool results as `role: tool` messages keyed by `tool_call_id`. The wire types
|
|
7
|
+
* declared below model OpenAI's snake_case JSON exactly. The two entry points are
|
|
8
|
+
* {@link buildRequest} (galdor request to wire request) and
|
|
9
|
+
* {@link responseFromWire} (wire response to galdor response).
|
|
10
|
+
*/
|
|
11
|
+
import { type Request, type Response } from "@galdor/core/provider";
|
|
12
|
+
import { type StopReason } from "@galdor/core/schema";
|
|
13
|
+
interface WireImageURL {
|
|
14
|
+
url: string;
|
|
15
|
+
detail?: string;
|
|
16
|
+
}
|
|
17
|
+
interface WireContentPart {
|
|
18
|
+
type: string;
|
|
19
|
+
text?: string;
|
|
20
|
+
image_url?: WireImageURL;
|
|
21
|
+
}
|
|
22
|
+
interface WireFuncCall {
|
|
23
|
+
name?: string;
|
|
24
|
+
arguments?: string;
|
|
25
|
+
}
|
|
26
|
+
interface WireToolCall {
|
|
27
|
+
id?: string;
|
|
28
|
+
type?: string;
|
|
29
|
+
function: WireFuncCall;
|
|
30
|
+
/** Only set on streaming deltas. */
|
|
31
|
+
index?: number;
|
|
32
|
+
}
|
|
33
|
+
interface WireMessage {
|
|
34
|
+
role: string;
|
|
35
|
+
content?: string | WireContentPart[];
|
|
36
|
+
name?: string;
|
|
37
|
+
tool_calls?: WireToolCall[];
|
|
38
|
+
tool_call_id?: string;
|
|
39
|
+
/** Reasoning from OpenAI-compatible models (e.g. DeepSeek-R1). Inbound only. */
|
|
40
|
+
reasoning_content?: string;
|
|
41
|
+
}
|
|
42
|
+
interface WireFuncDecl {
|
|
43
|
+
name: string;
|
|
44
|
+
description?: string;
|
|
45
|
+
parameters: unknown;
|
|
46
|
+
}
|
|
47
|
+
interface WireTool {
|
|
48
|
+
type: string;
|
|
49
|
+
function: WireFuncDecl;
|
|
50
|
+
}
|
|
51
|
+
interface WireJSONSchema {
|
|
52
|
+
name?: string;
|
|
53
|
+
strict?: boolean;
|
|
54
|
+
schema: unknown;
|
|
55
|
+
}
|
|
56
|
+
interface WireRespFormat {
|
|
57
|
+
type: string;
|
|
58
|
+
json_schema?: WireJSONSchema;
|
|
59
|
+
}
|
|
60
|
+
/** Serialized request body for the OpenAI /chat/completions endpoint. */
|
|
61
|
+
export interface ChatRequest {
|
|
62
|
+
model: string;
|
|
63
|
+
messages: WireMessage[];
|
|
64
|
+
max_tokens?: number;
|
|
65
|
+
max_completion_tokens?: number;
|
|
66
|
+
temperature?: number;
|
|
67
|
+
top_p?: number;
|
|
68
|
+
stop?: string[];
|
|
69
|
+
stream?: boolean;
|
|
70
|
+
stream_options?: {
|
|
71
|
+
include_usage: boolean;
|
|
72
|
+
};
|
|
73
|
+
tools?: WireTool[];
|
|
74
|
+
tool_choice?: string;
|
|
75
|
+
response_format?: WireRespFormat;
|
|
76
|
+
reasoning_effort?: string;
|
|
77
|
+
user?: string;
|
|
78
|
+
}
|
|
79
|
+
interface WireTokenDetails {
|
|
80
|
+
cached_tokens?: number;
|
|
81
|
+
}
|
|
82
|
+
/** Token accounting block as returned by OpenAI, in its snake_case form. */
|
|
83
|
+
export interface WireUsage {
|
|
84
|
+
prompt_tokens?: number;
|
|
85
|
+
completion_tokens?: number;
|
|
86
|
+
total_tokens?: number;
|
|
87
|
+
prompt_tokens_details?: WireTokenDetails;
|
|
88
|
+
}
|
|
89
|
+
interface WireResponseMessage {
|
|
90
|
+
role?: string;
|
|
91
|
+
content?: string | WireContentPart[];
|
|
92
|
+
tool_calls?: WireToolCall[];
|
|
93
|
+
reasoning_content?: string;
|
|
94
|
+
}
|
|
95
|
+
interface WireChoice {
|
|
96
|
+
index?: number;
|
|
97
|
+
message: WireResponseMessage;
|
|
98
|
+
finish_reason?: string;
|
|
99
|
+
}
|
|
100
|
+
/** Decoded body of a non-streaming OpenAI /chat/completions response. */
|
|
101
|
+
export interface ChatResponse {
|
|
102
|
+
id?: string;
|
|
103
|
+
object?: string;
|
|
104
|
+
created?: number;
|
|
105
|
+
model?: string;
|
|
106
|
+
choices?: WireChoice[];
|
|
107
|
+
usage?: WireUsage;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Translate a galdor {@link Request} into an OpenAI Chat Completions wire
|
|
111
|
+
* request.
|
|
112
|
+
*
|
|
113
|
+
* Maps messages, tools, tool choice and response format; toggles
|
|
114
|
+
* `stream`/`stream_options` for streaming; and applies o-series reasoning rules,
|
|
115
|
+
* where the effort level is set and `max_tokens` is moved to
|
|
116
|
+
* `max_completion_tokens` while `temperature` and `top_p` are dropped (those
|
|
117
|
+
* models reject them).
|
|
118
|
+
*
|
|
119
|
+
* @param req - The provider-neutral galdor request to translate.
|
|
120
|
+
* @param stream - When true, request a streamed response with usage included.
|
|
121
|
+
* @returns The wire-ready {@link ChatRequest}.
|
|
122
|
+
* @throws {Error} When `req.model` is empty, or a message contains an unknown
|
|
123
|
+
* role or unsupported content type.
|
|
124
|
+
* @example
|
|
125
|
+
* ```ts
|
|
126
|
+
* const wire = buildRequest({ model: "gpt-4o-mini", messages }, false);
|
|
127
|
+
* ```
|
|
128
|
+
*/
|
|
129
|
+
export declare function buildRequest(req: Request, stream: boolean): ChatRequest;
|
|
130
|
+
/**
|
|
131
|
+
* Convert OpenAI's wire usage block into galdor's {@link Usage} shape.
|
|
132
|
+
*
|
|
133
|
+
* @param u - The wire usage object, or `undefined` when absent.
|
|
134
|
+
* @returns A usage record; missing fields default to 0. Cached prompt tokens are
|
|
135
|
+
* reported as cache reads; cache-creation tokens are always 0.
|
|
136
|
+
*/
|
|
137
|
+
export declare function usageFromWire(u: WireUsage | undefined): {
|
|
138
|
+
inputTokens: number;
|
|
139
|
+
outputTokens: number;
|
|
140
|
+
cacheCreationTokens: number;
|
|
141
|
+
cacheReadTokens: number;
|
|
142
|
+
};
|
|
143
|
+
/**
|
|
144
|
+
* Map an OpenAI `finish_reason` string to a galdor {@link StopReason}.
|
|
145
|
+
*
|
|
146
|
+
* @param s - The wire finish reason (e.g. `"stop"`, `"length"`, `"tool_calls"`).
|
|
147
|
+
* @returns The corresponding {@link StopReason}; an empty or absent value
|
|
148
|
+
* becomes `"end_turn"`, and an unrecognized value is passed through unchanged.
|
|
149
|
+
*/
|
|
150
|
+
export declare function normalizeFinishReason(s: string | undefined): StopReason;
|
|
151
|
+
/**
|
|
152
|
+
* Collapse a non-streaming Chat Completions response into a galdor
|
|
153
|
+
* {@link Response}.
|
|
154
|
+
*
|
|
155
|
+
* Reads the first choice: surfaces any reasoning content as a thinking part,
|
|
156
|
+
* appends decoded text, and collects tool calls (parsing their JSON arguments).
|
|
157
|
+
*
|
|
158
|
+
* @param r - The decoded wire response.
|
|
159
|
+
* @param raw - Optional raw response bytes, attached as `providerRaw` when given.
|
|
160
|
+
* @returns The assembled galdor {@link Response} with message, stop reason,
|
|
161
|
+
* usage and model.
|
|
162
|
+
*/
|
|
163
|
+
export declare function responseFromWire(r: ChatResponse, raw?: Uint8Array): Response;
|
|
164
|
+
export {};
|
|
165
|
+
//# sourceMappingURL=convert.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"convert.d.ts","sourceRoot":"","sources":["../src/convert.ts"],"names":[],"mappings":"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"}
|
package/dist/convert.js
ADDED
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Conversion between galdor's shared schema and the OpenAI Chat Completions API
|
|
3
|
+
* wire shape.
|
|
4
|
+
*
|
|
5
|
+
* On the wire OpenAI carries the system prompt as a `role: system` message and
|
|
6
|
+
* tool results as `role: tool` messages keyed by `tool_call_id`. The wire types
|
|
7
|
+
* declared below model OpenAI's snake_case JSON exactly. The two entry points are
|
|
8
|
+
* {@link buildRequest} (galdor request to wire request) and
|
|
9
|
+
* {@link responseFromWire} (wire response to galdor response).
|
|
10
|
+
*/
|
|
11
|
+
import { InvalidRequestError } from "@galdor/core/provider";
|
|
12
|
+
import { ContentType, messageText, Role, textPart, thinkingPart, } from "@galdor/core/schema";
|
|
13
|
+
/** Build a typed invalid-request error for a request that cannot be lowered to the wire. */
|
|
14
|
+
function invalidRequest(message) {
|
|
15
|
+
return new InvalidRequestError({ kind: "invalid_request", provider: "openai", statusCode: 0, message });
|
|
16
|
+
}
|
|
17
|
+
// ── Request building ─────────────────────────────────────────────────────────
|
|
18
|
+
function toBase64(data) {
|
|
19
|
+
return Buffer.from(data).toString("base64");
|
|
20
|
+
}
|
|
21
|
+
/** Render an image part as OpenAI's image_url.url (direct URL or data: URL). */
|
|
22
|
+
function imageToURL(img) {
|
|
23
|
+
if (img.url && img.url !== "")
|
|
24
|
+
return img.url;
|
|
25
|
+
if (img.data && img.data.length > 0) {
|
|
26
|
+
if (!img.media)
|
|
27
|
+
throw invalidRequest("openai: inline image missing media (MIME type)");
|
|
28
|
+
return `data:${img.media};base64,${toBase64(img.data)}`;
|
|
29
|
+
}
|
|
30
|
+
throw invalidRequest("openai: image part with no url or data");
|
|
31
|
+
}
|
|
32
|
+
function partsToWire(parts) {
|
|
33
|
+
const out = [];
|
|
34
|
+
for (const p of parts) {
|
|
35
|
+
switch (p.type) {
|
|
36
|
+
case ContentType.Text:
|
|
37
|
+
out.push({ type: "text", text: p.text ?? "" });
|
|
38
|
+
break;
|
|
39
|
+
case ContentType.Image:
|
|
40
|
+
if (!p.image)
|
|
41
|
+
throw invalidRequest("openai: image part with nil image");
|
|
42
|
+
out.push({ type: "image_url", image_url: { url: imageToURL(p.image) } });
|
|
43
|
+
break;
|
|
44
|
+
case ContentType.Thinking:
|
|
45
|
+
case ContentType.RedactedThinking:
|
|
46
|
+
// Reasoning is model output, not input: never echo it back.
|
|
47
|
+
continue;
|
|
48
|
+
default:
|
|
49
|
+
throw invalidRequest(`openai: unsupported content type ${p.type}`);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return out;
|
|
53
|
+
}
|
|
54
|
+
function roleToWire(r) {
|
|
55
|
+
switch (r) {
|
|
56
|
+
case Role.System:
|
|
57
|
+
return "system";
|
|
58
|
+
case Role.User:
|
|
59
|
+
return "user";
|
|
60
|
+
case Role.Assistant:
|
|
61
|
+
return "assistant";
|
|
62
|
+
case Role.Tool:
|
|
63
|
+
return "tool";
|
|
64
|
+
default:
|
|
65
|
+
throw invalidRequest(`openai: unknown role ${r}`);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
function messageToWire(m) {
|
|
69
|
+
const wm = { role: roleToWire(m.role) };
|
|
70
|
+
if (m.name)
|
|
71
|
+
wm.name = m.name;
|
|
72
|
+
if (m.toolCallId)
|
|
73
|
+
wm.tool_call_id = m.toolCallId;
|
|
74
|
+
// Assistant tool calls.
|
|
75
|
+
const toolCalls = [];
|
|
76
|
+
for (const tc of m.toolCalls ?? []) {
|
|
77
|
+
toolCalls.push({
|
|
78
|
+
id: tc.id,
|
|
79
|
+
type: "function",
|
|
80
|
+
function: { name: tc.name, arguments: stringifyArguments(tc.arguments) },
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
if (toolCalls.length > 0)
|
|
84
|
+
wm.tool_calls = toolCalls;
|
|
85
|
+
// Content. Prefer the plain-string form when all parts are text; use the
|
|
86
|
+
// array form when any non-text part is present.
|
|
87
|
+
const allText = m.content.every((p) => p.type === ContentType.Text);
|
|
88
|
+
if (m.content.length === 0 && toolCalls.length > 0) {
|
|
89
|
+
// Assistant tool-call-only messages omit content.
|
|
90
|
+
}
|
|
91
|
+
else if (allText) {
|
|
92
|
+
wm.content = messageText(m);
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
wm.content = partsToWire(m.content);
|
|
96
|
+
}
|
|
97
|
+
return wm;
|
|
98
|
+
}
|
|
99
|
+
function stringifyArguments(args) {
|
|
100
|
+
if (args === undefined || args === null)
|
|
101
|
+
return "{}";
|
|
102
|
+
if (typeof args === "string")
|
|
103
|
+
return args;
|
|
104
|
+
return JSON.stringify(args);
|
|
105
|
+
}
|
|
106
|
+
function toolChoiceToWire(c) {
|
|
107
|
+
switch (c) {
|
|
108
|
+
case "auto":
|
|
109
|
+
return "auto";
|
|
110
|
+
case "none":
|
|
111
|
+
return "none";
|
|
112
|
+
case "required":
|
|
113
|
+
return "required";
|
|
114
|
+
default:
|
|
115
|
+
return undefined;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
function responseFormatToWire(rf) {
|
|
119
|
+
if (!rf)
|
|
120
|
+
return undefined;
|
|
121
|
+
switch (rf.type) {
|
|
122
|
+
case "json_object":
|
|
123
|
+
return { type: "json_object" };
|
|
124
|
+
case "json_schema":
|
|
125
|
+
return {
|
|
126
|
+
type: "json_schema",
|
|
127
|
+
json_schema: { ...(rf.name ? { name: rf.name } : {}), strict: true, schema: rf.schema },
|
|
128
|
+
};
|
|
129
|
+
default:
|
|
130
|
+
return undefined;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Translate a galdor {@link Request} into an OpenAI Chat Completions wire
|
|
135
|
+
* request.
|
|
136
|
+
*
|
|
137
|
+
* Maps messages, tools, tool choice and response format; toggles
|
|
138
|
+
* `stream`/`stream_options` for streaming; and applies o-series reasoning rules,
|
|
139
|
+
* where the effort level is set and `max_tokens` is moved to
|
|
140
|
+
* `max_completion_tokens` while `temperature` and `top_p` are dropped (those
|
|
141
|
+
* models reject them).
|
|
142
|
+
*
|
|
143
|
+
* @param req - The provider-neutral galdor request to translate.
|
|
144
|
+
* @param stream - When true, request a streamed response with usage included.
|
|
145
|
+
* @returns The wire-ready {@link ChatRequest}.
|
|
146
|
+
* @throws {Error} When `req.model` is empty, or a message contains an unknown
|
|
147
|
+
* role or unsupported content type.
|
|
148
|
+
* @example
|
|
149
|
+
* ```ts
|
|
150
|
+
* const wire = buildRequest({ model: "gpt-4o-mini", messages }, false);
|
|
151
|
+
* ```
|
|
152
|
+
*/
|
|
153
|
+
export function buildRequest(req, stream) {
|
|
154
|
+
if (req.model === "")
|
|
155
|
+
throw invalidRequest("openai: model is required");
|
|
156
|
+
const out = { model: req.model, messages: req.messages.map(messageToWire) };
|
|
157
|
+
if (req.maxTokens !== undefined)
|
|
158
|
+
out.max_tokens = req.maxTokens;
|
|
159
|
+
if (req.temperature !== undefined)
|
|
160
|
+
out.temperature = req.temperature;
|
|
161
|
+
if (req.topP !== undefined)
|
|
162
|
+
out.top_p = req.topP;
|
|
163
|
+
// Only emit `stop` when non-empty; an empty array is a no-op some backends reject.
|
|
164
|
+
if (req.stopSequences && req.stopSequences.length > 0)
|
|
165
|
+
out.stop = req.stopSequences;
|
|
166
|
+
if (stream) {
|
|
167
|
+
out.stream = true;
|
|
168
|
+
out.stream_options = { include_usage: true };
|
|
169
|
+
}
|
|
170
|
+
if (req.tools && req.tools.length > 0) {
|
|
171
|
+
out.tools = req.tools.map((t) => ({
|
|
172
|
+
type: "function",
|
|
173
|
+
function: { name: t.name, ...(t.description ? { description: t.description } : {}), parameters: t.schema },
|
|
174
|
+
}));
|
|
175
|
+
}
|
|
176
|
+
const tc = toolChoiceToWire(req.toolChoice);
|
|
177
|
+
if (tc)
|
|
178
|
+
out.tool_choice = tc;
|
|
179
|
+
const rf = responseFormatToWire(req.responseFormat);
|
|
180
|
+
if (rf)
|
|
181
|
+
out.response_format = rf;
|
|
182
|
+
if (req.reasoning?.enabled) {
|
|
183
|
+
// OpenAI is effort-based (o-series): map the effort level, defaulting to
|
|
184
|
+
// medium. Budget is ignored.
|
|
185
|
+
out.reasoning_effort = req.reasoning.effort ?? "medium";
|
|
186
|
+
// o-series reasoning models reject max_tokens (use max_completion_tokens)
|
|
187
|
+
// and reject temperature / top_p. Move and drop them so the request is
|
|
188
|
+
// accepted.
|
|
189
|
+
if (out.max_tokens !== undefined)
|
|
190
|
+
out.max_completion_tokens = out.max_tokens;
|
|
191
|
+
delete out.max_tokens;
|
|
192
|
+
delete out.temperature;
|
|
193
|
+
delete out.top_p;
|
|
194
|
+
}
|
|
195
|
+
const uid = req.metadata?.user_id;
|
|
196
|
+
if (uid)
|
|
197
|
+
out.user = uid;
|
|
198
|
+
return out;
|
|
199
|
+
}
|
|
200
|
+
// ── Response decoding ────────────────────────────────────────────────────────
|
|
201
|
+
/** Concatenate text from either content form (plain string or part array). */
|
|
202
|
+
function decodeContent(content) {
|
|
203
|
+
if (content === undefined)
|
|
204
|
+
return "";
|
|
205
|
+
if (typeof content === "string")
|
|
206
|
+
return content;
|
|
207
|
+
let out = "";
|
|
208
|
+
for (const p of content) {
|
|
209
|
+
if (p.type === "text" && p.text)
|
|
210
|
+
out += p.text;
|
|
211
|
+
}
|
|
212
|
+
return out;
|
|
213
|
+
}
|
|
214
|
+
function parseArguments(raw) {
|
|
215
|
+
if (!raw || raw === "")
|
|
216
|
+
return {};
|
|
217
|
+
try {
|
|
218
|
+
return JSON.parse(raw);
|
|
219
|
+
}
|
|
220
|
+
catch {
|
|
221
|
+
return raw;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Convert OpenAI's wire usage block into galdor's {@link Usage} shape.
|
|
226
|
+
*
|
|
227
|
+
* @param u - The wire usage object, or `undefined` when absent.
|
|
228
|
+
* @returns A usage record; missing fields default to 0. Cached prompt tokens are
|
|
229
|
+
* reported as cache reads; cache-creation tokens are always 0.
|
|
230
|
+
*/
|
|
231
|
+
export function usageFromWire(u) {
|
|
232
|
+
return {
|
|
233
|
+
inputTokens: u?.prompt_tokens ?? 0,
|
|
234
|
+
outputTokens: u?.completion_tokens ?? 0,
|
|
235
|
+
cacheCreationTokens: 0,
|
|
236
|
+
cacheReadTokens: u?.prompt_tokens_details?.cached_tokens ?? 0,
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Map an OpenAI `finish_reason` string to a galdor {@link StopReason}.
|
|
241
|
+
*
|
|
242
|
+
* @param s - The wire finish reason (e.g. `"stop"`, `"length"`, `"tool_calls"`).
|
|
243
|
+
* @returns The corresponding {@link StopReason}; an empty or absent value
|
|
244
|
+
* becomes `"end_turn"`, and an unrecognized value is passed through unchanged.
|
|
245
|
+
*/
|
|
246
|
+
export function normalizeFinishReason(s) {
|
|
247
|
+
switch (s) {
|
|
248
|
+
case "stop":
|
|
249
|
+
return "end_turn";
|
|
250
|
+
case "length":
|
|
251
|
+
return "max_tokens";
|
|
252
|
+
case "tool_calls":
|
|
253
|
+
case "function_call":
|
|
254
|
+
return "tool_use";
|
|
255
|
+
case "content_filter":
|
|
256
|
+
return "refusal";
|
|
257
|
+
default:
|
|
258
|
+
return (s === undefined || s === "" ? "end_turn" : s);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* Collapse a non-streaming Chat Completions response into a galdor
|
|
263
|
+
* {@link Response}.
|
|
264
|
+
*
|
|
265
|
+
* Reads the first choice: surfaces any reasoning content as a thinking part,
|
|
266
|
+
* appends decoded text, and collects tool calls (parsing their JSON arguments).
|
|
267
|
+
*
|
|
268
|
+
* @param r - The decoded wire response.
|
|
269
|
+
* @param raw - Optional raw response bytes, attached as `providerRaw` when given.
|
|
270
|
+
* @returns The assembled galdor {@link Response} with message, stop reason,
|
|
271
|
+
* usage and model.
|
|
272
|
+
*/
|
|
273
|
+
export function responseFromWire(r, raw) {
|
|
274
|
+
const message = { role: Role.Assistant, content: [] };
|
|
275
|
+
let stopReason = "end_turn";
|
|
276
|
+
const choice = r.choices?.[0];
|
|
277
|
+
if (choice) {
|
|
278
|
+
stopReason = normalizeFinishReason(choice.finish_reason);
|
|
279
|
+
if (choice.message.reasoning_content) {
|
|
280
|
+
// Reasoning from an OpenAI-compatible model (e.g. DeepSeek). messageText
|
|
281
|
+
// skips it, so the answer stays clean.
|
|
282
|
+
message.content.push(thinkingPart(choice.message.reasoning_content));
|
|
283
|
+
}
|
|
284
|
+
const text = decodeContent(choice.message.content);
|
|
285
|
+
if (text !== "")
|
|
286
|
+
message.content.push(textPart(text));
|
|
287
|
+
const toolCalls = [];
|
|
288
|
+
for (const t of choice.message.tool_calls ?? []) {
|
|
289
|
+
toolCalls.push({ id: t.id ?? "", name: t.function.name ?? "", arguments: parseArguments(t.function.arguments) });
|
|
290
|
+
}
|
|
291
|
+
if (toolCalls.length > 0)
|
|
292
|
+
message.toolCalls = toolCalls;
|
|
293
|
+
}
|
|
294
|
+
return {
|
|
295
|
+
message,
|
|
296
|
+
stopReason,
|
|
297
|
+
usage: usageFromWire(r.usage),
|
|
298
|
+
model: r.model ?? "",
|
|
299
|
+
...(raw ? { providerRaw: raw } : {}),
|
|
300
|
+
};
|
|
301
|
+
}
|
|
302
|
+
//# sourceMappingURL=convert.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"convert.js","sourceRoot":"","sources":["../src/convert.ts"],"names":[],"mappings":"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"}
|
package/dist/embed.d.ts
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenAI embeddings — a galdor {@link Embedder} over the `/embeddings` endpoint.
|
|
3
|
+
*
|
|
4
|
+
* Works against the OpenAI API and any OpenAI-compatible endpoint (Mistral,
|
|
5
|
+
* Together, MiniMax, vLLM, Ollama, …) by pointing {@link EmbedderConfig.baseURL}
|
|
6
|
+
* at it. Construct one with {@link newEmbedder}.
|
|
7
|
+
*/
|
|
8
|
+
import type { Embedder } from "@galdor/core/memory";
|
|
9
|
+
/** Configuration for an {@link OpenAIEmbedder}. */
|
|
10
|
+
export interface EmbedderConfig {
|
|
11
|
+
/** Authenticates against the API. Required. */
|
|
12
|
+
apiKey: string;
|
|
13
|
+
/** Embedding model id. Defaults to `"text-embedding-3-small"`. */
|
|
14
|
+
model?: string;
|
|
15
|
+
/**
|
|
16
|
+
* Vector size. Defaults to the model's native size (1536 for
|
|
17
|
+
* `text-embedding-3-small`). When set and the model supports it (the
|
|
18
|
+
* `text-embedding-3-*` family), it is sent as `dimensions` to truncate output.
|
|
19
|
+
*/
|
|
20
|
+
dimensions?: number;
|
|
21
|
+
/** Overrides the API endpoint. Default `https://api.openai.com/v1`; the `/v1` segment is part of it. */
|
|
22
|
+
baseURL?: string;
|
|
23
|
+
/** Sent as `openai-organization` when non-empty. */
|
|
24
|
+
organization?: string;
|
|
25
|
+
/** Sent as `openai-project` when non-empty. */
|
|
26
|
+
project?: string;
|
|
27
|
+
/** Sent as the `User-Agent` header when non-empty. */
|
|
28
|
+
userAgent?: string;
|
|
29
|
+
/** Per-request timeout in milliseconds. Defaults to 60000; `0` disables it. */
|
|
30
|
+
timeoutMs?: number;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* A galdor {@link Embedder} backed by the OpenAI embeddings API.
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* ```ts
|
|
37
|
+
* const embedder = newEmbedder({ apiKey: process.env.OPENAI_API_KEY! });
|
|
38
|
+
* const [vec] = await embedder.embed(["quito ecuador capital"]);
|
|
39
|
+
* ```
|
|
40
|
+
*/
|
|
41
|
+
export declare class OpenAIEmbedder implements Embedder {
|
|
42
|
+
#private;
|
|
43
|
+
/**
|
|
44
|
+
* @param cfg - Embedder configuration; `apiKey` is required.
|
|
45
|
+
* @throws {Error} When `apiKey` is missing or blank.
|
|
46
|
+
*/
|
|
47
|
+
constructor(cfg: EmbedderConfig);
|
|
48
|
+
/** @returns The embedding model id. */
|
|
49
|
+
model(): string;
|
|
50
|
+
/**
|
|
51
|
+
* @returns The embedding vector size: the configured/learned size when known,
|
|
52
|
+
* otherwise the model's native default until the first response sets it.
|
|
53
|
+
*/
|
|
54
|
+
dimensions(): number;
|
|
55
|
+
/**
|
|
56
|
+
* Embed each input text, preserving order: `out[i]` is the vector for `texts[i]`.
|
|
57
|
+
*
|
|
58
|
+
* @param texts - Inputs to embed; an empty array returns `[]`.
|
|
59
|
+
* @returns One vector per input, ordered to match `texts`.
|
|
60
|
+
* @throws {Error} On a non-2xx response, or when the API returns the wrong number of vectors.
|
|
61
|
+
*/
|
|
62
|
+
embed(texts: string[], signal?: AbortSignal): Promise<number[][]>;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Construct an {@link OpenAIEmbedder}.
|
|
66
|
+
*
|
|
67
|
+
* @param cfg - Embedder configuration; `apiKey` is required.
|
|
68
|
+
* @returns A ready embedder.
|
|
69
|
+
* @throws {Error} When `apiKey` is missing or blank.
|
|
70
|
+
*/
|
|
71
|
+
export declare function newEmbedder(cfg: EmbedderConfig): OpenAIEmbedder;
|
|
72
|
+
//# sourceMappingURL=embed.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"embed.d.ts","sourceRoot":"","sources":["../src/embed.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAYpD,mDAAmD;AACnD,MAAM,WAAW,cAAc;IAC7B,+CAA+C;IAC/C,MAAM,EAAE,MAAM,CAAC;IACf,kEAAkE;IAClE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,wGAAwG;IACxG,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,oDAAoD;IACpD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,+CAA+C;IAC/C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,sDAAsD;IACtD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,+EAA+E;IAC/E,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAQD;;;;;;;;GAQG;AACH,qBAAa,cAAe,YAAW,QAAQ;;IAY7C;;;OAGG;gBACS,GAAG,EAAE,cAAc;IAc/B,uCAAuC;IACvC,KAAK,IAAI,MAAM;IAIf;;;OAGG;IACH,UAAU,IAAI,MAAM;IAIpB;;;;;;OAMG;IACG,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;CAyCxE;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,cAAc,GAAG,cAAc,CAE/D"}
|