?? ?? tool_result preview ??? ???? golden workbook ??? ??
?? ?? - ??, ??, ?? ?? tool_result preview? ??? ??? ???? replacement state? ?? ??? ? ??? ??? ?? ??? ?? - XLSX ?? ?? ??? ?? ?? ?? workbook golden ??? ??? summary/dashboard/detail ??? ????? ?? ?? ???? - AgentMessageInvariantHelper? synthetic tool_result preview ?? ??? ??? QueryPreviewContent? ?? ?? ?? ??? tool_use_id, tool_name, ??? content/output/error ?? preview? ????? ?? - BuildToolResultPreviewMap? ?? preview? ?? ???? ?? ?? synthetic preview? ?? ??? ?? - AgentMessageInvariantHelperTests? ??? preview? ?? long tool_result? synthetic preview? ???? ??? explicit preview ?? ?? ??? ?? ?? - AgentQueryContextBuilderTests? synthetic preview? query view ?? ? ?? ???? ???? ????? ?? - ExcelSkillGoldenWorkbookTests? ??? summary/dashboard/detail, formula, data validation, conditional formatting? ??? ?? ?? workbook? Needs work: none ? Repair guide: none? ????? ?? - README.md? docs/DEVELOPMENT.md? 2026-04-15 09:36 (KST) ?? ?? ??? ?? ??? ?? ?? ?? - dotnet build src/AxCopilot/AxCopilot.csproj -c Release -v minimal -p:OutputPath=bin\\verify_preview_golden_finish\\ -p:IntermediateOutputPath=obj\\verify_preview_golden_finish\\ : ?? 0 / ?? 0 - dotnet test src/AxCopilot.Tests/AxCopilot.Tests.csproj -c Release -v minimal --filter "AgentMessageInvariantHelperTests|AgentQueryContextBuilderTests|AgentQueuedCommandProjectorTests|ExcelSkillGoldenWorkbookTests|ExcelSkillDashboardSummaryTests|PptxSkillGoldenDeckTests" -p:OutputPath=bin\\verify_preview_golden_finish_tests\\ -p:IntermediateOutputPath=obj\\verify_preview_golden_finish_tests\\ : ?? 10
This commit is contained in:
@@ -8,13 +8,17 @@ namespace AxCopilot.Services.Agent;
|
||||
/// </summary>
|
||||
internal static class AgentMessageInvariantHelper
|
||||
{
|
||||
private const int SyntheticPreviewTextLimit = 280;
|
||||
|
||||
public static Dictionary<string, string> BuildToolResultPreviewMap(IEnumerable<ChatMessage>? messages)
|
||||
{
|
||||
var previews = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||
if (messages == null)
|
||||
return previews;
|
||||
|
||||
foreach (var message in messages)
|
||||
var bufferedMessages = messages as IList<ChatMessage> ?? messages.ToList();
|
||||
|
||||
foreach (var message in bufferedMessages)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(message.QueryPreviewContent))
|
||||
continue;
|
||||
@@ -24,6 +28,16 @@ internal static class AgentMessageInvariantHelper
|
||||
previews[toolResultId] = message.QueryPreviewContent!;
|
||||
}
|
||||
|
||||
foreach (var message in bufferedMessages)
|
||||
{
|
||||
if (!TryGetToolResultId(message, out var toolResultId) || previews.ContainsKey(toolResultId))
|
||||
continue;
|
||||
if (!TryBuildSyntheticToolResultPreview(message, out var preview))
|
||||
continue;
|
||||
|
||||
previews[toolResultId] = preview;
|
||||
}
|
||||
|
||||
return previews;
|
||||
}
|
||||
|
||||
@@ -164,4 +178,93 @@ internal static class AgentMessageInvariantHelper
|
||||
doc?.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
internal static bool TryBuildSyntheticToolResultPreview(ChatMessage message, out string preview)
|
||||
{
|
||||
preview = "";
|
||||
if (!TryGetToolResultId(message, out var toolResultId))
|
||||
return false;
|
||||
|
||||
var content = message.Content ?? "";
|
||||
if (string.IsNullOrWhiteSpace(content))
|
||||
return false;
|
||||
|
||||
try
|
||||
{
|
||||
using var doc = JsonDocument.Parse(content);
|
||||
var root = doc.RootElement;
|
||||
var toolName = root.TryGetProperty("tool_name", out var toolNameEl)
|
||||
? toolNameEl.GetString()
|
||||
: null;
|
||||
var previewText = ExtractPreviewText(root);
|
||||
if (string.IsNullOrWhiteSpace(previewText))
|
||||
previewText = "tool result available";
|
||||
|
||||
var payload = new Dictionary<string, object?>
|
||||
{
|
||||
["type"] = "tool_result",
|
||||
["tool_use_id"] = toolResultId,
|
||||
["tool_name"] = toolName,
|
||||
["content"] = previewText
|
||||
};
|
||||
|
||||
preview = JsonSerializer.Serialize(payload);
|
||||
return true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static string ExtractPreviewText(JsonElement root)
|
||||
{
|
||||
if (root.TryGetProperty("content", out var contentEl))
|
||||
{
|
||||
var preview = NormalizePreviewText(contentEl.ValueKind switch
|
||||
{
|
||||
JsonValueKind.String => contentEl.GetString() ?? "",
|
||||
JsonValueKind.Object or JsonValueKind.Array => contentEl.GetRawText(),
|
||||
JsonValueKind.Number or JsonValueKind.True or JsonValueKind.False => contentEl.ToString(),
|
||||
_ => ""
|
||||
});
|
||||
if (!string.IsNullOrWhiteSpace(preview))
|
||||
return preview;
|
||||
}
|
||||
|
||||
if (root.TryGetProperty("output", out var outputEl))
|
||||
{
|
||||
var preview = NormalizePreviewText(outputEl.ValueKind switch
|
||||
{
|
||||
JsonValueKind.String => outputEl.GetString() ?? "",
|
||||
JsonValueKind.Object or JsonValueKind.Array => outputEl.GetRawText(),
|
||||
JsonValueKind.Number or JsonValueKind.True or JsonValueKind.False => outputEl.ToString(),
|
||||
_ => ""
|
||||
});
|
||||
if (!string.IsNullOrWhiteSpace(preview))
|
||||
return preview;
|
||||
}
|
||||
|
||||
if (root.TryGetProperty("error", out var errorEl) && errorEl.ValueKind == JsonValueKind.String)
|
||||
return NormalizePreviewText(errorEl.GetString() ?? "");
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
private static string NormalizePreviewText(string text)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(text))
|
||||
return "";
|
||||
|
||||
var collapsed = string.Join(" ", text
|
||||
.Replace('\r', ' ')
|
||||
.Replace('\n', ' ')
|
||||
.Replace('\t', ' ')
|
||||
.Split(' ', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries));
|
||||
|
||||
if (collapsed.Length <= SyntheticPreviewTextLimit)
|
||||
return collapsed;
|
||||
|
||||
return collapsed[..(SyntheticPreviewTextLimit - 3)].TrimEnd() + "...";
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user