@elizaos/plugin-imessage 2.0.3-beta.2 → 2.0.3-beta.3

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 (58) hide show
  1. package/dist/accounts.d.ts +135 -0
  2. package/dist/accounts.d.ts.map +1 -0
  3. package/dist/accounts.js +209 -0
  4. package/dist/accounts.js.map +1 -0
  5. package/dist/api/bluebubbles-routes.d.ts +10 -0
  6. package/dist/api/bluebubbles-routes.d.ts.map +1 -0
  7. package/dist/api/bluebubbles-routes.js +132 -0
  8. package/dist/api/bluebubbles-routes.js.map +1 -0
  9. package/dist/api/imessage-routes.d.ts +68 -0
  10. package/dist/api/imessage-routes.d.ts.map +1 -0
  11. package/dist/api/imessage-routes.js +228 -0
  12. package/dist/api/imessage-routes.js.map +1 -0
  13. package/dist/chatdb-reader.d.ts +240 -0
  14. package/dist/chatdb-reader.d.ts.map +1 -0
  15. package/dist/chatdb-reader.js +667 -0
  16. package/dist/chatdb-reader.js.map +1 -0
  17. package/dist/config.d.ts +60 -0
  18. package/dist/config.d.ts.map +1 -0
  19. package/dist/config.js +8 -0
  20. package/dist/config.js.map +1 -0
  21. package/dist/connector-account-provider.d.ts +18 -0
  22. package/dist/connector-account-provider.d.ts.map +1 -0
  23. package/dist/connector-account-provider.js +83 -0
  24. package/dist/connector-account-provider.js.map +1 -0
  25. package/dist/contacts-reader.d.ts +141 -0
  26. package/dist/contacts-reader.d.ts.map +1 -0
  27. package/dist/contacts-reader.js +359 -0
  28. package/dist/contacts-reader.js.map +1 -0
  29. package/dist/data-routes.d.ts +21 -0
  30. package/dist/data-routes.d.ts.map +1 -0
  31. package/dist/data-routes.js +280 -0
  32. package/dist/data-routes.js.map +1 -0
  33. package/dist/index.d.ts +24 -0
  34. package/dist/index.d.ts.map +1 -0
  35. package/dist/index.js +83 -0
  36. package/dist/index.js.map +1 -0
  37. package/dist/providers/index.d.ts +4 -0
  38. package/dist/providers/index.d.ts.map +1 -0
  39. package/dist/providers/index.js +5 -0
  40. package/dist/providers/index.js.map +1 -0
  41. package/dist/rpc.d.ts +206 -0
  42. package/dist/rpc.d.ts.map +1 -0
  43. package/dist/rpc.js +393 -0
  44. package/dist/rpc.js.map +1 -0
  45. package/dist/service.d.ts +264 -0
  46. package/dist/service.d.ts.map +1 -0
  47. package/dist/service.js +1705 -0
  48. package/dist/service.js.map +1 -0
  49. package/dist/setup-routes.d.ts +26 -0
  50. package/dist/setup-routes.d.ts.map +1 -0
  51. package/dist/setup-routes.js +139 -0
  52. package/dist/setup-routes.js.map +1 -0
  53. package/dist/types.d.ts +192 -0
  54. package/dist/types.d.ts.map +1 -0
  55. package/dist/types.js +138 -0
  56. package/dist/types.js.map +1 -0
  57. package/package.json +4 -3
  58. package/registry-entry.json +103 -0
package/dist/rpc.js ADDED
@@ -0,0 +1,393 @@
1
+ import { spawn } from "node:child_process";
2
+ import { homedir } from "node:os";
3
+ import { resolve as resolvePath } from "node:path";
4
+ import { createInterface } from "node:readline";
5
+ /**
6
+ * Default probe timeout in milliseconds
7
+ */
8
+ export const DEFAULT_PROBE_TIMEOUT_MS = 5000;
9
+ /**
10
+ * Default request timeout in milliseconds
11
+ */
12
+ export const DEFAULT_REQUEST_TIMEOUT_MS = 30000;
13
+ /**
14
+ * Resolves a path with ~ expansion
15
+ */
16
+ function resolveUserPath(path) {
17
+ if (path.startsWith("~/")) {
18
+ return resolvePath(homedir(), path.slice(2));
19
+ }
20
+ return resolvePath(path);
21
+ }
22
+ /**
23
+ * iMessage RPC client for communicating with the imsg CLI tool
24
+ */
25
+ export class IMessageRpcClient {
26
+ cliPath;
27
+ dbPath;
28
+ onNotification;
29
+ onError;
30
+ onClose;
31
+ pending = new Map();
32
+ closedPromise;
33
+ closedResolve = null;
34
+ child = null;
35
+ reader = null;
36
+ nextId = 1;
37
+ started = false;
38
+ constructor(opts = {}) {
39
+ this.cliPath = opts.cliPath?.trim() || "imsg";
40
+ this.dbPath = opts.dbPath?.trim() ? resolveUserPath(opts.dbPath) : undefined;
41
+ this.onNotification = opts.onNotification;
42
+ this.onError = opts.onError;
43
+ this.onClose = opts.onClose;
44
+ this.closedPromise = new Promise((resolve) => {
45
+ this.closedResolve = resolve;
46
+ });
47
+ }
48
+ /**
49
+ * Starts the RPC client by spawning the CLI process
50
+ */
51
+ async start() {
52
+ if (this.child) {
53
+ return;
54
+ }
55
+ const args = ["rpc"];
56
+ if (this.dbPath) {
57
+ args.push("--db", this.dbPath);
58
+ }
59
+ const child = spawn(this.cliPath, args, {
60
+ stdio: ["pipe", "pipe", "pipe"],
61
+ });
62
+ this.child = child;
63
+ this.started = true;
64
+ this.reader = createInterface({ input: child.stdout });
65
+ this.reader.on("line", (line) => {
66
+ const trimmed = line.trim();
67
+ if (!trimmed) {
68
+ return;
69
+ }
70
+ this.handleLine(trimmed);
71
+ });
72
+ child.stderr.on("data", (chunk) => {
73
+ const lines = chunk.toString().split(/\r?\n/);
74
+ for (const line of lines) {
75
+ if (!line.trim()) {
76
+ continue;
77
+ }
78
+ this.onError?.(new Error(`imsg rpc stderr: ${line.trim()}`));
79
+ }
80
+ });
81
+ child.on("error", (err) => {
82
+ this.failAll(err instanceof Error ? err : new Error(String(err)));
83
+ this.onError?.(err instanceof Error ? err : new Error(String(err)));
84
+ this.closedResolve?.();
85
+ });
86
+ child.on("close", (code, signal) => {
87
+ if (code !== 0 && code !== null) {
88
+ const reason = signal ? `signal ${signal}` : `code ${code}`;
89
+ this.failAll(new Error(`imsg rpc exited (${reason})`));
90
+ }
91
+ else {
92
+ this.failAll(new Error("imsg rpc closed"));
93
+ }
94
+ this.onClose?.(code, signal);
95
+ this.closedResolve?.();
96
+ });
97
+ }
98
+ /**
99
+ * Stops the RPC client
100
+ */
101
+ async stop() {
102
+ if (!this.child) {
103
+ return;
104
+ }
105
+ this.reader?.close();
106
+ this.reader = null;
107
+ this.child.stdin.end();
108
+ const child = this.child;
109
+ this.child = null;
110
+ await Promise.race([
111
+ this.closedPromise,
112
+ new Promise((resolve) => {
113
+ setTimeout(() => {
114
+ if (!child.killed) {
115
+ child.kill("SIGTERM");
116
+ }
117
+ resolve();
118
+ }, 500);
119
+ }),
120
+ ]);
121
+ }
122
+ /**
123
+ * Waits for the RPC client to close
124
+ */
125
+ async waitForClose() {
126
+ await this.closedPromise;
127
+ }
128
+ /**
129
+ * Checks if the client is running
130
+ */
131
+ isRunning() {
132
+ return this.child !== null && this.started;
133
+ }
134
+ /**
135
+ * Makes an RPC request
136
+ */
137
+ async request(method, params, opts) {
138
+ if (!this.child?.stdin) {
139
+ throw new Error("imsg rpc not running");
140
+ }
141
+ const id = this.nextId++;
142
+ const payload = {
143
+ jsonrpc: "2.0",
144
+ id,
145
+ method,
146
+ params: params ?? {},
147
+ };
148
+ const line = `${JSON.stringify(payload)}\n`;
149
+ const timeoutMs = opts?.timeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;
150
+ const response = new Promise((resolve, reject) => {
151
+ const key = String(id);
152
+ const timer = timeoutMs > 0
153
+ ? setTimeout(() => {
154
+ this.pending.delete(key);
155
+ reject(new Error(`imsg rpc timeout (${method})`));
156
+ }, timeoutMs)
157
+ : undefined;
158
+ this.pending.set(key, {
159
+ resolve: (value) => resolve(value),
160
+ reject,
161
+ timer,
162
+ });
163
+ });
164
+ this.child.stdin.write(line);
165
+ return await response;
166
+ }
167
+ /**
168
+ * Handles an incoming line from the RPC process
169
+ */
170
+ handleLine(line) {
171
+ let parsed;
172
+ try {
173
+ parsed = JSON.parse(line);
174
+ }
175
+ catch (err) {
176
+ const detail = err instanceof Error ? err.message : String(err);
177
+ this.onError?.(new Error(`imsg rpc: failed to parse ${line}: ${detail}`));
178
+ return;
179
+ }
180
+ // Handle response with ID
181
+ if (parsed.id !== undefined && parsed.id !== null) {
182
+ const key = String(parsed.id);
183
+ const pending = this.pending.get(key);
184
+ if (!pending) {
185
+ return;
186
+ }
187
+ if (pending.timer) {
188
+ clearTimeout(pending.timer);
189
+ }
190
+ this.pending.delete(key);
191
+ if (parsed.error) {
192
+ const baseMessage = parsed.error.message ?? "imsg rpc error";
193
+ const details = parsed.error.data;
194
+ const code = parsed.error.code;
195
+ const suffixes = [];
196
+ if (typeof code === "number") {
197
+ suffixes.push(`code=${code}`);
198
+ }
199
+ if (details !== undefined) {
200
+ const detailText = typeof details === "string" ? details : JSON.stringify(details, null, 2);
201
+ if (detailText) {
202
+ suffixes.push(detailText);
203
+ }
204
+ }
205
+ const msg = suffixes.length > 0 ? `${baseMessage}: ${suffixes.join(" ")}` : baseMessage;
206
+ pending.reject(new Error(msg));
207
+ return;
208
+ }
209
+ pending.resolve(parsed.result);
210
+ return;
211
+ }
212
+ // Handle notification
213
+ if (parsed.method) {
214
+ this.onNotification?.({
215
+ method: parsed.method,
216
+ params: parsed.params,
217
+ });
218
+ }
219
+ }
220
+ /**
221
+ * Fails all pending requests
222
+ */
223
+ failAll(err) {
224
+ for (const [key, pending] of this.pending.entries()) {
225
+ if (pending.timer) {
226
+ clearTimeout(pending.timer);
227
+ }
228
+ pending.reject(err);
229
+ this.pending.delete(key);
230
+ }
231
+ }
232
+ }
233
+ /**
234
+ * Creates and starts an iMessage RPC client
235
+ */
236
+ export async function createIMessageRpcClient(opts = {}) {
237
+ const client = new IMessageRpcClient(opts);
238
+ await client.start();
239
+ return client;
240
+ }
241
+ /**
242
+ * Probes the iMessage RPC to check connectivity
243
+ */
244
+ export async function probeIMessageRpc(params) {
245
+ const client = new IMessageRpcClient({
246
+ cliPath: params.cliPath,
247
+ dbPath: params.dbPath,
248
+ });
249
+ try {
250
+ await client.start();
251
+ await client.request("chats.list", { limit: 1 }, {
252
+ timeoutMs: params.timeoutMs ?? DEFAULT_PROBE_TIMEOUT_MS,
253
+ });
254
+ await client.stop();
255
+ return { ok: true };
256
+ }
257
+ catch (err) {
258
+ await client.stop().catch(() => { });
259
+ return {
260
+ ok: false,
261
+ error: err instanceof Error ? err.message : String(err),
262
+ };
263
+ }
264
+ }
265
+ /**
266
+ * Lists all contacts via iMessage RPC
267
+ */
268
+ export async function listContacts(_client) {
269
+ throw new Error("imsg RPC does not expose contacts");
270
+ }
271
+ /**
272
+ * Lists all chats via iMessage RPC
273
+ */
274
+ export async function listChats(client, params = {}) {
275
+ const response = await client.request("chats.list", {
276
+ limit: params.limit ?? 20,
277
+ });
278
+ const chats = Array.isArray(response.chats) ? response.chats : [];
279
+ return chats.map((chat) => {
280
+ const participants = Array.isArray(chat.participants)
281
+ ? chat.participants.filter((entry) => typeof entry === "string" && entry.trim().length > 0)
282
+ : [];
283
+ const lastMessageAt = typeof chat.last_message_at === "string" ? Date.parse(chat.last_message_at) : Number.NaN;
284
+ return {
285
+ id: typeof chat.id === "string" || typeof chat.id === "number" ? String(chat.id) : "",
286
+ chatIdentifier: typeof chat.identifier === "string" ? chat.identifier : "",
287
+ guid: typeof chat.guid === "string" ? chat.guid : undefined,
288
+ displayName: typeof chat.name === "string" && chat.name.trim().length > 0 ? chat.name.trim() : undefined,
289
+ isGroup: Boolean(chat.is_group),
290
+ participants,
291
+ service: typeof chat.service === "string" ? chat.service : undefined,
292
+ lastMessageDate: Number.isFinite(lastMessageAt) ? lastMessageAt : undefined,
293
+ };
294
+ });
295
+ }
296
+ /**
297
+ * Gets recent messages from a chat
298
+ */
299
+ export async function getMessages(client, params) {
300
+ const chatId = typeof params.chatId === "number" ? params.chatId : Number.parseInt(String(params.chatId), 10);
301
+ if (!Number.isFinite(chatId)) {
302
+ throw new Error("chatId must be numeric for imsg history requests");
303
+ }
304
+ const response = await client.request("messages.history", {
305
+ chat_id: chatId,
306
+ limit: params.limit,
307
+ attachments: params.attachments,
308
+ participants: params.participants,
309
+ start: params.start,
310
+ end: params.end,
311
+ });
312
+ const messages = Array.isArray(response.messages) ? response.messages : [];
313
+ return messages.map((message) => {
314
+ const createdAt = typeof message.created_at === "string" ? Date.parse(message.created_at) : Number.NaN;
315
+ const deliveredAt = typeof message.date_delivered === "string" ? Date.parse(message.date_delivered) : Number.NaN;
316
+ const readAt = typeof message.date_read === "string" ? Date.parse(message.date_read) : Number.NaN;
317
+ const attachments = Array.isArray(message.attachments)
318
+ ? message.attachments.reduce((acc, attachment) => {
319
+ if (!attachment || typeof attachment !== "object") {
320
+ return acc;
321
+ }
322
+ const raw = attachment;
323
+ acc.push({
324
+ id: typeof raw.filename === "string" && raw.filename.trim().length > 0
325
+ ? raw.filename.trim()
326
+ : typeof raw.original_path === "string"
327
+ ? raw.original_path
328
+ : "",
329
+ filename: typeof raw.filename === "string" ? raw.filename : undefined,
330
+ mimeType: typeof raw.mime_type === "string" ? raw.mime_type : undefined,
331
+ path: typeof raw.original_path === "string" ? raw.original_path : undefined,
332
+ size: typeof raw.total_bytes === "number"
333
+ ? raw.total_bytes
334
+ : typeof raw.total_bytes === "string"
335
+ ? Number.parseInt(raw.total_bytes, 10)
336
+ : undefined,
337
+ });
338
+ return acc;
339
+ }, [])
340
+ : [];
341
+ return {
342
+ id: typeof message.id === "string" || typeof message.id === "number" ? String(message.id) : "",
343
+ chatId: typeof message.chat_id === "string" || typeof message.chat_id === "number"
344
+ ? String(message.chat_id)
345
+ : "",
346
+ guid: typeof message.guid === "string" ? message.guid : undefined,
347
+ text: typeof message.text === "string" ? message.text : "",
348
+ sender: typeof message.sender === "string" ? message.sender : "",
349
+ isFromMe: Boolean(message.is_from_me),
350
+ date: Number.isFinite(createdAt) ? createdAt : 0,
351
+ dateRead: Number.isFinite(readAt) ? readAt : undefined,
352
+ dateDelivered: Number.isFinite(deliveredAt) ? deliveredAt : undefined,
353
+ attachments,
354
+ };
355
+ });
356
+ }
357
+ /**
358
+ * Sends a message via iMessage RPC
359
+ */
360
+ export async function sendIMessageRpc(client, params) {
361
+ const file = Array.isArray(params.attachments) && params.attachments.length > 0
362
+ ? params.attachments[0]
363
+ : undefined;
364
+ const service = params.service === "iMessage" ? "imessage" : params.service === "SMS" ? "sms" : "auto";
365
+ const result = await client.request("send", {
366
+ to: params.to,
367
+ text: params.text,
368
+ file,
369
+ service,
370
+ chat_id: params.chatId,
371
+ chat_identifier: params.chatIdentifier,
372
+ chat_guid: params.chatGuid,
373
+ });
374
+ return { ok: result.ok !== false };
375
+ }
376
+ /**
377
+ * Gets chat info via iMessage RPC
378
+ */
379
+ export async function getChatInfo(client, params) {
380
+ const chats = await listChats(client, { limit: 100 });
381
+ return (chats.find((chat) => chat.id === params.chatId ||
382
+ chat.chatIdentifier === params.chatId ||
383
+ chat.guid === params.chatId) ?? null);
384
+ }
385
+ /**
386
+ * Gets contact info via iMessage RPC
387
+ */
388
+ export async function getContactInfo(client, params) {
389
+ void client;
390
+ void params;
391
+ throw new Error("imsg RPC does not expose contacts");
392
+ }
393
+ //# sourceMappingURL=rpc.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rpc.js","sourceRoot":"","sources":["../src/rpc.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,264 @@
1
+ /**
2
+ * iMessage service implementation for elizaOS.
3
+ */
4
+ import { type IAgentRuntime, Service } from "@elizaos/core";
5
+ import { type ChatDbMessage } from "./chatdb-reader.js";
6
+ import { type ContactPatch, type ContactsMap, type FullContact, type NewContactInput } from "./contacts-reader.js";
7
+ import { type IIMessageService, type IMessageChat, type IMessageListMessagesOptions, type IMessageMessage, type IMessageSendOptions, type IMessageSendResult, type IMessageServiceStatus, type IMessageSettings } from "./types.js";
8
+ /**
9
+ * iMessage service for Eliza agents.
10
+ * Note: This only works on macOS.
11
+ */
12
+ export declare class IMessageService extends Service implements IIMessageService {
13
+ static serviceType: string;
14
+ capabilityDescription: string;
15
+ private settings;
16
+ private connected;
17
+ private pollInterval;
18
+ /**
19
+ * Highest `message.ROWID` we've already dispatched to the agent. The
20
+ * polling loop asks chat.db for rows strictly greater than this value,
21
+ * then advances the cursor to the largest row it actually processed.
22
+ * Initialized to 0 on start; bumped on every successful dispatch so
23
+ * we skip backlog on a fresh launch without ever double-delivering.
24
+ */
25
+ private lastRowId;
26
+ /**
27
+ * Reentrancy gate for the polling loop. Dispatch calls
28
+ * `messageService.handleMessage` which invokes the LLM and typically
29
+ * takes several seconds per message. With a 2-second poll interval
30
+ * that means multiple ticks can land on top of each other, each
31
+ * seeing the same stale cursor and re-dispatching the same rows.
32
+ * This flag ensures at most one poll is in flight at a time; ticks
33
+ * that arrive while a poll is active are dropped (the next scheduled
34
+ * tick will pick up where the current one left off).
35
+ */
36
+ private pollInFlight;
37
+ /**
38
+ * Room keys we've already emitted a WORLD_JOINED event for in this
39
+ * service lifetime. Not persisted — on restart every room is
40
+ * re-greeted, which is correct: a fresh Eliza process doesn't know
41
+ * what previous processes already synced, and the bootstrap plugin's
42
+ * WORLD_JOINED handler is idempotent (handleServerSync tolerates
43
+ * already-known rooms via upsert semantics).
44
+ */
45
+ private seenWorlds;
46
+ /**
47
+ * Entity keys we've already emitted an ENTITY_JOINED event for.
48
+ * Same lifetime + rationale as seenWorlds.
49
+ */
50
+ private seenEntities;
51
+ /**
52
+ * Live chat.db handle, bound to the lifetime of this service. Non-null
53
+ * means inbound polling is active. Null means either (a) not running
54
+ * under Bun, or (b) chat.db couldn't be opened — in both cases the
55
+ * service remains send-only and logs a one-time warning on start.
56
+ */
57
+ private chatDb;
58
+ private chatDbPath;
59
+ /**
60
+ * Cached handle → display name map from the user's Apple Contacts.
61
+ * Populated lazily on first inbound message through CNContactStore, NOT at
62
+ * service start. Loading at boot would create a settings-level Contacts
63
+ * dependency at app launch, even though the user may never receive an
64
+ * inbound iMessage. We defer the read until the first message that actually
65
+ * needs handle→name resolution. Empty map means either the user hasn't
66
+ * authorized Contacts access yet, the address book is empty, or no inbound
67
+ * message has triggered the lazy load yet.
68
+ */
69
+ private contacts;
70
+ /** Whether the lazy contact load has been attempted this session. */
71
+ private contactsLoadAttempted;
72
+ /**
73
+ * Start the iMessage service.
74
+ */
75
+ static start(runtime: IAgentRuntime): Promise<IMessageService>;
76
+ static registerSendHandlers(runtime: IAgentRuntime, service: IMessageService): void;
77
+ /**
78
+ * Stop the iMessage service.
79
+ */
80
+ stop(): Promise<void>;
81
+ /**
82
+ * Check if the service is connected.
83
+ */
84
+ isConnected(): boolean;
85
+ getStatus(): IMessageServiceStatus;
86
+ /**
87
+ * Check if running on macOS.
88
+ */
89
+ isMacOS(): boolean;
90
+ /**
91
+ * Send a message via iMessage.
92
+ */
93
+ sendMessage(to: string, text: string, options?: IMessageSendOptions): Promise<IMessageSendResult>;
94
+ /**
95
+ * Get recent messages by reading chat.db. Returns the most recent
96
+ * `limit` messages (any sender, any chat) in chronological order.
97
+ *
98
+ * Returns an empty array if the chat.db reader is unavailable (plugin
99
+ * running under plain Node without bun:sqlite, or Full Disk Access not
100
+ * granted, etc.).
101
+ */
102
+ getRecentMessages(limit?: number): Promise<IMessageMessage[]>;
103
+ /**
104
+ * Return the newest messages in chronological order, optionally scoped
105
+ * to a single chat identifier. Returns an empty array if chat.db is not
106
+ * available and the connector is currently running in send-only mode.
107
+ */
108
+ getMessages(options?: IMessageListMessagesOptions): Promise<IMessageMessage[]>;
109
+ /**
110
+ * List every chat the Messages.app database knows about, joined with
111
+ * participant handles. Returns an empty list if the chat.db reader is
112
+ * unavailable (Node runtime, missing FDA, etc.).
113
+ *
114
+ * Previously this method used an AppleScript query against
115
+ * Messages.app's `chats` collection. That verb works but is slow and
116
+ * returns a coarser view (no participant handles, no style field), so
117
+ * the chat.db path is strictly better when it's available.
118
+ */
119
+ getChats(): Promise<IMessageChat[]>;
120
+ /**
121
+ * Get current settings.
122
+ */
123
+ getSettings(): IMessageSettings | null;
124
+ /**
125
+ * Get the cached Apple Contacts map, if lazy loading has happened.
126
+ *
127
+ * Keys are normalized handles (phones in digits-only + optional leading `+`,
128
+ * emails lowercased). Values carry the contact's display name.
129
+ *
130
+ * Exposed for providers that want to inject contact lookups into agent
131
+ * state so the LLM can resolve a person's name ("text Shaw") to a handle
132
+ * it can pass to `sendMessage`.
133
+ *
134
+ * Returns an empty map if Contacts access was denied, failed to load,
135
+ * or the service hasn't finished starting.
136
+ */
137
+ getContacts(): ContactsMap;
138
+ /**
139
+ * Lazy-load the Apple Contacts map on first call. Subsequent calls
140
+ * are no-ops. We split this out from `start()` so Contacts permission
141
+ * pressure only appears when the runtime actually needs handle→name
142
+ * resolution, instead of at app launch. Failure is non-fatal; the cached
143
+ * map stays empty and the service falls back to raw handles.
144
+ */
145
+ private ensureContactsLoaded;
146
+ private recordContactsPermissionBlock;
147
+ /**
148
+ * List every contact in the user's address book as a full record with
149
+ * id, name, and all phones/emails. Delegates to contacts-reader's
150
+ * `listAllContacts` which uses CNContactStore. Returns `[]` on failure
151
+ * (permission denied, etc.).
152
+ */
153
+ listAllContacts(): Promise<FullContact[]>;
154
+ /**
155
+ * Create a new Apple Contacts record. Requires the Contacts privacy grant.
156
+ * Returns the new person's id on success, or null on failure.
157
+ *
158
+ * After a successful create we refresh the cached handle→name map so
159
+ * inbound messages from the new contact resolve to their name on the
160
+ * very next poll, without requiring a service restart.
161
+ */
162
+ addContact(input: NewContactInput): Promise<string | null>;
163
+ /**
164
+ * Patch an existing contact (name fields, add/remove phones, add/remove
165
+ * emails). Returns true on success, false on failure. Refreshes the
166
+ * cached map on success so name resolution reflects the change.
167
+ */
168
+ updateContact(personId: string, patch: ContactPatch): Promise<boolean>;
169
+ /**
170
+ * Delete a contact by Apple Contacts id. Returns true on success, false on
171
+ * failure. Refreshes the cached map on success.
172
+ */
173
+ deleteContact(personId: string): Promise<boolean>;
174
+ private loadSettings;
175
+ private validateSettings;
176
+ private sendSingleMessage;
177
+ private sendViaCli;
178
+ private sendViaAppleScript;
179
+ private runAppleScript;
180
+ private startPolling;
181
+ /**
182
+ * Poll chat.db for rows newer than the cursor and route each inbound
183
+ * message through the agent's message pipeline.
184
+ *
185
+ * Flow per message:
186
+ * 1. Read new rows from chat.db via the bun:sqlite reader.
187
+ * 2. Skip outbound (is_from_me=1), already-seen, and policy-denied rows.
188
+ * 3. Build a Memory object in the shape the bootstrap plugin expects.
189
+ * 4. Ensure the entity + room + world exist via ensureConnection.
190
+ * 5. Call runtime.messageService.handleMessage with a callback that
191
+ * sends the agent's reply back through sendViaAppleScript.
192
+ * 6. Also emit the plugin-namespaced IMESSAGE_MESSAGE_RECEIVED event
193
+ * and the core EventType.MESSAGE_RECEIVED event for any listeners.
194
+ *
195
+ * Advances this.lastRowId unconditionally to the max rowId we saw in
196
+ * this batch — even for skipped rows — so the cursor keeps moving
197
+ * forward and we never get stuck re-reading the same row on every poll.
198
+ */
199
+ private pollForNewMessages;
200
+ private pollForNewMessagesInner;
201
+ /**
202
+ * Turn a single chat.db row into a `Memory`, wire up a reply callback,
203
+ * and hand the whole thing to `runtime.messageService.handleMessage`.
204
+ *
205
+ * Mirrors the shape used by @elizaos/plugin-telegram so the bootstrap
206
+ * plugin's message pipeline picks up inbound iMessages the same way it
207
+ * picks up Telegram messages — same entity/room/world creation, same
208
+ * `source: "imessage"` tag on content, same HandlerCallback signature
209
+ * for the reply path.
210
+ */
211
+ private dispatchInboundMessage;
212
+ /**
213
+ * Handle non-conversational chat.db rows — reactions, group events,
214
+ * anything that isn't a normal text turn. These shouldn't flow through
215
+ * `messageService.handleMessage` (which would try to generate a reply)
216
+ * but they're still useful to surface as plugin-namespaced events so
217
+ * listeners can react, log, or update state.
218
+ *
219
+ * Emits two events:
220
+ * - A plugin-namespaced event on the existing `IMessageEventTypes`
221
+ * enum (e.g. `IMESSAGE_REACTION_RECEIVED`).
222
+ * - The generic `EventType.REACTION_RECEIVED` from core when the
223
+ * row is a reaction, so core-level handlers see it.
224
+ */
225
+ private emitAuxiliaryEvent;
226
+ private isAllowed;
227
+ /**
228
+ * Register a recurring heartbeat task with Eliza's task system and
229
+ * kick off one if it isn't already queued.
230
+ *
231
+ * The heartbeat runs once a minute (configurable via
232
+ * `IMESSAGE_HEARTBEAT_INTERVAL_MS`) and does a lightweight health
233
+ * probe: (a) chat.db reader is still open and responsive,
234
+ * (b) Contacts map still populated, (c) polling cursor is advancing
235
+ * when expected. On failure it logs + emits
236
+ * `IMESSAGE_HEARTBEAT_UNHEALTHY`; on success it emits
237
+ * `IMESSAGE_HEARTBEAT_OK`. Observers (Eliza's heartbeat UI, ops
238
+ * dashboards, trajectory logger) subscribe to these events.
239
+ *
240
+ * The task is tagged `["queue", "repeat", "imessage"]` so Eliza's
241
+ * built-in TaskService picks it up via its standard polling loop.
242
+ * Without `updateInterval` being set in metadata, the task fires
243
+ * once and then deletes; with it, the task service re-schedules.
244
+ */
245
+ private registerHeartbeat;
246
+ }
247
+ /**
248
+ * Convert a `ChatDbMessage` (the shape the bun:sqlite reader returns)
249
+ * into the public `IMessageMessage` shape exposed by this plugin's API.
250
+ * Exported so the test suite can exercise it in isolation without
251
+ * spinning up a full runtime + service instance.
252
+ */
253
+ export declare function chatDbMessageToPublicShape(row: ChatDbMessage): IMessageMessage;
254
+ /**
255
+ * Parse tab-delimited AppleScript messages output.
256
+ * Expected format per line: "id\ttext\tdate_sent\tis_from_me\tchat_identifier\tsender"
257
+ */
258
+ export declare function parseMessagesFromAppleScript(result: string): IMessageMessage[];
259
+ /**
260
+ * Parse tab-delimited AppleScript chats output.
261
+ * Expected format per line: "chat_identifier\tdisplay_name\tparticipant_count\tlast_message_date"
262
+ */
263
+ export declare function parseChatsFromAppleScript(result: string): IMessageChat[];
264
+ //# sourceMappingURL=service.d.ts.map