From f03acd4a4156b98993d9366996244eb49e69c006 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Mon, 9 Feb 2026 21:30:54 +0000 Subject: [PATCH 1/3] fix: support Google Shared Drives and improve file ID extraction - Added `supportsAllDrives: true` and `includeItemsFromAllDrives: true` to Drive API calls in `DriveService`, `DocsService`, `SheetsService`, and `SlidesService`. - Improved `drive.downloadFile` to robustly handle full Drive URLs by extracting the file ID using `extractDocumentId`. - Updated unit tests to verify Shared Drive support and URL handling. Co-authored-by: raybell-md <196701227+raybell-md@users.noreply.github.com> --- .../__tests__/services/DocsService.test.ts | 16 ++++++- .../__tests__/services/DriveService.test.ts | 44 +++++++++++++++++++ .../__tests__/services/SheetsService.test.ts | 2 + .../__tests__/services/SlidesService.test.ts | 2 + workspace-server/src/services/DocsService.ts | 5 +++ workspace-server/src/services/DriveService.ts | 8 ++-- .../src/services/SheetsService.ts | 2 + .../src/services/SlidesService.ts | 2 + 8 files changed, 77 insertions(+), 4 deletions(-) diff --git a/workspace-server/src/__tests__/services/DocsService.test.ts b/workspace-server/src/__tests__/services/DocsService.test.ts index b33553ac..b7c9d7ae 100644 --- a/workspace-server/src/__tests__/services/DocsService.test.ts +++ b/workspace-server/src/__tests__/services/DocsService.test.ts @@ -117,7 +117,12 @@ describe('DocsService', () => { markdown: '# Hello', }); - expect(mockDriveAPI.files.create).toHaveBeenCalled(); + expect(mockDriveAPI.files.create).toHaveBeenCalledWith( + expect.objectContaining({ + supportsAllDrives: true, + }), + expect.any(Object), + ); expect(JSON.parse(result.content[0].text)).toEqual({ documentId: 'test-doc-id', title: 'Test Title', @@ -157,6 +162,7 @@ describe('DocsService', () => { addParents: 'test-folder-id', removeParents: 'root', fields: 'id, parents', + supportsAllDrives: true, }); }); @@ -269,6 +275,8 @@ describe('DocsService', () => { expect(mockDriveAPI.files.list).toHaveBeenCalledWith( expect.objectContaining({ q: expect.stringContaining("fullText contains 'Test'"), + supportsAllDrives: true, + includeItemsFromAllDrives: true, }), ); expect(JSON.parse(result.content[0].text)).toEqual({ @@ -336,11 +344,17 @@ describe('DocsService', () => { expect(mockDriveService.findFolder).toHaveBeenCalledWith({ folderName: 'Test Folder', }); + expect(mockDriveAPI.files.get).toHaveBeenCalledWith( + expect.objectContaining({ + supportsAllDrives: true, + }), + ); expect(mockDriveAPI.files.update).toHaveBeenCalledWith({ fileId: 'test-doc-id', addParents: 'test-folder-id', removeParents: 'root', fields: 'id, parents', + supportsAllDrives: true, }); expect(result.content[0].text).toBe( 'Moved document test-doc-id to folder Test Folder', diff --git a/workspace-server/src/__tests__/services/DriveService.test.ts b/workspace-server/src/__tests__/services/DriveService.test.ts index bdc4c233..2e0a9413 100644 --- a/workspace-server/src/__tests__/services/DriveService.test.ts +++ b/workspace-server/src/__tests__/services/DriveService.test.ts @@ -884,6 +884,50 @@ describe('DriveService', () => { ); }); + it('should download files when provided with a full Drive URL', async () => { + const mockFileId = 'file-id-from-url'; + const mockUrl = `https://drive.google.com/file/d/${mockFileId}/view`; + const mockContent = 'Hello, World!'; + const mockBuffer = Buffer.from(mockContent); + const mockLocalPath = 'downloads/test.txt'; + + mockDriveAPI.files.get.mockImplementation((params: any) => { + if (params.alt === 'media') { + return Promise.resolve({ + data: mockBuffer, + }); + } + return Promise.resolve({ + data: { id: mockFileId, name: 'test.txt', mimeType: 'text/plain' }, + }); + }); + + const result = await driveService.downloadFile({ + fileId: mockUrl, + localPath: mockLocalPath, + }); + + expect(mockDriveAPI.files.get).toHaveBeenCalledWith( + expect.objectContaining({ + fileId: mockFileId, + supportsAllDrives: true, + }), + ); + + expect(mockDriveAPI.files.get).toHaveBeenCalledWith( + expect.objectContaining({ + fileId: mockFileId, + alt: 'media', + supportsAllDrives: true, + }), + expect.any(Object), + ); + + expect(result.content[0].text).toContain( + `Successfully downloaded file test.txt`, + ); + }); + it('should suggest specialized tools for workspace types', async () => { const mockFileId = 'doc-id'; mockDriveAPI.files.get.mockResolvedValue({ diff --git a/workspace-server/src/__tests__/services/SheetsService.test.ts b/workspace-server/src/__tests__/services/SheetsService.test.ts index e61b675c..ac5fc7fd 100644 --- a/workspace-server/src/__tests__/services/SheetsService.test.ts +++ b/workspace-server/src/__tests__/services/SheetsService.test.ts @@ -328,6 +328,8 @@ describe('SheetsService', () => { fields: 'nextPageToken, files(id, name)', q: "mimeType='application/vnd.google-apps.spreadsheet' and fullText contains 'budget'", pageToken: undefined, + supportsAllDrives: true, + includeItemsFromAllDrives: true, }); expect(response.files).toHaveLength(2); diff --git a/workspace-server/src/__tests__/services/SlidesService.test.ts b/workspace-server/src/__tests__/services/SlidesService.test.ts index c1351c28..b1f180ee 100644 --- a/workspace-server/src/__tests__/services/SlidesService.test.ts +++ b/workspace-server/src/__tests__/services/SlidesService.test.ts @@ -217,6 +217,8 @@ describe('SlidesService', () => { fields: 'nextPageToken, files(id, name)', q: "mimeType='application/vnd.google-apps.presentation' and fullText contains 'test query'", pageToken: undefined, + supportsAllDrives: true, + includeItemsFromAllDrives: true, }); expect(response.files).toHaveLength(2); diff --git a/workspace-server/src/services/DocsService.ts b/workspace-server/src/services/DocsService.ts index b62b7df3..b90f66af 100644 --- a/workspace-server/src/services/DocsService.ts +++ b/workspace-server/src/services/DocsService.ts @@ -83,6 +83,7 @@ export class DocsService { requestBody: fileMetadata, media: media, fields: 'id, name', + supportsAllDrives: true, }, mediaUploadOptions, ); @@ -235,6 +236,8 @@ export class DocsService { fields: 'nextPageToken, files(id, name)', q: q, pageToken: pageToken, + supportsAllDrives: true, + includeItemsFromAllDrives: true, }); const files = res.data.files || []; @@ -798,6 +801,7 @@ export class DocsService { const file = await drive.files.get({ fileId: documentId, fields: 'parents', + supportsAllDrives: true, }); const previousParents = file.data.parents?.join(','); @@ -807,6 +811,7 @@ export class DocsService { addParents: folderId, removeParents: previousParents, fields: 'id, parents', + supportsAllDrives: true, }); } catch (error) { if (error instanceof Error) { diff --git a/workspace-server/src/services/DriveService.ts b/workspace-server/src/services/DriveService.ts index b01ad68b..040c8314 100644 --- a/workspace-server/src/services/DriveService.ts +++ b/workspace-server/src/services/DriveService.ts @@ -9,6 +9,7 @@ import { AuthManager } from '../auth/AuthManager'; import { logToFile } from '../utils/logger'; import { gaxiosOptions } from '../utils/GaxiosConfig'; import { escapeQueryString } from '../utils/DriveQueryBuilder'; +import { extractDocumentId } from '../utils/validation'; import * as fs from 'node:fs'; import * as path from 'node:path'; import { PROJECT_ROOT } from '../utils/paths'; @@ -355,10 +356,11 @@ export class DriveService { logToFile(`Downloading Drive file ${fileId} to ${localPath}`); try { const drive = await this.getDriveClient(); + const id = extractDocumentId(fileId); // 1. Check if it's a Google Doc (special handling required, export instead of download) const metadata = await drive.files.get({ - fileId: fileId, + fileId: id, fields: 'id, name, mimeType', supportsAllDrives: true, }); @@ -391,7 +393,7 @@ export class DriveService { content: [ { type: 'text' as const, - text: `This is a ${fileInfo.type}. Direct download is not supported. Please use the '${fileInfo.tool}' tool with ${fileInfo.idName}: ${fileId}`, + text: `This is a ${fileInfo.type}. Direct download is not supported. Please use the '${fileInfo.tool}' tool with ${fileInfo.idName}: ${id}`, }, ], }; @@ -411,7 +413,7 @@ export class DriveService { // 2. Download media const response = await drive.files.get( { - fileId: fileId, + fileId: id, alt: 'media', supportsAllDrives: true, }, diff --git a/workspace-server/src/services/SheetsService.ts b/workspace-server/src/services/SheetsService.ts index e981aeb3..fb8df36f 100644 --- a/workspace-server/src/services/SheetsService.ts +++ b/workspace-server/src/services/SheetsService.ts @@ -223,6 +223,8 @@ export class SheetsService { fields: 'nextPageToken, files(id, name)', q: q, pageToken: pageToken, + supportsAllDrives: true, + includeItemsFromAllDrives: true, }); const files = res.data.files || []; diff --git a/workspace-server/src/services/SlidesService.ts b/workspace-server/src/services/SlidesService.ts index 46b18da1..d9627d7f 100644 --- a/workspace-server/src/services/SlidesService.ts +++ b/workspace-server/src/services/SlidesService.ts @@ -154,6 +154,8 @@ export class SlidesService { fields: 'nextPageToken, files(id, name)', q: q, pageToken: pageToken, + supportsAllDrives: true, + includeItemsFromAllDrives: true, }); const files = res.data.files || []; From 849daccaad2caf6da316c5ca1f593e3d0664d694 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Mon, 9 Feb 2026 22:05:26 +0000 Subject: [PATCH 2/3] fix: support Google Shared Drives and improve file ID extraction - Added `supportsAllDrives: true` and `includeItemsFromAllDrives: true` to Drive API calls in `DriveService`, `DocsService`, `SheetsService`, and `SlidesService`. - Improved `drive.downloadFile` to robustly handle full Drive URLs by extracting the file ID using `extractDocumentId`. - Updated unit tests to verify Shared Drive support and URL handling. Co-authored-by: raybell-md <196701227+raybell-md@users.noreply.github.com> From f102d78f3124d57a32bed0d2fe7ba31472f4914e Mon Sep 17 00:00:00 2001 From: Allen Hutchison Date: Wed, 11 Feb 2026 12:59:01 -0800 Subject: [PATCH 3/3] Update workspace-server/src/__tests__/services/DriveService.test.ts Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- workspace-server/src/__tests__/services/DriveService.test.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/workspace-server/src/__tests__/services/DriveService.test.ts b/workspace-server/src/__tests__/services/DriveService.test.ts index 2e0a9413..2bb8150a 100644 --- a/workspace-server/src/__tests__/services/DriveService.test.ts +++ b/workspace-server/src/__tests__/services/DriveService.test.ts @@ -910,6 +910,7 @@ describe('DriveService', () => { expect(mockDriveAPI.files.get).toHaveBeenCalledWith( expect.objectContaining({ fileId: mockFileId, + fields: 'id, name, mimeType', supportsAllDrives: true, }), );