mirror of
https://github.com/simstudioai/sim.git
synced 2026-09-24 15:45:35 +08:00
feat(tools): added google docs tools/block
This commit is contained in:
@@ -51,12 +51,22 @@ export async function GET(request: NextRequest) {
|
||||
|
||||
// Add mimeType filter if provided
|
||||
if (mimeType) {
|
||||
queryParams += `&mimeType='${mimeType}'`
|
||||
// For Google Drive API, we need to use 'q' parameter for mimeType filtering
|
||||
// Instead of using the mimeType parameter directly, we'll add it to the query
|
||||
if (queryParams.includes('q=')) {
|
||||
queryParams += ` and mimeType='${mimeType}'`
|
||||
} else {
|
||||
queryParams += `&q=mimeType='${mimeType}'`
|
||||
}
|
||||
}
|
||||
|
||||
// Add search query if provided
|
||||
if (query) {
|
||||
queryParams += `&q=name contains '${query}'`
|
||||
if (queryParams.includes('q=')) {
|
||||
queryParams += ` and name contains '${query}'`
|
||||
} else {
|
||||
queryParams += `&q=name contains '${query}'`
|
||||
}
|
||||
}
|
||||
|
||||
// Fetch files from Google Drive
|
||||
@@ -78,14 +88,14 @@ export async function GET(request: NextRequest) {
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
|
||||
// Filter for Google Sheets files if mimeType is for spreadsheets
|
||||
let files = data.files || []
|
||||
|
||||
if (mimeType === 'application/vnd.google-apps.spreadsheet') {
|
||||
files = files.filter(
|
||||
(file: any) => file.mimeType === 'application/vnd.google-apps.spreadsheet'
|
||||
)
|
||||
} else if (mimeType === 'application/vnd.google-apps.document') {
|
||||
files = files.filter((file: any) => file.mimeType === 'application/vnd.google-apps.document')
|
||||
}
|
||||
|
||||
return NextResponse.json({ files }, { status: 200 })
|
||||
|
||||
@@ -0,0 +1,192 @@
|
||||
import { GoogleDocsIcon } from '@/components/icons'
|
||||
import {
|
||||
GoogleDocsCreateResponse,
|
||||
GoogleDocsReadResponse,
|
||||
GoogleDocsWriteResponse,
|
||||
} from '@/tools/docs/types'
|
||||
import { BlockConfig } from '../types'
|
||||
|
||||
type GoogleDocsResponse =
|
||||
| GoogleDocsReadResponse
|
||||
| GoogleDocsWriteResponse
|
||||
| GoogleDocsCreateResponse
|
||||
|
||||
export const GoogleDocsBlock: BlockConfig<GoogleDocsResponse> = {
|
||||
type: 'google_docs',
|
||||
name: 'Google Docs',
|
||||
description: 'Read, write, and create documents',
|
||||
longDescription:
|
||||
'Integrate Google Docs functionality to manage documents. Read content from existing documents, write to documents, and create new documents using OAuth authentication. Supports text content manipulation for document creation and editing.',
|
||||
category: 'tools',
|
||||
bgColor: '#E0E0E0',
|
||||
icon: GoogleDocsIcon,
|
||||
subBlocks: [
|
||||
// Operation selector
|
||||
{
|
||||
id: 'operation',
|
||||
title: 'Operation',
|
||||
type: 'dropdown',
|
||||
layout: 'full',
|
||||
options: [
|
||||
{ label: 'Read Document', id: 'read' },
|
||||
{ label: 'Write to Document', id: 'write' },
|
||||
{ label: 'Create Document', id: 'create' },
|
||||
],
|
||||
},
|
||||
// Google Docs Credentials
|
||||
{
|
||||
id: 'credential',
|
||||
title: 'Google Account',
|
||||
type: 'oauth-input',
|
||||
layout: 'full',
|
||||
provider: 'google-docs',
|
||||
serviceId: 'google-docs',
|
||||
requiredScopes: ['https://www.googleapis.com/auth/documents'],
|
||||
placeholder: 'Select Google account',
|
||||
},
|
||||
// Document Selector for read operation
|
||||
{
|
||||
id: 'documentId',
|
||||
title: 'Select Document',
|
||||
type: 'file-selector',
|
||||
layout: 'full',
|
||||
provider: 'google-drive',
|
||||
serviceId: 'google-drive',
|
||||
requiredScopes: ['https://www.googleapis.com/auth/drive.readonly'],
|
||||
mimeType: 'application/vnd.google-apps.document',
|
||||
placeholder: 'Select a document',
|
||||
condition: { field: 'operation', value: 'read' },
|
||||
},
|
||||
// Document Selector for write operation
|
||||
{
|
||||
id: 'documentId',
|
||||
title: 'Select Document',
|
||||
type: 'file-selector',
|
||||
layout: 'full',
|
||||
provider: 'google-drive',
|
||||
serviceId: 'google-drive',
|
||||
requiredScopes: ['https://www.googleapis.com/auth/drive.readonly'],
|
||||
mimeType: 'application/vnd.google-apps.document',
|
||||
placeholder: 'Select a document',
|
||||
condition: { field: 'operation', value: 'write' },
|
||||
},
|
||||
// Manual Document ID for read operation
|
||||
{
|
||||
id: 'manualDocumentId',
|
||||
title: 'Or Enter Document ID Manually',
|
||||
type: 'short-input',
|
||||
layout: 'full',
|
||||
placeholder: 'ID of the document (from URL)',
|
||||
condition: {
|
||||
field: 'operation',
|
||||
value: 'read',
|
||||
and: { field: 'documentId', value: '' },
|
||||
},
|
||||
},
|
||||
// Manual Document ID for write operation
|
||||
{
|
||||
id: 'manualDocumentId',
|
||||
title: 'Or Enter Document ID Manually',
|
||||
type: 'short-input',
|
||||
layout: 'full',
|
||||
placeholder: 'ID of the document (from URL)',
|
||||
condition: {
|
||||
field: 'operation',
|
||||
value: 'write',
|
||||
and: { field: 'documentId', value: '' },
|
||||
},
|
||||
},
|
||||
// Create-specific Fields
|
||||
{
|
||||
id: 'title',
|
||||
title: 'Document Title',
|
||||
type: 'short-input',
|
||||
layout: 'full',
|
||||
placeholder: 'Enter title for the new document',
|
||||
condition: { field: 'operation', value: 'create' },
|
||||
},
|
||||
{
|
||||
id: 'folderId',
|
||||
title: 'Parent Folder ID (Optional)',
|
||||
type: 'short-input',
|
||||
layout: 'full',
|
||||
placeholder: 'ID of the parent folder (leave empty for root folder)',
|
||||
condition: { field: 'operation', value: 'create' },
|
||||
},
|
||||
// Content Field for write operation
|
||||
{
|
||||
id: 'content',
|
||||
title: 'Content',
|
||||
type: 'long-input',
|
||||
layout: 'full',
|
||||
placeholder: 'Enter document content',
|
||||
condition: { field: 'operation', value: 'write' },
|
||||
},
|
||||
// Content Field for create operation
|
||||
{
|
||||
id: 'content',
|
||||
title: 'Content',
|
||||
type: 'long-input',
|
||||
layout: 'full',
|
||||
placeholder: 'Enter document content',
|
||||
condition: { field: 'operation', value: 'create' },
|
||||
},
|
||||
],
|
||||
tools: {
|
||||
access: ['google_docs_read', 'google_docs_write', 'google_docs_create'],
|
||||
config: {
|
||||
tool: (params) => {
|
||||
switch (params.operation) {
|
||||
case 'read':
|
||||
return 'google_docs_read'
|
||||
case 'write':
|
||||
return 'google_docs_write'
|
||||
case 'create':
|
||||
return 'google_docs_create'
|
||||
default:
|
||||
throw new Error(`Invalid Google Docs operation: ${params.operation}`)
|
||||
}
|
||||
},
|
||||
params: (params) => {
|
||||
const { credential, documentId, manualDocumentId, ...rest } = params
|
||||
|
||||
// Use the selected document ID or the manually entered one
|
||||
// If documentId is provided, it's from the file selector and contains the file ID
|
||||
// If not, fall back to manually entered ID
|
||||
const effectiveDocumentId = (documentId || manualDocumentId || '').trim()
|
||||
|
||||
if (params.operation !== 'create' && !effectiveDocumentId) {
|
||||
throw new Error(
|
||||
'Document ID is required. Please select a document or enter an ID manually.'
|
||||
)
|
||||
}
|
||||
|
||||
return {
|
||||
...rest,
|
||||
documentId: effectiveDocumentId,
|
||||
credential,
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
inputs: {
|
||||
operation: { type: 'string', required: true },
|
||||
credential: { type: 'string', required: true },
|
||||
documentId: { type: 'string', required: false },
|
||||
manualDocumentId: { type: 'string', required: false },
|
||||
// Create operation inputs
|
||||
title: { type: 'string', required: false },
|
||||
folderId: { type: 'string', required: false },
|
||||
// Write/Create operation inputs
|
||||
content: { type: 'string', required: false },
|
||||
},
|
||||
outputs: {
|
||||
response: {
|
||||
type: {
|
||||
content: 'string',
|
||||
metadata: 'json',
|
||||
updatedContent: 'boolean',
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
import { AgentBlock } from './blocks/agent'
|
||||
import { ApiBlock } from './blocks/api'
|
||||
import { ConditionBlock } from './blocks/condition'
|
||||
import { GoogleDocsBlock } from './blocks/docs'
|
||||
import { GoogleDriveBlock } from './blocks/drive'
|
||||
import { EvaluatorBlock } from './blocks/evaluator'
|
||||
import { ExaBlock } from './blocks/exa'
|
||||
@@ -57,6 +58,7 @@ export {
|
||||
ExaBlock,
|
||||
RedditBlock,
|
||||
GoogleDriveBlock,
|
||||
GoogleDocsBlock,
|
||||
WhatsAppBlock,
|
||||
GoogleSheetsBlock,
|
||||
}
|
||||
@@ -72,6 +74,7 @@ const blocks: Record<string, BlockConfig> = {
|
||||
function: FunctionBlock,
|
||||
github: GitHubBlock,
|
||||
gmail: GmailBlock,
|
||||
google_docs: GoogleDocsBlock,
|
||||
google_drive: GoogleDriveBlock,
|
||||
google_sheets: GoogleSheetsBlock,
|
||||
// guesty: GuestyBlock,
|
||||
|
||||
@@ -0,0 +1,156 @@
|
||||
import { ToolConfig } from '../types'
|
||||
import { GoogleDocsCreateResponse, GoogleDocsToolParams } from './types'
|
||||
|
||||
export const createTool: ToolConfig<GoogleDocsToolParams, GoogleDocsCreateResponse> = {
|
||||
id: 'google_docs_create',
|
||||
name: 'Create Google Docs Document',
|
||||
description: 'Create a new Google Docs document',
|
||||
version: '1.0',
|
||||
oauth: {
|
||||
required: true,
|
||||
provider: 'google-docs',
|
||||
additionalScopes: [
|
||||
'https://www.googleapis.com/auth/documents',
|
||||
'https://www.googleapis.com/auth/drive',
|
||||
],
|
||||
},
|
||||
params: {
|
||||
accessToken: { type: 'string', required: true },
|
||||
title: { type: 'string', required: true },
|
||||
content: { type: 'string', required: false },
|
||||
folderId: { type: 'string', required: false },
|
||||
},
|
||||
request: {
|
||||
url: (params) => {
|
||||
// Build URL with query parameters to pass content and folderId
|
||||
const url = new URL('https://docs.googleapis.com/v1/documents')
|
||||
if (params.content) {
|
||||
url.searchParams.append('content', params.content)
|
||||
}
|
||||
if (params.folderId) {
|
||||
url.searchParams.append('folderId', params.folderId)
|
||||
}
|
||||
return url.toString()
|
||||
},
|
||||
method: 'POST',
|
||||
headers: (params) => {
|
||||
// Validate access token
|
||||
if (!params.accessToken) {
|
||||
throw new Error('Access token is required')
|
||||
}
|
||||
|
||||
return {
|
||||
Authorization: `Bearer ${params.accessToken}`,
|
||||
'Content-Type': 'application/json',
|
||||
'X-Access-Token': params.accessToken, // Store access token in a custom header for later use
|
||||
}
|
||||
},
|
||||
body: (params) => {
|
||||
// Validate title
|
||||
if (!params.title) {
|
||||
throw new Error('Title is required')
|
||||
}
|
||||
|
||||
// Create a new document with the specified title
|
||||
return {
|
||||
title: params.title,
|
||||
}
|
||||
},
|
||||
},
|
||||
transformResponse: async (response: Response) => {
|
||||
if (!response.ok) {
|
||||
const errorText = await response.text()
|
||||
throw new Error(`Failed to create Google Docs document: ${errorText}`)
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
const documentId = data.documentId
|
||||
|
||||
// Get access token from the custom header we set in the request
|
||||
const accessToken = response.headers.get('X-Access-Token') || ''
|
||||
|
||||
// Extract content and folderId from the request URL query parameters
|
||||
const requestUrl = new URL(response.url)
|
||||
const content = requestUrl.searchParams.get('content') || ''
|
||||
const folderId = requestUrl.searchParams.get('folderId') || ''
|
||||
|
||||
// If content was provided, we need to update the document with content
|
||||
if (documentId && content) {
|
||||
try {
|
||||
// Make a second request to update the document with content
|
||||
const updateResponse = await fetch(
|
||||
`https://docs.googleapis.com/v1/documents/${documentId}:batchUpdate`,
|
||||
{
|
||||
method: 'POST',
|
||||
headers: {
|
||||
Authorization: `Bearer ${accessToken}`,
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
requests: [
|
||||
{
|
||||
insertText: {
|
||||
location: {
|
||||
index: 1,
|
||||
},
|
||||
text: content,
|
||||
},
|
||||
},
|
||||
],
|
||||
}),
|
||||
}
|
||||
)
|
||||
|
||||
if (!updateResponse.ok) {
|
||||
console.warn('Failed to update document with content, but document was created')
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn('Error updating document with content:', error)
|
||||
}
|
||||
}
|
||||
|
||||
// If folderId was provided, we need to move the document to that folder
|
||||
if (documentId && folderId) {
|
||||
try {
|
||||
// Make a request to the Drive API to move the file
|
||||
const moveResponse = await fetch(
|
||||
`https://www.googleapis.com/drive/v3/files/${documentId}?addParents=${folderId}`,
|
||||
{
|
||||
method: 'PATCH',
|
||||
headers: {
|
||||
Authorization: `Bearer ${accessToken}`,
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
if (!moveResponse.ok) {
|
||||
console.warn('Failed to move document to specified folder, but document was created')
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn('Error moving document to folder:', error)
|
||||
}
|
||||
}
|
||||
|
||||
// Create document metadata
|
||||
const metadata = {
|
||||
documentId: data.documentId,
|
||||
title: data.title || 'Untitled Document',
|
||||
mimeType: 'application/vnd.google-apps.document',
|
||||
url: `https://docs.google.com/document/d/${data.documentId}/edit`,
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
metadata,
|
||||
},
|
||||
}
|
||||
},
|
||||
transformError: (error) => {
|
||||
if (typeof error === 'object' && error !== null) {
|
||||
return JSON.stringify(error) || 'An error occurred while creating Google Docs document'
|
||||
}
|
||||
return error.message || 'An error occurred while creating Google Docs document'
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
import { createTool } from './create'
|
||||
import { readTool } from './read'
|
||||
import { writeTool } from './write'
|
||||
|
||||
export const docsReadTool = readTool
|
||||
export const docsWriteTool = writeTool
|
||||
export const docsCreateTool = createTool
|
||||
@@ -0,0 +1,118 @@
|
||||
import { ToolConfig } from '../types'
|
||||
import { GoogleDocsReadResponse, GoogleDocsToolParams } from './types'
|
||||
|
||||
export const readTool: ToolConfig<GoogleDocsToolParams, GoogleDocsReadResponse> = {
|
||||
id: 'google_docs_read',
|
||||
name: 'Read Google Docs Document',
|
||||
description: 'Read content from a Google Docs document',
|
||||
version: '1.0',
|
||||
oauth: {
|
||||
required: true,
|
||||
provider: 'google-docs',
|
||||
additionalScopes: [
|
||||
'https://www.googleapis.com/auth/documents',
|
||||
'https://www.googleapis.com/auth/drive.readonly',
|
||||
],
|
||||
},
|
||||
params: {
|
||||
accessToken: { type: 'string', required: true },
|
||||
documentId: { type: 'string', required: true },
|
||||
},
|
||||
request: {
|
||||
url: (params) => {
|
||||
// Ensure documentId is valid
|
||||
const documentId = params.documentId?.trim()
|
||||
if (!documentId) {
|
||||
throw new Error('Document ID is required')
|
||||
}
|
||||
|
||||
return `https://docs.googleapis.com/v1/documents/${documentId}`
|
||||
},
|
||||
method: 'GET',
|
||||
headers: (params) => {
|
||||
// Validate access token
|
||||
if (!params.accessToken) {
|
||||
throw new Error('Access token is required')
|
||||
}
|
||||
|
||||
return {
|
||||
Authorization: `Bearer ${params.accessToken}`,
|
||||
}
|
||||
},
|
||||
},
|
||||
transformResponse: async (response: Response) => {
|
||||
if (!response.ok) {
|
||||
const errorText = await response.text()
|
||||
throw new Error(`Failed to read Google Docs document: ${errorText}`)
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
|
||||
// Extract document content from the response
|
||||
let content = ''
|
||||
if (data.body && data.body.content) {
|
||||
content = extractTextFromDocument(data)
|
||||
}
|
||||
|
||||
// Create document metadata
|
||||
const metadata = {
|
||||
documentId: data.documentId,
|
||||
title: data.title || 'Untitled Document',
|
||||
mimeType: 'application/vnd.google-apps.document',
|
||||
url: `https://docs.google.com/document/d/${data.documentId}/edit`,
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
content,
|
||||
metadata,
|
||||
},
|
||||
}
|
||||
},
|
||||
transformError: (error) => {
|
||||
if (typeof error === 'object' && error !== null) {
|
||||
return JSON.stringify(error) || 'An error occurred while reading from Google Docs'
|
||||
}
|
||||
return error.message || 'An error occurred while reading from Google Docs'
|
||||
},
|
||||
}
|
||||
|
||||
// Helper function to extract text content from Google Docs document structure
|
||||
function extractTextFromDocument(document: any): string {
|
||||
let text = ''
|
||||
|
||||
if (!document.body || !document.body.content) {
|
||||
return text
|
||||
}
|
||||
|
||||
// Process each structural element in the document
|
||||
for (const element of document.body.content) {
|
||||
if (element.paragraph) {
|
||||
for (const paragraphElement of element.paragraph.elements) {
|
||||
if (paragraphElement.textRun && paragraphElement.textRun.content) {
|
||||
text += paragraphElement.textRun.content
|
||||
}
|
||||
}
|
||||
} else if (element.table) {
|
||||
// Process tables if needed
|
||||
for (const tableRow of element.table.tableRows) {
|
||||
for (const tableCell of tableRow.tableCells) {
|
||||
if (tableCell.content) {
|
||||
for (const cellContent of tableCell.content) {
|
||||
if (cellContent.paragraph) {
|
||||
for (const paragraphElement of cellContent.paragraph.elements) {
|
||||
if (paragraphElement.textRun && paragraphElement.textRun.content) {
|
||||
text += paragraphElement.textRun.content
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return text
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
import { ToolResponse } from '../types'
|
||||
|
||||
export interface GoogleDocsMetadata {
|
||||
documentId: string
|
||||
title: string
|
||||
mimeType?: string
|
||||
createdTime?: string
|
||||
modifiedTime?: string
|
||||
url?: string
|
||||
}
|
||||
|
||||
export interface GoogleDocsReadResponse extends ToolResponse {
|
||||
output: {
|
||||
content: string
|
||||
metadata: GoogleDocsMetadata
|
||||
}
|
||||
}
|
||||
|
||||
export interface GoogleDocsWriteResponse extends ToolResponse {
|
||||
output: {
|
||||
updatedContent: boolean
|
||||
metadata: GoogleDocsMetadata
|
||||
}
|
||||
}
|
||||
|
||||
export interface GoogleDocsCreateResponse extends ToolResponse {
|
||||
output: {
|
||||
metadata: GoogleDocsMetadata
|
||||
}
|
||||
}
|
||||
|
||||
export interface GoogleDocsToolParams {
|
||||
accessToken: string
|
||||
documentId?: string
|
||||
title?: string
|
||||
content?: string
|
||||
folderId?: string
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
import { ToolConfig } from '../types'
|
||||
import { GoogleDocsToolParams, GoogleDocsWriteResponse } from './types'
|
||||
|
||||
export const writeTool: ToolConfig<GoogleDocsToolParams, GoogleDocsWriteResponse> = {
|
||||
id: 'google_docs_write',
|
||||
name: 'Write to Google Docs Document',
|
||||
description: 'Write or update content in a Google Docs document',
|
||||
version: '1.0',
|
||||
oauth: {
|
||||
required: true,
|
||||
provider: 'google-docs',
|
||||
additionalScopes: [
|
||||
'https://www.googleapis.com/auth/documents',
|
||||
'https://www.googleapis.com/auth/drive',
|
||||
],
|
||||
},
|
||||
params: {
|
||||
accessToken: { type: 'string', required: true },
|
||||
documentId: { type: 'string', required: true },
|
||||
content: { type: 'string', required: true },
|
||||
},
|
||||
request: {
|
||||
url: (params) => {
|
||||
// Ensure documentId is valid
|
||||
const documentId = params.documentId?.trim()
|
||||
if (!documentId) {
|
||||
throw new Error('Document ID is required')
|
||||
}
|
||||
|
||||
return `https://docs.googleapis.com/v1/documents/${documentId}:batchUpdate`
|
||||
},
|
||||
method: 'POST',
|
||||
headers: (params) => {
|
||||
// Validate access token
|
||||
if (!params.accessToken) {
|
||||
throw new Error('Access token is required')
|
||||
}
|
||||
|
||||
return {
|
||||
Authorization: `Bearer ${params.accessToken}`,
|
||||
'Content-Type': 'application/json',
|
||||
}
|
||||
},
|
||||
body: (params) => {
|
||||
// Validate content
|
||||
if (!params.content) {
|
||||
throw new Error('Content is required')
|
||||
}
|
||||
|
||||
// Create a batch update request to replace all content
|
||||
return {
|
||||
requests: [
|
||||
{
|
||||
// First, delete all existing content
|
||||
deleteContentRange: {
|
||||
range: {
|
||||
startIndex: 1, // Start after the initial paragraph marker
|
||||
endIndex: 999999, // A large number to ensure all content is deleted
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
// Then insert the new content
|
||||
insertText: {
|
||||
location: {
|
||||
index: 1, // Insert after the initial paragraph marker
|
||||
},
|
||||
text: params.content,
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
},
|
||||
},
|
||||
transformResponse: async (response: Response) => {
|
||||
if (!response.ok) {
|
||||
const errorText = await response.text()
|
||||
throw new Error(`Failed to write to Google Docs document: ${errorText}`)
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
|
||||
// Get the document ID from the URL
|
||||
const urlParts = response.url.split('/')
|
||||
const documentId = urlParts[urlParts.length - 2].split(':')[0]
|
||||
|
||||
// Create document metadata
|
||||
const metadata = {
|
||||
documentId,
|
||||
title: 'Updated Document', // We don't get the title back from the batchUpdate endpoint
|
||||
mimeType: 'application/vnd.google-apps.document',
|
||||
url: `https://docs.google.com/document/d/${documentId}/edit`,
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
updatedContent: true,
|
||||
metadata,
|
||||
},
|
||||
}
|
||||
},
|
||||
transformError: (error) => {
|
||||
if (typeof error === 'object' && error !== null) {
|
||||
return JSON.stringify(error) || 'An error occurred while writing to Google Docs'
|
||||
}
|
||||
return error.message || 'An error occurred while writing to Google Docs'
|
||||
},
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
import { useCustomToolsStore } from '@/stores/custom-tools/store'
|
||||
import { useEnvironmentStore } from '@/stores/settings/environment/store'
|
||||
import { docsCreateTool, docsReadTool, docsWriteTool } from './docs'
|
||||
import { driveDownloadTool, driveListTool, driveUploadTool } from './drive'
|
||||
import { exaAnswerTool, exaFindSimilarLinksTool, exaGetContentsTool, exaSearchTool } from './exa'
|
||||
import { scrapeTool } from './firecrawl/scrape'
|
||||
@@ -78,6 +79,9 @@ export const tools: Record<string, ToolConfig> = {
|
||||
google_drive_download: driveDownloadTool,
|
||||
google_drive_list: driveListTool,
|
||||
google_drive_upload: driveUploadTool,
|
||||
google_docs_read: docsReadTool,
|
||||
google_docs_write: docsWriteTool,
|
||||
google_docs_create: docsCreateTool,
|
||||
google_sheets_read: sheetsReadTool,
|
||||
google_sheets_write: sheetsWriteTool,
|
||||
google_sheets_update: sheetsUpdateTool,
|
||||
@@ -513,6 +517,7 @@ async function handleProxyRequest(
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ toolId, params }),
|
||||
})
|
||||
console.log('Proxy response:', response)
|
||||
|
||||
const result = await response.json()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user