Skip to content

Commit 683b447

Browse files
aadamgoughaadamgough
andauthored
fix(google-drive): added support for shared drive (#2232)
* added param for shared drive * removed comments --------- Co-authored-by: aadamgough <adam@sim.ai>
1 parent ae79372 commit 683b447

File tree

7 files changed

+114
-17
lines changed

7 files changed

+114
-17
lines changed

apps/sim/app/api/tools/drive/file/route.ts

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,35 @@ export async function GET(request: NextRequest) {
5757
}
5858
)
5959

60+
if (!response.ok && response.status === 404) {
61+
logger.info(`[${requestId}] File not found, checking if it's a shared drive`)
62+
const driveResponse = await fetch(
63+
`https://www.googleapis.com/drive/v3/drives/${fileId}?fields=id,name`,
64+
{
65+
headers: {
66+
Authorization: `Bearer ${accessToken}`,
67+
},
68+
}
69+
)
70+
71+
if (driveResponse.ok) {
72+
const driveData = await driveResponse.json()
73+
logger.info(`[${requestId}] Found shared drive: ${driveData.name}`)
74+
return NextResponse.json(
75+
{
76+
file: {
77+
id: driveData.id,
78+
name: driveData.name,
79+
mimeType: 'application/vnd.google-apps.folder',
80+
iconLink:
81+
'https://ssl.gstatic.com/docs/doclist/images/icon_11_shared_collection_list_1.png',
82+
},
83+
},
84+
{ status: 200 }
85+
)
86+
}
87+
}
88+
6089
if (!response.ok) {
6190
const errorData = await response.json().catch(() => ({ error: { message: 'Unknown error' } }))
6291
logger.error(`[${requestId}] Google Drive API error`, {
@@ -112,12 +141,12 @@ export async function GET(request: NextRequest) {
112141
if (!file.exportLinks) {
113142
file.downloadUrl = `https://www.googleapis.com/drive/v3/files/${file.id}/export?mimeType=${encodeURIComponent(
114143
format
115-
)}`
144+
)}&supportsAllDrives=true`
116145
} else {
117146
file.downloadUrl = file.exportLinks[format]
118147
}
119148
} else {
120-
file.downloadUrl = `https://www.googleapis.com/drive/v3/files/${file.id}?alt=media`
149+
file.downloadUrl = `https://www.googleapis.com/drive/v3/files/${file.id}?alt=media&supportsAllDrives=true`
121150
}
122151

123152
return NextResponse.json({ file }, { status: 200 })

apps/sim/app/api/tools/drive/files/route.ts

Lines changed: 72 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,62 @@ function escapeForDriveQuery(value: string): string {
1212
return value.replace(/\\/g, '\\\\').replace(/'/g, "\\'")
1313
}
1414

15+
interface SharedDrive {
16+
id: string
17+
name: string
18+
kind: string
19+
}
20+
21+
interface DriveFile {
22+
id: string
23+
name: string
24+
mimeType: string
25+
iconLink?: string
26+
webViewLink?: string
27+
thumbnailLink?: string
28+
createdTime?: string
29+
modifiedTime?: string
30+
size?: string
31+
owners?: any[]
32+
parents?: string[]
33+
}
34+
35+
/**
36+
* Fetches shared drives the user has access to
37+
*/
38+
async function fetchSharedDrives(accessToken: string, requestId: string): Promise<DriveFile[]> {
39+
try {
40+
const response = await fetch(
41+
'https://www.googleapis.com/drive/v3/drives?pageSize=100&fields=drives(id,name)',
42+
{
43+
headers: {
44+
Authorization: `Bearer ${accessToken}`,
45+
},
46+
}
47+
)
48+
49+
if (!response.ok) {
50+
logger.warn(`[${requestId}] Failed to fetch shared drives`, {
51+
status: response.status,
52+
})
53+
return []
54+
}
55+
56+
const data = await response.json()
57+
const drives: SharedDrive[] = data.drives || []
58+
59+
return drives.map((drive) => ({
60+
id: drive.id,
61+
name: drive.name,
62+
mimeType: 'application/vnd.google-apps.folder',
63+
iconLink: 'https://ssl.gstatic.com/docs/doclist/images/icon_11_shared_collection_list_1.png',
64+
}))
65+
} catch (error) {
66+
logger.error(`[${requestId}] Error fetching shared drives`, error)
67+
return []
68+
}
69+
}
70+
1571
export async function GET(request: NextRequest) {
1672
const requestId = generateRequestId()
1773
logger.info(`[${requestId}] Google Drive files request received`)
@@ -65,7 +121,7 @@ export async function GET(request: NextRequest) {
65121
const q = encodeURIComponent(qParts.join(' and '))
66122

67123
const response = await fetch(
68-
`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)`,
124+
`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)`,
69125
{
70126
headers: {
71127
Authorization: `Bearer ${accessToken}`,
@@ -88,14 +144,26 @@ export async function GET(request: NextRequest) {
88144
}
89145

90146
const data = await response.json()
91-
let files = data.files || []
147+
let files: DriveFile[] = data.files || []
92148

93149
if (mimeType === 'application/vnd.google-apps.spreadsheet') {
94150
files = files.filter(
95-
(file: any) => file.mimeType === 'application/vnd.google-apps.spreadsheet'
151+
(file: DriveFile) => file.mimeType === 'application/vnd.google-apps.spreadsheet'
96152
)
97153
} else if (mimeType === 'application/vnd.google-apps.document') {
98-
files = files.filter((file: any) => file.mimeType === 'application/vnd.google-apps.document')
154+
files = files.filter(
155+
(file: DriveFile) => file.mimeType === 'application/vnd.google-apps.document'
156+
)
157+
}
158+
159+
const isRootFolderListing =
160+
!folderId && mimeType === 'application/vnd.google-apps.folder' && !query
161+
if (isRootFolderListing) {
162+
const sharedDrives = await fetchSharedDrives(accessToken, requestId)
163+
if (sharedDrives.length > 0) {
164+
logger.info(`[${requestId}] Found ${sharedDrives.length} shared drives`)
165+
files = [...sharedDrives, ...files]
166+
}
99167
}
100168

101169
return NextResponse.json({ files }, { status: 200 })

apps/sim/tools/google_docs/create.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ export const createTool: ToolConfig<GoogleDocsToolParams, GoogleDocsCreateRespon
5050

5151
request: {
5252
url: () => {
53-
return 'https://www.googleapis.com/drive/v3/files'
53+
return 'https://www.googleapis.com/drive/v3/files?supportsAllDrives=true'
5454
},
5555
method: 'POST',
5656
headers: (params) => {

apps/sim/tools/google_drive/download.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ export const downloadTool: ToolConfig<GoogleDriveToolParams, GoogleDriveDownload
4545

4646
request: {
4747
url: (params) =>
48-
`https://www.googleapis.com/drive/v3/files/${params.fileId}?fields=id,name,mimeType`,
48+
`https://www.googleapis.com/drive/v3/files/${params.fileId}?fields=id,name,mimeType&supportsAllDrives=true`,
4949
method: 'GET',
5050
headers: (params) => ({
5151
Authorization: `Bearer ${params.accessToken}`,
@@ -83,7 +83,7 @@ export const downloadTool: ToolConfig<GoogleDriveToolParams, GoogleDriveDownload
8383
})
8484

8585
const exportResponse = await fetch(
86-
`https://www.googleapis.com/drive/v3/files/${fileId}/export?mimeType=${encodeURIComponent(exportFormat)}`,
86+
`https://www.googleapis.com/drive/v3/files/${fileId}/export?mimeType=${encodeURIComponent(exportFormat)}&supportsAllDrives=true`,
8787
{
8888
headers: {
8989
Authorization: authHeader,
@@ -110,7 +110,7 @@ export const downloadTool: ToolConfig<GoogleDriveToolParams, GoogleDriveDownload
110110
})
111111

112112
const downloadResponse = await fetch(
113-
`https://www.googleapis.com/drive/v3/files/${fileId}?alt=media`,
113+
`https://www.googleapis.com/drive/v3/files/${fileId}?alt=media&supportsAllDrives=true`,
114114
{
115115
headers: {
116116
Authorization: authHeader,

apps/sim/tools/google_drive/get_content.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ export const getContentTool: ToolConfig<GoogleDriveToolParams, GoogleDriveGetCon
4343

4444
request: {
4545
url: (params) =>
46-
`https://www.googleapis.com/drive/v3/files/${params.fileId}?fields=id,name,mimeType`,
46+
`https://www.googleapis.com/drive/v3/files/${params.fileId}?fields=id,name,mimeType&supportsAllDrives=true`,
4747
method: 'GET',
4848
headers: (params) => ({
4949
Authorization: `Bearer ${params.accessToken}`,
@@ -77,7 +77,7 @@ export const getContentTool: ToolConfig<GoogleDriveToolParams, GoogleDriveGetCon
7777
})
7878

7979
const exportResponse = await fetch(
80-
`https://www.googleapis.com/drive/v3/files/${fileId}/export?mimeType=${encodeURIComponent(exportFormat)}`,
80+
`https://www.googleapis.com/drive/v3/files/${fileId}/export?mimeType=${encodeURIComponent(exportFormat)}&supportsAllDrives=true`,
8181
{
8282
headers: {
8383
Authorization: authHeader,
@@ -103,7 +103,7 @@ export const getContentTool: ToolConfig<GoogleDriveToolParams, GoogleDriveGetCon
103103
})
104104

105105
const downloadResponse = await fetch(
106-
`https://www.googleapis.com/drive/v3/files/${fileId}?alt=media`,
106+
`https://www.googleapis.com/drive/v3/files/${fileId}?alt=media&supportsAllDrives=true`,
107107
{
108108
headers: {
109109
Authorization: authHeader,
@@ -125,7 +125,7 @@ export const getContentTool: ToolConfig<GoogleDriveToolParams, GoogleDriveGetCon
125125
}
126126

127127
const metadataResponse = await fetch(
128-
`https://www.googleapis.com/drive/v3/files/${fileId}?fields=id,name,mimeType,webViewLink,webContentLink,size,createdTime,modifiedTime,parents`,
128+
`https://www.googleapis.com/drive/v3/files/${fileId}?fields=id,name,mimeType,webViewLink,webContentLink,size,createdTime,modifiedTime,parents&supportsAllDrives=true`,
129129
{
130130
headers: {
131131
Authorization: authHeader,

apps/sim/tools/google_drive/list.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,10 +59,10 @@ export const listTool: ToolConfig<GoogleDriveToolParams, GoogleDriveListResponse
5959
'fields',
6060
'files(id,name,mimeType,webViewLink,webContentLink,size,createdTime,modifiedTime,parents),nextPageToken'
6161
)
62-
// Ensure shared drives support
62+
// Ensure shared drives support - corpora=allDrives is critical for searching across shared drives
63+
url.searchParams.append('corpora', 'allDrives')
6364
url.searchParams.append('supportsAllDrives', 'true')
6465
url.searchParams.append('includeItemsFromAllDrives', 'true')
65-
url.searchParams.append('spaces', 'drive')
6666

6767
// Build the query conditions
6868
const conditions = ['trashed = false'] // Always exclude trashed files

apps/sim/tools/google_slides/create.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ export const createTool: ToolConfig<GoogleSlidesToolParams, GoogleSlidesCreateRe
5353

5454
request: {
5555
url: () => {
56-
return 'https://www.googleapis.com/drive/v3/files'
56+
return 'https://www.googleapis.com/drive/v3/files?supportsAllDrives=true'
5757
},
5858
method: 'POST',
5959
headers: (params) => {

0 commit comments

Comments
 (0)