mirror of
https://github.com/MODSetter/SurfSense.git
synced 2026-07-02 22:01:05 +02:00
feat: enhance OneDrive file creation by converting markdown to DOCX format and updating client to handle byte content
This commit is contained in:
parent
dc034a98eb
commit
8035eb9749
3 changed files with 50 additions and 6 deletions
|
|
@ -1,4 +1,7 @@
|
||||||
import logging
|
import logging
|
||||||
|
import os
|
||||||
|
import tempfile
|
||||||
|
from pathlib import Path
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from langchain_core.tools import tool
|
from langchain_core.tools import tool
|
||||||
|
|
@ -11,6 +14,34 @@ from app.db import SearchSourceConnector, SearchSourceConnectorType
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
DOCX_MIME = "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
|
||||||
|
|
||||||
|
|
||||||
|
def _ensure_docx_extension(name: str) -> str:
|
||||||
|
"""Strip any existing extension and append .docx."""
|
||||||
|
stem = Path(name).stem
|
||||||
|
return f"{stem}.docx"
|
||||||
|
|
||||||
|
|
||||||
|
def _markdown_to_docx(markdown_text: str) -> bytes:
|
||||||
|
"""Convert a markdown string to DOCX bytes using pypandoc."""
|
||||||
|
import pypandoc
|
||||||
|
|
||||||
|
fd, tmp_path = tempfile.mkstemp(suffix=".docx")
|
||||||
|
os.close(fd)
|
||||||
|
try:
|
||||||
|
pypandoc.convert_text(
|
||||||
|
markdown_text,
|
||||||
|
"docx",
|
||||||
|
format="gfm",
|
||||||
|
extra_args=["--standalone"],
|
||||||
|
outputfile=tmp_path,
|
||||||
|
)
|
||||||
|
with open(tmp_path, "rb") as f:
|
||||||
|
return f.read()
|
||||||
|
finally:
|
||||||
|
os.unlink(tmp_path)
|
||||||
|
|
||||||
|
|
||||||
def create_create_onedrive_file_tool(
|
def create_create_onedrive_file_tool(
|
||||||
db_session: AsyncSession | None = None,
|
db_session: AsyncSession | None = None,
|
||||||
|
|
@ -22,14 +53,17 @@ def create_create_onedrive_file_tool(
|
||||||
name: str,
|
name: str,
|
||||||
content: str | None = None,
|
content: str | None = None,
|
||||||
) -> dict[str, Any]:
|
) -> dict[str, Any]:
|
||||||
"""Create a new file in Microsoft OneDrive.
|
"""Create a new Word document (.docx) in Microsoft OneDrive.
|
||||||
|
|
||||||
Use this tool when the user explicitly asks to create a new document
|
Use this tool when the user explicitly asks to create a new document
|
||||||
in OneDrive. The user MUST specify a topic before you call this tool.
|
in OneDrive. The user MUST specify a topic before you call this tool.
|
||||||
|
|
||||||
|
The file is always saved as a .docx Word document. Provide content as
|
||||||
|
markdown and it will be automatically converted to a formatted Word file.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
name: The file name (with extension, e.g. "notes.txt" or "report.docx").
|
name: The document title (without extension). Extension will be set to .docx automatically.
|
||||||
content: Optional initial content as plain text or markdown.
|
content: Optional initial content as markdown. Will be converted to a formatted Word document.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Dictionary with status, file_id, name, web_url, and message.
|
Dictionary with status, file_id, name, web_url, and message.
|
||||||
|
|
@ -125,6 +159,8 @@ def create_create_onedrive_file_tool(
|
||||||
if not final_name or not final_name.strip():
|
if not final_name or not final_name.strip():
|
||||||
return {"status": "error", "message": "File name cannot be empty."}
|
return {"status": "error", "message": "File name cannot be empty."}
|
||||||
|
|
||||||
|
final_name = _ensure_docx_extension(final_name)
|
||||||
|
|
||||||
if final_connector_id is not None:
|
if final_connector_id is not None:
|
||||||
result = await db_session.execute(
|
result = await db_session.execute(
|
||||||
select(SearchSourceConnector).filter(
|
select(SearchSourceConnector).filter(
|
||||||
|
|
@ -141,11 +177,14 @@ def create_create_onedrive_file_tool(
|
||||||
if not connector:
|
if not connector:
|
||||||
return {"status": "error", "message": "Selected OneDrive connector is invalid."}
|
return {"status": "error", "message": "Selected OneDrive connector is invalid."}
|
||||||
|
|
||||||
|
docx_bytes = _markdown_to_docx(final_content or "")
|
||||||
|
|
||||||
client = OneDriveClient(session=db_session, connector_id=connector.id)
|
client = OneDriveClient(session=db_session, connector_id=connector.id)
|
||||||
created = await client.create_file(
|
created = await client.create_file(
|
||||||
name=final_name,
|
name=final_name,
|
||||||
parent_id=final_parent_folder_id,
|
parent_id=final_parent_folder_id,
|
||||||
content=final_content,
|
content=docx_bytes,
|
||||||
|
mime_type=DOCX_MIME,
|
||||||
)
|
)
|
||||||
|
|
||||||
logger.info(f"OneDrive file created: id={created.get('id')}, name={created.get('name')}")
|
logger.info(f"OneDrive file created: id={created.get('id')}, name={created.get('name')}")
|
||||||
|
|
|
||||||
|
|
@ -224,12 +224,15 @@ class OneDriveClient:
|
||||||
self,
|
self,
|
||||||
name: str,
|
name: str,
|
||||||
parent_id: str | None = None,
|
parent_id: str | None = None,
|
||||||
content: str | None = None,
|
content: str | bytes | None = None,
|
||||||
mime_type: str | None = None,
|
mime_type: str | None = None,
|
||||||
) -> dict[str, Any]:
|
) -> dict[str, Any]:
|
||||||
"""Create (upload) a file in OneDrive."""
|
"""Create (upload) a file in OneDrive."""
|
||||||
folder_path = f"/me/drive/items/{parent_id or 'root'}"
|
folder_path = f"/me/drive/items/{parent_id or 'root'}"
|
||||||
body = (content or "").encode("utf-8")
|
if isinstance(content, bytes):
|
||||||
|
body = content
|
||||||
|
else:
|
||||||
|
body = (content or "").encode("utf-8")
|
||||||
resp = await self._request(
|
resp = await self._request(
|
||||||
"PUT",
|
"PUT",
|
||||||
f"{folder_path}:/{name}:/content",
|
f"{folder_path}:/{name}:/content",
|
||||||
|
|
|
||||||
|
|
@ -877,6 +877,8 @@ async def _stream_agent_events(
|
||||||
"delete_linear_issue",
|
"delete_linear_issue",
|
||||||
"create_google_drive_file",
|
"create_google_drive_file",
|
||||||
"delete_google_drive_file",
|
"delete_google_drive_file",
|
||||||
|
"create_onedrive_file",
|
||||||
|
"delete_onedrive_file",
|
||||||
"create_gmail_draft",
|
"create_gmail_draft",
|
||||||
"update_gmail_draft",
|
"update_gmail_draft",
|
||||||
"send_gmail_email",
|
"send_gmail_email",
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue