@yielded/agent-platform-cloudflare 0.1.0-beta.167 → 0.1.0-beta.169
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/{Alarm-B0ODr1NE.mjs → Alarm-BMEAZo3p.mjs} +261 -159
- package/dist/Alarm-BMEAZo3p.mjs.map +1 -0
- package/dist/Alarm.d.mts +29 -36
- package/dist/Alarm.mjs +2 -2
- package/dist/BrowserCredentials-C5IWfi7f.d.mts +91 -0
- package/dist/BrowserCredentials.d.mts +2 -91
- package/dist/BrowserRestCapture.mjs +3 -3
- package/dist/BrowserRestCapture.mjs.map +1 -1
- package/dist/BrowserRestCrawl.mjs +6 -6
- package/dist/BrowserRestCrawl.mjs.map +1 -1
- package/dist/{BrowserSession-RfIzxGCH.mjs → BrowserSession-BfNmyayH.mjs} +5 -5
- package/dist/BrowserSession-BfNmyayH.mjs.map +1 -0
- package/dist/{BrowserSession-B969Xg-2.d.mts → BrowserSession-Bx0V1-6_.d.mts} +6 -3
- package/dist/BrowserSession.d.mts +1 -1
- package/dist/BrowserSession.mjs +2 -2
- package/dist/BrowserUse-Bc2JdLW2.mjs +1528 -0
- package/dist/BrowserUse-Bc2JdLW2.mjs.map +1 -0
- package/dist/BrowserUse.d.mts +83 -0
- package/dist/BrowserUse.mjs +2 -0
- package/dist/CloudflareBindings.d.mts +8 -1
- package/dist/CloudflareBindings.mjs +2 -2
- package/dist/CloudflareBindings.mjs.map +1 -1
- package/dist/{CloudflareBrowser-5an6m-Qb.mjs → CloudflareBrowser-Vt8qTdYW.mjs} +11 -13
- package/dist/CloudflareBrowser-Vt8qTdYW.mjs.map +1 -0
- package/dist/CloudflareBrowser.mjs +1 -1
- package/dist/CloudflareCodeMode.mjs +1 -1
- package/dist/CloudflareCodeMode.mjs.map +1 -1
- package/dist/{CloudflareConfig-qDrRLofL.d.mts → CloudflareConfig-C9MvPbX8.d.mts} +9 -11
- package/dist/CloudflareConfig.d.mts +1 -1
- package/dist/CloudflareConfig.mjs +9 -12
- package/dist/CloudflareConfig.mjs.map +1 -1
- package/dist/CloudflareMemory.d.mts +3 -25
- package/dist/CloudflareMemory.mjs +33 -31
- package/dist/CloudflareMemory.mjs.map +1 -1
- package/dist/CloudflareScheduling.mjs +8 -15
- package/dist/CloudflareScheduling.mjs.map +1 -1
- package/dist/CloudflareSubscriptions.mjs +9 -16
- package/dist/CloudflareSubscriptions.mjs.map +1 -1
- package/dist/CloudflareThreadClient-CLZpN9zU.mjs +588 -0
- package/dist/CloudflareThreadClient-CLZpN9zU.mjs.map +1 -0
- package/dist/CloudflareThreadClient-QsVzLGGZ.d.mts +2033 -0
- package/dist/CloudflareThreadClient.d.mts +2 -1796
- package/dist/CloudflareThreadClient.mjs +2 -382
- package/dist/{InteractiveBrowser-BbG3kGA9.mjs → InteractiveBrowser-LdKzQeLR.mjs} +18 -19
- package/dist/InteractiveBrowser-LdKzQeLR.mjs.map +1 -0
- package/dist/InteractiveBrowser.mjs +1 -1
- package/dist/{ThreadObject-BcfXbzSO.d.mts → ThreadObject-7s5XnlH-.d.mts} +103 -79
- package/dist/{ThreadObject-DHjrnlX4.mjs → ThreadObject-CgXZMlr4.mjs} +265 -66
- package/dist/ThreadObject-CgXZMlr4.mjs.map +1 -0
- package/dist/ThreadObject.d.mts +2 -2
- package/dist/ThreadObject.mjs +2 -3
- package/dist/WakeScheduler.d.mts +6 -5
- package/dist/WakeScheduler.mjs +15 -11
- package/dist/WakeScheduler.mjs.map +1 -1
- package/dist/index.d.mts +7 -6
- package/dist/index.mjs +7 -6
- package/dist/page-function-CmUCcyNP.mjs +11 -0
- package/dist/page-function-CmUCcyNP.mjs.map +1 -0
- package/dist/{prepared-admission-DMX5p9dC.mjs → prepared-admission-B61A7y6O.mjs} +3 -3
- package/dist/{prepared-admission-DMX5p9dC.mjs.map → prepared-admission-B61A7y6O.mjs.map} +1 -1
- package/package.json +1 -1
- package/src/Alarm.ts +512 -279
- package/src/BrowserRestCapture.ts +2 -2
- package/src/BrowserRestCrawl.ts +10 -14
- package/src/BrowserSession.ts +10 -2
- package/src/BrowserUse.ts +1591 -0
- package/src/CloudflareBindings.ts +13 -4
- package/src/CloudflareCodeMode.ts +1 -1
- package/src/CloudflareConfig.ts +9 -12
- package/src/CloudflareMemory.ts +21 -28
- package/src/CloudflareScheduling.ts +7 -15
- package/src/CloudflareSubscriptions.ts +11 -20
- package/src/CloudflareThreadClient.ts +289 -9
- package/src/InteractiveBrowser.ts +325 -323
- package/src/ThreadObject.ts +172 -52
- package/src/WakeScheduler.ts +29 -18
- package/src/index.ts +1 -0
- package/src/internal/browser-dom.ts +886 -0
- package/src/internal/browser-file-selection.ts +8 -1
- package/src/internal/browser-jev-dom.ts +362 -0
- package/src/internal/browser-quick-action.ts +7 -8
- package/src/internal/browser-session-lifecycle.ts +2 -5
- package/src/internal/crypto.ts +41 -0
- package/src/internal/due-queue.ts +5 -69
- package/src/internal/layers.ts +100 -17
- package/src/internal/live-text-protocol.ts +51 -0
- package/src/internal/live-text.ts +256 -0
- package/src/internal/page-function.ts +12 -0
- package/src/internal/prepared-admission.ts +1 -1
- package/src/internal/progress-wait.ts +19 -24
- package/src/internal/transport.ts +1 -1
- package/dist/Alarm-B0ODr1NE.mjs.map +0 -1
- package/dist/BrowserSession-RfIzxGCH.mjs.map +0 -1
- package/dist/CloudflareBrowser-5an6m-Qb.mjs.map +0 -1
- package/dist/CloudflareThreadClient.mjs.map +0 -1
- package/dist/InteractiveBrowser-BbG3kGA9.mjs.map +0 -1
- package/dist/ThreadObject-DHjrnlX4.mjs.map +0 -1
|
@@ -61,6 +61,7 @@ import {
|
|
|
61
61
|
BrowserRunSessionLifecycle,
|
|
62
62
|
type BrowserRunLifecycleOptions,
|
|
63
63
|
} from "./internal/browser-session-lifecycle.ts";
|
|
64
|
+
import { pageFunction } from "./internal/page-function.ts";
|
|
64
65
|
|
|
65
66
|
export {
|
|
66
67
|
BrowserRunCleanupError,
|
|
@@ -776,364 +777,370 @@ const disposeActionHandles = async (handles: ReadonlyArray<{ dispose: () => Prom
|
|
|
776
777
|
};
|
|
777
778
|
|
|
778
779
|
/** Runs entirely in the page realm for both observations and the last bound-element guard. */
|
|
779
|
-
const observePage = (
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
const matches =
|
|
793
|
-
requestedSelector === undefined
|
|
794
|
-
? undefined
|
|
795
|
-
: Reflect.apply(Reflect.get(pageDocument, "querySelectorAll"), pageDocument, [
|
|
796
|
-
requestedSelector,
|
|
797
|
-
]);
|
|
798
|
-
|
|
799
|
-
const selectorMatchCount =
|
|
800
|
-
matches === undefined || matches === null
|
|
801
|
-
? 1
|
|
802
|
-
: Math.min(10_000, Reflect.get(matches, "length"));
|
|
803
|
-
|
|
804
|
-
const element =
|
|
805
|
-
target ??
|
|
806
|
-
(matches === undefined || matches === null
|
|
807
|
-
? Reflect.get(pageDocument, "body")
|
|
808
|
-
: Reflect.get(matches, 0));
|
|
780
|
+
const observePage = pageFunction(
|
|
781
|
+
(
|
|
782
|
+
target: object | undefined,
|
|
783
|
+
requestedSelector: string | undefined,
|
|
784
|
+
maximum: number,
|
|
785
|
+
maximumControls: number,
|
|
786
|
+
input?: {
|
|
787
|
+
readonly mode: "click" | "fill";
|
|
788
|
+
readonly expectedTarget: BrowserExpectedTarget;
|
|
789
|
+
readonly value?: string;
|
|
790
|
+
},
|
|
791
|
+
) => {
|
|
792
|
+
const pageDocument = Reflect.get(globalThis, "document");
|
|
809
793
|
|
|
810
|
-
|
|
811
|
-
|
|
794
|
+
const matches =
|
|
795
|
+
requestedSelector === undefined
|
|
796
|
+
? undefined
|
|
797
|
+
: Reflect.apply(Reflect.get(pageDocument, "querySelectorAll"), pageDocument, [
|
|
798
|
+
requestedSelector,
|
|
799
|
+
]);
|
|
800
|
+
|
|
801
|
+
const selectorMatchCount =
|
|
802
|
+
matches === undefined || matches === null
|
|
803
|
+
? 1
|
|
804
|
+
: Math.min(10_000, Reflect.get(matches, "length"));
|
|
805
|
+
|
|
806
|
+
const element =
|
|
807
|
+
target ??
|
|
808
|
+
(matches === undefined || matches === null
|
|
809
|
+
? Reflect.get(pageDocument, "body")
|
|
810
|
+
: Reflect.get(matches, 0));
|
|
811
|
+
|
|
812
|
+
if (target !== undefined && Reflect.get(target, "isConnected") !== true)
|
|
813
|
+
return { _tag: "MissingElement" };
|
|
812
814
|
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
815
|
+
if (element === null) return { _tag: "MissingElement" };
|
|
816
|
+
if (element === undefined) return { _tag: "MissingElement" };
|
|
817
|
+
const innerText = Reflect.get(element, "innerText");
|
|
818
|
+
const textContent = Reflect.get(element, "textContent");
|
|
817
819
|
|
|
818
|
-
|
|
819
|
-
|
|
820
|
+
const pageText =
|
|
821
|
+
typeof innerText === "string"
|
|
822
|
+
? innerText
|
|
823
|
+
: typeof textContent === "string"
|
|
824
|
+
? textContent
|
|
825
|
+
: "";
|
|
820
826
|
|
|
821
|
-
|
|
822
|
-
|
|
827
|
+
const primaryControlSelector =
|
|
828
|
+
'input,select,textarea,label,button,[role="checkbox"],[role="radio"],[role="option"],[role="switch"],[role="tab"],[role="button"]';
|
|
823
829
|
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
830
|
+
const optionSelector = "select option";
|
|
831
|
+
const secondaryControlSelector = "a[href]";
|
|
832
|
+
const controlSelector = `${primaryControlSelector},${optionSelector},${secondaryControlSelector}`;
|
|
827
833
|
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
834
|
+
const selectorFor = (candidate: object) => {
|
|
835
|
+
const parts: Array<string> = [];
|
|
836
|
+
let current: object | null = candidate;
|
|
831
837
|
|
|
832
|
-
|
|
833
|
-
|
|
838
|
+
while (current !== null && current !== undefined) {
|
|
839
|
+
const tagName = String(Reflect.get(current, "tagName") ?? "").toLowerCase();
|
|
834
840
|
|
|
835
|
-
|
|
836
|
-
|
|
841
|
+
if (tagName === "") break;
|
|
842
|
+
const parent: object | null = Reflect.get(current, "parentElement");
|
|
837
843
|
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
+
if (parent === null) {
|
|
845
|
+
parts.push(tagName);
|
|
846
|
+
break;
|
|
847
|
+
}
|
|
848
|
+
let sibling = Reflect.get(current, "previousElementSibling");
|
|
849
|
+
let index = 1;
|
|
844
850
|
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
851
|
+
while (sibling !== null && sibling !== undefined) {
|
|
852
|
+
if (String(Reflect.get(sibling, "tagName") ?? "").toLowerCase() === tagName) index++;
|
|
853
|
+
sibling = Reflect.get(sibling, "previousElementSibling");
|
|
854
|
+
}
|
|
855
|
+
parts.push(`${tagName}:nth-of-type(${index})`);
|
|
856
|
+
current = parent;
|
|
848
857
|
}
|
|
849
|
-
parts.push(`${tagName}:nth-of-type(${index})`);
|
|
850
|
-
current = parent;
|
|
851
|
-
}
|
|
852
|
-
|
|
853
|
-
return parts.reverse().join(" > ");
|
|
854
|
-
};
|
|
855
|
-
|
|
856
|
-
const visible = (candidate: object) => {
|
|
857
|
-
const hidden = Reflect.get(candidate, "hidden");
|
|
858
|
-
|
|
859
|
-
const ariaHidden = Reflect.apply(Reflect.get(candidate, "getAttribute"), candidate, [
|
|
860
|
-
"aria-hidden",
|
|
861
|
-
]);
|
|
862
858
|
|
|
863
|
-
|
|
859
|
+
return parts.reverse().join(" > ");
|
|
860
|
+
};
|
|
864
861
|
|
|
865
|
-
|
|
866
|
-
hidden
|
|
867
|
-
ariaHidden !== "true" &&
|
|
868
|
-
typeof rects === "object" &&
|
|
869
|
-
rects !== null &&
|
|
870
|
-
Reflect.get(rects, "length") > 0
|
|
871
|
-
);
|
|
872
|
-
};
|
|
862
|
+
const visible = (candidate: object) => {
|
|
863
|
+
const hidden = Reflect.get(candidate, "hidden");
|
|
873
864
|
|
|
874
|
-
|
|
875
|
-
|
|
865
|
+
const ariaHidden = Reflect.apply(Reflect.get(candidate, "getAttribute"), candidate, [
|
|
866
|
+
"aria-hidden",
|
|
867
|
+
]);
|
|
876
868
|
|
|
877
|
-
|
|
878
|
-
const tagName = String(Reflect.get(candidate, "tagName") ?? "").toLowerCase();
|
|
869
|
+
const rects = Reflect.apply(Reflect.get(candidate, "getClientRects"), candidate, []);
|
|
879
870
|
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
871
|
+
return (
|
|
872
|
+
hidden !== true &&
|
|
873
|
+
ariaHidden !== "true" &&
|
|
874
|
+
typeof rects === "object" &&
|
|
875
|
+
rects !== null &&
|
|
876
|
+
Reflect.get(rects, "length") > 0
|
|
877
|
+
);
|
|
878
|
+
};
|
|
886
879
|
|
|
887
|
-
const
|
|
880
|
+
const candidates: Array<object> = [];
|
|
881
|
+
let controlsTruncated = false;
|
|
888
882
|
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
typeof visibilityTarget !== "object" ||
|
|
892
|
-
visibilityTarget === null ||
|
|
893
|
-
!visible(visibilityTarget)
|
|
894
|
-
)
|
|
895
|
-
return;
|
|
896
|
-
candidates.push(candidate);
|
|
897
|
-
if (candidates.length > maximumControls) controlsTruncated = true;
|
|
898
|
-
};
|
|
883
|
+
const consider = (candidate: object) => {
|
|
884
|
+
const tagName = String(Reflect.get(candidate, "tagName") ?? "").toLowerCase();
|
|
899
885
|
|
|
900
|
-
|
|
886
|
+
// Collapsed native options have no client rects. Their owning
|
|
887
|
+
// select determines visibility; observe text/selection, never value.
|
|
888
|
+
const visibilityTarget =
|
|
889
|
+
tagName === "option"
|
|
890
|
+
? Reflect.apply(Reflect.get(candidate, "closest"), candidate, ["select"])
|
|
891
|
+
: candidate;
|
|
901
892
|
|
|
902
|
-
|
|
903
|
-
typeof elementMatches === "function" &&
|
|
904
|
-
Reflect.apply(elementMatches, element, [controlSelector])
|
|
905
|
-
) {
|
|
906
|
-
consider(element);
|
|
907
|
-
}
|
|
893
|
+
const actionable = tagName !== "label" || Reflect.get(candidate, "control") !== null;
|
|
908
894
|
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
895
|
+
if (
|
|
896
|
+
!actionable ||
|
|
897
|
+
typeof visibilityTarget !== "object" ||
|
|
898
|
+
visibilityTarget === null ||
|
|
899
|
+
!visible(visibilityTarget)
|
|
900
|
+
)
|
|
901
|
+
return;
|
|
902
|
+
candidates.push(candidate);
|
|
903
|
+
if (candidates.length > maximumControls) controlsTruncated = true;
|
|
904
|
+
};
|
|
913
905
|
|
|
914
|
-
|
|
915
|
-
const descendantCount = Reflect.get(descendants, "length");
|
|
906
|
+
const elementMatches = Reflect.get(element, "matches");
|
|
916
907
|
|
|
917
|
-
|
|
918
|
-
|
|
908
|
+
if (
|
|
909
|
+
typeof elementMatches === "function" &&
|
|
910
|
+
Reflect.apply(elementMatches, element, [controlSelector])
|
|
911
|
+
) {
|
|
912
|
+
consider(element);
|
|
919
913
|
}
|
|
920
|
-
};
|
|
921
914
|
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
915
|
+
const considerSelector = (candidateSelector: string) => {
|
|
916
|
+
const descendants = Reflect.apply(Reflect.get(element, "querySelectorAll"), element, [
|
|
917
|
+
candidateSelector,
|
|
918
|
+
]);
|
|
925
919
|
|
|
926
|
-
|
|
927
|
-
|
|
920
|
+
if (typeof descendants !== "object" || descendants === null) return;
|
|
921
|
+
const descendantCount = Reflect.get(descendants, "length");
|
|
928
922
|
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
documentId: crypto.getRandomValues(new Uint32Array(4)).join("-"),
|
|
933
|
-
nodes: new WeakMap<object, string>(),
|
|
923
|
+
for (let index = 0; index < descendantCount && !controlsTruncated; index++) {
|
|
924
|
+
consider(Reflect.get(descendants, index));
|
|
925
|
+
}
|
|
934
926
|
};
|
|
935
|
-
Reflect.set(globalThis, identityKey, identity);
|
|
936
|
-
}
|
|
937
927
|
|
|
938
|
-
|
|
939
|
-
|
|
928
|
+
considerSelector(primaryControlSelector);
|
|
929
|
+
if (!controlsTruncated) considerSelector(optionSelector);
|
|
930
|
+
if (!controlsTruncated) considerSelector(secondaryControlSelector);
|
|
931
|
+
|
|
932
|
+
const identityKey = Symbol.for("@effect-agent/browser-observation");
|
|
933
|
+
let identity = Reflect.get(globalThis, identityKey);
|
|
940
934
|
|
|
941
|
-
if (
|
|
942
|
-
|
|
943
|
-
|
|
935
|
+
if (identity === undefined || identity.document !== pageDocument) {
|
|
936
|
+
identity = {
|
|
937
|
+
document: pageDocument,
|
|
938
|
+
documentId: crypto.getRandomValues(new Uint32Array(4)).join("-"),
|
|
939
|
+
nodes: new WeakMap<object, string>(),
|
|
940
|
+
};
|
|
941
|
+
Reflect.set(globalThis, identityKey, identity);
|
|
944
942
|
}
|
|
945
|
-
const associated = Reflect.get(candidate, "control") ?? candidate;
|
|
946
|
-
const tagName = String(Reflect.get(candidate, "tagName") ?? "").toLowerCase();
|
|
947
|
-
const inputType = String(Reflect.get(associated, "type") ?? "").toLowerCase();
|
|
948
943
|
|
|
949
|
-
const
|
|
950
|
-
|
|
951
|
-
).toLowerCase();
|
|
944
|
+
const controls = candidates.slice(0, maximumControls).map((candidate) => {
|
|
945
|
+
let nodeId = identity.nodes.get(candidate);
|
|
952
946
|
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
947
|
+
if (nodeId === undefined) {
|
|
948
|
+
nodeId = crypto.getRandomValues(new Uint32Array(4)).join("-");
|
|
949
|
+
identity.nodes.set(candidate, nodeId);
|
|
950
|
+
}
|
|
951
|
+
const associated = Reflect.get(candidate, "control") ?? candidate;
|
|
952
|
+
const tagName = String(Reflect.get(candidate, "tagName") ?? "").toLowerCase();
|
|
953
|
+
const inputType = String(Reflect.get(associated, "type") ?? "").toLowerCase();
|
|
956
954
|
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
: Reflect.get(candidate, tagName === "option" ? "label" : "innerText");
|
|
961
|
-
|
|
962
|
-
const associatedLabels = Reflect.get(associated, "labels");
|
|
963
|
-
|
|
964
|
-
const associatedLabel =
|
|
965
|
-
associatedLabels !== undefined &&
|
|
966
|
-
associatedLabels !== null &&
|
|
967
|
-
Reflect.get(associatedLabels, "length") > 0
|
|
968
|
-
? Reflect.get(Reflect.get(associatedLabels, 0), "innerText")
|
|
969
|
-
: undefined;
|
|
970
|
-
|
|
971
|
-
const label = String(
|
|
972
|
-
typeof ariaLabel === "string" && ariaLabel !== ""
|
|
973
|
-
? ariaLabel
|
|
974
|
-
: typeof candidateText === "string" && candidateText !== ""
|
|
975
|
-
? candidateText
|
|
976
|
-
: (associatedLabel ?? ""),
|
|
977
|
-
)
|
|
978
|
-
.replace(/\s+/g, " ")
|
|
979
|
-
.trim()
|
|
980
|
-
.slice(0, 200);
|
|
955
|
+
const role = String(
|
|
956
|
+
Reflect.apply(Reflect.get(candidate, "getAttribute"), candidate, ["role"]) ?? "",
|
|
957
|
+
).toLowerCase();
|
|
981
958
|
|
|
982
|
-
|
|
959
|
+
const ariaLabel = Reflect.apply(Reflect.get(candidate, "getAttribute"), candidate, [
|
|
960
|
+
"aria-label",
|
|
961
|
+
]);
|
|
983
962
|
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
963
|
+
const candidateText =
|
|
964
|
+
tagName === "textarea" || tagName === "input" || tagName === "select"
|
|
965
|
+
? undefined
|
|
966
|
+
: Reflect.get(candidate, tagName === "option" ? "label" : "innerText");
|
|
967
|
+
|
|
968
|
+
const associatedLabels = Reflect.get(associated, "labels");
|
|
969
|
+
|
|
970
|
+
const associatedLabel =
|
|
971
|
+
associatedLabels !== undefined &&
|
|
972
|
+
associatedLabels !== null &&
|
|
973
|
+
Reflect.get(associatedLabels, "length") > 0
|
|
974
|
+
? Reflect.get(Reflect.get(associatedLabels, 0), "innerText")
|
|
975
|
+
: undefined;
|
|
976
|
+
|
|
977
|
+
const label = String(
|
|
978
|
+
typeof ariaLabel === "string" && ariaLabel !== ""
|
|
979
|
+
? ariaLabel
|
|
980
|
+
: typeof candidateText === "string" && candidateText !== ""
|
|
981
|
+
? candidateText
|
|
982
|
+
: (associatedLabel ?? ""),
|
|
983
|
+
)
|
|
984
|
+
.replace(/\s+/g, " ")
|
|
985
|
+
.trim()
|
|
986
|
+
.slice(0, 200);
|
|
988
987
|
|
|
989
|
-
|
|
990
|
-
const required = Reflect.get(associated, "required");
|
|
991
|
-
const validity = Reflect.get(associated, "validity");
|
|
992
|
-
const form = Reflect.get(associated, "form");
|
|
988
|
+
const checked = Reflect.get(associated, "checked");
|
|
993
989
|
|
|
994
|
-
|
|
995
|
-
|
|
990
|
+
const selected =
|
|
991
|
+
tagName === "select"
|
|
992
|
+
? Reflect.get(associated, "selectedIndex") >= 0
|
|
993
|
+
: Reflect.get(associated, "selected");
|
|
996
994
|
|
|
997
|
-
|
|
998
|
-
"
|
|
999
|
-
|
|
995
|
+
const disabled = Reflect.get(associated, "disabled");
|
|
996
|
+
const required = Reflect.get(associated, "required");
|
|
997
|
+
const validity = Reflect.get(associated, "validity");
|
|
998
|
+
const form = Reflect.get(associated, "form");
|
|
1000
999
|
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
]);
|
|
1000
|
+
const formMatches =
|
|
1001
|
+
form === null || form === undefined ? undefined : Reflect.get(form, "matches");
|
|
1004
1002
|
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1003
|
+
const ariaChecked = Reflect.apply(Reflect.get(candidate, "getAttribute"), candidate, [
|
|
1004
|
+
"aria-checked",
|
|
1005
|
+
]);
|
|
1008
1006
|
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
selector: selectorFor(candidate),
|
|
1013
|
-
kind: (tagName === "label"
|
|
1014
|
-
? `label:${inputType || "control"}`
|
|
1015
|
-
: tagName === "input"
|
|
1016
|
-
? `input:${inputType || "text"}`
|
|
1017
|
-
: role !== ""
|
|
1018
|
-
? `role:${role}`
|
|
1019
|
-
: tagName
|
|
1020
|
-
).slice(0, 128),
|
|
1021
|
-
...(label === "" ? {} : { label }),
|
|
1022
|
-
...(typeof checked === "boolean"
|
|
1023
|
-
? { checked }
|
|
1024
|
-
: ariaChecked === "true" || ariaChecked === "false"
|
|
1025
|
-
? { checked: ariaChecked === "true" }
|
|
1026
|
-
: {}),
|
|
1027
|
-
...(typeof selected === "boolean"
|
|
1028
|
-
? { selected }
|
|
1029
|
-
: ariaSelected === "true" || ariaSelected === "false"
|
|
1030
|
-
? { selected: ariaSelected === "true" }
|
|
1031
|
-
: {}),
|
|
1032
|
-
...(typeof disabled === "boolean"
|
|
1033
|
-
? { disabled }
|
|
1034
|
-
: ariaDisabled === "true" || ariaDisabled === "false"
|
|
1035
|
-
? { disabled: ariaDisabled === "true" }
|
|
1036
|
-
: {}),
|
|
1037
|
-
...(typeof required === "boolean" ? { required } : {}),
|
|
1038
|
-
...(validity !== undefined && typeof Reflect.get(validity, "valid") === "boolean"
|
|
1039
|
-
? { valid: Reflect.get(validity, "valid") }
|
|
1040
|
-
: {}),
|
|
1041
|
-
...(typeof formMatches === "function"
|
|
1042
|
-
? { formValid: Reflect.apply(formMatches, form, [":valid"]) }
|
|
1043
|
-
: {}),
|
|
1044
|
-
};
|
|
1045
|
-
});
|
|
1007
|
+
const ariaSelected = Reflect.apply(Reflect.get(candidate, "getAttribute"), candidate, [
|
|
1008
|
+
"aria-selected",
|
|
1009
|
+
]);
|
|
1046
1010
|
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
const fields = [
|
|
1052
|
-
"kind",
|
|
1053
|
-
"inputType",
|
|
1054
|
-
"label",
|
|
1055
|
-
"checked",
|
|
1056
|
-
"selected",
|
|
1057
|
-
"disabled",
|
|
1058
|
-
"required",
|
|
1059
|
-
"valid",
|
|
1060
|
-
"formValid",
|
|
1061
|
-
] as const;
|
|
1011
|
+
const ariaDisabled = Reflect.apply(Reflect.get(candidate, "getAttribute"), candidate, [
|
|
1012
|
+
"aria-disabled",
|
|
1013
|
+
]);
|
|
1062
1014
|
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1015
|
+
return {
|
|
1016
|
+
nodeId,
|
|
1017
|
+
...(inputType === "" ? {} : { inputType: inputType.slice(0, 64) }),
|
|
1018
|
+
selector: selectorFor(candidate),
|
|
1019
|
+
kind: (tagName === "label"
|
|
1020
|
+
? `label:${inputType || "control"}`
|
|
1021
|
+
: tagName === "input"
|
|
1022
|
+
? `input:${inputType || "text"}`
|
|
1023
|
+
: role !== ""
|
|
1024
|
+
? `role:${role}`
|
|
1025
|
+
: tagName
|
|
1026
|
+
).slice(0, 128),
|
|
1027
|
+
...(label === "" ? {} : { label }),
|
|
1028
|
+
...(typeof checked === "boolean"
|
|
1029
|
+
? { checked }
|
|
1030
|
+
: ariaChecked === "true" || ariaChecked === "false"
|
|
1031
|
+
? { checked: ariaChecked === "true" }
|
|
1032
|
+
: {}),
|
|
1033
|
+
...(typeof selected === "boolean"
|
|
1034
|
+
? { selected }
|
|
1035
|
+
: ariaSelected === "true" || ariaSelected === "false"
|
|
1036
|
+
? { selected: ariaSelected === "true" }
|
|
1037
|
+
: {}),
|
|
1038
|
+
...(typeof disabled === "boolean"
|
|
1039
|
+
? { disabled }
|
|
1040
|
+
: ariaDisabled === "true" || ariaDisabled === "false"
|
|
1041
|
+
? { disabled: ariaDisabled === "true" }
|
|
1042
|
+
: {}),
|
|
1043
|
+
...(typeof required === "boolean" ? { required } : {}),
|
|
1044
|
+
...(validity !== undefined && typeof Reflect.get(validity, "valid") === "boolean"
|
|
1045
|
+
? { valid: Reflect.get(validity, "valid") }
|
|
1046
|
+
: {}),
|
|
1047
|
+
...(typeof formMatches === "function"
|
|
1048
|
+
? { formValid: Reflect.apply(formMatches, form, [":valid"]) }
|
|
1049
|
+
: {}),
|
|
1050
|
+
};
|
|
1051
|
+
});
|
|
1075
1052
|
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1053
|
+
if (input !== undefined) {
|
|
1054
|
+
const expected = input.expectedTarget;
|
|
1055
|
+
const control = controls.find((candidate) => candidate.nodeId === expected.nodeId);
|
|
1056
|
+
|
|
1057
|
+
const fields = [
|
|
1058
|
+
"kind",
|
|
1059
|
+
"inputType",
|
|
1060
|
+
"label",
|
|
1061
|
+
"checked",
|
|
1062
|
+
"selected",
|
|
1063
|
+
"disabled",
|
|
1064
|
+
"required",
|
|
1065
|
+
"valid",
|
|
1066
|
+
"formValid",
|
|
1067
|
+
] as const;
|
|
1085
1068
|
|
|
1086
1069
|
if (
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1070
|
+
target === undefined ||
|
|
1071
|
+
identity.documentId !== expected.documentId ||
|
|
1072
|
+
identity.nodes.get(target) !== expected.nodeId ||
|
|
1073
|
+
control === undefined ||
|
|
1074
|
+
(expected.state !== undefined &&
|
|
1075
|
+
fields.some((field) => control[field] !== expected.state?.[field])) ||
|
|
1076
|
+
Reflect.get(target, "isConnected") !== true
|
|
1090
1077
|
)
|
|
1091
1078
|
return { _tag: "MissingElement" };
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
let setValue: ((value: string) => void) | undefined;
|
|
1102
|
-
|
|
1103
|
-
while (prototype !== null) {
|
|
1104
|
-
const setter = Reflect.getOwnPropertyDescriptor(prototype, "value")?.set;
|
|
1105
|
-
|
|
1106
|
-
if (typeof setter === "function") {
|
|
1107
|
-
setValue = setter;
|
|
1108
|
-
break;
|
|
1079
|
+
if (expected.scopeSelector !== undefined) {
|
|
1080
|
+
let roots;
|
|
1081
|
+
|
|
1082
|
+
try {
|
|
1083
|
+
roots = Reflect.apply(Reflect.get(pageDocument, "querySelectorAll"), pageDocument, [
|
|
1084
|
+
expected.scopeSelector,
|
|
1085
|
+
]);
|
|
1086
|
+
} catch {
|
|
1087
|
+
return { _tag: "MissingElement" };
|
|
1109
1088
|
}
|
|
1110
|
-
|
|
1089
|
+
if (typeof roots !== "object" || roots === null) return { _tag: "MissingElement" };
|
|
1090
|
+
const root = Reflect.get(roots, 0);
|
|
1091
|
+
|
|
1092
|
+
if (
|
|
1093
|
+
Reflect.get(roots, "length") !== 1 ||
|
|
1094
|
+
root === undefined ||
|
|
1095
|
+
!Reflect.apply(Reflect.get(root, "contains"), root, [target])
|
|
1096
|
+
)
|
|
1097
|
+
return { _tag: "MissingElement" };
|
|
1111
1098
|
}
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1099
|
+
// Validation and dispatch share one page JS task. No coordinate lookup, selector
|
|
1100
|
+
// re-resolution, or asynchronous boundary can select a replacement node.
|
|
1101
|
+
if (input.mode === "click") {
|
|
1102
|
+
const prototype = Reflect.get(Reflect.get(globalThis, "HTMLElement"), "prototype");
|
|
1103
|
+
|
|
1104
|
+
Reflect.apply(Reflect.get(prototype, "click"), target, []);
|
|
1105
|
+
} else {
|
|
1106
|
+
let prototype = Reflect.getPrototypeOf(target);
|
|
1107
|
+
let setValue: ((value: string) => void) | undefined;
|
|
1108
|
+
|
|
1109
|
+
while (prototype !== null) {
|
|
1110
|
+
const setter = Reflect.getOwnPropertyDescriptor(prototype, "value")?.set;
|
|
1111
|
+
|
|
1112
|
+
if (typeof setter === "function") {
|
|
1113
|
+
setValue = setter;
|
|
1114
|
+
break;
|
|
1115
|
+
}
|
|
1116
|
+
prototype = Reflect.getPrototypeOf(prototype);
|
|
1117
|
+
}
|
|
1118
|
+
if (setValue === undefined || input.value === undefined) return { _tag: "MissingElement" };
|
|
1119
|
+
Reflect.apply(setValue, target, [input.value]);
|
|
1120
|
+
const dispatchEvent = Reflect.get(target, "dispatchEvent");
|
|
1115
1121
|
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1122
|
+
Reflect.apply(dispatchEvent, target, [new Event("input", { bubbles: true })]);
|
|
1123
|
+
Reflect.apply(dispatchEvent, target, [new Event("change", { bubbles: true })]);
|
|
1124
|
+
}
|
|
1119
1125
|
|
|
1120
|
-
|
|
1121
|
-
|
|
1126
|
+
return { _tag: "Text", text: "" };
|
|
1127
|
+
}
|
|
1122
1128
|
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1129
|
+
// JSON is the bounded wire representation of this existing text result.
|
|
1130
|
+
// eslint-disable-next-line no-restricted-properties
|
|
1131
|
+
const text = JSON.stringify({
|
|
1132
|
+
documentId: identity.documentId,
|
|
1133
|
+
pageText,
|
|
1134
|
+
selectorMatchCount,
|
|
1135
|
+
controls,
|
|
1136
|
+
controlsTruncated,
|
|
1137
|
+
});
|
|
1132
1138
|
|
|
1133
|
-
|
|
1139
|
+
const observed = new TextEncoder().encode(text).byteLength;
|
|
1134
1140
|
|
|
1135
|
-
|
|
1136
|
-
}
|
|
1141
|
+
return observed > maximum ? { _tag: "OverLimit", observed } : { _tag: "Text", text };
|
|
1142
|
+
},
|
|
1143
|
+
);
|
|
1137
1144
|
|
|
1138
1145
|
const runObservedPageAction = async (
|
|
1139
1146
|
page: Page,
|
|
@@ -1546,7 +1553,7 @@ const inputMayStillRun = (cause: unknown): boolean =>
|
|
|
1546
1553
|
(cause instanceof Error && cause.name === "TimeoutError") ||
|
|
1547
1554
|
(cause instanceof BrowserRunFailure && cause.reason === "timeout");
|
|
1548
1555
|
|
|
1549
|
-
const snapshotPolicy = Effect.
|
|
1556
|
+
const snapshotPolicy = Effect.fnUntraced(function* (
|
|
1550
1557
|
input: InteractiveBrowserPolicy,
|
|
1551
1558
|
): Effect.fn.Return<
|
|
1552
1559
|
InteractiveBrowserPolicySnapshot,
|
|
@@ -1635,7 +1642,7 @@ const closeWithWarning = (close: () => Promise<void>, warning: string): Effect.E
|
|
|
1635
1642
|
),
|
|
1636
1643
|
);
|
|
1637
1644
|
|
|
1638
|
-
const deadlineError = Effect.
|
|
1645
|
+
const deadlineError = Effect.fnUntraced(function* (
|
|
1639
1646
|
policy: InteractiveBrowserPolicySnapshot,
|
|
1640
1647
|
startedAt: number,
|
|
1641
1648
|
) {
|
|
@@ -1650,7 +1657,7 @@ const deadlineError = Effect.fn("BrowserRunInteractive.deadlineError")(function*
|
|
|
1650
1657
|
});
|
|
1651
1658
|
});
|
|
1652
1659
|
|
|
1653
|
-
const withinDeadline = Effect.
|
|
1660
|
+
const withinDeadline = Effect.fnUntraced(function* <A, E, R>(
|
|
1654
1661
|
effect: Effect.Effect<A, E, R>,
|
|
1655
1662
|
policy: InteractiveBrowserPolicySnapshot,
|
|
1656
1663
|
startedAt: number,
|
|
@@ -1758,7 +1765,7 @@ const awaitPendingRequests = (state: HandleState): Effect.Effect<void> =>
|
|
|
1758
1765
|
);
|
|
1759
1766
|
});
|
|
1760
1767
|
|
|
1761
|
-
const decodeNavigationResult = Effect.
|
|
1768
|
+
const decodeNavigationResult = Effect.fnUntraced(function* (
|
|
1762
1769
|
page: BrowserRunInteractivePage,
|
|
1763
1770
|
policy: InteractiveBrowserPolicySnapshot,
|
|
1764
1771
|
) {
|
|
@@ -1782,7 +1789,7 @@ const decodeNavigationResult = Effect.fn("BrowserRunInteractive.decodeNavigation
|
|
|
1782
1789
|
return result;
|
|
1783
1790
|
});
|
|
1784
1791
|
|
|
1785
|
-
const decodeActionResult = Effect.
|
|
1792
|
+
const decodeActionResult = Effect.fnUntraced(function* (
|
|
1786
1793
|
page: BrowserRunInteractivePage,
|
|
1787
1794
|
policy: InteractiveBrowserPolicySnapshot,
|
|
1788
1795
|
) {
|
|
@@ -1846,7 +1853,7 @@ const makeRequestListener =
|
|
|
1846
1853
|
state.pendingRequests.add(observed);
|
|
1847
1854
|
};
|
|
1848
1855
|
|
|
1849
|
-
const makeHandle = Effect.
|
|
1856
|
+
const makeHandle = Effect.fnUntraced(function* (
|
|
1850
1857
|
page: BrowserRunInteractivePage,
|
|
1851
1858
|
policy: InteractiveBrowserPolicySnapshot,
|
|
1852
1859
|
startedAt: number,
|
|
@@ -1980,15 +1987,12 @@ const makeHandle = Effect.fn("BrowserRunInteractive.makeHandle")(function* (
|
|
|
1980
1987
|
),
|
|
1981
1988
|
);
|
|
1982
1989
|
|
|
1983
|
-
const decodeActionObservation =
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
);
|
|
1990
|
-
},
|
|
1991
|
-
);
|
|
1990
|
+
const decodeActionObservation = (raw: unknown) =>
|
|
1991
|
+
Schema.decodeUnknownEffect(ActionObservation)(raw).pipe(
|
|
1992
|
+
Effect.mapError((cause) =>
|
|
1993
|
+
protocolError("The browser returned a malformed action observation", cause),
|
|
1994
|
+
),
|
|
1995
|
+
);
|
|
1992
1996
|
|
|
1993
1997
|
const logActionObservation = (
|
|
1994
1998
|
operation: "fill" | "click" | "select-file",
|
|
@@ -2365,7 +2369,7 @@ const makeHandle = Effect.fn("BrowserRunInteractive.makeHandle")(function* (
|
|
|
2365
2369
|
return { handle, run };
|
|
2366
2370
|
});
|
|
2367
2371
|
|
|
2368
|
-
const remainingMillis = Effect.
|
|
2372
|
+
const remainingMillis = Effect.fnUntraced(function* (
|
|
2369
2373
|
policy: InteractiveBrowserPolicySnapshot,
|
|
2370
2374
|
startedAt: number,
|
|
2371
2375
|
) {
|
|
@@ -2496,7 +2500,7 @@ const makeHostService = (
|
|
|
2496
2500
|
),
|
|
2497
2501
|
);
|
|
2498
2502
|
|
|
2499
|
-
const terminate = Effect.
|
|
2503
|
+
const terminate = Effect.fnUntraced(function* (
|
|
2500
2504
|
sessionId: Redacted.Redacted<string>,
|
|
2501
2505
|
entries: ReadonlyArray<CloseEntry>,
|
|
2502
2506
|
) {
|
|
@@ -2541,9 +2545,7 @@ const makeHostService = (
|
|
|
2541
2545
|
);
|
|
2542
2546
|
});
|
|
2543
2547
|
|
|
2544
|
-
const closeAcquired = Effect.
|
|
2545
|
-
browser: BrowserRunInteractiveBrowser,
|
|
2546
|
-
) {
|
|
2548
|
+
const closeAcquired = Effect.fnUntraced(function* (browser: BrowserRunInteractiveBrowser) {
|
|
2547
2549
|
const sessionId = yield* Effect.try({
|
|
2548
2550
|
try: browser.sessionId,
|
|
2549
2551
|
catch: (cause) => actionError("close", cause),
|
|
@@ -2560,7 +2562,7 @@ const makeHostService = (
|
|
|
2560
2562
|
]);
|
|
2561
2563
|
});
|
|
2562
2564
|
|
|
2563
|
-
const acquire = Effect.
|
|
2565
|
+
const acquire = Effect.fnUntraced(function* (
|
|
2564
2566
|
policy: InteractiveBrowserPolicy,
|
|
2565
2567
|
resume?: BrowserRunInteractiveCheckpoint,
|
|
2566
2568
|
pendingInput = false,
|