-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy path3-budget-persistence.js
More file actions
133 lines (113 loc) · 3.66 KB
/
3-budget-persistence.js
File metadata and controls
133 lines (113 loc) · 3.66 KB
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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
/**
* Example 3: Budget Persistence - Save and Restore State
*
* This example shows how to:
* - Save budget state to disk
* - Restore budget state on restart
* - Maintain budget tracking across application restarts
*/
const fs = require('fs');
const path = require('path');
const {
createBudgetGuard,
exportBudgetState,
importBudgetState,
getBudgetStatus,
patchGlobalFetch
} = require("../dist/index.js");
const BUDGET_FILE = path.join(__dirname, 'budget-state.json');
// Load saved budget state
function loadBudgetState() {
try {
if (fs.existsSync(BUDGET_FILE)) {
const data = fs.readFileSync(BUDGET_FILE, 'utf8');
const state = JSON.parse(data);
console.log(`✅ Loaded saved budget: $${state.totalSpent.toFixed(4)} spent`);
return state;
}
} catch (error) {
console.warn('⚠️ Could not load budget state:', error.message);
}
return null;
}
// Save current budget state
function saveBudgetState() {
try {
const state = exportBudgetState();
if (state) {
fs.writeFileSync(BUDGET_FILE, JSON.stringify(state, null, 2));
console.log(`💾 Saved budget state: $${state.totalSpent.toFixed(4)} spent`);
}
} catch (error) {
console.error('❌ Could not save budget state:', error.message);
}
}
async function main() {
console.log("🔥 TokenFirewall - Budget Persistence Example\n");
console.log("=".repeat(60) + "\n");
// Step 1: Create budget guard
createBudgetGuard({
monthlyLimit: 100,
mode: "warn"
});
// Step 2: Load previous state if exists
const savedState = loadBudgetState();
if (savedState) {
importBudgetState(savedState);
console.log("✅ Restored previous budget state\n");
} else {
console.log("ℹ️ No previous budget state found - starting fresh\n");
}
patchGlobalFetch();
// Step 3: Show current status
let status = getBudgetStatus();
console.log("📊 Current Budget Status:");
console.log(` Spent: $${status.totalSpent.toFixed(4)}`);
console.log(` Remaining: $${status.remaining.toFixed(2)}`);
console.log(` Usage: ${status.percentageUsed.toFixed(2)}%\n`);
console.log("=".repeat(60) + "\n");
// Step 4: Make some API calls (example)
if (process.env.OPENAI_API_KEY) {
console.log("Making API call...\n");
try {
await fetch("https://api.openai.com/v1/chat/completions", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.OPENAI_API_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
model: "gpt-4o-mini",
messages: [{ role: "user", content: "Hi" }]
})
});
// Show updated status
status = getBudgetStatus();
console.log("📊 Updated Budget Status:");
console.log(` Spent: $${status.totalSpent.toFixed(4)}`);
console.log(` Remaining: $${status.remaining.toFixed(2)}`);
console.log(` Usage: ${status.percentageUsed.toFixed(2)}%\n`);
} catch (error) {
console.log("(API call failed - that's okay for this demo)\n");
}
}
// Step 5: Save state before exit
saveBudgetState();
console.log("\n" + "=".repeat(60));
console.log("\n💡 Budget state saved to: budget-state.json");
console.log(" Run this example again to see state restored!\n");
}
// Auto-save on exit
process.on('beforeExit', () => {
saveBudgetState();
});
process.on('SIGINT', () => {
saveBudgetState();
process.exit(0);
});
main();
// 💡 Key Points:
// - exportBudgetState() returns { totalSpent, limit, mode }
// - importBudgetState() validates and restores state
// - Save state periodically or on exit
// - Perfect for long-running applications or serverless functions