lam-cli 0.1.7__tar.gz → 1.0.0__tar.gz

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.
@@ -0,0 +1,17 @@
1
+ # Changelog
2
+
3
+ ## [0.2.0] - 2024-01-20
4
+
5
+ ### Added
6
+ - Support for handling multiple JSON objects from JQ output
7
+ - Comprehensive logging throughout JQ execution
8
+ - New test suite for JQ engine
9
+ - Better error handling and reporting
10
+
11
+ ### Changed
12
+ - JQ output processing now properly handles arrays of objects
13
+ - Improved logging verbosity and clarity
14
+ - Updated documentation structure
15
+
16
+ ### Fixed
17
+ - Issue with JQ output not being properly parsed when multiple objects are returned
lam_cli-1.0.0/DOCS.md ADDED
@@ -0,0 +1,174 @@
1
+ # LAM
2
+ LAM is a data transformation tool designed for Laminar's API integration platform.
3
+
4
+ ## Overview
5
+ LAM enables you to write efficient transformations for your API data using either JavaScript (Bun) or Python. It's designed to be secure, fast, and easy to integrate into your Laminar workflows.
6
+
7
+ ## Features
8
+ - **Dual Engine Support**: Choose between JavaScript (Bun runtime) for fast execution or Python for complex data processing
9
+ - **Built-in Libraries**: Access lodash and date-fns in JavaScript, comprehensive Python standard library modules
10
+ - **Security**: Runs in sandboxed environments with strict resource limits and security restrictions
11
+ - **Performance**: Uses Bun runtime for JavaScript and sandboxed Python interpreter
12
+ - **Monitoring**: Built-in execution statistics and error tracking
13
+
14
+ ## Execution Environments
15
+
16
+ ### Bun JavaScript Runtime (js)
17
+ **Configuration**:
18
+ - **Engine**: Bun
19
+ - **Timeout**: 5 seconds
20
+ - **Execution**: Isolated with `--no-fetch --smol --silent` flags
21
+ - **Storage**: No localStorage/sessionStorage support
22
+ - **Modules**: Shared node_modules directory
23
+
24
+ **Available Libraries**:
25
+ - **lodash** (^4.17.21): Utility library for array/object manipulation, data transformations (Global: `_`)
26
+ - **date-fns** (^2.30.0): Modern date utility library with `format`, `parseISO` functions
27
+
28
+ **Transform Function Signature**:
29
+ ```js
30
+ (input) => { /* transform logic */ return result; }
31
+ ```
32
+
33
+ ### Python Interpreter with Sandboxing (py)
34
+ **Configuration**:
35
+ - **Engine**: Python interpreter
36
+ - **Timeout**: 5 seconds
37
+ - **Memory Limit**: 100MB
38
+ - **CPU Limit**: 5 seconds (RLIMIT_CPU)
39
+ - **Virtual Memory**: 100MB (RLIMIT_AS)
40
+ - **Execution**: Isolated with `-I` flag (ignores environment/site packages)
41
+
42
+ **Security Restrictions**:
43
+ - **Blocked Modules**: subprocess, sys, os, shutil, pathlib, importlib, builtins, _thread, ctypes, socket, pickle, multiprocessing
44
+ - **Blocked Functions**: __import__, eval, exec, globals, locals, getattr, setattr, delattr, compile, open
45
+ - **Blocked Patterns**: __subclasses__, dunder attributes access
46
+
47
+ **Available Standard Library Modules**:
48
+ - **json**: JSON encoder and decoder
49
+ - **datetime**: Date and time handling
50
+ - **time**: Time-related functions
51
+ - **math**: Mathematical functions and constants
52
+ - **statistics**: Statistical functions (mean, median, mode, standard deviation)
53
+ - **collections**: Counter, defaultdict, OrderedDict, deque
54
+ - **itertools**: Efficient looping, combinations, permutations
55
+ - **functools**: reduce, partial, lru_cache
56
+ - **re**: Regular expression operations
57
+ - **copy**: Shallow and deep copy operations
58
+ - **decimal**: Precise decimal calculations
59
+ - **csv**: CSV file reading and writing
60
+ - **io**: StringIO, BytesIO for in-memory files
61
+ - **dataclasses**: Data classes for storing data
62
+ - **typing**: Type hints support
63
+ - **enum**: Support for enumerations
64
+ - **random**: Random number generation
65
+ - **uuid**: UUID generation
66
+ - **hashlib**: Secure hash and message digest algorithms
67
+ - **base64**: Base64 encoding and decoding
68
+ - **urllib**: URL handling modules
69
+ - **urllib.parse**: URL parsing utilities
70
+ - **html**: HTML processing utilities
71
+ - **xml**: XML processing
72
+ - **xml.etree**: XML ElementTree API
73
+ - **xml.etree.ElementTree**: XML parsing and creation
74
+ - **string**: String constants and classes
75
+ - **textwrap**: Text wrapping and filling
76
+ - **operator**: Standard operators as functions
77
+ - **bisect**: Array bisection algorithm
78
+ - **heapq**: Heap queue algorithm
79
+ - **array**: Efficient arrays of numeric values
80
+ - **unicodedata**: Unicode character database
81
+ - **locale**: Internationalization services
82
+ - **calendar**: Calendar-related functions
83
+ - **zoneinfo**: Time zone support (Python 3.9+)
84
+ - **struct**: Pack and unpack binary data
85
+ - **binascii**: Binary/ASCII conversions
86
+ - **codecs**: Encode and decode data
87
+ - **difflib**: Sequence comparison utilities
88
+ - **pprint**: Pretty-printer for data structures
89
+ - **reprlib**: Alternate repr() implementation
90
+ - **abc**: Abstract base classes
91
+ - **contextlib**: Context management utilities
92
+ - **secrets**: Cryptographically secure random numbers
93
+ - **fractions**: Rational numbers
94
+ - **numbers**: Numeric abstract base classes
95
+
96
+ **Safe Built-in Functions**:
97
+ `abs`, `all`, `any`, `bool`, `chr`, `dict`, `divmod`, `enumerate`, `filter`, `float`, `format`, `frozenset`, `hash`, `hex`, `int`, `isinstance`, `issubclass`, `iter`, `len`, `list`, `map`, `max`, `min`, `next`, `oct`, `ord`, `pow`, `print`, `range`, `repr`, `reversed`, `round`, `set`, `slice`, `sorted`, `str`, `sum`, `tuple`, `type`, `zip`
98
+
99
+ **Transform Function Signature**:
100
+ ```py
101
+ def transform(input_data):
102
+ # transform logic
103
+ return result
104
+ ```
105
+
106
+ ## Examples
107
+
108
+ ### JavaScript (Bun) Transformations
109
+ Perfect for fast data manipulation with familiar syntax:
110
+
111
+ ```javascript
112
+ (input) => {
113
+ // Use lodash for data manipulation
114
+ const processed = _.map(input.data, item => ({
115
+ id: item.id,
116
+ formattedDate: format(parseISO(item.date), 'MMM dd, yyyy'),
117
+ value: item.value * 2
118
+ }));
119
+
120
+ return {
121
+ processed,
122
+ summary: {
123
+ total: _.sumBy(processed, 'value'),
124
+ count: processed.length
125
+ }
126
+ };
127
+ }
128
+ ```
129
+
130
+ ### Python Transformations
131
+ Ideal for complex data processing and statistical analysis:
132
+
133
+ ```python
134
+ def transform(input_data):
135
+ import statistics
136
+ from collections import Counter
137
+
138
+ # Process numerical data
139
+ values = [item["value"] for item in input_data["data"] if "value" in item]
140
+
141
+ return {
142
+ "statistics": {
143
+ "mean": statistics.mean(values) if values else 0,
144
+ "median": statistics.median(values) if values else 0,
145
+ "count": len(values)
146
+ },
147
+ "frequency": dict(Counter(item["category"] for item in input_data["data"])),
148
+ "processedAt": datetime.now().isoformat()
149
+ }
150
+ ```
151
+
152
+ ## Integration with Laminar
153
+ LAM is designed to work seamlessly with Laminar's integration platform:
154
+
155
+ 1. **Flows**: Add data transformations to your API flows
156
+ 2. **Automation**: Schedule and automate data processing
157
+ 3. **Monitoring**: Track execution statistics and errors
158
+
159
+ ## Getting Started
160
+
161
+ ### Using LAM in Laminar
162
+ 1. Create a new flow in [Laminar](https://app.laminar.run)
163
+ 2. Add a transformation step
164
+ 3. Choose your engine (JavaScript or Python)
165
+ 4. Write your transformation function
166
+ 5. Deploy and monitor
167
+
168
+ ## Resources
169
+ - [Laminar Documentation](https://docs.laminar.run)
170
+ - [Sign up for Laminar](https://app.laminar.run)
171
+
172
+ ## Support
173
+ Get help with LAM:
174
+ - [Contact Support](mailto:connect@laminar.run)
@@ -0,0 +1,5 @@
1
+ include DOCS.md
2
+ include README.md
3
+ include LICENSE
4
+ include CHANGELOG.md
5
+ include requirements.txt
lam_cli-1.0.0/PKG-INFO ADDED
@@ -0,0 +1,229 @@
1
+ Metadata-Version: 2.4
2
+ Name: lam-cli
3
+ Version: 1.0.0
4
+ Summary: Secure data transformation tool supporting JQ and JavaScript (Bun)
5
+ Home-page: https://github.com/laminar-run/lam
6
+ Author: Laminar Run, Inc.
7
+ Author-email: connect@laminar.run
8
+ License: GPLv3
9
+ Project-URL: Documentation, https://docs.laminar.run
10
+ Project-URL: Source, https://github.com/laminar-run/lam
11
+ Project-URL: Issue Tracker, https://github.com/laminar-run/lam/issues
12
+ Keywords: laminar,api,integration,transformation,json,jq,javascript,bun
13
+ Classifier: Development Status :: 4 - Beta
14
+ Classifier: Environment :: Console
15
+ Classifier: Intended Audience :: Developers
16
+ Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
17
+ Classifier: Operating System :: OS Independent
18
+ Classifier: Programming Language :: Python :: 3
19
+ Classifier: Programming Language :: Python :: 3.9
20
+ Classifier: Programming Language :: Python :: 3.10
21
+ Classifier: Programming Language :: Python :: 3.11
22
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
23
+ Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
24
+ Classifier: Topic :: Software Development :: Build Tools
25
+ Requires-Python: >=3.9
26
+ Description-Content-Type: text/markdown
27
+ License-File: LICENSE
28
+ Requires-Dist: backoff>=2.2.1
29
+ Requires-Dist: certifi>=2024.12.14
30
+ Requires-Dist: charset-normalizer>=3.3.2
31
+ Requires-Dist: click>=8.1.7
32
+ Requires-Dist: idna>=3.7
33
+ Requires-Dist: logtail-python>=0.2.2
34
+ Requires-Dist: monotonic>=1.6
35
+ Requires-Dist: msgpack>=1.0.8
36
+ Requires-Dist: posthog>=3.4.0
37
+ Requires-Dist: psutil>=5.9.0
38
+ Requires-Dist: python-dateutil>=2.8.2
39
+ Requires-Dist: requests>=2.32.3
40
+ Requires-Dist: six>=1.16.0
41
+ Requires-Dist: urllib3>=2.2.2
42
+ Dynamic: author
43
+ Dynamic: author-email
44
+ Dynamic: classifier
45
+ Dynamic: description
46
+ Dynamic: description-content-type
47
+ Dynamic: home-page
48
+ Dynamic: keywords
49
+ Dynamic: license
50
+ Dynamic: license-file
51
+ Dynamic: project-url
52
+ Dynamic: requires-dist
53
+ Dynamic: requires-python
54
+ Dynamic: summary
55
+
56
+ # LAM
57
+ LAM is a data transformation tool designed for Laminar's API integration platform.
58
+
59
+ ## Overview
60
+ LAM enables you to write efficient transformations for your API data using either JavaScript (Bun) or Python. It's designed to be secure, fast, and easy to integrate into your Laminar workflows.
61
+
62
+ ## Features
63
+ - **Dual Engine Support**: Choose between JavaScript (Bun runtime) for fast execution or Python for complex data processing
64
+ - **Built-in Libraries**: Access lodash and date-fns in JavaScript, comprehensive Python standard library modules
65
+ - **Security**: Runs in sandboxed environments with strict resource limits and security restrictions
66
+ - **Performance**: Uses Bun runtime for JavaScript and sandboxed Python interpreter
67
+ - **Monitoring**: Built-in execution statistics and error tracking
68
+
69
+ ## Execution Environments
70
+
71
+ ### Bun JavaScript Runtime (js)
72
+ **Configuration**:
73
+ - **Engine**: Bun
74
+ - **Timeout**: 5 seconds
75
+ - **Execution**: Isolated with `--no-fetch --smol --silent` flags
76
+ - **Storage**: No localStorage/sessionStorage support
77
+ - **Modules**: Shared node_modules directory
78
+
79
+ **Available Libraries**:
80
+ - **lodash** (^4.17.21): Utility library for array/object manipulation, data transformations (Global: `_`)
81
+ - **date-fns** (^2.30.0): Modern date utility library with `format`, `parseISO` functions
82
+
83
+ **Transform Function Signature**:
84
+ ```js
85
+ (input) => { /* transform logic */ return result; }
86
+ ```
87
+
88
+ ### Python Interpreter with Sandboxing (py)
89
+ **Configuration**:
90
+ - **Engine**: Python interpreter
91
+ - **Timeout**: 5 seconds
92
+ - **Memory Limit**: 100MB
93
+ - **CPU Limit**: 5 seconds (RLIMIT_CPU)
94
+ - **Virtual Memory**: 100MB (RLIMIT_AS)
95
+ - **Execution**: Isolated with `-I` flag (ignores environment/site packages)
96
+
97
+ **Security Restrictions**:
98
+ - **Blocked Modules**: subprocess, sys, os, shutil, pathlib, importlib, builtins, _thread, ctypes, socket, pickle, multiprocessing
99
+ - **Blocked Functions**: __import__, eval, exec, globals, locals, getattr, setattr, delattr, compile, open
100
+ - **Blocked Patterns**: __subclasses__, dunder attributes access
101
+
102
+ **Available Standard Library Modules**:
103
+ - **json**: JSON encoder and decoder
104
+ - **datetime**: Date and time handling
105
+ - **time**: Time-related functions
106
+ - **math**: Mathematical functions and constants
107
+ - **statistics**: Statistical functions (mean, median, mode, standard deviation)
108
+ - **collections**: Counter, defaultdict, OrderedDict, deque
109
+ - **itertools**: Efficient looping, combinations, permutations
110
+ - **functools**: reduce, partial, lru_cache
111
+ - **re**: Regular expression operations
112
+ - **copy**: Shallow and deep copy operations
113
+ - **decimal**: Precise decimal calculations
114
+ - **csv**: CSV file reading and writing
115
+ - **io**: StringIO, BytesIO for in-memory files
116
+ - **dataclasses**: Data classes for storing data
117
+ - **typing**: Type hints support
118
+ - **enum**: Support for enumerations
119
+ - **random**: Random number generation
120
+ - **uuid**: UUID generation
121
+ - **hashlib**: Secure hash and message digest algorithms
122
+ - **base64**: Base64 encoding and decoding
123
+ - **urllib**: URL handling modules
124
+ - **urllib.parse**: URL parsing utilities
125
+ - **html**: HTML processing utilities
126
+ - **xml**: XML processing
127
+ - **xml.etree**: XML ElementTree API
128
+ - **xml.etree.ElementTree**: XML parsing and creation
129
+ - **string**: String constants and classes
130
+ - **textwrap**: Text wrapping and filling
131
+ - **operator**: Standard operators as functions
132
+ - **bisect**: Array bisection algorithm
133
+ - **heapq**: Heap queue algorithm
134
+ - **array**: Efficient arrays of numeric values
135
+ - **unicodedata**: Unicode character database
136
+ - **locale**: Internationalization services
137
+ - **calendar**: Calendar-related functions
138
+ - **zoneinfo**: Time zone support (Python 3.9+)
139
+ - **struct**: Pack and unpack binary data
140
+ - **binascii**: Binary/ASCII conversions
141
+ - **codecs**: Encode and decode data
142
+ - **difflib**: Sequence comparison utilities
143
+ - **pprint**: Pretty-printer for data structures
144
+ - **reprlib**: Alternate repr() implementation
145
+ - **abc**: Abstract base classes
146
+ - **contextlib**: Context management utilities
147
+ - **secrets**: Cryptographically secure random numbers
148
+ - **fractions**: Rational numbers
149
+ - **numbers**: Numeric abstract base classes
150
+
151
+ **Safe Built-in Functions**:
152
+ `abs`, `all`, `any`, `bool`, `chr`, `dict`, `divmod`, `enumerate`, `filter`, `float`, `format`, `frozenset`, `hash`, `hex`, `int`, `isinstance`, `issubclass`, `iter`, `len`, `list`, `map`, `max`, `min`, `next`, `oct`, `ord`, `pow`, `print`, `range`, `repr`, `reversed`, `round`, `set`, `slice`, `sorted`, `str`, `sum`, `tuple`, `type`, `zip`
153
+
154
+ **Transform Function Signature**:
155
+ ```py
156
+ def transform(input_data):
157
+ # transform logic
158
+ return result
159
+ ```
160
+
161
+ ## Examples
162
+
163
+ ### JavaScript (Bun) Transformations
164
+ Perfect for fast data manipulation with familiar syntax:
165
+
166
+ ```javascript
167
+ (input) => {
168
+ // Use lodash for data manipulation
169
+ const processed = _.map(input.data, item => ({
170
+ id: item.id,
171
+ formattedDate: format(parseISO(item.date), 'MMM dd, yyyy'),
172
+ value: item.value * 2
173
+ }));
174
+
175
+ return {
176
+ processed,
177
+ summary: {
178
+ total: _.sumBy(processed, 'value'),
179
+ count: processed.length
180
+ }
181
+ };
182
+ }
183
+ ```
184
+
185
+ ### Python Transformations
186
+ Ideal for complex data processing and statistical analysis:
187
+
188
+ ```python
189
+ def transform(input_data):
190
+ import statistics
191
+ from collections import Counter
192
+
193
+ # Process numerical data
194
+ values = [item["value"] for item in input_data["data"] if "value" in item]
195
+
196
+ return {
197
+ "statistics": {
198
+ "mean": statistics.mean(values) if values else 0,
199
+ "median": statistics.median(values) if values else 0,
200
+ "count": len(values)
201
+ },
202
+ "frequency": dict(Counter(item["category"] for item in input_data["data"])),
203
+ "processedAt": datetime.now().isoformat()
204
+ }
205
+ ```
206
+
207
+ ## Integration with Laminar
208
+ LAM is designed to work seamlessly with Laminar's integration platform:
209
+
210
+ 1. **Flows**: Add data transformations to your API flows
211
+ 2. **Automation**: Schedule and automate data processing
212
+ 3. **Monitoring**: Track execution statistics and errors
213
+
214
+ ## Getting Started
215
+
216
+ ### Using LAM in Laminar
217
+ 1. Create a new flow in [Laminar](https://app.laminar.run)
218
+ 2. Add a transformation step
219
+ 3. Choose your engine (JavaScript or Python)
220
+ 4. Write your transformation function
221
+ 5. Deploy and monitor
222
+
223
+ ## Resources
224
+ - [Laminar Documentation](https://docs.laminar.run)
225
+ - [Sign up for Laminar](https://app.laminar.run)
226
+
227
+ ## Support
228
+ Get help with LAM:
229
+ - [Contact Support](mailto:connect@laminar.run)
@@ -116,6 +116,9 @@ make test-js-edge-cases
116
116
 
117
117
  # Run single test
118
118
  make test-single TEST=test/js/example.js DATA=test/data/input.json
119
+
120
+ # Or
121
+ python -m lam.lam run --language js test/js/simple.js test/data/simple.json
119
122
  ```
120
123
 
121
124
  ## Releases
@@ -0,0 +1,95 @@
1
+ #!/usr/bin/env python3
2
+
3
+ import logging
4
+ import os
5
+ import shutil
6
+ import tempfile
7
+ from datetime import datetime, timezone
8
+ from pathlib import Path
9
+ from typing import Optional
10
+
11
+ import psutil
12
+ from logtail import LogtailHandler
13
+
14
+
15
+ def setup_logging():
16
+ """Configure logging with UTC timezone and handlers"""
17
+ # Configure logging with UTC timezone
18
+ logging.Formatter.converter = lambda *args: datetime.now(timezone.utc).timetuple()
19
+
20
+ # Set up root logger configuration
21
+ logging.basicConfig(
22
+ level=logging.DEBUG,
23
+ format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
24
+ force=True # Override any existing configuration
25
+ )
26
+
27
+ # Suppress noisy loggers
28
+ logging.getLogger('urllib3').setLevel(logging.WARNING)
29
+
30
+ # Add LogTail handler to root logger
31
+ root_logger = logging.getLogger()
32
+ handler = LogtailHandler(source_token="TYz3WrrvC8ehYjXdAEGGyiDp")
33
+ root_logger.addHandler(handler)
34
+
35
+ return logging.getLogger(__name__)
36
+
37
+
38
+ class LAMError(Exception):
39
+ """Base exception for LAM errors"""
40
+ pass
41
+
42
+
43
+ class UserError(LAMError):
44
+ """Errors caused by user input"""
45
+ pass
46
+
47
+
48
+ class SystemError(LAMError):
49
+ """Errors caused by system issues"""
50
+ pass
51
+
52
+
53
+ class ResourceLimitError(LAMError):
54
+ """Errors caused by resource limits"""
55
+ pass
56
+
57
+
58
+ class ProcessingError(Exception):
59
+ """Custom exception for processing errors"""
60
+ pass
61
+
62
+
63
+ def check_resource_limits(modules_dir: Optional[Path] = None) -> None:
64
+ """Check system resource availability"""
65
+ disk = shutil.disk_usage(tempfile.gettempdir())
66
+ if disk.free < 100 * 1024 * 1024: # 100MB minimum
67
+ raise ResourceLimitError("Insufficient disk space")
68
+
69
+ if modules_dir and modules_dir.exists():
70
+ modules_size = sum(
71
+ os.path.getsize(os.path.join(dirpath, filename))
72
+ for dirpath, _, filenames in os.walk(modules_dir)
73
+ for filename in filenames
74
+ )
75
+ if modules_size > 500 * 1024 * 1024:
76
+ shutil.rmtree(modules_dir)
77
+ modules_dir.mkdir(exist_ok=True)
78
+
79
+
80
+ class Stats:
81
+ """Track execution statistics"""
82
+ def __init__(self):
83
+ self.start_time = datetime.now()
84
+ self.memory_start = self.get_memory_usage()
85
+
86
+ def get_memory_usage(self):
87
+ process = psutil.Process()
88
+ return process.memory_info().rss
89
+
90
+ def finalize(self):
91
+ return {
92
+ 'duration_ms': (datetime.now() - self.start_time).total_seconds() * 1000,
93
+ 'memory_used_mb': (self.get_memory_usage() - self.memory_start) / (1024 * 1024),
94
+ 'timestamp': datetime.now().isoformat()
95
+ }
@@ -0,0 +1,23 @@
1
+ from .base import Engine, EngineType
2
+ from .javascript import BunEngine
3
+ from .jq import JQEngine
4
+ from .python import PythonEngine
5
+
6
+
7
+ def get_engine(engine_type: str, workspace_id: str, flow_id: str, execution_id: str) -> Engine:
8
+ """Factory function to get the appropriate execution engine"""
9
+ engines = {
10
+ EngineType.JQ.value: JQEngine,
11
+ EngineType.JAVASCRIPT.value: BunEngine,
12
+ EngineType.PYTHON.value: PythonEngine
13
+ }
14
+
15
+ engine_class = engines.get(engine_type)
16
+ if not engine_class:
17
+ raise ValueError(f"Unsupported engine type: {engine_type}")
18
+
19
+ engine = engine_class(workspace_id, flow_id, execution_id)
20
+ if not engine.validate_environment():
21
+ raise EnvironmentError(f"Required dependencies not found for {engine_type}")
22
+
23
+ return engine
@@ -0,0 +1,56 @@
1
+ import logging
2
+ import os
3
+ import socket
4
+ from datetime import datetime
5
+ from enum import Enum
6
+ from typing import Any, Dict, Optional, Tuple, Union
7
+
8
+ from posthog import Posthog
9
+
10
+ # Initialize analytics
11
+ posthog = Posthog(project_api_key='phc_wfeHFG0p5yZIdBpjVYy00o5x1HbEpggdMzIuFYgNPSK',
12
+ host='https://app.posthog.com')
13
+
14
+ logger = logging.getLogger(__name__)
15
+
16
+
17
+ class EngineType(Enum):
18
+ JQ = "jq"
19
+ JAVASCRIPT = "js"
20
+ PYTHON = "py"
21
+
22
+
23
+ class Engine:
24
+ """Base class for execution engines"""
25
+ def __init__(self, workspace_id: str, flow_id: str, execution_id: str):
26
+ self.workspace_id = workspace_id
27
+ self.flow_id = flow_id
28
+ self.execution_id = execution_id
29
+ self.timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
30
+
31
+ def get_log_file(self) -> str:
32
+ return f"lam_run_{self.workspace_id}_{self.flow_id}_{self.execution_id}_{self.timestamp}.log"
33
+
34
+ def get_result_file(self) -> str:
35
+ return f"lam_result_{self.workspace_id}_{self.flow_id}_{self.execution_id}_{self.timestamp}.json"
36
+
37
+ def track_event(self, event_name: str, properties: Dict[str, Any]) -> None:
38
+ """Track events with PostHog"""
39
+ try:
40
+ distinct_id = f"{os.getuid()}_{socket.gethostname()}_{self.workspace_id}_{self.flow_id}"
41
+ properties |= {
42
+ 'workspace_id': self.workspace_id,
43
+ 'flow_id': self.flow_id,
44
+ 'engine': self.__class__.__name__,
45
+ }
46
+ posthog.capture(distinct_id=distinct_id, event=event_name, properties=properties)
47
+ except Exception as e:
48
+ logger.error(f"Error tracking event: {e}")
49
+
50
+ def validate_environment(self) -> bool:
51
+ """Validate that the engine can run in this environment"""
52
+ raise NotImplementedError
53
+
54
+ def execute(self, program_file: str, input_data: str) -> Tuple[Union[Dict, str], Optional[str]]:
55
+ """Execute the program with input data"""
56
+ raise NotImplementedError