memra 0.2.4__py3-none-any.whl → 0.2.5__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.
- memra/__init__.py +16 -2
- memra/cli.py +286 -0
- memra/execution.py +217 -46
- memra/models.py +1 -0
- memra/tool_registry_client.py +2 -2
- memra-0.2.5.dist-info/METADATA +319 -0
- {memra-0.2.4.dist-info → memra-0.2.5.dist-info}/RECORD +24 -14
- memra-0.2.5.dist-info/entry_points.txt +2 -0
- memra-0.2.5.dist-info/licenses/LICENSE +21 -0
- memra-ops/app.py +98 -0
- memra-ops/logic/__init__.py +1 -0
- memra-ops/logic/file_tools.py +43 -0
- memra-ops/logic/invoice_tools.py +668 -0
- memra-ops/logic/invoice_tools_fix.py +66 -0
- memra-ops/mcp_bridge_server.py +1178 -0
- memra-ops/scripts/check_database.py +37 -0
- memra-ops/scripts/clear_database.py +48 -0
- memra-ops/scripts/monitor_database.py +67 -0
- memra-ops/scripts/reset_database.py +65 -0
- memra-ops/server_tool_registry.py +3 -1
- memra-sdk/memra/__init__.py +1 -1
- memra-sdk/setup.py +1 -1
- memra-0.2.4.dist-info/METADATA +0 -145
- memra-0.2.4.dist-info/entry_points.txt +0 -2
- memra-0.2.4.dist-info/licenses/LICENSE +0 -0
- {memra-0.2.4.dist-info → memra-0.2.5.dist-info}/WHEEL +0 -0
- {memra-0.2.4.dist-info → memra-0.2.5.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,37 @@
|
|
1
|
+
import psycopg2
|
2
|
+
from prettytable import PrettyTable
|
3
|
+
import time
|
4
|
+
|
5
|
+
def check_database():
|
6
|
+
# Connect to the Postgres database
|
7
|
+
conn = psycopg2.connect(
|
8
|
+
dbname="memra_invoice_db",
|
9
|
+
user="memra", # From docker-compose.yml
|
10
|
+
password="memra123", # From docker-compose.yml
|
11
|
+
host="localhost",
|
12
|
+
port=5432
|
13
|
+
)
|
14
|
+
|
15
|
+
# Create a cursor and run the query
|
16
|
+
cur = conn.cursor()
|
17
|
+
cur.execute("SELECT * FROM invoices ORDER BY created_at DESC LIMIT 10;")
|
18
|
+
rows = cur.fetchall()
|
19
|
+
columns = [desc[0] for desc in cur.description]
|
20
|
+
|
21
|
+
# Create and populate the pretty table
|
22
|
+
table = PrettyTable()
|
23
|
+
table.field_names = columns
|
24
|
+
for row in rows:
|
25
|
+
table.add_row(row)
|
26
|
+
|
27
|
+
# Print the table
|
28
|
+
print(f"\n📊 Current invoices in database (as of {time.strftime('%H:%M:%S')}):")
|
29
|
+
print(table)
|
30
|
+
print(f"Total rows: {len(rows)}")
|
31
|
+
|
32
|
+
# Clean up
|
33
|
+
cur.close()
|
34
|
+
conn.close()
|
35
|
+
|
36
|
+
if __name__ == "__main__":
|
37
|
+
check_database()
|
@@ -0,0 +1,48 @@
|
|
1
|
+
import psycopg2
|
2
|
+
|
3
|
+
def clear_database():
|
4
|
+
"""Clear all data from the invoices table"""
|
5
|
+
|
6
|
+
# Connect to the Postgres database
|
7
|
+
conn = psycopg2.connect(
|
8
|
+
dbname="memra_invoice_db",
|
9
|
+
user="memra", # From docker-compose.yml
|
10
|
+
password="memra123", # From docker-compose.yml
|
11
|
+
host="localhost",
|
12
|
+
port=5432
|
13
|
+
)
|
14
|
+
|
15
|
+
try:
|
16
|
+
# Create a cursor and run the query
|
17
|
+
cur = conn.cursor()
|
18
|
+
|
19
|
+
# First, let's see how many rows we have
|
20
|
+
cur.execute("SELECT COUNT(*) FROM invoices;")
|
21
|
+
count_before = cur.fetchone()[0]
|
22
|
+
print(f"📊 Current invoice count: {count_before}")
|
23
|
+
|
24
|
+
if count_before > 0:
|
25
|
+
# Clear all data from the invoices table
|
26
|
+
cur.execute("DELETE FROM invoices;")
|
27
|
+
conn.commit()
|
28
|
+
|
29
|
+
# Verify the deletion
|
30
|
+
cur.execute("SELECT COUNT(*) FROM invoices;")
|
31
|
+
count_after = cur.fetchone()[0]
|
32
|
+
|
33
|
+
print(f"🗑️ Deleted {count_before} invoice records")
|
34
|
+
print(f"📊 New invoice count: {count_after}")
|
35
|
+
print("✅ Database cleared successfully!")
|
36
|
+
else:
|
37
|
+
print("📊 Database is already empty")
|
38
|
+
|
39
|
+
cur.close()
|
40
|
+
|
41
|
+
except Exception as e:
|
42
|
+
print(f"❌ Error: {e}")
|
43
|
+
conn.rollback()
|
44
|
+
finally:
|
45
|
+
conn.close()
|
46
|
+
|
47
|
+
if __name__ == "__main__":
|
48
|
+
clear_database()
|
@@ -0,0 +1,67 @@
|
|
1
|
+
import psycopg2
|
2
|
+
from prettytable import PrettyTable
|
3
|
+
import time
|
4
|
+
import os
|
5
|
+
|
6
|
+
def monitor_database():
|
7
|
+
"""Continuously monitor the database for new invoice rows"""
|
8
|
+
|
9
|
+
# Connect to the Postgres database
|
10
|
+
conn = psycopg2.connect(
|
11
|
+
dbname="memra_invoice_db",
|
12
|
+
user="memra", # From docker-compose.yml
|
13
|
+
password="memra123", # From docker-compose.yml
|
14
|
+
host="localhost",
|
15
|
+
port=5432
|
16
|
+
)
|
17
|
+
|
18
|
+
print("🔍 Monitoring database for new invoice rows...")
|
19
|
+
print("Press Ctrl+C to stop monitoring\n")
|
20
|
+
|
21
|
+
last_count = 0
|
22
|
+
|
23
|
+
try:
|
24
|
+
while True:
|
25
|
+
# Create a cursor and run the query
|
26
|
+
cur = conn.cursor()
|
27
|
+
cur.execute("SELECT COUNT(*) FROM invoices;")
|
28
|
+
current_count = cur.fetchone()[0]
|
29
|
+
|
30
|
+
# Get the latest invoices
|
31
|
+
cur.execute("SELECT id, invoice_number, vendor_name, total_amount, created_at FROM invoices ORDER BY created_at DESC LIMIT 5;")
|
32
|
+
rows = cur.fetchall()
|
33
|
+
|
34
|
+
# Clear screen (works on Unix-like systems)
|
35
|
+
os.system('clear' if os.name == 'posix' else 'cls')
|
36
|
+
|
37
|
+
print(f"📊 Database Monitor - {time.strftime('%Y-%m-%d %H:%M:%S')}")
|
38
|
+
print(f"Total invoices: {current_count}")
|
39
|
+
|
40
|
+
if current_count > last_count:
|
41
|
+
print(f"🆕 New invoices detected! (+{current_count - last_count})")
|
42
|
+
last_count = current_count
|
43
|
+
|
44
|
+
if rows:
|
45
|
+
# Create and populate the pretty table
|
46
|
+
table = PrettyTable()
|
47
|
+
table.field_names = ["ID", "Invoice #", "Vendor", "Amount", "Created"]
|
48
|
+
for row in rows:
|
49
|
+
table.add_row(row)
|
50
|
+
print("\nLatest invoices:")
|
51
|
+
print(table)
|
52
|
+
else:
|
53
|
+
print("\nNo invoices found in database.")
|
54
|
+
|
55
|
+
print(f"\nMonitoring... (refresh every 2 seconds)")
|
56
|
+
cur.close()
|
57
|
+
time.sleep(2)
|
58
|
+
|
59
|
+
except KeyboardInterrupt:
|
60
|
+
print("\n\n🛑 Monitoring stopped by user.")
|
61
|
+
except Exception as e:
|
62
|
+
print(f"\n❌ Error: {e}")
|
63
|
+
finally:
|
64
|
+
conn.close()
|
65
|
+
|
66
|
+
if __name__ == "__main__":
|
67
|
+
monitor_database()
|
@@ -0,0 +1,65 @@
|
|
1
|
+
import psycopg2
|
2
|
+
|
3
|
+
def reset_database():
|
4
|
+
"""Clear all data from the invoices table and reset the sequence"""
|
5
|
+
|
6
|
+
# Connect to the Postgres database
|
7
|
+
conn = psycopg2.connect(
|
8
|
+
dbname="memra_invoice_db",
|
9
|
+
user="memra", # From docker-compose.yml
|
10
|
+
password="memra123", # From docker-compose.yml
|
11
|
+
host="localhost",
|
12
|
+
port=5432
|
13
|
+
)
|
14
|
+
|
15
|
+
try:
|
16
|
+
# Create a cursor and run the query
|
17
|
+
cur = conn.cursor()
|
18
|
+
|
19
|
+
# First, let's see how many rows we have and current sequence value
|
20
|
+
cur.execute("SELECT COUNT(*) FROM invoices;")
|
21
|
+
count_before = cur.fetchone()[0]
|
22
|
+
|
23
|
+
cur.execute("SELECT last_value FROM invoices_id_seq;")
|
24
|
+
sequence_before = cur.fetchone()[0]
|
25
|
+
|
26
|
+
print(f"📊 Current invoice count: {count_before}")
|
27
|
+
print(f"🔢 Current sequence value: {sequence_before}")
|
28
|
+
|
29
|
+
if count_before > 0:
|
30
|
+
# Clear all data from the invoices table
|
31
|
+
cur.execute("DELETE FROM invoices;")
|
32
|
+
|
33
|
+
# Reset the sequence to start from 1
|
34
|
+
cur.execute("ALTER SEQUENCE invoices_id_seq RESTART WITH 1;")
|
35
|
+
|
36
|
+
conn.commit()
|
37
|
+
|
38
|
+
# Verify the deletion and sequence reset
|
39
|
+
cur.execute("SELECT COUNT(*) FROM invoices;")
|
40
|
+
count_after = cur.fetchone()[0]
|
41
|
+
|
42
|
+
cur.execute("SELECT last_value FROM invoices_id_seq;")
|
43
|
+
sequence_after = cur.fetchone()[0]
|
44
|
+
|
45
|
+
print(f"🗑️ Deleted {count_before} invoice records")
|
46
|
+
print(f"🔄 Reset sequence from {sequence_before} to {sequence_after}")
|
47
|
+
print(f"📊 New invoice count: {count_after}")
|
48
|
+
print("✅ Database reset successfully!")
|
49
|
+
else:
|
50
|
+
print("📊 Database is already empty")
|
51
|
+
# Still reset the sequence
|
52
|
+
cur.execute("ALTER SEQUENCE invoices_id_seq RESTART WITH 1;")
|
53
|
+
conn.commit()
|
54
|
+
print("🔄 Reset sequence to start from 1")
|
55
|
+
|
56
|
+
cur.close()
|
57
|
+
|
58
|
+
except Exception as e:
|
59
|
+
print(f"❌ Error: {e}")
|
60
|
+
conn.rollback()
|
61
|
+
finally:
|
62
|
+
conn.close()
|
63
|
+
|
64
|
+
if __name__ == "__main__":
|
65
|
+
reset_database()
|
@@ -137,7 +137,9 @@ class ServerToolRegistry:
|
|
137
137
|
|
138
138
|
elif tool_name == "PDFProcessor":
|
139
139
|
file_path = input_data.get("file", "")
|
140
|
-
|
140
|
+
# Handle both "schema" and "invoice_schema" keys
|
141
|
+
schema = input_data.get("schema") or input_data.get("invoice_schema", {})
|
142
|
+
return tool_instance.process_pdf(file_path, schema)
|
141
143
|
|
142
144
|
elif tool_name == "OCRTool":
|
143
145
|
# Assume PDF processor output is passed as input
|
memra-sdk/memra/__init__.py
CHANGED
memra-sdk/setup.py
CHANGED
@@ -5,7 +5,7 @@ with open("README.md", "r", encoding="utf-8") as fh:
|
|
5
5
|
|
6
6
|
setup(
|
7
7
|
name="memra",
|
8
|
-
version="0.2.
|
8
|
+
version="0.2.4",
|
9
9
|
author="Memra",
|
10
10
|
author_email="support@memra.com",
|
11
11
|
description="Declarative framework for enterprise workflows with MCP integration - Client SDK",
|
memra-0.2.4.dist-info/METADATA
DELETED
@@ -1,145 +0,0 @@
|
|
1
|
-
Metadata-Version: 2.4
|
2
|
-
Name: memra
|
3
|
-
Version: 0.2.4
|
4
|
-
Summary: Declarative framework for enterprise workflows with MCP integration - Client SDK
|
5
|
-
Home-page: https://github.com/memra/memra-sdk
|
6
|
-
Author: Memra
|
7
|
-
Author-email: Memra <support@memra.com>
|
8
|
-
License: MIT
|
9
|
-
Project-URL: Homepage, https://memra.co
|
10
|
-
Project-URL: Repository, https://github.com/memra-platform/memra-sdk
|
11
|
-
Classifier: Development Status :: 3 - Alpha
|
12
|
-
Classifier: Intended Audience :: Developers
|
13
|
-
Classifier: License :: OSI Approved :: MIT License
|
14
|
-
Classifier: Operating System :: OS Independent
|
15
|
-
Classifier: Programming Language :: Python :: 3
|
16
|
-
Classifier: Programming Language :: Python :: 3.8
|
17
|
-
Classifier: Programming Language :: Python :: 3.9
|
18
|
-
Classifier: Programming Language :: Python :: 3.10
|
19
|
-
Classifier: Programming Language :: Python :: 3.11
|
20
|
-
Requires-Python: >=3.8
|
21
|
-
Description-Content-Type: text/markdown
|
22
|
-
License-File: LICENSE
|
23
|
-
Requires-Dist: pydantic>=1.8.0
|
24
|
-
Requires-Dist: httpx>=0.24.0
|
25
|
-
Requires-Dist: typing-extensions>=4.0.0
|
26
|
-
Requires-Dist: aiohttp>=3.8.0
|
27
|
-
Requires-Dist: aiohttp-cors>=0.7.0
|
28
|
-
Provides-Extra: dev
|
29
|
-
Requires-Dist: pytest>=6.0; extra == "dev"
|
30
|
-
Requires-Dist: pytest-asyncio; extra == "dev"
|
31
|
-
Requires-Dist: black; extra == "dev"
|
32
|
-
Requires-Dist: flake8; extra == "dev"
|
33
|
-
Provides-Extra: mcp
|
34
|
-
Requires-Dist: psycopg2-binary>=2.9.0; extra == "mcp"
|
35
|
-
Dynamic: author
|
36
|
-
Dynamic: home-page
|
37
|
-
Dynamic: license-file
|
38
|
-
Dynamic: requires-python
|
39
|
-
|
40
|
-
# Memra SDK
|
41
|
-
|
42
|
-
The core Memra framework for building AI-powered business workflows.
|
43
|
-
|
44
|
-
## Installation
|
45
|
-
|
46
|
-
```bash
|
47
|
-
pip install memra
|
48
|
-
```
|
49
|
-
|
50
|
-
## Quick Start
|
51
|
-
|
52
|
-
```python
|
53
|
-
from memra import Agent, Department, LLM, ExecutionEngine
|
54
|
-
|
55
|
-
# Define an agent
|
56
|
-
agent = Agent(
|
57
|
-
role="Data Analyst",
|
58
|
-
job="Analyze customer data",
|
59
|
-
llm=LLM(model="llama-3.2-11b-vision-preview"),
|
60
|
-
sops=["Load data", "Perform analysis", "Generate report"],
|
61
|
-
output_key="analysis_result"
|
62
|
-
)
|
63
|
-
|
64
|
-
# Create a department
|
65
|
-
department = Department(
|
66
|
-
name="Analytics",
|
67
|
-
mission="Provide data insights",
|
68
|
-
agents=[agent],
|
69
|
-
workflow_order=["Data Analyst"]
|
70
|
-
)
|
71
|
-
|
72
|
-
# Execute the workflow
|
73
|
-
engine = ExecutionEngine()
|
74
|
-
result = engine.execute_department(department, {"data": "customer_data.csv"})
|
75
|
-
```
|
76
|
-
|
77
|
-
## Core Components
|
78
|
-
|
79
|
-
### Agent
|
80
|
-
An AI worker that performs specific tasks using LLMs and tools.
|
81
|
-
|
82
|
-
### Department
|
83
|
-
A team of agents working together to accomplish a mission.
|
84
|
-
|
85
|
-
### ExecutionEngine
|
86
|
-
Orchestrates the execution of departments and their workflows.
|
87
|
-
|
88
|
-
### LLM
|
89
|
-
Configuration for language models used by agents.
|
90
|
-
|
91
|
-
## Examples
|
92
|
-
|
93
|
-
See the `examples/` directory for basic usage examples:
|
94
|
-
- `simple_text_to_sql.py` - Basic text-to-SQL conversion
|
95
|
-
- `ask_questions.py` - Simple question answering
|
96
|
-
|
97
|
-
## Documentation
|
98
|
-
|
99
|
-
For detailed documentation, visit [docs.memra.co](https://docs.memra.co)
|
100
|
-
|
101
|
-
Documentation is also available locally in the `examples/` directory.
|
102
|
-
|
103
|
-
## Example: Propane Delivery Workflow
|
104
|
-
|
105
|
-
See the `examples/propane_delivery.py` file for a complete example of how to use Memra to orchestrate a propane delivery workflow.
|
106
|
-
|
107
|
-
## 🔍 Smart File Discovery
|
108
|
-
|
109
|
-
Memra includes intelligent file discovery and management capabilities:
|
110
|
-
|
111
|
-
### File Discovery Tools
|
112
|
-
- **FileDiscovery**: Automatically scan directories for files matching patterns
|
113
|
-
- **FileCopy**: Copy files from external locations to standard processing directories
|
114
|
-
- **Smart Routing**: Automatically handle file paths and directory management
|
115
|
-
|
116
|
-
### Example: Smart Invoice Processing
|
117
|
-
```python
|
118
|
-
from memra import Agent
|
119
|
-
|
120
|
-
# Smart agent that discovers and processes files automatically
|
121
|
-
smart_parser = Agent(
|
122
|
-
role="Smart Invoice Parser",
|
123
|
-
job="Discover and process invoice files intelligently",
|
124
|
-
tools=[
|
125
|
-
{"name": "FileDiscovery", "hosted_by": "memra"},
|
126
|
-
{"name": "FileCopy", "hosted_by": "memra"},
|
127
|
-
{"name": "InvoiceExtractionWorkflow", "hosted_by": "memra"}
|
128
|
-
]
|
129
|
-
)
|
130
|
-
|
131
|
-
# Three modes of operation:
|
132
|
-
# 1. Auto-discovery: Scan invoices/ directory
|
133
|
-
# 2. External file: Copy from Downloads to invoices/
|
134
|
-
# 3. Specific file: Process exact file path
|
135
|
-
```
|
136
|
-
|
137
|
-
See `examples/accounts_payable_smart.py` for a complete implementation.
|
138
|
-
|
139
|
-
## Contributing
|
140
|
-
|
141
|
-
We welcome contributions! Please see our [contributing guide](CONTRIBUTING.md) for details.
|
142
|
-
|
143
|
-
## License
|
144
|
-
|
145
|
-
MIT License - see LICENSE file for details.
|
File without changes
|
File without changes
|
File without changes
|