feat: implement provider credit tracking and balance management

- Added 'credit_balance' and 'low_credit_threshold' to 'provider_configs' table.
- Updated dashboard backend to support reading and updating provider credits.
- Implemented real-time credit deduction from provider balances on successful requests.
- Added visual balance indicators and configuration modal to the 'Providers' dashboard tab.
This commit is contained in:
2026-02-26 18:25:39 -05:00
parent 9b254d50ea
commit efb50737bf
4 changed files with 64 additions and 10 deletions

View File

@@ -43,6 +43,10 @@ class ProvidersPage {
const statusClass = provider.status === 'online' ? 'success' : 'warning';
const modelCount = provider.models ? provider.models.length : 0;
// Credit balance display logic
const isLowBalance = provider.credit_balance <= provider.low_credit_threshold && provider.id !== 'ollama';
const balanceColor = isLowBalance ? 'var(--red-light)' : 'var(--green-light)';
return `
<div class="provider-card ${provider.status}">
<div class="provider-card-header">
@@ -61,6 +65,11 @@ class ProvidersPage {
<i class="fas fa-microchip"></i>
<span>${modelCount} Models Available</span>
</div>
<div class="meta-item" style="color: ${balanceColor}; font-weight: 700;">
<i class="fas fa-wallet"></i>
<span>Balance: ${provider.id === 'ollama' ? 'FREE' : window.api.formatCurrency(provider.credit_balance)}</span>
${isLowBalance ? '<i class="fas fa-exclamation-triangle" title="Low Balance"></i>' : ''}
</div>
<div class="meta-item">
<i class="fas fa-clock"></i>
<span>Last used: ${provider.last_used ? window.api.formatTimeAgo(provider.last_used) : 'Never'}</span>
@@ -146,12 +155,21 @@ class ProvidersPage {
</div>
<div class="form-control">
<label for="provider-base-url">Base URL</label>
<input type="text" id="provider-base-url" value="${provider.base_url || ''}" placeholder="Default: ${provider.id === 'ollama' ? 'http://localhost:11434/v1' : 'Standard API URL'}">
<input type="text" id="provider-base-url" value="${provider.base_url || ''}" placeholder="Default API URL">
</div>
<div class="form-control">
<label for="provider-api-key">API Key (Optional / Overwrite)</label>
<input type="password" id="provider-api-key" placeholder="••••••••••••••••">
<small>Leave blank to keep existing key from .env or config.toml</small>
</div>
<div class="grid-2">
<div class="form-control">
<label for="provider-balance">Current Credit Balance ($)</label>
<input type="number" id="provider-balance" value="${provider.credit_balance}" step="0.01">
</div>
<div class="form-control">
<label for="provider-threshold">Low Balance Alert ($)</label>
<input type="number" id="provider-threshold" value="${provider.low_credit_threshold}" step="0.50">
</div>
</div>
</div>
<div class="modal-footer">
@@ -167,12 +185,16 @@ class ProvidersPage {
const enabled = modal.querySelector('#provider-enabled').checked;
const baseUrl = modal.querySelector('#provider-base-url').value;
const apiKey = modal.querySelector('#provider-api-key').value;
const balance = parseFloat(modal.querySelector('#provider-balance').value);
const threshold = parseFloat(modal.querySelector('#provider-threshold').value);
try {
await window.api.put(`/providers/${id}`, {
enabled,
base_url: baseUrl || null,
api_key: apiKey || null
api_key: apiKey || null,
credit_balance: isNaN(balance) ? null : balance,
low_credit_threshold: isNaN(threshold) ? null : threshold
});
window.authManager.showToast(`${provider.name} configuration saved`, 'success');