using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Runtime.CompilerServices;
using System.Runtime.ExceptionServices;
using System.Text;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using System.Threading.Tasks.Sources;
using AxCopilot.Models;
using AxCopilot.Services.Agent;

namespace AxCopilot.Services;

public class LlmService : IDisposable
{
	public class ContentBlock
	{
		public string Type { get; init; } = "text";

		public string Text { get; init; } = "";

		public string ToolName { get; init; } = "";

		public string ToolId { get; init; } = "";

		public JsonElement? ToolInput { get; init; }
	}

	[CompilerGenerated]
	private sealed class _003CStreamAsync_003Ed__34 : IAsyncEnumerable<string>, IAsyncEnumerator<string>, IAsyncDisposable, IValueTaskSource<bool>, IValueTaskSource, IAsyncStateMachine
	{
		public int _003C_003E1__state;

		public AsyncIteratorMethodBuilder _003C_003Et__builder;

		public ManualResetValueTaskSourceCore<bool> _003C_003Ev__promiseOfValueOrEnd;

		private string _003C_003E2__current;

		private bool _003C_003Ew__disposeMode;

		private CancellationTokenSource _003C_003Ex__combinedTokens;

		private int _003C_003El__initialThreadId;

		private List<ChatMessage> messages;

		public List<ChatMessage> _003C_003E3__messages;

		private CancellationToken ct;

		public CancellationToken _003C_003E3__ct;

		public LlmService _003C_003E4__this;

		private string _003CactiveService_003E5__1;

		private IAsyncEnumerable<string> _003Cstream_003E5__2;

		private string _003C_003Es__3;

		private ConfiguredCancelableAsyncEnumerable<string>.Enumerator _003C_003Es__4;

		private object _003C_003Es__5;

		private int _003C_003Es__6;

		private string _003Cchunk_003E5__7;

		private bool _003C_003Es__8;

		private ConfiguredValueTaskAwaitable<bool>.ConfiguredValueTaskAwaiter _003C_003Eu__1;

		private ConfiguredValueTaskAwaitable.ConfiguredValueTaskAwaiter _003C_003Eu__2;

		string IAsyncEnumerator<string>.Current
		{
			[DebuggerHidden]
			get
			{
				return _003C_003E2__current;
			}
		}

		[DebuggerHidden]
		public _003CStreamAsync_003Ed__34(int _003C_003E1__state)
		{
			_003C_003Et__builder = AsyncIteratorMethodBuilder.Create();
			this._003C_003E1__state = _003C_003E1__state;
			_003C_003El__initialThreadId = Environment.CurrentManagedThreadId;
		}

		private void MoveNext()
		{
			int num = _003C_003E1__state;
			try
			{
				ConfiguredValueTaskAwaitable.ConfiguredValueTaskAwaiter awaiter;
				switch (num)
				{
				default:
					if (!_003C_003Ew__disposeMode)
					{
						num = (_003C_003E1__state = -1);
						_003CactiveService_003E5__1 = _003C_003E4__this.ResolveService();
						_003C_003Es__3 = _003CactiveService_003E5__1.ToLowerInvariant();
						if (1 == 0)
						{
						}
						IAsyncEnumerable<string> asyncEnumerable = _003C_003Es__3 switch
						{
							"gemini" => _003C_003E4__this.StreamGeminiAsync(messages, ct), 
							"claude" => _003C_003E4__this.StreamClaudeAsync(messages, ct), 
							"vllm" => _003C_003E4__this.StreamOpenAiCompatibleAsync(messages, ct), 
							_ => _003C_003E4__this.StreamOllamaAsync(messages, ct), 
						};
						if (1 == 0)
						{
						}
						_003Cstream_003E5__2 = asyncEnumerable;
						_003C_003Es__3 = null;
						_003C_003Es__4 = _003Cstream_003E5__2.WithCancellation(ct).GetAsyncEnumerator();
						_003C_003Es__5 = null;
						_003C_003Es__6 = 0;
						goto case -4;
					}
					goto end_IL_0007;
				case -4:
				case 0:
					try
					{
						ConfiguredValueTaskAwaitable<bool>.ConfiguredValueTaskAwaiter awaiter2;
						if (num != -4)
						{
							if (num != 0)
							{
								goto IL_01aa;
							}
							awaiter2 = _003C_003Eu__1;
							_003C_003Eu__1 = default(ConfiguredValueTaskAwaitable<bool>.ConfiguredValueTaskAwaiter);
							num = (_003C_003E1__state = -1);
							goto IL_0216;
						}
						num = (_003C_003E1__state = -1);
						if (!_003C_003Ew__disposeMode)
						{
							_003Cchunk_003E5__7 = null;
							goto IL_01aa;
						}
						goto end_IL_014c;
						IL_01aa:
						_003C_003E2__current = null;
						awaiter2 = _003C_003Es__4.MoveNextAsync().GetAwaiter();
						if (!awaiter2.IsCompleted)
						{
							num = (_003C_003E1__state = 0);
							_003C_003Eu__1 = awaiter2;
							_003CStreamAsync_003Ed__34 stateMachine = this;
							_003C_003Et__builder.AwaitUnsafeOnCompleted(ref awaiter2, ref stateMachine);
							return;
						}
						goto IL_0216;
						IL_0216:
						_003C_003Es__8 = awaiter2.GetResult();
						if (_003C_003Es__8)
						{
							_003Cchunk_003E5__7 = _003C_003Es__4.Current;
							_003C_003E2__current = _003Cchunk_003E5__7;
							num = (_003C_003E1__state = -4);
							goto IL_03ef;
						}
						end_IL_014c:;
					}
					catch (object obj)
					{
						_003C_003Es__5 = obj;
					}
					_003C_003E2__current = null;
					awaiter = _003C_003Es__4.DisposeAsync().GetAwaiter();
					if (!awaiter.IsCompleted)
					{
						num = (_003C_003E1__state = 1);
						_003C_003Eu__2 = awaiter;
						_003CStreamAsync_003Ed__34 stateMachine = this;
						_003C_003Et__builder.AwaitUnsafeOnCompleted(ref awaiter, ref stateMachine);
						return;
					}
					break;
				case 1:
					awaiter = _003C_003Eu__2;
					_003C_003Eu__2 = default(ConfiguredValueTaskAwaitable.ConfiguredValueTaskAwaiter);
					num = (_003C_003E1__state = -1);
					break;
				}
				awaiter.GetResult();
				object obj2 = _003C_003Es__5;
				if (obj2 != null)
				{
					if (!(obj2 is Exception source))
					{
						throw obj2;
					}
					ExceptionDispatchInfo.Capture(source).Throw();
				}
				_ = _003C_003Es__6;
				if (!_003C_003Ew__disposeMode)
				{
					_003C_003Es__5 = null;
					_003C_003Es__4 = default(ConfiguredCancelableAsyncEnumerable<string>.Enumerator);
				}
				end_IL_0007:;
			}
			catch (Exception exception)
			{
				_003C_003E1__state = -2;
				_003CactiveService_003E5__1 = null;
				_003Cstream_003E5__2 = null;
				_003C_003Es__3 = null;
				_003C_003Es__4 = default(ConfiguredCancelableAsyncEnumerable<string>.Enumerator);
				_003C_003Es__5 = null;
				_003Cchunk_003E5__7 = null;
				if (_003C_003Ex__combinedTokens != null)
				{
					_003C_003Ex__combinedTokens.Dispose();
					_003C_003Ex__combinedTokens = null;
				}
				_003C_003E2__current = null;
				_003C_003Et__builder.Complete();
				_003C_003Ev__promiseOfValueOrEnd.SetException(exception);
				return;
			}
			_003C_003E1__state = -2;
			_003CactiveService_003E5__1 = null;
			_003Cstream_003E5__2 = null;
			_003C_003Es__3 = null;
			_003C_003Es__4 = default(ConfiguredCancelableAsyncEnumerable<string>.Enumerator);
			_003C_003Es__5 = null;
			_003Cchunk_003E5__7 = null;
			if (_003C_003Ex__combinedTokens != null)
			{
				_003C_003Ex__combinedTokens.Dispose();
				_003C_003Ex__combinedTokens = null;
			}
			_003C_003E2__current = null;
			_003C_003Et__builder.Complete();
			_003C_003Ev__promiseOfValueOrEnd.SetResult(result: false);
			return;
			IL_03ef:
			_003C_003Ev__promiseOfValueOrEnd.SetResult(result: true);
		}

		void IAsyncStateMachine.MoveNext()
		{
			//ILSpy generated this explicit interface implementation from .override directive in MoveNext
			this.MoveNext();
		}

		[DebuggerHidden]
		private void SetStateMachine(IAsyncStateMachine stateMachine)
		{
		}

		void IAsyncStateMachine.SetStateMachine(IAsyncStateMachine stateMachine)
		{
			//ILSpy generated this explicit interface implementation from .override directive in SetStateMachine
			this.SetStateMachine(stateMachine);
		}

		[DebuggerHidden]
		IAsyncEnumerator<string> IAsyncEnumerable<string>.GetAsyncEnumerator(CancellationToken cancellationToken = default(CancellationToken))
		{
			_003CStreamAsync_003Ed__34 _003CStreamAsync_003Ed__;
			if (_003C_003E1__state == -2 && _003C_003El__initialThreadId == Environment.CurrentManagedThreadId)
			{
				_003C_003E1__state = -3;
				_003C_003Et__builder = AsyncIteratorMethodBuilder.Create();
				_003C_003Ew__disposeMode = false;
				_003CStreamAsync_003Ed__ = this;
			}
			else
			{
				_003CStreamAsync_003Ed__ = new _003CStreamAsync_003Ed__34(-3)
				{
					_003C_003E4__this = _003C_003E4__this
				};
			}
			_003CStreamAsync_003Ed__.messages = _003C_003E3__messages;
			if (_003C_003E3__ct.Equals(default(CancellationToken)))
			{
				_003CStreamAsync_003Ed__.ct = cancellationToken;
			}
			else if (cancellationToken.Equals(_003C_003E3__ct) || cancellationToken.Equals(default(CancellationToken)))
			{
				_003CStreamAsync_003Ed__.ct = _003C_003E3__ct;
			}
			else
			{
				_003C_003Ex__combinedTokens = CancellationTokenSource.CreateLinkedTokenSource(_003C_003E3__ct, cancellationToken);
				_003CStreamAsync_003Ed__.ct = _003C_003Ex__combinedTokens.Token;
			}
			return _003CStreamAsync_003Ed__;
		}

		[DebuggerHidden]
		ValueTask<bool> IAsyncEnumerator<string>.MoveNextAsync()
		{
			if (_003C_003E1__state == -2)
			{
				return default(ValueTask<bool>);
			}
			_003C_003Ev__promiseOfValueOrEnd.Reset();
			_003CStreamAsync_003Ed__34 stateMachine = this;
			_003C_003Et__builder.MoveNext(ref stateMachine);
			short version = _003C_003Ev__promiseOfValueOrEnd.Version;
			if (_003C_003Ev__promiseOfValueOrEnd.GetStatus(version) == ValueTaskSourceStatus.Succeeded)
			{
				return new ValueTask<bool>(_003C_003Ev__promiseOfValueOrEnd.GetResult(version));
			}
			return new ValueTask<bool>(this, version);
		}

		[DebuggerHidden]
		bool IValueTaskSource<bool>.GetResult(short token)
		{
			return _003C_003Ev__promiseOfValueOrEnd.GetResult(token);
		}

		[DebuggerHidden]
		ValueTaskSourceStatus IValueTaskSource<bool>.GetStatus(short token)
		{
			return _003C_003Ev__promiseOfValueOrEnd.GetStatus(token);
		}

		[DebuggerHidden]
		void IValueTaskSource<bool>.OnCompleted(Action<object?> continuation, object? state, short token, ValueTaskSourceOnCompletedFlags flags)
		{
			_003C_003Ev__promiseOfValueOrEnd.OnCompleted(continuation, state, token, flags);
		}

		[DebuggerHidden]
		void IValueTaskSource.GetResult(short token)
		{
			_003C_003Ev__promiseOfValueOrEnd.GetResult(token);
		}

		[DebuggerHidden]
		ValueTaskSourceStatus IValueTaskSource.GetStatus(short token)
		{
			return _003C_003Ev__promiseOfValueOrEnd.GetStatus(token);
		}

		[DebuggerHidden]
		void IValueTaskSource.OnCompleted(Action<object?> continuation, object? state, short token, ValueTaskSourceOnCompletedFlags flags)
		{
			_003C_003Ev__promiseOfValueOrEnd.OnCompleted(continuation, state, token, flags);
		}

		[DebuggerHidden]
		ValueTask IAsyncDisposable.DisposeAsync()
		{
			if (_003C_003E1__state >= -1)
			{
				throw new NotSupportedException();
			}
			if (_003C_003E1__state == -2)
			{
				return default(ValueTask);
			}
			_003C_003Ew__disposeMode = true;
			_003C_003Ev__promiseOfValueOrEnd.Reset();
			_003CStreamAsync_003Ed__34 stateMachine = this;
			_003C_003Et__builder.MoveNext(ref stateMachine);
			return new ValueTask(this, _003C_003Ev__promiseOfValueOrEnd.Version);
		}
	}

	[CompilerGenerated]
	private sealed class _003CStreamClaudeAsync_003Ed__46 : IAsyncEnumerable<string>, IAsyncEnumerator<string>, IAsyncDisposable, IValueTaskSource<bool>, IValueTaskSource, IAsyncStateMachine
	{
		public int _003C_003E1__state;

		public AsyncIteratorMethodBuilder _003C_003Et__builder;

		public ManualResetValueTaskSourceCore<bool> _003C_003Ev__promiseOfValueOrEnd;

		private string _003C_003E2__current;

		private bool _003C_003Ew__disposeMode;

		private CancellationTokenSource _003C_003Ex__combinedTokens;

		private int _003C_003El__initialThreadId;

		private List<ChatMessage> messages;

		public List<ChatMessage> _003C_003E3__messages;

		private CancellationToken ct;

		public CancellationToken _003C_003E3__ct;

		public LlmService _003C_003E4__this;

		private LlmSettings _003Cllm_003E5__1;

		private string _003CapiKey_003E5__2;

		private object _003Cbody_003E5__3;

		private string _003Cjson_003E5__4;

		private HttpRequestMessage _003Creq_003E5__5;

		private HttpResponseMessage _003Cresp_003E5__6;

		private Stream _003Cstream_003E5__7;

		private StreamReader _003Creader_003E5__8;

		private HttpResponseMessage _003C_003Es__9;

		private string _003CerrBody_003E5__10;

		private string _003C_003Es__11;

		private Stream _003C_003Es__12;

		private string _003Cline_003E5__13;

		private string _003Cdata_003E5__14;

		private string _003Ctext_003E5__15;

		private string _003C_003Es__16;

		private JsonDocument _003Cdoc_003E5__17;

		private string _003Ctype_003E5__18;

		private JsonElement _003Cdelta_003E5__19;

		private JsonElement _003Ct_003E5__20;

		private JsonElement _003Cmsg_003E5__21;

		private JsonElement _003Cu1_003E5__22;

		private JsonElement _003Cu2_003E5__23;

		private JsonException _003Cex_003E5__24;

		private TaskAwaiter<HttpResponseMessage> _003C_003Eu__1;

		private TaskAwaiter<string> _003C_003Eu__2;

		private TaskAwaiter<Stream> _003C_003Eu__3;

		string IAsyncEnumerator<string>.Current
		{
			[DebuggerHidden]
			get
			{
				return _003C_003E2__current;
			}
		}

		[DebuggerHidden]
		public _003CStreamClaudeAsync_003Ed__46(int _003C_003E1__state)
		{
			_003C_003Et__builder = AsyncIteratorMethodBuilder.Create();
			this._003C_003E1__state = _003C_003E1__state;
			_003C_003El__initialThreadId = Environment.CurrentManagedThreadId;
		}

		private void MoveNext()
		{
			int num = _003C_003E1__state;
			try
			{
				switch (num)
				{
				default:
					if (!_003C_003Ew__disposeMode)
					{
						num = (_003C_003E1__state = -1);
						_003Cllm_003E5__1 = _003C_003E4__this._settings.Settings.Llm;
						_003CapiKey_003E5__2 = _003Cllm_003E5__1.ApiKey;
						if (string.IsNullOrEmpty(_003CapiKey_003E5__2))
						{
							throw new InvalidOperationException("Claude API 키가 설정되지 않았습니다.");
						}
						_003Cbody_003E5__3 = _003C_003E4__this.BuildClaudeBody(messages, stream: true);
						_003Cjson_003E5__4 = JsonSerializer.Serialize(_003Cbody_003E5__3);
						_003Creq_003E5__5 = new HttpRequestMessage(HttpMethod.Post, "https://api.anthropic.com/v1/messages");
						break;
					}
					goto end_IL_0007;
				case -4:
				case 0:
				case 1:
				case 2:
				case 3:
					break;
				}
				try
				{
					TaskAwaiter<HttpResponseMessage> awaiter;
					switch (num)
					{
					default:
						_003Creq_003E5__5.Content = new StringContent(_003Cjson_003E5__4, Encoding.UTF8, "application/json");
						_003Creq_003E5__5.Headers.Add("x-api-key", _003CapiKey_003E5__2);
						_003Creq_003E5__5.Headers.Add("anthropic-version", "2023-06-01");
						_003C_003E2__current = null;
						awaiter = _003C_003E4__this._http.SendAsync(_003Creq_003E5__5, HttpCompletionOption.ResponseHeadersRead, ct).GetAwaiter();
						if (!awaiter.IsCompleted)
						{
							num = (_003C_003E1__state = 0);
							_003C_003Eu__1 = awaiter;
							_003CStreamClaudeAsync_003Ed__46 stateMachine = this;
							_003C_003Et__builder.AwaitUnsafeOnCompleted(ref awaiter, ref stateMachine);
							return;
						}
						goto IL_01d9;
					case 0:
						awaiter = _003C_003Eu__1;
						_003C_003Eu__1 = default(TaskAwaiter<HttpResponseMessage>);
						num = (_003C_003E1__state = -1);
						goto IL_01d9;
					case -4:
					case 1:
					case 2:
					case 3:
						break;
						IL_01d9:
						_003C_003Es__9 = awaiter.GetResult();
						_003Cresp_003E5__6 = _003C_003Es__9;
						_003C_003Es__9 = null;
						break;
					}
					try
					{
						TaskAwaiter<string> awaiter3;
						TaskAwaiter<Stream> awaiter2;
						switch (num)
						{
						default:
							if (!_003Cresp_003E5__6.IsSuccessStatusCode)
							{
								_003C_003E2__current = null;
								awaiter3 = _003Cresp_003E5__6.Content.ReadAsStringAsync(ct).GetAwaiter();
								if (!awaiter3.IsCompleted)
								{
									num = (_003C_003E1__state = 1);
									_003C_003Eu__2 = awaiter3;
									_003CStreamClaudeAsync_003Ed__46 stateMachine = this;
									_003C_003Et__builder.AwaitUnsafeOnCompleted(ref awaiter3, ref stateMachine);
									return;
								}
								goto IL_02ad;
							}
							_003C_003E2__current = null;
							awaiter2 = _003Cresp_003E5__6.Content.ReadAsStreamAsync(ct).GetAwaiter();
							if (!awaiter2.IsCompleted)
							{
								num = (_003C_003E1__state = 2);
								_003C_003Eu__3 = awaiter2;
								_003CStreamClaudeAsync_003Ed__46 stateMachine = this;
								_003C_003Et__builder.AwaitUnsafeOnCompleted(ref awaiter2, ref stateMachine);
								return;
							}
							goto IL_0356;
						case 1:
							awaiter3 = _003C_003Eu__2;
							_003C_003Eu__2 = default(TaskAwaiter<string>);
							num = (_003C_003E1__state = -1);
							goto IL_02ad;
						case 2:
							awaiter2 = _003C_003Eu__3;
							_003C_003Eu__3 = default(TaskAwaiter<Stream>);
							num = (_003C_003E1__state = -1);
							goto IL_0356;
						case -4:
						case 3:
							break;
							IL_02ad:
							_003C_003Es__11 = awaiter3.GetResult();
							_003CerrBody_003E5__10 = _003C_003Es__11;
							_003C_003Es__11 = null;
							throw new HttpRequestException(ClassifyHttpError(_003Cresp_003E5__6, _003CerrBody_003E5__10));
							IL_0356:
							_003C_003Es__12 = awaiter2.GetResult();
							_003Cstream_003E5__7 = _003C_003Es__12;
							_003C_003Es__12 = null;
							break;
						}
						try
						{
							if (num != -4 && num != 3)
							{
								_003Creader_003E5__8 = new StreamReader(_003Cstream_003E5__7);
							}
							try
							{
								TaskAwaiter<string> awaiter4;
								if (num != -4)
								{
									if (num != 3)
									{
										goto IL_071e;
									}
									awaiter4 = _003C_003Eu__2;
									_003C_003Eu__2 = default(TaskAwaiter<string>);
									num = (_003C_003E1__state = -1);
									goto IL_041f;
								}
								num = (_003C_003E1__state = -1);
								if (!_003C_003Ew__disposeMode)
								{
									goto IL_0708;
								}
								goto end_IL_0398;
								IL_0708:
								_003Cline_003E5__13 = null;
								_003Cdata_003E5__14 = null;
								_003Ctext_003E5__15 = null;
								goto IL_071e;
								IL_06c6:
								if (string.IsNullOrEmpty(_003Ctext_003E5__15))
								{
									goto IL_0708;
								}
								_003C_003E2__current = _003Ctext_003E5__15;
								num = (_003C_003E1__state = -4);
								goto IL_0a2d;
								IL_041f:
								_003C_003Es__16 = awaiter4.GetResult();
								_003Cline_003E5__13 = _003C_003Es__16;
								_003C_003Es__16 = null;
								if (_003Cline_003E5__13 != null)
								{
									if (string.IsNullOrEmpty(_003Cline_003E5__13) || !_003Cline_003E5__13.StartsWith("data: "))
									{
										goto IL_071e;
									}
									string text = _003Cline_003E5__13;
									int length = "data: ".Length;
									_003Cdata_003E5__14 = text.Substring(length, text.Length - length);
									_003Ctext_003E5__15 = null;
									try
									{
										_003Cdoc_003E5__17 = JsonDocument.Parse(_003Cdata_003E5__14);
										try
										{
											_003Ctype_003E5__18 = _003Cdoc_003E5__17.RootElement.GetProperty("type").GetString();
											if (_003Ctype_003E5__18 == "content_block_delta")
											{
												_003Cdelta_003E5__19 = _003Cdoc_003E5__17.RootElement.GetProperty("delta");
												if (_003Cdelta_003E5__19.TryGetProperty("text", out _003Ct_003E5__20))
												{
													_003Ctext_003E5__15 = _003Ct_003E5__20.GetString();
												}
												_003Cdelta_003E5__19 = default(JsonElement);
												_003Ct_003E5__20 = default(JsonElement);
											}
											else
											{
												text = _003Ctype_003E5__18;
												if ((text == "message_start" || text == "message_delta") ? true : false)
												{
													if (_003Cdoc_003E5__17.RootElement.TryGetProperty("message", out _003Cmsg_003E5__21) && _003Cmsg_003E5__21.TryGetProperty("usage", out _003Cu1_003E5__22))
													{
														_003C_003E4__this.TryParseClaudeUsageFromElement(_003Cu1_003E5__22);
													}
													else
													{
														if (_003Cdoc_003E5__17.RootElement.TryGetProperty("usage", out _003Cu2_003E5__23))
														{
															_003C_003E4__this.TryParseClaudeUsageFromElement(_003Cu2_003E5__23);
														}
														_003Cu2_003E5__23 = default(JsonElement);
													}
													_003Cmsg_003E5__21 = default(JsonElement);
													_003Cu1_003E5__22 = default(JsonElement);
												}
											}
										}
										finally
										{
											if (num == -1 && _003Cdoc_003E5__17 != null)
											{
												((IDisposable)_003Cdoc_003E5__17).Dispose();
											}
										}
										if (!_003C_003Ew__disposeMode)
										{
											_003Cdoc_003E5__17 = null;
											_003Ctype_003E5__18 = null;
											goto IL_06c6;
										}
									}
									catch (JsonException ex)
									{
										_003Cex_003E5__24 = ex;
										LogService.Warn("Claude 스트리밍 JSON 파싱 오류: " + _003Cex_003E5__24.Message);
										goto IL_06c6;
									}
									goto end_IL_0398;
								}
								goto end_IL_0377;
								IL_071e:
								if (!_003Creader_003E5__8.EndOfStream && !ct.IsCancellationRequested)
								{
									_003C_003E2__current = null;
									awaiter4 = ReadLineWithTimeoutAsync(_003Creader_003E5__8, ct).GetAwaiter();
									if (!awaiter4.IsCompleted)
									{
										num = (_003C_003E1__state = 3);
										_003C_003Eu__2 = awaiter4;
										_003CStreamClaudeAsync_003Ed__46 stateMachine = this;
										_003C_003Et__builder.AwaitUnsafeOnCompleted(ref awaiter4, ref stateMachine);
										return;
									}
									goto IL_041f;
								}
								goto end_IL_0377;
								end_IL_0398:;
							}
							finally
							{
								if (num == -1 && _003Creader_003E5__8 != null)
								{
									((IDisposable)_003Creader_003E5__8).Dispose();
								}
							}
							if (!_003C_003Ew__disposeMode)
							{
							}
							goto IL_0788;
							end_IL_0377:;
						}
						finally
						{
							if (num == -1 && _003Cstream_003E5__7 != null)
							{
								((IDisposable)_003Cstream_003E5__7).Dispose();
							}
						}
						goto end_IL_01fa;
						IL_0788:
						if (!_003C_003Ew__disposeMode)
						{
						}
						goto IL_07ad;
						end_IL_01fa:;
					}
					finally
					{
						if (num == -1 && _003Cresp_003E5__6 != null)
						{
							((IDisposable)_003Cresp_003E5__6).Dispose();
						}
					}
					goto end_IL_00d6;
					IL_07ad:
					if (!_003C_003Ew__disposeMode)
					{
					}
					goto IL_07d2;
					end_IL_00d6:;
				}
				finally
				{
					if (num == -1 && _003Creq_003E5__5 != null)
					{
						((IDisposable)_003Creq_003E5__5).Dispose();
					}
				}
				goto end_IL_0007;
				IL_07d2:
				if (!_003C_003Ew__disposeMode)
				{
					_003Cllm_003E5__1 = null;
					_003CapiKey_003E5__2 = null;
					_003Cbody_003E5__3 = null;
					_003Cjson_003E5__4 = null;
					_003Creq_003E5__5 = null;
					_003Cresp_003E5__6 = null;
					_003Cstream_003E5__7 = null;
					_003Creader_003E5__8 = null;
				}
				end_IL_0007:;
			}
			catch (Exception exception)
			{
				_003C_003E1__state = -2;
				_003Cllm_003E5__1 = null;
				_003CapiKey_003E5__2 = null;
				_003Cbody_003E5__3 = null;
				_003Cjson_003E5__4 = null;
				_003Creq_003E5__5 = null;
				_003Cresp_003E5__6 = null;
				_003Cstream_003E5__7 = null;
				_003Creader_003E5__8 = null;
				_003C_003Es__9 = null;
				_003CerrBody_003E5__10 = null;
				_003C_003Es__11 = null;
				_003C_003Es__12 = null;
				_003Cline_003E5__13 = null;
				_003Cdata_003E5__14 = null;
				_003Ctext_003E5__15 = null;
				_003C_003Es__16 = null;
				_003Cdoc_003E5__17 = null;
				_003Ctype_003E5__18 = null;
				_003Cdelta_003E5__19 = default(JsonElement);
				_003Ct_003E5__20 = default(JsonElement);
				_003Cmsg_003E5__21 = default(JsonElement);
				_003Cu1_003E5__22 = default(JsonElement);
				_003Cu2_003E5__23 = default(JsonElement);
				_003Cex_003E5__24 = null;
				if (_003C_003Ex__combinedTokens != null)
				{
					_003C_003Ex__combinedTokens.Dispose();
					_003C_003Ex__combinedTokens = null;
				}
				_003C_003E2__current = null;
				_003C_003Et__builder.Complete();
				_003C_003Ev__promiseOfValueOrEnd.SetException(exception);
				return;
			}
			_003C_003E1__state = -2;
			_003Cllm_003E5__1 = null;
			_003CapiKey_003E5__2 = null;
			_003Cbody_003E5__3 = null;
			_003Cjson_003E5__4 = null;
			_003Creq_003E5__5 = null;
			_003Cresp_003E5__6 = null;
			_003Cstream_003E5__7 = null;
			_003Creader_003E5__8 = null;
			_003C_003Es__9 = null;
			_003CerrBody_003E5__10 = null;
			_003C_003Es__11 = null;
			_003C_003Es__12 = null;
			_003Cline_003E5__13 = null;
			_003Cdata_003E5__14 = null;
			_003Ctext_003E5__15 = null;
			_003C_003Es__16 = null;
			_003Cdoc_003E5__17 = null;
			_003Ctype_003E5__18 = null;
			_003Cdelta_003E5__19 = default(JsonElement);
			_003Ct_003E5__20 = default(JsonElement);
			_003Cmsg_003E5__21 = default(JsonElement);
			_003Cu1_003E5__22 = default(JsonElement);
			_003Cu2_003E5__23 = default(JsonElement);
			_003Cex_003E5__24 = null;
			if (_003C_003Ex__combinedTokens != null)
			{
				_003C_003Ex__combinedTokens.Dispose();
				_003C_003Ex__combinedTokens = null;
			}
			_003C_003E2__current = null;
			_003C_003Et__builder.Complete();
			_003C_003Ev__promiseOfValueOrEnd.SetResult(result: false);
			return;
			IL_0a2d:
			_003C_003Ev__promiseOfValueOrEnd.SetResult(result: true);
		}

		void IAsyncStateMachine.MoveNext()
		{
			//ILSpy generated this explicit interface implementation from .override directive in MoveNext
			this.MoveNext();
		}

		[DebuggerHidden]
		private void SetStateMachine(IAsyncStateMachine stateMachine)
		{
		}

		void IAsyncStateMachine.SetStateMachine(IAsyncStateMachine stateMachine)
		{
			//ILSpy generated this explicit interface implementation from .override directive in SetStateMachine
			this.SetStateMachine(stateMachine);
		}

		[DebuggerHidden]
		IAsyncEnumerator<string> IAsyncEnumerable<string>.GetAsyncEnumerator(CancellationToken cancellationToken = default(CancellationToken))
		{
			_003CStreamClaudeAsync_003Ed__46 _003CStreamClaudeAsync_003Ed__;
			if (_003C_003E1__state == -2 && _003C_003El__initialThreadId == Environment.CurrentManagedThreadId)
			{
				_003C_003E1__state = -3;
				_003C_003Et__builder = AsyncIteratorMethodBuilder.Create();
				_003C_003Ew__disposeMode = false;
				_003CStreamClaudeAsync_003Ed__ = this;
			}
			else
			{
				_003CStreamClaudeAsync_003Ed__ = new _003CStreamClaudeAsync_003Ed__46(-3)
				{
					_003C_003E4__this = _003C_003E4__this
				};
			}
			_003CStreamClaudeAsync_003Ed__.messages = _003C_003E3__messages;
			if (_003C_003E3__ct.Equals(default(CancellationToken)))
			{
				_003CStreamClaudeAsync_003Ed__.ct = cancellationToken;
			}
			else if (cancellationToken.Equals(_003C_003E3__ct) || cancellationToken.Equals(default(CancellationToken)))
			{
				_003CStreamClaudeAsync_003Ed__.ct = _003C_003E3__ct;
			}
			else
			{
				_003C_003Ex__combinedTokens = CancellationTokenSource.CreateLinkedTokenSource(_003C_003E3__ct, cancellationToken);
				_003CStreamClaudeAsync_003Ed__.ct = _003C_003Ex__combinedTokens.Token;
			}
			return _003CStreamClaudeAsync_003Ed__;
		}

		[DebuggerHidden]
		ValueTask<bool> IAsyncEnumerator<string>.MoveNextAsync()
		{
			if (_003C_003E1__state == -2)
			{
				return default(ValueTask<bool>);
			}
			_003C_003Ev__promiseOfValueOrEnd.Reset();
			_003CStreamClaudeAsync_003Ed__46 stateMachine = this;
			_003C_003Et__builder.MoveNext(ref stateMachine);
			short version = _003C_003Ev__promiseOfValueOrEnd.Version;
			if (_003C_003Ev__promiseOfValueOrEnd.GetStatus(version) == ValueTaskSourceStatus.Succeeded)
			{
				return new ValueTask<bool>(_003C_003Ev__promiseOfValueOrEnd.GetResult(version));
			}
			return new ValueTask<bool>(this, version);
		}

		[DebuggerHidden]
		bool IValueTaskSource<bool>.GetResult(short token)
		{
			return _003C_003Ev__promiseOfValueOrEnd.GetResult(token);
		}

		[DebuggerHidden]
		ValueTaskSourceStatus IValueTaskSource<bool>.GetStatus(short token)
		{
			return _003C_003Ev__promiseOfValueOrEnd.GetStatus(token);
		}

		[DebuggerHidden]
		void IValueTaskSource<bool>.OnCompleted(Action<object?> continuation, object? state, short token, ValueTaskSourceOnCompletedFlags flags)
		{
			_003C_003Ev__promiseOfValueOrEnd.OnCompleted(continuation, state, token, flags);
		}

		[DebuggerHidden]
		void IValueTaskSource.GetResult(short token)
		{
			_003C_003Ev__promiseOfValueOrEnd.GetResult(token);
		}

		[DebuggerHidden]
		ValueTaskSourceStatus IValueTaskSource.GetStatus(short token)
		{
			return _003C_003Ev__promiseOfValueOrEnd.GetStatus(token);
		}

		[DebuggerHidden]
		void IValueTaskSource.OnCompleted(Action<object?> continuation, object? state, short token, ValueTaskSourceOnCompletedFlags flags)
		{
			_003C_003Ev__promiseOfValueOrEnd.OnCompleted(continuation, state, token, flags);
		}

		[DebuggerHidden]
		ValueTask IAsyncDisposable.DisposeAsync()
		{
			if (_003C_003E1__state >= -1)
			{
				throw new NotSupportedException();
			}
			if (_003C_003E1__state == -2)
			{
				return default(ValueTask);
			}
			_003C_003Ew__disposeMode = true;
			_003C_003Ev__promiseOfValueOrEnd.Reset();
			_003CStreamClaudeAsync_003Ed__46 stateMachine = this;
			_003C_003Et__builder.MoveNext(ref stateMachine);
			return new ValueTask(this, _003C_003Ev__promiseOfValueOrEnd.Version);
		}
	}

	[CompilerGenerated]
	private sealed class _003CStreamGeminiAsync_003Ed__43 : IAsyncEnumerable<string>, IAsyncEnumerator<string>, IAsyncDisposable, IValueTaskSource<bool>, IValueTaskSource, IAsyncStateMachine
	{
		public int _003C_003E1__state;

		public AsyncIteratorMethodBuilder _003C_003Et__builder;

		public ManualResetValueTaskSourceCore<bool> _003C_003Ev__promiseOfValueOrEnd;

		private string _003C_003E2__current;

		private bool _003C_003Ew__disposeMode;

		private CancellationTokenSource _003C_003Ex__combinedTokens;

		private int _003C_003El__initialThreadId;

		private List<ChatMessage> messages;

		public List<ChatMessage> _003C_003E3__messages;

		private CancellationToken ct;

		public CancellationToken _003C_003E3__ct;

		public LlmService _003C_003E4__this;

		private LlmSettings _003Cllm_003E5__1;

		private string _003CapiKey_003E5__2;

		private string _003Cmodel_003E5__3;

		private object _003Cbody_003E5__4;

		private string _003Curl_003E5__5;

		private HttpRequestMessage _003Creq_003E5__6;

		private HttpResponseMessage _003Cresp_003E5__7;

		private Stream _003Cstream_003E5__8;

		private StreamReader _003Creader_003E5__9;

		private HttpResponseMessage _003C_003Es__10;

		private Stream _003C_003Es__11;

		private string _003Cline_003E5__12;

		private string _003Cdata_003E5__13;

		private string _003Cparsed_003E5__14;

		private string _003C_003Es__15;

		private JsonDocument _003Cdoc_003E5__16;

		private JsonElement _003Ccandidates_003E5__17;

		private StringBuilder _003Csb_003E5__18;

		private JsonElement _003Cparts_003E5__19;

		private JsonElement.ArrayEnumerator _003C_003Es__20;

		private JsonElement _003Cpart_003E5__21;

		private JsonElement _003Ct_003E5__22;

		private string _003Ctext_003E5__23;

		private JsonException _003Cex_003E5__24;

		private TaskAwaiter<HttpResponseMessage> _003C_003Eu__1;

		private TaskAwaiter<Stream> _003C_003Eu__2;

		private TaskAwaiter<string?> _003C_003Eu__3;

		string IAsyncEnumerator<string>.Current
		{
			[DebuggerHidden]
			get
			{
				return _003C_003E2__current;
			}
		}

		[DebuggerHidden]
		public _003CStreamGeminiAsync_003Ed__43(int _003C_003E1__state)
		{
			_003C_003Et__builder = AsyncIteratorMethodBuilder.Create();
			this._003C_003E1__state = _003C_003E1__state;
			_003C_003El__initialThreadId = Environment.CurrentManagedThreadId;
		}

		private void MoveNext()
		{
			int num = _003C_003E1__state;
			try
			{
				switch (num)
				{
				default:
					if (!_003C_003Ew__disposeMode)
					{
						num = (_003C_003E1__state = -1);
						_003Cllm_003E5__1 = _003C_003E4__this._settings.Settings.Llm;
						_003CapiKey_003E5__2 = _003C_003E4__this.ResolveApiKeyForService("gemini");
						if (string.IsNullOrEmpty(_003CapiKey_003E5__2))
						{
							throw new InvalidOperationException("Gemini API 키가 설정되지 않았습니다.");
						}
						_003Cmodel_003E5__3 = _003C_003E4__this.ResolveModel();
						_003Cbody_003E5__4 = _003C_003E4__this.BuildGeminiBody(messages);
						_003Curl_003E5__5 = "https://generativelanguage.googleapis.com/v1beta/models/" + _003Cmodel_003E5__3 + ":streamGenerateContent?alt=sse&key=" + _003CapiKey_003E5__2;
						_003Creq_003E5__6 = new HttpRequestMessage(HttpMethod.Post, _003Curl_003E5__5)
						{
							Content = JsonContent(_003Cbody_003E5__4)
						};
						break;
					}
					goto end_IL_0007;
				case -4:
				case 0:
				case 1:
				case 2:
					break;
				}
				try
				{
					TaskAwaiter<HttpResponseMessage> awaiter;
					switch (num)
					{
					default:
						_003C_003E2__current = null;
						awaiter = _003C_003E4__this.SendWithErrorClassificationAsync(_003Creq_003E5__6, ct).GetAwaiter();
						if (!awaiter.IsCompleted)
						{
							num = (_003C_003E1__state = 0);
							_003C_003Eu__1 = awaiter;
							_003CStreamGeminiAsync_003Ed__43 stateMachine = this;
							_003C_003Et__builder.AwaitUnsafeOnCompleted(ref awaiter, ref stateMachine);
							return;
						}
						goto IL_01a7;
					case 0:
						awaiter = _003C_003Eu__1;
						_003C_003Eu__1 = default(TaskAwaiter<HttpResponseMessage>);
						num = (_003C_003E1__state = -1);
						goto IL_01a7;
					case -4:
					case 1:
					case 2:
						break;
						IL_01a7:
						_003C_003Es__10 = awaiter.GetResult();
						_003Cresp_003E5__7 = _003C_003Es__10;
						_003C_003Es__10 = null;
						break;
					}
					try
					{
						if (num != -4)
						{
							TaskAwaiter<Stream> awaiter2;
							if (num != 1)
							{
								if (num == 2)
								{
									goto IL_0275;
								}
								_003C_003E2__current = null;
								awaiter2 = _003Cresp_003E5__7.Content.ReadAsStreamAsync(ct).GetAwaiter();
								if (!awaiter2.IsCompleted)
								{
									num = (_003C_003E1__state = 1);
									_003C_003Eu__2 = awaiter2;
									_003CStreamGeminiAsync_003Ed__43 stateMachine = this;
									_003C_003Et__builder.AwaitUnsafeOnCompleted(ref awaiter2, ref stateMachine);
									return;
								}
							}
							else
							{
								awaiter2 = _003C_003Eu__2;
								_003C_003Eu__2 = default(TaskAwaiter<Stream>);
								num = (_003C_003E1__state = -1);
							}
							_003C_003Es__11 = awaiter2.GetResult();
							_003Cstream_003E5__8 = _003C_003Es__11;
							_003C_003Es__11 = null;
						}
						goto IL_0275;
						IL_0699:
						if (!_003C_003Ew__disposeMode)
						{
						}
						goto IL_06be;
						IL_0275:
						try
						{
							if (num != -4 && num != 2)
							{
								_003Creader_003E5__9 = new StreamReader(_003Cstream_003E5__8);
							}
							try
							{
								TaskAwaiter<string> awaiter3;
								if (num != -4)
								{
									if (num != 2)
									{
										goto IL_062f;
									}
									awaiter3 = _003C_003Eu__3;
									_003C_003Eu__3 = default(TaskAwaiter<string>);
									num = (_003C_003E1__state = -1);
									goto IL_031d;
								}
								num = (_003C_003E1__state = -1);
								if (!_003C_003Ew__disposeMode)
								{
									goto IL_0619;
								}
								goto end_IL_0296;
								IL_0619:
								_003Cline_003E5__12 = null;
								_003Cdata_003E5__13 = null;
								_003Cparsed_003E5__14 = null;
								goto IL_062f;
								IL_05dc:
								if (_003Cparsed_003E5__14 == null)
								{
									goto IL_0619;
								}
								_003C_003E2__current = _003Cparsed_003E5__14;
								num = (_003C_003E1__state = -4);
								goto IL_0945;
								IL_031d:
								_003C_003Es__15 = awaiter3.GetResult();
								_003Cline_003E5__12 = _003C_003Es__15;
								_003C_003Es__15 = null;
								if (_003Cline_003E5__12 != null)
								{
									if (!string.IsNullOrEmpty(_003Cline_003E5__12) && _003Cline_003E5__12.StartsWith("data: "))
									{
										string text = _003Cline_003E5__12;
										int length = "data: ".Length;
										_003Cdata_003E5__13 = text.Substring(length, text.Length - length);
										_003Cparsed_003E5__14 = null;
										try
										{
											_003Cdoc_003E5__16 = JsonDocument.Parse(_003Cdata_003E5__13);
											try
											{
												_003C_003E4__this.TryParseGeminiUsage(_003Cdoc_003E5__16.RootElement);
												_003Ccandidates_003E5__17 = _003Cdoc_003E5__16.RootElement.GetProperty("candidates");
												if (_003Ccandidates_003E5__17.GetArrayLength() != 0)
												{
													_003Csb_003E5__18 = new StringBuilder();
													_003Cparts_003E5__19 = _003Ccandidates_003E5__17[0].GetProperty("content").GetProperty("parts");
													_003C_003Es__20 = _003Cparts_003E5__19.EnumerateArray().GetEnumerator();
													try
													{
														while (_003C_003Es__20.MoveNext())
														{
															_003Cpart_003E5__21 = _003C_003Es__20.Current;
															if (_003Cpart_003E5__21.TryGetProperty("text", out _003Ct_003E5__22))
															{
																_003Ctext_003E5__23 = _003Ct_003E5__22.GetString();
																if (!string.IsNullOrEmpty(_003Ctext_003E5__23))
																{
																	_003Csb_003E5__18.Append(_003Ctext_003E5__23);
																}
																_003Ctext_003E5__23 = null;
															}
															_003Ct_003E5__22 = default(JsonElement);
															_003Cpart_003E5__21 = default(JsonElement);
														}
													}
													finally
													{
														if (num == -1)
														{
															((IDisposable)_003C_003Es__20/*cast due to .constrained prefix*/).Dispose();
														}
													}
													if (!_003C_003Ew__disposeMode)
													{
														_003C_003Es__20 = default(JsonElement.ArrayEnumerator);
														if (_003Csb_003E5__18.Length > 0)
														{
															_003Cparsed_003E5__14 = _003Csb_003E5__18.ToString();
														}
													}
													goto IL_057d;
												}
											}
											finally
											{
												if (num == -1 && _003Cdoc_003E5__16 != null)
												{
													((IDisposable)_003Cdoc_003E5__16).Dispose();
												}
											}
											goto end_IL_03b3;
											IL_057d:
											if (!_003C_003Ew__disposeMode)
											{
												_003Cdoc_003E5__16 = null;
												_003Ccandidates_003E5__17 = default(JsonElement);
												_003Csb_003E5__18 = null;
												_003Cparts_003E5__19 = default(JsonElement);
												goto IL_05dc;
											}
											goto end_IL_0296;
											end_IL_03b3:;
										}
										catch (JsonException ex)
										{
											_003Cex_003E5__24 = ex;
											LogService.Warn("Gemini 스트리밍 JSON 파싱 오류: " + _003Cex_003E5__24.Message);
											goto IL_05dc;
										}
									}
									goto IL_062f;
								}
								goto end_IL_0275;
								IL_062f:
								if (!_003Creader_003E5__9.EndOfStream && !ct.IsCancellationRequested)
								{
									_003C_003E2__current = null;
									awaiter3 = ReadLineWithTimeoutAsync(_003Creader_003E5__9, ct).GetAwaiter();
									if (!awaiter3.IsCompleted)
									{
										num = (_003C_003E1__state = 2);
										_003C_003Eu__3 = awaiter3;
										_003CStreamGeminiAsync_003Ed__43 stateMachine = this;
										_003C_003Et__builder.AwaitUnsafeOnCompleted(ref awaiter3, ref stateMachine);
										return;
									}
									goto IL_031d;
								}
								goto end_IL_0275;
								end_IL_0296:;
							}
							finally
							{
								if (num == -1 && _003Creader_003E5__9 != null)
								{
									((IDisposable)_003Creader_003E5__9).Dispose();
								}
							}
							if (!_003C_003Ew__disposeMode)
							{
							}
							goto IL_0699;
							end_IL_0275:;
						}
						finally
						{
							if (num == -1 && _003Cstream_003E5__8 != null)
							{
								((IDisposable)_003Cstream_003E5__8).Dispose();
							}
						}
					}
					finally
					{
						if (num == -1 && _003Cresp_003E5__7 != null)
						{
							((IDisposable)_003Cresp_003E5__7).Dispose();
						}
					}
					goto end_IL_0109;
					IL_06be:
					if (!_003C_003Ew__disposeMode)
					{
					}
					goto IL_06e3;
					end_IL_0109:;
				}
				finally
				{
					if (num == -1 && _003Creq_003E5__6 != null)
					{
						((IDisposable)_003Creq_003E5__6).Dispose();
					}
				}
				goto end_IL_0007;
				IL_06e3:
				if (!_003C_003Ew__disposeMode)
				{
					_003Cllm_003E5__1 = null;
					_003CapiKey_003E5__2 = null;
					_003Cmodel_003E5__3 = null;
					_003Cbody_003E5__4 = null;
					_003Curl_003E5__5 = null;
					_003Creq_003E5__6 = null;
					_003Cresp_003E5__7 = null;
					_003Cstream_003E5__8 = null;
					_003Creader_003E5__9 = null;
				}
				end_IL_0007:;
			}
			catch (Exception exception)
			{
				_003C_003E1__state = -2;
				_003Cllm_003E5__1 = null;
				_003CapiKey_003E5__2 = null;
				_003Cmodel_003E5__3 = null;
				_003Cbody_003E5__4 = null;
				_003Curl_003E5__5 = null;
				_003Creq_003E5__6 = null;
				_003Cresp_003E5__7 = null;
				_003Cstream_003E5__8 = null;
				_003Creader_003E5__9 = null;
				_003C_003Es__10 = null;
				_003C_003Es__11 = null;
				_003Cline_003E5__12 = null;
				_003Cdata_003E5__13 = null;
				_003Cparsed_003E5__14 = null;
				_003C_003Es__15 = null;
				_003Cdoc_003E5__16 = null;
				_003Ccandidates_003E5__17 = default(JsonElement);
				_003Csb_003E5__18 = null;
				_003Cparts_003E5__19 = default(JsonElement);
				_003C_003Es__20 = default(JsonElement.ArrayEnumerator);
				_003Cpart_003E5__21 = default(JsonElement);
				_003Ct_003E5__22 = default(JsonElement);
				_003Ctext_003E5__23 = null;
				_003Cex_003E5__24 = null;
				if (_003C_003Ex__combinedTokens != null)
				{
					_003C_003Ex__combinedTokens.Dispose();
					_003C_003Ex__combinedTokens = null;
				}
				_003C_003E2__current = null;
				_003C_003Et__builder.Complete();
				_003C_003Ev__promiseOfValueOrEnd.SetException(exception);
				return;
			}
			_003C_003E1__state = -2;
			_003Cllm_003E5__1 = null;
			_003CapiKey_003E5__2 = null;
			_003Cmodel_003E5__3 = null;
			_003Cbody_003E5__4 = null;
			_003Curl_003E5__5 = null;
			_003Creq_003E5__6 = null;
			_003Cresp_003E5__7 = null;
			_003Cstream_003E5__8 = null;
			_003Creader_003E5__9 = null;
			_003C_003Es__10 = null;
			_003C_003Es__11 = null;
			_003Cline_003E5__12 = null;
			_003Cdata_003E5__13 = null;
			_003Cparsed_003E5__14 = null;
			_003C_003Es__15 = null;
			_003Cdoc_003E5__16 = null;
			_003Ccandidates_003E5__17 = default(JsonElement);
			_003Csb_003E5__18 = null;
			_003Cparts_003E5__19 = default(JsonElement);
			_003C_003Es__20 = default(JsonElement.ArrayEnumerator);
			_003Cpart_003E5__21 = default(JsonElement);
			_003Ct_003E5__22 = default(JsonElement);
			_003Ctext_003E5__23 = null;
			_003Cex_003E5__24 = null;
			if (_003C_003Ex__combinedTokens != null)
			{
				_003C_003Ex__combinedTokens.Dispose();
				_003C_003Ex__combinedTokens = null;
			}
			_003C_003E2__current = null;
			_003C_003Et__builder.Complete();
			_003C_003Ev__promiseOfValueOrEnd.SetResult(result: false);
			return;
			IL_0945:
			_003C_003Ev__promiseOfValueOrEnd.SetResult(result: true);
		}

		void IAsyncStateMachine.MoveNext()
		{
			//ILSpy generated this explicit interface implementation from .override directive in MoveNext
			this.MoveNext();
		}

		[DebuggerHidden]
		private void SetStateMachine(IAsyncStateMachine stateMachine)
		{
		}

		void IAsyncStateMachine.SetStateMachine(IAsyncStateMachine stateMachine)
		{
			//ILSpy generated this explicit interface implementation from .override directive in SetStateMachine
			this.SetStateMachine(stateMachine);
		}

		[DebuggerHidden]
		IAsyncEnumerator<string> IAsyncEnumerable<string>.GetAsyncEnumerator(CancellationToken cancellationToken = default(CancellationToken))
		{
			_003CStreamGeminiAsync_003Ed__43 _003CStreamGeminiAsync_003Ed__;
			if (_003C_003E1__state == -2 && _003C_003El__initialThreadId == Environment.CurrentManagedThreadId)
			{
				_003C_003E1__state = -3;
				_003C_003Et__builder = AsyncIteratorMethodBuilder.Create();
				_003C_003Ew__disposeMode = false;
				_003CStreamGeminiAsync_003Ed__ = this;
			}
			else
			{
				_003CStreamGeminiAsync_003Ed__ = new _003CStreamGeminiAsync_003Ed__43(-3)
				{
					_003C_003E4__this = _003C_003E4__this
				};
			}
			_003CStreamGeminiAsync_003Ed__.messages = _003C_003E3__messages;
			if (_003C_003E3__ct.Equals(default(CancellationToken)))
			{
				_003CStreamGeminiAsync_003Ed__.ct = cancellationToken;
			}
			else if (cancellationToken.Equals(_003C_003E3__ct) || cancellationToken.Equals(default(CancellationToken)))
			{
				_003CStreamGeminiAsync_003Ed__.ct = _003C_003E3__ct;
			}
			else
			{
				_003C_003Ex__combinedTokens = CancellationTokenSource.CreateLinkedTokenSource(_003C_003E3__ct, cancellationToken);
				_003CStreamGeminiAsync_003Ed__.ct = _003C_003Ex__combinedTokens.Token;
			}
			return _003CStreamGeminiAsync_003Ed__;
		}

		[DebuggerHidden]
		ValueTask<bool> IAsyncEnumerator<string>.MoveNextAsync()
		{
			if (_003C_003E1__state == -2)
			{
				return default(ValueTask<bool>);
			}
			_003C_003Ev__promiseOfValueOrEnd.Reset();
			_003CStreamGeminiAsync_003Ed__43 stateMachine = this;
			_003C_003Et__builder.MoveNext(ref stateMachine);
			short version = _003C_003Ev__promiseOfValueOrEnd.Version;
			if (_003C_003Ev__promiseOfValueOrEnd.GetStatus(version) == ValueTaskSourceStatus.Succeeded)
			{
				return new ValueTask<bool>(_003C_003Ev__promiseOfValueOrEnd.GetResult(version));
			}
			return new ValueTask<bool>(this, version);
		}

		[DebuggerHidden]
		bool IValueTaskSource<bool>.GetResult(short token)
		{
			return _003C_003Ev__promiseOfValueOrEnd.GetResult(token);
		}

		[DebuggerHidden]
		ValueTaskSourceStatus IValueTaskSource<bool>.GetStatus(short token)
		{
			return _003C_003Ev__promiseOfValueOrEnd.GetStatus(token);
		}

		[DebuggerHidden]
		void IValueTaskSource<bool>.OnCompleted(Action<object?> continuation, object? state, short token, ValueTaskSourceOnCompletedFlags flags)
		{
			_003C_003Ev__promiseOfValueOrEnd.OnCompleted(continuation, state, token, flags);
		}

		[DebuggerHidden]
		void IValueTaskSource.GetResult(short token)
		{
			_003C_003Ev__promiseOfValueOrEnd.GetResult(token);
		}

		[DebuggerHidden]
		ValueTaskSourceStatus IValueTaskSource.GetStatus(short token)
		{
			return _003C_003Ev__promiseOfValueOrEnd.GetStatus(token);
		}

		[DebuggerHidden]
		void IValueTaskSource.OnCompleted(Action<object?> continuation, object? state, short token, ValueTaskSourceOnCompletedFlags flags)
		{
			_003C_003Ev__promiseOfValueOrEnd.OnCompleted(continuation, state, token, flags);
		}

		[DebuggerHidden]
		ValueTask IAsyncDisposable.DisposeAsync()
		{
			if (_003C_003E1__state >= -1)
			{
				throw new NotSupportedException();
			}
			if (_003C_003E1__state == -2)
			{
				return default(ValueTask);
			}
			_003C_003Ew__disposeMode = true;
			_003C_003Ev__promiseOfValueOrEnd.Reset();
			_003CStreamGeminiAsync_003Ed__43 stateMachine = this;
			_003C_003Et__builder.MoveNext(ref stateMachine);
			return new ValueTask(this, _003C_003Ev__promiseOfValueOrEnd.Version);
		}
	}

	[CompilerGenerated]
	private sealed class _003CStreamOllamaAsync_003Ed__37 : IAsyncEnumerable<string>, IAsyncEnumerator<string>, IAsyncDisposable, IValueTaskSource<bool>, IValueTaskSource, IAsyncStateMachine
	{
		public int _003C_003E1__state;

		public AsyncIteratorMethodBuilder _003C_003Et__builder;

		public ManualResetValueTaskSourceCore<bool> _003C_003Ev__promiseOfValueOrEnd;

		private string _003C_003E2__current;

		private bool _003C_003Ew__disposeMode;

		private CancellationTokenSource _003C_003Ex__combinedTokens;

		private int _003C_003El__initialThreadId;

		private List<ChatMessage> messages;

		public List<ChatMessage> _003C_003E3__messages;

		private CancellationToken ct;

		public CancellationToken _003C_003E3__ct;

		public LlmService _003C_003E4__this;

		private LlmSettings _003Cllm_003E5__1;

		private string _003Cendpoint_003E5__2;

		private string _003Cep_003E5__3;

		private object _003Cbody_003E5__4;

		private string _003Curl_003E5__5;

		private HttpRequestMessage _003Creq_003E5__6;

		private HttpResponseMessage _003Cresp_003E5__7;

		private Stream _003Cstream_003E5__8;

		private StreamReader _003Creader_003E5__9;

		private HttpResponseMessage _003C_003Es__10;

		private Stream _003C_003Es__11;

		private string _003Cline_003E5__12;

		private string _003Ctext_003E5__13;

		private string _003C_003Es__14;

		private JsonDocument _003Cdoc_003E5__15;

		private JsonElement _003Cmsg_003E5__16;

		private JsonElement _003Cc_003E5__17;

		private JsonElement _003Cdone_003E5__18;

		private JsonException _003Cex_003E5__19;

		private TaskAwaiter<HttpResponseMessage> _003C_003Eu__1;

		private TaskAwaiter<Stream> _003C_003Eu__2;

		private TaskAwaiter<string?> _003C_003Eu__3;

		string IAsyncEnumerator<string>.Current
		{
			[DebuggerHidden]
			get
			{
				return _003C_003E2__current;
			}
		}

		[DebuggerHidden]
		public _003CStreamOllamaAsync_003Ed__37(int _003C_003E1__state)
		{
			_003C_003Et__builder = AsyncIteratorMethodBuilder.Create();
			this._003C_003E1__state = _003C_003E1__state;
			_003C_003El__initialThreadId = Environment.CurrentManagedThreadId;
		}

		private void MoveNext()
		{
			int num = _003C_003E1__state;
			try
			{
				switch (num)
				{
				default:
					if (!_003C_003Ew__disposeMode)
					{
						num = (_003C_003E1__state = -1);
						_003Cllm_003E5__1 = _003C_003E4__this._settings.Settings.Llm;
						_003Cendpoint_003E5__2 = _003C_003E4__this.ResolveServerInfo().Endpoint;
						_003Cep_003E5__3 = (string.IsNullOrEmpty(_003Cendpoint_003E5__2) ? _003Cllm_003E5__1.Endpoint : _003Cendpoint_003E5__2);
						_003Cbody_003E5__4 = _003C_003E4__this.BuildOllamaBody(messages, stream: true);
						_003Curl_003E5__5 = _003Cep_003E5__3.TrimEnd('/') + "/api/chat";
						_003Creq_003E5__6 = new HttpRequestMessage(HttpMethod.Post, _003Curl_003E5__5)
						{
							Content = JsonContent(_003Cbody_003E5__4)
						};
						break;
					}
					goto end_IL_0007;
				case -4:
				case 0:
				case 1:
				case 2:
					break;
				}
				try
				{
					TaskAwaiter<HttpResponseMessage> awaiter;
					switch (num)
					{
					default:
						_003C_003E2__current = null;
						awaiter = _003C_003E4__this.SendWithErrorClassificationAsync(_003Creq_003E5__6, ct).GetAwaiter();
						if (!awaiter.IsCompleted)
						{
							num = (_003C_003E1__state = 0);
							_003C_003Eu__1 = awaiter;
							_003CStreamOllamaAsync_003Ed__37 stateMachine = this;
							_003C_003Et__builder.AwaitUnsafeOnCompleted(ref awaiter, ref stateMachine);
							return;
						}
						goto IL_01a1;
					case 0:
						awaiter = _003C_003Eu__1;
						_003C_003Eu__1 = default(TaskAwaiter<HttpResponseMessage>);
						num = (_003C_003E1__state = -1);
						goto IL_01a1;
					case -4:
					case 1:
					case 2:
						break;
						IL_01a1:
						_003C_003Es__10 = awaiter.GetResult();
						_003Cresp_003E5__7 = _003C_003Es__10;
						_003C_003Es__10 = null;
						break;
					}
					try
					{
						if (num != -4)
						{
							TaskAwaiter<Stream> awaiter2;
							if (num != 1)
							{
								if (num == 2)
								{
									goto IL_026f;
								}
								_003C_003E2__current = null;
								awaiter2 = _003Cresp_003E5__7.Content.ReadAsStreamAsync(ct).GetAwaiter();
								if (!awaiter2.IsCompleted)
								{
									num = (_003C_003E1__state = 1);
									_003C_003Eu__2 = awaiter2;
									_003CStreamOllamaAsync_003Ed__37 stateMachine = this;
									_003C_003Et__builder.AwaitUnsafeOnCompleted(ref awaiter2, ref stateMachine);
									return;
								}
							}
							else
							{
								awaiter2 = _003C_003Eu__2;
								_003C_003Eu__2 = default(TaskAwaiter<Stream>);
								num = (_003C_003E1__state = -1);
							}
							_003C_003Es__11 = awaiter2.GetResult();
							_003Cstream_003E5__8 = _003C_003Es__11;
							_003C_003Es__11 = null;
						}
						goto IL_026f;
						IL_055b:
						if (!_003C_003Ew__disposeMode)
						{
						}
						goto IL_0580;
						IL_026f:
						try
						{
							if (num != -4 && num != 2)
							{
								_003Creader_003E5__9 = new StreamReader(_003Cstream_003E5__8);
							}
							try
							{
								TaskAwaiter<string> awaiter3;
								if (num != -4)
								{
									if (num != 2)
									{
										goto IL_04f1;
									}
									awaiter3 = _003C_003Eu__3;
									_003C_003Eu__3 = default(TaskAwaiter<string>);
									num = (_003C_003E1__state = -1);
									goto IL_0317;
								}
								num = (_003C_003E1__state = -1);
								if (!_003C_003Ew__disposeMode)
								{
									goto IL_04e2;
								}
								goto end_IL_0290;
								IL_04a0:
								if (string.IsNullOrEmpty(_003Ctext_003E5__13))
								{
									goto IL_04e2;
								}
								_003C_003E2__current = _003Ctext_003E5__13;
								num = (_003C_003E1__state = -4);
								goto IL_07ad;
								IL_04e2:
								_003Cline_003E5__12 = null;
								_003Ctext_003E5__13 = null;
								goto IL_04f1;
								IL_0317:
								_003C_003Es__14 = awaiter3.GetResult();
								_003Cline_003E5__12 = _003C_003Es__14;
								_003C_003Es__14 = null;
								if (_003Cline_003E5__12 != null)
								{
									if (string.IsNullOrEmpty(_003Cline_003E5__12))
									{
										goto IL_04f1;
									}
									_003Ctext_003E5__13 = null;
									try
									{
										_003Cdoc_003E5__15 = JsonDocument.Parse(_003Cline_003E5__12);
										try
										{
											if (_003Cdoc_003E5__15.RootElement.TryGetProperty("message", out _003Cmsg_003E5__16) && _003Cmsg_003E5__16.TryGetProperty("content", out _003Cc_003E5__17))
											{
												_003Ctext_003E5__13 = _003Cc_003E5__17.GetString();
											}
											if (_003Cdoc_003E5__15.RootElement.TryGetProperty("done", out _003Cdone_003E5__18) && _003Cdone_003E5__18.GetBoolean())
											{
												_003C_003E4__this.TryParseOllamaUsage(_003Cdoc_003E5__15.RootElement);
											}
										}
										finally
										{
											if (num == -1 && _003Cdoc_003E5__15 != null)
											{
												((IDisposable)_003Cdoc_003E5__15).Dispose();
											}
										}
										if (!_003C_003Ew__disposeMode)
										{
											_003Cdoc_003E5__15 = null;
											_003Cmsg_003E5__16 = default(JsonElement);
											_003Cc_003E5__17 = default(JsonElement);
											_003Cdone_003E5__18 = default(JsonElement);
											goto IL_04a0;
										}
									}
									catch (JsonException ex)
									{
										_003Cex_003E5__19 = ex;
										LogService.Warn("Ollama 스트리밍 JSON 파싱 오류: " + _003Cex_003E5__19.Message);
										goto IL_04a0;
									}
									goto end_IL_0290;
								}
								goto end_IL_026f;
								IL_04f1:
								if (!_003Creader_003E5__9.EndOfStream && !ct.IsCancellationRequested)
								{
									_003C_003E2__current = null;
									awaiter3 = ReadLineWithTimeoutAsync(_003Creader_003E5__9, ct).GetAwaiter();
									if (!awaiter3.IsCompleted)
									{
										num = (_003C_003E1__state = 2);
										_003C_003Eu__3 = awaiter3;
										_003CStreamOllamaAsync_003Ed__37 stateMachine = this;
										_003C_003Et__builder.AwaitUnsafeOnCompleted(ref awaiter3, ref stateMachine);
										return;
									}
									goto IL_0317;
								}
								goto end_IL_026f;
								end_IL_0290:;
							}
							finally
							{
								if (num == -1 && _003Creader_003E5__9 != null)
								{
									((IDisposable)_003Creader_003E5__9).Dispose();
								}
							}
							if (!_003C_003Ew__disposeMode)
							{
							}
							goto IL_055b;
							end_IL_026f:;
						}
						finally
						{
							if (num == -1 && _003Cstream_003E5__8 != null)
							{
								((IDisposable)_003Cstream_003E5__8).Dispose();
							}
						}
					}
					finally
					{
						if (num == -1 && _003Cresp_003E5__7 != null)
						{
							((IDisposable)_003Cresp_003E5__7).Dispose();
						}
					}
					goto end_IL_0103;
					IL_0580:
					if (!_003C_003Ew__disposeMode)
					{
					}
					goto IL_05a5;
					end_IL_0103:;
				}
				finally
				{
					if (num == -1 && _003Creq_003E5__6 != null)
					{
						((IDisposable)_003Creq_003E5__6).Dispose();
					}
				}
				goto end_IL_0007;
				IL_05a5:
				if (!_003C_003Ew__disposeMode)
				{
					_003Cllm_003E5__1 = null;
					_003Cendpoint_003E5__2 = null;
					_003Cep_003E5__3 = null;
					_003Cbody_003E5__4 = null;
					_003Curl_003E5__5 = null;
					_003Creq_003E5__6 = null;
					_003Cresp_003E5__7 = null;
					_003Cstream_003E5__8 = null;
					_003Creader_003E5__9 = null;
				}
				end_IL_0007:;
			}
			catch (Exception exception)
			{
				_003C_003E1__state = -2;
				_003Cllm_003E5__1 = null;
				_003Cendpoint_003E5__2 = null;
				_003Cep_003E5__3 = null;
				_003Cbody_003E5__4 = null;
				_003Curl_003E5__5 = null;
				_003Creq_003E5__6 = null;
				_003Cresp_003E5__7 = null;
				_003Cstream_003E5__8 = null;
				_003Creader_003E5__9 = null;
				_003C_003Es__10 = null;
				_003C_003Es__11 = null;
				_003Cline_003E5__12 = null;
				_003Ctext_003E5__13 = null;
				_003C_003Es__14 = null;
				_003Cdoc_003E5__15 = null;
				_003Cmsg_003E5__16 = default(JsonElement);
				_003Cc_003E5__17 = default(JsonElement);
				_003Cdone_003E5__18 = default(JsonElement);
				_003Cex_003E5__19 = null;
				if (_003C_003Ex__combinedTokens != null)
				{
					_003C_003Ex__combinedTokens.Dispose();
					_003C_003Ex__combinedTokens = null;
				}
				_003C_003E2__current = null;
				_003C_003Et__builder.Complete();
				_003C_003Ev__promiseOfValueOrEnd.SetException(exception);
				return;
			}
			_003C_003E1__state = -2;
			_003Cllm_003E5__1 = null;
			_003Cendpoint_003E5__2 = null;
			_003Cep_003E5__3 = null;
			_003Cbody_003E5__4 = null;
			_003Curl_003E5__5 = null;
			_003Creq_003E5__6 = null;
			_003Cresp_003E5__7 = null;
			_003Cstream_003E5__8 = null;
			_003Creader_003E5__9 = null;
			_003C_003Es__10 = null;
			_003C_003Es__11 = null;
			_003Cline_003E5__12 = null;
			_003Ctext_003E5__13 = null;
			_003C_003Es__14 = null;
			_003Cdoc_003E5__15 = null;
			_003Cmsg_003E5__16 = default(JsonElement);
			_003Cc_003E5__17 = default(JsonElement);
			_003Cdone_003E5__18 = default(JsonElement);
			_003Cex_003E5__19 = null;
			if (_003C_003Ex__combinedTokens != null)
			{
				_003C_003Ex__combinedTokens.Dispose();
				_003C_003Ex__combinedTokens = null;
			}
			_003C_003E2__current = null;
			_003C_003Et__builder.Complete();
			_003C_003Ev__promiseOfValueOrEnd.SetResult(result: false);
			return;
			IL_07ad:
			_003C_003Ev__promiseOfValueOrEnd.SetResult(result: true);
		}

		void IAsyncStateMachine.MoveNext()
		{
			//ILSpy generated this explicit interface implementation from .override directive in MoveNext
			this.MoveNext();
		}

		[DebuggerHidden]
		private void SetStateMachine(IAsyncStateMachine stateMachine)
		{
		}

		void IAsyncStateMachine.SetStateMachine(IAsyncStateMachine stateMachine)
		{
			//ILSpy generated this explicit interface implementation from .override directive in SetStateMachine
			this.SetStateMachine(stateMachine);
		}

		[DebuggerHidden]
		IAsyncEnumerator<string> IAsyncEnumerable<string>.GetAsyncEnumerator(CancellationToken cancellationToken = default(CancellationToken))
		{
			_003CStreamOllamaAsync_003Ed__37 _003CStreamOllamaAsync_003Ed__;
			if (_003C_003E1__state == -2 && _003C_003El__initialThreadId == Environment.CurrentManagedThreadId)
			{
				_003C_003E1__state = -3;
				_003C_003Et__builder = AsyncIteratorMethodBuilder.Create();
				_003C_003Ew__disposeMode = false;
				_003CStreamOllamaAsync_003Ed__ = this;
			}
			else
			{
				_003CStreamOllamaAsync_003Ed__ = new _003CStreamOllamaAsync_003Ed__37(-3)
				{
					_003C_003E4__this = _003C_003E4__this
				};
			}
			_003CStreamOllamaAsync_003Ed__.messages = _003C_003E3__messages;
			if (_003C_003E3__ct.Equals(default(CancellationToken)))
			{
				_003CStreamOllamaAsync_003Ed__.ct = cancellationToken;
			}
			else if (cancellationToken.Equals(_003C_003E3__ct) || cancellationToken.Equals(default(CancellationToken)))
			{
				_003CStreamOllamaAsync_003Ed__.ct = _003C_003E3__ct;
			}
			else
			{
				_003C_003Ex__combinedTokens = CancellationTokenSource.CreateLinkedTokenSource(_003C_003E3__ct, cancellationToken);
				_003CStreamOllamaAsync_003Ed__.ct = _003C_003Ex__combinedTokens.Token;
			}
			return _003CStreamOllamaAsync_003Ed__;
		}

		[DebuggerHidden]
		ValueTask<bool> IAsyncEnumerator<string>.MoveNextAsync()
		{
			if (_003C_003E1__state == -2)
			{
				return default(ValueTask<bool>);
			}
			_003C_003Ev__promiseOfValueOrEnd.Reset();
			_003CStreamOllamaAsync_003Ed__37 stateMachine = this;
			_003C_003Et__builder.MoveNext(ref stateMachine);
			short version = _003C_003Ev__promiseOfValueOrEnd.Version;
			if (_003C_003Ev__promiseOfValueOrEnd.GetStatus(version) == ValueTaskSourceStatus.Succeeded)
			{
				return new ValueTask<bool>(_003C_003Ev__promiseOfValueOrEnd.GetResult(version));
			}
			return new ValueTask<bool>(this, version);
		}

		[DebuggerHidden]
		bool IValueTaskSource<bool>.GetResult(short token)
		{
			return _003C_003Ev__promiseOfValueOrEnd.GetResult(token);
		}

		[DebuggerHidden]
		ValueTaskSourceStatus IValueTaskSource<bool>.GetStatus(short token)
		{
			return _003C_003Ev__promiseOfValueOrEnd.GetStatus(token);
		}

		[DebuggerHidden]
		void IValueTaskSource<bool>.OnCompleted(Action<object?> continuation, object? state, short token, ValueTaskSourceOnCompletedFlags flags)
		{
			_003C_003Ev__promiseOfValueOrEnd.OnCompleted(continuation, state, token, flags);
		}

		[DebuggerHidden]
		void IValueTaskSource.GetResult(short token)
		{
			_003C_003Ev__promiseOfValueOrEnd.GetResult(token);
		}

		[DebuggerHidden]
		ValueTaskSourceStatus IValueTaskSource.GetStatus(short token)
		{
			return _003C_003Ev__promiseOfValueOrEnd.GetStatus(token);
		}

		[DebuggerHidden]
		void IValueTaskSource.OnCompleted(Action<object?> continuation, object? state, short token, ValueTaskSourceOnCompletedFlags flags)
		{
			_003C_003Ev__promiseOfValueOrEnd.OnCompleted(continuation, state, token, flags);
		}

		[DebuggerHidden]
		ValueTask IAsyncDisposable.DisposeAsync()
		{
			if (_003C_003E1__state >= -1)
			{
				throw new NotSupportedException();
			}
			if (_003C_003E1__state == -2)
			{
				return default(ValueTask);
			}
			_003C_003Ew__disposeMode = true;
			_003C_003Ev__promiseOfValueOrEnd.Reset();
			_003CStreamOllamaAsync_003Ed__37 stateMachine = this;
			_003C_003Et__builder.MoveNext(ref stateMachine);
			return new ValueTask(this, _003C_003Ev__promiseOfValueOrEnd.Version);
		}
	}

	[CompilerGenerated]
	private sealed class _003CStreamOpenAiCompatibleAsync_003Ed__40 : IAsyncEnumerable<string>, IAsyncEnumerator<string>, IAsyncDisposable, IValueTaskSource<bool>, IValueTaskSource, IAsyncStateMachine
	{
		public int _003C_003E1__state;

		public AsyncIteratorMethodBuilder _003C_003Et__builder;

		public ManualResetValueTaskSourceCore<bool> _003C_003Ev__promiseOfValueOrEnd;

		private string _003C_003E2__current;

		private bool _003C_003Ew__disposeMode;

		private CancellationTokenSource _003C_003Ex__combinedTokens;

		private int _003C_003El__initialThreadId;

		private List<ChatMessage> messages;

		public List<ChatMessage> _003C_003E3__messages;

		private CancellationToken ct;

		public CancellationToken _003C_003E3__ct;

		public LlmService _003C_003E4__this;

		private LlmSettings _003Cllm_003E5__1;

		private string _003Cendpoint_003E5__2;

		private string _003Cep_003E5__3;

		private object _003Cbody_003E5__4;

		private string _003Curl_003E5__5;

		private HttpRequestMessage _003Creq_003E5__6;

		private HttpResponseMessage _003Cresp_003E5__7;

		private Stream _003Cstream_003E5__8;

		private StreamReader _003Creader_003E5__9;

		private HttpResponseMessage _003C_003Es__10;

		private Stream _003C_003Es__11;

		private string _003Cline_003E5__12;

		private string _003Cdata_003E5__13;

		private string _003Ctext_003E5__14;

		private string _003C_003Es__15;

		private JsonDocument _003Cdoc_003E5__16;

		private JsonElement _003Cchoices_003E5__17;

		private JsonElement _003Cdelta_003E5__18;

		private JsonElement _003Cc_003E5__19;

		private JsonException _003Cex_003E5__20;

		private TaskAwaiter _003C_003Eu__1;

		private TaskAwaiter<HttpResponseMessage> _003C_003Eu__2;

		private TaskAwaiter<Stream> _003C_003Eu__3;

		private TaskAwaiter<string?> _003C_003Eu__4;

		string IAsyncEnumerator<string>.Current
		{
			[DebuggerHidden]
			get
			{
				return _003C_003E2__current;
			}
		}

		[DebuggerHidden]
		public _003CStreamOpenAiCompatibleAsync_003Ed__40(int _003C_003E1__state)
		{
			_003C_003Et__builder = AsyncIteratorMethodBuilder.Create();
			this._003C_003E1__state = _003C_003E1__state;
			_003C_003El__initialThreadId = Environment.CurrentManagedThreadId;
		}

		private void MoveNext()
		{
			int num = _003C_003E1__state;
			try
			{
				switch (num)
				{
				default:
					if (!_003C_003Ew__disposeMode)
					{
						num = (_003C_003E1__state = -1);
						_003Cllm_003E5__1 = _003C_003E4__this._settings.Settings.Llm;
						_003Cendpoint_003E5__2 = _003C_003E4__this.ResolveServerInfo().Endpoint;
						_003Cep_003E5__3 = (string.IsNullOrEmpty(_003Cendpoint_003E5__2) ? _003Cllm_003E5__1.Endpoint : _003Cendpoint_003E5__2);
						_003Cbody_003E5__4 = _003C_003E4__this.BuildOpenAiBody(messages, stream: true);
						_003Curl_003E5__5 = _003Cep_003E5__3.TrimEnd('/') + "/v1/chat/completions";
						_003Creq_003E5__6 = new HttpRequestMessage(HttpMethod.Post, _003Curl_003E5__5)
						{
							Content = JsonContent(_003Cbody_003E5__4)
						};
						break;
					}
					goto end_IL_0007;
				case -4:
				case 0:
				case 1:
				case 2:
				case 3:
					break;
				}
				try
				{
					TaskAwaiter awaiter2;
					TaskAwaiter<HttpResponseMessage> awaiter;
					switch (num)
					{
					default:
						_003C_003E2__current = null;
						awaiter2 = _003C_003E4__this.ApplyAuthHeaderAsync(_003Creq_003E5__6, ct).GetAwaiter();
						if (!awaiter2.IsCompleted)
						{
							num = (_003C_003E1__state = 0);
							_003C_003Eu__1 = awaiter2;
							_003CStreamOpenAiCompatibleAsync_003Ed__40 stateMachine = this;
							_003C_003Et__builder.AwaitUnsafeOnCompleted(ref awaiter2, ref stateMachine);
							return;
						}
						goto IL_01ae;
					case 0:
						awaiter2 = _003C_003Eu__1;
						_003C_003Eu__1 = default(TaskAwaiter);
						num = (_003C_003E1__state = -1);
						goto IL_01ae;
					case 1:
						awaiter = _003C_003Eu__2;
						_003C_003Eu__2 = default(TaskAwaiter<HttpResponseMessage>);
						num = (_003C_003E1__state = -1);
						goto IL_0229;
					case -4:
					case 2:
					case 3:
						break;
						IL_0229:
						_003C_003Es__10 = awaiter.GetResult();
						_003Cresp_003E5__7 = _003C_003Es__10;
						_003C_003Es__10 = null;
						break;
						IL_01ae:
						awaiter2.GetResult();
						_003C_003E2__current = null;
						awaiter = _003C_003E4__this.SendWithErrorClassificationAsync(_003Creq_003E5__6, ct).GetAwaiter();
						if (!awaiter.IsCompleted)
						{
							num = (_003C_003E1__state = 1);
							_003C_003Eu__2 = awaiter;
							_003CStreamOpenAiCompatibleAsync_003Ed__40 stateMachine = this;
							_003C_003Et__builder.AwaitUnsafeOnCompleted(ref awaiter, ref stateMachine);
							return;
						}
						goto IL_0229;
					}
					try
					{
						if (num != -4)
						{
							TaskAwaiter<Stream> awaiter3;
							if (num != 2)
							{
								if (num == 3)
								{
									goto IL_02f7;
								}
								_003C_003E2__current = null;
								awaiter3 = _003Cresp_003E5__7.Content.ReadAsStreamAsync(ct).GetAwaiter();
								if (!awaiter3.IsCompleted)
								{
									num = (_003C_003E1__state = 2);
									_003C_003Eu__3 = awaiter3;
									_003CStreamOpenAiCompatibleAsync_003Ed__40 stateMachine = this;
									_003C_003Et__builder.AwaitUnsafeOnCompleted(ref awaiter3, ref stateMachine);
									return;
								}
							}
							else
							{
								awaiter3 = _003C_003Eu__3;
								_003C_003Eu__3 = default(TaskAwaiter<Stream>);
								num = (_003C_003E1__state = -1);
							}
							_003C_003Es__11 = awaiter3.GetResult();
							_003Cstream_003E5__8 = _003C_003Es__11;
							_003C_003Es__11 = null;
						}
						goto IL_02f7;
						IL_0646:
						if (!_003C_003Ew__disposeMode)
						{
						}
						goto IL_066b;
						IL_02f7:
						try
						{
							if (num != -4 && num != 3)
							{
								_003Creader_003E5__9 = new StreamReader(_003Cstream_003E5__8);
							}
							try
							{
								TaskAwaiter<string> awaiter4;
								if (num != -4)
								{
									if (num != 3)
									{
										goto IL_05dc;
									}
									awaiter4 = _003C_003Eu__4;
									_003C_003Eu__4 = default(TaskAwaiter<string>);
									num = (_003C_003E1__state = -1);
									goto IL_039f;
								}
								num = (_003C_003E1__state = -1);
								if (!_003C_003Ew__disposeMode)
								{
									goto IL_05c6;
								}
								goto end_IL_0318;
								IL_0584:
								if (string.IsNullOrEmpty(_003Ctext_003E5__14))
								{
									goto IL_05c6;
								}
								_003C_003E2__current = _003Ctext_003E5__14;
								num = (_003C_003E1__state = -4);
								goto IL_08a6;
								IL_05c6:
								_003Cline_003E5__12 = null;
								_003Cdata_003E5__13 = null;
								_003Ctext_003E5__14 = null;
								goto IL_05dc;
								IL_039f:
								_003C_003Es__15 = awaiter4.GetResult();
								_003Cline_003E5__12 = _003C_003Es__15;
								_003C_003Es__15 = null;
								if (_003Cline_003E5__12 != null)
								{
									if (string.IsNullOrEmpty(_003Cline_003E5__12) || !_003Cline_003E5__12.StartsWith("data: "))
									{
										goto IL_05dc;
									}
									string text = _003Cline_003E5__12;
									int length = "data: ".Length;
									_003Cdata_003E5__13 = text.Substring(length, text.Length - length);
									if (!(_003Cdata_003E5__13 == "[DONE]"))
									{
										_003Ctext_003E5__14 = null;
										try
										{
											_003Cdoc_003E5__16 = JsonDocument.Parse(_003Cdata_003E5__13);
											try
											{
												_003C_003E4__this.TryParseOpenAiUsage(_003Cdoc_003E5__16.RootElement);
												_003Cchoices_003E5__17 = _003Cdoc_003E5__16.RootElement.GetProperty("choices");
												if (_003Cchoices_003E5__17.GetArrayLength() > 0)
												{
													_003Cdelta_003E5__18 = _003Cchoices_003E5__17[0].GetProperty("delta");
													if (_003Cdelta_003E5__18.TryGetProperty("content", out _003Cc_003E5__19))
													{
														_003Ctext_003E5__14 = _003Cc_003E5__19.GetString();
													}
													_003Cdelta_003E5__18 = default(JsonElement);
													_003Cc_003E5__19 = default(JsonElement);
												}
											}
											finally
											{
												if (num == -1 && _003Cdoc_003E5__16 != null)
												{
													((IDisposable)_003Cdoc_003E5__16).Dispose();
												}
											}
											if (!_003C_003Ew__disposeMode)
											{
												_003Cdoc_003E5__16 = null;
												_003Cchoices_003E5__17 = default(JsonElement);
												goto IL_0584;
											}
										}
										catch (JsonException ex)
										{
											_003Cex_003E5__20 = ex;
											LogService.Warn("vLLM 스트리밍 JSON 파싱 오류: " + _003Cex_003E5__20.Message);
											goto IL_0584;
										}
										goto end_IL_0318;
									}
								}
								goto end_IL_02f7;
								IL_05dc:
								if (!_003Creader_003E5__9.EndOfStream && !ct.IsCancellationRequested)
								{
									_003C_003E2__current = null;
									awaiter4 = ReadLineWithTimeoutAsync(_003Creader_003E5__9, ct).GetAwaiter();
									if (!awaiter4.IsCompleted)
									{
										num = (_003C_003E1__state = 3);
										_003C_003Eu__4 = awaiter4;
										_003CStreamOpenAiCompatibleAsync_003Ed__40 stateMachine = this;
										_003C_003Et__builder.AwaitUnsafeOnCompleted(ref awaiter4, ref stateMachine);
										return;
									}
									goto IL_039f;
								}
								goto end_IL_02f7;
								end_IL_0318:;
							}
							finally
							{
								if (num == -1 && _003Creader_003E5__9 != null)
								{
									((IDisposable)_003Creader_003E5__9).Dispose();
								}
							}
							if (!_003C_003Ew__disposeMode)
							{
							}
							goto IL_0646;
							end_IL_02f7:;
						}
						finally
						{
							if (num == -1 && _003Cstream_003E5__8 != null)
							{
								((IDisposable)_003Cstream_003E5__8).Dispose();
							}
						}
					}
					finally
					{
						if (num == -1 && _003Cresp_003E5__7 != null)
						{
							((IDisposable)_003Cresp_003E5__7).Dispose();
						}
					}
					goto end_IL_0107;
					IL_066b:
					if (!_003C_003Ew__disposeMode)
					{
					}
					goto IL_0690;
					end_IL_0107:;
				}
				finally
				{
					if (num == -1 && _003Creq_003E5__6 != null)
					{
						((IDisposable)_003Creq_003E5__6).Dispose();
					}
				}
				goto end_IL_0007;
				IL_0690:
				if (!_003C_003Ew__disposeMode)
				{
					_003Cllm_003E5__1 = null;
					_003Cendpoint_003E5__2 = null;
					_003Cep_003E5__3 = null;
					_003Cbody_003E5__4 = null;
					_003Curl_003E5__5 = null;
					_003Creq_003E5__6 = null;
					_003Cresp_003E5__7 = null;
					_003Cstream_003E5__8 = null;
					_003Creader_003E5__9 = null;
				}
				end_IL_0007:;
			}
			catch (Exception exception)
			{
				_003C_003E1__state = -2;
				_003Cllm_003E5__1 = null;
				_003Cendpoint_003E5__2 = null;
				_003Cep_003E5__3 = null;
				_003Cbody_003E5__4 = null;
				_003Curl_003E5__5 = null;
				_003Creq_003E5__6 = null;
				_003Cresp_003E5__7 = null;
				_003Cstream_003E5__8 = null;
				_003Creader_003E5__9 = null;
				_003C_003Es__10 = null;
				_003C_003Es__11 = null;
				_003Cline_003E5__12 = null;
				_003Cdata_003E5__13 = null;
				_003Ctext_003E5__14 = null;
				_003C_003Es__15 = null;
				_003Cdoc_003E5__16 = null;
				_003Cchoices_003E5__17 = default(JsonElement);
				_003Cdelta_003E5__18 = default(JsonElement);
				_003Cc_003E5__19 = default(JsonElement);
				_003Cex_003E5__20 = null;
				if (_003C_003Ex__combinedTokens != null)
				{
					_003C_003Ex__combinedTokens.Dispose();
					_003C_003Ex__combinedTokens = null;
				}
				_003C_003E2__current = null;
				_003C_003Et__builder.Complete();
				_003C_003Ev__promiseOfValueOrEnd.SetException(exception);
				return;
			}
			_003C_003E1__state = -2;
			_003Cllm_003E5__1 = null;
			_003Cendpoint_003E5__2 = null;
			_003Cep_003E5__3 = null;
			_003Cbody_003E5__4 = null;
			_003Curl_003E5__5 = null;
			_003Creq_003E5__6 = null;
			_003Cresp_003E5__7 = null;
			_003Cstream_003E5__8 = null;
			_003Creader_003E5__9 = null;
			_003C_003Es__10 = null;
			_003C_003Es__11 = null;
			_003Cline_003E5__12 = null;
			_003Cdata_003E5__13 = null;
			_003Ctext_003E5__14 = null;
			_003C_003Es__15 = null;
			_003Cdoc_003E5__16 = null;
			_003Cchoices_003E5__17 = default(JsonElement);
			_003Cdelta_003E5__18 = default(JsonElement);
			_003Cc_003E5__19 = default(JsonElement);
			_003Cex_003E5__20 = null;
			if (_003C_003Ex__combinedTokens != null)
			{
				_003C_003Ex__combinedTokens.Dispose();
				_003C_003Ex__combinedTokens = null;
			}
			_003C_003E2__current = null;
			_003C_003Et__builder.Complete();
			_003C_003Ev__promiseOfValueOrEnd.SetResult(result: false);
			return;
			IL_08a6:
			_003C_003Ev__promiseOfValueOrEnd.SetResult(result: true);
		}

		void IAsyncStateMachine.MoveNext()
		{
			//ILSpy generated this explicit interface implementation from .override directive in MoveNext
			this.MoveNext();
		}

		[DebuggerHidden]
		private void SetStateMachine(IAsyncStateMachine stateMachine)
		{
		}

		void IAsyncStateMachine.SetStateMachine(IAsyncStateMachine stateMachine)
		{
			//ILSpy generated this explicit interface implementation from .override directive in SetStateMachine
			this.SetStateMachine(stateMachine);
		}

		[DebuggerHidden]
		IAsyncEnumerator<string> IAsyncEnumerable<string>.GetAsyncEnumerator(CancellationToken cancellationToken = default(CancellationToken))
		{
			_003CStreamOpenAiCompatibleAsync_003Ed__40 _003CStreamOpenAiCompatibleAsync_003Ed__;
			if (_003C_003E1__state == -2 && _003C_003El__initialThreadId == Environment.CurrentManagedThreadId)
			{
				_003C_003E1__state = -3;
				_003C_003Et__builder = AsyncIteratorMethodBuilder.Create();
				_003C_003Ew__disposeMode = false;
				_003CStreamOpenAiCompatibleAsync_003Ed__ = this;
			}
			else
			{
				_003CStreamOpenAiCompatibleAsync_003Ed__ = new _003CStreamOpenAiCompatibleAsync_003Ed__40(-3)
				{
					_003C_003E4__this = _003C_003E4__this
				};
			}
			_003CStreamOpenAiCompatibleAsync_003Ed__.messages = _003C_003E3__messages;
			if (_003C_003E3__ct.Equals(default(CancellationToken)))
			{
				_003CStreamOpenAiCompatibleAsync_003Ed__.ct = cancellationToken;
			}
			else if (cancellationToken.Equals(_003C_003E3__ct) || cancellationToken.Equals(default(CancellationToken)))
			{
				_003CStreamOpenAiCompatibleAsync_003Ed__.ct = _003C_003E3__ct;
			}
			else
			{
				_003C_003Ex__combinedTokens = CancellationTokenSource.CreateLinkedTokenSource(_003C_003E3__ct, cancellationToken);
				_003CStreamOpenAiCompatibleAsync_003Ed__.ct = _003C_003Ex__combinedTokens.Token;
			}
			return _003CStreamOpenAiCompatibleAsync_003Ed__;
		}

		[DebuggerHidden]
		ValueTask<bool> IAsyncEnumerator<string>.MoveNextAsync()
		{
			if (_003C_003E1__state == -2)
			{
				return default(ValueTask<bool>);
			}
			_003C_003Ev__promiseOfValueOrEnd.Reset();
			_003CStreamOpenAiCompatibleAsync_003Ed__40 stateMachine = this;
			_003C_003Et__builder.MoveNext(ref stateMachine);
			short version = _003C_003Ev__promiseOfValueOrEnd.Version;
			if (_003C_003Ev__promiseOfValueOrEnd.GetStatus(version) == ValueTaskSourceStatus.Succeeded)
			{
				return new ValueTask<bool>(_003C_003Ev__promiseOfValueOrEnd.GetResult(version));
			}
			return new ValueTask<bool>(this, version);
		}

		[DebuggerHidden]
		bool IValueTaskSource<bool>.GetResult(short token)
		{
			return _003C_003Ev__promiseOfValueOrEnd.GetResult(token);
		}

		[DebuggerHidden]
		ValueTaskSourceStatus IValueTaskSource<bool>.GetStatus(short token)
		{
			return _003C_003Ev__promiseOfValueOrEnd.GetStatus(token);
		}

		[DebuggerHidden]
		void IValueTaskSource<bool>.OnCompleted(Action<object?> continuation, object? state, short token, ValueTaskSourceOnCompletedFlags flags)
		{
			_003C_003Ev__promiseOfValueOrEnd.OnCompleted(continuation, state, token, flags);
		}

		[DebuggerHidden]
		void IValueTaskSource.GetResult(short token)
		{
			_003C_003Ev__promiseOfValueOrEnd.GetResult(token);
		}

		[DebuggerHidden]
		ValueTaskSourceStatus IValueTaskSource.GetStatus(short token)
		{
			return _003C_003Ev__promiseOfValueOrEnd.GetStatus(token);
		}

		[DebuggerHidden]
		void IValueTaskSource.OnCompleted(Action<object?> continuation, object? state, short token, ValueTaskSourceOnCompletedFlags flags)
		{
			_003C_003Ev__promiseOfValueOrEnd.OnCompleted(continuation, state, token, flags);
		}

		[DebuggerHidden]
		ValueTask IAsyncDisposable.DisposeAsync()
		{
			if (_003C_003E1__state >= -1)
			{
				throw new NotSupportedException();
			}
			if (_003C_003E1__state == -2)
			{
				return default(ValueTask);
			}
			_003C_003Ew__disposeMode = true;
			_003C_003Ev__promiseOfValueOrEnd.Reset();
			_003CStreamOpenAiCompatibleAsync_003Ed__40 stateMachine = this;
			_003C_003Et__builder.MoveNext(ref stateMachine);
			return new ValueTask(this, _003C_003Ev__promiseOfValueOrEnd.Version);
		}
	}

	private readonly HttpClient _http;

	private readonly SettingsService _settings;

	private string? _systemPrompt;

	private const int MaxRetries = 2;

	private static readonly TimeSpan ChunkTimeout = TimeSpan.FromSeconds(30.0);

	private string? _serviceOverride;

	private string? _modelOverride;

	public TokenUsage? LastTokenUsage { get; private set; }

	public string? SystemPrompt => _systemPrompt;

	public string? LastFallbackInfo { get; private set; }

	public void PushRouteOverride(string service, string model)
	{
		_serviceOverride = service;
		_modelOverride = model;
	}

	public void ClearRouteOverride()
	{
		_serviceOverride = null;
		_modelOverride = null;
	}

	public (string service, string model) GetCurrentModelInfo()
	{
		return (service: ResolveService(), model: ResolveModel());
	}

	private string ResolveService()
	{
		return _serviceOverride ?? _settings.Settings.Llm.Service;
	}

	private string ResolveModel()
	{
		if (_modelOverride != null)
		{
			return _modelOverride;
		}
		return ResolveModelName();
	}

	private string ResolveApiKeyForService(string service)
	{
		LlmSettings llm = _settings.Settings.Llm;
		string text = service.ToLowerInvariant();
		if (1 == 0)
		{
		}
		string result = text switch
		{
			"gemini" => llm.GeminiApiKey, 
			"claude" => llm.ClaudeApiKey, 
			"vllm" => CryptoService.DecryptIfEnabled(llm.VllmApiKey, llm.EncryptionEnabled), 
			"ollama" => CryptoService.DecryptIfEnabled(llm.OllamaApiKey, llm.EncryptionEnabled), 
			_ => "", 
		};
		if (1 == 0)
		{
		}
		return result;
	}

	private string ResolveEndpointForService(string service)
	{
		LlmSettings llm = _settings.Settings.Llm;
		string text = service.ToLowerInvariant();
		if (1 == 0)
		{
		}
		string result = ((text == "vllm") ? llm.VllmEndpoint : ((!(text == "ollama")) ? llm.Endpoint : llm.OllamaEndpoint));
		if (1 == 0)
		{
		}
		return result;
	}

	public LlmService(SettingsService settings)
	{
		_settings = settings;
		_http = new HttpClient
		{
			Timeout = TimeSpan.FromMinutes(10.0)
		};
		LoadSystemPrompt();
	}

	private void LoadSystemPrompt()
	{
		string baseDirectory = AppContext.BaseDirectory;
		string path = Path.Combine(baseDirectory, "system_prompt.txt");
		if (File.Exists(path))
		{
			_systemPrompt = File.ReadAllText(path, Encoding.UTF8).Trim();
		}
	}

	private string ResolveModelName()
	{
		LlmSettings llm = _settings.Settings.Llm;
		string service = llm.Service;
		bool flag = ((service == "ollama" || service == "vllm") ? true : false);
		if (flag && !string.IsNullOrEmpty(llm.Model))
		{
			return CryptoService.DecryptIfEnabled(llm.Model, llm.EncryptionEnabled);
		}
		return llm.Model;
	}

	private (string Endpoint, string ApiKey) ResolveServerInfo()
	{
		LlmSettings llm = _settings.Settings.Llm;
		string text = ResolveService();
		string modelName = ResolveModel();
		RegisteredModel registeredModel = FindRegisteredModel(llm, text, modelName);
		if (registeredModel != null && !string.IsNullOrEmpty(registeredModel.Endpoint))
		{
			string item = ((!string.IsNullOrEmpty(registeredModel.ApiKey)) ? CryptoService.DecryptIfEnabled(registeredModel.ApiKey, llm.EncryptionEnabled) : GetDefaultApiKey(llm, text));
			return (Endpoint: registeredModel.Endpoint, ApiKey: item);
		}
		string text2 = text.ToLowerInvariant();
		if (1 == 0)
		{
		}
		(string, string) result = ((text2 == "vllm") ? (llm.VllmEndpoint, CryptoService.DecryptIfEnabled(llm.VllmApiKey, llm.EncryptionEnabled)) : ((!(text2 == "ollama")) ? ("", "") : (llm.OllamaEndpoint, CryptoService.DecryptIfEnabled(llm.OllamaApiKey, llm.EncryptionEnabled))));
		if (1 == 0)
		{
		}
		return result;
	}

	private static RegisteredModel? FindRegisteredModel(LlmSettings llm, string service, string modelName)
	{
		return llm.RegisteredModels.FirstOrDefault((RegisteredModel m) => m.Service.Equals(service, StringComparison.OrdinalIgnoreCase) && (CryptoService.DecryptIfEnabled(m.EncryptedModelName, llm.EncryptionEnabled) == modelName || m.Alias == modelName));
	}

	internal async Task<string?> ResolveAuthTokenAsync(CancellationToken ct = default(CancellationToken))
	{
		LlmSettings llm = _settings.Settings.Llm;
		string activeService = ResolveService();
		string modelName = ResolveModel();
		RegisteredModel registered = FindRegisteredModel(llm, activeService, modelName);
		if (registered != null && registered.AuthType.Equals("cp4d", StringComparison.OrdinalIgnoreCase) && !string.IsNullOrWhiteSpace(registered.Cp4dUrl))
		{
			return await Cp4dTokenService.GetTokenAsync(password: CryptoService.DecryptIfEnabled(registered.Cp4dPassword, llm.EncryptionEnabled), cp4dUrl: registered.Cp4dUrl, username: registered.Cp4dUsername, ct: ct);
		}
		string apiKey = ResolveServerInfo().ApiKey;
		return string.IsNullOrEmpty(apiKey) ? null : apiKey;
	}

	private async Task ApplyAuthHeaderAsync(HttpRequestMessage req, CancellationToken ct)
	{
		string token = await ResolveAuthTokenAsync(ct);
		if (!string.IsNullOrEmpty(token))
		{
			req.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token);
		}
	}

	private static string GetDefaultApiKey(LlmSettings llm, string? service = null)
	{
		string text = service ?? llm.Service;
		string text2 = text.ToLowerInvariant();
		if (1 == 0)
		{
		}
		string result = ((text2 == "vllm") ? CryptoService.DecryptIfEnabled(llm.VllmApiKey, llm.EncryptionEnabled) : ((!(text2 == "ollama")) ? "" : CryptoService.DecryptIfEnabled(llm.OllamaApiKey, llm.EncryptionEnabled)));
		if (1 == 0)
		{
		}
		return result;
	}

	public async Task<string> SendAsync(List<ChatMessage> messages, CancellationToken ct = default(CancellationToken))
	{
		LlmSettings llm = _settings.Settings.Llm;
		string activeService = ResolveService();
		try
		{
			return await SendWithServiceAsync(activeService, messages, ct);
		}
		catch (Exception ex) when (llm.FallbackModels.Count > 0)
		{
			foreach (string fallback in llm.FallbackModels)
			{
				string[] parts = fallback.Split(':', 2);
				string fbService = parts[0].Trim();
				if (parts.Length > 1)
				{
					parts[1].Trim();
				}
				try
				{
					LogService.Warn($"모델 폴백: {activeService} → {fbService} ({ex.Message})");
					LastFallbackInfo = activeService + " → " + fbService;
					return await SendWithServiceAsync(fbService, messages, ct);
				}
				catch
				{
				}
			}
			throw;
		}
	}

	private Task<string> SendWithServiceAsync(string service, List<ChatMessage> messages, CancellationToken ct)
	{
		string text = service.ToLowerInvariant();
		if (1 == 0)
		{
		}
		Task<string> result = text switch
		{
			"gemini" => SendGeminiAsync(messages, ct), 
			"claude" => SendClaudeAsync(messages, ct), 
			"vllm" => SendOpenAiCompatibleAsync(messages, ct), 
			_ => SendOllamaAsync(messages, ct), 
		};
		if (1 == 0)
		{
		}
		return result;
	}

	[AsyncIteratorStateMachine(typeof(_003CStreamAsync_003Ed__34))]
	public IAsyncEnumerable<string> StreamAsync(List<ChatMessage> messages, [EnumeratorCancellation] CancellationToken ct = default(CancellationToken))
	{
		return new _003CStreamAsync_003Ed__34(-2)
		{
			_003C_003E4__this = this,
			_003C_003E3__messages = messages,
			_003C_003E3__ct = ct
		};
	}

	public async Task<(bool ok, string message)> TestConnectionAsync()
	{
		try
		{
			LlmSettings llm = _settings.Settings.Llm;
			switch (llm.Service.ToLowerInvariant())
			{
			case "ollama":
			{
				HttpResponseMessage resp = await _http.GetAsync(llm.Endpoint.TrimEnd('/') + "/api/tags");
				return resp.IsSuccessStatusCode ? (ok: true, message: "Ollama 연결 성공") : (ok: false, message: ClassifyHttpError(resp));
			}
			case "vllm":
			{
				HttpResponseMessage vResp = await _http.GetAsync(llm.Endpoint.TrimEnd('/') + "/v1/models");
				return vResp.IsSuccessStatusCode ? (ok: true, message: "vLLM 연결 성공") : (ok: false, message: ClassifyHttpError(vResp));
			}
			case "gemini":
			{
				string gKey = llm.ApiKey;
				if (string.IsNullOrEmpty(gKey))
				{
					return (ok: false, message: "API 키가 설정되지 않았습니다");
				}
				HttpResponseMessage gResp = await _http.GetAsync("https://generativelanguage.googleapis.com/v1beta/models?key=" + gKey);
				return gResp.IsSuccessStatusCode ? (ok: true, message: "Gemini API 연결 성공") : (ok: false, message: ClassifyHttpError(gResp));
			}
			case "claude":
			{
				string cKey = llm.ApiKey;
				if (string.IsNullOrEmpty(cKey))
				{
					return (ok: false, message: "API 키가 설정되지 않았습니다");
				}
				using HttpRequestMessage cReq = new HttpRequestMessage(HttpMethod.Get, "https://api.anthropic.com/v1/models");
				cReq.Headers.Add("x-api-key", cKey);
				cReq.Headers.Add("anthropic-version", "2023-06-01");
				HttpResponseMessage cResp = await _http.SendAsync(cReq);
				return cResp.IsSuccessStatusCode ? (ok: true, message: "Claude API 연결 성공") : (ok: false, message: ClassifyHttpError(cResp));
			}
			default:
				return (ok: false, message: "알 수 없는 서비스");
			}
		}
		catch (TaskCanceledException)
		{
			return (ok: false, message: "연결 시간 초과 — 서버가 응답하지 않습니다");
		}
		catch (HttpRequestException ex2)
		{
			HttpRequestException ex3 = ex2;
			return (ok: false, message: "연결 실패 — " + ex3.Message);
		}
		catch (Exception ex4)
		{
			Exception ex5 = ex4;
			return (ok: false, message: ex5.Message);
		}
	}

	private async Task<string> SendOllamaAsync(List<ChatMessage> messages, CancellationToken ct)
	{
		LlmSettings llm = _settings.Settings.Llm;
		string endpoint = ResolveServerInfo().Endpoint;
		string ep = (string.IsNullOrEmpty(endpoint) ? llm.Endpoint : endpoint);
		return SafeParseJson(await PostJsonWithRetryAsync(body: BuildOllamaBody(messages, stream: false), url: ep.TrimEnd('/') + "/api/chat", ct: ct), delegate(JsonElement root)
		{
			TryParseOllamaUsage(root);
			return root.GetProperty("message").GetProperty("content").GetString() ?? "";
		}, "Ollama 응답");
	}

	[AsyncIteratorStateMachine(typeof(_003CStreamOllamaAsync_003Ed__37))]
	private IAsyncEnumerable<string> StreamOllamaAsync(List<ChatMessage> messages, [EnumeratorCancellation] CancellationToken ct)
	{
		return new _003CStreamOllamaAsync_003Ed__37(-2)
		{
			_003C_003E4__this = this,
			_003C_003E3__messages = messages,
			_003C_003E3__ct = ct
		};
	}

	private object BuildOllamaBody(List<ChatMessage> messages, bool stream)
	{
		LlmSettings llm = _settings.Settings.Llm;
		List<object> messages2 = BuildMessageList(messages);
		return new
		{
			model = ResolveModelName(),
			messages = messages2,
			stream = stream,
			options = new
			{
				temperature = llm.Temperature
			}
		};
	}

	private async Task<string> SendOpenAiCompatibleAsync(List<ChatMessage> messages, CancellationToken ct)
	{
		LlmSettings llm = _settings.Settings.Llm;
		string endpoint = ResolveServerInfo().Endpoint;
		string ep = (string.IsNullOrEmpty(endpoint) ? llm.Endpoint : endpoint);
		object body = BuildOpenAiBody(messages, stream: false);
		string url = ep.TrimEnd('/') + "/v1/chat/completions";
		string json = JsonSerializer.Serialize(body);
		using HttpRequestMessage req = new HttpRequestMessage(HttpMethod.Post, url)
		{
			Content = new StringContent(json, Encoding.UTF8, "application/json")
		};
		await ApplyAuthHeaderAsync(req, ct);
		using HttpResponseMessage resp = await SendWithErrorClassificationAsync(req, ct);
		return SafeParseJson(await resp.Content.ReadAsStringAsync(ct), delegate(JsonElement root)
		{
			TryParseOpenAiUsage(root);
			JsonElement property = root.GetProperty("choices");
			return (property.GetArrayLength() == 0) ? "(빈 응답)" : (property[0].GetProperty("message").GetProperty("content").GetString() ?? "");
		}, "vLLM 응답");
	}

	[AsyncIteratorStateMachine(typeof(_003CStreamOpenAiCompatibleAsync_003Ed__40))]
	private IAsyncEnumerable<string> StreamOpenAiCompatibleAsync(List<ChatMessage> messages, [EnumeratorCancellation] CancellationToken ct)
	{
		return new _003CStreamOpenAiCompatibleAsync_003Ed__40(-2)
		{
			_003C_003E4__this = this,
			_003C_003E3__messages = messages,
			_003C_003E3__ct = ct
		};
	}

	private object BuildOpenAiBody(List<ChatMessage> messages, bool stream)
	{
		LlmSettings llm = _settings.Settings.Llm;
		List<object> messages2 = BuildMessageList(messages, openAiVision: true);
		return new
		{
			model = ResolveModelName(),
			messages = messages2,
			stream = stream,
			temperature = llm.Temperature,
			max_tokens = llm.MaxContextTokens
		};
	}

	private async Task<string> SendGeminiAsync(List<ChatMessage> messages, CancellationToken ct)
	{
		_ = _settings.Settings.Llm;
		string apiKey = ResolveApiKeyForService("gemini");
		if (string.IsNullOrEmpty(apiKey))
		{
			throw new InvalidOperationException("Gemini API 키가 설정되지 않았습니다. 설정 > AX Agent에서 API 키를 입력하세요.");
		}
		string model = ResolveModel();
		object body = BuildGeminiBody(messages);
		string url = "https://generativelanguage.googleapis.com/v1beta/models/" + model + ":generateContent?key=" + apiKey;
		return SafeParseJson(await PostJsonWithRetryAsync(url, body, ct), delegate(JsonElement root)
		{
			TryParseGeminiUsage(root);
			JsonElement property = root.GetProperty("candidates");
			if (property.GetArrayLength() == 0)
			{
				return "(빈 응답)";
			}
			JsonElement property2 = property[0].GetProperty("content").GetProperty("parts");
			return (property2.GetArrayLength() == 0) ? "(빈 응답)" : (property2[0].GetProperty("text").GetString() ?? "");
		}, "Gemini 응답");
	}

	[AsyncIteratorStateMachine(typeof(_003CStreamGeminiAsync_003Ed__43))]
	private IAsyncEnumerable<string> StreamGeminiAsync(List<ChatMessage> messages, [EnumeratorCancellation] CancellationToken ct)
	{
		return new _003CStreamGeminiAsync_003Ed__43(-2)
		{
			_003C_003E4__this = this,
			_003C_003E3__messages = messages,
			_003C_003E3__ct = ct
		};
	}

	private object BuildGeminiBody(List<ChatMessage> messages)
	{
		LlmSettings llm = _settings.Settings.Llm;
		List<object> list = new List<object>();
		object obj = null;
		if (!string.IsNullOrEmpty(_systemPrompt))
		{
			obj = new
			{
				parts = new[]
				{
					new
					{
						text = _systemPrompt
					}
				}
			};
		}
		foreach (ChatMessage message in messages)
		{
			if (message.Role == "system")
			{
				continue;
			}
			List<object> list2 = new List<object>
			{
				new
				{
					text = message.Content
				}
			};
			List<ImageAttachment>? images = message.Images;
			if (images != null && images.Count > 0)
			{
				foreach (ImageAttachment image in message.Images)
				{
					list2.Add(new
					{
						inlineData = new
						{
							mimeType = image.MimeType,
							data = image.Base64
						}
					});
				}
			}
			list.Add(new
			{
				role = ((message.Role == "assistant") ? "model" : "user"),
				parts = list2
			});
		}
		if (obj != null)
		{
			return new
			{
				systemInstruction = obj,
				contents = list,
				generationConfig = new
				{
					temperature = llm.Temperature,
					maxOutputTokens = llm.MaxContextTokens
				}
			};
		}
		return new
		{
			contents = list,
			generationConfig = new
			{
				temperature = llm.Temperature,
				maxOutputTokens = llm.MaxContextTokens
			}
		};
	}

	private async Task<string> SendClaudeAsync(List<ChatMessage> messages, CancellationToken ct)
	{
		LlmSettings llm = _settings.Settings.Llm;
		string apiKey = llm.ApiKey;
		if (string.IsNullOrEmpty(apiKey))
		{
			throw new InvalidOperationException("Claude API 키가 설정되지 않았습니다. 설정 > AX Agent에서 API 키를 입력하세요.");
		}
		object body = BuildClaudeBody(messages, stream: false);
		string json = JsonSerializer.Serialize(body);
		using HttpRequestMessage req = new HttpRequestMessage(HttpMethod.Post, "https://api.anthropic.com/v1/messages");
		req.Content = new StringContent(json, Encoding.UTF8, "application/json");
		req.Headers.Add("x-api-key", apiKey);
		req.Headers.Add("anthropic-version", "2023-06-01");
		using HttpResponseMessage resp = await _http.SendAsync(req, ct);
		if (!resp.IsSuccessStatusCode)
		{
			throw new HttpRequestException(ClassifyHttpError(resp, await resp.Content.ReadAsStringAsync(ct)));
		}
		return SafeParseJson(await resp.Content.ReadAsStringAsync(ct), delegate(JsonElement root)
		{
			TryParseClaudeUsage(root);
			JsonElement property = root.GetProperty("content");
			return (property.GetArrayLength() == 0) ? "(빈 응답)" : (property[0].GetProperty("text").GetString() ?? "");
		}, "Claude 응답");
	}

	[AsyncIteratorStateMachine(typeof(_003CStreamClaudeAsync_003Ed__46))]
	private IAsyncEnumerable<string> StreamClaudeAsync(List<ChatMessage> messages, [EnumeratorCancellation] CancellationToken ct)
	{
		return new _003CStreamClaudeAsync_003Ed__46(-2)
		{
			_003C_003E4__this = this,
			_003C_003E3__messages = messages,
			_003C_003E3__ct = ct
		};
	}

	private object BuildClaudeBody(List<ChatMessage> messages, bool stream)
	{
		LlmSettings llm = _settings.Settings.Llm;
		List<object> list = new List<object>();
		foreach (ChatMessage message in messages)
		{
			if (message.Role == "system")
			{
				continue;
			}
			List<ImageAttachment>? images = message.Images;
			if (images != null && images.Count > 0)
			{
				List<object> list2 = new List<object>();
				foreach (ImageAttachment image in message.Images)
				{
					list2.Add(new
					{
						type = "image",
						source = new
						{
							type = "base64",
							media_type = image.MimeType,
							data = image.Base64
						}
					});
				}
				list2.Add(new
				{
					type = "text",
					text = message.Content
				});
				list.Add(new
				{
					role = message.Role,
					content = list2
				});
			}
			else
			{
				list.Add(new
				{
					role = message.Role,
					content = message.Content
				});
			}
		}
		string model = ResolveModel();
		if (!string.IsNullOrEmpty(_systemPrompt))
		{
			return new
			{
				model = model,
				max_tokens = llm.MaxContextTokens,
				temperature = llm.Temperature,
				system = _systemPrompt,
				messages = list,
				stream = stream
			};
		}
		return new
		{
			model = model,
			max_tokens = llm.MaxContextTokens,
			temperature = llm.Temperature,
			messages = list,
			stream = stream
		};
	}

	private List<object> BuildMessageList(List<ChatMessage> messages, bool openAiVision = false)
	{
		List<object> list = new List<object>();
		if (!string.IsNullOrEmpty(_systemPrompt))
		{
			list.Add(new
			{
				role = "system",
				content = _systemPrompt
			});
		}
		foreach (ChatMessage message in messages)
		{
			if (message.Role == "system")
			{
				continue;
			}
			List<ImageAttachment>? images = message.Images;
			if (images != null && images.Count > 0)
			{
				if (openAiVision)
				{
					List<object> list2 = new List<object>();
					list2.Add(new
					{
						type = "text",
						text = message.Content
					});
					foreach (ImageAttachment image in message.Images)
					{
						list2.Add(new
						{
							type = "image_url",
							image_url = new
							{
								url = "data:" + image.MimeType + ";base64," + image.Base64
							}
						});
					}
					list.Add(new
					{
						role = message.Role,
						content = list2
					});
				}
				else
				{
					list.Add(new
					{
						role = message.Role,
						content = message.Content,
						images = message.Images.Select((ImageAttachment i) => i.Base64).ToArray()
					});
				}
			}
			else
			{
				list.Add(new
				{
					role = message.Role,
					content = message.Content
				});
			}
		}
		return list;
	}

	private async Task<string> PostJsonWithRetryAsync(string url, object body, CancellationToken ct)
	{
		string json = JsonSerializer.Serialize(body);
		Exception lastEx = null;
		for (int attempt = 0; attempt <= 2; attempt++)
		{
			try
			{
				using StringContent content = new StringContent(json, Encoding.UTF8, "application/json");
				using HttpResponseMessage resp = await _http.PostAsync(url, content, ct);
				if (resp.IsSuccessStatusCode)
				{
					return await resp.Content.ReadAsStringAsync(ct);
				}
				if (resp.StatusCode != HttpStatusCode.TooManyRequests || attempt >= 2)
				{
					throw new HttpRequestException(ClassifyHttpError(resp, await resp.Content.ReadAsStringAsync(ct)));
				}
				await Task.Delay(1000 * (attempt + 1), ct);
			}
			catch (HttpRequestException)
			{
				throw;
			}
			catch (TaskCanceledException) when (!ct.IsCancellationRequested && attempt < 2)
			{
				lastEx = new TimeoutException("요청 시간 초과");
				await Task.Delay(1000 * (attempt + 1), ct);
			}
		}
		throw lastEx ?? new HttpRequestException("요청 실패");
	}

	private async Task<HttpResponseMessage> SendWithErrorClassificationAsync(HttpRequestMessage req, CancellationToken ct)
	{
		HttpResponseMessage resp = await _http.SendAsync(req, HttpCompletionOption.ResponseHeadersRead, ct);
		if (!resp.IsSuccessStatusCode)
		{
			string errorMsg = ClassifyHttpError(resp, await resp.Content.ReadAsStringAsync(ct));
			resp.Dispose();
			throw new HttpRequestException(errorMsg);
		}
		return resp;
	}

	private static async Task<string?> ReadLineWithTimeoutAsync(StreamReader reader, CancellationToken ct)
	{
		using CancellationTokenSource cts = CancellationTokenSource.CreateLinkedTokenSource(ct);
		cts.CancelAfter(ChunkTimeout);
		try
		{
			return await reader.ReadLineAsync(cts.Token);
		}
		catch (OperationCanceledException) when (!ct.IsCancellationRequested)
		{
			LogService.Warn("스트리밍 청크 타임아웃 (30초 무응답)");
			return null;
		}
	}

	private static string SafeParseJson(string json, Func<JsonElement, string> extractor, string context)
	{
		try
		{
			using JsonDocument jsonDocument = JsonDocument.Parse(json);
			if (jsonDocument.RootElement.TryGetProperty("error", out var value))
			{
				JsonElement value2;
				string text = (value.TryGetProperty("message", out value2) ? value2.GetString() : value.ToString());
				throw new HttpRequestException("[" + context + "] API 에러: " + text);
			}
			return extractor(jsonDocument.RootElement);
		}
		catch (JsonException ex)
		{
			string value3 = ((json.Length > 200) ? (json.Substring(0, 200) + "…") : json);
			throw new InvalidOperationException($"[{context}] 응답 형식 오류 — 예상하지 못한 JSON 형식입니다.\n파싱 오류: {ex.Message}\n응답 미리보기: {value3}");
		}
		catch (KeyNotFoundException)
		{
			string text2 = ((json.Length > 200) ? (json.Substring(0, 200) + "…") : json);
			throw new InvalidOperationException("[" + context + "] 응답에 필요한 필드가 없습니다.\n응답 미리보기: " + text2);
		}
	}

	private static string ClassifyHttpError(HttpResponseMessage resp, string? body = null)
	{
		int statusCode = (int)resp.StatusCode;
		string text = "";
		if (!string.IsNullOrEmpty(body))
		{
			try
			{
				using JsonDocument jsonDocument = JsonDocument.Parse(body);
				if (jsonDocument.RootElement.TryGetProperty("error", out var value))
				{
					if (value.ValueKind == JsonValueKind.Object && value.TryGetProperty("message", out var value2))
					{
						text = value2.GetString() ?? "";
					}
					else if (value.ValueKind == JsonValueKind.String)
					{
						text = value.GetString() ?? "";
					}
				}
			}
			catch
			{
			}
		}
		if (1 == 0)
		{
		}
		string text2;
		switch (statusCode)
		{
		case 400:
			text2 = "잘못된 요청 — 모델 이름이나 요청 형식을 확인하세요";
			break;
		case 401:
			text2 = "인증 실패 — API 키가 유효하지 않습니다";
			break;
		case 403:
			text2 = "접근 거부 — API 키 권한을 확인하세요";
			break;
		case 404:
			text2 = "모델을 찾을 수 없습니다 — 모델 이름을 확인하세요";
			break;
		case 429:
			text2 = "요청 한도 초과 — 잠시 후 다시 시도하세요";
			break;
		case 500:
			text2 = "서버 내부 오류 — LLM 서버 상태를 확인하세요";
			break;
		case 502:
		case 503:
			text2 = "서버 일시 장애 — 잠시 후 다시 시도하세요";
			break;
		default:
			text2 = $"HTTP {statusCode} 오류";
			break;
		}
		if (1 == 0)
		{
		}
		string text3 = text2;
		return string.IsNullOrEmpty(text) ? text3 : (text3 + "\n상세: " + text);
	}

	private static StringContent JsonContent(object body)
	{
		string content = JsonSerializer.Serialize(body);
		return new StringContent(content, Encoding.UTF8, "application/json");
	}

	private void TryParseOllamaUsage(JsonElement root)
	{
		try
		{
			JsonElement value;
			int num = (root.TryGetProperty("prompt_eval_count", out value) ? value.GetInt32() : 0);
			JsonElement value2;
			int num2 = (root.TryGetProperty("eval_count", out value2) ? value2.GetInt32() : 0);
			if (num > 0 || num2 > 0)
			{
				LastTokenUsage = new TokenUsage(num, num2);
			}
		}
		catch
		{
		}
	}

	private void TryParseOpenAiUsage(JsonElement root)
	{
		try
		{
			if (root.TryGetProperty("usage", out var value))
			{
				JsonElement value2;
				int num = (value.TryGetProperty("prompt_tokens", out value2) ? value2.GetInt32() : 0);
				JsonElement value3;
				int num2 = (value.TryGetProperty("completion_tokens", out value3) ? value3.GetInt32() : 0);
				if (num > 0 || num2 > 0)
				{
					LastTokenUsage = new TokenUsage(num, num2);
				}
			}
		}
		catch
		{
		}
	}

	private void TryParseGeminiUsage(JsonElement root)
	{
		try
		{
			if (root.TryGetProperty("usageMetadata", out var value))
			{
				JsonElement value2;
				int num = (value.TryGetProperty("promptTokenCount", out value2) ? value2.GetInt32() : 0);
				JsonElement value3;
				int num2 = (value.TryGetProperty("candidatesTokenCount", out value3) ? value3.GetInt32() : 0);
				if (num > 0 || num2 > 0)
				{
					LastTokenUsage = new TokenUsage(num, num2);
				}
			}
		}
		catch
		{
		}
	}

	private void TryParseClaudeUsage(JsonElement root)
	{
		try
		{
			if (root.TryGetProperty("usage", out var value))
			{
				TryParseClaudeUsageFromElement(value);
			}
		}
		catch
		{
		}
	}

	private void TryParseClaudeUsageFromElement(JsonElement usage)
	{
		try
		{
			JsonElement value;
			int num = (usage.TryGetProperty("input_tokens", out value) ? value.GetInt32() : 0);
			JsonElement value2;
			int num2 = (usage.TryGetProperty("output_tokens", out value2) ? value2.GetInt32() : 0);
			if (num > 0 || num2 > 0)
			{
				LastTokenUsage = new TokenUsage(num, num2);
			}
		}
		catch
		{
		}
	}

	public void Dispose()
	{
		_http.Dispose();
	}

	public async Task<List<ContentBlock>> SendWithToolsAsync(List<ChatMessage> messages, IReadOnlyCollection<IAgentTool> tools, CancellationToken ct = default(CancellationToken))
	{
		string activeService = ResolveService();
		string text = activeService.ToLowerInvariant();
		if (1 == 0)
		{
		}
		List<ContentBlock> result;
		switch (text)
		{
		case "claude":
			result = await SendClaudeWithToolsAsync(messages, tools, ct);
			break;
		case "gemini":
			result = await SendGeminiWithToolsAsync(messages, tools, ct);
			break;
		case "ollama":
		case "vllm":
			result = await SendOpenAiWithToolsAsync(messages, tools, ct);
			break;
		default:
			throw new NotSupportedException("서비스 '" + activeService + "'는 아직 Function Calling을 지원하지 않습니다.");
		}
		if (1 == 0)
		{
		}
		return result;
	}

	public static ChatMessage CreateToolResultMessage(string toolId, string toolName, string result)
	{
		string content = JsonSerializer.Serialize(new
		{
			type = "tool_result",
			tool_use_id = toolId,
			tool_name = toolName,
			content = result
		});
		return new ChatMessage
		{
			Role = "user",
			Content = content,
			Timestamp = DateTime.Now
		};
	}

	private async Task<List<ContentBlock>> SendClaudeWithToolsAsync(List<ChatMessage> messages, IReadOnlyCollection<IAgentTool> tools, CancellationToken ct)
	{
		LlmSettings llm = _settings.Settings.Llm;
		string apiKey = llm.ApiKey;
		if (string.IsNullOrEmpty(apiKey))
		{
			throw new InvalidOperationException("Claude API 키가 설정되지 않았습니다.");
		}
		object body = BuildClaudeToolBody(messages, tools);
		string json = JsonSerializer.Serialize(body);
		using HttpRequestMessage req = new HttpRequestMessage(HttpMethod.Post, "https://api.anthropic.com/v1/messages");
		req.Content = new StringContent(json, Encoding.UTF8, "application/json");
		req.Headers.Add("x-api-key", apiKey);
		req.Headers.Add("anthropic-version", "2023-06-01");
		using HttpResponseMessage resp = await _http.SendAsync(req, ct);
		if (!resp.IsSuccessStatusCode)
		{
			throw new HttpRequestException(ClassifyHttpError(resp, await resp.Content.ReadAsStringAsync(ct)));
		}
		using JsonDocument doc = JsonDocument.Parse(await resp.Content.ReadAsStringAsync(ct));
		JsonElement root = doc.RootElement;
		if (root.TryGetProperty("usage", out var usage))
		{
			TryParseClaudeUsageFromElement(usage);
		}
		List<ContentBlock> blocks = new List<ContentBlock>();
		if (root.TryGetProperty("content", out var content))
		{
			foreach (JsonElement block in content.EnumerateArray())
			{
				JsonElement tp;
				string type = (block.TryGetProperty("type", out tp) ? tp.GetString() : "");
				if (type == "text")
				{
					blocks.Add(new ContentBlock
					{
						Type = "text",
						Text = (block.TryGetProperty("text", out var txt) ? (txt.GetString() ?? "") : "")
					});
					txt = default(JsonElement);
				}
				else if (type == "tool_use")
				{
					blocks.Add(new ContentBlock
					{
						Type = "tool_use",
						ToolName = (block.TryGetProperty("name", out var nm) ? (nm.GetString() ?? "") : ""),
						ToolId = (block.TryGetProperty("id", out var bid) ? (bid.GetString() ?? "") : ""),
						ToolInput = (block.TryGetProperty("input", out var inp) ? new JsonElement?(inp.Clone()) : ((JsonElement?)null))
					});
					nm = default(JsonElement);
					bid = default(JsonElement);
					inp = default(JsonElement);
				}
				tp = default(JsonElement);
			}
		}
		return blocks;
	}

	private object BuildClaudeToolBody(List<ChatMessage> messages, IReadOnlyCollection<IAgentTool> tools)
	{
		LlmSettings llm = _settings.Settings.Llm;
		List<object> list = new List<object>();
		foreach (ChatMessage message in messages)
		{
			if (message.Role == "system")
			{
				continue;
			}
			if (message.Role == "user" && message.Content.StartsWith("{\"type\":\"tool_result\""))
			{
				try
				{
					using JsonDocument jsonDocument = JsonDocument.Parse(message.Content);
					JsonElement rootElement = jsonDocument.RootElement;
					list.Add(new
					{
						role = "user",
						content = new object[1]
						{
							new
							{
								type = "tool_result",
								tool_use_id = (rootElement.TryGetProperty("tool_use_id", out var value) ? value.GetString() : ""),
								content = (rootElement.TryGetProperty("content", out var value2) ? value2.GetString() : "")
							}
						}
					});
				}
				catch
				{
					goto IL_0117;
				}
				continue;
			}
			goto IL_0117;
			IL_0117:
			if (message.Role == "assistant" && message.Content.StartsWith("{\"_tool_use_blocks\""))
			{
				try
				{
					using JsonDocument jsonDocument2 = JsonDocument.Parse(message.Content);
					if (!jsonDocument2.RootElement.TryGetProperty("_tool_use_blocks", out var value3))
					{
						throw new Exception();
					}
					List<object> list2 = new List<object>();
					foreach (JsonElement item in value3.EnumerateArray())
					{
						JsonElement value4;
						string text = (item.TryGetProperty("type", out value4) ? value4.GetString() : "");
						if (text == "text")
						{
							list2.Add(new
							{
								type = "text",
								text = (item.TryGetProperty("text", out var value5) ? (value5.GetString() ?? "") : "")
							});
						}
						else if (text == "tool_use")
						{
							list2.Add(new
							{
								type = "tool_use",
								id = (item.TryGetProperty("id", out var value6) ? (value6.GetString() ?? "") : ""),
								name = (item.TryGetProperty("name", out var value7) ? (value7.GetString() ?? "") : ""),
								input = (item.TryGetProperty("input", out var value8) ? ((object)value8.Clone()) : new { })
							});
						}
					}
					list.Add(new
					{
						role = "assistant",
						content = list2
					});
				}
				catch
				{
					goto IL_0301;
				}
				continue;
			}
			goto IL_0301;
			IL_0301:
			List<ImageAttachment>? images = message.Images;
			if (images != null && images.Count > 0 && message.Role == "user")
			{
				List<object> list3 = new List<object>();
				foreach (ImageAttachment image in message.Images)
				{
					list3.Add(new
					{
						type = "image",
						source = new
						{
							type = "base64",
							media_type = image.MimeType,
							data = image.Base64
						}
					});
				}
				list3.Add(new
				{
					type = "text",
					text = message.Content
				});
				list.Add(new
				{
					role = message.Role,
					content = list3
				});
			}
			else
			{
				list.Add(new
				{
					role = message.Role,
					content = message.Content
				});
			}
		}
		var tools2 = tools.Select((IAgentTool t) => new
		{
			name = t.Name,
			description = t.Description,
			input_schema = new
			{
				type = "object",
				properties = t.Parameters.Properties.ToDictionary<KeyValuePair<string, ToolProperty>, string, object>((KeyValuePair<string, ToolProperty> kv) => kv.Key, (KeyValuePair<string, ToolProperty> kv) => BuildPropertySchema(kv.Value, upperCaseType: false)),
				required = t.Parameters.Required
			}
		}).ToArray();
		string text2 = messages.FirstOrDefault((ChatMessage m) => m.Role == "system")?.Content ?? _systemPrompt;
		string model = ResolveModel();
		if (!string.IsNullOrEmpty(text2))
		{
			return new
			{
				model = model,
				max_tokens = Math.Max(llm.MaxContextTokens, 4096),
				temperature = llm.Temperature,
				system = text2,
				messages = list,
				tools = tools2,
				stream = false
			};
		}
		return new
		{
			model = model,
			max_tokens = Math.Max(llm.MaxContextTokens, 4096),
			temperature = llm.Temperature,
			messages = list,
			tools = tools2,
			stream = false
		};
	}

	private async Task<List<ContentBlock>> SendGeminiWithToolsAsync(List<ChatMessage> messages, IReadOnlyCollection<IAgentTool> tools, CancellationToken ct)
	{
		_ = _settings.Settings.Llm;
		string apiKey = ResolveApiKeyForService("gemini");
		if (string.IsNullOrEmpty(apiKey))
		{
			throw new InvalidOperationException("Gemini API 키가 설정되지 않았습니다.");
		}
		string activeModel = ResolveModel();
		object body = BuildGeminiToolBody(messages, tools);
		string url = "https://generativelanguage.googleapis.com/v1beta/models/" + activeModel + ":generateContent?key=" + apiKey;
		string json = JsonSerializer.Serialize(body);
		using StringContent content = new StringContent(json, Encoding.UTF8, "application/json");
		using HttpResponseMessage resp = await _http.PostAsync(url, content, ct);
		if (!resp.IsSuccessStatusCode)
		{
			string errBody = await resp.Content.ReadAsStringAsync(ct);
			throw new HttpRequestException($"Gemini API 오류 ({resp.StatusCode}): {errBody}");
		}
		using JsonDocument doc = JsonDocument.Parse(await resp.Content.ReadAsStringAsync(ct));
		JsonElement root = doc.RootElement;
		TryParseGeminiUsage(root);
		List<ContentBlock> blocks = new List<ContentBlock>();
		if (root.TryGetProperty("candidates", out var candidates) && candidates.GetArrayLength() > 0 && candidates[0].TryGetProperty("content", out var contentObj) && contentObj.TryGetProperty("parts", out var parts))
		{
			foreach (JsonElement part in parts.EnumerateArray())
			{
				if (part.TryGetProperty("text", out var text))
				{
					blocks.Add(new ContentBlock
					{
						Type = "text",
						Text = (text.GetString() ?? "")
					});
				}
				else
				{
					if (part.TryGetProperty("functionCall", out var fc))
					{
						blocks.Add(new ContentBlock
						{
							Type = "tool_use",
							ToolName = (fc.TryGetProperty("name", out var fcName) ? (fcName.GetString() ?? "") : ""),
							ToolId = Guid.NewGuid().ToString("N").Substring(0, 12),
							ToolInput = (fc.TryGetProperty("args", out var a) ? new JsonElement?(a.Clone()) : ((JsonElement?)null))
						});
						fcName = default(JsonElement);
						a = default(JsonElement);
					}
					fc = default(JsonElement);
				}
				text = default(JsonElement);
			}
		}
		return blocks;
	}

	private object BuildGeminiToolBody(List<ChatMessage> messages, IReadOnlyCollection<IAgentTool> tools)
	{
		List<object> list = new List<object>();
		foreach (ChatMessage message in messages)
		{
			if (message.Role == "system")
			{
				continue;
			}
			string role = ((message.Role == "assistant") ? "model" : "user");
			if (message.Role == "user" && message.Content.StartsWith("{\"type\":\"tool_result\""))
			{
				try
				{
					using JsonDocument jsonDocument = JsonDocument.Parse(message.Content);
					JsonElement rootElement = jsonDocument.RootElement;
					JsonElement value;
					string name = (rootElement.TryGetProperty("tool_name", out value) ? (value.GetString() ?? "") : "");
					JsonElement value2;
					string result = (rootElement.TryGetProperty("content", out value2) ? (value2.GetString() ?? "") : "");
					list.Add(new
					{
						role = "function",
						parts = new object[1]
						{
							new
							{
								functionResponse = new
								{
									name = name,
									response = new { result }
								}
							}
						}
					});
				}
				catch
				{
					goto IL_0146;
				}
				continue;
			}
			goto IL_0146;
			IL_0146:
			if (message.Role == "assistant" && message.Content.StartsWith("{\"_tool_use_blocks\""))
			{
				try
				{
					using JsonDocument jsonDocument2 = JsonDocument.Parse(message.Content);
					if (jsonDocument2.RootElement.TryGetProperty("_tool_use_blocks", out var value3))
					{
						List<object> list2 = new List<object>();
						foreach (JsonElement item in value3.EnumerateArray())
						{
							JsonElement value4;
							string text = (item.TryGetProperty("type", out value4) ? value4.GetString() : "");
							if (text == "text")
							{
								list2.Add(new
								{
									text = (item.TryGetProperty("text", out var value5) ? (value5.GetString() ?? "") : "")
								});
							}
							else if (text == "tool_use")
							{
								list2.Add(new
								{
									functionCall = new
									{
										name = (item.TryGetProperty("name", out var value6) ? (value6.GetString() ?? "") : ""),
										args = (item.TryGetProperty("input", out var value7) ? ((object)value7.Clone()) : new { })
									}
								});
							}
						}
						list.Add(new
						{
							role = "model",
							parts = list2
						});
						continue;
					}
				}
				catch
				{
				}
			}
			List<ImageAttachment>? images = message.Images;
			if (images != null && images.Count > 0 && message.Role == "user")
			{
				List<object> list3 = new List<object>
				{
					new
					{
						text = message.Content
					}
				};
				foreach (ImageAttachment image in message.Images)
				{
					list3.Add(new
					{
						inlineData = new
						{
							mimeType = image.MimeType,
							data = image.Base64
						}
					});
				}
				list.Add(new
				{
					role = role,
					parts = list3
				});
			}
			else
			{
				list.Add(new
				{
					role = role,
					parts = new[]
					{
						new
						{
							text = message.Content
						}
					}
				});
			}
		}
		var function_declarations = tools.Select((IAgentTool t) => new
		{
			name = t.Name,
			description = t.Description,
			parameters = new
			{
				type = "OBJECT",
				properties = t.Parameters.Properties.ToDictionary<KeyValuePair<string, ToolProperty>, string, object>((KeyValuePair<string, ToolProperty> kv) => kv.Key, (KeyValuePair<string, ToolProperty> kv) => BuildPropertySchema(kv.Value, upperCaseType: true)),
				required = t.Parameters.Required
			}
		}).ToArray();
		ChatMessage chatMessage = messages.FirstOrDefault((ChatMessage m) => m.Role == "system");
		Dictionary<string, object> dictionary = new Dictionary<string, object>();
		dictionary["contents"] = list;
		dictionary["tools"] = new[]
		{
			new { function_declarations }
		};
		dictionary["generationConfig"] = new
		{
			temperature = _settings.Settings.Llm.Temperature,
			maxOutputTokens = _settings.Settings.Llm.MaxContextTokens
		};
		Dictionary<string, object> dictionary2 = dictionary;
		if (chatMessage != null)
		{
			dictionary2["systemInstruction"] = new
			{
				parts = new[]
				{
					new
					{
						text = chatMessage.Content
					}
				}
			};
		}
		return dictionary2;
	}

	private async Task<List<ContentBlock>> SendOpenAiWithToolsAsync(List<ChatMessage> messages, IReadOnlyCollection<IAgentTool> tools, CancellationToken ct)
	{
		_ = _settings.Settings.Llm;
		string activeService = ResolveService();
		object body = BuildOpenAiToolBody(messages, tools);
		string resolvedEp = ResolveServerInfo().Endpoint;
		string endpoint = (string.IsNullOrEmpty(resolvedEp) ? ResolveEndpointForService(activeService) : resolvedEp);
		string url = ((activeService.ToLowerInvariant() == "ollama") ? (endpoint.TrimEnd('/') + "/api/chat") : (endpoint.TrimEnd('/') + "/v1/chat/completions"));
		string json = JsonSerializer.Serialize(body);
		using HttpRequestMessage req = new HttpRequestMessage(HttpMethod.Post, url)
		{
			Content = new StringContent(json, Encoding.UTF8, "application/json")
		};
		await ApplyAuthHeaderAsync(req, ct);
		using HttpResponseMessage resp = await _http.SendAsync(req, ct);
		if (!resp.IsSuccessStatusCode)
		{
			string errBody = await resp.Content.ReadAsStringAsync(ct);
			string detail = ExtractErrorDetail(errBody);
			LogService.Warn($"[ToolUse] {activeService} API 오류 ({resp.StatusCode}): {errBody}");
			if (resp.StatusCode == HttpStatusCode.BadRequest)
			{
				throw new ToolCallNotSupportedException($"{activeService} API 오류 ({resp.StatusCode}): {detail}");
			}
			throw new HttpRequestException($"{activeService} API 오류 ({resp.StatusCode}): {detail}");
		}
		using JsonDocument doc = JsonDocument.Parse(await resp.Content.ReadAsStringAsync(ct));
		JsonElement root = doc.RootElement;
		TryParseOpenAiUsage(root);
		List<ContentBlock> blocks = new List<ContentBlock>();
		JsonElement message;
		if (root.TryGetProperty("message", out var ollamaMsg))
		{
			message = ollamaMsg;
		}
		else
		{
			if (!root.TryGetProperty("choices", out var choices) || choices.GetArrayLength() <= 0)
			{
				return blocks;
			}
			message = (choices[0].TryGetProperty("message", out var choiceMsg) ? choiceMsg : default(JsonElement));
		}
		if (message.TryGetProperty("content", out var content))
		{
			string text = content.GetString();
			if (!string.IsNullOrWhiteSpace(text))
			{
				blocks.Add(new ContentBlock
				{
					Type = "text",
					Text = text
				});
			}
		}
		if (message.TryGetProperty("tool_calls", out var toolCalls))
		{
			foreach (JsonElement tc in toolCalls.EnumerateArray())
			{
				if (!tc.TryGetProperty("function", out var func))
				{
					continue;
				}
				JsonElement? parsedArgs = null;
				if (func.TryGetProperty("arguments", out var argsEl))
				{
					if (argsEl.ValueKind == JsonValueKind.String)
					{
						try
						{
							using JsonDocument argsDoc = JsonDocument.Parse(argsEl.GetString() ?? "{}");
							parsedArgs = argsDoc.RootElement.Clone();
						}
						catch
						{
							parsedArgs = null;
						}
					}
					else if (argsEl.ValueKind == JsonValueKind.Object || argsEl.ValueKind == JsonValueKind.Array)
					{
						parsedArgs = argsEl.Clone();
					}
				}
				blocks.Add(new ContentBlock
				{
					Type = "tool_use",
					ToolName = (func.TryGetProperty("name", out var fnm) ? (fnm.GetString() ?? "") : ""),
					ToolId = (tc.TryGetProperty("id", out var id) ? (id.GetString() ?? Guid.NewGuid().ToString("N").Substring(0, 12)) : Guid.NewGuid().ToString("N").Substring(0, 12)),
					ToolInput = parsedArgs
				});
				func = default(JsonElement);
				argsEl = default(JsonElement);
				fnm = default(JsonElement);
				id = default(JsonElement);
			}
		}
		return blocks;
	}

	private object BuildOpenAiToolBody(List<ChatMessage> messages, IReadOnlyCollection<IAgentTool> tools)
	{
		LlmSettings llm = _settings.Settings.Llm;
		List<object> list = new List<object>();
		foreach (ChatMessage message in messages)
		{
			if (message.Role == "user" && message.Content.StartsWith("{\"type\":\"tool_result\""))
			{
				try
				{
					using JsonDocument jsonDocument = JsonDocument.Parse(message.Content);
					JsonElement rootElement = jsonDocument.RootElement;
					list.Add(new
					{
						role = "tool",
						tool_call_id = rootElement.GetProperty("tool_use_id").GetString(),
						content = rootElement.GetProperty("content").GetString()
					});
				}
				catch
				{
					goto IL_00d3;
				}
				continue;
			}
			goto IL_00d3;
			IL_0292:
			if (message.Role == "user")
			{
				List<ImageAttachment>? images = message.Images;
				if (images != null && images.Count > 0)
				{
					List<object> list2 = new List<object>();
					foreach (ImageAttachment image in message.Images)
					{
						list2.Add(new
						{
							type = "image_url",
							image_url = new
							{
								url = "data:" + image.MimeType + ";base64," + image.Base64
							}
						});
					}
					list2.Add(new
					{
						type = "text",
						text = message.Content
					});
					list.Add(new
					{
						role = message.Role,
						content = list2
					});
					continue;
				}
			}
			list.Add(new
			{
				role = message.Role,
				content = message.Content
			});
			continue;
			IL_00d3:
			if (message.Role == "assistant" && message.Content.StartsWith("{\"_tool_use_blocks\""))
			{
				try
				{
					using JsonDocument jsonDocument2 = JsonDocument.Parse(message.Content);
					JsonElement property = jsonDocument2.RootElement.GetProperty("_tool_use_blocks");
					string text = "";
					List<object> list3 = new List<object>();
					foreach (JsonElement item in property.EnumerateArray())
					{
						string text2 = item.GetProperty("type").GetString();
						if (text2 == "text")
						{
							text = item.GetProperty("text").GetString() ?? "";
						}
						else if (text2 == "tool_use")
						{
							JsonElement value;
							string arguments = (item.TryGetProperty("input", out value) ? value.GetRawText() : "{}");
							list3.Add(new
							{
								id = (item.GetProperty("id").GetString() ?? ""),
								type = "function",
								function = new
								{
									name = (item.GetProperty("name").GetString() ?? ""),
									arguments = arguments
								}
							});
						}
					}
					list.Add(new
					{
						role = "assistant",
						content = (string.IsNullOrEmpty(text) ? null : text),
						tool_calls = list3
					});
				}
				catch
				{
					goto IL_0292;
				}
				continue;
			}
			goto IL_0292;
		}
		var tools2 = tools.Select(delegate(IAgentTool t)
		{
			Dictionary<string, object> dictionary = new Dictionary<string, object>
			{
				["type"] = "object",
				["properties"] = t.Parameters.Properties.ToDictionary<KeyValuePair<string, ToolProperty>, string, object>((KeyValuePair<string, ToolProperty> kv) => kv.Key, (KeyValuePair<string, ToolProperty> kv) => BuildPropertySchema(kv.Value, upperCaseType: false))
			};
			List<string> required = t.Parameters.Required;
			if (required != null && required.Count > 0)
			{
				dictionary["required"] = t.Parameters.Required;
			}
			return new
			{
				type = "function",
				function = new
				{
					name = t.Name,
					description = t.Description,
					parameters = dictionary
				}
			};
		}).ToArray();
		string text3 = ResolveService();
		string model = ResolveModel();
		if (text3.Equals("ollama", StringComparison.OrdinalIgnoreCase))
		{
			return new
			{
				model = model,
				messages = list,
				tools = tools2,
				stream = false,
				options = new
				{
					temperature = llm.Temperature
				}
			};
		}
		return new
		{
			model = model,
			messages = list,
			tools = tools2,
			stream = false,
			temperature = llm.Temperature,
			max_tokens = llm.MaxContextTokens
		};
	}

	private static object BuildPropertySchema(ToolProperty prop, bool upperCaseType)
	{
		string type = (upperCaseType ? prop.Type.ToUpperInvariant() : prop.Type);
		if (prop.Type.Equals("array", StringComparison.OrdinalIgnoreCase) && prop.Items != null)
		{
			return new
			{
				type = type,
				description = prop.Description,
				items = BuildPropertySchema(prop.Items, upperCaseType)
			};
		}
		List<string> list = prop.Enum;
		if (list != null && list.Count > 0)
		{
			return new
			{
				type = type,
				description = prop.Description,
				@enum = prop.Enum
			};
		}
		return new
		{
			type = type,
			description = prop.Description
		};
	}

	private static string ExtractErrorDetail(string errBody)
	{
		if (string.IsNullOrWhiteSpace(errBody))
		{
			return "응답 없음";
		}
		try
		{
			using JsonDocument jsonDocument = JsonDocument.Parse(errBody);
			if (jsonDocument.RootElement.TryGetProperty("error", out var value))
			{
				if (value.ValueKind == JsonValueKind.String)
				{
					return value.GetString() ?? errBody;
				}
				if (value.ValueKind == JsonValueKind.Object && value.TryGetProperty("message", out var value2))
				{
					return value2.GetString() ?? errBody;
				}
			}
		}
		catch
		{
		}
		return (errBody.Length > 500) ? (errBody.Substring(0, 500) + "…") : errBody;
	}
}
