Skip to content

fix(ai): openrouter quota publishes a zero-limit window — $0.00 / $0.00 with null percent reads as headroom where there is no limit #1799

Closed

Description

@dezren39

Problem

OpenRouter quota publishes a window for a key whose limit is 0: usedPercent: null with the value label $0.00 / $0.00, and the result is ok: true. A zero limit is no quota figure at all — the window reads as a live (empty) quota where the key in fact has no limit/headroom surface. This is exactly the symptom the window contract and a sibling provider already dispositioned:

OpenRouter was not given the same disposition. The #1795 inventory lists OpenRouter's only known-lossy item as #1725 (unpinned resolveResetAt); the zero-limit case is not covered there.

Evidence (verified this run, main 5fd613e46d)

packages/ai/src/quota/providers/openrouter.ts:

  • :105-106 limit / limitRemaining parsed via toNumber.
  • :130-133 in the limited branch: used = Math.max(0, limit - limitRemaining), percent = limit > 0 ? (used / limit) * 100 : null — for limit === 0 the percent becomes null but the branch still builds a window.
  • :149-152 the window is published unconditionally under the reset-derived key.

Laptop probe (worktree of origin/main 5fd613e46d, driving provider.fetchQuota with a stubbed fetch, probe kept at ~/git/fleet/probe-2026-11-05-creator-2135/probe2.ts on the laptop):

  • {limit: 0, limit_remaining: 0, usage_monthly: 0, limit_reset: "monthly"} → ok: true, window monthly: { usedPercent: null, remainingPercent: null, valueLabel: "$0.00 / $0.00", windowSeconds: 2592000, resetAt: <next month> }
  • {limit: 0, limit_remaining: -5, usage_monthly: 5, limit_reset: "monthly"} → ok: true, window monthly: { usedPercent: null, valueLabel: "$5.00 / $0.00" } — spent money against a zero limit, still no percent and no error.
  • Controls behave: {limit: 100, limit_remaining: -20} → usedPercent: 100, label $120.00 / $100.00; {limit: 100, limit_remaining: 150} → usedPercent: 0, label $0.00 / $100.00.

Why it matters

The opencode quota listing and downstream consumers (aggregator/dashboard) treat an ok: true window as a real quota surface. A zero-limit key (revoked, unpaid, or a free key with no purchased limit) currently shows a plausible monthly window with a reset date instead of the no-data/error row its siblings produce, masking exactly the state a user checks quota to discover.

Acceptance criteria

Related: #1794 (window contract), #1725 (OpenRouter resolveResetAt pinning — separate), #1750 (OpenDesign zero-limit precedent).

Activity

  1. added
    kind/bugSomething isn't working (prefixed form of the classic bug label)
    task/triageQueue packet kind: verify, reproduce, and route this item
    source/creatorFiled by the new-issue-creator job
    priority/normalOrdinary priority (the default)
    queue/queuedHas a queued task in the Supabase agent queue
    app/aiPackage: ai (pkgs/ or apps/ in this repo)
    on Nov 6, 2026
  2. dezren39 commented on Nov 6, 2026

    @dezren39
    Author

    🤖 Agent note · state: filed

  3. added
    work/assignedAn agent holds this item via the queue (claimed task)
    queue/claimedA queue worker has claimed the task for this item
    and removed
    queue/queuedHas a queued task in the Supabase agent queue
    on Nov 6, 2026
  4. dezren39 commented on Nov 6, 2026

    @dezren39
    Author

    🤖 Agent note · picked up

  5. added a commit that references this issue on Nov 6, 2026
  6. removed
    queue/claimedA queue worker has claimed the task for this item
    work/assignedAn agent holds this item via the queue (claimed task)
    on Nov 6, 2026
  7. dezren39 commented on Nov 6, 2026

    @dezren39
    Author

    🤖 Agent note · state: done

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    app/aiPackage: ai (pkgs/ or apps/ in this repo)kind/bugSomething isn't working (prefixed form of the classic bug label)priority/normalOrdinary priority (the default)source/creatorFiled by the new-issue-creator jobtask/triageQueue packet kind: verify, reproduce, and route this item

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions