@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,413 @@
1
+ import type { CookieRecordReader } from "@hraness/kb/clip/acquire";
2
+
3
+ import type { GhostgetAuth } from "../auth";
4
+ import {
5
+ browserResultData,
6
+ createBrowserSession,
7
+ PreservedBrowserArtifactsError,
8
+ type BrowserSession,
9
+ } from "../browser";
10
+ import type { GhostgetManifest } from "../model";
11
+ import type {
12
+ WebSessionCleanupResourcePublisher,
13
+ WebSessionOperationDeadline,
14
+ } from "../web-session-execution";
15
+ import { jsonScriptLiteral } from "../canonical-json";
16
+
17
+ const X_ORIGIN = "https://x.com";
18
+ const X_HOME = `${X_ORIGIN}/home`;
19
+ const X_ASSET_ORIGIN = "https://abs.twimg.com";
20
+ const MAX_MAIN_BUNDLE_BYTES = 16 * 1024 * 1024;
21
+ const MAX_EVALUATION_OUTPUT_BYTES = 64 * 1024;
22
+ const WEB_SESSION_OPERATION_LABEL = "authenticated web operation deadline";
23
+
24
+ const xTransactionBrowserManifest = Object.freeze({
25
+ schemaVersion: 2,
26
+ id: "wrench-x-transaction-bootstrap",
27
+ version: "1.0.0",
28
+ displayName: "Ghostget X transaction bootstrap",
29
+ origins: Object.freeze([X_ORIGIN]),
30
+ browserDomains: Object.freeze(["x.com", "*.x.com", "abs.twimg.com"]),
31
+ operations: Object.freeze({}),
32
+ } satisfies GhostgetManifest);
33
+
34
+ export type XTransactionRuntimeIds = {
35
+ readonly wrapperModuleId: number;
36
+ readonly exportName: string;
37
+ readonly chunkId: number;
38
+ readonly moduleId: number;
39
+ };
40
+
41
+ export type XTransactionBrowserDependencies = {
42
+ readonly createBrowserSession?: typeof createBrowserSession;
43
+ readonly acquireCookieRecords?: CookieRecordReader;
44
+ };
45
+
46
+ function boundedWebpackId(value: string, label: string): number {
47
+ if (!/^[1-9][0-9]{0,9}$/u.test(value)) throw new Error(`${label} is not a bounded webpack ID`);
48
+ const parsed = Number(value);
49
+ if (!Number.isSafeInteger(parsed) || parsed > 2_147_483_647) {
50
+ throw new Error(`${label} is not a bounded webpack ID`);
51
+ }
52
+ return parsed;
53
+ }
54
+
55
+ /**
56
+ * Locate only the lazy transaction generator referenced by X's current
57
+ * first-party wrapper. Any minifier or module-layout drift fails closed.
58
+ */
59
+ export function parseXTransactionRuntimeIds(mainBundleText: string): XTransactionRuntimeIds {
60
+ if (mainBundleText.length < 1 || mainBundleText.length > MAX_MAIN_BUNDLE_BYTES) {
61
+ throw new Error("X transaction bootstrap main bundle exceeded its reviewed byte limit");
62
+ }
63
+ const marker = "rweb_client_transaction_id_enabled";
64
+ const firstMarker = mainBundleText.indexOf(marker);
65
+ if (firstMarker < 0 || mainBundleText.indexOf(marker, firstMarker + marker.length) >= 0) {
66
+ throw new Error("X transaction bootstrap did not expose one unique current wrapper");
67
+ }
68
+ const window = mainBundleText.slice(Math.max(0, firstMarker - 4_096), firstMarker + 4_096);
69
+ if (!window.includes("x-client-transaction-id")) {
70
+ throw new Error("X transaction bootstrap wrapper omitted its reviewed request header");
71
+ }
72
+ const references: { readonly chunk: string; readonly module: string }[] = [];
73
+ const referencePattern = /([A-Za-z_$][A-Za-z0-9_$]*)\.e\(([1-9][0-9]{0,9})\)\.then\(\1\.bind\(\1,([1-9][0-9]{0,9})\)\)/gu;
74
+ for (const match of window.matchAll(referencePattern)) {
75
+ if (match[2] !== undefined && match[3] !== undefined) {
76
+ references.push({ chunk: match[2], module: match[3] });
77
+ }
78
+ }
79
+ if (references.length !== 1) {
80
+ throw new Error("X transaction bootstrap did not expose one unique lazy runtime binding");
81
+ }
82
+ const markerInWindow = window.indexOf(marker);
83
+ const beforeMarker = window.slice(0, markerInWindow);
84
+ const modulePattern = /\},([1-9][0-9]{0,9})\(([A-Za-z_$][A-Za-z0-9_$]*),([A-Za-z_$][A-Za-z0-9_$]*),([A-Za-z_$][A-Za-z0-9_$]*)\)\{"use strict";/gu;
85
+ const modules = [...beforeMarker.matchAll(modulePattern)];
86
+ const wrapper = modules.at(-1);
87
+ if (wrapper?.[1] === undefined || wrapper[3] === undefined || wrapper[4] === undefined) {
88
+ throw new Error("X transaction bootstrap did not expose its current wrapper module");
89
+ }
90
+ const helperMatch = /\["x-client-transaction-id"\]=await ([A-Za-z_$][A-Za-z0-9_$]*)\(/u.exec(window);
91
+ const helperName = helperMatch?.[1];
92
+ if (helperName === undefined) {
93
+ throw new Error("X transaction bootstrap did not expose its current wrapper helper");
94
+ }
95
+ const exportMapPattern = new RegExp(`${wrapper[4]}\\.d\\(${wrapper[3]},\\{([^}]{1,2048})\\}\\)`, "u");
96
+ const exportMap = exportMapPattern.exec(window)?.[1];
97
+ if (exportMap === undefined) throw new Error("X transaction bootstrap did not expose its wrapper exports");
98
+ const escapedHelper = helperName.replace(/[.*+?^${}()|[\]\\]/gu, "\\$&");
99
+ const exportMatches = [...exportMap.matchAll(new RegExp(`(?:^|,)([A-Za-z_$][A-Za-z0-9_$]*):\\(\\)=>${escapedHelper}(?=,|$)`, "gu"))];
100
+ const exportName = exportMatches.length === 1 ? exportMatches[0]?.[1] : undefined;
101
+ if (exportName === undefined) {
102
+ throw new Error("X transaction bootstrap did not expose one unique exported wrapper helper");
103
+ }
104
+ const reference = references[0]!;
105
+ return Object.freeze({
106
+ wrapperModuleId: boundedWebpackId(wrapper[1], "X transaction wrapper module ID"),
107
+ exportName,
108
+ chunkId: boundedWebpackId(reference.chunk, "X transaction chunk ID"),
109
+ moduleId: boundedWebpackId(reference.module, "X transaction module ID"),
110
+ });
111
+ }
112
+
113
+ function exactMutationPath(value: string): string {
114
+ if (!/^\/i\/api\/graphql\/[A-Za-z0-9_-]{8,128}\/[A-Za-z][A-Za-z0-9_]{1,127}$/u.test(value)) {
115
+ throw new Error("X transaction bootstrap path is not one exact reviewed GraphQL mutation");
116
+ }
117
+ return value;
118
+ }
119
+
120
+ function exactMainBundlePath(value: string | URL): string {
121
+ let url: URL;
122
+ try {
123
+ url = value instanceof URL ? new URL(value.href) : new URL(value);
124
+ } catch {
125
+ throw new Error("X transaction bootstrap main bundle URL is invalid");
126
+ }
127
+ if (
128
+ url.origin !== X_ASSET_ORIGIN
129
+ || url.username !== ""
130
+ || url.password !== ""
131
+ || url.search !== ""
132
+ || url.hash !== ""
133
+ || !/^\/responsive-web\/client-web\/main\.[A-Za-z0-9_-]{6,128}\.js$/u.test(url.pathname)
134
+ ) throw new Error("X transaction bootstrap main bundle URL escaped its reviewed asset path");
135
+ return url.pathname;
136
+ }
137
+
138
+ function containedBrowserAuth(auth: GhostgetAuth): GhostgetAuth {
139
+ if (auth.kind === "cookie-source" || auth.kind === "cookies-file") return auth;
140
+ if (auth.kind === "browser-profile" && auth.cookieSource !== undefined) {
141
+ return {
142
+ schemaVersion: 1,
143
+ id: auth.id,
144
+ kind: "cookie-source",
145
+ source: auth.cookieSource,
146
+ ...(auth.cookieProfile === undefined ? {} : { profile: auth.cookieProfile }),
147
+ ...(auth.subject === undefined ? {} : { subject: auth.subject }),
148
+ };
149
+ }
150
+ throw new Error("X transaction bootstrap requires target-filtered cookie auth");
151
+ }
152
+
153
+ function transactionEvaluationSource(input: {
154
+ readonly method: "POST";
155
+ readonly path: string;
156
+ readonly mainBundlePath: string;
157
+ readonly runtime: XTransactionRuntimeIds;
158
+ }): string {
159
+ const bound = jsonScriptLiteral({
160
+ method: input.method,
161
+ path: exactMutationPath(input.path),
162
+ mainBundlePath: input.mainBundlePath,
163
+ wrapperModuleId: input.runtime.wrapperModuleId,
164
+ exportName: input.runtime.exportName,
165
+ chunkId: input.runtime.chunkId,
166
+ moduleId: input.runtime.moduleId,
167
+ });
168
+ return `(async()=>{const input=${bound};if(location.origin!=="${X_ORIGIN}")throw new Error("unexpected X origin");const mains=Array.from(document.scripts).map((node)=>{try{return new URL(node.src,location.href)}catch{return null}}).filter((url)=>url!==null&&url.origin==="${X_ASSET_ORIGIN}"&&/^\\/responsive-web\\/client-web\\/main\\.[A-Za-z0-9_-]{6,128}\\.js$/.test(url.pathname));if(mains.length!==1||mains[0].pathname!==input.mainBundlePath)throw new Error("X main runtime drifted");const chunks=globalThis.webpackChunk_twitter_responsive_web;if(!Array.isArray(chunks)||typeof chunks.push!=="function")throw new Error("X webpack runtime is unavailable");let runtime=null;chunks.push([["wrench_x_client_transaction_bootstrap"],{},(candidate)=>{runtime=candidate}]);if(typeof runtime!=="function")throw new Error("X webpack runtime is unavailable");const exports=runtime(input.wrapperModuleId);if(exports===null||typeof exports!=="object")throw new Error("X transaction wrapper is unavailable");const helper=exports[input.exportName];if(typeof helper!=="function")throw new Error("X transaction wrapper helper is unavailable");const value=await helper(location.host,input.path,input.method);if(typeof value!=="string"||value.length<8||value.length>2048)throw new Error("X transaction wrapper returned an invalid value");try{if(atob(value).startsWith("e:"))throw new Error("X transaction wrapper reported an error")}catch(error){if(error instanceof Error&&error.message==="X transaction wrapper reported an error")throw error}return value})()`;
169
+ }
170
+
171
+ function currentBrowserUrl(record: Record<string, unknown>): URL {
172
+ const data = browserResultData(record);
173
+ if (typeof data !== "object" || data === null || Array.isArray(data)) {
174
+ throw new Error("X transaction bootstrap browser omitted its current URL");
175
+ }
176
+ const value = (data as Record<string, unknown>).url;
177
+ if (typeof value !== "string") throw new Error("X transaction bootstrap browser omitted its current URL");
178
+ let url: URL;
179
+ try {
180
+ url = new URL(value);
181
+ } catch {
182
+ throw new Error("X transaction bootstrap browser returned an invalid current URL");
183
+ }
184
+ if (url.origin !== X_ORIGIN || url.username !== "" || url.password !== "") {
185
+ throw new Error("X transaction bootstrap browser left its reviewed origin");
186
+ }
187
+ return url;
188
+ }
189
+
190
+ function transactionId(record: Record<string, unknown>): string {
191
+ const data = browserResultData(record);
192
+ if (typeof data !== "object" || data === null || Array.isArray(data)) {
193
+ throw new Error("X transaction bootstrap returned a malformed evaluation envelope");
194
+ }
195
+ const envelope = data as Record<string, unknown>;
196
+ if (typeof envelope.origin !== "string") {
197
+ throw new Error("X transaction bootstrap evaluation omitted its origin");
198
+ }
199
+ let origin: URL;
200
+ try {
201
+ origin = new URL(envelope.origin);
202
+ } catch {
203
+ throw new Error("X transaction bootstrap evaluation returned an invalid origin");
204
+ }
205
+ if (origin.origin !== X_ORIGIN || origin.username !== "" || origin.password !== "") {
206
+ throw new Error("X transaction bootstrap evaluation escaped its reviewed origin");
207
+ }
208
+ const value = envelope.result;
209
+ if (typeof value !== "string" || !/^[A-Za-z0-9_+/=-]{8,2048}$/u.test(value)) {
210
+ throw new Error("X transaction bootstrap returned an invalid request value");
211
+ }
212
+ return value;
213
+ }
214
+
215
+ type BrowserFinalizationResult = {
216
+ readonly closeVerified: boolean;
217
+ readonly cleanupVerified: boolean;
218
+ readonly failures: readonly unknown[];
219
+ };
220
+
221
+ async function finalizeBrowserSession(
222
+ session: BrowserSession,
223
+ ): Promise<BrowserFinalizationResult> {
224
+ const failures: unknown[] = [];
225
+ let closeVerified = false;
226
+ try {
227
+ await session.close();
228
+ closeVerified = true;
229
+ } catch (error) {
230
+ failures.push(error);
231
+ }
232
+ let cleanupVerified = false;
233
+ try {
234
+ await session.cleanup();
235
+ cleanupVerified = true;
236
+ } catch (error) {
237
+ failures.push(error);
238
+ }
239
+ return Object.freeze({
240
+ closeVerified,
241
+ cleanupVerified,
242
+ failures: Object.freeze(failures),
243
+ });
244
+ }
245
+
246
+ function remainingTimeoutMs(
247
+ timeoutMs: number,
248
+ operationDeadline: WebSessionOperationDeadline | undefined,
249
+ ): number {
250
+ if (operationDeadline === undefined) return timeoutMs;
251
+ operationDeadline.throwIfUnavailable(WEB_SESSION_OPERATION_LABEL);
252
+ const remaining = Math.min(timeoutMs, operationDeadline.remainingTimeMs());
253
+ if (remaining < 1) {
254
+ operationDeadline.throwIfUnavailable(WEB_SESSION_OPERATION_LABEL);
255
+ throw new Error("X transaction bootstrap timed out");
256
+ }
257
+ return remaining;
258
+ }
259
+
260
+ function runWithinOperationDeadline<T>(
261
+ operationDeadline: WebSessionOperationDeadline | undefined,
262
+ work: () => Promise<T>,
263
+ ): Promise<T> {
264
+ return operationDeadline === undefined
265
+ ? work()
266
+ : operationDeadline.run(work, WEB_SESSION_OPERATION_LABEL);
267
+ }
268
+
269
+ function finalizeBrowserSessionWithoutBlocking(session: BrowserSession): void {
270
+ void finalizeBrowserSession(session);
271
+ }
272
+
273
+ /** Generate one ephemeral value. The caller may place it only on this exact in-origin mutation request. */
274
+ export async function generateXClientTransactionId(input: {
275
+ readonly auth: GhostgetAuth;
276
+ readonly mainBundleText: string;
277
+ readonly mainBundleUrl: string | URL;
278
+ readonly method: "POST";
279
+ readonly path: string;
280
+ readonly timeoutMs: number;
281
+ readonly maxOutputBytes: number;
282
+ readonly operationDeadline?: WebSessionOperationDeadline;
283
+ readonly publishCleanupResource?: WebSessionCleanupResourcePublisher;
284
+ readonly dependencies?: XTransactionBrowserDependencies;
285
+ }): Promise<string> {
286
+ input.operationDeadline?.throwIfUnavailable(WEB_SESSION_OPERATION_LABEL);
287
+ if (input.method !== "POST") throw new Error("X transaction bootstrap supports mutations only");
288
+ const path = exactMutationPath(input.path);
289
+ const mainBundlePath = exactMainBundlePath(input.mainBundleUrl);
290
+ const runtime = parseXTransactionRuntimeIds(input.mainBundleText);
291
+ const createSession = input.dependencies?.createBrowserSession ?? createBrowserSession;
292
+ const creation = createSession(
293
+ xTransactionBrowserManifest,
294
+ containedBrowserAuth(input.auth),
295
+ {
296
+ headed: false,
297
+ timeoutMs: remainingTimeoutMs(input.timeoutMs, input.operationDeadline),
298
+ maxOutputBytes: Math.min(input.maxOutputBytes, MAX_EVALUATION_OUTPUT_BYTES),
299
+ allowCodeOwnedEvaluation: true,
300
+ ...(input.operationDeadline === undefined
301
+ ? {}
302
+ : { operationDeadline: input.operationDeadline }),
303
+ ...(input.dependencies?.acquireCookieRecords === undefined
304
+ ? {}
305
+ : { dependencies: { acquireCookieRecords: input.dependencies.acquireCookieRecords } }),
306
+ ...(input.publishCleanupResource === undefined
307
+ ? {}
308
+ : { publishCleanupResource: input.publishCleanupResource }),
309
+ },
310
+ );
311
+ let session: BrowserSession;
312
+ try {
313
+ // The production creator owns deadline-aware teardown and must be allowed
314
+ // to report its cleanup outcome. A test-only injected creator is still
315
+ // outer-raced so a broken seam cannot defeat the kernel deadline.
316
+ session = input.dependencies?.createBrowserSession === undefined
317
+ ? await creation
318
+ : await runWithinOperationDeadline(
319
+ input.operationDeadline,
320
+ () => creation,
321
+ );
322
+ } catch (error) {
323
+ if (
324
+ input.operationDeadline !== undefined
325
+ && input.dependencies?.createBrowserSession !== undefined
326
+ ) {
327
+ void creation.then(
328
+ (lateSession) => finalizeBrowserSessionWithoutBlocking(lateSession),
329
+ () => undefined,
330
+ );
331
+ }
332
+ throw error;
333
+ }
334
+ let generated: string | undefined;
335
+ let failure: unknown;
336
+ let failed = false;
337
+ const activeBatchState: {
338
+ current: Promise<readonly Record<string, unknown>[]> | null;
339
+ } = { current: null };
340
+ const runBatch = (
341
+ commands: readonly (readonly string[])[],
342
+ ): Promise<readonly Record<string, unknown>[]> => {
343
+ const batch = session.runBatch(
344
+ commands,
345
+ remainingTimeoutMs(input.timeoutMs, input.operationDeadline),
346
+ MAX_EVALUATION_OUTPUT_BYTES,
347
+ );
348
+ activeBatchState.current = batch;
349
+ void batch.then(
350
+ () => {
351
+ if (activeBatchState.current === batch) activeBatchState.current = null;
352
+ },
353
+ () => {
354
+ if (activeBatchState.current === batch) activeBatchState.current = null;
355
+ },
356
+ );
357
+ return runWithinOperationDeadline(
358
+ input.operationDeadline,
359
+ () => batch,
360
+ );
361
+ };
362
+ try {
363
+ await runBatch([["open", X_HOME]]);
364
+ const [urlRecord] = await runBatch([["get", "url"]]);
365
+ if (urlRecord === undefined) throw new Error("X transaction bootstrap browser omitted its current URL");
366
+ currentBrowserUrl(urlRecord);
367
+ const [evaluationRecord] = await runBatch([[
368
+ "eval",
369
+ transactionEvaluationSource({ method: "POST", path, mainBundlePath, runtime }),
370
+ ]]);
371
+ if (evaluationRecord === undefined) throw new Error("X transaction bootstrap browser omitted its evaluation result");
372
+ generated = transactionId(evaluationRecord);
373
+ } catch (error) {
374
+ failed = true;
375
+ failure = error;
376
+ }
377
+ // Never close concurrently with an injected abort-ignorant batch. The
378
+ // production BrowserSession also tracks its underlying command cleanup, so
379
+ // close remains the authoritative quiescence gate after its outer promise
380
+ // has observed cancellation.
381
+ const activeBatch = activeBatchState.current;
382
+ if (activeBatch !== null) {
383
+ await activeBatch.catch(() => undefined);
384
+ }
385
+ const finalization = await finalizeBrowserSession(session);
386
+ if (!finalization.closeVerified || !finalization.cleanupVerified) {
387
+ const cleanupEvidence = (
388
+ finalization.closeVerified
389
+ && !finalization.cleanupVerified
390
+ && session.cleanupResourceIdentity !== undefined
391
+ )
392
+ ? Object.freeze({
393
+ kind: "agent-browser-closed-artifacts-v1" as const,
394
+ resource: session.cleanupResourceIdentity,
395
+ })
396
+ : undefined;
397
+ throw new PreservedBrowserArtifactsError(
398
+ "X transaction bootstrap browser finalization failed; private artifacts were preserved",
399
+ session.recoveryHandle ?? "session=x-transaction-bootstrap;artifacts=unknown",
400
+ new AggregateError(
401
+ [
402
+ ...(failed ? [failure] : []),
403
+ ...finalization.failures,
404
+ ],
405
+ "X transaction bootstrap browser finalization failed",
406
+ ),
407
+ cleanupEvidence,
408
+ );
409
+ }
410
+ if (failed) throw failure;
411
+ if (generated === undefined) throw new Error("X transaction bootstrap produced no request value");
412
+ return generated;
413
+ }