datarobot-genai 0.2.26__tar.gz → 0.2.27__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/PKG-INFO +1 -1
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/pyproject.toml +1 -1
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/drmcp/tools/clients/gdrive.py +127 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/drmcp/tools/gdrive/tools.py +95 -2
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/.gitignore +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/AUTHORS +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/LICENSE +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/README.md +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/__init__.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/core/__init__.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/core/agents/__init__.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/core/agents/base.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/core/chat/__init__.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/core/chat/auth.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/core/chat/client.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/core/chat/responses.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/core/cli/__init__.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/core/cli/agent_environment.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/core/cli/agent_kernel.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/core/custom_model.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/core/mcp/__init__.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/core/mcp/common.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/core/telemetry_agent.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/core/utils/__init__.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/core/utils/auth.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/core/utils/urls.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/crewai/__init__.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/crewai/agent.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/crewai/base.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/crewai/events.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/crewai/mcp.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/drmcp/__init__.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/drmcp/core/__init__.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/drmcp/core/auth.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/drmcp/core/clients.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/drmcp/core/config.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/drmcp/core/config_utils.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/drmcp/core/constants.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/drmcp/core/credentials.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/drmcp/core/dr_mcp_server.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/drmcp/core/dr_mcp_server_logo.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/drmcp/core/dynamic_prompts/__init__.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/drmcp/core/dynamic_prompts/controllers.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/drmcp/core/dynamic_prompts/dr_lib.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/drmcp/core/dynamic_prompts/register.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/drmcp/core/dynamic_prompts/utils.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/drmcp/core/dynamic_tools/__init__.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/drmcp/core/dynamic_tools/deployment/__init__.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/drmcp/core/dynamic_tools/deployment/adapters/__init__.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/drmcp/core/dynamic_tools/deployment/adapters/base.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/drmcp/core/dynamic_tools/deployment/adapters/default.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/drmcp/core/dynamic_tools/deployment/adapters/drum.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/drmcp/core/dynamic_tools/deployment/config.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/drmcp/core/dynamic_tools/deployment/controllers.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/drmcp/core/dynamic_tools/deployment/metadata.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/drmcp/core/dynamic_tools/deployment/register.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/drmcp/core/dynamic_tools/deployment/schemas/drum_agentic_fallback_schema.json +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/drmcp/core/dynamic_tools/deployment/schemas/drum_prediction_fallback_schema.json +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/drmcp/core/dynamic_tools/register.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/drmcp/core/dynamic_tools/schema.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/drmcp/core/exceptions.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/drmcp/core/logging.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/drmcp/core/mcp_instance.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/drmcp/core/memory_management/__init__.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/drmcp/core/memory_management/manager.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/drmcp/core/memory_management/memory_tools.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/drmcp/core/routes.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/drmcp/core/routes_utils.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/drmcp/core/server_life_cycle.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/drmcp/core/telemetry.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/drmcp/core/tool_config.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/drmcp/core/tool_filter.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/drmcp/core/utils.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/drmcp/server.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/drmcp/test_utils/__init__.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/drmcp/test_utils/elicitation_test_tool.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/drmcp/test_utils/integration_mcp_server.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/drmcp/test_utils/mcp_utils_ete.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/drmcp/test_utils/mcp_utils_integration.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/drmcp/test_utils/openai_llm_mcp_client.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/drmcp/test_utils/test_interactive.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/drmcp/test_utils/tool_base_ete.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/drmcp/test_utils/utils.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/drmcp/tools/__init__.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/drmcp/tools/clients/__init__.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/drmcp/tools/clients/atlassian.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/drmcp/tools/clients/confluence.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/drmcp/tools/clients/jira.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/drmcp/tools/clients/s3.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/drmcp/tools/confluence/__init__.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/drmcp/tools/confluence/tools.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/drmcp/tools/gdrive/__init__.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/drmcp/tools/jira/__init__.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/drmcp/tools/jira/tools.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/drmcp/tools/predictive/__init__.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/drmcp/tools/predictive/data.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/drmcp/tools/predictive/deployment.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/drmcp/tools/predictive/deployment_info.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/drmcp/tools/predictive/model.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/drmcp/tools/predictive/predict.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/drmcp/tools/predictive/predict_realtime.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/drmcp/tools/predictive/project.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/drmcp/tools/predictive/training.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/langgraph/__init__.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/langgraph/agent.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/langgraph/mcp.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/llama_index/__init__.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/llama_index/agent.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/llama_index/base.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/llama_index/mcp.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/nat/__init__.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/nat/agent.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/nat/datarobot_auth_provider.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/nat/datarobot_llm_clients.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/nat/datarobot_llm_providers.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/nat/datarobot_mcp_client.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/nat/helpers.py +0 -0
- {datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/py.typed +0 -0
{datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/drmcp/tools/clients/gdrive.py
RENAMED
|
@@ -15,7 +15,9 @@
|
|
|
15
15
|
"""Google Drive API Client and utilities for OAuth."""
|
|
16
16
|
|
|
17
17
|
import io
|
|
18
|
+
import json
|
|
18
19
|
import logging
|
|
20
|
+
import uuid
|
|
19
21
|
from typing import Annotated
|
|
20
22
|
from typing import Any
|
|
21
23
|
|
|
@@ -45,6 +47,12 @@ GOOGLE_WORKSPACE_EXPORT_MIMES: dict[str, str] = {
|
|
|
45
47
|
"application/vnd.google-apps.presentation": "text/plain",
|
|
46
48
|
}
|
|
47
49
|
|
|
50
|
+
# MIME type mappings for content conversion during upload to Google Workspace formats
|
|
51
|
+
UPLOAD_CONTENT_TYPES: dict[str, str] = {
|
|
52
|
+
"application/vnd.google-apps.document": "text/plain",
|
|
53
|
+
"application/vnd.google-apps.spreadsheet": "text/csv",
|
|
54
|
+
}
|
|
55
|
+
|
|
48
56
|
BINARY_MIME_PREFIXES = (
|
|
49
57
|
"image/",
|
|
50
58
|
"audio/",
|
|
@@ -599,6 +607,125 @@ class GoogleDriveClient:
|
|
|
599
607
|
web_view_link=file_metadata.web_view_link,
|
|
600
608
|
)
|
|
601
609
|
|
|
610
|
+
async def create_file(
|
|
611
|
+
self,
|
|
612
|
+
name: str,
|
|
613
|
+
mime_type: str,
|
|
614
|
+
parent_id: str | None = None,
|
|
615
|
+
initial_content: str | None = None,
|
|
616
|
+
) -> GoogleDriveFile:
|
|
617
|
+
"""Create a new file or folder in Google Drive.
|
|
618
|
+
|
|
619
|
+
Creates a new file with the specified name and MIME type. Optionally places
|
|
620
|
+
it in a specific folder and populates it with initial content.
|
|
621
|
+
|
|
622
|
+
For Google Workspace files (Docs, Sheets), the Drive API automatically
|
|
623
|
+
converts plain text content to the appropriate format.
|
|
624
|
+
|
|
625
|
+
Args:
|
|
626
|
+
name: The name for the new file or folder.
|
|
627
|
+
mime_type: The MIME type of the file (e.g., 'text/plain',
|
|
628
|
+
'application/vnd.google-apps.document',
|
|
629
|
+
'application/vnd.google-apps.folder').
|
|
630
|
+
parent_id: Optional ID of the parent folder. If not specified,
|
|
631
|
+
the file is created in the root of the user's Drive.
|
|
632
|
+
initial_content: Optional text content to populate the file.
|
|
633
|
+
Ignored for folders.
|
|
634
|
+
|
|
635
|
+
Returns
|
|
636
|
+
-------
|
|
637
|
+
GoogleDriveFile with the created file's metadata.
|
|
638
|
+
|
|
639
|
+
Raises
|
|
640
|
+
------
|
|
641
|
+
GoogleDriveError: If file creation fails (permission denied,
|
|
642
|
+
parent not found, rate limited, etc.).
|
|
643
|
+
"""
|
|
644
|
+
metadata: dict[str, Any] = {
|
|
645
|
+
"name": name,
|
|
646
|
+
"mimeType": mime_type,
|
|
647
|
+
}
|
|
648
|
+
if parent_id:
|
|
649
|
+
metadata["parents"] = [parent_id]
|
|
650
|
+
|
|
651
|
+
if mime_type == GOOGLE_DRIVE_FOLDER_MIME or not initial_content:
|
|
652
|
+
response = await self._client.post(
|
|
653
|
+
"/",
|
|
654
|
+
json=metadata,
|
|
655
|
+
params={"fields": SUPPORTED_FIELDS_STR, "supportsAllDrives": "true"},
|
|
656
|
+
)
|
|
657
|
+
else:
|
|
658
|
+
response = await self._create_file_with_content(
|
|
659
|
+
metadata=metadata,
|
|
660
|
+
content=initial_content,
|
|
661
|
+
target_mime_type=mime_type,
|
|
662
|
+
)
|
|
663
|
+
|
|
664
|
+
if response.status_code == 404:
|
|
665
|
+
raise GoogleDriveError(
|
|
666
|
+
f"Parent folder with ID '{parent_id}' not found."
|
|
667
|
+
if parent_id
|
|
668
|
+
else "Resource not found."
|
|
669
|
+
)
|
|
670
|
+
if response.status_code == 403:
|
|
671
|
+
raise GoogleDriveError(
|
|
672
|
+
"Permission denied: you don't have permission to create files in this location."
|
|
673
|
+
)
|
|
674
|
+
if response.status_code == 400:
|
|
675
|
+
raise GoogleDriveError(
|
|
676
|
+
f"Bad request: invalid parameters for file creation. "
|
|
677
|
+
f"Check that the MIME type '{mime_type}' is valid."
|
|
678
|
+
)
|
|
679
|
+
if response.status_code == 429:
|
|
680
|
+
raise GoogleDriveError("Rate limit exceeded. Please try again later.")
|
|
681
|
+
|
|
682
|
+
response.raise_for_status()
|
|
683
|
+
return GoogleDriveFile.from_api_response(response.json())
|
|
684
|
+
|
|
685
|
+
async def _create_file_with_content(
|
|
686
|
+
self,
|
|
687
|
+
metadata: dict[str, Any],
|
|
688
|
+
content: str,
|
|
689
|
+
target_mime_type: str,
|
|
690
|
+
) -> httpx.Response:
|
|
691
|
+
"""Create a file with content using multipart upload.
|
|
692
|
+
|
|
693
|
+
Args:
|
|
694
|
+
metadata: File metadata dictionary.
|
|
695
|
+
content: Text content for the file.
|
|
696
|
+
target_mime_type: The target MIME type for the file.
|
|
697
|
+
|
|
698
|
+
Returns
|
|
699
|
+
-------
|
|
700
|
+
The HTTP response from the upload.
|
|
701
|
+
"""
|
|
702
|
+
content_type = UPLOAD_CONTENT_TYPES.get(target_mime_type, "text/plain")
|
|
703
|
+
boundary = f"===gdrive_boundary_{uuid.uuid4().hex}==="
|
|
704
|
+
body_parts = [
|
|
705
|
+
f"--{boundary}",
|
|
706
|
+
"Content-Type: application/json; charset=UTF-8",
|
|
707
|
+
"",
|
|
708
|
+
json.dumps(metadata),
|
|
709
|
+
f"--{boundary}",
|
|
710
|
+
f"Content-Type: {content_type}",
|
|
711
|
+
"",
|
|
712
|
+
content,
|
|
713
|
+
f"--{boundary}--",
|
|
714
|
+
]
|
|
715
|
+
body = "\r\n".join(body_parts)
|
|
716
|
+
|
|
717
|
+
upload_url = "https://www.googleapis.com/upload/drive/v3/files"
|
|
718
|
+
return await self._client.post(
|
|
719
|
+
upload_url,
|
|
720
|
+
content=body.encode("utf-8"),
|
|
721
|
+
params={
|
|
722
|
+
"uploadType": "multipart",
|
|
723
|
+
"fields": SUPPORTED_FIELDS_STR,
|
|
724
|
+
"supportsAllDrives": "true",
|
|
725
|
+
},
|
|
726
|
+
headers={"Content-Type": f"multipart/related; boundary={boundary}"},
|
|
727
|
+
)
|
|
728
|
+
|
|
602
729
|
async def __aenter__(self) -> "GoogleDriveClient":
|
|
603
730
|
"""Async context manager entry."""
|
|
604
731
|
return self
|
{datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/drmcp/tools/gdrive/tools.py
RENAMED
|
@@ -21,6 +21,7 @@ from fastmcp.exceptions import ToolError
|
|
|
21
21
|
from fastmcp.tools.tool import ToolResult
|
|
22
22
|
|
|
23
23
|
from datarobot_genai.drmcp.core.mcp_instance import dr_mcp_tool
|
|
24
|
+
from datarobot_genai.drmcp.tools.clients.gdrive import GOOGLE_DRIVE_FOLDER_MIME
|
|
24
25
|
from datarobot_genai.drmcp.tools.clients.gdrive import LIMIT
|
|
25
26
|
from datarobot_genai.drmcp.tools.clients.gdrive import MAX_PAGE_SIZE
|
|
26
27
|
from datarobot_genai.drmcp.tools.clients.gdrive import SUPPORTED_FIELDS
|
|
@@ -60,7 +61,7 @@ async def gdrive_find_contents(
|
|
|
60
61
|
"Optional list of metadata fields to include. Ex. id, name, mimeType. "
|
|
61
62
|
f"Default = {SUPPORTED_FIELDS_STR}",
|
|
62
63
|
] = None,
|
|
63
|
-
) -> ToolResult
|
|
64
|
+
) -> ToolResult:
|
|
64
65
|
"""
|
|
65
66
|
Search or list files in the user's Google Drive with pagination and filtering support.
|
|
66
67
|
Use this tool to discover file names and IDs for use with other tools.
|
|
@@ -121,7 +122,7 @@ async def gdrive_read_content(
|
|
|
121
122
|
"(e.g., 'text/markdown' for Docs, 'text/csv' for Sheets). "
|
|
122
123
|
"If not specified, uses sensible defaults. Has no effect on regular files.",
|
|
123
124
|
] = None,
|
|
124
|
-
) -> ToolResult
|
|
125
|
+
) -> ToolResult:
|
|
125
126
|
"""
|
|
126
127
|
Retrieve the content of a specific file by its ID. Google Workspace files are
|
|
127
128
|
automatically exported to LLM-readable formats (Push-Down).
|
|
@@ -175,3 +176,95 @@ async def gdrive_read_content(
|
|
|
175
176
|
),
|
|
176
177
|
structured_content=file_content.as_flat_dict(),
|
|
177
178
|
)
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
@dr_mcp_tool(tags={"google", "gdrive", "create", "write", "file", "folder"}, enabled=False)
|
|
182
|
+
async def gdrive_create_file(
|
|
183
|
+
*,
|
|
184
|
+
name: Annotated[str, "The name for the new file or folder."],
|
|
185
|
+
mime_type: Annotated[
|
|
186
|
+
str,
|
|
187
|
+
"The MIME type of the file (e.g., 'text/plain', "
|
|
188
|
+
"'application/vnd.google-apps.document', 'application/vnd.google-apps.folder').",
|
|
189
|
+
],
|
|
190
|
+
parent_id: Annotated[
|
|
191
|
+
str | None, "The ID of the parent folder where the file should be created."
|
|
192
|
+
] = None,
|
|
193
|
+
initial_content: Annotated[
|
|
194
|
+
str | None, "Text content to populate the new file, if applicable."
|
|
195
|
+
] = None,
|
|
196
|
+
) -> ToolResult:
|
|
197
|
+
"""
|
|
198
|
+
Create a new file or folder in Google Drive.
|
|
199
|
+
|
|
200
|
+
This tool is essential for an AI agent to generate new output (like reports or
|
|
201
|
+
documentation) directly into the Drive structure.
|
|
202
|
+
|
|
203
|
+
Usage:
|
|
204
|
+
- Create empty file: gdrive_create_file(name="report.txt", mime_type="text/plain")
|
|
205
|
+
- Create Google Doc: gdrive_create_file(
|
|
206
|
+
name="My Report",
|
|
207
|
+
mime_type="application/vnd.google-apps.document",
|
|
208
|
+
initial_content="# Report Title"
|
|
209
|
+
)
|
|
210
|
+
- Create folder: gdrive_create_file(
|
|
211
|
+
name="Reports",
|
|
212
|
+
mime_type="application/vnd.google-apps.folder"
|
|
213
|
+
)
|
|
214
|
+
- Create in subfolder: gdrive_create_file(
|
|
215
|
+
name="file.txt",
|
|
216
|
+
mime_type="text/plain",
|
|
217
|
+
parent_id="folder_id_here",
|
|
218
|
+
initial_content="File content"
|
|
219
|
+
)
|
|
220
|
+
|
|
221
|
+
Supported MIME types:
|
|
222
|
+
- text/plain: Plain text file
|
|
223
|
+
- application/vnd.google-apps.document: Google Doc (content auto-converted)
|
|
224
|
+
- application/vnd.google-apps.spreadsheet: Google Sheet (CSV content works best)
|
|
225
|
+
- application/vnd.google-apps.folder: Folder (initial_content is ignored)
|
|
226
|
+
|
|
227
|
+
Note: For Google Workspace files, the Drive API automatically converts plain text
|
|
228
|
+
content to the appropriate format.
|
|
229
|
+
"""
|
|
230
|
+
if not name or not name.strip():
|
|
231
|
+
raise ToolError("Argument validation error: 'name' cannot be empty.")
|
|
232
|
+
|
|
233
|
+
if not mime_type or not mime_type.strip():
|
|
234
|
+
raise ToolError("Argument validation error: 'mime_type' cannot be empty.")
|
|
235
|
+
|
|
236
|
+
access_token = await get_gdrive_access_token()
|
|
237
|
+
if isinstance(access_token, ToolError):
|
|
238
|
+
raise access_token
|
|
239
|
+
|
|
240
|
+
try:
|
|
241
|
+
async with GoogleDriveClient(access_token) as client:
|
|
242
|
+
created_file = await client.create_file(
|
|
243
|
+
name=name,
|
|
244
|
+
mime_type=mime_type,
|
|
245
|
+
parent_id=parent_id,
|
|
246
|
+
initial_content=initial_content,
|
|
247
|
+
)
|
|
248
|
+
except GoogleDriveError as e:
|
|
249
|
+
logger.error(f"Google Drive error creating file: {e}")
|
|
250
|
+
raise ToolError(str(e))
|
|
251
|
+
except Exception as e:
|
|
252
|
+
logger.error(f"Unexpected error creating Google Drive file: {e}")
|
|
253
|
+
raise ToolError(f"An unexpected error occurred while creating Google Drive file: {str(e)}")
|
|
254
|
+
|
|
255
|
+
# Build response message
|
|
256
|
+
file_type = "folder" if mime_type == GOOGLE_DRIVE_FOLDER_MIME else "file"
|
|
257
|
+
content_info = ""
|
|
258
|
+
if initial_content and mime_type != GOOGLE_DRIVE_FOLDER_MIME:
|
|
259
|
+
content_info = " with initial content"
|
|
260
|
+
|
|
261
|
+
return ToolResult(
|
|
262
|
+
content=f"Successfully created {file_type} '{created_file.name}'{content_info}.",
|
|
263
|
+
structured_content={
|
|
264
|
+
"id": created_file.id,
|
|
265
|
+
"name": created_file.name,
|
|
266
|
+
"mimeType": created_file.mime_type,
|
|
267
|
+
"webViewLink": created_file.web_view_link,
|
|
268
|
+
"createdTime": created_file.created_time,
|
|
269
|
+
},
|
|
270
|
+
)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/core/agents/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/core/chat/responses.py
RENAMED
|
File without changes
|
|
File without changes
|
{datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/core/cli/agent_environment.py
RENAMED
|
File without changes
|
{datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/core/cli/agent_kernel.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/core/telemetry_agent.py
RENAMED
|
File without changes
|
{datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/core/utils/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/drmcp/core/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/drmcp/core/config_utils.py
RENAMED
|
File without changes
|
{datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/drmcp/core/constants.py
RENAMED
|
File without changes
|
{datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/drmcp/core/credentials.py
RENAMED
|
File without changes
|
{datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/drmcp/core/dr_mcp_server.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/drmcp/core/exceptions.py
RENAMED
|
File without changes
|
|
File without changes
|
{datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/drmcp/core/mcp_instance.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/drmcp/core/routes_utils.py
RENAMED
|
File without changes
|
|
File without changes
|
{datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/drmcp/core/telemetry.py
RENAMED
|
File without changes
|
{datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/drmcp/core/tool_config.py
RENAMED
|
File without changes
|
{datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/drmcp/core/tool_filter.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/drmcp/test_utils/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/drmcp/test_utils/utils.py
RENAMED
|
File without changes
|
{datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/drmcp/tools/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/drmcp/tools/clients/jira.py
RENAMED
|
File without changes
|
{datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/drmcp/tools/clients/s3.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/drmcp/tools/gdrive/__init__.py
RENAMED
|
File without changes
|
{datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/drmcp/tools/jira/__init__.py
RENAMED
|
File without changes
|
{datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/drmcp/tools/jira/tools.py
RENAMED
|
File without changes
|
|
File without changes
|
{datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/drmcp/tools/predictive/data.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/llama_index/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/nat/datarobot_auth_provider.py
RENAMED
|
File without changes
|
{datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/nat/datarobot_llm_clients.py
RENAMED
|
File without changes
|
{datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/nat/datarobot_llm_providers.py
RENAMED
|
File without changes
|
{datarobot_genai-0.2.26 → datarobot_genai-0.2.27}/src/datarobot_genai/nat/datarobot_mcp_client.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|