feat: P&ID 연결 분석, LLM 에이전트 모드, KB 확장, MCP 서버 리팩토링

- P&ID: 연결 분석 API, Prefix 규칙 관리, 카테고리 분류, DXF 그래프 빌드
- LLM: 대화 요약, tool card 영구 보존, 시계열 차트(uPlot), 에이전트 모드
- KB: 청크 미리보기, Field Instrument Inference, 인증/Qdrant 클라이언트
- MCP: 서버 기능 확장, 파이프라인 수정, timeout 개선
- Frontend: P&ID UI, LLM UI, KB UI, OPC UA Write 탭 추가
- 설정: AGENTS.md, plant_context, README, opencode.json 업데이트
- 정리: 진단 체크리스트 문서 삭제
This commit is contained in:
windpacer
2026-05-21 23:36:57 +09:00
parent 960bda4a3c
commit 302183c97e
142 changed files with 2432231 additions and 1082 deletions

View File

@@ -20,6 +20,7 @@ var mvcBuilder = builder.Services.AddControllers()
// JSON 직렬화 시 대소문자 구분 없이 처리하도록 PascalCase 유지
opt.JsonSerializerOptions.PropertyNamingPolicy = null;
});
builder.Services.AddMemoryCache();
// ── P&ID 컨트롤러 조건부 활성화 (기본: 비활성화) ─────────────────────────────
// PidControllers:Enabled = true 로 설정 시 P&ID 관련 컨트롤러 활성화
@@ -46,6 +47,7 @@ builder.Services.AddSingleton<IExperionCertificateService, ExperionCertificateSe
builder.Services.AddSingleton<IExperionStatusCodeService, ExperionStatusCodeService>();
builder.Services.AddSingleton<IOpcUaConfigProvider, OpcUaConfigProvider>();
builder.Services.AddScoped<IExperionOpcClient, ExperionOpcClient>();
builder.Services.AddScoped<IExperionOpcWriteClient, ExperionOpcWriteClient>();
builder.Services.AddScoped<IExperionCsvService, ExperionCsvService>();
builder.Services.AddScoped<AssetLoader>();
@@ -87,9 +89,15 @@ builder.Services.AddHostedService<DigitalEventDetectorService>();
// ── MCP Service ───────────────────────────────────────────────────────────────
// Python MCP 서버 (localhost:5001)와 통신
// McpClient: 저수준 HTTP 클라이언트 / McpService: IMcpService 구현 (McpClient 위임)
// NOTE: 팩토리 등록 — DI가 HttpClient를 주입하면 BaseAddress 미설정 상태가 되므로
// 직접 생성자 호출하여 자체 HttpClient를 사용하도록 함
builder.Services.AddSingleton<McpClient>(_ => new McpClient());
// IHttpClientFactory 패턴: 핸들러 재사용으로 소켓 고갈 방지, 기본 타임아웃 명시
builder.Services.AddHttpClient(McpClient.HttpClientName, c =>
{
c.BaseAddress = new Uri("http://localhost:5001");
// HttpClient.Timeout = 하드 상한. McpClient 내부에서 소프트(120s)→연장(300s) 2단계 적용.
// ExtendedTimeoutSeconds(300) + 네트워크/직렬화 여유 60s.
c.Timeout = TimeSpan.FromSeconds(McpClient.ExtendedTimeoutSeconds + 60);
}).SetHandlerLifetime(TimeSpan.FromMinutes(5));
builder.Services.AddSingleton<McpClient>();
builder.Services.AddSingleton<IMcpService, McpService>();
builder.Services.AddHostedService<McpServerHostedService>();
@@ -145,13 +153,27 @@ builder.Services.AddHttpClient("Ollama", c =>
// ── vLLM HttpClient (OpenAI-compatible) ──────────────────────────────────────
builder.Services.AddHttpClient("Vllm", c =>
{
c.BaseAddress = new Uri("http://localhost:8000");
c.BaseAddress = new Uri("http://localhost:8001");
c.Timeout = TimeSpan.FromSeconds(1800);
}).SetHandlerLifetime(Timeout.InfiniteTimeSpan);
// ── CORS ──────────────────────────────────────────────────────────────────────
// appsettings.json 의 "Cors:AllowedOrigins" 배열을 화이트리스트로 사용.
// 미설정 또는 ["*"] 인 경우에만 AllowAnyOrigin (개발 편의). 운영에서는 명시적 origin 권장.
builder.Services.AddCors(opt =>
opt.AddDefaultPolicy(p => p.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader()));
opt.AddDefaultPolicy(p =>
{
var origins = builder.Configuration.GetSection("Cors:AllowedOrigins").Get<string[]>();
if (origins == null || origins.Length == 0 || (origins.Length == 1 && origins[0] == "*"))
{
// 자격증명 미사용 + 내부망 가정: 와일드카드 허용 (역호환)
p.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader();
}
else
{
p.WithOrigins(origins).AllowAnyMethod().AllowAnyHeader();
}
}));
// ── 포트 설정 (Ubuntu 환경: 기본 5000) ───────────────────────────────────────
builder.WebHost.UseUrls("http://0.0.0.0:5000");