@@ -25,6 +25,7 @@ import { DEFAULT_SYSTEM_PROMPT } from './shared';
25
25
import { InMemoryTransport } from '@modelcontextprotocol/sdk/inMemory.js' ;
26
26
import { Client } from '@modelcontextprotocol/sdk/client/index.js' ;
27
27
import { GUIAgent } from './gui-agent' ;
28
+ import { LocalBrowser } from '@agent-infra/browser' ;
28
29
29
30
/**
30
31
* A Agent TARS that uses in-memory MCP tool call
@@ -36,6 +37,7 @@ export class AgentTARS extends MCPAgent {
36
37
private mcpServers : BuiltInMCPServers = { } ;
37
38
private inMemoryMCPClients : Partial < Record < BuiltInMCPServerName , Client > > = { } ;
38
39
private guiAgent ?: GUIAgent ;
40
+ private sharedBrowser ?: LocalBrowser ;
39
41
40
42
// Message history storage for experimental dump feature
41
43
private traces : Array < {
@@ -91,15 +93,6 @@ export class AgentTARS extends MCPAgent {
91
93
command : 'npx' ,
92
94
args : [ '-y' , '@agent-infra/mcp-server-browser' ] ,
93
95
} ,
94
- // Only include browser server if GUI agent is not enabled
95
- // ...(tarsOptions.browser?.controlSolution !== 'gui-agent'
96
- // ? {
97
- // browser: {
98
- // command: 'npx',
99
- // args: ['-y', '@agent-infra/mcp-server-browser'],
100
- // },
101
- // }
102
- // : {}),
103
96
filesystem : {
104
97
command : 'npx' ,
105
98
args : [ '-y' , '@agent-infra/mcp-server-filesystem' , workingDirectory ] ,
@@ -137,31 +130,69 @@ export class AgentTARS extends MCPAgent {
137
130
async initialize ( ) : Promise < void > {
138
131
this . logger . info ( 'Initializing AgentTARS ...' ) ;
139
132
140
- const initPromises : Promise < void > [ ] = [
133
+ try {
134
+ // First initialize shared browser instance
135
+ await this . initializeSharedBrowser ( ) ;
136
+
137
+ const initPromises : Promise < void > [ ] = [
138
+ /**
139
+ * Base mcp-agent's initialization process.
140
+ */
141
+ super . initialize ( ) ,
142
+ ] ;
143
+
141
144
/**
142
- * Base mcp-agent's initialization process.
145
+ * Initialize GUI Agent if enabled
143
146
*/
144
- super . initialize ( ) ,
145
- ] ;
146
-
147
- /**
148
- * Initialize GUI Agent if enabled
149
- */
150
- if ( this . tarsOptions . browser ?. controlSolution === 'gui-agent' ) {
151
- await this . initializeGUIAgent ( ) ;
152
- }
147
+ if ( this . tarsOptions . browser ?. controlSolution === 'gui-agent' ) {
148
+ await this . initializeGUIAgent ( ) ;
149
+ }
150
+
151
+ /**
152
+ * In-process MCP initialization.
153
+ */
154
+ if ( this . tarsOptions . mcpImpl === 'in-memory' ) {
155
+ initPromises . push ( this . initializeInMemoryMCPForBuiltInMCPServers ( ) ) ;
156
+ }
153
157
154
- /**
155
- * In-process MCP initialization.
156
- */
157
- if ( this . tarsOptions . mcpImpl === 'in-memory' ) {
158
- initPromises . push ( this . initializeInMemoryMCPForBuiltInMCPServers ( ) ) ;
158
+ await Promise . all ( initPromises ) ;
159
+ this . logger . info ( '✅ AgentTARS initialization complete' ) ;
160
+ // Log all registered tools in a beautiful format
161
+ this . logRegisteredTools ( ) ;
162
+ } catch ( error ) {
163
+ this . logger . error ( '❌ Failed to initialize AgentTARS:' , error ) ;
164
+ await this . cleanup ( ) ;
165
+ throw error ;
159
166
}
167
+ }
168
+
169
+ /**
170
+ * Initialize shared browser instance
171
+ */
172
+ /**
173
+ * Initialize shared browser instance
174
+ */
175
+ private async initializeSharedBrowser ( ) : Promise < void > {
176
+ try {
177
+ this . logger . info ( '🌐 Initializing shared browser instance...' ) ;
178
+
179
+ this . sharedBrowser = new LocalBrowser ( {
180
+ logger : this . logger . spawn ( 'SharedBrowser' ) ,
181
+ } ) ;
182
+
183
+ // Configure browser based on options
184
+ const launchOptions = {
185
+ headless : this . tarsOptions . browser ?. headless ,
186
+ } ;
187
+
188
+ // Launch the browser
189
+ await this . sharedBrowser . launch ( launchOptions ) ;
160
190
161
- await Promise . all ( initPromises ) ;
162
- this . logger . info ( '✅ AgentTARS initialization complete' ) ;
163
- // Log all registered tools in a beautiful format
164
- this . logRegisteredTools ( ) ;
191
+ this . logger . success ( '✅ Shared browser instance initialized with initial page' ) ;
192
+ } catch ( error ) {
193
+ this . logger . error ( `❌ Failed to initialize shared browser: ${ error } ` ) ;
194
+ throw error ;
195
+ }
165
196
}
166
197
167
198
/**
@@ -226,10 +257,11 @@ export class AgentTARS extends MCPAgent {
226
257
try {
227
258
this . logger . info ( '🖥️ Initializing GUI Agent for visual browser control' ) ;
228
259
229
- // Create GUI Agent instance
260
+ // Create GUI Agent instance with shared browser
230
261
this . guiAgent = new GUIAgent ( {
231
- logger : this . logger . spawn ( 'GUIAgent' ) ,
262
+ logger : this . logger ,
232
263
headless : this . tarsOptions . browser ?. headless ,
264
+ externalBrowser : this . sharedBrowser , // Pass the shared browser instance
233
265
} ) ;
234
266
235
267
// Initialize the browser
@@ -256,10 +288,6 @@ export class AgentTARS extends MCPAgent {
256
288
const moduleImports = [
257
289
this . dynamicImport ( '@agent-infra/mcp-server-search' ) ,
258
290
this . dynamicImport ( '@agent-infra/mcp-server-browser' ) ,
259
- // Only import browser module if GUI agent is not enabled
260
- // ...(this.tarsOptions.browser?.controlSolution !== 'gui-agent'
261
- // ? [this.dynamicImport('@agent-infra/mcp-server-browser')]
262
- // : [Promise.resolve({ default: { createServer: () => undefined } })]),
263
291
this . dynamicImport ( '@agent-infra/mcp-server-filesystem' ) ,
264
292
this . dynamicImport ( '@agent-infra/mcp-server-commands' ) ,
265
293
] ;
@@ -280,20 +308,11 @@ export class AgentTARS extends MCPAgent {
280
308
baseUrl : this . tarsOptions . search ! . baseUrl ,
281
309
} ) ,
282
310
browser : browserModule . default . createServer ( {
311
+ externalBrowser : this . sharedBrowser , // Pass the shared browser instance
283
312
launchOptions : {
284
313
headless : this . tarsOptions . browser ?. headless ,
285
314
} ,
286
315
} ) ,
287
- // Only create browser server if GUI agent is not enabled
288
- // ...(this.tarsOptions.browser?.controlSolution !== 'gui-agent'
289
- // ? {
290
- // browser: browserModule.default.createServer({
291
- // launchOptions: {
292
- // headless: this.tarsOptions.browser?.headless,
293
- // },
294
- // }),
295
- // }
296
- // : {}),
297
316
filesystem : filesystemModule . default . createServer ( {
298
317
allowedDirectories : [ this . workingDirectory ] ,
299
318
} ) ,
@@ -462,13 +481,23 @@ export class AgentTARS extends MCPAgent {
462
481
}
463
482
}
464
483
484
+ // Finally close the shared browser instance
485
+ if ( this . sharedBrowser ) {
486
+ cleanupPromises . push (
487
+ this . sharedBrowser . close ( ) . catch ( ( error ) => {
488
+ this . logger . warn ( `⚠️ Error while closing shared browser: ${ error } ` ) ;
489
+ } ) ,
490
+ ) ;
491
+ }
492
+
465
493
// Wait for all cleanup operations to complete
466
494
await Promise . allSettled ( cleanupPromises ) ;
467
495
468
496
// Clear references
469
497
this . inMemoryMCPClients = { } ;
470
498
this . mcpServers = { } ;
471
499
this . guiAgent = undefined ;
500
+ this . sharedBrowser = undefined ;
472
501
473
502
this . logger . info ( '✅ Cleanup complete' ) ;
474
503
}
0 commit comments