From 5617e3d11fc8f00e602805b5129d63b12d2fd633 Mon Sep 17 00:00:00 2001 From: Waleed Latif Date: Sat, 3 Oct 2026 12:09:54 -0700 Subject: [PATCH 1/3] fix(docs): cap search query length and time out the embedding call --- apps/docs/app/api/search/route.ts | 4 +++- apps/docs/lib/embeddings.ts | 3 +++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/apps/docs/app/api/search/route.ts b/apps/docs/app/api/search/route.ts index 30915b87529..32d6877f492 100644 --- a/apps/docs/app/api/search/route.ts +++ b/apps/docs/app/api/search/route.ts @@ -11,6 +11,8 @@ export const revalidate = 0 const DEFAULT_SEARCH_LIMIT = 10 const MAX_SEARCH_LIMIT = 20 +/** Bounds the paid embedding call per request; real searches are a few words. */ +const MAX_QUERY_LENGTH = 256 /** PostgreSQL text-search configuration for the docs' English content. */ const TS_CONFIG = 'english' @@ -38,7 +40,7 @@ export async function GET(request: NextRequest) { try { const { query, limit } = getSearchParams(request) - if (!query || query.trim().length === 0) { + if (query.trim().length === 0 || query.length > MAX_QUERY_LENGTH) { return NextResponse.json([]) } diff --git a/apps/docs/lib/embeddings.ts b/apps/docs/lib/embeddings.ts index c41a3f19899..67570bb7801 100644 --- a/apps/docs/lib/embeddings.ts +++ b/apps/docs/lib/embeddings.ts @@ -1,3 +1,5 @@ +const EMBEDDING_TIMEOUT_MS = 10_000 + /** * Generate embeddings for search queries using OpenAI API */ @@ -19,6 +21,7 @@ export async function generateSearchEmbedding(query: string): Promise model: 'text-embedding-3-small', encoding_format: 'float', }), + signal: AbortSignal.timeout(EMBEDDING_TIMEOUT_MS), }) if (!response.ok) { From 21ae7507226e2b6b1bb8a48d9681de5ee4f5679d Mon Sep 17 00:00:00 2001 From: Waleed Latif Date: Sat, 3 Oct 2026 12:16:30 -0700 Subject: [PATCH 2/3] fix(docs): truncate long search queries instead of dropping them --- apps/docs/app/api/search/route.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/docs/app/api/search/route.ts b/apps/docs/app/api/search/route.ts index 32d6877f492..8b3e15784df 100644 --- a/apps/docs/app/api/search/route.ts +++ b/apps/docs/app/api/search/route.ts @@ -30,7 +30,7 @@ function getSearchLimit(value: unknown): number { function getSearchParams(request: NextRequest) { const searchParams = request.nextUrl.searchParams return { - query: searchParams.get('query') || searchParams.get('q') || '', + query: (searchParams.get('query') || searchParams.get('q') || '').slice(0, MAX_QUERY_LENGTH), limit: getSearchLimit(searchParams.get('limit')), } } @@ -40,7 +40,7 @@ export async function GET(request: NextRequest) { try { const { query, limit } = getSearchParams(request) - if (query.trim().length === 0 || query.length > MAX_QUERY_LENGTH) { + if (query.trim().length === 0) { return NextResponse.json([]) } From 5841ef010f1340bd80de92f8d6a675ee0cc704a1 Mon Sep 17 00:00:00 2001 From: Waleed Latif Date: Sat, 3 Oct 2026 13:15:20 -0700 Subject: [PATCH 3/3] fix(docs): truncate search queries on a code point boundary --- apps/docs/app/api/search/route.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/apps/docs/app/api/search/route.ts b/apps/docs/app/api/search/route.ts index 8b3e15784df..7ebf6d7ae4b 100644 --- a/apps/docs/app/api/search/route.ts +++ b/apps/docs/app/api/search/route.ts @@ -1,4 +1,5 @@ import { createLogger } from '@sim/logger' +import { truncateAtCodePoint } from '@sim/utils/string' import { sql } from 'drizzle-orm' import { type NextRequest, NextResponse } from 'next/server' import { db, docsEmbeddings } from '@/lib/db' @@ -30,7 +31,11 @@ function getSearchLimit(value: unknown): number { function getSearchParams(request: NextRequest) { const searchParams = request.nextUrl.searchParams return { - query: (searchParams.get('query') || searchParams.get('q') || '').slice(0, MAX_QUERY_LENGTH), + query: truncateAtCodePoint( + searchParams.get('query') || searchParams.get('q') || '', + MAX_QUERY_LENGTH, + '' + ), limit: getSearchLimit(searchParams.get('limit')), } }