SuperCharge Claude Code v1.0.0 - Complete Customization Package
Features: - 30+ Custom Skills (cognitive, development, UI/UX, autonomous agents) - RalphLoop autonomous agent integration - Multi-AI consultation (Qwen) - Agent management system with sync capabilities - Custom hooks for session management - MCP servers integration - Plugin marketplace setup - Comprehensive installation script Components: - Skills: always-use-superpowers, ralph, brainstorming, ui-ux-pro-max, etc. - Agents: 100+ agents across engineering, marketing, product, etc. - Hooks: session-start-superpowers, qwen-consult, ralph-auto-trigger - Commands: /brainstorm, /write-plan, /execute-plan - MCP Servers: zai-mcp-server, web-search-prime, web-reader, zread - Binaries: ralphloop wrapper Installation: ./supercharge.sh
This commit is contained in:
174
skills/dev-browser/extension/entrypoints/background.ts
Normal file
174
skills/dev-browser/extension/entrypoints/background.ts
Normal file
@@ -0,0 +1,174 @@
|
||||
/**
|
||||
* dev-browser Chrome Extension Background Script
|
||||
*
|
||||
* This extension connects to the dev-browser relay server and allows
|
||||
* Playwright automation of the user's existing browser tabs.
|
||||
*/
|
||||
|
||||
import { createLogger } from "../utils/logger";
|
||||
import { TabManager } from "../services/TabManager";
|
||||
import { ConnectionManager } from "../services/ConnectionManager";
|
||||
import { CDPRouter } from "../services/CDPRouter";
|
||||
import { StateManager } from "../services/StateManager";
|
||||
import type { PopupMessage, StateResponse } from "../utils/types";
|
||||
|
||||
export default defineBackground(() => {
|
||||
// Create connection manager first (needed for sendMessage)
|
||||
let connectionManager: ConnectionManager;
|
||||
|
||||
// Create logger with sendMessage function
|
||||
const logger = createLogger((msg) => connectionManager?.send(msg));
|
||||
|
||||
// Create state manager for persistence
|
||||
const stateManager = new StateManager();
|
||||
|
||||
// Create tab manager
|
||||
const tabManager = new TabManager({
|
||||
logger,
|
||||
sendMessage: (msg) => connectionManager.send(msg),
|
||||
});
|
||||
|
||||
// Create CDP router
|
||||
const cdpRouter = new CDPRouter({
|
||||
logger,
|
||||
tabManager,
|
||||
});
|
||||
|
||||
// Create connection manager
|
||||
connectionManager = new ConnectionManager({
|
||||
logger,
|
||||
onMessage: (msg) => cdpRouter.handleCommand(msg),
|
||||
onDisconnect: () => tabManager.detachAll(),
|
||||
});
|
||||
|
||||
// Keep-alive alarm name for Chrome Alarms API
|
||||
const KEEPALIVE_ALARM = "keepAlive";
|
||||
|
||||
// Update badge to show active/inactive state
|
||||
function updateBadge(isActive: boolean): void {
|
||||
chrome.action.setBadgeText({ text: isActive ? "ON" : "" });
|
||||
chrome.action.setBadgeBackgroundColor({ color: "#4CAF50" });
|
||||
}
|
||||
|
||||
// Handle state changes
|
||||
async function handleStateChange(isActive: boolean): Promise<void> {
|
||||
await stateManager.setState({ isActive });
|
||||
if (isActive) {
|
||||
chrome.alarms.create(KEEPALIVE_ALARM, { periodInMinutes: 0.5 });
|
||||
connectionManager.startMaintaining();
|
||||
} else {
|
||||
chrome.alarms.clear(KEEPALIVE_ALARM);
|
||||
connectionManager.disconnect();
|
||||
}
|
||||
updateBadge(isActive);
|
||||
}
|
||||
|
||||
// Handle debugger events
|
||||
function onDebuggerEvent(
|
||||
source: chrome.debugger.DebuggerSession,
|
||||
method: string,
|
||||
params: unknown
|
||||
): void {
|
||||
cdpRouter.handleDebuggerEvent(source, method, params, (msg) => connectionManager.send(msg));
|
||||
}
|
||||
|
||||
function onDebuggerDetach(
|
||||
source: chrome.debugger.Debuggee,
|
||||
reason: `${chrome.debugger.DetachReason}`
|
||||
): void {
|
||||
const tabId = source.tabId;
|
||||
if (!tabId) return;
|
||||
|
||||
logger.debug(`Debugger detached for tab ${tabId}: ${reason}`);
|
||||
tabManager.handleDebuggerDetach(tabId);
|
||||
}
|
||||
|
||||
// Handle messages from popup
|
||||
chrome.runtime.onMessage.addListener(
|
||||
(
|
||||
message: PopupMessage,
|
||||
_sender: chrome.runtime.MessageSender,
|
||||
sendResponse: (response: StateResponse) => void
|
||||
) => {
|
||||
if (message.type === "getState") {
|
||||
(async () => {
|
||||
const state = await stateManager.getState();
|
||||
const isConnected = await connectionManager.checkConnection();
|
||||
sendResponse({
|
||||
isActive: state.isActive,
|
||||
isConnected,
|
||||
});
|
||||
})();
|
||||
return true; // Async response
|
||||
}
|
||||
|
||||
if (message.type === "setState") {
|
||||
(async () => {
|
||||
await handleStateChange(message.isActive);
|
||||
const state = await stateManager.getState();
|
||||
const isConnected = await connectionManager.checkConnection();
|
||||
sendResponse({
|
||||
isActive: state.isActive,
|
||||
isConnected,
|
||||
});
|
||||
})();
|
||||
return true; // Async response
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
);
|
||||
|
||||
// Set up event listeners
|
||||
|
||||
chrome.tabs.onRemoved.addListener((tabId) => {
|
||||
if (tabManager.has(tabId)) {
|
||||
logger.debug("Tab closed:", tabId);
|
||||
tabManager.detach(tabId, false);
|
||||
}
|
||||
});
|
||||
|
||||
// Register debugger event listeners
|
||||
chrome.debugger.onEvent.addListener(onDebuggerEvent);
|
||||
chrome.debugger.onDetach.addListener(onDebuggerDetach);
|
||||
|
||||
// Reset any stale debugger connections on startup
|
||||
chrome.debugger.getTargets().then((targets) => {
|
||||
const attached = targets.filter((t) => t.tabId && t.attached);
|
||||
if (attached.length > 0) {
|
||||
logger.log(`Detaching ${attached.length} stale debugger connections`);
|
||||
for (const target of attached) {
|
||||
chrome.debugger.detach({ tabId: target.tabId }).catch(() => {});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
logger.log("Extension initialized");
|
||||
|
||||
// Initialize from stored state
|
||||
stateManager.getState().then((state) => {
|
||||
updateBadge(state.isActive);
|
||||
if (state.isActive) {
|
||||
// Create keep-alive alarm only when extension is active
|
||||
chrome.alarms.create(KEEPALIVE_ALARM, { periodInMinutes: 0.5 });
|
||||
connectionManager.startMaintaining();
|
||||
}
|
||||
});
|
||||
|
||||
// Set up Chrome Alarms keep-alive listener
|
||||
// This ensures the connection is maintained even after service worker unloads
|
||||
chrome.alarms.onAlarm.addListener(async (alarm) => {
|
||||
if (alarm.name === KEEPALIVE_ALARM) {
|
||||
const state = await stateManager.getState();
|
||||
|
||||
if (state.isActive) {
|
||||
const isConnected = connectionManager.isConnected();
|
||||
|
||||
if (!isConnected) {
|
||||
logger.debug("Keep-alive: Connection lost, restarting...");
|
||||
connectionManager.startMaintaining();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user