# retoor <retoor@molodetz.nl>

from .._shared import endpoint, field

GROUP = {
        "slug": "tools",
        "title": "Tools (SEO, DeepSearch & AI Usage Analyzer)",
        "intro": """
# Tools: SEO Diagnostics & DeepSearch

Two public developer tools that run as background jobs.

**SEO Diagnostics** audits a URL or sitemap with a headless browser and runs a broad battery of
technical, on-page, structured-data, Core Web Vitals, accessibility and AI-readiness checks.

**DeepSearch** is a multi-agent deep web researcher that crawls and indexes sources, then
synthesises a cited report with confidence scoring and gap analysis, plus a grounded chat over
the results.

**AI Usage Analyzer** classifies a git repository or website as AI slop, sophisticated AI-assisted
work or genuine human work, and publishes a persistent report with an embeddable authenticity
badge.

Every endpoint follows the shared [Conventions & Errors](/docs/conventions.html). These are
**capability URLs**: the job `uid` is an unguessable identifier, so anyone holding it can read the
status and report.
""",
        "endpoints": [
            endpoint(
                id="tools-seo-run",
                method="POST",
                path="/tools/seo/run",
                title="Queue an SEO audit",
                summary="Start a background SEO audit of a URL or sitemap. Returns the job uid plus status and websocket URLs.",
                auth="public",
                encoding="form",
                params=[
                    field("url", "form", "string", True, "https://example.com", "Page URL or sitemap.xml URL to audit."),
                    field("mode", "form", "enum", False, "url", "'url' (single page) or 'sitemap' (crawl).", ["url", "sitemap"]),
                    field("max_pages", "form", "integer", False, "10", "Max pages to crawl in sitemap mode (1-50)."),
                ],
                sample_response={
                    "uid": "SEO_JOB_UID",
                    "status_url": "/tools/seo/SEO_JOB_UID",
                    "ws_url": "/tools/seo/SEO_JOB_UID/ws",
                },
            ),
            endpoint(
                id="tools-seo-status",
                method="GET",
                path="/tools/seo/{uid}",
                title="SEO audit status",
                summary="Poll an SEO audit. Once done, score, grade and report_url are populated.",
                auth="public",
                params=[
                    field("uid", "path", "string", True, "SEO_JOB_UID", "SEO job uid returned when the audit was queued."),
                ],
                sample_response={
                    "uid": "SEO_JOB_UID",
                    "kind": "seo",
                    "status": "done",
                    "target": "https://example.com",
                    "mode": "url",
                    "ws_url": "/tools/seo/SEO_JOB_UID/ws",
                    "report_url": "/tools/seo/SEO_JOB_UID/report",
                    "score": 82,
                    "grade": "B",
                    "page_count": 1,
                    "error": None,
                    "created_at": "2026-06-14T10:00:00+00:00",
                    "completed_at": "2026-06-14T10:00:18+00:00",
                },
            ),
            endpoint(
                id="tools-seo-report",
                method="GET",
                path="/tools/seo/{uid}/report",
                title="SEO audit report",
                summary="Full categorised report: overall score, per-category subscores, and every check with its recommendation. Negotiates HTML or JSON.",
                auth="public",
                params=[
                    field("uid", "path", "string", True, "SEO_JOB_UID", "SEO job uid of a finished audit."),
                ],
                sample_response={
                    "uid": "SEO_JOB_UID",
                    "status": "done",
                    "target": "https://example.com",
                    "score": 82,
                    "grade": "B",
                    "page_count": 1,
                    "counts": {"pass": 40, "warn": 8, "fail": 3, "info": 5, "skip": 0},
                    "categories": {"crawlability": {"score": 90, "pass": 9, "warn": 1, "fail": 0}},
                    "pages": [{"url": "https://example.com", "status": 200, "score": 82, "grade": "B"}],
                    "checks": [
                        {
                            "id": "meta.title_present",
                            "category": "meta",
                            "title": "Title tag",
                            "status": "pass",
                            "severity": "high",
                            "value": "Example Domain",
                            "recommendation": "",
                            "url": "https://example.com",
                        }
                    ],
                    "site": {"robots": {"status": 200}, "sitemap": {"status": 200, "url_count": 12}},
                    "generated_at": "2026-06-14T10:00:18+00:00",
                },
            ),
            endpoint(
                id="tools-seo-screenshot",
                method="GET",
                path="/tools/seo/{uid}/screenshot/{index}",
                title="SEO audit page screenshot",
                summary="Stream the rendered screenshot (image/png) captured for the audited page at the given zero-based index.",
                auth="public",
                interactive=True,
                params=[
                    field("uid", "path", "string", True, "SEO_JOB_UID", "SEO job uid of a finished audit."),
                    field("index", "path", "integer", True, "0", "Zero-based index of the audited page."),
                ],
            ),
            endpoint(
                id="tools-seo-meta-status",
                method="GET",
                path="/tools/seo-meta/{target_type}/{target_uid}",
                title="Generated SEO metadata for a content item",
                summary="Read the clean, AI-generated SEO title, description and keywords for a published post, project, gist, news article or issue. Returns a plain-content default with status 'pending' until the AI value is ready.",
                auth="public",
                params=[
                    field("target_type", "path", "enum", True, "post", "Content type.", ["post", "project", "gist", "news", "issue"]),
                    field("target_uid", "path", "string", True, "CONTENT_UID", "The content uid (or issue number)."),
                ],
                sample_response={
                    "uid": "SEO_META_UID",
                    "target_type": "post",
                    "target_uid": "CONTENT_UID",
                    "seo_title": "Building a fast SQLite social network",
                    "seo_description": "How DevPlace keeps SQLite synchronous and still serves a developer social network fast, with WAL, mmap and batch query helpers.",
                    "seo_keywords": "sqlite, fastapi, social network, performance, wal",
                    "status": "ready",
                    "source": "ai",
                    "generated_at": "2026-06-14T10:00:18+00:00",
                },
            ),
            endpoint(
                id="tools-deepsearch-run",
                method="POST",
                path="/tools/deepsearch/run",
                title="Queue a DeepSearch research job",
                summary="Start a multi-agent deep web research job. Returns the job uid plus status and websocket URLs. Connect ws_url for live progress frames.",
                auth="public",
                encoding="form",
                params=[
                    field("query", "form", "string", True, "history of the transistor", "The research question to investigate."),
                    field("depth", "form", "integer", False, "2", "Research depth (1-4)."),
                    field("max_pages", "form", "integer", False, "12", "Maximum sources to crawl (1-30)."),
                ],
                sample_response={
                    "uid": "DEEPSEARCH_JOB_UID",
                    "status_url": "/tools/deepsearch/DEEPSEARCH_JOB_UID",
                    "ws_url": "/tools/deepsearch/DEEPSEARCH_JOB_UID/ws",
                    "progress_frames_note": (
                        "The ws_url stream emits newline-delimited JSON frames; the set is append-only "
                        "and the first frame carries version:1. Each frame has a type: phase "
                        "(phase, index, total, label), stage, substep (planning angles), queries, "
                        "candidates, rsearch, progress (done, total, url), page_loaded (source, render, "
                        "elapsed_ms, done, total), page_cached, page_skipped (reason), page_duplicate, "
                        "embed_batch (batch, total_batches, backend, done, total), embed_done (backend, "
                        "chunk_count), agent (agent, status start|done, elapsed_ms, tokens_in, tokens_out), "
                        "report_ready, done (session_url), failed (message)."
                    ),
                },
            ),
            endpoint(
                id="tools-deepsearch-status",
                method="GET",
                path="/tools/deepsearch/{uid}",
                title="DeepSearch status",
                summary="Poll a DeepSearch job. Once done, score, confidence and session_url are populated.",
                auth="public",
                params=[
                    field("uid", "path", "string", True, "DEEPSEARCH_JOB_UID", "DeepSearch job uid returned when the run was queued."),
                ],
                sample_response={
                    "uid": "DEEPSEARCH_JOB_UID",
                    "kind": "deepsearch",
                    "status": "done",
                    "query": "history of the transistor",
                    "depth": 2,
                    "max_pages": 12,
                    "ws_url": "/tools/deepsearch/DEEPSEARCH_JOB_UID/ws",
                    "chat_ws_url": "/tools/deepsearch/DEEPSEARCH_JOB_UID/chat",
                    "session_url": "/tools/deepsearch/DEEPSEARCH_JOB_UID/session",
                    "score": 78,
                    "confidence": 0.72,
                    "source_diversity": 0.64,
                    "page_count": 11,
                    "chunk_count": 240,
                    "error": None,
                    "created_at": "2026-06-14T10:00:00+00:00",
                    "completed_at": "2026-06-14T10:01:40+00:00",
                },
            ),
            endpoint(
                id="tools-deepsearch-session",
                method="GET",
                path="/tools/deepsearch/{uid}/session",
                title="DeepSearch report",
                summary="Full cited research report: summary, findings, sources and metrics. Negotiates HTML or JSON.",
                auth="public",
                params=[
                    field("uid", "path", "string", True, "DEEPSEARCH_JOB_UID", "DeepSearch job uid of a finished run."),
                ],
                sample_response={
                    "uid": "DEEPSEARCH_JOB_UID",
                    "status": "done",
                    "query": "history of the transistor",
                    "score": 78,
                    "confidence": 0.72,
                    "source_diversity": 0.64,
                    "page_count": 11,
                    "chunk_count": 240,
                    "summary": "The transistor was invented at Bell Labs in 1947...",
                    "findings": [
                        {"title": "Invention", "detail": "...", "confidence": 0.8, "citations": [1]}
                    ],
                    "sources": [{"url": "https://example.com", "title": "Example", "source": "httpx"}],
                    "follow_up_questions": ["Who else worked on the transistor?", "How did it replace vacuum tubes?"],
                    "chat_ws_url": "/tools/deepsearch/DEEPSEARCH_JOB_UID/chat",
                    "export_md_url": "/tools/deepsearch/DEEPSEARCH_JOB_UID/export.md",
                    "export_json_url": "/tools/deepsearch/DEEPSEARCH_JOB_UID/export.json",
                    "export_pdf_url": "/tools/deepsearch/DEEPSEARCH_JOB_UID/export.pdf",
                },
            ),
            endpoint(
                id="tools-isslop-run",
                method="POST",
                path="/tools/isslop/run",
                title="Queue a AI usage analysis",
                summary="Start a background authenticity analysis of a git repository or website. Returns the job uid plus status, events and report URLs.",
                auth="public",
                encoding="form",
                params=[
                    field("url", "form", "string", True, "https://github.com/owner/repository", "Repository (http/git/ssh) or website URL to classify."),
                ],
                sample_response={
                    "uid": "ISSLOP_UID",
                    "status_url": "/tools/isslop/ISSLOP_UID",
                    "events_url": "/tools/isslop/ISSLOP_UID/events",
                    "report_url": "/tools/isslop/ISSLOP_UID/report",
                    "topic": "public.isslop.ISSLOP_UID",
                },
            ),
            endpoint(
                id="tools-isslop-list",
                method="GET",
                path="/tools/isslop/list",
                title="My AI usage analyses",
                summary="List the caller's analyses, newest first. Member history is account-bound; guest history is session-bound and claimed by the account on first signed-in call.",
                auth="public",
                params=[
                    field("limit", "query", "integer", False, "50", "Maximum analyses to return (1-200)."),
                ],
                sample_response={
                    "analyses": [
                        {
                            "uid": "ISSLOP_UID",
                            "status": "completed",
                            "source_url": "https://github.com/owner/repository",
                            "source_kind": "git",
                            "grade": "B",
                            "human_percent": 71.4,
                            "ai_percent": 28.6,
                            "category": "human-clean",
                            "report_url": "/tools/isslop/ISSLOP_UID/report",
                            "badge_url": "/tools/isslop/ISSLOP_UID/badge.svg",
                        }
                    ]
                },
            ),
            endpoint(
                id="tools-isslop-status",
                method="GET",
                path="/tools/isslop/{uid}",
                title="AI usage analysis status",
                summary="Poll an analysis. Once completed, grade, category and the human/AI split are populated.",
                auth="public",
                params=[
                    field("uid", "path", "string", True, "ISSLOP_UID", "Analysis uid returned when the run was queued."),
                ],
                sample_response={
                    "uid": "ISSLOP_UID",
                    "status": "completed",
                    "source_url": "https://github.com/owner/repository",
                    "source_kind": "git",
                    "grade": "B",
                    "slop_score": 31.2,
                    "origin_score": 28.0,
                    "quality_deficit_score": 22.5,
                    "human_percent": 71.4,
                    "ai_percent": 28.6,
                    "category": "human-clean",
                    "confidence": "medium",
                    "files_total": 120,
                    "files_analyzed": 96,
                    "report_url": "/tools/isslop/ISSLOP_UID/report",
                    "badge_url": "/tools/isslop/ISSLOP_UID/badge.svg",
                    "events_url": "/tools/isslop/ISSLOP_UID/events",
                    "topic": "public.isslop.ISSLOP_UID",
                },
            ),
            endpoint(
                id="tools-isslop-events",
                method="GET",
                path="/tools/isslop/{uid}/events",
                title="AI usage analysis event trail",
                summary="The persisted, ordered event trail of an analysis. Use ?after=SEQ to poll incrementally; live frames also stream on the pub/sub topic.",
                auth="public",
                params=[
                    field("uid", "path", "string", True, "ISSLOP_UID", "Analysis uid."),
                    field("after", "query", "integer", False, "0", "Return only events with a sequence number greater than this."),
                    field("limit", "query", "integer", False, "2000", "Maximum events to return (1-5000)."),
                ],
                sample_response={
                    "uid": "ISSLOP_UID",
                    "status": "running",
                    "events": [
                        {"seq": 1, "kind": "stage", "message": "Resolving source type", "data": {"stage": "resolve"}, "created_at": "2026-06-14T10:00:00+00:00"}
                    ],
                },
            ),
            endpoint(
                id="tools-isslop-report",
                method="GET",
                path="/tools/isslop/{uid}/report",
                title="AI usage analysis report",
                summary="Full report: verdict, markdown body, per-file results, image review and badge embeds. Negotiates HTML or JSON.",
                auth="public",
                params=[
                    field("uid", "path", "string", True, "ISSLOP_UID", "Analysis uid of a finished run."),
                ],
                sample_response={
                    "uid": "ISSLOP_UID",
                    "status": "completed",
                    "source_url": "https://github.com/owner/repository",
                    "grade": "B",
                    "human_percent": 71.4,
                    "ai_percent": 28.6,
                    "category": "human-clean",
                    "markdown": "# Verdict...",
                    "generator_model": "molodetz",
                    "badge": {
                        "badge_url": "https://devplace.example/tools/isslop/ISSLOP_UID/badge.svg",
                        "report_url": "https://devplace.example/tools/isslop/ISSLOP_UID/report",
                        "markdown": "[![authenticity human score](...)](...)",
                        "html": "<a href=...><img src=.../></a>",
                    },
                    "files": [{"path": "src/main.py", "language": "python", "lines": 120, "origin_score": 35.0, "quality_deficit_score": 18.0, "category": "human-clean", "signals": []}],
                    "images": [{"path": "assets/hero.png", "ai_probability": 84.0, "grade": "F", "verdict": "ai-generated", "image_kind": "illustration", "tells": ["waxy skin"], "description": "...", "thumb_url": "/tools/isslop/ISSLOP_UID/media/0f3a9c2d1b4e5a67.webp"}],
                },
            ),
            endpoint(
                id="tools-isslop-report-md",
                method="GET",
                path="/tools/isslop/{uid}/report.md",
                title="Download report markdown",
                summary="Download the full report as a markdown file.",
                auth="public",
                params=[
                    field("uid", "path", "string", True, "ISSLOP_UID", "Analysis uid of a finished run."),
                ],
            ),
            endpoint(
                id="tools-isslop-source",
                method="GET",
                path="/tools/isslop/{uid}/source",
                title="Annotated source of a flagged file",
                summary="The persisted source of a signal-bearing file with its signals, rendered with line numbers and highlighted findings (HTML) or as JSON. Linked from the report's file table, signal chips and prose.",
                auth="public",
                params=[
                    field("uid", "path", "string", True, "ISSLOP_UID", "Analysis uid."),
                    field("path", "query", "string", True, "src/libs/Env.ts", "Workspace-relative file path from the report."),
                    field("line", "query", "integer", False, "12", "Line to focus and highlight."),
                ],
                sample_response={
                    "uid": "ISSLOP_UID",
                    "path": "src/libs/Env.ts",
                    "language": "typescript",
                    "category": "human-clean",
                    "origin_score": 24.0,
                    "quality_deficit_score": 34.9,
                    "source": "import { createEnv } from '@t3-oss/env-nextjs';...",
                    "truncated": False,
                    "signals": [{"code": "PUBLIC_ENV_SECRET", "title": "Secret exposed via public env variable", "severity": "strong", "line": 12}],
                },
            ),
            endpoint(
                id="tools-isslop-media",
                method="GET",
                path="/tools/isslop/{uid}/media/{name}",
                title="Reviewed image thumbnail",
                summary="Aspect-preserving WebP thumbnail of a reviewed image, persisted as evidence. The name comes from the report's images[].thumb_url.",
                auth="public",
                params=[
                    field("uid", "path", "string", True, "ISSLOP_UID", "Analysis uid."),
                    field("name", "path", "string", True, "0f3a9c2d1b4e5a67.webp", "Thumbnail file name from the report."),
                ],
            ),
            endpoint(
                id="tools-isslop-badge",
                method="GET",
                path="/tools/isslop/{uid}/badge.svg",
                title="Authenticity badge",
                summary="Embeddable SVG badge showing the human score and authenticity grade, linking to the report.",
                auth="public",
                params=[
                    field("uid", "path", "string", True, "ISSLOP_UID", "Analysis uid."),
                ],
            ),
        ],
}
