#!/usr/bin/env python3 """ WorkBuddy Token 提取工具(傻瓜版) 全自动检测和安装依赖,用户只需双击运行即可。 功能: - 自动检测并安装 Python(如未安装) - 自动安装脚本依赖 - 自动启动 WorkBuddy(调试模式) - 自动提取 Token 并保存到桌面 """ import os import sys import time import json import subprocess import asyncio import platform from pathlib import Path def run_cmd(cmd, check=True, shell=True): """执行命令并返回结果""" try: result = subprocess.run( cmd, shell=shell, capture_output=True, text=True, timeout=300 ) if check and result.returncode != 0: return False, result.stderr return True, result.stdout except subprocess.TimeoutExpired: return False, "命令执行超时" except Exception as e: return False, str(e) def check_python(): """检查 Python 是否安装""" py_names = ["python", "python3"] if platform.system() == "Windows" else ["python3", "python"] for name in py_names: try: result = subprocess.run( [name, "--version"], capture_output=True, text=True ) if result.returncode == 0: version = result.stdout.strip() print(f" ✅ Python 已安装: {version}") return True except FileNotFoundError: continue print(" ❌ Python 未安装,正在安装...") return False def install_homebrew(): """安装 Homebrew""" print("\n正在安装 Homebrew...") print("(这可能需要几分钟,请耐心等待)\n") cmd = '/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"' ok, msg = run_cmd(cmd, check=False) if ok: print(" ✅ Homebrew 安装成功!") return True else: print(f" ⚠️ Homebrew 安装失败") print("\n请手动安装 Homebrew:") print(" 打开终端,粘贴以下命令:") print(" /bin/bash -c \"$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)\"") return False def install_python_via_installer(): """通过 python.org 安装包安装 Python(不需要 sudo)""" print("\n正在下载 Python 安装包...") print("(这可能需要几分钟,取决于网速)\n") dmg_url = "https://www.python.org/ftp/python/3.13.0/python-3.13.0-macos11.pkg" dmg_path = "/tmp/python-installer.pkg" ok, _ = run_cmd(f'curl -L -o "{dmg_path}" "{dmg_url}"', check=False) if not ok: print(" ❌ 下载失败,请检查网络连接") return False print(" ✅ 下载完成,正在打开安装程序...") print("\n" + "=" * 50) print(" 请在弹出的安装程序中:") print(" 1. 点击「继续」") print(" 2. 阅读许可协议,点击「继续」→「同意」") print(" 3. 选择安装位置,点击「安装」") print(" 4. 输入电脑密码(如果有)") print(" 5. 等待安装完成,点击「关闭」") print("=" * 50) print("\n安装完成后,回到此窗口按回车键继续...") print("(或者输入 q 退出,稍后手动安装)") response = input("\n按回车继续,或输入 q 退出: ").strip().lower() if response == 'q': return False run_cmd(f'open "{dmg_path}"', check=False) input("\n安装完成后,按回车继续...") return True def install_python(): """安装 Python""" print("\n" + "=" * 50) print("正在安装 Python...") print("=" * 50) success, _ = run_cmd("which brew") if not success: print(" ❌ 未检测到 Homebrew") print("\n尝试通过安装包安装 Python(不需要 sudo)...") if install_python_via_installer(): ok, _ = run_cmd("which python3", check=False) if ok: print(" ✅ Python 安装成功!") return True print("\n正在安装 Homebrew 作为备选...") if not install_homebrew(): print("\n⚠️ 无法自动安装 Python") print("请手动安装: https://www.python.org/downloads/") return False print("\n重新检测 Homebrew...") success, _ = run_cmd("which brew") if not success: print(" ❌ Homebrew 安装失败") return False print("使用 Homebrew 安装 Python...") ok, msg = run_cmd("brew install python", check=False) if ok: print(" ✅ Python 安装成功!") return True else: print(f" ⚠️ Homebrew 安装 Python 失败") print("尝试通过安装包安装...") if install_python_via_installer(): ok, _ = run_cmd("which python3", check=False) if ok: print(" ✅ Python 安装成功!") return True return False def install_dependencies(): """安装脚本依赖""" print("\n正在安装依赖 (httpx, websockets)...") pip_cmd = "pip" if platform.system() == "Windows" else "pip3" deps = ["httpx", "websockets"] for dep in deps: ok, _ = run_cmd(f"{pip_cmd} install {dep}") if ok: print(f" ✅ {dep} 安装成功") else: print(f" ❌ {dep} 安装失败") return False return True def check_workbuddy_installed(): """检查 WorkBuddy 是否安装""" paths = [ Path("/Applications/WorkBuddy.app"), Path.home() / "Applications/WorkBuddy.app", # Windows paths Path(os.path.expandvars(r"%LOCALAPPDATA%\Programs\WorkBuddy\WorkBuddy.exe")), Path(os.path.expandvars(r"%ProgramFiles%\WorkBuddy\WorkBuddy.exe")), Path(os.path.expandvars(r"%ProgramFiles(x86)%\WorkBuddy\WorkBuddy.exe")), Path(r"D:\Program Files\WorkBuddy\WorkBuddy.exe"), Path(r"E:\Program Files\WorkBuddy\WorkBuddy.exe"), ] for p in paths: if p.exists(): return True, p return False, None def check_workbuddy_running(): """检查 WorkBuddy 是否正在运行(调试模式)""" try: import httpx resp = httpx.get("http://127.0.0.1:9222/json", timeout=2) if resp.status_code == 200: return True except: pass return False def start_workbuddy_debug(): """启动 WorkBuddy 调试模式""" print("\n正在启动 WorkBuddy(调试模式)...") if platform.system() == "Windows": # Find WorkBuddy on Windows candidates = [ os.path.expandvars(r"%LOCALAPPDATA%\Programs\WorkBuddy\WorkBuddy.exe"), os.path.expandvars(r"%ProgramFiles%\WorkBuddy\WorkBuddy.exe"), os.path.expandvars(r"%ProgramFiles(x86)%\WorkBuddy\WorkBuddy.exe"), r"D:\Program Files\WorkBuddy\WorkBuddy.exe", r"E:\Program Files\WorkBuddy\WorkBuddy.exe", ] workbuddy_path = next((p for p in candidates if os.path.exists(p)), None) if not workbuddy_path: print(" ❌ 找不到 WorkBuddy,请手动启动" ) print(" → 关闭 WorkBuddy,然后重新打开" ) print(" → 或者:Win+R 运行:workbuddy --remote-debugging-port=9222" ) return False cmd = f'"{workbuddy_path}" --remote-debugging-port=9222' else: workbuddy_path = "/Applications/WorkBuddy.app/Contents/MacOS/Electron" cmd = f'"{workbuddy_path}" --remote-debugging-port=9222' try: subprocess.Popen(cmd, shell=True) print(" ✅ WorkBuddy 已启动") print("\n等待 WorkBuddy 完全加载(5秒)...") time.sleep(5) return True except Exception as e: print(f" ❌ 启动失败: {e}") return False def check_requirements(): """检查前置条件""" print("\n[检查 1/4] 检测 Python...") if not check_python(): if not install_python(): return False print("\n[检查 2/4] 安装依赖...") if not install_dependencies(): return False print("\n[检查 3/4] 检测 WorkBuddy...") installed, path = check_workbuddy_installed() if not installed: print(" ❌ WorkBuddy 未安装") print(" 请先安装 WorkBuddy: https://workbuddy.com/download") return False print(f" ✅ WorkBuddy 已安装: {path}") print("\n[检查 4/4] 检测 WorkBuddy 运行状态...") if check_workbuddy_running(): print(" ✅ WorkBuddy 已运行(调试模式)") else: print(" ⚠️ WorkBuddy 未运行,正在启动...") if not start_workbuddy_debug(): return False return True async def extract_token(): """从 WorkBuddy 提取 Token""" import httpx import websockets print("\n正在连接 WorkBuddy...") async with httpx.AsyncClient() as client: resp = await client.get("http://127.0.0.1:9222/json", timeout=5) targets = resp.json() print(f" ✅ 找到 {len(targets)} 个页面") ws_url = None for t in targets: if t.get("type") == "page" and "workbench" in t.get("url", ""): ws_url = t.get("webSocketDebuggerUrl") break if not ws_url: for t in targets: if t.get("type") == "page": ws_url = t.get("webSocketDebuggerUrl") break if not ws_url: raise Exception("未找到 WorkBuddy 页面") print(" ✅ 已找到 WorkBuddy 页面") print("\n正在提取 Token...") async with websockets.connect(ws_url, ping_timeout=30) as ws: cmd = { "id": 1, "method": "Runtime.evaluate", "params": { "expression": """ (async () => { try { const s = await window.vscode.ipcRenderer.invoke( 'vscode:genie:auth:getSession' ); return JSON.stringify(s); } catch(e) { return JSON.stringify({error: e.message}); } })() """, "awaitPromise": True, "returnByValue": True, }, } await ws.send(json.dumps(cmd)) result = json.loads(await asyncio.wait_for(ws.recv(), timeout=30)) value = result.get("result", {}).get("result", {}).get("value", "") if not value: raise Exception("CDP 返回为空") session = json.loads(value) if session.get("error"): raise Exception(f"CDP 错误: {session['error']}") return session def save_token(access_token, refresh_token): """保存 Token 到桌面""" desktop = Path.home() / "Desktop" output_file = desktop / "token.txt" content = f"""WorkBuddy Token 生成时间: {time.strftime("%Y-%m-%d %H:%M:%S")} access_token={access_token} refresh_token={refresh_token} """ output_file.write_text(content, encoding="utf-8") return output_file def main(): print("=" * 50) print(" WorkBuddy Token 提取工具") print("=" * 50) print("\n正在检测环境...\n") if not check_requirements(): input("\n按回车键退出...") sys.exit(1) try: session = asyncio.run(extract_token()) except Exception as e: print(f"\n❌ 提取失败: {e}") print("\n请确保:") print(" 1. WorkBuddy 已登录") print(" 2. 重新运行此脚本") input("\n按回车键退出...") sys.exit(1) auth = session.get("auth", session) access_token = auth.get("accessToken", "") refresh_token = auth.get("refreshToken", "") if not access_token: print("\n❌ 未获取到 accessToken") print("请确保 WorkBuddy 已登录 AI 功能") input("\n按回车键退出...") sys.exit(1) try: output_file = save_token(access_token, refresh_token) except Exception as e: print(f"\n❌ 保存失败: {e}") input("\n按回车键退出...") sys.exit(1) print("\n" + "=" * 50) print("✅ 成功!") print("=" * 50) print(f"\n📄 Token 已保存到桌面:") print(f" {output_file}") print(f"\n🔑 access_token: {access_token[:30]}...") print(f"🔑 refresh_token: {refresh_token[:30] if refresh_token else 'N/A'}...") print("\n" + "=" * 50) input("\n按回车键退出...") if __name__ == "__main__": main()