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
memra/cli.py CHANGED
@@ -37,11 +37,18 @@ def run_demo():
37
37
  print("⏳ Waiting for services to be ready...")
38
38
  wait_for_services()
39
39
 
40
- # Step 5: Run the demo
40
+ # Step 5: Start MCP bridge server
41
+ print("🔌 Starting MCP bridge server...")
42
+ if not start_mcp_bridge_server(demo_dir):
43
+ print("❌ Failed to start MCP bridge server.")
44
+ print(" You can start it manually: cd memra-ops && python mcp_bridge_server.py")
45
+ return False
46
+
47
+ # Step 6: Run the demo
41
48
  print("🎯 Running ETL workflow...")
42
49
  success = run_etl_workflow(demo_dir)
43
50
 
44
- # Step 6: Show results
51
+ # Step 7: Show results
45
52
  if success:
46
53
  print("=" * 50)
47
54
  print("🎉 Demo completed successfully!")
@@ -53,6 +60,7 @@ def run_demo():
53
60
  print(" • Check database: docker exec -it memra_postgres psql -U postgres -d local_workflow")
54
61
  print(" • View data: SELECT * FROM invoices ORDER BY created_at DESC;")
55
62
  print(" • Stop services: cd memra-ops && docker compose down")
63
+ print(" • Stop MCP server: pkill -f mcp_bridge_server.py")
56
64
  print(" • Explore code: Check the extracted files in the demo directory")
57
65
  else:
58
66
  print("❌ Demo failed. Check the logs above for details.")
@@ -158,36 +166,132 @@ import asyncio
158
166
  import aiohttp
159
167
  from aiohttp import web
160
168
  import json
169
+ import psycopg2
170
+ import os
161
171
 
162
- async def health_handler(request):
163
- return web.json_response({"status": "healthy"})
172
+ class MCPBridgeServer:
173
+ def __init__(self):
174
+ self.db_url = os.getenv('DATABASE_URL', 'postgresql://postgres:postgres@localhost:5432/local_workflow')
175
+
176
+ async def health_handler(self, request):
177
+ return web.json_response({"status": "healthy", "server": "MCP Bridge"})
178
+
179
+ async def execute_tool_handler(self, request):
180
+ try:
181
+ data = await request.json()
182
+ tool_name = data.get('tool_name', 'unknown')
183
+ tool_params = data.get('parameters', {})
184
+
185
+ if tool_name == 'SQLExecutor':
186
+ return await self.execute_sql(tool_params)
187
+ elif tool_name == 'PostgresInsert':
188
+ return await self.insert_data(tool_params)
189
+ elif tool_name == 'DataValidator':
190
+ return await self.validate_data(tool_params)
191
+ else:
192
+ return web.json_response({
193
+ "success": True,
194
+ "message": f"Demo {tool_name} executed",
195
+ "data": {"demo": True}
196
+ })
197
+ except Exception as e:
198
+ return web.json_response({
199
+ "success": False,
200
+ "error": str(e)
201
+ }, status=500)
202
+
203
+ async def execute_sql(self, params):
204
+ try:
205
+ query = params.get('query', 'SELECT 1')
206
+ conn = psycopg2.connect(self.db_url)
207
+ cursor = conn.cursor()
208
+ cursor.execute(query)
209
+ results = cursor.fetchall()
210
+ cursor.close()
211
+ conn.close()
212
+
213
+ return web.json_response({
214
+ "success": True,
215
+ "results": results,
216
+ "query": query
217
+ })
218
+ except Exception as e:
219
+ return web.json_response({
220
+ "success": False,
221
+ "error": f"SQL execution failed: {str(e)}"
222
+ }, status=500)
223
+
224
+ async def insert_data(self, params):
225
+ try:
226
+ table_name = params.get('table_name', 'invoices')
227
+ data = params.get('data', {})
228
+
229
+ conn = psycopg2.connect(self.db_url)
230
+ cursor = conn.cursor()
231
+
232
+ # Simple insert logic
233
+ columns = list(data.keys())
234
+ values = list(data.values())
235
+ placeholders = ', '.join(['%s'] * len(values))
236
+ column_list = ', '.join(columns)
237
+
238
+ query = f"INSERT INTO {table_name} ({column_list}) VALUES ({placeholders}) RETURNING id"
239
+ cursor.execute(query, values)
240
+ record_id = cursor.fetchone()[0]
241
+
242
+ conn.commit()
243
+ cursor.close()
244
+ conn.close()
245
+
246
+ return web.json_response({
247
+ "success": True,
248
+ "record_id": record_id,
249
+ "message": f"Inserted into {table_name}"
250
+ })
251
+ except Exception as e:
252
+ return web.json_response({
253
+ "success": False,
254
+ "error": f"Insert failed: {str(e)}"
255
+ }, status=500)
256
+
257
+ async def validate_data(self, params):
258
+ try:
259
+ data = params.get('data', {})
260
+
261
+ # Simple validation
262
+ is_valid = True
263
+ errors = []
264
+
265
+ if not data.get('vendor_name'):
266
+ is_valid = False
267
+ errors.append("Missing vendor name")
268
+
269
+ if not data.get('amount') or float(data.get('amount', 0)) <= 0:
270
+ is_valid = False
271
+ errors.append("Invalid amount")
272
+
273
+ return web.json_response({
274
+ "success": True,
275
+ "is_valid": is_valid,
276
+ "errors": errors,
277
+ "validated_data": data
278
+ })
279
+ except Exception as e:
280
+ return web.json_response({
281
+ "success": False,
282
+ "error": f"Validation failed: {str(e)}"
283
+ }, status=500)
164
284
 
165
- async def execute_tool_handler(request):
166
- data = await request.json()
167
- tool_name = data.get('tool_name', 'unknown')
168
-
169
- # Mock responses for demo
170
- if tool_name == 'SQLExecutor':
171
- return web.json_response({
172
- "success": True,
173
- "results": [{"message": "Demo SQL executed"}]
174
- })
175
- elif tool_name == 'PostgresInsert':
176
- return web.json_response({
177
- "success": True,
178
- "id": 1
179
- })
180
- else:
181
- return web.json_response({
182
- "success": True,
183
- "message": f"Demo {tool_name} executed"
184
- })
285
+ # Create server instance
286
+ server = MCPBridgeServer()
185
287
 
288
+ # Create web application
186
289
  app = web.Application()
187
- app.router.add_get('/health', health_handler)
188
- app.router.add_post('/execute_tool', execute_tool_handler)
290
+ app.router.add_get('/health', server.health_handler)
291
+ app.router.add_post('/execute_tool', server.execute_tool_handler)
189
292
 
190
293
  if __name__ == '__main__':
294
+ print("🚀 Starting MCP Bridge Server on port 8081...")
191
295
  web.run_app(app, host='0.0.0.0', port=8081)
192
296
  """
193
297
 
@@ -232,36 +336,132 @@ import asyncio
232
336
  import aiohttp
233
337
  from aiohttp import web
234
338
  import json
339
+ import psycopg2
340
+ import os
235
341
 
236
- async def health_handler(request):
237
- return web.json_response({"status": "healthy"})
342
+ class MCPBridgeServer:
343
+ def __init__(self):
344
+ self.db_url = os.getenv('DATABASE_URL', 'postgresql://postgres:postgres@localhost:5432/local_workflow')
345
+
346
+ async def health_handler(self, request):
347
+ return web.json_response({"status": "healthy", "server": "MCP Bridge"})
348
+
349
+ async def execute_tool_handler(self, request):
350
+ try:
351
+ data = await request.json()
352
+ tool_name = data.get('tool_name', 'unknown')
353
+ tool_params = data.get('parameters', {})
354
+
355
+ if tool_name == 'SQLExecutor':
356
+ return await self.execute_sql(tool_params)
357
+ elif tool_name == 'PostgresInsert':
358
+ return await self.insert_data(tool_params)
359
+ elif tool_name == 'DataValidator':
360
+ return await self.validate_data(tool_params)
361
+ else:
362
+ return web.json_response({
363
+ "success": True,
364
+ "message": f"Demo {tool_name} executed",
365
+ "data": {"demo": True}
366
+ })
367
+ except Exception as e:
368
+ return web.json_response({
369
+ "success": False,
370
+ "error": str(e)
371
+ }, status=500)
372
+
373
+ async def execute_sql(self, params):
374
+ try:
375
+ query = params.get('query', 'SELECT 1')
376
+ conn = psycopg2.connect(self.db_url)
377
+ cursor = conn.cursor()
378
+ cursor.execute(query)
379
+ results = cursor.fetchall()
380
+ cursor.close()
381
+ conn.close()
382
+
383
+ return web.json_response({
384
+ "success": True,
385
+ "results": results,
386
+ "query": query
387
+ })
388
+ except Exception as e:
389
+ return web.json_response({
390
+ "success": False,
391
+ "error": f"SQL execution failed: {str(e)}"
392
+ }, status=500)
393
+
394
+ async def insert_data(self, params):
395
+ try:
396
+ table_name = params.get('table_name', 'invoices')
397
+ data = params.get('data', {})
398
+
399
+ conn = psycopg2.connect(self.db_url)
400
+ cursor = conn.cursor()
401
+
402
+ # Simple insert logic
403
+ columns = list(data.keys())
404
+ values = list(data.values())
405
+ placeholders = ', '.join(['%s'] * len(values))
406
+ column_list = ', '.join(columns)
407
+
408
+ query = f"INSERT INTO {table_name} ({column_list}) VALUES ({placeholders}) RETURNING id"
409
+ cursor.execute(query, values)
410
+ record_id = cursor.fetchone()[0]
411
+
412
+ conn.commit()
413
+ cursor.close()
414
+ conn.close()
415
+
416
+ return web.json_response({
417
+ "success": True,
418
+ "record_id": record_id,
419
+ "message": f"Inserted into {table_name}"
420
+ })
421
+ except Exception as e:
422
+ return web.json_response({
423
+ "success": False,
424
+ "error": f"Insert failed: {str(e)}"
425
+ }, status=500)
426
+
427
+ async def validate_data(self, params):
428
+ try:
429
+ data = params.get('data', {})
430
+
431
+ # Simple validation
432
+ is_valid = True
433
+ errors = []
434
+
435
+ if not data.get('vendor_name'):
436
+ is_valid = False
437
+ errors.append("Missing vendor name")
438
+
439
+ if not data.get('amount') or float(data.get('amount', 0)) <= 0:
440
+ is_valid = False
441
+ errors.append("Invalid amount")
442
+
443
+ return web.json_response({
444
+ "success": True,
445
+ "is_valid": is_valid,
446
+ "errors": errors,
447
+ "validated_data": data
448
+ })
449
+ except Exception as e:
450
+ return web.json_response({
451
+ "success": False,
452
+ "error": f"Validation failed: {str(e)}"
453
+ }, status=500)
238
454
 
239
- async def execute_tool_handler(request):
240
- data = await request.json()
241
- tool_name = data.get('tool_name', 'unknown')
242
-
243
- # Mock responses for demo
244
- if tool_name == 'SQLExecutor':
245
- return web.json_response({
246
- "success": True,
247
- "results": [{"message": "Demo SQL executed"}]
248
- })
249
- elif tool_name == 'PostgresInsert':
250
- return web.json_response({
251
- "success": True,
252
- "id": 1
253
- })
254
- else:
255
- return web.json_response({
256
- "success": True,
257
- "message": f"Demo {tool_name} executed"
258
- })
455
+ # Create server instance
456
+ server = MCPBridgeServer()
259
457
 
458
+ # Create web application
260
459
  app = web.Application()
261
- app.router.add_get('/health', health_handler)
262
- app.router.add_post('/execute_tool', execute_tool_handler)
460
+ app.router.add_get('/health', server.health_handler)
461
+ app.router.add_post('/execute_tool', server.execute_tool_handler)
263
462
 
264
463
  if __name__ == '__main__':
464
+ print("🚀 Starting MCP Bridge Server on port 8081...")
265
465
  web.run_app(app, host='0.0.0.0', port=8081)
266
466
  """
267
467
 
@@ -498,8 +698,32 @@ def run_etl_workflow(demo_dir):
498
698
  real_demo_script = demo_dir / "etl_invoice_demo.py"
499
699
  if real_demo_script.exists():
500
700
  print("🎯 Running real ETL workflow...")
701
+ print(f"📁 Working directory: {demo_dir}")
702
+ print(f"📄 Demo script: {real_demo_script}")
703
+
704
+ # Check if data directory exists
705
+ data_dir = demo_dir / "data"
706
+ invoices_dir = data_dir / "invoices"
707
+ if invoices_dir.exists():
708
+ pdf_files = list(invoices_dir.glob("*.PDF"))
709
+ print(f"📊 Found {len(pdf_files)} PDF files in {invoices_dir}")
710
+ if pdf_files:
711
+ print(f" First few files: {[f.name for f in pdf_files[:3]]}")
712
+ else:
713
+ print(f"⚠️ Warning: {invoices_dir} does not exist")
714
+ print(f" Available directories in {demo_dir}:")
715
+ for item in demo_dir.iterdir():
716
+ if item.is_dir():
717
+ print(f" - {item.name}/")
718
+
501
719
  print("⏱️ Processing 15 files with delays - this may take 10-15 minutes")
502
- result = subprocess.run([sys.executable, str(real_demo_script)], cwd=demo_dir, timeout=1800) # 30 minute timeout
720
+
721
+ # Set the working directory to the demo directory so the script can find data/invoices/
722
+ result = subprocess.run(
723
+ [sys.executable, str(real_demo_script)],
724
+ cwd=demo_dir, # This is crucial - sets working directory
725
+ timeout=1800 # 30 minute timeout
726
+ )
503
727
  return result.returncode == 0
504
728
  else:
505
729
  # Fallback to simplified demo
@@ -510,6 +734,10 @@ def run_etl_workflow(demo_dir):
510
734
  return result.returncode == 0
511
735
  else:
512
736
  print("❌ No demo script found")
737
+ print(f" Looking for: {real_demo_script}")
738
+ print(f" Available files in {demo_dir}:")
739
+ for item in demo_dir.iterdir():
740
+ print(f" - {item.name}")
513
741
  return False
514
742
 
515
743
  except subprocess.TimeoutExpired:
@@ -520,6 +748,49 @@ def run_etl_workflow(demo_dir):
520
748
  print(f"❌ Error running ETL workflow: {e}")
521
749
  return False
522
750
 
751
+ def start_mcp_bridge_server(demo_dir):
752
+ """Start the MCP bridge server"""
753
+ try:
754
+ ops_dir = demo_dir / "memra-ops"
755
+ bridge_script = ops_dir / "mcp_bridge_server.py"
756
+
757
+ if not bridge_script.exists():
758
+ print("❌ MCP bridge server script not found")
759
+ return False
760
+
761
+ # Start the bridge server in the background
762
+ if os.name == 'nt': # Windows
763
+ # Use start command to run in background
764
+ result = subprocess.run([
765
+ 'start', '/B', 'python', str(bridge_script)
766
+ ], cwd=ops_dir, shell=True, capture_output=True, text=True)
767
+ else: # Unix/Linux/Mac
768
+ result = subprocess.run([
769
+ 'python', str(bridge_script)
770
+ ], cwd=ops_dir, start_new_session=True, capture_output=True, text=True)
771
+
772
+ # Wait a moment for the server to start
773
+ time.sleep(3)
774
+
775
+ # Check if the server is responding
776
+ try:
777
+ import requests
778
+ response = requests.get('http://localhost:8081/health', timeout=5)
779
+ if response.status_code == 200:
780
+ print("✅ MCP bridge server started successfully")
781
+ return True
782
+ else:
783
+ print(f"⚠️ MCP bridge server responded with status {response.status_code}")
784
+ return False
785
+ except Exception as e:
786
+ print(f"⚠️ Could not verify MCP bridge server: {e}")
787
+ print(" Server may still be starting up...")
788
+ return True # Assume it's working
789
+
790
+ except Exception as e:
791
+ print(f"❌ Error starting MCP bridge server: {e}")
792
+ return False
793
+
523
794
  def main():
524
795
  """Main CLI entry point"""
525
796
  if len(sys.argv) < 2:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: memra
3
- Version: 0.2.13
3
+ Version: 0.2.15
4
4
  Summary: Declarative framework for enterprise workflows with MCP integration - Client SDK
5
5
  Home-page: https://github.com/memra/memra-sdk
6
6
  Author: Memra
@@ -1,5 +1,5 @@
1
1
  memra/__init__.py,sha256=6i82jodsWZPgtRhUaDF3wuQuRDSaboIpew8D3zDN__s,1109
2
- memra/cli.py,sha256=wFmGDUJBgWhQJ5NG99TXDuk4laezivZbSWEbiobcYhs,19105
2
+ memra/cli.py,sha256=_IlOrTBlv_zBElxxQs13JYsdAuOn9wO1UiogmnwO1Qg,29430
3
3
  memra/discovery.py,sha256=yJIQnrDQu1nyzKykCIuzG_5SW5dIXHCEBLLKRWacIoY,480
4
4
  memra/discovery_client.py,sha256=AbnKn6qhyrf7vmOvknEeDzH4tiGHsqPHtDaein_qaW0,1271
5
5
  memra/execution.py,sha256=OXpBKxwBIjhACWL_qh8KHNndO8HUgB6gBF81AiQBBm0,34751
@@ -58,63 +58,9 @@ memra/demos/etl_invoice_processing/data/invoices/10352262702.PDF,sha256=aNWnxbYq
58
58
  memra/demos/etl_invoice_processing/data/invoices/10352262884.PDF,sha256=G0eszEhpTOS15hIlMyPMM6iyVw6UZPKycXvS3P42xRc,1010830
59
59
  memra/demos/etl_invoice_processing/data/invoices/10352263346.PDF,sha256=NMfsgrmaNtvNu6xk2aLtubI05I9cuVIbwJMxv_pYPhQ,1089624
60
60
  memra/demos/etl_invoice_processing/data/invoices/10352263429.PDF,sha256=1IzJbmnsKDE1cV6CtyNMENn0Rmpq2tA_BDnZYTYhNhQ,1082893
61
- memra-ops/app.py,sha256=S8B82gOAuT9x-NhmVLL9HM03Pde3Fa7QXm6TG1PEbbU,29439
62
- memra-ops/config.py,sha256=6mBbS_stoEIhJDBqdJOalryAnyWeHbDy81mU1j08ids,969
63
- memra-ops/mcp_bridge_server.py,sha256=tDEigRstIEAEu16F1ctCor2ny9CBbEOMY046bHdzFpE,47607
64
- memra-ops/server_tool_registry.py,sha256=rg5wz8dTfJNqo2QRe69iBKJKeoJemltt_XzZsdxyJa8,8367
65
- memra-ops/config/config.py,sha256=7dcT9W5b_nWrVAylbdeOaA60_NJlhv2YLyEILTcNKtI,600
66
- memra-ops/logic/__init__.py,sha256=UFKwzAUU-5pWt-7gcajY1M9PLoJ1wiQ8L0HDTlkRv7E,43
67
- memra-ops/logic/file_tools.py,sha256=iVe4xE7lNBhhoiL0Hi2zx4oF7koDeVvsOh1uMbn6HEo,1126
68
- memra-ops/logic/invoice_tools.py,sha256=Jp3PEFfUXRTAAP1ZM4Juei_zzPKy8EFi8H2uP6T9c2A,27787
69
- memra-ops/logic/invoice_tools_fix.py,sha256=sF4qADqbfWEgOyavslrNlCDEyIkaZo35TtnyHd7PClY,3020
70
- memra-ops/scripts/check_database.py,sha256=sBPmIJ10WW3jHQfOjeDRJnQahRBwVAi60-98r4HG9rw,987
71
- memra-ops/scripts/clear_database.py,sha256=yO4JUbMOcSQ1-S57n1oua-SheM360yg-oNiPyj8LW5o,1441
72
- memra-ops/scripts/monitor_database.py,sha256=OmIgUmtVjtUfSziSEiTy5CheueMMZ5R5HciPpMishE0,2287
73
- memra-ops/scripts/release.py,sha256=riQ-jz7-vnd1cSfQdU1eUZmVDyuWym1nmZW65lGetiI,4218
74
- memra-ops/scripts/reset_database.py,sha256=QJagPQIkMOr3s-o-g_Urz0CvSYNm0D2xbwo3JSrKIWY,2255
75
- memra-ops/scripts/start_memra.py,sha256=VR7WESQXgvPuzZEFMhtmABSR7IzYixsnpgtoPcECLK0,11987
76
- memra-ops/scripts/stop_memra.py,sha256=yyTu4jxjUbxTrvobQ-UhpNk-eWB8bCFjcBPGW1scIJg,4591
77
- memra-ops/tests/test_llm_text_to_sql.py,sha256=IDL7FEzlm2Dr9pRCcJQ6SGddF9VBDfHonwztrDpxBGU,4099
78
- memra-ops/tests/test_llm_vs_pattern.py,sha256=ZATV1fS7C6Jn-N4-UB5LzuRjbiO1ctZq3gNoIud2RWc,4880
79
- memra-ops/tests/test_mcp_schema_aware.py,sha256=H5NmGxS3LWo9xoodqVeliJyHco7ZjGOtHg80ep1SHzw,4537
80
- memra-ops/tests/test_schema_aware_sql.py,sha256=b_XPtv7eldR2ARBVlriTHMA1nwqYUcMgthL8mHpewuM,4645
81
- memra-ops/tests/test_schema_aware_sql_simple.py,sha256=8f8zijkTwvIqVHM3B5oVviRfFS-U6bfC43fk9hcWsoE,2309
82
- memra-ops/tests/test_text_to_sql_demo.py,sha256=5mmpSwXZ8r8sj3J9iCYkFx0SgwyXPe-7Prie1hL6cis,5092
83
- memra-ops/tools/mcp_bridge_server.py,sha256=IKUNusZovPdR0_6Bv_XejmAk27lnHrM1uOE8xPVnM8s,35051
84
- memra-sdk/setup.py,sha256=j95Pq2ha28B3owPv0J1isq5pgUwa9p02nbBXqxa4Lwo,1513
85
- memra-sdk/examples/accounts_payable.py,sha256=PfpXKrGOUu6NpkNcHy6cN6TtsXfnsJZhUv-KGlOvDqY,7990
86
- memra-sdk/examples/accounts_payable_client.py,sha256=tLHHCydEpasLHTHd4YULhSxFy6zs81X5PZHav0dlQ2I,7816
87
- memra-sdk/examples/accounts_payable_mcp.py,sha256=lOgwDfMVKxifQi70GmeXQnpZiIFrZnNj5_JSZ9qsdBw,7344
88
- memra-sdk/examples/ask_questions.py,sha256=jek7EVXXZ_vODlMy_hQGQCkN9vYBfaW7SOWsIQRV2GY,3830
89
- memra-sdk/examples/invoice_processing.py,sha256=STe3ri65WH_Ss84qiRWuGZTpDZke5GoJf8LEqOAc5ys,3980
90
- memra-sdk/examples/propane_delivery.py,sha256=ryvIxDjM9GJY9T6fFIqJgHOcX2PEMkfF_t_3E5CyZW4,2539
91
- memra-sdk/examples/simple_text_to_sql.py,sha256=NnpKo9nFpmPQ089zcSx4wwG6_tSHTmGJSS7LPs55NA0,5314
92
- memra-sdk/memra/__init__.py,sha256=CTiSeBBZ40-pNd2-wBIdZduqNLrA5OnWmmwk1y1f894,787
93
- memra-sdk/memra/discovery.py,sha256=yJIQnrDQu1nyzKykCIuzG_5SW5dIXHCEBLLKRWacIoY,480
94
- memra-sdk/memra/discovery_client.py,sha256=AbnKn6qhyrf7vmOvknEeDzH4tiGHsqPHtDaein_qaW0,1271
95
- memra-sdk/memra/execution.py,sha256=P7tAur0SEMtX6uLlfxTfCZBgMLIRj6Wl3dsv2EA9fHc,23443
96
- memra-sdk/memra/models.py,sha256=sXMPRnMB_mUVtJdBFyd0ElCf_uh1yqx7iLssIYNm0vI,3333
97
- memra-sdk/memra/tool_registry.py,sha256=P2TafpiqV19yzi0jVrQQrXFGBpQkbmePbRfEW_ai24M,14700
98
- memra-sdk/memra/tool_registry_client.py,sha256=uzMQ4COvRams9vuPLcqcdljUpDlAYU_tyFxrRhrA0Lc,4009
99
- memra-sdk/scripts/release.py,sha256=riQ-jz7-vnd1cSfQdU1eUZmVDyuWym1nmZW65lGetiI,4218
100
- memra-workflows/mcp_bridge_server.py,sha256=6K9fedZiwNpkT7wGAS6IW-HgMYBUC94zu8ppUgftqDg,8528
101
- memra-workflows/accounts_payable/accounts_payable.py,sha256=rRpviqKZ-g0KPEnI98GbXy-KnyTrN1dLkj0HP9PKlYs,8012
102
- memra-workflows/accounts_payable/accounts_payable_client.py,sha256=kNu2EQ8d6T6qcKn68FznnMGBeoqtXFbN4PHDVDImapk,7813
103
- memra-workflows/accounts_payable/accounts_payable_mcp.py,sha256=kySt7PKyIgLbG1Q3jPY1kFPQK8o_3aAmL9vJG2Qcnxc,7366
104
- memra-workflows/accounts_payable/accounts_payable_smart.py,sha256=g_V6-1qPsLiIOFw-eLT4w-RoljjErF65SuKRzkEeSck,8004
105
- memra-workflows/invoice_processing/invoice_processing.py,sha256=STe3ri65WH_Ss84qiRWuGZTpDZke5GoJf8LEqOAc5ys,3980
106
- memra-workflows/invoice_processing/smart_invoice_processor.py,sha256=Ct3ZjNujK4VTlCDgwMWXn6Y7b1dg0a_eIbRP-xm-p3g,7203
107
- memra-workflows/logic/__init__.py,sha256=kLTdniFpBqOusmRng8W2LSIAmgj-jfM3Agjl_vXYTl8,76
108
- memra-workflows/logic/file_tools.py,sha256=n6uDwInPZcr74zAJJbA9iZajWgRcKoHYtEKX_lbzsik,1586
109
- memra-workflows/logic/invoice_tools.py,sha256=wLTI0JqkMYMlFv1z_DPwliIvKbpFBcYh5SnEnhU13Co,20366
110
- memra-workflows/logic/propane_agents.py,sha256=ZF1RSccn73a5XZVa-1nxgjvubcYzf62g9lr9PoTbGl4,1804
111
- memra-workflows/propane_delivery/propane_delivery.py,sha256=ryvIxDjM9GJY9T6fFIqJgHOcX2PEMkfF_t_3E5CyZW4,2539
112
- memra-workflows/text_to_sql/complete_invoice_workflow_with_queries.py,sha256=x4wq3o_ogFnnrI6MQwEhqIiNH-NNwS5SXQUoKd_br7U,7428
113
- memra-workflows/text_to_sql/complete_text_to_sql_system.py,sha256=Izj4ucXDXTWFY29SWr2YrEf3ZyXH4QCDEljNk4jlpI0,8991
114
- memra-workflows/text_to_sql/file_discovery_demo.py,sha256=4R_QN0Y6OtHmnX6CvtwDXen122XCDrk-MRBOzxb_x_k,5306
115
- memra-0.2.13.dist-info/LICENSE,sha256=8OrnTd8DWwLWmUEj5srSLvT4PREfW1Qo1T5gEUIHPws,1062
116
- memra-0.2.13.dist-info/METADATA,sha256=KwY4StFLr17bUJ6eZ3eazCqwBZlVX7jBMzX_bB9iKxY,9427
117
- memra-0.2.13.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
118
- memra-0.2.13.dist-info/entry_points.txt,sha256=LBVjwWoxWJRzNLgeByPn6xUvWFIRnqnemvAZgIoSt08,41
119
- memra-0.2.13.dist-info/top_level.txt,sha256=IviXF9qSQY_BidRYund9zFaV-q1VMl6CuizwTAggQks,42
120
- memra-0.2.13.dist-info/RECORD,,
61
+ memra-0.2.15.dist-info/LICENSE,sha256=8OrnTd8DWwLWmUEj5srSLvT4PREfW1Qo1T5gEUIHPws,1062
62
+ memra-0.2.15.dist-info/METADATA,sha256=-a6F6PGuriDeFNJjtGn30f0XFdt64O1pmkZjKwvzCB8,9427
63
+ memra-0.2.15.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
64
+ memra-0.2.15.dist-info/entry_points.txt,sha256=LBVjwWoxWJRzNLgeByPn6xUvWFIRnqnemvAZgIoSt08,41
65
+ memra-0.2.15.dist-info/top_level.txt,sha256=pXWcTRS1zctdiSUivW4iyKpJ4tcfIu-1BW_fpbal3OY,6
66
+ memra-0.2.15.dist-info/RECORD,,
@@ -0,0 +1 @@
1
+ memra
@@ -1,4 +0,0 @@
1
- memra
2
- memra-ops
3
- memra-sdk
4
- memra-workflows