* chore(release): 1.8.0
Substantial release: weread-official adapter, wider LinkedIn / Twitter / Reddit / Zhihu coverage, 12306 / Suno / Xianyu additions, security and reliability fixes, plus a 20% README shrink.
* chore: remove orphan docs/adapters-doc/ones.md
The file was a leftover from PR #386 (2026-04-10) and has been
superseded by docs/adapters/browser/ones.md. Bundled into the 1.8.0
release commit chain so the release doesn't ship with a dead docs
file alongside the new docs.
Skipped from opus-reviewer's audit (Tier 1 #1-#4) for this release:
- #1 smart-search dead refs (10 spots) — owned by @codex-coder's
skill-deletion PR; release PR will rebase on top of it.
- #3 clis/test-utils.js relocation — touches 19 importers, separate
refactor PR.
- #4 clis/slock/ orphan — needs WAWQAQ design call.
- #6 opencli-usage:161 wording — current "Commands that used to
exist" framing is already clear enough.
- #7 docs/adapters/index.md sync (8-20 missing sites) — broader docs
PR, not release-time bundling.
* chore: remove clis/slock + sync docs/adapters/index.md (audit #4 + #7)
Per WAWQAQ post-audit directive on #OpenCLI:f046ece7:
- `clis/slock/` was a half-finished orphan with only `_utils.js` and no
command entry points. Removed.
- `docs/adapters/index.md` was missing 11 browser adapters: 12306,
suno, weread-official, qwen, 1point3acres, brave, duckduckgo, cnki,
flomo, jianyu, taobao. Added all with commands sourced from
cli-manifest.json. Desktop section already covered all 7 desktop
adapters (Cursor / Codex / Antigravity / ChatGPT App / ChatWise /
Discord / Doubao App).
* chore: drop util.styleText to support Node v20+
util.styleText was added in Node v21.7.0 / v20.12.0. v21.0.0-v21.6.x and
v20.0.0-v20.11.x throw `SyntaxError: ... styleText` at startup because the
import resolves before any user code runs (a real user reported this on
v21.2.0).
OpenCLI is primarily agent-facing — terminal colors are noise to consumers,
and the [OK] / [WARN] / [FAIL] / ℹ / ⚠ / ✖ markers we already write carry
the semantic info that colors only repeated. Strip styleText entirely from
logger / output / doctor / tui / update-check / cli / download/progress /
commands/daemon and clean up the resulting awkward `${'literal'}` template
fragments. engines.node now reads ">=20.0.0".
This removes the Node-version coupling that A/B fixes would only have
papered over.
* fix(runtime): truly support Node v20+ by aligning guard + undici
Follow-up to the styleText removal: declaring engines.node >=20.0.0 is
not enough on its own. Two coupled barriers remained:
- src/runtime-detect.ts: MIN_SUPPORTED_NODE_MAJOR = 21 explicitly
rejected v20 at startup
- undici@^8.0.2 declares engines.node >=22.19.0; Node 20/21 crash on
webidl.util.markAsUncloneable before any user code runs
Lower the guard to 20 and downgrade undici to ^6.25.0 (engines >=18.17,
retains Agent / EnvHttpProxyAgent / fetch / Dispatcher). Smoke-tested
--help / doctor / list on Node v20.0.0, v21.2.0, v22.22.2. 213/213
targeted unit tests pass.
* feat(download): harden HTML→Markdown pipeline
Inspired by the MD-This-Page / markdown-viewer-extension analysis, tighten
the shared article→Markdown converter used by zhihu/weixin/web adapters:
- enable turndown-plugin-gfm (tables, strikethrough, task lists)
- strip script/style/noscript/iframe/canvas/form/button/dialog unconditionally
- strip SVG via a dedicated rule (not in HTMLElementTagNameMap)
- drop base64 data-URI images so they don't bloat .md output
- post-process: collapse NBSP, lone bullet/middle-dot residue,
trailing whitespace, and 3+ blank lines
- frontmatter shape guarantees ≤2 consecutive newlines even when
some metadata fields are absent
Adds a minimal local .d.ts for turndown-plugin-gfm and 6 new tests
covering GFM conversion, tag stripping, base64 drop, and whitespace cleanup.
* fix(download): emit canonical markdown strikethrough
* feat(download,browser): finish article pipeline polish
Per the follow-up from the MD-This-Page / markdown-viewer-extension
analysis, land the remaining items in the same PR instead of splitting:
article-download.ts
- extend STRIPPED_TAGS with header/footer/nav/aside (page chrome; the
article's title/author/publishTime are supplied as separate fields on
ArticleData, so duplicated DOM is redundant)
- new option ArticleDownloadOptions.cleanSelectors — per-adapter CSS
selector list removed before conversion, applied as a Turndown rule
via node.matches so invalid selectors fail silently
browser/article-extract.ts (new)
- generic Readability-based extraction that runs in-page via CDP
evaluate (no jsdom in Node)
- short-circuits non-HTML documents (text/plain, JSON, XML) and the
single-<pre> "browser rendering a plain text file" case
- clones the document before any mutation (preserves live page state
for subsequent snapshot / click)
- isProbablyReaderable gate, Readability.parse on the clone, then a
fallback chain main → [role="main"] → #main-content → … → body
- library sources are JSON-embedded and eval'd inside a Function scope
so their backticks / module.exports guards don't collide with the
surrounding IIFE
Tests
- article-download: page-chrome strip, cleanSelectors match + invalid
selector silently ignored (2 new)
- article-extract: JS generation contents, default fallback chain,
response normalization, null / malformed handling, and a Function()
parse check to catch any template-literal break-out in the embedded
Readability sources (8 new)
* fix(download): honor selector cleanup in fallback paths
* test(e2e): real-site regression for hardened article pipeline
Adds tests/e2e/article-download-pipeline.test.ts driving `opencli web read`
through 6 representative pages (example.com baseline, Wikipedia GFM tables,
MDN metadata, GitHub fenced code, Vercel SSR blog, Ruan Yifeng CJK+images)
and asserting the post-processing invariants: no base64/script/style leaks,
no blank-line runs, no residue, no trailing whitespace, no NBSP.
Graceful skip on bot detection / transient CDP errors, with a single retry.
All 6 sites pass locally (37s total).
* test(browser): add article extraction e2e fixtures
* fix: sync package-lock.json with package.json dependencies
package-lock.json was missing @emnapi/core@1.9.2 and
@emnapi/runtime@1.9.2 (transitive deps of @emnapi/wasi-threads),
causing `npm ci` to fail on all CI jobs.
* fix: resolve remaining CI failures after TS-to-JS adapter migration
- vitest.config.ts: update adapter project include/exclude from .test.ts
to .test.{ts,js} to match converted adapter test files
- check-doc-coverage.sh: skip adapter directories containing only utility
files (prefixed with _), fixing false positive for clis/slock/
- linux-do/topic-content.test.js: fix hardcoded reference to topic.ts
(now topic.js after PR #928 migration)
* refactor: simplify core modules — remove root shims, consolidate error classification, streamline cascade/interceptor, clean up synthesize
1. Remove root-level shim files (errors.ts, logger.ts, registry.ts, types.ts, utils.ts, launcher.ts) — update all ~840 adapter imports to reference src/ directly
2. Consolidate interceptor: reuse shared DISGUISE_FN in tap interceptor instead of reimplementing
3. Unify error classification: single ClassifiedError type with icon/exitCode/hint lookup table, eliminating duplicated pattern matching between resolveExitCode and renderError
4. Simplify cascade probe: replace repetitive switch cases with PROBE_OPTIONS lookup map
12. Clean up synthesize.ts: remove deprecated snake_case field aliases (recommended_args, recommended_columns, recommendedColumnsLegacy) and unnecessary constant aliases
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* docs: update import paths in contributor docs and skill templates
Update all documentation and skill files to reference src/ directly,
matching the shim removal in the previous commit.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: update new Gemini adapter imports to use src/ paths
Fix imports in newly added deep-research adapter files that were
still referencing the deleted root shim files.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: update xiaohongshu tests for /search_result/ URL change
Tests now expect /search_result/<id> for bare note IDs (matching
the note-helpers.ts change from PR #774) and updated empty-shell
hint assertion.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: update LessWrong and hupu adapter imports to use src/ paths
Fix imports in newly merged LessWrong and hupu/mentions adapter
files that were still referencing the deleted root shim files.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* test(xueqiu): mock logger via src path
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* 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>
* 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>