Files
AX-Copilot-Codex/src/AxCopilot/Services/ServerStatusService.cs
lacvet 1b4a2bfb1c AX Agent 진행 시간·글로우 경로 정리 및 최근 로컬 변경 일괄 반영
- AX Agent 스트리밍 경과 시간을 공용 helper로 통일해 비정상적인 수천만 시간 표시를 방지함

- 채팅 입력창 글로우를 런처와 같은 표시/숨김 중심의 얇은 외곽 글로우로 정리하고 런처 글로우 설정은 일반 설정에 유지함

- README와 DEVELOPMENT 문서를 2026-04-08 12:02 (KST) 기준으로 갱신하고 Release 빌드 경고 0 / 오류 0을 확인함
2026-04-08 23:20:53 +09:00

116 lines
3.2 KiB
C#

using System.Net.Http;
using AxCopilot.Models;
namespace AxCopilot.Services;
internal sealed class ServerStatusService
{
public static readonly ServerStatusService Instance = new();
private static readonly HttpClient Http = new()
{
Timeout = TimeSpan.FromMilliseconds(1500)
};
public bool OllamaOnline { get; private set; }
public bool LlmOnline { get; private set; }
public bool McpOnline { get; private set; }
public string McpName { get; private set; } = "MCP";
public event EventHandler? StatusChanged;
private System.Threading.Timer? _timer;
private string _ollamaEndpoint = "http://localhost:11434";
private string _llmEndpoint = "";
private string _llmService = "Ollama";
private string _mcpEndpoint = "";
private ServerStatusService() { }
public void Start(AppSettings? settings = null)
{
LoadEndpoints(settings);
if (_timer != null)
return;
_timer = new System.Threading.Timer(async _ => await CheckAllAsync(), null, 0, 60000);
}
public void Stop()
{
_timer?.Dispose();
_timer = null;
}
public void Refresh(AppSettings? settings = null)
{
LoadEndpoints(settings);
_ = CheckAllAsync();
}
private void LoadEndpoints(AppSettings? settings)
{
var llm = settings?.Llm;
if (llm == null)
return;
_ollamaEndpoint = llm.OllamaEndpoint?.TrimEnd('/') ?? "http://localhost:11434";
_llmService = llm.Service ?? "Ollama";
_llmEndpoint = string.Equals(_llmService, "vLLM", StringComparison.OrdinalIgnoreCase)
? (llm.VllmEndpoint?.TrimEnd('/') ?? "")
: _ollamaEndpoint;
var mcp = llm.McpServers?.FirstOrDefault(s => s.Enabled && !string.IsNullOrWhiteSpace(s.Url));
if (mcp != null)
{
McpName = mcp.Name;
_mcpEndpoint = mcp.Url?.TrimEnd('/') ?? "";
}
else
{
McpName = "MCP";
_mcpEndpoint = "";
}
}
private async Task CheckAllAsync()
{
var ollamaTask = PingAsync(_ollamaEndpoint + "/api/version");
var llmTask = string.IsNullOrEmpty(_llmEndpoint) || _llmEndpoint == _ollamaEndpoint
? ollamaTask
: PingAsync(_llmEndpoint);
var mcpTask = string.IsNullOrEmpty(_mcpEndpoint)
? Task.FromResult(false)
: PingAsync(_mcpEndpoint);
await Task.WhenAll(ollamaTask, llmTask, mcpTask).ConfigureAwait(false);
var changed = OllamaOnline != ollamaTask.Result ||
LlmOnline != llmTask.Result ||
McpOnline != mcpTask.Result;
OllamaOnline = ollamaTask.Result;
LlmOnline = llmTask.Result;
McpOnline = mcpTask.Result;
if (changed)
StatusChanged?.Invoke(this, EventArgs.Empty);
}
private static async Task<bool> PingAsync(string url)
{
if (string.IsNullOrWhiteSpace(url))
return false;
try
{
var resp = await Http.GetAsync(url).ConfigureAwait(false);
return resp.IsSuccessStatusCode || (int)resp.StatusCode < 500;
}
catch
{
return false;
}
}
}