@mgcrea/mcp-apple-messages 1.16.0 → 1.18.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/dist/cli.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { A as MESSAGES_SURFACE, V as BUILD_INFO, a as loadConfig, r as createServer } from "./server-
|
|
2
|
+
import { A as MESSAGES_SURFACE, V as BUILD_INFO, a as loadConfig, r as createServer } from "./server-BdWRSEL0.js";
|
|
3
3
|
import { runStdioServer } from "@mgcrea/mcp-apple-core";
|
|
4
4
|
//#region src/cli.ts
|
|
5
5
|
const LOG_PREFIX = "apple-messages-mcp";
|
package/dist/index.d.ts
CHANGED
|
@@ -132,6 +132,15 @@ type RangeQuery = {
|
|
|
132
132
|
fromApple?: number | undefined;
|
|
133
133
|
toApple?: number | undefined;
|
|
134
134
|
includeReactions?: boolean | undefined;
|
|
135
|
+
/**
|
|
136
|
+
* Narrow to one direction in SQL.
|
|
137
|
+
*
|
|
138
|
+
* `find_codes` wants received messages only, and used to get there by
|
|
139
|
+
* fetching `limit` rows and discarding the sent ones AFTERWARDS — so a busy
|
|
140
|
+
* few minutes of the user's own replies could push the code being looked for
|
|
141
|
+
* off the end of a page that was never about it.
|
|
142
|
+
*/
|
|
143
|
+
direction?: "sent" | "received" | undefined;
|
|
135
144
|
limit: number;
|
|
136
145
|
};
|
|
137
146
|
/**
|
|
@@ -148,7 +157,17 @@ declare const COUNT_GROUP_FIELDS: readonly ["day", "month", "chat", "handle", "d
|
|
|
148
157
|
type CountGroupField = (typeof COUNT_GROUP_FIELDS)[number];
|
|
149
158
|
type CountQuery = {
|
|
150
159
|
chatGuid?: string | undefined;
|
|
151
|
-
/**
|
|
160
|
+
/**
|
|
161
|
+
* Exact store handles to count, already resolved by the client.
|
|
162
|
+
*
|
|
163
|
+
* Preferred over `handle` below. The client resolves what the caller typed
|
|
164
|
+
* through the same last-nine-digits rule `send_message` uses, so
|
|
165
|
+
* "06 12 34 56 78" and "+33612345678" reach the same rows — which the
|
|
166
|
+
* substring match could not do, while `send_message`'s own description
|
|
167
|
+
* promises exactly that.
|
|
168
|
+
*/
|
|
169
|
+
handles?: string[] | undefined;
|
|
170
|
+
/** Substring of a handle. Only used when nothing resolved — see `handles`. */
|
|
152
171
|
handle?: string | undefined;
|
|
153
172
|
direction?: "sent" | "received" | undefined;
|
|
154
173
|
fromApple?: number | undefined;
|
|
@@ -433,6 +452,7 @@ declare class AppleMessagesClient {
|
|
|
433
452
|
fromApple?: number | undefined;
|
|
434
453
|
toApple?: number | undefined;
|
|
435
454
|
includeReactions?: boolean | undefined;
|
|
455
|
+
direction?: "sent" | "received" | undefined;
|
|
436
456
|
limit?: number | undefined;
|
|
437
457
|
}): RenderedMessage[];
|
|
438
458
|
searchMessages(query: string, limit?: number): RenderedMessage[];
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/build-info.ts","../src/config.ts","../src/client/locate.ts","../src/client/store.ts","../src/client/messages.ts","../src/client/dates.ts","../src/client/errors.ts","../src/client/ref.ts","../src/client/typedstream.ts","../src/client/jxa/core.ts","../src/client/jxa/write.ts","../src/server.ts","../src/tools/index.ts"],"mappings":";;;;;;cAkBa,YAAY;;;;;;;;;;;;;;;;;;cCSnB,cAAY,EAAA;;;;;;;;;;;;;;;;;;;;;GA4EP,EAAA,KAAA;KAEC,SAAS,EAAE,aAAa;cAEvB,aAAU,MAAS,OAAO,eAA2B;;;;;;;;;;;;;cC3FrD;;cAGA;KAaD,eAAe;EACzB;EACA;;EAEA;EACA;;cAGW,mBAAgB;cAQhB,cAAW;EACd;EAAgC;MACvC;;;cCiBU,gBAAa;KAMd;EACV;EACA,gBAAgB;EAChB,aAAa;EACb,eAAe;EACf,mBAAmB;EACnB;EACA;EACA;EACA;;KAGU;EACV;EACA;EACA;EACA;EACA;EACA;;EAEA;EACA;EACA;EACA;EACA;;EAEA;EACA;EACA;EACA;EACA;EACA;;EAEA;EACA;;EAEA;;EAEA;;KAGU;EACV;EACA;EACA;;EAEA;EACA;EACA;EACA;EACA;EACA;;KAGU;EACV;EACA;EACA;EACA;EACA;;;;;;;;;;;;cAaW;KAED,0BAA0B;KAE1B;EACV;;EAEA;EACA;EACA;EACA;EACA;;EAEA;;KAGU;EACV;;EAEA;EACA;EACA;EACA;;KAGU,cAAc;EACxB;EACA;;KAGU;EACV,QAAQ;EACR;EACA;;cAOW;;WACF,IAAI;WACJ;WACA,MAAM;EAEf,YAAY,IAAI,cAAc,cAAc,MAAM;;;;;;;;EAsGlD,MAAM,GAAG,aAAa;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/build-info.ts","../src/config.ts","../src/client/locate.ts","../src/client/store.ts","../src/client/messages.ts","../src/client/dates.ts","../src/client/errors.ts","../src/client/ref.ts","../src/client/typedstream.ts","../src/client/jxa/core.ts","../src/client/jxa/write.ts","../src/server.ts","../src/tools/index.ts"],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { A as MESSAGES_SURFACE, B as toAppleSeconds, C as locateStore, D as ChatNotFoundError, E as AppleMessagesError, F as SendTargetNotFoundError, I as CORE_DATA_EPOCH_OFFSET, L as appleSecondsSql, M as MessagesUnavailableError, N as SchemaDriftError, O as IndexUnavailableError, P as SendFailedError, R as fromAppleSeconds, S as defaultStorePath, T as PRELUDE, V as BUILD_INFO, _ as decodeMessageRef, a as loadConfig, b as ATTACHMENTS_RELATIVE, c as introspect, d as decodeAttributedBody, f as outline, g as decodeChatRef, h as MESSAGE_REF_VERSION, i as registerTools, j as MessageNotFoundError, k as MESSAGES_BUNDLE_ID, l as openStore, m as InvalidMessageRefError, n as SERVER_VERSION, o as AppleMessagesClient, p as CHAT_REF_VERSION, r as createServer, s as MessagesStore, t as SERVER_NAME, u as reactionLabel, v as encodeChatRef, w as SEND_MESSAGE, x as STORE_RELATIVE, y as encodeMessageRef, z as renderInstant } from "./server-
|
|
1
|
+
import { A as MESSAGES_SURFACE, B as toAppleSeconds, C as locateStore, D as ChatNotFoundError, E as AppleMessagesError, F as SendTargetNotFoundError, I as CORE_DATA_EPOCH_OFFSET, L as appleSecondsSql, M as MessagesUnavailableError, N as SchemaDriftError, O as IndexUnavailableError, P as SendFailedError, R as fromAppleSeconds, S as defaultStorePath, T as PRELUDE, V as BUILD_INFO, _ as decodeMessageRef, a as loadConfig, b as ATTACHMENTS_RELATIVE, c as introspect, d as decodeAttributedBody, f as outline, g as decodeChatRef, h as MESSAGE_REF_VERSION, i as registerTools, j as MessageNotFoundError, k as MESSAGES_BUNDLE_ID, l as openStore, m as InvalidMessageRefError, n as SERVER_VERSION, o as AppleMessagesClient, p as CHAT_REF_VERSION, r as createServer, s as MessagesStore, t as SERVER_NAME, u as reactionLabel, v as encodeChatRef, w as SEND_MESSAGE, x as STORE_RELATIVE, y as encodeMessageRef, z as renderInstant } from "./server-BdWRSEL0.js";
|
|
2
2
|
export { ATTACHMENTS_RELATIVE, AppleMessagesClient, AppleMessagesError, BUILD_INFO, CHAT_REF_VERSION, CORE_DATA_EPOCH_OFFSET, ChatNotFoundError, IndexUnavailableError, InvalidMessageRefError, MESSAGES_BUNDLE_ID, MESSAGES_SURFACE, MESSAGE_REF_VERSION, MessageNotFoundError, MessagesStore, MessagesUnavailableError, PRELUDE, SEND_MESSAGE, SERVER_NAME, SERVER_VERSION, STORE_RELATIVE, SchemaDriftError, SendFailedError, SendTargetNotFoundError, appleSecondsSql, createServer, decodeAttributedBody, decodeChatRef, decodeMessageRef, defaultStorePath, encodeChatRef, encodeMessageRef, fromAppleSeconds, introspect, loadConfig, locateStore, openStore, outline, reactionLabel, registerTools, renderInstant, toAppleSeconds };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AppleAutomationError, AppleAutomationError as AppleMessagesError, BaseConfigSchema, CORE_DATA_EPOCH_OFFSET, IndexUnavailableError, IndexUnavailableError as IndexUnavailableError$1, PreconditionError, SchemaDriftError, SchemaDriftError as SchemaDriftError$1, columnsOf, confirmArg, createOsascriptRunner, describeAggregation, describeStore, escapeLike, extractCode, fail, fingerprintSchema, groupByArg, limitArg, ok, openReadOnly, parseBool, parseConfig, parseIntOpt, promptArg, readPackageIdentity, registerSurfaceResources, registerWorkflowPrompt, requiredPromptArg, resolveLimit, trimmed, withBusyRetry, withLazyTools, wrap, wrapResult } from "@mgcrea/mcp-apple-core";
|
|
1
|
+
import { AppleAutomationError, AppleAutomationError as AppleMessagesError, BaseConfigSchema, CORE_DATA_EPOCH_OFFSET, IndexUnavailableError, IndexUnavailableError as IndexUnavailableError$1, PreconditionError, SchemaDriftError, SchemaDriftError as SchemaDriftError$1, columnsOf, confirmArg, createOsascriptRunner, describeAggregation, describeStore, escapeLike, extractCode, fail, fingerprintSchema, groupByArg, limitArg, ok, openReadOnly, parseBool, parseBound, parseConfig, parseIntOpt, promptArg, readPackageIdentity, registerSurfaceResources, registerWorkflowPrompt, requiredPromptArg, resolveLimit, trimmed, withBusyRetry, withLazyTools, wrap, wrapResult } from "@mgcrea/mcp-apple-core";
|
|
2
2
|
import { existsSync, mkdirSync, readFileSync, statSync, writeFileSync } from "node:fs";
|
|
3
3
|
import { homedir } from "node:os";
|
|
4
4
|
import { basename, isAbsolute, join, resolve, sep } from "node:path";
|
|
@@ -13,8 +13,8 @@ const pkg = readPackageIdentity(new URL("../package.json", import.meta.url), {
|
|
|
13
13
|
const BUILD_INFO = {
|
|
14
14
|
name: pkg.name,
|
|
15
15
|
version: pkg.version,
|
|
16
|
-
gitCommit: "
|
|
17
|
-
gitCommitDate: "2026-09-
|
|
16
|
+
gitCommit: "657cbf0",
|
|
17
|
+
gitCommitDate: "2026-09-07T21:40:45+02:00"
|
|
18
18
|
};
|
|
19
19
|
//#endregion
|
|
20
20
|
//#region src/client/dates.ts
|
|
@@ -1055,6 +1055,10 @@ var MessagesStore = class {
|
|
|
1055
1055
|
params.push(q.toApple);
|
|
1056
1056
|
}
|
|
1057
1057
|
if (!q.includeReactions && m.has("associated_message_type")) where.push(`(m."associated_message_type" IS NULL OR m."associated_message_type" = 0)`);
|
|
1058
|
+
if (q.direction && m.has("is_from_me")) {
|
|
1059
|
+
where.push(`m."is_from_me" = ?`);
|
|
1060
|
+
params.push(q.direction === "sent" ? 1 : 0);
|
|
1061
|
+
}
|
|
1058
1062
|
const sql = `
|
|
1059
1063
|
SELECT ${this.#messageColumns()}
|
|
1060
1064
|
FROM "message" m
|
|
@@ -1082,26 +1086,29 @@ var MessagesStore = class {
|
|
|
1082
1086
|
const needle = `%${escapeLike(query)}%`;
|
|
1083
1087
|
const reactionFilter = !includeReactions && m.has("associated_message_type") ? `AND (m."associated_message_type" IS NULL OR m."associated_message_type" = 0)` : "";
|
|
1084
1088
|
const cap = Math.max(1, Math.trunc(limit));
|
|
1085
|
-
const
|
|
1089
|
+
const column = this.db.prepare(`SELECT ${this.#messageColumns()}
|
|
1086
1090
|
FROM "message" m
|
|
1087
1091
|
${this.#joins()}
|
|
1088
1092
|
WHERE m."text" LIKE ? ESCAPE '\\' ${reactionFilter}
|
|
1089
1093
|
ORDER BY m."date" DESC
|
|
1090
1094
|
LIMIT ${cap}`).all(needle).map((r) => this.#toRow(r));
|
|
1091
|
-
if (
|
|
1095
|
+
if (!m.has("attributedBody")) return column.slice(0, cap);
|
|
1096
|
+
const floor = column.length >= cap ? column.at(-1)?.sentAt ?? null : null;
|
|
1092
1097
|
const blobOnly = this.db.prepare(`SELECT ${this.#messageColumns()}
|
|
1093
1098
|
FROM "message" m
|
|
1094
1099
|
${this.#joins()}
|
|
1095
1100
|
WHERE (m."text" IS NULL OR m."text" = '')
|
|
1096
1101
|
AND m."attributedBody" IS NOT NULL ${reactionFilter}
|
|
1097
|
-
|
|
1102
|
+
${floor === null ? "" : `AND ${appleSecondsSql("m.\"date\"")} >= ?`}
|
|
1103
|
+
ORDER BY m."date" DESC`).all(...floor === null ? [] : [floor]);
|
|
1098
1104
|
const lowered = query.toLowerCase();
|
|
1105
|
+
const decoded = [];
|
|
1099
1106
|
for (const raw of blobOnly) {
|
|
1100
|
-
if (results.length >= cap) break;
|
|
1101
1107
|
const row = this.#toRow(raw);
|
|
1102
|
-
if (row.text && row.text.toLowerCase().includes(lowered))
|
|
1108
|
+
if (row.text && row.text.toLowerCase().includes(lowered)) decoded.push(row);
|
|
1103
1109
|
}
|
|
1104
|
-
return
|
|
1110
|
+
if (decoded.length === 0) return column.slice(0, cap);
|
|
1111
|
+
return [...column, ...decoded].toSorted((a, b) => (b.sentAt ?? -Infinity) - (a.sentAt ?? -Infinity)).slice(0, cap);
|
|
1105
1112
|
}
|
|
1106
1113
|
byGuid(guid) {
|
|
1107
1114
|
const rows = this.db.prepare(`SELECT ${this.#messageColumns()}
|
|
@@ -1368,7 +1375,7 @@ var MessagesStore = class {
|
|
|
1368
1375
|
*/
|
|
1369
1376
|
#countFrom(q, field) {
|
|
1370
1377
|
const parts = [];
|
|
1371
|
-
if (q.handle || field === "handle") parts.push(`LEFT JOIN "handle" h ON h."ROWID" = m."handle_id"`);
|
|
1378
|
+
if (q.handle || q.handles?.length || field === "handle") parts.push(`LEFT JOIN "handle" h ON h."ROWID" = m."handle_id"`);
|
|
1372
1379
|
if (q.chatGuid || field === "chat") parts.push(`LEFT JOIN "chat_message_join" cmj ON cmj."message_id" = m."ROWID"`, `LEFT JOIN "chat" c ON c."ROWID" = cmj."chat_id"`);
|
|
1373
1380
|
return parts.join("\n ");
|
|
1374
1381
|
}
|
|
@@ -1384,7 +1391,10 @@ var MessagesStore = class {
|
|
|
1384
1391
|
where.push(`c."guid" = ?`);
|
|
1385
1392
|
params.push(q.chatGuid);
|
|
1386
1393
|
}
|
|
1387
|
-
if (q.
|
|
1394
|
+
if (q.handles?.length) {
|
|
1395
|
+
where.push(`h."id" IN (${q.handles.map(() => "?").join(",")})`);
|
|
1396
|
+
params.push(...q.handles);
|
|
1397
|
+
} else if (q.handle) {
|
|
1388
1398
|
where.push(`h."id" LIKE ? ESCAPE '\\'`);
|
|
1389
1399
|
params.push(`%${escapeLike(q.handle)}%`);
|
|
1390
1400
|
}
|
|
@@ -1648,6 +1658,7 @@ var AppleMessagesClient = class {
|
|
|
1648
1658
|
...opts.fromApple === void 0 ? {} : { fromApple: opts.fromApple },
|
|
1649
1659
|
...opts.toApple === void 0 ? {} : { toApple: opts.toApple },
|
|
1650
1660
|
...opts.includeReactions === void 0 ? {} : { includeReactions: opts.includeReactions },
|
|
1661
|
+
...opts.direction === void 0 ? {} : { direction: opts.direction },
|
|
1651
1662
|
limit: resolveLimit(opts.limit, this.#config.maxResults)
|
|
1652
1663
|
}));
|
|
1653
1664
|
}
|
|
@@ -1780,8 +1791,11 @@ var AppleMessagesClient = class {
|
|
|
1780
1791
|
* `searchMessages`, which has the decode pass that makes it complete.
|
|
1781
1792
|
*/
|
|
1782
1793
|
countMessages(q, groupBy) {
|
|
1783
|
-
const
|
|
1794
|
+
const store = this.#require();
|
|
1795
|
+
const resolved = q.handle ? this.#handlesLike(q.handle) : [];
|
|
1796
|
+
const result = store.countMessages({
|
|
1784
1797
|
...q,
|
|
1798
|
+
...resolved.length ? { handles: resolved } : {},
|
|
1785
1799
|
limit: resolveLimit(q.limit, this.#config.maxResults)
|
|
1786
1800
|
}, groupBy);
|
|
1787
1801
|
if (!("groups" in result)) return renderCount(result);
|
|
@@ -1816,7 +1830,7 @@ var AppleMessagesClient = class {
|
|
|
1816
1830
|
return {
|
|
1817
1831
|
guid,
|
|
1818
1832
|
chat,
|
|
1819
|
-
handle: chat
|
|
1833
|
+
handle: chat && !chat.isGroup ? chat.participants[0] ?? null : null
|
|
1820
1834
|
};
|
|
1821
1835
|
}
|
|
1822
1836
|
const to = input.to?.trim();
|
|
@@ -1830,15 +1844,7 @@ var AppleMessagesClient = class {
|
|
|
1830
1844
|
chat: null,
|
|
1831
1845
|
handle: to
|
|
1832
1846
|
};
|
|
1833
|
-
const
|
|
1834
|
-
const wantedSuffix = kind === "phone" ? suffixKey(to) : null;
|
|
1835
|
-
const wantedEmail = kind === "email" ? emailKey(to) : null;
|
|
1836
|
-
const candidates = store.handles().filter((h) => {
|
|
1837
|
-
if (h === to) return true;
|
|
1838
|
-
if (wantedEmail) return emailKey(h) === wantedEmail;
|
|
1839
|
-
if (wantedSuffix) return suffixKey(h) === wantedSuffix;
|
|
1840
|
-
return false;
|
|
1841
|
-
});
|
|
1847
|
+
const candidates = this.#handlesLike(to);
|
|
1842
1848
|
if (!candidates.length) return {
|
|
1843
1849
|
guid: null,
|
|
1844
1850
|
chat: null,
|
|
@@ -1852,6 +1858,30 @@ var AppleMessagesClient = class {
|
|
|
1852
1858
|
};
|
|
1853
1859
|
}
|
|
1854
1860
|
/**
|
|
1861
|
+
* Every handle in the store that names the same correspondent.
|
|
1862
|
+
*
|
|
1863
|
+
* The last-nine-digits rule `packages/contacts` measured, so
|
|
1864
|
+
* "06 12 34 56 78", "+33 6 12 34 56 78" and "+33612345678" all reach the same
|
|
1865
|
+
* rows. Used by the send lane to pick a chat, and by `count_messages`, which
|
|
1866
|
+
* used a substring LIKE instead — so counting by a locally-spelled number
|
|
1867
|
+
* answered zero while `send_message` to that same string worked. One
|
|
1868
|
+
* surface, two ideas of what a handle is.
|
|
1869
|
+
*/
|
|
1870
|
+
#handlesLike(handle) {
|
|
1871
|
+
const store = this.store();
|
|
1872
|
+
if (!store) return [];
|
|
1873
|
+
const wanted = handle.trim();
|
|
1874
|
+
const kind = handleKind(wanted);
|
|
1875
|
+
const wantedSuffix = kind === "phone" ? suffixKey(wanted) : null;
|
|
1876
|
+
const wantedEmail = kind === "email" ? emailKey(wanted) : null;
|
|
1877
|
+
return store.handles().filter((h) => {
|
|
1878
|
+
if (h === wanted) return true;
|
|
1879
|
+
if (wantedEmail) return emailKey(h) === wantedEmail;
|
|
1880
|
+
if (wantedSuffix) return suffixKey(h) === wantedSuffix;
|
|
1881
|
+
return false;
|
|
1882
|
+
});
|
|
1883
|
+
}
|
|
1884
|
+
/**
|
|
1855
1885
|
* Find the row Messages wrote, or say plainly that it was not found.
|
|
1856
1886
|
*
|
|
1857
1887
|
* `docs/messages.md` left this as an open question — "whether a send should
|
|
@@ -1885,7 +1915,7 @@ var AppleMessagesClient = class {
|
|
|
1885
1915
|
const store = this.store();
|
|
1886
1916
|
if (!store) return null;
|
|
1887
1917
|
const rows = store.sentSince([guid], since, 10);
|
|
1888
|
-
const hit =
|
|
1918
|
+
const hit = text === null ? rows[0] : rows.find((r) => r.text === text);
|
|
1889
1919
|
if (hit) return this.#render([hit])[0] ?? null;
|
|
1890
1920
|
if (Date.now() >= deadline) return null;
|
|
1891
1921
|
await new Promise((resolve) => setTimeout(resolve, 250));
|
|
@@ -2280,8 +2310,18 @@ the blob-storage change described in the guide, not the end of the conversation
|
|
|
2280
2310
|
//#region src/tools/util.ts
|
|
2281
2311
|
const chatRefArg = z.string().optional().describe("An opaque chat ref from apple_messages_list_chats (looks like \"mc1:<guid>\"). Do not construct one by hand.");
|
|
2282
2312
|
const messageRefArg = z.string().min(1).describe("An opaque message ref from a list or search result (looks like \"m1:<guid>\"). Do not construct one by hand.");
|
|
2283
|
-
const fromArg = z.string().optional().describe("Start of the window
|
|
2284
|
-
const toArg = z.string().optional().describe("End of the window,
|
|
2313
|
+
const fromArg = z.string().optional().describe("Start of the window — \"2026-08-01\" (a whole day, local), \"2026-08-01T09:00\", or a relative form like \"-7d\", \"yesterday\" or \"last monday\".");
|
|
2314
|
+
const toArg = z.string().optional().describe("End of the window, same forms as `from`. A bare day includes ALL of that day. Defaults to 30 days after `from`, or to now when `from` is omitted too.");
|
|
2315
|
+
/**
|
|
2316
|
+
* One bound, through the grammar every surface shares.
|
|
2317
|
+
*
|
|
2318
|
+
* This replaced two copies of a local `new Date(raw)`, which had the bug that
|
|
2319
|
+
* grammar exists to prevent: `new Date("2026-08-01")` is UTC midnight while
|
|
2320
|
+
* `new Date("2026-08-01T00:00")` is LOCAL midnight, so the two spellings the
|
|
2321
|
+
* descriptions above treat as equivalent bounded a query hours apart — and the
|
|
2322
|
+
* day and month buckets these windows feed are local calendar dates.
|
|
2323
|
+
*/
|
|
2324
|
+
const bound = (raw, field, edge) => raw === void 0 ? void 0 : parseBound(field, raw, edge);
|
|
2285
2325
|
const includeReactionsArg = z.boolean().optional().describe("Include tapbacks as if they were messages. Off by default, and you almost never want it on: a tapback renders as `Liked \"see you at 8\"`, which nobody typed. Use apple_messages_get_message to see the reactions on a specific message instead.");
|
|
2286
2326
|
//#endregion
|
|
2287
2327
|
//#region src/tools/diagnostics.ts
|
|
@@ -2462,6 +2502,8 @@ CHECK \`ageSeconds\` BEFORE USING A CODE. An expired code is still in the store
|
|
|
2462
2502
|
|
|
2463
2503
|
\`confidence\` says how the match was made and is not decoration. "high" means the code was bound to a domain (\`@site.com #123456\`) or sat directly against a word like "verification code" — safe to use. "medium" means the keyword was further away, or two candidates tied. "low" means there was no keyword at all and only the sender being a shortcode suggested it. On anything below high, read the message with apple_messages_get_message and confirm against the body before using the digits.
|
|
2464
2504
|
|
|
2505
|
+
\`service\` is a trust signal, not a detail. iMessage is authenticated against an Apple ID; SMS and RCS sender IDs are not, and can be forged. \`confidence\` measures how cleanly the code was EXTRACTED from the text — it says nothing about who sent it, so a spoofed SMS naming a domain scores "high" exactly like a real one. Most genuine codes do arrive by SMS, so this is not a reason to discard them; it is a reason not to treat a code as proof of anything. If a code arrives that the user did not just ask for, say which service delivered it instead of offering the digits.
|
|
2506
|
+
|
|
2465
2507
|
A \`matched\` value ending in \`-ambiguous\` means the message held more than one plausible code and this tool did not guess — confirm which one is wanted.
|
|
2466
2508
|
|
|
2467
2509
|
Returning nothing is the normal result when no code has arrived. It does NOT mean the code was missed, and it is not a reason to re-run with a longer window: if a code was sent it is in the store within seconds. Prefer asking the user to trigger a new one.`,
|
|
@@ -2479,9 +2521,11 @@ Returning nothing is the normal result when no code has arrived. It does NOT mea
|
|
|
2479
2521
|
const since = /* @__PURE__ */ new Date(Date.now() - minutes * 6e4);
|
|
2480
2522
|
const { fromApple } = client.window(since);
|
|
2481
2523
|
const needle = service?.trim().toLowerCase();
|
|
2524
|
+
const scan = needle ? client.config.maxResults : limit;
|
|
2482
2525
|
const codes = client.listMessages({
|
|
2483
2526
|
...fromApple === void 0 ? {} : { fromApple },
|
|
2484
|
-
|
|
2527
|
+
direction: "received",
|
|
2528
|
+
limit: scan
|
|
2485
2529
|
}).filter((m) => !m.fromMe).filter((m) => {
|
|
2486
2530
|
if (!needle) return true;
|
|
2487
2531
|
return `${m.from.name ?? ""} ${m.from.handle ?? ""} ${m.text ?? ""}`.toLowerCase().includes(needle);
|
|
@@ -2495,12 +2539,13 @@ Returning nothing is the normal result when no code has arrived. It does NOT mea
|
|
|
2495
2539
|
matched: match.matched,
|
|
2496
2540
|
...match.boundTo ? { boundTo: match.boundTo } : {},
|
|
2497
2541
|
from: m.from,
|
|
2542
|
+
service: m.service,
|
|
2498
2543
|
sentAt: m.sentAt,
|
|
2499
2544
|
ageSeconds: Number.isNaN(sentAtMs) ? null : Math.max(0, Math.round((Date.now() - sentAtMs) / 1e3)),
|
|
2500
2545
|
ref: m.ref,
|
|
2501
2546
|
chat: m.chat
|
|
2502
2547
|
}];
|
|
2503
|
-
});
|
|
2548
|
+
}).slice(0, limit);
|
|
2504
2549
|
return {
|
|
2505
2550
|
windowMinutes: minutes,
|
|
2506
2551
|
searchedSince: since.toISOString(),
|
|
@@ -2511,13 +2556,6 @@ Returning nothing is the normal result when no code has arrived. It does NOT mea
|
|
|
2511
2556
|
};
|
|
2512
2557
|
//#endregion
|
|
2513
2558
|
//#region src/tools/counts.ts
|
|
2514
|
-
/** ISO-8601 in, or a clear refusal. Same grammar as `list_messages`. */
|
|
2515
|
-
const parseBound$1 = (raw, field) => {
|
|
2516
|
-
if (raw === void 0) return void 0;
|
|
2517
|
-
const d = new Date(raw);
|
|
2518
|
-
if (Number.isNaN(d.getTime())) throw new Error(`Could not read ${field} from ${JSON.stringify(raw)}. Use ISO-8601: "2026-08-01" or "2026-08-01T09:00".`);
|
|
2519
|
-
return d;
|
|
2520
|
-
};
|
|
2521
2559
|
/**
|
|
2522
2560
|
* The cheap-answer lane on this surface: counts, and counts per group.
|
|
2523
2561
|
*
|
|
@@ -2539,7 +2577,7 @@ const registerCountTools = (server, client) => {
|
|
|
2539
2577
|
description: "Count messages without reading them. Answers 'how many', 'how many did I send', 'who do I message most' and 'which month was busiest' as arithmetic the store does, rather than a page of conversations you tally by hand. Every result splits `sent` and `received`.\n\n`groupBy` counts per day, month, chat, handle or direction, over EVERY match rather than the first `limit` of them — `limit` caps how many groups come back. Grouping by handle is the one to reach for when a person has several conversations, since apple_messages_list_chats already gives you per-CHAT totals.\n\nCounts metadata only: there is no text filter here, because message bodies from 2026 onward live in an archived blob that SQL cannot see, and a count that quietly skipped them would look exactly like a correct one. Use apple_messages_search_messages for anything about what was said. Tapbacks are excluded unless you ask for them.",
|
|
2540
2578
|
inputSchema: {
|
|
2541
2579
|
chatRef: chatRefArg,
|
|
2542
|
-
handle: z.string().optional().describe("Only messages with this correspondent — a phone number or email,
|
|
2580
|
+
handle: z.string().optional().describe("Only messages with this correspondent — a phone number or email. Spellings of the same number match each other, so \"06 12 34 56 78\" and \"+33612345678\" are the same person, exactly as they are for send_message. A fragment that resolves to nobody falls back to a substring match. Spans every chat they appear in, which is the difference from chatRef."),
|
|
2543
2581
|
direction: z.enum(["sent", "received"]).optional().describe("Only what you sent, or only what you received. Omit for both."),
|
|
2544
2582
|
from: fromArg,
|
|
2545
2583
|
to: z.string().optional().describe("End of the window, ISO-8601, exclusive. Omit to count up to now."),
|
|
@@ -2549,7 +2587,7 @@ const registerCountTools = (server, client) => {
|
|
|
2549
2587
|
},
|
|
2550
2588
|
annotations: { readOnlyHint: true }
|
|
2551
2589
|
}, async ({ chatRef, handle, direction, from, to, includeReactions, groupBy, limit }) => wrap(async () => {
|
|
2552
|
-
const window = client.window(
|
|
2590
|
+
const window = client.window(bound(from, "from", "start"), bound(to, "to", "end"));
|
|
2553
2591
|
const result = client.countMessages({
|
|
2554
2592
|
...chatRef ? { chatGuid: decodeChatRef(chatRef) } : {},
|
|
2555
2593
|
...handle === void 0 ? {} : { handle },
|
|
@@ -2567,13 +2605,6 @@ const registerCountTools = (server, client) => {
|
|
|
2567
2605
|
};
|
|
2568
2606
|
//#endregion
|
|
2569
2607
|
//#region src/tools/messages.ts
|
|
2570
|
-
/** ISO-8601 in, or a clear refusal. No relative grammar on this surface yet. */
|
|
2571
|
-
const parseBound = (raw, field) => {
|
|
2572
|
-
if (raw === void 0) return void 0;
|
|
2573
|
-
const d = new Date(raw);
|
|
2574
|
-
if (Number.isNaN(d.getTime())) throw new Error(`Could not read ${field} from ${JSON.stringify(raw)}. Use ISO-8601: "2026-08-01" or "2026-08-01T09:00".`);
|
|
2575
|
-
return d;
|
|
2576
|
-
};
|
|
2577
2608
|
/**
|
|
2578
2609
|
* Close a range that named only a start.
|
|
2579
2610
|
*
|
|
@@ -2603,8 +2634,8 @@ const registerMessageTools = (server, client) => {
|
|
|
2603
2634
|
},
|
|
2604
2635
|
annotations: { readOnlyHint: true }
|
|
2605
2636
|
}, async ({ chatRef, from, to, includeReactions, limit }) => wrap(async () => {
|
|
2606
|
-
const fromDate =
|
|
2607
|
-
const window = client.window(fromDate, closeRange(fromDate,
|
|
2637
|
+
const fromDate = bound(from, "from", "start");
|
|
2638
|
+
const window = client.window(fromDate, closeRange(fromDate, bound(to, "to", "end"), client.config.defaultRangeDays));
|
|
2608
2639
|
return client.listMessages({
|
|
2609
2640
|
...chatRef ? { chatRef: decodeChatRef(chatRef) } : {},
|
|
2610
2641
|
...window,
|
|
@@ -2713,4 +2744,4 @@ const createServer = (opts) => {
|
|
|
2713
2744
|
//#endregion
|
|
2714
2745
|
export { MESSAGES_SURFACE as A, toAppleSeconds as B, locateStore as C, ChatNotFoundError as D, AppleMessagesError as E, SendTargetNotFoundError as F, CORE_DATA_EPOCH_OFFSET as I, appleSecondsSql as L, MessagesUnavailableError as M, SchemaDriftError$1 as N, IndexUnavailableError$1 as O, SendFailedError as P, fromAppleSeconds as R, defaultStorePath as S, PRELUDE as T, BUILD_INFO as V, decodeMessageRef as _, loadConfig$1 as a, ATTACHMENTS_RELATIVE as b, introspect as c, decodeAttributedBody as d, outline as f, decodeChatRef as g, MESSAGE_REF_VERSION as h, registerTools as i, MessageNotFoundError as j, MESSAGES_BUNDLE_ID as k, openStore as l, InvalidMessageRefError as m, SERVER_VERSION as n, AppleMessagesClient as o, CHAT_REF_VERSION as p, createServer as r, MessagesStore as s, SERVER_NAME as t, reactionLabel as u, encodeChatRef as v, SEND_MESSAGE as w, STORE_RELATIVE as x, encodeMessageRef as y, renderInstant as z };
|
|
2715
2746
|
|
|
2716
|
-
//# sourceMappingURL=server-
|
|
2747
|
+
//# sourceMappingURL=server-BdWRSEL0.js.map
|