feat(client): rate limit guidance and backoff-aware retries - #43
Merged
Conversation
Document the per-endpoint limits, the 429 shape and the local-draft save pattern, and add a hard rule against autosaving to the platform on every change. Expose RequestError.retryAfter, back off between retries with jitter, honour Retry-After, and stop retrying 4xx that cannot succeed.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
feat(client): rate limit guidance and backoff-aware retries
Why
A user (Jack Gray) hit sustained
429s last week. The cause was an assistant that builtautosave-to-the-server into his app without telling him — a write per change, against an
endpoint capped at 30 writes/minute. His feedback: our LLM prep documents never mention
rate limits or an alternative, and our errors don't say what the limit was.
Nothing in this package told anyone otherwise:
resources/AGENTS.mdhad a single hard rule(UI must be Lit), and no doc anywhere carried a limit number.
What changed
Docs
docs/rate-limits.md: per-endpoint limits, what a429looks like, the local-draftsave pattern, and retry guidance. Numbers copied from the
@Throttledecorators inplatform_backend-api.resources/AGENTS.md: new hard rule Add new methods to the backend library to make the platform builderless #1 — never write to the platform on every change;drafts live in
localStorage/ IndexedDB, the platform gets an explicit save. Added thedoc to the session-start index table.
docs/ai-quickstart.md: same rule in the assistant rules list.CLAUDE.md: where the numbers come from and that they go stale silently.Client
RequestError.retryAfter— seconds to wait, read from theRetry-Afterheader, fallingback to
details.retryAfterin the body (survives proxies that strip headers).Retry-Afterwhen the server sends one.429and5xxare retried. Previously every failure wasretried immediately with no delay, so a client configured with retries turned a rate
limit into a burst against the same endpoint, and repeated 401/404s that could never
succeed.
retries: 0), so this only changes behaviour for callers whoopted in.
Pairs with
platform_backend-apiPR — structured429body (code: 'RATE_LIMITED', limit, window,retryAfter). The client reads it, but degrades fine against the current generic body.
Testing
npx vitest run— 96 passed, including 8 new retry-policy tests (no retry on 4xx, retryon 429/5xx/network, waits for
Retry-After, gives up after N, exposesretryAfter).npx eslint src/andnpx tsc --noEmitclean.src/core/examples/were not run — they need real credentials insrc/core/examples/.env, which isn't set up here. No example calls changed shape.