@arcadialdev/arcality 2.4.36 → 2.4.37

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": "@arcadialdev/arcality",
3
- "version": "2.4.36",
3
+ "version": "2.4.37",
4
4
  "description": "AI-powered QA testing tool — Autonomous web testing agent by Arcadial",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -939,11 +939,11 @@ ${relevantFailures.map((m) => `- ${m.prompt}`).join("\n")}
939
939
  const role = htmlEl.getAttribute("role") || "";
940
940
  const text = (htmlEl.innerText || htmlEl.getAttribute("aria-label") || htmlEl.getAttribute("title") || "").trim().replace(/\s+/g, " ");
941
941
  const textLower = text.toLowerCase();
942
- const isCriticalFailure = (textLower.includes("error") || textLower.includes("fall\xF3") || textLower.includes("no se puede") || textLower.includes("ya existe") || textLower.includes("existe") || textLower.includes("inv\xE1lido") || textLower.includes("incorrecto") || textLower.includes("ligado") || textLower.includes("depende") || textLower.includes("duplicado") || textLower.includes("repetido") || /* Validaciones ZOD / Wizard de campos de formulario */
942
+ const isCriticalFailure = (textLower.includes("error") || textLower.includes("fall\xF3") || textLower.includes("no se puede") || textLower.includes("ya existe") || textLower.includes("inv\xE1lido") || textLower.includes("incorrecto") || textLower.includes("ligado") || textLower.includes("depende") || textLower.includes("duplicado") || textLower.includes("repetido") || /* Validaciones ZOD / Wizard de campos de formulario */
943
943
  textLower.includes("debe ser mayor") || textLower.includes("debe ser menor") || textLower.includes("debe ser igual") || textLower.includes("debe ser mayor o igual") || textLower.includes("debe ser menor o igual") || /* ZOD date messages (Spanish) */
944
944
  textLower.includes("debe ser posterior") || textLower.includes("debe ser anterior") || textLower.includes("debe ser una fecha") || textLower.includes("fecha debe ser") || textLower.includes("posterior o igual a la fecha") || textLower.includes("anterior o igual a la fecha") || textLower.includes("posterior a la fecha") || textLower.includes("anterior a la fecha") || textLower.includes("fecha") && (textLower.includes("actual") || textLower.includes("pasada") || textLower.includes("futura") || textLower.includes("requerida") || textLower.includes("inv\xE1lida") || textLower.includes("incorrecta") || textLower.includes("posterior") || textLower.includes("anterior")) || /* ZOD number/range messages */
945
- textLower.includes("debe ser un n\xFAmero") || textLower.includes("debe ser positivo") || textLower.includes("debe ser negativo") || textLower.includes("m\xEDnimo") && textLower.includes("caracteres") || textLower.includes("m\xE1ximo") && textLower.includes("caracteres") || textLower.includes("al menos") || textLower.includes("como m\xE1ximo") || /* Generic ZOD/form required */
946
- textLower.includes("campo requerido") || textLower.includes("campo obligatorio") || textLower.includes("requerido") || textLower.includes("obligatorio") || textLower.includes("no puede estar vac\xEDo") || textLower.includes("no puede ser") || textLower.includes("no es v\xE1lido") || textLower.includes("no es correcto") || textLower.includes("recuerda llenar") || textLower.includes("completa los campos") || textLower.includes("campos obligatorios") || textLower.includes("formato incorrecto") || textLower.includes("formato inv\xE1lido") || textLower.includes("valor no permitido")) && text.length < 250;
945
+ textLower.includes("debe ser un n\xFAmero") || textLower.includes("debe ser positivo") || textLower.includes("debe ser negativo") || textLower.includes("m\xEDnimo") && textLower.includes("caracteres") || textLower.includes("m\xE1ximo") && textLower.includes("caracteres") || /* Generic ZOD/form required — must be specific, NOT broad instructional text */
946
+ textLower.includes("campo requerido") || textLower.includes("campo obligatorio") || textLower === "requerido" || textLower === "obligatorio" || textLower.includes("este campo es requerido") || textLower.includes("este campo es obligatorio") || textLower.includes("no puede estar vac\xEDo") || textLower.includes("no puede ser") || textLower.includes("no es v\xE1lido") || textLower.includes("no es correcto") || textLower.includes("formato incorrecto") || textLower.includes("formato inv\xE1lido") || textLower.includes("valor no permitido")) && text.length < 200 && !textLower.includes("recuerda") && !textLower.includes("antes de guardar");
947
947
  const isCriticalSuccess = (textLower.includes("exitosamente") || textLower.includes("guardado") || textLower.includes("creado") || textLower.includes("success") || textLower.includes("correctamente") && text.length < 100) && text.length < 200;
948
948
  const isCriticalFeedback = isCriticalFailure || isCriticalSuccess;
949
949
  if (!isCriticalFeedback && (tag === "span" || tag === "p" || tag === "label" || tag === "i" || tag === "svg" || tag === "img" || tag === "div")) {
@@ -1247,10 +1247,18 @@ ${relevantFailures.map((m) => `- ${m.prompt}`).join("\n")}
1247
1247
  return c.selector === memStep.action_data?.selector || cleanMemName !== "" && (cleanMemName === cleanCurrName || cleanCurrName.includes(cleanMemName));
1248
1248
  });
1249
1249
  if (!foundComponent && memStep.action_data?.action !== "wait") {
1250
- console.log(`>>ARCALITY_STATUS>> \u23F3 Componente target no visible ("${memStep.componentName}"). Forzando espera de transici\xF3n DOM...`);
1251
1250
  console.log(`>>ARCALITY_STATUS>> \u{1F50D} Descartado (Componente visual no encontrado: ${memStep.componentName})`);
1252
1251
  return null;
1253
1252
  }
1253
+ if (foundComponent && memStep.action_data?.action === "fill") {
1254
+ const compType = (foundComponent.type || "").toLowerCase();
1255
+ const compName = (foundComponent.name || "").toLowerCase();
1256
+ const looksLikeDropdown = compType.includes("select") || compType.includes("combobox") || compName.includes("tipo") || compName.includes("type") || compName.includes("categor\xEDa") || compName.includes("estado") || compName.includes("frecuencia") || compName.includes("alcance");
1257
+ if (looksLikeDropdown) {
1258
+ console.log(`>>ARCALITY_STATUS>> \u{1F50D} Descartado (fill en dropdown detectado: ${foundComponent.name}). Delegando a IA.`);
1259
+ return null;
1260
+ }
1261
+ }
1254
1262
  const memCompName = memStep.componentName || "";
1255
1263
  if (memCompName.length > 80) {
1256
1264
  console.log(`>>ARCALITY_STATUS>> \u{1F50D} Descartado (Mensaje enorme o nombre inconsistente: ${memCompName.substring(0, 20)}...)`);
@@ -1505,6 +1513,10 @@ These are NOT optional. You MUST use these tools in these situations:
1505
1513
  # CRITICAL RULES
1506
1514
  1. **NEVER BLIND-RETRY**: If an action fails, you MUST investigate with \`inspect_element_details\` before retrying. Repeating the exact same failed action is FORBIDDEN.
1507
1515
  2. **NO REPEAT ACTIONS**: Check HISTORY. If you already filled a field or clicked a button, do NOT do it again unless the UI clearly reset OR the button belongs to a different step/modal/section mentioned in the mission (e.g., Save in modal vs Save in main form).
1516
+ 3. **GROUP ACTIONS**: You MUST group non-conflicting actions in a single turn to save time and tokens. You can \`fill\` multiple text inputs in the SAME turn.
1517
+ - NEVER use \`click\` on a text field before using \`fill\`. The \`fill\` action automatically focuses the field.
1518
+ - Example: \`fill\` Nombre, \`fill\` Fecha, \`fill\` Descripci\xF3n all in one single turn.
1519
+ - BUT keep dropdown interactions isolated: Turn A = \`click\` dropdown. Turn B = \`click\` option.
1508
1520
 
1509
1521
  3. **CURRENT STATE > MEMORY**: What you see in CURRENT COMPONENTS is the truth. SUCCESS MEMORY is a guide, not gospel.
1510
1522
  4. **PAGE TRANSITIONS**: If URL contains '/edit' or you see a 'Save' button, you ARE in the edit view. Don't go back.
@@ -1535,9 +1547,7 @@ These are NOT optional. You MUST use these tools in these situations:
1535
1547
  # WIZARD & MULTI-STEP FORMS (CRITICAL)
1536
1548
  When a form is divided into numbered steps (e.g., Step 1 \u2192 Step 2 \u2192 Step 3):
1537
1549
 
1538
- 1. **VALIDATION ERROR ON SAVE = STEP HAS INVALID DATA**: If you see a \u{1F6D1} [ERROR_CR\xCDTICO] after clicking Save/Next and you are on step N, it means a PREVIOUS step contains bad data. You MUST navigate BACK to that step.
1539
- - Look for a "Back" / "Anterior" / "Periodo" / step-number button and click it to return.
1540
- - NEVER retry the Save button without first fixing the invalid data in the previous step.
1550
+ 1. **VALIDATION ERROR ON ADVANCE**: If you click "Next/Siguiente" and the UI DOES NOT advance to the next step, AND you see a \u{1F6D1} [ERROR_CR\xCDTICO], you must fix the data on the CURRENT step. DO NOT GO BACK to previous steps simply because you see an error, unless the error explicitly states that a previous step's data is invalid.
1541
1551
 
1542
1552
  2. **DATE VALIDATION ERRORS \u2014 MANDATORY PROTOCOL (ZOD-AWARE)**:
1543
1553
  - ZOD generates Spanish validation messages such as:
@@ -1548,8 +1558,8 @@ When a form is divided into numbered steps (e.g., Step 1 \u2192 Step 2 \u2192 St
1548
1558
  - ANY \u{1F6D1} [ERROR_CR\xCDTICO] containing FECHA + (POSTERIOR/ANTERIOR/ACTUAL/PASADA/FUTURA) is a **ZOD DATE VALIDATION ERROR**.
1549
1559
  - **RECOVERY PROTOCOL** (follow in order, NEVER skip):
1550
1560
  1. STOP \u2014 do NOT click Save/Siguiente again with the same data.
1551
- 2. Identify which wizard step contains the failing date field (check HISTORY \u2014 usually Step 1 or Step 2).
1552
- 3. Click the Back/Anterior/step-number button to return to that step.
1561
+ 2. Identify which wizard step contains the failing date field (check HISTORY).
1562
+ 3. If you are NOT on that step, click the Back/Anterior button to return to it.
1553
1563
  4. Locate the date input using \`validate_element_state\` with 'has_value' to confirm its current (bad) value.
1554
1564
  5. Clear and re-fill the date using \`interact_native_control\` with control_type \`'date'\` and a value \u2265 TODAY in YYYY-MM-DD format.
1555
1565
  6. TODAY: \`${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]}\` \u2014 use this exact expression to compute the date dynamically.
@@ -1557,7 +1567,9 @@ When a form is divided into numbered steps (e.g., Step 1 \u2192 Step 2 \u2192 St
1557
1567
 
1558
1568
  3. **NEVER LOOP ON THE SAME STEP**: If you've been on the same wizard step for 3+ turns without advancing, go back one step and verify the data is correct before trying to advance again.
1559
1569
 
1560
- 4. **STEP VERIFICATION**: Before clicking Next/Save on any step, VERIFY that date fields have future-or-today dates. Use \`validate_element_state\` with 'has_value' to confirm.`
1570
+ 4. **STEP VERIFICATION**: Before clicking Next/Save on any step, VERIFY that date fields have future-or-today dates. Use \`validate_element_state\` with 'has_value' to confirm.
1571
+
1572
+ 5. **FINAL PREVIEW STEP**: If you reach a final step like "Previsualizaci\xF3n", "Resumen", or see a "Terminar" / "Finalizar" button, your objective is ALMOST COMPLETE. Do NOT go back to previous steps just because you see read-only data. Click the final submit button ("Terminar", "Guardar", "Finalizar") to complete the mission.`
1561
1573
  }
1562
1574
  ];
1563
1575
  if (this.testInfo) {
@@ -1689,7 +1701,12 @@ ${history.slice(-25).join("\n") || "None"}`
1689
1701
  const textResponse = message.content.find((c) => c.type === "text")?.text || "";
1690
1702
  if (toolCalls.length === 0) {
1691
1703
  console.log(`(${((Date.now() - startTime) / 1e3).toFixed(1)}s)`);
1692
- return { thought: textResponse || "No action decided", actions: [], usage: totalUsage };
1704
+ console.log(`>>ARCALITY_STATUS>> \u26A0\uFE0F Agente devolvi\xF3 texto sin acci\xF3n. Reinyectando instrucci\xF3n mandatoria...`);
1705
+ anthropicMessages.push({
1706
+ role: "user",
1707
+ content: [{ type: "text", text: `MANDATORY: You MUST call one of the available tools right now. You are NOT allowed to return plain text only. If you are unsure, call 'perform_ui_actions' with the most logical next action based on the mission and history. If you are truly stuck, call 'report_inability_to_proceed'. DO NOT return text without a tool call.` }]
1708
+ });
1709
+ continue;
1693
1710
  }
1694
1711
  const toolResults = [];
1695
1712
  let uiActionCall = null;