@@ -1797,7 +1797,7 @@ def _pick_layout_for_slots(prs, anchor_slide, needs_title, needs_body): # ADD
17971797 return anchor_slide .slide_layout if anchor_slide else prs .slide_layouts [- 1 ]
17981798
17991799def _collect_needs (edit_items ): # ADD
1800- needs = {} # "n0" -> {"title": bool, "body": bool}
1800+ needs = {}
18011801 for tgt , _ in edit_items :
18021802 if not isinstance (tgt , str ):
18031803 continue
@@ -1809,8 +1809,6 @@ def _collect_needs(edit_items): # ADD
18091809 return needs
18101810
18111811
1812- # ... existing code ...
1813-
18141812@mcp .tool ()
18151813def edit_document (
18161814 file_id : str ,
@@ -2262,8 +2260,6 @@ def edit_document(
22622260 ensure_ascii = False
22632261 )
22642262
2265- # ... existing code ...
2266-
22672263@mcp .tool (
22682264 name = "review_document" ,
22692265 title = "Review and comment on various document types" ,
@@ -2300,6 +2296,15 @@ def review_document(
23002296 try :
23012297 doc = Document (user_file )
23022298 paragraphs = list (doc .paragraphs )
2299+ para_by_xml_id = {}
2300+ para_id_counter = 1
2301+
2302+ for para in doc .paragraphs :
2303+ text = para .text .strip ()
2304+ if not text :
2305+ continue
2306+ para_by_xml_id [para_id_counter ] = para
2307+ para_id_counter += 1
23032308
23042309 for index , comment_text in review_comments :
23052310 if isinstance (index , int ) and 0 <= index < len (paragraphs ):
@@ -2314,6 +2319,34 @@ def review_document(
23142319 )
23152320 except Exception :
23162321 para .add_run (f" [AI Comment: { comment_text } ]" )
2322+ elif isinstance (index , str ) and index .startswith ("pid:" ):
2323+ try :
2324+ para_xml_id = int (index .split (":" )[1 ])
2325+ para = para_by_xml_id .get (para_xml_id )
2326+ if para and para .runs :
2327+ try :
2328+ doc .add_comment (
2329+ runs = [para .runs [0 ]],
2330+ text = comment_text ,
2331+ author = "AI Reviewer" ,
2332+ initials = "AI"
2333+ )
2334+ except Exception :
2335+ para .add_run (f" [AI Comment: { comment_text } ]" )
2336+ except Exception :
2337+ # Fallback to paragraph index if para_xml_id not found
2338+ if isinstance (index , int ) and 0 <= index < len (paragraphs ):
2339+ para = paragraphs [index ]
2340+ if para .runs :
2341+ try :
2342+ doc .add_comment (
2343+ runs = [para .runs [0 ]],
2344+ text = comment_text ,
2345+ author = "AI Reviewer" ,
2346+ initials = "AI"
2347+ )
2348+ except Exception :
2349+ para .add_run (f" [AI Comment: { comment_text } ]" )
23172350 reviewed_path = os .path .join (
23182351 temp_folder , f"{ os .path .splitext (file_name )[0 ]} _reviewed.docx"
23192352 )
@@ -2333,9 +2366,11 @@ def review_document(
23332366
23342367 for index , comment_text in review_comments :
23352368 try :
2369+ # Handle both old format (integer) and new format (cell reference)
23362370 if isinstance (index , str ) and re .match (r"^[A-Z]+[0-9]+$" , index .strip ().upper ()):
23372371 cell_ref = index .strip ().upper ()
23382372 elif isinstance (index , int ):
2373+ # For backward compatibility, treat integer as row number
23392374 cell_ref = f"A{ index + 1 } "
23402375 else :
23412376 cell_ref = "A1"
@@ -2344,6 +2379,7 @@ def review_document(
23442379 add_auto_sized_review_comment (cell , comment_text , author = "AI Reviewer" )
23452380
23462381 except Exception :
2382+ # Fallback to A1 if error
23472383 fallback_cell = ws ["A1" ]
23482384 add_auto_sized_review_comment (fallback_cell , comment_text , author = "AI Reviewer" )
23492385
@@ -2362,8 +2398,12 @@ def review_document(
23622398 elif file_type == "pptx" :
23632399 try :
23642400 prs = Presentation (user_file )
2365-
2401+ # Get document structure to understand how to map comments
2402+ # For now, we'll use the existing logic but with better handling
2403+ slides_by_id = {int (s .slide_id ): s for s in prs .slides }
2404+
23662405 for index , comment_text in review_comments :
2406+ # Handle both old format (integer) and new format (slide_id)
23672407 if isinstance (index , int ) and 0 <= index < len (prs .slides ):
23682408 slide = prs .slides [index ]
23692409 left = top = Inches (0.2 )
@@ -2374,6 +2414,32 @@ def review_document(
23742414 p = text_frame .add_paragraph ()
23752415 p .text = f"AI Reviewer: { comment_text } "
23762416 p .font .size = PptPt (10 )
2417+ elif isinstance (index , str ) and index .startswith ("sid:" ):
2418+ # New format: using slide_id
2419+ try :
2420+ slide_id = int (index .split (":" )[1 ])
2421+ slide = slides_by_id .get (slide_id )
2422+ if slide :
2423+ left = top = Inches (0.2 )
2424+ width = Inches (4 )
2425+ height = Inches (1 )
2426+ textbox = slide .shapes .add_textbox (left , top , width , height )
2427+ text_frame = textbox .text_frame
2428+ p = text_frame .add_paragraph ()
2429+ p .text = f"AI Reviewer: { comment_text } "
2430+ p .font .size = PptPt (10 )
2431+ except Exception :
2432+ # Fallback to slide index if slide_id not found
2433+ if isinstance (index , int ) and 0 <= index < len (prs .slides ):
2434+ slide = prs .slides [index ]
2435+ left = top = Inches (0.2 )
2436+ width = Inches (4 )
2437+ height = Inches (1 )
2438+ textbox = slide .shapes .add_textbox (left , top , width , height )
2439+ text_frame = textbox .text_frame
2440+ p = text_frame .add_paragraph ()
2441+ p .text = f"AI Reviewer: { comment_text } "
2442+ p .font .size = PptPt (10 )
23772443
23782444 reviewed_path = os .path .join (
23792445 temp_folder , f"{ os .path .splitext (file_name )[0 ]} _reviewed.pptx"
@@ -2494,4 +2560,4 @@ def generate_and_archive(files_data: list[dict], archive_format: str = "zip", ar
24942560
24952561if __name__ == "__main__" :
24962562 log .info (f"Starting File Export builtin MCPO v{ SCRIPT_VERSION } " )
2497- mcp .run ()
2563+ mcp .run ()
0 commit comments