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
async def update_notion_page(
page_title: str,
new_title: str | None = None,
new_content: str | None = None,
content: str,
) -> 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
a Notion page. At least one of new_title or new_content must be provided.
Use this tool when the user asks you to add content to, modify, or update
a Notion page. The new content will be appended to the existing page content.
Args:
page_title: The current title of the Notion page to update (required).
new_title: New title for the page (optional).
new_content: New markdown content for the page body (optional).
If provided, replaces all existing content.
page_title: The title of the Notion page to update.
content: The markdown content to append to the page body (supports headings, lists, paragraphs).
Returns:
Dictionary with:
@ -54,17 +51,16 @@ def create_update_notion_page_tool(
- url: URL to the updated page (if success)
- title: Current page title (if success)
- message: Result message
IMPORTANT: If status is "rejected", the user explicitly declined the action.
Respond with a brief acknowledgment (e.g., "Understood, I didn't update the page.")
Respond with a brief acknowledgment (e.g., "Understood, I didn't update the page.")
and move on. Do NOT ask for alternatives or troubleshoot.
Examples:
- "Update the 'Meeting Notes' page with new title 'Updated Meeting Notes'"
- "Change the content of 'Project Plan' page to 'New content here'"
- "Update 'Weekly Report' with new title 'Final Report' and content '# Summary...'"
- "Add 'New meeting notes from today' to the 'Meeting Notes' page"
- "Append the following to 'Project Plan': '# Status Update\n\nCompleted phase 1'"
"""
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:
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.",
}
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 {
"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:
@ -103,8 +100,7 @@ def create_update_notion_page_tool(
"tool": "update_notion_page",
"params": {
"page_id": page_id,
"title": new_title,
"content": new_content,
"content": content,
"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_page_id = final_params.get("page_id", page_id)
final_title = final_params.get("title", new_title)
final_content = final_params.get("content", new_content)
final_content = final_params.get("content", content)
final_connector_id = final_params.get("connector_id", connector_id_from_context)
# Validate title if it's being updated
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}")
logger.info(f"Updating Notion page with final params: page_id={final_page_id}, has_content={final_content is not None}")
from sqlalchemy.future import select
@ -189,7 +176,6 @@ def create_update_notion_page_tool(
result = await notion_connector.update_page(
page_id=final_page_id,
title=final_title,
content=final_content,
)
logger.info(f"update_page result: {result.get('status')} - {result.get('message', '')}")

View file

@ -219,7 +219,7 @@ BUILTIN_TOOLS: list[ToolDefinition] = [
),
ToolDefinition(
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(
db_session=deps["db_session"],
search_space_id=deps["search_space_id"],

View file

@ -987,15 +987,16 @@ class NotionHistoryConnector:
}
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]:
"""
Update an existing Notion page.
Update an existing Notion page by appending new content.
Note: Content is appended to the page, not replaced.
Args:
page_id: Page ID to update
title: New page title (optional)
content: New page content in markdown (optional)
content: New markdown content to append to the page (optional)
Returns:
Dictionary with update result
@ -1006,31 +1007,13 @@ class NotionHistoryConnector:
try:
notion = await self._get_client()
# Update title 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
# Append content if provided
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:
children = self._markdown_to_blocks(content)
if not children:
logger.warning("No blocks generated from content, skipping update")
logger.warning("No blocks generated from content, skipping append")
return {
"status": "error",
"message": "Content conversion failed: no valid blocks generated",
@ -1042,25 +1025,7 @@ class NotionHistoryConnector:
"message": f"Failed to parse content: {e!s}",
}
# Store block count for logging
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.
# Append new content blocks
try:
for i in range(0, len(children), 100):
batch = children[i : i + 100]
@ -1069,44 +1034,15 @@ class NotionHistoryConnector:
block_id=page_id,
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:
# CRITICAL ERROR: Content was deleted but new content failed to add
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}")
logger.error(f"Failed to append content blocks: {e}")
return {
"status": "error",
"message": f"CRITICAL: Failed to update page content. Original content ({block_count} blocks) "
f"was deleted but new content could not be added: {e!s}",
"message": f"Failed to append content: {e!s}",
}
# Get updated page
# Get updated page info
response = await self._api_call_with_retry(
notion.pages.retrieve,
page_id=page_id
@ -1119,7 +1055,7 @@ class NotionHistoryConnector:
"page_id": page_id,
"url": page_url,
"title": page_title,
"message": f"Updated Notion page '{page_title}'",
"message": f"Updated Notion page '{page_title}' (content appended)",
}
except APIResponseError as e:

View file

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

View file

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