data-primals-engine 1.3.3-rc.1 → 1.3.4

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.
@@ -23,6 +23,7 @@ import {getHost} from "../constants.js";
23
23
  import {providers} from "./assistant/constants.js";
24
24
  import {ChatAnthropic} from "@langchain/anthropic";
25
25
  import {getAIProvider} from "./assistant/assistant.js";
26
+ import {escapeRegex} from "../core.js";
26
27
 
27
28
  let logger = null;
28
29
  export async function onInit(defaultEngine) {
@@ -32,7 +33,6 @@ export async function onInit(defaultEngine) {
32
33
  }
33
34
 
34
35
 
35
-
36
36
  /**
37
37
  * Déclenche un workflow par son nom et lui passe des données de contexte.
38
38
  * C'est la fonction clé à exposer aux endpoints pour lancer des processus métier.
@@ -284,8 +284,14 @@ export async function executeSafeJavascript(actionDef, context, user) {
284
284
  await jail.set('_db_find', new ivm.Reference(find));
285
285
  await jail.set('_db_findOne', new ivm.Reference(findOne));
286
286
 
287
- await jail.set('_db_update', new ivm.Reference(async (modelName, filter, updateObject) => patchData(modelName, JSON.parse(filter), JSON.parse(updateObject), {}, user, false)));
288
- await jail.set('_db_delete', new ivm.Reference(async (modelName, filter) => deleteData(modelName, JSON.parse(filter), user, false)));
287
+ await jail.set('_db_update', new ivm.Reference(async (modelName, filter, updateObject) => {
288
+ const result = await patchData(modelName, JSON.parse(filter), JSON.parse(updateObject), {}, user, false);
289
+ return new ivm.ExternalCopy(result).copyInto();
290
+ }));
291
+ await jail.set('_db_delete', new ivm.Reference(async (modelName, filter) => {
292
+ const result = await deleteData(modelName, JSON.parse(filter), user, false);
293
+ return new ivm.ExternalCopy(result).copyInto();
294
+ }));
289
295
 
290
296
  const createLoggerMethod = (level) => {
291
297
  return (...args) => {
@@ -311,9 +317,29 @@ export async function executeSafeJavascript(actionDef, context, user) {
311
317
  const result = await getEnv(user);
312
318
  return new ivm.ExternalCopy(result).copyInto();
313
319
  }));
320
+ await jail.set('_http_request', new ivm.Reference(async (method, url, optionsStr) => {
321
+ try {
322
+ const options = optionsStr ? JSON.parse(optionsStr) : {};
323
+ const fetchOptions = {
324
+ method: method.toUpperCase(),
325
+ headers: options.headers || {},
326
+ body: options.body ? (typeof options.body === 'object' ? JSON.stringify(options.body) : options.body) : undefined
327
+ };
328
+
329
+ const response = await fetch(url, fetchOptions);
330
+ const responseBody = await response.json().catch(() => response.text());
331
+
332
+ const result = { success: response.ok, status: response.status, body: responseBody };
333
+ return new ivm.ExternalCopy(result).copyInto();
334
+ } catch (error) {
335
+ logger.error(`[VM http_request] Error: ${error.message}`);
336
+ return new ivm.ExternalCopy({ success: false, message: error.message }).copyInto();
337
+ }
338
+ }));
314
339
 
315
340
  // Contexte sécurisé
316
341
  const safeContext = JSON.parse(JSON.stringify(context));
342
+
317
343
  await jail.set('context', new ivm.ExternalCopy(safeContext).copyInto());
318
344
 
319
345
  // Exécution
@@ -347,6 +373,10 @@ export async function executeSafeJavascript(actionDef, context, user) {
347
373
  getAll: _env_get_all
348
374
  };
349
375
 
376
+ const http = {
377
+ request: (...args) => _http_request.applySyncPromise(null, normalizeArgs(args))
378
+ };
379
+
350
380
  (async function() {
351
381
  ${code}
352
382
  })();
@@ -360,13 +390,22 @@ export async function executeSafeJavascript(actionDef, context, user) {
360
390
  copy: true // Copie automatique du résultat
361
391
  });
362
392
 
363
- return {
364
- success: true,
365
- data: result,
366
- logs: collectedLogs,
367
- updatedContext: { result }
368
- };
393
+ // Vérifier si le script lui-même a signalé un échec.
394
+ if (result && typeof result === 'object' && result.success === false) {
395
+ const scriptMessage = result.message || 'Le script a signalé un échec sans message.';
396
+ collectedLogs.push({
397
+ level: 'warn',
398
+ message: `Script reported failure: ${scriptMessage}`,
399
+ timestamp: new Date().toISOString()
400
+ });
401
+ return {
402
+ success: false,
403
+ message: scriptMessage,
404
+ logs: collectedLogs
405
+ };
406
+ }
369
407
 
408
+ return { success: true, data: result, logs: collectedLogs, updatedContext: { result } };
370
409
  } catch (error) {
371
410
  const errorMessage = `Script execution failed: ${error.message}`;
372
411
  const finalErrorMessage = logger.trace('critical', `[VM Script] ${errorMessage}\n${error.stack}`);
@@ -1445,9 +1484,18 @@ export async function processWorkflowRun(workflowRunId, user) {
1445
1484
  // --- 7. Évaluation des conditions de l'étape ---
1446
1485
  if (currentStepDef.conditions && Object.keys(currentStepDef.conditions).length > 0) {
1447
1486
  const substitutedConditions = await substituteVariables(currentStepDef.conditions, contextData, user);
1448
- const searchResult = await searchData({ model: contextData.triggerDataModel, filter: substitutedConditions, limit: 1}, user);
1449
- conditionsMet = searchResult && searchResult.count > 0;
1450
- logger.info(`[processWorkflowRun] Run ID: ${runId}, Step ID: ${currentStepId}: Conditions evaluated. Found ${searchResult ? searchResult.count : 0} match(es). Result: ${conditionsMet}`);
1487
+ // Si un modèle est spécifié dans le contexte, la condition est une requête sur la base de données.
1488
+ if (contextData.triggerDataModel) {
1489
+ const searchResult = await searchData({ model: contextData.triggerDataModel, filter: substitutedConditions, limit: 1 }, user);
1490
+ conditionsMet = searchResult && searchResult.count > 0;
1491
+ logger.info(`[processWorkflowRun] Run ID: ${runId}, Step ID: ${currentStepId}: DB condition evaluated. Found ${searchResult ? searchResult.count : 0} match(es). Result: ${conditionsMet}`);
1492
+ } else {
1493
+ console.log({substitutedConditions, c:contextData['triggerData']['event']['type']});
1494
+ // Si aucun modèle n'est spécifié (ex: webhook), la condition est évaluée sur l'objet de contexte lui-même.
1495
+ conditionsMet = isConditionMet(null, substitutedConditions, contextData, [], user);
1496
+
1497
+ logger.info(`[processWorkflowRun] Run ID: ${runId}, Step ID: ${currentStepId}: Context condition evaluated. Operator: ${JSON.stringify(substitutedConditions)}, Result: ${conditionsMet}`);
1498
+ }
1451
1499
  }
1452
1500
 
1453
1501
  // --- 8. Exécution des actions si les conditions sont remplies ---