{
  "id": "deepfake-check",
  "name": "Deepfake-Check",
  "version": "1.2.0",
  "type": "agent-tool",
  "author": "Astoris",
  "premium": true,
  "description": "Prueft ein Bild auf Manipulation (Deepfake + KI-Generierung, Sightengine) mit 4-stufiger Bewertung. Akzeptiert eine oeffentliche Bild-URL ODER ein hochgeladenes Bild (data-URL). Braucht api_user + api_secret (Gratis-Tier sightengine.com).",
  "inputHint": "{ \"imageUrl\": \"https://...\", \"imageData\": \"data:image/...;base64,...\", \"apiUser\": \"\", \"apiSecret\": \"\" }",
  "code": "// Deepfake-/Manipulations-Check via Sightengine. Bild als oeffentliche URL ODER hochgeladene data-URL (Multipart).\nasync function run(input) {\n  const apiUser = String((input && input.apiUser) || '').trim();\n  const apiSecret = String((input && input.apiSecret) || '').trim();\n  if (!apiUser || !apiSecret) return { fehler: 'Sightengine api_user und api_secret noetig (Gratis-Tier auf sightengine.com).' };\n  const imageData = String((input && input.imageData) || '').trim();\n  const imageUrl = String((input && input.imageUrl) || '').trim();\n  let d;\n  try {\n    let res;\n    if (imageData) {\n      const m = imageData.match(/^data:(image\\/[a-z0-9.+-]+);base64,(.+)$/i);\n      if (!m) return { fehler: 'Ungueltiges Bildformat — erwartet data:image/...;base64,...' };\n      const bin = atob(m[2]);\n      const arr = new Uint8Array(bin.length);\n      for (let i = 0; i < bin.length; i++) arr[i] = bin.charCodeAt(i);\n      const fd = new FormData();\n      fd.append('media', new Blob([arr], { type: m[1] }), 'image');\n      fd.append('models', 'deepfake,genai');\n      fd.append('api_user', apiUser);\n      fd.append('api_secret', apiSecret);\n      res = await fetch('https://api.sightengine.com/1.0/check.json', { method: 'POST', body: fd });\n    } else if (/^https?:\\/\\//.test(imageUrl)) {\n      const ep = 'https://api.sightengine.com/1.0/check.json?models=deepfake,genai'\n        + '&api_user=' + encodeURIComponent(apiUser) + '&api_secret=' + encodeURIComponent(apiSecret)\n        + '&url=' + encodeURIComponent(imageUrl);\n      res = await fetch(ep);\n    } else {\n      return { fehler: 'Bitte imageUrl (oeffentliche URL) oder imageData (hochgeladenes Bild als data-URL) angeben.' };\n    }\n    if (!res.ok) return { fehler: 'Sightengine HTTP ' + res.status + ' — Schluessel oder Kontingent pruefen.' };\n    d = await res.json();\n  } catch (e) {\n    return { fehler: 'Sightengine nicht erreichbar (Zeitueberschreitung oder Netzwerkfehler).' };\n  }\n  if (!d || d.status !== 'success') return { fehler: (d && d.error && d.error.message) || 'Pruefung fehlgeschlagen.' };\n  const deepfake = (d.type && typeof d.type.deepfake === 'number') ? d.type.deepfake : 0;\n  const aiGen = (d.type && typeof d.type.ai_generated === 'number') ? d.type.ai_generated : 0;\n  const score = Math.max(deepfake, aiGen);\n  function stufe(s) {\n    if (s < 0.2) return 'sehr wahrscheinlich echt';\n    if (s < 0.5) return 'unklar';\n    if (s < 0.8) return 'wahrscheinlich manipuliert';\n    return 'sehr wahrscheinlich manipuliert';\n  }\n  return {\n    gesamtscore: Math.round(score * 1000) / 1000, prozent: Math.round(score * 100) + '%',\n    bewertung: stufe(score),\n    signale: { deepfakeGesicht: Math.round(deepfake * 100) + '%', kiGeneriert: Math.round(aiGen * 100) + '%' },\n    quelle: imageData ? 'Upload' : 'URL',\n    hinweis: 'Wahrscheinlichkeit, kein forensischer Beweis.'\n  };\n}",
  "configFields": [
    {
      "key": "apiUser",
      "label": "Sightengine API User",
      "type": "text",
      "placeholder": "von sightengine.com"
    },
    {
      "key": "apiSecret",
      "label": "Sightengine API Secret",
      "type": "password",
      "placeholder": "geheim"
    }
  ]
}