368 Commits

Author SHA1 Message Date
Jamie 5767c07bd8 feat(dribbble): add browser adapter commands (#2403)
* feat(dribbble): add browser adapter commands

* fix(dribbble): improve adapter commands

* fix(dribbble): verify and complete adapter contracts

---------

Co-authored-by: OpenCLI-sol <opencli-sol@users.noreply.github.com>
2026-08-28 19:07:49 +08:00
jakevin 6b3dffd398 feat(gmail): add browser-backed Gmail adapter (#2396)
* feat(gmail): add browser-backed adapter

* docs(gmail): document adapter commands

* refactor(gmail): remove unsupported write surface

* chore(gmail): split author workflow into dedicated PR

---------

Co-authored-by: OpenCLI-sol <opencli-sol@users.noreply.github.com>
2026-08-25 21:37:08 +08:00
Ao Liu cee4713918 fix(nowcoder): validate mixed post entities (#2218)
Co-authored-by: jackwener <jakevingoo@gmail.com>
2026-08-25 00:56:06 +08:00
billow 5d102265e6 feat(pixiv): add novel commands (#2112)
* feat(pixiv): add novel commands

* feat(pixiv): add account bookmarks and novel downloads

* fix(pixiv): harden novel payload validation

* fix(pixiv): tighten auth proof and numeric args

* fix(pixiv): harden archive boundaries

* fix(pixiv): validate novel archive metadata

---------

Co-authored-by: jackwener <jakevingoo@gmail.com>
2026-08-24 23:52:03 +08:00
Mingming Lou b4910ed6a8 feat(xiaoyuzhou): add playback history (#2260)
Co-authored-by: jackwener <jakevingoo@gmail.com>
2026-08-24 19:29:55 +08:00
lingjiuu 4a1cc3a457 fix(notebooklm): migrate redirected domain session (#2228) 2026-08-24 18:49:37 +08:00
qiuyang bc7d20e6d0 feat(xiaohongshu): add deterministic search filters (#2276)
Co-authored-by: jackwener <jakevingoo@gmail.com>
2026-08-24 18:22:21 +08:00
ele-yufo c16a2539fe feat(bilibili): add creator analytics adapter (#2268)
* feat(bilibili): add creator analytics adapter

* feat(bilibili): narrow creator stats contract

---------

Co-authored-by: yufo <yufo@MacBook-Pro.local>
Co-authored-by: jackwener <jakevingoo@gmail.com>
2026-08-24 17:39:26 +08:00
Octopus 5cb60a8468 feat(minimax): add guarded music generation adapter (#2290)
Co-authored-by: jackwener <jakevingoo@gmail.com>
2026-08-24 17:24:23 +08:00
Ninglin Du 48c151c6e3 feat(jira): add custom field support (#2289)
* feat(twitter): add custom field support

* change to comma fields

* remove ATLASSIAN_JIRA_FIELDS add --fields

* fix(jira): preserve selected field identity

---------

Co-authored-by: jackwener <jakevingoo@gmail.com>
2026-08-24 16:27:10 +08:00
kino 14d47c08bc feat(zhihu): export answers with local images (#2304)
* feat(zhihu): export answers with local images

* test(zhihu): cover answer image normalization

* fix(zhihu): harden answer export boundaries

* fix(zhihu): require question URL provenance

---------

Co-authored-by: jackwener <jakevingoo@gmail.com>
2026-08-24 15:38:10 +08:00
kino 85e95870bb feat(zhihu): preserve comment reply threads (#2306)
Co-authored-by: jackwener <jakevingoo@gmail.com>
2026-08-24 14:51:40 +08:00
Henry 144629740d feat(bilibili): add --top to fetch pinned comments (#2106)
* feat(bilibili): add --top to fetch pinned comments

The comments command already fetches /x/v2/reply/main, whose response
includes top_replies (置顶评论) alongside regular replies but discarded
them. Add a --top flag that returns only the pinned comments.

- --top reads data.top_replies (reusing formatReplyRow)
- --top is mutually exclusive with --parent (楼中楼 threads have no
  top_replies) and raises ArgumentError before any request
- generalize requireReplies to accept a key; absent top_replies is
  treated as empty, and an empty pinned list raises EmptyResultError

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

* fix(bilibili): harden pinned comment contract

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: jackwener <jakevingoo@gmail.com>
2026-08-24 04:01:50 +08:00
genoooool a86d64705c docs(plugin): add X Article publisher to examples (#2190) 2026-08-09 23:46:03 +08:00
Bo Liu 18f1ceba32 fix(codex): resolve the ChatGPT executable inside Codex.app (#2232)
* fix(codex): resolve the ChatGPT executable inside Codex.app

* fix(codex): try the ChatGPT executable first and sync the launch doc

* fix(codex): scope executable process detection to app bundle

* fix(codex): resolve symlinked app process identity

---------

Co-authored-by: jackwener <jakevingoo@gmail.com>
2026-08-08 20:05:32 +08:00
Bo Liu 05cfbee66e fix(codex): select slash-command picker options from send (#2239)
* fix(codex): select slash-command picker options from send

* fix(codex): unwrap bridge envelopes in send flows

---------

Co-authored-by: jackwener <jakevingoo@gmail.com>
2026-08-08 16:41:14 +08:00
lingjiuu 8b9faef054 fix(weread-official): bump skill version to 1.0.4 (#2227) 2026-08-08 15:52:16 +08:00
Alex Su dc9dde41f3 feat(pinterest): add Pinterest adapter suite (#2177)
* feat(pinterest): add Pinterest adapter suite

Adds `opencli pinterest` with 19 commands over Pinterest's internal resource API
(`POST /resource/<Name>Resource/<action>/`, form-urlencoded `source_url` + `data`,
`X-CSRFToken` + `X-Pinterest-PWS-Handler` headers, `bookmark` paging).

- Read: search-pins / search-boards / search-users, pin, user, user-pins,
  user-boards, board-pins, board-sections, download. Reads work anonymously
  because Pinterest issues a csrftoken to logged-out sessions too.
- Write: save (boardless repin lands in "Quick saves"), pin-create /
  pin-update / pin-delete, board-create / board-update / board-delete,
  board-section-create / board-section-delete.
- Deletes require `--confirm`; without it the command resolves and names the
  target, then exits non-zero via ArgumentError (pin title + board for
  pin-delete, pin count for board-delete, section title for
  board-section-delete).
- Boards are addressed by `<username>/<slug>`, a board URL, or the numeric
  `boardId` (BoardResource accepts `board_id` and reports the board's url, which
  is reused so the id path costs no extra round trip); sections by id or slug.
  Display names are not accepted — a name alone cannot say which account a board
  belongs to. A Pinterest site route such as a `/pin/<id>/` URL is rejected as
  such instead of being parsed as the board `pin/<id>`.
- Board URLs are percent-decoded before use: Pinterest hands out encoded slugs
  for non-ASCII board names, and posting those verbatim answers HTTP 404. Slugs
  are compared Unicode-normalized so an NFD-composed accent still matches.
- Sections can only be set by a follow-up move. PinResource/create and
  RepinResource/create accept a section key, answer HTTP 200, and file the pin
  at the board root anyway; only PinResource/update honours it (under
  `board_section_id`, not `section_id`). So `save --section` and
  `pin-create --section` create then move, and report the created pin id if the
  move fails rather than claiming success.
- Omitting an optional text flag leaves the field alone; passing an empty string
  clears it. Pinterest refuses link edits on pins it scraped, and answers 401
  for that, so its own message is surfaced rather than only "log in".
- Typed errors throughout: ArgumentError for bad refs, unknown sections,
  `--section` without `--board`, and limits (validated before any request, with
  no silent clamp); AuthRequiredError on 401 (and 403 on writes only, since
  reads are anonymous); CommandExecutionError for malformed payloads and
  unresolvable targets.

Live-verified end-to-end against a logged-in account: all 10 read commands, and
the full write cycle (board-create → board-section-create → board-update →
pin-create → pin-update → save → the three deletes, preview and confirmed),
including section placement checked on each pin's own `section` field, non-ASCII
board/section slugs, board-id addressing, and clearing a description. 131 tests;
full suite 6258 passed; `tsc --noEmit` clean; `opencli validate` 0 errors;
typed-error-lint and silent-column-drop both new=0; doc coverage 174/174.

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

* fix(pinterest): drop board-update --privacy empty default

`coerceAndValidateArgs` applies an arg's default and then enforces `choices`
against it, so `default: ''` on a public|secret flag rejected every run that
omitted `--privacy`:

    $ opencli pinterest board-update janedoe/my-board --name Foo
    error: ARGUMENT  Argument "privacy" must be one of: public, secret. Received: ""

Leaving the default off keeps the flag optional; the command already reads it
as `String(kwargs.privacy ?? '')`.

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

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-30 20:31:59 +08:00
ele-yufo 7702d8d534 feat(midjourney): add image generation adapter (#2201)
* feat(midjourney): add complete browser adapter

* fix(midjourney): verify paid action settings

---------

Co-authored-by: yufo <yufo@MacBook-Pro.local>
Co-authored-by: OpenCLI-sol <opencli-sol@users.noreply.github.com>
2026-07-30 20:25:49 +08:00
Ao Liu b4f5df9d19 fix(xiaohongshu): extract direct comment reply target (#2175) 2026-07-29 20:26:21 +08:00
Bo Liu ab28a1f2eb fix(amazon): honor the input marketplace instead of rewriting to amazon.com (#2185)
* fix(amazon): honor the input marketplace instead of rewriting to amazon.com

* fix(amazon): reject amazon.<label>.<tld> look-alikes and localize the auth hint

* fix(amazon): allow only known marketplace domains

---------

Co-authored-by: OpenCLI-sol <opencli-sol@users.noreply.github.com>
2026-07-29 20:14:38 +08:00
Bo Liu 5256711a25 enrich(ctrip): expand the adapter across Ctrip's travel verticals (#2156)
* enrich(ctrip): add train ticket search command

ctrip search already suggests railway stations but there was no way to query the
actual departures. ctrip train <from> <to> --date fills that gap on the public
trains.ctrip.com list page, browser-mode + cookie like flight/hotel-search. Rows
are read by stable class-keyed fields rather than positional innerText;
incomplete cards are dropped, not sentinel-filled.

* enrich(ctrip): add hotel detail command

Single-hotel profile from the detail-page SSR: rating sub-scores, hot facilities, check-in/out policy.

* enrich(ctrip): add bus ticket search command

Intercity coach search via the newbus results deep link (landing SPA does not hydrate under the bridge).

* enrich(ctrip): add ferry ticket search command

Passenger ferry sailings via the ship.ctrip.com results deep link, sibling of bus.

* enrich(ctrip): add cruise package search command

Resolves a departure port name to its legacy per-port code, then reads the .route_info cards.

* enrich(ctrip): add tour package search command

Group and self-guided tour search via the vacations sv=<destination> deep link, stable-class cards.

* enrich(ctrip): add flight+hotel package search command

Shares the vacations product extractor with tour (freetravel section); folds a 万 count multiplier into the shared parser.

* enrich(ctrip): raise CommandExecutionError on rendered-but-unparsed results

Matches the drift handling bus/ferry/train use, so genuine-empty stays EmptyResultError.

* enrich(ctrip): generalize shared list helpers, drop dead train constants

parseListLimit / parsePlaceName replace the train-named helpers now reused across bus/ferry/cruise/tour/package with neutral hints; ferry ship-name/duration read by pattern, not position.

* enrich(ctrip): add attraction listing command

* enrich(ctrip): add round-trip flight search command

* enrich(ctrip): scope attraction to city id and harden flight-round

* fix(ctrip): repoint one-way flight to Ctrip's migrated .flight-item cards

* fix(ctrip): harden travel adapter boundaries

* fix(ctrip): preserve raw limit strings

* test(ctrip): avoid adapter src import

---------

Co-authored-by: jackwener <jakevingoo@gmail.com>
2026-07-21 01:58:26 +08:00
Bo Liu 0124c4eb7d feat(trip): add Trip.com international adapter (#2158)
* feat(trip): add Trip.com international flight search adapter

Trip.com is the English-facing sibling of the ctrip adapter. trip flight
searches worldwide one-way flights, browser-mode + cookie like ctrip flight.
Results are read from .result-item cards by stable data-testid anchors rather
than positional innerText; incomplete cards are dropped, not sentinel-filled.

Closes #2157

* enrich(trip): add hotel-search command

* enrich(trip): add hotel detail command

Single-hotel profile from the detail-page SSR (same shape ctrip hotel uses); also documents the existing hotel-search command.

* enrich(trip): add round-trip flight search command

Reuses the shared .result-item flight extractor against a triptype=rt search URL.

* enrich(trip): rename parseFlightLimit to parseListLimit

The 1-50 limit parser is shared by hotel-search and both flight commands, so a neutral name reads truer than the flight-specific one.

* enrich(trip): add attractions and experiences search command

Anchors on each things-to-do card's stable detail link (name + per-row url) and reads rating/reviews/booked/price by data-format pattern, since the cards use hashed CSS-module classes.

* enrich(trip): add train route timetable command

Reads the per-country SEO route timetable (departure/arrival times, stations, duration, changes) by stable class fields; per-journey fares sit behind the booking step.

* enrich(trip): add car-rental listing command

* enrich(trip): add airport-transfer listing command

* enrich(trip): add tour-package search command

* enrich(trip): add public destination-suggest command

* enrich(trip): add flight+hotel package search command

* docs(trip): note eSIM plans surface via attraction search

* enrich(trip): add live-promotions deals command

* enrich(trip): treat empty deals parse as drift, not empty result

* enrich(trip): split tour no-match (empty) from schema drift

* fix(trip): type public fetch drift failures

* fix(trip): require package flight identity

---------

Co-authored-by: jackwener <jakevingoo@gmail.com>
2026-07-21 01:35:12 +08:00
cypggs c1ee31d063 feat(kimi/usage): read quota from membership subscription page (#2104)
* feat(kimi/usage): read quota from membership subscription page

Replace the /code/console page with /membership/subscription?tab=quota so the command surfaces the total usage percentage plus 5h/7h rate limits, gift quota, and booster balance.

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

* feat(deepseek/usage): add usage command for platform.deepseek.com

Reads DeepSeek platform usage data from https://platform.deepseek.com/usage
via internal API (get_user_summary) for account-level data and DOM extraction
for time-dimension summary cards.

Output columns:
- balance / bonusBalance (充值/赠送余额)
- cumulativeSpend (累计消费金额)
- monthlySpend / monthlyApiCalls / monthlyTokens (本月数据)
- currentTokenEstimation (当前可用 Tokens 预估)
- timePeriod / periodSpend / periodApiCalls / periodTokens (时间维度)

* test(usage): harden kimi and deepseek usage contracts

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: jackwener <jakevingoo@gmail.com>
2026-07-20 17:57:27 +08:00
pi-dal 0e73c3c2c2 feat(google): add images search adapter
Adds a read-only Google Images browser search adapter with typed parser boundaries.\n\nReviewed-by: codex-mini0\nReviewed-by: First-principles-0
2026-07-19 19:07:23 +08:00
Bo Liu f3586293d0 feat(toutiao): add recommend channel feed, fix hot --limit being ignored (#2149)
* feat(toutiao): add recommend channel feed, fix hot --limit being ignored

hot declared func(_page, kwargs) while browser:false commands receive a single
args object, so kwargs was always undefined and --limit silently fell back to
30. Its unit tests passed only because they called func(null, kwargs) by hand.

* fix(toutiao): require recommend article identity

---------

Co-authored-by: jackwener <jakevingoo@gmail.com>
2026-07-19 17:15:36 +08:00
Adong 928b1e548d feat(hltv): add HLTV adapters (#2028)
* feat(hltv): add HLTV adapters

* fix(hltv): harden row identity contracts

---------

Co-authored-by: Adong <jhdong8855@gmail.com>
Co-authored-by: jackwener <jakevingoo@gmail.com>
2026-07-03 20:50:22 +08:00
Louie 96cbeb4f65 docs: align adapter contribution example with the JavaScript adapter layer (#2017)
The "Create a file like clis/<site>/<command>.ts" example predates #928, which
converted the entire adapter layer from TypeScript to JavaScript. The repo now
ships 0 .ts and 1259 .js built-in adapters, so a contributor following the doc
creates a file in the wrong format. Update the example to JavaScript (keeping a
pointer to the still-supported TypeScript path), and fix the adapter test
command, which pointed at src/ rather than the adapter's own clis/ test file.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-03 20:21:47 +08:00
Marvin d6a7011454 Add ChatGPT Deep Research result extraction (#2023)
* Add ChatGPT Deep Research result extraction

* fix(chatgpt): bind deep research results to requested conversation

* fix(chatgpt): preserve deep research payload failures

---------

Co-authored-by: jackwener <jakevingoo@gmail.com>
2026-07-01 02:12:06 +08:00
Marvin e7bdad4783 Fix ChatGPT intelligence level selection (#2022)
* Fix ChatGPT intelligence level selection

* Document ChatGPT model adapter usage in browser skill

* fix(chatgpt): verify model config selection

* fix(chatgpt): classify model preference api drift

---------

Co-authored-by: jackwener <jakevingoo@gmail.com>
2026-07-01 02:01:22 +08:00
lizkaiman 215a73dc56 feat(gemini): add model and thinking selection (#2044)
* feat(gemini): add model and thinking selection

Co-authored-by: multica-agent <github@multica.ai>

* fix(gemini): harden model selection contracts

---------

Co-authored-by: coder-SOTA-hm <coder-SOTA-hm@users.noreply.github.com>
Co-authored-by: multica-agent <github@multica.ai>
Co-authored-by: jackwener <jakevingoo@gmail.com>
2026-07-01 01:33:43 +08:00
iynewz d174f724ec feat(adapter): add Mercury reimbursement helpers (#2052)
* Add Mercury reimbursement helpers

* fix(mercury): fail closed reimbursement drafts

* fix(mercury): harden reimbursement draft safety checks

---------

Co-authored-by: jackwener <jakevingoo@gmail.com>
2026-07-01 01:25:09 +08:00
jakevin ba2dcc0dcc fix(browser): enforce fixed daemon bridge port (#2031) 2026-06-27 21:51:54 +08:00
Louie df8ca8d440 feat(xianyu): search 服务端价格区间 / 地区筛选 (mtop API) (#2013)
* feat(xianyu): search 支持服务端价格区间 / 地区筛选(--min-price/--max-price/--province/--city)

闲鱼 search 之前只有 query + limit。本次改成直接调 goofish 自己的搜索接口
`mtop.taobao.idlemtopsearch.pc.search`(沿用 item.js 里 window.lib.mtop.request
的用法,签名由页面自带,无需手搓),把价格区间和地区交给服务端筛选 + 分页,
而不是抓一屏 DOM 再在本地过滤。

筛选编码是在登录态浏览器里 hook window.lib.mtop.request、实际操作筛选面板抓到
真实请求后逆出来的,并逐条用接口返回 + 详情接口 publishCity 做了 ground-truth 校验:

- --min-price / --max-price → propValueStr.searchFilter = "priceRange:<min>,<max>;"
  (元;单边区间用 0 / 99999999 兜底)。实测 priceRange:100000,150000 返回价格
  全部落在 112999–149900。
- --province / --city → extraFilterValue = JSON({divisionList:[{province,city}],
  excludeMultiPlacesSellers:"0",extraDivision:""})。city 可单独使用(province 留空)。
  实测「广东」「北京」结果集完全不相交;--city 深圳 / 湛江 的结果用详情接口校验
  publishCity 全部命中。
- 任一筛选生效时 fromFilter=true。limit 最多 60,按需翻页(rowsPerPage=30)。

返回字段改为结构化解析(item_id / title / price / location / want / url),
鉴权与风控错误处理沿用 item.js 的成熟逻辑(AuthRequired / Empty / mtop-not-ready)。

已在登录态浏览器里真跑验证(深圳+10–20万、湛江、无筛选基线均正确),
clis/xianyu 45 个单测全绿,tsc --noEmit 通过,cli-manifest.json 同步重建。

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

* fix(xianyu): harden search filter result handling

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: jackwener <jakevingoo@gmail.com>
2026-06-27 18:28:47 +08:00
Bo Liu 1dd712d609 feat(juejin): add Juejin (掘金) read-only adapter (#2007)
* feat(juejin): add Juejin (掘金) read-only adapter

Two PUBLIC commands for the Juejin developer community: `recommend` (homepage feed) and `hot` (article ranking by category). Native fetch against api.juejin.cn; no browser, no auth. Category aliases (`backend`, `frontend`, `android`, `ios`, `ai`) resolve to Juejin's stable numeric ids.

Closes #1711

* fix(juejin): fail closed on API shape drift

* fix(juejin): expose recommendation cursor

* fix(juejin): classify response cursor drift

---------

Co-authored-by: jackwener <jakevingoo@gmail.com>
2026-06-24 06:18:24 +08:00
Louie ee4820ef59 feat(adapters): add Chinese car-platform adapters — 懂车帝 / 瓜子二手车 / 汽车之家 (no-login) (#2009)
* feat(adapters): add 懂车帝 (dongchedi) + 瓜子二手车 (guazi) car adapters

Two no-login PUBLIC adapters for Chinese car platforms. Both read
server-rendered data (no cookies, no signature, no browser) and ship
pure parsers unit-tested against frozen real-data fixtures.

dongchedi (6 commands) — parses __NEXT_DATA__ SSR JSON:
  search  车系搜索 + 指导价/经销商价
  series  车系概览(品牌/价格/懂车分/销量排名/款型数)
  models  款型列表 + 价格
  specs   配置概览(尺寸/动力/四驱/悬挂/气囊)
  score   懂车分 8 维评分 + 同级对比
  koubei  车主口碑/评价正文
  (Dongchedi's /motor XHR APIs are ByteDance-signature gated; the SSR
   pages expose the same data unsigned, so the adapter reads those.)

guazi (2 commands) — parses m.guazi.com mobile SSR HTML:
  browse  分城市在售二手车列表(售价/里程/年份)
  car     车源详情(售价/上牌/里程/过户/配置/车况)
  (Desktop www.guazi.com is signature-locked; mobile SSR is open. Deep
   pagination/filtering uses the signed API and is intentionally omitted.)

Gates green: tsc, doc-coverage --strict, silent-column-drop (new=0),
typed-error-lint (no new), 24 adapter tests passing.

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

* feat(adapters): add 汽车之家 (autohome) — brand catalog + 口碑 ratings

Third no-login PUBLIC car adapter (search by brand, not free text).

autohome (2 commands):
  brand  按品牌列出全部车系 + 厂商指导价(grade/carhtml/<INITIAL>.html,
         中文品牌名→拼音首字母目录页,DL 块按品牌定位)
  score  车系口碑评分:总分 + 各维度 + 故障率PPH + 竞品对比
         (k.autohome.com.cn/<id> 的 __NEXT_DATA__.baseData,免登录免签名)

Deliberately omitted (would be silently-wrong without a browser running
Autohome's signing/anti-scrape code): free-text keyword search (signature
gated) and full per-trim 参数配置 (rotating CSS font-glyph obfuscation).
Use dongchedi search/specs/koubei for those. Documented in the adapter doc.

Gates green: tsc, doc-coverage --strict (170/170), silent-column-drop
(new=0), typed-error-lint (no new); 31 adapter tests passing across the
three car adapters.

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

* fix(car-adapters): fail closed on parser drift

* fix(guazi): fail closed on empty SSR listings

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: jackwener <jakevingoo@gmail.com>
2026-06-24 06:07:01 +08:00
leo1in88 7af50abd04 feat(github): add github trending adapter (#1953)
* feat(github): add `github trending` adapter

Add a PUBLIC adapter that lists repositories from
https://github.com/trending — the trending view is a public HTML page with
no official REST API, so the data was previously unreachable through opencli.

The adapter fetches the page server-side (no browser, no auth) and parses
each repo's full name, description, primary language, total stars, forks,
and stars gained in the period.

Flags:
- `--since`    daily | weekly | monthly (default daily)
- `--language` filter by language slug, e.g. python, rust, "c++"
- `--limit`    1..25 (GitHub lists at most 25)

Typed errors: ArgumentError for bad --since / --limit, CommandExecutionError
on request/HTTP failure, EmptyResultError when the page yields no repos.

Tests cover parsing (stars/forks/language/description/url, missing language),
limit truncation, language+since URL building, argument validation, the
empty-result path, and non-ok HTTP.

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

* refactor(github-trending): rename to standalone `github-trending repos`

Move the trending scraper out of the `github` site namespace into a
dedicated `github-trending` adapter to avoid confusion with the bundled
`gh` external CLI. Command is now `opencli github-trending repos`
(site=github-trending, name=repos), leaving room for a future
`developers` subcommand. The `github` site retains only login/whoami.

Regenerated cli-manifest.json; 8 fixture tests + typecheck pass.

* fix(github-trending): fail closed on parser drift

---------

Co-authored-by: minh <claude@ttfy.cc>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: jackwener <jakevingoo@gmail.com>
2026-06-22 21:27:57 +08:00
Bo Liu acfab26a52 feat(semanticscholar): add Semantic Scholar academic graph adapter (#1994)
* feat(semanticscholar): add Semantic Scholar academic graph adapter

Native fetch against api.semanticscholar.org. Four read commands cover paper detail (with influentialCitationCount and tldr), citation list, AI-curated recommendations, and free-text search. Optional SEMANTIC_SCHOLAR_API_KEY env var lifts the anonymous rate limit.

Closes #1993

* fix(semanticscholar): fail closed on malformed paper rows

---------

Co-authored-by: jackwener <jakevingoo@gmail.com>
2026-06-22 16:25:11 +08:00
cypggs 7879b774e9 feat(kimi): add usage adapter (#1985)
* feat(kimi): add code-console adapter

Read Kimi Code console usage cards: weekly quota, rate limit,
membership, and model permission.

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

* refactor(kimi): rename code-console adapter to usage

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

* refactor(kimi): remove code-console.js after renaming to usage

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

* fix(kimi): register and harden usage adapter

* fix(kimi): fail closed on missing usage cards

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: codex-mini0 <codex-mini0@slock.local>
Co-authored-by: jackwener <jakevingoo@gmail.com>
2026-06-20 23:57:22 +08:00
Bo Liu d2abdcc4b7 feat(archive): add Internet Archive read-only adapter
Final head 5f5661c270.

Contract: adds a public read-only Internet Archive adapter with archive search, item, wayback, and snapshots commands. All commands are read access, browser:false, with no login, write, upload, or browser UI side effects. Source of truth is Internet Archive Advanced Search response.docs, /metadata/<identifier>, Wayback available closest snapshot, and CDX JSON header/rows. Fail-closed boundaries: search requires response.docs array, true empty maps to EmptyResultError, rows require stable identifier and numeric downloads; item requires metadata.identifier equals requested identifier and files array, while missing metadata/404 remains empty; wayback distinguishes no closest snapshot true empty from available:true missing URL or 14-digit timestamp malformed CommandExecutionError; snapshots requires top-level CDX array, header array, required columns, and per-row timestamp/original/statuscode/mimetype cells, with malformed shapes typed CommandExecutionError rather than empty snapshot URLs or empty status columns.

Validation: lead+aux final green. GitHub final gate OPEN/non-draft/CLEAN, required checks SUCCESS, adapter/smoke skipped. Local reviewer validation covered current-main merge-tree clean, targeted/full clis/archive 1 file/18 tests, typecheck, build manifest 1231, docs-build, doc coverage 165/165, prod audit clean, node --check touched Archive files/tests, diff-check, typed-error-lint and silent-column-drop no new.
2026-06-19 04:28:56 +08:00
Marvin efd3c03d49 fix(chatgpt): support current intelligence levels
Final head 2279aca321.

Contract: chatgpt model keeps the existing write surface and supports instant, medium, high, extra-high, and pro intelligence levels; thinking remains a backward-compatible alias for high. Unsupported or unknown requested levels fail upfront with ArgumentError. The selection path requires a logged-in ChatGPT composer and native click. The model selector prefers stable test id / exact visible option text, covering current English Instant/Medium/High/Extra High/Pro and Chinese 极速/均衡/高级/超高/专业 labels. Unknown localization falls back to order only when composer-intelligence-picker-content exists and exactly five visible menuitemradio options are present; otherwise it typed-fails with CommandExecutionError instead of treating an ordinary menu or drifted DOM as success. Postcondition re-reads current selector/test id after click; when label recognition is unavailable, it reopens the picker and verifies the target checked index in the five-option intelligence picker. High vs Extra High matching uses longest/exact ordering to avoid substring false success. No ask/send/read/image/history surface changes.

Validation: lead+aux content green. Remote statusCheckRollup is empty, merged under the standing no-check override after final poll confirmed OPEN/non-draft, head unchanged, and MERGEABLE/UNSTABLE with no conflict/dirty/content blocker. Local reviewer validation covered current-main replay clean, focused ChatGPT utils+commands tests 77/77, full ChatGPT 6 files/118, typecheck, build manifest 1227, docs-build, doc coverage 164/164, prod audit clean, node --check touched files/tests, diff-check, typed-error-lint and silent-column-drop no new, and merge-tree clean.
2026-06-17 22:04:30 +08:00
AstroHan 8b765236fb feat(xiaohongshu): expose ask source metadata
Final head 53686e6a62.

Contract: xiaohongshu ask remains a browser-backed write command. Answer success still requires the same-send message_id/conversation_id plus a finished non-empty answer. Source identity/url/xsec_token are still trusted only from a 24-hex note id, xhsdiscover://item/<id>, or trusted XHS note URL. New source metadata is a minimal optional enrichment: note_type, user_id, and published_at are forwarded from the 点点 source payload and omitted when empty; like_count is parsed only from non-negative safe integers, strict decimal compact counts with 万/w/W/亿 and optional +, or legal pure digit/thousands strings. Malformed values such as 1e2, 0x10, 1..2万, bad comma grouping, negatives, and decimal numbers are omitted rather than coerced into successful counts. No extra note/detail round-trip or new write surface.

Validation: lead+aux final green. GitHub final gate OPEN/non-draft/CLEAN, required checks SUCCESS, adapter/smoke skipped. Local reviewer validation covered focused clis/xiaohongshu/ask.test.js 1 file/15, full XHS adapter 20 files/270, typecheck, build manifest 1227, docs-build, node --check ask/touched tests plus dist/src/main.js, diff-check clean, and local merge-tree clean.
2026-06-17 22:01:01 +08:00
Henry a28390d36f feat(xiaohongshu): support text-image publishing
Final head d41552312e.

Contract: xiaohongshu publish gains text-image publishing behind --card-text. --card-text/--images require at least one content source. Normal image suffix/path validation and text-image gif append are pre-navigation ArgumentError. Text-image flow enters 文字配图, writes/verifies each card, waits for a new active empty card before multi-card input, generates previews, then Next enters the standard editor before title/body/topics. Explicit --card-style must resolve/click or typed-fail with CommandExecutionError, with no silent fallback to 基础. After Generate/Next and image append, visible media count postconditions must prove cards and appended images landed. Publish/draft final success requires a success marker or leaving the publish page; warning-like text cannot fake success.

Validation: lead+aux final green on d4155231. GitHub final gate OPEN/non-draft/CLEAN with required checks SUCCESS and adapter/smoke skipped. Local reviewer validation covered publish tests 31/31, full Xiaohongshu 17 files/246 tests, typecheck, build manifest 1225, docs-build, doc coverage 164/164, production audit clean, node --check, diff-check, typed-error-lint/silent-column-drop no new, and merge-tree clean.
2026-06-17 01:54:14 +08:00
G6-CSE-2246 0a239af512 feat(xiaohongshu): add saved and liked collection scrapers
Adds Xiaohongshu saved and liked collection read commands.\n\nFinal review contract:\n- saved/liked are read-only current-user collection scrapers; no write, unlike, or favorite side effects.\n- --limit validates strictly in 1..100 before browser navigation.\n- Collection page location is read back after goto and after each scroll before trusting captures/DOM.\n- Location must be exactly https://www.xiaohongshu.com/user/profile/<resolvedUserId>; /login or login-wall text maps to AuthRequiredError; other host/path/profile drift maps to CommandExecutionError.\n- Browser Bridge {session,data} envelopes are unwrapped; malformed location, non-array intercepted requests, and non-array DOM extraction fail closed.\n- API/DOM notes require stable note id and xsec_token; output URLs round-trip to note/detail.\n- Auth/private/empty/malformed/API/parser/selector drift typed boundaries are preserved.\n\nValidation:\n- Lead and aux final green on ef12a197.\n- Final GitHub poll: open, non-draft, head ef12a197, statusCheckRollup empty only; merged under standing no-check override because content review is green and no conflict/dirty/content blocker remains.\n- Focused collection/saved/liked tests 3 files / 19.\n- Full XHS adapter 20 files / 253.\n- typecheck, build/manifest 1227, docs-build.\n- node --check touched collection files + dist/src/main.js.\n- typed-error-lint and silent-column-drop no new issues; listing-id advisory 13; diff-check clean.
2026-06-17 01:50:15 +08:00
AlexYue b85ab89938 feat(discord-app): add targeted read navigation
Adds targeted Discord desktop-app read/navigation commands with fail-closed identity checks.\n\nFinal review contract:\n- Surface remains read/navigation only: goto, channels, servers, threads, read, and thread-read; no Discord write command is introduced.\n- Browser Bridge evaluate results are unwrapped and shape-guarded at the Node boundary for route state, list rows, messages, and thread lists.\n- True empty list/read/thread-read results map to EmptyResultError; malformed rows or browser output map to CommandExecutionError.\n- Targeted read and thread-read verify message rows bind to the requested channel/thread via channel_id; stale, wrong-channel, parent-channel, or missing identity rows typed-fail.\n- List rows require stable identities: channels require Channel/guild_id/channel_id/url, servers require Server/guild_id/url, threads require Thread/guild_id/channel_id/thread_id/url.\n\nValidation:\n- Lead final and aux final green on e84a7d85.\n- merge-tree clean against base 8ed8ca26.\n- Discord app tests 19/19.\n- build manifest 1225, typecheck, docs-build, doc coverage 164/164, node --check touched files/tests, diff-check.\n- typed-error-lint and silent-column-drop no new issues.\n- GitHub required checks SUCCESS; adapter/smoke skipped.
2026-06-15 17:06:30 +08:00
AstroHan c027944380 feat(xiaohongshu): add ask adapter with citations
feat(xiaohongshu): add ask adapter with citations

Co-authored-by: codex-mini1 <codex-mini1@users.noreply.github.com>
Co-authored-by: First-principles-1 <first-principles-1@users.noreply.github.com>
2026-06-14 04:13:56 +08:00
sundyli ac0a8ba725 feat(huodongxing): add events adapter
feat(huodongxing): add events adapter

Co-authored-by: codex-mini0 <codex-mini0@users.noreply.github.com>
Co-authored-by: First-principles-0 <first-principles-0@users.noreply.github.com>
2026-06-14 04:12:38 +08:00
Jacky 7382a3541f feat(slock): add collaboration adapter
feat(slock): add collaboration adapter

Co-authored-by: codex-mini1 <codex-mini1@users.noreply.github.com>
Co-authored-by: First-principles-1 <first-principles-1@users.noreply.github.com>
2026-06-13 02:52:05 +08:00
gucasbrg 1e40165107 fix(bloomberg): read Businessweek from section page
fix(bloomberg): read Businessweek from section page

Co-authored-by: codex-mini1 <codex-mini1@users.noreply.github.com>
Co-authored-by: First-principles-1 <first-principles-1@users.noreply.github.com>
2026-06-12 18:11:59 +08:00
Ocean aa468589c5 feat(bilibili,xiaohongshu): add follow and unfollow commands
feat(bilibili,xiaohongshu): add follow and unfollow commands

Co-authored-by: codex-mini0 <codex-mini0@users.noreply.github.com>
Co-authored-by: First-principles-0 <first-principles-0@users.noreply.github.com>
2026-06-12 02:13:10 +08:00