| 1 | #nullable enable |
| 2 | |
| 3 | using System.Text.Json; |
| 4 | using System.Text.Json.Serialization; |
| 5 | using CasaField.Core; |
| 6 | using CascadeIDE.Features.Workspace; |
| 7 | |
| 8 | namespace CascadeIDE.Features.CasaField.Application; |
| 9 | |
| 10 | /// <summary>Native C# hot path: decode field grid + SN/CEN (parity with sn_cen_infer --from-field).</summary> |
| 11 | public static class CasaFieldHotPathRunner |
| 12 | { |
| 13 | private static readonly JsonSerializerOptions JsonOptions = new() |
| 14 | { |
| 15 | PropertyNamingPolicy = JsonNamingPolicy.CamelCase, |
| 16 | DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, |
| 17 | WriteIndented = false, |
| 18 | }; |
| 19 | |
| 20 | public static string BuildJson(string? workspaceRoot, string? query) |
| 21 | { |
| 22 | var store = CasaFieldStoreResolver.ResolveStoreDirectory(workspaceRoot); |
| 23 | if (store is null || !Directory.Exists(store)) |
| 24 | return """{"error":"store_missing"}"""; |
| 25 | |
| 26 | try |
| 27 | { |
| 28 | var result = CasaFieldHotPath.Run(store, query); |
| 29 | var payload = new |
| 30 | { |
| 31 | pipeline = "casa_field_hot_path_csharp_v2", |
| 32 | wallMs = result.WallMs, |
| 33 | fieldVersion = result.FieldVersion, |
| 34 | stale = result.Stale, |
| 35 | decoded = new |
| 36 | { |
| 37 | conceptCount = result.Decoded.ConceptIds.Count, |
| 38 | edgeCount = result.Decoded.Edges.Count, |
| 39 | }, |
| 40 | sn = new |
| 41 | { |
| 42 | mode = result.Sn.Mode, |
| 43 | ports = result.Sn.Ports, |
| 44 | cenOpen = result.Sn.CenOpen, |
| 45 | }, |
| 46 | cen = new |
| 47 | { |
| 48 | intent = result.Cen.Intent, |
| 49 | action = result.Cen.Action, |
| 50 | concepts = result.Cen.Concepts, |
| 51 | targets = result.Cen.Targets.Select(t => new |
| 52 | { |
| 53 | kind = t.Kind, |
| 54 | conceptId = t.ConceptId, |
| 55 | docPath = t.DocPath, |
| 56 | section = t.Section, |
| 57 | file = t.File, |
| 58 | line = t.Line, |
| 59 | }), |
| 60 | taskBand = result.Cen.TaskBand, |
| 61 | queryToDmn = result.Cen.QueryToDmn, |
| 62 | confidence = result.Cen.Confidence, |
| 63 | answerBlocks = result.Cen.AnswerBlocks.Select(b => new |
| 64 | { |
| 65 | conceptId = b.ConceptId, |
| 66 | text = b.Text, |
| 67 | section = b.Section, |
| 68 | docPath = b.DocPath, |
| 69 | score = b.Score, |
| 70 | claimKind = b.ClaimKind, |
| 71 | }), |
| 72 | }, |
| 73 | }; |
| 74 | return JsonSerializer.Serialize(payload, JsonOptions); |
| 75 | } |
| 76 | catch (Exception ex) |
| 77 | { |
| 78 | return JsonSerializer.Serialize(new { error = ex.Message }, JsonOptions); |
| 79 | } |
| 80 | } |
| 81 | } |
| 82 | |