From 8b662961c15fec92193a8a645cf6a8e89b78c39d Mon Sep 17 00:00:00 2001
From: Ernie <ernestfrench@gmail.com>
Date: Wed, 21 Feb 2024 12:15:16 -0800
Subject: [PATCH 1/5] Fix revised_prompt parameter name so it will be correctly
 deserialized.

---
 OpenAI_API/Images/ImageResult.cs | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/OpenAI_API/Images/ImageResult.cs b/OpenAI_API/Images/ImageResult.cs
index 5c9770e..d2f2aa0 100644
--- a/OpenAI_API/Images/ImageResult.cs
+++ b/OpenAI_API/Images/ImageResult.cs
@@ -51,10 +51,11 @@ public class Data
 		[JsonProperty("b64_json")]
 		public string Base64Data { get; set; }
 
-		/// <summary>
-		/// The prompt that was used to generate the image, if there was any revision to the prompt.
-		/// </summary>
-		public string RevisedPrompt { get; set; }
+        /// <summary>
+        /// The prompt that was used to generate the image, if there was any revision to the prompt.
+        /// </summary>
+        [JsonProperty("revised_prompt")]
+        public string RevisedPrompt { get; set; }
 
 	}
 }

From 0f4384be3627661b703ba85ba64c278e6e5ddd43 Mon Sep 17 00:00:00 2001
From: Ernie <ernestfrench@gmail.com>
Date: Sun, 25 Feb 2024 10:14:15 -0800
Subject: [PATCH 2/5] whitespace

---
 OpenAI_API/Images/ImageResult.cs | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/OpenAI_API/Images/ImageResult.cs b/OpenAI_API/Images/ImageResult.cs
index d2f2aa0..a871a47 100644
--- a/OpenAI_API/Images/ImageResult.cs
+++ b/OpenAI_API/Images/ImageResult.cs
@@ -52,9 +52,9 @@ public class Data
 		public string Base64Data { get; set; }
 
         /// <summary>
-        /// The prompt that was used to generate the image, if there was any revision to the prompt.
-        /// </summary>
-        [JsonProperty("revised_prompt")]
+		/// The prompt that was used to generate the image, if there was any revision to the prompt.
+		/// </summary>
+		[JsonProperty("revised_prompt")]
         public string RevisedPrompt { get; set; }
 
 	}

From 85da80bf87b58a850d51280785bf59a110f0ac89 Mon Sep 17 00:00:00 2001
From: Ernie <ernestfrench@gmail.com>
Date: Sun, 25 Feb 2024 10:26:26 -0800
Subject: [PATCH 3/5] formatting

---
 OpenAI_API/Images/ImageResult.cs | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/OpenAI_API/Images/ImageResult.cs b/OpenAI_API/Images/ImageResult.cs
index a871a47..17e6e87 100644
--- a/OpenAI_API/Images/ImageResult.cs
+++ b/OpenAI_API/Images/ImageResult.cs
@@ -49,13 +49,13 @@ public class Data
 		/// The base64-encoded image data as returned by the API
 		/// </summary>
 		[JsonProperty("b64_json")]
-		public string Base64Data { get; set; }
+		public string Base64Data { get; set; } 
 
-        /// <summary>
+		/// <summary>
 		/// The prompt that was used to generate the image, if there was any revision to the prompt.
 		/// </summary>
 		[JsonProperty("revised_prompt")]
-        public string RevisedPrompt { get; set; }
+		public string RevisedPrompt { get; set; }
 
 	}
 }

From 4fce673a82223110d188212e43f23c491ac6722d Mon Sep 17 00:00:00 2001
From: Ernie <ernestfrench@gmail.com>
Date: Fri, 1 Mar 2024 20:20:26 -0800
Subject: [PATCH 4/5] fix a few little things, icon location, reporting etc.

---
 OpenAI_API/EndpointBase.cs       | 785 ++++++++++++++++---------------
 OpenAI_API/Images/ImageResult.cs |   2 +-
 2 files changed, 397 insertions(+), 390 deletions(-)

diff --git a/OpenAI_API/EndpointBase.cs b/OpenAI_API/EndpointBase.cs
index d981c7e..3a27fa4 100644
--- a/OpenAI_API/EndpointBase.cs
+++ b/OpenAI_API/EndpointBase.cs
@@ -1,4 +1,5 @@
 using Newtonsoft.Json;
+
 using System;
 using System.Collections.Generic;
 using System.Diagnostics;
@@ -11,233 +12,233 @@
 
 namespace OpenAI_API
 {
-	/// <summary>
-	/// A base object for any OpenAI API endpoint, encompassing common functionality
-	/// </summary>
-	public abstract class EndpointBase
-	{
-		private const string UserAgent = "okgodoit/dotnet_openai_api";
-
-		/// <summary>
-		/// The internal reference to the API, mostly used for authentication
-		/// </summary>
-		protected readonly OpenAIAPI _Api;
-
-		/// <summary>
-		/// Constructor of the api endpoint base, to be called from the contructor of any devived classes.  Rather than instantiating any endpoint yourself, access it through an instance of <see cref="OpenAIAPI"/>.
-		/// </summary>
-		/// <param name="api"></param>
-		internal EndpointBase(OpenAIAPI api)
-		{
-			this._Api = api;
-		}
-
-		/// <summary>
-		/// The name of the endpoint, which is the final path segment in the API URL.  Must be overriden in a derived class.
-		/// </summary>
-		protected abstract string Endpoint { get; }
-
-		/// <summary>
-		/// Gets the URL of the endpoint, based on the base OpenAI API URL followed by the endpoint name.  For example "https://api.openai.com/v1/completions"
-		/// </summary>
-		protected string Url
-		{
-			get
-			{
-				return string.Format(_Api.ApiUrlFormat, _Api.ApiVersion, Endpoint);
-			}
-		}
-
-		/// <summary>
-		/// Gets an HTTPClient with the appropriate authorization and other headers set
-		/// </summary>
-		/// <returns>The fully initialized HttpClient</returns>
-		/// <exception cref="AuthenticationException">Thrown if there is no valid authentication.  Please refer to <see href="https://github.com/OkGoDoIt/OpenAI-API-dotnet#authentication"/> for details.</exception>
-		protected HttpClient GetClient()
-		{
-			if (_Api.Auth?.ApiKey is null)
-			{
-				throw new AuthenticationException("You must provide API authentication.  Please refer to https://github.com/OkGoDoIt/OpenAI-API-dotnet#authentication for details.");
-			}
-
-			HttpClient client;
-			var clientFactory = _Api.HttpClientFactory;
-			if (clientFactory != null)
-			{
-				client = clientFactory.CreateClient();
-			}
-			else
-			{
-				client = new HttpClient();
-			}
-
-			client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", _Api.Auth.ApiKey);
-			// Further authentication-header used for Azure openAI service
-			client.DefaultRequestHeaders.Add("api-key", _Api.Auth.ApiKey);
-			client.DefaultRequestHeaders.Add("User-Agent", UserAgent);
-			if (!string.IsNullOrEmpty(_Api.Auth.OpenAIOrganization)) client.DefaultRequestHeaders.Add("OpenAI-Organization", _Api.Auth.OpenAIOrganization);
-
-			return client;
-		}
-
-		/// <summary>
-		/// Formats a human-readable error message relating to calling the API and parsing the response
-		/// </summary>
-		/// <param name="resultAsString">The full content returned in the http response</param>
-		/// <param name="response">The http response object itself</param>
-		/// <param name="name">The name of the endpoint being used</param>
-		/// <param name="description">Additional details about the endpoint of this request (optional)</param>
-		/// <returns>A human-readable string error message.</returns>
-		protected string GetErrorMessage(string resultAsString, HttpResponseMessage response, string name, string description = "")
-		{
-			return $"Error at {name} ({description}) with HTTP status code: {response.StatusCode}. Content: {resultAsString ?? "<no content>"}";
-		}
-
-
-		/// <summary>
-		/// Sends an HTTP request and returns the response.  Does not do any parsing, but does do error handling.
-		/// </summary>
-		/// <param name="url">(optional) If provided, overrides the url endpoint for this request.  If omitted, then <see cref="Url"/> will be used.</param>
-		/// <param name="verb">(optional) The HTTP verb to use, for example "<see cref="HttpMethod.Get"/>".  If omitted, then "GET" is assumed.</param>
-		/// <param name="postData">(optional) A json-serializable object to include in the request body.</param>
-		/// <param name="streaming">(optional) If true, streams the response.  Otherwise waits for the entire response before returning.</param>
-		/// <returns>The HttpResponseMessage of the response, which is confirmed to be successful.</returns>
-		/// <exception cref="HttpRequestException">Throws an exception if a non-success HTTP response was returned</exception>
-		private async Task<HttpResponseMessage> HttpRequestRaw(string url = null, HttpMethod verb = null, object postData = null, bool streaming = false)
-		{
-			if (string.IsNullOrEmpty(url))
-				url = this.Url;
-
-			if (verb == null)
-				verb = HttpMethod.Get;
-
-			using var client = GetClient();
-
-			HttpResponseMessage response = null;
-			string resultAsString = null;
-			HttpRequestMessage req = new HttpRequestMessage(verb, url);
-
-			if (postData != null)
-			{
-				if (postData is HttpContent)
-				{
-					req.Content = postData as HttpContent;
-				}
-				else
-				{
-					string jsonContent = JsonConvert.SerializeObject(postData, new JsonSerializerSettings() { NullValueHandling = NullValueHandling.Ignore });
-					var stringContent = new StringContent(jsonContent, UnicodeEncoding.UTF8, "application/json");
-					req.Content = stringContent;
-				}
-			}
-			response = await client.SendAsync(req, streaming ? HttpCompletionOption.ResponseHeadersRead : HttpCompletionOption.ResponseContentRead);
-
-			if (response.IsSuccessStatusCode)
-			{
-				return response;
-			}
-			else
-			{
-				try
-				{
-					resultAsString = await response.Content.ReadAsStringAsync();
-				}
-				catch (Exception readError)
-				{
-					resultAsString = "Additionally, the following error was thrown when attemping to read the response content: " + readError.ToString();
-				}
-
-				if (response.StatusCode == System.Net.HttpStatusCode.Unauthorized)
-				{
-					throw new AuthenticationException("OpenAI rejected your authorization, most likely due to an invalid API Key.  Try checking your API Key and see https://github.com/OkGoDoIt/OpenAI-API-dotnet#authentication for guidance.  Full API response follows: " + resultAsString);
-				}
-				else if (response.StatusCode == System.Net.HttpStatusCode.InternalServerError)
-				{
-					throw new HttpRequestException("OpenAI had an internal server error, which can happen occasionally.  Please retry your request.  " + GetErrorMessage(resultAsString, response, Endpoint, url));
-				}
-				else
-				{
-					var errorToThrow = new HttpRequestException(GetErrorMessage(resultAsString, response, Endpoint, url));
-
-					var parsedError = JsonConvert.DeserializeObject<ApiErrorResponse>(resultAsString);
-					try
-					{
-						errorToThrow.Data.Add("message", parsedError.Error.Message);
-						errorToThrow.Data.Add("type", parsedError.Error.ErrorType);
-						errorToThrow.Data.Add("param", parsedError.Error.Parameter);
-						errorToThrow.Data.Add("code", parsedError.Error.ErrorCode);
-					}
-					catch (Exception parsingError)
-					{
-						throw new HttpRequestException(errorToThrow.Message, parsingError);
-					}
-					throw errorToThrow;
-				}
-			}
-		}
-
-		/// <summary>
-		/// Sends an HTTP Get request and return the string content of the response without parsing, and does error handling.
-		/// </summary>
-		/// <param name="url">(optional) If provided, overrides the url endpoint for this request.  If omitted, then <see cref="Url"/> will be used.</param>
-		/// <param name="verb">(optional) The HTTP verb to use, for example "<see cref="HttpMethod.Get"/>".  If omitted, then "GET" is assumed.</param>
-		/// <param name="postData">(optional) A json-serializable object to include in the request body.</param>
-		/// <returns>The text string of the response, which is confirmed to be successful.</returns>
-		/// <exception cref="HttpRequestException">Throws an exception if a non-success HTTP response was returned</exception>
-		internal async Task<string> HttpGetContent(string url = null, HttpMethod verb = null, object postData = null)
-		{
-			var response = await HttpRequestRaw(url, verb, postData);
-			return await response.Content.ReadAsStringAsync();
-		}
-
-		/// <summary>
-		/// Sends an HTTP request and return the raw content stream of the response without parsing, and does error handling.
-		/// </summary>
-		/// <param name="url">(optional) If provided, overrides the url endpoint for this request.  If omitted, then <see cref="Url"/> will be used.</param>
-		/// <param name="verb">(optional) The HTTP verb to use, for example "<see cref="HttpMethod.Get"/>".  If omitted, then "GET" is assumed.</param>
-		/// <param name="postData">(optional) A json-serializable object to include in the request body.</param>
-		/// <returns>The response content stream, which is confirmed to be successful.</returns>
-		/// <exception cref="HttpRequestException">Throws an exception if a non-success HTTP response was returned</exception>
-		internal async Task<Stream> HttpRequest(string url = null, HttpMethod verb = null, object postData = null)
-		{
-			var response = await HttpRequestRaw(url, verb, postData);
-			return await response.Content.ReadAsStreamAsync();
-		}
-
-
-		/// <summary>
-		/// Sends an HTTP Request and does initial parsing
-		/// </summary>
-		/// <typeparam name="T">The <see cref="ApiResultBase"/>-derived class for the result</typeparam>
-		/// <param name="url">(optional) If provided, overrides the url endpoint for this request.  If omitted, then <see cref="Url"/> will be used.</param>
-		/// <param name="verb">(optional) The HTTP verb to use, for example "<see cref="HttpMethod.Get"/>".  If omitted, then "GET" is assumed.</param>
-		/// <param name="postData">(optional) A json-serializable object to include in the request body.</param>
-		/// <returns>An awaitable Task with the parsed result of type <typeparamref name="T"/></returns>
-		/// <exception cref="HttpRequestException">Throws an exception if a non-success HTTP response was returned or if the result couldn't be parsed.</exception>
-		private async Task<T> HttpRequest<T>(string url = null, HttpMethod verb = null, object postData = null) where T : ApiResultBase
-		{
-			var response = await HttpRequestRaw(url, verb, postData);
-			string resultAsString = await response.Content.ReadAsStringAsync();
-
-			var res = JsonConvert.DeserializeObject<T>(resultAsString);
-			try
-			{
-				res.Organization = response.Headers.GetValues("Openai-Organization").FirstOrDefault();
-				res.RequestId = response.Headers.GetValues("X-Request-ID").FirstOrDefault();
-				res.ProcessingTime = TimeSpan.FromMilliseconds(int.Parse(response.Headers.GetValues("Openai-Processing-Ms").First()));
-				res.OpenaiVersion = response.Headers.GetValues("Openai-Version").FirstOrDefault();
-				if (string.IsNullOrEmpty(res.Model))
-					res.Model = response.Headers.GetValues("Openai-Model").FirstOrDefault();
-			}
-			catch (Exception e)
-			{
-				Debug.Print($"Issue parsing metadata of OpenAi Response.  Url: {url}, Error: {e.ToString()}, Response: {resultAsString}.  This is probably ignorable.");
-			}
-
-			return res;
-		}
-
-		/*
+    /// <summary>
+    /// A base object for any OpenAI API endpoint, encompassing common functionality
+    /// </summary>
+    public abstract class EndpointBase
+    {
+        private const string UserAgent = "okgodoit/dotnet_openai_api";
+
+        /// <summary>
+        /// The internal reference to the API, mostly used for authentication
+        /// </summary>
+        protected readonly OpenAIAPI _Api;
+
+        /// <summary>
+        /// Constructor of the api endpoint base, to be called from the contructor of any devived classes.  Rather than instantiating any endpoint yourself, access it through an instance of <see cref="OpenAIAPI"/>.
+        /// </summary>
+        /// <param name="api"></param>
+        internal EndpointBase(OpenAIAPI api)
+        {
+            this._Api = api;
+        }
+
+        /// <summary>
+        /// The name of the endpoint, which is the final path segment in the API URL.  Must be overriden in a derived class.
+        /// </summary>
+        protected abstract string Endpoint { get; }
+
+        /// <summary>
+        /// Gets the URL of the endpoint, based on the base OpenAI API URL followed by the endpoint name.  For example "https://api.openai.com/v1/completions"
+        /// </summary>
+        protected string Url
+        {
+            get
+            {
+                return string.Format(_Api.ApiUrlFormat, _Api.ApiVersion, Endpoint);
+            }
+        }
+
+        /// <summary>
+        /// Gets an HTTPClient with the appropriate authorization and other headers set
+        /// </summary>
+        /// <returns>The fully initialized HttpClient</returns>
+        /// <exception cref="AuthenticationException">Thrown if there is no valid authentication.  Please refer to <see href="https://github.com/OkGoDoIt/OpenAI-API-dotnet#authentication"/> for details.</exception>
+        protected HttpClient GetClient()
+        {
+            if (_Api.Auth?.ApiKey is null)
+            {
+                throw new AuthenticationException("You must provide API authentication.  Please refer to https://github.com/OkGoDoIt/OpenAI-API-dotnet#authentication for details.");
+            }
+
+            HttpClient client;
+            var clientFactory = _Api.HttpClientFactory;
+            if (clientFactory != null)
+            {
+                client = clientFactory.CreateClient();
+            }
+            else
+            {
+                client = new HttpClient();
+            }
+
+            client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", _Api.Auth.ApiKey);
+            // Further authentication-header used for Azure openAI service
+            client.DefaultRequestHeaders.Add("api-key", _Api.Auth.ApiKey);
+            client.DefaultRequestHeaders.Add("User-Agent", UserAgent);
+            if (!string.IsNullOrEmpty(_Api.Auth.OpenAIOrganization)) client.DefaultRequestHeaders.Add("OpenAI-Organization", _Api.Auth.OpenAIOrganization);
+
+            return client;
+        }
+
+        /// <summary>
+        /// Formats a human-readable error message relating to calling the API and parsing the response
+        /// </summary>
+        /// <param name="resultAsString">The full content returned in the http response</param>
+        /// <param name="response">The http response object itself</param>
+        /// <param name="name">The name of the endpoint being used</param>
+        /// <param name="description">Additional details about the endpoint of this request (optional)</param>
+        /// <returns>A human-readable string error message.</returns>
+        protected string GetErrorMessage(string resultAsString, HttpResponseMessage response, string name, string description = "")
+        {
+            return $"Error at {name} ({description}) with HTTP status code: {response.StatusCode}. Content: {resultAsString ?? "<no content>"}";
+        }
+
+        /// <summary>
+        /// Sends an HTTP request and returns the response.  Does not do any parsing, but does do error handling.
+        /// </summary>
+        /// <param name="url">(optional) If provided, overrides the url endpoint for this request.  If omitted, then <see cref="Url"/> will be used.</param>
+        /// <param name="verb">(optional) The HTTP verb to use, for example "<see cref="HttpMethod.Get"/>".  If omitted, then "GET" is assumed.</param>
+        /// <param name="postData">(optional) A json-serializable object to include in the request body.</param>
+        /// <param name="streaming">(optional) If true, streams the response.  Otherwise waits for the entire response before returning.</param>
+        /// <returns>The HttpResponseMessage of the response, which is confirmed to be successful.</returns>
+        /// <exception cref="HttpRequestException">Throws an exception if a non-success HTTP response was returned</exception>
+        private async Task<HttpResponseMessage> HttpRequestRaw(string url = null, HttpMethod verb = null, object postData = null, bool streaming = false)
+        {
+            if (string.IsNullOrEmpty(url))
+                url = this.Url;
+
+            if (verb == null)
+                verb = HttpMethod.Get;
+
+            using var client = GetClient();
+
+            HttpResponseMessage response = null;
+            string resultAsString = null;
+            HttpRequestMessage req = new HttpRequestMessage(verb, url);
+
+            if (postData != null)
+            {
+                if (postData is HttpContent)
+                {
+                    req.Content = postData as HttpContent;
+                }
+                else
+                {
+                    string jsonContent = JsonConvert.SerializeObject(postData, new JsonSerializerSettings() { NullValueHandling = NullValueHandling.Ignore });
+                    var stringContent = new StringContent(jsonContent, UnicodeEncoding.UTF8, "application/json");
+                    req.Content = stringContent;
+                }
+            }
+            response = await client.SendAsync(req, streaming ? HttpCompletionOption.ResponseHeadersRead : HttpCompletionOption.ResponseContentRead);
+
+            if (response.IsSuccessStatusCode)
+            {
+                return response;
+            }
+            else
+            {
+                try
+                {
+                    resultAsString = await response.Content.ReadAsStringAsync();
+                }
+                catch (Exception readError)
+                {
+                    resultAsString = "Additionally, the following error was thrown when attemping to read the response content: " + readError.ToString();
+                }
+
+                if (response.StatusCode == System.Net.HttpStatusCode.Unauthorized)
+                {
+                    throw new AuthenticationException("OpenAI rejected your authorization, most likely due to an invalid API Key.  Try checking your API Key and see https://github.com/OkGoDoIt/OpenAI-API-dotnet#authentication for guidance.  Full API response follows: " + resultAsString);
+                }
+                else if (response.StatusCode == System.Net.HttpStatusCode.InternalServerError)
+                {
+                    throw new HttpRequestException("OpenAI had an internal server error, which can happen occasionally.  Please retry your request.  " + GetErrorMessage(resultAsString, response, Endpoint, url));
+                }
+                else
+                {
+                    var errorToThrow = new HttpRequestException(GetErrorMessage(resultAsString, response, Endpoint, url));
+
+                    var parsedError = JsonConvert.DeserializeObject<ApiErrorResponse>(resultAsString);
+                    try
+                    {
+                        errorToThrow.Data.Add("message", parsedError.Error.Message);
+                        errorToThrow.Data.Add("type", parsedError.Error.ErrorType);
+                        errorToThrow.Data.Add("param", parsedError.Error.Parameter);
+                        errorToThrow.Data.Add("code", parsedError.Error.ErrorCode);
+                    }
+                    catch (Exception parsingError)
+                    {
+                        throw new HttpRequestException(errorToThrow.Message, parsingError);
+                    }
+                    throw errorToThrow;
+                }
+            }
+        }
+
+        /// <summary>
+        /// Sends an HTTP Get request and return the string content of the response without parsing, and does error handling.
+        /// </summary>
+        /// <param name="url">(optional) If provided, overrides the url endpoint for this request.  If omitted, then <see cref="Url"/> will be used.</param>
+        /// <param name="verb">(optional) The HTTP verb to use, for example "<see cref="HttpMethod.Get"/>".  If omitted, then "GET" is assumed.</param>
+        /// <param name="postData">(optional) A json-serializable object to include in the request body.</param>
+        /// <returns>The text string of the response, which is confirmed to be successful.</returns>
+        /// <exception cref="HttpRequestException">Throws an exception if a non-success HTTP response was returned</exception>
+        internal async Task<string> HttpGetContent(string url = null, HttpMethod verb = null, object postData = null)
+        {
+            var response = await HttpRequestRaw(url, verb, postData);
+            return await response.Content.ReadAsStringAsync();
+        }
+
+        /// <summary>
+        /// Sends an HTTP request and return the raw content stream of the response without parsing, and does error handling.
+        /// </summary>
+        /// <param name="url">(optional) If provided, overrides the url endpoint for this request.  If omitted, then <see cref="Url"/> will be used.</param>
+        /// <param name="verb">(optional) The HTTP verb to use, for example "<see cref="HttpMethod.Get"/>".  If omitted, then "GET" is assumed.</param>
+        /// <param name="postData">(optional) A json-serializable object to include in the request body.</param>
+        /// <returns>The response content stream, which is confirmed to be successful.</returns>
+        /// <exception cref="HttpRequestException">Throws an exception if a non-success HTTP response was returned</exception>
+        internal async Task<Stream> HttpRequest(string url = null, HttpMethod verb = null, object postData = null)
+        {
+            var response = await HttpRequestRaw(url, verb, postData);
+            return await response.Content.ReadAsStreamAsync();
+        }
+
+        /// <summary>
+        /// Sends an HTTP Request and does initial parsing
+        /// </summary>
+        /// <typeparam name="T">The <see cref="ApiResultBase"/>-derived class for the result</typeparam>
+        /// <param name="url">(optional) If provided, overrides the url endpoint for this request.  If omitted, then <see cref="Url"/> will be used.</param>
+        /// <param name="verb">(optional) The HTTP verb to use, for example "<see cref="HttpMethod.Get"/>".  If omitted, then "GET" is assumed.</param>
+        /// <param name="postData">(optional) A json-serializable object to include in the request body.</param>
+        /// <returns>An awaitable Task with the parsed result of type <typeparamref name="T"/></returns>
+        /// <exception cref="HttpRequestException">Throws an exception if a non-success HTTP response was returned or if the result couldn't be parsed.</exception>
+        private async Task<T> HttpRequest<T>(string url = null, HttpMethod verb = null, object postData = null) where T : ApiResultBase
+        {
+            var response = await HttpRequestRaw(url, verb, postData);
+            string resultAsString = await response.Content.ReadAsStringAsync();
+
+            var res = JsonConvert.DeserializeObject<T>(resultAsString);
+
+            try
+            {
+
+                res.Organization = response.Headers.GetValues("Openai-Organization").FirstOrDefault();
+                res.RequestId = response.Headers.GetValues("X-Request-ID").FirstOrDefault();
+                res.ProcessingTime = TimeSpan.FromMilliseconds(int.Parse(response.Headers.GetValues("Openai-Processing-Ms").First()));
+                res.OpenaiVersion = response.Headers.GetValues("Openai-Version").FirstOrDefault();
+                if (string.IsNullOrEmpty(res.Model))
+                    res.Model = response.Headers.GetValues("Openai-Model").FirstOrDefault();
+            }
+            catch (Exception e)
+            {
+                Debug.Print($"Issue parsing metadata of OpenAi Response.  Url: {url}, Error: {e.ToString()}, Response: {resultAsString}.  This is probably ignorable.");
+            }
+
+            return res;
+        }
+
+        /*
 		/// <summary>
 		/// Sends an HTTP Request, supporting a streaming response
 		/// </summary>
@@ -271,61 +272,58 @@ private async Task<T> StreamingHttpRequest<T>(string url = null, HttpMethod verb
 		}
 		*/
 
-		/// <summary>
-		/// Sends an HTTP Get request and does initial parsing
-		/// </summary>
-		/// <typeparam name="T">The <see cref="ApiResultBase"/>-derived class for the result</typeparam>
-		/// <param name="url">(optional) If provided, overrides the url endpoint for this request.  If omitted, then <see cref="Url"/> will be used.</param>
-		/// <returns>An awaitable Task with the parsed result of type <typeparamref name="T"/></returns>
-		/// <exception cref="HttpRequestException">Throws an exception if a non-success HTTP response was returned or if the result couldn't be parsed.</exception>
-		internal async Task<T> HttpGet<T>(string url = null) where T : ApiResultBase
-		{
-			return await HttpRequest<T>(url, HttpMethod.Get);
-		}
-
-		/// <summary>
-		/// Sends an HTTP Post request and does initial parsing
-		/// </summary>
-		/// <typeparam name="T">The <see cref="ApiResultBase"/>-derived class for the result</typeparam>
-		/// <param name="url">(optional) If provided, overrides the url endpoint for this request.  If omitted, then <see cref="Url"/> will be used.</param>
-		/// <param name="postData">(optional) A json-serializable object to include in the request body.</param>
-		/// <returns>An awaitable Task with the parsed result of type <typeparamref name="T"/></returns>
-		/// <exception cref="HttpRequestException">Throws an exception if a non-success HTTP response was returned or if the result couldn't be parsed.</exception>
-		internal async Task<T> HttpPost<T>(string url = null, object postData = null) where T : ApiResultBase
-		{
-			return await HttpRequest<T>(url, HttpMethod.Post, postData);
-		}
-
-		/// <summary>
-		/// Sends an HTTP Delete request and does initial parsing
-		/// </summary>
-		/// <typeparam name="T">The <see cref="ApiResultBase"/>-derived class for the result</typeparam>
-		/// <param name="url">(optional) If provided, overrides the url endpoint for this request.  If omitted, then <see cref="Url"/> will be used.</param>
-		/// <param name="postData">(optional) A json-serializable object to include in the request body.</param>
-		/// <returns>An awaitable Task with the parsed result of type <typeparamref name="T"/></returns>
-		/// <exception cref="HttpRequestException">Throws an exception if a non-success HTTP response was returned or if the result couldn't be parsed.</exception>
-		internal async Task<T> HttpDelete<T>(string url = null, object postData = null) where T : ApiResultBase
-		{
-			return await HttpRequest<T>(url, HttpMethod.Delete, postData);
-		}
-
-
-		/// <summary>
-		/// Sends an HTTP Put request and does initial parsing
-		/// </summary>
-		/// <typeparam name="T">The <see cref="ApiResultBase"/>-derived class for the result</typeparam>
-		/// <param name="url">(optional) If provided, overrides the url endpoint for this request.  If omitted, then <see cref="Url"/> will be used.</param>
-		/// <param name="postData">(optional) A json-serializable object to include in the request body.</param>
-		/// <returns>An awaitable Task with the parsed result of type <typeparamref name="T"/></returns>
-		/// <exception cref="HttpRequestException">Throws an exception if a non-success HTTP response was returned or if the result couldn't be parsed.</exception>
-		internal async Task<T> HttpPut<T>(string url = null, object postData = null) where T : ApiResultBase
-		{
-			return await HttpRequest<T>(url, HttpMethod.Put, postData);
-		}
-
-
-
-		/*
+        /// <summary>
+        /// Sends an HTTP Get request and does initial parsing
+        /// </summary>
+        /// <typeparam name="T">The <see cref="ApiResultBase"/>-derived class for the result</typeparam>
+        /// <param name="url">(optional) If provided, overrides the url endpoint for this request.  If omitted, then <see cref="Url"/> will be used.</param>
+        /// <returns>An awaitable Task with the parsed result of type <typeparamref name="T"/></returns>
+        /// <exception cref="HttpRequestException">Throws an exception if a non-success HTTP response was returned or if the result couldn't be parsed.</exception>
+        internal async Task<T> HttpGet<T>(string url = null) where T : ApiResultBase
+        {
+            return await HttpRequest<T>(url, HttpMethod.Get);
+        }
+
+        /// <summary>
+        /// Sends an HTTP Post request and does initial parsing
+        /// </summary>
+        /// <typeparam name="T">The <see cref="ApiResultBase"/>-derived class for the result</typeparam>
+        /// <param name="url">(optional) If provided, overrides the url endpoint for this request.  If omitted, then <see cref="Url"/> will be used.</param>
+        /// <param name="postData">(optional) A json-serializable object to include in the request body.</param>
+        /// <returns>An awaitable Task with the parsed result of type <typeparamref name="T"/></returns>
+        /// <exception cref="HttpRequestException">Throws an exception if a non-success HTTP response was returned or if the result couldn't be parsed.</exception>
+        internal async Task<T> HttpPost<T>(string url = null, object postData = null) where T : ApiResultBase
+        {
+            return await HttpRequest<T>(url, HttpMethod.Post, postData);
+        }
+
+        /// <summary>
+        /// Sends an HTTP Delete request and does initial parsing
+        /// </summary>
+        /// <typeparam name="T">The <see cref="ApiResultBase"/>-derived class for the result</typeparam>
+        /// <param name="url">(optional) If provided, overrides the url endpoint for this request.  If omitted, then <see cref="Url"/> will be used.</param>
+        /// <param name="postData">(optional) A json-serializable object to include in the request body.</param>
+        /// <returns>An awaitable Task with the parsed result of type <typeparamref name="T"/></returns>
+        /// <exception cref="HttpRequestException">Throws an exception if a non-success HTTP response was returned or if the result couldn't be parsed.</exception>
+        internal async Task<T> HttpDelete<T>(string url = null, object postData = null) where T : ApiResultBase
+        {
+            return await HttpRequest<T>(url, HttpMethod.Delete, postData);
+        }
+
+        /// <summary>
+        /// Sends an HTTP Put request and does initial parsing
+        /// </summary>
+        /// <typeparam name="T">The <see cref="ApiResultBase"/>-derived class for the result</typeparam>
+        /// <param name="url">(optional) If provided, overrides the url endpoint for this request.  If omitted, then <see cref="Url"/> will be used.</param>
+        /// <param name="postData">(optional) A json-serializable object to include in the request body.</param>
+        /// <returns>An awaitable Task with the parsed result of type <typeparamref name="T"/></returns>
+        /// <exception cref="HttpRequestException">Throws an exception if a non-success HTTP response was returned or if the result couldn't be parsed.</exception>
+        internal async Task<T> HttpPut<T>(string url = null, object postData = null) where T : ApiResultBase
+        {
+            return await HttpRequest<T>(url, HttpMethod.Put, postData);
+        }
+
+        /*
 		/// <summary>
 		/// Sends an HTTP request and handles a streaming response.  Does basic line splitting and error handling.
 		/// </summary>
@@ -359,111 +357,120 @@ private async IAsyncEnumerable<string> HttpStreamingRequestRaw(string url = null
 		}
 		*/
 
-
-		/// <summary>
-		/// Sends an HTTP request and handles a streaming response.  Does basic line splitting and error handling.
-		/// </summary>
-		/// <param name="url">(optional) If provided, overrides the url endpoint for this request.  If omitted, then <see cref="Url"/> will be used.</param>
-		/// <param name="verb">(optional) The HTTP verb to use, for example "<see cref="HttpMethod.Get"/>".  If omitted, then "GET" is assumed.</param>
-		/// <param name="postData">(optional) A json-serializable object to include in the request body.</param>
-		/// <returns>The HttpResponseMessage of the response, which is confirmed to be successful.</returns>
-		/// <exception cref="HttpRequestException">Throws an exception if a non-success HTTP response was returned</exception>
-		protected async IAsyncEnumerable<T> HttpStreamingRequest<T>(string url = null, HttpMethod verb = null, object postData = null) where T : ApiResultBase
-		{
-			var response = await HttpRequestRaw(url, verb, postData, true);
-					   
-			string organization = null;
-			string requestId = null;
-			TimeSpan processingTime = TimeSpan.Zero;
-			string openaiVersion = null;
-			string modelFromHeaders = null;
-
-			try
-			{
-				organization = response.Headers.GetValues("Openai-Organization").FirstOrDefault();
-				requestId = response.Headers.GetValues("X-Request-ID").FirstOrDefault();
-				processingTime = TimeSpan.FromMilliseconds(int.Parse(response.Headers.GetValues("Openai-Processing-Ms").First()));
-				openaiVersion = response.Headers.GetValues("Openai-Version").FirstOrDefault();
-				modelFromHeaders = response.Headers.GetValues("Openai-Model").FirstOrDefault();
-			}
-			catch (Exception e)
-			{
-				Debug.Print($"Issue parsing metadata of OpenAi Response.  Url: {url}, Error: {e.ToString()}.  This is probably ignorable.");
-			}
-
-			string resultAsString = "";
-
-			using (var stream = await response.Content.ReadAsStreamAsync())
-			using (StreamReader reader = new StreamReader(stream))
-			{
-				string line;
-				while ((line = await reader.ReadLineAsync()) != null)
-				{
-					resultAsString += line + Environment.NewLine;
-
-					if (line.StartsWith("data:"))
-						line = line.Substring("data:".Length);
-
-					line = line.TrimStart();
-
-					if (line == "[DONE]")
-					{
-						yield break;
-					}
-					else if (line.StartsWith(":"))
-					{ }
-					else if (!string.IsNullOrWhiteSpace(line))
-					{
-						var res = JsonConvert.DeserializeObject<T>(line);
-
-						res.Organization = organization;
-						res.RequestId = requestId;
-						res.ProcessingTime = processingTime;
-						res.OpenaiVersion = openaiVersion;
-						if (string.IsNullOrEmpty(res.Model))
-							res.Model = modelFromHeaders;
-
-						yield return res;
-					}
-				}
-			}
-		}
-
-		internal class ApiErrorResponse
-		{
-			/// <summary>
-			/// The error details
-			/// </summary>
-			[JsonProperty("error")]
-			public ApiErrorResponseError Error { get; set; }
-		}
-		internal class ApiErrorResponseError
-		{
-			/// <summary>
-			/// The error message
-			/// </summary>
-			[JsonProperty("message")]
-
-			public string Message { get; set; }
-
-			/// <summary>
-			/// The type of error
-			/// </summary>
-			[JsonProperty("type")]
-			public string ErrorType { get; set; }
-
-			/// <summary>
-			/// The parameter that caused the error
-			/// </summary>
-			[JsonProperty("param")]
-
-			public string Parameter { get; set; }
-
-			/// <summary>
-			/// The error code
-			/// </summary>
-			[JsonProperty("code")]
-			public string ErrorCode { get; set; }
-		}
-	}
+        /// <summary>
+        /// Sends an HTTP request and handles a streaming response.  Does basic line splitting and error handling.
+        /// </summary>
+        /// <param name="url">(optional) If provided, overrides the url endpoint for this request.  If omitted, then <see cref="Url"/> will be used.</param>
+        /// <param name="verb">(optional) The HTTP verb to use, for example "<see cref="HttpMethod.Get"/>".  If omitted, then "GET" is assumed.</param>
+        /// <param name="postData">(optional) A json-serializable object to include in the request body.</param>
+        /// <returns>The HttpResponseMessage of the response, which is confirmed to be successful.</returns>
+        /// <exception cref="HttpRequestException">Throws an exception if a non-success HTTP response was returned</exception>
+        protected async IAsyncEnumerable<T> HttpStreamingRequest<T>(string url = null, HttpMethod verb = null, object postData = null) where T : ApiResultBase
+        {
+            var response = await HttpRequestRaw(url, verb, postData, true);
+
+            string organization = null;
+            string requestId = null;
+            TimeSpan processingTime = TimeSpan.Zero;
+            string openaiVersion = null;
+            string modelFromHeaders = null;
+            var headerNameHolder = "";
+            try
+            {
+                headerNameHolder = "Openai-Organization";
+                organization = response.Headers.GetValues(headerNameHolder).FirstOrDefault();
+
+                headerNameHolder = "X-Request-ID";
+                requestId = response.Headers.GetValues(headerNameHolder).FirstOrDefault();
+
+                headerNameHolder = "Openai-Processing-Ms";
+                processingTime = TimeSpan.FromMilliseconds(int.Parse(response.Headers.GetValues(headerNameHolder).First()));
+
+                headerNameHolder = "Openai-Version";
+                openaiVersion = response.Headers.GetValues(headerNameHolder).FirstOrDefault();
+                
+                headerNameHolder = "Openai-Model";
+                modelFromHeaders = response.Headers.GetValues(headerNameHolder).FirstOrDefault();
+            }
+            catch (Exception e)
+            {
+                Debug.Print($"Issue parsing metadata of OpenAi Response while trying to get header name: {headerNameHolder}.  Url: {url}, Error: {e.ToString()}.  This is probably ignorable. Data gotten so far: organization={organization}, requestId={requestId}, processingTime ={processingTime}, openaiVersion={openaiVersion},modelFromHeaders={modelFromHeaders},");
+
+            }
+
+            string resultAsString = "";
+
+            using (var stream = await response.Content.ReadAsStreamAsync())
+            using (StreamReader reader = new StreamReader(stream))
+            {
+                string line;
+                while ((line = await reader.ReadLineAsync()) != null)
+                {
+                    resultAsString += line + Environment.NewLine;
+
+                    if (line.StartsWith("data:"))
+                        line = line.Substring("data:".Length);
+
+                    line = line.TrimStart();
+
+                    if (line == "[DONE]")
+                    {
+                        yield break;
+                    }
+                    else if (line.StartsWith(":"))
+                    { }
+                    else if (!string.IsNullOrWhiteSpace(line))
+                    {
+                        var res = JsonConvert.DeserializeObject<T>(line);
+
+                        res.Organization = organization;
+                        res.RequestId = requestId;
+                        res.ProcessingTime = processingTime;
+                        res.OpenaiVersion = openaiVersion;
+                        if (string.IsNullOrEmpty(res.Model))
+                            res.Model = modelFromHeaders;
+
+                        yield return res;
+                    }
+                }
+            }
+        }
+
+        internal class ApiErrorResponse
+        {
+            /// <summary>
+            /// The error details
+            /// </summary>
+            [JsonProperty("error")]
+            public ApiErrorResponseError Error { get; set; }
+        }
+        internal class ApiErrorResponseError
+        {
+            /// <summary>
+            /// The error message
+            /// </summary>
+            [JsonProperty("message")]
+
+            public string Message { get; set; }
+
+            /// <summary>
+            /// The type of error
+            /// </summary>
+            [JsonProperty("type")]
+            public string ErrorType { get; set; }
+
+            /// <summary>
+            /// The parameter that caused the error
+            /// </summary>
+            [JsonProperty("param")]
+
+            public string Parameter { get; set; }
+
+            /// <summary>
+            /// The error code
+            /// </summary>
+            [JsonProperty("code")]
+            public string ErrorCode { get; set; }
+        }
+    }
 }
diff --git a/OpenAI_API/Images/ImageResult.cs b/OpenAI_API/Images/ImageResult.cs
index 17e6e87..6817baf 100644
--- a/OpenAI_API/Images/ImageResult.cs
+++ b/OpenAI_API/Images/ImageResult.cs
@@ -49,7 +49,7 @@ public class Data
 		/// The base64-encoded image data as returned by the API
 		/// </summary>
 		[JsonProperty("b64_json")]
-		public string Base64Data { get; set; } 
+		public string Base64Data { get; set; }
 
 		/// <summary>
 		/// The prompt that was used to generate the image, if there was any revision to the prompt.

From eb905171fa0c42d7cc8fe2b3d8b9cbb021e5699b Mon Sep 17 00:00:00 2001
From: Ernie French <efrench@gmail.com>
Date: Fri, 3 May 2024 15:33:54 -0700
Subject: [PATCH 5/5] added vivid.

---
 OpenAI_API/Images/ImageGenerationRequest.cs | 58 ++++++++++++++++-----
 OpenAI_API/OpenAI_API.csproj                |  8 +++
 2 files changed, 52 insertions(+), 14 deletions(-)

diff --git a/OpenAI_API/Images/ImageGenerationRequest.cs b/OpenAI_API/Images/ImageGenerationRequest.cs
index 98a8277..9483053 100644
--- a/OpenAI_API/Images/ImageGenerationRequest.cs
+++ b/OpenAI_API/Images/ImageGenerationRequest.cs
@@ -14,6 +14,7 @@ public class ImageGenerationRequest
 	{
 		private int? numOfImages = 1;
 		private ImageSize size = ImageSize._1024;
+		private string style = "vivid";
 		private string quality = "standard";
 
 		/// <summary>
@@ -65,10 +66,36 @@ public ImageSize Size
 			set => size = value;
 		}
 
-		/// <summary>
-		/// By default, images are generated at `standard` quality, but when using DALL·E 3 you can set quality to `hd` for enhanced detail. Square, standard quality images are the fastest to generate.
-		/// </summary>
-		[JsonProperty("quality", NullValueHandling=NullValueHandling.Ignore)]
+        /// <summary>
+        /// Adding this, upstream is missing this value too. What else is there?? revisedText was VITAL yet not added by upstream yet.
+        /// </summary>
+        [JsonProperty("style", NullValueHandling = NullValueHandling.Ignore)]
+        public string Style
+        {
+            get
+            {
+                return style;
+            }
+            set
+            {
+                switch (value.ToLower().Trim())
+                {
+                    case "vivid":
+                        style = "vivid";
+                        break;
+                    case "natural":
+                        style = "natural";
+                        break;
+                    default:
+                        throw new ArgumentException("Style must be either 'vivid' or 'natural'.");
+                }
+            }
+        }
+
+        /// <summary>
+        /// By default, images are generated at `standard` quality, but when using DALL·E 3 you can set quality to `hd` for enhanced detail. Square, standard quality images are the fastest to generate.
+        /// </summary>
+        [JsonProperty("quality", NullValueHandling=NullValueHandling.Ignore)]
 		public string Quality
 		{
 			get
@@ -109,26 +136,29 @@ public ImageGenerationRequest()
 
 		}
 
-		/// <summary>
-		/// Creates a new <see cref="ImageGenerationRequest"/> with the specified parameters
-		/// </summary>
-		/// <param name="prompt">A text description of the desired image(s). The maximum length is 1000 characters.</param>
-		/// <param name="model">The model to use for this request. Defaults to DALL-E 2.</param>
-		/// <param name="size">The size of the generated images. Must be one of 256x256, 512x512, or 1024x1024.</param>
-		/// <param name="quality">By default, images are generated at `standard` quality, but when using DALL·E 3 you can set quality to `hd` for enhanced detail.</param>
-		/// <param name="user">A unique identifier representing your end-user, which can help OpenAI to monitor and detect abuse.</param>
-		/// <param name="responseFormat">The format in which the generated images are returned. Must be one of url or b64_json.</param>
-		public ImageGenerationRequest(
+        /// <summary>
+        /// Creates a new <see cref="ImageGenerationRequest"/> with the specified parameters
+        /// </summary>
+        /// <param name="prompt">A text description of the desired image(s). The maximum length is 1000 characters.</param>
+        /// <param name="model">The model to use for this request. Defaults to DALL-E 2.</param>
+        /// <param name="size">The size of the generated images. Must be one of 256x256, 512x512, or 1024x1024.</param>
+        /// <param name="quality">By default, images are generated at `standard` quality, but when using DALL·E 3 you can set quality to `hd` for enhanced detail.</param>
+        /// <param name="style">natural or vivid, part of the openAI API</param>
+        /// <param name="user">A unique identifier representing your end-user, which can help OpenAI to monitor and detect abuse.</param>
+        /// <param name="responseFormat">The format in which the generated images are returned. Must be one of url or b64_json.</param>
+        public ImageGenerationRequest(
 			string prompt,
 			Model model,
 			ImageSize size = null,
 			string quality = "standard",
+			string style = "vivid",
 			string user = null,
 			ImageResponseFormat responseFormat = null)
 		{
 			this.Prompt = prompt;
 			this.Model = model ?? OpenAI_API.Models.Model.DALLE2;
 			this.Quality = quality ?? "standard";
+			this.Style = style ?? "vivid";
 			this.User = user;
 			this.Size = size ?? ImageSize._1024;
 			this.ResponseFormat = responseFormat ?? ImageResponseFormat.Url;
diff --git a/OpenAI_API/OpenAI_API.csproj b/OpenAI_API/OpenAI_API.csproj
index 75dc2c3..8f2e9df 100644
--- a/OpenAI_API/OpenAI_API.csproj
+++ b/OpenAI_API/OpenAI_API.csproj
@@ -37,6 +37,14 @@
 		<PackageIcon>nuget_logo.png</PackageIcon>
 	</PropertyGroup>
 
+	<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
+	  <NoWarn>1701;1702;1591</NoWarn>
+	</PropertyGroup>
+
+	<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
+	  <NoWarn>1701;1702;1591</NoWarn>
+	</PropertyGroup>
+
 	<ItemGroup>
 		<None Include="nuget_logo.png" Pack="true" PackagePath="\" />
 	</ItemGroup>