Commit 020b3a28 authored by Lisa's avatar Lisa

Remove browser extension (moved to hermes-node-chrome repo)

The Chrome browser extension now lives in its own repository:
git@git.nexlab.net:lisa/hermes-node-chrome.git

This keeps the node-agent repo focused on the core agent functionality.
parent f7f01954
// Hermes Extension Background Service Worker
// Provides bidirectional communication between CDP and content scripts
const PORT_NAME = 'hermes_agent_port';
let ports = new Map();
let messageQueue = [];
chrome.runtime.onConnect.addListener((port) => {
if (port.name === PORT_NAME) {
const tabId = port.sender?.tab?.id;
console.log('[Hermes] Port connected from tab:', tabId);
if (tabId) ports.set(tabId, port);
port.onMessage.addListener((msg) => {
console.log('[Hermes] Message from tab', tabId, ':', msg);
if (msg.type === 'hermes_injected_ready') {
// Inject script reported ready
}
});
port.onDisconnect.addListener(() => {
console.log('[Hermes] Port disconnected from tab:', tabId);
ports.delete(tabId);
});
}
});
// Message from external (CDP Runtime.evaluate)
chrome.runtime.onMessageExternal.addListener((msg, sender, sendResponse) => {
if (msg.type && msg.type.startsWith('hermes_')) {
handleHermesMessage(msg, sender, sendResponse);
return true; // async response
}
});
function handleHermesMessage(msg, sender, sendResponse) {
switch (msg.type) {
case 'hermes_eval_in_page':
// Execute JS in all tabs
chrome.tabs.query({}, (tabs) => {
tabs.forEach(tab => {
if (ports.has(tab.id)) {
ports.get(tab.id).postMessage({
type: 'hermes_exec',
script: msg.script,
id: msg.id
});
}
});
sendResponse({status: 'sent'});
});
break;
case 'hermes_get_info':
sendResponse({
status: 'ok',
extension: 'hermes_browser_agent',
version: '1.0',
tabs: Array.from(ports.keys())
});
break;
default:
sendResponse({status: 'unknown'});
}
}
// CDP can call chrome.runtime.sendMessage via Runtime.evaluate
// This allows remote commands to trigger extension actions
console.log('[Hermes] Background service worker initialized');
// Hermes Content Script - runs in every page
// Establishes communication channel with injected code
const PORT_NAME = 'hermes_agent_port';
const port = chrome.runtime.connect({name: PORT_NAME});
port.onMessage.addListener((msg) => {
if (msg.type === 'hermes_exec') {
// Execute script in page context
try {
const result = eval(msg.script);
// Result is not sent back via port (no return mechanism in MV3)
// Use CDP Runtime.evaluate for return values
} catch (e) {
console.error('[Hermes] Script execution error:', e);
}
}
});
// Signal that content script is loaded
port.postMessage({type: 'hermes_content_ready'});
console.log('[Hermes] Content script loaded');
// Hermes Injected API - exposed to page JavaScript context
// Allows page scripts to communicate with the extension and agent
window.HermesAgent = {
version: '1.0',
// Execute code via extension (safer than direct eval)
execute: async function(script) {
return new Promise((resolve) => {
const msg = {type: 'hermes_exec', script, id: Date.now()};
// CDP Runtime.evaluate is the primary channel, this is secondary
console.log('[Hermes] execute called:', script);
resolve({ok: true, note: 'use CDP Runtime.evaluate for results'});
});
},
// Get page info
getInfo: async function() {
return {
url: window.location.href,
title: document.title,
domain: window.location.hostname,
referrer: document.referrer,
timestamp: Date.now()
};
},
// Helper: wait for selector
waitForSelector: function(selector, timeout = 5000) {
return new Promise((resolve, reject) => {
const start = Date.now();
const check = () => {
const el = document.querySelector(selector);
if (el) {
resolve(el);
} else if (Date.now() - start > timeout) {
reject(new Error('Timeout waiting for: ' + selector));
} else {
requestAnimationFrame(check);
}
};
check();
});
},
// Helper: fill form
fillForm: function(selector, value) {
const el = document.querySelector(selector);
if (el) {
el.value = value;
el.dispatchEvent(new Event('input', {bubbles: true}));
el.dispatchEvent(new Event('change', {bubbles: true}));
return true;
}
return false;
}
};
console.log('[Hermes] Injected API loaded - window.HermesAgent available');
// Notify background script
if (chrome && chrome.runtime) {
chrome.runtime.sendMessage({
type: 'hermes_injected_ready',
url: window.location.href
});
}
{
"manifest_version": 3,
"name": "Hermes Node Agent Extension",
"version": "1.0",
"description": "Hermes agent helper - provides CDP communication and JS injection utilities for remote browser automation.",
"permissions": [
"storage",
"scripting",
"activeTab",
"tabs",
"webNavigation"
],
"host_permissions": [
"<all_urls>"
],
"background": {
"service_worker": "background.js",
"type": "module"
},
"content_scripts": [
{
"matches": [
"<all_urls>"
],
"js": [
"content.js"
],
"run_at": "document_start"
}
],
"web_accessible_resources": [
{
"resources": [
"injected.js"
],
"matches": [
"<all_urls>"
]
}
]
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment