@sovovs/bycli 1.8.0 → 2.1.0

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 (539) hide show
  1. package/cli-manifest.json +0 -61
  2. package/clis/twitter/search.js +3 -3
  3. package/dist/src/adapter-shadow.js +2 -2
  4. package/dist/src/browser/analyze.d.ts +10 -99
  5. package/dist/src/browser/analyze.js +10 -226
  6. package/dist/src/browser/cdp.js +67 -7
  7. package/dist/src/browser/daemon-client.d.ts +2 -0
  8. package/dist/src/browser/daemon-client.js +1 -1
  9. package/dist/src/browser/extension-capabilities.d.ts +13 -0
  10. package/dist/src/browser/extension-capabilities.js +22 -0
  11. package/dist/src/browser/extension-capabilities.test.d.ts +1 -0
  12. package/dist/src/browser/extension-version-metadata.test.d.ts +1 -0
  13. package/dist/src/browser/navigation-guard.d.ts +78 -0
  14. package/dist/src/browser/navigation-guard.js +142 -0
  15. package/dist/src/browser/navigation-guard.test.d.ts +1 -0
  16. package/dist/src/browser/page.d.ts +1 -0
  17. package/dist/src/browser/page.js +20 -1
  18. package/dist/src/browser/url-policy.d.ts +89 -0
  19. package/dist/src/browser/url-policy.js +311 -0
  20. package/dist/src/browser/url-policy.test.d.ts +1 -0
  21. package/dist/src/browser/verify-fixture.js +2 -2
  22. package/dist/src/build-manifest.js +4 -2
  23. package/dist/src/capabilityRouting.d.ts +3 -2
  24. package/dist/src/capabilityRouting.js +10 -2
  25. package/dist/src/cli.js +11 -14
  26. package/dist/src/commanderAdapter.js +5 -5
  27. package/dist/src/config-paths.d.ts +19 -0
  28. package/dist/src/config-paths.js +31 -0
  29. package/dist/src/daemon.js +256 -0
  30. package/dist/src/discovery.d.ts +10 -3
  31. package/dist/src/discovery.js +20 -10
  32. package/dist/src/discovery.test.d.ts +1 -0
  33. package/dist/src/execution.d.ts +5 -0
  34. package/dist/src/execution.js +272 -48
  35. package/dist/src/help.js +8 -8
  36. package/dist/src/main.js +18 -2
  37. package/dist/src/manifest-schema.d.ts +9 -0
  38. package/dist/src/manifest-schema.js +162 -0
  39. package/dist/src/manifest-schema.test.d.ts +1 -0
  40. package/dist/src/manifest-types.d.ts +1 -1
  41. package/dist/src/observation/redaction.js +10 -4
  42. package/dist/src/plugin.js +11 -8
  43. package/dist/src/recorder/highlevel/analyze.d.ts +29 -0
  44. package/dist/src/recorder/highlevel/analyze.js +91 -0
  45. package/dist/src/recorder/highlevel/init.d.ts +125 -0
  46. package/dist/src/recorder/highlevel/init.js +279 -0
  47. package/dist/src/recorder/highlevel/init.test.d.ts +1 -0
  48. package/dist/src/recorder/highlevel/verify.d.ts +73 -0
  49. package/dist/src/recorder/highlevel/verify.js +74 -0
  50. package/dist/src/recorder/http/analyze-runner.d.ts +28 -0
  51. package/dist/src/recorder/http/analyze-runner.js +78 -0
  52. package/dist/src/recorder/http/analyze-runner.test.d.ts +1 -0
  53. package/dist/src/recorder/http/handlers.d.ts +51 -0
  54. package/dist/src/recorder/http/handlers.js +219 -0
  55. package/dist/src/recorder/http/wrapper-config.d.ts +20 -0
  56. package/dist/src/recorder/http/wrapper-config.js +82 -0
  57. package/dist/src/recorder/http/wrapper-envelope.d.ts +31 -0
  58. package/dist/src/recorder/http/wrapper-envelope.js +51 -0
  59. package/dist/src/recorder/http/wrapper-gates.d.ts +16 -0
  60. package/dist/src/recorder/http/wrapper-gates.js +28 -0
  61. package/dist/src/recorder/http/wrapper-metrics.d.ts +1 -0
  62. package/dist/src/recorder/http/wrapper-metrics.js +5 -0
  63. package/dist/src/recorder/http/wrapper-registry.d.ts +50 -0
  64. package/dist/src/recorder/http/wrapper-registry.js +98 -0
  65. package/dist/src/recorder/http/wrapper-server.d.ts +59 -0
  66. package/dist/src/recorder/http/wrapper-server.js +240 -0
  67. package/dist/src/recorder/http/wrapper.test.d.ts +1 -0
  68. package/dist/src/recorder/observability/logger.d.ts +5 -0
  69. package/dist/src/recorder/observability/logger.js +13 -0
  70. package/dist/src/recorder/runner/config.d.ts +34 -0
  71. package/dist/src/recorder/runner/config.js +84 -0
  72. package/dist/src/recorder/runner/config.test.d.ts +1 -0
  73. package/dist/src/recorder/runner/reap.d.ts +79 -0
  74. package/dist/src/recorder/runner/reap.js +230 -0
  75. package/dist/src/recorder/runner/reap.test.d.ts +1 -0
  76. package/dist/src/recorder/runner/runner-port.d.ts +95 -0
  77. package/dist/src/recorder/runner/runner-port.js +518 -0
  78. package/dist/src/recorder/runner/runner-port.test.d.ts +1 -0
  79. package/dist/src/recorder/runner/session-keys.d.ts +28 -0
  80. package/dist/src/recorder/runner/session-keys.js +72 -0
  81. package/dist/src/recorder/runner/session-keys.test.d.ts +1 -0
  82. package/dist/src/recorder/runner/verify-runner-main.d.ts +96 -0
  83. package/dist/src/recorder/runner/verify-runner-main.js +292 -0
  84. package/dist/src/recorder/runner/verify-runner-main.test.d.ts +1 -0
  85. package/dist/src/registry-api.d.ts +1 -1
  86. package/dist/src/registry-api.types.test.d.ts +1 -0
  87. package/dist/src/registry-transaction.d.ts +42 -0
  88. package/dist/src/registry-transaction.js +194 -0
  89. package/dist/src/registry-transaction.test.d.ts +1 -0
  90. package/dist/src/registry.d.ts +58 -16
  91. package/dist/src/registry.js +131 -15
  92. package/dist/src/serialization.d.ts +1 -1
  93. package/dist/src/serialization.js +3 -3
  94. package/dist/src/types.d.ts +2 -0
  95. package/package.json +8 -5
  96. package/scripts/m1-daemon-navigate-drive.mjs +138 -0
  97. package/scripts/m1-extension-spike.mjs +237 -0
  98. package/scripts/m1-live-spike.mjs +156 -0
  99. package/scripts/m6b-connect-back-spike.sh +31 -0
  100. package/clis/12306/utils.test.js +0 -331
  101. package/clis/1688/assets.test.js +0 -39
  102. package/clis/1688/download.test.js +0 -31
  103. package/clis/1688/item.test.js +0 -67
  104. package/clis/1688/search.test.js +0 -75
  105. package/clis/1688/shared.test.js +0 -57
  106. package/clis/1688/store.test.js +0 -62
  107. package/clis/36kr/article.test.js +0 -46
  108. package/clis/36kr/hot.test.js +0 -15
  109. package/clis/36kr/news.test.js +0 -85
  110. package/clis/51job/utils.test.js +0 -69
  111. package/clis/_atlassian/shared.test.js +0 -170
  112. package/clis/aibase/news.test.js +0 -59
  113. package/clis/amazon/bestsellers.test.js +0 -29
  114. package/clis/amazon/discussion.test.js +0 -124
  115. package/clis/amazon/offer.test.js +0 -29
  116. package/clis/amazon/product.test.js +0 -24
  117. package/clis/amazon/rankings.test.js +0 -41
  118. package/clis/amazon/search.test.js +0 -22
  119. package/clis/amazon/shared.test.js +0 -44
  120. package/clis/apple-podcasts/commands.test.js +0 -119
  121. package/clis/apple-podcasts/utils.test.js +0 -57
  122. package/clis/arxiv/arxiv.test.js +0 -112
  123. package/clis/baidu-scholar/search.test.js +0 -23
  124. package/clis/barchart/greeks.test.js +0 -138
  125. package/clis/bilibili/comment.test.js +0 -153
  126. package/clis/bilibili/comments.test.js +0 -142
  127. package/clis/bilibili/dynamic.test.js +0 -68
  128. package/clis/bilibili/hot.test.js +0 -17
  129. package/clis/bilibili/subtitle.test.js +0 -196
  130. package/clis/bilibili/summary.test.js +0 -210
  131. package/clis/bilibili/utils.test.js +0 -61
  132. package/clis/bilibili/video.test.js +0 -132
  133. package/clis/binance/commands.test.js +0 -70
  134. package/clis/bloomberg/utils.test.js +0 -129
  135. package/clis/booking/booking.test.js +0 -356
  136. package/clis/boss/chatlist.test.js +0 -211
  137. package/clis/boss/chatmsg.test.js +0 -230
  138. package/clis/boss/search.test.js +0 -78
  139. package/clis/boss/utils.test.js +0 -34
  140. package/clis/brave/search.test.js +0 -76
  141. package/clis/chaoxing/utils.test.js +0 -45
  142. package/clis/chatgpt/commands.test.js +0 -45
  143. package/clis/chatgpt/envelope.test.js +0 -108
  144. package/clis/chatgpt/image.test.js +0 -188
  145. package/clis/chatgpt/utils.test.js +0 -330
  146. package/clis/chatgpt-app/ax.test.js +0 -35
  147. package/clis/chatwise/composer.test.js +0 -186
  148. package/clis/chess/analyze.test.js +0 -79
  149. package/clis/chess/game.test.js +0 -178
  150. package/clis/chess/games.test.js +0 -164
  151. package/clis/chess/stats.test.js +0 -79
  152. package/clis/chess/utils.test.js +0 -230
  153. package/clis/claude/ask.test.js +0 -338
  154. package/clis/claude/commands.test.js +0 -118
  155. package/clis/claude/utils.test.js +0 -148
  156. package/clis/cnki/search.test.js +0 -18
  157. package/clis/codex/sidebar.test.js +0 -329
  158. package/clis/coingecko/coingecko.test.js +0 -109
  159. package/clis/confluence/commands.test.js +0 -195
  160. package/clis/coupang/coupang.test.js +0 -159
  161. package/clis/coupang/utils.test.js +0 -62
  162. package/clis/ctrip/ctrip.test.js +0 -719
  163. package/clis/dblp/dblp.test.js +0 -397
  164. package/clis/deepseek/ask.test.js +0 -312
  165. package/clis/deepseek/detail.test.js +0 -81
  166. package/clis/deepseek/send.test.js +0 -107
  167. package/clis/deepseek/utils.test.js +0 -370
  168. package/clis/defillama/defillama.test.js +0 -99
  169. package/clis/devto/devto.test.js +0 -236
  170. package/clis/dianping/dianping.test.js +0 -578
  171. package/clis/douban/download.test.js +0 -170
  172. package/clis/douban/movie-hot.test.js +0 -14
  173. package/clis/douban/search.test.js +0 -11
  174. package/clis/douban/subject.test.js +0 -11
  175. package/clis/douban/utils.test.js +0 -438
  176. package/clis/doubao/detail.test.js +0 -42
  177. package/clis/doubao/history.test.js +0 -37
  178. package/clis/doubao/utils.test.js +0 -344
  179. package/clis/douyin/_shared/browser-fetch.test.js +0 -64
  180. package/clis/douyin/_shared/creation-id.test.js +0 -22
  181. package/clis/douyin/_shared/imagex-upload.test.js +0 -87
  182. package/clis/douyin/_shared/sts2.test.js +0 -27
  183. package/clis/douyin/_shared/text-extra.test.js +0 -37
  184. package/clis/douyin/_shared/timing.test.js +0 -28
  185. package/clis/douyin/_shared/tos-upload-short-read.test.js +0 -83
  186. package/clis/douyin/_shared/tos-upload.test.js +0 -229
  187. package/clis/douyin/_shared/transcode.test.js +0 -91
  188. package/clis/douyin/_shared/vod-upload.test.js +0 -38
  189. package/clis/douyin/activities.test.js +0 -55
  190. package/clis/douyin/collections.test.js +0 -45
  191. package/clis/douyin/delete.test.js +0 -100
  192. package/clis/douyin/draft.test.js +0 -335
  193. package/clis/douyin/drafts.test.js +0 -11
  194. package/clis/douyin/hashtag.test.js +0 -171
  195. package/clis/douyin/location.test.js +0 -23
  196. package/clis/douyin/profile.test.js +0 -46
  197. package/clis/douyin/publish-upload-id.test.js +0 -170
  198. package/clis/douyin/publish.test.js +0 -38
  199. package/clis/douyin/stats.test.js +0 -22
  200. package/clis/douyin/update.test.js +0 -11
  201. package/clis/douyin/user-videos.test.js +0 -151
  202. package/clis/douyin/videos.test.js +0 -54
  203. package/clis/duckduckgo/search.test.js +0 -128
  204. package/clis/duckduckgo/suggest.test.js +0 -66
  205. package/clis/eastmoney/hot-rank.test.js +0 -59
  206. package/clis/endoflife/endoflife.test.js +0 -51
  207. package/clis/facebook/feed.test.js +0 -169
  208. package/clis/facebook/marketplace.test.js +0 -91
  209. package/clis/facebook/notifications.test.js +0 -458
  210. package/clis/facebook/search.test.js +0 -55
  211. package/clis/flathub/flathub.test.js +0 -90
  212. package/clis/flomo/memos.test.js +0 -144
  213. package/clis/gemini/ask.test.js +0 -100
  214. package/clis/gemini/deep-research-result.test.js +0 -155
  215. package/clis/gemini/deep-research.test.js +0 -181
  216. package/clis/gemini/reply-state.test.js +0 -671
  217. package/clis/gemini/utils.test.js +0 -198
  218. package/clis/geogebra/geogebra.test.js +0 -175
  219. package/clis/gitee/search.test.js +0 -65
  220. package/clis/gitee/user.test.js +0 -63
  221. package/clis/google/utils.test.js +0 -75
  222. package/clis/google-scholar/cite.test.js +0 -47
  223. package/clis/google-scholar/profile.test.js +0 -49
  224. package/clis/google-scholar/search.test.js +0 -71
  225. package/clis/goproxy/goproxy.test.js +0 -103
  226. package/clis/gov-law/commands.test.js +0 -39
  227. package/clis/gov-policy/gov-policy.test.js +0 -224
  228. package/clis/grok/ask.test.js +0 -29
  229. package/clis/grok/utils.test.js +0 -103
  230. package/clis/hackernews/hackernews.test.js +0 -132
  231. package/clis/hf/hf.test.js +0 -16
  232. package/clis/hupu/hot.test.js +0 -224
  233. package/clis/imdb/utils.test.js +0 -88
  234. package/clis/indeed/indeed.test.js +0 -375
  235. package/clis/instagram/_shared/private-publish.test.js +0 -705
  236. package/clis/instagram/_shared/protocol-capture.test.js +0 -114
  237. package/clis/instagram/download.test.js +0 -118
  238. package/clis/instagram/note.test.js +0 -53
  239. package/clis/instagram/post.test.js +0 -1647
  240. package/clis/instagram/reel.test.js +0 -167
  241. package/clis/instagram/story.test.js +0 -134
  242. package/clis/jd/commands.test.js +0 -41
  243. package/clis/jd/item.test.js +0 -354
  244. package/clis/jianyu/search.test.js +0 -153
  245. package/clis/jianyu/shared/procurement-contract.test.js +0 -72
  246. package/clis/jianyu/shared/procurement-detail.test.js +0 -84
  247. package/clis/jike/read.test.js +0 -86
  248. package/clis/jira/commands.test.js +0 -287
  249. package/clis/juejin/search.js +0 -123
  250. package/clis/juejin/search.test.js +0 -98
  251. package/clis/lesswrong/frontpage.test.js +0 -37
  252. package/clis/lichess/lichess.test.js +0 -85
  253. package/clis/linkedin/connect.test.js +0 -213
  254. package/clis/linkedin/inbox.test.js +0 -152
  255. package/clis/linkedin/job-detail.test.js +0 -38
  256. package/clis/linkedin/jobs-preferences.test.js +0 -43
  257. package/clis/linkedin/people-search.test.js +0 -216
  258. package/clis/linkedin/post-analytics.test.js +0 -40
  259. package/clis/linkedin/posts.test.js +0 -40
  260. package/clis/linkedin/profile-analytics.test.js +0 -67
  261. package/clis/linkedin/profile-experience.test.js +0 -152
  262. package/clis/linkedin/profile-projects.test.js +0 -111
  263. package/clis/linkedin/profile-read.test.js +0 -77
  264. package/clis/linkedin/safe-send.test.js +0 -204
  265. package/clis/linkedin/salesnav-inbox.test.js +0 -113
  266. package/clis/linkedin/salesnav-message.test.js +0 -172
  267. package/clis/linkedin/salesnav-search.test.js +0 -76
  268. package/clis/linkedin/salesnav-thread.test.js +0 -79
  269. package/clis/linkedin/search.test.js +0 -222
  270. package/clis/linkedin/sent-invitations.test.js +0 -62
  271. package/clis/linkedin/services-read.test.js +0 -105
  272. package/clis/linkedin/thread-snapshot.test.js +0 -89
  273. package/clis/linkedin/timeline.test.js +0 -81
  274. package/clis/linkedin-learning/course.test.js +0 -114
  275. package/clis/linkedin-learning/search.test.js +0 -144
  276. package/clis/linkedin-learning/trending.test.js +0 -123
  277. package/clis/linux-do/feed.test.js +0 -153
  278. package/clis/linux-do/topic-content.test.js +0 -59
  279. package/clis/lobsters/lobsters.test.js +0 -169
  280. package/clis/notebooklm/add-source.test.js +0 -97
  281. package/clis/notebooklm/compat.test.js +0 -16
  282. package/clis/notebooklm/create.test.js +0 -58
  283. package/clis/notebooklm/generate-audio.test.js +0 -63
  284. package/clis/notebooklm/generate-slides.test.js +0 -75
  285. package/clis/notebooklm/history.test.js +0 -58
  286. package/clis/notebooklm/note-list.test.js +0 -56
  287. package/clis/notebooklm/notes-get.test.js +0 -72
  288. package/clis/notebooklm/open.test.js +0 -63
  289. package/clis/notebooklm/rpc.test.js +0 -131
  290. package/clis/notebooklm/source-fulltext.test.js +0 -106
  291. package/clis/notebooklm/source-get.test.js +0 -84
  292. package/clis/notebooklm/source-guide.test.js +0 -104
  293. package/clis/notebooklm/summary.test.js +0 -78
  294. package/clis/notebooklm/utils.test.js +0 -449
  295. package/clis/notebooklm/write-note.test.js +0 -70
  296. package/clis/nuget/nuget.test.js +0 -111
  297. package/clis/oeis/oeis.test.js +0 -88
  298. package/clis/ones/task-helpers.test.js +0 -12
  299. package/clis/ones/worklog.test.js +0 -20
  300. package/clis/openfda/openfda.test.js +0 -114
  301. package/clis/openreview/openreview.test.js +0 -427
  302. package/clis/osv/osv.test.js +0 -97
  303. package/clis/paperreview/commands.test.js +0 -243
  304. package/clis/paperreview/utils.test.js +0 -49
  305. package/clis/pixiv/download.test.js +0 -87
  306. package/clis/pixiv/illusts.test.js +0 -99
  307. package/clis/pixiv/search.test.js +0 -83
  308. package/clis/powerchina/search.test.js +0 -93
  309. package/clis/producthunt/utils.test.js +0 -64
  310. package/clis/pubmed/pubmed.test.js +0 -276
  311. package/clis/quark/utils.test.js +0 -58
  312. package/clis/qwen/utils.test.js +0 -45
  313. package/clis/reddit/extract-media.test.js +0 -149
  314. package/clis/reddit/frontpage.test.js +0 -34
  315. package/clis/reddit/home.test.js +0 -170
  316. package/clis/reddit/hot.test.js +0 -32
  317. package/clis/reddit/popular.test.js +0 -26
  318. package/clis/reddit/read.test.js +0 -335
  319. package/clis/reddit/reply.test.js +0 -89
  320. package/clis/reddit/search.test.js +0 -26
  321. package/clis/reddit/subreddit-info.test.js +0 -163
  322. package/clis/reddit/subreddit.test.js +0 -31
  323. package/clis/reddit/subscribed.test.js +0 -168
  324. package/clis/reddit/whoami.test.js +0 -105
  325. package/clis/rednote/navigation.test.js +0 -26
  326. package/clis/rednote/rednote.test.js +0 -222
  327. package/clis/rest-countries/rest-countries.test.js +0 -83
  328. package/clis/reuters/reuters.test.js +0 -299
  329. package/clis/rfc/rfc.test.js +0 -74
  330. package/clis/sinafinance/stock.test.js +0 -59
  331. package/clis/spotify/utils.test.js +0 -67
  332. package/clis/stackoverflow/stackoverflow.test.js +0 -404
  333. package/clis/steam/steam.test.js +0 -46
  334. package/clis/substack/utils.test.js +0 -44
  335. package/clis/suno/commands.test.js +0 -188
  336. package/clis/suno/download.test.js +0 -151
  337. package/clis/suno/generate.test.js +0 -252
  338. package/clis/suno/utils.test.js +0 -329
  339. package/clis/taobao/commands.test.js +0 -41
  340. package/clis/tdx/hot-rank.test.js +0 -59
  341. package/clis/ths/hot-rank.test.js +0 -64
  342. package/clis/tieba/commands.test.js +0 -79
  343. package/clis/tieba/utils.test.js +0 -290
  344. package/clis/tiktok/creator-videos.test.js +0 -113
  345. package/clis/tiktok/refactor.test.js +0 -389
  346. package/clis/tiktok/write-refactor.test.js +0 -370
  347. package/clis/toutiao/toutiao.test.js +0 -378
  348. package/clis/tvmaze/tvmaze.test.js +0 -93
  349. package/clis/twitter/bookmark-folder.test.js +0 -395
  350. package/clis/twitter/bookmark-folders.test.js +0 -152
  351. package/clis/twitter/bookmark.test.js +0 -74
  352. package/clis/twitter/bookmarks.test.js +0 -205
  353. package/clis/twitter/delete.test.js +0 -85
  354. package/clis/twitter/device-follow.test.js +0 -287
  355. package/clis/twitter/download.test.js +0 -457
  356. package/clis/twitter/followers.test.js +0 -62
  357. package/clis/twitter/following.test.js +0 -338
  358. package/clis/twitter/hide-reply.test.js +0 -76
  359. package/clis/twitter/like.test.js +0 -73
  360. package/clis/twitter/likes.test.js +0 -220
  361. package/clis/twitter/list-add.test.js +0 -133
  362. package/clis/twitter/list-create.test.js +0 -169
  363. package/clis/twitter/list-remove.test.js +0 -110
  364. package/clis/twitter/list-tweets.test.js +0 -196
  365. package/clis/twitter/lists.test.js +0 -253
  366. package/clis/twitter/post.test.js +0 -258
  367. package/clis/twitter/profile.test.js +0 -39
  368. package/clis/twitter/quote.test.js +0 -194
  369. package/clis/twitter/reply.test.js +0 -237
  370. package/clis/twitter/retweet.test.js +0 -73
  371. package/clis/twitter/search.test.js +0 -349
  372. package/clis/twitter/shared.test.js +0 -794
  373. package/clis/twitter/thread.test.js +0 -58
  374. package/clis/twitter/timeline.test.js +0 -104
  375. package/clis/twitter/trending.test.js +0 -15
  376. package/clis/twitter/tweets.test.js +0 -362
  377. package/clis/twitter/unbookmark.test.js +0 -73
  378. package/clis/twitter/unlike.test.js +0 -75
  379. package/clis/twitter/unretweet.test.js +0 -73
  380. package/clis/twitter/utils.test.js +0 -169
  381. package/clis/uisdc/news.test.js +0 -66
  382. package/clis/uiverse/_shared.test.js +0 -62
  383. package/clis/uiverse/navigation.test.js +0 -12
  384. package/clis/upwork/upwork.test.js +0 -566
  385. package/clis/wanfang/search.test.js +0 -23
  386. package/clis/web/read.test.js +0 -392
  387. package/clis/weibo/delete.test.js +0 -94
  388. package/clis/weibo/envelope.test.js +0 -85
  389. package/clis/weibo/favorites.test.js +0 -114
  390. package/clis/weibo/publish.test.js +0 -192
  391. package/clis/weibo/user-posts.test.js +0 -92
  392. package/clis/weibo/utils.test.js +0 -36
  393. package/clis/weixin/drafts.test.js +0 -69
  394. package/clis/weixin/search.test.js +0 -227
  395. package/clis/weread/ai-outline.test.js +0 -83
  396. package/clis/weread/book-search.test.js +0 -242
  397. package/clis/weread/commands.test.js +0 -398
  398. package/clis/weread/private-api-regression.test.js +0 -369
  399. package/clis/weread/search-regression.test.js +0 -494
  400. package/clis/weread/utils.test.js +0 -128
  401. package/clis/weread-official/commands.test.js +0 -385
  402. package/clis/weread-official/utils.test.js +0 -242
  403. package/clis/wikidata/wikidata.test.js +0 -83
  404. package/clis/wikipedia/trending.test.js +0 -57
  405. package/clis/wttr/wttr.test.js +0 -84
  406. package/clis/xianyu/chat.test.js +0 -84
  407. package/clis/xianyu/im.test.js +0 -253
  408. package/clis/xianyu/item.test.js +0 -56
  409. package/clis/xianyu/publish.test.js +0 -220
  410. package/clis/xianyu/search.test.js +0 -17
  411. package/clis/xiaoe/xiaoe.test.js +0 -486
  412. package/clis/xiaohongshu/comments.test.js +0 -258
  413. package/clis/xiaohongshu/creator-note-detail.test.js +0 -451
  414. package/clis/xiaohongshu/creator-notes-summary.test.js +0 -94
  415. package/clis/xiaohongshu/creator-notes.test.js +0 -281
  416. package/clis/xiaohongshu/creator-stats.test.js +0 -24
  417. package/clis/xiaohongshu/delete-note.test.js +0 -172
  418. package/clis/xiaohongshu/download.test.js +0 -316
  419. package/clis/xiaohongshu/navigation.test.js +0 -34
  420. package/clis/xiaohongshu/note.test.js +0 -249
  421. package/clis/xiaohongshu/publish.test.js +0 -608
  422. package/clis/xiaohongshu/search.test.js +0 -325
  423. package/clis/xiaohongshu/user-helpers.test.js +0 -160
  424. package/clis/xiaoyuzhou/auth.test.js +0 -124
  425. package/clis/xiaoyuzhou/download.test.js +0 -135
  426. package/clis/xiaoyuzhou/podcast-episodes.test.js +0 -78
  427. package/clis/xiaoyuzhou/transcript.test.js +0 -195
  428. package/clis/xiaoyuzhou/utils.test.js +0 -39
  429. package/clis/xueqiu/comments.test.js +0 -696
  430. package/clis/xueqiu/danjuan-utils.test.js +0 -41
  431. package/clis/xueqiu/utils.test.js +0 -26
  432. package/clis/yahoo/search.test.js +0 -94
  433. package/clis/youdao/note.test.js +0 -99
  434. package/clis/youtube/channel.test.js +0 -59
  435. package/clis/youtube/feed.test.js +0 -131
  436. package/clis/youtube/transcript-group.test.js +0 -99
  437. package/clis/youtube/transcript.test.js +0 -296
  438. package/clis/youtube/utils.test.js +0 -84
  439. package/clis/yuanbao/ask.test.js +0 -124
  440. package/clis/yuanbao/new.test.js +0 -30
  441. package/clis/yuanbao/shared.test.js +0 -80
  442. package/clis/zhihu/answer-comments.test.js +0 -287
  443. package/clis/zhihu/answer-detail.test.js +0 -338
  444. package/clis/zhihu/answer.test.js +0 -54
  445. package/clis/zhihu/collection.test.js +0 -337
  446. package/clis/zhihu/collections.test.js +0 -182
  447. package/clis/zhihu/comment.test.js +0 -50
  448. package/clis/zhihu/download.test.js +0 -12
  449. package/clis/zhihu/favorite.test.js +0 -59
  450. package/clis/zhihu/follow.test.js +0 -42
  451. package/clis/zhihu/like.test.js +0 -41
  452. package/clis/zhihu/question.test.js +0 -251
  453. package/clis/zhihu/recommend.test.js +0 -143
  454. package/clis/zhihu/search.test.js +0 -198
  455. package/clis/zhihu/target.test.js +0 -77
  456. package/clis/zhihu/text.test.js +0 -24
  457. package/clis/zhihu/write-shared.test.js +0 -176
  458. package/clis/zlibrary/commands.test.js +0 -65
  459. package/clis/zsxq/search.test.js +0 -24
  460. package/clis/zsxq/topic.test.js +0 -30
  461. package/clis/zsxq/topics.test.js +0 -24
  462. package/clis/zsxq/utils.test.js +0 -31
  463. package/dist/src/adapter-shadow.test.js +0 -49
  464. package/dist/src/adapter-source.test.js +0 -29
  465. package/dist/src/browser/analyze.test.js +0 -166
  466. package/dist/src/browser/article-extract.e2e.test.js +0 -105
  467. package/dist/src/browser/article-extract.test.js +0 -94
  468. package/dist/src/browser/ax-snapshot.test.js +0 -91
  469. package/dist/src/browser/base-page.test.js +0 -758
  470. package/dist/src/browser/cdp-click-fixture.test.js +0 -87
  471. package/dist/src/browser/cdp.test.js +0 -79
  472. package/dist/src/browser/compound.test.js +0 -175
  473. package/dist/src/browser/daemon-client.test.js +0 -199
  474. package/dist/src/browser/dom-helpers.test.js +0 -106
  475. package/dist/src/browser/dom-snapshot.test.js +0 -313
  476. package/dist/src/browser/errors.test.js +0 -60
  477. package/dist/src/browser/extract.test.js +0 -129
  478. package/dist/src/browser/find.test.js +0 -180
  479. package/dist/src/browser/html-tree.test.js +0 -181
  480. package/dist/src/browser/network-cache.test.js +0 -58
  481. package/dist/src/browser/network-key.test.js +0 -49
  482. package/dist/src/browser/page.test.js +0 -378
  483. package/dist/src/browser/shape-filter.test.js +0 -101
  484. package/dist/src/browser/shape.test.js +0 -82
  485. package/dist/src/browser/stealth.test.js +0 -134
  486. package/dist/src/browser/target-errors.test.js +0 -94
  487. package/dist/src/browser/target-resolver.test.js +0 -118
  488. package/dist/src/browser/utils.test.js +0 -29
  489. package/dist/src/browser/verify-fixture.test.js +0 -219
  490. package/dist/src/browser.test.js +0 -232
  491. package/dist/src/build-manifest.test.js +0 -341
  492. package/dist/src/capabilityRouting.test.js +0 -63
  493. package/dist/src/cli-argv-preprocess.test.js +0 -209
  494. package/dist/src/cli.test.js +0 -2803
  495. package/dist/src/commanderAdapter.test.js +0 -352
  496. package/dist/src/commands/daemon.test.js +0 -219
  497. package/dist/src/completion.test.js +0 -24
  498. package/dist/src/convention-audit.test.js +0 -247
  499. package/dist/src/daemon.test.js +0 -60
  500. package/dist/src/doctor.test.js +0 -263
  501. package/dist/src/download/article-download.test.js +0 -235
  502. package/dist/src/download/index.test.js +0 -140
  503. package/dist/src/download/media-download.test.js +0 -112
  504. package/dist/src/download/progress.test.js +0 -36
  505. package/dist/src/electron-apps.test.js +0 -49
  506. package/dist/src/engine.test.js +0 -312
  507. package/dist/src/errors.test.js +0 -109
  508. package/dist/src/execution.test.js +0 -623
  509. package/dist/src/extension-manifest-regression.test.js +0 -12
  510. package/dist/src/external.test.js +0 -146
  511. package/dist/src/help.test.js +0 -58
  512. package/dist/src/hooks.test.js +0 -92
  513. package/dist/src/interceptor.test.js +0 -81
  514. package/dist/src/launcher.test.js +0 -138
  515. package/dist/src/node-network.test.js +0 -55
  516. package/dist/src/observation/artifact.test.js +0 -121
  517. package/dist/src/observation/manager.test.js +0 -13
  518. package/dist/src/observation/redaction.test.js +0 -32
  519. package/dist/src/observation/retention.test.js +0 -118
  520. package/dist/src/observation/ring-buffer.test.js +0 -22
  521. package/dist/src/output.test.js +0 -53
  522. package/dist/src/package-exports.test.js +0 -112
  523. package/dist/src/pipeline/executor.test.js +0 -182
  524. package/dist/src/pipeline/steps/download.test.js +0 -102
  525. package/dist/src/pipeline/steps/fetch.test.js +0 -117
  526. package/dist/src/pipeline/template.test.js +0 -175
  527. package/dist/src/pipeline/transform.test.js +0 -133
  528. package/dist/src/plugin-manifest.test.js +0 -179
  529. package/dist/src/plugin-scaffold.test.js +0 -83
  530. package/dist/src/plugin.test.js +0 -1324
  531. package/dist/src/registry.test.js +0 -209
  532. package/dist/src/runtime-detect.test.js +0 -39
  533. package/dist/src/serialization.test.js +0 -78
  534. package/dist/src/snapshotFormatter.test.js +0 -521
  535. package/dist/src/tui.test.js +0 -19
  536. package/dist/src/update-check.test.js +0 -116
  537. package/dist/src/utils.test.js +0 -155
  538. package/dist/src/validate.test.js +0 -90
  539. package/dist/src/weixin-download.test.js +0 -45
@@ -8,18 +8,20 @@
8
8
  * 2. FALLBACK (filesystem scan): Traditional runtime discovery for development.
9
9
  */
10
10
  import * as fs from 'node:fs';
11
- import * as os from 'node:os';
12
11
  import * as path from 'node:path';
13
12
  import { fileURLToPath, pathToFileURL } from 'node:url';
14
13
  import { Strategy, registerCommand } from './registry.js';
15
14
  import { getErrorMessage } from './errors.js';
16
15
  import { log } from './logger.js';
17
16
  import { findPackageRoot, getCliManifestPath } from './package-paths.js';
18
- /** User runtime directory: ~/.bycli */
19
- export const USER_BYCLI_DIR = path.join(os.homedir(), '.bycli');
20
- /** User CLIs directory: ~/.bycli/clis */
21
- export const USER_CLIS_DIR = path.join(USER_BYCLI_DIR, 'clis');
22
- /** Plugins directory: ~/.bycli/plugins/ */
17
+ import { getConfigDir, getUserClisDir } from './config-paths.js';
18
+ /** User runtime directory: BYCLI_CONFIG_DIR or ~/.bycli.
19
+ * Resolved once at module load; the entry process fixes BYCLI_CONFIG_DIR before import. */
20
+ export const USER_BYCLI_DIR = getConfigDir();
21
+ /** User CLIs directory: <config>/clis */
22
+ export const USER_CLIS_DIR = getUserClisDir();
23
+ /** Plugins directory: <config>/plugins/ (plugins are out of scope for the clis/sites
24
+ * relocation; kept as a const that many plugin.ts/tests consumers rely on). */
23
25
  export const PLUGINS_DIR = path.join(USER_BYCLI_DIR, 'plugins');
24
26
  /** Matches files that register commands via cli() or lifecycle hooks */
25
27
  const PLUGIN_MODULE_PATTERN = /\b(?:cli|onStartup|onBeforeExecute|onAfterExecute)\s*\(/;
@@ -111,7 +113,7 @@ export async function discoverClis(...dirs) {
111
113
  * Fast-path: register commands from pre-compiled manifest.
112
114
  * TS modules are deferred — loaded lazily on first execution.
113
115
  */
114
- async function loadFromManifest(manifestPath, clisDir) {
116
+ export async function loadFromManifest(manifestPath, clisDir) {
115
117
  try {
116
118
  const raw = await fs.promises.readFile(manifestPath, 'utf-8');
117
119
  const manifest = JSON.parse(raw);
@@ -119,7 +121,7 @@ async function loadFromManifest(manifestPath, clisDir) {
119
121
  if (!entry.modulePath)
120
122
  continue;
121
123
  const modulePath = path.resolve(clisDir, entry.modulePath);
122
- const cmd = {
124
+ const common = {
123
125
  site: entry.site,
124
126
  name: entry.name,
125
127
  aliases: entry.aliases,
@@ -128,7 +130,6 @@ async function loadFromManifest(manifestPath, clisDir) {
128
130
  example: entry.example,
129
131
  domain: entry.domain,
130
132
  strategy: parseStrategy(entry.strategy),
131
- browser: entry.browser,
132
133
  args: entry.args ?? [],
133
134
  columns: entry.columns,
134
135
  defaultFormat: entry.defaultFormat,
@@ -139,7 +140,16 @@ async function loadFromManifest(manifestPath, clisDir) {
139
140
  _lazy: true,
140
141
  _modulePath: modulePath,
141
142
  };
142
- // normalizeCommand inside registerCommand handles strategy → browser/navigateBefore
143
+ const cmd = entry.browser === 'conditional'
144
+ ? {
145
+ ...common,
146
+ browser: 'conditional',
147
+ requiresBrowser: () => {
148
+ throw new Error(`Conditional manifest placeholder ${entry.site}/${entry.name} was not hydrated`);
149
+ },
150
+ _hydrateBeforeBrowserRouting: true,
151
+ }
152
+ : { ...common, browser: entry.browser };
143
153
  registerCommand(cmd);
144
154
  }
145
155
  return true;
@@ -0,0 +1 @@
1
+ export {};
@@ -11,6 +11,9 @@
11
11
  */
12
12
  import { type CliCommand, type Arg, type CommandArgs } from './registry.js';
13
13
  import { type ObservationExportResult } from './observation/index.js';
14
+ /** Internal test-only reset. Never use this to recover a production process. */
15
+ export declare function _resetLazyModuleStateForTests(): void;
16
+ export declare function _getLazyModuleFingerprintReadCountForTests(): number;
14
17
  export declare function coerceAndValidateArgs(cmdArgs: Arg[], kwargs: CommandArgs): CommandArgs;
15
18
  export declare function executeCommand(cmd: CliCommand, rawKwargs: CommandArgs, debug?: boolean, opts?: {
16
19
  prepared?: boolean;
@@ -22,3 +25,5 @@ export declare function executeCommand(cmd: CliCommand, rawKwargs: CommandArgs,
22
25
  onTraceExport?: (trace: ObservationExportResult) => void;
23
26
  }): Promise<unknown>;
24
27
  export declare function prepareCommandArgs(cmd: CliCommand, rawKwargs: CommandArgs): CommandArgs;
28
+ /** Prepare adapter arguments using the execution boundary's public error contract. */
29
+ export declare function prepareCommandArgsOrThrowArgumentError(cmd: CliCommand, rawKwargs: CommandArgs): CommandArgs;
@@ -13,9 +13,10 @@ import { getRegistry, fullName, } from './registry.js';
13
13
  import { pathToFileURL } from 'node:url';
14
14
  import * as crypto from 'node:crypto';
15
15
  import * as fs from 'node:fs';
16
- import * as os from 'node:os';
16
+ import * as path from 'node:path';
17
+ import { getUserClisDir } from './config-paths.js';
17
18
  import { executePipeline } from './pipeline/index.js';
18
- import { adapterLoadError, ArgumentError, CommandExecutionError, attachTraceReceipt, getErrorMessage } from './errors.js';
19
+ import { adapterLoadError, ArgumentError, CliError, CommandExecutionError, attachTraceReceipt, getErrorMessage } from './errors.js';
19
20
  import { shouldUseBrowserSession } from './capabilityRouting.js';
20
21
  import { getBrowserFactory, browserSession, runWithTimeout, DEFAULT_BROWSER_COMMAND_TIMEOUT } from './runtime.js';
21
22
  import { resolveProfileContextId } from './browser/profile.js';
@@ -25,10 +26,34 @@ import { isElectronApp } from './electron-apps.js';
25
26
  import { probeCDP, resolveElectronEndpoint } from './launcher.js';
26
27
  import { ObservationSession, exportObservationSession } from './observation/index.js';
27
28
  import { resolveAdapterSourcePath } from './adapter-source.js';
29
+ import { canonicalizeManifestArgSchema, ManifestSchemaError } from './manifest-schema.js';
30
+ import { capturedRegistryValues, closeRegistryTransaction, createRegistryTransaction, finalizeRegistryTransaction, resetRegistryTransactionStateForTests, rollbackRegistryTransaction, runRegistryTransaction, transactionGroupsForKey, } from './registry-transaction.js';
28
31
  const _loadedModules = new Map();
29
- /** Track mtime of loaded user adapter files for hot-reload in daemon mode. */
30
- const _moduleMtimes = new Map();
31
- const _userClisDir = `${os.homedir()}/.bycli/clis/`;
32
+ /** Independent cache-busting generation; retained when an import promise is discarded. */
33
+ const _moduleImportGenerations = new Map();
34
+ let _registrationImportTail = Promise.resolve();
35
+ let _registrationImportsPoisoned = false;
36
+ let _fingerprintReadCount = 0;
37
+ const DEFAULT_ADAPTER_IMPORT_TIMEOUT_MS = 30_000;
38
+ function adapterImportTimeoutMs() {
39
+ const configured = Number(process.env.BYCLI_ADAPTER_IMPORT_TIMEOUT_MS);
40
+ return Number.isFinite(configured) && configured > 0 ? configured : DEFAULT_ADAPTER_IMPORT_TIMEOUT_MS;
41
+ }
42
+ function poisonedImportError() {
43
+ return adapterLoadError('Adapter registration imports are unavailable because a previous import timed out.', 'Restart byCLI before retrying; the timed-out module may still complete and register stale commands in this process.');
44
+ }
45
+ /** Internal test-only reset. Never use this to recover a production process. */
46
+ export function _resetLazyModuleStateForTests() {
47
+ _loadedModules.clear();
48
+ _moduleImportGenerations.clear();
49
+ _registrationImportTail = Promise.resolve();
50
+ _registrationImportsPoisoned = false;
51
+ _fingerprintReadCount = 0;
52
+ resetRegistryTransactionStateForTests();
53
+ }
54
+ export function _getLazyModuleFingerprintReadCountForTests() {
55
+ return _fingerprintReadCount;
56
+ }
32
57
  function normalizeTraceMode(raw) {
33
58
  if (raw === undefined || raw === null || raw === '' || raw === 'off')
34
59
  return 'off';
@@ -81,41 +106,19 @@ export function coerceAndValidateArgs(cmdArgs, kwargs) {
81
106
  async function runCommand(cmd, page, kwargs, debug) {
82
107
  const internal = cmd;
83
108
  if (internal._lazy && internal._modulePath) {
84
- const modulePath = internal._modulePath;
85
- // Hot-reload: if a user adapter's file has changed on disk, invalidate cache
86
- const isUserAdapter = modulePath.startsWith(_userClisDir);
87
- if (isUserAdapter && _loadedModules.has(modulePath)) {
88
- try {
89
- const stat = fs.statSync(modulePath);
90
- const prevMtime = _moduleMtimes.get(modulePath);
91
- if (prevMtime !== undefined && stat.mtimeMs !== prevMtime) {
92
- _loadedModules.delete(modulePath);
93
- _moduleMtimes.delete(modulePath);
94
- }
95
- }
96
- catch { /* file may have been deleted; let import below handle it */ }
97
- }
98
- if (!_loadedModules.has(modulePath)) {
99
- const url = pathToFileURL(modulePath).href;
100
- const importUrl = _moduleMtimes.has(modulePath) ? `${url}?t=${Date.now()}` : url;
101
- const loadPromise = import(importUrl).then(() => {
102
- try {
103
- _moduleMtimes.set(modulePath, fs.statSync(modulePath).mtimeMs);
104
- }
105
- catch { }
106
- }, (err) => {
107
- _loadedModules.delete(modulePath);
108
- throw adapterLoadError(`Failed to load adapter module ${modulePath}: ${getErrorMessage(err)}`, 'Check that the adapter file exists and has no syntax errors.');
109
- });
110
- _loadedModules.set(modulePath, loadPromise);
111
- }
112
- await _loadedModules.get(modulePath);
113
- const updated = getRegistry().get(fullName(cmd));
114
- if (updated?.func) {
109
+ const loadedEntry = await loadLazyModule(internal);
110
+ // Use the command registered by this import generation. A newer file
111
+ // generation may already be queued/current, but an execution that began
112
+ // on the older generation is allowed to finish with its own command.
113
+ const updated = loadedEntry?.registeredCommands.get(fullName(cmd));
114
+ if (loadedEntry && updated?.func) {
115
+ finalizeCommandRegistration(loadedEntry, fullName(cmd));
115
116
  return runCommandFunc(updated, page, kwargs, debug);
116
117
  }
117
- if (updated?.pipeline)
118
+ if (loadedEntry && updated?.pipeline) {
119
+ finalizeCommandRegistration(loadedEntry, fullName(cmd));
118
120
  return executePipeline(page, updated.pipeline, { args: kwargs, debug });
121
+ }
119
122
  }
120
123
  if (cmd.func)
121
124
  return runCommandFunc(cmd, page, kwargs, debug);
@@ -123,14 +126,212 @@ async function runCommand(cmd, page, kwargs, debug) {
123
126
  return executePipeline(page, cmd.pipeline, { args: kwargs, debug });
124
127
  throw new CommandExecutionError(`Command ${fullName(cmd)} has no func or pipeline`, 'This is likely a bug in the adapter definition. Please report this issue.');
125
128
  }
129
+ function moduleFingerprint(modulePath) {
130
+ try {
131
+ _fingerprintReadCount += 1;
132
+ return crypto.createHash('sha256').update(fs.readFileSync(modulePath)).digest('hex');
133
+ }
134
+ catch {
135
+ return undefined;
136
+ }
137
+ }
138
+ function isHotReloadableModule(modulePath) {
139
+ const prefix = getUserClisDir() + path.sep;
140
+ return modulePath.startsWith(prefix);
141
+ }
142
+ function refreshCapturedCommands(entry) {
143
+ entry.registeredCommands = capturedRegistryValues(entry.transaction);
144
+ }
145
+ function rollbackImport(entry) {
146
+ rollbackRegistryTransaction(entry.transaction, getRegistry());
147
+ }
148
+ function rollbackCommandRegistration(entry, key) {
149
+ const groups = transactionGroupsForKey(entry.transaction, key);
150
+ rollbackRegistryTransaction(entry.transaction, getRegistry(), groups);
151
+ }
152
+ function finalizeCommandRegistration(entry, key) {
153
+ const groups = transactionGroupsForKey(entry.transaction, key);
154
+ finalizeRegistryTransaction(entry.transaction, getRegistry(), groups);
155
+ }
156
+ async function performRegistrationImport(entry, importUrl, modulePath) {
157
+ if (_registrationImportsPoisoned)
158
+ throw poisonedImportError();
159
+ const settlement = runRegistryTransaction(entry.transaction, () => import(importUrl)).then(() => ({ ok: true }), (error) => ({ ok: false, error }));
160
+ let timeoutId;
161
+ const timeout = new Promise((resolve) => {
162
+ timeoutId = setTimeout(() => resolve({ timeout: true }), adapterImportTimeoutMs());
163
+ });
164
+ const outcome = await Promise.race([settlement, timeout]);
165
+ if ('timeout' in outcome) {
166
+ _registrationImportsPoisoned = true;
167
+ closeRegistryTransaction(entry.transaction);
168
+ rollbackImport(entry);
169
+ void settlement.then(() => {
170
+ refreshCapturedCommands(entry);
171
+ rollbackImport(entry);
172
+ });
173
+ throw adapterLoadError(`Adapter module ${modulePath} registration timed out after ${adapterImportTimeoutMs()}ms.`, 'Restart byCLI before retrying; ESM evaluation cannot be cancelled safely.');
174
+ }
175
+ if (timeoutId)
176
+ clearTimeout(timeoutId);
177
+ refreshCapturedCommands(entry);
178
+ if (!outcome.ok) {
179
+ rollbackImport(entry);
180
+ throw adapterLoadError(`Failed to load adapter module ${modulePath}: ${getErrorMessage(outcome.error)}`, 'Check that the adapter file exists and has no syntax errors.');
181
+ }
182
+ }
183
+ function scheduleRegistrationImport(entry, importUrl, modulePath) {
184
+ const scheduled = _registrationImportTail.then(() => performRegistrationImport(entry, importUrl, modulePath), () => performRegistrationImport(entry, importUrl, modulePath));
185
+ _registrationImportTail = scheduled.then(() => undefined, () => undefined);
186
+ return scheduled;
187
+ }
188
+ async function loadLazyModule(internal) {
189
+ const modulePath = internal._modulePath;
190
+ if (!internal._lazy || !modulePath)
191
+ return;
192
+ let entry = _loadedModules.get(modulePath);
193
+ if (entry) {
194
+ if (!entry.hotReloadable) {
195
+ await entry.promise;
196
+ return entry;
197
+ }
198
+ const currentFingerprint = moduleFingerprint(modulePath);
199
+ if (entry.fingerprint === currentFingerprint) {
200
+ await entry.promise;
201
+ return entry;
202
+ }
203
+ if (_registrationImportsPoisoned)
204
+ throw poisonedImportError();
205
+ invalidateLazyModule(modulePath, entry);
206
+ entry = undefined;
207
+ }
208
+ if (_registrationImportsPoisoned)
209
+ throw poisonedImportError();
210
+ if (!entry) {
211
+ const hotReloadable = isHotReloadableModule(modulePath);
212
+ const fingerprint = hotReloadable ? moduleFingerprint(modulePath) : undefined;
213
+ const url = pathToFileURL(modulePath).href;
214
+ const generation = _moduleImportGenerations.get(modulePath) ?? 0;
215
+ const importUrl = generation === 0 ? url : `${url}?v=${generation}`;
216
+ const createdEntry = {
217
+ promise: Promise.resolve(),
218
+ fingerprint,
219
+ generation,
220
+ registeredCommands: new Map(),
221
+ transaction: createRegistryTransaction(),
222
+ hotReloadable,
223
+ };
224
+ createdEntry.promise = scheduleRegistrationImport(createdEntry, importUrl, modulePath).catch((error) => {
225
+ invalidateLazyModule(modulePath, createdEntry);
226
+ throw error;
227
+ });
228
+ _loadedModules.set(modulePath, createdEntry);
229
+ entry = createdEntry;
230
+ }
231
+ await entry.promise;
232
+ return entry;
233
+ }
234
+ function invalidateLazyModule(modulePath, expectedEntry) {
235
+ if (!modulePath)
236
+ return;
237
+ const currentEntry = _loadedModules.get(modulePath);
238
+ if (!currentEntry || (expectedEntry && currentEntry !== expectedEntry))
239
+ return;
240
+ if (currentEntry.transaction.active) {
241
+ void currentEntry.promise.then(() => finalizeRegistryTransaction(currentEntry.transaction, getRegistry()), () => finalizeRegistryTransaction(currentEntry.transaction, getRegistry()));
242
+ }
243
+ else {
244
+ finalizeRegistryTransaction(currentEntry.transaction, getRegistry());
245
+ }
246
+ _loadedModules.delete(modulePath);
247
+ _moduleImportGenerations.set(modulePath, Math.max(_moduleImportGenerations.get(modulePath) ?? 0, currentEntry.generation) + 1);
248
+ }
249
+ function assertMatchingArgSchema(placeholder, hydrated, loadedEntry) {
250
+ const key = fullName(placeholder);
251
+ try {
252
+ const manifestSchema = canonicalizeManifestArgSchema(placeholder.args, `Manifest command ${key}`);
253
+ const moduleSchema = canonicalizeManifestArgSchema(hydrated.args, `Hydrated command ${key}`);
254
+ if (manifestSchema === moduleSchema)
255
+ return;
256
+ }
257
+ catch (error) {
258
+ if (loadedEntry)
259
+ rollbackCommandRegistration(loadedEntry, key);
260
+ invalidateLazyModule(placeholder._modulePath, loadedEntry);
261
+ if (!(error instanceof ManifestSchemaError))
262
+ throw error;
263
+ throw new CommandExecutionError(`Conditional adapter ${key} has an unsafe argument schema: ${error.message}`, 'Use only JSON-safe defaults and string choices, then rebuild the CLI manifest.');
264
+ }
265
+ if (loadedEntry)
266
+ rollbackCommandRegistration(loadedEntry, key);
267
+ invalidateLazyModule(placeholder._modulePath, loadedEntry);
268
+ throw new CommandExecutionError(`Conditional adapter ${key} argument schema does not match its manifest`, 'Rebuild the CLI manifest so defaults, coercion, and validation use the adapter module schema.');
269
+ }
270
+ async function hydrateConditionalCommand(cmd) {
271
+ const internal = cmd;
272
+ const key = fullName(cmd);
273
+ if (cmd.browser !== 'conditional') {
274
+ throw new CommandExecutionError(`Conditional adapter placeholder ${key} has invalid browser metadata`, 'Rebuild the CLI manifest with the current byCLI version.');
275
+ }
276
+ const placeholderResolver = cmd.requiresBrowser;
277
+ let loadedEntry;
278
+ try {
279
+ loadedEntry = await loadLazyModule(internal);
280
+ }
281
+ catch (error) {
282
+ if (error instanceof CliError)
283
+ throw error;
284
+ throw new CommandExecutionError(`Failed to hydrate conditional adapter ${key}: ${getErrorMessage(error)}`, 'Rebuild or reinstall the adapter so its manifest and module are both available.');
285
+ }
286
+ const hydrated = loadedEntry?.registeredCommands.get(key);
287
+ const invalidReplacement = !hydrated
288
+ || hydrated === cmd
289
+ || fullName(hydrated) !== key
290
+ || hydrated.browser !== 'conditional';
291
+ if (invalidReplacement) {
292
+ if (loadedEntry)
293
+ rollbackCommandRegistration(loadedEntry, key);
294
+ invalidateLazyModule(internal._modulePath, loadedEntry);
295
+ throw new CommandExecutionError(`Conditional adapter ${key} did not register a valid hydrated conditional command`, 'Ensure the module registers the same site/name with a browser predicate and is rebuilt with the current byCLI version.');
296
+ }
297
+ const hydratedInternal = hydrated;
298
+ if (typeof hydrated.requiresBrowser !== 'function'
299
+ || hydrated.requiresBrowser === placeholderResolver
300
+ || hydratedInternal._hydrateBeforeBrowserRouting === true
301
+ || hydratedInternal._lazy === true
302
+ || hydratedInternal._modulePath !== undefined) {
303
+ if (loadedEntry)
304
+ rollbackCommandRegistration(loadedEntry, key);
305
+ invalidateLazyModule(internal._modulePath, loadedEntry);
306
+ throw new CommandExecutionError(`Conditional adapter ${key} did not register a valid hydrated conditional command`, 'Ensure the module registers the same site/name with a browser predicate and is rebuilt with the current byCLI version.');
307
+ }
308
+ assertMatchingArgSchema(cmd, hydrated, loadedEntry);
309
+ if (loadedEntry)
310
+ finalizeCommandRegistration(loadedEntry, key);
311
+ return hydrated;
312
+ }
126
313
  function runCommandFunc(cmd, page, kwargs, debug) {
127
314
  if (cmd.browser === false)
128
315
  return cmd.func(kwargs, debug);
316
+ if (cmd.browser === 'conditional')
317
+ return cmd.func(page, kwargs, debug);
129
318
  if (!page) {
130
319
  throw new CommandExecutionError(`Command ${fullName(cmd)} requires a browser session but none was provided`);
131
320
  }
132
321
  return cmd.func(page, kwargs, debug);
133
322
  }
323
+ function resolveBrowserRequirement(cmd, kwargs) {
324
+ if (cmd.browser !== 'conditional')
325
+ return cmd.browser;
326
+ try {
327
+ return Boolean(cmd.requiresBrowser(kwargs));
328
+ }
329
+ catch (error) {
330
+ if (error instanceof CliError)
331
+ throw error;
332
+ throw new CommandExecutionError(`Browser requirement evaluation failed for ${fullName(cmd)}: ${getErrorMessage(error)}`);
333
+ }
334
+ }
134
335
  function resolvePreNav(cmd) {
135
336
  if (cmd.navigateBefore === false)
136
337
  return null;
@@ -172,16 +373,24 @@ async function shouldRunPreNav(cmd, page, siteSession, preNavUrl) {
172
373
  return !urlMatchesDomain(currentUrl, cmd.domain);
173
374
  }
174
375
  export async function executeCommand(cmd, rawKwargs, debug = false, opts = {}) {
175
- let kwargs;
176
- try {
177
- kwargs = opts.prepared ? rawKwargs : prepareCommandArgs(cmd, rawKwargs);
178
- }
179
- catch (err) {
180
- if (err instanceof ArgumentError)
181
- throw err;
182
- throw new ArgumentError(getErrorMessage(err));
376
+ const initialTraceCommand = cmd;
377
+ let kwargs = opts.prepared
378
+ ? rawKwargs
379
+ : prepareCommandArgsOrThrowArgumentError(cmd, rawKwargs);
380
+ if (cmd._hydrateBeforeBrowserRouting) {
381
+ cmd = await hydrateConditionalCommand(cmd);
382
+ // Manifest placeholders cannot serialize adapter validators. The matching
383
+ // schema above guarantees coercion/defaults stay valid; run only the real
384
+ // module validator here so custom validation has exactly one side effect.
385
+ try {
386
+ cmd.validateArgs?.(kwargs);
387
+ }
388
+ catch (error) {
389
+ if (error instanceof ArgumentError)
390
+ throw error;
391
+ throw new ArgumentError(getErrorMessage(error));
392
+ }
183
393
  }
184
- const userTimeoutSec = readUserTimeoutSeconds(cmd, kwargs);
185
394
  const traceMode = normalizeTraceMode(opts.trace);
186
395
  const hookCtx = {
187
396
  command: fullName(cmd),
@@ -189,9 +398,12 @@ export async function executeCommand(cmd, rawKwargs, debug = false, opts = {}) {
189
398
  startedAt: Date.now(),
190
399
  };
191
400
  await emitHook('onBeforeExecute', hookCtx);
401
+ kwargs = hookCtx.args;
192
402
  let result;
193
403
  try {
194
- if (shouldUseBrowserSession(cmd)) {
404
+ const resolvedBrowser = resolveBrowserRequirement(cmd, kwargs);
405
+ const userTimeoutSec = readUserTimeoutSeconds(cmd, kwargs);
406
+ if (shouldUseBrowserSession(cmd, resolvedBrowser)) {
195
407
  const electron = isElectronApp(cmd.site);
196
408
  let cdpEndpoint;
197
409
  if (electron) {
@@ -225,7 +437,8 @@ export async function executeCommand(cmd, rawKwargs, debug = false, opts = {}) {
225
437
  target: page.getActivePage?.(),
226
438
  site: cmd.site,
227
439
  command: fullName(cmd),
228
- adapterSourcePath: resolveAdapterSourcePath(internal),
440
+ adapterSourcePath: resolveAdapterSourcePath(internal)
441
+ ?? resolveAdapterSourcePath(initialTraceCommand),
229
442
  },
230
443
  });
231
444
  if (observation) {
@@ -433,6 +646,17 @@ export function prepareCommandArgs(cmd, rawKwargs) {
433
646
  cmd.validateArgs?.(kwargs);
434
647
  return kwargs;
435
648
  }
649
+ /** Prepare adapter arguments using the execution boundary's public error contract. */
650
+ export function prepareCommandArgsOrThrowArgumentError(cmd, rawKwargs) {
651
+ try {
652
+ return prepareCommandArgs(cmd, rawKwargs);
653
+ }
654
+ catch (err) {
655
+ if (err instanceof ArgumentError)
656
+ throw err;
657
+ throw new ArgumentError(getErrorMessage(err));
658
+ }
659
+ }
436
660
  /**
437
661
  * Runtime ceiling padding (seconds) added on top of the user's `--timeout`.
438
662
  * The adapter's polling loop typically uses the full user value; the padding
package/dist/src/help.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import yaml from 'js-yaml';
2
- import { fullName } from './registry.js';
2
+ import { browserRequirementLabel, fullName, hasBrowserCapability } from './registry.js';
3
3
  import { formatCommandExample } from './serialization.js';
4
4
  const COMMON_OPTIONS = [
5
5
  {
@@ -363,12 +363,12 @@ function compactCommand(cmd) {
363
363
  usage: formatUsage(cmd),
364
364
  access: cmd.access,
365
365
  description: cmd.description,
366
- browser: !!cmd.browser,
366
+ browser: cmd.browser,
367
367
  ...(cmd.domain ? { domain: cmd.domain } : {}),
368
368
  ...(cmd.aliases?.length ? { aliases: cmd.aliases } : {}),
369
369
  positionals: positionals(cmd).map(compactArg),
370
370
  command_options: commandOptions(cmd).map(compactArg),
371
- ...(cmd.browser ? { browser_common_options: BROWSER_COMMON_OPTIONS.map(compactCommonOption) } : {}),
371
+ ...(hasBrowserCapability(cmd) ? { browser_common_options: BROWSER_COMMON_OPTIONS.map(compactCommonOption) } : {}),
372
372
  example: formatCommandExample(cmd),
373
373
  ...(cmd.siteSession ? { siteSession: cmd.siteSession } : {}),
374
374
  ...(cmd.defaultFormat ? { defaultFormat: cmd.defaultFormat } : {}),
@@ -416,7 +416,7 @@ export function siteHelpData(site, commands) {
416
416
  command_count: unique.length,
417
417
  commands: unique.map(cmd => compactCommand(cmd)),
418
418
  common_options: COMMON_OPTIONS.map(compactCommonOption),
419
- ...(unique.some(cmd => cmd.browser) ? { browser_common_options: BROWSER_COMMON_OPTIONS.map(compactCommonOption) } : {}),
419
+ ...(unique.some(hasBrowserCapability) ? { browser_common_options: BROWSER_COMMON_OPTIONS.map(compactCommonOption) } : {}),
420
420
  next: [
421
421
  `bycli ${site} <command> --help -f yaml`,
422
422
  `bycli ${site} <command> -f yaml`,
@@ -428,7 +428,7 @@ export function commandHelpData(cmd) {
428
428
  site: cmd.site,
429
429
  ...compactCommand(cmd),
430
430
  common_options: COMMON_OPTIONS.map(compactCommonOption),
431
- ...(cmd.browser ? { browser_common_options: BROWSER_COMMON_OPTIONS.map(compactCommonOption) } : {}),
431
+ ...(hasBrowserCapability(cmd) ? { browser_common_options: BROWSER_COMMON_OPTIONS.map(compactCommonOption) } : {}),
432
432
  output_formats: ['table', 'plain', 'yaml', 'json', 'md', 'csv'],
433
433
  };
434
434
  }
@@ -480,7 +480,7 @@ export function formatSiteHelpText(site, commands) {
480
480
  ...formatRows(unique.map(cmd => [formatCommandListTerm(cmd), formatSiteCommandDescription(cmd)])),
481
481
  '',
482
482
  formatCommonOptionsHelpText(),
483
- ...(unique.some(cmd => cmd.browser) ? ['', formatBrowserCommonOptionsHelpText()] : []),
483
+ ...(unique.some(hasBrowserCapability) ? ['', formatBrowserCommonOptionsHelpText()] : []),
484
484
  '',
485
485
  `Agent tip: use 'bycli ${site} --help -f yaml' to get all command args/options in one structured response.`,
486
486
  '',
@@ -509,11 +509,11 @@ export function formatCommandHelpText(cmd) {
509
509
  lines.push('Command options:', ...formatRows(optionRows), '');
510
510
  }
511
511
  lines.push(formatCommonOptionsHelpText(), '');
512
- if (cmd.browser)
512
+ if (hasBrowserCapability(cmd))
513
513
  lines.push(formatBrowserCommonOptionsHelpText(), '');
514
514
  const meta = [];
515
515
  meta.push(`Access: ${cmd.access}`);
516
- meta.push(`Browser: ${cmd.browser ? 'yes' : 'no'}`);
516
+ meta.push(`Browser: ${browserRequirementLabel(cmd)}`);
517
517
  if (cmd.domain)
518
518
  meta.push(`Domain: ${cmd.domain}`);
519
519
  if (cmd.defaultFormat)
package/dist/src/main.js CHANGED
@@ -13,8 +13,8 @@ if (process.platform !== 'win32') {
13
13
  process.env.PATH = [...cur].join(':');
14
14
  }
15
15
  import * as fs from 'node:fs';
16
- import * as os from 'node:os';
17
16
  import * as path from 'node:path';
17
+ import { getUserClisDir } from './config-paths.js';
18
18
  import { fileURLToPath } from 'node:url';
19
19
  import { getCompletionsFromManifest, hasAllManifests, printCompletionScriptFast } from './completion-fast.js';
20
20
  import { findPackageRoot, getCliManifestPath } from './package-paths.js';
@@ -26,7 +26,7 @@ const __dirname = path.dirname(__filename);
26
26
  // Adapters are JS-first and live at <package-root>/clis/.
27
27
  // Use findPackageRoot so the path works both in dev (src/main.ts) and prod (dist/src/main.js).
28
28
  const BUILTIN_CLIS = path.join(findPackageRoot(__filename), 'clis');
29
- const USER_CLIS = path.join(os.homedir(), '.bycli', 'clis');
29
+ const USER_CLIS = getUserClisDir();
30
30
  // ── Ultra-fast path: lightweight commands bypass full discovery ──────────
31
31
  // These are high-frequency or trivial paths that must not pay the startup tax.
32
32
  const argv = process.argv.slice(2);
@@ -52,6 +52,22 @@ if (argv[0] === 'completion' && argv.length >= 2) {
52
52
  }
53
53
  // Unknown shell — fall through to full path for proper error handling
54
54
  }
55
+ // Fast path: internal verify-runner — the child process spawned by the verify RunnerPort
56
+ // (08). It loads ONLY the target adapter (by path, from input.json) and emits JSONL; it must
57
+ // never run full adapter discovery, and its stdout must stay pure JSONL.
58
+ if (argv[0] === 'internal' && argv[1] === 'verify-runner') {
59
+ const { runVerifyRunnerCli } = await import('./recorder/runner/verify-runner-main.js');
60
+ await runVerifyRunnerCli(argv.slice(2));
61
+ process.exit(process.exitCode ?? EXIT_CODES.SUCCESS);
62
+ }
63
+ // Fast path: internal highlevel-http — the OPTIONAL standalone High-Level HTTP wrapper (M9,
64
+ // 07 · Optional HTTP Wrapper). Default off; opt-in only via this command. Binds 127.0.0.1 and
65
+ // keeps running, so it must skip full adapter discovery. Distinct from the daemon /v1/* family.
66
+ if (argv[0] === 'internal' && argv[1] === 'highlevel-http') {
67
+ const { runWrapperCli } = await import('./recorder/http/wrapper-server.js');
68
+ await runWrapperCli(); // blocks while the server is alive; resolves on close (SIGTERM/SIGINT)
69
+ process.exit(process.exitCode ?? EXIT_CODES.SUCCESS); // never fall through to CLI discovery
70
+ }
55
71
  // Fast path: --get-completions — read from manifest, skip discovery
56
72
  const getCompIdx = process.argv.indexOf('--get-completions');
57
73
  if (getCompIdx !== -1) {
@@ -0,0 +1,9 @@
1
+ import type { Arg } from './registry.js';
2
+ export declare class ManifestSchemaError extends Error {
3
+ constructor(message: string);
4
+ }
5
+ /**
6
+ * Canonical execution-relevant argument schema used by both manifest build and
7
+ * runtime hydration. Objects are key-order independent; arrays remain ordered.
8
+ */
9
+ export declare function canonicalizeManifestArgSchema(args: readonly Arg[], context: string): string;