@wirecat/cli-core 0.477.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.
- package/CHANGELOG.md +12 -0
- package/dist/cli/messenger/catch-up-answers.d.ts +2 -0
- package/dist/cli/messenger/catch-up-answers.js +2 -1
- package/dist/cli/messenger/message-items.d.ts +1 -1
- package/dist/cli/messenger/message-items.js +2 -2
- package/dist/cli/messenger/search-answers.js +5 -1
- package/dist/domain/models.d.ts +2 -0
- package/dist/domain/models.js +2 -0
- package/dist/entities/hit.d.ts +2 -0
- package/dist/entities/hit.js +2 -0
- package/dist/entities/index.d.ts +8 -1
- package/dist/entities/index.js +2 -0
- package/dist/services/pictures.d.ts +2 -1
- package/dist/services/pictures.js +2 -0
- package/dist/services/search-all.d.ts +3 -1
- package/dist/services/search-all.js +2 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,18 @@ Notable changes to `@wirecat/cli-core` (`@wirecat/cli-messaging` up to 0.261.0,
|
|
|
5
5
|
minor version may break callers, and says how under "Changed — may break callers". `pnpm docs:check` checks the
|
|
6
6
|
shape of this file.
|
|
7
7
|
|
|
8
|
+
## Unreleased
|
|
9
|
+
|
|
10
|
+
## 0.478.0 — 29.10.2026
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
|
|
14
|
+
- **`sender_is_me` on `inbox`, `review`, `search messages` and `search all`**, as 0.473.0 promised. The catch-up
|
|
15
|
+
answers and the search hits are built field by field, not from `messageItem`, and left it out; only `messages list`
|
|
16
|
+
and the other `messageItem` answers had it. A `search all` hit carries it for a message or a mail, and the picture
|
|
17
|
+
lane's hits of `search messages` carry it too. Every answer applies the one rule: `outgoing`, or the sender id is
|
|
18
|
+
the reading account's own.
|
|
19
|
+
|
|
8
20
|
## 0.477.0 — 29.10.2026
|
|
9
21
|
|
|
10
22
|
### Added
|
|
@@ -20,6 +20,7 @@ export declare const inboxAnswer: (inbox: Inbox, hearing: Hearing | undefined, r
|
|
|
20
20
|
chat_title: string | null | undefined;
|
|
21
21
|
timestamp: string;
|
|
22
22
|
sender_name: string | null;
|
|
23
|
+
sender_is_me: boolean;
|
|
23
24
|
outgoing: boolean | null;
|
|
24
25
|
text: string;
|
|
25
26
|
transcript?: string | undefined;
|
|
@@ -74,6 +75,7 @@ export declare const reviewAnswer: (found: Review, hearing: Hearing | undefined,
|
|
|
74
75
|
chat_title: string | null | undefined;
|
|
75
76
|
timestamp: string;
|
|
76
77
|
sender_name: string | null;
|
|
78
|
+
sender_is_me: boolean;
|
|
77
79
|
outgoing: boolean | null;
|
|
78
80
|
text: string;
|
|
79
81
|
transcript?: string | undefined;
|
|
@@ -34,13 +34,14 @@ export const catchUpQuery = (words, registry, command) => {
|
|
|
34
34
|
};
|
|
35
35
|
};
|
|
36
36
|
const summaryOf = (message, reader) => {
|
|
37
|
-
const { ref, chat_id, chat_title, timestamp, sender_name, outgoing, text, transcript, attachments } = messageItem(message, reader);
|
|
37
|
+
const { ref, chat_id, chat_title, timestamp, sender_name, sender_is_me, outgoing, text, transcript, attachments } = messageItem(message, reader);
|
|
38
38
|
return {
|
|
39
39
|
ref,
|
|
40
40
|
chat_id,
|
|
41
41
|
chat_title,
|
|
42
42
|
timestamp,
|
|
43
43
|
sender_name,
|
|
44
|
+
sender_is_me,
|
|
44
45
|
outgoing,
|
|
45
46
|
text,
|
|
46
47
|
...(transcript === undefined ? {} : { transcript }),
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type * as v from "valibot";
|
|
2
|
-
import type
|
|
2
|
+
import { type Message, type MessageHit } from "../../domain/models.js";
|
|
3
3
|
import type { message as messageSchema } from "../../entities/message.js";
|
|
4
4
|
import type { MessengerAdapter } from "../../ports/messenger.js";
|
|
5
5
|
import type { AccountKey } from "../../store/store.js";
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { CliError } from "@wirecat/cli-base";
|
|
2
2
|
import { formatLocator, parseLocator } from "../../domain/locator.js";
|
|
3
|
+
import { senderIsMe, } from "../../domain/models.js";
|
|
3
4
|
const defined = (value) => Object.fromEntries(Object.entries(value).filter(([, one]) => one !== undefined));
|
|
4
5
|
const attachmentItem = (attachment) => defined({
|
|
5
6
|
kind: attachment.kind,
|
|
@@ -50,8 +51,7 @@ export const messageItem = (message, reader) => {
|
|
|
50
51
|
sender_name: message.senderName,
|
|
51
52
|
sender_username: message.senderUsername,
|
|
52
53
|
sender_is_chat: message.senderIsChat,
|
|
53
|
-
|
|
54
|
-
sender_is_me: message.outgoing === true || (message.senderId !== null && String(message.senderId) === account),
|
|
54
|
+
sender_is_me: senderIsMe(message, account),
|
|
55
55
|
mentions: message.mentions,
|
|
56
56
|
timestamp: message.timestamp,
|
|
57
57
|
edited_at: message.editedAt,
|
|
@@ -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],
|
package/dist/domain/models.d.ts
CHANGED
|
@@ -366,6 +366,8 @@ export interface Message {
|
|
|
366
366
|
*/
|
|
367
367
|
delivery?: Delivery;
|
|
368
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;
|
|
369
371
|
/** `delivered` reached the other person's phone; `read` they opened it (a voice note or view-once file played counts). */
|
|
370
372
|
export type Delivery = "delivered" | "read";
|
|
371
373
|
/**
|
package/dist/domain/models.js
CHANGED
|
@@ -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"];
|
package/dist/entities/hit.d.ts
CHANGED
|
@@ -13,6 +13,8 @@ export declare const hit: v.StrictObjectSchema<{
|
|
|
13
13
|
readonly timestamp: 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>;
|
|
14
14
|
readonly excerpt: v.StringSchema<undefined>;
|
|
15
15
|
readonly sender_name: v.OptionalSchema<v.NullableSchema<v.StringSchema<undefined>, undefined>, undefined>;
|
|
16
|
+
/** A message's or a mail's: whether the owner wrote it. */
|
|
17
|
+
readonly sender_is_me: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
|
|
16
18
|
/** The writer's `person:` reference, where the store has one. */
|
|
17
19
|
readonly sender_ref: v.OptionalSchema<v.NullableSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, "a reference such as `note:42`">]>, undefined>, undefined>;
|
|
18
20
|
readonly found_by: v.OptionalSchema<v.ArraySchema<v.PicklistSchema<["title", "words", "meaning"], undefined>, undefined>, undefined>;
|
package/dist/entities/hit.js
CHANGED
|
@@ -14,6 +14,8 @@ export const hit = v.strictObject({
|
|
|
14
14
|
timestamp: v.nullable(time),
|
|
15
15
|
excerpt: text,
|
|
16
16
|
sender_name: v.optional(v.nullable(text)),
|
|
17
|
+
/** A message's or a mail's: whether the owner wrote it. */
|
|
18
|
+
sender_is_me: v.optional(v.boolean()),
|
|
17
19
|
/** The writer's `person:` reference, where the store has one. */
|
|
18
20
|
sender_ref: v.optional(v.nullable(reference)),
|
|
19
21
|
found_by: v.optional(v.array(v.picklist(["title", "words", "meaning"]))),
|
package/dist/entities/index.d.ts
CHANGED
|
@@ -1141,6 +1141,7 @@ export declare const ENTITIES: {
|
|
|
1141
1141
|
readonly ref: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, "a reference such as `note:42`">]>;
|
|
1142
1142
|
readonly chat_title: v.OptionalSchema<v.NullableSchema<v.StringSchema<undefined>, undefined>, undefined>;
|
|
1143
1143
|
readonly sender_name: v.NullableSchema<v.StringSchema<undefined>, undefined>;
|
|
1144
|
+
readonly sender_is_me: v.BooleanSchema<undefined>;
|
|
1144
1145
|
readonly timestamp: 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`">]>;
|
|
1145
1146
|
readonly excerpt: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
|
|
1146
1147
|
readonly matched_in: v.OptionalSchema<v.PicklistSchema<["text", "transcript", "filename", "file", "context", "picture"], undefined>, undefined>;
|
|
@@ -1623,12 +1624,13 @@ export declare const ENTITIES: {
|
|
|
1623
1624
|
}, undefined>, undefined>;
|
|
1624
1625
|
}, undefined>, undefined>;
|
|
1625
1626
|
readonly provider_metadata: v.OptionalSchema<v.RecordSchema<v.StringSchema<undefined>, v.UnknownSchema, undefined>, undefined>;
|
|
1626
|
-
}, "attachments" | "chat_id" | "chat_title" | "outgoing" | "ref" | "sender_name" | "text" | "timestamp" | "transcript">;
|
|
1627
|
+
}, "attachments" | "chat_id" | "chat_title" | "outgoing" | "ref" | "sender_is_me" | "sender_name" | "text" | "timestamp" | "transcript">;
|
|
1627
1628
|
readonly "~standard": v.StandardProps<{
|
|
1628
1629
|
ref: string;
|
|
1629
1630
|
chat_id: string;
|
|
1630
1631
|
chat_title?: string | null | undefined;
|
|
1631
1632
|
sender_name: string | null;
|
|
1633
|
+
sender_is_me: boolean;
|
|
1632
1634
|
timestamp: string;
|
|
1633
1635
|
text: string;
|
|
1634
1636
|
transcript?: string | undefined;
|
|
@@ -1671,6 +1673,7 @@ export declare const ENTITIES: {
|
|
|
1671
1673
|
chat_id: string;
|
|
1672
1674
|
chat_title?: string | null | undefined;
|
|
1673
1675
|
sender_name: string | null;
|
|
1676
|
+
sender_is_me: boolean;
|
|
1674
1677
|
timestamp: string;
|
|
1675
1678
|
text: string;
|
|
1676
1679
|
transcript?: string | undefined;
|
|
@@ -1714,6 +1717,7 @@ export declare const ENTITIES: {
|
|
|
1714
1717
|
chat_id: string;
|
|
1715
1718
|
chat_title?: string | null | undefined;
|
|
1716
1719
|
sender_name: string | null;
|
|
1720
|
+
sender_is_me: boolean;
|
|
1717
1721
|
timestamp: string;
|
|
1718
1722
|
text: string;
|
|
1719
1723
|
transcript?: string | undefined;
|
|
@@ -1758,6 +1762,7 @@ export declare const ENTITIES: {
|
|
|
1758
1762
|
chat_id: string;
|
|
1759
1763
|
chat_title?: string | null | undefined;
|
|
1760
1764
|
sender_name: string | null;
|
|
1765
|
+
sender_is_me: boolean;
|
|
1761
1766
|
timestamp: string;
|
|
1762
1767
|
text: string;
|
|
1763
1768
|
transcript?: string | undefined;
|
|
@@ -1801,6 +1806,7 @@ export declare const ENTITIES: {
|
|
|
1801
1806
|
chat_id: string;
|
|
1802
1807
|
chat_title?: string | null | undefined;
|
|
1803
1808
|
sender_name: string | null;
|
|
1809
|
+
sender_is_me: boolean;
|
|
1804
1810
|
timestamp: string;
|
|
1805
1811
|
text: string;
|
|
1806
1812
|
transcript?: string | undefined;
|
|
@@ -4469,6 +4475,7 @@ export declare const ENTITIES: {
|
|
|
4469
4475
|
readonly timestamp: 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>;
|
|
4470
4476
|
readonly excerpt: v.StringSchema<undefined>;
|
|
4471
4477
|
readonly sender_name: v.OptionalSchema<v.NullableSchema<v.StringSchema<undefined>, undefined>, undefined>;
|
|
4478
|
+
readonly sender_is_me: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
|
|
4472
4479
|
readonly sender_ref: v.OptionalSchema<v.NullableSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, "a reference such as `note:42`">]>, undefined>, undefined>;
|
|
4473
4480
|
readonly found_by: v.OptionalSchema<v.ArraySchema<v.PicklistSchema<["title", "words", "meaning"], undefined>, undefined>, undefined>;
|
|
4474
4481
|
readonly offset_ms: v.OptionalSchema<v.NullableSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 0, undefined>]>, undefined>, undefined>;
|
package/dist/entities/index.js
CHANGED
|
@@ -108,6 +108,7 @@ export const ENTITIES = {
|
|
|
108
108
|
"chat_title",
|
|
109
109
|
"timestamp",
|
|
110
110
|
"sender_name",
|
|
111
|
+
"sender_is_me",
|
|
111
112
|
"excerpt",
|
|
112
113
|
"matched_in",
|
|
113
114
|
"score",
|
|
@@ -126,6 +127,7 @@ export const ENTITIES = {
|
|
|
126
127
|
"chat_title",
|
|
127
128
|
"timestamp",
|
|
128
129
|
"sender_name",
|
|
130
|
+
"sender_is_me",
|
|
129
131
|
"outgoing",
|
|
130
132
|
"text",
|
|
131
133
|
"transcript",
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type Id } from "../domain/models.js";
|
|
2
2
|
import type { ServiceDeps } from "./deps.js";
|
|
3
3
|
import type { MessagesService } from "./messages.js";
|
|
4
4
|
/** A bigger file is no photo a chat sends: skipping it costs a vector, reading it costs memory. */
|
|
@@ -20,6 +20,7 @@ export interface PictureHit {
|
|
|
20
20
|
messageId: Id;
|
|
21
21
|
timestamp: string;
|
|
22
22
|
senderName: string | null;
|
|
23
|
+
senderIsMe: boolean;
|
|
23
24
|
score: number;
|
|
24
25
|
}
|
|
25
26
|
export interface PictureLane {
|
|
@@ -3,6 +3,7 @@ import { readFile, stat } from "node:fs/promises";
|
|
|
3
3
|
import { setTimeout as sleep } from "node:timers/promises";
|
|
4
4
|
import { CliError } from "@wirecat/cli-base";
|
|
5
5
|
import { formatLocator } from "../domain/locator.js";
|
|
6
|
+
import { senderIsMe } from "../domain/models.js";
|
|
6
7
|
import { DEFAULT_IMAGE_MODEL, imageModel, imageModelsDirectory, isImageModelInstalled, } from "../images/picture/models.js";
|
|
7
8
|
import { capability } from "../ports/messenger.js";
|
|
8
9
|
import { refreshedFiles } from "./file-download.js";
|
|
@@ -218,6 +219,7 @@ export const picturesService = (deps) => {
|
|
|
218
219
|
messageId,
|
|
219
220
|
timestamp: message.timestamp,
|
|
220
221
|
senderName: message.senderName,
|
|
222
|
+
senderIsMe: senderIsMe(message, account.account),
|
|
221
223
|
score: Number(score.toFixed(4)),
|
|
222
224
|
},
|
|
223
225
|
];
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type ErrorCode } from "@wirecat/cli-base";
|
|
2
|
-
import type
|
|
2
|
+
import { type MailFields } from "../domain/models.js";
|
|
3
3
|
import type { MessengerTraits } from "../ports/traits.js";
|
|
4
4
|
import type { AccountKey, MessageStore } from "../store/store.js";
|
|
5
5
|
import type { SearchFound, SearchQuery } from "./messages.js";
|
|
@@ -25,6 +25,8 @@ export interface SearchAllItem {
|
|
|
25
25
|
name: string | null;
|
|
26
26
|
ref: string | null;
|
|
27
27
|
};
|
|
28
|
+
/** A message's or a mail's: whether the owner wrote it. */
|
|
29
|
+
senderIsMe?: boolean;
|
|
28
30
|
/** A mail's people, labels and thread, as `search mail` gives them. */
|
|
29
31
|
email?: MailFields;
|
|
30
32
|
/** Which search found it: words, meaning or both. */
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { CliError } from "@wirecat/cli-base";
|
|
2
2
|
import { parseLucene } from "@wirecat/cli-base/query";
|
|
3
3
|
import { parseLocator } from "../domain/locator.js";
|
|
4
|
+
import { senderIsMe } from "../domain/models.js";
|
|
4
5
|
import { INTERNAL_NOTES, kindIn } from "../domain/providers.js";
|
|
5
6
|
import { runEmbedders } from "../embeddings/embed.js";
|
|
6
7
|
import { DEFAULT_TEXT_MODEL } from "../embeddings/models.js";
|
|
@@ -96,6 +97,7 @@ export const searchAll = async (store, account, request, messenger = {}, searchM
|
|
|
96
97
|
from: hit.email?.from
|
|
97
98
|
? { name: hit.email.from.name ?? hit.email.from.address, ref: hit.email.from.ref }
|
|
98
99
|
: { name: hit.senderName, ref: null },
|
|
100
|
+
senderIsMe: senderIsMe(hit, at.account),
|
|
99
101
|
...(hit.email ? { email: hit.email } : {}),
|
|
100
102
|
foundBy,
|
|
101
103
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wirecat/cli-core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.478.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",
|