@o-lang/olang 1.2.5 โ 1.2.7
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 +1 -1
- package/src/runtime/RuntimeAPI.js +134 -39
package/package.json
CHANGED
|
@@ -331,40 +331,101 @@ class RuntimeAPI {
|
|
|
331
331
|
});
|
|
332
332
|
}
|
|
333
333
|
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
334
|
+
// -----------------------------
|
|
335
|
+
// โ
KERNEL-LEVEL LLM HALLUCINATION PREVENTION (MULTILINGUAL SEMANTIC SAFETY)
|
|
336
|
+
// -----------------------------
|
|
337
|
+
_validateLLMOutput(output, actionContext) {
|
|
338
|
+
if (!output || typeof output !== 'string') return { passed: true };
|
|
339
|
+
|
|
340
|
+
// ๐ Extract allowed capabilities from workflow allowlist
|
|
341
|
+
const allowedCapabilities = Array.from(this.allowedResolvers)
|
|
342
|
+
.filter(name => !name.startsWith('llm-') && name !== 'builtInMathResolver')
|
|
343
|
+
.map(name => name.replace('@o-lang/', '').replace(/-resolver$/, ''));
|
|
344
|
+
|
|
345
|
+
// ๐ MULTILINGUAL INTENT DETECTION (Deterministic, No LLM Required)
|
|
346
|
+
// Patterns ordered by language family โ script โ frequency
|
|
347
|
+
const forbiddenPatterns = [
|
|
348
|
+
// โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
349
|
+
// ๐ณ๐ฌ NIGERIAN LANGUAGES (Priority for your mission)
|
|
350
|
+
// โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
351
|
+
|
|
352
|
+
// Yoruba (yo) - Latin script
|
|
353
|
+
{ pattern: /\b(fi\s+(?:owo|แบนฬwแปฬ|ewo|ku|fun|s'แปkแปแป))\b/i, capability: 'transfer', lang: 'yo' },
|
|
354
|
+
{ pattern: /\b(san\s+(?:owo|แบนฬwแปฬ|ewo|fun|wo|lแบนsแบนkแบนsแบน))\b/i, capability: 'payment', lang: 'yo' },
|
|
355
|
+
{ pattern: /\b(gba\s+owo)\b/i, capability: 'withdrawal', lang: 'yo' },
|
|
356
|
+
{ pattern: /\b(mo\s+ti\s+(?:fi|san))\b/i, capability: 'unauthorized_action', lang: 'yo' }, // "I have transferred/paid"
|
|
357
|
+
|
|
358
|
+
// Hausa (ha) - Latin script
|
|
359
|
+
{ pattern: /\b(ciyar\s*(?:da)?|ciya\s*(?:da)?)\b/i, capability: 'transfer', lang: 'ha' },
|
|
360
|
+
{ pattern: /\b(biya\s*(?:da)?|sauce\s+kuษi)\b/i, capability: 'payment', lang: 'ha' },
|
|
361
|
+
{ pattern: /\b(sahawa\s+kuษi|sahawar)\b/i, capability: 'withdrawal', lang: 'ha' },
|
|
362
|
+
{ pattern: /\b(ina\s+(?:ciyar|biya))\b/i, capability: 'unauthorized_action', lang: 'ha' }, // "I am transferring/paying"
|
|
363
|
+
|
|
364
|
+
// Igbo (ig) - Latin script
|
|
365
|
+
{ pattern: /\b(zipu\s+(?:ego|moni|isi|na))\b/i, capability: 'transfer', lang: 'ig' },
|
|
366
|
+
{ pattern: /\b(buru\s+(?:ego|moni|isi))\b/i, capability: 'transfer', lang: 'ig' }, // "carry/send money"
|
|
367
|
+
{ pattern: /\b(tinye\s+(?:ego|moni|isi))\b/i, capability: 'deposit', lang: 'ig' },
|
|
368
|
+
{ pattern: /\b(m\s+(?:ziri|buru|zipuru))\b/i, capability: 'unauthorized_action', lang: 'ig' }, // "I sent/carried"
|
|
369
|
+
|
|
370
|
+
// โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
371
|
+
// ๐ GLOBAL LANGUAGES (Critical mass coverage)
|
|
372
|
+
// โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
373
|
+
|
|
374
|
+
// English (en) - Baseline
|
|
375
|
+
{ pattern: /\b(transfer|transferred|transferring|send|sent|sending|wire|wired|pay|paid|paying|withdraw|withdrew|withdrawal|deposit|deposited)\b/i, capability: 'financial_action', lang: 'en' },
|
|
376
|
+
{ pattern: /\bI\s+(?:can|will|am able to|have|'ve|did)\s+(?:transfer|send|pay|withdraw|deposit)\b/i, capability: 'unauthorized_action', lang: 'en' },
|
|
377
|
+
|
|
378
|
+
// French (fr) - Latin script
|
|
379
|
+
{ pattern: /\b(transfรฉrer|transfรฉrรฉ|transfรฉrant|envoyer|envoyรฉ|payer|payรฉ|retirer|retirรฉ|dรฉposer|dรฉposรฉ)\b/i, capability: 'financial_action', lang: 'fr' },
|
|
380
|
+
{ pattern: /\b(je\s+(?:peux|vais|ai)\s+(?:transfรฉrer|envoyer|payer))\b/i, capability: 'unauthorized_action', lang: 'fr' }, // "I can transfer/send/pay"
|
|
381
|
+
|
|
382
|
+
// Arabic (ar) - Right-to-left script (Unicode ranges)
|
|
383
|
+
{ pattern: /[\u0621-\u064A]{0,3}(?:ุญููู|ุญูู|ุฃุฑุณู|ุงุฑุณู|ุงุฏูุน|ุงุฏูุน|ุงูุฏุน|ุงูุฏุน|ุณุญุจ|ุงุณุชุฎุฑุฌ)[\u0621-\u064A]{0,3}/u, capability: 'financial_action', lang: 'ar' },
|
|
384
|
+
{ pattern: /[\u0621-\u064A]{0,3}(?:ุฃูุง)\s*(?:ุญูููุช|ุฃุฑุณูุช|ุฏูุนุช)[\u0621-\u064A]{0,3}/u, capability: 'unauthorized_action', lang: 'ar' }, // "I transferred/sent/paid"
|
|
385
|
+
|
|
386
|
+
// Chinese (zh) - Han script (Simplified)
|
|
387
|
+
{ pattern: /[\u4e00-\u9fff]{0,2}(?:่ฝฌ่ดฆ|่ฝฌๅธ|ๆฏไป|ไปๆฌพ|ๆๆฌพ|ๅๆฌพ|ๅญๆฌพ|ๅญๅ
ฅ)[\u4e00-\u9fff]{0,2}/u, capability: 'financial_action', lang: 'zh' },
|
|
388
|
+
{ pattern: /[\u4e00-\u9fff]{0,2}(?:ๆ)\s*(?:ๅทฒ|ๅทฒ็ป)?\s*(?:่ฝฌ่ดฆ|ๆฏไป|ๆๆฌพ)[\u4e00-\u9fff]{0,2}/u, capability: 'unauthorized_action', lang: 'zh' }, // "I have transferred/paid/withdrawn"
|
|
389
|
+
|
|
390
|
+
// โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
391
|
+
// ๐ก๏ธ CROSS-LINGUAL DECEPTION PATTERNS (Critical!)
|
|
392
|
+
// โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
393
|
+
|
|
394
|
+
// Numeric deception (works across ALL languages)
|
|
395
|
+
{ pattern: /\b(\d{1,3}(?:,\d{3})*(?:\.\d{2})?)\s*(?:naira|ngn|โฆ|\$|usd|dollars|euros|โฌ|yuan|ยฅ)\s+(?:sent|transferred|paid|to account)\b/i, capability: 'unauthorized_action', lang: 'multi' },
|
|
396
|
+
|
|
397
|
+
// Account number leakage (PII risk)
|
|
398
|
+
{ pattern: /\b(?:account|acct|a\/c)\s*[:\-]?\s*(\d{8,})\b/i, capability: 'pii_exposure', lang: 'multi' },
|
|
399
|
+
|
|
400
|
+
// Fake confirmation patterns
|
|
401
|
+
{ pattern: /\b(successful(?:ly)?|completed|processed|confirmed|approved)\s+(?:transaction|transfer|payment)\b/i, capability: 'deceptive_claim', lang: 'multi' }
|
|
402
|
+
];
|
|
403
|
+
|
|
404
|
+
// ๐ SCAN OUTPUT FOR FORBIDDEN INTENTS
|
|
405
|
+
for (const { pattern, capability, lang } of forbiddenPatterns) {
|
|
406
|
+
if (pattern.test(output)) {
|
|
407
|
+
// โ
Only block if capability NOT in workflow allowlist
|
|
408
|
+
const hasCapability = allowedCapabilities.some(c =>
|
|
409
|
+
c.includes(capability) ||
|
|
410
|
+
c.includes('transfer') ||
|
|
411
|
+
c.includes('payment') ||
|
|
412
|
+
c.includes('financial')
|
|
413
|
+
);
|
|
414
|
+
|
|
415
|
+
if (!hasCapability) {
|
|
416
|
+
const match = output.match(pattern);
|
|
417
|
+
return {
|
|
418
|
+
passed: false,
|
|
419
|
+
reason: `Hallucinated "${capability}" capability in ${lang} (not in workflow allowlist: ${allowedCapabilities.join(', ') || 'none'})`,
|
|
420
|
+
detected: match ? match[0].trim() : 'unknown pattern',
|
|
421
|
+
language: lang
|
|
422
|
+
};
|
|
362
423
|
}
|
|
363
424
|
}
|
|
364
|
-
|
|
365
|
-
return { passed: true };
|
|
366
425
|
}
|
|
367
426
|
|
|
427
|
+
return { passed: true };
|
|
428
|
+
}
|
|
368
429
|
// -----------------------------
|
|
369
430
|
// โ
CRITICAL FIX: Resolver output unwrapping helper
|
|
370
431
|
// -----------------------------
|
|
@@ -585,7 +646,7 @@ class RuntimeAPI {
|
|
|
585
646
|
break;
|
|
586
647
|
}
|
|
587
648
|
|
|
588
|
-
|
|
649
|
+
case 'action': {
|
|
589
650
|
// ๐ Interpolate workflow variables first
|
|
590
651
|
let action = this._safeInterpolate(
|
|
591
652
|
step.actionRaw,
|
|
@@ -633,15 +694,49 @@ class RuntimeAPI {
|
|
|
633
694
|
const rawResult = await runResolvers(action);
|
|
634
695
|
const unwrapped = this._unwrapResolverResult(rawResult);
|
|
635
696
|
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
697
|
+
// ๐ KERNEL-ENFORCED: Block LLM hallucinations BEFORE saving to context
|
|
698
|
+
// Detect LLM resolver by action pattern (comprehensive coverage)
|
|
699
|
+
const isLLMAction = action.toLowerCase().includes('groq') ||
|
|
700
|
+
action.toLowerCase().includes('openai') ||
|
|
701
|
+
action.toLowerCase().includes('anthropic') ||
|
|
702
|
+
action.toLowerCase().includes('claude') ||
|
|
703
|
+
action.toLowerCase().includes('gpt') ||
|
|
704
|
+
action.toLowerCase().includes('gemini') ||
|
|
705
|
+
action.toLowerCase().includes('google') ||
|
|
706
|
+
action.toLowerCase().includes('llama') ||
|
|
707
|
+
action.toLowerCase().includes('meta') ||
|
|
708
|
+
action.toLowerCase().includes('mistral') ||
|
|
709
|
+
action.toLowerCase().includes('mixtral') ||
|
|
710
|
+
action.toLowerCase().includes('cohere') ||
|
|
711
|
+
action.toLowerCase().includes('huggingface') ||
|
|
712
|
+
action.toLowerCase().includes('hugging-face') ||
|
|
713
|
+
action.toLowerCase().includes('together') ||
|
|
714
|
+
action.toLowerCase().includes('perplexity') ||
|
|
715
|
+
action.toLowerCase().includes('fireworks') ||
|
|
716
|
+
action.toLowerCase().includes('bedrock') ||
|
|
717
|
+
action.toLowerCase().includes('azure') ||
|
|
718
|
+
action.toLowerCase().includes('ollama') ||
|
|
719
|
+
action.toLowerCase().includes('replicate') ||
|
|
720
|
+
action.toLowerCase().includes('deepseek') ||
|
|
721
|
+
action.toLowerCase().includes('qwen') ||
|
|
722
|
+
action.toLowerCase().includes('falcon') ||
|
|
723
|
+
action.toLowerCase().includes('phi') ||
|
|
724
|
+
action.toLowerCase().includes('gemma') ||
|
|
725
|
+
action.toLowerCase().includes('stablelm') ||
|
|
726
|
+
action.toLowerCase().includes('yi') ||
|
|
727
|
+
action.toLowerCase().includes('dbrx') ||
|
|
728
|
+
action.toLowerCase().includes('command') ||
|
|
729
|
+
action.toLowerCase().includes('llm'); // Catch-all fallback
|
|
730
|
+
|
|
731
|
+
// Extract actual text from resolver output (your llm-groq returns { response: "...", ... })
|
|
732
|
+
const llmText = unwrapped?.response || // โ
Primary field for @o-lang/llm-groq
|
|
733
|
+
unwrapped?.text ||
|
|
734
|
+
unwrapped?.content ||
|
|
735
|
+
unwrapped?.answer ||
|
|
736
|
+
(typeof unwrapped === 'string' ? unwrapped : null);
|
|
642
737
|
|
|
643
|
-
if (isLLMAction && typeof
|
|
644
|
-
const safetyCheck = this._validateLLMOutput(
|
|
738
|
+
if (isLLMAction && typeof llmText === 'string') {
|
|
739
|
+
const safetyCheck = this._validateLLMOutput(llmText, action);
|
|
645
740
|
if (!safetyCheck.passed) {
|
|
646
741
|
throw new Error(
|
|
647
742
|
`[O-Lang SAFETY] LLM hallucinated unauthorized capability:\n` +
|