Forge
csharpdeeb25a2
1using System.Text.Json;
2using System.Text.Json.Nodes;
3using CascadeIDE.Models.AgentChat;
4using CascadeIDE.Services.Intercom;
5
6namespace CascadeIDE.Features.Intercom.Transport;
7
8/// <summary>Нормализует входящий wire payload для локального NDJSON (disjoint из <c>relates_to[]</c>).</summary>
9internal static class IntercomTransportPayloadNormalizer
10{
11 public static string NormalizeInbound(string wireKind, string payloadJson)
12 {
13 if (!string.Equals(wireKind, "message_range_related", StringComparison.Ordinal))
14 return payloadJson;
15
16 JsonObject? root;
17 try
18 {
19 root = JsonNode.Parse(payloadJson) as JsonObject;
20 }
21 catch (JsonException)
22 {
23 return payloadJson;
24 }
25
26 if (root is null)
27 return payloadJson;
28
29 if (root["ordinal_segments"] is JsonArray { Count: > 0 })
30 return payloadJson;
31
32 if (root["relates_to"] is not JsonArray relates || relates.Count == 0)
33 return payloadJson;
34
35 var segments = new List<ChatHistoryMessageOrdinalSegment>();
36 foreach (var linkNode in relates)
37 {
38 if (linkNode is not JsonObject link)
39 continue;
40
41 if (link["ordinal_range"] is not JsonObject ordinalRange)
42 continue;
43
44 if (!ordinalRange.TryGetPropertyValue("start_ordinal", out var startNode)
45 || !ordinalRange.TryGetPropertyValue("end_ordinal", out var endNode))
46 {
47 continue;
48 }
49
50 if (startNode is null || endNode is null)
51 continue;
52
53 var start = startNode.GetValue<int>();
54 var end = endNode.GetValue<int>();
55 if (start < 1 || end < start)
56 continue;
57
58 segments.Add(new ChatHistoryMessageOrdinalSegment(start, end));
59 }
60
61 if (segments.Count <= 1)
62 return payloadJson;
63
64 root["ordinal_segments"] = JsonSerializer.SerializeToNode(segments, IntercomTransportJson.Web);
65 root["start_ordinal"] = segments.Min(s => s.StartOrdinal);
66 root["end_ordinal"] = segments.Max(s => s.EndOrdinal);
67
68 return root.ToJsonString(IntercomTransportJson.Web);
69 }
70}
71
View only · write via MCP/CIDE