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,37 +0,0 @@
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()
@@ -1,48 +0,0 @@
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()
@@ -1,67 +0,0 @@
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()
@@ -1,133 +0,0 @@
1
- #!/usr/bin/env python3
2
- """
3
- Release script for Memra SDK
4
- Builds and uploads the package to PyPI
5
- """
6
-
7
- import os
8
- import sys
9
- import subprocess
10
- import shutil
11
- from pathlib import Path
12
-
13
- def run_command(cmd, description):
14
- """Run a command and handle errors"""
15
- print(f"🔄 {description}...")
16
- result = subprocess.run(cmd, shell=True, capture_output=True, text=True)
17
- if result.returncode != 0:
18
- print(f"❌ {description} failed:")
19
- print(result.stderr)
20
- sys.exit(1)
21
- print(f"✅ {description} completed")
22
- return result.stdout
23
-
24
- def clean_build_artifacts():
25
- """Clean up build artifacts"""
26
- print("🧹 Cleaning build artifacts...")
27
-
28
- # Remove build directories
29
- for dir_name in ['build', 'dist', 'memra.egg-info']:
30
- if os.path.exists(dir_name):
31
- shutil.rmtree(dir_name)
32
- print(f" Removed {dir_name}/")
33
-
34
- # Remove __pycache__ directories
35
- for root, dirs, files in os.walk('.'):
36
- for dir_name in dirs:
37
- if dir_name == '__pycache__':
38
- pycache_path = os.path.join(root, dir_name)
39
- shutil.rmtree(pycache_path)
40
- print(f" Removed {pycache_path}")
41
-
42
- print("✅ Build artifacts cleaned")
43
-
44
- def run_tests():
45
- """Run tests before release"""
46
- print("🧪 Running tests...")
47
-
48
- # Check if pytest is available
49
- try:
50
- subprocess.run(['pytest', '--version'], check=True, capture_output=True)
51
- run_command('pytest tests/', 'Running pytest')
52
- except (subprocess.CalledProcessError, FileNotFoundError):
53
- print("⚠️ pytest not found, skipping tests")
54
-
55
- # Run basic import test
56
- run_command('python -c "import memra; print(f\'Memra SDK version: {memra.__version__ if hasattr(memra, \"__version__\") else \"unknown\"}\')"', 'Testing basic import')
57
-
58
- def build_package():
59
- """Build the package"""
60
- print("📦 Building package...")
61
-
62
- # Install build dependencies
63
- run_command('pip install build twine', 'Installing build tools')
64
-
65
- # Build the package
66
- run_command('python -m build', 'Building wheel and source distribution')
67
-
68
- # Check the package
69
- run_command('twine check dist/*', 'Checking package')
70
-
71
- def upload_package(test=False):
72
- """Upload package to PyPI"""
73
- if test:
74
- print("🚀 Uploading to Test PyPI...")
75
- run_command('twine upload --repository testpypi dist/*', 'Uploading to Test PyPI')
76
- print("📍 Package uploaded to Test PyPI: https://test.pypi.org/project/memra/")
77
- else:
78
- print("🚀 Uploading to PyPI...")
79
- run_command('twine upload dist/*', 'Uploading to PyPI')
80
- print("📍 Package uploaded to PyPI: https://pypi.org/project/memra/")
81
-
82
- def main():
83
- """Main release process"""
84
- print("🎯 Memra SDK Release Process")
85
- print("=" * 40)
86
-
87
- # Parse arguments
88
- test_release = '--test' in sys.argv
89
- skip_tests = '--skip-tests' in sys.argv
90
-
91
- if test_release:
92
- print("🧪 Test release mode enabled")
93
-
94
- # Ensure we're in the right directory
95
- if not os.path.exists('setup.py'):
96
- print("❌ setup.py not found. Please run from the project root.")
97
- sys.exit(1)
98
-
99
- try:
100
- # Clean up
101
- clean_build_artifacts()
102
-
103
- # Run tests
104
- if not skip_tests:
105
- run_tests()
106
- else:
107
- print("⚠️ Skipping tests")
108
-
109
- # Build package
110
- build_package()
111
-
112
- # Upload package
113
- upload_package(test=test_release)
114
-
115
- print("\n🎉 Release completed successfully!")
116
-
117
- if test_release:
118
- print("\n📋 Next steps:")
119
- print("1. Test the package: pip install -i https://test.pypi.org/simple/ memra")
120
- print("2. If everything works, run: python scripts/release.py")
121
- else:
122
- print("\n📋 Package is now available on PyPI!")
123
- print("Install with: pip install memra")
124
-
125
- except KeyboardInterrupt:
126
- print("\n❌ Release cancelled by user")
127
- sys.exit(1)
128
- except Exception as e:
129
- print(f"\n❌ Release failed: {e}")
130
- sys.exit(1)
131
-
132
- if __name__ == '__main__':
133
- main()
@@ -1,65 +0,0 @@
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()
@@ -1,334 +0,0 @@
1
- #!/usr/bin/env python3
2
- """
3
- Memra System Startup Script
4
- Starts all dependencies required for the Memra system to run
5
- """
6
-
7
- import os
8
- import sys
9
- import time
10
- import subprocess
11
- import requests
12
- import signal
13
- from pathlib import Path
14
-
15
- # Add the project root to the path
16
- project_root = Path(__file__).parent.parent
17
- sys.path.insert(0, str(project_root))
18
-
19
- class MemraStartup:
20
- def __init__(self):
21
- self.project_root = project_root
22
- self.docker_compose_file = project_root / "docker-compose.yml"
23
- self.mcp_bridge_script = project_root / "mcp_bridge_server.py"
24
- self.processes = []
25
-
26
- def print_banner(self):
27
- """Print startup banner"""
28
- print("=" * 60)
29
- print("🚀 MEMRA SYSTEM STARTUP")
30
- print("=" * 60)
31
- print("Starting all dependencies for Memra AI workflow system...")
32
- print()
33
-
34
- def check_conda_environment(self):
35
- """Check if we're in the correct conda environment"""
36
- print("🔍 Checking conda environment...")
37
-
38
- # Check if we're in the memra environment
39
- conda_env = os.getenv('CONDA_DEFAULT_ENV')
40
- if conda_env != 'memra':
41
- print(f"❌ Warning: Not in 'memra' conda environment (current: {conda_env})")
42
- print(" Please run: conda activate memra")
43
- print(" Then run this script again.")
44
- return False
45
-
46
- print(f"✅ Conda environment: {conda_env}")
47
- return True
48
-
49
- def check_docker(self):
50
- """Check if Docker is running"""
51
- print("🐳 Checking Docker...")
52
- try:
53
- result = subprocess.run(['docker', 'info'],
54
- capture_output=True, text=True, timeout=10)
55
- if result.returncode == 0:
56
- print("✅ Docker is running")
57
- return True
58
- else:
59
- print("❌ Docker is not running")
60
- return False
61
- except (subprocess.TimeoutExpired, FileNotFoundError):
62
- print("❌ Docker is not running or not installed")
63
- return False
64
-
65
- def start_postgresql(self):
66
- """Start PostgreSQL using Docker Compose"""
67
- print("🐘 Starting PostgreSQL...")
68
-
69
- try:
70
- # Check if containers are already running
71
- result = subprocess.run(['docker', 'ps', '--filter', 'name=memra-postgres'],
72
- capture_output=True, text=True)
73
-
74
- if 'memra-postgres' in result.stdout:
75
- print("✅ PostgreSQL is already running")
76
- return True
77
-
78
- # Start PostgreSQL
79
- print(" Starting PostgreSQL container...")
80
- result = subprocess.run(['docker-compose', 'up', '-d', 'postgres'],
81
- cwd=self.project_root, capture_output=True, text=True)
82
-
83
- if result.returncode == 0:
84
- print("✅ PostgreSQL started successfully")
85
- return True
86
- else:
87
- print(f"❌ Failed to start PostgreSQL: {result.stderr}")
88
- return False
89
-
90
- except Exception as e:
91
- print(f"❌ Error starting PostgreSQL: {e}")
92
- return False
93
-
94
- def wait_for_postgresql(self, max_attempts=30):
95
- """Wait for PostgreSQL to be ready"""
96
- print("⏳ Waiting for PostgreSQL to be ready...")
97
-
98
- for attempt in range(max_attempts):
99
- try:
100
- # Try to connect to PostgreSQL
101
- result = subprocess.run([
102
- 'docker', 'exec', 'memra-postgres',
103
- 'pg_isready', '-U', 'memra', '-d', 'memra_invoice_db'
104
- ], capture_output=True, text=True, timeout=5)
105
-
106
- if result.returncode == 0:
107
- print("✅ PostgreSQL is ready")
108
- return True
109
-
110
- except (subprocess.TimeoutExpired, subprocess.CalledProcessError):
111
- pass
112
-
113
- print(f" Attempt {attempt + 1}/{max_attempts}...")
114
- time.sleep(2)
115
-
116
- print("❌ PostgreSQL failed to start within timeout")
117
- return False
118
-
119
- def check_memra_api_key(self):
120
- """Check if MEMRA_API_KEY is set"""
121
- print("🔑 Checking Memra API key...")
122
-
123
- api_key = os.getenv('MEMRA_API_KEY')
124
- if not api_key:
125
- print("❌ MEMRA_API_KEY environment variable is not set")
126
- print(" Please set: export MEMRA_API_KEY='your-key-here'")
127
- return False
128
-
129
- print(f"✅ Memra API key is set: {api_key[:8]}...")
130
- return True
131
-
132
- def start_mcp_bridge(self):
133
- """Start the MCP bridge server"""
134
- print("🌉 Starting MCP Bridge Server...")
135
-
136
- try:
137
- # Check if MCP bridge is already running
138
- try:
139
- response = requests.get('http://localhost:8081/health', timeout=5)
140
- if response.status_code == 200:
141
- print("✅ MCP Bridge Server is already running")
142
- return True
143
- except requests.RequestException:
144
- pass
145
-
146
- # Start MCP bridge server in background
147
- print(" Starting MCP bridge server...")
148
- process = subprocess.Popen([
149
- sys.executable, str(self.mcp_bridge_script)
150
- ], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
151
-
152
- self.processes.append(process)
153
-
154
- # Wait a moment for server to start
155
- time.sleep(3)
156
-
157
- # Check if server started successfully
158
- try:
159
- response = requests.get('http://localhost:8081/health', timeout=5)
160
- if response.status_code == 200:
161
- print("✅ MCP Bridge Server started successfully")
162
- return True
163
- else:
164
- print(f"❌ MCP Bridge Server returned status {response.status_code}")
165
- return False
166
- except requests.RequestException as e:
167
- print(f"❌ MCP Bridge Server failed to start: {e}")
168
- return False
169
-
170
- except Exception as e:
171
- print(f"❌ Error starting MCP Bridge Server: {e}")
172
- return False
173
-
174
- def test_memra_api(self):
175
- """Test the Memra API connection"""
176
- print("🌐 Testing Memra API connection...")
177
-
178
- try:
179
- from memra import get_api_status
180
- api_status = get_api_status()
181
-
182
- if api_status['api_healthy']:
183
- print(f"✅ Memra API is healthy")
184
- print(f" URL: {api_status['api_url']}")
185
- print(f" Tools Available: {api_status['tools_available']}")
186
- return True
187
- else:
188
- print("❌ Memra API is not healthy")
189
- return False
190
-
191
- except Exception as e:
192
- print(f"❌ Error testing Memra API: {e}")
193
- return False
194
-
195
- def run_test_workflow(self):
196
- """Run a quick test to verify everything works"""
197
- print("🧪 Running system test...")
198
-
199
- try:
200
- # Import and run a simple test
201
- from memra import Agent, Department, LLM
202
- from memra.execution import ExecutionEngine
203
-
204
- # Create a simple test agent
205
- test_agent = Agent(
206
- role="Test Agent",
207
- job="Verify system is working",
208
- llm=LLM(model="llama-3.2-11b-vision-preview", temperature=0.1),
209
- sops=["Return a simple success message"],
210
- output_key="test_result"
211
- )
212
-
213
- # Create test department
214
- test_dept = Department(
215
- name="Test Department",
216
- mission="Verify Memra system is working",
217
- agents=[test_agent],
218
- workflow_order=["Test Agent"]
219
- )
220
-
221
- # Run test
222
- engine = ExecutionEngine()
223
- result = engine.execute_department(test_dept, {})
224
-
225
- if result.success:
226
- print("✅ System test passed - Memra is ready!")
227
- return True
228
- else:
229
- print(f"❌ System test failed: {result.error}")
230
- return False
231
-
232
- except Exception as e:
233
- print(f"❌ Error running system test: {e}")
234
- return False
235
-
236
- def cleanup(self):
237
- """Cleanup processes on exit"""
238
- print("\n🧹 Cleaning up processes...")
239
- for process in self.processes:
240
- try:
241
- process.terminate()
242
- process.wait(timeout=5)
243
- except:
244
- try:
245
- process.kill()
246
- except:
247
- pass
248
-
249
- def signal_handler(self, signum, frame):
250
- """Handle interrupt signals"""
251
- print("\n🛑 Received interrupt signal, shutting down...")
252
- self.cleanup()
253
- sys.exit(0)
254
-
255
- def start(self):
256
- """Main startup sequence"""
257
- try:
258
- self.print_banner()
259
-
260
- # Set up signal handlers
261
- signal.signal(signal.SIGINT, self.signal_handler)
262
- signal.signal(signal.SIGTERM, self.signal_handler)
263
-
264
- # Check environment
265
- if not self.check_conda_environment():
266
- return False
267
-
268
- # Check Docker
269
- if not self.check_docker():
270
- print("❌ Please start Docker Desktop and try again")
271
- return False
272
-
273
- # Start PostgreSQL
274
- if not self.start_postgresql():
275
- return False
276
-
277
- if not self.wait_for_postgresql():
278
- return False
279
-
280
- # Check API key
281
- if not self.check_memra_api_key():
282
- return False
283
-
284
- # Start MCP bridge
285
- if not self.start_mcp_bridge():
286
- return False
287
-
288
- # Test API
289
- if not self.test_memra_api():
290
- return False
291
-
292
- # Run system test
293
- if not self.run_test_workflow():
294
- return False
295
-
296
- print("\n" + "=" * 60)
297
- print("🎉 MEMRA SYSTEM STARTED SUCCESSFULLY!")
298
- print("=" * 60)
299
- print("✅ All dependencies are running:")
300
- print(" • PostgreSQL Database (Docker)")
301
- print(" • MCP Bridge Server (localhost:8081)")
302
- print(" • Memra API (https://api.memra.co)")
303
- print()
304
- print("🚀 Ready to run workflows!")
305
- print(" Example: python3 examples/accounts_payable_client.py")
306
- print()
307
- print("💡 Keep this terminal open to maintain the MCP bridge server")
308
- print(" Press Ctrl+C to stop all services")
309
- print("=" * 60)
310
-
311
- # Keep the script running to maintain the MCP bridge server
312
- try:
313
- while True:
314
- time.sleep(1)
315
- except KeyboardInterrupt:
316
- print("\n🛑 Shutting down Memra system...")
317
- self.cleanup()
318
- print("✅ Memra system stopped")
319
-
320
- except Exception as e:
321
- print(f"❌ Startup failed: {e}")
322
- self.cleanup()
323
- return False
324
-
325
- return True
326
-
327
- def main():
328
- """Main entry point"""
329
- startup = MemraStartup()
330
- success = startup.start()
331
- sys.exit(0 if success else 1)
332
-
333
- if __name__ == "__main__":
334
- main()