@runcofactor/cli 0.13.0 → 0.15.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/dist/account-22LMP5PX.js +255 -0
- package/dist/account-22LMP5PX.js.map +1 -0
- package/dist/{api-catalog-7HLEN7C2.js → api-catalog-WTFQNLK6.js} +5 -5
- package/dist/{attachment-OVNQD6Z2.js → attachment-U3NKVPEY.js} +5 -5
- package/dist/augmentor-5GMNAX4M.js +198 -0
- package/dist/augmentor-5GMNAX4M.js.map +1 -0
- package/dist/{auth-VUHL74FH.js → auth-VQG2CDUD.js} +3 -3
- package/dist/{chunk-PZ4LCN6K.js → chunk-3X3NW7QA.js} +2 -2
- package/dist/{chunk-VGTKUOYS.js → chunk-46IUJXSD.js} +2 -2
- package/dist/{chunk-YN763NWQ.js → chunk-7VMO2WOZ.js} +10 -4
- package/dist/chunk-7VMO2WOZ.js.map +1 -0
- package/dist/{chunk-Z5LUTUDN.js → chunk-CMGI7UZD.js} +3 -3
- package/dist/{chunk-EEN2TZUQ.js → chunk-FNPMWDUQ.js} +3 -3
- package/dist/{chunk-EJ4U242G.js → chunk-HDFYUFBI.js} +2 -2
- package/dist/{chunk-JZMJUPZP.js → chunk-JMJVGMXI.js} +2 -2
- package/dist/{chunk-JZMJUPZP.js.map → chunk-JMJVGMXI.js.map} +1 -1
- package/dist/{chunk-QGI4UCJX.js → chunk-JYGNMKZ5.js} +62 -35
- package/dist/chunk-JYGNMKZ5.js.map +1 -0
- package/dist/{chunk-CRHPDPRS.js → chunk-KCHKFYVX.js} +30 -8
- package/dist/{chunk-CRHPDPRS.js.map → chunk-KCHKFYVX.js.map} +1 -1
- package/dist/{chunk-ZD3KHESI.js → chunk-KRWRUU6R.js} +27 -7
- package/dist/chunk-KRWRUU6R.js.map +1 -0
- package/dist/{chunk-ENDHMYEJ.js → chunk-NHTEKEYE.js} +3 -3
- package/dist/{chunk-CQE46HSM.js → chunk-PRBRSIZP.js} +14 -8
- package/dist/chunk-PRBRSIZP.js.map +1 -0
- package/dist/{chunk-NL7CVG56.js → chunk-UETBLPKM.js} +57 -10
- package/dist/chunk-UETBLPKM.js.map +1 -0
- package/dist/{chunk-QQVWGWPI.js → chunk-VGYN2KU2.js} +8494 -1504
- package/dist/chunk-VGYN2KU2.js.map +1 -0
- package/dist/{chunk-ZTOE3ND3.js → chunk-XJ5YYYGC.js} +4 -4
- package/dist/{credential-LO2SEEHU.js → credential-E6KUHRGU.js} +5 -5
- package/dist/{credential-template-ZN7W7734.js → credential-template-4GPOPBGD.js} +5 -5
- package/dist/{debug-workflow-R3RYYAXK.js → debug-workflow-XCLCY6S7.js} +5 -5
- package/dist/{docs-DIAFBDXQ.js → docs-COCZYMW6.js} +95 -11
- package/dist/docs-COCZYMW6.js.map +1 -0
- package/dist/{doctor-NZPUSCRE.js → doctor-ERIVTCQS.js} +3 -3
- package/dist/{environment-RQVU4P5M.js → environment-7Y4BV6XY.js} +5 -5
- package/dist/{feature-flag-XG26RURR.js → feature-flag-MHONEX6T.js} +98 -12
- package/dist/feature-flag-MHONEX6T.js.map +1 -0
- package/dist/index.js +107 -51
- package/dist/index.js.map +1 -1
- package/dist/{init-EDNLKGPT.js → init-OROOM4HF.js} +5 -5
- package/dist/{install-FYZ3HNZK.js → install-OJFXHY6U.js} +5 -5
- package/dist/{issues-NNRVTJ4L.js → issues-32GONR6C.js} +5 -5
- package/dist/{knobs-A2BOBH22.js → knobs-UQGGY3CP.js} +7 -6
- package/dist/knobs-UQGGY3CP.js.map +1 -0
- package/dist/{list-F33VZ4BJ.js → list-ZMIKEC5P.js} +5 -5
- package/dist/{local-DQDTM3XA.js → local-PUD24GGQ.js} +7 -7
- package/dist/{login-BUMVIB36.js → login-BSO7YX2D.js} +5 -5
- package/dist/{mcp-B5Y5CDMQ.js → mcp-4LS7OJUT.js} +9 -9
- package/dist/{mcp-B5Y5CDMQ.js.map → mcp-4LS7OJUT.js.map} +1 -1
- package/dist/{pdf-extract-ABWV3L5X.js → pdf-extract-YHE54XU4.js} +2 -2
- package/dist/product-3JKSJCBC.js +346 -0
- package/dist/product-3JKSJCBC.js.map +1 -0
- package/dist/{property-NJ4SRXQG.js → property-K5DBL4UE.js} +5 -5
- package/dist/{psql-VBZFCMNR.js → psql-PQFUFTSE.js} +3 -3
- package/dist/{record-WAO36O7G.js → record-EIIYLFJ4.js} +6 -6
- package/dist/{redis-DHZXHL4S.js → redis-BU36EZZI.js} +3 -3
- package/dist/redis-BU36EZZI.js.map +1 -0
- package/dist/{release-STJKUKTE.js → release-LYC2P7DZ.js} +5 -5
- package/dist/{sandbox-DWSGLY7B.js → sandbox-CKHXXZHU.js} +51 -7
- package/dist/sandbox-CKHXXZHU.js.map +1 -0
- package/dist/{scenarios-HCIDY725.js → scenarios-2XJ2G3KR.js} +5 -5
- package/dist/{session-Y5RHU54D.js → session-UTOD5ZYH.js} +8 -9
- package/dist/session-UTOD5ZYH.js.map +1 -0
- package/dist/{skill-23WAHUOB.js → skill-GMAERMQL.js} +10 -10
- package/dist/{skill-23WAHUOB.js.map → skill-GMAERMQL.js.map} +1 -1
- package/dist/skills/debug-run/SKILL.md +7 -1
- package/dist/skills/debug-run/history/1.3.1.md +279 -0
- package/dist/skills/debug-run/version.json +1 -1
- package/dist/skills/optimize-cache/SKILL.md +29 -2
- package/dist/{spec-LM5XHOQ5.js → spec-2NP36U3Y.js} +5 -5
- package/dist/{src-22RI5VP2.js → src-4T6GHXVO.js} +2 -2
- package/dist/{src-NCJPUAE6.js → src-CG52HEE7.js} +10 -8
- package/dist/{src-Y3K7UJEF.js → src-PK5OZXCM.js} +2 -2
- package/dist/{src-BGDRMOKC.js → src-UEOOC425.js} +295 -102
- package/dist/src-UEOOC425.js.map +1 -0
- package/dist/{start-SWY55CZX.js → start-3C7EEFW2.js} +5 -5
- package/dist/{tag-YSU2XXPI.js → tag-JSHOMLBR.js} +6 -6
- package/dist/{task-NLBKLD7D.js → task-YGWVYTBJ.js} +5 -5
- package/dist/{test-suite-QCPWZ2LS.js → test-suite-LI7ZH367.js} +10 -8
- package/dist/{test-suite-QCPWZ2LS.js.map → test-suite-LI7ZH367.js.map} +1 -1
- package/dist/trace-UMLOSIIR.js +16 -0
- package/dist/{triage-TT4BMDBU.js → triage-ZWJG4NBJ.js} +6 -6
- package/dist/{upgrade-6ZUFETKX.js → upgrade-S7CGEK6H.js} +3 -3
- package/dist/{workflow-2CX3ZNOQ.js → workflow-T4HSAOGW.js} +86 -15
- package/dist/workflow-T4HSAOGW.js.map +1 -0
- package/dist/{workflow-cache-GXNE6SU2.js → workflow-cache-XVEZ36KF.js} +8 -8
- package/dist/{workflow-debug-PRX3DWGD.js → workflow-debug-T2BULXZ7.js} +9 -9
- package/dist/{workflow-proposals-BW327WGL.js → workflow-proposals-XXEZICN2.js} +5 -7
- package/dist/workflow-proposals-XXEZICN2.js.map +1 -0
- package/package.json +1 -1
- package/dist/chunk-CQE46HSM.js.map +0 -1
- package/dist/chunk-NL7CVG56.js.map +0 -1
- package/dist/chunk-QGI4UCJX.js.map +0 -1
- package/dist/chunk-QQVWGWPI.js.map +0 -1
- package/dist/chunk-YN763NWQ.js.map +0 -1
- package/dist/chunk-ZD3KHESI.js.map +0 -1
- package/dist/docs-DIAFBDXQ.js.map +0 -1
- package/dist/feature-flag-XG26RURR.js.map +0 -1
- package/dist/knobs-A2BOBH22.js.map +0 -1
- package/dist/redis-DHZXHL4S.js.map +0 -1
- package/dist/sandbox-DWSGLY7B.js.map +0 -1
- package/dist/session-Y5RHU54D.js.map +0 -1
- package/dist/src-BGDRMOKC.js.map +0 -1
- package/dist/trace-A3ZY6K26.js +0 -16
- package/dist/workflow-2CX3ZNOQ.js.map +0 -1
- package/dist/workflow-proposals-BW327WGL.js.map +0 -1
- /package/dist/{api-catalog-7HLEN7C2.js.map → api-catalog-WTFQNLK6.js.map} +0 -0
- /package/dist/{attachment-OVNQD6Z2.js.map → attachment-U3NKVPEY.js.map} +0 -0
- /package/dist/{auth-VUHL74FH.js.map → auth-VQG2CDUD.js.map} +0 -0
- /package/dist/{chunk-PZ4LCN6K.js.map → chunk-3X3NW7QA.js.map} +0 -0
- /package/dist/{chunk-VGTKUOYS.js.map → chunk-46IUJXSD.js.map} +0 -0
- /package/dist/{chunk-Z5LUTUDN.js.map → chunk-CMGI7UZD.js.map} +0 -0
- /package/dist/{chunk-EEN2TZUQ.js.map → chunk-FNPMWDUQ.js.map} +0 -0
- /package/dist/{chunk-EJ4U242G.js.map → chunk-HDFYUFBI.js.map} +0 -0
- /package/dist/{chunk-ENDHMYEJ.js.map → chunk-NHTEKEYE.js.map} +0 -0
- /package/dist/{chunk-ZTOE3ND3.js.map → chunk-XJ5YYYGC.js.map} +0 -0
- /package/dist/{credential-LO2SEEHU.js.map → credential-E6KUHRGU.js.map} +0 -0
- /package/dist/{credential-template-ZN7W7734.js.map → credential-template-4GPOPBGD.js.map} +0 -0
- /package/dist/{debug-workflow-R3RYYAXK.js.map → debug-workflow-XCLCY6S7.js.map} +0 -0
- /package/dist/{doctor-NZPUSCRE.js.map → doctor-ERIVTCQS.js.map} +0 -0
- /package/dist/{environment-RQVU4P5M.js.map → environment-7Y4BV6XY.js.map} +0 -0
- /package/dist/{init-EDNLKGPT.js.map → init-OROOM4HF.js.map} +0 -0
- /package/dist/{install-FYZ3HNZK.js.map → install-OJFXHY6U.js.map} +0 -0
- /package/dist/{issues-NNRVTJ4L.js.map → issues-32GONR6C.js.map} +0 -0
- /package/dist/{list-F33VZ4BJ.js.map → list-ZMIKEC5P.js.map} +0 -0
- /package/dist/{local-DQDTM3XA.js.map → local-PUD24GGQ.js.map} +0 -0
- /package/dist/{login-BUMVIB36.js.map → login-BSO7YX2D.js.map} +0 -0
- /package/dist/{pdf-extract-ABWV3L5X.js.map → pdf-extract-YHE54XU4.js.map} +0 -0
- /package/dist/{property-NJ4SRXQG.js.map → property-K5DBL4UE.js.map} +0 -0
- /package/dist/{psql-VBZFCMNR.js.map → psql-PQFUFTSE.js.map} +0 -0
- /package/dist/{record-WAO36O7G.js.map → record-EIIYLFJ4.js.map} +0 -0
- /package/dist/{release-STJKUKTE.js.map → release-LYC2P7DZ.js.map} +0 -0
- /package/dist/{scenarios-HCIDY725.js.map → scenarios-2XJ2G3KR.js.map} +0 -0
- /package/dist/{spec-LM5XHOQ5.js.map → spec-2NP36U3Y.js.map} +0 -0
- /package/dist/{src-22RI5VP2.js.map → src-4T6GHXVO.js.map} +0 -0
- /package/dist/{src-NCJPUAE6.js.map → src-CG52HEE7.js.map} +0 -0
- /package/dist/{src-Y3K7UJEF.js.map → src-PK5OZXCM.js.map} +0 -0
- /package/dist/{start-SWY55CZX.js.map → start-3C7EEFW2.js.map} +0 -0
- /package/dist/{tag-YSU2XXPI.js.map → tag-JSHOMLBR.js.map} +0 -0
- /package/dist/{task-NLBKLD7D.js.map → task-YGWVYTBJ.js.map} +0 -0
- /package/dist/{trace-A3ZY6K26.js.map → trace-UMLOSIIR.js.map} +0 -0
- /package/dist/{triage-TT4BMDBU.js.map → triage-ZWJG4NBJ.js.map} +0 -0
- /package/dist/{upgrade-6ZUFETKX.js.map → upgrade-S7CGEK6H.js.map} +0 -0
- /package/dist/{workflow-cache-GXNE6SU2.js.map → workflow-cache-XVEZ36KF.js.map} +0 -0
- /package/dist/{workflow-debug-PRX3DWGD.js.map → workflow-debug-T2BULXZ7.js.map} +0 -0
|
@@ -1,30 +1,32 @@
|
|
|
1
1
|
import { createRequire as __cr } from "module"; const require = __cr(import.meta.url);
|
|
2
2
|
import {
|
|
3
3
|
reconstructSnapshots
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-KCHKFYVX.js";
|
|
5
5
|
import {
|
|
6
6
|
buildLocatorString
|
|
7
7
|
} from "./chunk-5GD47G2D.js";
|
|
8
8
|
import {
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
applyCustomAugmentors,
|
|
10
|
+
captureSubstrateV2,
|
|
11
|
+
parseSnapshot
|
|
12
|
+
} from "./chunk-VGYN2KU2.js";
|
|
11
13
|
import "./chunk-JWHYXEA2.js";
|
|
12
14
|
import {
|
|
13
15
|
MACRO_PATTERN,
|
|
14
16
|
isVolatileIdentifier,
|
|
15
17
|
stableAttrSelector,
|
|
16
18
|
stableIdentifierPrefix
|
|
17
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-JYGNMKZ5.js";
|
|
18
20
|
import "./chunk-6LEZCKKV.js";
|
|
19
21
|
import {
|
|
20
22
|
consoleLogger
|
|
21
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-KRWRUU6R.js";
|
|
22
24
|
import "./chunk-VKVL7WBN.js";
|
|
23
25
|
|
|
24
26
|
// ../workflow-cache/src/logger.ts
|
|
25
27
|
var activeLogger = consoleLogger;
|
|
26
|
-
function setWorkflowCacheLogger(
|
|
27
|
-
activeLogger =
|
|
28
|
+
function setWorkflowCacheLogger(logger4) {
|
|
29
|
+
activeLogger = logger4;
|
|
28
30
|
}
|
|
29
31
|
function createLogger(bindings) {
|
|
30
32
|
if (!bindings || Object.keys(bindings).length === 0) {
|
|
@@ -53,8 +55,8 @@ function sortObjectKeys(obj) {
|
|
|
53
55
|
}
|
|
54
56
|
if (obj !== null && typeof obj === "object") {
|
|
55
57
|
const sorted = Object.keys(obj).sort().reduce(
|
|
56
|
-
(acc,
|
|
57
|
-
acc[
|
|
58
|
+
(acc, key2) => {
|
|
59
|
+
acc[key2] = sortObjectKeys(obj[key2]);
|
|
58
60
|
return acc;
|
|
59
61
|
},
|
|
60
62
|
{}
|
|
@@ -64,10 +66,26 @@ function sortObjectKeys(obj) {
|
|
|
64
66
|
return obj;
|
|
65
67
|
}
|
|
66
68
|
function generateNodeHash(input) {
|
|
69
|
+
return hashWithPrefix(input, HASH_VERSION);
|
|
70
|
+
}
|
|
71
|
+
function generateNodeHashV3(input) {
|
|
72
|
+
const { playbookSteps: _playbookSteps, inlineAssertions, ...identity } = input;
|
|
73
|
+
const v3Input = {
|
|
74
|
+
...identity,
|
|
75
|
+
...inlineAssertions ? {
|
|
76
|
+
inlineAssertions: inlineAssertions.map(({ condition, agentic }) => ({
|
|
77
|
+
condition,
|
|
78
|
+
...agentic !== void 0 ? { agentic } : {}
|
|
79
|
+
}))
|
|
80
|
+
} : {}
|
|
81
|
+
};
|
|
82
|
+
return hashWithPrefix(v3Input, "v3");
|
|
83
|
+
}
|
|
84
|
+
function hashWithPrefix(input, version) {
|
|
67
85
|
const sortedInput = sortObjectKeys(input);
|
|
68
86
|
const stableJson = JSON.stringify(sortedInput);
|
|
69
87
|
const hash = createHash("sha256").update(stableJson).digest("hex").slice(0, 16);
|
|
70
|
-
return `${
|
|
88
|
+
return `${version}:${hash}`;
|
|
71
89
|
}
|
|
72
90
|
|
|
73
91
|
// ../workflow-cache/src/build-locator.ts
|
|
@@ -95,6 +113,15 @@ function buildLocator(snapshot, ref, variableValues = {}) {
|
|
|
95
113
|
const frameContext = frameContextFor(target.el);
|
|
96
114
|
const baseDynamicText = buildDynamicText(target);
|
|
97
115
|
const ancestors = ancestorChain(target);
|
|
116
|
+
const augmentorAnchor = target.el.augmentorAnchor;
|
|
117
|
+
if (augmentorAnchor) {
|
|
118
|
+
return {
|
|
119
|
+
selectors: applyContexts({ css: augmentorAnchor }, frameContext, baseDynamicText),
|
|
120
|
+
predicate: "augmentorAnchor",
|
|
121
|
+
bindings: allBindings,
|
|
122
|
+
irreducible: false
|
|
123
|
+
};
|
|
124
|
+
}
|
|
98
125
|
const uniqueTestId = pickUniqueTestId(target, flat);
|
|
99
126
|
if (uniqueTestId) {
|
|
100
127
|
return {
|
|
@@ -366,12 +393,12 @@ function buildRowScopedOrdinalLocator(args) {
|
|
|
366
393
|
const buttonRefs = collectRoleRefs(anchor.el, "button");
|
|
367
394
|
const ordinal = buttonRefs.indexOf(args.target.el.ref);
|
|
368
395
|
if (ordinal < 0) continue;
|
|
369
|
-
const [
|
|
396
|
+
const [key2, value] = match;
|
|
370
397
|
return {
|
|
371
|
-
locator: `getByRole('${escapeLocatorString(anchor.el.role)}').filter({ hasText: '{{var.${
|
|
398
|
+
locator: `getByRole('${escapeLocatorString(anchor.el.role)}').filter({ hasText: '{{var.${key2}}}' }).getByRole('button').nth(${ordinal})`,
|
|
372
399
|
anchor,
|
|
373
400
|
innerAncestors: args.ancestors.slice(i + 1),
|
|
374
|
-
key,
|
|
401
|
+
key: key2,
|
|
375
402
|
value
|
|
376
403
|
};
|
|
377
404
|
}
|
|
@@ -392,8 +419,8 @@ function escapeLocatorString(value) {
|
|
|
392
419
|
var MIN_TEMPLATING_LENGTH = 3;
|
|
393
420
|
function templateAll(flat, variableValues) {
|
|
394
421
|
const summary = /* @__PURE__ */ new Map();
|
|
395
|
-
const compiled = Object.entries(variableValues).filter(([, v]) => typeof v === "string" && v.length >= MIN_TEMPLATING_LENGTH).map(([
|
|
396
|
-
key,
|
|
422
|
+
const compiled = Object.entries(variableValues).filter(([, v]) => typeof v === "string" && v.length >= MIN_TEMPLATING_LENGTH).map(([key2, value]) => ({
|
|
423
|
+
key: key2,
|
|
397
424
|
value,
|
|
398
425
|
regex: new RegExp(`(^|\\W)${escapeRegex(value)}(?=\\W|$)`, "g")
|
|
399
426
|
}));
|
|
@@ -870,12 +897,12 @@ function findRowVariableScope(args) {
|
|
|
870
897
|
continue;
|
|
871
898
|
}
|
|
872
899
|
const anchorText = collectSubtreeText(anchor.el);
|
|
873
|
-
for (const [
|
|
900
|
+
for (const [key2, value] of entries) {
|
|
874
901
|
if (!textContainsValue(anchorText, value)) continue;
|
|
875
902
|
return {
|
|
876
903
|
anchor,
|
|
877
904
|
innerAncestors: args.ancestors.slice(i + 1),
|
|
878
|
-
key,
|
|
905
|
+
key: key2,
|
|
879
906
|
value
|
|
880
907
|
};
|
|
881
908
|
}
|
|
@@ -977,9 +1004,9 @@ function parseLine(line) {
|
|
|
977
1004
|
if (cleanContent.startsWith("/")) {
|
|
978
1005
|
const colonIdx = cleanContent.indexOf(":");
|
|
979
1006
|
if (colonIdx !== -1) {
|
|
980
|
-
const
|
|
1007
|
+
const key2 = cleanContent.slice(1, colonIdx).trim();
|
|
981
1008
|
const value = cleanContent.slice(colonIdx + 1).trim();
|
|
982
|
-
return { indent, role: "_property", attributes: { [
|
|
1009
|
+
return { indent, role: "_property", attributes: { [key2]: value } };
|
|
983
1010
|
}
|
|
984
1011
|
}
|
|
985
1012
|
if (withoutBrackets.startsWith('"') && withoutBrackets.endsWith('"')) {
|
|
@@ -1005,9 +1032,9 @@ function parseLine(line) {
|
|
|
1005
1032
|
const attributes = {};
|
|
1006
1033
|
const attrMatches = cleanContent.matchAll(/\[(\w+)=([^\]]+)\]/g);
|
|
1007
1034
|
for (const match of attrMatches) {
|
|
1008
|
-
const [,
|
|
1009
|
-
if (
|
|
1010
|
-
attributes[
|
|
1035
|
+
const [, key2, value] = match;
|
|
1036
|
+
if (key2 !== "ref") {
|
|
1037
|
+
attributes[key2] = value;
|
|
1011
1038
|
}
|
|
1012
1039
|
}
|
|
1013
1040
|
return {
|
|
@@ -1414,11 +1441,11 @@ function escapeForLocatorString(value) {
|
|
|
1414
1441
|
return value.replace(/\\/g, "\\\\").replace(/'/g, "\\'");
|
|
1415
1442
|
}
|
|
1416
1443
|
function hydrateLocatorVariables(locatorStr, variableValues) {
|
|
1417
|
-
return locatorStr.replace(/\{\{var\.([a-zA-Z0-9_]+)\}\}/g, (_match,
|
|
1418
|
-
const value = variableValues[
|
|
1444
|
+
return locatorStr.replace(/\{\{var\.([a-zA-Z0-9_]+)\}\}/g, (_match, key2) => {
|
|
1445
|
+
const value = variableValues[key2];
|
|
1419
1446
|
if (value === void 0) {
|
|
1420
|
-
getLogger().warn("[LocatorParser] Variable placeholder not found in values", { key });
|
|
1421
|
-
return `{{var.${
|
|
1447
|
+
getLogger().warn("[LocatorParser] Variable placeholder not found in values", { key: key2 });
|
|
1448
|
+
return `{{var.${key2}}}`;
|
|
1422
1449
|
}
|
|
1423
1450
|
return escapeForLocatorString(value);
|
|
1424
1451
|
});
|
|
@@ -1585,7 +1612,7 @@ function parseObjectArg(input) {
|
|
|
1585
1612
|
for (const pair of pairs) {
|
|
1586
1613
|
const colonIdx = pair.indexOf(":");
|
|
1587
1614
|
if (colonIdx === -1) continue;
|
|
1588
|
-
const
|
|
1615
|
+
const key2 = pair.slice(0, colonIdx).trim().replace(/^['"]|['"]$/g, "");
|
|
1589
1616
|
const rawValue = pair.slice(colonIdx + 1).trim();
|
|
1590
1617
|
if (rawValue.startsWith("'") || rawValue.startsWith('"')) {
|
|
1591
1618
|
const q = rawValue[0];
|
|
@@ -1594,20 +1621,20 @@ function parseObjectArg(input) {
|
|
|
1594
1621
|
if (rawValue[end] === "\\") end++;
|
|
1595
1622
|
end++;
|
|
1596
1623
|
}
|
|
1597
|
-
obj[
|
|
1624
|
+
obj[key2] = rawValue.slice(1, end).replace(/\\'/g, "'").replace(/\\"/g, '"');
|
|
1598
1625
|
} else if (rawValue.startsWith("/")) {
|
|
1599
1626
|
const regexMatch = rawValue.match(/^\/([^/]+)\/([gimsuy]*)/);
|
|
1600
1627
|
if (regexMatch) {
|
|
1601
|
-
obj[
|
|
1628
|
+
obj[key2] = new RegExp(regexMatch[1], regexMatch[2]);
|
|
1602
1629
|
}
|
|
1603
1630
|
} else if (rawValue === "true") {
|
|
1604
|
-
obj[
|
|
1631
|
+
obj[key2] = true;
|
|
1605
1632
|
} else if (rawValue === "false") {
|
|
1606
|
-
obj[
|
|
1633
|
+
obj[key2] = false;
|
|
1607
1634
|
} else if (/^-?\d+$/.test(rawValue)) {
|
|
1608
|
-
obj[
|
|
1635
|
+
obj[key2] = parseInt(rawValue, 10);
|
|
1609
1636
|
} else {
|
|
1610
|
-
obj[
|
|
1637
|
+
obj[key2] = rawValue;
|
|
1611
1638
|
}
|
|
1612
1639
|
}
|
|
1613
1640
|
return { value: obj, rest };
|
|
@@ -3368,8 +3395,8 @@ async function resolveElement(page, selectors, _timeoutMs, options) {
|
|
|
3368
3395
|
errors.push(`CSS selector ("${selectors.css}") found no matches`);
|
|
3369
3396
|
}
|
|
3370
3397
|
if (selectors.dynamicText && options?.variableValues && selectors.role && !requireSelect && !skipHeuristicFallbacks) {
|
|
3371
|
-
const { key } = selectors.dynamicText;
|
|
3372
|
-
const currentValue = options.variableValues[
|
|
3398
|
+
const { key: key2 } = selectors.dynamicText;
|
|
3399
|
+
const currentValue = options.variableValues[key2];
|
|
3373
3400
|
if (currentValue) {
|
|
3374
3401
|
logger().debug("[ElementResolver] Trying structural fallback for dynamic text", {
|
|
3375
3402
|
role: selectors.role.role,
|
|
@@ -3585,15 +3612,15 @@ function deriveSelectorsFromElementInfo(elementInfo) {
|
|
|
3585
3612
|
}
|
|
3586
3613
|
function sanitizeArgsForCache(args) {
|
|
3587
3614
|
const sanitized = {};
|
|
3588
|
-
for (const [
|
|
3589
|
-
if (
|
|
3615
|
+
for (const [key2, value] of Object.entries(args)) {
|
|
3616
|
+
if (key2 === "ref" || key2 === "startRef" || key2 === "endRef") {
|
|
3590
3617
|
continue;
|
|
3591
3618
|
}
|
|
3592
|
-
if (
|
|
3619
|
+
if (key2 === "signal" || key2 === "timeoutMs") {
|
|
3593
3620
|
continue;
|
|
3594
3621
|
}
|
|
3595
3622
|
if (Array.isArray(value)) {
|
|
3596
|
-
sanitized[
|
|
3623
|
+
sanitized[key2] = value.map((item) => {
|
|
3597
3624
|
if (typeof item === "object" && item !== null) {
|
|
3598
3625
|
return sanitizeArgsForCache(item);
|
|
3599
3626
|
}
|
|
@@ -3601,7 +3628,7 @@ function sanitizeArgsForCache(args) {
|
|
|
3601
3628
|
});
|
|
3602
3629
|
continue;
|
|
3603
3630
|
}
|
|
3604
|
-
sanitized[
|
|
3631
|
+
sanitized[key2] = value;
|
|
3605
3632
|
}
|
|
3606
3633
|
return sanitized;
|
|
3607
3634
|
}
|
|
@@ -3754,12 +3781,12 @@ async function findRowAnchor(originalLocator, timeoutMs) {
|
|
|
3754
3781
|
const t = raw.trim();
|
|
3755
3782
|
if (t.length < 3) return;
|
|
3756
3783
|
if (t.length > 120) return;
|
|
3757
|
-
const
|
|
3758
|
-
if (
|
|
3759
|
-
if (targetText.length > 0 &&
|
|
3760
|
-
if (targetText.length > 0 && targetText.includes(
|
|
3761
|
-
if (seen.has(
|
|
3762
|
-
seen.add(
|
|
3784
|
+
const key2 = t.toLowerCase();
|
|
3785
|
+
if (key2 === targetText) return;
|
|
3786
|
+
if (targetText.length > 0 && key2.includes(targetText)) return;
|
|
3787
|
+
if (targetText.length > 0 && targetText.includes(key2)) return;
|
|
3788
|
+
if (seen.has(key2)) return;
|
|
3789
|
+
seen.add(key2);
|
|
3763
3790
|
texts.push(t);
|
|
3764
3791
|
};
|
|
3765
3792
|
if (ariaLabel) pushText(ariaLabel);
|
|
@@ -3814,7 +3841,7 @@ async function findRowAnchor(originalLocator, timeoutMs) {
|
|
|
3814
3841
|
}
|
|
3815
3842
|
async function discoverParentContext(page, selectors, selectorType, originalLocator, options) {
|
|
3816
3843
|
const { timeoutMs, maxParentDepth } = options;
|
|
3817
|
-
const
|
|
3844
|
+
const logger4 = getLogger2();
|
|
3818
3845
|
const context = selectors.frameContext?.selector ? page.frameLocator(selectors.frameContext.selector) : page;
|
|
3819
3846
|
try {
|
|
3820
3847
|
const rowCandidate = await findRowAnchor(originalLocator, timeoutMs);
|
|
@@ -3833,7 +3860,7 @@ async function discoverParentContext(page, selectors, selectorType, originalLoca
|
|
|
3833
3860
|
if (!resolved) continue;
|
|
3834
3861
|
const isSame = await isSameDOMElement(page, originalLocator, resolved, timeoutMs);
|
|
3835
3862
|
if (!isSame) continue;
|
|
3836
|
-
|
|
3863
|
+
logger4.debug("[SelectorDerivation] Found unique row anchor", {
|
|
3837
3864
|
selectorType,
|
|
3838
3865
|
parentContext: candidateParent
|
|
3839
3866
|
});
|
|
@@ -3844,7 +3871,7 @@ async function discoverParentContext(page, selectors, selectorType, originalLoca
|
|
|
3844
3871
|
}
|
|
3845
3872
|
}
|
|
3846
3873
|
} catch (err) {
|
|
3847
|
-
|
|
3874
|
+
logger4.debug("[SelectorDerivation] Row-anchor strategy error", {
|
|
3848
3875
|
error: err instanceof Error ? err.message : String(err)
|
|
3849
3876
|
});
|
|
3850
3877
|
}
|
|
@@ -3937,7 +3964,7 @@ async function discoverParentContext(page, selectors, selectorType, originalLoca
|
|
|
3937
3964
|
if (resolved) {
|
|
3938
3965
|
const isSame = await isSameDOMElement(page, originalLocator, resolved, timeoutMs);
|
|
3939
3966
|
if (!isSame) {
|
|
3940
|
-
|
|
3967
|
+
logger4.debug(
|
|
3941
3968
|
"[SelectorDerivation] Parent-scoped selector resolved to wrong element, skipping",
|
|
3942
3969
|
{
|
|
3943
3970
|
selectorType,
|
|
@@ -3946,7 +3973,7 @@ async function discoverParentContext(page, selectors, selectorType, originalLoca
|
|
|
3946
3973
|
);
|
|
3947
3974
|
continue;
|
|
3948
3975
|
}
|
|
3949
|
-
|
|
3976
|
+
logger4.debug("[SelectorDerivation] Found unique parent via simple scoping", {
|
|
3950
3977
|
selectorType,
|
|
3951
3978
|
parentContext: candidateParent
|
|
3952
3979
|
});
|
|
@@ -3958,7 +3985,7 @@ async function discoverParentContext(page, selectors, selectorType, originalLoca
|
|
|
3958
3985
|
}
|
|
3959
3986
|
}
|
|
3960
3987
|
} catch (err) {
|
|
3961
|
-
|
|
3988
|
+
logger4.debug("[SelectorDerivation] Error in simple parent scoping", {
|
|
3962
3989
|
error: err instanceof Error ? err.message : String(err)
|
|
3963
3990
|
});
|
|
3964
3991
|
}
|
|
@@ -4079,7 +4106,7 @@ async function discoverParentContext(page, selectors, selectorType, originalLoca
|
|
|
4079
4106
|
}
|
|
4080
4107
|
const targetEl = elementAncestries.find((e) => e.isTarget);
|
|
4081
4108
|
if (!targetEl) {
|
|
4082
|
-
|
|
4109
|
+
logger4.warn("[SelectorDerivation] Target not found by DOM identity in ancestry search");
|
|
4083
4110
|
return null;
|
|
4084
4111
|
}
|
|
4085
4112
|
for (let depth = 0; depth < maxParentDepth; depth++) {
|
|
@@ -4098,7 +4125,7 @@ async function discoverParentContext(page, selectors, selectorType, originalLoca
|
|
|
4098
4125
|
try {
|
|
4099
4126
|
const resolved = await resolveElement(page, strategyWithChain, timeoutMs, { mode: "verify" });
|
|
4100
4127
|
if (resolved) {
|
|
4101
|
-
|
|
4128
|
+
logger4.debug("[SelectorDerivation] Found unique parent chain via recursive search", {
|
|
4102
4129
|
depth,
|
|
4103
4130
|
parentChain
|
|
4104
4131
|
});
|
|
@@ -4108,7 +4135,7 @@ async function discoverParentContext(page, selectors, selectorType, originalLoca
|
|
|
4108
4135
|
continue;
|
|
4109
4136
|
}
|
|
4110
4137
|
}
|
|
4111
|
-
|
|
4138
|
+
logger4.warn("[SelectorDerivation] No unique parent found, using matchIndex fallback", {
|
|
4112
4139
|
targetIndex: targetEl.index,
|
|
4113
4140
|
matchCount: count
|
|
4114
4141
|
});
|
|
@@ -4117,7 +4144,7 @@ async function discoverParentContext(page, selectors, selectorType, originalLoca
|
|
|
4117
4144
|
};
|
|
4118
4145
|
}
|
|
4119
4146
|
async function probeChildIconCSS(page, originalLocator, role) {
|
|
4120
|
-
const
|
|
4147
|
+
const logger4 = getLogger2();
|
|
4121
4148
|
const iconAttr = await originalLocator.evaluate((el) => {
|
|
4122
4149
|
const svg = el.querySelector("svg[data-icon]");
|
|
4123
4150
|
return svg?.getAttribute("data-icon") ?? null;
|
|
@@ -4127,7 +4154,7 @@ async function probeChildIconCSS(page, originalLocator, role) {
|
|
|
4127
4154
|
try {
|
|
4128
4155
|
const count = await page.locator(baseSelector).count();
|
|
4129
4156
|
if (count === 1) {
|
|
4130
|
-
|
|
4157
|
+
logger4.debug("[SelectorDerivation] probeChildIconCSS found unique selector", {
|
|
4131
4158
|
css: baseSelector
|
|
4132
4159
|
});
|
|
4133
4160
|
return baseSelector;
|
|
@@ -4141,7 +4168,7 @@ async function probeChildIconCSS(page, originalLocator, role) {
|
|
|
4141
4168
|
const hasMarker = await matches.nth(i).evaluate((el, attr) => el.hasAttribute(attr), MARKER);
|
|
4142
4169
|
if (hasMarker) {
|
|
4143
4170
|
const nthSelector = `${baseSelector} >> nth=${i}`;
|
|
4144
|
-
|
|
4171
|
+
logger4.debug("[SelectorDerivation] probeChildIconCSS disambiguated via nth", {
|
|
4145
4172
|
css: nthSelector,
|
|
4146
4173
|
matchCount: count,
|
|
4147
4174
|
index: i
|
|
@@ -4154,7 +4181,7 @@ async function probeChildIconCSS(page, originalLocator, role) {
|
|
|
4154
4181
|
});
|
|
4155
4182
|
}
|
|
4156
4183
|
}
|
|
4157
|
-
|
|
4184
|
+
logger4.debug("[SelectorDerivation] probeChildIconCSS could not disambiguate", {
|
|
4158
4185
|
css: baseSelector,
|
|
4159
4186
|
count
|
|
4160
4187
|
});
|
|
@@ -4164,7 +4191,7 @@ async function probeChildIconCSS(page, originalLocator, role) {
|
|
|
4164
4191
|
}
|
|
4165
4192
|
}
|
|
4166
4193
|
async function probeElementIdCSS(page, originalLocator) {
|
|
4167
|
-
const
|
|
4194
|
+
const logger4 = getLogger2();
|
|
4168
4195
|
const elementId = await originalLocator.evaluate((el) => {
|
|
4169
4196
|
if (el.id) return el.id;
|
|
4170
4197
|
const child = el.querySelector("[id]");
|
|
@@ -4175,7 +4202,7 @@ async function probeElementIdCSS(page, originalLocator) {
|
|
|
4175
4202
|
try {
|
|
4176
4203
|
const count = await page.locator(baseSelector).count();
|
|
4177
4204
|
if (count === 1) {
|
|
4178
|
-
|
|
4205
|
+
logger4.debug("[SelectorDerivation] probeElementIdCSS found unique selector", {
|
|
4179
4206
|
css: baseSelector
|
|
4180
4207
|
});
|
|
4181
4208
|
return baseSelector;
|
|
@@ -4198,7 +4225,7 @@ async function probeElementIdCSS(page, originalLocator) {
|
|
|
4198
4225
|
}
|
|
4199
4226
|
}
|
|
4200
4227
|
if (visibleCount === 1 && targetIsOnlyVisible) {
|
|
4201
|
-
|
|
4228
|
+
logger4.debug("[SelectorDerivation] probeElementIdCSS: single visible among duplicates", {
|
|
4202
4229
|
css: baseSelector,
|
|
4203
4230
|
matchCount: count
|
|
4204
4231
|
});
|
|
@@ -4212,7 +4239,7 @@ async function probeElementIdCSS(page, originalLocator) {
|
|
|
4212
4239
|
const hasMarker = await matches.nth(i).evaluate((el, attr) => el.hasAttribute(attr), MARKER);
|
|
4213
4240
|
if (hasMarker) {
|
|
4214
4241
|
const nthSelector = `${baseSelector} >> nth=${i}`;
|
|
4215
|
-
|
|
4242
|
+
logger4.debug("[SelectorDerivation] probeElementIdCSS disambiguated via nth", {
|
|
4216
4243
|
css: nthSelector,
|
|
4217
4244
|
matchCount: count,
|
|
4218
4245
|
index: i
|
|
@@ -4225,7 +4252,7 @@ async function probeElementIdCSS(page, originalLocator) {
|
|
|
4225
4252
|
});
|
|
4226
4253
|
}
|
|
4227
4254
|
}
|
|
4228
|
-
|
|
4255
|
+
logger4.debug("[SelectorDerivation] probeElementIdCSS could not disambiguate", {
|
|
4229
4256
|
css: baseSelector,
|
|
4230
4257
|
count
|
|
4231
4258
|
});
|
|
@@ -4235,14 +4262,14 @@ async function probeElementIdCSS(page, originalLocator) {
|
|
|
4235
4262
|
}
|
|
4236
4263
|
}
|
|
4237
4264
|
async function probeTitleCSS(page, originalLocator) {
|
|
4238
|
-
const
|
|
4265
|
+
const logger4 = getLogger2();
|
|
4239
4266
|
const titleAttr = await originalLocator.evaluate((el) => el.getAttribute("title")).catch(() => null);
|
|
4240
4267
|
if (!titleAttr) return void 0;
|
|
4241
4268
|
const baseSelector = `[title="${titleAttr}"]`;
|
|
4242
4269
|
try {
|
|
4243
4270
|
const count = await page.locator(baseSelector).count();
|
|
4244
4271
|
if (count === 1) {
|
|
4245
|
-
|
|
4272
|
+
logger4.debug("[SelectorDerivation] probeTitleCSS found unique selector", {
|
|
4246
4273
|
css: baseSelector
|
|
4247
4274
|
});
|
|
4248
4275
|
return baseSelector;
|
|
@@ -4256,7 +4283,7 @@ async function probeTitleCSS(page, originalLocator) {
|
|
|
4256
4283
|
const hasMarker = await matches.nth(i).evaluate((el, attr) => el.hasAttribute(attr), MARKER);
|
|
4257
4284
|
if (hasMarker) {
|
|
4258
4285
|
const nthSelector = `${baseSelector} >> nth=${i}`;
|
|
4259
|
-
|
|
4286
|
+
logger4.debug("[SelectorDerivation] probeTitleCSS disambiguated via nth", {
|
|
4260
4287
|
css: nthSelector,
|
|
4261
4288
|
matchCount: count,
|
|
4262
4289
|
index: i
|
|
@@ -4269,7 +4296,7 @@ async function probeTitleCSS(page, originalLocator) {
|
|
|
4269
4296
|
});
|
|
4270
4297
|
}
|
|
4271
4298
|
}
|
|
4272
|
-
|
|
4299
|
+
logger4.debug("[SelectorDerivation] probeTitleCSS could not disambiguate", {
|
|
4273
4300
|
css: baseSelector,
|
|
4274
4301
|
count
|
|
4275
4302
|
});
|
|
@@ -4375,7 +4402,7 @@ async function probeAncestorRowIndex(elementLocator, timeoutMs = 3e3) {
|
|
|
4375
4402
|
}
|
|
4376
4403
|
async function verifySingleSelector(page, selectors, selectorType, originalLocator, options) {
|
|
4377
4404
|
const { timeoutMs } = options;
|
|
4378
|
-
const
|
|
4405
|
+
const logger4 = getLogger2();
|
|
4379
4406
|
const result = {
|
|
4380
4407
|
selectorType,
|
|
4381
4408
|
verified: false,
|
|
@@ -4395,11 +4422,11 @@ async function verifySingleSelector(page, selectors, selectorType, originalLocat
|
|
|
4395
4422
|
result.verified = true;
|
|
4396
4423
|
return result;
|
|
4397
4424
|
}
|
|
4398
|
-
|
|
4425
|
+
logger4.debug("[SelectorDerivation] Initial resolution failed, trying parent disambiguation", {
|
|
4399
4426
|
selectorType
|
|
4400
4427
|
});
|
|
4401
4428
|
if (selectors.itemIndex !== void 0 || selectors.rowIndex !== void 0) {
|
|
4402
|
-
|
|
4429
|
+
logger4.debug("[SelectorDerivation] Data attributes present but did not disambiguate", {
|
|
4403
4430
|
selectorType,
|
|
4404
4431
|
itemIndex: selectors.itemIndex,
|
|
4405
4432
|
rowIndex: selectors.rowIndex
|
|
@@ -4552,9 +4579,9 @@ var DYNAMIC_TEXT_MIN_RATIO = 0.4;
|
|
|
4552
4579
|
var DYNAMIC_TEXT_DISTINCTIVE_LENGTH = 8;
|
|
4553
4580
|
function buildDynamicValueEntries(variableValues) {
|
|
4554
4581
|
const entries = [];
|
|
4555
|
-
for (const [
|
|
4582
|
+
for (const [key2, value] of Object.entries(variableValues)) {
|
|
4556
4583
|
if (typeof value !== "string" || value.length < DYNAMIC_TEXT_MIN_LENGTH) continue;
|
|
4557
|
-
entries.push({ source: "inputValue", key, value });
|
|
4584
|
+
entries.push({ source: "inputValue", key: key2, value });
|
|
4558
4585
|
}
|
|
4559
4586
|
entries.sort((a, b) => b.value.length - a.value.length);
|
|
4560
4587
|
return entries;
|
|
@@ -4709,9 +4736,9 @@ function hydrateDynamicSelectors(selectors, variableValues) {
|
|
|
4709
4736
|
}
|
|
4710
4737
|
const dynamicText = hydrated.dynamicText;
|
|
4711
4738
|
if (!dynamicText) return hydrated;
|
|
4712
|
-
const { key, originalText } = dynamicText;
|
|
4739
|
+
const { key: key2, originalText } = dynamicText;
|
|
4713
4740
|
selectors = hydrated;
|
|
4714
|
-
const currentValue = variableValues[
|
|
4741
|
+
const currentValue = variableValues[key2];
|
|
4715
4742
|
if (!currentValue || currentValue === originalText) {
|
|
4716
4743
|
return selectors;
|
|
4717
4744
|
}
|
|
@@ -4720,7 +4747,7 @@ function hydrateDynamicSelectors(selectors, variableValues) {
|
|
|
4720
4747
|
getLogger2().warn(
|
|
4721
4748
|
"[SelectorDerivation] Full-field replacement triggered due to stale surrounding text",
|
|
4722
4749
|
{
|
|
4723
|
-
key,
|
|
4750
|
+
key: key2,
|
|
4724
4751
|
originalText,
|
|
4725
4752
|
currentValue,
|
|
4726
4753
|
roleName: selectors.role?.name,
|
|
@@ -4736,8 +4763,8 @@ function hydrateDynamicSelectors(selectors, variableValues) {
|
|
|
4736
4763
|
return nextSelectors;
|
|
4737
4764
|
}
|
|
4738
4765
|
function hydratePlaywrightLocatorVariables(locator, variableValues) {
|
|
4739
|
-
return locator.replace(/\{\{var\.([a-zA-Z0-9_]+)\}\}/g, (match,
|
|
4740
|
-
const value = variableValues[
|
|
4766
|
+
return locator.replace(/\{\{var\.([a-zA-Z0-9_]+)\}\}/g, (match, key2) => {
|
|
4767
|
+
const value = variableValues[key2];
|
|
4741
4768
|
if (value === void 0) return match;
|
|
4742
4769
|
return value.replace(/\\/g, "\\\\").replace(/'/g, "\\'");
|
|
4743
4770
|
});
|
|
@@ -4827,9 +4854,9 @@ var escapeRegex3 = (s) => s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
|
4827
4854
|
var STRING_LITERAL = /'(?:\\.|[^'\\])*'|"(?:\\.|[^"\\])*"/g;
|
|
4828
4855
|
function replaceVariableValuesInString(input, sortedEntries) {
|
|
4829
4856
|
let out = input;
|
|
4830
|
-
for (const [
|
|
4857
|
+
for (const [key2, value] of sortedEntries) {
|
|
4831
4858
|
if (!value || out.indexOf(value) === -1) continue;
|
|
4832
|
-
out = out.replace(new RegExp(escapeRegex3(value), "g"), `$var.${
|
|
4859
|
+
out = out.replace(new RegExp(escapeRegex3(value), "g"), `$var.${key2}`);
|
|
4833
4860
|
}
|
|
4834
4861
|
return out;
|
|
4835
4862
|
}
|
|
@@ -4846,21 +4873,21 @@ function endsWithOddBackslashes(s) {
|
|
|
4846
4873
|
return count % 2 === 1;
|
|
4847
4874
|
}
|
|
4848
4875
|
function rewriteStringLiteralInner(inner, quote, sortedEntries) {
|
|
4849
|
-
for (const [
|
|
4876
|
+
for (const [key2, value] of sortedEntries) {
|
|
4850
4877
|
if (!value || inner.indexOf(value) === -1) continue;
|
|
4851
|
-
if (inner === value) return `$var.${
|
|
4878
|
+
if (inner === value) return `$var.${key2}`;
|
|
4852
4879
|
const parts = inner.split(value);
|
|
4853
4880
|
if (parts.some((p) => p.length > 0 && endsWithOddBackslashes(p))) continue;
|
|
4854
4881
|
const pieces = [];
|
|
4855
4882
|
for (let i = 0; i < parts.length; i++) {
|
|
4856
4883
|
const segment = parts[i];
|
|
4857
4884
|
if (segment.length > 0) pieces.push(`${quote}${segment}${quote}`);
|
|
4858
|
-
if (i < parts.length - 1) pieces.push(`$var.${
|
|
4885
|
+
if (i < parts.length - 1) pieces.push(`$var.${key2}`);
|
|
4859
4886
|
}
|
|
4860
4887
|
const rebuilt = pieces.join(" + ");
|
|
4861
4888
|
return replaceVariableValuesInJsExpression(
|
|
4862
4889
|
rebuilt,
|
|
4863
|
-
sortedEntries.filter(([k]) => k !==
|
|
4890
|
+
sortedEntries.filter(([k]) => k !== key2)
|
|
4864
4891
|
);
|
|
4865
4892
|
}
|
|
4866
4893
|
return `${quote}${inner}${quote}`;
|
|
@@ -5103,7 +5130,7 @@ var HeadlessDomSession = class {
|
|
|
5103
5130
|
|
|
5104
5131
|
// ../workflow-cache/src/optimizer/trace-node-segmenter.ts
|
|
5105
5132
|
var STEP_GROUP = /^Step (\d+): (.*)$/;
|
|
5106
|
-
var CACHE_REPLAY_GROUP = /^Cache Replay
|
|
5133
|
+
var CACHE_REPLAY_GROUP = /^Cache Replay(?: (\d+))?: (.*)$/;
|
|
5107
5134
|
var INTERNAL_GROUP_PREFIX = "Canary Internal:";
|
|
5108
5135
|
function segmentTraceByNode(groups, actions) {
|
|
5109
5136
|
const nodeGroups = groups.filter(
|
|
@@ -5114,10 +5141,11 @@ function segmentTraceByNode(groups, actions) {
|
|
|
5114
5141
|
const stepMatch = STEP_GROUP.exec(g.name);
|
|
5115
5142
|
const replayMatch = CACHE_REPLAY_GROUP.exec(g.name);
|
|
5116
5143
|
const effectiveEnd = g.endTime ?? sorted[idx + 1]?.startTime;
|
|
5144
|
+
const stepNumberRaw = stepMatch ? stepMatch[1] : replayMatch?.[1];
|
|
5117
5145
|
return {
|
|
5118
5146
|
kind: stepMatch ? "agent-step" : "cache-replay",
|
|
5119
|
-
stepNumber:
|
|
5120
|
-
label: stepMatch ? stepMatch[2] : replayMatch[
|
|
5147
|
+
stepNumber: stepNumberRaw !== void 0 ? Number(stepNumberRaw) : void 0,
|
|
5148
|
+
label: stepMatch ? stepMatch[2] : replayMatch[2],
|
|
5121
5149
|
groupCallId: g.callId,
|
|
5122
5150
|
startTime: g.startTime,
|
|
5123
5151
|
endTime: effectiveEnd,
|
|
@@ -5150,10 +5178,28 @@ function segmentTraceByNode(groups, actions) {
|
|
|
5150
5178
|
}
|
|
5151
5179
|
return segments;
|
|
5152
5180
|
}
|
|
5181
|
+
function resolveSegmentNodeIds(segments, steps) {
|
|
5182
|
+
let cursor = 0;
|
|
5183
|
+
return segments.map((segment) => {
|
|
5184
|
+
if (segment.stepNumber !== void 0) {
|
|
5185
|
+
const idx = segment.stepNumber - 1;
|
|
5186
|
+
cursor = Math.max(cursor, idx + 1);
|
|
5187
|
+
return steps[idx]?.nodeId ?? null;
|
|
5188
|
+
}
|
|
5189
|
+
for (let j = cursor; j < steps.length; j++) {
|
|
5190
|
+
if (steps[j].label === segment.label) {
|
|
5191
|
+
cursor = j + 1;
|
|
5192
|
+
return steps[j].nodeId;
|
|
5193
|
+
}
|
|
5194
|
+
}
|
|
5195
|
+
return null;
|
|
5196
|
+
});
|
|
5197
|
+
}
|
|
5153
5198
|
|
|
5154
5199
|
// ../workflow-cache/src/optimizer/substrate-materializer.ts
|
|
5155
5200
|
import { mkdir, writeFile } from "fs/promises";
|
|
5156
5201
|
import path from "path";
|
|
5202
|
+
import { pathToFileURL } from "url";
|
|
5157
5203
|
var logger2 = createLogger({ module: "SubstrateMaterializer" });
|
|
5158
5204
|
var SubstrateMaterializer = class {
|
|
5159
5205
|
constructor(opts) {
|
|
@@ -5171,8 +5217,8 @@ var SubstrateMaterializer = class {
|
|
|
5171
5217
|
* `'after'` is its result (the next action's context).
|
|
5172
5218
|
*/
|
|
5173
5219
|
async materialize(actionIndex, phase = "before") {
|
|
5174
|
-
const
|
|
5175
|
-
const hit = this.cache.get(
|
|
5220
|
+
const key2 = `${actionIndex}:${phase}`;
|
|
5221
|
+
const hit = this.cache.get(key2);
|
|
5176
5222
|
if (hit) return hit;
|
|
5177
5223
|
const results = await reconstructSnapshots({
|
|
5178
5224
|
traceZipPath: this.opts.traceZipPath,
|
|
@@ -5189,14 +5235,14 @@ var SubstrateMaterializer = class {
|
|
|
5189
5235
|
);
|
|
5190
5236
|
}
|
|
5191
5237
|
await mkdir(this.opts.outDir, { recursive: true });
|
|
5192
|
-
const domPath = path.
|
|
5238
|
+
const domPath = path.resolve(this.opts.outDir, `${actionIndex}.${phase}.dom.html`);
|
|
5193
5239
|
await writeFile(domPath, snapshot.html, "utf-8");
|
|
5194
5240
|
const page = await this.session.page();
|
|
5195
5241
|
try {
|
|
5196
|
-
await page.goto(
|
|
5242
|
+
await page.goto(pathToFileURL(domPath).href, { waitUntil: "load" });
|
|
5197
5243
|
await waitForTraceDomHydration(page);
|
|
5198
5244
|
const substrateYaml = await captureSubstrateV2(page, this.opts.logger ?? logger2);
|
|
5199
|
-
const substratePath = path.
|
|
5245
|
+
const substratePath = path.resolve(this.opts.outDir, `${actionIndex}.${phase}.substrate.v2.yaml`);
|
|
5200
5246
|
await writeFile(substratePath, substrateYaml, "utf-8");
|
|
5201
5247
|
const out = {
|
|
5202
5248
|
substrateYaml,
|
|
@@ -5205,7 +5251,7 @@ var SubstrateMaterializer = class {
|
|
|
5205
5251
|
actionIndex,
|
|
5206
5252
|
phase
|
|
5207
5253
|
};
|
|
5208
|
-
this.cache.set(
|
|
5254
|
+
this.cache.set(key2, out);
|
|
5209
5255
|
return out;
|
|
5210
5256
|
} finally {
|
|
5211
5257
|
await page.close().catch(() => void 0);
|
|
@@ -5224,6 +5270,8 @@ async function waitForTraceDomHydration(page) {
|
|
|
5224
5270
|
}
|
|
5225
5271
|
|
|
5226
5272
|
// ../workflow-cache/src/optimizer/locator-verifier.ts
|
|
5273
|
+
import path2 from "path";
|
|
5274
|
+
import { pathToFileURL as pathToFileURL2 } from "url";
|
|
5227
5275
|
var RESOLVE_TIMEOUT_MS2 = 5e3;
|
|
5228
5276
|
function identifyingTokens(strategy) {
|
|
5229
5277
|
const tokens = [];
|
|
@@ -5259,7 +5307,7 @@ var LocatorVerifier = class {
|
|
|
5259
5307
|
const tokenPass = classifyStrategyTokens(opts.strategy);
|
|
5260
5308
|
const page = await this.session.page();
|
|
5261
5309
|
try {
|
|
5262
|
-
await page.goto(
|
|
5310
|
+
await page.goto(pathToFileURL2(path2.resolve(opts.domPath)).href, { waitUntil: "load" });
|
|
5263
5311
|
await waitForTraceDomHydration(page);
|
|
5264
5312
|
await page.ariaSnapshot({ mode: "ai" });
|
|
5265
5313
|
const truth = page.locator(`aria-ref=${opts.targetRef}`);
|
|
@@ -5317,6 +5365,148 @@ var LocatorVerifier = class {
|
|
|
5317
5365
|
}
|
|
5318
5366
|
};
|
|
5319
5367
|
|
|
5368
|
+
// ../workflow-cache/src/optimizer/augmentor-verifier.ts
|
|
5369
|
+
import path3 from "path";
|
|
5370
|
+
import { pathToFileURL as pathToFileURL3 } from "url";
|
|
5371
|
+
var logger3 = createLogger({ module: "AugmentorVerifier" });
|
|
5372
|
+
function flatten2(roots) {
|
|
5373
|
+
const out = [];
|
|
5374
|
+
const walk = (n) => {
|
|
5375
|
+
out.push(n);
|
|
5376
|
+
for (const c of n.children) walk(c);
|
|
5377
|
+
};
|
|
5378
|
+
for (const r of roots) walk(r);
|
|
5379
|
+
return out;
|
|
5380
|
+
}
|
|
5381
|
+
var key = (role, name) => `${role}\0${name ?? ""}`;
|
|
5382
|
+
var AugmentorVerifier = class {
|
|
5383
|
+
session;
|
|
5384
|
+
ownsSession;
|
|
5385
|
+
constructor(opts) {
|
|
5386
|
+
this.session = opts?.session ?? new HeadlessDomSession();
|
|
5387
|
+
this.ownsSession = !opts?.session;
|
|
5388
|
+
}
|
|
5389
|
+
async verify(opts) {
|
|
5390
|
+
const { domPath, augmentor } = opts;
|
|
5391
|
+
const issues = [];
|
|
5392
|
+
const page = await this.session.page();
|
|
5393
|
+
try {
|
|
5394
|
+
await page.goto(pathToFileURL3(path3.resolve(domPath)).href, { waitUntil: "load" });
|
|
5395
|
+
await waitForTraceDomHydration(page);
|
|
5396
|
+
const baselineYaml = await captureSubstrateV2(page, logger3);
|
|
5397
|
+
const baselineKeys = new Set(flatten2(parseSnapshot(baselineYaml)).map((e) => key(e.role, e.text)));
|
|
5398
|
+
const pass = await applyCustomAugmentors(page, [augmentor], logger3);
|
|
5399
|
+
const exec = pass.executions[0];
|
|
5400
|
+
const elementsAnnotated = exec?.elementsAnnotated ?? 0;
|
|
5401
|
+
const errored = exec?.errored ?? false;
|
|
5402
|
+
const invariantPassed = exec?.invariantPassed ?? false;
|
|
5403
|
+
const durationMs = exec?.durationMs ?? 0;
|
|
5404
|
+
if (errored) {
|
|
5405
|
+
issues.push(`collector errored in page: ${exec?.errorMessage ?? "unknown"}`);
|
|
5406
|
+
}
|
|
5407
|
+
if (elementsAnnotated === 0) {
|
|
5408
|
+
issues.push("collector annotated 0 elements \u2014 matchSelector found nothing, or every descriptor was rejected");
|
|
5409
|
+
}
|
|
5410
|
+
const augmentedYaml = await captureSubstrateV2(page, logger3);
|
|
5411
|
+
const augmentedEls = flatten2(parseSnapshot(augmentedYaml));
|
|
5412
|
+
const annotatedKeys = new Set(pass.annotations.map((a) => key(a.role, a.name)));
|
|
5413
|
+
const newEls = augmentedEls.filter(
|
|
5414
|
+
(e) => annotatedKeys.has(key(e.role, e.text)) && !baselineKeys.has(key(e.role, e.text))
|
|
5415
|
+
);
|
|
5416
|
+
const baselineAbsent = pass.annotations.length > 0 && newEls.length > 0;
|
|
5417
|
+
if (!baselineAbsent && pass.annotations.length > 0) {
|
|
5418
|
+
issues.push(
|
|
5419
|
+
"annotated (role,name) pairs were already present in the un-augmented snapshot \u2014 this augmentor heals nothing (or the names are not distinctive)"
|
|
5420
|
+
);
|
|
5421
|
+
}
|
|
5422
|
+
const sampleRefs = newEls.slice(0, 8).map((e) => e.ref);
|
|
5423
|
+
const targeting = await Promise.all(
|
|
5424
|
+
sampleRefs.map(async (ref) => {
|
|
5425
|
+
try {
|
|
5426
|
+
const handle = await page.$(`aria-ref=${ref}`);
|
|
5427
|
+
const augId = handle ? await handle.getAttribute("data-augmentor-id").catch(() => null) : null;
|
|
5428
|
+
await handle?.dispose();
|
|
5429
|
+
if (augId !== augmentor.id) {
|
|
5430
|
+
return `ref ${ref} did not resolve to an augmentor-annotated element`;
|
|
5431
|
+
}
|
|
5432
|
+
return null;
|
|
5433
|
+
} catch (err) {
|
|
5434
|
+
return `ref ${ref} could not be resolved: ${err instanceof Error ? err.message : String(err)}`;
|
|
5435
|
+
}
|
|
5436
|
+
})
|
|
5437
|
+
);
|
|
5438
|
+
const targetingIssues = targeting.filter((i) => i !== null);
|
|
5439
|
+
for (const i of targetingIssues) issues.push(i);
|
|
5440
|
+
const refsResolveToTargets = sampleRefs.length > 0 && targetingIssues.length === 0;
|
|
5441
|
+
const cacheCheck = await page.evaluate(() => {
|
|
5442
|
+
const els = Array.from(document.querySelectorAll("[data-augmentor-id]"));
|
|
5443
|
+
let anchorless = 0;
|
|
5444
|
+
const failures = [];
|
|
5445
|
+
els.forEach((el, i) => el.setAttribute("data-aug-verify-idx", String(i)));
|
|
5446
|
+
const anchors = els.map((el) => el.getAttribute("data-augmentor-anchor"));
|
|
5447
|
+
for (const el of els) {
|
|
5448
|
+
el.removeAttribute("role");
|
|
5449
|
+
el.removeAttribute("aria-label");
|
|
5450
|
+
el.removeAttribute("aria-disabled");
|
|
5451
|
+
el.removeAttribute("data-augmentor-id");
|
|
5452
|
+
el.removeAttribute("data-augmentor-anchor");
|
|
5453
|
+
}
|
|
5454
|
+
els.forEach((el, i) => {
|
|
5455
|
+
const anchor = anchors[i];
|
|
5456
|
+
if (!anchor) {
|
|
5457
|
+
anchorless++;
|
|
5458
|
+
return;
|
|
5459
|
+
}
|
|
5460
|
+
if (anchor.length > 500) {
|
|
5461
|
+
failures.push(`stableAnchor #${i} exceeds 500 chars \u2014 too complex to be durable: ${anchor.slice(0, 80)}\u2026`);
|
|
5462
|
+
return;
|
|
5463
|
+
}
|
|
5464
|
+
let matches = [];
|
|
5465
|
+
try {
|
|
5466
|
+
matches = Array.from(document.querySelectorAll(anchor));
|
|
5467
|
+
} catch {
|
|
5468
|
+
failures.push(`stableAnchor #${i} is not a valid selector: ${anchor}`);
|
|
5469
|
+
return;
|
|
5470
|
+
}
|
|
5471
|
+
if (matches.length !== 1) {
|
|
5472
|
+
failures.push(`stableAnchor #${i} matched ${matches.length} elements (want exactly 1): ${anchor}`);
|
|
5473
|
+
} else if (matches[0]?.getAttribute("data-aug-verify-idx") !== String(i)) {
|
|
5474
|
+
failures.push(`stableAnchor #${i} resolved to a different element than its target: ${anchor}`);
|
|
5475
|
+
}
|
|
5476
|
+
});
|
|
5477
|
+
return { anchorless, failures };
|
|
5478
|
+
});
|
|
5479
|
+
for (const f of cacheCheck.failures) issues.push(f);
|
|
5480
|
+
const cacheSafe = cacheCheck.failures.length === 0;
|
|
5481
|
+
if (cacheCheck.anchorless > 0) {
|
|
5482
|
+
issues.push(
|
|
5483
|
+
`${cacheCheck.anchorless} annotated element(s) declared no stableAnchor \u2014 they will be visible to the agent but their locators stay irreducible (workflow-variable / L3 disambiguation)`
|
|
5484
|
+
);
|
|
5485
|
+
}
|
|
5486
|
+
const verified = baselineAbsent && !errored && invariantPassed && elementsAnnotated > 0 && refsResolveToTargets && cacheSafe;
|
|
5487
|
+
return {
|
|
5488
|
+
verified,
|
|
5489
|
+
baselineAbsent,
|
|
5490
|
+
elementsAnnotated,
|
|
5491
|
+
invariantPassed,
|
|
5492
|
+
errored,
|
|
5493
|
+
errorMessage: exec?.errorMessage,
|
|
5494
|
+
sampleRefs,
|
|
5495
|
+
refsResolveToTargets,
|
|
5496
|
+
cacheSafe,
|
|
5497
|
+
anchorlessCount: cacheCheck.anchorless,
|
|
5498
|
+
durationMs,
|
|
5499
|
+
issues
|
|
5500
|
+
};
|
|
5501
|
+
} finally {
|
|
5502
|
+
await page.close().catch(() => void 0);
|
|
5503
|
+
}
|
|
5504
|
+
}
|
|
5505
|
+
async close() {
|
|
5506
|
+
if (this.ownsSession) await this.session.close();
|
|
5507
|
+
}
|
|
5508
|
+
};
|
|
5509
|
+
|
|
5320
5510
|
// ../workflow-cache/src/optimizer/action-synthesizer.ts
|
|
5321
5511
|
var ELEMENT_TARGET_ACTION_TYPES = /* @__PURE__ */ new Set([
|
|
5322
5512
|
"click",
|
|
@@ -5426,7 +5616,7 @@ function buildCacheRecipe(opts) {
|
|
|
5426
5616
|
const bindingKeys = /* @__PURE__ */ new Set();
|
|
5427
5617
|
for (const a of actionsJson) {
|
|
5428
5618
|
if (a.variableKey) bindingKeys.add(`$var.${a.variableKey}`);
|
|
5429
|
-
for (const
|
|
5619
|
+
for (const key2 of Object.values(a.variableBindings ?? {})) bindingKeys.add(`$var.${key2}`);
|
|
5430
5620
|
for (const expr of Object.values(a.macroBindings ?? {})) bindingKeys.add(expr);
|
|
5431
5621
|
}
|
|
5432
5622
|
const missing = opts.requiredTokens.filter((t) => !present.has(t) && !bindingKeys.has(t));
|
|
@@ -5655,13 +5845,13 @@ function resolveMacros(value, ctx) {
|
|
|
5655
5845
|
function resolveMacrosInRecord(values, ctx) {
|
|
5656
5846
|
const resolved = {};
|
|
5657
5847
|
const log = /* @__PURE__ */ new Map();
|
|
5658
|
-
for (const [
|
|
5848
|
+
for (const [key2, value] of Object.entries(values)) {
|
|
5659
5849
|
if (containsMacro(value)) {
|
|
5660
5850
|
const resolvedValue = resolveMacros(value, ctx);
|
|
5661
|
-
resolved[
|
|
5662
|
-
log.set(
|
|
5851
|
+
resolved[key2] = resolvedValue;
|
|
5852
|
+
log.set(key2, { expression: value, resolved: resolvedValue });
|
|
5663
5853
|
} else {
|
|
5664
|
-
resolved[
|
|
5854
|
+
resolved[key2] = value;
|
|
5665
5855
|
}
|
|
5666
5856
|
}
|
|
5667
5857
|
return { resolved, log };
|
|
@@ -5671,12 +5861,13 @@ function resolveNodeInputMacros(inputValues, ctx, workflowState) {
|
|
|
5671
5861
|
const hasMacros = Object.values(inputValues).some((v) => containsMacro(v));
|
|
5672
5862
|
if (!hasMacros) return { resolvedValues: inputValues, macroResolutionLog: void 0 };
|
|
5673
5863
|
const { resolved, log } = resolveMacrosInRecord(inputValues, ctx);
|
|
5674
|
-
for (const [
|
|
5675
|
-
workflowState[`macro:${
|
|
5864
|
+
for (const [key2, { resolved: val }] of log.entries()) {
|
|
5865
|
+
workflowState[`macro:${key2}`] = val;
|
|
5676
5866
|
}
|
|
5677
5867
|
return { resolvedValues: resolved, macroResolutionLog: log };
|
|
5678
5868
|
}
|
|
5679
5869
|
export {
|
|
5870
|
+
AugmentorVerifier,
|
|
5680
5871
|
CACHE_COMPILER_VERSION,
|
|
5681
5872
|
HeadlessDomSession,
|
|
5682
5873
|
LocatorVerifier,
|
|
@@ -5708,6 +5899,7 @@ export {
|
|
|
5708
5899
|
findElementWithAncestors,
|
|
5709
5900
|
findFirstVisibleElement,
|
|
5710
5901
|
generateNodeHash,
|
|
5902
|
+
generateNodeHashV3,
|
|
5711
5903
|
getFrameLocators,
|
|
5712
5904
|
getMacro,
|
|
5713
5905
|
getMacroNames,
|
|
@@ -5732,6 +5924,7 @@ export {
|
|
|
5732
5924
|
resolveMacros,
|
|
5733
5925
|
resolveMacrosInRecord,
|
|
5734
5926
|
resolveNodeInputMacros,
|
|
5927
|
+
resolveSegmentNodeIds,
|
|
5735
5928
|
resolveSpecificIframeSelector,
|
|
5736
5929
|
sanitizeArgsForCache,
|
|
5737
5930
|
segmentTraceByNode,
|
|
@@ -5745,4 +5938,4 @@ export {
|
|
|
5745
5938
|
verifySelectorAgainstRef,
|
|
5746
5939
|
waitForTraceDomHydration
|
|
5747
5940
|
};
|
|
5748
|
-
//# sourceMappingURL=src-
|
|
5941
|
+
//# sourceMappingURL=src-UEOOC425.js.map
|