Nishan30 commited on
Commit
bb653a9
Β·
verified Β·
1 Parent(s): 2fb4ad7

Upload app.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. app.py +67 -12
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
- # Convert JS object notation to JSON
404
- # Replace single quotes with double quotes (but preserve n8n expressions)
405
- json_str = js_obj_str.replace("'", '"')
406
-
407
- # Add quotes around unquoted keys (e.g., {path: "data"} -> {"path": "data"})
408
- json_str = re.sub(r'(\w+):', r'"\1":', json_str)
 
 
409
 
410
- # Parse the JSON
411
- parsed = json.loads(json_str)
412
- return clean_n8n_expressions(parsed)
 
 
 
 
 
 
 
 
 
 
 
 
 
413
  except Exception as e:
414
- print(f"Warning: Could not parse parameters '{js_obj_str}': {e}")
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"