Fixed attached files silently reaching the AI as empty documents (#904)

This commit is contained in:
Thorsten Sommer authored and GitHub committed 2026-08-10 16:37:44 +02:00
1 parent b9ec13edcf
commit 8f8f788896
31 files changed
+1730 -285

No files matched your search

@@ -17,6 +17,19 @@ public sealed partial class RustService : BackgroundService
private static string TB(string fallbackEN) => I18N.I.T(fallbackEN, typeof(RustService).Namespace, nameof(RustService));
private readonly HttpClient http;
/// <summary>
/// A dedicated client for file extraction.
/// </summary>
/// <remarks>
/// Extraction needs its own client because <see cref="HttpClient.Timeout"/> is a client-wide
/// setting which also covers reading the streamed response body. A per-request cancellation
/// token can only shorten that limit, never extend it. Reading a large file from a slow
/// network share legitimately exceeds the default limit, so this client has no timeout of its
/// own and the extraction bounds each request itself.
/// </remarks>
private readonly HttpClient extractionHttp;
private readonly SemaphoreSlim fileDialogLock = new(1, 1);
private readonly SemaphoreSlim userLanguageLock = new(1, 1);
private readonly SemaphoreSlim userNameLock = new(1, 1);
@@ -42,26 +55,37 @@ public sealed partial class RustService : BackgroundService
{
this.apiPort = apiPort;
this.certificateFingerprint = certificateFingerprint;
// The default timeout of HttpClient, kept explicit so the difference to the
// extraction client below is visible:
this.http = CreateHttpClient(apiPort, certificateFingerprint, TimeSpan.FromSeconds(100));
this.extractionHttp = CreateHttpClient(apiPort, certificateFingerprint, Timeout.InfiniteTimeSpan);
}
private static HttpClient CreateHttpClient(string apiPort, string certificateFingerprint, TimeSpan timeout)
{
var certificateValidationHandler = new HttpClientHandler
{
ServerCertificateCustomValidationCallback = (_, certificate, _, _) =>
{
if(certificate is null)
return false;
var currentCertificateFingerprint = certificate.GetCertHashString(HashAlgorithmName.SHA256);
return currentCertificateFingerprint == certificateFingerprint;
},
};
this.http = new HttpClient(certificateValidationHandler)
var client = new HttpClient(certificateValidationHandler)
{
BaseAddress = new Uri($"https://127.0.0.1:{apiPort}"),
DefaultRequestVersion = Version.Parse("2.0"),
DefaultVersionPolicy = HttpVersionPolicy.RequestVersionOrHigher,
Timeout = timeout,
};
this.http.DefaultRequestHeaders.AddApiToken();
client.DefaultRequestHeaders.AddApiToken();
return client;
}
public void SetLogger(ILogger<RustService> logService)
@@ -93,6 +117,7 @@ public sealed partial class RustService : BackgroundService
public override void Dispose()
{
this.http.Dispose();
this.extractionHttp.Dispose();
this.userLanguageLock.Dispose();
this.userNameLock.Dispose();
base.Dispose();