@simulacra-ai/openai 0.0.11 → 0.0.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +42 -4
- package/dist/index.cjs +45 -13
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +61 -4
- package/dist/index.d.ts +61 -4
- package/dist/index.js +45 -13
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Simulacra OpenAI Provider
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
OpenAI chat-completions provider for Simulacra. Works against OpenAI directly (GPT, o-series) and against any OpenAI-compatible endpoint (DeepSeek, OpenRouter, self-hosted gateways like vLLM / llama.cpp / Ollama, Anthropic-via-compat, etc.).
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
@@ -15,22 +15,60 @@ import { Conversation } from "@simulacra-ai/core";
|
|
|
15
15
|
import { OpenAIProvider } from "@simulacra-ai/openai";
|
|
16
16
|
import OpenAI from "openai";
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
const provider = new OpenAIProvider(new OpenAI(), { model: MODEL_NAME });
|
|
18
|
+
const provider = new OpenAIProvider(new OpenAI(), { model: "gpt-4o" });
|
|
20
19
|
using conversation = new Conversation(provider);
|
|
21
20
|
```
|
|
22
21
|
|
|
23
|
-
|
|
22
|
+
For a non-OpenAI endpoint, point the SDK at it:
|
|
23
|
+
|
|
24
|
+
```typescript
|
|
25
|
+
const sdk = new OpenAI({
|
|
26
|
+
baseURL: "https://api.deepseek.com",
|
|
27
|
+
apiKey: process.env.DEEPSEEK_API_KEY,
|
|
28
|
+
});
|
|
29
|
+
const provider = new OpenAIProvider(sdk, { model: "deepseek-v4-flash" });
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## OpenAIProviderConfig
|
|
24
33
|
|
|
25
34
|
```typescript
|
|
26
35
|
interface OpenAIProviderConfig {
|
|
27
36
|
model: string;
|
|
28
37
|
max_tokens?: number;
|
|
38
|
+
system_role?: "auto" | "system" | "developer";
|
|
39
|
+
strict_tools?: "auto" | "never";
|
|
40
|
+
upstream_reasoning?: "inline" | "field" | "drop";
|
|
29
41
|
}
|
|
30
42
|
```
|
|
31
43
|
|
|
32
44
|
Additional properties (`temperature`, `top_p`, etc.) spread into the API request.
|
|
33
45
|
|
|
46
|
+
### `system_role`
|
|
47
|
+
|
|
48
|
+
Role used for the system prompt.
|
|
49
|
+
|
|
50
|
+
- `"auto"` (default): `gpt*` → `system`, o-series (`o1`, `o3`, `o4`, ...) → `developer`, anything else → `system`. The fallback to `system` is the broadly-compatible default — most non-OpenAI endpoints reject `developer`.
|
|
51
|
+
- `"system"` / `"developer"`: force regardless of model id.
|
|
52
|
+
|
|
53
|
+
Set explicitly when routing through a relay using `vendor/model` ids (`openai/o3`); the heuristic only matches bare ids.
|
|
54
|
+
|
|
55
|
+
### `strict_tools`
|
|
56
|
+
|
|
57
|
+
Whether to emit OpenAI's `function.strict: true` flag on tool definitions.
|
|
58
|
+
|
|
59
|
+
- `"auto"` (default): emitted for `gpt*` and o-series. Other models get tool defs without `strict`.
|
|
60
|
+
- `"never"`: never emitted.
|
|
61
|
+
|
|
62
|
+
`strict` is an OpenAI-specific extension. Most other endpoints either ignore it or reject it.
|
|
63
|
+
|
|
64
|
+
### `upstream_reasoning`
|
|
65
|
+
|
|
66
|
+
Treatment of prior `thinking` content blocks when serializing assistant messages back up the wire.
|
|
67
|
+
|
|
68
|
+
- `"inline"` (default): appended as text content. OpenAI tolerates it (treated as ordinary assistant text on subsequent calls).
|
|
69
|
+
- `"field"`: emitted as a `reasoning_content` field on the assistant message. Required by DeepSeek V4 thinking-mode, which rejects follow-up calls when prior reasoning is missing or inlined into content.
|
|
70
|
+
- `"drop"`: omitted entirely.
|
|
71
|
+
|
|
34
72
|
## License
|
|
35
73
|
|
|
36
74
|
MIT
|
package/dist/index.cjs
CHANGED
|
@@ -51,7 +51,9 @@ var OpenAIProvider = class _OpenAIProvider {
|
|
|
51
51
|
* @returns A promise that resolves when the request completes.
|
|
52
52
|
*/
|
|
53
53
|
async execute_request(request, receiver, cancellation) {
|
|
54
|
-
const { model, max_tokens, ...api_extras } = this.#config;
|
|
54
|
+
const { model, max_tokens, system_role, strict_tools, upstream_reasoning, ...api_extras } = this.#config;
|
|
55
|
+
const emit_strict = resolve_strict_tools(model, strict_tools);
|
|
56
|
+
const reasoning_mode = upstream_reasoning ?? "inline";
|
|
55
57
|
const params = {
|
|
56
58
|
...api_extras,
|
|
57
59
|
model,
|
|
@@ -59,11 +61,11 @@ var OpenAIProvider = class _OpenAIProvider {
|
|
|
59
61
|
max_tokens,
|
|
60
62
|
...request.tools.length > 0 ? {
|
|
61
63
|
tool_choice: "auto",
|
|
62
|
-
tools: request.tools.map((t) => to_openai_tool(t))
|
|
64
|
+
tools: request.tools.map((t) => to_openai_tool(t, emit_strict))
|
|
63
65
|
} : {},
|
|
64
66
|
messages: [
|
|
65
|
-
...get_system_context(model, request.system),
|
|
66
|
-
...request.messages.flatMap((m) => to_openai_messages(m))
|
|
67
|
+
...get_system_context(model, request.system, system_role),
|
|
68
|
+
...request.messages.flatMap((m) => to_openai_messages(m, reasoning_mode))
|
|
67
69
|
],
|
|
68
70
|
stream_options: {
|
|
69
71
|
include_usage: true
|
|
@@ -237,26 +239,48 @@ var OpenAIProvider = class _OpenAIProvider {
|
|
|
237
239
|
}
|
|
238
240
|
}
|
|
239
241
|
};
|
|
240
|
-
function get_system_context(model, system) {
|
|
242
|
+
function get_system_context(model, system, system_role = "auto") {
|
|
241
243
|
if (!system) {
|
|
242
244
|
return [];
|
|
243
245
|
}
|
|
244
|
-
|
|
246
|
+
const role = resolve_system_role(model, system_role);
|
|
247
|
+
if (role === "developer") {
|
|
245
248
|
return [
|
|
246
249
|
{
|
|
247
|
-
role: "
|
|
250
|
+
role: "developer",
|
|
248
251
|
content: system
|
|
249
252
|
}
|
|
250
253
|
];
|
|
251
254
|
}
|
|
252
255
|
return [
|
|
253
256
|
{
|
|
254
|
-
role: "
|
|
257
|
+
role: "system",
|
|
255
258
|
content: system
|
|
256
259
|
}
|
|
257
260
|
];
|
|
258
261
|
}
|
|
259
|
-
function
|
|
262
|
+
function resolve_system_role(model, system_role = "auto") {
|
|
263
|
+
if (system_role === "system" || system_role === "developer") {
|
|
264
|
+
return system_role;
|
|
265
|
+
}
|
|
266
|
+
if (model.startsWith("gpt")) {
|
|
267
|
+
return "system";
|
|
268
|
+
}
|
|
269
|
+
if (is_openai_reasoning_model(model)) {
|
|
270
|
+
return "developer";
|
|
271
|
+
}
|
|
272
|
+
return "system";
|
|
273
|
+
}
|
|
274
|
+
function resolve_strict_tools(model, strict_tools = "auto") {
|
|
275
|
+
if (strict_tools === "never") {
|
|
276
|
+
return false;
|
|
277
|
+
}
|
|
278
|
+
return model.startsWith("gpt") || is_openai_reasoning_model(model);
|
|
279
|
+
}
|
|
280
|
+
function is_openai_reasoning_model(model) {
|
|
281
|
+
return /^o[1-9]\d*(-|$)/.test(model);
|
|
282
|
+
}
|
|
283
|
+
function to_openai_tool(tool, strict) {
|
|
260
284
|
function map_parameter_type(parameter) {
|
|
261
285
|
switch (parameter.type) {
|
|
262
286
|
case "object":
|
|
@@ -295,7 +319,7 @@ function to_openai_tool(tool) {
|
|
|
295
319
|
tool.parameters.map(({ name, ...parameter }) => [name, parameter])
|
|
296
320
|
)
|
|
297
321
|
}),
|
|
298
|
-
strict: true
|
|
322
|
+
...strict ? { strict: true } : {}
|
|
299
323
|
}
|
|
300
324
|
};
|
|
301
325
|
}
|
|
@@ -423,9 +447,9 @@ function from_openai_tool_call(tool_call) {
|
|
|
423
447
|
extended
|
|
424
448
|
};
|
|
425
449
|
}
|
|
426
|
-
function to_openai_messages(message) {
|
|
450
|
+
function to_openai_messages(message, upstream_reasoning) {
|
|
427
451
|
if (message.role === "assistant") {
|
|
428
|
-
return [to_openai_assistant_message(message)];
|
|
452
|
+
return [to_openai_assistant_message(message, upstream_reasoning)];
|
|
429
453
|
}
|
|
430
454
|
const tool_result_content = message.content.filter((c) => c.type === "tool_result");
|
|
431
455
|
const other_content = message.content.filter((c) => c.type !== "tool_result");
|
|
@@ -508,7 +532,7 @@ function to_openai_messages(message) {
|
|
|
508
532
|
}
|
|
509
533
|
return results;
|
|
510
534
|
}
|
|
511
|
-
function to_openai_assistant_message(message) {
|
|
535
|
+
function to_openai_assistant_message(message, upstream_reasoning) {
|
|
512
536
|
let result = {
|
|
513
537
|
role: "assistant"
|
|
514
538
|
};
|
|
@@ -575,6 +599,14 @@ function to_openai_assistant_message(message) {
|
|
|
575
599
|
};
|
|
576
600
|
break;
|
|
577
601
|
case "thinking":
|
|
602
|
+
if (upstream_reasoning === "drop") {
|
|
603
|
+
break;
|
|
604
|
+
}
|
|
605
|
+
if (upstream_reasoning === "field") {
|
|
606
|
+
const widened = result;
|
|
607
|
+
widened.reasoning_content = widened.reasoning_content !== void 0 ? widened.reasoning_content + "\n" + content.thought : content.thought;
|
|
608
|
+
break;
|
|
609
|
+
}
|
|
578
610
|
if (typeof result.content === "string") {
|
|
579
611
|
result.content = [
|
|
580
612
|
{
|
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\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\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 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(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 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"]}
|
|
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 * Treatment of prior `thinking` content blocks when serializing assistant\n * messages back up the wire.\n *\n * - `\"inline\"` (default): appended as text content. openai tolerates it.\n * - `\"field\"`: emitted as a `reasoning_content` field. required by\n * deepseek v4 thinking-mode.\n * - `\"drop\"`: omitted entirely.\n */\n upstream_reasoning?: \"inline\" | \"field\" | \"drop\";\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 * `OpenAIProviderConfig.upstream_reasoning` controls how prior thinking\n * content is round-tripped on subsequent calls for providers (deepseek v4)\n * that require it in a specific shape.\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, upstream_reasoning, ...api_extras } =\n this.#config;\n const emit_strict = resolve_strict_tools(model, strict_tools);\n const reasoning_mode = upstream_reasoning ?? \"inline\";\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, reasoning_mode)),\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(\n message: Message,\n upstream_reasoning: NonNullable<OpenAIProviderConfig[\"upstream_reasoning\"]>,\n) {\n if (message.role === \"assistant\") {\n return [to_openai_assistant_message(message, upstream_reasoning)];\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(\n message: AssistantMessage,\n upstream_reasoning: NonNullable<OpenAIProviderConfig[\"upstream_reasoning\"]>,\n) {\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 (upstream_reasoning === \"drop\") {\n break;\n }\n if (upstream_reasoning === \"field\") {\n const widened = result as OpenAI.ChatCompletionAssistantMessageParam & {\n reasoning_content?: string;\n };\n widened.reasoning_content =\n widened.reasoning_content !== undefined\n ? widened.reasoning_content + \"\\n\" + content.thought\n : content.thought;\n break;\n }\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,71 @@ 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";
|
|
49
|
+
/**
|
|
50
|
+
* Treatment of prior `thinking` content blocks when serializing assistant
|
|
51
|
+
* messages back up the wire.
|
|
52
|
+
*
|
|
53
|
+
* - `"inline"` (default): appended as text content. openai tolerates it.
|
|
54
|
+
* - `"field"`: emitted as a `reasoning_content` field. required by
|
|
55
|
+
* deepseek v4 thinking-mode.
|
|
56
|
+
* - `"drop"`: omitted entirely.
|
|
57
|
+
*/
|
|
58
|
+
upstream_reasoning?: "inline" | "field" | "drop";
|
|
12
59
|
}
|
|
13
60
|
/**
|
|
14
61
|
* Model provider implementation for OpenAI's chat completion models.
|
|
15
62
|
*
|
|
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
|
-
*
|
|
63
|
+
* This provider wraps the OpenAI SDK to provide streaming completions with
|
|
64
|
+
* support for tool use and function calling. It handles message formatting,
|
|
65
|
+
* content streaming, and usage tracking according to the ModelProvider
|
|
66
|
+
* interface.
|
|
67
|
+
*
|
|
68
|
+
* Works against OpenAI directly as well as OpenAI-compatible endpoints
|
|
69
|
+
* (DeepSeek, OpenRouter, self-hosted gateways, etc.). The default behaviour
|
|
70
|
+
* picks `system` vs. `developer` for the system prompt and decides whether
|
|
71
|
+
* to emit OpenAI's `strict` flag on tool defs based on the model id; both
|
|
72
|
+
* can be overridden through `OpenAIProviderConfig.system_role` and
|
|
73
|
+
* `OpenAIProviderConfig.strict_tools` for endpoints whose behaviour differs.
|
|
74
|
+
* `OpenAIProviderConfig.upstream_reasoning` controls how prior thinking
|
|
75
|
+
* content is round-tripped on subsequent calls for providers (deepseek v4)
|
|
76
|
+
* that require it in a specific shape.
|
|
20
77
|
*/
|
|
21
78
|
declare class OpenAIProvider implements ModelProvider {
|
|
22
79
|
#private;
|
package/dist/index.d.ts
CHANGED
|
@@ -9,14 +9,71 @@ 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";
|
|
49
|
+
/**
|
|
50
|
+
* Treatment of prior `thinking` content blocks when serializing assistant
|
|
51
|
+
* messages back up the wire.
|
|
52
|
+
*
|
|
53
|
+
* - `"inline"` (default): appended as text content. openai tolerates it.
|
|
54
|
+
* - `"field"`: emitted as a `reasoning_content` field. required by
|
|
55
|
+
* deepseek v4 thinking-mode.
|
|
56
|
+
* - `"drop"`: omitted entirely.
|
|
57
|
+
*/
|
|
58
|
+
upstream_reasoning?: "inline" | "field" | "drop";
|
|
12
59
|
}
|
|
13
60
|
/**
|
|
14
61
|
* Model provider implementation for OpenAI's chat completion models.
|
|
15
62
|
*
|
|
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
|
-
*
|
|
63
|
+
* This provider wraps the OpenAI SDK to provide streaming completions with
|
|
64
|
+
* support for tool use and function calling. It handles message formatting,
|
|
65
|
+
* content streaming, and usage tracking according to the ModelProvider
|
|
66
|
+
* interface.
|
|
67
|
+
*
|
|
68
|
+
* Works against OpenAI directly as well as OpenAI-compatible endpoints
|
|
69
|
+
* (DeepSeek, OpenRouter, self-hosted gateways, etc.). The default behaviour
|
|
70
|
+
* picks `system` vs. `developer` for the system prompt and decides whether
|
|
71
|
+
* to emit OpenAI's `strict` flag on tool defs based on the model id; both
|
|
72
|
+
* can be overridden through `OpenAIProviderConfig.system_role` and
|
|
73
|
+
* `OpenAIProviderConfig.strict_tools` for endpoints whose behaviour differs.
|
|
74
|
+
* `OpenAIProviderConfig.upstream_reasoning` controls how prior thinking
|
|
75
|
+
* content is round-tripped on subsequent calls for providers (deepseek v4)
|
|
76
|
+
* that require it in a specific shape.
|
|
20
77
|
*/
|
|
21
78
|
declare class OpenAIProvider implements ModelProvider {
|
|
22
79
|
#private;
|
package/dist/index.js
CHANGED
|
@@ -25,7 +25,9 @@ var OpenAIProvider = class _OpenAIProvider {
|
|
|
25
25
|
* @returns A promise that resolves when the request completes.
|
|
26
26
|
*/
|
|
27
27
|
async execute_request(request, receiver, cancellation) {
|
|
28
|
-
const { model, max_tokens, ...api_extras } = this.#config;
|
|
28
|
+
const { model, max_tokens, system_role, strict_tools, upstream_reasoning, ...api_extras } = this.#config;
|
|
29
|
+
const emit_strict = resolve_strict_tools(model, strict_tools);
|
|
30
|
+
const reasoning_mode = upstream_reasoning ?? "inline";
|
|
29
31
|
const params = {
|
|
30
32
|
...api_extras,
|
|
31
33
|
model,
|
|
@@ -33,11 +35,11 @@ var OpenAIProvider = class _OpenAIProvider {
|
|
|
33
35
|
max_tokens,
|
|
34
36
|
...request.tools.length > 0 ? {
|
|
35
37
|
tool_choice: "auto",
|
|
36
|
-
tools: request.tools.map((t) => to_openai_tool(t))
|
|
38
|
+
tools: request.tools.map((t) => to_openai_tool(t, emit_strict))
|
|
37
39
|
} : {},
|
|
38
40
|
messages: [
|
|
39
|
-
...get_system_context(model, request.system),
|
|
40
|
-
...request.messages.flatMap((m) => to_openai_messages(m))
|
|
41
|
+
...get_system_context(model, request.system, system_role),
|
|
42
|
+
...request.messages.flatMap((m) => to_openai_messages(m, reasoning_mode))
|
|
41
43
|
],
|
|
42
44
|
stream_options: {
|
|
43
45
|
include_usage: true
|
|
@@ -211,26 +213,48 @@ var OpenAIProvider = class _OpenAIProvider {
|
|
|
211
213
|
}
|
|
212
214
|
}
|
|
213
215
|
};
|
|
214
|
-
function get_system_context(model, system) {
|
|
216
|
+
function get_system_context(model, system, system_role = "auto") {
|
|
215
217
|
if (!system) {
|
|
216
218
|
return [];
|
|
217
219
|
}
|
|
218
|
-
|
|
220
|
+
const role = resolve_system_role(model, system_role);
|
|
221
|
+
if (role === "developer") {
|
|
219
222
|
return [
|
|
220
223
|
{
|
|
221
|
-
role: "
|
|
224
|
+
role: "developer",
|
|
222
225
|
content: system
|
|
223
226
|
}
|
|
224
227
|
];
|
|
225
228
|
}
|
|
226
229
|
return [
|
|
227
230
|
{
|
|
228
|
-
role: "
|
|
231
|
+
role: "system",
|
|
229
232
|
content: system
|
|
230
233
|
}
|
|
231
234
|
];
|
|
232
235
|
}
|
|
233
|
-
function
|
|
236
|
+
function resolve_system_role(model, system_role = "auto") {
|
|
237
|
+
if (system_role === "system" || system_role === "developer") {
|
|
238
|
+
return system_role;
|
|
239
|
+
}
|
|
240
|
+
if (model.startsWith("gpt")) {
|
|
241
|
+
return "system";
|
|
242
|
+
}
|
|
243
|
+
if (is_openai_reasoning_model(model)) {
|
|
244
|
+
return "developer";
|
|
245
|
+
}
|
|
246
|
+
return "system";
|
|
247
|
+
}
|
|
248
|
+
function resolve_strict_tools(model, strict_tools = "auto") {
|
|
249
|
+
if (strict_tools === "never") {
|
|
250
|
+
return false;
|
|
251
|
+
}
|
|
252
|
+
return model.startsWith("gpt") || is_openai_reasoning_model(model);
|
|
253
|
+
}
|
|
254
|
+
function is_openai_reasoning_model(model) {
|
|
255
|
+
return /^o[1-9]\d*(-|$)/.test(model);
|
|
256
|
+
}
|
|
257
|
+
function to_openai_tool(tool, strict) {
|
|
234
258
|
function map_parameter_type(parameter) {
|
|
235
259
|
switch (parameter.type) {
|
|
236
260
|
case "object":
|
|
@@ -269,7 +293,7 @@ function to_openai_tool(tool) {
|
|
|
269
293
|
tool.parameters.map(({ name, ...parameter }) => [name, parameter])
|
|
270
294
|
)
|
|
271
295
|
}),
|
|
272
|
-
strict: true
|
|
296
|
+
...strict ? { strict: true } : {}
|
|
273
297
|
}
|
|
274
298
|
};
|
|
275
299
|
}
|
|
@@ -397,9 +421,9 @@ function from_openai_tool_call(tool_call) {
|
|
|
397
421
|
extended
|
|
398
422
|
};
|
|
399
423
|
}
|
|
400
|
-
function to_openai_messages(message) {
|
|
424
|
+
function to_openai_messages(message, upstream_reasoning) {
|
|
401
425
|
if (message.role === "assistant") {
|
|
402
|
-
return [to_openai_assistant_message(message)];
|
|
426
|
+
return [to_openai_assistant_message(message, upstream_reasoning)];
|
|
403
427
|
}
|
|
404
428
|
const tool_result_content = message.content.filter((c) => c.type === "tool_result");
|
|
405
429
|
const other_content = message.content.filter((c) => c.type !== "tool_result");
|
|
@@ -482,7 +506,7 @@ function to_openai_messages(message) {
|
|
|
482
506
|
}
|
|
483
507
|
return results;
|
|
484
508
|
}
|
|
485
|
-
function to_openai_assistant_message(message) {
|
|
509
|
+
function to_openai_assistant_message(message, upstream_reasoning) {
|
|
486
510
|
let result = {
|
|
487
511
|
role: "assistant"
|
|
488
512
|
};
|
|
@@ -549,6 +573,14 @@ function to_openai_assistant_message(message) {
|
|
|
549
573
|
};
|
|
550
574
|
break;
|
|
551
575
|
case "thinking":
|
|
576
|
+
if (upstream_reasoning === "drop") {
|
|
577
|
+
break;
|
|
578
|
+
}
|
|
579
|
+
if (upstream_reasoning === "field") {
|
|
580
|
+
const widened = result;
|
|
581
|
+
widened.reasoning_content = widened.reasoning_content !== void 0 ? widened.reasoning_content + "\n" + content.thought : content.thought;
|
|
582
|
+
break;
|
|
583
|
+
}
|
|
552
584
|
if (typeof result.content === "string") {
|
|
553
585
|
result.content = [
|
|
554
586
|
{
|
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\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\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 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(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 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"]}
|
|
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 * Treatment of prior `thinking` content blocks when serializing assistant\n * messages back up the wire.\n *\n * - `\"inline\"` (default): appended as text content. openai tolerates it.\n * - `\"field\"`: emitted as a `reasoning_content` field. required by\n * deepseek v4 thinking-mode.\n * - `\"drop\"`: omitted entirely.\n */\n upstream_reasoning?: \"inline\" | \"field\" | \"drop\";\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 * `OpenAIProviderConfig.upstream_reasoning` controls how prior thinking\n * content is round-tripped on subsequent calls for providers (deepseek v4)\n * that require it in a specific shape.\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, upstream_reasoning, ...api_extras } =\n this.#config;\n const emit_strict = resolve_strict_tools(model, strict_tools);\n const reasoning_mode = upstream_reasoning ?? \"inline\";\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, reasoning_mode)),\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(\n message: Message,\n upstream_reasoning: NonNullable<OpenAIProviderConfig[\"upstream_reasoning\"]>,\n) {\n if (message.role === \"assistant\") {\n return [to_openai_assistant_message(message, upstream_reasoning)];\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(\n message: AssistantMessage,\n upstream_reasoning: NonNullable<OpenAIProviderConfig[\"upstream_reasoning\"]>,\n) {\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 (upstream_reasoning === \"drop\") {\n break;\n }\n if (upstream_reasoning === \"field\") {\n const widened = result as OpenAI.ChatCompletionAssistantMessageParam & {\n reasoning_content?: string;\n };\n widened.reasoning_content =\n widened.reasoning_content !== undefined\n ? widened.reasoning_content + \"\\n\" + content.thought\n : content.thought;\n break;\n }\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.13",
|
|
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.13",
|
|
29
29
|
"openai": ">=4.0.0 <7.0.0"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|