@framers/agentos-ext-gmail-source 0.2.0 → 0.3.0

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 CHANGED
@@ -1,8 +1,8 @@
1
1
  # Gmail source
2
2
 
3
- This library provides read-only Gmail authorization on the AgentOS redirect grant and sealed-token contracts, and text helpers that sanitize and trim mail before it is stored (see Text ingestion below). It requests the sole Gmail read-only scope, offline access and incremental consent. It exports no send, reply, label-modification or attachment-download tool.
3
+ This library provides read-only Gmail authorization on the AgentOS redirect grant and sealed-token contracts, text helpers that sanitize and trim mail before it is stored (see Text ingestion below), and a bounded mapper that turns one thread response into a sanitized source document (see Thread documents below). It requests the sole Gmail read-only scope, offline access and incremental consent. It exports no send, reply, label-modification or attachment-download tool.
4
4
 
5
- Install it next to `@framers/agentos` 0.13.134 or later and `@framers/agentos-ext-account-sources` 0.4.0 or later. Both are peer dependencies with a floor and no upper bound. Node.js 20.19 or later is required.
5
+ Install it next to `@framers/agentos` 0.13.134 or later and `@framers/agentos-ext-account-sources` 0.7.0 or later. Both are peer dependencies with a floor and no upper bound. Node.js 20.19 or later is required.
6
6
 
7
7
  ```ts
8
8
  import { GmailOAuthFlow } from '@framers/agentos-ext-gmail-source';
@@ -59,3 +59,38 @@ const filename = sanitizeMailMetadata(decodedFilename, { ...policy, maxOutputCha
59
59
  `messageText(input, policy)` sanitizes first, trims recognized reply history and short signatures, then applies the output cap. Explicit forwarded content and ambiguous prose are retained. Its `trimmedQuote`, `trimmedSignature` and `truncated` flags describe omissions. Quote spans must refer to its returned string, without inserted summaries or an ellipsis presented as source text. A host should disclose that attachments are listed and their contents are not read when its mapper implements that boundary.
60
60
 
61
61
  The functions return text and counts only. They do not store raw values or a reverse-redaction map, log matches, fetch URLs, interpret mail as instructions or invoke a model. Sanitization can remove benign text and cannot identify every possible secret. It does not make personal mail anonymous or authorize model processing, sharing or retention. Hosts must preserve the source's privacy, expiry and deletion rules for both text and derived results.
62
+
63
+ ## Thread documents
64
+
65
+ ```ts
66
+ import { GmailThreadMapper } from '@framers/agentos-ext-gmail-source';
67
+
68
+ const mapper = new GmailThreadMapper({
69
+ maxResponseBytes: 2_097_152, maxDecodedBytes: 2_097_152, maxMimeDepth: 20, maxMimeParts: 1_000,
70
+ maxMessages: 100, maxMessageCharacters: 20_000, maxThreadCharacters: 200_000,
71
+ maxMetadataCharacters: 200_000, maxInputCharacters: 2_097_152, maxLineCharacters: 65_536,
72
+ maximumCacheMs: 86_400_000,
73
+ });
74
+
75
+ // `response` is the parsed threads.get (format=full) body from a transport that capped its bytes.
76
+ const result = await mapper.map(response, {
77
+ sourceId: response.id,
78
+ sourceDetailUrl: detailPath, // the host's authenticated source-detail route, never a Gmail link
79
+ cutoff, windowMs: 30 * 86_400_000, readStartedAt, receivedAt,
80
+ permission, cacheHeaders, labelNames, labelCache, signal,
81
+ });
82
+ // result.kind is 'document' (text, message spans, metadata, cache expiry) or 'skipped' with a fixed reason.
83
+ ```
84
+
85
+ Construct `GmailThreadMapper(bounds)` with explicit response, decoded-byte, MIME depth/part, retained-message, message/thread text, metadata, sanitizer and cache ceilings. `map(thread, options)` returns the account-source `SourceSyncReadResult` union. The input is the parsed response from a transport that already enforced its byte cap before JSON decoding. The mapper separately checks recognized MIME data and the entire part tree before decoding any selected body. A parsed object alone cannot establish its original wire size.
86
+
87
+ Supply a fixed selection cutoff, message window, original read start and completion times, actual response cache headers, independently established cache permission and a host-generated relative detail path. The path must resolve authentication and current source generation in the host. It is never a Gmail deep link or a request-derived external URL. A successful OAuth grant does not establish cache or model-processing permission.
88
+ Pass `labelCache` as the separate labels response’s cache decision. Missing, refused or expired label permission keeps ids without names. Permitted names shorten the entire document’s expiry when their allowed lifetime ends first.
89
+
90
+ Each message is filtered by its internal timestamp and excluded labels. Retained messages are selected newest first with stable id ties, within the explicit cap, and rendered chronologically. Plain text wins within a MIME alternative. Other multipart containers retain their non-attachment text children in MIME order. HTML uses the public AgentOS `HtmlLoader` with an in-memory Buffer. No browser or remote resource is loaded. The resulting text, structured headers, filenames, media types and label names all pass the text sanitizer.
91
+
92
+ Attachments are listed; their contents are not read. An external body or attachment contributes only sanitized filename, media type and size. Inline attachment bytes and attachment ids are discarded. Bcc, raw payloads, snippets and unknown fields are not returned. The mapper never calls any Gmail endpoint. Unsupported charset, invalid bytes and omitted content have fixed counted reasons. Invalid protocol shape is a failure rather than an empty successful source.
93
+
94
+ A returned document has matching item/ref versions, a normalized-content hash, message ids and body spans, earliest allowed expiry and explicit omission/truncation metadata. Spans count UTF-16 code units in the returned text and exclude the header prefix. Quote trimming preserves normalized source text; no generated summary or ellipsis is inserted into a quote. Header-only messages can have an empty body span. Render structured metadata as escaped text and treat all mail as untrusted data.
95
+
96
+ A history-only change does not extend cache life or change the normalized hash. Storage still requires the account-source transactional fence, fresh expiry checks and host allowances. Derived results retain the whole source's personal-use, expiry and deletion restrictions. Never persist the transient MIME types or bypass the account-source store with a mapper result.
package/dist/index.d.ts CHANGED
@@ -1,12 +1,15 @@
1
1
  /**
2
2
  * @fileoverview A read-only Gmail source's grant: Google's read-only scope on the AgentOS redirect OAuth flow and
3
- * sealed-token store, with capped, cancellable OAuth calls and fixed failures; and its text helpers: bounded
3
+ * sealed-token store, with capped, cancellable OAuth calls and fixed failures; its text helpers: bounded
4
4
  * pre-storage sanitization of mail text, allow-listed headers and metadata, and conservative trimming of reply history
5
- * and signatures.
5
+ * and signatures; and its thread mapper: bounded MIME reading of one thread into a sanitized account-source document
6
+ * with message provenance, attachment listings and an explicit cache decision.
6
7
  * @module agentos-ext-gmail-source
7
8
  */
8
9
  export { GmailOAuthFlow } from './GmailOAuthFlow.js';
9
10
  export { GMAIL_READONLY_SCOPE, GmailOAuthFault, type GmailOAuthFailure, type GmailGrantCleanup, type GmailOAuthClient, type GmailOAuthEndpoints, type GmailOAuthOptions, } from './types.js';
10
11
  export { GmailTextFault, sanitizeMailText, sanitizeMailMetadata, sanitizeMailHeaders, type GmailTextPolicy, type GmailSanitizedText, type GmailHeaderInput, type GmailSanitizedHeaders, type GmailTextFailure, } from './mailSanitize.js';
11
12
  export { messageText, type GmailMessageText } from './messageText.js';
13
+ export { GmailThreadMapper, type GmailMapThreadOptions } from './mapThread.js';
14
+ export { GmailMappingFault, type GmailMappingBounds } from './mime.js';
12
15
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EACL,oBAAoB,EAAE,eAAe,EAAE,KAAK,iBAAiB,EAAE,KAAK,iBAAiB,EACrF,KAAK,gBAAgB,EAAE,KAAK,mBAAmB,EAAE,KAAK,iBAAiB,GACxE,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,cAAc,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,mBAAmB,EAC3E,KAAK,eAAe,EAAE,KAAK,kBAAkB,EAAE,KAAK,gBAAgB,EACpE,KAAK,qBAAqB,EAAE,KAAK,gBAAgB,GAClD,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,WAAW,EAAE,KAAK,gBAAgB,EAAE,MAAM,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EACL,oBAAoB,EAAE,eAAe,EAAE,KAAK,iBAAiB,EAAE,KAAK,iBAAiB,EACrF,KAAK,gBAAgB,EAAE,KAAK,mBAAmB,EAAE,KAAK,iBAAiB,GACxE,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,cAAc,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,mBAAmB,EAC3E,KAAK,eAAe,EAAE,KAAK,kBAAkB,EAAE,KAAK,gBAAgB,EACpE,KAAK,qBAAqB,EAAE,KAAK,gBAAgB,GAClD,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,WAAW,EAAE,KAAK,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACtE,OAAO,EAAE,iBAAiB,EAAE,KAAK,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AAC/E,OAAO,EAAE,iBAAiB,EAAE,KAAK,kBAAkB,EAAE,MAAM,WAAW,CAAC"}
package/dist/index.js CHANGED
@@ -1,12 +1,15 @@
1
1
  /**
2
2
  * @fileoverview A read-only Gmail source's grant: Google's read-only scope on the AgentOS redirect OAuth flow and
3
- * sealed-token store, with capped, cancellable OAuth calls and fixed failures; and its text helpers: bounded
3
+ * sealed-token store, with capped, cancellable OAuth calls and fixed failures; its text helpers: bounded
4
4
  * pre-storage sanitization of mail text, allow-listed headers and metadata, and conservative trimming of reply history
5
- * and signatures.
5
+ * and signatures; and its thread mapper: bounded MIME reading of one thread into a sanitized account-source document
6
+ * with message provenance, attachment listings and an explicit cache decision.
6
7
  * @module agentos-ext-gmail-source
7
8
  */
8
9
  export { GmailOAuthFlow } from './GmailOAuthFlow.js';
9
10
  export { GMAIL_READONLY_SCOPE, GmailOAuthFault, } from './types.js';
10
11
  export { GmailTextFault, sanitizeMailText, sanitizeMailMetadata, sanitizeMailHeaders, } from './mailSanitize.js';
11
12
  export { messageText } from './messageText.js';
13
+ export { GmailThreadMapper } from './mapThread.js';
14
+ export { GmailMappingFault } from './mime.js';
12
15
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EACL,oBAAoB,EAAE,eAAe,GAEtC,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,cAAc,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,mBAAmB,GAG5E,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,WAAW,EAAyB,MAAM,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EACL,oBAAoB,EAAE,eAAe,GAEtC,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,cAAc,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,mBAAmB,GAG5E,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,WAAW,EAAyB,MAAM,kBAAkB,CAAC;AACtE,OAAO,EAAE,iBAAiB,EAA8B,MAAM,gBAAgB,CAAC;AAC/E,OAAO,EAAE,iBAAiB,EAA2B,MAAM,WAAW,CAAC"}
@@ -0,0 +1,66 @@
1
+ import { type SourceCachePermission, type SourceCacheHeaders, type SourceCacheDecision, type SourceSyncReadResult } from '@framers/agentos-ext-account-sources';
2
+ import { type GmailMappingBounds } from './mime.js';
3
+ /** The per-read values of one `map` call. The host supplies every value; none comes from a browser request. */
4
+ export interface GmailMapThreadOptions {
5
+ /** The requested thread id; the response must carry the same id. */
6
+ readonly sourceId: string;
7
+ /**
8
+ * The host's authenticated source-detail path, used as `SourceRef.url`: a relative path of segments made of letters,
9
+ * digits, `_` and `-`, with no query, fragment or origin, at most 512 characters. Never a Gmail link.
10
+ */
11
+ readonly sourceDetailUrl: string;
12
+ /** The selection cutoff, epoch milliseconds, no later than `receivedAt`: a message received after it is left out. */
13
+ readonly cutoff: number;
14
+ /**
15
+ * The message window in milliseconds, 1 to 90 days. A message received at or before `cutoff - windowMs`, or whose
16
+ * window has ended by `receivedAt`, is left out.
17
+ */
18
+ readonly windowMs: number;
19
+ /** When the thread request started, epoch milliseconds. */
20
+ readonly readStartedAt: number;
21
+ /** When the thread response was complete, epoch milliseconds; it becomes `SourceRef.readAt`. */
22
+ readonly receivedAt: number;
23
+ /** The host's evidenced cache permission; null refuses durable content. */
24
+ readonly permission: SourceCachePermission | null;
25
+ /** The thread response's own cache headers. */
26
+ readonly cacheHeaders: SourceCacheHeaders;
27
+ /** Label names from the cycle's labels response, by label id. */
28
+ readonly labelNames: Readonly<Record<string, string>>;
29
+ /** The labels response's own cache decision. Null, a refusal or an expired decision keeps ids without names. */
30
+ readonly labelCache: SourceCacheDecision | null;
31
+ /** Cancels the call between steps. */
32
+ readonly signal?: AbortSignal;
33
+ }
34
+ /**
35
+ * Maps one parsed Gmail thread into a sanitized account-source document: one thread, one document, with each retained
36
+ * message's id, dates, sanitized headers, labels, attachment listing and body span. It calls no endpoint, writes no log
37
+ * and keeps no state between calls.
38
+ */
39
+ export declare class GmailThreadMapper {
40
+ private readonly bounds;
41
+ /**
42
+ * @param bounds Every operational ceiling; see `GmailMappingBounds`.
43
+ * @throws {GmailMappingFault} `configuration` for an invalid bound.
44
+ */
45
+ constructor(bounds: GmailMappingBounds);
46
+ private policy;
47
+ private normalize;
48
+ /**
49
+ * Validates the whole response, filters each message by its internal date and by the spam, trash and draft labels,
50
+ * keeps the newest eligible messages up to the cap with ties broken by id, spends the thread's character budget
51
+ * newest first and renders the kept messages oldest first. A message's text is its sanitized header prefix followed
52
+ * by its sanitized, trimmed body, and its span covers the body alone. A message that cannot be read is counted under
53
+ * `metadata.omitted` by a fixed reason. The cache expiry is the earliest of the permission's retention, the read start
54
+ * plus `maximumCacheMs`, the response's cache headers, every kept message's window end and the label names' expiry.
55
+ *
56
+ * @param input The parsed `threads.get` response in the `full` format, from a transport that capped its bytes.
57
+ * @param options The per-read values.
58
+ * @returns A document, or a skip with a fixed reason: a thread-wide bound was exceeded, no message survived, or the
59
+ * cache policy refused durable content.
60
+ * @throws {GmailMappingFault} `configuration` for invalid options.
61
+ * @throws {SourceSyncFault} `invalid_response` for an invalid response, never an empty success; `cancelled` once the
62
+ * signal is aborted.
63
+ */
64
+ map(input: unknown, options: GmailMapThreadOptions): Promise<SourceSyncReadResult>;
65
+ }
66
+ //# sourceMappingURL=mapThread.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mapThread.d.ts","sourceRoot":"","sources":["../src/mapThread.ts"],"names":[],"mappings":"AAQA,OAAO,EAEL,KAAK,qBAAqB,EAAE,KAAK,kBAAkB,EAAE,KAAK,mBAAmB,EACjD,KAAK,oBAAoB,EACtD,MAAM,sCAAsC,CAAC;AAC9C,OAAO,EAGL,KAAK,kBAAkB,EACxB,MAAM,WAAW,CAAC;AAOnB,+GAA+G;AAC/G,MAAM,WAAW,qBAAqB;IACpC,oEAAoE;IACpE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B;;;OAGG;IACH,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,qHAAqH;IACrH,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB;;;OAGG;IACH,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,2DAA2D;IAC3D,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,gGAAgG;IAChG,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,2EAA2E;IAC3E,QAAQ,CAAC,UAAU,EAAE,qBAAqB,GAAG,IAAI,CAAC;IAClD,+CAA+C;IAC/C,QAAQ,CAAC,YAAY,EAAE,kBAAkB,CAAC;IAC1C,iEAAiE;IACjE,QAAQ,CAAC,UAAU,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACtD,gHAAgH;IAChH,QAAQ,CAAC,UAAU,EAAE,mBAAmB,GAAG,IAAI,CAAC;IAChD,sCAAsC;IACtC,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAC;CAC/B;AAyCD;;;;GAIG;AACH,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAqB;IAC5C;;;OAGG;gBACS,MAAM,EAAE,kBAAkB;IAEtC,OAAO,CAAC,MAAM;YAKA,SAAS;IAyBvB;;;;;;;;;;;;;;;OAeG;IACG,GAAG,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC,oBAAoB,CAAC;CAmFzF"}
@@ -0,0 +1,228 @@
1
+ /**
2
+ * @fileoverview Thread document mapping: one Gmail thread becomes one account-source document whose text holds each
3
+ * retained message's sanitized header prefix and trimmed body, with message ids, body spans, labels, attachment
4
+ * listings, omission counts and the earliest permitted cache expiry. The transient MIME objects are never returned or
5
+ * persisted, and the account-source store's fences still decide what is committed.
6
+ * @module agentos-ext-gmail-source/mapThread
7
+ */
8
+ import { createHash } from 'node:crypto';
9
+ import { decideSourceCache, SourceSyncFault, } from '@framers/agentos-ext-account-sources';
10
+ import { GmailMappingFault, mappingBounds, mappingActive, gmailId, parseMimeThread, decodedHeaders, decodeMimeWords, mimeBody, } from './mime.js';
11
+ import { GmailTextFault, sanitizeMailHeaders, sanitizeMailMetadata, } from './mailSanitize.js';
12
+ import { messageText } from './messageText.js';
13
+ // An epoch-millisecond value a Date can hold.
14
+ const validTime = (n) => Number.isSafeInteger(n) && n >= 0 && n <= 8_640_000_000_000_000;
15
+ const compareId = (a, b) => a < b ? -1 : a > b ? 1 : 0;
16
+ // Newest first, ties broken by id, so the selection is stable.
17
+ const newest = (a, b) => b.receivedAt - a.receivedAt || compareId(a.id, b.id);
18
+ // Clips without leaving the high half of a surrogate pair at the end.
19
+ function clip(text, maximum) {
20
+ let end = Math.min(text.length, maximum);
21
+ if (end > 0 && end < text.length && /[\uD800-\uDBFF]/.test(text[end - 1]) && /[\uDC00-\uDFFF]/.test(text[end]))
22
+ end--;
23
+ return text.slice(0, end);
24
+ }
25
+ // Refuses options that would point attribution outside the host or leave the window or the clock unbounded.
26
+ function configuration(options) {
27
+ const url = options.sourceDetailUrl;
28
+ if (!gmailId(options.sourceId) || typeof url !== 'string' || !/^\/[A-Za-z0-9_-]+(?:\/[A-Za-z0-9_-]+)*\/?$/.test(url)
29
+ || url.length > 512 || !validTime(options.cutoff) || !validTime(options.readStartedAt)
30
+ || !validTime(options.receivedAt) || options.receivedAt < options.readStartedAt || options.cutoff > options.receivedAt
31
+ || !Number.isSafeInteger(options.windowMs) || options.windowMs < 1 || options.windowMs > 90 * 86_400_000) {
32
+ throw new GmailMappingFault('configuration');
33
+ }
34
+ }
35
+ // The skip reason a refusal stands for; every other error propagates.
36
+ function mappingReason(error) {
37
+ if (error instanceof GmailMappingFault && error.reason !== 'configuration')
38
+ return error.reason;
39
+ if (error instanceof GmailTextFault && error.reason === 'input_too_large')
40
+ return 'response_too_large';
41
+ return null;
42
+ }
43
+ /**
44
+ * Maps one parsed Gmail thread into a sanitized account-source document: one thread, one document, with each retained
45
+ * message's id, dates, sanitized headers, labels, attachment listing and body span. It calls no endpoint, writes no log
46
+ * and keeps no state between calls.
47
+ */
48
+ export class GmailThreadMapper {
49
+ bounds;
50
+ /**
51
+ * @param bounds Every operational ceiling; see `GmailMappingBounds`.
52
+ * @throws {GmailMappingFault} `configuration` for an invalid bound.
53
+ */
54
+ constructor(bounds) { this.bounds = mappingBounds(bounds); }
55
+ // The sanitizer policy for one output cap.
56
+ policy(maximum) {
57
+ return { maxInputCharacters: this.bounds.maxInputCharacters,
58
+ maxLineCharacters: this.bounds.maxLineCharacters, maxOutputCharacters: Math.min(maximum, this.bounds.maxInputCharacters) };
59
+ }
60
+ // Decodes, sanitizes and trims one message; `map` counts its refusals against this message alone.
61
+ async normalize(message, budget, options) {
62
+ mappingActive(options.signal);
63
+ const metadataPolicy = this.policy(1000);
64
+ const headers = sanitizeMailHeaders(decodedHeaders(message.payload, budget), metadataPolicy);
65
+ const body = await mimeBody(message.payload, budget, options.signal);
66
+ mappingActive(options.signal);
67
+ const clean = messageText(body.text, this.policy(this.bounds.maxMessageCharacters));
68
+ const metadata = (input, maximum = 200) => sanitizeMailMetadata(decodeMimeWords(input, budget), this.policy(maximum)).text;
69
+ const attachments = body.attachments.map((attachment) => ({
70
+ filename: metadata(attachment.filename), mediaType: metadata(attachment.mediaType, 128), size: attachment.size,
71
+ }));
72
+ const labels = message.labels.map((id) => {
73
+ const permitted = options.labelCache?.kind === 'cache' && validTime(options.labelCache.expiresAt) && options.labelCache.expiresAt > options.receivedAt && options.labelCache.evidenceId.length > 0;
74
+ const raw = permitted && Object.hasOwn(options.labelNames, id) ? options.labelNames[id] : id;
75
+ if (typeof raw !== 'string')
76
+ throw new SourceSyncFault('invalid_response');
77
+ return { id, name: metadata(raw) };
78
+ });
79
+ const lines = ['subject', 'date', 'from', 'to', 'cc']
80
+ .filter((key) => headers[key] !== '').map((key) => key[0].toUpperCase() + key.slice(1) + ': ' + headers[key]);
81
+ const prefix = lines.length > 0 ? lines.join('\n') + '\n\n' : '';
82
+ if (!prefix && !clean.text)
83
+ throw new GmailMappingFault('no_eligible_content');
84
+ return { message, headers, prefix, body: clean.text,
85
+ trimmedQuote: clean.trimmedQuote, trimmedSignature: clean.trimmedSignature, truncated: clean.truncated,
86
+ attachments, labels, unsupportedParts: body.unsupportedParts };
87
+ }
88
+ /**
89
+ * Validates the whole response, filters each message by its internal date and by the spam, trash and draft labels,
90
+ * keeps the newest eligible messages up to the cap with ties broken by id, spends the thread's character budget
91
+ * newest first and renders the kept messages oldest first. A message's text is its sanitized header prefix followed
92
+ * by its sanitized, trimmed body, and its span covers the body alone. A message that cannot be read is counted under
93
+ * `metadata.omitted` by a fixed reason. The cache expiry is the earliest of the permission's retention, the read start
94
+ * plus `maximumCacheMs`, the response's cache headers, every kept message's window end and the label names' expiry.
95
+ *
96
+ * @param input The parsed `threads.get` response in the `full` format, from a transport that capped its bytes.
97
+ * @param options The per-read values.
98
+ * @returns A document, or a skip with a fixed reason: a thread-wide bound was exceeded, no message survived, or the
99
+ * cache policy refused durable content.
100
+ * @throws {GmailMappingFault} `configuration` for invalid options.
101
+ * @throws {SourceSyncFault} `invalid_response` for an invalid response, never an empty success; `cancelled` once the
102
+ * signal is aborted.
103
+ */
104
+ async map(input, options) {
105
+ configuration(options);
106
+ mappingActive(options.signal);
107
+ const skipped = (reason) => ({ kind: 'skipped', id: options.sourceId, reason });
108
+ const budget = { bounds: this.bounds, rawBytes: 0, decodedBytes: 0, parts: 0 };
109
+ let thread;
110
+ try {
111
+ thread = parseMimeThread(input, options.sourceId, budget, options.signal);
112
+ }
113
+ catch (error) {
114
+ const reason = mappingReason(error);
115
+ if (reason)
116
+ return skipped(reason);
117
+ throw error;
118
+ }
119
+ const omitted = {};
120
+ const omit = (reason, count = 1) => { if (count > 0)
121
+ omitted[reason] = (omitted[reason] ?? 0) + count; };
122
+ const eligible = [];
123
+ for (const message of thread.messages) {
124
+ if (message.receivedAt > options.cutoff || message.receivedAt <= options.cutoff - options.windowMs
125
+ || !validTime(message.receivedAt + options.windowMs) || message.receivedAt + options.windowMs <= options.receivedAt) {
126
+ omit('out_of_window');
127
+ continue;
128
+ }
129
+ if (message.labels.some((label) => ['SPAM', 'TRASH', 'DRAFT'].includes(label))) {
130
+ omit('excluded_label');
131
+ continue;
132
+ }
133
+ eligible.push(message);
134
+ }
135
+ eligible.sort(newest);
136
+ const selected = eligible.slice(0, this.bounds.maxMessages);
137
+ omit('message_limit', eligible.length - selected.length);
138
+ const retained = [];
139
+ let used = 0;
140
+ let lastReason = 'no_eligible_content';
141
+ for (const message of selected) {
142
+ mappingActive(options.signal);
143
+ const remaining = this.bounds.maxThreadCharacters - used - (retained.length ? 2 : 0);
144
+ if (remaining <= 0) {
145
+ omit('thread_limit');
146
+ continue;
147
+ }
148
+ let normalized;
149
+ try {
150
+ normalized = await this.normalize(message, budget, options);
151
+ }
152
+ catch (error) {
153
+ const reason = mappingReason(error);
154
+ if (!reason)
155
+ throw error;
156
+ lastReason = reason;
157
+ omit(reason);
158
+ continue;
159
+ }
160
+ mappingActive(options.signal);
161
+ const maximum = Math.min(this.bounds.maxMessageCharacters, remaining);
162
+ if (normalized.prefix.length > maximum) {
163
+ lastReason = 'structure_limit';
164
+ omit('thread_limit');
165
+ continue;
166
+ }
167
+ const body = clip(normalized.body, maximum - normalized.prefix.length);
168
+ const text = normalized.prefix + body;
169
+ if (!text) {
170
+ lastReason = 'no_eligible_content';
171
+ omit(lastReason);
172
+ continue;
173
+ }
174
+ retained.push({ normalized, text, bodyStart: normalized.prefix.length,
175
+ truncated: normalized.truncated || body.length < normalized.body.length });
176
+ used += text.length + (retained.length > 1 ? 2 : 0);
177
+ }
178
+ if (retained.length === 0) {
179
+ if (eligible.length === 0)
180
+ lastReason = omitted.excluded_label ? 'excluded_label' : omitted.out_of_window ? 'out_of_window' : lastReason;
181
+ return skipped(lastReason);
182
+ }
183
+ retained.sort((a, b) => a.normalized.message.receivedAt - b.normalized.message.receivedAt
184
+ || compareId(a.normalized.message.id, b.normalized.message.id));
185
+ const messages = [];
186
+ const metadataMessages = [];
187
+ const texts = [];
188
+ let offset = 0;
189
+ for (const kept of retained) {
190
+ const { normalized } = kept;
191
+ const { message, headers } = normalized;
192
+ if (texts.length)
193
+ offset += 2;
194
+ messages.push({ messageId: message.id, start: offset + kept.bodyStart, end: offset + kept.text.length,
195
+ receivedAt: message.receivedAt, windowExpiresAt: message.receivedAt + options.windowMs, truncated: kept.truncated });
196
+ metadataMessages.push({ messageId: message.id, headers: { ...headers }, labels: normalized.labels,
197
+ attachments: normalized.attachments, trimmedQuote: normalized.trimmedQuote,
198
+ trimmedSignature: normalized.trimmedSignature, unsupportedParts: normalized.unsupportedParts });
199
+ texts.push(kept.text);
200
+ offset += kept.text.length;
201
+ }
202
+ const metadata = { messages: metadataMessages,
203
+ omitted: Object.fromEntries(Object.entries(omitted).sort(([a], [b]) => compareId(a, b))),
204
+ attachmentsRead: false };
205
+ const metadataJson = JSON.stringify(metadata);
206
+ if (metadataJson.length > this.bounds.maxMetadataCharacters)
207
+ return skipped('structure_limit');
208
+ const cache = decideSourceCache({ permission: options.permission, maximumCacheMs: this.bounds.maximumCacheMs,
209
+ readStartedAt: options.readStartedAt, receivedAt: options.receivedAt,
210
+ windowExpiresAt: Math.min(...messages.map((m) => m.windowExpiresAt)), headers: options.cacheHeaders });
211
+ if (cache.kind === 'skip')
212
+ return skipped(cache.reason);
213
+ const labelExpiry = options.labelCache?.kind === 'cache' && options.labelCache.expiresAt > options.receivedAt ? options.labelCache.expiresAt : cache.expiresAt;
214
+ const allowedCache = { ...cache, expiresAt: Math.min(cache.expiresAt, labelExpiry) };
215
+ const text = texts.join('\n\n');
216
+ const contentHash = createHash('sha256').update(JSON.stringify({ text, metadata, messages })).digest('hex');
217
+ const version = thread.historyId + ':' + contentHash;
218
+ const mostRecent = [...retained].sort((a, b) => newest(a.normalized.message, b.normalized.message));
219
+ const title = mostRecent.find((m) => m.normalized.headers.subject)?.normalized.headers.subject || 'Mail thread';
220
+ mappingActive(options.signal);
221
+ return { kind: 'document', document: {
222
+ read: { item: { id: thread.id, title, size: text.length, version }, content: { text },
223
+ ref: { kind: 'gmail', title, url: options.sourceDetailUrl, version, readAt: new Date(options.receivedAt).toISOString() } },
224
+ messages, metadata, activityAt: Math.max(...messages.map((m) => m.receivedAt)), contentHash, cache: allowedCache,
225
+ } };
226
+ }
227
+ }
228
+ //# sourceMappingURL=mapThread.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mapThread.js","sourceRoot":"","sources":["../src/mapThread.ts"],"names":[],"mappings":"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"}
package/dist/mime.d.ts ADDED
@@ -0,0 +1,141 @@
1
+ import { type SourceSyncSkipReason } from '@framers/agentos-ext-account-sources';
2
+ import type { GmailHeaderInput } from './mailSanitize.js';
3
+ /**
4
+ * The ceilings one mapper enforces, each a positive safe integer no greater than the value in brackets. They are
5
+ * operating choices, not Gmail service limits.
6
+ */
7
+ export interface GmailMappingBounds {
8
+ /** Bytes of recognized strings read from one parsed thread response (2,097,152). */
9
+ readonly maxResponseBytes: number;
10
+ /** Bytes decoded from bodies and encoded header words in one thread (2,097,152). */
11
+ readonly maxDecodedBytes: number;
12
+ /** MIME nesting depth, a message's payload being level 1 (20). */
13
+ readonly maxMimeDepth: number;
14
+ /** MIME parts across every message of the thread, and the entries any one list may hold (1,000). */
15
+ readonly maxMimeParts: number;
16
+ /** Messages retained in one thread document, newest first (100). */
17
+ readonly maxMessages: number;
18
+ /** UTF-16 code units of one message's header prefix and body together (20,000). */
19
+ readonly maxMessageCharacters: number;
20
+ /** UTF-16 code units of the thread document's text, separators included (200,000). */
21
+ readonly maxThreadCharacters: number;
22
+ /** Characters of the document's serialized metadata (200,000). */
23
+ readonly maxMetadataCharacters: number;
24
+ /** Characters one string may hold before or after decoding, and the sanitizer's input cap (2,097,152). */
25
+ readonly maxInputCharacters: number;
26
+ /** The sanitizer's line cap: a longer line is suppressed (65,536). */
27
+ readonly maxLineCharacters: number;
28
+ /** Cache lifetime in milliseconds a document may receive before permission and response limits (86,400,000). */
29
+ readonly maximumCacheMs: number;
30
+ }
31
+ /**
32
+ * A mapper's fixed refusal; its message is `gmail_mapping_<reason>` and never carries mail text. `configuration` is
33
+ * thrown for invalid bounds or options. `map` catches every other reason and answers it as a skipped thread, or counts
34
+ * it against the one message it concerns.
35
+ */
36
+ export declare class GmailMappingFault extends Error {
37
+ readonly reason: 'configuration' | SourceSyncSkipReason;
38
+ /** @param reason `configuration`, or the skip reason the refusal stands for. */
39
+ constructor(reason: 'configuration' | SourceSyncSkipReason);
40
+ }
41
+ /** One MIME part as this package reads it. Internal: never persisted and not exported from the package root. */
42
+ export interface MimePart {
43
+ /** The media type in lower case. */
44
+ readonly mimeType: string;
45
+ /** Gmail's filename for the part; empty when there is none. */
46
+ readonly filename: string;
47
+ readonly headers: readonly GmailHeaderInput[];
48
+ /** Gmail's decoded byte count of the body. */
49
+ readonly size: number;
50
+ /** The base64url body, kept only for a text/plain or text/html part outside every attachment; otherwise empty. */
51
+ readonly data: string;
52
+ /** Whether the body sits behind an attachment id. */
53
+ readonly external: boolean;
54
+ /** Whether the part is listed as an attachment instead of read. */
55
+ readonly attachment: boolean;
56
+ readonly parts: readonly MimePart[];
57
+ }
58
+ /** One message's protocol fields. Internal. */
59
+ export interface MimeMessage {
60
+ readonly id: string;
61
+ /** Gmail's `internalDate`, epoch milliseconds. */
62
+ readonly receivedAt: number;
63
+ /** Label ids, unique and sorted. */
64
+ readonly labels: readonly string[];
65
+ readonly payload: MimePart;
66
+ }
67
+ /** One thread's protocol fields. Internal. */
68
+ export interface MimeThread {
69
+ readonly id: string;
70
+ /** The thread's history value, decimal digits. */
71
+ readonly historyId: string;
72
+ readonly messages: readonly MimeMessage[];
73
+ }
74
+ /** An attachment as listed: its contents are never read. Internal. */
75
+ export interface MimeAttachment {
76
+ readonly filename: string;
77
+ readonly mediaType: string;
78
+ readonly size: number;
79
+ }
80
+ /** A message body before sanitization, with its attachment list. Internal. */
81
+ export interface MimeBody {
82
+ readonly text: string;
83
+ readonly attachments: readonly MimeAttachment[];
84
+ /** Parts whose media type is not read, and alternatives that offered no readable branch. */
85
+ readonly unsupportedParts: number;
86
+ }
87
+ /** The running counts of one `map` call, checked against its bounds. Internal. */
88
+ export interface MimeBudget {
89
+ readonly bounds: GmailMappingBounds;
90
+ rawBytes: number;
91
+ decodedBytes: number;
92
+ parts: number;
93
+ }
94
+ /** Whether a value is an accepted Gmail message or thread id: 1 to 64 hexadecimal characters. */
95
+ export declare const gmailId: (value: unknown) => value is string;
96
+ /** Throws `SourceSyncFault('cancelled')` once the signal is aborted. */
97
+ export declare function mappingActive(signal?: AbortSignal): void;
98
+ /**
99
+ * Validates and freezes a mapper's bounds.
100
+ *
101
+ * @throws {GmailMappingFault} `configuration` when a bound is not a positive safe integer or exceeds its ceiling, or
102
+ * when the message or thread character cap exceeds the input cap.
103
+ */
104
+ export declare function mappingBounds(input: GmailMappingBounds): GmailMappingBounds;
105
+ /**
106
+ * Validate the whole structure before decoding any selected message. Copies only the fields this package reads: ids,
107
+ * internal dates, labels and each payload's MIME tree. Every message's tree, excluded messages included, counts against
108
+ * the byte, depth and part bounds. `raw`, `snippet` and unknown fields are never read.
109
+ *
110
+ * @param value The parsed `threads.get` response.
111
+ * @param sourceId The thread id the caller asked for; any other id is an invalid response.
112
+ * @param budget The call's running counts.
113
+ * @param signal Checked before each part.
114
+ * @throws {SourceSyncFault} `invalid_response` for an invalid shape, id, history value, date, label, media type or a
115
+ * repeated message id; `cancelled` once the signal is aborted.
116
+ * @throws {GmailMappingFault} `response_too_large` or `structure_limit` when a bound is exceeded.
117
+ */
118
+ export declare function parseMimeThread(value: unknown, sourceId: string, budget: MimeBudget, signal?: AbortSignal): MimeThread;
119
+ /**
120
+ * Decoding is followed by sanitation even when the input looked like ASCII. Decodes the RFC 2047 encoded words (B and
121
+ * Q) of one header value with a fatal decoder for each declared charset; whitespace between adjacent encoded words is
122
+ * dropped, as RFC 2047 requires.
123
+ *
124
+ * @throws {GmailMappingFault} `invalid_encoding` for a malformed or overlong word, invalid bytes or a value that still
125
+ * holds an encoded-word opener after decoding; `unsupported_charset` for a charset the runtime does not decode;
126
+ * `response_too_large` above the character or decoded-byte bound.
127
+ */
128
+ export declare function decodeMimeWords(input: string, budget: MimeBudget): string;
129
+ /** A part's Subject, Date, From, To and Cc, decoded; Bcc and every other header are never decoded or returned. */
130
+ export declare function decodedHeaders(part: MimePart, budget: MimeBudget): readonly GmailHeaderInput[];
131
+ /**
132
+ * Select before decoding, and never interpret Content-Transfer-Encoding a second time: Gmail's `data` already holds the
133
+ * part's bytes. Lists the message's attachments and builds its body text. Within `multipart/alternative` the branch
134
+ * with eligible plain text wins over HTML; other multipart containers join their text children in MIME order. HTML
135
+ * becomes inert text through `HtmlLoader` given an in-memory Buffer. Other media types are counted, not read.
136
+ *
137
+ * @throws {GmailMappingFault} `invalid_encoding`, `unsupported_charset` or `response_too_large` for the message.
138
+ * @throws {SourceSyncFault} `cancelled` once the signal is aborted.
139
+ */
140
+ export declare function mimeBody(root: MimePart, budget: MimeBudget, signal?: AbortSignal): Promise<MimeBody>;
141
+ //# sourceMappingURL=mime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mime.d.ts","sourceRoot":"","sources":["../src/mime.ts"],"names":[],"mappings":"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"}
package/dist/mime.js ADDED
@@ -0,0 +1,377 @@
1
+ /**
2
+ * @fileoverview Bounded reading of one Gmail `threads.get` response in the `full` format. The MIME tree of every
3
+ * message, excluded messages included, is checked against byte, depth and part bounds before any body is decoded. One
4
+ * representation is selected per `multipart/alternative`; base64url bodies, RFC 2047 encoded words and declared charsets
5
+ * are decoded strictly; HTML becomes inert text through the AgentOS `HtmlLoader`. An attachment keeps only its name,
6
+ * media type and size: its bytes are dropped while the tree is read, whether Gmail returned them inline or behind an
7
+ * attachment id. Nothing here fetches, logs or puts provider text into an error.
8
+ * @module agentos-ext-gmail-source/mime
9
+ */
10
+ import { HtmlLoader } from '@framers/agentos/cognition/memory';
11
+ import { SourceSyncFault } from '@framers/agentos-ext-account-sources';
12
+ /**
13
+ * A mapper's fixed refusal; its message is `gmail_mapping_<reason>` and never carries mail text. `configuration` is
14
+ * thrown for invalid bounds or options. `map` catches every other reason and answers it as a skipped thread, or counts
15
+ * it against the one message it concerns.
16
+ */
17
+ export class GmailMappingFault extends Error {
18
+ reason;
19
+ /** @param reason `configuration`, or the skip reason the refusal stands for. */
20
+ constructor(reason) {
21
+ super(`gmail_mapping_${reason}`);
22
+ this.reason = reason;
23
+ this.name = 'GmailMappingFault';
24
+ }
25
+ }
26
+ // An invalid provider shape is a fixed failure, never an empty success.
27
+ const fail = () => { throw new SourceSyncFault('invalid_response'); };
28
+ const integer = (n) => typeof n === 'number' && Number.isSafeInteger(n) && n >= 0;
29
+ /** Whether a value is an accepted Gmail message or thread id: 1 to 64 hexadecimal characters. */
30
+ export const gmailId = (value) => typeof value === 'string' && /^[a-fA-F0-9]{1,64}$/.test(value);
31
+ // Accepted label ids: system labels in upper case and user labels as Label_ and digits.
32
+ const labelId = (value) => typeof value === 'string'
33
+ && /^(?:[A-Z][A-Z0-9_]{0,63}|Label_[0-9]{1,64})$/.test(value);
34
+ /** Throws `SourceSyncFault('cancelled')` once the signal is aborted. */
35
+ export function mappingActive(signal) {
36
+ if (signal?.aborted)
37
+ throw new SourceSyncFault('cancelled');
38
+ }
39
+ /**
40
+ * Validates and freezes a mapper's bounds.
41
+ *
42
+ * @throws {GmailMappingFault} `configuration` when a bound is not a positive safe integer or exceeds its ceiling, or
43
+ * when the message or thread character cap exceeds the input cap.
44
+ */
45
+ export function mappingBounds(input) {
46
+ const ceilings = {
47
+ maxResponseBytes: 2_097_152, maxDecodedBytes: 2_097_152,
48
+ maxMimeDepth: 20, maxMimeParts: 1000, maxMessages: 100,
49
+ maxMessageCharacters: 20_000, maxThreadCharacters: 200_000,
50
+ maxMetadataCharacters: 200_000, maxInputCharacters: 2_097_152,
51
+ maxLineCharacters: 65_536, maximumCacheMs: 86_400_000,
52
+ };
53
+ for (const key of Object.keys(ceilings)) {
54
+ if (!integer(input[key]) || input[key] < 1 || input[key] > ceilings[key])
55
+ throw new GmailMappingFault('configuration');
56
+ }
57
+ if (input.maxMessageCharacters > input.maxInputCharacters || input.maxThreadCharacters > input.maxInputCharacters) {
58
+ throw new GmailMappingFault('configuration');
59
+ }
60
+ return Object.freeze({ ...input });
61
+ }
62
+ // Shape readers. A wrong type is an invalid response; every string read is charged to the recognized-input budget.
63
+ function object(value) {
64
+ if (!value || typeof value !== 'object' || Array.isArray(value))
65
+ return fail();
66
+ return value;
67
+ }
68
+ function string(value, budget) {
69
+ if (typeof value !== 'string')
70
+ return fail();
71
+ if (value.length > budget.bounds.maxInputCharacters)
72
+ throw new GmailMappingFault('response_too_large');
73
+ budget.rawBytes += Buffer.byteLength(value, 'utf8');
74
+ if (budget.rawBytes > budget.bounds.maxResponseBytes)
75
+ throw new GmailMappingFault('response_too_large');
76
+ return value;
77
+ }
78
+ function array(value, maximum) {
79
+ if (!Array.isArray(value))
80
+ return fail();
81
+ if (value.length > maximum)
82
+ throw new GmailMappingFault('structure_limit');
83
+ return value;
84
+ }
85
+ // Reads one part and its children. `withinAttachment` marks the subtree of an attachment, such as an attached message.
86
+ function parsePart(value, budget, depth, signal, withinAttachment = false) {
87
+ mappingActive(signal);
88
+ if (depth > budget.bounds.maxMimeDepth || ++budget.parts > budget.bounds.maxMimeParts) {
89
+ throw new GmailMappingFault('structure_limit');
90
+ }
91
+ const raw = object(value);
92
+ const mimeType = string(raw.mimeType ?? 'application/octet-stream', budget).toLowerCase();
93
+ if (!/^[a-z0-9!#$&^_.+-]{1,64}\/[a-z0-9!#$&^_.+-]{1,64}$/.test(mimeType))
94
+ return fail();
95
+ const filename = string(raw.filename ?? '', budget);
96
+ const headers = array(raw.headers ?? [], budget.bounds.maxMimeParts).map((value) => {
97
+ const h = object(value);
98
+ return { name: string(h.name, budget), value: string(h.value, budget) };
99
+ });
100
+ const body = object(raw.body ?? {});
101
+ const size = body.size ?? 0;
102
+ if (!integer(size))
103
+ return fail();
104
+ const data = string(body.data ?? '', budget);
105
+ const attachmentId = body.attachmentId === undefined ? '' : string(body.attachmentId, budget);
106
+ const disposition = headers.filter((h) => h.name.toLowerCase() === 'content-disposition');
107
+ if (disposition.length > 1)
108
+ return fail();
109
+ const attachment = filename !== '' || attachmentId !== ''
110
+ || /^\s*attachment(?:\s*;|\s*$)/i.test(disposition[0]?.value ?? '') || mimeType === 'message/rfc822';
111
+ const children = array(raw.parts ?? [], budget.bounds.maxMimeParts);
112
+ if (children.length > 0 && !mimeType.startsWith('multipart/') && mimeType !== 'message/rfc822')
113
+ return fail();
114
+ // Only a text body outside every attachment keeps its encoded data. Attachment bytes, which Gmail returns inline in
115
+ // `data` whenever a part has no attachment id, and every other part's bytes are dropped here, before any decoding.
116
+ const readable = !attachment && !withinAttachment && (mimeType === 'text/plain' || mimeType === 'text/html');
117
+ return { mimeType, filename, headers, size, data: readable ? data : '', external: attachmentId !== '', attachment,
118
+ parts: children.map((child) => parsePart(child, budget, depth + 1, signal, withinAttachment || attachment)) };
119
+ }
120
+ /**
121
+ * Validate the whole structure before decoding any selected message. Copies only the fields this package reads: ids,
122
+ * internal dates, labels and each payload's MIME tree. Every message's tree, excluded messages included, counts against
123
+ * the byte, depth and part bounds. `raw`, `snippet` and unknown fields are never read.
124
+ *
125
+ * @param value The parsed `threads.get` response.
126
+ * @param sourceId The thread id the caller asked for; any other id is an invalid response.
127
+ * @param budget The call's running counts.
128
+ * @param signal Checked before each part.
129
+ * @throws {SourceSyncFault} `invalid_response` for an invalid shape, id, history value, date, label, media type or a
130
+ * repeated message id; `cancelled` once the signal is aborted.
131
+ * @throws {GmailMappingFault} `response_too_large` or `structure_limit` when a bound is exceeded.
132
+ */
133
+ export function parseMimeThread(value, sourceId, budget, signal) {
134
+ mappingActive(signal);
135
+ const raw = object(value);
136
+ const id = string(raw.id, budget);
137
+ const historyId = string(raw.historyId, budget);
138
+ if (!gmailId(id) || id !== sourceId || !/^[0-9]{1,128}$/.test(historyId))
139
+ return fail();
140
+ const seen = new Set();
141
+ const messages = array(raw.messages ?? [], budget.bounds.maxMimeParts).map((value) => {
142
+ const m = object(value);
143
+ const messageId = string(m.id, budget);
144
+ const parentId = string(m.threadId, budget);
145
+ const timestamp = string(m.internalDate, budget);
146
+ if (!gmailId(messageId) || seen.has(messageId) || parentId !== id || !/^[0-9]{1,16}$/.test(timestamp))
147
+ return fail();
148
+ const receivedAt = Number(timestamp);
149
+ if (!integer(receivedAt))
150
+ return fail();
151
+ seen.add(messageId);
152
+ const labels = array(m.labelIds ?? [], budget.bounds.maxMimeParts).map((value) => {
153
+ const label = string(value, budget);
154
+ if (!labelId(label))
155
+ return fail();
156
+ return label;
157
+ });
158
+ return { id: messageId, receivedAt, labels: [...new Set(labels)].sort(), payload: parsePart(m.payload, budget, 1, signal) };
159
+ });
160
+ return { id, historyId, messages };
161
+ }
162
+ // Charges decoded bytes to the call's budget.
163
+ function charge(bytes, budget) {
164
+ budget.decodedBytes += bytes.byteLength;
165
+ if (budget.decodedBytes > budget.bounds.maxDecodedBytes)
166
+ throw new GmailMappingFault('response_too_large');
167
+ return bytes;
168
+ }
169
+ // Strict base64 or base64url: the alphabet and padding are checked and the size is charged before decoding, and the
170
+ // bytes must encode back to the same text, so a noncanonical final character is refused.
171
+ function base64(value, url, budget) {
172
+ const alphabet = url ? /^[A-Za-z0-9_-]*={0,2}$/ : /^[A-Za-z0-9+/]*={0,2}$/;
173
+ if (!alphabet.test(value))
174
+ throw new GmailMappingFault('invalid_encoding');
175
+ const bare = value.replace(/=+$/, '');
176
+ const padding = value.length - bare.length;
177
+ if (bare.length % 4 === 1 || (padding > 0 && (value.length % 4 !== 0 || padding !== (4 - bare.length % 4) % 4))) {
178
+ throw new GmailMappingFault('invalid_encoding');
179
+ }
180
+ const bytesNeeded = Math.floor(bare.length * 6 / 8);
181
+ if (budget.decodedBytes + bytesNeeded > budget.bounds.maxDecodedBytes)
182
+ throw new GmailMappingFault('response_too_large');
183
+ const bytes = Buffer.from(bare, url ? 'base64url' : 'base64');
184
+ if (bytes.toString(url ? 'base64url' : 'base64').replace(/=+$/, '') !== bare)
185
+ throw new GmailMappingFault('invalid_encoding');
186
+ return charge(bytes, budget);
187
+ }
188
+ // A fatal decoder: an unknown charset and invalid bytes are separate fixed reasons, and nothing is replaced.
189
+ function decode(bytes, charset) {
190
+ let decoder;
191
+ try {
192
+ decoder = new TextDecoder(charset, { fatal: true });
193
+ }
194
+ catch {
195
+ throw new GmailMappingFault('unsupported_charset');
196
+ }
197
+ try {
198
+ return decoder.decode(bytes);
199
+ }
200
+ catch {
201
+ throw new GmailMappingFault('invalid_encoding');
202
+ }
203
+ }
204
+ /**
205
+ * Decoding is followed by sanitation even when the input looked like ASCII. Decodes the RFC 2047 encoded words (B and
206
+ * Q) of one header value with a fatal decoder for each declared charset; whitespace between adjacent encoded words is
207
+ * dropped, as RFC 2047 requires.
208
+ *
209
+ * @throws {GmailMappingFault} `invalid_encoding` for a malformed or overlong word, invalid bytes or a value that still
210
+ * holds an encoded-word opener after decoding; `unsupported_charset` for a charset the runtime does not decode;
211
+ * `response_too_large` above the character or decoded-byte bound.
212
+ */
213
+ export function decodeMimeWords(input, budget) {
214
+ if (input.length > budget.bounds.maxInputCharacters)
215
+ throw new GmailMappingFault('response_too_large');
216
+ const pattern = /=\?([^?\s]{1,40})\?([bq])\?([^?\r\n]*)\?=/gi;
217
+ let result = '';
218
+ let end = 0;
219
+ let previousWord = false;
220
+ for (const match of input.matchAll(pattern)) {
221
+ const start = match.index;
222
+ const between = input.slice(end, start);
223
+ if (match[0].length > 75)
224
+ throw new GmailMappingFault('invalid_encoding');
225
+ if (!(previousWord && /^[ \t\r\n]*$/.test(between)))
226
+ result += between;
227
+ let bytes;
228
+ if (match[2].toLowerCase() === 'b')
229
+ bytes = base64(match[3], false, budget);
230
+ else {
231
+ const encoded = match[3];
232
+ const values = [];
233
+ for (let i = 0; i < encoded.length; i++) {
234
+ const character = encoded[i];
235
+ if (character === '=') {
236
+ const hex = encoded.slice(i + 1, i + 3);
237
+ if (!/^[0-9a-f]{2}$/i.test(hex))
238
+ throw new GmailMappingFault('invalid_encoding');
239
+ values.push(Number.parseInt(hex, 16));
240
+ i += 2;
241
+ }
242
+ else {
243
+ const point = character.charCodeAt(0);
244
+ if (point < 33 || point > 126 || character === '?')
245
+ throw new GmailMappingFault('invalid_encoding');
246
+ values.push(character === '_' ? 32 : point);
247
+ }
248
+ }
249
+ bytes = charge(Uint8Array.from(values), budget);
250
+ }
251
+ result += decode(bytes, match[1]);
252
+ end = start + match[0].length;
253
+ previousWord = true;
254
+ if (result.length > budget.bounds.maxInputCharacters)
255
+ throw new GmailMappingFault('response_too_large');
256
+ }
257
+ result += input.slice(end);
258
+ if (result.includes('=?') || result.length > budget.bounds.maxInputCharacters)
259
+ throw new GmailMappingFault('invalid_encoding');
260
+ return result;
261
+ }
262
+ /** A part's Subject, Date, From, To and Cc, decoded; Bcc and every other header are never decoded or returned. */
263
+ export function decodedHeaders(part, budget) {
264
+ return part.headers.filter((h) => ['subject', 'date', 'from', 'to', 'cc'].includes(h.name.toLowerCase()))
265
+ .map((h) => ({ name: h.name, value: decodeMimeWords(h.value, budget) }));
266
+ }
267
+ // A text part's one declared charset, UTF-8 when none is declared; a repeated or malformed parameter refuses the part.
268
+ function charset(part) {
269
+ const values = part.headers.filter((h) => h.name.toLowerCase() === 'content-type');
270
+ if (values.length > 1)
271
+ throw new GmailMappingFault('invalid_encoding');
272
+ const header = values[0]?.value ?? part.mimeType;
273
+ const parameters = [...header.matchAll(/;\s*charset\s*=\s*(?:"([^"\r\n]*)"|([^;\s]+))/gi)];
274
+ const mentions = header.match(/\bcharset\s*=/gi)?.length ?? 0;
275
+ if (parameters.length !== mentions || parameters.length > 1)
276
+ throw new GmailMappingFault('invalid_encoding');
277
+ const value = (parameters[0]?.[1] ?? parameters[0]?.[2] ?? 'utf-8').trim();
278
+ if (!/^[a-z0-9._:-]{1,40}$/i.test(value))
279
+ throw new GmailMappingFault('unsupported_charset');
280
+ return value;
281
+ }
282
+ // The best body a subtree offers: plain text 2, HTML 1, nothing readable 0.
283
+ function rank(part) {
284
+ if (part.attachment)
285
+ return 0;
286
+ if (part.mimeType === 'text/plain')
287
+ return 2;
288
+ if (part.mimeType === 'text/html')
289
+ return 1;
290
+ return part.parts.reduce((best, child) => Math.max(best, rank(child)), 0);
291
+ }
292
+ // Lists attachment parts in MIME order without descending into them.
293
+ function attachments(part, output) {
294
+ if (part.attachment) {
295
+ output.push({ filename: part.filename || 'attachment', mediaType: part.mimeType, size: part.size });
296
+ return;
297
+ }
298
+ for (const child of part.parts)
299
+ attachments(child, output);
300
+ }
301
+ /**
302
+ * Select before decoding, and never interpret Content-Transfer-Encoding a second time: Gmail's `data` already holds the
303
+ * part's bytes. Lists the message's attachments and builds its body text. Within `multipart/alternative` the branch
304
+ * with eligible plain text wins over HTML; other multipart containers join their text children in MIME order. HTML
305
+ * becomes inert text through `HtmlLoader` given an in-memory Buffer. Other media types are counted, not read.
306
+ *
307
+ * @throws {GmailMappingFault} `invalid_encoding`, `unsupported_charset` or `response_too_large` for the message.
308
+ * @throws {SourceSyncFault} `cancelled` once the signal is aborted.
309
+ */
310
+ export async function mimeBody(root, budget, signal) {
311
+ const listed = [];
312
+ attachments(root, listed);
313
+ let unsupportedParts = 0;
314
+ const text = async (part) => {
315
+ mappingActive(signal);
316
+ if (part.attachment)
317
+ return '';
318
+ if (part.mimeType === 'multipart/alternative') {
319
+ let chosen;
320
+ let best = 0;
321
+ for (const child of part.parts) {
322
+ const score = rank(child);
323
+ if (score > best) {
324
+ chosen = child;
325
+ best = score;
326
+ }
327
+ }
328
+ if (!chosen) {
329
+ unsupportedParts++;
330
+ return '';
331
+ }
332
+ return text(chosen);
333
+ }
334
+ if (part.mimeType.startsWith('multipart/')) {
335
+ const chunks = [];
336
+ let characters = 0;
337
+ for (const child of part.parts) {
338
+ const value = await text(child);
339
+ mappingActive(signal);
340
+ if (!value)
341
+ continue;
342
+ characters += value.length + (chunks.length ? 2 : 0);
343
+ if (characters > budget.bounds.maxInputCharacters)
344
+ throw new GmailMappingFault('response_too_large');
345
+ chunks.push(value);
346
+ }
347
+ return chunks.join('\n\n');
348
+ }
349
+ if (!['text/plain', 'text/html'].includes(part.mimeType)) {
350
+ unsupportedParts++;
351
+ return '';
352
+ }
353
+ const bytes = base64(part.data, true, budget);
354
+ if (bytes.byteLength !== part.size)
355
+ throw new GmailMappingFault('invalid_encoding');
356
+ const decoded = decode(bytes, charset(part));
357
+ if (decoded.length > budget.bounds.maxInputCharacters)
358
+ throw new GmailMappingFault('response_too_large');
359
+ if (part.mimeType === 'text/plain')
360
+ return decoded;
361
+ let content;
362
+ try {
363
+ content = (await new HtmlLoader().load(Buffer.from(decoded, 'utf8'))).content;
364
+ }
365
+ catch {
366
+ throw new GmailMappingFault('invalid_encoding');
367
+ }
368
+ mappingActive(signal);
369
+ if (content.length > budget.bounds.maxInputCharacters)
370
+ throw new GmailMappingFault('response_too_large');
371
+ return content;
372
+ };
373
+ const body = await text(root);
374
+ mappingActive(signal);
375
+ return { text: body, attachments: listed, unsupportedParts };
376
+ }
377
+ //# sourceMappingURL=mime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mime.js","sourceRoot":"","sources":["../src/mime.ts"],"names":[],"mappings":"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"}
package/manifest.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "$schema": "https://agentos.sh/schemas/extension-manifest-v1.json",
3
3
  "id": "com.framers.productivity.gmail-source",
4
4
  "name": "Gmail Source",
5
- "version": "0.2.0",
5
+ "version": "0.3.0",
6
6
  "description": "Read-only OAuth and bounded personal Gmail source helpers",
7
7
  "author": {
8
8
  "name": "Frame",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@framers/agentos-ext-gmail-source",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "Read-only OAuth and bounded personal Gmail source helpers",
5
5
  "type": "module",
6
6
  "sideEffects": false,