Skip to content

Conversation

@aadamgough
Copy link
Contributor

Summary

Add more metadata fields to google drive.

Type of Change

  • Other: Improvement

Testing

Tested manually

Checklist

  • Code follows project style guidelines
  • Self-reviewed my changes
  • Tests added/updated and passing
  • No new warnings introduced
  • I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)

@vercel
Copy link

vercel bot commented Jan 9, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Review Updated (UTC)
docs Skipped Skipped Jan 10, 2026 0:51am

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Greptile Overview

Greptile Summary

This PR enhances Google Drive tool integration by adding comprehensive metadata fields (50+ fields including owners, permissions, capabilities, labels, checksums, media metadata, etc.) to match the Google Drive API v3 specification.

Changes Made

  • types.ts: Added detailed TypeScript interfaces for Google Drive metadata including GoogleDriveUser, GoogleDrivePermission, GoogleDriveCapabilities, GoogleDriveRevision, and expanded GoogleDriveFile interface
  • download.ts, get_content.ts: Added ALL_FILE_FIELDS constant to fetch complete metadata, implemented optional revision history fetching (default: true), updated output schemas
  • list.ts, upload.ts: Added ALL_FILE_FIELDS constant for comprehensive metadata in listings and after uploads, expanded output schemas
  • create_folder.ts: Updated output schema to match new metadata structure

Critical Issues Found

1. create_folder.ts - Incomplete Metadata Implementation

The transformResponse function only returns 9 basic fields but the output schema promises 50+ fields including owners, permissions, capabilities, etc. This will cause consumers to receive undefined for most promised fields. Other tools (upload, download, get_content) properly fetch complete metadata with a follow-up API call using ALL_FILE_FIELDS.

2. Missing Fields in ALL_FILE_FIELDS

The labels and labelInfo fields defined in the GoogleDriveFile type interface are not included in any of the ALL_FILE_FIELDS constants across the four tool files. These metadata fields will never be fetched despite being part of the type definition.

3. Code Duplication

The ALL_FILE_FIELDS and ALL_REVISION_FIELDS constants are duplicated identically across 4 files (download.ts, get_content.ts, list.ts, upload.ts). This creates maintenance burden where field additions/removals must be synchronized manually. These should be moved to utils.ts alongside other shared constants.

Confidence Score: 2/5

  • This PR has a critical bug in create_folder.ts that will cause runtime failures when consumers try to access promised metadata fields
  • Score reflects one critical logical bug (create_folder.ts not fetching complete metadata despite promising it), multiple consistency issues (missing labels/labelInfo fields), and code maintainability concerns (significant duplication). The incomplete metadata in create_folder.ts will definitely cause issues in production when consumers try to access fields like owners, permissions, or capabilities that the output schema promises but won't be present.
  • Pay close attention to create_folder.ts which has a critical implementation gap that must be fixed before merge. The other files need the missing 'labels' and 'labelInfo' fields added to ALL_FILE_FIELDS constants.

Important Files Changed

File Analysis

Filename Score Overview
apps/sim/tools/google_drive/types.ts 5/5 Added comprehensive TypeScript interfaces for Google Drive metadata (50+ fields) including user info, permissions, labels, capabilities, and media metadata. Type definitions are well-structured and match Google Drive API v3 schema.
apps/sim/tools/google_drive/create_folder.ts 1/5 Updated output schema to promise extensive metadata fields, but transformResponse only returns 9 basic fields. This mismatch will cause runtime issues where promised fields are undefined. Needs to fetch complete metadata like other tools.
apps/sim/tools/google_drive/download.ts 3/5 Added ALL_FILE_FIELDS constant and revision fetching. Missing 'labels' and 'labelInfo' fields from the constant. Has code duplication issue (ALL_FILE_FIELDS replicated across 4 files). Logic for fetching complete metadata and revisions is sound.
apps/sim/tools/google_drive/get_content.ts 3/5 Added ALL_FILE_FIELDS constant and revision fetching. Same issues as download.ts - missing 'labels' and 'labelInfo' fields, code duplication. Updated output schema comprehensively. Core logic works correctly.
apps/sim/tools/google_drive/list.ts 3/5 Added ALL_FILE_FIELDS constant to fetch complete metadata for all files in listing. Missing 'labels' and 'labelInfo' fields. Code duplication issue. Updated output schema with all fields. Returns data correctly from API.
apps/sim/tools/google_drive/upload.ts 3/5 Added ALL_FILE_FIELDS constant to fetch complete metadata after upload. Missing 'labels' and 'labelInfo' fields. Code duplication issue. Properly fetches complete metadata at end of upload flow. Updated output schema comprehensively.

Sequence Diagram

sequenceDiagram
    participant User
    participant Tool as Google Drive Tool
    participant GDriveAPI as Google Drive API
    participant Storage as File Storage

    alt Download File
        User->>Tool: google_drive_download(fileId)
        Tool->>GDriveAPI: GET /files/{id}?fields=ALL_FILE_FIELDS
        GDriveAPI-->>Tool: File metadata (50+ fields)
        
        alt Google Workspace File
            Tool->>GDriveAPI: GET /files/{id}/export?mimeType=...
            GDriveAPI-->>Tool: Exported file content
        else Regular File
            Tool->>GDriveAPI: GET /files/{id}?alt=media
            GDriveAPI-->>Tool: File content
        end
        
        opt includeRevisions=true (default)
            Tool->>GDriveAPI: GET /files/{id}/revisions
            GDriveAPI-->>Tool: Revision history (up to 100)
        end
        
        Tool->>Storage: Store file content
        Storage-->>Tool: File reference
        Tool-->>User: {file, metadata with revisions}
    end

    alt Get Content
        User->>Tool: google_drive_get_content(fileId)
        Tool->>GDriveAPI: GET /files/{id}?fields=ALL_FILE_FIELDS
        GDriveAPI-->>Tool: File metadata
        
        alt Google Workspace File
            Tool->>GDriveAPI: GET /files/{id}/export?mimeType=...
            GDriveAPI-->>Tool: Exported content as text
        else Regular File
            Tool->>GDriveAPI: GET /files/{id}?alt=media
            GDriveAPI-->>Tool: File content as text
        end
        
        opt includeRevisions=true (default)
            Tool->>GDriveAPI: GET /files/{id}/revisions
            GDriveAPI-->>Tool: Revision history
        end
        
        Tool-->>User: {content, metadata with revisions}
    end

    alt Upload File
        User->>Tool: google_drive_upload(file, fileName)
        Tool->>GDriveAPI: POST /files (create metadata)
        GDriveAPI-->>Tool: Basic file metadata
        Tool->>GDriveAPI: PATCH /upload/files/{id} (upload content)
        GDriveAPI-->>Tool: Upload confirmation
        
        opt Google Workspace File
            Tool->>GDriveAPI: PATCH /files/{id} (update name)
            GDriveAPI-->>Tool: Updated metadata
        end
        
        Tool->>GDriveAPI: GET /files/{id}?fields=ALL_FILE_FIELDS
        GDriveAPI-->>Tool: Complete metadata (50+ fields)
        Tool-->>User: {file: complete metadata}
    end

    alt List Files
        User->>Tool: google_drive_list(folderId?, query?)
        Tool->>GDriveAPI: GET /files?fields=files(ALL_FILE_FIELDS)
        GDriveAPI-->>Tool: Array of file metadata (50+ fields per file)
        Tool-->>User: {files, nextPageToken}
    end

    alt Create Folder (Issue: Incomplete metadata)
        User->>Tool: google_drive_create_folder(folderName)
        Tool->>GDriveAPI: POST /files (create folder)
        GDriveAPI-->>Tool: Basic folder metadata (9 fields)
        Note over Tool,GDriveAPI: Missing: Should fetch complete metadata<br/>with ALL_FILE_FIELDS like other tools
        Tool-->>User: {file: incomplete metadata}
    end
Loading

Comment on lines 14 to 88
const ALL_FILE_FIELDS = [
// Basic Info
'id',
'name',
'mimeType',
'kind',
'description',
'originalFilename',
'fullFileExtension',
'fileExtension',
// Ownership & Sharing
'owners',
'permissions',
'permissionIds',
'shared',
'ownedByMe',
'writersCanShare',
'viewersCanCopyContent',
'copyRequiresWriterPermission',
'sharingUser',
// Labels/Tags
'starred',
'trashed',
'explicitlyTrashed',
'properties',
'appProperties',
'folderColorRgb',
// Timestamps
'createdTime',
'modifiedTime',
'modifiedByMeTime',
'viewedByMeTime',
'sharedWithMeTime',
'trashedTime',
// User Info
'lastModifyingUser',
'trashingUser',
'viewedByMe',
'modifiedByMe',
// Links
'webViewLink',
'webContentLink',
'iconLink',
'thumbnailLink',
'exportLinks',
// Size & Storage
'size',
'quotaBytesUsed',
// Checksums
'md5Checksum',
'sha1Checksum',
'sha256Checksum',
// Hierarchy & Location
'parents',
'spaces',
'driveId',
'teamDriveId',
// Capabilities
'capabilities',
// Versions
'version',
'headRevisionId',
// Media Metadata
'hasThumbnail',
'thumbnailVersion',
'imageMediaMetadata',
'videoMediaMetadata',
'contentHints',
// Other
'isAppAuthorized',
'contentRestrictions',
'resourceKey',
'shortcutDetails',
'linkShareMetadata',
].join(',')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the ALL_FILE_FIELDS constant is missing the 'labels' and 'labelInfo' fields that are defined in the GoogleDriveFile type (types.ts lines 210-213). This means these metadata fields will never be fetched from the Google Drive API even though the type system expects them.

Suggested change
const ALL_FILE_FIELDS = [
// Basic Info
'id',
'name',
'mimeType',
'kind',
'description',
'originalFilename',
'fullFileExtension',
'fileExtension',
// Ownership & Sharing
'owners',
'permissions',
'permissionIds',
'shared',
'ownedByMe',
'writersCanShare',
'viewersCanCopyContent',
'copyRequiresWriterPermission',
'sharingUser',
// Labels/Tags
'starred',
'trashed',
'explicitlyTrashed',
'properties',
'appProperties',
'folderColorRgb',
// Timestamps
'createdTime',
'modifiedTime',
'modifiedByMeTime',
'viewedByMeTime',
'sharedWithMeTime',
'trashedTime',
// User Info
'lastModifyingUser',
'trashingUser',
'viewedByMe',
'modifiedByMe',
// Links
'webViewLink',
'webContentLink',
'iconLink',
'thumbnailLink',
'exportLinks',
// Size & Storage
'size',
'quotaBytesUsed',
// Checksums
'md5Checksum',
'sha1Checksum',
'sha256Checksum',
// Hierarchy & Location
'parents',
'spaces',
'driveId',
'teamDriveId',
// Capabilities
'capabilities',
// Versions
'version',
'headRevisionId',
// Media Metadata
'hasThumbnail',
'thumbnailVersion',
'imageMediaMetadata',
'videoMediaMetadata',
'contentHints',
// Other
'isAppAuthorized',
'contentRestrictions',
'resourceKey',
'shortcutDetails',
'linkShareMetadata',
].join(',')
const ALL_FILE_FIELDS = [
// Basic Info
'id',
'name',
'mimeType',
'kind',
'description',
'originalFilename',
'fullFileExtension',
'fileExtension',
// Ownership & Sharing
'owners',
'permissions',
'permissionIds',
'shared',
'ownedByMe',
'writersCanShare',
'viewersCanCopyContent',
'copyRequiresWriterPermission',
'sharingUser',
// Labels/Tags
'labels',
'labelInfo',
'starred',
'trashed',
'explicitlyTrashed',
'properties',
'appProperties',
'folderColorRgb',
// Timestamps
'createdTime',
'modifiedTime',
'modifiedByMeTime',
'viewedByMeTime',
'sharedWithMeTime',
'trashedTime',
// User Info
'lastModifyingUser',
'trashingUser',
'viewedByMe',
'modifiedByMe',
// Links
'webViewLink',
'webContentLink',
'iconLink',
'thumbnailLink',
'exportLinks',
// Size & Storage
'size',
'quotaBytesUsed',
// Checksums
'md5Checksum',
'sha1Checksum',
'sha256Checksum',
// Hierarchy & Location
'parents',
'spaces',
'driveId',
'teamDriveId',
// Capabilities
'capabilities',
// Versions
'version',
'headRevisionId',
// Media Metadata
'hasThumbnail',
'thumbnailVersion',
'imageMediaMetadata',
'videoMediaMetadata',
'contentHints',
// Other
'isAppAuthorized',
'contentRestrictions',
'resourceKey',
'shortcutDetails',
'linkShareMetadata',
].join(',')
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/sim/tools/google_drive/download.ts
Line: 14:88

Comment:
the ALL_FILE_FIELDS constant is missing the 'labels' and 'labelInfo' fields that are defined in the GoogleDriveFile type (types.ts lines 210-213). This means these metadata fields will never be fetched from the Google Drive API even though the type system expects them.

```suggestion
const ALL_FILE_FIELDS = [
  // Basic Info
  'id',
  'name',
  'mimeType',
  'kind',
  'description',
  'originalFilename',
  'fullFileExtension',
  'fileExtension',
  // Ownership & Sharing
  'owners',
  'permissions',
  'permissionIds',
  'shared',
  'ownedByMe',
  'writersCanShare',
  'viewersCanCopyContent',
  'copyRequiresWriterPermission',
  'sharingUser',
  // Labels/Tags
  'labels',
  'labelInfo',
  'starred',
  'trashed',
  'explicitlyTrashed',
  'properties',
  'appProperties',
  'folderColorRgb',
  // Timestamps
  'createdTime',
  'modifiedTime',
  'modifiedByMeTime',
  'viewedByMeTime',
  'sharedWithMeTime',
  'trashedTime',
  // User Info
  'lastModifyingUser',
  'trashingUser',
  'viewedByMe',
  'modifiedByMe',
  // Links
  'webViewLink',
  'webContentLink',
  'iconLink',
  'thumbnailLink',
  'exportLinks',
  // Size & Storage
  'size',
  'quotaBytesUsed',
  // Checksums
  'md5Checksum',
  'sha1Checksum',
  'sha256Checksum',
  // Hierarchy & Location
  'parents',
  'spaces',
  'driveId',
  'teamDriveId',
  // Capabilities
  'capabilities',
  // Versions
  'version',
  'headRevisionId',
  // Media Metadata
  'hasThumbnail',
  'thumbnailVersion',
  'imageMediaMetadata',
  'videoMediaMetadata',
  'contentHints',
  // Other
  'isAppAuthorized',
  'contentRestrictions',
  'resourceKey',
  'shortcutDetails',
  'linkShareMetadata',
].join(',')
```

How can I resolve this? If you propose a fix, please make it concise.

Comment on lines 14 to 88
const ALL_FILE_FIELDS = [
// Basic Info
'id',
'name',
'mimeType',
'kind',
'description',
'originalFilename',
'fullFileExtension',
'fileExtension',
// Ownership & Sharing
'owners',
'permissions',
'permissionIds',
'shared',
'ownedByMe',
'writersCanShare',
'viewersCanCopyContent',
'copyRequiresWriterPermission',
'sharingUser',
// Labels/Tags
'starred',
'trashed',
'explicitlyTrashed',
'properties',
'appProperties',
'folderColorRgb',
// Timestamps
'createdTime',
'modifiedTime',
'modifiedByMeTime',
'viewedByMeTime',
'sharedWithMeTime',
'trashedTime',
// User Info
'lastModifyingUser',
'trashingUser',
'viewedByMe',
'modifiedByMe',
// Links
'webViewLink',
'webContentLink',
'iconLink',
'thumbnailLink',
'exportLinks',
// Size & Storage
'size',
'quotaBytesUsed',
// Checksums
'md5Checksum',
'sha1Checksum',
'sha256Checksum',
// Hierarchy & Location
'parents',
'spaces',
'driveId',
'teamDriveId',
// Capabilities
'capabilities',
// Versions
'version',
'headRevisionId',
// Media Metadata
'hasThumbnail',
'thumbnailVersion',
'imageMediaMetadata',
'videoMediaMetadata',
'contentHints',
// Other
'isAppAuthorized',
'contentRestrictions',
'resourceKey',
'shortcutDetails',
'linkShareMetadata',
].join(',')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the ALL_FILE_FIELDS constant is missing the 'labels' and 'labelInfo' fields that are defined in the GoogleDriveFile type (types.ts lines 210-213). This means these metadata fields will never be fetched from the Google Drive API even though the type system expects them.

Suggested change
const ALL_FILE_FIELDS = [
// Basic Info
'id',
'name',
'mimeType',
'kind',
'description',
'originalFilename',
'fullFileExtension',
'fileExtension',
// Ownership & Sharing
'owners',
'permissions',
'permissionIds',
'shared',
'ownedByMe',
'writersCanShare',
'viewersCanCopyContent',
'copyRequiresWriterPermission',
'sharingUser',
// Labels/Tags
'starred',
'trashed',
'explicitlyTrashed',
'properties',
'appProperties',
'folderColorRgb',
// Timestamps
'createdTime',
'modifiedTime',
'modifiedByMeTime',
'viewedByMeTime',
'sharedWithMeTime',
'trashedTime',
// User Info
'lastModifyingUser',
'trashingUser',
'viewedByMe',
'modifiedByMe',
// Links
'webViewLink',
'webContentLink',
'iconLink',
'thumbnailLink',
'exportLinks',
// Size & Storage
'size',
'quotaBytesUsed',
// Checksums
'md5Checksum',
'sha1Checksum',
'sha256Checksum',
// Hierarchy & Location
'parents',
'spaces',
'driveId',
'teamDriveId',
// Capabilities
'capabilities',
// Versions
'version',
'headRevisionId',
// Media Metadata
'hasThumbnail',
'thumbnailVersion',
'imageMediaMetadata',
'videoMediaMetadata',
'contentHints',
// Other
'isAppAuthorized',
'contentRestrictions',
'resourceKey',
'shortcutDetails',
'linkShareMetadata',
].join(',')
const ALL_FILE_FIELDS = [
// Basic Info
'id',
'name',
'mimeType',
'kind',
'description',
'originalFilename',
'fullFileExtension',
'fileExtension',
// Ownership & Sharing
'owners',
'permissions',
'permissionIds',
'shared',
'ownedByMe',
'writersCanShare',
'viewersCanCopyContent',
'copyRequiresWriterPermission',
'sharingUser',
// Labels/Tags
'labels',
'labelInfo',
'starred',
'trashed',
'explicitlyTrashed',
'properties',
'appProperties',
'folderColorRgb',
// Timestamps
'createdTime',
'modifiedTime',
'modifiedByMeTime',
'viewedByMeTime',
'sharedWithMeTime',
'trashedTime',
// User Info
'lastModifyingUser',
'trashingUser',
'viewedByMe',
'modifiedByMe',
// Links
'webViewLink',
'webContentLink',
'iconLink',
'thumbnailLink',
'exportLinks',
// Size & Storage
'size',
'quotaBytesUsed',
// Checksums
'md5Checksum',
'sha1Checksum',
'sha256Checksum',
// Hierarchy & Location
'parents',
'spaces',
'driveId',
'teamDriveId',
// Capabilities
'capabilities',
// Versions
'version',
'headRevisionId',
// Media Metadata
'hasThumbnail',
'thumbnailVersion',
'imageMediaMetadata',
'videoMediaMetadata',
'contentHints',
// Other
'isAppAuthorized',
'contentRestrictions',
'resourceKey',
'shortcutDetails',
'linkShareMetadata',
].join(',')
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/sim/tools/google_drive/get_content.ts
Line: 14:88

Comment:
the ALL_FILE_FIELDS constant is missing the 'labels' and 'labelInfo' fields that are defined in the GoogleDriveFile type (types.ts lines 210-213). This means these metadata fields will never be fetched from the Google Drive API even though the type system expects them.

```suggestion
const ALL_FILE_FIELDS = [
  // Basic Info
  'id',
  'name',
  'mimeType',
  'kind',
  'description',
  'originalFilename',
  'fullFileExtension',
  'fileExtension',
  // Ownership & Sharing
  'owners',
  'permissions',
  'permissionIds',
  'shared',
  'ownedByMe',
  'writersCanShare',
  'viewersCanCopyContent',
  'copyRequiresWriterPermission',
  'sharingUser',
  // Labels/Tags
  'labels',
  'labelInfo',
  'starred',
  'trashed',
  'explicitlyTrashed',
  'properties',
  'appProperties',
  'folderColorRgb',
  // Timestamps
  'createdTime',
  'modifiedTime',
  'modifiedByMeTime',
  'viewedByMeTime',
  'sharedWithMeTime',
  'trashedTime',
  // User Info
  'lastModifyingUser',
  'trashingUser',
  'viewedByMe',
  'modifiedByMe',
  // Links
  'webViewLink',
  'webContentLink',
  'iconLink',
  'thumbnailLink',
  'exportLinks',
  // Size & Storage
  'size',
  'quotaBytesUsed',
  // Checksums
  'md5Checksum',
  'sha1Checksum',
  'sha256Checksum',
  // Hierarchy & Location
  'parents',
  'spaces',
  'driveId',
  'teamDriveId',
  // Capabilities
  'capabilities',
  // Versions
  'version',
  'headRevisionId',
  // Media Metadata
  'hasThumbnail',
  'thumbnailVersion',
  'imageMediaMetadata',
  'videoMediaMetadata',
  'contentHints',
  // Other
  'isAppAuthorized',
  'contentRestrictions',
  'resourceKey',
  'shortcutDetails',
  'linkShareMetadata',
].join(',')
```

How can I resolve this? If you propose a fix, please make it concise.

Comment on lines 6 to 80
const ALL_FILE_FIELDS = [
// Basic Info
'id',
'name',
'mimeType',
'kind',
'description',
'originalFilename',
'fullFileExtension',
'fileExtension',
// Ownership & Sharing
'owners',
'permissions',
'permissionIds',
'shared',
'ownedByMe',
'writersCanShare',
'viewersCanCopyContent',
'copyRequiresWriterPermission',
'sharingUser',
// Labels/Tags
'starred',
'trashed',
'explicitlyTrashed',
'properties',
'appProperties',
'folderColorRgb',
// Timestamps
'createdTime',
'modifiedTime',
'modifiedByMeTime',
'viewedByMeTime',
'sharedWithMeTime',
'trashedTime',
// User Info
'lastModifyingUser',
'trashingUser',
'viewedByMe',
'modifiedByMe',
// Links
'webViewLink',
'webContentLink',
'iconLink',
'thumbnailLink',
'exportLinks',
// Size & Storage
'size',
'quotaBytesUsed',
// Checksums
'md5Checksum',
'sha1Checksum',
'sha256Checksum',
// Hierarchy & Location
'parents',
'spaces',
'driveId',
'teamDriveId',
// Capabilities
'capabilities',
// Versions
'version',
'headRevisionId',
// Media Metadata
'hasThumbnail',
'thumbnailVersion',
'imageMediaMetadata',
'videoMediaMetadata',
'contentHints',
// Other
'isAppAuthorized',
'contentRestrictions',
'resourceKey',
'shortcutDetails',
'linkShareMetadata',
].join(',')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the ALL_FILE_FIELDS constant is missing the 'labels' and 'labelInfo' fields that are defined in the GoogleDriveFile type (types.ts lines 210-213). This means these metadata fields will never be fetched from the Google Drive API even though the type system expects them.

Suggested change
const ALL_FILE_FIELDS = [
// Basic Info
'id',
'name',
'mimeType',
'kind',
'description',
'originalFilename',
'fullFileExtension',
'fileExtension',
// Ownership & Sharing
'owners',
'permissions',
'permissionIds',
'shared',
'ownedByMe',
'writersCanShare',
'viewersCanCopyContent',
'copyRequiresWriterPermission',
'sharingUser',
// Labels/Tags
'starred',
'trashed',
'explicitlyTrashed',
'properties',
'appProperties',
'folderColorRgb',
// Timestamps
'createdTime',
'modifiedTime',
'modifiedByMeTime',
'viewedByMeTime',
'sharedWithMeTime',
'trashedTime',
// User Info
'lastModifyingUser',
'trashingUser',
'viewedByMe',
'modifiedByMe',
// Links
'webViewLink',
'webContentLink',
'iconLink',
'thumbnailLink',
'exportLinks',
// Size & Storage
'size',
'quotaBytesUsed',
// Checksums
'md5Checksum',
'sha1Checksum',
'sha256Checksum',
// Hierarchy & Location
'parents',
'spaces',
'driveId',
'teamDriveId',
// Capabilities
'capabilities',
// Versions
'version',
'headRevisionId',
// Media Metadata
'hasThumbnail',
'thumbnailVersion',
'imageMediaMetadata',
'videoMediaMetadata',
'contentHints',
// Other
'isAppAuthorized',
'contentRestrictions',
'resourceKey',
'shortcutDetails',
'linkShareMetadata',
].join(',')
const ALL_FILE_FIELDS = [
// Basic Info
'id',
'name',
'mimeType',
'kind',
'description',
'originalFilename',
'fullFileExtension',
'fileExtension',
// Ownership & Sharing
'owners',
'permissions',
'permissionIds',
'shared',
'ownedByMe',
'writersCanShare',
'viewersCanCopyContent',
'copyRequiresWriterPermission',
'sharingUser',
// Labels/Tags
'labels',
'labelInfo',
'starred',
'trashed',
'explicitlyTrashed',
'properties',
'appProperties',
'folderColorRgb',
// Timestamps
'createdTime',
'modifiedTime',
'modifiedByMeTime',
'viewedByMeTime',
'sharedWithMeTime',
'trashedTime',
// User Info
'lastModifyingUser',
'trashingUser',
'viewedByMe',
'modifiedByMe',
// Links
'webViewLink',
'webContentLink',
'iconLink',
'thumbnailLink',
'exportLinks',
// Size & Storage
'size',
'quotaBytesUsed',
// Checksums
'md5Checksum',
'sha1Checksum',
'sha256Checksum',
// Hierarchy & Location
'parents',
'spaces',
'driveId',
'teamDriveId',
// Capabilities
'capabilities',
// Versions
'version',
'headRevisionId',
// Media Metadata
'hasThumbnail',
'thumbnailVersion',
'imageMediaMetadata',
'videoMediaMetadata',
'contentHints',
// Other
'isAppAuthorized',
'contentRestrictions',
'resourceKey',
'shortcutDetails',
'linkShareMetadata',
].join(',')
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/sim/tools/google_drive/list.ts
Line: 6:80

Comment:
the ALL_FILE_FIELDS constant is missing the 'labels' and 'labelInfo' fields that are defined in the GoogleDriveFile type (types.ts lines 210-213). This means these metadata fields will never be fetched from the Google Drive API even though the type system expects them.

```suggestion
const ALL_FILE_FIELDS = [
  // Basic Info
  'id',
  'name',
  'mimeType',
  'kind',
  'description',
  'originalFilename',
  'fullFileExtension',
  'fileExtension',
  // Ownership & Sharing
  'owners',
  'permissions',
  'permissionIds',
  'shared',
  'ownedByMe',
  'writersCanShare',
  'viewersCanCopyContent',
  'copyRequiresWriterPermission',
  'sharingUser',
  // Labels/Tags
  'labels',
  'labelInfo',
  'starred',
  'trashed',
  'explicitlyTrashed',
  'properties',
  'appProperties',
  'folderColorRgb',
  // Timestamps
  'createdTime',
  'modifiedTime',
  'modifiedByMeTime',
  'viewedByMeTime',
  'sharedWithMeTime',
  'trashedTime',
  // User Info
  'lastModifyingUser',
  'trashingUser',
  'viewedByMe',
  'modifiedByMe',
  // Links
  'webViewLink',
  'webContentLink',
  'iconLink',
  'thumbnailLink',
  'exportLinks',
  // Size & Storage
  'size',
  'quotaBytesUsed',
  // Checksums
  'md5Checksum',
  'sha1Checksum',
  'sha256Checksum',
  // Hierarchy & Location
  'parents',
  'spaces',
  'driveId',
  'teamDriveId',
  // Capabilities
  'capabilities',
  // Versions
  'version',
  'headRevisionId',
  // Media Metadata
  'hasThumbnail',
  'thumbnailVersion',
  'imageMediaMetadata',
  'videoMediaMetadata',
  'contentHints',
  // Other
  'isAppAuthorized',
  'contentRestrictions',
  'resourceKey',
  'shortcutDetails',
  'linkShareMetadata',
].join(',')
```

How can I resolve this? If you propose a fix, please make it concise.

Comment on lines 13 to 87
const ALL_FILE_FIELDS = [
// Basic Info
'id',
'name',
'mimeType',
'kind',
'description',
'originalFilename',
'fullFileExtension',
'fileExtension',
// Ownership & Sharing
'owners',
'permissions',
'permissionIds',
'shared',
'ownedByMe',
'writersCanShare',
'viewersCanCopyContent',
'copyRequiresWriterPermission',
'sharingUser',
// Labels/Tags
'starred',
'trashed',
'explicitlyTrashed',
'properties',
'appProperties',
'folderColorRgb',
// Timestamps
'createdTime',
'modifiedTime',
'modifiedByMeTime',
'viewedByMeTime',
'sharedWithMeTime',
'trashedTime',
// User Info
'lastModifyingUser',
'trashingUser',
'viewedByMe',
'modifiedByMe',
// Links
'webViewLink',
'webContentLink',
'iconLink',
'thumbnailLink',
'exportLinks',
// Size & Storage
'size',
'quotaBytesUsed',
// Checksums
'md5Checksum',
'sha1Checksum',
'sha256Checksum',
// Hierarchy & Location
'parents',
'spaces',
'driveId',
'teamDriveId',
// Capabilities
'capabilities',
// Versions
'version',
'headRevisionId',
// Media Metadata
'hasThumbnail',
'thumbnailVersion',
'imageMediaMetadata',
'videoMediaMetadata',
'contentHints',
// Other
'isAppAuthorized',
'contentRestrictions',
'resourceKey',
'shortcutDetails',
'linkShareMetadata',
].join(',')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the ALL_FILE_FIELDS constant is missing the 'labels' and 'labelInfo' fields that are defined in the GoogleDriveFile type (types.ts lines 210-213). This means these metadata fields will never be fetched from the Google Drive API even though the type system expects them.

Suggested change
const ALL_FILE_FIELDS = [
// Basic Info
'id',
'name',
'mimeType',
'kind',
'description',
'originalFilename',
'fullFileExtension',
'fileExtension',
// Ownership & Sharing
'owners',
'permissions',
'permissionIds',
'shared',
'ownedByMe',
'writersCanShare',
'viewersCanCopyContent',
'copyRequiresWriterPermission',
'sharingUser',
// Labels/Tags
'starred',
'trashed',
'explicitlyTrashed',
'properties',
'appProperties',
'folderColorRgb',
// Timestamps
'createdTime',
'modifiedTime',
'modifiedByMeTime',
'viewedByMeTime',
'sharedWithMeTime',
'trashedTime',
// User Info
'lastModifyingUser',
'trashingUser',
'viewedByMe',
'modifiedByMe',
// Links
'webViewLink',
'webContentLink',
'iconLink',
'thumbnailLink',
'exportLinks',
// Size & Storage
'size',
'quotaBytesUsed',
// Checksums
'md5Checksum',
'sha1Checksum',
'sha256Checksum',
// Hierarchy & Location
'parents',
'spaces',
'driveId',
'teamDriveId',
// Capabilities
'capabilities',
// Versions
'version',
'headRevisionId',
// Media Metadata
'hasThumbnail',
'thumbnailVersion',
'imageMediaMetadata',
'videoMediaMetadata',
'contentHints',
// Other
'isAppAuthorized',
'contentRestrictions',
'resourceKey',
'shortcutDetails',
'linkShareMetadata',
].join(',')
const ALL_FILE_FIELDS = [
// Basic Info
'id',
'name',
'mimeType',
'kind',
'description',
'originalFilename',
'fullFileExtension',
'fileExtension',
// Ownership & Sharing
'owners',
'permissions',
'permissionIds',
'shared',
'ownedByMe',
'writersCanShare',
'viewersCanCopyContent',
'copyRequiresWriterPermission',
'sharingUser',
// Labels/Tags
'labels',
'labelInfo',
'starred',
'trashed',
'explicitlyTrashed',
'properties',
'appProperties',
'folderColorRgb',
// Timestamps
'createdTime',
'modifiedTime',
'modifiedByMeTime',
'viewedByMeTime',
'sharedWithMeTime',
'trashedTime',
// User Info
'lastModifyingUser',
'trashingUser',
'viewedByMe',
'modifiedByMe',
// Links
'webViewLink',
'webContentLink',
'iconLink',
'thumbnailLink',
'exportLinks',
// Size & Storage
'size',
'quotaBytesUsed',
// Checksums
'md5Checksum',
'sha1Checksum',
'sha256Checksum',
// Hierarchy & Location
'parents',
'spaces',
'driveId',
'teamDriveId',
// Capabilities
'capabilities',
// Versions
'version',
'headRevisionId',
// Media Metadata
'hasThumbnail',
'thumbnailVersion',
'imageMediaMetadata',
'videoMediaMetadata',
'contentHints',
// Other
'isAppAuthorized',
'contentRestrictions',
'resourceKey',
'shortcutDetails',
'linkShareMetadata',
].join(',')
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/sim/tools/google_drive/upload.ts
Line: 13:87

Comment:
the ALL_FILE_FIELDS constant is missing the 'labels' and 'labelInfo' fields that are defined in the GoogleDriveFile type (types.ts lines 210-213). This means these metadata fields will never be fetched from the Google Drive API even though the type system expects them.

```suggestion
const ALL_FILE_FIELDS = [
  // Basic Info
  'id',
  'name',
  'mimeType',
  'kind',
  'description',
  'originalFilename',
  'fullFileExtension',
  'fileExtension',
  // Ownership & Sharing
  'owners',
  'permissions',
  'permissionIds',
  'shared',
  'ownedByMe',
  'writersCanShare',
  'viewersCanCopyContent',
  'copyRequiresWriterPermission',
  'sharingUser',
  // Labels/Tags
  'labels',
  'labelInfo',
  'starred',
  'trashed',
  'explicitlyTrashed',
  'properties',
  'appProperties',
  'folderColorRgb',
  // Timestamps
  'createdTime',
  'modifiedTime',
  'modifiedByMeTime',
  'viewedByMeTime',
  'sharedWithMeTime',
  'trashedTime',
  // User Info
  'lastModifyingUser',
  'trashingUser',
  'viewedByMe',
  'modifiedByMe',
  // Links
  'webViewLink',
  'webContentLink',
  'iconLink',
  'thumbnailLink',
  'exportLinks',
  // Size & Storage
  'size',
  'quotaBytesUsed',
  // Checksums
  'md5Checksum',
  'sha1Checksum',
  'sha256Checksum',
  // Hierarchy & Location
  'parents',
  'spaces',
  'driveId',
  'teamDriveId',
  // Capabilities
  'capabilities',
  // Versions
  'version',
  'headRevisionId',
  // Media Metadata
  'hasThumbnail',
  'thumbnailVersion',
  'imageMediaMetadata',
  'videoMediaMetadata',
  'contentHints',
  // Other
  'isAppAuthorized',
  'contentRestrictions',
  'resourceKey',
  'shortcutDetails',
  'linkShareMetadata',
].join(',')
```

How can I resolve this? If you propose a fix, please make it concise.

Comment on lines 14 to 106
const ALL_FILE_FIELDS = [
// Basic Info
'id',
'name',
'mimeType',
'kind',
'description',
'originalFilename',
'fullFileExtension',
'fileExtension',
// Ownership & Sharing
'owners',
'permissions',
'permissionIds',
'shared',
'ownedByMe',
'writersCanShare',
'viewersCanCopyContent',
'copyRequiresWriterPermission',
'sharingUser',
// Labels/Tags
'starred',
'trashed',
'explicitlyTrashed',
'properties',
'appProperties',
'folderColorRgb',
// Timestamps
'createdTime',
'modifiedTime',
'modifiedByMeTime',
'viewedByMeTime',
'sharedWithMeTime',
'trashedTime',
// User Info
'lastModifyingUser',
'trashingUser',
'viewedByMe',
'modifiedByMe',
// Links
'webViewLink',
'webContentLink',
'iconLink',
'thumbnailLink',
'exportLinks',
// Size & Storage
'size',
'quotaBytesUsed',
// Checksums
'md5Checksum',
'sha1Checksum',
'sha256Checksum',
// Hierarchy & Location
'parents',
'spaces',
'driveId',
'teamDriveId',
// Capabilities
'capabilities',
// Versions
'version',
'headRevisionId',
// Media Metadata
'hasThumbnail',
'thumbnailVersion',
'imageMediaMetadata',
'videoMediaMetadata',
'contentHints',
// Other
'isAppAuthorized',
'contentRestrictions',
'resourceKey',
'shortcutDetails',
'linkShareMetadata',
].join(',')

// All revision fields
const ALL_REVISION_FIELDS = [
'id',
'mimeType',
'modifiedTime',
'keepForever',
'published',
'publishAuto',
'publishedLink',
'publishedOutsideDomain',
'lastModifyingUser',
'originalFilename',
'md5Checksum',
'size',
'exportLinks',
'kind',
].join(',')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the ALL_FILE_FIELDS and ALL_REVISION_FIELDS constants are duplicated across 4 files (download.ts, get_content.ts, list.ts, and upload.ts). This creates a maintenance burden where any field addition/removal must be synchronized across all files.

These constants should be moved to utils.ts (where other shared constants like GOOGLE_WORKSPACE_MIME_TYPES already live) and imported by the files that need them. This would ensure consistency and make updates easier.

Example:

// In utils.ts
export const ALL_FILE_FIELDS = [
  'id', 'name', 'mimeType', 'kind', 'description', 'originalFilename',
  'fullFileExtension', 'fileExtension', 'owners', 'permissions', 
  // ... all other fields including 'labels' and 'labelInfo'
].join(',')

export const ALL_REVISION_FIELDS = [
  'id', 'mimeType', 'modifiedTime', 'keepForever', 'published',
  // ... all other fields
].join(',')

// Then in each tool file:
import { ALL_FILE_FIELDS, ALL_REVISION_FIELDS } from './utils'

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/sim/tools/google_drive/download.ts
Line: 14:106

Comment:
the ALL_FILE_FIELDS and ALL_REVISION_FIELDS constants are duplicated across 4 files (download.ts, get_content.ts, list.ts, and upload.ts). This creates a maintenance burden where any field addition/removal must be synchronized across all files.

These constants should be moved to utils.ts (where other shared constants like GOOGLE_WORKSPACE_MIME_TYPES already live) and imported by the files that need them. This would ensure consistency and make updates easier.

Example:
```typescript
// In utils.ts
export const ALL_FILE_FIELDS = [
  'id', 'name', 'mimeType', 'kind', 'description', 'originalFilename',
  'fullFileExtension', 'fileExtension', 'owners', 'permissions', 
  // ... all other fields including 'labels' and 'labelInfo'
].join(',')

export const ALL_REVISION_FIELDS = [
  'id', 'mimeType', 'modifiedTime', 'keepForever', 'published',
  // ... all other fields
].join(',')

// Then in each tool file:
import { ALL_FILE_FIELDS, ALL_REVISION_FIELDS } from './utils'
```

<sub>Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!</sub>

How can I resolve this? If you propose a fix, please make it concise.

@greptile-apps
Copy link
Contributor

greptile-apps bot commented Jan 9, 2026

Additional Comments (1)

apps/sim/tools/google_drive/create_folder.ts
the transformResponse function only returns a limited subset of metadata fields, but the expanded output schema (lines 95-109) promises many additional fields like owners, permissions, capabilities, starred, etc. that will not be present in the response.

To fix this, the function should either:

  1. Fetch the complete metadata using ALL_FILE_FIELDS (like the other tools do), or
  2. Update the output schema to only list the fields that are actually returned
  transformResponse: async (response: Response, params?: GoogleDriveToolParams) => {
    if (!response.ok) {
      const data = await response.json().catch(() => ({}))
      throw new Error(data.error?.message || 'Failed to create folder in Google Drive')
    }
    const data = await response.json()
    
    // Fetch complete metadata with all fields
    const folderId = data.id
    const authHeader = `Bearer ${params?.accessToken || ''}`
    const ALL_FILE_FIELDS = [
      'id', 'name', 'mimeType', 'kind', 'description', 'originalFilename',
      'fullFileExtension', 'fileExtension', 'owners', 'permissions', 'permissionIds',
      'shared', 'ownedByMe', 'writersCanShare', 'viewersCanCopyContent',
      'copyRequiresWriterPermission', 'sharingUser', 'starred', 'trashed',
      'explicitlyTrashed', 'properties', 'appProperties', 'folderColorRgb',
      'createdTime', 'modifiedTime', 'modifiedByMeTime', 'viewedByMeTime',
      'sharedWithMeTime', 'trashedTime', 'lastModifyingUser', 'trashingUser',
      'viewedByMe', 'modifiedByMe', 'webViewLink', 'webContentLink', 'iconLink',
      'thumbnailLink', 'exportLinks', 'size', 'quotaBytesUsed', 'md5Checksum',
      'sha1Checksum', 'sha256Checksum', 'parents', 'spaces', 'driveId',
      'teamDriveId', 'capabilities', 'version', 'headRevisionId', 'hasThumbnail',
      'thumbnailVersion', 'imageMediaMetadata', 'videoMediaMetadata',
      'contentHints', 'isAppAuthorized', 'contentRestrictions', 'resourceKey',
      'shortcutDetails', 'linkShareMetadata'
    ].join(',')
    
    const metadataResponse = await fetch(
      `https://www.googleapis.com/drive/v3/files/${folderId}?fields=${ALL_FILE_FIELDS}&supportsAllDrives=true`,
      {
        headers: {
          Authorization: authHeader,
        },
      }
    )
    
    if (!metadataResponse.ok) {
      throw new Error('Failed to fetch complete folder metadata')
    }
    
    const fullMetadata = await metadataResponse.json()

    return {
      success: true,
      output: {
        file: fullMetadata,
      },
    }
  },
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/sim/tools/google_drive/create_folder.ts
Line: 79:90

Comment:
the transformResponse function only returns a limited subset of metadata fields, but the expanded output schema (lines 95-109) promises many additional fields like `owners`, `permissions`, `capabilities`, `starred`, etc. that will not be present in the response.

To fix this, the function should either:
1. Fetch the complete metadata using `ALL_FILE_FIELDS` (like the other tools do), or
2. Update the output schema to only list the fields that are actually returned

```suggestion
  transformResponse: async (response: Response, params?: GoogleDriveToolParams) => {
    if (!response.ok) {
      const data = await response.json().catch(() => ({}))
      throw new Error(data.error?.message || 'Failed to create folder in Google Drive')
    }
    const data = await response.json()
    
    // Fetch complete metadata with all fields
    const folderId = data.id
    const authHeader = `Bearer ${params?.accessToken || ''}`
    const ALL_FILE_FIELDS = [
      'id', 'name', 'mimeType', 'kind', 'description', 'originalFilename',
      'fullFileExtension', 'fileExtension', 'owners', 'permissions', 'permissionIds',
      'shared', 'ownedByMe', 'writersCanShare', 'viewersCanCopyContent',
      'copyRequiresWriterPermission', 'sharingUser', 'starred', 'trashed',
      'explicitlyTrashed', 'properties', 'appProperties', 'folderColorRgb',
      'createdTime', 'modifiedTime', 'modifiedByMeTime', 'viewedByMeTime',
      'sharedWithMeTime', 'trashedTime', 'lastModifyingUser', 'trashingUser',
      'viewedByMe', 'modifiedByMe', 'webViewLink', 'webContentLink', 'iconLink',
      'thumbnailLink', 'exportLinks', 'size', 'quotaBytesUsed', 'md5Checksum',
      'sha1Checksum', 'sha256Checksum', 'parents', 'spaces', 'driveId',
      'teamDriveId', 'capabilities', 'version', 'headRevisionId', 'hasThumbnail',
      'thumbnailVersion', 'imageMediaMetadata', 'videoMediaMetadata',
      'contentHints', 'isAppAuthorized', 'contentRestrictions', 'resourceKey',
      'shortcutDetails', 'linkShareMetadata'
    ].join(',')
    
    const metadataResponse = await fetch(
      `https://www.googleapis.com/drive/v3/files/${folderId}?fields=${ALL_FILE_FIELDS}&supportsAllDrives=true`,
      {
        headers: {
          Authorization: authHeader,
        },
      }
    )
    
    if (!metadataResponse.ok) {
      throw new Error('Failed to fetch complete folder metadata')
    }
    
    const fullMetadata = await metadataResponse.json()

    return {
      success: true,
      output: {
        file: fullMetadata,
      },
    }
  },
```

How can I resolve this? If you propose a fix, please make it concise.

@aadamgough
Copy link
Contributor Author

@greptile

@greptile-apps
Copy link
Contributor

greptile-apps bot commented Jan 9, 2026

Greptile Overview

Greptile Summary

This PR enhances Google Drive integration by adding comprehensive metadata fields across all tools. The implementation introduces ALL_FILE_FIELDS and ALL_REVISION_FIELDS constants to fetch 50+ metadata fields from the Google Drive API v3, including owners, permissions, capabilities, timestamps, checksums, and media metadata.

Key Changes:

  • Metadata Expansion: All tools now return complete Google Drive file metadata with 50+ fields
  • Revision History: download and get_content tools can now fetch file revision history (default: enabled, up to 100 revisions)
  • Type Safety: Comprehensive TypeScript interfaces added for all Google Drive API objects
  • Query Escaping: List tool properly escapes user input for Google Drive query syntax
  • Documentation: Updated tool descriptions to reflect complete metadata return values

Issues Identified:

  1. Critical - API Route Metadata Inconsistency: The upload API route (apps/sim/app/api/tools/google_drive/upload/route.ts) only fetches 8 metadata fields instead of using ALL_FILE_FIELDS, creating an inconsistency where file uploads return less metadata than text-only uploads. This breaks the tool's promise of "complete metadata."

  2. Logic Error - Output Schema Mismatch: The download tool's output schema for the file field doesn't match what's actually returned. Schema promises properties like id, url, key, context but code returns name, mimeType, data, size.

  3. Best Practice - Revision Pagination: Both download and get_content tools fetch only the first 100 revisions without handling pagination. Files with >100 revisions will have incomplete revision history with no indication to users.

  4. Style - Input Validation Inconsistency: create_folder doesn't trim/validate parentFolderId for empty strings, while upload does. Could cause unclear API errors with whitespace-only folder IDs.

Overall Assessment: The metadata enhancement is well-implemented with proper type definitions and comprehensive field coverage. However, the inconsistency in the API route and the output schema mismatch in download need to be addressed to ensure consistent behavior across all upload methods.

Confidence Score: 3/5

  • This PR has functional issues that should be addressed before merging, particularly the metadata inconsistency and schema mismatch
  • Score of 3 reflects that while the core metadata enhancement is well-designed with comprehensive type definitions, there are two logic errors that could cause production issues: (1) the API route returns incomplete metadata creating inconsistency between upload methods, and (2) the download tool's output schema doesn't match actual return values. The revision pagination limitation is a minor concern but acceptable. These issues are straightforward to fix but should be addressed to ensure API consistency.
  • Pay close attention to apps/sim/app/api/tools/google_drive/upload/route.ts (needs to fetch ALL_FILE_FIELDS) and apps/sim/tools/google_drive/download.ts (output schema mismatch)

Important Files Changed

File Analysis

Filename Score Overview
apps/sim/app/api/tools/google_drive/upload/route.ts 3/5 API route only fetches limited metadata fields instead of ALL_FILE_FIELDS, creating inconsistency with tool's promise of complete metadata
apps/sim/tools/google_drive/download.ts 3/5 Output schema mismatch - promises properties that aren't returned; revision fetching limited to 100 without pagination
apps/sim/tools/google_drive/get_content.ts 4/5 Revision fetching limited to 100 without pagination handling; otherwise properly implemented with complete metadata
apps/sim/tools/google_drive/create_folder.ts 4/5 Missing trim check for parentFolderId (inconsistent with upload.ts); otherwise correctly fetches complete metadata
apps/sim/tools/google_drive/upload.ts 4/5 Text-only uploads properly fetch complete metadata; file uploads delegate to API route which has metadata issue
apps/sim/tools/google_drive/list.ts 5/5 Properly implements query escaping and fetches complete metadata for all files; no issues found

Sequence Diagram

sequenceDiagram
    participant User
    participant Tool
    participant GoogleDrive as Google Drive API
    participant Storage
    
    Note over User,Storage: Upload File Flow (with metadata enhancement)
    User->>Tool: upload(file, fileName, folderId)
    Tool->>Storage: Store file temporarily
    Tool->>GoogleDrive: POST /files (multipart upload)
    GoogleDrive-->>Tool: Basic file response (id, name)
    Tool->>GoogleDrive: GET /files/{id}?fields=ALL_FILE_FIELDS
    GoogleDrive-->>Tool: Complete metadata (50+ fields)
    Tool-->>User: {file: GoogleDriveFile}
    
    Note over User,Storage: Download File Flow (with revisions)
    User->>Tool: download(fileId, includeRevisions=true)
    Tool->>GoogleDrive: GET /files/{id}?fields=ALL_FILE_FIELDS
    GoogleDrive-->>Tool: Complete metadata
    alt includeRevisions && canReadRevisions
        Tool->>GoogleDrive: GET /files/{id}/revisions?pageSize=100
        GoogleDrive-->>Tool: Revision history (up to 100)
        Tool->>Tool: Attach revisions to metadata
    end
    Tool->>GoogleDrive: GET /files/{id}?alt=media
    GoogleDrive-->>Tool: File content
    Tool-->>User: {file: Buffer, metadata: GoogleDriveFile}
    
    Note over User,Storage: List Files Flow
    User->>Tool: list(folderId, query)
    Tool->>Tool: Escape query (backslash & quotes)
    Tool->>GoogleDrive: GET /files?fields=files(ALL_FILE_FIELDS)
    GoogleDrive-->>Tool: Array of complete metadata
    Tool-->>User: {files: GoogleDriveFile[]}
    
    Note over User,Storage: Create Folder Flow
    User->>Tool: create_folder(name, parentId)
    Tool->>GoogleDrive: POST /files (mimeType=folder)
    GoogleDrive-->>Tool: Basic folder response
    Tool->>GoogleDrive: GET /files/{id}?fields=ALL_FILE_FIELDS
    GoogleDrive-->>Tool: Complete folder metadata
    Tool-->>User: {file: GoogleDriveFile}
Loading

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

6 files reviewed, 6 comments

Edit Code Review Agent Settings | Greptile

Comment on lines 152 to 182
const includeRevisions = params?.includeRevisions !== false
if (includeRevisions) {
try {
const revisionsResponse = await fetch(
`https://www.googleapis.com/drive/v3/files/${fileId}/revisions?fields=revisions(${ALL_REVISION_FIELDS})&pageSize=100`,
{
headers: {
Authorization: authHeader,
},
}
)

if (revisionsResponse.ok) {
const revisionsData = await revisionsResponse.json()
metadata.revisions = revisionsData.revisions as GoogleDriveRevision[]
logger.info('Fetched file revisions', {
fileId,
revisionCount: metadata.revisions?.length || 0,
})
} else {
logger.warn('Failed to fetch revisions, continuing without them', {
status: revisionsResponse.status,
statusText: revisionsResponse.statusText,
})
}
} catch (revisionError: any) {
logger.warn('Error fetching revisions, continuing without them', {
error: revisionError.message,
})
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

revision history is fetched for all files without first checking if the user has permission to read revisions. The metadata already includes a capabilities.canReadRevisions field that indicates whether the current user can access revision history. Making unnecessary API calls when the user doesn't have permission wastes API quota and adds latency.

Consider checking the capability first:

Suggested change
const includeRevisions = params?.includeRevisions !== false
if (includeRevisions) {
try {
const revisionsResponse = await fetch(
`https://www.googleapis.com/drive/v3/files/${fileId}/revisions?fields=revisions(${ALL_REVISION_FIELDS})&pageSize=100`,
{
headers: {
Authorization: authHeader,
},
}
)
if (revisionsResponse.ok) {
const revisionsData = await revisionsResponse.json()
metadata.revisions = revisionsData.revisions as GoogleDriveRevision[]
logger.info('Fetched file revisions', {
fileId,
revisionCount: metadata.revisions?.length || 0,
})
} else {
logger.warn('Failed to fetch revisions, continuing without them', {
status: revisionsResponse.status,
statusText: revisionsResponse.statusText,
})
}
} catch (revisionError: any) {
logger.warn('Error fetching revisions, continuing without them', {
error: revisionError.message,
})
}
}
const includeRevisions = params?.includeRevisions !== false
if (includeRevisions && metadata.capabilities?.canReadRevisions) {
try {
const revisionsResponse = await fetch(
`https://www.googleapis.com/drive/v3/files/${fileId}/revisions?fields=revisions(${ALL_REVISION_FIELDS})&pageSize=100`,
{
headers: {
Authorization: authHeader,
},
}
)
if (revisionsResponse.ok) {
const revisionsData = await revisionsResponse.json()
metadata.revisions = revisionsData.revisions as GoogleDriveRevision[]
logger.info('Fetched file revisions', {
fileId,
revisionCount: metadata.revisions?.length || 0,
})
} else {
logger.warn('Failed to fetch revisions, continuing without them', {
status: revisionsResponse.status,
statusText: revisionsResponse.statusText,
})
}
} catch (revisionError: any) {
logger.warn('Error fetching revisions, continuing without them', {
error: revisionError.message,
})
}
}
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/sim/tools/google_drive/download.ts
Line: 152:182

Comment:
revision history is fetched for all files without first checking if the user has permission to read revisions. The metadata already includes a `capabilities.canReadRevisions` field that indicates whether the current user can access revision history. Making unnecessary API calls when the user doesn't have permission wastes API quota and adds latency.

Consider checking the capability first:

```suggestion
      const includeRevisions = params?.includeRevisions !== false
      if (includeRevisions && metadata.capabilities?.canReadRevisions) {
        try {
          const revisionsResponse = await fetch(
            `https://www.googleapis.com/drive/v3/files/${fileId}/revisions?fields=revisions(${ALL_REVISION_FIELDS})&pageSize=100`,
            {
              headers: {
                Authorization: authHeader,
              },
            }
          )

          if (revisionsResponse.ok) {
            const revisionsData = await revisionsResponse.json()
            metadata.revisions = revisionsData.revisions as GoogleDriveRevision[]
            logger.info('Fetched file revisions', {
              fileId,
              revisionCount: metadata.revisions?.length || 0,
            })
          } else {
            logger.warn('Failed to fetch revisions, continuing without them', {
              status: revisionsResponse.status,
              statusText: revisionsResponse.statusText,
            })
          }
        } catch (revisionError: any) {
          logger.warn('Error fetching revisions, continuing without them', {
            error: revisionError.message,
          })
        }
      }
```

How can I resolve this? If you propose a fix, please make it concise.

Comment on lines 140 to 170
const includeRevisions = params?.includeRevisions !== false
if (includeRevisions) {
try {
const revisionsResponse = await fetch(
`https://www.googleapis.com/drive/v3/files/${fileId}/revisions?fields=revisions(${ALL_REVISION_FIELDS})&pageSize=100`,
{
headers: {
Authorization: authHeader,
},
}
)

if (!metadataResponse.ok) {
logger.warn('Failed to get full metadata, using partial metadata', {
status: metadataResponse.status,
statusText: metadataResponse.statusText,
})
} else {
const fullMetadata = await metadataResponse.json()
Object.assign(metadata, fullMetadata)
if (revisionsResponse.ok) {
const revisionsData = await revisionsResponse.json()
metadata.revisions = revisionsData.revisions as GoogleDriveRevision[]
logger.info('Fetched file revisions', {
fileId,
revisionCount: metadata.revisions?.length || 0,
})
} else {
logger.warn('Failed to fetch revisions, continuing without them', {
status: revisionsResponse.status,
statusText: revisionsResponse.statusText,
})
}
} catch (revisionError: any) {
logger.warn('Error fetching revisions, continuing without them', {
error: revisionError.message,
})
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

revision history is fetched without checking the capabilities.canReadRevisions field first. This mirrors the same issue in download.ts - unnecessary API calls are made even when the user doesn't have permission to read revisions, wasting API quota and adding latency.

Consider checking the capability before fetching:

Suggested change
const includeRevisions = params?.includeRevisions !== false
if (includeRevisions) {
try {
const revisionsResponse = await fetch(
`https://www.googleapis.com/drive/v3/files/${fileId}/revisions?fields=revisions(${ALL_REVISION_FIELDS})&pageSize=100`,
{
headers: {
Authorization: authHeader,
},
}
)
if (!metadataResponse.ok) {
logger.warn('Failed to get full metadata, using partial metadata', {
status: metadataResponse.status,
statusText: metadataResponse.statusText,
})
} else {
const fullMetadata = await metadataResponse.json()
Object.assign(metadata, fullMetadata)
if (revisionsResponse.ok) {
const revisionsData = await revisionsResponse.json()
metadata.revisions = revisionsData.revisions as GoogleDriveRevision[]
logger.info('Fetched file revisions', {
fileId,
revisionCount: metadata.revisions?.length || 0,
})
} else {
logger.warn('Failed to fetch revisions, continuing without them', {
status: revisionsResponse.status,
statusText: revisionsResponse.statusText,
})
}
} catch (revisionError: any) {
logger.warn('Error fetching revisions, continuing without them', {
error: revisionError.message,
})
}
}
const includeRevisions = params?.includeRevisions !== false
if (includeRevisions && metadata.capabilities?.canReadRevisions) {
try {
const revisionsResponse = await fetch(
`https://www.googleapis.com/drive/v3/files/${fileId}/revisions?fields=revisions(${ALL_REVISION_FIELDS})&pageSize=100`,
{
headers: {
Authorization: authHeader,
},
}
)
if (revisionsResponse.ok) {
const revisionsData = await revisionsResponse.json()
metadata.revisions = revisionsData.revisions as GoogleDriveRevision[]
logger.info('Fetched file revisions', {
fileId,
revisionCount: metadata.revisions?.length || 0,
})
} else {
logger.warn('Failed to fetch revisions, continuing without them', {
status: revisionsResponse.status,
statusText: revisionsResponse.statusText,
})
}
} catch (revisionError: any) {
logger.warn('Error fetching revisions, continuing without them', {
error: revisionError.message,
})
}
}
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/sim/tools/google_drive/get_content.ts
Line: 140:170

Comment:
revision history is fetched without checking the `capabilities.canReadRevisions` field first. This mirrors the same issue in download.ts - unnecessary API calls are made even when the user doesn't have permission to read revisions, wasting API quota and adding latency.

Consider checking the capability before fetching:

```suggestion
      const includeRevisions = params?.includeRevisions !== false
      if (includeRevisions && metadata.capabilities?.canReadRevisions) {
        try {
          const revisionsResponse = await fetch(
            `https://www.googleapis.com/drive/v3/files/${fileId}/revisions?fields=revisions(${ALL_REVISION_FIELDS})&pageSize=100`,
            {
              headers: {
                Authorization: authHeader,
              },
            }
          )

          if (revisionsResponse.ok) {
            const revisionsData = await revisionsResponse.json()
            metadata.revisions = revisionsData.revisions as GoogleDriveRevision[]
            logger.info('Fetched file revisions', {
              fileId,
              revisionCount: metadata.revisions?.length || 0,
            })
          } else {
            logger.warn('Failed to fetch revisions, continuing without them', {
              status: revisionsResponse.status,
              statusText: revisionsResponse.statusText,
            })
          }
        } catch (revisionError: any) {
          logger.warn('Error fetching revisions, continuing without them', {
            error: revisionError.message,
          })
        }
      }
```

How can I resolve this? If you propose a fix, please make it concise.

@greptile-apps
Copy link
Contributor

greptile-apps bot commented Jan 9, 2026

Additional Comments (4)

apps/sim/tools/google_drive/list.ts
the user-provided query parameter is directly interpolated into the Google Drive query string without escaping single quotes. If a user inputs a search term containing a single quote (e.g., "John's file"), it will break the query syntax and cause the API call to fail. Additionally, this could allow users to inject additional query conditions.

The query should escape single quotes by doubling them (replacing ' with '') according to Google Drive API query syntax:

        const escapedQuery = params.query.replace(/'/g, "''")
        const queryPart = `name contains '${escapedQuery}'`
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/sim/tools/google_drive/list.ts
Line: 77:77

Comment:
the user-provided query parameter is directly interpolated into the Google Drive query string without escaping single quotes. If a user inputs a search term containing a single quote (e.g., "John's file"), it will break the query syntax and cause the API call to fail. Additionally, this could allow users to inject additional query conditions.

The query should escape single quotes by doubling them (replacing `'` with `''`) according to Google Drive API query syntax:

```suggestion
        const escapedQuery = params.query.replace(/'/g, "''")
        const queryPart = `name contains '${escapedQuery}'`
```

How can I resolve this? If you propose a fix, please make it concise.

apps/sim/tools/google_drive/list.ts
the folderId is directly interpolated into the query string without escaping. While folder IDs are typically safe since they come from Google Drive itself, if a malformed or malicious folderId is provided (e.g., containing single quotes), it will break the query syntax.

Consider escaping the folderId as well:

        const escapedFolderId = folderId.replace(/'/g, "''")
        conditions.push(`'${escapedFolderId}' in parents`)
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/sim/tools/google_drive/list.ts
Line: 69:69

Comment:
the folderId is directly interpolated into the query string without escaping. While folder IDs are typically safe since they come from Google Drive itself, if a malformed or malicious folderId is provided (e.g., containing single quotes), it will break the query syntax.

Consider escaping the folderId as well:

```suggestion
        const escapedFolderId = folderId.replace(/'/g, "''")
        conditions.push(`'${escapedFolderId}' in parents`)
```

How can I resolve this? If you propose a fix, please make it concise.

apps/sim/app/api/tools/google_drive/upload/route.ts
the API route fetches only basic metadata fields after upload, but the upload.ts tool now promises complete metadata with ALL_FILE_FIELDS in its output schema (lines 260-333). This creates an inconsistency where file uploads via the API route return limited fields while text uploads return complete metadata.

To maintain consistency with the PR's goal of adding "complete metadata", the API route should also use ALL_FILE_FIELDS:

    const finalFileResponse = await fetch(
      `https://www.googleapis.com/drive/v3/files/${fileId}?supportsAllDrives=true&fields=${ALL_FILE_FIELDS}`,
      {
        headers: {
          Authorization: `Bearer ${validatedData.accessToken}`,
        },
      }
    )

You'll need to import ALL_FILE_FIELDS at the top of the file from '@/tools/google_drive/utils'.

Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/sim/app/api/tools/google_drive/upload/route.ts
Line: 243:244

Comment:
the API route fetches only basic metadata fields after upload, but the upload.ts tool now promises complete metadata with ALL_FILE_FIELDS in its output schema (lines 260-333). This creates an inconsistency where file uploads via the API route return limited fields while text uploads return complete metadata.

To maintain consistency with the PR's goal of adding "complete metadata", the API route should also use ALL_FILE_FIELDS:

```suggestion
    const finalFileResponse = await fetch(
      `https://www.googleapis.com/drive/v3/files/${fileId}?supportsAllDrives=true&fields=${ALL_FILE_FIELDS}`,
      {
        headers: {
          Authorization: `Bearer ${validatedData.accessToken}`,
        },
      }
    )
```

You'll need to import ALL_FILE_FIELDS at the top of the file from '@/tools/google_drive/utils'.

How can I resolve this? If you propose a fix, please make it concise.

apps/sim/app/api/tools/google_drive/upload/route.ts
the response manually constructs a limited file object instead of returning the complete metadata fetched from the API. Since finalFile already contains all the metadata from the Google Drive API response (which now should include ALL_FILE_FIELDS after the previous comment is addressed), you should return it directly rather than manually selecting specific fields.

This ensures consistency and reduces maintenance burden:

    return NextResponse.json({
      success: true,
      output: {
        file: finalFile,
      },
    })

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/sim/app/api/tools/google_drive/upload/route.ts
Line: 260:275

Comment:
the response manually constructs a limited file object instead of returning the complete metadata fetched from the API. Since finalFile already contains all the metadata from the Google Drive API response (which now should include ALL_FILE_FIELDS after the previous comment is addressed), you should return it directly rather than manually selecting specific fields.

This ensures consistency and reduces maintenance burden:

```suggestion
    return NextResponse.json({
      success: true,
      output: {
        file: finalFile,
      },
    })
```

<sub>Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!</sub>

How can I resolve this? If you propose a fix, please make it concise.

@aadamgough
Copy link
Contributor Author

@greptile

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

5 files reviewed, 5 comments

Edit Code Review Agent Settings | Greptile

Comment on lines +156 to +171
const revisionsResponse = await fetch(
`https://www.googleapis.com/drive/v3/files/${fileId}/revisions?fields=revisions(${ALL_REVISION_FIELDS})&pageSize=100`,
{
headers: {
Authorization: authHeader,
},
}
)

if (revisionsResponse.ok) {
const revisionsData = await revisionsResponse.json()
metadata.revisions = revisionsData.revisions as GoogleDriveRevision[]
logger.info('Fetched file revisions', {
fileId,
revisionCount: metadata.revisions?.length || 0,
})
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the revision fetching logic only retrieves the first 100 revisions (pageSize=100) but does not handle pagination. If a file has more than 100 revisions, only the first 100 will be returned and subsequent revisions will be silently omitted without any indication to the user.

The Google Drive API returns a nextPageToken field when there are more results, but this code doesn't check for it or fetch additional pages.

Consider either:

  1. Documenting in the output schema that only the first 100 revisions are returned
  2. Implementing pagination to fetch all revisions
  3. Making the pageSize configurable via a parameter
  4. Logging a warning when there are more revisions available

Note: The same issue exists in get_content.ts at line 145.

Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/sim/tools/google_drive/download.ts
Line: 156:171

Comment:
the revision fetching logic only retrieves the first 100 revisions (pageSize=100) but does not handle pagination. If a file has more than 100 revisions, only the first 100 will be returned and subsequent revisions will be silently omitted without any indication to the user.

The Google Drive API returns a `nextPageToken` field when there are more results, but this code doesn't check for it or fetch additional pages.

Consider either:
1. Documenting in the output schema that only the first 100 revisions are returned
2. Implementing pagination to fetch all revisions
3. Making the pageSize configurable via a parameter
4. Logging a warning when there are more revisions available

Note: The same issue exists in `get_content.ts` at line 145.

How can I resolve this? If you propose a fix, please make it concise.

Comment on lines +144 to +159
const revisionsResponse = await fetch(
`https://www.googleapis.com/drive/v3/files/${fileId}/revisions?fields=revisions(${ALL_REVISION_FIELDS})&pageSize=100`,
{
headers: {
Authorization: authHeader,
},
}
)

if (!metadataResponse.ok) {
logger.warn('Failed to get full metadata, using partial metadata', {
status: metadataResponse.status,
statusText: metadataResponse.statusText,
if (revisionsResponse.ok) {
const revisionsData = await revisionsResponse.json()
metadata.revisions = revisionsData.revisions as GoogleDriveRevision[]
logger.info('Fetched file revisions', {
fileId,
revisionCount: metadata.revisions?.length || 0,
})
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the revision fetching logic only retrieves the first 100 revisions (pageSize=100) but does not handle pagination. If a file has more than 100 revisions, only the first 100 will be returned and subsequent revisions will be silently omitted without any indication to the user.

The Google Drive API returns a nextPageToken field when there are more results, but this code doesn't check for it or fetch additional pages.

Consider either:

  1. Documenting in the output schema that only the first 100 revisions are returned
  2. Implementing pagination to fetch all revisions
  3. Making the pageSize configurable via a parameter
  4. Logging a warning when there are more revisions available

Note: The same issue exists in download.ts at line 157.

Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/sim/tools/google_drive/get_content.ts
Line: 144:159

Comment:
the revision fetching logic only retrieves the first 100 revisions (pageSize=100) but does not handle pagination. If a file has more than 100 revisions, only the first 100 will be returned and subsequent revisions will be silently omitted without any indication to the user.

The Google Drive API returns a `nextPageToken` field when there are more results, but this code doesn't check for it or fetch additional pages.

Consider either:
1. Documenting in the output schema that only the first 100 revisions are returned
2. Implementing pagination to fetch all revisions
3. Making the pageSize configurable via a parameter
4. Logging a warning when there are more revisions available

Note: The same issue exists in `download.ts` at line 157.

How can I resolve this? If you propose a fix, please make it concise.

Comment on lines 223 to 234
file: {
type: 'object',
description: 'Downloaded file stored in execution files',
properties: {
id: { type: 'string', description: 'Unique file identifier' },
name: { type: 'string', description: 'File name' },
size: { type: 'number', description: 'File size in bytes' },
type: { type: 'string', description: 'MIME type of the file' },
url: { type: 'string', description: 'Signed URL to access the file' },
key: { type: 'string', description: 'Storage key for the file' },
context: { type: 'string', description: 'Context where file is stored' },
},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the output schema for the file field does not match what is actually returned by the code.

The schema promises these properties:

  • id, name, size, type, url, key, context

But the actual return value (lines 204-209) only contains:

  • name, mimeType, data, size

The schema is missing the data property (which contains the actual Buffer) and includes properties (id, url, key, context) that are never set. The schema also uses type instead of mimeType.

This mismatch could cause issues for consumers relying on the schema definition.

Suggested change
file: {
type: 'object',
description: 'Downloaded file stored in execution files',
properties: {
id: { type: 'string', description: 'Unique file identifier' },
name: { type: 'string', description: 'File name' },
size: { type: 'number', description: 'File size in bytes' },
type: { type: 'string', description: 'MIME type of the file' },
url: { type: 'string', description: 'Signed URL to access the file' },
key: { type: 'string', description: 'Storage key for the file' },
context: { type: 'string', description: 'Context where file is stored' },
},
file: {
type: 'object',
description: 'Downloaded file stored in execution files',
properties: {
name: { type: 'string', description: 'File name' },
mimeType: { type: 'string', description: 'MIME type of the file' },
data: { type: 'buffer', description: 'File content as Buffer' },
size: { type: 'number', description: 'File size in bytes' },
},
},
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/sim/tools/google_drive/download.ts
Line: 223:234

Comment:
the output schema for the `file` field does not match what is actually returned by the code. 

The schema promises these properties:
- `id`, `name`, `size`, `type`, `url`, `key`, `context`

But the actual return value (lines 204-209) only contains:
- `name`, `mimeType`, `data`, `size`

The schema is missing the `data` property (which contains the actual Buffer) and includes properties (`id`, `url`, `key`, `context`) that are never set. The schema also uses `type` instead of `mimeType`.

This mismatch could cause issues for consumers relying on the schema definition.

```suggestion
    file: {
      type: 'object',
      description: 'Downloaded file stored in execution files',
      properties: {
        name: { type: 'string', description: 'File name' },
        mimeType: { type: 'string', description: 'MIME type of the file' },
        data: { type: 'buffer', description: 'File content as Buffer' },
        size: { type: 'number', description: 'File size in bytes' },
      },
    },
```

How can I resolve this? If you propose a fix, please make it concise.

@greptile-apps
Copy link
Contributor

greptile-apps bot commented Jan 10, 2026

Additional Comments (2)

apps/sim/app/api/tools/google_drive/upload/route.ts
the API route only fetches a limited subset of metadata fields (id,name,mimeType,webViewLink,webContentLink,size,createdTime,modifiedTime,parents), but the upload tool promises "complete metadata" in its description and output schema. This creates an inconsistency where file uploads via the API route return less metadata than text-only uploads (which fetch ALL_FILE_FIELDS).

The limited metadata returned here lacks important fields like:

  • owners, permissions, capabilities
  • starred, trashed, shared
  • Checksums (md5Checksum, sha1Checksum, sha256Checksum)
  • Media metadata (imageMediaMetadata, videoMediaMetadata)
  • And 30+ other fields defined in the output schema

This breaks the consistency of the API's metadata promise and could cause downstream issues if consumers expect complete metadata.

    const finalFileResponse = await fetch(
      `https://www.googleapis.com/drive/v3/files/${fileId}?supportsAllDrives=true&fields=${ALL_FILE_FIELDS}`,
      {

Note: You'll need to import ALL_FILE_FIELDS from @/tools/google_drive/utils at the top of the file.

Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/sim/app/api/tools/google_drive/upload/route.ts
Line: 243:244

Comment:
the API route only fetches a limited subset of metadata fields (`id,name,mimeType,webViewLink,webContentLink,size,createdTime,modifiedTime,parents`), but the upload tool promises "complete metadata" in its description and output schema. This creates an inconsistency where file uploads via the API route return less metadata than text-only uploads (which fetch `ALL_FILE_FIELDS`).

The limited metadata returned here lacks important fields like:
- `owners`, `permissions`, `capabilities`
- `starred`, `trashed`, `shared`
- Checksums (`md5Checksum`, `sha1Checksum`, `sha256Checksum`)
- Media metadata (`imageMediaMetadata`, `videoMediaMetadata`)
- And 30+ other fields defined in the output schema

This breaks the consistency of the API's metadata promise and could cause downstream issues if consumers expect complete metadata.

```suggestion
    const finalFileResponse = await fetch(
      `https://www.googleapis.com/drive/v3/files/${fileId}?supportsAllDrives=true&fields=${ALL_FILE_FIELDS}`,
      {
```

Note: You'll need to import `ALL_FILE_FIELDS` from `@/tools/google_drive/utils` at the top of the file.

How can I resolve this? If you propose a fix, please make it concise.

apps/sim/tools/google_drive/create_folder.ts
the code doesn't check if parentFolderId is an empty or whitespace-only string before adding it to the metadata. This is inconsistent with upload.ts which does parentFolderId.trim() !== '' check (line 112).

If a user provides a whitespace-only string as the folder ID, this will send an invalid parent folder ID to the Google Drive API, which could cause the API call to fail with an unclear error message.

      const parentFolderId = params.folderSelector || params.folderId
      if (parentFolderId && parentFolderId.trim() !== '') {
        metadata.parents = [parentFolderId]
      }
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/sim/tools/google_drive/create_folder.ts
Line: 64:66

Comment:
the code doesn't check if `parentFolderId` is an empty or whitespace-only string before adding it to the metadata. This is inconsistent with `upload.ts` which does `parentFolderId.trim() !== ''` check (line 112).

If a user provides a whitespace-only string as the folder ID, this will send an invalid parent folder ID to the Google Drive API, which could cause the API call to fail with an unclear error message.

```suggestion
      const parentFolderId = params.folderSelector || params.folderId
      if (parentFolderId && parentFolderId.trim() !== '') {
        metadata.parents = [parentFolderId]
      }
```

How can I resolve this? If you propose a fix, please make it concise.

@aadamgough aadamgough merged commit 796f73e into staging Jan 10, 2026
10 checks passed
@aadamgough aadamgough deleted the improvement/google-drive branch January 10, 2026 00:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants