@opengeni/react 1.4.0 → 1.4.4
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/README.md +8 -0
- package/dist/accounts.js +2 -0
- package/dist/accounts.js.map +1 -1
- package/dist/artifacts-document.js +5 -4
- package/dist/artifacts-presentation.js +5 -4
- package/dist/artifacts-spreadsheet.js +4 -3
- package/dist/artifacts.js +14 -13
- package/dist/artifacts.js.map +1 -1
- package/dist/browser-viewer-5EEAS3IU.js +17 -0
- package/dist/chat-interactive-block-ZFHOKTMS.js +12 -0
- package/dist/{chunk-WEHMPOXK.js → chunk-2DDJ6YH6.js} +3 -1
- package/dist/{chunk-WEHMPOXK.js.map → chunk-2DDJ6YH6.js.map} +1 -1
- package/dist/{chunk-C5X5AJXK.js → chunk-2HVLQ26H.js} +5 -4
- package/dist/{chunk-C5X5AJXK.js.map → chunk-2HVLQ26H.js.map} +1 -1
- package/dist/{chunk-HDJWDK7W.js → chunk-2OQA3CPB.js} +300 -166
- package/dist/{chunk-HDJWDK7W.js.map → chunk-2OQA3CPB.js.map} +1 -1
- package/dist/{chunk-A4UJB2MM.js → chunk-32CGLXW2.js} +4 -3
- package/dist/{chunk-A4UJB2MM.js.map → chunk-32CGLXW2.js.map} +1 -1
- package/dist/{chunk-5CVXZA3Y.js → chunk-45NUOSXQ.js} +3 -2
- package/dist/{chunk-5CVXZA3Y.js.map → chunk-45NUOSXQ.js.map} +1 -1
- package/dist/{chunk-WUISZ3WU.js → chunk-53KJBGPZ.js} +5 -4
- package/dist/{chunk-WUISZ3WU.js.map → chunk-53KJBGPZ.js.map} +1 -1
- package/dist/{chunk-MBMPHOMA.js → chunk-55DXD22O.js} +3 -2
- package/dist/{chunk-MBMPHOMA.js.map → chunk-55DXD22O.js.map} +1 -1
- package/dist/{chunk-JT4JW7BC.js → chunk-5I4VRWBB.js} +3 -1
- package/dist/{chunk-JT4JW7BC.js.map → chunk-5I4VRWBB.js.map} +1 -1
- package/dist/{chunk-UK4TINKT.js → chunk-B27E3V37.js} +3 -1
- package/dist/{chunk-UK4TINKT.js.map → chunk-B27E3V37.js.map} +1 -1
- package/dist/{chunk-J6DBS4T3.js → chunk-BNKV5ZLF.js} +5 -4
- package/dist/{chunk-J6DBS4T3.js.map → chunk-BNKV5ZLF.js.map} +1 -1
- package/dist/{chunk-YM2DE7BQ.js → chunk-C5BF4L26.js} +13 -12
- package/dist/{chunk-YM2DE7BQ.js.map → chunk-C5BF4L26.js.map} +1 -1
- package/dist/{chunk-YBXQDQFX.js → chunk-C7CMD56T.js} +6 -5
- package/dist/{chunk-YBXQDQFX.js.map → chunk-C7CMD56T.js.map} +1 -1
- package/dist/{chunk-UGLEYEMP.js → chunk-CM7LVUKC.js} +3 -1
- package/dist/{chunk-UGLEYEMP.js.map → chunk-CM7LVUKC.js.map} +1 -1
- package/dist/{chunk-JVYQRRC4.js → chunk-CVYCLFMH.js} +3 -1
- package/dist/{chunk-JVYQRRC4.js.map → chunk-CVYCLFMH.js.map} +1 -1
- package/dist/{chunk-LJ2UTJJE.js → chunk-EAOSEIXB.js} +182 -97
- package/dist/chunk-EAOSEIXB.js.map +1 -0
- package/dist/{chunk-Y2PRMYLC.js → chunk-G3U2A6GS.js} +3 -2
- package/dist/{chunk-Y2PRMYLC.js.map → chunk-G3U2A6GS.js.map} +1 -1
- package/dist/{chunk-WZMYFJD3.js → chunk-G6YRCIYJ.js} +16 -7
- package/dist/{chunk-WZMYFJD3.js.map → chunk-G6YRCIYJ.js.map} +1 -1
- package/dist/{chunk-B3V6TG77.js → chunk-GC3PH6N7.js} +3 -1
- package/dist/{chunk-B3V6TG77.js.map → chunk-GC3PH6N7.js.map} +1 -1
- package/dist/{chunk-CJUO7J5Z.js → chunk-HXYOSSQO.js} +3 -2
- package/dist/{chunk-CJUO7J5Z.js.map → chunk-HXYOSSQO.js.map} +1 -1
- package/dist/{chunk-GYVRFZDY.js → chunk-I6OY3MWC.js} +310 -115
- package/dist/chunk-I6OY3MWC.js.map +1 -0
- package/dist/{chunk-BRM6FVZA.js → chunk-IEE7WCLN.js} +4 -3
- package/dist/{chunk-BRM6FVZA.js.map → chunk-IEE7WCLN.js.map} +1 -1
- package/dist/{chunk-DYWBUX5Q.js → chunk-IMSUVYQB.js} +6 -5
- package/dist/{chunk-DYWBUX5Q.js.map → chunk-IMSUVYQB.js.map} +1 -1
- package/dist/{chunk-LN6TCXD3.js → chunk-IUHHPMAX.js} +184 -48
- package/dist/chunk-IUHHPMAX.js.map +1 -0
- package/dist/{chunk-SGKD2OCN.js → chunk-IYQCWGU5.js} +6 -5
- package/dist/{chunk-SGKD2OCN.js.map → chunk-IYQCWGU5.js.map} +1 -1
- package/dist/{chunk-J2QWVSQY.js → chunk-JH7V627O.js} +8 -7
- package/dist/{chunk-J2QWVSQY.js.map → chunk-JH7V627O.js.map} +1 -1
- package/dist/{chunk-EESD3PY3.js → chunk-JHTIMBOL.js} +6 -5
- package/dist/{chunk-EESD3PY3.js.map → chunk-JHTIMBOL.js.map} +1 -1
- package/dist/{chunk-LNIRAOA3.js → chunk-L2J3PU7A.js} +7 -6
- package/dist/{chunk-LNIRAOA3.js.map → chunk-L2J3PU7A.js.map} +1 -1
- package/dist/{chunk-ZYRGEKWS.js → chunk-LJUMYUBO.js} +3 -1
- package/dist/{chunk-ZYRGEKWS.js.map → chunk-LJUMYUBO.js.map} +1 -1
- package/dist/{chunk-4RVYOY4O.js → chunk-LSW2OJVV.js} +4 -3
- package/dist/{chunk-4RVYOY4O.js.map → chunk-LSW2OJVV.js.map} +1 -1
- package/dist/{chunk-UTRTG6LH.js → chunk-LVS3MH5T.js} +3 -1
- package/dist/{chunk-UTRTG6LH.js.map → chunk-LVS3MH5T.js.map} +1 -1
- package/dist/chunk-M357MHH3.js +2 -0
- package/dist/{chunk-WRHIZYZF.js → chunk-MEQM4LI3.js} +6 -5
- package/dist/{chunk-WRHIZYZF.js.map → chunk-MEQM4LI3.js.map} +1 -1
- package/dist/chunk-NX4ADH73.js +14 -0
- package/dist/chunk-NX4ADH73.js.map +1 -0
- package/dist/{chunk-XCHWDJ22.js → chunk-OGTTUYNT.js} +3 -1
- package/dist/{chunk-XCHWDJ22.js.map → chunk-OGTTUYNT.js.map} +1 -1
- package/dist/{chunk-GIMRELBW.js → chunk-OYQQJL3J.js} +3 -1
- package/dist/{chunk-GIMRELBW.js.map → chunk-OYQQJL3J.js.map} +1 -1
- package/dist/{chunk-RSI7XYXL.js → chunk-PBCZL4JP.js} +6 -5
- package/dist/{chunk-RSI7XYXL.js.map → chunk-PBCZL4JP.js.map} +1 -1
- package/dist/{chunk-I7IWRQLN.js → chunk-PHBFJCEU.js} +17 -11
- package/dist/chunk-PHBFJCEU.js.map +1 -0
- package/dist/{chunk-3CTRFMAK.js → chunk-PKCAYHDC.js} +5 -4
- package/dist/{chunk-3CTRFMAK.js.map → chunk-PKCAYHDC.js.map} +1 -1
- package/dist/{chunk-K3HQAKQX.js → chunk-PMV53IMM.js} +3 -1
- package/dist/{chunk-K3HQAKQX.js.map → chunk-PMV53IMM.js.map} +1 -1
- package/dist/{chunk-YQEAA6LT.js → chunk-QHUE7E4N.js} +3 -2
- package/dist/{chunk-YQEAA6LT.js.map → chunk-QHUE7E4N.js.map} +1 -1
- package/dist/{chunk-OA6HFRQP.js → chunk-QMMCJGFI.js} +4 -3
- package/dist/{chunk-OA6HFRQP.js.map → chunk-QMMCJGFI.js.map} +1 -1
- package/dist/{chunk-YV4L3ILF.js → chunk-QV3DJVRZ.js} +3 -1
- package/dist/{chunk-YV4L3ILF.js.map → chunk-QV3DJVRZ.js.map} +1 -1
- package/dist/{chunk-447JLCBU.js → chunk-S2QH6EZ5.js} +3 -1
- package/dist/{chunk-447JLCBU.js.map → chunk-S2QH6EZ5.js.map} +1 -1
- package/dist/{chunk-PNY3JKBJ.js → chunk-SFH43JT2.js} +5 -4
- package/dist/{chunk-PNY3JKBJ.js.map → chunk-SFH43JT2.js.map} +1 -1
- package/dist/{chunk-AWZLIMKX.js → chunk-T46QZH3E.js} +3 -1
- package/dist/{chunk-AWZLIMKX.js.map → chunk-T46QZH3E.js.map} +1 -1
- package/dist/{chunk-5J4FOW6Q.js → chunk-TNEZNMSN.js} +3 -1
- package/dist/{chunk-5J4FOW6Q.js.map → chunk-TNEZNMSN.js.map} +1 -1
- package/dist/{chunk-22KP6LR5.js → chunk-TXS65BB2.js} +3 -1
- package/dist/{chunk-22KP6LR5.js.map → chunk-TXS65BB2.js.map} +1 -1
- package/dist/{chunk-H5X55XH7.js → chunk-UDPH5SLV.js} +4 -3
- package/dist/{chunk-H5X55XH7.js.map → chunk-UDPH5SLV.js.map} +1 -1
- package/dist/{chunk-VZTQ73XT.js → chunk-XEA5BCMA.js} +3 -1
- package/dist/{chunk-VZTQ73XT.js.map → chunk-XEA5BCMA.js.map} +1 -1
- package/dist/{chunk-5F4WR7X7.js → chunk-XS67YG5R.js} +3 -1
- package/dist/{chunk-5F4WR7X7.js.map → chunk-XS67YG5R.js.map} +1 -1
- package/dist/{chunk-TKOTKRWY.js → chunk-XTD7TZHW.js} +3 -1
- package/dist/{chunk-TKOTKRWY.js.map → chunk-XTD7TZHW.js.map} +1 -1
- package/dist/{chunk-A2PI6UMY.js → chunk-YSRBFJMQ.js} +3 -1
- package/dist/{chunk-A2PI6UMY.js.map → chunk-YSRBFJMQ.js.map} +1 -1
- package/dist/chunk-YVFRBXST.js +1420 -0
- package/dist/chunk-YVFRBXST.js.map +1 -0
- package/dist/{chunk-SCOTPE2I.js → chunk-YYLBXXTE.js} +3 -1
- package/dist/{chunk-SCOTPE2I.js.map → chunk-YYLBXXTE.js.map} +1 -1
- package/dist/{chunk-RHREZ7BO.js → chunk-ZUWF4NF7.js} +3 -1
- package/dist/{chunk-RHREZ7BO.js.map → chunk-ZUWF4NF7.js.map} +1 -1
- package/dist/clipboard.js +3 -2
- package/dist/components/composer-transcription-control.d.ts +4 -0
- package/dist/components/session-conversation.d.ts +6 -0
- package/dist/composer-voice-events.d.ts +8 -0
- package/dist/composer.js +15 -13
- package/dist/computer-viewer-ELNLZGHI.js +20 -0
- package/dist/connect.js +15 -12
- package/dist/connect.js.map +1 -1
- package/dist/desktop.js +6 -5
- package/dist/desktop.js.map +1 -1
- package/dist/diffs.js +2 -1
- package/dist/diffs.js.map +1 -1
- package/dist/editor.js +4 -3
- package/dist/editor.js.map +1 -1
- package/dist/embedded-voice-NIL4RDX3.js +69 -0
- package/dist/embedded-voice-NIL4RDX3.js.map +1 -0
- package/dist/{fleet-decision-row-YZ3ZKWMM.js → fleet-decision-row-SI63O5V4.js} +3 -1
- package/dist/{fleet-decision-row-YZ3ZKWMM.js.map → fleet-decision-row-SI63O5V4.js.map} +1 -1
- package/dist/hooks/use-client-config-flags.d.ts +6 -0
- package/dist/hooks/use-computer-session.d.ts +2 -0
- package/dist/hooks/use-realtime-voice-models.d.ts +9 -0
- package/dist/hooks/use-voice-input.d.ts +8 -1
- package/dist/index.js +47 -45
- package/dist/index.js.map +1 -1
- package/dist/interaction.js +14 -13
- package/dist/interaction.js.map +1 -1
- package/dist/{latest-question-GPYM2JNU.js → latest-question-2POFPYNB.js} +5 -4
- package/dist/{latest-question-GPYM2JNU.js.map → latest-question-2POFPYNB.js.map} +1 -1
- package/dist/machines.js +8 -7
- package/dist/{markdown-table-layout-QXSLK4BY.js → markdown-table-layout-DQ4DRNVT.js} +3 -1
- package/dist/{markdown-table-layout-QXSLK4BY.js.map → markdown-table-layout-DQ4DRNVT.js.map} +1 -1
- package/dist/model-policy-picker-menu-WRNSRFQC.js +15 -0
- package/dist/model-policy.js +2 -1
- package/dist/{noto-sans-arabic-loader-IA2T4X2A.js → noto-sans-arabic-loader-XSH2KYWJ.js} +3 -1
- package/dist/{noto-sans-arabic-loader-IA2T4X2A.js.map → noto-sans-arabic-loader-XSH2KYWJ.js.map} +1 -1
- package/dist/{noto-sans-jp-loader.generated-HFGLYBR3.js → noto-sans-jp-loader.generated-MR5L6V7K.js} +3 -1
- package/dist/{noto-sans-jp-loader.generated-HFGLYBR3.js.map → noto-sans-jp-loader.generated-MR5L6V7K.js.map} +1 -1
- package/dist/{platform-activity-row-627BFZ46.js → platform-activity-row-PJJVATTZ.js} +3 -1
- package/dist/{platform-activity-row-627BFZ46.js.map → platform-activity-row-PJJVATTZ.js.map} +1 -1
- package/dist/{queue-surface-implementation-ZHFI5JBP.js → queue-surface-implementation-67FS7FUI.js} +10 -9
- package/dist/{queue-surface-implementation-ZHFI5JBP.js.map → queue-surface-implementation-67FS7FUI.js.map} +1 -1
- package/dist/realtime/embedded-voice.d.ts +20 -0
- package/dist/realtime.js +22 -1353
- package/dist/realtime.js.map +1 -1
- package/dist/sandbox-files-34CJJNOY.js +21 -0
- package/dist/session-ui.js +32 -30
- package/dist/session-ui.js.map +1 -1
- package/dist/session.js +10 -9
- package/dist/sites.js +2 -1
- package/dist/terminal.js +6 -5
- package/dist/terminal.js.map +1 -1
- package/dist/{timeline-annotation-markers-GNDHTGBD.js → timeline-annotation-markers-U3G66KUD.js} +5 -4
- package/dist/{timeline-annotation-markers-GNDHTGBD.js.map → timeline-annotation-markers-U3G66KUD.js.map} +1 -1
- package/dist/{timeline-annotation-selection-DMLMM2TX.js → timeline-annotation-selection-BI7QTPTZ.js} +4 -3
- package/dist/{timeline-annotation-selection-DMLMM2TX.js.map → timeline-annotation-selection-BI7QTPTZ.js.map} +1 -1
- package/dist/{timeline-annotations-dialog-ELRDBHTS.js → timeline-annotations-dialog-FOMHSDTE.js} +7 -6
- package/dist/{timeline-annotations-dialog-ELRDBHTS.js.map → timeline-annotations-dialog-FOMHSDTE.js.map} +1 -1
- package/dist/usage.js +6 -5
- package/dist/usage.js.map +1 -1
- package/dist/voice-recording-owner.d.ts +7 -0
- package/package.json +3 -3
- package/src/components/composer-transcription-control.tsx +109 -27
- package/src/components/computer-viewer.tsx +139 -30
- package/src/components/markdown.tsx +7 -2
- package/src/components/message-timeline.tsx +10 -1
- package/src/components/session-conversation.tsx +44 -0
- package/src/components/session-list.tsx +1 -1
- package/src/components/session-proxy-scope.tsx +26 -5
- package/src/composer-voice-events.ts +12 -0
- package/src/connection-discovery.tsx +4 -1
- package/src/hooks/use-browser-session.ts +445 -168
- package/src/hooks/use-client-config-flags.ts +8 -0
- package/src/hooks/use-computer-session.ts +334 -98
- package/src/hooks/use-goal.ts +12 -1
- package/src/hooks/use-realtime-voice-models.ts +67 -0
- package/src/hooks/use-voice-input.ts +109 -18
- package/src/realtime/embedded-voice.tsx +81 -0
- package/src/realtime/realtime-control.tsx +82 -17
- package/src/voice-recording-owner.ts +22 -0
- package/styles/compiled.css +77 -18
- package/styles/index.css +49 -0
- package/styles/responsive.css +61 -4
- package/styles/session-capability.css +1 -1
- package/dist/browser-viewer-SHYKQRNX.js +0 -16
- package/dist/chat-interactive-block-UGBTNB3L.js +0 -11
- package/dist/chunk-GYVRFZDY.js.map +0 -1
- package/dist/chunk-I7IWRQLN.js.map +0 -1
- package/dist/chunk-IWIDV7SB.js +0 -1
- package/dist/chunk-LJ2UTJJE.js.map +0 -1
- package/dist/chunk-LN6TCXD3.js.map +0 -1
- package/dist/computer-viewer-6SRGWRUX.js +0 -19
- package/dist/model-policy-picker-menu-DXHUL73H.js +0 -14
- package/dist/sandbox-files-GORZOUUJ.js +0 -20
- /package/dist/{browser-viewer-SHYKQRNX.js.map → browser-viewer-5EEAS3IU.js.map} +0 -0
- /package/dist/{chat-interactive-block-UGBTNB3L.js.map → chat-interactive-block-ZFHOKTMS.js.map} +0 -0
- /package/dist/{chunk-IWIDV7SB.js.map → chunk-M357MHH3.js.map} +0 -0
- /package/dist/{computer-viewer-6SRGWRUX.js.map → computer-viewer-ELNLZGHI.js.map} +0 -0
- /package/dist/{model-policy-picker-menu-DXHUL73H.js.map → model-policy-picker-menu-WRNSRFQC.js.map} +0 -0
- /package/dist/{sandbox-files-GORZOUUJ.js.map → sandbox-files-34CJJNOY.js.map} +0 -0
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
"use client";
|
|
1
2
|
import {
|
|
2
3
|
InteractionInterventionBanner,
|
|
3
4
|
isInteractionControlUnavailable,
|
|
@@ -6,16 +7,16 @@ import {
|
|
|
6
7
|
useInteractionInterventions,
|
|
7
8
|
useInteractionInvalidation,
|
|
8
9
|
useViewerMenuDismiss
|
|
9
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-BNKV5ZLF.js";
|
|
10
11
|
import {
|
|
11
12
|
copyTextToClipboard
|
|
12
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-CVYCLFMH.js";
|
|
13
14
|
import {
|
|
14
15
|
interactionHostPlatform
|
|
15
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-ZUWF4NF7.js";
|
|
16
17
|
import {
|
|
17
18
|
formatBytes
|
|
18
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-LVS3MH5T.js";
|
|
19
20
|
import {
|
|
20
21
|
STREAM_CLOSE_REASON_NORMAL,
|
|
21
22
|
STREAM_KIND_BROWSER,
|
|
@@ -24,16 +25,16 @@ import {
|
|
|
24
25
|
decodeStreamOpenAck,
|
|
25
26
|
encodeStreamClose,
|
|
26
27
|
encodeStreamOpen
|
|
27
|
-
} from "./chunk-
|
|
28
|
+
} from "./chunk-TNEZNMSN.js";
|
|
28
29
|
import {
|
|
29
30
|
usePageLiveActivity
|
|
30
|
-
} from "./chunk-
|
|
31
|
+
} from "./chunk-QHUE7E4N.js";
|
|
31
32
|
import {
|
|
32
33
|
useEmbeddedBrowserInteraction
|
|
33
|
-
} from "./chunk-
|
|
34
|
+
} from "./chunk-XTD7TZHW.js";
|
|
34
35
|
import {
|
|
35
36
|
cn
|
|
36
|
-
} from "./chunk-
|
|
37
|
+
} from "./chunk-TXS65BB2.js";
|
|
37
38
|
|
|
38
39
|
// src/components/browser-viewer.tsx
|
|
39
40
|
import { interactionControlFailureFromError } from "@opengeni/sdk/interaction";
|
|
@@ -866,6 +867,11 @@ function useBrowserSession(options) {
|
|
|
866
867
|
const { client, workspaceId } = useEmbeddedBrowserInteraction(options);
|
|
867
868
|
const browserSessionId = options.browserSessionId;
|
|
868
869
|
const enabled = (options.enabled ?? true) && browserSessionId !== null;
|
|
870
|
+
const sourceRef = useRef5({ client, workspaceId, browserSessionId, enabled });
|
|
871
|
+
if (sourceRef.current.client !== client || sourceRef.current.workspaceId !== workspaceId || sourceRef.current.browserSessionId !== browserSessionId || sourceRef.current.enabled !== enabled) {
|
|
872
|
+
sourceRef.current = { client, workspaceId, browserSessionId, enabled };
|
|
873
|
+
}
|
|
874
|
+
const source = sourceRef.current;
|
|
869
875
|
const semanticObservationEnabled = options.semanticObservationEnabled ?? true;
|
|
870
876
|
const semanticObservationEnabledRef = useRef5(semanticObservationEnabled);
|
|
871
877
|
semanticObservationEnabledRef.current = semanticObservationEnabled;
|
|
@@ -875,13 +881,15 @@ function useBrowserSession(options) {
|
|
|
875
881
|
});
|
|
876
882
|
const pageLive = usePageLiveActivity();
|
|
877
883
|
const pollIntervalMs = Math.max(750, options.pollIntervalMs ?? 2e3);
|
|
878
|
-
const [state, setState] = useState5(() => emptyState4(browserSessionId, enabled));
|
|
879
|
-
const visible = state.browserSessionId === browserSessionId ? state : emptyState4(browserSessionId, enabled);
|
|
884
|
+
const [state, setState] = useState5(() => ({ ...emptyState4(browserSessionId, enabled), source }));
|
|
885
|
+
const visible = state.source === source && state.browserSessionId === browserSessionId ? state : { ...emptyState4(browserSessionId, enabled), source };
|
|
880
886
|
const refreshBlocked = isNonRetryableInteractionError(visible.error);
|
|
881
887
|
const inputFailureRef = useRef5(visible.inputFailure);
|
|
882
888
|
inputFailureRef.current = visible.inputFailure;
|
|
883
889
|
const selectedTargetIdRef = useRef5(visible.selectedTargetId);
|
|
884
890
|
selectedTargetIdRef.current = visible.selectedTargetId;
|
|
891
|
+
const selectionRevisionRef = useRef5(0);
|
|
892
|
+
const actionResultOrderRef = useRef5({ next: 0, settled: 0 });
|
|
885
893
|
const selectedTargetRef = useRef5(
|
|
886
894
|
visible.targets.find((target) => target.id === visible.selectedTargetId) ?? null
|
|
887
895
|
);
|
|
@@ -902,17 +910,23 @@ function useBrowserSession(options) {
|
|
|
902
910
|
});
|
|
903
911
|
const mutationRef = useRef5({
|
|
904
912
|
browserSessionId,
|
|
905
|
-
|
|
913
|
+
source,
|
|
914
|
+
count: 0,
|
|
915
|
+
needsInventoryReconcile: false
|
|
906
916
|
});
|
|
907
917
|
const mountedRef = useRef5(true);
|
|
918
|
+
const isCurrentSource = useCallback5(
|
|
919
|
+
() => mountedRef.current && sourceRef.current === source,
|
|
920
|
+
[source]
|
|
921
|
+
);
|
|
908
922
|
const invalidateRefresh = useCallback5(() => {
|
|
909
923
|
const id = requestRef.current.id + 1;
|
|
910
924
|
requestRef.current.controller?.abort();
|
|
911
925
|
requestRef.current = { id, controller: null };
|
|
912
926
|
}, []);
|
|
913
927
|
const refreshInventory = useCallback5(
|
|
914
|
-
async (checkInput = false) => {
|
|
915
|
-
if (!enabled || !browserSessionId) return;
|
|
928
|
+
async (checkInput = false, observeSelectedTarget = true) => {
|
|
929
|
+
if (!enabled || !browserSessionId || !isCurrentSource()) return;
|
|
916
930
|
const checkedInputFailure = inputFailureRef.current;
|
|
917
931
|
const id = requestRef.current.id + 1;
|
|
918
932
|
requestRef.current.controller?.abort();
|
|
@@ -927,14 +941,18 @@ function useBrowserSession(options) {
|
|
|
927
941
|
signal: controller.signal
|
|
928
942
|
})
|
|
929
943
|
]);
|
|
930
|
-
if (!
|
|
944
|
+
if (!isCurrentSource() || requestRef.current.id !== id) return;
|
|
931
945
|
const selected = chooseTarget(targetResponse.targets, selectedTargetIdRef.current);
|
|
932
946
|
selectedTargetIdRef.current = selected?.id ?? null;
|
|
947
|
+
selectedTargetRef.current = selected;
|
|
933
948
|
const previousObservation = observationRef.current.browserSessionId === browserSessionId ? observationRef.current.observation : null;
|
|
934
949
|
const retainedObservation = selected && previousObservation && sameObservationTarget(previousObservation, selected) ? previousObservation : null;
|
|
935
|
-
observationRef.current = {
|
|
950
|
+
observationRef.current = {
|
|
951
|
+
browserSessionId,
|
|
952
|
+
observation: retainedObservation
|
|
953
|
+
};
|
|
936
954
|
setState(
|
|
937
|
-
(current) => current.browserSessionId === browserSessionId ? {
|
|
955
|
+
(current) => isCurrentSource() && current.source === source && current.browserSessionId === browserSessionId ? {
|
|
938
956
|
...current,
|
|
939
957
|
session,
|
|
940
958
|
targets: targetResponse.targets,
|
|
@@ -947,7 +965,7 @@ function useBrowserSession(options) {
|
|
|
947
965
|
inputFailure: checkInput && session.id === browserSessionId && targetResponse.browserSessionId === browserSessionId && current.inputFailure === checkedInputFailure ? null : current.inputFailure
|
|
948
966
|
} : current
|
|
949
967
|
);
|
|
950
|
-
if (!selected || !semanticObservationEnabledRef.current) return;
|
|
968
|
+
if (!selected || !observeSelectedTarget || !semanticObservationEnabledRef.current) return;
|
|
951
969
|
try {
|
|
952
970
|
const observation = await client.observeBrowserTarget(
|
|
953
971
|
workspaceId,
|
|
@@ -955,22 +973,29 @@ function useBrowserSession(options) {
|
|
|
955
973
|
selected.id,
|
|
956
974
|
{ signal: controller.signal }
|
|
957
975
|
);
|
|
958
|
-
if (!
|
|
976
|
+
if (!isCurrentSource() || requestRef.current.id !== id) return;
|
|
977
|
+
const currentSelected = selectedTargetRef.current;
|
|
978
|
+
if (observationRef.current.browserSessionId !== browserSessionId || currentSelected?.id !== selected.id || observation.browserSessionId !== browserSessionId || observation.target.id !== selected.id || observation.target.controllerGeneration !== currentSelected.controllerGeneration || observation.target.targetGeneration !== currentSelected.targetGeneration)
|
|
979
|
+
return;
|
|
980
|
+
selectedTargetRef.current = observation.target;
|
|
959
981
|
observationRef.current = { browserSessionId, observation };
|
|
960
982
|
lastObservationAtRef.current = Date.now();
|
|
961
983
|
setState(
|
|
962
|
-
(current) => current.browserSessionId === browserSessionId && current.selectedTargetId === observation.target.id ? {
|
|
984
|
+
(current) => isCurrentSource() && current.source === source && current.browserSessionId === browserSessionId && current.selectedTargetId === observation.target.id ? {
|
|
985
|
+
...current,
|
|
986
|
+
observation,
|
|
987
|
+
targets: replaceTarget(current.targets, observation.target)
|
|
988
|
+
} : current
|
|
963
989
|
);
|
|
964
990
|
} catch (cause) {
|
|
965
|
-
if (controller.signal.aborted || !
|
|
991
|
+
if (controller.signal.aborted || !isCurrentSource() || requestRef.current.id !== id)
|
|
966
992
|
return;
|
|
967
993
|
void cause;
|
|
968
994
|
}
|
|
969
995
|
} catch (cause) {
|
|
970
|
-
if (controller.signal.aborted || !
|
|
971
|
-
return;
|
|
996
|
+
if (controller.signal.aborted || !isCurrentSource() || requestRef.current.id !== id) return;
|
|
972
997
|
setState(
|
|
973
|
-
(current) => current.browserSessionId === browserSessionId ? {
|
|
998
|
+
(current) => isCurrentSource() && current.source === source && current.browserSessionId === browserSessionId ? {
|
|
974
999
|
...current,
|
|
975
1000
|
loading: false,
|
|
976
1001
|
error: cause instanceof Error ? cause : new Error(String(cause))
|
|
@@ -982,11 +1007,11 @@ function useBrowserSession(options) {
|
|
|
982
1007
|
}
|
|
983
1008
|
}
|
|
984
1009
|
},
|
|
985
|
-
[browserSessionId, client, enabled, workspaceId]
|
|
1010
|
+
[browserSessionId, client, enabled, isCurrentSource, source, workspaceId]
|
|
986
1011
|
);
|
|
987
1012
|
const refresh = useCallback5(async () => await refreshInventory(true), [refreshInventory]);
|
|
988
1013
|
const refreshSemantic = useCallback5(async () => {
|
|
989
|
-
if (!enabled || !browserSessionId) return;
|
|
1014
|
+
if (!enabled || !browserSessionId || !isCurrentSource()) return;
|
|
990
1015
|
const target = selectedTargetRef.current;
|
|
991
1016
|
if (!target) return;
|
|
992
1017
|
const id = requestRef.current.id + 1;
|
|
@@ -1000,34 +1025,34 @@ function useBrowserSession(options) {
|
|
|
1000
1025
|
target.id,
|
|
1001
1026
|
{ signal: controller.signal }
|
|
1002
1027
|
);
|
|
1003
|
-
if (!
|
|
1028
|
+
if (!isCurrentSource() || requestRef.current.id !== id) return;
|
|
1004
1029
|
if (!sameObservationTarget(observation, selectedTargetRef.current)) return;
|
|
1005
1030
|
observationRef.current = { browserSessionId, observation };
|
|
1006
1031
|
lastObservationAtRef.current = Date.now();
|
|
1007
1032
|
setState(
|
|
1008
|
-
(current) => current.browserSessionId === browserSessionId && current.selectedTargetId === target.id ? { ...current, observation } : current
|
|
1033
|
+
(current) => isCurrentSource() && current.source === source && current.browserSessionId === browserSessionId && current.selectedTargetId === target.id ? { ...current, observation } : current
|
|
1009
1034
|
);
|
|
1010
1035
|
} catch {
|
|
1011
1036
|
} finally {
|
|
1012
1037
|
if (requestRef.current.id === id) requestRef.current = { id, controller: null };
|
|
1013
1038
|
}
|
|
1014
|
-
}, [browserSessionId, client, enabled, workspaceId]);
|
|
1039
|
+
}, [browserSessionId, client, enabled, isCurrentSource, source, workspaceId]);
|
|
1015
1040
|
useEffect5(() => {
|
|
1016
1041
|
mountedRef.current = true;
|
|
1017
1042
|
if (!enabled) {
|
|
1018
1043
|
invalidateRefresh();
|
|
1019
|
-
setState(emptyState4(browserSessionId, false));
|
|
1044
|
+
setState({ ...emptyState4(browserSessionId, false), source });
|
|
1020
1045
|
return;
|
|
1021
1046
|
}
|
|
1022
1047
|
setState(
|
|
1023
|
-
(current) => current.browserSessionId === browserSessionId ? { ...current, loading: true } : emptyState4(browserSessionId, true)
|
|
1048
|
+
(current) => isCurrentSource() && current.source === source && current.browserSessionId === browserSessionId ? { ...current, loading: true } : { ...emptyState4(browserSessionId, true), source }
|
|
1024
1049
|
);
|
|
1025
1050
|
void refreshInventory();
|
|
1026
1051
|
return () => {
|
|
1027
1052
|
mountedRef.current = false;
|
|
1028
1053
|
invalidateRefresh();
|
|
1029
1054
|
};
|
|
1030
|
-
}, [browserSessionId, enabled, invalidateRefresh, refreshInventory]);
|
|
1055
|
+
}, [browserSessionId, enabled, invalidateRefresh, isCurrentSource, refreshInventory, source]);
|
|
1031
1056
|
useEffect5(() => {
|
|
1032
1057
|
const previous = previousSemanticObservationRef.current;
|
|
1033
1058
|
previousSemanticObservationRef.current = {
|
|
@@ -1041,11 +1066,19 @@ function useBrowserSession(options) {
|
|
|
1041
1066
|
}
|
|
1042
1067
|
observationRef.current = { browserSessionId, observation: null };
|
|
1043
1068
|
setState(
|
|
1044
|
-
(current) => current.browserSessionId === browserSessionId ? { ...current, observation: null } : current
|
|
1069
|
+
(current) => isCurrentSource() && current.source === source && current.browserSessionId === browserSessionId ? { ...current, observation: null } : current
|
|
1045
1070
|
);
|
|
1046
1071
|
void refreshSemantic();
|
|
1047
1072
|
}
|
|
1048
|
-
}, [
|
|
1073
|
+
}, [
|
|
1074
|
+
browserSessionId,
|
|
1075
|
+
enabled,
|
|
1076
|
+
isCurrentSource,
|
|
1077
|
+
pollIntervalMs,
|
|
1078
|
+
refreshSemantic,
|
|
1079
|
+
semanticObservationEnabled,
|
|
1080
|
+
source
|
|
1081
|
+
]);
|
|
1049
1082
|
useEffect5(() => {
|
|
1050
1083
|
if (!enabled || !pageLive || visible.mutating || refreshBlocked) return;
|
|
1051
1084
|
const timer = setInterval(() => {
|
|
@@ -1057,6 +1090,7 @@ function useBrowserSession(options) {
|
|
|
1057
1090
|
if (!enabled || !browserSessionId || !pageLive || refreshBlocked) return;
|
|
1058
1091
|
let disposed = false;
|
|
1059
1092
|
const heartbeat = () => {
|
|
1093
|
+
if (!isCurrentSource()) return;
|
|
1060
1094
|
void client.heartbeatBrowserSession(workspaceId, browserSessionId).catch(() => {
|
|
1061
1095
|
if (!disposed) void refreshInventory();
|
|
1062
1096
|
});
|
|
@@ -1066,151 +1100,216 @@ function useBrowserSession(options) {
|
|
|
1066
1100
|
disposed = true;
|
|
1067
1101
|
clearInterval(timer);
|
|
1068
1102
|
};
|
|
1069
|
-
}, [
|
|
1103
|
+
}, [
|
|
1104
|
+
browserSessionId,
|
|
1105
|
+
client,
|
|
1106
|
+
enabled,
|
|
1107
|
+
isCurrentSource,
|
|
1108
|
+
pageLive,
|
|
1109
|
+
refreshInventory,
|
|
1110
|
+
refreshBlocked,
|
|
1111
|
+
workspaceId
|
|
1112
|
+
]);
|
|
1070
1113
|
const runMutation = useCallback5(
|
|
1071
|
-
async (scopeBrowserSessionId, operation) => {
|
|
1114
|
+
async (scopeBrowserSessionId, operation, selectionRead = false, changesInventory = false) => {
|
|
1115
|
+
if (!enabled || !isCurrentSource()) {
|
|
1116
|
+
throw new Error("The browser source is no longer selected.");
|
|
1117
|
+
}
|
|
1118
|
+
const selectionRevision = ++selectionRevisionRef.current;
|
|
1072
1119
|
invalidateRefresh();
|
|
1073
|
-
|
|
1120
|
+
const readRequestId = requestRef.current.id;
|
|
1121
|
+
if (mutationRef.current.browserSessionId !== scopeBrowserSessionId || mutationRef.current.source !== source) {
|
|
1074
1122
|
mutationRef.current = {
|
|
1075
1123
|
browserSessionId: scopeBrowserSessionId,
|
|
1076
|
-
|
|
1124
|
+
source,
|
|
1125
|
+
count: 0,
|
|
1126
|
+
needsInventoryReconcile: false
|
|
1077
1127
|
};
|
|
1078
1128
|
}
|
|
1079
1129
|
mutationRef.current.count += 1;
|
|
1080
1130
|
setState(
|
|
1081
|
-
(current) => current.browserSessionId === scopeBrowserSessionId ? { ...current, mutating: true, error: null } : current
|
|
1131
|
+
(current) => isCurrentSource() && current.source === source && current.browserSessionId === scopeBrowserSessionId ? { ...current, mutating: true, error: null } : current
|
|
1082
1132
|
);
|
|
1083
1133
|
try {
|
|
1084
|
-
return await operation();
|
|
1134
|
+
return await operation(selectionRevision, readRequestId);
|
|
1085
1135
|
} catch (cause) {
|
|
1086
1136
|
const error = cause instanceof Error ? cause : new Error(String(cause));
|
|
1087
|
-
|
|
1088
|
-
(
|
|
1089
|
-
|
|
1137
|
+
if (!selectionRead || requestRef.current.id === readRequestId) {
|
|
1138
|
+
setState(
|
|
1139
|
+
(current) => isCurrentSource() && selectionRevisionRef.current === selectionRevision && current.source === source && current.browserSessionId === scopeBrowserSessionId ? { ...current, error } : current
|
|
1140
|
+
);
|
|
1141
|
+
}
|
|
1090
1142
|
throw error;
|
|
1091
1143
|
} finally {
|
|
1092
|
-
if (mutationRef.current.browserSessionId === scopeBrowserSessionId) {
|
|
1144
|
+
if (mutationRef.current.browserSessionId === scopeBrowserSessionId && mutationRef.current.source === source) {
|
|
1145
|
+
if (changesInventory && (selectionRevisionRef.current !== selectionRevision || requestRef.current.id !== readRequestId)) {
|
|
1146
|
+
mutationRef.current.needsInventoryReconcile = true;
|
|
1147
|
+
}
|
|
1093
1148
|
mutationRef.current.count = Math.max(0, mutationRef.current.count - 1);
|
|
1094
1149
|
const mutating = mutationRef.current.count > 0;
|
|
1095
1150
|
setState(
|
|
1096
|
-
(current) => current.browserSessionId === scopeBrowserSessionId ? { ...current, mutating } : current
|
|
1151
|
+
(current) => isCurrentSource() && current.source === source && current.browserSessionId === scopeBrowserSessionId ? { ...current, mutating } : current
|
|
1097
1152
|
);
|
|
1153
|
+
if (!mutating && mutationRef.current.needsInventoryReconcile && isCurrentSource()) {
|
|
1154
|
+
mutationRef.current.needsInventoryReconcile = false;
|
|
1155
|
+
void refreshInventory(false, false);
|
|
1156
|
+
}
|
|
1098
1157
|
}
|
|
1099
1158
|
}
|
|
1100
1159
|
},
|
|
1101
|
-
[invalidateRefresh]
|
|
1160
|
+
[enabled, invalidateRefresh, isCurrentSource, refreshInventory, source]
|
|
1102
1161
|
);
|
|
1103
1162
|
const selectTarget = useCallback5(
|
|
1104
1163
|
async (targetId) => {
|
|
1105
1164
|
if (!browserSessionId) throw new Error("No BrowserSession is selected.");
|
|
1106
|
-
return await runMutation(
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1165
|
+
return await runMutation(
|
|
1166
|
+
browserSessionId,
|
|
1167
|
+
async (selectionRevision, readRequestId) => {
|
|
1168
|
+
const isCurrentSelection = () => isCurrentSource() && selectionRevisionRef.current === selectionRevision;
|
|
1169
|
+
const isCurrentSelectionRead = () => isCurrentSelection() && requestRef.current.id === readRequestId;
|
|
1170
|
+
let targets = visible.targets;
|
|
1171
|
+
let target;
|
|
1172
|
+
let observation;
|
|
1173
|
+
try {
|
|
1174
|
+
observation = await client.selectBrowserTarget(workspaceId, browserSessionId, targetId);
|
|
1175
|
+
target = observation.target;
|
|
1176
|
+
} catch (cause) {
|
|
1177
|
+
if (!isCurrentSelectionRead() || !isMissingBrowserTarget(cause)) throw cause;
|
|
1178
|
+
const response = await client.listBrowserTargets(workspaceId, browserSessionId);
|
|
1179
|
+
if (!isCurrentSelectionRead()) throw cause;
|
|
1180
|
+
targets = response.targets;
|
|
1181
|
+
const fallback = chooseTarget(targets, null);
|
|
1182
|
+
if (!fallback) {
|
|
1183
|
+
selectedTargetIdRef.current = null;
|
|
1184
|
+
selectedTargetRef.current = null;
|
|
1185
|
+
observationRef.current = { browserSessionId, observation: null };
|
|
1186
|
+
setState(
|
|
1187
|
+
(current) => isCurrentSelection() && current.source === source && current.browserSessionId === browserSessionId ? {
|
|
1188
|
+
...current,
|
|
1189
|
+
targets,
|
|
1190
|
+
selectedTargetId: null,
|
|
1191
|
+
observation: null
|
|
1192
|
+
} : current
|
|
1193
|
+
);
|
|
1194
|
+
throw cause;
|
|
1195
|
+
}
|
|
1196
|
+
observation = await client.selectBrowserTarget(
|
|
1197
|
+
workspaceId,
|
|
1198
|
+
browserSessionId,
|
|
1199
|
+
fallback.id
|
|
1128
1200
|
);
|
|
1129
|
-
|
|
1201
|
+
target = observation.target;
|
|
1130
1202
|
}
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1203
|
+
if (!isCurrentSelectionRead()) return target;
|
|
1204
|
+
selectedTargetIdRef.current = target.id;
|
|
1205
|
+
selectedTargetRef.current = target;
|
|
1206
|
+
observationRef.current = { browserSessionId, observation };
|
|
1207
|
+
lastObservationAtRef.current = Date.now();
|
|
1208
|
+
setState(
|
|
1209
|
+
(current) => isCurrentSelection() && current.source === source && current.browserSessionId === browserSessionId ? {
|
|
1210
|
+
...current,
|
|
1211
|
+
targets: replaceTarget(targets, target).map((candidate) => ({
|
|
1212
|
+
...candidate,
|
|
1213
|
+
selected: candidate.id === target.id
|
|
1214
|
+
})),
|
|
1215
|
+
selectedTargetId: target.id,
|
|
1216
|
+
observation
|
|
1217
|
+
} : current
|
|
1135
1218
|
);
|
|
1136
|
-
|
|
1137
|
-
}
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
lastObservationAtRef.current = Date.now();
|
|
1141
|
-
setState(
|
|
1142
|
-
(current) => current.browserSessionId === browserSessionId ? {
|
|
1143
|
-
...current,
|
|
1144
|
-
targets: targets.map((candidate) => ({
|
|
1145
|
-
...candidate,
|
|
1146
|
-
selected: candidate.id === target.id
|
|
1147
|
-
})),
|
|
1148
|
-
selectedTargetId: target.id,
|
|
1149
|
-
observation
|
|
1150
|
-
} : current
|
|
1151
|
-
);
|
|
1152
|
-
return target;
|
|
1153
|
-
});
|
|
1219
|
+
return target;
|
|
1220
|
+
},
|
|
1221
|
+
true
|
|
1222
|
+
);
|
|
1154
1223
|
},
|
|
1155
|
-
[browserSessionId, client, runMutation, visible.targets, workspaceId]
|
|
1224
|
+
[browserSessionId, client, isCurrentSource, runMutation, source, visible.targets, workspaceId]
|
|
1156
1225
|
);
|
|
1157
1226
|
const openTarget = useCallback5(
|
|
1158
1227
|
async (url) => {
|
|
1159
1228
|
if (!browserSessionId) throw new Error("No BrowserSession is selected.");
|
|
1160
|
-
return await runMutation(
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
(
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1229
|
+
return await runMutation(
|
|
1230
|
+
browserSessionId,
|
|
1231
|
+
async (selectionRevision, readRequestId) => {
|
|
1232
|
+
const isCurrentSelection = () => isCurrentSource() && selectionRevisionRef.current === selectionRevision;
|
|
1233
|
+
const isCurrentSelectionRead = () => isCurrentSelection() && requestRef.current.id === readRequestId;
|
|
1234
|
+
const observation = await client.openBrowserTarget(
|
|
1235
|
+
workspaceId,
|
|
1236
|
+
browserSessionId,
|
|
1237
|
+
url === void 0 ? {} : { url }
|
|
1238
|
+
);
|
|
1239
|
+
const target = observation.target;
|
|
1240
|
+
if (!isCurrentSource()) return target;
|
|
1241
|
+
if (!isCurrentSelectionRead()) return target;
|
|
1242
|
+
selectedTargetIdRef.current = target.id;
|
|
1243
|
+
selectedTargetRef.current = target;
|
|
1244
|
+
observationRef.current = { browserSessionId, observation };
|
|
1245
|
+
lastObservationAtRef.current = Date.now();
|
|
1246
|
+
setState(
|
|
1247
|
+
(current) => isCurrentSelection() && current.source === source && current.browserSessionId === browserSessionId ? {
|
|
1248
|
+
...current,
|
|
1249
|
+
targets: [
|
|
1250
|
+
...current.targets.map((candidate) => ({
|
|
1251
|
+
...candidate,
|
|
1252
|
+
selected: false
|
|
1253
|
+
})),
|
|
1254
|
+
target
|
|
1255
|
+
],
|
|
1256
|
+
selectedTargetId: target.id,
|
|
1257
|
+
observation
|
|
1258
|
+
} : current
|
|
1259
|
+
);
|
|
1260
|
+
return target;
|
|
1261
|
+
},
|
|
1262
|
+
false,
|
|
1263
|
+
true
|
|
1264
|
+
);
|
|
1186
1265
|
},
|
|
1187
|
-
[browserSessionId, client, runMutation, workspaceId]
|
|
1266
|
+
[browserSessionId, client, isCurrentSource, runMutation, source, workspaceId]
|
|
1188
1267
|
);
|
|
1189
1268
|
const closeTarget = useCallback5(
|
|
1190
1269
|
async (targetId) => {
|
|
1191
1270
|
if (!browserSessionId) throw new Error("No BrowserSession is selected.");
|
|
1192
|
-
await runMutation(
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1271
|
+
await runMutation(
|
|
1272
|
+
browserSessionId,
|
|
1273
|
+
async (selectionRevision, readRequestId) => {
|
|
1274
|
+
const isCurrentSelection = () => isCurrentSource() && selectionRevisionRef.current === selectionRevision;
|
|
1275
|
+
const isCurrentSelectionRead = () => isCurrentSelection() && requestRef.current.id === readRequestId;
|
|
1276
|
+
const response = await client.closeBrowserTarget(workspaceId, browserSessionId, targetId);
|
|
1277
|
+
if (!isCurrentSource()) return;
|
|
1278
|
+
if (!isCurrentSelectionRead()) return;
|
|
1279
|
+
const selected = chooseTarget(response.targets, selectedTargetIdRef.current);
|
|
1280
|
+
const observed = selected ? await client.observeBrowserTarget(workspaceId, browserSessionId, selected.id) : null;
|
|
1281
|
+
if (!isCurrentSource()) return;
|
|
1282
|
+
if (!isCurrentSelectionRead()) return;
|
|
1283
|
+
const observation = observed && selected && observed.browserSessionId === browserSessionId && observed.target.id === selected.id && observed.target.controllerGeneration === selected.controllerGeneration && observed.target.targetGeneration === selected.targetGeneration ? observed : null;
|
|
1284
|
+
const currentTarget = observation?.target ?? selected;
|
|
1285
|
+
selectedTargetIdRef.current = currentTarget?.id ?? null;
|
|
1286
|
+
selectedTargetRef.current = currentTarget;
|
|
1287
|
+
observationRef.current = { browserSessionId, observation };
|
|
1288
|
+
if (observation) lastObservationAtRef.current = Date.now();
|
|
1289
|
+
setState(
|
|
1290
|
+
(current) => isCurrentSelection() && current.source === source && current.browserSessionId === browserSessionId ? {
|
|
1291
|
+
...current,
|
|
1292
|
+
targets: currentTarget ? replaceTarget(response.targets, currentTarget) : response.targets,
|
|
1293
|
+
selectedTargetId: currentTarget?.id ?? null,
|
|
1294
|
+
observation
|
|
1295
|
+
} : current
|
|
1296
|
+
);
|
|
1297
|
+
},
|
|
1298
|
+
false,
|
|
1299
|
+
true
|
|
1300
|
+
);
|
|
1208
1301
|
},
|
|
1209
|
-
[browserSessionId, client, runMutation, workspaceId]
|
|
1302
|
+
[browserSessionId, client, isCurrentSource, runMutation, source, workspaceId]
|
|
1210
1303
|
);
|
|
1211
1304
|
const dispatchAction = useCallback5(
|
|
1212
1305
|
async (action, operationId, frame, observationMode = "none") => {
|
|
1213
1306
|
if (!browserSessionId) throw new Error("No BrowserSession is selected.");
|
|
1307
|
+
if (!enabled || !isCurrentSource()) {
|
|
1308
|
+
throw new Error("The browser source is no longer selected.");
|
|
1309
|
+
}
|
|
1310
|
+
if (!selectedTargetRef.current) {
|
|
1311
|
+
throw new Error("The browser page is not ready for input.");
|
|
1312
|
+
}
|
|
1214
1313
|
if (frame && frame.browserSessionId !== browserSessionId) {
|
|
1215
1314
|
throw new Error("The displayed browser frame belongs to another BrowserSession.");
|
|
1216
1315
|
}
|
|
@@ -1220,7 +1319,7 @@ function useBrowserSession(options) {
|
|
|
1220
1319
|
expectedTargetGeneration: frame.targetGeneration,
|
|
1221
1320
|
expectedDocumentGeneration: frame.documentGeneration,
|
|
1222
1321
|
expectedFrameId: frame.frameId
|
|
1223
|
-
} : currentObservation ? {
|
|
1322
|
+
} : currentObservation && sameObservationTarget(currentObservation, selectedTargetRef.current) ? {
|
|
1224
1323
|
targetId: currentObservation.target.id,
|
|
1225
1324
|
expectedTargetGeneration: currentObservation.target.targetGeneration,
|
|
1226
1325
|
expectedDocumentGeneration: currentObservation.target.documentGeneration,
|
|
@@ -1229,6 +1328,21 @@ function useBrowserSession(options) {
|
|
|
1229
1328
|
if (!fence) {
|
|
1230
1329
|
throw new Error("The browser page is not ready for input.");
|
|
1231
1330
|
}
|
|
1331
|
+
const expectedControllerGeneration = frame?.controllerGeneration ?? currentObservation.target.controllerGeneration;
|
|
1332
|
+
const selectionRevision = selectionRevisionRef.current;
|
|
1333
|
+
const resultOrder = ++actionResultOrderRef.current.next;
|
|
1334
|
+
let resultDocumentGeneration = fence.expectedDocumentGeneration;
|
|
1335
|
+
const isCurrentResultView = () => {
|
|
1336
|
+
const selected = selectedTargetRef.current;
|
|
1337
|
+
return isCurrentSource() && selectionRevisionRef.current === selectionRevision && selected?.browserSessionId === browserSessionId && selected.id === fence.targetId && selected.controllerGeneration === expectedControllerGeneration && selected.targetGeneration === fence.expectedTargetGeneration && (selected.documentGeneration === fence.expectedDocumentGeneration || selected.documentGeneration === resultDocumentGeneration);
|
|
1338
|
+
};
|
|
1339
|
+
const canProjectResult = () => isCurrentResultView() && resultOrder >= actionResultOrderRef.current.settled;
|
|
1340
|
+
const settleResult = () => {
|
|
1341
|
+
if (!canProjectResult()) return false;
|
|
1342
|
+
actionResultOrderRef.current.settled = resultOrder;
|
|
1343
|
+
invalidateRefresh();
|
|
1344
|
+
return true;
|
|
1345
|
+
};
|
|
1232
1346
|
try {
|
|
1233
1347
|
const receipt = await client.actInBrowser(workspaceId, browserSessionId, {
|
|
1234
1348
|
operationId,
|
|
@@ -1236,40 +1350,49 @@ function useBrowserSession(options) {
|
|
|
1236
1350
|
observationMode,
|
|
1237
1351
|
action
|
|
1238
1352
|
});
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
);
|
|
1248
|
-
}
|
|
1249
|
-
if (receipt.observation) {
|
|
1353
|
+
resultDocumentGeneration = receipt.observation?.target.documentGeneration ?? fence.expectedDocumentGeneration;
|
|
1354
|
+
const settled = receipt.state === "completed" || receipt.state === "failed" || receipt.state === "outcome_unknown";
|
|
1355
|
+
if (!canProjectResult() || settled && !settleResult()) return receipt;
|
|
1356
|
+
const receivedObservation = receipt.observation;
|
|
1357
|
+
const selectedTarget = selectedTargetRef.current;
|
|
1358
|
+
let projectedObservation = null;
|
|
1359
|
+
if (settled && receivedObservation && canProjectResult() && receipt.browserSessionId === browserSessionId && receipt.controllerGeneration === expectedControllerGeneration && receipt.targetId === fence.targetId && observationRef.current.browserSessionId === browserSessionId && receivedObservation.browserSessionId === browserSessionId && selectedTarget?.browserSessionId === browserSessionId && selectedTarget.id === fence.targetId && receivedObservation.target.id === fence.targetId && selectedTarget.controllerGeneration === expectedControllerGeneration && receivedObservation.target.controllerGeneration === expectedControllerGeneration && selectedTarget.targetGeneration === fence.expectedTargetGeneration && receivedObservation.target.targetGeneration === fence.expectedTargetGeneration && (selectedTarget.documentGeneration === fence.expectedDocumentGeneration || selectedTarget.documentGeneration === receivedObservation.target.documentGeneration)) {
|
|
1360
|
+
projectedObservation = receivedObservation;
|
|
1250
1361
|
observationRef.current = {
|
|
1251
1362
|
browserSessionId,
|
|
1252
|
-
observation:
|
|
1363
|
+
observation: receivedObservation
|
|
1253
1364
|
};
|
|
1365
|
+
selectedTargetRef.current = receivedObservation.target;
|
|
1254
1366
|
lastObservationAtRef.current = Date.now();
|
|
1255
|
-
setState(
|
|
1256
|
-
(current) => current.browserSessionId === browserSessionId ? {
|
|
1257
|
-
...current,
|
|
1258
|
-
observation: receipt.observation,
|
|
1259
|
-
targets: replaceTarget(current.targets, receipt.observation.target)
|
|
1260
|
-
} : current
|
|
1261
|
-
);
|
|
1262
1367
|
}
|
|
1368
|
+
setState(
|
|
1369
|
+
(current) => isCurrentResultView() && current.source === source && current.browserSessionId === browserSessionId && current.actionResultOrder <= resultOrder ? {
|
|
1370
|
+
...current,
|
|
1371
|
+
actionResultOrder: settled ? resultOrder : current.actionResultOrder,
|
|
1372
|
+
error: receipt.state === "completed" ? null : current.error,
|
|
1373
|
+
inputFailure: receipt.state === "completed" ? current.inputFailure : {
|
|
1374
|
+
operationId: receipt.operationId,
|
|
1375
|
+
state: receipt.state,
|
|
1376
|
+
error: receipt.error
|
|
1377
|
+
},
|
|
1378
|
+
...projectedObservation ? {
|
|
1379
|
+
observation: projectedObservation,
|
|
1380
|
+
targets: replaceTarget(current.targets, projectedObservation.target)
|
|
1381
|
+
} : {}
|
|
1382
|
+
} : current
|
|
1383
|
+
);
|
|
1263
1384
|
return receipt;
|
|
1264
1385
|
} catch (cause) {
|
|
1265
1386
|
const error = cause instanceof Error ? cause : new Error(String(cause));
|
|
1266
|
-
|
|
1267
|
-
(
|
|
1268
|
-
|
|
1387
|
+
if (settleResult()) {
|
|
1388
|
+
setState(
|
|
1389
|
+
(current) => isCurrentResultView() && current.source === source && current.browserSessionId === browserSessionId && current.actionResultOrder <= resultOrder ? { ...current, error, actionResultOrder: resultOrder } : current
|
|
1390
|
+
);
|
|
1391
|
+
}
|
|
1269
1392
|
throw error;
|
|
1270
1393
|
}
|
|
1271
1394
|
},
|
|
1272
|
-
[browserSessionId, client, workspaceId]
|
|
1395
|
+
[browserSessionId, client, enabled, invalidateRefresh, isCurrentSource, source, workspaceId]
|
|
1273
1396
|
);
|
|
1274
1397
|
const act = useCallback5(
|
|
1275
1398
|
async (action, operationId = crypto.randomUUID()) => await dispatchAction(action, operationId, null),
|
|
@@ -1281,13 +1404,16 @@ function useBrowserSession(options) {
|
|
|
1281
1404
|
);
|
|
1282
1405
|
const observeForInput = useCallback5(async () => {
|
|
1283
1406
|
const target = selectedTargetRef.current;
|
|
1407
|
+
if (!enabled || !isCurrentSource()) {
|
|
1408
|
+
throw new Error("The browser source is no longer selected.");
|
|
1409
|
+
}
|
|
1284
1410
|
if (!browserSessionId || !target) throw new Error("No browser tab is selected.");
|
|
1285
1411
|
const observation = await client.observeBrowserTarget(workspaceId, browserSessionId, target.id);
|
|
1286
|
-
if (!
|
|
1412
|
+
if (!isCurrentSource() || observation.browserSessionId !== browserSessionId || !sameObservationTarget(observation, selectedTargetRef.current)) {
|
|
1287
1413
|
throw new Error("The browser page changed. Open the options again.");
|
|
1288
1414
|
}
|
|
1289
1415
|
return observation;
|
|
1290
|
-
}, [browserSessionId, client, workspaceId]);
|
|
1416
|
+
}, [browserSessionId, client, enabled, isCurrentSource, workspaceId]);
|
|
1291
1417
|
const actFromObservation = useCallback5(
|
|
1292
1418
|
async (action, observation) => {
|
|
1293
1419
|
if (!sameObservationTarget(observation, selectedTargetRef.current)) {
|
|
@@ -1295,6 +1421,7 @@ function useBrowserSession(options) {
|
|
|
1295
1421
|
}
|
|
1296
1422
|
return await dispatchAction(action, crypto.randomUUID(), {
|
|
1297
1423
|
browserSessionId: observation.browserSessionId,
|
|
1424
|
+
controllerGeneration: observation.target.controllerGeneration,
|
|
1298
1425
|
targetId: observation.target.id,
|
|
1299
1426
|
targetGeneration: observation.target.targetGeneration,
|
|
1300
1427
|
documentGeneration: observation.target.documentGeneration,
|
|
@@ -1305,6 +1432,9 @@ function useBrowserSession(options) {
|
|
|
1305
1432
|
);
|
|
1306
1433
|
const diagnostics = useCallback5(
|
|
1307
1434
|
async (diagnosticOptions = {}) => {
|
|
1435
|
+
if (!enabled || !isCurrentSource()) {
|
|
1436
|
+
throw new Error("The browser source is no longer selected.");
|
|
1437
|
+
}
|
|
1308
1438
|
const targetId = selectedTargetIdRef.current;
|
|
1309
1439
|
if (!browserSessionId || !targetId) {
|
|
1310
1440
|
throw new Error("No browser tab is selected.");
|
|
@@ -1316,16 +1446,19 @@ function useBrowserSession(options) {
|
|
|
1316
1446
|
diagnosticOptions
|
|
1317
1447
|
);
|
|
1318
1448
|
},
|
|
1319
|
-
[browserSessionId, client, workspaceId]
|
|
1449
|
+
[browserSessionId, client, enabled, isCurrentSource, workspaceId]
|
|
1320
1450
|
);
|
|
1321
1451
|
const readClipboard = useCallback5(async () => {
|
|
1452
|
+
if (!enabled || !isCurrentSource()) {
|
|
1453
|
+
throw new Error("The browser source is no longer selected.");
|
|
1454
|
+
}
|
|
1322
1455
|
if (!browserSessionId) throw new Error("No BrowserSession is selected.");
|
|
1323
1456
|
const clipboard = await client.readBrowserClipboard(workspaceId, browserSessionId);
|
|
1324
|
-
if (clipboard.browserSessionId !== browserSessionId) {
|
|
1457
|
+
if (!isCurrentSource() || clipboard.browserSessionId !== browserSessionId) {
|
|
1325
1458
|
throw new Error("Browser clipboard belongs to another BrowserSession.");
|
|
1326
1459
|
}
|
|
1327
1460
|
return clipboard;
|
|
1328
|
-
}, [browserSessionId, client, workspaceId]);
|
|
1461
|
+
}, [browserSessionId, client, enabled, isCurrentSource, workspaceId]);
|
|
1329
1462
|
return {
|
|
1330
1463
|
session: visible.session,
|
|
1331
1464
|
targets: visible.targets,
|
|
@@ -1357,7 +1490,8 @@ function emptyState4(browserSessionId, loading) {
|
|
|
1357
1490
|
loading,
|
|
1358
1491
|
mutating: false,
|
|
1359
1492
|
error: null,
|
|
1360
|
-
inputFailure: null
|
|
1493
|
+
inputFailure: null,
|
|
1494
|
+
actionResultOrder: 0
|
|
1361
1495
|
};
|
|
1362
1496
|
}
|
|
1363
1497
|
function chooseTarget(targets, preferredId) {
|
|
@@ -4546,4 +4680,4 @@ export {
|
|
|
4546
4680
|
useBrowserFrameStream,
|
|
4547
4681
|
BrowserViewer
|
|
4548
4682
|
};
|
|
4549
|
-
//# sourceMappingURL=chunk-
|
|
4683
|
+
//# sourceMappingURL=chunk-2OQA3CPB.js.map
|