|

Meet WebBrain: An Open-Source, Local-First AI Browser Agent That Reads Pages and Automates Tasks in Chrome and Firefox

🧠

WebBrain is a free, open-source browser agent for Chrome and Firefox. It reads pages, extracts knowledge, and automates multi-step duties. Unlike most browser AI plugins, it could possibly additionally run totally on a neighborhood mannequin.

It is constructed by Emre Sokullu and licensed below MIT. The full supply lives on GitHub

Run the agent in opposition to a neighborhood mannequin, and no web page knowledge leaves your machine. Connect a cloud API if you need extra functionality.

What is WebMind?

WebBrain lives in your browser’s facet panel. In Chrome it makes use of Manifest V3 and the sidePanel API. In Firefox it makes use of Manifest V2 and sidebar_action. Each tab retains its personal dialog historical past.

The extension operates inside your current authenticated session. It sees your logged-in accounts precisely as you do. It shops no knowledge externally and provides no telemetry or accounts.

The plugin ships in English, Español, Français, Türkçe, and 中文. It auto-detects your browser language on first launch.

Ask Mode, Act Mode, and How Actions Actually Fire

WebBrain has two modes: Ask mode is read-only and can not change the web page. Act mode can click on, sort, scroll, navigate, and run workflows.

Ask mode reads pages by way of atypical content material scripts. Act mode is completely different. It drives the web page by way of the Chrome DevTools Protocol through the chrome.debugger API. That produces trusted enter occasions that trendy websites truly honor. It additionally reaches cross-origin iframes and shadow DOM that content material scripts can not see.

That energy is scoped intentionally. WebMind attaches the debugger solely when an motion wants it, per tab. Chrome surfaces its customary ‘WebMind began debugging this browser’ banner whereas hooked up. Firefox has no CDP equal, so its Act mode is meaningfully weaker.

Temperatures are fastened for predictability. Act mode makes use of temperature 0.15. Ask mode makes use of 0.3. Dedicated imaginative and prescient screenshot descriptions use 0.

The Security Model

Browser brokers run on an adversarial floor. Web pages can cover immediate injections that hijack an agent’s habits. WebMind’s design addresses this instantly.

The agent begins in read-only Ask mode. It asks earlier than consequential actions. You can disable these prompts in the Permissions settings. They are on by default.

There can be a UI-first rule for mutations. For something that creates, sends, submits, or buys, WebMind makes use of the seen UI. It refuses to name REST or GraphQL endpoints instantly for mutations. A per-conversation /allow-api override exists when the UI genuinely fails.

Reading is handled individually. Fetching a README or evaluating costs makes use of background HTTP by way of the fetch_url and research_url instruments. Reading modifications nothing remotely, so the strict guidelines don’t apply.

Use Cases, With Concrete Examples

  • Data extraction is the plain one: Open a catalog and ask: ‘Extract all product names and costs from this web page.’ The agent reads the construction and returns rows. It additionally works with PDFs.
  • Research summaries are one other: Ask ‘Summarize this text,’ then observe up with a particular query. WebMind detects paywalls truthfully and doesn’t attempt to bypass them. It additionally dismisses widespread cookie-consent banners earlier than studying.
  • Form filling fits repetitive signups: An non-compulsory Profile auto-fill shops a brief bio in native plaintext. That textual content is distributed to your configured LLM to finish low-stakes kinds. Keep essential passwords out of it.
  • Automation spans a number of steps: Try ‘Navigate to github.com and discover trending repositories.’ In Act mode, the agent chains navigation, reads, and clicks.

Keeping Token Costs Down

Cloud tokens add up on lengthy classes. WebMind bounds the fee in 3 ways.

  • Screenshots are resized and iteratively JPEG-compressed earlier than they depart your machine. That retains picture tokens small. 
  • Conversation historical past and software outputs are trimmed oldest-first because the context window fills. 
  • You can even pair an affordable textual content mannequin for planning with a separate imaginative and prescient mannequin for screenshots.

How It Compares

WebBrain sits between browser AI plugins and full agent frameworks. Here is the plugin comparability, drawn from the undertaking’s personal documentation.

Feature WebMind Claude in Chrome
Open supply MIT License Proprietary
Price Free without end Requires Claude Pro ($20/mo)
Local LLM assist llama.cpp, Ollama No — Claude solely
Multi-provider All OpenAI-compatible endpoints Claude solely
Chrome Yes (MV3) Yes
Firefox Yes (MV2) No
Side panel UI Yes Yes
Ask / Act modes Yes Similar
Fully offline Yes (with native LLM) No — cloud required
Self-hostable Yes No

Frameworks like OpenClaw or Browser-Use are a distinct class. Those are developer SDKs for headless pipelines. WebMind is an end-user extension you drive from a chat panel. You can use each.

Running It: Providers and Setup

WebBrain helps native and cloud fashions by way of one interface. Local choices embrace llama.cpp, Ollama, LM Studio, Jan, vLLM, and SGLang. Cloud choices embrace OpenAI, Anthropic Claude, Gemini, Mistral, DeepSeek, and xAI Grok. It additionally helps Groq, MiniMax, Alibaba Cloud (Qwen), Nvidia NIM, and OpenRouter.

A built-in managed possibility, WebMind Cloud, wants no native setup. It prices $5 monthly per gadget profile below a fair-use coverage. For native use, llama.cpp wants no API key.

Starting a neighborhood server takes one command:

# llama.cpp — load at the very least a 16k-token context window
llama-server -m your-model.gguf -c 16384 --port 8080

# Ollama (OpenAI-compatible) — set the extension-origin env var
OLLAMA_ORIGINS="*" ollama serve
# then set the bottom URL to http://localhost:11434/v1 in settings

Point WebMind on the endpoint in settings. For a cross-machine vLLM server, allow CORS with –allowed-origins ‘[“*”]’.

The really useful mannequin is Qwen 3.6 35B (Qwen3.6-35B-A3B). It beat Gemma 4 on the undertaking’s screenshot benchmark. An RTX 5090 is right; an RTX 4090 works with INT4 AutoRound quantization.

Each supplier is a category that extends BaseLLMProvider. It normalizes to at least one response form:

null, utilization: Object

Key Takeaways

  • WebMind is a free, MIT-licensed AI browser agent for Chrome and Firefox, constructed by Emre Sokullu.
  • It runs on native fashions (llama.cpp, Ollama; Qwen 3.6 35B really useful) or any cloud API — no web page knowledge leaves your machine when native.
  • Ask mode reads pages read-only; Act mode clicks and sorts through the Chrome DevTools Protocol for trusted enter occasions.
  • Security-first by design: begins read-only, approves consequential actions, and makes use of the UI as a substitute of direct API requires mutations.
  • Free without end self-hosted, or $5/month per gadget profile for the managed WebMind Cloud below honest use.

Interactive Explainer with Demo

Demo-1

</div>
<div>
<h2>WebMind &mdash; Interactive Demo</h2>
<p class=”wb-sub”>Pick a activity, select Ask or Act, and watch the agent work.</p>
</div>
<span class=”wb-badge”>Simulated &middot; no actual LLM calls</span>
</div>

<div class=”wb-controls”>
<div class=”wb-seg” id=”wb-modeseg”>
<button data-mode=”ask” class=”on”>Ask mode</button>
<button data-mode=”act”>Act mode</button>
</div>
<div class=”wb-chips” id=”wb-chips”></div>
</div>

<div class=”wb-grid”>
<div class=”wb-pane”>
<div class=”wb-bar”>
<div class=”wb-dots”><span class=”wb-dot” model=”background:#f87171″></span>
<span class=”wb-dot” model=”background:#fbbf24″></span>
<span class=”wb-dot” model=”background:#34d399″></span></div>
<div class=”wb-url” id=”wb-url”></div>
</div>
<div class=”wb-page” id=”wb-page”></div>
</div>

<div class=”wb-pane”>
<div class=”wb-panehead”>🧠 WebMind
<span class=”wb-mode-pill ask” id=”wb-modepill”>Ask</span>
</div>
<div class=”wb-panel”>
<div class=”wb-prompt”>
<enter id=”wb-input” sort=”textual content” autocomplete=”off”>
<button class=”wb-run” id=”wb-run”>Run</button>
</div>
<div class=”wb-log” id=”wb-log”>
<div class=”wb-hint”>Choose a activity above, then press <b>Run</b>. Read-only Ask mode is the default.</div>
</div>
</div>
</div>
</div>

<div class=”wb-foot”>
<button class=”wb-reset” id=”wb-reset”>Reset demo</button>
<span>Actions listed here are illustrative and secure. The actual extension asks earlier than consequential actions.</span>
<span class=”model”>Built by Marktechpost</span>
</div>
</div>

<script>
(perform(){
var SCEN = {
merchandise: {
label:”Extract merchandise”, req:”ask”,
url:”https://instance.com/merchandise”,
immediate:”Extract all product names and costs from this web page”,
web page:'<b>Product Catalog</b>’+
‘<div class=”prod”><span>Widget Pro</span><b>$29.99</b></div>’+
‘<div class=”prod”><span>Super Gadget</span><b>$49.99</b></div>’+
‘<div class=”prod”><span>MegaTool X</span><b>$19.99</b></div>’+
‘<div class=”prod”><span>Nano Clip</span><b>$8.50</b></div>’+
‘<div class=”prod”><span>HyperDock</span><b>$74.00</b></div>’+
‘<div class=”prod”><span>PixelCase</span><b>$14.25</b></div>’+
‘<p class=”wb-hint” model=”margin-top:8px”>&hellip;and 18 extra</p>’,
steps:[
{t:’Reading page’, c:’get_accessibility_tree’},
{t:’Extracting structured rows’, c:’extract_data’}
],
consequence:perform(){
return ‘<h4>Found 24 merchandise</h4><desk>’+
‘<tr><td>Widget Pro</td><td>$29.99</td></tr>’+
‘<tr><td>Super Gadget</td><td>$49.99</td></tr>’+
‘<tr><td>MegaTool X</td><td>$19.99</td></tr>’+
‘<tr><td>Nano Clip</td><td>$8.50</td></tr>’+
‘<tr><td>HyperDock</td><td>$74.00</td></tr>’+
‘<tr><td>PixelCase</td><td>$14.25</td></tr>’+
‘</desk><p class=”wb-note” model=”margin-top:7px”>&hellip;and 18 extra. Export as CSV or JSON.</p>’;
}
},
abstract: {
label:”Summarize article”, req:”ask”,
url:”https://journal.dev/local-ai-2026″,
immediate:”Summarize this text”,
web page:'<b>The Future of Local AI</b><p class=”wb-hint”>By Jane Smith &middot; 8 min learn</p>’+
‘<p>Local LLMs now match cloud high quality on many duties. Better quantization, quicker client GPUs, ‘+
‘and a privacy-first shift are the drivers. The writer expects most client AI to run on-device by 2026.</p>’,
steps:[
{t:’Reading page text’, c:’read_page’}
],
consequence:perform(){
return ‘<h4>Summary</h4><ul model=”margin:0;padding-left:18px”>’+
‘<li>Local LLMs now rival cloud high quality on many duties.</li>’+
‘<li>Drivers: higher quantization, quicker GPUs, privateness demand.</li>’+
‘<li>Author predicts 70%+ of client AI runs on-device by 2026.</li>’+
‘</ul><p class=”wb-note” model=”margin-top:8px”>Follow-up: <a href=”#” id=”wb-follow”>’+
‘What does the writer predict for 2026?</a></p>’;
},
observe:{
steps:[{t:’Recalling article context’, c:’scratchpad_write’}],
consequence:'<h4>Answer</h4><p>By 2026, the writer expects 70%+ of client AI workloads to run on-device.</p>’
}
},
video: {
label:”Download video”, req:”act”,
url:”https://socialvid.app/@nomad/clip-8472″,
immediate:”Download this video”,
web page:'<div class=”vid”>&#9654; Sunset timelapse over Bodrum<br><span model=”font-size:11px;opacity:.7″>’+
‘@nomad &middot; 0:24</span></div><p class=”wb-hint” model=”margin-top:8px”>Video submit</p>’,
steps:[
{t:’Listing interactive elements’, c:’get_interactive_elements’},
{t:’Capturing visible tab’, c:’screenshot’, token:true},
{t:’Locating video stream’, c:’download_resource_from_page’}
],
approve:”Download the MP4 to your machine?”,
consequence:perform(){
return ‘<h4>Saved</h4><p>Downloads/nomad-bodrum.mp4</p>’+
‘<p class=”wb-note”>1080p &middot; 24s &middot; 4.2 MB</p>’;
}
},
signup: {
label:”Fill signup type”, req:”act”,
url:”https://acmestudio.io/signup”,
immediate:”Sign me up utilizing my profile”,
web page:'<b>Create your Acme Studio account</b>’+
‘<div class=”discipline”><label>Work e-mail</label><div class=”field” id=”f-email”></div></div>’+
‘<div class=”discipline”><label>Company</label><div class=”field” id=”f-company”></div></div>’+
‘<div class=”discipline”><label>Password</label><div class=”field” id=”f-pass”></div></div>’+
‘<p class=”wb-hint”>Uses non-compulsory Profile auto-fill (saved regionally, plaintext).</p>’,
steps:[
{t:’Reading form fields’, c:’get_accessibility_tree’},
{t:’Filling email’, c:’set_field’, fill:{id:’f-email’,v:’[email protected]’}},
{t:’Filling company’, c:’set_field’, fill:{id:’f-company’,v:’Acme Labs’}},
{t:’Filling throwaway password’, c:’set_field’, fill:{id:’f-pass’,v:’&bull;&bull;&bull;&bull;&bull;&bull;&bull;&bull;’}},
{t:’Checking values before submit’, c:’verify_form’}
],
approve:”Submit the signup type and create the account?”,
consequence:perform(){
return ‘<h4>Account created</h4><p>Confirmation display screen proven by the location.</p>’+
‘<p class=”wb-note”>Profile textual content is distributed to your LLM every flip. Keep essential passwords out of it.</p>’;
}
}
};

var order = [‘products’,’summary’,’video’,’signup’];
var state = { mode:’ask’, scen:’merchandise’, operating:false, aborted:false };
var timers = [];

var $ = perform(id){ return doc.getElementById(id); };
perform clearTimers(){ timers.forEach(clearTimeout); timers = []; }

perform renderChips(){
var field = $(‘wb-chips’); field.innerHTML=”;
order.forEach(perform(ok){
var s = SCEN[k];
var b = doc.createElement(‘button’);
b.className = ‘wb-chip’ + (ok===state.scen?’ on’:”);
b.innerHTML = s.label + ‘ <span class=”req”>&middot; ‘+(s.req===’act’?’Act’:’Ask’)+'</span>’;
b.onclick = perform(){ selectScen(ok); };
field.appendChild(b);
});
}

perform renderMode(){
var seg = $(‘wb-modeseg’).querySelectorAll(‘button’);
seg.forEach(perform(b){ b.classList.toggle(‘on’, b.dataset.mode===state.mode); });
var capsule = $(‘wb-modepill’);
capsule.textContent = state.mode===’act’?’Act’:’Ask’;
capsule.className = ‘wb-mode-pill ‘+(state.mode===’act’?’act’:’ask’);
}

perform selectScen(ok){
if(state.operating) return;
state.scen = ok;
var s = SCEN[k];
$(‘wb-url’).textContent = s.url;
$(‘wb-page’).innerHTML = s.web page;
$(‘wb-input’).worth = s.immediate;
if(s.req===’act’ && state.mode!==’act’){ state.mode=’act’; }
renderChips(); renderMode(); resetLog();
}

perform resetLog(){
clearTimers(); state.operating=false; state.aborted=false;
$(‘wb-run’).model.show=”; $(‘wb-run’).disabled=false;
var cease=$(‘wb-stopbtn’); if(cease) cease.take away();
$(‘wb-log’).innerHTML = ‘<div class=”wb-hint”>Press <b>Run</b> to start out. Ask mode is read-only; Act mode can act.</div>’;
var s=SCEN[state.scen];
if(s.req===’signup’||state.scen===’signup’){ /* fields already clean in web page html */ }
}

perform addStep(html){
var d=doc.createElement(‘div’); d.className=’wb-step’; d.innerHTML=html;
$(‘wb-log’).appendChild(d); postHeight(); return d;
}

perform presentStop(){
var cease=doc.createElement(‘button’);
cease.id=’wb-stopbtn’; cease.className=’wb-stop’; cease.textContent=’Stop’;
cease.onclick=perform(){ state.aborted=true; clearTimers(); finishAbort(); };
$(‘wb-run’).model.show=’none’;
$(‘wb-run’).mother or fatherNode.appendChild(cease);
}
perform coverStop(){ var s=$(‘wb-stopbtn’); if(s) s.take away(); $(‘wb-run’).model.show=”; $(‘wb-run’).disabled=false; }

perform finishAbort(){
state.operating=false; coverStop();
addStep(‘<span model=”coloration:#b91c1c;font-weight:700″>&instances;</span> Stopped by person.’);
}

perform run(){
if(state.operating) return;
var s = SCEN[state.scen];
if(s.req===’act’ && state.mode!==’act’){
$(‘wb-log’).innerHTML=”;
addStep(‘<span model=”coloration:#4338ca;font-weight:700″>&#9432;</span> ‘+
‘Ask mode is read-only. Switch to <b>Act mode</b> to run this activity.’);
return;
}
state.operating=true; state.aborted=false;
$(‘wb-log’).innerHTML=”; $(‘wb-run’).disabled=true; presentStop();
var delay=350;
s.steps.forEach(perform(st){
timers.push(setTimeout(perform(){
if(state.aborted) return;
var el=addStep(‘<span class=”spin”></span> ‘+st.t+’ &middot; <code>’+st.c+'</code>’);
timers.push(setTimeout(perform(){
if(state.aborted) return;
el.innerHTML='<span class=”tick”>&test;</span> ‘+st.t+’ &middot; <code>’+st.c+'</code>’;
if(st.token) addStep(‘<div class=”wb-token”>Token-conscious: screenshot 2000&instances;1200 ‘+
‘resized &amp; JPEG-compressed &rarr; ~380 picture tokens (illustrative).</div>’);
if(st.fill){ var f=doc.getElementById(st.fill.id); if(f){ f.innerHTML=st.fill.v; f.classList.add(‘fill’); } }
postHeight();
}, 420));
}, delay));
delay += 780;
});
timers.push(setTimeout(perform(){
if(state.aborted) return;
if(s.approve){ askApproval(s); } else { end(s); }
}, delay+150));
}

perform askApproval(s){
var field=doc.createElement(‘div’); field.className=’wb-approve’;
field.innerHTML='<p>&#9888; Consequential motion &mdash; ‘+s.approve+'</p><div class=”row”>’+
‘<button class=”wb-yes”>Approve</button><button class=”wb-no”>Cancel</button></div>’;
$(‘wb-log’).appendChild(field); postHeight();
field.querySelector(‘.wb-yes’).onclick=perform(){ field.take away(); end(s); };
field.querySelector(‘.wb-no’).onclick=perform(){
field.take away(); state.operating=false; coverStop();
addStep(‘<span model=”coloration:#b91c1c;font-weight:700″>&instances;</span> Action cancelled. Nothing was modified.’);
};
}

perform end(s){
state.operating=false; coverStop();
var r=doc.createElement(‘div’); r.className=’wb-result’; r.innerHTML=s.consequence();
$(‘wb-log’).appendChild(r);
addStep(‘<span class=”tick”>&test;</span> Task full &middot; <code>performed</code>’);
postHeight();
if(s.observe){
var hyperlink=doc.getElementById(‘wb-follow’);
if(hyperlink) hyperlink.onclick=perform(e){ e.preventDefault(); runFollow(s); };
}
}

perform runFollow(s){
if(state.operating) return; state.operating=true; $(‘wb-run’).disabled=true; presentStop();
var d=400;
s.observe.steps.forEach(perform(st){
timers.push(setTimeout(perform(){
if(state.aborted) return;
var el=addStep(‘<span class=”spin”></span> ‘+st.t+’ &middot; <code>’+st.c+'</code>’);
timers.push(setTimeout(perform(){
if(state.aborted) return;
el.innerHTML='<span class=”tick”>&test;</span> ‘+st.t+’ &middot; <code>’+st.c+'</code>’;
},380));
},d)); d+=650;
});
timers.push(setTimeout(perform(){
if(state.aborted) return;
state.operating=false; coverStop();
var r=doc.createElement(‘div’); r.className=’wb-result’; r.innerHTML=s.observe.consequence;
$(‘wb-log’).appendChild(r); postHeight();
}, d+150));
}

// mode buttons
$(‘wb-modeseg’).querySelectorAll(‘button’).forEach(perform(b){
b.onclick=perform(){ if(state.operating) return; state.mode=b.dataset.mode; renderMode(); };
});
$(‘wb-run’).onclick=run;
$(‘wb-reset’).onclick=perform(){ state.mode=’ask’; selectScen(‘merchandise’); };
$(‘wb-input’).addEventListener(‘keydown’,perform(e){ if(e.key===’Enter’) run(); });

// auto-resize: element’s personal offsetHeight + 40 (by no means scrollHeight)
perform postHeight(){
attempt{
var el=doc.getElementById(‘wb-root’);
var h=(el?el.offsetHeight:doc.physique.offsetHeight)+40;
if(window.mother or father && window.mother or father!==window){ window.mother or father.postMessage({wbHeight:h},’*’); }
}catch(e){}
}
window.postHeight=postHeight;
window.addEventListener(‘load’,perform(){ postHeight(); setTimeout(postHeight,300); });
if(window.ResizeObserver){
attempt{ new ResizeObserver(postHeight).observe(doc.getElementById(‘wb-root’)); }catch(e){}
}

// init
renderChips(); renderMode(); selectScen(‘merchandise’);
})();
</script>
</physique>
</html>
“>

Demo-2

</div>
<div>
<h2>WebMind for Developers &mdash; Interactive Demo</h2>
<p class=”wb-sub”>Read code, extract API specs, analysis sources, and act &mdash; from the facet panel.</p>
</div>
<span class=”wb-badge”>Simulated &middot; no actual LLM calls</span>
</div>

<div class=”wb-controls”>
<div class=”wb-seg” id=”wb-modeseg”>
<button data-mode=”ask” class=”on”>Ask mode</button>
<button data-mode=”act”>Act mode</button>
</div>
<div class=”wb-chips” id=”wb-chips”></div>
</div>

<div class=”wb-grid”>
<div class=”wb-pane”>
<div class=”wb-bar”>
<div class=”wb-dots”><span class=”wb-dot” model=”background:#f87171″></span>
<span class=”wb-dot” model=”background:#fbbf24″></span>
<span class=”wb-dot” model=”background:#34d399″></span></div>
<div class=”wb-url” id=”wb-url”></div>
</div>
<div class=”wb-page” id=”wb-page”></div>
</div>

<div class=”wb-pane”>
<div class=”wb-panehead”>🧠 WebMind
<span class=”wb-mode-pill ask” id=”wb-modepill”>Ask</span>
</div>
<div class=”wb-panel”>
<div class=”wb-prompt”>
<enter id=”wb-input” sort=”textual content” autocomplete=”off”>
<button class=”wb-run” id=”wb-run”>Run</button>
</div>
<div class=”wb-log” id=”wb-log”>
<div class=”wb-hint”>Choose a activity above, then press <b>Run</b>. Read-only Ask mode is the default.</div>
</div>
</div>
</div>
</div>

<div class=”wb-foot”>
<button class=”wb-reset” id=”wb-reset”>Reset demo</button>
<span>Actions listed here are illustrative and secure. The actual extension asks earlier than consequential actions.</span>
<span class=”model”>Built by Marktechpost</span>
</div>
</div>

<script>
(perform(){
var CH = ‘wb-dev-demo’;
var SCEN = {
clarify: {
label:”Explain code”, req:”ask”,
url:”https://github.com/acme/router/blob/major/debounce.js”,
immediate:”Explain what this perform does”,
web page:'<div class=”repo”><span>&#128196;</span><span class=”path”>debounce.js</span></div>’+
‘<pre>export perform debounce(fn, wait) {n let t;n return (…args) => {n’+
‘ clearTimeout(t);n t = setTimeout(() => fn(…args), wait);n };n}</pre>’+
‘<p class=”wb-hint”>Source file view</p>’,
steps:[{t:’Reading file contents’, c:’read_page’}],
consequence:perform(){
return ‘<h4>What it does</h4><ul>’+
‘<li>Returns a wrapped model of <code>fn</code> that delays calls.</li>’+
‘<li>Each new name clears the pending timer and restarts it.</li>’+
‘<li><code>fn</code> runs solely after <code>wait</code> ms of no new calls.</li>’+
‘</ul><p class=”wb-note” model=”margin-top:8px”>Follow-up: ‘+
‘<a href=”#” id=”wb-follow”>How do I exploit it?</a></p>’;
},
observe:{
steps:[{t:’Preparing an example’, c:’scratchpad_write’}],
consequence:'<h4>Usage</h4><pre>const onSearch = debounce((q) => {n fetchResults(q);n}, 300);nninput.addEventListener(“enter”, e => onSearch(e.goal.worth));</pre>’
}
},
api: {
label:”Extract API endpoints”, req:”ask”,
url:”https://docs.acme.dev/api/reference”,
immediate:”List each endpoint and its technique from this reference”,
web page:'<b>Acme API Reference</b><p class=”wb-hint”>v1</p>’+
‘<div class=”ep”><span>List customers</span><b>GET /v1/customers</b></div>’+
‘<div class=”ep”><span>Create person</span><b>POST /v1/customers</b></div>’+
‘<div class=”ep”><span>Get person</span><b>GET /v1/customers/{id}</b></div>’+
‘<div class=”ep”><span>Update person</span><b>PATCH /v1/customers/{id}</b></div>’+
‘<div class=”ep”><span>Delete person</span><b>DELETE /v1/customers/{id}</b></div>’+
‘<div class=”ep”><span>Health test</span><b>GET /v1/well being</b></div>’,
steps:[
{t:’Reading page structure’, c:’get_accessibility_tree’},
{t:’Extracting endpoints’, c:’extract_data’}
],
consequence:perform(){
return ‘<h4>6 endpoints discovered</h4><desk>’+
‘<tr><td>GET</td><td>/v1/customers</td></tr>’+
‘<tr><td>POST</td><td>/v1/customers</td></tr>’+
‘<tr><td>GET</td><td>/v1/customers/{id}</td></tr>’+
‘<tr><td>PATCH</td><td>/v1/customers/{id}</td></tr>’+
‘<tr><td>DELETE</td><td>/v1/customers/{id}</td></tr>’+
‘<tr><td>GET</td><td>/v1/well being</td></tr>’+
‘</desk><p class=”wb-note” model=”margin-top:7px”>Export as JSON or an OpenAPI stub.</p>’;
}
},
analysis: {
label:”Research a subject”, req:”ask”,
url:”https://weblog.statelib.dev/state-in-2026″,
immediate:”Compare these two state libraries and advocate one”,
web page:'<b>State administration in 2026</b><p class=”wb-hint”>By A. Rivera &middot; 6 min learn</p>’+
‘<p>Two small libraries dominate new initiatives: StateLib and Acme Store. ‘+
‘Both are signal-based. They differ on bundle measurement, server rendering, and devtools.</p>’+
‘<p class=”wb-hint”>The agent additionally reads docs.acme-store.dev in the background.</p>’,
steps:[
{t:’Reading blog.statelib.dev’, c:’research_url’},
{t:’Reading docs.acme-store.dev’, c:’research_url’}
],
consequence:perform(){
return ‘<h4>Summary</h4><ul>’+
‘<li>Both are signal-based and ship first-class TypeScript sorts.</li>’+
‘<li>StateLib has a smaller core; Acme Store has stronger SSR assist.</li>’+
‘<li>For a server-rendered app, the sources lean Acme Store.</li>’+
‘</ul><p class=”wb-note” model=”margin-top:8px”>Illustrative synthesis from two sources. ‘+
‘<a href=”#” id=”wb-follow”>Which is smaller?</a></p>’;
},
observe:{
steps:[{t:’Checking published bundle sizes’, c:’fetch_url’}],
consequence:'<h4>Bundle measurement (illustrative)</h4><desk>’+
‘<tr><td>StateLib</td><td>3.1 kB min+gzip</td></tr>’+
‘<tr><td>Acme Store</td><td>5.4 kB min+gzip</td></tr></desk>’
}
},
star: {
label:”Star the repo”, req:”act”,
url:”https://github.com/acme/router”,
immediate:”Star this repository”,
web page:'<div class=”repo”><span>&#128193;</span><span class=”path”>acme/router</span></div>’+
‘<p model=”margin:6px 0 10px”>Tiny type-safe router for contemporary internet apps.</p>’+
‘<span id=”gh-star” model=”show:inline-block;border:1px strong #d0d7de;border-radius:7px;’+
‘padding:6px 12px;font-weight:700;font-size:12.5px;background:#f6f8fa;coloration:#1f2430″>’+
‘&#9734; Star &middot; 8.4k</span>’+
‘<p class=”wb-hint” model=”margin-top:10px”>Signed in as you on GitHub.</p>’,
steps:[
{t:’Finding the Star control’, c:’get_interactive_elements’},
{t:’Capturing visible tab’, c:’screenshot’, token:true}
],
approve:”Star this repository in your signed-in GitHub account?”,
finishStep:{t:’Clicking Star through the web page UI’, c:’click_ax’},
onFinish:perform(){
var b=doc.getElementById(‘gh-star’);
if(b){ b.innerHTML=’&#9733; Starred &middot; 8.4k’;
b.model.background=’#f8faf4′; b.model.borderColor=’#cfe6a8′; b.model.coloration=’#4f8a00′; }
},
consequence:perform(){
return ‘<h4>Done</h4><p>Repository starred by way of the seen UI &mdash; not a direct API name.</p>’+
‘<p class=”wb-note”>Ran in your authenticated session; no credentials had been saved.</p>’;
}
}
};

var order = [‘explain’,’api’,’research’,’star’];
var state = { mode:’ask’, scen:’clarify’, operating:false, aborted:false };
var timers = [];
var $ = perform(id){ return doc.getElementById(id); };
perform clearTimers(){ timers.forEach(clearTimeout); timers = []; }

perform renderChips(){
var field=$(‘wb-chips’); field.innerHTML=”;
order.forEach(perform(ok){
var s=SCEN[k];
var b=doc.createElement(‘button’);
b.className=’wb-chip’+(ok===state.scen?’ on’:”);
b.innerHTML=s.label+’ <span class=”req”>&middot; ‘+(s.req===’act’?’Act’:’Ask’)+'</span>’;
b.onclick=perform(){ selectScen(ok); };
field.appendChild(b);
});
}
perform renderMode(){
$(‘wb-modeseg’).querySelectorAll(‘button’).forEach(perform(b){ b.classList.toggle(‘on’, b.dataset.mode===state.mode); });
var capsule=$(‘wb-modepill’); capsule.textContent=state.mode===’act’?’Act’:’Ask’;
capsule.className=’wb-mode-pill ‘+(state.mode===’act’?’act’:’ask’);
}
perform selectScen(ok){
if(state.operating) return;
state.scen=ok; var s=SCEN[k];
$(‘wb-url’).textContent=s.url; $(‘wb-page’).innerHTML=s.web page; $(‘wb-input’).worth=s.immediate;
if(s.req===’act’ && state.mode!==’act’){ state.mode=’act’; }
renderChips(); renderMode(); resetLog();
}
perform resetLog(){
clearTimers(); state.operating=false; state.aborted=false;
$(‘wb-run’).model.show=”; $(‘wb-run’).disabled=false;
var cease=$(‘wb-stopbtn’); if(cease) cease.take away();
$(‘wb-log’).innerHTML='<div class=”wb-hint”>Press <b>Run</b> to start out. Ask mode is read-only; Act mode can act.</div>’;
}
perform addStep(html){
var d=doc.createElement(‘div’); d.className=’wb-step’; d.innerHTML=html;
$(‘wb-log’).appendChild(d); postHeight(); return d;
}
perform presentStop(){
var cease=doc.createElement(‘button’);
cease.id=’wb-stopbtn’; cease.className=’wb-stop’; cease.textContent=’Stop’;
cease.onclick=perform(){ state.aborted=true; clearTimers(); finishAbort(); };
$(‘wb-run’).model.show=’none’; $(‘wb-run’).mother or fatherNode.appendChild(cease);
}
perform coverStop(){ var s=$(‘wb-stopbtn’); if(s) s.take away(); $(‘wb-run’).model.show=”; $(‘wb-run’).disabled=false; }
perform finishAbort(){ state.operating=false; coverStop();
addStep(‘<span model=”coloration:#b91c1c;font-weight:700″>&instances;</span> Stopped by person.’); }

perform run(){
if(state.operating) return;
var s=SCEN[state.scen];
if(s.req===’act’ && state.mode!==’act’){
$(‘wb-log’).innerHTML=”;
addStep(‘<span model=”coloration:#4338ca;font-weight:700″>&#9432;</span> ‘+
‘Ask mode is read-only. Switch to <b>Act mode</b> to run this activity.’);
return;
}
state.operating=true; state.aborted=false;
$(‘wb-log’).innerHTML=”; $(‘wb-run’).disabled=true; presentStop();
var delay=350;
s.steps.forEach(perform(st){
timers.push(setTimeout(perform(){
if(state.aborted) return;
var el=addStep(‘<span class=”spin”></span> ‘+st.t+’ &middot; <code>’+st.c+'</code>’);
timers.push(setTimeout(perform(){
if(state.aborted) return;
el.innerHTML='<span class=”tick”>&test;</span> ‘+st.t+’ &middot; <code>’+st.c+'</code>’;
if(st.token) addStep(‘<div class=”wb-token”>Token-conscious: screenshot 2000&instances;1200 ‘+
‘resized &amp; JPEG-compressed &rarr; ~380 picture tokens (illustrative).</div>’);
postHeight();
},420));
},delay));
delay+=780;
});
timers.push(setTimeout(perform(){
if(state.aborted) return;
if(s.approve){ askApproval(s); } else { end(s); }
}, delay+150));
}
perform askApproval(s){
var field=doc.createElement(‘div’); field.className=’wb-approve’;
field.innerHTML='<p>&#9888; Consequential motion &mdash; ‘+s.approve+'</p><div class=”row”>’+
‘<button class=”wb-yes”>Approve</button><button class=”wb-no”>Cancel</button></div>’;
$(‘wb-log’).appendChild(field); postHeight();
field.querySelector(‘.wb-yes’).onclick=perform(){ field.take away(); end(s); };
field.querySelector(‘.wb-no’).onclick=perform(){
field.take away(); state.operating=false; coverStop();
addStep(‘<span model=”coloration:#b91c1c;font-weight:700″>&instances;</span> Action cancelled. Nothing was modified.’);
};
}
perform end(s){
state.operating=false; coverStop();
if(s.finishStep){ addStep(‘<span class=”tick”>&test;</span> ‘+s.finishStep.t+’ &middot; <code>’+s.finishStep.c+'</code>’); }
if(s.onFinish){ attempt{ s.onFinish(); }catch(e){} }
var r=doc.createElement(‘div’); r.className=’wb-result’; r.innerHTML=s.consequence();
$(‘wb-log’).appendChild(r);
addStep(‘<span class=”tick”>&test;</span> Task full &middot; <code>performed</code>’);
postHeight();
if(s.observe){ var hyperlink=doc.getElementById(‘wb-follow’); if(hyperlink) hyperlink.onclick=perform(e){ e.preventDefault(); runFollow(s); }; }
}
perform runFollow(s){
if(state.operating) return; state.operating=true; $(‘wb-run’).disabled=true; presentStop();
var d=400;
s.observe.steps.forEach(perform(st){
timers.push(setTimeout(perform(){
if(state.aborted) return;
var el=addStep(‘<span class=”spin”></span> ‘+st.t+’ &middot; <code>’+st.c+'</code>’);
timers.push(setTimeout(perform(){
if(state.aborted) return;
el.innerHTML='<span class=”tick”>&test;</span> ‘+st.t+’ &middot; <code>’+st.c+'</code>’;
},380));
},d)); d+=650;
});
timers.push(setTimeout(perform(){
if(state.aborted) return;
state.operating=false; coverStop();
var r=doc.createElement(‘div’); r.className=’wb-result’; r.innerHTML=s.observe.consequence;
$(‘wb-log’).appendChild(r); postHeight();
}, d+150));
}

$(‘wb-modeseg’).querySelectorAll(‘button’).forEach(perform(b){
b.onclick=perform(){ if(state.operating) return; state.mode=b.dataset.mode; renderMode(); };
});
$(‘wb-run’).onclick=run;
$(‘wb-reset’).onclick=perform(){ state.mode=’ask’; selectScen(‘clarify’); };
$(‘wb-input’).addEventListener(‘keydown’,perform(e){ if(e.key===’Enter’) run(); });

perform postHeight(){
attempt{
var el=doc.getElementById(‘wb-root’);
var h=(el?el.offsetHeight:doc.physique.offsetHeight)+40;
if(window.mother or father && window.mother or father!==window){ window.mother or father.postMessage({wbHeight:h, ch:CH},’*’); }
}catch(e){}
}
window.postHeight=postHeight;
window.addEventListener(‘load’,perform(){ postHeight(); setTimeout(postHeight,300); });
if(window.ResizeObserver){ attempt{ new ResizeObserver(postHeight).observe(doc.getElementById(‘wb-root’)); }catch(e){} }

renderChips(); renderMode(); selectScen(‘clarify’);
})();
</script>
</physique>
</html>
“>

WebMind is offered on the Chrome Web Store, Firefox Add-ons, and GitHub. Product particulars at webbrain website.


Note:Thanks to the Webbrain workforce for the thought management/ Resources for this text. Webbrain workforce has supported this content material/article for promotion.

The submit Meet WebBrain: An Open-Source, Local-First AI Browser Agent That Reads Pages and Automates Tasks in Chrome and Firefox appeared first on MarkTechPost.

Similar Posts