claude-playwright
Version:
Seamless integration between Claude Code and Playwright MCP for efficient browser automation and testing
200 lines • 8.06 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.SessionHelper = void 0;
const session_manager_1 = require("../core/session-manager");
/**
* Session Helper for integrating Playwright with Session Management
* Provides automatic session backup, loading, and rotation
*/
class SessionHelper {
constructor(workingDir) {
this.sessionManager = new session_manager_1.SessionManager(workingDir);
}
/**
* Initialize session helper with Playwright context and page
*/
async init(context, page) {
this.context = context;
this.page = page;
}
/**
* Save current browser session
*/
async saveCurrentSession(sessionName, options) {
if (!this.context || !this.page) {
throw new Error('SessionHelper not initialized. Call init() first.');
}
try {
// Get current storage state
const storageState = await this.context.storageState();
let metadata;
if (options?.includeMetadata) {
// Gather metadata from current page
const url = this.page.url();
const userAgent = await this.page.evaluate(() => {
return globalThis.navigator?.userAgent || 'Unknown';
});
const viewport = this.page.viewportSize();
metadata = {
url,
userAgent,
viewport: viewport || { width: 1920, height: 1080 },
timestamp: Date.now()
};
}
// Save session with metadata
await this.sessionManager.saveSession(sessionName, storageState, {
browserProfile: options?.browserProfile,
metadata
});
this.currentSession = {
sessionName,
browserProfile: options?.browserProfile,
autoSave: true
};
return true;
}
catch (error) {
console.error(`Failed to save session '${sessionName}':`, error.message);
return false;
}
}
/**
* Create a new browser context with a saved session
*/
static async createContextWithSession(browser, sessionName, workingDir) {
const sessionManager = new session_manager_1.SessionManager(workingDir);
try {
// Check if session is valid
if (!await sessionManager.isSessionValid(sessionName)) {
console.warn(`Cannot create context: Session '${sessionName}' is expired or doesn't exist`);
return null;
}
// Load storage state
const storageState = await sessionManager.loadSession(sessionName);
const sessionData = await sessionManager.getSessionData(sessionName);
// Create context with storage state
const contextOptions = {
storageState
};
// Apply metadata if available
if (sessionData.metadata) {
if (sessionData.metadata.userAgent) {
contextOptions.userAgent = sessionData.metadata.userAgent;
}
if (sessionData.metadata.viewport) {
contextOptions.viewport = sessionData.metadata.viewport;
}
}
const context = await browser.newContext(contextOptions);
console.log(`Context created with session: ${sessionName}`);
return context;
}
catch (error) {
console.error(`Failed to create context with session '${sessionName}':`, error.message);
return null;
}
}
/**
* Create context with auto-loaded session from environment (MCP integration)
*/
static async createContextWithMCPSession(browser) {
// Check for auto-loaded session from MCP integration
const activeSessionName = process.env.PLAYWRIGHT_ACTIVE_SESSION;
const storageStateData = process.env.PLAYWRIGHT_SESSION_STORAGE_STATE;
const activeProfile = process.env.PLAYWRIGHT_ACTIVE_PROFILE;
const lastUrl = process.env.PLAYWRIGHT_LAST_URL;
const viewport = process.env.PLAYWRIGHT_VIEWPORT;
const userAgent = process.env.PLAYWRIGHT_USER_AGENT;
if (!storageStateData || !activeSessionName) {
console.log('No MCP session data available, creating fresh context');
return null;
}
try {
const storageState = JSON.parse(storageStateData);
const contextOptions = {
storageState
};
// Apply viewport from session metadata
if (viewport) {
try {
contextOptions.viewport = JSON.parse(viewport);
}
catch (error) {
console.warn('Could not parse viewport from session metadata');
}
}
// Apply user agent from session metadata
if (userAgent) {
contextOptions.userAgent = userAgent;
}
const context = await browser.newContext(contextOptions);
console.log(`🎭 Context created with MCP session: ${activeSessionName}`);
if (activeProfile) {
console.log(`🎨 Using profile: ${activeProfile}`);
}
if (lastUrl) {
console.log(`🌐 Last visited: ${lastUrl}`);
}
return context;
}
catch (error) {
console.error('Failed to create context with MCP session:', error.message);
return null;
}
}
/**
* Save session with MCP integration awareness
*/
async saveMCPSession(sessionName, options) {
const result = await this.saveCurrentSession(sessionName, options);
if (result && options?.updateEnvironment) {
// Update environment variables for ongoing MCP session
process.env.PLAYWRIGHT_ACTIVE_SESSION = sessionName;
if (options.browserProfile) {
process.env.PLAYWRIGHT_ACTIVE_PROFILE = options.browserProfile;
}
if (this.page && options.includeMetadata) {
process.env.PLAYWRIGHT_LAST_URL = this.page.url();
}
console.log(`🔄 Updated MCP environment for session: ${sessionName}`);
}
return result;
}
/**
* Auto-save session periodically (for MCP background operations)
*/
startAutoSave(intervalMinutes = 30) {
if (!this.context || !this.page) {
console.warn('Cannot start auto-save: SessionHelper not initialized');
return null;
}
const intervalMs = intervalMinutes * 60 * 1000;
return setInterval(async () => {
try {
const activeSessionName = process.env.PLAYWRIGHT_ACTIVE_SESSION;
if (activeSessionName) {
const autoSaveName = `${activeSessionName}-autosave-${Date.now()}`;
await this.saveCurrentSession(autoSaveName, {
includeMetadata: true,
browserProfile: process.env.PLAYWRIGHT_ACTIVE_PROFILE
});
console.log(`Auto-saved session: ${autoSaveName}`);
}
else {
// Create a new auto-save session
const autoSaveName = `autosave-${Date.now()}`;
await this.saveCurrentSession(autoSaveName, {
includeMetadata: true
});
console.log(`Created auto-save session: ${autoSaveName}`);
}
}
catch (error) {
console.warn('Auto-save failed:', error.message);
}
}, intervalMs);
}
}
exports.SessionHelper = SessionHelper;
//# sourceMappingURL=session-helper.js.map
;