import { formatServiceError, isAbortError } from "../shared/errors"; import { fetchJson, fetchText } from "../shared/http"; import { CONTEXT7_API_BASE, type LibraryResult, type LibrarySearchResponse } from "../types"; function buildContext7Headers(apiKey: string | null): Record { const headers: Record = { "Content-Type": "application/json" }; if (apiKey) headers.Authorization = `Bearer ${apiKey}`; return headers; } /** * Resolves a user-supplied library/query pair to the first Context7 library match. * Returns `{ id, name }` on success or `{ error }` for provider/HTTP failures; abort errors are rethrown. * Accepts both array and `{ results }` response shapes and falls back from `name` to `title` to `id`. */ export async function resolveContext7Library(library: string, query: string, apiKey: string | null, signal?: AbortSignal): Promise<{ id: string; name: string } | { error: string }> { try { const params = new URLSearchParams({ libraryName: library, query }); const data = await fetchJson(`${CONTEXT7_API_BASE}/libs/search?${params}`, { headers: buildContext7Headers(apiKey), signal, }); const results = Array.isArray(data) ? data : (data.results ?? []); if (!results.length) { return { error: `No library found matching \"${library}\"` }; } const first = results[0]; return { id: first.id, name: first.name ?? first.title ?? first.id }; } catch (error) { if (isAbortError(error)) throw error; return { error: `Library search failed: ${formatServiceError("Context7", error)}` }; } } /** * Fetches documentation content for a resolved Context7 library id and query. * Returns `{ content }` on success or `{ error }` for provider/HTTP failures; abort errors are rethrown. * Sends the already-resolved id unchanged and leaves snippet/query normalization to Context7. */ export async function fetchContext7Docs(libraryId: string, query: string, apiKey: string | null, signal?: AbortSignal): Promise<{ content: string } | { error: string }> { try { const params = new URLSearchParams({ libraryId, query }); const content = await fetchText(`${CONTEXT7_API_BASE}/context?${params}`, { headers: buildContext7Headers(apiKey), signal, }); return { content }; } catch (error) { if (isAbortError(error)) throw error; return { error: `Docs fetch failed: ${formatServiceError("Context7", error)}` }; } }