@o-lang/olang 1.2.28 → 1.2.29

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@o-lang/olang",
3
- "version": "1.2.28",
3
+ "version": "1.2.29",
4
4
  "author": "Olalekan Ogundipe <info@olang.cloud>",
5
5
  "description": "O-Lang: A governance language for user-directed, rule-enforced agent workflows",
6
6
  "main": "./src/runtime/index.js",
@@ -305,6 +305,20 @@ function parseWorkflowLines(lines, filename) {
305
305
  continue;
306
306
  }
307
307
 
308
+ // ✅ ADD: Set keyword (e.g., Set analysis_result = "")
309
+ const setMatch = line.match(/^Set\s+(\w+)\s*=\s*(.+)$/i);
310
+ if (setMatch) {
311
+ flushCurrentStep();
312
+ workflow.steps.push({
313
+ type: 'calculate',
314
+ stepNumber: workflow.steps.length + 1,
315
+ actionRaw: setMatch[2].trim(), // e.g., '""' or '"N/A"'
316
+ saveAs: setMatch[1].trim(), // e.g., 'analysis_result'
317
+ constraints: {}
318
+ });
319
+ continue;
320
+ }
321
+
308
322
  // Debrief
309
323
  const debriefMatch = line.match(/^Debrief\s+([^\s]+)\s+with\s+"([^"]*)"$/i);
310
324
  if (debriefMatch) {
@@ -589,6 +603,18 @@ function parseBlock(lines) {
589
603
  continue;
590
604
  }
591
605
 
606
+ // ✅ ADD: Set keyword inside blocks (e.g., Set analysis_result = "")
607
+ const setMatch = line.match(/^Set\s+(\w+)\s*=\s*(.+)$/i);
608
+ if (setMatch) {
609
+ flush(); // Flush any pending step
610
+ steps.push({
611
+ type: 'calculate',
612
+ actionRaw: setMatch[2].trim(), // e.g., '""' or '"N/A"'
613
+ saveAs: setMatch[1].trim(), // e.g., 'analysis_result'
614
+ constraints: {}
615
+ });
616
+ continue;
617
+ }
592
618
  // Fallback
593
619
  if (current) {
594
620
  current.actionRaw += ' ' + line; // ← PRESERVED EXACTLY (no normalizeAction)
@@ -638,17 +638,38 @@ class RuntimeAPI {
638
638
  return path.split('.').reduce((o, k) => (o && o[k] !== undefined ? o[k] : undefined), obj);
639
639
  }
640
640
 
641
- evaluateCondition(cond, ctx) {
641
+ evaluateCondition(cond, ctx) {
642
642
  cond = cond.trim();
643
- const eq = cond.match(/^\{(.+)\}\s+equals\s+"(.*)"$/);
644
- if (eq) return this.getNested(ctx, eq[1]) == eq[2];
643
+
644
+ // 1. Handle Logical OR (|| or 'or')
645
+ if (/\|\||\bor\b/i.test(cond)) {
646
+ return cond.split(/\|\||\bor\b/i).some(c => this.evaluateCondition(c.trim(), ctx));
647
+ }
648
+ // ✅ 2. Handle Logical AND (&& or 'and')
649
+ if (/&&|\band\b/i.test(cond)) {
650
+ return cond.split(/&&|\band\b/i).every(c => this.evaluateCondition(c.trim(), ctx));
651
+ }
652
+
653
+ // ✅ 3. Handle == or === (works with or without {})
654
+ const eqMatch = cond.match(/^(?:\{(.+)\}|(\w+))\s*===?\s*"(.*)"$/);
655
+ if (eqMatch) {
656
+ const key = eqMatch[1] || eqMatch[2];
657
+ return this.getNested(ctx, key) === eqMatch[3];
658
+ }
659
+
660
+ // ✅ 4. Keep original O-Lang syntax
661
+ const oldEq = cond.match(/^\{(.+)\}\s+equals\s+"(.*)"$/);
662
+ if (oldEq) return this.getNested(ctx, oldEq[1]) == oldEq[2];
663
+
645
664
  const gt = cond.match(/^\{(.+)\}\s+greater than\s+(\d+\.?\d*)$/);
646
665
  if (gt) return parseFloat(this.getNested(ctx, gt[1])) > parseFloat(gt[2]);
666
+
647
667
  const lt = cond.match(/^\{(.+)\}\s+less than\s+(\d+\.?\d*)$/);
648
668
  if (lt) return parseFloat(this.getNested(ctx, lt[1])) < parseFloat(lt[2]);
669
+
670
+ // Fallback: truthy check
649
671
  return Boolean(this.getNested(ctx, cond.replace(/\{|\}/g, '')));
650
672
  }
651
-
652
673
  mathFunctions = {
653
674
  add: (a, b) => a + b,
654
675
  subtract: (a, b) => a - b,