@modelprofile.com/browser-runtime 1.0.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/.smartconfig.json +34 -0
- package/changelog.md +11 -0
- package/dist_ts/00_commitinfo_data.d.ts +8 -0
- package/dist_ts/00_commitinfo_data.js +9 -0
- package/dist_ts/actions.d.ts +3 -0
- package/dist_ts/actions.js +215 -0
- package/dist_ts/classes.artifactstore.d.ts +38 -0
- package/dist_ts/classes.artifactstore.js +344 -0
- package/dist_ts/classes.egressproxy.d.ts +67 -0
- package/dist_ts/classes.egressproxy.js +830 -0
- package/dist_ts/classes.flexprovider.d.ts +9 -0
- package/dist_ts/classes.flexprovider.js +117 -0
- package/dist_ts/classes.framed.d.ts +52 -0
- package/dist_ts/classes.framed.js +557 -0
- package/dist_ts/classes.runtime.d.ts +202 -0
- package/dist_ts/classes.runtime.js +1667 -0
- package/dist_ts/confinement.d.ts +2 -0
- package/dist_ts/confinement.js +63 -0
- package/dist_ts/errors.d.ts +7 -0
- package/dist_ts/errors.js +40 -0
- package/dist_ts/index.d.ts +11 -0
- package/dist_ts/index.js +9 -0
- package/dist_ts/interfaces.d.ts +287 -0
- package/dist_ts/interfaces.js +2 -0
- package/dist_ts/internal.testing.d.ts +9 -0
- package/dist_ts/internal.testing.js +2 -0
- package/dist_ts/mcp.d.ts +4 -0
- package/dist_ts/mcp.js +196 -0
- package/dist_ts/plugins.d.ts +20 -0
- package/dist_ts/plugins.js +24 -0
- package/dist_ts/utils.d.ts +25 -0
- package/dist_ts/utils.js +143 -0
- package/license.md +21 -0
- package/package.json +59 -0
- package/readme.hints.md +35 -0
- package/readme.md +181 -0
- package/ts/00_commitinfo_data.ts +8 -0
- package/ts/actions.ts +241 -0
- package/ts/classes.artifactstore.ts +432 -0
- package/ts/classes.egressproxy.ts +1005 -0
- package/ts/classes.flexprovider.ts +134 -0
- package/ts/classes.framed.ts +649 -0
- package/ts/classes.runtime.ts +2135 -0
- package/ts/confinement.ts +90 -0
- package/ts/errors.ts +63 -0
- package/ts/index.ts +52 -0
- package/ts/interfaces.ts +375 -0
- package/ts/internal.testing.ts +18 -0
- package/ts/mcp.ts +230 -0
- package/ts/plugins.ts +28 -0
- package/ts/utils.ts +188 -0
|
@@ -0,0 +1,1667 @@
|
|
|
1
|
+
import * as plugins from './plugins.js';
|
|
2
|
+
import { validateAgentAction } from './actions.js';
|
|
3
|
+
import { BrowserArtifactStore } from './classes.artifactstore.js';
|
|
4
|
+
import { BrowserEgressProxy } from './classes.egressproxy.js';
|
|
5
|
+
import { runProductionConfinementProbe } from './confinement.js';
|
|
6
|
+
import { BrowserRuntimeError } from './errors.js';
|
|
7
|
+
import { browserRuntimeTesting, } from './internal.testing.js';
|
|
8
|
+
import { TransitionMutex, digestToken, digestsEqual, randomId, truncateString, validateBoundedString, validateInteger, validateOptionalInteger, waitBounded, } from './utils.js';
|
|
9
|
+
import { BrowserRuntimeFramedServerPeer } from './classes.framed.js';
|
|
10
|
+
const projectIdMaximum = 128;
|
|
11
|
+
const actorIdMaximum = 128;
|
|
12
|
+
const peerIdMaximum = 128;
|
|
13
|
+
export class BrowserRuntime {
|
|
14
|
+
options;
|
|
15
|
+
profileRoot;
|
|
16
|
+
artifactRoot;
|
|
17
|
+
lockPath;
|
|
18
|
+
artifactStore;
|
|
19
|
+
slots = new Map();
|
|
20
|
+
capabilitiesByDigest = new Map();
|
|
21
|
+
capabilitiesById = new Map();
|
|
22
|
+
failedRevocations = new Set();
|
|
23
|
+
capabilityMutex = new TransitionMutex();
|
|
24
|
+
cleanupOperations = new Set();
|
|
25
|
+
framedPeers = new Set();
|
|
26
|
+
lockHandle;
|
|
27
|
+
lockHandleClosed = false;
|
|
28
|
+
startPromise;
|
|
29
|
+
stopPromise;
|
|
30
|
+
lifecycleState = 'stopped';
|
|
31
|
+
lifecycleEpoch = 0;
|
|
32
|
+
lifecycleController = new AbortController();
|
|
33
|
+
pendingCapabilities = 0;
|
|
34
|
+
pendingCapabilitiesByProject = new Map();
|
|
35
|
+
constructor(options) {
|
|
36
|
+
if (!options || typeof options !== 'object') {
|
|
37
|
+
throw new BrowserRuntimeError('INVALID_INPUT');
|
|
38
|
+
}
|
|
39
|
+
if (!plugins.path.isAbsolute(options.runtimeDirectory)) {
|
|
40
|
+
throw new BrowserRuntimeError('INVALID_INPUT', 'runtimeDirectory must be absolute');
|
|
41
|
+
}
|
|
42
|
+
if (typeof options.authorizeCapability !== 'function') {
|
|
43
|
+
throw new BrowserRuntimeError('INVALID_INPUT', 'authorizeCapability is required');
|
|
44
|
+
}
|
|
45
|
+
if (options.audit !== undefined && typeof options.audit !== 'function') {
|
|
46
|
+
throw new BrowserRuntimeError('INVALID_INPUT', 'audit must be a function');
|
|
47
|
+
}
|
|
48
|
+
const testingOptions = browserRuntimeTesting in options
|
|
49
|
+
&& options[browserRuntimeTesting] === true
|
|
50
|
+
? options
|
|
51
|
+
: undefined;
|
|
52
|
+
const capabilityMaximumTtlMs = validateOptionalInteger(options.capabilityMaximumTtlMs, 'capabilityMaximumTtlMs', 60_000, 24 * 60 * 60 * 1000, 24 * 60 * 60 * 1000);
|
|
53
|
+
const capabilityDefaultTtlMs = validateOptionalInteger(options.capabilityDefaultTtlMs, 'capabilityDefaultTtlMs', 1000, capabilityMaximumTtlMs, 5 * 60_000);
|
|
54
|
+
const environment = testingOptions?.environment ?? {
|
|
55
|
+
platform: process.platform,
|
|
56
|
+
uid: process.getuid?.(),
|
|
57
|
+
};
|
|
58
|
+
if (!environment
|
|
59
|
+
|| typeof environment.platform !== 'string'
|
|
60
|
+
|| (environment.uid !== undefined && !Number.isInteger(environment.uid))) {
|
|
61
|
+
throw new BrowserRuntimeError('INVALID_INPUT', 'environment is invalid');
|
|
62
|
+
}
|
|
63
|
+
this.options = {
|
|
64
|
+
runtimeDirectory: options.runtimeDirectory,
|
|
65
|
+
authorizeCapability: options.authorizeCapability,
|
|
66
|
+
audit: options.audit,
|
|
67
|
+
sessionFactory: testingOptions?.sessionFactory ?? ((sessionOptions) => (new plugins.smartpuppeteer.LiveBrowserSession(sessionOptions))),
|
|
68
|
+
confinementProbe: testingOptions?.confinementProbe ?? runProductionConfinementProbe,
|
|
69
|
+
environment,
|
|
70
|
+
maxProjectSlots: validateOptionalInteger(options.maxProjectSlots, 'maxProjectSlots', 1, 256, 32),
|
|
71
|
+
maxCapabilities: validateOptionalInteger(options.maxCapabilities, 'maxCapabilities', 1, 4096, 512),
|
|
72
|
+
maxCapabilitiesPerProject: validateOptionalInteger(options.maxCapabilitiesPerProject, 'maxCapabilitiesPerProject', 1, 512, 64),
|
|
73
|
+
capabilityDefaultTtlMs,
|
|
74
|
+
capabilityMaximumTtlMs,
|
|
75
|
+
authorizationTimeoutMs: validateOptionalInteger(options.authorizationTimeoutMs, 'authorizationTimeoutMs', 100, 120_000, 10_000),
|
|
76
|
+
maxTabsPerProject: validateOptionalInteger(options.maxTabsPerProject, 'maxTabsPerProject', 1, 256, 32),
|
|
77
|
+
operationTimeoutMs: validateOptionalInteger(options.operationTimeoutMs, 'operationTimeoutMs', 100, 120_000, 30_000),
|
|
78
|
+
quiescenceTimeoutMs: validateOptionalInteger(options.quiescenceTimeoutMs, 'quiescenceTimeoutMs', 100, 60_000, 5000),
|
|
79
|
+
terminationGraceMs: validateOptionalInteger(options.terminationGraceMs, 'terminationGraceMs', 100, 60_000, 5000),
|
|
80
|
+
terminationForceMs: validateOptionalInteger(options.terminationForceMs, 'terminationForceMs', 100, 60_000, 5000),
|
|
81
|
+
auditTimeoutMs: validateOptionalInteger(options.auditTimeoutMs, 'auditTimeoutMs', 100, 30_000, 2000),
|
|
82
|
+
confinementProbeTimeoutMs: validateOptionalInteger(options.confinementProbeTimeoutMs, 'confinementProbeTimeoutMs', 1000, 60_000, 10_000),
|
|
83
|
+
idleRetirementMs: validateOptionalInteger(options.idleRetirementMs, 'idleRetirementMs', 1000, 24 * 60 * 60 * 1000, 15 * 60_000),
|
|
84
|
+
maxFrameBytes: validateOptionalInteger(options.maxFrameBytes, 'maxFrameBytes', 64 * 1024, 16 * 1024 * 1024, 4 * 1024 * 1024),
|
|
85
|
+
frameAcknowledgementTimeoutMs: validateOptionalInteger(options.frameAcknowledgementTimeoutMs, 'frameAcknowledgementTimeoutMs', 100, 60_000, 10_000),
|
|
86
|
+
egress: options.egress ?? {},
|
|
87
|
+
};
|
|
88
|
+
this.profileRoot = plugins.path.join(options.runtimeDirectory, 'profiles');
|
|
89
|
+
this.artifactRoot = plugins.path.join(options.runtimeDirectory, 'artifacts');
|
|
90
|
+
this.lockPath = plugins.path.join(options.runtimeDirectory, 'runtime.lock');
|
|
91
|
+
this.artifactStore = new BrowserArtifactStore({
|
|
92
|
+
rootDirectory: this.artifactRoot,
|
|
93
|
+
...(options.artifacts ?? {}),
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
start() {
|
|
97
|
+
if (this.lifecycleState === 'running')
|
|
98
|
+
return Promise.resolve();
|
|
99
|
+
if (this.startPromise)
|
|
100
|
+
return this.startPromise;
|
|
101
|
+
if (this.stopPromise)
|
|
102
|
+
return this.stopPromise.then(() => this.start());
|
|
103
|
+
this.lifecycleState = 'starting';
|
|
104
|
+
const epoch = ++this.lifecycleEpoch;
|
|
105
|
+
this.lifecycleController = new AbortController();
|
|
106
|
+
this.startPromise = this.startInternal().then(() => {
|
|
107
|
+
if (this.lifecycleState !== 'starting'
|
|
108
|
+
|| this.lifecycleEpoch !== epoch
|
|
109
|
+
|| this.lifecycleController.signal.aborted)
|
|
110
|
+
throw new BrowserRuntimeError('ABORTED');
|
|
111
|
+
this.lifecycleState = 'running';
|
|
112
|
+
}).catch((error) => {
|
|
113
|
+
if (this.lifecycleState === 'starting')
|
|
114
|
+
this.lifecycleState = 'stopped';
|
|
115
|
+
throw error;
|
|
116
|
+
}).finally(() => {
|
|
117
|
+
this.startPromise = undefined;
|
|
118
|
+
});
|
|
119
|
+
return this.startPromise;
|
|
120
|
+
}
|
|
121
|
+
stop() {
|
|
122
|
+
if (this.stopPromise)
|
|
123
|
+
return this.stopPromise;
|
|
124
|
+
if (this.lifecycleState === 'stopped' && !this.lockHandle && !this.startPromise) {
|
|
125
|
+
return Promise.resolve();
|
|
126
|
+
}
|
|
127
|
+
this.lifecycleState = 'stopping';
|
|
128
|
+
this.lifecycleEpoch += 1;
|
|
129
|
+
this.lifecycleController.abort(new BrowserRuntimeError('ABORTED'));
|
|
130
|
+
const startup = this.startPromise;
|
|
131
|
+
this.stopPromise = (async () => {
|
|
132
|
+
await startup?.catch(() => undefined);
|
|
133
|
+
await this.stopInternal();
|
|
134
|
+
this.lifecycleState = 'stopped';
|
|
135
|
+
})().finally(() => {
|
|
136
|
+
this.stopPromise = undefined;
|
|
137
|
+
});
|
|
138
|
+
return this.stopPromise;
|
|
139
|
+
}
|
|
140
|
+
async issueCapability(requestArg) {
|
|
141
|
+
this.requireRunning();
|
|
142
|
+
if (!requestArg || typeof requestArg !== 'object') {
|
|
143
|
+
throw new BrowserRuntimeError('INVALID_INPUT');
|
|
144
|
+
}
|
|
145
|
+
const projectId = validateBoundedString(requestArg.projectId, 'projectId', 1, projectIdMaximum);
|
|
146
|
+
const actorId = validateBoundedString(requestArg.actorId, 'actorId', 1, actorIdMaximum);
|
|
147
|
+
const peerId = validateBoundedString(requestArg.peerId, 'peerId', 1, peerIdMaximum);
|
|
148
|
+
const role = this.validateRole(requestArg.role);
|
|
149
|
+
const source = this.validateSource(requestArg.source);
|
|
150
|
+
if ((role === 'human' && source !== 'human')
|
|
151
|
+
|| (role === 'agent' && source === 'human')) {
|
|
152
|
+
throw new BrowserRuntimeError('INVALID_INPUT');
|
|
153
|
+
}
|
|
154
|
+
if (requestArg.disconnect !== undefined && typeof requestArg.disconnect !== 'function') {
|
|
155
|
+
throw new BrowserRuntimeError('INVALID_INPUT');
|
|
156
|
+
}
|
|
157
|
+
const disconnect = requestArg.disconnect;
|
|
158
|
+
const scopeId = requestArg.scopeId === undefined
|
|
159
|
+
? undefined
|
|
160
|
+
: validateBoundedString(requestArg.scopeId, 'scopeId', 1, 128);
|
|
161
|
+
const sessionId = requestArg.sessionId === undefined
|
|
162
|
+
? undefined
|
|
163
|
+
: validateBoundedString(requestArg.sessionId, 'sessionId', 1, 128);
|
|
164
|
+
if ((source === 'flex' && (!scopeId || !sessionId))
|
|
165
|
+
|| (source !== 'flex' && (scopeId !== undefined || sessionId !== undefined)))
|
|
166
|
+
throw new BrowserRuntimeError('INVALID_INPUT');
|
|
167
|
+
const expiresInMs = requestArg.expiresInMs === undefined
|
|
168
|
+
? this.options.capabilityDefaultTtlMs
|
|
169
|
+
: validateInteger(requestArg.expiresInMs, 'expiresInMs', 1000, this.options.capabilityMaximumTtlMs);
|
|
170
|
+
const lifecycleEpoch = this.lifecycleEpoch;
|
|
171
|
+
const pendingForProject = this.pendingCapabilitiesByProject.get(projectId) ?? 0;
|
|
172
|
+
const activeForProject = [...this.capabilitiesById.values()].filter((record) => (record.projectId === projectId && record.state === 'active')).length;
|
|
173
|
+
if (this.pendingCapabilities + this.capabilitiesById.size >= this.options.maxCapabilities
|
|
174
|
+
|| pendingForProject + activeForProject >= this.options.maxCapabilitiesPerProject)
|
|
175
|
+
throw new BrowserRuntimeError('QUOTA_EXCEEDED');
|
|
176
|
+
this.pendingCapabilities += 1;
|
|
177
|
+
this.pendingCapabilitiesByProject.set(projectId, pendingForProject + 1);
|
|
178
|
+
let authorized = false;
|
|
179
|
+
const authorizationController = new AbortController();
|
|
180
|
+
const authorizationSignal = AbortSignal.any([
|
|
181
|
+
authorizationController.signal,
|
|
182
|
+
this.lifecycleController.signal,
|
|
183
|
+
]);
|
|
184
|
+
try {
|
|
185
|
+
const authorization = Promise.resolve(this.options.authorizeCapability({
|
|
186
|
+
projectId,
|
|
187
|
+
actorId,
|
|
188
|
+
role,
|
|
189
|
+
peerId,
|
|
190
|
+
source,
|
|
191
|
+
...(scopeId ? { scopeId } : {}),
|
|
192
|
+
...(sessionId ? { sessionId } : {}),
|
|
193
|
+
}, authorizationSignal));
|
|
194
|
+
const result = await waitBounded(authorization, this.options.authorizationTimeoutMs);
|
|
195
|
+
if (!result.settled) {
|
|
196
|
+
authorizationController.abort(new BrowserRuntimeError('TIMEOUT'));
|
|
197
|
+
throw new BrowserRuntimeError('TIMEOUT');
|
|
198
|
+
}
|
|
199
|
+
authorized = result.value;
|
|
200
|
+
}
|
|
201
|
+
catch {
|
|
202
|
+
throw new BrowserRuntimeError('AUTHORIZATION_DENIED');
|
|
203
|
+
}
|
|
204
|
+
finally {
|
|
205
|
+
authorizationController.abort(new BrowserRuntimeError('ABORTED'));
|
|
206
|
+
this.pendingCapabilities -= 1;
|
|
207
|
+
const remaining = (this.pendingCapabilitiesByProject.get(projectId) ?? 1) - 1;
|
|
208
|
+
if (remaining > 0)
|
|
209
|
+
this.pendingCapabilitiesByProject.set(projectId, remaining);
|
|
210
|
+
else
|
|
211
|
+
this.pendingCapabilitiesByProject.delete(projectId);
|
|
212
|
+
}
|
|
213
|
+
if (authorized !== true)
|
|
214
|
+
throw new BrowserRuntimeError('AUTHORIZATION_DENIED');
|
|
215
|
+
this.requireRunning();
|
|
216
|
+
if (this.lifecycleEpoch !== lifecycleEpoch)
|
|
217
|
+
throw new BrowserRuntimeError('ABORTED');
|
|
218
|
+
const release = await this.capabilityMutex.acquire();
|
|
219
|
+
try {
|
|
220
|
+
this.requireRunning();
|
|
221
|
+
if (this.lifecycleEpoch !== lifecycleEpoch)
|
|
222
|
+
throw new BrowserRuntimeError('ABORTED');
|
|
223
|
+
const activeProjectCapabilities = [...this.capabilitiesById.values()].filter((record) => (record.projectId === projectId && record.state === 'active')).length;
|
|
224
|
+
if (this.capabilitiesById.size >= this.options.maxCapabilities
|
|
225
|
+
|| activeProjectCapabilities >= this.options.maxCapabilitiesPerProject) {
|
|
226
|
+
throw new BrowserRuntimeError('QUOTA_EXCEEDED');
|
|
227
|
+
}
|
|
228
|
+
this.getOrCreateSlot(projectId);
|
|
229
|
+
let capabilityToken;
|
|
230
|
+
let digest;
|
|
231
|
+
let digestKey;
|
|
232
|
+
do {
|
|
233
|
+
capabilityToken = randomId(32);
|
|
234
|
+
digest = digestToken(capabilityToken);
|
|
235
|
+
digestKey = digest.toString('hex');
|
|
236
|
+
} while (this.capabilitiesByDigest.has(digestKey));
|
|
237
|
+
const capabilityId = randomId(18);
|
|
238
|
+
const expiresAt = Date.now() + expiresInMs;
|
|
239
|
+
let record;
|
|
240
|
+
const expiryTimer = setTimeout(() => {
|
|
241
|
+
if (record.state === 'active')
|
|
242
|
+
record.state = 'expired';
|
|
243
|
+
this.trackCleanup(this.revokeCapabilityRecord(record));
|
|
244
|
+
}, expiresInMs);
|
|
245
|
+
record = {
|
|
246
|
+
capabilityId,
|
|
247
|
+
projectId,
|
|
248
|
+
actorId,
|
|
249
|
+
role,
|
|
250
|
+
peerId,
|
|
251
|
+
source,
|
|
252
|
+
...(scopeId ? { scopeId } : {}),
|
|
253
|
+
...(sessionId ? { sessionId } : {}),
|
|
254
|
+
expiresAt,
|
|
255
|
+
digest,
|
|
256
|
+
state: 'active',
|
|
257
|
+
disconnect,
|
|
258
|
+
expiryTimer,
|
|
259
|
+
};
|
|
260
|
+
record.expiryTimer.unref();
|
|
261
|
+
this.capabilitiesByDigest.set(digestKey, record);
|
|
262
|
+
this.capabilitiesById.set(capabilityId, record);
|
|
263
|
+
return {
|
|
264
|
+
capabilityId,
|
|
265
|
+
projectId,
|
|
266
|
+
actorId,
|
|
267
|
+
role,
|
|
268
|
+
peerId,
|
|
269
|
+
source,
|
|
270
|
+
...(scopeId ? { scopeId } : {}),
|
|
271
|
+
...(sessionId ? { sessionId } : {}),
|
|
272
|
+
expiresAt,
|
|
273
|
+
capabilityToken,
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
finally {
|
|
277
|
+
release();
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
async acquireLease(optionsArg) {
|
|
281
|
+
this.requireRunning();
|
|
282
|
+
if (!optionsArg || typeof optionsArg !== 'object') {
|
|
283
|
+
throw new BrowserRuntimeError('INVALID_INPUT');
|
|
284
|
+
}
|
|
285
|
+
const peerId = validateBoundedString(optionsArg.peerId, 'peerId', 1, peerIdMaximum);
|
|
286
|
+
const expectedRole = optionsArg.expectedRole === undefined
|
|
287
|
+
? undefined
|
|
288
|
+
: this.validateRole(optionsArg.expectedRole);
|
|
289
|
+
const expectedSource = optionsArg.expectedSource === undefined
|
|
290
|
+
? undefined
|
|
291
|
+
: this.validateSource(optionsArg.expectedSource);
|
|
292
|
+
const scopeId = optionsArg.scopeId === undefined
|
|
293
|
+
? undefined
|
|
294
|
+
: validateBoundedString(optionsArg.scopeId, 'scopeId', 1, 128);
|
|
295
|
+
const sessionId = optionsArg.sessionId === undefined
|
|
296
|
+
? undefined
|
|
297
|
+
: validateBoundedString(optionsArg.sessionId, 'sessionId', 1, 128);
|
|
298
|
+
this.throwIfAcquisitionAborted(optionsArg.signal);
|
|
299
|
+
const capabilityToken = validateBoundedString(optionsArg.capabilityToken, 'capabilityToken', 16, 512);
|
|
300
|
+
const digest = digestToken(capabilityToken);
|
|
301
|
+
const capability = this.resolveCapability(digest, peerId, expectedRole, expectedSource, scopeId, sessionId);
|
|
302
|
+
const slot = this.getOrCreateSlot(capability.projectId);
|
|
303
|
+
return capability.role === 'agent'
|
|
304
|
+
? this.acquireAgentLease(slot, capability, digest, optionsArg)
|
|
305
|
+
: this.acquireHumanLease(slot, capability, digest, optionsArg);
|
|
306
|
+
}
|
|
307
|
+
authorizeCapability(capabilityTokenArg, peerIdArg, role, source) {
|
|
308
|
+
this.requireRunning();
|
|
309
|
+
const token = validateBoundedString(capabilityTokenArg, 'capabilityToken', 16, 512);
|
|
310
|
+
const peerId = validateBoundedString(peerIdArg, 'peerId', 1, peerIdMaximum);
|
|
311
|
+
const record = this.resolveCapability(digestToken(token), peerId, role, source);
|
|
312
|
+
return this.describeCapability(record);
|
|
313
|
+
}
|
|
314
|
+
async revokeCapability(capabilityIdArg) {
|
|
315
|
+
const capabilityId = validateBoundedString(capabilityIdArg, 'capabilityId', 1, 128);
|
|
316
|
+
const capability = this.capabilitiesById.get(capabilityId);
|
|
317
|
+
if (!capability)
|
|
318
|
+
return;
|
|
319
|
+
await this.revokeCapabilityRecord(capability);
|
|
320
|
+
}
|
|
321
|
+
async disconnectPeer(peerIdArg) {
|
|
322
|
+
const peerId = validateBoundedString(peerIdArg, 'peerId', 1, peerIdMaximum);
|
|
323
|
+
const matching = [...this.capabilitiesById.values()].filter((record) => (record.peerId === peerId && record.state === 'active'));
|
|
324
|
+
const results = await Promise.allSettled(matching.map((record) => this.revokeCapabilityRecord(record, false)));
|
|
325
|
+
const errors = results
|
|
326
|
+
.filter((result) => result.status === 'rejected')
|
|
327
|
+
.map((result) => result.reason);
|
|
328
|
+
if (errors.length > 0)
|
|
329
|
+
throw new AggregateError(errors, 'Peer cleanup is incomplete');
|
|
330
|
+
}
|
|
331
|
+
async retireProject(projectIdArg) {
|
|
332
|
+
const projectId = validateBoundedString(projectIdArg, 'projectId', 1, projectIdMaximum);
|
|
333
|
+
const capabilities = [...this.capabilitiesById.values()].filter((record) => (record.projectId === projectId));
|
|
334
|
+
const results = await Promise.allSettled(capabilities.map((record) => this.revokeCapabilityRecord(record)));
|
|
335
|
+
const errors = results
|
|
336
|
+
.filter((result) => result.status === 'rejected')
|
|
337
|
+
.map((result) => result.reason);
|
|
338
|
+
if (errors.length > 0)
|
|
339
|
+
throw new AggregateError(errors, 'Project capability cleanup is incomplete');
|
|
340
|
+
await this.retireSlot(projectId, true);
|
|
341
|
+
}
|
|
342
|
+
attachTrustedFramedPeer(options) {
|
|
343
|
+
this.requireRunning();
|
|
344
|
+
const peerId = validateBoundedString(options.peerId, 'peerId', 1, peerIdMaximum);
|
|
345
|
+
if ([...this.framedPeers].some((peer) => peer.peerId === peerId)) {
|
|
346
|
+
throw new BrowserRuntimeError('BUSY');
|
|
347
|
+
}
|
|
348
|
+
const peer = new BrowserRuntimeFramedServerPeer(this, options, () => {
|
|
349
|
+
this.framedPeers.delete(peer);
|
|
350
|
+
});
|
|
351
|
+
this.framedPeers.add(peer);
|
|
352
|
+
peer.start();
|
|
353
|
+
return peer;
|
|
354
|
+
}
|
|
355
|
+
getArtifactStore() {
|
|
356
|
+
return this.artifactStore;
|
|
357
|
+
}
|
|
358
|
+
/** @internal */
|
|
359
|
+
getLeaseState(lease) {
|
|
360
|
+
this.requireValidLease(lease);
|
|
361
|
+
const session = lease.slot.session;
|
|
362
|
+
return this.projectState(session.getState());
|
|
363
|
+
}
|
|
364
|
+
/** @internal */
|
|
365
|
+
async executeLeaseAgentAction(lease, actionArg, operationOptions = {}) {
|
|
366
|
+
if (lease.role !== 'agent')
|
|
367
|
+
throw new BrowserRuntimeError('CAPABILITY_INVALID');
|
|
368
|
+
const action = validateAgentAction(actionArg);
|
|
369
|
+
return this.runOperation(lease, action.action, operationOptions, async (signal, session) => (this.executeAgentActionInternal(lease, session, action, signal)));
|
|
370
|
+
}
|
|
371
|
+
/** @internal */
|
|
372
|
+
async leaseCreateTab(lease, options = {}, operationOptions = {}) {
|
|
373
|
+
this.requireHuman(lease);
|
|
374
|
+
return this.runOperation(lease, 'createTab', operationOptions, async (signal, session) => {
|
|
375
|
+
if (session.getState().tabs.length >= this.options.maxTabsPerProject) {
|
|
376
|
+
throw new BrowserRuntimeError('QUOTA_EXCEEDED');
|
|
377
|
+
}
|
|
378
|
+
await session.createTab(options, { signal });
|
|
379
|
+
return this.projectState(session.getState());
|
|
380
|
+
});
|
|
381
|
+
}
|
|
382
|
+
/** @internal */
|
|
383
|
+
async leaseActivateTab(lease, tabIdArg, operationOptions = {}) {
|
|
384
|
+
this.requireHuman(lease);
|
|
385
|
+
const tabId = validateBoundedString(tabIdArg, 'tabId', 1, 128);
|
|
386
|
+
return this.runOperation(lease, 'activateTab', operationOptions, async (signal, session) => {
|
|
387
|
+
await session.activateTab(tabId, { signal });
|
|
388
|
+
return this.projectState(session.getState());
|
|
389
|
+
});
|
|
390
|
+
}
|
|
391
|
+
/** @internal */
|
|
392
|
+
async leaseCloseTab(lease, tabIdArg, operationOptions = {}) {
|
|
393
|
+
this.requireHuman(lease);
|
|
394
|
+
const tabId = validateBoundedString(tabIdArg, 'tabId', 1, 128);
|
|
395
|
+
return this.runOperation(lease, 'closeTab', operationOptions, async (signal, session) => {
|
|
396
|
+
await session.closeTab(tabId, { signal });
|
|
397
|
+
return this.projectState(session.getState());
|
|
398
|
+
});
|
|
399
|
+
}
|
|
400
|
+
/** @internal */
|
|
401
|
+
async leaseHistory(lease, action, options = {}, operationOptions = {}) {
|
|
402
|
+
this.requireHuman(lease);
|
|
403
|
+
return this.runOperation(lease, action, operationOptions, async (signal, session) => {
|
|
404
|
+
await session[action](options, { signal });
|
|
405
|
+
return this.projectState(session.getState());
|
|
406
|
+
});
|
|
407
|
+
}
|
|
408
|
+
/** @internal */
|
|
409
|
+
async leaseHumanAgentAction(lease, actionArg, operationOptions = {}) {
|
|
410
|
+
this.requireHuman(lease);
|
|
411
|
+
const action = validateAgentAction(actionArg);
|
|
412
|
+
return this.runOperation(lease, action.action, operationOptions, async (signal, session) => (this.executeAgentActionInternal(lease, session, action, signal)));
|
|
413
|
+
}
|
|
414
|
+
/** @internal */
|
|
415
|
+
async leaseSetViewport(lease, viewport, operationOptions = {}) {
|
|
416
|
+
this.requireHuman(lease);
|
|
417
|
+
await this.runOperation(lease, 'setViewport', operationOptions, async (signal, session) => {
|
|
418
|
+
await session.setViewport(viewport, { signal });
|
|
419
|
+
});
|
|
420
|
+
}
|
|
421
|
+
/** @internal */
|
|
422
|
+
async leaseDispatchRawInput(lease, action, input, operationOptions = {}) {
|
|
423
|
+
this.requireHuman(lease);
|
|
424
|
+
await this.runOperation(lease, action, operationOptions, async (_signal, session) => {
|
|
425
|
+
if (action === 'dispatchMouse') {
|
|
426
|
+
await session.dispatchMouse(input);
|
|
427
|
+
}
|
|
428
|
+
else if (action === 'dispatchWheel') {
|
|
429
|
+
await session.dispatchWheel(input);
|
|
430
|
+
}
|
|
431
|
+
else if (action === 'dispatchKey') {
|
|
432
|
+
await session.dispatchKey(input);
|
|
433
|
+
}
|
|
434
|
+
else {
|
|
435
|
+
await session.insertText(input);
|
|
436
|
+
}
|
|
437
|
+
});
|
|
438
|
+
}
|
|
439
|
+
/** @internal */
|
|
440
|
+
async subscribeLeaseEvents(lease, listener) {
|
|
441
|
+
this.requireHuman(lease);
|
|
442
|
+
if (typeof listener !== 'function')
|
|
443
|
+
throw new BrowserRuntimeError('INVALID_INPUT');
|
|
444
|
+
const slot = lease.slot;
|
|
445
|
+
const release = await slot.mutex.acquire();
|
|
446
|
+
let subscription;
|
|
447
|
+
try {
|
|
448
|
+
this.requireValidLease(lease);
|
|
449
|
+
if (slot.frameSubscription)
|
|
450
|
+
throw new BrowserRuntimeError('BUSY');
|
|
451
|
+
subscription = { lease, listener, closed: false };
|
|
452
|
+
slot.frameSubscription = subscription;
|
|
453
|
+
this.pushToSubscription(subscription, {
|
|
454
|
+
type: 'state',
|
|
455
|
+
state: this.projectState(slot.session.getState()),
|
|
456
|
+
});
|
|
457
|
+
}
|
|
458
|
+
finally {
|
|
459
|
+
release();
|
|
460
|
+
}
|
|
461
|
+
return {
|
|
462
|
+
close: async () => this.closeFrameSubscription(subscription),
|
|
463
|
+
};
|
|
464
|
+
}
|
|
465
|
+
/** @internal */
|
|
466
|
+
async acknowledgeLeaseFrame(lease, acknowledgement) {
|
|
467
|
+
this.requireHuman(lease);
|
|
468
|
+
if (!acknowledgement || typeof acknowledgement !== 'object') {
|
|
469
|
+
throw new BrowserRuntimeError('INVALID_INPUT');
|
|
470
|
+
}
|
|
471
|
+
validateBoundedString(acknowledgement.tabId, 'tabId', 1, 128);
|
|
472
|
+
validateInteger(acknowledgement.sequence, 'sequence', 0, Number.MAX_SAFE_INTEGER);
|
|
473
|
+
validateInteger(acknowledgement.generation, 'generation', 0, Number.MAX_SAFE_INTEGER);
|
|
474
|
+
validateInteger(acknowledgement.viewportRevision, 'viewportRevision', 0, Number.MAX_SAFE_INTEGER);
|
|
475
|
+
const slot = lease.slot;
|
|
476
|
+
const subscription = slot.frameSubscription;
|
|
477
|
+
this.requireValidLease(lease);
|
|
478
|
+
if (!subscription || subscription.lease !== lease || !subscription.outstanding)
|
|
479
|
+
return false;
|
|
480
|
+
const expected = subscription.outstanding.acknowledgement;
|
|
481
|
+
if (expected.tabId !== acknowledgement.tabId
|
|
482
|
+
|| expected.sequence !== acknowledgement.sequence
|
|
483
|
+
|| expected.generation !== acknowledgement.generation
|
|
484
|
+
|| expected.viewportRevision !== acknowledgement.viewportRevision)
|
|
485
|
+
return false;
|
|
486
|
+
clearTimeout(subscription.outstanding.timer);
|
|
487
|
+
subscription.outstanding = undefined;
|
|
488
|
+
const session = slot.session;
|
|
489
|
+
const operation = session.acknowledgeFrame(acknowledgement);
|
|
490
|
+
const result = await waitBounded(operation, this.options.frameAcknowledgementTimeoutMs)
|
|
491
|
+
.catch(() => ({ settled: true, value: { accepted: false } }));
|
|
492
|
+
if (!result.settled || !result.value.accepted) {
|
|
493
|
+
operation.catch(() => undefined);
|
|
494
|
+
const errors = [];
|
|
495
|
+
await this.revokeCapabilityRecord(lease.capability).catch((error) => errors.push(error));
|
|
496
|
+
if (slot.session === session) {
|
|
497
|
+
await this.terminateSlotSession(slot).catch((error) => errors.push(error));
|
|
498
|
+
}
|
|
499
|
+
if (errors.length === 1)
|
|
500
|
+
throw errors[0];
|
|
501
|
+
if (errors.length > 1) {
|
|
502
|
+
throw new AggregateError(errors, 'Frame acknowledgement cleanup is incomplete');
|
|
503
|
+
}
|
|
504
|
+
return false;
|
|
505
|
+
}
|
|
506
|
+
return true;
|
|
507
|
+
}
|
|
508
|
+
/** @internal */
|
|
509
|
+
async readLeaseArtifact(lease, artifactId) {
|
|
510
|
+
this.requireHuman(lease);
|
|
511
|
+
this.requireValidLease(lease);
|
|
512
|
+
return this.artifactStore.read(lease.capability.projectId, artifactId);
|
|
513
|
+
}
|
|
514
|
+
/** @internal */
|
|
515
|
+
async deleteLeaseArtifact(lease, artifactId) {
|
|
516
|
+
this.requireHuman(lease);
|
|
517
|
+
this.requireValidLease(lease);
|
|
518
|
+
await this.artifactStore.delete(lease.capability.projectId, artifactId);
|
|
519
|
+
}
|
|
520
|
+
/** @internal */
|
|
521
|
+
cancelLeaseOperation(lease) {
|
|
522
|
+
this.requireValidLease(lease);
|
|
523
|
+
const operation = lease.slot.operation;
|
|
524
|
+
if (!operation || operation.lease !== lease)
|
|
525
|
+
return false;
|
|
526
|
+
operation.controller.abort(new BrowserRuntimeError('ABORTED'));
|
|
527
|
+
return true;
|
|
528
|
+
}
|
|
529
|
+
/** @internal */
|
|
530
|
+
async releaseLease(lease) {
|
|
531
|
+
await this.releaseLeaseRecord(lease);
|
|
532
|
+
}
|
|
533
|
+
async startInternal() {
|
|
534
|
+
if (this.options.environment.platform !== 'linux') {
|
|
535
|
+
throw new BrowserRuntimeError('FENCED', 'browser runtime requires Linux');
|
|
536
|
+
}
|
|
537
|
+
if (this.options.environment.uid === undefined || this.options.environment.uid === 0) {
|
|
538
|
+
throw new BrowserRuntimeError('FENCED', 'browser runtime requires a non-root uid');
|
|
539
|
+
}
|
|
540
|
+
await plugins.fsPromises.mkdir(this.options.runtimeDirectory, { recursive: true, mode: 0o700 });
|
|
541
|
+
await plugins.fsPromises.chmod(this.options.runtimeDirectory, 0o700);
|
|
542
|
+
if (!this.lockHandle) {
|
|
543
|
+
try {
|
|
544
|
+
this.lockHandle = await plugins.fsPromises.open(this.lockPath, 'wx', 0o600);
|
|
545
|
+
this.lockHandleClosed = false;
|
|
546
|
+
await this.lockHandle.chmod(0o600);
|
|
547
|
+
}
|
|
548
|
+
catch (error) {
|
|
549
|
+
if (error.code === 'EEXIST') {
|
|
550
|
+
throw new BrowserRuntimeError('LOCKED');
|
|
551
|
+
}
|
|
552
|
+
throw error;
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
await plugins.fsPromises.mkdir(this.profileRoot, { recursive: true, mode: 0o700 });
|
|
556
|
+
await plugins.fsPromises.chmod(this.profileRoot, 0o700);
|
|
557
|
+
const profileEntries = await plugins.fsPromises.readdir(this.profileRoot);
|
|
558
|
+
if (profileEntries.length > 0) {
|
|
559
|
+
throw new BrowserRuntimeError('FENCED', 'profile root is not empty');
|
|
560
|
+
}
|
|
561
|
+
await this.artifactStore.start();
|
|
562
|
+
}
|
|
563
|
+
async stopInternal() {
|
|
564
|
+
const peerResults = await Promise.allSettled([...this.framedPeers].map((peer) => peer.close()));
|
|
565
|
+
const revocationRecords = new Set([
|
|
566
|
+
...this.capabilitiesById.values(),
|
|
567
|
+
...this.failedRevocations,
|
|
568
|
+
]);
|
|
569
|
+
const revokeResults = await Promise.allSettled([...revocationRecords].map((record) => this.revokeCapabilityRecord(record)));
|
|
570
|
+
const retirementResults = await Promise.allSettled([...this.slots.keys()].map((projectId) => this.retireSlot(projectId, true)));
|
|
571
|
+
while (this.cleanupOperations.size > 0) {
|
|
572
|
+
await Promise.allSettled([...this.cleanupOperations]);
|
|
573
|
+
}
|
|
574
|
+
const errors = [...peerResults, ...revokeResults, ...retirementResults]
|
|
575
|
+
.filter((result) => result.status === 'rejected')
|
|
576
|
+
.map((result) => result.reason);
|
|
577
|
+
if (errors.length > 0) {
|
|
578
|
+
throw new AggregateError(errors, 'Browser runtime cleanup is incomplete');
|
|
579
|
+
}
|
|
580
|
+
await this.artifactStore.stop();
|
|
581
|
+
if (this.lockHandle) {
|
|
582
|
+
if (!this.lockHandleClosed) {
|
|
583
|
+
await this.lockHandle.close();
|
|
584
|
+
this.lockHandleClosed = true;
|
|
585
|
+
}
|
|
586
|
+
await plugins.fsPromises.rm(this.lockPath, { force: true });
|
|
587
|
+
this.lockHandle = undefined;
|
|
588
|
+
this.lockHandleClosed = false;
|
|
589
|
+
}
|
|
590
|
+
this.startPromise = undefined;
|
|
591
|
+
}
|
|
592
|
+
requireRunning() {
|
|
593
|
+
if (this.lifecycleState !== 'running')
|
|
594
|
+
throw new BrowserRuntimeError('NOT_RUNNING');
|
|
595
|
+
}
|
|
596
|
+
getOrCreateSlot(projectId) {
|
|
597
|
+
let slot = this.slots.get(projectId);
|
|
598
|
+
if (slot)
|
|
599
|
+
return slot;
|
|
600
|
+
if (this.slots.size >= this.options.maxProjectSlots) {
|
|
601
|
+
throw new BrowserRuntimeError('QUOTA_EXCEEDED');
|
|
602
|
+
}
|
|
603
|
+
slot = {
|
|
604
|
+
projectId,
|
|
605
|
+
mutex: new TransitionMutex(),
|
|
606
|
+
generation: 0,
|
|
607
|
+
permanentlyFenced: false,
|
|
608
|
+
};
|
|
609
|
+
this.slots.set(projectId, slot);
|
|
610
|
+
return slot;
|
|
611
|
+
}
|
|
612
|
+
async acquireAgentLease(slot, capability, digest, acquisition) {
|
|
613
|
+
const release = slot.mutex.tryAcquire();
|
|
614
|
+
if (!release)
|
|
615
|
+
throw new BrowserRuntimeError('BUSY');
|
|
616
|
+
try {
|
|
617
|
+
this.assertSlotAvailable(slot);
|
|
618
|
+
this.resolveCapability(digest, capability.peerId, acquisition.expectedRole ?? 'agent', acquisition.expectedSource, acquisition.scopeId, acquisition.sessionId);
|
|
619
|
+
if (slot.lease || slot.operation)
|
|
620
|
+
throw new BrowserRuntimeError('BUSY');
|
|
621
|
+
await this.ensureSession(slot, acquisition.signal);
|
|
622
|
+
this.throwIfAcquisitionAborted(acquisition.signal);
|
|
623
|
+
this.resolveCapability(digest, capability.peerId, acquisition.expectedRole ?? 'agent', acquisition.expectedSource, acquisition.scopeId, acquisition.sessionId);
|
|
624
|
+
const lease = this.createLeaseRecord(slot, capability, digest);
|
|
625
|
+
return new BrowserRuntimeLease(this, lease);
|
|
626
|
+
}
|
|
627
|
+
catch (error) {
|
|
628
|
+
if (slot.session && !slot.lease)
|
|
629
|
+
this.scheduleIdleRetirement(slot);
|
|
630
|
+
throw error;
|
|
631
|
+
}
|
|
632
|
+
finally {
|
|
633
|
+
release();
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
async acquireHumanLease(slot, capability, digest, acquisition) {
|
|
637
|
+
const release = await slot.mutex.acquire();
|
|
638
|
+
let generation = 0;
|
|
639
|
+
let preemptedLease;
|
|
640
|
+
try {
|
|
641
|
+
this.assertSlotAvailable(slot);
|
|
642
|
+
this.resolveCapability(digest, capability.peerId, 'human', 'human');
|
|
643
|
+
this.throwIfAcquisitionAborted(acquisition.signal);
|
|
644
|
+
if (slot.fencingGeneration !== undefined)
|
|
645
|
+
throw new BrowserRuntimeError('BUSY');
|
|
646
|
+
if (slot.lease?.role === 'human')
|
|
647
|
+
throw new BrowserRuntimeError('BUSY');
|
|
648
|
+
generation = ++slot.generation;
|
|
649
|
+
slot.fencingGeneration = generation;
|
|
650
|
+
preemptedLease = slot.lease;
|
|
651
|
+
if (preemptedLease) {
|
|
652
|
+
preemptedLease.released = true;
|
|
653
|
+
preemptedLease.controller.abort(new BrowserRuntimeError('ABORTED'));
|
|
654
|
+
slot.operation?.controller.abort(new BrowserRuntimeError('ABORTED'));
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
finally {
|
|
658
|
+
release();
|
|
659
|
+
}
|
|
660
|
+
try {
|
|
661
|
+
if (preemptedLease)
|
|
662
|
+
await this.quiesceSlot(slot);
|
|
663
|
+
this.throwIfAcquisitionAborted(acquisition.signal);
|
|
664
|
+
const finalRelease = await slot.mutex.acquire();
|
|
665
|
+
try {
|
|
666
|
+
if (slot.generation !== generation || slot.fencingGeneration !== generation) {
|
|
667
|
+
throw new BrowserRuntimeError('BUSY');
|
|
668
|
+
}
|
|
669
|
+
if (preemptedLease) {
|
|
670
|
+
if (preemptedLease.capability.lease === preemptedLease) {
|
|
671
|
+
preemptedLease.capability.lease = undefined;
|
|
672
|
+
}
|
|
673
|
+
if (slot.lease === preemptedLease)
|
|
674
|
+
slot.lease = undefined;
|
|
675
|
+
}
|
|
676
|
+
if (slot.permanentlyFenced)
|
|
677
|
+
throw new BrowserRuntimeError('FENCED');
|
|
678
|
+
slot.fencingGeneration = undefined;
|
|
679
|
+
await this.ensureSession(slot, acquisition.signal);
|
|
680
|
+
this.throwIfAcquisitionAborted(acquisition.signal);
|
|
681
|
+
this.resolveCapability(digest, capability.peerId, 'human', 'human');
|
|
682
|
+
const lease = this.createLeaseRecord(slot, capability, digest);
|
|
683
|
+
return new BrowserRuntimeLease(this, lease);
|
|
684
|
+
}
|
|
685
|
+
finally {
|
|
686
|
+
finalRelease();
|
|
687
|
+
}
|
|
688
|
+
}
|
|
689
|
+
catch (error) {
|
|
690
|
+
const cleanupRelease = await slot.mutex.acquire();
|
|
691
|
+
try {
|
|
692
|
+
if (preemptedLease) {
|
|
693
|
+
if (preemptedLease.capability.lease === preemptedLease) {
|
|
694
|
+
preemptedLease.capability.lease = undefined;
|
|
695
|
+
}
|
|
696
|
+
if (slot.lease === preemptedLease)
|
|
697
|
+
slot.lease = undefined;
|
|
698
|
+
}
|
|
699
|
+
if (slot.fencingGeneration === generation)
|
|
700
|
+
slot.fencingGeneration = undefined;
|
|
701
|
+
if (slot.session && !slot.lease)
|
|
702
|
+
this.scheduleIdleRetirement(slot);
|
|
703
|
+
}
|
|
704
|
+
finally {
|
|
705
|
+
cleanupRelease();
|
|
706
|
+
}
|
|
707
|
+
throw error;
|
|
708
|
+
}
|
|
709
|
+
}
|
|
710
|
+
createLeaseRecord(slot, capability, digest) {
|
|
711
|
+
if (capability.lease || slot.lease)
|
|
712
|
+
throw new BrowserRuntimeError('BUSY');
|
|
713
|
+
if (slot.idleTimer) {
|
|
714
|
+
clearTimeout(slot.idleTimer);
|
|
715
|
+
slot.idleTimer = undefined;
|
|
716
|
+
}
|
|
717
|
+
const lease = {
|
|
718
|
+
leaseId: randomId(18),
|
|
719
|
+
capability,
|
|
720
|
+
digest,
|
|
721
|
+
peerId: capability.peerId,
|
|
722
|
+
role: capability.role,
|
|
723
|
+
slot,
|
|
724
|
+
controller: new AbortController(),
|
|
725
|
+
released: false,
|
|
726
|
+
};
|
|
727
|
+
slot.lease = lease;
|
|
728
|
+
capability.lease = lease;
|
|
729
|
+
return lease;
|
|
730
|
+
}
|
|
731
|
+
async ensureSession(slot, signalArg) {
|
|
732
|
+
if (slot.session)
|
|
733
|
+
return;
|
|
734
|
+
this.assertSlotAvailable(slot);
|
|
735
|
+
const profileDirectory = plugins.path.join(this.profileRoot, randomId(24));
|
|
736
|
+
let profileCreated = false;
|
|
737
|
+
let proxy;
|
|
738
|
+
let session;
|
|
739
|
+
let unsubscribe;
|
|
740
|
+
try {
|
|
741
|
+
await plugins.fsPromises.mkdir(profileDirectory, { mode: 0o700 });
|
|
742
|
+
profileCreated = true;
|
|
743
|
+
await plugins.fsPromises.chmod(profileDirectory, 0o700);
|
|
744
|
+
proxy = new BrowserEgressProxy({
|
|
745
|
+
projectId: slot.projectId,
|
|
746
|
+
...this.options.egress,
|
|
747
|
+
});
|
|
748
|
+
await proxy.start();
|
|
749
|
+
const credentials = proxy.credentials;
|
|
750
|
+
session = this.options.sessionFactory({
|
|
751
|
+
requireSandbox: true,
|
|
752
|
+
forceNoSandbox: false,
|
|
753
|
+
usePipe: true,
|
|
754
|
+
allowEvaluation: true,
|
|
755
|
+
launchOptions: {
|
|
756
|
+
headless: true,
|
|
757
|
+
userDataDir: profileDirectory,
|
|
758
|
+
args: [
|
|
759
|
+
`--proxy-server=http://127.0.0.1:${proxy.port}`,
|
|
760
|
+
'--proxy-bypass-list=<-loopback>',
|
|
761
|
+
'--disable-quic',
|
|
762
|
+
'--disable-dns-prefetch',
|
|
763
|
+
'--disable-background-networking',
|
|
764
|
+
'--disable-extensions',
|
|
765
|
+
'--webrtc-ip-handling-policy=disable_non_proxied_udp',
|
|
766
|
+
'--host-resolver-rules=MAP * ~NOTFOUND, EXCLUDE 127.0.0.1',
|
|
767
|
+
],
|
|
768
|
+
},
|
|
769
|
+
security: {
|
|
770
|
+
denyDownloads: true,
|
|
771
|
+
denyFileChoosers: true,
|
|
772
|
+
denyPermissions: true,
|
|
773
|
+
httpNavigationOnly: true,
|
|
774
|
+
proxyCredentials: credentials,
|
|
775
|
+
},
|
|
776
|
+
});
|
|
777
|
+
unsubscribe = session.onEvent((event) => {
|
|
778
|
+
this.handleSessionEvent(slot, session, event);
|
|
779
|
+
});
|
|
780
|
+
const timeoutController = new AbortController();
|
|
781
|
+
const timeout = setTimeout(() => {
|
|
782
|
+
timeoutController.abort(new BrowserRuntimeError('CONFINEMENT_FAILED'));
|
|
783
|
+
}, this.options.confinementProbeTimeoutMs);
|
|
784
|
+
timeout.unref();
|
|
785
|
+
const probeSignal = AbortSignal.any([
|
|
786
|
+
this.lifecycleController.signal,
|
|
787
|
+
signalArg ?? new AbortController().signal,
|
|
788
|
+
timeoutController.signal,
|
|
789
|
+
]);
|
|
790
|
+
const runBounded = async (operation) => {
|
|
791
|
+
if (probeSignal.aborted)
|
|
792
|
+
throw probeSignal.reason;
|
|
793
|
+
let onAbort;
|
|
794
|
+
const aborted = new Promise((_resolve, reject) => {
|
|
795
|
+
onAbort = () => reject(probeSignal.reason);
|
|
796
|
+
probeSignal.addEventListener('abort', onAbort, { once: true });
|
|
797
|
+
});
|
|
798
|
+
try {
|
|
799
|
+
await Promise.race([operation, aborted]);
|
|
800
|
+
}
|
|
801
|
+
finally {
|
|
802
|
+
probeSignal.removeEventListener('abort', onAbort);
|
|
803
|
+
}
|
|
804
|
+
};
|
|
805
|
+
try {
|
|
806
|
+
await runBounded(session.start({ signal: probeSignal }));
|
|
807
|
+
await runBounded(this.options.confinementProbe({ session, proxy, signal: probeSignal }));
|
|
808
|
+
}
|
|
809
|
+
finally {
|
|
810
|
+
clearTimeout(timeout);
|
|
811
|
+
}
|
|
812
|
+
if (probeSignal.aborted)
|
|
813
|
+
throw probeSignal.reason;
|
|
814
|
+
slot.session = session;
|
|
815
|
+
slot.proxy = proxy;
|
|
816
|
+
slot.profileDirectory = profileDirectory;
|
|
817
|
+
slot.unsubscribeSession = unsubscribe;
|
|
818
|
+
}
|
|
819
|
+
catch (error) {
|
|
820
|
+
unsubscribe?.();
|
|
821
|
+
let confirmed = true;
|
|
822
|
+
if (session) {
|
|
823
|
+
try {
|
|
824
|
+
const termination = await waitBounded(session.terminate({
|
|
825
|
+
gracefulTimeoutMs: this.options.terminationGraceMs,
|
|
826
|
+
forceTimeoutMs: this.options.terminationForceMs,
|
|
827
|
+
}), this.options.terminationGraceMs + this.options.terminationForceMs + 1000);
|
|
828
|
+
confirmed = termination.settled && termination.value.confirmedDead;
|
|
829
|
+
}
|
|
830
|
+
catch {
|
|
831
|
+
confirmed = false;
|
|
832
|
+
}
|
|
833
|
+
}
|
|
834
|
+
if (!confirmed) {
|
|
835
|
+
slot.permanentlyFenced = true;
|
|
836
|
+
slot.session = session;
|
|
837
|
+
slot.proxy = proxy;
|
|
838
|
+
slot.profileDirectory = profileDirectory;
|
|
839
|
+
slot.unsubscribeSession = unsubscribe;
|
|
840
|
+
throw new BrowserRuntimeError('FENCED');
|
|
841
|
+
}
|
|
842
|
+
let proxyStopped = true;
|
|
843
|
+
let profileRemoved = !profileCreated;
|
|
844
|
+
if (proxy) {
|
|
845
|
+
await this.stopProxyBounded(proxy).catch(() => { proxyStopped = false; });
|
|
846
|
+
}
|
|
847
|
+
if (profileCreated) {
|
|
848
|
+
await plugins.fsPromises.rm(profileDirectory, { recursive: true, force: true })
|
|
849
|
+
.then(() => { profileRemoved = true; })
|
|
850
|
+
.catch(() => undefined);
|
|
851
|
+
}
|
|
852
|
+
if (!proxyStopped || !profileRemoved) {
|
|
853
|
+
slot.permanentlyFenced = true;
|
|
854
|
+
if (!proxyStopped)
|
|
855
|
+
slot.proxy = proxy;
|
|
856
|
+
if (!profileRemoved)
|
|
857
|
+
slot.profileDirectory = profileDirectory;
|
|
858
|
+
throw new BrowserRuntimeError('FENCED');
|
|
859
|
+
}
|
|
860
|
+
if (signalArg?.aborted)
|
|
861
|
+
throw new BrowserRuntimeError('ABORTED');
|
|
862
|
+
throw error instanceof BrowserRuntimeError
|
|
863
|
+
? error
|
|
864
|
+
: new BrowserRuntimeError('CONFINEMENT_FAILED');
|
|
865
|
+
}
|
|
866
|
+
}
|
|
867
|
+
async runOperation(lease, action, operationOptions, execute) {
|
|
868
|
+
if (!operationOptions || typeof operationOptions !== 'object') {
|
|
869
|
+
throw new BrowserRuntimeError('INVALID_INPUT');
|
|
870
|
+
}
|
|
871
|
+
if (operationOptions.signal !== undefined
|
|
872
|
+
&& !(operationOptions.signal instanceof AbortSignal))
|
|
873
|
+
throw new BrowserRuntimeError('INVALID_INPUT');
|
|
874
|
+
if (operationOptions.onOperationStarted !== undefined
|
|
875
|
+
&& typeof operationOptions.onOperationStarted !== 'function')
|
|
876
|
+
throw new BrowserRuntimeError('INVALID_INPUT');
|
|
877
|
+
operationOptions.signal?.throwIfAborted();
|
|
878
|
+
const slot = lease.slot;
|
|
879
|
+
const release = slot.mutex.tryAcquire();
|
|
880
|
+
if (!release)
|
|
881
|
+
throw new BrowserRuntimeError('BUSY');
|
|
882
|
+
let operation;
|
|
883
|
+
let executionPromise;
|
|
884
|
+
let combinedSignal;
|
|
885
|
+
let timeout;
|
|
886
|
+
let session;
|
|
887
|
+
let generation;
|
|
888
|
+
const startedAt = Date.now();
|
|
889
|
+
try {
|
|
890
|
+
this.requireValidLease(lease);
|
|
891
|
+
this.assertSlotAvailable(slot);
|
|
892
|
+
if (slot.operation)
|
|
893
|
+
throw new BrowserRuntimeError('BUSY');
|
|
894
|
+
session = slot.session;
|
|
895
|
+
generation = slot.generation;
|
|
896
|
+
const timeoutMs = operationOptions.timeoutMs === undefined
|
|
897
|
+
? this.options.operationTimeoutMs
|
|
898
|
+
: validateInteger(operationOptions.timeoutMs, 'timeoutMs', 100, 120_000);
|
|
899
|
+
const controller = new AbortController();
|
|
900
|
+
const timeoutController = new AbortController();
|
|
901
|
+
timeout = setTimeout(() => {
|
|
902
|
+
timeoutController.abort(new BrowserRuntimeError('TIMEOUT'));
|
|
903
|
+
}, timeoutMs);
|
|
904
|
+
timeout.unref();
|
|
905
|
+
combinedSignal = AbortSignal.any([
|
|
906
|
+
controller.signal,
|
|
907
|
+
lease.controller.signal,
|
|
908
|
+
operationOptions.signal ?? new AbortController().signal,
|
|
909
|
+
timeoutController.signal,
|
|
910
|
+
]);
|
|
911
|
+
executionPromise = Promise.resolve().then(() => execute(combinedSignal, session));
|
|
912
|
+
operation = {
|
|
913
|
+
operationId: randomId(18),
|
|
914
|
+
lease,
|
|
915
|
+
controller,
|
|
916
|
+
action,
|
|
917
|
+
startedAt,
|
|
918
|
+
promise: executionPromise.then(() => undefined, () => undefined),
|
|
919
|
+
};
|
|
920
|
+
slot.operation = operation;
|
|
921
|
+
try {
|
|
922
|
+
operationOptions.onOperationStarted?.(operation.operationId);
|
|
923
|
+
}
|
|
924
|
+
catch {
|
|
925
|
+
controller.abort(new BrowserRuntimeError('ABORTED'));
|
|
926
|
+
}
|
|
927
|
+
}
|
|
928
|
+
finally {
|
|
929
|
+
release();
|
|
930
|
+
}
|
|
931
|
+
let phase = 'completed';
|
|
932
|
+
let errorCode;
|
|
933
|
+
try {
|
|
934
|
+
let onAbort;
|
|
935
|
+
const aborted = new Promise((_resolve, reject) => {
|
|
936
|
+
onAbort = () => reject(combinedSignal.reason ?? new BrowserRuntimeError('ABORTED'));
|
|
937
|
+
combinedSignal.addEventListener('abort', onAbort, { once: true });
|
|
938
|
+
});
|
|
939
|
+
let result;
|
|
940
|
+
try {
|
|
941
|
+
result = await Promise.race([executionPromise, aborted]);
|
|
942
|
+
}
|
|
943
|
+
finally {
|
|
944
|
+
combinedSignal.removeEventListener('abort', onAbort);
|
|
945
|
+
}
|
|
946
|
+
if (combinedSignal.aborted)
|
|
947
|
+
throw combinedSignal.reason;
|
|
948
|
+
this.requireValidLease(lease);
|
|
949
|
+
if (slot.session !== session || slot.generation !== generation) {
|
|
950
|
+
throw new BrowserRuntimeError('ABORTED');
|
|
951
|
+
}
|
|
952
|
+
return result;
|
|
953
|
+
}
|
|
954
|
+
catch (error) {
|
|
955
|
+
phase = 'failed';
|
|
956
|
+
errorCode = error instanceof BrowserRuntimeError
|
|
957
|
+
? error.code
|
|
958
|
+
: error instanceof Error
|
|
959
|
+
? truncateString(error.name, 64)
|
|
960
|
+
: 'Error';
|
|
961
|
+
if (combinedSignal.aborted) {
|
|
962
|
+
this.trackCleanup(this.enforceOperationQuiescence(operation));
|
|
963
|
+
const reason = combinedSignal.reason;
|
|
964
|
+
throw reason instanceof BrowserRuntimeError
|
|
965
|
+
? reason
|
|
966
|
+
: new BrowserRuntimeError(reason instanceof Error && reason.name === 'TimeoutError' ? 'TIMEOUT' : 'ABORTED');
|
|
967
|
+
}
|
|
968
|
+
throw error;
|
|
969
|
+
}
|
|
970
|
+
finally {
|
|
971
|
+
clearTimeout(timeout);
|
|
972
|
+
executionPromise.finally(async () => {
|
|
973
|
+
const cleanupRelease = await slot.mutex.acquire();
|
|
974
|
+
try {
|
|
975
|
+
if (slot.operation === operation)
|
|
976
|
+
slot.operation = undefined;
|
|
977
|
+
}
|
|
978
|
+
finally {
|
|
979
|
+
cleanupRelease();
|
|
980
|
+
}
|
|
981
|
+
}).catch(() => undefined);
|
|
982
|
+
await this.emitAudit({
|
|
983
|
+
operationId: operation.operationId,
|
|
984
|
+
capabilityId: lease.capability.capabilityId,
|
|
985
|
+
projectId: lease.capability.projectId,
|
|
986
|
+
actorId: lease.capability.actorId,
|
|
987
|
+
role: lease.role,
|
|
988
|
+
source: lease.capability.source,
|
|
989
|
+
action,
|
|
990
|
+
phase,
|
|
991
|
+
startedAt,
|
|
992
|
+
finishedAt: Date.now(),
|
|
993
|
+
...(errorCode ? { errorCode } : {}),
|
|
994
|
+
});
|
|
995
|
+
}
|
|
996
|
+
}
|
|
997
|
+
async executeAgentActionInternal(lease, session, action, signal) {
|
|
998
|
+
if (action.action === 'navigate') {
|
|
999
|
+
await session.navigate({
|
|
1000
|
+
url: action.url,
|
|
1001
|
+
...(action.tabId ? { tabId: action.tabId } : {}),
|
|
1002
|
+
...(action.timeoutMs ? { timeoutMs: action.timeoutMs } : {}),
|
|
1003
|
+
}, { signal });
|
|
1004
|
+
return {
|
|
1005
|
+
action: 'navigate',
|
|
1006
|
+
state: this.projectState(session.getState()),
|
|
1007
|
+
};
|
|
1008
|
+
}
|
|
1009
|
+
if (action.action === 'snapshot') {
|
|
1010
|
+
const observation = await session.observe({
|
|
1011
|
+
...(action.tabId ? { tabId: action.tabId } : {}),
|
|
1012
|
+
...(action.maxCharacters ? { maxCharacters: action.maxCharacters } : {}),
|
|
1013
|
+
}, { signal });
|
|
1014
|
+
return {
|
|
1015
|
+
action: 'snapshot',
|
|
1016
|
+
tabId: truncateString(observation.tabId, 128),
|
|
1017
|
+
url: truncateString(observation.url, 8192),
|
|
1018
|
+
title: truncateString(observation.title, 2048),
|
|
1019
|
+
text: truncateString(observation.text, 50_000),
|
|
1020
|
+
truncated: observation.truncated,
|
|
1021
|
+
state: this.projectState(observation.state),
|
|
1022
|
+
};
|
|
1023
|
+
}
|
|
1024
|
+
if (action.action === 'screenshot') {
|
|
1025
|
+
const snapshot = await session.captureSnapshot({
|
|
1026
|
+
...(action.tabId ? { tabId: action.tabId } : {}),
|
|
1027
|
+
...(action.format ? { format: action.format } : {}),
|
|
1028
|
+
...(action.quality !== undefined ? { quality: action.quality } : {}),
|
|
1029
|
+
}, { signal });
|
|
1030
|
+
try {
|
|
1031
|
+
signal.throwIfAborted();
|
|
1032
|
+
this.requireValidLease(lease);
|
|
1033
|
+
if (lease.slot.session !== session)
|
|
1034
|
+
throw new BrowserRuntimeError('ABORTED');
|
|
1035
|
+
const artifact = await this.artifactStore.store(lease.capability.projectId, snapshot.mimeType, snapshot.data);
|
|
1036
|
+
return { action: 'screenshot', artifact };
|
|
1037
|
+
}
|
|
1038
|
+
finally {
|
|
1039
|
+
snapshot.data.fill(0);
|
|
1040
|
+
}
|
|
1041
|
+
}
|
|
1042
|
+
const target = this.resolveSemanticTarget(session.getState(), action.tabId);
|
|
1043
|
+
if (action.action === 'click') {
|
|
1044
|
+
await session.click({
|
|
1045
|
+
...target,
|
|
1046
|
+
selector: action.selector,
|
|
1047
|
+
...(action.timeoutMs ? { timeoutMs: action.timeoutMs } : {}),
|
|
1048
|
+
}, { signal });
|
|
1049
|
+
}
|
|
1050
|
+
else if (action.action === 'fill') {
|
|
1051
|
+
await session.fill({
|
|
1052
|
+
...target,
|
|
1053
|
+
selector: action.selector,
|
|
1054
|
+
text: action.text,
|
|
1055
|
+
...(action.timeoutMs ? { timeoutMs: action.timeoutMs } : {}),
|
|
1056
|
+
}, { signal });
|
|
1057
|
+
}
|
|
1058
|
+
else {
|
|
1059
|
+
await session.press({
|
|
1060
|
+
...target,
|
|
1061
|
+
selector: action.selector,
|
|
1062
|
+
key: action.key,
|
|
1063
|
+
...(action.timeoutMs ? { timeoutMs: action.timeoutMs } : {}),
|
|
1064
|
+
}, { signal });
|
|
1065
|
+
}
|
|
1066
|
+
return {
|
|
1067
|
+
action: action.action,
|
|
1068
|
+
state: this.projectState(session.getState()),
|
|
1069
|
+
};
|
|
1070
|
+
}
|
|
1071
|
+
resolveSemanticTarget(state, tabIdArg) {
|
|
1072
|
+
const tabId = tabIdArg ?? state.activeTabId;
|
|
1073
|
+
const tab = state.tabs.find((candidate) => candidate.id === tabId);
|
|
1074
|
+
if (!tab)
|
|
1075
|
+
throw new BrowserRuntimeError('INVALID_INPUT');
|
|
1076
|
+
return {
|
|
1077
|
+
tabId: tab.id,
|
|
1078
|
+
generation: tab.generation,
|
|
1079
|
+
viewportRevision: state.viewportRevision,
|
|
1080
|
+
};
|
|
1081
|
+
}
|
|
1082
|
+
projectState(state) {
|
|
1083
|
+
return {
|
|
1084
|
+
status: state.status,
|
|
1085
|
+
activeTabId: state.activeTabId ? truncateString(state.activeTabId, 128) : null,
|
|
1086
|
+
viewportRevision: state.viewportRevision,
|
|
1087
|
+
viewport: {
|
|
1088
|
+
width: state.viewport.width,
|
|
1089
|
+
height: state.viewport.height,
|
|
1090
|
+
deviceScaleFactor: state.viewport.deviceScaleFactor,
|
|
1091
|
+
},
|
|
1092
|
+
tabs: state.tabs.slice(0, 256).map((tab) => ({
|
|
1093
|
+
id: truncateString(tab.id, 128),
|
|
1094
|
+
url: truncateString(tab.url, 8192),
|
|
1095
|
+
title: truncateString(tab.title, 2048),
|
|
1096
|
+
active: tab.active,
|
|
1097
|
+
status: tab.status,
|
|
1098
|
+
generation: tab.generation,
|
|
1099
|
+
appliedViewportRevision: tab.appliedViewportRevision,
|
|
1100
|
+
streaming: tab.streaming,
|
|
1101
|
+
})),
|
|
1102
|
+
...(state.lastError
|
|
1103
|
+
? {
|
|
1104
|
+
lastError: {
|
|
1105
|
+
code: truncateString(state.lastError.code, 128),
|
|
1106
|
+
fatal: state.lastError.fatal,
|
|
1107
|
+
...(state.lastError.tabId
|
|
1108
|
+
? { tabId: truncateString(state.lastError.tabId, 128) }
|
|
1109
|
+
: {}),
|
|
1110
|
+
},
|
|
1111
|
+
}
|
|
1112
|
+
: {}),
|
|
1113
|
+
};
|
|
1114
|
+
}
|
|
1115
|
+
handleSessionEvent(slot, session, event) {
|
|
1116
|
+
if (slot.session && slot.session !== session) {
|
|
1117
|
+
if (event.type === 'frame') {
|
|
1118
|
+
this.trackCleanup(this.acknowledgeFrameInBackground(slot, session, {
|
|
1119
|
+
tabId: event.frame.tabId,
|
|
1120
|
+
sequence: event.frame.sequence,
|
|
1121
|
+
generation: event.frame.generation,
|
|
1122
|
+
viewportRevision: event.frame.viewportRevision,
|
|
1123
|
+
}));
|
|
1124
|
+
}
|
|
1125
|
+
return;
|
|
1126
|
+
}
|
|
1127
|
+
const subscription = slot.frameSubscription;
|
|
1128
|
+
if (event.type === 'frame') {
|
|
1129
|
+
const acknowledgement = {
|
|
1130
|
+
tabId: event.frame.tabId,
|
|
1131
|
+
sequence: event.frame.sequence,
|
|
1132
|
+
generation: event.frame.generation,
|
|
1133
|
+
viewportRevision: event.frame.viewportRevision,
|
|
1134
|
+
};
|
|
1135
|
+
if (!subscription || subscription.closed) {
|
|
1136
|
+
this.trackCleanup(this.acknowledgeFrameInBackground(slot, session, acknowledgement));
|
|
1137
|
+
return;
|
|
1138
|
+
}
|
|
1139
|
+
try {
|
|
1140
|
+
this.requireValidLease(subscription.lease);
|
|
1141
|
+
}
|
|
1142
|
+
catch {
|
|
1143
|
+
this.trackCleanup(this.acknowledgeFrameInBackground(slot, session, acknowledgement));
|
|
1144
|
+
this.trackCleanup(this.revokeCapabilityRecord(subscription.lease.capability));
|
|
1145
|
+
return;
|
|
1146
|
+
}
|
|
1147
|
+
if (subscription.outstanding) {
|
|
1148
|
+
this.trackCleanup(this.acknowledgeFrameInBackground(slot, session, acknowledgement));
|
|
1149
|
+
return;
|
|
1150
|
+
}
|
|
1151
|
+
if (event.frame.data.byteLength > this.options.maxFrameBytes) {
|
|
1152
|
+
this.trackCleanup(this.acknowledgeFrameInBackground(slot, session, acknowledgement));
|
|
1153
|
+
this.pushToSubscription(subscription, {
|
|
1154
|
+
type: 'error',
|
|
1155
|
+
error: { code: 'FRAME_TOO_LARGE', fatal: true, tabId: event.frame.tabId },
|
|
1156
|
+
});
|
|
1157
|
+
this.trackCleanup(this.revokeCapabilityRecord(subscription.lease.capability));
|
|
1158
|
+
return;
|
|
1159
|
+
}
|
|
1160
|
+
const timer = setTimeout(() => {
|
|
1161
|
+
if (subscription.outstanding?.acknowledgement.sequence !== acknowledgement.sequence)
|
|
1162
|
+
return;
|
|
1163
|
+
subscription.outstanding = undefined;
|
|
1164
|
+
this.trackCleanup(this.acknowledgeFrameInBackground(slot, session, acknowledgement));
|
|
1165
|
+
this.trackCleanup(this.revokeCapabilityRecord(subscription.lease.capability));
|
|
1166
|
+
}, this.options.frameAcknowledgementTimeoutMs);
|
|
1167
|
+
timer.unref();
|
|
1168
|
+
subscription.outstanding = { acknowledgement, timer };
|
|
1169
|
+
this.pushToSubscription(subscription, { type: 'frame', frame: event.frame });
|
|
1170
|
+
return;
|
|
1171
|
+
}
|
|
1172
|
+
if (event.type === 'error' && event.error.fatal && slot.lease) {
|
|
1173
|
+
this.trackCleanup(this.revokeCapabilityRecord(slot.lease.capability));
|
|
1174
|
+
}
|
|
1175
|
+
if (!subscription || subscription.closed)
|
|
1176
|
+
return;
|
|
1177
|
+
if (event.type === 'state') {
|
|
1178
|
+
this.pushToSubscription(subscription, { type: 'state', state: this.projectState(event.state) });
|
|
1179
|
+
}
|
|
1180
|
+
else {
|
|
1181
|
+
this.pushToSubscription(subscription, {
|
|
1182
|
+
type: 'error',
|
|
1183
|
+
error: {
|
|
1184
|
+
code: truncateString(event.error.code, 128),
|
|
1185
|
+
fatal: event.error.fatal,
|
|
1186
|
+
...(event.error.tabId ? { tabId: truncateString(event.error.tabId, 128) } : {}),
|
|
1187
|
+
},
|
|
1188
|
+
});
|
|
1189
|
+
}
|
|
1190
|
+
}
|
|
1191
|
+
pushToSubscription(subscription, event) {
|
|
1192
|
+
try {
|
|
1193
|
+
this.requireValidLease(subscription.lease);
|
|
1194
|
+
subscription.listener(event);
|
|
1195
|
+
}
|
|
1196
|
+
catch {
|
|
1197
|
+
if (event.type === 'frame' && subscription.outstanding) {
|
|
1198
|
+
const outstanding = subscription.outstanding;
|
|
1199
|
+
clearTimeout(outstanding.timer);
|
|
1200
|
+
subscription.outstanding = undefined;
|
|
1201
|
+
this.trackCleanup(this.acknowledgeFrameInBackground(subscription.lease.slot, subscription.lease.slot.session, outstanding.acknowledgement));
|
|
1202
|
+
}
|
|
1203
|
+
this.trackCleanup(this.revokeCapabilityRecord(subscription.lease.capability));
|
|
1204
|
+
}
|
|
1205
|
+
}
|
|
1206
|
+
async closeFrameSubscription(subscription) {
|
|
1207
|
+
if (subscription.closed)
|
|
1208
|
+
return;
|
|
1209
|
+
subscription.closed = true;
|
|
1210
|
+
const slot = subscription.lease.slot;
|
|
1211
|
+
if (slot.frameSubscription === subscription)
|
|
1212
|
+
slot.frameSubscription = undefined;
|
|
1213
|
+
if (subscription.outstanding) {
|
|
1214
|
+
clearTimeout(subscription.outstanding.timer);
|
|
1215
|
+
const acknowledgement = subscription.outstanding.acknowledgement;
|
|
1216
|
+
subscription.outstanding = undefined;
|
|
1217
|
+
const session = slot.session;
|
|
1218
|
+
if (session) {
|
|
1219
|
+
const operation = session.acknowledgeFrame(acknowledgement);
|
|
1220
|
+
const result = await waitBounded(operation, this.options.frameAcknowledgementTimeoutMs)
|
|
1221
|
+
.catch(() => ({ settled: true, value: { accepted: false } }));
|
|
1222
|
+
if ((!result.settled || !result.value.accepted) && slot.session === session) {
|
|
1223
|
+
operation.catch(() => undefined);
|
|
1224
|
+
await this.terminateSlotSession(slot);
|
|
1225
|
+
}
|
|
1226
|
+
}
|
|
1227
|
+
}
|
|
1228
|
+
}
|
|
1229
|
+
async acknowledgeFrameInBackground(slot, session, acknowledgement) {
|
|
1230
|
+
const operation = session.acknowledgeFrame(acknowledgement);
|
|
1231
|
+
const result = await waitBounded(operation, this.options.frameAcknowledgementTimeoutMs)
|
|
1232
|
+
.catch(() => ({ settled: true, value: { accepted: false } }));
|
|
1233
|
+
if (result.settled && result.value.accepted)
|
|
1234
|
+
return;
|
|
1235
|
+
operation.catch(() => undefined);
|
|
1236
|
+
if (slot.session !== session)
|
|
1237
|
+
return;
|
|
1238
|
+
if (slot.lease)
|
|
1239
|
+
await this.revokeCapabilityRecord(slot.lease.capability);
|
|
1240
|
+
else
|
|
1241
|
+
await this.retireSlot(slot.projectId, true);
|
|
1242
|
+
}
|
|
1243
|
+
requireValidLease(lease) {
|
|
1244
|
+
if (lease.released || lease.controller.signal.aborted) {
|
|
1245
|
+
throw new BrowserRuntimeError('CAPABILITY_REVOKED');
|
|
1246
|
+
}
|
|
1247
|
+
const capability = this.resolveCapability(lease.digest, lease.peerId, lease.role, lease.capability.source);
|
|
1248
|
+
if (capability !== lease.capability
|
|
1249
|
+
|| capability.lease !== lease
|
|
1250
|
+
|| lease.slot.lease !== lease
|
|
1251
|
+
|| !lease.slot.session) {
|
|
1252
|
+
throw new BrowserRuntimeError('CAPABILITY_REVOKED');
|
|
1253
|
+
}
|
|
1254
|
+
}
|
|
1255
|
+
resolveCapability(digest, peerId, expectedRole, expectedSource, expectedScopeId, expectedSessionId) {
|
|
1256
|
+
const record = this.capabilitiesByDigest.get(digest.toString('hex'));
|
|
1257
|
+
if (!record || !digestsEqual(record.digest, digest) || record.peerId !== peerId) {
|
|
1258
|
+
throw new BrowserRuntimeError('CAPABILITY_INVALID');
|
|
1259
|
+
}
|
|
1260
|
+
if (record.expiresAt <= Date.now()) {
|
|
1261
|
+
record.state = 'expired';
|
|
1262
|
+
this.trackCleanup(this.revokeCapabilityRecord(record));
|
|
1263
|
+
throw new BrowserRuntimeError('CAPABILITY_EXPIRED');
|
|
1264
|
+
}
|
|
1265
|
+
if (record.state !== 'active')
|
|
1266
|
+
throw new BrowserRuntimeError('CAPABILITY_REVOKED');
|
|
1267
|
+
if ((expectedRole && record.role !== expectedRole)
|
|
1268
|
+
|| (expectedSource && record.source !== expectedSource)
|
|
1269
|
+
|| (expectedScopeId && record.scopeId !== expectedScopeId)
|
|
1270
|
+
|| (expectedSessionId && record.sessionId !== expectedSessionId)) {
|
|
1271
|
+
throw new BrowserRuntimeError('CAPABILITY_INVALID');
|
|
1272
|
+
}
|
|
1273
|
+
return record;
|
|
1274
|
+
}
|
|
1275
|
+
describeCapability(record) {
|
|
1276
|
+
return {
|
|
1277
|
+
capabilityId: record.capabilityId,
|
|
1278
|
+
projectId: record.projectId,
|
|
1279
|
+
actorId: record.actorId,
|
|
1280
|
+
role: record.role,
|
|
1281
|
+
peerId: record.peerId,
|
|
1282
|
+
source: record.source,
|
|
1283
|
+
...(record.scopeId ? { scopeId: record.scopeId } : {}),
|
|
1284
|
+
...(record.sessionId ? { sessionId: record.sessionId } : {}),
|
|
1285
|
+
expiresAt: record.expiresAt,
|
|
1286
|
+
};
|
|
1287
|
+
}
|
|
1288
|
+
async revokeCapabilityRecord(capability, invokeDisconnect = true) {
|
|
1289
|
+
if (capability.revocationComplete)
|
|
1290
|
+
return;
|
|
1291
|
+
if (capability.revocationPromise)
|
|
1292
|
+
return capability.revocationPromise;
|
|
1293
|
+
capability.revocationInvokeDisconnect ??= invokeDisconnect;
|
|
1294
|
+
if (capability.state === 'active')
|
|
1295
|
+
capability.state = 'revoked';
|
|
1296
|
+
clearTimeout(capability.expiryTimer);
|
|
1297
|
+
this.capabilitiesByDigest.delete(capability.digest.toString('hex'));
|
|
1298
|
+
const operation = (async () => {
|
|
1299
|
+
const errors = [];
|
|
1300
|
+
const lease = capability.lease;
|
|
1301
|
+
if (!capability.leaseCleanupComplete) {
|
|
1302
|
+
if (lease) {
|
|
1303
|
+
await this.releaseLeaseRecord(lease).then(() => { capability.leaseCleanupComplete = true; }, (error) => errors.push(error));
|
|
1304
|
+
}
|
|
1305
|
+
else {
|
|
1306
|
+
capability.leaseCleanupComplete = true;
|
|
1307
|
+
}
|
|
1308
|
+
}
|
|
1309
|
+
if (!capability.revocationInvokeDisconnect)
|
|
1310
|
+
capability.disconnectComplete = true;
|
|
1311
|
+
if (capability.revocationInvokeDisconnect && !capability.disconnectComplete) {
|
|
1312
|
+
if (capability.disconnect) {
|
|
1313
|
+
const disconnectController = new AbortController();
|
|
1314
|
+
let disconnectFailed = false;
|
|
1315
|
+
const result = await waitBounded(Promise.resolve().then(() => capability.disconnect(disconnectController.signal)), this.options.quiescenceTimeoutMs).catch((error) => {
|
|
1316
|
+
disconnectFailed = true;
|
|
1317
|
+
errors.push(error);
|
|
1318
|
+
return { settled: true, value: undefined };
|
|
1319
|
+
});
|
|
1320
|
+
if (!result.settled) {
|
|
1321
|
+
disconnectController.abort(new BrowserRuntimeError('TIMEOUT'));
|
|
1322
|
+
errors.push(new BrowserRuntimeError('TIMEOUT'));
|
|
1323
|
+
}
|
|
1324
|
+
else if (!disconnectFailed) {
|
|
1325
|
+
capability.disconnectComplete = true;
|
|
1326
|
+
}
|
|
1327
|
+
}
|
|
1328
|
+
else {
|
|
1329
|
+
const framedPeer = [...this.framedPeers].find((peer) => peer.peerId === capability.peerId);
|
|
1330
|
+
if (framedPeer) {
|
|
1331
|
+
await framedPeer.close().then(() => { capability.disconnectComplete = true; }, (error) => errors.push(error));
|
|
1332
|
+
}
|
|
1333
|
+
else {
|
|
1334
|
+
capability.disconnectComplete = true;
|
|
1335
|
+
}
|
|
1336
|
+
}
|
|
1337
|
+
}
|
|
1338
|
+
if (errors.length > 0)
|
|
1339
|
+
throw new AggregateError(errors, 'Capability cleanup is incomplete');
|
|
1340
|
+
capability.revocationComplete = true;
|
|
1341
|
+
this.capabilitiesById.delete(capability.capabilityId);
|
|
1342
|
+
const slot = this.slots.get(capability.projectId);
|
|
1343
|
+
if (slot
|
|
1344
|
+
&& !slot.mutex.busy
|
|
1345
|
+
&& !slot.session
|
|
1346
|
+
&& !slot.lease
|
|
1347
|
+
&& !slot.operation
|
|
1348
|
+
&& ![...this.capabilitiesById.values()].some((record) => (record.projectId === capability.projectId)))
|
|
1349
|
+
this.slots.delete(capability.projectId);
|
|
1350
|
+
})();
|
|
1351
|
+
capability.revocationPromise = operation;
|
|
1352
|
+
try {
|
|
1353
|
+
await operation;
|
|
1354
|
+
this.failedRevocations.delete(capability);
|
|
1355
|
+
}
|
|
1356
|
+
catch (error) {
|
|
1357
|
+
this.failedRevocations.add(capability);
|
|
1358
|
+
throw error;
|
|
1359
|
+
}
|
|
1360
|
+
finally {
|
|
1361
|
+
if (capability.revocationPromise === operation)
|
|
1362
|
+
capability.revocationPromise = undefined;
|
|
1363
|
+
}
|
|
1364
|
+
}
|
|
1365
|
+
async releaseLeaseRecord(lease) {
|
|
1366
|
+
if (lease.releasePromise)
|
|
1367
|
+
return lease.releasePromise;
|
|
1368
|
+
const operation = this.releaseLeaseRecordInternal(lease);
|
|
1369
|
+
lease.releasePromise = operation;
|
|
1370
|
+
try {
|
|
1371
|
+
await operation;
|
|
1372
|
+
}
|
|
1373
|
+
finally {
|
|
1374
|
+
if (lease.releasePromise === operation)
|
|
1375
|
+
lease.releasePromise = undefined;
|
|
1376
|
+
}
|
|
1377
|
+
}
|
|
1378
|
+
async releaseLeaseRecordInternal(lease) {
|
|
1379
|
+
if (lease.released && lease.slot.lease !== lease)
|
|
1380
|
+
return;
|
|
1381
|
+
const slot = lease.slot;
|
|
1382
|
+
const release = await slot.mutex.acquire();
|
|
1383
|
+
const generation = lease.releaseGeneration ?? ++slot.generation;
|
|
1384
|
+
lease.releaseGeneration = generation;
|
|
1385
|
+
try {
|
|
1386
|
+
if (slot.fencingGeneration !== undefined && slot.fencingGeneration !== generation) {
|
|
1387
|
+
lease.controller.abort(new BrowserRuntimeError('ABORTED'));
|
|
1388
|
+
}
|
|
1389
|
+
else {
|
|
1390
|
+
slot.fencingGeneration = generation;
|
|
1391
|
+
}
|
|
1392
|
+
lease.released = true;
|
|
1393
|
+
lease.controller.abort(new BrowserRuntimeError('ABORTED'));
|
|
1394
|
+
if (slot.operation?.lease === lease) {
|
|
1395
|
+
slot.operation.controller.abort(new BrowserRuntimeError('ABORTED'));
|
|
1396
|
+
}
|
|
1397
|
+
}
|
|
1398
|
+
finally {
|
|
1399
|
+
release();
|
|
1400
|
+
}
|
|
1401
|
+
await this.closeFrameSubscriptionIfLease(lease);
|
|
1402
|
+
await this.quiesceSlot(slot);
|
|
1403
|
+
if (slot.permanentlyFenced
|
|
1404
|
+
&& (slot.session || slot.proxy || slot.profileDirectory))
|
|
1405
|
+
await this.terminateSlotSession(slot);
|
|
1406
|
+
const finalRelease = await slot.mutex.acquire();
|
|
1407
|
+
try {
|
|
1408
|
+
if (slot.lease === lease)
|
|
1409
|
+
slot.lease = undefined;
|
|
1410
|
+
if (lease.capability.lease === lease)
|
|
1411
|
+
lease.capability.lease = undefined;
|
|
1412
|
+
if (slot.fencingGeneration === generation)
|
|
1413
|
+
slot.fencingGeneration = undefined;
|
|
1414
|
+
lease.releaseGeneration = undefined;
|
|
1415
|
+
this.scheduleIdleRetirement(slot);
|
|
1416
|
+
}
|
|
1417
|
+
finally {
|
|
1418
|
+
finalRelease();
|
|
1419
|
+
}
|
|
1420
|
+
}
|
|
1421
|
+
async closeFrameSubscriptionIfLease(lease) {
|
|
1422
|
+
const subscription = lease.slot.frameSubscription;
|
|
1423
|
+
if (subscription?.lease === lease)
|
|
1424
|
+
await this.closeFrameSubscription(subscription);
|
|
1425
|
+
}
|
|
1426
|
+
async quiesceSlot(slot) {
|
|
1427
|
+
const operation = slot.operation;
|
|
1428
|
+
if (!operation)
|
|
1429
|
+
return;
|
|
1430
|
+
operation.controller.abort(new BrowserRuntimeError('ABORTED'));
|
|
1431
|
+
const settled = await waitBounded(operation.promise, this.options.quiescenceTimeoutMs);
|
|
1432
|
+
if (settled.settled)
|
|
1433
|
+
return;
|
|
1434
|
+
await this.terminateSlotSession(slot);
|
|
1435
|
+
if (slot.operation === operation)
|
|
1436
|
+
slot.operation = undefined;
|
|
1437
|
+
}
|
|
1438
|
+
async enforceOperationQuiescence(operation) {
|
|
1439
|
+
const settled = await waitBounded(operation.promise, this.options.quiescenceTimeoutMs);
|
|
1440
|
+
if (settled.settled || operation.lease.released)
|
|
1441
|
+
return;
|
|
1442
|
+
await this.revokeCapabilityRecord(operation.lease.capability);
|
|
1443
|
+
}
|
|
1444
|
+
async terminateSlotSession(slot) {
|
|
1445
|
+
const session = slot.session;
|
|
1446
|
+
if (session) {
|
|
1447
|
+
let termination;
|
|
1448
|
+
try {
|
|
1449
|
+
const result = await waitBounded(session.terminate({
|
|
1450
|
+
gracefulTimeoutMs: this.options.terminationGraceMs,
|
|
1451
|
+
forceTimeoutMs: this.options.terminationForceMs,
|
|
1452
|
+
}), this.options.terminationGraceMs + this.options.terminationForceMs + 1000);
|
|
1453
|
+
if (!result.settled)
|
|
1454
|
+
throw new BrowserRuntimeError('TIMEOUT');
|
|
1455
|
+
termination = result.value;
|
|
1456
|
+
}
|
|
1457
|
+
catch {
|
|
1458
|
+
slot.permanentlyFenced = true;
|
|
1459
|
+
throw new BrowserRuntimeError('FENCED');
|
|
1460
|
+
}
|
|
1461
|
+
if (!termination.confirmedDead) {
|
|
1462
|
+
slot.permanentlyFenced = true;
|
|
1463
|
+
throw new BrowserRuntimeError('FENCED');
|
|
1464
|
+
}
|
|
1465
|
+
slot.unsubscribeSession?.();
|
|
1466
|
+
slot.unsubscribeSession = undefined;
|
|
1467
|
+
slot.session = undefined;
|
|
1468
|
+
}
|
|
1469
|
+
if (slot.proxy) {
|
|
1470
|
+
await this.stopProxyBounded(slot.proxy).then(() => { slot.proxy = undefined; }, () => { slot.permanentlyFenced = true; });
|
|
1471
|
+
}
|
|
1472
|
+
if (slot.profileDirectory) {
|
|
1473
|
+
await plugins.fsPromises.rm(slot.profileDirectory, { recursive: true, force: true }).then(() => { slot.profileDirectory = undefined; }, () => { slot.permanentlyFenced = true; });
|
|
1474
|
+
}
|
|
1475
|
+
if (slot.proxy || slot.profileDirectory)
|
|
1476
|
+
throw new BrowserRuntimeError('FENCED');
|
|
1477
|
+
}
|
|
1478
|
+
scheduleIdleRetirement(slot) {
|
|
1479
|
+
if (slot.idleTimer)
|
|
1480
|
+
clearTimeout(slot.idleTimer);
|
|
1481
|
+
const generation = slot.generation;
|
|
1482
|
+
slot.idleTimer = setTimeout(() => {
|
|
1483
|
+
if (slot.generation !== generation || slot.lease)
|
|
1484
|
+
return;
|
|
1485
|
+
this.trackCleanup(this.retireSlot(slot.projectId, false));
|
|
1486
|
+
}, this.options.idleRetirementMs);
|
|
1487
|
+
slot.idleTimer.unref();
|
|
1488
|
+
}
|
|
1489
|
+
async stopProxyBounded(proxy) {
|
|
1490
|
+
const operation = proxy.stop();
|
|
1491
|
+
const result = await waitBounded(operation, this.options.terminationGraceMs + this.options.terminationForceMs + 1000);
|
|
1492
|
+
if (!result.settled) {
|
|
1493
|
+
operation.catch(() => undefined);
|
|
1494
|
+
throw new BrowserRuntimeError('TIMEOUT');
|
|
1495
|
+
}
|
|
1496
|
+
}
|
|
1497
|
+
async retireSlot(projectId, force) {
|
|
1498
|
+
const slot = this.slots.get(projectId);
|
|
1499
|
+
if (!slot)
|
|
1500
|
+
return;
|
|
1501
|
+
const release = await slot.mutex.acquire();
|
|
1502
|
+
const generation = ++slot.generation;
|
|
1503
|
+
try {
|
|
1504
|
+
if (!force && (slot.lease || slot.operation))
|
|
1505
|
+
return;
|
|
1506
|
+
slot.fencingGeneration = generation;
|
|
1507
|
+
if (slot.idleTimer) {
|
|
1508
|
+
clearTimeout(slot.idleTimer);
|
|
1509
|
+
slot.idleTimer = undefined;
|
|
1510
|
+
}
|
|
1511
|
+
if (slot.lease) {
|
|
1512
|
+
slot.lease.released = true;
|
|
1513
|
+
slot.lease.controller.abort(new BrowserRuntimeError('ABORTED'));
|
|
1514
|
+
}
|
|
1515
|
+
slot.operation?.controller.abort(new BrowserRuntimeError('ABORTED'));
|
|
1516
|
+
}
|
|
1517
|
+
finally {
|
|
1518
|
+
release();
|
|
1519
|
+
}
|
|
1520
|
+
await this.quiesceSlot(slot);
|
|
1521
|
+
if (slot.lease)
|
|
1522
|
+
await this.closeFrameSubscriptionIfLease(slot.lease);
|
|
1523
|
+
await this.terminateSlotSession(slot);
|
|
1524
|
+
await this.artifactStore.purgeProject(projectId);
|
|
1525
|
+
const finalRelease = await slot.mutex.acquire();
|
|
1526
|
+
try {
|
|
1527
|
+
if (slot.generation !== generation || slot.fencingGeneration !== generation) {
|
|
1528
|
+
throw new BrowserRuntimeError('BUSY');
|
|
1529
|
+
}
|
|
1530
|
+
const lease = slot.lease;
|
|
1531
|
+
if (lease && lease.capability.lease === lease) {
|
|
1532
|
+
lease.capability.lease = undefined;
|
|
1533
|
+
}
|
|
1534
|
+
slot.lease = undefined;
|
|
1535
|
+
slot.operation = undefined;
|
|
1536
|
+
slot.fencingGeneration = undefined;
|
|
1537
|
+
this.slots.delete(projectId);
|
|
1538
|
+
}
|
|
1539
|
+
finally {
|
|
1540
|
+
finalRelease();
|
|
1541
|
+
}
|
|
1542
|
+
}
|
|
1543
|
+
assertSlotAvailable(slot) {
|
|
1544
|
+
if (slot.permanentlyFenced)
|
|
1545
|
+
throw new BrowserRuntimeError('FENCED');
|
|
1546
|
+
if (slot.fencingGeneration !== undefined)
|
|
1547
|
+
throw new BrowserRuntimeError('BUSY');
|
|
1548
|
+
}
|
|
1549
|
+
throwIfAcquisitionAborted(signal) {
|
|
1550
|
+
if (signal?.aborted)
|
|
1551
|
+
throw new BrowserRuntimeError('ABORTED');
|
|
1552
|
+
}
|
|
1553
|
+
requireHuman(lease) {
|
|
1554
|
+
if (lease.role !== 'human')
|
|
1555
|
+
throw new BrowserRuntimeError('CAPABILITY_INVALID');
|
|
1556
|
+
}
|
|
1557
|
+
validateRole(value) {
|
|
1558
|
+
if (value !== 'human' && value !== 'agent')
|
|
1559
|
+
throw new BrowserRuntimeError('INVALID_INPUT');
|
|
1560
|
+
return value;
|
|
1561
|
+
}
|
|
1562
|
+
validateSource(value) {
|
|
1563
|
+
if (value !== 'human' && value !== 'flex' && value !== 'mcp') {
|
|
1564
|
+
throw new BrowserRuntimeError('INVALID_INPUT');
|
|
1565
|
+
}
|
|
1566
|
+
return value;
|
|
1567
|
+
}
|
|
1568
|
+
trackCleanup(operation) {
|
|
1569
|
+
const observed = operation.catch(() => undefined).finally(() => {
|
|
1570
|
+
this.cleanupOperations.delete(observed);
|
|
1571
|
+
});
|
|
1572
|
+
this.cleanupOperations.add(observed);
|
|
1573
|
+
}
|
|
1574
|
+
async emitAudit(event) {
|
|
1575
|
+
if (!this.options.audit)
|
|
1576
|
+
return;
|
|
1577
|
+
const controller = new AbortController();
|
|
1578
|
+
const operation = Promise.resolve().then(() => this.options.audit(event, controller.signal));
|
|
1579
|
+
const observed = waitBounded(operation, this.options.auditTimeoutMs)
|
|
1580
|
+
.then((result) => {
|
|
1581
|
+
if (!result.settled)
|
|
1582
|
+
controller.abort(new BrowserRuntimeError('TIMEOUT'));
|
|
1583
|
+
})
|
|
1584
|
+
.catch(() => undefined);
|
|
1585
|
+
this.trackCleanup(observed);
|
|
1586
|
+
await observed;
|
|
1587
|
+
}
|
|
1588
|
+
}
|
|
1589
|
+
export class BrowserRuntimeLease {
|
|
1590
|
+
runtime;
|
|
1591
|
+
record;
|
|
1592
|
+
/** @internal */
|
|
1593
|
+
constructor(runtime, record) {
|
|
1594
|
+
this.runtime = runtime;
|
|
1595
|
+
this.record = record;
|
|
1596
|
+
}
|
|
1597
|
+
get leaseId() {
|
|
1598
|
+
return this.record.leaseId;
|
|
1599
|
+
}
|
|
1600
|
+
get role() {
|
|
1601
|
+
return this.record.role;
|
|
1602
|
+
}
|
|
1603
|
+
get projectId() {
|
|
1604
|
+
return this.record.capability.projectId;
|
|
1605
|
+
}
|
|
1606
|
+
getState() {
|
|
1607
|
+
return this.runtime.getLeaseState(this.record);
|
|
1608
|
+
}
|
|
1609
|
+
executeAgentAction(action, options) {
|
|
1610
|
+
return this.runtime.executeLeaseAgentAction(this.record, action, options);
|
|
1611
|
+
}
|
|
1612
|
+
executeHumanAction(action, options) {
|
|
1613
|
+
return this.runtime.leaseHumanAgentAction(this.record, action, options);
|
|
1614
|
+
}
|
|
1615
|
+
createTab(options, operationOptions) {
|
|
1616
|
+
return this.runtime.leaseCreateTab(this.record, options, operationOptions);
|
|
1617
|
+
}
|
|
1618
|
+
activateTab(tabId, operationOptions) {
|
|
1619
|
+
return this.runtime.leaseActivateTab(this.record, tabId, operationOptions);
|
|
1620
|
+
}
|
|
1621
|
+
closeTab(tabId, operationOptions) {
|
|
1622
|
+
return this.runtime.leaseCloseTab(this.record, tabId, operationOptions);
|
|
1623
|
+
}
|
|
1624
|
+
back(options, operationOptions) {
|
|
1625
|
+
return this.runtime.leaseHistory(this.record, 'back', options, operationOptions);
|
|
1626
|
+
}
|
|
1627
|
+
forward(options, operationOptions) {
|
|
1628
|
+
return this.runtime.leaseHistory(this.record, 'forward', options, operationOptions);
|
|
1629
|
+
}
|
|
1630
|
+
reload(options, operationOptions) {
|
|
1631
|
+
return this.runtime.leaseHistory(this.record, 'reload', options, operationOptions);
|
|
1632
|
+
}
|
|
1633
|
+
setViewport(viewport, operationOptions) {
|
|
1634
|
+
return this.runtime.leaseSetViewport(this.record, viewport, operationOptions);
|
|
1635
|
+
}
|
|
1636
|
+
dispatchMouse(input, operationOptions) {
|
|
1637
|
+
return this.runtime.leaseDispatchRawInput(this.record, 'dispatchMouse', input, operationOptions);
|
|
1638
|
+
}
|
|
1639
|
+
dispatchWheel(input, operationOptions) {
|
|
1640
|
+
return this.runtime.leaseDispatchRawInput(this.record, 'dispatchWheel', input, operationOptions);
|
|
1641
|
+
}
|
|
1642
|
+
dispatchKey(input, operationOptions) {
|
|
1643
|
+
return this.runtime.leaseDispatchRawInput(this.record, 'dispatchKey', input, operationOptions);
|
|
1644
|
+
}
|
|
1645
|
+
insertText(input, operationOptions) {
|
|
1646
|
+
return this.runtime.leaseDispatchRawInput(this.record, 'insertText', input, operationOptions);
|
|
1647
|
+
}
|
|
1648
|
+
subscribeEvents(listener) {
|
|
1649
|
+
return this.runtime.subscribeLeaseEvents(this.record, listener);
|
|
1650
|
+
}
|
|
1651
|
+
acknowledgeFrame(acknowledgement) {
|
|
1652
|
+
return this.runtime.acknowledgeLeaseFrame(this.record, acknowledgement);
|
|
1653
|
+
}
|
|
1654
|
+
readArtifact(artifactId) {
|
|
1655
|
+
return this.runtime.readLeaseArtifact(this.record, artifactId);
|
|
1656
|
+
}
|
|
1657
|
+
deleteArtifact(artifactId) {
|
|
1658
|
+
return this.runtime.deleteLeaseArtifact(this.record, artifactId);
|
|
1659
|
+
}
|
|
1660
|
+
cancelActiveOperation() {
|
|
1661
|
+
return this.runtime.cancelLeaseOperation(this.record);
|
|
1662
|
+
}
|
|
1663
|
+
release() {
|
|
1664
|
+
return this.runtime.releaseLease(this.record);
|
|
1665
|
+
}
|
|
1666
|
+
}
|
|
1667
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5ydW50aW1lLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvY2xhc3Nlcy5ydW50aW1lLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sY0FBYyxDQUFDO0FBQ3hDLE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxNQUFNLGNBQWMsQ0FBQztBQUNuRCxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUNsRSxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUM5RCxPQUFPLEVBQUUsNkJBQTZCLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUNqRSxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFDbEQsT0FBTyxFQUNMLHFCQUFxQixHQUV0QixNQUFNLHVCQUF1QixDQUFDO0FBdUIvQixPQUFPLEVBQ0wsZUFBZSxFQUNmLFdBQVcsRUFDWCxZQUFZLEVBQ1osUUFBUSxFQUNSLGNBQWMsRUFDZCxxQkFBcUIsRUFDckIsZUFBZSxFQUNmLHVCQUF1QixFQUN2QixXQUFXLEdBQ1osTUFBTSxZQUFZLENBQUM7QUFDcEIsT0FBTyxFQUFFLDhCQUE4QixFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFxR3JFLE1BQU0sZ0JBQWdCLEdBQUcsR0FBRyxDQUFDO0FBQzdCLE1BQU0sY0FBYyxHQUFHLEdBQUcsQ0FBQztBQUMzQixNQUFNLGFBQWEsR0FBRyxHQUFHLENBQUM7QUFFMUIsTUFBTSxPQUFPLGNBQWM7SUFDUixPQUFPLENBQTRCO0lBQ25DLFdBQVcsQ0FBUztJQUNwQixZQUFZLENBQVM7SUFDckIsUUFBUSxDQUFTO0lBQ2pCLGFBQWEsQ0FBdUI7SUFDcEMsS0FBSyxHQUFHLElBQUksR0FBRyxFQUF3QixDQUFDO0lBQ3hDLG9CQUFvQixHQUFHLElBQUksR0FBRyxFQUE2QixDQUFDO0lBQzVELGdCQUFnQixHQUFHLElBQUksR0FBRyxFQUE2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
|