@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.
- package/cli-manifest.json +0 -61
- package/clis/twitter/search.js +3 -3
- package/dist/src/adapter-shadow.js +2 -2
- package/dist/src/browser/analyze.d.ts +10 -99
- package/dist/src/browser/analyze.js +10 -226
- package/dist/src/browser/cdp.js +67 -7
- package/dist/src/browser/daemon-client.d.ts +2 -0
- package/dist/src/browser/daemon-client.js +1 -1
- package/dist/src/browser/extension-capabilities.d.ts +13 -0
- package/dist/src/browser/extension-capabilities.js +22 -0
- package/dist/src/browser/extension-capabilities.test.d.ts +1 -0
- package/dist/src/browser/extension-version-metadata.test.d.ts +1 -0
- package/dist/src/browser/navigation-guard.d.ts +78 -0
- package/dist/src/browser/navigation-guard.js +142 -0
- package/dist/src/browser/navigation-guard.test.d.ts +1 -0
- package/dist/src/browser/page.d.ts +1 -0
- package/dist/src/browser/page.js +20 -1
- package/dist/src/browser/url-policy.d.ts +89 -0
- package/dist/src/browser/url-policy.js +311 -0
- package/dist/src/browser/url-policy.test.d.ts +1 -0
- package/dist/src/browser/verify-fixture.js +2 -2
- package/dist/src/build-manifest.js +4 -2
- package/dist/src/capabilityRouting.d.ts +3 -2
- package/dist/src/capabilityRouting.js +10 -2
- package/dist/src/cli.js +11 -14
- package/dist/src/commanderAdapter.js +5 -5
- package/dist/src/config-paths.d.ts +19 -0
- package/dist/src/config-paths.js +31 -0
- package/dist/src/daemon.js +256 -0
- package/dist/src/discovery.d.ts +10 -3
- package/dist/src/discovery.js +20 -10
- package/dist/src/discovery.test.d.ts +1 -0
- package/dist/src/execution.d.ts +5 -0
- package/dist/src/execution.js +272 -48
- package/dist/src/help.js +8 -8
- package/dist/src/main.js +18 -2
- package/dist/src/manifest-schema.d.ts +9 -0
- package/dist/src/manifest-schema.js +162 -0
- package/dist/src/manifest-schema.test.d.ts +1 -0
- package/dist/src/manifest-types.d.ts +1 -1
- package/dist/src/observation/redaction.js +10 -4
- package/dist/src/plugin.js +11 -8
- package/dist/src/recorder/highlevel/analyze.d.ts +29 -0
- package/dist/src/recorder/highlevel/analyze.js +91 -0
- package/dist/src/recorder/highlevel/init.d.ts +125 -0
- package/dist/src/recorder/highlevel/init.js +279 -0
- package/dist/src/recorder/highlevel/init.test.d.ts +1 -0
- package/dist/src/recorder/highlevel/verify.d.ts +73 -0
- package/dist/src/recorder/highlevel/verify.js +74 -0
- package/dist/src/recorder/http/analyze-runner.d.ts +28 -0
- package/dist/src/recorder/http/analyze-runner.js +78 -0
- package/dist/src/recorder/http/analyze-runner.test.d.ts +1 -0
- package/dist/src/recorder/http/handlers.d.ts +51 -0
- package/dist/src/recorder/http/handlers.js +219 -0
- package/dist/src/recorder/http/wrapper-config.d.ts +20 -0
- package/dist/src/recorder/http/wrapper-config.js +82 -0
- package/dist/src/recorder/http/wrapper-envelope.d.ts +31 -0
- package/dist/src/recorder/http/wrapper-envelope.js +51 -0
- package/dist/src/recorder/http/wrapper-gates.d.ts +16 -0
- package/dist/src/recorder/http/wrapper-gates.js +28 -0
- package/dist/src/recorder/http/wrapper-metrics.d.ts +1 -0
- package/dist/src/recorder/http/wrapper-metrics.js +5 -0
- package/dist/src/recorder/http/wrapper-registry.d.ts +50 -0
- package/dist/src/recorder/http/wrapper-registry.js +98 -0
- package/dist/src/recorder/http/wrapper-server.d.ts +59 -0
- package/dist/src/recorder/http/wrapper-server.js +240 -0
- package/dist/src/recorder/http/wrapper.test.d.ts +1 -0
- package/dist/src/recorder/observability/logger.d.ts +5 -0
- package/dist/src/recorder/observability/logger.js +13 -0
- package/dist/src/recorder/runner/config.d.ts +34 -0
- package/dist/src/recorder/runner/config.js +84 -0
- package/dist/src/recorder/runner/config.test.d.ts +1 -0
- package/dist/src/recorder/runner/reap.d.ts +79 -0
- package/dist/src/recorder/runner/reap.js +230 -0
- package/dist/src/recorder/runner/reap.test.d.ts +1 -0
- package/dist/src/recorder/runner/runner-port.d.ts +95 -0
- package/dist/src/recorder/runner/runner-port.js +518 -0
- package/dist/src/recorder/runner/runner-port.test.d.ts +1 -0
- package/dist/src/recorder/runner/session-keys.d.ts +28 -0
- package/dist/src/recorder/runner/session-keys.js +72 -0
- package/dist/src/recorder/runner/session-keys.test.d.ts +1 -0
- package/dist/src/recorder/runner/verify-runner-main.d.ts +96 -0
- package/dist/src/recorder/runner/verify-runner-main.js +292 -0
- package/dist/src/recorder/runner/verify-runner-main.test.d.ts +1 -0
- package/dist/src/registry-api.d.ts +1 -1
- package/dist/src/registry-api.types.test.d.ts +1 -0
- package/dist/src/registry-transaction.d.ts +42 -0
- package/dist/src/registry-transaction.js +194 -0
- package/dist/src/registry-transaction.test.d.ts +1 -0
- package/dist/src/registry.d.ts +58 -16
- package/dist/src/registry.js +131 -15
- package/dist/src/serialization.d.ts +1 -1
- package/dist/src/serialization.js +3 -3
- package/dist/src/types.d.ts +2 -0
- package/package.json +8 -5
- package/scripts/m1-daemon-navigate-drive.mjs +138 -0
- package/scripts/m1-extension-spike.mjs +237 -0
- package/scripts/m1-live-spike.mjs +156 -0
- package/scripts/m6b-connect-back-spike.sh +31 -0
- package/clis/12306/utils.test.js +0 -331
- package/clis/1688/assets.test.js +0 -39
- package/clis/1688/download.test.js +0 -31
- package/clis/1688/item.test.js +0 -67
- package/clis/1688/search.test.js +0 -75
- package/clis/1688/shared.test.js +0 -57
- package/clis/1688/store.test.js +0 -62
- package/clis/36kr/article.test.js +0 -46
- package/clis/36kr/hot.test.js +0 -15
- package/clis/36kr/news.test.js +0 -85
- package/clis/51job/utils.test.js +0 -69
- package/clis/_atlassian/shared.test.js +0 -170
- package/clis/aibase/news.test.js +0 -59
- package/clis/amazon/bestsellers.test.js +0 -29
- package/clis/amazon/discussion.test.js +0 -124
- package/clis/amazon/offer.test.js +0 -29
- package/clis/amazon/product.test.js +0 -24
- package/clis/amazon/rankings.test.js +0 -41
- package/clis/amazon/search.test.js +0 -22
- package/clis/amazon/shared.test.js +0 -44
- package/clis/apple-podcasts/commands.test.js +0 -119
- package/clis/apple-podcasts/utils.test.js +0 -57
- package/clis/arxiv/arxiv.test.js +0 -112
- package/clis/baidu-scholar/search.test.js +0 -23
- package/clis/barchart/greeks.test.js +0 -138
- package/clis/bilibili/comment.test.js +0 -153
- package/clis/bilibili/comments.test.js +0 -142
- package/clis/bilibili/dynamic.test.js +0 -68
- package/clis/bilibili/hot.test.js +0 -17
- package/clis/bilibili/subtitle.test.js +0 -196
- package/clis/bilibili/summary.test.js +0 -210
- package/clis/bilibili/utils.test.js +0 -61
- package/clis/bilibili/video.test.js +0 -132
- package/clis/binance/commands.test.js +0 -70
- package/clis/bloomberg/utils.test.js +0 -129
- package/clis/booking/booking.test.js +0 -356
- package/clis/boss/chatlist.test.js +0 -211
- package/clis/boss/chatmsg.test.js +0 -230
- package/clis/boss/search.test.js +0 -78
- package/clis/boss/utils.test.js +0 -34
- package/clis/brave/search.test.js +0 -76
- package/clis/chaoxing/utils.test.js +0 -45
- package/clis/chatgpt/commands.test.js +0 -45
- package/clis/chatgpt/envelope.test.js +0 -108
- package/clis/chatgpt/image.test.js +0 -188
- package/clis/chatgpt/utils.test.js +0 -330
- package/clis/chatgpt-app/ax.test.js +0 -35
- package/clis/chatwise/composer.test.js +0 -186
- package/clis/chess/analyze.test.js +0 -79
- package/clis/chess/game.test.js +0 -178
- package/clis/chess/games.test.js +0 -164
- package/clis/chess/stats.test.js +0 -79
- package/clis/chess/utils.test.js +0 -230
- package/clis/claude/ask.test.js +0 -338
- package/clis/claude/commands.test.js +0 -118
- package/clis/claude/utils.test.js +0 -148
- package/clis/cnki/search.test.js +0 -18
- package/clis/codex/sidebar.test.js +0 -329
- package/clis/coingecko/coingecko.test.js +0 -109
- package/clis/confluence/commands.test.js +0 -195
- package/clis/coupang/coupang.test.js +0 -159
- package/clis/coupang/utils.test.js +0 -62
- package/clis/ctrip/ctrip.test.js +0 -719
- package/clis/dblp/dblp.test.js +0 -397
- package/clis/deepseek/ask.test.js +0 -312
- package/clis/deepseek/detail.test.js +0 -81
- package/clis/deepseek/send.test.js +0 -107
- package/clis/deepseek/utils.test.js +0 -370
- package/clis/defillama/defillama.test.js +0 -99
- package/clis/devto/devto.test.js +0 -236
- package/clis/dianping/dianping.test.js +0 -578
- package/clis/douban/download.test.js +0 -170
- package/clis/douban/movie-hot.test.js +0 -14
- package/clis/douban/search.test.js +0 -11
- package/clis/douban/subject.test.js +0 -11
- package/clis/douban/utils.test.js +0 -438
- package/clis/doubao/detail.test.js +0 -42
- package/clis/doubao/history.test.js +0 -37
- package/clis/doubao/utils.test.js +0 -344
- package/clis/douyin/_shared/browser-fetch.test.js +0 -64
- package/clis/douyin/_shared/creation-id.test.js +0 -22
- package/clis/douyin/_shared/imagex-upload.test.js +0 -87
- package/clis/douyin/_shared/sts2.test.js +0 -27
- package/clis/douyin/_shared/text-extra.test.js +0 -37
- package/clis/douyin/_shared/timing.test.js +0 -28
- package/clis/douyin/_shared/tos-upload-short-read.test.js +0 -83
- package/clis/douyin/_shared/tos-upload.test.js +0 -229
- package/clis/douyin/_shared/transcode.test.js +0 -91
- package/clis/douyin/_shared/vod-upload.test.js +0 -38
- package/clis/douyin/activities.test.js +0 -55
- package/clis/douyin/collections.test.js +0 -45
- package/clis/douyin/delete.test.js +0 -100
- package/clis/douyin/draft.test.js +0 -335
- package/clis/douyin/drafts.test.js +0 -11
- package/clis/douyin/hashtag.test.js +0 -171
- package/clis/douyin/location.test.js +0 -23
- package/clis/douyin/profile.test.js +0 -46
- package/clis/douyin/publish-upload-id.test.js +0 -170
- package/clis/douyin/publish.test.js +0 -38
- package/clis/douyin/stats.test.js +0 -22
- package/clis/douyin/update.test.js +0 -11
- package/clis/douyin/user-videos.test.js +0 -151
- package/clis/douyin/videos.test.js +0 -54
- package/clis/duckduckgo/search.test.js +0 -128
- package/clis/duckduckgo/suggest.test.js +0 -66
- package/clis/eastmoney/hot-rank.test.js +0 -59
- package/clis/endoflife/endoflife.test.js +0 -51
- package/clis/facebook/feed.test.js +0 -169
- package/clis/facebook/marketplace.test.js +0 -91
- package/clis/facebook/notifications.test.js +0 -458
- package/clis/facebook/search.test.js +0 -55
- package/clis/flathub/flathub.test.js +0 -90
- package/clis/flomo/memos.test.js +0 -144
- package/clis/gemini/ask.test.js +0 -100
- package/clis/gemini/deep-research-result.test.js +0 -155
- package/clis/gemini/deep-research.test.js +0 -181
- package/clis/gemini/reply-state.test.js +0 -671
- package/clis/gemini/utils.test.js +0 -198
- package/clis/geogebra/geogebra.test.js +0 -175
- package/clis/gitee/search.test.js +0 -65
- package/clis/gitee/user.test.js +0 -63
- package/clis/google/utils.test.js +0 -75
- package/clis/google-scholar/cite.test.js +0 -47
- package/clis/google-scholar/profile.test.js +0 -49
- package/clis/google-scholar/search.test.js +0 -71
- package/clis/goproxy/goproxy.test.js +0 -103
- package/clis/gov-law/commands.test.js +0 -39
- package/clis/gov-policy/gov-policy.test.js +0 -224
- package/clis/grok/ask.test.js +0 -29
- package/clis/grok/utils.test.js +0 -103
- package/clis/hackernews/hackernews.test.js +0 -132
- package/clis/hf/hf.test.js +0 -16
- package/clis/hupu/hot.test.js +0 -224
- package/clis/imdb/utils.test.js +0 -88
- package/clis/indeed/indeed.test.js +0 -375
- package/clis/instagram/_shared/private-publish.test.js +0 -705
- package/clis/instagram/_shared/protocol-capture.test.js +0 -114
- package/clis/instagram/download.test.js +0 -118
- package/clis/instagram/note.test.js +0 -53
- package/clis/instagram/post.test.js +0 -1647
- package/clis/instagram/reel.test.js +0 -167
- package/clis/instagram/story.test.js +0 -134
- package/clis/jd/commands.test.js +0 -41
- package/clis/jd/item.test.js +0 -354
- package/clis/jianyu/search.test.js +0 -153
- package/clis/jianyu/shared/procurement-contract.test.js +0 -72
- package/clis/jianyu/shared/procurement-detail.test.js +0 -84
- package/clis/jike/read.test.js +0 -86
- package/clis/jira/commands.test.js +0 -287
- package/clis/juejin/search.js +0 -123
- package/clis/juejin/search.test.js +0 -98
- package/clis/lesswrong/frontpage.test.js +0 -37
- package/clis/lichess/lichess.test.js +0 -85
- package/clis/linkedin/connect.test.js +0 -213
- package/clis/linkedin/inbox.test.js +0 -152
- package/clis/linkedin/job-detail.test.js +0 -38
- package/clis/linkedin/jobs-preferences.test.js +0 -43
- package/clis/linkedin/people-search.test.js +0 -216
- package/clis/linkedin/post-analytics.test.js +0 -40
- package/clis/linkedin/posts.test.js +0 -40
- package/clis/linkedin/profile-analytics.test.js +0 -67
- package/clis/linkedin/profile-experience.test.js +0 -152
- package/clis/linkedin/profile-projects.test.js +0 -111
- package/clis/linkedin/profile-read.test.js +0 -77
- package/clis/linkedin/safe-send.test.js +0 -204
- package/clis/linkedin/salesnav-inbox.test.js +0 -113
- package/clis/linkedin/salesnav-message.test.js +0 -172
- package/clis/linkedin/salesnav-search.test.js +0 -76
- package/clis/linkedin/salesnav-thread.test.js +0 -79
- package/clis/linkedin/search.test.js +0 -222
- package/clis/linkedin/sent-invitations.test.js +0 -62
- package/clis/linkedin/services-read.test.js +0 -105
- package/clis/linkedin/thread-snapshot.test.js +0 -89
- package/clis/linkedin/timeline.test.js +0 -81
- package/clis/linkedin-learning/course.test.js +0 -114
- package/clis/linkedin-learning/search.test.js +0 -144
- package/clis/linkedin-learning/trending.test.js +0 -123
- package/clis/linux-do/feed.test.js +0 -153
- package/clis/linux-do/topic-content.test.js +0 -59
- package/clis/lobsters/lobsters.test.js +0 -169
- package/clis/notebooklm/add-source.test.js +0 -97
- package/clis/notebooklm/compat.test.js +0 -16
- package/clis/notebooklm/create.test.js +0 -58
- package/clis/notebooklm/generate-audio.test.js +0 -63
- package/clis/notebooklm/generate-slides.test.js +0 -75
- package/clis/notebooklm/history.test.js +0 -58
- package/clis/notebooklm/note-list.test.js +0 -56
- package/clis/notebooklm/notes-get.test.js +0 -72
- package/clis/notebooklm/open.test.js +0 -63
- package/clis/notebooklm/rpc.test.js +0 -131
- package/clis/notebooklm/source-fulltext.test.js +0 -106
- package/clis/notebooklm/source-get.test.js +0 -84
- package/clis/notebooklm/source-guide.test.js +0 -104
- package/clis/notebooklm/summary.test.js +0 -78
- package/clis/notebooklm/utils.test.js +0 -449
- package/clis/notebooklm/write-note.test.js +0 -70
- package/clis/nuget/nuget.test.js +0 -111
- package/clis/oeis/oeis.test.js +0 -88
- package/clis/ones/task-helpers.test.js +0 -12
- package/clis/ones/worklog.test.js +0 -20
- package/clis/openfda/openfda.test.js +0 -114
- package/clis/openreview/openreview.test.js +0 -427
- package/clis/osv/osv.test.js +0 -97
- package/clis/paperreview/commands.test.js +0 -243
- package/clis/paperreview/utils.test.js +0 -49
- package/clis/pixiv/download.test.js +0 -87
- package/clis/pixiv/illusts.test.js +0 -99
- package/clis/pixiv/search.test.js +0 -83
- package/clis/powerchina/search.test.js +0 -93
- package/clis/producthunt/utils.test.js +0 -64
- package/clis/pubmed/pubmed.test.js +0 -276
- package/clis/quark/utils.test.js +0 -58
- package/clis/qwen/utils.test.js +0 -45
- package/clis/reddit/extract-media.test.js +0 -149
- package/clis/reddit/frontpage.test.js +0 -34
- package/clis/reddit/home.test.js +0 -170
- package/clis/reddit/hot.test.js +0 -32
- package/clis/reddit/popular.test.js +0 -26
- package/clis/reddit/read.test.js +0 -335
- package/clis/reddit/reply.test.js +0 -89
- package/clis/reddit/search.test.js +0 -26
- package/clis/reddit/subreddit-info.test.js +0 -163
- package/clis/reddit/subreddit.test.js +0 -31
- package/clis/reddit/subscribed.test.js +0 -168
- package/clis/reddit/whoami.test.js +0 -105
- package/clis/rednote/navigation.test.js +0 -26
- package/clis/rednote/rednote.test.js +0 -222
- package/clis/rest-countries/rest-countries.test.js +0 -83
- package/clis/reuters/reuters.test.js +0 -299
- package/clis/rfc/rfc.test.js +0 -74
- package/clis/sinafinance/stock.test.js +0 -59
- package/clis/spotify/utils.test.js +0 -67
- package/clis/stackoverflow/stackoverflow.test.js +0 -404
- package/clis/steam/steam.test.js +0 -46
- package/clis/substack/utils.test.js +0 -44
- package/clis/suno/commands.test.js +0 -188
- package/clis/suno/download.test.js +0 -151
- package/clis/suno/generate.test.js +0 -252
- package/clis/suno/utils.test.js +0 -329
- package/clis/taobao/commands.test.js +0 -41
- package/clis/tdx/hot-rank.test.js +0 -59
- package/clis/ths/hot-rank.test.js +0 -64
- package/clis/tieba/commands.test.js +0 -79
- package/clis/tieba/utils.test.js +0 -290
- package/clis/tiktok/creator-videos.test.js +0 -113
- package/clis/tiktok/refactor.test.js +0 -389
- package/clis/tiktok/write-refactor.test.js +0 -370
- package/clis/toutiao/toutiao.test.js +0 -378
- package/clis/tvmaze/tvmaze.test.js +0 -93
- package/clis/twitter/bookmark-folder.test.js +0 -395
- package/clis/twitter/bookmark-folders.test.js +0 -152
- package/clis/twitter/bookmark.test.js +0 -74
- package/clis/twitter/bookmarks.test.js +0 -205
- package/clis/twitter/delete.test.js +0 -85
- package/clis/twitter/device-follow.test.js +0 -287
- package/clis/twitter/download.test.js +0 -457
- package/clis/twitter/followers.test.js +0 -62
- package/clis/twitter/following.test.js +0 -338
- package/clis/twitter/hide-reply.test.js +0 -76
- package/clis/twitter/like.test.js +0 -73
- package/clis/twitter/likes.test.js +0 -220
- package/clis/twitter/list-add.test.js +0 -133
- package/clis/twitter/list-create.test.js +0 -169
- package/clis/twitter/list-remove.test.js +0 -110
- package/clis/twitter/list-tweets.test.js +0 -196
- package/clis/twitter/lists.test.js +0 -253
- package/clis/twitter/post.test.js +0 -258
- package/clis/twitter/profile.test.js +0 -39
- package/clis/twitter/quote.test.js +0 -194
- package/clis/twitter/reply.test.js +0 -237
- package/clis/twitter/retweet.test.js +0 -73
- package/clis/twitter/search.test.js +0 -349
- package/clis/twitter/shared.test.js +0 -794
- package/clis/twitter/thread.test.js +0 -58
- package/clis/twitter/timeline.test.js +0 -104
- package/clis/twitter/trending.test.js +0 -15
- package/clis/twitter/tweets.test.js +0 -362
- package/clis/twitter/unbookmark.test.js +0 -73
- package/clis/twitter/unlike.test.js +0 -75
- package/clis/twitter/unretweet.test.js +0 -73
- package/clis/twitter/utils.test.js +0 -169
- package/clis/uisdc/news.test.js +0 -66
- package/clis/uiverse/_shared.test.js +0 -62
- package/clis/uiverse/navigation.test.js +0 -12
- package/clis/upwork/upwork.test.js +0 -566
- package/clis/wanfang/search.test.js +0 -23
- package/clis/web/read.test.js +0 -392
- package/clis/weibo/delete.test.js +0 -94
- package/clis/weibo/envelope.test.js +0 -85
- package/clis/weibo/favorites.test.js +0 -114
- package/clis/weibo/publish.test.js +0 -192
- package/clis/weibo/user-posts.test.js +0 -92
- package/clis/weibo/utils.test.js +0 -36
- package/clis/weixin/drafts.test.js +0 -69
- package/clis/weixin/search.test.js +0 -227
- package/clis/weread/ai-outline.test.js +0 -83
- package/clis/weread/book-search.test.js +0 -242
- package/clis/weread/commands.test.js +0 -398
- package/clis/weread/private-api-regression.test.js +0 -369
- package/clis/weread/search-regression.test.js +0 -494
- package/clis/weread/utils.test.js +0 -128
- package/clis/weread-official/commands.test.js +0 -385
- package/clis/weread-official/utils.test.js +0 -242
- package/clis/wikidata/wikidata.test.js +0 -83
- package/clis/wikipedia/trending.test.js +0 -57
- package/clis/wttr/wttr.test.js +0 -84
- package/clis/xianyu/chat.test.js +0 -84
- package/clis/xianyu/im.test.js +0 -253
- package/clis/xianyu/item.test.js +0 -56
- package/clis/xianyu/publish.test.js +0 -220
- package/clis/xianyu/search.test.js +0 -17
- package/clis/xiaoe/xiaoe.test.js +0 -486
- package/clis/xiaohongshu/comments.test.js +0 -258
- package/clis/xiaohongshu/creator-note-detail.test.js +0 -451
- package/clis/xiaohongshu/creator-notes-summary.test.js +0 -94
- package/clis/xiaohongshu/creator-notes.test.js +0 -281
- package/clis/xiaohongshu/creator-stats.test.js +0 -24
- package/clis/xiaohongshu/delete-note.test.js +0 -172
- package/clis/xiaohongshu/download.test.js +0 -316
- package/clis/xiaohongshu/navigation.test.js +0 -34
- package/clis/xiaohongshu/note.test.js +0 -249
- package/clis/xiaohongshu/publish.test.js +0 -608
- package/clis/xiaohongshu/search.test.js +0 -325
- package/clis/xiaohongshu/user-helpers.test.js +0 -160
- package/clis/xiaoyuzhou/auth.test.js +0 -124
- package/clis/xiaoyuzhou/download.test.js +0 -135
- package/clis/xiaoyuzhou/podcast-episodes.test.js +0 -78
- package/clis/xiaoyuzhou/transcript.test.js +0 -195
- package/clis/xiaoyuzhou/utils.test.js +0 -39
- package/clis/xueqiu/comments.test.js +0 -696
- package/clis/xueqiu/danjuan-utils.test.js +0 -41
- package/clis/xueqiu/utils.test.js +0 -26
- package/clis/yahoo/search.test.js +0 -94
- package/clis/youdao/note.test.js +0 -99
- package/clis/youtube/channel.test.js +0 -59
- package/clis/youtube/feed.test.js +0 -131
- package/clis/youtube/transcript-group.test.js +0 -99
- package/clis/youtube/transcript.test.js +0 -296
- package/clis/youtube/utils.test.js +0 -84
- package/clis/yuanbao/ask.test.js +0 -124
- package/clis/yuanbao/new.test.js +0 -30
- package/clis/yuanbao/shared.test.js +0 -80
- package/clis/zhihu/answer-comments.test.js +0 -287
- package/clis/zhihu/answer-detail.test.js +0 -338
- package/clis/zhihu/answer.test.js +0 -54
- package/clis/zhihu/collection.test.js +0 -337
- package/clis/zhihu/collections.test.js +0 -182
- package/clis/zhihu/comment.test.js +0 -50
- package/clis/zhihu/download.test.js +0 -12
- package/clis/zhihu/favorite.test.js +0 -59
- package/clis/zhihu/follow.test.js +0 -42
- package/clis/zhihu/like.test.js +0 -41
- package/clis/zhihu/question.test.js +0 -251
- package/clis/zhihu/recommend.test.js +0 -143
- package/clis/zhihu/search.test.js +0 -198
- package/clis/zhihu/target.test.js +0 -77
- package/clis/zhihu/text.test.js +0 -24
- package/clis/zhihu/write-shared.test.js +0 -176
- package/clis/zlibrary/commands.test.js +0 -65
- package/clis/zsxq/search.test.js +0 -24
- package/clis/zsxq/topic.test.js +0 -30
- package/clis/zsxq/topics.test.js +0 -24
- package/clis/zsxq/utils.test.js +0 -31
- package/dist/src/adapter-shadow.test.js +0 -49
- package/dist/src/adapter-source.test.js +0 -29
- package/dist/src/browser/analyze.test.js +0 -166
- package/dist/src/browser/article-extract.e2e.test.js +0 -105
- package/dist/src/browser/article-extract.test.js +0 -94
- package/dist/src/browser/ax-snapshot.test.js +0 -91
- package/dist/src/browser/base-page.test.js +0 -758
- package/dist/src/browser/cdp-click-fixture.test.js +0 -87
- package/dist/src/browser/cdp.test.js +0 -79
- package/dist/src/browser/compound.test.js +0 -175
- package/dist/src/browser/daemon-client.test.js +0 -199
- package/dist/src/browser/dom-helpers.test.js +0 -106
- package/dist/src/browser/dom-snapshot.test.js +0 -313
- package/dist/src/browser/errors.test.js +0 -60
- package/dist/src/browser/extract.test.js +0 -129
- package/dist/src/browser/find.test.js +0 -180
- package/dist/src/browser/html-tree.test.js +0 -181
- package/dist/src/browser/network-cache.test.js +0 -58
- package/dist/src/browser/network-key.test.js +0 -49
- package/dist/src/browser/page.test.js +0 -378
- package/dist/src/browser/shape-filter.test.js +0 -101
- package/dist/src/browser/shape.test.js +0 -82
- package/dist/src/browser/stealth.test.js +0 -134
- package/dist/src/browser/target-errors.test.js +0 -94
- package/dist/src/browser/target-resolver.test.js +0 -118
- package/dist/src/browser/utils.test.js +0 -29
- package/dist/src/browser/verify-fixture.test.js +0 -219
- package/dist/src/browser.test.js +0 -232
- package/dist/src/build-manifest.test.js +0 -341
- package/dist/src/capabilityRouting.test.js +0 -63
- package/dist/src/cli-argv-preprocess.test.js +0 -209
- package/dist/src/cli.test.js +0 -2803
- package/dist/src/commanderAdapter.test.js +0 -352
- package/dist/src/commands/daemon.test.js +0 -219
- package/dist/src/completion.test.js +0 -24
- package/dist/src/convention-audit.test.js +0 -247
- package/dist/src/daemon.test.js +0 -60
- package/dist/src/doctor.test.js +0 -263
- package/dist/src/download/article-download.test.js +0 -235
- package/dist/src/download/index.test.js +0 -140
- package/dist/src/download/media-download.test.js +0 -112
- package/dist/src/download/progress.test.js +0 -36
- package/dist/src/electron-apps.test.js +0 -49
- package/dist/src/engine.test.js +0 -312
- package/dist/src/errors.test.js +0 -109
- package/dist/src/execution.test.js +0 -623
- package/dist/src/extension-manifest-regression.test.js +0 -12
- package/dist/src/external.test.js +0 -146
- package/dist/src/help.test.js +0 -58
- package/dist/src/hooks.test.js +0 -92
- package/dist/src/interceptor.test.js +0 -81
- package/dist/src/launcher.test.js +0 -138
- package/dist/src/node-network.test.js +0 -55
- package/dist/src/observation/artifact.test.js +0 -121
- package/dist/src/observation/manager.test.js +0 -13
- package/dist/src/observation/redaction.test.js +0 -32
- package/dist/src/observation/retention.test.js +0 -118
- package/dist/src/observation/ring-buffer.test.js +0 -22
- package/dist/src/output.test.js +0 -53
- package/dist/src/package-exports.test.js +0 -112
- package/dist/src/pipeline/executor.test.js +0 -182
- package/dist/src/pipeline/steps/download.test.js +0 -102
- package/dist/src/pipeline/steps/fetch.test.js +0 -117
- package/dist/src/pipeline/template.test.js +0 -175
- package/dist/src/pipeline/transform.test.js +0 -133
- package/dist/src/plugin-manifest.test.js +0 -179
- package/dist/src/plugin-scaffold.test.js +0 -83
- package/dist/src/plugin.test.js +0 -1324
- package/dist/src/registry.test.js +0 -209
- package/dist/src/runtime-detect.test.js +0 -39
- package/dist/src/serialization.test.js +0 -78
- package/dist/src/snapshotFormatter.test.js +0 -521
- package/dist/src/tui.test.js +0 -19
- package/dist/src/update-check.test.js +0 -116
- package/dist/src/utils.test.js +0 -155
- package/dist/src/validate.test.js +0 -90
- package/dist/src/weixin-download.test.js +0 -45
package/dist/src/discovery.js
CHANGED
|
@@ -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
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
export const
|
|
22
|
-
/**
|
|
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
|
|
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
|
-
|
|
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 {};
|
package/dist/src/execution.d.ts
CHANGED
|
@@ -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;
|
package/dist/src/execution.js
CHANGED
|
@@ -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
|
|
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
|
-
/**
|
|
30
|
-
const
|
|
31
|
-
|
|
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
|
|
85
|
-
//
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
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
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
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
|
-
|
|
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:
|
|
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
|
|
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(
|
|
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
|
|
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(
|
|
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
|
|
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
|
|
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 =
|
|
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;
|