@framers/agentos-ext-gmail-source 0.2.0 → 0.4.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 +75 -2
- package/dist/gmail.d.ts +182 -0
- package/dist/gmail.d.ts.map +1 -0
- package/dist/gmail.js +568 -0
- package/dist/gmail.js.map +1 -0
- package/dist/index.d.ts +8 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -2
- package/dist/index.js.map +1 -1
- package/dist/mapThread.d.ts +66 -0
- package/dist/mapThread.d.ts.map +1 -0
- package/dist/mapThread.js +228 -0
- package/dist/mapThread.js.map +1 -0
- package/dist/mime.d.ts +141 -0
- package/dist/mime.d.ts.map +1 -0
- package/dist/mime.js +377 -0
- package/dist/mime.js.map +1 -0
- package/dist/retry.d.ts +44 -0
- package/dist/retry.d.ts.map +1 -0
- package/dist/retry.js +102 -0
- package/dist/retry.js.map +1 -0
- package/manifest.json +1 -1
- package/package.json +2 -2
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
|
package/dist/mime.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mime.js","sourceRoot":"","sources":["../src/mime.ts"],"names":[],"mappings":"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"}
|
package/dist/retry.d.ts
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { SourceSyncFault, type SourceQuotaMethod, type SourceSyncFailureCode } from '@framers/agentos-ext-account-sources';
|
|
2
|
+
/**
|
|
3
|
+
* What one Gmail API answer calls for: `ok` for a success; `refresh` for a 401, which earns one fresh access token and
|
|
4
|
+
* one repeat of the same call; `gone` for a canonical thread read's 404; `retry` for a rate limit or a server failure,
|
|
5
|
+
* with the scope its wait applies to and whether it is the provider's daily limit; `fault` for a fixed failure.
|
|
6
|
+
*/
|
|
7
|
+
export type GmailHttpDisposition = {
|
|
8
|
+
readonly kind: 'ok' | 'refresh' | 'gone';
|
|
9
|
+
} | {
|
|
10
|
+
readonly kind: 'retry';
|
|
11
|
+
readonly code: 'rate_limited' | 'provider_unavailable';
|
|
12
|
+
readonly scope: 'project' | 'mailbox';
|
|
13
|
+
readonly daily: boolean;
|
|
14
|
+
} | {
|
|
15
|
+
readonly kind: 'fault';
|
|
16
|
+
readonly code: SourceSyncFailureCode;
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Classifies one Gmail API answer by its status and, for a 403, the exact reason tokens of at most 32 error entries.
|
|
20
|
+
* A 429 or 5xx is retried whether or not its body parses. A 403 `domainPolicy` wins over any other reason, then
|
|
21
|
+
* `insufficientPermissions`, `dailyLimitExceeded` (the whole project, daily), `rateLimitExceeded` (the whole project)
|
|
22
|
+
* and `userRateLimitExceeded` (the mailbox). A 404 is `gone` for a thread read and `history_expired` for a history
|
|
23
|
+
* page. Any other answer, an unknown reason included, is the fixed `invalid_response`, never an inferred grant loss.
|
|
24
|
+
* Only exact reason tokens influence policy. Provider text never leaves this function.
|
|
25
|
+
*
|
|
26
|
+
* @param status The HTTP status.
|
|
27
|
+
* @param body The answer's parsed JSON, or null when it did not parse.
|
|
28
|
+
* @param method The kind of call that was answered.
|
|
29
|
+
*/
|
|
30
|
+
export declare function classifyGmailHttp(status: number, body: unknown, method: SourceQuotaMethod): GmailHttpDisposition;
|
|
31
|
+
/**
|
|
32
|
+
* Translates a failure of an OAuth grant operation into a fixed account-source fault. A missing grant or Google's
|
|
33
|
+
* `invalid_grant` is `grant_rejected` and `invalid_scope` or a scope check is `insufficient_scope`, the two that start
|
|
34
|
+
* the coordinator's fenced grant-loss lifecycle; a 429 is `rate_limited`; a 5xx, `server_error` or
|
|
35
|
+
* `temporarily_unavailable` is `provider_unavailable`; a transport failure or deadline is `network`. A refused client
|
|
36
|
+
* (`invalid_client`, `unauthorized_client`) needs an operator's configuration fix and, like every other failure, is
|
|
37
|
+
* `invalid_response`: never a revoked mailbox. A `SourceSyncFault` is returned unchanged.
|
|
38
|
+
*
|
|
39
|
+
* Call inside withGrant so that its fixed-fault boundary preserves this distinction.
|
|
40
|
+
*
|
|
41
|
+
* @param error What the grant operation threw.
|
|
42
|
+
*/
|
|
43
|
+
export declare function gmailOAuthFault(error: unknown): SourceSyncFault;
|
|
44
|
+
//# sourceMappingURL=retry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"retry.d.ts","sourceRoot":"","sources":["../src/retry.ts"],"names":[],"mappings":"AAOA,OAAO,EACL,eAAe,EAAE,KAAK,iBAAiB,EAAE,KAAK,qBAAqB,EACpE,MAAM,sCAAsC,CAAC;AAG9C;;;;GAIG;AACH,MAAM,MAAM,oBAAoB,GAC5B;IAAE,QAAQ,CAAC,IAAI,EAAE,IAAI,GAAG,SAAS,GAAG,MAAM,CAAA;CAAE,GAC5C;IAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,cAAc,GAAG,sBAAsB,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,SAAS,GAAG,SAAS,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAA;CAAE,GAClJ;IAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,qBAAqB,CAAA;CAAE,CAAC;AAMrE;;;;;;;;;;;GAWG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,iBAAiB,GAAG,oBAAoB,CA0BhH;AACD;;;;;;;;;;;GAWG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,eAAe,CAiB/D"}
|
package/dist/retry.js
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Fixed classification of Gmail API answers and OAuth refresh failures. Only an HTTP status and exact,
|
|
3
|
+
* allow-listed reason tokens decide a disposition; provider text, error bodies and causes never reach a result or an
|
|
4
|
+
* error. The durable account-source coordinator owns retry episodes, backoff and grant-loss handling.
|
|
5
|
+
* @module agentos-ext-gmail-source/retry
|
|
6
|
+
*/
|
|
7
|
+
import { OAuthGrantRefused } from '@framers/agentos/auth';
|
|
8
|
+
import { SourceSyncFault, } from '@framers/agentos-ext-account-sources';
|
|
9
|
+
import { GmailOAuthFault } from './types.js';
|
|
10
|
+
// A plain object, or null for anything else.
|
|
11
|
+
function record(value) {
|
|
12
|
+
return value !== null && typeof value === 'object' && !Array.isArray(value)
|
|
13
|
+
? value : null;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Classifies one Gmail API answer by its status and, for a 403, the exact reason tokens of at most 32 error entries.
|
|
17
|
+
* A 429 or 5xx is retried whether or not its body parses. A 403 `domainPolicy` wins over any other reason, then
|
|
18
|
+
* `insufficientPermissions`, `dailyLimitExceeded` (the whole project, daily), `rateLimitExceeded` (the whole project)
|
|
19
|
+
* and `userRateLimitExceeded` (the mailbox). A 404 is `gone` for a thread read and `history_expired` for a history
|
|
20
|
+
* page. Any other answer, an unknown reason included, is the fixed `invalid_response`, never an inferred grant loss.
|
|
21
|
+
* Only exact reason tokens influence policy. Provider text never leaves this function.
|
|
22
|
+
*
|
|
23
|
+
* @param status The HTTP status.
|
|
24
|
+
* @param body The answer's parsed JSON, or null when it did not parse.
|
|
25
|
+
* @param method The kind of call that was answered.
|
|
26
|
+
*/
|
|
27
|
+
export function classifyGmailHttp(status, body, method) {
|
|
28
|
+
if (status === 200)
|
|
29
|
+
return { kind: 'ok' };
|
|
30
|
+
if (status === 401)
|
|
31
|
+
return { kind: 'refresh' };
|
|
32
|
+
if (status === 404 && method === 'read')
|
|
33
|
+
return { kind: 'gone' };
|
|
34
|
+
if (status === 404 && method === 'changes')
|
|
35
|
+
return { kind: 'fault', code: 'history_expired' };
|
|
36
|
+
const retry = (code, scope, daily = false) => ({ kind: 'retry', code, scope, daily });
|
|
37
|
+
if (status === 429)
|
|
38
|
+
return retry('rate_limited', 'mailbox');
|
|
39
|
+
if (status >= 500 && status <= 599)
|
|
40
|
+
return retry('provider_unavailable', 'mailbox');
|
|
41
|
+
if (status === 403) {
|
|
42
|
+
const entries = record(record(body)?.error)?.errors;
|
|
43
|
+
const reasons = new Set();
|
|
44
|
+
if (Array.isArray(entries) && entries.length <= 32) {
|
|
45
|
+
for (const entry of entries) {
|
|
46
|
+
const reason = record(entry)?.reason;
|
|
47
|
+
if (typeof reason === 'string' && ['domainPolicy', 'insufficientPermissions', 'dailyLimitExceeded',
|
|
48
|
+
'rateLimitExceeded', 'userRateLimitExceeded'].includes(reason))
|
|
49
|
+
reasons.add(reason);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
if (reasons.has('domainPolicy'))
|
|
53
|
+
return { kind: 'fault', code: 'domain_policy' };
|
|
54
|
+
if (reasons.has('insufficientPermissions'))
|
|
55
|
+
return { kind: 'fault', code: 'insufficient_scope' };
|
|
56
|
+
if (reasons.has('dailyLimitExceeded'))
|
|
57
|
+
return retry('rate_limited', 'project', true);
|
|
58
|
+
if (reasons.has('rateLimitExceeded'))
|
|
59
|
+
return retry('rate_limited', 'project');
|
|
60
|
+
if (reasons.has('userRateLimitExceeded'))
|
|
61
|
+
return retry('rate_limited', 'mailbox');
|
|
62
|
+
}
|
|
63
|
+
return { kind: 'fault', code: 'invalid_response' };
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Translates a failure of an OAuth grant operation into a fixed account-source fault. A missing grant or Google's
|
|
67
|
+
* `invalid_grant` is `grant_rejected` and `invalid_scope` or a scope check is `insufficient_scope`, the two that start
|
|
68
|
+
* the coordinator's fenced grant-loss lifecycle; a 429 is `rate_limited`; a 5xx, `server_error` or
|
|
69
|
+
* `temporarily_unavailable` is `provider_unavailable`; a transport failure or deadline is `network`. A refused client
|
|
70
|
+
* (`invalid_client`, `unauthorized_client`) needs an operator's configuration fix and, like every other failure, is
|
|
71
|
+
* `invalid_response`: never a revoked mailbox. A `SourceSyncFault` is returned unchanged.
|
|
72
|
+
*
|
|
73
|
+
* Call inside withGrant so that its fixed-fault boundary preserves this distinction.
|
|
74
|
+
*
|
|
75
|
+
* @param error What the grant operation threw.
|
|
76
|
+
*/
|
|
77
|
+
export function gmailOAuthFault(error) {
|
|
78
|
+
if (error instanceof SourceSyncFault)
|
|
79
|
+
return error;
|
|
80
|
+
if (error instanceof GmailOAuthFault) {
|
|
81
|
+
if (error.reason === 'scope')
|
|
82
|
+
return new SourceSyncFault('insufficient_scope');
|
|
83
|
+
if (error.reason === 'network' || error.reason === 'timeout')
|
|
84
|
+
return new SourceSyncFault('network');
|
|
85
|
+
if (error.reason === 'cancelled')
|
|
86
|
+
return new SourceSyncFault('cancelled');
|
|
87
|
+
return new SourceSyncFault('invalid_response');
|
|
88
|
+
}
|
|
89
|
+
if (error instanceof OAuthGrantRefused) {
|
|
90
|
+
if (error.reason === 'missing' || error.providerError === 'invalid_grant')
|
|
91
|
+
return new SourceSyncFault('grant_rejected');
|
|
92
|
+
if (error.providerError === 'invalid_scope')
|
|
93
|
+
return new SourceSyncFault('insufficient_scope');
|
|
94
|
+
if (error.status === 429)
|
|
95
|
+
return new SourceSyncFault('rate_limited');
|
|
96
|
+
if ((error.status !== undefined && error.status >= 500) || ['server_error', 'temporarily_unavailable'].includes(error.providerError ?? '')) {
|
|
97
|
+
return new SourceSyncFault('provider_unavailable');
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
return new SourceSyncFault('invalid_response');
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=retry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"retry.js","sourceRoot":"","sources":["../src/retry.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.
|
|
5
|
+
"version": "0.4.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.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Read-only OAuth and bounded personal Gmail source helpers",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
"typescript": "5.4.5",
|
|
53
53
|
"vitest": "^3.2.7",
|
|
54
54
|
"@framers/agentos": "^0.13.134",
|
|
55
|
-
"@framers/agentos-ext-account-sources": "^0.7.
|
|
55
|
+
"@framers/agentos-ext-account-sources": "^0.7.1"
|
|
56
56
|
},
|
|
57
57
|
"scripts": {
|
|
58
58
|
"build": "tsc",
|