Skip to content

feat(umans): add Umans provider with request-based quota tracking#164

Closed
claw-io wants to merge 27 commits into
Mirrowel:devfrom
b3nw:feat/umans-provider-quota
Closed

feat(umans): add Umans provider with request-based quota tracking#164
claw-io wants to merge 27 commits into
Mirrowel:devfrom
b3nw:feat/umans-provider-quota

Conversation

@claw-io

@claw-io claw-io commented Jun 22, 2026

Copy link
Copy Markdown

Description

This PR adds first-class support for the Umans API () to the proxy.

  • New provider plugin with dynamic model discovery from .
  • Request-based sliding-window quota tracking via the new mixin, following the existing Chutes/API-key pattern.
  • Plan-aware behavior:
    • : 200 req / 5h soft limit, 400 hard cap, 3 concurrent sessions.
    • : no request limit, 4 concurrent sessions.
  • env var overrides the soft request limit only for credentials.
  • Request-quota exhaustion is display-only () until the burst-ceiling enforcement behavior is confirmed. API 429s still trigger cooldown through the standard error handler.

Files Changed

Verification

  • — passed
  • — passed
  • All checks passed! — passed
  • All checks passed! — passed
  • fork stack validation passed — passed
  • ============================= test session starts ==============================
    platform linux -- Python 3.13.5, pytest-9.1.1, pluggy-1.6.0 -- /opt/data/workspace/developer/repos/forks/b3nw/LLM-API-Key-Proxy/worktrees/feat-umans-provider-quota/.venv/bin/python3
    cachedir: .pytest_cache
    rootdir: /opt/data/workspace/developer/repos/forks/b3nw/LLM-API-Key-Proxy/worktrees/feat-umans-provider-quota
    configfile: pyproject.toml
    plugins: mock-3.15.1, anyio-4.13.0, asyncio-1.4.0
    asyncio: mode=Mode.AUTO, debug=False, asyncio_default_fixture_loop_scope=None, asyncio_default_test_loop_scope=function
    collecting ... collected 23 items

tests/test_umans_quota_tracker.py::test_get_credential_identifier_env_path PASSED [ 4%]
tests/test_umans_quota_tracker.py::test_get_credential_identifier_masks_long_key PASSED [ 8%]
tests/test_umans_quota_tracker.py::test_get_credential_identifier_short_key_unmasked PASSED [ 13%]
tests/test_umans_quota_tracker.py::test_parse_iso_to_unix_z PASSED [ 17%]
tests/test_umans_quota_tracker.py::test_detect_plan_code_pro_inferred PASSED [ 21%]
tests/test_umans_quota_tracker.py::test_detect_plan_code_pro_explicit PASSED [ 26%]
tests/test_umans_quota_tracker.py::test_detect_plan_max PASSED [ 30%]
tests/test_umans_quota_tracker.py::test_resolve_request_limit_code_pro PASSED [ 34%]
tests/test_umans_quota_tracker.py::test_resolve_request_limit_code_pro_no_limit PASSED [ 39%]
tests/test_umans_quota_tracker.py::test_resolve_request_limit_max PASSED [ 43%]
tests/test_umans_quota_tracker.py::test_resolve_request_limit_max_ignores_positive_env PASSED [ 47%]
tests/test_umans_quota_tracker.py::test_resolve_request_limit_code_pro_env_override PASSED [ 52%]
tests/test_umans_quota_tracker.py::test_parse_usage_response_code_pro PASSED [ 56%]
tests/test_umans_quota_tracker.py::test_parse_usage_response_max PASSED [ 60%]
tests/test_umans_quota_tracker.py::test_parse_usage_response_code_pro_env_override PASSED [ 65%]
tests/test_umans_quota_tracker.py::test_store_baselines_to_usage_manager PASSED [ 69%]
tests/test_umans_quota_tracker.py::test_store_baselines_skips_request_group_for_max_plan PASSED [ 73%]
tests/test_umans_quota_tracker.py::test_fetch_initial_baselines_mixed PASSED [ 78%]
tests/test_umans_quota_tracker.py::test_provider_get_model_quota_group PASSED [ 82%]
tests/test_umans_quota_tracker.py::test_provider_get_models_success PASSED [ 86%]
tests/test_umans_quota_tracker.py::test_provider_parse_quota_error_rate_limit PASSED [ 91%]
tests/test_umans_quota_tracker.py::test_provider_parse_quota_error_not_quota PASSED [ 95%]
tests/test_umans_quota_tracker.py::test_provider_get_credential_concurrency_limit_from_cache PASSED [100%]

============================== 23 passed in 3.05s ============================== — 23 passed

  • ........................................................................ [ 17%]
    ........................................................................ [ 35%]
    ........................................................................ [ 53%]
    ........................................................................ [ 71%]
    ........................................................................ [ 89%]
    .......................................... [100%]
    =============================== warnings summary ===============================
    tests/test_failure_logger.py: 10 warnings
    /opt/data/workspace/developer/repos/forks/b3nw/LLM-API-Key-Proxy/worktrees/feat-umans-provider-quota/src/rotator_library/failure_logger.py:226: DeprecationWarning: datetime.datetime.utcnow() is deprecated and scheduled for removal in a future version. Use timezone-aware objects to represent datetimes in UTC: datetime.datetime.now(datetime.UTC).
    "timestamp": datetime.utcnow().isoformat(),

-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
402 passed, 10 warnings in 4.06s — 402 passed

Notes / Follow-ups

  • Request-quota exhaustion is intentionally display-only pending confirmation of the 400-request hard-cap behavior. Once observed, we can switch at the soft limit or use to target the burst ceiling.
  • The Anthropic-compatible endpoint is not explicitly routed in this PR; requests currently flow through the standard OpenAI-compatible path.

b3nw added 27 commits June 19, 2026 01:52
…a cleanup

- Native Anthropic endpoint routing for Claude models via NanoGPT
- Anthropic format converters for OpenAI<->Anthropic message translation
- Fix streaming fallback: convert static ModelResponse to fake stream
- Fix stream parameter handling to prevent duplicate arguments
- Remove obsolete monthly quota group from NanoGPT provider
- Add embedding routing support in executor
- Clean up _anthropic_payload from kwargs before LiteLLM calls
Custom provider for Google Vertex AI Express Mode API keys that uses
x-goog-api-key header authentication against the Vertex AI
OpenAI-compatible endpoint. Supports non-streaming and streaming
chat completions with automatic model discovery.

Models are prefixed as vertex/ (e.g. vertex/gemini-3.1-flash-lite-preview).
Env vars: VERTEX_PROJECT, VERTEX_LOCATION, VERTEX_API_KEY_N
Track KiloCode credit balance through the Kilo web dashboard
session cookie. Fetches /api/user on a background interval and
surfaces the balance as credits($) in the TUI. The session token
is auto-refreshed on each poll via /api/auth/session.
…ased model filtering, and enhanced X-Initiator heuristic
…ardization, and utilities

Core infrastructure improvements:
- Smart 'latest' model alias resolution with cost-based tiebreaking
- Standardized error responses with proper HTTP status codes and error.code field
- ProxyExhaustionError for structured credential exhaustion reporting
- TerminalRequestError for non-rotatable errors (404, model not found)
- Per-provider retry count override via MAX_RETRIES_{PROVIDER} env var
- Retry 429 rate_limit errors with backoff instead of rotating
- Cached token pricing in streaming cost calculation
- Split quota stats into current_period and global/lifetime views
- Log rotation for proxy.log and proxy_debug.log (RotatingFileHandler)
- Include latest virtual models in /v1/models endpoint
- Resolve singleton cache pollution for dynamic providers
- Fork-specific README and .gitignore updates
…dential routing

Add configurable proxy routing for outbound LLM API traffic.

ProxyConfig supports:
- Global default proxy (PROXY_URL_DEFAULT)
- Per-provider proxies (PROXY_URL_<PROVIDER>)
- Per-credential proxies (PROXY_URL_CREDENTIAL_<STABLE_ID>)
- Rotation pool with round-robin/random strategy
- JSON file config (PROXY_CONFIG_PATH) for complex setups

Resolution priority: per-credential > per-provider > rotation > global > direct.

Supports http, https, socks5, socks5h, and socks4 schemes.
Prefers socks5h:// (remote DNS) over socks5:// (local DNS) to avoid
resolution failures in containerized environments.

ProxiedClientPool manages httpx.AsyncClient instances per proxy URL.
LiteLLM integration uses openai.AsyncOpenAI with proxied http_client
to satisfy internal OpenAI-compatible code paths.

Requires: socksio (added to requirements.txt)
Add two new per-credential quota systems integrated into the limit
engine pipeline, with full UI support in TUI and WebUI:

Monthly Budget: env-driven spending cap (MONTHLY_BUDGET_{PROVIDER}=N)
that blocks credentials once cumulative cost exceeds the budget.
Resets on a configurable day of the month.

RPD (Requests Per Day): env-driven per-model daily request caps
(RPD_LIMIT_{PROVIDER}_{MODEL}=N) with alias support
(RPD_ALIAS_{PROVIDER}_{ALIAS}=canonical) for latest-model name
resolution. Counters reset at midnight in the configured timezone.

Both features are opt-in via environment variables with no hardcoded
defaults. Status is exposed in /v1/quota-stats and rendered in the
TUI summary/detail views and WebUI credential cards.
…flow

Replaces the old manifest-driven multi-branch replay system with a
simpler linear commit stack. Changes are made via fixup!/autosquash.
Upstream syncs are a single git rebase.

Includes:
- AGENTS.md: entry point for all AI coding agents
- .agent/rules/claude.md: Claude-specific SSH/deployment notes
- .agent/rules/llm-proxy.md: container layout and deployment pipeline
- .agent/skills/upstream-sync/SKILL.md: sync workflow reference
… explorer, and settings

Replace TUI with a React/TypeScript/Tailwind web interface served from FastAPI.

Backend: new admin API routers for /v1/admin/transactions, /v1/admin/failures,
/v1/admin/config, /v1/admin/credentials, /v1/admin/oauth/providers, and a
/v1/ws WebSocket endpoint for real-time quota/error updates. Static file
serving under /ui with SPA fallback.

Frontend: Vite + React 19 + Tailwind v4 + shadcn-style components.
Pages: Dashboard (health, providers, errors), Quota (per-provider/credential
drill-down with progress bars), Log Explorer (transactions + failures with
JSON viewer), Credentials (API key + OAuth management), Models (searchable
catalog), Settings (config, filters, aliases, custom providers).

Auth via Bearer token stored in localStorage with remote proxy URL support.
Multi-stage Dockerfile adds Node build stage for the webui dist.
- Switch git-cliff range from $LAST_TAG..HEAD to upstream/dev..HEAD
- Add incremental diff step comparing fork_state markers between releases
- Embed state markers in release body for next build consumption
- Add upstream sync reference line to release notes
- Drop broken tag-hunting logic (~90 lines) that relied on orphaned tags
- Add Release Notes subsection and Rule 8 to AGENTS.md
- xai_auth_base.py: OAuth2 base class inheriting from OpenAIOAuthBase
  - PKCE Authorization Code flow with loopback redirect (127.0.0.1:56121)
  - Device Code flow for headless environments
  - Auto-selects Device Code in headless, offers choice in interactive
  - Uses xAI public client ID (b1a00492-073a-47ea-816f-4c329264a828)
  - Scopes: openid, offline_access, grok-cli:access

- xai_provider.py: ProviderInterface implementation
  - Routes through LiteLLM's native xai/ prefix
  - Resolves OAuth credential files to bearer tokens
  - Live model discovery from https://api.x.ai/v1/models
  - Supports acompletion and aembedding

- Register xai in provider_factory, credential_manager, credential_tool
…ken counts

- Add gemini-3.5-flash to AVAILABLE_MODELS (maps to gemini-3-flash via CCPA)
- Fix is_gemini_3_flash check so 3.5-flash uses thinkingLevel (not thinkingBudget)
- Merge 25-flash + 3-flash into single "flash" quota group (verified via
  matching reset timestamps on live quota API)
- Unify flash-lite models (2.5 + 3.1) into single "flash-lite" quota group
- Add gemini-3.5-flash to DEFAULT_MAX_REQUESTS for PRO/FREE tiers
- Filter stale quota groups from usage manager to prevent display of
  renamed/merged groups in quota UI
- Fix streaming token counts: the final SSE chunk carrying usageMetadata
  often contains only a thoughtSignature (empty text), causing all parts
  to be skipped and token counts to be lost (reported as 0/0 in logs).
  Emit a usage-only chunk when no parts yield content but usageMetadata
  is present.
Add x-ai to the proxy's admin OAuth API so the WebUI Credentials page
can onboard xAI Grok accounts via the device-code flow.

src/proxy_app/api/oauth.py:
- Add 'x-ai' to PROVIDER_META with flow_type=device_code.
- Add dispatcher branch in start_oauth_flow for 'x-ai'.
- Implement _start_xai_device_flow, _poll_xai_device, and _finalize_xai
  parallel to the copilot device-code path. Reuses XAI_CLIENT_ID,
  XAI_OAUTH_SCOPES, XAI_DEVICE_CODE_URL, XAI_TOKEN_URL, and
  XAI_USERINFO_URL from XAiAuthBase — no constant duplication.
- Persists credentials via the existing _save_credential_file helper
  with the exact shape XAiAuthBase's loader expects (access_token,
  refresh_token, expiry_date, account_id, _proxy_metadata).

No frontend changes. The existing Credentials.tsx dialog already
handles flow_type=device_code generically (user_code, verification_uri,
polling, copy-to-clipboard) — adding the provider to PROVIDER_META is
sufficient to surface it in the 'Add OAuth' dialog.

tests/test_xai_oauth_flow.py: 6 test cases covering the providers
list, the start envelope (with upstream mock), the unknown-provider
regression, the status endpoint, and the credential-file prefix.
Un-ignore via .gitignore per the established pattern for tracked
test files in this repo.
- Switch git-cliff range from $LAST_TAG..HEAD to upstream/dev..HEAD
- Add incremental diff step comparing fork_state markers between releases
- Embed state markers in release body for next build consumption
- Add upstream sync reference line to release notes
- Drop broken tag-hunting logic (~90 lines) that relied on orphaned tags
- Add Release Notes subsection and Rule 8 to AGENTS.md
@claw-io claw-io requested a review from Mirrowel as a code owner June 22, 2026 01:35
@greptile-apps

greptile-apps Bot commented Jun 22, 2026

Copy link
Copy Markdown

Too many files changed for review. (200 files found, 100 file limit)

@coderabbitai

coderabbitai Bot commented Jun 22, 2026

Copy link
Copy Markdown

Important

Review skipped

Too many files!

This PR contains 194 files, which is 44 over the limit of 150.

To get a review, narrow the scope:
• coderabbit review --type committed # exclude uncommitted changes
• coderabbit review --dir # limit to a subdirectory
• coderabbit review --base # compare against a closer base

Upgrade to a paid plan to raise the limit.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 21a10ebc-110a-46d8-aece-0907b37157fd

📥 Commits

Reviewing files that changed from the base of the PR and between e85e5f6 and 0671009.

⛔ Files ignored due to path filters (6)
  • uv.lock is excluded by !**/*.lock
  • webui/package-lock.json is excluded by !**/package-lock.json
  • webui/public/favicon-dark.svg is excluded by !**/*.svg
  • webui/public/favicon.svg is excluded by !**/*.svg
  • webui/public/icons.svg is excluded by !**/*.svg
  • webui/src/assets/hero.png is excluded by !**/*.png
📒 Files selected for processing (194)
  • .antigravitycli/22148748-73e2-4bca-aff2-c0bfb511dd11.json
  • .dockerignore
  • .env.example
  • .fork/check-stack.py
  • .fork/features/ci.md
  • .fork/features/codex.md
  • .fork/features/gemini-cli.md
  • .fork/features/tooling.md
  • .fork/features/umans.md
  • .fork/features/xai.md
  • .fork/stack.yml
  • .github/workflows/build.yml
  • .github/workflows/docker-build.yml
  • .gitignore
  • AGENTS.md
  • Dockerfile
  • README.md
  • STRUCTURE.md
  • pyproject.toml
  • requirements.txt
  • scratch/inspect_registry.py
  • scratch/test_gitlawb.py
  • scratch/test_gitlawb_debug.py
  • scratch/test_litellm_url.py
  • scripts/cleanup-logs.sh
  • scripts/create_release.sh
  • src/proxy_app/api/__init__.py
  • src/proxy_app/api/config.py
  • src/proxy_app/api/logs.py
  • src/proxy_app/api/oauth.py
  • src/proxy_app/launcher_tui.py
  • src/proxy_app/log_viewer.py
  • src/proxy_app/main.py
  • src/proxy_app/provider_urls.py
  • src/proxy_app/quota_viewer.py
  • src/proxy_app/responses_compat.py
  • src/proxy_app/settings_tool.py
  • src/rotator_library/anthropic_compat/streaming.py
  • src/rotator_library/client/anthropic.py
  • src/rotator_library/client/cross_provider_executor.py
  • src/rotator_library/client/executor.py
  • src/rotator_library/client/models.py
  • src/rotator_library/client/request_builder.py
  • src/rotator_library/client/rotating_client.py
  • src/rotator_library/client/streaming.py
  • src/rotator_library/client/transforms.py
  • src/rotator_library/client/types.py
  • src/rotator_library/config/__init__.py
  • src/rotator_library/config/defaults.py
  • src/rotator_library/core/constants.py
  • src/rotator_library/core/errors.py
  • src/rotator_library/core/types.py
  • src/rotator_library/core/utils.py
  • src/rotator_library/credential_manager.py
  • src/rotator_library/credential_tool.py
  • src/rotator_library/error_handler.py
  • src/rotator_library/error_tracker.py
  • src/rotator_library/failure_logger.py
  • src/rotator_library/litellm_providers.py
  • src/rotator_library/model_alias_registry.py
  • src/rotator_library/model_fallback_registry.py
  • src/rotator_library/model_info_service.py
  • src/rotator_library/model_latest_registry.py
  • src/rotator_library/provider_config.py
  • src/rotator_library/provider_factory.py
  • src/rotator_library/providers/__init__.py
  • src/rotator_library/providers/anthropic_oauth_base.py
  • src/rotator_library/providers/anthropic_provider.py
  • src/rotator_library/providers/chutes_provider.py
  • src/rotator_library/providers/codex_prompt.txt
  • src/rotator_library/providers/codex_provider.py
  • src/rotator_library/providers/command_provider.py
  • src/rotator_library/providers/copilot_auth_base.py
  • src/rotator_library/providers/copilot_plan_mapping.py
  • src/rotator_library/providers/copilot_provider.py
  • src/rotator_library/providers/gemini_auth_base.py
  • src/rotator_library/providers/gemini_cli_provider.py
  • src/rotator_library/providers/gemini_provider.py
  • src/rotator_library/providers/kilo_provider.py
  • src/rotator_library/providers/nanogpt_provider.py
  • src/rotator_library/providers/openai_oauth_base.py
  • src/rotator_library/providers/opencode_go_provider.py
  • src/rotator_library/providers/opencode_zen_provider.py
  • src/rotator_library/providers/provider_interface.py
  • src/rotator_library/providers/umans_provider.py
  • src/rotator_library/providers/utilities/__init__.py
  • src/rotator_library/providers/utilities/anthropic_converters.py
  • src/rotator_library/providers/utilities/anthropic_quota_tracker.py
  • src/rotator_library/providers/utilities/base_quota_tracker.py
  • src/rotator_library/providers/utilities/chutes_quota_tracker.py
  • src/rotator_library/providers/utilities/codex_quota_tracker.py
  • src/rotator_library/providers/utilities/codex_ws_transport.py
  • src/rotator_library/providers/utilities/copilot_quota_tracker.py
  • src/rotator_library/providers/utilities/gemini_cli_quota_tracker.py
  • src/rotator_library/providers/utilities/gemini_credential_manager.py
  • src/rotator_library/providers/utilities/gemini_quota_utils.py
  • src/rotator_library/providers/utilities/gemini_shared_utils.py
  • src/rotator_library/providers/utilities/kilo_quota_tracker.py
  • src/rotator_library/providers/utilities/nanogpt_quota_tracker.py
  • src/rotator_library/providers/utilities/opencode_quota_tracker.py
  • src/rotator_library/providers/utilities/umans_quota_tracker.py
  • src/rotator_library/providers/utilities/x_ai_quota_tracker.py
  • src/rotator_library/providers/vertex_provider.py
  • src/rotator_library/providers/x_ai_auth_base.py
  • src/rotator_library/providers/x_ai_provider.py
  • src/rotator_library/proxy_config.py
  • src/rotator_library/request_sanitizer.py
  • src/rotator_library/transaction_logger.py
  • src/rotator_library/usage/config.py
  • src/rotator_library/usage/identity/registry.py
  • src/rotator_library/usage/limits/engine.py
  • src/rotator_library/usage/limits/monthly_budget.py
  • src/rotator_library/usage/limits/rpd_limit.py
  • src/rotator_library/usage/manager.py
  • src/rotator_library/usage/persistence/storage.py
  • src/rotator_library/usage/types.py
  • src/rotator_library/utils/paths.py
  • tests/README.md
  • tests/conftest.py
  • tests/rotator_library/test_litellm_providers.py
  • tests/rotator_library/test_vertex_provider.py
  • tests/test_anthropic_compat_e2e.py
  • tests/test_anthropic_streaming.py
  • tests/test_anthropic_translator.py
  • tests/test_credential_manager.py
  • tests/test_error_handler.py
  • tests/test_error_tracker.py
  • tests/test_failure_logger.py
  • tests/test_headless_detection.py
  • tests/test_model_alias.py
  • tests/test_model_fallback.py
  • tests/test_model_filters.py
  • tests/test_provider_config.py
  • tests/test_provider_plugins.py
  • tests/test_provider_transforms.py
  • tests/test_proxy_endpoints.py
  • tests/test_request_sanitizer.py
  • tests/test_resilient_io.py
  • tests/test_timeout_config.py
  • tests/test_umans_quota_tracker.py
  • tests/test_usage_reconciliation.py
  • tests/test_usage_tracking.py
  • tests/test_usage_window_modes.py
  • tests/test_x_ai_quota_tracker.py
  • tests/test_xai_oauth_flow.py
  • tests/utils/__init__.py
  • tests/utils/test_paths.py
  • tests/utils/test_resilient_io.py
  • webui/.gitignore
  • webui/README.md
  • webui/eslint.config.js
  • webui/index.html
  • webui/package.json
  • webui/src/App.tsx
  • webui/src/api/client.ts
  • webui/src/api/config.ts
  • webui/src/api/health.ts
  • webui/src/api/logs.ts
  • webui/src/api/models.ts
  • webui/src/api/oauth.ts
  • webui/src/api/quota.ts
  • webui/src/api/websocket.ts
  • webui/src/components/ErrorBoundary.tsx
  • webui/src/components/LoginForm.tsx
  • webui/src/components/layout/Header.tsx
  • webui/src/components/layout/Shell.tsx
  • webui/src/components/layout/Sidebar.tsx
  • webui/src/components/ui/badge.tsx
  • webui/src/components/ui/button.tsx
  • webui/src/components/ui/card.tsx
  • webui/src/components/ui/dialog.tsx
  • webui/src/components/ui/input.tsx
  • webui/src/components/ui/progress.tsx
  • webui/src/components/ui/select.tsx
  • webui/src/components/ui/table.tsx
  • webui/src/components/ui/tabs.tsx
  • webui/src/hooks/useAuth.ts
  • webui/src/hooks/usePolling.ts
  • webui/src/hooks/useWebSocket.ts
  • webui/src/index.css
  • webui/src/lib/navigation.ts
  • webui/src/lib/utils.ts
  • webui/src/lib/utils.xai-quota.test.ts
  • webui/src/main.tsx
  • webui/src/pages/Credentials.tsx
  • webui/src/pages/Dashboard.tsx
  • webui/src/pages/Logs.tsx
  • webui/src/pages/Models.tsx
  • webui/src/pages/Quota.tsx
  • webui/src/pages/Settings.tsx
  • webui/tsconfig.app.json
  • webui/tsconfig.json
  • webui/tsconfig.node.json
  • webui/vite.config.ts

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@claw-io

claw-io commented Jun 22, 2026

Copy link
Copy Markdown
Author

Opened against wrong repo by automation; will recreate in the b3nw fork.

@claw-io claw-io closed this Jun 22, 2026
@mirrobot-agent

Copy link
Copy Markdown
Contributor

Starting my review of the Umans provider addition — focusing on the quota tracker mixin, provider integration, and test coverage. I'll also scan the broader diff for repo-hygiene issues since it includes the full fork stack. Report coming shortly.

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.

2 participants