(function() { 'use strict'; if (window.__agentPDInjected) return; window.__agentPDInjected = true; const AGENT_PATTERNS = { 'claude.ai': 'claude-code', 'chatgpt.com': 'chatgpt', 'chat.openai.com': 'chatgpt', 'github.com': 'github-copilot', 'cursor.sh': 'cursor' }; function detectAgent() { const hostname = location.hostname; for (const [domain, agent] of Object.entries(AGENT_PATTERNS)) { if (hostname.includes(domain)) return agent; } return 'unknown'; } function sendEvent(type, tool, target, extra = {}) { const event = { type: 'AGENT_EVENT', payload: { agent: detectAgent(), type: type, tool: tool, target: target, url: location.href, timestamp: new Date().toISOString(), id: crypto.randomUUID(), ...extra } }; chrome.runtime.sendMessage(event).catch(() => {}); } function observeClaude() { const observer = new MutationObserver((mutations) => { for (const mutation of mutations) { for (const node of mutation.addedNodes) { if (node.nodeType !== Node.ELEMENT_NODE) continue; const text = node.textContent || ''; if (text.includes('Using tool') || text.includes('tool use')) { const toolMatch = text.match(/Using tool[:\s]+(\w+)/i) || text.match(/tool\s+use[:\s]+(\w+)/i); const toolName = toolMatch ? toolMatch[1] : 'unknown'; sendEvent('tool_use', toolName, location.href, { context: text.slice(0, 200) }); } if (text.includes('I\'ll help you') || text.includes('I can help')) { sendEvent('session_start', 'chat', location.href, { context: text.slice(0, 100) }); } if (text.includes('file') || node.querySelector?.('[data-testid="file"]')) { const fileNodes = node.querySelectorAll?.('[data-testid="file"], .file-name, [class*="file"]') || []; for (const fn of fileNodes) { const path = fn.textContent || fn.getAttribute('data-path') || 'unknown'; sendEvent('file_access', 'read_file', path, { context: text.slice(0, 100) }); } } } } }); observer.observe(document.body, { childList: true, subtree: true }); } function observeGitHub() { const observer = new MutationObserver((mutations) => { for (const mutation of mutations) { for (const node of mutation.addedNodes) { if (node.nodeType !== Node.ELEMENT_NODE) continue; const text = node.textContent || ''; if (text.includes('GitHub Copilot') || text.includes('Copilot')) { sendEvent('tool_use', 'github_copilot', location.href, { context: text.slice(0, 100) }); } if (text.includes('suggested') && text.includes('change')) { sendEvent('code_generation', 'copilot_suggestion', location.href, { context: text.slice(0, 200) }); } } } }); if (document.body) observer.observe(document.body, { childList: true, subtree: true }); } function observeChatGPT() { const observer = new MutationObserver((mutations) => { for (const mutation of mutations) { for (const node of mutation.addedNodes) { if (node.nodeType !== Node.ELEMENT_NODE) continue; const text = node.textContent || ''; if (text.includes('```') || text.includes('code')) { sendEvent('code_generation', 'code_block', location.href, { context: text.slice(0, 200) }); } if (text.includes('browsing') || text.includes('search')) { sendEvent('tool_use', 'web_search', location.href, { context: text.slice(0, 100) }); } } } }); if (document.body) observer.observe(document.body, { childList: true, subtree: true }); } function observeCursor() { const observer = new MutationObserver((mutations) => { for (const mutation of mutations) { for (const node of mutation.addedNodes) { if (node.nodeType !== Node.ELEMENT_NODE) continue; const text = node.textContent || ''; if (text.includes('Cursor') || text.includes('AI')) { sendEvent('tool_use', 'cursor_ai', location.href, { context: text.slice(0, 100) }); } } } }); if (document.body) observer.observe(document.body, { childList: true, subtree: true }); } function init() { const agent = detectAgent(); if (agent === 'claude-code') observeClaude(); else if (agent === 'github-copilot') observeGitHub(); else if (agent === 'chatgpt') observeChatGPT(); else if (agent === 'cursor') observeCursor(); sendEvent('page_visit', 'page_load', location.href, { agent }); const originalFetch = window.fetch; window.fetch = async function(...args) { const url = args[0] instanceof Request ? args[0].url : String(args[0]); const method = args[0] instanceof Request ? args[0].method : (args[1]?.method || 'GET'); try { const response = await originalFetch.apply(this, args); if (url.includes('api') || url.includes('completion') || url.includes('chat')) { sendEvent('api_call', method, url, { status: response.status }); } return response; } catch (err) { sendEvent('api_call', method, url, { error: err.message, status: 0 }); throw err; } }; } if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', init); } else { init(); } })();