@hraness/ghostget 0.17.2

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 (500) hide show
  1. package/CHANGELOG.md +458 -0
  2. package/LICENSE +21 -0
  3. package/README.md +1359 -0
  4. package/bunfig.toml +2 -0
  5. package/dist/apple-photos-client.js +704 -0
  6. package/dist/beeper-client.js +4602 -0
  7. package/dist/client.js +1605 -0
  8. package/dist/index-26yq8q16.js +31 -0
  9. package/dist/index-9t13b4k7.js +508 -0
  10. package/dist/index-axwm9b3v.js +5 -0
  11. package/dist/index-gwk7rbyj.js +30 -0
  12. package/dist/index.js +701 -0
  13. package/dist/messaging.js +1130 -0
  14. package/dist/omni-client.js +1406 -0
  15. package/dist/whatsapp-client.js +355 -0
  16. package/docs/imessage-direct-provider.md +106 -0
  17. package/docs/rental-listings.md +94 -0
  18. package/package.json +600 -0
  19. package/skills/ghostget/SKILL.md +251 -0
  20. package/skills/ghostget/agents/openai.yaml +4 -0
  21. package/skills/ghostget/references/adapter-contract.md +181 -0
  22. package/skills/ghostget/references/apple-photos.md +115 -0
  23. package/skills/ghostget/references/article-drafts.md +235 -0
  24. package/skills/ghostget/references/code-owned-provider-scaffold.md +134 -0
  25. package/skills/ghostget/references/cross-posting-video.md +139 -0
  26. package/skills/ghostget/references/cross-posting.md +82 -0
  27. package/skills/ghostget/references/derivation.md +390 -0
  28. package/skills/ghostget/references/hraness-social-profile-stats.json +269 -0
  29. package/skills/ghostget/references/install.md +66 -0
  30. package/skills/ghostget/references/linkedin-adapter.md +442 -0
  31. package/skills/ghostget/references/messaging.md +168 -0
  32. package/skills/ghostget/references/meta-comet-contract.md +153 -0
  33. package/skills/ghostget/references/platform-patterns.md +122 -0
  34. package/skills/ghostget/references/provider-plugins.md +496 -0
  35. package/skills/ghostget/references/reddit-flair.md +78 -0
  36. package/skills/ghostget/references/safety-and-state.md +214 -0
  37. package/skills/ghostget/references/settlement-and-duplicate-cleanup.md +79 -0
  38. package/skills/ghostget/references/social-platform-routing.md +66 -0
  39. package/skills/ghostget/references/social-profile-stats.md +195 -0
  40. package/skills/ghostget/references/social-video-platform-routing.md +89 -0
  41. package/skills/ghostget/references/whatsapp-adapter.md +101 -0
  42. package/skills/ghostget/references/x-adapter.md +332 -0
  43. package/skills/ghostget/references/x-ai-disclosure.md +71 -0
  44. package/src/apple-photos-cli.ts +639 -0
  45. package/src/apple-photos-client-types.ts +168 -0
  46. package/src/apple-photos-client.ts +201 -0
  47. package/src/apple-photos-contact-evidence.ts +838 -0
  48. package/src/apple-photos-local-source.ts +1131 -0
  49. package/src/args.ts +2053 -0
  50. package/src/article-draft-document.ts +417 -0
  51. package/src/article-draft-embeds.ts +123 -0
  52. package/src/article-draft-images.ts +214 -0
  53. package/src/assets/adapter-template/wrench-adapter.json +40 -0
  54. package/src/assets/adapters/beeper/wrench-web-adapter.json +1500 -0
  55. package/src/assets/adapters/beeper/wrench-web-adapter.v1.0.0.json +129 -0
  56. package/src/assets/adapters/beeper/wrench-web-adapter.v1.1.0.json +207 -0
  57. package/src/assets/adapters/beeper/wrench-web-adapter.v2.0.0.json +1463 -0
  58. package/src/assets/adapters/beeper/wrench-web-adapter.v2.1.0.json +1463 -0
  59. package/src/assets/adapters/beeper/wrench-web-adapter.v2.2.0.json +1475 -0
  60. package/src/assets/adapters/beeper/wrench-web-adapter.v2.3.0.json +1488 -0
  61. package/src/assets/adapters/bluesky/wrench-web-adapter.json +684 -0
  62. package/src/assets/adapters/bluesky/wrench-web-adapter.v1.0.0.json +581 -0
  63. package/src/assets/adapters/bluesky/wrench-web-adapter.v1.1.0.json +581 -0
  64. package/src/assets/adapters/bluesky/wrench-web-adapter.v1.2.0.json +581 -0
  65. package/src/assets/adapters/bluesky/wrench-web-adapter.v1.3.0.json +615 -0
  66. package/src/assets/adapters/bluesky/wrench-web-adapter.v1.4.0.json +684 -0
  67. package/src/assets/adapters/bluesky/wrench-web-adapter.v1.5.0.json +684 -0
  68. package/src/assets/adapters/bluesky/wrench-web-adapter.v1.6.0.json +684 -0
  69. package/src/assets/adapters/clasificados/wrench-web-adapter.json +54 -0
  70. package/src/assets/adapters/facebook/wrench-web-adapter.json +750 -0
  71. package/src/assets/adapters/facebook/wrench-web-adapter.v1.0.0.json +706 -0
  72. package/src/assets/adapters/facebook/wrench-web-adapter.v1.1.0.json +703 -0
  73. package/src/assets/adapters/facebook/wrench-web-adapter.v1.2.0.json +750 -0
  74. package/src/assets/adapters/facebook-group/wrench-web-adapter.json +682 -0
  75. package/src/assets/adapters/facebook-group/wrench-web-adapter.v1.0.0.json +583 -0
  76. package/src/assets/adapters/facebook-group/wrench-web-adapter.v1.1.0.json +682 -0
  77. package/src/assets/adapters/facebook-marketplace/wrench-web-adapter.json +437 -0
  78. package/src/assets/adapters/facebook-marketplace/wrench-web-adapter.v1.0.0.json +383 -0
  79. package/src/assets/adapters/facebook-marketplace/wrench-web-adapter.v1.1.0.json +437 -0
  80. package/src/assets/adapters/facebook-marketplace/wrench-web-adapter.v1.1.1.json +437 -0
  81. package/src/assets/adapters/facebook-page/wrench-web-adapter.json +880 -0
  82. package/src/assets/adapters/facebook-page/wrench-web-adapter.v1.0.0.json +740 -0
  83. package/src/assets/adapters/facebook-page/wrench-web-adapter.v1.1.0.json +880 -0
  84. package/src/assets/adapters/github/wrench-web-adapter.json +69 -0
  85. package/src/assets/adapters/github/wrench-web-adapter.v1.0.0.json +42 -0
  86. package/src/assets/adapters/github/wrench-web-adapter.v1.1.0.json +69 -0
  87. package/src/assets/adapters/gmail/wrench-adapter.json +161 -0
  88. package/src/assets/adapters/gmail/wrench-adapter.v1.2.0.json +157 -0
  89. package/src/assets/adapters/hacker-news/wrench-web-adapter.json +315 -0
  90. package/src/assets/adapters/hacker-news/wrench-web-adapter.v1.0.0.json +315 -0
  91. package/src/assets/adapters/imessage/wrench-web-adapter.json +236 -0
  92. package/src/assets/adapters/instagram/wrench-web-adapter.json +719 -0
  93. package/src/assets/adapters/instagram/wrench-web-adapter.v1.0.0.json +627 -0
  94. package/src/assets/adapters/instagram/wrench-web-adapter.v1.1.0.json +609 -0
  95. package/src/assets/adapters/instagram/wrench-web-adapter.v1.2.0.json +640 -0
  96. package/src/assets/adapters/instagram/wrench-web-adapter.v1.3.0.json +671 -0
  97. package/src/assets/adapters/instagram/wrench-web-adapter.v1.4.0.json +710 -0
  98. package/src/assets/adapters/instagram/wrench-web-adapter.v1.5.0.json +710 -0
  99. package/src/assets/adapters/instagram/wrench-web-adapter.v1.6.0.json +719 -0
  100. package/src/assets/adapters/instagram/wrench-web-adapter.v1.7.0.json +719 -0
  101. package/src/assets/adapters/linkedin/wrench-adapter.json +442 -0
  102. package/src/assets/adapters/linkedin/wrench-adapter.v0.4.0.json +124 -0
  103. package/src/assets/adapters/linkedin/wrench-adapter.v1.0.0.json +411 -0
  104. package/src/assets/adapters/linkedin/wrench-web-adapter.json +914 -0
  105. package/src/assets/adapters/linkedin/wrench-web-adapter.v1.0.0.json +604 -0
  106. package/src/assets/adapters/linkedin/wrench-web-adapter.v1.1.0.json +604 -0
  107. package/src/assets/adapters/linkedin/wrench-web-adapter.v1.10.0.json +809 -0
  108. package/src/assets/adapters/linkedin/wrench-web-adapter.v1.11.0.json +809 -0
  109. package/src/assets/adapters/linkedin/wrench-web-adapter.v1.12.0.json +820 -0
  110. package/src/assets/adapters/linkedin/wrench-web-adapter.v1.13.0.json +819 -0
  111. package/src/assets/adapters/linkedin/wrench-web-adapter.v1.14.0.json +819 -0
  112. package/src/assets/adapters/linkedin/wrench-web-adapter.v1.15.0.json +819 -0
  113. package/src/assets/adapters/linkedin/wrench-web-adapter.v1.16.0.json +874 -0
  114. package/src/assets/adapters/linkedin/wrench-web-adapter.v1.17.0.json +874 -0
  115. package/src/assets/adapters/linkedin/wrench-web-adapter.v1.18.0.json +874 -0
  116. package/src/assets/adapters/linkedin/wrench-web-adapter.v1.19.0.json +874 -0
  117. package/src/assets/adapters/linkedin/wrench-web-adapter.v1.2.0.json +731 -0
  118. package/src/assets/adapters/linkedin/wrench-web-adapter.v1.3.0.json +768 -0
  119. package/src/assets/adapters/linkedin/wrench-web-adapter.v1.4.0.json +808 -0
  120. package/src/assets/adapters/linkedin/wrench-web-adapter.v1.5.0.json +808 -0
  121. package/src/assets/adapters/linkedin/wrench-web-adapter.v1.6.0.json +808 -0
  122. package/src/assets/adapters/linkedin/wrench-web-adapter.v1.7.0.json +825 -0
  123. package/src/assets/adapters/linkedin/wrench-web-adapter.v1.8.0.json +792 -0
  124. package/src/assets/adapters/linkedin/wrench-web-adapter.v1.9.0.json +809 -0
  125. package/src/assets/adapters/reddit/wrench-web-adapter.json +855 -0
  126. package/src/assets/adapters/reddit/wrench-web-adapter.v1.0.0.json +577 -0
  127. package/src/assets/adapters/reddit/wrench-web-adapter.v1.1.0.json +604 -0
  128. package/src/assets/adapters/reddit/wrench-web-adapter.v1.10.0.json +712 -0
  129. package/src/assets/adapters/reddit/wrench-web-adapter.v1.11.0.json +712 -0
  130. package/src/assets/adapters/reddit/wrench-web-adapter.v1.12.0.json +712 -0
  131. package/src/assets/adapters/reddit/wrench-web-adapter.v1.2.0.json +653 -0
  132. package/src/assets/adapters/reddit/wrench-web-adapter.v1.3.0.json +712 -0
  133. package/src/assets/adapters/reddit/wrench-web-adapter.v1.4.0.json +713 -0
  134. package/src/assets/adapters/reddit/wrench-web-adapter.v1.5.0.json +712 -0
  135. package/src/assets/adapters/reddit/wrench-web-adapter.v1.6.0.json +713 -0
  136. package/src/assets/adapters/reddit/wrench-web-adapter.v1.7.0.json +713 -0
  137. package/src/assets/adapters/reddit/wrench-web-adapter.v1.8.0.json +713 -0
  138. package/src/assets/adapters/reddit/wrench-web-adapter.v1.9.0.json +713 -0
  139. package/src/assets/adapters/substack/wrench-web-adapter.json +936 -0
  140. package/src/assets/adapters/substack/wrench-web-adapter.v1.0.0.json +817 -0
  141. package/src/assets/adapters/substack/wrench-web-adapter.v1.1.0.json +812 -0
  142. package/src/assets/adapters/substack/wrench-web-adapter.v1.2.0.json +812 -0
  143. package/src/assets/adapters/substack/wrench-web-adapter.v1.3.0.json +902 -0
  144. package/src/assets/adapters/substack/wrench-web-adapter.v1.4.0.json +936 -0
  145. package/src/assets/adapters/substack/wrench-web-adapter.v1.5.0.json +936 -0
  146. package/src/assets/adapters/substack/wrench-web-adapter.v1.6.0.json +936 -0
  147. package/src/assets/adapters/threads/wrench-web-adapter.json +692 -0
  148. package/src/assets/adapters/threads/wrench-web-adapter.v1.0.0.json +629 -0
  149. package/src/assets/adapters/threads/wrench-web-adapter.v1.1.0.json +623 -0
  150. package/src/assets/adapters/threads/wrench-web-adapter.v1.2.0.json +622 -0
  151. package/src/assets/adapters/threads/wrench-web-adapter.v1.3.0.json +622 -0
  152. package/src/assets/adapters/threads/wrench-web-adapter.v1.4.0.json +622 -0
  153. package/src/assets/adapters/threads/wrench-web-adapter.v1.5.0.json +699 -0
  154. package/src/assets/adapters/threads/wrench-web-adapter.v1.6.0.json +693 -0
  155. package/src/assets/adapters/threads/wrench-web-adapter.v1.7.0.json +692 -0
  156. package/src/assets/adapters/tiktok/wrench-web-adapter.json +762 -0
  157. package/src/assets/adapters/tiktok/wrench-web-adapter.v1.0.0.json +681 -0
  158. package/src/assets/adapters/tiktok/wrench-web-adapter.v1.1.0.json +708 -0
  159. package/src/assets/adapters/tiktok/wrench-web-adapter.v1.2.0.json +762 -0
  160. package/src/assets/adapters/tiktok/wrench-web-adapter.v1.3.0.json +762 -0
  161. package/src/assets/adapters/twitch/wrench-web-adapter.json +42 -0
  162. package/src/assets/adapters/twitch/wrench-web-adapter.v1.0.0.json +42 -0
  163. package/src/assets/adapters/whatsapp/wrench-web-adapter.json +400 -0
  164. package/src/assets/adapters/whatsapp/wrench-web-adapter.v1.0.0.json +355 -0
  165. package/src/assets/adapters/whatsapp/wrench-web-adapter.v1.1.0.json +386 -0
  166. package/src/assets/adapters/whatsapp/wrench-web-adapter.v1.2.0.json +386 -0
  167. package/src/assets/adapters/whatsapp/wrench-web-adapter.v1.3.0.json +400 -0
  168. package/src/assets/adapters/x/wrench-adapter.json +749 -0
  169. package/src/assets/adapters/x/wrench-adapter.v1.0.0.json +700 -0
  170. package/src/assets/adapters/x/wrench-adapter.v1.1.0.json +707 -0
  171. package/src/assets/adapters/x/wrench-web-adapter.json +712 -0
  172. package/src/assets/adapters/x/wrench-web-adapter.v1.1.0.json +579 -0
  173. package/src/assets/adapters/x/wrench-web-adapter.v1.10.0.json +685 -0
  174. package/src/assets/adapters/x/wrench-web-adapter.v1.11.0.json +712 -0
  175. package/src/assets/adapters/x/wrench-web-adapter.v1.12.0.json +712 -0
  176. package/src/assets/adapters/x/wrench-web-adapter.v1.13.0.json +712 -0
  177. package/src/assets/adapters/x/wrench-web-adapter.v1.2.0.json +578 -0
  178. package/src/assets/adapters/x/wrench-web-adapter.v1.3.0.json +610 -0
  179. package/src/assets/adapters/x/wrench-web-adapter.v1.4.0.json +617 -0
  180. package/src/assets/adapters/x/wrench-web-adapter.v1.5.0.json +634 -0
  181. package/src/assets/adapters/x/wrench-web-adapter.v1.6.0.json +632 -0
  182. package/src/assets/adapters/x/wrench-web-adapter.v1.7.0.json +649 -0
  183. package/src/assets/adapters/x/wrench-web-adapter.v1.8.0.json +649 -0
  184. package/src/assets/adapters/x/wrench-web-adapter.v1.9.0.json +683 -0
  185. package/src/assets/adapters/youtube/wrench-web-adapter.json +561 -0
  186. package/src/assets/adapters/youtube/wrench-web-adapter.v1.0.0.json +465 -0
  187. package/src/assets/adapters/youtube/wrench-web-adapter.v1.1.0.json +519 -0
  188. package/src/assets/adapters/youtube/wrench-web-adapter.v1.2.0.json +561 -0
  189. package/src/assets/adapters/youtube/wrench-web-adapter.v1.3.0.json +561 -0
  190. package/src/assets/code-owned-provider-template/plugin.test.ts.template +54 -0
  191. package/src/assets/code-owned-provider-template/plugin.ts.template +102 -0
  192. package/src/assets/code-owned-provider-template/runtime.internal.test.ts.template +44 -0
  193. package/src/assets/code-owned-provider-template/runtime.ts.template +59 -0
  194. package/src/assets/code-owned-provider-template/wrench-adapter.json.template +33 -0
  195. package/src/assets/fonts/nebula-sans/LICENSE.txt +96 -0
  196. package/src/assets/fonts/nebula-sans/NebulaSans-Book.woff2 +0 -0
  197. package/src/assets/fonts/nebula-sans/PROVENANCE.md +14 -0
  198. package/src/assets.d.ts +4 -0
  199. package/src/auth.ts +1157 -0
  200. package/src/beeper-client-types.ts +169 -0
  201. package/src/beeper-client.ts +250 -0
  202. package/src/beeper-contact-interactions-cli.ts +180 -0
  203. package/src/beeper-contact-interactions.ts +1612 -0
  204. package/src/beeper-message-bundle-v1.ts +257 -0
  205. package/src/beeper-message-like-me-cli.ts +84 -0
  206. package/src/beeper-message-like-me-export.ts +2274 -0
  207. package/src/beeper-message-like-me-recovery.ts +931 -0
  208. package/src/beeper-message-like-me-source.ts +4034 -0
  209. package/src/browser-admission.ts +928 -0
  210. package/src/browser-snapshots.ts +260 -0
  211. package/src/browser.ts +3873 -0
  212. package/src/canonical-json.ts +60 -0
  213. package/src/catalog-cli.ts +638 -0
  214. package/src/cli.ts +208 -0
  215. package/src/client-types.ts +301 -0
  216. package/src/client.ts +2726 -0
  217. package/src/confirmed-write-failure.ts +44 -0
  218. package/src/confirmed-write-model.ts +72 -0
  219. package/src/confirmed-write-platform.ts +1055 -0
  220. package/src/confirmed-write-program.ts +224 -0
  221. package/src/confirmed-write-runtime.ts +16 -0
  222. package/src/cursor-token.ts +228 -0
  223. package/src/derivation-dnr-readiness.ts +367 -0
  224. package/src/derivation-file-chooser.ts +384 -0
  225. package/src/derivation-network-boundary.ts +835 -0
  226. package/src/derivation-network-guard.ts +782 -0
  227. package/src/derivation-network-proxy-helper.ts +440 -0
  228. package/src/derivation-network-proxy.ts +385 -0
  229. package/src/derive-command-helper.ts +693 -0
  230. package/src/derive-fixtures.ts +343 -0
  231. package/src/derive-review.ts +980 -0
  232. package/src/derive.ts +4754 -0
  233. package/src/fixtures/beeper-message-like-me-v1/accounts.ndjson +2 -0
  234. package/src/fixtures/beeper-message-like-me-v1/conversations.ndjson +1 -0
  235. package/src/fixtures/beeper-message-like-me-v1/manifest.json +1 -0
  236. package/src/fixtures/beeper-message-like-me-v1/messages.ndjson +2 -0
  237. package/src/fixtures/beeper-message-like-me-v1/participants.ndjson +3 -0
  238. package/src/fixtures/beeper-message-like-me-v1/reactions.ndjson +1 -0
  239. package/src/fixtures/beeper-message-like-me-v1/tombstones.ndjson +1 -0
  240. package/src/ghostget.ts +3672 -0
  241. package/src/gmail-capture.ts +1244 -0
  242. package/src/har-internal.ts +1242 -0
  243. package/src/har.ts +743 -0
  244. package/src/index.ts +218 -0
  245. package/src/invocation-read-platform.ts +55 -0
  246. package/src/invocation-read-program.ts +93 -0
  247. package/src/invocation-read-runtime.ts +11 -0
  248. package/src/linked-device-lifecycle-admission.ts +450 -0
  249. package/src/linked-device-lifecycle-journal.ts +1560 -0
  250. package/src/linked-device-lifecycle-runtime.ts +1602 -0
  251. package/src/local-cli-admission.ts +135 -0
  252. package/src/local-cli-contracts.ts +271 -0
  253. package/src/local-cli-execution.ts +98 -0
  254. package/src/local-cli-surface-contract.ts +1510 -0
  255. package/src/local-cli-tool-identity.ts +336 -0
  256. package/src/media/archive.ts +2325 -0
  257. package/src/media/args.ts +303 -0
  258. package/src/media/cli.ts +287 -0
  259. package/src/media/doctor.ts +475 -0
  260. package/src/media/ffmpeg.ts +1330 -0
  261. package/src/media/http-capture.ts +711 -0
  262. package/src/media/http-probe.ts +593 -0
  263. package/src/media/http.ts +387 -0
  264. package/src/media/index.ts +10 -0
  265. package/src/media/local-transcription.ts +613 -0
  266. package/src/media/lock.ts +321 -0
  267. package/src/media/manifest.ts +1712 -0
  268. package/src/media/metadata.ts +906 -0
  269. package/src/media/process.ts +723 -0
  270. package/src/media/revision.ts +166 -0
  271. package/src/media/runtime-closure.ts +1063 -0
  272. package/src/media/source-router.ts +187 -0
  273. package/src/media/transcriber-config.ts +1122 -0
  274. package/src/media/transcript-persistence-model.ts +15 -0
  275. package/src/media/transcript-persistence-platform.ts +89 -0
  276. package/src/media/transcript-persistence-program.ts +39 -0
  277. package/src/media/transcript-persistence-runtime.ts +24 -0
  278. package/src/media/transcript.ts +616 -0
  279. package/src/media/utf8-order.ts +30 -0
  280. package/src/media/whisper-cpp.ts +464 -0
  281. package/src/media/whisper-language.ts +58 -0
  282. package/src/media/yt-dlp.ts +439 -0
  283. package/src/message-like-me-agentic-messaging.ts +882 -0
  284. package/src/messaging-action-store.ts +793 -0
  285. package/src/messaging-runtime.ts +2136 -0
  286. package/src/messaging-store.ts +539 -0
  287. package/src/messaging-types.ts +1663 -0
  288. package/src/messaging.ts +334 -0
  289. package/src/model.ts +2671 -0
  290. package/src/oauth-google.ts +888 -0
  291. package/src/omni-client-types.ts +306 -0
  292. package/src/omni-client.ts +2225 -0
  293. package/src/omni-limits.ts +34 -0
  294. package/src/omni-model.ts +1614 -0
  295. package/src/omni-request.ts +379 -0
  296. package/src/omni-runtime.ts +1632 -0
  297. package/src/operation-deadline.ts +189 -0
  298. package/src/path-helper.ts +1656 -0
  299. package/src/pinned-https.ts +194 -0
  300. package/src/plan-assets.ts +832 -0
  301. package/src/platform-catalog.ts +1832 -0
  302. package/src/plugins/beeper-linked-device/plugin.ts +310 -0
  303. package/src/plugins/bluesky-web/plugin.ts +178 -0
  304. package/src/plugins/clasificados-web/plugin.ts +66 -0
  305. package/src/plugins/github-web/plugin.ts +80 -0
  306. package/src/plugins/gmail-official/plugin.ts +110 -0
  307. package/src/plugins/hacker-news-web/plugin.ts +52 -0
  308. package/src/plugins/imessage-direct/plugin.ts +195 -0
  309. package/src/plugins/imessage-direct/vendor/0001-fix-keep-AppleScript-send-payloads-out-of-child-argv.patch +1430 -0
  310. package/src/plugins/imessage-direct/vendor/0002-feat-rpc-add-exact-chat-lookup.patch +225 -0
  311. package/src/plugins/imessage-direct/vendor/provenance.json +80 -0
  312. package/src/plugins/linkedin-official/plugin.ts +84 -0
  313. package/src/plugins/linkedin-web/plugin.ts +412 -0
  314. package/src/plugins/meta-web/plugin.ts +317 -0
  315. package/src/plugins/reddit-web/flair.ts +492 -0
  316. package/src/plugins/reddit-web/plugin.ts +477 -0
  317. package/src/plugins/substack-web/plugin.ts +124 -0
  318. package/src/plugins/tiktok-web/plugin.ts +67 -0
  319. package/src/plugins/twitch-web/plugin.ts +54 -0
  320. package/src/plugins/whatsapp-linked-device/plugin.ts +105 -0
  321. package/src/plugins/x-official/plugin.ts +64 -0
  322. package/src/plugins/x-web/plugin.ts +488 -0
  323. package/src/plugins/youtube-web/plugin.ts +101 -0
  324. package/src/portable-run-recovery.ts +466 -0
  325. package/src/process-identity.ts +501 -0
  326. package/src/profile-clone-helper.ts +104 -0
  327. package/src/provider-catalog-views.ts +51 -0
  328. package/src/provider-context.ts +69 -0
  329. package/src/provider-contract-definitions-x.ts +45 -0
  330. package/src/provider-contract-definitions.ts +948 -0
  331. package/src/provider-contract-input-gmail.ts +176 -0
  332. package/src/provider-contract-input-linkedin.ts +77 -0
  333. package/src/provider-contract-input-x.ts +304 -0
  334. package/src/provider-contract-planning.ts +23 -0
  335. package/src/provider-contract-semantic-identity.ts +54 -0
  336. package/src/provider-contracts.ts +251 -0
  337. package/src/provider-http.ts +723 -0
  338. package/src/provider-plugin-auth.ts +36 -0
  339. package/src/provider-plugin-builtins.ts +229 -0
  340. package/src/provider-plugin-cleanup-barrier.ts +229 -0
  341. package/src/provider-plugin-cleanup-execution.ts +79 -0
  342. package/src/provider-plugin-cleanup-resource.ts +470 -0
  343. package/src/provider-plugin-contract-identity.ts +707 -0
  344. package/src/provider-plugin-host.ts +1972 -0
  345. package/src/provider-plugin-identifiers.ts +60 -0
  346. package/src/provider-plugin-invocation-lease.ts +889 -0
  347. package/src/provider-plugin-lifecycle-kernel.ts +566 -0
  348. package/src/provider-plugin-lifecycle.ts +1455 -0
  349. package/src/provider-plugin-module-analysis.ts +336 -0
  350. package/src/provider-plugin-package.ts +2530 -0
  351. package/src/provider-plugin-portable-authority.ts +106 -0
  352. package/src/provider-plugin-portable-catalog.ts +94 -0
  353. package/src/provider-plugin-portable-identity.ts +315 -0
  354. package/src/provider-plugin-portable-runtime.ts +2057 -0
  355. package/src/provider-plugin-protocol.ts +1625 -0
  356. package/src/provider-plugin-registry.ts +3342 -0
  357. package/src/provider-plugin-store.ts +2155 -0
  358. package/src/provider-plugin-test-fixture.ts +5 -0
  359. package/src/provider-plugin.ts +4907 -0
  360. package/src/provider-plugins.generated.ts +43 -0
  361. package/src/provider-plugins.ts +8 -0
  362. package/src/provider-subject.ts +41 -0
  363. package/src/provider.ts +315 -0
  364. package/src/providers/beeper-local-runtime.ts +5426 -0
  365. package/src/providers/beeper-local.ts +2739 -0
  366. package/src/providers/beeper-messaging.ts +462 -0
  367. package/src/providers/beeper-omni.ts +1159 -0
  368. package/src/providers/bluesky-web-runtime.ts +2895 -0
  369. package/src/providers/bluesky-web.ts +1614 -0
  370. package/src/providers/clasificados-web-runtime.ts +255 -0
  371. package/src/providers/clasificados-web.ts +503 -0
  372. package/src/providers/contact-projection.ts +301 -0
  373. package/src/providers/github-read-model.ts +94 -0
  374. package/src/providers/github-read-platform.ts +165 -0
  375. package/src/providers/github-read-program.ts +97 -0
  376. package/src/providers/github-web-runtime.ts +320 -0
  377. package/src/providers/github-web.ts +403 -0
  378. package/src/providers/gmail-api.ts +2834 -0
  379. package/src/providers/gmail-omni.ts +830 -0
  380. package/src/providers/gmail.ts +1130 -0
  381. package/src/providers/hacker-news-web-runtime.ts +220 -0
  382. package/src/providers/hacker-news-web.ts +809 -0
  383. package/src/providers/imessage-direct-install.ts +354 -0
  384. package/src/providers/imessage-direct-messaging.ts +532 -0
  385. package/src/providers/imessage-direct-omni.ts +400 -0
  386. package/src/providers/imessage-direct-runtime.ts +1498 -0
  387. package/src/providers/imessage-direct.ts +351 -0
  388. package/src/providers/instagram-video-foundations.ts +913 -0
  389. package/src/providers/instagram-web-profile-browser.ts +600 -0
  390. package/src/providers/iso-bmff.ts +338 -0
  391. package/src/providers/linkedin-company-platform.ts +42 -0
  392. package/src/providers/linkedin-company-program.ts +88 -0
  393. package/src/providers/linkedin-contact-failure.ts +84 -0
  394. package/src/providers/linkedin-contact-platform.ts +45 -0
  395. package/src/providers/linkedin-contact-program.ts +91 -0
  396. package/src/providers/linkedin-profile-activity-failure.ts +76 -0
  397. package/src/providers/linkedin-profile-activity-platform.ts +41 -0
  398. package/src/providers/linkedin-profile-activity-program.ts +67 -0
  399. package/src/providers/linkedin-read-failure.ts +52 -0
  400. package/src/providers/linkedin-self-platform.ts +53 -0
  401. package/src/providers/linkedin-self-program.ts +122 -0
  402. package/src/providers/linkedin-web-article-browser.ts +794 -0
  403. package/src/providers/linkedin-web-bootstrap.ts +146 -0
  404. package/src/providers/linkedin-web-contact.ts +830 -0
  405. package/src/providers/linkedin-web-feed-browser.ts +832 -0
  406. package/src/providers/linkedin-web-feed.ts +864 -0
  407. package/src/providers/linkedin-web-post-browser.ts +653 -0
  408. package/src/providers/linkedin-web-profile-browser.ts +683 -0
  409. package/src/providers/linkedin-web-runtime.ts +2388 -0
  410. package/src/providers/linkedin-web.ts +3305 -0
  411. package/src/providers/linkedin.ts +1885 -0
  412. package/src/providers/meta-bootstrap.ts +1043 -0
  413. package/src/providers/meta-facebook-group.ts +690 -0
  414. package/src/providers/meta-marketplace-relay.ts +747 -0
  415. package/src/providers/meta-omni.ts +373 -0
  416. package/src/providers/meta-relay-bundle.ts +1049 -0
  417. package/src/providers/meta-web-descriptors.ts +1740 -0
  418. package/src/providers/meta-web-runtime.ts +3388 -0
  419. package/src/providers/meta-web.ts +2931 -0
  420. package/src/providers/read-failure.ts +139 -0
  421. package/src/providers/reddit-omni.ts +462 -0
  422. package/src/providers/reddit-web-runtime.ts +1929 -0
  423. package/src/providers/reddit-web.ts +1611 -0
  424. package/src/providers/rental-listings.ts +460 -0
  425. package/src/providers/substack-omni.ts +406 -0
  426. package/src/providers/substack-video-mp4.ts +33 -0
  427. package/src/providers/substack-web-runtime.ts +2812 -0
  428. package/src/providers/substack-web.ts +1502 -0
  429. package/src/providers/tiktok-video-mp4.ts +33 -0
  430. package/src/providers/tiktok-web-runtime.ts +770 -0
  431. package/src/providers/tiktok-web.ts +2786 -0
  432. package/src/providers/twitch-web-runtime.ts +226 -0
  433. package/src/providers/twitch-web.ts +274 -0
  434. package/src/providers/whatsapp-account-identity.ts +55 -0
  435. package/src/providers/whatsapp-contact-projection-helper.ts +874 -0
  436. package/src/providers/whatsapp-contact-projection-protocol.ts +403 -0
  437. package/src/providers/whatsapp-interaction-projection-helper.ts +1452 -0
  438. package/src/providers/whatsapp-interaction-projection-protocol.ts +462 -0
  439. package/src/providers/whatsapp-message-export-projection-protocol.ts +532 -0
  440. package/src/providers/whatsapp-messaging.ts +132 -0
  441. package/src/providers/whatsapp-omni.ts +586 -0
  442. package/src/providers/whatsapp-web-runtime.ts +3108 -0
  443. package/src/providers/whatsapp-web.ts +1037 -0
  444. package/src/providers/x-image-provenance.ts +523 -0
  445. package/src/providers/x-made-with-ai.ts +106 -0
  446. package/src/providers/x-transaction-id.ts +413 -0
  447. package/src/providers/x-web-runtime.ts +3485 -0
  448. package/src/providers/x-web.ts +2332 -0
  449. package/src/providers/x.ts +1889 -0
  450. package/src/providers/youtube-web-runtime.ts +1400 -0
  451. package/src/providers/youtube-web.ts +1221 -0
  452. package/src/read-admission-runtime.ts +91 -0
  453. package/src/read-client.ts +521 -0
  454. package/src/read-effect-platform.ts +7 -0
  455. package/src/read-effect-runtime.ts +14 -0
  456. package/src/read-effect.ts +52 -0
  457. package/src/read-projection-admission.ts +866 -0
  458. package/src/read-projections.ts +3151 -0
  459. package/src/recovery.ts +1492 -0
  460. package/src/reviewed-template.ts +146 -0
  461. package/src/run-journal.ts +1272 -0
  462. package/src/runtime.ts +5116 -0
  463. package/src/scripts/generate-provider-plugin-catalog.ts +121 -0
  464. package/src/scripts/install-whatsapp-protocol.sh +232 -0
  465. package/src/scripts/recover-install-stages.ts +1491 -0
  466. package/src/scripts/resolve-state-home.ts +30 -0
  467. package/src/scripts/scaffold-web-provider.ts +973 -0
  468. package/src/scripts/sync-bundled-adapters.ts +695 -0
  469. package/src/session-secrets.ts +1183 -0
  470. package/src/state-helper.bunfig.toml +2 -0
  471. package/src/state-helper.ts +2914 -0
  472. package/src/storage.ts +3842 -0
  473. package/src/transport-policy.ts +2 -0
  474. package/src/usage.ts +182 -0
  475. package/src/version.ts +2 -0
  476. package/src/web-session-authentication-policy.ts +136 -0
  477. package/src/web-session-cleanup-admission.ts +2344 -0
  478. package/src/web-session-cleanup-join.ts +99 -0
  479. package/src/web-session-client.ts +996 -0
  480. package/src/web-session-contract-definitions.ts +820 -0
  481. package/src/web-session-contract-planning.ts +42 -0
  482. package/src/web-session-contracts.ts +228 -0
  483. package/src/web-session-cookies.ts +500 -0
  484. package/src/web-session-execution.ts +385 -0
  485. package/src/web-session-http.ts +373 -0
  486. package/src/web-session-read-errors.ts +19 -0
  487. package/src/web-session-read-runtime.ts +124 -0
  488. package/src/web-session-recovery.ts +818 -0
  489. package/src/web-session-sites.ts +58 -0
  490. package/src/web-session-template.ts +994 -0
  491. package/src/web-session.ts +93 -0
  492. package/src/whatsapp-client-binding.ts +21 -0
  493. package/src/whatsapp-client-types.ts +75 -0
  494. package/src/whatsapp-client.ts +395 -0
  495. package/src/whatsapp-export-coordinate.ts +17 -0
  496. package/src/whatsapp-message-bundle-v2.ts +195 -0
  497. package/src/whatsapp-message-like-me-cli.ts +195 -0
  498. package/src/whatsapp-message-like-me-export.ts +1072 -0
  499. package/src/whatsapp-message-like-me-source.ts +1012 -0
  500. package/tsconfig.json +67 -0
@@ -0,0 +1,532 @@
1
+ import { canonicalJson, sha256 } from "../canonical-json";
2
+ import {
3
+ messageLikeMeSourceConversationCoordinateBindingV1,
4
+ } from "../message-like-me-agentic-messaging";
5
+ import type { OperationInput } from "../model";
6
+ import type { ProviderMessageV1 } from "../omni-model";
7
+ import type {
8
+ ProviderPluginMessagingDefinitionV1,
9
+ ProviderPluginMessagingTargetV1,
10
+ } from "../provider-plugin";
11
+ import {
12
+ IMSG_ACCOUNT_SELECTION,
13
+ IMSG_SERVICE,
14
+ IMSG_SMS_FALLBACK,
15
+ IMSG_TRANSPORT,
16
+ boundedImsgString,
17
+ parseImsgDirectOperationInput,
18
+ } from "./imessage-direct";
19
+ import {
20
+ imsgConversationProviderId,
21
+ imsgMessageProviderId,
22
+ materializeImsgExactConversation,
23
+ } from "./imessage-direct-omni";
24
+
25
+ type JsonRecord = Readonly<Record<string, unknown>>;
26
+
27
+ function record(value: unknown, label: string): JsonRecord {
28
+ if (
29
+ typeof value !== "object"
30
+ || value === null
31
+ || Array.isArray(value)
32
+ || Object.getPrototypeOf(value) !== Object.prototype
33
+ ) throw new Error(`${label} must be a plain object`);
34
+ const descriptors = Object.getOwnPropertyDescriptors(value);
35
+ if (Reflect.ownKeys(descriptors).some((key) => typeof key !== "string")) {
36
+ throw new Error(`${label} must not contain symbol fields`);
37
+ }
38
+ for (const descriptor of Object.values(descriptors)) {
39
+ if (!descriptor.enumerable || !("value" in descriptor)) {
40
+ throw new Error(`${label} must contain only enumerable data fields`);
41
+ }
42
+ }
43
+ return value as JsonRecord;
44
+ }
45
+
46
+ function exactKeys(value: JsonRecord, keys: readonly string[], label: string): void {
47
+ const actual = Object.keys(value).sort();
48
+ const expected = [...keys].sort();
49
+ if (
50
+ actual.length !== expected.length
51
+ || actual.some((key, index) => key !== expected[index])
52
+ ) throw new Error(`${label} has unsupported fields`);
53
+ }
54
+
55
+ function positiveRowId(value: unknown, label: string): number {
56
+ const parsed = typeof value === "string" && /^[1-9][0-9]*$/u.test(value)
57
+ ? Number(value)
58
+ : Number.NaN;
59
+ if (!Number.isSafeInteger(parsed) || parsed < 1) {
60
+ throw new Error(`${label} must be a positive decimal row ID`);
61
+ }
62
+ return parsed;
63
+ }
64
+
65
+ function positiveNumericRowId(value: unknown, label: string): number {
66
+ if (
67
+ typeof value !== "number"
68
+ || !Number.isSafeInteger(value)
69
+ || value < 1
70
+ ) throw new Error(`${label} must be a positive row ID`);
71
+ return value;
72
+ }
73
+
74
+ function targetField(
75
+ target: ProviderPluginMessagingTargetV1,
76
+ key: "chatGuid" | "service" | "observedChatRowId",
77
+ ): string {
78
+ const value = target[key];
79
+ if (value === undefined) throw new Error("iMessage target changed after parsing");
80
+ return value;
81
+ }
82
+
83
+ export function parseImsgMessagingTarget(
84
+ value: unknown,
85
+ ): ProviderPluginMessagingTargetV1 {
86
+ const source = record(value, "iMessage messaging target");
87
+ exactKeys(
88
+ source,
89
+ ["chatGuid", "service", "observedChatRowId"],
90
+ "iMessage messaging target",
91
+ );
92
+ if (source.service !== IMSG_SERVICE) {
93
+ throw new Error("iMessage messaging target service must be exactly iMessage");
94
+ }
95
+ const observedChatRowId = positiveRowId(
96
+ source.observedChatRowId,
97
+ "iMessage messaging target row ID",
98
+ );
99
+ return Object.freeze({
100
+ chatGuid: boundedImsgString(
101
+ source.chatGuid,
102
+ "iMessage messaging target chat GUID",
103
+ 2_048,
104
+ ),
105
+ service: IMSG_SERVICE,
106
+ observedChatRowId: String(observedChatRowId),
107
+ });
108
+ }
109
+
110
+ function decodeConversationGuid(providerId: string): string {
111
+ const prefix = "imessage:chat:";
112
+ if (!providerId.startsWith(prefix)) {
113
+ throw new Error("iMessage conversation provider ID is malformed");
114
+ }
115
+ let decoded: string;
116
+ try {
117
+ decoded = Buffer.from(providerId.slice(prefix.length), "base64url").toString("utf8");
118
+ } catch {
119
+ throw new Error("iMessage conversation provider ID is malformed");
120
+ }
121
+ if (imsgConversationProviderId(decoded) !== providerId) {
122
+ throw new Error("iMessage conversation provider ID is noncanonical");
123
+ }
124
+ return boundedImsgString(decoded, "iMessage conversation GUID", 2_048);
125
+ }
126
+
127
+ function rowIdFromRevision(revision: string | null): number {
128
+ if (revision === null) throw new Error("iMessage conversation lacks a live row revision");
129
+ const separator = revision.indexOf(":");
130
+ if (separator < 1) throw new Error("iMessage conversation row revision is malformed");
131
+ return positiveRowId(revision.slice(0, separator), "iMessage conversation row revision");
132
+ }
133
+
134
+ function exactConversationFromOutput(output: unknown) {
135
+ const envelope = record(output, "direct iMessage exact conversation output");
136
+ const rawConversation = record(
137
+ envelope.conversation,
138
+ "direct iMessage exact conversation output conversation",
139
+ );
140
+ if (rawConversation.service !== IMSG_SERVICE) {
141
+ throw new Error("direct iMessage exact conversation changed service");
142
+ }
143
+ return materializeImsgExactConversation(Object.freeze({
144
+ chat_guid: boundedImsgString(
145
+ rawConversation.guid,
146
+ "direct iMessage exact conversation GUID",
147
+ 2_048,
148
+ ),
149
+ service: IMSG_SERVICE,
150
+ observed_chat_row_id: positiveNumericRowId(
151
+ rawConversation.id,
152
+ "direct iMessage exact conversation row ID",
153
+ ),
154
+ }), output);
155
+ }
156
+
157
+ function rawImsgMessageGuid(providerId: string): string {
158
+ const prefix = "imessage:message:";
159
+ if (!providerId.startsWith(prefix)) {
160
+ throw new Error("iMessage message provider ID is malformed");
161
+ }
162
+ let decoded: string;
163
+ try {
164
+ decoded = Buffer.from(providerId.slice(prefix.length), "base64url").toString("utf8");
165
+ } catch {
166
+ throw new Error("iMessage message provider ID is malformed");
167
+ }
168
+ if (imsgMessageProviderId(decoded) !== providerId) {
169
+ throw new Error("iMessage message provider ID is noncanonical");
170
+ }
171
+ return boundedImsgString(decoded, "iMessage message GUID", 2_048);
172
+ }
173
+
174
+ function canonicalMessages(messages: readonly ProviderMessageV1[]): readonly ProviderMessageV1[] {
175
+ return Object.freeze([...messages].sort((left, right) => {
176
+ const leftKey = `${left.orderedAt ?? ""}\0${left.providerId}`;
177
+ const rightKey = `${right.orderedAt ?? ""}\0${right.providerId}`;
178
+ return leftKey < rightKey ? -1 : leftKey > rightKey ? 1 : 0;
179
+ }));
180
+ }
181
+
182
+ function exactAcceptedMessage(
183
+ message: ProviderMessageV1,
184
+ expected: {
185
+ readonly providerMessageId: string;
186
+ readonly providerRevision: string | null;
187
+ readonly direction: "outgoing";
188
+ readonly bodySha256: string;
189
+ readonly replyToProviderId: string | null;
190
+ },
191
+ ): boolean {
192
+ return message.providerId === expected.providerMessageId
193
+ && message.providerRevision === expected.providerRevision
194
+ && message.direction === "outgoing"
195
+ && message.state === "active"
196
+ && message.subject === null
197
+ && message.body !== null
198
+ && message.bodyTruncated !== true
199
+ && sha256(message.body) === expected.bodySha256
200
+ && expected.replyToProviderId === null
201
+ && message.replyToProviderId === null
202
+ && message.attachments.length === 0;
203
+ }
204
+
205
+ export const imsgDirectMessagingDefinition = Object.freeze({
206
+ schemaVersion: 1,
207
+ contractId: "wrench.provider-messaging.imessage-direct.v1",
208
+ network: "imessage",
209
+ contextLiveness: "fresh-as-of-live-preflight",
210
+ listOperation: "messaging.list",
211
+ contextOperation: "messaging.read",
212
+ enumerateRoutes: (_input: OperationInput, page) => Object.freeze(
213
+ page.entities.map((entity) => {
214
+ if (entity.kind !== "conversation") {
215
+ throw new Error("iMessage route projection contained a non-conversation");
216
+ }
217
+ const chatGuid = decodeConversationGuid(entity.providerId);
218
+ const observedChatRowId = rowIdFromRevision(entity.providerRevision);
219
+ return Object.freeze({
220
+ target: Object.freeze({
221
+ chatGuid,
222
+ service: IMSG_SERVICE,
223
+ observedChatRowId: String(observedChatRowId),
224
+ }),
225
+ conversationProviderId: entity.providerId,
226
+ conversationKind: entity.conversationKind ?? "unknown",
227
+ title: entity.title,
228
+ participants: entity.participants,
229
+ // The chat row's last-message timestamp changes after every send. Route
230
+ // identity is the exact GUID, row ID, service, and participant set.
231
+ providerRevision: null,
232
+ });
233
+ }),
234
+ ),
235
+ resolveRoute: Object.freeze({
236
+ operation: "conversations.read",
237
+ input: (target: ProviderPluginMessagingTargetV1) => {
238
+ const parsed = parseImsgMessagingTarget(target);
239
+ return Object.freeze({
240
+ chat_guid: boundedImsgString(
241
+ targetField(parsed, "chatGuid"),
242
+ "direct iMessage route chat GUID",
243
+ 2_048,
244
+ ),
245
+ service: IMSG_SERVICE,
246
+ observed_chat_row_id: positiveRowId(
247
+ targetField(parsed, "observedChatRowId"),
248
+ "direct iMessage route row ID",
249
+ ),
250
+ });
251
+ },
252
+ candidates: (target, output) => {
253
+ const parsed = parseImsgMessagingTarget(target);
254
+ const chatGuid = targetField(parsed, "chatGuid");
255
+ const observedChatRowId = positiveRowId(
256
+ targetField(parsed, "observedChatRowId"),
257
+ "direct iMessage route row ID",
258
+ );
259
+ const input = Object.freeze({
260
+ chat_guid: chatGuid,
261
+ service: IMSG_SERVICE,
262
+ observed_chat_row_id: observedChatRowId,
263
+ });
264
+ const entity = materializeImsgExactConversation(input, output);
265
+ return Object.freeze([Object.freeze({
266
+ target: Object.freeze({
267
+ chatGuid,
268
+ service: IMSG_SERVICE,
269
+ observedChatRowId: String(observedChatRowId),
270
+ }),
271
+ conversationProviderId: entity.providerId,
272
+ conversationKind: entity.conversationKind ?? "unknown",
273
+ title: entity.title,
274
+ participants: entity.participants,
275
+ providerRevision: null,
276
+ })]);
277
+ },
278
+ sourceConversationCoordinate: (
279
+ target,
280
+ output,
281
+ _expectedAccountSubject,
282
+ ) => {
283
+ const parsed = parseImsgMessagingTarget(target);
284
+ const chatGuid = targetField(parsed, "chatGuid");
285
+ const observedChatRowId = positiveRowId(
286
+ targetField(parsed, "observedChatRowId"),
287
+ "direct iMessage source row ID",
288
+ );
289
+ exactConversationFromOutput(output);
290
+ return messageLikeMeSourceConversationCoordinateBindingV1({
291
+ sourceAccountId: null,
292
+ sourceExternalId: chatGuid,
293
+ coordinate: Object.freeze({
294
+ kind: "imessageChat" as const,
295
+ chatGuid,
296
+ service: IMSG_SERVICE,
297
+ observedChatRowId,
298
+ }),
299
+ });
300
+ },
301
+ }),
302
+ parseTarget: parseImsgMessagingTarget,
303
+ contextInput: (target, limit) => {
304
+ const parsed = parseImsgMessagingTarget(target);
305
+ return Object.freeze({
306
+ chat_guid: targetField(parsed, "chatGuid"),
307
+ service: targetField(parsed, "service"),
308
+ observed_chat_row_id: positiveRowId(
309
+ targetField(parsed, "observedChatRowId"),
310
+ "iMessage context row ID",
311
+ ),
312
+ limit,
313
+ });
314
+ },
315
+ action: Object.freeze({
316
+ state: "supported",
317
+ operation: "messaging.send",
318
+ reply: "unsupported",
319
+ livePreflight: Object.freeze({
320
+ operation: "conversations.read",
321
+ input: (target: ProviderPluginMessagingTargetV1) => {
322
+ const parsed = parseImsgMessagingTarget(target);
323
+ return Object.freeze({
324
+ chat_guid: targetField(parsed, "chatGuid"),
325
+ service: targetField(parsed, "service"),
326
+ observed_chat_row_id: positiveRowId(
327
+ targetField(parsed, "observedChatRowId"),
328
+ "iMessage live preflight row ID",
329
+ ),
330
+ });
331
+ },
332
+ snapshot: (output: unknown, _expectedAccountSubject: string) => {
333
+ const envelope = record(
334
+ output,
335
+ "direct iMessage exact conversation output",
336
+ );
337
+ const rawConversation = record(
338
+ envelope.conversation,
339
+ "direct iMessage exact conversation output conversation",
340
+ );
341
+ const entity = exactConversationFromOutput(output);
342
+ const chatGuid = boundedImsgString(
343
+ rawConversation.guid,
344
+ "direct iMessage exact conversation GUID",
345
+ 2_048,
346
+ );
347
+ const observedChatRowId = positiveNumericRowId(
348
+ rawConversation.id,
349
+ "direct iMessage exact conversation row ID",
350
+ );
351
+ return Object.freeze({
352
+ conversationProviderId: entity.providerId,
353
+ network: "imessage",
354
+ conversation: Object.freeze({
355
+ kind: entity.conversationKind ?? "unknown",
356
+ title: entity.title,
357
+ participantCount: entity.participants.length,
358
+ }),
359
+ sourceConversationCoordinate:
360
+ messageLikeMeSourceConversationCoordinateBindingV1({
361
+ sourceAccountId: null,
362
+ sourceExternalId: chatGuid,
363
+ coordinate: {
364
+ kind: "imessageChat",
365
+ chatGuid,
366
+ service: IMSG_SERVICE,
367
+ observedChatRowId,
368
+ },
369
+ }),
370
+ participantFingerprint: sha256(canonicalJson(entity.participants)),
371
+ providerRevision: null,
372
+ });
373
+ },
374
+ }),
375
+ compileTurnPart: (target, part) => {
376
+ if (part.replyToProviderId !== null) {
377
+ throw new Error("AppleScript iMessage transport does not support threaded replies");
378
+ }
379
+ const parsed = parseImsgMessagingTarget(target);
380
+ const input = Object.freeze({
381
+ chat_guid: targetField(parsed, "chatGuid"),
382
+ service: targetField(parsed, "service"),
383
+ observed_chat_row_id: positiveRowId(
384
+ targetField(parsed, "observedChatRowId"),
385
+ "iMessage send row ID",
386
+ ),
387
+ text: part.text,
388
+ });
389
+ parseImsgDirectOperationInput("messaging.send", input);
390
+ return input;
391
+ },
392
+ mapAcceptedResult: (output) => {
393
+ const source = record(output, "direct iMessage accepted result");
394
+ exactKeys(source, [
395
+ "provider",
396
+ "operation",
397
+ "accountSelection",
398
+ "service",
399
+ "transport",
400
+ "smsFallback",
401
+ "transportOutcome",
402
+ "acceptanceEvidence",
403
+ "chatGuid",
404
+ "chatRowId",
405
+ "messageGuid",
406
+ "messageRowId",
407
+ ], "direct iMessage accepted result");
408
+ if (
409
+ source.provider !== "imessage"
410
+ || source.operation !== "messaging.send"
411
+ || source.accountSelection !== IMSG_ACCOUNT_SELECTION
412
+ || source.service !== IMSG_SERVICE
413
+ || source.transport !== IMSG_TRANSPORT
414
+ || source.smsFallback !== IMSG_SMS_FALLBACK
415
+ || source.transportOutcome !== "accepted"
416
+ || source.acceptanceEvidence !== "matching-outgoing-chat-db-row"
417
+ ) throw new Error("direct iMessage send lacks exact accepted evidence");
418
+ const messageGuid = boundedImsgString(
419
+ source.messageGuid,
420
+ "direct iMessage accepted message GUID",
421
+ 2_048,
422
+ );
423
+ if (
424
+ typeof source.messageRowId !== "number"
425
+ || !Number.isSafeInteger(source.messageRowId)
426
+ || source.messageRowId < 1
427
+ ) throw new Error("direct iMessage accepted message row is malformed");
428
+ return Object.freeze({
429
+ state: "submitted" as const,
430
+ providerMessageId: imsgMessageProviderId(messageGuid),
431
+ providerRevision: `${source.messageRowId}:${messageGuid}`,
432
+ });
433
+ },
434
+ proveExpectedOwnPrefix: ({ base, current, accepted }) => {
435
+ if (
436
+ base.contextLimit < 1
437
+ || base.contextLimit > 200
438
+ || base.messages.length > base.contextLimit
439
+ ) return Object.freeze({ state: "drift" as const });
440
+ const baseIds = base.messages.map((message) => message.providerMessageId);
441
+ const acceptedIds = accepted.map((message) => message.providerMessageId);
442
+ if (
443
+ new Set(baseIds).size !== baseIds.length
444
+ || new Set(acceptedIds).size !== acceptedIds.length
445
+ || acceptedIds.some((id) => baseIds.includes(id))
446
+ ) return Object.freeze({ state: "drift" as const });
447
+ const currentMessages = canonicalMessages(current.messages);
448
+ const currentIds = currentMessages.map((message) => message.providerId);
449
+ if (new Set(currentIds).size !== currentIds.length) {
450
+ return Object.freeze({ state: "drift" as const });
451
+ }
452
+ const baseById = new Map(base.messages.map((message) => [
453
+ message.providerMessageId,
454
+ message,
455
+ ]));
456
+ const acceptedById = new Map(accepted.map((message) => [
457
+ message.providerMessageId,
458
+ message,
459
+ ]));
460
+ const exactBaseWindow = currentIds.length === baseIds.length
461
+ && currentIds.every((id, index) => id === baseIds[index])
462
+ && currentMessages.every((message) => {
463
+ const expected = baseById.get(message.providerId);
464
+ return expected !== undefined
465
+ && message.providerRevision === expected.providerRevision
466
+ && message.orderedAt === expected.orderedAt
467
+ && sha256(canonicalJson(message)) === expected.messageSha256;
468
+ });
469
+ if (
470
+ exactBaseWindow
471
+ && current.exactDataRevision === base.exactDataRevision
472
+ && current.latestMessageRevision === base.latestMessageRevision
473
+ ) return Object.freeze({
474
+ state: "proven" as const,
475
+ matchedAcceptedPrefixCount: 0,
476
+ });
477
+ let visibleAcceptedCount = 0;
478
+ for (let count = 1; count <= accepted.length; count += 1) {
479
+ const visibleIds = [...baseIds, ...acceptedIds.slice(0, count)];
480
+ const expectedWindow = visibleIds.slice(
481
+ Math.max(0, visibleIds.length - base.contextLimit),
482
+ );
483
+ if (
484
+ currentIds.length === expectedWindow.length
485
+ && currentIds.every((id, index) => id === expectedWindow[index])
486
+ ) {
487
+ visibleAcceptedCount = count;
488
+ break;
489
+ }
490
+ }
491
+ if (
492
+ visibleAcceptedCount === 0
493
+ || current.exactDataRevision === base.exactDataRevision
494
+ || current.latestMessageRevision === base.latestMessageRevision
495
+ ) return Object.freeze({ state: "drift" as const });
496
+ for (const message of currentMessages) {
497
+ const baseMessage = baseById.get(message.providerId);
498
+ if (baseMessage !== undefined) {
499
+ if (
500
+ message.providerRevision !== baseMessage.providerRevision
501
+ || message.orderedAt !== baseMessage.orderedAt
502
+ || sha256(canonicalJson(message)) !== baseMessage.messageSha256
503
+ ) return Object.freeze({ state: "drift" as const });
504
+ continue;
505
+ }
506
+ const expected = acceptedById.get(message.providerId);
507
+ if (expected === undefined || !exactAcceptedMessage(message, expected)) {
508
+ return Object.freeze({ state: "drift" as const });
509
+ }
510
+ }
511
+ return Object.freeze({
512
+ state: "proven" as const,
513
+ matchedAcceptedPrefixCount: visibleAcceptedCount,
514
+ });
515
+ },
516
+ reconciliation: (target, accepted) => {
517
+ const parsed = parseImsgMessagingTarget(target);
518
+ return Object.freeze({
519
+ operation: "messaging.delivery.read",
520
+ input: Object.freeze({
521
+ chat_guid: targetField(parsed, "chatGuid"),
522
+ service: targetField(parsed, "service"),
523
+ observed_chat_row_id: positiveRowId(
524
+ targetField(parsed, "observedChatRowId"),
525
+ "iMessage reconciliation row ID",
526
+ ),
527
+ message_guid: rawImsgMessageGuid(accepted.providerMessageId),
528
+ }),
529
+ });
530
+ },
531
+ }),
532
+ } satisfies ProviderPluginMessagingDefinitionV1);