claude-code 기준 provider 호환성과 compact 후속 흐름을 보강한다
- OpenAI 호환 tool_choice 400 오류에 대한 일반 fallback을 추가하고 Qwen·LLaMA·DeepSeek 계열 vLLM의 도구 호출 프로파일을 더 보수적으로 조정 - compact 이후 branch context와 최근 tool state를 query view에 재주입하고 UI 표현 수준에 맞춰 compact 카드/컨텍스트 사용 팝업/최종 보고 밀도를 세분화 - README와 DEVELOPMENT 문서 이력을 2026-04-12 23:45 KST 기준으로 갱신 - 검증: 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:
@@ -3517,8 +3517,30 @@ public partial class AgentLoopService
|
||||
"찾을 수 없");
|
||||
}
|
||||
|
||||
private static string GetAgentUiExpressionLevel()
|
||||
{
|
||||
var app = System.Windows.Application.Current as App;
|
||||
var raw = app?.SettingsService?.Settings?.Llm?.AgentUiExpressionLevel;
|
||||
return (raw ?? "balanced").Trim().ToLowerInvariant() switch
|
||||
{
|
||||
"rich" => "rich",
|
||||
"simple" => "simple",
|
||||
_ => "balanced",
|
||||
};
|
||||
}
|
||||
|
||||
private static string BuildFinalReportQualityPrompt(TaskTypePolicy taskPolicy, bool highImpact)
|
||||
{
|
||||
var expressionLevel = GetAgentUiExpressionLevel();
|
||||
|
||||
if (expressionLevel == "simple" && !taskPolicy.IsReviewTask && !highImpact)
|
||||
{
|
||||
return "[System:FinalReportQuality] 최종 답변을 매우 짧게 정리하세요.\n" +
|
||||
"1. 변경 또는 산출물 한 줄\n" +
|
||||
"2. 확인한 근거 한 줄\n" +
|
||||
"실제 미해결 문제가 있을 때만 마지막 한 줄을 추가하세요.";
|
||||
}
|
||||
|
||||
if (!taskPolicy.IsReviewTask && !highImpact)
|
||||
{
|
||||
return "[System:FinalReportQuality] 최종 답변을 짧고 명확하게 정리하세요.\n" +
|
||||
@@ -3531,6 +3553,19 @@ public partial class AgentLoopService
|
||||
var taskLine = taskPolicy.FinalReportTaskLine;
|
||||
var riskLine = "남은 리스크나 추가 확인 필요 사항이 실제로 남아 있을 때만 짧게 적으세요.\n";
|
||||
|
||||
if (expressionLevel == "rich")
|
||||
{
|
||||
return "[System:FinalReportQuality] 최종 답변을 구조적으로 정리하세요.\n" +
|
||||
"1. 무엇을 변경했는지\n" +
|
||||
"2. 어떤 파일/호출부/자료를 확인했는지\n" +
|
||||
"3. 어떤 build/test/검증 근거가 있는지\n" +
|
||||
"4. 실제 파일 경로 또는 파일명 1~3개를 명시하세요\n" +
|
||||
"5. review 작업이면 이슈별 상태를 구분하세요\n" +
|
||||
taskLine +
|
||||
riskLine +
|
||||
"후속 권유는 실제 미해결 위험이 남아 있을 때만 포함하세요.";
|
||||
}
|
||||
|
||||
return "[System:FinalReportQuality] 최종 답변을 더 구조적으로 정리하세요.\n" +
|
||||
"1. 무엇을 변경했는지\n" +
|
||||
"2. 어떤 파일/호출부를 확인했는지\n" +
|
||||
|
||||
@@ -157,21 +157,39 @@ public static class AgentQueryContextBuilder
|
||||
string.Equals(m.MetaKind, "microcompact_boundary", StringComparison.OrdinalIgnoreCase)
|
||||
|| string.Equals(m.MetaKind, "session_memory_compaction", StringComparison.OrdinalIgnoreCase)
|
||||
|| string.Equals(m.MetaKind, "collapsed_boundary", StringComparison.OrdinalIgnoreCase));
|
||||
var branchContextCount = messages.Count(m =>
|
||||
string.Equals(m.MetaKind, "branch_context", StringComparison.OrdinalIgnoreCase));
|
||||
var structuredToolHistoryCount = messages.Count(m =>
|
||||
{
|
||||
var content = m.Content ?? "";
|
||||
return content.StartsWith("{\"_tool_use_blocks\"", StringComparison.Ordinal)
|
||||
|| content.StartsWith("{\"type\":\"tool_result\"", StringComparison.Ordinal);
|
||||
});
|
||||
var recentToolNames = messages
|
||||
.Where(m => m.Role == "user")
|
||||
.Select(m => TryExtractToolResultToolName(m, out var toolName) ? toolName : "")
|
||||
.Where(toolName => !string.IsNullOrWhiteSpace(toolName))
|
||||
.Distinct(StringComparer.OrdinalIgnoreCase)
|
||||
.Take(4)
|
||||
.ToList();
|
||||
|
||||
if (attachedFiles.Count == 0 && imageCount == 0 && compactSummaryCount == 0 && structuredToolHistoryCount == 0)
|
||||
if (attachedFiles.Count == 0
|
||||
&& imageCount == 0
|
||||
&& compactSummaryCount == 0
|
||||
&& structuredToolHistoryCount == 0
|
||||
&& branchContextCount == 0
|
||||
&& recentToolNames.Count == 0)
|
||||
return;
|
||||
|
||||
var lines = new List<string> { "[post-compact context]" };
|
||||
if (compactSummaryCount > 0)
|
||||
lines.Add($"restored compact summaries: {compactSummaryCount}");
|
||||
if (branchContextCount > 0)
|
||||
lines.Add($"restored branch context: {branchContextCount}");
|
||||
if (structuredToolHistoryCount > 0)
|
||||
lines.Add($"restored tool history blocks: {structuredToolHistoryCount}");
|
||||
if (recentToolNames.Count > 0)
|
||||
lines.Add("restored recent tools: " + string.Join(", ", recentToolNames));
|
||||
if (attachedFiles.Count > 0)
|
||||
lines.Add("restored file refs: " + string.Join(", ", attachedFiles));
|
||||
if (imageCount > 0)
|
||||
@@ -190,4 +208,28 @@ public static class AgentQueryContextBuilder
|
||||
AttachedFiles = attachedFiles.Count > 0 ? attachedFiles : null,
|
||||
});
|
||||
}
|
||||
|
||||
private static bool TryExtractToolResultToolName(ChatMessage message, out string toolName)
|
||||
{
|
||||
toolName = "";
|
||||
if (!string.Equals(message.Role, "user", StringComparison.OrdinalIgnoreCase)
|
||||
|| string.IsNullOrWhiteSpace(message.Content)
|
||||
|| !message.Content.StartsWith("{\"type\":\"tool_result\"", StringComparison.Ordinal))
|
||||
return false;
|
||||
|
||||
try
|
||||
{
|
||||
using var doc = System.Text.Json.JsonDocument.Parse(message.Content);
|
||||
if (doc.RootElement.TryGetProperty("tool_name", out var toolNameEl))
|
||||
{
|
||||
toolName = toolNameEl.GetString() ?? "";
|
||||
return !string.IsNullOrWhiteSpace(toolName);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user