@wrongstack/providers 0.257.2 → 0.260.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -164,6 +164,26 @@ interface ConvertOptions {
164
164
  flattenContentToString?: boolean | undefined;
165
165
  stripCacheControl?: boolean | undefined;
166
166
  systemAsMessage?: boolean | undefined;
167
+ /**
168
+ * What to write as the assistant message's `content` field when the
169
+ * message has tool_calls but no prose. Two values:
170
+ *
171
+ * - `'empty_string'` (default): writes `content: ''`. This is the
172
+ * OpenAI 2024-2025 wire-format contract. Vanilla OpenAI, K2P7,
173
+ * strict Mistral / OpenRouter / DeepSeek proxies all reject
174
+ * requests where `content` is missing or `null` on a tool_call
175
+ * assistant message.
176
+ *
177
+ * - `'null'`: writes `content: null` explicitly. Some older or
178
+ * permissive proxies (e.g. certain vLLM builds, local llama.cpp
179
+ * servers) prefer this. Set this only if a specific provider
180
+ * rejects the empty-string form.
181
+ *
182
+ * The default is `'empty_string'` (NOT undefined) because omitting
183
+ * `content` entirely (the pre-2024 behaviour) breaks too many
184
+ * providers to be the safe default in 2025. Callers that need the
185
+ * old behaviour can opt in with `emptyToolCallContent: 'null'`.
186
+ */
167
187
  emptyToolCallContent?: 'null' | 'empty_string' | undefined;
168
188
  }
169
189
  declare function messagesToOpenAI(system: TextBlock[] | undefined, messages: Message[], opts?: ConvertOptions): OpenAIMessage[];
package/dist/index.js CHANGED
@@ -1209,6 +1209,7 @@ function toolsToOpenAI(tools) {
1209
1209
  }));
1210
1210
  }
1211
1211
  function messagesToOpenAI(system, messages, opts = {}) {
1212
+ const emptyContentMode = opts.emptyToolCallContent ?? "empty_string";
1212
1213
  const out = [];
1213
1214
  if (system && system.length > 0) {
1214
1215
  const sysText = system.map((b) => b.text).join("\n\n");
@@ -1255,7 +1256,6 @@ function messagesToOpenAI(system, messages, opts = {}) {
1255
1256
  if (text) {
1256
1257
  message.content = text;
1257
1258
  } else {
1258
- const emptyContentMode = opts.emptyToolCallContent ?? "empty_string";
1259
1259
  message.content = emptyContentMode === "null" ? null : "";
1260
1260
  }
1261
1261
  } else {
@@ -1627,7 +1627,7 @@ var mistralWireFormat = defineWireFormat({
1627
1627
  buildBody: (req) => {
1628
1628
  const body = {
1629
1629
  model: req.model,
1630
- messages: messagesToOpenAI(stripCacheControl(req.system), req.messages, {}),
1630
+ messages: messagesToOpenAI(stripCacheControl(req.system), req.messages),
1631
1631
  max_tokens: req.maxTokens,
1632
1632
  stream: true
1633
1633
  };
@@ -1908,7 +1908,7 @@ var openaiWireFormat = defineWireFormat({
1908
1908
  buildBody: (req) => {
1909
1909
  const body = {
1910
1910
  model: req.model,
1911
- messages: messagesToOpenAI(stripCacheControl2(req.system), req.messages, {}),
1911
+ messages: messagesToOpenAI(stripCacheControl2(req.system), req.messages),
1912
1912
  // Real OpenAI requires `max_completion_tokens`; newer model families
1913
1913
  // (gpt-4o, o1/o3/o4) 400 on the deprecated `max_tokens`. See issue #10.
1914
1914
  max_completion_tokens: req.maxTokens,