@mastra/agent-browser 0.0.0-studio-deploy-20260404184540 → 0.0.0-studio-cli-20260504022012

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,11 +1,66 @@
1
1
  # @mastra/agent-browser
2
2
 
3
- ## 0.0.0-studio-deploy-20260404184540
3
+ ## 0.0.0-studio-cli-20260504022012
4
4
 
5
5
  ### Patch Changes
6
6
 
7
- - Updated dependencies [[`e133cc7`](https://github.com/mastra-ai/mastra/commit/e133cc73c2a73d90a39ad73f724e9cb492466b41), [`c55b527`](https://github.com/mastra-ai/mastra/commit/c55b52758a31368b2077b0dbbc3badfe4063f560), [`e133cc7`](https://github.com/mastra-ai/mastra/commit/e133cc73c2a73d90a39ad73f724e9cb492466b41), [`e133cc7`](https://github.com/mastra-ai/mastra/commit/e133cc73c2a73d90a39ad73f724e9cb492466b41), [`7eb2596`](https://github.com/mastra-ai/mastra/commit/7eb25960d607e07468c9a10c5437abd2deaf1e9a)]:
8
- - @mastra/core@0.0.0-studio-deploy-20260404184540
7
+ - Updated dependencies [[`6dcd65f`](https://github.com/mastra-ai/mastra/commit/6dcd65f2a34069e6dc43ba35f1d11119b9b40bef), [`c05c9a1`](https://github.com/mastra-ai/mastra/commit/c05c9a13230988cef6d438a62f37760f31927bc7), [`e24aacb`](https://github.com/mastra-ai/mastra/commit/e24aacba07bd66f5d95b636dc24016fca26b52cf), [`1c2dda8`](https://github.com/mastra-ai/mastra/commit/1c2dda805fbfccc0abf55d4cb20cc34402dc3f0c), [`c721164`](https://github.com/mastra-ai/mastra/commit/c7211643f7ac861f83b19a3757cc921487fc9d75), [`1b55954`](https://github.com/mastra-ai/mastra/commit/1b559541c1e08a10e49d01ffc51a634dfc37a286), [`5adc55e`](https://github.com/mastra-ai/mastra/commit/5adc55e63407be8ee977914957d68bcc2a075ceb), [`70017d7`](https://github.com/mastra-ai/mastra/commit/70017d72ab741b5d7040e2a15c251a317782e39e), [`e4942bc`](https://github.com/mastra-ai/mastra/commit/e4942bc7fdc903572f7d84f26d5e15f9d39c763d)]:
8
+ - @mastra/core@0.0.0-studio-cli-20260504022012
9
+
10
+ ## 0.2.1
11
+
12
+ ### Patch Changes
13
+
14
+ - Standardize `headless` default to `true` across all browser providers. Each provider now resolves `headless` once in its constructor and passes it to the thread manager via the base class getter, removing duplicate fallback logic. ([#15696](https://github.com/mastra-ai/mastra/pull/15696))
15
+
16
+ - Fixed `browser_evaluate` so expression scripts now return their computed value instead of `undefined` (for example, `document.querySelectorAll('a').length`). ([#15689](https://github.com/mastra-ai/mastra/pull/15689))
17
+
18
+ - Updated dependencies [[`733bf53`](https://github.com/mastra-ai/mastra/commit/733bf53d9352aedd3ef38c3d501edb275b65b43c), [`5405b3b`](https://github.com/mastra-ai/mastra/commit/5405b3b35325c5b8fb34fc7ac109bd2feb7bb6fe), [`45e29cb`](https://github.com/mastra-ai/mastra/commit/45e29cb5b5737f3083eb3852db02b944b9cf37ed), [`750b4d3`](https://github.com/mastra-ai/mastra/commit/750b4d3d8231f92e769b2c485921ac5a8ca639b9), [`c321127`](https://github.com/mastra-ai/mastra/commit/c3211275fc195de9ad1ead2746b354beb8eae6e8), [`a07bcef`](https://github.com/mastra-ai/mastra/commit/a07bcefea77c03d6d322caad973dca49b4b15fa1), [`696694e`](https://github.com/mastra-ai/mastra/commit/696694e00f29241a25dd1a1b749afa06c3a626b4), [`b084a80`](https://github.com/mastra-ai/mastra/commit/b084a800db0f82d62e1fc3d6e3e3480da1ba5a53), [`82b7a96`](https://github.com/mastra-ai/mastra/commit/82b7a964169636c1d1e0c694fc892a213b0179d5), [`df97812`](https://github.com/mastra-ai/mastra/commit/df97812bd949dcafeb074b80ecab501724b49c3b), [`8bbe360`](https://github.com/mastra-ai/mastra/commit/8bbe36042af7fc4be0244dffd8913f6795179421), [`f6b8ba8`](https://github.com/mastra-ai/mastra/commit/f6b8ba8dbf533b7a8db90c72b6805ddc804a3a72), [`a07bcef`](https://github.com/mastra-ai/mastra/commit/a07bcefea77c03d6d322caad973dca49b4b15fa1)]:
19
+ - @mastra/core@1.28.0
20
+
21
+ ## 0.2.1-alpha.1
22
+
23
+ ### Patch Changes
24
+
25
+ - Standardize `headless` default to `true` across all browser providers. Each provider now resolves `headless` once in its constructor and passes it to the thread manager via the base class getter, removing duplicate fallback logic. ([#15696](https://github.com/mastra-ai/mastra/pull/15696))
26
+
27
+ - Updated dependencies [[`750b4d3`](https://github.com/mastra-ai/mastra/commit/750b4d3d8231f92e769b2c485921ac5a8ca639b9)]:
28
+ - @mastra/core@1.28.0-alpha.1
29
+
30
+ ## 0.2.1-alpha.0
31
+
32
+ ### Patch Changes
33
+
34
+ - Fixed `browser_evaluate` so expression scripts now return their computed value instead of `undefined` (for example, `document.querySelectorAll('a').length`). ([#15689](https://github.com/mastra-ai/mastra/pull/15689))
35
+
36
+ - Updated dependencies [[`733bf53`](https://github.com/mastra-ai/mastra/commit/733bf53d9352aedd3ef38c3d501edb275b65b43c), [`5405b3b`](https://github.com/mastra-ai/mastra/commit/5405b3b35325c5b8fb34fc7ac109bd2feb7bb6fe), [`c321127`](https://github.com/mastra-ai/mastra/commit/c3211275fc195de9ad1ead2746b354beb8eae6e8), [`a07bcef`](https://github.com/mastra-ai/mastra/commit/a07bcefea77c03d6d322caad973dca49b4b15fa1), [`b084a80`](https://github.com/mastra-ai/mastra/commit/b084a800db0f82d62e1fc3d6e3e3480da1ba5a53), [`82b7a96`](https://github.com/mastra-ai/mastra/commit/82b7a964169636c1d1e0c694fc892a213b0179d5), [`df97812`](https://github.com/mastra-ai/mastra/commit/df97812bd949dcafeb074b80ecab501724b49c3b), [`8bbe360`](https://github.com/mastra-ai/mastra/commit/8bbe36042af7fc4be0244dffd8913f6795179421), [`f6b8ba8`](https://github.com/mastra-ai/mastra/commit/f6b8ba8dbf533b7a8db90c72b6805ddc804a3a72), [`a07bcef`](https://github.com/mastra-ai/mastra/commit/a07bcefea77c03d6d322caad973dca49b4b15fa1)]:
37
+ - @mastra/core@1.28.0-alpha.0
38
+
39
+ ## 0.2.0
40
+
41
+ ### Minor Changes
42
+
43
+ - Added `storageState` option and `exportStorageState()` method for lightweight auth persistence (cookies and localStorage). Also kills orphaned Chrome child processes on close to prevent zombies. ([#15194](https://github.com/mastra-ai/mastra/pull/15194))
44
+
45
+ ### Patch Changes
46
+
47
+ - AgentBrowser with default thread scope now initializes correctly. Previously, calling launch() followed by getPage() would throw "Browser not launched" when no explicit thread ID was provided. ([#15285](https://github.com/mastra-ai/mastra/pull/15285))
48
+
49
+ - Updated dependencies [[`87df955`](https://github.com/mastra-ai/mastra/commit/87df955c028660c075873fd5d74af28233ce32eb), [`8fad147`](https://github.com/mastra-ai/mastra/commit/8fad14759804179c8e080ce4d9dec6ef1a808b31), [`582644c`](https://github.com/mastra-ai/mastra/commit/582644c4a87f83b4f245a84d72b9e8590585012e), [`cbdf3e1`](https://github.com/mastra-ai/mastra/commit/cbdf3e12b3d0c30a6e5347be658e2009648c130a), [`8fe46d3`](https://github.com/mastra-ai/mastra/commit/8fe46d354027f3f0f0846e64219772348de106dd), [`18c67db`](https://github.com/mastra-ai/mastra/commit/18c67dbb9c9ebc26f26f65f7d3ff836e5691ef46), [`4ba3bb1`](https://github.com/mastra-ai/mastra/commit/4ba3bb1e465ad2ddaba3bbf2bc47e0faec32985e), [`5d84914`](https://github.com/mastra-ai/mastra/commit/5d84914e0e520c642a40329b210b413fcd139898), [`8dcc77e`](https://github.com/mastra-ai/mastra/commit/8dcc77e78a5340f5848f74b9e9f1b3da3513c1f5), [`aa67fc5`](https://github.com/mastra-ai/mastra/commit/aa67fc59ee8a5eeff1f23eb05970b8d7a536c8ff), [`fd2f314`](https://github.com/mastra-ai/mastra/commit/fd2f31473d3449b6b97e837ef8641264377f41a7), [`fa8140b`](https://github.com/mastra-ai/mastra/commit/fa8140bcd4251d2e3ac85fdc5547dfc4f372b5be), [`190f452`](https://github.com/mastra-ai/mastra/commit/190f45258b0640e2adfc8219fa3258cdc5b8f071), [`e80fead`](https://github.com/mastra-ai/mastra/commit/e80fead1412cc0d1b2f7d6a1ce5017d9e0098ff7), [`0287b64`](https://github.com/mastra-ai/mastra/commit/0287b644a5c3272755cf3112e71338106664103b), [`7e7bf60`](https://github.com/mastra-ai/mastra/commit/7e7bf606886bf374a6f9d4ca9b09dd83d0533372), [`184907d`](https://github.com/mastra-ai/mastra/commit/184907d775d8609c03c26e78ccaf37315f3aa287), [`075e91a`](https://github.com/mastra-ai/mastra/commit/075e91a4549baf46ad7a42a6a8ac8dfa78cc09e6), [`0c4cd13`](https://github.com/mastra-ai/mastra/commit/0c4cd131931c04ac5405373c932a242dbe88edd6), [`b16a753`](https://github.com/mastra-ai/mastra/commit/b16a753d5748440248d7df82e29bb987a9c8386c)]:
50
+ - @mastra/core@1.25.0
51
+
52
+ ## 0.2.0-alpha.0
53
+
54
+ ### Minor Changes
55
+
56
+ - Added `storageState` option and `exportStorageState()` method for lightweight auth persistence (cookies and localStorage). Also kills orphaned Chrome child processes on close to prevent zombies. ([#15194](https://github.com/mastra-ai/mastra/pull/15194))
57
+
58
+ ### Patch Changes
59
+
60
+ - AgentBrowser with default thread scope now initializes correctly. Previously, calling launch() followed by getPage() would throw "Browser not launched" when no explicit thread ID was provided. ([#15285](https://github.com/mastra-ai/mastra/pull/15285))
61
+
62
+ - Updated dependencies [[`cbdf3e1`](https://github.com/mastra-ai/mastra/commit/cbdf3e12b3d0c30a6e5347be658e2009648c130a), [`8fe46d3`](https://github.com/mastra-ai/mastra/commit/8fe46d354027f3f0f0846e64219772348de106dd), [`18c67db`](https://github.com/mastra-ai/mastra/commit/18c67dbb9c9ebc26f26f65f7d3ff836e5691ef46), [`8dcc77e`](https://github.com/mastra-ai/mastra/commit/8dcc77e78a5340f5848f74b9e9f1b3da3513c1f5), [`aa67fc5`](https://github.com/mastra-ai/mastra/commit/aa67fc59ee8a5eeff1f23eb05970b8d7a536c8ff), [`fa8140b`](https://github.com/mastra-ai/mastra/commit/fa8140bcd4251d2e3ac85fdc5547dfc4f372b5be), [`190f452`](https://github.com/mastra-ai/mastra/commit/190f45258b0640e2adfc8219fa3258cdc5b8f071), [`7e7bf60`](https://github.com/mastra-ai/mastra/commit/7e7bf606886bf374a6f9d4ca9b09dd83d0533372), [`184907d`](https://github.com/mastra-ai/mastra/commit/184907d775d8609c03c26e78ccaf37315f3aa287), [`0c4cd13`](https://github.com/mastra-ai/mastra/commit/0c4cd131931c04ac5405373c932a242dbe88edd6), [`b16a753`](https://github.com/mastra-ai/mastra/commit/b16a753d5748440248d7df82e29bb987a9c8386c)]:
63
+ - @mastra/core@1.25.0-alpha.3
9
64
 
10
65
  ## 0.1.0
11
66
 
package/README.md ADDED
@@ -0,0 +1,138 @@
1
+ # @mastra/agent-browser
2
+
3
+ Deterministic browser automation for Mastra agents using [agent-browser](https://github.com/vercel-labs/agent-browser).
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @mastra/agent-browser
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ```typescript
14
+ import { Agent } from '@mastra/core/agent';
15
+ import { AgentBrowser } from '@mastra/agent-browser';
16
+
17
+ // Create an AgentBrowser instance
18
+ const browser = new AgentBrowser({
19
+ headless: true,
20
+ });
21
+
22
+ // Create an agent with the browser
23
+ const agent = new Agent({
24
+ name: 'web-agent',
25
+ instructions: `You are a web automation assistant.
26
+ Use browser_snapshot to see the page structure,
27
+ then interact with elements using their refs (e.g., @e5).`,
28
+ model: 'openai/gpt-5.4',
29
+ browser,
30
+ });
31
+
32
+ // Use the agent to browse the web
33
+ const result = await agent.generate('Go to example.com and click the first link');
34
+ ```
35
+
36
+ ## Configuration
37
+
38
+ ```typescript
39
+ const browser = new AgentBrowser({
40
+ // Run headless (default: true)
41
+ headless: true,
42
+
43
+ // Viewport dimensions
44
+ viewport: { width: 1280, height: 720 },
45
+
46
+ // Default timeout for operations in ms (default: 30000)
47
+ timeout: 30000,
48
+
49
+ // CDP URL for connecting to existing browser
50
+ cdpUrl: 'ws://localhost:9222',
51
+
52
+ // Browser instance scope
53
+ // Default: 'thread' for local launch, 'shared' when cdpUrl is provided
54
+ // 'thread': Each thread gets its own browser
55
+ // 'shared': All threads share one browser
56
+ scope: 'thread',
57
+
58
+ // Screencast settings for Studio
59
+ screencast: {
60
+ enabled: true,
61
+ format: 'jpeg',
62
+ quality: 80,
63
+ },
64
+ });
65
+ ```
66
+
67
+ ## Tools
68
+
69
+ AgentBrowser exposes 15 deterministic tools using accessibility tree refs:
70
+
71
+ ### Core Tools
72
+
73
+ - **browser_goto** - Navigate to a URL
74
+ - **browser_snapshot** - Get accessibility tree with element refs (@e1, @e2, etc.)
75
+ - **browser_click** - Click an element by ref
76
+ - **browser_type** - Type text into an element
77
+ - **browser_press** - Press keyboard keys
78
+ - **browser_select** - Select option from dropdown
79
+ - **browser_scroll** - Scroll the page or element
80
+ - **browser_close** - Close the browser
81
+
82
+ ### Extended Tools
83
+
84
+ - **browser_hover** - Hover over an element
85
+ - **browser_back** - Go back in browser history
86
+ - **browser_dialog** - Handle browser dialogs (alert, confirm, prompt)
87
+ - **browser_wait** - Wait for element state changes
88
+ - **browser_tabs** - Manage browser tabs (list, new, switch, close)
89
+ - **browser_drag** - Drag and drop elements
90
+
91
+ ### Escape Hatch
92
+
93
+ - **browser_evaluate** - Execute JavaScript in the page context
94
+
95
+ ## How Refs Work
96
+
97
+ AgentBrowser uses accessibility tree refs for precise element targeting:
98
+
99
+ 1. Call `browser_snapshot` to get the page structure with refs
100
+ 2. Find the element you want to interact with
101
+ 3. Use its ref with other tools
102
+
103
+ ```text
104
+ [document] Example Page
105
+ [banner]
106
+ [link @e1] Home
107
+ [link @e2] About
108
+ [main]
109
+ [textbox @e3] Search...
110
+ [button @e4] Submit
111
+ ```
112
+
113
+ ```typescript
114
+ // Type in the search box
115
+ { tool: "browser_type", input: { ref: "@e3", text: "mastra" } }
116
+
117
+ // Click submit
118
+ { tool: "browser_click", input: { ref: "@e4" } }
119
+ ```
120
+
121
+ ## Comparison with StagehandBrowser
122
+
123
+ | Feature | AgentBrowser | StagehandBrowser |
124
+ | ----------- | ------------------------ | ---------------------------- |
125
+ | Approach | Deterministic refs (@e1) | Natural language |
126
+ | Token cost | Low | Higher (LLM calls) |
127
+ | Speed | Fast | Slower |
128
+ | Reliability | High (exact refs) | Variable (AI interpretation) |
129
+ | Best for | Structured workflows | Unknown/dynamic pages |
130
+
131
+ ## Documentation
132
+
133
+ - [agent-browser guide](https://mastra.ai/docs/browser/agent-browser) - Usage guide
134
+ - [AgentBrowser reference](https://mastra.ai/reference/browser/agent-browser) - API reference
135
+
136
+ ## License
137
+
138
+ Apache-2.0
package/dist/index.cjs CHANGED
@@ -36,8 +36,11 @@ var AgentBrowserThreadManager = class extends browser.ThreadManager {
36
36
  if (this.scope === "thread") {
37
37
  const manager = new agentBrowser.BrowserManager();
38
38
  const launchOptions = {
39
- headless: this.browserConfig.headless ?? true,
40
- viewport: this.browserConfig.viewport
39
+ headless: this.browserConfig.headless,
40
+ viewport: this.browserConfig.viewport,
41
+ profile: this.browserConfig.profile,
42
+ executablePath: this.browserConfig.executablePath,
43
+ storageState: this.browserConfig.storageState
41
44
  };
42
45
  if (this.browserConfig.cdpUrl && this.resolveCdpUrl) {
43
46
  launchOptions.cdpUrl = await this.resolveCdpUrl(this.browserConfig.cdpUrl);
@@ -218,7 +221,9 @@ var dragInputSchema = zod.z.object({
218
221
  }
219
222
  });
220
223
  var evaluateInputSchema = zod.z.object({
221
- script: zod.z.string().describe("JavaScript code to execute"),
224
+ script: zod.z.string().describe(
225
+ "JavaScript expression to evaluate in the browser and return the result. Do not use `return` \u2014 write a bare expression like `document.title` or `1 + 1`. For async code, wrap in an async IIFE: `(async () => { ... })()`."
226
+ ),
222
227
  arg: zod.z.unknown().optional().describe("Argument to pass to the script (JSON-serializable)")
223
228
  });
224
229
  var browserSchemas = {
@@ -491,12 +496,36 @@ function createAgentBrowserTools(browser) {
491
496
  };
492
497
  }
493
498
 
499
+ // src/utils.ts
500
+ async function getBrowserPid(manager) {
501
+ try {
502
+ let browser = manager.getBrowser();
503
+ if (!browser) {
504
+ const ctx = manager.getContext();
505
+ browser = ctx?.browser?.() ?? null;
506
+ }
507
+ if (!browser) return void 0;
508
+ const cdp = await browser.newBrowserCDPSession();
509
+ try {
510
+ const info = await cdp.send("SystemInfo.getProcessInfo");
511
+ const browserProcess = info.processInfo?.find((p) => p.type === "browser");
512
+ return browserProcess?.id;
513
+ } finally {
514
+ await cdp.detach().catch(() => void 0);
515
+ }
516
+ } catch {
517
+ return void 0;
518
+ }
519
+ }
520
+
494
521
  // src/agent-browser.ts
495
522
  var AgentBrowser = class extends browser.MastraBrowser {
496
523
  id;
497
524
  name = "AgentBrowser";
498
525
  provider = "vercel-labs/agent-browser";
499
526
  defaultTimeout = 3e4;
527
+ /** Pending PID lookups — awaited in disconnect handlers to avoid racing. */
528
+ pidLookups = /* @__PURE__ */ new Set();
500
529
  constructor(config = {}) {
501
530
  super(config);
502
531
  this.id = `agent-browser-${Date.now()}`;
@@ -506,7 +535,7 @@ var AgentBrowser = class extends browser.MastraBrowser {
506
535
  const effectiveScope = config.cdpUrl ? config.scope ?? "shared" : config.scope ?? "thread";
507
536
  this.threadManager = new AgentBrowserThreadManager({
508
537
  scope: effectiveScope,
509
- browserConfig: config,
538
+ browserConfig: { ...config, headless: this.headless },
510
539
  resolveCdpUrl: this.resolveCdpUrl.bind(this),
511
540
  logger: this.logger,
512
541
  // When a new thread session is created, notify listeners so screencast can start
@@ -534,11 +563,11 @@ var AgentBrowser = class extends browser.MastraBrowser {
534
563
  const scope = this.threadManager.getScope();
535
564
  const threadId = this.getCurrentThread();
536
565
  const existingSession = this.threadManager.hasSession(threadId);
537
- if (scope === "thread" && threadId !== browser.DEFAULT_THREAD_ID && !existingSession) {
566
+ if (scope === "thread" && !existingSession) {
538
567
  await this.getManagerForThread(threadId);
539
568
  }
540
569
  await super.ensureReady();
541
- if (scope === "thread" && threadId !== browser.DEFAULT_THREAD_ID && existingSession) {
570
+ if (scope === "thread" && existingSession) {
542
571
  await this.getManagerForThread(threadId);
543
572
  }
544
573
  }
@@ -570,8 +599,11 @@ var AgentBrowser = class extends browser.MastraBrowser {
570
599
  this.sharedManager = new agentBrowser.BrowserManager();
571
600
  const localConfig = this.config;
572
601
  const launchOptions = {
573
- headless: localConfig.headless ?? true,
574
- viewport: localConfig.viewport
602
+ headless: this.headless,
603
+ viewport: localConfig.viewport,
604
+ profile: localConfig.profile,
605
+ executablePath: localConfig.executablePath,
606
+ storageState: localConfig.storageState
575
607
  };
576
608
  if (localConfig.cdpUrl) {
577
609
  launchOptions.cdpUrl = await this.resolveCdpUrl(localConfig.cdpUrl);
@@ -586,11 +618,15 @@ var AgentBrowser = class extends browser.MastraBrowser {
586
618
  */
587
619
  setupCloseListenerForSharedScope(manager) {
588
620
  try {
621
+ const pidLookup = getBrowserPid(manager).then((pid) => {
622
+ if (pid && this.sharedManager === manager) this.sharedBrowserPid = pid;
623
+ }).finally(() => this.pidLookups.delete(pidLookup));
624
+ this.pidLookups.add(pidLookup);
589
625
  let disconnectHandled = false;
590
626
  const handleDisconnect = () => {
591
627
  if (disconnectHandled) return;
592
628
  disconnectHandled = true;
593
- this.handleBrowserDisconnected();
629
+ void pidLookup.catch(() => void 0).then(() => this.handleBrowserDisconnected());
594
630
  };
595
631
  const context = manager.getContext();
596
632
  if (context) {
@@ -609,6 +645,8 @@ var AgentBrowser = class extends browser.MastraBrowser {
609
645
  }
610
646
  }
611
647
  async doClose() {
648
+ await Promise.allSettled([...this.pidLookups]);
649
+ this.pidLookups.clear();
612
650
  await this.threadManager.destroyAllSessions();
613
651
  this.setCurrentThread(void 0);
614
652
  const scope = this.threadManager.getScope();
@@ -692,11 +730,17 @@ var AgentBrowser = class extends browser.MastraBrowser {
692
730
  */
693
731
  setupCloseListenerForThread(manager, threadId) {
694
732
  try {
733
+ const pidLookup = getBrowserPid(manager).then((pid) => {
734
+ if (pid && this.threadManager?.getExistingManagerForThread(threadId) === manager) {
735
+ this.threadBrowserPids.set(threadId, pid);
736
+ }
737
+ }).finally(() => this.pidLookups.delete(pidLookup));
738
+ this.pidLookups.add(pidLookup);
695
739
  let disconnectHandled = false;
696
740
  const handleDisconnect = () => {
697
741
  if (disconnectHandled) return;
698
742
  disconnectHandled = true;
699
- this.handleThreadBrowserDisconnected(threadId);
743
+ void pidLookup.catch(() => void 0).then(() => this.handleThreadBrowserDisconnected(threadId));
700
744
  };
701
745
  const context = manager.getContext();
702
746
  if (context) {
@@ -886,6 +930,25 @@ var AgentBrowser = class extends browser.MastraBrowser {
886
930
  return 0;
887
931
  }
888
932
  }
933
+ /**
934
+ * Export the current browser session's storage state (cookies, localStorage) to a JSON file.
935
+ * This can later be loaded via the `storageState` config option to restore the session.
936
+ *
937
+ * @param path - File path to save the storage state JSON
938
+ * @param threadId - Optional thread ID (defaults to current thread)
939
+ */
940
+ async exportStorageState(path, threadId) {
941
+ const effectiveThreadId = threadId ?? this.getCurrentThread();
942
+ const manager = this.threadManager.getExistingManagerForThread(effectiveThreadId);
943
+ if (!manager) {
944
+ throw new Error("No browser is running. Launch a browser first before exporting storage state.");
945
+ }
946
+ const context = manager.getContext();
947
+ if (!context) {
948
+ throw new Error("Browser context not available");
949
+ }
950
+ await context.storageState({ path });
951
+ }
889
952
  // ---------------------------------------------------------------------------
890
953
  // 1. browser_goto - Navigate to URL
891
954
  // ---------------------------------------------------------------------------
@@ -1402,8 +1465,7 @@ var AgentBrowser = class extends browser.MastraBrowser {
1402
1465
  async evaluate(input, threadId) {
1403
1466
  try {
1404
1467
  const page = await this.getPage(threadId);
1405
- const wrappedScript = `(async () => { ${input.script} })()`;
1406
- const result = await page.evaluate(wrappedScript);
1468
+ const result = await page.evaluate(input.script);
1407
1469
  return {
1408
1470
  success: true,
1409
1471
  result,
@@ -1564,6 +1626,7 @@ exports.createAgentBrowserTools = createAgentBrowserTools;
1564
1626
  exports.dialogInputSchema = dialogInputSchema;
1565
1627
  exports.dragInputSchema = dragInputSchema;
1566
1628
  exports.evaluateInputSchema = evaluateInputSchema;
1629
+ exports.getBrowserPid = getBrowserPid;
1567
1630
  exports.gotoInputSchema = gotoInputSchema;
1568
1631
  exports.hoverInputSchema = hoverInputSchema;
1569
1632
  exports.pressInputSchema = pressInputSchema;