ff-automationv2 1.0.0 → 2.0.1-beta.0
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/bitbucket-pipelines.yml +20 -0
- package/eslint.config.ts +29 -29
- package/package.json +51 -51
- package/src/ai/llmcalls/decodeApiKey.ts +14 -14
- package/src/ai/llmcalls/llmAction.ts +89 -89
- package/src/ai/llmcalls/parseLlmOputput.ts +69 -69
- package/src/ai/llmprompts/systemPrompts/actionExtractorPrompt.ts +70 -70
- package/src/ai/llmprompts/systemPrompts/errorDescriptionPrompt.ts +23 -23
- package/src/ai/llmprompts/systemPrompts/fireflinkElementIndexExtactors.ts +198 -198
- package/src/ai/llmprompts/systemPrompts/userStoryToListPrompt.ts +24 -24
- package/src/ai/llmprompts/systemPrompts/visionPrompt.ts +28 -28
- package/src/automation/actions/executor.ts +74 -74
- package/src/automation/actions/interaction/enterInput.ts +27 -27
- package/src/automation/actions/interface/interactionActionInterface.ts +26 -26
- package/src/automation/actions/interface/navigationActionInterface.ts +21 -21
- package/src/automation/actions/interface/waitActionInterface.ts +5 -5
- package/src/automation/actions/navigation/getTitle.ts +8 -8
- package/src/automation/actions/navigation/goBack.ts +8 -8
- package/src/automation/actions/navigation/navigate.ts +9 -9
- package/src/automation/actions/navigation/refresh.ts +8 -8
- package/src/automation/actions/wait/wait.ts +9 -9
- package/src/automation/browserSession/initiateBrowserSession.ts +81 -81
- package/src/core/constants/supportedActions.ts +7 -7
- package/src/core/interfaces/StableDomInterface.ts +5 -5
- package/src/core/interfaces/actionInterface.ts +13 -13
- package/src/core/interfaces/automationRunnerInterface.ts +2 -2
- package/src/core/interfaces/browserCapabilitiesInterface.ts +4 -4
- package/src/core/interfaces/browserConfigurationInterface.ts +2 -2
- package/src/core/interfaces/domAnalysisInterface.ts +34 -34
- package/src/core/interfaces/executionDetails.ts +29 -29
- package/src/core/interfaces/fireflinkScriptPayloadInterface.ts +39 -39
- package/src/core/interfaces/llmConfigurationInterface.ts +2 -2
- package/src/core/interfaces/llmResponseInterface.ts +38 -38
- package/src/core/interfaces/promptInterface.ts +21 -21
- package/src/core/interfaces/scriptGenrationDataInterface.ts +16 -16
- package/src/core/interfaces/toolsInterface.ts +5 -5
- package/src/core/main/actionHandlerFactory.ts +86 -86
- package/src/core/main/executionContext.ts +18 -18
- package/src/core/main/runAutomationScript.ts +177 -177
- package/src/core/main/stepProcessor.ts +28 -28
- package/src/core/types/llmResponseType.ts +10 -10
- package/src/core/types/visionllmInputType.ts +4 -4
- package/src/domAnalysis/getRelaventElements.ts +24 -24
- package/src/domAnalysis/relativeElementsFromDom.ts +94 -94
- package/src/domAnalysis/searchBest.ts +159 -159
- package/src/domAnalysis/simplifyAndFlatten.ts +118 -118
- package/src/fireflinkData/fireflinkLocators/elementsFromHTML.ts +656 -656
- package/src/fireflinkData/fireflinkLocators/getListOfLocators.ts +31 -31
- package/src/fireflinkData/fireflinkLocators/typeList.ts +36 -36
- package/src/fireflinkData/fireflinkScript/scriptGenrationData.ts +30 -30
- package/src/index.ts +5 -5
- package/src/llmConfig/llmConfiguration.ts +26 -26
- package/src/service/fireflinkApi.service.ts +46 -46
- package/src/service/scriptRunner.service.ts +83 -83
- package/src/utils/DomExtraction/jsForAttributeInjection.ts +254 -254
- package/src/utils/javascript/jsFindElement.ts +161 -161
- package/src/utils/javascript/jsForShadowRoot.ts +216 -216
- package/src/utils/javascript/jsForToaster.ts +60 -60
- package/src/utils/logger/logData.ts +36 -36
- package/tsconfig.json +26 -26
|
@@ -1,118 +1,118 @@
|
|
|
1
|
-
import * as cheerio from "cheerio";
|
|
2
|
-
import { Element } from "domhandler";
|
|
3
|
-
|
|
4
|
-
export interface FlatNode {
|
|
5
|
-
node: Record<string, any>;
|
|
6
|
-
search: string;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
export class DomSimplifier {
|
|
10
|
-
|
|
11
|
-
public simplify(rawDom: string): FlatNode[] {
|
|
12
|
-
|
|
13
|
-
const $ = cheerio.load(rawDom);
|
|
14
|
-
const flatNodes: FlatNode[] = [];
|
|
15
|
-
|
|
16
|
-
$("*").each((_, node) => {
|
|
17
|
-
|
|
18
|
-
if (node.type !== "tag") return;
|
|
19
|
-
|
|
20
|
-
const el = node as Element;
|
|
21
|
-
const tag = el.tagName.toLowerCase();
|
|
22
|
-
if (!tag || tag === "meta") return;
|
|
23
|
-
|
|
24
|
-
const attribs = el.attribs ?? {}; // ✅ declared only once
|
|
25
|
-
|
|
26
|
-
if (tag !== "select" && tag !== "option") {
|
|
27
|
-
if (
|
|
28
|
-
(attribs["element-visibility"] === "hidden" ||
|
|
29
|
-
attribs["element-covered"] === "true") &&
|
|
30
|
-
attribs["element-covered-by-tag"] !== "iframe"
|
|
31
|
-
) {
|
|
32
|
-
return;
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
const simplified: Record<string, any> = { tag };
|
|
37
|
-
|
|
38
|
-
if (attribs["ff-inspect"])
|
|
39
|
-
simplified["FF-inspecter"] = attribs["ff-inspect"];
|
|
40
|
-
|
|
41
|
-
if (attribs["ff-xpath"])
|
|
42
|
-
simplified["ff-xpath"] = attribs["ff-xpath"];
|
|
43
|
-
|
|
44
|
-
// -----------------
|
|
45
|
-
// Direct text only
|
|
46
|
-
// -----------------
|
|
47
|
-
let directText = "";
|
|
48
|
-
|
|
49
|
-
$(el).contents().each((_, child) => {
|
|
50
|
-
if (child.type === "text") {
|
|
51
|
-
const txt = child.data?.trim();
|
|
52
|
-
if (txt) directText += txt;
|
|
53
|
-
}
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
const cleanText = directText
|
|
57
|
-
.replace(/[^a-zA-Z0-9\s]/g, " ")
|
|
58
|
-
.trim();
|
|
59
|
-
|
|
60
|
-
if (cleanText)
|
|
61
|
-
simplified["text"] = cleanText.slice(0, 200);
|
|
62
|
-
|
|
63
|
-
// -----------------
|
|
64
|
-
// Copy attributes
|
|
65
|
-
// -----------------
|
|
66
|
-
const EXCLUDED_ATTRS = new Set([
|
|
67
|
-
"style", "onclick", "onchange", "href",
|
|
68
|
-
"oninput", "onmouseover", "onfocus",
|
|
69
|
-
"ff-inspect", "element-visibility",
|
|
70
|
-
"element-pointer-events", "element-zindex", "element-covered"
|
|
71
|
-
]);
|
|
72
|
-
|
|
73
|
-
Object.entries(attribs).forEach(([key, val]) => {
|
|
74
|
-
if (!EXCLUDED_ATTRS.has(key.toLowerCase())) {
|
|
75
|
-
simplified[key] = val;
|
|
76
|
-
}
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
// -----------------
|
|
80
|
-
// Build search
|
|
81
|
-
// -----------------
|
|
82
|
-
const parts = new Set<string>();
|
|
83
|
-
|
|
84
|
-
if (cleanText && cleanText.length <= 70) {
|
|
85
|
-
parts.add(cleanText.toLowerCase());
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
const SEARCH_EXCLUDED = new Set([
|
|
89
|
-
"class", "style", "onclick", "onchange",
|
|
90
|
-
"oninput", "onmouseover", "onfocus",
|
|
91
|
-
"tabindex", "role", "href"
|
|
92
|
-
]);
|
|
93
|
-
|
|
94
|
-
Object.entries(simplified).forEach(([key, value]) => {
|
|
95
|
-
if (!value) return;
|
|
96
|
-
if (SEARCH_EXCLUDED.has(key.toLowerCase())) return;
|
|
97
|
-
if (["tag", "FF-inspecter", "search", "ff-xpath"].includes(key)) return;
|
|
98
|
-
|
|
99
|
-
const v = String(value)
|
|
100
|
-
.replace(/[^a-zA-Z0-9\s]/g, " ")
|
|
101
|
-
.trim()
|
|
102
|
-
.toLowerCase();
|
|
103
|
-
|
|
104
|
-
if (v) parts.add(v);
|
|
105
|
-
});
|
|
106
|
-
|
|
107
|
-
simplified["search"] = Array.from(parts).join(" ").trim();
|
|
108
|
-
|
|
109
|
-
flatNodes.push({
|
|
110
|
-
node: simplified,
|
|
111
|
-
search: simplified["search"]
|
|
112
|
-
});
|
|
113
|
-
|
|
114
|
-
});
|
|
115
|
-
|
|
116
|
-
return flatNodes;
|
|
117
|
-
}
|
|
118
|
-
}
|
|
1
|
+
import * as cheerio from "cheerio";
|
|
2
|
+
import { Element } from "domhandler";
|
|
3
|
+
|
|
4
|
+
export interface FlatNode {
|
|
5
|
+
node: Record<string, any>;
|
|
6
|
+
search: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export class DomSimplifier {
|
|
10
|
+
|
|
11
|
+
public simplify(rawDom: string): FlatNode[] {
|
|
12
|
+
|
|
13
|
+
const $ = cheerio.load(rawDom);
|
|
14
|
+
const flatNodes: FlatNode[] = [];
|
|
15
|
+
|
|
16
|
+
$("*").each((_, node) => {
|
|
17
|
+
|
|
18
|
+
if (node.type !== "tag") return;
|
|
19
|
+
|
|
20
|
+
const el = node as Element;
|
|
21
|
+
const tag = el.tagName.toLowerCase();
|
|
22
|
+
if (!tag || tag === "meta") return;
|
|
23
|
+
|
|
24
|
+
const attribs = el.attribs ?? {}; // ✅ declared only once
|
|
25
|
+
|
|
26
|
+
if (tag !== "select" && tag !== "option") {
|
|
27
|
+
if (
|
|
28
|
+
(attribs["element-visibility"] === "hidden" ||
|
|
29
|
+
attribs["element-covered"] === "true") &&
|
|
30
|
+
attribs["element-covered-by-tag"] !== "iframe"
|
|
31
|
+
) {
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const simplified: Record<string, any> = { tag };
|
|
37
|
+
|
|
38
|
+
if (attribs["ff-inspect"])
|
|
39
|
+
simplified["FF-inspecter"] = attribs["ff-inspect"];
|
|
40
|
+
|
|
41
|
+
if (attribs["ff-xpath"])
|
|
42
|
+
simplified["ff-xpath"] = attribs["ff-xpath"];
|
|
43
|
+
|
|
44
|
+
// -----------------
|
|
45
|
+
// Direct text only
|
|
46
|
+
// -----------------
|
|
47
|
+
let directText = "";
|
|
48
|
+
|
|
49
|
+
$(el).contents().each((_, child) => {
|
|
50
|
+
if (child.type === "text") {
|
|
51
|
+
const txt = child.data?.trim();
|
|
52
|
+
if (txt) directText += txt;
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
const cleanText = directText
|
|
57
|
+
.replace(/[^a-zA-Z0-9\s]/g, " ")
|
|
58
|
+
.trim();
|
|
59
|
+
|
|
60
|
+
if (cleanText)
|
|
61
|
+
simplified["text"] = cleanText.slice(0, 200);
|
|
62
|
+
|
|
63
|
+
// -----------------
|
|
64
|
+
// Copy attributes
|
|
65
|
+
// -----------------
|
|
66
|
+
const EXCLUDED_ATTRS = new Set([
|
|
67
|
+
"style", "onclick", "onchange", "href",
|
|
68
|
+
"oninput", "onmouseover", "onfocus",
|
|
69
|
+
"ff-inspect", "element-visibility",
|
|
70
|
+
"element-pointer-events", "element-zindex", "element-covered"
|
|
71
|
+
]);
|
|
72
|
+
|
|
73
|
+
Object.entries(attribs).forEach(([key, val]) => {
|
|
74
|
+
if (!EXCLUDED_ATTRS.has(key.toLowerCase())) {
|
|
75
|
+
simplified[key] = val;
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
// -----------------
|
|
80
|
+
// Build search
|
|
81
|
+
// -----------------
|
|
82
|
+
const parts = new Set<string>();
|
|
83
|
+
|
|
84
|
+
if (cleanText && cleanText.length <= 70) {
|
|
85
|
+
parts.add(cleanText.toLowerCase());
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const SEARCH_EXCLUDED = new Set([
|
|
89
|
+
"class", "style", "onclick", "onchange",
|
|
90
|
+
"oninput", "onmouseover", "onfocus",
|
|
91
|
+
"tabindex", "role", "href"
|
|
92
|
+
]);
|
|
93
|
+
|
|
94
|
+
Object.entries(simplified).forEach(([key, value]) => {
|
|
95
|
+
if (!value) return;
|
|
96
|
+
if (SEARCH_EXCLUDED.has(key.toLowerCase())) return;
|
|
97
|
+
if (["tag", "FF-inspecter", "search", "ff-xpath"].includes(key)) return;
|
|
98
|
+
|
|
99
|
+
const v = String(value)
|
|
100
|
+
.replace(/[^a-zA-Z0-9\s]/g, " ")
|
|
101
|
+
.trim()
|
|
102
|
+
.toLowerCase();
|
|
103
|
+
|
|
104
|
+
if (v) parts.add(v);
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
simplified["search"] = Array.from(parts).join(" ").trim();
|
|
108
|
+
|
|
109
|
+
flatNodes.push({
|
|
110
|
+
node: simplified,
|
|
111
|
+
search: simplified["search"]
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
return flatNodes;
|
|
117
|
+
}
|
|
118
|
+
}
|