diff --git a/TMWebDriver.py b/TMWebDriver.py index e6379fd..7fd56d7 100644 --- a/TMWebDriver.py +++ b/TMWebDriver.py @@ -97,7 +97,7 @@ class TMWebDriver: auto_switch_newtab = data.get('auto_switch_newtab', False) try: result = self.execute_js(code, timeout=timeout, session_id=session_id, auto_switch_newtab=auto_switch_newtab) - print('[remote result]', str(result)[:500]) + print('[remote result]', str(result)[:500].replace('\n', ' ')) newTabs = result.get('newTabs', []) if isinstance(result, dict) else [] return json.dumps({'result': result, 'newTabs': newTabs}, ensure_ascii=False) except Exception as e: @@ -175,7 +175,7 @@ class TMWebDriver: session.mark_disconnected() break - def execute_js(self, code, timeout=10.0, session_id=None, auto_switch_newtab=False) -> Any: + def execute_js(self, code, timeout=15, session_id=None, auto_switch_newtab=False) -> Any: if session_id is None: session_id = self.default_session_id if self.is_remote: print('remote_execute_js') diff --git a/assets/cookie_grabber/background.js b/assets/cookie_grabber/background.js new file mode 100644 index 0000000..cdff0aa --- /dev/null +++ b/assets/cookie_grabber/background.js @@ -0,0 +1,24 @@ +// background.js - 保留原有事件 + 新增消息监听 +chrome.runtime.onInstalled.addListener(() => { + console.log('Cookie Grabber installed'); +}); + +// content script 请求cookie时的处理 +chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => { + if (msg.type === 'getCookies' && sender.tab) { + const url = sender.tab.url; + // 普通cookie + partitioned cookie 双查合并 + chrome.cookies.getAll({url}, cookies => { + console.log('[CookieGrabber] normal cookies:', cookies.map(c => c.name)); + chrome.cookies.getAll({url, partitionKey: {topLevelSite: url.match(/^https?:\/\/[^/]+/)[0]}}, pCookies => { + console.log('[CookieGrabber] partitioned cookies:', pCookies.map(c => c.name)); + const map = {}; + cookies.forEach(c => map[c.name] = c.value); + pCookies.forEach(c => map[c.name] = c.value); + const str = Object.entries(map).map(([k,v]) => k + '=' + v).join('; '); + sendResponse({cookies: str}); + }); + }); + return true; // 异步响应 + } +}); \ No newline at end of file diff --git a/assets/cookie_grabber/content.js b/assets/cookie_grabber/content.js new file mode 100644 index 0000000..64ad502 --- /dev/null +++ b/assets/cookie_grabber/content.js @@ -0,0 +1,18 @@ +// content.js - MutationObserver 监听触发元素 +const TRIGGER_ID = '__ljqcg__'; + +const obs = new MutationObserver(muts => { + for (const m of muts) { + for (const node of m.addedNodes) { + if (node.nodeType === 1 && node.id === TRIGGER_ID) { + chrome.runtime.sendMessage({type: 'getCookies'}, res => { + if (res && res.cookies) node.textContent = res.cookies; + else node.textContent = '__cg_error__'; + }); + return; + } + } + } +}); + +obs.observe(document.documentElement, {childList: true, subtree: true}); diff --git a/assets/cookie_grabber/manifest.json b/assets/cookie_grabber/manifest.json new file mode 100644 index 0000000..1e41399 --- /dev/null +++ b/assets/cookie_grabber/manifest.json @@ -0,0 +1,32 @@ +{ + "manifest_version": 3, + "name": "Cookie Grabber", + "version": "1.0", + "description": "获取所有 cookies", + "permissions": [ + "cookies", + "storage", + "tabs", + "activeTab" + ], + "background": { + "service_worker": "background.js" + }, + "action": { + "default_popup": "popup.html" + }, + "host_permissions": [ + "" + ], + "content_scripts": [ + { + "matches": [ + "" + ], + "js": [ + "content.js" + ], + "run_at": "document_idle" + } + ] +} \ No newline at end of file diff --git a/assets/cookie_grabber/popup.html b/assets/cookie_grabber/popup.html new file mode 100644 index 0000000..b25f8a4 --- /dev/null +++ b/assets/cookie_grabber/popup.html @@ -0,0 +1,20 @@ + + + + + HttpOnly Cookie Grabber + + + + +

Get All Cookies

+ + + + \ No newline at end of file diff --git a/assets/cookie_grabber/popup.js b/assets/cookie_grabber/popup.js new file mode 100644 index 0000000..3979435 --- /dev/null +++ b/assets/cookie_grabber/popup.js @@ -0,0 +1,56 @@ +document.addEventListener('DOMContentLoaded', () => { + // 当刷新按钮被点击时,获取当前页面的 cookies + document.getElementById('refresh').addEventListener('click', fetchCookies); + // 加载时显示当前页面的 cookies + fetchCookies(); +}); + +// 从 cookies 存储中获取当前页面的 cookies +function fetchCookies() { + // 获取当前活动的标签页 + chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => { + const activeTab = tabs[0]; // 获取活动标签页 + const currentUrl = activeTab.url; // 当前页面的 URL + console.log("当前活动的 URL:", currentUrl); + + // 双查: 普通 + partitioned + const origin = currentUrl.match(/^https?:\/\/[^\/]+/)[0]; + chrome.cookies.getAll({ url: currentUrl }, (cookies) => { + chrome.cookies.getAll({ url: currentUrl, partitionKey: { topLevelSite: origin } }, (pCookies) => { + const map = {}; + cookies.forEach(c => map[c.name] = c.value); + pCookies.forEach(c => map[c.name] = c.value); + const allCookies = Object.entries(map); + + const cookiesDisplay = document.getElementById('cookiesDisplay'); + cookiesDisplay.innerHTML = ''; + + if (allCookies.length === 0) { + cookiesDisplay.innerHTML = '
  • No available cookies
  • '; + } else { + let cookiesString = ''; + allCookies.forEach(([name, value]) => { + const li = document.createElement('li'); + li.textContent = `${name}: ${value}`; + cookiesDisplay.appendChild(li); + cookiesString += `${name}=${value}; `; + }); + console.log('cookies:', allCookies.length); + copyCookiesToClipboard(cookiesString.trim()); + } + }); + }); + }); +} + +// 将 cookies 复制到剪贴板 +function copyCookiesToClipboard(cookiesString) { + // 使用 Clipboard API 复制到剪贴板 + navigator.clipboard.writeText(cookiesString) + .then(() => { + console.log("Cookies copied to clipboard:", cookiesString); + }) + .catch(err => { + console.error("Unable to copy to clipboard:", err); + }); +} \ No newline at end of file diff --git a/memory/autonomous_operation_sop.md b/memory/autonomous_operation_sop.md index 1b17f23..fb14400 100644 --- a/memory/autonomous_operation_sop.md +++ b/memory/autonomous_operation_sop.md @@ -1,9 +1,9 @@ -# 自主行动 SOP (探测-报告-执行) [2026年] +# 自主行动 SOP (探测-报告-执行) 授权你进行自主行动,只要不对环境造成副作用都可进行。 请先选择核心目标,再选择一个小目标进行。最终探测结果形成报告(含操作申请),待用户回来确认后再进行可能的写入或修改操作。 -> **启动时写入工作记忆**:`自主探索|≤15回合|只有cwd内可写|用户不在(问题存报告)|收尾:重读本SOP检查遗漏+更新history|产出=报告+记忆提案` +> **启动时写入工作记忆**:`自主探索|≤15回合|只有cwd内可写|用户不在(问题存报告)|收尾:重读本SOP确认报告目录+更新history|产出=报告+记忆提案` ## 🎯 核心目标(按价值优先级排序) diff --git a/memory/tmwebdriver_sop.md b/memory/tmwebdriver_sop.md index 1e90393..13e3f0f 100644 --- a/memory/tmwebdriver_sop.md +++ b/memory/tmwebdriver_sop.md @@ -9,6 +9,10 @@ - JS dispatch的事件`isTrusted=false`,敏感操作(文件上传/部分按钮)会被浏览器拦截 - 文件上传:JS无法填充``,必须ljqCtrl物理点击+Win32轮询文件对话框 - 流程:SetForegroundWindow→ljqCtrl点上传按钮→FindWindow轮询对话框→输入路径→轮询关闭 +- 元素→屏幕物理坐标(ljqCtrl点击前必算):JS一次取rect+窗口信息,公式: + - `physX = (screenX + rect中心x) * dpr`,`physY = (screenY + chromeH + rect中心y) * dpr` + - chromeH = outerHeight - innerHeight,dpr = devicePixelRatio + - 注意:screenX/Y也是CSS像素,所有值先加后统一乘dpr - 结论:读信息+普通操作用TMWebDriver;文件上传等敏感操作需配合ljqCtrl ## 导航 @@ -30,4 +34,8 @@ fetch('PDF_URL').then(r=>r.blob()).then(b=>{ a.click(); }); ``` -注意:需同源或CORS允许,跨域先导航到目标域再执行 \ No newline at end of file +注意:需同源或CORS允许,跨域先导航到目标域再执行 + +## Cookie提取(含HttpOnly) +前提:需先安装`assets/cookie_grabber/`扩展 +机制:注入`id="__ljqcg__"`的div→扩展检测后自动将完整cookie写回该元素textContent(含HttpOnly) \ No newline at end of file diff --git a/simphtml.py b/simphtml.py index 73c3b4a..71c796f 100644 --- a/simphtml.py +++ b/simphtml.py @@ -904,7 +904,6 @@ def execute_js_rich(script, driver): if isinstance(error, dict): error.pop('stack', None) error_msg = str(error) print(f"Error: {error_msg}") - if driver.default_session_id != curr_session: print('Session changed') new_tab = True