feat(search): add Xquik X search provider (#11370)

Merged into release/v3.8.51 via batch validation: xquik provider suites green on the combined tree (193 node:test assertions incl. your 7 new cases), check:provider-consistency OK (353 canonical providers), static gates green. Well-scoped fallbackOnly X-provider with clean citation building — thanks @kriptoburak!
This commit is contained in:
Burak Bayır
2026-08-25 07:39:39 +03:00
committed by GitHub
parent 14ca809924
commit a0ceccc6f0
70 changed files with 893 additions and 248 deletions

View File

@@ -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]