add support for tab groups. green
This commit is contained in:
@@ -3,7 +3,7 @@
|
|||||||
"name": "Playwriter MCP",
|
"name": "Playwriter MCP",
|
||||||
"version": "0.0.52",
|
"version": "0.0.52",
|
||||||
"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"],
|
"permissions": ["debugger", "tabGroups"],
|
||||||
"host_permissions": ["<all_urls>"],
|
"host_permissions": ["<all_urls>"],
|
||||||
"background": {
|
"background": {
|
||||||
"service_worker": "lib/background.mjs",
|
"service_worker": "lib/background.mjs",
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ const RELAY_URL = 'ws://localhost:19988/extension'
|
|||||||
let ws: WebSocket | null = null
|
let ws: WebSocket | null = null
|
||||||
let childSessions: Map<string, number> = new Map()
|
let childSessions: Map<string, number> = new Map()
|
||||||
let nextSessionId = 1
|
let nextSessionId = 1
|
||||||
|
let playwriterGroupId: number | null = null
|
||||||
|
|
||||||
const store = createStore<ExtensionState>(() => ({
|
const store = createStore<ExtensionState>(() => ({
|
||||||
tabs: new Map(),
|
tabs: new Map(),
|
||||||
@@ -94,6 +95,46 @@ function sendMessage(message: any): void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function addTabToGroup(tabId: number): Promise<void> {
|
||||||
|
try {
|
||||||
|
if (playwriterGroupId !== null) {
|
||||||
|
const existingGroups = await chrome.tabGroups.query({ title: 'playwriter' })
|
||||||
|
if (!existingGroups.some((g) => g.id === playwriterGroupId)) {
|
||||||
|
playwriterGroupId = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (playwriterGroupId === null) {
|
||||||
|
playwriterGroupId = await chrome.tabs.group({ tabIds: [tabId] })
|
||||||
|
await chrome.tabGroups.update(playwriterGroupId, { title: 'playwriter', color: 'green' })
|
||||||
|
logger.debug('Created tab group:', playwriterGroupId)
|
||||||
|
} else {
|
||||||
|
await chrome.tabs.group({ tabIds: [tabId], groupId: playwriterGroupId })
|
||||||
|
logger.debug('Added tab to existing group:', tabId)
|
||||||
|
}
|
||||||
|
} catch (error: any) {
|
||||||
|
logger.debug('Failed to add tab to group:', error.message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function removeTabFromGroup(tabId: number): Promise<void> {
|
||||||
|
try {
|
||||||
|
await chrome.tabs.ungroup(tabId)
|
||||||
|
logger.debug('Removed tab from group:', tabId)
|
||||||
|
|
||||||
|
if (playwriterGroupId !== null) {
|
||||||
|
const groups = await chrome.tabGroups.query({ title: 'playwriter' })
|
||||||
|
const group = groups.find((g) => g.id === playwriterGroupId)
|
||||||
|
if (!group) {
|
||||||
|
playwriterGroupId = null
|
||||||
|
logger.debug('Tab group was deleted')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error: any) {
|
||||||
|
logger.debug('Failed to remove tab from group:', error.message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function getTabBySessionId(sessionId: string): { tabId: number; tab: TabInfo } | undefined {
|
function getTabBySessionId(sessionId: string): { tabId: number; tab: TabInfo } | undefined {
|
||||||
for (const [tabId, tab] of store.getState().tabs) {
|
for (const [tabId, tab] of store.getState().tabs) {
|
||||||
if (tab.sessionId === sessionId) {
|
if (tab.sessionId === sessionId) {
|
||||||
@@ -299,6 +340,7 @@ async function attachTab(tabId: number): Promise<Protocol.Target.TargetInfo> {
|
|||||||
})
|
})
|
||||||
|
|
||||||
logger.debug('Tab attached successfully:', tabId, 'sessionId:', sessionId, 'targetId:', targetInfo.targetId)
|
logger.debug('Tab attached successfully:', tabId, 'sessionId:', sessionId, 'targetId:', targetInfo.targetId)
|
||||||
|
await addTabToGroup(tabId)
|
||||||
return targetInfo
|
return targetInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -311,6 +353,8 @@ function detachTab(tabId: number, shouldDetachDebugger: boolean): void {
|
|||||||
|
|
||||||
logger.debug('Detaching tab:', tabId, 'sessionId:', tab.sessionId, 'shouldDetach:', shouldDetachDebugger)
|
logger.debug('Detaching tab:', tabId, 'sessionId:', tab.sessionId, 'shouldDetach:', shouldDetachDebugger)
|
||||||
|
|
||||||
|
void removeTabFromGroup(tabId)
|
||||||
|
|
||||||
sendMessage({
|
sendMessage({
|
||||||
method: 'forwardCDPEvent',
|
method: 'forwardCDPEvent',
|
||||||
params: {
|
params: {
|
||||||
@@ -353,6 +397,7 @@ function closeConnection(reason: string): void {
|
|||||||
|
|
||||||
store.setState({ tabs: new Map(), connectionState: 'disconnected', errorText: undefined })
|
store.setState({ tabs: new Map(), connectionState: 'disconnected', errorText: undefined })
|
||||||
childSessions.clear()
|
childSessions.clear()
|
||||||
|
playwriterGroupId = null
|
||||||
|
|
||||||
if (ws) {
|
if (ws) {
|
||||||
ws.close(1000, reason)
|
ws.close(1000, reason)
|
||||||
@@ -375,6 +420,7 @@ function handleConnectionClose(reason: string, code: number): void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
childSessions.clear()
|
childSessions.clear()
|
||||||
|
playwriterGroupId = null
|
||||||
ws = null
|
ws = null
|
||||||
|
|
||||||
if (reason === 'Extension Replaced' || code === 4001) {
|
if (reason === 'Extension Replaced' || code === 4001) {
|
||||||
|
|||||||
Reference in New Issue
Block a user