diff --git a/skills/baoyu-danger-x-to-markdown/scripts/vendor/baoyu-chrome-cdp/src/index.ts b/skills/baoyu-danger-x-to-markdown/scripts/vendor/baoyu-chrome-cdp/src/index.ts index 1fcd241..ee4fd71 100644 --- a/skills/baoyu-danger-x-to-markdown/scripts/vendor/baoyu-chrome-cdp/src/index.ts +++ b/skills/baoyu-danger-x-to-markdown/scripts/vendor/baoyu-chrome-cdp/src/index.ts @@ -43,6 +43,18 @@ type FindExistingChromeDebugPortOptions = { timeoutMs?: number; }; +export type ChromeChannel = "stable" | "beta" | "canary" | "dev"; + +export type DiscoveredChrome = { + port: number; + wsUrl: string; +}; + +type DiscoverRunningChromeOptions = { + channels?: ChromeChannel[]; + timeoutMs?: number; +}; + type LaunchChromeOptions = { chromePath: string; profileDir: string; @@ -173,16 +185,32 @@ async function isDebugPortReady(port: number, timeoutMs = 3_000): Promise { + return new Promise((resolve) => { + const socket = new net.Socket(); + const timer = setTimeout(() => { socket.destroy(); resolve(false); }, timeoutMs); + socket.once("connect", () => { clearTimeout(timer); socket.destroy(); resolve(true); }); + socket.once("error", () => { clearTimeout(timer); resolve(false); }); + socket.connect(port, "127.0.0.1"); + }); +} + +function parseDevToolsActivePort(filePath: string): { port: number; wsPath: string } | null { + try { + const content = fs.readFileSync(filePath, "utf-8"); + const lines = content.split(/\r?\n/); + const port = Number.parseInt(lines[0]?.trim() ?? "", 10); + const wsPath = lines[1]?.trim(); + if (port > 0 && wsPath) return { port, wsPath }; + } catch {} + return null; +} + export async function findExistingChromeDebugPort(options: FindExistingChromeDebugPortOptions): Promise { const timeoutMs = options.timeoutMs ?? 3_000; - const portFile = path.join(options.profileDir, "DevToolsActivePort"); + const parsed = parseDevToolsActivePort(path.join(options.profileDir, "DevToolsActivePort")); - try { - const content = fs.readFileSync(portFile, "utf-8"); - const [portLine] = content.split(/\r?\n/); - const port = Number.parseInt(portLine?.trim() ?? "", 10); - if (port > 0 && await isDebugPortReady(port, timeoutMs)) return port; - } catch {} + if (parsed && parsed.port > 0 && await isDebugPortReady(parsed.port, timeoutMs)) return parsed.port; if (process.platform === "win32") return null; @@ -204,6 +232,81 @@ export async function findExistingChromeDebugPort(options: FindExistingChromeDeb return null; } +export function getDefaultChromeUserDataDirs(channels: ChromeChannel[] = ["stable"]): string[] { + const home = os.homedir(); + const dirs: string[] = []; + + const channelDirs: Record = { + stable: { + darwin: path.join(home, "Library", "Application Support", "Google", "Chrome"), + linux: path.join(home, ".config", "google-chrome"), + win32: path.join(process.env.LOCALAPPDATA ?? path.join(home, "AppData", "Local"), "Google", "Chrome", "User Data"), + }, + beta: { + darwin: path.join(home, "Library", "Application Support", "Google", "Chrome Beta"), + linux: path.join(home, ".config", "google-chrome-beta"), + win32: path.join(process.env.LOCALAPPDATA ?? path.join(home, "AppData", "Local"), "Google", "Chrome Beta", "User Data"), + }, + canary: { + darwin: path.join(home, "Library", "Application Support", "Google", "Chrome Canary"), + linux: path.join(home, ".config", "google-chrome-canary"), + win32: path.join(process.env.LOCALAPPDATA ?? path.join(home, "AppData", "Local"), "Google", "Chrome SxS", "User Data"), + }, + dev: { + darwin: path.join(home, "Library", "Application Support", "Google", "Chrome Dev"), + linux: path.join(home, ".config", "google-chrome-dev"), + win32: path.join(process.env.LOCALAPPDATA ?? path.join(home, "AppData", "Local"), "Google", "Chrome Dev", "User Data"), + }, + }; + + const platform = process.platform === "darwin" ? "darwin" : process.platform === "win32" ? "win32" : "linux"; + + for (const ch of channels) { + const entry = channelDirs[ch]; + if (entry) dirs.push(entry[platform]); + } + + return dirs; +} + +export async function discoverRunningChromeDebugPort(options: DiscoverRunningChromeOptions = {}): Promise { + const channels = options.channels ?? ["stable", "beta", "canary", "dev"]; + const timeoutMs = options.timeoutMs ?? 3_000; + + const userDataDirs = getDefaultChromeUserDataDirs(channels); + for (const dir of userDataDirs) { + const parsed = parseDevToolsActivePort(path.join(dir, "DevToolsActivePort")); + if (!parsed) continue; + if (await isPortListening(parsed.port, timeoutMs)) { + return { port: parsed.port, wsUrl: `ws://127.0.0.1:${parsed.port}${parsed.wsPath}` }; + } + } + + if (process.platform !== "win32") { + try { + const result = spawnSync("ps", ["aux"], { encoding: "utf-8", timeout: 5_000 }); + if (result.status === 0 && result.stdout) { + const lines = result.stdout + .split("\n") + .filter((line) => line.includes("--remote-debugging-port=") && /chrome|chromium/i.test(line)); + + for (const line of lines) { + const portMatch = line.match(/--remote-debugging-port=(\d+)/); + const port = Number.parseInt(portMatch?.[1] ?? "", 10); + if (port > 0 && await isDebugPortReady(port, timeoutMs)) { + try { + const version = await fetchJson<{ webSocketDebuggerUrl?: string }>(`http://127.0.0.1:${port}/json/version`, { timeoutMs }); + if (version.webSocketDebuggerUrl) return { port, wsUrl: version.webSocketDebuggerUrl }; + } catch {} + } + } + } + } catch {} + } + + return null; +} + export async function waitForChromeDebugPort( port: number, timeoutMs: number, diff --git a/skills/baoyu-post-to-weibo/scripts/vendor/baoyu-chrome-cdp/src/index.ts b/skills/baoyu-post-to-weibo/scripts/vendor/baoyu-chrome-cdp/src/index.ts index 1fcd241..ee4fd71 100644 --- a/skills/baoyu-post-to-weibo/scripts/vendor/baoyu-chrome-cdp/src/index.ts +++ b/skills/baoyu-post-to-weibo/scripts/vendor/baoyu-chrome-cdp/src/index.ts @@ -43,6 +43,18 @@ type FindExistingChromeDebugPortOptions = { timeoutMs?: number; }; +export type ChromeChannel = "stable" | "beta" | "canary" | "dev"; + +export type DiscoveredChrome = { + port: number; + wsUrl: string; +}; + +type DiscoverRunningChromeOptions = { + channels?: ChromeChannel[]; + timeoutMs?: number; +}; + type LaunchChromeOptions = { chromePath: string; profileDir: string; @@ -173,16 +185,32 @@ async function isDebugPortReady(port: number, timeoutMs = 3_000): Promise { + return new Promise((resolve) => { + const socket = new net.Socket(); + const timer = setTimeout(() => { socket.destroy(); resolve(false); }, timeoutMs); + socket.once("connect", () => { clearTimeout(timer); socket.destroy(); resolve(true); }); + socket.once("error", () => { clearTimeout(timer); resolve(false); }); + socket.connect(port, "127.0.0.1"); + }); +} + +function parseDevToolsActivePort(filePath: string): { port: number; wsPath: string } | null { + try { + const content = fs.readFileSync(filePath, "utf-8"); + const lines = content.split(/\r?\n/); + const port = Number.parseInt(lines[0]?.trim() ?? "", 10); + const wsPath = lines[1]?.trim(); + if (port > 0 && wsPath) return { port, wsPath }; + } catch {} + return null; +} + export async function findExistingChromeDebugPort(options: FindExistingChromeDebugPortOptions): Promise { const timeoutMs = options.timeoutMs ?? 3_000; - const portFile = path.join(options.profileDir, "DevToolsActivePort"); + const parsed = parseDevToolsActivePort(path.join(options.profileDir, "DevToolsActivePort")); - try { - const content = fs.readFileSync(portFile, "utf-8"); - const [portLine] = content.split(/\r?\n/); - const port = Number.parseInt(portLine?.trim() ?? "", 10); - if (port > 0 && await isDebugPortReady(port, timeoutMs)) return port; - } catch {} + if (parsed && parsed.port > 0 && await isDebugPortReady(parsed.port, timeoutMs)) return parsed.port; if (process.platform === "win32") return null; @@ -204,6 +232,81 @@ export async function findExistingChromeDebugPort(options: FindExistingChromeDeb return null; } +export function getDefaultChromeUserDataDirs(channels: ChromeChannel[] = ["stable"]): string[] { + const home = os.homedir(); + const dirs: string[] = []; + + const channelDirs: Record = { + stable: { + darwin: path.join(home, "Library", "Application Support", "Google", "Chrome"), + linux: path.join(home, ".config", "google-chrome"), + win32: path.join(process.env.LOCALAPPDATA ?? path.join(home, "AppData", "Local"), "Google", "Chrome", "User Data"), + }, + beta: { + darwin: path.join(home, "Library", "Application Support", "Google", "Chrome Beta"), + linux: path.join(home, ".config", "google-chrome-beta"), + win32: path.join(process.env.LOCALAPPDATA ?? path.join(home, "AppData", "Local"), "Google", "Chrome Beta", "User Data"), + }, + canary: { + darwin: path.join(home, "Library", "Application Support", "Google", "Chrome Canary"), + linux: path.join(home, ".config", "google-chrome-canary"), + win32: path.join(process.env.LOCALAPPDATA ?? path.join(home, "AppData", "Local"), "Google", "Chrome SxS", "User Data"), + }, + dev: { + darwin: path.join(home, "Library", "Application Support", "Google", "Chrome Dev"), + linux: path.join(home, ".config", "google-chrome-dev"), + win32: path.join(process.env.LOCALAPPDATA ?? path.join(home, "AppData", "Local"), "Google", "Chrome Dev", "User Data"), + }, + }; + + const platform = process.platform === "darwin" ? "darwin" : process.platform === "win32" ? "win32" : "linux"; + + for (const ch of channels) { + const entry = channelDirs[ch]; + if (entry) dirs.push(entry[platform]); + } + + return dirs; +} + +export async function discoverRunningChromeDebugPort(options: DiscoverRunningChromeOptions = {}): Promise { + const channels = options.channels ?? ["stable", "beta", "canary", "dev"]; + const timeoutMs = options.timeoutMs ?? 3_000; + + const userDataDirs = getDefaultChromeUserDataDirs(channels); + for (const dir of userDataDirs) { + const parsed = parseDevToolsActivePort(path.join(dir, "DevToolsActivePort")); + if (!parsed) continue; + if (await isPortListening(parsed.port, timeoutMs)) { + return { port: parsed.port, wsUrl: `ws://127.0.0.1:${parsed.port}${parsed.wsPath}` }; + } + } + + if (process.platform !== "win32") { + try { + const result = spawnSync("ps", ["aux"], { encoding: "utf-8", timeout: 5_000 }); + if (result.status === 0 && result.stdout) { + const lines = result.stdout + .split("\n") + .filter((line) => line.includes("--remote-debugging-port=") && /chrome|chromium/i.test(line)); + + for (const line of lines) { + const portMatch = line.match(/--remote-debugging-port=(\d+)/); + const port = Number.parseInt(portMatch?.[1] ?? "", 10); + if (port > 0 && await isDebugPortReady(port, timeoutMs)) { + try { + const version = await fetchJson<{ webSocketDebuggerUrl?: string }>(`http://127.0.0.1:${port}/json/version`, { timeoutMs }); + if (version.webSocketDebuggerUrl) return { port, wsUrl: version.webSocketDebuggerUrl }; + } catch {} + } + } + } + } catch {} + } + + return null; +} + export async function waitForChromeDebugPort( port: number, timeoutMs: number, diff --git a/skills/baoyu-post-to-x/scripts/vendor/baoyu-chrome-cdp/src/index.ts b/skills/baoyu-post-to-x/scripts/vendor/baoyu-chrome-cdp/src/index.ts index 1fcd241..ee4fd71 100644 --- a/skills/baoyu-post-to-x/scripts/vendor/baoyu-chrome-cdp/src/index.ts +++ b/skills/baoyu-post-to-x/scripts/vendor/baoyu-chrome-cdp/src/index.ts @@ -43,6 +43,18 @@ type FindExistingChromeDebugPortOptions = { timeoutMs?: number; }; +export type ChromeChannel = "stable" | "beta" | "canary" | "dev"; + +export type DiscoveredChrome = { + port: number; + wsUrl: string; +}; + +type DiscoverRunningChromeOptions = { + channels?: ChromeChannel[]; + timeoutMs?: number; +}; + type LaunchChromeOptions = { chromePath: string; profileDir: string; @@ -173,16 +185,32 @@ async function isDebugPortReady(port: number, timeoutMs = 3_000): Promise { + return new Promise((resolve) => { + const socket = new net.Socket(); + const timer = setTimeout(() => { socket.destroy(); resolve(false); }, timeoutMs); + socket.once("connect", () => { clearTimeout(timer); socket.destroy(); resolve(true); }); + socket.once("error", () => { clearTimeout(timer); resolve(false); }); + socket.connect(port, "127.0.0.1"); + }); +} + +function parseDevToolsActivePort(filePath: string): { port: number; wsPath: string } | null { + try { + const content = fs.readFileSync(filePath, "utf-8"); + const lines = content.split(/\r?\n/); + const port = Number.parseInt(lines[0]?.trim() ?? "", 10); + const wsPath = lines[1]?.trim(); + if (port > 0 && wsPath) return { port, wsPath }; + } catch {} + return null; +} + export async function findExistingChromeDebugPort(options: FindExistingChromeDebugPortOptions): Promise { const timeoutMs = options.timeoutMs ?? 3_000; - const portFile = path.join(options.profileDir, "DevToolsActivePort"); + const parsed = parseDevToolsActivePort(path.join(options.profileDir, "DevToolsActivePort")); - try { - const content = fs.readFileSync(portFile, "utf-8"); - const [portLine] = content.split(/\r?\n/); - const port = Number.parseInt(portLine?.trim() ?? "", 10); - if (port > 0 && await isDebugPortReady(port, timeoutMs)) return port; - } catch {} + if (parsed && parsed.port > 0 && await isDebugPortReady(parsed.port, timeoutMs)) return parsed.port; if (process.platform === "win32") return null; @@ -204,6 +232,81 @@ export async function findExistingChromeDebugPort(options: FindExistingChromeDeb return null; } +export function getDefaultChromeUserDataDirs(channels: ChromeChannel[] = ["stable"]): string[] { + const home = os.homedir(); + const dirs: string[] = []; + + const channelDirs: Record = { + stable: { + darwin: path.join(home, "Library", "Application Support", "Google", "Chrome"), + linux: path.join(home, ".config", "google-chrome"), + win32: path.join(process.env.LOCALAPPDATA ?? path.join(home, "AppData", "Local"), "Google", "Chrome", "User Data"), + }, + beta: { + darwin: path.join(home, "Library", "Application Support", "Google", "Chrome Beta"), + linux: path.join(home, ".config", "google-chrome-beta"), + win32: path.join(process.env.LOCALAPPDATA ?? path.join(home, "AppData", "Local"), "Google", "Chrome Beta", "User Data"), + }, + canary: { + darwin: path.join(home, "Library", "Application Support", "Google", "Chrome Canary"), + linux: path.join(home, ".config", "google-chrome-canary"), + win32: path.join(process.env.LOCALAPPDATA ?? path.join(home, "AppData", "Local"), "Google", "Chrome SxS", "User Data"), + }, + dev: { + darwin: path.join(home, "Library", "Application Support", "Google", "Chrome Dev"), + linux: path.join(home, ".config", "google-chrome-dev"), + win32: path.join(process.env.LOCALAPPDATA ?? path.join(home, "AppData", "Local"), "Google", "Chrome Dev", "User Data"), + }, + }; + + const platform = process.platform === "darwin" ? "darwin" : process.platform === "win32" ? "win32" : "linux"; + + for (const ch of channels) { + const entry = channelDirs[ch]; + if (entry) dirs.push(entry[platform]); + } + + return dirs; +} + +export async function discoverRunningChromeDebugPort(options: DiscoverRunningChromeOptions = {}): Promise { + const channels = options.channels ?? ["stable", "beta", "canary", "dev"]; + const timeoutMs = options.timeoutMs ?? 3_000; + + const userDataDirs = getDefaultChromeUserDataDirs(channels); + for (const dir of userDataDirs) { + const parsed = parseDevToolsActivePort(path.join(dir, "DevToolsActivePort")); + if (!parsed) continue; + if (await isPortListening(parsed.port, timeoutMs)) { + return { port: parsed.port, wsUrl: `ws://127.0.0.1:${parsed.port}${parsed.wsPath}` }; + } + } + + if (process.platform !== "win32") { + try { + const result = spawnSync("ps", ["aux"], { encoding: "utf-8", timeout: 5_000 }); + if (result.status === 0 && result.stdout) { + const lines = result.stdout + .split("\n") + .filter((line) => line.includes("--remote-debugging-port=") && /chrome|chromium/i.test(line)); + + for (const line of lines) { + const portMatch = line.match(/--remote-debugging-port=(\d+)/); + const port = Number.parseInt(portMatch?.[1] ?? "", 10); + if (port > 0 && await isDebugPortReady(port, timeoutMs)) { + try { + const version = await fetchJson<{ webSocketDebuggerUrl?: string }>(`http://127.0.0.1:${port}/json/version`, { timeoutMs }); + if (version.webSocketDebuggerUrl) return { port, wsUrl: version.webSocketDebuggerUrl }; + } catch {} + } + } + } + } catch {} + } + + return null; +} + export async function waitForChromeDebugPort( port: number, timeoutMs: number, diff --git a/skills/baoyu-url-to-markdown/scripts/vendor/baoyu-chrome-cdp/src/index.ts b/skills/baoyu-url-to-markdown/scripts/vendor/baoyu-chrome-cdp/src/index.ts index 1fcd241..ee4fd71 100644 --- a/skills/baoyu-url-to-markdown/scripts/vendor/baoyu-chrome-cdp/src/index.ts +++ b/skills/baoyu-url-to-markdown/scripts/vendor/baoyu-chrome-cdp/src/index.ts @@ -43,6 +43,18 @@ type FindExistingChromeDebugPortOptions = { timeoutMs?: number; }; +export type ChromeChannel = "stable" | "beta" | "canary" | "dev"; + +export type DiscoveredChrome = { + port: number; + wsUrl: string; +}; + +type DiscoverRunningChromeOptions = { + channels?: ChromeChannel[]; + timeoutMs?: number; +}; + type LaunchChromeOptions = { chromePath: string; profileDir: string; @@ -173,16 +185,32 @@ async function isDebugPortReady(port: number, timeoutMs = 3_000): Promise { + return new Promise((resolve) => { + const socket = new net.Socket(); + const timer = setTimeout(() => { socket.destroy(); resolve(false); }, timeoutMs); + socket.once("connect", () => { clearTimeout(timer); socket.destroy(); resolve(true); }); + socket.once("error", () => { clearTimeout(timer); resolve(false); }); + socket.connect(port, "127.0.0.1"); + }); +} + +function parseDevToolsActivePort(filePath: string): { port: number; wsPath: string } | null { + try { + const content = fs.readFileSync(filePath, "utf-8"); + const lines = content.split(/\r?\n/); + const port = Number.parseInt(lines[0]?.trim() ?? "", 10); + const wsPath = lines[1]?.trim(); + if (port > 0 && wsPath) return { port, wsPath }; + } catch {} + return null; +} + export async function findExistingChromeDebugPort(options: FindExistingChromeDebugPortOptions): Promise { const timeoutMs = options.timeoutMs ?? 3_000; - const portFile = path.join(options.profileDir, "DevToolsActivePort"); + const parsed = parseDevToolsActivePort(path.join(options.profileDir, "DevToolsActivePort")); - try { - const content = fs.readFileSync(portFile, "utf-8"); - const [portLine] = content.split(/\r?\n/); - const port = Number.parseInt(portLine?.trim() ?? "", 10); - if (port > 0 && await isDebugPortReady(port, timeoutMs)) return port; - } catch {} + if (parsed && parsed.port > 0 && await isDebugPortReady(parsed.port, timeoutMs)) return parsed.port; if (process.platform === "win32") return null; @@ -204,6 +232,81 @@ export async function findExistingChromeDebugPort(options: FindExistingChromeDeb return null; } +export function getDefaultChromeUserDataDirs(channels: ChromeChannel[] = ["stable"]): string[] { + const home = os.homedir(); + const dirs: string[] = []; + + const channelDirs: Record = { + stable: { + darwin: path.join(home, "Library", "Application Support", "Google", "Chrome"), + linux: path.join(home, ".config", "google-chrome"), + win32: path.join(process.env.LOCALAPPDATA ?? path.join(home, "AppData", "Local"), "Google", "Chrome", "User Data"), + }, + beta: { + darwin: path.join(home, "Library", "Application Support", "Google", "Chrome Beta"), + linux: path.join(home, ".config", "google-chrome-beta"), + win32: path.join(process.env.LOCALAPPDATA ?? path.join(home, "AppData", "Local"), "Google", "Chrome Beta", "User Data"), + }, + canary: { + darwin: path.join(home, "Library", "Application Support", "Google", "Chrome Canary"), + linux: path.join(home, ".config", "google-chrome-canary"), + win32: path.join(process.env.LOCALAPPDATA ?? path.join(home, "AppData", "Local"), "Google", "Chrome SxS", "User Data"), + }, + dev: { + darwin: path.join(home, "Library", "Application Support", "Google", "Chrome Dev"), + linux: path.join(home, ".config", "google-chrome-dev"), + win32: path.join(process.env.LOCALAPPDATA ?? path.join(home, "AppData", "Local"), "Google", "Chrome Dev", "User Data"), + }, + }; + + const platform = process.platform === "darwin" ? "darwin" : process.platform === "win32" ? "win32" : "linux"; + + for (const ch of channels) { + const entry = channelDirs[ch]; + if (entry) dirs.push(entry[platform]); + } + + return dirs; +} + +export async function discoverRunningChromeDebugPort(options: DiscoverRunningChromeOptions = {}): Promise { + const channels = options.channels ?? ["stable", "beta", "canary", "dev"]; + const timeoutMs = options.timeoutMs ?? 3_000; + + const userDataDirs = getDefaultChromeUserDataDirs(channels); + for (const dir of userDataDirs) { + const parsed = parseDevToolsActivePort(path.join(dir, "DevToolsActivePort")); + if (!parsed) continue; + if (await isPortListening(parsed.port, timeoutMs)) { + return { port: parsed.port, wsUrl: `ws://127.0.0.1:${parsed.port}${parsed.wsPath}` }; + } + } + + if (process.platform !== "win32") { + try { + const result = spawnSync("ps", ["aux"], { encoding: "utf-8", timeout: 5_000 }); + if (result.status === 0 && result.stdout) { + const lines = result.stdout + .split("\n") + .filter((line) => line.includes("--remote-debugging-port=") && /chrome|chromium/i.test(line)); + + for (const line of lines) { + const portMatch = line.match(/--remote-debugging-port=(\d+)/); + const port = Number.parseInt(portMatch?.[1] ?? "", 10); + if (port > 0 && await isDebugPortReady(port, timeoutMs)) { + try { + const version = await fetchJson<{ webSocketDebuggerUrl?: string }>(`http://127.0.0.1:${port}/json/version`, { timeoutMs }); + if (version.webSocketDebuggerUrl) return { port, wsUrl: version.webSocketDebuggerUrl }; + } catch {} + } + } + } + } catch {} + } + + return null; +} + export async function waitForChromeDebugPort( port: number, timeoutMs: number,