Skip to content
Open
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
23 changes: 23 additions & 0 deletions workspace-server/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -532,6 +532,29 @@ async function main() {
driveService.downloadFile,
);

server.registerTool(
'drive.copy',
{
description:
'Copies a file in Google Drive. Useful for creating documents from templates. Returns the new file ID and URL.',
inputSchema: {
fileId: z
.string()
.describe(
'The ID of the file to copy. Can be extracted from a Google Drive URL.',
),
name: z.string().describe('The name for the new copied file.'),
folderId: z
.string()
.optional()
.describe(
'Optional folder ID to place the copy in. If not specified, the copy is placed in the same location as the original.',
),
},
},
driveService.copyFile,
);

server.registerTool(
'drive.moveFile',
{
Expand Down
59 changes: 58 additions & 1 deletion workspace-server/src/services/DriveService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ export class DriveService {
);
try {
const drive = await this.getDriveClient();
const id = extractDocumentId(fileId);
const fileMetadata: drive_v3.Schema$File = {
name: name,
mimeType: 'application/vnd.google-apps.folder',
Expand Down Expand Up @@ -157,6 +158,7 @@ export class DriveService {
sharedWithMe?: boolean;
}) => {
const drive = await this.getDriveClient();
const id = extractDocumentId(fileId);
let q = query;
let isProcessed = false;

Expand Down Expand Up @@ -209,7 +211,7 @@ export class DriveService {
logToFile(`Extracted File ID from URL: ${fileId}, using files.get`);
try {
const res = await drive.files.get({
fileId: fileId,
fileId: id,
fields:
'id, name, modifiedTime, viewedByMeTime, mimeType, parents',
supportsAllDrives: true,
Expand Down Expand Up @@ -361,6 +363,7 @@ export class DriveService {
try {
const drive = await this.getDriveClient();
const id = extractDocumentId(fileId);
const id = extractDocumentId(fileId);

const file = await drive.files.update({
fileId: id,
Expand Down Expand Up @@ -398,6 +401,7 @@ export class DriveService {
try {
const drive = await this.getDriveClient();
const id = extractDocumentId(fileId);
const id = extractDocumentId(fileId);

const file = await drive.files.update({
fileId: id,
Expand Down Expand Up @@ -428,6 +432,7 @@ export class DriveService {
try {
const drive = await this.getDriveClient();
const id = extractDocumentId(fileId);
const id = extractDocumentId(fileId);
const res = await drive.comments.list({
fileId: id,
fields:
Expand Down Expand Up @@ -467,6 +472,7 @@ export class DriveService {
try {
const drive = await this.getDriveClient();
const id = extractDocumentId(fileId);
const id = extractDocumentId(fileId);

let targetFolderId = folderId;

Expand Down Expand Up @@ -531,6 +537,56 @@ export class DriveService {
}
};

public copyFile = async ({
fileId,
name,
folderId,
}: {
fileId: string;
name: string;
folderId?: string;
}) => {
logToFile(
`Copying Drive file ${fileId} with new name: ${name}${folderId ? ` to folder: ${folderId}` : ''}`,
);
try {
const drive = await this.getDriveClient();
const id = extractDocumentId(fileId);

const requestBody: drive_v3.Schema$File = { name };
if (folderId) {
requestBody.parents = [folderId];
}

const copy = await drive.files.copy({
fileId: id,
requestBody: requestBody,
fields: 'id, name, mimeType, webViewLink',
supportsAllDrives: true,
});

logToFile(
`Successfully copied file: ${copy.data.name} (${copy.data.id})`,
);

return {
content: [
{
type: 'text' as const,
text: JSON.stringify({
id: copy.data.id,
name: copy.data.name,
mimeType: copy.data.mimeType,
webViewLink: copy.data.webViewLink,
}),
},
],
};
} catch (error) {
return this.handleError('drive.copyFile', error);
}
};

public downloadFile = async ({
fileId,
localPath,
Expand All @@ -542,6 +598,7 @@ export class DriveService {
try {
const drive = await this.getDriveClient();
const id = extractDocumentId(fileId);
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({
Expand Down