memra 0.2.13__py3-none-any.whl → 0.2.15__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. memra/cli.py +322 -51
  2. {memra-0.2.13.dist-info → memra-0.2.15.dist-info}/METADATA +1 -1
  3. {memra-0.2.13.dist-info → memra-0.2.15.dist-info}/RECORD +7 -61
  4. memra-0.2.15.dist-info/top_level.txt +1 -0
  5. memra-0.2.13.dist-info/top_level.txt +0 -4
  6. memra-ops/app.py +0 -808
  7. memra-ops/config/config.py +0 -25
  8. memra-ops/config.py +0 -34
  9. memra-ops/logic/__init__.py +0 -1
  10. memra-ops/logic/file_tools.py +0 -43
  11. memra-ops/logic/invoice_tools.py +0 -668
  12. memra-ops/logic/invoice_tools_fix.py +0 -66
  13. memra-ops/mcp_bridge_server.py +0 -1178
  14. memra-ops/scripts/check_database.py +0 -37
  15. memra-ops/scripts/clear_database.py +0 -48
  16. memra-ops/scripts/monitor_database.py +0 -67
  17. memra-ops/scripts/release.py +0 -133
  18. memra-ops/scripts/reset_database.py +0 -65
  19. memra-ops/scripts/start_memra.py +0 -334
  20. memra-ops/scripts/stop_memra.py +0 -132
  21. memra-ops/server_tool_registry.py +0 -190
  22. memra-ops/tests/test_llm_text_to_sql.py +0 -115
  23. memra-ops/tests/test_llm_vs_pattern.py +0 -130
  24. memra-ops/tests/test_mcp_schema_aware.py +0 -124
  25. memra-ops/tests/test_schema_aware_sql.py +0 -139
  26. memra-ops/tests/test_schema_aware_sql_simple.py +0 -66
  27. memra-ops/tests/test_text_to_sql_demo.py +0 -140
  28. memra-ops/tools/mcp_bridge_server.py +0 -851
  29. memra-sdk/examples/accounts_payable.py +0 -215
  30. memra-sdk/examples/accounts_payable_client.py +0 -217
  31. memra-sdk/examples/accounts_payable_mcp.py +0 -200
  32. memra-sdk/examples/ask_questions.py +0 -123
  33. memra-sdk/examples/invoice_processing.py +0 -116
  34. memra-sdk/examples/propane_delivery.py +0 -87
  35. memra-sdk/examples/simple_text_to_sql.py +0 -158
  36. memra-sdk/memra/__init__.py +0 -31
  37. memra-sdk/memra/discovery.py +0 -15
  38. memra-sdk/memra/discovery_client.py +0 -49
  39. memra-sdk/memra/execution.py +0 -481
  40. memra-sdk/memra/models.py +0 -99
  41. memra-sdk/memra/tool_registry.py +0 -343
  42. memra-sdk/memra/tool_registry_client.py +0 -106
  43. memra-sdk/scripts/release.py +0 -133
  44. memra-sdk/setup.py +0 -52
  45. memra-workflows/accounts_payable/accounts_payable.py +0 -215
  46. memra-workflows/accounts_payable/accounts_payable_client.py +0 -216
  47. memra-workflows/accounts_payable/accounts_payable_mcp.py +0 -200
  48. memra-workflows/accounts_payable/accounts_payable_smart.py +0 -221
  49. memra-workflows/invoice_processing/invoice_processing.py +0 -116
  50. memra-workflows/invoice_processing/smart_invoice_processor.py +0 -220
  51. memra-workflows/logic/__init__.py +0 -1
  52. memra-workflows/logic/file_tools.py +0 -50
  53. memra-workflows/logic/invoice_tools.py +0 -501
  54. memra-workflows/logic/propane_agents.py +0 -52
  55. memra-workflows/mcp_bridge_server.py +0 -230
  56. memra-workflows/propane_delivery/propane_delivery.py +0 -87
  57. memra-workflows/text_to_sql/complete_invoice_workflow_with_queries.py +0 -208
  58. memra-workflows/text_to_sql/complete_text_to_sql_system.py +0 -266
  59. memra-workflows/text_to_sql/file_discovery_demo.py +0 -156
  60. {memra-0.2.13.dist-info → memra-0.2.15.dist-info}/LICENSE +0 -0
  61. {memra-0.2.13.dist-info → memra-0.2.15.dist-info}/WHEEL +0 -0
  62. {memra-0.2.13.dist-info → memra-0.2.15.dist-info}/entry_points.txt +0 -0
@@ -1,221 +0,0 @@
1
- #!/usr/bin/env python3
2
- """
3
- Smart Accounts Payable Example with File Discovery
4
- This example demonstrates intelligent file discovery and management
5
- """
6
-
7
- import os
8
- import sys
9
- import logging
10
- sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
11
-
12
- from memra import Agent, Department
13
- from memra.execution import ExecutionEngine
14
-
15
- # Set up environment
16
- os.environ['MEMRA_API_KEY'] = 'memra-prod-2024-001'
17
-
18
- # Set up logging
19
- logging.basicConfig(level=logging.INFO)
20
- logger = logging.getLogger(__name__)
21
-
22
- # Enhanced agents with smart file discovery
23
- etl_agent = Agent(
24
- role="Data Engineer",
25
- job="Extract invoice schema from Postgres database",
26
- sops=[
27
- "Connect to PostgresDB using credentials",
28
- "Query information_schema for invoices table",
29
- "Extract column names, types, and constraints",
30
- "Return schema as structured JSON"
31
- ],
32
- systems=["PostgresDB"],
33
- tools=[
34
- {"name": "DatabaseQueryTool", "hosted_by": "memra"}
35
- ],
36
- output_key="invoice_schema"
37
- )
38
-
39
- # Smart Invoice Parser with file discovery
40
- smart_parser_agent = Agent(
41
- role="Smart Invoice Parser",
42
- job="Extract structured data from invoice PDFs",
43
- sops=[
44
- "Load and process the invoice PDF file",
45
- "Convert to high-contrast images if needed",
46
- "Run OCR to extract text",
47
- "Use schema to identify and extract fields",
48
- "Validate extracted data against schema types",
49
- "Return structured invoice data"
50
- ],
51
- systems=["InvoiceStore"],
52
- tools=[
53
- {"name": "PDFProcessor", "hosted_by": "memra"},
54
- {"name": "OCRTool", "hosted_by": "memra"},
55
- {"name": "InvoiceExtractionWorkflow", "hosted_by": "memra"}
56
- ],
57
- input_keys=["file", "invoice_schema"], # file is the correct key
58
- output_key="invoice_data"
59
- )
60
-
61
- writer_agent = Agent(
62
- role="Data Entry Specialist",
63
- job="Write validated invoice data to Postgres database",
64
- sops=[
65
- "Validate invoice data completeness",
66
- "Map fields to database columns using schema",
67
- "Connect to PostgresDB",
68
- "Insert record into invoices table",
69
- "Return confirmation with record ID"
70
- ],
71
- systems=["PostgresDB"],
72
- tools=[
73
- {"name": "DataValidator", "hosted_by": "memra"},
74
- {"name": "PostgresInsert", "hosted_by": "memra"}
75
- ],
76
- input_keys=["invoice_data", "invoice_schema"],
77
- output_key="write_confirmation"
78
- )
79
-
80
- # Smart manager that handles file discovery workflow
81
- smart_manager_agent = Agent(
82
- role="Smart Accounts Payable Manager",
83
- job="Coordinate intelligent invoice processing with file discovery",
84
- sops=[
85
- "Check if specific file path was provided",
86
- "If no file specified, discover available files in invoices/ directory",
87
- "Handle file copying from external locations if needed",
88
- "Coordinate schema extraction and invoice processing",
89
- "Validate results and provide comprehensive reporting"
90
- ],
91
- allow_delegation=True,
92
- output_key="workflow_status"
93
- )
94
-
95
- # Create the smart department
96
- smart_ap_department = Department(
97
- name="Smart Accounts Payable",
98
- mission="Intelligently discover and process invoices with minimal user input",
99
- agents=[etl_agent, smart_parser_agent, writer_agent],
100
- manager_agent=smart_manager_agent,
101
- workflow_order=["Data Engineer", "Smart Invoice Parser", "Data Entry Specialist"],
102
- dependencies=["PostgresDB", "InvoiceStore", "FileSystem"],
103
- execution_policy={
104
- "retry_on_fail": True,
105
- "max_retries": 2,
106
- "halt_on_validation_error": True,
107
- "timeout_seconds": 300
108
- },
109
- context={
110
- "company_id": "acme_corp",
111
- "fiscal_year": "2024",
112
- "default_invoice_dir": "invoices",
113
- "mcp_bridge_url": "http://localhost:8081",
114
- "mcp_bridge_secret": "test-secret-for-development"
115
- }
116
- )
117
-
118
- def main():
119
- print("🧠 Smart Accounts Payable with File Discovery")
120
- print("=" * 60)
121
-
122
- # Create execution engine
123
- engine = ExecutionEngine()
124
-
125
- # Example 1: Auto-discovery mode (no file specified)
126
- print("\n📂 Example 1: Auto-discovery mode")
127
- print("Scanning invoices/ directory for available files...")
128
-
129
- input_data_auto = {
130
- "file": "invoices/10352259310.PDF", # Default file for auto-discovery demo
131
- "connection": "postgresql://tarpus@localhost:5432/memra_invoice_db"
132
- }
133
-
134
- result = engine.execute_department(smart_ap_department, input_data_auto)
135
-
136
- if result.success:
137
- print("✅ Auto-discovery workflow completed successfully!")
138
- display_results(result)
139
- else:
140
- print(f"❌ Auto-discovery failed: {result.error}")
141
-
142
- print("\n" + "="*60)
143
-
144
- # Example 2: External file mode
145
- print("\n📁 Example 2: External file processing")
146
- print("Processing file from external location...")
147
-
148
- input_data_external = {
149
- "file": "invoices/10352259310.PDF", # Use existing file for demo
150
- "connection": "postgresql://tarpus@localhost:5432/memra_invoice_db"
151
- }
152
-
153
- result = engine.execute_department(smart_ap_department, input_data_external)
154
-
155
- if result.success:
156
- print("✅ External file workflow completed successfully!")
157
- display_results(result)
158
- else:
159
- print(f"❌ External file processing failed: {result.error}")
160
-
161
- print("\n" + "="*60)
162
-
163
- # Example 3: Specific file mode
164
- print("\n🎯 Example 3: Specific file processing")
165
- print("Processing specific file from invoices/ directory...")
166
-
167
- input_data_specific = {
168
- "file": "invoices/10352259310.PDF", # Specific file
169
- "connection": "postgresql://tarpus@localhost:5432/memra_invoice_db"
170
- }
171
-
172
- result = engine.execute_department(smart_ap_department, input_data_specific)
173
-
174
- if result.success:
175
- print("✅ Specific file workflow completed successfully!")
176
- display_results(result)
177
- else:
178
- print(f"❌ Specific file processing failed: {result.error}")
179
-
180
- def display_results(result):
181
- """Display comprehensive workflow results"""
182
-
183
- # Show manager validation results
184
- if 'workflow_status' in result.data:
185
- manager_report = result.data['workflow_status']
186
- print(f"\n🔍 Manager Report:")
187
- print(f"Status: {manager_report.get('validation_status', 'unknown')}")
188
- print(f"Summary: {manager_report.get('summary', 'No summary available')}")
189
-
190
- # Show agent performance
191
- if 'agent_performance' in manager_report:
192
- print(f"\n📊 Agent Performance:")
193
- for agent_role, performance in manager_report['agent_performance'].items():
194
- work_quality = performance['work_quality']
195
- status_emoji = "✅" if work_quality == "real" else "🔄"
196
- print(f"{status_emoji} {agent_role}: {performance['status']}")
197
- if performance['tools_real_work']:
198
- print(f" Real work: {', '.join(performance['tools_real_work'])}")
199
-
200
- # Show file discovery results
201
- if 'invoice_data' in result.data:
202
- invoice_data = result.data['invoice_data']
203
- if isinstance(invoice_data, dict) and 'file_metadata' in invoice_data:
204
- print(f"\n📄 File Processing:")
205
- metadata = invoice_data['file_metadata']
206
- print(f"Processed: {metadata.get('filename', 'unknown')}")
207
- print(f"Location: {metadata.get('path', 'unknown')}")
208
- print(f"Size: {metadata.get('size', 'unknown')}")
209
-
210
- # Show database results
211
- if 'write_confirmation' in result.data:
212
- confirmation = result.data['write_confirmation']
213
- if isinstance(confirmation, dict) and 'record_id' in confirmation:
214
- print(f"\n💾 Database: Record ID {confirmation['record_id']}")
215
-
216
- # Show execution trace
217
- print(f"\n🔄 Execution: {', '.join(result.trace.agents_executed)}")
218
- print(f"🛠 Tools: {', '.join(result.trace.tools_invoked)}")
219
-
220
- if __name__ == "__main__":
221
- main()
@@ -1,116 +0,0 @@
1
- from memra import Agent, Department, LLM
2
-
3
- # Define LLMs that agents can use
4
- default_llm = LLM(model="gpt-4", temperature=0.1)
5
- parsing_llm = LLM(model="claude-3-opus", temperature=0) # More accurate for structured extraction
6
- manager_llm = LLM(model="gpt-4-turbo", temperature=0.3) # Balanced for decision-making
7
-
8
- # Define agents with specific LLMs
9
- etl_agent = Agent(
10
- role="Data Engineer",
11
- job="Extract invoice schema from Postgres database",
12
- llm=default_llm, # Standard LLM for SQL generation
13
- sops=[
14
- "Connect to PostgresDB using credentials",
15
- "Query information_schema for invoices table",
16
- "Extract column names, types, and constraints",
17
- "Return schema as structured JSON"
18
- ],
19
- systems=["PostgresDB"],
20
- tools=[
21
- {"name": "DatabaseQueryTool", "hosted_by": "memra"}
22
- ],
23
- output_key="invoice_schema"
24
- )
25
-
26
- parser_agent = Agent(
27
- role="Invoice Parser",
28
- job="Extract structured data from invoice PDF using schema",
29
- llm=parsing_llm, # High-accuracy LLM for document parsing
30
- sops=[
31
- "Load invoice PDF file",
32
- "Convert to high-contrast images if needed",
33
- "Run OCR to extract text",
34
- "Use schema to identify and extract fields",
35
- "Validate extracted data against schema types",
36
- "Return structured invoice data"
37
- ],
38
- systems=["InvoiceStore"],
39
- tools=[
40
- {"name": "PDFProcessor", "hosted_by": "memra"},
41
- {"name": "OCRTool", "hosted_by": "memra"},
42
- {"name": "InvoiceExtractionWorkflow", "hosted_by": "memra"}
43
- ],
44
- input_keys=["file", "invoice_schema"],
45
- output_key="invoice_data"
46
- )
47
-
48
- writer_agent = Agent(
49
- role="Data Entry Specialist",
50
- job="Write validated invoice data to Postgres database",
51
- llm=default_llm,
52
- sops=[
53
- "Validate invoice data completeness",
54
- "Map fields to database columns using schema",
55
- "Connect to PostgresDB",
56
- "Insert record into invoices table",
57
- "Return confirmation with record ID"
58
- ],
59
- systems=["PostgresDB"],
60
- tools=[
61
- {"name": "DataValidator", "hosted_by": "memra"},
62
- {"name": "PostgresInsert", "hosted_by": "mcp"}
63
- ],
64
- input_keys=["invoice_data", "invoice_schema"],
65
- output_key="write_confirmation"
66
- )
67
-
68
- # Manager with its own LLM
69
- manager_agent = Agent(
70
- role="Accounts Payable Manager",
71
- job="Coordinate invoice processing pipeline and handle exceptions",
72
- llm=manager_llm, # Manager gets a more flexible LLM
73
- sops=[
74
- "Check if schema extraction succeeded",
75
- "If schema missing, delegate to Schema Loader",
76
- "Validate parsed invoice has required fields",
77
- "Ensure invoice total matches line items before DB write",
78
- "Handle and log any errors with appropriate escalation"
79
- ],
80
- allow_delegation=True,
81
- fallback_agents={
82
- "Data Engineer": "Schema Loader"
83
- },
84
- output_key="workflow_status"
85
- )
86
-
87
- # Create the Accounts Payable Department
88
- ap_department = Department(
89
- name="Accounts Payable",
90
- mission="Process invoices accurately into financial system per company data standards",
91
- agents=[etl_agent, parser_agent, writer_agent],
92
- manager_agent=manager_agent,
93
- default_llm=default_llm, # Fallback for any agent without explicit LLM
94
- workflow_order=["Data Engineer", "Invoice Parser", "Data Entry Specialist"]
95
- )
96
-
97
- # Example usage
98
- if __name__ == "__main__":
99
- from memra.execution import ExecutionEngine
100
-
101
- # This is how a developer would use the department
102
- engine = ExecutionEngine()
103
- input_data = {
104
- "file": "path/to/invoice.pdf",
105
- "connection": "postgres://ap_user:password@localhost:5432/finance"
106
- }
107
-
108
- result = engine.execute_department(ap_department, input_data)
109
-
110
- if result.success:
111
- print("✅ Invoice processing completed!")
112
- print(f"Result: {result.data}")
113
- else:
114
- print(f"❌ Processing failed: {result.error}")
115
-
116
- print(f"Workflow result: {result}")
@@ -1,220 +0,0 @@
1
- #!/usr/bin/env python3
2
- """
3
- Smart Invoice Processor with Intelligent File Discovery
4
-
5
- This system automatically:
6
- 1. Empty invoices/ directory → Ask user for file path
7
- 2. Single file in invoices/ → Process it automatically
8
- 3. Multiple files in invoices/ → Show list, let user choose or batch process
9
- """
10
-
11
- import os
12
- import sys
13
- import glob
14
- from pathlib import Path
15
-
16
- sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
17
-
18
- from memra import Agent, Department, ExecutionEngine
19
-
20
- # Set up environment
21
- os.environ['MEMRA_API_KEY'] = 'memra-prod-2024-001'
22
-
23
- def discover_invoice_files():
24
- """Discover invoice files in the invoices directory"""
25
- invoice_dir = Path("invoices")
26
- if not invoice_dir.exists():
27
- invoice_dir.mkdir()
28
- return []
29
-
30
- # Look for PDF files
31
- pdf_files = list(invoice_dir.glob("*.pdf")) + list(invoice_dir.glob("*.PDF"))
32
- return [str(f) for f in pdf_files]
33
-
34
- def get_file_to_process():
35
- """Intelligent file discovery logic"""
36
- files = discover_invoice_files()
37
-
38
- if len(files) == 0:
39
- print("📂 The invoices/ directory is empty.")
40
- print("Please provide the path to the invoice you want to process:")
41
- file_path = input("File path: ").strip()
42
-
43
- if not file_path:
44
- print("❌ No file path provided.")
45
- return None
46
-
47
- if not os.path.exists(file_path):
48
- print(f"❌ File not found: {file_path}")
49
- return None
50
-
51
- # Copy file to invoices directory
52
- import shutil
53
- filename = os.path.basename(file_path)
54
- dest_path = f"invoices/{filename}"
55
- shutil.copy2(file_path, dest_path)
56
- print(f"📁 Copied {filename} to invoices/ directory")
57
- return dest_path
58
-
59
- elif len(files) == 1:
60
- print(f"📄 Found 1 invoice file: {files[0]}")
61
- print("🚀 Processing automatically...")
62
- return files[0]
63
-
64
- else:
65
- print(f"📄 Found {len(files)} invoice files:")
66
- for i, file in enumerate(files, 1):
67
- filename = os.path.basename(file)
68
- size = os.path.getsize(file)
69
- size_kb = size // 1024
70
- print(f" {i}. {filename} ({size_kb}KB)")
71
-
72
- print("\nOptions:")
73
- print(" • Enter a number (1-{}) to process that file".format(len(files)))
74
- print(" • Enter 'all' to process all files in batch")
75
- print(" • Enter 'quit' to exit")
76
-
77
- choice = input("Your choice: ").strip().lower()
78
-
79
- if choice == 'quit':
80
- return None
81
- elif choice == 'all':
82
- return 'batch'
83
- else:
84
- try:
85
- index = int(choice) - 1
86
- if 0 <= index < len(files):
87
- return files[index]
88
- else:
89
- print("❌ Invalid selection")
90
- return None
91
- except ValueError:
92
- print("❌ Invalid input")
93
- return None
94
-
95
- def create_invoice_processing_department():
96
- """Create the invoice processing department"""
97
-
98
- # Schema extraction agent
99
- schema_agent = Agent(
100
- role="Schema Engineer",
101
- job="Extract invoice database schema",
102
- tools=[
103
- {"name": "DatabaseQueryTool", "hosted_by": "memra"}
104
- ],
105
- output_key="invoice_schema"
106
- )
107
-
108
- # Invoice processing agent
109
- processor_agent = Agent(
110
- role="Invoice Processor",
111
- job="Extract structured data from invoice PDF",
112
- tools=[
113
- {"name": "PDFProcessor", "hosted_by": "memra"},
114
- {"name": "InvoiceExtractionWorkflow", "hosted_by": "memra"}
115
- ],
116
- input_keys=["file", "invoice_schema"],
117
- output_key="invoice_data"
118
- )
119
-
120
- # Database writer agent
121
- writer_agent = Agent(
122
- role="Database Writer",
123
- job="Insert validated invoice data into database",
124
- tools=[
125
- {"name": "DataValidator", "hosted_by": "mcp"},
126
- {"name": "PostgresInsert", "hosted_by": "mcp"}
127
- ],
128
- input_keys=["invoice_data", "invoice_schema"],
129
- output_key="write_confirmation"
130
- )
131
-
132
- return Department(
133
- name="Smart Invoice Processing",
134
- mission="Intelligently process invoices from PDF to database",
135
- agents=[schema_agent, processor_agent, writer_agent],
136
- workflow_order=["Schema Engineer", "Invoice Processor", "Database Writer"],
137
- context={
138
- "mcp_bridge_url": "http://localhost:8081",
139
- "mcp_bridge_secret": "test-secret-for-development"
140
- }
141
- )
142
-
143
- def process_single_invoice(file_path):
144
- """Process a single invoice file"""
145
- print(f"\n🔄 Processing: {os.path.basename(file_path)}")
146
- print("=" * 60)
147
-
148
- department = create_invoice_processing_department()
149
- engine = ExecutionEngine()
150
-
151
- input_data = {
152
- "file": file_path,
153
- "connection": "postgresql://tarpus@localhost:5432/memra_invoice_db"
154
- }
155
-
156
- result = engine.execute_department(department, input_data)
157
-
158
- if result.success:
159
- print(f"✅ Successfully processed {os.path.basename(file_path)}")
160
-
161
- # Show extracted data
162
- invoice_data = result.data.get('invoice_data', {})
163
- if 'headerSection' in invoice_data:
164
- vendor = invoice_data['headerSection'].get('vendorName', 'Unknown')
165
- print(f"🏢 Vendor: {vendor}")
166
-
167
- # Show database result
168
- confirmation = result.data.get('write_confirmation', {})
169
- if 'record_id' in confirmation:
170
- print(f"💾 Database Record ID: {confirmation['record_id']}")
171
- elif confirmation.get('_mock'):
172
- print("🔄 Database: Mock insertion (MCP bridge issue)")
173
-
174
- return True
175
- else:
176
- print(f"❌ Failed to process {os.path.basename(file_path)}: {result.error}")
177
- return False
178
-
179
- def process_batch(file_list):
180
- """Process multiple invoice files in batch"""
181
- print(f"\n🔄 Batch Processing: {len(file_list)} files")
182
- print("=" * 60)
183
-
184
- results = []
185
- for i, file_path in enumerate(file_list, 1):
186
- print(f"\n📄 File {i}/{len(file_list)}: {os.path.basename(file_path)}")
187
- success = process_single_invoice(file_path)
188
- results.append((file_path, success))
189
-
190
- # Summary
191
- print(f"\n📊 Batch Processing Summary:")
192
- successful = sum(1 for _, success in results if success)
193
- print(f"✅ Successful: {successful}/{len(file_list)}")
194
-
195
- if successful < len(file_list):
196
- print("❌ Failed files:")
197
- for file_path, success in results:
198
- if not success:
199
- print(f" • {os.path.basename(file_path)}")
200
-
201
- def main():
202
- print("🧠 Smart Invoice Processor")
203
- print("Intelligent file discovery and processing")
204
- print("=" * 60)
205
-
206
- # Discover what to process
207
- target = get_file_to_process()
208
-
209
- if target is None:
210
- print("👋 Goodbye!")
211
- return
212
-
213
- if target == 'batch':
214
- files = discover_invoice_files()
215
- process_batch(files)
216
- else:
217
- process_single_invoice(target)
218
-
219
- if __name__ == "__main__":
220
- main()
@@ -1 +0,0 @@
1
- # Logic package - contains the actual implementation of tools and workflows
@@ -1,50 +0,0 @@
1
- from typing import Dict, Any
2
- import logging
3
- import json
4
- from pathlib import Path
5
-
6
- logger = logging.getLogger(__name__)
7
-
8
- class FileReader:
9
- """Tool for reading files from the filesystem"""
10
-
11
- def read_file(self, file_path: str) -> Dict[str, Any]:
12
- """Read a file and return its contents"""
13
- logger.info(f"Reading file: {file_path}")
14
- try:
15
- path = Path(file_path)
16
- if not path.exists():
17
- return {
18
- "success": False,
19
- "error": f"File not found: {file_path}"
20
- }
21
-
22
- with open(path, 'r') as f:
23
- content = f.read()
24
-
25
- # Try to parse as JSON if it's a .json file
26
- if path.suffix.lower() == '.json':
27
- try:
28
- parsed_content = json.loads(content)
29
- return {
30
- "success": True,
31
- "content": parsed_content,
32
- "raw_content": content
33
- }
34
- except json.JSONDecodeError as e:
35
- return {
36
- "success": False,
37
- "error": f"Invalid JSON: {str(e)}"
38
- }
39
-
40
- return {
41
- "success": True,
42
- "content": content
43
- }
44
-
45
- except Exception as e:
46
- logger.error(f"Error reading file {file_path}: {str(e)}")
47
- return {
48
- "success": False,
49
- "error": str(e)
50
- }