The project is in a healthy, maintained state
Adds an ActiveRecord-backed wallet store, has_token_wallet concern, token wallet/transaction models, an install generator with migrations, and an expiry sweep job to any Rails app using ask-token-usage.
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
 Dependencies

Development

~> 5.25
~> 13.0

Runtime

>= 7.0
 Project Readme

ask-tokens-rails

ActiveRecord persistence for the ask-tokens wallet engine.

Ships an ActiveRecord store adapter, a has_token_wallet macro, install generator with migrations, and an expiry sweep job.

Installation

# Gemfile
gem "ask-tokens-rails"
bundle install
rails g ask_tokens:install
rails db:migrate

Table names default to ask_tokens_wallets and ask_tokens_transactions. To adopt existing tables:

Ask::Tokens::Rails.configure do |config|
  config.wallets_table = "token_wallets"
  config.transactions_table = "token_transactions"
end

Usage

class User < ApplicationRecord
  has_token_wallet
end

# Grant tokens
user.grant_tokens!(10_000, reason: :trial, expires_at: 7.days.from_now)

# Spend on an activity (charges only if the block succeeds)
user.spend_tokens_on!(:chat_message, input: "hi", output: "yo") do
  LLM.chat(...)
end

# Check balance
user.token_balance   # => 9_998

# Read the ledger
user.token_transactions.credits
user.token_transactions.debits.since(30.days.ago)

# Use the PORO wallet directly
wallet = user.ask_token_wallet
wallet.entries
wallet.used_since(30.days.ago)

Pass metadata: {model_id:, provider:, input_tokens:, output_tokens:, cached_tokens:, llm_cost_usd:, multiplier:} on a grant/deduction and the store lifts those keys into the ledger's billing columns, so model spend and margin can be summed without JSON casts.

Scheduled jobs

SweepExpiredTokensJob expires grant entries whose expires_at has passed, removing only each grant's unspent remainder (first-to-expire-first allocation). Add an expires_at index if your install predates migration column v0.4.0.

# config/recurring.yml (Solid Queue)
ask_tokens_sweep:
  class: Ask::Tokens::Rails::SweepExpiredTokensJob
  schedule: every hour