{
  "id": "web-search",
  "name": "Web-Suche",
  "version": "1.1.0",
  "type": "agent-tool",
  "author": "Astoris",
  "premium": false,
  "description": "Durchsucht das Web. Mit Brave-API-Schluessel (gratis, robust) oder ohne Schluessel via DuckDuckGo (Best-Effort, kann zeitweise limitiert sein). Schluessel optional im Feld apiKey.",
  "inputHint": "{ \"query\": \"aktuelle Nachrichten Schweiz\", \"apiKey\": \"\" }",
  "code": "// Web-Suche: Brave API (mit apiKey, robust) sonst DuckDuckGo HTML (kein Key, Best-Effort).\nasync function run(input) {\n  const q = String((input && input.query) || '').trim();\n  if (!q) return { fehler: 'Bitte eine Suchanfrage angeben.' };\n  const apiKey = String((input && input.apiKey) || '').trim();\n  function strip(s) {\n    return String(s).replace(/<[^>]+>/g, '')\n      .replace(/&amp;/g, '&').replace(/&#x27;/g, \"'\").replace(/&#39;/g, \"'\")\n      .replace(/&quot;/g, '\"').replace(/&lt;/g, '<').replace(/&gt;/g, '>')\n      .replace(/\\s+/g, ' ').trim();\n  }\n  // 1. Brave Search API (robust, wenn Schluessel vorhanden)\n  if (apiKey) {\n    const r = await fetch('https://api.search.brave.com/res/v1/web/search?count=6&q=' + encodeURIComponent(q),\n      { headers: { 'X-Subscription-Token': apiKey, 'Accept': 'application/json' } });\n    if (r.ok) {\n      const d = await r.json();\n      const items = (d.web && d.web.results) || [];\n      const ergebnisse = items.slice(0, 6).map(function (x) {\n        return { titel: strip(x.title || ''), url: x.url || '', snippet: strip(x.description || '') };\n      });\n      if (ergebnisse.length) return { anfrage: q, quelle: 'brave', ergebnisse: ergebnisse };\n    }\n  }\n  // 2. DuckDuckGo HTML (kein Key, kann zeitweise limitiert sein)\n  const res = await fetch('https://html.duckduckgo.com/html/?q=' + encodeURIComponent(q),\n    { headers: { 'user-agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120 Safari/537.36' } });\n  if (!res.ok) return { fehler: 'Suche fehlgeschlagen (HTTP ' + res.status + ').' };\n  const html = await res.text();\n  if (html.indexOf('anomaly') >= 0 && html.indexOf('result__a') < 0) {\n    return { fehler: 'DuckDuckGo limitiert die Suche gerade. Fuer robuste Suche einen gratis Brave-API-Schluessel im Feld apiKey hinterlegen.', anfrage: q };\n  }\n  const results = [];\n  const linkRe = /result__a\"\\s+href=\"([^\"]*)\"[^>]*>([\\s\\S]*?)<\\/a>/g;\n  let m;\n  while ((m = linkRe.exec(html)) !== null && results.length < 6) {\n    let url = m[1];\n    const uddg = url.match(/uddg=([^&]*)/);\n    if (uddg) { try { url = decodeURIComponent(uddg[1]); } catch (e) {} }\n    if (url.indexOf('//') === 0) url = 'https:' + url;\n    if (url.indexOf('y.js') >= 0 || url.indexOf('ad_domain') >= 0) continue;\n    results.push({ titel: strip(m[2]), url: url });\n  }\n  if (!results.length) return { fehler: 'Keine Ergebnisse gefunden.', anfrage: q };\n  return { anfrage: q, quelle: 'duckduckgo', ergebnisse: results };\n}"
}