Refactor update_notion_page to append-only with simplified parameters

This commit is contained in:
CREDO23 2026-02-13 13:07:19 +02:00
parent 0d1b61d7e6
commit 9411edf057
5 changed files with 34 additions and 115 deletions

View file

@ -33,19 +33,16 @@ def create_update_notion_page_tool(
@tool @tool
async def update_notion_page( async def update_notion_page(
page_title: str, page_title: str,
new_title: str | None = None, content: str,
new_content: str | None = None,
) -> dict[str, Any]: ) -> dict[str, Any]:
"""Update an existing Notion page's title and/or content. """Update an existing Notion page by appending new content.
Use this tool when the user asks you to modify, edit, or update Use this tool when the user asks you to add content to, modify, or update
a Notion page. At least one of new_title or new_content must be provided. a Notion page. The new content will be appended to the existing page content.
Args: Args:
page_title: The current title of the Notion page to update (required). page_title: The title of the Notion page to update.
new_title: New title for the page (optional). content: The markdown content to append to the page body (supports headings, lists, paragraphs).
new_content: New markdown content for the page body (optional).
If provided, replaces all existing content.
Returns: Returns:
Dictionary with: Dictionary with:
@ -60,11 +57,10 @@ def create_update_notion_page_tool(
and move on. Do NOT ask for alternatives or troubleshoot. and move on. Do NOT ask for alternatives or troubleshoot.
Examples: Examples:
- "Update the 'Meeting Notes' page with new title 'Updated Meeting Notes'" - "Add 'New meeting notes from today' to the 'Meeting Notes' page"
- "Change the content of 'Project Plan' page to 'New content here'" - "Append the following to 'Project Plan': '# Status Update\n\nCompleted phase 1'"
- "Update 'Weekly Report' with new title 'Final Report' and content '# Summary...'"
""" """
logger.info(f"update_notion_page called: page_title='{page_title}', new_title={new_title}, has_content={new_content is not None}") logger.info(f"update_notion_page called: page_title='{page_title}', content_length={len(content) if content else 0}")
if db_session is None or search_space_id is None or user_id is None: if db_session is None or search_space_id is None or user_id is None:
logger.error("Notion tool not properly configured - missing required parameters") logger.error("Notion tool not properly configured - missing required parameters")
@ -73,10 +69,11 @@ def create_update_notion_page_tool(
"message": "Notion tool not properly configured. Please contact support.", "message": "Notion tool not properly configured. Please contact support.",
} }
if not new_title and not new_content: if not content or not content.strip():
logger.error(f"Empty content provided for page '{page_title}'")
return { return {
"status": "error", "status": "error",
"message": "At least one of 'new_title' or 'new_content' must be provided to update the page.", "message": "Content is required to update the page. Please provide the actual content you want to add.",
} }
try: try:
@ -103,8 +100,7 @@ def create_update_notion_page_tool(
"tool": "update_notion_page", "tool": "update_notion_page",
"params": { "params": {
"page_id": page_id, "page_id": page_id,
"title": new_title, "content": content,
"content": new_content,
"connector_id": connector_id_from_context, "connector_id": connector_id_from_context,
}, },
}, },
@ -135,19 +131,10 @@ def create_update_notion_page_tool(
final_params = edited_action.get("args", {}) if edited_action else {} final_params = edited_action.get("args", {}) if edited_action else {}
final_page_id = final_params.get("page_id", page_id) final_page_id = final_params.get("page_id", page_id)
final_title = final_params.get("title", new_title) final_content = final_params.get("content", content)
final_content = final_params.get("content", new_content)
final_connector_id = final_params.get("connector_id", connector_id_from_context) final_connector_id = final_params.get("connector_id", connector_id_from_context)
# Validate title if it's being updated logger.info(f"Updating Notion page with final params: page_id={final_page_id}, has_content={final_content is not None}")
if final_title is not None and not final_title.strip():
logger.error("Title is empty or contains only whitespace")
return {
"status": "error",
"message": "Page title cannot be empty. Please provide a valid title.",
}
logger.info(f"Updating Notion page with final params: page_id={final_page_id}, title={final_title}, has_content={final_content is not None}")
from sqlalchemy.future import select from sqlalchemy.future import select
@ -189,7 +176,6 @@ def create_update_notion_page_tool(
result = await notion_connector.update_page( result = await notion_connector.update_page(
page_id=final_page_id, page_id=final_page_id,
title=final_title,
content=final_content, content=final_content,
) )
logger.info(f"update_page result: {result.get('status')} - {result.get('message', '')}") logger.info(f"update_page result: {result.get('status')} - {result.get('message', '')}")

View file

@ -219,7 +219,7 @@ BUILTIN_TOOLS: list[ToolDefinition] = [
), ),
ToolDefinition( ToolDefinition(
name="update_notion_page", name="update_notion_page",
description="Update an existing Notion page's title or content", description="Append new content to an existing Notion page",
factory=lambda deps: create_update_notion_page_tool( factory=lambda deps: create_update_notion_page_tool(
db_session=deps["db_session"], db_session=deps["db_session"],
search_space_id=deps["search_space_id"], search_space_id=deps["search_space_id"],

View file

@ -987,15 +987,16 @@ class NotionHistoryConnector:
} }
async def update_page( async def update_page(
self, page_id: str, title: str | None = None, content: str | None = None self, page_id: str, content: str | None = None
) -> dict[str, Any]: ) -> dict[str, Any]:
""" """
Update an existing Notion page. Update an existing Notion page by appending new content.
Note: Content is appended to the page, not replaced.
Args: Args:
page_id: Page ID to update page_id: Page ID to update
title: New page title (optional) content: New markdown content to append to the page (optional)
content: New page content in markdown (optional)
Returns: Returns:
Dictionary with update result Dictionary with update result
@ -1006,31 +1007,13 @@ class NotionHistoryConnector:
try: try:
notion = await self._get_client() notion = await self._get_client()
# Update title if provided # Append content if provided
if title:
await self._api_call_with_retry(
notion.pages.update,
page_id=page_id,
properties={
"title": {
"title": [{"type": "text", "text": {"content": title}}]
}
},
)
# Update content if provided
if content: if content:
# First, get existing blocks
existing_blocks = await self._api_call_with_retry(
notion.blocks.children.list,
block_id=page_id
)
# Convert new content to blocks # Convert new content to blocks
try: try:
children = self._markdown_to_blocks(content) children = self._markdown_to_blocks(content)
if not children: if not children:
logger.warning("No blocks generated from content, skipping update") logger.warning("No blocks generated from content, skipping append")
return { return {
"status": "error", "status": "error",
"message": "Content conversion failed: no valid blocks generated", "message": "Content conversion failed: no valid blocks generated",
@ -1042,25 +1025,7 @@ class NotionHistoryConnector:
"message": f"Failed to parse content: {e!s}", "message": f"Failed to parse content: {e!s}",
} }
# Store block count for logging # Append new content blocks
block_count = len(existing_blocks.get("results", []))
# Delete existing blocks
try:
for block in existing_blocks.get("results", []):
await self._api_call_with_retry(
notion.blocks.delete,
block_id=block["id"]
)
logger.info(f"Deleted {block_count} existing blocks from page {page_id}")
except Exception as e:
logger.error(f"Failed to delete existing blocks: {e}")
return {
"status": "error",
"message": f"Failed to clear existing content: {e!s}",
}
# Add new content (CRITICAL: if this fails, content is lost) Need improvement to handle this better.
try: try:
for i in range(0, len(children), 100): for i in range(0, len(children), 100):
batch = children[i : i + 100] batch = children[i : i + 100]
@ -1069,44 +1034,15 @@ class NotionHistoryConnector:
block_id=page_id, block_id=page_id,
children=batch children=batch
) )
logger.info(f"Successfully added {len(children)} new blocks to page {page_id}") logger.info(f"Successfully appended {len(children)} new blocks to page {page_id}")
except Exception as e: except Exception as e:
# CRITICAL ERROR: Content was deleted but new content failed to add logger.error(f"Failed to append content blocks: {e}")
logger.error(
f"CRITICAL: Failed to add new content after deleting {block_count} blocks. "
f"Page {page_id} content is lost! Error: {e}"
)
# Attempt to add an error placeholder block so page isn't completely empty
try:
await self._api_call_with_retry(
notion.blocks.children.append,
block_id=page_id,
children=[{
"object": "block",
"type": "paragraph",
"paragraph": {
"rich_text": [{
"type": "text",
"text": {
"content": "[ERROR] Content update failed. Original content was lost. "
"Please check your SurfSense logs for details."
}
}]
},
}]
)
logger.info(f"Added error placeholder to page {page_id}")
except Exception as placeholder_error:
logger.error(f"Failed to add error placeholder: {placeholder_error}")
return { return {
"status": "error", "status": "error",
"message": f"CRITICAL: Failed to update page content. Original content ({block_count} blocks) " "message": f"Failed to append content: {e!s}",
f"was deleted but new content could not be added: {e!s}",
} }
# Get updated page # Get updated page info
response = await self._api_call_with_retry( response = await self._api_call_with_retry(
notion.pages.retrieve, notion.pages.retrieve,
page_id=page_id page_id=page_id
@ -1119,7 +1055,7 @@ class NotionHistoryConnector:
"page_id": page_id, "page_id": page_id,
"url": page_url, "url": page_url,
"title": page_title, "title": page_title,
"message": f"Updated Notion page '{page_title}'", "message": f"Updated Notion page '{page_title}' (content appended)",
} }
except APIResponseError as e: except APIResponseError as e:

View file

@ -140,7 +140,6 @@ class NotionToolMetadataService:
"account": account.to_dict(), "account": account.to_dict(),
"page_id": page_id, "page_id": page_id,
"current_title": document.title, "current_title": document.title,
"current_content": document.content,
"document_id": document.id, "document_id": document.id,
"indexed_at": document.document_metadata.get("indexed_at"), "indexed_at": document.document_metadata.get("indexed_at"),
} }

View file

@ -38,7 +38,6 @@ interface InterruptResult {
}; };
page_id?: string; page_id?: string;
current_title?: string; current_title?: string;
current_content?: string;
document_id?: number; document_id?: number;
indexed_at?: string; indexed_at?: string;
error?: string; error?: string;
@ -102,7 +101,6 @@ function ApprovalCard({
const account = interruptData.context?.account; const account = interruptData.context?.account;
const currentTitle = interruptData.context?.current_title; const currentTitle = interruptData.context?.current_title;
const currentContent = interruptData.context?.current_content;
// Title is not editable, so it's always valid // Title is not editable, so it's always valid
const isTitleValid = true; const isTitleValid = true;
@ -220,7 +218,7 @@ function ApprovalCard({
id="notion-content" id="notion-content"
value={String(editedArgs.content ?? "")} value={String(editedArgs.content ?? "")}
onChange={(e) => setEditedArgs({ ...editedArgs, content: e.target.value || null })} onChange={(e) => setEditedArgs({ ...editedArgs, content: e.target.value || null })}
placeholder={currentContent || "Enter new content"} placeholder="Enter content to append to the page"
rows={isFullScreen ? undefined : 12} rows={isFullScreen ? undefined : 12}
className={`resize-none ${isFullScreen ? "flex-1 min-h-0" : ""}`} className={`resize-none ${isFullScreen ? "flex-1 min-h-0" : ""}`}
/> />
@ -406,7 +404,7 @@ function SuccessCard({ result }: { result: SuccessResult }) {
} }
export const UpdateNotionPageToolUI = makeAssistantToolUI< export const UpdateNotionPageToolUI = makeAssistantToolUI<
{ page_id: string; title?: string | null; content?: string | null }, { page_id: string; content: string },
UpdateNotionPageResult UpdateNotionPageResult
>({ >({
toolName: "update_notion_page", toolName: "update_notion_page",