Commit Graph

70 Commits

Author SHA1 Message Date
AstroHan caebede7c2 fix: repair baseline main ci checks (#901) 2026-04-09 12:19:44 +08:00
ziiiiiwang 2883620ba2 Feat : add Gitee adapters and docs (#845)
* feat: add gitee adapters and docs

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: compact gitee trending table output

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* docs: add gitee adapter documentation

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix(gitee): avoid faking user index values

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: jackwener <jakevingoo@gmail.com>
2026-04-09 01:29:48 +08:00
X 61b247f90c feat(quark): add Quark Drive adapter (#858)
* feat(quark): add Quark Drive adapter (ls, mkdir, mv, rename, rm, save, share-tree)

Browser-based adapter for Quark Cloud Drive (pan.quark.cn) using cookie
strategy. Supports file browsing, folder management, and saving shared
files with task polling for async operations.

* fix(quark): address review feedback on adapter correctness and docs

- ls: fix depth off-by-one (default 0 now lists target folder only)
- save/mv: report success only after pollTask confirms completion; throw on timeout
- save/mv: reject combining --to and --to-fid instead of silently preferring --to-fid
- utils: check content-type before calling r.json() to handle non-JSON responses gracefully
- tests: add quark graceful auth-failure E2E cases for all 7 commands
- docs: add Browser Bridge extension to prerequisites; fix mkdir --parent example; expand command table with positional args; add Notes section explaining stoken flow

* fix(quark): map auth failures and cover utils

* fix(quark): reuse auth mapping for share-tree

---------

Co-authored-by: xzy <xzy@mbp-m5.local>
Co-authored-by: jackwener <jakevingoo@gmail.com>
2026-04-08 00:28:59 +08:00
AstroHan ce559da7fc feat(zhihu): add interaction commands (#868)
* feat(zhihu): add interaction commands

* fix(zhihu): tighten interaction target anchoring

* fix(zhihu): scope comment authorship proof

---------

Co-authored-by: jackwener <jakevingoo@gmail.com>
2026-04-07 23:17:51 +08:00
GanFanNewOrder 9c5571eba3 feat(jianyu): add search adapter for bid notices (#849)
* feat(jianyu): add search adapter for bid notices

* docs(jianyu): add adapter usage guide

* docs(jianyu): neutralize examples and add adapter guide

---------

Co-authored-by: 泽加武 <zejiawu@zejiawudeMac-mini.local>
2026-04-07 19:20:00 +08:00
tiaot33 5553300597 feat(linux-do): split topic content into a dedicated command (#821)
* feat(linux-do): split topic content into a dedicated command

Move the old main-post path out of linux-do topic so topic stays a summarized first-page reader while topic-content becomes the Markdown-focused entrypoint for full post bodies.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* feat(linux-do): update topic content handling to include YAML front matter

* fix(linux-do): update default output format to plain for topic-content rendering

* fix(linux-do): replace js-yaml with inline YAML serialization for topic-content

Adapters must only import node builtins, relative modules, or opencli
public APIs. Hand-roll the simple front matter serialization to remove
the third-party js-yaml dependency.

* fix(linux-do): refine YAML quoting to only escape colons followed by space

Colons in URLs (e.g. https://) are valid unquoted YAML values. Only
quote when a colon is followed by a space or appears at end of line.

---------

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-04-06 02:59:56 +08:00
BruceLoveDecimal d2ae28786c feat:add 1688 assets downloadable (#820)
* feat:add 1688 assets downloadable

* fix: remove duplicate visitedRoots declaration and fix normalizeMediaUrl re-export

- Remove unused outer `visitedRoots` variable in scriptToReadAssets()
- Move normalizeMediaUrl test to import from shared.ts where it's defined
- Remove unused normalizeMediaUrl import from assets.ts

---------

Co-authored-by: 刘启灏 <liuqihao@liuqihaodeMacBook-Pro.local>
Co-authored-by: jackwener <jakevingoo@gmail.com>
2026-04-06 01:59:39 +08:00
jakevin ab58aa4098 fix(docs): update outdated paths and command lists across all docs (#787)
- Replace 140 instances of `src/clis/` → `clis/` across 12 doc files
  (path changed after repo restructure)
- Remove non-command `rpc` and `rankings` from notebooklm/amazon
  command lists in README, README.zh-CN, SKILL.md, and adapters index
  (these are internal utility modules, not user-facing commands)
- Add `deep-research` and `deep-research-result` to gemini adapter doc
- Add `movers-shakers` and `new-releases` to amazon adapter doc
- Update notebooklm doc examples to use canonical commands instead of
  deprecated aliases (`metadata` → `get`, `notes-list` → `note-list`)
- Bump SKILL.md version to 1.6.3
2026-04-05 03:53:52 +08:00
kevin.zhang 8bd36aaa37 fix(hupu): add mentions command (#757)
* feat(hupu): add hupu cli adapter

* fix(hupu): prevent detail from returning the wrong thread

* refactor: deduplicate shared utilities in hupu adapter

- Merge postHupuJson and postHupuReplyJson into single function with mode parameter
- Move stripHtml and decodeHtmlEntities to utils.ts, remove duplicate definitions

* fix(hupu): add mentions command

* fix: move mentions.ts to clis/hupu/, remove src/clis/hupu duplicates

Post PR #782 restructure: adapter files live at root clis/, not src/clis/.

---------

Co-authored-by: jackwener <jakevingoo@gmail.com>
2026-04-05 03:26:40 +08:00
Xule Lin d2051cdab7 feat(lesswrong): add LessWrong adapter (#773)
* feat(lesswrong): add LessWrong adapter

15 commands for the LessWrong rationality and AI alignment community:
- Post listings: curated, frontpage, new, top, top-week/month/year
- Content: read (full post), comments, shortform (quick takes)
- Discovery: tag, tags, sequences
- Users: user (profile), user-posts

All commands use the public GraphQL API (no browser required).
Time-filtered views use the `after` date parameter.
Tag lookup resolves slugs to IDs via the `tagBySlug` view.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: move lesswrong adapter to clis/ (post PR #782 restructure)

New adapter files were created at src/clis/lesswrong/ but PR #782 moved
all adapters to root clis/. Move to correct location.

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: jackwener <jakevingoo@gmail.com>
2026-04-05 03:21:48 +08:00
kevin.zhang e0a66af0f0 feat(hupu): add Hupu adapter (#751)
* feat(hupu): add hupu cli adapter

* fix(hupu): prevent detail from returning the wrong thread

* refactor: deduplicate shared utilities in hupu adapter

- Merge postHupuJson and postHupuReplyJson into single function with mode parameter
- Move stripHtml and decodeHtmlEntities to utils.ts, remove duplicate definitions

---------

Co-authored-by: jackwener <jakevingoo@gmail.com>
2026-04-04 16:03:14 +08:00
yulin7645 6364934423 feat(xiaoe): add 小鹅通 (Xiaoe-tech) student platform adapter (#617)
* feat(xiaoe): add 小鹅通 (Xiaoe-tech) student platform adapter

Add 5 YAML adapters for 小鹅通 (xiaoe-tech.com), the leading Chinese
online education platform:

- courses: list purchased courses with URLs and shop names
- detail: course info (name, price, user count, shop)
- catalog: full course outline supporting normal courses (type 50),
  columns (type 6), and big columns (type 8)
- play-url: get M3U8 play URL via direct API for video courses,
  and Vue component tree search + Performance API polling for
  live replay courses
- content: extract rich-text page content as plain text

Technical notes:
- Strategy: cookie (reuses Chrome login session)
- Framework: Vue 2 + Vuex Store (SPA)
- Video courses use a two-step API chain:
  detail_info.get → play_sign → getPlayUrl → M3U8
- Live replays use Performance API + Vue data tree polling
- Catalog expands chapters via Vue component method getSecitonList()
- Supports multiple stores (cross-domain cookie sharing via
  study.xiaoe-tech.com)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* review: stop truncating xiaoe content

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: jackwener <jakevingoo@gmail.com>
2026-04-04 15:54:14 +08:00
yichuanzhao99-ctrl 8eefa3b1c9 增加新浪财经热搜股票榜 (#736)
* 增加新浪财经热搜股票榜

* fix: address review issues in stock-rank adapter

- Fix string interpolation injection: use JSON.stringify for market param
- Add choices validation for market arg (cn/hk/us/wh/ft)
- Normalize column names to lowercase (rank/name/symbol/market/price/change/url)
- Add navigateBefore: false to avoid redundant navigation
- Add null safety on tabEl with optional chaining
- Remove unused waitForElement helper and unnecessary await on querySelectorAll
- Remove unrelated ?from=opencli tracking change from rolling-news.ts
- Remove ?from=opencli tracking from stock-rank URLs

---------

Co-authored-by: jackwener <jakevingoo@gmail.com>
2026-04-04 15:16:05 +08:00
GanFanNewOrder 81de69be3a feat(1688): add browser adapter and docs (#650)
* feat(1688): add browser adapter and docs

* fix(1688): retry alternate store seed offers

* feat(1688): harden adapter contracts and search pagination

---------

Co-authored-by: 泽加武 <zejiawu@zejiawudeMac-mini.local>
2026-04-04 14:45:32 +08:00
tiaot33 f377ec000c feat(元宝): add browser adapter and docs (#693)
* feat(yuanbao): add browser adapter and docs

* refactor(yuanbao): normalize adapter failures to CliError

* refactor: extract shared yuanbao helpers to reduce duplication

Move isOnYuanbao, ensureYuanbaoPage, hasLoginGate, authRequired,
and IS_VISIBLE_JS to shared.ts. This eliminates identical copies
across ask.ts and new.ts, reducing correctness risk when modifying
shared logic.

---------

Co-authored-by: jackwener <jakevingoo@gmail.com>
2026-04-03 17:03:48 +08:00
BruceLoveDecimal 0ce46b15bb feat:add xianyu (#696)
* feat:add xianyu

feat:add xianyu

feat:add xianyu

* chore:add xianyu docs

* fix:update xianyu after review

---------

Co-authored-by: 刘启灏 <liuqihao@liuqihaodeMacBook-Pro.local>
2026-04-03 12:30:28 +08:00
jakevin 706e01dbca docs: fix outdated adapter counts, missing commands and adapters (#704)
* docs: fix outdated adapter counts, missing commands, and absent adapters

- Update version 1.6.0 → 1.6.1 in skills/opencli-usage/SKILL.md
- Update site count 70+ → 73+ across README.md, README.zh-CN.md,
  docs/comparison.md
- Remove non-existent adapters (kimi, deepseek, qwen) from SKILL.md
- Add missing commands for xiaohongshu (+note, comments, download,
  publish), weibo (+search, feed, user, me, post, comments),
  jike (+post, topic, user), linux-do (+hot, latest, category),
  doubao (+detail, history, meeting-summary, meeting-transcript),
  weread (+notebooks), chatgpt (+model), wikipedia (+random, trending),
  stackoverflow (+unanswered), producthunt (fix command list)
- Add entirely missing adapters: band, zsxq, bluesky, douyin, 36kr,
  ones, tieba, gemini, notebooklm, imdb, spotify, paperreview
- Update docs/adapters/index.md with same fixes
- Add opencli-operate to Related Skills section

* docs: second-pass audit fixes — deeper inconsistencies

Skills sub-files (browser.md, public-api.md):
- Remove phantom kimi/deepseek/qwen adapters (no src/clis/ dirs)
- Replace with real gemini and notebooklm sections
- Add missing weibo commands (search, feed, user, me, post, comments)
- Add missing xiaohongshu commands (note, comments, download, publish)
- Add missing doubao commands (detail, history, meeting-summary, meeting-transcript)
- Add 7 entirely missing adapter sections: bluesky, douyin, band, zsxq,
  tieba, 36kr, ones
- Fix producthunt: remove non-existent week/month/search, add hot/browse/posts
- Add wikipedia random and trending

SKILL.md command table:
- Add twitter `likes`, xueqiu `comments`, douban `movie-hot`/`book-hot`
- Add entirely missing `amazon` adapter
- Add linux-do `latest`
- Remove producthunt non-existent `search`

Individual adapter docs:
- docs/adapters/browser/weibo.md: add 5 missing commands
- docs/adapters/browser/doubao.md: add 4 missing commands
- docs/adapters/browser/wikipedia.md: add random and trending
- docs/adapters/browser/36kr.md: fix contradictory prerequisites
- docs/adapters/index.md: add twitter `likes`
- docs/developer/contributing.md: add missing `positional: true`
- package.json: fix description to include "Electron App"
2026-04-03 01:05:47 +08:00
jakevin fe82b3882f docs: update outdated adapter counts, operate commands, and skill references (#701)
- Update adapter count from 50+/60+/66+ to 70+ across all docs (actual: 74 sites)
- Add missing operate commands (eval, network, init, verify) to README
- Add opencli-operate skill to Install AI Skills section in both READMEs
- Replace outdated "Playwright MCP Bridge" with "Browser Bridge" in doubao docs
2026-04-02 23:32:36 +08:00
fii6 abd46bccba feat(gemini): add Gemini web adapter with minimal output (#619)
* feat(gemini): add web adapter with minimal output

* fix(gemini): use defaultFormat for minimal output

* fix(gemini): preserve full transcript responses

* docs(gemini): add browser adapter guide

* review: wire gemini into adapter indexes

---------

Co-authored-by: fii6 <246637913+fii6@users.noreply.github.com>
Co-authored-by: jackwener <jakevingoo@gmail.com>
2026-04-02 13:39:35 +08:00
GanFanNewOrder d721eb6c6c feat(amazon): add browser adapter and docs (#659)
* feat(amazon): add browser adapter and docs

* review: wire amazon into discovery docs

---------

Co-authored-by: 泽加武 <zejiawu@zejiawudeMac-mini.local>
Co-authored-by: jackwener <jakevingoo@gmail.com>
2026-04-02 13:32:23 +08:00
jakevin 773178345d refactor: remove bind-current, restore owned-only browser automation model (#664)
* fix(notebooklm): remove bind-current workflow

* fix: relax notebook ID check in open.ts and clean up idle timeout test

- open.ts: only throw when page kind is not 'notebook'; log a warning
  instead of throwing when the notebook ID doesn't match exactly
- background.test.ts: remove unused tabs[1] setup in idle timeout test
  that was leftover from borrowed-session era

* build: rebuild extension dist after bind-current removal
2026-04-01 23:23:48 +08:00
muqiao215 0204dbb018 feat(notebooklm): add read commands and compatibility layer (#622)
* feat(notebooklm): add read commands and compatibility layer

* review: trim notebooklm artifacts and sync docs

---------

Co-authored-by: qiaoqiao147 <camtup044@gmail.com>
Co-authored-by: jackwener <jakevingoo@gmail.com>
2026-03-31 13:19:47 +08:00
ahahaha d0803857f1 feat(xiaohongshu): add note command and nested reply support for comments (#599)
* feat(xiaohongshu): add note command and nested reply support for comments

Add `xiaohongshu note` command to read full note content (title, author,
description, engagement metrics, tags) from public note pages.

Enhance `xiaohongshu comments` with `--with-replies` flag to extract
nested replies (楼中楼), including reply_to attribution and per-reply
like counts. Limit logic counts only top-level comments so replies
are included for free.

Extract shared `parseNoteId` into side-effect-free `note-helpers.ts`
to avoid cross-module command registration leakage.

Normalize non-numeric engagement placeholders ("赞"/"收藏"/"评论")
to "0" for zero-count notes.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* docs(xiaohongshu): add note and comments --with-replies to adapter docs

Update xiaohongshu adapter documentation and README command table
to reflect the new note command and enhanced comments with nested
reply support.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* docs(xiaohongshu): fix download example to show both note-id and url

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(xiaohongshu): expand nested reply threads before scraping

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: jackwener <jakevingoo@gmail.com>
2026-03-30 23:29:30 +08:00
AstroHan cf79ec5c23 feat(xueqiu): add comments command (#587)
* feat: add xueqiu comments command

* docs(xueqiu): add comments command docs

---------

Co-authored-by: jackwener <jakevingoo@gmail.com>
2026-03-30 01:22:44 +08:00
Zhangchen 8c00ad9f02 feat(browser): add ONES adapter support for tasks and worklog commands (#386)
* feat(browser): add ONES adapter support for tasks and worklog commands
Add ONES auth/session commands, task listing/details utilities, and worklog operations, with related docs and helper utilities.

* fix(ones): harden worklog and task-list adapter behavior

---------

Co-authored-by: jackwener <jakevingoo@gmail.com>
2026-03-30 01:06:38 +08:00
AstroHan a32b65be4a feat: add Tieba browser adapters in TypeScript (#581)
* feat(tieba): add browser adapters for hot posts search and read

* fix(tieba): stabilize search and e2e coverage

---------

Co-authored-by: jackwener <jakevingoo@gmail.com>
2026-03-29 22:39:26 +08:00
jakevin f8e9b08223 fix(zsxq): require active group context (#579)
* fix(zsxq): require active group context

* docs(zsxq): add adapter guide
2026-03-29 17:29:36 +08:00
bhutano 1ae1c82c4a feat(spotify): add Spotify playback adapter (#560)
* feat(spotify): add Spotify playback adapter

Adds a new adapter for controlling Spotify via the official Web API.
Uses Strategy.PUBLIC with OAuth2 — no browser session required.

Commands: auth, status, play, pause, next, prev, volume, search, queue, shuffle, repeat.
Credentials are loaded from ~/.opencli/spotify.env or environment variables.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(spotify): rename index.ts → spotify.ts and fix CliError calls

- Renamed src/clis/spotify/index.ts to spotify.ts so the build-manifest
  picks it up (index.js is intentionally excluded from manifest scanning)
- Fixed 4 CliError calls: constructor now requires (code, message, hint?)
  so each throw now passes an appropriate error code as first argument

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(spotify): fix token refresh corruption, env parse, null guards, validation

- refreshAccessToken: check res.ok before parsing; construct Tokens object
  directly instead of mutating loadTokens() result to avoid writing
  undefined/NaN on Spotify error responses; preserve existing refresh_token
  when Spotify omits it from the response
- loadEnv: split on first '=' only so values containing '=' are preserved
- SCOPES: remove write/library/top scopes not used by any command
- status: guard against data.item being null (active device but no track)
- volume: validate 0-100 range before API call
- auth: check tokenRes.ok on initial token exchange; add server.on('error')
  handler for EADDRINUSE; add 5-minute timeout with clearTimeout on close

* feat(postinstall): auto-create ~/.opencli/spotify.env template on install

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(spotify): guard null progress, podcast items, missing tracks data, corrupted tokens, invalid search limit

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(spotify): improve missing credentials error with step-by-step guidance

* fix(spotify): harden setup and add docs coverage

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: jackwener <jakevingoo@gmail.com>
2026-03-29 17:28:37 +08:00
康厚超 440c001a20 feat(band): add Band.us adapter — bands, posts, mentions, post commands (#532)
* feat(band): add bands, posts, and mentions commands for band.us

- bands: lists all Bands via get_band_list_with_filter intercept
- posts: lists posts from a Band via get_posts_and_announcements intercept
- mentions: shows @mention notifications via get_news intercept

All use Strategy.INTERCEPT since band.us API requires an HMAC md header
generated by its own JS. SPA navigation to /band/{no}/post triggers the
band list and posts APIs; bell + @メンション tab click triggers mentions.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* refactor(band): clean up all three band adapters

- Fix doc comments: Band uses XHR not fetch; clarify INTERCEPT rationale
- bands: replace for-loop with flatMap; explain why band page nav is needed
- posts: remove item.post ?? item fallback (API always wraps in post); rename
  finalRequests → requests for consistency; extract stripBandTags helper
- mentions: remove redundant ?? defaults (args have defaults defined); fix
  unreadOnly bug (was not applied to post/comment modes); consolidate Band tag
  stripping to single regex; cast kwargs types directly instead of converting;
  add comments explaining last-response strategy and 'referred' filter flag

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(band/posts): handle mixed post/announcement items from API

get_posts_and_announcements returns both regular posts and announcements
that have different shapes — some lack post_no and wrap differently.
Restore item.post ?? item fallback and filter out items with no resolvable
identifier to prevent undefined in URLs and empty rows in output.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat(band): add post command — full post export with comments and photo download

Exports the complete content of a single Band post:
- Post body (with Band markup tags stripped)
- All comments in chronological order
- Photo URLs shown inline, or downloaded with --output <dir>

Uses Strategy.INTERCEPT with a broad 'band.us' pattern to capture both the
batch request (embedding get_post) and get_comments in one SPA navigation.
Responses are identified client-side by shape: batch_result array vs items
array with comment_id fields.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* refactor(band): replace XHR interception with direct DOM extraction

- bands, posts, post: navigate directly to target URL instead of home→SPA detour
- All three switch from Strategy.INTERCEPT to Strategy.COOKIE with navigateBefore: false
  (bands uses framework pre-nav to home; posts/post disable it and goto target directly)
- DOM extraction polls for specific content elements rather than fixed waits
- post: confirm selectors via browser inspection (a.text, time.time, .sCommentList,
  .sReplyList for nested replies); add --comments flag to skip comment fetch
- posts: extract from rendered post list DOM; correct comment item selector (div.cComment)
- Fix: post empty-result guard changed from && to handle null data safely
- Fix: photo download now checks HTTP status code before piping to avoid writing
  redirect HTML into image files
- Fix: mentions unread client-side filter skipped for 'mentioned' mode since
  server already filtered via 未確認のみ button click

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(band): address code review feedback

- post: replace manual http/https download with shared downloadMedia utility
  (handles redirects, timeouts, stream errors correctly)
- post: fix photo URL resolution to use location.href as base, handling
  protocol-relative and relative URLs without throwing
- post: switch to node:-prefixed imports per repo convention
- post/posts: remove redundant ArgumentError guards — framework already
  validates required args before func() is called
- mentions: INTERCEPT strategy is intentional (Band HMAC prevents DOM-only
  approach for notifications; update PR description to clarify)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(band): address second round of code review feedback

- bands: tighten href selector to /band/{id}(?:/post)?$ so feed/post-detail
  links are excluded; only sidebar navigation links match
- mentions: replace fixed page.wait(2) sleeps with polling on
  getInterceptedRequests() — waits up to 8 s per action, exits as soon
  as the expected number of captures arrives (avoids flakiness on slow XHR)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(band): fix selector bugs found during testing

- bands: use a.bandCover._link + p.uriText + span.member em selectors
  (previous a[href*="/band/"] + .bandName combo leaked "メンバー" text)
- posts: use article.cContentsCard._postMainWrap + span.count selectors
  (previous li._postListItem selector matched nothing; DOM changed)
- mentions: fix page.wait(500) → page.wait(0.5) (was waiting 500s not ms);
  use timestamp-suffixed URL to force fresh page load each run so the
  notification panel is closed; fix get_news vs get_news_count capture
  ambiguity with result_data.news check; replace cumulative waitForCaptures
  with waitForOneCapture (getInterceptedRequests clears array on each call)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(band/mentions): use CSS class selector for bell button instead of locale-dependent text match

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(band): address third round of code review feedback

- post: pass browser cookies to downloadMedia so Band's login-protected
  photo URLs don't fail with 401/403
- post: include photos.length in empty-result guard so photo-only posts
  are not falsely reported as not found
- mentions: accumulate captures across poll iterations so get_news_count
  responses don't cause early exit before the real get_news arrives
- mentions: update docstring to match actual implementation (client-side
  filtering, no tab-click)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(band): address fourth round of code review feedback

- mentions: fail fast with a clear error when bell button is not found,
  instead of silently no-op and waiting 8s before EmptyResultError
- post: use shared formatCookieHeader() instead of manual cookie string
  construction

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(band): address fifth round of code review feedback

- mentions: replace fixed page.wait(2) with polling for bell button
  readiness (up to 10s), eliminating the fixed sleep and fail-fast
  when the selector is missing
- mentions: add explicit !newsReq guard with a clear error message when
  get_news capture times out, instead of falling through to a misleading
  "No notifications found"
- posts: skip posts with no permalink href instead of emitting a bogus
  'https://www.band.us' URL

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(band): address sixth round of code review feedback

- post: only send Band cookies to *.band.us photo URLs; third-party CDN
  URLs are downloaded without cookies to avoid cross-domain cookie leakage
- bands: strip non-digit chars before parseInt so member counts like
  "1,234" parse correctly
- posts: same fix for comment counts

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(band): address seventh round of code review feedback

- posts: check limit before push so --limit 0 returns empty result
- post: indent replies proportionally by depth ('  '.repeat(depth))
  so multi-level threads remain readable in table output

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(band/bands): anchor href regex to prevent matching post-detail URLs

Pattern now requires /band/{id} or /band/{id}/post (with optional trailing
slash) so deeper paths like /band/{id}/post/{postNo} are excluded.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(band): address ninth round of code review feedback

- mentions: guard bell click with a boolean return so a disappearing
  element throws a clear EmptyResultError instead of a raw TypeError
- post: wait for comment list container instead of first .cComment so
  posts with zero comments don't incur a fixed 6s delay

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(band): use page.getCookies() for login detection across all commands

Replaces document.cookie.includes('band_session') with
page.getCookies({ domain: 'band.us' }) so login detection works even
if Band.us marks the session cookie as HttpOnly in the future.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(band): address eleventh round of code review feedback

- mentions: replace EmptyResultError with SelectorError for missing/
  disappeared bell button — produces a clearer SELECTOR error code
- post: assign per-photo filenames using a global index across both
  download batches so band-hosted and CDN photos don't overwrite each other

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(band): address twelfth round of code review feedback

- post: derive file extension from URL path and include in filename
  (e.g. photo_1.jpg) so downloaded photos have correct extensions
- posts: remove dead code guard (!url && !content) — url is always
  non-empty here since href-empty posts are already skipped above

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(band/post): use url-scoped getCookies for photo download auth

Domain-scoped getCookies may omit host-only cookies scoped to www.band.us;
using url: 'https://www.band.us' ensures all relevant cookies are included
in the auth header for Band-hosted photo downloads.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* docs(band): add adapter documentation and sidebar entry

Required by CI doc-check --strict: every adapter in src/clis/ must have
a corresponding docs/adapters/browser/*.md file.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* test(e2e): wire band auth coverage into default matrix

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: jackwener <jakevingoo@gmail.com>
2026-03-29 17:19:26 +08:00
jakevin 5c655ee3c8 feat(sinafinance): rewrite stock as public API, no browser required (#563)
* feat(sinafinance): rewrite stock as public API adapter

Replace browser-based DOM scraping with direct Sina public APIs:
  suggest3.sinajs.cn — symbol search (GBK, no auth)
  hq.sinajs.cn       — real-time quote (GBK, no auth)

Strategy.PUBLIC, browser: false — no Chrome or login required.
Supports A股 (sh/sz), 港股 (hk prefix), 美股 (gb_ prefix).
US MarketCap parsed from hq field [12]; formatted as T/B/M.

* feat(exit-codes): add Unix-standard exit codes to all CliError types

Introduce EXIT_CODES constant table (sysexits.h conventions) and wire
exitCode into every CliError subclass so the process exit code reflects
the semantic type of failure:

  0   success (default)
  1   generic / unexpected error
  2   argument / usage error        (ArgumentError)
 66   empty result / not found      (EmptyResultError, SelectorError)
 69   service unavailable           (BrowserConnectError, AdapterLoadError)
 77   permission / auth required    (AuthRequiredError)
 78   configuration error           (ConfigError)
124   timeout                       (TimeoutError)
130   Ctrl-C / SIGINT               (unchanged, tui.ts)

resolveExitCode() in commanderAdapter.ts reads err.exitCode for typed
CliErrors, and falls back to pattern-matching message text for untyped
adapter errors (auth pattern → 77, not-found pattern → 66, else → 1).

Shell scripts can now distinguish error categories:
  opencli spotify status || echo "exit $?"   # 69 if browser not running
  opencli github issues --repo x 2>/dev/null; [ $? -eq 77 ] && opencli github auth

* review: regex escape sym, fix change precision, optimize suggest type param
2026-03-28 21:59:44 +08:00
yichuanzhao99-ctrl 0b15561025 添加新浪财经行情及滚动新闻抓取 (#546)
* 添加新浪财经行情及滚动新闻抓取

* review: fix injection vuln, dead code, typos, hardcoded waits

rolling-news:
- Remove dead dateToTimestampParams function and unused CliError import
- Fix column field name typo: clomn → column
- Replace page.wait(5) with selector-based wait
- Remove all commented-out code

stock:
- Fix P0 JS injection: use JSON.stringify() to safely embed args.key/market
- Add null guard for inputEl before calling .focus()
- waitForElement returns null instead of throwing on timeout
- Replace page.wait(5) with selector-based wait
- Extract MARKET_CN/HK/US as named constants
- Throw CliError on NOT_FOUND instead of silent empty return

---------

Co-authored-by: jackwener <jakevingoo@gmail.com>
2026-03-28 21:46:33 +08:00
sline 9a9e078462 feat(bluesky): add Bluesky adapter with 9 commands (#215)
Bluesky (9 commands, public AT Protocol API, no auth needed):
- profile: user profile info (followers, following, posts)
- user: recent posts from a user with engagement stats
- trending: trending topics on Bluesky
- search: search users
- feeds: popular feed generators
- followers: list user's followers
- following: list accounts a user follows
- thread: post thread with replies
- starter-packs: user's starter packs

All commands use the public Bluesky API, no browser or login required.
2026-03-27 14:39:43 +08:00
Lr_2002 310e136a6c feat(paperreview): add paperreview.ai adapter (#464)
* feat(paperreview): add paperreview.ai adapter

* fix(cli): normalize boolean command options

---------

Co-authored-by: jackwener <jakevingoo@gmail.com>
2026-03-26 22:25:30 +08:00
AstroHan 0773616c1e feat(imdb): add IMDb adapter with 6 commands (#472)
* feat(imdb): add IMDb adapter with 6 commands

Add a public IMDb adapter using browser-based JSON-LD and __NEXT_DATA__
extraction. All commands use Strategy.PUBLIC with browser: true.

Commands:
- imdb search <query> — search movies, TV shows, and people
- imdb title <id> — get movie/show details (Movie, TVSeries, TVEpisode, TVMiniseries, TVMovie, etc.)
- imdb top — IMDb Top 250 chart
- imdb trending — Most Popular Movies
- imdb person <id> — actor/director info with filmography
- imdb reviews <id> — user reviews (first page, max 25)

Shared utils: ID normalization, ISO 8601 duration formatting, locale
forcing, JSON-LD extraction (supports type array filtering), and
anti-bot challenge detection.

* review: harden imdb adapter loading and tests

* test: unblock PR CI on merge head

---------

Co-authored-by: jackwener <jakevingoo@gmail.com>
2026-03-26 22:21:52 +08:00
槑囿脑袋 c75fea90ad feat(douban): add photo listing and download commands (#474)
* feat(douban): add photo listing and download commands

* refactor(douban): remove unreachable empty download branch

---------

Co-authored-by: jackwener <jakevingoo@gmail.com>
2026-03-26 21:59:20 +08:00
Conn Ho 15b9bc8e0c feat(producthunt): add Product Hunt CLI adapter (#462)
* feat(producthunt): add Product Hunt CLI adapter

Add three commands:
- posts: RSS feed with optional category filter
- today: latest day's posts from feed
- hot: today's top posts with vote counts (browser INTERCEPT strategy)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat(producthunt): add browse command for category best products

Browse top-rated products in any Product Hunt category (e.g. vibe-coding,
ai-agents, developer-tools) with name, tagline, and review count.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* docs(producthunt): add adapter documentation

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(producthunt): rebase on main and stabilize selectors

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: jackwener <jakevingoo@gmail.com>
2026-03-26 16:02:33 +08:00
Conn Ho 22399cee1a feat(36kr): add 36氪 CLI adapter (#461)
* feat(36kr): add 36氪 CLI adapter with 4 commands

- news: latest articles via public RSS feed (no browser needed), includes title/summary/date/url
- hot: trending articles via INTERCEPT strategy, supports --type renqi/zonghe/shoucang/catalog
- search: keyword search via INTERCEPT + DOM scraping
- article: fetch article detail (title/author/date/body) by ID or URL

Also adds vitest adapter project entry for 36kr tests.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* docs(36kr): add adapter documentation

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(36kr): use Shanghai hot-list dates and complete docs

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: jackwener <jakevingoo@gmail.com>
2026-03-26 15:34:46 +08:00
Xeron ed89157804 fix(jd): filter avif images only from pcpubliccms CDN (#453)
* feat(jd): add item adapter for JD.com product details

Support fetching:
- Product title, price, shop
- Product specifications (品牌, 型号, 规格参数 etc.)
- Main product images
- Detail images from product page

Usage: opencli jd item <sku>

* fix(jd): update test to expect avifImages column

* review: tighten jd item image contract

* fix: stabilize extension packaging and Chinese-site e2e

---------

Co-authored-by: jackwener <jakevingoo@gmail.com>
2026-03-26 15:12:41 +08:00
tiaot33 e64046219d feat(linux-do): refactor adapters with unified feed, tags, user commands (#434)
* feat(linux-do): refactor adapters with unified feed, tags, user commands

- Replace hot/latest/category with unified `feed` command (tag/category/view routing)
- Add `tags`, `user-topics`, `user-posts` commands
- Add static data files for categories and tags lookup
- Fix error handling: use CliError subclasses instead of raw Error
- Fix Discourse API field mapping in search (tags, created)
- Add strategy: cookie to all YAML adapters
- Update docs and README command listings
- Update E2E tests for new command signatures

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* review: resolve linux-do feed from live metadata

* fix: restore linux-do CI

* fix: harden linux-do compatibility

* refactor: stabilize linux-do command migration

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: jackwener <jakevingoo@gmail.com>
2026-03-26 00:45:34 +08:00
nianyi(likai) 39ca8330c5 feat(douyin): add Douyin creator center adapter (14 commands, 8-phase publish pipeline) (#416)
* feat(douyin): add Douyin creator center adapter (14 commands, 8-phase publish pipeline)

- publish: 8-phase pipeline (STS2 → TOS multipart upload w/ resume → ImageX cover → transcode poll → safety check → create_v2)
- draft: save as draft (phases 1-6 + is_draft:1, no timing)
- videos/drafts/delete/profile/update: content management
- hashtag (search/suggest/hot) / location / activities / collections / stats: discovery & analytics
- _shared: tos-upload (AWS Sig V4, multipart, resume), imagex-upload, transcode poller (encode=2), browser-fetch, sts2, creation-id, timing, text-extra
- 124 tests, tsc clean

* fix(douyin): accept unix timestamp strings

* docs(douyin): add browser adapter guide

---------

Co-authored-by: jackwener <jakevingoo@gmail.com>
2026-03-25 15:36:07 +08:00
pshu 554329fceb feat: add filter option for twitter search (#410)
* feat: add filter option for twitter search

* test: add tests

* docs: 📝 update

* fix(twitter): default search filter safely

---------

Co-authored-by: jackwener <jakevingoo@gmail.com>
2026-03-25 15:09:38 +08:00
iridite 9c99cbf8ab feat(xueqiu): add Danjuan fund account commands (#391)
* feat(xueqiu): add danjuan fund account commands

* refactor(xueqiu): convert danjuan fund YAML adapters to TS

- Replace 3 YAML files with 4 TS files (shared utils + 3 commands)
- Extract shared helpers: fetchDanjuanApi, fetchAssetGain, collectHoldings
- Fix double-navigation by using navigateBefore instead of pipeline navigate
- Unify error messages to English with Hint pattern
- Mask real account ID in docs example
- Add explicit default for --account arg

* refactor(xueqiu): optimize danjuan fund adapters

- Single page.evaluate with Promise.all for parallel account fetching
  (1 browser round-trip instead of N+1)
- Merge fund-accounts into fund-holdings (account info visible per row)
- 3 files: danjuan-utils.ts (shared), fund-holdings.ts, fund-snapshot.ts
- Strong TypeScript interfaces for all data shapes
- Update docs to reflect 2-command design

* fix(xueqiu): preserve danjuan pre-navigation metadata

* fix(xueqiu): fail on incomplete danjuan snapshots

---------

Co-authored-by: jackwener <jakevingoo@gmail.com>
2026-03-25 13:32:41 +08:00
Ryan Tan d36a43e805 feat(pixiv): add Pixiv adapter (#403)
* feat(pixiv): add Pixiv adapter with 6 commands

Add support for Pixiv (pixiv.net) with the following commands:
- ranking: daily/weekly/monthly illustration rankings
- search: search illustrations by keyword/tag
- user: view artist profile info
- illusts: list illustrations by artist
- detail: view illustration details (tags, stats)
- download: download original-quality images

All commands use COOKIE strategy to reuse Chrome's logged-in session.
YAML adapters for simple API fetches (ranking, detail, user), TypeScript
for complex logic (search, illusts, download with Referer header).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* test(pixiv): add unit tests and E2E auth failure tests

- search.test.ts: auth error, result parsing, limit, empty results (4 tests)
- illusts.test.ts: auth error, empty user, two-step fetch, limit (4 tests)
- download.test.ts: auth error, no images, Referer header, partial failure (4 tests)
- Add pixiv to vitest adapter project include list
- Add 5 pixiv commands to E2E browser-auth graceful failure tests

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(pixiv): correct ranking API path and YAML arg naming

- ranking: use /ranking.php?format=json (not /ajax/ranking which 404s)
- ranking: fix JSON path from data.body.contents to data.contents
- user/detail: rename hyphenated args (user-id → uid, illust-id → id)
  to fix YAML template evaluation (dot access doesn't support hyphens)

All 6 commands verified working against live Pixiv API.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(pixiv): use JSON.stringify to prevent code injection in page.evaluate

Address CodeRabbit review: all user inputs (query, userId, illustId,
idsParam) passed to page.evaluate are now serialized via JSON.stringify
instead of direct string interpolation, preventing code injection in
browser context.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor(pixiv): address code review feedback

- ranking.yaml: add | json filter to page/limit args for defense-in-depth
- user.yaml: guard illusts/manga/novels with typeof check for robustness
- Extract shared createPageMock to test-utils.ts, deduplicate across 3 test files

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor(pixiv): use minimal page mock and add download E2E test

- test-utils.ts: slim down to minimal mock (goto, evaluate, getCookies)
  with overrides support, matching upstream's pragmatic mock style
- Add missing download command to E2E browser-auth graceful failure tests

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(pixiv): address all remaining CodeRabbit review comments

- detail.yaml: add url to columns to match description mentioning "URLs"
- All adapters: differentiate HTTP errors — 401/403 → AuthRequiredError,
  404 → "not found", others → generic "request failed (HTTP N)"
- Tests: use beforeAll to cache registry lookup, avoiding repeated reads
  from global singleton
- Tests: assert error type (AuthRequiredError) not just message content
- Tests: add dedicated test cases for non-auth errors (500) and 404

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs(pixiv): add adapter docs and indexes

- Add pixiv.md documentation page under docs/adapters/browser/
- Update docs/adapters/index.md with pixiv entry
- Add Pixiv to sidebar in docs/.vitepress/config.mts
- Update README.md and README.zh-CN.md adapter tables
- Add pixiv to download support tables in both READMEs

Completes the documentation checklist for the pixiv adapter PR.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(pixiv): address code review findings

- Use CommandExecutionError instead of raw Error for HTTP failures
- Add page.goto() before page.evaluate() to establish browser context
- Fix search keyword double-encoding in URL construction
- Fix ranking.yaml using rating_count instead of illust_bookmark_count
- Throw on batch detail fetch failure instead of silent empty return
- Add beforeEach mock reset in download tests
- Add novels column to user.yaml output

Ensures pixiv adapter follows upstream CliError conventions and handles
edge cases correctly before submitting to upstream.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs(pixiv): improve download description in READMEs

- Replace technical Referer header detail with user-facing description
- Describe what users care about: original quality and multi-page support

Technical details belong in code comments, not user-facing docs.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs(pixiv): expand usage examples with all options

- Add ranking mode examples including R18 variants
- Add search filter examples (mode, order, pagination)
- Organize examples by command category for readability

Users need to know available options without reading source code.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(pixiv): address second round of CodeRabbit review comments

- Validate illust-id is numeric to prevent path traversal
- Move URL parsing inside per-item try block for graceful error handling
- Add auth error handling for batch detail request (consistent with step 1)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor(pixiv): extract shared pixivFetch helper, add input validation & batch support

- Create utils.ts with pixivFetch() for unified navigate + fetch + error handling
- Refactor search.ts, illusts.ts, download.ts to use pixivFetch (DRY)
- Add user-id/illust-id numeric validation in TS adapters
- Add batch pagination in illusts.ts for limit > 48 (Pixiv server limit)
- Add comment explaining Pixiv search API dual keyword requirement
- Update tests: new invalid-ID test cases, aligned mock format with pixivFetch

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: jackwener <jakevingoo@gmail.com>
2026-03-25 12:52:21 +08:00
VK 3d39574501 feat(dictionary): add dictionary search, synonyms, and examples adapters (#241)
* feat(dictionary): add dictionary search, synonyms, and examples adapters

* feat: Improve dictionary commands with positional word arguments, URL encoding, enhanced phonetic parsing, and new E2E tests.
2026-03-24 19:26:00 +08:00
jakevin 505c86bae9 docs: add missing adapter docs for jd and web (#349)
Add documentation for jd (item) and web (read) adapters to fix
doc-coverage CI check (55/57 → 57/57).
2026-03-24 16:03:18 +08:00
Piotr Yordanov 8869d3b457 feat(linkedin): add timeline feed command (#342)
* feat(linkedin): add timeline feed command

* test(linkedin): add timeline adapter unit tests

Add shape tests and utility function tests for the new timeline command.
Include linkedin in the vitest adapter project config.

---------

Co-authored-by: jackwener <jakevingoo@gmail.com>
2026-03-24 15:54:51 +08:00
jakevin 89a20e11bc docs: sync command references with current registry (#318) 2026-03-24 01:13:55 +08:00
AniChikage ea8324257d feat(yollomi): add new commands and update documentation in README files (#235)
* feat(yollomi): add new commands and update documentation in README files

- Added yollomi commands for generating images, videos, and editing capabilities.
- Updated README.md and README.zh-CN.md to include yollomi in the command list.
- Enhanced SKILL.md with yollomi-related tags and usage examples.

* feat(yollomi): add yollomi adapter to documentation

- Included yollomi in the VitePress configuration for browser adapters.
- Updated adapters index documentation to reflect yollomi's capabilities and commands.

* fix(yollomi): bug fixes, tests & improvements

- models.ts: add browser: false (no browser connection needed for hardcoded data)
- edit.ts: remove unused resolveImageInput import
- upload.ts: lower video upload limit from 100MB to 20MB (base64 OOM risk)
- generate.ts: improve file extension detection using URL.pathname
- upscale.ts: use choices for scale arg, improve extension detection
- object-remover.ts: make image/mask args positional
- Add yollomi models tests to public-commands.test.ts
- Add yollomi generate/video graceful-failure tests to browser-auth.test.ts

---------

Co-authored-by: anichikage <hanzhishuai@bytedance.com>
Co-authored-by: jackwener <jakevingoo@gmail.com>
2026-03-23 23:04:01 +08:00
jakevin 4343ec07e0 fix(tests): use positional arg syntax in browser search tests (#302)
Replace redundant --keyword/--query named flags with positional
arg syntax for all search commands that declare positional: true.
Also fix --query usage in tiktok.md docs example.

Affected:
- bilibili, weibo, zhihu, reuters, youtube, smzdm, boss, coupang, xiaohongshu search (browser-public.test.ts)
- linux-do search (browser-auth.test.ts)
- tiktok search (docs/adapters/browser/tiktok.md)
2026-03-23 19:00:12 +08:00
jakevin f00a5d1929 docs: update xiaohongshu search description, fix test count 31→32 (#301)
- docs/adapters/browser/xiaohongshu.md: fill in search command description
  (was empty), update usage examples with keyword positional arg
- TESTING.md: update unit test count 31→32 (search.test.ts added in #298),
  add xiaohongshu/search.test.ts to the adapter test file list
2026-03-23 17:59:35 +08:00