Files
gnome-jarvis/vendor/agent-harness/lib/web-process.js
T
snxraven aa06c71fe1
Rolling release / release (push) Failing after 1m46s
obsidian
2026-09-14 11:24:10 -04:00

161 lines
6.2 KiB
JavaScript

/**
* Web browsing stays on the local Chrome window. Groq only thinks about
* browser results. Other tools stay on the local model.
*/
const RETIRED_WEB = new Set([
'web_search',
'google_search',
'fetch_page',
'web_fetch',
'wiki_search',
'hn_search',
'code_search',
]);
const CANON = {
search: 'web_search',
websearch: 'web_search',
google: 'google_search',
googlesearch: 'google_search',
fetch: 'web_fetch',
webfetch: 'web_fetch',
fetchpage: 'fetch_page',
open_url: 'fetch_page',
openurl: 'fetch_page',
};
function fold(name) {
return String(name || '').trim().toLowerCase().replace(/[\s-]+/g, '_');
}
function canonicalWeb(name) {
const folded = fold(name);
return CANON[folded] || folded;
}
function isRetiredWeb(name) {
return RETIRED_WEB.has(canonicalWeb(name));
}
const { duckduckgoSearchUrl } = require('../../../browser-use/startpage.cjs');
function searchUrl(query, engine) {
const q = encodeURIComponent(String(query || '').trim());
const id = fold(engine) || 'duckduckgo';
if (id === 'duckduckgo' || id === 'ddg' || id === 'startpage' || id === 'start' || id === 'auto') {
return duckduckgoSearchUrl(query);
}
if (id === 'google') return 'https://www.google.com/search?q=' + q;
if (id === 'bing') return 'https://www.bing.com/search?q=' + q;
if (id === 'wikipedia' || id === 'wiki') return 'https://en.wikipedia.org/w/index.php?search=' + q;
if (id === 'hn' || id === 'hackernews') return 'https://hn.algolia.com/?q=' + q;
if (id === 'github') return 'https://github.com/search?q=' + q + '&type=repositories';
if (id === 'npm') return 'https://www.npmjs.com/search?q=' + q;
if (id === 'mdn') return 'https://developer.mozilla.org/en-US/search?q=' + q;
if (id === 'stackoverflow') return 'https://stackoverflow.com/search?q=' + q;
if (id === 'arxiv') return 'https://arxiv.org/search/?query=' + q + '&searchtype=all';
return duckduckgoSearchUrl(query);
}
function asBrowserCall(name, args) {
const canonical = canonicalWeb(name);
const input = args && typeof args === 'object' && !Array.isArray(args) ? args : {};
if (!RETIRED_WEB.has(canonical)) return { name, arguments: input };
if (canonical === 'web_fetch' || canonical === 'fetch_page') {
return { name: 'browser', arguments: { action: 'navigate', url: String(input.url || input.href || '') } };
}
const engine = canonical === 'wiki_search' ? 'wikipedia'
: canonical === 'hn_search' ? 'hn'
: canonical === 'code_search' ? (input.engine || 'github')
: 'duckduckgo';
return { name: 'browser', arguments: { action: 'navigate', url: searchUrl(input.query || input.q, engine) } };
}
function callName(call) {
if (!call) return '';
return call.name || (call.function && call.function.name) || '';
}
function isPageVisionFollowUp(msg) {
if (!msg || msg.role !== 'user') return false;
const text = String(msg.content || '');
if (/slices of one open page|open browser page|page_text is the full readable page/i.test(text)) return true;
return Array.isArray(msg.attachments) && msg.attachments.length > 0 && /do not only describe/i.test(text);
}
function needsGroqWebProcess(history) {
const list = Array.isArray(history) ? history : [];
for (let i = list.length - 1; i >= 0; i--) {
const msg = list[i];
if (!msg || !msg.role) continue;
if (msg.role === 'user' && isPageVisionFollowUp(msg)) continue;
if (msg.role === 'user') return false;
if (msg.role === 'tool' || msg.role === 'function') return callName(msg) === 'browser' || msg.name === 'browser';
if (msg.role === 'assistant' && Array.isArray(msg.tool_calls) && msg.tool_calls.length) {
const names = msg.tool_calls.map(callName).filter(Boolean);
return names.length > 0 && names.every((n) => n === 'browser');
}
if (msg.role === 'assistant') return false;
}
return false;
}
function browserToolsOnly(tools) {
return (Array.isArray(tools) ? tools : []).filter((tool) => {
if (!tool) return false;
return tool.name === 'browser' || (tool.function && tool.function.name === 'browser');
});
}
const GROQ_WEB_HINT = 'This turn is web-page processing only. Chrome already scrolled the open page and left the window open. page_text is the full readable page, not just the first screen. Read it from start to end. Draft the spoken report now from those facts: names, numbers, dates, titles, and the points the page states. A search-results page is enough for that report. You may open one result afterward for more detail, but do not stop after thinking and do not wait for another page before speaking. Do not call file, shell, desktop, or camera tools. Those stay on the local model.';
function latestBrowserReading(history) {
const list = Array.isArray(history) ? history : [];
for (let i = list.length - 1; i >= 0; i--) {
const msg = list[i];
if (!msg || (msg.role !== 'tool' && msg.role !== 'function')) continue;
if (msg.name !== 'browser' && !String(msg.content || '').includes('\npage_text:\n')) continue;
return String(msg.content || '');
}
return '';
}
function pageReport(reading) {
const raw = String(reading || '');
const split = raw.split('\npage_text:\n');
const body = (split.length > 1 ? split.slice(1).join('\npage_text:\n') : raw)
.split('\nrefs:')[0]
.split('\nRead page_text')[0];
const lines = body.split('\n').map((line) => line.replace(/\s+/g, ' ').trim()).filter((line) => {
if (!line || line.length < 12) return false;
if (/^(url|title|coverage|headings|tables|visible|page_text):/.test(line)) return false;
if (line === '(no readable text yet)') return false;
if (/cookie|privacy policy|sign in|log in|accept all/i.test(line)) return false;
return true;
});
const picked = [];
for (const line of lines) {
const clean = line.replace(/^[-*]\s*/, '');
if (picked.some((item) => item === clean)) continue;
picked.push(clean);
if (picked.length >= 8) break;
}
if (!picked.length) return '';
return 'Here is what the open page says. ' + picked.join('. ').replace(/\.\./g, '.');
}
module.exports = {
RETIRED_WEB,
canonicalWeb,
isRetiredWeb,
asBrowserCall,
needsGroqWebProcess,
isPageVisionFollowUp,
pageReport,
latestBrowserReading,
browserToolsOnly,
GROQ_WEB_HINT,
searchUrl,
};