@wirecat/cli-core 0.562.0 → 0.564.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 +139 -0
- package/dist/calendar/mcp/index.d.ts +12 -12
- package/dist/cli/config-command.js +18 -1
- package/dist/cli/envelope.js +13 -1
- package/dist/cli/execution.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/reply-stats-command.d.ts +4 -0
- package/dist/cli/messenger/reply-stats-command.js +57 -0
- package/dist/cli/messenger/search-answers.d.ts +1 -0
- package/dist/cli/messenger/search-answers.js +1 -1
- package/dist/cli/messenger/search-command.js +8 -0
- package/dist/cli/messenger/stats-answers.d.ts +6 -3
- package/dist/cli/messenger/stats-answers.js +39 -9
- package/dist/cli/messenger/stats-command.js +5 -0
- package/dist/cli/messenger/tasks-command.js +35 -14
- package/dist/cli/output-budget.d.ts +26 -0
- package/dist/cli/output-budget.js +73 -0
- package/dist/cli/program.js +14 -1
- package/dist/cli/settings.d.ts +5 -0
- package/dist/cli/settings.js +88 -5
- package/dist/cli/shared-command-exports.d.ts +8 -0
- package/dist/conversations/mail-text.d.ts +6 -0
- package/dist/conversations/mail-text.js +73 -0
- package/dist/domain/admin-statistics.d.ts +5 -0
- package/dist/domain/admin-statistics.js +4 -3
- 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 +80 -802
- package/dist/entities/index.js +26 -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/reply-stats.d.ts +33 -0
- package/dist/entities/reply-stats.js +19 -0
- package/dist/entities/store-records.d.ts +8 -0
- package/dist/entities/store-records.js +8 -0
- package/dist/errors/reasons.d.ts +1 -1
- package/dist/errors/reasons.js +7 -3
- package/dist/mail/attachments.d.ts +15 -2
- package/dist/mail/attachments.js +19 -3
- package/dist/mail/cli/index.d.ts +22 -1
- package/dist/mail/cli/index.js +28 -4
- package/dist/mail/cli/review.d.ts +5 -2
- package/dist/mail/cli/review.js +58 -43
- package/dist/mail/index.d.ts +4 -0
- package/dist/mail/index.js +4 -0
- package/dist/mail/partial.d.ts +3 -1
- package/dist/mail/partial.js +2 -2
- package/dist/mail/retry.d.ts +3 -1
- package/dist/mail/retry.js +3 -3
- package/dist/mail/stats.d.ts +50 -0
- package/dist/mail/stats.js +60 -0
- package/dist/mail/sync-types.d.ts +3 -0
- package/dist/mail/sync.js +5 -3
- package/dist/mail/whole.d.ts +28 -0
- package/dist/mail/whole.js +70 -0
- 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/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 +3 -1
- package/dist/services/index.js +3 -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/notes-search.d.ts +5 -1
- package/dist/services/notes-search.js +16 -5
- package/dist/services/proposal-tasks.js +3 -12
- package/dist/services/proposals/ids.d.ts +2 -2
- package/dist/services/proposals/ids.js +5 -3
- package/dist/services/proposals/kinds/action.js +3 -2
- 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 +12 -4
- package/dist/services/proposals/types.d.ts +2 -0
- package/dist/services/reply-stats.d.ts +48 -0
- package/dist/services/reply-stats.js +137 -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 +16 -11
- package/dist/store/decisions.js +11 -2
- package/dist/store/exports.d.ts +1 -1
- package/dist/store/exports.js +1 -1
- package/dist/store/index.d.ts +5 -4
- package/dist/store/index.js +3 -3
- package/dist/store/queries.d.ts +4 -0
- package/dist/store/queries.js +3 -0
- package/dist/store/sqlite/completeness.d.ts +17 -0
- package/dist/store/sqlite/completeness.js +49 -13
- package/dist/store/sqlite/email-locations.d.ts +4 -0
- package/dist/store/sqlite/email-locations.js +26 -11
- package/dist/store/sqlite/lucene-fields.d.ts +2 -0
- package/dist/store/sqlite/lucene-fields.js +5 -1
- 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/mail-findings.js +1 -1
- package/dist/store/sqlite/meeting-findings.js +1 -1
- package/dist/store/sqlite/meeting-stats.d.ts +2 -0
- package/dist/store/sqlite/meeting-stats.js +27 -1
- package/dist/store/sqlite/proposed-actions.d.ts +2 -0
- package/dist/store/sqlite/proposed-actions.js +24 -17
- package/dist/store/sqlite/reply-times.d.ts +57 -0
- package/dist/store/sqlite/reply-times.js +113 -0
- 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/dist/store/sqlite/work-tasks.d.ts +12 -2
- package/dist/store/sqlite/work-tasks.js +35 -26
- package/dist/store/store.d.ts +1 -0
- package/package.json +1 -1
- package/parity.json +37 -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";
|
|
@@ -78,11 +79,12 @@ import { reactionChange } from "./reaction-change.js";
|
|
|
78
79
|
import { recipient, recipientAdded, recipientChange, recipientOff, recipientRemoved } from "./recipient.js";
|
|
79
80
|
import { recordedRun, runDetails, runHit, runLocation } from "./recorded-run.js";
|
|
80
81
|
import { relationship } from "./relationship.js";
|
|
82
|
+
import { responseTimes, waitingChats } from "./reply-stats.js";
|
|
81
83
|
import { retention } from "./retention.js";
|
|
82
84
|
import { savedSearch, searchHistoryClear } from "./saved-search.js";
|
|
83
85
|
import { sendAttempt } from "./send-attempt.js";
|
|
84
86
|
import { storeBackup, storeCheck, storeCopyRemoval, storeDecrypt, storeInfo, storeMigration, storeReindex, storeRepair, storeReset, storeRestore, } from "./store-maintenance.js";
|
|
85
|
-
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";
|
|
86
88
|
import { storeTable } from "./store-table.js";
|
|
87
89
|
import { automaticTags, tagChange } from "./tag-change.js";
|
|
88
90
|
import { tagging } from "./tagging.js";
|
|
@@ -95,7 +97,7 @@ import { topic } from "./topic.js";
|
|
|
95
97
|
* subset of its fields, never a renamed one. Commands move onto these one by one; until then, a schema
|
|
96
98
|
* is the target, not a description of today's output.
|
|
97
99
|
*/
|
|
98
|
-
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, 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, 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, };
|
|
99
101
|
export const ENTITIES = {
|
|
100
102
|
sync_progress: syncProgress,
|
|
101
103
|
...MEETING_RESULT_ENTITIES,
|
|
@@ -125,19 +127,22 @@ export const ENTITIES = {
|
|
|
125
127
|
attachments: v.optional(v.array(hitFile)),
|
|
126
128
|
untrusted,
|
|
127
129
|
}),
|
|
128
|
-
"message.summary": v.
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
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
|
+
}),
|
|
141
146
|
message_link: messageLink,
|
|
142
147
|
message_write: messageWrite,
|
|
143
148
|
message_send: messageSend,
|
|
@@ -256,6 +261,7 @@ export const ENTITIES = {
|
|
|
256
261
|
meeting_review: meetingReview,
|
|
257
262
|
meeting_link: meetingLink,
|
|
258
263
|
meeting_stats: meetingStats,
|
|
264
|
+
meeting_counts: meetingCounts,
|
|
259
265
|
meeting_speaker: meetingSpeaker,
|
|
260
266
|
meeting_participants: meetingParticipants,
|
|
261
267
|
meeting_passage: meetingPassage,
|
|
@@ -293,6 +299,7 @@ export const ENTITIES = {
|
|
|
293
299
|
job,
|
|
294
300
|
store_chat_status: storeChatStatus,
|
|
295
301
|
store_clear: storeClear,
|
|
302
|
+
chat_coverage: chatCoverage,
|
|
296
303
|
store_export: storeExport,
|
|
297
304
|
store_gap_plan: storeGapPlan,
|
|
298
305
|
store_gap_repair: storeGapRepair,
|
|
@@ -348,6 +355,9 @@ export const ENTITIES = {
|
|
|
348
355
|
topic,
|
|
349
356
|
folder,
|
|
350
357
|
message_counts: messageCounts,
|
|
358
|
+
response_times: responseTimes,
|
|
359
|
+
waiting_chats: waitingChats,
|
|
360
|
+
mail_counts: mailCounts,
|
|
351
361
|
ranking,
|
|
352
362
|
admin_report: adminReport,
|
|
353
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";
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import * as v from "valibot";
|
|
2
|
+
/** How long replies took in one-to-one chats: the owner's (`me`) or the other side's (`others`). */
|
|
3
|
+
export declare const responseTimes: v.StrictObjectSchema<{
|
|
4
|
+
readonly replies: v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 0, undefined>]>;
|
|
5
|
+
readonly median_ms: v.NullableSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.MinValueAction<number, 0, undefined>]>, undefined>;
|
|
6
|
+
readonly p90_ms: v.NullableSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.MinValueAction<number, 0, undefined>]>, undefined>;
|
|
7
|
+
readonly mean_ms: v.NullableSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.MinValueAction<number, 0, undefined>]>, undefined>;
|
|
8
|
+
readonly who: v.PicklistSchema<["me", "others"], undefined>;
|
|
9
|
+
readonly buckets: v.StrictObjectSchema<{
|
|
10
|
+
readonly under_5m: v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 0, undefined>]>;
|
|
11
|
+
readonly under_1h: v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 0, undefined>]>;
|
|
12
|
+
readonly under_1d: v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 0, undefined>]>;
|
|
13
|
+
readonly over_1d: v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 0, undefined>]>;
|
|
14
|
+
}, undefined>;
|
|
15
|
+
/** One row per calendar day of the reply; empty with `--by total`. */
|
|
16
|
+
readonly rows: v.ArraySchema<v.StrictObjectSchema<{
|
|
17
|
+
readonly replies: v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 0, undefined>]>;
|
|
18
|
+
readonly median_ms: v.NullableSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.MinValueAction<number, 0, undefined>]>, undefined>;
|
|
19
|
+
readonly p90_ms: v.NullableSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.MinValueAction<number, 0, undefined>]>, undefined>;
|
|
20
|
+
readonly mean_ms: v.NullableSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.MinValueAction<number, 0, undefined>]>, undefined>;
|
|
21
|
+
readonly key: v.StringSchema<undefined>;
|
|
22
|
+
}, undefined>, undefined>;
|
|
23
|
+
}, undefined>;
|
|
24
|
+
/** Chats whose newest message asks the owner something, and how much waits there. */
|
|
25
|
+
export declare const waitingChats: v.StrictObjectSchema<{
|
|
26
|
+
readonly chats: v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 0, undefined>]>;
|
|
27
|
+
readonly messages: v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 0, undefined>]>;
|
|
28
|
+
readonly oldest_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>;
|
|
29
|
+
readonly by_kind: v.StrictObjectSchema<{
|
|
30
|
+
readonly private: v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 0, undefined>]>;
|
|
31
|
+
readonly group: v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 0, undefined>]>;
|
|
32
|
+
}, undefined>;
|
|
33
|
+
}, undefined>;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import * as v from "valibot";
|
|
2
|
+
import { count, text, time } from "./fields.js";
|
|
3
|
+
const milliseconds = v.nullable(v.pipe(v.number(), v.minValue(0)));
|
|
4
|
+
const figures = { replies: count, median_ms: milliseconds, p90_ms: milliseconds, mean_ms: milliseconds };
|
|
5
|
+
/** How long replies took in one-to-one chats: the owner's (`me`) or the other side's (`others`). */
|
|
6
|
+
export const responseTimes = v.strictObject({
|
|
7
|
+
who: v.picklist(["me", "others"]),
|
|
8
|
+
...figures,
|
|
9
|
+
buckets: v.strictObject({ under_5m: count, under_1h: count, under_1d: count, over_1d: count }),
|
|
10
|
+
/** One row per calendar day of the reply; empty with `--by total`. */
|
|
11
|
+
rows: v.array(v.strictObject({ key: text, ...figures })),
|
|
12
|
+
});
|
|
13
|
+
/** Chats whose newest message asks the owner something, and how much waits there. */
|
|
14
|
+
export const waitingChats = v.strictObject({
|
|
15
|
+
chats: count,
|
|
16
|
+
messages: count,
|
|
17
|
+
oldest_at: v.nullable(time),
|
|
18
|
+
by_kind: v.strictObject({ private: count, group: count }),
|
|
19
|
+
});
|
|
@@ -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.d.ts
CHANGED
|
@@ -7,7 +7,7 @@ export declare const REASONS: ErrorReason[];
|
|
|
7
7
|
* Detail keys an error from this package may carry, until each is registered on its own reason. Not `cause`:
|
|
8
8
|
* that can hold a provider's or SQLite's raw text.
|
|
9
9
|
*/
|
|
10
|
-
export declare const DETAILS: readonly ["contracts", "calendars", "allowed", "alternative", "arguments", "at", "available", "batch", "budget", "built", "candidates", "chat", "chat_id", "cli", "column", "complete", "emitted_bytes", "exact", "file", "forum", "guide", "hint", "id", "index", "kind", "limit", "limit_source", "line", "max_bytes", "model", "name", "operation_id", "operation_ids", "text_limit", "store_refused_in", "
|
|
10
|
+
export declare const DETAILS: readonly ["contracts", "calendars", "allowed", "alternative", "arguments", "at", "available", "batch", "budget", "built", "candidates", "chat", "chat_id", "cli", "column", "complete", "emitted_bytes", "exact", "file", "forum", "guide", "hint", "id", "index", "kind", "limit", "limit_source", "line", "max_bytes", "model", "name", "operation_id", "operation_ids", "text_limit", "store_refused_in", "partial_output", "parent", "path", "permission", "person_ids", "previous_chat_id", "profiles", "provider_error", "provider", "recovery", "reference", "remembered", "retry_at", "retry_after_ms", "runtime", "saved", "scheduled_for", "script", "sent", "sent_count", "settlement_failed", "span", "sqlite", "stage", "standing", "state", "stderr", "term", "total", "upgraded", "wanted"];
|
|
11
11
|
/** What a CLI adds to the shared registry: its own reasons, and the detail keys its adapters raise. */
|
|
12
12
|
export interface AppErrors {
|
|
13
13
|
reasons?: readonly ErrorReason[];
|
package/dist/errors/reasons.js
CHANGED
|
@@ -47,6 +47,7 @@ const OTHERS = [
|
|
|
47
47
|
validation("mail-findings.stale", "mail findings cite mail that changed since it was read; stage a new batch"),
|
|
48
48
|
validation("mail-findings.partial", "a cited email is not stored whole yet; cite it once it is"),
|
|
49
49
|
validation("evidence-findings.dedicated-review", "review evidence findings through the dedicated findings command"),
|
|
50
|
+
validation("mail-findings.dedicated-review", "review mail findings through the dedicated findings command"),
|
|
50
51
|
validation("document.changed", "the document changed while it was read; nothing was saved"),
|
|
51
52
|
["document.not-imported", "not_found", "the document is not imported in this source account"],
|
|
52
53
|
["extraction.invalid-proposals", "invalid_response", "the model's memory proposals could not be used"],
|
|
@@ -54,6 +55,11 @@ const OTHERS = [
|
|
|
54
55
|
validation("file.locked", "another process holds the file's lock"),
|
|
55
56
|
["mail.source-failed", "provider_error", "the mail server refused or did not complete a request"],
|
|
56
57
|
["mail.search-refused", "provider_error", "the mail server refused to search a folder"],
|
|
58
|
+
[
|
|
59
|
+
"mail.attachments-unread",
|
|
60
|
+
"provider_unavailable",
|
|
61
|
+
"the email could not be read again, so its skipped attachments have no text",
|
|
62
|
+
],
|
|
57
63
|
["mirror.partial", "provider_error", "some mirrored files were not synced"],
|
|
58
64
|
["profile.wrong-account", "authentication_error", "the signed-in source account does not match this profile"],
|
|
59
65
|
validation("push.too-many-files", "the folder holds more files than one push takes"),
|
|
@@ -218,8 +224,7 @@ const OTHERS = [
|
|
|
218
224
|
["task.stale", "configuration_error", "the task changed since it was read; read it again"],
|
|
219
225
|
validation("task.column", "the task beside which it moves is in another column than the status asked for"),
|
|
220
226
|
validation("task.dependency-cycle", "the task would depend on itself"),
|
|
221
|
-
validation("task.
|
|
222
|
-
validation("task.is-subtask", "a subtask moves to another project only when it is detached from its parent in the same write"),
|
|
227
|
+
validation("task.is-subtask", "a subtask moves to another project alone only when it is detached from its parent in the same write"),
|
|
223
228
|
validation("task.duplicate-candidates", "open tasks may be the same job: attach to one, or add it as new"),
|
|
224
229
|
validation("task.already-read", "the message was already read for tasks: a read again only updates and closes tasks unless --open-new"),
|
|
225
230
|
validation("task.certainty-required", "an agent closes a task with its certainty, 0 to 1"),
|
|
@@ -300,7 +305,6 @@ export const DETAILS = [
|
|
|
300
305
|
"operation_ids",
|
|
301
306
|
"text_limit",
|
|
302
307
|
"store_refused_in",
|
|
303
|
-
"subtasks",
|
|
304
308
|
"partial_output",
|
|
305
309
|
"parent",
|
|
306
310
|
"path",
|
|
@@ -3,14 +3,27 @@ import type { AttachmentInput, EmailAddress } from "../store/index.js";
|
|
|
3
3
|
import type { Address, ParsedMail } from "./parse.js";
|
|
4
4
|
import type { MailSyncResult } from "./sync.js";
|
|
5
5
|
export declare const MAX_ATTACHMENT_CHARS = 200000;
|
|
6
|
+
/** Whether a sync reads an email's attachments into the index, and the largest file it reads. */
|
|
7
|
+
export interface MailAttachmentPolicy {
|
|
8
|
+
read: boolean;
|
|
9
|
+
maxBytes: number;
|
|
10
|
+
}
|
|
11
|
+
/** On, up to 10 MB a file: ordinary documents and scans are read, a large archive or video is not. */
|
|
12
|
+
export declare const DEFAULT_ATTACHMENT_POLICY: MailAttachmentPolicy;
|
|
13
|
+
/** Why a policy left an attachment unread; `readEmailWhole` reads it anyway. */
|
|
14
|
+
export declare const POLICY_SKIPS: readonly ["not-read", "too-large"];
|
|
6
15
|
/** One chunk of raw mail is held in memory at a time. */
|
|
7
16
|
export declare const FETCH_CHUNK = 50;
|
|
8
17
|
export declare const addressOf: ({ email, name }: Address) => EmailAddress;
|
|
9
18
|
export type AttachmentLog = NonNullable<MailSyncResult["attachments"]>;
|
|
10
|
-
/**
|
|
11
|
-
|
|
19
|
+
/**
|
|
20
|
+
* A parsed email's attachments as the store keeps them, each with its text or why it has none. Without `policy` every
|
|
21
|
+
* attachment is read, whatever its size.
|
|
22
|
+
*/
|
|
23
|
+
export declare const readAttachments: (mail: ParsedMail, messageId: string, { loadEngine, maxAttachmentChars, at, signal, policy, }: {
|
|
12
24
|
loadEngine: LoadEngine;
|
|
13
25
|
maxAttachmentChars: number;
|
|
14
26
|
at: number;
|
|
15
27
|
signal?: AbortSignal;
|
|
28
|
+
policy?: MailAttachmentPolicy;
|
|
16
29
|
}, log: AttachmentLog) => Promise<AttachmentInput[]>;
|
package/dist/mail/attachments.js
CHANGED
|
@@ -1,17 +1,33 @@
|
|
|
1
1
|
import { extractText } from "../attachments/extract.js";
|
|
2
2
|
export const MAX_ATTACHMENT_CHARS = 200_000;
|
|
3
|
+
/** On, up to 10 MB a file: ordinary documents and scans are read, a large archive or video is not. */
|
|
4
|
+
export const DEFAULT_ATTACHMENT_POLICY = { read: true, maxBytes: 10 * 1024 * 1024 };
|
|
5
|
+
/** Why a policy left an attachment unread; `readEmailWhole` reads it anyway. */
|
|
6
|
+
export const POLICY_SKIPS = ["not-read", "too-large"];
|
|
3
7
|
/** One chunk of raw mail is held in memory at a time. */
|
|
4
8
|
export const FETCH_CHUNK = 50;
|
|
5
9
|
export const addressOf = ({ email, name }) => ({ address: email, name });
|
|
6
|
-
/**
|
|
7
|
-
|
|
10
|
+
/**
|
|
11
|
+
* A parsed email's attachments as the store keeps them, each with its text or why it has none. Without `policy` every
|
|
12
|
+
* attachment is read, whatever its size.
|
|
13
|
+
*/
|
|
14
|
+
export const readAttachments = async (mail, messageId, { loadEngine, maxAttachmentChars, at, signal, policy, }, log) => {
|
|
8
15
|
const files = [];
|
|
9
16
|
for (const [position, part] of mail.attachments.entries()) {
|
|
10
17
|
if (signal?.aborted)
|
|
11
18
|
throw signal.reason;
|
|
19
|
+
const skipped = part.bytes === null || policy === undefined
|
|
20
|
+
? undefined
|
|
21
|
+
: !policy.read
|
|
22
|
+
? "not-read"
|
|
23
|
+
: part.bytes.byteLength > policy.maxBytes
|
|
24
|
+
? "too-large"
|
|
25
|
+
: undefined;
|
|
12
26
|
const extraction = part.bytes === null
|
|
13
27
|
? { status: "unavailable" }
|
|
14
|
-
:
|
|
28
|
+
: skipped
|
|
29
|
+
? { status: skipped }
|
|
30
|
+
: await extractText(part.bytes, { kind: "file", name: part.name, mime: part.mime, path: part.name }, loadEngine, signal);
|
|
15
31
|
log.push({ message: messageId, part: part.id, status: extraction.status });
|
|
16
32
|
const extracted = extraction.status === "extracted" ? extraction : undefined;
|
|
17
33
|
files.push({
|
package/dist/mail/cli/index.d.ts
CHANGED
|
@@ -3,7 +3,22 @@ import { type MailServerAccess } from "../../mail/server-search.js";
|
|
|
3
3
|
import type { AppIdentity } from "../../ports/app.js";
|
|
4
4
|
import { type AccountKey, type MessageStore } from "../../store/store.js";
|
|
5
5
|
export { mailMark, markItem, markText } from "./marks.js";
|
|
6
|
-
export { MAIL_REVIEW_QUERY, MAIL_REVIEW_STEPS } from "./review.js";
|
|
6
|
+
export { MAIL_REVIEW_QUERY, MAIL_REVIEW_STEPS, mailReviewSteps } from "./review.js";
|
|
7
|
+
/**
|
|
8
|
+
* Where a host mounted `review`, `messages acknowledge` and `conversations show`, and the option that names one
|
|
9
|
+
* mailbox, so the steps a review hands on run there. A mail CLI leaves it out: its profile names the mailbox.
|
|
10
|
+
*/
|
|
11
|
+
export interface MailMount {
|
|
12
|
+
review?: string;
|
|
13
|
+
acknowledge?: string;
|
|
14
|
+
/** `null`: the host mounts no thread read, so a review offers none. */
|
|
15
|
+
conversation?: string | null;
|
|
16
|
+
/** In snake_case, as a step names it: memo's `source`, with `email:<account>`. */
|
|
17
|
+
mailbox?: {
|
|
18
|
+
option: string;
|
|
19
|
+
value: (mailbox: AccountKey) => string;
|
|
20
|
+
};
|
|
21
|
+
}
|
|
7
22
|
/** What a mail CLI hands the shared commands: how to open the store for one run, and whose mail it reads. */
|
|
8
23
|
export interface MailReads {
|
|
9
24
|
app: AppIdentity;
|
|
@@ -14,8 +29,14 @@ export interface MailReads {
|
|
|
14
29
|
read: <T>(command: Command, work: (store: MessageStore, mailbox: AccountKey) => Promise<T>) => Promise<T>;
|
|
15
30
|
/** The mailbox's server, for `search messages --backend`; without it the search reads the store only. */
|
|
16
31
|
server?: (command: Command) => MailServerAccess;
|
|
32
|
+
mount?: MailMount;
|
|
17
33
|
/** How `--server-time` help states its default when a provider's own differs (`MailServerAccess.timeMs`). */
|
|
18
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>;
|
|
19
40
|
}
|
|
20
41
|
export declare const THREAD_QUERY: {
|
|
21
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";
|
|
@@ -21,13 +22,21 @@ import { queryFilter, THREAD_COLUMNS } from "../../store/store.js";
|
|
|
21
22
|
import { acknowledgeCommand } from "./marks.js";
|
|
22
23
|
import { mailReviewCommand } from "./review.js";
|
|
23
24
|
export { mailMark, markItem, markText } from "./marks.js";
|
|
24
|
-
export { MAIL_REVIEW_QUERY, MAIL_REVIEW_STEPS } from "./review.js";
|
|
25
|
+
export { MAIL_REVIEW_QUERY, MAIL_REVIEW_STEPS, mailReviewSteps } from "./review.js";
|
|
25
26
|
/** A locked or broken store must fail the command, not read as "nothing stored yet". */
|
|
26
27
|
const absentAccount = (error) => {
|
|
27
28
|
if (error instanceof CliError && error.code === "not_found")
|
|
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;
|
|
@@ -1,8 +1,11 @@
|
|
|
1
|
+
import { type StepDefinition } from "@wirecat/cli-base/standards";
|
|
1
2
|
import { Command } from "commander";
|
|
2
|
-
import type { MailReads } from "./index.js";
|
|
3
|
+
import type { MailMount, MailReads } from "./index.js";
|
|
3
4
|
/** Where a mail review starts: a time only; one thread is `conversations show`. */
|
|
4
5
|
export declare const MAIL_REVIEW_QUERY: import("@wirecat/cli-base/query").QueryRegistry;
|
|
5
|
-
/** The mail review's steps; a host lists them beside its own so its step checks know them. */
|
|
6
|
+
/** The mail review's steps where a host mounted them; a host lists them beside its own so its step checks know them. */
|
|
7
|
+
export declare const mailReviewSteps: (mount?: MailMount) => StepDefinition[];
|
|
8
|
+
/** The steps of a mail CLI, whose profile names the mailbox. */
|
|
6
9
|
export declare const MAIL_REVIEW_STEPS: ({
|
|
7
10
|
id: string;
|
|
8
11
|
kind: "command";
|