@opengeni/sdk 0.48.0 → 0.57.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/README.md +147 -1
- package/dist/artifact-client.d.ts +20 -2
- package/dist/artifacts.d.ts +4 -0
- package/dist/artifacts.js +11 -0
- package/dist/artifacts.js.map +1 -0
- package/dist/{chunk-V5F253OG.js → chunk-GU6JF75T.js} +6 -3
- package/dist/chunk-GU6JF75T.js.map +1 -0
- package/dist/chunk-HJ3HHUT5.js +222 -0
- package/dist/chunk-HJ3HHUT5.js.map +1 -0
- package/dist/{chunk-KIHGPM7H.js → chunk-JDLDDRNE.js} +20 -14
- package/dist/chunk-JDLDDRNE.js.map +1 -0
- package/dist/chunk-JRPFWI6T.js +128 -0
- package/dist/chunk-JRPFWI6T.js.map +1 -0
- package/dist/{chunk-MBGBLVUV.js → chunk-PKQ377ED.js} +1725 -555
- package/dist/chunk-PKQ377ED.js.map +1 -0
- package/dist/chunk-ST5DDKJP.js +987 -0
- package/dist/chunk-ST5DDKJP.js.map +1 -0
- package/dist/chunk-VWE2QIVO.js +1162 -0
- package/dist/chunk-VWE2QIVO.js.map +1 -0
- package/dist/chunk-VYCTL62C.js +230 -0
- package/dist/chunk-VYCTL62C.js.map +1 -0
- package/dist/{chunk-DXDL7EEW.js → chunk-YKZME56C.js} +197 -113
- package/dist/chunk-YKZME56C.js.map +1 -0
- package/dist/client.d.ts +240 -16
- package/dist/codex-realtime-controller.d.ts +9 -6
- package/dist/codex-realtime-controller.js +2 -2
- package/dist/codex-realtime-lifecycle.d.ts +1 -1
- package/dist/codex-realtime-v3.d.ts +3 -3
- package/dist/codex-realtime.d.ts +1 -1
- package/dist/company-profile.d.ts +100 -0
- package/dist/core.d.ts +5 -5
- package/dist/core.js +10 -5
- package/dist/desktop.d.ts +9 -1
- package/dist/editable-artifact-resources.d.ts +96 -0
- package/dist/editable-artifacts/browser-session.d.ts +35 -0
- package/dist/editable-artifacts/controller.d.ts +60 -0
- package/dist/editable-artifacts/errors.d.ts +23 -0
- package/dist/editable-artifacts/http-live-transport.d.ts +46 -0
- package/dist/editable-artifacts/index.d.ts +19 -0
- package/dist/editable-artifacts/pool.d.ts +15 -0
- package/dist/editable-artifacts/session.d.ts +96 -0
- package/dist/editable-artifacts/storage.d.ts +72 -0
- package/dist/editable-artifacts/types.d.ts +416 -0
- package/dist/editable-artifacts/worker/browser-client.d.ts +80 -0
- package/dist/editable-artifacts/worker/browser-entry.d.ts +6 -0
- package/dist/editable-artifacts/worker/kernel-adapter.d.ts +45 -0
- package/dist/editable-artifacts/worker/rpc-protocol.d.ts +92 -0
- package/dist/editable-artifacts/worker/runtime.d.ts +66 -0
- package/dist/editable-artifacts/worker/wire-codec.d.ts +52 -0
- package/dist/editable-artifacts-worker.d.ts +8 -0
- package/dist/editable-artifacts-worker.js +1708 -0
- package/dist/editable-artifacts-worker.js.map +1 -0
- package/dist/editable-artifacts.d.ts +6 -0
- package/dist/editable-artifacts.js +5954 -0
- package/dist/editable-artifacts.js.map +1 -0
- package/dist/gateway-realtime-transport.d.ts +2 -1
- package/dist/gateway-realtime-transport.js +5 -3
- package/dist/index.d.ts +45 -35
- package/dist/index.js +134 -64
- package/dist/index.js.map +1 -1
- package/dist/interaction-revision-stream.d.ts +11 -0
- package/dist/interaction.d.ts +1484 -0
- package/dist/interaction.js +81 -0
- package/dist/interaction.js.map +1 -0
- package/dist/memory-slack-client.d.ts +13 -0
- package/dist/memory-slack-delivery.d.ts +99 -0
- package/dist/memory-slack.d.ts +4 -0
- package/dist/memory-slack.js +44 -0
- package/dist/memory-slack.js.map +1 -0
- package/dist/proxy.d.ts +3 -3
- package/dist/realtime.d.ts +14 -14
- package/dist/realtime.js +11 -7
- package/dist/realtime.js.map +1 -1
- package/dist/retained-artifacts.d.ts +12 -0
- package/dist/stream.d.ts +1 -1
- package/dist/terminal.d.ts +1 -1
- package/dist/types.d.ts +1347 -34
- package/dist/workspace-control-stream.d.ts +2 -2
- package/dist/workspace-live-stream.d.ts +14 -0
- package/dist/workspace-state.d.ts +1 -1
- package/package.json +29 -3
- package/src/artifact-client.ts +129 -0
- package/src/artifacts.ts +17 -0
- package/src/client.ts +3022 -910
- package/src/codex-realtime-controller.ts +25 -7
- package/src/codex-realtime-lifecycle.ts +1 -0
- package/src/company-profile.ts +92 -0
- package/src/desktop.ts +11 -1
- package/src/editable-artifact-resources.ts +119 -0
- package/src/editable-artifacts/browser-session.ts +176 -0
- package/src/editable-artifacts/controller.ts +2632 -0
- package/src/editable-artifacts/errors.ts +52 -0
- package/src/editable-artifacts/http-live-transport.ts +1449 -0
- package/src/editable-artifacts/index.ts +175 -0
- package/src/editable-artifacts/pool.ts +81 -0
- package/src/editable-artifacts/session.ts +778 -0
- package/src/editable-artifacts/storage.ts +1718 -0
- package/src/editable-artifacts/types.ts +499 -0
- package/src/editable-artifacts/worker/browser-client.ts +1167 -0
- package/src/editable-artifacts/worker/browser-entry.ts +57 -0
- package/src/editable-artifacts/worker/kernel-adapter.ts +1039 -0
- package/src/editable-artifacts/worker/rpc-protocol.ts +622 -0
- package/src/editable-artifacts/worker/runtime.ts +1204 -0
- package/src/editable-artifacts/worker/wire-codec.ts +852 -0
- package/src/editable-artifacts-worker.ts +8 -0
- package/src/editable-artifacts.ts +6 -0
- package/src/errors.ts +16 -2
- package/src/gateway-realtime-transport.ts +252 -109
- package/src/index.ts +215 -1
- package/src/interaction-revision-stream.ts +117 -0
- package/src/interaction.ts +2874 -0
- package/src/memory-slack-client.ts +71 -0
- package/src/memory-slack-delivery.ts +128 -0
- package/src/memory-slack.ts +19 -0
- package/src/realtime.ts +14 -4
- package/src/retained-artifacts.ts +326 -0
- package/src/types.ts +1636 -52
- package/src/workspace-live-stream.ts +137 -0
- package/dist/chunk-DXDL7EEW.js.map +0 -1
- package/dist/chunk-KIHGPM7H.js.map +0 -1
- package/dist/chunk-MBGBLVUV.js.map +0 -1
- package/dist/chunk-V5F253OG.js.map +0 -1
|
@@ -0,0 +1,2874 @@
|
|
|
1
|
+
import type { OpenGeniRequestOptions } from "./client";
|
|
2
|
+
import type { RetainedArtifactReference } from "./types";
|
|
3
|
+
|
|
4
|
+
/** Public Browser/Computer protocol version. Driver and provider details stay private. */
|
|
5
|
+
export const INTERACTION_PROTOCOL_VERSION = 1 as const;
|
|
6
|
+
export const BROWSER_CONTROL_WEBSOCKET_PROTOCOL = "opengeni.browser.v1" as const;
|
|
7
|
+
export const COMPUTER_CONTROL_WEBSOCKET_PROTOCOL = "opengeni.computer.v1" as const;
|
|
8
|
+
export const BROWSER_CONTROL_WEBSOCKET_BEARER_PREFIX = "opengeni.auth." as const;
|
|
9
|
+
export const BROWSER_CONTROL_MAX_FRAME_HEADER_BYTES = 64 * 1024;
|
|
10
|
+
export const BROWSER_FRAME_MAX_BYTES = 24 * 1024 * 1024;
|
|
11
|
+
export const BROWSER_FRAME_MAX_DIMENSION = 32_768;
|
|
12
|
+
export const BROWSER_FRAME_MAX_PIXELS = 100_000_000;
|
|
13
|
+
|
|
14
|
+
/** Latest-wins invalidation cursor for workspace Browser/Computer resources. */
|
|
15
|
+
export type WorkspaceInteractionRevisionEvent = {
|
|
16
|
+
workspaceId: string;
|
|
17
|
+
sequence: number;
|
|
18
|
+
revision: number;
|
|
19
|
+
type: "workspace.interaction.changed";
|
|
20
|
+
occurredAt: string;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export type InteractionJsonValue =
|
|
24
|
+
| null
|
|
25
|
+
| string
|
|
26
|
+
| number
|
|
27
|
+
| boolean
|
|
28
|
+
| InteractionJsonValue[]
|
|
29
|
+
| { [key: string]: InteractionJsonValue };
|
|
30
|
+
|
|
31
|
+
export type InteractionPlacement =
|
|
32
|
+
| { kind: "sandbox_group"; sandboxGroupId: string }
|
|
33
|
+
| { kind: "connected_machine"; sandboxId: string }
|
|
34
|
+
| { kind: "attached_device"; deviceId: string }
|
|
35
|
+
| { kind: "external_provider"; providerId: string; placementId: string };
|
|
36
|
+
|
|
37
|
+
export type AttachedBrowserDeviceCapabilities = {
|
|
38
|
+
tabInventory: boolean;
|
|
39
|
+
debuggerAttachment: boolean;
|
|
40
|
+
semanticObservation: boolean;
|
|
41
|
+
screenshots: boolean;
|
|
42
|
+
liveFrames: boolean;
|
|
43
|
+
humanInput: boolean;
|
|
44
|
+
diagnostics: boolean;
|
|
45
|
+
rawCdp: boolean;
|
|
46
|
+
linkedComputer: boolean;
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
/** One live browser-profile endpoint on an enrolled machine. Saved, reusable
|
|
50
|
+
* login state is represented separately by BrowserIdentity. */
|
|
51
|
+
export type AttachedBrowserDevice = {
|
|
52
|
+
id: string;
|
|
53
|
+
accountId: string;
|
|
54
|
+
workspaceId: string;
|
|
55
|
+
enrollmentId: string;
|
|
56
|
+
name: string;
|
|
57
|
+
profileLabel: string | null;
|
|
58
|
+
browserName: string;
|
|
59
|
+
browserVersion: string;
|
|
60
|
+
extensionVersion: string;
|
|
61
|
+
platform: "linux" | "macos" | "windows";
|
|
62
|
+
architecture: "x64" | "arm64";
|
|
63
|
+
state: "connected" | "disconnected";
|
|
64
|
+
connectionGeneration: string;
|
|
65
|
+
inventoryRevision: number;
|
|
66
|
+
tabCount: number;
|
|
67
|
+
capabilities: AttachedBrowserDeviceCapabilities;
|
|
68
|
+
lastSeenAt: string;
|
|
69
|
+
disconnectedAt: string | null;
|
|
70
|
+
createdAt: string;
|
|
71
|
+
updatedAt: string;
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
export type AttachedBrowserDeviceListResponse = {
|
|
75
|
+
revision: number;
|
|
76
|
+
devices: AttachedBrowserDevice[];
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
export type InteractionControllerBinding = {
|
|
80
|
+
controllerId: string;
|
|
81
|
+
controllerGeneration: string;
|
|
82
|
+
placementInstanceId: string;
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
export type InteractionAssociation = {
|
|
86
|
+
sessionId: string;
|
|
87
|
+
turnId: string | null;
|
|
88
|
+
attemptId: string | null;
|
|
89
|
+
relationship: "created" | "using" | "observing" | "related";
|
|
90
|
+
actorSubjectId: string;
|
|
91
|
+
lastUsedAt: string;
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
export type InteractionLifecycle =
|
|
95
|
+
| "starting"
|
|
96
|
+
| "active"
|
|
97
|
+
| "suspending"
|
|
98
|
+
| "suspended"
|
|
99
|
+
| "restoring"
|
|
100
|
+
| "repair_required"
|
|
101
|
+
| "lost"
|
|
102
|
+
| "ending"
|
|
103
|
+
| "ended"
|
|
104
|
+
| "failed";
|
|
105
|
+
|
|
106
|
+
export type BrowserSessionCapabilities = {
|
|
107
|
+
semanticObservation: boolean;
|
|
108
|
+
screenshots: boolean;
|
|
109
|
+
liveFrames: boolean;
|
|
110
|
+
humanInput: boolean;
|
|
111
|
+
tabs: boolean;
|
|
112
|
+
downloads: boolean;
|
|
113
|
+
uploads: boolean;
|
|
114
|
+
clipboard: boolean;
|
|
115
|
+
permissions: boolean;
|
|
116
|
+
diagnostics: boolean;
|
|
117
|
+
rawCdp: boolean;
|
|
118
|
+
linkedComputer: boolean;
|
|
119
|
+
privateCheckpoint: boolean;
|
|
120
|
+
identityPublication: boolean;
|
|
121
|
+
parallelTargets: boolean;
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
export type BrowserSession = {
|
|
125
|
+
id: string;
|
|
126
|
+
accountId: string;
|
|
127
|
+
workspaceId: string;
|
|
128
|
+
name: string;
|
|
129
|
+
lifecycle: InteractionLifecycle;
|
|
130
|
+
placement: InteractionPlacement;
|
|
131
|
+
controller: InteractionControllerBinding | null;
|
|
132
|
+
driverId: string;
|
|
133
|
+
engine: "chromium" | "chrome" | "firefox" | "webkit" | "lightpanda" | "external";
|
|
134
|
+
engineVersion: string | null;
|
|
135
|
+
headless: boolean;
|
|
136
|
+
identityId: string | null;
|
|
137
|
+
baseRevisionId: string | null;
|
|
138
|
+
networkRouteId: string | null;
|
|
139
|
+
linkedComputerSessionId: string | null;
|
|
140
|
+
capabilities: BrowserSessionCapabilities;
|
|
141
|
+
associations: InteractionAssociation[];
|
|
142
|
+
createdBySubjectId: string;
|
|
143
|
+
createdAt: string;
|
|
144
|
+
lastUsedAt: string;
|
|
145
|
+
failureCode: string | null;
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
export type BrowserClipboard = {
|
|
149
|
+
browserSessionId: string;
|
|
150
|
+
controllerGeneration: string;
|
|
151
|
+
revision: number;
|
|
152
|
+
text: string;
|
|
153
|
+
source: "empty" | "write" | "clear" | "copy" | "paste";
|
|
154
|
+
sourceTargetId: string | null;
|
|
155
|
+
updatedAt: string | null;
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
export type InteractionCredentialAuthorityRef = {
|
|
159
|
+
connectionId: string;
|
|
160
|
+
connectionSubjectId: string | null;
|
|
161
|
+
providerDomain: string;
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
export type NetworkRouteConfiguration =
|
|
165
|
+
| { kind: "direct" }
|
|
166
|
+
| {
|
|
167
|
+
kind: "proxy";
|
|
168
|
+
protocol: "http" | "https" | "socks5";
|
|
169
|
+
host: string;
|
|
170
|
+
port: number;
|
|
171
|
+
credential: InteractionCredentialAuthorityRef | null;
|
|
172
|
+
}
|
|
173
|
+
| {
|
|
174
|
+
kind: "managed";
|
|
175
|
+
providerId: string;
|
|
176
|
+
routeId: string;
|
|
177
|
+
egressClass: "datacenter" | "residential" | "isp";
|
|
178
|
+
region: string | null;
|
|
179
|
+
credential: InteractionCredentialAuthorityRef | null;
|
|
180
|
+
}
|
|
181
|
+
| { kind: "tunnel"; placement: InteractionPlacement; tunnelId: string };
|
|
182
|
+
|
|
183
|
+
export type NetworkRouteConsistency = {
|
|
184
|
+
dns: "placement" | "proxy" | "provider";
|
|
185
|
+
expectedPublicIp: string | null;
|
|
186
|
+
expectedRegion: string | null;
|
|
187
|
+
locale: string | null;
|
|
188
|
+
timezone: string | null;
|
|
189
|
+
geolocation: {
|
|
190
|
+
latitude: number;
|
|
191
|
+
longitude: number;
|
|
192
|
+
accuracyMeters: number;
|
|
193
|
+
} | null;
|
|
194
|
+
webRtc: "default" | "disable_non_proxied_udp" | "proxy_only";
|
|
195
|
+
stability: "session" | "sticky" | "persistent";
|
|
196
|
+
};
|
|
197
|
+
|
|
198
|
+
export type NetworkRoute = {
|
|
199
|
+
id: string;
|
|
200
|
+
accountId: string;
|
|
201
|
+
workspaceId: string;
|
|
202
|
+
name: string;
|
|
203
|
+
status: "active" | "archived";
|
|
204
|
+
configuration: NetworkRouteConfiguration;
|
|
205
|
+
consistency: NetworkRouteConsistency;
|
|
206
|
+
version: number;
|
|
207
|
+
createdBySubjectId: string;
|
|
208
|
+
createdAt: string;
|
|
209
|
+
updatedAt: string;
|
|
210
|
+
};
|
|
211
|
+
|
|
212
|
+
export type NetworkRouteListResponse = { revision: number; routes: NetworkRoute[] };
|
|
213
|
+
export type CreateNetworkRouteRequest = {
|
|
214
|
+
operationId: string;
|
|
215
|
+
name: string;
|
|
216
|
+
configuration: NetworkRouteConfiguration;
|
|
217
|
+
consistency: NetworkRouteConsistency;
|
|
218
|
+
};
|
|
219
|
+
export type UpdateNetworkRouteRequest = {
|
|
220
|
+
operationId: string;
|
|
221
|
+
expectedVersion: number;
|
|
222
|
+
name?: string | undefined;
|
|
223
|
+
status?: "active" | "archived" | undefined;
|
|
224
|
+
configuration?: NetworkRouteConfiguration | undefined;
|
|
225
|
+
consistency?: NetworkRouteConsistency | undefined;
|
|
226
|
+
};
|
|
227
|
+
export type NetworkRouteMutationResponse = {
|
|
228
|
+
route: NetworkRoute;
|
|
229
|
+
operationId: string;
|
|
230
|
+
replayed: boolean;
|
|
231
|
+
};
|
|
232
|
+
|
|
233
|
+
export type SiteAuthFieldPurpose = "identifier" | "password" | "secret" | "totp";
|
|
234
|
+
export type SiteAuthAuthority =
|
|
235
|
+
| {
|
|
236
|
+
id: string;
|
|
237
|
+
kind: "connection_fields";
|
|
238
|
+
label: string;
|
|
239
|
+
credential: InteractionCredentialAuthorityRef;
|
|
240
|
+
fields: Array<{
|
|
241
|
+
id: string;
|
|
242
|
+
purpose: SiteAuthFieldPurpose;
|
|
243
|
+
credentialKey: string;
|
|
244
|
+
digits?: number | undefined;
|
|
245
|
+
periodSeconds?: number | undefined;
|
|
246
|
+
algorithm?: "sha1" | "sha256" | "sha512" | undefined;
|
|
247
|
+
}>;
|
|
248
|
+
}
|
|
249
|
+
| {
|
|
250
|
+
id: string;
|
|
251
|
+
kind: "human";
|
|
252
|
+
label: string;
|
|
253
|
+
fields: Array<{ id: string; purpose: SiteAuthFieldPurpose }>;
|
|
254
|
+
}
|
|
255
|
+
| {
|
|
256
|
+
id: string;
|
|
257
|
+
kind: "external_provider";
|
|
258
|
+
label: string;
|
|
259
|
+
adapterId: string;
|
|
260
|
+
connectionId: string;
|
|
261
|
+
credential: InteractionCredentialAuthorityRef | null;
|
|
262
|
+
};
|
|
263
|
+
|
|
264
|
+
export type SiteAuthMethod = {
|
|
265
|
+
id: string;
|
|
266
|
+
kind: "password" | "sso" | "magic_link" | "passkey" | "external";
|
|
267
|
+
label: string;
|
|
268
|
+
authorityIds: string[];
|
|
269
|
+
};
|
|
270
|
+
|
|
271
|
+
export type SiteAuthHealthPolicy = {
|
|
272
|
+
mode: "on_use" | "maintained";
|
|
273
|
+
intervalSeconds: number | null;
|
|
274
|
+
automaticRepair: boolean;
|
|
275
|
+
};
|
|
276
|
+
|
|
277
|
+
export type SiteAuthConnectionConfiguration = {
|
|
278
|
+
name: string;
|
|
279
|
+
accountLabel: string;
|
|
280
|
+
origins: string[];
|
|
281
|
+
loginUrl: string | null;
|
|
282
|
+
verificationUrlPrefixes: string[];
|
|
283
|
+
authorities: SiteAuthAuthority[];
|
|
284
|
+
methods: SiteAuthMethod[];
|
|
285
|
+
preferredIdentityId: string | null;
|
|
286
|
+
preferredPlacement: InteractionPlacement | null;
|
|
287
|
+
preferredNetworkRouteId: string | null;
|
|
288
|
+
healthPolicy: SiteAuthHealthPolicy;
|
|
289
|
+
};
|
|
290
|
+
|
|
291
|
+
export type SiteAuthConnection = SiteAuthConnectionConfiguration & {
|
|
292
|
+
id: string;
|
|
293
|
+
accountId: string;
|
|
294
|
+
workspaceId: string;
|
|
295
|
+
status: "active" | "archived";
|
|
296
|
+
verificationState: "unknown" | "verified" | "needs_repair" | "failed";
|
|
297
|
+
lastVerifiedAt: string | null;
|
|
298
|
+
lastVerifiedUrl: string | null;
|
|
299
|
+
lastCheckedAt: string | null;
|
|
300
|
+
nextCheckAt: string | null;
|
|
301
|
+
maintenance: {
|
|
302
|
+
action: "health_check" | "repair";
|
|
303
|
+
sessionId: string | null;
|
|
304
|
+
dueAt: string;
|
|
305
|
+
startedAt: string | null;
|
|
306
|
+
} | null;
|
|
307
|
+
repairCode: string | null;
|
|
308
|
+
version: number;
|
|
309
|
+
createdBySubjectId: string;
|
|
310
|
+
createdAt: string;
|
|
311
|
+
updatedAt: string;
|
|
312
|
+
};
|
|
313
|
+
|
|
314
|
+
export type SiteAuthConnectionListResponse = {
|
|
315
|
+
revision: number;
|
|
316
|
+
connections: SiteAuthConnection[];
|
|
317
|
+
};
|
|
318
|
+
export type CreateSiteAuthConnectionRequest = SiteAuthConnectionConfiguration & {
|
|
319
|
+
operationId: string;
|
|
320
|
+
};
|
|
321
|
+
export type UpdateSiteAuthConnectionRequest = Partial<SiteAuthConnectionConfiguration> & {
|
|
322
|
+
operationId: string;
|
|
323
|
+
expectedVersion: number;
|
|
324
|
+
status?: "active" | "archived" | undefined;
|
|
325
|
+
};
|
|
326
|
+
export type SiteAuthConnectionMutationResponse = {
|
|
327
|
+
connection: SiteAuthConnection;
|
|
328
|
+
operationId: string;
|
|
329
|
+
replayed: boolean;
|
|
330
|
+
};
|
|
331
|
+
|
|
332
|
+
export type AuthRun = {
|
|
333
|
+
id: string;
|
|
334
|
+
accountId: string;
|
|
335
|
+
workspaceId: string;
|
|
336
|
+
siteAuthConnectionId: string;
|
|
337
|
+
browserSessionId: string;
|
|
338
|
+
targetId: string;
|
|
339
|
+
controllerGeneration: string;
|
|
340
|
+
targetGeneration: string;
|
|
341
|
+
documentGeneration: string | null;
|
|
342
|
+
purpose: "authenticate" | "health_check" | "repair";
|
|
343
|
+
methodId: string | null;
|
|
344
|
+
authorityId: string | null;
|
|
345
|
+
state:
|
|
346
|
+
| "discovering"
|
|
347
|
+
| "awaiting_choice"
|
|
348
|
+
| "awaiting_secret"
|
|
349
|
+
| "awaiting_external_action"
|
|
350
|
+
| "working"
|
|
351
|
+
| "verified"
|
|
352
|
+
| "failed"
|
|
353
|
+
| "cancelled";
|
|
354
|
+
choices: Array<{ id: string; label: string; methodId: string }>;
|
|
355
|
+
pendingFields: Array<{ id: string; label: string; purpose: SiteAuthFieldPurpose }>;
|
|
356
|
+
externalAction: {
|
|
357
|
+
kind: "push" | "security_key" | "passkey" | "device" | "human" | "other";
|
|
358
|
+
label: string;
|
|
359
|
+
expiresAt: string | null;
|
|
360
|
+
} | null;
|
|
361
|
+
interventionId: string | null;
|
|
362
|
+
verifiedUrl: string | null;
|
|
363
|
+
failureCode: string | null;
|
|
364
|
+
version: number;
|
|
365
|
+
operationId: string;
|
|
366
|
+
createdBySubjectId: string;
|
|
367
|
+
createdAt: string;
|
|
368
|
+
updatedAt: string;
|
|
369
|
+
settledAt: string | null;
|
|
370
|
+
};
|
|
371
|
+
|
|
372
|
+
export type AuthRunListResponse = { runs: AuthRun[] };
|
|
373
|
+
export type AuthRunMutationResponse = { run: AuthRun; operationId: string; replayed: boolean };
|
|
374
|
+
export type StartAuthRunRequest = {
|
|
375
|
+
operationId: string;
|
|
376
|
+
siteAuthConnectionId: string;
|
|
377
|
+
targetId: string;
|
|
378
|
+
expectedTargetGeneration: string;
|
|
379
|
+
expectedDocumentGeneration: string | null;
|
|
380
|
+
purpose?: "authenticate" | "health_check" | "repair" | undefined;
|
|
381
|
+
methodId?: string | undefined;
|
|
382
|
+
authorityId?: string | undefined;
|
|
383
|
+
};
|
|
384
|
+
export type ReportAuthRunRequest = {
|
|
385
|
+
operationId: string;
|
|
386
|
+
expectedVersion: number;
|
|
387
|
+
methodId?: string | undefined;
|
|
388
|
+
authorityId?: string | undefined;
|
|
389
|
+
state:
|
|
390
|
+
| "awaiting_choice"
|
|
391
|
+
| "awaiting_secret"
|
|
392
|
+
| "awaiting_external_action"
|
|
393
|
+
| "working"
|
|
394
|
+
| "failed"
|
|
395
|
+
| "cancelled";
|
|
396
|
+
choices?: AuthRun["choices"] | undefined;
|
|
397
|
+
pendingFields?: AuthRun["pendingFields"] | undefined;
|
|
398
|
+
externalAction?: AuthRun["externalAction"] | undefined;
|
|
399
|
+
failureCode?: string | null | undefined;
|
|
400
|
+
};
|
|
401
|
+
export type ProtectedAuthFillRequest = {
|
|
402
|
+
operationId: string;
|
|
403
|
+
expectedVersion: number;
|
|
404
|
+
expectedTargetGeneration: string;
|
|
405
|
+
expectedDocumentGeneration: string | null;
|
|
406
|
+
expectedFrameId: string | null;
|
|
407
|
+
authorityId: string;
|
|
408
|
+
fields: Array<{ fieldId: string; locator: BrowserLocator }>;
|
|
409
|
+
submit:
|
|
410
|
+
| { type: "none" }
|
|
411
|
+
| { type: "click"; locator: BrowserLocator }
|
|
412
|
+
| { type: "press"; key: string; locator?: BrowserLocator | undefined };
|
|
413
|
+
};
|
|
414
|
+
export type ProtectedAuthFillResponse = {
|
|
415
|
+
run: AuthRun;
|
|
416
|
+
status: "submitted" | "working" | "needs_human" | "stale" | "failed";
|
|
417
|
+
operationId: string;
|
|
418
|
+
replayed: boolean;
|
|
419
|
+
};
|
|
420
|
+
export type ExternalAuthRunRequest = {
|
|
421
|
+
operationId: string;
|
|
422
|
+
expectedVersion: number;
|
|
423
|
+
action: "start" | "poll";
|
|
424
|
+
};
|
|
425
|
+
export type ExternalAuthRunResponse = {
|
|
426
|
+
run: AuthRun;
|
|
427
|
+
status: "working" | "needs_human" | "ready_to_verify" | "failed";
|
|
428
|
+
operationId: string;
|
|
429
|
+
replayed: boolean;
|
|
430
|
+
};
|
|
431
|
+
export type ExternalAuthInteractiveRequest = {
|
|
432
|
+
operationId: string;
|
|
433
|
+
expectedVersion: number;
|
|
434
|
+
};
|
|
435
|
+
export type ExternalAuthInteractiveResponse = {
|
|
436
|
+
authRunId: string;
|
|
437
|
+
url: string;
|
|
438
|
+
expiresAt: string | null;
|
|
439
|
+
};
|
|
440
|
+
export type VerifyAuthRunRequest = { operationId: string; expectedVersion: number };
|
|
441
|
+
|
|
442
|
+
export type InteractionIntervention = {
|
|
443
|
+
id: string;
|
|
444
|
+
accountId: string;
|
|
445
|
+
workspaceId: string;
|
|
446
|
+
resourceKind: "browser_session" | "computer_session";
|
|
447
|
+
resourceId: string;
|
|
448
|
+
targetId: string;
|
|
449
|
+
controllerGeneration: string;
|
|
450
|
+
targetGeneration: string;
|
|
451
|
+
documentGeneration: string | null;
|
|
452
|
+
kind: "manual_login" | "mfa" | "external_action" | "confirmation" | "other";
|
|
453
|
+
reason: string;
|
|
454
|
+
status: "open" | "completed" | "dismissed" | "expired" | "cancelled";
|
|
455
|
+
authRunId: string | null;
|
|
456
|
+
originatingSessionId: string;
|
|
457
|
+
originatingTurnId: string | null;
|
|
458
|
+
originatingAttemptId: string | null;
|
|
459
|
+
originatingToolOperationId: string | null;
|
|
460
|
+
responseActorSubjectId: string | null;
|
|
461
|
+
version: number;
|
|
462
|
+
operationId: string;
|
|
463
|
+
expiresAt: string;
|
|
464
|
+
createdAt: string;
|
|
465
|
+
updatedAt: string;
|
|
466
|
+
settledAt: string | null;
|
|
467
|
+
};
|
|
468
|
+
export type InteractionInterventionListResponse = {
|
|
469
|
+
interventions: InteractionIntervention[];
|
|
470
|
+
};
|
|
471
|
+
export type CreateInteractionInterventionRequest = {
|
|
472
|
+
operationId: string;
|
|
473
|
+
resourceKind: "browser_session" | "computer_session";
|
|
474
|
+
resourceId: string;
|
|
475
|
+
targetId: string;
|
|
476
|
+
expectedControllerGeneration: string;
|
|
477
|
+
expectedTargetGeneration: string;
|
|
478
|
+
expectedDocumentGeneration: string | null;
|
|
479
|
+
kind: InteractionIntervention["kind"];
|
|
480
|
+
reason: string;
|
|
481
|
+
authRunId?: string | undefined;
|
|
482
|
+
expiresInSeconds?: number | undefined;
|
|
483
|
+
};
|
|
484
|
+
export type ResolveInteractionInterventionRequest = {
|
|
485
|
+
operationId: string;
|
|
486
|
+
expectedVersion: number;
|
|
487
|
+
outcome: "completed" | "dismissed";
|
|
488
|
+
};
|
|
489
|
+
export type InteractionInterventionMutationResponse = {
|
|
490
|
+
intervention: InteractionIntervention;
|
|
491
|
+
operationId: string;
|
|
492
|
+
replayed: boolean;
|
|
493
|
+
};
|
|
494
|
+
|
|
495
|
+
export type BrowserIdentityStatus = "active" | "archived";
|
|
496
|
+
export type BrowserRevisionComponentKind =
|
|
497
|
+
| "chromium_profile"
|
|
498
|
+
| "normalized_web_state"
|
|
499
|
+
| "provider_snapshot";
|
|
500
|
+
export type BrowserRevisionPortability = "portable" | "provider_bound" | "placement_bound";
|
|
501
|
+
|
|
502
|
+
export type BrowserRevisionMaterialization = {
|
|
503
|
+
portability: BrowserRevisionPortability;
|
|
504
|
+
reason: string | null;
|
|
505
|
+
platform: "linux" | "macos" | "windows" | null;
|
|
506
|
+
architecture: "x64" | "arm64" | null;
|
|
507
|
+
engine: "chromium" | "chrome" | "firefox" | "webkit" | "lightpanda" | "external";
|
|
508
|
+
engineVersion: string | null;
|
|
509
|
+
driverId: string;
|
|
510
|
+
driverSchemaVersion: number;
|
|
511
|
+
profileCrypto: "chromium_basic" | "chromium_mock_keychain" | "platform_bound";
|
|
512
|
+
providerId: string | null;
|
|
513
|
+
placement: InteractionPlacement | null;
|
|
514
|
+
};
|
|
515
|
+
|
|
516
|
+
export type BrowserRevisionComponent = {
|
|
517
|
+
id: string;
|
|
518
|
+
kind: BrowserRevisionComponentKind;
|
|
519
|
+
format: string;
|
|
520
|
+
artifactDigest: string;
|
|
521
|
+
sizeBytes: number;
|
|
522
|
+
materialization: BrowserRevisionMaterialization;
|
|
523
|
+
};
|
|
524
|
+
|
|
525
|
+
export type BrowserRevision = {
|
|
526
|
+
id: string;
|
|
527
|
+
accountId: string;
|
|
528
|
+
workspaceId: string;
|
|
529
|
+
identityId: string;
|
|
530
|
+
parentRevisionId: string | null;
|
|
531
|
+
ordinal: number;
|
|
532
|
+
sourceBrowserSessionId: string;
|
|
533
|
+
manifestDigest: string;
|
|
534
|
+
components: BrowserRevisionComponent[];
|
|
535
|
+
createdBySubjectId: string;
|
|
536
|
+
createdAt: string;
|
|
537
|
+
};
|
|
538
|
+
|
|
539
|
+
export type BrowserIdentity = {
|
|
540
|
+
id: string;
|
|
541
|
+
accountId: string;
|
|
542
|
+
workspaceId: string;
|
|
543
|
+
name: string;
|
|
544
|
+
status: BrowserIdentityStatus;
|
|
545
|
+
version: number;
|
|
546
|
+
defaultRevisionId: string | null;
|
|
547
|
+
headGeneration: number;
|
|
548
|
+
revisionCount: number;
|
|
549
|
+
createdBySubjectId: string;
|
|
550
|
+
createdAt: string;
|
|
551
|
+
updatedAt: string;
|
|
552
|
+
};
|
|
553
|
+
|
|
554
|
+
export type BrowserIdentityListResponse = {
|
|
555
|
+
revision: number;
|
|
556
|
+
identities: BrowserIdentity[];
|
|
557
|
+
};
|
|
558
|
+
|
|
559
|
+
export type BrowserRevisionListResponse = {
|
|
560
|
+
identity: BrowserIdentity;
|
|
561
|
+
revisions: BrowserRevision[];
|
|
562
|
+
};
|
|
563
|
+
|
|
564
|
+
export type CreateBrowserIdentityRequest = {
|
|
565
|
+
operationId: string;
|
|
566
|
+
name: string;
|
|
567
|
+
};
|
|
568
|
+
|
|
569
|
+
export type UpdateBrowserIdentityRequest = {
|
|
570
|
+
operationId: string;
|
|
571
|
+
expectedVersion: number;
|
|
572
|
+
name?: string | undefined;
|
|
573
|
+
status?: BrowserIdentityStatus | undefined;
|
|
574
|
+
defaultRevisionId?: string | undefined;
|
|
575
|
+
};
|
|
576
|
+
|
|
577
|
+
export type BrowserIdentityMutationResponse = {
|
|
578
|
+
identity: BrowserIdentity;
|
|
579
|
+
operationId: string;
|
|
580
|
+
replayed: boolean;
|
|
581
|
+
};
|
|
582
|
+
|
|
583
|
+
export type PublishBrowserRevisionRequest = {
|
|
584
|
+
operationId: string;
|
|
585
|
+
identityId: string;
|
|
586
|
+
expectedHeadGeneration: number;
|
|
587
|
+
advanceDefault?: boolean | undefined;
|
|
588
|
+
};
|
|
589
|
+
|
|
590
|
+
export type PublishBrowserRevisionResponse = {
|
|
591
|
+
identity: BrowserIdentity;
|
|
592
|
+
revision: BrowserRevision;
|
|
593
|
+
outcome: "saved_as_default" | "saved_not_default";
|
|
594
|
+
replayed: boolean;
|
|
595
|
+
};
|
|
596
|
+
|
|
597
|
+
export type BrowserTarget = {
|
|
598
|
+
id: string;
|
|
599
|
+
browserSessionId: string;
|
|
600
|
+
controllerGeneration: string;
|
|
601
|
+
targetGeneration: string;
|
|
602
|
+
documentGeneration: string | null;
|
|
603
|
+
kind: "page" | "popup" | "background_page" | "worker";
|
|
604
|
+
title: string;
|
|
605
|
+
url: string;
|
|
606
|
+
selected: boolean;
|
|
607
|
+
attached: boolean;
|
|
608
|
+
createdAt: string;
|
|
609
|
+
};
|
|
610
|
+
|
|
611
|
+
export type BrowserDownloadStatus =
|
|
612
|
+
| "in_progress"
|
|
613
|
+
| "completed"
|
|
614
|
+
| "cancelled"
|
|
615
|
+
| "failed"
|
|
616
|
+
| "unavailable";
|
|
617
|
+
|
|
618
|
+
/** One browser-produced file. Its bytes remain private to the exact browser
|
|
619
|
+
* controller until an explicit save publishes them into the workspace. */
|
|
620
|
+
export type BrowserDownload = {
|
|
621
|
+
id: string;
|
|
622
|
+
browserSessionId: string;
|
|
623
|
+
controllerGeneration: string;
|
|
624
|
+
targetId: string | null;
|
|
625
|
+
filename: string;
|
|
626
|
+
status: BrowserDownloadStatus;
|
|
627
|
+
receivedBytes: number;
|
|
628
|
+
totalBytes: number | null;
|
|
629
|
+
sha256: string | null;
|
|
630
|
+
version: number;
|
|
631
|
+
startedAt: string;
|
|
632
|
+
settledAt: string | null;
|
|
633
|
+
failureCode: string | null;
|
|
634
|
+
};
|
|
635
|
+
|
|
636
|
+
export type BrowserDownloadListResponse = {
|
|
637
|
+
browserSessionId: string;
|
|
638
|
+
controllerGeneration: string;
|
|
639
|
+
downloads: BrowserDownload[];
|
|
640
|
+
};
|
|
641
|
+
|
|
642
|
+
export type BrowserDownloadSaveRequest = {
|
|
643
|
+
operationId: string;
|
|
644
|
+
destinationPath: string;
|
|
645
|
+
overwrite?: boolean | undefined;
|
|
646
|
+
};
|
|
647
|
+
|
|
648
|
+
export type BrowserDownloadSaveResponse = {
|
|
649
|
+
download: BrowserDownload;
|
|
650
|
+
destinationPath: string;
|
|
651
|
+
fileId: string;
|
|
652
|
+
operationId: string;
|
|
653
|
+
replayed: boolean;
|
|
654
|
+
};
|
|
655
|
+
|
|
656
|
+
export type InteractionRect = {
|
|
657
|
+
x: number;
|
|
658
|
+
y: number;
|
|
659
|
+
width: number;
|
|
660
|
+
height: number;
|
|
661
|
+
};
|
|
662
|
+
|
|
663
|
+
export type InteractionRedactedValue = {
|
|
664
|
+
redacted: true;
|
|
665
|
+
reason: "password" | "payment" | "private" | "policy";
|
|
666
|
+
};
|
|
667
|
+
|
|
668
|
+
export type InteractionSemanticNode = {
|
|
669
|
+
ref: string;
|
|
670
|
+
role: string;
|
|
671
|
+
identifier?: string | undefined;
|
|
672
|
+
name?: string | undefined;
|
|
673
|
+
description?: string | undefined;
|
|
674
|
+
value?: string | InteractionRedactedValue | undefined;
|
|
675
|
+
states: string[];
|
|
676
|
+
bounds?: InteractionRect | undefined;
|
|
677
|
+
actions: string[];
|
|
678
|
+
children?: InteractionSemanticNode[] | undefined;
|
|
679
|
+
native?: { platform: "dom" | "mac_ax" | "at_spi" | "uia"; data: unknown } | undefined;
|
|
680
|
+
};
|
|
681
|
+
|
|
682
|
+
export type InteractionSemanticSnapshot = {
|
|
683
|
+
kind: "snapshot";
|
|
684
|
+
roots: InteractionSemanticNode[];
|
|
685
|
+
nodeCount: number;
|
|
686
|
+
};
|
|
687
|
+
|
|
688
|
+
export type InteractionSemanticDiff = {
|
|
689
|
+
kind: "diff";
|
|
690
|
+
baseObservationId: string;
|
|
691
|
+
removedRefs: string[];
|
|
692
|
+
changed: InteractionSemanticNode[];
|
|
693
|
+
};
|
|
694
|
+
|
|
695
|
+
export type InteractionDiagnosticSummary = {
|
|
696
|
+
consoleErrorCount: number;
|
|
697
|
+
failedRequestCount: number;
|
|
698
|
+
downloadCount: number;
|
|
699
|
+
pageErrorCount: number;
|
|
700
|
+
};
|
|
701
|
+
|
|
702
|
+
export type BrowserDialog = {
|
|
703
|
+
type: "alert" | "confirm" | "prompt" | "beforeunload";
|
|
704
|
+
message: string;
|
|
705
|
+
defaultPrompt: string;
|
|
706
|
+
openedAt: string;
|
|
707
|
+
};
|
|
708
|
+
|
|
709
|
+
export type BrowserObservation = {
|
|
710
|
+
protocolVersion: typeof INTERACTION_PROTOCOL_VERSION;
|
|
711
|
+
observationId: string;
|
|
712
|
+
browserSessionId: string;
|
|
713
|
+
target: BrowserTarget;
|
|
714
|
+
frameId: string | null;
|
|
715
|
+
semantic: InteractionSemanticSnapshot | InteractionSemanticDiff | null;
|
|
716
|
+
screenshot: RetainedArtifactReference | null;
|
|
717
|
+
focusedRef: string | null;
|
|
718
|
+
changedRegions: InteractionRect[];
|
|
719
|
+
diagnostics: InteractionDiagnosticSummary;
|
|
720
|
+
dialog: BrowserDialog | null;
|
|
721
|
+
observedAt: string;
|
|
722
|
+
};
|
|
723
|
+
|
|
724
|
+
export type BrowserDiagnosticKind = "console" | "page_error" | "failed_request" | "download";
|
|
725
|
+
|
|
726
|
+
export type BrowserDiagnosticEntry = {
|
|
727
|
+
sequence: number;
|
|
728
|
+
kind: BrowserDiagnosticKind;
|
|
729
|
+
level: "debug" | "info" | "warning" | "error" | null;
|
|
730
|
+
message: string;
|
|
731
|
+
url: string | null;
|
|
732
|
+
method: string | null;
|
|
733
|
+
status: number | null;
|
|
734
|
+
filename: string | null;
|
|
735
|
+
occurredAt: string;
|
|
736
|
+
};
|
|
737
|
+
|
|
738
|
+
export type BrowserDiagnosticBatch = {
|
|
739
|
+
browserSessionId: string;
|
|
740
|
+
controllerGeneration: string;
|
|
741
|
+
targetId: string;
|
|
742
|
+
targetGeneration: string;
|
|
743
|
+
entries: BrowserDiagnosticEntry[];
|
|
744
|
+
cursor: number;
|
|
745
|
+
truncated: boolean;
|
|
746
|
+
};
|
|
747
|
+
|
|
748
|
+
export type BrowserLocator =
|
|
749
|
+
| { kind: "ref"; ref: string }
|
|
750
|
+
| {
|
|
751
|
+
kind: "role";
|
|
752
|
+
role: string;
|
|
753
|
+
name?: string | undefined;
|
|
754
|
+
exact?: boolean | undefined;
|
|
755
|
+
}
|
|
756
|
+
| { kind: "label"; text: string }
|
|
757
|
+
| { kind: "text"; text: string }
|
|
758
|
+
| { kind: "placeholder"; text: string }
|
|
759
|
+
| { kind: "test_id"; value: string }
|
|
760
|
+
| { kind: "css"; selector: string };
|
|
761
|
+
|
|
762
|
+
export type BrowserPermission =
|
|
763
|
+
| "geolocation"
|
|
764
|
+
| "notifications"
|
|
765
|
+
| "camera"
|
|
766
|
+
| "microphone"
|
|
767
|
+
| "midi"
|
|
768
|
+
| "midi_sysex"
|
|
769
|
+
| "sensors"
|
|
770
|
+
| "idle_detection"
|
|
771
|
+
| "local_fonts"
|
|
772
|
+
| "window_management";
|
|
773
|
+
|
|
774
|
+
export type BrowserPermissionSetting = "granted" | "denied" | "prompt";
|
|
775
|
+
|
|
776
|
+
export type BrowserAction =
|
|
777
|
+
| { type: "navigate"; url: string }
|
|
778
|
+
| {
|
|
779
|
+
type: "click";
|
|
780
|
+
locator: BrowserLocator;
|
|
781
|
+
button?: "left" | "right" | "middle" | undefined;
|
|
782
|
+
}
|
|
783
|
+
| { type: "double_click"; locator: BrowserLocator }
|
|
784
|
+
| { type: "hover"; locator: BrowserLocator }
|
|
785
|
+
| { type: "fill"; locator: BrowserLocator; value: string }
|
|
786
|
+
| { type: "type"; locator?: BrowserLocator | undefined; text: string }
|
|
787
|
+
| { type: "press"; locator?: BrowserLocator | undefined; key: string }
|
|
788
|
+
| { type: "select"; locator: BrowserLocator; values: string[] }
|
|
789
|
+
| { type: "check"; locator: BrowserLocator; checked: boolean }
|
|
790
|
+
| {
|
|
791
|
+
type: "scroll";
|
|
792
|
+
locator?: BrowserLocator | undefined;
|
|
793
|
+
deltaX: number;
|
|
794
|
+
deltaY: number;
|
|
795
|
+
}
|
|
796
|
+
| { type: "drag"; from: BrowserLocator; to: BrowserLocator }
|
|
797
|
+
| {
|
|
798
|
+
type: "pointer";
|
|
799
|
+
action: "click" | "double_click" | "move" | "scroll" | "drag";
|
|
800
|
+
x: number;
|
|
801
|
+
y: number;
|
|
802
|
+
endX?: number | undefined;
|
|
803
|
+
endY?: number | undefined;
|
|
804
|
+
deltaX?: number | undefined;
|
|
805
|
+
deltaY?: number | undefined;
|
|
806
|
+
button?: "left" | "right" | "middle" | undefined;
|
|
807
|
+
clickCount?: 1 | 2 | undefined;
|
|
808
|
+
}
|
|
809
|
+
| {
|
|
810
|
+
type: "handle_dialog";
|
|
811
|
+
response: "accept" | "dismiss";
|
|
812
|
+
promptText?: string | undefined;
|
|
813
|
+
}
|
|
814
|
+
| { type: "upload"; locator: BrowserLocator; workspaceFileIds: string[] }
|
|
815
|
+
| {
|
|
816
|
+
type: "clipboard";
|
|
817
|
+
operation: "write" | "clear" | "copy" | "paste";
|
|
818
|
+
text?: string | undefined;
|
|
819
|
+
locator?: BrowserLocator | undefined;
|
|
820
|
+
content?: "selection" | "value" | "text" | undefined;
|
|
821
|
+
}
|
|
822
|
+
| {
|
|
823
|
+
type: "permission";
|
|
824
|
+
permission: BrowserPermission;
|
|
825
|
+
setting: BrowserPermissionSetting;
|
|
826
|
+
}
|
|
827
|
+
| {
|
|
828
|
+
type: "wait";
|
|
829
|
+
condition: "load" | "network_idle" | "visible" | "hidden";
|
|
830
|
+
locator?: BrowserLocator | undefined;
|
|
831
|
+
timeoutMs?: number | undefined;
|
|
832
|
+
};
|
|
833
|
+
|
|
834
|
+
export type BrowserActionBatch = { type: "batch"; actions: BrowserAction[] };
|
|
835
|
+
|
|
836
|
+
export type InteractionError = {
|
|
837
|
+
code:
|
|
838
|
+
| "resource_not_found"
|
|
839
|
+
| "resource_unavailable"
|
|
840
|
+
| "controller_stale"
|
|
841
|
+
| "target_not_found"
|
|
842
|
+
| "target_stale"
|
|
843
|
+
| "observation_stale"
|
|
844
|
+
| "document_stale"
|
|
845
|
+
| "frame_stale"
|
|
846
|
+
| "locator_not_found"
|
|
847
|
+
| "locator_ambiguous"
|
|
848
|
+
| "unsupported"
|
|
849
|
+
| "permission_denied"
|
|
850
|
+
| "machine_locked"
|
|
851
|
+
| "attempt_stale"
|
|
852
|
+
| "operation_conflict"
|
|
853
|
+
| "outcome_unknown"
|
|
854
|
+
| "invalid_action"
|
|
855
|
+
| "timeout"
|
|
856
|
+
| "controller_lost"
|
|
857
|
+
| "driver_failed";
|
|
858
|
+
message: string;
|
|
859
|
+
retryable: boolean;
|
|
860
|
+
details?: Record<string, InteractionJsonValue> | undefined;
|
|
861
|
+
};
|
|
862
|
+
|
|
863
|
+
export type InteractionOperationState =
|
|
864
|
+
| "prepared"
|
|
865
|
+
| "dispatched"
|
|
866
|
+
| "completed"
|
|
867
|
+
| "failed"
|
|
868
|
+
| "outcome_unknown";
|
|
869
|
+
|
|
870
|
+
export type InteractionLifecycleOperationReceipt = {
|
|
871
|
+
operationId: string;
|
|
872
|
+
resourceKind: "browser_session" | "computer_session";
|
|
873
|
+
resourceId: string;
|
|
874
|
+
kind: "create" | "resume" | "suspend" | "end" | "publish";
|
|
875
|
+
state: InteractionOperationState;
|
|
876
|
+
replayed: boolean;
|
|
877
|
+
error: InteractionError | null;
|
|
878
|
+
createdAt: string;
|
|
879
|
+
dispatchedAt: string | null;
|
|
880
|
+
settledAt: string | null;
|
|
881
|
+
};
|
|
882
|
+
|
|
883
|
+
export type CreateBrowserSessionRequest = {
|
|
884
|
+
operationId: string;
|
|
885
|
+
sessionId: string;
|
|
886
|
+
name?: string | undefined;
|
|
887
|
+
initialUrl?: string | undefined;
|
|
888
|
+
headless?: boolean | undefined;
|
|
889
|
+
engine?: "chromium" | "lightpanda" | undefined;
|
|
890
|
+
placement?: InteractionPlacement | undefined;
|
|
891
|
+
identityId?: string | undefined;
|
|
892
|
+
baseRevisionId?: string | undefined;
|
|
893
|
+
networkRouteId?: string | undefined;
|
|
894
|
+
linkedComputerSessionId?: string | undefined;
|
|
895
|
+
};
|
|
896
|
+
|
|
897
|
+
export type BrowserSessionListResponse = {
|
|
898
|
+
revision: number;
|
|
899
|
+
sessions: BrowserSession[];
|
|
900
|
+
};
|
|
901
|
+
|
|
902
|
+
export type BrowserSessionMutationResponse = {
|
|
903
|
+
session: BrowserSession;
|
|
904
|
+
operation: InteractionLifecycleOperationReceipt;
|
|
905
|
+
};
|
|
906
|
+
|
|
907
|
+
export type BrowserSessionLifecycleRequest = { operationId: string };
|
|
908
|
+
export type BrowserOpenTargetRequest = { url?: string | undefined };
|
|
909
|
+
|
|
910
|
+
export type BrowserTargetListResponse = {
|
|
911
|
+
browserSessionId: string;
|
|
912
|
+
controllerGeneration: string;
|
|
913
|
+
targets: BrowserTarget[];
|
|
914
|
+
};
|
|
915
|
+
|
|
916
|
+
export type InteractionFrameStreamAttachment<RelayKind extends 3 | 4 = 3 | 4> =
|
|
917
|
+
| { kind: "direct_websocket"; url: string; protocols: string[] }
|
|
918
|
+
| {
|
|
919
|
+
kind: "relay";
|
|
920
|
+
url: string;
|
|
921
|
+
token: string;
|
|
922
|
+
channel: {
|
|
923
|
+
channelId: string;
|
|
924
|
+
workspaceId: string;
|
|
925
|
+
agentId: string;
|
|
926
|
+
kind: RelayKind;
|
|
927
|
+
port: number;
|
|
928
|
+
};
|
|
929
|
+
};
|
|
930
|
+
|
|
931
|
+
export type ComputerFrameStreamAttachment =
|
|
932
|
+
| InteractionFrameStreamAttachment<4>
|
|
933
|
+
| { kind: "direct_rfb"; url: string; protocols: string[] };
|
|
934
|
+
|
|
935
|
+
export type BrowserSessionAttachment = {
|
|
936
|
+
browserSessionId: string;
|
|
937
|
+
controllerGeneration: string;
|
|
938
|
+
targetId: string;
|
|
939
|
+
stream: InteractionFrameStreamAttachment<3>;
|
|
940
|
+
expiresAt: string;
|
|
941
|
+
};
|
|
942
|
+
|
|
943
|
+
export type BrowserSessionAttachmentRequest = {
|
|
944
|
+
targetId: string;
|
|
945
|
+
expiresInSeconds?: number | undefined;
|
|
946
|
+
stream?: BrowserFrameStreamOptions | undefined;
|
|
947
|
+
};
|
|
948
|
+
|
|
949
|
+
export type BrowserActionRequest = {
|
|
950
|
+
operationId: string;
|
|
951
|
+
targetId: string;
|
|
952
|
+
expectedTargetGeneration: string;
|
|
953
|
+
expectedDocumentGeneration: string | null;
|
|
954
|
+
expectedFrameId: string | null;
|
|
955
|
+
observationMode?: "full" | "none" | undefined;
|
|
956
|
+
action: BrowserAction | BrowserActionBatch;
|
|
957
|
+
};
|
|
958
|
+
|
|
959
|
+
export type BrowserActionReceipt = {
|
|
960
|
+
protocolVersion: typeof INTERACTION_PROTOCOL_VERSION;
|
|
961
|
+
operationId: string;
|
|
962
|
+
browserSessionId: string;
|
|
963
|
+
controllerGeneration: string;
|
|
964
|
+
targetId: string;
|
|
965
|
+
state: InteractionOperationState;
|
|
966
|
+
dispatchedAt: string | null;
|
|
967
|
+
settledAt: string | null;
|
|
968
|
+
observation: BrowserObservation | null;
|
|
969
|
+
error: InteractionError | null;
|
|
970
|
+
};
|
|
971
|
+
|
|
972
|
+
export type BrowserSessionHeartbeatResponse = {
|
|
973
|
+
browserSessionId: string;
|
|
974
|
+
controllerGeneration: string;
|
|
975
|
+
alive: true;
|
|
976
|
+
};
|
|
977
|
+
|
|
978
|
+
export type ComputerSessionCapabilities = {
|
|
979
|
+
semanticObservation: boolean;
|
|
980
|
+
appDiscovery: boolean;
|
|
981
|
+
appLaunch: boolean;
|
|
982
|
+
windowCapture: boolean;
|
|
983
|
+
screenCapture: boolean;
|
|
984
|
+
semanticActions: boolean;
|
|
985
|
+
pointerInput: boolean;
|
|
986
|
+
keyboardInput: boolean;
|
|
987
|
+
clipboard: boolean;
|
|
988
|
+
backgroundActions: boolean;
|
|
989
|
+
parallelApps: boolean;
|
|
990
|
+
};
|
|
991
|
+
|
|
992
|
+
export type ComputerClipboard = {
|
|
993
|
+
computerSessionId: string;
|
|
994
|
+
controllerGeneration: string;
|
|
995
|
+
text: string | null;
|
|
996
|
+
truncated: boolean;
|
|
997
|
+
observedAt: string;
|
|
998
|
+
};
|
|
999
|
+
|
|
1000
|
+
export type ComputerSession = {
|
|
1001
|
+
id: string;
|
|
1002
|
+
accountId: string;
|
|
1003
|
+
workspaceId: string;
|
|
1004
|
+
name: string;
|
|
1005
|
+
lifecycle: InteractionLifecycle;
|
|
1006
|
+
placement: InteractionPlacement;
|
|
1007
|
+
controller: InteractionControllerBinding | null;
|
|
1008
|
+
platform: "linux" | "macos" | "windows" | null;
|
|
1009
|
+
adapter: string | null;
|
|
1010
|
+
seatId: string | null;
|
|
1011
|
+
displayId: string | null;
|
|
1012
|
+
capabilities: ComputerSessionCapabilities | null;
|
|
1013
|
+
associations: InteractionAssociation[];
|
|
1014
|
+
createdBySubjectId: string;
|
|
1015
|
+
createdAt: string;
|
|
1016
|
+
lastUsedAt: string;
|
|
1017
|
+
failureCode: string | null;
|
|
1018
|
+
};
|
|
1019
|
+
|
|
1020
|
+
export type ComputerTarget = {
|
|
1021
|
+
id: string;
|
|
1022
|
+
computerSessionId: string;
|
|
1023
|
+
controllerGeneration: string;
|
|
1024
|
+
targetGeneration: string;
|
|
1025
|
+
kind: "app" | "window" | "screen";
|
|
1026
|
+
applicationId: string | null;
|
|
1027
|
+
processId: number | null;
|
|
1028
|
+
title: string;
|
|
1029
|
+
bounds: InteractionRect | null;
|
|
1030
|
+
focused: boolean;
|
|
1031
|
+
};
|
|
1032
|
+
|
|
1033
|
+
export type ComputerObservation = {
|
|
1034
|
+
protocolVersion: typeof INTERACTION_PROTOCOL_VERSION;
|
|
1035
|
+
observationId: string;
|
|
1036
|
+
computerSessionId: string;
|
|
1037
|
+
target: ComputerTarget;
|
|
1038
|
+
frameId: string | null;
|
|
1039
|
+
semantic: InteractionSemanticSnapshot | InteractionSemanticDiff | null;
|
|
1040
|
+
screenshot: RetainedArtifactReference | null;
|
|
1041
|
+
focusedRef: string | null;
|
|
1042
|
+
changedRegions: InteractionRect[];
|
|
1043
|
+
observedAt: string;
|
|
1044
|
+
};
|
|
1045
|
+
|
|
1046
|
+
export type ComputerLocator =
|
|
1047
|
+
| { kind: "ref"; ref: string }
|
|
1048
|
+
| {
|
|
1049
|
+
kind: "role";
|
|
1050
|
+
role: string;
|
|
1051
|
+
name?: string | undefined;
|
|
1052
|
+
exact?: boolean | undefined;
|
|
1053
|
+
}
|
|
1054
|
+
| { kind: "label"; text: string; exact?: boolean | undefined }
|
|
1055
|
+
| { kind: "text"; text: string; exact?: boolean | undefined }
|
|
1056
|
+
| { kind: "identifier"; value: string };
|
|
1057
|
+
|
|
1058
|
+
export type ComputerAction =
|
|
1059
|
+
| {
|
|
1060
|
+
type: "semantic";
|
|
1061
|
+
locator: ComputerLocator;
|
|
1062
|
+
action:
|
|
1063
|
+
| "invoke"
|
|
1064
|
+
| "focus"
|
|
1065
|
+
| "set_value"
|
|
1066
|
+
| "increment"
|
|
1067
|
+
| "decrement"
|
|
1068
|
+
| "select"
|
|
1069
|
+
| "deselect"
|
|
1070
|
+
| "expand"
|
|
1071
|
+
| "collapse"
|
|
1072
|
+
| "show_menu"
|
|
1073
|
+
| "scroll_into_view";
|
|
1074
|
+
value?: string | number | boolean | undefined;
|
|
1075
|
+
}
|
|
1076
|
+
| {
|
|
1077
|
+
type: "pointer";
|
|
1078
|
+
frameId: string;
|
|
1079
|
+
action: "click" | "double_click" | "move" | "scroll" | "drag";
|
|
1080
|
+
x: number;
|
|
1081
|
+
y: number;
|
|
1082
|
+
endX?: number | undefined;
|
|
1083
|
+
endY?: number | undefined;
|
|
1084
|
+
deltaX?: number | undefined;
|
|
1085
|
+
deltaY?: number | undefined;
|
|
1086
|
+
button?: "left" | "right" | "middle" | undefined;
|
|
1087
|
+
}
|
|
1088
|
+
| { type: "keyboard"; action: "type" | "press"; value: string }
|
|
1089
|
+
| {
|
|
1090
|
+
type: "clipboard";
|
|
1091
|
+
operation: "write" | "clear" | "copy" | "paste";
|
|
1092
|
+
text?: string | undefined;
|
|
1093
|
+
}
|
|
1094
|
+
| { type: "focus"; targetId: string }
|
|
1095
|
+
| { type: "launch"; applicationId: string };
|
|
1096
|
+
|
|
1097
|
+
export type CreateComputerSessionRequest = {
|
|
1098
|
+
operationId: string;
|
|
1099
|
+
sessionId: string;
|
|
1100
|
+
name?: string | undefined;
|
|
1101
|
+
placement?: InteractionPlacement | undefined;
|
|
1102
|
+
};
|
|
1103
|
+
|
|
1104
|
+
export type ComputerSessionListResponse = {
|
|
1105
|
+
revision: number;
|
|
1106
|
+
sessions: ComputerSession[];
|
|
1107
|
+
};
|
|
1108
|
+
|
|
1109
|
+
export type ComputerSessionMutationResponse = {
|
|
1110
|
+
session: ComputerSession;
|
|
1111
|
+
operation: InteractionLifecycleOperationReceipt;
|
|
1112
|
+
};
|
|
1113
|
+
|
|
1114
|
+
export type ComputerSessionLifecycleRequest = { operationId: string };
|
|
1115
|
+
|
|
1116
|
+
export type ComputerTargetListResponse = {
|
|
1117
|
+
computerSessionId: string;
|
|
1118
|
+
controllerGeneration: string;
|
|
1119
|
+
targets: ComputerTarget[];
|
|
1120
|
+
};
|
|
1121
|
+
|
|
1122
|
+
export type InteractionFrameStreamOptions = {
|
|
1123
|
+
format?: "jpeg" | "png" | undefined;
|
|
1124
|
+
quality?: number | undefined;
|
|
1125
|
+
maxWidth?: number | undefined;
|
|
1126
|
+
maxHeight?: number | undefined;
|
|
1127
|
+
everyNthFrame?: number | undefined;
|
|
1128
|
+
};
|
|
1129
|
+
|
|
1130
|
+
export type ComputerFrameStreamOptions = InteractionFrameStreamOptions;
|
|
1131
|
+
|
|
1132
|
+
export type ComputerSessionAttachment = {
|
|
1133
|
+
computerSessionId: string;
|
|
1134
|
+
controllerGeneration: string;
|
|
1135
|
+
targetId: string;
|
|
1136
|
+
stream: ComputerFrameStreamAttachment;
|
|
1137
|
+
expiresAt: string;
|
|
1138
|
+
};
|
|
1139
|
+
|
|
1140
|
+
export type ComputerSessionAttachmentRequest = {
|
|
1141
|
+
targetId: string;
|
|
1142
|
+
expiresInSeconds?: number | undefined;
|
|
1143
|
+
stream?: ComputerFrameStreamOptions | undefined;
|
|
1144
|
+
};
|
|
1145
|
+
|
|
1146
|
+
export type ComputerActionRequest = {
|
|
1147
|
+
operationId: string;
|
|
1148
|
+
targetId: string;
|
|
1149
|
+
expectedTargetGeneration: string;
|
|
1150
|
+
expectedObservationId: string | null;
|
|
1151
|
+
expectedFrameId: string | null;
|
|
1152
|
+
action: ComputerAction;
|
|
1153
|
+
};
|
|
1154
|
+
|
|
1155
|
+
export type ComputerActionReceipt = {
|
|
1156
|
+
protocolVersion: typeof INTERACTION_PROTOCOL_VERSION;
|
|
1157
|
+
operationId: string;
|
|
1158
|
+
computerSessionId: string;
|
|
1159
|
+
controllerGeneration: string;
|
|
1160
|
+
targetId: string;
|
|
1161
|
+
state: InteractionOperationState;
|
|
1162
|
+
dispatchedAt: string | null;
|
|
1163
|
+
settledAt: string | null;
|
|
1164
|
+
observation: ComputerObservation | null;
|
|
1165
|
+
error: InteractionError | null;
|
|
1166
|
+
};
|
|
1167
|
+
|
|
1168
|
+
export type ComputerSessionHeartbeatResponse = {
|
|
1169
|
+
computerSessionId: string;
|
|
1170
|
+
controllerGeneration: string;
|
|
1171
|
+
alive: true;
|
|
1172
|
+
};
|
|
1173
|
+
|
|
1174
|
+
export type BrowserDiagnosticsOptions = {
|
|
1175
|
+
kinds?: BrowserDiagnosticKind[] | undefined;
|
|
1176
|
+
after?: number | undefined;
|
|
1177
|
+
limit?: number | undefined;
|
|
1178
|
+
signal?: AbortSignal | undefined;
|
|
1179
|
+
};
|
|
1180
|
+
|
|
1181
|
+
/** The exact HTTP surface needed by the framework-free interaction client. */
|
|
1182
|
+
export interface InteractionTransport {
|
|
1183
|
+
listNetworkRoutes(
|
|
1184
|
+
workspaceId: string,
|
|
1185
|
+
options?: NetworkRouteListOptions,
|
|
1186
|
+
): Promise<NetworkRouteListResponse>;
|
|
1187
|
+
getNetworkRoute(
|
|
1188
|
+
workspaceId: string,
|
|
1189
|
+
networkRouteId: string,
|
|
1190
|
+
options?: OpenGeniRequestOptions,
|
|
1191
|
+
): Promise<NetworkRoute>;
|
|
1192
|
+
createNetworkRoute(
|
|
1193
|
+
workspaceId: string,
|
|
1194
|
+
request: CreateNetworkRouteRequest,
|
|
1195
|
+
options?: OpenGeniRequestOptions,
|
|
1196
|
+
): Promise<NetworkRouteMutationResponse>;
|
|
1197
|
+
updateNetworkRoute(
|
|
1198
|
+
workspaceId: string,
|
|
1199
|
+
networkRouteId: string,
|
|
1200
|
+
request: UpdateNetworkRouteRequest,
|
|
1201
|
+
options?: OpenGeniRequestOptions,
|
|
1202
|
+
): Promise<NetworkRouteMutationResponse>;
|
|
1203
|
+
listSiteAuthConnections(
|
|
1204
|
+
workspaceId: string,
|
|
1205
|
+
options?: SiteAuthConnectionListOptions,
|
|
1206
|
+
): Promise<SiteAuthConnectionListResponse>;
|
|
1207
|
+
getSiteAuthConnection(
|
|
1208
|
+
workspaceId: string,
|
|
1209
|
+
siteAuthConnectionId: string,
|
|
1210
|
+
options?: OpenGeniRequestOptions,
|
|
1211
|
+
): Promise<SiteAuthConnection>;
|
|
1212
|
+
createSiteAuthConnection(
|
|
1213
|
+
workspaceId: string,
|
|
1214
|
+
request: CreateSiteAuthConnectionRequest,
|
|
1215
|
+
options?: OpenGeniRequestOptions,
|
|
1216
|
+
): Promise<SiteAuthConnectionMutationResponse>;
|
|
1217
|
+
updateSiteAuthConnection(
|
|
1218
|
+
workspaceId: string,
|
|
1219
|
+
siteAuthConnectionId: string,
|
|
1220
|
+
request: UpdateSiteAuthConnectionRequest,
|
|
1221
|
+
options?: OpenGeniRequestOptions,
|
|
1222
|
+
): Promise<SiteAuthConnectionMutationResponse>;
|
|
1223
|
+
listAuthRuns(workspaceId: string, options?: AuthRunListOptions): Promise<AuthRunListResponse>;
|
|
1224
|
+
getAuthRun(
|
|
1225
|
+
workspaceId: string,
|
|
1226
|
+
authRunId: string,
|
|
1227
|
+
options?: OpenGeniRequestOptions,
|
|
1228
|
+
): Promise<AuthRun>;
|
|
1229
|
+
startBrowserAuthRun(
|
|
1230
|
+
workspaceId: string,
|
|
1231
|
+
browserSessionId: string,
|
|
1232
|
+
request: StartAuthRunRequest,
|
|
1233
|
+
options?: OpenGeniRequestOptions,
|
|
1234
|
+
): Promise<AuthRunMutationResponse>;
|
|
1235
|
+
reportBrowserAuthRun(
|
|
1236
|
+
workspaceId: string,
|
|
1237
|
+
browserSessionId: string,
|
|
1238
|
+
authRunId: string,
|
|
1239
|
+
request: ReportAuthRunRequest,
|
|
1240
|
+
options?: OpenGeniRequestOptions,
|
|
1241
|
+
): Promise<AuthRunMutationResponse>;
|
|
1242
|
+
protectedBrowserAuthFill(
|
|
1243
|
+
workspaceId: string,
|
|
1244
|
+
browserSessionId: string,
|
|
1245
|
+
authRunId: string,
|
|
1246
|
+
request: ProtectedAuthFillRequest,
|
|
1247
|
+
options?: OpenGeniRequestOptions,
|
|
1248
|
+
): Promise<ProtectedAuthFillResponse>;
|
|
1249
|
+
advanceExternalBrowserAuthRun(
|
|
1250
|
+
workspaceId: string,
|
|
1251
|
+
browserSessionId: string,
|
|
1252
|
+
authRunId: string,
|
|
1253
|
+
request: ExternalAuthRunRequest,
|
|
1254
|
+
options?: OpenGeniRequestOptions,
|
|
1255
|
+
): Promise<ExternalAuthRunResponse>;
|
|
1256
|
+
openExternalBrowserAuthFlow(
|
|
1257
|
+
workspaceId: string,
|
|
1258
|
+
browserSessionId: string,
|
|
1259
|
+
authRunId: string,
|
|
1260
|
+
request: ExternalAuthInteractiveRequest,
|
|
1261
|
+
options?: OpenGeniRequestOptions,
|
|
1262
|
+
): Promise<ExternalAuthInteractiveResponse>;
|
|
1263
|
+
verifyBrowserAuthRun(
|
|
1264
|
+
workspaceId: string,
|
|
1265
|
+
browserSessionId: string,
|
|
1266
|
+
authRunId: string,
|
|
1267
|
+
request: VerifyAuthRunRequest,
|
|
1268
|
+
options?: OpenGeniRequestOptions,
|
|
1269
|
+
): Promise<AuthRunMutationResponse>;
|
|
1270
|
+
listInteractionInterventions(
|
|
1271
|
+
workspaceId: string,
|
|
1272
|
+
options?: InteractionInterventionListOptions,
|
|
1273
|
+
): Promise<InteractionInterventionListResponse>;
|
|
1274
|
+
getInteractionIntervention(
|
|
1275
|
+
workspaceId: string,
|
|
1276
|
+
interventionId: string,
|
|
1277
|
+
options?: OpenGeniRequestOptions,
|
|
1278
|
+
): Promise<InteractionIntervention>;
|
|
1279
|
+
createInteractionIntervention(
|
|
1280
|
+
workspaceId: string,
|
|
1281
|
+
request: CreateInteractionInterventionRequest,
|
|
1282
|
+
options?: OpenGeniRequestOptions,
|
|
1283
|
+
): Promise<InteractionInterventionMutationResponse>;
|
|
1284
|
+
resolveInteractionIntervention(
|
|
1285
|
+
workspaceId: string,
|
|
1286
|
+
interventionId: string,
|
|
1287
|
+
request: ResolveInteractionInterventionRequest,
|
|
1288
|
+
options?: OpenGeniRequestOptions,
|
|
1289
|
+
): Promise<InteractionInterventionMutationResponse>;
|
|
1290
|
+
listAttachedBrowsers(
|
|
1291
|
+
workspaceId: string,
|
|
1292
|
+
options?: AttachedBrowserDeviceListOptions,
|
|
1293
|
+
): Promise<AttachedBrowserDeviceListResponse>;
|
|
1294
|
+
getAttachedBrowser(
|
|
1295
|
+
workspaceId: string,
|
|
1296
|
+
deviceId: string,
|
|
1297
|
+
options?: OpenGeniRequestOptions,
|
|
1298
|
+
): Promise<AttachedBrowserDevice>;
|
|
1299
|
+
listBrowserIdentities(
|
|
1300
|
+
workspaceId: string,
|
|
1301
|
+
options?: BrowserIdentityListOptions,
|
|
1302
|
+
): Promise<BrowserIdentityListResponse>;
|
|
1303
|
+
getBrowserIdentity(
|
|
1304
|
+
workspaceId: string,
|
|
1305
|
+
identityId: string,
|
|
1306
|
+
options?: OpenGeniRequestOptions,
|
|
1307
|
+
): Promise<BrowserIdentity>;
|
|
1308
|
+
createBrowserIdentity(
|
|
1309
|
+
workspaceId: string,
|
|
1310
|
+
request: CreateBrowserIdentityRequest,
|
|
1311
|
+
options?: OpenGeniRequestOptions,
|
|
1312
|
+
): Promise<BrowserIdentityMutationResponse>;
|
|
1313
|
+
updateBrowserIdentity(
|
|
1314
|
+
workspaceId: string,
|
|
1315
|
+
identityId: string,
|
|
1316
|
+
request: UpdateBrowserIdentityRequest,
|
|
1317
|
+
options?: OpenGeniRequestOptions,
|
|
1318
|
+
): Promise<BrowserIdentityMutationResponse>;
|
|
1319
|
+
listBrowserRevisions(
|
|
1320
|
+
workspaceId: string,
|
|
1321
|
+
identityId: string,
|
|
1322
|
+
options?: OpenGeniRequestOptions,
|
|
1323
|
+
): Promise<BrowserRevisionListResponse>;
|
|
1324
|
+
listBrowserSessions(
|
|
1325
|
+
workspaceId: string,
|
|
1326
|
+
options?: OpenGeniRequestOptions,
|
|
1327
|
+
): Promise<BrowserSessionListResponse>;
|
|
1328
|
+
getBrowserSession(
|
|
1329
|
+
workspaceId: string,
|
|
1330
|
+
browserSessionId: string,
|
|
1331
|
+
options?: OpenGeniRequestOptions,
|
|
1332
|
+
): Promise<BrowserSession>;
|
|
1333
|
+
readBrowserClipboard(
|
|
1334
|
+
workspaceId: string,
|
|
1335
|
+
browserSessionId: string,
|
|
1336
|
+
options?: OpenGeniRequestOptions,
|
|
1337
|
+
): Promise<BrowserClipboard>;
|
|
1338
|
+
listBrowserDownloads(
|
|
1339
|
+
workspaceId: string,
|
|
1340
|
+
browserSessionId: string,
|
|
1341
|
+
options?: OpenGeniRequestOptions,
|
|
1342
|
+
): Promise<BrowserDownloadListResponse>;
|
|
1343
|
+
getBrowserDownload(
|
|
1344
|
+
workspaceId: string,
|
|
1345
|
+
browserSessionId: string,
|
|
1346
|
+
downloadId: string,
|
|
1347
|
+
options?: OpenGeniRequestOptions,
|
|
1348
|
+
): Promise<BrowserDownload>;
|
|
1349
|
+
saveBrowserDownload(
|
|
1350
|
+
workspaceId: string,
|
|
1351
|
+
browserSessionId: string,
|
|
1352
|
+
downloadId: string,
|
|
1353
|
+
request: BrowserDownloadSaveRequest,
|
|
1354
|
+
options?: OpenGeniRequestOptions,
|
|
1355
|
+
): Promise<BrowserDownloadSaveResponse>;
|
|
1356
|
+
createBrowserSession(
|
|
1357
|
+
workspaceId: string,
|
|
1358
|
+
request: CreateBrowserSessionRequest,
|
|
1359
|
+
options?: OpenGeniRequestOptions,
|
|
1360
|
+
): Promise<BrowserSessionMutationResponse>;
|
|
1361
|
+
listBrowserTargets(
|
|
1362
|
+
workspaceId: string,
|
|
1363
|
+
browserSessionId: string,
|
|
1364
|
+
options?: OpenGeniRequestOptions,
|
|
1365
|
+
): Promise<BrowserTargetListResponse>;
|
|
1366
|
+
openBrowserTarget(
|
|
1367
|
+
workspaceId: string,
|
|
1368
|
+
browserSessionId: string,
|
|
1369
|
+
request?: BrowserOpenTargetRequest,
|
|
1370
|
+
options?: OpenGeniRequestOptions,
|
|
1371
|
+
): Promise<BrowserObservation>;
|
|
1372
|
+
selectBrowserTarget(
|
|
1373
|
+
workspaceId: string,
|
|
1374
|
+
browserSessionId: string,
|
|
1375
|
+
targetId: string,
|
|
1376
|
+
options?: OpenGeniRequestOptions,
|
|
1377
|
+
): Promise<BrowserObservation>;
|
|
1378
|
+
closeBrowserTarget(
|
|
1379
|
+
workspaceId: string,
|
|
1380
|
+
browserSessionId: string,
|
|
1381
|
+
targetId: string,
|
|
1382
|
+
options?: OpenGeniRequestOptions,
|
|
1383
|
+
): Promise<BrowserTargetListResponse>;
|
|
1384
|
+
observeBrowserTarget(
|
|
1385
|
+
workspaceId: string,
|
|
1386
|
+
browserSessionId: string,
|
|
1387
|
+
targetId: string,
|
|
1388
|
+
options?: OpenGeniRequestOptions,
|
|
1389
|
+
): Promise<BrowserObservation>;
|
|
1390
|
+
actInBrowser(
|
|
1391
|
+
workspaceId: string,
|
|
1392
|
+
browserSessionId: string,
|
|
1393
|
+
request: BrowserActionRequest,
|
|
1394
|
+
options?: OpenGeniRequestOptions,
|
|
1395
|
+
): Promise<BrowserActionReceipt>;
|
|
1396
|
+
getBrowserActionReceipt(
|
|
1397
|
+
workspaceId: string,
|
|
1398
|
+
browserSessionId: string,
|
|
1399
|
+
operationId: string,
|
|
1400
|
+
options?: OpenGeniRequestOptions,
|
|
1401
|
+
): Promise<BrowserActionReceipt>;
|
|
1402
|
+
listBrowserDiagnostics(
|
|
1403
|
+
workspaceId: string,
|
|
1404
|
+
browserSessionId: string,
|
|
1405
|
+
targetId: string,
|
|
1406
|
+
options?: BrowserDiagnosticsOptions,
|
|
1407
|
+
): Promise<BrowserDiagnosticBatch>;
|
|
1408
|
+
attachBrowserSession(
|
|
1409
|
+
workspaceId: string,
|
|
1410
|
+
browserSessionId: string,
|
|
1411
|
+
request: BrowserSessionAttachmentRequest,
|
|
1412
|
+
options?: OpenGeniRequestOptions,
|
|
1413
|
+
): Promise<BrowserSessionAttachment>;
|
|
1414
|
+
heartbeatBrowserSession(
|
|
1415
|
+
workspaceId: string,
|
|
1416
|
+
browserSessionId: string,
|
|
1417
|
+
options?: OpenGeniRequestOptions,
|
|
1418
|
+
): Promise<BrowserSessionHeartbeatResponse>;
|
|
1419
|
+
publishBrowserRevision(
|
|
1420
|
+
workspaceId: string,
|
|
1421
|
+
browserSessionId: string,
|
|
1422
|
+
request: PublishBrowserRevisionRequest,
|
|
1423
|
+
options?: OpenGeniRequestOptions,
|
|
1424
|
+
): Promise<PublishBrowserRevisionResponse>;
|
|
1425
|
+
suspendBrowserSession(
|
|
1426
|
+
workspaceId: string,
|
|
1427
|
+
browserSessionId: string,
|
|
1428
|
+
request: BrowserSessionLifecycleRequest,
|
|
1429
|
+
options?: OpenGeniRequestOptions,
|
|
1430
|
+
): Promise<BrowserSessionMutationResponse>;
|
|
1431
|
+
resumeBrowserSession(
|
|
1432
|
+
workspaceId: string,
|
|
1433
|
+
browserSessionId: string,
|
|
1434
|
+
request: BrowserSessionLifecycleRequest,
|
|
1435
|
+
options?: OpenGeniRequestOptions,
|
|
1436
|
+
): Promise<BrowserSessionMutationResponse>;
|
|
1437
|
+
endBrowserSession(
|
|
1438
|
+
workspaceId: string,
|
|
1439
|
+
browserSessionId: string,
|
|
1440
|
+
request: BrowserSessionLifecycleRequest,
|
|
1441
|
+
options?: OpenGeniRequestOptions,
|
|
1442
|
+
): Promise<BrowserSessionMutationResponse>;
|
|
1443
|
+
listComputerSessions(
|
|
1444
|
+
workspaceId: string,
|
|
1445
|
+
options?: OpenGeniRequestOptions,
|
|
1446
|
+
): Promise<ComputerSessionListResponse>;
|
|
1447
|
+
getComputerSession(
|
|
1448
|
+
workspaceId: string,
|
|
1449
|
+
computerSessionId: string,
|
|
1450
|
+
options?: OpenGeniRequestOptions,
|
|
1451
|
+
): Promise<ComputerSession>;
|
|
1452
|
+
readComputerClipboard(
|
|
1453
|
+
workspaceId: string,
|
|
1454
|
+
computerSessionId: string,
|
|
1455
|
+
options?: OpenGeniRequestOptions,
|
|
1456
|
+
): Promise<ComputerClipboard>;
|
|
1457
|
+
createComputerSession(
|
|
1458
|
+
workspaceId: string,
|
|
1459
|
+
request: CreateComputerSessionRequest,
|
|
1460
|
+
options?: OpenGeniRequestOptions,
|
|
1461
|
+
): Promise<ComputerSessionMutationResponse>;
|
|
1462
|
+
listComputerTargets(
|
|
1463
|
+
workspaceId: string,
|
|
1464
|
+
computerSessionId: string,
|
|
1465
|
+
options?: OpenGeniRequestOptions,
|
|
1466
|
+
): Promise<ComputerTargetListResponse>;
|
|
1467
|
+
observeComputerTarget(
|
|
1468
|
+
workspaceId: string,
|
|
1469
|
+
computerSessionId: string,
|
|
1470
|
+
targetId: string,
|
|
1471
|
+
options?: OpenGeniRequestOptions,
|
|
1472
|
+
): Promise<ComputerObservation>;
|
|
1473
|
+
actInComputer(
|
|
1474
|
+
workspaceId: string,
|
|
1475
|
+
computerSessionId: string,
|
|
1476
|
+
request: ComputerActionRequest,
|
|
1477
|
+
options?: OpenGeniRequestOptions,
|
|
1478
|
+
): Promise<ComputerActionReceipt>;
|
|
1479
|
+
getComputerActionReceipt(
|
|
1480
|
+
workspaceId: string,
|
|
1481
|
+
computerSessionId: string,
|
|
1482
|
+
operationId: string,
|
|
1483
|
+
options?: OpenGeniRequestOptions,
|
|
1484
|
+
): Promise<ComputerActionReceipt>;
|
|
1485
|
+
attachComputerSession(
|
|
1486
|
+
workspaceId: string,
|
|
1487
|
+
computerSessionId: string,
|
|
1488
|
+
request: ComputerSessionAttachmentRequest,
|
|
1489
|
+
options?: OpenGeniRequestOptions,
|
|
1490
|
+
): Promise<ComputerSessionAttachment>;
|
|
1491
|
+
heartbeatComputerSession(
|
|
1492
|
+
workspaceId: string,
|
|
1493
|
+
computerSessionId: string,
|
|
1494
|
+
options?: OpenGeniRequestOptions,
|
|
1495
|
+
): Promise<ComputerSessionHeartbeatResponse>;
|
|
1496
|
+
endComputerSession(
|
|
1497
|
+
workspaceId: string,
|
|
1498
|
+
computerSessionId: string,
|
|
1499
|
+
request: ComputerSessionLifecycleRequest,
|
|
1500
|
+
options?: OpenGeniRequestOptions,
|
|
1501
|
+
): Promise<ComputerSessionMutationResponse>;
|
|
1502
|
+
}
|
|
1503
|
+
|
|
1504
|
+
/** @deprecated Use InteractionTransport. */
|
|
1505
|
+
export type BrowserInteractionTransport = InteractionTransport;
|
|
1506
|
+
|
|
1507
|
+
export type BrowserIdentityListOptions = OpenGeniRequestOptions & {
|
|
1508
|
+
includeArchived?: boolean | undefined;
|
|
1509
|
+
};
|
|
1510
|
+
|
|
1511
|
+
export type NetworkRouteListOptions = OpenGeniRequestOptions & {
|
|
1512
|
+
includeArchived?: boolean | undefined;
|
|
1513
|
+
};
|
|
1514
|
+
|
|
1515
|
+
export type SiteAuthConnectionListOptions = OpenGeniRequestOptions & {
|
|
1516
|
+
includeArchived?: boolean | undefined;
|
|
1517
|
+
};
|
|
1518
|
+
|
|
1519
|
+
export type AuthRunListOptions = OpenGeniRequestOptions & {
|
|
1520
|
+
browserSessionId?: string | undefined;
|
|
1521
|
+
siteAuthConnectionId?: string | undefined;
|
|
1522
|
+
includeSettled?: boolean | undefined;
|
|
1523
|
+
};
|
|
1524
|
+
|
|
1525
|
+
export type InteractionInterventionListOptions = OpenGeniRequestOptions & {
|
|
1526
|
+
resourceKind?: "browser_session" | "computer_session" | undefined;
|
|
1527
|
+
resourceId?: string | undefined;
|
|
1528
|
+
includeSettled?: boolean | undefined;
|
|
1529
|
+
};
|
|
1530
|
+
|
|
1531
|
+
export type AttachedBrowserDeviceListOptions = OpenGeniRequestOptions & {
|
|
1532
|
+
includeDisconnected?: boolean | undefined;
|
|
1533
|
+
};
|
|
1534
|
+
|
|
1535
|
+
export type BrowserDownloadSaveOptions = OpenGeniRequestOptions & {
|
|
1536
|
+
operationId?: string | undefined;
|
|
1537
|
+
overwrite?: boolean | undefined;
|
|
1538
|
+
};
|
|
1539
|
+
|
|
1540
|
+
export type CurrentOrOpenBrowserOptions = {
|
|
1541
|
+
workspaceId: string;
|
|
1542
|
+
associationSessionId: string;
|
|
1543
|
+
operationId?: string | undefined;
|
|
1544
|
+
name?: string | undefined;
|
|
1545
|
+
initialUrl?: string | undefined;
|
|
1546
|
+
headless?: boolean | undefined;
|
|
1547
|
+
placement?: InteractionPlacement | undefined;
|
|
1548
|
+
identityId?: string | undefined;
|
|
1549
|
+
baseRevisionId?: string | undefined;
|
|
1550
|
+
networkRouteId?: string | undefined;
|
|
1551
|
+
linkedComputerSessionId?: string | undefined;
|
|
1552
|
+
signal?: AbortSignal | undefined;
|
|
1553
|
+
};
|
|
1554
|
+
|
|
1555
|
+
export type CurrentOrOpenComputerOptions = {
|
|
1556
|
+
workspaceId: string;
|
|
1557
|
+
associationSessionId: string;
|
|
1558
|
+
operationId?: string | undefined;
|
|
1559
|
+
name?: string | undefined;
|
|
1560
|
+
placement?: InteractionPlacement | undefined;
|
|
1561
|
+
signal?: AbortSignal | undefined;
|
|
1562
|
+
};
|
|
1563
|
+
|
|
1564
|
+
/** Framework-free resource facade over the public interaction HTTP API. */
|
|
1565
|
+
export class OpenGeniInteractionClient {
|
|
1566
|
+
readonly attachedBrowsers: AttachedBrowserDeviceCollection;
|
|
1567
|
+
readonly authRuns: AuthRunCollection;
|
|
1568
|
+
readonly browsers: BrowserSessionCollection;
|
|
1569
|
+
readonly computers: ComputerSessionCollection;
|
|
1570
|
+
readonly identities: BrowserIdentityCollection;
|
|
1571
|
+
readonly interventions: InteractionInterventionCollection;
|
|
1572
|
+
readonly networkRoutes: NetworkRouteCollection;
|
|
1573
|
+
readonly siteAuthConnections: SiteAuthConnectionCollection;
|
|
1574
|
+
|
|
1575
|
+
constructor(transport: BrowserInteractionTransport) {
|
|
1576
|
+
this.attachedBrowsers = new AttachedBrowserDeviceCollection(transport);
|
|
1577
|
+
this.authRuns = new AuthRunCollection(transport);
|
|
1578
|
+
this.browsers = new BrowserSessionCollection(transport);
|
|
1579
|
+
this.computers = new ComputerSessionCollection(transport);
|
|
1580
|
+
this.identities = new BrowserIdentityCollection(transport);
|
|
1581
|
+
this.interventions = new InteractionInterventionCollection(transport);
|
|
1582
|
+
this.networkRoutes = new NetworkRouteCollection(transport);
|
|
1583
|
+
this.siteAuthConnections = new SiteAuthConnectionCollection(transport);
|
|
1584
|
+
}
|
|
1585
|
+
}
|
|
1586
|
+
|
|
1587
|
+
export class NetworkRouteCollection {
|
|
1588
|
+
constructor(private readonly transport: BrowserInteractionTransport) {}
|
|
1589
|
+
|
|
1590
|
+
async list(
|
|
1591
|
+
workspaceId: string,
|
|
1592
|
+
options: NetworkRouteListOptions = {},
|
|
1593
|
+
): Promise<NetworkRouteListResponse> {
|
|
1594
|
+
return await this.transport.listNetworkRoutes(workspaceId, options);
|
|
1595
|
+
}
|
|
1596
|
+
|
|
1597
|
+
route(workspaceId: string, networkRouteId: string): NetworkRouteResource {
|
|
1598
|
+
return new NetworkRouteResource(this.transport, workspaceId, networkRouteId);
|
|
1599
|
+
}
|
|
1600
|
+
|
|
1601
|
+
async create(
|
|
1602
|
+
workspaceId: string,
|
|
1603
|
+
request: CreateNetworkRouteRequest,
|
|
1604
|
+
options: OpenGeniRequestOptions = {},
|
|
1605
|
+
): Promise<NetworkRouteResource> {
|
|
1606
|
+
const response = await this.transport.createNetworkRoute(workspaceId, request, options);
|
|
1607
|
+
return this.route(workspaceId, response.route.id);
|
|
1608
|
+
}
|
|
1609
|
+
}
|
|
1610
|
+
|
|
1611
|
+
export class NetworkRouteResource {
|
|
1612
|
+
constructor(
|
|
1613
|
+
private readonly transport: BrowserInteractionTransport,
|
|
1614
|
+
readonly workspaceId: string,
|
|
1615
|
+
readonly id: string,
|
|
1616
|
+
) {}
|
|
1617
|
+
|
|
1618
|
+
async get(options: OpenGeniRequestOptions = {}): Promise<NetworkRoute> {
|
|
1619
|
+
return await this.transport.getNetworkRoute(this.workspaceId, this.id, options);
|
|
1620
|
+
}
|
|
1621
|
+
|
|
1622
|
+
async update(
|
|
1623
|
+
request: UpdateNetworkRouteRequest,
|
|
1624
|
+
options: OpenGeniRequestOptions = {},
|
|
1625
|
+
): Promise<NetworkRouteMutationResponse> {
|
|
1626
|
+
return await this.transport.updateNetworkRoute(this.workspaceId, this.id, request, options);
|
|
1627
|
+
}
|
|
1628
|
+
}
|
|
1629
|
+
|
|
1630
|
+
export class SiteAuthConnectionCollection {
|
|
1631
|
+
constructor(private readonly transport: BrowserInteractionTransport) {}
|
|
1632
|
+
|
|
1633
|
+
async list(
|
|
1634
|
+
workspaceId: string,
|
|
1635
|
+
options: SiteAuthConnectionListOptions = {},
|
|
1636
|
+
): Promise<SiteAuthConnectionListResponse> {
|
|
1637
|
+
return await this.transport.listSiteAuthConnections(workspaceId, options);
|
|
1638
|
+
}
|
|
1639
|
+
|
|
1640
|
+
connection(workspaceId: string, connectionId: string): SiteAuthConnectionResource {
|
|
1641
|
+
return new SiteAuthConnectionResource(this.transport, workspaceId, connectionId);
|
|
1642
|
+
}
|
|
1643
|
+
|
|
1644
|
+
async create(
|
|
1645
|
+
workspaceId: string,
|
|
1646
|
+
request: CreateSiteAuthConnectionRequest,
|
|
1647
|
+
options: OpenGeniRequestOptions = {},
|
|
1648
|
+
): Promise<SiteAuthConnectionResource> {
|
|
1649
|
+
const response = await this.transport.createSiteAuthConnection(workspaceId, request, options);
|
|
1650
|
+
return this.connection(workspaceId, response.connection.id);
|
|
1651
|
+
}
|
|
1652
|
+
}
|
|
1653
|
+
|
|
1654
|
+
export class SiteAuthConnectionResource {
|
|
1655
|
+
constructor(
|
|
1656
|
+
private readonly transport: BrowserInteractionTransport,
|
|
1657
|
+
readonly workspaceId: string,
|
|
1658
|
+
readonly id: string,
|
|
1659
|
+
) {}
|
|
1660
|
+
|
|
1661
|
+
async get(options: OpenGeniRequestOptions = {}): Promise<SiteAuthConnection> {
|
|
1662
|
+
return await this.transport.getSiteAuthConnection(this.workspaceId, this.id, options);
|
|
1663
|
+
}
|
|
1664
|
+
|
|
1665
|
+
async update(
|
|
1666
|
+
request: UpdateSiteAuthConnectionRequest,
|
|
1667
|
+
options: OpenGeniRequestOptions = {},
|
|
1668
|
+
): Promise<SiteAuthConnectionMutationResponse> {
|
|
1669
|
+
return await this.transport.updateSiteAuthConnection(
|
|
1670
|
+
this.workspaceId,
|
|
1671
|
+
this.id,
|
|
1672
|
+
request,
|
|
1673
|
+
options,
|
|
1674
|
+
);
|
|
1675
|
+
}
|
|
1676
|
+
}
|
|
1677
|
+
|
|
1678
|
+
export class AuthRunCollection {
|
|
1679
|
+
constructor(private readonly transport: BrowserInteractionTransport) {}
|
|
1680
|
+
|
|
1681
|
+
async list(workspaceId: string, options: AuthRunListOptions = {}): Promise<AuthRunListResponse> {
|
|
1682
|
+
return await this.transport.listAuthRuns(workspaceId, options);
|
|
1683
|
+
}
|
|
1684
|
+
|
|
1685
|
+
async get(
|
|
1686
|
+
workspaceId: string,
|
|
1687
|
+
authRunId: string,
|
|
1688
|
+
options: OpenGeniRequestOptions = {},
|
|
1689
|
+
): Promise<AuthRun> {
|
|
1690
|
+
return await this.transport.getAuthRun(workspaceId, authRunId, options);
|
|
1691
|
+
}
|
|
1692
|
+
|
|
1693
|
+
run(workspaceId: string, browserSessionId: string, authRunId: string): AuthRunResource {
|
|
1694
|
+
return new AuthRunResource(this.transport, workspaceId, browserSessionId, authRunId);
|
|
1695
|
+
}
|
|
1696
|
+
}
|
|
1697
|
+
|
|
1698
|
+
export class BrowserAuthRunCollection {
|
|
1699
|
+
constructor(
|
|
1700
|
+
private readonly transport: BrowserInteractionTransport,
|
|
1701
|
+
readonly workspaceId: string,
|
|
1702
|
+
readonly browserSessionId: string,
|
|
1703
|
+
) {}
|
|
1704
|
+
|
|
1705
|
+
async list(
|
|
1706
|
+
options: Omit<AuthRunListOptions, "browserSessionId"> = {},
|
|
1707
|
+
): Promise<AuthRunListResponse> {
|
|
1708
|
+
return await this.transport.listAuthRuns(this.workspaceId, {
|
|
1709
|
+
...options,
|
|
1710
|
+
browserSessionId: this.browserSessionId,
|
|
1711
|
+
});
|
|
1712
|
+
}
|
|
1713
|
+
|
|
1714
|
+
run(authRunId: string): AuthRunResource {
|
|
1715
|
+
return new AuthRunResource(this.transport, this.workspaceId, this.browserSessionId, authRunId);
|
|
1716
|
+
}
|
|
1717
|
+
|
|
1718
|
+
async start(
|
|
1719
|
+
request: StartAuthRunRequest,
|
|
1720
|
+
options: OpenGeniRequestOptions = {},
|
|
1721
|
+
): Promise<AuthRunResource> {
|
|
1722
|
+
const response = await this.transport.startBrowserAuthRun(
|
|
1723
|
+
this.workspaceId,
|
|
1724
|
+
this.browserSessionId,
|
|
1725
|
+
request,
|
|
1726
|
+
options,
|
|
1727
|
+
);
|
|
1728
|
+
return this.run(response.run.id);
|
|
1729
|
+
}
|
|
1730
|
+
}
|
|
1731
|
+
|
|
1732
|
+
export class AuthRunResource {
|
|
1733
|
+
constructor(
|
|
1734
|
+
private readonly transport: BrowserInteractionTransport,
|
|
1735
|
+
readonly workspaceId: string,
|
|
1736
|
+
readonly browserSessionId: string,
|
|
1737
|
+
readonly id: string,
|
|
1738
|
+
) {}
|
|
1739
|
+
|
|
1740
|
+
async get(options: OpenGeniRequestOptions = {}): Promise<AuthRun> {
|
|
1741
|
+
const run = await this.transport.getAuthRun(this.workspaceId, this.id, options);
|
|
1742
|
+
if (run.browserSessionId !== this.browserSessionId) {
|
|
1743
|
+
throw new Error("AuthRun belongs to another BrowserSession");
|
|
1744
|
+
}
|
|
1745
|
+
return run;
|
|
1746
|
+
}
|
|
1747
|
+
|
|
1748
|
+
async report(
|
|
1749
|
+
request: ReportAuthRunRequest,
|
|
1750
|
+
options: OpenGeniRequestOptions = {},
|
|
1751
|
+
): Promise<AuthRunMutationResponse> {
|
|
1752
|
+
return await this.transport.reportBrowserAuthRun(
|
|
1753
|
+
this.workspaceId,
|
|
1754
|
+
this.browserSessionId,
|
|
1755
|
+
this.id,
|
|
1756
|
+
request,
|
|
1757
|
+
options,
|
|
1758
|
+
);
|
|
1759
|
+
}
|
|
1760
|
+
|
|
1761
|
+
async protectedFill(
|
|
1762
|
+
request: ProtectedAuthFillRequest,
|
|
1763
|
+
options: OpenGeniRequestOptions = {},
|
|
1764
|
+
): Promise<ProtectedAuthFillResponse> {
|
|
1765
|
+
return await this.transport.protectedBrowserAuthFill(
|
|
1766
|
+
this.workspaceId,
|
|
1767
|
+
this.browserSessionId,
|
|
1768
|
+
this.id,
|
|
1769
|
+
request,
|
|
1770
|
+
options,
|
|
1771
|
+
);
|
|
1772
|
+
}
|
|
1773
|
+
|
|
1774
|
+
async advanceExternal(
|
|
1775
|
+
request: ExternalAuthRunRequest,
|
|
1776
|
+
options: OpenGeniRequestOptions = {},
|
|
1777
|
+
): Promise<ExternalAuthRunResponse> {
|
|
1778
|
+
return await this.transport.advanceExternalBrowserAuthRun(
|
|
1779
|
+
this.workspaceId,
|
|
1780
|
+
this.browserSessionId,
|
|
1781
|
+
this.id,
|
|
1782
|
+
request,
|
|
1783
|
+
options,
|
|
1784
|
+
);
|
|
1785
|
+
}
|
|
1786
|
+
|
|
1787
|
+
/** Human-session helper. Hosted provider URLs never appear in model tools. */
|
|
1788
|
+
async openExternalFlow(
|
|
1789
|
+
request: ExternalAuthInteractiveRequest,
|
|
1790
|
+
options: OpenGeniRequestOptions = {},
|
|
1791
|
+
): Promise<ExternalAuthInteractiveResponse> {
|
|
1792
|
+
return await this.transport.openExternalBrowserAuthFlow(
|
|
1793
|
+
this.workspaceId,
|
|
1794
|
+
this.browserSessionId,
|
|
1795
|
+
this.id,
|
|
1796
|
+
request,
|
|
1797
|
+
options,
|
|
1798
|
+
);
|
|
1799
|
+
}
|
|
1800
|
+
|
|
1801
|
+
async verify(
|
|
1802
|
+
request: VerifyAuthRunRequest,
|
|
1803
|
+
options: OpenGeniRequestOptions = {},
|
|
1804
|
+
): Promise<AuthRunMutationResponse> {
|
|
1805
|
+
return await this.transport.verifyBrowserAuthRun(
|
|
1806
|
+
this.workspaceId,
|
|
1807
|
+
this.browserSessionId,
|
|
1808
|
+
this.id,
|
|
1809
|
+
request,
|
|
1810
|
+
options,
|
|
1811
|
+
);
|
|
1812
|
+
}
|
|
1813
|
+
}
|
|
1814
|
+
|
|
1815
|
+
export class InteractionInterventionCollection {
|
|
1816
|
+
constructor(private readonly transport: BrowserInteractionTransport) {}
|
|
1817
|
+
|
|
1818
|
+
async list(
|
|
1819
|
+
workspaceId: string,
|
|
1820
|
+
options: InteractionInterventionListOptions = {},
|
|
1821
|
+
): Promise<InteractionInterventionListResponse> {
|
|
1822
|
+
return await this.transport.listInteractionInterventions(workspaceId, options);
|
|
1823
|
+
}
|
|
1824
|
+
|
|
1825
|
+
intervention(workspaceId: string, interventionId: string): InteractionInterventionResource {
|
|
1826
|
+
return new InteractionInterventionResource(this.transport, workspaceId, interventionId);
|
|
1827
|
+
}
|
|
1828
|
+
|
|
1829
|
+
async create(
|
|
1830
|
+
workspaceId: string,
|
|
1831
|
+
request: CreateInteractionInterventionRequest,
|
|
1832
|
+
options: OpenGeniRequestOptions = {},
|
|
1833
|
+
): Promise<InteractionInterventionResource> {
|
|
1834
|
+
const response = await this.transport.createInteractionIntervention(
|
|
1835
|
+
workspaceId,
|
|
1836
|
+
request,
|
|
1837
|
+
options,
|
|
1838
|
+
);
|
|
1839
|
+
return this.intervention(workspaceId, response.intervention.id);
|
|
1840
|
+
}
|
|
1841
|
+
}
|
|
1842
|
+
|
|
1843
|
+
export class InteractionInterventionResource {
|
|
1844
|
+
constructor(
|
|
1845
|
+
private readonly transport: BrowserInteractionTransport,
|
|
1846
|
+
readonly workspaceId: string,
|
|
1847
|
+
readonly id: string,
|
|
1848
|
+
) {}
|
|
1849
|
+
|
|
1850
|
+
async get(options: OpenGeniRequestOptions = {}): Promise<InteractionIntervention> {
|
|
1851
|
+
return await this.transport.getInteractionIntervention(this.workspaceId, this.id, options);
|
|
1852
|
+
}
|
|
1853
|
+
|
|
1854
|
+
async resolve(
|
|
1855
|
+
request: ResolveInteractionInterventionRequest,
|
|
1856
|
+
options: OpenGeniRequestOptions = {},
|
|
1857
|
+
): Promise<InteractionInterventionMutationResponse> {
|
|
1858
|
+
return await this.transport.resolveInteractionIntervention(
|
|
1859
|
+
this.workspaceId,
|
|
1860
|
+
this.id,
|
|
1861
|
+
request,
|
|
1862
|
+
options,
|
|
1863
|
+
);
|
|
1864
|
+
}
|
|
1865
|
+
}
|
|
1866
|
+
|
|
1867
|
+
export class AttachedBrowserDeviceCollection {
|
|
1868
|
+
constructor(private readonly transport: BrowserInteractionTransport) {}
|
|
1869
|
+
|
|
1870
|
+
async list(
|
|
1871
|
+
workspaceId: string,
|
|
1872
|
+
options: AttachedBrowserDeviceListOptions = {},
|
|
1873
|
+
): Promise<AttachedBrowserDeviceListResponse> {
|
|
1874
|
+
return await this.transport.listAttachedBrowsers(workspaceId, options);
|
|
1875
|
+
}
|
|
1876
|
+
|
|
1877
|
+
device(workspaceId: string, deviceId: string): AttachedBrowserDeviceResource {
|
|
1878
|
+
return new AttachedBrowserDeviceResource(this.transport, workspaceId, deviceId);
|
|
1879
|
+
}
|
|
1880
|
+
}
|
|
1881
|
+
|
|
1882
|
+
export class AttachedBrowserDeviceResource {
|
|
1883
|
+
constructor(
|
|
1884
|
+
private readonly transport: BrowserInteractionTransport,
|
|
1885
|
+
readonly workspaceId: string,
|
|
1886
|
+
readonly id: string,
|
|
1887
|
+
) {}
|
|
1888
|
+
|
|
1889
|
+
async get(options: OpenGeniRequestOptions = {}): Promise<AttachedBrowserDevice> {
|
|
1890
|
+
return await this.transport.getAttachedBrowser(this.workspaceId, this.id, options);
|
|
1891
|
+
}
|
|
1892
|
+
}
|
|
1893
|
+
|
|
1894
|
+
export class BrowserIdentityCollection {
|
|
1895
|
+
constructor(private readonly transport: BrowserInteractionTransport) {}
|
|
1896
|
+
|
|
1897
|
+
async list(
|
|
1898
|
+
workspaceId: string,
|
|
1899
|
+
options: BrowserIdentityListOptions = {},
|
|
1900
|
+
): Promise<BrowserIdentityListResponse> {
|
|
1901
|
+
return await this.transport.listBrowserIdentities(workspaceId, options);
|
|
1902
|
+
}
|
|
1903
|
+
|
|
1904
|
+
identity(workspaceId: string, identityId: string): BrowserIdentityResource {
|
|
1905
|
+
return new BrowserIdentityResource(this.transport, workspaceId, identityId);
|
|
1906
|
+
}
|
|
1907
|
+
|
|
1908
|
+
async create(
|
|
1909
|
+
workspaceId: string,
|
|
1910
|
+
request: CreateBrowserIdentityRequest,
|
|
1911
|
+
options: OpenGeniRequestOptions = {},
|
|
1912
|
+
): Promise<BrowserIdentityResource> {
|
|
1913
|
+
const response = await this.transport.createBrowserIdentity(workspaceId, request, options);
|
|
1914
|
+
return this.identity(workspaceId, response.identity.id);
|
|
1915
|
+
}
|
|
1916
|
+
}
|
|
1917
|
+
|
|
1918
|
+
export class BrowserIdentityResource {
|
|
1919
|
+
constructor(
|
|
1920
|
+
private readonly transport: BrowserInteractionTransport,
|
|
1921
|
+
readonly workspaceId: string,
|
|
1922
|
+
readonly id: string,
|
|
1923
|
+
) {}
|
|
1924
|
+
|
|
1925
|
+
async get(options: OpenGeniRequestOptions = {}): Promise<BrowserIdentity> {
|
|
1926
|
+
return await this.transport.getBrowserIdentity(this.workspaceId, this.id, options);
|
|
1927
|
+
}
|
|
1928
|
+
|
|
1929
|
+
async revisions(options: OpenGeniRequestOptions = {}): Promise<BrowserRevisionListResponse> {
|
|
1930
|
+
return await this.transport.listBrowserRevisions(this.workspaceId, this.id, options);
|
|
1931
|
+
}
|
|
1932
|
+
|
|
1933
|
+
async update(
|
|
1934
|
+
request: UpdateBrowserIdentityRequest,
|
|
1935
|
+
options: OpenGeniRequestOptions = {},
|
|
1936
|
+
): Promise<BrowserIdentityMutationResponse> {
|
|
1937
|
+
return await this.transport.updateBrowserIdentity(this.workspaceId, this.id, request, options);
|
|
1938
|
+
}
|
|
1939
|
+
}
|
|
1940
|
+
|
|
1941
|
+
export class BrowserSessionCollection {
|
|
1942
|
+
constructor(private readonly transport: BrowserInteractionTransport) {}
|
|
1943
|
+
|
|
1944
|
+
async list(
|
|
1945
|
+
workspaceId: string,
|
|
1946
|
+
options: OpenGeniRequestOptions = {},
|
|
1947
|
+
): Promise<BrowserSessionListResponse> {
|
|
1948
|
+
return await this.transport.listBrowserSessions(workspaceId, options);
|
|
1949
|
+
}
|
|
1950
|
+
|
|
1951
|
+
session(workspaceId: string, browserSessionId: string): BrowserSessionResource {
|
|
1952
|
+
return new BrowserSessionResource(this.transport, workspaceId, browserSessionId);
|
|
1953
|
+
}
|
|
1954
|
+
|
|
1955
|
+
async open(
|
|
1956
|
+
workspaceId: string,
|
|
1957
|
+
request: CreateBrowserSessionRequest,
|
|
1958
|
+
options: OpenGeniRequestOptions = {},
|
|
1959
|
+
): Promise<BrowserSessionResource> {
|
|
1960
|
+
const response = await this.transport.createBrowserSession(workspaceId, request, options);
|
|
1961
|
+
return this.session(workspaceId, response.session.id);
|
|
1962
|
+
}
|
|
1963
|
+
|
|
1964
|
+
async currentOrOpen(options: CurrentOrOpenBrowserOptions): Promise<BrowserSessionResource> {
|
|
1965
|
+
const requestOptions = options.signal ? { signal: options.signal } : {};
|
|
1966
|
+
const listed = await this.list(options.workspaceId, requestOptions);
|
|
1967
|
+
const current = newestRelevantBrowser(listed.sessions, options.associationSessionId);
|
|
1968
|
+
if (current) {
|
|
1969
|
+
const resource = this.session(options.workspaceId, current.id);
|
|
1970
|
+
if (current.lifecycle === "suspended") {
|
|
1971
|
+
await resource.resume(
|
|
1972
|
+
{ operationId: options.operationId ?? crypto.randomUUID() },
|
|
1973
|
+
requestOptions,
|
|
1974
|
+
);
|
|
1975
|
+
}
|
|
1976
|
+
return resource;
|
|
1977
|
+
}
|
|
1978
|
+
return await this.open(
|
|
1979
|
+
options.workspaceId,
|
|
1980
|
+
{
|
|
1981
|
+
operationId: options.operationId ?? crypto.randomUUID(),
|
|
1982
|
+
sessionId: options.associationSessionId,
|
|
1983
|
+
...(options.name !== undefined ? { name: options.name } : {}),
|
|
1984
|
+
...(options.initialUrl !== undefined ? { initialUrl: options.initialUrl } : {}),
|
|
1985
|
+
...(options.headless !== undefined ? { headless: options.headless } : {}),
|
|
1986
|
+
...(options.placement !== undefined ? { placement: options.placement } : {}),
|
|
1987
|
+
...(options.identityId !== undefined ? { identityId: options.identityId } : {}),
|
|
1988
|
+
...(options.baseRevisionId !== undefined ? { baseRevisionId: options.baseRevisionId } : {}),
|
|
1989
|
+
...(options.networkRouteId !== undefined ? { networkRouteId: options.networkRouteId } : {}),
|
|
1990
|
+
...(options.linkedComputerSessionId !== undefined
|
|
1991
|
+
? { linkedComputerSessionId: options.linkedComputerSessionId }
|
|
1992
|
+
: {}),
|
|
1993
|
+
},
|
|
1994
|
+
requestOptions,
|
|
1995
|
+
);
|
|
1996
|
+
}
|
|
1997
|
+
}
|
|
1998
|
+
|
|
1999
|
+
export class BrowserSessionResource {
|
|
2000
|
+
readonly auth: BrowserAuthRunCollection;
|
|
2001
|
+
readonly clipboard: BrowserClipboardResource;
|
|
2002
|
+
readonly downloads: BrowserDownloadCollection;
|
|
2003
|
+
readonly tabs: BrowserTargetCollection;
|
|
2004
|
+
/** Alias for hosts that prefer the protocol term. */
|
|
2005
|
+
readonly targets: BrowserTargetCollection;
|
|
2006
|
+
|
|
2007
|
+
constructor(
|
|
2008
|
+
private readonly transport: BrowserInteractionTransport,
|
|
2009
|
+
readonly workspaceId: string,
|
|
2010
|
+
readonly id: string,
|
|
2011
|
+
) {
|
|
2012
|
+
this.auth = new BrowserAuthRunCollection(transport, workspaceId, id);
|
|
2013
|
+
this.clipboard = new BrowserClipboardResource(transport, workspaceId, id);
|
|
2014
|
+
this.downloads = new BrowserDownloadCollection(transport, workspaceId, id);
|
|
2015
|
+
this.tabs = new BrowserTargetCollection(transport, workspaceId, id);
|
|
2016
|
+
this.targets = this.tabs;
|
|
2017
|
+
}
|
|
2018
|
+
|
|
2019
|
+
async get(options: OpenGeniRequestOptions = {}): Promise<BrowserSession> {
|
|
2020
|
+
return await this.transport.getBrowserSession(this.workspaceId, this.id, options);
|
|
2021
|
+
}
|
|
2022
|
+
|
|
2023
|
+
async observe(
|
|
2024
|
+
targetId: string,
|
|
2025
|
+
options: OpenGeniRequestOptions = {},
|
|
2026
|
+
): Promise<BrowserObservation> {
|
|
2027
|
+
return await this.transport.observeBrowserTarget(this.workspaceId, this.id, targetId, options);
|
|
2028
|
+
}
|
|
2029
|
+
|
|
2030
|
+
async act(
|
|
2031
|
+
request: BrowserActionRequest,
|
|
2032
|
+
options: OpenGeniRequestOptions = {},
|
|
2033
|
+
): Promise<BrowserActionReceipt> {
|
|
2034
|
+
return await this.transport.actInBrowser(this.workspaceId, this.id, request, options);
|
|
2035
|
+
}
|
|
2036
|
+
|
|
2037
|
+
async receipt(
|
|
2038
|
+
operationId: string,
|
|
2039
|
+
options: OpenGeniRequestOptions = {},
|
|
2040
|
+
): Promise<BrowserActionReceipt> {
|
|
2041
|
+
return await this.transport.getBrowserActionReceipt(
|
|
2042
|
+
this.workspaceId,
|
|
2043
|
+
this.id,
|
|
2044
|
+
operationId,
|
|
2045
|
+
options,
|
|
2046
|
+
);
|
|
2047
|
+
}
|
|
2048
|
+
|
|
2049
|
+
async diagnostics(
|
|
2050
|
+
targetId: string,
|
|
2051
|
+
options: BrowserDiagnosticsOptions = {},
|
|
2052
|
+
): Promise<BrowserDiagnosticBatch> {
|
|
2053
|
+
return await this.transport.listBrowserDiagnostics(
|
|
2054
|
+
this.workspaceId,
|
|
2055
|
+
this.id,
|
|
2056
|
+
targetId,
|
|
2057
|
+
options,
|
|
2058
|
+
);
|
|
2059
|
+
}
|
|
2060
|
+
|
|
2061
|
+
async attach(
|
|
2062
|
+
request: BrowserSessionAttachmentRequest,
|
|
2063
|
+
options: OpenGeniRequestOptions = {},
|
|
2064
|
+
): Promise<BrowserSessionAttachment> {
|
|
2065
|
+
return await this.transport.attachBrowserSession(this.workspaceId, this.id, request, options);
|
|
2066
|
+
}
|
|
2067
|
+
|
|
2068
|
+
async heartbeat(options: OpenGeniRequestOptions = {}): Promise<BrowserSessionHeartbeatResponse> {
|
|
2069
|
+
return await this.transport.heartbeatBrowserSession(this.workspaceId, this.id, options);
|
|
2070
|
+
}
|
|
2071
|
+
|
|
2072
|
+
async publishRevision(
|
|
2073
|
+
request: PublishBrowserRevisionRequest,
|
|
2074
|
+
options: OpenGeniRequestOptions = {},
|
|
2075
|
+
): Promise<PublishBrowserRevisionResponse> {
|
|
2076
|
+
return await this.transport.publishBrowserRevision(this.workspaceId, this.id, request, options);
|
|
2077
|
+
}
|
|
2078
|
+
|
|
2079
|
+
async suspend(
|
|
2080
|
+
request: BrowserSessionLifecycleRequest = {
|
|
2081
|
+
operationId: crypto.randomUUID(),
|
|
2082
|
+
},
|
|
2083
|
+
options: OpenGeniRequestOptions = {},
|
|
2084
|
+
): Promise<BrowserSessionMutationResponse> {
|
|
2085
|
+
return await this.transport.suspendBrowserSession(this.workspaceId, this.id, request, options);
|
|
2086
|
+
}
|
|
2087
|
+
|
|
2088
|
+
async resume(
|
|
2089
|
+
request: BrowserSessionLifecycleRequest = {
|
|
2090
|
+
operationId: crypto.randomUUID(),
|
|
2091
|
+
},
|
|
2092
|
+
options: OpenGeniRequestOptions = {},
|
|
2093
|
+
): Promise<BrowserSessionMutationResponse> {
|
|
2094
|
+
return await this.transport.resumeBrowserSession(this.workspaceId, this.id, request, options);
|
|
2095
|
+
}
|
|
2096
|
+
|
|
2097
|
+
async end(
|
|
2098
|
+
request: BrowserSessionLifecycleRequest = {
|
|
2099
|
+
operationId: crypto.randomUUID(),
|
|
2100
|
+
},
|
|
2101
|
+
options: OpenGeniRequestOptions = {},
|
|
2102
|
+
): Promise<BrowserSessionMutationResponse> {
|
|
2103
|
+
return await this.transport.endBrowserSession(this.workspaceId, this.id, request, options);
|
|
2104
|
+
}
|
|
2105
|
+
}
|
|
2106
|
+
|
|
2107
|
+
export class BrowserClipboardResource {
|
|
2108
|
+
constructor(
|
|
2109
|
+
private readonly transport: BrowserInteractionTransport,
|
|
2110
|
+
readonly workspaceId: string,
|
|
2111
|
+
readonly browserSessionId: string,
|
|
2112
|
+
) {}
|
|
2113
|
+
|
|
2114
|
+
async read(options: OpenGeniRequestOptions = {}): Promise<BrowserClipboard> {
|
|
2115
|
+
const clipboard = await this.transport.readBrowserClipboard(
|
|
2116
|
+
this.workspaceId,
|
|
2117
|
+
this.browserSessionId,
|
|
2118
|
+
options,
|
|
2119
|
+
);
|
|
2120
|
+
if (clipboard.browserSessionId !== this.browserSessionId) {
|
|
2121
|
+
throw new Error("Browser clipboard belongs to another BrowserSession");
|
|
2122
|
+
}
|
|
2123
|
+
return clipboard;
|
|
2124
|
+
}
|
|
2125
|
+
}
|
|
2126
|
+
|
|
2127
|
+
export class BrowserDownloadCollection {
|
|
2128
|
+
constructor(
|
|
2129
|
+
private readonly transport: BrowserInteractionTransport,
|
|
2130
|
+
readonly workspaceId: string,
|
|
2131
|
+
readonly browserSessionId: string,
|
|
2132
|
+
) {}
|
|
2133
|
+
|
|
2134
|
+
async list(options: OpenGeniRequestOptions = {}): Promise<BrowserDownloadListResponse> {
|
|
2135
|
+
return await this.transport.listBrowserDownloads(
|
|
2136
|
+
this.workspaceId,
|
|
2137
|
+
this.browserSessionId,
|
|
2138
|
+
options,
|
|
2139
|
+
);
|
|
2140
|
+
}
|
|
2141
|
+
|
|
2142
|
+
download(downloadId: string): BrowserDownloadResource {
|
|
2143
|
+
return new BrowserDownloadResource(
|
|
2144
|
+
this.transport,
|
|
2145
|
+
this.workspaceId,
|
|
2146
|
+
this.browserSessionId,
|
|
2147
|
+
downloadId,
|
|
2148
|
+
);
|
|
2149
|
+
}
|
|
2150
|
+
}
|
|
2151
|
+
|
|
2152
|
+
export class BrowserDownloadResource {
|
|
2153
|
+
constructor(
|
|
2154
|
+
private readonly transport: BrowserInteractionTransport,
|
|
2155
|
+
readonly workspaceId: string,
|
|
2156
|
+
readonly browserSessionId: string,
|
|
2157
|
+
readonly id: string,
|
|
2158
|
+
) {}
|
|
2159
|
+
|
|
2160
|
+
async get(options: OpenGeniRequestOptions = {}): Promise<BrowserDownload> {
|
|
2161
|
+
const download = await this.transport.getBrowserDownload(
|
|
2162
|
+
this.workspaceId,
|
|
2163
|
+
this.browserSessionId,
|
|
2164
|
+
this.id,
|
|
2165
|
+
options,
|
|
2166
|
+
);
|
|
2167
|
+
if (download.browserSessionId !== this.browserSessionId) {
|
|
2168
|
+
throw new Error("BrowserDownload belongs to another BrowserSession");
|
|
2169
|
+
}
|
|
2170
|
+
return download;
|
|
2171
|
+
}
|
|
2172
|
+
|
|
2173
|
+
/** Publish this exact private browser download into the source session's
|
|
2174
|
+
* workspace. Pass an operationId when the caller needs retry identity across
|
|
2175
|
+
* process boundaries; otherwise one is generated for this call. */
|
|
2176
|
+
async saveToWorkspace(
|
|
2177
|
+
destinationPath: string,
|
|
2178
|
+
options: BrowserDownloadSaveOptions = {},
|
|
2179
|
+
): Promise<BrowserDownloadSaveResponse> {
|
|
2180
|
+
const { operationId = crypto.randomUUID(), overwrite = false, ...requestOptions } = options;
|
|
2181
|
+
const response = await this.transport.saveBrowserDownload(
|
|
2182
|
+
this.workspaceId,
|
|
2183
|
+
this.browserSessionId,
|
|
2184
|
+
this.id,
|
|
2185
|
+
{ operationId, destinationPath, overwrite },
|
|
2186
|
+
requestOptions,
|
|
2187
|
+
);
|
|
2188
|
+
if (
|
|
2189
|
+
response.download.id !== this.id ||
|
|
2190
|
+
response.download.browserSessionId !== this.browserSessionId
|
|
2191
|
+
) {
|
|
2192
|
+
throw new Error("BrowserDownload save returned another resource");
|
|
2193
|
+
}
|
|
2194
|
+
return response;
|
|
2195
|
+
}
|
|
2196
|
+
}
|
|
2197
|
+
|
|
2198
|
+
export class BrowserTargetCollection {
|
|
2199
|
+
constructor(
|
|
2200
|
+
private readonly transport: BrowserInteractionTransport,
|
|
2201
|
+
private readonly workspaceId: string,
|
|
2202
|
+
private readonly browserSessionId: string,
|
|
2203
|
+
) {}
|
|
2204
|
+
|
|
2205
|
+
async list(options: OpenGeniRequestOptions = {}): Promise<BrowserTargetListResponse> {
|
|
2206
|
+
return await this.transport.listBrowserTargets(
|
|
2207
|
+
this.workspaceId,
|
|
2208
|
+
this.browserSessionId,
|
|
2209
|
+
options,
|
|
2210
|
+
);
|
|
2211
|
+
}
|
|
2212
|
+
|
|
2213
|
+
async open(url?: string, options: OpenGeniRequestOptions = {}): Promise<BrowserObservation> {
|
|
2214
|
+
return await this.transport.openBrowserTarget(
|
|
2215
|
+
this.workspaceId,
|
|
2216
|
+
this.browserSessionId,
|
|
2217
|
+
url === undefined ? {} : { url },
|
|
2218
|
+
options,
|
|
2219
|
+
);
|
|
2220
|
+
}
|
|
2221
|
+
|
|
2222
|
+
async select(
|
|
2223
|
+
targetId: string,
|
|
2224
|
+
options: OpenGeniRequestOptions = {},
|
|
2225
|
+
): Promise<BrowserObservation> {
|
|
2226
|
+
return await this.transport.selectBrowserTarget(
|
|
2227
|
+
this.workspaceId,
|
|
2228
|
+
this.browserSessionId,
|
|
2229
|
+
targetId,
|
|
2230
|
+
options,
|
|
2231
|
+
);
|
|
2232
|
+
}
|
|
2233
|
+
|
|
2234
|
+
async close(
|
|
2235
|
+
targetId: string,
|
|
2236
|
+
options: OpenGeniRequestOptions = {},
|
|
2237
|
+
): Promise<BrowserTargetListResponse> {
|
|
2238
|
+
return await this.transport.closeBrowserTarget(
|
|
2239
|
+
this.workspaceId,
|
|
2240
|
+
this.browserSessionId,
|
|
2241
|
+
targetId,
|
|
2242
|
+
options,
|
|
2243
|
+
);
|
|
2244
|
+
}
|
|
2245
|
+
}
|
|
2246
|
+
|
|
2247
|
+
export class ComputerSessionCollection {
|
|
2248
|
+
constructor(private readonly transport: BrowserInteractionTransport) {}
|
|
2249
|
+
|
|
2250
|
+
async list(
|
|
2251
|
+
workspaceId: string,
|
|
2252
|
+
options: OpenGeniRequestOptions = {},
|
|
2253
|
+
): Promise<ComputerSessionListResponse> {
|
|
2254
|
+
return await this.transport.listComputerSessions(workspaceId, options);
|
|
2255
|
+
}
|
|
2256
|
+
|
|
2257
|
+
session(workspaceId: string, computerSessionId: string): ComputerSessionResource {
|
|
2258
|
+
return new ComputerSessionResource(this.transport, workspaceId, computerSessionId);
|
|
2259
|
+
}
|
|
2260
|
+
|
|
2261
|
+
async open(
|
|
2262
|
+
workspaceId: string,
|
|
2263
|
+
request: CreateComputerSessionRequest,
|
|
2264
|
+
options: OpenGeniRequestOptions = {},
|
|
2265
|
+
): Promise<ComputerSessionResource> {
|
|
2266
|
+
const response = await this.transport.createComputerSession(workspaceId, request, options);
|
|
2267
|
+
return this.session(workspaceId, response.session.id);
|
|
2268
|
+
}
|
|
2269
|
+
|
|
2270
|
+
async currentOrOpen(options: CurrentOrOpenComputerOptions): Promise<ComputerSessionResource> {
|
|
2271
|
+
const requestOptions = options.signal ? { signal: options.signal } : {};
|
|
2272
|
+
const listed = await this.list(options.workspaceId, requestOptions);
|
|
2273
|
+
const current = newestRelevantComputer(listed.sessions, options.associationSessionId);
|
|
2274
|
+
if (current) {
|
|
2275
|
+
return this.session(options.workspaceId, current.id);
|
|
2276
|
+
}
|
|
2277
|
+
return await this.open(
|
|
2278
|
+
options.workspaceId,
|
|
2279
|
+
{
|
|
2280
|
+
operationId: options.operationId ?? crypto.randomUUID(),
|
|
2281
|
+
sessionId: options.associationSessionId,
|
|
2282
|
+
...(options.name !== undefined ? { name: options.name } : {}),
|
|
2283
|
+
...(options.placement !== undefined ? { placement: options.placement } : {}),
|
|
2284
|
+
},
|
|
2285
|
+
requestOptions,
|
|
2286
|
+
);
|
|
2287
|
+
}
|
|
2288
|
+
}
|
|
2289
|
+
|
|
2290
|
+
export class ComputerSessionResource {
|
|
2291
|
+
readonly targets: ComputerTargetCollection;
|
|
2292
|
+
/** Native application/window targets are also the public app collection. */
|
|
2293
|
+
readonly apps: ComputerTargetCollection;
|
|
2294
|
+
readonly clipboard: ComputerClipboardResource;
|
|
2295
|
+
|
|
2296
|
+
constructor(
|
|
2297
|
+
private readonly transport: BrowserInteractionTransport,
|
|
2298
|
+
readonly workspaceId: string,
|
|
2299
|
+
readonly id: string,
|
|
2300
|
+
) {
|
|
2301
|
+
this.targets = new ComputerTargetCollection(transport, workspaceId, id);
|
|
2302
|
+
this.apps = this.targets;
|
|
2303
|
+
this.clipboard = new ComputerClipboardResource(transport, workspaceId, id);
|
|
2304
|
+
}
|
|
2305
|
+
|
|
2306
|
+
async get(options: OpenGeniRequestOptions = {}): Promise<ComputerSession> {
|
|
2307
|
+
return await this.transport.getComputerSession(this.workspaceId, this.id, options);
|
|
2308
|
+
}
|
|
2309
|
+
|
|
2310
|
+
async observe(
|
|
2311
|
+
targetId: string,
|
|
2312
|
+
options: OpenGeniRequestOptions = {},
|
|
2313
|
+
): Promise<ComputerObservation> {
|
|
2314
|
+
return await this.transport.observeComputerTarget(this.workspaceId, this.id, targetId, options);
|
|
2315
|
+
}
|
|
2316
|
+
|
|
2317
|
+
async act(
|
|
2318
|
+
request: ComputerActionRequest,
|
|
2319
|
+
options: OpenGeniRequestOptions = {},
|
|
2320
|
+
): Promise<ComputerActionReceipt> {
|
|
2321
|
+
return await this.transport.actInComputer(this.workspaceId, this.id, request, options);
|
|
2322
|
+
}
|
|
2323
|
+
|
|
2324
|
+
async receipt(
|
|
2325
|
+
operationId: string,
|
|
2326
|
+
options: OpenGeniRequestOptions = {},
|
|
2327
|
+
): Promise<ComputerActionReceipt> {
|
|
2328
|
+
return await this.transport.getComputerActionReceipt(
|
|
2329
|
+
this.workspaceId,
|
|
2330
|
+
this.id,
|
|
2331
|
+
operationId,
|
|
2332
|
+
options,
|
|
2333
|
+
);
|
|
2334
|
+
}
|
|
2335
|
+
|
|
2336
|
+
async attach(
|
|
2337
|
+
request: ComputerSessionAttachmentRequest,
|
|
2338
|
+
options: OpenGeniRequestOptions = {},
|
|
2339
|
+
): Promise<ComputerSessionAttachment> {
|
|
2340
|
+
return await this.transport.attachComputerSession(this.workspaceId, this.id, request, options);
|
|
2341
|
+
}
|
|
2342
|
+
|
|
2343
|
+
async heartbeat(options: OpenGeniRequestOptions = {}): Promise<ComputerSessionHeartbeatResponse> {
|
|
2344
|
+
return await this.transport.heartbeatComputerSession(this.workspaceId, this.id, options);
|
|
2345
|
+
}
|
|
2346
|
+
|
|
2347
|
+
async end(
|
|
2348
|
+
request: ComputerSessionLifecycleRequest = { operationId: crypto.randomUUID() },
|
|
2349
|
+
options: OpenGeniRequestOptions = {},
|
|
2350
|
+
): Promise<ComputerSessionMutationResponse> {
|
|
2351
|
+
return await this.transport.endComputerSession(this.workspaceId, this.id, request, options);
|
|
2352
|
+
}
|
|
2353
|
+
}
|
|
2354
|
+
|
|
2355
|
+
export class ComputerClipboardResource {
|
|
2356
|
+
constructor(
|
|
2357
|
+
private readonly transport: BrowserInteractionTransport,
|
|
2358
|
+
readonly workspaceId: string,
|
|
2359
|
+
readonly computerSessionId: string,
|
|
2360
|
+
) {}
|
|
2361
|
+
|
|
2362
|
+
async read(options: OpenGeniRequestOptions = {}): Promise<ComputerClipboard> {
|
|
2363
|
+
const clipboard = await this.transport.readComputerClipboard(
|
|
2364
|
+
this.workspaceId,
|
|
2365
|
+
this.computerSessionId,
|
|
2366
|
+
options,
|
|
2367
|
+
);
|
|
2368
|
+
if (clipboard.computerSessionId !== this.computerSessionId) {
|
|
2369
|
+
throw new Error("Computer clipboard belongs to another ComputerSession");
|
|
2370
|
+
}
|
|
2371
|
+
return clipboard;
|
|
2372
|
+
}
|
|
2373
|
+
}
|
|
2374
|
+
|
|
2375
|
+
export class ComputerTargetCollection {
|
|
2376
|
+
constructor(
|
|
2377
|
+
private readonly transport: BrowserInteractionTransport,
|
|
2378
|
+
private readonly workspaceId: string,
|
|
2379
|
+
private readonly computerSessionId: string,
|
|
2380
|
+
) {}
|
|
2381
|
+
|
|
2382
|
+
async list(options: OpenGeniRequestOptions = {}): Promise<ComputerTargetListResponse> {
|
|
2383
|
+
return await this.transport.listComputerTargets(
|
|
2384
|
+
this.workspaceId,
|
|
2385
|
+
this.computerSessionId,
|
|
2386
|
+
options,
|
|
2387
|
+
);
|
|
2388
|
+
}
|
|
2389
|
+
}
|
|
2390
|
+
|
|
2391
|
+
export type BrowserFrameMetadata = {
|
|
2392
|
+
frameId: string;
|
|
2393
|
+
browserSessionId: string;
|
|
2394
|
+
controllerGeneration: string;
|
|
2395
|
+
targetId: string;
|
|
2396
|
+
targetGeneration: string;
|
|
2397
|
+
documentGeneration: string;
|
|
2398
|
+
sequence: number;
|
|
2399
|
+
mediaType: "image/jpeg" | "image/png";
|
|
2400
|
+
width: number;
|
|
2401
|
+
height: number;
|
|
2402
|
+
deviceScaleFactor: number;
|
|
2403
|
+
scrollX: number;
|
|
2404
|
+
scrollY: number;
|
|
2405
|
+
capturedAt: string;
|
|
2406
|
+
};
|
|
2407
|
+
|
|
2408
|
+
export type BrowserFrame = BrowserFrameMetadata & { data: Uint8Array };
|
|
2409
|
+
|
|
2410
|
+
export type ComputerFrameMetadata = {
|
|
2411
|
+
frameId: string;
|
|
2412
|
+
computerSessionId: string;
|
|
2413
|
+
controllerGeneration: string;
|
|
2414
|
+
targetId: string;
|
|
2415
|
+
targetGeneration: string;
|
|
2416
|
+
sequence: number;
|
|
2417
|
+
mediaType: "image/jpeg" | "image/png";
|
|
2418
|
+
width: number;
|
|
2419
|
+
height: number;
|
|
2420
|
+
capturedAt: string;
|
|
2421
|
+
sha256: string;
|
|
2422
|
+
};
|
|
2423
|
+
|
|
2424
|
+
export type ComputerFrame = ComputerFrameMetadata & { data: Uint8Array };
|
|
2425
|
+
|
|
2426
|
+
export type BrowserFrameStreamOptions = InteractionFrameStreamOptions;
|
|
2427
|
+
|
|
2428
|
+
/** Convert a short-lived HTTP attachment URL into its browser WebSocket URL. */
|
|
2429
|
+
export function browserFrameSocketUrl(
|
|
2430
|
+
attachment: BrowserSessionAttachment,
|
|
2431
|
+
options: BrowserFrameStreamOptions = {},
|
|
2432
|
+
): string {
|
|
2433
|
+
if (attachment.stream.kind !== "direct_websocket") {
|
|
2434
|
+
throw new Error("relay browser attachments are opened through the relay protocol");
|
|
2435
|
+
}
|
|
2436
|
+
const url = new URL(attachment.stream.url);
|
|
2437
|
+
if (url.protocol === "http:") url.protocol = "ws:";
|
|
2438
|
+
else if (url.protocol === "https:") url.protocol = "wss:";
|
|
2439
|
+
else if (url.protocol !== "ws:" && url.protocol !== "wss:") {
|
|
2440
|
+
throw new Error("browser frame attachment did not contain an HTTP or WebSocket URL");
|
|
2441
|
+
}
|
|
2442
|
+
if (options.format !== undefined) url.searchParams.set("format", options.format);
|
|
2443
|
+
setBoundedIntegerQuery(url, "quality", options.quality, 1, 100);
|
|
2444
|
+
setBoundedIntegerQuery(url, "maxWidth", options.maxWidth, 1, 4_096);
|
|
2445
|
+
setBoundedIntegerQuery(url, "maxHeight", options.maxHeight, 1, 4_096);
|
|
2446
|
+
setBoundedIntegerQuery(url, "everyNthFrame", options.everyNthFrame, 1, 60);
|
|
2447
|
+
return url.toString();
|
|
2448
|
+
}
|
|
2449
|
+
|
|
2450
|
+
/** Convert a direct ComputerSession attachment into its WebSocket URL. */
|
|
2451
|
+
export function computerFrameSocketUrl(
|
|
2452
|
+
attachment: ComputerSessionAttachment,
|
|
2453
|
+
options: ComputerFrameStreamOptions = {},
|
|
2454
|
+
): string {
|
|
2455
|
+
if (attachment.stream.kind !== "direct_websocket") {
|
|
2456
|
+
throw new Error("relay computer attachments are opened through the relay protocol");
|
|
2457
|
+
}
|
|
2458
|
+
const url = new URL(attachment.stream.url);
|
|
2459
|
+
if (url.protocol === "http:") url.protocol = "ws:";
|
|
2460
|
+
else if (url.protocol === "https:") url.protocol = "wss:";
|
|
2461
|
+
else if (url.protocol !== "ws:" && url.protocol !== "wss:") {
|
|
2462
|
+
throw new Error("computer frame attachment did not contain an HTTP or WebSocket URL");
|
|
2463
|
+
}
|
|
2464
|
+
if (options.format !== undefined) url.searchParams.set("format", options.format);
|
|
2465
|
+
setBoundedIntegerQuery(url, "quality", options.quality, 1, 100);
|
|
2466
|
+
setBoundedIntegerQuery(url, "maxWidth", options.maxWidth, 1, 4_096);
|
|
2467
|
+
setBoundedIntegerQuery(url, "maxHeight", options.maxHeight, 1, 4_096);
|
|
2468
|
+
setBoundedIntegerQuery(url, "everyNthFrame", options.everyNthFrame, 1, 60);
|
|
2469
|
+
return url.toString();
|
|
2470
|
+
}
|
|
2471
|
+
|
|
2472
|
+
/** Decode one bounded binary frame message from the placement controller. */
|
|
2473
|
+
export function decodeBrowserFrameMessage(message: ArrayBuffer | Uint8Array): BrowserFrame {
|
|
2474
|
+
const bytes = message instanceof Uint8Array ? message : new Uint8Array(message);
|
|
2475
|
+
if (
|
|
2476
|
+
bytes.byteLength < 5 ||
|
|
2477
|
+
bytes.byteLength > 4 + BROWSER_CONTROL_MAX_FRAME_HEADER_BYTES + BROWSER_FRAME_MAX_BYTES
|
|
2478
|
+
) {
|
|
2479
|
+
throw new Error("browser frame message is truncated or too large");
|
|
2480
|
+
}
|
|
2481
|
+
const metadataLength = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength).getUint32(
|
|
2482
|
+
0,
|
|
2483
|
+
false,
|
|
2484
|
+
);
|
|
2485
|
+
if (
|
|
2486
|
+
metadataLength < 1 ||
|
|
2487
|
+
metadataLength > BROWSER_CONTROL_MAX_FRAME_HEADER_BYTES ||
|
|
2488
|
+
metadataLength + 4 >= bytes.byteLength
|
|
2489
|
+
) {
|
|
2490
|
+
throw new Error("browser frame metadata length is invalid");
|
|
2491
|
+
}
|
|
2492
|
+
let value: unknown;
|
|
2493
|
+
try {
|
|
2494
|
+
value = JSON.parse(
|
|
2495
|
+
new TextDecoder("utf-8", { fatal: true }).decode(bytes.subarray(4, 4 + metadataLength)),
|
|
2496
|
+
);
|
|
2497
|
+
} catch {
|
|
2498
|
+
throw new Error("browser frame metadata is invalid JSON");
|
|
2499
|
+
}
|
|
2500
|
+
const metadata = parseBrowserFrameMetadata(value);
|
|
2501
|
+
const data = bytes.slice(4 + metadataLength);
|
|
2502
|
+
if (data.byteLength < 1 || data.byteLength > BROWSER_FRAME_MAX_BYTES) {
|
|
2503
|
+
throw new Error("browser frame image is empty or too large");
|
|
2504
|
+
}
|
|
2505
|
+
const dimensions = imageDimensions(data, metadata.mediaType);
|
|
2506
|
+
if (dimensions.width !== metadata.width || dimensions.height !== metadata.height) {
|
|
2507
|
+
throw new Error("browser frame image dimensions do not match metadata");
|
|
2508
|
+
}
|
|
2509
|
+
return { ...metadata, data };
|
|
2510
|
+
}
|
|
2511
|
+
|
|
2512
|
+
/** Decode and authenticate one bounded ComputerSession frame. Computer frames
|
|
2513
|
+
* carry a content digest because native capture adapters may cross process and
|
|
2514
|
+
* relay boundaries before reaching the SDK. */
|
|
2515
|
+
export async function decodeComputerFrameMessage(
|
|
2516
|
+
message: ArrayBuffer | Uint8Array,
|
|
2517
|
+
): Promise<ComputerFrame> {
|
|
2518
|
+
const bytes = message instanceof Uint8Array ? message : new Uint8Array(message);
|
|
2519
|
+
if (
|
|
2520
|
+
bytes.byteLength < 5 ||
|
|
2521
|
+
bytes.byteLength > 4 + BROWSER_CONTROL_MAX_FRAME_HEADER_BYTES + BROWSER_FRAME_MAX_BYTES
|
|
2522
|
+
) {
|
|
2523
|
+
throw new Error("computer frame message is truncated or too large");
|
|
2524
|
+
}
|
|
2525
|
+
const metadataLength = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength).getUint32(
|
|
2526
|
+
0,
|
|
2527
|
+
false,
|
|
2528
|
+
);
|
|
2529
|
+
if (
|
|
2530
|
+
metadataLength < 1 ||
|
|
2531
|
+
metadataLength > BROWSER_CONTROL_MAX_FRAME_HEADER_BYTES ||
|
|
2532
|
+
metadataLength + 4 >= bytes.byteLength
|
|
2533
|
+
) {
|
|
2534
|
+
throw new Error("computer frame metadata length is invalid");
|
|
2535
|
+
}
|
|
2536
|
+
let value: unknown;
|
|
2537
|
+
try {
|
|
2538
|
+
value = JSON.parse(
|
|
2539
|
+
new TextDecoder("utf-8", { fatal: true }).decode(bytes.subarray(4, 4 + metadataLength)),
|
|
2540
|
+
);
|
|
2541
|
+
} catch {
|
|
2542
|
+
throw new Error("computer frame metadata is invalid JSON");
|
|
2543
|
+
}
|
|
2544
|
+
const metadata = parseComputerFrameMetadata(value);
|
|
2545
|
+
const data = bytes.slice(4 + metadataLength);
|
|
2546
|
+
if (data.byteLength < 1 || data.byteLength > BROWSER_FRAME_MAX_BYTES) {
|
|
2547
|
+
throw new Error("computer frame image is empty or too large");
|
|
2548
|
+
}
|
|
2549
|
+
const dimensions = imageDimensions(data, metadata.mediaType);
|
|
2550
|
+
if (dimensions.width !== metadata.width || dimensions.height !== metadata.height) {
|
|
2551
|
+
throw new Error("computer frame image dimensions do not match metadata");
|
|
2552
|
+
}
|
|
2553
|
+
if ((await sha256Hex(data)) !== metadata.sha256) {
|
|
2554
|
+
throw new Error("computer frame digest does not match image");
|
|
2555
|
+
}
|
|
2556
|
+
return { ...metadata, data };
|
|
2557
|
+
}
|
|
2558
|
+
|
|
2559
|
+
export function parseBrowserFrameMetadata(value: unknown): BrowserFrameMetadata {
|
|
2560
|
+
if (!isRecord(value)) throw new Error("browser frame metadata is invalid");
|
|
2561
|
+
const allowed = new Set([
|
|
2562
|
+
"frameId",
|
|
2563
|
+
"browserSessionId",
|
|
2564
|
+
"controllerGeneration",
|
|
2565
|
+
"targetId",
|
|
2566
|
+
"targetGeneration",
|
|
2567
|
+
"documentGeneration",
|
|
2568
|
+
"sequence",
|
|
2569
|
+
"mediaType",
|
|
2570
|
+
"width",
|
|
2571
|
+
"height",
|
|
2572
|
+
"deviceScaleFactor",
|
|
2573
|
+
"scrollX",
|
|
2574
|
+
"scrollY",
|
|
2575
|
+
"capturedAt",
|
|
2576
|
+
]);
|
|
2577
|
+
if (Object.keys(value).some((key) => !allowed.has(key))) {
|
|
2578
|
+
throw new Error("browser frame metadata contains unknown fields");
|
|
2579
|
+
}
|
|
2580
|
+
const strings = [
|
|
2581
|
+
"frameId",
|
|
2582
|
+
"browserSessionId",
|
|
2583
|
+
"controllerGeneration",
|
|
2584
|
+
"targetId",
|
|
2585
|
+
"targetGeneration",
|
|
2586
|
+
"documentGeneration",
|
|
2587
|
+
"mediaType",
|
|
2588
|
+
"capturedAt",
|
|
2589
|
+
] as const;
|
|
2590
|
+
for (const key of strings) {
|
|
2591
|
+
const item = value[key];
|
|
2592
|
+
const max = key === "targetId" ? 512 : key === "capturedAt" ? 128 : 256;
|
|
2593
|
+
if (typeof item !== "string" || item.length < 1 || utf8Bytes(item) > max) {
|
|
2594
|
+
throw new Error("browser frame metadata is invalid");
|
|
2595
|
+
}
|
|
2596
|
+
}
|
|
2597
|
+
const numbers = [
|
|
2598
|
+
"sequence",
|
|
2599
|
+
"width",
|
|
2600
|
+
"height",
|
|
2601
|
+
"deviceScaleFactor",
|
|
2602
|
+
"scrollX",
|
|
2603
|
+
"scrollY",
|
|
2604
|
+
] as const;
|
|
2605
|
+
for (const key of numbers) {
|
|
2606
|
+
if (typeof value[key] !== "number" || !Number.isFinite(value[key])) {
|
|
2607
|
+
throw new Error("browser frame metadata is invalid");
|
|
2608
|
+
}
|
|
2609
|
+
}
|
|
2610
|
+
const metadata = value as unknown as BrowserFrameMetadata;
|
|
2611
|
+
if (
|
|
2612
|
+
!Number.isSafeInteger(metadata.sequence) ||
|
|
2613
|
+
metadata.sequence < 0 ||
|
|
2614
|
+
!Number.isSafeInteger(metadata.width) ||
|
|
2615
|
+
!Number.isSafeInteger(metadata.height)
|
|
2616
|
+
) {
|
|
2617
|
+
throw new Error("browser frame metadata integers are invalid");
|
|
2618
|
+
}
|
|
2619
|
+
assertImageDimensions(metadata.width, metadata.height);
|
|
2620
|
+
if (
|
|
2621
|
+
metadata.deviceScaleFactor <= 0 ||
|
|
2622
|
+
metadata.deviceScaleFactor > 16 ||
|
|
2623
|
+
Math.abs(metadata.scrollX) > 1_000_000_000 ||
|
|
2624
|
+
Math.abs(metadata.scrollY) > 1_000_000_000
|
|
2625
|
+
) {
|
|
2626
|
+
throw new Error("browser frame geometry metadata is invalid");
|
|
2627
|
+
}
|
|
2628
|
+
if (metadata.mediaType !== "image/jpeg" && metadata.mediaType !== "image/png") {
|
|
2629
|
+
throw new Error("browser frame media type is invalid");
|
|
2630
|
+
}
|
|
2631
|
+
if (!isUuid(metadata.browserSessionId)) throw new Error("browser frame session id is invalid");
|
|
2632
|
+
if (!/^[A-Za-z0-9][A-Za-z0-9._:-]*$/u.test(metadata.controllerGeneration)) {
|
|
2633
|
+
throw new Error("browser frame controller generation is invalid");
|
|
2634
|
+
}
|
|
2635
|
+
if (!Number.isFinite(new Date(metadata.capturedAt).valueOf())) {
|
|
2636
|
+
throw new Error("browser frame timestamp is invalid");
|
|
2637
|
+
}
|
|
2638
|
+
return metadata;
|
|
2639
|
+
}
|
|
2640
|
+
|
|
2641
|
+
export function parseComputerFrameMetadata(value: unknown): ComputerFrameMetadata {
|
|
2642
|
+
if (!isRecord(value)) throw new Error("computer frame metadata is invalid");
|
|
2643
|
+
const allowed = new Set([
|
|
2644
|
+
"frameId",
|
|
2645
|
+
"computerSessionId",
|
|
2646
|
+
"controllerGeneration",
|
|
2647
|
+
"targetId",
|
|
2648
|
+
"targetGeneration",
|
|
2649
|
+
"sequence",
|
|
2650
|
+
"mediaType",
|
|
2651
|
+
"width",
|
|
2652
|
+
"height",
|
|
2653
|
+
"capturedAt",
|
|
2654
|
+
"sha256",
|
|
2655
|
+
]);
|
|
2656
|
+
if (Object.keys(value).some((key) => !allowed.has(key))) {
|
|
2657
|
+
throw new Error("computer frame metadata contains unknown fields");
|
|
2658
|
+
}
|
|
2659
|
+
const strings = [
|
|
2660
|
+
"frameId",
|
|
2661
|
+
"computerSessionId",
|
|
2662
|
+
"controllerGeneration",
|
|
2663
|
+
"targetId",
|
|
2664
|
+
"targetGeneration",
|
|
2665
|
+
"mediaType",
|
|
2666
|
+
"capturedAt",
|
|
2667
|
+
"sha256",
|
|
2668
|
+
] as const;
|
|
2669
|
+
for (const key of strings) {
|
|
2670
|
+
const item = value[key];
|
|
2671
|
+
const max = key === "targetId" ? 512 : key === "capturedAt" ? 128 : 256;
|
|
2672
|
+
if (typeof item !== "string" || item.length < 1 || utf8Bytes(item) > max) {
|
|
2673
|
+
throw new Error("computer frame metadata is invalid");
|
|
2674
|
+
}
|
|
2675
|
+
}
|
|
2676
|
+
const metadata = value as unknown as ComputerFrameMetadata;
|
|
2677
|
+
if (
|
|
2678
|
+
!Number.isSafeInteger(metadata.sequence) ||
|
|
2679
|
+
metadata.sequence < 0 ||
|
|
2680
|
+
!Number.isSafeInteger(metadata.width) ||
|
|
2681
|
+
!Number.isSafeInteger(metadata.height)
|
|
2682
|
+
) {
|
|
2683
|
+
throw new Error("computer frame metadata integers are invalid");
|
|
2684
|
+
}
|
|
2685
|
+
assertImageDimensions(metadata.width, metadata.height);
|
|
2686
|
+
if (metadata.mediaType !== "image/jpeg" && metadata.mediaType !== "image/png") {
|
|
2687
|
+
throw new Error("computer frame media type is invalid");
|
|
2688
|
+
}
|
|
2689
|
+
if (!isUuid(metadata.computerSessionId)) {
|
|
2690
|
+
throw new Error("computer frame session id is invalid");
|
|
2691
|
+
}
|
|
2692
|
+
if (!/^[A-Za-z0-9][A-Za-z0-9._:-]*$/u.test(metadata.controllerGeneration)) {
|
|
2693
|
+
throw new Error("computer frame controller generation is invalid");
|
|
2694
|
+
}
|
|
2695
|
+
if (!Number.isFinite(new Date(metadata.capturedAt).valueOf())) {
|
|
2696
|
+
throw new Error("computer frame timestamp is invalid");
|
|
2697
|
+
}
|
|
2698
|
+
if (!/^[0-9a-f]{64}$/u.test(metadata.sha256)) {
|
|
2699
|
+
throw new Error("computer frame digest is invalid");
|
|
2700
|
+
}
|
|
2701
|
+
return metadata;
|
|
2702
|
+
}
|
|
2703
|
+
|
|
2704
|
+
function newestRelevantBrowser(
|
|
2705
|
+
sessions: readonly BrowserSession[],
|
|
2706
|
+
associationSessionId: string,
|
|
2707
|
+
): BrowserSession | null {
|
|
2708
|
+
const live = sessions.filter(
|
|
2709
|
+
(session) =>
|
|
2710
|
+
!["ending", "ended", "failed", "lost"].includes(session.lifecycle) &&
|
|
2711
|
+
session.associations.some((association) => association.sessionId === associationSessionId),
|
|
2712
|
+
);
|
|
2713
|
+
live.sort(
|
|
2714
|
+
(left, right) =>
|
|
2715
|
+
browserRelevance(right, associationSessionId) - browserRelevance(left, associationSessionId),
|
|
2716
|
+
);
|
|
2717
|
+
return live[0] ?? null;
|
|
2718
|
+
}
|
|
2719
|
+
|
|
2720
|
+
function newestRelevantComputer(
|
|
2721
|
+
sessions: readonly ComputerSession[],
|
|
2722
|
+
associationSessionId: string,
|
|
2723
|
+
): ComputerSession | null {
|
|
2724
|
+
const live = sessions.filter(
|
|
2725
|
+
(session) =>
|
|
2726
|
+
["starting", "active", "restoring"].includes(session.lifecycle) &&
|
|
2727
|
+
session.associations.some((association) => association.sessionId === associationSessionId),
|
|
2728
|
+
);
|
|
2729
|
+
live.sort(
|
|
2730
|
+
(left, right) =>
|
|
2731
|
+
computerRelevance(right, associationSessionId) -
|
|
2732
|
+
computerRelevance(left, associationSessionId),
|
|
2733
|
+
);
|
|
2734
|
+
return live[0] ?? null;
|
|
2735
|
+
}
|
|
2736
|
+
|
|
2737
|
+
function browserRelevance(session: BrowserSession, associationSessionId: string): number {
|
|
2738
|
+
const association = session.associations
|
|
2739
|
+
.filter((item) => item.sessionId === associationSessionId)
|
|
2740
|
+
.map((item) => Date.parse(item.lastUsedAt))
|
|
2741
|
+
.filter(Number.isFinite)
|
|
2742
|
+
.reduce((best, timestamp) => Math.max(best, timestamp), 0);
|
|
2743
|
+
const used = Date.parse(session.lastUsedAt);
|
|
2744
|
+
return Math.max(association, Number.isFinite(used) ? used : 0);
|
|
2745
|
+
}
|
|
2746
|
+
|
|
2747
|
+
function computerRelevance(session: ComputerSession, associationSessionId: string): number {
|
|
2748
|
+
const association = session.associations
|
|
2749
|
+
.filter((item) => item.sessionId === associationSessionId)
|
|
2750
|
+
.map((item) => Date.parse(item.lastUsedAt))
|
|
2751
|
+
.filter(Number.isFinite)
|
|
2752
|
+
.reduce((best, timestamp) => Math.max(best, timestamp), 0);
|
|
2753
|
+
const used = Date.parse(session.lastUsedAt);
|
|
2754
|
+
return Math.max(association, Number.isFinite(used) ? used : 0);
|
|
2755
|
+
}
|
|
2756
|
+
|
|
2757
|
+
function setBoundedIntegerQuery(
|
|
2758
|
+
url: URL,
|
|
2759
|
+
name: string,
|
|
2760
|
+
value: number | undefined,
|
|
2761
|
+
min: number,
|
|
2762
|
+
max: number,
|
|
2763
|
+
): void {
|
|
2764
|
+
if (value === undefined) return;
|
|
2765
|
+
if (!Number.isSafeInteger(value) || value < min || value > max) {
|
|
2766
|
+
throw new Error(`browser frame ${name} must be an integer between ${min} and ${max}`);
|
|
2767
|
+
}
|
|
2768
|
+
url.searchParams.set(name, String(value));
|
|
2769
|
+
}
|
|
2770
|
+
|
|
2771
|
+
function imageDimensions(
|
|
2772
|
+
data: Uint8Array,
|
|
2773
|
+
mediaType: BrowserFrameMetadata["mediaType"],
|
|
2774
|
+
): { width: number; height: number } {
|
|
2775
|
+
const dimensions = mediaType === "image/png" ? pngDimensions(data) : jpegDimensions(data);
|
|
2776
|
+
assertImageDimensions(dimensions.width, dimensions.height);
|
|
2777
|
+
return dimensions;
|
|
2778
|
+
}
|
|
2779
|
+
|
|
2780
|
+
function assertImageDimensions(width: number, height: number): void {
|
|
2781
|
+
if (
|
|
2782
|
+
!Number.isSafeInteger(width) ||
|
|
2783
|
+
!Number.isSafeInteger(height) ||
|
|
2784
|
+
width < 1 ||
|
|
2785
|
+
height < 1 ||
|
|
2786
|
+
width > BROWSER_FRAME_MAX_DIMENSION ||
|
|
2787
|
+
height > BROWSER_FRAME_MAX_DIMENSION ||
|
|
2788
|
+
width * height > BROWSER_FRAME_MAX_PIXELS
|
|
2789
|
+
) {
|
|
2790
|
+
throw new Error("browser image dimensions exceed their bounded envelope");
|
|
2791
|
+
}
|
|
2792
|
+
}
|
|
2793
|
+
|
|
2794
|
+
function pngDimensions(data: Uint8Array): { width: number; height: number } {
|
|
2795
|
+
const signature = [137, 80, 78, 71, 13, 10, 26, 10];
|
|
2796
|
+
if (
|
|
2797
|
+
data.byteLength < 24 ||
|
|
2798
|
+
!signature.every((byte, index) => data[index] === byte) ||
|
|
2799
|
+
String.fromCharCode(...data.slice(12, 16)) !== "IHDR"
|
|
2800
|
+
) {
|
|
2801
|
+
throw new Error("browser returned an invalid PNG image");
|
|
2802
|
+
}
|
|
2803
|
+
const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
|
|
2804
|
+
return { width: view.getUint32(16), height: view.getUint32(20) };
|
|
2805
|
+
}
|
|
2806
|
+
|
|
2807
|
+
function jpegDimensions(data: Uint8Array): { width: number; height: number } {
|
|
2808
|
+
if (data.byteLength < 4 || data[0] !== 0xff || data[1] !== 0xd8) {
|
|
2809
|
+
throw new Error("browser returned an invalid JPEG image");
|
|
2810
|
+
}
|
|
2811
|
+
let offset = 2;
|
|
2812
|
+
while (offset + 3 < data.byteLength) {
|
|
2813
|
+
if (data[offset] !== 0xff) {
|
|
2814
|
+
offset += 1;
|
|
2815
|
+
continue;
|
|
2816
|
+
}
|
|
2817
|
+
let marker = data[offset + 1]!;
|
|
2818
|
+
while (marker === 0xff) {
|
|
2819
|
+
offset += 1;
|
|
2820
|
+
marker = data[offset + 1]!;
|
|
2821
|
+
}
|
|
2822
|
+
if (
|
|
2823
|
+
marker === 0xd8 ||
|
|
2824
|
+
marker === 0xd9 ||
|
|
2825
|
+
marker === 0x01 ||
|
|
2826
|
+
(marker >= 0xd0 && marker <= 0xd7)
|
|
2827
|
+
) {
|
|
2828
|
+
offset += 2;
|
|
2829
|
+
continue;
|
|
2830
|
+
}
|
|
2831
|
+
if (offset + 3 >= data.byteLength) break;
|
|
2832
|
+
const length = (data[offset + 2]! << 8) | data[offset + 3]!;
|
|
2833
|
+
if (length < 2 || offset + 2 + length > data.byteLength) break;
|
|
2834
|
+
if (isJpegStartOfFrame(marker)) {
|
|
2835
|
+
if (length < 7 || offset + 8 >= data.byteLength) break;
|
|
2836
|
+
return {
|
|
2837
|
+
height: (data[offset + 5]! << 8) | data[offset + 6]!,
|
|
2838
|
+
width: (data[offset + 7]! << 8) | data[offset + 8]!,
|
|
2839
|
+
};
|
|
2840
|
+
}
|
|
2841
|
+
offset += 2 + length;
|
|
2842
|
+
}
|
|
2843
|
+
throw new Error("browser returned a JPEG without dimensions");
|
|
2844
|
+
}
|
|
2845
|
+
|
|
2846
|
+
function isJpegStartOfFrame(marker: number): boolean {
|
|
2847
|
+
return (
|
|
2848
|
+
(marker >= 0xc0 && marker <= 0xc3) ||
|
|
2849
|
+
(marker >= 0xc5 && marker <= 0xc7) ||
|
|
2850
|
+
(marker >= 0xc9 && marker <= 0xcb) ||
|
|
2851
|
+
(marker >= 0xcd && marker <= 0xcf)
|
|
2852
|
+
);
|
|
2853
|
+
}
|
|
2854
|
+
|
|
2855
|
+
function utf8Bytes(value: string): number {
|
|
2856
|
+
return new TextEncoder().encode(value).byteLength;
|
|
2857
|
+
}
|
|
2858
|
+
|
|
2859
|
+
async function sha256Hex(value: Uint8Array): Promise<string> {
|
|
2860
|
+
const subtle = globalThis.crypto?.subtle;
|
|
2861
|
+
if (!subtle) throw new Error("computer frame digest verification is unavailable");
|
|
2862
|
+
const copy = new Uint8Array(value.byteLength);
|
|
2863
|
+
copy.set(value);
|
|
2864
|
+
const digest = new Uint8Array(await subtle.digest("SHA-256", copy));
|
|
2865
|
+
return [...digest].map((byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
2866
|
+
}
|
|
2867
|
+
|
|
2868
|
+
function isUuid(value: string): boolean {
|
|
2869
|
+
return /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/iu.test(value);
|
|
2870
|
+
}
|
|
2871
|
+
|
|
2872
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
2873
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
2874
|
+
}
|