diff --git a/src/libs/Inworld/Generated/Inworld.AutoSDKHttpResponse.g.cs b/src/libs/Inworld/Generated/Inworld.AutoSDKHttpResponse.g.cs new file mode 100644 index 0000000..3b3cc66 --- /dev/null +++ b/src/libs/Inworld/Generated/Inworld.AutoSDKHttpResponse.g.cs @@ -0,0 +1,121 @@ + +#nullable enable + +namespace Inworld +{ + /// + /// Represents a successful HTTP response with status code and headers. + /// + public partial class AutoSDKHttpResponse + { + /// + /// Initializes a new instance of the class. + /// + public AutoSDKHttpResponse( + global::System.Net.HttpStatusCode statusCode, + global::System.Collections.Generic.Dictionary> headers) + : this( + statusCode: statusCode, + headers: headers, + requestUri: null) + { + } + + /// + /// Initializes a new instance of the class. + /// + public AutoSDKHttpResponse( + global::System.Net.HttpStatusCode statusCode, + global::System.Collections.Generic.Dictionary> headers, + global::System.Uri? requestUri) + { + StatusCode = statusCode; + Headers = headers ?? throw new global::System.ArgumentNullException(nameof(headers)); + RequestUri = requestUri; + } + + /// + /// Gets the HTTP status code. + /// + public global::System.Net.HttpStatusCode StatusCode { get; } + /// + /// Gets the response headers. + /// + public global::System.Collections.Generic.Dictionary> Headers { get; } + /// + /// Gets the final request URI associated with the response. + /// + public global::System.Uri? RequestUri { get; } + + internal static global::System.Collections.Generic.Dictionary> CreateHeaders( + global::System.Net.Http.HttpResponseMessage response) + { + response = response ?? throw new global::System.ArgumentNullException(nameof(response)); + + var headers = global::System.Linq.Enumerable.ToDictionary( + response.Headers, + static header => header.Key, + static header => (global::System.Collections.Generic.IEnumerable)global::System.Linq.Enumerable.ToArray(header.Value), + global::System.StringComparer.OrdinalIgnoreCase); + + if (response.Content?.Headers == null) + { + return headers; + } + + foreach (var header in response.Content.Headers) + { + if (headers.TryGetValue(header.Key, out var existingValues)) + { + headers[header.Key] = global::System.Linq.Enumerable.ToArray( + global::System.Linq.Enumerable.Concat(existingValues, header.Value)); + } + else + { + headers[header.Key] = global::System.Linq.Enumerable.ToArray(header.Value); + } + } + + return headers; + } + } + + /// + /// Represents a successful HTTP response with status code, headers, and body. + /// + public partial class AutoSDKHttpResponse : AutoSDKHttpResponse + { + /// + /// Initializes a new instance of the class. + /// + public AutoSDKHttpResponse( + global::System.Net.HttpStatusCode statusCode, + global::System.Collections.Generic.Dictionary> headers, + T body) + : this( + statusCode: statusCode, + headers: headers, + requestUri: null, + body: body) + { + } + + /// + /// Initializes a new instance of the class. + /// + public AutoSDKHttpResponse( + global::System.Net.HttpStatusCode statusCode, + global::System.Collections.Generic.Dictionary> headers, + global::System.Uri? requestUri, + T body) + : base(statusCode, headers, requestUri) + { + Body = body; + } + + /// + /// Gets the response body. + /// + public T Body { get; } + } +} \ No newline at end of file diff --git a/src/libs/Inworld/Generated/Inworld.IModelsClient.ListModels.g.cs b/src/libs/Inworld/Generated/Inworld.IModelsClient.ListModels.g.cs index f62d3c4..5df8a51 100644 --- a/src/libs/Inworld/Generated/Inworld.IModelsClient.ListModels.g.cs +++ b/src/libs/Inworld/Generated/Inworld.IModelsClient.ListModels.g.cs @@ -15,5 +15,16 @@ public partial interface IModelsClient global::System.Threading.Tasks.Task ListModelsAsync( global::Inworld.AutoSDKRequestOptions? requestOptions = default, global::System.Threading.CancellationToken cancellationToken = default); + /// + /// List available LLM models
+ /// List all LLM models supported by the Inworld LLM Router, including
+ /// provider, pricing, modalities, capabilities, and context length. + ///
+ /// Per-request overrides such as headers, query parameters, timeout, retries, and response buffering. + /// The token to cancel the operation with + /// + global::System.Threading.Tasks.Task> ListModelsAsResponseAsync( + global::Inworld.AutoSDKRequestOptions? requestOptions = default, + global::System.Threading.CancellationToken cancellationToken = default); } } \ No newline at end of file diff --git a/src/libs/Inworld/Generated/Inworld.ISpeechToTextClient.TranscribeAudio.g.cs b/src/libs/Inworld/Generated/Inworld.ISpeechToTextClient.TranscribeAudio.g.cs index fd7fdf0..eab4cd7 100644 --- a/src/libs/Inworld/Generated/Inworld.ISpeechToTextClient.TranscribeAudio.g.cs +++ b/src/libs/Inworld/Generated/Inworld.ISpeechToTextClient.TranscribeAudio.g.cs @@ -21,6 +21,19 @@ public partial interface ISpeechToTextClient /// Transcribe audio
/// Transcribe a complete audio file using the configured STT model. /// + /// + /// Per-request overrides such as headers, query parameters, timeout, retries, and response buffering. + /// The token to cancel the operation with + /// + global::System.Threading.Tasks.Task> TranscribeAudioAsResponseAsync( + + global::Inworld.TranscribeRequest request, + global::Inworld.AutoSDKRequestOptions? requestOptions = default, + global::System.Threading.CancellationToken cancellationToken = default); + /// + /// Transcribe audio
+ /// Transcribe a complete audio file using the configured STT model. + ///
/// /// Configuration for STT transcription. /// diff --git a/src/libs/Inworld/Generated/Inworld.ITextToSpeechClient.SynthesizeSpeech.g.cs b/src/libs/Inworld/Generated/Inworld.ITextToSpeechClient.SynthesizeSpeech.g.cs index f4bd3bc..e436a58 100644 --- a/src/libs/Inworld/Generated/Inworld.ITextToSpeechClient.SynthesizeSpeech.g.cs +++ b/src/libs/Inworld/Generated/Inworld.ITextToSpeechClient.SynthesizeSpeech.g.cs @@ -25,6 +25,21 @@ public partial interface ITextToSpeechClient /// Returns the full audio payload once generation completes. Maximum
/// input is 2,000 characters; maximum output is 16 MB. /// + /// + /// Per-request overrides such as headers, query parameters, timeout, retries, and response buffering. + /// The token to cancel the operation with + /// + global::System.Threading.Tasks.Task> SynthesizeSpeechAsResponseAsync( + + global::Inworld.SynthesizeSpeechRequest request, + global::Inworld.AutoSDKRequestOptions? requestOptions = default, + global::System.Threading.CancellationToken cancellationToken = default); + /// + /// Synthesize speech
+ /// Synthesize speech from text using the specified voice and model.
+ /// Returns the full audio payload once generation completes. Maximum
+ /// input is 2,000 characters; maximum output is 16 MB. + ///
/// /// The text to synthesize. Maximum 2,000 characters. /// diff --git a/src/libs/Inworld/Generated/Inworld.IVoicesClient.CloneVoice.g.cs b/src/libs/Inworld/Generated/Inworld.IVoicesClient.CloneVoice.g.cs index 04f0895..843731e 100644 --- a/src/libs/Inworld/Generated/Inworld.IVoicesClient.CloneVoice.g.cs +++ b/src/libs/Inworld/Generated/Inworld.IVoicesClient.CloneVoice.g.cs @@ -23,6 +23,20 @@ public partial interface IVoicesClient /// Create an Instant Voice Clone (IVC) from one or more short audio
/// samples. The returned voice can be used in TTS synthesis. /// + /// + /// Per-request overrides such as headers, query parameters, timeout, retries, and response buffering. + /// The token to cancel the operation with + /// + global::System.Threading.Tasks.Task> CloneVoiceAsResponseAsync( + + global::Inworld.CloneVoiceRequest request, + global::Inworld.AutoSDKRequestOptions? requestOptions = default, + global::System.Threading.CancellationToken cancellationToken = default); + /// + /// Clone voice
+ /// Create an Instant Voice Clone (IVC) from one or more short audio
+ /// samples. The returned voice can be used in TTS synthesis. + ///
/// /// /// BCP-47-like language code used by Inworld voice APIs. diff --git a/src/libs/Inworld/Generated/Inworld.IVoicesClient.DeleteVoice.g.cs b/src/libs/Inworld/Generated/Inworld.IVoicesClient.DeleteVoice.g.cs index c1bf671..9962f84 100644 --- a/src/libs/Inworld/Generated/Inworld.IVoicesClient.DeleteVoice.g.cs +++ b/src/libs/Inworld/Generated/Inworld.IVoicesClient.DeleteVoice.g.cs @@ -15,5 +15,16 @@ public partial interface IVoicesClient string voiceId, global::Inworld.AutoSDKRequestOptions? requestOptions = default, global::System.Threading.CancellationToken cancellationToken = default); + /// + /// Delete voice + /// + /// + /// Per-request overrides such as headers, query parameters, timeout, retries, and response buffering. + /// The token to cancel the operation with + /// + global::System.Threading.Tasks.Task> DeleteVoiceAsResponseAsync( + string voiceId, + global::Inworld.AutoSDKRequestOptions? requestOptions = default, + global::System.Threading.CancellationToken cancellationToken = default); } } \ No newline at end of file diff --git a/src/libs/Inworld/Generated/Inworld.IVoicesClient.DesignVoice.g.cs b/src/libs/Inworld/Generated/Inworld.IVoicesClient.DesignVoice.g.cs index f16d694..bdd75b9 100644 --- a/src/libs/Inworld/Generated/Inworld.IVoicesClient.DesignVoice.g.cs +++ b/src/libs/Inworld/Generated/Inworld.IVoicesClient.DesignVoice.g.cs @@ -23,6 +23,20 @@ public partial interface IVoicesClient /// Generate candidate voice previews from a text description. Previews
/// can be promoted to a persistent voice via Publish Voice. /// + /// + /// Per-request overrides such as headers, query parameters, timeout, retries, and response buffering. + /// The token to cancel the operation with + /// + global::System.Threading.Tasks.Task> DesignVoiceAsResponseAsync( + + global::Inworld.DesignVoiceRequest request, + global::Inworld.AutoSDKRequestOptions? requestOptions = default, + global::System.Threading.CancellationToken cancellationToken = default); + /// + /// Design voice
+ /// Generate candidate voice previews from a text description. Previews
+ /// can be promoted to a persistent voice via Publish Voice. + ///
/// /// BCP-47-like language code used by Inworld voice APIs. /// diff --git a/src/libs/Inworld/Generated/Inworld.IVoicesClient.GetVoice.g.cs b/src/libs/Inworld/Generated/Inworld.IVoicesClient.GetVoice.g.cs index b18ede1..27fb64b 100644 --- a/src/libs/Inworld/Generated/Inworld.IVoicesClient.GetVoice.g.cs +++ b/src/libs/Inworld/Generated/Inworld.IVoicesClient.GetVoice.g.cs @@ -15,5 +15,16 @@ public partial interface IVoicesClient string voiceId, global::Inworld.AutoSDKRequestOptions? requestOptions = default, global::System.Threading.CancellationToken cancellationToken = default); + /// + /// Get voice + /// + /// + /// Per-request overrides such as headers, query parameters, timeout, retries, and response buffering. + /// The token to cancel the operation with + /// + global::System.Threading.Tasks.Task> GetVoiceAsResponseAsync( + string voiceId, + global::Inworld.AutoSDKRequestOptions? requestOptions = default, + global::System.Threading.CancellationToken cancellationToken = default); } } \ No newline at end of file diff --git a/src/libs/Inworld/Generated/Inworld.IVoicesClient.ListVoices.g.cs b/src/libs/Inworld/Generated/Inworld.IVoicesClient.ListVoices.g.cs index 7a845ce..87e3aa2 100644 --- a/src/libs/Inworld/Generated/Inworld.IVoicesClient.ListVoices.g.cs +++ b/src/libs/Inworld/Generated/Inworld.IVoicesClient.ListVoices.g.cs @@ -16,5 +16,17 @@ public partial interface IVoicesClient global::System.Collections.Generic.IList? languages = default, global::Inworld.AutoSDKRequestOptions? requestOptions = default, global::System.Threading.CancellationToken cancellationToken = default); + /// + /// List voices
+ /// List voices available to the authenticated workspace, optionally filtered by language. + ///
+ /// + /// Per-request overrides such as headers, query parameters, timeout, retries, and response buffering. + /// The token to cancel the operation with + /// + global::System.Threading.Tasks.Task> ListVoicesAsResponseAsync( + global::System.Collections.Generic.IList? languages = default, + global::Inworld.AutoSDKRequestOptions? requestOptions = default, + global::System.Threading.CancellationToken cancellationToken = default); } } \ No newline at end of file diff --git a/src/libs/Inworld/Generated/Inworld.IVoicesClient.PublishVoice.g.cs b/src/libs/Inworld/Generated/Inworld.IVoicesClient.PublishVoice.g.cs index 36e3b17..92a5a13 100644 --- a/src/libs/Inworld/Generated/Inworld.IVoicesClient.PublishVoice.g.cs +++ b/src/libs/Inworld/Generated/Inworld.IVoicesClient.PublishVoice.g.cs @@ -24,6 +24,21 @@ public partial interface IVoicesClient /// Promote a drafted Design Voice preview into a persistent voice. /// /// + /// + /// Per-request overrides such as headers, query parameters, timeout, retries, and response buffering. + /// The token to cancel the operation with + /// + global::System.Threading.Tasks.Task> PublishVoiceAsResponseAsync( + string voiceId, + + global::Inworld.PublishVoiceRequest request, + global::Inworld.AutoSDKRequestOptions? requestOptions = default, + global::System.Threading.CancellationToken cancellationToken = default); + /// + /// Publish voice
+ /// Promote a drafted Design Voice preview into a persistent voice. + ///
+ /// /// /// /// diff --git a/src/libs/Inworld/Generated/Inworld.IVoicesClient.UpdateVoice.g.cs b/src/libs/Inworld/Generated/Inworld.IVoicesClient.UpdateVoice.g.cs index a2d24e3..549b02a 100644 --- a/src/libs/Inworld/Generated/Inworld.IVoicesClient.UpdateVoice.g.cs +++ b/src/libs/Inworld/Generated/Inworld.IVoicesClient.UpdateVoice.g.cs @@ -24,6 +24,21 @@ public partial interface IVoicesClient /// Update editable voice metadata (display name, description, tags). /// /// + /// + /// Per-request overrides such as headers, query parameters, timeout, retries, and response buffering. + /// The token to cancel the operation with + /// + global::System.Threading.Tasks.Task> UpdateVoiceAsResponseAsync( + string voiceId, + + global::Inworld.UpdateVoiceRequest request, + global::Inworld.AutoSDKRequestOptions? requestOptions = default, + global::System.Threading.CancellationToken cancellationToken = default); + /// + /// Update voice
+ /// Update editable voice metadata (display name, description, tags). + ///
+ /// /// /// /// diff --git a/src/libs/Inworld/Generated/Inworld.InworldClient.g.cs b/src/libs/Inworld/Generated/Inworld.InworldClient.g.cs index bf2348d..b2705b9 100644 --- a/src/libs/Inworld/Generated/Inworld.InworldClient.g.cs +++ b/src/libs/Inworld/Generated/Inworld.InworldClient.g.cs @@ -56,7 +56,7 @@ public sealed partial class InworldClient : global::Inworld.IInworldClient, glob /// /// Discover available LLM models. /// - public ModelsClient Models => new ModelsClient(HttpClient, authorizations: Authorizations, options: Options) + public ModelsClient Models => new ModelsClient(HttpClient, baseUri: null, authorizations: Authorizations, options: Options) { ReadResponseAsString = ReadResponseAsString, JsonSerializerContext = JsonSerializerContext, @@ -65,7 +65,7 @@ public sealed partial class InworldClient : global::Inworld.IInworldClient, glob /// /// Transcribe speech to text. /// - public SpeechToTextClient SpeechToText => new SpeechToTextClient(HttpClient, authorizations: Authorizations, options: Options) + public SpeechToTextClient SpeechToText => new SpeechToTextClient(HttpClient, baseUri: null, authorizations: Authorizations, options: Options) { ReadResponseAsString = ReadResponseAsString, JsonSerializerContext = JsonSerializerContext, @@ -74,7 +74,7 @@ public sealed partial class InworldClient : global::Inworld.IInworldClient, glob /// /// Synthesize speech from text. /// - public TextToSpeechClient TextToSpeech => new TextToSpeechClient(HttpClient, authorizations: Authorizations, options: Options) + public TextToSpeechClient TextToSpeech => new TextToSpeechClient(HttpClient, baseUri: null, authorizations: Authorizations, options: Options) { ReadResponseAsString = ReadResponseAsString, JsonSerializerContext = JsonSerializerContext, @@ -83,7 +83,7 @@ public sealed partial class InworldClient : global::Inworld.IInworldClient, glob /// /// Manage voices — list, get, clone, design, publish, update, delete. /// - public VoicesClient Voices => new VoicesClient(HttpClient, authorizations: Authorizations, options: Options) + public VoicesClient Voices => new VoicesClient(HttpClient, baseUri: null, authorizations: Authorizations, options: Options) { ReadResponseAsString = ReadResponseAsString, JsonSerializerContext = JsonSerializerContext, @@ -122,10 +122,10 @@ public InworldClient( /// Client-wide request defaults such as headers, query parameters, retries, and timeout. /// Dispose the HttpClient when the instance is disposed. True by default. public InworldClient( - global::System.Net.Http.HttpClient? httpClient = null, - global::System.Uri? baseUri = null, - global::System.Collections.Generic.List? authorizations = null, - global::Inworld.AutoSDKClientOptions? options = null, + global::System.Net.Http.HttpClient? httpClient, + global::System.Uri? baseUri, + global::System.Collections.Generic.List? authorizations, + global::Inworld.AutoSDKClientOptions? options, bool disposeHttpClient = true) { diff --git a/src/libs/Inworld/Generated/Inworld.ModelsClient.ListModels.g.cs b/src/libs/Inworld/Generated/Inworld.ModelsClient.ListModels.g.cs index 5577074..edfa5c7 100644 --- a/src/libs/Inworld/Generated/Inworld.ModelsClient.ListModels.g.cs +++ b/src/libs/Inworld/Generated/Inworld.ModelsClient.ListModels.g.cs @@ -50,6 +50,25 @@ partial void ProcessListModelsResponseContent( public async global::System.Threading.Tasks.Task ListModelsAsync( global::Inworld.AutoSDKRequestOptions? requestOptions = default, global::System.Threading.CancellationToken cancellationToken = default) + { + var __response = await ListModelsAsResponseAsync( + requestOptions: requestOptions, + cancellationToken: cancellationToken + ).ConfigureAwait(false); + + return __response.Body; + } + /// + /// List available LLM models
+ /// List all LLM models supported by the Inworld LLM Router, including
+ /// provider, pricing, modalities, capabilities, and context length. + ///
+ /// Per-request overrides such as headers, query parameters, timeout, retries, and response buffering. + /// The token to cancel the operation with + /// + public async global::System.Threading.Tasks.Task> ListModelsAsResponseAsync( + global::Inworld.AutoSDKRequestOptions? requestOptions = default, + global::System.Threading.CancellationToken cancellationToken = default) { PrepareArguments( client: HttpClient); @@ -78,6 +97,7 @@ partial void ProcessListModelsResponseContent( global::System.Net.Http.HttpRequestMessage __CreateHttpRequest() { + var __pathBuilder = new global::Inworld.PathBuilder( path: "/llm/v1alpha/models", baseUri: HttpClient.BaseAddress); @@ -150,6 +170,8 @@ partial void ProcessListModelsResponseContent( attempt: __attempt, maxAttempts: __maxAttempts, willRetry: false, + retryDelay: null, + retryReason: global::System.String.Empty, cancellationToken: __effectiveCancellationToken)).ConfigureAwait(false); try { @@ -160,6 +182,11 @@ partial void ProcessListModelsResponseContent( } catch (global::System.Net.Http.HttpRequestException __exception) { + var __retryDelay = global::Inworld.AutoSDKRequestOptionsSupport.GetRetryDelay( + clientOptions: Options, + requestOptions: requestOptions, + response: null, + attempt: __attempt); var __willRetry = __attempt < __maxAttempts && !__effectiveCancellationToken.IsCancellationRequested; await global::Inworld.AutoSDKRequestOptionsSupport.OnAfterErrorAsync( clientOptions: Options, @@ -177,6 +204,8 @@ partial void ProcessListModelsResponseContent( attempt: __attempt, maxAttempts: __maxAttempts, willRetry: __willRetry, + retryDelay: __willRetry ? __retryDelay : (global::System.TimeSpan?)null, + retryReason: "exception", cancellationToken: __effectiveCancellationToken)).ConfigureAwait(false); if (!__willRetry) { @@ -186,8 +215,7 @@ partial void ProcessListModelsResponseContent( __httpRequest.Dispose(); __httpRequest = null; await global::Inworld.AutoSDKRequestOptionsSupport.DelayBeforeRetryAsync( - clientOptions: Options, - requestOptions: requestOptions, + retryDelay: __retryDelay, cancellationToken: __effectiveCancellationToken).ConfigureAwait(false); continue; } @@ -196,6 +224,11 @@ partial void ProcessListModelsResponseContent( __attempt < __maxAttempts && global::Inworld.AutoSDKRequestOptionsSupport.ShouldRetryStatusCode(__response.StatusCode)) { + var __retryDelay = global::Inworld.AutoSDKRequestOptionsSupport.GetRetryDelay( + clientOptions: Options, + requestOptions: requestOptions, + response: __response, + attempt: __attempt); await global::Inworld.AutoSDKRequestOptionsSupport.OnAfterErrorAsync( clientOptions: Options, context: global::Inworld.AutoSDKRequestOptionsSupport.CreateHookContext( @@ -212,14 +245,15 @@ partial void ProcessListModelsResponseContent( attempt: __attempt, maxAttempts: __maxAttempts, willRetry: true, + retryDelay: __retryDelay, + retryReason: "status:" + ((int)__response.StatusCode).ToString(global::System.Globalization.CultureInfo.InvariantCulture), cancellationToken: __effectiveCancellationToken)).ConfigureAwait(false); __response.Dispose(); __response = null; __httpRequest.Dispose(); __httpRequest = null; await global::Inworld.AutoSDKRequestOptionsSupport.DelayBeforeRetryAsync( - clientOptions: Options, - requestOptions: requestOptions, + retryDelay: __retryDelay, cancellationToken: __effectiveCancellationToken).ConfigureAwait(false); continue; } @@ -259,6 +293,8 @@ partial void ProcessListModelsResponseContent( attempt: __attemptNumber, maxAttempts: __maxAttempts, willRetry: false, + retryDelay: null, + retryReason: global::System.String.Empty, cancellationToken: __effectiveCancellationToken)).ConfigureAwait(false); } else @@ -279,6 +315,8 @@ partial void ProcessListModelsResponseContent( attempt: __attemptNumber, maxAttempts: __maxAttempts, willRetry: false, + retryDelay: null, + retryReason: global::System.String.Empty, cancellationToken: __effectiveCancellationToken)).ConfigureAwait(false); } // Error response. @@ -341,9 +379,13 @@ partial void ProcessListModelsResponseContent( { __response.EnsureSuccessStatusCode(); - return - global::Inworld.ListModelsResponse.FromJson(__content, JsonSerializerContext) ?? + var __value = global::Inworld.ListModelsResponse.FromJson(__content, JsonSerializerContext) ?? throw new global::System.InvalidOperationException($"Response deserialization failed for \"{__content}\" "); + return new global::Inworld.AutoSDKHttpResponse( + statusCode: __response.StatusCode, + headers: global::Inworld.AutoSDKHttpResponse.CreateHeaders(__response), + requestUri: __response.RequestMessage?.RequestUri, + body: __value); } catch (global::System.Exception __ex) { @@ -371,9 +413,13 @@ partial void ProcessListModelsResponseContent( #endif ).ConfigureAwait(false); - return - await global::Inworld.ListModelsResponse.FromJsonStreamAsync(__content, JsonSerializerContext).ConfigureAwait(false) ?? + var __value = await global::Inworld.ListModelsResponse.FromJsonStreamAsync(__content, JsonSerializerContext).ConfigureAwait(false) ?? throw new global::System.InvalidOperationException("Response deserialization failed."); + return new global::Inworld.AutoSDKHttpResponse( + statusCode: __response.StatusCode, + headers: global::Inworld.AutoSDKHttpResponse.CreateHeaders(__response), + requestUri: __response.RequestMessage?.RequestUri, + body: __value); } catch (global::System.Exception __ex) { diff --git a/src/libs/Inworld/Generated/Inworld.ModelsClient.g.cs b/src/libs/Inworld/Generated/Inworld.ModelsClient.g.cs index 1530451..7feb715 100644 --- a/src/libs/Inworld/Generated/Inworld.ModelsClient.g.cs +++ b/src/libs/Inworld/Generated/Inworld.ModelsClient.g.cs @@ -73,10 +73,10 @@ public ModelsClient( /// Client-wide request defaults such as headers, query parameters, retries, and timeout. /// Dispose the HttpClient when the instance is disposed. True by default. public ModelsClient( - global::System.Net.Http.HttpClient? httpClient = null, - global::System.Uri? baseUri = null, - global::System.Collections.Generic.List? authorizations = null, - global::Inworld.AutoSDKClientOptions? options = null, + global::System.Net.Http.HttpClient? httpClient, + global::System.Uri? baseUri, + global::System.Collections.Generic.List? authorizations, + global::Inworld.AutoSDKClientOptions? options, bool disposeHttpClient = true) { diff --git a/src/libs/Inworld/Generated/Inworld.OptionsSupport.g.cs b/src/libs/Inworld/Generated/Inworld.OptionsSupport.g.cs index 4f1351d..84329bd 100644 --- a/src/libs/Inworld/Generated/Inworld.OptionsSupport.g.cs +++ b/src/libs/Inworld/Generated/Inworld.OptionsSupport.g.cs @@ -101,9 +101,45 @@ public sealed class AutoSDKRetryOptions public int MaxAttempts { get; set; } = 1; /// - /// Optional fixed delay between retry attempts. + /// Optional fixed delay between retry attempts. When set, this takes precedence over exponential backoff. /// public global::System.TimeSpan? Delay { get; set; } + + /// + /// Initial exponential backoff delay used when is not set. + /// + public global::System.TimeSpan InitialDelay { get; set; } = global::System.TimeSpan.FromSeconds(1); + + /// + /// Maximum retry delay after applying retry headers, backoff, and jitter. + /// + public global::System.TimeSpan MaxDelay { get; set; } = global::System.TimeSpan.FromSeconds(30); + + /// + /// Multiplier applied to exponential backoff after each failed attempt. + /// Values below 1 are normalized to 1. + /// + public double BackoffMultiplier { get; set; } = 2D; + + /// + /// Randomizes computed backoff by plus or minus this ratio. Values are clamped to 0..1. + /// + public double JitterRatio { get; set; } = 0.2D; + + /// + /// Whether Retry-After response headers should control retry delay when present. + /// + public bool UseRetryAfterHeader { get; set; } = true; + + /// + /// Whether a rate-limit reset response header should control retry delay when present. + /// + public bool UseRateLimitResetHeader { get; set; } + + /// + /// Optional provider-specific rate-limit reset header name. Values may be Unix seconds or an HTTP date. + /// + public string? RateLimitResetHeaderName { get; set; } = "X-RateLimit-Reset"; } @@ -231,6 +267,16 @@ public sealed class AutoSDKHookContext /// public bool WillRetry { get; set; } + /// + /// The computed retry delay when is true. + /// + public global::System.TimeSpan? RetryDelay { get; set; } + + /// + /// A short retry reason such as exception or status:429. + /// + public string RetryReason { get; set; } = string.Empty; + /// /// The effective cancellation token for the current request attempt. /// @@ -254,6 +300,8 @@ internal static class AutoSDKRequestOptionsSupport int attempt, int maxAttempts, bool willRetry, + global::System.TimeSpan? retryDelay, + string retryReason, global::System.Threading.CancellationToken cancellationToken) { return new global::Inworld.AutoSDKHookContext @@ -271,6 +319,8 @@ internal static class AutoSDKRequestOptionsSupport Attempt = attempt, MaxAttempts = maxAttempts, WillRetry = willRetry, + RetryDelay = retryDelay, + RetryReason = retryReason ?? string.Empty, CancellationToken = cancellationToken, }; } @@ -338,19 +388,188 @@ internal static int GetMaxAttempts( return maxAttempts < 1 ? 1 : maxAttempts; } - internal static async global::System.Threading.Tasks.Task DelayBeforeRetryAsync( + internal static global::System.TimeSpan GetRetryDelay( global::Inworld.AutoSDKClientOptions clientOptions, global::Inworld.AutoSDKRequestOptions? requestOptions, + global::System.Net.Http.HttpResponseMessage? response, + int attempt) + { + var retryOptions = requestOptions?.Retry ?? clientOptions.Retry ?? new global::Inworld.AutoSDKRetryOptions(); + + if (retryOptions.UseRetryAfterHeader && + TryGetRetryAfterDelay(response, out var retryAfterDelay)) + { + return ClampRetryDelay(retryAfterDelay, retryOptions); + } + + if (retryOptions.UseRateLimitResetHeader && + TryGetRateLimitResetDelay(response, retryOptions.RateLimitResetHeaderName, out var rateLimitResetDelay)) + { + return ClampRetryDelay(rateLimitResetDelay, retryOptions); + } + + if (retryOptions.Delay.HasValue) + { + return ClampRetryDelay(retryOptions.Delay.Value, retryOptions); + } + + var initialDelay = retryOptions.InitialDelay; + if (initialDelay <= global::System.TimeSpan.Zero) + { + return global::System.TimeSpan.Zero; + } + + var multiplier = retryOptions.BackoffMultiplier < 1D ? 1D : retryOptions.BackoffMultiplier; + var exponent = attempt <= 1 ? 0 : attempt - 1; + var delayMilliseconds = initialDelay.TotalMilliseconds * global::System.Math.Pow(multiplier, exponent); + if (double.IsNaN(delayMilliseconds) || double.IsInfinity(delayMilliseconds) || delayMilliseconds < 0D) + { + delayMilliseconds = 0D; + } + + var delay = global::System.TimeSpan.FromMilliseconds(delayMilliseconds); + delay = ApplyJitter(delay, retryOptions.JitterRatio); + return ClampRetryDelay(delay, retryOptions); + } + + internal static async global::System.Threading.Tasks.Task DelayBeforeRetryAsync( + global::System.TimeSpan retryDelay, global::System.Threading.CancellationToken cancellationToken) { - var delay = requestOptions?.Retry?.Delay ?? - clientOptions.Retry?.Delay; - if (!delay.HasValue || delay.Value <= global::System.TimeSpan.Zero) + if (retryDelay <= global::System.TimeSpan.Zero) { return; } - await global::System.Threading.Tasks.Task.Delay(delay.Value, cancellationToken).ConfigureAwait(false); + await global::System.Threading.Tasks.Task.Delay(retryDelay, cancellationToken).ConfigureAwait(false); + } + + private static bool TryGetRetryAfterDelay( + global::System.Net.Http.HttpResponseMessage? response, + out global::System.TimeSpan delay) + { + delay = global::System.TimeSpan.Zero; + var retryAfter = response?.Headers.RetryAfter; + if (retryAfter == null) + { + return false; + } + + if (retryAfter.Delta.HasValue) + { + delay = retryAfter.Delta.Value; + return delay > global::System.TimeSpan.Zero; + } + + if (retryAfter.Date.HasValue) + { + delay = retryAfter.Date.Value - global::System.DateTimeOffset.UtcNow; + return delay > global::System.TimeSpan.Zero; + } + + return false; + } + + private static bool TryGetRateLimitResetDelay( + global::System.Net.Http.HttpResponseMessage? response, + string? headerName, + out global::System.TimeSpan delay) + { + delay = global::System.TimeSpan.Zero; + if (response == null || string.IsNullOrWhiteSpace(headerName)) + { + return false; + } + + if (!response.Headers.TryGetValues(headerName, out var values) && + (response.Content?.Headers == null || !response.Content.Headers.TryGetValues(headerName, out values))) + { + return false; + } + + var value = global::System.Linq.Enumerable.FirstOrDefault(values); + if (string.IsNullOrWhiteSpace(value)) + { + return false; + } + + value = value.Trim(); + if (long.TryParse( + value, + global::System.Globalization.NumberStyles.Integer, + global::System.Globalization.CultureInfo.InvariantCulture, + out var unixSeconds)) + { + delay = global::System.DateTimeOffset.FromUnixTimeSeconds(unixSeconds) - global::System.DateTimeOffset.UtcNow; + return delay > global::System.TimeSpan.Zero; + } + + if (global::System.DateTimeOffset.TryParse( + value, + global::System.Globalization.CultureInfo.InvariantCulture, + global::System.Globalization.DateTimeStyles.AssumeUniversal | global::System.Globalization.DateTimeStyles.AdjustToUniversal, + out var resetAt)) + { + delay = resetAt - global::System.DateTimeOffset.UtcNow; + return delay > global::System.TimeSpan.Zero; + } + + return false; + } + + private static global::System.TimeSpan ApplyJitter( + global::System.TimeSpan delay, + double jitterRatio) + { + if (delay <= global::System.TimeSpan.Zero || jitterRatio <= 0D) + { + return delay; + } + + if (jitterRatio > 1D) + { + jitterRatio = 1D; + } + + var sample = NextJitterSample(); + var multiplier = 1D - jitterRatio + (sample * jitterRatio * 2D); + var milliseconds = delay.TotalMilliseconds * multiplier; + if (double.IsNaN(milliseconds) || double.IsInfinity(milliseconds) || milliseconds < 0D) + { + milliseconds = 0D; + } + + return global::System.TimeSpan.FromMilliseconds(milliseconds); + } + + private static double NextJitterSample() + { + var bytes = new byte[8]; + using (var randomNumberGenerator = global::System.Security.Cryptography.RandomNumberGenerator.Create()) + { + randomNumberGenerator.GetBytes(bytes); + } + + var value = global::System.BitConverter.ToUInt64(bytes, 0); + return value / (double)ulong.MaxValue; + } + + private static global::System.TimeSpan ClampRetryDelay( + global::System.TimeSpan delay, + global::Inworld.AutoSDKRetryOptions retryOptions) + { + if (delay <= global::System.TimeSpan.Zero) + { + return global::System.TimeSpan.Zero; + } + + var maxDelay = retryOptions.MaxDelay; + if (maxDelay > global::System.TimeSpan.Zero && delay > maxDelay) + { + return maxDelay; + } + + return delay; } internal static bool ShouldRetryStatusCode( diff --git a/src/libs/Inworld/Generated/Inworld.Realtime.InworldSpeechToTextStreamRealtimeClient.ReceiveUpdates.g.cs b/src/libs/Inworld/Generated/Inworld.Realtime.InworldSpeechToTextStreamRealtimeClient.ReceiveUpdates.g.cs index a4b99d6..8d7d22d 100644 --- a/src/libs/Inworld/Generated/Inworld.Realtime.InworldSpeechToTextStreamRealtimeClient.ReceiveUpdates.g.cs +++ b/src/libs/Inworld/Generated/Inworld.Realtime.InworldSpeechToTextStreamRealtimeClient.ReceiveUpdates.g.cs @@ -41,8 +41,14 @@ public sealed partial class InworldSpeechToTextStreamRealtimeClient } catch (global::System.Net.WebSockets.WebSocketException exception) { + RaiseException(exception); var rethrow = false; OnReceiveException(exception, ref rethrow); + if (await TryReconnectAsync(exception, cancellationToken).ConfigureAwait(false)) + { + continue; + } + if (rethrow) { throw; @@ -52,6 +58,11 @@ public sealed partial class InworldSpeechToTextStreamRealtimeClient } catch (global::System.OperationCanceledException exception) { + if (!cancellationToken.IsCancellationRequested) + { + RaiseException(exception); + } + var rethrow = false; OnReceiveException(exception, ref rethrow); if (rethrow) @@ -64,6 +75,7 @@ public sealed partial class InworldSpeechToTextStreamRealtimeClient if (result.MessageType == global::System.Net.WebSockets.WebSocketMessageType.Close) { + RaiseClosed(result.CloseStatus, result.CloseStatusDescription); await _clientWebSocket.CloseAsync( closeStatus: global::System.Net.WebSockets.WebSocketCloseStatus.NormalClosure, statusDescription: "Closing", @@ -93,10 +105,96 @@ await _clientWebSocket.CloseAsync( } string json = global::System.Text.Encoding.UTF8.GetString(__messageBuffer.ToArray()); - var @event = (global::Inworld.Realtime.SpeechToTextStreamServerEvent)global::System.Text.Json.JsonSerializer.Deserialize(json, typeof(global::Inworld.Realtime.SpeechToTextStreamServerEvent), JsonSerializerContext)!; + global::Inworld.Realtime.SpeechToTextStreamServerEvent @event; + try + { + @event = (global::Inworld.Realtime.SpeechToTextStreamServerEvent)global::System.Text.Json.JsonSerializer.Deserialize(json, typeof(global::Inworld.Realtime.SpeechToTextStreamServerEvent), JsonSerializerContext)!; + } + catch (global::System.Exception exception) when ( + exception is global::System.Text.Json.JsonException || + exception is global::System.NotSupportedException || + exception is global::System.InvalidOperationException) + { + var rethrow = false; + OnReceiveException(exception, ref rethrow); + DispatchUnknownMessage(json); + if (rethrow) + { + throw; + } + + continue; + } + DispatchReceivedMessage(@event, json); yield return @event; } } + + + private static global::System.Text.Json.JsonElement? TryParseMessageJson( + string rawText) + { + try + { + using var document = global::System.Text.Json.JsonDocument.Parse(rawText); + return document.RootElement.Clone(); + } + catch (global::System.Text.Json.JsonException) + { + return null; + } + } + + private void DispatchUnknownMessage( + string rawText) + { + UnknownMessage?.Invoke( + this, + new AutoSDKWebSocketUnknownMessageEventArgs( + rawText, + TryParseMessageJson(rawText))); + } + + private void DispatchReceivedMessage( + global::Inworld.Realtime.SpeechToTextStreamServerEvent @event, + string rawText) + { + var json = TryParseMessageJson(rawText); + MessageReceived?.Invoke( + this, + new AutoSDKWebSocketMessageEventArgs( + @event, + rawText, + json)); + + if (@event.SttTranscription is { } __SttTranscriptionReceived) + { + SttTranscriptionReceived?.Invoke( + this, + new AutoSDKWebSocketMessageEventArgs( + __SttTranscriptionReceived, + rawText, + json)); + } + if (@event.SttUsage is { } __SttUsageReceived) + { + SttUsageReceived?.Invoke( + this, + new AutoSDKWebSocketMessageEventArgs( + __SttUsageReceived, + rawText, + json)); + } + if (@event.SttSpeechStarted is { } __SttSpeechStartedReceived) + { + SttSpeechStartedReceived?.Invoke( + this, + new AutoSDKWebSocketMessageEventArgs( + __SttSpeechStartedReceived, + rawText, + json)); + } + } } } \ No newline at end of file diff --git a/src/libs/Inworld/Generated/Inworld.Realtime.InworldSpeechToTextStreamRealtimeClient.g.cs b/src/libs/Inworld/Generated/Inworld.Realtime.InworldSpeechToTextStreamRealtimeClient.g.cs index fa5431c..aa45487 100644 --- a/src/libs/Inworld/Generated/Inworld.Realtime.InworldSpeechToTextStreamRealtimeClient.g.cs +++ b/src/libs/Inworld/Generated/Inworld.Realtime.InworldSpeechToTextStreamRealtimeClient.g.cs @@ -13,7 +13,269 @@ public sealed partial class InworldSpeechToTextStreamRealtimeClient : global::Sy /// public const string DefaultBaseUrl = "wss://api.inworld.ai/stt/v1/transcribe:streamBidirectional"; - private readonly global::System.Net.WebSockets.ClientWebSocket _clientWebSocket; + private global::System.Net.WebSockets.ClientWebSocket _clientWebSocket; + private global::System.Uri? _lastConnectUri; + private global::System.Collections.Generic.Dictionary? _lastAdditionalHeaders; + private global::System.Collections.Generic.List? _lastAdditionalSubProtocols; + private global::System.TimeSpan? _lastKeepAliveInterval; + private global::System.TimeSpan? _lastConnectTimeout; + + + /// + /// Current WebSocket connection status. + /// + public enum AutoSDKWebSocketConnectionStatus + { + /// + /// The client is not connected. + /// + Disconnected, + + /// + /// The client is connecting. + /// + Connecting, + + /// + /// The client is connected. + /// + Connected, + + /// + /// The client observed a normal close. + /// + Closed, + + /// + /// The client observed a connection error. + /// + Faulted, + } + + /// + /// Configures automatic reconnect attempts after receive-loop WebSocket failures. + /// + public sealed class AutoSDKWebSocketReconnectOptions + { + /// + /// Enables reconnect attempts from the receive loop. + /// + public bool Enabled { get; set; } + + /// + /// Maximum reconnect attempts per observed receive failure. + /// + public int MaxAttempts { get; set; } = 3; + + /// + /// Delay before the first reconnect attempt. + /// + public global::System.TimeSpan InitialDelay { get; set; } = global::System.TimeSpan.FromSeconds(1); + + /// + /// Maximum delay between reconnect attempts. + /// + public global::System.TimeSpan MaxDelay { get; set; } = global::System.TimeSpan.FromSeconds(30); + + /// + /// Multiplier applied to the delay after each failed reconnect attempt. + /// + public double BackoffMultiplier { get; set; } = 2D; + } + + /// + /// Event data for closed WebSocket connections. + /// + public sealed class AutoSDKWebSocketClosedEventArgs : global::System.EventArgs + { + /// + /// Initializes a new instance of the class. + /// + public AutoSDKWebSocketClosedEventArgs( + global::System.Net.WebSockets.WebSocketCloseStatus? closeStatus, + string? closeStatusDescription) + { + CloseStatus = closeStatus; + CloseStatusDescription = closeStatusDescription; + } + + /// + /// Gets the WebSocket close status. + /// + public global::System.Net.WebSockets.WebSocketCloseStatus? CloseStatus { get; } + + /// + /// Gets the WebSocket close status description. + /// + public string? CloseStatusDescription { get; } + } + + /// + /// Event data for WebSocket exceptions. + /// + public sealed class AutoSDKWebSocketExceptionEventArgs : global::System.EventArgs + { + /// + /// Initializes a new instance of the class. + /// + public AutoSDKWebSocketExceptionEventArgs( + global::System.Exception exception) + { + Exception = exception ?? throw new global::System.ArgumentNullException(nameof(exception)); + } + + /// + /// Gets the observed exception. + /// + public global::System.Exception Exception { get; } + } + + /// + /// Event data for WebSocket reconnect attempts. + /// + public sealed class AutoSDKWebSocketReconnectEventArgs : global::System.EventArgs + { + /// + /// Initializes a new instance of the class. + /// + public AutoSDKWebSocketReconnectEventArgs( + int attempt, + global::System.TimeSpan delay, + global::System.Exception exception) + { + Attempt = attempt; + Delay = delay; + Exception = exception ?? throw new global::System.ArgumentNullException(nameof(exception)); + } + + /// + /// Gets the reconnect attempt number. + /// + public int Attempt { get; } + + /// + /// Gets the delay before the reconnect attempt. + /// + public global::System.TimeSpan Delay { get; } + + /// + /// Gets the exception that triggered reconnect. + /// + public global::System.Exception Exception { get; } + } + + /// + /// Event data for deserialized WebSocket messages. + /// + public sealed class AutoSDKWebSocketMessageEventArgs : global::System.EventArgs + { + /// + /// Initializes a new instance of the class. + /// + public AutoSDKWebSocketMessageEventArgs( + TMessage message, + string rawText, + global::System.Text.Json.JsonElement? json) + { + Message = message; + RawText = rawText ?? string.Empty; + Json = json; + } + + /// + /// Gets the deserialized message. + /// + public TMessage Message { get; } + + /// + /// Gets the raw text received from the WebSocket. + /// + public string RawText { get; } + + /// + /// Gets the parsed JSON payload when available. + /// + public global::System.Text.Json.JsonElement? Json { get; } + } + + /// + /// Event data for messages that could not be deserialized into a known receive type. + /// + public sealed class AutoSDKWebSocketUnknownMessageEventArgs : global::System.EventArgs + { + /// + /// Initializes a new instance of the class. + /// + public AutoSDKWebSocketUnknownMessageEventArgs( + string rawText, + global::System.Text.Json.JsonElement? json) + { + RawText = rawText ?? string.Empty; + Json = json; + } + + /// + /// Gets the raw text received from the WebSocket. + /// + public string RawText { get; } + + /// + /// Gets the parsed JSON payload when available. + /// + public global::System.Text.Json.JsonElement? Json { get; } + } + + /// + /// Gets the current WebSocket connection status. + /// + public AutoSDKWebSocketConnectionStatus Status { get; private set; } = AutoSDKWebSocketConnectionStatus.Disconnected; + + /// + /// Gets reconnect options used by the receive loop. + /// + public AutoSDKWebSocketReconnectOptions ReconnectOptions { get; } = new AutoSDKWebSocketReconnectOptions(); + + /// + /// Raised after the WebSocket connection is opened. + /// + public event global::System.EventHandler? Connected; + + /// + /// Raised after the WebSocket connection is closed. + /// + public event global::System.EventHandler? Closed; + + /// + /// Raised after a WebSocket connection exception is observed. + /// + public event global::System.EventHandler? ExceptionOccurred; + + /// + /// Raised before a reconnect attempt starts. + /// + public event global::System.EventHandler? Reconnecting; + + /// + /// Raised when an inbound text message cannot be deserialized into a known receive event. + /// + public event global::System.EventHandler? UnknownMessage; + + /// + /// Raised after a text message is deserialized into the receive event type. + /// + public event global::System.EventHandler>? MessageReceived; + /// + /// Raised after a SttTranscription message is deserialized. + /// + public event global::System.EventHandler>? SttTranscriptionReceived; + /// + /// Raised after a SttUsage message is deserialized. + /// + public event global::System.EventHandler>? SttUsageReceived; + /// + /// Raised after a SttSpeechStarted message is deserialized. + /// + public event global::System.EventHandler>? SttSpeechStartedReceived; /// /// @@ -91,6 +353,142 @@ private void ApplyStoredAuthorization( _clientWebSocket.Options.SetRequestHeader(_storedAuthorizationHeaderName, __authorizationValue); } } + private void RememberConnectionOptions( + global::System.Uri uri, + global::System.Collections.Generic.IDictionary? additionalHeaders, + global::System.Collections.Generic.IEnumerable? additionalSubProtocols, + global::System.TimeSpan? keepAliveInterval, + global::System.TimeSpan? connectTimeout) + { + _lastConnectUri = uri; + _lastAdditionalHeaders = additionalHeaders is null + ? null + : new global::System.Collections.Generic.Dictionary( + additionalHeaders, + global::System.StringComparer.OrdinalIgnoreCase); + _lastAdditionalSubProtocols = additionalSubProtocols is null + ? null + : new global::System.Collections.Generic.List(additionalSubProtocols); + _lastKeepAliveInterval = keepAliveInterval; + _lastConnectTimeout = connectTimeout; + } + + private void ResetClientWebSocket() + { + _clientWebSocket.Dispose(); + _clientWebSocket = new global::System.Net.WebSockets.ClientWebSocket(); + Initialized(_clientWebSocket); + } + + private void RaiseClosed( + global::System.Net.WebSockets.WebSocketCloseStatus? closeStatus, + string? closeStatusDescription) + { + Status = AutoSDKWebSocketConnectionStatus.Closed; + Closed?.Invoke( + this, + new AutoSDKWebSocketClosedEventArgs(closeStatus, closeStatusDescription)); + } + + private void RaiseException( + global::System.Exception exception) + { + Status = AutoSDKWebSocketConnectionStatus.Faulted; + ExceptionOccurred?.Invoke( + this, + new AutoSDKWebSocketExceptionEventArgs(exception)); + } + + private global::System.TimeSpan GetReconnectDelay( + int attempt) + { + var delay = ReconnectOptions.InitialDelay; + if (delay < global::System.TimeSpan.Zero) + { + delay = global::System.TimeSpan.Zero; + } + + var multiplier = ReconnectOptions.BackoffMultiplier; + if (multiplier < 1D) + { + multiplier = 1D; + } + + for (var index = 1; index < attempt; index++) + { + var nextMilliseconds = delay.TotalMilliseconds * multiplier; + if (nextMilliseconds >= ReconnectOptions.MaxDelay.TotalMilliseconds) + { + delay = ReconnectOptions.MaxDelay; + break; + } + + delay = global::System.TimeSpan.FromMilliseconds(nextMilliseconds); + } + + if (ReconnectOptions.MaxDelay >= global::System.TimeSpan.Zero && + delay > ReconnectOptions.MaxDelay) + { + delay = ReconnectOptions.MaxDelay; + } + + return delay; + } + + private async global::System.Threading.Tasks.Task TryReconnectAsync( + global::System.Exception exception, + global::System.Threading.CancellationToken cancellationToken) + { + if (!ReconnectOptions.Enabled || + _lastConnectUri is null || + cancellationToken.IsCancellationRequested) + { + return false; + } + + var maxAttempts = ReconnectOptions.MaxAttempts < 1 ? 1 : ReconnectOptions.MaxAttempts; + var lastException = exception; + for (var attempt = 1; attempt <= maxAttempts; attempt++) + { + var delay = GetReconnectDelay(attempt); + Reconnecting?.Invoke( + this, + new AutoSDKWebSocketReconnectEventArgs(attempt, delay, lastException)); + + if (delay > global::System.TimeSpan.Zero) + { + await global::System.Threading.Tasks.Task.Delay(delay, cancellationToken).ConfigureAwait(false); + } + + try + { + ResetClientWebSocket(); + await ConnectAsync( + uri: _lastConnectUri, + additionalHeaders: _lastAdditionalHeaders, + additionalSubProtocols: _lastAdditionalSubProtocols, + keepAliveInterval: _lastKeepAliveInterval, + connectTimeout: _lastConnectTimeout, + cancellationToken: cancellationToken).ConfigureAwait(false); + return true; + } + catch (global::System.Exception reconnectException) when ( + reconnectException is global::System.Net.WebSockets.WebSocketException || + reconnectException is global::System.Net.Http.HttpRequestException || + reconnectException is global::System.OperationCanceledException) + { + lastException = reconnectException; + RaiseException(reconnectException); + if (cancellationToken.IsCancellationRequested) + { + return false; + } + } + } + + return false; + } + private void ApplyConnectionOptions( global::System.Collections.Generic.IDictionary? additionalHeaders, global::System.Collections.Generic.IEnumerable? additionalSubProtocols, @@ -137,7 +535,18 @@ private void ApplyConnectionOptions( try { + Status = AutoSDKWebSocketConnectionStatus.Connecting; await _clientWebSocket.ConnectAsync(uri, __effectiveCancellationToken).ConfigureAwait(false); + Status = AutoSDKWebSocketConnectionStatus.Connected; + Connected?.Invoke(this, global::System.EventArgs.Empty); + } + catch (global::System.Exception exception) when ( + exception is global::System.Net.WebSockets.WebSocketException || + exception is global::System.Net.Http.HttpRequestException || + exception is global::System.OperationCanceledException) + { + RaiseException(exception); + throw; } finally { @@ -167,6 +576,7 @@ private void ApplyConnectionOptions( __uri = new global::System.Uri(__pathBuilder.ToString()); } + RememberConnectionOptions(__uri, additionalHeaders, additionalSubProtocols, keepAliveInterval, connectTimeout); ApplyConnectionOptions(additionalHeaders, additionalSubProtocols, keepAliveInterval); await ConnectAsyncCore(__uri, connectTimeout, cancellationToken).ConfigureAwait(false); } diff --git a/src/libs/Inworld/Generated/Inworld.Realtime.InworldTextToSpeechStreamRealtimeClient.ReceiveUpdates.g.cs b/src/libs/Inworld/Generated/Inworld.Realtime.InworldTextToSpeechStreamRealtimeClient.ReceiveUpdates.g.cs index 445b13d..c4b5e9a 100644 --- a/src/libs/Inworld/Generated/Inworld.Realtime.InworldTextToSpeechStreamRealtimeClient.ReceiveUpdates.g.cs +++ b/src/libs/Inworld/Generated/Inworld.Realtime.InworldTextToSpeechStreamRealtimeClient.ReceiveUpdates.g.cs @@ -41,8 +41,14 @@ public sealed partial class InworldTextToSpeechStreamRealtimeClient } catch (global::System.Net.WebSockets.WebSocketException exception) { + RaiseException(exception); var rethrow = false; OnReceiveException(exception, ref rethrow); + if (await TryReconnectAsync(exception, cancellationToken).ConfigureAwait(false)) + { + continue; + } + if (rethrow) { throw; @@ -52,6 +58,11 @@ public sealed partial class InworldTextToSpeechStreamRealtimeClient } catch (global::System.OperationCanceledException exception) { + if (!cancellationToken.IsCancellationRequested) + { + RaiseException(exception); + } + var rethrow = false; OnReceiveException(exception, ref rethrow); if (rethrow) @@ -64,6 +75,7 @@ public sealed partial class InworldTextToSpeechStreamRealtimeClient if (result.MessageType == global::System.Net.WebSockets.WebSocketMessageType.Close) { + RaiseClosed(result.CloseStatus, result.CloseStatusDescription); await _clientWebSocket.CloseAsync( closeStatus: global::System.Net.WebSockets.WebSocketCloseStatus.NormalClosure, statusDescription: "Closing", @@ -93,10 +105,105 @@ await _clientWebSocket.CloseAsync( } string json = global::System.Text.Encoding.UTF8.GetString(__messageBuffer.ToArray()); - var @event = (global::Inworld.Realtime.TextToSpeechStreamServerEvent)global::System.Text.Json.JsonSerializer.Deserialize(json, typeof(global::Inworld.Realtime.TextToSpeechStreamServerEvent), JsonSerializerContext)!; + global::Inworld.Realtime.TextToSpeechStreamServerEvent @event; + try + { + @event = (global::Inworld.Realtime.TextToSpeechStreamServerEvent)global::System.Text.Json.JsonSerializer.Deserialize(json, typeof(global::Inworld.Realtime.TextToSpeechStreamServerEvent), JsonSerializerContext)!; + } + catch (global::System.Exception exception) when ( + exception is global::System.Text.Json.JsonException || + exception is global::System.NotSupportedException || + exception is global::System.InvalidOperationException) + { + var rethrow = false; + OnReceiveException(exception, ref rethrow); + DispatchUnknownMessage(json); + if (rethrow) + { + throw; + } + + continue; + } + DispatchReceivedMessage(@event, json); yield return @event; } } + + + private static global::System.Text.Json.JsonElement? TryParseMessageJson( + string rawText) + { + try + { + using var document = global::System.Text.Json.JsonDocument.Parse(rawText); + return document.RootElement.Clone(); + } + catch (global::System.Text.Json.JsonException) + { + return null; + } + } + + private void DispatchUnknownMessage( + string rawText) + { + UnknownMessage?.Invoke( + this, + new AutoSDKWebSocketUnknownMessageEventArgs( + rawText, + TryParseMessageJson(rawText))); + } + + private void DispatchReceivedMessage( + global::Inworld.Realtime.TextToSpeechStreamServerEvent @event, + string rawText) + { + var json = TryParseMessageJson(rawText); + MessageReceived?.Invoke( + this, + new AutoSDKWebSocketMessageEventArgs( + @event, + rawText, + json)); + + if (@event.TtsContextCreated is { } __TtsContextCreatedReceived) + { + TtsContextCreatedReceived?.Invoke( + this, + new AutoSDKWebSocketMessageEventArgs( + __TtsContextCreatedReceived, + rawText, + json)); + } + if (@event.TtsAudioChunk is { } __TtsAudioChunkReceived) + { + TtsAudioChunkReceived?.Invoke( + this, + new AutoSDKWebSocketMessageEventArgs( + __TtsAudioChunkReceived, + rawText, + json)); + } + if (@event.TtsFlushCompleted is { } __TtsFlushCompletedReceived) + { + TtsFlushCompletedReceived?.Invoke( + this, + new AutoSDKWebSocketMessageEventArgs( + __TtsFlushCompletedReceived, + rawText, + json)); + } + if (@event.TtsContextClosed is { } __TtsContextClosedReceived) + { + TtsContextClosedReceived?.Invoke( + this, + new AutoSDKWebSocketMessageEventArgs( + __TtsContextClosedReceived, + rawText, + json)); + } + } } } \ No newline at end of file diff --git a/src/libs/Inworld/Generated/Inworld.Realtime.InworldTextToSpeechStreamRealtimeClient.g.cs b/src/libs/Inworld/Generated/Inworld.Realtime.InworldTextToSpeechStreamRealtimeClient.g.cs index 2176d6b..22887f8 100644 --- a/src/libs/Inworld/Generated/Inworld.Realtime.InworldTextToSpeechStreamRealtimeClient.g.cs +++ b/src/libs/Inworld/Generated/Inworld.Realtime.InworldTextToSpeechStreamRealtimeClient.g.cs @@ -13,7 +13,273 @@ public sealed partial class InworldTextToSpeechStreamRealtimeClient : global::Sy /// public const string DefaultBaseUrl = "wss://api.inworld.ai/tts/v1/voice:streamBidirectional"; - private readonly global::System.Net.WebSockets.ClientWebSocket _clientWebSocket; + private global::System.Net.WebSockets.ClientWebSocket _clientWebSocket; + private global::System.Uri? _lastConnectUri; + private global::System.Collections.Generic.Dictionary? _lastAdditionalHeaders; + private global::System.Collections.Generic.List? _lastAdditionalSubProtocols; + private global::System.TimeSpan? _lastKeepAliveInterval; + private global::System.TimeSpan? _lastConnectTimeout; + + + /// + /// Current WebSocket connection status. + /// + public enum AutoSDKWebSocketConnectionStatus + { + /// + /// The client is not connected. + /// + Disconnected, + + /// + /// The client is connecting. + /// + Connecting, + + /// + /// The client is connected. + /// + Connected, + + /// + /// The client observed a normal close. + /// + Closed, + + /// + /// The client observed a connection error. + /// + Faulted, + } + + /// + /// Configures automatic reconnect attempts after receive-loop WebSocket failures. + /// + public sealed class AutoSDKWebSocketReconnectOptions + { + /// + /// Enables reconnect attempts from the receive loop. + /// + public bool Enabled { get; set; } + + /// + /// Maximum reconnect attempts per observed receive failure. + /// + public int MaxAttempts { get; set; } = 3; + + /// + /// Delay before the first reconnect attempt. + /// + public global::System.TimeSpan InitialDelay { get; set; } = global::System.TimeSpan.FromSeconds(1); + + /// + /// Maximum delay between reconnect attempts. + /// + public global::System.TimeSpan MaxDelay { get; set; } = global::System.TimeSpan.FromSeconds(30); + + /// + /// Multiplier applied to the delay after each failed reconnect attempt. + /// + public double BackoffMultiplier { get; set; } = 2D; + } + + /// + /// Event data for closed WebSocket connections. + /// + public sealed class AutoSDKWebSocketClosedEventArgs : global::System.EventArgs + { + /// + /// Initializes a new instance of the class. + /// + public AutoSDKWebSocketClosedEventArgs( + global::System.Net.WebSockets.WebSocketCloseStatus? closeStatus, + string? closeStatusDescription) + { + CloseStatus = closeStatus; + CloseStatusDescription = closeStatusDescription; + } + + /// + /// Gets the WebSocket close status. + /// + public global::System.Net.WebSockets.WebSocketCloseStatus? CloseStatus { get; } + + /// + /// Gets the WebSocket close status description. + /// + public string? CloseStatusDescription { get; } + } + + /// + /// Event data for WebSocket exceptions. + /// + public sealed class AutoSDKWebSocketExceptionEventArgs : global::System.EventArgs + { + /// + /// Initializes a new instance of the class. + /// + public AutoSDKWebSocketExceptionEventArgs( + global::System.Exception exception) + { + Exception = exception ?? throw new global::System.ArgumentNullException(nameof(exception)); + } + + /// + /// Gets the observed exception. + /// + public global::System.Exception Exception { get; } + } + + /// + /// Event data for WebSocket reconnect attempts. + /// + public sealed class AutoSDKWebSocketReconnectEventArgs : global::System.EventArgs + { + /// + /// Initializes a new instance of the class. + /// + public AutoSDKWebSocketReconnectEventArgs( + int attempt, + global::System.TimeSpan delay, + global::System.Exception exception) + { + Attempt = attempt; + Delay = delay; + Exception = exception ?? throw new global::System.ArgumentNullException(nameof(exception)); + } + + /// + /// Gets the reconnect attempt number. + /// + public int Attempt { get; } + + /// + /// Gets the delay before the reconnect attempt. + /// + public global::System.TimeSpan Delay { get; } + + /// + /// Gets the exception that triggered reconnect. + /// + public global::System.Exception Exception { get; } + } + + /// + /// Event data for deserialized WebSocket messages. + /// + public sealed class AutoSDKWebSocketMessageEventArgs : global::System.EventArgs + { + /// + /// Initializes a new instance of the class. + /// + public AutoSDKWebSocketMessageEventArgs( + TMessage message, + string rawText, + global::System.Text.Json.JsonElement? json) + { + Message = message; + RawText = rawText ?? string.Empty; + Json = json; + } + + /// + /// Gets the deserialized message. + /// + public TMessage Message { get; } + + /// + /// Gets the raw text received from the WebSocket. + /// + public string RawText { get; } + + /// + /// Gets the parsed JSON payload when available. + /// + public global::System.Text.Json.JsonElement? Json { get; } + } + + /// + /// Event data for messages that could not be deserialized into a known receive type. + /// + public sealed class AutoSDKWebSocketUnknownMessageEventArgs : global::System.EventArgs + { + /// + /// Initializes a new instance of the class. + /// + public AutoSDKWebSocketUnknownMessageEventArgs( + string rawText, + global::System.Text.Json.JsonElement? json) + { + RawText = rawText ?? string.Empty; + Json = json; + } + + /// + /// Gets the raw text received from the WebSocket. + /// + public string RawText { get; } + + /// + /// Gets the parsed JSON payload when available. + /// + public global::System.Text.Json.JsonElement? Json { get; } + } + + /// + /// Gets the current WebSocket connection status. + /// + public AutoSDKWebSocketConnectionStatus Status { get; private set; } = AutoSDKWebSocketConnectionStatus.Disconnected; + + /// + /// Gets reconnect options used by the receive loop. + /// + public AutoSDKWebSocketReconnectOptions ReconnectOptions { get; } = new AutoSDKWebSocketReconnectOptions(); + + /// + /// Raised after the WebSocket connection is opened. + /// + public event global::System.EventHandler? Connected; + + /// + /// Raised after the WebSocket connection is closed. + /// + public event global::System.EventHandler? Closed; + + /// + /// Raised after a WebSocket connection exception is observed. + /// + public event global::System.EventHandler? ExceptionOccurred; + + /// + /// Raised before a reconnect attempt starts. + /// + public event global::System.EventHandler? Reconnecting; + + /// + /// Raised when an inbound text message cannot be deserialized into a known receive event. + /// + public event global::System.EventHandler? UnknownMessage; + + /// + /// Raised after a text message is deserialized into the receive event type. + /// + public event global::System.EventHandler>? MessageReceived; + /// + /// Raised after a TtsContextCreated message is deserialized. + /// + public event global::System.EventHandler>? TtsContextCreatedReceived; + /// + /// Raised after a TtsAudioChunk message is deserialized. + /// + public event global::System.EventHandler>? TtsAudioChunkReceived; + /// + /// Raised after a TtsFlushCompleted message is deserialized. + /// + public event global::System.EventHandler>? TtsFlushCompletedReceived; + /// + /// Raised after a TtsContextClosed message is deserialized. + /// + public event global::System.EventHandler>? TtsContextClosedReceived; /// /// @@ -91,6 +357,142 @@ private void ApplyStoredAuthorization( _clientWebSocket.Options.SetRequestHeader(_storedAuthorizationHeaderName, __authorizationValue); } } + private void RememberConnectionOptions( + global::System.Uri uri, + global::System.Collections.Generic.IDictionary? additionalHeaders, + global::System.Collections.Generic.IEnumerable? additionalSubProtocols, + global::System.TimeSpan? keepAliveInterval, + global::System.TimeSpan? connectTimeout) + { + _lastConnectUri = uri; + _lastAdditionalHeaders = additionalHeaders is null + ? null + : new global::System.Collections.Generic.Dictionary( + additionalHeaders, + global::System.StringComparer.OrdinalIgnoreCase); + _lastAdditionalSubProtocols = additionalSubProtocols is null + ? null + : new global::System.Collections.Generic.List(additionalSubProtocols); + _lastKeepAliveInterval = keepAliveInterval; + _lastConnectTimeout = connectTimeout; + } + + private void ResetClientWebSocket() + { + _clientWebSocket.Dispose(); + _clientWebSocket = new global::System.Net.WebSockets.ClientWebSocket(); + Initialized(_clientWebSocket); + } + + private void RaiseClosed( + global::System.Net.WebSockets.WebSocketCloseStatus? closeStatus, + string? closeStatusDescription) + { + Status = AutoSDKWebSocketConnectionStatus.Closed; + Closed?.Invoke( + this, + new AutoSDKWebSocketClosedEventArgs(closeStatus, closeStatusDescription)); + } + + private void RaiseException( + global::System.Exception exception) + { + Status = AutoSDKWebSocketConnectionStatus.Faulted; + ExceptionOccurred?.Invoke( + this, + new AutoSDKWebSocketExceptionEventArgs(exception)); + } + + private global::System.TimeSpan GetReconnectDelay( + int attempt) + { + var delay = ReconnectOptions.InitialDelay; + if (delay < global::System.TimeSpan.Zero) + { + delay = global::System.TimeSpan.Zero; + } + + var multiplier = ReconnectOptions.BackoffMultiplier; + if (multiplier < 1D) + { + multiplier = 1D; + } + + for (var index = 1; index < attempt; index++) + { + var nextMilliseconds = delay.TotalMilliseconds * multiplier; + if (nextMilliseconds >= ReconnectOptions.MaxDelay.TotalMilliseconds) + { + delay = ReconnectOptions.MaxDelay; + break; + } + + delay = global::System.TimeSpan.FromMilliseconds(nextMilliseconds); + } + + if (ReconnectOptions.MaxDelay >= global::System.TimeSpan.Zero && + delay > ReconnectOptions.MaxDelay) + { + delay = ReconnectOptions.MaxDelay; + } + + return delay; + } + + private async global::System.Threading.Tasks.Task TryReconnectAsync( + global::System.Exception exception, + global::System.Threading.CancellationToken cancellationToken) + { + if (!ReconnectOptions.Enabled || + _lastConnectUri is null || + cancellationToken.IsCancellationRequested) + { + return false; + } + + var maxAttempts = ReconnectOptions.MaxAttempts < 1 ? 1 : ReconnectOptions.MaxAttempts; + var lastException = exception; + for (var attempt = 1; attempt <= maxAttempts; attempt++) + { + var delay = GetReconnectDelay(attempt); + Reconnecting?.Invoke( + this, + new AutoSDKWebSocketReconnectEventArgs(attempt, delay, lastException)); + + if (delay > global::System.TimeSpan.Zero) + { + await global::System.Threading.Tasks.Task.Delay(delay, cancellationToken).ConfigureAwait(false); + } + + try + { + ResetClientWebSocket(); + await ConnectAsync( + uri: _lastConnectUri, + additionalHeaders: _lastAdditionalHeaders, + additionalSubProtocols: _lastAdditionalSubProtocols, + keepAliveInterval: _lastKeepAliveInterval, + connectTimeout: _lastConnectTimeout, + cancellationToken: cancellationToken).ConfigureAwait(false); + return true; + } + catch (global::System.Exception reconnectException) when ( + reconnectException is global::System.Net.WebSockets.WebSocketException || + reconnectException is global::System.Net.Http.HttpRequestException || + reconnectException is global::System.OperationCanceledException) + { + lastException = reconnectException; + RaiseException(reconnectException); + if (cancellationToken.IsCancellationRequested) + { + return false; + } + } + } + + return false; + } + private void ApplyConnectionOptions( global::System.Collections.Generic.IDictionary? additionalHeaders, global::System.Collections.Generic.IEnumerable? additionalSubProtocols, @@ -137,7 +539,18 @@ private void ApplyConnectionOptions( try { + Status = AutoSDKWebSocketConnectionStatus.Connecting; await _clientWebSocket.ConnectAsync(uri, __effectiveCancellationToken).ConfigureAwait(false); + Status = AutoSDKWebSocketConnectionStatus.Connected; + Connected?.Invoke(this, global::System.EventArgs.Empty); + } + catch (global::System.Exception exception) when ( + exception is global::System.Net.WebSockets.WebSocketException || + exception is global::System.Net.Http.HttpRequestException || + exception is global::System.OperationCanceledException) + { + RaiseException(exception); + throw; } finally { @@ -167,6 +580,7 @@ private void ApplyConnectionOptions( __uri = new global::System.Uri(__pathBuilder.ToString()); } + RememberConnectionOptions(__uri, additionalHeaders, additionalSubProtocols, keepAliveInterval, connectTimeout); ApplyConnectionOptions(additionalHeaders, additionalSubProtocols, keepAliveInterval); await ConnectAsyncCore(__uri, connectTimeout, cancellationToken).ConfigureAwait(false); } diff --git a/src/libs/Inworld/Generated/Inworld.Realtime.OptionsSupport.g.cs b/src/libs/Inworld/Generated/Inworld.Realtime.OptionsSupport.g.cs index f7adf62..9513e47 100644 --- a/src/libs/Inworld/Generated/Inworld.Realtime.OptionsSupport.g.cs +++ b/src/libs/Inworld/Generated/Inworld.Realtime.OptionsSupport.g.cs @@ -101,9 +101,45 @@ public sealed class AutoSDKRetryOptions public int MaxAttempts { get; set; } = 1; /// - /// Optional fixed delay between retry attempts. + /// Optional fixed delay between retry attempts. When set, this takes precedence over exponential backoff. /// public global::System.TimeSpan? Delay { get; set; } + + /// + /// Initial exponential backoff delay used when is not set. + /// + public global::System.TimeSpan InitialDelay { get; set; } = global::System.TimeSpan.FromSeconds(1); + + /// + /// Maximum retry delay after applying retry headers, backoff, and jitter. + /// + public global::System.TimeSpan MaxDelay { get; set; } = global::System.TimeSpan.FromSeconds(30); + + /// + /// Multiplier applied to exponential backoff after each failed attempt. + /// Values below 1 are normalized to 1. + /// + public double BackoffMultiplier { get; set; } = 2D; + + /// + /// Randomizes computed backoff by plus or minus this ratio. Values are clamped to 0..1. + /// + public double JitterRatio { get; set; } = 0.2D; + + /// + /// Whether Retry-After response headers should control retry delay when present. + /// + public bool UseRetryAfterHeader { get; set; } = true; + + /// + /// Whether a rate-limit reset response header should control retry delay when present. + /// + public bool UseRateLimitResetHeader { get; set; } + + /// + /// Optional provider-specific rate-limit reset header name. Values may be Unix seconds or an HTTP date. + /// + public string? RateLimitResetHeaderName { get; set; } = "X-RateLimit-Reset"; } @@ -231,6 +267,16 @@ public sealed class AutoSDKHookContext /// public bool WillRetry { get; set; } + /// + /// The computed retry delay when is true. + /// + public global::System.TimeSpan? RetryDelay { get; set; } + + /// + /// A short retry reason such as exception or status:429. + /// + public string RetryReason { get; set; } = string.Empty; + /// /// The effective cancellation token for the current request attempt. /// @@ -254,6 +300,8 @@ internal static class AutoSDKRequestOptionsSupport int attempt, int maxAttempts, bool willRetry, + global::System.TimeSpan? retryDelay, + string retryReason, global::System.Threading.CancellationToken cancellationToken) { return new global::Inworld.Realtime.AutoSDKHookContext @@ -271,6 +319,8 @@ internal static class AutoSDKRequestOptionsSupport Attempt = attempt, MaxAttempts = maxAttempts, WillRetry = willRetry, + RetryDelay = retryDelay, + RetryReason = retryReason ?? string.Empty, CancellationToken = cancellationToken, }; } @@ -338,19 +388,188 @@ internal static int GetMaxAttempts( return maxAttempts < 1 ? 1 : maxAttempts; } - internal static async global::System.Threading.Tasks.Task DelayBeforeRetryAsync( + internal static global::System.TimeSpan GetRetryDelay( global::Inworld.Realtime.AutoSDKClientOptions clientOptions, global::Inworld.Realtime.AutoSDKRequestOptions? requestOptions, + global::System.Net.Http.HttpResponseMessage? response, + int attempt) + { + var retryOptions = requestOptions?.Retry ?? clientOptions.Retry ?? new global::Inworld.Realtime.AutoSDKRetryOptions(); + + if (retryOptions.UseRetryAfterHeader && + TryGetRetryAfterDelay(response, out var retryAfterDelay)) + { + return ClampRetryDelay(retryAfterDelay, retryOptions); + } + + if (retryOptions.UseRateLimitResetHeader && + TryGetRateLimitResetDelay(response, retryOptions.RateLimitResetHeaderName, out var rateLimitResetDelay)) + { + return ClampRetryDelay(rateLimitResetDelay, retryOptions); + } + + if (retryOptions.Delay.HasValue) + { + return ClampRetryDelay(retryOptions.Delay.Value, retryOptions); + } + + var initialDelay = retryOptions.InitialDelay; + if (initialDelay <= global::System.TimeSpan.Zero) + { + return global::System.TimeSpan.Zero; + } + + var multiplier = retryOptions.BackoffMultiplier < 1D ? 1D : retryOptions.BackoffMultiplier; + var exponent = attempt <= 1 ? 0 : attempt - 1; + var delayMilliseconds = initialDelay.TotalMilliseconds * global::System.Math.Pow(multiplier, exponent); + if (double.IsNaN(delayMilliseconds) || double.IsInfinity(delayMilliseconds) || delayMilliseconds < 0D) + { + delayMilliseconds = 0D; + } + + var delay = global::System.TimeSpan.FromMilliseconds(delayMilliseconds); + delay = ApplyJitter(delay, retryOptions.JitterRatio); + return ClampRetryDelay(delay, retryOptions); + } + + internal static async global::System.Threading.Tasks.Task DelayBeforeRetryAsync( + global::System.TimeSpan retryDelay, global::System.Threading.CancellationToken cancellationToken) { - var delay = requestOptions?.Retry?.Delay ?? - clientOptions.Retry?.Delay; - if (!delay.HasValue || delay.Value <= global::System.TimeSpan.Zero) + if (retryDelay <= global::System.TimeSpan.Zero) { return; } - await global::System.Threading.Tasks.Task.Delay(delay.Value, cancellationToken).ConfigureAwait(false); + await global::System.Threading.Tasks.Task.Delay(retryDelay, cancellationToken).ConfigureAwait(false); + } + + private static bool TryGetRetryAfterDelay( + global::System.Net.Http.HttpResponseMessage? response, + out global::System.TimeSpan delay) + { + delay = global::System.TimeSpan.Zero; + var retryAfter = response?.Headers.RetryAfter; + if (retryAfter == null) + { + return false; + } + + if (retryAfter.Delta.HasValue) + { + delay = retryAfter.Delta.Value; + return delay > global::System.TimeSpan.Zero; + } + + if (retryAfter.Date.HasValue) + { + delay = retryAfter.Date.Value - global::System.DateTimeOffset.UtcNow; + return delay > global::System.TimeSpan.Zero; + } + + return false; + } + + private static bool TryGetRateLimitResetDelay( + global::System.Net.Http.HttpResponseMessage? response, + string? headerName, + out global::System.TimeSpan delay) + { + delay = global::System.TimeSpan.Zero; + if (response == null || string.IsNullOrWhiteSpace(headerName)) + { + return false; + } + + if (!response.Headers.TryGetValues(headerName, out var values) && + (response.Content?.Headers == null || !response.Content.Headers.TryGetValues(headerName, out values))) + { + return false; + } + + var value = global::System.Linq.Enumerable.FirstOrDefault(values); + if (string.IsNullOrWhiteSpace(value)) + { + return false; + } + + value = value.Trim(); + if (long.TryParse( + value, + global::System.Globalization.NumberStyles.Integer, + global::System.Globalization.CultureInfo.InvariantCulture, + out var unixSeconds)) + { + delay = global::System.DateTimeOffset.FromUnixTimeSeconds(unixSeconds) - global::System.DateTimeOffset.UtcNow; + return delay > global::System.TimeSpan.Zero; + } + + if (global::System.DateTimeOffset.TryParse( + value, + global::System.Globalization.CultureInfo.InvariantCulture, + global::System.Globalization.DateTimeStyles.AssumeUniversal | global::System.Globalization.DateTimeStyles.AdjustToUniversal, + out var resetAt)) + { + delay = resetAt - global::System.DateTimeOffset.UtcNow; + return delay > global::System.TimeSpan.Zero; + } + + return false; + } + + private static global::System.TimeSpan ApplyJitter( + global::System.TimeSpan delay, + double jitterRatio) + { + if (delay <= global::System.TimeSpan.Zero || jitterRatio <= 0D) + { + return delay; + } + + if (jitterRatio > 1D) + { + jitterRatio = 1D; + } + + var sample = NextJitterSample(); + var multiplier = 1D - jitterRatio + (sample * jitterRatio * 2D); + var milliseconds = delay.TotalMilliseconds * multiplier; + if (double.IsNaN(milliseconds) || double.IsInfinity(milliseconds) || milliseconds < 0D) + { + milliseconds = 0D; + } + + return global::System.TimeSpan.FromMilliseconds(milliseconds); + } + + private static double NextJitterSample() + { + var bytes = new byte[8]; + using (var randomNumberGenerator = global::System.Security.Cryptography.RandomNumberGenerator.Create()) + { + randomNumberGenerator.GetBytes(bytes); + } + + var value = global::System.BitConverter.ToUInt64(bytes, 0); + return value / (double)ulong.MaxValue; + } + + private static global::System.TimeSpan ClampRetryDelay( + global::System.TimeSpan delay, + global::Inworld.Realtime.AutoSDKRetryOptions retryOptions) + { + if (delay <= global::System.TimeSpan.Zero) + { + return global::System.TimeSpan.Zero; + } + + var maxDelay = retryOptions.MaxDelay; + if (maxDelay > global::System.TimeSpan.Zero && delay > maxDelay) + { + return maxDelay; + } + + return delay; } internal static bool ShouldRetryStatusCode( diff --git a/src/libs/Inworld/Generated/Inworld.SpeechToTextClient.TranscribeAudio.g.cs b/src/libs/Inworld/Generated/Inworld.SpeechToTextClient.TranscribeAudio.g.cs index fcd5236..f4dfa3d 100644 --- a/src/libs/Inworld/Generated/Inworld.SpeechToTextClient.TranscribeAudio.g.cs +++ b/src/libs/Inworld/Generated/Inworld.SpeechToTextClient.TranscribeAudio.g.cs @@ -51,6 +51,29 @@ partial void ProcessTranscribeAudioResponseContent( /// public async global::System.Threading.Tasks.Task TranscribeAudioAsync( + global::Inworld.TranscribeRequest request, + global::Inworld.AutoSDKRequestOptions? requestOptions = default, + global::System.Threading.CancellationToken cancellationToken = default) + { + var __response = await TranscribeAudioAsResponseAsync( + + request: request, + requestOptions: requestOptions, + cancellationToken: cancellationToken + ).ConfigureAwait(false); + + return __response.Body; + } + /// + /// Transcribe audio
+ /// Transcribe a complete audio file using the configured STT model. + ///
+ /// + /// Per-request overrides such as headers, query parameters, timeout, retries, and response buffering. + /// The token to cancel the operation with + /// + public async global::System.Threading.Tasks.Task> TranscribeAudioAsResponseAsync( + global::Inworld.TranscribeRequest request, global::Inworld.AutoSDKRequestOptions? requestOptions = default, global::System.Threading.CancellationToken cancellationToken = default) @@ -85,6 +108,7 @@ partial void ProcessTranscribeAudioResponseContent( global::System.Net.Http.HttpRequestMessage __CreateHttpRequest() { + var __pathBuilder = new global::Inworld.PathBuilder( path: "/stt/v1/transcribe", baseUri: HttpClient.BaseAddress); @@ -164,6 +188,8 @@ partial void ProcessTranscribeAudioResponseContent( attempt: __attempt, maxAttempts: __maxAttempts, willRetry: false, + retryDelay: null, + retryReason: global::System.String.Empty, cancellationToken: __effectiveCancellationToken)).ConfigureAwait(false); try { @@ -174,6 +200,11 @@ partial void ProcessTranscribeAudioResponseContent( } catch (global::System.Net.Http.HttpRequestException __exception) { + var __retryDelay = global::Inworld.AutoSDKRequestOptionsSupport.GetRetryDelay( + clientOptions: Options, + requestOptions: requestOptions, + response: null, + attempt: __attempt); var __willRetry = __attempt < __maxAttempts && !__effectiveCancellationToken.IsCancellationRequested; await global::Inworld.AutoSDKRequestOptionsSupport.OnAfterErrorAsync( clientOptions: Options, @@ -191,6 +222,8 @@ partial void ProcessTranscribeAudioResponseContent( attempt: __attempt, maxAttempts: __maxAttempts, willRetry: __willRetry, + retryDelay: __willRetry ? __retryDelay : (global::System.TimeSpan?)null, + retryReason: "exception", cancellationToken: __effectiveCancellationToken)).ConfigureAwait(false); if (!__willRetry) { @@ -200,8 +233,7 @@ partial void ProcessTranscribeAudioResponseContent( __httpRequest.Dispose(); __httpRequest = null; await global::Inworld.AutoSDKRequestOptionsSupport.DelayBeforeRetryAsync( - clientOptions: Options, - requestOptions: requestOptions, + retryDelay: __retryDelay, cancellationToken: __effectiveCancellationToken).ConfigureAwait(false); continue; } @@ -210,6 +242,11 @@ partial void ProcessTranscribeAudioResponseContent( __attempt < __maxAttempts && global::Inworld.AutoSDKRequestOptionsSupport.ShouldRetryStatusCode(__response.StatusCode)) { + var __retryDelay = global::Inworld.AutoSDKRequestOptionsSupport.GetRetryDelay( + clientOptions: Options, + requestOptions: requestOptions, + response: __response, + attempt: __attempt); await global::Inworld.AutoSDKRequestOptionsSupport.OnAfterErrorAsync( clientOptions: Options, context: global::Inworld.AutoSDKRequestOptionsSupport.CreateHookContext( @@ -226,14 +263,15 @@ partial void ProcessTranscribeAudioResponseContent( attempt: __attempt, maxAttempts: __maxAttempts, willRetry: true, + retryDelay: __retryDelay, + retryReason: "status:" + ((int)__response.StatusCode).ToString(global::System.Globalization.CultureInfo.InvariantCulture), cancellationToken: __effectiveCancellationToken)).ConfigureAwait(false); __response.Dispose(); __response = null; __httpRequest.Dispose(); __httpRequest = null; await global::Inworld.AutoSDKRequestOptionsSupport.DelayBeforeRetryAsync( - clientOptions: Options, - requestOptions: requestOptions, + retryDelay: __retryDelay, cancellationToken: __effectiveCancellationToken).ConfigureAwait(false); continue; } @@ -273,6 +311,8 @@ partial void ProcessTranscribeAudioResponseContent( attempt: __attemptNumber, maxAttempts: __maxAttempts, willRetry: false, + retryDelay: null, + retryReason: global::System.String.Empty, cancellationToken: __effectiveCancellationToken)).ConfigureAwait(false); } else @@ -293,6 +333,8 @@ partial void ProcessTranscribeAudioResponseContent( attempt: __attemptNumber, maxAttempts: __maxAttempts, willRetry: false, + retryDelay: null, + retryReason: global::System.String.Empty, cancellationToken: __effectiveCancellationToken)).ConfigureAwait(false); } // Error response. @@ -355,9 +397,13 @@ partial void ProcessTranscribeAudioResponseContent( { __response.EnsureSuccessStatusCode(); - return - global::Inworld.TranscribeResponse.FromJson(__content, JsonSerializerContext) ?? + var __value = global::Inworld.TranscribeResponse.FromJson(__content, JsonSerializerContext) ?? throw new global::System.InvalidOperationException($"Response deserialization failed for \"{__content}\" "); + return new global::Inworld.AutoSDKHttpResponse( + statusCode: __response.StatusCode, + headers: global::Inworld.AutoSDKHttpResponse.CreateHeaders(__response), + requestUri: __response.RequestMessage?.RequestUri, + body: __value); } catch (global::System.Exception __ex) { @@ -385,9 +431,13 @@ partial void ProcessTranscribeAudioResponseContent( #endif ).ConfigureAwait(false); - return - await global::Inworld.TranscribeResponse.FromJsonStreamAsync(__content, JsonSerializerContext).ConfigureAwait(false) ?? + var __value = await global::Inworld.TranscribeResponse.FromJsonStreamAsync(__content, JsonSerializerContext).ConfigureAwait(false) ?? throw new global::System.InvalidOperationException("Response deserialization failed."); + return new global::Inworld.AutoSDKHttpResponse( + statusCode: __response.StatusCode, + headers: global::Inworld.AutoSDKHttpResponse.CreateHeaders(__response), + requestUri: __response.RequestMessage?.RequestUri, + body: __value); } catch (global::System.Exception __ex) { diff --git a/src/libs/Inworld/Generated/Inworld.SpeechToTextClient.g.cs b/src/libs/Inworld/Generated/Inworld.SpeechToTextClient.g.cs index 787b3ed..85ee4e8 100644 --- a/src/libs/Inworld/Generated/Inworld.SpeechToTextClient.g.cs +++ b/src/libs/Inworld/Generated/Inworld.SpeechToTextClient.g.cs @@ -73,10 +73,10 @@ public SpeechToTextClient( /// Client-wide request defaults such as headers, query parameters, retries, and timeout. /// Dispose the HttpClient when the instance is disposed. True by default. public SpeechToTextClient( - global::System.Net.Http.HttpClient? httpClient = null, - global::System.Uri? baseUri = null, - global::System.Collections.Generic.List? authorizations = null, - global::Inworld.AutoSDKClientOptions? options = null, + global::System.Net.Http.HttpClient? httpClient, + global::System.Uri? baseUri, + global::System.Collections.Generic.List? authorizations, + global::Inworld.AutoSDKClientOptions? options, bool disposeHttpClient = true) { diff --git a/src/libs/Inworld/Generated/Inworld.TextToSpeechClient.SynthesizeSpeech.g.cs b/src/libs/Inworld/Generated/Inworld.TextToSpeechClient.SynthesizeSpeech.g.cs index aff2154..b1677bc 100644 --- a/src/libs/Inworld/Generated/Inworld.TextToSpeechClient.SynthesizeSpeech.g.cs +++ b/src/libs/Inworld/Generated/Inworld.TextToSpeechClient.SynthesizeSpeech.g.cs @@ -53,6 +53,31 @@ partial void ProcessSynthesizeSpeechResponseContent( /// public async global::System.Threading.Tasks.Task SynthesizeSpeechAsync( + global::Inworld.SynthesizeSpeechRequest request, + global::Inworld.AutoSDKRequestOptions? requestOptions = default, + global::System.Threading.CancellationToken cancellationToken = default) + { + var __response = await SynthesizeSpeechAsResponseAsync( + + request: request, + requestOptions: requestOptions, + cancellationToken: cancellationToken + ).ConfigureAwait(false); + + return __response.Body; + } + /// + /// Synthesize speech
+ /// Synthesize speech from text using the specified voice and model.
+ /// Returns the full audio payload once generation completes. Maximum
+ /// input is 2,000 characters; maximum output is 16 MB. + ///
+ /// + /// Per-request overrides such as headers, query parameters, timeout, retries, and response buffering. + /// The token to cancel the operation with + /// + public async global::System.Threading.Tasks.Task> SynthesizeSpeechAsResponseAsync( + global::Inworld.SynthesizeSpeechRequest request, global::Inworld.AutoSDKRequestOptions? requestOptions = default, global::System.Threading.CancellationToken cancellationToken = default) @@ -87,6 +112,7 @@ partial void ProcessSynthesizeSpeechResponseContent( global::System.Net.Http.HttpRequestMessage __CreateHttpRequest() { + var __pathBuilder = new global::Inworld.PathBuilder( path: "/tts/v1/voice", baseUri: HttpClient.BaseAddress); @@ -166,6 +192,8 @@ partial void ProcessSynthesizeSpeechResponseContent( attempt: __attempt, maxAttempts: __maxAttempts, willRetry: false, + retryDelay: null, + retryReason: global::System.String.Empty, cancellationToken: __effectiveCancellationToken)).ConfigureAwait(false); try { @@ -176,6 +204,11 @@ partial void ProcessSynthesizeSpeechResponseContent( } catch (global::System.Net.Http.HttpRequestException __exception) { + var __retryDelay = global::Inworld.AutoSDKRequestOptionsSupport.GetRetryDelay( + clientOptions: Options, + requestOptions: requestOptions, + response: null, + attempt: __attempt); var __willRetry = __attempt < __maxAttempts && !__effectiveCancellationToken.IsCancellationRequested; await global::Inworld.AutoSDKRequestOptionsSupport.OnAfterErrorAsync( clientOptions: Options, @@ -193,6 +226,8 @@ partial void ProcessSynthesizeSpeechResponseContent( attempt: __attempt, maxAttempts: __maxAttempts, willRetry: __willRetry, + retryDelay: __willRetry ? __retryDelay : (global::System.TimeSpan?)null, + retryReason: "exception", cancellationToken: __effectiveCancellationToken)).ConfigureAwait(false); if (!__willRetry) { @@ -202,8 +237,7 @@ partial void ProcessSynthesizeSpeechResponseContent( __httpRequest.Dispose(); __httpRequest = null; await global::Inworld.AutoSDKRequestOptionsSupport.DelayBeforeRetryAsync( - clientOptions: Options, - requestOptions: requestOptions, + retryDelay: __retryDelay, cancellationToken: __effectiveCancellationToken).ConfigureAwait(false); continue; } @@ -212,6 +246,11 @@ partial void ProcessSynthesizeSpeechResponseContent( __attempt < __maxAttempts && global::Inworld.AutoSDKRequestOptionsSupport.ShouldRetryStatusCode(__response.StatusCode)) { + var __retryDelay = global::Inworld.AutoSDKRequestOptionsSupport.GetRetryDelay( + clientOptions: Options, + requestOptions: requestOptions, + response: __response, + attempt: __attempt); await global::Inworld.AutoSDKRequestOptionsSupport.OnAfterErrorAsync( clientOptions: Options, context: global::Inworld.AutoSDKRequestOptionsSupport.CreateHookContext( @@ -228,14 +267,15 @@ partial void ProcessSynthesizeSpeechResponseContent( attempt: __attempt, maxAttempts: __maxAttempts, willRetry: true, + retryDelay: __retryDelay, + retryReason: "status:" + ((int)__response.StatusCode).ToString(global::System.Globalization.CultureInfo.InvariantCulture), cancellationToken: __effectiveCancellationToken)).ConfigureAwait(false); __response.Dispose(); __response = null; __httpRequest.Dispose(); __httpRequest = null; await global::Inworld.AutoSDKRequestOptionsSupport.DelayBeforeRetryAsync( - clientOptions: Options, - requestOptions: requestOptions, + retryDelay: __retryDelay, cancellationToken: __effectiveCancellationToken).ConfigureAwait(false); continue; } @@ -275,6 +315,8 @@ partial void ProcessSynthesizeSpeechResponseContent( attempt: __attemptNumber, maxAttempts: __maxAttempts, willRetry: false, + retryDelay: null, + retryReason: global::System.String.Empty, cancellationToken: __effectiveCancellationToken)).ConfigureAwait(false); } else @@ -295,6 +337,8 @@ partial void ProcessSynthesizeSpeechResponseContent( attempt: __attemptNumber, maxAttempts: __maxAttempts, willRetry: false, + retryDelay: null, + retryReason: global::System.String.Empty, cancellationToken: __effectiveCancellationToken)).ConfigureAwait(false); } // Error response. @@ -357,9 +401,13 @@ partial void ProcessSynthesizeSpeechResponseContent( { __response.EnsureSuccessStatusCode(); - return - global::Inworld.SynthesizeSpeechResponse.FromJson(__content, JsonSerializerContext) ?? + var __value = global::Inworld.SynthesizeSpeechResponse.FromJson(__content, JsonSerializerContext) ?? throw new global::System.InvalidOperationException($"Response deserialization failed for \"{__content}\" "); + return new global::Inworld.AutoSDKHttpResponse( + statusCode: __response.StatusCode, + headers: global::Inworld.AutoSDKHttpResponse.CreateHeaders(__response), + requestUri: __response.RequestMessage?.RequestUri, + body: __value); } catch (global::System.Exception __ex) { @@ -387,9 +435,13 @@ partial void ProcessSynthesizeSpeechResponseContent( #endif ).ConfigureAwait(false); - return - await global::Inworld.SynthesizeSpeechResponse.FromJsonStreamAsync(__content, JsonSerializerContext).ConfigureAwait(false) ?? + var __value = await global::Inworld.SynthesizeSpeechResponse.FromJsonStreamAsync(__content, JsonSerializerContext).ConfigureAwait(false) ?? throw new global::System.InvalidOperationException("Response deserialization failed."); + return new global::Inworld.AutoSDKHttpResponse( + statusCode: __response.StatusCode, + headers: global::Inworld.AutoSDKHttpResponse.CreateHeaders(__response), + requestUri: __response.RequestMessage?.RequestUri, + body: __value); } catch (global::System.Exception __ex) { diff --git a/src/libs/Inworld/Generated/Inworld.TextToSpeechClient.g.cs b/src/libs/Inworld/Generated/Inworld.TextToSpeechClient.g.cs index 425f56d..1e65979 100644 --- a/src/libs/Inworld/Generated/Inworld.TextToSpeechClient.g.cs +++ b/src/libs/Inworld/Generated/Inworld.TextToSpeechClient.g.cs @@ -73,10 +73,10 @@ public TextToSpeechClient( /// Client-wide request defaults such as headers, query parameters, retries, and timeout. /// Dispose the HttpClient when the instance is disposed. True by default. public TextToSpeechClient( - global::System.Net.Http.HttpClient? httpClient = null, - global::System.Uri? baseUri = null, - global::System.Collections.Generic.List? authorizations = null, - global::Inworld.AutoSDKClientOptions? options = null, + global::System.Net.Http.HttpClient? httpClient, + global::System.Uri? baseUri, + global::System.Collections.Generic.List? authorizations, + global::Inworld.AutoSDKClientOptions? options, bool disposeHttpClient = true) { diff --git a/src/libs/Inworld/Generated/Inworld.VoicesClient.CloneVoice.g.cs b/src/libs/Inworld/Generated/Inworld.VoicesClient.CloneVoice.g.cs index 281b6dd..1d685ab 100644 --- a/src/libs/Inworld/Generated/Inworld.VoicesClient.CloneVoice.g.cs +++ b/src/libs/Inworld/Generated/Inworld.VoicesClient.CloneVoice.g.cs @@ -52,6 +52,30 @@ partial void ProcessCloneVoiceResponseContent( /// public async global::System.Threading.Tasks.Task CloneVoiceAsync( + global::Inworld.CloneVoiceRequest request, + global::Inworld.AutoSDKRequestOptions? requestOptions = default, + global::System.Threading.CancellationToken cancellationToken = default) + { + var __response = await CloneVoiceAsResponseAsync( + + request: request, + requestOptions: requestOptions, + cancellationToken: cancellationToken + ).ConfigureAwait(false); + + return __response.Body; + } + /// + /// Clone voice
+ /// Create an Instant Voice Clone (IVC) from one or more short audio
+ /// samples. The returned voice can be used in TTS synthesis. + ///
+ /// + /// Per-request overrides such as headers, query parameters, timeout, retries, and response buffering. + /// The token to cancel the operation with + /// + public async global::System.Threading.Tasks.Task> CloneVoiceAsResponseAsync( + global::Inworld.CloneVoiceRequest request, global::Inworld.AutoSDKRequestOptions? requestOptions = default, global::System.Threading.CancellationToken cancellationToken = default) @@ -86,6 +110,7 @@ partial void ProcessCloneVoiceResponseContent( global::System.Net.Http.HttpRequestMessage __CreateHttpRequest() { + var __pathBuilder = new global::Inworld.PathBuilder( path: "/voices/v1/voices:clone", baseUri: HttpClient.BaseAddress); @@ -165,6 +190,8 @@ partial void ProcessCloneVoiceResponseContent( attempt: __attempt, maxAttempts: __maxAttempts, willRetry: false, + retryDelay: null, + retryReason: global::System.String.Empty, cancellationToken: __effectiveCancellationToken)).ConfigureAwait(false); try { @@ -175,6 +202,11 @@ partial void ProcessCloneVoiceResponseContent( } catch (global::System.Net.Http.HttpRequestException __exception) { + var __retryDelay = global::Inworld.AutoSDKRequestOptionsSupport.GetRetryDelay( + clientOptions: Options, + requestOptions: requestOptions, + response: null, + attempt: __attempt); var __willRetry = __attempt < __maxAttempts && !__effectiveCancellationToken.IsCancellationRequested; await global::Inworld.AutoSDKRequestOptionsSupport.OnAfterErrorAsync( clientOptions: Options, @@ -192,6 +224,8 @@ partial void ProcessCloneVoiceResponseContent( attempt: __attempt, maxAttempts: __maxAttempts, willRetry: __willRetry, + retryDelay: __willRetry ? __retryDelay : (global::System.TimeSpan?)null, + retryReason: "exception", cancellationToken: __effectiveCancellationToken)).ConfigureAwait(false); if (!__willRetry) { @@ -201,8 +235,7 @@ partial void ProcessCloneVoiceResponseContent( __httpRequest.Dispose(); __httpRequest = null; await global::Inworld.AutoSDKRequestOptionsSupport.DelayBeforeRetryAsync( - clientOptions: Options, - requestOptions: requestOptions, + retryDelay: __retryDelay, cancellationToken: __effectiveCancellationToken).ConfigureAwait(false); continue; } @@ -211,6 +244,11 @@ partial void ProcessCloneVoiceResponseContent( __attempt < __maxAttempts && global::Inworld.AutoSDKRequestOptionsSupport.ShouldRetryStatusCode(__response.StatusCode)) { + var __retryDelay = global::Inworld.AutoSDKRequestOptionsSupport.GetRetryDelay( + clientOptions: Options, + requestOptions: requestOptions, + response: __response, + attempt: __attempt); await global::Inworld.AutoSDKRequestOptionsSupport.OnAfterErrorAsync( clientOptions: Options, context: global::Inworld.AutoSDKRequestOptionsSupport.CreateHookContext( @@ -227,14 +265,15 @@ partial void ProcessCloneVoiceResponseContent( attempt: __attempt, maxAttempts: __maxAttempts, willRetry: true, + retryDelay: __retryDelay, + retryReason: "status:" + ((int)__response.StatusCode).ToString(global::System.Globalization.CultureInfo.InvariantCulture), cancellationToken: __effectiveCancellationToken)).ConfigureAwait(false); __response.Dispose(); __response = null; __httpRequest.Dispose(); __httpRequest = null; await global::Inworld.AutoSDKRequestOptionsSupport.DelayBeforeRetryAsync( - clientOptions: Options, - requestOptions: requestOptions, + retryDelay: __retryDelay, cancellationToken: __effectiveCancellationToken).ConfigureAwait(false); continue; } @@ -274,6 +313,8 @@ partial void ProcessCloneVoiceResponseContent( attempt: __attemptNumber, maxAttempts: __maxAttempts, willRetry: false, + retryDelay: null, + retryReason: global::System.String.Empty, cancellationToken: __effectiveCancellationToken)).ConfigureAwait(false); } else @@ -294,6 +335,8 @@ partial void ProcessCloneVoiceResponseContent( attempt: __attemptNumber, maxAttempts: __maxAttempts, willRetry: false, + retryDelay: null, + retryReason: global::System.String.Empty, cancellationToken: __effectiveCancellationToken)).ConfigureAwait(false); } // Error response. @@ -356,9 +399,13 @@ partial void ProcessCloneVoiceResponseContent( { __response.EnsureSuccessStatusCode(); - return - global::Inworld.CloneVoiceResponse.FromJson(__content, JsonSerializerContext) ?? + var __value = global::Inworld.CloneVoiceResponse.FromJson(__content, JsonSerializerContext) ?? throw new global::System.InvalidOperationException($"Response deserialization failed for \"{__content}\" "); + return new global::Inworld.AutoSDKHttpResponse( + statusCode: __response.StatusCode, + headers: global::Inworld.AutoSDKHttpResponse.CreateHeaders(__response), + requestUri: __response.RequestMessage?.RequestUri, + body: __value); } catch (global::System.Exception __ex) { @@ -386,9 +433,13 @@ partial void ProcessCloneVoiceResponseContent( #endif ).ConfigureAwait(false); - return - await global::Inworld.CloneVoiceResponse.FromJsonStreamAsync(__content, JsonSerializerContext).ConfigureAwait(false) ?? + var __value = await global::Inworld.CloneVoiceResponse.FromJsonStreamAsync(__content, JsonSerializerContext).ConfigureAwait(false) ?? throw new global::System.InvalidOperationException("Response deserialization failed."); + return new global::Inworld.AutoSDKHttpResponse( + statusCode: __response.StatusCode, + headers: global::Inworld.AutoSDKHttpResponse.CreateHeaders(__response), + requestUri: __response.RequestMessage?.RequestUri, + body: __value); } catch (global::System.Exception __ex) { diff --git a/src/libs/Inworld/Generated/Inworld.VoicesClient.DeleteVoice.g.cs b/src/libs/Inworld/Generated/Inworld.VoicesClient.DeleteVoice.g.cs index 9d078e6..487b331 100644 --- a/src/libs/Inworld/Generated/Inworld.VoicesClient.DeleteVoice.g.cs +++ b/src/libs/Inworld/Generated/Inworld.VoicesClient.DeleteVoice.g.cs @@ -52,6 +52,26 @@ partial void ProcessDeleteVoiceResponseContent( string voiceId, global::Inworld.AutoSDKRequestOptions? requestOptions = default, global::System.Threading.CancellationToken cancellationToken = default) + { + var __response = await DeleteVoiceAsResponseAsync( + voiceId: voiceId, + requestOptions: requestOptions, + cancellationToken: cancellationToken + ).ConfigureAwait(false); + + return __response.Body; + } + /// + /// Delete voice + /// + /// + /// Per-request overrides such as headers, query parameters, timeout, retries, and response buffering. + /// The token to cancel the operation with + /// + public async global::System.Threading.Tasks.Task> DeleteVoiceAsResponseAsync( + string voiceId, + global::Inworld.AutoSDKRequestOptions? requestOptions = default, + global::System.Threading.CancellationToken cancellationToken = default) { PrepareArguments( client: HttpClient); @@ -81,6 +101,7 @@ partial void ProcessDeleteVoiceResponseContent( global::System.Net.Http.HttpRequestMessage __CreateHttpRequest() { + var __pathBuilder = new global::Inworld.PathBuilder( path: $"/voices/v1/voices/{voiceId}", baseUri: HttpClient.BaseAddress); @@ -154,6 +175,8 @@ partial void ProcessDeleteVoiceResponseContent( attempt: __attempt, maxAttempts: __maxAttempts, willRetry: false, + retryDelay: null, + retryReason: global::System.String.Empty, cancellationToken: __effectiveCancellationToken)).ConfigureAwait(false); try { @@ -164,6 +187,11 @@ partial void ProcessDeleteVoiceResponseContent( } catch (global::System.Net.Http.HttpRequestException __exception) { + var __retryDelay = global::Inworld.AutoSDKRequestOptionsSupport.GetRetryDelay( + clientOptions: Options, + requestOptions: requestOptions, + response: null, + attempt: __attempt); var __willRetry = __attempt < __maxAttempts && !__effectiveCancellationToken.IsCancellationRequested; await global::Inworld.AutoSDKRequestOptionsSupport.OnAfterErrorAsync( clientOptions: Options, @@ -181,6 +209,8 @@ partial void ProcessDeleteVoiceResponseContent( attempt: __attempt, maxAttempts: __maxAttempts, willRetry: __willRetry, + retryDelay: __willRetry ? __retryDelay : (global::System.TimeSpan?)null, + retryReason: "exception", cancellationToken: __effectiveCancellationToken)).ConfigureAwait(false); if (!__willRetry) { @@ -190,8 +220,7 @@ partial void ProcessDeleteVoiceResponseContent( __httpRequest.Dispose(); __httpRequest = null; await global::Inworld.AutoSDKRequestOptionsSupport.DelayBeforeRetryAsync( - clientOptions: Options, - requestOptions: requestOptions, + retryDelay: __retryDelay, cancellationToken: __effectiveCancellationToken).ConfigureAwait(false); continue; } @@ -200,6 +229,11 @@ partial void ProcessDeleteVoiceResponseContent( __attempt < __maxAttempts && global::Inworld.AutoSDKRequestOptionsSupport.ShouldRetryStatusCode(__response.StatusCode)) { + var __retryDelay = global::Inworld.AutoSDKRequestOptionsSupport.GetRetryDelay( + clientOptions: Options, + requestOptions: requestOptions, + response: __response, + attempt: __attempt); await global::Inworld.AutoSDKRequestOptionsSupport.OnAfterErrorAsync( clientOptions: Options, context: global::Inworld.AutoSDKRequestOptionsSupport.CreateHookContext( @@ -216,14 +250,15 @@ partial void ProcessDeleteVoiceResponseContent( attempt: __attempt, maxAttempts: __maxAttempts, willRetry: true, + retryDelay: __retryDelay, + retryReason: "status:" + ((int)__response.StatusCode).ToString(global::System.Globalization.CultureInfo.InvariantCulture), cancellationToken: __effectiveCancellationToken)).ConfigureAwait(false); __response.Dispose(); __response = null; __httpRequest.Dispose(); __httpRequest = null; await global::Inworld.AutoSDKRequestOptionsSupport.DelayBeforeRetryAsync( - clientOptions: Options, - requestOptions: requestOptions, + retryDelay: __retryDelay, cancellationToken: __effectiveCancellationToken).ConfigureAwait(false); continue; } @@ -263,6 +298,8 @@ partial void ProcessDeleteVoiceResponseContent( attempt: __attemptNumber, maxAttempts: __maxAttempts, willRetry: false, + retryDelay: null, + retryReason: global::System.String.Empty, cancellationToken: __effectiveCancellationToken)).ConfigureAwait(false); } else @@ -283,6 +320,8 @@ partial void ProcessDeleteVoiceResponseContent( attempt: __attemptNumber, maxAttempts: __maxAttempts, willRetry: false, + retryDelay: null, + retryReason: global::System.String.Empty, cancellationToken: __effectiveCancellationToken)).ConfigureAwait(false); } // Error response. @@ -345,7 +384,11 @@ partial void ProcessDeleteVoiceResponseContent( { __response.EnsureSuccessStatusCode(); - return __content; + return new global::Inworld.AutoSDKHttpResponse( + statusCode: __response.StatusCode, + headers: global::Inworld.AutoSDKHttpResponse.CreateHeaders(__response), + requestUri: __response.RequestMessage?.RequestUri, + body: __content); } catch (global::System.Exception __ex) { @@ -373,7 +416,11 @@ partial void ProcessDeleteVoiceResponseContent( #endif ).ConfigureAwait(false); - return __content; + return new global::Inworld.AutoSDKHttpResponse( + statusCode: __response.StatusCode, + headers: global::Inworld.AutoSDKHttpResponse.CreateHeaders(__response), + requestUri: __response.RequestMessage?.RequestUri, + body: __content); } catch (global::System.Exception __ex) { diff --git a/src/libs/Inworld/Generated/Inworld.VoicesClient.DesignVoice.g.cs b/src/libs/Inworld/Generated/Inworld.VoicesClient.DesignVoice.g.cs index 1b3178f..bc889f8 100644 --- a/src/libs/Inworld/Generated/Inworld.VoicesClient.DesignVoice.g.cs +++ b/src/libs/Inworld/Generated/Inworld.VoicesClient.DesignVoice.g.cs @@ -52,6 +52,30 @@ partial void ProcessDesignVoiceResponseContent( /// public async global::System.Threading.Tasks.Task DesignVoiceAsync( + global::Inworld.DesignVoiceRequest request, + global::Inworld.AutoSDKRequestOptions? requestOptions = default, + global::System.Threading.CancellationToken cancellationToken = default) + { + var __response = await DesignVoiceAsResponseAsync( + + request: request, + requestOptions: requestOptions, + cancellationToken: cancellationToken + ).ConfigureAwait(false); + + return __response.Body; + } + /// + /// Design voice
+ /// Generate candidate voice previews from a text description. Previews
+ /// can be promoted to a persistent voice via Publish Voice. + ///
+ /// + /// Per-request overrides such as headers, query parameters, timeout, retries, and response buffering. + /// The token to cancel the operation with + /// + public async global::System.Threading.Tasks.Task> DesignVoiceAsResponseAsync( + global::Inworld.DesignVoiceRequest request, global::Inworld.AutoSDKRequestOptions? requestOptions = default, global::System.Threading.CancellationToken cancellationToken = default) @@ -86,6 +110,7 @@ partial void ProcessDesignVoiceResponseContent( global::System.Net.Http.HttpRequestMessage __CreateHttpRequest() { + var __pathBuilder = new global::Inworld.PathBuilder( path: "/voices/v1/voices:design", baseUri: HttpClient.BaseAddress); @@ -165,6 +190,8 @@ partial void ProcessDesignVoiceResponseContent( attempt: __attempt, maxAttempts: __maxAttempts, willRetry: false, + retryDelay: null, + retryReason: global::System.String.Empty, cancellationToken: __effectiveCancellationToken)).ConfigureAwait(false); try { @@ -175,6 +202,11 @@ partial void ProcessDesignVoiceResponseContent( } catch (global::System.Net.Http.HttpRequestException __exception) { + var __retryDelay = global::Inworld.AutoSDKRequestOptionsSupport.GetRetryDelay( + clientOptions: Options, + requestOptions: requestOptions, + response: null, + attempt: __attempt); var __willRetry = __attempt < __maxAttempts && !__effectiveCancellationToken.IsCancellationRequested; await global::Inworld.AutoSDKRequestOptionsSupport.OnAfterErrorAsync( clientOptions: Options, @@ -192,6 +224,8 @@ partial void ProcessDesignVoiceResponseContent( attempt: __attempt, maxAttempts: __maxAttempts, willRetry: __willRetry, + retryDelay: __willRetry ? __retryDelay : (global::System.TimeSpan?)null, + retryReason: "exception", cancellationToken: __effectiveCancellationToken)).ConfigureAwait(false); if (!__willRetry) { @@ -201,8 +235,7 @@ partial void ProcessDesignVoiceResponseContent( __httpRequest.Dispose(); __httpRequest = null; await global::Inworld.AutoSDKRequestOptionsSupport.DelayBeforeRetryAsync( - clientOptions: Options, - requestOptions: requestOptions, + retryDelay: __retryDelay, cancellationToken: __effectiveCancellationToken).ConfigureAwait(false); continue; } @@ -211,6 +244,11 @@ partial void ProcessDesignVoiceResponseContent( __attempt < __maxAttempts && global::Inworld.AutoSDKRequestOptionsSupport.ShouldRetryStatusCode(__response.StatusCode)) { + var __retryDelay = global::Inworld.AutoSDKRequestOptionsSupport.GetRetryDelay( + clientOptions: Options, + requestOptions: requestOptions, + response: __response, + attempt: __attempt); await global::Inworld.AutoSDKRequestOptionsSupport.OnAfterErrorAsync( clientOptions: Options, context: global::Inworld.AutoSDKRequestOptionsSupport.CreateHookContext( @@ -227,14 +265,15 @@ partial void ProcessDesignVoiceResponseContent( attempt: __attempt, maxAttempts: __maxAttempts, willRetry: true, + retryDelay: __retryDelay, + retryReason: "status:" + ((int)__response.StatusCode).ToString(global::System.Globalization.CultureInfo.InvariantCulture), cancellationToken: __effectiveCancellationToken)).ConfigureAwait(false); __response.Dispose(); __response = null; __httpRequest.Dispose(); __httpRequest = null; await global::Inworld.AutoSDKRequestOptionsSupport.DelayBeforeRetryAsync( - clientOptions: Options, - requestOptions: requestOptions, + retryDelay: __retryDelay, cancellationToken: __effectiveCancellationToken).ConfigureAwait(false); continue; } @@ -274,6 +313,8 @@ partial void ProcessDesignVoiceResponseContent( attempt: __attemptNumber, maxAttempts: __maxAttempts, willRetry: false, + retryDelay: null, + retryReason: global::System.String.Empty, cancellationToken: __effectiveCancellationToken)).ConfigureAwait(false); } else @@ -294,6 +335,8 @@ partial void ProcessDesignVoiceResponseContent( attempt: __attemptNumber, maxAttempts: __maxAttempts, willRetry: false, + retryDelay: null, + retryReason: global::System.String.Empty, cancellationToken: __effectiveCancellationToken)).ConfigureAwait(false); } // Error response. @@ -356,9 +399,13 @@ partial void ProcessDesignVoiceResponseContent( { __response.EnsureSuccessStatusCode(); - return - global::Inworld.DesignVoiceResponse.FromJson(__content, JsonSerializerContext) ?? + var __value = global::Inworld.DesignVoiceResponse.FromJson(__content, JsonSerializerContext) ?? throw new global::System.InvalidOperationException($"Response deserialization failed for \"{__content}\" "); + return new global::Inworld.AutoSDKHttpResponse( + statusCode: __response.StatusCode, + headers: global::Inworld.AutoSDKHttpResponse.CreateHeaders(__response), + requestUri: __response.RequestMessage?.RequestUri, + body: __value); } catch (global::System.Exception __ex) { @@ -386,9 +433,13 @@ partial void ProcessDesignVoiceResponseContent( #endif ).ConfigureAwait(false); - return - await global::Inworld.DesignVoiceResponse.FromJsonStreamAsync(__content, JsonSerializerContext).ConfigureAwait(false) ?? + var __value = await global::Inworld.DesignVoiceResponse.FromJsonStreamAsync(__content, JsonSerializerContext).ConfigureAwait(false) ?? throw new global::System.InvalidOperationException("Response deserialization failed."); + return new global::Inworld.AutoSDKHttpResponse( + statusCode: __response.StatusCode, + headers: global::Inworld.AutoSDKHttpResponse.CreateHeaders(__response), + requestUri: __response.RequestMessage?.RequestUri, + body: __value); } catch (global::System.Exception __ex) { diff --git a/src/libs/Inworld/Generated/Inworld.VoicesClient.GetVoice.g.cs b/src/libs/Inworld/Generated/Inworld.VoicesClient.GetVoice.g.cs index d01bae4..9f41b9e 100644 --- a/src/libs/Inworld/Generated/Inworld.VoicesClient.GetVoice.g.cs +++ b/src/libs/Inworld/Generated/Inworld.VoicesClient.GetVoice.g.cs @@ -52,6 +52,26 @@ partial void ProcessGetVoiceResponseContent( string voiceId, global::Inworld.AutoSDKRequestOptions? requestOptions = default, global::System.Threading.CancellationToken cancellationToken = default) + { + var __response = await GetVoiceAsResponseAsync( + voiceId: voiceId, + requestOptions: requestOptions, + cancellationToken: cancellationToken + ).ConfigureAwait(false); + + return __response.Body; + } + /// + /// Get voice + /// + /// + /// Per-request overrides such as headers, query parameters, timeout, retries, and response buffering. + /// The token to cancel the operation with + /// + public async global::System.Threading.Tasks.Task> GetVoiceAsResponseAsync( + string voiceId, + global::Inworld.AutoSDKRequestOptions? requestOptions = default, + global::System.Threading.CancellationToken cancellationToken = default) { PrepareArguments( client: HttpClient); @@ -81,6 +101,7 @@ partial void ProcessGetVoiceResponseContent( global::System.Net.Http.HttpRequestMessage __CreateHttpRequest() { + var __pathBuilder = new global::Inworld.PathBuilder( path: $"/voices/v1/voices/{voiceId}", baseUri: HttpClient.BaseAddress); @@ -154,6 +175,8 @@ partial void ProcessGetVoiceResponseContent( attempt: __attempt, maxAttempts: __maxAttempts, willRetry: false, + retryDelay: null, + retryReason: global::System.String.Empty, cancellationToken: __effectiveCancellationToken)).ConfigureAwait(false); try { @@ -164,6 +187,11 @@ partial void ProcessGetVoiceResponseContent( } catch (global::System.Net.Http.HttpRequestException __exception) { + var __retryDelay = global::Inworld.AutoSDKRequestOptionsSupport.GetRetryDelay( + clientOptions: Options, + requestOptions: requestOptions, + response: null, + attempt: __attempt); var __willRetry = __attempt < __maxAttempts && !__effectiveCancellationToken.IsCancellationRequested; await global::Inworld.AutoSDKRequestOptionsSupport.OnAfterErrorAsync( clientOptions: Options, @@ -181,6 +209,8 @@ partial void ProcessGetVoiceResponseContent( attempt: __attempt, maxAttempts: __maxAttempts, willRetry: __willRetry, + retryDelay: __willRetry ? __retryDelay : (global::System.TimeSpan?)null, + retryReason: "exception", cancellationToken: __effectiveCancellationToken)).ConfigureAwait(false); if (!__willRetry) { @@ -190,8 +220,7 @@ partial void ProcessGetVoiceResponseContent( __httpRequest.Dispose(); __httpRequest = null; await global::Inworld.AutoSDKRequestOptionsSupport.DelayBeforeRetryAsync( - clientOptions: Options, - requestOptions: requestOptions, + retryDelay: __retryDelay, cancellationToken: __effectiveCancellationToken).ConfigureAwait(false); continue; } @@ -200,6 +229,11 @@ partial void ProcessGetVoiceResponseContent( __attempt < __maxAttempts && global::Inworld.AutoSDKRequestOptionsSupport.ShouldRetryStatusCode(__response.StatusCode)) { + var __retryDelay = global::Inworld.AutoSDKRequestOptionsSupport.GetRetryDelay( + clientOptions: Options, + requestOptions: requestOptions, + response: __response, + attempt: __attempt); await global::Inworld.AutoSDKRequestOptionsSupport.OnAfterErrorAsync( clientOptions: Options, context: global::Inworld.AutoSDKRequestOptionsSupport.CreateHookContext( @@ -216,14 +250,15 @@ partial void ProcessGetVoiceResponseContent( attempt: __attempt, maxAttempts: __maxAttempts, willRetry: true, + retryDelay: __retryDelay, + retryReason: "status:" + ((int)__response.StatusCode).ToString(global::System.Globalization.CultureInfo.InvariantCulture), cancellationToken: __effectiveCancellationToken)).ConfigureAwait(false); __response.Dispose(); __response = null; __httpRequest.Dispose(); __httpRequest = null; await global::Inworld.AutoSDKRequestOptionsSupport.DelayBeforeRetryAsync( - clientOptions: Options, - requestOptions: requestOptions, + retryDelay: __retryDelay, cancellationToken: __effectiveCancellationToken).ConfigureAwait(false); continue; } @@ -263,6 +298,8 @@ partial void ProcessGetVoiceResponseContent( attempt: __attemptNumber, maxAttempts: __maxAttempts, willRetry: false, + retryDelay: null, + retryReason: global::System.String.Empty, cancellationToken: __effectiveCancellationToken)).ConfigureAwait(false); } else @@ -283,6 +320,8 @@ partial void ProcessGetVoiceResponseContent( attempt: __attemptNumber, maxAttempts: __maxAttempts, willRetry: false, + retryDelay: null, + retryReason: global::System.String.Empty, cancellationToken: __effectiveCancellationToken)).ConfigureAwait(false); } // Error response. @@ -345,9 +384,13 @@ partial void ProcessGetVoiceResponseContent( { __response.EnsureSuccessStatusCode(); - return - global::Inworld.Voice.FromJson(__content, JsonSerializerContext) ?? + var __value = global::Inworld.Voice.FromJson(__content, JsonSerializerContext) ?? throw new global::System.InvalidOperationException($"Response deserialization failed for \"{__content}\" "); + return new global::Inworld.AutoSDKHttpResponse( + statusCode: __response.StatusCode, + headers: global::Inworld.AutoSDKHttpResponse.CreateHeaders(__response), + requestUri: __response.RequestMessage?.RequestUri, + body: __value); } catch (global::System.Exception __ex) { @@ -375,9 +418,13 @@ partial void ProcessGetVoiceResponseContent( #endif ).ConfigureAwait(false); - return - await global::Inworld.Voice.FromJsonStreamAsync(__content, JsonSerializerContext).ConfigureAwait(false) ?? + var __value = await global::Inworld.Voice.FromJsonStreamAsync(__content, JsonSerializerContext).ConfigureAwait(false) ?? throw new global::System.InvalidOperationException("Response deserialization failed."); + return new global::Inworld.AutoSDKHttpResponse( + statusCode: __response.StatusCode, + headers: global::Inworld.AutoSDKHttpResponse.CreateHeaders(__response), + requestUri: __response.RequestMessage?.RequestUri, + body: __value); } catch (global::System.Exception __ex) { diff --git a/src/libs/Inworld/Generated/Inworld.VoicesClient.ListVoices.g.cs b/src/libs/Inworld/Generated/Inworld.VoicesClient.ListVoices.g.cs index 96a900c..51e0677 100644 --- a/src/libs/Inworld/Generated/Inworld.VoicesClient.ListVoices.g.cs +++ b/src/libs/Inworld/Generated/Inworld.VoicesClient.ListVoices.g.cs @@ -53,6 +53,27 @@ partial void ProcessListVoicesResponseContent( global::System.Collections.Generic.IList? languages = default, global::Inworld.AutoSDKRequestOptions? requestOptions = default, global::System.Threading.CancellationToken cancellationToken = default) + { + var __response = await ListVoicesAsResponseAsync( + languages: languages, + requestOptions: requestOptions, + cancellationToken: cancellationToken + ).ConfigureAwait(false); + + return __response.Body; + } + /// + /// List voices
+ /// List voices available to the authenticated workspace, optionally filtered by language. + ///
+ /// + /// Per-request overrides such as headers, query parameters, timeout, retries, and response buffering. + /// The token to cancel the operation with + /// + public async global::System.Threading.Tasks.Task> ListVoicesAsResponseAsync( + global::System.Collections.Generic.IList? languages = default, + global::Inworld.AutoSDKRequestOptions? requestOptions = default, + global::System.Threading.CancellationToken cancellationToken = default) { PrepareArguments( client: HttpClient); @@ -82,11 +103,12 @@ partial void ProcessListVoicesResponseContent( global::System.Net.Http.HttpRequestMessage __CreateHttpRequest() { + var __pathBuilder = new global::Inworld.PathBuilder( path: "/voices/v1/voices", - baseUri: HttpClient.BaseAddress); + baseUri: HttpClient.BaseAddress); __pathBuilder - .AddOptionalParameter("languages", languages, selector: static x => x.ToValueString(), delimiter: ",", explode: true) + .AddOptionalParameter("languages", languages, selector: static x => x.ToValueString(), delimiter: ",", explode: true) ; var __path = __pathBuilder.ToString(); __path = global::Inworld.AutoSDKRequestOptionsSupport.AppendQueryParameters( @@ -158,6 +180,8 @@ partial void ProcessListVoicesResponseContent( attempt: __attempt, maxAttempts: __maxAttempts, willRetry: false, + retryDelay: null, + retryReason: global::System.String.Empty, cancellationToken: __effectiveCancellationToken)).ConfigureAwait(false); try { @@ -168,6 +192,11 @@ partial void ProcessListVoicesResponseContent( } catch (global::System.Net.Http.HttpRequestException __exception) { + var __retryDelay = global::Inworld.AutoSDKRequestOptionsSupport.GetRetryDelay( + clientOptions: Options, + requestOptions: requestOptions, + response: null, + attempt: __attempt); var __willRetry = __attempt < __maxAttempts && !__effectiveCancellationToken.IsCancellationRequested; await global::Inworld.AutoSDKRequestOptionsSupport.OnAfterErrorAsync( clientOptions: Options, @@ -185,6 +214,8 @@ partial void ProcessListVoicesResponseContent( attempt: __attempt, maxAttempts: __maxAttempts, willRetry: __willRetry, + retryDelay: __willRetry ? __retryDelay : (global::System.TimeSpan?)null, + retryReason: "exception", cancellationToken: __effectiveCancellationToken)).ConfigureAwait(false); if (!__willRetry) { @@ -194,8 +225,7 @@ partial void ProcessListVoicesResponseContent( __httpRequest.Dispose(); __httpRequest = null; await global::Inworld.AutoSDKRequestOptionsSupport.DelayBeforeRetryAsync( - clientOptions: Options, - requestOptions: requestOptions, + retryDelay: __retryDelay, cancellationToken: __effectiveCancellationToken).ConfigureAwait(false); continue; } @@ -204,6 +234,11 @@ partial void ProcessListVoicesResponseContent( __attempt < __maxAttempts && global::Inworld.AutoSDKRequestOptionsSupport.ShouldRetryStatusCode(__response.StatusCode)) { + var __retryDelay = global::Inworld.AutoSDKRequestOptionsSupport.GetRetryDelay( + clientOptions: Options, + requestOptions: requestOptions, + response: __response, + attempt: __attempt); await global::Inworld.AutoSDKRequestOptionsSupport.OnAfterErrorAsync( clientOptions: Options, context: global::Inworld.AutoSDKRequestOptionsSupport.CreateHookContext( @@ -220,14 +255,15 @@ partial void ProcessListVoicesResponseContent( attempt: __attempt, maxAttempts: __maxAttempts, willRetry: true, + retryDelay: __retryDelay, + retryReason: "status:" + ((int)__response.StatusCode).ToString(global::System.Globalization.CultureInfo.InvariantCulture), cancellationToken: __effectiveCancellationToken)).ConfigureAwait(false); __response.Dispose(); __response = null; __httpRequest.Dispose(); __httpRequest = null; await global::Inworld.AutoSDKRequestOptionsSupport.DelayBeforeRetryAsync( - clientOptions: Options, - requestOptions: requestOptions, + retryDelay: __retryDelay, cancellationToken: __effectiveCancellationToken).ConfigureAwait(false); continue; } @@ -267,6 +303,8 @@ partial void ProcessListVoicesResponseContent( attempt: __attemptNumber, maxAttempts: __maxAttempts, willRetry: false, + retryDelay: null, + retryReason: global::System.String.Empty, cancellationToken: __effectiveCancellationToken)).ConfigureAwait(false); } else @@ -287,6 +325,8 @@ partial void ProcessListVoicesResponseContent( attempt: __attemptNumber, maxAttempts: __maxAttempts, willRetry: false, + retryDelay: null, + retryReason: global::System.String.Empty, cancellationToken: __effectiveCancellationToken)).ConfigureAwait(false); } // Error response. @@ -349,9 +389,13 @@ partial void ProcessListVoicesResponseContent( { __response.EnsureSuccessStatusCode(); - return - global::Inworld.ListVoicesResponse.FromJson(__content, JsonSerializerContext) ?? + var __value = global::Inworld.ListVoicesResponse.FromJson(__content, JsonSerializerContext) ?? throw new global::System.InvalidOperationException($"Response deserialization failed for \"{__content}\" "); + return new global::Inworld.AutoSDKHttpResponse( + statusCode: __response.StatusCode, + headers: global::Inworld.AutoSDKHttpResponse.CreateHeaders(__response), + requestUri: __response.RequestMessage?.RequestUri, + body: __value); } catch (global::System.Exception __ex) { @@ -379,9 +423,13 @@ partial void ProcessListVoicesResponseContent( #endif ).ConfigureAwait(false); - return - await global::Inworld.ListVoicesResponse.FromJsonStreamAsync(__content, JsonSerializerContext).ConfigureAwait(false) ?? + var __value = await global::Inworld.ListVoicesResponse.FromJsonStreamAsync(__content, JsonSerializerContext).ConfigureAwait(false) ?? throw new global::System.InvalidOperationException("Response deserialization failed."); + return new global::Inworld.AutoSDKHttpResponse( + statusCode: __response.StatusCode, + headers: global::Inworld.AutoSDKHttpResponse.CreateHeaders(__response), + requestUri: __response.RequestMessage?.RequestUri, + body: __value); } catch (global::System.Exception __ex) { diff --git a/src/libs/Inworld/Generated/Inworld.VoicesClient.PublishVoice.g.cs b/src/libs/Inworld/Generated/Inworld.VoicesClient.PublishVoice.g.cs index 6ac610f..f146dd3 100644 --- a/src/libs/Inworld/Generated/Inworld.VoicesClient.PublishVoice.g.cs +++ b/src/libs/Inworld/Generated/Inworld.VoicesClient.PublishVoice.g.cs @@ -55,6 +55,32 @@ partial void ProcessPublishVoiceResponseContent( public async global::System.Threading.Tasks.Task PublishVoiceAsync( string voiceId, + global::Inworld.PublishVoiceRequest request, + global::Inworld.AutoSDKRequestOptions? requestOptions = default, + global::System.Threading.CancellationToken cancellationToken = default) + { + var __response = await PublishVoiceAsResponseAsync( + voiceId: voiceId, + + request: request, + requestOptions: requestOptions, + cancellationToken: cancellationToken + ).ConfigureAwait(false); + + return __response.Body; + } + /// + /// Publish voice
+ /// Promote a drafted Design Voice preview into a persistent voice. + ///
+ /// + /// + /// Per-request overrides such as headers, query parameters, timeout, retries, and response buffering. + /// The token to cancel the operation with + /// + public async global::System.Threading.Tasks.Task> PublishVoiceAsResponseAsync( + string voiceId, + global::Inworld.PublishVoiceRequest request, global::Inworld.AutoSDKRequestOptions? requestOptions = default, global::System.Threading.CancellationToken cancellationToken = default) @@ -90,6 +116,7 @@ partial void ProcessPublishVoiceResponseContent( global::System.Net.Http.HttpRequestMessage __CreateHttpRequest() { + var __pathBuilder = new global::Inworld.PathBuilder( path: $"/voices/v1/voices/{voiceId}:publish", baseUri: HttpClient.BaseAddress); @@ -170,6 +197,8 @@ partial void ProcessPublishVoiceResponseContent( attempt: __attempt, maxAttempts: __maxAttempts, willRetry: false, + retryDelay: null, + retryReason: global::System.String.Empty, cancellationToken: __effectiveCancellationToken)).ConfigureAwait(false); try { @@ -180,6 +209,11 @@ partial void ProcessPublishVoiceResponseContent( } catch (global::System.Net.Http.HttpRequestException __exception) { + var __retryDelay = global::Inworld.AutoSDKRequestOptionsSupport.GetRetryDelay( + clientOptions: Options, + requestOptions: requestOptions, + response: null, + attempt: __attempt); var __willRetry = __attempt < __maxAttempts && !__effectiveCancellationToken.IsCancellationRequested; await global::Inworld.AutoSDKRequestOptionsSupport.OnAfterErrorAsync( clientOptions: Options, @@ -197,6 +231,8 @@ partial void ProcessPublishVoiceResponseContent( attempt: __attempt, maxAttempts: __maxAttempts, willRetry: __willRetry, + retryDelay: __willRetry ? __retryDelay : (global::System.TimeSpan?)null, + retryReason: "exception", cancellationToken: __effectiveCancellationToken)).ConfigureAwait(false); if (!__willRetry) { @@ -206,8 +242,7 @@ partial void ProcessPublishVoiceResponseContent( __httpRequest.Dispose(); __httpRequest = null; await global::Inworld.AutoSDKRequestOptionsSupport.DelayBeforeRetryAsync( - clientOptions: Options, - requestOptions: requestOptions, + retryDelay: __retryDelay, cancellationToken: __effectiveCancellationToken).ConfigureAwait(false); continue; } @@ -216,6 +251,11 @@ partial void ProcessPublishVoiceResponseContent( __attempt < __maxAttempts && global::Inworld.AutoSDKRequestOptionsSupport.ShouldRetryStatusCode(__response.StatusCode)) { + var __retryDelay = global::Inworld.AutoSDKRequestOptionsSupport.GetRetryDelay( + clientOptions: Options, + requestOptions: requestOptions, + response: __response, + attempt: __attempt); await global::Inworld.AutoSDKRequestOptionsSupport.OnAfterErrorAsync( clientOptions: Options, context: global::Inworld.AutoSDKRequestOptionsSupport.CreateHookContext( @@ -232,14 +272,15 @@ partial void ProcessPublishVoiceResponseContent( attempt: __attempt, maxAttempts: __maxAttempts, willRetry: true, + retryDelay: __retryDelay, + retryReason: "status:" + ((int)__response.StatusCode).ToString(global::System.Globalization.CultureInfo.InvariantCulture), cancellationToken: __effectiveCancellationToken)).ConfigureAwait(false); __response.Dispose(); __response = null; __httpRequest.Dispose(); __httpRequest = null; await global::Inworld.AutoSDKRequestOptionsSupport.DelayBeforeRetryAsync( - clientOptions: Options, - requestOptions: requestOptions, + retryDelay: __retryDelay, cancellationToken: __effectiveCancellationToken).ConfigureAwait(false); continue; } @@ -279,6 +320,8 @@ partial void ProcessPublishVoiceResponseContent( attempt: __attemptNumber, maxAttempts: __maxAttempts, willRetry: false, + retryDelay: null, + retryReason: global::System.String.Empty, cancellationToken: __effectiveCancellationToken)).ConfigureAwait(false); } else @@ -299,6 +342,8 @@ partial void ProcessPublishVoiceResponseContent( attempt: __attemptNumber, maxAttempts: __maxAttempts, willRetry: false, + retryDelay: null, + retryReason: global::System.String.Empty, cancellationToken: __effectiveCancellationToken)).ConfigureAwait(false); } // Error response. @@ -361,9 +406,13 @@ partial void ProcessPublishVoiceResponseContent( { __response.EnsureSuccessStatusCode(); - return - global::Inworld.Voice.FromJson(__content, JsonSerializerContext) ?? + var __value = global::Inworld.Voice.FromJson(__content, JsonSerializerContext) ?? throw new global::System.InvalidOperationException($"Response deserialization failed for \"{__content}\" "); + return new global::Inworld.AutoSDKHttpResponse( + statusCode: __response.StatusCode, + headers: global::Inworld.AutoSDKHttpResponse.CreateHeaders(__response), + requestUri: __response.RequestMessage?.RequestUri, + body: __value); } catch (global::System.Exception __ex) { @@ -391,9 +440,13 @@ partial void ProcessPublishVoiceResponseContent( #endif ).ConfigureAwait(false); - return - await global::Inworld.Voice.FromJsonStreamAsync(__content, JsonSerializerContext).ConfigureAwait(false) ?? + var __value = await global::Inworld.Voice.FromJsonStreamAsync(__content, JsonSerializerContext).ConfigureAwait(false) ?? throw new global::System.InvalidOperationException("Response deserialization failed."); + return new global::Inworld.AutoSDKHttpResponse( + statusCode: __response.StatusCode, + headers: global::Inworld.AutoSDKHttpResponse.CreateHeaders(__response), + requestUri: __response.RequestMessage?.RequestUri, + body: __value); } catch (global::System.Exception __ex) { diff --git a/src/libs/Inworld/Generated/Inworld.VoicesClient.UpdateVoice.g.cs b/src/libs/Inworld/Generated/Inworld.VoicesClient.UpdateVoice.g.cs index f7fc7e3..6cfe8ef 100644 --- a/src/libs/Inworld/Generated/Inworld.VoicesClient.UpdateVoice.g.cs +++ b/src/libs/Inworld/Generated/Inworld.VoicesClient.UpdateVoice.g.cs @@ -55,6 +55,32 @@ partial void ProcessUpdateVoiceResponseContent( public async global::System.Threading.Tasks.Task UpdateVoiceAsync( string voiceId, + global::Inworld.UpdateVoiceRequest request, + global::Inworld.AutoSDKRequestOptions? requestOptions = default, + global::System.Threading.CancellationToken cancellationToken = default) + { + var __response = await UpdateVoiceAsResponseAsync( + voiceId: voiceId, + + request: request, + requestOptions: requestOptions, + cancellationToken: cancellationToken + ).ConfigureAwait(false); + + return __response.Body; + } + /// + /// Update voice
+ /// Update editable voice metadata (display name, description, tags). + ///
+ /// + /// + /// Per-request overrides such as headers, query parameters, timeout, retries, and response buffering. + /// The token to cancel the operation with + /// + public async global::System.Threading.Tasks.Task> UpdateVoiceAsResponseAsync( + string voiceId, + global::Inworld.UpdateVoiceRequest request, global::Inworld.AutoSDKRequestOptions? requestOptions = default, global::System.Threading.CancellationToken cancellationToken = default) @@ -90,6 +116,7 @@ partial void ProcessUpdateVoiceResponseContent( global::System.Net.Http.HttpRequestMessage __CreateHttpRequest() { + var __pathBuilder = new global::Inworld.PathBuilder( path: $"/voices/v1/voices/{voiceId}", baseUri: HttpClient.BaseAddress); @@ -170,6 +197,8 @@ partial void ProcessUpdateVoiceResponseContent( attempt: __attempt, maxAttempts: __maxAttempts, willRetry: false, + retryDelay: null, + retryReason: global::System.String.Empty, cancellationToken: __effectiveCancellationToken)).ConfigureAwait(false); try { @@ -180,6 +209,11 @@ partial void ProcessUpdateVoiceResponseContent( } catch (global::System.Net.Http.HttpRequestException __exception) { + var __retryDelay = global::Inworld.AutoSDKRequestOptionsSupport.GetRetryDelay( + clientOptions: Options, + requestOptions: requestOptions, + response: null, + attempt: __attempt); var __willRetry = __attempt < __maxAttempts && !__effectiveCancellationToken.IsCancellationRequested; await global::Inworld.AutoSDKRequestOptionsSupport.OnAfterErrorAsync( clientOptions: Options, @@ -197,6 +231,8 @@ partial void ProcessUpdateVoiceResponseContent( attempt: __attempt, maxAttempts: __maxAttempts, willRetry: __willRetry, + retryDelay: __willRetry ? __retryDelay : (global::System.TimeSpan?)null, + retryReason: "exception", cancellationToken: __effectiveCancellationToken)).ConfigureAwait(false); if (!__willRetry) { @@ -206,8 +242,7 @@ partial void ProcessUpdateVoiceResponseContent( __httpRequest.Dispose(); __httpRequest = null; await global::Inworld.AutoSDKRequestOptionsSupport.DelayBeforeRetryAsync( - clientOptions: Options, - requestOptions: requestOptions, + retryDelay: __retryDelay, cancellationToken: __effectiveCancellationToken).ConfigureAwait(false); continue; } @@ -216,6 +251,11 @@ partial void ProcessUpdateVoiceResponseContent( __attempt < __maxAttempts && global::Inworld.AutoSDKRequestOptionsSupport.ShouldRetryStatusCode(__response.StatusCode)) { + var __retryDelay = global::Inworld.AutoSDKRequestOptionsSupport.GetRetryDelay( + clientOptions: Options, + requestOptions: requestOptions, + response: __response, + attempt: __attempt); await global::Inworld.AutoSDKRequestOptionsSupport.OnAfterErrorAsync( clientOptions: Options, context: global::Inworld.AutoSDKRequestOptionsSupport.CreateHookContext( @@ -232,14 +272,15 @@ partial void ProcessUpdateVoiceResponseContent( attempt: __attempt, maxAttempts: __maxAttempts, willRetry: true, + retryDelay: __retryDelay, + retryReason: "status:" + ((int)__response.StatusCode).ToString(global::System.Globalization.CultureInfo.InvariantCulture), cancellationToken: __effectiveCancellationToken)).ConfigureAwait(false); __response.Dispose(); __response = null; __httpRequest.Dispose(); __httpRequest = null; await global::Inworld.AutoSDKRequestOptionsSupport.DelayBeforeRetryAsync( - clientOptions: Options, - requestOptions: requestOptions, + retryDelay: __retryDelay, cancellationToken: __effectiveCancellationToken).ConfigureAwait(false); continue; } @@ -279,6 +320,8 @@ partial void ProcessUpdateVoiceResponseContent( attempt: __attemptNumber, maxAttempts: __maxAttempts, willRetry: false, + retryDelay: null, + retryReason: global::System.String.Empty, cancellationToken: __effectiveCancellationToken)).ConfigureAwait(false); } else @@ -299,6 +342,8 @@ partial void ProcessUpdateVoiceResponseContent( attempt: __attemptNumber, maxAttempts: __maxAttempts, willRetry: false, + retryDelay: null, + retryReason: global::System.String.Empty, cancellationToken: __effectiveCancellationToken)).ConfigureAwait(false); } // Error response. @@ -361,9 +406,13 @@ partial void ProcessUpdateVoiceResponseContent( { __response.EnsureSuccessStatusCode(); - return - global::Inworld.Voice.FromJson(__content, JsonSerializerContext) ?? + var __value = global::Inworld.Voice.FromJson(__content, JsonSerializerContext) ?? throw new global::System.InvalidOperationException($"Response deserialization failed for \"{__content}\" "); + return new global::Inworld.AutoSDKHttpResponse( + statusCode: __response.StatusCode, + headers: global::Inworld.AutoSDKHttpResponse.CreateHeaders(__response), + requestUri: __response.RequestMessage?.RequestUri, + body: __value); } catch (global::System.Exception __ex) { @@ -391,9 +440,13 @@ partial void ProcessUpdateVoiceResponseContent( #endif ).ConfigureAwait(false); - return - await global::Inworld.Voice.FromJsonStreamAsync(__content, JsonSerializerContext).ConfigureAwait(false) ?? + var __value = await global::Inworld.Voice.FromJsonStreamAsync(__content, JsonSerializerContext).ConfigureAwait(false) ?? throw new global::System.InvalidOperationException("Response deserialization failed."); + return new global::Inworld.AutoSDKHttpResponse( + statusCode: __response.StatusCode, + headers: global::Inworld.AutoSDKHttpResponse.CreateHeaders(__response), + requestUri: __response.RequestMessage?.RequestUri, + body: __value); } catch (global::System.Exception __ex) { diff --git a/src/libs/Inworld/Generated/Inworld.VoicesClient.g.cs b/src/libs/Inworld/Generated/Inworld.VoicesClient.g.cs index cd1dc4f..3bd9969 100644 --- a/src/libs/Inworld/Generated/Inworld.VoicesClient.g.cs +++ b/src/libs/Inworld/Generated/Inworld.VoicesClient.g.cs @@ -73,10 +73,10 @@ public VoicesClient( /// Client-wide request defaults such as headers, query parameters, retries, and timeout. /// Dispose the HttpClient when the instance is disposed. True by default. public VoicesClient( - global::System.Net.Http.HttpClient? httpClient = null, - global::System.Uri? baseUri = null, - global::System.Collections.Generic.List? authorizations = null, - global::Inworld.AutoSDKClientOptions? options = null, + global::System.Net.Http.HttpClient? httpClient, + global::System.Uri? baseUri, + global::System.Collections.Generic.List? authorizations, + global::Inworld.AutoSDKClientOptions? options, bool disposeHttpClient = true) {