From 22da128df42ed4cf92f0bebab14f6e6245265b4b Mon Sep 17 00:00:00 2001 From: kriptoburak Date: Mon, 24 Aug 2026 12:05:15 +0300 Subject: [PATCH] fix(search): document API and update dispatch golden --- docs/openapi.yaml | 195 ++++++++++++++++++ tests/snapshots/executors/dispatch-rules.json | 5 + 2 files changed, 200 insertions(+) diff --git a/docs/openapi.yaml b/docs/openapi.yaml index 7ce251c6a5..4e1ca84180 100644 --- a/docs/openapi.yaml +++ b/docs/openapi.yaml @@ -43,6 +43,8 @@ tags: description: Content moderation - name: Rerank description: Document reranking + - name: Search + description: Unified web, news, and X search - name: Models description: Available model listing - name: Providers @@ -1153,6 +1155,199 @@ paths: $ref: "#/components/responses/Unauthorized" # ─── Proxy Endpoints ────────────────────────────────────────── + /api/v1/search: + get: + tags: [Search] + summary: List search providers + description: Lists configured search providers and their supported search types. + responses: + "200": + description: Search provider catalog + content: + application/json: + schema: + type: object + required: [object, data] + properties: + object: + type: string + const: list + data: + type: array + items: + type: object + required: [id, object, created, name, search_types] + properties: + id: + type: string + object: + type: string + const: search_provider + created: + type: integer + name: + type: string + search_types: + type: array + items: + type: string + enum: [web, news, x] + post: + tags: [Search] + summary: Run a unified search + description: >- + Searches the web, news, or X through a configured provider. Set `provider` + to `xquik-search` to use Xquik for X search. The aliases `xquik` and + `xquik_search` resolve to the same provider. + security: + - BearerAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [query] + properties: + query: + type: string + minLength: 1 + maxLength: 500 + provider: + type: string + minLength: 1 + description: A search provider id or registered alias. + examples: [xquik-search] + max_results: + type: integer + minimum: 1 + maximum: 100 + default: 5 + search_type: + type: string + enum: [web, news, x] + default: web + offset: + type: integer + minimum: 0 + default: 0 + country: + type: string + maxLength: 2 + language: + type: string + minLength: 2 + maxLength: 5 + time_range: + type: string + enum: [any, hour, day, week, month, year] + content: + type: object + properties: + snippet: { type: boolean, default: true } + full_page: { type: boolean, default: false } + format: { type: string, enum: [text, markdown], default: text } + max_characters: { type: integer, minimum: 100, maximum: 100000 } + filters: + type: object + properties: + include_domains: + type: array + maxItems: 20 + items: { type: string, maxLength: 253 } + exclude_domains: + type: array + maxItems: 20 + items: { type: string, maxLength: 253 } + safe_search: { type: string, enum: [off, moderate, strict] } + provider_options: + type: object + additionalProperties: true + strict_filters: + type: boolean + default: false + additionalProperties: true + responses: + "200": + description: Normalized search results + content: + application/json: + schema: + type: object + required: [id, provider, query, results, answer, usage, metrics, errors, cached] + properties: + id: + type: string + pattern: ^search- + provider: + type: string + query: + type: string + cached: + type: boolean + results: + type: array + items: + type: object + required: [title, url, snippet, position, citation] + properties: + title: { type: string } + url: { type: string, format: uri } + display_url: { type: string } + snippet: { type: string } + position: { type: integer, minimum: 1 } + score: + type: [number, "null"] + minimum: 0 + maximum: 1 + published_at: { type: [string, "null"] } + favicon_url: { type: [string, "null"], format: uri } + citation: + type: object + required: [provider, retrieved_at, rank] + properties: + provider: { type: string } + retrieved_at: { type: string, format: date-time } + rank: { type: integer, minimum: 1 } + answer: + type: [object, "null"] + usage: + type: object + required: [queries_used, search_cost_usd] + properties: + queries_used: { type: integer, minimum: 0 } + search_cost_usd: { type: number, minimum: 0 } + llm_tokens: { type: integer, minimum: 0 } + metrics: + type: object + required: [response_time_ms, upstream_latency_ms, total_results_available] + properties: + response_time_ms: { type: number, minimum: 0 } + upstream_latency_ms: { type: number, minimum: 0 } + gateway_latency_ms: { type: number, minimum: 0 } + total_results_available: { type: [integer, "null"], minimum: 0 } + errors: + type: array + items: + type: object + required: [provider, code, message] + properties: + provider: { type: string } + code: { type: string } + message: { type: string } + "400": + description: Invalid request, provider, credentials, or search type + "401": + $ref: "#/components/responses/Unauthorized" + "403": + description: Search provider blocked by API key or security policy + "429": + description: Every eligible provider credential is rate limited + "500": + $ref: "#/components/responses/InternalError" + "502": + description: Search provider failed + /api/v1/chat/completions: post: tags: [Chat] diff --git a/tests/snapshots/executors/dispatch-rules.json b/tests/snapshots/executors/dispatch-rules.json index 3bd060eed4..a06d955196 100644 --- a/tests/snapshots/executors/dispatch-rules.json +++ b/tests/snapshots/executors/dispatch-rules.json @@ -87,6 +87,11 @@ "status": 400, "throws": true }, + "xquik-search": { + "message": "Provider \"xquik-search\" is a search provider and does not support chat completions; use the /v1/search endpoint instead.", + "status": 400, + "throws": true + }, "youcom-search": { "message": "Provider \"youcom-search\" is a search provider and does not support chat completions; use the /v1/search endpoint instead.", "status": 400,