@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
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import { CliError } from "@wirecat/cli-base";
|
|
2
|
+
/** A holder's name: what `--holder` takes and the mark's key ends with. */
|
|
3
|
+
export const HOLDER = /^[a-z0-9][a-z0-9-]{0,39}$/;
|
|
4
|
+
/** At most this many emails are read past the mark in one go; the rest come with the next read. */
|
|
5
|
+
export const MARK_BATCH = 200;
|
|
6
|
+
/** A partial email waits this long to be stored whole, then is skipped. */
|
|
7
|
+
export const HOLD_PARTIAL_MS = 7 * 86_400_000;
|
|
8
|
+
/** Held emails kept on one mark at most; past it the oldest are skipped as partial. */
|
|
9
|
+
const MOST_HELD = 500;
|
|
10
|
+
const PREFIX = "consumer:";
|
|
11
|
+
const noneSkipped = () => ({ bulk: 0, envelope: 0, partial: 0, draft: 0 });
|
|
12
|
+
const keyOf = (holder) => {
|
|
13
|
+
if (!HOLDER.test(holder))
|
|
14
|
+
throw new CliError("validation_error", `a holder is lower-case letters, digits and dashes, not "${holder}"`);
|
|
15
|
+
return `${PREFIX}${holder}`;
|
|
16
|
+
};
|
|
17
|
+
const parsed = (holder, value, at) => {
|
|
18
|
+
try {
|
|
19
|
+
const saved = JSON.parse(value);
|
|
20
|
+
if (typeof saved.throughId !== "number")
|
|
21
|
+
return undefined;
|
|
22
|
+
return {
|
|
23
|
+
holder,
|
|
24
|
+
throughId: saved.throughId,
|
|
25
|
+
throughAt: saved.throughAt ?? null,
|
|
26
|
+
held: Array.isArray(saved.held) ? saved.held.filter((id) => typeof id === "number") : [],
|
|
27
|
+
read: saved.read ?? 0,
|
|
28
|
+
skipped: { ...noneSkipped(), ...saved.skipped },
|
|
29
|
+
updatedAt: at,
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
return undefined;
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
const accountOf = async (store, mailbox) => store.accounts.storedAccount(mailbox).catch((error) => {
|
|
37
|
+
if (error instanceof CliError && error.code === "not_found")
|
|
38
|
+
return undefined;
|
|
39
|
+
throw error;
|
|
40
|
+
});
|
|
41
|
+
export const markOf = async (store, mailbox, holder) => {
|
|
42
|
+
const saved = await store.sync.syncState(mailbox, keyOf(holder));
|
|
43
|
+
return saved ? parsed(holder, saved.value, Date.parse(saved.at)) : undefined;
|
|
44
|
+
};
|
|
45
|
+
/** Every holder's mark on the mailbox, by name. */
|
|
46
|
+
export const marksOf = async (store, mailbox) => {
|
|
47
|
+
const account = await accountOf(store, mailbox);
|
|
48
|
+
if (!account)
|
|
49
|
+
return [];
|
|
50
|
+
return (await store.mail.statesLike(account.id, PREFIX))
|
|
51
|
+
.flatMap(({ key, value, at }) => parsed(key.slice(PREFIX.length), value, at) ?? [])
|
|
52
|
+
.sort((a, b) => a.holder.localeCompare(b.holder));
|
|
53
|
+
};
|
|
54
|
+
/** Why an email is not for the holder, or `held` while it is partial and young, or `read`. */
|
|
55
|
+
const verdict = (email, now) => {
|
|
56
|
+
if (email.draft)
|
|
57
|
+
return "draft";
|
|
58
|
+
if (email.envelope)
|
|
59
|
+
return "envelope";
|
|
60
|
+
if (email.bulk)
|
|
61
|
+
return "bulk";
|
|
62
|
+
if (email.partial)
|
|
63
|
+
return now - email.storedAt < HOLD_PARTIAL_MS ? "held" : "partial";
|
|
64
|
+
return "read";
|
|
65
|
+
};
|
|
66
|
+
/** The mark's state, as a cursor `acknowledge` takes back: the last id read, and when it was read. */
|
|
67
|
+
export const cursorOf = (throughId, readAt) => `${throughId}.${readAt}`;
|
|
68
|
+
const parseCursor = (cursor) => {
|
|
69
|
+
const match = /^(\d+)\.(\d+)$/.exec(cursor.trim());
|
|
70
|
+
if (!match)
|
|
71
|
+
throw new CliError("validation_error", `--cursor takes the cursor review gave, such as 9123.1762090000000`);
|
|
72
|
+
return { throughId: Number(match[1]), readAt: Number(match[2]) };
|
|
73
|
+
};
|
|
74
|
+
/**
|
|
75
|
+
* What the holder has not processed: the emails stored after its mark, and the held ones that are whole now. Reads
|
|
76
|
+
* only; the mark moves when the holder acknowledges. A holder with no mark starts from now: its first read is
|
|
77
|
+
* empty and gives the cursor of the newest stored email.
|
|
78
|
+
*/
|
|
79
|
+
export const readPastMark = async (store, mailbox, holder, { now = Date.now(), limit = MARK_BATCH } = {}) => {
|
|
80
|
+
const mark = await markOf(store, mailbox, holder);
|
|
81
|
+
const account = await accountOf(store, mailbox);
|
|
82
|
+
const empty = { emails: [], more: false, held: 0, skipped: noneSkipped(), mark };
|
|
83
|
+
if (!account)
|
|
84
|
+
return { ...empty, cursor: cursorOf(0, now) };
|
|
85
|
+
if (!mark)
|
|
86
|
+
return { ...empty, cursor: cursorOf(await store.mail.newestEmailId(account.id), now) };
|
|
87
|
+
const found = await store.mail.emailsAfter(account.id, mark.throughId, limit + 1, mark.held);
|
|
88
|
+
// Mail a running sync stored is read once that sync ended: it files bulk mail only at its end.
|
|
89
|
+
const settled = await store.sync.syncState(mailbox, "mail_coverage");
|
|
90
|
+
const settledAt = settled ? Date.parse(settled.at) : Number.POSITIVE_INFINITY;
|
|
91
|
+
const after = found.filter((email) => email.id > mark.throughId);
|
|
92
|
+
const unsettled = after.findIndex((email) => email.storedAt > settledAt);
|
|
93
|
+
const fresh = unsettled === -1 ? after : after.slice(0, unsettled);
|
|
94
|
+
const batch = fresh.slice(0, limit);
|
|
95
|
+
const examined = [...found.filter((email) => email.id <= mark.throughId), ...batch];
|
|
96
|
+
const skipped = noneSkipped();
|
|
97
|
+
const wanted = [];
|
|
98
|
+
let held = 0;
|
|
99
|
+
for (const email of examined) {
|
|
100
|
+
const said = verdict(email, now);
|
|
101
|
+
if (said === "read")
|
|
102
|
+
wanted.push(email.id);
|
|
103
|
+
else if (said === "held")
|
|
104
|
+
held += 1;
|
|
105
|
+
else if (email.id > mark.throughId)
|
|
106
|
+
skipped[said] += 1;
|
|
107
|
+
}
|
|
108
|
+
const emails = await store.mail.emailHits(wanted.sort((a, b) => a - b));
|
|
109
|
+
return {
|
|
110
|
+
emails,
|
|
111
|
+
cursor: cursorOf(batch.at(-1)?.id ?? mark.throughId, now),
|
|
112
|
+
more: after.length > batch.length,
|
|
113
|
+
held,
|
|
114
|
+
skipped,
|
|
115
|
+
mark,
|
|
116
|
+
};
|
|
117
|
+
};
|
|
118
|
+
/**
|
|
119
|
+
* Moves the holder's mark to the cursor its read gave, never back. An email whole when it was read counts read; one
|
|
120
|
+
* still partial, or changed after the read (it may have become whole since), is held and comes with the next read.
|
|
121
|
+
* The same cursor twice changes nothing more.
|
|
122
|
+
*/
|
|
123
|
+
export const acknowledgeMark = async (store, mailbox, holder, cursor, now = Date.now()) => {
|
|
124
|
+
const key = keyOf(holder);
|
|
125
|
+
const { throughId, readAt } = parseCursor(cursor);
|
|
126
|
+
const account = await accountOf(store, mailbox);
|
|
127
|
+
if (!account)
|
|
128
|
+
throw new CliError("not_found", `no mail of ${mailbox.account} is stored`);
|
|
129
|
+
const mark = await markOf(store, mailbox, holder);
|
|
130
|
+
const from = mark?.throughId ?? throughId;
|
|
131
|
+
if (throughId < from)
|
|
132
|
+
throw new CliError("validation_error", `${holder} is already past ${throughId}: its mark is at ${from}`);
|
|
133
|
+
const examined = [];
|
|
134
|
+
let after = from;
|
|
135
|
+
const held = new Set(mark?.held ?? []);
|
|
136
|
+
const again = await store.mail.emailsAfter(account.id, Number.MAX_SAFE_INTEGER, 0, [...held]);
|
|
137
|
+
examined.push(...again);
|
|
138
|
+
while (after < throughId) {
|
|
139
|
+
const page = (await store.mail.emailsAfter(account.id, after, MARK_BATCH)).filter((one) => one.id <= throughId);
|
|
140
|
+
if (page.length === 0)
|
|
141
|
+
break;
|
|
142
|
+
examined.push(...page);
|
|
143
|
+
after = page.at(-1)?.id ?? throughId;
|
|
144
|
+
}
|
|
145
|
+
const skipped = { ...(mark?.skipped ?? noneSkipped()) };
|
|
146
|
+
let read = mark?.read ?? 0;
|
|
147
|
+
const keep = [];
|
|
148
|
+
const live = new Set(again.map((one) => one.id));
|
|
149
|
+
for (const id of held)
|
|
150
|
+
if (!live.has(id))
|
|
151
|
+
held.delete(id);
|
|
152
|
+
for (const email of examined) {
|
|
153
|
+
const said = verdict(email, readAt);
|
|
154
|
+
const wasHeld = held.has(email.id);
|
|
155
|
+
if (said === "held" || (said === "read" && email.changedAt > readAt) || (wasHeld && email.changedAt > readAt)) {
|
|
156
|
+
if (email.partial && now - email.storedAt >= HOLD_PARTIAL_MS)
|
|
157
|
+
skipped.partial += 1;
|
|
158
|
+
else
|
|
159
|
+
keep.push(email.id);
|
|
160
|
+
}
|
|
161
|
+
else if (said === "read")
|
|
162
|
+
read += wasHeld || email.id > from ? 1 : 0;
|
|
163
|
+
else if (!wasHeld || said === "partial")
|
|
164
|
+
skipped[said] += 1;
|
|
165
|
+
}
|
|
166
|
+
const kept = [...new Set(keep)].sort((a, b) => a - b);
|
|
167
|
+
skipped.partial += Math.max(0, kept.length - MOST_HELD);
|
|
168
|
+
const through = examined.filter((one) => one.id <= throughId).at(-1);
|
|
169
|
+
const next = {
|
|
170
|
+
throughId,
|
|
171
|
+
throughAt: through?.id === throughId ? through.at : (mark?.throughAt ?? null),
|
|
172
|
+
held: kept.slice(-MOST_HELD),
|
|
173
|
+
read,
|
|
174
|
+
skipped,
|
|
175
|
+
};
|
|
176
|
+
await store.sync.setSyncState(mailbox, key, JSON.stringify(next));
|
|
177
|
+
return { holder, ...next, updatedAt: now };
|
|
178
|
+
};
|
|
@@ -38,6 +38,7 @@ export declare const meetingTools: ({
|
|
|
38
38
|
max_read_bytes?: undefined;
|
|
39
39
|
cursor?: undefined;
|
|
40
40
|
} | {
|
|
41
|
+
limit?: undefined;
|
|
41
42
|
event_id?: undefined;
|
|
42
43
|
series_id?: undefined;
|
|
43
44
|
page?: undefined;
|
|
@@ -53,11 +54,11 @@ export declare const meetingTools: ({
|
|
|
53
54
|
format?: undefined;
|
|
54
55
|
transcript_id?: undefined;
|
|
55
56
|
query?: undefined;
|
|
56
|
-
limit?: undefined;
|
|
57
57
|
scan_limit?: undefined;
|
|
58
58
|
max_read_bytes?: undefined;
|
|
59
59
|
cursor?: undefined;
|
|
60
60
|
} | {
|
|
61
|
+
limit?: undefined;
|
|
61
62
|
event_id?: undefined;
|
|
62
63
|
series_id?: undefined;
|
|
63
64
|
page?: undefined;
|
|
@@ -75,11 +76,11 @@ export declare const meetingTools: ({
|
|
|
75
76
|
format?: undefined;
|
|
76
77
|
transcript_id?: undefined;
|
|
77
78
|
query?: undefined;
|
|
78
|
-
limit?: undefined;
|
|
79
79
|
scan_limit?: undefined;
|
|
80
80
|
max_read_bytes?: undefined;
|
|
81
81
|
cursor?: undefined;
|
|
82
82
|
} | {
|
|
83
|
+
limit?: undefined;
|
|
83
84
|
event_id?: undefined;
|
|
84
85
|
series_id?: undefined;
|
|
85
86
|
page?: undefined;
|
|
@@ -101,7 +102,6 @@ export declare const meetingTools: ({
|
|
|
101
102
|
minimum: number;
|
|
102
103
|
};
|
|
103
104
|
query?: undefined;
|
|
104
|
-
limit?: undefined;
|
|
105
105
|
scan_limit?: undefined;
|
|
106
106
|
max_read_bytes?: undefined;
|
|
107
107
|
cursor?: undefined;
|
|
@@ -188,6 +188,7 @@ export declare const meetingTools: ({
|
|
|
188
188
|
max_read_bytes?: undefined;
|
|
189
189
|
cursor?: undefined;
|
|
190
190
|
} | {
|
|
191
|
+
limit?: undefined;
|
|
191
192
|
event_id?: undefined;
|
|
192
193
|
series_id?: undefined;
|
|
193
194
|
page?: undefined;
|
|
@@ -203,11 +204,11 @@ export declare const meetingTools: ({
|
|
|
203
204
|
format?: undefined;
|
|
204
205
|
transcript_id?: undefined;
|
|
205
206
|
query?: undefined;
|
|
206
|
-
limit?: undefined;
|
|
207
207
|
scan_limit?: undefined;
|
|
208
208
|
max_read_bytes?: undefined;
|
|
209
209
|
cursor?: undefined;
|
|
210
210
|
} | {
|
|
211
|
+
limit?: undefined;
|
|
211
212
|
event_id?: undefined;
|
|
212
213
|
series_id?: undefined;
|
|
213
214
|
page?: undefined;
|
|
@@ -225,11 +226,11 @@ export declare const meetingTools: ({
|
|
|
225
226
|
format?: undefined;
|
|
226
227
|
transcript_id?: undefined;
|
|
227
228
|
query?: undefined;
|
|
228
|
-
limit?: undefined;
|
|
229
229
|
scan_limit?: undefined;
|
|
230
230
|
max_read_bytes?: undefined;
|
|
231
231
|
cursor?: undefined;
|
|
232
232
|
} | {
|
|
233
|
+
limit?: undefined;
|
|
233
234
|
event_id?: undefined;
|
|
234
235
|
series_id?: undefined;
|
|
235
236
|
page?: undefined;
|
|
@@ -251,7 +252,6 @@ export declare const meetingTools: ({
|
|
|
251
252
|
minimum: number;
|
|
252
253
|
};
|
|
253
254
|
query?: undefined;
|
|
254
|
-
limit?: undefined;
|
|
255
255
|
scan_limit?: undefined;
|
|
256
256
|
max_read_bytes?: undefined;
|
|
257
257
|
cursor?: undefined;
|
|
@@ -338,6 +338,7 @@ export declare const meetingTools: ({
|
|
|
338
338
|
max_read_bytes?: undefined;
|
|
339
339
|
cursor?: undefined;
|
|
340
340
|
} | {
|
|
341
|
+
limit?: undefined;
|
|
341
342
|
event_id?: undefined;
|
|
342
343
|
series_id?: undefined;
|
|
343
344
|
page?: undefined;
|
|
@@ -353,11 +354,11 @@ export declare const meetingTools: ({
|
|
|
353
354
|
format?: undefined;
|
|
354
355
|
transcript_id?: undefined;
|
|
355
356
|
query?: undefined;
|
|
356
|
-
limit?: undefined;
|
|
357
357
|
scan_limit?: undefined;
|
|
358
358
|
max_read_bytes?: undefined;
|
|
359
359
|
cursor?: undefined;
|
|
360
360
|
} | {
|
|
361
|
+
limit?: undefined;
|
|
361
362
|
event_id?: undefined;
|
|
362
363
|
series_id?: undefined;
|
|
363
364
|
page?: undefined;
|
|
@@ -375,11 +376,11 @@ export declare const meetingTools: ({
|
|
|
375
376
|
format?: undefined;
|
|
376
377
|
transcript_id?: undefined;
|
|
377
378
|
query?: undefined;
|
|
378
|
-
limit?: undefined;
|
|
379
379
|
scan_limit?: undefined;
|
|
380
380
|
max_read_bytes?: undefined;
|
|
381
381
|
cursor?: undefined;
|
|
382
382
|
} | {
|
|
383
|
+
limit?: undefined;
|
|
383
384
|
event_id?: undefined;
|
|
384
385
|
series_id?: undefined;
|
|
385
386
|
page?: undefined;
|
|
@@ -401,7 +402,6 @@ export declare const meetingTools: ({
|
|
|
401
402
|
minimum: number;
|
|
402
403
|
};
|
|
403
404
|
query?: undefined;
|
|
404
|
-
limit?: undefined;
|
|
405
405
|
scan_limit?: undefined;
|
|
406
406
|
max_read_bytes?: undefined;
|
|
407
407
|
cursor?: undefined;
|
|
@@ -488,6 +488,7 @@ export declare const meetingTools: ({
|
|
|
488
488
|
max_read_bytes?: undefined;
|
|
489
489
|
cursor?: undefined;
|
|
490
490
|
} | {
|
|
491
|
+
limit?: undefined;
|
|
491
492
|
event_id?: undefined;
|
|
492
493
|
series_id?: undefined;
|
|
493
494
|
page?: undefined;
|
|
@@ -503,11 +504,11 @@ export declare const meetingTools: ({
|
|
|
503
504
|
format?: undefined;
|
|
504
505
|
transcript_id?: undefined;
|
|
505
506
|
query?: undefined;
|
|
506
|
-
limit?: undefined;
|
|
507
507
|
scan_limit?: undefined;
|
|
508
508
|
max_read_bytes?: undefined;
|
|
509
509
|
cursor?: undefined;
|
|
510
510
|
} | {
|
|
511
|
+
limit?: undefined;
|
|
511
512
|
event_id?: undefined;
|
|
512
513
|
series_id?: undefined;
|
|
513
514
|
page?: undefined;
|
|
@@ -525,11 +526,11 @@ export declare const meetingTools: ({
|
|
|
525
526
|
format?: undefined;
|
|
526
527
|
transcript_id?: undefined;
|
|
527
528
|
query?: undefined;
|
|
528
|
-
limit?: undefined;
|
|
529
529
|
scan_limit?: undefined;
|
|
530
530
|
max_read_bytes?: undefined;
|
|
531
531
|
cursor?: undefined;
|
|
532
532
|
} | {
|
|
533
|
+
limit?: undefined;
|
|
533
534
|
event_id?: undefined;
|
|
534
535
|
series_id?: undefined;
|
|
535
536
|
page?: undefined;
|
|
@@ -551,7 +552,6 @@ export declare const meetingTools: ({
|
|
|
551
552
|
minimum: number;
|
|
552
553
|
};
|
|
553
554
|
query?: undefined;
|
|
554
|
-
limit?: undefined;
|
|
555
555
|
scan_limit?: undefined;
|
|
556
556
|
max_read_bytes?: undefined;
|
|
557
557
|
cursor?: undefined;
|
|
@@ -638,6 +638,7 @@ export declare const meetingTools: ({
|
|
|
638
638
|
max_read_bytes?: undefined;
|
|
639
639
|
cursor?: undefined;
|
|
640
640
|
} | {
|
|
641
|
+
limit?: undefined;
|
|
641
642
|
event_id?: undefined;
|
|
642
643
|
series_id?: undefined;
|
|
643
644
|
page?: undefined;
|
|
@@ -653,11 +654,11 @@ export declare const meetingTools: ({
|
|
|
653
654
|
format?: undefined;
|
|
654
655
|
transcript_id?: undefined;
|
|
655
656
|
query?: undefined;
|
|
656
|
-
limit?: undefined;
|
|
657
657
|
scan_limit?: undefined;
|
|
658
658
|
max_read_bytes?: undefined;
|
|
659
659
|
cursor?: undefined;
|
|
660
660
|
} | {
|
|
661
|
+
limit?: undefined;
|
|
661
662
|
event_id?: undefined;
|
|
662
663
|
series_id?: undefined;
|
|
663
664
|
page?: undefined;
|
|
@@ -675,11 +676,11 @@ export declare const meetingTools: ({
|
|
|
675
676
|
format?: undefined;
|
|
676
677
|
transcript_id?: undefined;
|
|
677
678
|
query?: undefined;
|
|
678
|
-
limit?: undefined;
|
|
679
679
|
scan_limit?: undefined;
|
|
680
680
|
max_read_bytes?: undefined;
|
|
681
681
|
cursor?: undefined;
|
|
682
682
|
} | {
|
|
683
|
+
limit?: undefined;
|
|
683
684
|
event_id?: undefined;
|
|
684
685
|
series_id?: undefined;
|
|
685
686
|
page?: undefined;
|
|
@@ -701,7 +702,6 @@ export declare const meetingTools: ({
|
|
|
701
702
|
minimum: number;
|
|
702
703
|
};
|
|
703
704
|
query?: undefined;
|
|
704
|
-
limit?: undefined;
|
|
705
705
|
scan_limit?: undefined;
|
|
706
706
|
max_read_bytes?: undefined;
|
|
707
707
|
cursor?: undefined;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { MessageStore } from "../../../store/index.js";
|
|
2
|
+
import type { ProposalKind } from "../types.js";
|
|
3
|
+
export declare const invoiceKind: (store: Pick<MessageStore, "finance">) => ProposalKind;
|
|
4
|
+
export declare const paymentKind: (store: Pick<MessageStore, "finance">) => ProposalKind;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { kept, proposerOfAuthor, pushed } from "./shared.js";
|
|
2
|
+
const rowOf = (kind, entry) => ({
|
|
3
|
+
id: entry.ref,
|
|
4
|
+
kind,
|
|
5
|
+
status: entry.review,
|
|
6
|
+
project: entry.project,
|
|
7
|
+
subject: entry.ref,
|
|
8
|
+
object: "counterparty" in entry
|
|
9
|
+
? entry.counterparty.ref
|
|
10
|
+
: ((entry.direction === "in" ? entry.payer : entry.payee)?.ref ?? null),
|
|
11
|
+
summary: entry.title,
|
|
12
|
+
proposedBy: proposerOfAuthor(entry.author),
|
|
13
|
+
reason: entry.reason,
|
|
14
|
+
evidence: [],
|
|
15
|
+
score: null,
|
|
16
|
+
signals: null,
|
|
17
|
+
parts: null,
|
|
18
|
+
createdAt: entry.createdAt,
|
|
19
|
+
});
|
|
20
|
+
/**
|
|
21
|
+
* An agent's or an import's invoice or payment. One kind per entity, because the registry routes an id by its prefix
|
|
22
|
+
* and the id is the entry's own ref (`payment:12`), as a fact's is. Only the owner decides money.
|
|
23
|
+
*/
|
|
24
|
+
const financeKind = (store, kind) => ({
|
|
25
|
+
kind,
|
|
26
|
+
prefix: kind,
|
|
27
|
+
list: async (filter) => {
|
|
28
|
+
const status = filter.status ?? "proposed";
|
|
29
|
+
const options = { ...pushed(filter), ...(status === "all" ? {} : { review: status }) };
|
|
30
|
+
const entries = kind === "invoice" ? await store.finance.invoices(options) : await store.finance.payments(options);
|
|
31
|
+
return kept(entries.map((entry) => rowOf(kind, entry)), filter);
|
|
32
|
+
},
|
|
33
|
+
get: async (id) => rowOf(kind, kind === "invoice" ? await store.finance.invoice(id) : await store.finance.payment(id)),
|
|
34
|
+
decide: async (id, { confirm, by, reason }) => {
|
|
35
|
+
const entry = confirm ? await store.finance.confirm(id, by, reason) : await store.finance.reject(id, by, reason);
|
|
36
|
+
return { id, kind, status: confirm ? "confirmed" : "rejected", made: confirm ? [entry.ref] : [] };
|
|
37
|
+
},
|
|
38
|
+
});
|
|
39
|
+
export const invoiceKind = (store) => financeKind(store, "invoice");
|
|
40
|
+
export const paymentKind = (store) => financeKind(store, "payment");
|
|
@@ -2,6 +2,7 @@ import { CliError } from "@wirecat/cli-base";
|
|
|
2
2
|
import { mayDecide } from "../../store/decisions.js";
|
|
3
3
|
import { actionKind } from "./kinds/action.js";
|
|
4
4
|
import { factKind } from "./kinds/fact.js";
|
|
5
|
+
import { invoiceKind, paymentKind } from "./kinds/finance.js";
|
|
5
6
|
import { findingsKind } from "./kinds/findings.js";
|
|
6
7
|
import { keyDocumentKind } from "./kinds/key-document.js";
|
|
7
8
|
import { memoryKind } from "./kinds/memory.js";
|
|
@@ -122,6 +123,8 @@ export const proposalRegistry = (store) => {
|
|
|
122
123
|
relationshipUpdateKind(store),
|
|
123
124
|
keyDocumentKind(store),
|
|
124
125
|
factKind(store),
|
|
126
|
+
invoiceKind(store),
|
|
127
|
+
paymentKind(store),
|
|
125
128
|
memoryKind(store),
|
|
126
129
|
findingsKind(store),
|
|
127
130
|
])
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import type { ChatKind, Id, Message } from "../domain/models.js";
|
|
2
|
+
import type { AccountKey, MessageStore, TaskAnalysisMark } from "../store/index.js";
|
|
3
|
+
/** How many messages one read gives an agent: a page it can judge in one go. */
|
|
4
|
+
export declare const ANALYSIS_PAGE = 100;
|
|
5
|
+
export declare const ANALYSIS_PAGE_MAX = 1000;
|
|
6
|
+
/** Where a chat never read for tasks starts, unless the caller names a time: older history is not new work. */
|
|
7
|
+
export declare const defaultStart: (now: Date) => string;
|
|
8
|
+
export interface ChatAnalysis {
|
|
9
|
+
chatId: Id;
|
|
10
|
+
title: string | null;
|
|
11
|
+
kind: ChatKind;
|
|
12
|
+
newestAt: string | null;
|
|
13
|
+
mark: TaskAnalysisMark | null;
|
|
14
|
+
/** Stored messages after the mark, or since the default start when the chat was never read for tasks. */
|
|
15
|
+
waiting: number;
|
|
16
|
+
/** Stored inside the read stretch after it was read: `--since <from>` reads the stretch again. */
|
|
17
|
+
late: number;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Every chat whose messages can hold the owner's tasks — not a channel or Saved Messages (owner, 2026-10-17) — with
|
|
21
|
+
* how far it was read for tasks and how much waits, newest chat first.
|
|
22
|
+
*/
|
|
23
|
+
export declare const taskAnalysisList: (store: MessageStore, account: AccountKey, now?: Date) => Promise<ChatAnalysis[]>;
|
|
24
|
+
export interface UnanalysedPage {
|
|
25
|
+
mark: TaskAnalysisMark | null;
|
|
26
|
+
/** Where this read started: the mark, `since`, or the default start. */
|
|
27
|
+
from: string;
|
|
28
|
+
messages: Message[];
|
|
29
|
+
more: boolean;
|
|
30
|
+
late: number;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* The stored messages of a chat not yet read for tasks, oldest first, from its mark; `since` reads from that time
|
|
34
|
+
* instead, to read a stretch again. Reading moves nothing: `acknowledgeTaskAnalysis` does, once the reader is done.
|
|
35
|
+
*/
|
|
36
|
+
export declare const unanalysedMessages: (store: MessageStore, account: AccountKey, chatId: Id, { limit, since, now }?: {
|
|
37
|
+
limit?: number;
|
|
38
|
+
since?: string;
|
|
39
|
+
now?: Date;
|
|
40
|
+
}) => Promise<UnanalysedPage>;
|
|
41
|
+
/**
|
|
42
|
+
* Records that the chat was read for tasks through `messageId`, from `since` when that read started there. The mark
|
|
43
|
+
* never moves back. A read that covered the whole stretch again also clears what arrived late inside it.
|
|
44
|
+
*/
|
|
45
|
+
export declare const acknowledgeTaskAnalysis: (store: MessageStore, account: AccountKey, chatId: Id, messageId: Id, { since, by, now }: {
|
|
46
|
+
since?: string;
|
|
47
|
+
by: string;
|
|
48
|
+
now?: Date;
|
|
49
|
+
}) => Promise<{
|
|
50
|
+
mark: TaskAnalysisMark;
|
|
51
|
+
moved: boolean;
|
|
52
|
+
}>;
|
|
53
|
+
/**
|
|
54
|
+
* A read again of history the chat's task point already passed only updates and closes tasks (owner, 2026-11-03):
|
|
55
|
+
* a new task from such a message needs `--open-new`. A message that already has a task, or one after the point, is
|
|
56
|
+
* let through.
|
|
57
|
+
*/
|
|
58
|
+
export declare const refuseAlreadyRead: (store: MessageStore, account: AccountKey, source: string) => Promise<void>;
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { CliError } from "@wirecat/cli-base";
|
|
2
|
+
import { isLocator, parseLocator } from "../domain/locator.js";
|
|
3
|
+
import { FIRST_PASS_DAYS, RULES_IN, taskAccount } from "./task-rules.js";
|
|
4
|
+
/** How many messages one read gives an agent: a page it can judge in one go. */
|
|
5
|
+
export const ANALYSIS_PAGE = 100;
|
|
6
|
+
export const ANALYSIS_PAGE_MAX = 1000;
|
|
7
|
+
/** Where a chat never read for tasks starts, unless the caller names a time: older history is not new work. */
|
|
8
|
+
export const defaultStart = (now) => new Date(now.getTime() - FIRST_PASS_DAYS * 86_400_000).toISOString();
|
|
9
|
+
const after = (iso) => new Date(Date.parse(iso) + 1).toISOString();
|
|
10
|
+
/** Messages saved or edited after the mark was last checked, sent inside the stretch it had read. */
|
|
11
|
+
const lateOf = async (store, account, mark) => {
|
|
12
|
+
const { messages } = await store.messages.changes(account, mark.chatId, mark.checkedAt);
|
|
13
|
+
return messages.filter((one) => one.timestamp >= mark.from && one.timestamp <= mark.checkedThrough);
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Every chat whose messages can hold the owner's tasks — not a channel or Saved Messages (owner, 2026-10-17) — with
|
|
17
|
+
* how far it was read for tasks and how much waits, newest chat first.
|
|
18
|
+
*/
|
|
19
|
+
export const taskAnalysisList = async (store, account, now = new Date()) => {
|
|
20
|
+
const marks = new Map((await store.sync.taskAnalysisMarks(account)).map((mark) => [mark.chatId, mark]));
|
|
21
|
+
const start = defaultStart(now);
|
|
22
|
+
const chats = [];
|
|
23
|
+
for (const chat of await store.chats.chatStats(account)) {
|
|
24
|
+
if (RULES_IN[chat.kind] === "none")
|
|
25
|
+
continue;
|
|
26
|
+
const mark = marks.get(chat.chatId) ?? null;
|
|
27
|
+
chats.push({
|
|
28
|
+
chatId: chat.chatId,
|
|
29
|
+
title: chat.title,
|
|
30
|
+
kind: chat.kind,
|
|
31
|
+
newestAt: chat.newestAt,
|
|
32
|
+
mark,
|
|
33
|
+
waiting: await store.messages.countMessages(account, chat.chatId, { since: mark ? after(mark.through) : start }),
|
|
34
|
+
late: mark ? (await lateOf(store, account, mark)).length : 0,
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
return chats.sort((a, b) => (b.newestAt ?? "").localeCompare(a.newestAt ?? ""));
|
|
38
|
+
};
|
|
39
|
+
/**
|
|
40
|
+
* The stored messages of a chat not yet read for tasks, oldest first, from its mark; `since` reads from that time
|
|
41
|
+
* instead, to read a stretch again. Reading moves nothing: `acknowledgeTaskAnalysis` does, once the reader is done.
|
|
42
|
+
*/
|
|
43
|
+
export const unanalysedMessages = async (store, account, chatId, { limit = ANALYSIS_PAGE, since, now = new Date() } = {}) => {
|
|
44
|
+
const mark = (await store.sync.taskAnalysisMark(account, chatId)) ?? null;
|
|
45
|
+
const from = since ?? mark?.through ?? defaultStart(now);
|
|
46
|
+
const byTime = { time: Date.parse(from) - (since === undefined && mark ? 0 : 1) };
|
|
47
|
+
const read = (start) => store.messages.messages(account, chatId, { limit, after: start });
|
|
48
|
+
let page;
|
|
49
|
+
if (since === undefined && mark) {
|
|
50
|
+
try {
|
|
51
|
+
page = await read({ id: mark.throughId });
|
|
52
|
+
}
|
|
53
|
+
catch (error) {
|
|
54
|
+
if (!(error instanceof CliError && error.code === "not_found"))
|
|
55
|
+
throw error;
|
|
56
|
+
page = await read(byTime);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
else
|
|
60
|
+
page = await read(byTime);
|
|
61
|
+
return {
|
|
62
|
+
mark,
|
|
63
|
+
from,
|
|
64
|
+
messages: page.items,
|
|
65
|
+
more: page.hasMore,
|
|
66
|
+
late: mark ? (await lateOf(store, account, mark)).length : 0,
|
|
67
|
+
};
|
|
68
|
+
};
|
|
69
|
+
/**
|
|
70
|
+
* Records that the chat was read for tasks through `messageId`, from `since` when that read started there. The mark
|
|
71
|
+
* never moves back. A read that covered the whole stretch again also clears what arrived late inside it.
|
|
72
|
+
*/
|
|
73
|
+
export const acknowledgeTaskAnalysis = async (store, account, chatId, messageId, { since, by, now = new Date() }) => {
|
|
74
|
+
const message = await store.messages.message(account, messageId, { chatId });
|
|
75
|
+
if (!message)
|
|
76
|
+
throw new CliError("not_found", `message ${messageId} is not in the local copy of chat ${chatId}`);
|
|
77
|
+
const mark = await store.sync.taskAnalysisMark(account, chatId);
|
|
78
|
+
const start = since ?? mark?.from ?? defaultStart(now);
|
|
79
|
+
if (message.timestamp < start)
|
|
80
|
+
throw new CliError("validation_error", `message ${messageId} was sent before the read started (${start})`);
|
|
81
|
+
if (mark && message.timestamp < mark.from)
|
|
82
|
+
throw new CliError("validation_error", `message ${messageId} ends before the stretch already read (${mark.from}): read on to it, then acknowledge`);
|
|
83
|
+
const ahead = !mark || message.timestamp > mark.through || (since !== undefined && message.timestamp >= mark.through);
|
|
84
|
+
if (mark && !ahead && start >= mark.from)
|
|
85
|
+
return { mark, moved: false };
|
|
86
|
+
const reread = mark !== undefined && since !== undefined && since <= mark.from && ahead;
|
|
87
|
+
const checked = !mark || reread || (since === undefined && (await lateOf(store, account, mark)).length === 0);
|
|
88
|
+
const through = mark && !ahead ? mark : { through: message.timestamp, throughId: message.id };
|
|
89
|
+
const next = {
|
|
90
|
+
chatId,
|
|
91
|
+
from: mark && mark.from < start ? mark.from : start,
|
|
92
|
+
through: through.through,
|
|
93
|
+
throughId: through.throughId,
|
|
94
|
+
by,
|
|
95
|
+
checked,
|
|
96
|
+
checkedThrough: checked || !mark ? through.through : mark.checkedThrough,
|
|
97
|
+
};
|
|
98
|
+
await store.sync.setTaskAnalysisMark(account, next);
|
|
99
|
+
const saved = await store.sync.taskAnalysisMark(account, chatId);
|
|
100
|
+
if (!saved)
|
|
101
|
+
throw new Error(`the task analysis mark of chat ${chatId} was not saved`);
|
|
102
|
+
return { mark: saved, moved: true };
|
|
103
|
+
};
|
|
104
|
+
/**
|
|
105
|
+
* A read again of history the chat's task point already passed only updates and closes tasks (owner, 2026-11-03):
|
|
106
|
+
* a new task from such a message needs `--open-new`. A message that already has a task, or one after the point, is
|
|
107
|
+
* let through.
|
|
108
|
+
*/
|
|
109
|
+
export const refuseAlreadyRead = async (store, account, source) => {
|
|
110
|
+
if (!isLocator(source))
|
|
111
|
+
return;
|
|
112
|
+
const { provider, account: owner, chat, message } = parseLocator(source);
|
|
113
|
+
if (provider !== account.provider || owner !== account.account)
|
|
114
|
+
return;
|
|
115
|
+
const mark = await store.sync.taskAnalysisMark(account, chat);
|
|
116
|
+
if (!mark)
|
|
117
|
+
return;
|
|
118
|
+
const stored = await store.messages.message(account, message, { chatId: chat });
|
|
119
|
+
if (!stored || stored.timestamp > mark.through)
|
|
120
|
+
return;
|
|
121
|
+
if ((await store.tasks.findBySource(taskAccount(account), source)).length > 0)
|
|
122
|
+
return;
|
|
123
|
+
throw new CliError("validation_error", `${source} was already read for tasks (the point is at ${mark.through}): a read again only updates and closes ` +
|
|
124
|
+
"tasks; add --open-new to open a task from it anyway", { reason: "task.already-read" });
|
|
125
|
+
};
|
package/dist/store/exports.d.ts
CHANGED
|
@@ -23,7 +23,7 @@ export { storeClients } from "./sqlite/clients.js";
|
|
|
23
23
|
export { CHAT_LIST_KEY, type ChatCompleteness, fetchedKey, historyStartKey } from "./sqlite/completeness.js";
|
|
24
24
|
export { CONVERSATION_COLUMNS } from "./sqlite/conversations.js";
|
|
25
25
|
export type { CounterTarget } from "./sqlite/counters.js";
|
|
26
|
-
export { type EmailMarks, MAIL_AGENDA_COLUMNS, type NewestEmail, type ThreadActivity, } from "./sqlite/email-activity.js";
|
|
26
|
+
export { type EmailMarks, MAIL_AGENDA_COLUMNS, type MarkedEmail, type NewestEmail, type ThreadActivity, } from "./sqlite/email-activity.js";
|
|
27
27
|
export { messageOfEmail, threadConversation } from "./sqlite/emails.js";
|
|
28
28
|
export { orphanPointers } from "./sqlite/entity-types.js";
|
|
29
29
|
export { involvementStoreOver } from "./sqlite/involvements.js";
|
|
@@ -61,5 +61,5 @@ export type { MatchPlace, ScoredHit } from "./sqlite/words.js";
|
|
|
61
61
|
export type { TaskDetails } from "./sqlite/work-tasks.js";
|
|
62
62
|
export type { SyncStore } from "./sync.js";
|
|
63
63
|
export type { TagsStore } from "./tags.js";
|
|
64
|
-
export type { AccountKey, AccountMessageFilter, AgentAnswer, BatchMessage, ChatActivity, ChatStats, ConversationBuild, ConversationHit, ConversationSummary, DeletionScope, Delta, IdentityRef, IngestedVia, LinkBatch, LinkedIdentity, LinkOptions, MessageFilter, PersonFacts, PersonRecord, PictureInput, Range, SenderChatStats, StoredAccount, StoredChatFilter, StoredHit, StoredLink, StoredReadiness, } from "./types.js";
|
|
64
|
+
export type { AccountKey, AccountMessageFilter, AgentAnswer, BatchMessage, ChatActivity, ChatStats, ConversationBuild, ConversationHit, ConversationSummary, DeletionScope, Delta, IdentityRef, IngestedVia, LinkBatch, LinkedIdentity, LinkOptions, MessageFilter, PersonFacts, PersonRecord, PictureInput, Range, SenderChatStats, StoredAccount, StoredChatFilter, StoredHit, StoredLink, StoredReadiness, TaskAnalysisMark, TaskAnalysisMarkWrite, } from "./types.js";
|
|
65
65
|
export type { AccountVectors, VectorsStore } from "./vectors.js";
|
package/dist/store/index.d.ts
CHANGED
|
@@ -38,6 +38,7 @@ export { EVENT_FIELDS, type EventChunkToEmbed, type EventHit, type EventQuery, t
|
|
|
38
38
|
export type { EvidenceSource } from "./sqlite/evidence-sources.js";
|
|
39
39
|
export type { Fact, FactInput, FactsStore, PaymentFilter } from "./sqlite/facts.js";
|
|
40
40
|
export type { FileListQuery, FilesStore, StoredFile } from "./sqlite/files.js";
|
|
41
|
+
export type { Allocation, FinanceStore, Invoice, InvoiceDetail, InvoiceInput, InvoiceLine, InvoiceLineInput, OpenTotal, Party, Payment as FinancePayment, PaymentDetail as FinancePaymentDetail, PaymentInput as FinancePaymentInput, } from "./sqlite/finance.js";
|
|
41
42
|
export { IMPORTED_DOCUMENT_QUERY, type ImportedDocuments } from "./sqlite/imported-documents.js";
|
|
42
43
|
export type { Involvement, InvolvementStore } from "./sqlite/involvements.js";
|
|
43
44
|
export type { Annotation, KnowledgeRelation, KnowledgeStore, KnowledgeTarget, LabelledType, Organization, Project, Reminder, } from "./sqlite/knowledge.js";
|
|
@@ -71,4 +72,4 @@ export type { StoreTaskStore } from "./sqlite/tasks.js";
|
|
|
71
72
|
export type { TagPreflight, VocabularyAlias, VocabularyAliasReceipt, VocabularyAudit, VocabularyAuditOptions, VocabularyCatalog, VocabularyEntry, VocabularyKind, VocabularyOptions, VocabularyResolution, VocabularyStore, VocabularyTarget, } from "./sqlite/vocabulary.js";
|
|
72
73
|
export type { BoardCounts, BoardOptions, NewWorkTask, RevisionCheck, TaskAssignment, TaskDetails, TaskEvent, TaskFields, TaskMove, TaskMoved, TaskRole, TaskType, WorkTaskType, } from "./sqlite/work-tasks.js";
|
|
73
74
|
export { TASK_EVENT_KINDS, TASK_ROLES } from "./sqlite/work-tasks.js";
|
|
74
|
-
export { type AccountAccounts, type AccountAttachments, type AccountCounters, type AccountKey, type AccountMentions, type AccountMessageFilter, type AccountMessages, type AccountPeople, type AccountsStore, type AccountVectors, type AttachmentsStore, type AttachmentTextEntry, type AttachmentView, type ChatStats, type ChatsStore, type ConversationsStore, type CountersStore, type DeletionScope, type Delta, type FileAttachment, type IdentityRef, type IngestedVia, type LinkedIdentity, type LinkOptions, MENTION_QUERY, MENTION_STATUSES, type MentionsStore, type MessageFilter, type MessageStore, type MessagesStore, OTHER_SOURCES, openStore, type PeopleStore, type PersonFacts, type PersonRecord, type QueriesStore, type Range, type RankedEvidence, type RankedStoreFound, type RankedStoreRow, type RankingEvidenceItem, type RankingEvidenceRequest, type RankingRequest, type RosterStore, type SearchCommand, type SearchesStore, type SearchIndexStore, type SearchRecord, type StoredAccount, type StoredChatFilter, type StoredHit, type StoredSearch, type StoredTag, type StoreOptions, type SyncStore, type TagFilter, type TagsStore, type TagTarget, type TaskTagTarget, type TextOrigin, type VectorsStore, } from "./store.js";
|
|
75
|
+
export { type AccountAccounts, type AccountAttachments, type AccountCounters, type AccountKey, type AccountMentions, type AccountMessageFilter, type AccountMessages, type AccountPeople, type AccountsStore, type AccountVectors, type AttachmentsStore, type AttachmentTextEntry, type AttachmentView, type ChatStats, type ChatsStore, type ConversationsStore, type CountersStore, type DeletionScope, type Delta, type FileAttachment, type IdentityRef, type IngestedVia, type LinkedIdentity, type LinkOptions, MENTION_QUERY, MENTION_STATUSES, type MentionsStore, type MessageFilter, type MessageStore, type MessagesStore, OTHER_SOURCES, openStore, type PeopleStore, type PersonFacts, type PersonRecord, type QueriesStore, type Range, type RankedEvidence, type RankedStoreFound, type RankedStoreRow, type RankingEvidenceItem, type RankingEvidenceRequest, type RankingRequest, type RosterStore, type SearchCommand, type SearchesStore, type SearchIndexStore, type SearchRecord, type StoredAccount, type StoredChatFilter, type StoredHit, type StoredSearch, type StoredTag, type StoreOptions, type SyncStore, type TagFilter, type TagsStore, type TagTarget, type TaskAnalysisMark, type TaskAnalysisMarkWrite, type TaskTagTarget, type TextOrigin, type VectorsStore, } from "./store.js";
|