import type { GoogleBooksVolumeItem, GoogleBooksVolumeSearchParams, GoogleBooksVolumeSearchResponse, VolumeInfo, } from '@/tools/google_books/types' import type { ToolConfig } from '@/tools/types' function extractVolumeInfo(item: GoogleBooksVolumeItem): VolumeInfo { const info = item.volumeInfo const identifiers = info.industryIdentifiers ?? [] return { id: item.id, title: info.title ?? '', subtitle: info.subtitle ?? null, authors: info.authors ?? [], publisher: info.publisher ?? null, publishedDate: info.publishedDate ?? null, description: info.description ?? null, pageCount: info.pageCount ?? null, categories: info.categories ?? [], averageRating: info.averageRating ?? null, ratingsCount: info.ratingsCount ?? null, language: info.language ?? null, previewLink: info.previewLink ?? null, infoLink: info.infoLink ?? null, thumbnailUrl: info.imageLinks?.thumbnail ?? info.imageLinks?.smallThumbnail ?? null, isbn10: identifiers.find((id) => id.type === 'ISBN_10')?.identifier ?? null, isbn13: identifiers.find((id) => id.type === 'ISBN_13')?.identifier ?? null, } } export const googleBooksVolumeSearchTool: ToolConfig< GoogleBooksVolumeSearchParams, GoogleBooksVolumeSearchResponse > = { id: 'google_books_volume_search', name: 'Google Books Volume Search', description: 'Search for books using the Google Books API', version: '1.0.0', params: { apiKey: { type: 'string', required: true, visibility: 'user-only', description: 'Google Books API key', }, query: { type: 'string', required: true, visibility: 'user-or-llm', description: 'Search query. Supports special keywords: intitle:, inauthor:, inpublisher:, subject:, isbn:', }, filter: { type: 'string', required: false, visibility: 'user-or-llm', description: 'Filter results by availability (partial, full, free-ebooks, paid-ebooks, ebooks)', }, printType: { type: 'string', required: false, visibility: 'user-or-llm', description: 'Restrict to print type (all, books, magazines)', }, orderBy: { type: 'string', required: false, visibility: 'user-or-llm', description: 'Sort order (relevance, newest)', }, startIndex: { type: 'number', required: false, visibility: 'user-or-llm', description: 'Index of the first result to return (for pagination)', }, maxResults: { type: 'number', required: false, visibility: 'user-or-llm', description: 'Maximum number of results to return (1-40)', }, langRestrict: { type: 'string', required: false, visibility: 'user-or-llm', description: 'Restrict results to a specific language (ISO 639-1 code)', }, }, hosting: { envKeyPrefix: 'GOOGLE_CLOUD_API_KEY', apiKeyParam: 'apiKey', byokProviderId: 'google_cloud', pricing: { type: 'per_request', cost: 0, }, rateLimit: { mode: 'per_request', requestsPerMinute: 30, }, }, request: { url: (params) => { const url = new URL('https://www.googleapis.com/books/v1/volumes') url.searchParams.set('q', params.query.trim()) url.searchParams.set('key', params.apiKey.trim()) if (params.filter) { url.searchParams.set('filter', params.filter) } if (params.printType) { url.searchParams.set('printType', params.printType) } if (params.orderBy) { url.searchParams.set('orderBy', params.orderBy) } if (params.startIndex !== undefined) { url.searchParams.set('startIndex', String(params.startIndex)) } if (params.maxResults !== undefined) { url.searchParams.set('maxResults', String(params.maxResults)) } if (params.langRestrict) { url.searchParams.set('langRestrict', params.langRestrict) } return url.toString() }, method: 'GET', headers: () => ({ 'Content-Type': 'application/json', }), }, transformResponse: async (response: Response) => { const data = await response.json() const items: GoogleBooksVolumeItem[] = data.items ?? [] const volumes = items.map(extractVolumeInfo) return { success: true, output: { totalItems: data.totalItems ?? 0, volumes, }, } }, outputs: { totalItems: { type: 'number', description: 'Total number of matching results', }, volumes: { type: 'array', description: 'List of matching volumes', items: { type: 'object', properties: { id: { type: 'string', description: 'Volume ID' }, title: { type: 'string', description: 'Book title' }, subtitle: { type: 'string', description: 'Book subtitle' }, authors: { type: 'array', description: 'List of authors' }, publisher: { type: 'string', description: 'Publisher name' }, publishedDate: { type: 'string', description: 'Publication date' }, description: { type: 'string', description: 'Book description' }, pageCount: { type: 'number', description: 'Number of pages' }, categories: { type: 'array', description: 'Book categories' }, averageRating: { type: 'number', description: 'Average rating (1-5)' }, ratingsCount: { type: 'number', description: 'Number of ratings' }, language: { type: 'string', description: 'Language code' }, previewLink: { type: 'string', description: 'Link to preview on Google Books' }, infoLink: { type: 'string', description: 'Link to info page' }, thumbnailUrl: { type: 'string', description: 'Book cover thumbnail URL' }, isbn10: { type: 'string', description: 'ISBN-10 identifier' }, isbn13: { type: 'string', description: 'ISBN-13 identifier' }, }, }, }, }, }