@postalsys/email-content 0.1.7 → 0.1.9
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/README.md +65 -12
- package/dist/.tsbuildinfo +1 -1
- package/dist/analyze.d.ts +6 -0
- package/dist/analyze.d.ts.map +1 -1
- package/dist/analyze.js +27 -6
- package/dist/analyze.js.map +1 -1
- package/dist/annotate/agreement.d.ts +99 -0
- package/dist/annotate/agreement.d.ts.map +1 -0
- package/dist/annotate/agreement.js +126 -0
- package/dist/annotate/agreement.js.map +1 -0
- package/dist/annotate/client.d.ts +7 -19
- package/dist/annotate/client.d.ts.map +1 -1
- package/dist/annotate/client.js +28 -82
- package/dist/annotate/client.js.map +1 -1
- package/dist/annotate/http.d.ts +57 -0
- package/dist/annotate/http.d.ts.map +1 -0
- package/dist/annotate/http.js +99 -0
- package/dist/annotate/http.js.map +1 -0
- package/dist/annotate/llm.d.ts +17 -0
- package/dist/annotate/llm.d.ts.map +1 -1
- package/dist/annotate/llm.js +68 -36
- package/dist/annotate/llm.js.map +1 -1
- package/dist/annotate/probabilities.d.ts +48 -0
- package/dist/annotate/probabilities.d.ts.map +1 -0
- package/dist/annotate/probabilities.js +119 -0
- package/dist/annotate/probabilities.js.map +1 -0
- package/dist/annotate/providers.d.ts +26 -0
- package/dist/annotate/providers.d.ts.map +1 -0
- package/dist/annotate/providers.js +43 -0
- package/dist/annotate/providers.js.map +1 -0
- package/dist/annotate/store.d.ts +3 -0
- package/dist/annotate/store.d.ts.map +1 -1
- package/dist/annotate/store.js +3 -2
- package/dist/annotate/store.js.map +1 -1
- package/dist/annotate/typesafe-client.d.ts +64 -0
- package/dist/annotate/typesafe-client.d.ts.map +1 -0
- package/dist/annotate/typesafe-client.js +76 -0
- package/dist/annotate/typesafe-client.js.map +1 -0
- package/dist/annotate/typesafe-prompt.d.ts +64 -0
- package/dist/annotate/typesafe-prompt.d.ts.map +1 -0
- package/dist/annotate/typesafe-prompt.js +170 -0
- package/dist/annotate/typesafe-prompt.js.map +1 -0
- package/dist/canonical/text.d.ts +15 -3
- package/dist/canonical/text.d.ts.map +1 -1
- package/dist/canonical/text.js +20 -4
- package/dist/canonical/text.js.map +1 -1
- package/dist/classify/rules.d.ts +7 -0
- package/dist/classify/rules.d.ts.map +1 -1
- package/dist/classify/rules.js +67 -14
- package/dist/classify/rules.js.map +1 -1
- package/dist/cli/agreement.d.ts +27 -0
- package/dist/cli/agreement.d.ts.map +1 -0
- package/dist/cli/agreement.js +153 -0
- package/dist/cli/agreement.js.map +1 -0
- package/dist/cli/annotate.d.ts.map +1 -1
- package/dist/cli/annotate.js +28 -16
- package/dist/cli/annotate.js.map +1 -1
- package/dist/cli/audit.d.ts +12 -0
- package/dist/cli/audit.d.ts.map +1 -0
- package/dist/cli/audit.js +134 -0
- package/dist/cli/audit.js.map +1 -0
- package/dist/cli/disagreements.d.ts.map +1 -1
- package/dist/cli/disagreements.js +20 -3
- package/dist/cli/disagreements.js.map +1 -1
- package/dist/cli/evaluate.d.ts.map +1 -1
- package/dist/cli/evaluate.js +5 -70
- package/dist/cli/evaluate.js.map +1 -1
- package/dist/cli/main.js +28 -2
- package/dist/cli/main.js.map +1 -1
- package/dist/corpus/analyze.d.ts.map +1 -1
- package/dist/corpus/analyze.js +4 -5
- package/dist/corpus/analyze.js.map +1 -1
- package/dist/corpus/migrations/index.d.ts.map +1 -1
- package/dist/corpus/migrations/index.js +14 -0
- package/dist/corpus/migrations/index.js.map +1 -1
- package/dist/corpus/stats.d.ts +1 -0
- package/dist/corpus/stats.d.ts.map +1 -1
- package/dist/corpus/stats.js +1 -0
- package/dist/corpus/stats.js.map +1 -1
- package/dist/detect/patterns/forward-headers.json +24 -0
- package/dist/detect/patterns/html-clients.json +27 -0
- package/dist/detect/patterns/reply-headers.json +368 -0
- package/dist/detect/patterns.d.ts +19 -0
- package/dist/detect/patterns.d.ts.map +1 -1
- package/dist/detect/patterns.js +53 -25
- package/dist/detect/patterns.js.map +1 -1
- package/dist/detect/reply-header.d.ts.map +1 -1
- package/dist/detect/reply-header.js +12 -1
- package/dist/detect/reply-header.js.map +1 -1
- package/dist/detect/subject.d.ts +16 -0
- package/dist/detect/subject.d.ts.map +1 -0
- package/dist/detect/subject.js +22 -0
- package/dist/detect/subject.js.map +1 -0
- package/dist/eval/pattern-audit.d.ts +56 -0
- package/dist/eval/pattern-audit.d.ts.map +1 -0
- package/dist/eval/pattern-audit.js +111 -0
- package/dist/eval/pattern-audit.js.map +1 -0
- package/dist/eval/reference.d.ts +44 -0
- package/dist/eval/reference.d.ts.map +1 -0
- package/dist/eval/reference.js +87 -0
- package/dist/eval/reference.js.map +1 -0
- package/dist/index.d.ts +5 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -2
- package/dist/index.js.map +1 -1
- package/dist/mime/flowed.d.ts +14 -0
- package/dist/mime/flowed.d.ts.map +1 -0
- package/dist/mime/flowed.js +71 -0
- package/dist/mime/flowed.js.map +1 -0
- package/dist/mime/parse.js +2 -5
- package/dist/mime/parse.js.map +1 -1
- package/dist/segment/html-blocks.d.ts.map +1 -1
- package/dist/segment/html-blocks.js +11 -7
- package/dist/segment/html-blocks.js.map +1 -1
- package/dist/segment/text-blocks.d.ts.map +1 -1
- package/dist/segment/text-blocks.js +14 -3
- package/dist/segment/text-blocks.js.map +1 -1
- package/dist/types.d.ts +18 -3
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +2 -2
- package/package.json +8 -8
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minimal TypeSafe System One client.
|
|
3
|
+
*
|
|
4
|
+
* No SDK dependency, for the same reason as the OpenAI client: the package ships three runtime
|
|
5
|
+
* dependencies and none of them opens a socket. `@typesafe-ai/sdk` could only be a dev dependency,
|
|
6
|
+
* and `dist/cli` is part of the published tarball, so an installed `email-content annotate` would
|
|
7
|
+
* fail to load it. The surface used here is one POST.
|
|
8
|
+
*
|
|
9
|
+
* This is the second place in the codebase that sends message content off the machine, under the
|
|
10
|
+
* same terms as the first: only reachable from `email-content annotate`, opt in, fails closed
|
|
11
|
+
* without a key. See docs/threat-model.md, "Configured exception: LLM annotation".
|
|
12
|
+
*/
|
|
13
|
+
import { ApiError, type ApiConfig, type Usage } from './http';
|
|
14
|
+
/**
|
|
15
|
+
* Pinned rather than `jev-latest`: labels are stored with the model that produced them, and an
|
|
16
|
+
* alias that silently moves would put two models' output under one name.
|
|
17
|
+
*/
|
|
18
|
+
export declare const TYPESAFE_DEFAULT_MODEL = "jev-1.13.0";
|
|
19
|
+
export type TypeSafeConfig = ApiConfig;
|
|
20
|
+
export interface ChoiceQuestion {
|
|
21
|
+
type: 'choice';
|
|
22
|
+
instructions: string | Record<string, unknown>;
|
|
23
|
+
criteria: Record<string, string | Record<string, unknown> | null>;
|
|
24
|
+
}
|
|
25
|
+
export interface SystemOneRequest {
|
|
26
|
+
state: unknown;
|
|
27
|
+
questions: Record<string, ChoiceQuestion>;
|
|
28
|
+
}
|
|
29
|
+
/** One answer as returned. Fields are unvalidated until the annotator checks them. */
|
|
30
|
+
export interface ChoiceAnswer {
|
|
31
|
+
choice?: unknown;
|
|
32
|
+
probabilities?: unknown;
|
|
33
|
+
confidence?: unknown;
|
|
34
|
+
}
|
|
35
|
+
export interface SystemOneResponse {
|
|
36
|
+
answers: Record<string, ChoiceAnswer>;
|
|
37
|
+
}
|
|
38
|
+
/** The narrow surface the annotator depends on, so its validation can be tested without a network. */
|
|
39
|
+
export interface SystemOneClient {
|
|
40
|
+
readonly model: string;
|
|
41
|
+
ask(request: SystemOneRequest): Promise<SystemOneResponse>;
|
|
42
|
+
}
|
|
43
|
+
export declare class TypeSafeError extends ApiError {
|
|
44
|
+
constructor(message: string, status: number, retryable: boolean);
|
|
45
|
+
}
|
|
46
|
+
/** Load configuration from the environment, after process.loadEnvFile(). */
|
|
47
|
+
export declare function typeSafeConfigFromEnv(model: string, overrides?: Partial<TypeSafeConfig>): TypeSafeConfig;
|
|
48
|
+
export declare class TypeSafeClient implements SystemOneClient {
|
|
49
|
+
private readonly config;
|
|
50
|
+
/** Input tokens are reported as prompt tokens, output tokens as completion tokens. */
|
|
51
|
+
readonly usage: Usage;
|
|
52
|
+
constructor(config: TypeSafeConfig);
|
|
53
|
+
get model(): string;
|
|
54
|
+
/**
|
|
55
|
+
* Ask a set of questions about one state.
|
|
56
|
+
*
|
|
57
|
+
* Retries on rate limits (429), overload (529) and other server errors. Anything else, a 422
|
|
58
|
+
* validation failure in particular, is a bug in the request and is not retried. Error messages
|
|
59
|
+
* carry the status only, never the response body: a validation error may echo the state back,
|
|
60
|
+
* and the state is private mail.
|
|
61
|
+
*/
|
|
62
|
+
ask(request: SystemOneRequest): Promise<SystemOneResponse>;
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=typesafe-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"typesafe-client.d.ts","sourceRoot":"","sources":["../../src/annotate/typesafe-client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,QAAQ,EAA8B,KAAK,SAAS,EAAE,KAAK,KAAK,EAAE,MAAM,QAAQ,CAAC;AAE1F;;;GAGG;AACH,eAAO,MAAM,sBAAsB,eAAe,CAAC;AAEnD,MAAM,MAAM,cAAc,GAAG,SAAS,CAAC;AAEvC,MAAM,WAAW,cAAc;IAC3B,IAAI,EAAE,QAAQ,CAAC;IACf,YAAY,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/C,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC,CAAC;CACrE;AAED,MAAM,WAAW,gBAAgB;IAC7B,KAAK,EAAE,OAAO,CAAC;IACf,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;CAC7C;AAED,sFAAsF;AACtF,MAAM,WAAW,YAAY;IACzB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,UAAU,CAAC,EAAE,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,iBAAiB;IAC9B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;CACzC;AAED,sGAAsG;AACtG,MAAM,WAAW,eAAe;IAC5B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,GAAG,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;CAC9D;AAED,qBAAa,aAAc,SAAQ,QAAQ;gBAC3B,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO;CAIlE;AAED,4EAA4E;AAC5E,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,GAAE,OAAO,CAAC,cAAc,CAAM,GAAG,cAAc,CAE5G;AAED,qBAAa,cAAe,YAAW,eAAe;IAClD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAiB;IACxC,sFAAsF;IACtF,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAyE;gBAElF,MAAM,EAAE,cAAc;IAIlC,IAAI,KAAK,IAAI,MAAM,CAElB;IAED;;;;;;;OAOG;IACG,GAAG,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,iBAAiB,CAAC;CAwBnE"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Minimal TypeSafe System One client.
|
|
4
|
+
*
|
|
5
|
+
* No SDK dependency, for the same reason as the OpenAI client: the package ships three runtime
|
|
6
|
+
* dependencies and none of them opens a socket. `@typesafe-ai/sdk` could only be a dev dependency,
|
|
7
|
+
* and `dist/cli` is part of the published tarball, so an installed `email-content annotate` would
|
|
8
|
+
* fail to load it. The surface used here is one POST.
|
|
9
|
+
*
|
|
10
|
+
* This is the second place in the codebase that sends message content off the machine, under the
|
|
11
|
+
* same terms as the first: only reachable from `email-content annotate`, opt in, fails closed
|
|
12
|
+
* without a key. See docs/threat-model.md, "Configured exception: LLM annotation".
|
|
13
|
+
*/
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.TypeSafeClient = exports.TypeSafeError = exports.TYPESAFE_DEFAULT_MODEL = void 0;
|
|
16
|
+
exports.typeSafeConfigFromEnv = typeSafeConfigFromEnv;
|
|
17
|
+
const http_1 = require("./http");
|
|
18
|
+
/**
|
|
19
|
+
* Pinned rather than `jev-latest`: labels are stored with the model that produced them, and an
|
|
20
|
+
* alias that silently moves would put two models' output under one name.
|
|
21
|
+
*/
|
|
22
|
+
exports.TYPESAFE_DEFAULT_MODEL = 'jev-1.13.0';
|
|
23
|
+
class TypeSafeError extends http_1.ApiError {
|
|
24
|
+
constructor(message, status, retryable) {
|
|
25
|
+
super(message, status, retryable);
|
|
26
|
+
this.name = 'TypeSafeError';
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
exports.TypeSafeError = TypeSafeError;
|
|
30
|
+
/** Load configuration from the environment, after process.loadEnvFile(). */
|
|
31
|
+
function typeSafeConfigFromEnv(model, overrides = {}) {
|
|
32
|
+
return (0, http_1.apiConfigFromEnv)({ keyVar: 'TYPESAFE_API_KEY', urlVar: 'TYPESAFE_BASE_URL', defaultUrl: 'https://api.typesafe.ai/v1' }, model, overrides);
|
|
33
|
+
}
|
|
34
|
+
class TypeSafeClient {
|
|
35
|
+
config;
|
|
36
|
+
/** Input tokens are reported as prompt tokens, output tokens as completion tokens. */
|
|
37
|
+
usage = { promptTokens: 0, completionTokens: 0, totalTokens: 0, requests: 0 };
|
|
38
|
+
constructor(config) {
|
|
39
|
+
this.config = config;
|
|
40
|
+
}
|
|
41
|
+
get model() {
|
|
42
|
+
return this.config.model;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Ask a set of questions about one state.
|
|
46
|
+
*
|
|
47
|
+
* Retries on rate limits (429), overload (529) and other server errors. Anything else, a 422
|
|
48
|
+
* validation failure in particular, is a bug in the request and is not retried. Error messages
|
|
49
|
+
* carry the status only, never the response body: a validation error may echo the state back,
|
|
50
|
+
* and the state is private mail.
|
|
51
|
+
*/
|
|
52
|
+
async ask(request) {
|
|
53
|
+
return (0, http_1.postJson)({
|
|
54
|
+
url: `${this.config.baseUrl}/systemone`,
|
|
55
|
+
apiKey: this.config.apiKey,
|
|
56
|
+
policy: this.config,
|
|
57
|
+
payload: { model: this.config.model, state: request.state, questions: request.questions },
|
|
58
|
+
httpError: status => new TypeSafeError(`TypeSafe HTTP ${status}`, status, status === 429 || status >= 500),
|
|
59
|
+
parse: raw => {
|
|
60
|
+
const body = raw;
|
|
61
|
+
if (!body || typeof body.answers !== 'object' || body.answers === null) {
|
|
62
|
+
throw new TypeSafeError('TypeSafe response has no answers', 0, false);
|
|
63
|
+
}
|
|
64
|
+
const input = typeof body.usage?.input_tokens === 'number' ? body.usage.input_tokens : 0;
|
|
65
|
+
const output = typeof body.usage?.output_tokens === 'number' ? body.usage.output_tokens : 0;
|
|
66
|
+
this.usage.requests++;
|
|
67
|
+
this.usage.promptTokens += input;
|
|
68
|
+
this.usage.completionTokens += output;
|
|
69
|
+
this.usage.totalTokens += input + output;
|
|
70
|
+
return { answers: body.answers };
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
exports.TypeSafeClient = TypeSafeClient;
|
|
76
|
+
//# sourceMappingURL=typesafe-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"typesafe-client.js","sourceRoot":"","sources":["../../src/annotate/typesafe-client.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;GAWG;;;AAgDH,sDAEC;AAhDD,iCAA0F;AAE1F;;;GAGG;AACU,QAAA,sBAAsB,GAAG,YAAY,CAAC;AAgCnD,MAAa,aAAc,SAAQ,eAAQ;IACvC,YAAY,OAAe,EAAE,MAAc,EAAE,SAAkB;QAC3D,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC;QAClC,IAAI,CAAC,IAAI,GAAG,eAAe,CAAC;IAChC,CAAC;CACJ;AALD,sCAKC;AAED,4EAA4E;AAC5E,SAAgB,qBAAqB,CAAC,KAAa,EAAE,YAAqC,EAAE;IACxF,OAAO,IAAA,uBAAgB,EAAC,EAAE,MAAM,EAAE,kBAAkB,EAAE,MAAM,EAAE,mBAAmB,EAAE,UAAU,EAAE,4BAA4B,EAAE,EAAE,KAAK,EAAE,SAAS,CAAC,CAAC;AACrJ,CAAC;AAED,MAAa,cAAc;IACN,MAAM,CAAiB;IACxC,sFAAsF;IAC7E,KAAK,GAAU,EAAE,YAAY,EAAE,CAAC,EAAE,gBAAgB,EAAE,CAAC,EAAE,WAAW,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC;IAE9F,YAAY,MAAsB;QAC9B,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACzB,CAAC;IAED,IAAI,KAAK;QACL,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC;IAC7B,CAAC;IAED;;;;;;;OAOG;IACH,KAAK,CAAC,GAAG,CAAC,OAAyB;QAC/B,OAAO,IAAA,eAAQ,EAAoB;YAC/B,GAAG,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,YAAY;YACvC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,MAAM;YAC1B,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,OAAO,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,SAAS,EAAE,OAAO,CAAC,SAAS,EAAE;YACzF,SAAS,EAAE,MAAM,CAAC,EAAE,CAAC,IAAI,aAAa,CAAC,iBAAiB,MAAM,EAAE,EAAE,MAAM,EAAE,MAAM,KAAK,GAAG,IAAI,MAAM,IAAI,GAAG,CAAC;YAC1G,KAAK,EAAE,GAAG,CAAC,EAAE;gBACT,MAAM,IAAI,GAAG,GAAgG,CAAC;gBAC9G,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,CAAC,OAAO,KAAK,QAAQ,IAAI,IAAI,CAAC,OAAO,KAAK,IAAI,EAAE,CAAC;oBACrE,MAAM,IAAI,aAAa,CAAC,kCAAkC,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC;gBAC1E,CAAC;gBAED,MAAM,KAAK,GAAG,OAAO,IAAI,CAAC,KAAK,EAAE,YAAY,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC;gBACzF,MAAM,MAAM,GAAG,OAAO,IAAI,CAAC,KAAK,EAAE,aAAa,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC;gBAC5F,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC;gBACtB,IAAI,CAAC,KAAK,CAAC,YAAY,IAAI,KAAK,CAAC;gBACjC,IAAI,CAAC,KAAK,CAAC,gBAAgB,IAAI,MAAM,CAAC;gBACtC,IAAI,CAAC,KAAK,CAAC,WAAW,IAAI,KAAK,GAAG,MAAM,CAAC;gBAEzC,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,OAAuC,EAAE,CAAC;YACrE,CAAC;SACJ,CAAC,CAAC;IACP,CAAC;CACJ;AA7CD,wCA6CC"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The TypeSafe annotation questions.
|
|
3
|
+
*
|
|
4
|
+
* The same conventions as the OpenAI prompt (`prompt.ts`, docs/annotation-guide.md), reshaped for a
|
|
5
|
+
* model that answers typed questions instead of following a system prompt:
|
|
6
|
+
*
|
|
7
|
+
* - One Choice question per block, over the same closed label set. The answer is an option name
|
|
8
|
+
* and a probability distribution, so "select, never generate" holds by the protocol itself:
|
|
9
|
+
* there is no field in which text could come back.
|
|
10
|
+
* - The HOW TO DECIDE, QUOTE DEPTH and REGION WINS rules live in the option descriptions they
|
|
11
|
+
* disambiguate, because each question is evaluated in isolation and only sees its own criteria.
|
|
12
|
+
* - The COST OF ERRORS and CONFIDENCE sections are deliberately absent. Asking the model to be
|
|
13
|
+
* biased would bake the bias into the distribution; instead the raw distribution is stored and
|
|
14
|
+
* the asymmetry is applied in code (`probabilities.ts`).
|
|
15
|
+
*
|
|
16
|
+
* Versioned separately from the OpenAI prompt so runs under the two never share a resume key or get
|
|
17
|
+
* silently compared as one convention.
|
|
18
|
+
*/
|
|
19
|
+
import { type Label } from '../types';
|
|
20
|
+
import { type ChoiceQuestion, type SystemOneRequest } from './typesafe-client';
|
|
21
|
+
import { type PromptBlock } from './prompt';
|
|
22
|
+
export declare const TYPESAFE_PROMPT_VERSION = "annotate-ts-v1";
|
|
23
|
+
/**
|
|
24
|
+
* Option descriptions. Objects rather than strings because the confusable pairs (REPLY_HISTORY vs
|
|
25
|
+
* INLINE_QUOTE, SIGNATURE vs REPLY_HISTORY, DISCLAIMER vs NEW_CONTENT) need a stated boundary in
|
|
26
|
+
* both directions, and jev reads literally: an unstated rule is not applied.
|
|
27
|
+
*/
|
|
28
|
+
export declare const LABEL_CRITERIA: Readonly<Record<Label, Record<string, string | string[]>>>;
|
|
29
|
+
/**
|
|
30
|
+
* Question for the block at `position` in `state.blocks`.
|
|
31
|
+
*
|
|
32
|
+
* The path is the array position, not the block index: jev resolves `blocks[3]` as the fourth
|
|
33
|
+
* element, and block indices skip the blank blocks that are never sent. For the same reason the
|
|
34
|
+
* state carries no index field at all, so there is no second number the model could confuse with
|
|
35
|
+
* the position. One hop, named directly, per the jev 1.13 guidance on indirection.
|
|
36
|
+
*/
|
|
37
|
+
export declare function blockQuestion(position: number): ChoiceQuestion;
|
|
38
|
+
/** Question id for a block. Ids are never sent to the model, only used to match answers. */
|
|
39
|
+
export declare function questionId(index: number): string;
|
|
40
|
+
/** Inverse of `questionId`. Null for anything that is not one. */
|
|
41
|
+
export declare function parseQuestionId(id: string): number | null;
|
|
42
|
+
/** The state: exactly what the OpenAI prompt sends (block text, quote depth, reply flag), as JSON. */
|
|
43
|
+
export declare function buildState(blocks: readonly PromptBlock[], isReply: boolean): {
|
|
44
|
+
is_reply: boolean;
|
|
45
|
+
blocks: {
|
|
46
|
+
quote_depth: number;
|
|
47
|
+
truncated: boolean;
|
|
48
|
+
text: string;
|
|
49
|
+
}[];
|
|
50
|
+
};
|
|
51
|
+
/**
|
|
52
|
+
* Tokens allowed per request, below the documented 64k so the estimate below can be wrong by a
|
|
53
|
+
* margin without a request being rejected.
|
|
54
|
+
*/
|
|
55
|
+
export declare const REQUEST_TOKEN_BUDGET = 56000;
|
|
56
|
+
/**
|
|
57
|
+
* Split one message's questions into requests that fit the token budget.
|
|
58
|
+
*
|
|
59
|
+
* Every request carries the full state, because a block cannot be labelled without its neighbours.
|
|
60
|
+
* Only the questions are divided. With the 60 block, 700 character caps the state is at most about
|
|
61
|
+
* 21k estimated tokens, inside the documented 32k limit for state plus one question.
|
|
62
|
+
*/
|
|
63
|
+
export declare function planRequests(blocks: readonly PromptBlock[], isReply: boolean): SystemOneRequest[];
|
|
64
|
+
//# sourceMappingURL=typesafe-prompt.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"typesafe-prompt.d.ts","sourceRoot":"","sources":["../../src/annotate/typesafe-prompt.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAAE,KAAK,KAAK,EAAE,MAAM,UAAU,CAAC;AACtC,OAAO,EAAE,KAAK,cAAc,EAAE,KAAK,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAC/E,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,UAAU,CAAC;AAE5C,eAAO,MAAM,uBAAuB,mBAAmB,CAAC;AAExD;;;;GAIG;AACH,eAAO,MAAM,cAAc,EAAE,QAAQ,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAAC,CA+DrF,CAAC;AAEF;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,cAAc,CAY9D;AAED,4FAA4F;AAC5F,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEhD;AAED,kEAAkE;AAClE,wBAAgB,eAAe,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAGzD;AAED,sGAAsG;AACtG,wBAAgB,UAAU,CACtB,MAAM,EAAE,SAAS,WAAW,EAAE,EAC9B,OAAO,EAAE,OAAO,GACjB;IAAE,QAAQ,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,OAAO,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;CAAE,CAK5F;AAED;;;GAGG;AACH,eAAO,MAAM,oBAAoB,QAAQ,CAAC;AAa1C;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,SAAS,WAAW,EAAE,EAAE,OAAO,EAAE,OAAO,GAAG,gBAAgB,EAAE,CAiBjG"}
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* The TypeSafe annotation questions.
|
|
4
|
+
*
|
|
5
|
+
* The same conventions as the OpenAI prompt (`prompt.ts`, docs/annotation-guide.md), reshaped for a
|
|
6
|
+
* model that answers typed questions instead of following a system prompt:
|
|
7
|
+
*
|
|
8
|
+
* - One Choice question per block, over the same closed label set. The answer is an option name
|
|
9
|
+
* and a probability distribution, so "select, never generate" holds by the protocol itself:
|
|
10
|
+
* there is no field in which text could come back.
|
|
11
|
+
* - The HOW TO DECIDE, QUOTE DEPTH and REGION WINS rules live in the option descriptions they
|
|
12
|
+
* disambiguate, because each question is evaluated in isolation and only sees its own criteria.
|
|
13
|
+
* - The COST OF ERRORS and CONFIDENCE sections are deliberately absent. Asking the model to be
|
|
14
|
+
* biased would bake the bias into the distribution; instead the raw distribution is stored and
|
|
15
|
+
* the asymmetry is applied in code (`probabilities.ts`).
|
|
16
|
+
*
|
|
17
|
+
* Versioned separately from the OpenAI prompt so runs under the two never share a resume key or get
|
|
18
|
+
* silently compared as one convention.
|
|
19
|
+
*/
|
|
20
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
|
+
exports.REQUEST_TOKEN_BUDGET = exports.LABEL_CRITERIA = exports.TYPESAFE_PROMPT_VERSION = void 0;
|
|
22
|
+
exports.blockQuestion = blockQuestion;
|
|
23
|
+
exports.questionId = questionId;
|
|
24
|
+
exports.parseQuestionId = parseQuestionId;
|
|
25
|
+
exports.buildState = buildState;
|
|
26
|
+
exports.planRequests = planRequests;
|
|
27
|
+
exports.TYPESAFE_PROMPT_VERSION = 'annotate-ts-v1';
|
|
28
|
+
/**
|
|
29
|
+
* Option descriptions. Objects rather than strings because the confusable pairs (REPLY_HISTORY vs
|
|
30
|
+
* INLINE_QUOTE, SIGNATURE vs REPLY_HISTORY, DISCLAIMER vs NEW_CONTENT) need a stated boundary in
|
|
31
|
+
* both directions, and jev reads literally: an unstated rule is not applied.
|
|
32
|
+
*/
|
|
33
|
+
exports.LABEL_CRITERIA = {
|
|
34
|
+
NEW_CONTENT: {
|
|
35
|
+
what: 'Text the sender wrote themselves in this message.',
|
|
36
|
+
includes: [
|
|
37
|
+
'Greetings, answers, questions and closing words the sender wrote now, at quote depth 0',
|
|
38
|
+
'Text the sender pasted in that merely looks like an email',
|
|
39
|
+
'Boilerplate, when the message has no authored text at all outside it: then the boilerplate is the content, as in a newsletter'
|
|
40
|
+
],
|
|
41
|
+
not_this: [
|
|
42
|
+
'Any block at quote depth 2 or more: that is REPLY_HISTORY',
|
|
43
|
+
"The sender's name and contact block: that is SIGNATURE",
|
|
44
|
+
'System attached notices and service footers in a message that also has authored text: that is DISCLAIMER'
|
|
45
|
+
]
|
|
46
|
+
},
|
|
47
|
+
INLINE_QUOTE: {
|
|
48
|
+
what: 'Older text the sender quoted on purpose, usually at quote depth 1, in order to answer it here point by point.',
|
|
49
|
+
giveaway: "The sender's own new text comes after it and responds to it, often alternating several times.",
|
|
50
|
+
not_this: [
|
|
51
|
+
'A quote that runs uninterrupted to the end of the message as one copy of the previous mail: that is REPLY_HISTORY',
|
|
52
|
+
'Any block at quote depth 2 or more: that is REPLY_HISTORY'
|
|
53
|
+
]
|
|
54
|
+
},
|
|
55
|
+
REPLY_HISTORY: {
|
|
56
|
+
what: "A copy of an earlier message that the sender's mail client attached automatically, usually the whole previous message sitting at the end.",
|
|
57
|
+
includes: [
|
|
58
|
+
'The attribution line that opens it, such as "On <date>, <person> wrote:", "-----Original Message-----" or an embedded From:/Sent:/To:/Subject: block',
|
|
59
|
+
'Every block at quote depth 2 or more, including greetings, thanks, questions and sign-offs, because someone wrote them in an earlier message',
|
|
60
|
+
'Signatures, "--" delimiters, legal notices and forwards that sit inside that earlier message',
|
|
61
|
+
'An earlier message embedded without quote markers, as plain paragraphs after an attribution line',
|
|
62
|
+
'A hard wrapped quoted line whose continuation lost its quote marker'
|
|
63
|
+
],
|
|
64
|
+
not_this: ['A depth 1 quote that the sender answers below it: that is INLINE_QUOTE']
|
|
65
|
+
},
|
|
66
|
+
FORWARDED_CONTENT: {
|
|
67
|
+
what: 'A message the sender forwarded on purpose in this message.',
|
|
68
|
+
includes: [
|
|
69
|
+
'The forward marker that opens it, such as "Begin forwarded message:" or "---------- Forwarded message ----------"',
|
|
70
|
+
'Everything inside the forwarded message, including its signatures and confidentiality notices'
|
|
71
|
+
],
|
|
72
|
+
not_this: ['A forward that appears inside quoted reply history, since the earlier correspondent forwarded it: that is REPLY_HISTORY']
|
|
73
|
+
},
|
|
74
|
+
SIGNATURE: {
|
|
75
|
+
what: 'The sign-off block of this sender, in this message: name, role, company, phone, links, "Sent from my phone".',
|
|
76
|
+
not_this: ['A signature inside quoted history: that is REPLY_HISTORY', 'A signature inside a forwarded message: that is FORWARDED_CONTENT']
|
|
77
|
+
},
|
|
78
|
+
DISCLAIMER: {
|
|
79
|
+
what: 'Boilerplate a system, gateway or template attached to this message independently of what the sender wrote.',
|
|
80
|
+
includes: [
|
|
81
|
+
'Confidentiality and liability notices, virus scanning notices',
|
|
82
|
+
'Company registration and VAT numbers, registered office addresses',
|
|
83
|
+
'Unsubscribe and preference footers, "powered by" branding',
|
|
84
|
+
'Templated promotional or navigational footers: subscribe invitations, app download links, social media links, help and support pointers'
|
|
85
|
+
],
|
|
86
|
+
not_this: [
|
|
87
|
+
'Boilerplate inside quoted history: that is REPLY_HISTORY',
|
|
88
|
+
'Boilerplate inside a forwarded message: that is FORWARDED_CONTENT',
|
|
89
|
+
'Boilerplate in a message with no authored text anywhere else: that is NEW_CONTENT'
|
|
90
|
+
]
|
|
91
|
+
},
|
|
92
|
+
UNKNOWN: {
|
|
93
|
+
what: 'It is genuinely impossible to tell which message this block belongs to.',
|
|
94
|
+
not_this: ['A block whose place in the message is clear, however short it is']
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
/**
|
|
98
|
+
* Question for the block at `position` in `state.blocks`.
|
|
99
|
+
*
|
|
100
|
+
* The path is the array position, not the block index: jev resolves `blocks[3]` as the fourth
|
|
101
|
+
* element, and block indices skip the blank blocks that are never sent. For the same reason the
|
|
102
|
+
* state carries no index field at all, so there is no second number the model could confuse with
|
|
103
|
+
* the position. One hop, named directly, per the jev 1.13 guidance on indirection.
|
|
104
|
+
*/
|
|
105
|
+
function blockQuestion(position) {
|
|
106
|
+
return {
|
|
107
|
+
type: 'choice',
|
|
108
|
+
instructions: {
|
|
109
|
+
question: `Which part of this email message does \`blocks[${position}]\` belong to?`,
|
|
110
|
+
how_to_judge: 'Judge by which message the block was written in, never by what its text looks like. Greetings, signatures and legal footers occur inside every part of a message. Read the blocks before and after it to see where it sits.',
|
|
111
|
+
state_fields: '`blocks` is the whole message split into blocks, in order. `quote_depth` is the quote nesting the message shows: 0 not quoted, 1 quoted once, 2 or more quoted inside a quote. `truncated` means the text was cut short. `is_reply` says whether the message replies to an earlier one.'
|
|
112
|
+
},
|
|
113
|
+
criteria: exports.LABEL_CRITERIA
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
/** Question id for a block. Ids are never sent to the model, only used to match answers. */
|
|
117
|
+
function questionId(index) {
|
|
118
|
+
return `b${index}`;
|
|
119
|
+
}
|
|
120
|
+
/** Inverse of `questionId`. Null for anything that is not one. */
|
|
121
|
+
function parseQuestionId(id) {
|
|
122
|
+
const index = /^b(\d+)$/.exec(id)?.[1];
|
|
123
|
+
return index === undefined ? null : Number(index);
|
|
124
|
+
}
|
|
125
|
+
/** The state: exactly what the OpenAI prompt sends (block text, quote depth, reply flag), as JSON. */
|
|
126
|
+
function buildState(blocks, isReply) {
|
|
127
|
+
return {
|
|
128
|
+
is_reply: isReply,
|
|
129
|
+
blocks: blocks.map(block => ({ quote_depth: block.quoteDepth, truncated: block.truncated, text: block.text }))
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Tokens allowed per request, below the documented 64k so the estimate below can be wrong by a
|
|
134
|
+
* margin without a request being rejected.
|
|
135
|
+
*/
|
|
136
|
+
exports.REQUEST_TOKEN_BUDGET = 56000;
|
|
137
|
+
/**
|
|
138
|
+
* Deliberately pessimistic characters per token. English runs near four, but the corpus is largely
|
|
139
|
+
* Estonian and also holds Cyrillic and CJK text, which tokenise much denser. Overestimating only
|
|
140
|
+
* costs an extra request; underestimating costs a rejected message.
|
|
141
|
+
*/
|
|
142
|
+
const CHARS_PER_TOKEN = 2;
|
|
143
|
+
function estimateTokens(value) {
|
|
144
|
+
return Math.ceil(JSON.stringify(value).length / CHARS_PER_TOKEN);
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Split one message's questions into requests that fit the token budget.
|
|
148
|
+
*
|
|
149
|
+
* Every request carries the full state, because a block cannot be labelled without its neighbours.
|
|
150
|
+
* Only the questions are divided. With the 60 block, 700 character caps the state is at most about
|
|
151
|
+
* 21k estimated tokens, inside the documented 32k limit for state plus one question.
|
|
152
|
+
*/
|
|
153
|
+
function planRequests(blocks, isReply) {
|
|
154
|
+
if (!blocks.length) {
|
|
155
|
+
return [];
|
|
156
|
+
}
|
|
157
|
+
const state = buildState(blocks, isReply);
|
|
158
|
+
const perQuestion = estimateTokens(blockQuestion(blocks.length - 1));
|
|
159
|
+
const perRequest = Math.max(1, Math.floor((exports.REQUEST_TOKEN_BUDGET - estimateTokens(state)) / perQuestion));
|
|
160
|
+
const requests = [];
|
|
161
|
+
for (let from = 0; from < blocks.length; from += perRequest) {
|
|
162
|
+
const questions = {};
|
|
163
|
+
blocks.slice(from, from + perRequest).forEach((block, offset) => {
|
|
164
|
+
questions[questionId(block.index)] = blockQuestion(from + offset);
|
|
165
|
+
});
|
|
166
|
+
requests.push({ state, questions });
|
|
167
|
+
}
|
|
168
|
+
return requests;
|
|
169
|
+
}
|
|
170
|
+
//# sourceMappingURL=typesafe-prompt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"typesafe-prompt.js","sourceRoot":"","sources":["../../src/annotate/typesafe-prompt.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;GAiBG;;;AAsFH,sCAYC;AAGD,gCAEC;AAGD,0CAGC;AAGD,gCAQC;AA0BD,oCAiBC;AA7JY,QAAA,uBAAuB,GAAG,gBAAgB,CAAC;AAExD;;;;GAIG;AACU,QAAA,cAAc,GAA+D;IACtF,WAAW,EAAE;QACT,IAAI,EAAE,mDAAmD;QACzD,QAAQ,EAAE;YACN,wFAAwF;YACxF,2DAA2D;YAC3D,+HAA+H;SAClI;QACD,QAAQ,EAAE;YACN,2DAA2D;YAC3D,wDAAwD;YACxD,0GAA0G;SAC7G;KACJ;IACD,YAAY,EAAE;QACV,IAAI,EAAE,+GAA+G;QACrH,QAAQ,EAAE,+FAA+F;QACzG,QAAQ,EAAE;YACN,mHAAmH;YACnH,2DAA2D;SAC9D;KACJ;IACD,aAAa,EAAE;QACX,IAAI,EAAE,2IAA2I;QACjJ,QAAQ,EAAE;YACN,sJAAsJ;YACtJ,8IAA8I;YAC9I,8FAA8F;YAC9F,kGAAkG;YAClG,qEAAqE;SACxE;QACD,QAAQ,EAAE,CAAC,wEAAwE,CAAC;KACvF;IACD,iBAAiB,EAAE;QACf,IAAI,EAAE,4DAA4D;QAClE,QAAQ,EAAE;YACN,mHAAmH;YACnH,+FAA+F;SAClG;QACD,QAAQ,EAAE,CAAC,yHAAyH,CAAC;KACxI;IACD,SAAS,EAAE;QACP,IAAI,EAAE,8GAA8G;QACpH,QAAQ,EAAE,CAAC,0DAA0D,EAAE,mEAAmE,CAAC;KAC9I;IACD,UAAU,EAAE;QACR,IAAI,EAAE,4GAA4G;QAClH,QAAQ,EAAE;YACN,+DAA+D;YAC/D,mEAAmE;YACnE,2DAA2D;YAC3D,yIAAyI;SAC5I;QACD,QAAQ,EAAE;YACN,0DAA0D;YAC1D,mEAAmE;YACnE,mFAAmF;SACtF;KACJ;IACD,OAAO,EAAE;QACL,IAAI,EAAE,yEAAyE;QAC/E,QAAQ,EAAE,CAAC,kEAAkE,CAAC;KACjF;CACJ,CAAC;AAEF;;;;;;;GAOG;AACH,SAAgB,aAAa,CAAC,QAAgB;IAC1C,OAAO;QACH,IAAI,EAAE,QAAQ;QACd,YAAY,EAAE;YACV,QAAQ,EAAE,kDAAkD,QAAQ,gBAAgB;YACpF,YAAY,EACR,6NAA6N;YACjO,YAAY,EACR,yRAAyR;SAChS;QACD,QAAQ,EAAE,sBAAc;KAC3B,CAAC;AACN,CAAC;AAED,4FAA4F;AAC5F,SAAgB,UAAU,CAAC,KAAa;IACpC,OAAO,IAAI,KAAK,EAAE,CAAC;AACvB,CAAC;AAED,kEAAkE;AAClE,SAAgB,eAAe,CAAC,EAAU;IACtC,MAAM,KAAK,GAAG,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IACvC,OAAO,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AACtD,CAAC;AAED,sGAAsG;AACtG,SAAgB,UAAU,CACtB,MAA8B,EAC9B,OAAgB;IAEhB,OAAO;QACH,QAAQ,EAAE,OAAO;QACjB,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,EAAE,WAAW,EAAE,KAAK,CAAC,UAAU,EAAE,SAAS,EAAE,KAAK,CAAC,SAAS,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;KACjH,CAAC;AACN,CAAC;AAED;;;GAGG;AACU,QAAA,oBAAoB,GAAG,KAAK,CAAC;AAE1C;;;;GAIG;AACH,MAAM,eAAe,GAAG,CAAC,CAAC;AAE1B,SAAS,cAAc,CAAC,KAAc;IAClC,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,MAAM,GAAG,eAAe,CAAC,CAAC;AACrE,CAAC;AAED;;;;;;GAMG;AACH,SAAgB,YAAY,CAAC,MAA8B,EAAE,OAAgB;IACzE,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;QACjB,OAAO,EAAE,CAAC;IACd,CAAC;IACD,MAAM,KAAK,GAAG,UAAU,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC1C,MAAM,WAAW,GAAG,cAAc,CAAC,aAAa,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC;IACrE,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,4BAAoB,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC;IAEzG,MAAM,QAAQ,GAAuB,EAAE,CAAC;IACxC,KAAK,IAAI,IAAI,GAAG,CAAC,EAAE,IAAI,GAAG,MAAM,CAAC,MAAM,EAAE,IAAI,IAAI,UAAU,EAAE,CAAC;QAC1D,MAAM,SAAS,GAAmC,EAAE,CAAC;QACrD,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,GAAG,UAAU,CAAC,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE;YAC5D,SAAS,CAAC,UAAU,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,GAAG,aAAa,CAAC,IAAI,GAAG,MAAM,CAAC,CAAC;QACtE,CAAC,CAAC,CAAC;QACH,QAAQ,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;IACxC,CAAC;IACD,OAAO,QAAQ,CAAC;AACpB,CAAC"}
|
package/dist/canonical/text.d.ts
CHANGED
|
@@ -56,12 +56,24 @@ export declare function splitQuotePrefix(line: string): {
|
|
|
56
56
|
content: string;
|
|
57
57
|
};
|
|
58
58
|
/**
|
|
59
|
-
*
|
|
59
|
+
* The canonical string for a decoded plain text body, without the line model.
|
|
60
|
+
*
|
|
61
|
+
* Every character offset the extractor reports for a plain text representation (segment source
|
|
62
|
+
* ranges included) indexes the string this returns, not the input. EmailEngine slices message text
|
|
63
|
+
* at those offsets to fold quoted history, so it must canonicalise with this exact function; a
|
|
64
|
+
* private copy that drifts by one character moves the cut. Treat the output as a stable contract:
|
|
65
|
+
* changing it is a breaking change for any caller that slices offsets.
|
|
60
66
|
*
|
|
61
|
-
*
|
|
62
|
-
*
|
|
67
|
+
* A leading BOM is dropped, CRLF and lone CR both become LF, NUL characters are removed, and the
|
|
68
|
+
* result is NFC normalised so that visually identical text compares equal during history
|
|
63
69
|
* matching. Nothing else is altered: no trimming, no whitespace collapsing, no unwrapping.
|
|
64
70
|
*/
|
|
71
|
+
export declare function canonicalisePlainText(input: string): string;
|
|
72
|
+
/**
|
|
73
|
+
* Normalise decoded part text into the canonical form used by every later stage.
|
|
74
|
+
*
|
|
75
|
+
* The text is exactly `canonicalisePlainText(input)`; this adds the per line model on top of it.
|
|
76
|
+
*/
|
|
65
77
|
export declare function canonicaliseText(input: string): CanonicalText;
|
|
66
78
|
/**
|
|
67
79
|
* Describe how quoting is laid out in a plain text body.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"text.d.ts","sourceRoot":"","sources":["../../src/canonical/text.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,iEAAiE;AACjE,MAAM,WAAW,QAAQ;IACrB,4CAA4C;IAC5C,KAAK,EAAE,MAAM,CAAC;IACd,oEAAoE;IACpE,KAAK,EAAE,MAAM,CAAC;IACd,0EAA0E;IAC1E,GAAG,EAAE,MAAM,CAAC;IACZ,wFAAwF;IACxF,GAAG,EAAE,MAAM,CAAC;IACZ,8CAA8C;IAC9C,OAAO,EAAE,MAAM,CAAC;IAChB,gEAAgE;IAChE,KAAK,EAAE,MAAM,CAAC;IACd,6EAA6E;IAC7E,KAAK,EAAE,OAAO,CAAC;IACf,8FAA8F;IAC9F,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAED,MAAM,WAAW,aAAa;IAC1B,yEAAyE;IACzE,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,QAAQ,EAAE,CAAC;CACrB;AAED,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,KAAK,GAAG,QAAQ,GAAG,aAAa,GAAG,kBAAkB,GAAG,YAAY,CAAC;AAEvG,MAAM,WAAW,YAAY;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,0DAA0D;IAC1D,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,UAAU,CAAC;IAClB,6DAA6D;IAC7D,aAAa,EAAE,MAAM,CAAC;IACtB,uEAAuE;IACvE,cAAc,EAAE,MAAM,CAAC;IACvB,2DAA2D;IAC3D,YAAY,EAAE,MAAM,CAAC;CACxB;AAYD,+DAA+D;AAC/D,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAajF;AAED
|
|
1
|
+
{"version":3,"file":"text.d.ts","sourceRoot":"","sources":["../../src/canonical/text.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,iEAAiE;AACjE,MAAM,WAAW,QAAQ;IACrB,4CAA4C;IAC5C,KAAK,EAAE,MAAM,CAAC;IACd,oEAAoE;IACpE,KAAK,EAAE,MAAM,CAAC;IACd,0EAA0E;IAC1E,GAAG,EAAE,MAAM,CAAC;IACZ,wFAAwF;IACxF,GAAG,EAAE,MAAM,CAAC;IACZ,8CAA8C;IAC9C,OAAO,EAAE,MAAM,CAAC;IAChB,gEAAgE;IAChE,KAAK,EAAE,MAAM,CAAC;IACd,6EAA6E;IAC7E,KAAK,EAAE,OAAO,CAAC;IACf,8FAA8F;IAC9F,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAED,MAAM,WAAW,aAAa;IAC1B,yEAAyE;IACzE,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,QAAQ,EAAE,CAAC;CACrB;AAED,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,KAAK,GAAG,QAAQ,GAAG,aAAa,GAAG,kBAAkB,GAAG,YAAY,CAAC;AAEvG,MAAM,WAAW,YAAY;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,0DAA0D;IAC1D,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,UAAU,CAAC;IAClB,6DAA6D;IAC7D,aAAa,EAAE,MAAM,CAAC;IACtB,uEAAuE;IACvE,cAAc,EAAE,MAAM,CAAC;IACvB,2DAA2D;IAC3D,YAAY,EAAE,MAAM,CAAC;CACxB;AAYD,+DAA+D;AAC/D,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAajF;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAY3D;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,aAAa,CA+B7D;AA+CD;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,SAAS,QAAQ,EAAE,GAAG,YAAY,CA0EvE"}
|
package/dist/canonical/text.js
CHANGED
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
*/
|
|
15
15
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
16
|
exports.splitQuotePrefix = splitQuotePrefix;
|
|
17
|
+
exports.canonicalisePlainText = canonicalisePlainText;
|
|
17
18
|
exports.canonicaliseText = canonicaliseText;
|
|
18
19
|
exports.profileQuoting = profileQuoting;
|
|
19
20
|
/**
|
|
@@ -41,13 +42,19 @@ function splitQuotePrefix(line) {
|
|
|
41
42
|
return { depth, content: line.slice(match[0].length) };
|
|
42
43
|
}
|
|
43
44
|
/**
|
|
44
|
-
*
|
|
45
|
+
* The canonical string for a decoded plain text body, without the line model.
|
|
46
|
+
*
|
|
47
|
+
* Every character offset the extractor reports for a plain text representation (segment source
|
|
48
|
+
* ranges included) indexes the string this returns, not the input. EmailEngine slices message text
|
|
49
|
+
* at those offsets to fold quoted history, so it must canonicalise with this exact function; a
|
|
50
|
+
* private copy that drifts by one character moves the cut. Treat the output as a stable contract:
|
|
51
|
+
* changing it is a breaking change for any caller that slices offsets.
|
|
45
52
|
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
53
|
+
* A leading BOM is dropped, CRLF and lone CR both become LF, NUL characters are removed, and the
|
|
54
|
+
* result is NFC normalised so that visually identical text compares equal during history
|
|
48
55
|
* matching. Nothing else is altered: no trimming, no whitespace collapsing, no unwrapping.
|
|
49
56
|
*/
|
|
50
|
-
function
|
|
57
|
+
function canonicalisePlainText(input) {
|
|
51
58
|
let text = input;
|
|
52
59
|
if (text.charCodeAt(0) === 0xfeff) {
|
|
53
60
|
text = text.slice(1);
|
|
@@ -59,6 +66,15 @@ function canonicaliseText(input) {
|
|
|
59
66
|
catch {
|
|
60
67
|
// Extremely long or malformed input can defeat NFC. The unnormalised text is still usable.
|
|
61
68
|
}
|
|
69
|
+
return text;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Normalise decoded part text into the canonical form used by every later stage.
|
|
73
|
+
*
|
|
74
|
+
* The text is exactly `canonicalisePlainText(input)`; this adds the per line model on top of it.
|
|
75
|
+
*/
|
|
76
|
+
function canonicaliseText(input) {
|
|
77
|
+
const text = canonicalisePlainText(input);
|
|
62
78
|
const lines = [];
|
|
63
79
|
let offset = 0;
|
|
64
80
|
let index = 0;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"text.js","sourceRoot":"","sources":["../../src/canonical/text.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;GAYG;;AAwDH,4CAaC;
|
|
1
|
+
{"version":3,"file":"text.js","sourceRoot":"","sources":["../../src/canonical/text.ts"],"names":[],"mappings":"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"}
|
package/dist/classify/rules.d.ts
CHANGED
|
@@ -47,6 +47,13 @@ export interface ClassifyOptions {
|
|
|
47
47
|
* and unlike a greeting phrase it is language independent.
|
|
48
48
|
*/
|
|
49
49
|
senderTokens?: readonly string[];
|
|
50
|
+
/**
|
|
51
|
+
* The subject marks the message as a forward and not as a reply. Several clients introduce a
|
|
52
|
+
* forward with the same separators they use for reply history ("-------- Original Message
|
|
53
|
+
* --------", Outlook's #divRplyFwdMsg, quote containers), so without this the forwarded message
|
|
54
|
+
* is hidden as history. With it, whatever the reply rules call history is forwarded instead.
|
|
55
|
+
*/
|
|
56
|
+
messageIsForward?: boolean;
|
|
50
57
|
}
|
|
51
58
|
/**
|
|
52
59
|
* Classify one representation's blocks.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rules.d.ts","sourceRoot":"","sources":["../../src/classify/rules.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAAE,KAAK,KAAK,EAAE,KAAK,MAAM,EAAE,MAAM,UAAU,CAAC;AACnD,OAAO,EAAE,KAAK,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAsB,KAAK,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAEzE,MAAM,WAAW,aAAa;IAC1B,KAAK,EAAE,KAAK,CAAC;IACb,KAAK,EAAE,KAAK,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,MAAM,WAAW,eAAe;IAC5B,MAAM,CAAC,EAAE,gBAAgB,CAAC;IAC1B;;;OAGG;IACH,qBAAqB,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAC5C;;;;;OAKG;IACH,oBAAoB,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAC3C;;;;OAIG;IACH,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"rules.d.ts","sourceRoot":"","sources":["../../src/classify/rules.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAAE,KAAK,KAAK,EAAE,KAAK,MAAM,EAAE,MAAM,UAAU,CAAC;AACnD,OAAO,EAAE,KAAK,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAsB,KAAK,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAEzE,MAAM,WAAW,aAAa;IAC1B,KAAK,EAAE,KAAK,CAAC;IACb,KAAK,EAAE,KAAK,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,MAAM,WAAW,eAAe;IAC5B,MAAM,CAAC,EAAE,gBAAgB,CAAC;IAC1B;;;OAGG;IACH,qBAAqB,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAC5C;;;;;OAKG;IACH,oBAAoB,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAC3C;;;;OAIG;IACH,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAiGD;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,SAAS,KAAK,EAAE,EAAE,OAAO,GAAE,eAAoB,GAAG,aAAa,EAAE,CAqrBvG"}
|