@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,355 @@
1
+ // @bun
2
+ import {
3
+ canonicalJson,
4
+ sha256
5
+ } from "./index-gwk7rbyj.js";
6
+
7
+ // src/whatsapp-client.ts
8
+ import { spawnSync } from "child_process";
9
+ import { existsSync } from "fs";
10
+ import { fileURLToPath } from "url";
11
+ import { types as nodeTypes } from "util";
12
+
13
+ // src/whatsapp-client-binding.ts
14
+ function fail(message) {
15
+ throw new Error(`Ghostget WhatsApp client: ${message}`);
16
+ }
17
+ function requireWhatsAppMessageLikeMeReceiptRequestBinding(receipt, request) {
18
+ if (receipt.auth.id !== request.authId) {
19
+ return fail("receipt auth identity does not match the requested auth locator");
20
+ }
21
+ if (receipt.output.directory !== request.output) {
22
+ return fail("receipt output directory does not match the requested output");
23
+ }
24
+ return receipt;
25
+ }
26
+
27
+ // src/whatsapp-export-coordinate.ts
28
+ import { dirname, isAbsolute, resolve } from "path";
29
+ var WHATSAPP_EXPORT_AUTH_ID_PATTERN = /^[a-z][a-z0-9-]{0,47}$/u;
30
+ var MAX_WHATSAPP_EXPORT_OUTPUT_BYTES = 4096;
31
+ function isWhatsAppExportAuthId(value) {
32
+ return typeof value === "string" && WHATSAPP_EXPORT_AUTH_ID_PATTERN.test(value);
33
+ }
34
+ function isWhatsAppExportOutputDirectory(value) {
35
+ return typeof value === "string" && isAbsolute(value) && resolve(value) === value && dirname(value) !== value && Buffer.byteLength(value, "utf8") <= MAX_WHATSAPP_EXPORT_OUTPUT_BYTES && !/[\0\r\n]/u.test(value);
36
+ }
37
+
38
+ // src/whatsapp-client.ts
39
+ var MAX_STDOUT_BYTES = 2 * 1024 * 1024;
40
+ var MAX_STDERR_BYTES = 8 * 1024;
41
+ var MAX_V2_RECORDS = 500000;
42
+ var PROCESS_TIMEOUT_MS = 6 * 60 * 60 * 1000 + 60000;
43
+ var DIGEST_PATTERN = /^[a-f0-9]{64}$/u;
44
+ function fail2(message) {
45
+ throw new Error(`Ghostget WhatsApp client: ${message}`);
46
+ }
47
+ function record(value, label) {
48
+ if (typeof value !== "object" || value === null || Array.isArray(value) || nodeTypes.isProxy(value) || Object.getPrototypeOf(value) !== Object.prototype && Object.getPrototypeOf(value) !== null)
49
+ return fail2(`${label} must be a plain data object`);
50
+ const descriptors = Object.getOwnPropertyDescriptors(value);
51
+ for (const key of Reflect.ownKeys(descriptors)) {
52
+ if (typeof key !== "string")
53
+ return fail2(`${label} must contain only enumerable string data fields`);
54
+ const descriptor = descriptors[key];
55
+ if (descriptor === undefined || !descriptor.enumerable || !("value" in descriptor)) {
56
+ return fail2(`${label} must contain only enumerable string data fields`);
57
+ }
58
+ }
59
+ return Object.freeze(Object.fromEntries(Object.entries(descriptors).map(([key, descriptor]) => [key, descriptor.value])));
60
+ }
61
+ function exact(value, keys, label) {
62
+ const observed = Object.keys(value).sort();
63
+ const expected = [...keys].sort();
64
+ if (observed.length !== expected.length || observed.some((key, index) => key !== expected[index])) {
65
+ fail2(`${label} contains unsupported or missing fields`);
66
+ }
67
+ }
68
+ function timestamp(value, label, nullable = false) {
69
+ if (nullable && value === null)
70
+ return null;
71
+ if (typeof value !== "string")
72
+ return fail2(`${label} must be a timestamp`);
73
+ const parsed = new Date(value);
74
+ if (!Number.isFinite(parsed.getTime()) || parsed.toISOString() !== value) {
75
+ return fail2(`${label} must be a canonical UTC timestamp`);
76
+ }
77
+ return value;
78
+ }
79
+ function digest(value, label) {
80
+ if (typeof value !== "string" || !DIGEST_PATTERN.test(value)) {
81
+ return fail2(`${label} must be lowercase SHA-256`);
82
+ }
83
+ return value;
84
+ }
85
+ function nonNegative(value, label) {
86
+ if (typeof value !== "number" || !Number.isSafeInteger(value) || value < 0) {
87
+ return fail2(`${label} must be a non-negative safe integer`);
88
+ }
89
+ return value;
90
+ }
91
+ function denseDataArray(value, label, maximum) {
92
+ if (nodeTypes.isProxy(value) || !Array.isArray(value) || Object.getPrototypeOf(value) !== Array.prototype)
93
+ return fail2(`${label} must be an ordinary non-proxy array`);
94
+ const descriptors = Object.getOwnPropertyDescriptors(value);
95
+ const lengthDescriptor = Object.getOwnPropertyDescriptor(value, "length");
96
+ if (lengthDescriptor === undefined || !("value" in lengthDescriptor) || typeof lengthDescriptor.value !== "number" || !Number.isSafeInteger(lengthDescriptor.value) || lengthDescriptor.value < 0 || lengthDescriptor.value > maximum)
97
+ return fail2(`${label} length exceeds its reviewed bound`);
98
+ const length = lengthDescriptor.value;
99
+ const keys = Reflect.ownKeys(descriptors);
100
+ if (keys.length !== length + 1 || keys.some((key) => typeof key !== "string"))
101
+ return fail2(`${label} must be a dense array without named properties`);
102
+ const items = [];
103
+ for (let index = 0;index < length; index += 1) {
104
+ const descriptor = descriptors[String(index)];
105
+ if (descriptor === undefined || !descriptor.enumerable || !("value" in descriptor))
106
+ return fail2(`${label} must contain only dense enumerable data elements`);
107
+ items.push(descriptor.value);
108
+ }
109
+ if (keys.some((key) => key !== "length" && (typeof key !== "string" || !/^(0|[1-9][0-9]*)$/u.test(key)))) {
110
+ return fail2(`${label} must be a dense array without named properties`);
111
+ }
112
+ return Object.freeze(items);
113
+ }
114
+ function parseWhatsAppMessageLikeMeExportReceipt(value) {
115
+ const root = record(value, "receipt");
116
+ exact(root, [
117
+ "schemaVersion",
118
+ "format",
119
+ "runId",
120
+ "operation",
121
+ "status",
122
+ "transport",
123
+ "startedAt",
124
+ "finishedAt",
125
+ "auth",
126
+ "source",
127
+ "provider",
128
+ "completeness",
129
+ "warnings",
130
+ "counts",
131
+ "output",
132
+ "privacy",
133
+ "integrity"
134
+ ], "receipt");
135
+ if (root.schemaVersion !== 1 || root.format !== "wrench.whatsapp-message-like-me-export-receipt" || typeof root.runId !== "string" || !/^[a-f0-9]{8}-[a-f0-9]{4}-4[a-f0-9]{3}-[89ab][a-f0-9]{3}-[a-f0-9]{12}$/u.test(root.runId) || root.operation !== "whatsapp.export-message-like-me" || root.status !== "succeeded" || root.transport !== "linked-device-local-store")
136
+ return fail2("receipt identity is unsupported");
137
+ const startedAt = timestamp(root.startedAt, "receipt.startedAt");
138
+ const finishedAt = timestamp(root.finishedAt, "receipt.finishedAt");
139
+ if (finishedAt < startedAt)
140
+ return fail2("receipt timestamps are reversed");
141
+ const auth = record(root.auth, "receipt.auth");
142
+ exact(auth, ["id", "provider", "identitySha256"], "receipt.auth");
143
+ if (!isWhatsAppExportAuthId(auth.id)) {
144
+ return fail2("receipt.auth.id is not a bounded lowercase auth coordinate");
145
+ }
146
+ const parsedAuthId = auth.id;
147
+ if (auth.provider !== "whatsapp")
148
+ return fail2("receipt auth identity is unsupported");
149
+ const identitySha256 = digest(auth.identitySha256, "receipt.auth.identitySha256");
150
+ const source = record(root.source, "receipt.source");
151
+ exact(source, ["id", "version"], "receipt.source");
152
+ const provider = record(root.provider, "receipt.provider");
153
+ exact(provider, ["id", "version"], "receipt.provider");
154
+ if (source.id !== "wacli-local" || source.version !== "1.0.0" || provider.id !== "whatsapp" || provider.version !== "0.15.0")
155
+ return fail2("receipt producer identity is unsupported");
156
+ const completeness = record(root.completeness, "receipt.completeness");
157
+ exact(completeness, ["kind", "reason", "observedFrom", "observedThrough"], "receipt.completeness");
158
+ if (completeness.kind !== "bounded-local" || completeness.reason !== "local-store-coverage-unknown")
159
+ return fail2("receipt completeness boundary is unsupported");
160
+ const observedFrom = timestamp(completeness.observedFrom, "receipt.completeness.observedFrom", true);
161
+ const observedThrough = timestamp(completeness.observedThrough, "receipt.completeness.observedThrough", true);
162
+ if (observedFrom === null !== (observedThrough === null) || observedFrom !== null && observedThrough !== null && observedThrough < observedFrom) {
163
+ return fail2("receipt completeness timestamps are reversed");
164
+ }
165
+ const warnings = denseDataArray(root.warnings, "receipt.warnings", 5);
166
+ const warningOrder = [
167
+ "remote-history-incomplete",
168
+ "reaction-state-unproven",
169
+ "self-chat-excluded",
170
+ "message-payload-purged",
171
+ "non-conversation-chats-excluded"
172
+ ];
173
+ if (warnings[0] !== warningOrder[0] || warnings.some((item) => typeof item !== "string" || !warningOrder.includes(item)) || warnings.some((item, index) => index > 0 && warningOrder.indexOf(item) <= warningOrder.indexOf(warnings[index - 1])))
174
+ return fail2("receipt warnings are unsupported");
175
+ const warningTail = warnings.slice(1).map((warning) => warning);
176
+ const canonicalWarnings = Object.freeze([
177
+ "remote-history-incomplete",
178
+ ...warningTail
179
+ ]);
180
+ const counts = record(root.counts, "receipt.counts");
181
+ const countKinds = ["account", "participant", "conversation", "message", "reaction", "tombstone"];
182
+ exact(counts, countKinds, "receipt.counts");
183
+ const parsedCounts = Object.fromEntries(countKinds.map((kind) => [
184
+ kind,
185
+ nonNegative(counts[kind], `receipt.counts.${kind}`)
186
+ ]));
187
+ const observed = observedFrom !== null;
188
+ const totalRecords = countKinds.reduce((total, kind) => total + parsedCounts[kind], 0);
189
+ if (parsedCounts.account !== 1 || parsedCounts.participant < 1 || parsedCounts.reaction !== 0 || parsedCounts.tombstone !== 0 || parsedCounts.message > 0 !== observed || parsedCounts.conversation > 0 !== observed || parsedCounts.conversation > parsedCounts.message || parsedCounts.message > MAX_V2_RECORDS || parsedCounts.participant > parsedCounts.message + 1 || !Number.isSafeInteger(totalRecords) || totalRecords > MAX_V2_RECORDS || warnings.includes("message-payload-purged") && parsedCounts.message === 0)
190
+ return fail2("receipt counts contradict the fixed producer");
191
+ const output = record(root.output, "receipt.output");
192
+ exact(output, ["schemaVersion", "format", "directory", "manifestSha256"], "receipt.output");
193
+ if (!isWhatsAppExportOutputDirectory(output.directory)) {
194
+ return fail2("receipt.output.directory is not a bounded normalized non-root absolute directory");
195
+ }
196
+ const parsedOutputDirectory = output.directory;
197
+ if (output.schemaVersion !== 2 || output.format !== "message-like-me.local-message-bundle")
198
+ return fail2("receipt output identity is unsupported");
199
+ const manifestSha256 = digest(output.manifestSha256, "receipt.output.manifestSha256");
200
+ const privacy = record(root.privacy, "receipt.privacy");
201
+ exact(privacy, [
202
+ "classification",
203
+ "attachments",
204
+ "credentials",
205
+ "sourcePaths",
206
+ "mediaBytes",
207
+ "cloudSync"
208
+ ], "receipt.privacy");
209
+ if (privacy.classification !== "private-local" || privacy.attachments !== "metadata-only" || privacy.credentials !== "excluded" || privacy.sourcePaths !== "excluded" || privacy.mediaBytes !== "excluded" || privacy.cloudSync !== "none")
210
+ return fail2("receipt privacy boundary is unsupported");
211
+ const integrity = record(root.integrity, "receipt.integrity");
212
+ exact(integrity, ["algorithm", "receiptSha256"], "receipt.integrity");
213
+ if (integrity.algorithm !== "sha256")
214
+ return fail2("receipt integrity algorithm is unsupported");
215
+ const expectedDigest = digest(integrity.receiptSha256, "receipt.integrity.receiptSha256");
216
+ const projection = Object.freeze({
217
+ schemaVersion: 1,
218
+ format: "wrench.whatsapp-message-like-me-export-receipt",
219
+ runId: root.runId,
220
+ operation: "whatsapp.export-message-like-me",
221
+ status: "succeeded",
222
+ transport: "linked-device-local-store",
223
+ startedAt,
224
+ finishedAt,
225
+ auth: Object.freeze({
226
+ id: parsedAuthId,
227
+ provider: "whatsapp",
228
+ identitySha256
229
+ }),
230
+ source: Object.freeze({ id: "wacli-local", version: "1.0.0" }),
231
+ provider: Object.freeze({ id: "whatsapp", version: "0.15.0" }),
232
+ completeness: Object.freeze({
233
+ kind: "bounded-local",
234
+ reason: "local-store-coverage-unknown",
235
+ observedFrom,
236
+ observedThrough
237
+ }),
238
+ warnings: canonicalWarnings,
239
+ counts: Object.freeze({
240
+ account: 1,
241
+ participant: parsedCounts.participant,
242
+ conversation: parsedCounts.conversation,
243
+ message: parsedCounts.message,
244
+ reaction: 0,
245
+ tombstone: 0
246
+ }),
247
+ output: Object.freeze({
248
+ schemaVersion: 2,
249
+ format: "message-like-me.local-message-bundle",
250
+ directory: parsedOutputDirectory,
251
+ manifestSha256
252
+ }),
253
+ privacy: Object.freeze({
254
+ classification: "private-local",
255
+ attachments: "metadata-only",
256
+ credentials: "excluded",
257
+ sourcePaths: "excluded",
258
+ mediaBytes: "excluded",
259
+ cloudSync: "none"
260
+ })
261
+ });
262
+ if (sha256(canonicalJson(projection)) !== expectedDigest) {
263
+ return fail2("receipt digest does not match its canonical projection");
264
+ }
265
+ return Object.freeze({
266
+ ...projection,
267
+ integrity: Object.freeze({ algorithm: "sha256", receiptSha256: expectedDigest })
268
+ });
269
+ }
270
+ function cliSourcePath() {
271
+ const besideSource = fileURLToPath(new URL("./cli.ts", import.meta.url));
272
+ if (existsSync(besideSource))
273
+ return besideSource;
274
+ const packagedSource = fileURLToPath(new URL("../src/cli.ts", import.meta.url));
275
+ if (existsSync(packagedSource))
276
+ return packagedSource;
277
+ return fail2("the installed Ghostget CLI source is unavailable");
278
+ }
279
+ function preparedEnvironment(additions) {
280
+ const environment = Object.create(null);
281
+ for (const [key, value] of Object.entries(process.env)) {
282
+ if (typeof value === "string")
283
+ environment[key] = value;
284
+ }
285
+ if (additions === undefined)
286
+ return Object.freeze(environment);
287
+ const source = record(additions, "options.environment");
288
+ for (const [key, value] of Object.entries(source)) {
289
+ if (key.length < 1 || key.includes("=") || key.includes("\x00")) {
290
+ return fail2("environment name is malformed");
291
+ }
292
+ if (value === undefined)
293
+ delete environment[key];
294
+ else if (typeof value !== "string" || value.includes("\x00")) {
295
+ return fail2("environment value is malformed");
296
+ } else
297
+ environment[key] = value;
298
+ }
299
+ return Object.freeze(environment);
300
+ }
301
+ function exportWhatsAppMessageLikeMeSync(requestValue, optionsValue = {}) {
302
+ if (typeof process.versions.bun !== "string") {
303
+ return fail2("@hraness/ghostget/whatsapp requires Bun");
304
+ }
305
+ const request = record(requestValue, "request");
306
+ exact(request, ["authId", "output"], "request");
307
+ if (!isWhatsAppExportAuthId(request.authId)) {
308
+ return fail2("request.authId is not a bounded lowercase auth coordinate");
309
+ }
310
+ if (!isWhatsAppExportOutputDirectory(request.output)) {
311
+ return fail2("request.output is not a bounded normalized non-root absolute directory");
312
+ }
313
+ const requestedAuthId = request.authId;
314
+ const requestedOutput = request.output;
315
+ const requested = Object.freeze({
316
+ authId: requestedAuthId,
317
+ output: requestedOutput
318
+ });
319
+ const options = record(optionsValue, "options");
320
+ exact(options, Object.hasOwn(options, "environment") ? ["environment"] : [], "options");
321
+ const result = spawnSync(process.execPath, [
322
+ cliSourcePath(),
323
+ "whatsapp",
324
+ "export-message-like-me",
325
+ "--auth",
326
+ requestedAuthId,
327
+ "--output",
328
+ requestedOutput,
329
+ "--json"
330
+ ], {
331
+ cwd: process.cwd(),
332
+ env: preparedEnvironment(options.environment),
333
+ encoding: "utf8",
334
+ maxBuffer: MAX_STDOUT_BYTES,
335
+ timeout: PROCESS_TIMEOUT_MS,
336
+ stdio: ["ignore", "pipe", "inherit"]
337
+ });
338
+ if (result.error !== undefined)
339
+ return fail2("installed CLI could not complete the export");
340
+ if (result.status !== 0 || result.signal !== null) {
341
+ const errorText = typeof result.stderr === "string" ? Buffer.from(result.stderr, "utf8").subarray(0, MAX_STDERR_BYTES).toString("utf8").trim() : "";
342
+ return fail2(errorText.length > 0 ? errorText : "installed CLI rejected the export");
343
+ }
344
+ let raw;
345
+ try {
346
+ raw = JSON.parse(result.stdout.trim());
347
+ } catch {
348
+ return fail2("installed CLI returned malformed JSON");
349
+ }
350
+ return requireWhatsAppMessageLikeMeReceiptRequestBinding(parseWhatsAppMessageLikeMeExportReceipt(raw), requested);
351
+ }
352
+ export {
353
+ parseWhatsAppMessageLikeMeExportReceipt,
354
+ exportWhatsAppMessageLikeMeSync
355
+ };
@@ -0,0 +1,106 @@
1
+ # Direct iMessage provider
2
+
3
+ The `imessage` source plugin wraps one exact reviewed `openclaw/imsg` build. It
4
+ supports bounded local chat and message reads plus confirmed one-to-eight-bubble
5
+ turns to an exact live chat GUID. The mutation path is fixed to AppleScript and
6
+ `iMessage`, with SMS fallback disabled.
7
+
8
+ The plugin does not select an Apple ID. Messages chooses the device-default
9
+ account and routing identity. `account_id`, `account_login`, and
10
+ `last_addressed_handle` from `chat.db` are observations for route inspection,
11
+ not a selectable or proven sending account. The auth subject binds a canonical
12
+ local Messages store coordinate and this device-default policy. It does not
13
+ claim to identify the signed-in Apple account.
14
+
15
+ ## Reviewed transport
16
+
17
+ The vendored patch stack applies to `openclaw/imsg` 0.14.1 at commit
18
+ `25beb76c902b0acf2dd7ae392f1b0792f6813240`. The first commit,
19
+ `292db82d89293867ef847a2875667fea0fdd5dc1`, isolates AppleScript payloads.
20
+ The second, `c5994f00d17969fd7772fd2772e7b3591089513a`, adds the read-only exact
21
+ `chats.get(chat_id)` lookup required to revalidate a route without relying on a
22
+ bounded recent-chat scan. Patch SHA-256 values, changed files, and the full
23
+ artifact review boundary are recorded in
24
+ `src/plugins/imessage-direct/vendor/provenance.json`.
25
+
26
+ AppleScript source remains on standard input. Recipient, text, service,
27
+ attachment path, chat target, and the chat-routing flag live in checked
28
+ mode-0600 files under one random mode-0700 directory. The nested `osascript`
29
+ argv contains only fixed interpreter switches and an opaque random locator.
30
+ The patch rejects symlinks, file substitution, owner or mode changes, and
31
+ in-place content changes. It reaps the child before removing known private
32
+ files and the checked directory.
33
+
34
+ The Ghostget runtime adds an outer boundary. Every RPC child is a fresh detached
35
+ process group with fixed argv `imsg rpc`, bounded stdin/stdout/stderr, a fixed
36
+ minimal environment, a total deadline, and durable cleanup admission. Each
37
+ confirmed bubble produces one separately journaled send process and exactly one
38
+ send request. Private message text appears only in that process's RPC stdin.
39
+ Timeout, signal, malformed output, or lost output after spawn is indeterminate.
40
+ The runtime never retries.
41
+
42
+ `imsg rpc status` is the exact nonlaunching readiness probe. It retries the database open and
43
+ probes only an already-running private bridge. It does not launch, kill, or
44
+ relaunch Messages. Ghostget requires protocol 1, imsg 0.14.1, a readable database,
45
+ and the reviewed `chats.get`, read, and send methods. This proves the local contract is currently
46
+ usable, not which Apple account Messages will choose.
47
+
48
+ ## Build and installation boundary
49
+
50
+ Apply both vendored mail patches in order to an otherwise clean checkout at the exact base,
51
+ then build `imsg` in release mode. The current reviewed macOS arm64 executable
52
+ SHA-256 is
53
+ `77a0db864dfd247cd0a9142dd98997960582e6f150f76ecd3bf1c38944f2bf71`.
54
+ Compiler, SDK, and command provenance are in the manifest. A different byte is
55
+ not this reviewed transport, even if it prints version 0.14.1.
56
+
57
+ Install only that byte sequence through the checked installer:
58
+
59
+ ```sh
60
+ ghostget imessage transport install --binary /absolute/path/to/imsg --json
61
+ ```
62
+
63
+ The installer supports only the declared current platform, reads the source
64
+ without following a symlink, checks owner, mode, size, stability, and SHA-256,
65
+ and installs by an exclusive same-filesystem link. It never replaces mismatched
66
+ existing bytes. Software build, installation, Messages login, and account
67
+ recovery remain operator workflows, not provider operations.
68
+
69
+ Bind the local Messages store after the reviewed binary is installed:
70
+
71
+ ```sh
72
+ ghostget adapter sync-bundled --json
73
+ ghostget auth add imessage-main --linked-device imessage \
74
+ --device-store "${HOME}/Library/Messages"
75
+ ghostget auth bind imessage-main --site imessage
76
+ ```
77
+
78
+ macOS must grant the invoking terminal Full Disk Access for `chat.db` and
79
+ Automation access to Messages for a send. No live send is part of installation
80
+ or subject binding.
81
+
82
+ ## Outcome boundary
83
+
84
+ Stock AppleScript does not return a message GUID. A Ghostget result is
85
+ `submitted` only when the patched imsg process independently observes one
86
+ matching outgoing `chat.db` row and returns the exact message GUID, chat GUID,
87
+ row ID, `iMessage` service, and `applescript` transport. This is evidence of
88
+ local Messages acceptance, not network delivery or recipient receipt.
89
+
90
+ The transport preserves imsg's `not_started`, `may_have_completed`, and
91
+ `still_in_flight` categories in encrypted provider output. Once Ghostget has
92
+ started the confirmed child, every non-accepted result remains non-retryable at
93
+ the Ghostget boundary. The separately requested `messaging.delivery.read`
94
+ operation can inspect only a GUID already obtained from exact accepted evidence.
95
+ A missing row is not proof that an unobserved send did not happen.
96
+
97
+ Threaded replies are unsupported because AppleScript cannot express them. The
98
+ generic messaging facade owns one composite confirmation and a per-part
99
+ journal with a proven accepted prefix, at most one uncertain current part, and
100
+ an unattempted suffix. Before each remaining bubble it rereads the exact chat
101
+ and bounded history, accepting only the unchanged preview base, that same base
102
+ while an accepted bubble is not yet visible, or the exact visible own-message
103
+ prefix with bounded-window eviction. Foreign activity, edits, deletions,
104
+ reordering, or identity reuse stops the suffix. The provider hook
105
+ `executeImsgDirectMessagingPart` rejects non-send recipes and delegates every
106
+ bubble to the same supervised at-most-once operation boundary.
@@ -0,0 +1,94 @@
1
+ # Rental listings
2
+
3
+ Ghostget exposes public Puerto Rico rental search as one named operation,
4
+ `listings.search`, on the built-in `clasificados-web` plugin.
5
+
6
+ The operation is read-only. It takes a location plus optional bedroom and rent
7
+ bounds, fetches the reviewed ClasificadosOnline list pages, and returns
8
+ structured rows. Each row includes the canonical listing URL, rent, beds, baths,
9
+ street address when the list card publishes one, ZIP when a reviewed ZIP table
10
+ or known-address override can prove it, and a neighborhood derived from that
11
+ address and ZIP or from the listing's own coordinates. Broker titles and
12
+ `BarrioCond` blurbs are never the neighborhood source.
13
+
14
+ ## Input
15
+
16
+ Required key:
17
+
18
+ - `location` — a reviewed San Juan location token such as `San Juan, PR`,
19
+ `Hato Rey`, `Condado`, `Santurce`, `Río Piedras`, or `Viejo San Juan`.
20
+
21
+ Optional keys:
22
+
23
+ - `beds_min` — keep listings with at least this many bedrooms. ClasificadosOnline
24
+ treats its own bedroom field as an exact match, so Ghostget omits that field
25
+ from the query and applies the bound locally.
26
+ - `max_price` — keep listings at or below this monthly rent.
27
+
28
+ Unknown keys, extra fields, and locations outside the reviewed San Juan pueblo
29
+ set are rejected.
30
+
31
+ ## Neighborhood verification
32
+
33
+ Listing text often lies. A Hato Rey tower can advertise Condado. Ghostget resolves
34
+ neighborhood in this order:
35
+
36
+ 1. A reviewed street-plus-ZIP override for a known building.
37
+ 2. A reviewed San Juan ZIP when the listing or override publishes one.
38
+ 3. Coordinates published on the same list card as the listing.
39
+
40
+ Reviewed ZIP examples:
41
+
42
+ - `00918` — Hato Rey
43
+ - `00907` — Condado / Miramar
44
+ - `00901` — Old San Juan / Puerta de Tierra / Paseo Caribe
45
+
46
+ Coordinates on ClasificadosOnline detail pages include related listings. The
47
+ runtime therefore binds latitude and longitude from the list card only.
48
+
49
+ ## Completeness
50
+
51
+ San Juan is five ClasificadosOnline pueblos, not one island-wide search.
52
+ `location=San Juan, PR` walks those five reviewed list pages. The pueblo query
53
+ uses the page's latin-1 form encoding, so `Río Piedras` is `R%EDo`, not UTF-8.
54
+ Completeness is `partial` when any page is full, when a card is skipped because
55
+ it is not a San Juan listing, or when a card is missing a reviewed field.
56
+ Completeness is `complete` only when every requested pueblo page is a short,
57
+ fully projected page. Bath counts keep a reviewed half-step (`2 1/2` is `2.5`).
58
+ Studios that omit the bedroom icon and name themselves estudio, efficiency, or
59
+ studio project as zero bedrooms.
60
+
61
+ ## Live probe
62
+
63
+ A live ClasificadosOnline probe on 2026-09-03 for San Juan two-bedroom rentals
64
+ at or below $5500 returned 43 structured rows with canonical detail URLs,
65
+ including Hato Rey, Condado / Miramar, Santurce, Río Piedras, and Old San Juan
66
+ neighborhoods derived from coordinates or known-address overrides. First-page
67
+ pueblo results were full, so completeness was `partial`. Aquablue at 48 Luis
68
+ Muñoz Rivera is covered by the recorded fixture: the override binds Hato Rey
69
+ `00918` even when the title says Condado. Replay the live probe with:
70
+
71
+ ```bash
72
+ ghostget clasificados-web listings.search \
73
+ --input '{"location":"San Juan, PR","beds_min":2,"max_price":5500}' \
74
+ --json
75
+ ```
76
+
77
+ The command is a live network probe. Tests cover the same input against recorded
78
+ list-card fixtures so CI does not depend on the site.
79
+
80
+ ## Surfaces that are not shipped
81
+
82
+ Zillow-group HTML and first-party search endpoints from this environment
83
+ returned PerimeterX or equivalent bot challenges on zillow.com, hotpads.com,
84
+ trulia.com, apartments.com, and homes.com. No reviewed public search contract
85
+ exists for those hosts, so Ghostget does not ship a Zillow-group `listings.search`
86
+ and does not ship a DOM-click recipe.
87
+
88
+ Puerto Rico MLS public search is also not shipped. londonfoster.com's search
89
+ index is Florida inventory. puertoricorealtorsmls.com answered with a disk-full
90
+ error. stellarmls.com is a Florida member marketing site. Individual Puerto Rico
91
+ detail pages are not a reviewed search index.
92
+
93
+ Those blockers stay documented until a first-party public contract can be
94
+ reviewed. They are not capture-required stubs and they are not portable plugins.