mirror of
https://github.com/simstudioai/sim.git
synced 2026-02-13 07:55:09 -05:00
feat(google books): Add google books integration
This commit is contained in:
@@ -1157,6 +1157,21 @@ export function AirweaveIcon(props: SVGProps<SVGSVGElement>) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function GoogleBooksIcon(props: SVGProps<SVGSVGElement>) {
|
||||||
|
return (
|
||||||
|
<svg {...props} xmlns='http://www.w3.org/2000/svg' viewBox='0 0 478.633 540.068'>
|
||||||
|
<path
|
||||||
|
fill='#1C51A4'
|
||||||
|
d='M449.059,218.231L245.519,99.538l-0.061,193.23c0.031,1.504-0.368,2.977-1.166,4.204c-0.798,1.258-1.565,1.995-2.915,2.547c-1.35,0.552-2.792,0.706-4.204,0.399c-1.412-0.307-2.7-1.043-3.713-2.117l-69.166-70.609l-69.381,70.179c-1.013,0.982-2.301,1.657-3.652,1.903c-1.381,0.246-2.792,0.092-4.081-0.491c-1.289-0.583-1.626-0.522-2.394-1.749c-0.767-1.197-1.197-2.608-1.197-4.081L85.031,6.007l-2.915-1.289C43.973-11.638,0,16.409,0,59.891v420.306c0,46.029,49.312,74.782,88.775,51.767l360.285-210.138C488.491,298.782,488.491,241.246,449.059,218.231z'
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
fill='#80D7FB'
|
||||||
|
d='M88.805,8.124c-2.179-1.289-4.419-2.363-6.659-3.345l0.123,288.663c0,1.442,0.43,2.854,1.197,4.081c0.767,1.197,1.872,2.148,3.161,2.731c1.289,0.583,2.7,0.736,4.081,0.491c1.381-0.246,2.639-0.921,3.652-1.903l69.749-69.688l69.811,69.749c1.013,1.074,2.301,1.81,3.713,2.117c1.412,0.307,2.884,0.153,4.204-0.399c1.319-0.552,2.455-1.565,3.253-2.792c0.798-1.258,1.197-2.731,1.166-4.204V99.998L88.805,8.124z'
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
export function GoogleDocsIcon(props: SVGProps<SVGSVGElement>) {
|
export function GoogleDocsIcon(props: SVGProps<SVGSVGElement>) {
|
||||||
return (
|
return (
|
||||||
<svg
|
<svg
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ import {
|
|||||||
GithubIcon,
|
GithubIcon,
|
||||||
GitLabIcon,
|
GitLabIcon,
|
||||||
GmailIcon,
|
GmailIcon,
|
||||||
|
GoogleBooksIcon,
|
||||||
GoogleCalendarIcon,
|
GoogleCalendarIcon,
|
||||||
GoogleDocsIcon,
|
GoogleDocsIcon,
|
||||||
GoogleDriveIcon,
|
GoogleDriveIcon,
|
||||||
@@ -172,6 +173,7 @@ export const blockTypeToIconMap: Record<string, IconComponent> = {
|
|||||||
github_v2: GithubIcon,
|
github_v2: GithubIcon,
|
||||||
gitlab: GitLabIcon,
|
gitlab: GitLabIcon,
|
||||||
gmail_v2: GmailIcon,
|
gmail_v2: GmailIcon,
|
||||||
|
google_books: GoogleBooksIcon,
|
||||||
google_calendar_v2: GoogleCalendarIcon,
|
google_calendar_v2: GoogleCalendarIcon,
|
||||||
google_docs: GoogleDocsIcon,
|
google_docs: GoogleDocsIcon,
|
||||||
google_drive: GoogleDriveIcon,
|
google_drive: GoogleDriveIcon,
|
||||||
|
|||||||
96
apps/docs/content/docs/en/tools/google_books.mdx
Normal file
96
apps/docs/content/docs/en/tools/google_books.mdx
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
---
|
||||||
|
title: Google Books
|
||||||
|
description: Search and retrieve book information
|
||||||
|
---
|
||||||
|
|
||||||
|
import { BlockInfoCard } from "@/components/ui/block-info-card"
|
||||||
|
|
||||||
|
<BlockInfoCard
|
||||||
|
type="google_books"
|
||||||
|
color="#FFFFFF"
|
||||||
|
/>
|
||||||
|
|
||||||
|
## Usage Instructions
|
||||||
|
|
||||||
|
Search for books using the Google Books API. Find volumes by title, author, ISBN, or keywords, and retrieve detailed information about specific books including descriptions, ratings, and publication details.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Tools
|
||||||
|
|
||||||
|
### `google_books_volume_search`
|
||||||
|
|
||||||
|
Search for books using the Google Books API
|
||||||
|
|
||||||
|
#### Input
|
||||||
|
|
||||||
|
| Parameter | Type | Required | Description |
|
||||||
|
| --------- | ---- | -------- | ----------- |
|
||||||
|
| `apiKey` | string | Yes | Google Books API key |
|
||||||
|
| `query` | string | Yes | Search query. Supports special keywords: intitle:, inauthor:, inpublisher:, subject:, isbn: |
|
||||||
|
| `filter` | string | No | Filter results by availability \(partial, full, free-ebooks, paid-ebooks, ebooks\) |
|
||||||
|
| `printType` | string | No | Restrict to print type \(all, books, magazines\) |
|
||||||
|
| `orderBy` | string | No | Sort order \(relevance, newest\) |
|
||||||
|
| `startIndex` | number | No | Index of the first result to return \(for pagination\) |
|
||||||
|
| `maxResults` | number | No | Maximum number of results to return \(1-40\) |
|
||||||
|
| `langRestrict` | string | No | Restrict results to a specific language \(ISO 639-1 code\) |
|
||||||
|
|
||||||
|
#### Output
|
||||||
|
|
||||||
|
| Parameter | Type | Description |
|
||||||
|
| --------- | ---- | ----------- |
|
||||||
|
| `totalItems` | number | Total number of matching results |
|
||||||
|
| `volumes` | array | List of matching volumes |
|
||||||
|
| ↳ `id` | string | Volume ID |
|
||||||
|
| ↳ `title` | string | Book title |
|
||||||
|
| ↳ `subtitle` | string | Book subtitle |
|
||||||
|
| ↳ `authors` | array | List of authors |
|
||||||
|
| ↳ `publisher` | string | Publisher name |
|
||||||
|
| ↳ `publishedDate` | string | Publication date |
|
||||||
|
| ↳ `description` | string | Book description |
|
||||||
|
| ↳ `pageCount` | number | Number of pages |
|
||||||
|
| ↳ `categories` | array | Book categories |
|
||||||
|
| ↳ `averageRating` | number | Average rating \(1-5\) |
|
||||||
|
| ↳ `ratingsCount` | number | Number of ratings |
|
||||||
|
| ↳ `language` | string | Language code |
|
||||||
|
| ↳ `previewLink` | string | Link to preview on Google Books |
|
||||||
|
| ↳ `infoLink` | string | Link to info page |
|
||||||
|
| ↳ `thumbnailUrl` | string | Book cover thumbnail URL |
|
||||||
|
| ↳ `isbn10` | string | ISBN-10 identifier |
|
||||||
|
| ↳ `isbn13` | string | ISBN-13 identifier |
|
||||||
|
|
||||||
|
### `google_books_volume_details`
|
||||||
|
|
||||||
|
Get detailed information about a specific book volume
|
||||||
|
|
||||||
|
#### Input
|
||||||
|
|
||||||
|
| Parameter | Type | Required | Description |
|
||||||
|
| --------- | ---- | -------- | ----------- |
|
||||||
|
| `apiKey` | string | Yes | Google Books API key |
|
||||||
|
| `volumeId` | string | Yes | The ID of the volume to retrieve |
|
||||||
|
| `projection` | string | No | Projection level \(full, lite\) |
|
||||||
|
|
||||||
|
#### Output
|
||||||
|
|
||||||
|
| Parameter | Type | Description |
|
||||||
|
| --------- | ---- | ----------- |
|
||||||
|
| `id` | string | Volume ID |
|
||||||
|
| `title` | string | Book title |
|
||||||
|
| `subtitle` | string | Book subtitle |
|
||||||
|
| `authors` | array | List of authors |
|
||||||
|
| `publisher` | string | Publisher name |
|
||||||
|
| `publishedDate` | string | Publication date |
|
||||||
|
| `description` | string | Book description |
|
||||||
|
| `pageCount` | number | Number of pages |
|
||||||
|
| `categories` | array | Book categories |
|
||||||
|
| `averageRating` | number | Average rating \(1-5\) |
|
||||||
|
| `ratingsCount` | number | Number of ratings |
|
||||||
|
| `language` | string | Language code |
|
||||||
|
| `previewLink` | string | Link to preview on Google Books |
|
||||||
|
| `infoLink` | string | Link to info page |
|
||||||
|
| `thumbnailUrl` | string | Book cover thumbnail URL |
|
||||||
|
| `isbn10` | string | ISBN-10 identifier |
|
||||||
|
| `isbn13` | string | ISBN-13 identifier |
|
||||||
|
|
||||||
|
|
||||||
@@ -33,6 +33,7 @@
|
|||||||
"github",
|
"github",
|
||||||
"gitlab",
|
"gitlab",
|
||||||
"gmail",
|
"gmail",
|
||||||
|
"google_books",
|
||||||
"google_calendar",
|
"google_calendar",
|
||||||
"google_docs",
|
"google_docs",
|
||||||
"google_drive",
|
"google_drive",
|
||||||
|
|||||||
198
apps/sim/blocks/blocks/google_books.ts
Normal file
198
apps/sim/blocks/blocks/google_books.ts
Normal file
@@ -0,0 +1,198 @@
|
|||||||
|
import { GoogleBooksIcon } from '@/components/icons'
|
||||||
|
import type { BlockConfig } from '@/blocks/types'
|
||||||
|
|
||||||
|
export const GoogleBooksBlock: BlockConfig = {
|
||||||
|
type: 'google_books',
|
||||||
|
name: 'Google Books',
|
||||||
|
description: 'Search and retrieve book information',
|
||||||
|
longDescription:
|
||||||
|
'Search for books using the Google Books API. Find volumes by title, author, ISBN, or keywords, and retrieve detailed information about specific books including descriptions, ratings, and publication details.',
|
||||||
|
docsLink: 'https://docs.sim.ai/tools/google_books',
|
||||||
|
category: 'tools',
|
||||||
|
bgColor: '#E0E0E0',
|
||||||
|
icon: GoogleBooksIcon,
|
||||||
|
|
||||||
|
subBlocks: [
|
||||||
|
{
|
||||||
|
id: 'operation',
|
||||||
|
title: 'Operation',
|
||||||
|
type: 'dropdown',
|
||||||
|
options: [
|
||||||
|
{ label: 'Search Volumes', id: 'volume_search' },
|
||||||
|
{ label: 'Get Volume Details', id: 'volume_details' },
|
||||||
|
],
|
||||||
|
value: () => 'volume_search',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'apiKey',
|
||||||
|
title: 'API Key',
|
||||||
|
type: 'short-input',
|
||||||
|
password: true,
|
||||||
|
placeholder: 'Enter your Google Books API key',
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'query',
|
||||||
|
title: 'Search Query',
|
||||||
|
type: 'short-input',
|
||||||
|
placeholder: 'e.g., intitle:harry potter inauthor:rowling',
|
||||||
|
condition: { field: 'operation', value: 'volume_search' },
|
||||||
|
required: { field: 'operation', value: 'volume_search' },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'filter',
|
||||||
|
title: 'Filter',
|
||||||
|
type: 'dropdown',
|
||||||
|
options: [
|
||||||
|
{ label: 'None', id: '' },
|
||||||
|
{ label: 'Partial Preview', id: 'partial' },
|
||||||
|
{ label: 'Full Preview', id: 'full' },
|
||||||
|
{ label: 'Free eBooks', id: 'free-ebooks' },
|
||||||
|
{ label: 'Paid eBooks', id: 'paid-ebooks' },
|
||||||
|
{ label: 'All eBooks', id: 'ebooks' },
|
||||||
|
],
|
||||||
|
condition: { field: 'operation', value: 'volume_search' },
|
||||||
|
mode: 'advanced',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'printType',
|
||||||
|
title: 'Print Type',
|
||||||
|
type: 'dropdown',
|
||||||
|
options: [
|
||||||
|
{ label: 'All', id: 'all' },
|
||||||
|
{ label: 'Books', id: 'books' },
|
||||||
|
{ label: 'Magazines', id: 'magazines' },
|
||||||
|
],
|
||||||
|
value: () => 'all',
|
||||||
|
condition: { field: 'operation', value: 'volume_search' },
|
||||||
|
mode: 'advanced',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'orderBy',
|
||||||
|
title: 'Order By',
|
||||||
|
type: 'dropdown',
|
||||||
|
options: [
|
||||||
|
{ label: 'Relevance', id: 'relevance' },
|
||||||
|
{ label: 'Newest', id: 'newest' },
|
||||||
|
],
|
||||||
|
value: () => 'relevance',
|
||||||
|
condition: { field: 'operation', value: 'volume_search' },
|
||||||
|
mode: 'advanced',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'maxResults',
|
||||||
|
title: 'Max Results',
|
||||||
|
type: 'short-input',
|
||||||
|
placeholder: 'Number of results (1-40)',
|
||||||
|
condition: { field: 'operation', value: 'volume_search' },
|
||||||
|
mode: 'advanced',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'startIndex',
|
||||||
|
title: 'Start Index',
|
||||||
|
type: 'short-input',
|
||||||
|
placeholder: 'Starting index for pagination',
|
||||||
|
condition: { field: 'operation', value: 'volume_search' },
|
||||||
|
mode: 'advanced',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'langRestrict',
|
||||||
|
title: 'Language',
|
||||||
|
type: 'short-input',
|
||||||
|
placeholder: 'ISO 639-1 code (e.g., en, es, fr)',
|
||||||
|
condition: { field: 'operation', value: 'volume_search' },
|
||||||
|
mode: 'advanced',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'volumeId',
|
||||||
|
title: 'Volume ID',
|
||||||
|
type: 'short-input',
|
||||||
|
placeholder: 'Google Books volume ID',
|
||||||
|
condition: { field: 'operation', value: 'volume_details' },
|
||||||
|
required: { field: 'operation', value: 'volume_details' },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'projection',
|
||||||
|
title: 'Projection',
|
||||||
|
type: 'dropdown',
|
||||||
|
options: [
|
||||||
|
{ label: 'Full', id: 'full' },
|
||||||
|
{ label: 'Lite', id: 'lite' },
|
||||||
|
],
|
||||||
|
value: () => 'full',
|
||||||
|
mode: 'advanced',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
|
tools: {
|
||||||
|
access: ['google_books_volume_search', 'google_books_volume_details'],
|
||||||
|
config: {
|
||||||
|
tool: (params) => `google_books_${params.operation}`,
|
||||||
|
params: (params) => {
|
||||||
|
const { operation, ...rest } = params
|
||||||
|
|
||||||
|
let maxResults: number | undefined
|
||||||
|
if (params.maxResults) {
|
||||||
|
maxResults = Number.parseInt(params.maxResults, 10)
|
||||||
|
if (Number.isNaN(maxResults)) {
|
||||||
|
maxResults = undefined
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let startIndex: number | undefined
|
||||||
|
if (params.startIndex) {
|
||||||
|
startIndex = Number.parseInt(params.startIndex, 10)
|
||||||
|
if (Number.isNaN(startIndex)) {
|
||||||
|
startIndex = undefined
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
...rest,
|
||||||
|
maxResults,
|
||||||
|
startIndex,
|
||||||
|
filter: params.filter || undefined,
|
||||||
|
printType: params.printType || undefined,
|
||||||
|
orderBy: params.orderBy || undefined,
|
||||||
|
projection: params.projection || undefined,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
inputs: {
|
||||||
|
operation: { type: 'string', description: 'Operation to perform' },
|
||||||
|
apiKey: { type: 'string', description: 'Google Books API key' },
|
||||||
|
query: { type: 'string', description: 'Search query' },
|
||||||
|
filter: { type: 'string', description: 'Filter by availability' },
|
||||||
|
printType: { type: 'string', description: 'Print type filter' },
|
||||||
|
orderBy: { type: 'string', description: 'Sort order' },
|
||||||
|
maxResults: { type: 'string', description: 'Maximum number of results' },
|
||||||
|
startIndex: { type: 'string', description: 'Starting index for pagination' },
|
||||||
|
langRestrict: { type: 'string', description: 'Language restriction' },
|
||||||
|
volumeId: { type: 'string', description: 'Volume ID for details' },
|
||||||
|
projection: { type: 'string', description: 'Projection level' },
|
||||||
|
},
|
||||||
|
|
||||||
|
outputs: {
|
||||||
|
totalItems: { type: 'number', description: 'Total number of matching results' },
|
||||||
|
volumes: { type: 'json', description: 'List of matching volumes' },
|
||||||
|
id: { type: 'string', description: 'Volume ID' },
|
||||||
|
title: { type: 'string', description: 'Book title' },
|
||||||
|
subtitle: { type: 'string', description: 'Book subtitle' },
|
||||||
|
authors: { type: 'json', 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: 'json', 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' },
|
||||||
|
},
|
||||||
|
}
|
||||||
@@ -39,6 +39,7 @@ import { GitHubBlock, GitHubV2Block } from '@/blocks/blocks/github'
|
|||||||
import { GitLabBlock } from '@/blocks/blocks/gitlab'
|
import { GitLabBlock } from '@/blocks/blocks/gitlab'
|
||||||
import { GmailBlock, GmailV2Block } from '@/blocks/blocks/gmail'
|
import { GmailBlock, GmailV2Block } from '@/blocks/blocks/gmail'
|
||||||
import { GoogleSearchBlock } from '@/blocks/blocks/google'
|
import { GoogleSearchBlock } from '@/blocks/blocks/google'
|
||||||
|
import { GoogleBooksBlock } from '@/blocks/blocks/google_books'
|
||||||
import { GoogleCalendarBlock, GoogleCalendarV2Block } from '@/blocks/blocks/google_calendar'
|
import { GoogleCalendarBlock, GoogleCalendarV2Block } from '@/blocks/blocks/google_calendar'
|
||||||
import { GoogleDocsBlock } from '@/blocks/blocks/google_docs'
|
import { GoogleDocsBlock } from '@/blocks/blocks/google_docs'
|
||||||
import { GoogleDriveBlock } from '@/blocks/blocks/google_drive'
|
import { GoogleDriveBlock } from '@/blocks/blocks/google_drive'
|
||||||
@@ -214,6 +215,7 @@ export const registry: Record<string, BlockConfig> = {
|
|||||||
gmail_v2: GmailV2Block,
|
gmail_v2: GmailV2Block,
|
||||||
google_calendar: GoogleCalendarBlock,
|
google_calendar: GoogleCalendarBlock,
|
||||||
google_calendar_v2: GoogleCalendarV2Block,
|
google_calendar_v2: GoogleCalendarV2Block,
|
||||||
|
google_books: GoogleBooksBlock,
|
||||||
google_docs: GoogleDocsBlock,
|
google_docs: GoogleDocsBlock,
|
||||||
google_drive: GoogleDriveBlock,
|
google_drive: GoogleDriveBlock,
|
||||||
google_forms: GoogleFormsBlock,
|
google_forms: GoogleFormsBlock,
|
||||||
|
|||||||
@@ -1157,6 +1157,21 @@ export function AirweaveIcon(props: SVGProps<SVGSVGElement>) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function GoogleBooksIcon(props: SVGProps<SVGSVGElement>) {
|
||||||
|
return (
|
||||||
|
<svg {...props} xmlns='http://www.w3.org/2000/svg' viewBox='0 0 478.633 540.068'>
|
||||||
|
<path
|
||||||
|
fill='#1C51A4'
|
||||||
|
d='M449.059,218.231L245.519,99.538l-0.061,193.23c0.031,1.504-0.368,2.977-1.166,4.204c-0.798,1.258-1.565,1.995-2.915,2.547c-1.35,0.552-2.792,0.706-4.204,0.399c-1.412-0.307-2.7-1.043-3.713-2.117l-69.166-70.609l-69.381,70.179c-1.013,0.982-2.301,1.657-3.652,1.903c-1.381,0.246-2.792,0.092-4.081-0.491c-1.289-0.583-1.626-0.522-2.394-1.749c-0.767-1.197-1.197-2.608-1.197-4.081L85.031,6.007l-2.915-1.289C43.973-11.638,0,16.409,0,59.891v420.306c0,46.029,49.312,74.782,88.775,51.767l360.285-210.138C488.491,298.782,488.491,241.246,449.059,218.231z'
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
fill='#80D7FB'
|
||||||
|
d='M88.805,8.124c-2.179-1.289-4.419-2.363-6.659-3.345l0.123,288.663c0,1.442,0.43,2.854,1.197,4.081c0.767,1.197,1.872,2.148,3.161,2.731c1.289,0.583,2.7,0.736,4.081,0.491c1.381-0.246,2.639-0.921,3.652-1.903l69.749-69.688l69.811,69.749c1.013,1.074,2.301,1.81,3.713,2.117c1.412,0.307,2.884,0.153,4.204-0.399c1.319-0.552,2.455-1.565,3.253-2.792c0.798-1.258,1.197-2.731,1.166-4.204V99.998L88.805,8.124z'
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
export function GoogleDocsIcon(props: SVGProps<SVGSVGElement>) {
|
export function GoogleDocsIcon(props: SVGProps<SVGSVGElement>) {
|
||||||
return (
|
return (
|
||||||
<svg
|
<svg
|
||||||
|
|||||||
3
apps/sim/tools/google_books/index.ts
Normal file
3
apps/sim/tools/google_books/index.ts
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
export * from './types'
|
||||||
|
export { googleBooksVolumeDetailsTool } from './volume_details'
|
||||||
|
export { googleBooksVolumeSearchTool } from './volume_search'
|
||||||
64
apps/sim/tools/google_books/types.ts
Normal file
64
apps/sim/tools/google_books/types.ts
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
import type { ToolResponse } from '@/tools/types'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Volume information structure shared between search and details responses
|
||||||
|
*/
|
||||||
|
export interface VolumeInfo {
|
||||||
|
id: string
|
||||||
|
title: string
|
||||||
|
subtitle: string | null
|
||||||
|
authors: string[]
|
||||||
|
publisher: string | null
|
||||||
|
publishedDate: string | null
|
||||||
|
description: string | null
|
||||||
|
pageCount: number | null
|
||||||
|
categories: string[]
|
||||||
|
averageRating: number | null
|
||||||
|
ratingsCount: number | null
|
||||||
|
language: string | null
|
||||||
|
previewLink: string | null
|
||||||
|
infoLink: string | null
|
||||||
|
thumbnailUrl: string | null
|
||||||
|
isbn10: string | null
|
||||||
|
isbn13: string | null
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parameters for searching volumes
|
||||||
|
*/
|
||||||
|
export interface GoogleBooksVolumeSearchParams {
|
||||||
|
apiKey: string
|
||||||
|
query: string
|
||||||
|
filter?: 'partial' | 'full' | 'free-ebooks' | 'paid-ebooks' | 'ebooks'
|
||||||
|
printType?: 'all' | 'books' | 'magazines'
|
||||||
|
orderBy?: 'relevance' | 'newest'
|
||||||
|
startIndex?: number
|
||||||
|
maxResults?: number
|
||||||
|
langRestrict?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Response from volume search
|
||||||
|
*/
|
||||||
|
export interface GoogleBooksVolumeSearchResponse extends ToolResponse {
|
||||||
|
output: {
|
||||||
|
totalItems: number
|
||||||
|
volumes: VolumeInfo[]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parameters for getting volume details
|
||||||
|
*/
|
||||||
|
export interface GoogleBooksVolumeDetailsParams {
|
||||||
|
apiKey: string
|
||||||
|
volumeId: string
|
||||||
|
projection?: 'full' | 'lite'
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Response from volume details
|
||||||
|
*/
|
||||||
|
export interface GoogleBooksVolumeDetailsResponse extends ToolResponse {
|
||||||
|
output: VolumeInfo
|
||||||
|
}
|
||||||
198
apps/sim/tools/google_books/volume_details.ts
Normal file
198
apps/sim/tools/google_books/volume_details.ts
Normal file
@@ -0,0 +1,198 @@
|
|||||||
|
import type {
|
||||||
|
GoogleBooksVolumeDetailsParams,
|
||||||
|
GoogleBooksVolumeDetailsResponse,
|
||||||
|
} from '@/tools/google_books/types'
|
||||||
|
import type { ToolConfig } from '@/tools/types'
|
||||||
|
|
||||||
|
interface GoogleBooksVolumeResponse {
|
||||||
|
id: string
|
||||||
|
volumeInfo: {
|
||||||
|
title?: string
|
||||||
|
subtitle?: string
|
||||||
|
authors?: string[]
|
||||||
|
publisher?: string
|
||||||
|
publishedDate?: string
|
||||||
|
description?: string
|
||||||
|
pageCount?: number
|
||||||
|
categories?: string[]
|
||||||
|
averageRating?: number
|
||||||
|
ratingsCount?: number
|
||||||
|
language?: string
|
||||||
|
previewLink?: string
|
||||||
|
infoLink?: string
|
||||||
|
imageLinks?: {
|
||||||
|
thumbnail?: string
|
||||||
|
smallThumbnail?: string
|
||||||
|
}
|
||||||
|
industryIdentifiers?: Array<{
|
||||||
|
type: string
|
||||||
|
identifier: string
|
||||||
|
}>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const googleBooksVolumeDetailsTool: ToolConfig<
|
||||||
|
GoogleBooksVolumeDetailsParams,
|
||||||
|
GoogleBooksVolumeDetailsResponse
|
||||||
|
> = {
|
||||||
|
id: 'google_books_volume_details',
|
||||||
|
name: 'Google Books Volume Details',
|
||||||
|
description: 'Get detailed information about a specific book volume',
|
||||||
|
version: '1.0.0',
|
||||||
|
|
||||||
|
params: {
|
||||||
|
apiKey: {
|
||||||
|
type: 'string',
|
||||||
|
required: true,
|
||||||
|
visibility: 'user-only',
|
||||||
|
description: 'Google Books API key',
|
||||||
|
},
|
||||||
|
volumeId: {
|
||||||
|
type: 'string',
|
||||||
|
required: true,
|
||||||
|
visibility: 'user-or-llm',
|
||||||
|
description: 'The ID of the volume to retrieve',
|
||||||
|
},
|
||||||
|
projection: {
|
||||||
|
type: 'string',
|
||||||
|
required: false,
|
||||||
|
visibility: 'user-or-llm',
|
||||||
|
description: 'Projection level (full, lite)',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
request: {
|
||||||
|
url: (params) => {
|
||||||
|
const url = new URL(`https://www.googleapis.com/books/v1/volumes/${params.volumeId.trim()}`)
|
||||||
|
url.searchParams.set('key', params.apiKey.trim())
|
||||||
|
|
||||||
|
if (params.projection) {
|
||||||
|
url.searchParams.set('projection', params.projection)
|
||||||
|
}
|
||||||
|
|
||||||
|
return url.toString()
|
||||||
|
},
|
||||||
|
method: 'GET',
|
||||||
|
headers: () => ({
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
|
||||||
|
transformResponse: async (response: Response) => {
|
||||||
|
const data: GoogleBooksVolumeResponse = await response.json()
|
||||||
|
|
||||||
|
if (!data.volumeInfo) {
|
||||||
|
throw new Error('Volume not found')
|
||||||
|
}
|
||||||
|
|
||||||
|
const info = data.volumeInfo
|
||||||
|
const identifiers = info.industryIdentifiers ?? []
|
||||||
|
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
output: {
|
||||||
|
id: data.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,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
outputs: {
|
||||||
|
id: {
|
||||||
|
type: 'string',
|
||||||
|
description: 'Volume ID',
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
type: 'string',
|
||||||
|
description: 'Book title',
|
||||||
|
},
|
||||||
|
subtitle: {
|
||||||
|
type: 'string',
|
||||||
|
description: 'Book subtitle',
|
||||||
|
optional: true,
|
||||||
|
},
|
||||||
|
authors: {
|
||||||
|
type: 'array',
|
||||||
|
description: 'List of authors',
|
||||||
|
},
|
||||||
|
publisher: {
|
||||||
|
type: 'string',
|
||||||
|
description: 'Publisher name',
|
||||||
|
optional: true,
|
||||||
|
},
|
||||||
|
publishedDate: {
|
||||||
|
type: 'string',
|
||||||
|
description: 'Publication date',
|
||||||
|
optional: true,
|
||||||
|
},
|
||||||
|
description: {
|
||||||
|
type: 'string',
|
||||||
|
description: 'Book description',
|
||||||
|
optional: true,
|
||||||
|
},
|
||||||
|
pageCount: {
|
||||||
|
type: 'number',
|
||||||
|
description: 'Number of pages',
|
||||||
|
optional: true,
|
||||||
|
},
|
||||||
|
categories: {
|
||||||
|
type: 'array',
|
||||||
|
description: 'Book categories',
|
||||||
|
},
|
||||||
|
averageRating: {
|
||||||
|
type: 'number',
|
||||||
|
description: 'Average rating (1-5)',
|
||||||
|
optional: true,
|
||||||
|
},
|
||||||
|
ratingsCount: {
|
||||||
|
type: 'number',
|
||||||
|
description: 'Number of ratings',
|
||||||
|
optional: true,
|
||||||
|
},
|
||||||
|
language: {
|
||||||
|
type: 'string',
|
||||||
|
description: 'Language code',
|
||||||
|
optional: true,
|
||||||
|
},
|
||||||
|
previewLink: {
|
||||||
|
type: 'string',
|
||||||
|
description: 'Link to preview on Google Books',
|
||||||
|
optional: true,
|
||||||
|
},
|
||||||
|
infoLink: {
|
||||||
|
type: 'string',
|
||||||
|
description: 'Link to info page',
|
||||||
|
optional: true,
|
||||||
|
},
|
||||||
|
thumbnailUrl: {
|
||||||
|
type: 'string',
|
||||||
|
description: 'Book cover thumbnail URL',
|
||||||
|
optional: true,
|
||||||
|
},
|
||||||
|
isbn10: {
|
||||||
|
type: 'string',
|
||||||
|
description: 'ISBN-10 identifier',
|
||||||
|
optional: true,
|
||||||
|
},
|
||||||
|
isbn13: {
|
||||||
|
type: 'string',
|
||||||
|
description: 'ISBN-13 identifier',
|
||||||
|
optional: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
202
apps/sim/tools/google_books/volume_search.ts
Normal file
202
apps/sim/tools/google_books/volume_search.ts
Normal file
@@ -0,0 +1,202 @@
|
|||||||
|
import type {
|
||||||
|
GoogleBooksVolumeSearchParams,
|
||||||
|
GoogleBooksVolumeSearchResponse,
|
||||||
|
VolumeInfo,
|
||||||
|
} from '@/tools/google_books/types'
|
||||||
|
import type { ToolConfig } from '@/tools/types'
|
||||||
|
|
||||||
|
interface GoogleBooksVolumeItem {
|
||||||
|
id: string
|
||||||
|
volumeInfo: {
|
||||||
|
title?: string
|
||||||
|
subtitle?: string
|
||||||
|
authors?: string[]
|
||||||
|
publisher?: string
|
||||||
|
publishedDate?: string
|
||||||
|
description?: string
|
||||||
|
pageCount?: number
|
||||||
|
categories?: string[]
|
||||||
|
averageRating?: number
|
||||||
|
ratingsCount?: number
|
||||||
|
language?: string
|
||||||
|
previewLink?: string
|
||||||
|
infoLink?: string
|
||||||
|
imageLinks?: {
|
||||||
|
thumbnail?: string
|
||||||
|
smallThumbnail?: string
|
||||||
|
}
|
||||||
|
industryIdentifiers?: Array<{
|
||||||
|
type: string
|
||||||
|
identifier: string
|
||||||
|
}>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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)',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
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' },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
@@ -526,6 +526,7 @@ import {
|
|||||||
gmailUnarchiveV2Tool,
|
gmailUnarchiveV2Tool,
|
||||||
} from '@/tools/gmail'
|
} from '@/tools/gmail'
|
||||||
import { googleSearchTool } from '@/tools/google'
|
import { googleSearchTool } from '@/tools/google'
|
||||||
|
import { googleBooksVolumeDetailsTool, googleBooksVolumeSearchTool } from '@/tools/google_books'
|
||||||
import {
|
import {
|
||||||
googleCalendarCreateTool,
|
googleCalendarCreateTool,
|
||||||
googleCalendarCreateV2Tool,
|
googleCalendarCreateV2Tool,
|
||||||
@@ -2556,6 +2557,8 @@ export const tools: Record<string, ToolConfig> = {
|
|||||||
google_docs_read: googleDocsReadTool,
|
google_docs_read: googleDocsReadTool,
|
||||||
google_docs_write: googleDocsWriteTool,
|
google_docs_write: googleDocsWriteTool,
|
||||||
google_docs_create: googleDocsCreateTool,
|
google_docs_create: googleDocsCreateTool,
|
||||||
|
google_books_volume_search: googleBooksVolumeSearchTool,
|
||||||
|
google_books_volume_details: googleBooksVolumeDetailsTool,
|
||||||
google_maps_air_quality: googleMapsAirQualityTool,
|
google_maps_air_quality: googleMapsAirQualityTool,
|
||||||
google_maps_directions: googleMapsDirectionsTool,
|
google_maps_directions: googleMapsDirectionsTool,
|
||||||
google_maps_distance_matrix: googleMapsDistanceMatrixTool,
|
google_maps_distance_matrix: googleMapsDistanceMatrixTool,
|
||||||
|
|||||||
Reference in New Issue
Block a user