@o-lang/olang 1.2.1 → 1.2.2

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,24 +1,25 @@
1
1
  {
2
2
  "name": "@o-lang/olang",
3
- "version": "1.2.1",
3
+ "version": "1.2.2",
4
4
  "author": "Olalekan Ogundipe <info@workfily.com>",
5
5
  "description": "O-Lang: A governance language for user-directed, rule-enforced agent workflows",
6
6
  "main": "./src/index.js",
7
- "bin": {
8
- "olang": "./cli/olang.js"
9
- },
7
+ "bin": {
8
+ "olang": "./cli/olang.js"
9
+ },
10
10
  "files": [
11
11
  "cli.js",
12
12
  "src/"
13
13
  ],
14
14
  "scripts": {
15
- "start": "node cli.js"
15
+ "start": "node cli.js",
16
+ "test": "jest"
16
17
  },
17
18
  "dependencies": {
18
- "commander": "^12.0.0",
19
- "dotenv": "^17.2.3",
20
- "lodash": "^4.17.21",
21
- "fastify": "^4.26.0"
19
+ "commander": "^12.0.0",
20
+ "dotenv": "^17.2.3",
21
+ "fastify": "^4.26.0",
22
+ "lodash": "^4.17.21"
22
23
  },
23
24
  "keywords": [
24
25
  "agent",
@@ -37,5 +38,8 @@
37
38
  "homepage": "https://github.com/O-Lang-Central/olang-kernel",
38
39
  "publishConfig": {
39
40
  "access": "public"
41
+ },
42
+ "devDependencies": {
43
+ "jest": "^30.2.0"
40
44
  }
41
45
  }
@@ -4,7 +4,7 @@ const path = require('path');
4
4
 
5
5
  class RuntimeAPI {
6
6
  constructor({ verbose = false } = {}) {
7
- console.log('✅ KERNEL FIX VERIFIED - Unwrapping active');
7
+ // console.log('✅ KERNEL FIX VERIFIED - Unwrapping active');
8
8
  this.context = {};
9
9
  this.resources = {};
10
10
  this.agentMap = {};
@@ -552,34 +552,60 @@ class RuntimeAPI {
552
552
  break;
553
553
  }
554
554
 
555
- case 'action': {
556
- // SAFE INTERPOLATION: Block object→string coercion BEFORE resolver invocation
557
- const action = this._safeInterpolate(step.actionRaw, this.context, 'action step');
555
+ case 'action': {
556
+ // 🔒 Interpolate workflow variables first
557
+ let action = this._safeInterpolate(
558
+ step.actionRaw,
559
+ this.context,
560
+ 'action step'
561
+ );
558
562
 
559
- const mathCall = action.match(/^(add|subtract|multiply|divide|sum|avg|min|max|round|floor|ceil|abs)\((.*)\)$/i);
560
- if (mathCall) {
561
- const fn = mathCall[1].toLowerCase();
562
- const args = mathCall[2].split(',').map(s => {
563
- s = s.trim();
564
- if (!isNaN(s)) return parseFloat(s);
565
- return this.getNested(this.context, s.replace(/^\{|\}$/g, ''));
566
- });
567
- if (this.mathFunctions[fn]) {
568
- const value = this.mathFunctions[fn](...args);
569
- if (step.saveAs) this.context[step.saveAs] = value;
570
- break;
571
- }
572
- }
563
+ // CANONICALIZATION: Normalize DSL verbs → runtime Action
564
+ if (action.startsWith('Ask ')) {
565
+ action = 'Action ' + action.slice(4);
566
+ } else if (action.startsWith('Use ')) {
567
+ action = 'Action ' + action.slice(4);
568
+ }
569
+
570
+ // ❌ Reject non-canonical runtime actions early
571
+ if (!action.startsWith('Action ')) {
572
+ throw new Error(
573
+ `[O-Lang SAFETY] Non-canonical action received: "${action}"\n` +
574
+ ` → Expected format: Action <resolver> <args>\n` +
575
+ ` → This indicates a kernel or workflow authoring error.`
576
+ );
577
+ }
578
+
579
+ // ✅ Inline math support (language feature)
580
+ const mathCall = action.match(
581
+ /^(add|subtract|multiply|divide|sum|avg|min|max|round|floor|ceil|abs)\((.*)\)$/i
582
+ );
583
+
584
+ if (mathCall) {
585
+ const fn = mathCall[1].toLowerCase();
586
+ const args = mathCall[2].split(',').map(s => {
587
+ s = s.trim();
588
+ if (!isNaN(s)) return parseFloat(s);
589
+ return this.getNested(this.context, s.replace(/^\{|\}$/g, ''));
590
+ });
591
+
592
+ if (this.mathFunctions[fn]) {
593
+ const value = this.mathFunctions[fn](...args);
594
+ if (step.saveAs) this.context[step.saveAs] = value;
595
+ break;
596
+ }
597
+ }
598
+
599
+ // ✅ Resolver dispatch receives ONLY canonical actions
600
+ const rawResult = await runResolvers(action);
601
+ const unwrapped = this._unwrapResolverResult(rawResult);
602
+
603
+ if (step.saveAs) {
604
+ this.context[step.saveAs] = unwrapped;
605
+ }
606
+ break;
607
+ }
573
608
 
574
- // ✅ CRITICAL FIX: UNWRAP resolver result BEFORE saving to context
575
- const rawResult = await runResolvers(action);
576
- const unwrapped = this._unwrapResolverResult(rawResult);
577
-
578
- if (step.saveAs) {
579
- this.context[step.saveAs] = unwrapped;
580
- }
581
- break;
582
- }
583
609
 
584
610
  case 'use': {
585
611
  // ✅ SAFE INTERPOLATION for tool name