@wirecat/cli-core 0.534.0 → 0.536.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/CHANGELOG.md +16 -0
- package/dist/mail/server-search.js +11 -7
- package/dist/mail/sync.d.ts +2 -0
- package/dist/mail/sync.js +2 -2
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,22 @@ shape of this file.
|
|
|
7
7
|
|
|
8
8
|
## Unreleased
|
|
9
9
|
|
|
10
|
+
## 0.536.0 — 01.11.2026
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
|
|
14
|
+
- **A server mail search that ran out of time says so.** When the server's own deadline cut a search or the read of
|
|
15
|
+
its finds short, `searchMailServer` reported `search.server-failed` (`provider_unavailable`), as if the server had
|
|
16
|
+
refused. It now reports `search.server-timeout` (`timeout`), as when `--server-time` ends it, so a caller knows to
|
|
17
|
+
give it more time.
|
|
18
|
+
|
|
19
|
+
## 0.535.0 — 01.11.2026
|
|
20
|
+
|
|
21
|
+
### Added
|
|
22
|
+
|
|
23
|
+
- **`syncMail` takes `saveCoverage: false`** for a spot read, such as a CLI storing the copy of a message it just
|
|
24
|
+
sent: the mail is saved, and the coverage that memo reports for the archive stays what the last full run set.
|
|
25
|
+
|
|
10
26
|
## 0.534.0 — 01.11.2026
|
|
11
27
|
|
|
12
28
|
### Added
|
|
@@ -18,6 +18,12 @@ const refusal = {
|
|
|
18
18
|
no_words: "--backend server needs words, people, a subject, a date or a state to send to the server",
|
|
19
19
|
};
|
|
20
20
|
const BOUND = Symbol("bound");
|
|
21
|
+
/** A call the server's own deadline cut short is the time bound's, as one cut by --server-time is. */
|
|
22
|
+
const failureOf = (error) => error instanceof CliError && error.code === "rate_limited"
|
|
23
|
+
? "rate_limited"
|
|
24
|
+
: error instanceof CliError && error.code === "timeout"
|
|
25
|
+
? "time_or_abort_bound"
|
|
26
|
+
: "search_failed";
|
|
21
27
|
/** The newest first: a server's UIDs grow as mail arrives in the folder. */
|
|
22
28
|
const newest = (uids, count) => [...uids].sort((one, other) => Number(other) - Number(one)).slice(0, count);
|
|
23
29
|
/**
|
|
@@ -112,7 +118,7 @@ export const searchMailServer = async (store, mailbox, access, request) => {
|
|
|
112
118
|
if (!open)
|
|
113
119
|
return;
|
|
114
120
|
pending.delete(call);
|
|
115
|
-
fail(call, error
|
|
121
|
+
fail(call, failureOf(error));
|
|
116
122
|
}
|
|
117
123
|
}));
|
|
118
124
|
if (!open)
|
|
@@ -143,10 +149,7 @@ export const searchMailServer = async (store, mailbox, access, request) => {
|
|
|
143
149
|
});
|
|
144
150
|
let outcome;
|
|
145
151
|
try {
|
|
146
|
-
outcome = await Promise.race([
|
|
147
|
-
run().then(() => "done", () => "failed"),
|
|
148
|
-
bound,
|
|
149
|
-
]);
|
|
152
|
+
outcome = await Promise.race([run().then(() => "done", failureOf), bound]);
|
|
150
153
|
}
|
|
151
154
|
finally {
|
|
152
155
|
open = false;
|
|
@@ -158,12 +161,13 @@ export const searchMailServer = async (store, mailbox, access, request) => {
|
|
|
158
161
|
throw openFailure;
|
|
159
162
|
if (unsupported)
|
|
160
163
|
return skip("unsupported");
|
|
164
|
+
const ended = outcome === BOUND || outcome === "done" ? "time_or_abort_bound" : outcome;
|
|
161
165
|
for (const call of pending)
|
|
162
|
-
fail(call,
|
|
166
|
+
fail(call, ended);
|
|
163
167
|
if (outcome !== "done" || (fresh.length > 0 && raws === undefined)) {
|
|
164
168
|
// What was found but not read in time is the archive's to answer: none of it is claimed as the server's.
|
|
165
169
|
if (pending.size === 0)
|
|
166
|
-
fail(null,
|
|
170
|
+
fail(null, ended);
|
|
167
171
|
for (const item of fresh)
|
|
168
172
|
sources.delete(sourceKey(item.threadId, item.messageId));
|
|
169
173
|
report.returned = sources.size;
|
package/dist/mail/sync.d.ts
CHANGED
|
@@ -89,6 +89,8 @@ export interface MailSyncOptions {
|
|
|
89
89
|
retryAttachments?: boolean;
|
|
90
90
|
/** List every message in the window, not only those an earlier run left: proves deletions, refreshes labels. */
|
|
91
91
|
rescan?: boolean;
|
|
92
|
+
/** `false` for a spot read, like the copy of a sent message: the run leaves the saved coverage as the last full run set it. */
|
|
93
|
+
saveCoverage?: boolean;
|
|
92
94
|
/** A window smaller than this is listed whole every run: it costs seconds and keeps flags and deletions current. */
|
|
93
95
|
resumeFrom?: number;
|
|
94
96
|
/** Runs after the mail is saved, so chats and mail still waiting for vectors are indexed; its answer is `indexed`. */
|
package/dist/mail/sync.js
CHANGED
|
@@ -141,7 +141,7 @@ export const syncMail = async (source, store, options) => {
|
|
|
141
141
|
: {}),
|
|
142
142
|
};
|
|
143
143
|
};
|
|
144
|
-
const syncRound = async (source, store, { account, since, max = 200, maxBodyChars = MAX_BODY_CHARS, maxAttachmentChars = MAX_ATTACHMENT_CHARS, now = Date.now, ages, loadEngine = importEngine, retryAttachments = false, rescan = false, resumeFrom = RESUME_FROM, index, signal, }, plan) => {
|
|
144
|
+
const syncRound = async (source, store, { account, since, max = 200, maxBodyChars = MAX_BODY_CHARS, maxAttachmentChars = MAX_ATTACHMENT_CHARS, now = Date.now, ages, loadEngine = importEngine, retryAttachments = false, rescan = false, saveCoverage = true, resumeFrom = RESUME_FROM, index, signal, }, plan) => {
|
|
145
145
|
if (retryAttachments)
|
|
146
146
|
return retryUnread({
|
|
147
147
|
store,
|
|
@@ -777,7 +777,7 @@ const syncRound = async (source, store, { account, since, max = 200, maxBodyChar
|
|
|
777
777
|
state: complete ? "window" : "partial",
|
|
778
778
|
identity: account.mode === "imap" ? "message-id-or-uidvalidity-folder-uid" : "gmail-message-id",
|
|
779
779
|
};
|
|
780
|
-
if (!snapshot)
|
|
780
|
+
if (!snapshot && saveCoverage)
|
|
781
781
|
await store.sync.setSyncState(key, "mail_coverage", JSON.stringify(coverage));
|
|
782
782
|
const tagging = tagger.outcome();
|
|
783
783
|
await settleRuleTags(store, accountId, rules, tagging);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wirecat/cli-core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.536.0",
|
|
4
4
|
"description": "The messenger-neutral half of a messaging CLI: domain model, message locators, rendering, name resolution, the SQLite seam, the command skeleton and shared read commands, the send guard, run records and the message store",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "Viacheslav Ptsarev",
|