Skip to content

feat(api-usage): adds rate limit insights and usage tracking#58

Merged
wgordon17 merged 14 commits intogordon-code:mainfrom
wgordon17:worktree-feat+rate-limit-insights
Apr 8, 2026
Merged

feat(api-usage): adds rate limit insights and usage tracking#58
wgordon17 merged 14 commits intogordon-code:mainfrom
wgordon17:worktree-feat+rate-limit-insights

Conversation

@wgordon17
Copy link
Copy Markdown
Member

Summary

  • Adds API usage tracking via Octokit request hook with per-source call counts displayed in Settings
  • Adds rate limit tooltip on dashboard showing core/GraphQL remaining counts and reset time
  • Unifies reset time display on GraphQL pool consistently across tooltip and settings

wgordon17 added 14 commits April 7, 2026 19:54
Replaces 15 manual trackApiCall() calls and 8 updateResetAt() calls
with a single hook.wrap("request", ...) on the Octokit client. New API
calls are tracked automatically with zero manual instrumentation.

- Adds ApiRequestInfo interface and onApiRequest() callback to github.ts
- Adds hook.wrap("request", ...) to createGitHubClient() for automatic
  tracking, rate limit header extraction, and error path coverage
- Adds deriveSource() URL pattern matching in api-usage.ts to auto-detect
  REST source labels from URL patterns
- Passes apiSource metadata on GraphQL calls for display labels
- Removes all trackApiCall/updateResetAt calls from api.ts, poll.ts,
  and DashboardPage.tsx
- Removes fromCache from fetchRateLimitDetails return type
- Adds "graphql" and "rest" fallback source types for untagged calls
@octokit/graphql treats unknown top-level options as GraphQL variables,
burying apiSource in the request body where the hook cannot read it.
Passes apiSource through the `request` option instead, which is in
NON_VARIABLE_OPTIONS and preserved in parsed request options.
Adds 7 tests covering the Octokit hook.wrap tracking pipeline:
- Success path callback with correct ApiRequestInfo fields
- GraphQL isGraphql detection
- apiSource extraction from request metadata (the @octokit/graphql path)
- resetEpochMs null when header absent
- Error path callback with status code and response headers
- Network failure normalized to status 500 by Octokit
- Callback error swallowing (does not propagate to caller)

Also extracts x-ratelimit-reset from RequestError.response.headers on
error paths instead of unconditionally setting resetEpochMs to null.
- Derives ApiCallSource/ApiPool types from const arrays (single source of truth)
- Uses z.enum() in Zod schemas, removing unsafe type cast
- Validates apiSource in deriveSource to prevent invalid strings reaching storage
- Moves SOURCE_LABELS to api-usage.ts with Record<ApiCallSource, string> exhaustiveness
- Inlines checkAndResetIfExpired to single localStorage write
- Removes _requestCallbacks.length guard (always populated by api-usage.ts)
- Includes REST reset times in updateResetAt via Math.max
- Replaces positional callback capture with invoke-all-callbacks pattern
- Adds tests for guard conditions, multi-client callbacks, read-only guard,
  quota errors, null client path, and hermetic staleness cache
@wgordon17 wgordon17 force-pushed the worktree-feat+rate-limit-insights branch from 10e978c to 47e3c55 Compare April 8, 2026 00:16
@wgordon17 wgordon17 merged commit 1619daf into gordon-code:main Apr 8, 2026
1 check passed
@wgordon17 wgordon17 deleted the worktree-feat+rate-limit-insights branch April 8, 2026 17:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant