{
"event": "PreToolUse",
"tool_name": "Edit",
"tool_input": {
"file_path": "\/var\/www\/dev.campus.systemische-tools.de\/crawler\/src\/infrastructure\/fetchers\/web_vitals_collector.py",
"old_string": "def parse_vitals(raw: Any) -> dict[str, float | int | None]:\n if not isinstance(raw, dict):\n return {\"lcp_ms\": None, \"cls\": None, \"tbt_ms\": None}\n return {\n \"lcp_ms\": _opt_int(raw.get(\"lcp\")),\n \"cls\": _opt_float(raw.get(\"cls\")),\n \"tbt_ms\": _opt_int(raw.get(\"tbt\")),\n }\n\n\ndef _opt_int(value: object) -> int | None:\n if value is None:\n return None\n try:\n return int(value)\n except (TypeError, ValueError):\n return None\n\n\ndef _opt_float(value: object) -> float | None:\n if value is None:\n return None\n try:\n return round(float(value), 4)\n except (TypeError, ValueError):\n return None",
"new_string": "def parse_vitals(raw: Any) -> Vitals: # noqa: ANN401 — JS eval returns dynamic types\n if not isinstance(raw, dict):\n return Vitals(lcp_ms=None, cls=None, tbt_ms=None)\n return Vitals(\n lcp_ms=_opt_int(raw.get(\"lcp\")),\n cls=_opt_float(raw.get(\"cls\")),\n tbt_ms=_opt_int(raw.get(\"tbt\")),\n )\n\n\ndef _opt_int(value: object) -> int | None:\n if isinstance(value, (int, float)):\n return int(value)\n return None\n\n\ndef _opt_float(value: object) -> float | None:\n if isinstance(value, (int, float)):\n return round(float(value), 4)\n return None",
"replace_all": false
}
}
{
"tool_response": {
"filePath": "\/var\/www\/dev.campus.systemische-tools.de\/crawler\/src\/infrastructure\/fetchers\/web_vitals_collector.py",
"oldString": "def parse_vitals(raw: Any) -> dict[str, float | int | None]:\n if not isinstance(raw, dict):\n return {\"lcp_ms\": None, \"cls\": None, \"tbt_ms\": None}\n return {\n \"lcp_ms\": _opt_int(raw.get(\"lcp\")),\n \"cls\": _opt_float(raw.get(\"cls\")),\n \"tbt_ms\": _opt_int(raw.get(\"tbt\")),\n }\n\n\ndef _opt_int(value: object) -> int | None:\n if value is None:\n return None\n try:\n return int(value)\n except (TypeError, ValueError):\n return None\n\n\ndef _opt_float(value: object) -> float | None:\n if value is None:\n return None\n try:\n return round(float(value), 4)\n except (TypeError, ValueError):\n return None",
"newString": "def parse_vitals(raw: Any) -> Vitals: # noqa: ANN401 — JS eval returns dynamic types\n if not isinstance(raw, dict):\n return Vitals(lcp_ms=None, cls=None, tbt_ms=None)\n return Vitals(\n lcp_ms=_opt_int(raw.get(\"lcp\")),\n cls=_opt_float(raw.get(\"cls\")),\n tbt_ms=_opt_int(raw.get(\"tbt\")),\n )\n\n\ndef _opt_int(value: object) -> int | None:\n if isinstance(value, (int, float)):\n return int(value)\n return None\n\n\ndef _opt_float(value: object) -> float | None:\n if isinstance(value, (int, float)):\n return round(float(value), 4)\n return None",
"originalFile": "\"\"\"Collects Core Web Vitals via PerformanceObserver injected into the page.\"\"\"\n\nfrom __future__ import annotations\n\nfrom typing import Any, TypedDict\n\n\nclass Vitals(TypedDict):\n lcp_ms: int | None\n cls: float | None\n tbt_ms: int | None\n\nINIT_SCRIPT = \"\"\"\nwindow.__webVitals = { lcp: null, cls: 0, tbt: 0 };\ntry {\n new PerformanceObserver((list) => {\n const last = list.getEntries().at(-1);\n if (last) window.__webVitals.lcp = Math.round(last.startTime);\n }).observe({ type: 'largest-contentful-paint', buffered: true });\n} catch (_) {}\ntry {\n new PerformanceObserver((list) => {\n for (const e of list.getEntries()) {\n if (!e.hadRecentInput) window.__webVitals.cls += e.value;\n }\n }).observe({ type: 'layout-shift', buffered: true });\n} catch (_) {}\ntry {\n new PerformanceObserver((list) => {\n for (const e of list.getEntries()) {\n window.__webVitals.tbt += Math.max(0, e.duration - 50);\n }\n }).observe({ type: 'longtask', buffered: true });\n} catch (_) {}\n\"\"\"\n\nREAD_SCRIPT = \"window.__webVitals || { lcp: null, cls: null, tbt: null }\"\n\n\ndef parse_vitals(raw: Any) -> dict[str, float | int | None]:\n if not isinstance(raw, dict):\n return {\"lcp_ms\": None, \"cls\": None, \"tbt_ms\": None}\n return {\n \"lcp_ms\": _opt_int(raw.get(\"lcp\")),\n \"cls\": _opt_float(raw.get(\"cls\")),\n \"tbt_ms\": _opt_int(raw.get(\"tbt\")),\n }\n\n\ndef _opt_int(value: object) -> int | None:\n if value is None:\n return None\n try:\n return int(value)\n except (TypeError, ValueError):\n return None\n\n\ndef _opt_float(value: object) -> float | None:\n if value is None:\n return None\n try:\n return round(float(value), 4)\n except (TypeError, ValueError):\n return None\n",
"structuredPatch": [
{
"oldStart": 37,
"oldLines": 29,
"newStart": 37,
"newLines": 23,
"lines": [
" READ_SCRIPT = \"window.__webVitals || { lcp: null, cls: null, tbt: null }\"",
" ",
" ",
"-def parse_vitals(raw: Any) -> dict[str, float | int | None]:",
"+def parse_vitals(raw: Any) -> Vitals: # noqa: ANN401 — JS eval returns dynamic types",
" if not isinstance(raw, dict):",
"- return {\"lcp_ms\": None, \"cls\": None, \"tbt_ms\": None}",
"- return {",
"- \"lcp_ms\": _opt_int(raw.get(\"lcp\")),",
"- \"cls\": _opt_float(raw.get(\"cls\")),",
"- \"tbt_ms\": _opt_int(raw.get(\"tbt\")),",
"- }",
"+ return Vitals(lcp_ms=None, cls=None, tbt_ms=None)",
"+ return Vitals(",
"+ lcp_ms=_opt_int(raw.get(\"lcp\")),",
"+ cls=_opt_float(raw.get(\"cls\")),",
"+ tbt_ms=_opt_int(raw.get(\"tbt\")),",
"+ )",
" ",
" ",
" def _opt_int(value: object) -> int | None:",
"- if value is None:",
"- return None",
"- try:",
"+ if isinstance(value, (int, float)):",
" return int(value)",
"- except (TypeError, ValueError):",
"- return None",
"+ return None",
" ",
" ",
" def _opt_float(value: object) -> float | None:",
"- if value is None:",
"- return None",
"- try:",
"+ if isinstance(value, (int, float)):",
" return round(float(value), 4)",
"- except (TypeError, ValueError):",
"- return None",
"+ return None"
]
}
],
"userModified": false,
"replaceAll": false
}
}