에이전트 루프와 코드 언어 지원, PPT 생성 품질을 함께 고도화
- AgentCommandQueue를 도입해 실행 중 추가 입력을 우선순위와 인터럽트 여부까지 포함해 처리하도록 정리함 - AgentToolResultBudget와 AgentQueryContextBuilder에 tool result preview 캐시를 연결해 긴 세션에서 축약 결과 재사용을 안정화함 - CodeLanguageCatalog를 추가해 코드 탭의 내장 언어 지원, 인덱싱 확장자, 시스템 프롬프트 언어 가이드, LSP 언어 판정을 한 카탈로그로 통합함 - 설정의 코드 탭에 지원 언어(LSP)와 코드 탭 기본 지원 언어를 명시적으로 표시하도록 보강함 - DocumentPlannerTool의 presentation 구조를 컨설팅형 스토리라인으로 정리하고, PptxSkill에 executive_summary/recommendation/roadmap/comparison/kpi_dashboard 레이아웃을 추가함 - pptx-creator 스킬을 AX native pptx_create 중심으로 재작성하고, 관련 회귀 테스트를 추가했으며 WorkspaceContextGeneratorTests의 nullable 경고도 정리함 검증 결과 - dotnet build src/AxCopilot/AxCopilot.csproj -c Release -v minimal -p:OutputPath=bin\\verify_impl\\ -p:IntermediateOutputPath=obj\\verify_impl\\ - dotnet test src/AxCopilot.Tests/AxCopilot.Tests.csproj -c Release -v minimal --filter "CodeLanguageCatalogTests|AgentCommandQueueTests|AgentToolResultBudgetTests|DocumentPlannerPresentationTests|PptxSkillConsultingDeckTests" -p:OutputPath=bin\\verify_impl_tests\\ -p:IntermediateOutputPath=obj\\verify_impl_tests\\
This commit is contained in:
304
src/AxCopilot/Services/CodeLanguageCatalog.cs
Normal file
304
src/AxCopilot/Services/CodeLanguageCatalog.cs
Normal file
@@ -0,0 +1,304 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace AxCopilot.Services;
|
||||
|
||||
public sealed record CodeLanguageCapability(
|
||||
string Key,
|
||||
string DisplayName,
|
||||
IReadOnlyList<string> Extensions,
|
||||
IReadOnlyList<string> Guidance,
|
||||
string? LspLanguageId = null,
|
||||
bool ShowInQuickSelect = false,
|
||||
string? QuickSelectKey = null,
|
||||
string? QuickSelectLabel = null,
|
||||
string? QuickSelectIcon = null);
|
||||
|
||||
/// <summary>
|
||||
/// 코드 탭과 에이전트가 공통으로 참조하는 언어 지원 카탈로그.
|
||||
/// - 파일 분류
|
||||
/// - 인덱싱 대상 확장자
|
||||
/// - 시스템 프롬프트 언어 가이드
|
||||
/// - LSP 연동 가능 언어
|
||||
/// - 설정 UI 설명 문자열
|
||||
/// 를 한 곳에서 관리합니다.
|
||||
/// </summary>
|
||||
public static class CodeLanguageCatalog
|
||||
{
|
||||
private static readonly ReadOnlyCollection<CodeLanguageCapability> s_all =
|
||||
new(new List<CodeLanguageCapability>
|
||||
{
|
||||
new(
|
||||
"csharp",
|
||||
"C# (.NET)",
|
||||
[".cs", ".csx", ".csproj", ".sln"],
|
||||
[
|
||||
"Use dotnet CLI, solution/project files, and NuGet package conventions.",
|
||||
"Follow Microsoft naming conventions and prefer targeted edits over broad rewrites.",
|
||||
"Verify impact on callers, DI registration, nullable flow, and build configuration."
|
||||
],
|
||||
LspLanguageId: "csharp",
|
||||
ShowInQuickSelect: true,
|
||||
QuickSelectKey: "csharp",
|
||||
QuickSelectLabel: "C# (.NET)",
|
||||
QuickSelectIcon: "\uD83D\uDD39"),
|
||||
new(
|
||||
"python",
|
||||
"Python",
|
||||
[".py", ".pyi", ".ipynb"],
|
||||
[
|
||||
"Use pip/venv or conda only if already available in the environment.",
|
||||
"Follow PEP 8, type hints, and module/package boundaries.",
|
||||
"Prefer small focused functions and verify import/runtime errors after edits."
|
||||
],
|
||||
LspLanguageId: "python",
|
||||
ShowInQuickSelect: true,
|
||||
QuickSelectKey: "python",
|
||||
QuickSelectLabel: "Python",
|
||||
QuickSelectIcon: "\uD83D\uDC0D"),
|
||||
new(
|
||||
"java",
|
||||
"Java",
|
||||
[".java", ".gradle", ".pom"],
|
||||
[
|
||||
"Use Maven or Gradle conventions already present in the repository.",
|
||||
"Follow package structure, visibility rules, and style consistent with the existing codebase.",
|
||||
"Check interfaces, implementations, and test fixtures together when modifying shared behavior."
|
||||
],
|
||||
LspLanguageId: "java",
|
||||
ShowInQuickSelect: true,
|
||||
QuickSelectKey: "java",
|
||||
QuickSelectLabel: "Java",
|
||||
QuickSelectIcon: "\u2615"),
|
||||
new(
|
||||
"cpp",
|
||||
"C / C++",
|
||||
[".c", ".cc", ".cxx", ".cpp", ".h", ".hh", ".hpp", ".inl"],
|
||||
[
|
||||
"Respect the repository's existing build system, usually CMake, MSBuild, or compiler-specific scripts.",
|
||||
"Be careful with headers, include order, ownership, ABI-sensitive changes, and platform guards.",
|
||||
"Validate both declaration and implementation impact when editing shared types."
|
||||
],
|
||||
LspLanguageId: "cpp",
|
||||
ShowInQuickSelect: true,
|
||||
QuickSelectKey: "cpp",
|
||||
QuickSelectLabel: "C/C++",
|
||||
QuickSelectIcon: "\u2699"),
|
||||
new(
|
||||
"typescript",
|
||||
"TypeScript",
|
||||
[".ts", ".tsx", ".mts", ".cts"],
|
||||
[
|
||||
"Use the existing package manager and tsconfig structure.",
|
||||
"Prefer explicit types on public boundaries and check build/lint config before changing module format.",
|
||||
"Preserve framework conventions already used by the project."
|
||||
],
|
||||
LspLanguageId: "typescript"),
|
||||
new(
|
||||
"javascript",
|
||||
"JavaScript / Vue",
|
||||
[".js", ".jsx", ".mjs", ".cjs", ".vue"],
|
||||
[
|
||||
"Use the existing Node package manager and lint/format rules.",
|
||||
"For Vue, preserve the current component style and API pattern used by the project.",
|
||||
"Check module boundaries, imports, and runtime side effects after edits."
|
||||
],
|
||||
LspLanguageId: "javascript",
|
||||
ShowInQuickSelect: true,
|
||||
QuickSelectKey: "javascript",
|
||||
QuickSelectLabel: "JavaScript / Vue",
|
||||
QuickSelectIcon: "\uD83C\uDF10"),
|
||||
new(
|
||||
"go",
|
||||
"Go",
|
||||
[".go", ".mod", ".sum"],
|
||||
[
|
||||
"Preserve package boundaries, error-first flow, and gofmt-style formatting.",
|
||||
"Check interfaces, exported identifiers, and concurrency-sensitive changes together."
|
||||
]),
|
||||
new(
|
||||
"rust",
|
||||
"Rust",
|
||||
[".rs", ".toml"],
|
||||
[
|
||||
"Respect Cargo workspace structure, ownership/borrowing rules, and crate boundaries.",
|
||||
"Prefer explicit enums/results and verify compiler diagnostics after edits."
|
||||
]),
|
||||
new(
|
||||
"php",
|
||||
"PHP",
|
||||
[".php", ".phtml"],
|
||||
[
|
||||
"Follow the framework and autoloading structure already present in the project.",
|
||||
"Be careful with runtime includes, container wiring, and mixed template/application files."
|
||||
]),
|
||||
new(
|
||||
"ruby",
|
||||
"Ruby",
|
||||
[".rb", ".rake", ".gemspec"],
|
||||
[
|
||||
"Preserve gem structure, Rails or plain Ruby conventions already used in the repository.",
|
||||
"Check dynamic dispatch, concerns/modules, and tests together after edits."
|
||||
]),
|
||||
new(
|
||||
"kotlin",
|
||||
"Kotlin",
|
||||
[".kt", ".kts"],
|
||||
[
|
||||
"Preserve Gradle structure, package layout, and nullability intent.",
|
||||
"Be careful with JVM interop boundaries and Android-specific module structure when present."
|
||||
]),
|
||||
new(
|
||||
"swift",
|
||||
"Swift",
|
||||
[".swift"],
|
||||
[
|
||||
"Preserve target structure, Apple framework imports, and protocol-oriented design already in use.",
|
||||
"Check app lifecycle and platform-specific behavior after edits."
|
||||
]),
|
||||
new(
|
||||
"scala",
|
||||
"Scala",
|
||||
[".scala", ".sc"],
|
||||
[
|
||||
"Respect sbt/module structure, functional style, and existing typeclass or Akka patterns if present.",
|
||||
"Keep public APIs simple and avoid unnecessary type-level churn."
|
||||
]),
|
||||
new(
|
||||
"shell",
|
||||
"Shell",
|
||||
[".sh", ".bash", ".zsh"],
|
||||
[
|
||||
"Prefer safe quoting, explicit exit handling, and repository-local scripts over one-off inline shell.",
|
||||
"Check portability assumptions and environment-specific commands."
|
||||
]),
|
||||
new(
|
||||
"powershell",
|
||||
"PowerShell",
|
||||
[".ps1", ".psm1", ".psd1", ".bat", ".cmd"],
|
||||
[
|
||||
"Prefer native PowerShell cmdlets and safe path handling.",
|
||||
"Be careful with Windows-specific side effects, quoting, and admin-sensitive operations."
|
||||
]),
|
||||
new(
|
||||
"sql",
|
||||
"SQL",
|
||||
[".sql"],
|
||||
[
|
||||
"Preserve migration ordering, transactional safety, and index/constraint compatibility.",
|
||||
"Call out destructive or data-migrating changes explicitly."
|
||||
]),
|
||||
new(
|
||||
"web",
|
||||
"HTML / CSS / SCSS",
|
||||
[".html", ".htm", ".css", ".scss", ".sass", ".less", ".xaml"],
|
||||
[
|
||||
"Preserve the existing design system, layout structure, and accessibility semantics.",
|
||||
"Prefer incremental visual changes and keep selectors/components scoped."
|
||||
]),
|
||||
new(
|
||||
"markup",
|
||||
"JSON / YAML / XML / Markdown",
|
||||
[".json", ".jsonc", ".xml", ".yaml", ".yml", ".md", ".txt"],
|
||||
[
|
||||
"Preserve schema shape, indentation style, and comment/document conventions already used in the repository.",
|
||||
"Validate references, keys, and generated consumer impact after edits."
|
||||
]),
|
||||
});
|
||||
|
||||
private static readonly ReadOnlyDictionary<string, CodeLanguageCapability> s_byKey =
|
||||
new(s_all.ToDictionary(x => x.Key, StringComparer.OrdinalIgnoreCase));
|
||||
|
||||
private static readonly ReadOnlyDictionary<string, CodeLanguageCapability> s_byExtension =
|
||||
new(s_all
|
||||
.SelectMany(cap => cap.Extensions.Select(ext => new KeyValuePair<string, CodeLanguageCapability>(ext, cap)))
|
||||
.ToDictionary(x => x.Key, x => x.Value, StringComparer.OrdinalIgnoreCase));
|
||||
|
||||
private static readonly HashSet<string> s_codeExtensions = new(
|
||||
s_all.SelectMany(cap => cap.Extensions),
|
||||
StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
public static IReadOnlyList<CodeLanguageCapability> All => s_all;
|
||||
|
||||
public static IReadOnlyCollection<string> CodeExtensions => s_codeExtensions;
|
||||
|
||||
public static IReadOnlyList<CodeLanguageCapability> QuickSelectLanguages =>
|
||||
s_all.Where(x => x.ShowInQuickSelect).ToList();
|
||||
|
||||
public static IReadOnlyList<CodeLanguageCapability> LspBackedLanguages =>
|
||||
s_all.Where(x => !string.IsNullOrWhiteSpace(x.LspLanguageId)).ToList();
|
||||
|
||||
public static bool IsCodeLikeFile(string? extension)
|
||||
=> !string.IsNullOrWhiteSpace(extension) && s_codeExtensions.Contains(extension);
|
||||
|
||||
public static CodeLanguageCapability? FindByKey(string? key)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(key))
|
||||
return null;
|
||||
return s_byKey.TryGetValue(key.Trim(), out var found) ? found : null;
|
||||
}
|
||||
|
||||
public static CodeLanguageCapability? FindByExtension(string? extension)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(extension))
|
||||
return null;
|
||||
return s_byExtension.TryGetValue(extension.Trim(), out var found) ? found : null;
|
||||
}
|
||||
|
||||
public static string? DetectLspLanguageId(string? filePath)
|
||||
=> FindByExtension(Path.GetExtension(filePath ?? string.Empty))?.LspLanguageId;
|
||||
|
||||
public static string GetQuickSelectLabel(string? key)
|
||||
=> FindByKey(key)?.DisplayName ?? key ?? "Auto";
|
||||
|
||||
public static string BuildSelectedLanguagePrompt(string? key)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(key) || string.Equals(key, "auto", StringComparison.OrdinalIgnoreCase))
|
||||
return string.Empty;
|
||||
|
||||
var capability = FindByKey(key);
|
||||
if (capability == null)
|
||||
return string.Empty;
|
||||
|
||||
return $"IMPORTANT: User selected language: {capability.DisplayName}. Prioritize this language for code analysis and generation.";
|
||||
}
|
||||
|
||||
public static IEnumerable<string> GetGuidanceLines(string? selectedKey)
|
||||
{
|
||||
var selected = FindByKey(selectedKey);
|
||||
if (selected != null)
|
||||
{
|
||||
foreach (var line in selected.Guidance)
|
||||
yield return $"- {selected.DisplayName}: {line}";
|
||||
yield break;
|
||||
}
|
||||
|
||||
foreach (var capability in s_all.Where(x =>
|
||||
x.Key is "csharp" or "python" or "java" or "cpp" or "typescript" or "javascript" or "go" or "rust" or "kotlin" or "swift"))
|
||||
{
|
||||
var summary = capability.Guidance.FirstOrDefault();
|
||||
if (!string.IsNullOrWhiteSpace(summary))
|
||||
yield return $"- {capability.DisplayName}: {summary}";
|
||||
}
|
||||
}
|
||||
|
||||
public static string BuildLspSupportDescription()
|
||||
=> string.Join(", ", LspBackedLanguages.Select(x => x.DisplayName));
|
||||
|
||||
public static string BuildStaticSupportDescription()
|
||||
=> string.Join(", ", s_all.Select(x => x.DisplayName));
|
||||
|
||||
public static string BuildCodeTabSupportDescription()
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
sb.Append("정적 분류/검색/프롬프트 지원: ");
|
||||
sb.Append(BuildStaticSupportDescription());
|
||||
sb.Append(" | LSP 심화 분석: ");
|
||||
sb.Append(BuildLspSupportDescription());
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user