AX Agent 코워크·코드 흐름과 컨텍스트 관리를 claude-code 기준으로 대폭 정리
- 코워크·코드 프롬프트, 도구 선택, 문서 생성/검증 흐름을 claude-code 동등 품질 기준으로 재정렬함 - OpenAI/vLLM 경로의 오래된 tool history를 평탄화하고 최근 이력만 구조화해 컨텍스트 직렬화를 경량화함 - AX Agent UI를 테마 기준으로 재구성하고 플랜 승인/오버레이/이벤트 렌더링/명령 입력 상호작용을 개선함 - 파일 후보 제안, 반복 경로 정체 복구, LSP 보강, 문서·PPT 처리 개선, 설정/서비스 인터페이스 정리를 함께 반영함 - README.md 및 docs/DEVELOPMENT.md를 작업 시점별로 갱신함 - 검증: dotnet build src/AxCopilot/AxCopilot.csproj -c Release -v minimal -p:OutputPath=bin\\verify\\ -p:IntermediateOutputPath=obj\\verify\\ (경고 0, 오류 0)
This commit is contained in:
@@ -4,6 +4,7 @@ using System.Text.Json;
|
||||
using System.Text.RegularExpressions;
|
||||
using DocumentFormat.OpenXml.Packaging;
|
||||
using DocumentFormat.OpenXml.Spreadsheet;
|
||||
using A = DocumentFormat.OpenXml.Drawing;
|
||||
using UglyToad.PdfPig;
|
||||
|
||||
namespace AxCopilot.Services.Agent;
|
||||
@@ -17,7 +18,7 @@ public class DocumentReaderTool : IAgentTool
|
||||
public string Name => "document_read";
|
||||
public string Description =>
|
||||
"Read a document file and extract its text content. " +
|
||||
"Supports: PDF (.pdf), Word (.docx), Excel (.xlsx), CSV (.csv), text (.txt/.log/.json/.xml/.md), " +
|
||||
"Supports: PDF (.pdf), Word (.docx), PowerPoint (.pptx), Excel (.xlsx), CSV (.csv), text (.txt/.log/.json/.xml/.md), " +
|
||||
"BibTeX (.bib), RIS (.ris). " +
|
||||
"For large files, use 'offset' to read from a specific character position (chunked reading). " +
|
||||
"For large PDFs, use 'pages' parameter to read specific page ranges (e.g., '1-5', '10-20'). " +
|
||||
@@ -79,6 +80,7 @@ public class DocumentReaderTool : IAgentTool
|
||||
{
|
||||
".pdf" => await Task.Run(() => ReadPdf(fullPath, extractMax, pagesParam, sectionParam), ct),
|
||||
".docx" => await Task.Run(() => ReadDocx(fullPath, extractMax), ct),
|
||||
".pptx" => await Task.Run(() => ReadPptx(fullPath, extractMax), ct),
|
||||
".xlsx" => await Task.Run(() => ReadXlsx(fullPath, sheetParam, extractMax), ct),
|
||||
".bib" => await Task.Run(() => ReadBibTeX(fullPath, extractMax), ct),
|
||||
".ris" => await Task.Run(() => ReadRis(fullPath, extractMax), ct),
|
||||
@@ -478,6 +480,71 @@ public class DocumentReaderTool : IAgentTool
|
||||
return Truncate(sb.ToString(), maxChars);
|
||||
}
|
||||
|
||||
// ─── PPTX ───────────────────────────────────────────────────────────────
|
||||
|
||||
private static string ReadPptx(string path, int maxChars)
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
using var doc = PresentationDocument.Open(path, false);
|
||||
var presentation = doc.PresentationPart;
|
||||
if (presentation?.Presentation?.SlideIdList == null)
|
||||
return "(빈 프레젠테이션)";
|
||||
|
||||
var slideIds = presentation.Presentation.SlideIdList.Elements<DocumentFormat.OpenXml.Presentation.SlideId>().ToList();
|
||||
sb.AppendLine($"PowerPoint: {slideIds.Count}개 슬라이드");
|
||||
sb.AppendLine();
|
||||
|
||||
int slideNum = 0;
|
||||
foreach (var slideId in slideIds)
|
||||
{
|
||||
if (sb.Length >= maxChars) break;
|
||||
slideNum++;
|
||||
|
||||
var relId = slideId.RelationshipId?.Value;
|
||||
if (relId == null) continue;
|
||||
|
||||
var slidePart = (SlidePart)presentation.GetPartById(relId);
|
||||
var slide = slidePart.Slide;
|
||||
if (slide == null) continue;
|
||||
|
||||
sb.AppendLine($"--- Slide {slideNum} ---");
|
||||
|
||||
// 슬라이드 내 모든 텍스트 추출 (도형, 텍스트 박스, 테이블 등)
|
||||
var texts = slide.Descendants<A.Text>()
|
||||
.Select(t => t.Text)
|
||||
.Where(t => !string.IsNullOrWhiteSpace(t));
|
||||
|
||||
// 단락(Paragraph) 단위로 그룹핑하여 줄바꿈 유지
|
||||
var paragraphs = slide.Descendants<A.Paragraph>();
|
||||
foreach (var para in paragraphs)
|
||||
{
|
||||
var paraText = string.Join("", para.Descendants<A.Text>().Select(t => t.Text));
|
||||
if (!string.IsNullOrWhiteSpace(paraText))
|
||||
sb.AppendLine(paraText);
|
||||
}
|
||||
|
||||
// 슬라이드 노트가 있으면 포함
|
||||
var notesPart = slidePart.NotesSlidePart;
|
||||
if (notesPart != null)
|
||||
{
|
||||
var noteTexts = notesPart.NotesSlide.Descendants<A.Paragraph>()
|
||||
.Select(p => string.Join("", p.Descendants<A.Text>().Select(t => t.Text)))
|
||||
.Where(t => !string.IsNullOrWhiteSpace(t))
|
||||
.ToList();
|
||||
if (noteTexts.Count > 0)
|
||||
{
|
||||
sb.AppendLine(" [노트]");
|
||||
foreach (var note in noteTexts)
|
||||
sb.AppendLine($" {note}");
|
||||
}
|
||||
}
|
||||
|
||||
sb.AppendLine();
|
||||
}
|
||||
|
||||
return Truncate(sb.ToString(), maxChars);
|
||||
}
|
||||
|
||||
// ─── XLSX ───────────────────────────────────────────────────────────────
|
||||
|
||||
private static string ReadXlsx(string path, string sheetParam, int maxChars)
|
||||
|
||||
Reference in New Issue
Block a user