feat(drive): add create_drive_folder tool and unit test
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -453,6 +453,64 @@ async def list_drive_items(
|
||||
return text_output
|
||||
|
||||
|
||||
async def _create_drive_folder_impl(
|
||||
service,
|
||||
user_google_email: str,
|
||||
folder_name: str,
|
||||
parent_folder_id: str = "root",
|
||||
) -> str:
|
||||
"""Internal implementation for create_drive_folder. Used by tests."""
|
||||
resolved_folder_id = await resolve_folder_id(service, parent_folder_id)
|
||||
file_metadata = {
|
||||
"name": folder_name,
|
||||
"parents": [resolved_folder_id],
|
||||
"mimeType": "application/vnd.google-apps.folder",
|
||||
}
|
||||
created_file = await asyncio.to_thread(
|
||||
lambda: service.files()
|
||||
.create(
|
||||
body=file_metadata,
|
||||
fields="id, name, webViewLink",
|
||||
supportsAllDrives=True,
|
||||
)
|
||||
.execute()
|
||||
)
|
||||
link = created_file.get("webViewLink", "")
|
||||
return (
|
||||
f"Successfully created folder '{created_file.get('name', folder_name)}' (ID: {created_file.get('id', 'N/A')}) "
|
||||
f"in folder '{parent_folder_id}' for {user_google_email}. Link: {link}"
|
||||
)
|
||||
|
||||
|
||||
@server.tool()
|
||||
@handle_http_errors("create_drive_folder", service_type="drive")
|
||||
@require_google_service("drive", "drive_file")
|
||||
async def create_drive_folder(
|
||||
service,
|
||||
user_google_email: str,
|
||||
folder_name: str,
|
||||
parent_folder_id: str = "root",
|
||||
) -> str:
|
||||
"""
|
||||
Creates a new folder in Google Drive, supporting creation within shared drives.
|
||||
|
||||
Args:
|
||||
user_google_email (str): The user's Google email address. Required.
|
||||
folder_name (str): The name for the new folder.
|
||||
parent_folder_id (str): The ID of the parent folder. Defaults to 'root'.
|
||||
For shared drives, use a folder ID within that shared drive.
|
||||
|
||||
Returns:
|
||||
str: Confirmation message with folder name, ID, and link.
|
||||
"""
|
||||
logger.info(
|
||||
f"[create_drive_folder] Invoked. Email: '{user_google_email}', Folder: '{folder_name}', Parent: '{parent_folder_id}'"
|
||||
)
|
||||
return await _create_drive_folder_impl(
|
||||
service, user_google_email, folder_name, parent_folder_id
|
||||
)
|
||||
|
||||
|
||||
@server.tool()
|
||||
@handle_http_errors("create_drive_file", service_type="drive")
|
||||
@require_google_service("drive", "drive_file")
|
||||
@@ -484,7 +542,7 @@ async def create_drive_file(
|
||||
f"[create_drive_file] Invoked. Email: '{user_google_email}', File Name: {file_name}, Folder ID: {folder_id}, fileUrl: {fileUrl}"
|
||||
)
|
||||
|
||||
if not content and not fileUrl:
|
||||
if not content and not fileUrl and mime_type != "application/vnd.google-apps.folder":
|
||||
raise Exception("You must provide either 'content' or 'fileUrl'.")
|
||||
|
||||
file_data = None
|
||||
@@ -496,6 +554,23 @@ async def create_drive_file(
|
||||
"mimeType": mime_type,
|
||||
}
|
||||
|
||||
# Create folder (no content or media_body). Prefer create_drive_folder for new code.
|
||||
if mime_type == "application/vnd.google-apps.folder":
|
||||
created_file = await asyncio.to_thread(
|
||||
lambda: service.files()
|
||||
.create(
|
||||
body=file_metadata,
|
||||
fields="id, name, webViewLink",
|
||||
supportsAllDrives=True,
|
||||
)
|
||||
.execute()
|
||||
)
|
||||
link = created_file.get("webViewLink", "")
|
||||
return (
|
||||
f"Successfully created folder '{created_file.get('name', file_name)}' (ID: {created_file.get('id', 'N/A')}) "
|
||||
f"in folder '{folder_id}' for {user_google_email}. Link: {link}"
|
||||
)
|
||||
|
||||
# Prefer fileUrl if both are provided
|
||||
if fileUrl:
|
||||
logger.info(f"[create_drive_file] Fetching file from URL: {fileUrl}")
|
||||
|
||||
Reference in New Issue
Block a user