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
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:
- 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.
- 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)
- 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?
- Generic vs XHS-specific — should this be a reusable per-site throttle other high-risk adapters can opt into, or kept inside
clis/xiaohongshu/?
- 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?
- 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.
Context
Reading Xiaohongshu note-detail pages (
note/comments/download) in a run trips XHS's velocity-based risk control — the soft block that redirects towebsite-login/error?error_code=300017/300031or 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
Proposed shape (want your read before implementing)
The daemon is already a long-lived process holding per-context in-memory state (
SessionLeaseHoldermap insession-lease.ts), so it looks like the natural home for a per-site throttle:note/comments/downloadnavigation, 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.SECURITY_BLOCK, record a cooldown timestamp; detail commands within the cooldown window fail fast (SECURITY_BLOCKwith "in cooldown until …") instead of re-hitting the hot endpoint.Open questions (your call on the contract)
clis/xiaohongshu/?--pace/OPENCLI_XHS_PACE) so power users can tune or disable it?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.