@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.
- package/LICENSE +21 -0
- package/README.md +288 -0
- package/dist/.tsbuildinfo +1 -0
- package/dist/analyze.d.ts +91 -0
- package/dist/analyze.d.ts.map +1 -0
- package/dist/analyze.js +274 -0
- package/dist/analyze.js.map +1 -0
- package/dist/annotate/client.d.ts +64 -0
- package/dist/annotate/client.d.ts.map +1 -0
- package/dist/annotate/client.js +139 -0
- package/dist/annotate/client.js.map +1 -0
- package/dist/annotate/llm.d.ts +46 -0
- package/dist/annotate/llm.d.ts.map +1 -0
- package/dist/annotate/llm.js +107 -0
- package/dist/annotate/llm.js.map +1 -0
- package/dist/annotate/prompt.d.ts +38 -0
- package/dist/annotate/prompt.d.ts.map +1 -0
- package/dist/annotate/prompt.js +165 -0
- package/dist/annotate/prompt.js.map +1 -0
- package/dist/annotate/store.d.ts +43 -0
- package/dist/annotate/store.d.ts.map +1 -0
- package/dist/annotate/store.js +46 -0
- package/dist/annotate/store.js.map +1 -0
- package/dist/canonical/html.d.ts +33 -0
- package/dist/canonical/html.d.ts.map +1 -0
- package/dist/canonical/html.js +156 -0
- package/dist/canonical/html.js.map +1 -0
- package/dist/canonical/text.d.ts +75 -0
- package/dist/canonical/text.d.ts.map +1 -0
- package/dist/canonical/text.js +217 -0
- package/dist/canonical/text.js.map +1 -0
- package/dist/classify/confidence.d.ts +38 -0
- package/dist/classify/confidence.d.ts.map +1 -0
- package/dist/classify/confidence.js +59 -0
- package/dist/classify/confidence.js.map +1 -0
- package/dist/classify/reconcile.d.ts +52 -0
- package/dist/classify/reconcile.d.ts.map +1 -0
- package/dist/classify/reconcile.js +100 -0
- package/dist/classify/reconcile.js.map +1 -0
- package/dist/classify/rules.d.ts +51 -0
- package/dist/classify/rules.d.ts.map +1 -0
- package/dist/classify/rules.js +648 -0
- package/dist/classify/rules.js.map +1 -0
- package/dist/cli/annotate.d.ts +23 -0
- package/dist/cli/annotate.d.ts.map +1 -0
- package/dist/cli/annotate.js +328 -0
- package/dist/cli/annotate.js.map +1 -0
- package/dist/cli/args.d.ts +17 -0
- package/dist/cli/args.d.ts.map +1 -0
- package/dist/cli/args.js +72 -0
- package/dist/cli/args.js.map +1 -0
- package/dist/cli/benchmark.d.ts +13 -0
- package/dist/cli/benchmark.d.ts.map +1 -0
- package/dist/cli/benchmark.js +172 -0
- package/dist/cli/benchmark.js.map +1 -0
- package/dist/cli/corpus.d.ts +9 -0
- package/dist/cli/corpus.d.ts.map +1 -0
- package/dist/cli/corpus.js +152 -0
- package/dist/cli/corpus.js.map +1 -0
- package/dist/cli/disagreements.d.ts +14 -0
- package/dist/cli/disagreements.d.ts.map +1 -0
- package/dist/cli/disagreements.js +133 -0
- package/dist/cli/disagreements.js.map +1 -0
- package/dist/cli/evaluate.d.ts +15 -0
- package/dist/cli/evaluate.d.ts.map +1 -0
- package/dist/cli/evaluate.js +215 -0
- package/dist/cli/evaluate.js.map +1 -0
- package/dist/cli/extract.d.ts +10 -0
- package/dist/cli/extract.d.ts.map +1 -0
- package/dist/cli/extract.js +139 -0
- package/dist/cli/extract.js.map +1 -0
- package/dist/cli/main.d.ts +9 -0
- package/dist/cli/main.d.ts.map +1 -0
- package/dist/cli/main.js +147 -0
- package/dist/cli/main.js.map +1 -0
- package/dist/corpus/analyze.d.ts +66 -0
- package/dist/corpus/analyze.d.ts.map +1 -0
- package/dist/corpus/analyze.js +214 -0
- package/dist/corpus/analyze.js.map +1 -0
- package/dist/corpus/migrations/index.d.ts +14 -0
- package/dist/corpus/migrations/index.d.ts.map +1 -0
- package/dist/corpus/migrations/index.js +158 -0
- package/dist/corpus/migrations/index.js.map +1 -0
- package/dist/corpus/sample.d.ts +66 -0
- package/dist/corpus/sample.d.ts.map +1 -0
- package/dist/corpus/sample.js +98 -0
- package/dist/corpus/sample.js.map +1 -0
- package/dist/corpus/scanner.d.ts +79 -0
- package/dist/corpus/scanner.d.ts.map +1 -0
- package/dist/corpus/scanner.js +256 -0
- package/dist/corpus/scanner.js.map +1 -0
- package/dist/corpus/stats.d.ts +76 -0
- package/dist/corpus/stats.d.ts.map +1 -0
- package/dist/corpus/stats.js +240 -0
- package/dist/corpus/stats.js.map +1 -0
- package/dist/corpus/store.d.ts +67 -0
- package/dist/corpus/store.d.ts.map +1 -0
- package/dist/corpus/store.js +196 -0
- package/dist/corpus/store.js.map +1 -0
- package/dist/corpus/thread-index.d.ts +31 -0
- package/dist/corpus/thread-index.d.ts.map +1 -0
- package/dist/corpus/thread-index.js +182 -0
- package/dist/corpus/thread-index.js.map +1 -0
- package/dist/corpus/worker.d.ts +21 -0
- package/dist/corpus/worker.d.ts.map +1 -0
- package/dist/corpus/worker.js +74 -0
- package/dist/corpus/worker.js.map +1 -0
- package/dist/detect/client.d.ts +28 -0
- package/dist/detect/client.d.ts.map +1 -0
- package/dist/detect/client.js +121 -0
- package/dist/detect/client.js.map +1 -0
- package/dist/detect/disclaimer.d.ts +12 -0
- package/dist/detect/disclaimer.d.ts.map +1 -0
- package/dist/detect/disclaimer.js +28 -0
- package/dist/detect/disclaimer.js.map +1 -0
- package/dist/detect/forward-header.d.ts +10 -0
- package/dist/detect/forward-header.d.ts.map +1 -0
- package/dist/detect/forward-header.js +35 -0
- package/dist/detect/forward-header.js.map +1 -0
- package/dist/detect/patterns/disclaimers.json +113 -0
- package/dist/detect/patterns/forward-headers.json +40 -0
- package/dist/detect/patterns/html-clients.json +157 -0
- package/dist/detect/patterns/quoted-headers.json +41 -0
- package/dist/detect/patterns/reply-headers.json +139 -0
- package/dist/detect/patterns/signatures.json +58 -0
- package/dist/detect/patterns.d.ts +43 -0
- package/dist/detect/patterns.d.ts.map +1 -0
- package/dist/detect/patterns.js +125 -0
- package/dist/detect/patterns.js.map +1 -0
- package/dist/detect/reply-header.d.ts +44 -0
- package/dist/detect/reply-header.d.ts.map +1 -0
- package/dist/detect/reply-header.js +134 -0
- package/dist/detect/reply-header.js.map +1 -0
- package/dist/detect/signature.d.ts +28 -0
- package/dist/detect/signature.d.ts.map +1 -0
- package/dist/detect/signature.js +77 -0
- package/dist/detect/signature.js.map +1 -0
- package/dist/detect/traffic.d.ts +26 -0
- package/dist/detect/traffic.d.ts.map +1 -0
- package/dist/detect/traffic.js +98 -0
- package/dist/detect/traffic.js.map +1 -0
- package/dist/eval/metrics.d.ts +87 -0
- package/dist/eval/metrics.d.ts.map +1 -0
- package/dist/eval/metrics.js +185 -0
- package/dist/eval/metrics.js.map +1 -0
- package/dist/index.d.ts +54 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +163 -0
- package/dist/index.js.map +1 -0
- package/dist/match/history.d.ts +62 -0
- package/dist/match/history.d.ts.map +1 -0
- package/dist/match/history.js +128 -0
- package/dist/match/history.js.map +1 -0
- package/dist/match/normalize.d.ts +33 -0
- package/dist/match/normalize.d.ts.map +1 -0
- package/dist/match/normalize.js +63 -0
- package/dist/match/normalize.js.map +1 -0
- package/dist/match/shingle.d.ts +44 -0
- package/dist/match/shingle.d.ts.map +1 -0
- package/dist/match/shingle.js +78 -0
- package/dist/match/shingle.js.map +1 -0
- package/dist/mime/charset.d.ts +33 -0
- package/dist/mime/charset.d.ts.map +1 -0
- package/dist/mime/charset.js +118 -0
- package/dist/mime/charset.js.map +1 -0
- package/dist/mime/headers.d.ts +32 -0
- package/dist/mime/headers.d.ts.map +1 -0
- package/dist/mime/headers.js +127 -0
- package/dist/mime/headers.js.map +1 -0
- package/dist/mime/model.d.ts +111 -0
- package/dist/mime/model.d.ts.map +1 -0
- package/dist/mime/model.js +17 -0
- package/dist/mime/model.js.map +1 -0
- package/dist/mime/parse.d.ts +27 -0
- package/dist/mime/parse.d.ts.map +1 -0
- package/dist/mime/parse.js +343 -0
- package/dist/mime/parse.js.map +1 -0
- package/dist/segment/features.d.ts +29 -0
- package/dist/segment/features.d.ts.map +1 -0
- package/dist/segment/features.js +102 -0
- package/dist/segment/features.js.map +1 -0
- package/dist/segment/html-blocks.d.ts +28 -0
- package/dist/segment/html-blocks.d.ts.map +1 -0
- package/dist/segment/html-blocks.js +596 -0
- package/dist/segment/html-blocks.js.map +1 -0
- package/dist/segment/text-blocks.d.ts +30 -0
- package/dist/segment/text-blocks.d.ts.map +1 -0
- package/dist/segment/text-blocks.js +204 -0
- package/dist/segment/text-blocks.js.map +1 -0
- package/dist/segment/types.d.ts +88 -0
- package/dist/segment/types.d.ts.map +1 -0
- package/dist/segment/types.js +11 -0
- package/dist/segment/types.js.map +1 -0
- package/dist/types.d.ts +85 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +17 -0
- package/dist/types.js.map +1 -0
- package/dist/util/hash.d.ts +49 -0
- package/dist/util/hash.d.ts.map +1 -0
- package/dist/util/hash.js +0 -0
- package/dist/util/hash.js.map +1 -0
- package/dist/util/lang.d.ts +25 -0
- package/dist/util/lang.d.ts.map +1 -0
- package/dist/util/lang.js +135 -0
- package/dist/util/lang.js.map +1 -0
- package/dist/util/worker-pool.d.ts +51 -0
- package/dist/util/worker-pool.d.ts.map +1 -0
- package/dist/util/worker-pool.js +155 -0
- package/dist/util/worker-pool.js.map +1 -0
- package/package.json +74 -0
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* `email-content evaluate` subcommand.
|
|
4
|
+
*
|
|
5
|
+
* Scores the current extractor against a stored reference set. The reference is re-scored from
|
|
6
|
+
* scratch every run, rather than reusing the baseline verdict captured at annotation time, so that
|
|
7
|
+
* a change to the rules is actually measured instead of being compared against its own past
|
|
8
|
+
* output.
|
|
9
|
+
*
|
|
10
|
+
* The reference here is LLM produced. It is treated as a reference, not as truth: two capable
|
|
11
|
+
* models agree with each other on about 80 percent of blocks, so a number in the high nineties
|
|
12
|
+
* would indicate a measurement problem, not a solved task.
|
|
13
|
+
*/
|
|
14
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
15
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
16
|
+
};
|
|
17
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
exports.evaluateCommand = evaluateCommand;
|
|
19
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
|
20
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
21
|
+
const index_1 = require("../index");
|
|
22
|
+
const store_1 = require("../corpus/store");
|
|
23
|
+
const thread_index_1 = require("../corpus/thread-index");
|
|
24
|
+
const metrics_1 = require("../eval/metrics");
|
|
25
|
+
const parse_1 = require("../mime/parse");
|
|
26
|
+
const types_1 = require("../types");
|
|
27
|
+
const args_1 = require("./args");
|
|
28
|
+
function pct(value) {
|
|
29
|
+
return `${(100 * value).toFixed(1)}%`;
|
|
30
|
+
}
|
|
31
|
+
function renderReport(report, title) {
|
|
32
|
+
const out = [];
|
|
33
|
+
out.push(title);
|
|
34
|
+
out.push(` messages ${report.messages}, blocks ${report.blocks}, exact label agreement ${pct(report.exactAgreement)}`);
|
|
35
|
+
out.push('');
|
|
36
|
+
out.push('CONTENT RETENTION (the headline numbers)');
|
|
37
|
+
const r = report.retention;
|
|
38
|
+
out.push(` new content characters retained ${pct(r.newContentCharRecall)} (${r.newContentCharsRetained} of ${r.newContentChars})`);
|
|
39
|
+
out.push(` new content blocks retained ${pct(r.newContentBlockRecall)} (${r.newContentBlocksRetained} of ${r.newContentBlocks})`);
|
|
40
|
+
out.push(` hidden content genuinely history ${pct(r.hiddenPrecision)} (${r.hiddenCharsGenuinelyHistory} of ${r.hiddenChars})`);
|
|
41
|
+
out.push(` history still visible ${pct(r.historyStillVisibleShare)} (${r.historyCharsStillVisible} of ${r.historyChars})`);
|
|
42
|
+
out.push('');
|
|
43
|
+
out.push('PER LABEL');
|
|
44
|
+
out.push(' label support predicted precision recall f1');
|
|
45
|
+
for (const metric of report.perLabel) {
|
|
46
|
+
if (!metric.support && !metric.predicted) {
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
out.push(` ${metric.label.padEnd(18)} ${String(metric.support).padStart(7)} ${String(metric.predicted).padStart(10)} ` +
|
|
50
|
+
`${pct(metric.precision).padStart(10)} ${pct(metric.recall).padStart(7)} ${pct(metric.f1).padStart(7)}`);
|
|
51
|
+
}
|
|
52
|
+
out.push('');
|
|
53
|
+
out.push('CONFUSION (rows: reference, columns: predicted)');
|
|
54
|
+
const present = types_1.LABELS.filter(label => report.perLabel.find(metric => metric.label === label && (metric.support || metric.predicted)));
|
|
55
|
+
out.push(` ${' '.repeat(18)}${present.map(label => label.slice(0, 8).padStart(9)).join('')}`);
|
|
56
|
+
for (const reference of present) {
|
|
57
|
+
const cells = present.map(predicted => String(report.confusion.get(`${reference}|${predicted}`) ?? 0).padStart(9)).join('');
|
|
58
|
+
out.push(` ${reference.padEnd(18)}${cells}`);
|
|
59
|
+
}
|
|
60
|
+
out.push('');
|
|
61
|
+
out.push('CATASTROPHIC ERRORS (counted per message, never averaged)');
|
|
62
|
+
const c = report.catastrophic;
|
|
63
|
+
const line = (label, value) => ` ${label.padEnd(42)} ${String(value).padStart(5)} ${pct(value / Math.max(1, c.messages))}`;
|
|
64
|
+
out.push(line('all new content removed', c.allNewContentRemoved));
|
|
65
|
+
out.push(line('inline answer removed', c.inlineAnswerRemoved));
|
|
66
|
+
out.push(line('inline context removed', c.inlineContextRemoved));
|
|
67
|
+
out.push(line('forwarded content discarded', c.forwardedDiscarded));
|
|
68
|
+
out.push(line('only a footer retained', c.onlyFooterRetained));
|
|
69
|
+
out.push(line('empty extraction from non empty message', c.emptyExtraction));
|
|
70
|
+
out.push(line('mostly unknown content hidden', c.unknownHidden));
|
|
71
|
+
out.push('');
|
|
72
|
+
if (report.byGroup.length > 1) {
|
|
73
|
+
out.push('BY GROUP');
|
|
74
|
+
out.push(' group blocks agreement new content retained');
|
|
75
|
+
for (const group of report.byGroup.slice(0, 15)) {
|
|
76
|
+
out.push(` ${group.group.padEnd(24)} ${String(group.blocks).padStart(6)} ${pct(group.agreement).padStart(10)} ${pct(group.newContentCharRecall).padStart(21)}`);
|
|
77
|
+
}
|
|
78
|
+
out.push('');
|
|
79
|
+
}
|
|
80
|
+
return out.join('\n');
|
|
81
|
+
}
|
|
82
|
+
async function evaluateCommand(args) {
|
|
83
|
+
const dbPath = (0, args_1.flagString)(args, 'db', 'data/corpus.sqlite');
|
|
84
|
+
if (!node_fs_1.default.existsSync(dbPath)) {
|
|
85
|
+
process.stderr.write(`no corpus database at ${dbPath}\n`);
|
|
86
|
+
return 2;
|
|
87
|
+
}
|
|
88
|
+
const model = (0, args_1.flagString)(args, 'model', 'gpt-5.6-sol');
|
|
89
|
+
const useHistory = (0, args_1.flagBool)(args, 'history', false);
|
|
90
|
+
const groupBy = (0, args_1.flagString)(args, 'group-by', 'client');
|
|
91
|
+
const limit = (0, args_1.flagNumber)(args, 'limit', 0);
|
|
92
|
+
const store = new store_1.CorpusStore(dbPath);
|
|
93
|
+
const root = store.queryOne('SELECT root FROM runs ORDER BY id DESC LIMIT 1')?.root;
|
|
94
|
+
if (!root) {
|
|
95
|
+
process.stderr.write('no completed scan run found\n');
|
|
96
|
+
store.close();
|
|
97
|
+
return 2;
|
|
98
|
+
}
|
|
99
|
+
// Latest annotation per (path, block) for the chosen model, so re-annotated messages do not
|
|
100
|
+
// count twice.
|
|
101
|
+
const reference = store.query(`SELECT a.path, a.block_index, a.label, a.char_count, m.client, m.lang, m.reply_style
|
|
102
|
+
FROM annotations a
|
|
103
|
+
JOIN annotation_runs r ON r.id = a.run_id
|
|
104
|
+
JOIN messages m ON m.path = a.path
|
|
105
|
+
WHERE r.model = ? AND a.source = 'llm'
|
|
106
|
+
AND a.id = (SELECT MAX(a2.id) FROM annotations a2
|
|
107
|
+
JOIN annotation_runs r2 ON r2.id = a2.run_id
|
|
108
|
+
WHERE a2.path = a.path AND a2.block_index = a.block_index AND r2.model = r.model)
|
|
109
|
+
ORDER BY a.path, a.block_index`, model);
|
|
110
|
+
if (!reference.length) {
|
|
111
|
+
process.stderr.write(`no annotations found for model ${model}. Run "annotate" first.\n`);
|
|
112
|
+
store.close();
|
|
113
|
+
return 2;
|
|
114
|
+
}
|
|
115
|
+
const byPath = new Map();
|
|
116
|
+
for (const row of reference) {
|
|
117
|
+
const list = byPath.get(row.path);
|
|
118
|
+
if (list) {
|
|
119
|
+
list.push(row);
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
byPath.set(row.path, [row]);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
const paths = [...byPath.keys()].slice(0, limit || undefined);
|
|
126
|
+
const resolver = useHistory ? (0, thread_index_1.corpusThreadResolver)(store, root) : null;
|
|
127
|
+
process.stderr.write(`evaluating ${paths.length} messages against ${model}${useHistory ? ', with thread history' : ''}\n`);
|
|
128
|
+
const rows = [];
|
|
129
|
+
let failures = 0;
|
|
130
|
+
let withHistory = 0;
|
|
131
|
+
for (const relPath of paths) {
|
|
132
|
+
const references = byPath.get(relPath);
|
|
133
|
+
let raw;
|
|
134
|
+
try {
|
|
135
|
+
raw = node_fs_1.default.readFileSync(node_path_1.default.join(root, relPath));
|
|
136
|
+
}
|
|
137
|
+
catch {
|
|
138
|
+
failures++;
|
|
139
|
+
continue;
|
|
140
|
+
}
|
|
141
|
+
let historyDocuments;
|
|
142
|
+
if (resolver) {
|
|
143
|
+
try {
|
|
144
|
+
const message = await (0, parse_1.parseMessage)(raw);
|
|
145
|
+
historyDocuments = await resolver.resolve(message.headers);
|
|
146
|
+
if (historyDocuments.length) {
|
|
147
|
+
withHistory++;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
catch {
|
|
151
|
+
historyDocuments = undefined;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
let result;
|
|
155
|
+
try {
|
|
156
|
+
result = await (0, index_1.extract)(raw, historyDocuments ? { historyDocuments } : {});
|
|
157
|
+
}
|
|
158
|
+
catch {
|
|
159
|
+
failures++;
|
|
160
|
+
continue;
|
|
161
|
+
}
|
|
162
|
+
// Map every reference block to the prediction covering it. Segments merge adjacent blocks,
|
|
163
|
+
// so a block is matched by its index falling inside a segment's block range.
|
|
164
|
+
const predictions = new Map();
|
|
165
|
+
for (const segment of [...result.segments, ...result.hiddenSegments]) {
|
|
166
|
+
predictions.set(segment.source.blockIndex, { label: segment.type, hidden: segment.visibility === 'hide' });
|
|
167
|
+
}
|
|
168
|
+
// Segments start at a block index and run to the next one, so fill forward.
|
|
169
|
+
const ordered = [...predictions.keys()].sort((a, b) => a - b);
|
|
170
|
+
const lookup = (index) => {
|
|
171
|
+
let best = null;
|
|
172
|
+
for (const start of ordered) {
|
|
173
|
+
if (start <= index) {
|
|
174
|
+
best = start;
|
|
175
|
+
}
|
|
176
|
+
else {
|
|
177
|
+
break;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
return best === null ? null : (predictions.get(best) ?? null);
|
|
181
|
+
};
|
|
182
|
+
const first = references[0];
|
|
183
|
+
const group = groupBy === 'lang' ? (first?.lang ?? 'unknown') : groupBy === 'reply-style' ? (first?.reply_style ?? 'unknown') : (first?.client ?? 'unknown');
|
|
184
|
+
for (const item of references) {
|
|
185
|
+
const prediction = lookup(item.block_index);
|
|
186
|
+
rows.push({
|
|
187
|
+
path: relPath,
|
|
188
|
+
blockIndex: item.block_index,
|
|
189
|
+
charCount: item.char_count,
|
|
190
|
+
reference: item.label,
|
|
191
|
+
// A block with no covering segment was dropped as empty, which is equivalent to
|
|
192
|
+
// being shown as nothing. Treat it as UNKNOWN and visible rather than silently
|
|
193
|
+
// excluding it from the score.
|
|
194
|
+
predicted: prediction?.label ?? 'UNKNOWN',
|
|
195
|
+
hidden: prediction?.hidden ?? false,
|
|
196
|
+
group
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
store.close();
|
|
201
|
+
if (failures) {
|
|
202
|
+
process.stderr.write(`${failures} message(s) could not be evaluated\n`);
|
|
203
|
+
}
|
|
204
|
+
if (resolver) {
|
|
205
|
+
process.stderr.write(`thread history available for ${withHistory} of ${paths.length} messages\n`);
|
|
206
|
+
}
|
|
207
|
+
const report = (0, metrics_1.evaluate)(rows);
|
|
208
|
+
if ((0, args_1.flagBool)(args, 'json', false)) {
|
|
209
|
+
process.stdout.write(`${JSON.stringify({ ...report, confusion: Object.fromEntries(report.confusion) }, null, 2)}\n`);
|
|
210
|
+
return 0;
|
|
211
|
+
}
|
|
212
|
+
process.stdout.write(`${renderReport(report, `EVALUATION vs ${model}${useHistory ? ' (with history)' : ' (no history)'}`)}\n`);
|
|
213
|
+
return 0;
|
|
214
|
+
}
|
|
215
|
+
//# sourceMappingURL=evaluate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"evaluate.js","sourceRoot":"","sources":["../../src/cli/evaluate.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `email-content extract` subcommand.
|
|
3
|
+
*
|
|
4
|
+
* Human readable output shows the classification, the confidence and the reasons, so that a
|
|
5
|
+
* surprising decision can be understood without a debugger. Message content is printed here, which
|
|
6
|
+
* is fine and necessary: the operator asked for this specific message.
|
|
7
|
+
*/
|
|
8
|
+
import { type ParsedArgs } from './args';
|
|
9
|
+
export declare function extractCommand(args: ParsedArgs): Promise<number>;
|
|
10
|
+
//# sourceMappingURL=extract.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extract.d.ts","sourceRoot":"","sources":["../../src/cli/extract.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAMH,OAAO,EAA4C,KAAK,UAAU,EAAE,MAAM,QAAQ,CAAC;AAqBnF,wBAAsB,cAAc,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAiFtE"}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* `email-content extract` subcommand.
|
|
4
|
+
*
|
|
5
|
+
* Human readable output shows the classification, the confidence and the reasons, so that a
|
|
6
|
+
* surprising decision can be understood without a debugger. Message content is printed here, which
|
|
7
|
+
* is fine and necessary: the operator asked for this specific message.
|
|
8
|
+
*/
|
|
9
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
12
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
13
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
14
|
+
}
|
|
15
|
+
Object.defineProperty(o, k2, desc);
|
|
16
|
+
}) : (function(o, m, k, k2) {
|
|
17
|
+
if (k2 === undefined) k2 = k;
|
|
18
|
+
o[k2] = m[k];
|
|
19
|
+
}));
|
|
20
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
21
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
22
|
+
}) : function(o, v) {
|
|
23
|
+
o["default"] = v;
|
|
24
|
+
});
|
|
25
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
26
|
+
var ownKeys = function(o) {
|
|
27
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
28
|
+
var ar = [];
|
|
29
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
30
|
+
return ar;
|
|
31
|
+
};
|
|
32
|
+
return ownKeys(o);
|
|
33
|
+
};
|
|
34
|
+
return function (mod) {
|
|
35
|
+
if (mod && mod.__esModule) return mod;
|
|
36
|
+
var result = {};
|
|
37
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
38
|
+
__setModuleDefault(result, mod);
|
|
39
|
+
return result;
|
|
40
|
+
};
|
|
41
|
+
})();
|
|
42
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
43
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
44
|
+
};
|
|
45
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
46
|
+
exports.extractCommand = extractCommand;
|
|
47
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
|
48
|
+
const index_1 = require("../index");
|
|
49
|
+
const args_1 = require("./args");
|
|
50
|
+
const LABEL_WIDTH = 18;
|
|
51
|
+
function truncate(text, limit) {
|
|
52
|
+
const collapsed = text.replace(/\s+/g, ' ').trim();
|
|
53
|
+
return collapsed.length > limit ? `${collapsed.slice(0, limit - 1)}…` : collapsed;
|
|
54
|
+
}
|
|
55
|
+
function renderSegment(segment, index, full) {
|
|
56
|
+
const head = `${String(index).padStart(2)}. ${segment.type.padEnd(LABEL_WIDTH)} ${segment.confidence.toFixed(2)} ${segment.visibility.padEnd(8)} part ${segment.source.mimePart} [${segment.source.start}..${segment.source.end}]`;
|
|
57
|
+
const reasons = ` reasons: ${segment.reasons.join(', ') || 'none'}`;
|
|
58
|
+
const body = full
|
|
59
|
+
? segment.text
|
|
60
|
+
.split('\n')
|
|
61
|
+
.map(line => ` | ${line}`)
|
|
62
|
+
.join('\n')
|
|
63
|
+
: ` | ${truncate(segment.text, 100)}`;
|
|
64
|
+
return `${head}\n${reasons}\n${body}`;
|
|
65
|
+
}
|
|
66
|
+
async function extractCommand(args) {
|
|
67
|
+
const file = args.positional[0];
|
|
68
|
+
if (!file) {
|
|
69
|
+
process.stderr.write('usage: email-content extract <message.eml> [--json] [--explain] [--full]\n');
|
|
70
|
+
return 2;
|
|
71
|
+
}
|
|
72
|
+
if (!node_fs_1.default.existsSync(file)) {
|
|
73
|
+
process.stderr.write(`file not found: ${file}\n`);
|
|
74
|
+
return 2;
|
|
75
|
+
}
|
|
76
|
+
const explain = (0, args_1.flagBool)(args, 'explain', false);
|
|
77
|
+
const raw = node_fs_1.default.readFileSync(file);
|
|
78
|
+
// Stage 5 evidence, when the caller can point at earlier messages. Either a corpus database,
|
|
79
|
+
// which resolves the thread by Message-ID, or a folder of .eml files to index.
|
|
80
|
+
let historyDocuments = [];
|
|
81
|
+
const historySource = (0, args_1.flagOptionalString)(args, 'history');
|
|
82
|
+
if (historySource) {
|
|
83
|
+
const { parseMessage } = await Promise.resolve().then(() => __importStar(require('../mime/parse')));
|
|
84
|
+
const message = await parseMessage(raw);
|
|
85
|
+
const isDatabase = /\.sqlite$/i.test(historySource);
|
|
86
|
+
if (isDatabase) {
|
|
87
|
+
const { CorpusStore } = await Promise.resolve().then(() => __importStar(require('../corpus/store')));
|
|
88
|
+
const { corpusThreadResolver } = await Promise.resolve().then(() => __importStar(require('../corpus/thread-index')));
|
|
89
|
+
const store = new CorpusStore(historySource);
|
|
90
|
+
const root = store.queryOne('SELECT root FROM runs ORDER BY id DESC LIMIT 1')?.root;
|
|
91
|
+
if (root) {
|
|
92
|
+
historyDocuments = await corpusThreadResolver(store, root).resolve(message.headers);
|
|
93
|
+
}
|
|
94
|
+
store.close();
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
const { folderThreadResolver } = await Promise.resolve().then(() => __importStar(require('../corpus/thread-index')));
|
|
98
|
+
historyDocuments = await folderThreadResolver(historySource).resolve(message.headers);
|
|
99
|
+
}
|
|
100
|
+
process.stderr.write(`history: resolved ${historyDocuments.length} earlier message(s)\n`);
|
|
101
|
+
}
|
|
102
|
+
const result = await (0, index_1.extract)(raw, {
|
|
103
|
+
explain,
|
|
104
|
+
historyDocuments,
|
|
105
|
+
parse: { maxTextPartBytes: (0, args_1.flagNumber)(args, 'max-text-kb', 1024) * 1024 }
|
|
106
|
+
});
|
|
107
|
+
if ((0, args_1.flagBool)(args, 'json', false)) {
|
|
108
|
+
process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
|
|
109
|
+
return 0;
|
|
110
|
+
}
|
|
111
|
+
const full = (0, args_1.flagBool)(args, 'full', false);
|
|
112
|
+
const out = [];
|
|
113
|
+
out.push(`primary representation: ${result.primaryRepresentation}`);
|
|
114
|
+
out.push(`overall confidence: ${result.overallConfidence.toFixed(3)}`);
|
|
115
|
+
out.push(`history used: ${result.historyUsed}`);
|
|
116
|
+
if (result.warnings.length) {
|
|
117
|
+
out.push(`warnings: ${result.warnings.map(warning => warning.code).join(', ')}`);
|
|
118
|
+
}
|
|
119
|
+
out.push('');
|
|
120
|
+
out.push(`VISIBLE (${result.segments.length})`);
|
|
121
|
+
result.segments.forEach((segment, index) => out.push(renderSegment(segment, index, full)));
|
|
122
|
+
if (result.hiddenSegments.length) {
|
|
123
|
+
out.push('', `HIDDEN (${result.hiddenSegments.length}, retained and recoverable)`);
|
|
124
|
+
result.hiddenSegments.forEach((segment, index) => out.push(renderSegment(segment, index, full)));
|
|
125
|
+
}
|
|
126
|
+
if (explain && result.diagnostics) {
|
|
127
|
+
out.push('', `DIAGNOSTICS structure=${result.diagnostics.structure} part=${result.diagnostics.primaryPart}`);
|
|
128
|
+
for (const block of result.diagnostics.blocks) {
|
|
129
|
+
const evidence = block.evidence.map(item => `${item.id}@${item.strength}`).join(' ') || 'none';
|
|
130
|
+
out.push(` #${String(block.index).padStart(2)} ${block.kind.padEnd(20)} -> ${block.label.padEnd(LABEL_WIDTH)} ${block.confidence.toFixed(2)}`);
|
|
131
|
+
out.push(` evidence: ${evidence}`);
|
|
132
|
+
out.push(` reasons: ${block.reasons.join(', ')}`);
|
|
133
|
+
out.push(` text: ${truncate(block.preview, 100)}`);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
process.stdout.write(`${out.join('\n')}\n`);
|
|
137
|
+
return 0;
|
|
138
|
+
}
|
|
139
|
+
//# sourceMappingURL=extract.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extract.js","sourceRoot":"","sources":["../../src/cli/extract.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2BH,wCAiFC;AA1GD,sDAAyB;AACzB,oCAAmC;AAGnC,iCAAmF;AAEnF,MAAM,WAAW,GAAG,EAAE,CAAC;AAEvB,SAAS,QAAQ,CAAC,IAAY,EAAE,KAAa;IACzC,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IACnD,OAAO,SAAS,CAAC,MAAM,GAAG,KAAK,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC;AACtF,CAAC;AAED,SAAS,aAAa,CAAC,OAAgB,EAAE,KAAa,EAAE,IAAa;IACjE,MAAM,IAAI,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,OAAO,CAAC,MAAM,CAAC,QAAQ,KAAK,OAAO,CAAC,MAAM,CAAC,KAAK,KAAK,OAAO,CAAC,MAAM,CAAC,GAAG,GAAG,CAAC;IACpO,MAAM,OAAO,GAAG,gBAAgB,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,MAAM,EAAE,CAAC;IACvE,MAAM,IAAI,GAAG,IAAI;QACb,CAAC,CAAC,OAAO,CAAC,IAAI;aACP,KAAK,CAAC,IAAI,CAAC;aACX,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,SAAS,IAAI,EAAE,CAAC;aAC5B,IAAI,CAAC,IAAI,CAAC;QACjB,CAAC,CAAC,SAAS,QAAQ,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,EAAE,CAAC;IAC7C,OAAO,GAAG,IAAI,KAAK,OAAO,KAAK,IAAI,EAAE,CAAC;AAC1C,CAAC;AAEM,KAAK,UAAU,cAAc,CAAC,IAAgB;IACjD,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;IAChC,IAAI,CAAC,IAAI,EAAE,CAAC;QACR,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,4EAA4E,CAAC,CAAC;QACnG,OAAO,CAAC,CAAC;IACb,CAAC;IACD,IAAI,CAAC,iBAAE,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACvB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,mBAAmB,IAAI,IAAI,CAAC,CAAC;QAClD,OAAO,CAAC,CAAC;IACb,CAAC;IAED,MAAM,OAAO,GAAG,IAAA,eAAQ,EAAC,IAAI,EAAE,SAAS,EAAE,KAAK,CAAC,CAAC;IACjD,MAAM,GAAG,GAAG,iBAAE,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;IAElC,6FAA6F;IAC7F,+EAA+E;IAC/E,IAAI,gBAAgB,GAAsB,EAAE,CAAC;IAC7C,MAAM,aAAa,GAAG,IAAA,yBAAkB,EAAC,IAAI,EAAE,SAAS,CAAC,CAAC;IAC1D,IAAI,aAAa,EAAE,CAAC;QAChB,MAAM,EAAE,YAAY,EAAE,GAAG,wDAAa,eAAe,GAAC,CAAC;QACvD,MAAM,OAAO,GAAG,MAAM,YAAY,CAAC,GAAG,CAAC,CAAC;QACxC,MAAM,UAAU,GAAG,YAAY,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QACpD,IAAI,UAAU,EAAE,CAAC;YACb,MAAM,EAAE,WAAW,EAAE,GAAG,wDAAa,iBAAiB,GAAC,CAAC;YACxD,MAAM,EAAE,oBAAoB,EAAE,GAAG,wDAAa,wBAAwB,GAAC,CAAC;YACxE,MAAM,KAAK,GAAG,IAAI,WAAW,CAAC,aAAa,CAAC,CAAC;YAC7C,MAAM,IAAI,GAAG,KAAK,CAAC,QAAQ,CAAmB,gDAAgD,CAAC,EAAE,IAAI,CAAC;YACtG,IAAI,IAAI,EAAE,CAAC;gBACP,gBAAgB,GAAG,MAAM,oBAAoB,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;YACxF,CAAC;YACD,KAAK,CAAC,KAAK,EAAE,CAAC;QAClB,CAAC;aAAM,CAAC;YACJ,MAAM,EAAE,oBAAoB,EAAE,GAAG,wDAAa,wBAAwB,GAAC,CAAC;YACxE,gBAAgB,GAAG,MAAM,oBAAoB,CAAC,aAAa,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QAC1F,CAAC;QACD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,qBAAqB,gBAAgB,CAAC,MAAM,uBAAuB,CAAC,CAAC;IAC9F,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,IAAA,eAAO,EAAC,GAAG,EAAE;QAC9B,OAAO;QACP,gBAAgB;QAChB,KAAK,EAAE,EAAE,gBAAgB,EAAE,IAAA,iBAAU,EAAC,IAAI,EAAE,aAAa,EAAE,IAAI,CAAC,GAAG,IAAI,EAAE;KAC5E,CAAC,CAAC;IAEH,IAAI,IAAA,eAAQ,EAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,CAAC;QAChC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;QAC7D,OAAO,CAAC,CAAC;IACb,CAAC;IAED,MAAM,IAAI,GAAG,IAAA,eAAQ,EAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;IAC3C,MAAM,GAAG,GAAa,EAAE,CAAC;IAEzB,GAAG,CAAC,IAAI,CAAC,2BAA2B,MAAM,CAAC,qBAAqB,EAAE,CAAC,CAAC;IACpE,GAAG,CAAC,IAAI,CAAC,uBAAuB,MAAM,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IACvE,GAAG,CAAC,IAAI,CAAC,iBAAiB,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC;IAChD,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC;QACzB,GAAG,CAAC,IAAI,CAAC,aAAa,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACrF,CAAC;IACD,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAEb,GAAG,CAAC,IAAI,CAAC,YAAY,MAAM,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC;IAChD,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,aAAa,CAAC,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC;IAE3F,IAAI,MAAM,CAAC,cAAc,CAAC,MAAM,EAAE,CAAC;QAC/B,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,WAAW,MAAM,CAAC,cAAc,CAAC,MAAM,6BAA6B,CAAC,CAAC;QACnF,MAAM,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,aAAa,CAAC,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC;IACrG,CAAC;IAED,IAAI,OAAO,IAAI,MAAM,CAAC,WAAW,EAAE,CAAC;QAChC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,0BAA0B,MAAM,CAAC,WAAW,CAAC,SAAS,SAAS,MAAM,CAAC,WAAW,CAAC,WAAW,EAAE,CAAC,CAAC;QAC9G,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,WAAW,CAAC,MAAM,EAAE,CAAC;YAC5C,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,EAAE,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,MAAM,CAAC;YAC/F,GAAG,CAAC,IAAI,CAAC,MAAM,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,OAAO,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,KAAK,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YAChJ,GAAG,CAAC,IAAI,CAAC,mBAAmB,QAAQ,EAAE,CAAC,CAAC;YACxC,GAAG,CAAC,IAAI,CAAC,mBAAmB,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACxD,GAAG,CAAC,IAAI,CAAC,mBAAmB,QAAQ,CAAC,KAAK,CAAC,OAAO,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;QAChE,CAAC;IACL,CAAC;IAED,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC5C,OAAO,CAAC,CAAC;AACb,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../../src/cli/main.ts"],"names":[],"mappings":";AACA;;;;;GAKG"}
|
package/dist/cli/main.js
ADDED
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
/**
|
|
4
|
+
* email-content command line entry point.
|
|
5
|
+
*
|
|
6
|
+
* Commands are dispatched lazily so that, for example, `extract` does not pay for loading the
|
|
7
|
+
* corpus database layer.
|
|
8
|
+
*/
|
|
9
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
12
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
13
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
14
|
+
}
|
|
15
|
+
Object.defineProperty(o, k2, desc);
|
|
16
|
+
}) : (function(o, m, k, k2) {
|
|
17
|
+
if (k2 === undefined) k2 = k;
|
|
18
|
+
o[k2] = m[k];
|
|
19
|
+
}));
|
|
20
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
21
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
22
|
+
}) : function(o, v) {
|
|
23
|
+
o["default"] = v;
|
|
24
|
+
});
|
|
25
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
26
|
+
var ownKeys = function(o) {
|
|
27
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
28
|
+
var ar = [];
|
|
29
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
30
|
+
return ar;
|
|
31
|
+
};
|
|
32
|
+
return ownKeys(o);
|
|
33
|
+
};
|
|
34
|
+
return function (mod) {
|
|
35
|
+
if (mod && mod.__esModule) return mod;
|
|
36
|
+
var result = {};
|
|
37
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
38
|
+
__setModuleDefault(result, mod);
|
|
39
|
+
return result;
|
|
40
|
+
};
|
|
41
|
+
})();
|
|
42
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
43
|
+
const types_1 = require("../types");
|
|
44
|
+
const args_1 = require("./args");
|
|
45
|
+
const USAGE = `email-content <command> [options]
|
|
46
|
+
|
|
47
|
+
Commands:
|
|
48
|
+
corpus scan <folder> Scan a folder of .eml files into the corpus database
|
|
49
|
+
--db <path> Database path (default data/corpus.sqlite)
|
|
50
|
+
--sample <n> Deterministic sample of n files instead of the whole corpus
|
|
51
|
+
--seed <string> Sampling seed (default "default")
|
|
52
|
+
--concurrency <n> Worker threads (default: cores minus two)
|
|
53
|
+
--no-resume Re-process files already recorded
|
|
54
|
+
--max-file-mb <n> Skip files larger than this (default 32)
|
|
55
|
+
--timeout <ms> Per file timeout (default 30000)
|
|
56
|
+
|
|
57
|
+
corpus stats Print aggregate statistics
|
|
58
|
+
--db <path> Database path
|
|
59
|
+
--json Emit JSON instead of Markdown
|
|
60
|
+
--out <path> Write the Markdown report to a file
|
|
61
|
+
|
|
62
|
+
corpus threads Summarise in-corpus thread parent resolution
|
|
63
|
+
|
|
64
|
+
extract <message.eml> Classify one message into segments
|
|
65
|
+
--json Emit the full structured result
|
|
66
|
+
--explain Show per block evidence, features and reasons
|
|
67
|
+
--full Print complete segment text instead of a preview
|
|
68
|
+
--history <path> Corpus .sqlite or folder of .eml files, to resolve thread history
|
|
69
|
+
|
|
70
|
+
benchmark Measure throughput and catastrophic error rates
|
|
71
|
+
--db <path> Corpus database
|
|
72
|
+
--sample <n> Messages to run (default 2000)
|
|
73
|
+
--traffic <class> human, ticketing, mailing-list, bulk, all (default human)
|
|
74
|
+
--replies false Include non replies
|
|
75
|
+
|
|
76
|
+
annotate Label blocks with an LLM instead of a human (sends content to OpenAI)
|
|
77
|
+
--model <id> Model id (default gpt-5.6-sol)
|
|
78
|
+
--sample <n> Messages to annotate (default 25)
|
|
79
|
+
--concurrency <n> Parallel requests (default 4)
|
|
80
|
+
--traffic <class> Traffic class to sample from (default human)
|
|
81
|
+
--seed <string> Deterministic selection seed
|
|
82
|
+
--dry-run Count blocks and cost without calling the API
|
|
83
|
+
--no-resume Re-annotate messages already done by this model
|
|
84
|
+
|
|
85
|
+
disagreements Review blocks where annotator and baseline disagree (prints content)
|
|
86
|
+
--direction <d> expensive, cheap, footers, all (default expensive)
|
|
87
|
+
--limit <n> Rows to show (default 20)
|
|
88
|
+
--run <id> Restrict to one annotation run
|
|
89
|
+
|
|
90
|
+
evaluate Score the extractor against an annotated reference set
|
|
91
|
+
--model <id> Reference annotations from this model (default gpt-5.6-sol)
|
|
92
|
+
--history Resolve thread history from the corpus while evaluating
|
|
93
|
+
--group-by <field> client, lang or reply-style (default client)
|
|
94
|
+
--json Emit the full report as JSON
|
|
95
|
+
|
|
96
|
+
version Print version information
|
|
97
|
+
|
|
98
|
+
Privacy: no command prints message bodies, subjects or addresses.
|
|
99
|
+
`;
|
|
100
|
+
async function main(argv) {
|
|
101
|
+
const args = (0, args_1.parseArgs)(argv);
|
|
102
|
+
const command = args.positional[0];
|
|
103
|
+
switch (command) {
|
|
104
|
+
case 'corpus': {
|
|
105
|
+
const { corpusCommand } = await Promise.resolve().then(() => __importStar(require('./corpus')));
|
|
106
|
+
return corpusCommand(args.positional[1], { ...args, positional: args.positional.slice(2) });
|
|
107
|
+
}
|
|
108
|
+
case 'extract': {
|
|
109
|
+
const { extractCommand } = await Promise.resolve().then(() => __importStar(require('./extract')));
|
|
110
|
+
return extractCommand({ ...args, positional: args.positional.slice(1) });
|
|
111
|
+
}
|
|
112
|
+
case 'benchmark': {
|
|
113
|
+
const { benchmarkCommand } = await Promise.resolve().then(() => __importStar(require('./benchmark')));
|
|
114
|
+
return benchmarkCommand({ ...args, positional: args.positional.slice(1) });
|
|
115
|
+
}
|
|
116
|
+
case 'annotate': {
|
|
117
|
+
const { annotateCommand } = await Promise.resolve().then(() => __importStar(require('./annotate')));
|
|
118
|
+
return annotateCommand({ ...args, positional: args.positional.slice(1) });
|
|
119
|
+
}
|
|
120
|
+
case 'disagreements': {
|
|
121
|
+
const { disagreementsCommand } = await Promise.resolve().then(() => __importStar(require('./disagreements')));
|
|
122
|
+
return disagreementsCommand({ ...args, positional: args.positional.slice(1) });
|
|
123
|
+
}
|
|
124
|
+
case 'evaluate': {
|
|
125
|
+
const { evaluateCommand } = await Promise.resolve().then(() => __importStar(require('./evaluate')));
|
|
126
|
+
return evaluateCommand({ ...args, positional: args.positional.slice(1) });
|
|
127
|
+
}
|
|
128
|
+
case 'version':
|
|
129
|
+
process.stdout.write(`extractor ${types_1.EXTRACTOR_VERSION}, processing ${types_1.PROCESSING_VERSION}, node ${process.version}\n`);
|
|
130
|
+
return 0;
|
|
131
|
+
case 'help':
|
|
132
|
+
case undefined:
|
|
133
|
+
process.stdout.write(USAGE);
|
|
134
|
+
return command === undefined ? 2 : 0;
|
|
135
|
+
default:
|
|
136
|
+
process.stderr.write(`unknown command: ${command}\n\n${USAGE}`);
|
|
137
|
+
return 2;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
main(process.argv.slice(2)).then(code => {
|
|
141
|
+
process.exitCode = code;
|
|
142
|
+
}, (err) => {
|
|
143
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
144
|
+
process.stderr.write(`error: ${message}\n`);
|
|
145
|
+
process.exitCode = 1;
|
|
146
|
+
});
|
|
147
|
+
//# sourceMappingURL=main.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"main.js","sourceRoot":"","sources":["../../src/cli/main.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Corpus feature extraction.
|
|
3
|
+
*
|
|
4
|
+
* Turns a parsed message into the flat, privacy safe record stored in the corpus database. The hard
|
|
5
|
+
* rule here is that nothing derived from body text, subjects or addresses may leave this function
|
|
6
|
+
* in readable form. Subjects and addresses become salted hashes, sender domains are kept because
|
|
7
|
+
* they are needed for stratification, and body text is reduced to counts, ratios and a SimHash.
|
|
8
|
+
*/
|
|
9
|
+
import { type ReplyStyle } from '../canonical/text';
|
|
10
|
+
import { type ClientId } from '../detect/client';
|
|
11
|
+
import { type TrafficClass } from '../detect/traffic';
|
|
12
|
+
import { type ParsedMessage } from '../mime/model';
|
|
13
|
+
import { type LanguageCode } from '../util/lang';
|
|
14
|
+
export type BodyKind = 'both' | 'plain-only' | 'html-only' | 'none';
|
|
15
|
+
export interface MessageRecord {
|
|
16
|
+
messageId: string | null;
|
|
17
|
+
inReplyTo: string | null;
|
|
18
|
+
referencesCount: number;
|
|
19
|
+
referencesRoot: string | null;
|
|
20
|
+
dateMs: number | null;
|
|
21
|
+
fromDomain: string | null;
|
|
22
|
+
fromHash: string | null;
|
|
23
|
+
subjectHash: string | null;
|
|
24
|
+
subjectPrefix: 'reply' | 'forward' | 'plain' | 'none';
|
|
25
|
+
subjectLength: number;
|
|
26
|
+
structure: string;
|
|
27
|
+
bodyKind: BodyKind;
|
|
28
|
+
charsets: string;
|
|
29
|
+
encodings: string;
|
|
30
|
+
partCount: number;
|
|
31
|
+
attachmentCount: number;
|
|
32
|
+
hasRfc822: boolean;
|
|
33
|
+
textChars: number;
|
|
34
|
+
htmlChars: number;
|
|
35
|
+
flowed: boolean;
|
|
36
|
+
client: ClientId;
|
|
37
|
+
clientSource: string;
|
|
38
|
+
traffic: TrafficClass;
|
|
39
|
+
trafficSignals: string;
|
|
40
|
+
isReply: boolean;
|
|
41
|
+
isForward: boolean;
|
|
42
|
+
quoteDepthMax: number;
|
|
43
|
+
quotedRatio: number;
|
|
44
|
+
replyStyle: ReplyStyle | 'unknown';
|
|
45
|
+
/** Detector ids that fired, comma separated. Ids only, never matched text. */
|
|
46
|
+
markers: string;
|
|
47
|
+
htmlHints: string;
|
|
48
|
+
blockquoteCount: number;
|
|
49
|
+
tableCount: number;
|
|
50
|
+
hasImage: boolean;
|
|
51
|
+
suspectMalformedHtml: boolean;
|
|
52
|
+
lang: LanguageCode;
|
|
53
|
+
langScore: number;
|
|
54
|
+
bodySimhash: string;
|
|
55
|
+
warnings: string;
|
|
56
|
+
/** True when plain and HTML disagree about whether the message contains quoted history. */
|
|
57
|
+
quoteMarkingDisagrees: boolean;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Build the corpus record for one parsed message.
|
|
61
|
+
*
|
|
62
|
+
* @param message parsed MIME structure
|
|
63
|
+
* @param salt per database salt for the privacy preserving hashes
|
|
64
|
+
*/
|
|
65
|
+
export declare function analyzeMessage(message: ParsedMessage, salt: string): MessageRecord;
|
|
66
|
+
//# sourceMappingURL=analyze.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analyze.d.ts","sourceRoot":"","sources":["../../src/corpus/analyze.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EAAoC,KAAK,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACtF,OAAO,EAAqB,KAAK,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAEpE,OAAO,EAAmB,KAAK,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACvE,OAAO,EAAiB,KAAK,aAAa,EAAE,MAAM,eAAe,CAAC;AAElE,OAAO,EAAoB,KAAK,YAAY,EAAE,MAAM,cAAc,CAAC;AAEnE,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG,YAAY,GAAG,WAAW,GAAG,MAAM,CAAC;AAEpE,MAAM,WAAW,aAAa;IAC1B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,eAAe,EAAE,MAAM,CAAC;IACxB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,aAAa,EAAE,OAAO,GAAG,SAAS,GAAG,OAAO,GAAG,MAAM,CAAC;IACtD,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,QAAQ,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,MAAM,CAAC;IACxB,SAAS,EAAE,OAAO,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,EAAE,QAAQ,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,YAAY,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;IACvB,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,OAAO,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,UAAU,GAAG,SAAS,CAAC;IACnC,8EAA8E;IAC9E,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,MAAM,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,OAAO,CAAC;IAClB,oBAAoB,EAAE,OAAO,CAAC;IAC9B,IAAI,EAAE,YAAY,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,2FAA2F;IAC3F,qBAAqB,EAAE,OAAO,CAAC;CAClC;AAoHD;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,aAAa,EAAE,IAAI,EAAE,MAAM,GAAG,aAAa,CA6FlF"}
|