My agentic slop goes here. Not intended for anyone else!
1(** JMAP SearchSnippet Type
2
3 A SearchSnippet contains highlighted text snippets from an Email,
4 showing where search terms matched in the subject and body. This is
5 typically used to show search results with context.
6
7open Jmap_core
8
9 SearchSnippets are generated on-demand by SearchSnippet/get and are not
10 stored objects (they have no state, cannot be modified, etc.).
11
12 Reference: RFC 8621 Section 5 (Search Snippets)
13 Test files:
14 - test/data/mail/search_snippet_request.json
15 - test/data/mail/search_snippet_response.json
16*)
17
18(** SearchSnippet object type (RFC 8621 Section 5.1)
19
20 SearchSnippets are keyed by email ID and contain highlighted excerpts.
21 The <mark> tags indicate where the search terms matched.
22*)
23type t = {
24 email_id : Jmap_core.Id.t; (** Email ID this snippet is for *)
25 subject : string option; (** Subject with search terms highlighted using <mark> tags *)
26 preview : string option; (** Preview text with search terms highlighted using <mark> tags *)
27}
28
29(** Accessors *)
30let email_id t = t.email_id
31let subject t = t.subject
32let preview t = t.preview
33
34(** Constructor *)
35let v ~email_id ?subject ?preview () =
36 { email_id; subject; preview }
37
38(** SearchSnippet/get method (RFC 8621 Section 5.2)
39
40 This is the only method for SearchSnippets. It takes a filter and a list
41 of email IDs, and returns highlighted snippets showing where the filter
42 matched in each email.
43
44 Unlike standard /get methods, this requires a filter to know what to highlight.
45*)
46module Get = struct
47 type request = {
48 account_id : Jmap_core.Id.t;
49 filter : Jmap_email.Filter.t Jmap_core.Filter.t; (** Filter to apply for highlighting *)
50 email_ids : Jmap_core.Id.t list; (** Email IDs to get snippets for *)
51 }
52
53 type response = {
54 account_id : Jmap_core.Id.t;
55 list : t list; (** SearchSnippets for requested emails *)
56 not_found : Jmap_core.Id.t list; (** Email IDs that don't exist *)
57 }
58
59 (** Accessors for request *)
60 let account_id (r : request) = r.account_id
61 let filter (r : request) = r.filter
62 let email_ids (r : request) = r.email_ids
63
64 (** Constructor for request *)
65 let request_v ~account_id ~filter ~email_ids =
66 { account_id; filter; email_ids }
67
68 (** Accessors for response *)
69 let response_account_id (r : response) = r.account_id
70 let list (r : response) = r.list
71 let not_found r = r.not_found
72
73 (** Constructor for response *)
74 let response_v ~account_id ~list ~not_found =
75 { account_id; list; not_found }
76
77 (** Parse get request from JSON.
78 Test files: test/data/mail/search_snippet_request.json
79
80 Expected structure:
81 {
82 "accountId": "u123456",
83 "filter": {
84 "text": "project milestone"
85 },
86 "emailIds": ["e001", "e005", "e008"]
87 }
88 *)
89 let request_of_json _json =
90 raise (Jmap_core.Error.Parse_error "SearchSnippet.Get.request_of_json not yet implemented")
91
92 (** Parse get response from JSON.
93 Test files: test/data/mail/search_snippet_response.json
94
95 Expected structure:
96 {
97 "accountId": "u123456",
98 "list": [
99 {
100 "emailId": "e001",
101 "subject": "<mark>Project</mark> Update Q4 2025",
102 "preview": "...made significant progress on all major <mark>milestones</mark>..."
103 }
104 ],
105 "notFound": []
106 }
107 *)
108 let response_of_json _json =
109 raise (Jmap_core.Error.Parse_error "SearchSnippet.Get.response_of_json not yet implemented")
110end
111
112(** Parser submodule *)
113module Parser = struct
114 (** Parse SearchSnippet from JSON.
115 Test files: test/data/mail/search_snippet_response.json (list field)
116
117 Expected structure:
118 {
119 "emailId": "e001",
120 "subject": "<mark>Project</mark> Update Q4 2025",
121 "preview": "...made significant progress on all major <mark>milestones</mark> and are on track for delivery..."
122 }
123 *)
124 let of_json _json =
125 (* TODO: Implement JSON parsing *)
126 raise (Jmap_core.Error.Parse_error "SearchSnippet.Parser.of_json not yet implemented")
127
128 let to_json _t =
129 (* TODO: Implement JSON serialization *)
130 raise (Jmap_core.Error.Parse_error "SearchSnippet.Parser.to_json not yet implemented")
131end