proton-mail-bridge-client 2.1.6 → 2.1.7
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/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +81 -26
- package/dist/index.js.map +1 -1
- package/dist/services/simple-imap-service.d.ts.map +1 -1
- package/dist/services/simple-imap-service.js +9 -1
- package/dist/services/simple-imap-service.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -65,6 +65,9 @@ export declare function redactDraftAttachmentsForListing(draft: DraftRecord): {
|
|
|
65
65
|
remoteDraft?: import("./types/index.js").RemoteDraftRef;
|
|
66
66
|
lastSendResult?: import("./types/index.js").DraftSendResult;
|
|
67
67
|
};
|
|
68
|
+
export declare function truncateDraftBodyForResponse<T extends {
|
|
69
|
+
body: string;
|
|
70
|
+
}>(draft: T): T;
|
|
68
71
|
export declare function redactQueueRecordAttachments<T extends {
|
|
69
72
|
payload: SendEmailInput;
|
|
70
73
|
}>(record: T): T;
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AASA,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AAYnE,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC3D,OAAO,EAAE,qBAAqB,EAAE,MAAM,uCAAuC,CAAC;AAC9E,OAAO,EAAE,oBAAoB,EAAE,MAAM,sCAAsC,CAAC;AAC5E,OAAO,EAAE,iBAAiB,EAAE,MAAM,mCAAmC,CAAC;AACtE,OAAO,EAAE,iBAAiB,EAAE,MAAM,mCAAmC,CAAC;AACtE,OAAO,EAA2H,iBAAiB,EAA+B,MAAM,mCAAmC,CAAC;AAC5N,OAAO,EAAmC,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAC1F,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAE7D,OAAO,KAAK,EAMV,mBAAmB,EAEnB,WAAW,EAIX,WAAW,EAIX,gBAAgB,EAChB,cAAc,EAGf,MAAM,kBAAkB,CAAC;AAmB1B,OAAO,EAAE,cAAc,EAAE,KAAK,aAAa,EAAE,MAAM,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -385,12 +385,14 @@ const TOOLS = [
|
|
|
385
385
|
},
|
|
386
386
|
{
|
|
387
387
|
name: "list_drafts",
|
|
388
|
-
description: "List all locally saved drafts with their status, subject, and timestamps. Attachment content is omitted here (filename/type/size only) to
|
|
388
|
+
description: "List all locally saved drafts with their status, subject, and timestamps. Attachment content is omitted here (filename/type/size only) — use get_draft for the full attachment content of one draft. Each draft's body is also truncated to a short preview (bodyTruncated:true, bodyLength gives the real size) — use get_draft for the full body of one draft. Use to review in-progress or unsent messages. Does NOT list drafts stored only on the Proton server — use list_remote_drafts for those. Prefer get_draft when you already have a draftId and need the full content.",
|
|
389
389
|
annotations: { readOnlyHint: true },
|
|
390
390
|
inputSchema: {
|
|
391
391
|
type: "object",
|
|
392
392
|
properties: {
|
|
393
393
|
includeSent: { type: "boolean", description: "Include drafts already sent.", default: false },
|
|
394
|
+
limit: { type: "number", description: "Maximum drafts to return. Omit to return every draft (still with truncated bodies/attachments) — set this when you only need a bounded page." },
|
|
395
|
+
offset: { type: "number", description: "Number of drafts to skip, newest-updated first.", default: 0 },
|
|
394
396
|
},
|
|
395
397
|
},
|
|
396
398
|
},
|
|
@@ -2277,6 +2279,34 @@ export function redactDraftAttachmentsForListing(draft) {
|
|
|
2277
2279
|
})),
|
|
2278
2280
|
};
|
|
2279
2281
|
}
|
|
2282
|
+
// How much of a draft's body survives into a mutation/listing response before
|
|
2283
|
+
// it's truncated — long enough to recognize the draft at a glance, short
|
|
2284
|
+
// enough that a large body (a long thread quoted into a reply, a big pasted
|
|
2285
|
+
// table) doesn't dominate the response the way redactDraftAttachmentsForListing
|
|
2286
|
+
// already stops a base64 attachment from doing.
|
|
2287
|
+
const DRAFT_BODY_PREVIEW_LENGTH = 500;
|
|
2288
|
+
// Found live (external review, repeated across three rounds): create_draft,
|
|
2289
|
+
// update_draft, create_reply_draft, create_forward_draft,
|
|
2290
|
+
// create_thread_reply_draft, sync_draft_to_remote, and list_drafts all echoed
|
|
2291
|
+
// the draft's COMPLETE body back — confirmed live at ~40k tokens for a single
|
|
2292
|
+
// update_draft call that only changed the subject of a ~202 KB draft, and
|
|
2293
|
+
// ~261k tokens for list_drafts with 107 drafts. The caller supplied the body
|
|
2294
|
+
// itself (create/update) or already has it from a prior call (list) — same
|
|
2295
|
+
// "caller already knows what it sent" reasoning as attachment redaction, just
|
|
2296
|
+
// for the text body instead of base64. get_draft deliberately keeps the full
|
|
2297
|
+
// body — it's the "let me look at this one draft" call, not a repeated-edit
|
|
2298
|
+
// or bulk-listing one.
|
|
2299
|
+
export function truncateDraftBodyForResponse(draft) {
|
|
2300
|
+
if (draft.body.length <= DRAFT_BODY_PREVIEW_LENGTH) {
|
|
2301
|
+
return draft;
|
|
2302
|
+
}
|
|
2303
|
+
return {
|
|
2304
|
+
...draft,
|
|
2305
|
+
body: `${draft.body.slice(0, DRAFT_BODY_PREVIEW_LENGTH)}…`,
|
|
2306
|
+
bodyLength: draft.body.length,
|
|
2307
|
+
bodyTruncated: true,
|
|
2308
|
+
};
|
|
2309
|
+
}
|
|
2280
2310
|
// Same fix as redactDraftAttachmentsForListing, for list_scheduled_sends — a
|
|
2281
2311
|
// queued send's payload carries the same full base64 EmailAttachmentInput
|
|
2282
2312
|
// content (found live: ~955k tokens for a single 1 MiB attachment on ONE
|
|
@@ -4041,9 +4071,9 @@ export function createServer(config, options = {}) {
|
|
|
4041
4071
|
return presentDraft(createDraftBundle, remoteSync ? { ...synced.draft, remoteSync } : synced.draft);
|
|
4042
4072
|
});
|
|
4043
4073
|
// Same fix as update_draft's identical bloat — see its comment. The
|
|
4044
|
-
// caller already knows what it attached
|
|
4045
|
-
// the full
|
|
4046
|
-
return createTextResult(redactDraftAttachmentsForListing(result), false, [
|
|
4074
|
+
// caller already knows what it attached (and what body it just sent);
|
|
4075
|
+
// get_draft is the "let me see the full content" call, not this one.
|
|
4076
|
+
return createTextResult(truncateDraftBodyForResponse(redactDraftAttachmentsForListing(result)), false, [
|
|
4047
4077
|
draftSource(result),
|
|
4048
4078
|
...(result.remoteDraft?.emailId
|
|
4049
4079
|
? [
|
|
@@ -4126,7 +4156,7 @@ export function createServer(config, options = {}) {
|
|
|
4126
4156
|
return presentDraft(createReplyDraftBundle, remoteSync ? { ...synced.draft, remoteSync } : synced.draft);
|
|
4127
4157
|
});
|
|
4128
4158
|
// Same fix as create_draft/update_draft's identical bloat — see their comments.
|
|
4129
|
-
return createTextResult(redactDraftAttachmentsForListing(result), false, [
|
|
4159
|
+
return createTextResult(truncateDraftBodyForResponse(redactDraftAttachmentsForListing(result)), false, [
|
|
4130
4160
|
draftSource(result),
|
|
4131
4161
|
emailSource(detail),
|
|
4132
4162
|
...(result.remoteDraft?.emailId
|
|
@@ -4201,7 +4231,7 @@ export function createServer(config, options = {}) {
|
|
|
4201
4231
|
return presentDraft(createForwardDraftBundle, remoteSync ? { ...synced.draft, remoteSync } : synced.draft);
|
|
4202
4232
|
});
|
|
4203
4233
|
// Same fix as create_draft/update_draft's identical bloat — see their comments.
|
|
4204
|
-
return createTextResult(redactDraftAttachmentsForListing(result), false, [
|
|
4234
|
+
return createTextResult(truncateDraftBodyForResponse(redactDraftAttachmentsForListing(result)), false, [
|
|
4205
4235
|
draftSource(result),
|
|
4206
4236
|
emailSource(detail),
|
|
4207
4237
|
...(result.remoteDraft?.emailId
|
|
@@ -4220,10 +4250,23 @@ export function createServer(config, options = {}) {
|
|
|
4220
4250
|
// drafts only — a non-primary account's drafts aren't listed here yet. Use
|
|
4221
4251
|
// get_draft with that account's prefixed draftId if you already have one.
|
|
4222
4252
|
const drafts = await draftStore.listDrafts(normalizeBoolean(args.includeSent, false));
|
|
4253
|
+
// Found live (external review): every draft's full body was returned
|
|
4254
|
+
// alongside the already-redacted attachments — confirmed live at ~261k
|
|
4255
|
+
// tokens for 107 drafts. Bodies are now truncated the same way a
|
|
4256
|
+
// mutation response's body is (see truncateDraftBodyForResponse). limit/
|
|
4257
|
+
// offset are optional and additive — omitting them still returns every
|
|
4258
|
+
// draft (just with truncated bodies/attachments), so this doesn't change
|
|
4259
|
+
// behavior for a caller not using the new params.
|
|
4260
|
+
const offset = normalizeLimit(args.offset, 0, 0, 10_000);
|
|
4261
|
+
const limit = typeof args.limit === "number" ? normalizeLimit(args.limit, drafts.length, 1, 10_000) : undefined;
|
|
4262
|
+
const page = limit !== undefined ? drafts.slice(offset, offset + limit) : drafts.slice(offset);
|
|
4223
4263
|
return createTextResult({
|
|
4224
4264
|
total: drafts.length,
|
|
4225
|
-
|
|
4226
|
-
|
|
4265
|
+
offset,
|
|
4266
|
+
returned: page.length,
|
|
4267
|
+
hasMore: offset + page.length < drafts.length,
|
|
4268
|
+
drafts: page.map((draft) => truncateDraftBodyForResponse(redactDraftAttachmentsForListing(draft))),
|
|
4269
|
+
}, false, page.map(draftSource));
|
|
4227
4270
|
}
|
|
4228
4271
|
case "list_remote_drafts": {
|
|
4229
4272
|
// Scope limitation (follow-up round): stays scoped to the primary account's
|
|
@@ -4314,10 +4357,13 @@ export function createServer(config, options = {}) {
|
|
|
4314
4357
|
// subject/body — the attachments usually aren't touched by this call at all, so
|
|
4315
4358
|
// re-echoing their full base64 `content` (serialized twice by createTextResult,
|
|
4316
4359
|
// same issue redactDraftAttachmentsForListing already fixed for list_drafts)
|
|
4317
|
-
// burns tokens on every single edit for a draft that has any attachment.
|
|
4318
|
-
//
|
|
4319
|
-
//
|
|
4320
|
-
|
|
4360
|
+
// burns tokens on every single edit for a draft that has any attachment. Same
|
|
4361
|
+
// reasoning for the body itself — confirmed live at ~40k tokens for a single
|
|
4362
|
+
// subject-only edit of a ~202 KB draft (see truncateDraftBodyForResponse). The
|
|
4363
|
+
// caller already knows what it attached and what body it just sent; get_draft
|
|
4364
|
+
// remains full-content for the "let me look at this draft" case, which is a
|
|
4365
|
+
// single call rather than a loop.
|
|
4366
|
+
return createTextResult(truncateDraftBodyForResponse(redactDraftAttachmentsForListing(result)), false, [
|
|
4321
4367
|
draftSource(result),
|
|
4322
4368
|
...(result.remoteDraft?.emailId
|
|
4323
4369
|
? [
|
|
@@ -4337,7 +4383,7 @@ export function createServer(config, options = {}) {
|
|
|
4337
4383
|
const synced = await withAudit(auditService, name, args, async () => syncDraftToRemote(syncDraftBundle.draftStore, syncDraftBundle.smtpService, syncDraftBundle.imapService, draft));
|
|
4338
4384
|
const presentedSynced = presentDraft(syncDraftBundle, synced.draft);
|
|
4339
4385
|
// Same fix as create_draft/update_draft's identical bloat — see their comments.
|
|
4340
|
-
return createTextResult({ ...redactDraftAttachmentsForListing(presentedSynced), remoteSync: synced.remoteSync }, false, [
|
|
4386
|
+
return createTextResult({ ...truncateDraftBodyForResponse(redactDraftAttachmentsForListing(presentedSynced)), remoteSync: synced.remoteSync }, false, [
|
|
4341
4387
|
draftSource(presentedSynced),
|
|
4342
4388
|
...(presentedSynced.remoteDraft?.emailId
|
|
4343
4389
|
? [
|
|
@@ -4657,25 +4703,34 @@ export function createServer(config, options = {}) {
|
|
|
4657
4703
|
// requested offset/limit to that merged superset instead of per account.
|
|
4658
4704
|
const primarySlug = accountManager.primary().account.slug;
|
|
4659
4705
|
const requestedOffset = getEmailsInput.offset ?? 0;
|
|
4660
|
-
|
|
4706
|
+
// +1 beyond what's strictly needed to fill the page: whether that extra
|
|
4707
|
+
// item actually comes back is what tells us hasMore, independent of any
|
|
4708
|
+
// filter (beforeUid etc.) or of how the raw mailbox total compares to the
|
|
4709
|
+
// page window. Two things were tried and each broke a different case:
|
|
4710
|
+
// (1) using mergedAll.length > offset+limit as hasMore, with NO extra
|
|
4711
|
+
// overfetch — a lopsided distribution (e.g. 300 messages in one account,
|
|
4712
|
+
// 0 in another) fetches exactly offset+limit from the big account, so
|
|
4713
|
+
// mergedAll.length can never exceed that window even though hundreds
|
|
4714
|
+
// more exist, reporting hasMore:false wrongly.
|
|
4715
|
+
// (2) using the raw summed mailbox `total` for hasMore instead — correct
|
|
4716
|
+
// for that case, but wrong under a restrictive filter like beforeUid:
|
|
4717
|
+
// `total` is the UNFILTERED mailbox message count, not the count of
|
|
4718
|
+
// messages actually matching the filter, so a beforeUid narrowing 300
|
|
4719
|
+
// messages down to 2 matches still compared against total=300 and
|
|
4720
|
+
// reported hasMore:true with nothing left to page to.
|
|
4721
|
+
// Fetching one extra item fixes both: it directly observes whether a
|
|
4722
|
+
// NEXT matching item exists, under whatever filter is active, rather
|
|
4723
|
+
// than inferring it from a count that can be either capped-by-fetch or
|
|
4724
|
+
// filter-blind depending on which one you pick.
|
|
4725
|
+
const perAccountFetchLimit = requestedOffset + effectiveLimit + 1;
|
|
4661
4726
|
const perAccount = await Promise.all(accountManager.all().map(async (bundle) => {
|
|
4662
4727
|
const result = await bundle.imapService.getEmails({ ...getEmailsInput, offset: 0, limit: perAccountFetchLimit });
|
|
4663
4728
|
return { bundle, result };
|
|
4664
4729
|
}));
|
|
4665
4730
|
const taggedEmails = perAccount.flatMap(({ bundle, result }) => result.emails.map((email) => ({ ...email, id: withAccountPrefix(accountSlugForTag(bundle, primarySlug), email.id) })));
|
|
4666
4731
|
const mergedAll = sortByDateDesc(taggedEmails, (email) => email.internalDate || email.date);
|
|
4667
|
-
const { page: merged } = paginateMergedAccountResults(mergedAll, requestedOffset, effectiveLimit);
|
|
4732
|
+
const { page: merged, hasMore } = paginateMergedAccountResults(mergedAll, requestedOffset, effectiveLimit);
|
|
4668
4733
|
const total = perAccount.reduce((sum, { result }) => sum + result.total, 0);
|
|
4669
|
-
// Found live (external review): paginateMergedAccountResults' own hasMore
|
|
4670
|
-
// only looks at what was actually FETCHED (mergedAll.length, capped at
|
|
4671
|
-
// perAccountFetchLimit per account) — with a lopsided distribution (e.g.
|
|
4672
|
-
// 300 messages in one account, 0 in another) and a small page near the
|
|
4673
|
-
// start, mergedAll.length can equal requestedOffset+limit exactly even
|
|
4674
|
-
// though the account's real total is far larger, reporting hasMore:false
|
|
4675
|
-
// while 275 more messages exist. `total` above is each account's real,
|
|
4676
|
-
// authoritative IMAP mailbox count (not bounded by what we fetched), so
|
|
4677
|
-
// it's the correct source for this instead.
|
|
4678
|
-
const hasMore = total > requestedOffset + effectiveLimit;
|
|
4679
4734
|
return createTextResult({
|
|
4680
4735
|
folder: getEmailsInput.folder?.trim() || "INBOX",
|
|
4681
4736
|
total,
|
|
@@ -6537,7 +6592,7 @@ export function createServer(config, options = {}) {
|
|
|
6537
6592
|
return { ...presented, threadId: thread.id };
|
|
6538
6593
|
});
|
|
6539
6594
|
// Same fix as create_draft/update_draft's identical bloat — see their comments.
|
|
6540
|
-
return createTextResult(redactDraftAttachmentsForListing(result), false, [
|
|
6595
|
+
return createTextResult(truncateDraftBodyForResponse(redactDraftAttachmentsForListing(result)), false, [
|
|
6541
6596
|
draftSource(result),
|
|
6542
6597
|
threadSource(thread),
|
|
6543
6598
|
emailSource(detail),
|