@mastra/agent-browser 0.3.0 → 0.3.1
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 +18 -0
- package/dist/index.cjs +67 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +9 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +67 -8
- package/dist/index.js.map +1 -1
- package/package.json +7 -7
package/dist/index.d.cts
CHANGED
|
@@ -474,6 +474,8 @@ declare class AgentBrowser extends MastraBrowser {
|
|
|
474
474
|
private defaultTimeout;
|
|
475
475
|
/** Pending PID lookups — awaited in disconnect handlers to avoid racing. */
|
|
476
476
|
private pidLookups;
|
|
477
|
+
private readonly pendingCloseReasons;
|
|
478
|
+
private readonly activeUrlChangeSources;
|
|
477
479
|
/** Thread manager - narrowed type from base class */
|
|
478
480
|
protected threadManager: AgentBrowserThreadManager;
|
|
479
481
|
private browserConfig;
|
|
@@ -499,6 +501,7 @@ declare class AgentBrowser extends MastraBrowser {
|
|
|
499
501
|
*/
|
|
500
502
|
protected setupCloseListenerForSharedScope(manager: BrowserManager): void;
|
|
501
503
|
protected doClose(): Promise<void>;
|
|
504
|
+
closeThreadSession(threadId: string): Promise<void>;
|
|
502
505
|
/**
|
|
503
506
|
* Check if the browser is still alive by verifying the page is connected.
|
|
504
507
|
* Called by base class ensureReady() to detect externally closed browsers.
|
|
@@ -509,6 +512,12 @@ declare class AgentBrowser extends MastraBrowser {
|
|
|
509
512
|
* Returns 16 flat tools for browser automation.
|
|
510
513
|
*/
|
|
511
514
|
getTools(): Record<string, Tool<any, any>>;
|
|
515
|
+
private browserStateKey;
|
|
516
|
+
markBrowserCloseReason(reason: 'agent' | 'user' | 'process_restart' | 'error', threadId?: string): void;
|
|
517
|
+
private markActiveUrlChangeSource;
|
|
518
|
+
private getCloseReason;
|
|
519
|
+
private getActiveUrlChangeSource;
|
|
520
|
+
private rememberClosedBrowserState;
|
|
512
521
|
/**
|
|
513
522
|
* Get the page for the current thread.
|
|
514
523
|
* Uses thread scope if enabled, otherwise returns the shared page.
|
package/dist/index.d.ts
CHANGED
|
@@ -474,6 +474,8 @@ declare class AgentBrowser extends MastraBrowser {
|
|
|
474
474
|
private defaultTimeout;
|
|
475
475
|
/** Pending PID lookups — awaited in disconnect handlers to avoid racing. */
|
|
476
476
|
private pidLookups;
|
|
477
|
+
private readonly pendingCloseReasons;
|
|
478
|
+
private readonly activeUrlChangeSources;
|
|
477
479
|
/** Thread manager - narrowed type from base class */
|
|
478
480
|
protected threadManager: AgentBrowserThreadManager;
|
|
479
481
|
private browserConfig;
|
|
@@ -499,6 +501,7 @@ declare class AgentBrowser extends MastraBrowser {
|
|
|
499
501
|
*/
|
|
500
502
|
protected setupCloseListenerForSharedScope(manager: BrowserManager): void;
|
|
501
503
|
protected doClose(): Promise<void>;
|
|
504
|
+
closeThreadSession(threadId: string): Promise<void>;
|
|
502
505
|
/**
|
|
503
506
|
* Check if the browser is still alive by verifying the page is connected.
|
|
504
507
|
* Called by base class ensureReady() to detect externally closed browsers.
|
|
@@ -509,6 +512,12 @@ declare class AgentBrowser extends MastraBrowser {
|
|
|
509
512
|
* Returns 16 flat tools for browser automation.
|
|
510
513
|
*/
|
|
511
514
|
getTools(): Record<string, Tool<any, any>>;
|
|
515
|
+
private browserStateKey;
|
|
516
|
+
markBrowserCloseReason(reason: 'agent' | 'user' | 'process_restart' | 'error', threadId?: string): void;
|
|
517
|
+
private markActiveUrlChangeSource;
|
|
518
|
+
private getCloseReason;
|
|
519
|
+
private getActiveUrlChangeSource;
|
|
520
|
+
private rememberClosedBrowserState;
|
|
512
521
|
/**
|
|
513
522
|
* Get the page for the current thread.
|
|
514
523
|
* Uses thread scope if enabled, otherwise returns the shared page.
|
package/dist/index.js
CHANGED
|
@@ -314,13 +314,16 @@ function createCloseTool(browser) {
|
|
|
314
314
|
inputSchema: closeInputSchema,
|
|
315
315
|
execute: async (_input, { agent }) => {
|
|
316
316
|
const threadId = agent?.threadId;
|
|
317
|
+
browser.setCurrentThread(threadId);
|
|
317
318
|
if (browser.getScope() !== "shared") {
|
|
318
319
|
if (!threadId) {
|
|
319
320
|
throw new Error("browser_close requires agent.threadId when browser scope is not shared");
|
|
320
321
|
}
|
|
322
|
+
browser.markBrowserCloseReason("agent", threadId);
|
|
321
323
|
await browser.closeThreadSession(threadId);
|
|
322
324
|
return { success: true, hint: "Thread's browser session closed. A new session will be created on next use." };
|
|
323
325
|
}
|
|
326
|
+
browser.markBrowserCloseReason("agent");
|
|
324
327
|
await browser.close();
|
|
325
328
|
return { success: true, hint: "Browser closed. It will be re-launched automatically on next use." };
|
|
326
329
|
}
|
|
@@ -571,6 +574,8 @@ var AgentBrowser = class extends MastraBrowser {
|
|
|
571
574
|
defaultTimeout = 3e4;
|
|
572
575
|
/** Pending PID lookups — awaited in disconnect handlers to avoid racing. */
|
|
573
576
|
pidLookups = /* @__PURE__ */ new Set();
|
|
577
|
+
pendingCloseReasons = /* @__PURE__ */ new Map();
|
|
578
|
+
activeUrlChangeSources = /* @__PURE__ */ new Map();
|
|
574
579
|
browserConfig;
|
|
575
580
|
constructor(config = {}) {
|
|
576
581
|
super(config);
|
|
@@ -639,6 +644,8 @@ var AgentBrowser = class extends MastraBrowser {
|
|
|
639
644
|
// Lifecycle
|
|
640
645
|
// ---------------------------------------------------------------------------
|
|
641
646
|
async doLaunch() {
|
|
647
|
+
this.pendingCloseReasons.clear();
|
|
648
|
+
this.activeUrlChangeSources.clear();
|
|
642
649
|
const scope = this.threadManager.getScope();
|
|
643
650
|
if (scope === "thread") {
|
|
644
651
|
this.sharedManager = new BrowserManager();
|
|
@@ -675,6 +682,7 @@ var AgentBrowser = class extends MastraBrowser {
|
|
|
675
682
|
const handleDisconnect = () => {
|
|
676
683
|
if (disconnectHandled) return;
|
|
677
684
|
disconnectHandled = true;
|
|
685
|
+
this.rememberClosedBrowserState(manager, "user");
|
|
678
686
|
void pidLookup.catch(() => void 0).then(() => this.handleBrowserDisconnected());
|
|
679
687
|
};
|
|
680
688
|
const context = manager.getContext();
|
|
@@ -704,6 +712,14 @@ var AgentBrowser = class extends MastraBrowser {
|
|
|
704
712
|
}
|
|
705
713
|
this.sharedManager = null;
|
|
706
714
|
}
|
|
715
|
+
async closeThreadSession(threadId) {
|
|
716
|
+
const manager = this.threadManager.getExistingManagerForThread(threadId);
|
|
717
|
+
if (manager) {
|
|
718
|
+
const state = this.getBrowserStateForManager(manager, threadId);
|
|
719
|
+
if (state) this.threadManager.updateBrowserState(threadId, state);
|
|
720
|
+
}
|
|
721
|
+
await super.closeThreadSession(threadId);
|
|
722
|
+
}
|
|
707
723
|
/**
|
|
708
724
|
* Check if the browser is still alive by verifying the page is connected.
|
|
709
725
|
* Called by base class ensureReady() to detect externally closed browsers.
|
|
@@ -754,6 +770,32 @@ var AgentBrowser = class extends MastraBrowser {
|
|
|
754
770
|
// ---------------------------------------------------------------------------
|
|
755
771
|
// Helpers
|
|
756
772
|
// ---------------------------------------------------------------------------
|
|
773
|
+
browserStateKey(threadId) {
|
|
774
|
+
return threadId ?? this.getCurrentThread() ?? DEFAULT_THREAD_ID;
|
|
775
|
+
}
|
|
776
|
+
markBrowserCloseReason(reason, threadId) {
|
|
777
|
+
this.pendingCloseReasons.set(this.browserStateKey(threadId), reason);
|
|
778
|
+
}
|
|
779
|
+
markActiveUrlChangeSource(source, url, threadId) {
|
|
780
|
+
this.activeUrlChangeSources.set(this.browserStateKey(threadId), { url, source });
|
|
781
|
+
}
|
|
782
|
+
getCloseReason(threadId) {
|
|
783
|
+
return this.pendingCloseReasons.get(this.browserStateKey(threadId)) ?? this.pendingCloseReasons.get(DEFAULT_THREAD_ID);
|
|
784
|
+
}
|
|
785
|
+
getActiveUrlChangeSource(activeUrl, threadId) {
|
|
786
|
+
const entry = this.activeUrlChangeSources.get(this.browserStateKey(threadId));
|
|
787
|
+
return entry && entry.url === activeUrl ? entry.source : void 0;
|
|
788
|
+
}
|
|
789
|
+
rememberClosedBrowserState(manager, reason, threadId) {
|
|
790
|
+
const state = this.getBrowserStateForManager(manager, threadId);
|
|
791
|
+
if (!state || state.tabs.length === 0) return;
|
|
792
|
+
const closedState = { ...state, closeReason: this.getCloseReason(threadId) ?? reason };
|
|
793
|
+
if (threadId) {
|
|
794
|
+
this.threadManager.updateBrowserState(threadId, closedState);
|
|
795
|
+
} else {
|
|
796
|
+
this.lastBrowserState = closedState;
|
|
797
|
+
}
|
|
798
|
+
}
|
|
757
799
|
/**
|
|
758
800
|
* Get the page for the current thread.
|
|
759
801
|
* Uses thread scope if enabled, otherwise returns the shared page.
|
|
@@ -796,6 +838,7 @@ var AgentBrowser = class extends MastraBrowser {
|
|
|
796
838
|
const handleDisconnect = () => {
|
|
797
839
|
if (disconnectHandled) return;
|
|
798
840
|
disconnectHandled = true;
|
|
841
|
+
this.rememberClosedBrowserState(manager, "user", threadId);
|
|
799
842
|
void pidLookup.catch(() => void 0).then(() => this.handleThreadBrowserDisconnected(threadId));
|
|
800
843
|
};
|
|
801
844
|
const context = manager.getContext();
|
|
@@ -927,12 +970,12 @@ var AgentBrowser = class extends MastraBrowser {
|
|
|
927
970
|
* Get the current browser state (all tabs and active tab index).
|
|
928
971
|
*/
|
|
929
972
|
async getBrowserState(threadId) {
|
|
930
|
-
if (!this.isBrowserRunning()) {
|
|
973
|
+
if (!this.isBrowserRunning(threadId)) {
|
|
931
974
|
return null;
|
|
932
975
|
}
|
|
933
976
|
try {
|
|
934
977
|
const manager = await this.getManagerForThread(threadId);
|
|
935
|
-
return this.getBrowserStateForManager(manager);
|
|
978
|
+
return this.getBrowserStateForManager(manager, threadId);
|
|
936
979
|
} catch {
|
|
937
980
|
return null;
|
|
938
981
|
}
|
|
@@ -945,22 +988,32 @@ var AgentBrowser = class extends MastraBrowser {
|
|
|
945
988
|
const effectiveThreadId = threadId ?? this.getCurrentThread() ?? DEFAULT_THREAD_ID;
|
|
946
989
|
const manager = this.threadManager.getExistingManagerForThread(effectiveThreadId);
|
|
947
990
|
if (!manager) return null;
|
|
948
|
-
return this.getBrowserStateForManager(manager);
|
|
991
|
+
return this.getBrowserStateForManager(manager, effectiveThreadId);
|
|
949
992
|
}
|
|
950
993
|
/**
|
|
951
994
|
* Get browser state from a specific manager instance.
|
|
952
995
|
*/
|
|
953
|
-
getBrowserStateForManager(manager) {
|
|
996
|
+
getBrowserStateForManager(manager, threadId) {
|
|
954
997
|
try {
|
|
998
|
+
const stateKey = this.browserStateKey(threadId);
|
|
955
999
|
const pages = manager.getPages();
|
|
956
1000
|
const activeIndex = manager.getActiveIndex();
|
|
957
1001
|
const tabs = pages.map((page) => ({
|
|
958
1002
|
url: page.url()
|
|
959
1003
|
}));
|
|
960
|
-
|
|
1004
|
+
const activeUrl = tabs[activeIndex]?.url;
|
|
1005
|
+
const previousState = this.threadManager.getSavedBrowserState(stateKey) ?? this.lastBrowserState;
|
|
1006
|
+
const previousUrl = previousState?.tabs[previousState.activeTabIndex]?.url;
|
|
1007
|
+
const activeUrlChangeSource = this.getActiveUrlChangeSource(activeUrl, stateKey) ?? (previousUrl && activeUrl !== previousUrl ? "user" : void 0);
|
|
1008
|
+
const state = {
|
|
961
1009
|
tabs,
|
|
962
|
-
activeTabIndex: activeIndex
|
|
1010
|
+
activeTabIndex: activeIndex,
|
|
1011
|
+
...this.getCloseReason(stateKey) ? { closeReason: this.getCloseReason(stateKey) } : {},
|
|
1012
|
+
...activeUrlChangeSource ? { activeUrlChangeSource } : {}
|
|
963
1013
|
};
|
|
1014
|
+
this.threadManager.updateBrowserState(stateKey, state);
|
|
1015
|
+
this.lastBrowserState = state;
|
|
1016
|
+
return state;
|
|
964
1017
|
} catch {
|
|
965
1018
|
return null;
|
|
966
1019
|
}
|
|
@@ -1015,9 +1068,11 @@ var AgentBrowser = class extends MastraBrowser {
|
|
|
1015
1068
|
timeout: input.timeout ?? this.defaultTimeout,
|
|
1016
1069
|
waitUntil: input.waitUntil ?? "domcontentloaded"
|
|
1017
1070
|
});
|
|
1071
|
+
const url = page.url();
|
|
1072
|
+
this.markActiveUrlChangeSource("agent", url, threadId);
|
|
1018
1073
|
return {
|
|
1019
1074
|
success: true,
|
|
1020
|
-
url
|
|
1075
|
+
url,
|
|
1021
1076
|
title: await page.title(),
|
|
1022
1077
|
hint: "Take a snapshot to see interactive elements and get refs."
|
|
1023
1078
|
};
|
|
@@ -1304,9 +1359,11 @@ var AgentBrowser = class extends MastraBrowser {
|
|
|
1304
1359
|
try {
|
|
1305
1360
|
const page = await this.getPage(threadId);
|
|
1306
1361
|
await page.goBack({ timeout: this.defaultTimeout });
|
|
1362
|
+
const url = page.url();
|
|
1363
|
+
this.markActiveUrlChangeSource("agent", url, threadId);
|
|
1307
1364
|
return {
|
|
1308
1365
|
success: true,
|
|
1309
|
-
url
|
|
1366
|
+
url,
|
|
1310
1367
|
title: await page.title(),
|
|
1311
1368
|
hint: "Take a new snapshot to see the previous page."
|
|
1312
1369
|
};
|
|
@@ -1437,6 +1494,7 @@ var AgentBrowser = class extends MastraBrowser {
|
|
|
1437
1494
|
if (input.url) {
|
|
1438
1495
|
const page = await this.getPage(threadId);
|
|
1439
1496
|
await page.goto(input.url);
|
|
1497
|
+
this.markActiveUrlChangeSource("agent", page.url(), threadId);
|
|
1440
1498
|
}
|
|
1441
1499
|
this.updateSessionBrowserState(threadId);
|
|
1442
1500
|
return {
|
|
@@ -1457,6 +1515,7 @@ var AgentBrowser = class extends MastraBrowser {
|
|
|
1457
1515
|
await this.reconnectScreencastForThread(threadId, "tab switch");
|
|
1458
1516
|
const page = browser.getPage();
|
|
1459
1517
|
const pageUrl = page.url();
|
|
1518
|
+
this.markActiveUrlChangeSource("agent", pageUrl, threadId);
|
|
1460
1519
|
const streamKey = this.getStreamKey(threadId);
|
|
1461
1520
|
const stream = this.activeScreencastStreams.get(streamKey);
|
|
1462
1521
|
if (pageUrl && stream?.isActive()) {
|