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:
211
skills/dev-browser/extension/services/CDPRouter.ts
Normal file
211
skills/dev-browser/extension/services/CDPRouter.ts
Normal file
@@ -0,0 +1,211 @@
|
||||
/**
|
||||
* CDPRouter - Routes CDP commands to the correct tab.
|
||||
*/
|
||||
|
||||
import type { Logger } from "../utils/logger";
|
||||
import type { TabManager } from "./TabManager";
|
||||
import type { ExtensionCommandMessage, TabInfo } from "../utils/types";
|
||||
|
||||
export interface CDPRouterDeps {
|
||||
logger: Logger;
|
||||
tabManager: TabManager;
|
||||
}
|
||||
|
||||
export class CDPRouter {
|
||||
private logger: Logger;
|
||||
private tabManager: TabManager;
|
||||
private devBrowserGroupId: number | null = null;
|
||||
|
||||
constructor(deps: CDPRouterDeps) {
|
||||
this.logger = deps.logger;
|
||||
this.tabManager = deps.tabManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets or creates the "Dev Browser" tab group, returning its ID.
|
||||
*/
|
||||
private async getOrCreateDevBrowserGroup(tabId: number): Promise<number> {
|
||||
// If we have a cached group ID, verify it still exists
|
||||
if (this.devBrowserGroupId !== null) {
|
||||
try {
|
||||
await chrome.tabGroups.get(this.devBrowserGroupId);
|
||||
// Group exists, add tab to it
|
||||
await chrome.tabs.group({ tabIds: [tabId], groupId: this.devBrowserGroupId });
|
||||
return this.devBrowserGroupId;
|
||||
} catch {
|
||||
// Group no longer exists, reset cache
|
||||
this.devBrowserGroupId = null;
|
||||
}
|
||||
}
|
||||
|
||||
// Create a new group with this tab
|
||||
const groupId = await chrome.tabs.group({ tabIds: [tabId] });
|
||||
await chrome.tabGroups.update(groupId, {
|
||||
title: "Dev Browser",
|
||||
color: "blue",
|
||||
});
|
||||
this.devBrowserGroupId = groupId;
|
||||
return groupId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle an incoming CDP command from the relay.
|
||||
*/
|
||||
async handleCommand(msg: ExtensionCommandMessage): Promise<unknown> {
|
||||
if (msg.method !== "forwardCDPCommand") return;
|
||||
|
||||
let targetTabId: number | undefined;
|
||||
let targetTab: TabInfo | undefined;
|
||||
|
||||
// Find target tab by sessionId
|
||||
if (msg.params.sessionId) {
|
||||
const found = this.tabManager.getBySessionId(msg.params.sessionId);
|
||||
if (found) {
|
||||
targetTabId = found.tabId;
|
||||
targetTab = found.tab;
|
||||
}
|
||||
}
|
||||
|
||||
// Check child sessions (iframes, workers)
|
||||
if (!targetTab && msg.params.sessionId) {
|
||||
const parentTabId = this.tabManager.getParentTabId(msg.params.sessionId);
|
||||
if (parentTabId) {
|
||||
targetTabId = parentTabId;
|
||||
targetTab = this.tabManager.get(parentTabId);
|
||||
this.logger.debug(
|
||||
"Found parent tab for child session:",
|
||||
msg.params.sessionId,
|
||||
"tabId:",
|
||||
parentTabId
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Find by targetId in params
|
||||
if (
|
||||
!targetTab &&
|
||||
msg.params.params &&
|
||||
typeof msg.params.params === "object" &&
|
||||
"targetId" in msg.params.params
|
||||
) {
|
||||
const found = this.tabManager.getByTargetId(msg.params.params.targetId as string);
|
||||
if (found) {
|
||||
targetTabId = found.tabId;
|
||||
targetTab = found.tab;
|
||||
}
|
||||
}
|
||||
|
||||
const debuggee = targetTabId ? { tabId: targetTabId } : undefined;
|
||||
|
||||
// Handle special commands
|
||||
switch (msg.params.method) {
|
||||
case "Runtime.enable": {
|
||||
if (!debuggee) {
|
||||
throw new Error(
|
||||
`No debuggee found for Runtime.enable (sessionId: ${msg.params.sessionId})`
|
||||
);
|
||||
}
|
||||
// Disable and re-enable to reset state
|
||||
try {
|
||||
await chrome.debugger.sendCommand(debuggee, "Runtime.disable");
|
||||
await new Promise((resolve) => setTimeout(resolve, 200));
|
||||
} catch {
|
||||
// Ignore errors
|
||||
}
|
||||
return await chrome.debugger.sendCommand(debuggee, "Runtime.enable", msg.params.params);
|
||||
}
|
||||
|
||||
case "Target.createTarget": {
|
||||
const url = (msg.params.params?.url as string) || "about:blank";
|
||||
this.logger.debug("Creating new tab with URL:", url);
|
||||
const tab = await chrome.tabs.create({ url, active: false });
|
||||
if (!tab.id) throw new Error("Failed to create tab");
|
||||
|
||||
// Add tab to "Dev Browser" group
|
||||
await this.getOrCreateDevBrowserGroup(tab.id);
|
||||
|
||||
await new Promise((resolve) => setTimeout(resolve, 100));
|
||||
const targetInfo = await this.tabManager.attach(tab.id);
|
||||
return { targetId: targetInfo.targetId };
|
||||
}
|
||||
|
||||
case "Target.closeTarget": {
|
||||
if (!targetTabId) {
|
||||
this.logger.log(`Target not found: ${msg.params.params?.targetId}`);
|
||||
return { success: false };
|
||||
}
|
||||
await chrome.tabs.remove(targetTabId);
|
||||
return { success: true };
|
||||
}
|
||||
|
||||
case "Target.activateTarget": {
|
||||
if (!targetTabId) {
|
||||
this.logger.log(`Target not found for activation: ${msg.params.params?.targetId}`);
|
||||
return {};
|
||||
}
|
||||
await chrome.tabs.update(targetTabId, { active: true });
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
if (!debuggee || !targetTab) {
|
||||
throw new Error(
|
||||
`No tab found for method ${msg.params.method} sessionId: ${msg.params.sessionId}`
|
||||
);
|
||||
}
|
||||
|
||||
this.logger.debug("CDP command:", msg.params.method, "for tab:", targetTabId);
|
||||
|
||||
const debuggerSession: chrome.debugger.DebuggerSession = {
|
||||
...debuggee,
|
||||
sessionId: msg.params.sessionId !== targetTab.sessionId ? msg.params.sessionId : undefined,
|
||||
};
|
||||
|
||||
return await chrome.debugger.sendCommand(debuggerSession, msg.params.method, msg.params.params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle debugger events from Chrome.
|
||||
*/
|
||||
handleDebuggerEvent(
|
||||
source: chrome.debugger.DebuggerSession,
|
||||
method: string,
|
||||
params: unknown,
|
||||
sendMessage: (msg: unknown) => void
|
||||
): void {
|
||||
const tab = source.tabId ? this.tabManager.get(source.tabId) : undefined;
|
||||
if (!tab) return;
|
||||
|
||||
this.logger.debug("Forwarding CDP event:", method, "from tab:", source.tabId);
|
||||
|
||||
// Track child sessions
|
||||
if (
|
||||
method === "Target.attachedToTarget" &&
|
||||
params &&
|
||||
typeof params === "object" &&
|
||||
"sessionId" in params
|
||||
) {
|
||||
const sessionId = (params as { sessionId: string }).sessionId;
|
||||
this.tabManager.trackChildSession(sessionId, source.tabId!);
|
||||
}
|
||||
|
||||
if (
|
||||
method === "Target.detachedFromTarget" &&
|
||||
params &&
|
||||
typeof params === "object" &&
|
||||
"sessionId" in params
|
||||
) {
|
||||
const sessionId = (params as { sessionId: string }).sessionId;
|
||||
this.tabManager.untrackChildSession(sessionId);
|
||||
}
|
||||
|
||||
sendMessage({
|
||||
method: "forwardCDPEvent",
|
||||
params: {
|
||||
sessionId: source.sessionId || tab.sessionId,
|
||||
method,
|
||||
params,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user