Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 15 additions & 1 deletion workspace-server/src/__tests__/services/DocsService.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down Expand Up @@ -157,6 +162,7 @@ describe('DocsService', () => {
addParents: 'test-folder-id',
removeParents: 'root',
fields: 'id, parents',
supportsAllDrives: true,
});
});

Expand Down Expand Up @@ -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({
Expand Down Expand Up @@ -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',
Expand Down
45 changes: 45 additions & 0 deletions workspace-server/src/__tests__/services/DriveService.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -884,6 +884,51 @@ 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,
fields: 'id, name, mimeType',
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({
Expand Down
2 changes: 2 additions & 0 deletions workspace-server/src/__tests__/services/SheetsService.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 2 additions & 0 deletions workspace-server/src/__tests__/services/SlidesService.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
5 changes: 5 additions & 0 deletions workspace-server/src/services/DocsService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ export class DocsService {
requestBody: fileMetadata,
media: media,
fields: 'id, name',
supportsAllDrives: true,
},
mediaUploadOptions,
);
Expand Down Expand Up @@ -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 || [];
Expand Down Expand Up @@ -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(',');
Expand All @@ -807,6 +811,7 @@ export class DocsService {
addParents: folderId,
removeParents: previousParents,
fields: 'id, parents',
supportsAllDrives: true,
});
} catch (error) {
if (error instanceof Error) {
Expand Down
8 changes: 5 additions & 3 deletions workspace-server/src/services/DriveService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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,
});
Expand Down Expand Up @@ -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}`,
},
],
};
Expand All @@ -411,7 +413,7 @@ export class DriveService {
// 2. Download media
const response = await drive.files.get(
{
fileId: fileId,
fileId: id,
alt: 'media',
supportsAllDrives: true,
},
Expand Down
2 changes: 2 additions & 0 deletions workspace-server/src/services/SheetsService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 || [];
Expand Down
2 changes: 2 additions & 0 deletions workspace-server/src/services/SlidesService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 || [];
Expand Down
Loading