-
Notifications
You must be signed in to change notification settings - Fork 15
Expand file tree
/
Copy pathindex.ts
More file actions
162 lines (127 loc) Β· 5.67 KB
/
Copy pathindex.ts
File metadata and controls
162 lines (127 loc) Β· 5.67 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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
// Stagehand + Browserbase: Basic Caching - See README.md for full documentation
import "dotenv/config";
import { Stagehand } from "@browserbasehq/stagehand";
import fs from "fs";
import path from "path";
const CACHE_DIR = path.join(process.cwd(), ".cache", "stagehand-demo");
async function runWithoutCache() {
console.log("RUN 1: WITHOUT CACHING");
const startTime = Date.now();
const stagehand = new Stagehand({
env: "BROWSERBASE",
verbose: 0,
// 0 = errors only, 1 = info, 2 = debug
// (When handling sensitive data like passwords or API keys, set verbose: 0 to prevent secrets from appearing in logs.)
// https://docs.stagehand.dev/configuration/logging
model: "google/gemini-2.5-flash",
enableCaching: false,
});
await stagehand.init();
const page = stagehand.context.pages()[0];
try {
console.log("Navigating to Stripe checkout...");
await page.goto("https://checkout.stripe.dev/preview", {
waitUntil: "domcontentloaded",
});
await stagehand.act("Click on the View Demo button");
await stagehand.act("Type 'test@example.com' into the email field");
await stagehand.act("Type '4242424242424242' into the card number field");
await stagehand.act("Type '12/34' into the expiration date field");
const elapsed = ((Date.now() - startTime) / 1000).toFixed(2);
console.log(`Total time: ${elapsed}s`);
console.log("Cost: ~$0.01-0.05 (4 LLM calls)");
console.log("API calls: 4 (one per action)\n");
await stagehand.close();
return { elapsed, llmCalls: 4 };
} catch (error) {
console.error("Error:", error.message);
await stagehand.close();
throw error;
}
}
async function runWithCache() {
console.log("RUN 2: WITH CACHING");
const startTime = Date.now();
const stagehand = new Stagehand({
env: "BROWSERBASE",
verbose: 0,
// 0 = errors only, 1 = info, 2 = debug
// (When handling sensitive data like passwords or API keys, set verbose: 0 to prevent secrets from appearing in logs.)
// https://docs.stagehand.dev/configuration/logging
model: "google/gemini-2.5-flash",
enableCaching: true,
cacheDir: CACHE_DIR,
});
await stagehand.init();
const page = stagehand.context.pages()[0];
try {
console.log("Navigating to Stripe checkout...");
await page.goto("https://checkout.stripe.dev/preview", {
waitUntil: "domcontentloaded",
});
await stagehand.act("Click on the View Demo button");
await stagehand.act("Type 'test@example.com' into the email field");
await stagehand.act("Type '4242424242424242' into the card number field");
await stagehand.act("Type '12/34' into the expiration date field");
const elapsed = ((Date.now() - startTime) / 1000).toFixed(2);
const cacheExists = fs.existsSync(CACHE_DIR);
const cacheFiles = cacheExists ? fs.readdirSync(CACHE_DIR).length : 0;
console.log(`Total time: ${elapsed}s`);
if (cacheFiles > 0) {
console.log("Cost: $0.00 (cache hits, no LLM calls)");
console.log("API calls: 0 (all from cache)");
console.log(`Cache entries: ${cacheFiles}`);
} else {
console.log("π°Cost: ~$0.01-0.05 (first run, populated cache)");
console.log("π‘API calls: 4 (saved to cache for next run)");
console.log("πCache created");
}
console.log();
await stagehand.close();
return { elapsed, llmCalls: cacheFiles > 0 ? 0 : 4 };
} catch (error) {
console.error("Error:", error.message);
await stagehand.close();
throw error;
}
}
async function main() {
console.log("\nβββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ");
console.log("β Caching Demo - Run This Script TWICE! β");
console.log("βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n");
console.log("This demo shows caching impact by running the same workflow twice:\n");
console.log("First run:");
console.log(" 1. WITHOUT cache (baseline)");
console.log(" 2. WITH cache enabled (populates cache)\n");
console.log("Second run:");
console.log(" - WITH cache (instant, $0 cost)\n");
console.log("Run 'pnpm start' twice to see the difference!\n");
// Check if cache exists
const cacheExists = fs.existsSync(CACHE_DIR);
if (cacheExists) {
const cacheFiles = fs.readdirSync(CACHE_DIR);
console.log(`π Cache found: ${cacheFiles.length} entries`);
console.log(" This is a SUBSEQUENT run - cache will be used!\n");
} else {
console.log("No cache found - first run will populate cache");
}
console.log("\nRunning comparison: without cache vs with cache...\n");
const withoutCache = await runWithoutCache();
const withCache = await runWithCache();
console.log("\n=== Comparison ===");
console.log(`Without caching: ${withoutCache.elapsed}s, ${withoutCache.llmCalls} LLM calls`);
console.log(`With caching: ${withCache.elapsed}s, ${withCache.llmCalls} LLM calls`);
if (withCache.llmCalls === 0) {
const speedup = (parseFloat(withoutCache.elapsed) / parseFloat(withCache.elapsed)).toFixed(1);
console.log(`\nSpeedup: ${speedup}x faster with cache`);
console.log("Cost savings: 100% (no LLM calls)");
}
console.log("\nRun again to see cache benefits on subsequent runs!");
}
main().catch((err) => {
console.error("Error in caching demo:", err);
console.error("Common issues:");
console.error(" - Check .env file has BROWSERBASE_API_KEY");
console.error("Docs: https://docs.stagehand.dev/v3/first-steps/introduction");
process.exit(1);
});