Skip to content

Commit ab5e2c5

Browse files
authored
Add default timeout to waitForSettledDom (#132)
* Add default timeout to waitForSettledDom * set to 60 second default timeout * Change to 61 seconds * Update index.ts * Update index.ts
1 parent d850784 commit ab5e2c5

File tree

2 files changed

+43
-18
lines changed

2 files changed

+43
-18
lines changed

README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
- [Acknowledgements](#acknowledgements)
3535
- [License](#license)
3636

37-
> [!NOTE]
37+
> [!NOTE]
3838
> `Stagehand` is currently available as an early release, and we're actively seeking feedback from the community. Please join our [Slack community](https://join.slack.com/t/stagehand-dev/shared_invite/zt-2tdncfgkk-fF8y5U0uJzR2y2_M9c9OJA) to stay updated on the latest developments and provide feedback.
3939
4040
## Intro
@@ -133,6 +133,7 @@ This constructor is used to create an instance of Stagehand.
133133
- `1`: SDK-level logging
134134
- `2`: LLM-client level logging (most granular)
135135
- `debugDom`: a `boolean` that draws bounding boxes around elements presented to the LLM during automation.
136+
- `domSettleTimeoutMs`: an `integer` that specifies the timeout in milliseconds for waiting for the DOM to settle. Defaults to 30000 (30 seconds).
136137

137138
- **Returns:**
138139

@@ -212,7 +213,7 @@ This constructor is used to create an instance of Stagehand.
212213

213214
#### `observe()`
214215

215-
> [!NOTE]
216+
> [!NOTE]
216217
> `observe()` currently only evaluates the first chunk in the page.
217218
218219
`observe()` is used to get a list of actions that can be taken on the current page. It's useful for adding context to your planning step, or if you unsure of what page you're on.

lib/index.ts

Lines changed: 40 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,7 @@ export class Stagehand {
182182
category?: string;
183183
message: string;
184184
}) => void;
185+
private domSettleTimeoutMs: number;
185186

186187
constructor(
187188
{
@@ -191,6 +192,7 @@ export class Stagehand {
191192
llmProvider,
192193
headless = false,
193194
logger,
195+
domSettleTimeoutMs = 60000,
194196
}: {
195197
env: "LOCAL" | "BROWSERBASE";
196198
verbose?: 0 | 1 | 2;
@@ -202,6 +204,7 @@ export class Stagehand {
202204
message: string;
203205
level?: 0 | 1 | 2;
204206
}) => void;
207+
domSettleTimeoutMs?: number;
205208
} = {
206209
env: "BROWSERBASE",
207210
},
@@ -216,6 +219,7 @@ export class Stagehand {
216219
this.debugDom = debugDom;
217220
this.defaultModelName = "gpt-4o";
218221
this.headless = headless;
222+
this.domSettleTimeoutMs = domSettleTimeoutMs;
219223
}
220224

221225
async init({
@@ -357,25 +361,45 @@ export class Stagehand {
357361
}
358362
}
359363

360-
private async _waitForSettledDom() {
364+
private async _waitForSettledDom(timeoutMs?: number) {
361365
try {
362-
await this.page.waitForSelector("body");
363-
await this.page.waitForLoadState("domcontentloaded");
366+
const timeout = timeoutMs ?? this.domSettleTimeoutMs;
367+
const timeoutPromise = new Promise<void>((resolve) => {
368+
setTimeout(() => {
369+
console.warn(
370+
`[stagehand:dom] DOM settle timeout of ${timeout}ms exceeded, continuing anyway`,
371+
);
372+
this.log({
373+
category: "dom",
374+
message: `DOM settle timeout of ${timeout}ms exceeded, continuing anyway`,
375+
level: 1,
376+
});
377+
resolve();
378+
}, timeout);
379+
});
364380

365-
await this.page.evaluate(() => {
366-
return new Promise<void>((resolve) => {
367-
if (typeof window.waitForDomSettle === "function") {
368-
window.waitForDomSettle().then(() => {
369-
resolve();
381+
await Promise.race([
382+
(async () => {
383+
await this.page.waitForSelector("body");
384+
await this.page.waitForLoadState("domcontentloaded");
385+
386+
await this.page.evaluate(() => {
387+
return new Promise<void>((resolve) => {
388+
if (typeof window.waitForDomSettle === "function") {
389+
window.waitForDomSettle().then(() => {
390+
resolve();
391+
});
392+
} else {
393+
console.warn(
394+
"waitForDomSettle is not defined, considering DOM as settled",
395+
);
396+
resolve();
397+
}
370398
});
371-
} else {
372-
console.warn(
373-
"waitForDomSettle is not defined, considering DOM as settled",
374-
);
375-
resolve();
376-
}
377-
});
378-
});
399+
});
400+
})(),
401+
timeoutPromise,
402+
]);
379403
} catch (e) {
380404
this.log({
381405
category: "dom",

0 commit comments

Comments
 (0)