diff --git a/app/MindWork AI Studio/Dialogs/ProviderDialog.razor b/app/MindWork AI Studio/Dialogs/ProviderDialog.razor
index f465c5cf..a0cf55f4 100644
--- a/app/MindWork AI Studio/Dialogs/ProviderDialog.razor
+++ b/app/MindWork AI Studio/Dialogs/ProviderDialog.razor
@@ -135,7 +135,7 @@
@T("Please be aware: This is for experts only. You are responsible for verifying the correctness of the additional parameters you provide to the API call.")
- @T("By default, AI Studio uses the OpenAI-compatible chat/completions API, provided it is supported by the underlying service.")
+ @T("By default, AI Studio uses the OpenAI-compatible chat/completions API, provided it is supported by the underlying service and model.")
diff --git a/app/MindWork AI Studio/Provider/Anthropic/ChatRequest.cs b/app/MindWork AI Studio/Provider/Anthropic/ChatRequest.cs
index afaef92c..3a9404b9 100644
--- a/app/MindWork AI Studio/Provider/Anthropic/ChatRequest.cs
+++ b/app/MindWork AI Studio/Provider/Anthropic/ChatRequest.cs
@@ -20,6 +20,5 @@ public readonly record struct ChatRequest(
)
{
-[JsonExtensionData]
-public Dictionary AdditionalApiParameters { get; init; }
+public IDictionary AdditionalApiParameters { get; init; }
}
\ No newline at end of file
diff --git a/app/MindWork AI Studio/Provider/Anthropic/ProviderAnthropic.cs b/app/MindWork AI Studio/Provider/Anthropic/ProviderAnthropic.cs
index 9a7dd054..298f54d8 100644
--- a/app/MindWork AI Studio/Provider/Anthropic/ProviderAnthropic.cs
+++ b/app/MindWork AI Studio/Provider/Anthropic/ProviderAnthropic.cs
@@ -58,7 +58,7 @@ public sealed class ProviderAnthropic() : BaseProvider("https://api.anthropic.co
}).ToList()],
System = chatThread.PrepareSystemPrompt(settingsManager, chatThread),
- MaxTokens = apiParameters["max_tokens"] as int? ?? 4_096,
+ MaxTokens = int.TryParse(apiParameters["max_tokens"], out int parsed) ? parsed : 4_096,
// Right now, we only support streaming completions:
Stream = true,
diff --git a/app/MindWork AI Studio/Provider/BaseProvider.cs b/app/MindWork AI Studio/Provider/BaseProvider.cs
index 87248bae..e89f711d 100644
--- a/app/MindWork AI Studio/Provider/BaseProvider.cs
+++ b/app/MindWork AI Studio/Provider/BaseProvider.cs
@@ -530,49 +530,46 @@ public abstract class BaseProvider : IProvider, ISecretId
/// optionally merging additional parameters and removing specific keys.
///
/// A JSON string (without surrounding braces) containing the API parameters to be parsed.
- /// Optional additional parameters to merge into the result. These will overwrite existing keys.
/// Optional list of keys to remove from the final dictionary (case-insensitive). stream, model and messages are removed by default.
- protected Dictionary ParseApiParameters(
+ protected IDictionary ParseApiParameters(
string additionalUserProvidedParameters,
IEnumerable? keysToRemove = null)
{
-
- var json = $"{{{additionalUserProvidedParameters}}}";
- var jsonDoc = JsonSerializer.Deserialize(json, JSON_SERIALIZER_OPTIONS);
- var dict = this.ConvertToDictionary(jsonDoc);
-
- // Some keys are always removed because we always set them
- var finalKeysToRemove = keysToRemove?.ToList() ?? new List();
- finalKeysToRemove.Add("stream");
- finalKeysToRemove.Add("model");
- finalKeysToRemove.Add("messages");
+ try
+ {
+ // we need to remove line breaks from the JSON string otherwise the server might have problems with parsing the call
+ var withoutLineBreak = additionalUserProvidedParameters.Replace("\n", string.Empty);
+
+ var json = $"{{{withoutLineBreak}}}";
+ var jsonDoc = JsonSerializer.Deserialize(json, JSON_SERIALIZER_OPTIONS);
+ var dict = this.ConvertToDictionary(jsonDoc);
- var removeSet = new HashSet(finalKeysToRemove, StringComparer.OrdinalIgnoreCase);
- var toRemove = dict.Keys.Where(k => removeSet.Contains(k)).ToList();
- foreach (var k in toRemove)
- dict.Remove(k);
+ // Some keys are always removed because we always set them
+ var finalKeysToRemove = keysToRemove?.ToList() ?? new List();
+ finalKeysToRemove.Add("stream");
+ finalKeysToRemove.Add("model");
+ finalKeysToRemove.Add("messages");
- return dict;
+ var removeSet = new HashSet(finalKeysToRemove, StringComparer.OrdinalIgnoreCase);
+ var toRemove = dict.Keys.Where(k => removeSet.Contains(k)).ToList();
+ foreach (var k in toRemove)
+ dict.Remove(k);
+
+ return dict;
+ }
+ catch (JsonException ex)
+ {
+ throw new ArgumentException("Invalid JSON in additionalUserProvidedParameters", ex);
+ }
}
- private Dictionary ConvertToDictionary(JsonElement element)
+ private IDictionary ConvertToDictionary(JsonElement element)
{
return element.EnumerateObject()
.ToDictionary(
p => p.Name,
- p => this.ConvertJsonElement(p.Value)
+ p => p.Value.GetRawText()
);
}
-
- private object? ConvertJsonElement(JsonElement element) => element.ValueKind switch
- {
- JsonValueKind.String => element.GetString(),
- JsonValueKind.Number => element.TryGetInt32(out var i) ? (object)i : element.GetDouble(),
- JsonValueKind.True => true,
- JsonValueKind.False => false,
- JsonValueKind.Object => this.ConvertToDictionary(element),
- JsonValueKind.Array => element.EnumerateArray().Select(this.ConvertJsonElement).ToList(),
- JsonValueKind.Null => null,
- _ => element.ToString()
- };
+
}
\ No newline at end of file
diff --git a/app/MindWork AI Studio/Provider/Fireworks/ChatRequest.cs b/app/MindWork AI Studio/Provider/Fireworks/ChatRequest.cs
index cf9f5115..0738ea32 100644
--- a/app/MindWork AI Studio/Provider/Fireworks/ChatRequest.cs
+++ b/app/MindWork AI Studio/Provider/Fireworks/ChatRequest.cs
@@ -15,6 +15,5 @@ public readonly record struct ChatRequest(
)
{
- [JsonExtensionData]
- public Dictionary AdditionalApiParameters { get; init; }
+ public IDictionary AdditionalApiParameters { get; init; }
}
\ No newline at end of file
diff --git a/app/MindWork AI Studio/Provider/Google/ChatRequest.cs b/app/MindWork AI Studio/Provider/Google/ChatRequest.cs
index e0b50874..b8e1d2ed 100644
--- a/app/MindWork AI Studio/Provider/Google/ChatRequest.cs
+++ b/app/MindWork AI Studio/Provider/Google/ChatRequest.cs
@@ -15,7 +15,5 @@ public readonly record struct ChatRequest(
bool Stream
)
{
-
- [JsonExtensionData]
- public Dictionary AdditionalApiParameters { get; init; }
+ public IDictionary AdditionalApiParameters { get; init; }
}
\ No newline at end of file
diff --git a/app/MindWork AI Studio/Provider/Groq/ChatRequest.cs b/app/MindWork AI Studio/Provider/Groq/ChatRequest.cs
index 50d320bc..2725eae0 100644
--- a/app/MindWork AI Studio/Provider/Groq/ChatRequest.cs
+++ b/app/MindWork AI Studio/Provider/Groq/ChatRequest.cs
@@ -18,6 +18,5 @@ public readonly record struct ChatRequest(
)
{
- [JsonExtensionData]
- public Dictionary AdditionalApiParameters { get; init; }
+ public IDictionary AdditionalApiParameters { get; init; }
}
\ No newline at end of file
diff --git a/app/MindWork AI Studio/Provider/Mistral/ChatRequest.cs b/app/MindWork AI Studio/Provider/Mistral/ChatRequest.cs
index 48d69bb0..0daaebf7 100644
--- a/app/MindWork AI Studio/Provider/Mistral/ChatRequest.cs
+++ b/app/MindWork AI Studio/Provider/Mistral/ChatRequest.cs
@@ -19,6 +19,5 @@ public readonly record struct ChatRequest(
)
{
- [JsonExtensionData]
- public Dictionary AdditionalApiParameters { get; init; }
+ public IDictionary AdditionalApiParameters { get; init; }
}
\ No newline at end of file
diff --git a/app/MindWork AI Studio/Provider/Mistral/ProviderMistral.cs b/app/MindWork AI Studio/Provider/Mistral/ProviderMistral.cs
index 2b28487c..13e35a08 100644
--- a/app/MindWork AI Studio/Provider/Mistral/ProviderMistral.cs
+++ b/app/MindWork AI Studio/Provider/Mistral/ProviderMistral.cs
@@ -69,7 +69,7 @@ public sealed class ProviderMistral() : BaseProvider("https://api.mistral.ai/v1/
// Right now, we only support streaming completions:
Stream = true,
- SafePrompt = apiParameters["safe_prompt"] as bool? ?? false,
+ SafePrompt = bool.TryParse(apiParameters["safe_prompt"], out bool safePrompt) && safePrompt,
AdditionalApiParameters = apiParameters
}, JSON_SERIALIZER_OPTIONS);
diff --git a/app/MindWork AI Studio/Provider/OpenAI/ChatCompletionAPIRequest.cs b/app/MindWork AI Studio/Provider/OpenAI/ChatCompletionAPIRequest.cs
index d5a30286..1d79950e 100644
--- a/app/MindWork AI Studio/Provider/OpenAI/ChatCompletionAPIRequest.cs
+++ b/app/MindWork AI Studio/Provider/OpenAI/ChatCompletionAPIRequest.cs
@@ -18,6 +18,5 @@ public record ChatCompletionAPIRequest(
{
}
- [JsonExtensionData]
- public Dictionary? AdditionalApiParameters { get; init; }
+ public IDictionary? AdditionalApiParameters { get; init; }
}
\ No newline at end of file
diff --git a/app/MindWork AI Studio/Provider/OpenAI/ResponsesAPIRequest.cs b/app/MindWork AI Studio/Provider/OpenAI/ResponsesAPIRequest.cs
index 520e50f4..ee399e47 100644
--- a/app/MindWork AI Studio/Provider/OpenAI/ResponsesAPIRequest.cs
+++ b/app/MindWork AI Studio/Provider/OpenAI/ResponsesAPIRequest.cs
@@ -21,6 +21,5 @@ public record ResponsesAPIRequest(
{
}
- [JsonExtensionData]
- public Dictionary? AdditionalApiParameters { get; init; }
+ public IDictionary? AdditionalApiParameters { get; init; }
}
\ No newline at end of file
diff --git a/app/MindWork AI Studio/Provider/SelfHosted/ChatRequest.cs b/app/MindWork AI Studio/Provider/SelfHosted/ChatRequest.cs
index 97618492..8599f72c 100644
--- a/app/MindWork AI Studio/Provider/SelfHosted/ChatRequest.cs
+++ b/app/MindWork AI Studio/Provider/SelfHosted/ChatRequest.cs
@@ -15,6 +15,5 @@ public readonly record struct ChatRequest(
)
{
- [JsonExtensionData]
- public Dictionary AdditionalApiParameters { get; init; }
+ public IDictionary AdditionalApiParameters { get; init; }
}
\ No newline at end of file