@wirecat/cli-core 0.555.0 → 0.557.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 +59 -0
- package/dist/cli/config-command.js +64 -2
- package/dist/cli/config-issues.d.ts +2 -0
- package/dist/cli/config-issues.js +11 -3
- package/dist/cli/config-repair.d.ts +26 -0
- package/dist/cli/config-repair.js +252 -0
- package/dist/cli/messenger/tasks-analysis-command.d.ts +8 -0
- package/dist/cli/messenger/tasks-analysis-command.js +184 -0
- package/dist/cli/messenger/tasks-command.js +11 -2
- package/dist/cli/steps.js +10 -0
- package/dist/domain/finance.d.ts +40 -0
- package/dist/domain/finance.js +39 -0
- package/dist/domain/money.d.ts +29 -0
- package/dist/domain/money.js +98 -0
- package/dist/domain/ref-summaries.js +2 -0
- package/dist/domain/references.d.ts +1 -1
- package/dist/domain/references.js +2 -0
- package/dist/entities/index.d.ts +64 -2
- package/dist/entities/index.js +5 -2
- package/dist/entities/task-results.d.ts +72 -0
- package/dist/entities/task-results.js +40 -1
- package/dist/errors/reasons.d.ts +1 -1
- package/dist/errors/reasons.js +24 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/mail/cli/index.d.ts +1 -0
- package/dist/mail/cli/index.js +3 -0
- package/dist/mail/cli/marks.d.ts +26 -0
- package/dist/mail/cli/marks.js +51 -0
- package/dist/mail/cli/review.js +70 -1
- package/dist/mail/index.d.ts +1 -0
- package/dist/mail/index.js +1 -0
- package/dist/mail/marks.d.ts +56 -0
- package/dist/mail/marks.js +178 -0
- package/dist/meetings/mcp/index.d.ts +15 -15
- package/dist/sends/permissions.js +1 -0
- package/dist/services/proposals/kinds/finance.d.ts +4 -0
- package/dist/services/proposals/kinds/finance.js +40 -0
- package/dist/services/proposals/registry.js +3 -0
- package/dist/services/task-analysis.d.ts +58 -0
- package/dist/services/task-analysis.js +125 -0
- package/dist/store/exports.d.ts +2 -2
- package/dist/store/index.d.ts +2 -1
- package/dist/store/sqlite/email-activity.d.ts +31 -0
- package/dist/store/sqlite/email-activity.js +38 -0
- package/dist/store/sqlite/emails.d.ts +2 -0
- package/dist/store/sqlite/emails.js +1 -0
- package/dist/store/sqlite/entity-types.d.ts +2 -0
- package/dist/store/sqlite/entity-types.js +2 -0
- package/dist/store/sqlite/finance.d.ts +199 -0
- package/dist/store/sqlite/finance.js +514 -0
- package/dist/store/sqlite/knowledge.js +3 -1
- package/dist/store/sqlite/manifest.js +2 -0
- package/dist/store/sqlite/migrations.generated.js +35 -0
- package/dist/store/sqlite/ref-summaries.js +33 -0
- package/dist/store/sqlite/schema.d.ts +1043 -0
- package/dist/store/sqlite/schema.js +98 -0
- package/dist/store/sqlite/task-analysis-marks.d.ts +7 -0
- package/dist/store/sqlite/task-analysis-marks.js +27 -0
- package/dist/store/sqlite/things.js +2 -0
- package/dist/store/store.d.ts +3 -0
- package/dist/store/store.js +5 -0
- package/dist/store/sync.d.ts +5 -1
- package/dist/store/sync.js +4 -0
- package/dist/store/types.d.ts +25 -0
- package/package.json +1 -1
- package/parity.json +29 -0
- package/skills/follow-ups/SKILL.md +22 -2
|
@@ -587,3 +587,75 @@ export declare const taskScan: v.StrictObjectSchema<{
|
|
|
587
587
|
readonly category: v.NullableSchema<v.StringSchema<undefined>, undefined>;
|
|
588
588
|
}, undefined>, undefined>;
|
|
589
589
|
}, undefined>;
|
|
590
|
+
export declare const taskAnalysisMark: v.StrictObjectSchema<{
|
|
591
|
+
readonly chat: v.StringSchema<undefined>;
|
|
592
|
+
readonly from: 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`">]>;
|
|
593
|
+
readonly through: 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`">]>;
|
|
594
|
+
readonly through_id: v.StringSchema<undefined>;
|
|
595
|
+
readonly by: v.StringSchema<undefined>;
|
|
596
|
+
readonly checked_at: 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`">]>;
|
|
597
|
+
readonly checked_through: 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`">]>;
|
|
598
|
+
readonly at: 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`">]>;
|
|
599
|
+
}, undefined>;
|
|
600
|
+
export declare const taskAnalysisMarkMoved: v.StrictObjectSchema<{
|
|
601
|
+
readonly chat: v.StringSchema<undefined>;
|
|
602
|
+
readonly from: 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`">]>;
|
|
603
|
+
readonly through: 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`">]>;
|
|
604
|
+
readonly through_id: v.StringSchema<undefined>;
|
|
605
|
+
readonly by: v.StringSchema<undefined>;
|
|
606
|
+
readonly checked_at: 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`">]>;
|
|
607
|
+
readonly checked_through: 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`">]>;
|
|
608
|
+
readonly at: 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`">]>;
|
|
609
|
+
readonly moved: v.BooleanSchema<undefined>;
|
|
610
|
+
}, undefined>;
|
|
611
|
+
export declare const taskAnalysis: v.StrictObjectSchema<{
|
|
612
|
+
readonly chat: v.StringSchema<undefined>;
|
|
613
|
+
readonly title: v.NullableSchema<v.StringSchema<undefined>, undefined>;
|
|
614
|
+
readonly kind: v.StringSchema<undefined>;
|
|
615
|
+
readonly newest_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>;
|
|
616
|
+
readonly mark: v.NullableSchema<v.StrictObjectSchema<{
|
|
617
|
+
readonly chat: v.StringSchema<undefined>;
|
|
618
|
+
readonly from: 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
|
+
readonly through: 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
|
+
readonly through_id: v.StringSchema<undefined>;
|
|
621
|
+
readonly by: v.StringSchema<undefined>;
|
|
622
|
+
readonly checked_at: 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`">]>;
|
|
623
|
+
readonly checked_through: 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`">]>;
|
|
624
|
+
readonly at: 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`">]>;
|
|
625
|
+
}, undefined>, undefined>;
|
|
626
|
+
readonly waiting: v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 0, undefined>]>;
|
|
627
|
+
readonly late: v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 0, undefined>]>;
|
|
628
|
+
readonly untrusted: v.OptionalSchema<v.ArraySchema<v.StringSchema<undefined>, undefined>, undefined>;
|
|
629
|
+
}, undefined>;
|
|
630
|
+
export declare const taskReview: v.StrictObjectSchema<{
|
|
631
|
+
readonly chat: v.StringSchema<undefined>;
|
|
632
|
+
readonly from: 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`">]>;
|
|
633
|
+
readonly mark: v.NullableSchema<v.StrictObjectSchema<{
|
|
634
|
+
readonly chat: v.StringSchema<undefined>;
|
|
635
|
+
readonly from: 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`">]>;
|
|
636
|
+
readonly through: 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`">]>;
|
|
637
|
+
readonly through_id: v.StringSchema<undefined>;
|
|
638
|
+
readonly by: v.StringSchema<undefined>;
|
|
639
|
+
readonly checked_at: 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`">]>;
|
|
640
|
+
readonly checked_through: 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`">]>;
|
|
641
|
+
readonly at: 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`">]>;
|
|
642
|
+
}, undefined>, undefined>;
|
|
643
|
+
readonly late: v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 0, undefined>]>;
|
|
644
|
+
readonly has_more: v.BooleanSchema<undefined>;
|
|
645
|
+
readonly through: v.NullableSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, "a reference such as `note:42`">]>, undefined>;
|
|
646
|
+
readonly messages: v.ArraySchema<v.StrictObjectSchema<{
|
|
647
|
+
readonly ref: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, "a reference such as `note:42`">]>;
|
|
648
|
+
readonly at: 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`">]>;
|
|
649
|
+
readonly sender: v.NullableSchema<v.StringSchema<undefined>, undefined>;
|
|
650
|
+
readonly outgoing: v.BooleanSchema<undefined>;
|
|
651
|
+
readonly reply_to: v.NullableSchema<v.StringSchema<undefined>, undefined>;
|
|
652
|
+
readonly text: v.StringSchema<undefined>;
|
|
653
|
+
}, undefined>, undefined>;
|
|
654
|
+
readonly open_tasks: v.ArraySchema<v.StrictObjectSchema<{
|
|
655
|
+
readonly key: v.NullableSchema<v.StringSchema<undefined>, undefined>;
|
|
656
|
+
readonly kind: v.StringSchema<undefined>;
|
|
657
|
+
readonly title: v.NullableSchema<v.StringSchema<undefined>, undefined>;
|
|
658
|
+
readonly source: v.NullableSchema<v.StringSchema<undefined>, undefined>;
|
|
659
|
+
}, undefined>, undefined>;
|
|
660
|
+
readonly untrusted: v.OptionalSchema<v.ArraySchema<v.StringSchema<undefined>, undefined>, undefined>;
|
|
661
|
+
}, undefined>;
|
|
@@ -2,7 +2,7 @@ import * as v from "valibot";
|
|
|
2
2
|
import { TASK_TYPES } from "../domain/knowledge.js";
|
|
3
3
|
import { LINK_KINDS, LINK_SOURCES } from "../store/sqlite/link-kinds.js";
|
|
4
4
|
import { PRIORITY_LABELS, TASK_KINDS, TASK_ORIGINS, TASK_STATES, TASK_VERDICTS } from "../tasks/index.js";
|
|
5
|
-
import { count, id, reference, text, time } from "./fields.js";
|
|
5
|
+
import { count, id, reference, text, time, untrusted } from "./fields.js";
|
|
6
6
|
import { closeSuggestion } from "./task.js";
|
|
7
7
|
import { taskPair } from "./task-pair.js";
|
|
8
8
|
const nullableTime = v.nullable(time);
|
|
@@ -135,3 +135,42 @@ export const taskScan = v.strictObject({
|
|
|
135
135
|
held_chats: v.optional(count),
|
|
136
136
|
tasks: v.array(v.strictObject({ source: text, kind: v.picklist(TASK_KINDS), category: v.nullable(text) })),
|
|
137
137
|
});
|
|
138
|
+
export const taskAnalysisMark = v.strictObject({
|
|
139
|
+
chat: text,
|
|
140
|
+
from: time,
|
|
141
|
+
through: time,
|
|
142
|
+
through_id: text,
|
|
143
|
+
by: text,
|
|
144
|
+
checked_at: time,
|
|
145
|
+
checked_through: time,
|
|
146
|
+
at: time,
|
|
147
|
+
});
|
|
148
|
+
export const taskAnalysisMarkMoved = v.strictObject({ ...taskAnalysisMark.entries, moved: v.boolean() });
|
|
149
|
+
export const taskAnalysis = v.strictObject({
|
|
150
|
+
chat: text,
|
|
151
|
+
title: v.nullable(text),
|
|
152
|
+
kind: text,
|
|
153
|
+
newest_at: nullableTime,
|
|
154
|
+
mark: v.nullable(taskAnalysisMark),
|
|
155
|
+
waiting: count,
|
|
156
|
+
late: count,
|
|
157
|
+
untrusted,
|
|
158
|
+
});
|
|
159
|
+
export const taskReview = v.strictObject({
|
|
160
|
+
chat: text,
|
|
161
|
+
from: time,
|
|
162
|
+
mark: v.nullable(taskAnalysisMark),
|
|
163
|
+
late: count,
|
|
164
|
+
has_more: v.boolean(),
|
|
165
|
+
through: v.nullable(reference),
|
|
166
|
+
messages: v.array(v.strictObject({
|
|
167
|
+
ref: reference,
|
|
168
|
+
at: time,
|
|
169
|
+
sender: v.nullable(text),
|
|
170
|
+
outgoing: v.boolean(),
|
|
171
|
+
reply_to: v.nullable(text),
|
|
172
|
+
text,
|
|
173
|
+
})),
|
|
174
|
+
open_tasks: v.array(v.strictObject({ key: v.nullable(text), kind: text, title: v.nullable(text), source: v.nullable(text) })),
|
|
175
|
+
untrusted,
|
|
176
|
+
});
|
package/dist/errors/reasons.d.ts
CHANGED
|
@@ -7,7 +7,7 @@ export declare const REASONS: ErrorReason[];
|
|
|
7
7
|
* Detail keys an error from this package may carry, until each is registered on its own reason. Not `cause`:
|
|
8
8
|
* that can hold a provider's or SQLite's raw text.
|
|
9
9
|
*/
|
|
10
|
-
export declare const DETAILS: readonly ["contracts", "calendars", "allowed", "alternative", "arguments", "at", "available", "batch", "budget", "built", "candidates", "chat", "chat_id", "cli", "complete", "emitted_bytes", "exact", "forum", "guide", "hint", "id", "index", "kind", "limit", "limit_source", "max_bytes", "model", "name", "operation_id", "operation_ids", "text_limit", "store_refused_in", "subtasks", "partial_output", "parent", "path", "permission", "person_ids", "previous_chat_id", "profiles", "provider_error", "provider", "recovery", "reference", "remembered", "retry_at", "retry_after_ms", "runtime", "saved", "scheduled_for", "script", "sent", "sent_count", "settlement_failed", "span", "sqlite", "stage", "standing", "state", "stderr", "term", "total", "upgraded", "wanted"];
|
|
10
|
+
export declare const DETAILS: readonly ["contracts", "calendars", "allowed", "alternative", "arguments", "at", "available", "batch", "budget", "built", "candidates", "chat", "chat_id", "cli", "column", "complete", "emitted_bytes", "exact", "file", "forum", "guide", "hint", "id", "index", "kind", "limit", "limit_source", "line", "max_bytes", "model", "name", "operation_id", "operation_ids", "text_limit", "store_refused_in", "subtasks", "partial_output", "parent", "path", "permission", "person_ids", "previous_chat_id", "profiles", "provider_error", "provider", "recovery", "reference", "remembered", "retry_at", "retry_after_ms", "runtime", "saved", "scheduled_for", "script", "sent", "sent_count", "settlement_failed", "span", "sqlite", "stage", "standing", "state", "stderr", "term", "total", "upgraded", "wanted"];
|
|
11
11
|
/** What a CLI adds to the shared registry: its own reasons, and the detail keys its adapters raise. */
|
|
12
12
|
export interface AppErrors {
|
|
13
13
|
reasons?: readonly ErrorReason[];
|
package/dist/errors/reasons.js
CHANGED
|
@@ -57,6 +57,11 @@ const OTHERS = [
|
|
|
57
57
|
validation("push.too-many-files", "the folder holds more files than one push takes"),
|
|
58
58
|
validation("push.unreadable", "the folder to push could not be read"),
|
|
59
59
|
validation("spreadsheet.unreadable", "the workbook could not be read"),
|
|
60
|
+
[
|
|
61
|
+
"config.unrepairable",
|
|
62
|
+
"configuration_error",
|
|
63
|
+
"the settings file's damage has more than one reading; nothing was changed, so it is fixed by hand",
|
|
64
|
+
],
|
|
60
65
|
["state.invalid", "configuration_error", "the saved sync state is unreadable or invalid; it is kept, not reset"],
|
|
61
66
|
["sync.partial", "provider_error", "some calendars did not sync; the next sync retries them"],
|
|
62
67
|
validation("event.conflict", "the event changed at the provider since the last sync; sync and try again"),
|
|
@@ -133,8 +138,23 @@ const OTHERS = [
|
|
|
133
138
|
validation("input.required", "the command needs an answer and cannot ask for one"),
|
|
134
139
|
validation("input.too-large", "the input is over its size limit"),
|
|
135
140
|
["meeting-project.stale", "configuration_error", "the meeting's project changed meanwhile"],
|
|
141
|
+
validation("finance.allocate", "the invoice or payment cannot take an allocation in its state"),
|
|
142
|
+
validation("finance.currency", "the payment and the invoice are in different currencies; nothing is converted"),
|
|
143
|
+
validation("finance.field", "a field of the invoice or payment is not valid"),
|
|
144
|
+
validation("finance.line-amount", "the line's amount is not its quantity times its unit price"),
|
|
145
|
+
validation("finance.lines", "the invoice's lines are not valid"),
|
|
146
|
+
validation("finance.over-invoice", "the allocation would settle more than the invoice's total"),
|
|
147
|
+
validation("finance.over-payment", "the allocation would use more than the payment's amount"),
|
|
148
|
+
["finance.owner-only", "permission_error", "only the owner does this with money"],
|
|
149
|
+
validation("finance.party", "a party is a person: or organization: reference"),
|
|
150
|
+
validation("finance.ref", "the reference names no invoice or payment"),
|
|
151
|
+
validation("finance.status", "the invoice's status does not allow this"),
|
|
152
|
+
validation("finance.total", "the invoice's total is not the sum of its lines"),
|
|
136
153
|
validation("memory.evidence-required", "a memory needs its evidence"),
|
|
137
154
|
validation("memory.scope-required", "a memory needs its scope"),
|
|
155
|
+
validation("money.amount", "the amount is not a decimal string in the currency's scale"),
|
|
156
|
+
validation("money.currency", "the currency is not one the store keeps money in"),
|
|
157
|
+
validation("money.quantity", "the quantity is not a decimal above 0"),
|
|
138
158
|
["model.not-downloaded", "not_found", "the model is not downloaded on this machine"],
|
|
139
159
|
["person.no-owner", "not_found", "no person is marked as the owner in the store"],
|
|
140
160
|
["transcription.no-key", "authentication_error", "no OpenAI key is set for transcription"],
|
|
@@ -188,6 +208,7 @@ const OTHERS = [
|
|
|
188
208
|
validation("task.has-subtasks", "the task has subtasks; move or detach them before it moves to another project"),
|
|
189
209
|
validation("task.is-subtask", "a subtask moves to another project only when it is detached from its parent in the same write"),
|
|
190
210
|
validation("task.duplicate-candidates", "open tasks may be the same job: attach to one, or add it as new"),
|
|
211
|
+
validation("task.already-read", "the message was already read for tasks: a read again only updates and closes tasks unless --open-new"),
|
|
191
212
|
validation("task.certainty-required", "an agent closes a task with its certainty, 0 to 1"),
|
|
192
213
|
["task.pair-decided", "permission_error", "the owner already decided the pair; an agent does not change it"],
|
|
193
214
|
validation("task.no-close-suggestion", "the task has no agent's close waiting on the owner"),
|
|
@@ -245,9 +266,11 @@ export const DETAILS = [
|
|
|
245
266
|
"chat",
|
|
246
267
|
"chat_id",
|
|
247
268
|
"cli",
|
|
269
|
+
"column",
|
|
248
270
|
"complete",
|
|
249
271
|
"emitted_bytes",
|
|
250
272
|
"exact",
|
|
273
|
+
"file",
|
|
251
274
|
"forum",
|
|
252
275
|
"guide",
|
|
253
276
|
"hint",
|
|
@@ -256,6 +279,7 @@ export const DETAILS = [
|
|
|
256
279
|
"kind",
|
|
257
280
|
"limit",
|
|
258
281
|
"limit_source",
|
|
282
|
+
"line",
|
|
259
283
|
"max_bytes",
|
|
260
284
|
"model",
|
|
261
285
|
"name",
|
package/dist/index.d.ts
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
export { bareCheck, type CheckWords, checkWords } from "./domain/checks.js";
|
|
2
2
|
export type { CounterField, CounterObservation, CounterObservations, CounterState } from "./domain/counters.js";
|
|
3
3
|
export { COUNTER_FIELDS, counterValue, observedCounters } from "./domain/counters.js";
|
|
4
|
+
export { FINANCE_REVIEWS, type FinanceReview, INVOICE_DIRECTIONS, INVOICE_STATUSES, type InvoiceDirection, type InvoiceStatus, MONEY_DIRECTIONS, type MoneyDirection, } from "./domain/finance.js";
|
|
4
5
|
export { type FormattedText, type HtmlFormatting, type MarkdownFormatting, type TextSpan, validateFormattedText, } from "./domain/formatting.js";
|
|
5
6
|
export { formatLocator, isLocator, type MessageLocator, parseLocator } from "./domain/locator.js";
|
|
6
7
|
export { type Markup, parseMarkdown } from "./domain/markdown.js";
|
|
7
8
|
export { parseMarkdownSpans } from "./domain/markdown-spans.js";
|
|
8
9
|
export type { MessageLink, MessagePermalink } from "./domain/message-link.js";
|
|
9
10
|
export type * from "./domain/models.js";
|
|
11
|
+
export { CURRENCY_SCALES, currencyOf, type Money, minorUnits, moneyLabel, moneyOf, } from "./domain/money.js";
|
|
10
12
|
export { countedPoll } from "./domain/polls.js";
|
|
11
13
|
export { FOLDER_PROVIDERS, isFolderProvider, isKind, KINDS, type Kind, kindIn, kindOf, PROVIDERS, type ProviderEntry, providerNamed, providers, UNKNOWN_PROVIDER, useProviders, } from "./domain/providers.js";
|
|
12
14
|
export type { RankingGraphEvidence, RankingGraphLink } from "./domain/rankings-graph.js";
|
package/dist/index.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
export { bareCheck, checkWords } from "./domain/checks.js";
|
|
2
2
|
export { COUNTER_FIELDS, counterValue, observedCounters } from "./domain/counters.js";
|
|
3
|
+
export { FINANCE_REVIEWS, INVOICE_DIRECTIONS, INVOICE_STATUSES, MONEY_DIRECTIONS, } from "./domain/finance.js";
|
|
3
4
|
export { validateFormattedText, } from "./domain/formatting.js";
|
|
4
5
|
export { formatLocator, isLocator, parseLocator } from "./domain/locator.js";
|
|
5
6
|
export { parseMarkdown } from "./domain/markdown.js";
|
|
6
7
|
export { parseMarkdownSpans } from "./domain/markdown-spans.js";
|
|
8
|
+
export { CURRENCY_SCALES, currencyOf, minorUnits, moneyLabel, moneyOf, } from "./domain/money.js";
|
|
7
9
|
export { countedPoll } from "./domain/polls.js";
|
|
8
10
|
export { FOLDER_PROVIDERS, isFolderProvider, isKind, KINDS, kindIn, kindOf, PROVIDERS, providerNamed, providers, UNKNOWN_PROVIDER, useProviders, } from "./domain/providers.js";
|
|
9
11
|
export { rankingOptions } from "./domain/rankings-options.js";
|
package/dist/mail/cli/index.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { Command } from "commander";
|
|
|
2
2
|
import { type MailServerAccess } from "../../mail/server-search.js";
|
|
3
3
|
import type { AppIdentity } from "../../ports/app.js";
|
|
4
4
|
import { type AccountKey, type MessageStore } from "../../store/store.js";
|
|
5
|
+
export { mailMark, markItem, markText } from "./marks.js";
|
|
5
6
|
export { MAIL_REVIEW_QUERY, MAIL_REVIEW_STEPS } from "./review.js";
|
|
6
7
|
/** What a mail CLI hands the shared commands: how to open the store for one run, and whose mail it reads. */
|
|
7
8
|
export interface MailReads {
|
package/dist/mail/cli/index.js
CHANGED
|
@@ -18,7 +18,9 @@ import { searchMailServer } from "../../mail/server-search.js";
|
|
|
18
18
|
import { atDetail } from "../../output-detail.js";
|
|
19
19
|
import { sourceKey } from "../../services/server-search.js";
|
|
20
20
|
import { queryFilter, THREAD_COLUMNS } from "../../store/store.js";
|
|
21
|
+
import { acknowledgeCommand } from "./marks.js";
|
|
21
22
|
import { mailReviewCommand } from "./review.js";
|
|
23
|
+
export { mailMark, markItem, markText } from "./marks.js";
|
|
22
24
|
export { MAIL_REVIEW_QUERY, MAIL_REVIEW_STEPS } from "./review.js";
|
|
23
25
|
/** A locked or broken store must fail the command, not read as "nothing stored yet". */
|
|
24
26
|
const absentAccount = (error) => {
|
|
@@ -226,6 +228,7 @@ const messagesCommand = (mail) => {
|
|
|
226
228
|
? listOf("messages show", { items: shown, limit: Math.max(1, shown.length), has_more: false })
|
|
227
229
|
: itemOf(shown.find((_, at) => emails[at]?.anchor) ?? shown[0]), () => shownText(emails));
|
|
228
230
|
});
|
|
231
|
+
messages.addCommand(acknowledgeCommand(mail));
|
|
229
232
|
return messages;
|
|
230
233
|
};
|
|
231
234
|
const mailThread = v.strictObject({
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import * as v from "valibot";
|
|
3
|
+
import { type MailMark } from "../marks.js";
|
|
4
|
+
import type { MailReads } from "./index.js";
|
|
5
|
+
/** A holder's mark as `--json`, `mail status` and MCP show it. */
|
|
6
|
+
export declare const mailMark: v.StrictObjectSchema<{
|
|
7
|
+
readonly holder: v.StringSchema<undefined>;
|
|
8
|
+
readonly through_id: v.NumberSchema<undefined>;
|
|
9
|
+
readonly through_received_at: v.NullableSchema<v.StringSchema<undefined>, undefined>;
|
|
10
|
+
readonly held: v.NumberSchema<undefined>;
|
|
11
|
+
readonly read: v.NumberSchema<undefined>;
|
|
12
|
+
readonly skipped: v.StrictObjectSchema<{
|
|
13
|
+
readonly bulk: v.NumberSchema<undefined>;
|
|
14
|
+
readonly envelope: v.NumberSchema<undefined>;
|
|
15
|
+
readonly partial: v.NumberSchema<undefined>;
|
|
16
|
+
readonly draft: v.NumberSchema<undefined>;
|
|
17
|
+
}, undefined>;
|
|
18
|
+
readonly updated_at: v.StringSchema<undefined>;
|
|
19
|
+
}, undefined>;
|
|
20
|
+
export declare const markItem: (mark: MailMark) => v.InferOutput<typeof mailMark>;
|
|
21
|
+
export declare const markText: (mark: MailMark) => string;
|
|
22
|
+
/**
|
|
23
|
+
* `messages acknowledge`: a holder says it is done with what `review --holder` gave it, and its mark moves there. It
|
|
24
|
+
* only moves the holder's own bookkeeping forward, so a read-only scheduled run may do it.
|
|
25
|
+
*/
|
|
26
|
+
export declare const acknowledgeCommand: (mail: MailReads) => Command;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { annotate } from "@wirecat/cli-base/commands";
|
|
2
|
+
import { Command } from "commander";
|
|
3
|
+
import * as v from "valibot";
|
|
4
|
+
import { answerEntity } from "../../cli/answer-entity.js";
|
|
5
|
+
import { outputFor } from "../../cli/context.js";
|
|
6
|
+
import { destroysNothing, LOCAL_WRITE } from "../../cli/effects.js";
|
|
7
|
+
import { itemOf, renderAnswer } from "../../cli/envelope.js";
|
|
8
|
+
import { acknowledgeMark } from "../marks.js";
|
|
9
|
+
const iso = (ms) => (ms === null ? null : new Date(ms).toISOString());
|
|
10
|
+
/** A holder's mark as `--json`, `mail status` and MCP show it. */
|
|
11
|
+
export const mailMark = v.strictObject({
|
|
12
|
+
holder: v.string(),
|
|
13
|
+
through_id: v.number(),
|
|
14
|
+
through_received_at: v.nullable(v.string()),
|
|
15
|
+
held: v.number(),
|
|
16
|
+
read: v.number(),
|
|
17
|
+
skipped: v.strictObject({ bulk: v.number(), envelope: v.number(), partial: v.number(), draft: v.number() }),
|
|
18
|
+
updated_at: v.string(),
|
|
19
|
+
});
|
|
20
|
+
export const markItem = (mark) => ({
|
|
21
|
+
holder: mark.holder,
|
|
22
|
+
through_id: mark.throughId,
|
|
23
|
+
through_received_at: iso(mark.throughAt),
|
|
24
|
+
held: mark.held.length,
|
|
25
|
+
read: mark.read,
|
|
26
|
+
skipped: mark.skipped,
|
|
27
|
+
updated_at: iso(mark.updatedAt),
|
|
28
|
+
});
|
|
29
|
+
export const markText = (mark) => `${mark.holder} through ${mark.throughId}${mark.throughAt === null ? "" : ` (${iso(mark.throughAt)})`} ` +
|
|
30
|
+
`read ${mark.read} held ${mark.held.length} skipped bulk ${mark.skipped.bulk}, envelope ${mark.skipped.envelope}, ` +
|
|
31
|
+
`partial ${mark.skipped.partial}, draft ${mark.skipped.draft} updated ${iso(mark.updatedAt)}\n`;
|
|
32
|
+
/**
|
|
33
|
+
* `messages acknowledge`: a holder says it is done with what `review --holder` gave it, and its mark moves there. It
|
|
34
|
+
* only moves the holder's own bookkeeping forward, so a read-only scheduled run may do it.
|
|
35
|
+
*/
|
|
36
|
+
export const acknowledgeCommand = (mail) => answerEntity(destroysNothing(annotate(new Command("acknowledge"), {
|
|
37
|
+
effects: LOCAL_WRITE,
|
|
38
|
+
examples: [
|
|
39
|
+
`${mail.app.command} personal messages acknowledge --holder mail-triage --cursor 9123.1762090000000`,
|
|
40
|
+
],
|
|
41
|
+
})), "mail_mark", mailMark)
|
|
42
|
+
.summary("move a holder's processing mark to what it has read")
|
|
43
|
+
.description("record that a holder — an agent or a pipeline — processed the mail `review --holder` gave it, with the cursor " +
|
|
44
|
+
"that review gave; the mark only moves forward, and mail still partial waits for the next review")
|
|
45
|
+
.requiredOption("--holder <name>", "whose mark: lower-case letters, digits and dashes, such as mail-triage")
|
|
46
|
+
.requiredOption("--cursor <cursor>", "the cursor `review --holder` gave")
|
|
47
|
+
.action(async function () {
|
|
48
|
+
const { holder, cursor } = this.opts();
|
|
49
|
+
const mark = await mail.read(this, (store, mailbox) => acknowledgeMark(store, mailbox, holder, cursor));
|
|
50
|
+
renderAnswer(this, outputFor(this), itemOf(markItem(mark)), () => markText(mark));
|
|
51
|
+
});
|
package/dist/mail/cli/review.js
CHANGED
|
@@ -16,6 +16,7 @@ import { parseDuration } from "../../domain/duration.js";
|
|
|
16
16
|
import { formatReference } from "../../domain/references.js";
|
|
17
17
|
import { AGENDA_DEFAULTS } from "../../services/agenda.js";
|
|
18
18
|
import { REVIEW_DAYS, reviewStart } from "../../services/inbox.js";
|
|
19
|
+
import { readPastMark } from "../marks.js";
|
|
19
20
|
import { hitText } from "../read.js";
|
|
20
21
|
import { OWED_DAYS, REVIEW_THREADS, reviewMail } from "../review.js";
|
|
21
22
|
const DAY = 86_400_000;
|
|
@@ -30,6 +31,15 @@ export const MAIL_REVIEW_QUERY = defineQuery({
|
|
|
30
31
|
});
|
|
31
32
|
/** The mail review's steps; a host lists them beside its own so its step checks know them. */
|
|
32
33
|
export const MAIL_REVIEW_STEPS = defineSteps([
|
|
34
|
+
{
|
|
35
|
+
id: "mail-messages.acknowledge",
|
|
36
|
+
command: "messages acknowledge",
|
|
37
|
+
args: [
|
|
38
|
+
{ name: "holder", required: true },
|
|
39
|
+
{ name: "cursor", required: true },
|
|
40
|
+
],
|
|
41
|
+
why: "once these are processed, this moves the holder's mark past them",
|
|
42
|
+
},
|
|
33
43
|
{
|
|
34
44
|
id: "mail-review.next",
|
|
35
45
|
command: "review",
|
|
@@ -113,6 +123,62 @@ const reviewAnswer = (found, mailbox, fresh) => {
|
|
|
113
123
|
meta: found.complete ? {} : { complete: false },
|
|
114
124
|
});
|
|
115
125
|
};
|
|
126
|
+
const holderReview = async (command, mail, holder, query) => {
|
|
127
|
+
const { unanswered, waiting } = command.opts();
|
|
128
|
+
if (typedQuery(query).trim() || unanswered !== undefined || waiting !== undefined)
|
|
129
|
+
throw new CliError("validation_error", "--holder reads past its own mark — not with a query, --unanswered or --waiting");
|
|
130
|
+
const { read, mailbox, marks } = await mail.read(command, async (store, mailbox) => {
|
|
131
|
+
const read = await readPastMark(store, mailbox, holder);
|
|
132
|
+
const account = read.emails.length ? await store.accounts.storedAccount(mailbox) : undefined;
|
|
133
|
+
const marks = account
|
|
134
|
+
? await store.mail.emailMarks(account.id, read.emails.map((one) => one.id))
|
|
135
|
+
: new Map();
|
|
136
|
+
return { read, mailbox, marks };
|
|
137
|
+
});
|
|
138
|
+
const chats = new Map();
|
|
139
|
+
for (const email of read.emails) {
|
|
140
|
+
const chat = chats.get(email.chatId) ?? {
|
|
141
|
+
id: email.chatId,
|
|
142
|
+
title: email.chatTitle,
|
|
143
|
+
kind: "dialog",
|
|
144
|
+
messages: [],
|
|
145
|
+
more: false,
|
|
146
|
+
};
|
|
147
|
+
const mark = marks.get(email.id);
|
|
148
|
+
chat.messages.push(mark ? { ...email, marks: mark } : email);
|
|
149
|
+
chats.set(email.chatId, chat);
|
|
150
|
+
}
|
|
151
|
+
const now = new Date().toISOString();
|
|
152
|
+
const found = {
|
|
153
|
+
since: read.mark?.throughAt ? new Date(read.mark.throughAt).toISOString() : now,
|
|
154
|
+
until: now,
|
|
155
|
+
complete: !read.more,
|
|
156
|
+
chats: [...chats.values()],
|
|
157
|
+
skipped: [],
|
|
158
|
+
partial: false,
|
|
159
|
+
quiet: 0,
|
|
160
|
+
};
|
|
161
|
+
const answer = reviewAnswer(found, mailbox, true);
|
|
162
|
+
const skipped = Object.entries(read.skipped).filter(([, count]) => count > 0);
|
|
163
|
+
answer.next = [
|
|
164
|
+
stepOf(step("mail-messages.acknowledge"), { args: { holder, cursor: read.cursor } }),
|
|
165
|
+
...(answer.next ?? []),
|
|
166
|
+
];
|
|
167
|
+
answer.missing = [
|
|
168
|
+
...(answer.missing ?? []),
|
|
169
|
+
...(read.held > 0 ? [{ field: "items", why: `${read.held} partial emails held until they are whole` }] : []),
|
|
170
|
+
...(skipped.length
|
|
171
|
+
? [{ field: "items", why: `left out: ${skipped.map(([reason, count]) => `${count} ${reason}`).join(", ")}` }]
|
|
172
|
+
: []),
|
|
173
|
+
];
|
|
174
|
+
const output = outputFor(command);
|
|
175
|
+
renderAnswer(command, output, answer, () => {
|
|
176
|
+
output.renderer.note(read.mark
|
|
177
|
+
? `${holder}: past ${read.mark.throughId}; acknowledge with --cursor ${read.cursor}${read.more ? "; more after these" : ""}`
|
|
178
|
+
: `${holder} has no mark yet: it starts from now — acknowledge with --cursor ${read.cursor}`);
|
|
179
|
+
return read.emails.map((hit) => `${hitText(hit)}${markText(marks.get(hit.id))}\n`).join("");
|
|
180
|
+
});
|
|
181
|
+
};
|
|
116
182
|
/**
|
|
117
183
|
* `review` over the stored mail of the profile's mailbox, with tg's words: what is new, what the owner owes, what
|
|
118
184
|
* waits for an answer. It reads the store only and opens no task.
|
|
@@ -122,7 +188,6 @@ export const mailReviewCommand = (mail) => annotate(new Command("review"), {
|
|
|
122
188
|
`${mail.app.command} personal review "date>2h"`,
|
|
123
189
|
`${mail.app.command} personal review --new`,
|
|
124
190
|
`${mail.app.command} personal review --unanswered 1d`,
|
|
125
|
-
`${mail.app.command} personal review --waiting 7d`,
|
|
126
191
|
],
|
|
127
192
|
effects: LOCAL_READ,
|
|
128
193
|
partial: true,
|
|
@@ -136,6 +201,8 @@ export const mailReviewCommand = (mail) => annotate(new Command("review"), {
|
|
|
136
201
|
.argument("[query...]", `where the last review ended: date>2h; ${REVIEW_DAYS} days ago if no date`)
|
|
137
202
|
.option("--unanswered [duration]", "only threads whose newest email came to you, in To or Cc, with no answer for this long — 4h, 1d; 24h if not given")
|
|
138
203
|
.option("--waiting [duration]", "only threads where you wrote last and nobody answered for this long — 3d; 7d if not given")
|
|
204
|
+
.option("--holder <name>", "read for this holder — an agent or a pipeline — what is stored past its processing mark, by store order; " +
|
|
205
|
+
"bulk, envelopes, drafts and partial mail left out; `messages acknowledge` moves the mark")
|
|
139
206
|
.option("--new", "what changed since the last `review --new` of this mailbox, a point per thread — for scheduled runs")
|
|
140
207
|
.addHelpText("after", `
|
|
141
208
|
Without a date, --unanswered and --waiting look at threads active in the last ${OWED_DAYS} days.
|
|
@@ -145,6 +212,8 @@ Mail newer than the last finished sync waits for the next review. Each reader ke
|
|
|
145
212
|
an agent over MCP, and each scheduled run.`)
|
|
146
213
|
.action(async function (query) {
|
|
147
214
|
const options = this.opts();
|
|
215
|
+
if (options.holder !== undefined)
|
|
216
|
+
return holderReview(this, mail, options.holder, query);
|
|
148
217
|
const { since: from, meta } = catchUpQuery(query, MAIL_REVIEW_QUERY, "review");
|
|
149
218
|
const bulk = nativeTerms(listQuery(typedQuery(query), MAIL_REVIEW_QUERY, "review"), "review").get("bulk")?.value;
|
|
150
219
|
if (bulk !== undefined && bulk !== "false")
|
package/dist/mail/index.d.ts
CHANGED
|
@@ -6,6 +6,7 @@ export { dropMissing, type Gone, tooManyGone } from "./gone.js";
|
|
|
6
6
|
export { type AuthVerdicts, HEADER_FIELDS, headersOf, type MailHeaders, mailHeadersOf } from "./headers.js";
|
|
7
7
|
export { type MailIdsInput, mailIds } from "./ids.js";
|
|
8
8
|
export { decodedLabelName, decodeMailboxName, labelName, systemLabel } from "./labels.js";
|
|
9
|
+
export { acknowledgeMark, cursorOf, HOLD_PARTIAL_MS, HOLDER, MARK_BATCH, type MailMark, type MarkRead, markOf, marksOf, readPastMark, type SkipReason, } from "./marks.js";
|
|
9
10
|
export { type MailTurn, mailTurn } from "./owed.js";
|
|
10
11
|
export { type Address, htmlToText, looksLikeHtml, MAX_ATTACHMENTS, MAX_BODY_CHARS, type ParsedMail, parseMail, } from "./parse.js";
|
|
11
12
|
export { PARTIAL, type PartialOutcome } from "./partial.js";
|
package/dist/mail/index.js
CHANGED
|
@@ -6,6 +6,7 @@ export { dropMissing, tooManyGone } from "./gone.js";
|
|
|
6
6
|
export { HEADER_FIELDS, headersOf, mailHeadersOf } from "./headers.js";
|
|
7
7
|
export { mailIds } from "./ids.js";
|
|
8
8
|
export { decodedLabelName, decodeMailboxName, labelName, systemLabel } from "./labels.js";
|
|
9
|
+
export { acknowledgeMark, cursorOf, HOLD_PARTIAL_MS, HOLDER, MARK_BATCH, markOf, marksOf, readPastMark, } from "./marks.js";
|
|
9
10
|
export { mailTurn } from "./owed.js";
|
|
10
11
|
export { htmlToText, looksLikeHtml, MAX_ATTACHMENTS, MAX_BODY_CHARS, parseMail, } from "./parse.js";
|
|
11
12
|
export { PARTIAL } from "./partial.js";
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import type { AccountKey, MessageStore, StoredHit } from "../store/store.js";
|
|
2
|
+
/** A holder's name: what `--holder` takes and the mark's key ends with. */
|
|
3
|
+
export declare const HOLDER: RegExp;
|
|
4
|
+
/** At most this many emails are read past the mark in one go; the rest come with the next read. */
|
|
5
|
+
export declare const MARK_BATCH = 200;
|
|
6
|
+
/** A partial email waits this long to be stored whole, then is skipped. */
|
|
7
|
+
export declare const HOLD_PARTIAL_MS: number;
|
|
8
|
+
export type SkipReason = "bulk" | "envelope" | "partial" | "draft";
|
|
9
|
+
/**
|
|
10
|
+
* How far one holder — an agent, a pipeline — has processed an account's mail, in the shared store (`sync_cursors`,
|
|
11
|
+
* key `consumer:<holder>`). It counts by the store's insert order (`emails.id`), so mail stored late, older than what
|
|
12
|
+
* was read, is still after the mark. Partial emails are held until they are whole.
|
|
13
|
+
*/
|
|
14
|
+
export interface MailMark {
|
|
15
|
+
holder: string;
|
|
16
|
+
throughId: number;
|
|
17
|
+
/** ms: when the email at `throughId` was received; for display. */
|
|
18
|
+
throughAt: number | null;
|
|
19
|
+
held: number[];
|
|
20
|
+
read: number;
|
|
21
|
+
skipped: Record<SkipReason, number>;
|
|
22
|
+
/** ms. */
|
|
23
|
+
updatedAt: number;
|
|
24
|
+
}
|
|
25
|
+
export declare const markOf: (store: MessageStore, mailbox: AccountKey, holder: string) => Promise<MailMark | undefined>;
|
|
26
|
+
/** Every holder's mark on the mailbox, by name. */
|
|
27
|
+
export declare const marksOf: (store: MessageStore, mailbox: AccountKey) => Promise<MailMark[]>;
|
|
28
|
+
/** The mark's state, as a cursor `acknowledge` takes back: the last id read, and when it was read. */
|
|
29
|
+
export declare const cursorOf: (throughId: number, readAt: number) => string;
|
|
30
|
+
export interface MarkRead {
|
|
31
|
+
/** The emails for the holder, oldest first; bulk, envelopes, drafts and partial mail left out. */
|
|
32
|
+
emails: StoredHit[];
|
|
33
|
+
/** What `acknowledge --cursor` takes once the holder is done with these. */
|
|
34
|
+
cursor: string;
|
|
35
|
+
/** More is stored after this batch: read again after acknowledging. */
|
|
36
|
+
more: boolean;
|
|
37
|
+
held: number;
|
|
38
|
+
skipped: Record<SkipReason, number>;
|
|
39
|
+
/** `undefined` before the holder's first acknowledge: it starts from the mail stored now. */
|
|
40
|
+
mark: MailMark | undefined;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* What the holder has not processed: the emails stored after its mark, and the held ones that are whole now. Reads
|
|
44
|
+
* only; the mark moves when the holder acknowledges. A holder with no mark starts from now: its first read is
|
|
45
|
+
* empty and gives the cursor of the newest stored email.
|
|
46
|
+
*/
|
|
47
|
+
export declare const readPastMark: (store: MessageStore, mailbox: AccountKey, holder: string, { now, limit }?: {
|
|
48
|
+
now?: number;
|
|
49
|
+
limit?: number;
|
|
50
|
+
}) => Promise<MarkRead>;
|
|
51
|
+
/**
|
|
52
|
+
* Moves the holder's mark to the cursor its read gave, never back. An email whole when it was read counts read; one
|
|
53
|
+
* still partial, or changed after the read (it may have become whole since), is held and comes with the next read.
|
|
54
|
+
* The same cursor twice changes nothing more.
|
|
55
|
+
*/
|
|
56
|
+
export declare const acknowledgeMark: (store: MessageStore, mailbox: AccountKey, holder: string, cursor: string, now?: number) => Promise<MailMark>;
|