@spinabot/brigade 1.7.0 → 1.8.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.
Files changed (214) hide show
  1. package/dist/agents/agent-loop.d.ts +13 -0
  2. package/dist/agents/agent-loop.d.ts.map +1 -1
  3. package/dist/agents/agent-loop.js +5 -0
  4. package/dist/agents/agent-loop.js.map +1 -1
  5. package/dist/agents/channels/access-control/group-tool-policy.d.ts +73 -0
  6. package/dist/agents/channels/access-control/group-tool-policy.d.ts.map +1 -0
  7. package/dist/agents/channels/access-control/group-tool-policy.js +193 -0
  8. package/dist/agents/channels/access-control/group-tool-policy.js.map +1 -0
  9. package/dist/agents/channels/access-control/index.d.ts +1 -0
  10. package/dist/agents/channels/access-control/index.d.ts.map +1 -1
  11. package/dist/agents/channels/access-control/index.js +1 -0
  12. package/dist/agents/channels/access-control/index.js.map +1 -1
  13. package/dist/agents/channels/bluebubbles/account-config.d.ts +253 -0
  14. package/dist/agents/channels/bluebubbles/account-config.d.ts.map +1 -0
  15. package/dist/agents/channels/bluebubbles/account-config.js +486 -0
  16. package/dist/agents/channels/bluebubbles/account-config.js.map +1 -0
  17. package/dist/agents/channels/bluebubbles/account-registry.d.ts +33 -0
  18. package/dist/agents/channels/bluebubbles/account-registry.d.ts.map +1 -0
  19. package/dist/agents/channels/bluebubbles/account-registry.js +46 -0
  20. package/dist/agents/channels/bluebubbles/account-registry.js.map +1 -0
  21. package/dist/agents/channels/bluebubbles/adapter.d.ts +45 -0
  22. package/dist/agents/channels/bluebubbles/adapter.d.ts.map +1 -0
  23. package/dist/agents/channels/bluebubbles/adapter.js +366 -0
  24. package/dist/agents/channels/bluebubbles/adapter.js.map +1 -0
  25. package/dist/agents/channels/bluebubbles/catchup-cursor.d.ts +52 -0
  26. package/dist/agents/channels/bluebubbles/catchup-cursor.d.ts.map +1 -0
  27. package/dist/agents/channels/bluebubbles/catchup-cursor.js +118 -0
  28. package/dist/agents/channels/bluebubbles/catchup-cursor.js.map +1 -0
  29. package/dist/agents/channels/bluebubbles/catchup.d.ts +114 -0
  30. package/dist/agents/channels/bluebubbles/catchup.d.ts.map +1 -0
  31. package/dist/agents/channels/bluebubbles/catchup.js +220 -0
  32. package/dist/agents/channels/bluebubbles/catchup.js.map +1 -0
  33. package/dist/agents/channels/bluebubbles/chat.d.ts +75 -0
  34. package/dist/agents/channels/bluebubbles/chat.d.ts.map +1 -0
  35. package/dist/agents/channels/bluebubbles/chat.js +182 -0
  36. package/dist/agents/channels/bluebubbles/chat.js.map +1 -0
  37. package/dist/agents/channels/bluebubbles/connection.d.ts +95 -0
  38. package/dist/agents/channels/bluebubbles/connection.d.ts.map +1 -0
  39. package/dist/agents/channels/bluebubbles/connection.js +413 -0
  40. package/dist/agents/channels/bluebubbles/connection.js.map +1 -0
  41. package/dist/agents/channels/bluebubbles/contact-names.d.ts +79 -0
  42. package/dist/agents/channels/bluebubbles/contact-names.d.ts.map +1 -0
  43. package/dist/agents/channels/bluebubbles/contact-names.js +188 -0
  44. package/dist/agents/channels/bluebubbles/contact-names.js.map +1 -0
  45. package/dist/agents/channels/bluebubbles/debounce.d.ts +78 -0
  46. package/dist/agents/channels/bluebubbles/debounce.d.ts.map +1 -0
  47. package/dist/agents/channels/bluebubbles/debounce.js +173 -0
  48. package/dist/agents/channels/bluebubbles/debounce.js.map +1 -0
  49. package/dist/agents/channels/bluebubbles/dedupe.d.ts +25 -0
  50. package/dist/agents/channels/bluebubbles/dedupe.d.ts.map +1 -0
  51. package/dist/agents/channels/bluebubbles/dedupe.js +35 -0
  52. package/dist/agents/channels/bluebubbles/dedupe.js.map +1 -0
  53. package/dist/agents/channels/bluebubbles/effects.d.ts +17 -0
  54. package/dist/agents/channels/bluebubbles/effects.d.ts.map +1 -0
  55. package/dist/agents/channels/bluebubbles/effects.js +57 -0
  56. package/dist/agents/channels/bluebubbles/effects.js.map +1 -0
  57. package/dist/agents/channels/bluebubbles/history.d.ts +56 -0
  58. package/dist/agents/channels/bluebubbles/history.d.ts.map +1 -0
  59. package/dist/agents/channels/bluebubbles/history.js +140 -0
  60. package/dist/agents/channels/bluebubbles/history.js.map +1 -0
  61. package/dist/agents/channels/bluebubbles/index.d.ts +18 -0
  62. package/dist/agents/channels/bluebubbles/index.d.ts.map +1 -0
  63. package/dist/agents/channels/bluebubbles/index.js +18 -0
  64. package/dist/agents/channels/bluebubbles/index.js.map +1 -0
  65. package/dist/agents/channels/bluebubbles/media.d.ts +104 -0
  66. package/dist/agents/channels/bluebubbles/media.d.ts.map +1 -0
  67. package/dist/agents/channels/bluebubbles/media.js +222 -0
  68. package/dist/agents/channels/bluebubbles/media.js.map +1 -0
  69. package/dist/agents/channels/bluebubbles/messaging.d.ts +13 -0
  70. package/dist/agents/channels/bluebubbles/messaging.d.ts.map +1 -0
  71. package/dist/agents/channels/bluebubbles/messaging.js +36 -0
  72. package/dist/agents/channels/bluebubbles/messaging.js.map +1 -0
  73. package/dist/agents/channels/bluebubbles/module.d.ts +24 -0
  74. package/dist/agents/channels/bluebubbles/module.d.ts.map +1 -0
  75. package/dist/agents/channels/bluebubbles/module.js +52 -0
  76. package/dist/agents/channels/bluebubbles/module.js.map +1 -0
  77. package/dist/agents/channels/bluebubbles/normalize.d.ts +111 -0
  78. package/dist/agents/channels/bluebubbles/normalize.d.ts.map +1 -0
  79. package/dist/agents/channels/bluebubbles/normalize.js +239 -0
  80. package/dist/agents/channels/bluebubbles/normalize.js.map +1 -0
  81. package/dist/agents/channels/bluebubbles/plugin.d.ts +46 -0
  82. package/dist/agents/channels/bluebubbles/plugin.d.ts.map +1 -0
  83. package/dist/agents/channels/bluebubbles/plugin.js +242 -0
  84. package/dist/agents/channels/bluebubbles/plugin.js.map +1 -0
  85. package/dist/agents/channels/bluebubbles/probe.d.ts +79 -0
  86. package/dist/agents/channels/bluebubbles/probe.d.ts.map +1 -0
  87. package/dist/agents/channels/bluebubbles/probe.js +138 -0
  88. package/dist/agents/channels/bluebubbles/probe.js.map +1 -0
  89. package/dist/agents/channels/bluebubbles/reactions.d.ts +46 -0
  90. package/dist/agents/channels/bluebubbles/reactions.d.ts.map +1 -0
  91. package/dist/agents/channels/bluebubbles/reactions.js +207 -0
  92. package/dist/agents/channels/bluebubbles/reactions.js.map +1 -0
  93. package/dist/agents/channels/bluebubbles/send.d.ts +132 -0
  94. package/dist/agents/channels/bluebubbles/send.d.ts.map +1 -0
  95. package/dist/agents/channels/bluebubbles/send.js +327 -0
  96. package/dist/agents/channels/bluebubbles/send.js.map +1 -0
  97. package/dist/agents/channels/bluebubbles/status-issues.d.ts +57 -0
  98. package/dist/agents/channels/bluebubbles/status-issues.d.ts.map +1 -0
  99. package/dist/agents/channels/bluebubbles/status-issues.js +93 -0
  100. package/dist/agents/channels/bluebubbles/status-issues.js.map +1 -0
  101. package/dist/agents/channels/bluebubbles/types.d.ts +69 -0
  102. package/dist/agents/channels/bluebubbles/types.d.ts.map +1 -0
  103. package/dist/agents/channels/bluebubbles/types.js +118 -0
  104. package/dist/agents/channels/bluebubbles/types.js.map +1 -0
  105. package/dist/agents/channels/bluebubbles/webhook.d.ts +97 -0
  106. package/dist/agents/channels/bluebubbles/webhook.d.ts.map +1 -0
  107. package/dist/agents/channels/bluebubbles/webhook.js +249 -0
  108. package/dist/agents/channels/bluebubbles/webhook.js.map +1 -0
  109. package/dist/agents/channels/bundled-channel-metas.d.ts +13 -0
  110. package/dist/agents/channels/bundled-channel-metas.d.ts.map +1 -1
  111. package/dist/agents/channels/bundled-channel-metas.js +33 -0
  112. package/dist/agents/channels/bundled-channel-metas.js.map +1 -1
  113. package/dist/agents/channels/imessage/account-config.d.ts +178 -0
  114. package/dist/agents/channels/imessage/account-config.d.ts.map +1 -0
  115. package/dist/agents/channels/imessage/account-config.js +371 -0
  116. package/dist/agents/channels/imessage/account-config.js.map +1 -0
  117. package/dist/agents/channels/imessage/adapter.d.ts +36 -0
  118. package/dist/agents/channels/imessage/adapter.d.ts.map +1 -0
  119. package/dist/agents/channels/imessage/adapter.js +286 -0
  120. package/dist/agents/channels/imessage/adapter.js.map +1 -0
  121. package/dist/agents/channels/imessage/client.d.ts +99 -0
  122. package/dist/agents/channels/imessage/client.d.ts.map +1 -0
  123. package/dist/agents/channels/imessage/client.js +231 -0
  124. package/dist/agents/channels/imessage/client.js.map +1 -0
  125. package/dist/agents/channels/imessage/connection.d.ts +101 -0
  126. package/dist/agents/channels/imessage/connection.d.ts.map +1 -0
  127. package/dist/agents/channels/imessage/connection.js +367 -0
  128. package/dist/agents/channels/imessage/connection.js.map +1 -0
  129. package/dist/agents/channels/imessage/format.d.ts +45 -0
  130. package/dist/agents/channels/imessage/format.d.ts.map +1 -0
  131. package/dist/agents/channels/imessage/format.js +170 -0
  132. package/dist/agents/channels/imessage/format.js.map +1 -0
  133. package/dist/agents/channels/imessage/history.d.ts +49 -0
  134. package/dist/agents/channels/imessage/history.d.ts.map +1 -0
  135. package/dist/agents/channels/imessage/history.js +74 -0
  136. package/dist/agents/channels/imessage/history.js.map +1 -0
  137. package/dist/agents/channels/imessage/index.d.ts +25 -0
  138. package/dist/agents/channels/imessage/index.d.ts.map +1 -0
  139. package/dist/agents/channels/imessage/index.js +25 -0
  140. package/dist/agents/channels/imessage/index.js.map +1 -0
  141. package/dist/agents/channels/imessage/media.d.ts +92 -0
  142. package/dist/agents/channels/imessage/media.d.ts.map +1 -0
  143. package/dist/agents/channels/imessage/media.js +196 -0
  144. package/dist/agents/channels/imessage/media.js.map +1 -0
  145. package/dist/agents/channels/imessage/messaging.d.ts +14 -0
  146. package/dist/agents/channels/imessage/messaging.d.ts.map +1 -0
  147. package/dist/agents/channels/imessage/messaging.js +37 -0
  148. package/dist/agents/channels/imessage/messaging.js.map +1 -0
  149. package/dist/agents/channels/imessage/module.d.ts +16 -0
  150. package/dist/agents/channels/imessage/module.d.ts.map +1 -0
  151. package/dist/agents/channels/imessage/module.js +23 -0
  152. package/dist/agents/channels/imessage/module.js.map +1 -0
  153. package/dist/agents/channels/imessage/monitor.d.ts +207 -0
  154. package/dist/agents/channels/imessage/monitor.d.ts.map +1 -0
  155. package/dist/agents/channels/imessage/monitor.js +504 -0
  156. package/dist/agents/channels/imessage/monitor.js.map +1 -0
  157. package/dist/agents/channels/imessage/plugin.d.ts +53 -0
  158. package/dist/agents/channels/imessage/plugin.d.ts.map +1 -0
  159. package/dist/agents/channels/imessage/plugin.js +215 -0
  160. package/dist/agents/channels/imessage/plugin.js.map +1 -0
  161. package/dist/agents/channels/imessage/probe.d.ts +68 -0
  162. package/dist/agents/channels/imessage/probe.d.ts.map +1 -0
  163. package/dist/agents/channels/imessage/probe.js +134 -0
  164. package/dist/agents/channels/imessage/probe.js.map +1 -0
  165. package/dist/agents/channels/imessage/remote-attachments.d.ts +61 -0
  166. package/dist/agents/channels/imessage/remote-attachments.d.ts.map +1 -0
  167. package/dist/agents/channels/imessage/remote-attachments.js +131 -0
  168. package/dist/agents/channels/imessage/remote-attachments.js.map +1 -0
  169. package/dist/agents/channels/imessage/send.d.ts +61 -0
  170. package/dist/agents/channels/imessage/send.d.ts.map +1 -0
  171. package/dist/agents/channels/imessage/send.js +108 -0
  172. package/dist/agents/channels/imessage/send.js.map +1 -0
  173. package/dist/agents/channels/imessage/targets.d.ts +91 -0
  174. package/dist/agents/channels/imessage/targets.d.ts.map +1 -0
  175. package/dist/agents/channels/imessage/targets.js +245 -0
  176. package/dist/agents/channels/imessage/targets.js.map +1 -0
  177. package/dist/agents/channels/imessage/watch-error.d.ts +23 -0
  178. package/dist/agents/channels/imessage/watch-error.d.ts.map +1 -0
  179. package/dist/agents/channels/imessage/watch-error.js +69 -0
  180. package/dist/agents/channels/imessage/watch-error.js.map +1 -0
  181. package/dist/agents/channels/inbound-pipeline.d.ts +11 -0
  182. package/dist/agents/channels/inbound-pipeline.d.ts.map +1 -1
  183. package/dist/agents/channels/inbound-pipeline.js +20 -1
  184. package/dist/agents/channels/inbound-pipeline.js.map +1 -1
  185. package/dist/agents/channels/manager.d.ts +9 -0
  186. package/dist/agents/channels/manager.d.ts.map +1 -1
  187. package/dist/agents/channels/manager.js.map +1 -1
  188. package/dist/agents/channels/sdk.d.ts +4 -0
  189. package/dist/agents/channels/sdk.d.ts.map +1 -1
  190. package/dist/agents/channels/sdk.js +4 -0
  191. package/dist/agents/channels/sdk.js.map +1 -1
  192. package/dist/agents/extensions/modules/index.d.ts.map +1 -1
  193. package/dist/agents/extensions/modules/index.js +12 -0
  194. package/dist/agents/extensions/modules/index.js.map +1 -1
  195. package/dist/agents/session-wiring.d.ts +31 -0
  196. package/dist/agents/session-wiring.d.ts.map +1 -1
  197. package/dist/agents/session-wiring.js +45 -2
  198. package/dist/agents/session-wiring.js.map +1 -1
  199. package/dist/agents/tools/bluebubbles-action-tool.d.ts +66 -0
  200. package/dist/agents/tools/bluebubbles-action-tool.d.ts.map +1 -0
  201. package/dist/agents/tools/bluebubbles-action-tool.js +234 -0
  202. package/dist/agents/tools/bluebubbles-action-tool.js.map +1 -0
  203. package/dist/agents/tools/registry.d.ts.map +1 -1
  204. package/dist/agents/tools/registry.js +18 -0
  205. package/dist/agents/tools/registry.js.map +1 -1
  206. package/dist/buildstamp.json +1 -1
  207. package/dist/core/server.d.ts.map +1 -1
  208. package/dist/core/server.js +48 -2
  209. package/dist/core/server.js.map +1 -1
  210. package/dist/infra/net/fetch-guard.d.ts +24 -2
  211. package/dist/infra/net/fetch-guard.d.ts.map +1 -1
  212. package/dist/infra/net/fetch-guard.js +78 -31
  213. package/dist/infra/net/fetch-guard.js.map +1 -1
  214. package/package.json +1 -1
@@ -0,0 +1,101 @@
1
+ /**
2
+ * iMessage transport connection — the live `imsg rpc` subprocess lifecycle.
3
+ *
4
+ * `connectIMessage` owns a long-lived {@link IMessageRpcLike} client, subscribes
5
+ * to inbound notifications (`watch.subscribe`), runs each `message` notification
6
+ * through the monitor's gating brain (`decideInbound`), and hands dispatched
7
+ * inbounds to `onMessage`. It also exposes the outbound `sendText` / `sendMedia`
8
+ * (which `remember` every send in the echo cache so the inbound poll drops the
9
+ * echo) + reconnect with the shared jittered backoff.
10
+ *
11
+ * TEST SEAM: `clientFactory` builds the RPC client — production lets it default
12
+ * to the real {@link createIMessageRpcClient} (which itself refuses to spawn in
13
+ * tests); a unit test injects a fake satisfying {@link IMessageRpcLike}. The
14
+ * adapter layers a second seam (`connectImpl`) on top, mirroring Discord. No
15
+ * `isTestEnv` flag is consulted here — the seam is pure dependency injection.
16
+ */
17
+ import { type ResolvedIMessageAccount } from "./account-config.js";
18
+ import { type IMessageRpcLike, type IMessageRpcNotification } from "./client.js";
19
+ import { normalizeIMessageMessage, type NormalizedIMessage } from "./monitor.js";
20
+ import { type IMessageProbeResult } from "./probe.js";
21
+ import { type ScpCopyArgs, type ReadFileLike } from "./remote-attachments.js";
22
+ import { sendMessageIMessage } from "./send.js";
23
+ import type { BrigadeConfig } from "../sdk.js";
24
+ import type { OutboundMedia, OutboundSendOptions, InboundMediaAttachment } from "../sdk.js";
25
+ /** The inbound message the connection hands the adapter (carries the deferred-media thunk). */
26
+ export interface IMessageInboundMessage extends NormalizedIMessage {
27
+ /** Deferred inbound-media resolver (invoked only after the access gate admits the sender). */
28
+ resolveMedia?: () => Promise<InboundMediaAttachment[]>;
29
+ /**
30
+ * Rolling-history context block (`[recent conversation context]…`) to PREPEND
31
+ * to the body, set for an untagged group message when `historyLimit > 0`. The
32
+ * adapter folds it into the dispatched text. Unset when no context applies.
33
+ */
34
+ historyContext?: string;
35
+ }
36
+ /** Args for {@link connectIMessage}. */
37
+ export interface ConnectIMessageArgs {
38
+ account: ResolvedIMessageAccount;
39
+ /** Active config — used to resolve inbound attachment roots per message. */
40
+ loadConfig: () => BrigadeConfig;
41
+ log: (msg: string, meta?: Record<string, unknown>) => void;
42
+ /** Fired once the subscription is live. */
43
+ onConnected?: () => void;
44
+ /** Fired when the transport gives up (binary gone / fatal). */
45
+ onClosed?: (reason: string) => void;
46
+ /** Dispatched inbound (post gating + dedupe). */
47
+ onMessage: (msg: IMessageInboundMessage) => void;
48
+ signal?: AbortSignal;
49
+ /** TEST SEAM: build the RPC client. Defaults to the real subprocess client. */
50
+ clientFactory?: (opts: {
51
+ cliPath: string;
52
+ dbPath?: string;
53
+ onNotification: (msg: IMessageRpcNotification) => void;
54
+ runtime: {
55
+ error?: (m: string) => void;
56
+ info?: (m: string) => void;
57
+ };
58
+ }) => Promise<IMessageRpcLike>;
59
+ /** TEST SEAM: replace the real `sendMessageIMessage` (so outbound tests need no client). */
60
+ sendImpl?: typeof sendMessageIMessage;
61
+ /** TEST SEAM: replace the backoff sleep (instant reconnect in tests). */
62
+ sleepImpl?: (ms: number) => Promise<void>;
63
+ /**
64
+ * TEST SEAM: probe the transport readiness (the cold-bridge gate before the
65
+ * first subscribe). Defaults to the real `probeIMessage`.
66
+ */
67
+ probeImpl?: (args: {
68
+ cliPath: string;
69
+ dbPath?: string;
70
+ timeoutMs?: number;
71
+ }) => Promise<IMessageProbeResult>;
72
+ /** TEST SEAM: read an SSH-wrapper `cliPath` for remote-host auto-detection. */
73
+ readFileImpl?: ReadFileLike;
74
+ /** TEST SEAM: run the `scp` copy for a remote-host inbound attachment. */
75
+ scpRunner?: ScpCopyArgs["scpRunner"];
76
+ /** TEST SEAM: temp-dir factory for the remote-attachment copy. */
77
+ mkdtempImpl?: ScpCopyArgs["mkdtempImpl"];
78
+ }
79
+ /** The live connection handle the adapter drives. */
80
+ export interface IMessageConnection {
81
+ isConnected(): boolean;
82
+ connectedAt(): number | null;
83
+ /** Send text; returns the bridge message id when available. */
84
+ sendText(conversationId: string, text: string, opts?: OutboundSendOptions): Promise<{
85
+ messageId?: string;
86
+ }>;
87
+ /** Send media; returns the bridge message id when available. */
88
+ sendMedia(conversationId: string, media: OutboundMedia): Promise<{
89
+ messageId?: string;
90
+ }>;
91
+ /** Tear down the subprocess + stop reconnecting. */
92
+ close(): Promise<void>;
93
+ }
94
+ /**
95
+ * Open the iMessage transport. Resolves once the first subscription is live (or
96
+ * the connect terminally fails). Keeps reconnecting in the background until
97
+ * `close()` / the abort signal fires.
98
+ */
99
+ export declare function connectIMessage(args: ConnectIMessageArgs): Promise<IMessageConnection>;
100
+ export { normalizeIMessageMessage };
101
+ //# sourceMappingURL=connection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connection.d.ts","sourceRoot":"","sources":["../../../../src/agents/channels/imessage/connection.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,367 @@
1
+ /**
2
+ * iMessage transport connection — the live `imsg rpc` subprocess lifecycle.
3
+ *
4
+ * `connectIMessage` owns a long-lived {@link IMessageRpcLike} client, subscribes
5
+ * to inbound notifications (`watch.subscribe`), runs each `message` notification
6
+ * through the monitor's gating brain (`decideInbound`), and hands dispatched
7
+ * inbounds to `onMessage`. It also exposes the outbound `sendText` / `sendMedia`
8
+ * (which `remember` every send in the echo cache so the inbound poll drops the
9
+ * echo) + reconnect with the shared jittered backoff.
10
+ *
11
+ * TEST SEAM: `clientFactory` builds the RPC client — production lets it default
12
+ * to the real {@link createIMessageRpcClient} (which itself refuses to spawn in
13
+ * tests); a unit test injects a fake satisfying {@link IMessageRpcLike}. The
14
+ * adapter layers a second seam (`connectImpl`) on top, mirroring Discord. No
15
+ * `isTestEnv` flag is consulted here — the seam is pure dependency injection.
16
+ */
17
+ import { nextBackoffDelay } from "../sdk.js";
18
+ import { resolveIMessageAttachmentRoots, resolveIMessageRemoteAttachmentRoots, } from "./account-config.js";
19
+ import { createIMessageRpcClient, } from "./client.js";
20
+ import { IMessageHistoryBuffer, renderIMessageHistoryBlock } from "./history.js";
21
+ import { inferOutboundMediaKind, resolveInboundAttachments, resolveInboundAttachmentsRemote } from "./media.js";
22
+ import { createMonitorState, decideInbound, echoScope, normalizeIMessageMessage, parseIMessageNotification, } from "./monitor.js";
23
+ import { probeIMessage } from "./probe.js";
24
+ import { detectRemoteHostFromCliPath, normalizeScpRemoteHost, } from "./remote-attachments.js";
25
+ import { sendMessageIMessage } from "./send.js";
26
+ import { sanitizeIMessageWatchErrorPayload } from "./watch-error.js";
27
+ /** Reconnect schedule constants — mirror the shared WhatsApp curve. */
28
+ const RECONNECT_INITIAL_MS = 2_000;
29
+ const RECONNECT_MAX_MS = 30_000;
30
+ const RECONNECT_FACTOR = 1.8;
31
+ const RECONNECT_JITTER = 0.25;
32
+ const RECONNECT_MAX_ATTEMPTS = 12;
33
+ /** Watch-subscribe startup retry — 3 quick attempts before falling to backoff. */
34
+ const WATCH_SUBSCRIBE_MAX_ATTEMPTS = 3;
35
+ const WATCH_SUBSCRIBE_RETRY_DELAY_MS = 1_000;
36
+ /** Transport-readiness gate — poll `probeIMessage` until the bridge is up. */
37
+ const TRANSPORT_READY_TIMEOUT_MS = 30_000;
38
+ const TRANSPORT_READY_POLL_INTERVAL_MS = 500;
39
+ const TRANSPORT_READY_LOG_INTERVAL_MS = 10_000;
40
+ /** Transient startup errors worth a quick subscribe retry (vs the slow backoff loop). */
41
+ function isRetriableSubscribeStartupError(error) {
42
+ return /imsg rpc timeout \(watch\.subscribe\)|imsg rpc (closed|exited|not running)/i.test(String(error));
43
+ }
44
+ const defaultSleep = (ms) => new Promise((resolve) => {
45
+ const t = setTimeout(resolve, ms);
46
+ if (typeof t.unref === "function")
47
+ t.unref();
48
+ });
49
+ /**
50
+ * Open the iMessage transport. Resolves once the first subscription is live (or
51
+ * the connect terminally fails). Keeps reconnecting in the background until
52
+ * `close()` / the abort signal fires.
53
+ */
54
+ export async function connectIMessage(args) {
55
+ const { account } = args;
56
+ const state = createMonitorState();
57
+ const sleep = args.sleepImpl ?? defaultSleep;
58
+ const sendFn = args.sendImpl ?? sendMessageIMessage;
59
+ const probe = args.probeImpl ?? ((a) => probeIMessage(a));
60
+ const clientFactory = args.clientFactory ??
61
+ (async (opts) => createIMessageRpcClient({
62
+ cliPath: opts.cliPath,
63
+ ...(opts.dbPath ? { dbPath: opts.dbPath } : {}),
64
+ onNotification: opts.onNotification,
65
+ runtime: opts.runtime,
66
+ }));
67
+ // Rolling per-conversation history buffer (untagged group-message context).
68
+ const history = new IMessageHistoryBuffer();
69
+ let client = null;
70
+ let connected = false;
71
+ let connectedAtMs = null;
72
+ let closed = false;
73
+ let attempt = 0;
74
+ // Resolve the remote host once: explicit config wins; else auto-detect from an
75
+ // SSH-wrapper `cliPath`. Only a safety-validated host is accepted (so it can
76
+ // never inject an option/arg into the SCP command). Empty ⇒ same-host setup.
77
+ let remoteHost = normalizeScpRemoteHost(account.remoteHost);
78
+ if (account.remoteHost && !remoteHost) {
79
+ args.log("imessage: ignoring unsafe channels.imessage.remoteHost value");
80
+ }
81
+ if (!remoteHost && account.cliPath && account.cliPath !== "imsg") {
82
+ const detected = await detectRemoteHostFromCliPath(account.cliPath, ...(args.readFileImpl ? [args.readFileImpl] : []));
83
+ const normalizedDetected = normalizeScpRemoteHost(detected);
84
+ if (detected && !normalizedDetected) {
85
+ args.log("imessage: ignoring unsafe auto-detected remoteHost from cliPath");
86
+ }
87
+ remoteHost = normalizedDetected;
88
+ if (remoteHost && account.verbose)
89
+ args.log(`imessage: detected remoteHost=${remoteHost} from cliPath`);
90
+ }
91
+ const handleNotification = (msg) => {
92
+ // Wrap the whole handler so a synchronous throw (malformed payload, a
93
+ // decideInbound bug, a downstream onMessage error) can NEVER escape into the
94
+ // RPC client's notification loop and wedge the watch / crash the gateway.
95
+ // The transport keeps reading; a single bad notification is logged + dropped.
96
+ try {
97
+ if (msg.method === "error") {
98
+ // Sanitize before logging — the payload is attacker-influenced (a
99
+ // crafted row / remote bridge could smuggle ANSI escapes or a huge
100
+ // blob). Keep only a finite code + a stripped/truncated message.
101
+ args.log("imessage watch error", { error: sanitizeIMessageWatchErrorPayload(msg.params) });
102
+ return;
103
+ }
104
+ if (msg.method !== "message")
105
+ return;
106
+ const payload = parseIMessageNotification(msg.params);
107
+ if (!payload) {
108
+ args.log("dropping malformed iMessage payload");
109
+ return;
110
+ }
111
+ // `selfHandle` lets a group message naming the bot populate `mentions[]`
112
+ // so the central group requireMention gate can fire.
113
+ const decision = decideInbound(state, account.accountId, payload, account.selfHandle);
114
+ if (decision.kind === "drop") {
115
+ if (account.verbose)
116
+ args.log(`inbound dropped: ${decision.reason}`);
117
+ return;
118
+ }
119
+ const normalized = decision.message;
120
+ // Rolling-history context: for an UNTAGGED group message (no self-mention,
121
+ // not a reply) attach the last N seen messages as a fenced context block,
122
+ // then record THIS message for the next turn. iMessage's `imsg rpc`
123
+ // transport exposes no history method, so this is a pure in-memory buffer
124
+ // of messages the monitor has already seen (mirrors the upstream monitor).
125
+ const isUntaggedGroup = normalized.isGroup && (!normalized.mentions || normalized.mentions.length === 0) && !normalized.replyTo;
126
+ if (account.historyLimit > 0 && isUntaggedGroup && normalized.text.trim()) {
127
+ const entries = history.recent(normalized.conversationId, account.historyLimit);
128
+ const block = renderIMessageHistoryBlock(entries);
129
+ if (block)
130
+ normalized.historyContext = block;
131
+ }
132
+ if (normalized.isGroup) {
133
+ history.record(normalized.conversationId, {
134
+ sender: normalized.fromName || normalized.from || "Unknown",
135
+ body: normalized.text,
136
+ });
137
+ }
138
+ // Deferred media — resolve only after the central access gate admits the
139
+ // sender (the bridge has already saved the bytes to disk; we just map them).
140
+ const inbound = { ...normalized };
141
+ // `includeAttachments:false` opts the account out of inbound media entirely.
142
+ if (account.includeAttachments && Array.isArray(payload.attachments) && payload.attachments.length > 0) {
143
+ const atts = payload.attachments;
144
+ inbound.resolveMedia = remoteHost
145
+ ? async () => {
146
+ const remoteRoots = resolveIMessageRemoteAttachmentRoots(args.loadConfig(), account.accountId);
147
+ return resolveInboundAttachmentsRemote(atts, {
148
+ remoteHost: remoteHost,
149
+ remoteRoots,
150
+ ...(args.scpRunner ? { scpRunner: args.scpRunner } : {}),
151
+ ...(args.mkdtempImpl ? { mkdtempImpl: args.mkdtempImpl } : {}),
152
+ log: (m) => args.log(m),
153
+ });
154
+ }
155
+ : async () => {
156
+ const roots = resolveIMessageAttachmentRoots(args.loadConfig(), account.accountId);
157
+ return resolveInboundAttachments(atts, roots);
158
+ };
159
+ }
160
+ args.onMessage(inbound);
161
+ }
162
+ catch (err) {
163
+ args.log("imessage notification handler threw (dropped, loop continues)", {
164
+ error: err instanceof Error ? err.message : String(err),
165
+ });
166
+ }
167
+ };
168
+ /** Build a client + issue one `watch.subscribe`. Throws on failure (client torn down). */
169
+ const subscribeAttempt = async () => {
170
+ const c = await clientFactory({
171
+ cliPath: account.cliPath,
172
+ ...(account.dbPath ? { dbPath: account.dbPath } : {}),
173
+ onNotification: handleNotification,
174
+ runtime: {
175
+ error: (m) => args.log(m),
176
+ info: (m) => account.verbose && args.log(m),
177
+ },
178
+ });
179
+ try {
180
+ await c.request("watch.subscribe", { attachments: account.includeAttachments }, { timeoutMs: account.probeTimeoutMs });
181
+ }
182
+ catch (err) {
183
+ // Tear down the failed client before rethrowing so a slow subscribe
184
+ // can't keep emitting notifications into the next attempt's window.
185
+ try {
186
+ await c.stop();
187
+ }
188
+ catch {
189
+ /* best-effort */
190
+ }
191
+ throw err;
192
+ }
193
+ return c;
194
+ };
195
+ /**
196
+ * Subscribe with a short 3× startup retry (≈1s apart, tearing the client down
197
+ * between attempts) on transient startup errors, BEFORE the slow reconnect
198
+ * backoff loop takes over. A cold `imsg` bridge often fails the very first
199
+ * subscribe; this rides over it without waiting the full backoff.
200
+ */
201
+ const subscribeOnce = async () => {
202
+ let lastErr;
203
+ for (let i = 1; i <= WATCH_SUBSCRIBE_MAX_ATTEMPTS; i++) {
204
+ if (closed || args.signal?.aborted)
205
+ return;
206
+ try {
207
+ client = await subscribeAttempt();
208
+ connected = true;
209
+ connectedAtMs = Date.now();
210
+ attempt = 0;
211
+ args.onConnected?.();
212
+ return;
213
+ }
214
+ catch (err) {
215
+ lastErr = err;
216
+ const canRetry = i < WATCH_SUBSCRIBE_MAX_ATTEMPTS && isRetriableSubscribeStartupError(err);
217
+ if (!canRetry)
218
+ throw err;
219
+ args.log(`imessage: watch.subscribe startup failed (attempt ${i}/${WATCH_SUBSCRIBE_MAX_ATTEMPTS}): ${err instanceof Error ? err.message : String(err)}; retrying`);
220
+ await sleep(WATCH_SUBSCRIBE_RETRY_DELAY_MS);
221
+ }
222
+ }
223
+ throw lastErr instanceof Error ? lastErr : new Error(String(lastErr));
224
+ };
225
+ /**
226
+ * Poll `probeIMessage` until the `imsg` bridge is reachable (or the timeout
227
+ * elapses), so a cold bridge surfaces as a "waiting for transport" log rather
228
+ * than an immediate connect failure. A FATAL probe (old binary) is rethrown.
229
+ * Returns true when ready, false on timeout / abort.
230
+ */
231
+ const waitForTransportReady = async () => {
232
+ const started = Date.now();
233
+ let nextLogAt = started + TRANSPORT_READY_LOG_INTERVAL_MS;
234
+ while (!closed && !args.signal?.aborted) {
235
+ let result;
236
+ try {
237
+ result = await probe({
238
+ cliPath: account.cliPath,
239
+ ...(account.dbPath ? { dbPath: account.dbPath } : {}),
240
+ timeoutMs: account.probeTimeoutMs,
241
+ });
242
+ }
243
+ catch (err) {
244
+ result = { ok: false, error: err instanceof Error ? err.message : String(err), elapsedMs: 0 };
245
+ }
246
+ if (result.ok)
247
+ return true;
248
+ if (result.fatal)
249
+ throw new Error(result.error ?? "imsg rpc unavailable");
250
+ const now = Date.now();
251
+ if (now - started >= TRANSPORT_READY_TIMEOUT_MS)
252
+ return false;
253
+ if (now >= nextLogAt) {
254
+ args.log(`imessage: waiting for transport (imsg bridge not ready: ${result.error ?? "unreachable"})`);
255
+ nextLogAt = now + TRANSPORT_READY_LOG_INTERVAL_MS;
256
+ }
257
+ await sleep(TRANSPORT_READY_POLL_INTERVAL_MS);
258
+ }
259
+ return false;
260
+ };
261
+ /** Background supervise loop — reconnect with jittered backoff until closed. */
262
+ const supervise = async () => {
263
+ while (!closed && !args.signal?.aborted) {
264
+ try {
265
+ if (!connected)
266
+ await subscribeOnce();
267
+ // Block on the client closing; on close, fall through to reconnect.
268
+ await client?.waitForClose();
269
+ }
270
+ catch (err) {
271
+ args.log("imessage connect attempt failed", { error: err instanceof Error ? err.message : String(err) });
272
+ }
273
+ connected = false;
274
+ try {
275
+ await client?.stop();
276
+ }
277
+ catch {
278
+ /* best-effort */
279
+ }
280
+ client = null;
281
+ if (closed || args.signal?.aborted)
282
+ break;
283
+ attempt += 1;
284
+ if (attempt > RECONNECT_MAX_ATTEMPTS) {
285
+ args.onClosed?.(`gave up after ${RECONNECT_MAX_ATTEMPTS} reconnect attempts`);
286
+ break;
287
+ }
288
+ const delay = nextBackoffDelay({
289
+ attempt,
290
+ initialMs: RECONNECT_INITIAL_MS,
291
+ maxMs: RECONNECT_MAX_MS,
292
+ factor: RECONNECT_FACTOR,
293
+ jitter: RECONNECT_JITTER,
294
+ });
295
+ await sleep(delay);
296
+ }
297
+ };
298
+ // First connect — gate on transport readiness (a cold `imsg` bridge logs
299
+ // "waiting for transport" instead of failing immediately), then subscribe.
300
+ // Surface a failure to the caller; keep the loop running after.
301
+ await waitForTransportReady();
302
+ await subscribeOnce();
303
+ void supervise();
304
+ if (args.signal) {
305
+ if (args.signal.aborted)
306
+ closed = true;
307
+ else
308
+ args.signal.addEventListener("abort", () => void close(), { once: true });
309
+ }
310
+ const remember = (conversationId, sent) => {
311
+ // Build the same scope the inbound poll keys on so the echo is suppressed.
312
+ const numericChat = conversationId.startsWith("chat:") ? Number.parseInt(conversationId.slice(5), 10) : NaN;
313
+ const scope = Number.isFinite(numericChat)
314
+ ? echoScope(account.accountId, { chat_id: numericChat })
315
+ : `${account.accountId}:imessage:${conversationId}`;
316
+ state.sentMessageCache.remember(scope, { text: sent.sentText, messageId: sent.messageId });
317
+ };
318
+ async function close() {
319
+ if (closed)
320
+ return;
321
+ closed = true;
322
+ try {
323
+ await client?.stop();
324
+ }
325
+ catch {
326
+ /* best-effort */
327
+ }
328
+ client = null;
329
+ connected = false;
330
+ }
331
+ return {
332
+ isConnected: () => connected,
333
+ connectedAt: () => connectedAtMs,
334
+ async sendText(conversationId, text, opts) {
335
+ const result = await sendFn(conversationId, text, {
336
+ cliPath: account.cliPath,
337
+ ...(account.dbPath ? { dbPath: account.dbPath } : {}),
338
+ service: account.service,
339
+ region: account.region,
340
+ maxBytes: account.mediaMaxBytes,
341
+ timeoutMs: account.probeTimeoutMs,
342
+ ...(client ? { client } : {}),
343
+ ...(opts?.replyToId ? { replyToId: opts.replyToId } : {}),
344
+ });
345
+ remember(conversationId, result);
346
+ return result.messageId ? { messageId: result.messageId } : {};
347
+ },
348
+ async sendMedia(conversationId, media) {
349
+ const result = await sendFn(conversationId, media.caption ?? "", {
350
+ cliPath: account.cliPath,
351
+ ...(account.dbPath ? { dbPath: account.dbPath } : {}),
352
+ service: account.service,
353
+ region: account.region,
354
+ maxBytes: account.mediaMaxBytes,
355
+ timeoutMs: account.probeTimeoutMs,
356
+ mediaPath: media.path,
357
+ mediaKind: inferOutboundMediaKind(media),
358
+ ...(client ? { client } : {}),
359
+ });
360
+ remember(conversationId, result);
361
+ return result.messageId ? { messageId: result.messageId } : {};
362
+ },
363
+ close,
364
+ };
365
+ }
366
+ export { normalizeIMessageMessage };
367
+ //# sourceMappingURL=connection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connection.js","sourceRoot":"","sources":["../../../../src/agents/channels/imessage/connection.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * iMessage outbound formatting helpers.
3
+ *
4
+ * iMessage has NO rich markup — a message is plain text. So unlike Telegram
5
+ * (HTML) or Discord (CommonMark), the only transform we need is to make markdown
6
+ * READABLE as plain text:
7
+ * - a markdown pipe-table is flattened to `cell | cell` lines (the LLM emits
8
+ * tables and an un-flattened one renders as raw `| --- |` noise);
9
+ * - everything else passes through untouched (bold `**x**`, links `[a](b)` —
10
+ * iMessage shows the literal characters, which is the honest fallback).
11
+ *
12
+ * Plus two send-path utilities ported from the upstream `send.ts`:
13
+ * - `sanitizeReplyToId` — scrub a reply-to id of control chars / brackets so it
14
+ * can't break the bridge's tag parsing, capped at 256 chars;
15
+ * - `resolveDeliveredText` — when an outbound has media but no text, deliver a
16
+ * `<media:kind>` placeholder so the echo cache + transcript have a body.
17
+ */
18
+ /**
19
+ * Convert agent-style markdown to iMessage-friendly plain text. The only
20
+ * load-bearing transform is flattening pipe tables; all other markdown passes
21
+ * through verbatim (iMessage renders the literal characters).
22
+ */
23
+ export declare function markdownToIMessageText(markdown: string): string;
24
+ /**
25
+ * Sanitize an outbound reply-to id: trim, strip unsafe chars, cap at 256 chars.
26
+ * Returns undefined when nothing usable remains.
27
+ */
28
+ export declare function sanitizeReplyToId(raw?: string): string | undefined;
29
+ /**
30
+ * Strip Brigade-internal scaffolding from outbound text before it hits the wire.
31
+ * Returns the cleaned text; if stripping leaves nothing, returns the trimmed
32
+ * original (better to send something than confuse the recipient with silence).
33
+ */
34
+ export declare function sanitizeOutboundIMessageText(text: string): string;
35
+ /** Outbound media kind → the placeholder text used when the message has no body. */
36
+ export type IMessageMediaKind = OutboundMediaKind;
37
+ type OutboundMediaKind = "image" | "video" | "audio" | "voice" | "document" | "sticker";
38
+ /**
39
+ * When an outbound carries media but no text, deliver a `<media:kind>`
40
+ * placeholder so the echo cache + transcript have a body to key on. Returns the
41
+ * text unchanged when it's non-empty.
42
+ */
43
+ export declare function resolveDeliveredText(text: string, mediaKind?: OutboundMediaKind): string;
44
+ export {};
45
+ //# sourceMappingURL=format.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../../../../src/agents/channels/imessage/format.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AA+BH;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAiB/D;AAcD;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAOlE;AA8CD;;;;GAIG;AACH,wBAAgB,4BAA4B,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAYjE;AAED,oFAAoF;AACpF,MAAM,MAAM,iBAAiB,GAAG,iBAAiB,CAAC;AAClD,KAAK,iBAAiB,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,UAAU,GAAG,SAAS,CAAC;AAExF;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,iBAAiB,GAAG,MAAM,CAIxF"}