memra 0.2.2__py3-none-any.whl → 0.2.4__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 (57) hide show
  1. memra/__init__.py +6 -2
  2. memra/execution.py +53 -0
  3. memra/tool_registry.py +162 -0
  4. memra-0.2.4.dist-info/METADATA +145 -0
  5. memra-0.2.4.dist-info/RECORD +58 -0
  6. {memra-0.2.2.dist-info → memra-0.2.4.dist-info}/WHEEL +1 -1
  7. memra-0.2.4.dist-info/top_level.txt +4 -0
  8. memra-ops/app.py +710 -0
  9. memra-ops/config/config.py +25 -0
  10. memra-ops/config.py +34 -0
  11. memra-ops/scripts/release.py +133 -0
  12. memra-ops/scripts/start_memra.py +334 -0
  13. memra-ops/scripts/stop_memra.py +132 -0
  14. memra-ops/server_tool_registry.py +188 -0
  15. memra-ops/tests/test_llm_text_to_sql.py +115 -0
  16. memra-ops/tests/test_llm_vs_pattern.py +130 -0
  17. memra-ops/tests/test_mcp_schema_aware.py +124 -0
  18. memra-ops/tests/test_schema_aware_sql.py +139 -0
  19. memra-ops/tests/test_schema_aware_sql_simple.py +66 -0
  20. memra-ops/tests/test_text_to_sql_demo.py +140 -0
  21. memra-ops/tools/mcp_bridge_server.py +851 -0
  22. memra-sdk/examples/accounts_payable.py +215 -0
  23. memra-sdk/examples/accounts_payable_client.py +217 -0
  24. memra-sdk/examples/accounts_payable_mcp.py +200 -0
  25. memra-sdk/examples/ask_questions.py +123 -0
  26. memra-sdk/examples/invoice_processing.py +116 -0
  27. memra-sdk/examples/propane_delivery.py +87 -0
  28. memra-sdk/examples/simple_text_to_sql.py +158 -0
  29. memra-sdk/memra/__init__.py +31 -0
  30. memra-sdk/memra/discovery.py +15 -0
  31. memra-sdk/memra/discovery_client.py +49 -0
  32. memra-sdk/memra/execution.py +481 -0
  33. memra-sdk/memra/models.py +99 -0
  34. memra-sdk/memra/tool_registry.py +343 -0
  35. memra-sdk/memra/tool_registry_client.py +106 -0
  36. memra-sdk/scripts/release.py +133 -0
  37. memra-sdk/setup.py +52 -0
  38. memra-workflows/accounts_payable/accounts_payable.py +215 -0
  39. memra-workflows/accounts_payable/accounts_payable_client.py +216 -0
  40. memra-workflows/accounts_payable/accounts_payable_mcp.py +200 -0
  41. memra-workflows/accounts_payable/accounts_payable_smart.py +221 -0
  42. memra-workflows/invoice_processing/invoice_processing.py +116 -0
  43. memra-workflows/invoice_processing/smart_invoice_processor.py +220 -0
  44. memra-workflows/logic/__init__.py +1 -0
  45. memra-workflows/logic/file_tools.py +50 -0
  46. memra-workflows/logic/invoice_tools.py +501 -0
  47. memra-workflows/logic/propane_agents.py +52 -0
  48. memra-workflows/mcp_bridge_server.py +230 -0
  49. memra-workflows/propane_delivery/propane_delivery.py +87 -0
  50. memra-workflows/text_to_sql/complete_invoice_workflow_with_queries.py +208 -0
  51. memra-workflows/text_to_sql/complete_text_to_sql_system.py +266 -0
  52. memra-workflows/text_to_sql/file_discovery_demo.py +156 -0
  53. memra-0.2.2.dist-info/METADATA +0 -148
  54. memra-0.2.2.dist-info/RECORD +0 -13
  55. memra-0.2.2.dist-info/top_level.txt +0 -1
  56. {memra-0.2.2.dist-info → memra-0.2.4.dist-info}/entry_points.txt +0 -0
  57. {memra-0.2.2.dist-info → memra-0.2.4.dist-info/licenses}/LICENSE +0 -0
@@ -0,0 +1,266 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Complete Text-to-SQL System
4
+ Demonstrates the full pipeline: English Question → Schema → SQL Generation → Execution → Real Results
5
+ """
6
+
7
+ import os
8
+ import sys
9
+ import json
10
+ from pathlib import Path
11
+
12
+ # Add the parent directory to the path so we can import memra
13
+ sys.path.insert(0, str(Path(__file__).parent.parent))
14
+
15
+ from memra import ExecutionEngine, Agent, Tool
16
+
17
+ def create_text_to_sql_system():
18
+ """Create a complete text-to-SQL system with real database integration"""
19
+
20
+ # Initialize execution engine
21
+ engine = ExecutionEngine()
22
+
23
+ # Schema Extraction Agent
24
+ schema_agent = Agent(
25
+ role="Database Schema Analyst",
26
+ job="Extract and analyze database schemas",
27
+ output_key="schema_data",
28
+ tools=[
29
+ Tool(
30
+ name="DatabaseQueryTool",
31
+ hosted_by="memra",
32
+ description="Query database schemas and structure"
33
+ )
34
+ ]
35
+ )
36
+
37
+ # SQL Generation Agent
38
+ sql_generator_agent = Agent(
39
+ role="SQL Generator",
40
+ job="Convert natural language to SQL queries",
41
+ output_key="generated_sql",
42
+ tools=[
43
+ Tool(
44
+ name="TextToSQLGenerator",
45
+ hosted_by="mcp",
46
+ description="Generate SQL from natural language questions",
47
+ config={
48
+ "bridge_url": "http://localhost:8081",
49
+ "bridge_secret": "test-secret-for-development"
50
+ }
51
+ )
52
+ ]
53
+ )
54
+
55
+ # SQL Execution Agent
56
+ sql_executor_agent = Agent(
57
+ role="SQL Executor",
58
+ job="Execute SQL queries and return results",
59
+ output_key="query_results",
60
+ tools=[
61
+ Tool(
62
+ name="SQLExecutor",
63
+ hosted_by="mcp",
64
+ description="Execute SQL queries against PostgreSQL database",
65
+ config={
66
+ "bridge_url": "http://localhost:8081",
67
+ "bridge_secret": "test-secret-for-development"
68
+ }
69
+ )
70
+ ]
71
+ )
72
+
73
+ return engine, schema_agent, sql_generator_agent, sql_executor_agent
74
+
75
+ def extract_database_schema(engine, schema_agent):
76
+ """Extract the database schema for context"""
77
+ print("🔍 Extracting database schema...")
78
+
79
+ schema_task = {
80
+ "task": "Extract the complete schema for the invoices table including column names, types, and sample data",
81
+ "table_name": "invoices",
82
+ "include_sample_data": True
83
+ }
84
+
85
+ result = engine.execute_task(schema_agent, schema_task)
86
+
87
+ if result.get("success"):
88
+ print(f"✅ Schema extracted successfully ({result.get('execution_time', 0):.1f}s)")
89
+ schema_data = result.get("result", {})
90
+
91
+ # Display schema info
92
+ if "schema" in schema_data:
93
+ print("\n📊 Database Schema:")
94
+ schema = schema_data["schema"]
95
+ for table_name, table_info in schema.items():
96
+ print(f" Table: {table_name}")
97
+ if "columns" in table_info:
98
+ for col in table_info["columns"]:
99
+ print(f" - {col['name']} ({col['type']})")
100
+
101
+ return schema_data
102
+ else:
103
+ print(f"❌ Schema extraction failed: {result.get('error', 'Unknown error')}")
104
+ return {}
105
+
106
+ def generate_sql_from_question(engine, sql_generator_agent, question, schema_info):
107
+ """Generate SQL from natural language question"""
108
+ print(f"\n🤖 Generating SQL for: '{question}'")
109
+
110
+ sql_generation_task = {
111
+ "question": question,
112
+ "schema_info": schema_info,
113
+ "context": "Generate SQL query for invoice database analysis"
114
+ }
115
+
116
+ result = engine.execute_task(sql_generator_agent, sql_generation_task)
117
+
118
+ if result.get("success"):
119
+ print(f"✅ SQL generated successfully ({result.get('execution_time', 0):.1f}s)")
120
+ sql_data = result.get("result", {})
121
+
122
+ generated_sql = sql_data.get("generated_sql", "")
123
+ print(f"\n📝 Generated SQL:")
124
+ print(f" {generated_sql}")
125
+
126
+ return generated_sql
127
+ else:
128
+ print(f"❌ SQL generation failed: {result.get('error', 'Unknown error')}")
129
+ return None
130
+
131
+ def execute_sql_query(engine, sql_executor_agent, sql_query):
132
+ """Execute the generated SQL query"""
133
+ print(f"\n⚡ Executing SQL query...")
134
+
135
+ execution_task = {
136
+ "sql_query": sql_query,
137
+ "timeout": 30
138
+ }
139
+
140
+ result = engine.execute_task(sql_executor_agent, execution_task)
141
+
142
+ if result.get("success"):
143
+ print(f"✅ SQL executed successfully ({result.get('execution_time', 0):.1f}s)")
144
+ query_results = result.get("result", {})
145
+
146
+ # Display results
147
+ results = query_results.get("results", [])
148
+ row_count = query_results.get("row_count", 0)
149
+
150
+ print(f"\n📋 Query Results ({row_count} rows):")
151
+ if results:
152
+ # Display first few results
153
+ for i, row in enumerate(results[:5]):
154
+ print(f" Row {i+1}: {row}")
155
+
156
+ if len(results) > 5:
157
+ print(f" ... and {len(results) - 5} more rows")
158
+ else:
159
+ print(" No results found")
160
+
161
+ return query_results
162
+ else:
163
+ print(f"❌ SQL execution failed: {result.get('error', 'Unknown error')}")
164
+ return {}
165
+
166
+ def run_text_to_sql_query(engine, schema_agent, sql_generator_agent, sql_executor_agent, question):
167
+ """Run the complete text-to-SQL pipeline"""
168
+ print(f"\n{'='*60}")
169
+ print(f"🎯 Processing Question: {question}")
170
+ print(f"{'='*60}")
171
+
172
+ # Step 1: Extract schema (cached after first run)
173
+ if not hasattr(run_text_to_sql_query, 'cached_schema'):
174
+ run_text_to_sql_query.cached_schema = extract_database_schema(engine, schema_agent)
175
+
176
+ schema_info = run_text_to_sql_query.cached_schema
177
+
178
+ # Step 2: Generate SQL
179
+ sql_query = generate_sql_from_question(engine, sql_generator_agent, question, schema_info)
180
+
181
+ if not sql_query:
182
+ return None
183
+
184
+ # Step 3: Execute SQL
185
+ results = execute_sql_query(engine, sql_executor_agent, sql_query)
186
+
187
+ return {
188
+ "question": question,
189
+ "sql_query": sql_query,
190
+ "results": results
191
+ }
192
+
193
+ def main():
194
+ """Main function to demonstrate the complete text-to-SQL system"""
195
+ print("🚀 Starting Complete Text-to-SQL System")
196
+ print("=" * 60)
197
+
198
+ # Create the system
199
+ engine, schema_agent, sql_generator_agent, sql_executor_agent = create_text_to_sql_system()
200
+
201
+ # Example questions to test
202
+ test_questions = [
203
+ "Show me all invoices from Air Liquide",
204
+ "What is the total amount of all invoices?",
205
+ "How many invoices do we have in the database?",
206
+ "Show me the most recent 5 invoices",
207
+ "What is the average invoice amount?",
208
+ ]
209
+
210
+ print("📝 Available test questions:")
211
+ for i, question in enumerate(test_questions, 1):
212
+ print(f" {i}. {question}")
213
+
214
+ print("\n" + "="*60)
215
+
216
+ # Interactive mode
217
+ while True:
218
+ print("\n🤔 What would you like to know about the invoices?")
219
+ print(" (Enter a question, number 1-5 for examples, or 'quit' to exit)")
220
+
221
+ user_input = input("\n❓ Your question: ").strip()
222
+
223
+ if user_input.lower() in ['quit', 'exit', 'q']:
224
+ print("\n👋 Goodbye!")
225
+ break
226
+
227
+ # Check if it's a number for example questions
228
+ if user_input.isdigit():
229
+ question_num = int(user_input)
230
+ if 1 <= question_num <= len(test_questions):
231
+ question = test_questions[question_num - 1]
232
+ else:
233
+ print(f"❌ Please enter a number between 1 and {len(test_questions)}")
234
+ continue
235
+ else:
236
+ question = user_input
237
+
238
+ if not question:
239
+ print("❌ Please enter a question")
240
+ continue
241
+
242
+ # Run the complete pipeline
243
+ try:
244
+ result = run_text_to_sql_query(
245
+ engine, schema_agent, sql_generator_agent, sql_executor_agent, question
246
+ )
247
+
248
+ if result:
249
+ print(f"\n✨ Query completed successfully!")
250
+
251
+ # Check if results are real or mock
252
+ results_data = result.get("results", {})
253
+ if results_data.get("_mock"):
254
+ print("ℹ️ Note: Results are mocked (MCP bridge not fully connected)")
255
+ else:
256
+ print("🎉 Real database results!")
257
+ else:
258
+ print("❌ Query failed")
259
+
260
+ except KeyboardInterrupt:
261
+ print("\n\n⏹️ Query interrupted by user")
262
+ except Exception as e:
263
+ print(f"\n❌ Error: {str(e)}")
264
+
265
+ if __name__ == "__main__":
266
+ main()
@@ -0,0 +1,156 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ File Discovery and Management Demo
4
+ Simple demonstration of intelligent file discovery tools
5
+ """
6
+
7
+ import os
8
+ import sys
9
+ sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
10
+
11
+ from memra import Agent, Department
12
+ from memra.execution import ExecutionEngine
13
+
14
+ # Set up environment
15
+ os.environ['MEMRA_API_KEY'] = 'memra-prod-2024-001'
16
+
17
+ def create_file_discovery_department():
18
+ """Create a simple department for file discovery"""
19
+ file_manager_agent = Agent(
20
+ role="File Manager",
21
+ job="Discover and manage files in directories",
22
+ sops=[
23
+ "Scan specified directory for files matching pattern",
24
+ "List all discovered files with metadata",
25
+ "Copy files from external locations to standard directories",
26
+ "Provide file selection interface for multiple files"
27
+ ],
28
+ systems=["FileSystem"],
29
+ tools=[
30
+ {"name": "FileDiscovery", "hosted_by": "mcp"}
31
+ ],
32
+ input_keys=["directory", "pattern"],
33
+ output_key="file_operations"
34
+ )
35
+
36
+ return Department(
37
+ name="File Discovery",
38
+ mission="Discover files in directories",
39
+ agents=[file_manager_agent],
40
+ workflow_order=["File Manager"],
41
+ context={
42
+ "mcp_bridge_url": "http://localhost:8081",
43
+ "mcp_bridge_secret": "test-secret-for-development"
44
+ }
45
+ )
46
+
47
+ def create_file_copy_department():
48
+ """Create a simple department for file copying"""
49
+ file_copy_agent = Agent(
50
+ role="File Copier",
51
+ job="Copy files from external locations to standard directories",
52
+ sops=[
53
+ "Accept source file path and destination directory",
54
+ "Copy file to destination with proper naming",
55
+ "Verify copy operation success",
56
+ "Return copy confirmation with metadata"
57
+ ],
58
+ systems=["FileSystem"],
59
+ tools=[
60
+ {"name": "FileCopy", "hosted_by": "mcp"}
61
+ ],
62
+ input_keys=["source_path", "destination_dir"],
63
+ output_key="file_operations"
64
+ )
65
+
66
+ return Department(
67
+ name="File Copy",
68
+ mission="Copy files to standard directories",
69
+ agents=[file_copy_agent],
70
+ workflow_order=["File Copier"],
71
+ context={
72
+ "mcp_bridge_url": "http://localhost:8081",
73
+ "mcp_bridge_secret": "test-secret-for-development"
74
+ }
75
+ )
76
+
77
+ def main():
78
+ print("📁 File Discovery and Management Demo")
79
+ print("=" * 50)
80
+
81
+ engine = ExecutionEngine()
82
+
83
+ # Demo 1: Discover files in invoices directory
84
+ print("\n🔍 Demo 1: Discover files in invoices/ directory")
85
+
86
+ discovery_dept = create_file_discovery_department()
87
+ discovery_input = {
88
+ "directory": "invoices",
89
+ "pattern": "*.pdf"
90
+ }
91
+
92
+ result = engine.execute_department(discovery_dept, discovery_input)
93
+
94
+ if result.success:
95
+ print("✅ File discovery completed!")
96
+ file_data = result.data.get('file_operations', {})
97
+
98
+ if 'files' in file_data:
99
+ print(f"\n📄 Found {file_data['files_found']} files:")
100
+ for file_info in file_data['files']:
101
+ print(f" • {file_info['filename']} ({file_info['size']}) - {file_info['modified']}")
102
+ else:
103
+ print(f"📊 Scanned: {file_data.get('directory', 'unknown')} directory")
104
+ print(f"🔍 Pattern: {file_data.get('pattern', 'unknown')}")
105
+ print(f"📁 Files found: {file_data.get('files_found', 0)}")
106
+ else:
107
+ print(f"❌ Discovery failed: {result.error}")
108
+
109
+ print("\n" + "="*50)
110
+
111
+ # Demo 2: Copy external file
112
+ print("\n📋 Demo 2: Copy external file to invoices/ directory")
113
+
114
+ copy_dept = create_file_copy_department()
115
+ copy_input = {
116
+ "source_path": "/Users/tarpus/Downloads/new_invoice.pdf",
117
+ "destination_dir": "invoices"
118
+ }
119
+
120
+ result = engine.execute_department(copy_dept, copy_input)
121
+
122
+ if result.success:
123
+ print("✅ File copy completed!")
124
+ copy_data = result.data.get('file_operations', {})
125
+
126
+ print(f"\n📁 Copy Details:")
127
+ print(f" Source: {copy_data.get('source_path', 'unknown')}")
128
+ print(f" Destination: {copy_data.get('destination_path', 'unknown')}")
129
+ print(f" Size: {copy_data.get('file_size', 'unknown')}")
130
+ print(f" Status: {copy_data.get('message', 'unknown')}")
131
+ else:
132
+ print(f"❌ Copy failed: {result.error}")
133
+
134
+ print("\n" + "="*50)
135
+
136
+ # Demo 3: Discover files in different directory
137
+ print("\n🗂 Demo 3: Discover files in documents/ directory")
138
+
139
+ docs_input = {
140
+ "directory": "documents",
141
+ "pattern": "*.*"
142
+ }
143
+
144
+ result = engine.execute_department(discovery_dept, docs_input)
145
+
146
+ if result.success:
147
+ print("✅ Document discovery completed!")
148
+ doc_data = result.data.get('file_operations', {})
149
+ print(f"📊 Scanned: {doc_data.get('directory', 'unknown')} directory")
150
+ print(f"🔍 Pattern: {doc_data.get('pattern', 'unknown')}")
151
+ print(f"📁 Files found: {doc_data.get('files_found', 0)}")
152
+ else:
153
+ print(f"❌ Document discovery failed: {result.error}")
154
+
155
+ if __name__ == "__main__":
156
+ main()
@@ -1,148 +0,0 @@
1
- Metadata-Version: 2.1
2
- Name: memra
3
- Version: 0.2.2
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
-
36
- # Memra SDK
37
-
38
- A declarative orchestration framework for AI-powered business workflows. Think of it as "Kubernetes for business logic" where agents are the pods and departments are the deployments.
39
-
40
- ## 🚀 Team Setup
41
-
42
- **New team member?** See the complete setup guide: **[TEAM_SETUP.md](TEAM_SETUP.md)**
43
-
44
- This includes:
45
- - Database setup (PostgreSQL + Docker)
46
- - Local development environment
47
- - Testing instructions
48
- - Troubleshooting guide
49
-
50
- ## Quick Start
51
-
52
- ```python
53
- from memra.sdk.models import Agent, Department, Tool
54
-
55
- # Define your agents
56
- data_extractor = Agent(
57
- role="Data Extraction Specialist",
58
- job="Extract and validate data",
59
- tools=[Tool(name="DataExtractor", hosted_by="memra")],
60
- input_keys=["input_data"],
61
- output_key="extracted_data"
62
- )
63
-
64
- # Create a department
65
- dept = Department(
66
- name="Data Processing",
67
- mission="Process and validate data",
68
- agents=[data_extractor]
69
- )
70
-
71
- # Run the workflow
72
- result = dept.run({"input_data": {...}})
73
- ```
74
-
75
- ## Installation
76
-
77
- ```bash
78
- pip install memra
79
- ```
80
-
81
- ## API Access
82
-
83
- Memra requires an API key to execute workflows on the hosted infrastructure.
84
-
85
- ### Get Your API Key
86
- Contact [info@memra.co](mailto:info@memra.co) for API access.
87
-
88
- ### Set Your API Key
89
- ```bash
90
- # Set environment variable
91
- export MEMRA_API_KEY="your-api-key-here"
92
-
93
- # Or add to your shell profile for persistence
94
- echo 'export MEMRA_API_KEY="your-api-key-here"' >> ~/.zshrc
95
- ```
96
-
97
- ### Test Your Setup
98
- ```bash
99
- python examples/accounts_payable_client.py
100
- ```
101
-
102
- ## Architecture
103
-
104
- The Memra platform consists of three main components:
105
-
106
- - **Memra SDK** (this repository): Client library for building and executing workflows
107
- - **Memra Server**: Hosted infrastructure for heavy AI processing tools
108
- - **MCP Bridge**: Local execution environment for database operations
109
-
110
- Tools are automatically routed between server and local execution based on their `hosted_by` configuration.
111
-
112
- ## Documentation
113
-
114
- Documentation is coming soon. For now, see the examples below and in the `examples/` directory.
115
-
116
- ## Example: Propane Delivery Workflow
117
-
118
- See the `examples/propane_delivery.py` file for a complete example of how to use Memra to orchestrate a propane delivery workflow.
119
-
120
- ## Contributing
121
-
122
- We welcome contributions! Please see our [contributing guide](CONTRIBUTING.md) for details.
123
-
124
- ## License
125
-
126
- This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
127
-
128
- ## Repository Structure
129
-
130
- ```
131
- ├── examples/ # Example workflows and use cases
132
- │ ├── accounts_payable_client.py # API-based accounts payable workflow
133
- │ ├── accounts_payable_mcp.py # MCP-enabled accounts payable workflow
134
- │ ├── invoice_processing.py # Simple invoice processing example
135
- │ └── propane_delivery.py # Propane delivery domain example
136
- ├── memra/ # Core SDK package
137
- │ ├── __init__.py # Package initialization
138
- │ ├── tool_registry.py # Tool discovery and routing
139
- │ └── sdk/ # SDK components
140
- │ ├── __init__.py
141
- │ ├── client.py # API client
142
- │ ├── execution_engine.py # Workflow execution
143
- │ └── models.py # Core data models
144
- ├── docs/ # Documentation
145
- ├── tests/ # Test suite
146
- ├── local/dependencies/ # Local development setup
147
- └── scripts/ # Utility scripts
148
- ```
@@ -1,13 +0,0 @@
1
- memra/__init__.py,sha256=5WPh9vku8_ZV4T6WayAqArKAj1RDkbL47SsnA9GWD7A,662
2
- memra/discovery.py,sha256=yJIQnrDQu1nyzKykCIuzG_5SW5dIXHCEBLLKRWacIoY,480
3
- memra/discovery_client.py,sha256=AbnKn6qhyrf7vmOvknEeDzH4tiGHsqPHtDaein_qaW0,1271
4
- memra/execution.py,sha256=bg822ED6yYN7APjPac1LRhv48gtxV4DUPvzpyLyBa2I,21443
5
- memra/models.py,sha256=sXMPRnMB_mUVtJdBFyd0ElCf_uh1yqx7iLssIYNm0vI,3333
6
- memra/tool_registry.py,sha256=N7kpYQxgJcSMDDCX-_6og1-of3QKEaoz6H16ptCCg48,7784
7
- memra/tool_registry_client.py,sha256=uzMQ4COvRams9vuPLcqcdljUpDlAYU_tyFxrRhrA0Lc,4009
8
- memra-0.2.2.dist-info/LICENSE,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
- memra-0.2.2.dist-info/METADATA,sha256=jrZ9AwcGtPK-pc9TGGGoi1oJzXxcGx7LUsbsd6NxcxA,4856
10
- memra-0.2.2.dist-info/WHEEL,sha256=A3WOREP4zgxI0fKrHUG8DC8013e3dK3n7a6HDbcEIwE,91
11
- memra-0.2.2.dist-info/entry_points.txt,sha256=LBVjwWoxWJRzNLgeByPn6xUvWFIRnqnemvAZgIoSt08,41
12
- memra-0.2.2.dist-info/top_level.txt,sha256=pXWcTRS1zctdiSUivW4iyKpJ4tcfIu-1BW_fpbal3OY,6
13
- memra-0.2.2.dist-info/RECORD,,
@@ -1 +0,0 @@
1
- memra