@postalsys/email-content 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (210) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +288 -0
  3. package/dist/.tsbuildinfo +1 -0
  4. package/dist/analyze.d.ts +91 -0
  5. package/dist/analyze.d.ts.map +1 -0
  6. package/dist/analyze.js +274 -0
  7. package/dist/analyze.js.map +1 -0
  8. package/dist/annotate/client.d.ts +64 -0
  9. package/dist/annotate/client.d.ts.map +1 -0
  10. package/dist/annotate/client.js +139 -0
  11. package/dist/annotate/client.js.map +1 -0
  12. package/dist/annotate/llm.d.ts +46 -0
  13. package/dist/annotate/llm.d.ts.map +1 -0
  14. package/dist/annotate/llm.js +107 -0
  15. package/dist/annotate/llm.js.map +1 -0
  16. package/dist/annotate/prompt.d.ts +38 -0
  17. package/dist/annotate/prompt.d.ts.map +1 -0
  18. package/dist/annotate/prompt.js +165 -0
  19. package/dist/annotate/prompt.js.map +1 -0
  20. package/dist/annotate/store.d.ts +43 -0
  21. package/dist/annotate/store.d.ts.map +1 -0
  22. package/dist/annotate/store.js +46 -0
  23. package/dist/annotate/store.js.map +1 -0
  24. package/dist/canonical/html.d.ts +33 -0
  25. package/dist/canonical/html.d.ts.map +1 -0
  26. package/dist/canonical/html.js +156 -0
  27. package/dist/canonical/html.js.map +1 -0
  28. package/dist/canonical/text.d.ts +75 -0
  29. package/dist/canonical/text.d.ts.map +1 -0
  30. package/dist/canonical/text.js +217 -0
  31. package/dist/canonical/text.js.map +1 -0
  32. package/dist/classify/confidence.d.ts +38 -0
  33. package/dist/classify/confidence.d.ts.map +1 -0
  34. package/dist/classify/confidence.js +59 -0
  35. package/dist/classify/confidence.js.map +1 -0
  36. package/dist/classify/reconcile.d.ts +52 -0
  37. package/dist/classify/reconcile.d.ts.map +1 -0
  38. package/dist/classify/reconcile.js +100 -0
  39. package/dist/classify/reconcile.js.map +1 -0
  40. package/dist/classify/rules.d.ts +51 -0
  41. package/dist/classify/rules.d.ts.map +1 -0
  42. package/dist/classify/rules.js +648 -0
  43. package/dist/classify/rules.js.map +1 -0
  44. package/dist/cli/annotate.d.ts +23 -0
  45. package/dist/cli/annotate.d.ts.map +1 -0
  46. package/dist/cli/annotate.js +328 -0
  47. package/dist/cli/annotate.js.map +1 -0
  48. package/dist/cli/args.d.ts +17 -0
  49. package/dist/cli/args.d.ts.map +1 -0
  50. package/dist/cli/args.js +72 -0
  51. package/dist/cli/args.js.map +1 -0
  52. package/dist/cli/benchmark.d.ts +13 -0
  53. package/dist/cli/benchmark.d.ts.map +1 -0
  54. package/dist/cli/benchmark.js +172 -0
  55. package/dist/cli/benchmark.js.map +1 -0
  56. package/dist/cli/corpus.d.ts +9 -0
  57. package/dist/cli/corpus.d.ts.map +1 -0
  58. package/dist/cli/corpus.js +152 -0
  59. package/dist/cli/corpus.js.map +1 -0
  60. package/dist/cli/disagreements.d.ts +14 -0
  61. package/dist/cli/disagreements.d.ts.map +1 -0
  62. package/dist/cli/disagreements.js +133 -0
  63. package/dist/cli/disagreements.js.map +1 -0
  64. package/dist/cli/evaluate.d.ts +15 -0
  65. package/dist/cli/evaluate.d.ts.map +1 -0
  66. package/dist/cli/evaluate.js +215 -0
  67. package/dist/cli/evaluate.js.map +1 -0
  68. package/dist/cli/extract.d.ts +10 -0
  69. package/dist/cli/extract.d.ts.map +1 -0
  70. package/dist/cli/extract.js +139 -0
  71. package/dist/cli/extract.js.map +1 -0
  72. package/dist/cli/main.d.ts +9 -0
  73. package/dist/cli/main.d.ts.map +1 -0
  74. package/dist/cli/main.js +147 -0
  75. package/dist/cli/main.js.map +1 -0
  76. package/dist/corpus/analyze.d.ts +66 -0
  77. package/dist/corpus/analyze.d.ts.map +1 -0
  78. package/dist/corpus/analyze.js +214 -0
  79. package/dist/corpus/analyze.js.map +1 -0
  80. package/dist/corpus/migrations/index.d.ts +14 -0
  81. package/dist/corpus/migrations/index.d.ts.map +1 -0
  82. package/dist/corpus/migrations/index.js +158 -0
  83. package/dist/corpus/migrations/index.js.map +1 -0
  84. package/dist/corpus/sample.d.ts +66 -0
  85. package/dist/corpus/sample.d.ts.map +1 -0
  86. package/dist/corpus/sample.js +98 -0
  87. package/dist/corpus/sample.js.map +1 -0
  88. package/dist/corpus/scanner.d.ts +79 -0
  89. package/dist/corpus/scanner.d.ts.map +1 -0
  90. package/dist/corpus/scanner.js +256 -0
  91. package/dist/corpus/scanner.js.map +1 -0
  92. package/dist/corpus/stats.d.ts +76 -0
  93. package/dist/corpus/stats.d.ts.map +1 -0
  94. package/dist/corpus/stats.js +240 -0
  95. package/dist/corpus/stats.js.map +1 -0
  96. package/dist/corpus/store.d.ts +67 -0
  97. package/dist/corpus/store.d.ts.map +1 -0
  98. package/dist/corpus/store.js +196 -0
  99. package/dist/corpus/store.js.map +1 -0
  100. package/dist/corpus/thread-index.d.ts +31 -0
  101. package/dist/corpus/thread-index.d.ts.map +1 -0
  102. package/dist/corpus/thread-index.js +182 -0
  103. package/dist/corpus/thread-index.js.map +1 -0
  104. package/dist/corpus/worker.d.ts +21 -0
  105. package/dist/corpus/worker.d.ts.map +1 -0
  106. package/dist/corpus/worker.js +74 -0
  107. package/dist/corpus/worker.js.map +1 -0
  108. package/dist/detect/client.d.ts +28 -0
  109. package/dist/detect/client.d.ts.map +1 -0
  110. package/dist/detect/client.js +121 -0
  111. package/dist/detect/client.js.map +1 -0
  112. package/dist/detect/disclaimer.d.ts +12 -0
  113. package/dist/detect/disclaimer.d.ts.map +1 -0
  114. package/dist/detect/disclaimer.js +28 -0
  115. package/dist/detect/disclaimer.js.map +1 -0
  116. package/dist/detect/forward-header.d.ts +10 -0
  117. package/dist/detect/forward-header.d.ts.map +1 -0
  118. package/dist/detect/forward-header.js +35 -0
  119. package/dist/detect/forward-header.js.map +1 -0
  120. package/dist/detect/patterns/disclaimers.json +113 -0
  121. package/dist/detect/patterns/forward-headers.json +40 -0
  122. package/dist/detect/patterns/html-clients.json +157 -0
  123. package/dist/detect/patterns/quoted-headers.json +41 -0
  124. package/dist/detect/patterns/reply-headers.json +139 -0
  125. package/dist/detect/patterns/signatures.json +58 -0
  126. package/dist/detect/patterns.d.ts +43 -0
  127. package/dist/detect/patterns.d.ts.map +1 -0
  128. package/dist/detect/patterns.js +125 -0
  129. package/dist/detect/patterns.js.map +1 -0
  130. package/dist/detect/reply-header.d.ts +44 -0
  131. package/dist/detect/reply-header.d.ts.map +1 -0
  132. package/dist/detect/reply-header.js +134 -0
  133. package/dist/detect/reply-header.js.map +1 -0
  134. package/dist/detect/signature.d.ts +28 -0
  135. package/dist/detect/signature.d.ts.map +1 -0
  136. package/dist/detect/signature.js +77 -0
  137. package/dist/detect/signature.js.map +1 -0
  138. package/dist/detect/traffic.d.ts +26 -0
  139. package/dist/detect/traffic.d.ts.map +1 -0
  140. package/dist/detect/traffic.js +98 -0
  141. package/dist/detect/traffic.js.map +1 -0
  142. package/dist/eval/metrics.d.ts +87 -0
  143. package/dist/eval/metrics.d.ts.map +1 -0
  144. package/dist/eval/metrics.js +185 -0
  145. package/dist/eval/metrics.js.map +1 -0
  146. package/dist/index.d.ts +54 -0
  147. package/dist/index.d.ts.map +1 -0
  148. package/dist/index.js +163 -0
  149. package/dist/index.js.map +1 -0
  150. package/dist/match/history.d.ts +62 -0
  151. package/dist/match/history.d.ts.map +1 -0
  152. package/dist/match/history.js +128 -0
  153. package/dist/match/history.js.map +1 -0
  154. package/dist/match/normalize.d.ts +33 -0
  155. package/dist/match/normalize.d.ts.map +1 -0
  156. package/dist/match/normalize.js +63 -0
  157. package/dist/match/normalize.js.map +1 -0
  158. package/dist/match/shingle.d.ts +44 -0
  159. package/dist/match/shingle.d.ts.map +1 -0
  160. package/dist/match/shingle.js +78 -0
  161. package/dist/match/shingle.js.map +1 -0
  162. package/dist/mime/charset.d.ts +33 -0
  163. package/dist/mime/charset.d.ts.map +1 -0
  164. package/dist/mime/charset.js +118 -0
  165. package/dist/mime/charset.js.map +1 -0
  166. package/dist/mime/headers.d.ts +32 -0
  167. package/dist/mime/headers.d.ts.map +1 -0
  168. package/dist/mime/headers.js +127 -0
  169. package/dist/mime/headers.js.map +1 -0
  170. package/dist/mime/model.d.ts +111 -0
  171. package/dist/mime/model.d.ts.map +1 -0
  172. package/dist/mime/model.js +17 -0
  173. package/dist/mime/model.js.map +1 -0
  174. package/dist/mime/parse.d.ts +27 -0
  175. package/dist/mime/parse.d.ts.map +1 -0
  176. package/dist/mime/parse.js +343 -0
  177. package/dist/mime/parse.js.map +1 -0
  178. package/dist/segment/features.d.ts +29 -0
  179. package/dist/segment/features.d.ts.map +1 -0
  180. package/dist/segment/features.js +102 -0
  181. package/dist/segment/features.js.map +1 -0
  182. package/dist/segment/html-blocks.d.ts +28 -0
  183. package/dist/segment/html-blocks.d.ts.map +1 -0
  184. package/dist/segment/html-blocks.js +596 -0
  185. package/dist/segment/html-blocks.js.map +1 -0
  186. package/dist/segment/text-blocks.d.ts +30 -0
  187. package/dist/segment/text-blocks.d.ts.map +1 -0
  188. package/dist/segment/text-blocks.js +204 -0
  189. package/dist/segment/text-blocks.js.map +1 -0
  190. package/dist/segment/types.d.ts +88 -0
  191. package/dist/segment/types.d.ts.map +1 -0
  192. package/dist/segment/types.js +11 -0
  193. package/dist/segment/types.js.map +1 -0
  194. package/dist/types.d.ts +85 -0
  195. package/dist/types.d.ts.map +1 -0
  196. package/dist/types.js +17 -0
  197. package/dist/types.js.map +1 -0
  198. package/dist/util/hash.d.ts +49 -0
  199. package/dist/util/hash.d.ts.map +1 -0
  200. package/dist/util/hash.js +0 -0
  201. package/dist/util/hash.js.map +1 -0
  202. package/dist/util/lang.d.ts +25 -0
  203. package/dist/util/lang.d.ts.map +1 -0
  204. package/dist/util/lang.js +135 -0
  205. package/dist/util/lang.js.map +1 -0
  206. package/dist/util/worker-pool.d.ts +51 -0
  207. package/dist/util/worker-pool.d.ts.map +1 -0
  208. package/dist/util/worker-pool.js +155 -0
  209. package/dist/util/worker-pool.js.map +1 -0
  210. package/package.json +74 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Postal Systems OÜ
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,288 @@
1
+ # email-content
2
+
3
+ Extract the conversationally relevant content from arbitrary email messages.
4
+
5
+ Given a raw RFC 5322 message, the library separates what the sender actually wrote from the reply
6
+ history their mail client embedded automatically, and returns both, classified, with a confidence
7
+ and a machine readable reason for every decision.
8
+
9
+ It is built for a chat style application that uses ordinary email as its transport, where the other
10
+ participants use whatever client they like and do not know their mail is being read as chat.
11
+
12
+ ## The rule everything follows from
13
+
14
+ Hiding a sentence the sender wrote is a silent data loss the reader may never notice. Showing a
15
+ paragraph of redundant quoted history is a cosmetic annoyance. The first is treated as at least ten
16
+ times worse than the second, and every design decision follows from that.
17
+
18
+ In practice that means:
19
+
20
+ - Content is only ever hidden when something structural says it is history: an attribution line, a
21
+ client quote container, or a match against a message that demonstrably existed earlier. Quote
22
+ characters alone are never enough.
23
+ - Nothing is deleted. Hidden segments are returned in full next to the visible ones, and the
24
+ original message is always available. "Hidden" is a rendering hint.
25
+ - Ambiguous content is labelled `UNKNOWN` and stays visible.
26
+ - No generative model touches the sender's words. The pipeline selects and classifies existing
27
+ spans; it never rewrites, summarises or paraphrases.
28
+
29
+ ## Install and build
30
+
31
+ Requires Node 24 or later, for the built in `node:sqlite` and native TypeScript execution.
32
+
33
+ ```bash
34
+ npm install
35
+ npm run build
36
+ npm test
37
+ ```
38
+
39
+ ## Library
40
+
41
+ The primary entry point takes content you have already parsed. Most callers hold
42
+ `{ text, html, subject }` from mailparser, postal-mime, EmailEngine or an IMAP client, and never
43
+ have a raw message to hand.
44
+
45
+ ```js
46
+ const { analyze } = require('email-content');
47
+
48
+ const result = await analyze({
49
+ text: plainTextBody, // optional
50
+ html: htmlBody, // optional
51
+ subject: 'Re: Deploy window', // optional
52
+ from: 'Bob <bob@example.net>', // optional, improves signature detection
53
+ inReplyTo: '<parent@example.com>' // optional
54
+ });
55
+
56
+ for (const segment of result.segments) {
57
+ console.log(segment.type, segment.confidence, segment.text);
58
+ }
59
+ ```
60
+
61
+ Either body may be omitted. When both are present the HTML drives the classification, because that
62
+ is where quote structure survives, and the plain text is used as a cross check.
63
+
64
+ If you do have a raw RFC 5322 message, `extract()` parses it and runs the same pipeline:
65
+
66
+ ```js
67
+ const { extract } = require('email-content');
68
+ const result = await extract(fs.readFileSync('message.eml'));
69
+ ```
70
+
71
+ ### Result
72
+
73
+ ```jsonc
74
+ {
75
+ "segments": [ // render these
76
+ {
77
+ "type": "NEW_CONTENT",
78
+ "text": "No, wait until Monday.",
79
+ "html": "<div>No, wait until Monday.</div>",
80
+ "confidence": 0.95,
81
+ "visibility": "show", // show | collapse | hide
82
+ "reasons": ["new_content_default", "html_primary_representation"],
83
+ "source": {
84
+ "mimePart": "1.2", // IMAP style part path
85
+ "representation": "html",
86
+ "blockIndex": 0,
87
+ "start": 0, // character offsets into the canonical part text
88
+ "end": 79,
89
+ "domPath": "/0/1"
90
+ }
91
+ }
92
+ ],
93
+ "hiddenSegments": [ /* same shape, retained in full */ ],
94
+ "overallConfidence": 0.97,
95
+ "warnings": [],
96
+ "originalAvailable": true,
97
+ "primaryRepresentation": "html",
98
+ "extractorVersion": "0.1.0",
99
+ "historyUsed": false,
100
+ "isReply": true
101
+ }
102
+ ```
103
+
104
+ Segment types: `NEW_CONTENT`, `INLINE_QUOTE`, `REPLY_HISTORY`, `FORWARDED_CONTENT`, `SIGNATURE`,
105
+ `DISCLAIMER`, `UNKNOWN`.
106
+
107
+ Render `segments`. `hiddenSegments` holds what the extractor is confident is embedded reply
108
+ history, in full, so a client can offer to reveal it. Nothing is ever discarded.
109
+
110
+ ### Thread history
111
+
112
+ If earlier messages in the thread are available, pass them. A block whose text provably existed
113
+ before this message was written is history by definition, which is far stronger evidence than any
114
+ markup heuristic. Measured on the reference set, supplying history cuts the share of reply history
115
+ left visible from 70.9 percent to 60.1 percent, with no loss of new content.
116
+
117
+ ```js
118
+ const result = await analyze(
119
+ { text, html },
120
+ { history: [{ text: parentText, html: parentHtml }] } // nearest ancestor first
121
+ );
122
+ ```
123
+
124
+ History is always optional. Extraction works without it and never depends on it.
125
+
126
+ `analyze()` and `extract()` never throw. Malformed input produces a result whose body is a single
127
+ visible `UNKNOWN` segment plus a warning.
128
+
129
+ ## Command line
130
+
131
+ ```bash
132
+ # Classify one message
133
+ email-content extract message.eml
134
+ email-content extract message.eml --json
135
+ email-content extract message.eml --explain # per block evidence, features and reasons
136
+
137
+ # Label blocks with an LLM instead of a human (opt in, sends content to OpenAI)
138
+ email-content annotate --sample 60 --model gpt-5.4-mini
139
+ email-content disagreements --direction expensive
140
+
141
+ # Scan a corpus of .eml files into a local SQLite database
142
+ email-content corpus scan /path/to/eml-folder
143
+ email-content corpus scan /path/to/eml-folder --sample 2000 --seed phase1
144
+ email-content corpus scan /path/to/eml-folder --concurrency 14
145
+
146
+ # Report on it
147
+ email-content corpus stats --out docs/corpus-report.md
148
+ email-content corpus stats --json
149
+ email-content corpus threads # in-corpus thread parent resolution
150
+
151
+ # Throughput and catastrophic error rates
152
+ email-content benchmark --sample 3000
153
+ ```
154
+
155
+ ## What it gets right
156
+
157
+ The two cases that define the problem:
158
+
159
+ ```text
160
+ > Should we deploy this today?
161
+
162
+ No, wait until Monday.
163
+
164
+ > Should I notify the customer?
165
+
166
+ Yes, please.
167
+ ```
168
+
169
+ Both questions are `INLINE_QUOTE` and stay visible: they are the context the answers depend on.
170
+
171
+ ```text
172
+ Yes, Monday works.
173
+
174
+ On Friday, Alice wrote:
175
+ > Can we meet on Monday?
176
+ ```
177
+
178
+ The trailing quote is `REPLY_HISTORY` and is hidden, because an attribution line anchors it and no
179
+ authored content follows.
180
+
181
+ Beyond that, the deterministic baseline handles Gmail, Outlook desktop, Outlook Web, Apple Mail,
182
+ Thunderbird, Proton, Yahoo and Zimbra quote structures; forwarded messages with a comment above
183
+ them; bottom posted replies, which are collapsed rather than hidden because the reader is more
184
+ likely to need the context; `format=flowed`; legacy charsets; and messages whose plain text part
185
+ has lost its quote markers entirely, which is now the majority case for recent mail.
186
+
187
+ It also, deliberately, does not fire on ordinary prose that merely looks like email structure. Text
188
+ containing `From:` and `Subject:` lines is only treated as an embedded header block when the values
189
+ look like header values, so a support message explaining which headers to include stays visible.
190
+
191
+ ## Accuracy
192
+
193
+ Measured against a 452 message stratified reference set annotated by gpt-5.6-sol under the
194
+ conventions in [docs/annotation-guide.md](docs/annotation-guide.md), with thread history enabled.
195
+
196
+ The reference is not ground truth, but it is close. Two strong models (gpt-5.5 and gpt-5.6-sol)
197
+ given identical input agree with each other on **98.6 percent** of blocks, and **99.2 percent** once
198
+ a single spam message of machine generated word salad is excluded. That is the practical ceiling.
199
+
200
+ | property | measured |
201
+ | --- | ---: |
202
+ | block label agreement | 79.8% |
203
+ | new content characters retained | **100.0%** |
204
+ | new content blocks retained | **100.0%** |
205
+ | hidden content genuinely history | 99.4% |
206
+ | reply history correctly hidden | 60.3% |
207
+ | messages losing all new content | 0 |
208
+ | messages losing an inline answer | 0 |
209
+
210
+ Not one character the reference considers newly written is hidden, across 452 messages and 206,368
211
+ characters of new content.
212
+
213
+ Per label F1: REPLY_HISTORY 90.4, FORWARDED_CONTENT 81.5, NEW_CONTENT 70.1, SIGNATURE 48.8,
214
+ INLINE_QUOTE 35.9, DISCLAIMER 30.1.
215
+
216
+ With thread history available the numbers are materially better than the aggregate suggests, and a
217
+ chat application always has the thread it is rendering:
218
+
219
+ | | messages | agreement | history hidden |
220
+ | --- | ---: | ---: | ---: |
221
+ | history available | 305 | 85.9% | 64.7% |
222
+ | history unavailable | 147 | 64.9% | 37.0% |
223
+
224
+ ## Limitations
225
+
226
+ - **It still errs towards showing too much.** Around 40 percent of reply history remains displayed.
227
+ That is the cheap direction of error and it is deliberate, but it is the largest remaining gap.
228
+ - **Disclaimer recall is 18.1 percent** at 87.8 percent precision. The generic notification footer
229
+ shapes are covered; what remains is per-sender templates, which hand written rules cannot reach
230
+ without overfitting to one vendor. This is the clearest case for a learned model.
231
+ - **Signature recall is 36.7 percent** at 73.1 percent precision. Two independent signals are
232
+ required, such as a closing greeting plus contact details, or the sender's own name plus either.
233
+ - **INLINE_QUOTE precision is 27.2 percent.** Blocks wrongly called inline quote stay visible, so
234
+ this costs tidiness, not content.
235
+ - **Outlook remains the weakest client**, around 62 percent against 92 percent for Gmail and Apple
236
+ Mail.
237
+ - **No learned model.** This is the deterministic baseline. The labelled data, a settled labelling
238
+ convention and the evaluation harness all exist to train one.
239
+
240
+ ## Privacy
241
+
242
+ The corpus this was built against is private email, and the project is built accordingly:
243
+
244
+ - Nothing contacts the network by default. The runtime dependency tree is three packages and none
245
+ opens a socket. The one exception is `email-content annotate`, an opt in command that sends block
246
+ text to an LLM API; see [docs/annotation.md](docs/annotation.md).
247
+ - Source `.eml` files are opened read only and never modified.
248
+ - No message body, subject or address is written to logs, to the terminal, or to the corpus
249
+ database. Subjects and addresses are stored as salted hashes; sender domains are kept because
250
+ stratified sampling needs them.
251
+ - The corpus database is derived from private mail and is not anonymised. It is gitignored. See
252
+ [docs/threat-model.md](docs/threat-model.md) for exactly what it can still reveal.
253
+
254
+ ## Documentation
255
+
256
+ | document | contents |
257
+ | --- | --- |
258
+ | [docs/architecture.md](docs/architecture.md) | Pipeline stages, dependency choices and why, safety invariants |
259
+ | [docs/implementation-plan.md](docs/implementation-plan.md) | Phases, decisions taken, open questions |
260
+ | [docs/threat-model.md](docs/threat-model.md) | What is stored, what it reveals, hostile content handling |
261
+ | [docs/corpus-report.md](docs/corpus-report.md) | Statistics over the working corpus (generated, gitignored) |
262
+ | [docs/benchmark.md](docs/benchmark.md) | Throughput, memory, and where the time goes |
263
+ | [docs/annotation.md](docs/annotation.md) | Using an LLM as annotator: method, results, limitations |
264
+
265
+ ## Project layout
266
+
267
+ ```
268
+ src/mime/ MIME parsing, charset decoding, normalised message model
269
+ src/canonical/ Plain text and HTML canonicalisation
270
+ src/segment/ Block segmentation and feature extraction
271
+ src/detect/ Detectors, with pattern sets as JSON data
272
+ src/classify/ Rules, reconciliation, confidence
273
+ src/corpus/ Scanner, worker pool, SQLite store, statistics
274
+ src/cli/ Command line entry points
275
+ test/ Tests and hand written fixtures
276
+ ```
277
+
278
+ Pattern sets in `src/detect/patterns/` can be overridden at runtime by pointing
279
+ `EMAIL_CONTENT_PATTERNS` at a directory containing replacements.
280
+
281
+ ## Status
282
+
283
+ Working and measured: the MIME parser, canonicalisation, block segmentation, the deterministic rule
284
+ baseline, thread history matching, the corpus scanner over 320k messages, LLM assisted annotation,
285
+ the evaluation harness, the CLI, and 123 tests including fuzzing and performance bounds.
286
+
287
+ Not built: the local annotation app for adjudicating disagreements, and a learned sequence model.
288
+ Both are described in [docs/implementation-plan.md](docs/implementation-plan.md).
@@ -0,0 +1 @@
1
+ {"fileNames":["../node_modules/typescript/lib/lib.es5.d.ts","../node_modules/typescript/lib/lib.es2015.d.ts","../node_modules/typescript/lib/lib.es2016.d.ts","../node_modules/typescript/lib/lib.es2017.d.ts","../node_modules/typescript/lib/lib.es2018.d.ts","../node_modules/typescript/lib/lib.es2019.d.ts","../node_modules/typescript/lib/lib.es2020.d.ts","../node_modules/typescript/lib/lib.es2021.d.ts","../node_modules/typescript/lib/lib.es2022.d.ts","../node_modules/typescript/lib/lib.es2023.d.ts","../node_modules/typescript/lib/lib.es2015.core.d.ts","../node_modules/typescript/lib/lib.es2015.collection.d.ts","../node_modules/typescript/lib/lib.es2015.generator.d.ts","../node_modules/typescript/lib/lib.es2015.iterable.d.ts","../node_modules/typescript/lib/lib.es2015.promise.d.ts","../node_modules/typescript/lib/lib.es2015.proxy.d.ts","../node_modules/typescript/lib/lib.es2015.reflect.d.ts","../node_modules/typescript/lib/lib.es2015.symbol.d.ts","../node_modules/typescript/lib/lib.es2015.symbol.wellknown.d.ts","../node_modules/typescript/lib/lib.es2016.array.include.d.ts","../node_modules/typescript/lib/lib.es2016.intl.d.ts","../node_modules/typescript/lib/lib.es2017.arraybuffer.d.ts","../node_modules/typescript/lib/lib.es2017.date.d.ts","../node_modules/typescript/lib/lib.es2017.object.d.ts","../node_modules/typescript/lib/lib.es2017.sharedmemory.d.ts","../node_modules/typescript/lib/lib.es2017.string.d.ts","../node_modules/typescript/lib/lib.es2017.intl.d.ts","../node_modules/typescript/lib/lib.es2017.typedarrays.d.ts","../node_modules/typescript/lib/lib.es2018.asyncgenerator.d.ts","../node_modules/typescript/lib/lib.es2018.asynciterable.d.ts","../node_modules/typescript/lib/lib.es2018.intl.d.ts","../node_modules/typescript/lib/lib.es2018.promise.d.ts","../node_modules/typescript/lib/lib.es2018.regexp.d.ts","../node_modules/typescript/lib/lib.es2019.array.d.ts","../node_modules/typescript/lib/lib.es2019.object.d.ts","../node_modules/typescript/lib/lib.es2019.string.d.ts","../node_modules/typescript/lib/lib.es2019.symbol.d.ts","../node_modules/typescript/lib/lib.es2019.intl.d.ts","../node_modules/typescript/lib/lib.es2020.bigint.d.ts","../node_modules/typescript/lib/lib.es2020.date.d.ts","../node_modules/typescript/lib/lib.es2020.promise.d.ts","../node_modules/typescript/lib/lib.es2020.sharedmemory.d.ts","../node_modules/typescript/lib/lib.es2020.string.d.ts","../node_modules/typescript/lib/lib.es2020.symbol.wellknown.d.ts","../node_modules/typescript/lib/lib.es2020.intl.d.ts","../node_modules/typescript/lib/lib.es2020.number.d.ts","../node_modules/typescript/lib/lib.es2021.promise.d.ts","../node_modules/typescript/lib/lib.es2021.string.d.ts","../node_modules/typescript/lib/lib.es2021.weakref.d.ts","../node_modules/typescript/lib/lib.es2021.intl.d.ts","../node_modules/typescript/lib/lib.es2022.array.d.ts","../node_modules/typescript/lib/lib.es2022.error.d.ts","../node_modules/typescript/lib/lib.es2022.intl.d.ts","../node_modules/typescript/lib/lib.es2022.object.d.ts","../node_modules/typescript/lib/lib.es2022.string.d.ts","../node_modules/typescript/lib/lib.es2022.regexp.d.ts","../node_modules/typescript/lib/lib.es2023.array.d.ts","../node_modules/typescript/lib/lib.es2023.collection.d.ts","../node_modules/typescript/lib/lib.es2023.intl.d.ts","../node_modules/typescript/lib/lib.esnext.disposable.d.ts","../node_modules/typescript/lib/lib.esnext.float16.d.ts","../node_modules/typescript/lib/lib.decorators.d.ts","../node_modules/typescript/lib/lib.decorators.legacy.d.ts","../node_modules/node-html-parser/dist/index.d.ts","../src/detect/patterns.ts","../src/types.ts","../src/segment/types.ts","../src/detect/reply-header.ts","../src/detect/forward-header.ts","../src/detect/signature.ts","../src/detect/disclaimer.ts","../src/canonical/html.ts","../src/segment/features.ts","../src/segment/html-blocks.ts","../src/canonical/text.ts","../src/segment/text-blocks.ts","../src/classify/confidence.ts","../src/classify/rules.ts","../src/classify/reconcile.ts","../node_modules/@types/node/compatibility/iterators.d.ts","../node_modules/@types/node/globals.typedarray.d.ts","../node_modules/@types/node/buffer.buffer.d.ts","../node_modules/@types/node/globals.d.ts","../node_modules/@types/node/web-globals/abortcontroller.d.ts","../node_modules/@types/node/web-globals/crypto.d.ts","../node_modules/@types/node/web-globals/domexception.d.ts","../node_modules/@types/node/web-globals/events.d.ts","../node_modules/undici-types/utility.d.ts","../node_modules/undici-types/header.d.ts","../node_modules/undici-types/readable.d.ts","../node_modules/undici-types/fetch.d.ts","../node_modules/undici-types/formdata.d.ts","../node_modules/undici-types/connector.d.ts","../node_modules/undici-types/client-stats.d.ts","../node_modules/undici-types/client.d.ts","../node_modules/undici-types/errors.d.ts","../node_modules/undici-types/dispatcher.d.ts","../node_modules/undici-types/global-dispatcher.d.ts","../node_modules/undici-types/global-origin.d.ts","../node_modules/undici-types/pool-stats.d.ts","../node_modules/undici-types/pool.d.ts","../node_modules/undici-types/handlers.d.ts","../node_modules/undici-types/balanced-pool.d.ts","../node_modules/undici-types/round-robin-pool.d.ts","../node_modules/undici-types/h2c-client.d.ts","../node_modules/undici-types/agent.d.ts","../node_modules/undici-types/mock-interceptor.d.ts","../node_modules/undici-types/mock-call-history.d.ts","../node_modules/undici-types/mock-agent.d.ts","../node_modules/undici-types/mock-client.d.ts","../node_modules/undici-types/mock-pool.d.ts","../node_modules/undici-types/snapshot-agent.d.ts","../node_modules/undici-types/mock-errors.d.ts","../node_modules/undici-types/proxy-agent.d.ts","../node_modules/undici-types/env-http-proxy-agent.d.ts","../node_modules/undici-types/retry-handler.d.ts","../node_modules/undici-types/retry-agent.d.ts","../node_modules/undici-types/api.d.ts","../node_modules/undici-types/cache-interceptor.d.ts","../node_modules/undici-types/interceptors.d.ts","../node_modules/undici-types/util.d.ts","../node_modules/undici-types/cookies.d.ts","../node_modules/undici-types/patch.d.ts","../node_modules/undici-types/websocket.d.ts","../node_modules/undici-types/eventsource.d.ts","../node_modules/undici-types/diagnostics-channel.d.ts","../node_modules/undici-types/content-type.d.ts","../node_modules/undici-types/cache.d.ts","../node_modules/undici-types/index.d.ts","../node_modules/@types/node/web-globals/fetch.d.ts","../node_modules/@types/node/web-globals/navigator.d.ts","../node_modules/@types/node/web-globals/storage.d.ts","../node_modules/@types/node/web-globals/streams.d.ts","../node_modules/@types/node/assert.d.ts","../node_modules/@types/node/assert/strict.d.ts","../node_modules/@types/node/async_hooks.d.ts","../node_modules/@types/node/buffer.d.ts","../node_modules/@types/node/child_process.d.ts","../node_modules/@types/node/cluster.d.ts","../node_modules/@types/node/console.d.ts","../node_modules/@types/node/constants.d.ts","../node_modules/@types/node/crypto.d.ts","../node_modules/@types/node/dgram.d.ts","../node_modules/@types/node/diagnostics_channel.d.ts","../node_modules/@types/node/dns.d.ts","../node_modules/@types/node/dns/promises.d.ts","../node_modules/@types/node/domain.d.ts","../node_modules/@types/node/events.d.ts","../node_modules/@types/node/fs.d.ts","../node_modules/@types/node/fs/promises.d.ts","../node_modules/@types/node/http.d.ts","../node_modules/@types/node/http2.d.ts","../node_modules/@types/node/https.d.ts","../node_modules/@types/node/inspector.d.ts","../node_modules/@types/node/inspector.generated.d.ts","../node_modules/@types/node/module.d.ts","../node_modules/@types/node/net.d.ts","../node_modules/@types/node/os.d.ts","../node_modules/@types/node/path.d.ts","../node_modules/@types/node/perf_hooks.d.ts","../node_modules/@types/node/process.d.ts","../node_modules/@types/node/punycode.d.ts","../node_modules/@types/node/querystring.d.ts","../node_modules/@types/node/readline.d.ts","../node_modules/@types/node/readline/promises.d.ts","../node_modules/@types/node/repl.d.ts","../node_modules/@types/node/sea.d.ts","../node_modules/@types/node/sqlite.d.ts","../node_modules/@types/node/stream.d.ts","../node_modules/@types/node/stream/promises.d.ts","../node_modules/@types/node/stream/consumers.d.ts","../node_modules/@types/node/stream/web.d.ts","../node_modules/@types/node/string_decoder.d.ts","../node_modules/@types/node/test.d.ts","../node_modules/@types/node/timers.d.ts","../node_modules/@types/node/timers/promises.d.ts","../node_modules/@types/node/tls.d.ts","../node_modules/@types/node/trace_events.d.ts","../node_modules/@types/node/tty.d.ts","../node_modules/@types/node/url.d.ts","../node_modules/@types/node/util.d.ts","../node_modules/@types/node/v8.d.ts","../node_modules/@types/node/vm.d.ts","../node_modules/@types/node/wasi.d.ts","../node_modules/@types/node/worker_threads.d.ts","../node_modules/@types/node/zlib.d.ts","../node_modules/@types/node/index.d.ts","../node_modules/@zone-eu/mailsplit/lib/headers.d.ts","../node_modules/@zone-eu/mailsplit/lib/types.d.ts","../node_modules/@zone-eu/mailsplit/lib/message-splitter.d.ts","../node_modules/@zone-eu/mailsplit/lib/message-joiner.d.ts","../node_modules/@zone-eu/mailsplit/lib/node-rewriter.d.ts","../node_modules/@zone-eu/mailsplit/lib/node-streamer.d.ts","../node_modules/@zone-eu/mailsplit/lib/chunked-passthrough.d.ts","../node_modules/@zone-eu/mailsplit/lib/mime-node.d.ts","../node_modules/@zone-eu/mailsplit/index.d.ts","../src/mime/charset.ts","../src/mime/model.ts","../src/mime/headers.ts","../src/mime/parse.ts","../src/util/hash.ts","../src/match/normalize.ts","../src/match/shingle.ts","../src/match/history.ts","../src/analyze.ts","../src/corpus/migrations/index.ts","../src/detect/client.ts","../src/detect/traffic.ts","../src/util/lang.ts","../src/corpus/analyze.ts","../src/corpus/store.ts","../src/corpus/thread-index.ts","../src/index.ts","../src/vendor.d.ts","../src/annotate/client.ts","../src/annotate/prompt.ts","../src/annotate/llm.ts","../src/annotate/store.ts","../src/cli/args.ts","../src/corpus/sample.ts","../src/cli/annotate.ts","../src/cli/benchmark.ts","../src/util/worker-pool.ts","../src/corpus/worker.ts","../src/corpus/scanner.ts","../src/corpus/stats.ts","../src/cli/corpus.ts","../src/cli/disagreements.ts","../src/eval/metrics.ts","../src/cli/evaluate.ts","../src/cli/extract.ts","../src/cli/main.ts","../node_modules/@types/esrecurse/index.d.ts","../node_modules/@types/estree/index.d.ts","../node_modules/@types/json-schema/index.d.ts"],"fileIdsList":[[82,137,154,155],[82,134,135,137,154,155],[82,136,137,154,155],[137,154,155],[82,137,142,154,155,172],[82,137,138,143,148,154,155,157,169,180],[82,137,138,139,148,154,155,157],[82,137,140,154,155,181],[82,137,141,142,149,154,155,158],[82,137,142,154,155,169,177],[82,137,143,145,148,154,155,157],[82,136,137,144,154,155],[82,137,145,146,154,155],[82,137,147,148,154,155],[82,136,137,148,154,155],[82,137,148,149,150,154,155,169,180],[82,137,148,149,150,154,155,164,169,172],[82,129,137,145,148,151,154,155,157,169,180],[82,137,148,149,151,152,154,155,157,169,177,180],[82,137,151,153,154,155,169,177,180],[80,81,82,83,84,85,86,87,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186],[82,137,148,154,155],[82,137,154,155,156,180],[82,137,145,148,154,155,157,169],[82,137,154,155,158],[82,137,154,155,159],[82,136,137,154,155,160],[82,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186],[82,137,154,155,162],[82,137,154,155,163],[82,137,148,154,155,164,165],[82,137,154,155,164,166,181,183],[82,137,149,154,155],[82,137,148,154,155,169,170,172],[82,137,154,155,171,172],[82,137,154,155,169,170],[82,137,154,155,172],[82,137,154,155,173],[82,134,137,154,155,169,174,180],[82,137,148,154,155,175,176],[82,137,154,155,175,176],[82,137,142,154,155,157,169,177],[82,137,154,155,178],[82,137,154,155,157,179],[82,137,151,154,155,163,180],[82,137,142,154,155,181],[82,137,154,155,169,182],[82,137,154,155,156,183],[82,137,154,155,184],[82,137,142,154,155],[82,129,137,154,155],[82,137,154,155,185],[82,129,137,148,150,154,155,160,169,172,180,182,183,185],[82,137,154,155,169,186],[82,137,154,155,187,188,189,190,191,192,193,194,195],[82,137,154,155,169,189],[82,137,154,155,189],[82,137,154,155,169],[82,137,154,155,188,189],[82,137,154,155,169,188],[82,94,97,100,101,137,154,155,180],[82,97,137,154,155,169,180],[82,97,101,137,154,155,180],[82,91,137,154,155],[82,95,137,154,155],[82,93,94,97,137,154,155,180],[82,137,154,155,157,177],[82,137,154,155,187],[82,91,137,154,155,187],[82,93,97,137,154,155,157,180],[82,88,89,90,92,96,137,148,154,155,169,180],[82,97,106,114,137,154,155],[82,89,95,137,154,155],[82,97,123,124,137,154,155],[82,89,92,97,137,154,155,172,180,187],[82,97,137,154,155],[82,93,97,137,154,155,180],[82,88,137,154,155],[82,91,92,93,95,96,97,98,99,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,124,125,126,127,128,137,154,155],[82,97,116,119,137,145,154,155],[82,97,106,107,108,137,154,155],[82,95,97,107,109,137,154,155],[82,96,137,154,155],[82,89,91,97,137,154,155],[82,97,101,107,109,137,154,155],[82,101,137,154,155],[82,95,97,100,137,154,155,180],[82,89,93,97,106,137,154,155],[82,97,116,137,154,155],[82,109,137,154,155],[82,91,97,123,137,154,155,172,185,187],[66,67,74,76,77,78,79,82,137,154,155,204],[66,67,82,137,154,155,215,216],[66,82,137,154,155,211],[66,82,137,154,155],[66,78,82,137,154,155],[66,67,77,82,137,154,155],[66,67,74,76,78,82,137,149,154,155,159,200,201,211,215,216,217,218,219,220],[66,82,137,149,154,155,159,211,213,219],[82,137,149,154,155,159,211,219,225,226],[67,74,76,78,82,137,149,154,155,159,200,211,219],[66,82,137,149,154,155,159,200,211,212,213,219,229],[66,82,137,149,154,155,200,204,211,212,213,219],[66,82,137,154,155,219,221,222,227,228,230,231],[65,72,75,82,137,154,155,198,201,207,208,209],[82,137,154,155,201,211],[82,137,149,154,155,158,159,201,211,223,224],[82,137,154,155,211],[66,82,137,149,154,155,159,168,201,206,210],[82,137,149,154,155,159,198,200,204,211],[82,137,149,154,155,159,185,200,201,210,211],[82,137,154,155,198],[65,67,82,137,154,155],[82,137,149,154,155,159],[66,67,77,82,137,154,155,198,200,204,205,212],[67,72,75,82,137,154,155,200,202,203],[82,137,154,155,201,202],[82,137,154,155,214],[82,137,154,155,198,214],[66,82,137,154,155,195,196,197,198,199,214],[64,65,67,68,69,70,71,72,73,82,137,154,155],[67,68,69,70,71,73,75,82,137,154,155],[82,137,148,154,155,185]],"fileInfos":[{"version":"c430d44666289dae81f30fa7b2edebf186ecc91a2d4c71266ea6ae76388792e1","affectsGlobalScope":true,"impliedFormat":1},{"version":"45b7ab580deca34ae9729e97c13cfd999df04416a79116c3bfb483804f85ded4","impliedFormat":1},{"version":"3facaf05f0c5fc569c5649dd359892c98a85557e3e0c847964caeb67076f4d75","impliedFormat":1},{"version":"e44bb8bbac7f10ecc786703fe0a6a4b952189f908707980ba8f3c8975a760962","impliedFormat":1},{"version":"5e1c4c362065a6b95ff952c0eab010f04dcd2c3494e813b493ecfd4fcb9fc0d8","impliedFormat":1},{"version":"68d73b4a11549f9c0b7d352d10e91e5dca8faa3322bfb77b661839c42b1ddec7","impliedFormat":1},{"version":"5efce4fc3c29ea84e8928f97adec086e3dc876365e0982cc8479a07954a3efd4","impliedFormat":1},{"version":"feecb1be483ed332fad555aff858affd90a48ab19ba7272ee084704eb7167569","impliedFormat":1},{"version":"ee7bad0c15b58988daa84371e0b89d313b762ab83cb5b31b8a2d1162e8eb41c2","impliedFormat":1},{"version":"27bdc30a0e32783366a5abeda841bc22757c1797de8681bbe81fbc735eeb1c10","impliedFormat":1},{"version":"c57796738e7f83dbc4b8e65132f11a377649c00dd3eee333f672b8f0a6bea671","affectsGlobalScope":true,"impliedFormat":1},{"version":"dc2df20b1bcdc8c2d34af4926e2c3ab15ffe1160a63e58b7e09833f616efff44","affectsGlobalScope":true,"impliedFormat":1},{"version":"515d0b7b9bea2e31ea4ec968e9edd2c39d3eebf4a2d5cbd04e88639819ae3b71","affectsGlobalScope":true,"impliedFormat":1},{"version":"0559b1f683ac7505ae451f9a96ce4c3c92bdc71411651ca6ddb0e88baaaad6a3","affectsGlobalScope":true,"impliedFormat":1},{"version":"0dc1e7ceda9b8b9b455c3a2d67b0412feab00bd2f66656cd8850e8831b08b537","affectsGlobalScope":true,"impliedFormat":1},{"version":"ce691fb9e5c64efb9547083e4a34091bcbe5bdb41027e310ebba8f7d96a98671","affectsGlobalScope":true,"impliedFormat":1},{"version":"8d697a2a929a5fcb38b7a65594020fcef05ec1630804a33748829c5ff53640d0","affectsGlobalScope":true,"impliedFormat":1},{"version":"4ff2a353abf8a80ee399af572debb8faab2d33ad38c4b4474cff7f26e7653b8d","affectsGlobalScope":true,"impliedFormat":1},{"version":"fb0f136d372979348d59b3f5020b4cdb81b5504192b1cacff5d1fbba29378aa1","affectsGlobalScope":true,"impliedFormat":1},{"version":"d15bea3d62cbbdb9797079416b8ac375ae99162a7fba5de2c6c505446486ac0a","affectsGlobalScope":true,"impliedFormat":1},{"version":"68d18b664c9d32a7336a70235958b8997ebc1c3b8505f4f1ae2b7e7753b87618","affectsGlobalScope":true,"impliedFormat":1},{"version":"eb3d66c8327153d8fa7dd03f9c58d351107fe824c79e9b56b462935176cdf12a","affectsGlobalScope":true,"impliedFormat":1},{"version":"38f0219c9e23c915ef9790ab1d680440d95419ad264816fa15009a8851e79119","affectsGlobalScope":true,"impliedFormat":1},{"version":"69ab18c3b76cd9b1be3d188eaf8bba06112ebbe2f47f6c322b5105a6fbc45a2e","affectsGlobalScope":true,"impliedFormat":1},{"version":"a680117f487a4d2f30ea46f1b4b7f58bef1480456e18ba53ee85c2746eeca012","affectsGlobalScope":true,"impliedFormat":1},{"version":"2f11ff796926e0832f9ae148008138ad583bd181899ab7dd768a2666700b1893","affectsGlobalScope":true,"impliedFormat":1},{"version":"4de680d5bb41c17f7f68e0419412ca23c98d5749dcaaea1896172f06435891fc","affectsGlobalScope":true,"impliedFormat":1},{"version":"954296b30da6d508a104a3a0b5d96b76495c709785c1d11610908e63481ee667","affectsGlobalScope":true,"impliedFormat":1},{"version":"ac9538681b19688c8eae65811b329d3744af679e0bdfa5d842d0e32524c73e1c","affectsGlobalScope":true,"impliedFormat":1},{"version":"0a969edff4bd52585473d24995c5ef223f6652d6ef46193309b3921d65dd4376","affectsGlobalScope":true,"impliedFormat":1},{"version":"9e9fbd7030c440b33d021da145d3232984c8bb7916f277e8ffd3dc2e3eae2bdb","affectsGlobalScope":true,"impliedFormat":1},{"version":"811ec78f7fefcabbda4bfa93b3eb67d9ae166ef95f9bff989d964061cbf81a0c","affectsGlobalScope":true,"impliedFormat":1},{"version":"717937616a17072082152a2ef351cb51f98802fb4b2fdabd32399843875974ca","affectsGlobalScope":true,"impliedFormat":1},{"version":"d7e7d9b7b50e5f22c915b525acc5a49a7a6584cf8f62d0569e557c5cfc4b2ac2","affectsGlobalScope":true,"impliedFormat":1},{"version":"71c37f4c9543f31dfced6c7840e068c5a5aacb7b89111a4364b1d5276b852557","affectsGlobalScope":true,"impliedFormat":1},{"version":"576711e016cf4f1804676043e6a0a5414252560eb57de9faceee34d79798c850","affectsGlobalScope":true,"impliedFormat":1},{"version":"89c1b1281ba7b8a96efc676b11b264de7a8374c5ea1e6617f11880a13fc56dc6","affectsGlobalScope":true,"impliedFormat":1},{"version":"74f7fa2d027d5b33eb0471c8e82a6c87216223181ec31247c357a3e8e2fddc5b","affectsGlobalScope":true,"impliedFormat":1},{"version":"d6d7ae4d1f1f3772e2a3cde568ed08991a8ae34a080ff1151af28b7f798e22ca","affectsGlobalScope":true,"impliedFormat":1},{"version":"063600664504610fe3e99b717a1223f8b1900087fab0b4cad1496a114744f8df","affectsGlobalScope":true,"impliedFormat":1},{"version":"934019d7e3c81950f9a8426d093458b65d5aff2c7c1511233c0fd5b941e608ab","affectsGlobalScope":true,"impliedFormat":1},{"version":"52ada8e0b6e0482b728070b7639ee42e83a9b1c22d205992756fe020fd9f4a47","affectsGlobalScope":true,"impliedFormat":1},{"version":"3bdefe1bfd4d6dee0e26f928f93ccc128f1b64d5d501ff4a8cf3c6371200e5e6","affectsGlobalScope":true,"impliedFormat":1},{"version":"59fb2c069260b4ba00b5643b907ef5d5341b167e7d1dbf58dfd895658bda2867","affectsGlobalScope":true,"impliedFormat":1},{"version":"639e512c0dfc3fad96a84caad71b8834d66329a1f28dc95e3946c9b58176c73a","affectsGlobalScope":true,"impliedFormat":1},{"version":"368af93f74c9c932edd84c58883e736c9e3d53cec1fe24c0b0ff451f529ceab1","affectsGlobalScope":true,"impliedFormat":1},{"version":"af3dd424cf267428f30ccfc376f47a2c0114546b55c44d8c0f1d57d841e28d74","affectsGlobalScope":true,"impliedFormat":1},{"version":"995c005ab91a498455ea8dfb63aa9f83fa2ea793c3d8aa344be4a1678d06d399","affectsGlobalScope":true,"impliedFormat":1},{"version":"959d36cddf5e7d572a65045b876f2956c973a586da58e5d26cde519184fd9b8a","affectsGlobalScope":true,"impliedFormat":1},{"version":"965f36eae237dd74e6cca203a43e9ca801ce38824ead814728a2807b1910117d","affectsGlobalScope":true,"impliedFormat":1},{"version":"3925a6c820dcb1a06506c90b1577db1fdbf7705d65b62b99dce4be75c637e26b","affectsGlobalScope":true,"impliedFormat":1},{"version":"0a3d63ef2b853447ec4f749d3f368ce642264246e02911fcb1590d8c161b8005","affectsGlobalScope":true,"impliedFormat":1},{"version":"8cdf8847677ac7d20486e54dd3fcf09eda95812ac8ace44b4418da1bbbab6eb8","affectsGlobalScope":true,"impliedFormat":1},{"version":"8444af78980e3b20b49324f4a16ba35024fef3ee069a0eb67616ea6ca821c47a","affectsGlobalScope":true,"impliedFormat":1},{"version":"3287d9d085fbd618c3971944b65b4be57859f5415f495b33a6adc994edd2f004","affectsGlobalScope":true,"impliedFormat":1},{"version":"b4b67b1a91182421f5df999988c690f14d813b9850b40acd06ed44691f6727ad","affectsGlobalScope":true,"impliedFormat":1},{"version":"df83c2a6c73228b625b0beb6669c7ee2a09c914637e2d35170723ad49c0f5cd4","affectsGlobalScope":true,"impliedFormat":1},{"version":"436aaf437562f276ec2ddbee2f2cdedac7664c1e4c1d2c36839ddd582eeb3d0a","affectsGlobalScope":true,"impliedFormat":1},{"version":"8e3c06ea092138bf9fa5e874a1fdbc9d54805d074bee1de31b99a11e2fec239d","affectsGlobalScope":true,"impliedFormat":1},{"version":"51ad4c928303041605b4d7ae32e0c1ee387d43a24cd6f1ebf4a2699e1076d4fa","affectsGlobalScope":true,"impliedFormat":1},{"version":"196cb558a13d4533a5163286f30b0509ce0210e4b316c56c38d4c0fd2fb38405","affectsGlobalScope":true,"impliedFormat":1},{"version":"8e7f8264d0fb4c5339605a15daadb037bf238c10b654bb3eee14208f860a32ea","affectsGlobalScope":true,"impliedFormat":1},{"version":"782dec38049b92d4e85c1585fbea5474a219c6984a35b004963b00beb1aab538","affectsGlobalScope":true,"impliedFormat":1},{"version":"0df3024c30df0b1bb7d123ea4b8ee02a669173b62515d96ecf8c7e6f80aaae51","impliedFormat":1},{"version":"31b18451a893dfdcc66e8158b545da91e4948defb7ecbf9655cdf764cdf16239","signature":"3acd4da63638c7f7ee8bd049117425286058b47d0b4f52f8a8e5f55707b3aef8"},{"version":"589b47edf2106984d1eb908cab2720ead5919362c3796f79be66c20e58e0c76e","signature":"98fc5091348128b56fd52a3f2f37fd6ea59f1739843163453d8809c26fb36430"},{"version":"71412a49e2a7383a1674be29ea0cc45d7c16094aa5bfe711811d34bd46cf1b7e","signature":"8dd93c97330b19206ecbc709c795304dec3143a813e1f0463f36c9009864fc6b"},{"version":"dbf8bd57043a0f093276f0668aafa27d9a0f63089c52d4bbf5b43360001d6562","signature":"8ea1f140369b9c745f0a8c9963bd5c26c837e3b67183ee37d914ed6a620e5a7a"},{"version":"6a7e55aef75c0e68fc7e788911278a5c3d1c3c9cbb67587db892c4fcc544c62e","signature":"a96c5beada828ea39e62963f8018b3cd73857a032cc69a26cb6ba06cd966b6ad"},{"version":"79d598d0be628a468f5ab4b75eb27d259851a05a4ea1cfa1ced68f13ea571729","signature":"963923058134a645699c7b1dcad788fb8378e955c4a5890932f8d21cbddef28b"},{"version":"49fc7d2956791bc79441e11cbd5773a77f324b7f32600ffbf624ff40665493d0","signature":"0095ec48dc2766276d1621694338e6b1c658a2754f1f9af1158ef7f95cd6198b"},{"version":"9ce5670123e3a99ae5d7edfa65c760f1ca8a5556af0fc53f1ce60b0a245b3bd4","signature":"59d1fe7f70a440cc262e4868b4b2810e54f788c7a40946410f9a058181b55a47"},{"version":"6ce9079d89f12c26cb55518558d0987760cd30806c578f661f398428520c6cf5","signature":"0d63d11d1c95b31ae4c7ef989ea38ca143597e3b0735fdf6e6ca89293f0dd72f"},{"version":"c8871748edb776546cb7970a919140ceb6653bd675b267f23b1a803c3a1d68a0","signature":"1857b762e2f35181f6c8d1bbe24485a887419dedee4e819978639ea3c256da64"},{"version":"593b93111f455184a408520ed50e1b861fddb542e297493ab48fee71753fd2fa","signature":"4d21491fade0dd125a6e4031ef487dbd7ff91ec1a2e13cf1854b7f74f1148f39"},{"version":"454538c4cc7a9bc50de0705b7f77d8b67ed2585478855d885bfddb8bc6949669","signature":"85fb0955c01b197f4650b8b8d1c98514d588b4112910d57d1b1888fa62b5d1b0"},{"version":"a27f461ff9434170bdb6fdc071aa2f81aa871dca8b8e37499bdc0b5e9f7a6469","signature":"7df15809a3a5761352fa4bf926bf0d69796777a2719ec2a053eed24f0e25bc7b"},{"version":"8e513cc75a85891e691af088e1988d3b40ee37106442412d9067a1f9e1eea1c9","signature":"cc10c19641eb586ced803854607aec353b01236deb1001b87df6ec1df9593f83"},{"version":"04758008b53814c382bb3d73e3f0df7f457d4ca06de84a4bd7e1c2bca5cbf2a1","signature":"e6cff38bf49d2494d0830baee5e3f436d748371858f8310db2006879ccc6b964"},{"version":"d153a11543fd884b596587ccd97aebbeed950b26933ee000f94009f1ab142848","affectsGlobalScope":true,"impliedFormat":1},{"version":"378281aa35786c27d5811af7e6bcaa492eebd0c7013d48137c35bbc69a2b9751","affectsGlobalScope":true,"impliedFormat":1},{"version":"3af97acf03cc97de58a3a4bc91f8f616408099bc4233f6d0852e72a8ffb91ac9","affectsGlobalScope":true,"impliedFormat":1},{"version":"1b2dd1cbeb0cc6ae20795958ba5950395ebb2849b7c8326853dd15530c77ab0c","affectsGlobalScope":true,"impliedFormat":1},{"version":"1db0b7dca579049ca4193d034d835f6bfe73096c73663e5ef9a0b5779939f3d0","affectsGlobalScope":true,"impliedFormat":1},{"version":"387a023d363f755eb63450a66c28b14cdd7bc30a104565e2dbf0a8988bb4a56c","affectsGlobalScope":true,"impliedFormat":1},{"version":"9798340ffb0d067d69b1ae5b32faa17ab31b82466a3fc00d8f2f2df0c8554aaa","affectsGlobalScope":true,"impliedFormat":1},{"version":"f26b11d8d8e4b8028f1c7d618b22274c892e4b0ef5b3678a8ccbad85419aef43","affectsGlobalScope":true,"impliedFormat":1},{"version":"cdcf9ea426ad970f96ac930cd176d5c69c6c24eebd9fc580e1572d6c6a88f62c","impliedFormat":1},{"version":"23cd712e2ce083d68afe69224587438e5914b457b8acf87073c22494d706a3d0","impliedFormat":1},{"version":"156a859e21ef3244d13afeeba4e49760a6afa035c149dda52f0c45ea8903b338","impliedFormat":1},{"version":"10ec5e82144dfac6f04fa5d1d6c11763b3e4dbbac6d99101427219ab3e2ae887","impliedFormat":1},{"version":"615754924717c0b1e293e083b83503c0a872717ad5aa60ed7f1a699eb1b4ea5c","impliedFormat":1},{"version":"074de5b2fdead0165a2757e3aaef20f27a6347b1c36adea27d51456795b37682","impliedFormat":1},{"version":"68834d631c8838c715f225509cfc3927913b9cc7a4870460b5b60c8dbdb99baf","impliedFormat":1},{"version":"24371e69a38fc33e268d4a8716dbcda430d6c2c414a99ff9669239c4b8f40dea","impliedFormat":1},{"version":"ccab02f3920fc75c01174c47fcf67882a11daf16baf9e81701d0a94636e94556","impliedFormat":1},{"version":"3e11fce78ad8c0e1d1db4ba5f0652285509be3acdd519529bc8fcef85f7dafd9","impliedFormat":1},{"version":"ea6bc8de8b59f90a7a3960005fd01988f98fd0784e14bc6922dde2e93305ec7d","impliedFormat":1},{"version":"36107995674b29284a115e21a0618c4c2751b32a8766dd4cb3ba740308b16d59","impliedFormat":1},{"version":"914a0ae30d96d71915fc519ccb4efbf2b62c0ddfb3a3fc6129151076bc01dc60","impliedFormat":1},{"version":"9c32412007b5662fd34a8eb04292fb5314ec370d7016d1c2fb8aa193c807fe22","impliedFormat":1},{"version":"7fd1b31fd35876b0aa650811c25ec2c97a3c6387e5473eb18004bed86cdd76b6","impliedFormat":1},{"version":"4d327f7d72ad0918275cea3eee49a6a8dc8114ae1d5b7f3f5d0774de75f7439a","impliedFormat":1},{"version":"6ebe8ebb8659aaa9d1acbf3710d7dae3e923e97610238b9511c25dc39023a166","impliedFormat":1},{"version":"e85d7f8068f6a26710bff0cc8c0fc5e47f71089c3780fbede05857331d2ddec9","impliedFormat":1},{"version":"7befaf0e76b5671be1d47b77fcc65f2b0aad91cc26529df1904f4a7c46d216e9","impliedFormat":1},{"version":"0a60a292b89ca7218b8616f78e5bbd1c96b87e048849469cccb4355e98af959a","impliedFormat":1},{"version":"0b6e25234b4eec6ed96ab138d96eb70b135690d7dd01f3dd8a8ab291c35a683a","impliedFormat":1},{"version":"9666f2f84b985b62400d2e5ab0adae9ff44de9b2a34803c2c5bd3c8325b17dc0","impliedFormat":1},{"version":"40cd35c95e9cf22cfa5bd84e96408b6fcbca55295f4ff822390abb11afbc3dca","impliedFormat":1},{"version":"b1616b8959bf557feb16369c6124a97a0e74ed6f49d1df73bb4b9ddf68acf3f3","impliedFormat":1},{"version":"5b03a034c72146b61573aab280f295b015b9168470f2df05f6080a2122f9b4df","impliedFormat":1},{"version":"40b463c6766ca1b689bfcc46d26b5e295954f32ad43e37ee6953c0a677e4ae2b","impliedFormat":1},{"version":"249b9cab7f5d628b71308c7d9bb0a808b50b091e640ba3ed6e2d0516f4a8d91d","impliedFormat":1},{"version":"80aae6afc67faa5ac0b32b5b8bc8cc9f7fa299cff15cf09cc2e11fd28c6ae29e","impliedFormat":1},{"version":"f473cd2288991ff3221165dcf73cd5d24da30391f87e85b3dd4d0450c787a391","impliedFormat":1},{"version":"499e5b055a5aba1e1998f7311a6c441a369831c70905cc565ceac93c28083d53","impliedFormat":1},{"version":"8aee8b6d4f9f62cf3776cda1305fb18763e2aade7e13cea5bbe699112df85214","impliedFormat":1},{"version":"c63b9ada8c72f95aac5db92aea07e5e87ec810353cdf63b2d78f49a58662cf6c","impliedFormat":1},{"version":"1cc2a09e1a61a5222d4174ab358a9f9de5e906afe79dbf7363d871a7edda3955","impliedFormat":1},{"version":"5d0375ca7310efb77e3ef18d068d53784faf62705e0ad04569597ae0e755c401","impliedFormat":1},{"version":"59af37caec41ecf7b2e76059c9672a49e682c1a2aa6f9d7dc78878f53aa284d6","impliedFormat":1},{"version":"addf417b9eb3f938fddf8d81e96393a165e4be0d4a8b6402292f9c634b1cb00d","impliedFormat":1},{"version":"b64d4d1c5f877f9c666e98e833f0205edb9384acc46e98a1fef344f64d6aba44","impliedFormat":1},{"version":"adf27937dba6af9f08a68c5b1d3fce0ca7d4b960c57e6d6c844e7d1a8e53adae","impliedFormat":1},{"version":"12950411eeab8563b349cb7959543d92d8d02c289ed893d78499a19becb5a8cc","impliedFormat":1},{"version":"2e85db9e6fd73cfa3d7f28e0ab6b55417ea18931423bd47b409a96e4a169e8e6","impliedFormat":1},{"version":"c46e079fe54c76f95c67fb89081b3e399da2c7d109e7dca8e4b58d83e332e605","impliedFormat":1},{"version":"c9381908473a1c92cb8c516b184e75f4d226dad95c3a85a5af35f670064d9a2f","impliedFormat":1},{"version":"f724236417941ea77ec8d38c6b7021f5fb7f8521c7f8c1538e87661f2c6a0774","affectsGlobalScope":true,"impliedFormat":1},{"version":"1cf059eaf468efcc649f8cf6075d3cb98e9a35a0fe9c44419ec3d2f5428d7123","affectsGlobalScope":true,"impliedFormat":1},{"version":"e7721c4f69f93c91360c26a0a84ee885997d748237ef78ef665b153e622b36c1","affectsGlobalScope":true,"impliedFormat":1},{"version":"d97fb21da858fb18b8ae72c314e9743fd52f73ebe2764e12af1db32fc03f853f","affectsGlobalScope":true,"impliedFormat":1},{"version":"4ea15fd99b2e34cb25fe8346c955000bb70c8b423ae4377a972ef46bfb37f595","impliedFormat":1},{"version":"7cf69dd5502c41644c9e5106210b5da7144800670cbe861f66726fa209e231c4","impliedFormat":1},{"version":"72c1f5e0a28e473026074817561d1bc9647909cf253c8d56c41d1df8d95b85f7","impliedFormat":1},{"version":"f9b4137a0d285bd77dba2e6e895530112264310ae47e07bf311feae428fb8b61","affectsGlobalScope":true,"impliedFormat":1},{"version":"c06b2652ffeb89afd0f1c52c165ced77032f9cd09bc481153fbd6b5504c69494","impliedFormat":1},{"version":"51aecd2df90a3cffea1eb4696b33b2d78594ea2aa2138e6b9471ec4841c6c2ee","impliedFormat":1},{"version":"9d8f9e63e29a3396285620908e7f14d874d066caea747dc4b2c378f0599166b4","affectsGlobalScope":true,"impliedFormat":1},{"version":"5524481e56c48ff486f42926778c0a3cce1cc85dc46683b92b1271865bcf015a","impliedFormat":1},{"version":"612422d5ba6b4a5c4537f423e9199645468ad80a689801da63ab7edb43f7b835","impliedFormat":1},{"version":"db9ada976f9e52e13f7ae8b9a320f4b67b87685938c5879187d8864b2fbe97f3","impliedFormat":1},{"version":"9f39e70a354d0fba29ac3cdf6eca00b7f9e96f64b2b2780c432e8ea27f133743","impliedFormat":1},{"version":"0dace96cc0f7bc6d0ee2044921bdf19fe42d16284dbcc8ae200800d1c9579335","impliedFormat":1},{"version":"a2e2bbde231b65c53c764c12313897ffdfb6c49183dd31823ee2405f2f7b5378","impliedFormat":1},{"version":"1cbdcdef62bf42688e5d825898c3a59458466c48ad8a4ef3f88d8a1cd04310d6","impliedFormat":1},{"version":"c64e1888baaa3253ca4405b455e4bf44f76357868a1bd0a52998ade9a092ad78","affectsGlobalScope":true,"impliedFormat":1},{"version":"dc8c6f5322961b56d9906601b20798725df60baeab45ec014fba9f795d5596fd","impliedFormat":1},{"version":"67e435fa530778903f5525904e6645b7368eb5ac622055febd19bb399e328ccd","impliedFormat":1},{"version":"060d305fe4494d8cb2b99d620928d369d1ee55c1645f5e729a2aca07d0f108cb","impliedFormat":1},{"version":"5b22bf96be06fca1e134e3a85351ffe7aa2edf0c9a5bd175b7239ee48186dbf5","impliedFormat":1},{"version":"0c50296ee73dae94efc3f0da4936b1146ca6ce2217acfabb44c19c9a33fa30e5","impliedFormat":1},{"version":"bbf42f98a5819f4f06e18c8b669a994afe9a17fe520ae3454a195e6eabf7700d","impliedFormat":1},{"version":"5b48cc670da1dfe926036deaf349085caf822def460a6d50de23f1cc12a5f8cd","impliedFormat":1},{"version":"418f34087d52d001e2688a6282a5de9bf583ff771ed5546af0ae36e4f60a458b","affectsGlobalScope":true,"impliedFormat":1},{"version":"036c9a03b01281f99f8251fdc7088e894566be44b3f139a9d48501a978b611df","impliedFormat":1},{"version":"ff65b8a8bd380c6d129becc35de02f7c29ad7ce03300331ca91311fb4044d1a9","impliedFormat":1},{"version":"04bf1aa481d1adfb16d93d76e44ce71c51c8ef68039d849926551199489637f6","impliedFormat":1},{"version":"2c9adcc85574b002c9a6311ff2141055769e0071856ec979d92ff989042b1f1b","affectsGlobalScope":true,"impliedFormat":1},{"version":"1569ad5969ae0de6ad0bdfaaab0dabcd8878bc3147ab096206eed2019bb84e7f","affectsGlobalScope":true,"impliedFormat":1},{"version":"a58a15da4c5ba3df60c910a043281256fa52d36a0fcdef9b9100c646282e88dd","impliedFormat":1},{"version":"b36beffbf8acdc3ebc58c8bb4b75574b31a2169869c70fc03f82895b93950a12","impliedFormat":1},{"version":"42a350ce4f6f291198dc89833afcc4fd078248b4e1fdc9d05c846c66a670f710","impliedFormat":1},{"version":"77fbe5eecb6fac4b6242bbf6eebfc43e98ce5ccba8fa44e0ef6a95c945ff4d98","impliedFormat":1},{"version":"8c81fd4a110490c43d7c578e8c6f69b3af01717189196899a6a44f93daa57a3a","impliedFormat":1},{"version":"5fb39858b2459864b139950a09adae4f38dad87c25bf572ce414f10e4bd7baab","impliedFormat":1},{"version":"b03754211d839cdc48979996525a32eb62130682c2f9801dfc2f25533ce7238d","impliedFormat":1},{"version":"3910dab597c40e173bf0e0d419d3ce9682c54ebf6ae84849f9b829b1451a17ec","impliedFormat":1},{"version":"37ba7b45141a45ce6e80e66f2a96c8a5ab1bcef0fc2d0f56bb58df96ec67e972","impliedFormat":1},{"version":"45650f47bfb376c8a8ed39d4bcda5902ab899a3150029684ee4c10676d9fbaee","impliedFormat":1},{"version":"486c074a5c0f2254345c0d1c9540380f5463999e42d7e1a159305ea823d3c4b1","affectsGlobalScope":true,"impliedFormat":1},{"version":"c119835edf36415081dfd9ed15fc0cd37aaa28d232be029ad073f15f3d88c323","impliedFormat":1},{"version":"f4d99ac08c4097a3cc202bec2c7198c19dcdd80d4ec6c62d1356b10d03b119d5","impliedFormat":1},{"version":"9705cd157ffbb91c5cab48bdd2de5a437a372e63f870f8a8472e72ff634d47c1","affectsGlobalScope":true,"impliedFormat":1},{"version":"ae86f30d5d10e4f75ce8dcb6e1bd3a12ecec3d071a21e8f462c5c85c678efb41","impliedFormat":1},{"version":"ca77e83162eccec633513723d178d4203bdd5465297267696be08013bab0aa1d","impliedFormat":1},{"version":"e03460fe72b259f6d25ad029f085e4bedc3f90477da4401d8fbc1efa9793230e","impliedFormat":1},{"version":"4286a3a6619514fca656089aee160bb6f2e77f4dd53dc5a96b26a0b4fc778055","impliedFormat":1},{"version":"f61c153d5abbe4381a1fba0d41be0babdd5de51c626ee7ff14cede14dedc33f1","affectsGlobalScope":true,"impliedFormat":1},{"version":"7803171d745ab18e77f16bf82e742268ff72b7f7382ab191e4277527580c2d89","affectsGlobalScope":true,"impliedFormat":1},{"version":"0e9ba65cd3d6d194bdda7343f9f2917f7144ead96a924ca58d1a14919992dc20","impliedFormat":1},{"version":"255d948f87f24ffd57bcb2fdf95792fd418a2e1f712a98cf2cce88744d75085c","impliedFormat":1},{"version":"0d5b085f36e6dc55bc6332ecb9c733be3a534958c238fb8d8d18d4a2b6f2a15a","impliedFormat":1},{"version":"0b0dfb2d3e8420ead06f6a11acfb02ddcec42257e6ce391993e895ba0af86de4","affectsGlobalScope":true,"impliedFormat":1},{"version":"bfd3b3c21a56104693183942e221c1896ee23bcb8f8d91ab0b941f7b32985411","impliedFormat":1},{"version":"d7e9ab1b0996639047c61c1e62f85c620e4382206b3abb430d9a21fb7bc23c77","impliedFormat":1},{"version":"d2806f7b68a1533831bcfa0a72d50e4336a7341c1b8802ce9480d6799e9bc4f5","impliedFormat":1},{"version":"b9a9bf93f049cb3c766efa0ea6241991193a696d9838f7c16e5be854a48bceaf","impliedFormat":1},{"version":"994ab2ef8a87be9c16d2ddca21b0844eb14d6726fe05468c0e93d467c415b8a1","impliedFormat":1},{"version":"a356a366101a10fa309f074625eec5d51d5b0c90656ed62c0e8bdec5219837b5","impliedFormat":1},{"version":"7fb37e219b6e91f4295061b63868cd231e9f4021c307f396d6648df79766229a","impliedFormat":1},{"version":"de4e54f9dd0999029654135d5ad4716666c205f9324450baf982e10b19da4dd4","impliedFormat":1},{"version":"d6c16d18b8caf63c80e695525173e66bd771ff15bb4e1bbfbbf6c0045a236feb","impliedFormat":1},{"version":"7d59dcc9197c9a872c0d8bec846b3ad69b1d0ce8e78f5658a05c9c2d83ca1447","impliedFormat":1},{"version":"1a5e6c29ab30e8fe3b718b491303e4552b47c7930f8e6a1433ef62f1b45b9e32","impliedFormat":1},{"version":"cd758f1c3d4dedc862498f41d6544f390305fbc4fe1902c90ed50ff46802bcfa","signature":"f02a40c5b7520d527a400339836f67438927a52cc6b11a2c1d38bb7daf0df8b1"},{"version":"f0444158c4e84b2a656b6f8114ea363f48aae8c3a8720293dfa2df91b0fd675a","signature":"7d53549e4dde88f72b0b3db9f995f82cb68d6b3c171a7905d023d401a08318d2"},{"version":"c5e080893f95250d20a35df576fc13f85aa4259d3a3254b82db4e8797527c608","signature":"2dcd42dc3972f42e3b415b96f9072439ab6b7972a513d905a6d96dbdf2f869cf"},{"version":"909a53a6badbca96af14ee6fc635998d52074b80fd605114b77f8f26cc33b6e5","signature":"529ff564b0513164a1c6c2541fa7514131b4c816d65dbc172bd2130575d6d415"},{"version":"78e37a971813094af55aeb94a984975ac89fc93203ef9be3e8a04aad0c95cec1","signature":"784c4ce29dd51057ad472792a2437695b7345e8665738a49ef2153dcf09e4bc3"},{"version":"78e842f7a636b1f527ddc06fa27181282107b96234336f12a18fa95b68e44678","signature":"8509edb79c73edcde72ef16b57074af687efe3e8b5e3d73eae84ce68a67d9461"},{"version":"50ccf50d645d807e728ccead1ea6e8adea5f88bca6260b5e120772b0fcd87188","signature":"173b207c54834c37f208c98a03eddac27d5798260dfe95d38d482ebd3352e0a7"},{"version":"10fb4a09e37fc09c69ed578e8b2cee83c827cf18ed5812a22e4b3eb731268722","signature":"6b1560d38d963df46db84b648279801e19cb507dd016ae97a881ad0649954335"},{"version":"aefe3521550274d45e1eafc12acf8bd53a9f4f14b8271a82ccee62fccc82d833","signature":"b85fbb124083a076d5243a06aebcb7827af70d60a79d1bd3103005841f48f786"},{"version":"772236ee9d8380768b08362318c73460af14d4fb6b4945880002fca9ec7fc188","signature":"2fc2385a4df49a6855a2011b1d17b637a9c10ca3f6ab9f6caf9bd70e969073b5"},{"version":"4f0f521c3e550596664c0e2f7b1e00144cf003a1bbf95a6110bfcebff1943d2c","signature":"ef9feead1e6743148e5c4e85a0563a0fd92d59f5138c30c4527bf744ac3a0d55"},{"version":"5c855ee0553535df3fd43f77b4b0c46ca17357362ff321d1e541fa7e065900af","signature":"7752534b78a62464a2930a4778bf88e4c75bdd203d02e91ecef7982415735604"},{"version":"6781b8b0fa7aab693ed88853c874605879a0b17ee736b7ec1d6542100d1d95fb","signature":"eb24ac4188e14d346953e727dce4cff9862dba15938f2583929777553093c6f9"},{"version":"514fa467bed37b3bbf4fa295cd8db133b213dcdfe4aef9a19e9e99dd868c4937","signature":"2ac458815ba13b80da711c935e7a73a7fe4466015d5a11d90804ec07513ace89"},{"version":"c92f6f330888e60777ad64851e67c3b0290fd78d2fcbf6dc6ab42babbbbfb1a6","signature":"aad6f02558a19f62dd28836c98b36b0e087f950914953805a89bdbd3a8b927ad"},{"version":"e299652f5e5959b894cfd17545e668292bb64e9a58dbd316c68868ef90a76afc","signature":"b686d4582f744ca222e6c29871e7114ce83d805efe4286ab155dc1b014b5bf07"},{"version":"4704a596458f58bc97ed19af71c7284975877f7a4c008ba8225a23e3cfd7b982","signature":"5b498abd6ecfc929411994bd3b268ac8a1d930057f92f088f2d3b21cdcee3ff2"},"761042f7def8ac25af4395ef3fcbe3ee9a01bbf88aaf1a959435710020dc33e7",{"version":"9139f4769fe4a9737a03a25c0de887c2e51d0790eb69db33290ea563d1a19816","signature":"c4fb8a0f3f3d4ca3b9c3ccf8c841450caad67bb2d1cf9870d3fba9d7afd906e2"},{"version":"0f41fd58527b6191b294c8dc8f6547e584dbfc7811b33786f5c540969d7c24ab","signature":"a3be6822a6e3f9b309af7f4adfc5327c9af6db546e82077ef9262d997b236df6"},{"version":"ec38c06860ce480ad66069e64ffca2ad6098d1b78386e0e3b52ace8f4ce5d6b8","signature":"ed1c0a9834df25b836f147e57eed95e662ec7bb3ed563c29023fe35e6e7f2781"},{"version":"5976c615e8a5c03480bd11d0e309a88a252e914857dedaec94a55cd7ffd3f814","signature":"9a66ee5f0d928381f26c2b6a2a7164d23bb17696ea371b6027d1d939bf9cbcbb"},{"version":"5fa3f03aae0f8c0d455a742c8d13415c654c592551bbeafd7340071d7e63b6d4","signature":"8b92d8c784772b011c19170c3698e8caa724e7936cfb053888b0e798a6ab9c34"},{"version":"e2de8e78f329083f9d63aa04da8c9788f8087c503f9d688597f4a89459cc2638","signature":"58b8a92502891f00e8525f156ef0f4cb1f31088fe5c7afe371b75c5b9d6de6ef"},{"version":"6addcfb754a091abca4ec952330421d85cd5de44a68c8d0bc04a55f07aa629f5","signature":"c7cf07567328a1256168b6b20aa0e3c68ce394cab81ba50a63bc37b1f4964117"},{"version":"419e60fcda0e1a42092e173f63d12c4954e41e3fcb2c5d0f9bb819ec5f0bcef7","signature":"f0f23fb249e8a350554f074841f4fd81b533af2e585eca66c8337972a85bb9f9"},{"version":"9241ec0a181d4058d7a5d6061a633ed160730343fb9f936f2abb1eb0c47d0be6","signature":"05a26a029742d2bb5be847aa08ff97e32eafccd632a2874787397af1e1615045"},{"version":"2d97baa4c69ec4e5e8e878d331fbd2e6b55703795911e79e9b01859dc7c83e8f","signature":"fd0114eab35d9a4663f0c43d5753d169701a3e2d826c88d2ce70018708ce2b0a"},{"version":"a7aebaad76069144de1aa3260e880c9293c7d0f4c463a9c3240f02e55a610e51","signature":"b090778e899e8c650ed8576cd1397bb4829fea5a42cb876ea9eb15130717247b"},{"version":"2b438b959baddb6a435f39192f2af29a083e9686eeef1b64831246397fbd2456","signature":"f6444f20af7fb78da6fa1c2741a13c3992ba56e003cfd8e11765ed6a76eb8702"},{"version":"8194b458b91478dee20dff591cf489da6c86a4f0149764b0c7d0fc222add3bbb","signature":"ce0d69997971e7911d0678361cc90a5db735f777775552005bcad4df909e7cc9"},{"version":"4da1276835404d327af8d2473045d38ecfa729afae23db7bb8a3cbbc5731785a","signature":"ac6c2d13a2611ecd493a4559bc38edd3e717b794819c2f0793d57aaf8124c315"},{"version":"db86e53523e57f90fb85c6f716cc667e09b8adaade43dcd56862496e95c91d42","signature":"6e83177938d46f22dfd0617b424bf8ddb8d4021b10f36df5f7d49b6ac44a572f"},{"version":"1411ab908072924d565a80c630d52dde1410753a9d9e558d376f0586e565cb91","signature":"eff12d10abc71233147232e6013930694e84664a969aa4276711da23d7c237f8"},{"version":"91432dc8f7edc1bbb00ac3a7ceda5d76d2e27d3930d534226853d3c70a9d72c5","signature":"26df63a4cf13e015eb455000154dc5d28701fb99d8da156da7003897b5ddaa0a"},{"version":"6e4ee2c61ba1fa1e24b41a4a663641dc963203f0e36b9e36cf0596acc0ebd66f","signature":"8d5d974b6af785f4533176dd3e13d50497b869d5dbe56204d05ed2f6d19a4690"},{"version":"d5799bcf7fe4e6de3063abf4e321c14b051706f03cf5716d8a19f22fe1f69519","impliedFormat":1},{"version":"751764bb94219b4ce8f5475dc35d3de2e432fea01a0c9610cd7f69ad05e398c6","impliedFormat":1},{"version":"f3d8c757e148ad968f0d98697987db363070abada5f503da3c06aefd9d4248c1","impliedFormat":1}],"root":[[65,79],[197,232]],"options":{"declaration":true,"declarationMap":true,"esModuleInterop":true,"exactOptionalPropertyTypes":false,"module":1,"noFallthroughCasesInSwitch":true,"noImplicitOverride":true,"noPropertyAccessFromIndexSignature":false,"noUncheckedIndexedAccess":true,"outDir":"./","rootDir":"../src","skipLibCheck":true,"sourceMap":true,"strict":true,"target":10,"tsBuildInfoFile":"./.tsbuildinfo"},"referencedMap":[[233,1],[234,1],[235,1],[134,2],[135,2],[136,3],[82,4],[137,5],[138,6],[139,7],[80,1],[140,8],[141,9],[142,10],[143,11],[144,12],[145,13],[146,13],[147,14],[148,15],[149,16],[150,17],[83,1],[81,1],[151,18],[152,19],[153,20],[187,21],[154,22],[155,1],[156,23],[157,24],[158,25],[159,26],[160,27],[161,28],[162,29],[163,30],[164,31],[165,31],[166,32],[167,1],[168,33],[169,34],[171,35],[170,36],[172,37],[173,38],[174,39],[175,40],[176,41],[177,42],[178,43],[179,44],[180,45],[181,46],[182,47],[183,48],[184,49],[84,1],[85,50],[86,1],[87,1],[130,51],[131,52],[132,1],[133,37],[185,53],[186,54],[196,55],[194,56],[188,57],[191,58],[190,56],[195,59],[192,56],[193,56],[189,60],[64,1],[62,1],[63,1],[12,1],[11,1],[2,1],[13,1],[14,1],[15,1],[16,1],[17,1],[18,1],[19,1],[20,1],[3,1],[21,1],[22,1],[4,1],[23,1],[27,1],[24,1],[25,1],[26,1],[28,1],[29,1],[30,1],[5,1],[31,1],[32,1],[33,1],[34,1],[6,1],[38,1],[35,1],[36,1],[37,1],[39,1],[7,1],[40,1],[45,1],[46,1],[41,1],[42,1],[43,1],[44,1],[8,1],[50,1],[47,1],[48,1],[49,1],[51,1],[9,1],[52,1],[53,1],[54,1],[56,1],[55,1],[57,1],[58,1],[10,1],[59,1],[1,1],[60,1],[61,1],[106,61],[118,62],[103,63],[119,58],[128,64],[94,65],[95,66],[93,67],[127,68],[122,69],[126,70],[97,71],[115,72],[96,73],[125,74],[91,75],[92,69],[98,76],[99,1],[105,77],[102,76],[89,78],[129,79],[120,80],[109,81],[108,76],[110,82],[113,83],[107,84],[111,85],[123,68],[100,86],[101,87],[114,88],[90,58],[117,89],[116,76],[104,87],[112,90],[121,1],[88,1],[124,91],[205,92],[215,1],[217,93],[216,1],[218,94],[72,1],[75,1],[77,95],[79,96],[78,97],[221,98],[219,1],[222,99],[227,100],[228,101],[230,102],[231,103],[232,104],[210,105],[206,1],[220,106],[225,107],[226,108],[211,109],[212,110],[224,111],[207,112],[71,113],[69,113],[65,114],[68,113],[70,113],[208,112],[229,95],[213,115],[204,116],[202,1],[203,117],[197,118],[199,119],[198,95],[200,120],[73,113],[74,121],[76,122],[67,95],[66,1],[201,50],[209,1],[223,123],[214,1]],"version":"5.9.3"}
@@ -0,0 +1,91 @@
1
+ /**
2
+ * Content first API.
3
+ *
4
+ * `extract()` takes a raw RFC 5322 message and does its own MIME parsing. Most callers do not have
5
+ * one: they have already parsed the message, with mailparser, postal-mime, EmailEngine or an IMAP
6
+ * client, and hold `{ text, html, subject }`. Re-serialising that back into a message just to parse
7
+ * it again would be wasteful and lossy.
8
+ *
9
+ * `analyze()` is the same pipeline entered one stage later. Stage 1 is skipped, Stages 2 to 8 are
10
+ * identical, and the result has the same shape. Everything the extractor decides is derived from
11
+ * the bodies themselves, so nothing is lost by not having the envelope.
12
+ */
13
+ import { type ConfidenceConfig } from './classify/confidence';
14
+ import { type HistoryDocument } from './match/history';
15
+ import { type Reason, type Segment, type Warning } from './types';
16
+ /** A message body, in whichever representations are available. */
17
+ export interface MessageContent {
18
+ /** Plain text body, already transfer and charset decoded. */
19
+ text?: string | null;
20
+ /** HTML body, already transfer and charset decoded. */
21
+ html?: string | null;
22
+ /** Subject line. Optional, and never allowed to change a label on its own. */
23
+ subject?: string | null;
24
+ /** Sender, as a display name and/or address. Used only as signature evidence. */
25
+ from?: string | null;
26
+ /** Threading hints. Optional, used only to note whether the message looks like a reply. */
27
+ inReplyTo?: string | null;
28
+ references?: readonly string[];
29
+ /** MIME part ids, when the caller knows them, purely for traceability in the output. */
30
+ textPartId?: string;
31
+ htmlPartId?: string;
32
+ }
33
+ export interface AnalyzeOptions {
34
+ confidence?: ConfidenceConfig;
35
+ /**
36
+ * Earlier messages in the thread, nearest first. Each may be raw RFC 5322 or already split
37
+ * content. History is optional and only ever adds evidence.
38
+ */
39
+ history?: readonly (MessageContent | string | Buffer)[];
40
+ /** Pre-built history documents, for callers that resolve and cache threads themselves. */
41
+ historyDocuments?: readonly HistoryDocument[];
42
+ explain?: boolean;
43
+ }
44
+ export interface AnalyzeResult {
45
+ /** Segments the client should render, in document order. */
46
+ segments: Segment[];
47
+ /** Segments the client may hide or collapse. Retained in full so nothing is ever lost. */
48
+ hiddenSegments: Segment[];
49
+ overallConfidence: number;
50
+ warnings: Warning[];
51
+ originalAvailable: true;
52
+ primaryRepresentation: 'text' | 'html' | 'none';
53
+ extractorVersion: string;
54
+ historyUsed: boolean;
55
+ /** True when the input looked like a reply, from threading headers or a subject prefix. */
56
+ isReply: boolean;
57
+ diagnostics?: {
58
+ primaryPart: string | null;
59
+ blocks: {
60
+ index: number;
61
+ kind: string;
62
+ label: string;
63
+ confidence: number;
64
+ reasons: Reason[];
65
+ evidence: {
66
+ id: string;
67
+ kind: string;
68
+ strength: number;
69
+ }[];
70
+ features: Record<string, unknown>;
71
+ preview: string;
72
+ }[];
73
+ };
74
+ }
75
+ /**
76
+ * Name tokens from a From header, for signature detection.
77
+ *
78
+ * Takes the display name words and the address local part, keeping tokens long enough to be
79
+ * distinctive. Short tokens are dropped because a two letter name fragment matches everywhere.
80
+ */
81
+ export declare function senderTokensFrom(from: string | null | undefined): string[];
82
+ /** Turn whatever the caller supplied as history into searchable documents. */
83
+ export declare function resolveHistory(options: AnalyzeOptions): Promise<HistoryDocument[]>;
84
+ /**
85
+ * Analyse an already parsed message body.
86
+ *
87
+ * Never throws. A body that cannot be segmented is returned whole as a single visible `UNKNOWN`
88
+ * segment, because showing too much is always preferable to showing nothing.
89
+ */
90
+ export declare function analyze(content: MessageContent, options?: AnalyzeOptions): Promise<AnalyzeResult>;
91
+ //# sourceMappingURL=analyze.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analyze.d.ts","sourceRoot":"","sources":["../src/analyze.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAOH,OAAO,EAAwD,KAAK,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACpH,OAAO,EAAsF,KAAK,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAC3I,OAAO,EAAqB,KAAK,MAAM,EAAE,KAAK,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,SAAS,CAAC;AAErF,kEAAkE;AAClE,MAAM,WAAW,cAAc;IAC3B,6DAA6D;IAC7D,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,uDAAuD;IACvD,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,8EAA8E;IAC9E,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,iFAAiF;IACjF,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,2FAA2F;IAC3F,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,UAAU,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/B,wFAAwF;IACxF,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,cAAc;IAC3B,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAC9B;;;OAGG;IACH,OAAO,CAAC,EAAE,SAAS,CAAC,cAAc,GAAG,MAAM,GAAG,MAAM,CAAC,EAAE,CAAC;IACxD,0FAA0F;IAC1F,gBAAgB,CAAC,EAAE,SAAS,eAAe,EAAE,CAAC;IAC9C,OAAO,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,aAAa;IAC1B,4DAA4D;IAC5D,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,0FAA0F;IAC1F,cAAc,EAAE,OAAO,EAAE,CAAC;IAC1B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,iBAAiB,EAAE,IAAI,CAAC;IACxB,qBAAqB,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;IAChD,gBAAgB,EAAE,MAAM,CAAC;IACzB,WAAW,EAAE,OAAO,CAAC;IACrB,2FAA2F;IAC3F,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,CAAC,EAAE;QACV,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;QAC3B,MAAM,EAAE;YACJ,KAAK,EAAE,MAAM,CAAC;YACd,IAAI,EAAE,MAAM,CAAC;YACb,KAAK,EAAE,MAAM,CAAC;YACd,UAAU,EAAE,MAAM,CAAC;YACnB,OAAO,EAAE,MAAM,EAAE,CAAC;YAClB,QAAQ,EAAE;gBAAE,EAAE,EAAE,MAAM,CAAC;gBAAC,IAAI,EAAE,MAAM,CAAC;gBAAC,QAAQ,EAAE,MAAM,CAAA;aAAE,EAAE,CAAC;YAC3D,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;YAClC,OAAO,EAAE,MAAM,CAAC;SACnB,EAAE,CAAC;KACP,CAAC;CACL;AAiBD;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,EAAE,CAa1E;AAoED,8EAA8E;AAC9E,wBAAsB,cAAc,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC,CAkBxF;AAED;;;;;GAKG;AACH,wBAAsB,OAAO,CAAC,OAAO,EAAE,cAAc,EAAE,OAAO,GAAE,cAAmB,GAAG,OAAO,CAAC,aAAa,CAAC,CAuI3G"}