Skip to content

Conversation

@albu
Copy link

@albu albu commented Dec 28, 2025

Problem

When using LLM providers with quota limits (like zai-coding-plan), users have no visibility into their remaining quota or when it resets. This makes it difficult to track usage and avoid unexpected service interruptions.

Solution

Added plan usage display to the TUI sidebar that shows:

  • Current usage percentage (e.g., "65% used")
  • Time until quota resets (e.g., "Resets in 2h 15m")

Implementation

Core abstraction (src/provider/plan-usage.ts)

Generic PlanUsage interface that all providers implement:

export interface PlanUsage {
  used: number
  total: number
  resetAt?: Date
  percentage?: number  // Provider-supplied percentage if more accurate
}

Features:

  • Registry pattern - Provider handlers register themselves via registerProvider(id, handler)
  • Built-in caching - 60s TTL to avoid excessive API calls
  • Helpers - getPercentage(), formatResetTime()

Provider implementation (src/provider/plan-usage/zai.ts)

  • Fetches quota from /api/monitor/usage/quota/limit endpoint
  • Handles zai-specific response format with multiple limit types
  • Only displays TOKENS_LIMIT (ignores time-based limits)
  • Registers itself as zai-coding-plan handler

UI integration (sidebar.tsx)

  • Shows plan usage in session sidebar below context info
  • Auto-refreshes when new messages are exchanged (user or assistant)

Adding support for other providers

The pattern uses side-effect imports. The core module imports provider modules, which register themselves on load.

Step 1: Add import to src/provider/plan-usage.ts:

// Load built-in providers
import("./plan-usage/zai")
import("./plan-usage/your-provider")  // ← Add this

Step 2: Create src/provider/plan-usage/your-provider.ts:

import { registerProvider, type PlanUsageHandler } from "../plan-usage"

const handler: PlanUsageHandler = async ({ token, baseURL, timeout }) => {
  const response = await fetch(`${baseURL}/your-endpoint`, {
    headers: { Authorization: token },
    signal: AbortSignal.timeout(timeout)
  })

  if (!response.ok) {
    return { error: `HTTP ${response.status}` }
  }

  const data = await response.json()
  return {
    planUsage: {
      used: data.used,
      total: data.limit,
      resetAt: new Date(data.resetsAt),
    }
  }
}

registerProvider("your-provider-id", handler)  // ← Executes on import

The handler receives:

  • token - API key from auth
  • baseURL - Provider's base URL from config
  • timeout - Request timeout in ms (default 5000)

And returns:

{ planUsage: PlanUsage } | { error: string }

phj1081 added a commit to phj1081/opencode that referenced this pull request Jan 5, 2026
…idebar

- Add usage/anthropic.ts: fetch usage from Anthropic OAuth API
- Add usage/openai.ts: fetch usage from OpenAI/ChatGPT backend API
- Update dialog-status.tsx: show usage bars with reset times
- Update sidebar.tsx: show compact usage display with progress bars

Shows rate limit utilization percentages and reset times for:
- Anthropic: 5-hour and 7-day windows
- OpenAI: primary/secondary windows with plan type and credits

Related to anomalyco#6298 (plan usage tracking)
CasualDeveloper pushed a commit to CasualDeveloper/opencode that referenced this pull request Jan 16, 2026
…idebar

- Add usage/anthropic.ts: fetch usage from Anthropic OAuth API
- Add usage/openai.ts: fetch usage from OpenAI/ChatGPT backend API
- Update dialog-status.tsx: show usage bars with reset times
- Update sidebar.tsx: show compact usage display with progress bars
- Add negative time handling in formatResetTime (return 'refreshing')
- Add clamp for percent values in usage bars (0-100)
- Add 10s timeout to fetch calls (AbortSignal.timeout)
- Add NaN handling in formatCredits
- Extract shared utils (getUsageColor, clampPercent, usageBarString)
- Add refetch on message change for sidebar usage display
- Remove unused refetch destructuring in dialog-status
- Resolve infinite recursion in colorFor function
- Correct function name to getUsageColor in dialog-status

Shows rate limit utilization percentages and reset times for:
- Anthropic: 5-hour and 7-day windows
- OpenAI: primary/secondary windows with plan type and credits

Related to anomalyco#6298 (plan usage tracking)
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