@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,60 @@
1
+ import { createHash } from "node:crypto";
2
+
3
+ function isRecord(value: unknown): value is Record<string, unknown> {
4
+ return typeof value === "object" && value !== null && !Array.isArray(value);
5
+ }
6
+
7
+ /**
8
+ * Canonical JSON for plan binding, content addressing, and provider-owned
9
+ * semantic identities. This leaf has no catalog or runtime dependencies.
10
+ */
11
+ export function canonicalJson(value: unknown): string {
12
+ if (value === null || typeof value === "boolean" || typeof value === "string") {
13
+ return JSON.stringify(value);
14
+ }
15
+ if (typeof value === "number") {
16
+ if (!Number.isFinite(value)) {
17
+ throw new Error("canonical JSON cannot represent a non-finite number");
18
+ }
19
+ return JSON.stringify(value);
20
+ }
21
+ if (Array.isArray(value)) {
22
+ return `[${value.map((item) => canonicalJson(item)).join(",")}]`;
23
+ }
24
+ if (isRecord(value)) {
25
+ const entries = Object.entries(value)
26
+ .filter(([, item]) => item !== undefined)
27
+ .sort(([left], [right]) => left.localeCompare(right));
28
+ return `{${entries.map(([key, item]) =>
29
+ `${JSON.stringify(key)}:${canonicalJson(item)}`).join(",")}}`;
30
+ }
31
+ throw new Error("canonical JSON supports only JSON-compatible values");
32
+ }
33
+
34
+ /**
35
+ * Canonical JSON that is safe to embed as a JavaScript expression inside a
36
+ * generated page script. JSON permits raw U+2028, U+2029, and angle brackets
37
+ * inside strings; escaping them keeps the literal from terminating a script
38
+ * element or a JavaScript line. The escaped text parses to the same value.
39
+ */
40
+ export function canonicalJsonScriptLiteral(value: unknown): string {
41
+ return escapeScriptLiteral(canonicalJson(value));
42
+ }
43
+
44
+ /**
45
+ * Plain JSON with the same script-embedding escapes, for generated page
46
+ * scripts whose bindings keep their insertion order rather than the
47
+ * canonical ordering.
48
+ */
49
+ export function jsonScriptLiteral(value: unknown): string {
50
+ return escapeScriptLiteral(JSON.stringify(value));
51
+ }
52
+
53
+ function escapeScriptLiteral(json: string): string {
54
+ return json.replace(/[<>\u2028\u2029]/gu, (character) =>
55
+ `\\u${character.charCodeAt(0).toString(16).padStart(4, "0")}`);
56
+ }
57
+
58
+ export function sha256(value: string): string {
59
+ return createHash("sha256").update(value).digest("hex");
60
+ }
@@ -0,0 +1,638 @@
1
+ import { redactSensitiveText } from "@hraness/kb/clip/persist";
2
+ import {
3
+ sanitizeTerminalLine,
4
+ sanitizeTerminalText,
5
+ } from "@hraness/kb/clip/terminal";
6
+ import { existsSync } from "node:fs";
7
+ import { join } from "node:path";
8
+
9
+ import {
10
+ canonicalJson,
11
+ DOM_ACTION_TRANSPORT_DISABLED_MESSAGE,
12
+ isLocalCliOperation,
13
+ isProviderOperation,
14
+ isReviewedTemplateOperation,
15
+ isWebSessionOperation,
16
+ manifestHash,
17
+ sha256,
18
+ type GhostgetOperation,
19
+ } from "./model";
20
+ import {
21
+ getProviderContract,
22
+ providerContractHash,
23
+ } from "./provider-contracts";
24
+ import {
25
+ getLocalCliContract,
26
+ localCliContractHash,
27
+ } from "./local-cli-contracts";
28
+ import type {
29
+ ProviderPluginOperationV1,
30
+ ProviderPluginV1,
31
+ } from "./provider-plugin";
32
+ import type {
33
+ listPortableProviderPlugins,
34
+ showPortableProviderPlugin,
35
+ } from "./provider-plugin-lifecycle";
36
+ import type { ProviderPluginRegistry } from "./provider-plugin-registry";
37
+ import { providerPluginRegistry } from "./provider-plugins";
38
+ import {
39
+ ghostgetStateHome,
40
+ listInstalledManifests,
41
+ } from "./storage";
42
+ import {
43
+ getWebSessionContract,
44
+ webSessionContractHash,
45
+ } from "./web-session-contracts";
46
+
47
+ export type GhostgetCatalogCommand =
48
+ | {
49
+ readonly command: "capabilities";
50
+ readonly adapterId?: string;
51
+ readonly json: boolean;
52
+ }
53
+ | { readonly command: "plugin-list"; readonly json: boolean }
54
+ | {
55
+ readonly command: "plugin-show";
56
+ readonly id: string;
57
+ readonly json: boolean;
58
+ };
59
+
60
+ export type GhostgetCatalogOutput = {
61
+ readonly stdout: (value: string) => void;
62
+ readonly stderr: (value: string) => void;
63
+ };
64
+
65
+ const PROVIDER_PLUGIN_TRUST_NOTICE =
66
+ "Provider source plugins are trusted in-process code.";
67
+ const PORTABLE_PROVIDER_PLUGIN_TRUST_NOTICE =
68
+ "Portable plugins run as explicitly trusted child-process code; process isolation is not a hostile-code sandbox.";
69
+ const PROVIDER_PLUGIN_INSTALLATION_NOTICE =
70
+ "Adapter manifests remain non-executable data selectors; portable executable packages use the separate plugin trust store.";
71
+
72
+ function safe(value: string): string {
73
+ return sanitizeTerminalLine(redactSensitiveText(value));
74
+ }
75
+
76
+ function safeJson(
77
+ value: unknown,
78
+ reviewedPublicStrings: ReadonlySet<string> = new Set(),
79
+ ): string {
80
+ return `${JSON.stringify(value, (_key, candidate: unknown) =>
81
+ typeof candidate === "string"
82
+ ? sanitizeTerminalText(
83
+ reviewedPublicStrings.has(candidate)
84
+ ? candidate
85
+ : redactSensitiveText(candidate),
86
+ )
87
+ : candidate, 2)}\n`;
88
+ }
89
+
90
+ function print(
91
+ output: GhostgetCatalogOutput,
92
+ value: unknown,
93
+ json: boolean,
94
+ reviewedPublicStrings: ReadonlySet<string> = new Set(),
95
+ ): void {
96
+ output.stdout(
97
+ json
98
+ ? safeJson(value, reviewedPublicStrings)
99
+ : `${safe(
100
+ typeof value === "string"
101
+ ? value
102
+ : JSON.stringify(value, null, 2),
103
+ )}\n`,
104
+ );
105
+ }
106
+
107
+ function providerPluginTrustBoundary(): Record<string, unknown> {
108
+ return {
109
+ sourceExecution: "trusted-in-process",
110
+ portableExecution: "trusted-child-process",
111
+ sandboxed: false,
112
+ installedExecutablePlugins: true,
113
+ sourceRegistry: "static-source",
114
+ portableRegistry: "private-content-addressed",
115
+ notice: PROVIDER_PLUGIN_TRUST_NOTICE,
116
+ portableNotice: PORTABLE_PROVIDER_PLUGIN_TRUST_NOTICE,
117
+ installationNotice: PROVIDER_PLUGIN_INSTALLATION_NOTICE,
118
+ installedCapabilitiesCommand: "ghostget capabilities [adapter]",
119
+ };
120
+ }
121
+
122
+ function providerPluginSummary(
123
+ plugin: ProviderPluginV1,
124
+ ): Record<string, unknown> {
125
+ const operations: ProviderPluginOperationV1[] = [];
126
+ for (const binding of plugin.bindings) operations.push(...binding.operations);
127
+ return {
128
+ apiVersion: plugin.apiVersion,
129
+ id: plugin.id,
130
+ version: plugin.version,
131
+ displayName: plugin.displayName,
132
+ sourceKind: plugin.sourceKind,
133
+ bindingCount: plugin.bindings.length,
134
+ operationCount: operations.length,
135
+ contractCount: operations.reduce(
136
+ (count, operation) => count + operation.contractVersions.length,
137
+ 0,
138
+ ),
139
+ transports: [
140
+ ...new Set(plugin.bindings.map((binding) => binding.transport)),
141
+ ].sort(),
142
+ surfaces: [
143
+ ...new Set(plugin.bindings.map((binding) => binding.surfaceId)),
144
+ ].sort(),
145
+ };
146
+ }
147
+
148
+ function providerPluginView(plugin: ProviderPluginV1): Record<string, unknown> {
149
+ return {
150
+ apiVersion: plugin.apiVersion,
151
+ id: plugin.id,
152
+ version: plugin.version,
153
+ displayName: plugin.displayName,
154
+ sourceKind: plugin.sourceKind,
155
+ implementationSources: plugin.implementationSources.map(
156
+ (source) => source.label,
157
+ ),
158
+ bindings: plugin.bindings.map((binding) => ({
159
+ transport: binding.transport,
160
+ surfaceId: binding.surfaceId,
161
+ origin: binding.origin,
162
+ ...(binding.transport === "provider-api"
163
+ ? { runtimeOrigins: binding.runtimeOrigins }
164
+ : {}),
165
+ ...(binding.transport === "local-cli"
166
+ ? { localCliTool: binding.tool }
167
+ : {}),
168
+ manifestOrigins: binding.manifestOrigins,
169
+ protectedHostnameFamilies: binding.protectedHostnameFamilies,
170
+ authKinds: binding.authKinds,
171
+ subject: {
172
+ format: binding.subject.format,
173
+ hasCurrentSubjectProbe: binding.subject.probe !== undefined,
174
+ },
175
+ linkedDeviceLifecycle:
176
+ binding.transport === "linked-device"
177
+ && binding.linkedDeviceLifecycle !== undefined,
178
+ operations: binding.operations.map((operation) => ({
179
+ name: operation.name,
180
+ contractVersions: operation.contractVersions,
181
+ risk: operation.risk,
182
+ state: operation.state,
183
+ validatesSubjectInput: operation.validateSubjectInput !== undefined,
184
+ reconciliation: operation.reconciliation?.kind ?? null,
185
+ omni: operation.omni === undefined
186
+ ? null
187
+ : operation.omni.state === "supported"
188
+ ? {
189
+ state: "supported",
190
+ schemaVersion: operation.omni.schemaVersion,
191
+ materializerId: operation.omni.materializerId,
192
+ materializerVersion: operation.omni.materializerVersion,
193
+ }
194
+ : {
195
+ state: "unsupported",
196
+ reason: operation.omni.reason,
197
+ },
198
+ })),
199
+ })),
200
+ };
201
+ }
202
+
203
+ function renderProviderPluginListText(
204
+ plugins: readonly ProviderPluginV1[],
205
+ ): string {
206
+ const lines = [
207
+ `Ghostget trusted provider source plugins (${plugins.length})`,
208
+ PROVIDER_PLUGIN_TRUST_NOTICE,
209
+ PROVIDER_PLUGIN_INSTALLATION_NOTICE,
210
+ ];
211
+ for (const plugin of plugins) {
212
+ const operationCount = plugin.bindings.reduce(
213
+ (count, binding) => count + binding.operations.length,
214
+ 0,
215
+ );
216
+ lines.push(
217
+ `- ${plugin.id} ${plugin.version} (${plugin.displayName}; ${plugin.sourceKind}; ${plugin.bindings.length} binding${plugin.bindings.length === 1 ? "" : "s"}; ${operationCount} operation${operationCount === 1 ? "" : "s"})`,
218
+ );
219
+ }
220
+ lines.push(
221
+ "Run 'ghostget plugin show <id>' for routes and implementation ownership.",
222
+ "Run 'ghostget capabilities [adapter]' for installed data manifests.",
223
+ );
224
+ return `${lines.join("\n")}\n`;
225
+ }
226
+
227
+ function renderProviderPluginText(plugin: ProviderPluginV1): string {
228
+ const lines = [
229
+ "Ghostget provider source plugin",
230
+ `${plugin.displayName} (${plugin.id})`,
231
+ ` API/version: ${plugin.apiVersion}/${plugin.version}`,
232
+ ` Source: ${plugin.sourceKind}; trusted in-process; not sandboxed`,
233
+ " Implementation sources:",
234
+ ...plugin.implementationSources.map((source) => ` - ${source.label}`),
235
+ " Bindings:",
236
+ ];
237
+ for (const binding of plugin.bindings) {
238
+ const runtimeOriginLine = binding.transport === "provider-api"
239
+ ? [` Credential-bearing runtime origins: ${binding.runtimeOrigins.join(", ")}`]
240
+ : [];
241
+ const localCliToolLines = binding.transport === "local-cli"
242
+ ? [
243
+ ` Tool: ${binding.tool.id}@${binding.tool.version} (${binding.tool.versionScheme}; ${binding.tool.implementation})`,
244
+ ` Provenance: ${[
245
+ binding.tool.releaseCommit === undefined
246
+ ? null
247
+ : `commit ${binding.tool.releaseCommit}`,
248
+ binding.tool.releaseManifestSha256 === undefined
249
+ ? null
250
+ : `manifest ${binding.tool.releaseManifestSha256}`,
251
+ binding.tool.sourceUrl === undefined
252
+ ? null
253
+ : `source ${binding.tool.sourceUrl}`,
254
+ ].filter((value): value is string => value !== null).join("; ") || "not declared"}`,
255
+ ` Artifacts: ${binding.tool.artifacts.map((artifact) =>
256
+ `${artifact.platform}/${artifact.arch}:${artifact.executableSha256}`).join(", ")}`,
257
+ ]
258
+ : [];
259
+ lines.push(
260
+ ` - ${binding.transport}/${binding.surfaceId}`,
261
+ ` Origin: ${binding.origin}`,
262
+ ...runtimeOriginLine,
263
+ ...localCliToolLines,
264
+ ` Manifest origins: ${binding.manifestOrigins.join(", ")}`,
265
+ ` Protected host families: ${binding.protectedHostnameFamilies.join(", ")}`,
266
+ ` Auth: ${binding.authKinds.join(", ")}`,
267
+ ` Subject: ${binding.subject.format}; current-subject probe ${binding.subject.probe === undefined ? "not declared" : "declared"}`,
268
+ ` Operations: ${binding.operations.flatMap((operation) =>
269
+ operation.contractVersions.map(
270
+ (version) => `${operation.name}@${version}`,
271
+ )).join("; ")}`,
272
+ );
273
+ }
274
+ lines.push(
275
+ PROVIDER_PLUGIN_INSTALLATION_NOTICE,
276
+ "Run 'ghostget capabilities [adapter]' to inspect installed data manifests.",
277
+ );
278
+ return `${lines.join("\n")}\n`;
279
+ }
280
+
281
+ function renderPortableProviderPluginListText(
282
+ plugins: ReturnType<typeof listPortableProviderPlugins>,
283
+ ): string {
284
+ const lines = [
285
+ `Ghostget installed portable provider plugins (${plugins.length})`,
286
+ PORTABLE_PROVIDER_PLUGIN_TRUST_NOTICE,
287
+ ];
288
+ for (const plugin of plugins) {
289
+ lines.push(
290
+ `- ${plugin.id} ${plugin.version} (${plugin.displayName}; ${plugin.activation}; bundle ${plugin.bundleSha256.slice(0, 16)}…; ${plugin.bindings} binding${plugin.bindings === 1 ? "" : "s"}; ${plugin.operations} operation${plugin.operations === 1 ? "" : "s"})`,
291
+ );
292
+ }
293
+ lines.push(
294
+ "Run 'ghostget plugin doctor' to reverify every active package and trust record.",
295
+ );
296
+ return `${lines.join("\n")}\n`;
297
+ }
298
+
299
+ function renderPortableProviderPluginText(
300
+ plugin: NonNullable<ReturnType<typeof showPortableProviderPlugin>>,
301
+ ): string {
302
+ return [
303
+ "Ghostget portable provider plugin",
304
+ `${plugin.summary.displayName} (${plugin.summary.id})`,
305
+ ` Version: ${plugin.summary.version}`,
306
+ ` Activation: ${plugin.summary.activation}`,
307
+ ` Bundle: ${plugin.summary.bundleSha256}`,
308
+ ` Manifest: ${plugin.summary.manifestSha256}`,
309
+ " Execution: explicitly trusted child process; not a hostile-code sandbox",
310
+ ` Provenance: ${JSON.stringify(plugin.trust.provenance)}`,
311
+ ` Capabilities: ${JSON.stringify(plugin.summary.capabilities)}`,
312
+ ` Bindings: ${plugin.manifest.bindings.map((binding) =>
313
+ `${binding.transport}/${binding.surfaceId}`).join(", ")}`,
314
+ "",
315
+ ].join("\n");
316
+ }
317
+
318
+ function installedOperationTransport(
319
+ operation: GhostgetOperation,
320
+ ): "provider-api" | "web-session-api" | "local-cli" | "reviewed-template-api" {
321
+ if (isProviderOperation(operation)) return "provider-api";
322
+ if (isWebSessionOperation(operation)) return "web-session-api";
323
+ if (isLocalCliOperation(operation)) return "local-cli";
324
+ if (isReviewedTemplateOperation(operation)) return "reviewed-template-api";
325
+ throw new Error(DOM_ACTION_TRANSPORT_DISABLED_MESSAGE);
326
+ }
327
+
328
+ function reviewedTemplateHash(
329
+ recipe: Extract<GhostgetOperation, { readonly reviewedTemplate: unknown }>["reviewedTemplate"],
330
+ ): string {
331
+ return sha256(canonicalJson(recipe));
332
+ }
333
+
334
+ function listRuntimeManifests(
335
+ environment: Readonly<Record<string, string | undefined>>,
336
+ registry: ProviderPluginRegistry,
337
+ ): ReturnType<typeof listInstalledManifests> {
338
+ const stored = listInstalledManifests(environment, registry);
339
+ const storedIds = new Set(stored.map((entry) => entry.id));
340
+ const owned = registry.listOwnedManifests();
341
+ const collision = owned.find((manifest) => storedIds.has(manifest.id));
342
+ if (collision !== undefined) {
343
+ throw new Error(
344
+ `adapter ${collision.id} collides with an enabled portable provider plugin`,
345
+ );
346
+ }
347
+ return Object.freeze([
348
+ ...stored,
349
+ ...owned.map((manifest) => Object.freeze({
350
+ id: manifest.id,
351
+ result: Object.freeze({ ok: true as const, value: manifest }),
352
+ })),
353
+ ].sort((left, right) => left.id.localeCompare(right.id)));
354
+ }
355
+
356
+ function capabilitySummary(
357
+ environment: Readonly<Record<string, string | undefined>>,
358
+ registry: ProviderPluginRegistry,
359
+ reviewedPublicStrings: Set<string>,
360
+ ): readonly unknown[] {
361
+ return listRuntimeManifests(environment, registry).map(({ id, result }) =>
362
+ result.ok
363
+ ? {
364
+ id,
365
+ version: result.value.version,
366
+ displayName: result.value.displayName,
367
+ surfaceId: result.value.surfaceId ?? null,
368
+ origins: result.value.origins,
369
+ manifestHash: manifestHash(result.value),
370
+ operations: Object.entries(result.value.operations).map(
371
+ ([operationId, operation]) => {
372
+ const provider = isProviderOperation(operation)
373
+ ? getProviderContract(operation.provider, registry)
374
+ : null;
375
+ const webSession = isWebSessionOperation(operation)
376
+ ? getWebSessionContract(operation.webSession, registry)
377
+ : null;
378
+ const localCli = isLocalCliOperation(operation)
379
+ ? getLocalCliContract(operation.localCli, registry)
380
+ : null;
381
+ const reviewedTemplate = isReviewedTemplateOperation(operation)
382
+ ? operation.reviewedTemplate
383
+ : null;
384
+ if (provider !== null) {
385
+ for (const scopeSet of provider.requiredScopeSets) {
386
+ for (const scope of scopeSet) reviewedPublicStrings.add(scope);
387
+ }
388
+ }
389
+ return {
390
+ id: operationId,
391
+ description: operation.description,
392
+ risk: operation.risk,
393
+ sideEffect: operation.sideEffect,
394
+ idempotency: operation.idempotency,
395
+ dedupeWindowMs: operation.dedupeWindowMs,
396
+ transport: installedOperationTransport(operation),
397
+ input: operation.input,
398
+ ...(provider === null
399
+ ? {}
400
+ : {
401
+ provider: provider.provider,
402
+ providerAction: provider.operation,
403
+ providerContractVersion: provider.contractVersion,
404
+ providerContractHash: providerContractHash(
405
+ provider,
406
+ registry,
407
+ ),
408
+ requiredScopeSets: provider.requiredScopeSets,
409
+ coverage: provider.coverage,
410
+ implementation: provider.implementation,
411
+ }),
412
+ ...(webSession === null
413
+ ? {}
414
+ : {
415
+ site: webSession.site,
416
+ webSessionAction: webSession.operation,
417
+ webSessionContractVersion: webSession.contractVersion,
418
+ webSessionContractHash: webSessionContractHash(
419
+ webSession,
420
+ registry,
421
+ ),
422
+ state: webSession.state,
423
+ implementation: webSession.implementation,
424
+ }),
425
+ ...(localCli === null
426
+ ? {}
427
+ : {
428
+ surface: localCli.surface,
429
+ localCliAction: localCli.operation,
430
+ localCliContractVersion: localCli.contractVersion,
431
+ localCliContractHash: localCliContractHash(
432
+ localCli,
433
+ registry,
434
+ ),
435
+ localCliTool: localCli.tool,
436
+ state: localCli.state,
437
+ implementation: localCli.implementation,
438
+ }),
439
+ ...(reviewedTemplate === null
440
+ ? {}
441
+ : {
442
+ state: reviewedTemplate.state,
443
+ reviewedTemplateContractVersion:
444
+ reviewedTemplate.contractVersion,
445
+ reviewedTemplateContractHash:
446
+ reviewedTemplateHash(reviewedTemplate),
447
+ ...(reviewedTemplate.state === "capture-required"
448
+ ? { instructions: reviewedTemplate.instructions }
449
+ : {
450
+ reviewedAt: reviewedTemplate.reviewedAt,
451
+ evidenceSha256: reviewedTemplate.evidenceSha256,
452
+ origin: reviewedTemplate.template.origin,
453
+ }),
454
+ }),
455
+ };
456
+ },
457
+ ),
458
+ }
459
+ : { id, invalid: true, issues: result.issues });
460
+ }
461
+
462
+ export function runCapabilities(
463
+ command: Extract<GhostgetCatalogCommand, { readonly command: "capabilities" }>,
464
+ environment: Readonly<Record<string, string | undefined>>,
465
+ output: GhostgetCatalogOutput,
466
+ registry: ProviderPluginRegistry,
467
+ ): number {
468
+ const reviewedPublicStrings = new Set<string>();
469
+ const values = capabilitySummary(
470
+ environment,
471
+ registry,
472
+ reviewedPublicStrings,
473
+ );
474
+ const selected = command.adapterId === undefined
475
+ ? values
476
+ : values.filter((entry) =>
477
+ typeof entry === "object"
478
+ && entry !== null
479
+ && (entry as { readonly id?: unknown }).id === command.adapterId);
480
+ const found = selected.length > 0 || command.adapterId === undefined;
481
+ print(
482
+ output,
483
+ command.json ? { ok: found, adapters: selected } : selected,
484
+ command.json,
485
+ reviewedPublicStrings,
486
+ );
487
+ return found ? 0 : 3;
488
+ }
489
+
490
+ export async function runPluginList(
491
+ command: Extract<GhostgetCatalogCommand, { readonly command: "plugin-list" }>,
492
+ environment: Readonly<Record<string, string | undefined>>,
493
+ output: GhostgetCatalogOutput,
494
+ registry: ProviderPluginRegistry,
495
+ ): Promise<number> {
496
+ const { listPortableProviderPlugins } =
497
+ await import("./provider-plugin-lifecycle");
498
+ const sourcePlugins = registry.list();
499
+ const portablePlugins = listPortableProviderPlugins(environment);
500
+ const sourceIds = new Set(sourcePlugins.map((plugin) => plugin.id));
501
+ const collision = portablePlugins.find((plugin) => sourceIds.has(plugin.id));
502
+ if (collision !== undefined) {
503
+ throw new Error(
504
+ `portable plugin ${collision.id} conflicts with a trusted source plugin ID`,
505
+ );
506
+ }
507
+ if (command.json) {
508
+ output.stdout(safeJson({
509
+ ok: true,
510
+ kind: "provider-plugin-list",
511
+ trustBoundary: providerPluginTrustBoundary(),
512
+ plugins: [
513
+ ...sourcePlugins.map((plugin) => ({
514
+ ...providerPluginSummary(plugin),
515
+ execution: "trusted-in-process",
516
+ activation: "source",
517
+ })),
518
+ ...portablePlugins,
519
+ ],
520
+ }));
521
+ } else {
522
+ output.stdout(
523
+ sanitizeTerminalText(
524
+ redactSensitiveText(
525
+ `${renderProviderPluginListText(sourcePlugins)}\n`
526
+ + renderPortableProviderPluginListText(portablePlugins),
527
+ ),
528
+ ),
529
+ );
530
+ }
531
+ return 0;
532
+ }
533
+
534
+ export async function runPluginShow(
535
+ command: Extract<GhostgetCatalogCommand, { readonly command: "plugin-show" }>,
536
+ environment: Readonly<Record<string, string | undefined>>,
537
+ output: GhostgetCatalogOutput,
538
+ registry: ProviderPluginRegistry,
539
+ ): Promise<number> {
540
+ const { showPortableProviderPlugin } =
541
+ await import("./provider-plugin-lifecycle");
542
+ const sourcePlugin = registry.get(command.id);
543
+ const portablePlugin = showPortableProviderPlugin(command.id, environment);
544
+ if (sourcePlugin !== undefined && portablePlugin !== null) {
545
+ throw new Error(
546
+ `portable plugin ${command.id} conflicts with a trusted source plugin ID`,
547
+ );
548
+ }
549
+ if (sourcePlugin === undefined && portablePlugin === null) {
550
+ if (command.json) {
551
+ output.stdout(safeJson({
552
+ ok: false,
553
+ kind: "provider-plugin",
554
+ requestedId: command.id,
555
+ trustBoundary: providerPluginTrustBoundary(),
556
+ plugin: null,
557
+ }));
558
+ } else {
559
+ output.stdout(
560
+ `Ghostget provider plugin ${safe(command.id)} was not found.\n`
561
+ + "Run 'ghostget plugin list' to inspect source and portable plugins.\n",
562
+ );
563
+ }
564
+ return 3;
565
+ }
566
+ if (command.json) {
567
+ output.stdout(safeJson({
568
+ ok: true,
569
+ kind: "provider-plugin",
570
+ trustBoundary: providerPluginTrustBoundary(),
571
+ plugin: sourcePlugin === undefined
572
+ ? portablePlugin
573
+ : providerPluginView(sourcePlugin),
574
+ }));
575
+ } else {
576
+ output.stdout(
577
+ sanitizeTerminalText(
578
+ redactSensitiveText(
579
+ sourcePlugin === undefined
580
+ ? renderPortableProviderPluginText(
581
+ portablePlugin
582
+ ?? (() => {
583
+ throw new Error("portable plugin disappeared");
584
+ })(),
585
+ )
586
+ : renderProviderPluginText(sourcePlugin),
587
+ ),
588
+ ),
589
+ );
590
+ }
591
+ return 0;
592
+ }
593
+
594
+ export async function runGhostgetCatalogCommand(
595
+ command: GhostgetCatalogCommand,
596
+ environment: Readonly<Record<string, string | undefined>>,
597
+ output: GhostgetCatalogOutput,
598
+ ): Promise<number> {
599
+ try {
600
+ if (command.command === "capabilities") {
601
+ let registry = providerPluginRegistry;
602
+ const storeRoot = join(ghostgetStateHome(environment), "provider-plugins");
603
+ if (existsSync(storeRoot)) {
604
+ const { listInstalledPortableProviderPlugins } =
605
+ await import("./provider-plugin-store");
606
+ const installed = listInstalledPortableProviderPlugins(storeRoot);
607
+ if (installed.length > 0) {
608
+ const { createPortableProviderPluginCatalog } =
609
+ await import("./provider-plugin-portable-catalog");
610
+ registry = createPortableProviderPluginCatalog(
611
+ providerPluginRegistry,
612
+ environment,
613
+ ).registry;
614
+ }
615
+ }
616
+ return runCapabilities(command, environment, output, registry);
617
+ }
618
+ if (command.command === "plugin-list") {
619
+ return await runPluginList(
620
+ command,
621
+ environment,
622
+ output,
623
+ providerPluginRegistry,
624
+ );
625
+ }
626
+ return await runPluginShow(
627
+ command,
628
+ environment,
629
+ output,
630
+ providerPluginRegistry,
631
+ );
632
+ } catch (error) {
633
+ output.stderr(
634
+ `ghostget: ${safe(error instanceof Error ? error.message : String(error))}\n`,
635
+ );
636
+ return 3;
637
+ }
638
+ }