Skip to content

Instantly share code, notes, and snippets.

@DevEnable
Created June 12, 2025 21:06
Show Gist options
  • Select an option

  • Save DevEnable/9bc8f461c77830ac86c2298c9050f8b6 to your computer and use it in GitHub Desktop.

Select an option

Save DevEnable/9bc8f461c77830ac86c2298c9050f8b6 to your computer and use it in GitHub Desktop.
StripThroughtsClientHttpHandler
private sealed class StripThoughtsClientHttpHandler : HttpClientHandler
{
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request,
CancellationToken cancellationToken)
{
var response = await base.SendAsync(request, cancellationToken);
if (response is { IsSuccessStatusCode: true })
{
string originalContent = await response.Content.ReadAsStringAsync(cancellationToken);
if (!string.IsNullOrEmpty(originalContent) && originalContent.Contains("\"thought\""))
{
try
{
// Parse the JSON
using var jsonDoc = System.Text.Json.JsonDocument.Parse(originalContent);
var root = jsonDoc.RootElement;
// Check if we have the expected structure
if (root.TryGetProperty("candidates", out var candidates))
{
// Create a new JSON document with thoughts removed
var options = new System.Text.Json.JsonWriterOptions { Indented = false };
using var memoryStream = new MemoryStream();
using (var writer = new System.Text.Json.Utf8JsonWriter(memoryStream, options))
{
writer.WriteStartObject();
// Copy all root properties
foreach (var property in root.EnumerateObject())
{
if (property.Name == "candidates")
{
writer.WritePropertyName("candidates");
writer.WriteStartArray();
// Process each candidate
foreach (var candidate in property.Value.EnumerateArray())
{
writer.WriteStartObject();
// Copy all candidate properties
foreach (var candidateProperty in candidate.EnumerateObject())
{
if (candidateProperty.Name == "content")
{
writer.WritePropertyName("content");
writer.WriteStartObject();
// Copy all content properties
foreach (var contentProperty in candidateProperty.Value.EnumerateObject())
{
if (contentProperty.Name == "parts")
{
writer.WritePropertyName("parts");
writer.WriteStartArray();
// Filter out parts with "thought": true
foreach (var part in contentProperty.Value.EnumerateArray())
{
bool isThought = part.TryGetProperty("thoughtSignature", out var thoughtValue) &&
!string.IsNullOrWhiteSpace(thoughtValue.GetString());
// Only include non-thought parts
if (!isThought)
{
part.WriteTo(writer);
}
}
writer.WriteEndArray();
}
else
{
// Copy all other content properties as-is
writer.WritePropertyName(contentProperty.Name);
contentProperty.Value.WriteTo(writer);
}
}
writer.WriteEndObject();
}
else
{
// Copy all other candidate properties as-is
writer.WritePropertyName(candidateProperty.Name);
candidateProperty.Value.WriteTo(writer);
}
}
writer.WriteEndObject();
}
writer.WriteEndArray();
}
else
{
// Copy all other root properties as-is
writer.WritePropertyName(property.Name);
property.Value.WriteTo(writer);
}
}
writer.WriteEndObject();
}
// Create a new response with the modified content
var modifiedContent = Encoding.UTF8.GetString(memoryStream.ToArray());
var modifiedResponse = new HttpResponseMessage(response.StatusCode)
{
Content = new StringContent(modifiedContent, Encoding.UTF8, "application/json"),
RequestMessage = response.RequestMessage,
Version = response.Version
};
// Copy headers from original response
foreach (var header in response.Headers)
{
modifiedResponse.Headers.TryAddWithoutValidation(header.Key, header.Value);
}
return modifiedResponse;
}
}
catch (System.Text.Json.JsonException)
{
// If JSON parsing fails, return the original response
}
}
}
// Return the original response if any condition is not met
return response;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment