@moxxy/plugin-channel-imessage 0.29.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/LICENSE +21 -0
- package/dist/bluebubbles-client.d.ts +79 -0
- package/dist/bluebubbles-client.d.ts.map +1 -0
- package/dist/bluebubbles-client.js +113 -0
- package/dist/bluebubbles-client.js.map +1 -0
- package/dist/channel/chunker.d.ts +66 -0
- package/dist/channel/chunker.d.ts.map +1 -0
- package/dist/channel/chunker.js +130 -0
- package/dist/channel/chunker.js.map +1 -0
- package/dist/channel/turn-runner.d.ts +32 -0
- package/dist/channel/turn-runner.d.ts.map +1 -0
- package/dist/channel/turn-runner.js +58 -0
- package/dist/channel/turn-runner.js.map +1 -0
- package/dist/channel.d.ts +87 -0
- package/dist/channel.d.ts.map +1 -0
- package/dist/channel.js +264 -0
- package/dist/channel.js.map +1 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +211 -0
- package/dist/index.js.map +1 -0
- package/dist/keys.d.ts +70 -0
- package/dist/keys.d.ts.map +1 -0
- package/dist/keys.js +111 -0
- package/dist/keys.js.map +1 -0
- package/dist/message-gate.d.ts +40 -0
- package/dist/message-gate.d.ts.map +1 -0
- package/dist/message-gate.js +54 -0
- package/dist/message-gate.js.map +1 -0
- package/dist/permission.d.ts +25 -0
- package/dist/permission.d.ts.map +1 -0
- package/dist/permission.js +31 -0
- package/dist/permission.js.map +1 -0
- package/dist/schema.d.ts +96 -0
- package/dist/schema.d.ts.map +1 -0
- package/dist/schema.js +41 -0
- package/dist/schema.js.map +1 -0
- package/dist/setup-wizard.d.ts +15 -0
- package/dist/setup-wizard.d.ts.map +1 -0
- package/dist/setup-wizard.js +127 -0
- package/dist/setup-wizard.js.map +1 -0
- package/package.json +96 -0
- package/src/bluebubbles-client.ts +182 -0
- package/src/channel/chunker.test.ts +132 -0
- package/src/channel/chunker.ts +144 -0
- package/src/channel/turn-runner.ts +82 -0
- package/src/channel.test.ts +256 -0
- package/src/channel.ts +352 -0
- package/src/index.ts +273 -0
- package/src/keys.test.ts +86 -0
- package/src/keys.ts +109 -0
- package/src/message-gate.test.ts +126 -0
- package/src/message-gate.ts +94 -0
- package/src/permission.ts +40 -0
- package/src/schema.test.ts +51 -0
- package/src/schema.ts +47 -0
- package/src/setup-wizard.ts +155 -0
- package/src/subcommands.test.ts +194 -0
package/dist/channel.js
ADDED
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
import { newTurnId } from '@moxxy/core';
|
|
2
|
+
import { TurnCoordinator, resolveSecret } from '@moxxy/channel-kit';
|
|
3
|
+
import { IMESSAGE_ALLOWED_HANDLES_KEY, IMESSAGE_OWNER_HANDLES_KEY, IMESSAGE_SERVER_PASSWORD_ENV, IMESSAGE_SERVER_PASSWORD_KEY, IMESSAGE_SERVER_URL_ENV, IMESSAGE_SERVER_URL_KEY, normalizeHandle, parseHandleList, } from './keys.js';
|
|
4
|
+
import { gateInboundMessage } from './message-gate.js';
|
|
5
|
+
import { buildImessagePermissionResolver } from './permission.js';
|
|
6
|
+
import { BlueBubblesClient, } from './bluebubbles-client.js';
|
|
7
|
+
import { runImessageTurn } from './channel/turn-runner.js';
|
|
8
|
+
import { splitForImessage } from './channel/chunker.js';
|
|
9
|
+
/** Bound on remembered own-send ids (guid + tempGuid) for the echo drop. */
|
|
10
|
+
const MAX_SENT_IDS = 256;
|
|
11
|
+
/** Rate limit for "dropped inbound message" warnings. */
|
|
12
|
+
const DROP_WARN_INTERVAL_MS = 5_000;
|
|
13
|
+
/** Message when the server URL / password isn't configured yet. */
|
|
14
|
+
const NOT_CONFIGURED_MESSAGE = 'No BlueBubbles server configured. Run `moxxy channels imessage setup` (or set ' +
|
|
15
|
+
`${IMESSAGE_SERVER_URL_ENV} + ${IMESSAGE_SERVER_PASSWORD_ENV}).`;
|
|
16
|
+
export class ImessageChannel {
|
|
17
|
+
name = 'imessage';
|
|
18
|
+
/**
|
|
19
|
+
* Installed on the session by the CLI dispatcher. Replaced in `start()` once
|
|
20
|
+
* the live tool registry is available for `['*']` expansion; until then it
|
|
21
|
+
* denies everything (safe default before start).
|
|
22
|
+
*/
|
|
23
|
+
permissionResolver;
|
|
24
|
+
opts;
|
|
25
|
+
session = null;
|
|
26
|
+
model;
|
|
27
|
+
client = null;
|
|
28
|
+
allowedHandles = new Set();
|
|
29
|
+
ownerHandles = new Set();
|
|
30
|
+
// Single-flight turn state + the bounded own-turn-id set the foreign-turn
|
|
31
|
+
// mirror gate filters on (invariant #8).
|
|
32
|
+
turns = new TurnCoordinator();
|
|
33
|
+
lastChatGuid = null;
|
|
34
|
+
logUnsub = null;
|
|
35
|
+
/**
|
|
36
|
+
* guid + tempGuid of messages WE sent. BlueBubbles emits `new-message` for
|
|
37
|
+
* the account's own sends too (our replies come back `isFromMe`), so any
|
|
38
|
+
* inbound whose id is in this set is an echo of ourselves and must be dropped
|
|
39
|
+
* (loop protection).
|
|
40
|
+
*/
|
|
41
|
+
sentIds = new Set();
|
|
42
|
+
handle = null;
|
|
43
|
+
runningSettled = false;
|
|
44
|
+
resolveRunning = null;
|
|
45
|
+
stopping = false;
|
|
46
|
+
lastDropWarnAt = 0;
|
|
47
|
+
constructor(opts) {
|
|
48
|
+
this.opts = opts;
|
|
49
|
+
// Pre-start: deny-all (replaced with the real allow-list resolver in start()).
|
|
50
|
+
this.permissionResolver = buildImessagePermissionResolver({
|
|
51
|
+
allowedTools: [],
|
|
52
|
+
allToolNames: [],
|
|
53
|
+
...(opts.logger ? { logger: opts.logger } : {}),
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
async start(startOpts) {
|
|
57
|
+
if (this.handle)
|
|
58
|
+
return this.handle;
|
|
59
|
+
this.session = startOpts.session;
|
|
60
|
+
this.model = startOpts.model;
|
|
61
|
+
// Config: explicit option → env → vault (shared channel-kit precedence).
|
|
62
|
+
const serverUrl = this.opts.serverUrl ??
|
|
63
|
+
(await resolveSecret(this.opts.vault, {
|
|
64
|
+
envVar: IMESSAGE_SERVER_URL_ENV,
|
|
65
|
+
vaultKey: IMESSAGE_SERVER_URL_KEY,
|
|
66
|
+
}));
|
|
67
|
+
const password = this.opts.password ??
|
|
68
|
+
(await resolveSecret(this.opts.vault, {
|
|
69
|
+
envVar: IMESSAGE_SERVER_PASSWORD_ENV,
|
|
70
|
+
vaultKey: IMESSAGE_SERVER_PASSWORD_KEY,
|
|
71
|
+
}));
|
|
72
|
+
if (!serverUrl || !password)
|
|
73
|
+
throw new Error(NOT_CONFIGURED_MESSAGE);
|
|
74
|
+
// Allow-list (OTHER people) + owner handles (self-chat), from vault + options.
|
|
75
|
+
this.rebuildHandleSet(this.allowedHandles, parseHandleList(await this.opts.vault.get(IMESSAGE_ALLOWED_HANDLES_KEY)), this.opts.allowedHandles);
|
|
76
|
+
this.rebuildHandleSet(this.ownerHandles, parseHandleList(await this.opts.vault.get(IMESSAGE_OWNER_HANDLES_KEY)), this.opts.ownerHandles);
|
|
77
|
+
// Swap in the real autonomous allow-list resolver now that the tool registry
|
|
78
|
+
// is live (mirrors Signal; `['*']` expands here).
|
|
79
|
+
const allowedTools = startOpts.allowedTools ?? this.opts.allowedTools ?? [];
|
|
80
|
+
const allToolNames = this.session.tools.list().map((t) => t.name);
|
|
81
|
+
this.permissionResolver = buildImessagePermissionResolver({
|
|
82
|
+
allowedTools,
|
|
83
|
+
allToolNames,
|
|
84
|
+
...(this.opts.logger ? { logger: this.opts.logger } : {}),
|
|
85
|
+
});
|
|
86
|
+
this.session.setPermissionResolver(this.permissionResolver);
|
|
87
|
+
// Mirror-to-last-chat: post assistant prose for turns this channel did NOT
|
|
88
|
+
// initiate (a co-attached surface ran one) into the last chat served.
|
|
89
|
+
this.logUnsub = this.session.log.subscribe((event) => this.mirrorForeignTurn(event));
|
|
90
|
+
const running = new Promise((resolve) => {
|
|
91
|
+
this.resolveRunning = resolve;
|
|
92
|
+
});
|
|
93
|
+
const client = this.makeClient({ serverUrl, password });
|
|
94
|
+
this.client = client;
|
|
95
|
+
try {
|
|
96
|
+
// Reachability + auth probe deferred to here (NOT isAvailable): surfaces a
|
|
97
|
+
// friendly error if the localhost BlueBubbles server isn't up.
|
|
98
|
+
await client.ping();
|
|
99
|
+
await client.connect();
|
|
100
|
+
}
|
|
101
|
+
catch (err) {
|
|
102
|
+
this.logUnsub?.();
|
|
103
|
+
this.logUnsub = null;
|
|
104
|
+
this.client = null;
|
|
105
|
+
throw err;
|
|
106
|
+
}
|
|
107
|
+
client.onMessage((raw) => this.handleInbound(raw));
|
|
108
|
+
this.handle = {
|
|
109
|
+
running,
|
|
110
|
+
stop: async (reason = 'shutdown') => {
|
|
111
|
+
this.stopping = true;
|
|
112
|
+
// Abort the in-flight turn FIRST so the model loop stops the moment the
|
|
113
|
+
// operator asks to shut down. The autonomous allow-list resolver has no
|
|
114
|
+
// pending operator prompts, so there is nothing to abortAll.
|
|
115
|
+
this.turns.abort(reason);
|
|
116
|
+
this.logUnsub?.();
|
|
117
|
+
this.logUnsub = null;
|
|
118
|
+
const client = this.client;
|
|
119
|
+
this.client = null;
|
|
120
|
+
client?.close();
|
|
121
|
+
this.settleRunning();
|
|
122
|
+
},
|
|
123
|
+
};
|
|
124
|
+
this.opts.logger?.info?.('imessage: channel started', {
|
|
125
|
+
allowedHandles: this.allowedHandles.size,
|
|
126
|
+
ownerHandles: this.ownerHandles.size,
|
|
127
|
+
});
|
|
128
|
+
return this.handle;
|
|
129
|
+
}
|
|
130
|
+
// -------------------------------------------------------------------------
|
|
131
|
+
// Inbound
|
|
132
|
+
// -------------------------------------------------------------------------
|
|
133
|
+
/** Every inbound `new-message` funnels through the one gate. */
|
|
134
|
+
handleInbound(raw) {
|
|
135
|
+
if (this.stopping)
|
|
136
|
+
return;
|
|
137
|
+
const verdict = gateInboundMessage({
|
|
138
|
+
ownerHandles: this.ownerHandles,
|
|
139
|
+
allowedHandles: this.allowedHandles,
|
|
140
|
+
isOwnSend: (id) => this.sentIds.has(id),
|
|
141
|
+
}, raw);
|
|
142
|
+
if (!verdict.ok) {
|
|
143
|
+
this.warnDrop(verdict.reason);
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
this.dispatchInBackground(this.processMessage(verdict.chatGuid, verdict.text), 'new-message');
|
|
147
|
+
}
|
|
148
|
+
/** Busy gate, then one coordinated turn. */
|
|
149
|
+
async processMessage(chatGuid, text) {
|
|
150
|
+
if (!this.session)
|
|
151
|
+
return;
|
|
152
|
+
// Atomic single-flight guard (the coordinator claims the slot BEFORE any
|
|
153
|
+
// await); the turnId minted here is recorded as an own-turn id — that's what
|
|
154
|
+
// mirrorForeignTurn filters on (invariant #8).
|
|
155
|
+
const lease = this.turns.begin(newTurnId());
|
|
156
|
+
if (!lease) {
|
|
157
|
+
await this.sendText(chatGuid, 'I am still working on the previous prompt. One moment…');
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
this.lastChatGuid = chatGuid;
|
|
161
|
+
try {
|
|
162
|
+
await runImessageTurn({
|
|
163
|
+
session: this.session,
|
|
164
|
+
send: (t) => this.sendText(chatGuid, t),
|
|
165
|
+
...(this.opts.logger ? { logger: this.opts.logger } : {}),
|
|
166
|
+
}, {
|
|
167
|
+
text,
|
|
168
|
+
...(this.model ? { model: this.model } : {}),
|
|
169
|
+
controller: lease.controller,
|
|
170
|
+
turnId: lease.turnId,
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
finally {
|
|
174
|
+
lease.end();
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
// -------------------------------------------------------------------------
|
|
178
|
+
// Outbound
|
|
179
|
+
// -------------------------------------------------------------------------
|
|
180
|
+
/** Send one message and record its ids for the echo drop. */
|
|
181
|
+
async sendText(chatGuid, text) {
|
|
182
|
+
const client = this.client;
|
|
183
|
+
if (!client)
|
|
184
|
+
throw new Error('imessage client is not connected');
|
|
185
|
+
const { guid, tempGuid } = await client.sendText(chatGuid, text);
|
|
186
|
+
this.recordSent(tempGuid);
|
|
187
|
+
if (guid)
|
|
188
|
+
this.recordSent(guid);
|
|
189
|
+
}
|
|
190
|
+
recordSent(id) {
|
|
191
|
+
this.sentIds.add(id);
|
|
192
|
+
if (this.sentIds.size > MAX_SENT_IDS) {
|
|
193
|
+
const oldest = this.sentIds.values().next().value;
|
|
194
|
+
if (oldest !== undefined)
|
|
195
|
+
this.sentIds.delete(oldest);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Post the assistant's prose for a turn this channel did not initiate.
|
|
200
|
+
* Skipped for our own turnIds (robust to async ordering / replay, invariant
|
|
201
|
+
* #8) and while a turn of ours is streaming via the chunked sender.
|
|
202
|
+
*/
|
|
203
|
+
mirrorForeignTurn(event) {
|
|
204
|
+
const text = this.turns.mirrorText(event);
|
|
205
|
+
if (text == null)
|
|
206
|
+
return;
|
|
207
|
+
const chatGuid = this.lastChatGuid;
|
|
208
|
+
if (!chatGuid || !this.client)
|
|
209
|
+
return;
|
|
210
|
+
void (async () => {
|
|
211
|
+
for (const part of splitForImessage(text)) {
|
|
212
|
+
await this.sendText(chatGuid, part);
|
|
213
|
+
}
|
|
214
|
+
})().catch((err) => {
|
|
215
|
+
this.opts.logger?.warn?.('imessage: mirror failed', { err: String(err) });
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
// -------------------------------------------------------------------------
|
|
219
|
+
// Plumbing
|
|
220
|
+
// -------------------------------------------------------------------------
|
|
221
|
+
makeClient(opts) {
|
|
222
|
+
const clientOpts = {
|
|
223
|
+
serverUrl: opts.serverUrl,
|
|
224
|
+
password: opts.password,
|
|
225
|
+
...(this.opts.logger ? { logger: this.opts.logger } : {}),
|
|
226
|
+
};
|
|
227
|
+
const factory = this.opts.clientFactory ?? ((o) => new BlueBubblesClient(o));
|
|
228
|
+
return factory(clientOpts);
|
|
229
|
+
}
|
|
230
|
+
rebuildHandleSet(target, fromVault, fromOptions) {
|
|
231
|
+
target.clear();
|
|
232
|
+
for (const handle of fromVault)
|
|
233
|
+
target.add(handle);
|
|
234
|
+
for (const handle of fromOptions ?? []) {
|
|
235
|
+
const normalized = normalizeHandle(handle);
|
|
236
|
+
if (normalized.length > 0)
|
|
237
|
+
target.add(normalized);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* Run a handler detached from the socket read loop (an inbound handler that
|
|
242
|
+
* awaited a whole turn would park delivery for its duration). Errors are
|
|
243
|
+
* logged here — nothing upstream awaits this promise.
|
|
244
|
+
*/
|
|
245
|
+
dispatchInBackground(work, kind) {
|
|
246
|
+
void work.catch((err) => {
|
|
247
|
+
this.opts.logger?.warn?.('imessage: handler failed', { kind, err: String(err) });
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
warnDrop(reason) {
|
|
251
|
+
const now = Date.now();
|
|
252
|
+
if (now - this.lastDropWarnAt < DROP_WARN_INTERVAL_MS)
|
|
253
|
+
return;
|
|
254
|
+
this.lastDropWarnAt = now;
|
|
255
|
+
this.opts.logger?.debug?.('imessage: dropped inbound message', { reason });
|
|
256
|
+
}
|
|
257
|
+
settleRunning() {
|
|
258
|
+
if (this.runningSettled)
|
|
259
|
+
return;
|
|
260
|
+
this.runningSettled = true;
|
|
261
|
+
this.resolveRunning?.();
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
//# sourceMappingURL=channel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"channel.js","sourceRoot":"","sources":["../src/channel.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAUpE,OAAO,EACL,4BAA4B,EAC5B,0BAA0B,EAC1B,4BAA4B,EAC5B,4BAA4B,EAC5B,uBAAuB,EACvB,uBAAuB,EACvB,eAAe,EACf,eAAe,GAChB,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAE,+BAA+B,EAAE,MAAM,iBAAiB,CAAC;AAClE,OAAO,EACL,iBAAiB,GAGlB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAC3D,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAExD,4EAA4E;AAC5E,MAAM,YAAY,GAAG,GAAG,CAAC;AAEzB,yDAAyD;AACzD,MAAM,qBAAqB,GAAG,KAAK,CAAC;AAEpC,mEAAmE;AACnE,MAAM,sBAAsB,GAC1B,gFAAgF;IAChF,GAAG,uBAAuB,MAAM,4BAA4B,IAAI,CAAC;AAgCnE,MAAM,OAAO,eAAe;IACjB,IAAI,GAAG,UAAU,CAAC;IAC3B;;;;OAIG;IACH,kBAAkB,CAAqB;IAEtB,IAAI,CAAyB;IACtC,OAAO,GAAmB,IAAI,CAAC;IAC/B,KAAK,CAAqB;IAE1B,MAAM,GAAiC,IAAI,CAAC;IACnC,cAAc,GAAG,IAAI,GAAG,EAAU,CAAC;IACnC,YAAY,GAAG,IAAI,GAAG,EAAU,CAAC;IAElD,0EAA0E;IAC1E,yCAAyC;IACxB,KAAK,GAAG,IAAI,eAAe,EAAE,CAAC;IACvC,YAAY,GAAkB,IAAI,CAAC;IACnC,QAAQ,GAAwB,IAAI,CAAC;IAE7C;;;;;OAKG;IACc,OAAO,GAAG,IAAI,GAAG,EAAU,CAAC;IAErC,MAAM,GAAyB,IAAI,CAAC;IACpC,cAAc,GAAG,KAAK,CAAC;IACvB,cAAc,GAAwB,IAAI,CAAC;IAC3C,QAAQ,GAAG,KAAK,CAAC;IACjB,cAAc,GAAG,CAAC,CAAC;IAE3B,YAAY,IAA4B;QACtC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,+EAA+E;QAC/E,IAAI,CAAC,kBAAkB,GAAG,+BAA+B,CAAC;YACxD,YAAY,EAAE,EAAE;YAChB,YAAY,EAAE,EAAE;YAChB,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAChD,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,SAA4B;QACtC,IAAI,IAAI,CAAC,MAAM;YAAE,OAAO,IAAI,CAAC,MAAM,CAAC;QACpC,IAAI,CAAC,OAAO,GAAG,SAAS,CAAC,OAAO,CAAC;QACjC,IAAI,CAAC,KAAK,GAAG,SAAS,CAAC,KAAK,CAAC;QAE7B,yEAAyE;QACzE,MAAM,SAAS,GACb,IAAI,CAAC,IAAI,CAAC,SAAS;YACnB,CAAC,MAAM,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE;gBACpC,MAAM,EAAE,uBAAuB;gBAC/B,QAAQ,EAAE,uBAAuB;aAClC,CAAC,CAAC,CAAC;QACN,MAAM,QAAQ,GACZ,IAAI,CAAC,IAAI,CAAC,QAAQ;YAClB,CAAC,MAAM,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE;gBACpC,MAAM,EAAE,4BAA4B;gBACpC,QAAQ,EAAE,4BAA4B;aACvC,CAAC,CAAC,CAAC;QACN,IAAI,CAAC,SAAS,IAAI,CAAC,QAAQ;YAAE,MAAM,IAAI,KAAK,CAAC,sBAAsB,CAAC,CAAC;QAErE,+EAA+E;QAC/E,IAAI,CAAC,gBAAgB,CACnB,IAAI,CAAC,cAAc,EACnB,eAAe,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAC,EACxE,IAAI,CAAC,IAAI,CAAC,cAAc,CACzB,CAAC;QACF,IAAI,CAAC,gBAAgB,CACnB,IAAI,CAAC,YAAY,EACjB,eAAe,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,0BAA0B,CAAC,CAAC,EACtE,IAAI,CAAC,IAAI,CAAC,YAAY,CACvB,CAAC;QAEF,6EAA6E;QAC7E,kDAAkD;QAClD,MAAM,YAAY,GAAG,SAAS,CAAC,YAAY,IAAI,IAAI,CAAC,IAAI,CAAC,YAAY,IAAI,EAAE,CAAC;QAC5E,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QAClE,IAAI,CAAC,kBAAkB,GAAG,+BAA+B,CAAC;YACxD,YAAY;YACZ,YAAY;YACZ,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAC1D,CAAC,CAAC;QACH,IAAI,CAAC,OAAO,CAAC,qBAAqB,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;QAE5D,2EAA2E;QAC3E,sEAAsE;QACtE,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,iBAAiB,CAAC,KAAK,CAAC,CAAC,CAAC;QAErF,MAAM,OAAO,GAAG,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;YAC5C,IAAI,CAAC,cAAc,GAAG,OAAO,CAAC;QAChC,CAAC,CAAC,CAAC;QAEH,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,CAAC,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,CAAC;QACxD,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC;YACH,2EAA2E;YAC3E,+DAA+D;YAC/D,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;YACpB,MAAM,MAAM,CAAC,OAAO,EAAE,CAAC;QACzB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,CAAC,QAAQ,EAAE,EAAE,CAAC;YAClB,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;YACrB,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;YACnB,MAAM,GAAG,CAAC;QACZ,CAAC;QACD,MAAM,CAAC,SAAS,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC;QAEnD,IAAI,CAAC,MAAM,GAAG;YACZ,OAAO;YACP,IAAI,EAAE,KAAK,EAAE,MAAM,GAAG,UAAU,EAAE,EAAE;gBAClC,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;gBACrB,wEAAwE;gBACxE,wEAAwE;gBACxE,6DAA6D;gBAC7D,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;gBACzB,IAAI,CAAC,QAAQ,EAAE,EAAE,CAAC;gBAClB,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;gBACrB,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;gBAC3B,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;gBACnB,MAAM,EAAE,KAAK,EAAE,CAAC;gBAChB,IAAI,CAAC,aAAa,EAAE,CAAC;YACvB,CAAC;SACF,CAAC;QACF,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,2BAA2B,EAAE;YACpD,cAAc,EAAE,IAAI,CAAC,cAAc,CAAC,IAAI;YACxC,YAAY,EAAE,IAAI,CAAC,YAAY,CAAC,IAAI;SACrC,CAAC,CAAC;QACH,OAAO,IAAI,CAAC,MAAM,CAAC;IACrB,CAAC;IAED,4EAA4E;IAC5E,UAAU;IACV,4EAA4E;IAE5E,gEAAgE;IACxD,aAAa,CAAC,GAAY;QAChC,IAAI,IAAI,CAAC,QAAQ;YAAE,OAAO;QAC1B,MAAM,OAAO,GAAG,kBAAkB,CAChC;YACE,YAAY,EAAE,IAAI,CAAC,YAAY;YAC/B,cAAc,EAAE,IAAI,CAAC,cAAc;YACnC,SAAS,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;SACxC,EACD,GAAG,CACJ,CAAC;QACF,IAAI,CAAC,OAAO,CAAC,EAAE,EAAE,CAAC;YAChB,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;YAC9B,OAAO;QACT,CAAC;QACD,IAAI,CAAC,oBAAoB,CAAC,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,QAAQ,EAAE,OAAO,CAAC,IAAI,CAAC,EAAE,aAAa,CAAC,CAAC;IAChG,CAAC;IAED,4CAA4C;IACpC,KAAK,CAAC,cAAc,CAAC,QAAgB,EAAE,IAAY;QACzD,IAAI,CAAC,IAAI,CAAC,OAAO;YAAE,OAAO;QAC1B,yEAAyE;QACzE,6EAA6E;QAC7E,+CAA+C;QAC/C,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,SAAS,EAAE,CAAC,CAAC;QAC5C,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,MAAM,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,wDAAwD,CAAC,CAAC;YACxF,OAAO;QACT,CAAC;QACD,IAAI,CAAC,YAAY,GAAG,QAAQ,CAAC;QAC7B,IAAI,CAAC;YACH,MAAM,eAAe,CACnB;gBACE,OAAO,EAAE,IAAI,CAAC,OAAO;gBACrB,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC,CAAC;gBACvC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aAC1D,EACD;gBACE,IAAI;gBACJ,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC5C,UAAU,EAAE,KAAK,CAAC,UAAU;gBAC5B,MAAM,EAAE,KAAK,CAAC,MAAM;aACrB,CACF,CAAC;QACJ,CAAC;gBAAS,CAAC;YACT,KAAK,CAAC,GAAG,EAAE,CAAC;QACd,CAAC;IACH,CAAC;IAED,4EAA4E;IAC5E,WAAW;IACX,4EAA4E;IAE5E,6DAA6D;IACrD,KAAK,CAAC,QAAQ,CAAC,QAAgB,EAAE,IAAY;QACnD,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;QAC3B,IAAI,CAAC,MAAM;YAAE,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC;QACjE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QACjE,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;QAC1B,IAAI,IAAI;YAAE,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;IAClC,CAAC;IAEO,UAAU,CAAC,EAAU;QAC3B,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACrB,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,GAAG,YAAY,EAAE,CAAC;YACrC,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC;YAClD,IAAI,MAAM,KAAK,SAAS;gBAAE,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QACxD,CAAC;IACH,CAAC;IAED;;;;OAIG;IACK,iBAAiB,CAAC,KAAiB;QACzC,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;QAC1C,IAAI,IAAI,IAAI,IAAI;YAAE,OAAO;QACzB,MAAM,QAAQ,GAAG,IAAI,CAAC,YAAY,CAAC;QACnC,IAAI,CAAC,QAAQ,IAAI,CAAC,IAAI,CAAC,MAAM;YAAE,OAAO;QACtC,KAAK,CAAC,KAAK,IAAI,EAAE;YACf,KAAK,MAAM,IAAI,IAAI,gBAAgB,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC1C,MAAM,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;YACtC,CAAC;QACH,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;YACjB,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,yBAAyB,EAAE,EAAE,GAAG,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAC5E,CAAC,CAAC,CAAC;IACL,CAAC;IAED,4EAA4E;IAC5E,WAAW;IACX,4EAA4E;IAEpE,UAAU,CAAC,IAA6C;QAC9D,MAAM,UAAU,GAA6B;YAC3C,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAC1D,CAAC;QACF,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,aAAa,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,iBAAiB,CAAC,CAAC,CAAC,CAAC,CAAC;QAC7E,OAAO,OAAO,CAAC,UAAU,CAAC,CAAC;IAC7B,CAAC;IAEO,gBAAgB,CACtB,MAAmB,EACnB,SAAgC,EAChC,WAA8C;QAE9C,MAAM,CAAC,KAAK,EAAE,CAAC;QACf,KAAK,MAAM,MAAM,IAAI,SAAS;YAAE,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACnD,KAAK,MAAM,MAAM,IAAI,WAAW,IAAI,EAAE,EAAE,CAAC;YACvC,MAAM,UAAU,GAAG,eAAe,CAAC,MAAM,CAAC,CAAC;YAC3C,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC;gBAAE,MAAM,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QACpD,CAAC;IACH,CAAC;IAED;;;;OAIG;IACK,oBAAoB,CAAC,IAAmB,EAAE,IAAY;QAC5D,KAAK,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;YACtB,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,0BAA0B,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACnF,CAAC,CAAC,CAAC;IACL,CAAC;IAEO,QAAQ,CAAC,MAAc;QAC7B,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,IAAI,GAAG,GAAG,IAAI,CAAC,cAAc,GAAG,qBAAqB;YAAE,OAAO;QAC9D,IAAI,CAAC,cAAc,GAAG,GAAG,CAAC;QAC1B,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,CAAC,mCAAmC,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;IAC7E,CAAC;IAEO,aAAa;QACnB,IAAI,IAAI,CAAC,cAAc;YAAE,OAAO;QAChC,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC;QAC3B,IAAI,CAAC,cAAc,EAAE,EAAE,CAAC;IAC1B,CAAC;CACF"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { type Plugin } from '@moxxy/sdk';
|
|
2
|
+
import type { VaultStore } from '@moxxy/plugin-vault';
|
|
3
|
+
export { ImessageChannel, type ImessageChannelOptions, type ImessageStartOpts, } from './channel.js';
|
|
4
|
+
export { buildImessagePermissionResolver } from './permission.js';
|
|
5
|
+
export { BlueBubblesClient, makeTempGuid, type BlueBubblesClientLike, type BlueBubblesClientOptions, type SocketLike, } from './bluebubbles-client.js';
|
|
6
|
+
export { gateInboundMessage, type GateState, type GateVerdict } from './message-gate.js';
|
|
7
|
+
export { messageSchema, MAX_INBOUND_TEXT_CHARS, type ImessageMessage } from './schema.js';
|
|
8
|
+
export { ChunkedSender, takeChunk, splitForImessage, IMESSAGE_CHUNK_SOFT_LIMIT, IMESSAGE_CHUNK_HARD_LIMIT, } from './channel/chunker.js';
|
|
9
|
+
export { IMESSAGE_SERVER_URL_KEY, IMESSAGE_SERVER_URL_ENV, IMESSAGE_SERVER_PASSWORD_KEY, IMESSAGE_SERVER_PASSWORD_ENV, IMESSAGE_ALLOWED_HANDLES_KEY, IMESSAGE_OWNER_HANDLES_KEY, parseHandleList, parseDmChatGuid, normalizeHandle, isHandle, E164_RE, EMAIL_RE, } from './keys.js';
|
|
10
|
+
export interface BuildImessagePluginOptions {
|
|
11
|
+
/** Host-injected encrypted secret store (available immediately). */
|
|
12
|
+
readonly vault: VaultStore;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Build the iMessage channel plugin with a host-injected vault (mirrors the
|
|
16
|
+
* Signal/WhatsApp plugins' vault injection).
|
|
17
|
+
*/
|
|
18
|
+
export declare function buildImessagePlugin(opts: BuildImessagePluginOptions): Plugin;
|
|
19
|
+
/**
|
|
20
|
+
* Discovery-loadable default export: resolves the vault from the inter-plugin
|
|
21
|
+
* service registry in `onInit` (the vault plugin publishes `'vault'`). Requires
|
|
22
|
+
* `@moxxy/plugin-vault` to load first (declared in `package.json`
|
|
23
|
+
* `moxxy.requirements`).
|
|
24
|
+
*/
|
|
25
|
+
export declare const imessagePlugin: Plugin;
|
|
26
|
+
export default imessagePlugin;
|
|
27
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoD,KAAK,MAAM,EAAE,MAAM,YAAY,CAAC;AAC3F,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAatD,OAAO,EACL,eAAe,EACf,KAAK,sBAAsB,EAC3B,KAAK,iBAAiB,GACvB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,+BAA+B,EAAE,MAAM,iBAAiB,CAAC;AAClE,OAAO,EACL,iBAAiB,EACjB,YAAY,EACZ,KAAK,qBAAqB,EAC1B,KAAK,wBAAwB,EAC7B,KAAK,UAAU,GAChB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,kBAAkB,EAAE,KAAK,SAAS,EAAE,KAAK,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACzF,OAAO,EAAE,aAAa,EAAE,sBAAsB,EAAE,KAAK,eAAe,EAAE,MAAM,aAAa,CAAC;AAC1F,OAAO,EACL,aAAa,EACb,SAAS,EACT,gBAAgB,EAChB,yBAAyB,EACzB,yBAAyB,GAC1B,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,uBAAuB,EACvB,uBAAuB,EACvB,4BAA4B,EAC5B,4BAA4B,EAC5B,4BAA4B,EAC5B,0BAA0B,EAC1B,eAAe,EACf,eAAe,EACf,eAAe,EACf,QAAQ,EACR,OAAO,EACP,QAAQ,GACT,MAAM,WAAW,CAAC;AAEnB,MAAM,WAAW,0BAA0B;IACzC,oEAAoE;IACpE,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC;CAC5B;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,0BAA0B,GAAG,MAAM,CAE5E;AAED;;;;;GAKG;AACH,eAAO,MAAM,cAAc,EAAE,MAgBzB,CAAC;AAEL,eAAe,cAAc,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
import { defineChannel, definePlugin } from '@moxxy/sdk';
|
|
2
|
+
import { ImessageChannel } from './channel.js';
|
|
3
|
+
import { IMESSAGE_ALLOWED_HANDLES_KEY, IMESSAGE_OWNER_HANDLES_KEY, IMESSAGE_SERVER_PASSWORD_ENV, IMESSAGE_SERVER_PASSWORD_KEY, IMESSAGE_SERVER_URL_ENV, IMESSAGE_SERVER_URL_KEY, parseHandleList, } from './keys.js';
|
|
4
|
+
import { runImessageWizard } from './setup-wizard.js';
|
|
5
|
+
export { ImessageChannel, } from './channel.js';
|
|
6
|
+
export { buildImessagePermissionResolver } from './permission.js';
|
|
7
|
+
export { BlueBubblesClient, makeTempGuid, } from './bluebubbles-client.js';
|
|
8
|
+
export { gateInboundMessage } from './message-gate.js';
|
|
9
|
+
export { messageSchema, MAX_INBOUND_TEXT_CHARS } from './schema.js';
|
|
10
|
+
export { ChunkedSender, takeChunk, splitForImessage, IMESSAGE_CHUNK_SOFT_LIMIT, IMESSAGE_CHUNK_HARD_LIMIT, } from './channel/chunker.js';
|
|
11
|
+
export { IMESSAGE_SERVER_URL_KEY, IMESSAGE_SERVER_URL_ENV, IMESSAGE_SERVER_PASSWORD_KEY, IMESSAGE_SERVER_PASSWORD_ENV, IMESSAGE_ALLOWED_HANDLES_KEY, IMESSAGE_OWNER_HANDLES_KEY, parseHandleList, parseDmChatGuid, normalizeHandle, isHandle, E164_RE, EMAIL_RE, } from './keys.js';
|
|
12
|
+
/**
|
|
13
|
+
* Build the iMessage channel plugin with a host-injected vault (mirrors the
|
|
14
|
+
* Signal/WhatsApp plugins' vault injection).
|
|
15
|
+
*/
|
|
16
|
+
export function buildImessagePlugin(opts) {
|
|
17
|
+
return makeImessagePlugin(() => opts.vault);
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Discovery-loadable default export: resolves the vault from the inter-plugin
|
|
21
|
+
* service registry in `onInit` (the vault plugin publishes `'vault'`). Requires
|
|
22
|
+
* `@moxxy/plugin-vault` to load first (declared in `package.json`
|
|
23
|
+
* `moxxy.requirements`).
|
|
24
|
+
*/
|
|
25
|
+
export const imessagePlugin = (() => {
|
|
26
|
+
let resolved = null;
|
|
27
|
+
const getVault = () => {
|
|
28
|
+
if (!resolved) {
|
|
29
|
+
throw new Error('@moxxy/plugin-channel-imessage: the "vault" service is unavailable — @moxxy/plugin-vault must load first');
|
|
30
|
+
}
|
|
31
|
+
return resolved;
|
|
32
|
+
};
|
|
33
|
+
const hooks = {
|
|
34
|
+
onInit: (ctx) => {
|
|
35
|
+
resolved = ctx.services.require('vault');
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
return makeImessagePlugin(getVault, hooks);
|
|
39
|
+
})();
|
|
40
|
+
export default imessagePlugin;
|
|
41
|
+
function readStringArray(value) {
|
|
42
|
+
if (Array.isArray(value))
|
|
43
|
+
return value.map((x) => String(x));
|
|
44
|
+
if (typeof value === 'string' && value.trim()) {
|
|
45
|
+
return value
|
|
46
|
+
.split(',')
|
|
47
|
+
.map((s) => s.trim())
|
|
48
|
+
.filter(Boolean);
|
|
49
|
+
}
|
|
50
|
+
return undefined;
|
|
51
|
+
}
|
|
52
|
+
function envConfigured() {
|
|
53
|
+
const url = process.env[IMESSAGE_SERVER_URL_ENV];
|
|
54
|
+
const pass = process.env[IMESSAGE_SERVER_PASSWORD_ENV];
|
|
55
|
+
return typeof url === 'string' && url.trim().length > 0 && typeof pass === 'string' && pass.trim().length > 0;
|
|
56
|
+
}
|
|
57
|
+
function makeImessagePlugin(getVault, hooks) {
|
|
58
|
+
return definePlugin({
|
|
59
|
+
name: '@moxxy/plugin-channel-imessage',
|
|
60
|
+
version: '0.0.0',
|
|
61
|
+
...(hooks ? { hooks } : {}),
|
|
62
|
+
channels: [
|
|
63
|
+
defineChannel({
|
|
64
|
+
name: 'imessage',
|
|
65
|
+
description: 'iMessage channel via a localhost BlueBubbles server (macOS only). Allow-listed handles (and your own self-chat) drive the agent; replies go out as buffered chunked sends.',
|
|
66
|
+
// A BlueBubbles server sees ALL the account owner's messages, so this
|
|
67
|
+
// channel runs on its own dedicated, isolated runner (separate socket +
|
|
68
|
+
// sticky session), like Signal — it keeps its own persistent history
|
|
69
|
+
// apart from the user's desktop/TUI work.
|
|
70
|
+
dedicatedRunner: true,
|
|
71
|
+
sessionSource: 'imessage',
|
|
72
|
+
config: {
|
|
73
|
+
fields: [
|
|
74
|
+
{
|
|
75
|
+
name: 'serverUrl',
|
|
76
|
+
label: 'BlueBubbles server URL',
|
|
77
|
+
vaultKey: IMESSAGE_SERVER_URL_KEY,
|
|
78
|
+
required: true,
|
|
79
|
+
secret: false,
|
|
80
|
+
placeholder: 'http://localhost:1234',
|
|
81
|
+
help: 'The BlueBubbles server running on this Mac (default port 1234)',
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
name: 'password',
|
|
85
|
+
label: 'BlueBubbles server password',
|
|
86
|
+
vaultKey: IMESSAGE_SERVER_PASSWORD_KEY,
|
|
87
|
+
required: true,
|
|
88
|
+
secret: true,
|
|
89
|
+
help: 'The password set in the BlueBubbles app (sent as a query param on every request)',
|
|
90
|
+
},
|
|
91
|
+
],
|
|
92
|
+
hasRequestUrl: false,
|
|
93
|
+
runHint: 'Install the BlueBubbles server on this Mac, sign in to Messages, set a password, then run `moxxy channels imessage setup` to add allowed handles.',
|
|
94
|
+
connect: {
|
|
95
|
+
kind: 'instructions',
|
|
96
|
+
title: 'Connect BlueBubbles',
|
|
97
|
+
steps: [
|
|
98
|
+
'Install the BlueBubbles server on this Mac from https://bluebubbles.app and sign in to Messages.',
|
|
99
|
+
'In the BlueBubbles app, set a server password and note the port (default 1234).',
|
|
100
|
+
'Run `moxxy channels imessage setup` and paste the URL + password, then add the handles allowed to talk to moxxy.',
|
|
101
|
+
],
|
|
102
|
+
},
|
|
103
|
+
},
|
|
104
|
+
create: (deps) => {
|
|
105
|
+
const options = deps.options;
|
|
106
|
+
const channelOpts = {
|
|
107
|
+
vault: getVault(),
|
|
108
|
+
...(typeof options?.['serverUrl'] === 'string' ? { serverUrl: options['serverUrl'] } : {}),
|
|
109
|
+
...(typeof options?.['password'] === 'string' ? { password: options['password'] } : {}),
|
|
110
|
+
...(() => {
|
|
111
|
+
const tools = readStringArray(options?.['allowedTools']);
|
|
112
|
+
return tools ? { allowedTools: tools } : {};
|
|
113
|
+
})(),
|
|
114
|
+
...(() => {
|
|
115
|
+
const handles = readStringArray(options?.['allowedHandles']);
|
|
116
|
+
return handles ? { allowedHandles: handles } : {};
|
|
117
|
+
})(),
|
|
118
|
+
...(() => {
|
|
119
|
+
const handles = readStringArray(options?.['ownerHandles']);
|
|
120
|
+
return handles ? { ownerHandles: handles } : {};
|
|
121
|
+
})(),
|
|
122
|
+
logger: deps.logger,
|
|
123
|
+
};
|
|
124
|
+
return new ImessageChannel(channelOpts);
|
|
125
|
+
},
|
|
126
|
+
isAvailable: async () => {
|
|
127
|
+
// Pure check — NO network probe (this runs on every `moxxy channels
|
|
128
|
+
// list` / `moxxy doctor`). The reachability ping is deferred to start().
|
|
129
|
+
if (process.platform !== 'darwin') {
|
|
130
|
+
return {
|
|
131
|
+
ok: false,
|
|
132
|
+
reason: 'iMessage requires macOS (a BlueBubbles server running on this Mac).',
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
// Env pair short-circuit (the vault may not be wired in a probe context).
|
|
136
|
+
if (envConfigured())
|
|
137
|
+
return { ok: true };
|
|
138
|
+
try {
|
|
139
|
+
const vault = getVault();
|
|
140
|
+
if ((await vault.has(IMESSAGE_SERVER_URL_KEY)) && (await vault.has(IMESSAGE_SERVER_PASSWORD_KEY))) {
|
|
141
|
+
return { ok: true };
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
catch {
|
|
145
|
+
/* vault unavailable in a probe context — fall through */
|
|
146
|
+
}
|
|
147
|
+
return {
|
|
148
|
+
ok: false,
|
|
149
|
+
reason: 'No BlueBubbles server configured. Run `moxxy channels imessage setup`.',
|
|
150
|
+
};
|
|
151
|
+
},
|
|
152
|
+
interactiveCommand: 'setup',
|
|
153
|
+
subcommands: {
|
|
154
|
+
setup: {
|
|
155
|
+
description: 'Interactive setup: store the BlueBubbles server URL + password, the handle allow-list and your own self-chat handles, pick the tool allow-list, then start. Shown by default for `moxxy imessage` on a TTY.',
|
|
156
|
+
run: async (ctx) => {
|
|
157
|
+
if (process.stdin.isTTY !== true) {
|
|
158
|
+
// Headless: just start the channel (server must already be configured).
|
|
159
|
+
return ctx.startChannel();
|
|
160
|
+
}
|
|
161
|
+
return runImessageWizard(ctx);
|
|
162
|
+
},
|
|
163
|
+
},
|
|
164
|
+
status: {
|
|
165
|
+
description: 'Report platform / server-config / allow-list state as JSON.',
|
|
166
|
+
run: async (ctx) => {
|
|
167
|
+
const vault = ctx.deps.vault;
|
|
168
|
+
if (!vault) {
|
|
169
|
+
process.stderr.write('vault unavailable\n');
|
|
170
|
+
return 1;
|
|
171
|
+
}
|
|
172
|
+
const serverUrl = process.env[IMESSAGE_SERVER_URL_ENV]?.trim() || (await vault.get(IMESSAGE_SERVER_URL_KEY));
|
|
173
|
+
const passwordSet = (process.env[IMESSAGE_SERVER_PASSWORD_ENV]?.trim() ?? '').length > 0 ||
|
|
174
|
+
(await vault.has(IMESSAGE_SERVER_PASSWORD_KEY));
|
|
175
|
+
const allowedHandles = parseHandleList(await vault.get(IMESSAGE_ALLOWED_HANDLES_KEY));
|
|
176
|
+
const ownerHandles = parseHandleList(await vault.get(IMESSAGE_OWNER_HANDLES_KEY));
|
|
177
|
+
process.stdout.write(JSON.stringify({
|
|
178
|
+
platform: process.platform,
|
|
179
|
+
supported: process.platform === 'darwin',
|
|
180
|
+
serverUrl: serverUrl || null,
|
|
181
|
+
passwordSet,
|
|
182
|
+
allowedHandles,
|
|
183
|
+
ownerHandles,
|
|
184
|
+
}, null, 2) + '\n');
|
|
185
|
+
return 0;
|
|
186
|
+
},
|
|
187
|
+
},
|
|
188
|
+
unpair: {
|
|
189
|
+
description: 'Forget the stored BlueBubbles server URL + password and the handle allow-list. (The BlueBubbles app itself is untouched — uninstall or reset it there to fully disconnect.)',
|
|
190
|
+
run: async (ctx) => {
|
|
191
|
+
const vault = ctx.deps.vault;
|
|
192
|
+
if (!vault) {
|
|
193
|
+
process.stderr.write('vault unavailable\n');
|
|
194
|
+
return 1;
|
|
195
|
+
}
|
|
196
|
+
const removedUrl = await vault.delete(IMESSAGE_SERVER_URL_KEY);
|
|
197
|
+
await vault.delete(IMESSAGE_SERVER_PASSWORD_KEY);
|
|
198
|
+
await vault.delete(IMESSAGE_ALLOWED_HANDLES_KEY);
|
|
199
|
+
await vault.delete(IMESSAGE_OWNER_HANDLES_KEY);
|
|
200
|
+
process.stdout.write(removedUrl
|
|
201
|
+
? 'unpaired (vault cleared). The BlueBubbles server app is untouched — reset it there to fully disconnect.\n'
|
|
202
|
+
: 'no BlueBubbles server was configured\n');
|
|
203
|
+
return 0;
|
|
204
|
+
},
|
|
205
|
+
},
|
|
206
|
+
},
|
|
207
|
+
}),
|
|
208
|
+
],
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/keys.d.ts
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Vault keys + pure handle helpers shared by the channel, its subcommands, and
|
|
3
|
+
* the interactive setup wizard. Kept in their own module (the signal/whatsapp
|
|
4
|
+
* `keys.ts` pattern) so wizard helpers can import them without pulling in the
|
|
5
|
+
* plugin's full index (or, worse, socket.io-client — which stays behind a lazy
|
|
6
|
+
* import in `bluebubbles-client.ts`).
|
|
7
|
+
*
|
|
8
|
+
* Note on custody: the BlueBubbles server (a native macOS app) holds the actual
|
|
9
|
+
* iMessage identity + message store. The moxxy vault only stores the localhost
|
|
10
|
+
* server URL, its password, and two JSON handle arrays — the allow-list of OTHER
|
|
11
|
+
* people who may drive the agent, and the owner's own handle(s) that enable
|
|
12
|
+
* texting moxxy from your own devices (the "self-chat").
|
|
13
|
+
*/
|
|
14
|
+
/** Vault key for the BlueBubbles server URL (e.g. http://localhost:1234). */
|
|
15
|
+
export declare const IMESSAGE_SERVER_URL_KEY = "imessage_server_url";
|
|
16
|
+
/** Env override for the server URL — beats the vault (shared precedence). */
|
|
17
|
+
export declare const IMESSAGE_SERVER_URL_ENV = "MOXXY_IMESSAGE_SERVER_URL";
|
|
18
|
+
/** Vault key for the BlueBubbles server password. */
|
|
19
|
+
export declare const IMESSAGE_SERVER_PASSWORD_KEY = "imessage_server_password";
|
|
20
|
+
/** Env override for the server password — beats the vault. */
|
|
21
|
+
export declare const IMESSAGE_SERVER_PASSWORD_ENV = "MOXXY_IMESSAGE_SERVER_PASSWORD";
|
|
22
|
+
/**
|
|
23
|
+
* Vault key for the allow-list: a JSON array of iMessage handles (E.164 phone
|
|
24
|
+
* numbers and/or Apple-ID emails) that OTHER people may use to drive the
|
|
25
|
+
* session. The owner's own handle is NOT listed here — it lives in
|
|
26
|
+
* {@link IMESSAGE_OWNER_HANDLES_KEY} so an inbound from a friend and an outbound
|
|
27
|
+
* from the owner stay distinguishable (never react to the owner's private
|
|
28
|
+
* conversations with allow-listed friends).
|
|
29
|
+
*/
|
|
30
|
+
export declare const IMESSAGE_ALLOWED_HANDLES_KEY = "imessage_allowed_handles";
|
|
31
|
+
/**
|
|
32
|
+
* Vault key for the owner's OWN handle(s): a JSON array of the account owner's
|
|
33
|
+
* E.164 numbers / Apple-ID emails. A message the account itself sent
|
|
34
|
+
* (`isFromMe`) drives a turn only when it lands in a 1:1 chat with one of these
|
|
35
|
+
* handles — i.e. the owner texting their own "self-chat" from any Apple device.
|
|
36
|
+
* Empty (the default) means self-chat is off and every `isFromMe` message is
|
|
37
|
+
* dropped (fail closed); the friend allow-list path is unaffected.
|
|
38
|
+
*/
|
|
39
|
+
export declare const IMESSAGE_OWNER_HANDLES_KEY = "imessage_owner_handles";
|
|
40
|
+
/** E.164 shape: `+` then 7–15 digits, no leading zero. */
|
|
41
|
+
export declare const E164_RE: RegExp;
|
|
42
|
+
/** Pragmatic email shape (Apple-ID handles). Deliberately loose but anchored. */
|
|
43
|
+
export declare const EMAIL_RE: RegExp;
|
|
44
|
+
/** Whether a normalized string is a plausible iMessage handle. */
|
|
45
|
+
export declare function isHandle(value: string): boolean;
|
|
46
|
+
/**
|
|
47
|
+
* Canonical handle for allow-list comparisons: trimmed, and lowercased when it
|
|
48
|
+
* is an email (Apple-ID handles are case-insensitive). Phone numbers are left
|
|
49
|
+
* as-is (they are already digits + `+`).
|
|
50
|
+
*/
|
|
51
|
+
export declare function normalizeHandle(raw: string): string;
|
|
52
|
+
/**
|
|
53
|
+
* Parse a stored handle list. Returns `[]` for a missing OR corrupt value
|
|
54
|
+
* rather than throwing — a corrupt vault entry must degrade to "nobody extra is
|
|
55
|
+
* allowed" (fail closed), never crash the channel or silently allow. Non-string
|
|
56
|
+
* entries and entries that are neither an E.164 number nor an email are dropped.
|
|
57
|
+
*/
|
|
58
|
+
export declare function parseHandleList(raw: string | null | undefined): string[];
|
|
59
|
+
/**
|
|
60
|
+
* Parse the chat GUID BlueBubbles stamps on every message
|
|
61
|
+
* (`SERVICE;TYPE;IDENTIFIER`, e.g. `iMessage;-;+15551234567`). TYPE is `-` for a
|
|
62
|
+
* 1:1 chat and `+` for a group. Returns null for anything that is not a
|
|
63
|
+
* well-formed 1:1 GUID (groups included) so callers treat it as "not a DM" and
|
|
64
|
+
* drop it (v1 is direct-message only).
|
|
65
|
+
*/
|
|
66
|
+
export declare function parseDmChatGuid(guid: string | null | undefined): {
|
|
67
|
+
readonly service: string;
|
|
68
|
+
readonly handle: string;
|
|
69
|
+
} | null;
|
|
70
|
+
//# sourceMappingURL=keys.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"keys.d.ts","sourceRoot":"","sources":["../src/keys.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,6EAA6E;AAC7E,eAAO,MAAM,uBAAuB,wBAAwB,CAAC;AAC7D,6EAA6E;AAC7E,eAAO,MAAM,uBAAuB,8BAA8B,CAAC;AACnE,qDAAqD;AACrD,eAAO,MAAM,4BAA4B,6BAA6B,CAAC;AACvE,8DAA8D;AAC9D,eAAO,MAAM,4BAA4B,mCAAmC,CAAC;AAC7E;;;;;;;GAOG;AACH,eAAO,MAAM,4BAA4B,6BAA6B,CAAC;AACvE;;;;;;;GAOG;AACH,eAAO,MAAM,0BAA0B,2BAA2B,CAAC;AAEnE,0DAA0D;AAC1D,eAAO,MAAM,OAAO,QAAsB,CAAC;AAE3C,iFAAiF;AACjF,eAAO,MAAM,QAAQ,QAA+B,CAAC;AAErD,kEAAkE;AAClE,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAE/C;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAGnD;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,EAAE,CAgBxE;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAC7B,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAC9B;IAAE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAa9D"}
|