export interface CustomWidgetAiExpectation { sourceBaseUrl: string; sourceNetworkScope?: "public" | "private" | "loopback"; sourceAuth: "none" | "bearer" | "basic" | "apiKeyHeader" | "apiKeyQuery"; sourceAuthName?: string; minimumTemplateCharacters?: number; requests: Array<{ kind: "query" | "action"; method: "GET" | "POST"; pathIncludes: string; trigger?: "load" | "manual"; permission?: "view" | "modify" | "full"; queryIncludes?: Record; bodyIncludes?: Record; invalidates?: string[]; invalidatesPaths?: string[]; requiresConfirmation?: boolean; requiresStatusBinding?: boolean; }>; templateIncludes?: string[]; templateIncludesAny?: string[][]; } export interface CustomWidgetAiEvaluationCase { id: string; request: string; documentationUrl: string; apiNotes: string; sampleResponse?: unknown; previewResponses?: Array<{ pathIncludes: string; kind?: "query" | "action"; method?: "GET" | "POST"; response: unknown; }>; minimumPreviewCycles?: number; expectations?: CustomWidgetAiExpectation; expectedWidgets?: Array<{ id: string; request: string; apiNotes?: string; expectations: CustomWidgetAiExpectation; }>; research?: { query: string; requiredReferences: Array<"schema" | "runtime" | "security">; allowedReferences?: Array<"schema" | "runtime" | "security">; }; } const seerrSourceApiNotes = "Use the suggested self-hosted source http://seerr.local:5055/api/v1 with private network scope and X-Api-Key header authentication."; const seerrRequestOperationsApiNotes = "GET /request/count returns total, movie, tv, pending, approved, declined, processing, available, and completed counts. GET /request accepts take, skip, filter, sort, sortDirection, requestedBy, and mediaType; use fixed primitives take=10, skip=0, sort=added, and sortDirection=desc. Its response has pageInfo.pages/pageSize/results/page and a results array whose entries include id, type, numeric status, createdAt, profileName, requestedBy.displayName, and media.tmdbId/mediaType/status/status4k. Request status values are 1 Pending, 2 Approved, 3 Declined, 4 Failed, and 5 Completed. For managers, POST /request/{param:requestId}/approve and POST /request/{param:requestId}/decline change a pending request's status without a body; show them only for status 1, confirm both, and invalidate the count and list queries. This scoped widget intentionally uses text pageInfo context and does not require media-title joins, search requests, or interactive pagination."; const seerrMediaResearchApiNotes = "GET /search requires query and accepts optional page. Its entire response is an envelope with page, totalPages, totalResults, and results; mixed result entries include id, mediaType, title or name, overview, posterPath, backdropPath, voteAverage, releaseDate or firstAirDate, and mediaInfo.status/status4k, so render the array at response.results rather than mapping the envelope. TMDB artwork paths are relative: build a full https://image.tmdb.org/t/p/w780 URL from backdropPath with posterPath fallback. POST /request requires mediaType and mediaId; TV requests can use seasons='all'. Both request actions need modify permission, confirmation, and must invalidate the search query after success. This scoped widget intentionally does not require request counts, a request queue, status filters, or sorting."; const seerrMediaStatusApiNotes = "Both media.status and mediaInfo.status/status4k use 1 Unknown, 2 Pending, 3 Processing, 4 Partially Available, 5 Available, 6 Blocklisted, and 7 Deleted. Render readable labels rather than raw codes."; export const CUSTOM_WIDGET_AI_EVALUATION_CASES: readonly CustomWidgetAiEvaluationCase[] = [ { id: "pokedex", documentationUrl: "https://pokeapi.co/docs/v2", request: "Create a complete Pokédex widget using PokéAPI. Make at least three deliberate refinement passes through validation and preview testing. It must have a substantial polished UI with a direct name lookup, a searchable loaded list that stays visible while details open in a separate responsive result area, sprites, types, abilities, base-stat progress bars, and clear initial, loading, empty, failure, and success states. Use a restrained accent and flexible tile sizing rather than repetitive nested cards or a fixed-height list. Completeness must come from tested useful interactions, not filler JSX.", apiNotes: "Use GET /api/v2/pokemon?limit=