Forge
csharp4405de34
1#nullable enable
2
3using System.Text.Json;
4using CascadeIDE.Models.AgentChat;
5using CascadeIDE.Models.Intercom;
6
7namespace CascadeIDE.Services.Intercom;
8
9/// <summary>Проекция explicit relate из event log (ADR 0137 contiguous, 0138 disjoint).</summary>
10public static class IntercomMessageRangeRelatedProjector
11{
12 private static readonly JsonSerializerOptions PayloadJson = new(JsonSerializerDefaults.Web);
13
14 public sealed record ExplicitRelate(
15 Guid ThreadId,
16 int StartOrdinal,
17 int EndOrdinal,
18 IReadOnlyList<ChatHistoryMessageOrdinalSegment> OrdinalSegments,
19 AttachmentAnchor CodeRef,
20 string Source);
21
22 public static IReadOnlyList<ExplicitRelate> Project(IReadOnlyList<ChatHistoryEvent> events)
23 {
24 var list = new List<ExplicitRelate>();
25 foreach (var ev in events)
26 {
27 if (!string.Equals(ev.Kind, ChatHistoryEventKind.MessageRangeRelated, StringComparison.Ordinal))
28 continue;
29
30 if (!TryParsePayload(ev.PayloadJson, out var relate))
31 continue;
32
33 list.Add(relate);
34 }
35
36 return list;
37 }
38
39 public static IReadOnlyList<ExplicitRelate> ForThread(
40 IReadOnlyList<ExplicitRelate> all,
41 Guid threadId) =>
42 all.Where(r => r.ThreadId == threadId).ToList();
43
44 private static bool TryParsePayload(string payloadJson, out ExplicitRelate relate)
45 {
46 relate = default!;
47 ChatHistoryMessageRangeRelatedPayload? payload;
48 try
49 {
50 payload = JsonSerializer.Deserialize<ChatHistoryMessageRangeRelatedPayload>(payloadJson, PayloadJson);
51 }
52 catch (JsonException)
53 {
54 return false;
55 }
56
57 if (payload is null
58 || !Guid.TryParse(payload.ThreadId, out var threadId)
59 || threadId == Guid.Empty
60 || string.IsNullOrWhiteSpace(payload.CodeRef.File))
61 {
62 return false;
63 }
64
65 var segments = IntercomMessageRangeRelatedSupport.ResolveSegments(payload);
66 foreach (var segment in segments)
67 {
68 if (segment.StartOrdinal < 1 || segment.EndOrdinal < segment.StartOrdinal)
69 return false;
70 }
71
72 relate = new ExplicitRelate(
73 threadId,
74 payload.StartOrdinal,
75 payload.EndOrdinal,
76 segments,
77 payload.CodeRef,
78 string.IsNullOrWhiteSpace(payload.Source) ? "unknown" : payload.Source);
79 return true;
80 }
81}
82
View only · write via MCP/CIDE