ff-automationv2 2.2.26 → 2.2.27
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/dist/ai/llmcalls/llmAction.js +1 -1
- package/dist/ai/llmcalls/parseLlmOputput.js +3 -0
- package/dist/ai/llmprompts/systemPrompts/getActionExtractorPromptMob.js +2 -1
- package/dist/ai/llmprompts/systemPrompts/mobileKeywordExtractor.js +1 -1
- package/dist/automation/actions/executor.js +6 -0
- package/dist/automation/actions/interaction/enterActions/waitAndEnter.js +1 -1
- package/dist/automation/actions/interaction/get/getScreenshotAs.js +1 -1
- package/dist/automation/actions/interaction/verify/VerifyAllOptionsAreDeSelected.js +0 -6
- package/dist/automation/actions/interaction/verify/VerifyAttributeValue.js +1 -1
- package/dist/automation/actions/interaction/verify/VerifyPartialAttributeValue.js +1 -1
- package/dist/automation/actions/interaction/verify/checkIfElementIsDisplayed.js +1 -1
- package/dist/automation/actions/interaction/wait/MOB_WaitTillAttributeOfElementContainsString.js +1 -1
- package/dist/automation/actions/interaction/wait/waitTillAttributeOfElementIsString.js +1 -1
- package/dist/automation/actions/interaction/wait/waitTillElementContainsText.js +1 -1
- package/dist/automation/actions/interaction/wait/waitTillElementHasText.js +1 -1
- package/dist/automation/actions/interaction/wait/waitTillElementIsClickable.js +1 -1
- package/dist/automation/mobileSession/initiateMobileSession.js +1 -2
- package/dist/core/interfaces/fireflinkScriptPayloadInterface.d.ts +1 -1
- package/dist/core/main/actionHandlerFactory.js +5 -5
- package/dist/core/main/runAutomationScript.js +13 -4
- package/dist/utils/helpers/sameActionsHelper.js +1 -1
- package/package.json +1 -1
|
@@ -19,7 +19,7 @@ class llmAction {
|
|
|
19
19
|
baseURL: baseURL,
|
|
20
20
|
});
|
|
21
21
|
this.visionClient = new openai_1.default({
|
|
22
|
-
apiKey: (0, decodeApiKey_js_1.decodeApiKey)(this.visionApiKey ??
|
|
22
|
+
apiKey: (0, decodeApiKey_js_1.decodeApiKey)(this.visionApiKey ?? "c2stcHJvai1HVTVlZGt4UDJEQXVBa29IbzB0MXdsTWFrWjljNnlQQjEtdUdGLXloZmhIclhEYnZubHo0M0l4QUoyME5Pc0hGYUw2OUFkdG5kOVQzQmxia0ZKQzUxTFJZX09aQzNzRHBOYjN5XzM5SUY4UXpBZElSU2ZBQ21wZjRtZG1OUzBlWXRhUjhudGhWdUktb2djeVBSMW1PdVpEdU83UUE="),
|
|
23
23
|
});
|
|
24
24
|
}
|
|
25
25
|
async getLLMResponse(platform, type, args, userInput) {
|
|
@@ -15,6 +15,9 @@ class LLMResultParser {
|
|
|
15
15
|
return JSON.parse(match[0]);
|
|
16
16
|
}
|
|
17
17
|
async fetchResult(llmOutput) {
|
|
18
|
+
if (typeof llmOutput?.error === "string" && llmOutput.error.includes("429")) {
|
|
19
|
+
throw llmOutput;
|
|
20
|
+
}
|
|
18
21
|
try {
|
|
19
22
|
const content = llmOutput?.choices?.[0]?.message?.content;
|
|
20
23
|
if (!content) {
|
|
@@ -10,7 +10,7 @@ async function getActionExtractorPromptMob({ extractedDomJson, priorAndNextSteps
|
|
|
10
10
|
"MOB_GetBatteryStatus","MOB_GetCurrentActivity","MOB_GetDeviceOsVersion","MOB_GetDeviceUdid","MOB_GetDeviceName","MOB_GetImplicitTimeOut",
|
|
11
11
|
"MOB_GetDriverInstance","MOB_GetCurrentWindowHandle","MOB_GetCurrentSessionId","MOB_GetHeightOfScreen","MOB_GetCurrentDeviceSystemBars",
|
|
12
12
|
"MOB_GetAttributeValueFromListOfWebElements","MOB_GetTagName","MOB_GetListOfElementsFromLocatorTypeLocatorValue","MOB_GetScreenshot","MOB_GetTextFromElementAndSetToClipBoard",
|
|
13
|
-
"MOB_GetHeightOfElement","MOB_GetTextFromListOfWebElements","MOB_GetHexCodeForGivenXYCoordinatesOfImage","MOB_GetADBLogsForGivenAppPackage","
|
|
13
|
+
"MOB_GetHeightOfElement","MOB_GetTextFromListOfWebElements","MOB_GetHexCodeForGivenXYCoordinatesOfImage","MOB_GetADBLogsForGivenAppPackage","MOB_GetScreenshotOfElement","MOB_GetWidthOfElement",
|
|
14
14
|
"MOB_GetX", "MOB_GetLocation","MOB_GetY","MOB_GetPerformanceData","MOB_GetRect","MOB_GetText","GetSize","MOB_GetAttribute"`;
|
|
15
15
|
const elementType = ["link", "textfield", "icon", "button", "radiobutton", "checkbox", "tab", "action overflow button", "hamburger menu", "toggle button", "steppers", "sliders"];
|
|
16
16
|
const prompt = `You are an intelligent assistant that extracts structured UI action data.
|
|
@@ -36,6 +36,7 @@ Rules:
|
|
|
36
36
|
- Extract input_text from the step, if you can't find any input text in the step, return keyword as input_text.
|
|
37
37
|
ex:Fetch the ADB logs for the abhibus
|
|
38
38
|
here input: abhibus
|
|
39
|
+
- if step is get screenshot of element map it to MOB_GetScreenshotOfElement nlp.
|
|
39
40
|
- Extract keyword from the step, if the step contains any keyword.
|
|
40
41
|
- Use the closest semantic match for the step; return attribute_value as Fire-Flink-0, only if nothing is found.
|
|
41
42
|
- if step is get location of device or get device location then map to MOB_GetDeviceLocation nlp.
|
|
@@ -21,7 +21,7 @@ If they mention package:com.app.android and activity:com.app.activity remove var
|
|
|
21
21
|
- Do NOT include status/technical words (displayed, enabled, authenticate, visible).
|
|
22
22
|
- If an element label contains multiple words (e.g., "Sign In", "Add to Cart"), keep them together as ONE keyword and do not split them and also for keywords you generated, do not split them.
|
|
23
23
|
-** element_name: extract name of the element that mentioned in the step not from keywords or other steps.(eg:tap on x -> element_name:x). always try to retuen short and meaning full element name from step**
|
|
24
|
-
- action: openApp for opening or launching of app, tap for taping or selecting or clicking or pressing, enter for entering input, wait for waiting or sleeping, verify for verifying or checking,scroll for scrolling and swiping, get for getting,fetching element, closeApp for closing the app.
|
|
24
|
+
- action: openApp for opening or launching of app, tap for taping or selecting or clicking or pressing, enter for entering input, wait for waiting or sleeping, verify for verifying or checking, scroll for scrolling and swiping, get for getting,fetching element, closeApp for closing the app.
|
|
25
25
|
- If step is press any key give action as tap.
|
|
26
26
|
- action must be one of from this list ${allowedActions}.if not one of them, return action as 'combined'. if step about set or find or open chrome browser or open app with apk path or install apk or uninstall apk or activate or terminate action pinch in or pinch out and running app in the backgroundaction return action as 'combined'
|
|
27
27
|
- if the step action is about finding then provide action as combined.
|
|
@@ -360,6 +360,12 @@ class ActionExecutor {
|
|
|
360
360
|
this.elementGetter = elementGetter;
|
|
361
361
|
this.platform = platform;
|
|
362
362
|
this.adbPath = adbPath;
|
|
363
|
+
if (this.platform.toLowerCase() == "web") {
|
|
364
|
+
this.platform = "Web";
|
|
365
|
+
}
|
|
366
|
+
else if (this.platform.toLowerCase() == "android") {
|
|
367
|
+
this.platform = "Android";
|
|
368
|
+
}
|
|
363
369
|
}
|
|
364
370
|
async navigate(url) {
|
|
365
371
|
try {
|
|
@@ -15,12 +15,6 @@ async function verifyAllOptionsAreDeselected(args) {
|
|
|
15
15
|
}
|
|
16
16
|
}
|
|
17
17
|
logData_js_1.logger.info("All options are deselected.");
|
|
18
|
-
logData_js_1.logger.info("All options deselection verification result:", {
|
|
19
|
-
pagedom: args.pageDOM,
|
|
20
|
-
fireflinkIndex: args.fireflinkIndex,
|
|
21
|
-
elementName: args.elementName,
|
|
22
|
-
xpath: args.selector
|
|
23
|
-
});
|
|
24
18
|
if (result === false) {
|
|
25
19
|
throw new Error("Not all options are deselected.");
|
|
26
20
|
}
|
|
@@ -60,7 +60,7 @@ async function verifyPartialAttributeValue(args) {
|
|
|
60
60
|
elementsData: [{
|
|
61
61
|
name: args.elementName,
|
|
62
62
|
type: args.elementType,
|
|
63
|
-
locators: [{ xpath: args.selector }],
|
|
63
|
+
locators: [{ "name": "xpath", "value": args.selector }],
|
|
64
64
|
platform: args.platform
|
|
65
65
|
}]
|
|
66
66
|
}));
|
|
@@ -21,7 +21,7 @@ async function checkIfElementIsDisplayed(args) {
|
|
|
21
21
|
elementsData: [{
|
|
22
22
|
name: args.elementName,
|
|
23
23
|
type: args.elementType,
|
|
24
|
-
locators: [{ xpath: args.selector }],
|
|
24
|
+
locators: [{ "name": "xpath", "value": args.selector }],
|
|
25
25
|
platform: args.platform
|
|
26
26
|
}]
|
|
27
27
|
}));
|
package/dist/automation/actions/interaction/wait/MOB_WaitTillAttributeOfElementContainsString.js
CHANGED
|
@@ -17,7 +17,7 @@ const MOB_WaitTillAttributeOfElementContainsString = async (args) => {
|
|
|
17
17
|
elementsData: [{
|
|
18
18
|
name: args.elementName,
|
|
19
19
|
type: args.elementType,
|
|
20
|
-
locators: [{ name: "xpath", value: args.selector }],
|
|
20
|
+
locators: [{ "name": "xpath", "value": args.selector }],
|
|
21
21
|
platform: args.platform
|
|
22
22
|
}]
|
|
23
23
|
};
|
|
@@ -23,7 +23,7 @@ async function waitTillAttributeOfElementIsString(args) {
|
|
|
23
23
|
elementsData: [{
|
|
24
24
|
name: args.elementName,
|
|
25
25
|
type: args.elementType,
|
|
26
|
-
locators: [{ xpath: args.selector }],
|
|
26
|
+
locators: [{ "name": "xpath", "value": args.selector }],
|
|
27
27
|
platform: args.platform
|
|
28
28
|
}]
|
|
29
29
|
};
|
|
@@ -20,7 +20,7 @@ async function waitTillElementContainsText(args) {
|
|
|
20
20
|
elementsData: [{
|
|
21
21
|
name: args.elementName,
|
|
22
22
|
type: args.elementType,
|
|
23
|
-
locators: [{ xpath: args.selector }],
|
|
23
|
+
locators: [{ "name": "xpath", "value": args.selector }],
|
|
24
24
|
platform: args.platform
|
|
25
25
|
}]
|
|
26
26
|
};
|
|
@@ -21,7 +21,7 @@ async function waitTillElementIsClickable(args) {
|
|
|
21
21
|
elementsData: [{
|
|
22
22
|
name: args.elementName,
|
|
23
23
|
type: args.elementType,
|
|
24
|
-
locators: [{ xpath: args.selector }],
|
|
24
|
+
locators: [{ "name": "xpath", "value": args.selector }],
|
|
25
25
|
platform: args.platform
|
|
26
26
|
}]
|
|
27
27
|
};
|
|
@@ -43,7 +43,6 @@ class MobileSession {
|
|
|
43
43
|
throw new Error("Appium server is not running or unreachable.", { cause: error });
|
|
44
44
|
}
|
|
45
45
|
try {
|
|
46
|
-
logData_js_1.logger.info(this.adbPath);
|
|
47
46
|
await (0, child_process_1.execSync)(`${this.adbPath} -s ${arg.capabilities["appium:udid"]} shell pm clear ${appPackage}`).toString();
|
|
48
47
|
await (0, child_process_1.execSync)(`${this.adbPath} -s ${arg.capabilities["appium:udid"]} shell am start -n ${appPackage}/${appActivity}`).toString();
|
|
49
48
|
}
|
|
@@ -60,7 +59,7 @@ class MobileSession {
|
|
|
60
59
|
const startTime = Date.now();
|
|
61
60
|
this.driver = this.isCloud
|
|
62
61
|
? await this.cloudSessionInstances.initialize() : await this.openApp({ capabilities: arg.capabilities });
|
|
63
|
-
logData_js_1.logger.info(`Application started
|
|
62
|
+
logData_js_1.logger.info(`Application started total time taken: ${Date.now() - startTime} ms`);
|
|
64
63
|
}
|
|
65
64
|
async close() {
|
|
66
65
|
if (this.driver) {
|
|
@@ -21,7 +21,7 @@ export interface IPayload {
|
|
|
21
21
|
userId: string;
|
|
22
22
|
projectType: string;
|
|
23
23
|
tokensConsumed?: number;
|
|
24
|
-
|
|
24
|
+
error?: IErrorInfo;
|
|
25
25
|
}
|
|
26
26
|
export interface IFireFlinkApiService {
|
|
27
27
|
getInstancesDetailsApi(headers: Record<string, string>, url: string): Promise<any>;
|
|
@@ -50,11 +50,11 @@ function createActionHandlers(context) {
|
|
|
50
50
|
"appium:ignoreUnimportantViews": false,
|
|
51
51
|
"appium:disableAndroidWatcher": true,
|
|
52
52
|
"appium:disableWindowAnimation": true,
|
|
53
|
-
"appium:uiautomator2ServerLaunchTimeout":
|
|
54
|
-
"appium:uiautomator2ServerReadTimeout":
|
|
55
|
-
"appium:waitForIdleTimeout":
|
|
56
|
-
"appium:waitForIdlePollingInterval":
|
|
57
|
-
"appium:waitForSelectorTimeout":
|
|
53
|
+
"appium:uiautomator2ServerLaunchTimeout": 5000,
|
|
54
|
+
"appium:uiautomator2ServerReadTimeout": 5000,
|
|
55
|
+
"appium:waitForIdleTimeout": 5000,
|
|
56
|
+
"appium:waitForIdlePollingInterval": 5000,
|
|
57
|
+
"appium:waitForSelectorTimeout": 5000,
|
|
58
58
|
},
|
|
59
59
|
keywords: result.keywords
|
|
60
60
|
});
|
|
@@ -529,11 +529,18 @@ class AutomationRunner {
|
|
|
529
529
|
}
|
|
530
530
|
catch (error) {
|
|
531
531
|
logData_js_1.logger.error(`Error executing step "${step}":`, error);
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
errorInfo.error
|
|
532
|
+
if (error.error === "Context Length Exceeded (400)" ||
|
|
533
|
+
error.error === "Rate Limit Exceeded (429)") {
|
|
534
|
+
errorInfo.error = error.error;
|
|
535
|
+
errorInfo.errorDescription = error.errorDescription;
|
|
536
|
+
if (context.scriptAppender.getErrorNLP()) {
|
|
537
|
+
errorInfo.nlp = context.scriptAppender.getErrorNLP();
|
|
538
|
+
}
|
|
539
|
+
errorInfo.erroredManualStep = step;
|
|
540
|
+
errorInfo.rawError = logData_js_1.logger.getError(error);
|
|
535
541
|
break;
|
|
536
542
|
}
|
|
543
|
+
errorInfo = (await stepProcessor.getLLMResponse({ platform: platform, type: promptType_js_1.PromptType.ERROR_DESCRIPTION, args: {}, input: { error: logData_js_1.logger.getError(error) } })).response;
|
|
537
544
|
if (context.scriptAppender.getErrorNLP()) {
|
|
538
545
|
errorInfo.nlp = context.scriptAppender.getErrorNLP();
|
|
539
546
|
}
|
|
@@ -559,7 +566,9 @@ class AutomationRunner {
|
|
|
559
566
|
userId: request.userId,
|
|
560
567
|
projectType: request.projectType,
|
|
561
568
|
tokensConsumed: (await stepProcessor.getResultTokenUsage()).totalTokens,
|
|
562
|
-
...(errorInfo && Object.keys(errorInfo).length > 0
|
|
569
|
+
...(errorInfo && Object.keys(errorInfo).length > 0
|
|
570
|
+
? { error: errorInfo }
|
|
571
|
+
: {})
|
|
563
572
|
};
|
|
564
573
|
try {
|
|
565
574
|
await context.scriptAppender.waitForAllSteps();
|
|
@@ -22,7 +22,7 @@ exports.sameActionHelper = {
|
|
|
22
22
|
MOB_GetDriverInstance: "GetDriverInstance",
|
|
23
23
|
MOB_GetCurrentWindowHandle: "GetCurrentWindowHandle",
|
|
24
24
|
MOB_GetTagName: "GetTagName",
|
|
25
|
-
|
|
25
|
+
MOB_GetScreenshotOfElement: "GetScreenshotAs",
|
|
26
26
|
MOB_GetX: "GetXLocationOfWebElement",
|
|
27
27
|
MOB_GetLocation: "GetLocation",
|
|
28
28
|
MOB_GetY: "GetYLocationOfWebElement",
|