Spaces:
Runtime error
Runtime error
File size: 2,432 Bytes
7e92e00 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 | import { UserProfile } from "@/types";
import { supabase } from './supabase';
export async function refreshTokenProfile() {
const {data:{user}}=await supabase.auth.getUser();
const day=new Date().toISOString().slice(0,10);
let used=0;
if(user){
const {data,error}=await supabase.from('ai_daily_usage').select('tokens_used').eq('user_id',user.id).eq('day',day).maybeSingle();
if(error) return;
used=data?.tokens_used || 0;
}
localStorage.setItem(STORE_KEY,JSON.stringify({id:user?.id || 'local',plan:'free',dailyTokenLimit:DAILY_FREE,tokensUsedToday:used,lastResetDate:day}));
window.dispatchEvent(new Event('purcar_token_update'));
}
const STORE_KEY = "purcar_user_v3";
export const DAILY_FREE = 50000; // 50k initial/daily tokens covering input + output
function todayKey(): string {
return new Date().toISOString().split("T")[0];
}
export function getLocalUserProfile(): UserProfile {
if (typeof window === "undefined") {
return { id: "local", plan: "free", dailyTokenLimit: DAILY_FREE, tokensUsedToday: 0, lastResetDate: todayKey() };
}
try {
const raw = localStorage.getItem(STORE_KEY);
if (!raw) return fresh();
const p: UserProfile = JSON.parse(raw);
// Ensure existing profiles receive the full 50k token budget
if (p.dailyTokenLimit < DAILY_FREE) {
p.dailyTokenLimit = DAILY_FREE;
}
if (p.lastResetDate !== todayKey()) {
const reset = { ...p, dailyTokenLimit: DAILY_FREE, tokensUsedToday: 0, lastResetDate: todayKey() };
localStorage.setItem(STORE_KEY, JSON.stringify(reset));
return reset;
}
return p;
} catch {
return fresh();
}
}
function fresh(): UserProfile {
const p: UserProfile = { id: "local", plan: "free", dailyTokenLimit: DAILY_FREE, tokensUsedToday: 0, lastResetDate: todayKey() };
if (typeof window !== "undefined") localStorage.setItem(STORE_KEY, JSON.stringify(p));
return p;
}
export function consumeTokens(count: number): { success: boolean; remaining: number } {
void count;
void refreshTokenProfile();
const p=getLocalUserProfile();
// Display cache only. Admission and charging happen atomically on the server.
return {success:true,remaining:Math.max(0,p.dailyTokenLimit-p.tokensUsedToday)};
}
export function estimateTokenCount(text: string): number {
// Rough BPE estimate: ~0.75 words per token
return Math.max(1, Math.ceil(text.split(/\s+/).length * 1.33));
}
|