@wirecat/cli-core 0.476.0 → 0.478.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.
Files changed (66) hide show
  1. package/CHANGELOG.md +41 -0
  2. package/dist/calendar/mcp/index.d.ts +12 -12
  3. package/dist/cli/index.d.ts +1 -1
  4. package/dist/cli/index.js +1 -1
  5. package/dist/cli/messenger/account-command.js +10 -8
  6. package/dist/cli/messenger/catch-up-answers.d.ts +16 -0
  7. package/dist/cli/messenger/catch-up-answers.js +2 -1
  8. package/dist/cli/messenger/chat-answers.d.ts +8 -2
  9. package/dist/cli/messenger/chat-answers.js +43 -0
  10. package/dist/cli/messenger/contacts-command.js +20 -25
  11. package/dist/cli/messenger/context.d.ts +2 -0
  12. package/dist/cli/messenger/conversation-answers.d.ts +21 -0
  13. package/dist/cli/messenger/message-answers.d.ts +21 -0
  14. package/dist/cli/messenger/message-items.d.ts +1 -1
  15. package/dist/cli/messenger/message-items.js +10 -2
  16. package/dist/cli/messenger/message-writes.d.ts +42 -0
  17. package/dist/cli/messenger/people-queries.d.ts +2 -0
  18. package/dist/cli/messenger/people-queries.js +7 -1
  19. package/dist/cli/messenger/reactions-command.js +38 -2
  20. package/dist/cli/messenger/search-answers.js +5 -1
  21. package/dist/cli/messenger/serve-relay.d.ts +1 -0
  22. package/dist/domain/models.d.ts +24 -3
  23. package/dist/domain/models.js +2 -0
  24. package/dist/entities/attachment.d.ts +8 -0
  25. package/dist/entities/attachment.js +9 -1
  26. package/dist/entities/contact-context.d.ts +42 -0
  27. package/dist/entities/contact-read.d.ts +15 -25
  28. package/dist/entities/contact-read.js +4 -15
  29. package/dist/entities/contact.d.ts +103 -134
  30. package/dist/entities/contact.js +13 -2
  31. package/dist/entities/conversation-results.d.ts +42 -0
  32. package/dist/entities/evidence.d.ts +168 -0
  33. package/dist/entities/hit.d.ts +2 -0
  34. package/dist/entities/hit.js +2 -0
  35. package/dist/entities/index.d.ts +519 -202
  36. package/dist/entities/index.js +6 -3
  37. package/dist/entities/listener.d.ts +84 -0
  38. package/dist/entities/message-context.d.ts +63 -0
  39. package/dist/entities/message-write.d.ts +84 -0
  40. package/dist/entities/message.d.ts +21 -0
  41. package/dist/entities/reaction.d.ts +12 -0
  42. package/dist/entities/reaction.js +9 -0
  43. package/dist/entities/store-records.d.ts +21 -0
  44. package/dist/errors/reasons.js +2 -0
  45. package/dist/meetings/mcp/index.d.ts +15 -15
  46. package/dist/ports/messenger.d.ts +13 -2
  47. package/dist/render/markdown.js +4 -0
  48. package/dist/render/messages.js +7 -2
  49. package/dist/services/account.d.ts +1 -1
  50. package/dist/services/account.js +1 -2
  51. package/dist/services/people.d.ts +8 -5
  52. package/dist/services/people.js +6 -3
  53. package/dist/services/person-profile.d.ts +4 -3
  54. package/dist/services/person-profile.js +14 -3
  55. package/dist/services/pictures.d.ts +2 -1
  56. package/dist/services/pictures.js +2 -0
  57. package/dist/services/search-all.d.ts +3 -1
  58. package/dist/services/search-all.js +2 -0
  59. package/dist/store/sqlite/manifest.js +1 -0
  60. package/dist/store/sqlite/messages.js +5 -1
  61. package/dist/store/sqlite/migrations.generated.js +6 -0
  62. package/dist/store/sqlite/reads.js +1 -0
  63. package/dist/store/sqlite/schema.d.ts +16 -0
  64. package/dist/store/sqlite/schema.js +1 -0
  65. package/package.json +1 -1
  66. package/parity.json +20 -10
@@ -77,6 +77,13 @@ export declare const writtenAnswer: ({ operationId, sendId, message, messages, s
77
77
  error?: string | undefined;
78
78
  } | undefined;
79
79
  local_path?: string | undefined;
80
+ contact?: {
81
+ name: string;
82
+ first_name?: string | undefined;
83
+ last_name?: string | undefined;
84
+ phone?: string | undefined;
85
+ user_id?: string | undefined;
86
+ } | undefined;
80
87
  buttons?: {
81
88
  kind: "app" | "callback" | "chat" | "clipboard" | "contact" | "link" | "location" | "message" | "other";
82
89
  text: string;
@@ -109,6 +116,13 @@ export declare const writtenAnswer: ({ operationId, sendId, message, messages, s
109
116
  error?: string | undefined;
110
117
  } | undefined;
111
118
  local_path?: string | undefined;
119
+ contact?: {
120
+ name: string;
121
+ first_name?: string | undefined;
122
+ last_name?: string | undefined;
123
+ phone?: string | undefined;
124
+ user_id?: string | undefined;
125
+ } | undefined;
112
126
  buttons?: {
113
127
  kind: "app" | "callback" | "chat" | "clipboard" | "contact" | "link" | "location" | "message" | "other";
114
128
  text: string;
@@ -144,6 +158,13 @@ export declare const writtenAnswer: ({ operationId, sendId, message, messages, s
144
158
  error?: string | undefined;
145
159
  } | undefined;
146
160
  local_path?: string | undefined;
161
+ contact?: {
162
+ name: string;
163
+ first_name?: string | undefined;
164
+ last_name?: string | undefined;
165
+ phone?: string | undefined;
166
+ user_id?: string | undefined;
167
+ } | undefined;
147
168
  buttons?: {
148
169
  kind: "app" | "callback" | "chat" | "clipboard" | "contact" | "link" | "location" | "message" | "other";
149
170
  text: string;
@@ -268,6 +289,13 @@ export declare const writtenAnswer: ({ operationId, sendId, message, messages, s
268
289
  error?: string | undefined;
269
290
  } | undefined;
270
291
  local_path?: string | undefined;
292
+ contact?: {
293
+ name: string;
294
+ first_name?: string | undefined;
295
+ last_name?: string | undefined;
296
+ phone?: string | undefined;
297
+ user_id?: string | undefined;
298
+ } | undefined;
271
299
  buttons?: {
272
300
  kind: "app" | "callback" | "chat" | "clipboard" | "contact" | "link" | "location" | "message" | "other";
273
301
  text: string;
@@ -300,6 +328,13 @@ export declare const writtenAnswer: ({ operationId, sendId, message, messages, s
300
328
  error?: string | undefined;
301
329
  } | undefined;
302
330
  local_path?: string | undefined;
331
+ contact?: {
332
+ name: string;
333
+ first_name?: string | undefined;
334
+ last_name?: string | undefined;
335
+ phone?: string | undefined;
336
+ user_id?: string | undefined;
337
+ } | undefined;
303
338
  buttons?: {
304
339
  kind: "app" | "callback" | "chat" | "clipboard" | "contact" | "link" | "location" | "message" | "other";
305
340
  text: string;
@@ -335,6 +370,13 @@ export declare const writtenAnswer: ({ operationId, sendId, message, messages, s
335
370
  error?: string | undefined;
336
371
  } | undefined;
337
372
  local_path?: string | undefined;
373
+ contact?: {
374
+ name: string;
375
+ first_name?: string | undefined;
376
+ last_name?: string | undefined;
377
+ phone?: string | undefined;
378
+ user_id?: string | undefined;
379
+ } | undefined;
338
380
  buttons?: {
339
381
  kind: "app" | "callback" | "chat" | "clipboard" | "contact" | "link" | "location" | "message" | "other";
340
382
  text: string;
@@ -9,3 +9,5 @@ export declare const CONTACTS_QUERY: QueryRegistry;
9
9
  export declare const notesAllowed: (permissions: Parameters<typeof levelFor>[0], notes: Predicate | undefined) => void;
10
10
  /** The messenger keeps the voters of one answer; one answer id at a time. */
11
11
  export declare const VOTERS_QUERY: QueryRegistry;
12
+ /** Telegram keeps the people who chose one reaction; one emoji at a time. */
13
+ export declare const REACTORS_QUERY: QueryRegistry;
@@ -1,6 +1,6 @@
1
1
  import { CliError } from "@wirecat/cli-base";
2
2
  import { queryError, queryFieldsOf } from "@wirecat/cli-base/query";
3
- import { contact, pollVote } from "../../entities/index.js";
3
+ import { contact, pollVote, reaction } from "../../entities/index.js";
4
4
  import { levelFor } from "../../sends/permissions.js";
5
5
  const notesText = (node) => {
6
6
  if (/[*?]/.test(node.value.replace(/^\*+|\*+$/g, "")))
@@ -34,3 +34,9 @@ export const VOTERS_QUERY = {
34
34
  backend: "native",
35
35
  fields: queryFieldsOf(pollVote, { native: ["answers"], examples: { answers: "answers:0" } }),
36
36
  };
37
+ /** Telegram keeps the people who chose one reaction; one emoji at a time. */
38
+ export const REACTORS_QUERY = {
39
+ entity: "reaction",
40
+ backend: "native",
41
+ fields: queryFieldsOf(reaction, { native: ["reaction"], examples: { reaction: "reaction:🔥" } }),
42
+ };
@@ -1,11 +1,47 @@
1
1
  import { annotate } from "@wirecat/cli-base/commands";
2
2
  import { Command } from "commander";
3
- import { REMOTE_WRITE } from "../effects.js";
4
- import { itemOf, renderAnswer, snakeKeys } from "../envelope.js";
3
+ import { capability } from "../../ports/messenger.js";
4
+ import { REMOTE_READ, REMOTE_WRITE } from "../effects.js";
5
+ import { itemOf, listOf, renderAnswer, snakeKeys } from "../envelope.js";
6
+ import { listQuery, nativeTerms, typedQuery, withQuery } from "../list-query.js";
7
+ import { positiveCount } from "../paging.js";
8
+ import { lines, reactorAnswer } from "./chat-answers.js";
5
9
  import { messengerContext } from "./context.js";
10
+ import { REACTORS_QUERY } from "./people-queries.js";
6
11
  /** `reactions add|remove`: the owner's own reaction on a message. */
7
12
  export const reactionsCommand = (messenger) => {
8
13
  const reactions = new Command("reactions").description("react to messages");
14
+ if (messenger.reactionsList)
15
+ reactions.addCommand(withQuery(annotate(annotate(new Command("list"), {
16
+ effects: REMOTE_READ,
17
+ examples: [`${messenger.app.command} personal reactions list "Book club" 101 reaction:🔥 --limit 20`],
18
+ })
19
+ .description("who reacted to a message, newest first; refused where the chat hides the list")
20
+ .argument("<chat>", messenger.chatArgument)
21
+ .argument("<message>", "the message id")
22
+ .option("--limit <n>", "how many to show", positiveCount("--limit"))
23
+ .option("--cursor <cursor>", "go on from where the last page stopped; page.next gives it"), { output: { entity: "reaction" } }), REACTORS_QUERY).action(async function (chat, message, words) {
24
+ const emoji = nativeTerms(listQuery(typedQuery(words), REACTORS_QUERY, "reactions list"), "reactions list").get("reaction")?.value;
25
+ const context = messengerContext(this, messenger);
26
+ const { cursor } = this.opts();
27
+ const { limit } = context.settings;
28
+ const found = await context.withMessenger(async (connection) => {
29
+ const list = capability(connection, "reactors", "list who reacted");
30
+ return list((await connection.resolve(chat)).id, message.trim(), {
31
+ limit,
32
+ ...(emoji === undefined ? {} : { emoji: emoji.trim() }),
33
+ ...(cursor === undefined ? {} : { cursor }),
34
+ });
35
+ });
36
+ renderAnswer(this, context, listOf("reactions list", {
37
+ items: found.items.map(reactorAnswer),
38
+ limit,
39
+ has_more: found.hasMore,
40
+ paging: "cursor",
41
+ ...(found.cursor === undefined ? {} : { cursor: found.cursor }),
42
+ args: { chat, message, ...(words.length > 0 ? { query: words.join(" ") } : {}) },
43
+ }), lines(({ reacted_at, person, reaction: name }) => [reacted_at, person.name ?? person.id, name].join(" ")));
44
+ }));
9
45
  annotate(reactions.command("add"), {
10
46
  effects: REMOTE_WRITE,
11
47
  output: { entity: "reaction_change" },
@@ -1,4 +1,5 @@
1
1
  import { formatLocator, parseLocator } from "../../domain/locator.js";
2
+ import { senderIsMe } from "../../domain/models.js";
2
3
  import { DEFAULT_TEXT_MODEL } from "../../embeddings/models.js";
3
4
  import { excerpt } from "../../services/excerpt.js";
4
5
  import { MAX_SEARCH_OFFSET } from "../../services/messages-archive-search.js";
@@ -28,6 +29,7 @@ export const messageHitItem = (hit, query = "") => {
28
29
  chat_title: hit.chatTitle ?? undefined,
29
30
  timestamp: hit.timestamp,
30
31
  sender_name: hit.senderName,
32
+ sender_is_me: senderIsMe(hit, at.account),
31
33
  excerpt: hit.excerpt ?? excerpt(hit.text, query),
32
34
  matched_in: hit.matchedIn,
33
35
  score: hit.score ?? undefined,
@@ -165,10 +167,11 @@ const pictureItems = (found) => {
165
167
  const shown = new Set(found.items.map(({ locator }) => locator));
166
168
  return (found.pictures ?? [])
167
169
  .filter(({ locator }) => !shown.has(locator))
168
- .map(({ locator, timestamp, senderName, score }) => ({
170
+ .map(({ locator, timestamp, senderName, senderIsMe, score }) => ({
169
171
  ref: locator,
170
172
  timestamp,
171
173
  sender_name: senderName,
174
+ sender_is_me: senderIsMe,
172
175
  matched_in: "picture",
173
176
  score,
174
177
  untrusted: ["sender_name"],
@@ -226,6 +229,7 @@ export const allHitItem = (item) => item.kind === "meeting"
226
229
  url: item.url,
227
230
  excerpt: item.text,
228
231
  sender_name: item.from?.name,
232
+ sender_is_me: item.senderIsMe,
229
233
  sender_ref: item.from?.ref,
230
234
  found_by: item.foundBy,
231
235
  untrusted: ALL_HIT_UNTRUSTED[item.kind],
@@ -44,6 +44,7 @@ export declare const serveRelay: (command: Command, messenger: Messenger) => {
44
44
  groupSettings?: readonly import("../../domain/models.js").GroupSettingKey[];
45
45
  pollQuiz?: boolean;
46
46
  pollCloseSeconds?: readonly [min: number, max: number];
47
+ reactionsList?: boolean;
47
48
  pollVoters?: boolean;
48
49
  pollClose?: boolean;
49
50
  pollRevote?: boolean;
@@ -189,6 +189,18 @@ export interface Attachment {
189
189
  buttons?: Button[][];
190
190
  /** The poll the message carries, as it stood when read; drawn for a person, not part of the JSON answer. */
191
191
  poll?: Poll;
192
+ /** The contact card shared in the message (`kind: "contact"`), the phone as the sender typed it. */
193
+ contact?: SharedContact;
194
+ }
195
+ /** A contact card sent in a message: who it is for, and the number the sender put on it. */
196
+ export interface SharedContact {
197
+ /** First and last name as shown. */
198
+ name: string;
199
+ firstName?: string;
200
+ lastName?: string;
201
+ phone?: string;
202
+ /** The messenger's account for the card, when the number belongs to one. */
203
+ userId?: Id;
192
204
  }
193
205
  /**
194
206
  * What pressing a bot's button does: `callback` tells the bot, `link` opens `url`, `message` sends its
@@ -284,6 +296,13 @@ export interface PersonReaction {
284
296
  /** ISO 8601 — when the person reacted, as the messenger says, not when it arrived. */
285
297
  reactedAt: string;
286
298
  }
299
+ /** One person's reaction to a message, as `reactions list` gives it. */
300
+ export interface Reactor {
301
+ person: Member;
302
+ reaction: string;
303
+ /** ISO 8601. */
304
+ reactedAt: string;
305
+ }
287
306
  /** The message a reply answers or a forward carries. */
288
307
  export interface QuotedMessage {
289
308
  id: Id;
@@ -347,6 +366,8 @@ export interface Message {
347
366
  */
348
367
  delivery?: Delivery;
349
368
  }
369
+ /** MAX reports the owner's own messages with no sender id, so `outgoing` counts as well as the id. */
370
+ export declare const senderIsMe: (message: Pick<Message, "outgoing" | "senderId">, account: string) => boolean;
350
371
  /** `delivered` reached the other person's phone; `read` they opened it (a voice note or view-once file played counts). */
351
372
  export type Delivery = "delivered" | "read";
352
373
  /**
@@ -741,7 +762,7 @@ export interface Registered {
741
762
  /** How fine `at` is: Telegram tells a month, an estimate a month at best. */
742
763
  precision: "day" | "month";
743
764
  }
744
- /** Everything the messenger itself says about one person, as `contacts info` reads it. */
765
+ /** Everything the messenger itself says about one person, as `contacts show` reads it. */
745
766
  export interface ProfileFacts {
746
767
  id: Id;
747
768
  name: string | null;
@@ -794,7 +815,7 @@ export interface PersonAlias {
794
815
  lastSeenAt: string;
795
816
  source: "profile" | "messages";
796
817
  }
797
- /** `contacts info`: the person, and their activity in every chat shared with them. */
818
+ /** `contacts show`: the person, and their activity in every chat shared with them. */
798
819
  export interface PersonProfile extends Omit<ProfileFacts, "chats"> {
799
820
  chats: SharedChatActivity[];
800
821
  /** Earlier names and usernames, oldest first; the current ones are not repeated. */
@@ -815,7 +836,7 @@ export interface Account {
815
836
  name: string | null;
816
837
  /** The public handle, without `@`, when there is one. */
817
838
  username: string | null;
818
- /** The whole number, where the messenger tells it; printed as its last four digits unless asked. */
839
+ /** The whole number, where the messenger tells it; `--hide-phone` leaves it out. */
819
840
  phone?: string | null;
820
841
  }
821
842
  export interface Profile {
@@ -9,5 +9,7 @@ export const FOLDER_KINDS = ["contacts", "non-contacts", "groups", "channels", "
9
9
  export const FOLDER_SKIPS = ["muted", "read", "archived"];
10
10
  /** What an admin may do, in max-cli's words; a messenger maps them onto its own. */
11
11
  export const ADMIN_RIGHTS = ["read", "members", "admins", "info", "pin", "link", "post", "edit", "delete"];
12
+ /** MAX reports the owner's own messages with no sender id, so `outgoing` counts as well as the id. */
13
+ export const senderIsMe = (message, account) => message.outgoing === true || (message.senderId !== null && String(message.senderId) === account);
12
14
  /** Kinds of attachment `chats media` filters by. */
13
15
  export const MEDIA_KINDS = ["photo", "video", "file", "audio", "link"];
@@ -24,6 +24,14 @@ export declare const attachment: v.StrictObjectSchema<{
24
24
  readonly error: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
25
25
  }, undefined>, undefined>;
26
26
  readonly local_path: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
27
+ /** A shared contact card (`kind: "contact"`); the phone is the whole number as the sender put it. */
28
+ readonly contact: v.OptionalSchema<v.StrictObjectSchema<{
29
+ readonly name: v.StringSchema<undefined>;
30
+ readonly first_name: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
31
+ readonly last_name: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
32
+ readonly phone: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
33
+ readonly user_id: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>, undefined>;
34
+ }, undefined>, undefined>;
27
35
  /** A bot's keyboard under the message, row by row; `messages press` presses one. */
28
36
  readonly buttons: v.OptionalSchema<v.ArraySchema<v.ArraySchema<v.StrictObjectSchema<{
29
37
  readonly kind: v.PicklistSchema<["callback", "link", "message", "chat", "contact", "location", "app", "clipboard", "other"], undefined>;
@@ -1,5 +1,5 @@
1
1
  import * as v from "valibot";
2
- import { count, reference, text } from "./fields.js";
2
+ import { count, id, reference, text } from "./fields.js";
3
3
  export const attachment = v.strictObject({
4
4
  /** The message it came with, as a locator; absent inside that message. */
5
5
  message: v.optional(reference),
@@ -20,6 +20,14 @@ export const attachment = v.strictObject({
20
20
  text: v.optional(text),
21
21
  extraction: v.optional(v.strictObject({ origin: text, extractor: text, chars: count, error: v.optional(text) })),
22
22
  local_path: v.optional(text),
23
+ /** A shared contact card (`kind: "contact"`); the phone is the whole number as the sender put it. */
24
+ contact: v.optional(v.strictObject({
25
+ name: text,
26
+ first_name: v.optional(text),
27
+ last_name: v.optional(text),
28
+ phone: v.optional(text),
29
+ user_id: v.optional(id),
30
+ })),
23
31
  /** A bot's keyboard under the message, row by row; `messages press` presses one. */
24
32
  buttons: v.optional(v.array(v.array(v.strictObject({
25
33
  kind: v.picklist(["callback", "link", "message", "chat", "contact", "location", "app", "clipboard", "other"]),
@@ -180,6 +180,13 @@ export declare const contactMessages: v.StrictObjectSchema<{
180
180
  readonly error: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
181
181
  }, undefined>, undefined>;
182
182
  readonly local_path: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
183
+ readonly contact: v.OptionalSchema<v.StrictObjectSchema<{
184
+ readonly name: v.StringSchema<undefined>;
185
+ readonly first_name: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
186
+ readonly last_name: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
187
+ readonly phone: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
188
+ readonly user_id: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>, undefined>;
189
+ }, undefined>, undefined>;
183
190
  readonly buttons: v.OptionalSchema<v.ArraySchema<v.ArraySchema<v.StrictObjectSchema<{
184
191
  readonly kind: v.PicklistSchema<["callback", "link", "message", "chat", "contact", "location", "app", "clipboard", "other"], undefined>;
185
192
  readonly text: v.StringSchema<undefined>;
@@ -212,6 +219,13 @@ export declare const contactMessages: v.StrictObjectSchema<{
212
219
  readonly error: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
213
220
  }, undefined>, undefined>;
214
221
  readonly local_path: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
222
+ readonly contact: v.OptionalSchema<v.StrictObjectSchema<{
223
+ readonly name: v.StringSchema<undefined>;
224
+ readonly first_name: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
225
+ readonly last_name: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
226
+ readonly phone: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
227
+ readonly user_id: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>, undefined>;
228
+ }, undefined>, undefined>;
215
229
  readonly buttons: v.OptionalSchema<v.ArraySchema<v.ArraySchema<v.StrictObjectSchema<{
216
230
  readonly kind: v.PicklistSchema<["callback", "link", "message", "chat", "contact", "location", "app", "clipboard", "other"], undefined>;
217
231
  readonly text: v.StringSchema<undefined>;
@@ -247,6 +261,13 @@ export declare const contactMessages: v.StrictObjectSchema<{
247
261
  readonly error: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
248
262
  }, undefined>, undefined>;
249
263
  readonly local_path: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
264
+ readonly contact: v.OptionalSchema<v.StrictObjectSchema<{
265
+ readonly name: v.StringSchema<undefined>;
266
+ readonly first_name: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
267
+ readonly last_name: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
268
+ readonly phone: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
269
+ readonly user_id: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>, undefined>;
270
+ }, undefined>, undefined>;
250
271
  readonly buttons: v.OptionalSchema<v.ArraySchema<v.ArraySchema<v.StrictObjectSchema<{
251
272
  readonly kind: v.PicklistSchema<["callback", "link", "message", "chat", "contact", "location", "app", "clipboard", "other"], undefined>;
252
273
  readonly text: v.StringSchema<undefined>;
@@ -931,6 +952,13 @@ export declare const contactContext: v.UnionSchema<[v.StrictObjectSchema<{
931
952
  readonly error: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
932
953
  }, undefined>, undefined>;
933
954
  readonly local_path: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
955
+ readonly contact: v.OptionalSchema<v.StrictObjectSchema<{
956
+ readonly name: v.StringSchema<undefined>;
957
+ readonly first_name: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
958
+ readonly last_name: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
959
+ readonly phone: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
960
+ readonly user_id: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>, undefined>;
961
+ }, undefined>, undefined>;
934
962
  readonly buttons: v.OptionalSchema<v.ArraySchema<v.ArraySchema<v.StrictObjectSchema<{
935
963
  readonly kind: v.PicklistSchema<["callback", "link", "message", "chat", "contact", "location", "app", "clipboard", "other"], undefined>;
936
964
  readonly text: v.StringSchema<undefined>;
@@ -963,6 +991,13 @@ export declare const contactContext: v.UnionSchema<[v.StrictObjectSchema<{
963
991
  readonly error: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
964
992
  }, undefined>, undefined>;
965
993
  readonly local_path: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
994
+ readonly contact: v.OptionalSchema<v.StrictObjectSchema<{
995
+ readonly name: v.StringSchema<undefined>;
996
+ readonly first_name: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
997
+ readonly last_name: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
998
+ readonly phone: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
999
+ readonly user_id: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>, undefined>;
1000
+ }, undefined>, undefined>;
966
1001
  readonly buttons: v.OptionalSchema<v.ArraySchema<v.ArraySchema<v.StrictObjectSchema<{
967
1002
  readonly kind: v.PicklistSchema<["callback", "link", "message", "chat", "contact", "location", "app", "clipboard", "other"], undefined>;
968
1003
  readonly text: v.StringSchema<undefined>;
@@ -998,6 +1033,13 @@ export declare const contactContext: v.UnionSchema<[v.StrictObjectSchema<{
998
1033
  readonly error: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
999
1034
  }, undefined>, undefined>;
1000
1035
  readonly local_path: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
1036
+ readonly contact: v.OptionalSchema<v.StrictObjectSchema<{
1037
+ readonly name: v.StringSchema<undefined>;
1038
+ readonly first_name: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
1039
+ readonly last_name: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
1040
+ readonly phone: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
1041
+ readonly user_id: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>, undefined>;
1042
+ }, undefined>, undefined>;
1001
1043
  readonly buttons: v.OptionalSchema<v.ArraySchema<v.ArraySchema<v.StrictObjectSchema<{
1002
1044
  readonly kind: v.PicklistSchema<["callback", "link", "message", "chat", "contact", "location", "app", "clipboard", "other"], undefined>;
1003
1045
  readonly text: v.StringSchema<undefined>;
@@ -9,14 +9,12 @@ export declare const contactSync: v.StrictObjectSchema<{
9
9
  readonly changed: v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 0, undefined>]>;
10
10
  readonly known: v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 0, undefined>]>;
11
11
  }, undefined>;
12
- export declare const contactProfile: v.StrictObjectSchema<{
13
- readonly id: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>;
14
- readonly name: v.NullableSchema<v.StringSchema<undefined>, undefined>;
15
- readonly usernames: v.ArraySchema<v.StringSchema<undefined>, undefined>;
16
- readonly bio: v.NullableSchema<v.StringSchema<undefined>, undefined>;
17
- readonly birthday: v.OptionalSchema<v.NullableSchema<v.StringSchema<undefined>, undefined>, undefined>;
18
- readonly phone: v.OptionalSchema<v.NullableSchema<v.StringSchema<undefined>, undefined>, undefined>;
19
- readonly flags: Omit<v.StrictObjectSchema<{
12
+ /** What the messenger says about a person; `contacts show` carries these beside the card's own fields. */
13
+ export declare const profileFields: {
14
+ usernames: v.ArraySchema<v.StringSchema<undefined>, undefined>;
15
+ birthday: v.OptionalSchema<v.NullableSchema<v.StringSchema<undefined>, undefined>, undefined>;
16
+ phone: v.OptionalSchema<v.NullableSchema<v.StringSchema<undefined>, undefined>, undefined>;
17
+ flags: Omit<v.StrictObjectSchema<{
20
18
  readonly bot: v.BooleanSchema<undefined>;
21
19
  readonly verified: v.BooleanSchema<undefined>;
22
20
  readonly premium: v.BooleanSchema<undefined>;
@@ -89,26 +87,18 @@ export declare const contactProfile: v.StrictObjectSchema<{
89
87
  readonly issue: v.BooleanIssue | v.StrictObjectIssue;
90
88
  } | undefined;
91
89
  };
92
- readonly seen: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
93
- readonly contact: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
94
- readonly mutual_contact: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
95
- readonly common_chats_count: v.OptionalSchema<v.NullableSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 0, undefined>]>, undefined>, undefined>;
96
- readonly registered: v.OptionalSchema<v.NullableSchema<v.StrictObjectSchema<{
90
+ seen: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
91
+ contact: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
92
+ mutual_contact: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
93
+ common_chats_count: v.OptionalSchema<v.NullableSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 0, undefined>]>, undefined>, undefined>;
94
+ registered: v.OptionalSchema<v.NullableSchema<v.StrictObjectSchema<{
97
95
  readonly at: v.StringSchema<undefined>;
98
96
  readonly source: v.PicklistSchema<["telegram", "max", "estimate"], undefined>;
99
97
  readonly precision: v.PicklistSchema<["day", "month"], undefined>;
100
98
  }, undefined>, undefined>, undefined>;
101
- readonly has_photo: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
102
- readonly chats: v.ArraySchema<v.StrictObjectSchema<{
103
- readonly id: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>;
104
- readonly title: v.NullableSchema<v.StringSchema<undefined>, undefined>;
105
- readonly kind: v.PicklistSchema<["dialog", "group", "channel", "saved", "unknown"], undefined>;
106
- readonly their_messages: v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 0, undefined>]>;
107
- readonly first_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>;
108
- readonly last_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>;
109
- readonly complete: v.BooleanSchema<undefined>;
110
- }, undefined>, undefined>;
111
- readonly aliases: v.ArraySchema<v.StrictObjectSchema<{
99
+ has_photo: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
100
+ /** Earlier names and usernames, oldest first; the current ones are not repeated. */
101
+ aliases: v.ArraySchema<v.StrictObjectSchema<{
112
102
  readonly name: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
113
103
  readonly username: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
114
104
  readonly link: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
@@ -116,4 +106,4 @@ export declare const contactProfile: v.StrictObjectSchema<{
116
106
  readonly last_seen_at: 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`">]>;
117
107
  readonly source: v.PicklistSchema<["profile", "messages"], undefined>;
118
108
  }, undefined>, undefined>;
119
- }, undefined>;
109
+ };
@@ -1,13 +1,10 @@
1
1
  import * as v from "valibot";
2
- import { chat } from "./chat.js";
3
2
  import { count, id, text, time } from "./fields.js";
4
3
  export const contactLookup = v.strictObject({ id, name: v.nullable(text), username: v.nullable(text) });
5
4
  export const contactSync = v.strictObject({ added: count, changed: count, known: count });
6
- export const contactProfile = v.strictObject({
7
- id,
8
- name: v.nullable(text),
5
+ /** What the messenger says about a person; `contacts show` carries these beside the card's own fields. */
6
+ export const profileFields = {
9
7
  usernames: v.array(text),
10
- bio: v.nullable(text),
11
8
  birthday: v.optional(v.nullable(text)),
12
9
  phone: v.optional(v.nullable(text)),
13
10
  flags: v.partial(v.strictObject({
@@ -30,15 +27,7 @@ export const contactProfile = v.strictObject({
30
27
  precision: v.picklist(["day", "month"]),
31
28
  }))),
32
29
  has_photo: v.optional(v.boolean()),
33
- chats: v.array(v.strictObject({
34
- id,
35
- title: v.nullable(text),
36
- kind: chat.entries.kind,
37
- their_messages: count,
38
- first_at: v.nullable(time),
39
- last_at: v.nullable(time),
40
- complete: v.boolean(),
41
- })),
30
+ /** Earlier names and usernames, oldest first; the current ones are not repeated. */
42
31
  aliases: v.array(v.strictObject({
43
32
  name: v.optional(text),
44
33
  username: v.optional(text),
@@ -47,4 +36,4 @@ export const contactProfile = v.strictObject({
47
36
  last_seen_at: time,
48
37
  source: v.picklist(["profile", "messages"]),
49
38
  })),
50
- });
39
+ };