mirror of
https://github.com/MODSetter/SurfSense.git
synced 2026-07-22 23:31:12 +02:00
Refactor update_notion_page to append-only with simplified parameters
This commit is contained in:
parent
0d1b61d7e6
commit
9411edf057
5 changed files with 34 additions and 115 deletions
|
|
@ -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', '')}")
|
||||||
|
|
|
||||||
|
|
@ -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"],
|
||||||
|
|
|
||||||
|
|
@ -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:
|
||||||
|
|
|
||||||
|
|
@ -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"),
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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",
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue