@simulacra-ai/openai 0.0.10 → 0.0.12
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.cjs +130 -32
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +48 -4
- package/dist/index.d.ts +48 -4
- package/dist/index.js +130 -32
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -25,6 +25,7 @@ __export(index_exports, {
|
|
|
25
25
|
module.exports = __toCommonJS(index_exports);
|
|
26
26
|
|
|
27
27
|
// src/openai-provider.ts
|
|
28
|
+
var OPENAI_REASONING_DELTA_KEYS = ["reasoning", "reasoning_content", "thinking"];
|
|
28
29
|
var OpenAIProvider = class _OpenAIProvider {
|
|
29
30
|
#sdk;
|
|
30
31
|
#config;
|
|
@@ -50,7 +51,8 @@ var OpenAIProvider = class _OpenAIProvider {
|
|
|
50
51
|
* @returns A promise that resolves when the request completes.
|
|
51
52
|
*/
|
|
52
53
|
async execute_request(request, receiver, cancellation) {
|
|
53
|
-
const { model, max_tokens, ...api_extras } = this.#config;
|
|
54
|
+
const { model, max_tokens, system_role, strict_tools, ...api_extras } = this.#config;
|
|
55
|
+
const emit_strict = resolve_strict_tools(model, strict_tools);
|
|
54
56
|
const params = {
|
|
55
57
|
...api_extras,
|
|
56
58
|
model,
|
|
@@ -58,10 +60,10 @@ var OpenAIProvider = class _OpenAIProvider {
|
|
|
58
60
|
max_tokens,
|
|
59
61
|
...request.tools.length > 0 ? {
|
|
60
62
|
tool_choice: "auto",
|
|
61
|
-
tools: request.tools.map((t) => to_openai_tool(t))
|
|
63
|
+
tools: request.tools.map((t) => to_openai_tool(t, emit_strict))
|
|
62
64
|
} : {},
|
|
63
65
|
messages: [
|
|
64
|
-
...get_system_context(model, request.system),
|
|
66
|
+
...get_system_context(model, request.system, system_role),
|
|
65
67
|
...request.messages.flatMap((m) => to_openai_messages(m))
|
|
66
68
|
],
|
|
67
69
|
stream_options: {
|
|
@@ -123,6 +125,30 @@ var OpenAIProvider = class _OpenAIProvider {
|
|
|
123
125
|
}
|
|
124
126
|
choice.delta.refusal += delta_chunk.refusal;
|
|
125
127
|
}
|
|
128
|
+
const reasoning_delta = get_openai_reasoning_delta(delta_chunk);
|
|
129
|
+
if (reasoning_delta) {
|
|
130
|
+
const choice_delta = choice.delta;
|
|
131
|
+
const existing = choice_delta[reasoning_delta.key];
|
|
132
|
+
if (!existing) {
|
|
133
|
+
choice_delta[reasoning_delta.key] = reasoning_delta.thought;
|
|
134
|
+
receiver.start_content({
|
|
135
|
+
content: from_openai_thinking(choice_delta),
|
|
136
|
+
message: from_openai_completion(response_chunk, choice),
|
|
137
|
+
usage: response?.usage ? from_openai_usage(response.usage) : {}
|
|
138
|
+
});
|
|
139
|
+
receiver.update_message({
|
|
140
|
+
message: from_openai_completion(response_chunk, choice),
|
|
141
|
+
usage: response?.usage ? from_openai_usage(response.usage) : {}
|
|
142
|
+
});
|
|
143
|
+
} else {
|
|
144
|
+
choice_delta[reasoning_delta.key] = existing + reasoning_delta.thought;
|
|
145
|
+
receiver.update_content({
|
|
146
|
+
content: from_openai_thinking(choice_delta),
|
|
147
|
+
message: from_openai_completion(response_chunk, choice),
|
|
148
|
+
usage: response?.usage ? from_openai_usage(response.usage) : {}
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
}
|
|
126
152
|
if (delta_chunk.content) {
|
|
127
153
|
if (!choice.delta.content) {
|
|
128
154
|
choice.delta.content = delta_chunk.content;
|
|
@@ -212,26 +238,48 @@ var OpenAIProvider = class _OpenAIProvider {
|
|
|
212
238
|
}
|
|
213
239
|
}
|
|
214
240
|
};
|
|
215
|
-
function get_system_context(model, system) {
|
|
241
|
+
function get_system_context(model, system, system_role = "auto") {
|
|
216
242
|
if (!system) {
|
|
217
243
|
return [];
|
|
218
244
|
}
|
|
219
|
-
|
|
245
|
+
const role = resolve_system_role(model, system_role);
|
|
246
|
+
if (role === "developer") {
|
|
220
247
|
return [
|
|
221
248
|
{
|
|
222
|
-
role: "
|
|
249
|
+
role: "developer",
|
|
223
250
|
content: system
|
|
224
251
|
}
|
|
225
252
|
];
|
|
226
253
|
}
|
|
227
254
|
return [
|
|
228
255
|
{
|
|
229
|
-
role: "
|
|
256
|
+
role: "system",
|
|
230
257
|
content: system
|
|
231
258
|
}
|
|
232
259
|
];
|
|
233
260
|
}
|
|
234
|
-
function
|
|
261
|
+
function resolve_system_role(model, system_role = "auto") {
|
|
262
|
+
if (system_role === "system" || system_role === "developer") {
|
|
263
|
+
return system_role;
|
|
264
|
+
}
|
|
265
|
+
if (model.startsWith("gpt")) {
|
|
266
|
+
return "system";
|
|
267
|
+
}
|
|
268
|
+
if (is_openai_reasoning_model(model)) {
|
|
269
|
+
return "developer";
|
|
270
|
+
}
|
|
271
|
+
return "system";
|
|
272
|
+
}
|
|
273
|
+
function resolve_strict_tools(model, strict_tools = "auto") {
|
|
274
|
+
if (strict_tools === "never") {
|
|
275
|
+
return false;
|
|
276
|
+
}
|
|
277
|
+
return model.startsWith("gpt") || is_openai_reasoning_model(model);
|
|
278
|
+
}
|
|
279
|
+
function is_openai_reasoning_model(model) {
|
|
280
|
+
return /^o[1-9]\d*(-|$)/.test(model);
|
|
281
|
+
}
|
|
282
|
+
function to_openai_tool(tool, strict) {
|
|
235
283
|
function map_parameter_type(parameter) {
|
|
236
284
|
switch (parameter.type) {
|
|
237
285
|
case "object":
|
|
@@ -270,25 +318,44 @@ function to_openai_tool(tool) {
|
|
|
270
318
|
tool.parameters.map(({ name, ...parameter }) => [name, parameter])
|
|
271
319
|
)
|
|
272
320
|
}),
|
|
273
|
-
strict: true
|
|
321
|
+
...strict ? { strict: true } : {}
|
|
274
322
|
}
|
|
275
323
|
};
|
|
276
324
|
}
|
|
277
325
|
function from_openai_completion(completion, choice) {
|
|
278
326
|
let contents = [];
|
|
279
|
-
|
|
280
|
-
|
|
327
|
+
const thinking = from_openai_thinking(choice.delta);
|
|
328
|
+
if (thinking) {
|
|
329
|
+
contents = [...contents, thinking];
|
|
330
|
+
}
|
|
331
|
+
const delta_record = choice.delta;
|
|
332
|
+
for (const key of Object.keys(choice.delta)) {
|
|
281
333
|
if (key === "role") {
|
|
282
334
|
continue;
|
|
283
335
|
}
|
|
284
|
-
if (key
|
|
285
|
-
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
336
|
+
if (is_openai_reasoning_delta_key(key)) {
|
|
337
|
+
continue;
|
|
338
|
+
}
|
|
339
|
+
if (key === "content") {
|
|
340
|
+
if (choice.delta.content) {
|
|
341
|
+
contents = [...contents, from_openai_content(choice.delta)];
|
|
342
|
+
}
|
|
343
|
+
continue;
|
|
344
|
+
}
|
|
345
|
+
if (key === "refusal") {
|
|
346
|
+
if (choice.delta.refusal) {
|
|
347
|
+
contents = [...contents, from_openai_refusal(choice.delta)];
|
|
348
|
+
}
|
|
349
|
+
continue;
|
|
350
|
+
}
|
|
351
|
+
if (key === "tool_calls") {
|
|
352
|
+
if (choice.delta.tool_calls) {
|
|
353
|
+
contents = [...contents, ...choice.delta.tool_calls.map((t) => from_openai_tool_call(t))];
|
|
354
|
+
}
|
|
355
|
+
continue;
|
|
356
|
+
}
|
|
357
|
+
if (delta_record[key] !== void 0 && delta_record[key] !== null) {
|
|
358
|
+
const data = delta_record[key];
|
|
292
359
|
contents = [
|
|
293
360
|
...contents,
|
|
294
361
|
{
|
|
@@ -306,32 +373,63 @@ function from_openai_completion(completion, choice) {
|
|
|
306
373
|
content: contents
|
|
307
374
|
};
|
|
308
375
|
}
|
|
376
|
+
function get_openai_reasoning_delta(delta) {
|
|
377
|
+
const record = delta;
|
|
378
|
+
for (const key of OPENAI_REASONING_DELTA_KEYS) {
|
|
379
|
+
const thought = record[key];
|
|
380
|
+
if (typeof thought === "string" && thought.length > 0) {
|
|
381
|
+
return { key, thought };
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
return void 0;
|
|
385
|
+
}
|
|
386
|
+
function from_openai_thinking(content) {
|
|
387
|
+
const reasoning = get_openai_reasoning_delta(content);
|
|
388
|
+
if (!reasoning) {
|
|
389
|
+
return void 0;
|
|
390
|
+
}
|
|
391
|
+
const extended = get_openai_delta_extended(content);
|
|
392
|
+
return {
|
|
393
|
+
type: "thinking",
|
|
394
|
+
thought: reasoning.thought,
|
|
395
|
+
extended: {
|
|
396
|
+
...extended,
|
|
397
|
+
openai_reasoning_field: reasoning.key
|
|
398
|
+
}
|
|
399
|
+
};
|
|
400
|
+
}
|
|
401
|
+
function is_openai_reasoning_delta_key(key) {
|
|
402
|
+
return OPENAI_REASONING_DELTA_KEYS.includes(key);
|
|
403
|
+
}
|
|
309
404
|
function from_openai_refusal(content) {
|
|
310
|
-
const { refusal, tool_calls: _, function_call: __, content: ___, role: ____, ...rest } = content;
|
|
311
405
|
return {
|
|
312
406
|
type: "text",
|
|
313
|
-
text: refusal,
|
|
407
|
+
text: content.refusal,
|
|
314
408
|
extended: {
|
|
315
|
-
...
|
|
409
|
+
...get_openai_delta_extended(content),
|
|
316
410
|
openai_refusal: true
|
|
317
411
|
}
|
|
318
412
|
};
|
|
319
413
|
}
|
|
320
414
|
function from_openai_content(content) {
|
|
321
|
-
const {
|
|
322
|
-
content: c,
|
|
323
|
-
tool_calls: _,
|
|
324
|
-
function_call: __,
|
|
325
|
-
refusal: ___,
|
|
326
|
-
role: ____,
|
|
327
|
-
...rest
|
|
328
|
-
} = content;
|
|
329
415
|
return {
|
|
330
416
|
type: "text",
|
|
331
|
-
text:
|
|
332
|
-
extended:
|
|
417
|
+
text: content.content,
|
|
418
|
+
extended: get_openai_delta_extended(content)
|
|
333
419
|
};
|
|
334
420
|
}
|
|
421
|
+
function get_openai_delta_extended(content) {
|
|
422
|
+
const extended = { ...content };
|
|
423
|
+
delete extended.content;
|
|
424
|
+
delete extended.tool_calls;
|
|
425
|
+
delete extended.function_call;
|
|
426
|
+
delete extended.refusal;
|
|
427
|
+
delete extended.role;
|
|
428
|
+
for (const key of OPENAI_REASONING_DELTA_KEYS) {
|
|
429
|
+
delete extended[key];
|
|
430
|
+
}
|
|
431
|
+
return extended;
|
|
432
|
+
}
|
|
335
433
|
function from_openai_tool_call(tool_call) {
|
|
336
434
|
const { id: tool_request_id, function: fn, type: _, index: __, ...extended } = tool_call;
|
|
337
435
|
let params;
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/openai-provider.ts"],"sourcesContent":["export { OpenAIProvider, type OpenAIProviderConfig } from \"./openai-provider.ts\";\n","import { OpenAI } from \"openai\";\n\nimport type {\n AssistantContent,\n AssistantMessage,\n CancellationToken,\n CompletionResponseData,\n Content,\n Message,\n ModelProvider,\n ModelRequest,\n ParameterType,\n ProviderContextTransformer,\n StreamReceiver,\n ToolContent,\n ToolDefinition,\n Usage,\n} from \"@simulacra-ai/core\";\n\ntype Prettify<T> = { [K in keyof T]: T[K] } & {};\n\n/**\n * Configuration options for the OpenAI provider.\n */\nexport interface OpenAIProviderConfig extends Record<string, unknown> {\n /** The model identifier to use (e.g., \"gpt-4\", \"o1-preview\"). */\n model: string;\n /** The maximum number of tokens to generate in the response. */\n max_tokens?: number;\n}\n\n/**\n * Model provider implementation for OpenAI's chat completion models.\n *\n * This provider wraps the OpenAI SDK to provide streaming completions with support\n * for tool use and function calling. It handles message formatting, content streaming,\n * and usage tracking according to the ModelProvider interface. Supports both GPT models\n * (using system messages) and O-series models (using developer messages).\n */\nexport class OpenAIProvider implements ModelProvider {\n readonly #sdk: OpenAI;\n readonly #config: OpenAIProviderConfig;\n readonly context_transformers: ProviderContextTransformer[];\n\n /**\n * Creates a new OpenAI provider instance.\n *\n * @param sdk - The initialized OpenAI SDK client.\n * @param config - Configuration options for the provider.\n * @param context_transformers - Provider-level context transformers.\n */\n constructor(\n sdk: OpenAI,\n config: OpenAIProviderConfig,\n context_transformers: ProviderContextTransformer[] = [],\n ) {\n this.#sdk = sdk;\n this.#config = config;\n this.context_transformers = context_transformers;\n }\n\n /**\n * Executes a model request and streams the response through the provided receiver.\n *\n * @param request - The request containing messages, tools, and system prompt.\n * @param receiver - The receiver that handles streaming events.\n * @param cancellation - Token to signal cancellation of the request.\n * @returns A promise that resolves when the request completes.\n */\n async execute_request(\n request: ModelRequest,\n receiver: StreamReceiver,\n cancellation: CancellationToken,\n ): Promise<void> {\n const { model, max_tokens, ...api_extras } = this.#config;\n const params: OpenAI.ChatCompletionCreateParamsStreaming = {\n ...api_extras,\n model,\n stream: true,\n max_tokens,\n ...(request.tools.length > 0\n ? {\n tool_choice: \"auto\",\n tools: request.tools.map((t) => to_openai_tool(t)),\n }\n : {}),\n messages: [\n ...get_system_context(model, request.system),\n ...request.messages.flatMap((m) => to_openai_messages(m)),\n ],\n stream_options: {\n include_usage: true,\n },\n };\n\n receiver.before_request({ params });\n receiver.request_raw(params);\n\n const stream = await this.#sdk.chat.completions.create(params);\n\n // Intentionally not awaited. Streaming is event-driven through the receiver.\n // The policy wraps only connection establishment; chunk processing flows\n // asynchronously via StreamListener events back to the conversation.\n this.#stream_response(stream, receiver, cancellation);\n }\n\n /**\n * Creates a clone of this provider with the same configuration.\n *\n * @returns A new provider instance with identical configuration.\n */\n clone(): ModelProvider {\n return new OpenAIProvider(this.#sdk, this.#config, this.context_transformers);\n }\n\n async #stream_response(\n stream: AsyncIterable<OpenAI.Chat.Completions.ChatCompletionChunk>,\n receiver: StreamReceiver,\n cancellation: CancellationToken,\n ) {\n try {\n let response: OpenAI.Chat.Completions.ChatCompletionChunk | undefined;\n for await (const response_chunk of stream) {\n if (cancellation.is_cancellation_requested) {\n receiver.cancel();\n return;\n }\n receiver.stream_raw(response_chunk);\n\n const { choices: choices_chunk, ...rest } = response_chunk;\n response = {\n ...response,\n ...rest,\n choices: response?.choices ?? [],\n };\n\n for (const choice_chunk of choices_chunk) {\n if (!response.choices[choice_chunk.index]) {\n response.choices[choice_chunk.index] = choice_chunk;\n const message = from_openai_completion(response_chunk, choice_chunk);\n for (const content of message.content) {\n receiver.start_content({ content, message, usage: {} });\n }\n receiver.start_message({ message, usage: {} });\n continue;\n }\n\n const { delta: delta_chunk, ...rest } = choice_chunk;\n const choice = (response.choices[choice_chunk.index] = {\n ...response.choices[choice_chunk.index],\n ...rest,\n delta: {\n ...response.choices[choice_chunk.index]?.delta,\n },\n });\n\n if (delta_chunk.role) {\n choice.delta.role = delta_chunk.role;\n }\n if (delta_chunk.refusal) {\n if (!choice.delta.refusal) {\n choice.delta.refusal = \"\";\n }\n choice.delta.refusal += delta_chunk.refusal;\n }\n if (delta_chunk.content) {\n if (!choice.delta.content) {\n choice.delta.content = delta_chunk.content;\n receiver.start_content({\n content: from_openai_content(choice.delta) as AssistantContent,\n message: from_openai_completion(response_chunk, choice),\n usage: response?.usage ? from_openai_usage(response.usage) : {},\n });\n receiver.update_message({\n message: from_openai_completion(response_chunk, choice),\n usage: response?.usage ? from_openai_usage(response.usage) : {},\n });\n } else {\n choice.delta.content += delta_chunk.content;\n receiver.update_content({\n content: from_openai_content(choice.delta) as AssistantContent,\n message: from_openai_completion(response_chunk, choice),\n usage: response?.usage ? from_openai_usage(response.usage) : {},\n });\n }\n }\n if (delta_chunk.tool_calls) {\n if (!choice.delta.tool_calls) {\n choice.delta.tool_calls = [];\n }\n for (const tool_call_chunk of delta_chunk.tool_calls) {\n if (!choice.delta.tool_calls[tool_call_chunk.index]) {\n choice.delta.tool_calls[tool_call_chunk.index] = tool_call_chunk;\n receiver.start_content({\n content: from_openai_tool_call(tool_call_chunk),\n message: from_openai_completion(response_chunk, choice),\n usage: response?.usage ? from_openai_usage(response.usage) : {},\n });\n receiver.update_message({\n message: from_openai_completion(response_chunk, choice),\n usage: response?.usage ? from_openai_usage(response.usage) : {},\n });\n } else {\n const tool_call = choice.delta.tool_calls[tool_call_chunk.index];\n\n if (tool_call_chunk.id) {\n tool_call.id = tool_call_chunk.id;\n }\n if (tool_call_chunk.type) {\n tool_call.type = tool_call_chunk.type;\n }\n if (tool_call_chunk.function) {\n if (!tool_call.function) {\n tool_call.function = tool_call_chunk.function;\n } else {\n if (tool_call_chunk.function.name) {\n tool_call.function.name = tool_call_chunk.function.name;\n }\n if (tool_call_chunk.function.arguments) {\n if (!tool_call.function.arguments) {\n tool_call.function.arguments = \"\";\n }\n tool_call.function.arguments += tool_call_chunk.function.arguments;\n }\n }\n }\n receiver.update_content({\n content: from_openai_tool_call(tool_call),\n message: from_openai_completion(response_chunk, choice),\n usage: response?.usage ? from_openai_usage(response.usage) : {},\n });\n receiver.update_message({\n message: from_openai_completion(response_chunk, choice),\n usage: response?.usage ? from_openai_usage(response.usage) : {},\n });\n }\n }\n }\n }\n }\n if (!response || !response.choices?.[0]) {\n throw new Error(\"no data\");\n }\n receiver.response_raw({ ...response });\n\n const message = from_openai_completion(response, response.choices[0]);\n const usage = response?.usage ? from_openai_usage(response.usage) : {};\n for (const content of message.content) {\n receiver.complete_content({ content, message, usage });\n }\n receiver.complete_message({ message, usage, ...map_stop_reason(response) });\n } catch (error) {\n receiver.error(error);\n }\n }\n}\n\nfunction get_system_context(model: string, system?: string): OpenAI.ChatCompletionMessageParam[] {\n if (!system) {\n return [];\n }\n if (model.startsWith(\"gpt\")) {\n return [\n {\n role: \"system\",\n content: system,\n } as OpenAI.ChatCompletionSystemMessageParam,\n ];\n }\n return [\n {\n role: \"developer\",\n content: system,\n } as OpenAI.ChatCompletionDeveloperMessageParam,\n ];\n}\n\nfunction to_openai_tool(tool: ToolDefinition): OpenAI.Chat.ChatCompletionTool {\n function map_parameter_type(\n parameter: Prettify<ParameterType & { description?: string }>,\n ): OpenAI.FunctionParameters {\n switch (parameter.type) {\n case \"object\":\n return {\n type: parameter.required ? parameter.type : [parameter.type, \"null\"],\n description: parameter.description,\n properties: Object.fromEntries(\n Object.entries(parameter.properties).map(([k, v]) => [k, map_parameter_type(v)]),\n ),\n additionalProperties: false,\n required: Object.entries(parameter.properties).map(([k]) => k),\n };\n case \"array\":\n return {\n type: parameter.required ? parameter.type : [parameter.type, \"null\"],\n description: parameter.description,\n items: map_parameter_type(parameter.items),\n };\n default:\n return {\n type: parameter.required ? parameter.type : [parameter.type, \"null\"],\n description:\n parameter.default !== undefined\n ? parameter.description\n ? `${parameter.description} (default: ${parameter.default})`\n : `default: ${parameter.default}`\n : parameter.description,\n enum: \"enum\" in parameter ? parameter.enum : undefined,\n };\n }\n }\n return {\n type: \"function\",\n function: {\n name: tool.name,\n description: tool.description,\n parameters: map_parameter_type({\n type: \"object\",\n required: true,\n properties: Object.fromEntries(\n tool.parameters.map(({ name, ...parameter }) => [name, parameter]),\n ),\n }),\n strict: true,\n },\n };\n}\n\nfunction from_openai_completion(\n completion: OpenAI.Chat.Completions.ChatCompletionChunk,\n choice: OpenAI.Chat.Completions.ChatCompletionChunk.Choice,\n) {\n let contents: Content[] = [];\n for (const k in choice.delta) {\n const key = k as keyof typeof choice.delta;\n if (key === \"role\") {\n continue;\n }\n if (key === \"content\" && choice.delta.content) {\n contents = [...contents, from_openai_content(choice.delta)];\n } else if (key === \"refusal\" && choice.delta.refusal) {\n contents = [...contents, from_openai_refusal(choice.delta)];\n } else if (key === \"tool_calls\" && choice.delta.tool_calls) {\n contents = [...contents, ...choice.delta.tool_calls.map((t) => from_openai_tool_call(t))];\n } else if (choice.delta[key] !== undefined && choice.delta[key] !== null) {\n const { [key]: data } = choice.delta;\n contents = [\n ...contents,\n {\n type: \"raw\",\n model_kind: \"openai\",\n data: JSON.stringify({ [key]: data }),\n },\n ];\n }\n }\n return {\n id: completion.id,\n timestamp: completion.created,\n role: map_role(choice),\n content: contents,\n } as AssistantMessage;\n}\n\nfunction from_openai_refusal(content: OpenAI.Chat.Completions.ChatCompletionChunk.Choice.Delta) {\n const { refusal, tool_calls: _, function_call: __, content: ___, role: ____, ...rest } = content;\n return {\n type: \"text\",\n text: refusal,\n extended: {\n ...rest,\n openai_refusal: true,\n },\n } as Content;\n}\n\nfunction from_openai_content(content: OpenAI.Chat.Completions.ChatCompletionChunk.Choice.Delta) {\n const {\n content: c,\n tool_calls: _,\n function_call: __,\n refusal: ___,\n role: ____,\n ...rest\n } = content;\n return {\n type: \"text\",\n text: c,\n extended: rest,\n } as Content;\n}\n\nfunction from_openai_tool_call(\n tool_call: OpenAI.Chat.Completions.ChatCompletionChunk.Choice.Delta.ToolCall,\n) {\n const { id: tool_request_id, function: fn, type: _, index: __, ...extended } = tool_call;\n let params: unknown;\n try {\n params = JSON.parse(fn?.arguments ?? \"{}\");\n } catch {\n params = fn?.arguments;\n }\n return {\n tool_request_id,\n type: \"tool\",\n tool: fn?.name,\n params,\n extended,\n } as ToolContent;\n}\n\nfunction to_openai_messages(message: Message) {\n if (message.role === \"assistant\") {\n return [to_openai_assistant_message(message)];\n }\n // Partition content so tool_result blocks come before non-tool_result blocks.\n // OpenAI requires all tool-role messages immediately after the assistant message\n // containing the corresponding tool_calls; interleaving user messages between\n // tool messages causes a validation error.\n const tool_result_content = message.content.filter((c) => c.type === \"tool_result\");\n const other_content = message.content.filter((c) => c.type !== \"tool_result\");\n const ordered_content = [...tool_result_content, ...other_content];\n\n const results: OpenAI.ChatCompletionMessageParam[] = [];\n let result: OpenAI.ChatCompletionMessageParam | undefined;\n for (const content of ordered_content) {\n if (content.type === \"text\") {\n if (!result) {\n result = {\n role: \"user\",\n content: content.text,\n };\n } else if (result.role === \"tool\") {\n results.push(result);\n result = {\n role: \"user\",\n content: content.text,\n };\n } else {\n if (typeof result.content === \"string\") {\n result.content = [\n {\n type: \"text\",\n text: result.content,\n },\n ];\n }\n if (!result.content) {\n result.content = [\n {\n type: \"text\",\n text: content.text,\n },\n ];\n } else {\n result.content.push({\n type: \"text\",\n text: content.text,\n });\n }\n }\n } else if (content.type === \"tool_result\") {\n if (!result) {\n result = {\n role: \"tool\",\n tool_call_id: content.tool_request_id,\n content: JSON.stringify(content.result),\n };\n } else if (result.role !== \"tool\" || result.tool_call_id !== content.tool_request_id) {\n results.push(result);\n result = {\n role: \"tool\",\n tool_call_id: content.tool_request_id,\n content: JSON.stringify(content.result),\n };\n } else {\n if (typeof result.content === \"string\") {\n result.content = [\n {\n type: \"text\",\n text: result.content,\n },\n ];\n }\n result.content.push({\n type: \"text\",\n text: JSON.stringify(content.result),\n });\n }\n } else if (content.type === \"raw\") {\n result = {\n ...(result ?? {}),\n ...JSON.parse(content.data),\n };\n }\n }\n if (result) {\n results.push(result);\n }\n return results;\n}\n\nfunction to_openai_assistant_message(message: AssistantMessage) {\n let result: OpenAI.ChatCompletionAssistantMessageParam = {\n role: \"assistant\",\n };\n for (const content of message.content) {\n switch (content.type) {\n case \"text\":\n if (content.extended && content.extended.openai_refusal === true) {\n result.refusal = content.text;\n } else {\n if (typeof result.content === \"string\") {\n result.content = [\n {\n type: \"text\",\n text: result.content,\n },\n ];\n }\n if (!result.content) {\n result.content = content.text;\n } else {\n result.content.push({\n type: \"text\",\n text: content.text,\n });\n }\n }\n break;\n case \"tool\":\n if (!result.tool_calls) {\n result.tool_calls = [];\n }\n result.tool_calls.push({\n id: content.tool_request_id,\n type: \"function\",\n function: {\n name: content.tool,\n arguments: JSON.stringify(content.params),\n },\n });\n break;\n case \"raw\":\n if (content.model_kind !== \"openai\") {\n if (typeof result.content === \"string\") {\n result.content = [\n {\n type: \"text\",\n text: result.content,\n },\n ];\n }\n if (!result.content) {\n result.content = content.data;\n } else {\n result.content.push({\n type: \"text\",\n text: content.data,\n });\n }\n break;\n }\n result = {\n ...result,\n ...JSON.parse(content.data),\n };\n break;\n case \"thinking\":\n if (typeof result.content === \"string\") {\n result.content = [\n {\n type: \"text\",\n text: result.content,\n },\n ];\n }\n if (!result.content) {\n result.content = content.thought;\n } else {\n result.content.push({\n type: \"text\",\n text: content.thought,\n });\n }\n break;\n default:\n throw new Error(\"unexpected content type\");\n }\n }\n return result;\n}\n\nfunction from_openai_usage(usage: OpenAI.CompletionUsage | null | undefined) {\n return {\n input_tokens: usage?.prompt_tokens,\n output_tokens: usage?.completion_tokens,\n } as Usage;\n}\n\nfunction map_stop_reason(\n completion: OpenAI.ChatCompletionChunk,\n): Pick<CompletionResponseData, \"stop_reason\" | \"stop_details\"> {\n for (const choice of completion.choices) {\n switch (choice.finish_reason) {\n case \"content_filter\":\n return {\n stop_reason: \"error\",\n stop_details: choice.finish_reason,\n };\n case \"function_call\":\n return {\n stop_reason: \"tool_use\",\n };\n case \"length\":\n return {\n stop_reason: \"max_tokens\",\n };\n case \"stop\":\n return {\n stop_reason: \"end_turn\",\n };\n case \"tool_calls\":\n return {\n stop_reason: \"tool_use\",\n };\n default:\n return {\n stop_reason: \"other\",\n stop_details: `${choice.finish_reason}`,\n };\n }\n }\n return {\n stop_reason: \"other\",\n };\n}\n\nfunction map_role(choice: OpenAI.Chat.Completions.ChatCompletionChunk.Choice) {\n switch (choice.delta.role) {\n case \"user\":\n case \"developer\":\n case \"system\":\n return \"user\";\n case \"assistant\":\n case \"tool\":\n return \"assistant\";\n default:\n throw new Error(\"invalid role\");\n }\n}\n"],"mappings":"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","names":["message","rest"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/openai-provider.ts"],"sourcesContent":["export { OpenAIProvider, type OpenAIProviderConfig } from \"./openai-provider.ts\";\n","import { OpenAI } from \"openai\";\n\nimport type {\n AssistantContent,\n AssistantMessage,\n CancellationToken,\n CompletionResponseData,\n Content,\n Message,\n ModelProvider,\n ModelRequest,\n ParameterType,\n ProviderContextTransformer,\n StreamReceiver,\n ToolContent,\n ToolDefinition,\n Usage,\n} from \"@simulacra-ai/core\";\n\ntype Prettify<T> = { [K in keyof T]: T[K] } & {};\n\nconst OPENAI_REASONING_DELTA_KEYS = [\"reasoning\", \"reasoning_content\", \"thinking\"] as const;\n\ntype OpenAIReasoningDeltaKey = (typeof OPENAI_REASONING_DELTA_KEYS)[number];\ntype OpenAICompletionDelta = OpenAI.Chat.Completions.ChatCompletionChunk.Choice.Delta;\ntype OpenAIReasoningDelta = OpenAICompletionDelta &\n Partial<Record<OpenAIReasoningDeltaKey, string>>;\n\n/**\n * Configuration options for the OpenAI provider.\n */\nexport interface OpenAIProviderConfig extends Record<string, unknown> {\n /** The model identifier to use (e.g., \"gpt-4\", \"o1-preview\"). */\n model: string;\n /** The maximum number of tokens to generate in the response. */\n max_tokens?: number;\n /**\n * Which role to use for the system prompt.\n *\n * The OpenAI Chat Completions spec allows `system` (legacy / most providers)\n * and `developer` (introduced for o-series reasoning models). Most\n * OpenAI-compatible endpoints (DeepSeek, OpenRouter relays, Anthropic-via-\n * compat, self-hosted gateways, etc.) only accept `system` and reject\n * `developer` with a 400.\n *\n * - `\"auto\"` (default): use the built-in heuristic — `gpt*` → `\"system\"`,\n * o-series (`o1`, `o3`, `o4`, ...) → `\"developer\"`, anything else →\n * `\"system\"` (the broadly-compatible default).\n * - `\"system\"` / `\"developer\"`: force the role regardless of model id.\n *\n * The heuristic matches on the bare model id and does not understand\n * relay-style prefixes (`openai/o3`, `anthropic/claude-3-5-sonnet`,\n * etc.) — set this explicitly when routing OpenAI models through a\n * relay that uses `vendor/model` ids.\n */\n system_role?: \"auto\" | \"system\" | \"developer\";\n /**\n * Whether to emit OpenAI's strict structured-output flag on tool\n * definitions (`function.strict: true`).\n *\n * `strict` is an OpenAI-specific extension that constrains tool arguments\n * to the supplied JSON Schema. Most non-OpenAI endpoints either ignore the\n * field or reject it.\n *\n * - `\"auto\"` (default): emit `strict: true` when the model id matches the\n * built-in OpenAI heuristic — `gpt*` or o-series (`o1`, `o3`, `o4`, ...).\n * Any other model id (deepseek, etc.) gets tool defs without `strict`.\n * The heuristic matches on the bare model id; relay-style prefixes\n * (`openai/gpt-4o`) are NOT recognized — set this explicitly when\n * routing OpenAI models through a relay.\n * - `\"never\"`: never emit `strict`.\n */\n strict_tools?: \"auto\" | \"never\";\n}\n\n/**\n * Model provider implementation for OpenAI's chat completion models.\n *\n * This provider wraps the OpenAI SDK to provide streaming completions with\n * support for tool use and function calling. It handles message formatting,\n * content streaming, and usage tracking according to the ModelProvider\n * interface.\n *\n * Works against OpenAI directly as well as OpenAI-compatible endpoints\n * (DeepSeek, OpenRouter, self-hosted gateways, etc.). The default behaviour\n * picks `system` vs. `developer` for the system prompt and decides whether\n * to emit OpenAI's `strict` flag on tool defs based on the model id; both\n * can be overridden through `OpenAIProviderConfig.system_role` and\n * `OpenAIProviderConfig.strict_tools` for endpoints whose behaviour differs.\n */\nexport class OpenAIProvider implements ModelProvider {\n readonly #sdk: OpenAI;\n readonly #config: OpenAIProviderConfig;\n readonly context_transformers: ProviderContextTransformer[];\n\n /**\n * Creates a new OpenAI provider instance.\n *\n * @param sdk - The initialized OpenAI SDK client.\n * @param config - Configuration options for the provider.\n * @param context_transformers - Provider-level context transformers.\n */\n constructor(\n sdk: OpenAI,\n config: OpenAIProviderConfig,\n context_transformers: ProviderContextTransformer[] = [],\n ) {\n this.#sdk = sdk;\n this.#config = config;\n this.context_transformers = context_transformers;\n }\n\n /**\n * Executes a model request and streams the response through the provided receiver.\n *\n * @param request - The request containing messages, tools, and system prompt.\n * @param receiver - The receiver that handles streaming events.\n * @param cancellation - Token to signal cancellation of the request.\n * @returns A promise that resolves when the request completes.\n */\n async execute_request(\n request: ModelRequest,\n receiver: StreamReceiver,\n cancellation: CancellationToken,\n ): Promise<void> {\n const { model, max_tokens, system_role, strict_tools, ...api_extras } = this.#config;\n const emit_strict = resolve_strict_tools(model, strict_tools);\n const params: OpenAI.ChatCompletionCreateParamsStreaming = {\n ...api_extras,\n model,\n stream: true,\n max_tokens,\n ...(request.tools.length > 0\n ? {\n tool_choice: \"auto\",\n tools: request.tools.map((t) => to_openai_tool(t, emit_strict)),\n }\n : {}),\n messages: [\n ...get_system_context(model, request.system, system_role),\n ...request.messages.flatMap((m) => to_openai_messages(m)),\n ],\n stream_options: {\n include_usage: true,\n },\n };\n\n receiver.before_request({ params });\n receiver.request_raw(params);\n\n const stream = await this.#sdk.chat.completions.create(params);\n\n // Intentionally not awaited. Streaming is event-driven through the receiver.\n // The policy wraps only connection establishment; chunk processing flows\n // asynchronously via StreamListener events back to the conversation.\n this.#stream_response(stream, receiver, cancellation);\n }\n\n /**\n * Creates a clone of this provider with the same configuration.\n *\n * @returns A new provider instance with identical configuration.\n */\n clone(): ModelProvider {\n return new OpenAIProvider(this.#sdk, this.#config, this.context_transformers);\n }\n\n async #stream_response(\n stream: AsyncIterable<OpenAI.Chat.Completions.ChatCompletionChunk>,\n receiver: StreamReceiver,\n cancellation: CancellationToken,\n ) {\n try {\n let response: OpenAI.Chat.Completions.ChatCompletionChunk | undefined;\n for await (const response_chunk of stream) {\n if (cancellation.is_cancellation_requested) {\n receiver.cancel();\n return;\n }\n receiver.stream_raw(response_chunk);\n\n const { choices: choices_chunk, ...rest } = response_chunk;\n response = {\n ...response,\n ...rest,\n choices: response?.choices ?? [],\n };\n\n for (const choice_chunk of choices_chunk) {\n if (!response.choices[choice_chunk.index]) {\n response.choices[choice_chunk.index] = choice_chunk;\n const message = from_openai_completion(response_chunk, choice_chunk);\n for (const content of message.content) {\n receiver.start_content({ content, message, usage: {} });\n }\n receiver.start_message({ message, usage: {} });\n continue;\n }\n\n const { delta: delta_chunk, ...rest } = choice_chunk;\n const choice = (response.choices[choice_chunk.index] = {\n ...response.choices[choice_chunk.index],\n ...rest,\n delta: {\n ...response.choices[choice_chunk.index]?.delta,\n },\n });\n\n if (delta_chunk.role) {\n choice.delta.role = delta_chunk.role;\n }\n if (delta_chunk.refusal) {\n if (!choice.delta.refusal) {\n choice.delta.refusal = \"\";\n }\n choice.delta.refusal += delta_chunk.refusal;\n }\n const reasoning_delta = get_openai_reasoning_delta(delta_chunk);\n if (reasoning_delta) {\n const choice_delta = choice.delta as OpenAIReasoningDelta;\n const existing = choice_delta[reasoning_delta.key];\n if (!existing) {\n choice_delta[reasoning_delta.key] = reasoning_delta.thought;\n receiver.start_content({\n content: from_openai_thinking(choice_delta) as AssistantContent,\n message: from_openai_completion(response_chunk, choice),\n usage: response?.usage ? from_openai_usage(response.usage) : {},\n });\n receiver.update_message({\n message: from_openai_completion(response_chunk, choice),\n usage: response?.usage ? from_openai_usage(response.usage) : {},\n });\n } else {\n choice_delta[reasoning_delta.key] = existing + reasoning_delta.thought;\n receiver.update_content({\n content: from_openai_thinking(choice_delta) as AssistantContent,\n message: from_openai_completion(response_chunk, choice),\n usage: response?.usage ? from_openai_usage(response.usage) : {},\n });\n }\n }\n if (delta_chunk.content) {\n if (!choice.delta.content) {\n choice.delta.content = delta_chunk.content;\n receiver.start_content({\n content: from_openai_content(choice.delta) as AssistantContent,\n message: from_openai_completion(response_chunk, choice),\n usage: response?.usage ? from_openai_usage(response.usage) : {},\n });\n receiver.update_message({\n message: from_openai_completion(response_chunk, choice),\n usage: response?.usage ? from_openai_usage(response.usage) : {},\n });\n } else {\n choice.delta.content += delta_chunk.content;\n receiver.update_content({\n content: from_openai_content(choice.delta) as AssistantContent,\n message: from_openai_completion(response_chunk, choice),\n usage: response?.usage ? from_openai_usage(response.usage) : {},\n });\n }\n }\n if (delta_chunk.tool_calls) {\n if (!choice.delta.tool_calls) {\n choice.delta.tool_calls = [];\n }\n for (const tool_call_chunk of delta_chunk.tool_calls) {\n if (!choice.delta.tool_calls[tool_call_chunk.index]) {\n choice.delta.tool_calls[tool_call_chunk.index] = tool_call_chunk;\n receiver.start_content({\n content: from_openai_tool_call(tool_call_chunk),\n message: from_openai_completion(response_chunk, choice),\n usage: response?.usage ? from_openai_usage(response.usage) : {},\n });\n receiver.update_message({\n message: from_openai_completion(response_chunk, choice),\n usage: response?.usage ? from_openai_usage(response.usage) : {},\n });\n } else {\n const tool_call = choice.delta.tool_calls[tool_call_chunk.index];\n\n if (tool_call_chunk.id) {\n tool_call.id = tool_call_chunk.id;\n }\n if (tool_call_chunk.type) {\n tool_call.type = tool_call_chunk.type;\n }\n if (tool_call_chunk.function) {\n if (!tool_call.function) {\n tool_call.function = tool_call_chunk.function;\n } else {\n if (tool_call_chunk.function.name) {\n tool_call.function.name = tool_call_chunk.function.name;\n }\n if (tool_call_chunk.function.arguments) {\n if (!tool_call.function.arguments) {\n tool_call.function.arguments = \"\";\n }\n tool_call.function.arguments += tool_call_chunk.function.arguments;\n }\n }\n }\n receiver.update_content({\n content: from_openai_tool_call(tool_call),\n message: from_openai_completion(response_chunk, choice),\n usage: response?.usage ? from_openai_usage(response.usage) : {},\n });\n receiver.update_message({\n message: from_openai_completion(response_chunk, choice),\n usage: response?.usage ? from_openai_usage(response.usage) : {},\n });\n }\n }\n }\n }\n }\n if (!response || !response.choices?.[0]) {\n throw new Error(\"no data\");\n }\n receiver.response_raw({ ...response });\n\n const message = from_openai_completion(response, response.choices[0]);\n const usage = response?.usage ? from_openai_usage(response.usage) : {};\n for (const content of message.content) {\n receiver.complete_content({ content, message, usage });\n }\n receiver.complete_message({ message, usage, ...map_stop_reason(response) });\n } catch (error) {\n receiver.error(error);\n }\n }\n}\n\nfunction get_system_context(\n model: string,\n system: string | undefined,\n system_role: OpenAIProviderConfig[\"system_role\"] = \"auto\",\n): OpenAI.ChatCompletionMessageParam[] {\n if (!system) {\n return [];\n }\n const role = resolve_system_role(model, system_role);\n if (role === \"developer\") {\n return [\n {\n role: \"developer\",\n content: system,\n } as OpenAI.ChatCompletionDeveloperMessageParam,\n ];\n }\n return [\n {\n role: \"system\",\n content: system,\n } as OpenAI.ChatCompletionSystemMessageParam,\n ];\n}\n\nfunction resolve_system_role(\n model: string,\n system_role: OpenAIProviderConfig[\"system_role\"] = \"auto\",\n): \"system\" | \"developer\" {\n if (system_role === \"system\" || system_role === \"developer\") {\n return system_role;\n }\n if (model.startsWith(\"gpt\")) {\n return \"system\";\n }\n if (is_openai_reasoning_model(model)) {\n return \"developer\";\n }\n return \"system\";\n}\n\nfunction resolve_strict_tools(\n model: string,\n strict_tools: OpenAIProviderConfig[\"strict_tools\"] = \"auto\",\n): boolean {\n if (strict_tools === \"never\") {\n return false;\n }\n return model.startsWith(\"gpt\") || is_openai_reasoning_model(model);\n}\n\n// Best-effort match for OpenAI's o-series reasoning model ids (o1, o3,\n// o4-mini, etc.). The leading non-zero digit and end-of-string-or-hyphen\n// anchor narrow the pattern to what OpenAI actually ships. Two known\n// failure modes: a non-OpenAI vendor whose model id happens to follow the\n// same shape (e.g. `o2-fast`) gets matched as o-series, and a relay-style\n// id like `openai/o3` is NOT matched because the regex anchors at start\n// of string. Operators in either situation should set `system_role` and\n// `strict_tools` explicitly — the heuristic is a default, not a constraint.\nfunction is_openai_reasoning_model(model: string): boolean {\n return /^o[1-9]\\d*(-|$)/.test(model);\n}\n\nfunction to_openai_tool(tool: ToolDefinition, strict: boolean): OpenAI.Chat.ChatCompletionTool {\n function map_parameter_type(\n parameter: Prettify<ParameterType & { description?: string }>,\n ): OpenAI.FunctionParameters {\n switch (parameter.type) {\n case \"object\":\n return {\n type: parameter.required ? parameter.type : [parameter.type, \"null\"],\n description: parameter.description,\n properties: Object.fromEntries(\n Object.entries(parameter.properties).map(([k, v]) => [k, map_parameter_type(v)]),\n ),\n additionalProperties: false,\n required: Object.entries(parameter.properties).map(([k]) => k),\n };\n case \"array\":\n return {\n type: parameter.required ? parameter.type : [parameter.type, \"null\"],\n description: parameter.description,\n items: map_parameter_type(parameter.items),\n };\n default:\n return {\n type: parameter.required ? parameter.type : [parameter.type, \"null\"],\n description:\n parameter.default !== undefined\n ? parameter.description\n ? `${parameter.description} (default: ${parameter.default})`\n : `default: ${parameter.default}`\n : parameter.description,\n enum: \"enum\" in parameter ? parameter.enum : undefined,\n };\n }\n }\n return {\n type: \"function\",\n function: {\n name: tool.name,\n description: tool.description,\n parameters: map_parameter_type({\n type: \"object\",\n required: true,\n properties: Object.fromEntries(\n tool.parameters.map(({ name, ...parameter }) => [name, parameter]),\n ),\n }),\n ...(strict ? { strict: true } : {}),\n },\n };\n}\n\nfunction from_openai_completion(\n completion: OpenAI.Chat.Completions.ChatCompletionChunk,\n choice: OpenAI.Chat.Completions.ChatCompletionChunk.Choice,\n) {\n let contents: Content[] = [];\n const thinking = from_openai_thinking(choice.delta);\n if (thinking) {\n contents = [...contents, thinking];\n }\n const delta_record = choice.delta as Record<string, unknown>;\n for (const key of Object.keys(choice.delta)) {\n if (key === \"role\") {\n continue;\n }\n if (is_openai_reasoning_delta_key(key)) {\n continue;\n }\n if (key === \"content\") {\n if (choice.delta.content) {\n contents = [...contents, from_openai_content(choice.delta)];\n }\n continue;\n }\n if (key === \"refusal\") {\n if (choice.delta.refusal) {\n contents = [...contents, from_openai_refusal(choice.delta)];\n }\n continue;\n }\n if (key === \"tool_calls\") {\n if (choice.delta.tool_calls) {\n contents = [...contents, ...choice.delta.tool_calls.map((t) => from_openai_tool_call(t))];\n }\n continue;\n }\n if (delta_record[key] !== undefined && delta_record[key] !== null) {\n const data = delta_record[key];\n contents = [\n ...contents,\n {\n type: \"raw\",\n model_kind: \"openai\",\n data: JSON.stringify({ [key]: data }),\n },\n ];\n }\n }\n return {\n id: completion.id,\n timestamp: completion.created,\n role: map_role(choice),\n content: contents,\n } as AssistantMessage;\n}\n\nfunction get_openai_reasoning_delta(delta: OpenAICompletionDelta) {\n const record = delta as Partial<Record<OpenAIReasoningDeltaKey, unknown>>;\n for (const key of OPENAI_REASONING_DELTA_KEYS) {\n const thought = record[key];\n if (typeof thought === \"string\" && thought.length > 0) {\n return { key, thought };\n }\n }\n return undefined;\n}\n\nfunction from_openai_thinking(content: OpenAICompletionDelta) {\n const reasoning = get_openai_reasoning_delta(content);\n if (!reasoning) {\n return undefined;\n }\n const extended = get_openai_delta_extended(content);\n return {\n type: \"thinking\",\n thought: reasoning.thought,\n extended: {\n ...extended,\n openai_reasoning_field: reasoning.key,\n },\n } as Content;\n}\n\nfunction is_openai_reasoning_delta_key(key: string): key is OpenAIReasoningDeltaKey {\n return OPENAI_REASONING_DELTA_KEYS.includes(key as OpenAIReasoningDeltaKey);\n}\n\nfunction from_openai_refusal(content: OpenAICompletionDelta) {\n return {\n type: \"text\",\n text: content.refusal,\n extended: {\n ...get_openai_delta_extended(content),\n openai_refusal: true,\n },\n } as Content;\n}\n\nfunction from_openai_content(content: OpenAICompletionDelta) {\n return {\n type: \"text\",\n text: content.content,\n extended: get_openai_delta_extended(content),\n } as Content;\n}\n\nfunction get_openai_delta_extended(content: OpenAICompletionDelta) {\n const extended = { ...(content as Record<string, unknown>) };\n delete extended.content;\n delete extended.tool_calls;\n delete extended.function_call;\n delete extended.refusal;\n delete extended.role;\n for (const key of OPENAI_REASONING_DELTA_KEYS) {\n delete extended[key];\n }\n return extended;\n}\n\nfunction from_openai_tool_call(\n tool_call: OpenAI.Chat.Completions.ChatCompletionChunk.Choice.Delta.ToolCall,\n) {\n const { id: tool_request_id, function: fn, type: _, index: __, ...extended } = tool_call;\n let params: unknown;\n try {\n params = JSON.parse(fn?.arguments ?? \"{}\");\n } catch {\n params = fn?.arguments;\n }\n return {\n tool_request_id,\n type: \"tool\",\n tool: fn?.name,\n params,\n extended,\n } as ToolContent;\n}\n\nfunction to_openai_messages(message: Message) {\n if (message.role === \"assistant\") {\n return [to_openai_assistant_message(message)];\n }\n // Partition content so tool_result blocks come before non-tool_result blocks.\n // OpenAI requires all tool-role messages immediately after the assistant message\n // containing the corresponding tool_calls; interleaving user messages between\n // tool messages causes a validation error.\n const tool_result_content = message.content.filter((c) => c.type === \"tool_result\");\n const other_content = message.content.filter((c) => c.type !== \"tool_result\");\n const ordered_content = [...tool_result_content, ...other_content];\n\n const results: OpenAI.ChatCompletionMessageParam[] = [];\n let result: OpenAI.ChatCompletionMessageParam | undefined;\n for (const content of ordered_content) {\n if (content.type === \"text\") {\n if (!result) {\n result = {\n role: \"user\",\n content: content.text,\n };\n } else if (result.role === \"tool\") {\n results.push(result);\n result = {\n role: \"user\",\n content: content.text,\n };\n } else {\n if (typeof result.content === \"string\") {\n result.content = [\n {\n type: \"text\",\n text: result.content,\n },\n ];\n }\n if (!result.content) {\n result.content = [\n {\n type: \"text\",\n text: content.text,\n },\n ];\n } else {\n result.content.push({\n type: \"text\",\n text: content.text,\n });\n }\n }\n } else if (content.type === \"tool_result\") {\n if (!result) {\n result = {\n role: \"tool\",\n tool_call_id: content.tool_request_id,\n content: JSON.stringify(content.result),\n };\n } else if (result.role !== \"tool\" || result.tool_call_id !== content.tool_request_id) {\n results.push(result);\n result = {\n role: \"tool\",\n tool_call_id: content.tool_request_id,\n content: JSON.stringify(content.result),\n };\n } else {\n if (typeof result.content === \"string\") {\n result.content = [\n {\n type: \"text\",\n text: result.content,\n },\n ];\n }\n result.content.push({\n type: \"text\",\n text: JSON.stringify(content.result),\n });\n }\n } else if (content.type === \"raw\") {\n result = {\n ...(result ?? {}),\n ...JSON.parse(content.data),\n };\n }\n }\n if (result) {\n results.push(result);\n }\n return results;\n}\n\nfunction to_openai_assistant_message(message: AssistantMessage) {\n let result: OpenAI.ChatCompletionAssistantMessageParam = {\n role: \"assistant\",\n };\n for (const content of message.content) {\n switch (content.type) {\n case \"text\":\n if (content.extended && content.extended.openai_refusal === true) {\n result.refusal = content.text;\n } else {\n if (typeof result.content === \"string\") {\n result.content = [\n {\n type: \"text\",\n text: result.content,\n },\n ];\n }\n if (!result.content) {\n result.content = content.text;\n } else {\n result.content.push({\n type: \"text\",\n text: content.text,\n });\n }\n }\n break;\n case \"tool\":\n if (!result.tool_calls) {\n result.tool_calls = [];\n }\n result.tool_calls.push({\n id: content.tool_request_id,\n type: \"function\",\n function: {\n name: content.tool,\n arguments: JSON.stringify(content.params),\n },\n });\n break;\n case \"raw\":\n if (content.model_kind !== \"openai\") {\n if (typeof result.content === \"string\") {\n result.content = [\n {\n type: \"text\",\n text: result.content,\n },\n ];\n }\n if (!result.content) {\n result.content = content.data;\n } else {\n result.content.push({\n type: \"text\",\n text: content.data,\n });\n }\n break;\n }\n result = {\n ...result,\n ...JSON.parse(content.data),\n };\n break;\n case \"thinking\":\n if (typeof result.content === \"string\") {\n result.content = [\n {\n type: \"text\",\n text: result.content,\n },\n ];\n }\n if (!result.content) {\n result.content = content.thought;\n } else {\n result.content.push({\n type: \"text\",\n text: content.thought,\n });\n }\n break;\n default:\n throw new Error(\"unexpected content type\");\n }\n }\n return result;\n}\n\nfunction from_openai_usage(usage: OpenAI.CompletionUsage | null | undefined) {\n return {\n input_tokens: usage?.prompt_tokens,\n output_tokens: usage?.completion_tokens,\n } as Usage;\n}\n\nfunction map_stop_reason(\n completion: OpenAI.ChatCompletionChunk,\n): Pick<CompletionResponseData, \"stop_reason\" | \"stop_details\"> {\n for (const choice of completion.choices) {\n switch (choice.finish_reason) {\n case \"content_filter\":\n return {\n stop_reason: \"error\",\n stop_details: choice.finish_reason,\n };\n case \"function_call\":\n return {\n stop_reason: \"tool_use\",\n };\n case \"length\":\n return {\n stop_reason: \"max_tokens\",\n };\n case \"stop\":\n return {\n stop_reason: \"end_turn\",\n };\n case \"tool_calls\":\n return {\n stop_reason: \"tool_use\",\n };\n default:\n return {\n stop_reason: \"other\",\n stop_details: `${choice.finish_reason}`,\n };\n }\n }\n return {\n stop_reason: \"other\",\n };\n}\n\nfunction map_role(choice: OpenAI.Chat.Completions.ChatCompletionChunk.Choice) {\n switch (choice.delta.role) {\n case \"user\":\n case \"developer\":\n case \"system\":\n return \"user\";\n case \"assistant\":\n case \"tool\":\n return \"assistant\";\n default:\n throw new Error(\"invalid role\");\n }\n}\n"],"mappings":"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","names":["message","rest"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -9,14 +9,58 @@ interface OpenAIProviderConfig extends Record<string, unknown> {
|
|
|
9
9
|
model: string;
|
|
10
10
|
/** The maximum number of tokens to generate in the response. */
|
|
11
11
|
max_tokens?: number;
|
|
12
|
+
/**
|
|
13
|
+
* Which role to use for the system prompt.
|
|
14
|
+
*
|
|
15
|
+
* The OpenAI Chat Completions spec allows `system` (legacy / most providers)
|
|
16
|
+
* and `developer` (introduced for o-series reasoning models). Most
|
|
17
|
+
* OpenAI-compatible endpoints (DeepSeek, OpenRouter relays, Anthropic-via-
|
|
18
|
+
* compat, self-hosted gateways, etc.) only accept `system` and reject
|
|
19
|
+
* `developer` with a 400.
|
|
20
|
+
*
|
|
21
|
+
* - `"auto"` (default): use the built-in heuristic — `gpt*` → `"system"`,
|
|
22
|
+
* o-series (`o1`, `o3`, `o4`, ...) → `"developer"`, anything else →
|
|
23
|
+
* `"system"` (the broadly-compatible default).
|
|
24
|
+
* - `"system"` / `"developer"`: force the role regardless of model id.
|
|
25
|
+
*
|
|
26
|
+
* The heuristic matches on the bare model id and does not understand
|
|
27
|
+
* relay-style prefixes (`openai/o3`, `anthropic/claude-3-5-sonnet`,
|
|
28
|
+
* etc.) — set this explicitly when routing OpenAI models through a
|
|
29
|
+
* relay that uses `vendor/model` ids.
|
|
30
|
+
*/
|
|
31
|
+
system_role?: "auto" | "system" | "developer";
|
|
32
|
+
/**
|
|
33
|
+
* Whether to emit OpenAI's strict structured-output flag on tool
|
|
34
|
+
* definitions (`function.strict: true`).
|
|
35
|
+
*
|
|
36
|
+
* `strict` is an OpenAI-specific extension that constrains tool arguments
|
|
37
|
+
* to the supplied JSON Schema. Most non-OpenAI endpoints either ignore the
|
|
38
|
+
* field or reject it.
|
|
39
|
+
*
|
|
40
|
+
* - `"auto"` (default): emit `strict: true` when the model id matches the
|
|
41
|
+
* built-in OpenAI heuristic — `gpt*` or o-series (`o1`, `o3`, `o4`, ...).
|
|
42
|
+
* Any other model id (deepseek, etc.) gets tool defs without `strict`.
|
|
43
|
+
* The heuristic matches on the bare model id; relay-style prefixes
|
|
44
|
+
* (`openai/gpt-4o`) are NOT recognized — set this explicitly when
|
|
45
|
+
* routing OpenAI models through a relay.
|
|
46
|
+
* - `"never"`: never emit `strict`.
|
|
47
|
+
*/
|
|
48
|
+
strict_tools?: "auto" | "never";
|
|
12
49
|
}
|
|
13
50
|
/**
|
|
14
51
|
* Model provider implementation for OpenAI's chat completion models.
|
|
15
52
|
*
|
|
16
|
-
* This provider wraps the OpenAI SDK to provide streaming completions with
|
|
17
|
-
* for tool use and function calling. It handles message formatting,
|
|
18
|
-
* and usage tracking according to the ModelProvider
|
|
19
|
-
*
|
|
53
|
+
* This provider wraps the OpenAI SDK to provide streaming completions with
|
|
54
|
+
* support for tool use and function calling. It handles message formatting,
|
|
55
|
+
* content streaming, and usage tracking according to the ModelProvider
|
|
56
|
+
* interface.
|
|
57
|
+
*
|
|
58
|
+
* Works against OpenAI directly as well as OpenAI-compatible endpoints
|
|
59
|
+
* (DeepSeek, OpenRouter, self-hosted gateways, etc.). The default behaviour
|
|
60
|
+
* picks `system` vs. `developer` for the system prompt and decides whether
|
|
61
|
+
* to emit OpenAI's `strict` flag on tool defs based on the model id; both
|
|
62
|
+
* can be overridden through `OpenAIProviderConfig.system_role` and
|
|
63
|
+
* `OpenAIProviderConfig.strict_tools` for endpoints whose behaviour differs.
|
|
20
64
|
*/
|
|
21
65
|
declare class OpenAIProvider implements ModelProvider {
|
|
22
66
|
#private;
|
package/dist/index.d.ts
CHANGED
|
@@ -9,14 +9,58 @@ interface OpenAIProviderConfig extends Record<string, unknown> {
|
|
|
9
9
|
model: string;
|
|
10
10
|
/** The maximum number of tokens to generate in the response. */
|
|
11
11
|
max_tokens?: number;
|
|
12
|
+
/**
|
|
13
|
+
* Which role to use for the system prompt.
|
|
14
|
+
*
|
|
15
|
+
* The OpenAI Chat Completions spec allows `system` (legacy / most providers)
|
|
16
|
+
* and `developer` (introduced for o-series reasoning models). Most
|
|
17
|
+
* OpenAI-compatible endpoints (DeepSeek, OpenRouter relays, Anthropic-via-
|
|
18
|
+
* compat, self-hosted gateways, etc.) only accept `system` and reject
|
|
19
|
+
* `developer` with a 400.
|
|
20
|
+
*
|
|
21
|
+
* - `"auto"` (default): use the built-in heuristic — `gpt*` → `"system"`,
|
|
22
|
+
* o-series (`o1`, `o3`, `o4`, ...) → `"developer"`, anything else →
|
|
23
|
+
* `"system"` (the broadly-compatible default).
|
|
24
|
+
* - `"system"` / `"developer"`: force the role regardless of model id.
|
|
25
|
+
*
|
|
26
|
+
* The heuristic matches on the bare model id and does not understand
|
|
27
|
+
* relay-style prefixes (`openai/o3`, `anthropic/claude-3-5-sonnet`,
|
|
28
|
+
* etc.) — set this explicitly when routing OpenAI models through a
|
|
29
|
+
* relay that uses `vendor/model` ids.
|
|
30
|
+
*/
|
|
31
|
+
system_role?: "auto" | "system" | "developer";
|
|
32
|
+
/**
|
|
33
|
+
* Whether to emit OpenAI's strict structured-output flag on tool
|
|
34
|
+
* definitions (`function.strict: true`).
|
|
35
|
+
*
|
|
36
|
+
* `strict` is an OpenAI-specific extension that constrains tool arguments
|
|
37
|
+
* to the supplied JSON Schema. Most non-OpenAI endpoints either ignore the
|
|
38
|
+
* field or reject it.
|
|
39
|
+
*
|
|
40
|
+
* - `"auto"` (default): emit `strict: true` when the model id matches the
|
|
41
|
+
* built-in OpenAI heuristic — `gpt*` or o-series (`o1`, `o3`, `o4`, ...).
|
|
42
|
+
* Any other model id (deepseek, etc.) gets tool defs without `strict`.
|
|
43
|
+
* The heuristic matches on the bare model id; relay-style prefixes
|
|
44
|
+
* (`openai/gpt-4o`) are NOT recognized — set this explicitly when
|
|
45
|
+
* routing OpenAI models through a relay.
|
|
46
|
+
* - `"never"`: never emit `strict`.
|
|
47
|
+
*/
|
|
48
|
+
strict_tools?: "auto" | "never";
|
|
12
49
|
}
|
|
13
50
|
/**
|
|
14
51
|
* Model provider implementation for OpenAI's chat completion models.
|
|
15
52
|
*
|
|
16
|
-
* This provider wraps the OpenAI SDK to provide streaming completions with
|
|
17
|
-
* for tool use and function calling. It handles message formatting,
|
|
18
|
-
* and usage tracking according to the ModelProvider
|
|
19
|
-
*
|
|
53
|
+
* This provider wraps the OpenAI SDK to provide streaming completions with
|
|
54
|
+
* support for tool use and function calling. It handles message formatting,
|
|
55
|
+
* content streaming, and usage tracking according to the ModelProvider
|
|
56
|
+
* interface.
|
|
57
|
+
*
|
|
58
|
+
* Works against OpenAI directly as well as OpenAI-compatible endpoints
|
|
59
|
+
* (DeepSeek, OpenRouter, self-hosted gateways, etc.). The default behaviour
|
|
60
|
+
* picks `system` vs. `developer` for the system prompt and decides whether
|
|
61
|
+
* to emit OpenAI's `strict` flag on tool defs based on the model id; both
|
|
62
|
+
* can be overridden through `OpenAIProviderConfig.system_role` and
|
|
63
|
+
* `OpenAIProviderConfig.strict_tools` for endpoints whose behaviour differs.
|
|
20
64
|
*/
|
|
21
65
|
declare class OpenAIProvider implements ModelProvider {
|
|
22
66
|
#private;
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
// src/openai-provider.ts
|
|
2
|
+
var OPENAI_REASONING_DELTA_KEYS = ["reasoning", "reasoning_content", "thinking"];
|
|
2
3
|
var OpenAIProvider = class _OpenAIProvider {
|
|
3
4
|
#sdk;
|
|
4
5
|
#config;
|
|
@@ -24,7 +25,8 @@ var OpenAIProvider = class _OpenAIProvider {
|
|
|
24
25
|
* @returns A promise that resolves when the request completes.
|
|
25
26
|
*/
|
|
26
27
|
async execute_request(request, receiver, cancellation) {
|
|
27
|
-
const { model, max_tokens, ...api_extras } = this.#config;
|
|
28
|
+
const { model, max_tokens, system_role, strict_tools, ...api_extras } = this.#config;
|
|
29
|
+
const emit_strict = resolve_strict_tools(model, strict_tools);
|
|
28
30
|
const params = {
|
|
29
31
|
...api_extras,
|
|
30
32
|
model,
|
|
@@ -32,10 +34,10 @@ var OpenAIProvider = class _OpenAIProvider {
|
|
|
32
34
|
max_tokens,
|
|
33
35
|
...request.tools.length > 0 ? {
|
|
34
36
|
tool_choice: "auto",
|
|
35
|
-
tools: request.tools.map((t) => to_openai_tool(t))
|
|
37
|
+
tools: request.tools.map((t) => to_openai_tool(t, emit_strict))
|
|
36
38
|
} : {},
|
|
37
39
|
messages: [
|
|
38
|
-
...get_system_context(model, request.system),
|
|
40
|
+
...get_system_context(model, request.system, system_role),
|
|
39
41
|
...request.messages.flatMap((m) => to_openai_messages(m))
|
|
40
42
|
],
|
|
41
43
|
stream_options: {
|
|
@@ -97,6 +99,30 @@ var OpenAIProvider = class _OpenAIProvider {
|
|
|
97
99
|
}
|
|
98
100
|
choice.delta.refusal += delta_chunk.refusal;
|
|
99
101
|
}
|
|
102
|
+
const reasoning_delta = get_openai_reasoning_delta(delta_chunk);
|
|
103
|
+
if (reasoning_delta) {
|
|
104
|
+
const choice_delta = choice.delta;
|
|
105
|
+
const existing = choice_delta[reasoning_delta.key];
|
|
106
|
+
if (!existing) {
|
|
107
|
+
choice_delta[reasoning_delta.key] = reasoning_delta.thought;
|
|
108
|
+
receiver.start_content({
|
|
109
|
+
content: from_openai_thinking(choice_delta),
|
|
110
|
+
message: from_openai_completion(response_chunk, choice),
|
|
111
|
+
usage: response?.usage ? from_openai_usage(response.usage) : {}
|
|
112
|
+
});
|
|
113
|
+
receiver.update_message({
|
|
114
|
+
message: from_openai_completion(response_chunk, choice),
|
|
115
|
+
usage: response?.usage ? from_openai_usage(response.usage) : {}
|
|
116
|
+
});
|
|
117
|
+
} else {
|
|
118
|
+
choice_delta[reasoning_delta.key] = existing + reasoning_delta.thought;
|
|
119
|
+
receiver.update_content({
|
|
120
|
+
content: from_openai_thinking(choice_delta),
|
|
121
|
+
message: from_openai_completion(response_chunk, choice),
|
|
122
|
+
usage: response?.usage ? from_openai_usage(response.usage) : {}
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
}
|
|
100
126
|
if (delta_chunk.content) {
|
|
101
127
|
if (!choice.delta.content) {
|
|
102
128
|
choice.delta.content = delta_chunk.content;
|
|
@@ -186,26 +212,48 @@ var OpenAIProvider = class _OpenAIProvider {
|
|
|
186
212
|
}
|
|
187
213
|
}
|
|
188
214
|
};
|
|
189
|
-
function get_system_context(model, system) {
|
|
215
|
+
function get_system_context(model, system, system_role = "auto") {
|
|
190
216
|
if (!system) {
|
|
191
217
|
return [];
|
|
192
218
|
}
|
|
193
|
-
|
|
219
|
+
const role = resolve_system_role(model, system_role);
|
|
220
|
+
if (role === "developer") {
|
|
194
221
|
return [
|
|
195
222
|
{
|
|
196
|
-
role: "
|
|
223
|
+
role: "developer",
|
|
197
224
|
content: system
|
|
198
225
|
}
|
|
199
226
|
];
|
|
200
227
|
}
|
|
201
228
|
return [
|
|
202
229
|
{
|
|
203
|
-
role: "
|
|
230
|
+
role: "system",
|
|
204
231
|
content: system
|
|
205
232
|
}
|
|
206
233
|
];
|
|
207
234
|
}
|
|
208
|
-
function
|
|
235
|
+
function resolve_system_role(model, system_role = "auto") {
|
|
236
|
+
if (system_role === "system" || system_role === "developer") {
|
|
237
|
+
return system_role;
|
|
238
|
+
}
|
|
239
|
+
if (model.startsWith("gpt")) {
|
|
240
|
+
return "system";
|
|
241
|
+
}
|
|
242
|
+
if (is_openai_reasoning_model(model)) {
|
|
243
|
+
return "developer";
|
|
244
|
+
}
|
|
245
|
+
return "system";
|
|
246
|
+
}
|
|
247
|
+
function resolve_strict_tools(model, strict_tools = "auto") {
|
|
248
|
+
if (strict_tools === "never") {
|
|
249
|
+
return false;
|
|
250
|
+
}
|
|
251
|
+
return model.startsWith("gpt") || is_openai_reasoning_model(model);
|
|
252
|
+
}
|
|
253
|
+
function is_openai_reasoning_model(model) {
|
|
254
|
+
return /^o[1-9]\d*(-|$)/.test(model);
|
|
255
|
+
}
|
|
256
|
+
function to_openai_tool(tool, strict) {
|
|
209
257
|
function map_parameter_type(parameter) {
|
|
210
258
|
switch (parameter.type) {
|
|
211
259
|
case "object":
|
|
@@ -244,25 +292,44 @@ function to_openai_tool(tool) {
|
|
|
244
292
|
tool.parameters.map(({ name, ...parameter }) => [name, parameter])
|
|
245
293
|
)
|
|
246
294
|
}),
|
|
247
|
-
strict: true
|
|
295
|
+
...strict ? { strict: true } : {}
|
|
248
296
|
}
|
|
249
297
|
};
|
|
250
298
|
}
|
|
251
299
|
function from_openai_completion(completion, choice) {
|
|
252
300
|
let contents = [];
|
|
253
|
-
|
|
254
|
-
|
|
301
|
+
const thinking = from_openai_thinking(choice.delta);
|
|
302
|
+
if (thinking) {
|
|
303
|
+
contents = [...contents, thinking];
|
|
304
|
+
}
|
|
305
|
+
const delta_record = choice.delta;
|
|
306
|
+
for (const key of Object.keys(choice.delta)) {
|
|
255
307
|
if (key === "role") {
|
|
256
308
|
continue;
|
|
257
309
|
}
|
|
258
|
-
if (key
|
|
259
|
-
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
310
|
+
if (is_openai_reasoning_delta_key(key)) {
|
|
311
|
+
continue;
|
|
312
|
+
}
|
|
313
|
+
if (key === "content") {
|
|
314
|
+
if (choice.delta.content) {
|
|
315
|
+
contents = [...contents, from_openai_content(choice.delta)];
|
|
316
|
+
}
|
|
317
|
+
continue;
|
|
318
|
+
}
|
|
319
|
+
if (key === "refusal") {
|
|
320
|
+
if (choice.delta.refusal) {
|
|
321
|
+
contents = [...contents, from_openai_refusal(choice.delta)];
|
|
322
|
+
}
|
|
323
|
+
continue;
|
|
324
|
+
}
|
|
325
|
+
if (key === "tool_calls") {
|
|
326
|
+
if (choice.delta.tool_calls) {
|
|
327
|
+
contents = [...contents, ...choice.delta.tool_calls.map((t) => from_openai_tool_call(t))];
|
|
328
|
+
}
|
|
329
|
+
continue;
|
|
330
|
+
}
|
|
331
|
+
if (delta_record[key] !== void 0 && delta_record[key] !== null) {
|
|
332
|
+
const data = delta_record[key];
|
|
266
333
|
contents = [
|
|
267
334
|
...contents,
|
|
268
335
|
{
|
|
@@ -280,32 +347,63 @@ function from_openai_completion(completion, choice) {
|
|
|
280
347
|
content: contents
|
|
281
348
|
};
|
|
282
349
|
}
|
|
350
|
+
function get_openai_reasoning_delta(delta) {
|
|
351
|
+
const record = delta;
|
|
352
|
+
for (const key of OPENAI_REASONING_DELTA_KEYS) {
|
|
353
|
+
const thought = record[key];
|
|
354
|
+
if (typeof thought === "string" && thought.length > 0) {
|
|
355
|
+
return { key, thought };
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
return void 0;
|
|
359
|
+
}
|
|
360
|
+
function from_openai_thinking(content) {
|
|
361
|
+
const reasoning = get_openai_reasoning_delta(content);
|
|
362
|
+
if (!reasoning) {
|
|
363
|
+
return void 0;
|
|
364
|
+
}
|
|
365
|
+
const extended = get_openai_delta_extended(content);
|
|
366
|
+
return {
|
|
367
|
+
type: "thinking",
|
|
368
|
+
thought: reasoning.thought,
|
|
369
|
+
extended: {
|
|
370
|
+
...extended,
|
|
371
|
+
openai_reasoning_field: reasoning.key
|
|
372
|
+
}
|
|
373
|
+
};
|
|
374
|
+
}
|
|
375
|
+
function is_openai_reasoning_delta_key(key) {
|
|
376
|
+
return OPENAI_REASONING_DELTA_KEYS.includes(key);
|
|
377
|
+
}
|
|
283
378
|
function from_openai_refusal(content) {
|
|
284
|
-
const { refusal, tool_calls: _, function_call: __, content: ___, role: ____, ...rest } = content;
|
|
285
379
|
return {
|
|
286
380
|
type: "text",
|
|
287
|
-
text: refusal,
|
|
381
|
+
text: content.refusal,
|
|
288
382
|
extended: {
|
|
289
|
-
...
|
|
383
|
+
...get_openai_delta_extended(content),
|
|
290
384
|
openai_refusal: true
|
|
291
385
|
}
|
|
292
386
|
};
|
|
293
387
|
}
|
|
294
388
|
function from_openai_content(content) {
|
|
295
|
-
const {
|
|
296
|
-
content: c,
|
|
297
|
-
tool_calls: _,
|
|
298
|
-
function_call: __,
|
|
299
|
-
refusal: ___,
|
|
300
|
-
role: ____,
|
|
301
|
-
...rest
|
|
302
|
-
} = content;
|
|
303
389
|
return {
|
|
304
390
|
type: "text",
|
|
305
|
-
text:
|
|
306
|
-
extended:
|
|
391
|
+
text: content.content,
|
|
392
|
+
extended: get_openai_delta_extended(content)
|
|
307
393
|
};
|
|
308
394
|
}
|
|
395
|
+
function get_openai_delta_extended(content) {
|
|
396
|
+
const extended = { ...content };
|
|
397
|
+
delete extended.content;
|
|
398
|
+
delete extended.tool_calls;
|
|
399
|
+
delete extended.function_call;
|
|
400
|
+
delete extended.refusal;
|
|
401
|
+
delete extended.role;
|
|
402
|
+
for (const key of OPENAI_REASONING_DELTA_KEYS) {
|
|
403
|
+
delete extended[key];
|
|
404
|
+
}
|
|
405
|
+
return extended;
|
|
406
|
+
}
|
|
309
407
|
function from_openai_tool_call(tool_call) {
|
|
310
408
|
const { id: tool_request_id, function: fn, type: _, index: __, ...extended } = tool_call;
|
|
311
409
|
let params;
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/openai-provider.ts"],"sourcesContent":["import { OpenAI } from \"openai\";\n\nimport type {\n AssistantContent,\n AssistantMessage,\n CancellationToken,\n CompletionResponseData,\n Content,\n Message,\n ModelProvider,\n ModelRequest,\n ParameterType,\n ProviderContextTransformer,\n StreamReceiver,\n ToolContent,\n ToolDefinition,\n Usage,\n} from \"@simulacra-ai/core\";\n\ntype Prettify<T> = { [K in keyof T]: T[K] } & {};\n\n/**\n * Configuration options for the OpenAI provider.\n */\nexport interface OpenAIProviderConfig extends Record<string, unknown> {\n /** The model identifier to use (e.g., \"gpt-4\", \"o1-preview\"). */\n model: string;\n /** The maximum number of tokens to generate in the response. */\n max_tokens?: number;\n}\n\n/**\n * Model provider implementation for OpenAI's chat completion models.\n *\n * This provider wraps the OpenAI SDK to provide streaming completions with support\n * for tool use and function calling. It handles message formatting, content streaming,\n * and usage tracking according to the ModelProvider interface. Supports both GPT models\n * (using system messages) and O-series models (using developer messages).\n */\nexport class OpenAIProvider implements ModelProvider {\n readonly #sdk: OpenAI;\n readonly #config: OpenAIProviderConfig;\n readonly context_transformers: ProviderContextTransformer[];\n\n /**\n * Creates a new OpenAI provider instance.\n *\n * @param sdk - The initialized OpenAI SDK client.\n * @param config - Configuration options for the provider.\n * @param context_transformers - Provider-level context transformers.\n */\n constructor(\n sdk: OpenAI,\n config: OpenAIProviderConfig,\n context_transformers: ProviderContextTransformer[] = [],\n ) {\n this.#sdk = sdk;\n this.#config = config;\n this.context_transformers = context_transformers;\n }\n\n /**\n * Executes a model request and streams the response through the provided receiver.\n *\n * @param request - The request containing messages, tools, and system prompt.\n * @param receiver - The receiver that handles streaming events.\n * @param cancellation - Token to signal cancellation of the request.\n * @returns A promise that resolves when the request completes.\n */\n async execute_request(\n request: ModelRequest,\n receiver: StreamReceiver,\n cancellation: CancellationToken,\n ): Promise<void> {\n const { model, max_tokens, ...api_extras } = this.#config;\n const params: OpenAI.ChatCompletionCreateParamsStreaming = {\n ...api_extras,\n model,\n stream: true,\n max_tokens,\n ...(request.tools.length > 0\n ? {\n tool_choice: \"auto\",\n tools: request.tools.map((t) => to_openai_tool(t)),\n }\n : {}),\n messages: [\n ...get_system_context(model, request.system),\n ...request.messages.flatMap((m) => to_openai_messages(m)),\n ],\n stream_options: {\n include_usage: true,\n },\n };\n\n receiver.before_request({ params });\n receiver.request_raw(params);\n\n const stream = await this.#sdk.chat.completions.create(params);\n\n // Intentionally not awaited. Streaming is event-driven through the receiver.\n // The policy wraps only connection establishment; chunk processing flows\n // asynchronously via StreamListener events back to the conversation.\n this.#stream_response(stream, receiver, cancellation);\n }\n\n /**\n * Creates a clone of this provider with the same configuration.\n *\n * @returns A new provider instance with identical configuration.\n */\n clone(): ModelProvider {\n return new OpenAIProvider(this.#sdk, this.#config, this.context_transformers);\n }\n\n async #stream_response(\n stream: AsyncIterable<OpenAI.Chat.Completions.ChatCompletionChunk>,\n receiver: StreamReceiver,\n cancellation: CancellationToken,\n ) {\n try {\n let response: OpenAI.Chat.Completions.ChatCompletionChunk | undefined;\n for await (const response_chunk of stream) {\n if (cancellation.is_cancellation_requested) {\n receiver.cancel();\n return;\n }\n receiver.stream_raw(response_chunk);\n\n const { choices: choices_chunk, ...rest } = response_chunk;\n response = {\n ...response,\n ...rest,\n choices: response?.choices ?? [],\n };\n\n for (const choice_chunk of choices_chunk) {\n if (!response.choices[choice_chunk.index]) {\n response.choices[choice_chunk.index] = choice_chunk;\n const message = from_openai_completion(response_chunk, choice_chunk);\n for (const content of message.content) {\n receiver.start_content({ content, message, usage: {} });\n }\n receiver.start_message({ message, usage: {} });\n continue;\n }\n\n const { delta: delta_chunk, ...rest } = choice_chunk;\n const choice = (response.choices[choice_chunk.index] = {\n ...response.choices[choice_chunk.index],\n ...rest,\n delta: {\n ...response.choices[choice_chunk.index]?.delta,\n },\n });\n\n if (delta_chunk.role) {\n choice.delta.role = delta_chunk.role;\n }\n if (delta_chunk.refusal) {\n if (!choice.delta.refusal) {\n choice.delta.refusal = \"\";\n }\n choice.delta.refusal += delta_chunk.refusal;\n }\n if (delta_chunk.content) {\n if (!choice.delta.content) {\n choice.delta.content = delta_chunk.content;\n receiver.start_content({\n content: from_openai_content(choice.delta) as AssistantContent,\n message: from_openai_completion(response_chunk, choice),\n usage: response?.usage ? from_openai_usage(response.usage) : {},\n });\n receiver.update_message({\n message: from_openai_completion(response_chunk, choice),\n usage: response?.usage ? from_openai_usage(response.usage) : {},\n });\n } else {\n choice.delta.content += delta_chunk.content;\n receiver.update_content({\n content: from_openai_content(choice.delta) as AssistantContent,\n message: from_openai_completion(response_chunk, choice),\n usage: response?.usage ? from_openai_usage(response.usage) : {},\n });\n }\n }\n if (delta_chunk.tool_calls) {\n if (!choice.delta.tool_calls) {\n choice.delta.tool_calls = [];\n }\n for (const tool_call_chunk of delta_chunk.tool_calls) {\n if (!choice.delta.tool_calls[tool_call_chunk.index]) {\n choice.delta.tool_calls[tool_call_chunk.index] = tool_call_chunk;\n receiver.start_content({\n content: from_openai_tool_call(tool_call_chunk),\n message: from_openai_completion(response_chunk, choice),\n usage: response?.usage ? from_openai_usage(response.usage) : {},\n });\n receiver.update_message({\n message: from_openai_completion(response_chunk, choice),\n usage: response?.usage ? from_openai_usage(response.usage) : {},\n });\n } else {\n const tool_call = choice.delta.tool_calls[tool_call_chunk.index];\n\n if (tool_call_chunk.id) {\n tool_call.id = tool_call_chunk.id;\n }\n if (tool_call_chunk.type) {\n tool_call.type = tool_call_chunk.type;\n }\n if (tool_call_chunk.function) {\n if (!tool_call.function) {\n tool_call.function = tool_call_chunk.function;\n } else {\n if (tool_call_chunk.function.name) {\n tool_call.function.name = tool_call_chunk.function.name;\n }\n if (tool_call_chunk.function.arguments) {\n if (!tool_call.function.arguments) {\n tool_call.function.arguments = \"\";\n }\n tool_call.function.arguments += tool_call_chunk.function.arguments;\n }\n }\n }\n receiver.update_content({\n content: from_openai_tool_call(tool_call),\n message: from_openai_completion(response_chunk, choice),\n usage: response?.usage ? from_openai_usage(response.usage) : {},\n });\n receiver.update_message({\n message: from_openai_completion(response_chunk, choice),\n usage: response?.usage ? from_openai_usage(response.usage) : {},\n });\n }\n }\n }\n }\n }\n if (!response || !response.choices?.[0]) {\n throw new Error(\"no data\");\n }\n receiver.response_raw({ ...response });\n\n const message = from_openai_completion(response, response.choices[0]);\n const usage = response?.usage ? from_openai_usage(response.usage) : {};\n for (const content of message.content) {\n receiver.complete_content({ content, message, usage });\n }\n receiver.complete_message({ message, usage, ...map_stop_reason(response) });\n } catch (error) {\n receiver.error(error);\n }\n }\n}\n\nfunction get_system_context(model: string, system?: string): OpenAI.ChatCompletionMessageParam[] {\n if (!system) {\n return [];\n }\n if (model.startsWith(\"gpt\")) {\n return [\n {\n role: \"system\",\n content: system,\n } as OpenAI.ChatCompletionSystemMessageParam,\n ];\n }\n return [\n {\n role: \"developer\",\n content: system,\n } as OpenAI.ChatCompletionDeveloperMessageParam,\n ];\n}\n\nfunction to_openai_tool(tool: ToolDefinition): OpenAI.Chat.ChatCompletionTool {\n function map_parameter_type(\n parameter: Prettify<ParameterType & { description?: string }>,\n ): OpenAI.FunctionParameters {\n switch (parameter.type) {\n case \"object\":\n return {\n type: parameter.required ? parameter.type : [parameter.type, \"null\"],\n description: parameter.description,\n properties: Object.fromEntries(\n Object.entries(parameter.properties).map(([k, v]) => [k, map_parameter_type(v)]),\n ),\n additionalProperties: false,\n required: Object.entries(parameter.properties).map(([k]) => k),\n };\n case \"array\":\n return {\n type: parameter.required ? parameter.type : [parameter.type, \"null\"],\n description: parameter.description,\n items: map_parameter_type(parameter.items),\n };\n default:\n return {\n type: parameter.required ? parameter.type : [parameter.type, \"null\"],\n description:\n parameter.default !== undefined\n ? parameter.description\n ? `${parameter.description} (default: ${parameter.default})`\n : `default: ${parameter.default}`\n : parameter.description,\n enum: \"enum\" in parameter ? parameter.enum : undefined,\n };\n }\n }\n return {\n type: \"function\",\n function: {\n name: tool.name,\n description: tool.description,\n parameters: map_parameter_type({\n type: \"object\",\n required: true,\n properties: Object.fromEntries(\n tool.parameters.map(({ name, ...parameter }) => [name, parameter]),\n ),\n }),\n strict: true,\n },\n };\n}\n\nfunction from_openai_completion(\n completion: OpenAI.Chat.Completions.ChatCompletionChunk,\n choice: OpenAI.Chat.Completions.ChatCompletionChunk.Choice,\n) {\n let contents: Content[] = [];\n for (const k in choice.delta) {\n const key = k as keyof typeof choice.delta;\n if (key === \"role\") {\n continue;\n }\n if (key === \"content\" && choice.delta.content) {\n contents = [...contents, from_openai_content(choice.delta)];\n } else if (key === \"refusal\" && choice.delta.refusal) {\n contents = [...contents, from_openai_refusal(choice.delta)];\n } else if (key === \"tool_calls\" && choice.delta.tool_calls) {\n contents = [...contents, ...choice.delta.tool_calls.map((t) => from_openai_tool_call(t))];\n } else if (choice.delta[key] !== undefined && choice.delta[key] !== null) {\n const { [key]: data } = choice.delta;\n contents = [\n ...contents,\n {\n type: \"raw\",\n model_kind: \"openai\",\n data: JSON.stringify({ [key]: data }),\n },\n ];\n }\n }\n return {\n id: completion.id,\n timestamp: completion.created,\n role: map_role(choice),\n content: contents,\n } as AssistantMessage;\n}\n\nfunction from_openai_refusal(content: OpenAI.Chat.Completions.ChatCompletionChunk.Choice.Delta) {\n const { refusal, tool_calls: _, function_call: __, content: ___, role: ____, ...rest } = content;\n return {\n type: \"text\",\n text: refusal,\n extended: {\n ...rest,\n openai_refusal: true,\n },\n } as Content;\n}\n\nfunction from_openai_content(content: OpenAI.Chat.Completions.ChatCompletionChunk.Choice.Delta) {\n const {\n content: c,\n tool_calls: _,\n function_call: __,\n refusal: ___,\n role: ____,\n ...rest\n } = content;\n return {\n type: \"text\",\n text: c,\n extended: rest,\n } as Content;\n}\n\nfunction from_openai_tool_call(\n tool_call: OpenAI.Chat.Completions.ChatCompletionChunk.Choice.Delta.ToolCall,\n) {\n const { id: tool_request_id, function: fn, type: _, index: __, ...extended } = tool_call;\n let params: unknown;\n try {\n params = JSON.parse(fn?.arguments ?? \"{}\");\n } catch {\n params = fn?.arguments;\n }\n return {\n tool_request_id,\n type: \"tool\",\n tool: fn?.name,\n params,\n extended,\n } as ToolContent;\n}\n\nfunction to_openai_messages(message: Message) {\n if (message.role === \"assistant\") {\n return [to_openai_assistant_message(message)];\n }\n // Partition content so tool_result blocks come before non-tool_result blocks.\n // OpenAI requires all tool-role messages immediately after the assistant message\n // containing the corresponding tool_calls; interleaving user messages between\n // tool messages causes a validation error.\n const tool_result_content = message.content.filter((c) => c.type === \"tool_result\");\n const other_content = message.content.filter((c) => c.type !== \"tool_result\");\n const ordered_content = [...tool_result_content, ...other_content];\n\n const results: OpenAI.ChatCompletionMessageParam[] = [];\n let result: OpenAI.ChatCompletionMessageParam | undefined;\n for (const content of ordered_content) {\n if (content.type === \"text\") {\n if (!result) {\n result = {\n role: \"user\",\n content: content.text,\n };\n } else if (result.role === \"tool\") {\n results.push(result);\n result = {\n role: \"user\",\n content: content.text,\n };\n } else {\n if (typeof result.content === \"string\") {\n result.content = [\n {\n type: \"text\",\n text: result.content,\n },\n ];\n }\n if (!result.content) {\n result.content = [\n {\n type: \"text\",\n text: content.text,\n },\n ];\n } else {\n result.content.push({\n type: \"text\",\n text: content.text,\n });\n }\n }\n } else if (content.type === \"tool_result\") {\n if (!result) {\n result = {\n role: \"tool\",\n tool_call_id: content.tool_request_id,\n content: JSON.stringify(content.result),\n };\n } else if (result.role !== \"tool\" || result.tool_call_id !== content.tool_request_id) {\n results.push(result);\n result = {\n role: \"tool\",\n tool_call_id: content.tool_request_id,\n content: JSON.stringify(content.result),\n };\n } else {\n if (typeof result.content === \"string\") {\n result.content = [\n {\n type: \"text\",\n text: result.content,\n },\n ];\n }\n result.content.push({\n type: \"text\",\n text: JSON.stringify(content.result),\n });\n }\n } else if (content.type === \"raw\") {\n result = {\n ...(result ?? {}),\n ...JSON.parse(content.data),\n };\n }\n }\n if (result) {\n results.push(result);\n }\n return results;\n}\n\nfunction to_openai_assistant_message(message: AssistantMessage) {\n let result: OpenAI.ChatCompletionAssistantMessageParam = {\n role: \"assistant\",\n };\n for (const content of message.content) {\n switch (content.type) {\n case \"text\":\n if (content.extended && content.extended.openai_refusal === true) {\n result.refusal = content.text;\n } else {\n if (typeof result.content === \"string\") {\n result.content = [\n {\n type: \"text\",\n text: result.content,\n },\n ];\n }\n if (!result.content) {\n result.content = content.text;\n } else {\n result.content.push({\n type: \"text\",\n text: content.text,\n });\n }\n }\n break;\n case \"tool\":\n if (!result.tool_calls) {\n result.tool_calls = [];\n }\n result.tool_calls.push({\n id: content.tool_request_id,\n type: \"function\",\n function: {\n name: content.tool,\n arguments: JSON.stringify(content.params),\n },\n });\n break;\n case \"raw\":\n if (content.model_kind !== \"openai\") {\n if (typeof result.content === \"string\") {\n result.content = [\n {\n type: \"text\",\n text: result.content,\n },\n ];\n }\n if (!result.content) {\n result.content = content.data;\n } else {\n result.content.push({\n type: \"text\",\n text: content.data,\n });\n }\n break;\n }\n result = {\n ...result,\n ...JSON.parse(content.data),\n };\n break;\n case \"thinking\":\n if (typeof result.content === \"string\") {\n result.content = [\n {\n type: \"text\",\n text: result.content,\n },\n ];\n }\n if (!result.content) {\n result.content = content.thought;\n } else {\n result.content.push({\n type: \"text\",\n text: content.thought,\n });\n }\n break;\n default:\n throw new Error(\"unexpected content type\");\n }\n }\n return result;\n}\n\nfunction from_openai_usage(usage: OpenAI.CompletionUsage | null | undefined) {\n return {\n input_tokens: usage?.prompt_tokens,\n output_tokens: usage?.completion_tokens,\n } as Usage;\n}\n\nfunction map_stop_reason(\n completion: OpenAI.ChatCompletionChunk,\n): Pick<CompletionResponseData, \"stop_reason\" | \"stop_details\"> {\n for (const choice of completion.choices) {\n switch (choice.finish_reason) {\n case \"content_filter\":\n return {\n stop_reason: \"error\",\n stop_details: choice.finish_reason,\n };\n case \"function_call\":\n return {\n stop_reason: \"tool_use\",\n };\n case \"length\":\n return {\n stop_reason: \"max_tokens\",\n };\n case \"stop\":\n return {\n stop_reason: \"end_turn\",\n };\n case \"tool_calls\":\n return {\n stop_reason: \"tool_use\",\n };\n default:\n return {\n stop_reason: \"other\",\n stop_details: `${choice.finish_reason}`,\n };\n }\n }\n return {\n stop_reason: \"other\",\n };\n}\n\nfunction map_role(choice: OpenAI.Chat.Completions.ChatCompletionChunk.Choice) {\n switch (choice.delta.role) {\n case \"user\":\n case \"developer\":\n case \"system\":\n return \"user\";\n case \"assistant\":\n case \"tool\":\n return \"assistant\";\n default:\n throw new Error(\"invalid role\");\n }\n}\n"],"mappings":"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","names":["message","rest"]}
|
|
1
|
+
{"version":3,"sources":["../src/openai-provider.ts"],"sourcesContent":["import { OpenAI } from \"openai\";\n\nimport type {\n AssistantContent,\n AssistantMessage,\n CancellationToken,\n CompletionResponseData,\n Content,\n Message,\n ModelProvider,\n ModelRequest,\n ParameterType,\n ProviderContextTransformer,\n StreamReceiver,\n ToolContent,\n ToolDefinition,\n Usage,\n} from \"@simulacra-ai/core\";\n\ntype Prettify<T> = { [K in keyof T]: T[K] } & {};\n\nconst OPENAI_REASONING_DELTA_KEYS = [\"reasoning\", \"reasoning_content\", \"thinking\"] as const;\n\ntype OpenAIReasoningDeltaKey = (typeof OPENAI_REASONING_DELTA_KEYS)[number];\ntype OpenAICompletionDelta = OpenAI.Chat.Completions.ChatCompletionChunk.Choice.Delta;\ntype OpenAIReasoningDelta = OpenAICompletionDelta &\n Partial<Record<OpenAIReasoningDeltaKey, string>>;\n\n/**\n * Configuration options for the OpenAI provider.\n */\nexport interface OpenAIProviderConfig extends Record<string, unknown> {\n /** The model identifier to use (e.g., \"gpt-4\", \"o1-preview\"). */\n model: string;\n /** The maximum number of tokens to generate in the response. */\n max_tokens?: number;\n /**\n * Which role to use for the system prompt.\n *\n * The OpenAI Chat Completions spec allows `system` (legacy / most providers)\n * and `developer` (introduced for o-series reasoning models). Most\n * OpenAI-compatible endpoints (DeepSeek, OpenRouter relays, Anthropic-via-\n * compat, self-hosted gateways, etc.) only accept `system` and reject\n * `developer` with a 400.\n *\n * - `\"auto\"` (default): use the built-in heuristic — `gpt*` → `\"system\"`,\n * o-series (`o1`, `o3`, `o4`, ...) → `\"developer\"`, anything else →\n * `\"system\"` (the broadly-compatible default).\n * - `\"system\"` / `\"developer\"`: force the role regardless of model id.\n *\n * The heuristic matches on the bare model id and does not understand\n * relay-style prefixes (`openai/o3`, `anthropic/claude-3-5-sonnet`,\n * etc.) — set this explicitly when routing OpenAI models through a\n * relay that uses `vendor/model` ids.\n */\n system_role?: \"auto\" | \"system\" | \"developer\";\n /**\n * Whether to emit OpenAI's strict structured-output flag on tool\n * definitions (`function.strict: true`).\n *\n * `strict` is an OpenAI-specific extension that constrains tool arguments\n * to the supplied JSON Schema. Most non-OpenAI endpoints either ignore the\n * field or reject it.\n *\n * - `\"auto\"` (default): emit `strict: true` when the model id matches the\n * built-in OpenAI heuristic — `gpt*` or o-series (`o1`, `o3`, `o4`, ...).\n * Any other model id (deepseek, etc.) gets tool defs without `strict`.\n * The heuristic matches on the bare model id; relay-style prefixes\n * (`openai/gpt-4o`) are NOT recognized — set this explicitly when\n * routing OpenAI models through a relay.\n * - `\"never\"`: never emit `strict`.\n */\n strict_tools?: \"auto\" | \"never\";\n}\n\n/**\n * Model provider implementation for OpenAI's chat completion models.\n *\n * This provider wraps the OpenAI SDK to provide streaming completions with\n * support for tool use and function calling. It handles message formatting,\n * content streaming, and usage tracking according to the ModelProvider\n * interface.\n *\n * Works against OpenAI directly as well as OpenAI-compatible endpoints\n * (DeepSeek, OpenRouter, self-hosted gateways, etc.). The default behaviour\n * picks `system` vs. `developer` for the system prompt and decides whether\n * to emit OpenAI's `strict` flag on tool defs based on the model id; both\n * can be overridden through `OpenAIProviderConfig.system_role` and\n * `OpenAIProviderConfig.strict_tools` for endpoints whose behaviour differs.\n */\nexport class OpenAIProvider implements ModelProvider {\n readonly #sdk: OpenAI;\n readonly #config: OpenAIProviderConfig;\n readonly context_transformers: ProviderContextTransformer[];\n\n /**\n * Creates a new OpenAI provider instance.\n *\n * @param sdk - The initialized OpenAI SDK client.\n * @param config - Configuration options for the provider.\n * @param context_transformers - Provider-level context transformers.\n */\n constructor(\n sdk: OpenAI,\n config: OpenAIProviderConfig,\n context_transformers: ProviderContextTransformer[] = [],\n ) {\n this.#sdk = sdk;\n this.#config = config;\n this.context_transformers = context_transformers;\n }\n\n /**\n * Executes a model request and streams the response through the provided receiver.\n *\n * @param request - The request containing messages, tools, and system prompt.\n * @param receiver - The receiver that handles streaming events.\n * @param cancellation - Token to signal cancellation of the request.\n * @returns A promise that resolves when the request completes.\n */\n async execute_request(\n request: ModelRequest,\n receiver: StreamReceiver,\n cancellation: CancellationToken,\n ): Promise<void> {\n const { model, max_tokens, system_role, strict_tools, ...api_extras } = this.#config;\n const emit_strict = resolve_strict_tools(model, strict_tools);\n const params: OpenAI.ChatCompletionCreateParamsStreaming = {\n ...api_extras,\n model,\n stream: true,\n max_tokens,\n ...(request.tools.length > 0\n ? {\n tool_choice: \"auto\",\n tools: request.tools.map((t) => to_openai_tool(t, emit_strict)),\n }\n : {}),\n messages: [\n ...get_system_context(model, request.system, system_role),\n ...request.messages.flatMap((m) => to_openai_messages(m)),\n ],\n stream_options: {\n include_usage: true,\n },\n };\n\n receiver.before_request({ params });\n receiver.request_raw(params);\n\n const stream = await this.#sdk.chat.completions.create(params);\n\n // Intentionally not awaited. Streaming is event-driven through the receiver.\n // The policy wraps only connection establishment; chunk processing flows\n // asynchronously via StreamListener events back to the conversation.\n this.#stream_response(stream, receiver, cancellation);\n }\n\n /**\n * Creates a clone of this provider with the same configuration.\n *\n * @returns A new provider instance with identical configuration.\n */\n clone(): ModelProvider {\n return new OpenAIProvider(this.#sdk, this.#config, this.context_transformers);\n }\n\n async #stream_response(\n stream: AsyncIterable<OpenAI.Chat.Completions.ChatCompletionChunk>,\n receiver: StreamReceiver,\n cancellation: CancellationToken,\n ) {\n try {\n let response: OpenAI.Chat.Completions.ChatCompletionChunk | undefined;\n for await (const response_chunk of stream) {\n if (cancellation.is_cancellation_requested) {\n receiver.cancel();\n return;\n }\n receiver.stream_raw(response_chunk);\n\n const { choices: choices_chunk, ...rest } = response_chunk;\n response = {\n ...response,\n ...rest,\n choices: response?.choices ?? [],\n };\n\n for (const choice_chunk of choices_chunk) {\n if (!response.choices[choice_chunk.index]) {\n response.choices[choice_chunk.index] = choice_chunk;\n const message = from_openai_completion(response_chunk, choice_chunk);\n for (const content of message.content) {\n receiver.start_content({ content, message, usage: {} });\n }\n receiver.start_message({ message, usage: {} });\n continue;\n }\n\n const { delta: delta_chunk, ...rest } = choice_chunk;\n const choice = (response.choices[choice_chunk.index] = {\n ...response.choices[choice_chunk.index],\n ...rest,\n delta: {\n ...response.choices[choice_chunk.index]?.delta,\n },\n });\n\n if (delta_chunk.role) {\n choice.delta.role = delta_chunk.role;\n }\n if (delta_chunk.refusal) {\n if (!choice.delta.refusal) {\n choice.delta.refusal = \"\";\n }\n choice.delta.refusal += delta_chunk.refusal;\n }\n const reasoning_delta = get_openai_reasoning_delta(delta_chunk);\n if (reasoning_delta) {\n const choice_delta = choice.delta as OpenAIReasoningDelta;\n const existing = choice_delta[reasoning_delta.key];\n if (!existing) {\n choice_delta[reasoning_delta.key] = reasoning_delta.thought;\n receiver.start_content({\n content: from_openai_thinking(choice_delta) as AssistantContent,\n message: from_openai_completion(response_chunk, choice),\n usage: response?.usage ? from_openai_usage(response.usage) : {},\n });\n receiver.update_message({\n message: from_openai_completion(response_chunk, choice),\n usage: response?.usage ? from_openai_usage(response.usage) : {},\n });\n } else {\n choice_delta[reasoning_delta.key] = existing + reasoning_delta.thought;\n receiver.update_content({\n content: from_openai_thinking(choice_delta) as AssistantContent,\n message: from_openai_completion(response_chunk, choice),\n usage: response?.usage ? from_openai_usage(response.usage) : {},\n });\n }\n }\n if (delta_chunk.content) {\n if (!choice.delta.content) {\n choice.delta.content = delta_chunk.content;\n receiver.start_content({\n content: from_openai_content(choice.delta) as AssistantContent,\n message: from_openai_completion(response_chunk, choice),\n usage: response?.usage ? from_openai_usage(response.usage) : {},\n });\n receiver.update_message({\n message: from_openai_completion(response_chunk, choice),\n usage: response?.usage ? from_openai_usage(response.usage) : {},\n });\n } else {\n choice.delta.content += delta_chunk.content;\n receiver.update_content({\n content: from_openai_content(choice.delta) as AssistantContent,\n message: from_openai_completion(response_chunk, choice),\n usage: response?.usage ? from_openai_usage(response.usage) : {},\n });\n }\n }\n if (delta_chunk.tool_calls) {\n if (!choice.delta.tool_calls) {\n choice.delta.tool_calls = [];\n }\n for (const tool_call_chunk of delta_chunk.tool_calls) {\n if (!choice.delta.tool_calls[tool_call_chunk.index]) {\n choice.delta.tool_calls[tool_call_chunk.index] = tool_call_chunk;\n receiver.start_content({\n content: from_openai_tool_call(tool_call_chunk),\n message: from_openai_completion(response_chunk, choice),\n usage: response?.usage ? from_openai_usage(response.usage) : {},\n });\n receiver.update_message({\n message: from_openai_completion(response_chunk, choice),\n usage: response?.usage ? from_openai_usage(response.usage) : {},\n });\n } else {\n const tool_call = choice.delta.tool_calls[tool_call_chunk.index];\n\n if (tool_call_chunk.id) {\n tool_call.id = tool_call_chunk.id;\n }\n if (tool_call_chunk.type) {\n tool_call.type = tool_call_chunk.type;\n }\n if (tool_call_chunk.function) {\n if (!tool_call.function) {\n tool_call.function = tool_call_chunk.function;\n } else {\n if (tool_call_chunk.function.name) {\n tool_call.function.name = tool_call_chunk.function.name;\n }\n if (tool_call_chunk.function.arguments) {\n if (!tool_call.function.arguments) {\n tool_call.function.arguments = \"\";\n }\n tool_call.function.arguments += tool_call_chunk.function.arguments;\n }\n }\n }\n receiver.update_content({\n content: from_openai_tool_call(tool_call),\n message: from_openai_completion(response_chunk, choice),\n usage: response?.usage ? from_openai_usage(response.usage) : {},\n });\n receiver.update_message({\n message: from_openai_completion(response_chunk, choice),\n usage: response?.usage ? from_openai_usage(response.usage) : {},\n });\n }\n }\n }\n }\n }\n if (!response || !response.choices?.[0]) {\n throw new Error(\"no data\");\n }\n receiver.response_raw({ ...response });\n\n const message = from_openai_completion(response, response.choices[0]);\n const usage = response?.usage ? from_openai_usage(response.usage) : {};\n for (const content of message.content) {\n receiver.complete_content({ content, message, usage });\n }\n receiver.complete_message({ message, usage, ...map_stop_reason(response) });\n } catch (error) {\n receiver.error(error);\n }\n }\n}\n\nfunction get_system_context(\n model: string,\n system: string | undefined,\n system_role: OpenAIProviderConfig[\"system_role\"] = \"auto\",\n): OpenAI.ChatCompletionMessageParam[] {\n if (!system) {\n return [];\n }\n const role = resolve_system_role(model, system_role);\n if (role === \"developer\") {\n return [\n {\n role: \"developer\",\n content: system,\n } as OpenAI.ChatCompletionDeveloperMessageParam,\n ];\n }\n return [\n {\n role: \"system\",\n content: system,\n } as OpenAI.ChatCompletionSystemMessageParam,\n ];\n}\n\nfunction resolve_system_role(\n model: string,\n system_role: OpenAIProviderConfig[\"system_role\"] = \"auto\",\n): \"system\" | \"developer\" {\n if (system_role === \"system\" || system_role === \"developer\") {\n return system_role;\n }\n if (model.startsWith(\"gpt\")) {\n return \"system\";\n }\n if (is_openai_reasoning_model(model)) {\n return \"developer\";\n }\n return \"system\";\n}\n\nfunction resolve_strict_tools(\n model: string,\n strict_tools: OpenAIProviderConfig[\"strict_tools\"] = \"auto\",\n): boolean {\n if (strict_tools === \"never\") {\n return false;\n }\n return model.startsWith(\"gpt\") || is_openai_reasoning_model(model);\n}\n\n// Best-effort match for OpenAI's o-series reasoning model ids (o1, o3,\n// o4-mini, etc.). The leading non-zero digit and end-of-string-or-hyphen\n// anchor narrow the pattern to what OpenAI actually ships. Two known\n// failure modes: a non-OpenAI vendor whose model id happens to follow the\n// same shape (e.g. `o2-fast`) gets matched as o-series, and a relay-style\n// id like `openai/o3` is NOT matched because the regex anchors at start\n// of string. Operators in either situation should set `system_role` and\n// `strict_tools` explicitly — the heuristic is a default, not a constraint.\nfunction is_openai_reasoning_model(model: string): boolean {\n return /^o[1-9]\\d*(-|$)/.test(model);\n}\n\nfunction to_openai_tool(tool: ToolDefinition, strict: boolean): OpenAI.Chat.ChatCompletionTool {\n function map_parameter_type(\n parameter: Prettify<ParameterType & { description?: string }>,\n ): OpenAI.FunctionParameters {\n switch (parameter.type) {\n case \"object\":\n return {\n type: parameter.required ? parameter.type : [parameter.type, \"null\"],\n description: parameter.description,\n properties: Object.fromEntries(\n Object.entries(parameter.properties).map(([k, v]) => [k, map_parameter_type(v)]),\n ),\n additionalProperties: false,\n required: Object.entries(parameter.properties).map(([k]) => k),\n };\n case \"array\":\n return {\n type: parameter.required ? parameter.type : [parameter.type, \"null\"],\n description: parameter.description,\n items: map_parameter_type(parameter.items),\n };\n default:\n return {\n type: parameter.required ? parameter.type : [parameter.type, \"null\"],\n description:\n parameter.default !== undefined\n ? parameter.description\n ? `${parameter.description} (default: ${parameter.default})`\n : `default: ${parameter.default}`\n : parameter.description,\n enum: \"enum\" in parameter ? parameter.enum : undefined,\n };\n }\n }\n return {\n type: \"function\",\n function: {\n name: tool.name,\n description: tool.description,\n parameters: map_parameter_type({\n type: \"object\",\n required: true,\n properties: Object.fromEntries(\n tool.parameters.map(({ name, ...parameter }) => [name, parameter]),\n ),\n }),\n ...(strict ? { strict: true } : {}),\n },\n };\n}\n\nfunction from_openai_completion(\n completion: OpenAI.Chat.Completions.ChatCompletionChunk,\n choice: OpenAI.Chat.Completions.ChatCompletionChunk.Choice,\n) {\n let contents: Content[] = [];\n const thinking = from_openai_thinking(choice.delta);\n if (thinking) {\n contents = [...contents, thinking];\n }\n const delta_record = choice.delta as Record<string, unknown>;\n for (const key of Object.keys(choice.delta)) {\n if (key === \"role\") {\n continue;\n }\n if (is_openai_reasoning_delta_key(key)) {\n continue;\n }\n if (key === \"content\") {\n if (choice.delta.content) {\n contents = [...contents, from_openai_content(choice.delta)];\n }\n continue;\n }\n if (key === \"refusal\") {\n if (choice.delta.refusal) {\n contents = [...contents, from_openai_refusal(choice.delta)];\n }\n continue;\n }\n if (key === \"tool_calls\") {\n if (choice.delta.tool_calls) {\n contents = [...contents, ...choice.delta.tool_calls.map((t) => from_openai_tool_call(t))];\n }\n continue;\n }\n if (delta_record[key] !== undefined && delta_record[key] !== null) {\n const data = delta_record[key];\n contents = [\n ...contents,\n {\n type: \"raw\",\n model_kind: \"openai\",\n data: JSON.stringify({ [key]: data }),\n },\n ];\n }\n }\n return {\n id: completion.id,\n timestamp: completion.created,\n role: map_role(choice),\n content: contents,\n } as AssistantMessage;\n}\n\nfunction get_openai_reasoning_delta(delta: OpenAICompletionDelta) {\n const record = delta as Partial<Record<OpenAIReasoningDeltaKey, unknown>>;\n for (const key of OPENAI_REASONING_DELTA_KEYS) {\n const thought = record[key];\n if (typeof thought === \"string\" && thought.length > 0) {\n return { key, thought };\n }\n }\n return undefined;\n}\n\nfunction from_openai_thinking(content: OpenAICompletionDelta) {\n const reasoning = get_openai_reasoning_delta(content);\n if (!reasoning) {\n return undefined;\n }\n const extended = get_openai_delta_extended(content);\n return {\n type: \"thinking\",\n thought: reasoning.thought,\n extended: {\n ...extended,\n openai_reasoning_field: reasoning.key,\n },\n } as Content;\n}\n\nfunction is_openai_reasoning_delta_key(key: string): key is OpenAIReasoningDeltaKey {\n return OPENAI_REASONING_DELTA_KEYS.includes(key as OpenAIReasoningDeltaKey);\n}\n\nfunction from_openai_refusal(content: OpenAICompletionDelta) {\n return {\n type: \"text\",\n text: content.refusal,\n extended: {\n ...get_openai_delta_extended(content),\n openai_refusal: true,\n },\n } as Content;\n}\n\nfunction from_openai_content(content: OpenAICompletionDelta) {\n return {\n type: \"text\",\n text: content.content,\n extended: get_openai_delta_extended(content),\n } as Content;\n}\n\nfunction get_openai_delta_extended(content: OpenAICompletionDelta) {\n const extended = { ...(content as Record<string, unknown>) };\n delete extended.content;\n delete extended.tool_calls;\n delete extended.function_call;\n delete extended.refusal;\n delete extended.role;\n for (const key of OPENAI_REASONING_DELTA_KEYS) {\n delete extended[key];\n }\n return extended;\n}\n\nfunction from_openai_tool_call(\n tool_call: OpenAI.Chat.Completions.ChatCompletionChunk.Choice.Delta.ToolCall,\n) {\n const { id: tool_request_id, function: fn, type: _, index: __, ...extended } = tool_call;\n let params: unknown;\n try {\n params = JSON.parse(fn?.arguments ?? \"{}\");\n } catch {\n params = fn?.arguments;\n }\n return {\n tool_request_id,\n type: \"tool\",\n tool: fn?.name,\n params,\n extended,\n } as ToolContent;\n}\n\nfunction to_openai_messages(message: Message) {\n if (message.role === \"assistant\") {\n return [to_openai_assistant_message(message)];\n }\n // Partition content so tool_result blocks come before non-tool_result blocks.\n // OpenAI requires all tool-role messages immediately after the assistant message\n // containing the corresponding tool_calls; interleaving user messages between\n // tool messages causes a validation error.\n const tool_result_content = message.content.filter((c) => c.type === \"tool_result\");\n const other_content = message.content.filter((c) => c.type !== \"tool_result\");\n const ordered_content = [...tool_result_content, ...other_content];\n\n const results: OpenAI.ChatCompletionMessageParam[] = [];\n let result: OpenAI.ChatCompletionMessageParam | undefined;\n for (const content of ordered_content) {\n if (content.type === \"text\") {\n if (!result) {\n result = {\n role: \"user\",\n content: content.text,\n };\n } else if (result.role === \"tool\") {\n results.push(result);\n result = {\n role: \"user\",\n content: content.text,\n };\n } else {\n if (typeof result.content === \"string\") {\n result.content = [\n {\n type: \"text\",\n text: result.content,\n },\n ];\n }\n if (!result.content) {\n result.content = [\n {\n type: \"text\",\n text: content.text,\n },\n ];\n } else {\n result.content.push({\n type: \"text\",\n text: content.text,\n });\n }\n }\n } else if (content.type === \"tool_result\") {\n if (!result) {\n result = {\n role: \"tool\",\n tool_call_id: content.tool_request_id,\n content: JSON.stringify(content.result),\n };\n } else if (result.role !== \"tool\" || result.tool_call_id !== content.tool_request_id) {\n results.push(result);\n result = {\n role: \"tool\",\n tool_call_id: content.tool_request_id,\n content: JSON.stringify(content.result),\n };\n } else {\n if (typeof result.content === \"string\") {\n result.content = [\n {\n type: \"text\",\n text: result.content,\n },\n ];\n }\n result.content.push({\n type: \"text\",\n text: JSON.stringify(content.result),\n });\n }\n } else if (content.type === \"raw\") {\n result = {\n ...(result ?? {}),\n ...JSON.parse(content.data),\n };\n }\n }\n if (result) {\n results.push(result);\n }\n return results;\n}\n\nfunction to_openai_assistant_message(message: AssistantMessage) {\n let result: OpenAI.ChatCompletionAssistantMessageParam = {\n role: \"assistant\",\n };\n for (const content of message.content) {\n switch (content.type) {\n case \"text\":\n if (content.extended && content.extended.openai_refusal === true) {\n result.refusal = content.text;\n } else {\n if (typeof result.content === \"string\") {\n result.content = [\n {\n type: \"text\",\n text: result.content,\n },\n ];\n }\n if (!result.content) {\n result.content = content.text;\n } else {\n result.content.push({\n type: \"text\",\n text: content.text,\n });\n }\n }\n break;\n case \"tool\":\n if (!result.tool_calls) {\n result.tool_calls = [];\n }\n result.tool_calls.push({\n id: content.tool_request_id,\n type: \"function\",\n function: {\n name: content.tool,\n arguments: JSON.stringify(content.params),\n },\n });\n break;\n case \"raw\":\n if (content.model_kind !== \"openai\") {\n if (typeof result.content === \"string\") {\n result.content = [\n {\n type: \"text\",\n text: result.content,\n },\n ];\n }\n if (!result.content) {\n result.content = content.data;\n } else {\n result.content.push({\n type: \"text\",\n text: content.data,\n });\n }\n break;\n }\n result = {\n ...result,\n ...JSON.parse(content.data),\n };\n break;\n case \"thinking\":\n if (typeof result.content === \"string\") {\n result.content = [\n {\n type: \"text\",\n text: result.content,\n },\n ];\n }\n if (!result.content) {\n result.content = content.thought;\n } else {\n result.content.push({\n type: \"text\",\n text: content.thought,\n });\n }\n break;\n default:\n throw new Error(\"unexpected content type\");\n }\n }\n return result;\n}\n\nfunction from_openai_usage(usage: OpenAI.CompletionUsage | null | undefined) {\n return {\n input_tokens: usage?.prompt_tokens,\n output_tokens: usage?.completion_tokens,\n } as Usage;\n}\n\nfunction map_stop_reason(\n completion: OpenAI.ChatCompletionChunk,\n): Pick<CompletionResponseData, \"stop_reason\" | \"stop_details\"> {\n for (const choice of completion.choices) {\n switch (choice.finish_reason) {\n case \"content_filter\":\n return {\n stop_reason: \"error\",\n stop_details: choice.finish_reason,\n };\n case \"function_call\":\n return {\n stop_reason: \"tool_use\",\n };\n case \"length\":\n return {\n stop_reason: \"max_tokens\",\n };\n case \"stop\":\n return {\n stop_reason: \"end_turn\",\n };\n case \"tool_calls\":\n return {\n stop_reason: \"tool_use\",\n };\n default:\n return {\n stop_reason: \"other\",\n stop_details: `${choice.finish_reason}`,\n };\n }\n }\n return {\n stop_reason: \"other\",\n };\n}\n\nfunction map_role(choice: OpenAI.Chat.Completions.ChatCompletionChunk.Choice) {\n switch (choice.delta.role) {\n case \"user\":\n case \"developer\":\n case \"system\":\n return \"user\";\n case \"assistant\":\n case \"tool\":\n return \"assistant\";\n default:\n throw new Error(\"invalid role\");\n }\n}\n"],"mappings":"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","names":["message","rest"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@simulacra-ai/openai",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.12",
|
|
4
4
|
"description": "OpenAI provider for the Simulacra conversation engine",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"test:watch": "vitest"
|
|
26
26
|
},
|
|
27
27
|
"peerDependencies": {
|
|
28
|
-
"@simulacra-ai/core": "0.0.
|
|
28
|
+
"@simulacra-ai/core": "0.0.12",
|
|
29
29
|
"openai": ">=4.0.0 <7.0.0"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|