Documentation Index
Fetch the complete documentation index at: https://grantmaster.dev/llms.txt
Use this file to discover all available pages before exploring further.
Credit Service Reference
Source: src/features/billing/services/creditService.ts
Manages the agent credit lifecycle: reserve credits before agent runs, consume credits after successful steps, release uncommitted reservations on failure/cancellation, and purchase credit packs as one-time top-ups.
Uses Firestore transactions for atomicity — concurrent agent runs cannot overdraw the credit balance.
Architecture:
- Called by
AgentExecutionService before/after agent runs
- Emits events via EventBus for analytics and notification workflows
- Integrates with
QuotaService for monthly limit enforcement
Quick Example
import { creditService } from '@/features/billing/services/creditService';
// Before agent run — atomically reserve credits
const reservation = await creditService.reserveCredits('org-123', 50, 'run-456');
// After each step — deduct actual usage
await creditService.consumeCredits('org-123', reservation.id, 12);
// On completion — release unused reservation balance
await creditService.releaseCredits('org-123', reservation.id);
Types
CreditReservation
A credit hold created before an agent run begins. Reservations prevent overspend from concurrent agents by atomically decrementing the available balance. They transition through active -> consumed | released | expired.
| Field | Type | Description |
|---|
id | string | Auto-generated Firestore document ID |
organizationId | string | Tenant isolation key |
agentRunId | string | The AgentRun this reservation is attached to |
amount | number | Total credits reserved (upper bound for the run) |
consumedAmount | number | Credits actually consumed so far via consumeCredits() |
status | 'active' | 'consumed' | 'released' | 'expired' | Lifecycle state of the reservation |
createdAt | string | ISO-8601 creation timestamp |
updatedAt | string | ISO-8601 last-update timestamp |
expiresAt | string | ISO-8601 expiry timestamp (auto-release after 1 hour) |
CreditBalance
Real-time credit balance snapshot for an organization.
| Field | Type | Description |
|---|
total | number | Monthly allocation plus any purchased top-ups |
used | number | Credits actually consumed by completed agent steps |
reserved | number | Credits held by active reservations (not yet consumed) |
available | number | Spendable credits: total - used - reserved |
purchasedExtra | number | One-time credit pack purchases added on top of the monthly allocation |
CreditConsumptionResult
Result of consuming credits from an active reservation.
| Field | Type | Description |
|---|
success | boolean | true if the consumption was applied successfully |
creditsConsumed | number | Number of credits deducted in this call |
remainingInReservation | number | Credits still available within the reservation after this consumption |
totalUsedThisMonth | number | Cumulative credits consumed by the organization this billing month |
Methods
reserveCredits()
Reserve credits before an agent run. Uses a Firestore transaction to atomically check balance and create reservation.
reserveCredits(
organizationId: string,
amount: number,
agentRunId: string
): Promise<CreditReservation>
| Param | Type | Description |
|---|
organizationId | string | Organization ID |
amount | number | Credits to reserve |
agentRunId | string | Associated agent run ID |
Returns: The created CreditReservation in 'active' status.
Throws:
BusinessLogicError — If insufficient credits available
BusinessLogicError — If database is not initialized
Transaction details: Atomically reads the org document, sums active reservations, validates available balance, increments the agentCreditsReserved counter, and creates a reservation subcollection document — all within a single Firestore transaction.
consumeCredits()
Consume credits from an active reservation. Called after each agent step to deduct actual usage.
consumeCredits(
organizationId: string,
reservationId: string,
actualAmount: number
): Promise<CreditConsumptionResult>
| Param | Type | Description |
|---|
organizationId | string | Organization ID |
reservationId | string | Reservation ID from reserveCredits() |
actualAmount | number | Credits actually consumed by the step |
Returns: CreditConsumptionResult with updated balances.
Throws:
NotFoundError — If reservation does not exist
BusinessLogicError — If reservation is not in 'active' state
BusinessLogicError — If consumption exceeds remaining reservation balance
Side effects: Updates usageMetrics.agentCreditsUsedThisMonth on the org document. Decreases agentCreditsReserved by the consumed amount (credits move from reserved to consumed). Auto-transitions reservation to 'consumed' when fully used.
releaseCredits()
Release uncommitted credits from a reservation. Called on agent run completion, failure, or cancellation.
releaseCredits(
organizationId: string,
reservationId: string
): Promise<void>
| Param | Type | Description |
|---|
organizationId | string | Organization ID |
reservationId | string | Reservation ID to release |
Behavior: Silently returns if reservation is not found or already consumed/released. Decreases agentCreditsReserved on the org by the uncommitted amount (amount - consumedAmount).
getCreditBalance()
Get current credit balance for an organization.
getCreditBalance(organizationId: string): Promise<CreditBalance>
| Param | Type | Description |
|---|
organizationId | string | Organization ID |
Returns: CreditBalance breakdown including purchased extras.
Throws: NotFoundError — If organization does not exist.
Note: This is a point-in-time read (not transactional). For accurate balance checks before spending, use reserveCredits() which uses transactions.
addPurchasedCredits()
Purchase a credit pack (one-time top-up). Adds credits to the organization’s balance for the current period.
addPurchasedCredits(
organizationId: string,
packSize: number,
stripePaymentIntentId?: string
): Promise<void>
| Param | Type | Description |
|---|
organizationId | string | Organization ID |
packSize | number | Number of credits to add |
stripePaymentIntentId | string? | Optional Stripe payment intent ID for audit trail |
Events: Emits CREDITS_PURCHASED via EventBus after successful transaction.
Note: Stripe payment integration is handled by the billing service. This method handles the credit allocation after payment confirmation.
Singleton Export
import { creditService } from '@/features/billing/services/creditService';
The module exports a pre-instantiated CreditService singleton using default logger, EventBus, and time provider.