Files
sim/apps/sim/tools/google_slides/add_slide.ts
Waleed 6cb3977dd9 fix(visibility): updated visibility for non-sensitive tool params from user only to user or llm (#3095)
* fix(visibility): updated visibility for non-sensitive tool params from user only to user or llm

* update docs

* updated docs script
2026-01-31 11:31:08 -08:00

211 lines
5.8 KiB
TypeScript

import { createLogger } from '@sim/logger'
import type { ToolConfig } from '@/tools/types'
const logger = createLogger('GoogleSlidesAddSlideTool')
interface AddSlideParams {
accessToken: string
presentationId: string
layout?: string
insertionIndex?: number
placeholderIdMappings?: string
}
interface AddSlideResponse {
success: boolean
output: {
slideId: string
metadata: {
presentationId: string
layout: string
insertionIndex?: number
url: string
}
}
}
// Predefined layouts available in Google Slides API
const PREDEFINED_LAYOUTS = [
'BLANK',
'CAPTION_ONLY',
'TITLE',
'TITLE_AND_BODY',
'TITLE_AND_TWO_COLUMNS',
'TITLE_ONLY',
'SECTION_HEADER',
'SECTION_TITLE_AND_DESCRIPTION',
'ONE_COLUMN_TEXT',
'MAIN_POINT',
'BIG_NUMBER',
] as const
export const addSlideTool: ToolConfig<AddSlideParams, AddSlideResponse> = {
id: 'google_slides_add_slide',
name: 'Add Slide to Google Slides',
description: 'Add a new slide to a Google Slides presentation with a specified layout',
version: '1.0',
oauth: {
required: true,
provider: 'google-drive',
},
params: {
accessToken: {
type: 'string',
required: true,
visibility: 'hidden',
description: 'The access token for the Google Slides API',
},
presentationId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Google Slides presentation ID',
},
layout: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description:
'The predefined layout for the slide (BLANK, TITLE, TITLE_AND_BODY, TITLE_ONLY, SECTION_HEADER, etc.). Defaults to BLANK.',
},
insertionIndex: {
type: 'number',
required: false,
visibility: 'user-or-llm',
description:
'The optional zero-based index indicating where to insert the slide. If not specified, the slide is added at the end.',
},
placeholderIdMappings: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description:
'JSON array of placeholder mappings to assign custom object IDs to placeholders. Format: [{"layoutPlaceholder":{"type":"TITLE"},"objectId":"custom_title_id"}]',
},
},
request: {
url: (params) => {
const presentationId = params.presentationId?.trim()
if (!presentationId) {
throw new Error('Presentation ID is required')
}
return `https://slides.googleapis.com/v1/presentations/${presentationId}:batchUpdate`
},
method: 'POST',
headers: (params) => {
if (!params.accessToken) {
throw new Error('Access token is required')
}
return {
Authorization: `Bearer ${params.accessToken}`,
'Content-Type': 'application/json',
}
},
body: (params) => {
// Generate a unique object ID for the new slide
const slideObjectId = `slide_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`
// Validate and normalize the layout
let layout = (params.layout || 'BLANK').toUpperCase()
if (!PREDEFINED_LAYOUTS.includes(layout as (typeof PREDEFINED_LAYOUTS)[number])) {
logger.warn(`Invalid layout "${params.layout}", defaulting to BLANK`)
layout = 'BLANK'
}
const createSlideRequest: Record<string, any> = {
objectId: slideObjectId,
slideLayoutReference: {
predefinedLayout: layout,
},
}
// Add insertion index if specified
if (params.insertionIndex !== undefined && params.insertionIndex >= 0) {
createSlideRequest.insertionIndex = params.insertionIndex
}
// Add placeholder ID mappings if specified (for advanced use cases)
if (params.placeholderIdMappings?.trim()) {
try {
const mappings = JSON.parse(params.placeholderIdMappings)
if (Array.isArray(mappings) && mappings.length > 0) {
createSlideRequest.placeholderIdMappings = mappings
}
} catch (e) {
logger.warn('Invalid placeholderIdMappings JSON, ignoring:', e)
}
}
return {
requests: [
{
createSlide: createSlideRequest,
},
],
}
},
},
transformResponse: async (response: Response, params) => {
const data = await response.json()
if (!response.ok) {
logger.error('Google Slides API error:', { data })
throw new Error(data.error?.message || 'Failed to add slide')
}
// The response contains the created slide's object ID
const createSlideReply = data.replies?.[0]?.createSlide
const slideId = createSlideReply?.objectId || ''
const presentationId = params?.presentationId?.trim() || ''
const layout = (params?.layout || 'BLANK').toUpperCase()
return {
success: true,
output: {
slideId,
metadata: {
presentationId,
layout,
insertionIndex: params?.insertionIndex,
url: `https://docs.google.com/presentation/d/${presentationId}/edit`,
},
},
}
},
outputs: {
slideId: {
type: 'string',
description: 'The object ID of the newly created slide',
},
metadata: {
type: 'json',
description: 'Operation metadata including presentation ID, layout, and URL',
properties: {
presentationId: {
type: 'string',
description: 'The presentation ID',
},
layout: {
type: 'string',
description: 'The layout used for the new slide',
},
insertionIndex: {
type: 'number',
description: 'The zero-based index where the slide was inserted',
optional: true,
},
url: {
type: 'string',
description: 'URL to open the presentation',
},
},
},
},
}