@wirecat/cli-core 0.472.0 → 0.473.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.
Files changed (38) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/dist/cli/execution.d.ts +5 -0
  3. package/dist/cli/execution.js +5 -0
  4. package/dist/cli/help/first-screen.js +5 -0
  5. package/dist/cli/messenger/conversation-answers.d.ts +1 -0
  6. package/dist/cli/messenger/hearing-command.js +1 -1
  7. package/dist/cli/messenger/message-answers.d.ts +1 -0
  8. package/dist/cli/messenger/message-items.js +2 -0
  9. package/dist/cli/messenger/message-writes.d.ts +2 -0
  10. package/dist/cli/program.js +5 -3
  11. package/dist/entities/conversation-results.d.ts +2 -0
  12. package/dist/entities/evidence.d.ts +8 -0
  13. package/dist/entities/index.d.ts +19 -0
  14. package/dist/entities/knowledge-lists.d.ts +1 -0
  15. package/dist/entities/knowledge-lists.js +1 -0
  16. package/dist/entities/listener.d.ts +4 -0
  17. package/dist/entities/message-context.d.ts +3 -0
  18. package/dist/entities/message-write.d.ts +4 -0
  19. package/dist/entities/message.d.ts +1 -0
  20. package/dist/entities/message.js +1 -0
  21. package/dist/entities/store-records.d.ts +1 -0
  22. package/dist/mail/source.d.ts +7 -0
  23. package/dist/mail/sync.d.ts +16 -1
  24. package/dist/mail/sync.js +187 -11
  25. package/dist/mail/testing/fake.d.ts +11 -0
  26. package/dist/mail/testing/fake.js +28 -8
  27. package/dist/runs/error-detail.d.ts +2 -0
  28. package/dist/runs/error-detail.js +4 -0
  29. package/dist/speech/hearing.d.ts +2 -0
  30. package/dist/speech/hearing.js +10 -0
  31. package/dist/store/knowledge-query.js +3 -1
  32. package/dist/store/people.d.ts +2 -0
  33. package/dist/store/people.js +12 -0
  34. package/dist/store/sqlite/knowledge.d.ts +3 -1
  35. package/dist/store/sqlite/knowledge.js +7 -2
  36. package/dist/store/sqlite/task-keys.d.ts +1 -0
  37. package/dist/store/sqlite/task-keys.js +1 -0
  38. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -7,6 +7,42 @@ shape of this file.
7
7
 
8
8
  ## Unreleased
9
9
 
10
+ ## 0.473.0 — 29.10.2026
11
+
12
+ ### Added
13
+
14
+ - **`syncMail` takes a `budget` and answers `partial`** (WC-LIFE-16 for mail). With a `RunBudget` it reads the window in
15
+ rounds of `source.listBatch` messages, spends one request per call to the source, saves its resume point after every
16
+ round (a 16,000-message folder now finishes over several runs, mid-folder progress included), asks once more at the
17
+ end of the run for a message the source could not give, and returns `state`, `stopped`, `remaining` and `requests`.
18
+ `MailSource` gains the optional `listBatch` and `fetchBatch`. Without a budget nothing changes except that a failed
19
+ chunk now saves the resume point before it throws.
20
+ - **A failed run's record keeps the transport's code.** `runs show` has `error.cause_code` (`NoConnection`,
21
+ `ETIMEDOUT`, a server response code; plain codes only, never the server's text) when the error carries one.
22
+ - **A cooperative command that declares `partial` is a sync and gets 15 minutes at a terminal** (`DEFAULT_SYNC_MS`);
23
+ other cooperative commands keep 5 minutes and MCP keeps 45 seconds. The calendar `sync` is one: it had 5 minutes.
24
+ - **`sender_is_me` on every message the shared message output carries** (`messageItem`, so `messages list`, `show`,
25
+ `context`, search windows and the catch-up reads of tg, max and wa). It is true when the message is `outgoing` or its
26
+ sender id is the reading account's own, so MAX's owner, which has no sender id, is told apart from an unknown sender.
27
+ - **Projects have a `kind`: `project` or `inbox`**, and `projects(query)` takes `kind:` and `name:` (with `*`
28
+ wildcards) as query fields.
29
+ - **`store.people.owner()`** returns the person marked as the owner, with their linked identities, or `undefined`
30
+ when none is marked: what a caller needs to resolve `person:me`.
31
+
32
+ ### Changed — may break callers
33
+
34
+ - **`knowledge.projects()` leaves the per-account task inbox projects out** (`IN` plus eight hex digits, such as
35
+ `telegram:220195113`) unless the query names `kind`; `kind:inbox` lists only them. A caller that read inboxes from
36
+ the unfiltered list must ask for `kind:inbox`.
37
+
38
+ ### Fixed
39
+
40
+ - **`projects list 'name:*tart*'` no longer crashes** with `internal_error command.crashed`: `name` was a query field
41
+ the store had no column for.
42
+ - **`--offline --transcribe` says what it did not do.** It still shows transcripts already stored and never connects;
43
+ voice messages without one are now in `missing` with the exact `<app> <profile> messages transcribe <chat> <id>`
44
+ command, in `messages list`, `inbox` and `review`.
45
+
10
46
  ## 0.472.0 — 28.10.2026
11
47
 
12
48
  ### Added
@@ -3,6 +3,11 @@ import type { Closeable } from "./deadline.js";
3
3
  export declare const DEFAULT_COMMAND_MS = 30000;
4
4
  /** A `cooperative` command stops on its own before its deadline and keeps its work, so it may run longer. */
5
5
  export declare const DEFAULT_COOPERATIVE_MS: number;
6
+ /**
7
+ * A cooperative command that also declares `partial` is a resumable sync: it spends a request budget, answers
8
+ * `partial` with `next`, and loses nothing when it stops, so a terminal lets it run longer than other cooperative work.
9
+ */
10
+ export declare const DEFAULT_SYNC_MS: number;
6
11
  /**
7
12
  * The same over MCP: clients cut a tool call at about 60 s (the MCP TypeScript SDK's `DEFAULT_REQUEST_TIMEOUT_MSEC`
8
13
  * is 60000), so the command answers well before that.
@@ -4,6 +4,11 @@ import { fieldsOf, projectFields } from "./result-fields.js";
4
4
  export const DEFAULT_COMMAND_MS = 30_000;
5
5
  /** A `cooperative` command stops on its own before its deadline and keeps its work, so it may run longer. */
6
6
  export const DEFAULT_COOPERATIVE_MS = 5 * 60_000;
7
+ /**
8
+ * A cooperative command that also declares `partial` is a resumable sync: it spends a request budget, answers
9
+ * `partial` with `next`, and loses nothing when it stops, so a terminal lets it run longer than other cooperative work.
10
+ */
11
+ export const DEFAULT_SYNC_MS = 15 * 60_000;
7
12
  /**
8
13
  * The same over MCP: clients cut a tool call at about 60 s (the MCP TypeScript SDK's `DEFAULT_REQUEST_TIMEOUT_MSEC`
9
14
  * is 60000), so the command answers well before that.
@@ -38,6 +38,11 @@ export const WIRECAT_TOOLS = [
38
38
  shown: "memo context <person>",
39
39
  does: "one person across messengers, mail, notes and meetings",
40
40
  },
41
+ {
42
+ command: "mail",
43
+ package: "@wirecat/mail-cli",
44
+ does: "IMAP mail in the same local store: search your mailbox offline, next to your other WireCat data",
45
+ },
41
46
  ];
42
47
  const WIDTH = 100;
43
48
  const widest = (texts) => texts.reduce((most, text) => Math.max(most, text.length), 0);
@@ -45,6 +45,7 @@ export declare const conversationShown: (account: AccountKey, { summary, message
45
45
  sender_name: string | null;
46
46
  sender_username?: string | undefined;
47
47
  sender_is_chat?: boolean | undefined;
48
+ sender_is_me: boolean;
48
49
  mentions?: string[] | undefined;
49
50
  timestamp: string;
50
51
  edited_at: string | null;
@@ -34,7 +34,7 @@ export const hearForCommand = async (context, messenger, messages, transcribe, m
34
34
  else if (transcribe && hearing.unheard.length > 0) {
35
35
  context.renderer.note(`${hearing.unheard.length} voice message(s) not heard yet — ask again later`);
36
36
  }
37
- return hearing;
37
+ return offline ? { ...hearing, offline: `${messenger.app.command} ${context.profile}` } : hearing;
38
38
  }
39
39
  finally {
40
40
  await kept.close();
@@ -22,6 +22,7 @@ export declare const threadAnswer: ({ items, ...thread }: ThreadContext, reader:
22
22
  sender_name: string | null;
23
23
  sender_username?: string | undefined;
24
24
  sender_is_chat?: boolean | undefined;
25
+ sender_is_me: boolean;
25
26
  mentions?: string[] | undefined;
26
27
  timestamp: string;
27
28
  edited_at: string | null;
@@ -42,6 +42,8 @@ export const messageItem = (message, reader) => {
42
42
  sender_name: message.senderName,
43
43
  sender_username: message.senderUsername,
44
44
  sender_is_chat: message.senderIsChat,
45
+ // MAX reports the owner's own messages with no sender id, so `outgoing` counts as well as the id.
46
+ sender_is_me: message.outgoing === true || (message.senderId !== null && String(message.senderId) === account),
45
47
  mentions: message.mentions,
46
48
  timestamp: message.timestamp,
47
49
  edited_at: message.editedAt,
@@ -26,6 +26,7 @@ export declare const writtenAnswer: ({ operationId, sendId, message, messages, s
26
26
  sender_name: string | null;
27
27
  sender_username?: string | undefined;
28
28
  sender_is_chat?: boolean | undefined;
29
+ sender_is_me: boolean;
29
30
  mentions?: string[] | undefined;
30
31
  timestamp: string;
31
32
  edited_at: string | null;
@@ -216,6 +217,7 @@ export declare const writtenAnswer: ({ operationId, sendId, message, messages, s
216
217
  sender_name: string | null;
217
218
  sender_username?: string | undefined;
218
219
  sender_is_chat?: boolean | undefined;
220
+ sender_is_me: boolean;
219
221
  mentions?: string[] | undefined;
220
222
  timestamp: string;
221
223
  edited_at: string | null;
@@ -20,7 +20,7 @@ import { outputFor, provide } from "./context.js";
20
20
  import { refuseByCommandPermissions, refuseWriteBeforeConnecting } from "./early-refusal.js";
21
21
  import { changesAuthorityAt, changesAuthorityNow, isLogin, isStoreChange, judgedEffects, judgedTargets, storeChangeRefusal, } from "./effects.js";
22
22
  import { itemOf, renderAnswer, snakeKeys } from "./envelope.js";
23
- import { byteCount, DEFAULT_AGENT_COOPERATIVE_MS, DEFAULT_COMMAND_MS, DEFAULT_COOPERATIVE_MS, DEFAULT_OUTPUT_BYTES, execution, } from "./execution.js";
23
+ import { byteCount, DEFAULT_AGENT_COOPERATIVE_MS, DEFAULT_COMMAND_MS, DEFAULT_COOPERATIVE_MS, DEFAULT_OUTPUT_BYTES, DEFAULT_SYNC_MS, execution, } from "./execution.js";
24
24
  import { setupAtStart } from "./first-run.js";
25
25
  import { installHelp } from "./help/first-screen.js";
26
26
  import { showInputFields } from "./input-fields.js";
@@ -324,7 +324,7 @@ const runOnce = async (argv, definition, options) => {
324
324
  throw new CliError("permission_error", `\`${command} ${path.join(" ")}\` calls the Bot API directly, past the send guard and the recipient list, ` +
325
325
  `and this profile keeps that from agents (${BOT_API_KEY}) — the owner turns it on in a terminal: ` +
326
326
  `\`${command} <profile> config set --bot permissions.${BOT_API_KEY} allow\``, { permission: BOT_API_KEY, sent: false });
327
- const { lifetime, cooperative: stopsAtItsPace } = metaOf(action);
327
+ const { lifetime, cooperative: stopsAtItsPace, partial: answersPartial } = metaOf(action);
328
328
  const persistent = lifetime === "persistent";
329
329
  listens = persistent;
330
330
  const interactiveLogin = !headless && lifetime === "interactive";
@@ -339,7 +339,9 @@ const runOnce = async (argv, definition, options) => {
339
339
  : stopsAtItsPace === true
340
340
  ? options.agent
341
341
  ? DEFAULT_AGENT_COOPERATIVE_MS
342
- : DEFAULT_COOPERATIVE_MS
342
+ : answersPartial === true
343
+ ? DEFAULT_SYNC_MS
344
+ : DEFAULT_COOPERATIVE_MS
343
345
  : DEFAULT_COMMAND_MS
344
346
  : persistent
345
347
  ? undefined
@@ -21,6 +21,7 @@ export declare const conversationDetails: v.UnionSchema<[v.StrictObjectSchema<{
21
21
  readonly sender_name: v.NullableSchema<v.StringSchema<undefined>, undefined>;
22
22
  readonly sender_username: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
23
23
  readonly sender_is_chat: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
24
+ readonly sender_is_me: v.BooleanSchema<undefined>;
24
25
  readonly mentions: v.OptionalSchema<v.ArraySchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>, undefined>, undefined>;
25
26
  readonly timestamp: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>;
26
27
  readonly edited_at: v.NullableSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>, undefined>;
@@ -209,6 +210,7 @@ export declare const conversationDetails: v.UnionSchema<[v.StrictObjectSchema<{
209
210
  readonly sender_name: v.NullableSchema<v.StringSchema<undefined>, undefined>;
210
211
  readonly sender_username: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
211
212
  readonly sender_is_chat: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
213
+ readonly sender_is_me: v.BooleanSchema<undefined>;
212
214
  readonly mentions: v.OptionalSchema<v.ArraySchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>, undefined>, undefined>;
213
215
  readonly timestamp: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>;
214
216
  readonly edited_at: v.NullableSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>, undefined>;
@@ -12,6 +12,7 @@ export declare const contribution: v.StrictObjectSchema<{
12
12
  readonly sender_name: v.NullableSchema<v.StringSchema<undefined>, undefined>;
13
13
  readonly sender_username: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
14
14
  readonly sender_is_chat: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
15
+ readonly sender_is_me: v.BooleanSchema<undefined>;
15
16
  readonly mentions: v.OptionalSchema<v.ArraySchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>, undefined>, undefined>;
16
17
  readonly timestamp: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>;
17
18
  readonly edited_at: v.NullableSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>, undefined>;
@@ -200,6 +201,7 @@ export declare const contribution: v.StrictObjectSchema<{
200
201
  readonly sender_name: v.NullableSchema<v.StringSchema<undefined>, undefined>;
201
202
  readonly sender_username: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
202
203
  readonly sender_is_chat: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
204
+ readonly sender_is_me: v.BooleanSchema<undefined>;
203
205
  readonly mentions: v.OptionalSchema<v.ArraySchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>, undefined>, undefined>;
204
206
  readonly timestamp: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>;
205
207
  readonly edited_at: v.NullableSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>, undefined>;
@@ -426,6 +428,7 @@ export declare const contribution: v.StrictObjectSchema<{
426
428
  readonly sender_name: v.NullableSchema<v.StringSchema<undefined>, undefined>;
427
429
  readonly sender_username: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
428
430
  readonly sender_is_chat: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
431
+ readonly sender_is_me: v.BooleanSchema<undefined>;
429
432
  readonly mentions: v.OptionalSchema<v.ArraySchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>, undefined>, undefined>;
430
433
  readonly timestamp: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>;
431
434
  readonly edited_at: v.NullableSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>, undefined>;
@@ -614,6 +617,7 @@ export declare const contribution: v.StrictObjectSchema<{
614
617
  readonly sender_name: v.NullableSchema<v.StringSchema<undefined>, undefined>;
615
618
  readonly sender_username: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
616
619
  readonly sender_is_chat: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
620
+ readonly sender_is_me: v.BooleanSchema<undefined>;
617
621
  readonly mentions: v.OptionalSchema<v.ArraySchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>, undefined>, undefined>;
618
622
  readonly timestamp: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>;
619
623
  readonly edited_at: v.NullableSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>, undefined>;
@@ -876,6 +880,7 @@ export declare const evidence: v.UnionSchema<[v.StrictObjectSchema<{
876
880
  readonly sender_name: v.NullableSchema<v.StringSchema<undefined>, undefined>;
877
881
  readonly sender_username: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
878
882
  readonly sender_is_chat: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
883
+ readonly sender_is_me: v.BooleanSchema<undefined>;
879
884
  readonly mentions: v.OptionalSchema<v.ArraySchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>, undefined>, undefined>;
880
885
  readonly timestamp: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>;
881
886
  readonly edited_at: v.NullableSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>, undefined>;
@@ -1064,6 +1069,7 @@ export declare const evidence: v.UnionSchema<[v.StrictObjectSchema<{
1064
1069
  readonly sender_name: v.NullableSchema<v.StringSchema<undefined>, undefined>;
1065
1070
  readonly sender_username: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
1066
1071
  readonly sender_is_chat: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
1072
+ readonly sender_is_me: v.BooleanSchema<undefined>;
1067
1073
  readonly mentions: v.OptionalSchema<v.ArraySchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>, undefined>, undefined>;
1068
1074
  readonly timestamp: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>;
1069
1075
  readonly edited_at: v.NullableSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>, undefined>;
@@ -1290,6 +1296,7 @@ export declare const evidence: v.UnionSchema<[v.StrictObjectSchema<{
1290
1296
  readonly sender_name: v.NullableSchema<v.StringSchema<undefined>, undefined>;
1291
1297
  readonly sender_username: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
1292
1298
  readonly sender_is_chat: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
1299
+ readonly sender_is_me: v.BooleanSchema<undefined>;
1293
1300
  readonly mentions: v.OptionalSchema<v.ArraySchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>, undefined>, undefined>;
1294
1301
  readonly timestamp: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>;
1295
1302
  readonly edited_at: v.NullableSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>, undefined>;
@@ -1478,6 +1485,7 @@ export declare const evidence: v.UnionSchema<[v.StrictObjectSchema<{
1478
1485
  readonly sender_name: v.NullableSchema<v.StringSchema<undefined>, undefined>;
1479
1486
  readonly sender_username: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
1480
1487
  readonly sender_is_chat: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
1488
+ readonly sender_is_me: v.BooleanSchema<undefined>;
1481
1489
  readonly mentions: v.OptionalSchema<v.ArraySchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>, undefined>, undefined>;
1482
1490
  readonly timestamp: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>;
1483
1491
  readonly edited_at: v.NullableSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>, undefined>;
@@ -234,6 +234,7 @@ export declare const ENTITIES: {
234
234
  readonly sender_name: v.NullableSchema<v.StringSchema<undefined>, undefined>;
235
235
  readonly sender_username: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
236
236
  readonly sender_is_chat: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
237
+ readonly sender_is_me: v.BooleanSchema<undefined>;
237
238
  readonly mentions: v.OptionalSchema<v.ArraySchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>, undefined>, undefined>;
238
239
  readonly timestamp: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>;
239
240
  readonly edited_at: v.NullableSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>, undefined>;
@@ -422,6 +423,7 @@ export declare const ENTITIES: {
422
423
  readonly sender_name: v.NullableSchema<v.StringSchema<undefined>, undefined>;
423
424
  readonly sender_username: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
424
425
  readonly sender_is_chat: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
426
+ readonly sender_is_me: v.BooleanSchema<undefined>;
425
427
  readonly mentions: v.OptionalSchema<v.ArraySchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>, undefined>, undefined>;
426
428
  readonly timestamp: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>;
427
429
  readonly edited_at: v.NullableSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>, undefined>;
@@ -615,6 +617,7 @@ export declare const ENTITIES: {
615
617
  readonly sender_name: v.NullableSchema<v.StringSchema<undefined>, undefined>;
616
618
  readonly sender_username: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
617
619
  readonly sender_is_chat: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
620
+ readonly sender_is_me: v.BooleanSchema<undefined>;
618
621
  readonly mentions: v.OptionalSchema<v.ArraySchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>, undefined>, undefined>;
619
622
  readonly timestamp: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>;
620
623
  readonly edited_at: v.NullableSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>, undefined>;
@@ -1148,6 +1151,7 @@ export declare const ENTITIES: {
1148
1151
  readonly sender_name: v.NullableSchema<v.StringSchema<undefined>, undefined>;
1149
1152
  readonly sender_username: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
1150
1153
  readonly sender_is_chat: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
1154
+ readonly sender_is_me: v.BooleanSchema<undefined>;
1151
1155
  readonly mentions: v.OptionalSchema<v.ArraySchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>, undefined>, undefined>;
1152
1156
  readonly timestamp: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>;
1153
1157
  readonly edited_at: v.NullableSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>, undefined>;
@@ -1336,6 +1340,7 @@ export declare const ENTITIES: {
1336
1340
  readonly sender_name: v.NullableSchema<v.StringSchema<undefined>, undefined>;
1337
1341
  readonly sender_username: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
1338
1342
  readonly sender_is_chat: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
1343
+ readonly sender_is_me: v.BooleanSchema<undefined>;
1339
1344
  readonly mentions: v.OptionalSchema<v.ArraySchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>, undefined>, undefined>;
1340
1345
  readonly timestamp: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>;
1341
1346
  readonly edited_at: v.NullableSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>, undefined>;
@@ -1715,6 +1720,7 @@ export declare const ENTITIES: {
1715
1720
  readonly sender_name: v.NullableSchema<v.StringSchema<undefined>, undefined>;
1716
1721
  readonly sender_username: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
1717
1722
  readonly sender_is_chat: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
1723
+ readonly sender_is_me: v.BooleanSchema<undefined>;
1718
1724
  readonly mentions: v.OptionalSchema<v.ArraySchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>, undefined>, undefined>;
1719
1725
  readonly timestamp: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>;
1720
1726
  readonly edited_at: v.NullableSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>, undefined>;
@@ -1903,6 +1909,7 @@ export declare const ENTITIES: {
1903
1909
  readonly sender_name: v.NullableSchema<v.StringSchema<undefined>, undefined>;
1904
1910
  readonly sender_username: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
1905
1911
  readonly sender_is_chat: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
1912
+ readonly sender_is_me: v.BooleanSchema<undefined>;
1906
1913
  readonly mentions: v.OptionalSchema<v.ArraySchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>, undefined>, undefined>;
1907
1914
  readonly timestamp: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>;
1908
1915
  readonly edited_at: v.NullableSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>, undefined>;
@@ -2095,6 +2102,7 @@ export declare const ENTITIES: {
2095
2102
  readonly sender_name: v.NullableSchema<v.StringSchema<undefined>, undefined>;
2096
2103
  readonly sender_username: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
2097
2104
  readonly sender_is_chat: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
2105
+ readonly sender_is_me: v.BooleanSchema<undefined>;
2098
2106
  readonly mentions: v.OptionalSchema<v.ArraySchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>, undefined>, undefined>;
2099
2107
  readonly timestamp: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>;
2100
2108
  readonly edited_at: v.NullableSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>, undefined>;
@@ -2283,6 +2291,7 @@ export declare const ENTITIES: {
2283
2291
  readonly sender_name: v.NullableSchema<v.StringSchema<undefined>, undefined>;
2284
2292
  readonly sender_username: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
2285
2293
  readonly sender_is_chat: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
2294
+ readonly sender_is_me: v.BooleanSchema<undefined>;
2286
2295
  readonly mentions: v.OptionalSchema<v.ArraySchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>, undefined>, undefined>;
2287
2296
  readonly timestamp: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>;
2288
2297
  readonly edited_at: v.NullableSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>, undefined>;
@@ -4192,6 +4201,7 @@ export declare const ENTITIES: {
4192
4201
  readonly ref: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, "a reference such as `note:42`">]>;
4193
4202
  readonly key: v.StringSchema<undefined>;
4194
4203
  readonly name: v.StringSchema<undefined>;
4204
+ readonly kind: v.PicklistSchema<["project", "inbox"], undefined>;
4195
4205
  readonly type: v.PicklistSchema<["work", "client", "personal", "oss", "other"], undefined>;
4196
4206
  readonly organization_id: v.NullableSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>, undefined>;
4197
4207
  readonly scope: v.PicklistSchema<["personal", "work"], undefined>;
@@ -6620,6 +6630,7 @@ export declare const ENTITIES: {
6620
6630
  readonly sender_name: v.NullableSchema<v.StringSchema<undefined>, undefined>;
6621
6631
  readonly sender_username: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
6622
6632
  readonly sender_is_chat: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
6633
+ readonly sender_is_me: v.BooleanSchema<undefined>;
6623
6634
  readonly mentions: v.OptionalSchema<v.ArraySchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>, undefined>, undefined>;
6624
6635
  readonly timestamp: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>;
6625
6636
  readonly edited_at: v.NullableSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>, undefined>;
@@ -6808,6 +6819,7 @@ export declare const ENTITIES: {
6808
6819
  readonly sender_name: v.NullableSchema<v.StringSchema<undefined>, undefined>;
6809
6820
  readonly sender_username: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
6810
6821
  readonly sender_is_chat: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
6822
+ readonly sender_is_me: v.BooleanSchema<undefined>;
6811
6823
  readonly mentions: v.OptionalSchema<v.ArraySchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>, undefined>, undefined>;
6812
6824
  readonly timestamp: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>;
6813
6825
  readonly edited_at: v.NullableSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>, undefined>;
@@ -7239,6 +7251,7 @@ export declare const ENTITIES: {
7239
7251
  readonly sender_name: v.NullableSchema<v.StringSchema<undefined>, undefined>;
7240
7252
  readonly sender_username: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
7241
7253
  readonly sender_is_chat: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
7254
+ readonly sender_is_me: v.BooleanSchema<undefined>;
7242
7255
  readonly mentions: v.OptionalSchema<v.ArraySchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>, undefined>, undefined>;
7243
7256
  readonly timestamp: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>;
7244
7257
  readonly edited_at: v.NullableSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>, undefined>;
@@ -7718,6 +7731,7 @@ export declare const ENTITIES: {
7718
7731
  readonly sender_name: v.NullableSchema<v.StringSchema<undefined>, undefined>;
7719
7732
  readonly sender_username: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
7720
7733
  readonly sender_is_chat: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
7734
+ readonly sender_is_me: v.BooleanSchema<undefined>;
7721
7735
  readonly mentions: v.OptionalSchema<v.ArraySchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>, undefined>, undefined>;
7722
7736
  readonly timestamp: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>;
7723
7737
  readonly edited_at: v.NullableSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>, undefined>;
@@ -8373,6 +8387,7 @@ export declare const ENTITIES: {
8373
8387
  readonly sender_name: v.NullableSchema<v.StringSchema<undefined>, undefined>;
8374
8388
  readonly sender_username: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
8375
8389
  readonly sender_is_chat: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
8390
+ readonly sender_is_me: v.BooleanSchema<undefined>;
8376
8391
  readonly mentions: v.OptionalSchema<v.ArraySchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>, undefined>, undefined>;
8377
8392
  readonly timestamp: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>;
8378
8393
  readonly edited_at: v.NullableSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>, undefined>;
@@ -9970,6 +9985,7 @@ export declare const ENTITIES: {
9970
9985
  readonly sender_name: v.NullableSchema<v.StringSchema<undefined>, undefined>;
9971
9986
  readonly sender_username: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
9972
9987
  readonly sender_is_chat: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
9988
+ readonly sender_is_me: v.BooleanSchema<undefined>;
9973
9989
  readonly mentions: v.OptionalSchema<v.ArraySchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>, undefined>, undefined>;
9974
9990
  readonly timestamp: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>;
9975
9991
  readonly edited_at: v.NullableSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>, undefined>;
@@ -10158,6 +10174,7 @@ export declare const ENTITIES: {
10158
10174
  readonly sender_name: v.NullableSchema<v.StringSchema<undefined>, undefined>;
10159
10175
  readonly sender_username: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
10160
10176
  readonly sender_is_chat: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
10177
+ readonly sender_is_me: v.BooleanSchema<undefined>;
10161
10178
  readonly mentions: v.OptionalSchema<v.ArraySchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>, undefined>, undefined>;
10162
10179
  readonly timestamp: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>;
10163
10180
  readonly edited_at: v.NullableSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>, undefined>;
@@ -10384,6 +10401,7 @@ export declare const ENTITIES: {
10384
10401
  readonly sender_name: v.NullableSchema<v.StringSchema<undefined>, undefined>;
10385
10402
  readonly sender_username: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
10386
10403
  readonly sender_is_chat: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
10404
+ readonly sender_is_me: v.BooleanSchema<undefined>;
10387
10405
  readonly mentions: v.OptionalSchema<v.ArraySchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>, undefined>, undefined>;
10388
10406
  readonly timestamp: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>;
10389
10407
  readonly edited_at: v.NullableSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>, undefined>;
@@ -10572,6 +10590,7 @@ export declare const ENTITIES: {
10572
10590
  readonly sender_name: v.NullableSchema<v.StringSchema<undefined>, undefined>;
10573
10591
  readonly sender_username: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
10574
10592
  readonly sender_is_chat: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
10593
+ readonly sender_is_me: v.BooleanSchema<undefined>;
10575
10594
  readonly mentions: v.OptionalSchema<v.ArraySchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>, undefined>, undefined>;
10576
10595
  readonly timestamp: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>;
10577
10596
  readonly edited_at: v.NullableSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>, undefined>;
@@ -12,6 +12,7 @@ export declare const project: v.StrictObjectSchema<{
12
12
  readonly ref: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, "a reference such as `note:42`">]>;
13
13
  readonly key: v.StringSchema<undefined>;
14
14
  readonly name: v.StringSchema<undefined>;
15
+ readonly kind: v.PicklistSchema<["project", "inbox"], undefined>;
15
16
  readonly type: v.PicklistSchema<["work", "client", "personal", "oss", "other"], undefined>;
16
17
  readonly organization_id: v.NullableSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>, undefined>;
17
18
  readonly scope: v.PicklistSchema<["personal", "work"], undefined>;
@@ -13,6 +13,7 @@ export const project = v.strictObject({
13
13
  ref: reference,
14
14
  key: text,
15
15
  name: text,
16
+ kind: v.picklist(["project", "inbox"]),
16
17
  type: v.picklist(["work", "client", "personal", "oss", "other"]),
17
18
  organization_id: v.nullable(id),
18
19
  scope: v.picklist(["personal", "work"]),
@@ -11,6 +11,7 @@ export declare const watchedMessage: v.StrictObjectSchema<{
11
11
  readonly sender_name: v.NullableSchema<v.StringSchema<undefined>, undefined>;
12
12
  readonly sender_username: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
13
13
  readonly sender_is_chat: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
14
+ readonly sender_is_me: v.BooleanSchema<undefined>;
14
15
  readonly mentions: v.OptionalSchema<v.ArraySchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>, undefined>, undefined>;
15
16
  readonly timestamp: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>;
16
17
  readonly edited_at: v.NullableSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>, undefined>;
@@ -491,6 +492,7 @@ export declare const messageEvent: v.VariantSchema<"event", [v.StrictObjectSchem
491
492
  readonly sender_name: v.NullableSchema<v.StringSchema<undefined>, undefined>;
492
493
  readonly sender_username: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
493
494
  readonly sender_is_chat: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
495
+ readonly sender_is_me: v.BooleanSchema<undefined>;
494
496
  readonly mentions: v.OptionalSchema<v.ArraySchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>, undefined>, undefined>;
495
497
  readonly timestamp: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>;
496
498
  readonly edited_at: v.NullableSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>, undefined>;
@@ -1078,6 +1080,7 @@ export declare const watchItem: v.UnionSchema<[v.StrictObjectSchema<{
1078
1080
  readonly sender_name: v.NullableSchema<v.StringSchema<undefined>, undefined>;
1079
1081
  readonly sender_username: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
1080
1082
  readonly sender_is_chat: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
1083
+ readonly sender_is_me: v.BooleanSchema<undefined>;
1081
1084
  readonly mentions: v.OptionalSchema<v.ArraySchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>, undefined>, undefined>;
1082
1085
  readonly timestamp: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>;
1083
1086
  readonly edited_at: v.NullableSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>, undefined>;
@@ -1557,6 +1560,7 @@ export declare const watchItem: v.UnionSchema<[v.StrictObjectSchema<{
1557
1560
  readonly sender_name: v.NullableSchema<v.StringSchema<undefined>, undefined>;
1558
1561
  readonly sender_username: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
1559
1562
  readonly sender_is_chat: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
1563
+ readonly sender_is_me: v.BooleanSchema<undefined>;
1560
1564
  readonly mentions: v.OptionalSchema<v.ArraySchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>, undefined>, undefined>;
1561
1565
  readonly timestamp: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>;
1562
1566
  readonly edited_at: v.NullableSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>, undefined>;
@@ -16,6 +16,7 @@ export declare const messageThread: v.StrictObjectSchema<{
16
16
  readonly sender_name: v.NullableSchema<v.StringSchema<undefined>, undefined>;
17
17
  readonly sender_username: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
18
18
  readonly sender_is_chat: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
19
+ readonly sender_is_me: v.BooleanSchema<undefined>;
19
20
  readonly mentions: v.OptionalSchema<v.ArraySchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>, undefined>, undefined>;
20
21
  readonly timestamp: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>;
21
22
  readonly edited_at: v.NullableSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>, undefined>;
@@ -228,6 +229,7 @@ export declare const messageContext: v.UnionSchema<[v.StrictObjectSchema<{
228
229
  readonly sender_name: v.NullableSchema<v.StringSchema<undefined>, undefined>;
229
230
  readonly sender_username: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
230
231
  readonly sender_is_chat: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
232
+ readonly sender_is_me: v.BooleanSchema<undefined>;
231
233
  readonly mentions: v.OptionalSchema<v.ArraySchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>, undefined>, undefined>;
232
234
  readonly timestamp: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>;
233
235
  readonly edited_at: v.NullableSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>, undefined>;
@@ -421,6 +423,7 @@ export declare const messageContext: v.UnionSchema<[v.StrictObjectSchema<{
421
423
  readonly sender_name: v.NullableSchema<v.StringSchema<undefined>, undefined>;
422
424
  readonly sender_username: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
423
425
  readonly sender_is_chat: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
426
+ readonly sender_is_me: v.BooleanSchema<undefined>;
424
427
  readonly mentions: v.OptionalSchema<v.ArraySchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>, undefined>, undefined>;
425
428
  readonly timestamp: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>;
426
429
  readonly edited_at: v.NullableSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>, undefined>;
@@ -12,6 +12,7 @@ export declare const messageWrite: v.StrictObjectSchema<{
12
12
  readonly sender_name: v.NullableSchema<v.StringSchema<undefined>, undefined>;
13
13
  readonly sender_username: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
14
14
  readonly sender_is_chat: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
15
+ readonly sender_is_me: v.BooleanSchema<undefined>;
15
16
  readonly mentions: v.OptionalSchema<v.ArraySchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>, undefined>, undefined>;
16
17
  readonly timestamp: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>;
17
18
  readonly edited_at: v.NullableSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>, undefined>;
@@ -201,6 +202,7 @@ export declare const messageWrite: v.StrictObjectSchema<{
201
202
  readonly sender_name: v.NullableSchema<v.StringSchema<undefined>, undefined>;
202
203
  readonly sender_username: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
203
204
  readonly sender_is_chat: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
205
+ readonly sender_is_me: v.BooleanSchema<undefined>;
204
206
  readonly mentions: v.OptionalSchema<v.ArraySchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>, undefined>, undefined>;
205
207
  readonly timestamp: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>;
206
208
  readonly edited_at: v.NullableSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>, undefined>;
@@ -398,6 +400,7 @@ export declare const messageSend: v.UnionSchema<[v.StrictObjectSchema<{
398
400
  readonly sender_name: v.NullableSchema<v.StringSchema<undefined>, undefined>;
399
401
  readonly sender_username: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
400
402
  readonly sender_is_chat: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
403
+ readonly sender_is_me: v.BooleanSchema<undefined>;
401
404
  readonly mentions: v.OptionalSchema<v.ArraySchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>, undefined>, undefined>;
402
405
  readonly timestamp: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>;
403
406
  readonly edited_at: v.NullableSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>, undefined>;
@@ -587,6 +590,7 @@ export declare const messageSend: v.UnionSchema<[v.StrictObjectSchema<{
587
590
  readonly sender_name: v.NullableSchema<v.StringSchema<undefined>, undefined>;
588
591
  readonly sender_username: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
589
592
  readonly sender_is_chat: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
593
+ readonly sender_is_me: v.BooleanSchema<undefined>;
590
594
  readonly mentions: v.OptionalSchema<v.ArraySchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>, undefined>, undefined>;
591
595
  readonly timestamp: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>;
592
596
  readonly edited_at: v.NullableSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>, undefined>;
@@ -11,6 +11,7 @@ export declare const message: v.StrictObjectSchema<{
11
11
  readonly sender_name: v.NullableSchema<v.StringSchema<undefined>, undefined>;
12
12
  readonly sender_username: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
13
13
  readonly sender_is_chat: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
14
+ readonly sender_is_me: v.BooleanSchema<undefined>;
14
15
  readonly mentions: v.OptionalSchema<v.ArraySchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>, undefined>, undefined>;
15
16
  /** When it was sent. */
16
17
  readonly timestamp: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>;
@@ -23,6 +23,7 @@ export const message = v.strictObject({
23
23
  sender_name: v.nullable(text),
24
24
  sender_username: v.optional(text),
25
25
  sender_is_chat: v.optional(v.boolean()),
26
+ sender_is_me: v.boolean(),
26
27
  mentions: v.optional(v.array(id)),
27
28
  /** When it was sent. */
28
29
  timestamp: time,
@@ -35,6 +35,7 @@ export declare const storeExport: v.UnionSchema<[v.StrictObjectSchema<{
35
35
  readonly sender_name: v.NullableSchema<v.StringSchema<undefined>, undefined>;
36
36
  readonly sender_username: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
37
37
  readonly sender_is_chat: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
38
+ readonly sender_is_me: v.BooleanSchema<undefined>;
38
39
  readonly mentions: v.OptionalSchema<v.ArraySchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>, undefined>, undefined>;
39
40
  readonly timestamp: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>;
40
41
  readonly edited_at: v.NullableSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>, undefined>;
@@ -23,6 +23,13 @@ export interface Searched {
23
23
  }
24
24
  /** Everything the import asks of a mail client, so a transport can be replaced without touching the sync. */
25
25
  export interface MailSource {
26
+ /**
27
+ * How many messages one `list` call reads in about one request's time, parallel connections included; a budgeted
28
+ * sync lists that many at a time, so a request of the budget is one call. Absent: 200.
29
+ */
30
+ listBatch?: number;
31
+ /** The same for `fetchRaw`. Absent: 50. */
32
+ fetchBatch?: number;
26
33
  /**
27
34
  * Every message in `folder` received since `since`; all or nothing, since deletions are proved from it.
28
35
  * `headers` also reads From, To, Cc and the list fields, for the probe and the owner's rules.
@@ -1,3 +1,4 @@
1
+ import type { BudgetStop, RunBudget } from "../background/budget.js";
1
2
  import type { LoadEngine } from "../readers/types.js";
2
3
  import type { AccountKey, MessageStore } from "../store/index.js";
3
4
  import { type TagOutcome } from "./rule-tags.js";
@@ -31,6 +32,14 @@ export interface MailSyncResult {
31
32
  deleted: number;
32
33
  /** False when `max` stopped the run before every new message was read; the next run continues. */
33
34
  complete: boolean;
35
+ /** `partial`: a budgeted run stopped before the whole window was read; the next run goes on. */
36
+ state?: "partial" | "complete";
37
+ /** Why a budgeted run stopped early: its request budget, its deadline, or a cancel. */
38
+ stopped?: BudgetStop;
39
+ /** Messages of the window this run did not get to read; a budgeted run only. */
40
+ remaining?: number;
41
+ /** Requests a budgeted run spent. */
42
+ requests?: number;
34
43
  /** Emails that could not be read or parsed; they are tried again next run. */
35
44
  unreadable?: {
36
45
  message: string;
@@ -85,7 +94,13 @@ export interface MailSyncOptions {
85
94
  index?: (store: MessageStore, key: AccountKey) => Promise<MailIndexed>;
86
95
  /** Stops between batches of emails, after saving the resume point. */
87
96
  signal?: AbortSignal;
97
+ /**
98
+ * Makes the run budgeted: it reads the window in rounds, one request of the budget per call to the source, saves
99
+ * after each, stops when the budget says so and answers `state: "partial"`. A message the source could not give
100
+ * is tried once more at the end of the run and, if it still fails, left for the next one. `max` defaults to no limit.
101
+ */
102
+ budget?: RunBudget;
88
103
  }
89
- export declare const syncMail: (source: MailSource, store: MessageStore, { account, since, max, maxBodyChars, maxAttachmentChars, now, ages, loadEngine, retryAttachments, rescan, resumeFrom, index, signal, }: MailSyncOptions) => Promise<MailSyncResult>;
104
+ export declare const syncMail: (source: MailSource, store: MessageStore, options: MailSyncOptions) => Promise<MailSyncResult>;
90
105
  /** Failures a newer install mends: the reader was missing, not the file at fault, so reading again can succeed. */
91
106
  export declare const RETRYABLE_ATTACHMENTS: string[];
package/dist/mail/sync.js CHANGED
@@ -53,7 +53,100 @@ const readAttachments = async (mail, messageId, { loadEngine, maxAttachmentChars
53
53
  }
54
54
  return files;
55
55
  };
56
- export const syncMail = 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, }) => {
56
+ const LIST_SLICE = 200;
57
+ const FETCH_SLICE = 50;
58
+ const keyOf = (folder, uid) => `${folder}\0${uid}`;
59
+ export const syncMail = async (source, store, options) => {
60
+ const { budget, index } = options;
61
+ if (budget === undefined || options.retryAttachments || options.account.mode === "mbox")
62
+ return syncRound(source, store, options);
63
+ const plan = {
64
+ budget,
65
+ tried: new Set(),
66
+ failed: new Set(),
67
+ searches: new Map(),
68
+ modes: new Map(),
69
+ unreadable: new Map(),
70
+ unlisted: new Set(),
71
+ stopped: null,
72
+ remaining: 0,
73
+ asked: 0,
74
+ };
75
+ const rounds = [];
76
+ const goOn = async () => {
77
+ for (;;) {
78
+ plan.asked = 0;
79
+ plan.remaining = 0;
80
+ try {
81
+ rounds.push(await syncRound(source, store, { ...options, index: undefined, max: options.max ?? Number.POSITIVE_INFINITY }, plan));
82
+ }
83
+ catch (error) {
84
+ // A request cut at the deadline, or failed after the budget was spent, is the run's end, not its failure: what
85
+ // earlier rounds saved is kept and the next run goes on. While the budget has room the error is real.
86
+ const transient = error instanceof CliError && (error.code === "timeout" || error.code === "network_error");
87
+ const stop = transient && rounds.length > 0 ? budget.take() : null;
88
+ if (stop === null)
89
+ throw error;
90
+ plan.stopped = stop;
91
+ plan.remaining = Math.max(plan.remaining, 1);
92
+ return;
93
+ }
94
+ if (plan.stopped !== null || plan.remaining === 0)
95
+ return;
96
+ }
97
+ };
98
+ await goOn();
99
+ const remaining = plan.remaining;
100
+ // A message the server failed on once is often fine a minute later; only one more try, then the next run.
101
+ if (plan.stopped === null && plan.failed.size > 0) {
102
+ plan.only = new Set(plan.failed);
103
+ plan.failed.clear();
104
+ plan.tried.clear();
105
+ await goOn();
106
+ }
107
+ const last = rounds.at(-1);
108
+ const sum = (pick) => rounds.reduce((total, round) => total + pick(round), 0);
109
+ const unreadable = [
110
+ ...[...plan.unreadable].map(([message, reason]) => ({ message, reason })),
111
+ ...[...plan.unlisted].map((key) => ({
112
+ message: `uid:${key.replace("\0", ":")}`,
113
+ reason: "the server did not return it",
114
+ })),
115
+ ];
116
+ const complete = last.complete && plan.stopped === null && unreadable.length === 0 && remaining === 0;
117
+ const account = { provider: "email", account: options.account.address.toLowerCase() };
118
+ const indexed = plan.stopped === null ? await index?.(store, account) : undefined;
119
+ const deletionsSkipped = rounds.map((round) => round.deletionsSkipped).findLast((text) => text !== undefined);
120
+ const { unreadable: _unreadable, ...rest } = last;
121
+ return {
122
+ ...rest,
123
+ listed: sum((round) => round.listed),
124
+ saved: sum((round) => round.saved),
125
+ alreadyStored: sum((round) => round.alreadyStored),
126
+ skipped: sum((round) => round.skipped),
127
+ envelopes: sum((round) => round.envelopes),
128
+ deleted: sum((round) => round.deleted),
129
+ complete,
130
+ state: complete ? "complete" : "partial",
131
+ remaining,
132
+ requests: budget.used,
133
+ ...(plan.stopped === null ? {} : { stopped: plan.stopped }),
134
+ ...(indexed === undefined ? {} : { indexed }),
135
+ ...(unreadable.length ? { unreadable } : {}),
136
+ ...(deletionsSkipped === undefined ? {} : { deletionsSkipped }),
137
+ ...(rounds.some((round) => round.pass === "resumed") ? { pass: "resumed" } : {}),
138
+ ...(rounds.some((round) => round.attachments)
139
+ ? { attachments: rounds.flatMap((round) => round.attachments ?? []) }
140
+ : {}),
141
+ ...(rounds.some((round) => round.tagsReused)
142
+ ? { tagsReused: rounds.flatMap((round) => round.tagsReused ?? []) }
143
+ : {}),
144
+ ...(rounds.some((round) => round.tagsSkipped)
145
+ ? { tagsSkipped: rounds.flatMap((round) => round.tagsSkipped ?? []) }
146
+ : {}),
147
+ };
148
+ };
149
+ 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) => {
57
150
  if (retryAttachments)
58
151
  return retryUnread({
59
152
  store,
@@ -94,10 +187,24 @@ export const syncMail = async (source, store, { account, since, max = 200, maxBo
94
187
  if (point?.complete && point.size === mboxStamp.size && point.mtimeMs === mboxStamp.mtimeMs)
95
188
  mboxPoint = point;
96
189
  }
190
+ let capped = false;
97
191
  for (const folder of folders) {
98
192
  if (mboxPoint !== undefined)
99
193
  break;
100
- const searched = source.search === undefined || snapshot ? undefined : await source.search(since, folder);
194
+ let searched;
195
+ if (source.search !== undefined && !snapshot) {
196
+ searched = plan?.searches.get(folder);
197
+ if (searched === undefined) {
198
+ const stop = plan?.budget.take();
199
+ if (plan && stop) {
200
+ plan.stopped = stop;
201
+ capped = true;
202
+ continue;
203
+ }
204
+ searched = await source.search(since, folder);
205
+ plan?.searches.set(folder, searched);
206
+ }
207
+ }
101
208
  let wanted = searched;
102
209
  if (searched !== undefined) {
103
210
  searches.set(folder, searched);
@@ -107,18 +214,59 @@ export const syncMail = async (source, store, { account, since, max = 200, maxBo
107
214
  const point = fresh ? undefined : kept;
108
215
  if (point !== undefined && point.validity === searched.validity && point.rules === ruleSet) {
109
216
  earlier.set(folder, point);
110
- if (searched.uids.length >= resumeFrom &&
111
- Date.parse(point.full.since) <= since.getTime() &&
112
- startedAt - Date.parse(point.full.at) < FULL_PASS_MS) {
217
+ const mode = plan?.modes.get(folder);
218
+ const usable = Date.parse(point.full.since) <= since.getTime() && startedAt - Date.parse(point.full.at) < FULL_PASS_MS;
219
+ // A budgeted run goes on with an unfinished pass however small its window is: listing it whole again would
220
+ // ask for the same newest messages every run.
221
+ const unfinished = plan !== undefined && searched.uids.some((uid) => !within(point.done, Number(uid)));
222
+ if (mode === "resumed" ||
223
+ (mode === undefined && usable && (searched.uids.length >= resumeFrom || unfinished))) {
113
224
  resumed.add(folder);
114
225
  wanted = { ...searched, uids: searched.uids.filter((uid) => !within(point.done, Number(uid))) };
115
226
  }
116
227
  }
228
+ if (plan !== undefined) {
229
+ plan.modes.set(folder, resumed.has(folder) ? "resumed" : "full");
230
+ const open = wanted.uids.filter((uid) => plan.only
231
+ ? plan.only.has(keyOf(folder, uid)) && !plan.tried.has(keyOf(folder, uid))
232
+ : !plan.tried.has(keyOf(folder, uid)));
233
+ const slice = [...open].sort((a, b) => Number(b) - Number(a)).slice(0, source.listBatch ?? LIST_SLICE);
234
+ plan.remaining += open.length - slice.length;
235
+ wanted = { ...searched, uids: slice };
236
+ if (open.length > slice.length)
237
+ capped = true;
238
+ }
239
+ }
240
+ if (plan !== undefined && wanted !== undefined && wanted.uids.length === 0)
241
+ continue;
242
+ if (plan !== undefined) {
243
+ const stop = plan.budget.take();
244
+ if (stop) {
245
+ plan.stopped = stop;
246
+ capped = true;
247
+ plan.remaining += (wanted?.uids ?? []).length;
248
+ continue;
249
+ }
250
+ for (const uid of wanted?.uids ?? [])
251
+ plan.tried.add(keyOf(folder, uid));
252
+ plan.asked += (wanted?.uids ?? []).length;
117
253
  }
118
254
  const found = await source.list(since, folder, {
119
255
  headers: rules.length > 0,
120
256
  ...(wanted === undefined ? {} : { searched: wanted }),
121
257
  });
258
+ if (plan !== undefined && wanted !== undefined) {
259
+ const got = new Set(found.map(({ uid }) => uid));
260
+ for (const uid of wanted.uids) {
261
+ const key = keyOf(folder, uid);
262
+ if (got.has(uid))
263
+ plan.unlisted.delete(key);
264
+ else {
265
+ plan.failed.add(key);
266
+ plan.unlisted.add(key);
267
+ }
268
+ }
269
+ }
122
270
  // Spreading a whole mailbox into push() overflows the stack past ~120,000 emails.
123
271
  for (const item of found)
124
272
  collected.push(item);
@@ -151,6 +299,8 @@ export const syncMail = async (source, store, { account, since, max = 200, maxBo
151
299
  let skipped;
152
300
  if (snapshot)
153
301
  skipped = "an mbox file is a snapshot; mail missing from it is not proven deleted";
302
+ else if (plan !== undefined && (capped || plan.tried.size > plan.asked || plan.only !== undefined))
303
+ skipped = "this run read the window in parts; a run that lists all of it at once checks deletions";
154
304
  else if (resumed.size > 0)
155
305
  skipped =
156
306
  "this run listed only mail not read before; a full listing, at least daily or with --rescan, checks deletions";
@@ -355,14 +505,33 @@ export const syncMail = async (source, store, { account, since, max = 200, maxBo
355
505
  await tagStored(item);
356
506
  await saveNow();
357
507
  }
358
- for (let start = 0; start < pending.length; start += FETCH_CHUNK) {
508
+ const fetchChunk = plan === undefined ? FETCH_CHUNK : (source.fetchBatch ?? FETCH_SLICE);
509
+ for (let start = 0; start < pending.length; start += fetchChunk) {
359
510
  await stopIfAborted();
360
- const chunk = pending.slice(start, start + FETCH_CHUNK);
361
- const raws = await source.fetchRaw(chunk);
511
+ const chunk = pending.slice(start, start + fetchChunk);
512
+ if (plan !== undefined) {
513
+ const stop = plan.budget.take();
514
+ if (stop) {
515
+ plan.stopped = stop;
516
+ full = true;
517
+ break;
518
+ }
519
+ }
520
+ let raws;
521
+ try {
522
+ raws = await source.fetchRaw(chunk);
523
+ }
524
+ catch (error) {
525
+ // What this run saved stays saved: the next one goes on from it.
526
+ await saveNow(true);
527
+ throw error;
528
+ }
362
529
  await stopIfAborted();
363
530
  // Every email of a chunk failing is the connection or the login, not the mail: stop instead of trying the rest.
364
- if (chunk.length > 1 && raws.every((raw) => raw instanceof Error))
531
+ if (chunk.length > 1 && raws.every((raw) => raw instanceof Error)) {
532
+ await saveNow(true);
365
533
  throw raws[0];
534
+ }
366
535
  for (const [index, item] of chunk.entries()) {
367
536
  let mail;
368
537
  try {
@@ -372,9 +541,15 @@ export const syncMail = async (source, store, { account, since, max = 200, maxBo
372
541
  mail = await parseMail(raw, maxBodyChars);
373
542
  }
374
543
  catch (error) {
375
- unreadable.push({ message: item.messageId, reason: error instanceof Error ? error.message : String(error) });
544
+ const reason = error instanceof Error ? error.message : String(error);
545
+ unreadable.push({ message: item.messageId, reason });
546
+ if (plan !== undefined) {
547
+ plan.unreadable.set(item.messageId, reason);
548
+ plan.failed.add(keyOf(item.folder ?? folders[0], item.uid));
549
+ }
376
550
  continue;
377
551
  }
552
+ plan?.unreadable.delete(item.messageId);
378
553
  const header = mailHeadersOf(raws[index]);
379
554
  const files = await readAttachments(mail, item.messageId, { loadEngine, maxAttachmentChars, at: startedAt }, attachments);
380
555
  await store.mail.saveThread({
@@ -426,7 +601,8 @@ export const syncMail = async (source, store, { account, since, max = 200, maxBo
426
601
  await store.mail.setFlags(accountId, new Map([...labelsOf].flatMap(([id, { seen, flagged }]) => seen === undefined && flagged === undefined
427
602
  ? []
428
603
  : [[id, { ...(seen === undefined ? {} : { read: seen }), ...(flagged === undefined ? {} : { flagged }) }]])), startedAt);
429
- const complete = !full && unreadable.length === 0;
604
+ const incomplete = plan !== undefined && (capped || plan.stopped !== null || plan.failed.size > 0);
605
+ const complete = !full && !incomplete && unreadable.length === 0 && (plan?.unreadable.size ?? 0) === 0;
430
606
  const bulk = new Map(listed.filter((item) => item.headers?.bulk).map((item) => [item.messageId, [bulkBox.externalId]]));
431
607
  if (bulk.size)
432
608
  await store.mail.setMailboxes(accountId, [bulkBox], bulk, startedAt);
@@ -41,6 +41,17 @@ export interface FakeMailbox {
41
41
  moveFails?: boolean;
42
42
  /** UIDs whose raw bytes cannot be read: `fetchRaw` answers an Error for each of them, and only for them. */
43
43
  unreadable?: string[];
44
+ /** UIDs that fail once, as a server's backend error does: `list` leaves each out, `fetchRaw` answers an Error. */
45
+ failOnce?: string[];
46
+ /** Calls the source answered, by kind, so a test counts a budget's requests. */
47
+ calls?: {
48
+ search: number;
49
+ list: number;
50
+ fetchRaw: number;
51
+ };
52
+ /** What the source tells a budgeted sync about its batch sizes. */
53
+ listBatch?: number;
54
+ fetchBatch?: number;
44
55
  /** What the source was asked: the UIDs of each listing, and `msgid:<id>` for each `find`. */
45
56
  asked?: string[];
46
57
  }
@@ -64,9 +64,26 @@ export const fakeMailSource = (mailbox) => {
64
64
  .map((m) => m.uid),
65
65
  };
66
66
  };
67
+ const failedOnce = new Set();
68
+ const failsNow = (uid) => {
69
+ if (!mailbox.failOnce?.includes(uid) || failedOnce.has(uid))
70
+ return false;
71
+ failedOnce.add(uid);
72
+ return true;
73
+ };
74
+ const count = (kind) => {
75
+ if (mailbox.calls)
76
+ mailbox.calls[kind] += 1;
77
+ };
67
78
  return {
68
- search,
79
+ ...(mailbox.listBatch === undefined ? {} : { listBatch: mailbox.listBatch }),
80
+ ...(mailbox.fetchBatch === undefined ? {} : { fetchBatch: mailbox.fetchBatch }),
81
+ search: async (since, folder) => {
82
+ count("search");
83
+ return search(since, folder);
84
+ },
69
85
  list: async (since, folder, options) => {
86
+ count("list");
70
87
  const { uids } = options?.searched ?? (await search(since, folder));
71
88
  if (uids.length > 0)
72
89
  mailbox.asked?.push(uids.join(","));
@@ -74,7 +91,7 @@ export const fakeMailSource = (mailbox) => {
74
91
  throw failure("the header fetch was refused");
75
92
  const wanted = new Set(uids);
76
93
  return inFolder(folder)
77
- .filter((m) => wanted.has(m.uid))
94
+ .filter((m) => wanted.has(m.uid) && !failsNow(m.uid))
78
95
  .map((m) => listingOf(m, options?.headers ?? false, folder));
79
96
  },
80
97
  find: async (messageIds, folder, options) => {
@@ -112,12 +129,15 @@ export const fakeMailSource = (mailbox) => {
112
129
  if (messageIds.includes(m.messageId))
113
130
  m.labels = [...new Set([...(m.labels ?? []), ...labels])];
114
131
  },
115
- fetchRaw: async (items) => items.map((item) => {
116
- const m = mailbox.messages.find((each) => each.uid === item.uid);
117
- if (m === undefined || mailbox.unreadable?.includes(item.uid))
118
- return failure(`email ${item.uid} was not read`);
119
- return rawOf(m);
120
- }),
132
+ fetchRaw: async (items) => {
133
+ count("fetchRaw");
134
+ return items.map((item) => {
135
+ const m = mailbox.messages.find((each) => each.uid === item.uid);
136
+ if (m === undefined || mailbox.unreadable?.includes(item.uid) || failsNow(item.uid))
137
+ return failure(`email ${item.uid} was not read`);
138
+ return rawOf(m);
139
+ });
140
+ },
121
141
  };
122
142
  };
123
143
  /**
@@ -7,6 +7,8 @@ export interface RunError {
7
7
  class: string;
8
8
  code?: string;
9
9
  reason?: string;
10
+ /** The transport's own code (`NoConnection`, `ETIMEDOUT`, `UNAVAILABLE`), kept so a failed run says what broke. */
11
+ cause_code?: string;
10
12
  message?: string;
11
13
  /** Ours, not the messenger's: `messages.send`. */
12
14
  operation?: string;
@@ -10,6 +10,9 @@ export const errorDetailOf = (error, response) => {
10
10
  const thrown = error instanceof Error ? error : undefined;
11
11
  const code = isCliFailure(error) ? error.code : codeOf(error);
12
12
  const reason = typeof details.reason === "string" ? details.reason : undefined;
13
+ const causeCode = typeof details.cause_code === "string" && /^[A-Za-z0-9_.-]{1,40}$/.test(details.cause_code)
14
+ ? details.cause_code
15
+ : undefined;
13
16
  const message = thrown ? redactText(thrown.message) : undefined;
14
17
  const operation = stringOf(details.operation) ?? response?.operation;
15
18
  const status = numberOf(details.status) ?? response?.status;
@@ -30,6 +33,7 @@ export const errorDetailOf = (error, response) => {
30
33
  class: classOf(error),
31
34
  ...(code === undefined ? {} : { code }),
32
35
  ...(reason === undefined ? {} : { reason }),
36
+ ...(causeCode === undefined ? {} : { cause_code: causeCode }),
33
37
  ...(message ? { message } : {}),
34
38
  ...(operation === undefined ? {} : { operation }),
35
39
  ...(http ? { http } : {}),
@@ -19,6 +19,8 @@ export interface Hearing {
19
19
  unheard: Voice[];
20
20
  /** Why some were not heard — the first reason; the messages are still worth showing. */
21
21
  problem?: string;
22
+ /** Set under `--offline`: the command (`<app> <profile>`) that hears a message online, which `--offline` never does. */
23
+ offline?: string;
22
24
  }
23
25
  export declare const keyOf: ({ chatId, messageId }: Voice) => string;
24
26
  /** Telegram says `voice`; MAX says `audio` with Ogg in it. */
@@ -119,6 +119,16 @@ export const hearingMissing = (hearing, transcribe) => {
119
119
  return [{ field: "transcript", why: `not transcribed: ${hearing.problem}`, step: "messages.transcribe" }];
120
120
  if (hearing.unheard.length === 0)
121
121
  return [];
122
+ if (hearing.offline !== undefined) {
123
+ const commands = hearing.unheard.map(({ chatId, messageId }) => `${hearing.offline} messages transcribe ${chatId} ${messageId}`);
124
+ return [
125
+ {
126
+ field: "transcript",
127
+ why: `--offline reads only transcripts already stored; ${hearing.unheard.length} voice message(s) have none: ${commands.join("; ")}`,
128
+ step: "messages.transcribe",
129
+ },
130
+ ];
131
+ }
122
132
  const ids = hearing.unheard.map((voice) => voice.messageId).join(", ");
123
133
  return [
124
134
  {
@@ -13,10 +13,12 @@ export const PROJECTS_QUERY = {
13
13
  entity: "project",
14
14
  backend: "sql",
15
15
  fields: queryFieldsOf(project, {
16
- native: ["id", "key", "type", "organization_id", "scope", "created_at"],
16
+ native: ["id", "key", "name", "kind", "type", "organization_id", "scope", "created_at"],
17
17
  examples: {
18
18
  id: "id:1",
19
19
  key: "key:SMP",
20
+ name: "name:*tart*",
21
+ kind: "kind:inbox",
20
22
  type: "type:work",
21
23
  organization_id: "organization_id:1",
22
24
  scope: "scope:work",
@@ -45,6 +45,8 @@ export interface PeopleStore extends AccountPeople {
45
45
  /** The person a `person:<uid>` reference names. */
46
46
  personSeenInAccounts(uid: string, accountIds: readonly number[]): Promise<boolean>;
47
47
  personByUid(uid: string): Promise<PersonRecord | undefined>;
48
+ /** The person marked as the owner, with every identity linked to them; `undefined` when none is. */
49
+ owner(): Promise<PersonRecord | undefined>;
48
50
  /** Accepted facts, the owner's notes and open tasks about them; tasks of an account only if `accounts` holds it. */
49
51
  preparation(uid: string, options: {
50
52
  accounts: readonly AccountKey[];
@@ -1,4 +1,6 @@
1
+ import { CliError } from "@wirecat/cli-base";
1
2
  import { keysOver } from "./keys.js";
3
+ import { ownerPerson } from "./sqlite/actors.js";
2
4
  import * as identities from "./sqlite/identities.js";
3
5
  import { linkToOwner } from "./sqlite/own-identities.js";
4
6
  import * as personLinks from "./sqlite/person-links.js";
@@ -59,6 +61,16 @@ export const peopleStoreOver = (context, keyed) => {
59
61
  personOf: async (identity) => personLinks.personOf(context, identity),
60
62
  personSeenInAccounts: async (uid, accountIds) => personSeenInAccounts(context, uid, accountIds),
61
63
  personByUid: async (uid) => personLinks.personByUid(context, uid),
64
+ owner: async () => {
65
+ try {
66
+ return personLinks.personByUid(context, String(ownerPerson(database).id));
67
+ }
68
+ catch (error) {
69
+ if (error instanceof CliError && error.code === "configuration_error")
70
+ return undefined;
71
+ throw error;
72
+ }
73
+ },
62
74
  preparation: async (uid, options) => personPreparation(context, uid, options),
63
75
  linkIdentities: async (person, other, options) => {
64
76
  return write(database, () => personLinks.linkIdentities(context, person, other, options));
@@ -1,4 +1,4 @@
1
- import type { QueryAst } from "@wirecat/cli-base/query";
1
+ import { type QueryAst } from "@wirecat/cli-base/query";
2
2
  import type { AccountKey } from "../types.js";
3
3
  import { RELATION_KINDS } from "./link-kinds.js";
4
4
  import { type MeetingProjectsStore } from "./meeting-projects.js";
@@ -78,6 +78,8 @@ export interface Project {
78
78
  ref: string;
79
79
  key: string;
80
80
  name: string;
81
+ /** `inbox`: the per-account project that holds an account's tasks; listed only when asked for. */
82
+ kind: "project" | "inbox";
81
83
  type: (typeof PROJECT_TYPES)[number];
82
84
  organizationId: string | null;
83
85
  scope: (typeof SCOPES)[number];
@@ -1,4 +1,5 @@
1
1
  import { CliError } from "@wirecat/cli-base";
2
+ import { walkQuery } from "@wirecat/cli-base/query";
2
3
  import { parseLocator } from "../../domain/locator.js";
3
4
  import { formatReference, parseReference } from "../../domain/references.js";
4
5
  import { normalizeTag } from "../../domain/tags.js";
@@ -11,7 +12,7 @@ import { meetingProjectsStoreOver } from "./meeting-projects.js";
11
12
  import { insertLink, linkOf } from "./notes.js";
12
13
  import { queryFilter } from "./query-filter.js";
13
14
  import { addTags as addThingTags, canonicalTagNamed, createTag, labelsOf, liveTagging, removeTags as removeThingTags, setMainTopic, } from "./tags.js";
14
- import { TASK_KEY_PREFIXES } from "./task-keys.js";
15
+ import { INBOX_KEY_LENGTH, TASK_KEY_PREFIXES } from "./task-keys.js";
15
16
  import { inboxKey, taskAccountOf, taskIdOf, taskRowOf } from "./tasks.js";
16
17
  import { referenceOfThing, stateOfThing, storedThing, thingOf } from "./things.js";
17
18
  import { write } from "./transaction.js";
@@ -199,6 +200,7 @@ export const knowledgeStoreOver = (context) => {
199
200
  ref: `project:${row.id}`,
200
201
  key: String(row.key),
201
202
  name: String(row.name),
203
+ kind: String(row.key).length === INBOX_KEY_LENGTH ? "inbox" : "project",
202
204
  type: row.type,
203
205
  organizationId: row.organization_id == null ? null : String(row.organization_id),
204
206
  scope: row.scope,
@@ -489,17 +491,20 @@ export const knowledgeStoreOver = (context) => {
489
491
  return projectOf(row);
490
492
  }),
491
493
  projects: async (query) => {
494
+ const asksKind = query !== undefined && walkQuery(query.root).some((node) => node.field === "kind");
492
495
  const where = query &&
493
496
  queryFilter(query, {
494
497
  id: { type: "kw", sql: "CAST(id AS TEXT)" },
495
498
  key: { type: "kw", sql: "key" },
499
+ name: { type: "kw", sql: "name" },
500
+ kind: { type: "enum", sql: `CASE WHEN length(key) = ${INBOX_KEY_LENGTH} THEN 'inbox' ELSE 'project' END` },
496
501
  type: { type: "enum", sql: "type" },
497
502
  organization_id: { type: "kw", sql: "CAST(organization_id AS TEXT)" },
498
503
  scope: { type: "enum", sql: "scope" },
499
504
  created_at: { type: "time", sql: "created_at" },
500
505
  });
501
506
  return database
502
- .prepare(`SELECT * FROM projects WHERE deleted_at IS NULL${where ? ` AND (${where.sql})` : ""} ORDER BY name, id LIMIT 500`)
507
+ .prepare(`SELECT * FROM projects WHERE deleted_at IS NULL${asksKind ? "" : ` AND length(key) <> ${INBOX_KEY_LENGTH}`}${where ? ` AND (${where.sql})` : ""} ORDER BY name, id LIMIT 500`)
503
508
  .all(...(where?.params ?? []))
504
509
  .map(projectOf);
505
510
  },
@@ -8,6 +8,7 @@ export declare const TASK_KEY_PREFIXES: Readonly<Record<TaskKind, string>>;
8
8
  */
9
9
  export declare const typedKey: (database: CacheDatabase, kind: TaskKind) => string;
10
10
  /** One inbox project per task account (`telegram:100`): derived from the account text alone, no `-` in it. */
11
+ export declare const INBOX_KEY_LENGTH = 10;
11
12
  export declare const inboxKey: (account: string) => string;
12
13
  /** An inbox made before its messenger saved the account learns it here, not only on its next task. */
13
14
  export declare const linkInbox: (database: CacheDatabase, account: string, accountId: number) => void;
@@ -22,6 +22,7 @@ export const typedKey = (database, kind) => {
22
22
  }
23
23
  };
24
24
  /** One inbox project per task account (`telegram:100`): derived from the account text alone, no `-` in it. */
25
+ export const INBOX_KEY_LENGTH = 10;
25
26
  export const inboxKey = (account) => `IN${createHash("sha256").update(account).digest("hex").slice(0, 8).toUpperCase()}`;
26
27
  /** An inbox made before its messenger saved the account learns it here, not only on its next task. */
27
28
  export const linkInbox = (database, account, accountId) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wirecat/cli-core",
3
- "version": "0.472.0",
3
+ "version": "0.473.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",