@wirecat/cli-core 0.476.0 → 0.477.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 +30 -1
- package/dist/calendar/mcp/index.d.ts +12 -12
- package/dist/cli/index.d.ts +1 -1
- package/dist/cli/index.js +1 -1
- package/dist/cli/messenger/account-command.js +10 -8
- package/dist/cli/messenger/catch-up-answers.d.ts +14 -0
- package/dist/cli/messenger/chat-answers.d.ts +8 -2
- package/dist/cli/messenger/chat-answers.js +43 -0
- package/dist/cli/messenger/contacts-command.js +20 -25
- package/dist/cli/messenger/context.d.ts +2 -0
- package/dist/cli/messenger/conversation-answers.d.ts +21 -0
- package/dist/cli/messenger/message-answers.d.ts +21 -0
- package/dist/cli/messenger/message-items.js +8 -0
- package/dist/cli/messenger/message-writes.d.ts +42 -0
- package/dist/cli/messenger/people-queries.d.ts +2 -0
- package/dist/cli/messenger/people-queries.js +7 -1
- package/dist/cli/messenger/reactions-command.js +38 -2
- package/dist/cli/messenger/serve-relay.d.ts +1 -0
- package/dist/domain/models.d.ts +22 -3
- package/dist/entities/attachment.d.ts +8 -0
- package/dist/entities/attachment.js +9 -1
- package/dist/entities/contact-context.d.ts +42 -0
- package/dist/entities/contact-read.d.ts +15 -25
- package/dist/entities/contact-read.js +4 -15
- package/dist/entities/contact.d.ts +103 -134
- package/dist/entities/contact.js +13 -2
- package/dist/entities/conversation-results.d.ts +42 -0
- package/dist/entities/evidence.d.ts +168 -0
- package/dist/entities/index.d.ts +511 -201
- package/dist/entities/index.js +4 -3
- package/dist/entities/listener.d.ts +84 -0
- package/dist/entities/message-context.d.ts +63 -0
- package/dist/entities/message-write.d.ts +84 -0
- package/dist/entities/message.d.ts +21 -0
- package/dist/entities/reaction.d.ts +12 -0
- package/dist/entities/reaction.js +9 -0
- package/dist/entities/store-records.d.ts +21 -0
- package/dist/errors/reasons.js +2 -0
- package/dist/meetings/mcp/index.d.ts +15 -15
- package/dist/ports/messenger.d.ts +13 -2
- package/dist/render/markdown.js +4 -0
- package/dist/render/messages.js +7 -2
- package/dist/services/account.d.ts +1 -1
- package/dist/services/account.js +1 -2
- package/dist/services/people.d.ts +8 -5
- package/dist/services/people.js +6 -3
- package/dist/services/person-profile.d.ts +4 -3
- package/dist/services/person-profile.js +14 -3
- package/dist/store/sqlite/manifest.js +1 -0
- package/dist/store/sqlite/messages.js +5 -1
- package/dist/store/sqlite/migrations.generated.js +6 -0
- package/dist/store/sqlite/reads.js +1 -0
- package/dist/store/sqlite/schema.d.ts +16 -0
- package/dist/store/sqlite/schema.js +1 -0
- package/package.json +1 -1
- package/parity.json +20 -10
|
@@ -86,6 +86,13 @@ export declare const storeExport: v.UnionSchema<[v.StrictObjectSchema<{
|
|
|
86
86
|
readonly error: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
|
|
87
87
|
}, undefined>, undefined>;
|
|
88
88
|
readonly local_path: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
|
|
89
|
+
readonly contact: v.OptionalSchema<v.StrictObjectSchema<{
|
|
90
|
+
readonly name: v.StringSchema<undefined>;
|
|
91
|
+
readonly first_name: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
|
|
92
|
+
readonly last_name: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
|
|
93
|
+
readonly phone: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
|
|
94
|
+
readonly user_id: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>, undefined>;
|
|
95
|
+
}, undefined>, undefined>;
|
|
89
96
|
readonly buttons: v.OptionalSchema<v.ArraySchema<v.ArraySchema<v.StrictObjectSchema<{
|
|
90
97
|
readonly kind: v.PicklistSchema<["callback", "link", "message", "chat", "contact", "location", "app", "clipboard", "other"], undefined>;
|
|
91
98
|
readonly text: v.StringSchema<undefined>;
|
|
@@ -118,6 +125,13 @@ export declare const storeExport: v.UnionSchema<[v.StrictObjectSchema<{
|
|
|
118
125
|
readonly error: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
|
|
119
126
|
}, undefined>, undefined>;
|
|
120
127
|
readonly local_path: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
|
|
128
|
+
readonly contact: v.OptionalSchema<v.StrictObjectSchema<{
|
|
129
|
+
readonly name: v.StringSchema<undefined>;
|
|
130
|
+
readonly first_name: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
|
|
131
|
+
readonly last_name: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
|
|
132
|
+
readonly phone: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
|
|
133
|
+
readonly user_id: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>, undefined>;
|
|
134
|
+
}, undefined>, undefined>;
|
|
121
135
|
readonly buttons: v.OptionalSchema<v.ArraySchema<v.ArraySchema<v.StrictObjectSchema<{
|
|
122
136
|
readonly kind: v.PicklistSchema<["callback", "link", "message", "chat", "contact", "location", "app", "clipboard", "other"], undefined>;
|
|
123
137
|
readonly text: v.StringSchema<undefined>;
|
|
@@ -153,6 +167,13 @@ export declare const storeExport: v.UnionSchema<[v.StrictObjectSchema<{
|
|
|
153
167
|
readonly error: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
|
|
154
168
|
}, undefined>, undefined>;
|
|
155
169
|
readonly local_path: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
|
|
170
|
+
readonly contact: v.OptionalSchema<v.StrictObjectSchema<{
|
|
171
|
+
readonly name: v.StringSchema<undefined>;
|
|
172
|
+
readonly first_name: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
|
|
173
|
+
readonly last_name: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
|
|
174
|
+
readonly phone: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
|
|
175
|
+
readonly user_id: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>, undefined>;
|
|
176
|
+
}, undefined>, undefined>;
|
|
156
177
|
readonly buttons: v.OptionalSchema<v.ArraySchema<v.ArraySchema<v.StrictObjectSchema<{
|
|
157
178
|
readonly kind: v.PicklistSchema<["callback", "link", "message", "chat", "contact", "location", "app", "clipboard", "other"], undefined>;
|
|
158
179
|
readonly text: v.StringSchema<undefined>;
|
package/dist/errors/reasons.js
CHANGED
|
@@ -99,6 +99,8 @@ const OTHERS = [
|
|
|
99
99
|
validation("tag-review.required", "the tag needs the owner's review first"),
|
|
100
100
|
["tag-review.stale", "configuration_error", "the tag review changed meanwhile"],
|
|
101
101
|
validation("tag.invalid", "the tag is not valid"),
|
|
102
|
+
["reactions.list-hidden", "permission_error", "the chat does not let its members see who reacted"],
|
|
103
|
+
["reactions.broadcast", "permission_error", "a channel does not show who reacted to its posts"],
|
|
102
104
|
validation("task.category-unknown", "the category is not in the task category list"),
|
|
103
105
|
validation("task.claimed", "someone else holds the task"),
|
|
104
106
|
validation("task.closed", "the task is already closed"),
|
|
@@ -38,6 +38,7 @@ export declare const meetingTools: ({
|
|
|
38
38
|
max_read_bytes?: undefined;
|
|
39
39
|
cursor?: undefined;
|
|
40
40
|
} | {
|
|
41
|
+
limit?: undefined;
|
|
41
42
|
event_id?: undefined;
|
|
42
43
|
series_id?: undefined;
|
|
43
44
|
page?: undefined;
|
|
@@ -53,11 +54,11 @@ export declare const meetingTools: ({
|
|
|
53
54
|
format?: undefined;
|
|
54
55
|
transcript_id?: undefined;
|
|
55
56
|
query?: undefined;
|
|
56
|
-
limit?: undefined;
|
|
57
57
|
scan_limit?: undefined;
|
|
58
58
|
max_read_bytes?: undefined;
|
|
59
59
|
cursor?: undefined;
|
|
60
60
|
} | {
|
|
61
|
+
limit?: undefined;
|
|
61
62
|
event_id?: undefined;
|
|
62
63
|
series_id?: undefined;
|
|
63
64
|
page?: undefined;
|
|
@@ -75,11 +76,11 @@ export declare const meetingTools: ({
|
|
|
75
76
|
format?: undefined;
|
|
76
77
|
transcript_id?: undefined;
|
|
77
78
|
query?: undefined;
|
|
78
|
-
limit?: undefined;
|
|
79
79
|
scan_limit?: undefined;
|
|
80
80
|
max_read_bytes?: undefined;
|
|
81
81
|
cursor?: undefined;
|
|
82
82
|
} | {
|
|
83
|
+
limit?: undefined;
|
|
83
84
|
event_id?: undefined;
|
|
84
85
|
series_id?: undefined;
|
|
85
86
|
page?: undefined;
|
|
@@ -101,7 +102,6 @@ export declare const meetingTools: ({
|
|
|
101
102
|
minimum: number;
|
|
102
103
|
};
|
|
103
104
|
query?: undefined;
|
|
104
|
-
limit?: undefined;
|
|
105
105
|
scan_limit?: undefined;
|
|
106
106
|
max_read_bytes?: undefined;
|
|
107
107
|
cursor?: undefined;
|
|
@@ -188,6 +188,7 @@ export declare const meetingTools: ({
|
|
|
188
188
|
max_read_bytes?: undefined;
|
|
189
189
|
cursor?: undefined;
|
|
190
190
|
} | {
|
|
191
|
+
limit?: undefined;
|
|
191
192
|
event_id?: undefined;
|
|
192
193
|
series_id?: undefined;
|
|
193
194
|
page?: undefined;
|
|
@@ -203,11 +204,11 @@ export declare const meetingTools: ({
|
|
|
203
204
|
format?: undefined;
|
|
204
205
|
transcript_id?: undefined;
|
|
205
206
|
query?: undefined;
|
|
206
|
-
limit?: undefined;
|
|
207
207
|
scan_limit?: undefined;
|
|
208
208
|
max_read_bytes?: undefined;
|
|
209
209
|
cursor?: undefined;
|
|
210
210
|
} | {
|
|
211
|
+
limit?: undefined;
|
|
211
212
|
event_id?: undefined;
|
|
212
213
|
series_id?: undefined;
|
|
213
214
|
page?: undefined;
|
|
@@ -225,11 +226,11 @@ export declare const meetingTools: ({
|
|
|
225
226
|
format?: undefined;
|
|
226
227
|
transcript_id?: undefined;
|
|
227
228
|
query?: undefined;
|
|
228
|
-
limit?: undefined;
|
|
229
229
|
scan_limit?: undefined;
|
|
230
230
|
max_read_bytes?: undefined;
|
|
231
231
|
cursor?: undefined;
|
|
232
232
|
} | {
|
|
233
|
+
limit?: undefined;
|
|
233
234
|
event_id?: undefined;
|
|
234
235
|
series_id?: undefined;
|
|
235
236
|
page?: undefined;
|
|
@@ -251,7 +252,6 @@ export declare const meetingTools: ({
|
|
|
251
252
|
minimum: number;
|
|
252
253
|
};
|
|
253
254
|
query?: undefined;
|
|
254
|
-
limit?: undefined;
|
|
255
255
|
scan_limit?: undefined;
|
|
256
256
|
max_read_bytes?: undefined;
|
|
257
257
|
cursor?: undefined;
|
|
@@ -338,6 +338,7 @@ export declare const meetingTools: ({
|
|
|
338
338
|
max_read_bytes?: undefined;
|
|
339
339
|
cursor?: undefined;
|
|
340
340
|
} | {
|
|
341
|
+
limit?: undefined;
|
|
341
342
|
event_id?: undefined;
|
|
342
343
|
series_id?: undefined;
|
|
343
344
|
page?: undefined;
|
|
@@ -353,11 +354,11 @@ export declare const meetingTools: ({
|
|
|
353
354
|
format?: undefined;
|
|
354
355
|
transcript_id?: undefined;
|
|
355
356
|
query?: undefined;
|
|
356
|
-
limit?: undefined;
|
|
357
357
|
scan_limit?: undefined;
|
|
358
358
|
max_read_bytes?: undefined;
|
|
359
359
|
cursor?: undefined;
|
|
360
360
|
} | {
|
|
361
|
+
limit?: undefined;
|
|
361
362
|
event_id?: undefined;
|
|
362
363
|
series_id?: undefined;
|
|
363
364
|
page?: undefined;
|
|
@@ -375,11 +376,11 @@ export declare const meetingTools: ({
|
|
|
375
376
|
format?: undefined;
|
|
376
377
|
transcript_id?: undefined;
|
|
377
378
|
query?: undefined;
|
|
378
|
-
limit?: undefined;
|
|
379
379
|
scan_limit?: undefined;
|
|
380
380
|
max_read_bytes?: undefined;
|
|
381
381
|
cursor?: undefined;
|
|
382
382
|
} | {
|
|
383
|
+
limit?: undefined;
|
|
383
384
|
event_id?: undefined;
|
|
384
385
|
series_id?: undefined;
|
|
385
386
|
page?: undefined;
|
|
@@ -401,7 +402,6 @@ export declare const meetingTools: ({
|
|
|
401
402
|
minimum: number;
|
|
402
403
|
};
|
|
403
404
|
query?: undefined;
|
|
404
|
-
limit?: undefined;
|
|
405
405
|
scan_limit?: undefined;
|
|
406
406
|
max_read_bytes?: undefined;
|
|
407
407
|
cursor?: undefined;
|
|
@@ -488,6 +488,7 @@ export declare const meetingTools: ({
|
|
|
488
488
|
max_read_bytes?: undefined;
|
|
489
489
|
cursor?: undefined;
|
|
490
490
|
} | {
|
|
491
|
+
limit?: undefined;
|
|
491
492
|
event_id?: undefined;
|
|
492
493
|
series_id?: undefined;
|
|
493
494
|
page?: undefined;
|
|
@@ -503,11 +504,11 @@ export declare const meetingTools: ({
|
|
|
503
504
|
format?: undefined;
|
|
504
505
|
transcript_id?: undefined;
|
|
505
506
|
query?: undefined;
|
|
506
|
-
limit?: undefined;
|
|
507
507
|
scan_limit?: undefined;
|
|
508
508
|
max_read_bytes?: undefined;
|
|
509
509
|
cursor?: undefined;
|
|
510
510
|
} | {
|
|
511
|
+
limit?: undefined;
|
|
511
512
|
event_id?: undefined;
|
|
512
513
|
series_id?: undefined;
|
|
513
514
|
page?: undefined;
|
|
@@ -525,11 +526,11 @@ export declare const meetingTools: ({
|
|
|
525
526
|
format?: undefined;
|
|
526
527
|
transcript_id?: undefined;
|
|
527
528
|
query?: undefined;
|
|
528
|
-
limit?: undefined;
|
|
529
529
|
scan_limit?: undefined;
|
|
530
530
|
max_read_bytes?: undefined;
|
|
531
531
|
cursor?: undefined;
|
|
532
532
|
} | {
|
|
533
|
+
limit?: undefined;
|
|
533
534
|
event_id?: undefined;
|
|
534
535
|
series_id?: undefined;
|
|
535
536
|
page?: undefined;
|
|
@@ -551,7 +552,6 @@ export declare const meetingTools: ({
|
|
|
551
552
|
minimum: number;
|
|
552
553
|
};
|
|
553
554
|
query?: undefined;
|
|
554
|
-
limit?: undefined;
|
|
555
555
|
scan_limit?: undefined;
|
|
556
556
|
max_read_bytes?: undefined;
|
|
557
557
|
cursor?: undefined;
|
|
@@ -638,6 +638,7 @@ export declare const meetingTools: ({
|
|
|
638
638
|
max_read_bytes?: undefined;
|
|
639
639
|
cursor?: undefined;
|
|
640
640
|
} | {
|
|
641
|
+
limit?: undefined;
|
|
641
642
|
event_id?: undefined;
|
|
642
643
|
series_id?: undefined;
|
|
643
644
|
page?: undefined;
|
|
@@ -653,11 +654,11 @@ export declare const meetingTools: ({
|
|
|
653
654
|
format?: undefined;
|
|
654
655
|
transcript_id?: undefined;
|
|
655
656
|
query?: undefined;
|
|
656
|
-
limit?: undefined;
|
|
657
657
|
scan_limit?: undefined;
|
|
658
658
|
max_read_bytes?: undefined;
|
|
659
659
|
cursor?: undefined;
|
|
660
660
|
} | {
|
|
661
|
+
limit?: undefined;
|
|
661
662
|
event_id?: undefined;
|
|
662
663
|
series_id?: undefined;
|
|
663
664
|
page?: undefined;
|
|
@@ -675,11 +676,11 @@ export declare const meetingTools: ({
|
|
|
675
676
|
format?: undefined;
|
|
676
677
|
transcript_id?: undefined;
|
|
677
678
|
query?: undefined;
|
|
678
|
-
limit?: undefined;
|
|
679
679
|
scan_limit?: undefined;
|
|
680
680
|
max_read_bytes?: undefined;
|
|
681
681
|
cursor?: undefined;
|
|
682
682
|
} | {
|
|
683
|
+
limit?: undefined;
|
|
683
684
|
event_id?: undefined;
|
|
684
685
|
series_id?: undefined;
|
|
685
686
|
page?: undefined;
|
|
@@ -701,7 +702,6 @@ export declare const meetingTools: ({
|
|
|
701
702
|
minimum: number;
|
|
702
703
|
};
|
|
703
704
|
query?: undefined;
|
|
704
|
-
limit?: undefined;
|
|
705
705
|
scan_limit?: undefined;
|
|
706
706
|
max_read_bytes?: undefined;
|
|
707
707
|
cursor?: undefined;
|
|
@@ -3,7 +3,7 @@ import type { CounterField, CounterObservations } from "../domain/counters.js";
|
|
|
3
3
|
import type { HtmlFormatting, MarkdownFormatting, TextSpan } from "../domain/formatting.js";
|
|
4
4
|
import type { Markup } from "../domain/markdown.js";
|
|
5
5
|
import type { MessagePermalink } from "../domain/message-link.js";
|
|
6
|
-
import type { Account, AccountSession, AdminRight, Button, CallRecord, Chat, ChatCard, ChatEvent, ChatEvents, ChatUpdate, Discussion, Folder, FolderChange, FolderRules, GroupCard, GroupChange, GroupMember, Id, InviteLink, InviteLinkChange, JoinRequest, LinkTarget, MediaKind, Member, Message, MessageEvent, MessageHit, OfficialChatStats, Page, PersonCard, PersonReaction, PhoneBookEntry, Poll, PollVote, PrivacySettings, ProfileFacts, ProviderMetadata, SenderIdentity, Sticker, StickerSet, Topic, TopicChange, WindowedMessage } from "../domain/models.js";
|
|
6
|
+
import type { Account, AccountSession, AdminRight, Button, CallRecord, Chat, ChatCard, ChatEvent, ChatEvents, ChatUpdate, Discussion, Folder, FolderChange, FolderRules, GroupCard, GroupChange, GroupMember, Id, InviteLink, InviteLinkChange, JoinRequest, LinkTarget, MediaKind, Member, Message, MessageEvent, MessageHit, OfficialChatStats, Page, PersonCard, PersonReaction, PhoneBookEntry, Poll, PollVote, PrivacySettings, ProfileFacts, ProviderMetadata, Reactor, SenderIdentity, Sticker, StickerSet, Topic, TopicChange, WindowedMessage } from "../domain/models.js";
|
|
7
7
|
/** One attachment's bytes, fetched over the adapter's connection when `bytes` is read — so read it before the command closes. */
|
|
8
8
|
export interface RemoteFile {
|
|
9
9
|
kind: string;
|
|
@@ -237,6 +237,17 @@ export interface MessageStars {
|
|
|
237
237
|
export interface MessageReactions {
|
|
238
238
|
/** The owner's reaction on one message: an emoji replaces the one there was, `null` takes it off. */
|
|
239
239
|
react(chatId: Id, messageId: Id, emoji: string | null): Promise<void>;
|
|
240
|
+
/**
|
|
241
|
+
* Who reacted, newest first; `emoji` keeps one reaction, `cursor` is the last page's. Refuses with a
|
|
242
|
+
* `reactions.*` reason where the messenger hides the list, rather than answering with none.
|
|
243
|
+
*/
|
|
244
|
+
reactors?(chatId: Id, messageId: Id, window: {
|
|
245
|
+
limit: number;
|
|
246
|
+
emoji?: string;
|
|
247
|
+
cursor?: string;
|
|
248
|
+
}): Promise<Page<Reactor> & {
|
|
249
|
+
cursor?: string;
|
|
250
|
+
}>;
|
|
240
251
|
}
|
|
241
252
|
export interface ReadState {
|
|
242
253
|
/** Marks the chat read up to `until`, or to its newest message; the other side sees it. */
|
|
@@ -493,7 +504,7 @@ export interface AccountTools {
|
|
|
493
504
|
/** The owner's contact list as the messenger keeps it — the address book, not the chats. */
|
|
494
505
|
addressBook(): Promise<Member[]>;
|
|
495
506
|
}
|
|
496
|
-
/** Everything the messenger says about one person — what `contacts
|
|
507
|
+
/** Everything the messenger says about one person — what `contacts show` shows. */
|
|
497
508
|
export interface PersonProfiles {
|
|
498
509
|
/** Reading it tells them nothing. A chat that is not a person is refused. */
|
|
499
510
|
profile(person: string): Promise<ProfileFacts>;
|
package/dist/render/markdown.js
CHANGED
|
@@ -51,6 +51,10 @@ const attachmentLine = (attachment) => {
|
|
|
51
51
|
const buttons = attachment.buttons.flat().map((button, index) => `${index + 1} ${literal(singleLine(button.text))}`);
|
|
52
52
|
return `buttons: ${buttons.join(" · ")}`;
|
|
53
53
|
}
|
|
54
|
+
if (attachment.contact) {
|
|
55
|
+
const { name, phone } = attachment.contact;
|
|
56
|
+
return `contact: ${[name, phone].flatMap((part) => (part ? [literal(singleLine(part))] : [])).join(", ")}`;
|
|
57
|
+
}
|
|
54
58
|
const label = literal(singleLine(attachment.title ?? attachment.name ?? attachment.kind));
|
|
55
59
|
if (attachment.url) {
|
|
56
60
|
try {
|
package/dist/render/messages.js
CHANGED
|
@@ -119,9 +119,14 @@ const attachmentLines = (attachments, paint, options) => {
|
|
|
119
119
|
.flatMap((attachment) => attachment.buttons ?? [])
|
|
120
120
|
.map((row) => paint("dim", row.map((button) => link(`[${++number} ${singleLine(button.text)}]`, button.url)).join(" ")));
|
|
121
121
|
const polls = attachments.flatMap((attachment) => (attachment.poll ? pollLines(attachment.poll) : []));
|
|
122
|
+
const cards = attachments.flatMap(({ contact }) => contact
|
|
123
|
+
? [
|
|
124
|
+
paint("dim", `👤 ${[contact.name, contact.phone].flatMap((part) => (part ? [singleLine(part)] : [])).join(" · ")}`),
|
|
125
|
+
]
|
|
126
|
+
: []);
|
|
122
127
|
const groups = new Map();
|
|
123
128
|
for (const attachment of attachments) {
|
|
124
|
-
if (attachment.buttons || attachment.poll)
|
|
129
|
+
if (attachment.buttons || attachment.poll || attachment.contact)
|
|
125
130
|
continue;
|
|
126
131
|
const key = singleLine(attachment.name ?? attachment.title ?? attachment.kind);
|
|
127
132
|
groups.set(key, [...(groups.get(key) ?? []), attachment]);
|
|
@@ -134,7 +139,7 @@ const attachmentLines = (attachments, paint, options) => {
|
|
|
134
139
|
const each = same.map((attachment, index) => link(String(index + 1), attachment.url)).join(" ");
|
|
135
140
|
return paint("dim", `📎 ${label} ×${same.length} ${each}`);
|
|
136
141
|
});
|
|
137
|
-
return [...polls, ...files, ...keyboard];
|
|
142
|
+
return [...polls, ...cards, ...files, ...keyboard];
|
|
138
143
|
};
|
|
139
144
|
/** `📊 question`, then each answer with the id a vote takes, its voters and ✓ on the owner's own, then the totals. */
|
|
140
145
|
export const pollLines = (poll) => {
|
|
@@ -4,7 +4,7 @@ import { type Operated } from "../sends/guarded.js";
|
|
|
4
4
|
import type { ServiceDeps } from "./deps.js";
|
|
5
5
|
/** The owner's own profile and logins. */
|
|
6
6
|
export interface AccountService {
|
|
7
|
-
/** The account as it now stands
|
|
7
|
+
/** The account as it now stands. */
|
|
8
8
|
update(change: ProfileChange): Promise<Operated<{
|
|
9
9
|
account: Account;
|
|
10
10
|
}>>;
|
package/dist/services/account.js
CHANGED
|
@@ -2,7 +2,6 @@ import { CliError } from "@wirecat/cli-base";
|
|
|
2
2
|
import { capability } from "../ports/messenger.js";
|
|
3
3
|
import { guardedWrite } from "../sends/guarded.js";
|
|
4
4
|
import { newOperationId } from "../sends/send-id.js";
|
|
5
|
-
import { maskedAccount } from "./people.js";
|
|
6
5
|
export const accountService = (deps) => {
|
|
7
6
|
const online = async (command) => {
|
|
8
7
|
if (deps.offline)
|
|
@@ -28,7 +27,7 @@ export const accountService = (deps) => {
|
|
|
28
27
|
const update = capability(await online("account update"), "updateProfile", "change the profile");
|
|
29
28
|
const operationId = newOperationId();
|
|
30
29
|
const account = await guardedWrite(deps.guard, { operationId, chatId: null, kind: "account", action: "profile" }, () => update(change));
|
|
31
|
-
return { operationId, account
|
|
30
|
+
return { operationId, account };
|
|
32
31
|
},
|
|
33
32
|
endOtherSessions: async () => {
|
|
34
33
|
const end = capability(await online("account sessions end"), "endOtherSessions", "end other sessions");
|
|
@@ -30,8 +30,11 @@ export interface PeopleService {
|
|
|
30
30
|
show(person: string, options?: {
|
|
31
31
|
notes?: boolean;
|
|
32
32
|
}): Promise<PersonCard>;
|
|
33
|
-
/**
|
|
34
|
-
|
|
33
|
+
/**
|
|
34
|
+
* What the messenger says about them, and their stored activity in each shared chat. `known`: their card, already
|
|
35
|
+
* read, which stands in for a messenger that has no profile to give.
|
|
36
|
+
*/
|
|
37
|
+
profile(person: string, known?: PersonCard): Promise<PersonProfile>;
|
|
35
38
|
/** `phone` as digits, parsed by the caller (`phoneOf`). */
|
|
36
39
|
lookup(phone: string): Promise<Member>;
|
|
37
40
|
/** The whole contact list from the messenger into the store: what was new, what changed. */
|
|
@@ -89,7 +92,7 @@ export declare const peopleService: (deps: ServiceDeps) => PeopleService;
|
|
|
89
92
|
*/
|
|
90
93
|
export declare const linkPeople: (store: MessageStore, account: AccountKey, person: string, other: string, method?: string) => Promise<PersonRecord>;
|
|
91
94
|
export declare const phoneOf: (typed: string) => string;
|
|
92
|
-
/**
|
|
93
|
-
export declare const
|
|
95
|
+
/** `--hide-phone`: the answer without the number, for output that will be pasted somewhere. */
|
|
96
|
+
export declare const withoutPhone: <T extends {
|
|
94
97
|
phone?: string | null;
|
|
95
|
-
}>(
|
|
98
|
+
}>(answer: T) => T;
|
package/dist/services/people.js
CHANGED
|
@@ -74,7 +74,7 @@ export const peopleService = (deps) => {
|
|
|
74
74
|
const held = await storeIfOpen(deps);
|
|
75
75
|
return localCard(held ? { ...card, chats: await sharedChats(held.store, held.account, card.id) } : card, notes);
|
|
76
76
|
},
|
|
77
|
-
profile: (person) => personProfile(deps, person),
|
|
77
|
+
profile: (person, known) => personProfile(deps, person, known),
|
|
78
78
|
context: async (person, options) => personContext(await deps.store(), await deps.account(), person, options),
|
|
79
79
|
prepare: async (person, options) => personPreparation(await deps.store(), await deps.account(), person, options),
|
|
80
80
|
timeline: async (person, options) => personTimeline(await deps.store(), await deps.account(), person, options),
|
|
@@ -256,5 +256,8 @@ const toContact = (chat) => ({
|
|
|
256
256
|
});
|
|
257
257
|
const byRecency = (a, b) => (b.lastMessagedAt ?? "").localeCompare(a.lastMessagedAt ?? "");
|
|
258
258
|
const byName = (a, b) => (a.name ?? "").localeCompare(b.name ?? "");
|
|
259
|
-
/**
|
|
260
|
-
export const
|
|
259
|
+
/** `--hide-phone`: the answer without the number, for output that will be pasted somewhere. */
|
|
260
|
+
export const withoutPhone = (answer) => {
|
|
261
|
+
const { phone: _phone, ...rest } = answer;
|
|
262
|
+
return rest;
|
|
263
|
+
};
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import type { PersonProfile } from "../domain/models.js";
|
|
1
|
+
import type { PersonCard, PersonProfile } from "../domain/models.js";
|
|
2
2
|
import { type ServiceDeps } from "./deps.js";
|
|
3
3
|
/**
|
|
4
4
|
* The person as the messenger describes them, and their stored activity in every chat shared with
|
|
5
5
|
* them. Online, one profile read; `--offline`, or a messenger that cannot describe a person, what
|
|
6
6
|
* the store has seen of them. Counts always come from the store, so they are a floor unless the
|
|
7
|
-
* chat is stored whole.
|
|
7
|
+
* chat is stored whole. `known` is the card already read for them: where the messenger has no profile to give, it is
|
|
8
|
+
* what is known, so a person the store has not saved is not looked up in it a second time.
|
|
8
9
|
*/
|
|
9
|
-
export declare const personProfile: (deps: ServiceDeps, person: string) => Promise<PersonProfile>;
|
|
10
|
+
export declare const personProfile: (deps: ServiceDeps, person: string, known?: PersonCard) => Promise<PersonProfile>;
|
|
@@ -4,14 +4,17 @@ import { storeIfOpen } from "./deps.js";
|
|
|
4
4
|
* The person as the messenger describes them, and their stored activity in every chat shared with
|
|
5
5
|
* them. Online, one profile read; `--offline`, or a messenger that cannot describe a person, what
|
|
6
6
|
* the store has seen of them. Counts always come from the store, so they are a floor unless the
|
|
7
|
-
* chat is stored whole.
|
|
7
|
+
* chat is stored whole. `known` is the card already read for them: where the messenger has no profile to give, it is
|
|
8
|
+
* what is known, so a person the store has not saved is not looked up in it a second time.
|
|
8
9
|
*/
|
|
9
|
-
export const personProfile = async (deps, person) => {
|
|
10
|
+
export const personProfile = async (deps, person, known) => {
|
|
10
11
|
const online = deps.offline ? undefined : await deps.connection();
|
|
11
12
|
const held = await storeIfOpen(deps);
|
|
12
13
|
const facts = online?.profile
|
|
13
14
|
? await online.profile(person)
|
|
14
|
-
:
|
|
15
|
+
: known
|
|
16
|
+
? factsOfCard(known)
|
|
17
|
+
: await storedFacts(held ?? { store: await deps.store(), account: await deps.account() }, person);
|
|
15
18
|
if (!held)
|
|
16
19
|
return { ...facts, chats: quiet(facts), aliases: [] };
|
|
17
20
|
return {
|
|
@@ -25,6 +28,14 @@ const pastOf = (facts, recorded, provider) => recorded
|
|
|
25
28
|
.filter(({ name, username }) => (name ?? null) !== facts.name || (username !== undefined && !facts.usernames.includes(username)))
|
|
26
29
|
.map((alias) => alias.username && provider === "telegram" ? { ...alias, link: `https://t.me/${alias.username}` } : alias)
|
|
27
30
|
.sort((a, b) => a.firstSeenAt.localeCompare(b.firstSeenAt));
|
|
31
|
+
const factsOfCard = ({ id, name, username, description, chats }) => ({
|
|
32
|
+
id,
|
|
33
|
+
name,
|
|
34
|
+
usernames: username ? [username] : [],
|
|
35
|
+
bio: description,
|
|
36
|
+
flags: {},
|
|
37
|
+
chats,
|
|
38
|
+
});
|
|
28
39
|
const storedFacts = async ({ store, account }, person) => {
|
|
29
40
|
const found = pickPerson(person, await store.people.people(account.provider, { account: account.account }));
|
|
30
41
|
const chats = await store.chats.chatsWith(account, found.id);
|
|
@@ -47,6 +47,7 @@ export const MANIFEST = [
|
|
|
47
47
|
{ name: "20261025182501_version-34-vector-index-triggers", version: 34, minCompatible: 34 },
|
|
48
48
|
{ name: "20261027102259_version-35-calendar-neutral", version: 35, minCompatible: 34 },
|
|
49
49
|
{ name: "20261027102302_version-35-calendar-neutral-data", version: 35, minCompatible: 34 },
|
|
50
|
+
{ name: "20261029162435_version-36-attachment-contact", version: 36, minCompatible: 34 },
|
|
50
51
|
];
|
|
51
52
|
export const generatedMigrations = (manifest = MANIFEST, generated = GENERATED) => {
|
|
52
53
|
const migrations = [];
|
|
@@ -38,6 +38,7 @@ const ATTACHMENT_FIELDS = [
|
|
|
38
38
|
"duration",
|
|
39
39
|
"providerRef",
|
|
40
40
|
"nameFolded",
|
|
41
|
+
"contact",
|
|
41
42
|
];
|
|
42
43
|
const placeholders = (names) => Object.fromEntries(names.map((name) => [name, sql.placeholder(name)]));
|
|
43
44
|
const prepare = (orm) => ({
|
|
@@ -78,7 +79,9 @@ const prepare = (orm) => ({
|
|
|
78
79
|
const column = attachments[name].name;
|
|
79
80
|
return [
|
|
80
81
|
name,
|
|
81
|
-
sql.raw(name === "providerRef"
|
|
82
|
+
sql.raw(name === "providerRef" || name === "contact"
|
|
83
|
+
? `coalesce(excluded.${column}, ${column})`
|
|
84
|
+
: `excluded.${column}`),
|
|
82
85
|
];
|
|
83
86
|
})),
|
|
84
87
|
})
|
|
@@ -224,6 +227,7 @@ export const upsertMessage = (context, key, accountKey, chatKey, message, via, s
|
|
|
224
227
|
height: attachment.height ?? null,
|
|
225
228
|
duration: attachment.duration ?? null,
|
|
226
229
|
providerRef: refOf(attachment.providerRef),
|
|
230
|
+
contact: attachment.contact ? JSON.stringify(attachment.contact) : null,
|
|
227
231
|
});
|
|
228
232
|
});
|
|
229
233
|
if (Number(heardFirst) > 0)
|
|
@@ -778,5 +778,11 @@ export const GENERATED = [
|
|
|
778
778
|
"UPDATE calendar_entry_participants SET response = 'needs-action' WHERE response = 'needsAction';",
|
|
779
779
|
"UPDATE calendars SET access_role = 'free-busy' WHERE access_role = 'freeBusyReader';"
|
|
780
780
|
]
|
|
781
|
+
},
|
|
782
|
+
{
|
|
783
|
+
"name": "20261029162435_version-36-attachment-contact",
|
|
784
|
+
"statements": [
|
|
785
|
+
"ALTER TABLE `attachments` ADD `contact` text;"
|
|
786
|
+
]
|
|
781
787
|
}
|
|
782
788
|
];
|
|
@@ -6552,6 +6552,22 @@ export declare const attachments: import("drizzle-orm/sqlite-core").SQLiteTableW
|
|
|
6552
6552
|
identity: undefined;
|
|
6553
6553
|
generated: undefined;
|
|
6554
6554
|
}, {}>;
|
|
6555
|
+
contact: import("drizzle-orm/sqlite-core").SQLiteColumn<{
|
|
6556
|
+
name: string;
|
|
6557
|
+
tableName: "attachments";
|
|
6558
|
+
dataType: "string";
|
|
6559
|
+
data: string;
|
|
6560
|
+
driverParam: string;
|
|
6561
|
+
notNull: false;
|
|
6562
|
+
hasDefault: false;
|
|
6563
|
+
isPrimaryKey: false;
|
|
6564
|
+
isAutoincrement: false;
|
|
6565
|
+
hasRuntimeDefault: false;
|
|
6566
|
+
enumValues: [string, ...string[]];
|
|
6567
|
+
baseColumn: never;
|
|
6568
|
+
identity: undefined;
|
|
6569
|
+
generated: undefined;
|
|
6570
|
+
}, {}>;
|
|
6555
6571
|
};
|
|
6556
6572
|
dialect: 'sqlite';
|
|
6557
6573
|
isAlias: false;
|
|
@@ -713,6 +713,7 @@ export const attachments = sqliteTable("attachments", {
|
|
|
713
713
|
/** `fold(name)`, `fold(local_path)`: SQLite's lower() folds ASCII only, so filters compare these. */
|
|
714
714
|
nameFolded: text("name_folded"),
|
|
715
715
|
localPathFolded: text("local_path_folded"),
|
|
716
|
+
contact: text("contact"),
|
|
716
717
|
}, (table) => [
|
|
717
718
|
unique().on(table.attachableType, table.attachableId, table.position),
|
|
718
719
|
index("attachments_by_name_folded").on(table.nameFolded),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wirecat/cli-core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.477.0",
|
|
4
4
|
"description": "The messenger-neutral half of a messaging CLI: domain model, message locators, rendering, name resolution, the SQLite seam, the command skeleton and shared read commands, the send guard, run records and the message store",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "Viacheslav Ptsarev",
|
package/parity.json
CHANGED
|
@@ -433,6 +433,9 @@
|
|
|
433
433
|
"value": "<on|off>",
|
|
434
434
|
"meaning": "hide online status and last seen"
|
|
435
435
|
},
|
|
436
|
+
"--hide-phone": {
|
|
437
|
+
"meaning": "leave the phone number out"
|
|
438
|
+
},
|
|
436
439
|
"--history": {
|
|
437
440
|
"meaning": "the people added also see the messages from before they came"
|
|
438
441
|
},
|
|
@@ -906,9 +909,6 @@
|
|
|
906
909
|
"value": "<id>",
|
|
907
910
|
"meaning": "the stickers in this set"
|
|
908
911
|
},
|
|
909
|
-
"--show-phone": {
|
|
910
|
-
"meaning": "print the whole phone number"
|
|
911
|
-
},
|
|
912
912
|
"--silent": {
|
|
913
913
|
"meaning": "deliver without a notification"
|
|
914
914
|
},
|
|
@@ -1268,7 +1268,7 @@
|
|
|
1268
1268
|
"account show": {
|
|
1269
1269
|
"in": "all",
|
|
1270
1270
|
"options": {
|
|
1271
|
-
"--
|
|
1271
|
+
"--hide-phone": "all"
|
|
1272
1272
|
}
|
|
1273
1273
|
},
|
|
1274
1274
|
"account update": {
|
|
@@ -1276,6 +1276,7 @@
|
|
|
1276
1276
|
"options": {
|
|
1277
1277
|
"--description": "all",
|
|
1278
1278
|
"--first-name": "all",
|
|
1279
|
+
"--hide-phone": "all",
|
|
1279
1280
|
"--last-name": "all",
|
|
1280
1281
|
"--photo": {
|
|
1281
1282
|
"in": "all",
|
|
@@ -2803,12 +2804,6 @@
|
|
|
2803
2804
|
"contacts import": {
|
|
2804
2805
|
"in": "all"
|
|
2805
2806
|
},
|
|
2806
|
-
"contacts info": {
|
|
2807
|
-
"in": "all",
|
|
2808
|
-
"options": {
|
|
2809
|
-
"--show-phone": "all"
|
|
2810
|
-
}
|
|
2811
|
-
},
|
|
2812
2807
|
"contacts link": {
|
|
2813
2808
|
"in": "all"
|
|
2814
2809
|
},
|
|
@@ -2868,6 +2863,7 @@
|
|
|
2868
2863
|
"contacts show": {
|
|
2869
2864
|
"in": "all",
|
|
2870
2865
|
"options": {
|
|
2866
|
+
"--hide-phone": "all",
|
|
2871
2867
|
"--with-notes": {
|
|
2872
2868
|
"in": "all"
|
|
2873
2869
|
}
|
|
@@ -3674,6 +3670,20 @@
|
|
|
3674
3670
|
"reactions add": {
|
|
3675
3671
|
"in": "all"
|
|
3676
3672
|
},
|
|
3673
|
+
"reactions list": {
|
|
3674
|
+
"in": ["tg"],
|
|
3675
|
+
"reason": "max-cli and whatsapp-cli do not list who reacted to a message",
|
|
3676
|
+
"options": {
|
|
3677
|
+
"--cursor": {
|
|
3678
|
+
"in": ["tg"],
|
|
3679
|
+
"reason": "max-cli and whatsapp-cli do not list who reacted to a message"
|
|
3680
|
+
},
|
|
3681
|
+
"--limit": {
|
|
3682
|
+
"in": ["tg"],
|
|
3683
|
+
"reason": "max-cli and whatsapp-cli do not list who reacted to a message"
|
|
3684
|
+
}
|
|
3685
|
+
}
|
|
3686
|
+
},
|
|
3677
3687
|
"reactions remove": {
|
|
3678
3688
|
"in": "all"
|
|
3679
3689
|
},
|