@jackwener/opencli 1.6.1 → 1.6.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 (384) hide show
  1. package/CONTRIBUTING.md +1 -1
  2. package/README.md +27 -45
  3. package/README.zh-CN.md +32 -34
  4. package/autoresearch/browse-tasks.json +18 -20
  5. package/autoresearch/commands/debug.ts +163 -0
  6. package/autoresearch/commands/fix.ts +145 -0
  7. package/autoresearch/commands/plan.ts +88 -0
  8. package/autoresearch/commands/run.ts +138 -0
  9. package/autoresearch/config.ts +82 -0
  10. package/autoresearch/engine.ts +359 -0
  11. package/autoresearch/eval-all.ts +127 -0
  12. package/autoresearch/eval-browse.ts +1 -1
  13. package/autoresearch/eval-publish.ts +238 -0
  14. package/autoresearch/eval-save.ts +249 -0
  15. package/autoresearch/eval-skill.ts +14 -8
  16. package/autoresearch/eval-v2ex.ts +220 -0
  17. package/autoresearch/eval-zhihu.ts +230 -0
  18. package/autoresearch/logger.ts +69 -0
  19. package/autoresearch/presets/combined-reliability.ts +27 -0
  20. package/autoresearch/presets/index.ts +23 -0
  21. package/autoresearch/presets/operate-reliability.ts +24 -0
  22. package/autoresearch/presets/save-reliability.ts +26 -0
  23. package/autoresearch/presets/skill-quality.ts +20 -0
  24. package/autoresearch/presets/v2ex-reliability.ts +24 -0
  25. package/autoresearch/presets/zhihu-reliability.ts +25 -0
  26. package/autoresearch/publish-tasks.json +345 -0
  27. package/autoresearch/run-save.sh +11 -0
  28. package/autoresearch/save-adapters/xhs-explore-deep.ts +64 -0
  29. package/autoresearch/save-adapters/xhs-note-comments.ts +61 -0
  30. package/autoresearch/save-adapters/xhs-search-full.ts +62 -0
  31. package/autoresearch/save-adapters/zhihu-hot-detail.ts +52 -0
  32. package/autoresearch/save-adapters/zhihu-question-full.ts +57 -0
  33. package/autoresearch/save-adapters/zhihu-search-detail.ts +53 -0
  34. package/autoresearch/save-tasks.json +281 -0
  35. package/autoresearch/v2ex-tasks.json +899 -0
  36. package/autoresearch/zhihu-tasks.json +848 -0
  37. package/dist/browser/base-page.d.ts +4 -2
  38. package/dist/browser/base-page.js +37 -4
  39. package/dist/browser/bridge.js +10 -8
  40. package/dist/browser/cdp.js +2 -6
  41. package/dist/browser/daemon-client.d.ts +11 -1
  42. package/dist/browser/daemon-client.js +3 -0
  43. package/dist/browser/dom-helpers.d.ts +4 -2
  44. package/dist/browser/dom-helpers.js +42 -31
  45. package/dist/browser/dom-snapshot.js +23 -1
  46. package/dist/browser/page.d.ts +7 -2
  47. package/dist/browser/page.js +112 -30
  48. package/dist/browser.test.js +1 -1
  49. package/dist/build-manifest.d.ts +1 -0
  50. package/dist/build-manifest.js +1 -0
  51. package/dist/cli-manifest.json +1135 -184
  52. package/dist/cli.d.ts +2 -0
  53. package/dist/cli.js +48 -7
  54. package/dist/cli.test.d.ts +1 -0
  55. package/dist/cli.test.js +88 -0
  56. package/dist/clis/1688/item.d.ts +70 -0
  57. package/dist/clis/1688/item.js +187 -0
  58. package/dist/clis/1688/item.test.d.ts +1 -0
  59. package/dist/clis/1688/item.test.js +67 -0
  60. package/dist/clis/1688/search.d.ts +56 -0
  61. package/dist/clis/1688/search.js +309 -0
  62. package/dist/clis/1688/search.test.d.ts +1 -0
  63. package/dist/clis/1688/search.test.js +75 -0
  64. package/dist/clis/1688/shared.d.ts +112 -0
  65. package/dist/clis/1688/shared.js +514 -0
  66. package/dist/clis/1688/shared.test.d.ts +1 -0
  67. package/dist/clis/1688/shared.test.js +57 -0
  68. package/dist/clis/1688/store.d.ts +45 -0
  69. package/dist/clis/1688/store.js +226 -0
  70. package/dist/clis/1688/store.test.d.ts +1 -0
  71. package/dist/clis/1688/store.test.js +62 -0
  72. package/dist/clis/amazon/bestsellers.d.ts +0 -20
  73. package/dist/clis/amazon/bestsellers.js +6 -129
  74. package/dist/clis/amazon/bestsellers.test.js +12 -3
  75. package/dist/clis/amazon/movers-shakers.d.ts +1 -0
  76. package/dist/clis/amazon/movers-shakers.js +7 -0
  77. package/dist/clis/amazon/new-releases.d.ts +1 -0
  78. package/dist/clis/amazon/new-releases.js +7 -0
  79. package/dist/clis/amazon/rankings.d.ts +59 -0
  80. package/dist/clis/amazon/rankings.js +226 -0
  81. package/dist/clis/amazon/rankings.test.d.ts +1 -0
  82. package/dist/clis/amazon/rankings.test.js +41 -0
  83. package/dist/clis/amazon/shared.d.ts +11 -0
  84. package/dist/clis/amazon/shared.js +121 -11
  85. package/dist/clis/amazon/shared.test.js +11 -0
  86. package/dist/clis/bilibili/comments.js +2 -2
  87. package/dist/clis/bilibili/comments.test.js +3 -2
  88. package/dist/clis/bilibili/download.js +2 -1
  89. package/dist/clis/bilibili/subtitle.js +4 -3
  90. package/dist/clis/bilibili/subtitle.test.js +2 -1
  91. package/dist/clis/bilibili/utils.d.ts +5 -0
  92. package/dist/clis/bilibili/utils.js +30 -0
  93. package/dist/clis/bilibili/utils.test.d.ts +1 -0
  94. package/dist/clis/bilibili/utils.test.js +17 -0
  95. package/dist/clis/douban/marks.js +1 -1
  96. package/dist/clis/douban/subject.yaml +50 -19
  97. package/dist/clis/doubao/utils.js +32 -12
  98. package/dist/clis/douyin/_shared/browser-fetch.test.js +0 -1
  99. package/dist/clis/douyin/_shared/transcode.test.js +0 -2
  100. package/dist/clis/douyin/draft.test.js +0 -2
  101. package/dist/clis/facebook/search.test.js +0 -2
  102. package/dist/clis/gemini/ask.js +9 -3
  103. package/dist/clis/gemini/ask.test.d.ts +1 -0
  104. package/dist/clis/gemini/ask.test.js +100 -0
  105. package/dist/clis/gemini/reply-state.test.d.ts +1 -0
  106. package/dist/clis/gemini/reply-state.test.js +641 -0
  107. package/dist/clis/gemini/utils.d.ts +44 -1
  108. package/dist/clis/gemini/utils.js +528 -61
  109. package/dist/clis/gemini/utils.test.js +149 -2
  110. package/dist/clis/hupu/detail.d.ts +1 -0
  111. package/dist/clis/hupu/detail.js +72 -0
  112. package/dist/clis/hupu/hot.yaml +43 -0
  113. package/dist/clis/hupu/like.d.ts +1 -0
  114. package/dist/clis/hupu/like.js +75 -0
  115. package/dist/clis/hupu/reply.d.ts +1 -0
  116. package/dist/clis/hupu/reply.js +71 -0
  117. package/dist/clis/hupu/search.d.ts +1 -0
  118. package/dist/clis/hupu/search.js +59 -0
  119. package/dist/clis/hupu/unlike.d.ts +1 -0
  120. package/dist/clis/hupu/unlike.js +75 -0
  121. package/dist/clis/hupu/utils.d.ts +20 -0
  122. package/dist/clis/hupu/utils.js +319 -0
  123. package/dist/clis/instagram/_shared/private-publish.d.ts +138 -0
  124. package/dist/clis/instagram/_shared/private-publish.js +1030 -0
  125. package/dist/clis/instagram/_shared/private-publish.test.d.ts +1 -0
  126. package/dist/clis/instagram/_shared/private-publish.test.js +705 -0
  127. package/dist/clis/instagram/_shared/protocol-capture.d.ts +26 -0
  128. package/dist/clis/instagram/_shared/protocol-capture.js +282 -0
  129. package/dist/clis/instagram/_shared/protocol-capture.test.d.ts +1 -0
  130. package/dist/clis/instagram/_shared/protocol-capture.test.js +114 -0
  131. package/dist/clis/instagram/_shared/runtime-info.d.ts +9 -0
  132. package/dist/clis/instagram/_shared/runtime-info.js +81 -0
  133. package/dist/clis/instagram/note.d.ts +1 -0
  134. package/dist/clis/instagram/note.js +222 -0
  135. package/dist/clis/instagram/note.test.d.ts +1 -0
  136. package/dist/clis/instagram/note.test.js +81 -0
  137. package/dist/clis/instagram/post.d.ts +4 -0
  138. package/dist/clis/instagram/post.js +1496 -0
  139. package/dist/clis/instagram/post.test.d.ts +1 -0
  140. package/dist/clis/instagram/post.test.js +1647 -0
  141. package/dist/clis/instagram/reel.d.ts +1 -0
  142. package/dist/clis/instagram/reel.js +826 -0
  143. package/dist/clis/instagram/reel.test.d.ts +1 -0
  144. package/dist/clis/instagram/reel.test.js +167 -0
  145. package/dist/clis/instagram/story.d.ts +1 -0
  146. package/dist/clis/instagram/story.js +115 -0
  147. package/dist/clis/instagram/story.test.d.ts +1 -0
  148. package/dist/clis/instagram/story.test.js +167 -0
  149. package/dist/clis/sinafinance/stock-rank.d.ts +4 -0
  150. package/dist/clis/sinafinance/stock-rank.js +65 -0
  151. package/dist/clis/substack/utils.test.js +0 -2
  152. package/dist/clis/twitter/post.js +72 -45
  153. package/dist/clis/twitter/post.test.d.ts +1 -0
  154. package/dist/clis/twitter/post.test.js +116 -0
  155. package/dist/clis/twitter/reply.d.ts +12 -0
  156. package/dist/clis/twitter/reply.js +257 -35
  157. package/dist/clis/twitter/reply.test.d.ts +1 -0
  158. package/dist/clis/twitter/reply.test.js +151 -0
  159. package/dist/clis/xianyu/chat.d.ts +7 -0
  160. package/dist/clis/xianyu/chat.js +146 -0
  161. package/dist/clis/xianyu/chat.test.d.ts +1 -0
  162. package/dist/clis/xianyu/chat.test.js +15 -0
  163. package/dist/clis/xianyu/item.d.ts +7 -0
  164. package/dist/clis/xianyu/item.js +152 -0
  165. package/dist/clis/xianyu/item.test.d.ts +1 -0
  166. package/dist/clis/xianyu/item.test.js +56 -0
  167. package/dist/clis/xianyu/search.d.ts +10 -0
  168. package/dist/clis/xianyu/search.js +134 -0
  169. package/dist/clis/xianyu/search.test.d.ts +1 -0
  170. package/dist/clis/xianyu/search.test.js +17 -0
  171. package/dist/clis/xianyu/utils.d.ts +1 -0
  172. package/dist/clis/xianyu/utils.js +8 -0
  173. package/dist/clis/xiaoe/catalog.yaml +129 -0
  174. package/dist/clis/xiaoe/content.yaml +43 -0
  175. package/dist/clis/xiaoe/courses.yaml +73 -0
  176. package/dist/clis/xiaoe/detail.yaml +39 -0
  177. package/dist/clis/xiaoe/play-url.yaml +124 -0
  178. package/dist/clis/xiaohongshu/comments.test.js +0 -2
  179. package/dist/clis/xiaohongshu/creator-note-detail.test.js +0 -2
  180. package/dist/clis/xiaohongshu/creator-notes.test.js +0 -2
  181. package/dist/clis/xiaohongshu/download.test.js +0 -2
  182. package/dist/clis/xiaohongshu/note.test.js +0 -2
  183. package/dist/clis/xiaohongshu/publish.test.js +0 -2
  184. package/dist/clis/xiaohongshu/search.js +29 -20
  185. package/dist/clis/xiaohongshu/search.test.js +56 -48
  186. package/dist/clis/yuanbao/ask.d.ts +21 -0
  187. package/dist/clis/yuanbao/ask.js +427 -0
  188. package/dist/clis/yuanbao/ask.test.d.ts +1 -0
  189. package/dist/clis/yuanbao/ask.test.js +124 -0
  190. package/dist/clis/yuanbao/new.d.ts +1 -0
  191. package/dist/clis/yuanbao/new.js +70 -0
  192. package/dist/clis/yuanbao/new.test.d.ts +1 -0
  193. package/dist/clis/yuanbao/new.test.js +30 -0
  194. package/dist/clis/yuanbao/shared.d.ts +13 -0
  195. package/dist/clis/yuanbao/shared.js +49 -0
  196. package/dist/clis/zhihu/question.js +30 -19
  197. package/dist/clis/zhihu/question.test.js +34 -16
  198. package/dist/commanderAdapter.js +8 -4
  199. package/dist/commanderAdapter.test.js +42 -0
  200. package/dist/completion.js +3 -1
  201. package/dist/completion.test.d.ts +1 -0
  202. package/dist/completion.test.js +23 -0
  203. package/dist/doctor.js +1 -1
  204. package/dist/electron-apps.d.ts +2 -0
  205. package/dist/electron-apps.js +7 -1
  206. package/dist/errors.js +1 -1
  207. package/dist/execution.js +25 -35
  208. package/dist/explore.js +1 -1
  209. package/dist/launcher.d.ts +4 -0
  210. package/dist/launcher.js +64 -8
  211. package/dist/launcher.test.js +88 -7
  212. package/dist/output.d.ts +2 -0
  213. package/dist/output.js +10 -1
  214. package/dist/output.test.d.ts +0 -3
  215. package/dist/output.test.js +59 -92
  216. package/dist/pipeline/executor.test.js +0 -2
  217. package/dist/pipeline/steps/download.test.js +0 -2
  218. package/dist/registry.d.ts +2 -0
  219. package/dist/serialization.d.ts +1 -0
  220. package/dist/serialization.js +1 -0
  221. package/dist/types.d.ts +9 -2
  222. package/docs/.vitepress/config.mts +4 -0
  223. package/docs/adapters/browser/1688.md +52 -0
  224. package/docs/adapters/browser/36kr.md +2 -1
  225. package/docs/adapters/browser/doubao.md +5 -1
  226. package/docs/adapters/browser/hupu.md +53 -0
  227. package/docs/adapters/browser/sinafinance.md +32 -2
  228. package/docs/adapters/browser/weibo.md +6 -1
  229. package/docs/adapters/browser/wikipedia.md +2 -0
  230. package/docs/adapters/browser/xianyu.md +42 -0
  231. package/docs/adapters/browser/xiaoe.md +44 -0
  232. package/docs/adapters/browser/yuanbao.md +64 -0
  233. package/docs/adapters/index.md +14 -5
  234. package/docs/comparison.md +1 -1
  235. package/docs/developer/ai-workflow.md +2 -2
  236. package/docs/developer/contributing.md +1 -1
  237. package/docs/developer/testing.md +2 -0
  238. package/docs/guide/plugins.md +1 -0
  239. package/docs/guide/troubleshooting.md +11 -0
  240. package/docs/superpowers/specs/2026-04-03-v2ex-autoresearch-design.md +41 -0
  241. package/docs/zh/guide/plugins.md +1 -0
  242. package/extension/dist/background.js +1127 -0
  243. package/extension/src/background.test.ts +39 -0
  244. package/extension/src/background.ts +223 -34
  245. package/extension/src/cdp.ts +194 -4
  246. package/extension/src/protocol.ts +22 -1
  247. package/package.json +3 -2
  248. package/scripts/postinstall.js +1 -1
  249. package/skills/opencli-explorer/SKILL.md +1 -1
  250. package/skills/opencli-oneshot/SKILL.md +2 -2
  251. package/skills/opencli-operate/SKILL.md +120 -27
  252. package/skills/opencli-usage/SKILL.md +31 -20
  253. package/skills/opencli-usage/browser.md +114 -16
  254. package/skills/opencli-usage/public-api.md +32 -3
  255. package/skills/smart-search/SKILL.md +156 -0
  256. package/skills/smart-search/references/sources-ai.md +74 -0
  257. package/skills/smart-search/references/sources-info.md +43 -0
  258. package/skills/smart-search/references/sources-media.md +50 -0
  259. package/skills/smart-search/references/sources-other.md +42 -0
  260. package/skills/smart-search/references/sources-shopping.md +31 -0
  261. package/skills/smart-search/references/sources-social.md +51 -0
  262. package/skills/smart-search/references/sources-tech.md +42 -0
  263. package/skills/smart-search/references/sources-travel.md +20 -0
  264. package/src/browser/base-page.ts +41 -6
  265. package/src/browser/bridge.ts +11 -8
  266. package/src/browser/cdp.ts +1 -8
  267. package/src/browser/daemon-client.ts +11 -1
  268. package/src/browser/dom-helpers.ts +43 -31
  269. package/src/browser/dom-snapshot.ts +23 -1
  270. package/src/browser/page.ts +115 -31
  271. package/src/browser.test.ts +1 -1
  272. package/src/build-manifest.ts +2 -0
  273. package/src/cli.test.ts +133 -0
  274. package/src/cli.ts +73 -11
  275. package/src/clis/1688/item.test.ts +69 -0
  276. package/src/clis/1688/item.ts +282 -0
  277. package/src/clis/1688/search.test.ts +81 -0
  278. package/src/clis/1688/search.ts +402 -0
  279. package/src/clis/1688/shared.test.ts +75 -0
  280. package/src/clis/1688/shared.ts +623 -0
  281. package/src/clis/1688/store.test.ts +69 -0
  282. package/src/clis/1688/store.ts +300 -0
  283. package/src/clis/amazon/bestsellers.test.ts +12 -3
  284. package/src/clis/amazon/bestsellers.ts +6 -178
  285. package/src/clis/amazon/movers-shakers.ts +8 -0
  286. package/src/clis/amazon/new-releases.ts +8 -0
  287. package/src/clis/amazon/rankings.test.ts +47 -0
  288. package/src/clis/amazon/rankings.ts +312 -0
  289. package/src/clis/amazon/shared.test.ts +16 -0
  290. package/src/clis/amazon/shared.ts +134 -12
  291. package/src/clis/bilibili/comments.test.ts +4 -3
  292. package/src/clis/bilibili/comments.ts +2 -2
  293. package/src/clis/bilibili/download.ts +2 -1
  294. package/src/clis/bilibili/subtitle.test.ts +2 -1
  295. package/src/clis/bilibili/subtitle.ts +4 -3
  296. package/src/clis/bilibili/utils.test.ts +21 -0
  297. package/src/clis/bilibili/utils.ts +27 -0
  298. package/src/clis/douban/marks.ts +1 -1
  299. package/src/clis/douban/subject.yaml +50 -19
  300. package/src/clis/doubao/utils.ts +32 -12
  301. package/src/clis/douyin/_shared/browser-fetch.test.ts +0 -1
  302. package/src/clis/douyin/_shared/transcode.test.ts +0 -2
  303. package/src/clis/douyin/draft.test.ts +0 -2
  304. package/src/clis/facebook/search.test.ts +0 -2
  305. package/src/clis/gemini/ask.test.ts +116 -0
  306. package/src/clis/gemini/ask.ts +10 -3
  307. package/src/clis/gemini/reply-state.test.ts +708 -0
  308. package/src/clis/gemini/utils.test.ts +184 -2
  309. package/src/clis/gemini/utils.ts +588 -60
  310. package/src/clis/hupu/detail.ts +126 -0
  311. package/src/clis/hupu/hot.yaml +43 -0
  312. package/src/clis/hupu/like.ts +76 -0
  313. package/src/clis/hupu/reply.ts +76 -0
  314. package/src/clis/hupu/search.ts +95 -0
  315. package/src/clis/hupu/unlike.ts +76 -0
  316. package/src/clis/hupu/utils.ts +381 -0
  317. package/src/clis/instagram/_shared/private-publish.test.ts +827 -0
  318. package/src/clis/instagram/_shared/private-publish.ts +1303 -0
  319. package/src/clis/instagram/_shared/protocol-capture.test.ts +148 -0
  320. package/src/clis/instagram/_shared/protocol-capture.ts +321 -0
  321. package/src/clis/instagram/_shared/runtime-info.ts +91 -0
  322. package/src/clis/instagram/note.test.ts +96 -0
  323. package/src/clis/instagram/note.ts +254 -0
  324. package/src/clis/instagram/post.test.ts +1716 -0
  325. package/src/clis/instagram/post.ts +1620 -0
  326. package/src/clis/instagram/reel.test.ts +191 -0
  327. package/src/clis/instagram/reel.ts +886 -0
  328. package/src/clis/instagram/story.test.ts +191 -0
  329. package/src/clis/instagram/story.ts +151 -0
  330. package/src/clis/sinafinance/stock-rank.ts +68 -0
  331. package/src/clis/substack/utils.test.ts +0 -2
  332. package/src/clis/twitter/post.test.ts +157 -0
  333. package/src/clis/twitter/post.ts +82 -48
  334. package/src/clis/twitter/reply.test.ts +177 -0
  335. package/src/clis/twitter/reply.ts +285 -39
  336. package/src/clis/xianyu/chat.test.ts +20 -0
  337. package/src/clis/xianyu/chat.ts +175 -0
  338. package/src/clis/xianyu/item.test.ts +67 -0
  339. package/src/clis/xianyu/item.ts +172 -0
  340. package/src/clis/xianyu/search.test.ts +22 -0
  341. package/src/clis/xianyu/search.ts +151 -0
  342. package/src/clis/xianyu/utils.ts +9 -0
  343. package/src/clis/xiaoe/catalog.yaml +129 -0
  344. package/src/clis/xiaoe/content.yaml +43 -0
  345. package/src/clis/xiaoe/courses.yaml +73 -0
  346. package/src/clis/xiaoe/detail.yaml +39 -0
  347. package/src/clis/xiaoe/play-url.yaml +124 -0
  348. package/src/clis/xiaohongshu/comments.test.ts +0 -2
  349. package/src/clis/xiaohongshu/creator-note-detail.test.ts +0 -2
  350. package/src/clis/xiaohongshu/creator-notes.test.ts +0 -2
  351. package/src/clis/xiaohongshu/download.test.ts +0 -2
  352. package/src/clis/xiaohongshu/note.test.ts +0 -2
  353. package/src/clis/xiaohongshu/publish.test.ts +0 -2
  354. package/src/clis/xiaohongshu/search.test.ts +59 -48
  355. package/src/clis/xiaohongshu/search.ts +31 -21
  356. package/src/clis/yuanbao/ask.test.ts +156 -0
  357. package/src/clis/yuanbao/ask.ts +522 -0
  358. package/src/clis/yuanbao/new.test.ts +36 -0
  359. package/src/clis/yuanbao/new.ts +81 -0
  360. package/src/clis/yuanbao/shared.ts +57 -0
  361. package/src/clis/zhihu/question.test.ts +42 -17
  362. package/src/clis/zhihu/question.ts +31 -26
  363. package/src/commanderAdapter.test.ts +51 -0
  364. package/src/commanderAdapter.ts +8 -4
  365. package/src/completion.test.ts +30 -0
  366. package/src/completion.ts +3 -1
  367. package/src/doctor.ts +1 -1
  368. package/src/electron-apps.ts +9 -1
  369. package/src/errors.ts +1 -1
  370. package/src/execution.ts +26 -30
  371. package/src/explore.ts +1 -1
  372. package/src/launcher.test.ts +121 -7
  373. package/src/launcher.ts +87 -9
  374. package/src/output.test.ts +50 -90
  375. package/src/output.ts +10 -1
  376. package/src/pipeline/executor.test.ts +0 -2
  377. package/src/pipeline/steps/download.test.ts +0 -2
  378. package/src/registry.ts +2 -0
  379. package/src/serialization.ts +2 -0
  380. package/src/types.ts +9 -2
  381. package/tests/e2e/browser-auth.test.ts +9 -0
  382. package/CLI-EXPLORER.md +0 -724
  383. package/CLI-ONESHOT.md +0 -216
  384. package/SKILL.md +0 -59
@@ -0,0 +1,222 @@
1
+ import { ArgumentError, CommandExecutionError } from '../../errors.js';
2
+ import { cli, Strategy } from '../../registry.js';
3
+ const INSTAGRAM_INBOX_URL = 'https://www.instagram.com/direct/inbox/';
4
+ const INSTAGRAM_NOTE_DOC_ID = '25155183657506484';
5
+ const INSTAGRAM_NOTE_MUTATION_NAME = 'usePolarisCreateInboxTrayItemSubmitMutation';
6
+ const INSTAGRAM_NOTE_ROOT_FIELD = 'xdt_create_inbox_tray_item';
7
+ function requirePage(page) {
8
+ if (!page)
9
+ throw new CommandExecutionError('Browser session required for instagram note');
10
+ return page;
11
+ }
12
+ function validateInstagramNoteArgs(kwargs) {
13
+ if (kwargs.content === undefined) {
14
+ throw new ArgumentError('Argument "content" is required.', 'Provide a note text, for example: opencli instagram note "hello"');
15
+ }
16
+ }
17
+ function normalizeInstagramNoteContent(kwargs) {
18
+ const content = String(kwargs.content ?? '').trim();
19
+ if (!content) {
20
+ throw new ArgumentError('Instagram note content cannot be empty.', 'Provide a non-empty note text, for example: opencli instagram note "hello"');
21
+ }
22
+ if (Array.from(content).length > 60) {
23
+ throw new ArgumentError('Instagram note content must be 60 characters or fewer.', 'Shorten the note text and try again.');
24
+ }
25
+ return content;
26
+ }
27
+ function buildNoteSuccessResult(noteId) {
28
+ return [{
29
+ status: '✅ Posted',
30
+ detail: 'Instagram note published successfully',
31
+ noteId,
32
+ }];
33
+ }
34
+ function buildPublishInstagramNoteJs(content) {
35
+ return `
36
+ (async () => {
37
+ const input = ${JSON.stringify({ content })};
38
+ const html = document.documentElement?.outerHTML || '';
39
+ const scripts = Array.from(document.scripts || [])
40
+ .map((script) => script.textContent || '')
41
+ .join('\\n');
42
+ const source = html + '\\n' + scripts;
43
+ const pick = (patterns) => {
44
+ for (const pattern of patterns) {
45
+ const match = source.match(pattern);
46
+ if (!match) continue;
47
+ for (let index = 1; index < match.length; index += 1) {
48
+ if (match[index]) return match[index];
49
+ }
50
+ return match[0] || '';
51
+ }
52
+ return '';
53
+ };
54
+ const readCookie = (name) => {
55
+ const prefix = name + '=';
56
+ const part = document.cookie
57
+ .split('; ')
58
+ .find((cookie) => cookie.startsWith(prefix));
59
+ return part ? decodeURIComponent(part.slice(prefix.length)) : '';
60
+ };
61
+ const actorId = pick([
62
+ /"actorID":"(\\d+)"/,
63
+ /"actor_id":"(\\d+)"/,
64
+ /"viewerId":"(\\d+)"/,
65
+ ]);
66
+ const fbDtsg = pick([
67
+ /(NAF[a-zA-Z0-9:_-]{20,})/,
68
+ /(NAf[a-zA-Z0-9:_-]{20,})/,
69
+ ]);
70
+ const lsd = pick([
71
+ /"LSD",\\[\\],\\{"token":"([^"]+)"\\}/,
72
+ /"lsd":"([^"]+)"/,
73
+ ]);
74
+ const appId = pick([
75
+ /"X-IG-App-ID":"(\\d+)"/,
76
+ /"instagramWebAppId":"(\\d+)"/,
77
+ /"appId":"(\\d+)"/,
78
+ ]);
79
+ const asbdId = pick([
80
+ /"X-ASBD-ID":"(\\d+)"/,
81
+ /"asbd_id":"(\\d+)"/,
82
+ ]);
83
+ const spinR = pick([/"__spin_r":(\\d+)/]);
84
+ const spinB = pick([/"__spin_b":"([^"]+)"/]);
85
+ const spinT = pick([/"__spin_t":(\\d+)/]);
86
+ const csrfToken = readCookie('csrftoken') || pick([
87
+ /"csrf_token":"([^"]+)"/,
88
+ /"csrfToken":"([^"]+)"/,
89
+ ]);
90
+ const jazoest = fbDtsg
91
+ ? '2' + Array.from(fbDtsg).reduce((total, char) => total + char.charCodeAt(0), 0)
92
+ : '';
93
+
94
+ if (!actorId || !fbDtsg || !lsd || !appId || !csrfToken || !spinR || !spinB || !spinT || !jazoest) {
95
+ return {
96
+ ok: false,
97
+ stage: 'config',
98
+ text: JSON.stringify({
99
+ actorId: Boolean(actorId),
100
+ fbDtsg: Boolean(fbDtsg),
101
+ lsd: Boolean(lsd),
102
+ appId: Boolean(appId),
103
+ csrfToken: Boolean(csrfToken),
104
+ spinR: Boolean(spinR),
105
+ spinB: Boolean(spinB),
106
+ spinT: Boolean(spinT),
107
+ jazoest: Boolean(jazoest),
108
+ }),
109
+ };
110
+ }
111
+
112
+ const variables = {
113
+ input: {
114
+ actor_id: actorId,
115
+ client_mutation_id: '1',
116
+ additional_params: {
117
+ note_create_params: {
118
+ note_style: 0,
119
+ text: input.content,
120
+ },
121
+ },
122
+ audience: 0,
123
+ inbox_tray_item_type: 'note',
124
+ },
125
+ };
126
+
127
+ const body = new URLSearchParams();
128
+ body.set('av', actorId);
129
+ body.set('__user', '0');
130
+ body.set('__a', '1');
131
+ body.set('__req', '1');
132
+ body.set('__hs', '');
133
+ body.set('dpr', String(window.devicePixelRatio || 1));
134
+ body.set('__ccg', 'UNKNOWN');
135
+ body.set('__rev', spinR);
136
+ body.set('__s', '');
137
+ body.set('__hsi', '');
138
+ body.set('__dyn', '');
139
+ body.set('__csr', '');
140
+ body.set('__comet_req', '7');
141
+ body.set('fb_dtsg', fbDtsg);
142
+ body.set('jazoest', jazoest);
143
+ body.set('lsd', lsd);
144
+ body.set('__spin_r', spinR);
145
+ body.set('__spin_b', spinB);
146
+ body.set('__spin_t', spinT);
147
+ body.set('fb_api_caller_class', 'RelayModern');
148
+ body.set('fb_api_req_friendly_name', ${JSON.stringify(INSTAGRAM_NOTE_MUTATION_NAME)});
149
+ body.set('variables', JSON.stringify(variables));
150
+ body.set('server_timestamps', 'true');
151
+ body.set('doc_id', ${JSON.stringify(INSTAGRAM_NOTE_DOC_ID)});
152
+
153
+ const headers = {
154
+ Accept: '*/*',
155
+ 'Content-Type': 'application/x-www-form-urlencoded',
156
+ 'X-ASBD-ID': asbdId || undefined,
157
+ 'X-CSRFToken': csrfToken,
158
+ 'X-FB-Friendly-Name': ${JSON.stringify(INSTAGRAM_NOTE_MUTATION_NAME)},
159
+ 'X-FB-LSD': lsd,
160
+ 'X-IG-App-ID': appId,
161
+ 'X-Root-Field-Name': ${JSON.stringify(INSTAGRAM_NOTE_ROOT_FIELD)},
162
+ };
163
+
164
+ const response = await fetch('/graphql/query', {
165
+ method: 'POST',
166
+ credentials: 'include',
167
+ headers,
168
+ body: body.toString(),
169
+ });
170
+ const text = await response.text();
171
+ const normalizedText = text.replace(/^for \\(;;\\);?/, '').trim();
172
+ let data = null;
173
+ try {
174
+ data = JSON.parse(normalizedText);
175
+ } catch {}
176
+
177
+ const rootField = ${JSON.stringify(INSTAGRAM_NOTE_ROOT_FIELD)};
178
+ const note = data?.data?.[rootField]?.inbox_tray_item;
179
+ const noteId = String(note?.inbox_tray_item_id || note?.id || '');
180
+ if (response.ok && noteId) {
181
+ return {
182
+ ok: true,
183
+ stage: 'publish',
184
+ noteId,
185
+ text: String(note?.note_dict?.text || input.content || ''),
186
+ };
187
+ }
188
+
189
+ return {
190
+ ok: false,
191
+ stage: 'publish',
192
+ status: response.status,
193
+ text: normalizedText || text,
194
+ };
195
+ })()
196
+ `;
197
+ }
198
+ cli({
199
+ site: 'instagram',
200
+ name: 'note',
201
+ description: 'Publish a text Instagram note',
202
+ domain: 'www.instagram.com',
203
+ strategy: Strategy.UI,
204
+ browser: true,
205
+ timeoutSeconds: 120,
206
+ args: [
207
+ { name: 'content', positional: true, required: true, help: 'Note text (max 60 characters)' },
208
+ ],
209
+ columns: ['status', 'detail', 'noteId'],
210
+ validateArgs: validateInstagramNoteArgs,
211
+ func: async (page, kwargs) => {
212
+ const browserPage = requirePage(page);
213
+ const content = normalizeInstagramNoteContent(kwargs);
214
+ await browserPage.goto(INSTAGRAM_INBOX_URL);
215
+ await browserPage.wait({ time: 2 });
216
+ const result = await browserPage.evaluate(buildPublishInstagramNoteJs(content));
217
+ if (!result?.ok) {
218
+ throw new CommandExecutionError(`Instagram note publish failed at ${String(result?.stage || 'unknown')}: ${String(result?.text || 'unknown error')}`);
219
+ }
220
+ return buildNoteSuccessResult(String(result.noteId || ''));
221
+ },
222
+ });
@@ -0,0 +1 @@
1
+ import './note.js';
@@ -0,0 +1,81 @@
1
+ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
2
+ import { ArgumentError } from '../../errors.js';
3
+ import { getRegistry } from '../../registry.js';
4
+ import './note.js';
5
+ function createPageMock() {
6
+ return {
7
+ goto: vi.fn().mockResolvedValue(undefined),
8
+ evaluate: vi.fn().mockResolvedValue(undefined),
9
+ getCookies: vi.fn().mockResolvedValue([]),
10
+ snapshot: vi.fn().mockResolvedValue(undefined),
11
+ click: vi.fn().mockResolvedValue(undefined),
12
+ typeText: vi.fn().mockResolvedValue(undefined),
13
+ pressKey: vi.fn().mockResolvedValue(undefined),
14
+ scrollTo: vi.fn().mockResolvedValue(undefined),
15
+ getFormState: vi.fn().mockResolvedValue({ forms: [], orphanFields: [] }),
16
+ wait: vi.fn().mockResolvedValue(undefined),
17
+ tabs: vi.fn().mockResolvedValue([]),
18
+ closeTab: vi.fn().mockResolvedValue(undefined),
19
+ newTab: vi.fn().mockResolvedValue(undefined),
20
+ selectTab: vi.fn().mockResolvedValue(undefined),
21
+ networkRequests: vi.fn().mockResolvedValue([]),
22
+ consoleMessages: vi.fn().mockResolvedValue([]),
23
+ scroll: vi.fn().mockResolvedValue(undefined),
24
+ autoScroll: vi.fn().mockResolvedValue(undefined),
25
+ installInterceptor: vi.fn().mockResolvedValue(undefined),
26
+ getInterceptedRequests: vi.fn().mockResolvedValue([]),
27
+ waitForCapture: vi.fn().mockResolvedValue(undefined),
28
+ screenshot: vi.fn().mockResolvedValue(''),
29
+ setFileInput: vi.fn().mockResolvedValue(undefined),
30
+ insertText: vi.fn().mockResolvedValue(undefined),
31
+ getCurrentUrl: vi.fn().mockResolvedValue(null),
32
+ };
33
+ }
34
+ describe('instagram note registration', () => {
35
+ beforeEach(() => {
36
+ vi.restoreAllMocks();
37
+ });
38
+ afterEach(() => {
39
+ vi.restoreAllMocks();
40
+ });
41
+ it('registers the note command with a required positional content arg', () => {
42
+ const cmd = getRegistry().get('instagram/note');
43
+ expect(cmd).toBeDefined();
44
+ expect(cmd?.browser).toBe(true);
45
+ expect(cmd?.args.some((arg) => arg.name === 'content' && arg.positional && arg.required)).toBe(true);
46
+ });
47
+ it('rejects missing note content before browser work', async () => {
48
+ const page = createPageMock();
49
+ const cmd = getRegistry().get('instagram/note');
50
+ await expect(cmd.func(page, {})).rejects.toThrow(ArgumentError);
51
+ expect(page.goto).not.toHaveBeenCalled();
52
+ });
53
+ it('rejects blank note content before browser work', async () => {
54
+ const page = createPageMock();
55
+ const cmd = getRegistry().get('instagram/note');
56
+ await expect(cmd.func(page, { content: ' ' })).rejects.toThrow(ArgumentError);
57
+ expect(page.goto).not.toHaveBeenCalled();
58
+ });
59
+ it('rejects note content longer than 60 characters before browser work', async () => {
60
+ const page = createPageMock();
61
+ const cmd = getRegistry().get('instagram/note');
62
+ await expect(cmd.func(page, { content: 'x'.repeat(61) })).rejects.toThrow(ArgumentError);
63
+ expect(page.goto).not.toHaveBeenCalled();
64
+ });
65
+ it('publishes a note through the web inbox mutation', async () => {
66
+ const page = createPageMock();
67
+ const cmd = getRegistry().get('instagram/note');
68
+ vi.mocked(page.evaluate).mockResolvedValue({
69
+ ok: true,
70
+ noteId: '17849203563031468',
71
+ });
72
+ const rows = await cmd.func(page, { content: 'hello note' });
73
+ expect(page.goto).toHaveBeenCalledWith('https://www.instagram.com/direct/inbox/');
74
+ expect(page.evaluate).toHaveBeenCalledTimes(1);
75
+ expect(rows).toEqual([{
76
+ status: '✅ Posted',
77
+ detail: 'Instagram note published successfully',
78
+ noteId: '17849203563031468',
79
+ }]);
80
+ });
81
+ });
@@ -0,0 +1,4 @@
1
+ export declare function buildEnsureComposerOpenJs(): string;
2
+ export declare function buildPublishStatusProbeJs(): string;
3
+ export declare function buildInspectUploadStageJs(): string;
4
+ export declare function buildClickActionJs(labels: string[], scope?: 'any' | 'media' | 'caption'): string;