@wirecat/cli-core 0.563.0 → 0.565.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 +125 -0
- package/dist/calendar/busy.d.ts +10 -10
- package/dist/calendar/busy.js +9 -9
- package/dist/calendar/cli/answers.d.ts +7 -8
- package/dist/calendar/cli/answers.js +4 -5
- package/dist/calendar/cli/bodies.d.ts +33 -0
- package/dist/calendar/cli/bodies.js +52 -0
- package/dist/calendar/cli/files.d.ts +8 -0
- package/dist/calendar/cli/files.js +41 -0
- package/dist/calendar/cli/index.d.ts +58 -51
- package/dist/calendar/cli/index.js +311 -284
- package/dist/calendar/cli/remind.d.ts +2 -11
- package/dist/calendar/cli/remind.js +81 -81
- package/dist/calendar/cli/search-all.d.ts +3 -8
- package/dist/calendar/cli/search-all.js +47 -42
- package/dist/calendar/mcp/index.d.ts +1 -1
- package/dist/calendar/prepare.d.ts +1 -1
- package/dist/calendar/testing/answers.d.ts +27 -5
- package/dist/calendar/testing/answers.js +88 -17
- package/dist/calendar/testing/writer.d.ts +1 -0
- package/dist/calendar/testing/writer.js +6 -0
- package/dist/calendar/writer.d.ts +6 -1
- package/dist/calendar/writes.d.ts +3 -1
- package/dist/calendar/writes.js +42 -20
- package/dist/cli/config-command.js +1 -1
- package/dist/cli/config-issues.d.ts +3 -1
- package/dist/cli/config-issues.js +2 -2
- package/dist/cli/contract-evidence.d.ts +1 -1
- package/dist/cli/early-refusal.d.ts +2 -1
- package/dist/cli/early-refusal.js +4 -2
- package/dist/cli/entry.d.ts +6 -2
- package/dist/cli/entry.js +4 -1
- package/dist/cli/envelope.d.ts +2 -2
- package/dist/cli/index.d.ts +1 -0
- package/dist/cli/index.js +1 -0
- package/dist/cli/messenger/archive-commands.js +17 -0
- package/dist/cli/messenger/catch-up-answers.d.ts +5 -0
- package/dist/cli/messenger/catch-up-answers.js +3 -0
- package/dist/cli/messenger/search-answers.d.ts +1 -0
- package/dist/cli/messenger/search-answers.js +1 -1
- package/dist/cli/messenger/stats-answers.d.ts +3 -3
- package/dist/cli/messenger/stats-answers.js +21 -9
- package/dist/cli/messenger/store-maintenance-command.d.ts +1 -1
- package/dist/cli/messenger/tasks-command.js +35 -14
- package/dist/cli/permission-keys.d.ts +3 -1
- package/dist/cli/permission-keys.js +2 -1
- package/dist/cli/preview.d.ts +12 -0
- package/dist/cli/preview.js +8 -1
- package/dist/cli/settings.d.ts +2 -0
- package/dist/cli/settings.js +8 -1
- package/dist/conversations/mail-text.d.ts +6 -0
- package/dist/conversations/mail-text.js +73 -0
- package/dist/domain/calendar.d.ts +2 -0
- package/dist/domain/calendar.js +6 -0
- package/dist/entities/chat-stats.d.ts +16 -2
- package/dist/entities/chat-stats.js +18 -3
- package/dist/entities/index.d.ts +50 -802
- package/dist/entities/index.js +23 -16
- package/dist/entities/mail-counts.d.ts +15 -0
- package/dist/entities/mail-counts.js +16 -0
- package/dist/entities/meeting.d.ts +1 -1
- package/dist/entities/meeting.js +1 -1
- package/dist/entities/store-records.d.ts +8 -0
- package/dist/entities/store-records.js +8 -0
- package/dist/errors/reasons.js +19 -1
- package/dist/mail/cli/index.d.ts +5 -0
- package/dist/mail/cli/index.js +27 -3
- package/dist/mail/cli/review.js +11 -4
- package/dist/mail/index.d.ts +2 -0
- package/dist/mail/index.js +2 -0
- package/dist/mail/stats.d.ts +50 -0
- package/dist/mail/stats.js +60 -0
- package/dist/mail/whole.d.ts +4 -4
- package/dist/mail/whole.js +4 -3
- package/dist/mcp/meeting-preparation.d.ts +1 -1
- package/dist/mcp/meeting-project-candidates.d.ts +1 -1
- package/dist/mcp/meeting-series-inventory.d.ts +1 -1
- package/dist/meetings/index.d.ts +2 -2
- package/dist/meetings/index.js +2 -2
- package/dist/meetings/mcp/index.d.ts +15 -15
- package/dist/meetings/mcp/passage.d.ts +1 -1
- package/dist/meetings/mcp/project-evidence.d.ts +1 -1
- package/dist/meetings/mcp/search.d.ts +1 -1
- package/dist/meetings/read-answers.d.ts +22 -1
- package/dist/meetings/read-answers.js +38 -0
- package/dist/meetings/stats.d.ts +44 -0
- package/dist/meetings/stats.js +77 -7
- package/dist/search/lucene/registry.js +2 -1
- package/dist/search/question-plan.d.ts +16 -0
- package/dist/search/question-plan.js +34 -0
- package/dist/services/events-search.d.ts +5 -1
- package/dist/services/events-search.js +10 -4
- package/dist/services/index.d.ts +1 -1
- package/dist/services/index.js +1 -1
- package/dist/services/meeting-stats.d.ts +12 -1
- package/dist/services/meeting-stats.js +12 -0
- package/dist/services/messages-discovery.d.ts +1 -5
- package/dist/services/messages-discovery.js +5 -18
- package/dist/services/messages-meaning.js +25 -3
- package/dist/services/messages.js +4 -3
- package/dist/services/metadata.d.ts +1 -1
- package/dist/services/notes-search.d.ts +5 -1
- package/dist/services/notes-search.js +16 -5
- package/dist/services/proposals/ids.d.ts +2 -2
- package/dist/services/proposals/ids.js +5 -3
- package/dist/services/proposals/kinds/findings.d.ts +1 -1
- package/dist/services/proposals/kinds/findings.js +1 -1
- package/dist/services/proposals/kinds/meeting-findings.d.ts +7 -0
- package/dist/services/proposals/kinds/meeting-findings.js +73 -0
- package/dist/services/proposals/kinds/task-close.d.ts +7 -0
- package/dist/services/proposals/kinds/task-close.js +76 -0
- package/dist/services/proposals/registry.js +4 -0
- package/dist/services/search-all.d.ts +5 -0
- package/dist/services/search-all.js +47 -14
- package/dist/services/task-stats.d.ts +41 -0
- package/dist/services/task-stats.js +126 -0
- package/dist/services/tasks.d.ts +17 -4
- package/dist/services/tasks.js +31 -14
- package/dist/store/chats.d.ts +3 -1
- package/dist/store/chats.js +6 -0
- package/dist/store/decisions.d.ts +4 -2
- package/dist/store/decisions.js +5 -3
- package/dist/store/exports.d.ts +1 -1
- package/dist/store/exports.js +1 -1
- package/dist/store/index.d.ts +2 -1
- package/dist/store/index.js +1 -1
- package/dist/store/sqlite/completeness.d.ts +17 -0
- package/dist/store/sqlite/completeness.js +49 -13
- package/dist/store/sqlite/lucene-fields.js +2 -0
- package/dist/store/sqlite/lucene-groups.d.ts +15 -0
- package/dist/store/sqlite/lucene-groups.js +21 -0
- package/dist/store/sqlite/lucene.d.ts +2 -9
- package/dist/store/sqlite/lucene.js +1 -12
- package/dist/store/sqlite/meeting-stats.d.ts +2 -0
- package/dist/store/sqlite/meeting-stats.js +27 -1
- package/dist/store/sqlite/retention.js +2 -7
- package/dist/store/sqlite/task-board.js +2 -0
- package/dist/store/sqlite/task-stats.d.ts +32 -0
- package/dist/store/sqlite/task-stats.js +45 -0
- package/dist/store/sqlite/tasks.d.ts +2 -1
- package/dist/store/sqlite/tasks.js +2 -0
- package/package.json +3 -3
- package/parity.json +13 -1
package/dist/entities/index.js
CHANGED
|
@@ -44,9 +44,10 @@ import { joinRequest } from "./join-request.js";
|
|
|
44
44
|
import { organization, project, reminder } from "./knowledge-lists.js";
|
|
45
45
|
import { botAdmin, botMenuEntry, botProfile, botSeenChat, botTemplate, botWebhook, callRecord, scheduledJob, stickerInventory, topicIcon, } from "./list-results.js";
|
|
46
46
|
import { messageEvent, serveSummary, watchedMessage, watchItem } from "./listener.js";
|
|
47
|
+
import { mailCounts } from "./mail-counts.js";
|
|
47
48
|
import { mailFindings } from "./mail-findings.js";
|
|
48
49
|
import { mediaArchive, mediaArchiveCheck, mediaArchiveMove, mediaArchiveTimer } from "./media-archive.js";
|
|
49
|
-
import { event, meeting, meetingDetails, meetingHit, meetingLink, meetingParticipants, meetingPassage, meetingProjectEvidence, meetingReview, meetingSpeaker, meetingStats, meetingSummary, meetingTranscript, } from "./meeting.js";
|
|
50
|
+
import { event, meeting, meetingCounts, meetingDetails, meetingHit, meetingLink, meetingParticipants, meetingPassage, meetingProjectEvidence, meetingReview, meetingSpeaker, meetingStats, meetingSummary, meetingTranscript, } from "./meeting.js";
|
|
50
51
|
import { meetingEvidence, meetingPersonContext } from "./meeting-evidence.js";
|
|
51
52
|
import { meetingFindings } from "./meeting-findings.js";
|
|
52
53
|
import { meetingPreparation } from "./meeting-preparation.js";
|
|
@@ -83,7 +84,7 @@ import { retention } from "./retention.js";
|
|
|
83
84
|
import { savedSearch, searchHistoryClear } from "./saved-search.js";
|
|
84
85
|
import { sendAttempt } from "./send-attempt.js";
|
|
85
86
|
import { storeBackup, storeCheck, storeCopyRemoval, storeDecrypt, storeInfo, storeMigration, storeReindex, storeRepair, storeReset, storeRestore, } from "./store-maintenance.js";
|
|
86
|
-
import { storeChatStatus, storeClear, storeExport, storeGapPlan, storeGapRepair, storeJobCancel, storeJobClear, storeJobDetails, storeJobRetry, syncProgress, } from "./store-records.js";
|
|
87
|
+
import { chatCoverage, storeChatStatus, storeClear, storeExport, storeGapPlan, storeGapRepair, storeJobCancel, storeJobClear, storeJobDetails, storeJobRetry, syncProgress, } from "./store-records.js";
|
|
87
88
|
import { storeTable } from "./store-table.js";
|
|
88
89
|
import { automaticTags, tagChange } from "./tag-change.js";
|
|
89
90
|
import { tagging } from "./tagging.js";
|
|
@@ -96,7 +97,7 @@ import { topic } from "./topic.js";
|
|
|
96
97
|
* subset of its fields, never a renamed one. Commands move onto these one by one; until then, a schema
|
|
97
98
|
* is the target, not a description of today's output.
|
|
98
99
|
*/
|
|
99
|
-
export { account, accountChange, accountPrivacy, accountPrivacyChange, accountProfile, accountSession, adminReport, agenda, analysisConsent, analysisConsentRevocation, attachment, attachmentBytes, attachmentExtraction, attachmentTextChange, automaticTags, botAdmin, botMenuEntry, botProfile, botSeenChat, botTemplate, botWebhook, cachedChatMetadata, callRecord, chart, chat, chatAdminChange, chatArchive, chatEvent, chatFolderChange, chatFolderOrder, chatFolderRemoval, chatGroupChange, chatInspection, chatInvite, chatInviteChange, chatMembersChange, chatMembersFetch, chatMetadata, chatMetadataRefresh, chatModeration, chatMuting, chatPin, chatRead, chatRemoval, chatRequestChange, chatRules, chatSender, chatStats, chatTracking, chatUnread, contact, contactActivity, contactAlias, contactCheck, contactContext, contactImport, contactLookup, contactNote, contactNoteRemoval, contactPreparation, contactStateChange, contactSync, contactUpdate, conversation, conversationBatch, conversationBatchStatus, conversationBuildResult, conversationChange, conversationDetails, conversationEmbedding, conversationEmbeddingStatus, conversationHit, conversationPreparation, conversationReadiness, counterRefresh, counters, document, documentLink, endedAccountSessions, evidence, evidencePacket, fact, folder, hit, identity, imageEmbedding, inviteLink, job, joinRequest, linkedPerson, mediaArchive, mediaArchiveCheck, mediaArchiveMove, mediaArchiveTimer, meeting, meetingProjectCandidates, meetingSeriesInventory, member, memory, mention, mentionDecision, mentionDetails, mentionDomain, mentionRebuild, message, messageContext, messageCounts, messageDeletion, messageDownload, messageEvent, messageLink, messageLinks, messagePin, messageStar, messageSync, messageTranscript, messageWrite, model, modelKey, note, officialStats, organization, person, place, poll, pollChange, pollVote, project, ranking, reaction, reactionChange, recipient, recipientAdded, recipientChange, recipientOff, recipientRemoved, recordedRun, reference, relationship, reminder, removedModelKey, responseTimes, retention, runDetails, runHit, runLocation, savedSearch, scheduledJob, searchHistoryClear, sendAttempt, serveSummary, stickerInventory, storeBackup, storeChatStatus, storeCheck, storeClear, storeCopyRemoval, storeDecrypt, storedModelKey, storeExport, storeGapPlan, storeGapRepair, storeInfo, storeJobCancel, storeJobClear, storeJobDetails, storeJobRetry, storeMigration, storeReindex, storeRepair, storeReset, storeRestore, storeTable, tagChange, tagging, task, taskAnalysis, taskAnalysisMark, taskCard, taskCategories, taskClosed, taskCreated, taskLinks, taskMerge, taskPair, taskScan, taskSimilar, taskStats, taskUnmerge, topic, topicIcon, trackedChat, trackedChatHistory, waitingChats, watchedMessage, watchItem, };
|
|
100
|
+
export { account, accountChange, accountPrivacy, accountPrivacyChange, accountProfile, accountSession, adminReport, agenda, analysisConsent, analysisConsentRevocation, attachment, attachmentBytes, attachmentExtraction, attachmentTextChange, automaticTags, botAdmin, botMenuEntry, botProfile, botSeenChat, botTemplate, botWebhook, cachedChatMetadata, callRecord, chart, chat, chatAdminChange, chatArchive, chatCoverage, chatEvent, chatFolderChange, chatFolderOrder, chatFolderRemoval, chatGroupChange, chatInspection, chatInvite, chatInviteChange, chatMembersChange, chatMembersFetch, chatMetadata, chatMetadataRefresh, chatModeration, chatMuting, chatPin, chatRead, chatRemoval, chatRequestChange, chatRules, chatSender, chatStats, chatTracking, chatUnread, contact, contactActivity, contactAlias, contactCheck, contactContext, contactImport, contactLookup, contactNote, contactNoteRemoval, contactPreparation, contactStateChange, contactSync, contactUpdate, conversation, conversationBatch, conversationBatchStatus, conversationBuildResult, conversationChange, conversationDetails, conversationEmbedding, conversationEmbeddingStatus, conversationHit, conversationPreparation, conversationReadiness, counterRefresh, counters, document, documentLink, endedAccountSessions, evidence, evidencePacket, fact, folder, hit, identity, imageEmbedding, inviteLink, job, joinRequest, linkedPerson, mailCounts, mediaArchive, mediaArchiveCheck, mediaArchiveMove, mediaArchiveTimer, meeting, meetingProjectCandidates, meetingSeriesInventory, member, memory, mention, mentionDecision, mentionDetails, mentionDomain, mentionRebuild, message, messageContext, messageCounts, messageDeletion, messageDownload, messageEvent, messageLink, messageLinks, messagePin, messageStar, messageSync, messageTranscript, messageWrite, model, modelKey, note, officialStats, organization, person, place, poll, pollChange, pollVote, project, ranking, reaction, reactionChange, recipient, recipientAdded, recipientChange, recipientOff, recipientRemoved, recordedRun, reference, relationship, reminder, removedModelKey, responseTimes, retention, runDetails, runHit, runLocation, savedSearch, scheduledJob, searchHistoryClear, sendAttempt, serveSummary, stickerInventory, storeBackup, storeChatStatus, storeCheck, storeClear, storeCopyRemoval, storeDecrypt, storedModelKey, storeExport, storeGapPlan, storeGapRepair, storeInfo, storeJobCancel, storeJobClear, storeJobDetails, storeJobRetry, storeMigration, storeReindex, storeRepair, storeReset, storeRestore, storeTable, tagChange, tagging, task, taskAnalysis, taskAnalysisMark, taskCard, taskCategories, taskClosed, taskCreated, taskLinks, taskMerge, taskPair, taskScan, taskSimilar, taskStats, taskUnmerge, topic, topicIcon, trackedChat, trackedChatHistory, waitingChats, watchedMessage, watchItem, };
|
|
100
101
|
export const ENTITIES = {
|
|
101
102
|
sync_progress: syncProgress,
|
|
102
103
|
...MEETING_RESULT_ENTITIES,
|
|
@@ -126,19 +127,22 @@ export const ENTITIES = {
|
|
|
126
127
|
attachments: v.optional(v.array(hitFile)),
|
|
127
128
|
untrusted,
|
|
128
129
|
}),
|
|
129
|
-
"message.summary": v.
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
130
|
+
"message.summary": v.strictObject({
|
|
131
|
+
...v.pick(message, [
|
|
132
|
+
"ref",
|
|
133
|
+
"chat_id",
|
|
134
|
+
"chat_title",
|
|
135
|
+
"timestamp",
|
|
136
|
+
"sender_name",
|
|
137
|
+
"sender_is_me",
|
|
138
|
+
"outgoing",
|
|
139
|
+
"text",
|
|
140
|
+
"transcript",
|
|
141
|
+
"attachments",
|
|
142
|
+
"email",
|
|
143
|
+
]).entries,
|
|
144
|
+
untrusted,
|
|
145
|
+
}),
|
|
142
146
|
message_link: messageLink,
|
|
143
147
|
message_write: messageWrite,
|
|
144
148
|
message_send: messageSend,
|
|
@@ -257,6 +261,7 @@ export const ENTITIES = {
|
|
|
257
261
|
meeting_review: meetingReview,
|
|
258
262
|
meeting_link: meetingLink,
|
|
259
263
|
meeting_stats: meetingStats,
|
|
264
|
+
meeting_counts: meetingCounts,
|
|
260
265
|
meeting_speaker: meetingSpeaker,
|
|
261
266
|
meeting_participants: meetingParticipants,
|
|
262
267
|
meeting_passage: meetingPassage,
|
|
@@ -294,6 +299,7 @@ export const ENTITIES = {
|
|
|
294
299
|
job,
|
|
295
300
|
store_chat_status: storeChatStatus,
|
|
296
301
|
store_clear: storeClear,
|
|
302
|
+
chat_coverage: chatCoverage,
|
|
297
303
|
store_export: storeExport,
|
|
298
304
|
store_gap_plan: storeGapPlan,
|
|
299
305
|
store_gap_repair: storeGapRepair,
|
|
@@ -351,6 +357,7 @@ export const ENTITIES = {
|
|
|
351
357
|
message_counts: messageCounts,
|
|
352
358
|
response_times: responseTimes,
|
|
353
359
|
waiting_chats: waitingChats,
|
|
360
|
+
mail_counts: mailCounts,
|
|
354
361
|
ranking,
|
|
355
362
|
admin_report: adminReport,
|
|
356
363
|
analysis_consent: analysisConsent,
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import * as v from "valibot";
|
|
2
|
+
/** Stored mail received and sent, one row per calendar day, week (by its Monday) or sender. */
|
|
3
|
+
export declare const mailCounts: v.StrictObjectSchema<{
|
|
4
|
+
readonly by: v.PicklistSchema<["day", "week", "sender"], undefined>;
|
|
5
|
+
readonly received: v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 0, undefined>]>;
|
|
6
|
+
readonly sent: v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 0, undefined>]>;
|
|
7
|
+
readonly rows: v.ArraySchema<v.StrictObjectSchema<{
|
|
8
|
+
/** `YYYY-MM-DD`, or the sender's address. */
|
|
9
|
+
readonly key: v.StringSchema<undefined>;
|
|
10
|
+
readonly name: v.NullableSchema<v.StringSchema<undefined>, undefined>;
|
|
11
|
+
readonly received: v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 0, undefined>]>;
|
|
12
|
+
/** Always 0 by sender: the owner sends that mail. */
|
|
13
|
+
readonly sent: v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 0, undefined>]>;
|
|
14
|
+
}, undefined>, undefined>;
|
|
15
|
+
}, undefined>;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import * as v from "valibot";
|
|
2
|
+
import { count, text } from "./fields.js";
|
|
3
|
+
/** Stored mail received and sent, one row per calendar day, week (by its Monday) or sender. */
|
|
4
|
+
export const mailCounts = v.strictObject({
|
|
5
|
+
by: v.picklist(["day", "week", "sender"]),
|
|
6
|
+
received: count,
|
|
7
|
+
sent: count,
|
|
8
|
+
rows: v.array(v.strictObject({
|
|
9
|
+
/** `YYYY-MM-DD`, or the sender's address. */
|
|
10
|
+
key: text,
|
|
11
|
+
name: v.nullable(text),
|
|
12
|
+
received: count,
|
|
13
|
+
/** Always 0 by sender: the owner sends that mail. */
|
|
14
|
+
sent: count,
|
|
15
|
+
})),
|
|
16
|
+
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { event, meeting, meetingDetails, meetingHit, meetingLink, meetingParticipants, meetingPassage, meetingProjectEvidence, meetingReview, meetingSpeaker, meetingStats, meetingSummary, meetingTranscript, } from "../meetings/index.js";
|
|
1
|
+
export { event, meeting, meetingCounts, meetingDetails, meetingHit, meetingLink, meetingParticipants, meetingPassage, meetingProjectEvidence, meetingReview, meetingSpeaker, meetingStats, meetingSummary, meetingTranscript, } from "../meetings/index.js";
|
package/dist/entities/meeting.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { event, meeting, meetingDetails, meetingHit, meetingLink, meetingParticipants, meetingPassage, meetingProjectEvidence, meetingReview, meetingSpeaker, meetingStats, meetingSummary, meetingTranscript, } from "../meetings/index.js";
|
|
1
|
+
export { event, meeting, meetingCounts, meetingDetails, meetingHit, meetingLink, meetingParticipants, meetingPassage, meetingProjectEvidence, meetingReview, meetingSpeaker, meetingStats, meetingSummary, meetingTranscript, } from "../meetings/index.js";
|
|
@@ -12,6 +12,14 @@ export declare const storeChatStatus: v.StrictObjectSchema<{
|
|
|
12
12
|
readonly to: v.NumberSchema<undefined>;
|
|
13
13
|
}, undefined>, undefined>;
|
|
14
14
|
}, undefined>;
|
|
15
|
+
/** `store chats status`: chats = fetched + partial + never, over the account's searchable chats of every kind. */
|
|
16
|
+
export declare const chatCoverage: v.StrictObjectSchema<{
|
|
17
|
+
readonly chats: v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 0, undefined>]>;
|
|
18
|
+
readonly fetched: v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 0, undefined>]>;
|
|
19
|
+
readonly partial: v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 0, undefined>]>;
|
|
20
|
+
readonly never: v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 0, undefined>]>;
|
|
21
|
+
readonly oldest_message_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>;
|
|
22
|
+
}, undefined>;
|
|
15
23
|
export declare const storeClear: v.StrictObjectSchema<{
|
|
16
24
|
readonly cleared: v.BooleanSchema<undefined>;
|
|
17
25
|
readonly dry_run: v.OptionalSchema<v.LiteralSchema<true, undefined>, undefined>;
|
|
@@ -17,6 +17,14 @@ export const storeChatStatus = v.strictObject({
|
|
|
17
17
|
last_stored_at: v.nullable(time),
|
|
18
18
|
held: v.array(range),
|
|
19
19
|
});
|
|
20
|
+
/** `store chats status`: chats = fetched + partial + never, over the account's searchable chats of every kind. */
|
|
21
|
+
export const chatCoverage = v.strictObject({
|
|
22
|
+
chats: count,
|
|
23
|
+
fetched: count,
|
|
24
|
+
partial: count,
|
|
25
|
+
never: count,
|
|
26
|
+
oldest_message_at: v.nullable(time),
|
|
27
|
+
});
|
|
20
28
|
export const storeClear = v.strictObject({
|
|
21
29
|
cleared: v.boolean(),
|
|
22
30
|
dry_run: v.optional(v.literal(true)),
|
package/dist/errors/reasons.js
CHANGED
|
@@ -31,6 +31,18 @@ const SIGN_IN = [
|
|
|
31
31
|
["oauth.not-saved", "configuration_error", "the sign-in cannot be saved or read where it is kept"],
|
|
32
32
|
["sign-in.client-file-open", "configuration_error", "other users of this computer can read the client file"],
|
|
33
33
|
["sign-in.client-file-invalid", "configuration_error", "the file is not a Desktop app OAuth client JSON"],
|
|
34
|
+
["oauth.scope-missing", "permission_error", "the sign-in lacks a permission this command needs"],
|
|
35
|
+
["sign-in.client-rejected", "configuration_error", "the provider rejected the OAuth client"],
|
|
36
|
+
];
|
|
37
|
+
/** Reasons every CLI over a provider's API raises alike: gcal and drive today. */
|
|
38
|
+
const PROVIDER_API = [
|
|
39
|
+
["offline.refused", "permission_error", "this command needs the provider; --offline was given"],
|
|
40
|
+
validation("api.unknown-method", "the provider has no method by this name"),
|
|
41
|
+
["api.disabled", "configuration_error", "the provider's API is turned off for this OAuth project"],
|
|
42
|
+
["provider.usage-limit", "rate_limited", "the account's usage limit at the provider is reached; wait, do not retry"],
|
|
43
|
+
["file.not-found", "not_found", "the file named, or its folder, does not exist"],
|
|
44
|
+
validation("file.not-a-file", "the path names a folder or another thing that is not a file"),
|
|
45
|
+
["file.denied", "permission_error", "the file cannot be opened: permission denied"],
|
|
34
46
|
];
|
|
35
47
|
const OTHERS = [
|
|
36
48
|
["query.time-limit", "timeout", "the search took longer than its time limit; the query itself is valid"],
|
|
@@ -55,6 +67,11 @@ const OTHERS = [
|
|
|
55
67
|
validation("file.locked", "another process holds the file's lock"),
|
|
56
68
|
["mail.source-failed", "provider_error", "the mail server refused or did not complete a request"],
|
|
57
69
|
["mail.search-refused", "provider_error", "the mail server refused to search a folder"],
|
|
70
|
+
[
|
|
71
|
+
"mail.attachments-unread",
|
|
72
|
+
"provider_unavailable",
|
|
73
|
+
"the email could not be read again, so its skipped attachments have no text",
|
|
74
|
+
],
|
|
58
75
|
["mirror.partial", "provider_error", "some mirrored files were not synced"],
|
|
59
76
|
["profile.wrong-account", "authentication_error", "the signed-in source account does not match this profile"],
|
|
60
77
|
validation("push.too-many-files", "the folder holds more files than one push takes"),
|
|
@@ -82,6 +99,7 @@ const OTHERS = [
|
|
|
82
99
|
validation("event.repeat-split", "the series cannot be split at this occurrence, or was split there already"),
|
|
83
100
|
validation("event.repeat-count", "a COUNT series is split only with a rule for its new part"),
|
|
84
101
|
validation("event.unmovable", "the provider keeps this kind of event on its calendar"),
|
|
102
|
+
validation("event.quick-add-ambiguous", "more than one event could be the one a lost quick add made"),
|
|
85
103
|
validation("event.text-with-fields", "--text takes the whole event from its line, so no field option goes with it"),
|
|
86
104
|
validation("calendar.ambiguous", "two or more calendars have this name; name one by its id"),
|
|
87
105
|
validation("export.too-many", "the query finds more events than one export writes"),
|
|
@@ -253,7 +271,7 @@ export const INPUT_FIELD_REASONS = defineReasons([
|
|
|
253
271
|
export const REASONS = defineReasons([
|
|
254
272
|
...QUERY_REASONS,
|
|
255
273
|
...INPUT_FIELD_REASONS,
|
|
256
|
-
...[...QUERY, ...SIGN_IN, ...OTHERS].map(([reason, code, message]) => ({
|
|
274
|
+
...[...QUERY, ...SIGN_IN, ...PROVIDER_API, ...OTHERS].map(([reason, code, message]) => ({
|
|
257
275
|
reason,
|
|
258
276
|
code,
|
|
259
277
|
message,
|
package/dist/mail/cli/index.d.ts
CHANGED
|
@@ -32,6 +32,11 @@ export interface MailReads {
|
|
|
32
32
|
mount?: MailMount;
|
|
33
33
|
/** How `--server-time` help states its default when a provider's own differs (`MailServerAccess.timeMs`). */
|
|
34
34
|
serverTimeDefault?: string;
|
|
35
|
+
/**
|
|
36
|
+
* Reads one stored email again from the mailbox's server, every attachment whatever its size (`readEmailWhole`).
|
|
37
|
+
* With it, `messages show` reads an email whose attachment a sync's policy left unread before it answers.
|
|
38
|
+
*/
|
|
39
|
+
whole?: (command: Command, store: MessageStore, mailbox: AccountKey, emailId: string) => Promise<void>;
|
|
35
40
|
}
|
|
36
41
|
export declare const THREAD_QUERY: {
|
|
37
42
|
readonly entity: "mail_thread";
|
package/dist/mail/cli/index.js
CHANGED
|
@@ -5,7 +5,7 @@ import { Command, InvalidArgumentError } from "commander";
|
|
|
5
5
|
import * as v from "valibot";
|
|
6
6
|
import { answerEntity } from "../../cli/answer-entity.js";
|
|
7
7
|
import { environmentOf, outputFor } from "../../cli/context.js";
|
|
8
|
-
import { LOCAL_READ, REMOTE_READ } from "../../cli/effects.js";
|
|
8
|
+
import { FETCH, LOCAL_READ, REMOTE_READ } from "../../cli/effects.js";
|
|
9
9
|
import { itemOf, listOf, renderAnswer, snakeKeys } from "../../cli/envelope.js";
|
|
10
10
|
import { listQuery, typedQuery, withQuery } from "../../cli/list-query.js";
|
|
11
11
|
import { messagesAnswer, offsetOf, shownOf } from "../../cli/messenger/search-answers.js";
|
|
@@ -13,6 +13,7 @@ import { backendRequest, noteServer, serverSearchOptions } from "../../cli/messe
|
|
|
13
13
|
import { positiveCount } from "../../cli/paging.js";
|
|
14
14
|
import { formatReference, parseReference } from "../../domain/references.js";
|
|
15
15
|
import { count, reference, text, time, untrusted } from "../../entities/fields.js";
|
|
16
|
+
import { POLICY_SKIPS } from "../../mail/attachments.js";
|
|
16
17
|
import { attachmentsText, hitText, searchMail, showMail, withAttachmentText } from "../../mail/read.js";
|
|
17
18
|
import { searchMailServer } from "../../mail/server-search.js";
|
|
18
19
|
import { atDetail } from "../../output-detail.js";
|
|
@@ -28,6 +29,14 @@ const absentAccount = (error) => {
|
|
|
28
29
|
return undefined;
|
|
29
30
|
throw error;
|
|
30
31
|
};
|
|
32
|
+
/** The shown email whose attachment a sync's policy left without text, if any. */
|
|
33
|
+
const policySkipped = (emails) => {
|
|
34
|
+
const shown = emails.find((email) => email.anchor) ?? emails[0];
|
|
35
|
+
const skips = POLICY_SKIPS;
|
|
36
|
+
return shown?.attachments?.some((file) => skips.includes(String(file.extraction)))
|
|
37
|
+
? shown
|
|
38
|
+
: undefined;
|
|
39
|
+
};
|
|
31
40
|
const DEFAULT_LIMIT = 20;
|
|
32
41
|
const MAX_LIMIT = 100;
|
|
33
42
|
const limitOf = (value) => {
|
|
@@ -203,7 +212,7 @@ const shownText = (emails) => `${emails.map((email) => [hitText(email, "full"),
|
|
|
203
212
|
const messagesCommand = (mail) => {
|
|
204
213
|
const messages = new Command("messages").summary("read stored emails").description("read the emails sync stored");
|
|
205
214
|
annotate(messages.command("show"), {
|
|
206
|
-
effects: LOCAL_READ,
|
|
215
|
+
effects: mail.whole ? FETCH : LOCAL_READ,
|
|
207
216
|
examples: [
|
|
208
217
|
`${mail.app.command} personal messages show 'msg:email/me%40example.com/thread-1/%3Cid%40example.com%3E'`,
|
|
209
218
|
`${mail.app.command} personal messages show 'msg:email/me%40example.com/thread-1/%3Cid%40example.com%3E' --before-n 2`,
|
|
@@ -218,15 +227,30 @@ const messagesCommand = (mail) => {
|
|
|
218
227
|
.action(async function (reference) {
|
|
219
228
|
const { beforeN, afterN } = this.opts();
|
|
220
229
|
const full = detailOf(this) === "full";
|
|
230
|
+
let unread;
|
|
221
231
|
const emails = await mail.read(this, async (store, mailbox) => {
|
|
222
232
|
threadOf(mailbox, reference);
|
|
233
|
+
const shown = await showMail(store, reference, { before: beforeN, after: afterN, full });
|
|
234
|
+
const skipped = mail.whole ? policySkipped(shown) : undefined;
|
|
235
|
+
if (!skipped || !mail.whole)
|
|
236
|
+
return shown;
|
|
237
|
+
try {
|
|
238
|
+
await mail.whole(this, store, mailbox, skipped.id);
|
|
239
|
+
}
|
|
240
|
+
catch (error) {
|
|
241
|
+
if (!(error instanceof CliError))
|
|
242
|
+
throw error;
|
|
243
|
+
// The stored email is still worth showing; the answer says its attachments were not read.
|
|
244
|
+
unread = { code: error.code, reason: "mail.attachments-unread", source: "server" };
|
|
245
|
+
return shown;
|
|
246
|
+
}
|
|
223
247
|
return showMail(store, reference, { before: beforeN, after: afterN, full });
|
|
224
248
|
});
|
|
225
249
|
const output = outputFor(this);
|
|
226
250
|
const shown = emails.map((email) => snakeKeys(atDetail(email)));
|
|
227
251
|
renderAnswer(this, output, beforeN || afterN
|
|
228
252
|
? listOf("messages show", { items: shown, limit: Math.max(1, shown.length), has_more: false })
|
|
229
|
-
: itemOf(shown.find((_, at) => emails[at]?.anchor) ?? shown[0]), () => shownText(emails));
|
|
253
|
+
: itemOf(shown.find((_, at) => emails[at]?.anchor) ?? shown[0], unread ? { meta: { complete: false, issues: [unread] } } : undefined), () => shownText(emails));
|
|
230
254
|
});
|
|
231
255
|
messages.addCommand(acknowledgeCommand(mail));
|
|
232
256
|
return messages;
|
package/dist/mail/cli/review.js
CHANGED
|
@@ -8,10 +8,12 @@ import { LOCAL_READ } from "../../cli/effects.js";
|
|
|
8
8
|
import { listOf, renderAnswer } from "../../cli/envelope.js";
|
|
9
9
|
import { listQuery, nativeField, nativeTerms, queryHelp, typedQuery } from "../../cli/list-query.js";
|
|
10
10
|
import { pointsOf } from "../../cli/messenger/catch-up.js";
|
|
11
|
-
import { catchUpQuery, summaryOf } from "../../cli/messenger/catch-up-answers.js";
|
|
11
|
+
import { catchUpQuery, SUMMARY_UNTRUSTED, summaryOf } from "../../cli/messenger/catch-up-answers.js";
|
|
12
12
|
import { messageItem } from "../../cli/messenger/message-items.js";
|
|
13
13
|
import { checkPoints } from "../../cli/messenger/points.js";
|
|
14
14
|
import { unansweredHours } from "../../cli/messenger/review.js";
|
|
15
|
+
import { MAIL_HIT_UNTRUSTED } from "../../cli/messenger/search-answers.js";
|
|
16
|
+
import { mailOwnText } from "../../conversations/mail-text.js";
|
|
15
17
|
import { parseDuration } from "../../domain/duration.js";
|
|
16
18
|
import { formatReference } from "../../domain/references.js";
|
|
17
19
|
import { AGENDA_DEFAULTS } from "../../services/agenda.js";
|
|
@@ -20,6 +22,7 @@ import { readPastMark } from "../marks.js";
|
|
|
20
22
|
import { hitText } from "../read.js";
|
|
21
23
|
import { OWED_DAYS, REVIEW_THREADS, reviewMail } from "../review.js";
|
|
22
24
|
const DAY = 86_400_000;
|
|
25
|
+
const REVIEW_UNTRUSTED = [...SUMMARY_UNTRUSTED, ...MAIL_HIT_UNTRUSTED];
|
|
23
26
|
/** Where a mail review starts: a time only; one thread is `conversations show`. */
|
|
24
27
|
export const MAIL_REVIEW_QUERY = defineQuery({
|
|
25
28
|
entity: "message",
|
|
@@ -132,6 +135,7 @@ const reviewAnswer = (found, mailbox, fresh, step) => {
|
|
|
132
135
|
}
|
|
133
136
|
: {}),
|
|
134
137
|
},
|
|
138
|
+
untrusted: REVIEW_UNTRUSTED,
|
|
135
139
|
})),
|
|
136
140
|
limit: Math.max(1, read.length),
|
|
137
141
|
has_more: false,
|
|
@@ -152,8 +156,10 @@ const holderReview = async (command, mail, holder, query) => {
|
|
|
152
156
|
: new Map();
|
|
153
157
|
return { read, mailbox, marks };
|
|
154
158
|
});
|
|
159
|
+
// An agent reads this: earlier mail and signatures stay out of its text; the fingerprint is over the stored body.
|
|
160
|
+
const emails = read.emails.map((email) => ({ ...email, text: mailOwnText(email.text) }));
|
|
155
161
|
const chats = new Map();
|
|
156
|
-
for (const email of
|
|
162
|
+
for (const email of emails) {
|
|
157
163
|
const chat = chats.get(email.chatId) ?? {
|
|
158
164
|
id: email.chatId,
|
|
159
165
|
title: email.chatTitle,
|
|
@@ -191,7 +197,7 @@ const holderReview = async (command, mail, holder, query) => {
|
|
|
191
197
|
output.renderer.note(read.mark
|
|
192
198
|
? `${holder}: past ${read.mark.throughId}; acknowledge with --cursor ${read.cursor}${read.more ? "; more after these" : ""}`
|
|
193
199
|
: `${holder} has no mark yet: it starts from now — acknowledge with --cursor ${read.cursor}`);
|
|
194
|
-
return
|
|
200
|
+
return emails.map((hit) => `${hitText(hit)}${markText(marks.get(hit.id))}\n`).join("");
|
|
195
201
|
});
|
|
196
202
|
};
|
|
197
203
|
/**
|
|
@@ -217,7 +223,8 @@ export const mailReviewCommand = (mail) => annotate(new Command("review"), {
|
|
|
217
223
|
.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")
|
|
218
224
|
.option("--waiting [duration]", "only threads where you wrote last and nobody answered for this long — 3d; 7d if not given")
|
|
219
225
|
.option("--holder <name>", "read for this holder — an agent or a pipeline — what is stored past its processing mark, by store order; " +
|
|
220
|
-
"bulk, envelopes, drafts, suspicious senders and partial mail left out;
|
|
226
|
+
"bulk, envelopes, drafts, suspicious senders and partial mail left out; each text without quoted earlier mail " +
|
|
227
|
+
"or the signature; `messages acknowledge` moves the mark")
|
|
221
228
|
.option("--new", "what changed since the last `review --new` of this mailbox, a point per thread — for scheduled runs")
|
|
222
229
|
.addHelpText("after", `
|
|
223
230
|
Without a date, --unanswered and --waiting look at threads active in the last ${OWED_DAYS} days.
|
package/dist/mail/index.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export { mailOwnText } from "../conversations/mail-text.js";
|
|
1
2
|
export { mailAccountKey } from "./account-key.js";
|
|
2
3
|
export { DEFAULT_ATTACHMENT_POLICY, type MailAttachmentPolicy, POLICY_SKIPS } from "./attachments.js";
|
|
3
4
|
export { BULK, bulkBox } from "./bulk.js";
|
|
@@ -28,6 +29,7 @@ export { type MailCriteria, mailCriteriaOf, narrows } from "./server-query.js";
|
|
|
28
29
|
export { type MailServerAccess, type MailServerRequest, searchMailServer } from "./server-search.js";
|
|
29
30
|
export type { Listed, MailSource, Quick, Searched } from "./source.js";
|
|
30
31
|
export { SEARCH_REFUSED, searchRefused } from "./source.js";
|
|
32
|
+
export { MAIL_STATS_BY, type MailStats, type MailStatsBy, type MailStatsRequest, type MailStatsRow, mailStats, mailStatsItem, } from "./stats.js";
|
|
31
33
|
export { listedOf, type StoredMail } from "./stored.js";
|
|
32
34
|
export { MAX_ATTACHMENT_CHARS, type MailAccount, type MailIndexed, type MailSyncOptions, type MailSyncResult, RETRYABLE_ATTACHMENTS, syncMail, } from "./sync.js";
|
|
33
35
|
export { readEmailWhole, type WholeAttachment } from "./whole.js";
|
package/dist/mail/index.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export { mailOwnText } from "../conversations/mail-text.js";
|
|
1
2
|
export { mailAccountKey } from "./account-key.js";
|
|
2
3
|
export { DEFAULT_ATTACHMENT_POLICY, POLICY_SKIPS } from "./attachments.js";
|
|
3
4
|
export { BULK, bulkBox } from "./bulk.js";
|
|
@@ -27,6 +28,7 @@ export { DEMOTE_AT, demotedSenders, SCORE_VERSION, scoreSenders, } from "./sende
|
|
|
27
28
|
export { mailCriteriaOf, narrows } from "./server-query.js";
|
|
28
29
|
export { searchMailServer } from "./server-search.js";
|
|
29
30
|
export { SEARCH_REFUSED, searchRefused } from "./source.js";
|
|
31
|
+
export { MAIL_STATS_BY, mailStats, mailStatsItem, } from "./stats.js";
|
|
30
32
|
export { listedOf } from "./stored.js";
|
|
31
33
|
export { MAX_ATTACHMENT_CHARS, RETRYABLE_ATTACHMENTS, syncMail, } from "./sync.js";
|
|
32
34
|
export { readEmailWhole } from "./whole.js";
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import type { Saved } from "../services/message-resolution.js";
|
|
2
|
+
import type { AccountKey, MessageStore } from "../store/store.js";
|
|
3
|
+
export declare const MAIL_STATS_BY: readonly ["day", "week", "sender"];
|
|
4
|
+
export type MailStatsBy = (typeof MAIL_STATS_BY)[number];
|
|
5
|
+
export interface MailStatsRequest {
|
|
6
|
+
by: MailStatsBy;
|
|
7
|
+
/** The query of `search mail`; every stored email when unset. */
|
|
8
|
+
text?: string;
|
|
9
|
+
/** Only these mailboxes; every stored one when neither this nor `mailAccount` is given. */
|
|
10
|
+
accounts?: AccountKey[];
|
|
11
|
+
/** Only this mailbox, by its address. */
|
|
12
|
+
mailAccount?: string;
|
|
13
|
+
exact?: boolean;
|
|
14
|
+
/** Where calendar days and weeks start; the system timezone when unset, as for search. */
|
|
15
|
+
timezone?: string;
|
|
16
|
+
/** Rows kept: the busiest senders, or the latest days and weeks, oldest first. */
|
|
17
|
+
limit: number;
|
|
18
|
+
}
|
|
19
|
+
export interface MailStatsRow {
|
|
20
|
+
/** `YYYY-MM-DD` (a week by its Monday), or the sender's address. */
|
|
21
|
+
key: string;
|
|
22
|
+
name: string | null;
|
|
23
|
+
received: number;
|
|
24
|
+
sent: number;
|
|
25
|
+
}
|
|
26
|
+
export interface MailStats {
|
|
27
|
+
by: MailStatsBy;
|
|
28
|
+
received: number;
|
|
29
|
+
sent: number;
|
|
30
|
+
rows: MailStatsRow[];
|
|
31
|
+
hasMore: boolean;
|
|
32
|
+
timezone: string;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Stored mail the `search mail` query matches, received and sent, per calendar day, week or sender; counts only.
|
|
36
|
+
* `--by sender` counts received mail: the sender of sent mail is the owner. Reads the store, records no search.
|
|
37
|
+
*/
|
|
38
|
+
export declare const mailStats: (store: MessageStore, runAs: AccountKey, { by, text, accounts, mailAccount, exact, timezone, limit }: MailStatsRequest, saved?: Saved) => Promise<MailStats>;
|
|
39
|
+
/** The `mail_counts` entity: what a command answers as its `item`. */
|
|
40
|
+
export declare const mailStatsItem: ({ by, received, sent, rows }: MailStats) => {
|
|
41
|
+
by: "day" | "sender" | "week";
|
|
42
|
+
received: number;
|
|
43
|
+
sent: number;
|
|
44
|
+
rows: {
|
|
45
|
+
key: string;
|
|
46
|
+
name: string | null;
|
|
47
|
+
received: number;
|
|
48
|
+
sent: number;
|
|
49
|
+
}[];
|
|
50
|
+
};
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { calendarKey, weekKey } from "../domain/calendar.js";
|
|
2
|
+
import { prepareLucene } from "../services/messages-search.js";
|
|
3
|
+
export const MAIL_STATS_BY = ["day", "week", "sender"];
|
|
4
|
+
/**
|
|
5
|
+
* Stored mail the `search mail` query matches, received and sent, per calendar day, week or sender; counts only.
|
|
6
|
+
* `--by sender` counts received mail: the sender of sent mail is the owner. Reads the store, records no search.
|
|
7
|
+
*/
|
|
8
|
+
export const mailStats = async (store, runAs, { by, text, accounts, mailAccount, exact, timezone, limit }, saved = {}) => {
|
|
9
|
+
const prepared = await prepareLucene(store, runAs, {
|
|
10
|
+
kind: "mail",
|
|
11
|
+
limit: 1,
|
|
12
|
+
...(text?.trim() ? { text } : {}),
|
|
13
|
+
...(accounts === undefined ? {} : { accounts }),
|
|
14
|
+
...(mailAccount === undefined ? {} : { mailAccount }),
|
|
15
|
+
...(exact ? { exact: true } : {}),
|
|
16
|
+
...(timezone === undefined ? {} : { timezone }),
|
|
17
|
+
}, saved);
|
|
18
|
+
const mailboxes = prepared.scopeAccounts.filter(({ provider }) => provider === "email");
|
|
19
|
+
const groups = mailboxes.length
|
|
20
|
+
? await store.queries.countQuery({ ...prepared.execution, accounts: mailboxes, corpus: "mail" }, by === "sender" ? "sender_direction" : "time_direction")
|
|
21
|
+
: [];
|
|
22
|
+
const received = groups.filter(({ outgoing }) => !outgoing).reduce((sum, { count }) => sum + count, 0);
|
|
23
|
+
const sent = groups.filter(({ outgoing }) => outgoing).reduce((sum, { count }) => sum + count, 0);
|
|
24
|
+
let rows;
|
|
25
|
+
if (by === "sender")
|
|
26
|
+
rows = groups
|
|
27
|
+
.filter(({ outgoing }) => !outgoing)
|
|
28
|
+
.map(({ id, name, count }) => ({ key: id ?? "unknown", name, received: count, sent: 0 }))
|
|
29
|
+
.sort((a, b) => b.received - a.received || a.key.localeCompare(b.key));
|
|
30
|
+
else {
|
|
31
|
+
const day = calendarKey(prepared.timezone, "day");
|
|
32
|
+
const keyOf = by === "week" ? (at) => weekKey(day(at)) : day;
|
|
33
|
+
const totals = new Map();
|
|
34
|
+
for (const { id, outgoing, count } of groups) {
|
|
35
|
+
const key = keyOf(Number(id));
|
|
36
|
+
const row = totals.get(key) ?? { key, name: null, received: 0, sent: 0 };
|
|
37
|
+
if (outgoing)
|
|
38
|
+
row.sent += count;
|
|
39
|
+
else
|
|
40
|
+
row.received += count;
|
|
41
|
+
totals.set(key, row);
|
|
42
|
+
}
|
|
43
|
+
rows = [...totals.values()].sort((a, b) => a.key.localeCompare(b.key));
|
|
44
|
+
}
|
|
45
|
+
return {
|
|
46
|
+
by,
|
|
47
|
+
received,
|
|
48
|
+
sent,
|
|
49
|
+
rows: by === "sender" ? rows.slice(0, limit) : rows.slice(-limit),
|
|
50
|
+
hasMore: rows.length > limit,
|
|
51
|
+
timezone: prepared.timezone,
|
|
52
|
+
};
|
|
53
|
+
};
|
|
54
|
+
/** The `mail_counts` entity: what a command answers as its `item`. */
|
|
55
|
+
export const mailStatsItem = ({ by, received, sent, rows }) => ({
|
|
56
|
+
by,
|
|
57
|
+
received,
|
|
58
|
+
sent,
|
|
59
|
+
rows: rows.map(({ key, name, received, sent }) => ({ key, name, received, sent })),
|
|
60
|
+
});
|
package/dist/mail/whole.d.ts
CHANGED
|
@@ -21,8 +21,8 @@ export declare const readEmailWhole: ({ store, source, address, externalId, fold
|
|
|
21
21
|
address: string;
|
|
22
22
|
externalId: string;
|
|
23
23
|
folders: () => Promise<readonly string[]>;
|
|
24
|
-
maxBodyChars
|
|
25
|
-
maxAttachmentChars
|
|
26
|
-
loadEngine
|
|
27
|
-
now
|
|
24
|
+
maxBodyChars?: number;
|
|
25
|
+
maxAttachmentChars?: number;
|
|
26
|
+
loadEngine?: LoadEngine;
|
|
27
|
+
now?: number;
|
|
28
28
|
}) => Promise<WholeAttachment[]>;
|
package/dist/mail/whole.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { CliError } from "@wirecat/cli-base";
|
|
2
|
+
import { importEngine } from "../attachments/extract.js";
|
|
2
3
|
import { mailAccountKey } from "./account-key.js";
|
|
3
|
-
import { readAttachments } from "./attachments.js";
|
|
4
|
+
import { MAX_ATTACHMENT_CHARS, readAttachments } from "./attachments.js";
|
|
4
5
|
import { parsedEmail } from "./email-input.js";
|
|
5
6
|
import { mailHeadersOf } from "./headers.js";
|
|
6
|
-
import { parseMail } from "./parse.js";
|
|
7
|
+
import { MAX_BODY_CHARS, parseMail } from "./parse.js";
|
|
7
8
|
import { PARTIAL } from "./partial.js";
|
|
8
9
|
/**
|
|
9
10
|
* Reads one stored email from its source again and every attachment of it, whatever its size: what a person asks for
|
|
@@ -11,7 +12,7 @@ import { PARTIAL } from "./partial.js";
|
|
|
11
12
|
* takes it; the files are only answered, never written. Gmail's email is found by its id in `folders`; elsewhere it is
|
|
12
13
|
* read at its newest stored place, trusted only when `identify` gives the stored id for the bytes read there.
|
|
13
14
|
*/
|
|
14
|
-
export const readEmailWhole = async ({ store, source, address, externalId, folders, maxBodyChars, maxAttachmentChars, loadEngine, now, }) => {
|
|
15
|
+
export const readEmailWhole = async ({ store, source, address, externalId, folders, maxBodyChars = MAX_BODY_CHARS, maxAttachmentChars = MAX_ATTACHMENT_CHARS, loadEngine = importEngine, now = Date.now(), }) => {
|
|
15
16
|
const { id: accountId } = await store.accounts.storedAccount(mailAccountKey(address));
|
|
16
17
|
const stored = await store.mail.emailPlace(accountId, externalId);
|
|
17
18
|
if (stored === null)
|
|
@@ -28,7 +28,7 @@ export declare const callMeetingPreparationTool: (read: MeetingPreparationReader
|
|
|
28
28
|
}[];
|
|
29
29
|
structuredContent: {
|
|
30
30
|
error: {
|
|
31
|
-
code: "authentication_error" | "cancelled" | "configuration_error" | "confirmation_required" | "internal_error" | "invalid_response" | "network_error" | "not_found" | "outcome_unknown" | "permission_error" | "provider_error" | "provider_unavailable" | "rate_limited" | "timeout" | "validation_error";
|
|
31
|
+
code: "authentication_error" | "cancelled" | "configuration_error" | "confirmation_required" | "conflict" | "internal_error" | "invalid_response" | "network_error" | "not_found" | "outcome_unknown" | "permission_error" | "provider_error" | "provider_unavailable" | "rate_limited" | "timeout" | "validation_error";
|
|
32
32
|
reason: string;
|
|
33
33
|
message: string;
|
|
34
34
|
param?: string | undefined;
|
|
@@ -23,7 +23,7 @@ export declare const callMeetingProjectCandidatesTool: (read: StoredMeetingProje
|
|
|
23
23
|
}[];
|
|
24
24
|
structuredContent: {
|
|
25
25
|
error: {
|
|
26
|
-
code: "authentication_error" | "cancelled" | "configuration_error" | "confirmation_required" | "internal_error" | "invalid_response" | "network_error" | "not_found" | "outcome_unknown" | "permission_error" | "provider_error" | "provider_unavailable" | "rate_limited" | "timeout" | "validation_error";
|
|
26
|
+
code: "authentication_error" | "cancelled" | "configuration_error" | "confirmation_required" | "conflict" | "internal_error" | "invalid_response" | "network_error" | "not_found" | "outcome_unknown" | "permission_error" | "provider_error" | "provider_unavailable" | "rate_limited" | "timeout" | "validation_error";
|
|
27
27
|
reason: string;
|
|
28
28
|
message: string;
|
|
29
29
|
param?: string | undefined;
|
|
@@ -23,7 +23,7 @@ export declare const callMeetingSeriesInventoryTool: (read: MeetingSeriesInvento
|
|
|
23
23
|
}[];
|
|
24
24
|
structuredContent: {
|
|
25
25
|
error: {
|
|
26
|
-
code: "authentication_error" | "cancelled" | "configuration_error" | "confirmation_required" | "internal_error" | "invalid_response" | "network_error" | "not_found" | "outcome_unknown" | "permission_error" | "provider_error" | "provider_unavailable" | "rate_limited" | "timeout" | "validation_error";
|
|
26
|
+
code: "authentication_error" | "cancelled" | "configuration_error" | "confirmation_required" | "conflict" | "internal_error" | "invalid_response" | "network_error" | "not_found" | "outcome_unknown" | "permission_error" | "provider_error" | "provider_unavailable" | "rate_limited" | "timeout" | "validation_error";
|
|
27
27
|
reason: string;
|
|
28
28
|
message: string;
|
|
29
29
|
param?: string | undefined;
|
package/dist/meetings/index.d.ts
CHANGED
|
@@ -32,7 +32,7 @@ export { type MeetingProjectEvidenceAnswer, type MeetingProjectEvidenceItem, mee
|
|
|
32
32
|
export { MEETING_PROJECT_EVIDENCE_QUERY, type MeetingProjectEvidenceRequest, prepareMeetingProjectEvidence, } from "./project-evidence-query.js";
|
|
33
33
|
export { type MeetingProviderScope, snapshotMeetingScope } from "./provider.js";
|
|
34
34
|
export { type PullOptions, pull, type RunReport } from "./pull.js";
|
|
35
|
-
export { event, eventItem, meetingLink, meetingLinkItem, meetingParticipants, meetingPassage, meetingReview, meetingReviewItem, meetingSpeaker, meetingSpeakerItem, meetingStats, meetingStatsItem, } from "./read-answers.js";
|
|
35
|
+
export { event, eventItem, meetingCounts, meetingCountsItem, meetingLink, meetingLinkItem, meetingParticipants, meetingPassage, meetingReview, meetingReviewItem, meetingSpeaker, meetingSpeakerItem, meetingStats, meetingStatsItem, } from "./read-answers.js";
|
|
36
36
|
export type { MeetingContextReadCapabilities, MeetingReadBudget, MeetingReadCapabilities, MeetingReadScope, TranscriptContextInput, TranscriptContextPage, TranscriptPage, TranscriptReadScope, TranscriptRowPage, } from "./read-store.js";
|
|
37
37
|
export { listed, MeetingError, meetingDetailsAnswer, meetingPeople, meetingSummaryAnswer, meetingTranscriptAnswer, type TranscriptReadOptions, } from "./reads.js";
|
|
38
38
|
export { installRecordingArchiveSchedule, parseRecordingArchiveSchedule, planRecordingArchiveSchedule, type RecordingArchiveSchedule, type RecordingArchiveScheduleInput, type RecordingArchiveScheduler, recordingArchiveScheduleWindow, } from "./recording-schedule.js";
|
|
@@ -51,7 +51,7 @@ export { createMeetingSeriesInventoryReader } from "./series-inventory.js";
|
|
|
51
51
|
export type { MeetingSeriesCandidate, MeetingSeriesInventoryPage, MeetingSeriesInventoryPort, MeetingSeriesInventoryRead, MeetingSeriesInventoryRequest, MeetingSeriesInventoryResult, } from "./series-inventory-types.js";
|
|
52
52
|
export { validateMeetingSeriesInventoryCursor } from "./series-inventory-validation.js";
|
|
53
53
|
export type { MeetingSource, SourceParticipant } from "./source.js";
|
|
54
|
-
export { aggregateMeetingStats, type MeetingSpeakerStats, type MeetingStats, type MeetingStatsInput, type MeetingStatsRow, type MeetingStatsSelection, type MeetingStatsStore, type MeetingWeekStats, } from "./stats.js";
|
|
54
|
+
export { aggregateMeetingCounts, aggregateMeetingStats, MEETING_COUNTS_GROUPINGS, type MeetingCounts, type MeetingCountsGrouping, type MeetingCountsInput, type MeetingCountsMeeting, type MeetingCountsRow, type MeetingSpeakerStats, type MeetingStats, type MeetingStatsInput, type MeetingStatsRow, type MeetingStatsSelection, type MeetingStatsStore, type MeetingWeekStats, NO_SERIES, } from "./stats.js";
|
|
55
55
|
export type { ChatInput, ContractCase, EventCandidateFilter, IdentityInput, MeetingDetails, MeetingFilter, MeetingHitSource, MeetingInput, MeetingSave, MeetingStore, NewRecord, ParticipantInput, SearchHit, TranscriptInput, TranscriptLanguageFill, TranscriptRowInput, } from "./store.js";
|
|
56
56
|
export { meetingTimestamp } from "./timestamp.js";
|
|
57
57
|
export type { MeetingTranscriptReceiptStore, MeetingTranscriptStore, TranscriptAppend, TranscriptAppendReceipt, UnlinkedTranscriptInput, } from "./transcript-store.js";
|
package/dist/meetings/index.js
CHANGED
|
@@ -24,7 +24,7 @@ export { meetingProjectEvidence, meetingProjectEvidenceAnswer, } from "./project
|
|
|
24
24
|
export { MEETING_PROJECT_EVIDENCE_QUERY, prepareMeetingProjectEvidence, } from "./project-evidence-query.js";
|
|
25
25
|
export { snapshotMeetingScope } from "./provider.js";
|
|
26
26
|
export { pull } from "./pull.js";
|
|
27
|
-
export { event, eventItem, meetingLink, meetingLinkItem, meetingParticipants, meetingPassage, meetingReview, meetingReviewItem, meetingSpeaker, meetingSpeakerItem, meetingStats, meetingStatsItem, } from "./read-answers.js";
|
|
27
|
+
export { event, eventItem, meetingCounts, meetingCountsItem, meetingLink, meetingLinkItem, meetingParticipants, meetingPassage, meetingReview, meetingReviewItem, meetingSpeaker, meetingSpeakerItem, meetingStats, meetingStatsItem, } from "./read-answers.js";
|
|
28
28
|
export { listed, MeetingError, meetingDetailsAnswer, meetingPeople, meetingSummaryAnswer, meetingTranscriptAnswer, } from "./reads.js";
|
|
29
29
|
export { installRecordingArchiveSchedule, parseRecordingArchiveSchedule, planRecordingArchiveSchedule, recordingArchiveScheduleWindow, } from "./recording-schedule.js";
|
|
30
30
|
export { parseRecordingSyncCheckpoint, RecordingSyncError, recordingAssetFingerprint, recordingWindows, syncRecordingArchive, } from "./recording-sync.js";
|
|
@@ -38,7 +38,7 @@ export { validateMeetingHitSearch } from "./search-validation.js";
|
|
|
38
38
|
export { validateMeetingSeriesHistory, } from "./series-history.js";
|
|
39
39
|
export { createMeetingSeriesInventoryReader } from "./series-inventory.js";
|
|
40
40
|
export { validateMeetingSeriesInventoryCursor } from "./series-inventory-validation.js";
|
|
41
|
-
export { aggregateMeetingStats, } from "./stats.js";
|
|
41
|
+
export { aggregateMeetingCounts, aggregateMeetingStats, MEETING_COUNTS_GROUPINGS, NO_SERIES, } from "./stats.js";
|
|
42
42
|
export { meetingTimestamp } from "./timestamp.js";
|
|
43
43
|
export { parseTranscriptText, TranscriptTextError } from "./transcript-text.js";
|
|
44
44
|
export { transcribeMeeting, } from "./transcription.js";
|