Spaces:
Running
Running
Upload app.py with huggingface_hub
Browse files
app.py
CHANGED
|
@@ -284,6 +284,19 @@ condition.to(lowPriority, 1); // FALSE path (output index 1)
|
|
| 284 |
6. Use proper n8n expression syntax: ={{{{$json.fieldName}}}}
|
| 285 |
7. Only use nodes from the list above
|
| 286 |
8. Keep workflows clean and maintainable
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 287 |
|
| 288 |
Generate ONLY the TypeScript DSL code, wrapped in ```typescript code blocks.
|
| 289 |
|
|
@@ -388,30 +401,46 @@ def clean_n8n_expressions(obj):
|
|
| 388 |
return obj
|
| 389 |
|
| 390 |
def parse_js_object(js_obj_str):
|
| 391 |
-
"""Convert JavaScript object notation to Python dict"""
|
| 392 |
if not js_obj_str or js_obj_str.strip() == "{}":
|
| 393 |
return {}
|
| 394 |
|
|
|
|
| 395 |
try:
|
| 396 |
-
# First try direct JSON parsing
|
| 397 |
parsed = json.loads(js_obj_str)
|
| 398 |
return clean_n8n_expressions(parsed)
|
| 399 |
except:
|
| 400 |
pass
|
| 401 |
|
|
|
|
| 402 |
try:
|
| 403 |
-
|
| 404 |
-
# Replace
|
| 405 |
-
|
| 406 |
-
|
| 407 |
-
|
| 408 |
-
|
|
|
|
|
|
|
| 409 |
|
| 410 |
-
|
| 411 |
-
|
| 412 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 413 |
except Exception as e:
|
| 414 |
-
print(f"Warning:
|
| 415 |
return {}
|
| 416 |
|
| 417 |
def sanitize_n8n_parameters(node_type, parameters):
|
|
@@ -478,9 +507,35 @@ def extract_balanced_braces(text, start_pos):
|
|
| 478 |
|
| 479 |
return None
|
| 480 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 481 |
def convert_to_n8n_json(typescript_code):
|
| 482 |
"""Convert TypeScript DSL to n8n JSON format"""
|
| 483 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 484 |
nodes = []
|
| 485 |
connections = {}
|
| 486 |
workflow_name = "Generated Workflow"
|
|
|
|
| 284 |
6. Use proper n8n expression syntax: ={{{{$json.fieldName}}}}
|
| 285 |
7. Only use nodes from the list above
|
| 286 |
8. Keep workflows clean and maintainable
|
| 287 |
+
9. **ALWAYS add connection calls** - Every node must be connected with `.to()`
|
| 288 |
+
10. **Keep parameters simple** - Avoid complex nested formulas
|
| 289 |
+
11. **No Excel formulas** - Don't use DATE(), IF(), FILTER(), etc. Use n8n expressions only
|
| 290 |
+
12. **Complete the code** - Include all connection statements at the end
|
| 291 |
+
|
| 292 |
+
## CRITICAL RULES:
|
| 293 |
+
|
| 294 |
+
- β **NEVER** use Excel-like formulas (DATE, IF, FILTER, MIN, MAX, etc.)
|
| 295 |
+
- β **NEVER** leave code incomplete - always add connections
|
| 296 |
+
- β **NEVER** use node types not in the list above (e.g., no `apiRequest`)
|
| 297 |
+
- β
**ALWAYS** connect all nodes with `.to()` calls
|
| 298 |
+
- β
**ALWAYS** use simple, valid JSON for parameters
|
| 299 |
+
- β
**ALWAYS** use n8n expressions like `={{{{$json.field}}}}` for dynamic values
|
| 300 |
|
| 301 |
Generate ONLY the TypeScript DSL code, wrapped in ```typescript code blocks.
|
| 302 |
|
|
|
|
| 401 |
return obj
|
| 402 |
|
| 403 |
def parse_js_object(js_obj_str):
|
| 404 |
+
"""Convert JavaScript object notation to Python dict with robust error handling"""
|
| 405 |
if not js_obj_str or js_obj_str.strip() == "{}":
|
| 406 |
return {}
|
| 407 |
|
| 408 |
+
# Try direct JSON parsing first
|
| 409 |
try:
|
|
|
|
| 410 |
parsed = json.loads(js_obj_str)
|
| 411 |
return clean_n8n_expressions(parsed)
|
| 412 |
except:
|
| 413 |
pass
|
| 414 |
|
| 415 |
+
# Try with ast.literal_eval for Python-like syntax
|
| 416 |
try:
|
| 417 |
+
import ast
|
| 418 |
+
# Replace JS booleans with Python booleans
|
| 419 |
+
python_str = js_obj_str.replace('true', 'True').replace('false', 'False').replace('null', 'None')
|
| 420 |
+
parsed = ast.literal_eval(python_str)
|
| 421 |
+
if isinstance(parsed, dict):
|
| 422 |
+
return clean_n8n_expressions(parsed)
|
| 423 |
+
except:
|
| 424 |
+
pass
|
| 425 |
|
| 426 |
+
# Last resort: Try manual key-value extraction
|
| 427 |
+
try:
|
| 428 |
+
# Extract simple key-value pairs only
|
| 429 |
+
result = {}
|
| 430 |
+
# Match simple patterns: "key": "value" or key: "value"
|
| 431 |
+
pattern = r'["\']?(\w+)["\']?\s*:\s*["\']([^"\']*)["\']'
|
| 432 |
+
matches = re.findall(pattern, js_obj_str)
|
| 433 |
+
for key, value in matches:
|
| 434 |
+
result[key] = value
|
| 435 |
+
|
| 436 |
+
if result:
|
| 437 |
+
return clean_n8n_expressions(result)
|
| 438 |
+
|
| 439 |
+
# If no matches, return empty dict to avoid breaking the workflow
|
| 440 |
+
print(f"Warning: Could not parse parameters, using empty dict. Input: {js_obj_str[:100]}...")
|
| 441 |
+
return {}
|
| 442 |
except Exception as e:
|
| 443 |
+
print(f"Warning: Complete parse failure for parameters: {str(e)[:100]}")
|
| 444 |
return {}
|
| 445 |
|
| 446 |
def sanitize_n8n_parameters(node_type, parameters):
|
|
|
|
| 507 |
|
| 508 |
return None
|
| 509 |
|
| 510 |
+
def validate_dsl_code(typescript_code):
|
| 511 |
+
"""Validate DSL code has minimum required structure"""
|
| 512 |
+
if not typescript_code or len(typescript_code.strip()) < 50:
|
| 513 |
+
return False, "Generated code is too short or empty"
|
| 514 |
+
|
| 515 |
+
if "workflow.add(" not in typescript_code:
|
| 516 |
+
return False, "No nodes found in generated code"
|
| 517 |
+
|
| 518 |
+
# Count nodes and connections
|
| 519 |
+
node_count = len(re.findall(r'const\s+\w+\s*=\s*workflow\.add\(', typescript_code))
|
| 520 |
+
connection_count = len(re.findall(r'\.to\(', typescript_code))
|
| 521 |
+
|
| 522 |
+
if node_count == 0:
|
| 523 |
+
return False, "No valid nodes found"
|
| 524 |
+
|
| 525 |
+
if node_count > 1 and connection_count == 0:
|
| 526 |
+
return False, f"Found {node_count} nodes but no connections - code may be incomplete"
|
| 527 |
+
|
| 528 |
+
return True, "OK"
|
| 529 |
+
|
| 530 |
def convert_to_n8n_json(typescript_code):
|
| 531 |
"""Convert TypeScript DSL to n8n JSON format"""
|
| 532 |
|
| 533 |
+
# Validate DSL first
|
| 534 |
+
is_valid, error_msg = validate_dsl_code(typescript_code)
|
| 535 |
+
if not is_valid:
|
| 536 |
+
print(f"β οΈ DSL Validation Warning: {error_msg}")
|
| 537 |
+
# Continue anyway but warn user
|
| 538 |
+
|
| 539 |
nodes = []
|
| 540 |
connections = {}
|
| 541 |
workflow_name = "Generated Workflow"
|