jackwener / jackwener/OpenCLI

feat(xiaohongshu): session-level velocity throttling to prevent cumulative risk-control blocks

Open
#2,208 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
JavaScript
Stars
29.3k
Forks
2.9k
Avg merge
15h 36m
Merged PRs (30d)
70

Description

### Context

Reading Xiaohongshu note-detail pages (`note` / `comments` / `download`) in a run trips XHS's **velocity-based** risk control — the soft block that redirects to `website-login/error?error_code=300017`/`300031` or renders `安全限制` / `访问链接异常` (#1825, #962), and repeated hammering escalates toward account-violation / ban (#842, #677).

#2207 (just opened) is the per-command half of this: it retries once through a cooldown on a soft block and never hammers. But it deliberately does **not** cap request velocity **across separate CLI invocations** — each `opencli xiaohongshu note …` is a fresh process, so a scripted loop over dozens of notes still hits detail pages back-to-back and trips the cumulative threshold. This issue is to align on the design for that second half before I build it, since it touches the daemon/session layer rather than a single adapter.

### The gap

- Per-command jitter/backoff (in #2207) makes each read gentler and recovers transient blocks.
- What's missing is a notion of *"how many detail pages have I hit recently"* that survives across invocations, plus a way to **stop** after a confirmed block instead of letting an unattended script keep hammering (which is what turns a soft block into a ban).

### Proposed shape (want your read before implementing)

The daemon is already a long-lived process holding per-context in-memory state (`SessionLeaseHolder` map in `session-lease.ts`), so it looks like the natural home for a per-site throttle:

1. **Velocity limiter** — before a `note`/`comments`/`download` navigation, consult a per-site (per-contextId) rolling window of recent detail-request timestamps; enforce a minimum spacing + a rolling-window cap (e.g. ≤ N detail reads / minute), sleeping if needed.
2. **Cooldown gate** — when any XHS detail command surfaces `SECURITY_BLOCK`, record a cooldown timestamp; detail commands within the cooldown window fail fast (`SECURITY_BLOCK` with "in cooldown until …") instead of re-hitting the hot endpoint.

### Open questions (your call on the contract)

1. **State location** — daemon in-memory (alongside the session leases) vs a small state file for non-daemon / ephemeral runs? Or in-memory only, accepting that a cold process starts with an empty window?
2. **Generic vs XHS-specific** — should this be a reusable per-site throttle other high-risk adapters can opt into, or kept inside `clis/xiaohongshu/`?
3. **Opt-in surface** — always on for XHS, or behind a flag / env (e.g. `--pace` / `OPENCLI_XHS_PACE`) so power users can tune or disable it?
4. **Default limits** — I'd start conservative (e.g. min spacing 3–6s, ≤ 12 detail reads/min, cooldown a few minutes) and make them tunable.

Happy to implement whichever shape you prefer — flagging the design first because it reaches into the daemon/session layer. Related: #2207, #1825, #962, #842, #677.

Contributor guide

Open the contributing guide

Research direction

The relevant state is described as the SessionLeaseHolder map in session-lease.ts, with XHS entry points under clis/xiaohongshu/ for note, comments, and download. Start by reading those paths and #2207, then settle the state location, scope, opt-in contract, and limits; done means the design is agreed before implementation.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
backend, cli
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Needs clarification
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.