fix(google-drive): added support for shared drive (#2232)

* added param for shared drive

* removed comments

---------

Co-authored-by: aadamgough <adam@sim.ai>
This commit is contained in:
Adam Gough
2025-12-06 17:37:02 -08:00
committed by GitHub
parent ae7937280e
commit 683b4476fa
7 changed files with 114 additions and 17 deletions

View File

@@ -57,6 +57,35 @@ export async function GET(request: NextRequest) {
}
)
if (!response.ok && response.status === 404) {
logger.info(`[${requestId}] File not found, checking if it's a shared drive`)
const driveResponse = await fetch(
`https://www.googleapis.com/drive/v3/drives/${fileId}?fields=id,name`,
{
headers: {
Authorization: `Bearer ${accessToken}`,
},
}
)
if (driveResponse.ok) {
const driveData = await driveResponse.json()
logger.info(`[${requestId}] Found shared drive: ${driveData.name}`)
return NextResponse.json(
{
file: {
id: driveData.id,
name: driveData.name,
mimeType: 'application/vnd.google-apps.folder',
iconLink:
'https://ssl.gstatic.com/docs/doclist/images/icon_11_shared_collection_list_1.png',
},
},
{ status: 200 }
)
}
}
if (!response.ok) {
const errorData = await response.json().catch(() => ({ error: { message: 'Unknown error' } }))
logger.error(`[${requestId}] Google Drive API error`, {
@@ -112,12 +141,12 @@ export async function GET(request: NextRequest) {
if (!file.exportLinks) {
file.downloadUrl = `https://www.googleapis.com/drive/v3/files/${file.id}/export?mimeType=${encodeURIComponent(
format
)}`
)}&supportsAllDrives=true`
} else {
file.downloadUrl = file.exportLinks[format]
}
} else {
file.downloadUrl = `https://www.googleapis.com/drive/v3/files/${file.id}?alt=media`
file.downloadUrl = `https://www.googleapis.com/drive/v3/files/${file.id}?alt=media&supportsAllDrives=true`
}
return NextResponse.json({ file }, { status: 200 })

View File

@@ -12,6 +12,62 @@ function escapeForDriveQuery(value: string): string {
return value.replace(/\\/g, '\\\\').replace(/'/g, "\\'")
}
interface SharedDrive {
id: string
name: string
kind: string
}
interface DriveFile {
id: string
name: string
mimeType: string
iconLink?: string
webViewLink?: string
thumbnailLink?: string
createdTime?: string
modifiedTime?: string
size?: string
owners?: any[]
parents?: string[]
}
/**
* Fetches shared drives the user has access to
*/
async function fetchSharedDrives(accessToken: string, requestId: string): Promise<DriveFile[]> {
try {
const response = await fetch(
'https://www.googleapis.com/drive/v3/drives?pageSize=100&fields=drives(id,name)',
{
headers: {
Authorization: `Bearer ${accessToken}`,
},
}
)
if (!response.ok) {
logger.warn(`[${requestId}] Failed to fetch shared drives`, {
status: response.status,
})
return []
}
const data = await response.json()
const drives: SharedDrive[] = data.drives || []
return drives.map((drive) => ({
id: drive.id,
name: drive.name,
mimeType: 'application/vnd.google-apps.folder',
iconLink: 'https://ssl.gstatic.com/docs/doclist/images/icon_11_shared_collection_list_1.png',
}))
} catch (error) {
logger.error(`[${requestId}] Error fetching shared drives`, error)
return []
}
}
export async function GET(request: NextRequest) {
const requestId = generateRequestId()
logger.info(`[${requestId}] Google Drive files request received`)
@@ -65,7 +121,7 @@ export async function GET(request: NextRequest) {
const q = encodeURIComponent(qParts.join(' and '))
const response = await fetch(
`https://www.googleapis.com/drive/v3/files?q=${q}&supportsAllDrives=true&includeItemsFromAllDrives=true&spaces=drive&fields=files(id,name,mimeType,iconLink,webViewLink,thumbnailLink,createdTime,modifiedTime,size,owners,parents)`,
`https://www.googleapis.com/drive/v3/files?q=${q}&corpora=allDrives&supportsAllDrives=true&includeItemsFromAllDrives=true&fields=files(id,name,mimeType,iconLink,webViewLink,thumbnailLink,createdTime,modifiedTime,size,owners,parents)`,
{
headers: {
Authorization: `Bearer ${accessToken}`,
@@ -88,14 +144,26 @@ export async function GET(request: NextRequest) {
}
const data = await response.json()
let files = data.files || []
let files: DriveFile[] = data.files || []
if (mimeType === 'application/vnd.google-apps.spreadsheet') {
files = files.filter(
(file: any) => file.mimeType === 'application/vnd.google-apps.spreadsheet'
(file: DriveFile) => 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')
files = files.filter(
(file: DriveFile) => file.mimeType === 'application/vnd.google-apps.document'
)
}
const isRootFolderListing =
!folderId && mimeType === 'application/vnd.google-apps.folder' && !query
if (isRootFolderListing) {
const sharedDrives = await fetchSharedDrives(accessToken, requestId)
if (sharedDrives.length > 0) {
logger.info(`[${requestId}] Found ${sharedDrives.length} shared drives`)
files = [...sharedDrives, ...files]
}
}
return NextResponse.json({ files }, { status: 200 })

View File

@@ -50,7 +50,7 @@ export const createTool: ToolConfig<GoogleDocsToolParams, GoogleDocsCreateRespon
request: {
url: () => {
return 'https://www.googleapis.com/drive/v3/files'
return 'https://www.googleapis.com/drive/v3/files?supportsAllDrives=true'
},
method: 'POST',
headers: (params) => {

View File

@@ -45,7 +45,7 @@ export const downloadTool: ToolConfig<GoogleDriveToolParams, GoogleDriveDownload
request: {
url: (params) =>
`https://www.googleapis.com/drive/v3/files/${params.fileId}?fields=id,name,mimeType`,
`https://www.googleapis.com/drive/v3/files/${params.fileId}?fields=id,name,mimeType&supportsAllDrives=true`,
method: 'GET',
headers: (params) => ({
Authorization: `Bearer ${params.accessToken}`,
@@ -83,7 +83,7 @@ export const downloadTool: ToolConfig<GoogleDriveToolParams, GoogleDriveDownload
})
const exportResponse = await fetch(
`https://www.googleapis.com/drive/v3/files/${fileId}/export?mimeType=${encodeURIComponent(exportFormat)}`,
`https://www.googleapis.com/drive/v3/files/${fileId}/export?mimeType=${encodeURIComponent(exportFormat)}&supportsAllDrives=true`,
{
headers: {
Authorization: authHeader,
@@ -110,7 +110,7 @@ export const downloadTool: ToolConfig<GoogleDriveToolParams, GoogleDriveDownload
})
const downloadResponse = await fetch(
`https://www.googleapis.com/drive/v3/files/${fileId}?alt=media`,
`https://www.googleapis.com/drive/v3/files/${fileId}?alt=media&supportsAllDrives=true`,
{
headers: {
Authorization: authHeader,

View File

@@ -43,7 +43,7 @@ export const getContentTool: ToolConfig<GoogleDriveToolParams, GoogleDriveGetCon
request: {
url: (params) =>
`https://www.googleapis.com/drive/v3/files/${params.fileId}?fields=id,name,mimeType`,
`https://www.googleapis.com/drive/v3/files/${params.fileId}?fields=id,name,mimeType&supportsAllDrives=true`,
method: 'GET',
headers: (params) => ({
Authorization: `Bearer ${params.accessToken}`,
@@ -77,7 +77,7 @@ export const getContentTool: ToolConfig<GoogleDriveToolParams, GoogleDriveGetCon
})
const exportResponse = await fetch(
`https://www.googleapis.com/drive/v3/files/${fileId}/export?mimeType=${encodeURIComponent(exportFormat)}`,
`https://www.googleapis.com/drive/v3/files/${fileId}/export?mimeType=${encodeURIComponent(exportFormat)}&supportsAllDrives=true`,
{
headers: {
Authorization: authHeader,
@@ -103,7 +103,7 @@ export const getContentTool: ToolConfig<GoogleDriveToolParams, GoogleDriveGetCon
})
const downloadResponse = await fetch(
`https://www.googleapis.com/drive/v3/files/${fileId}?alt=media`,
`https://www.googleapis.com/drive/v3/files/${fileId}?alt=media&supportsAllDrives=true`,
{
headers: {
Authorization: authHeader,
@@ -125,7 +125,7 @@ export const getContentTool: ToolConfig<GoogleDriveToolParams, GoogleDriveGetCon
}
const metadataResponse = await fetch(
`https://www.googleapis.com/drive/v3/files/${fileId}?fields=id,name,mimeType,webViewLink,webContentLink,size,createdTime,modifiedTime,parents`,
`https://www.googleapis.com/drive/v3/files/${fileId}?fields=id,name,mimeType,webViewLink,webContentLink,size,createdTime,modifiedTime,parents&supportsAllDrives=true`,
{
headers: {
Authorization: authHeader,

View File

@@ -59,10 +59,10 @@ export const listTool: ToolConfig<GoogleDriveToolParams, GoogleDriveListResponse
'fields',
'files(id,name,mimeType,webViewLink,webContentLink,size,createdTime,modifiedTime,parents),nextPageToken'
)
// Ensure shared drives support
// Ensure shared drives support - corpora=allDrives is critical for searching across shared drives
url.searchParams.append('corpora', 'allDrives')
url.searchParams.append('supportsAllDrives', 'true')
url.searchParams.append('includeItemsFromAllDrives', 'true')
url.searchParams.append('spaces', 'drive')
// Build the query conditions
const conditions = ['trashed = false'] // Always exclude trashed files

View File

@@ -53,7 +53,7 @@ export const createTool: ToolConfig<GoogleSlidesToolParams, GoogleSlidesCreateRe
request: {
url: () => {
return 'https://www.googleapis.com/drive/v3/files'
return 'https://www.googleapis.com/drive/v3/files?supportsAllDrives=true'
},
method: 'POST',
headers: (params) => {