Add ping/pong keep-alive to prevent service worker termination

This commit is contained in:
Tommy D. Rossi
2025-12-31 16:15:17 +01:00
parent 02fda90578
commit be1b9514d3
4 changed files with 39 additions and 5 deletions
+1 -1
View File
@@ -1,7 +1,7 @@
{ {
"manifest_version": 3, "manifest_version": 3,
"name": "Playwriter MCP", "name": "Playwriter MCP",
"version": "0.0.61", "version": "0.0.64",
"description": "Automate your Browser using Cursor, Claude, VS Code. More capable and context efficient than Playwright MCP.", "description": "Automate your Browser using Cursor, Claude, VS Code. More capable and context efficient than Playwright MCP.",
"permissions": ["debugger", "tabGroups", "contextMenus", "tabs"], "permissions": ["debugger", "tabGroups", "contextMenus", "tabs"],
"host_permissions": ["<all_urls>"], "host_permissions": ["<all_urls>"],
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "mcp-extension", "name": "mcp-extension",
"version": "0.0.61", "version": "0.0.64",
"description": "Playwright MCP Browser Extension", "description": "Playwright MCP Browser Extension",
"private": true, "private": true,
"repository": { "repository": {
+23 -2
View File
@@ -41,6 +41,23 @@ export async function startPlayWriterCDPRelayServer({ port = 19988, host = '127.
reject: (error: Error) => void reject: (error: Error) => void
}>() }>()
let extensionMessageId = 0 let extensionMessageId = 0
let extensionPingInterval: ReturnType<typeof setInterval> | null = null
function startExtensionPing() {
if (extensionPingInterval) {
clearInterval(extensionPingInterval)
}
extensionPingInterval = setInterval(() => {
extensionWs?.send(JSON.stringify({ method: 'ping' }))
}, 5000)
}
function stopExtensionPing() {
if (extensionPingInterval) {
clearInterval(extensionPingInterval)
extensionPingInterval = null
}
}
function logCdpMessage({ function logCdpMessage({
direction, direction,
@@ -504,6 +521,7 @@ export async function startPlayWriterCDPRelayServer({ port = 19988, host = '127.
} }
extensionWs = ws extensionWs = ws
startExtensionPing()
logger?.log('Extension connected with clean state') logger?.log('Extension connected with clean state')
}, },
@@ -517,7 +535,7 @@ export async function startPlayWriterCDPRelayServer({ port = 19988, host = '127.
return return
} }
if ('id' in message) { if (message.id !== undefined) {
const pending = extensionPendingRequests.get(message.id) const pending = extensionPendingRequests.get(message.id)
if (!pending) { if (!pending) {
logger?.log('Unexpected response with id:', message.id) logger?.log('Unexpected response with id:', message.id)
@@ -531,6 +549,8 @@ export async function startPlayWriterCDPRelayServer({ port = 19988, host = '127.
} else { } else {
pending.resolve(message.result) pending.resolve(message.result)
} }
} else if (message.method === 'pong') {
// Keep-alive response, nothing to do
} else if (message.method === 'log') { } else if (message.method === 'log') {
const { level, args } = message.params const { level, args } = message.params
const logFn = (logger as any)?.[level] || logger?.log const logFn = (logger as any)?.[level] || logger?.log
@@ -681,7 +701,8 @@ export async function startPlayWriterCDPRelayServer({ port = 19988, host = '127.
}, },
onClose(event, ws) { onClose(event, ws) {
logger?.log('Extension disconnected') logger?.log(`Extension disconnected: code=${event.code} reason=${event.reason || 'none'}`)
stopExtensionPing()
// If this is an old connection closing after we've already established a new one, // If this is an old connection closing after we've already established a new one,
// don't clear the global state // don't clear the global state
+14 -1
View File
@@ -19,6 +19,7 @@ export type ExtensionCommandMessage = ForwardCDPCommand
export type ExtensionResponseMessage = { export type ExtensionResponseMessage = {
id: number id: number
method?: undefined
result?: any result?: any
error?: string error?: string
} }
@@ -30,6 +31,7 @@ export type ExtensionResponseMessage = {
export type ExtensionEventMessage = export type ExtensionEventMessage =
{ {
[K in keyof ProtocolMapping.Events]: { [K in keyof ProtocolMapping.Events]: {
id?: undefined
method: 'forwardCDPEvent' method: 'forwardCDPEvent'
params: { params: {
method: CDPEventFor<K>['method'] method: CDPEventFor<K>['method']
@@ -40,6 +42,7 @@ export type ExtensionEventMessage =
}[keyof ProtocolMapping.Events] }[keyof ProtocolMapping.Events]
export type ExtensionLogMessage = { export type ExtensionLogMessage = {
id?: undefined
method: 'log' method: 'log'
params: { params: {
level: 'log' | 'debug' | 'info' | 'warn' | 'error' level: 'log' | 'debug' | 'info' | 'warn' | 'error'
@@ -47,4 +50,14 @@ export type ExtensionLogMessage = {
} }
} }
export type ExtensionMessage = ExtensionResponseMessage | ExtensionEventMessage | ExtensionLogMessage export type ExtensionPongMessage = {
id?: undefined
method: 'pong'
}
export type ServerPingMessage = {
method: 'ping'
id?: undefined
}
export type ExtensionMessage = ExtensionResponseMessage | ExtensionEventMessage | ExtensionLogMessage | ExtensionPongMessage