imsg-mcp 1.17.0 → 1.19.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 +14 -0
- package/dist/cli.js +1 -1
- package/dist/index.js +101 -24
- package/dist/index.js.map +1 -1
- package/dist/{meta-B5cdb7uT.js → meta-CD2uvSHu.js} +2 -2
- package/dist/{meta-B5cdb7uT.js.map → meta-CD2uvSHu.js.map} +1 -1
- package/dist/tui.js +1 -1
- package/dist/{watchdog-CW2SEAmu.js → watchdog-D54vuRzh.js} +3 -2
- package/dist/{watchdog-CW2SEAmu.js.map → watchdog-D54vuRzh.js.map} +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,20 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and follows [Semantic Versioning](https://semver.org/).
|
|
5
5
|
|
|
6
|
+
# [1.19.0](https://github.com/george43g/imsg-mcp/compare/v1.18.0...v1.19.0) (2026-07-25)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### Features
|
|
10
|
+
|
|
11
|
+
* **contacts:** attach a normalized identity block to get_contact + resolve_handle ([99dfc72](https://github.com/george43g/imsg-mcp/commit/99dfc723e2a5bf8508f1b3940a63a0aeb684d120))
|
|
12
|
+
|
|
13
|
+
# [1.18.0](https://github.com/george43g/imsg-mcp/compare/v1.17.0...v1.18.0) (2026-07-25)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
### Features
|
|
17
|
+
|
|
18
|
+
* **tools:** uniform completeness metadata across list responses ([d8fd930](https://github.com/george43g/imsg-mcp/commit/d8fd930dfd28f28ac677ec4ffefd1addb39afbf5))
|
|
19
|
+
|
|
6
20
|
# [1.17.0](https://github.com/george43g/imsg-mcp/compare/v1.16.0...v1.17.0) (2026-07-25)
|
|
7
21
|
|
|
8
22
|
|
package/dist/cli.js
CHANGED
|
@@ -4,7 +4,7 @@ import { createInterface } from "node:readline";
|
|
|
4
4
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
5
5
|
import { Command } from "commander";
|
|
6
6
|
import { d as checkLocalAccess, f as formatAccessReport, I as IMPLEMENTED_TYPES, A as ANALYTIC_INFO, i as installShutdownHandlers, r as registerCleanup, l as looksLikeThreadSlug } from "./shutdown-0TCv4XJB.js";
|
|
7
|
-
import { A as APP_VERSION, t as toYaml } from "./meta-
|
|
7
|
+
import { A as APP_VERSION, t as toYaml } from "./meta-CD2uvSHu.js";
|
|
8
8
|
import { spawn } from "node:child_process";
|
|
9
9
|
import { join, dirname } from "node:path";
|
|
10
10
|
function distRoot() {
|
package/dist/index.js
CHANGED
|
@@ -14,11 +14,11 @@ import { ensureAttachmentDownloaded } from "./attachment-sync-DMvlT8Zk.js";
|
|
|
14
14
|
import { n as normalizedPhoneVariants, h as hasNativeModule, I as IMessageDB, r as rankFuzzy } from "./imessage-db-CHbdUXk3.js";
|
|
15
15
|
import { parseUserDate } from "./date-parse-DJXMfq3a.js";
|
|
16
16
|
import { streamExport, ExportInterpretGuardError } from "./exportStream-BFxilSlL.js";
|
|
17
|
-
import {
|
|
17
|
+
import { n as normalizePhoneToE164, m as minMessageId, a as resolveRecipient, d as defaultCountryFromEnv, i as installWatchdog, b as noteActivity, r as readWatchdogState } from "./watchdog-D54vuRzh.js";
|
|
18
|
+
import { r as renderAnalyticText, A as APP_VERSION, a as APP_NAME } from "./meta-CD2uvSHu.js";
|
|
18
19
|
import { randomUUID } from "node:crypto";
|
|
19
20
|
import { z } from "zod";
|
|
20
21
|
import { a as applyInlineInterpretations, i as imageBlockFromFile, v as videoPosterFrame, m as mediaMetadata, b as refForAttachment, T as TRANSCRIBE_MAX_BYTES, g as getInterpretRuntime, t as transcriptSourceEnum, d as detectTranscriber } from "./media-intel-runtime-BkxG4bmW.js";
|
|
21
|
-
import { m as minMessageId, a as resolveRecipient, d as defaultCountryFromEnv, i as installWatchdog, n as noteActivity, r as readWatchdogState } from "./watchdog-CW2SEAmu.js";
|
|
22
22
|
const DEFAULT_TTL_MS = 24 * 60 * 60 * 1e3;
|
|
23
23
|
let dbPath = join(homedir(), ".imsg-mcp", "analytics-cache.db");
|
|
24
24
|
let db = null;
|
|
@@ -323,6 +323,37 @@ function humansHintText(hint) {
|
|
|
323
323
|
_Relationship file(s): ${list}_
|
|
324
324
|
_${hint.guidance}_`;
|
|
325
325
|
}
|
|
326
|
+
function dedupe(items) {
|
|
327
|
+
const seen = /* @__PURE__ */ new Set();
|
|
328
|
+
const out = [];
|
|
329
|
+
for (const item of items) {
|
|
330
|
+
if (item && !seen.has(item)) {
|
|
331
|
+
seen.add(item);
|
|
332
|
+
out.push(item);
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
return out;
|
|
336
|
+
}
|
|
337
|
+
function normalizeEmail(email) {
|
|
338
|
+
return email.trim().toLowerCase();
|
|
339
|
+
}
|
|
340
|
+
function e164OrOriginal(phone, country) {
|
|
341
|
+
return normalizePhoneToE164(phone, country) ?? phone.trim();
|
|
342
|
+
}
|
|
343
|
+
function buildIdentity(canonicalName, phoneNumbers, emails, country) {
|
|
344
|
+
const phones = dedupe(phoneNumbers.map((p) => e164OrOriginal(p, country)));
|
|
345
|
+
const mails = dedupe(emails.map(normalizeEmail));
|
|
346
|
+
return {
|
|
347
|
+
canonicalName,
|
|
348
|
+
phones,
|
|
349
|
+
emails: mails,
|
|
350
|
+
handles: dedupe([...phones, ...mails])
|
|
351
|
+
};
|
|
352
|
+
}
|
|
353
|
+
function buildIdentityFromHandle(handle, name, country) {
|
|
354
|
+
const isEmail = handle.includes("@");
|
|
355
|
+
return buildIdentity(name ?? handle, isEmail ? [] : [handle], isEmail ? [handle] : [], country);
|
|
356
|
+
}
|
|
326
357
|
const INSTRUCTIONS_UUID = randomUUID();
|
|
327
358
|
function wrapUntrusted(text) {
|
|
328
359
|
if (text == null || text === "") return "";
|
|
@@ -1826,7 +1857,9 @@ const GetUnreadMessagesOutputSchema = z.object({
|
|
|
1826
1857
|
messages: z.array(MessageSchema),
|
|
1827
1858
|
count: z.number().int(),
|
|
1828
1859
|
hasMore: z.boolean(),
|
|
1829
|
-
|
|
1860
|
+
truncated: z.boolean().describe(
|
|
1861
|
+
"True if more unread messages exist than were returned — raise `limit` to get the rest."
|
|
1862
|
+
)
|
|
1830
1863
|
});
|
|
1831
1864
|
const SendMessageSchema = z.object({
|
|
1832
1865
|
recipient: nonEmptyString("Phone number or email address to send to").optional(),
|
|
@@ -1886,6 +1919,9 @@ const ListConversationsOutputSchema = z.object({
|
|
|
1886
1919
|
conversations: z.array(ConversationSchema),
|
|
1887
1920
|
count: z.number().int(),
|
|
1888
1921
|
hasMore: z.boolean(),
|
|
1922
|
+
truncated: z.boolean().describe(
|
|
1923
|
+
"True if more conversations exist beyond this page — page on with `offset` + `nextOffset`."
|
|
1924
|
+
),
|
|
1889
1925
|
nextOffset: z.number().int().nullable()
|
|
1890
1926
|
});
|
|
1891
1927
|
const SearchMessagesSchema = z.object({
|
|
@@ -1904,7 +1940,7 @@ const SearchMessagesOutputSchema = z.object({
|
|
|
1904
1940
|
messages: z.array(MessageSchema),
|
|
1905
1941
|
count: z.number().int(),
|
|
1906
1942
|
hasMore: z.boolean(),
|
|
1907
|
-
|
|
1943
|
+
truncated: z.boolean().describe("True if more matches exist than were returned — raise `limit` or narrow the query."),
|
|
1908
1944
|
softCapWarning: z.string().optional()
|
|
1909
1945
|
});
|
|
1910
1946
|
const GetLogsSchema = z.object({
|
|
@@ -1971,7 +2007,9 @@ const ListContactsOutputSchema = z.object({
|
|
|
1971
2007
|
contacts: z.array(ContactSchema),
|
|
1972
2008
|
count: z.number().int(),
|
|
1973
2009
|
hasMore: z.boolean(),
|
|
1974
|
-
|
|
2010
|
+
truncated: z.boolean().describe("True if more contacts exist beyond this page — page on with `offset`."),
|
|
2011
|
+
totalAvailable: z.number().int().describe("Total contacts available across all pages."),
|
|
2012
|
+
totalCount: z.number().int().describe("Alias of `totalAvailable` (kept for back-compat).")
|
|
1975
2013
|
});
|
|
1976
2014
|
const RankedContactSchema = ContactSchema.extend({
|
|
1977
2015
|
score: z.number().describe("Relevance in [0,1]; higher = better. Results are sorted best-first."),
|
|
@@ -1984,7 +2022,9 @@ const SearchContactsSchema = z.object({
|
|
|
1984
2022
|
const SearchContactsOutputSchema = z.object({
|
|
1985
2023
|
query: z.string(),
|
|
1986
2024
|
contacts: z.array(RankedContactSchema),
|
|
1987
|
-
count: z.number().int()
|
|
2025
|
+
count: z.number().int(),
|
|
2026
|
+
truncated: z.boolean().describe("True if more contacts matched than were returned — raise `limit`."),
|
|
2027
|
+
totalAvailable: z.number().int().describe("Total contacts that matched the query.")
|
|
1988
2028
|
});
|
|
1989
2029
|
const GetContactSchema = z.object({
|
|
1990
2030
|
handle: z.string().optional().describe("Phone number or email to look up."),
|
|
@@ -1992,8 +2032,16 @@ const GetContactSchema = z.object({
|
|
|
1992
2032
|
}).refine((v) => v.handle !== void 0 || v.id !== void 0, {
|
|
1993
2033
|
message: "Provide either `handle` or `id`."
|
|
1994
2034
|
});
|
|
2035
|
+
const IdentitySchema = z.object({
|
|
2036
|
+
canonicalName: z.string().describe("Best display name for this person (or the handle itself)."),
|
|
2037
|
+
phones: z.array(z.string()).describe("Phone handles, E.164-normalized where derivable."),
|
|
2038
|
+
emails: z.array(z.string()).describe("Email handles, trimmed + lowercased."),
|
|
2039
|
+
handles: z.array(z.string()).describe("Every reachable handle, deduped — phones first, then emails.")
|
|
2040
|
+
});
|
|
1995
2041
|
const GetContactOutputSchema = z.object({
|
|
1996
2042
|
contact: ContactSchema.nullable(),
|
|
2043
|
+
/** Normalized cross-tool handle view (E.164 phones, lowercased emails). */
|
|
2044
|
+
identity: IdentitySchema.optional(),
|
|
1997
2045
|
/** Per-handle conversation mapping: which thread slug each handle chats under. */
|
|
1998
2046
|
threads: z.array(
|
|
1999
2047
|
z.object({
|
|
@@ -2032,7 +2080,9 @@ const ResolveHandleOutputSchema = z.object({
|
|
|
2032
2080
|
displayName: z.string(),
|
|
2033
2081
|
contactId: z.number().int().nullable(),
|
|
2034
2082
|
label: z.string().nullable(),
|
|
2035
|
-
resolved: z.boolean()
|
|
2083
|
+
resolved: z.boolean(),
|
|
2084
|
+
/** Normalized cross-tool handle view — populated even when unresolved. */
|
|
2085
|
+
identity: IdentitySchema.optional()
|
|
2036
2086
|
});
|
|
2037
2087
|
const CheckImessageAvailabilitySchema = z.object({
|
|
2038
2088
|
handle: nonEmptyString("Phone number or email to preflight-check for reachability.")
|
|
@@ -2057,11 +2107,12 @@ const SearchAttachmentsSchema = z.object({
|
|
|
2057
2107
|
chatIdentifier: z.string().optional().describe("Restrict to a single chat (use chat_identifier from list_conversations)."),
|
|
2058
2108
|
since: z.string().optional().describe("ISO date or relative ('1 week ago'). Lower bound on attachment creation."),
|
|
2059
2109
|
until: z.string().optional().describe("ISO date or relative. Upper bound on creation."),
|
|
2060
|
-
limit: z.number().int().min(0).default(20).describe("Max results. 0 = unlimited
|
|
2110
|
+
limit: z.number().int().min(0).default(20).describe("Max results. 0 = unlimited.")
|
|
2061
2111
|
});
|
|
2062
2112
|
const SearchAttachmentsOutputSchema = z.object({
|
|
2063
2113
|
attachments: z.array(AttachmentRecordSchema),
|
|
2064
|
-
count: z.number().int()
|
|
2114
|
+
count: z.number().int(),
|
|
2115
|
+
truncated: z.boolean().describe("True if more attachments matched than were returned — raise `limit`.")
|
|
2065
2116
|
});
|
|
2066
2117
|
const InitHumanSchema = z.object({
|
|
2067
2118
|
contact: nonEmptyString(
|
|
@@ -2415,7 +2466,7 @@ const TOOLS = [
|
|
|
2415
2466
|
},
|
|
2416
2467
|
{
|
|
2417
2468
|
name: "search_contacts",
|
|
2418
|
-
description: "Substring-match contacts by display name, phone number, or email.",
|
|
2469
|
+
description: "Substring-match contacts by display name, phone number, or email, ranked best-first (score + matchedField). Response reports `truncated` and `totalAvailable` so you know when more matched than were returned — raise `limit` to widen.",
|
|
2419
2470
|
annotations: annotations.read,
|
|
2420
2471
|
inputSchema: {
|
|
2421
2472
|
type: "object",
|
|
@@ -2429,7 +2480,7 @@ const TOOLS = [
|
|
|
2429
2480
|
},
|
|
2430
2481
|
{
|
|
2431
2482
|
name: "get_contact",
|
|
2432
|
-
description: "Fetch a single contact by handle (phone/email) or by numeric id, including each handle's thread slug (for send_message/get_messages). Returns null if not found. Includes `humansFile` — the path to this person's humans/v1 relationship file if one exists (read it for relationship context; init_human scaffolds one otherwise).",
|
|
2483
|
+
description: "Fetch a single contact by handle (phone/email) or by numeric id, including each handle's thread slug (for send_message/get_messages) and an `identity` block (canonicalName + E.164-normalized phones + lowercased emails + deduped handles). Returns null if not found. Includes `humansFile` — the path to this person's humans/v1 relationship file if one exists (read it for relationship context; init_human scaffolds one otherwise).",
|
|
2433
2484
|
annotations: annotations.read,
|
|
2434
2485
|
inputSchema: {
|
|
2435
2486
|
type: "object",
|
|
@@ -2459,7 +2510,7 @@ const TOOLS = [
|
|
|
2459
2510
|
},
|
|
2460
2511
|
{
|
|
2461
2512
|
name: "resolve_handle",
|
|
2462
|
-
description: "Resolve a phone number or email to its contact display name. Pass-through if unknown.",
|
|
2513
|
+
description: "Resolve a phone number or email to its contact display name. Pass-through if unknown. Always returns an `identity` block (canonicalName + E.164-normalized phones + lowercased emails + deduped handles) — even for an unknown handle, so you get it in canonical form.",
|
|
2463
2514
|
annotations: annotations.read,
|
|
2464
2515
|
inputSchema: {
|
|
2465
2516
|
type: "object",
|
|
@@ -2488,7 +2539,7 @@ const TOOLS = [
|
|
|
2488
2539
|
},
|
|
2489
2540
|
{
|
|
2490
2541
|
name: "search_attachments",
|
|
2491
|
-
description: "Search attachments (images, videos, files) by MIME type prefix, date range, and/or chat. Returns metadata only — use get_attachment to fetch bytes. Excludes stickers and Apple plugin payloads.",
|
|
2542
|
+
description: "Search attachments (images, videos, files) by MIME type prefix, date range, and/or chat. Returns metadata only — use get_attachment to fetch bytes. Excludes stickers and Apple plugin payloads. Response reports `truncated` (more matched than returned — raise `limit`).",
|
|
2492
2543
|
annotations: annotations.read,
|
|
2493
2544
|
inputSchema: {
|
|
2494
2545
|
type: "object",
|
|
@@ -3181,7 +3232,7 @@ ${formatted}${paginationLine}${perfLine}${humansLine}`,
|
|
|
3181
3232
|
messages: [],
|
|
3182
3233
|
count: 0,
|
|
3183
3234
|
hasMore: false,
|
|
3184
|
-
|
|
3235
|
+
truncated: false
|
|
3185
3236
|
});
|
|
3186
3237
|
}
|
|
3187
3238
|
const formatted = results.map((msg) => {
|
|
@@ -3195,7 +3246,7 @@ ${formatted}`, {
|
|
|
3195
3246
|
messages: results.map(messageToStructured),
|
|
3196
3247
|
count: results.length,
|
|
3197
3248
|
hasMore,
|
|
3198
|
-
|
|
3249
|
+
truncated: hasMore
|
|
3199
3250
|
});
|
|
3200
3251
|
}
|
|
3201
3252
|
async handleSendMessage(args) {
|
|
@@ -3462,6 +3513,7 @@ ${formatted}${humansLine}`, {
|
|
|
3462
3513
|
conversations: [],
|
|
3463
3514
|
count: 0,
|
|
3464
3515
|
hasMore: false,
|
|
3516
|
+
truncated: false,
|
|
3465
3517
|
nextOffset: null
|
|
3466
3518
|
});
|
|
3467
3519
|
}
|
|
@@ -3501,6 +3553,7 @@ ${formatted}`, {
|
|
|
3501
3553
|
}),
|
|
3502
3554
|
count: results.length,
|
|
3503
3555
|
hasMore,
|
|
3556
|
+
truncated: hasMore,
|
|
3504
3557
|
nextOffset: hasMore ? startAfter : null
|
|
3505
3558
|
});
|
|
3506
3559
|
}
|
|
@@ -3529,7 +3582,7 @@ ${formatted}`, {
|
|
|
3529
3582
|
messages: [],
|
|
3530
3583
|
count: 0,
|
|
3531
3584
|
hasMore: false,
|
|
3532
|
-
|
|
3585
|
+
truncated: false,
|
|
3533
3586
|
softCapWarning
|
|
3534
3587
|
});
|
|
3535
3588
|
}
|
|
@@ -3546,7 +3599,7 @@ ${formatted}`, {
|
|
|
3546
3599
|
messages: results.map(messageToStructured),
|
|
3547
3600
|
count: results.length,
|
|
3548
3601
|
hasMore,
|
|
3549
|
-
|
|
3602
|
+
truncated: hasMore,
|
|
3550
3603
|
softCapWarning
|
|
3551
3604
|
});
|
|
3552
3605
|
}
|
|
@@ -3563,6 +3616,8 @@ ${formatted}`, {
|
|
|
3563
3616
|
contacts: [],
|
|
3564
3617
|
count: 0,
|
|
3565
3618
|
hasMore: false,
|
|
3619
|
+
truncated: false,
|
|
3620
|
+
totalAvailable: total,
|
|
3566
3621
|
totalCount: total
|
|
3567
3622
|
});
|
|
3568
3623
|
}
|
|
@@ -3577,6 +3632,8 @@ ${formatted}`, {
|
|
|
3577
3632
|
contacts,
|
|
3578
3633
|
count: contacts.length,
|
|
3579
3634
|
hasMore,
|
|
3635
|
+
truncated: hasMore,
|
|
3636
|
+
totalAvailable: total,
|
|
3580
3637
|
totalCount: total
|
|
3581
3638
|
});
|
|
3582
3639
|
}
|
|
@@ -3590,7 +3647,9 @@ ${formatted}`, {
|
|
|
3590
3647
|
return toolText(`No contacts match "${query}".`, {
|
|
3591
3648
|
query,
|
|
3592
3649
|
contacts: [],
|
|
3593
|
-
count: 0
|
|
3650
|
+
count: 0,
|
|
3651
|
+
truncated: false,
|
|
3652
|
+
totalAvailable: 0
|
|
3594
3653
|
});
|
|
3595
3654
|
}
|
|
3596
3655
|
rememberSearch(
|
|
@@ -3621,7 +3680,9 @@ ${formatted}${hint}`,
|
|
|
3621
3680
|
score: m.score,
|
|
3622
3681
|
matchedField: m.matchedField
|
|
3623
3682
|
})),
|
|
3624
|
-
count: results.length
|
|
3683
|
+
count: results.length,
|
|
3684
|
+
truncated: ranked.length > results.length,
|
|
3685
|
+
totalAvailable: ranked.length
|
|
3625
3686
|
}
|
|
3626
3687
|
);
|
|
3627
3688
|
}
|
|
@@ -3668,10 +3729,17 @@ ${withThreads.map((t) => ` ${t.handle} → ${t.threadSlug}`).join("\n")}` : "";
|
|
|
3668
3729
|
const humansLine = humansHint ? humansHintText(humansHint) : `
|
|
3669
3730
|
|
|
3670
3731
|
_${HUMANS_INIT_HINT}_`;
|
|
3732
|
+
const identity = buildIdentity(
|
|
3733
|
+
contact.displayName,
|
|
3734
|
+
contact.phoneNumbers,
|
|
3735
|
+
contact.emails,
|
|
3736
|
+
defaultCountryFromEnv()
|
|
3737
|
+
);
|
|
3671
3738
|
return toolText(
|
|
3672
3739
|
`${sanitizeUserText(contact.displayName)} (id ${contact.id})${phones}${emails}${org}${threadLines}${humansLine}`,
|
|
3673
3740
|
{
|
|
3674
3741
|
contact,
|
|
3742
|
+
identity,
|
|
3675
3743
|
threads,
|
|
3676
3744
|
humansFile,
|
|
3677
3745
|
humansGuidance: humansHint?.guidance ?? HUMANS_INIT_HINT
|
|
@@ -3729,13 +3797,17 @@ ${lines}${hint}`,
|
|
|
3729
3797
|
const selectorHit = resolveContactSelector(handle);
|
|
3730
3798
|
const effectiveHandle = selectorHit?.handle ?? handle;
|
|
3731
3799
|
const lookup = this.db.contacts.lookupContact(effectiveHandle);
|
|
3800
|
+
const country = defaultCountryFromEnv();
|
|
3732
3801
|
if (lookup) {
|
|
3802
|
+
const contact = this.db.contacts.getContact(lookup.contactId);
|
|
3803
|
+
const identity = contact ? buildIdentity(contact.displayName, contact.phoneNumbers, contact.emails, country) : buildIdentityFromHandle(effectiveHandle, lookup.displayName, country);
|
|
3733
3804
|
return toolText(`${handle} → ${sanitizeUserText(lookup.displayName)}`, {
|
|
3734
3805
|
handle,
|
|
3735
3806
|
displayName: lookup.displayName,
|
|
3736
3807
|
contactId: lookup.contactId,
|
|
3737
3808
|
label: lookup.label ?? null,
|
|
3738
|
-
resolved: true
|
|
3809
|
+
resolved: true,
|
|
3810
|
+
identity
|
|
3739
3811
|
});
|
|
3740
3812
|
}
|
|
3741
3813
|
return toolText(`No contact for ${handle}.`, {
|
|
@@ -3743,7 +3815,8 @@ ${lines}${hint}`,
|
|
|
3743
3815
|
displayName: handle,
|
|
3744
3816
|
contactId: null,
|
|
3745
3817
|
label: null,
|
|
3746
|
-
resolved: false
|
|
3818
|
+
resolved: false,
|
|
3819
|
+
identity: buildIdentityFromHandle(effectiveHandle, null, country)
|
|
3747
3820
|
});
|
|
3748
3821
|
}
|
|
3749
3822
|
async handleCheckImessageAvailability(args) {
|
|
@@ -3774,14 +3847,17 @@ ${lines}${hint}`,
|
|
|
3774
3847
|
const sinceMs = since ? parseUserDate(since)?.getTime() : void 0;
|
|
3775
3848
|
const untilMs = until ? parseUserDate(until)?.getTime() : void 0;
|
|
3776
3849
|
const resolvedLimit = resolveLimit(limit);
|
|
3850
|
+
const bounded = resolvedLimit < Number.MAX_SAFE_INTEGER;
|
|
3777
3851
|
const opts = {
|
|
3778
|
-
limit: resolvedLimit
|
|
3852
|
+
limit: bounded ? resolvedLimit + 1 : resolvedLimit
|
|
3779
3853
|
};
|
|
3780
3854
|
if (mimePrefix !== void 0) opts.mimePrefix = mimePrefix;
|
|
3781
3855
|
if (chatIdentifier !== void 0) opts.chatIdentifier = chatIdentifier;
|
|
3782
3856
|
if (sinceMs !== void 0) opts.sinceMs = sinceMs;
|
|
3783
3857
|
if (untilMs !== void 0) opts.untilMs = untilMs;
|
|
3784
|
-
const
|
|
3858
|
+
const raw = this.db.searchAttachments(opts);
|
|
3859
|
+
const truncated = raw.length > resolvedLimit;
|
|
3860
|
+
const results = raw.slice(0, resolvedLimit);
|
|
3785
3861
|
const formatted = results.map(
|
|
3786
3862
|
(a) => `[${a.rowId}] ${a.mimeType ?? "?"} · ${a.totalBytes}B · ${a.createdDate.toISOString().slice(0, 10)} · ${a.transferName ?? a.filename}`
|
|
3787
3863
|
).join("\n");
|
|
@@ -3797,7 +3873,8 @@ ${formatted}`, {
|
|
|
3797
3873
|
createdDate: a.createdDate.toISOString(),
|
|
3798
3874
|
chatId: a.chatId
|
|
3799
3875
|
})),
|
|
3800
|
-
count: results.length
|
|
3876
|
+
count: results.length,
|
|
3877
|
+
truncated
|
|
3801
3878
|
});
|
|
3802
3879
|
}
|
|
3803
3880
|
async handleGetAttachment(args) {
|