@wirecat/cli-core 0.545.0 → 0.547.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 +228 -0
- package/dist/calendar/busy.js +4 -1
- package/dist/calendar/cli/answers.d.ts +31 -0
- package/dist/calendar/cli/answers.js +8 -0
- package/dist/calendar/cli/index.d.ts +6 -0
- package/dist/calendar/cli/index.js +43 -4
- package/dist/calendar/cli/remind.js +2 -1
- package/dist/calendar/expand.d.ts +17 -0
- package/dist/calendar/expand.js +340 -0
- package/dist/calendar/feeds.d.ts +96 -0
- package/dist/calendar/feeds.js +324 -0
- package/dist/calendar/ics.d.ts +15 -4
- package/dist/calendar/ics.js +18 -7
- package/dist/calendar/index.d.ts +3 -1
- package/dist/calendar/index.js +2 -0
- package/dist/calendar/server-search.js +3 -1
- package/dist/calendar/writes.js +15 -4
- package/dist/cli/after-dashes.d.ts +16 -0
- package/dist/cli/after-dashes.js +41 -0
- package/dist/cli/bot/context.d.ts +1 -1
- package/dist/cli/bot/context.js +9 -1
- package/dist/cli/bot/messages.js +2 -0
- package/dist/cli/bot/setup.js +1 -0
- package/dist/cli/contract-templates.js +2 -2
- package/dist/cli/entry.d.ts +2 -0
- package/dist/cli/entry.js +3 -2
- package/dist/cli/index.d.ts +2 -1
- package/dist/cli/index.js +2 -1
- package/dist/cli/messenger/admin-commands.js +5 -1
- package/dist/cli/messenger/admin-contacts-command.js +5 -1
- package/dist/cli/messenger/admin-folders-command.js +5 -1
- package/dist/cli/messenger/complete-command.js +1 -0
- package/dist/cli/messenger/history-query.d.ts +10 -4
- package/dist/cli/messenger/history-query.js +87 -31
- package/dist/cli/messenger/messages-command.js +12 -23
- package/dist/cli/messenger/messages-comments-command.js +4 -2
- package/dist/cli/messenger/messages-edit-command.js +1 -0
- package/dist/cli/messenger/messages-press-command.js +1 -0
- package/dist/cli/messenger/messages-send-command.js +1 -0
- package/dist/cli/messenger/observed.js +2 -2
- package/dist/cli/messenger/polls-command.js +1 -0
- package/dist/cli/messenger/private-people-command.js +5 -1
- package/dist/cli/messenger/store-maintenance-command.d.ts +1 -1
- package/dist/cli/messenger/stored.js +56 -3
- package/dist/cli/messenger/topics-command.js +1 -1
- package/dist/cli/option-hints.d.ts +6 -0
- package/dist/cli/option-hints.js +15 -0
- package/dist/cli/program.js +17 -6
- package/dist/cli/schedule/schedule-command.js +1 -0
- package/dist/domain/message-link.d.ts +3 -0
- package/dist/domain/message-link.js +9 -14
- package/dist/domain/money-words.d.ts +11 -0
- package/dist/domain/money-words.js +38 -0
- package/dist/domain/providers.d.ts +2 -0
- package/dist/domain/providers.js +15 -3
- package/dist/domain/ref-arguments.d.ts +31 -0
- package/dist/domain/ref-arguments.js +79 -0
- package/dist/domain/references.d.ts +20 -2
- package/dist/domain/references.js +132 -47
- package/dist/errors/reasons.js +31 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/mail/cli/index.js +4 -4
- package/dist/mail/index.d.ts +2 -0
- package/dist/mail/index.js +2 -0
- package/dist/mail/partial.d.ts +34 -0
- package/dist/mail/partial.js +94 -0
- package/dist/mail/server-search.js +17 -9
- package/dist/mail/source.d.ts +13 -2
- package/dist/mail/source.js +7 -1
- package/dist/mail/sync-types.d.ts +112 -0
- package/dist/mail/sync-types.js +1 -0
- package/dist/mail/sync.d.ts +4 -106
- package/dist/mail/sync.js +49 -4
- package/dist/mail/testing/fake.d.ts +3 -1
- package/dist/mail/testing/fake.js +10 -2
- package/dist/meetings/mcp/index.d.ts +15 -15
- package/dist/oauth/client-file.d.ts +14 -0
- package/dist/oauth/client-file.js +28 -0
- package/dist/oauth/index.d.ts +1 -0
- package/dist/oauth/index.js +1 -0
- package/dist/ports/messenger.d.ts +3 -2
- package/dist/resolve.d.ts +3 -1
- package/dist/resolve.js +8 -0
- package/dist/search/task-signature.d.ts +5 -1
- package/dist/search/task-signature.js +27 -9
- package/dist/services/agenda.d.ts +5 -0
- package/dist/services/agenda.js +3 -1
- package/dist/services/deps.d.ts +0 -2
- package/dist/services/deps.js +0 -2
- package/dist/services/documents/ingestion.js +1 -1
- package/dist/services/documents/knowledge.d.ts +10 -6
- package/dist/services/documents/knowledge.js +25 -11
- package/dist/services/index.d.ts +6 -1
- package/dist/services/index.js +6 -1
- package/dist/services/message-resolution.d.ts +4 -1
- package/dist/services/message-resolution.js +19 -3
- package/dist/services/messages.d.ts +2 -0
- package/dist/services/messages.js +40 -36
- package/dist/services/money-words.d.ts +3 -0
- package/dist/services/money-words.js +5 -0
- package/dist/services/proposal-tasks.d.ts +3 -2
- package/dist/services/proposal-tasks.js +5 -2
- package/dist/services/proposals/ids.d.ts +5 -0
- package/dist/services/proposals/ids.js +43 -0
- package/dist/services/proposals/index.d.ts +3 -0
- package/dist/services/proposals/index.js +2 -0
- package/dist/services/proposals/kinds/action.d.ts +7 -0
- package/dist/services/proposals/kinds/action.js +45 -0
- package/dist/services/proposals/kinds/fact.d.ts +4 -0
- package/dist/services/proposals/kinds/fact.js +43 -0
- package/dist/services/proposals/kinds/findings.d.ts +7 -0
- package/dist/services/proposals/kinds/findings.js +75 -0
- package/dist/services/proposals/kinds/key-document.d.ts +9 -0
- package/dist/services/proposals/kinds/key-document.js +75 -0
- package/dist/services/proposals/kinds/memory.d.ts +4 -0
- package/dist/services/proposals/kinds/memory.js +42 -0
- package/dist/services/proposals/kinds/relationship.d.ts +10 -0
- package/dist/services/proposals/kinds/relationship.js +82 -0
- package/dist/services/proposals/kinds/shared.d.ts +25 -0
- package/dist/services/proposals/kinds/shared.js +49 -0
- package/dist/services/proposals/registry.d.ts +9 -0
- package/dist/services/proposals/registry.js +129 -0
- package/dist/services/proposals/types.d.ts +85 -0
- package/dist/services/proposals/types.js +1 -0
- package/dist/services/questions.d.ts +7 -2
- package/dist/services/questions.js +13 -4
- package/dist/services/server-search.d.ts +7 -4
- package/dist/services/server-search.js +5 -2
- package/dist/services/stored-project-gathering.d.ts +9 -0
- package/dist/services/stored-project-gathering.js +9 -4
- package/dist/services/task-categories.d.ts +2 -0
- package/dist/services/task-categories.js +19 -8
- package/dist/services/tasks.js +8 -4
- package/dist/store/decisions.d.ts +65 -0
- package/dist/store/decisions.js +55 -0
- package/dist/store/evidence-findings.d.ts +6 -6
- package/dist/store/index.d.ts +4 -3
- package/dist/store/index.js +2 -1
- package/dist/store/meeting-findings.d.ts +2 -0
- package/dist/store/messages.d.ts +4 -9
- package/dist/store/sqlite/actors.d.ts +13 -2
- package/dist/store/sqlite/actors.js +24 -1
- package/dist/store/sqlite/email-locations.d.ts +16 -0
- package/dist/store/sqlite/email-locations.js +26 -0
- package/dist/store/sqlite/emails.d.ts +6 -2
- package/dist/store/sqlite/emails.js +2 -1
- package/dist/store/sqlite/evidence-findings.js +13 -3
- package/dist/store/sqlite/evidence-sources.js +2 -2
- package/dist/store/sqlite/facts.d.ts +16 -8
- package/dist/store/sqlite/facts.js +48 -15
- package/dist/store/sqlite/findings-core.d.ts +2 -1
- package/dist/store/sqlite/findings-core.js +4 -4
- package/dist/store/sqlite/identities.js +1 -1
- package/dist/store/sqlite/knowledge.d.ts +43 -7
- package/dist/store/sqlite/knowledge.js +62 -17
- package/dist/store/sqlite/meeting-findings.js +6 -6
- package/dist/store/sqlite/memories.d.ts +12 -8
- package/dist/store/sqlite/memories.js +33 -10
- package/dist/store/sqlite/notes.d.ts +5 -1
- package/dist/store/sqlite/notes.js +22 -6
- package/dist/store/sqlite/open-store.d.ts +4 -1
- package/dist/store/sqlite/open-store.js +8 -2
- package/dist/store/sqlite/open.d.ts +3 -0
- package/dist/store/sqlite/proposed-actions.d.ts +21 -8
- package/dist/store/sqlite/proposed-actions.js +29 -9
- package/dist/store/sqlite/reads.d.ts +13 -2
- package/dist/store/sqlite/reads.js +8 -4
- package/dist/store/sqlite/relation-proposals.d.ts +34 -0
- package/dist/store/sqlite/relation-proposals.js +114 -0
- package/dist/store/sqlite/things.d.ts +0 -1
- package/dist/store/sqlite/things.js +25 -24
- package/dist/store/store.d.ts +3 -0
- package/dist/store/store.js +2 -0
- package/package.json +1 -1
package/dist/mail/sync.js
CHANGED
|
@@ -12,11 +12,13 @@ import { dropMissing, tooManyGone } from "./gone.js";
|
|
|
12
12
|
import { mailHeadersOf } from "./headers.js";
|
|
13
13
|
import { flagsToRefresh, proveByLocation } from "./locations.js";
|
|
14
14
|
import { MAX_BODY_CHARS, parseMail } from "./parse.js";
|
|
15
|
+
import { completePartial } from "./partial.js";
|
|
15
16
|
import { FETCH_SLICE, keyOf, readQuick } from "./quick.js";
|
|
16
17
|
import { FULL_PASS_MS, MBOX_RESUME, mergeRanges, parsePoint, rangesOf, resumeKey, rulesKey, within, } from "./resume.js";
|
|
17
18
|
import { retryUnread } from "./retry.js";
|
|
18
19
|
import { ruleTagger, settleRuleTags } from "./rule-tags.js";
|
|
19
20
|
import { decide, ENVELOPE, envelopeBox, envelopeBoxOf, tagsOf } from "./rules.js";
|
|
21
|
+
import { searchRefused } from "./source.js";
|
|
20
22
|
const DAY = 86_400_000;
|
|
21
23
|
/** IMAP's SINCE counts whole days in the server's zone, so the window's first days are not trusted. */
|
|
22
24
|
const EDGE = 2 * DAY;
|
|
@@ -32,6 +34,29 @@ const LIST_SLICE = 200;
|
|
|
32
34
|
const STORE_BUSY_TRIES = 5;
|
|
33
35
|
const STORE_BUSY_WAIT_MS = 2_000;
|
|
34
36
|
export const syncMail = async (source, store, options) => {
|
|
37
|
+
const result = await syncRounds(source, store, options);
|
|
38
|
+
if (options.completePartial === false || options.retryAttachments || options.account.mode === "mbox")
|
|
39
|
+
return result;
|
|
40
|
+
if (result.stopped !== undefined || options.signal?.aborted)
|
|
41
|
+
return result;
|
|
42
|
+
const partial = await completePartial({
|
|
43
|
+
store,
|
|
44
|
+
source,
|
|
45
|
+
accountId: await store.accounts.saveAccount(mailAccountKey(options.account.address), {
|
|
46
|
+
name: options.account.address,
|
|
47
|
+
}),
|
|
48
|
+
address: options.account.address,
|
|
49
|
+
folders: () => mailFolders(options.account, source),
|
|
50
|
+
maxBodyChars: options.maxBodyChars ?? MAX_BODY_CHARS,
|
|
51
|
+
maxAttachmentChars: options.maxAttachmentChars ?? MAX_ATTACHMENT_CHARS,
|
|
52
|
+
loadEngine: options.loadEngine ?? importEngine,
|
|
53
|
+
now: (options.now ?? Date.now)(),
|
|
54
|
+
...(options.budget ? { take: () => options.budget?.take() ?? null } : {}),
|
|
55
|
+
...(options.signal ? { signal: options.signal } : {}),
|
|
56
|
+
});
|
|
57
|
+
return partial.completed || partial.left ? { ...result, partial } : result;
|
|
58
|
+
};
|
|
59
|
+
const syncRounds = async (source, store, options) => {
|
|
35
60
|
const { budget, index } = options;
|
|
36
61
|
if (budget === undefined || options.retryAttachments || options.account.mode === "mbox")
|
|
37
62
|
return syncRound(source, store, options);
|
|
@@ -45,6 +70,7 @@ export const syncMail = async (source, store, options) => {
|
|
|
45
70
|
unlisted: new Set(),
|
|
46
71
|
quick: new Map(),
|
|
47
72
|
quickFolders: new Set(),
|
|
73
|
+
refused: new Set(),
|
|
48
74
|
stopped: null,
|
|
49
75
|
remaining: 0,
|
|
50
76
|
asked: 0,
|
|
@@ -195,10 +221,16 @@ const syncRound = async (source, store, { account, since, max = 200, maxBodyChar
|
|
|
195
221
|
/** A quick folder's stored mail as it was before this run changed anything, with the UID of each. */
|
|
196
222
|
const folderMail = new Map();
|
|
197
223
|
const refreshed = new Map();
|
|
224
|
+
/** Folders whose server refused SEARCH: nothing of them is known, so nothing of them is proved or moved. */
|
|
225
|
+
const refused = new Set();
|
|
198
226
|
const holdsMail = async (folder) => (await store.mail.emails({ accountId, mailbox: folder, limit: 1 })).length > 0;
|
|
199
227
|
for (const folder of folders) {
|
|
200
228
|
if (mboxPoint !== undefined)
|
|
201
229
|
break;
|
|
230
|
+
if (plan?.refused.has(folder)) {
|
|
231
|
+
refused.add(folder);
|
|
232
|
+
continue;
|
|
233
|
+
}
|
|
202
234
|
let searched;
|
|
203
235
|
if (source.search !== undefined && !snapshot) {
|
|
204
236
|
searched = plan?.searches.get(folder);
|
|
@@ -209,7 +241,16 @@ const syncRound = async (source, store, { account, since, max = 200, maxBodyChar
|
|
|
209
241
|
capped = true;
|
|
210
242
|
continue;
|
|
211
243
|
}
|
|
212
|
-
|
|
244
|
+
try {
|
|
245
|
+
searched = await source.search(since, folder);
|
|
246
|
+
}
|
|
247
|
+
catch (error) {
|
|
248
|
+
if (!searchRefused(error))
|
|
249
|
+
throw error;
|
|
250
|
+
refused.add(folder);
|
|
251
|
+
plan?.refused.add(folder);
|
|
252
|
+
continue;
|
|
253
|
+
}
|
|
213
254
|
plan?.searches.set(folder, searched);
|
|
214
255
|
}
|
|
215
256
|
}
|
|
@@ -380,6 +421,8 @@ const syncRound = async (source, store, { account, since, max = 200, maxBodyChar
|
|
|
380
421
|
let skipped;
|
|
381
422
|
if (snapshot)
|
|
382
423
|
skipped = "an mbox file is a snapshot; mail missing from it is not proven deleted";
|
|
424
|
+
else if (refused.size > 0)
|
|
425
|
+
skipped = `the server refused to search ${[...refused].join(", ")}; no deletion is checked until it answers`;
|
|
383
426
|
else if (plan !== undefined && (capped || plan.tried.size > plan.asked || plan.only !== undefined))
|
|
384
427
|
skipped = "this run read the window in parts; a run that lists all of it at once checks deletions";
|
|
385
428
|
else if (quickRan.size > 0) {
|
|
@@ -427,7 +470,7 @@ const syncRound = async (source, store, { account, since, max = 200, maxBodyChar
|
|
|
427
470
|
skipped ??= older.skipped;
|
|
428
471
|
}
|
|
429
472
|
if (!snapshot)
|
|
430
|
-
await store.mail.setMailboxes(accountId, folders.map(mailbox), new Map([...foundFolders].map(([id, found]) => [id, [...found]])), startedAt);
|
|
473
|
+
await store.mail.setMailboxes(accountId, folders.filter((folder) => !refused.has(folder)).map(mailbox), new Map([...foundFolders].map(([id, found]) => [id, [...found]])), startedAt);
|
|
431
474
|
// A message's label list is whole, so every label the account has is replaced for each message read.
|
|
432
475
|
if (labelsOf.size && !snapshot) {
|
|
433
476
|
const known = (await store.mail.mailboxes(accountId)).filter(({ kind }) => kind === "label");
|
|
@@ -766,7 +809,7 @@ const syncRound = async (source, store, { account, since, max = 200, maxBodyChar
|
|
|
766
809
|
],
|
|
767
810
|
]),
|
|
768
811
|
]), startedAt);
|
|
769
|
-
const incomplete = capped || (plan !== undefined && (plan.stopped !== null || plan.failed.size > 0));
|
|
812
|
+
const incomplete = capped || refused.size > 0 || (plan !== undefined && (plan.stopped !== null || plan.failed.size > 0));
|
|
770
813
|
const complete = !full && !incomplete && unreadable.length === 0 && (plan?.unreadable.size ?? 0) === 0;
|
|
771
814
|
const bulk = new Map(listed.filter((item) => item.headers?.bulk).map((item) => [item.messageId, [bulkBox.externalId]]));
|
|
772
815
|
if (bulk.size)
|
|
@@ -782,7 +825,8 @@ const syncRound = async (source, store, { account, since, max = 200, maxBodyChar
|
|
|
782
825
|
state: complete ? "window" : "partial",
|
|
783
826
|
identity: account.mode === "imap" ? "message-id-or-uidvalidity-folder-uid" : "gmail-message-id",
|
|
784
827
|
};
|
|
785
|
-
|
|
828
|
+
// A refused folder says nothing of its mail, so the coverage an earlier run proved stays as it was.
|
|
829
|
+
if (!snapshot && saveCoverage && refused.size === 0)
|
|
786
830
|
await store.sync.setSyncState(key, "mail_coverage", JSON.stringify(coverage));
|
|
787
831
|
const tagging = tagger.outcome();
|
|
788
832
|
await settleRuleTags(store, accountId, rules, tagging);
|
|
@@ -802,6 +846,7 @@ const syncRound = async (source, store, { account, since, max = 200, maxBodyChar
|
|
|
802
846
|
...(attachments.length ? { attachments } : {}),
|
|
803
847
|
...(unreadable.length ? { unreadable } : {}),
|
|
804
848
|
...(skipped === undefined ? {} : { deletionsSkipped: skipped }),
|
|
849
|
+
...(refused.size ? { refusedFolders: [...refused] } : {}),
|
|
805
850
|
...(searches.size > 0 ? { pass: resumed.size > 0 ? "resumed" : "full" } : {}),
|
|
806
851
|
...(tagging.reused.length ? { tagsReused: tagging.reused } : {}),
|
|
807
852
|
...(tagging.skipped.length ? { tagsSkipped: tagging.skipped } : {}),
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { FileStamp } from "../resume.js";
|
|
2
2
|
import type { MailCriteria } from "../server-query.js";
|
|
3
|
-
import type
|
|
3
|
+
import { type MailSource } from "../source.js";
|
|
4
4
|
export type FakePerson = [name: string | null, address: string];
|
|
5
5
|
/** One message of a fake Gmail-like mailbox: its ids, envelope and the parts `rawOf` writes as RFC 5322. */
|
|
6
6
|
export interface FakeMail {
|
|
@@ -39,6 +39,8 @@ export interface FakeMailbox {
|
|
|
39
39
|
validity?: number;
|
|
40
40
|
/** Each answer of `search` and `list` ends in this failure. */
|
|
41
41
|
searchFails?: string;
|
|
42
|
+
/** Folders whose SEARCH the server refuses: `search` and `query` throw `SEARCH_REFUSED`. */
|
|
43
|
+
refusesSearch?: string[];
|
|
42
44
|
/** A refused header fetch fails the whole listing. */
|
|
43
45
|
headersFail?: boolean;
|
|
44
46
|
moveFails?: boolean;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { CliError } from "@wirecat/cli-base";
|
|
2
2
|
import { GMAIL_ALL_MAIL } from "../folders.js";
|
|
3
3
|
import { headersOf } from "../headers.js";
|
|
4
|
+
import { SEARCH_REFUSED } from "../source.js";
|
|
4
5
|
/** As IMAP SEARCH matches: a case-blind substring of the field, every part required. */
|
|
5
6
|
const matches = (m, criteria) => {
|
|
6
7
|
const has = (field, value) => field.toLowerCase().includes(value.toLowerCase());
|
|
@@ -73,9 +74,14 @@ export const fakeMailSource = (mailbox) => {
|
|
|
73
74
|
throw failure(`Gmail has no such mailbox: ${folder}`);
|
|
74
75
|
return mailbox.messages.filter((m) => (folder === trash() ? m.folder === "trash" : m.folder !== "trash") && !m.absentFrom?.includes(folder));
|
|
75
76
|
};
|
|
77
|
+
const refuse = (folder) => {
|
|
78
|
+
if (mailbox.refusesSearch?.includes(folder))
|
|
79
|
+
throw new CliError("provider_error", `the mail server refused to search ${folder}`, { reason: SEARCH_REFUSED });
|
|
80
|
+
};
|
|
76
81
|
const search = async (since, folder) => {
|
|
77
82
|
if (mailbox.searchFails)
|
|
78
83
|
throw failure(mailbox.searchFails);
|
|
84
|
+
refuse(folder);
|
|
79
85
|
const from = Date.UTC(since.getUTCFullYear(), since.getUTCMonth(), since.getUTCDate());
|
|
80
86
|
return {
|
|
81
87
|
validity: String(mailbox.validity ?? 12),
|
|
@@ -137,6 +143,7 @@ export const fakeMailSource = (mailbox) => {
|
|
|
137
143
|
count("search");
|
|
138
144
|
if (mailbox.searchFails)
|
|
139
145
|
throw failure(mailbox.searchFails);
|
|
146
|
+
refuse(folder);
|
|
140
147
|
mailbox.queried?.push({ criteria, folder });
|
|
141
148
|
return {
|
|
142
149
|
validity: String(mailbox.validity ?? 12),
|
|
@@ -180,14 +187,15 @@ export const fakeMailSource = (mailbox) => {
|
|
|
180
187
|
if (messageIds.includes(m.messageId))
|
|
181
188
|
m.labels = [...new Set([...(m.labels ?? []), ...labels])];
|
|
182
189
|
},
|
|
183
|
-
fetchRaw: async (items) => {
|
|
190
|
+
fetchRaw: async (items, options) => {
|
|
184
191
|
count("fetchRaw");
|
|
185
192
|
mailbox.read?.push(...items.map(({ uid }) => uid));
|
|
186
193
|
return items.map((item) => {
|
|
187
194
|
const m = mailbox.messages.find((each) => each.uid === item.uid);
|
|
188
195
|
if (m === undefined || mailbox.unreadable?.includes(item.uid) || failsNow(item.uid))
|
|
189
196
|
return failure(`email ${item.uid} was not read`);
|
|
190
|
-
|
|
197
|
+
const raw = rawOf(m);
|
|
198
|
+
return options?.bytes === undefined ? raw : raw.subarray(0, options.bytes);
|
|
191
199
|
});
|
|
192
200
|
},
|
|
193
201
|
};
|
|
@@ -38,7 +38,6 @@ export declare const meetingTools: ({
|
|
|
38
38
|
max_read_bytes?: undefined;
|
|
39
39
|
cursor?: undefined;
|
|
40
40
|
} | {
|
|
41
|
-
limit?: undefined;
|
|
42
41
|
event_id?: undefined;
|
|
43
42
|
series_id?: undefined;
|
|
44
43
|
page?: undefined;
|
|
@@ -54,11 +53,11 @@ export declare const meetingTools: ({
|
|
|
54
53
|
format?: undefined;
|
|
55
54
|
transcript_id?: undefined;
|
|
56
55
|
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;
|
|
62
61
|
event_id?: undefined;
|
|
63
62
|
series_id?: undefined;
|
|
64
63
|
page?: undefined;
|
|
@@ -76,11 +75,11 @@ export declare const meetingTools: ({
|
|
|
76
75
|
format?: undefined;
|
|
77
76
|
transcript_id?: undefined;
|
|
78
77
|
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;
|
|
84
83
|
event_id?: undefined;
|
|
85
84
|
series_id?: undefined;
|
|
86
85
|
page?: undefined;
|
|
@@ -102,6 +101,7 @@ export declare const meetingTools: ({
|
|
|
102
101
|
minimum: number;
|
|
103
102
|
};
|
|
104
103
|
query?: undefined;
|
|
104
|
+
limit?: undefined;
|
|
105
105
|
scan_limit?: undefined;
|
|
106
106
|
max_read_bytes?: undefined;
|
|
107
107
|
cursor?: undefined;
|
|
@@ -188,7 +188,6 @@ export declare const meetingTools: ({
|
|
|
188
188
|
max_read_bytes?: undefined;
|
|
189
189
|
cursor?: undefined;
|
|
190
190
|
} | {
|
|
191
|
-
limit?: undefined;
|
|
192
191
|
event_id?: undefined;
|
|
193
192
|
series_id?: undefined;
|
|
194
193
|
page?: undefined;
|
|
@@ -204,11 +203,11 @@ export declare const meetingTools: ({
|
|
|
204
203
|
format?: undefined;
|
|
205
204
|
transcript_id?: undefined;
|
|
206
205
|
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;
|
|
212
211
|
event_id?: undefined;
|
|
213
212
|
series_id?: undefined;
|
|
214
213
|
page?: undefined;
|
|
@@ -226,11 +225,11 @@ export declare const meetingTools: ({
|
|
|
226
225
|
format?: undefined;
|
|
227
226
|
transcript_id?: undefined;
|
|
228
227
|
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;
|
|
234
233
|
event_id?: undefined;
|
|
235
234
|
series_id?: undefined;
|
|
236
235
|
page?: undefined;
|
|
@@ -252,6 +251,7 @@ export declare const meetingTools: ({
|
|
|
252
251
|
minimum: number;
|
|
253
252
|
};
|
|
254
253
|
query?: undefined;
|
|
254
|
+
limit?: undefined;
|
|
255
255
|
scan_limit?: undefined;
|
|
256
256
|
max_read_bytes?: undefined;
|
|
257
257
|
cursor?: undefined;
|
|
@@ -338,7 +338,6 @@ export declare const meetingTools: ({
|
|
|
338
338
|
max_read_bytes?: undefined;
|
|
339
339
|
cursor?: undefined;
|
|
340
340
|
} | {
|
|
341
|
-
limit?: undefined;
|
|
342
341
|
event_id?: undefined;
|
|
343
342
|
series_id?: undefined;
|
|
344
343
|
page?: undefined;
|
|
@@ -354,11 +353,11 @@ export declare const meetingTools: ({
|
|
|
354
353
|
format?: undefined;
|
|
355
354
|
transcript_id?: undefined;
|
|
356
355
|
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;
|
|
362
361
|
event_id?: undefined;
|
|
363
362
|
series_id?: undefined;
|
|
364
363
|
page?: undefined;
|
|
@@ -376,11 +375,11 @@ export declare const meetingTools: ({
|
|
|
376
375
|
format?: undefined;
|
|
377
376
|
transcript_id?: undefined;
|
|
378
377
|
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;
|
|
384
383
|
event_id?: undefined;
|
|
385
384
|
series_id?: undefined;
|
|
386
385
|
page?: undefined;
|
|
@@ -402,6 +401,7 @@ export declare const meetingTools: ({
|
|
|
402
401
|
minimum: number;
|
|
403
402
|
};
|
|
404
403
|
query?: undefined;
|
|
404
|
+
limit?: undefined;
|
|
405
405
|
scan_limit?: undefined;
|
|
406
406
|
max_read_bytes?: undefined;
|
|
407
407
|
cursor?: undefined;
|
|
@@ -488,7 +488,6 @@ export declare const meetingTools: ({
|
|
|
488
488
|
max_read_bytes?: undefined;
|
|
489
489
|
cursor?: undefined;
|
|
490
490
|
} | {
|
|
491
|
-
limit?: undefined;
|
|
492
491
|
event_id?: undefined;
|
|
493
492
|
series_id?: undefined;
|
|
494
493
|
page?: undefined;
|
|
@@ -504,11 +503,11 @@ export declare const meetingTools: ({
|
|
|
504
503
|
format?: undefined;
|
|
505
504
|
transcript_id?: undefined;
|
|
506
505
|
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;
|
|
512
511
|
event_id?: undefined;
|
|
513
512
|
series_id?: undefined;
|
|
514
513
|
page?: undefined;
|
|
@@ -526,11 +525,11 @@ export declare const meetingTools: ({
|
|
|
526
525
|
format?: undefined;
|
|
527
526
|
transcript_id?: undefined;
|
|
528
527
|
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;
|
|
534
533
|
event_id?: undefined;
|
|
535
534
|
series_id?: undefined;
|
|
536
535
|
page?: undefined;
|
|
@@ -552,6 +551,7 @@ export declare const meetingTools: ({
|
|
|
552
551
|
minimum: number;
|
|
553
552
|
};
|
|
554
553
|
query?: undefined;
|
|
554
|
+
limit?: undefined;
|
|
555
555
|
scan_limit?: undefined;
|
|
556
556
|
max_read_bytes?: undefined;
|
|
557
557
|
cursor?: undefined;
|
|
@@ -638,7 +638,6 @@ export declare const meetingTools: ({
|
|
|
638
638
|
max_read_bytes?: undefined;
|
|
639
639
|
cursor?: undefined;
|
|
640
640
|
} | {
|
|
641
|
-
limit?: undefined;
|
|
642
641
|
event_id?: undefined;
|
|
643
642
|
series_id?: undefined;
|
|
644
643
|
page?: undefined;
|
|
@@ -654,11 +653,11 @@ export declare const meetingTools: ({
|
|
|
654
653
|
format?: undefined;
|
|
655
654
|
transcript_id?: undefined;
|
|
656
655
|
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;
|
|
662
661
|
event_id?: undefined;
|
|
663
662
|
series_id?: undefined;
|
|
664
663
|
page?: undefined;
|
|
@@ -676,11 +675,11 @@ export declare const meetingTools: ({
|
|
|
676
675
|
format?: undefined;
|
|
677
676
|
transcript_id?: undefined;
|
|
678
677
|
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;
|
|
684
683
|
event_id?: undefined;
|
|
685
684
|
series_id?: undefined;
|
|
686
685
|
page?: undefined;
|
|
@@ -702,6 +701,7 @@ export declare const meetingTools: ({
|
|
|
702
701
|
minimum: number;
|
|
703
702
|
};
|
|
704
703
|
query?: undefined;
|
|
704
|
+
limit?: undefined;
|
|
705
705
|
scan_limit?: undefined;
|
|
706
706
|
max_read_bytes?: undefined;
|
|
707
707
|
cursor?: undefined;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { CliError } from "@wirecat/cli-base";
|
|
2
|
+
import type { OAuthClient } from "./provider.js";
|
|
3
|
+
export interface ClientFileOptions {
|
|
4
|
+
platform?: NodeJS.Platform;
|
|
5
|
+
/** Skip the owner-only check, for a file the package ships. Default: the file must be private to its owner. */
|
|
6
|
+
shipped?: boolean;
|
|
7
|
+
/** Thrown when the file cannot be read or has the wrong shape. */
|
|
8
|
+
invalid?: CliError;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Reads a Google Desktop OAuth client file (`{ "installed": { client_id, client_secret? } }`, the JSON Google's console
|
|
12
|
+
* downloads). Refuses a file other users can read, and never puts the file's contents in an error.
|
|
13
|
+
*/
|
|
14
|
+
export declare const readClientFile: (location: URL | string, options?: ClientFileOptions) => OAuthClient;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
import { CliError } from "@wirecat/cli-base";
|
|
3
|
+
import { privateFiles } from "../cli/messenger/private-files.js";
|
|
4
|
+
// No schema library: the keeper-process test bundles this module without a node_modules next to it.
|
|
5
|
+
/**
|
|
6
|
+
* Reads a Google Desktop OAuth client file (`{ "installed": { client_id, client_secret? } }`, the JSON Google's console
|
|
7
|
+
* downloads). Refuses a file other users can read, and never puts the file's contents in an error.
|
|
8
|
+
*/
|
|
9
|
+
export const readClientFile = (location, options = {}) => {
|
|
10
|
+
if (!options.shipped && typeof location === "string") {
|
|
11
|
+
const mode = privateFiles({ files: [location], dirs: [] }, options.platform);
|
|
12
|
+
if (mode.checked && !mode.ok)
|
|
13
|
+
throw new CliError("configuration_error", `the client file can be read by other users of this computer; run chmod 600 ${location} and try again`, { reason: "sign-in.client-file-open" });
|
|
14
|
+
}
|
|
15
|
+
try {
|
|
16
|
+
const { installed } = JSON.parse(readFileSync(location, "utf8"));
|
|
17
|
+
const { client_id: clientId, client_secret: clientSecret } = installed;
|
|
18
|
+
if (typeof clientId !== "string" || !clientId)
|
|
19
|
+
throw new TypeError("client_id");
|
|
20
|
+
if (clientSecret !== undefined && typeof clientSecret !== "string")
|
|
21
|
+
throw new TypeError("client_secret");
|
|
22
|
+
return { clientId, ...(clientSecret ? { clientSecret } : {}) };
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
throw (options.invalid ??
|
|
26
|
+
new CliError("configuration_error", "could not read a Desktop app OAuth client JSON from the client file; its contents were not logged", { reason: "sign-in.client-file-invalid" }));
|
|
27
|
+
}
|
|
28
|
+
};
|
package/dist/oauth/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { type Authorization, type AuthorizeOptions, authorize } from "./authorize.js";
|
|
2
|
+
export { type ClientFileOptions, readClientFile } from "./client-file.js";
|
|
2
3
|
export { type SignInOptions, type TokenKeeper, type TokenKeeperOptions, type TokensOptions, tokenKeeper, } from "./keeper.js";
|
|
3
4
|
export type { ExchangeContext, OAuthClient, OAuthProvider, RequestContext, TokenSet } from "./provider.js";
|
|
4
5
|
export { requestTokens, revokeToken, TOKEN_LOG_ALLOW, TOKEN_LOG_EVENT } from "./requests.js";
|
package/dist/oauth/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { authorize } from "./authorize.js";
|
|
2
|
+
export { readClientFile } from "./client-file.js";
|
|
2
3
|
export { tokenKeeper, } from "./keeper.js";
|
|
3
4
|
export { requestTokens, revokeToken, TOKEN_LOG_ALLOW, TOKEN_LOG_EVENT } from "./requests.js";
|
|
4
5
|
export { credentialStorage, driveSessionCodec, oauthAccount, standardCodec, zoomTokenCodec, } from "./storage.js";
|
|
@@ -401,9 +401,10 @@ export interface HistoryBatch {
|
|
|
401
401
|
/**
|
|
402
402
|
* Takes one pushed batch. The CLI's own handler resolves `true` once the batch is in the local store and `false` when it
|
|
403
403
|
* could not be written, so a messenger that pushes history once can keep a batch until it is saved; a handler that
|
|
404
|
-
* stores nothing returns nothing.
|
|
404
|
+
* stores nothing returns nothing. A command's own handler, called through the store, is handed that answer as `saved`,
|
|
405
|
+
* so what it reports as kept is what reached the store.
|
|
405
406
|
*/
|
|
406
|
-
export type HistoryBatchHandler = (batch: HistoryBatch) => void | Promise<boolean>;
|
|
407
|
+
export type HistoryBatchHandler = (batch: HistoryBatch, saved?: Promise<boolean>) => void | Promise<boolean>;
|
|
407
408
|
/** For a messenger that pushes its history to the client instead of answering for it (`Messenger.history: "store"`). */
|
|
408
409
|
export interface PushedHistory {
|
|
409
410
|
/** Chats, people and past messages as the messenger pushes them, until `signal` aborts. */
|
package/dist/resolve.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
import type { Chat, Contact, Id } from "./domain/models.js";
|
|
1
|
+
import type { Chat, Contact, Id, Provider } from "./domain/models.js";
|
|
2
2
|
/** The part of a store that `pickPerson` reads. */
|
|
3
3
|
export interface PeopleLookup {
|
|
4
|
+
/** Whose identities these are; a `contact:` reference of another provider is refused when it is set. */
|
|
5
|
+
provider?: Provider;
|
|
4
6
|
get(id: Id): Contact | undefined;
|
|
5
7
|
/** Everyone known, in any order. */
|
|
6
8
|
all(): Contact[];
|
package/dist/resolve.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { CliError, singleLine } from "@wirecat/cli-base";
|
|
2
|
+
import { contactReferenceOf } from "./domain/ref-arguments.js";
|
|
2
3
|
/** Shaped like a Telegram or MAX id. Another messenger's ids may be any string, so a miss here is not "not an id". */
|
|
3
4
|
export const isId = (reference) => /^-?\d+$/.test(reference.trim());
|
|
4
5
|
/**
|
|
@@ -31,6 +32,13 @@ export const pickChat = (reference, chats) => {
|
|
|
31
32
|
*/
|
|
32
33
|
export const pickPerson = (reference, people) => {
|
|
33
34
|
const trimmed = reference.trim();
|
|
35
|
+
const contact = contactReferenceOf(trimmed, people.provider);
|
|
36
|
+
if (contact !== undefined) {
|
|
37
|
+
const named = people.get(contact);
|
|
38
|
+
if (named)
|
|
39
|
+
return named;
|
|
40
|
+
throw new CliError("not_found", `no person ${contact} in what this account has seen`);
|
|
41
|
+
}
|
|
34
42
|
const known = people.get(trimmed);
|
|
35
43
|
if (known)
|
|
36
44
|
return known;
|
|
@@ -7,7 +7,11 @@ export type TaskAmount = {
|
|
|
7
7
|
value: number;
|
|
8
8
|
currency: string | null;
|
|
9
9
|
};
|
|
10
|
-
/**
|
|
10
|
+
/**
|
|
11
|
+
* A bare number is not an amount: `верни 3000 за бензин` has none, so a reminder about it compares as missing.
|
|
12
|
+
* Takes the text as written; it is lower-cased here.
|
|
13
|
+
*/
|
|
14
|
+
export declare const amountsOf: (text: string) => TaskAmount[];
|
|
11
15
|
export declare const amountOf: (text: string) => TaskAmount | null;
|
|
12
16
|
/** The creator's calendar date in the machine's time zone, as a day count: "tomorrow" late at night is local. */
|
|
13
17
|
export declare const dayOf: (ms: number) => number;
|
|
@@ -10,18 +10,36 @@ const CURRENCY = [
|
|
|
10
10
|
[/^(\$|usd|долл.*|dollars?)$/u, "USD"],
|
|
11
11
|
];
|
|
12
12
|
const currencyOf = (word) => word ? (CURRENCY.find(([pattern]) => pattern.test(word))?.[1] ?? null) : null;
|
|
13
|
-
const
|
|
14
|
-
/**
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
13
|
+
const SEPARATORS = String.raw `[ \u00a0\u2009\u202f.,]`;
|
|
14
|
+
/**
|
|
15
|
+
* Groups of three after a space (also no-break, thin, narrow no-break), a dot or a comma (`50 000`, `1.200`,
|
|
16
|
+
* `$1,200`) are one number, with an optional one or two digit decimal after (`5 000.50`). A lone `1,5` is a decimal.
|
|
17
|
+
*/
|
|
18
|
+
const NUMBER = String.raw `\d{1,3}(?:${SEPARATORS}\d{3})+(?:[.,]\d{1,2})?|\d+(?:[.,]\d+)?`;
|
|
19
|
+
const AMOUNT = new RegExp(String.raw `(?<![\p{L}\p{N}])([$€₽])?\s?(${NUMBER})(?:([кk])(?![\p{L}])|\s?(тыс\.?|тысяч\p{L}*))?(?![\p{N}])\s?(₽|руб\p{L}*\.?|р\.|р(?![\p{L}])|rub|eur|евро|€|\$|usd|долл\p{L}*|dollars?|euros?)?(?![\p{L}])`, "gu");
|
|
20
|
+
const GROUPED = new RegExp(String.raw `^(\d{1,3}(?:${SEPARATORS}\d{3})+)([.,]\d{1,2})?$`, "u");
|
|
21
|
+
const amountValue = (number, thousands) => {
|
|
22
|
+
const grouped = GROUPED.exec(number);
|
|
23
|
+
const plain = grouped
|
|
24
|
+
? `${(grouped[1] ?? "").replace(new RegExp(SEPARATORS, "gu"), "")}${(grouped[2] ?? "").replace(",", ".")}`
|
|
25
|
+
: number.replace(",", ".");
|
|
26
|
+
return Math.round(Number(plain) * (thousands ? 1000 : 1) * 100) / 100;
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* A bare number is not an amount: `верни 3000 за бензин` has none, so a reminder about it compares as missing.
|
|
30
|
+
* Takes the text as written; it is lower-cased here.
|
|
31
|
+
*/
|
|
32
|
+
export const amountsOf = (text) => {
|
|
33
|
+
const found = [];
|
|
34
|
+
for (const [, before, number = "", short, long, after] of text.toLowerCase().matchAll(AMOUNT)) {
|
|
35
|
+
const thousands = (short ?? long) !== undefined;
|
|
36
|
+
if (!before && !after && !thousands)
|
|
19
37
|
continue;
|
|
20
|
-
|
|
21
|
-
return { value, currency: currencyOf(before ?? after?.replace(/\.$/u, "")) };
|
|
38
|
+
found.push({ value: amountValue(number, thousands), currency: currencyOf(before ?? after?.replace(/\.$/u, "")) });
|
|
22
39
|
}
|
|
23
|
-
return
|
|
40
|
+
return found;
|
|
24
41
|
};
|
|
42
|
+
export const amountOf = (text) => amountsOf(text)[0] ?? null;
|
|
25
43
|
const RU_WEEKDAYS = ["воскресен", "понедельник", "вторник", "сред", "четверг", "пятниц", "суббот"];
|
|
26
44
|
const EN_WEEKDAYS = ["sunday", "monday", "tuesday", "wednesday", "thursday", "friday", "saturday"];
|
|
27
45
|
const ES_WEEKDAYS = ["domingo", "lunes", "martes", "miercoles", "jueves", "viernes", "sabado"];
|
|
@@ -4,6 +4,11 @@ import { agenda } from "../entities/agenda.js";
|
|
|
4
4
|
import { type ChatActivity, type TaskDetails } from "../store/store.js";
|
|
5
5
|
import { type ChatCoverage } from "./chat-coverage.js";
|
|
6
6
|
import type { ServiceDeps } from "./deps.js";
|
|
7
|
+
/** How long a chat must be silent before `tasks agenda` lists it, per side. */
|
|
8
|
+
export declare const AGENDA_DEFAULTS: {
|
|
9
|
+
readonly unanswered: 86400000;
|
|
10
|
+
readonly waiting: number;
|
|
11
|
+
};
|
|
7
12
|
export interface AgendaOptions {
|
|
8
13
|
/** ms: a task due within this is listed. */
|
|
9
14
|
dueWithin?: number;
|
package/dist/services/agenda.js
CHANGED
|
@@ -8,6 +8,8 @@ import { CHAT_KINDS } from "./chats.js";
|
|
|
8
8
|
import { taskAccount } from "./task-rules.js";
|
|
9
9
|
import { taskTagFilters } from "./task-tag-filters.js";
|
|
10
10
|
const DAY = 86_400_000;
|
|
11
|
+
/** How long a chat must be silent before `tasks agenda` lists it, per side. */
|
|
12
|
+
export const AGENDA_DEFAULTS = { unanswered: DAY, waiting: 7 * DAY };
|
|
11
13
|
const CLAIMS = ["none", "mine", "others", "any"];
|
|
12
14
|
const TASK_FIELDS = new Set(["tag", "category", "claimed"]);
|
|
13
15
|
export const AGENDA_QUERY = {
|
|
@@ -35,7 +37,7 @@ export const AGENDA_QUERY = {
|
|
|
35
37
|
defaults: ["chat_kind:(dialog OR group)", "claimed:(none OR mine)"],
|
|
36
38
|
};
|
|
37
39
|
export const agendaService = (deps, now = Date.now) => ({
|
|
38
|
-
show: async ({ dueWithin = DAY, waiting =
|
|
40
|
+
show: async ({ dueWithin = DAY, waiting = AGENDA_DEFAULTS.waiting, unanswered = AGENDA_DEFAULTS.unanswered, within = 30 * DAY, query, holder, } = {}) => {
|
|
39
41
|
const [store, account] = [await deps.store(), await deps.account()];
|
|
40
42
|
const at = now();
|
|
41
43
|
const parts = query ? split(query) : { tasks: undefined, chats: undefined };
|
package/dist/services/deps.d.ts
CHANGED
|
@@ -70,8 +70,6 @@ export declare const storeIfOpen: (deps: ServiceDeps) => Promise<{
|
|
|
70
70
|
export declare const fromStore: (deps: Pick<ServiceDeps, "offline" | "reads">) => boolean;
|
|
71
71
|
/** What a store-mode read answers for a chat the store holds nothing of. */
|
|
72
72
|
export declare const nothingStored: (messenger: MessengerTraits) => string;
|
|
73
|
-
/** Where a store-mode messenger's history comes from, for what it cannot do. */
|
|
74
|
-
export declare const PUSHED = "this messenger's history is read from the local store";
|
|
75
73
|
export declare const OFFLINE = "--offline answers only from what is kept locally: `chats list|show`, `messages list|show|context|download`, `contacts list|show` and `review`";
|
|
76
74
|
/** Over a connection that is already open — an MCP session holds one for minutes. */
|
|
77
75
|
export declare const onlineDeps: (messenger: ServiceMessenger, adapter: MessengerAdapter, guard: SendGuard, where?: {
|
package/dist/services/deps.js
CHANGED
|
@@ -53,8 +53,6 @@ export const storeIfOpen = async (deps) => {
|
|
|
53
53
|
export const fromStore = (deps) => deps.offline || deps.reads === "store";
|
|
54
54
|
/** What a store-mode read answers for a chat the store holds nothing of. */
|
|
55
55
|
export const nothingStored = (messenger) => `nothing stored for this chat yet — keep \`${typedCommand(messenger.app.command, "serve")}\` running`;
|
|
56
|
-
/** Where a store-mode messenger's history comes from, for what it cannot do. */
|
|
57
|
-
export const PUSHED = "this messenger's history is read from the local store";
|
|
58
56
|
export const OFFLINE = "--offline answers only from what is kept locally: `chats list|show`, `messages list|show|context|download`, `contacts list|show` and `review`";
|
|
59
57
|
/** Over a connection that is already open — an MCP session holds one for minutes. */
|
|
60
58
|
export const onlineDeps = (messenger, adapter, guard, where = {}) => ({
|
|
@@ -37,7 +37,7 @@ export const documentIngestion = (store, options) => {
|
|
|
37
37
|
for (let batch = 0;; batch++) {
|
|
38
38
|
const memories = await store.memories.list({ subject: ref, status, limit: 500 });
|
|
39
39
|
for (const memory of memories)
|
|
40
|
-
await store.memories.markStale(memory.ref);
|
|
40
|
+
await store.memories.markStale(memory.ref, "owner");
|
|
41
41
|
if (memories.length < 500)
|
|
42
42
|
break;
|
|
43
43
|
if (batch >= 20)
|