#!/usr/bin/env python3 """ Test script for the Document Editor Agent Demonstrates Cline-like document editing with HTML """ import asyncio import os import sys from dotenv import load_dotenv # Load environment variables load_dotenv() # Add parent directory to path sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))) from langchain_openai import ChatOpenAI from agents.doc_editor import DocumentEditorAgent # Example HTML document - Service Contract SAMPLE_CONTRACT = """ Contrat de prestation de services

CONTRAT DE PRESTATION DE SERVICES

Article 1 - Objet

Le présent contrat a pour objet de définir les conditions dans lesquelles la Société X (ci-après « le Prestataire ») s'engage à fournir des services à la Société Y (ci-après « le Client »).

Article 2 - Durée

Le contrat prend effet le 1er janvier 2026 pour une durée de 12 mois.

Article 3 - Tarification

Les services sont facturés selon les conditions suivantes :

Service Tarif
Consultation 200€/heure
Audit 500€/jour
""" async def test_document_editor(): """Test document editor agent with sample contract.""" # Initialize LLM (requires OPENAI_API_KEY environment variable) api_key = os.getenv("OPENAI_API_KEY") or os.getenv("CEREBRAS_API_KEY") if not api_key: print("❌ Error: OPENAI_API_KEY or CEREBRAS_API_KEY environment variable not set") return llm = ChatOpenAI( model=os.getenv("LLM_MODEL", "gpt-4o-mini"), temperature=0, api_key=api_key, base_url=os.getenv("OPENAI_API_BASE", None) ) # Initialize document editor agent doc_editor = DocumentEditorAgent(llm=llm, llm_tool_calling=llm) print("=" * 80) print("📄 ORIGINAL DOCUMENT (HTML)") print("=" * 80) print(SAMPLE_CONTRACT) print("\n") # Test 1: Simple text replacement print("=" * 80) print("🔧 TEST 1: Change contract duration from 12 to 24 months") print("=" * 80) result1 = await doc_editor.edit_document( doc_text=SAMPLE_CONTRACT, user_instruction="Change the contract duration from 12 months to 24 months in Article 2", doc_summaries=["Service contract between Company X and Company Y"], max_iterations=5 ) print(f"✅ Success: {result1['success']}") print(f"📝 Message: {result1['message']}") print(f"🔄 Iterations: {result1['iteration_count']}") if result1['success']: print("\n📄 MODIFIED DOCUMENT:") print(result1['doc_text']) # Update for next test current_doc = result1['doc_text'] else: current_doc = SAMPLE_CONTRACT print("\n" + "=" * 80) print("🔧 TEST 2: Add Article 4 about confidentiality") print("=" * 80) result2 = await doc_editor.edit_document( doc_text=current_doc, user_instruction="Add a new Article 4 after Article 3 that covers confidentiality with a heading 'Article 4 - Confidentialité' and a paragraph explaining that all information exchanged remains confidential", doc_summaries=["Service contract between Company X and Company Y"], max_iterations=8 ) print(f"✅ Success: {result2['success']}") print(f"📝 Message: {result2['message']}") print(f"🔄 Iterations: {result2['iteration_count']}") if result2['success']: print("\n📄 MODIFIED DOCUMENT:") print(result2['doc_text']) print("\n" + "=" * 80) print("✅ TESTS COMPLETED") print("=" * 80) async def test_tools_directly(): """Test document editor tools directly without the agent.""" from utils.editor_tools import replace_html, add_html, delete_html, view_current_document, attempt_completion print("=" * 80) print("🔧 TESTING TOOLS DIRECTLY") print("=" * 80) current_doc = SAMPLE_CONTRACT # Test 1: replace_html print("\n1️⃣ Testing 'replace_html' tool...") result = await replace_html.ainvoke({ "doc_text": current_doc, "search": "12 mois", "replace": "24 mois", "expected_matches": 1 }) if result['ok']: print(f"✅ Replace successful! Found {result['matches']} matches") current_doc = result['doc_text'] else: print(f"❌ Replace failed: {result['error']}") # Test 2: add_html print("\n2️⃣ Testing 'add_html' tool...") result = await add_html.ainvoke({ "doc_text": current_doc, "anchor_search": "

Article 1 - Objet

", "insert": "

Article ajouté : Ceci est un nouveau paragraphe inséré avant Article 1.

", "position": "before", "expected_matches": 1 }) if result['ok']: print(f"✅ Add successful! Inserted before anchor") current_doc = result['doc_text'] else: print(f"❌ Add failed: {result['error']}") # Test 3: delete_html print("\n3️⃣ Testing 'delete_html' tool...") result = await delete_html.ainvoke({ "doc_text": current_doc, "search": "
  • Renouvellement tacite
  • ", "expected_matches": 1 }) if result['ok']: print(f"✅ Delete successful! Removed {result['matches']} element") current_doc = result['doc_text'] else: print(f"❌ Delete failed: {result['error']}") print("\n4️⃣ Testing 'view_current_document' tool...") # Note: The tool now has no parameters - document is injected by the workflow result = await view_current_document.ainvoke() if result['ok']: print(f"✅ view_current_document works!") else: print(f"❌ view_current_document failed") print("\n5️⃣ Final document after tool tests:") print(current_doc) # Test 6: attempt_completion print("\n6️⃣ Testing 'attempt_completion' tool...") result = await attempt_completion.ainvoke({ "message": "Successfully modified the HTML document" }) print(f"✅ Completion: {result}") if __name__ == "__main__": print("🚀 Document Editor Agent Test Suite\n") # Test tools directly first (simpler, no LLM needed) print("\n" + "=" * 80) print("PART 1: Testing Tools Directly") print("=" * 80) asyncio.run(test_tools_directly()) # Test full agent workflow (requires LLM) print("\n\n" + "=" * 80) print("PART 2: Testing Full Agent Workflow (requires OPENAI_API_KEY or CEREBRAS_API_KEY)") print("=" * 80) print("Note: This part requires API key environment variable") print("=" * 80 + "\n") asyncio.run(test_document_editor())