opensteer 0.4.6 → 0.4.7
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/CHANGELOG.md +4 -3
- package/README.md +4 -4
- package/bin/opensteer.mjs +5 -3
- package/dist/{chunk-MGZ3QEYT.js → chunk-PIJI7FBH.js} +469 -220
- package/dist/cli/server.cjs +465 -216
- package/dist/cli/server.js +3 -2
- package/dist/index.cjs +475 -225
- package/dist/index.d.cts +64 -41
- package/dist/index.d.ts +64 -41
- package/dist/index.js +13 -11
- package/package.json +73 -80
|
@@ -4936,33 +4936,36 @@ var OpensteerActionError = class extends Error {
|
|
|
4936
4936
|
}
|
|
4937
4937
|
};
|
|
4938
4938
|
|
|
4939
|
-
// src/
|
|
4940
|
-
var
|
|
4939
|
+
// src/cloud/contracts.ts
|
|
4940
|
+
var cloudSessionContractVersion = "v3";
|
|
4941
|
+
|
|
4942
|
+
// src/cloud/errors.ts
|
|
4943
|
+
var OpensteerCloudError = class extends Error {
|
|
4941
4944
|
code;
|
|
4942
4945
|
status;
|
|
4943
4946
|
details;
|
|
4944
4947
|
constructor(code, message, status, details) {
|
|
4945
4948
|
super(message);
|
|
4946
|
-
this.name = "
|
|
4949
|
+
this.name = "OpensteerCloudError";
|
|
4947
4950
|
this.code = code;
|
|
4948
4951
|
this.status = status;
|
|
4949
4952
|
this.details = details;
|
|
4950
4953
|
}
|
|
4951
4954
|
};
|
|
4952
|
-
function
|
|
4953
|
-
return new
|
|
4954
|
-
"
|
|
4955
|
-
message || `${method} is not supported in
|
|
4955
|
+
function cloudUnsupportedMethodError(method, message) {
|
|
4956
|
+
return new OpensteerCloudError(
|
|
4957
|
+
"CLOUD_UNSUPPORTED_METHOD",
|
|
4958
|
+
message || `${method} is not supported in cloud mode.`
|
|
4956
4959
|
);
|
|
4957
4960
|
}
|
|
4958
|
-
function
|
|
4959
|
-
return new
|
|
4960
|
-
"
|
|
4961
|
-
"
|
|
4961
|
+
function cloudNotLaunchedError() {
|
|
4962
|
+
return new OpensteerCloudError(
|
|
4963
|
+
"CLOUD_SESSION_NOT_FOUND",
|
|
4964
|
+
"Cloud session is not connected. Call launch() first."
|
|
4962
4965
|
);
|
|
4963
4966
|
}
|
|
4964
4967
|
|
|
4965
|
-
// src/
|
|
4968
|
+
// src/cloud/action-ws-client.ts
|
|
4966
4969
|
import WebSocket from "ws";
|
|
4967
4970
|
var ActionWsClient = class _ActionWsClient {
|
|
4968
4971
|
ws;
|
|
@@ -4980,18 +4983,18 @@ var ActionWsClient = class _ActionWsClient {
|
|
|
4980
4983
|
});
|
|
4981
4984
|
ws.on("error", (error) => {
|
|
4982
4985
|
this.rejectAll(
|
|
4983
|
-
new
|
|
4984
|
-
"
|
|
4985
|
-
`
|
|
4986
|
+
new OpensteerCloudError(
|
|
4987
|
+
"CLOUD_TRANSPORT_ERROR",
|
|
4988
|
+
`Cloud action websocket error: ${error.message}`
|
|
4986
4989
|
)
|
|
4987
4990
|
);
|
|
4988
4991
|
});
|
|
4989
4992
|
ws.on("close", () => {
|
|
4990
4993
|
this.closed = true;
|
|
4991
4994
|
this.rejectAll(
|
|
4992
|
-
new
|
|
4993
|
-
"
|
|
4994
|
-
"
|
|
4995
|
+
new OpensteerCloudError(
|
|
4996
|
+
"CLOUD_SESSION_CLOSED",
|
|
4997
|
+
"Cloud action websocket closed."
|
|
4995
4998
|
)
|
|
4996
4999
|
);
|
|
4997
5000
|
});
|
|
@@ -5003,8 +5006,8 @@ var ActionWsClient = class _ActionWsClient {
|
|
|
5003
5006
|
ws.once("open", () => resolve());
|
|
5004
5007
|
ws.once("error", (error) => {
|
|
5005
5008
|
reject(
|
|
5006
|
-
new
|
|
5007
|
-
"
|
|
5009
|
+
new OpensteerCloudError(
|
|
5010
|
+
"CLOUD_TRANSPORT_ERROR",
|
|
5008
5011
|
`Failed to connect action websocket: ${error.message}`
|
|
5009
5012
|
)
|
|
5010
5013
|
);
|
|
@@ -5014,9 +5017,9 @@ var ActionWsClient = class _ActionWsClient {
|
|
|
5014
5017
|
}
|
|
5015
5018
|
async request(method, args) {
|
|
5016
5019
|
if (this.closed || this.ws.readyState !== WebSocket.OPEN) {
|
|
5017
|
-
throw new
|
|
5018
|
-
"
|
|
5019
|
-
"
|
|
5020
|
+
throw new OpensteerCloudError(
|
|
5021
|
+
"CLOUD_SESSION_CLOSED",
|
|
5022
|
+
"Cloud action websocket is closed."
|
|
5020
5023
|
);
|
|
5021
5024
|
}
|
|
5022
5025
|
const id = this.nextRequestId;
|
|
@@ -5035,8 +5038,8 @@ var ActionWsClient = class _ActionWsClient {
|
|
|
5035
5038
|
this.ws.send(JSON.stringify(payload));
|
|
5036
5039
|
} catch (error) {
|
|
5037
5040
|
this.pending.delete(id);
|
|
5038
|
-
const message = error instanceof Error ? error.message : "Failed to send
|
|
5039
|
-
throw new
|
|
5041
|
+
const message = error instanceof Error ? error.message : "Failed to send cloud action request.";
|
|
5042
|
+
throw new OpensteerCloudError("CLOUD_TRANSPORT_ERROR", message);
|
|
5040
5043
|
}
|
|
5041
5044
|
return await resultPromise;
|
|
5042
5045
|
}
|
|
@@ -5054,9 +5057,9 @@ var ActionWsClient = class _ActionWsClient {
|
|
|
5054
5057
|
parsed = JSON.parse(rawDataToUtf8(raw));
|
|
5055
5058
|
} catch {
|
|
5056
5059
|
this.rejectAll(
|
|
5057
|
-
new
|
|
5058
|
-
"
|
|
5059
|
-
"Invalid
|
|
5060
|
+
new OpensteerCloudError(
|
|
5061
|
+
"CLOUD_TRANSPORT_ERROR",
|
|
5062
|
+
"Invalid cloud action response payload."
|
|
5060
5063
|
)
|
|
5061
5064
|
);
|
|
5062
5065
|
return;
|
|
@@ -5069,7 +5072,7 @@ var ActionWsClient = class _ActionWsClient {
|
|
|
5069
5072
|
return;
|
|
5070
5073
|
}
|
|
5071
5074
|
pending.reject(
|
|
5072
|
-
new
|
|
5075
|
+
new OpensteerCloudError(
|
|
5073
5076
|
parsed.code,
|
|
5074
5077
|
parsed.error,
|
|
5075
5078
|
void 0,
|
|
@@ -5097,7 +5100,7 @@ function withTokenQuery(wsUrl, token) {
|
|
|
5097
5100
|
return url.toString();
|
|
5098
5101
|
}
|
|
5099
5102
|
|
|
5100
|
-
// src/
|
|
5103
|
+
// src/cloud/local-cache-sync.ts
|
|
5101
5104
|
import fs2 from "fs";
|
|
5102
5105
|
import path3 from "path";
|
|
5103
5106
|
function collectLocalSelectorCacheEntries(storage) {
|
|
@@ -5221,26 +5224,26 @@ function dedupeNewest(entries) {
|
|
|
5221
5224
|
return [...byKey.values()];
|
|
5222
5225
|
}
|
|
5223
5226
|
|
|
5224
|
-
// src/
|
|
5227
|
+
// src/cloud/cdp-client.ts
|
|
5225
5228
|
import {
|
|
5226
5229
|
chromium
|
|
5227
5230
|
} from "playwright";
|
|
5228
|
-
var
|
|
5231
|
+
var CloudCdpClient = class {
|
|
5229
5232
|
async connect(args) {
|
|
5230
5233
|
const endpoint = withTokenQuery2(args.wsUrl, args.token);
|
|
5231
5234
|
let browser;
|
|
5232
5235
|
try {
|
|
5233
5236
|
browser = await chromium.connectOverCDP(endpoint);
|
|
5234
5237
|
} catch (error) {
|
|
5235
|
-
const message = error instanceof Error ? error.message : "Failed to connect to
|
|
5236
|
-
throw new
|
|
5238
|
+
const message = error instanceof Error ? error.message : "Failed to connect to cloud CDP endpoint.";
|
|
5239
|
+
throw new OpensteerCloudError("CLOUD_TRANSPORT_ERROR", message);
|
|
5237
5240
|
}
|
|
5238
5241
|
const context = browser.contexts()[0];
|
|
5239
5242
|
if (!context) {
|
|
5240
5243
|
await browser.close();
|
|
5241
|
-
throw new
|
|
5242
|
-
"
|
|
5243
|
-
"
|
|
5244
|
+
throw new OpensteerCloudError(
|
|
5245
|
+
"CLOUD_INTERNAL",
|
|
5246
|
+
"Cloud browser returned no context."
|
|
5244
5247
|
);
|
|
5245
5248
|
}
|
|
5246
5249
|
const page = context.pages()[0] || await context.newPage();
|
|
@@ -5253,9 +5256,9 @@ function withTokenQuery2(wsUrl, token) {
|
|
|
5253
5256
|
return url.toString();
|
|
5254
5257
|
}
|
|
5255
5258
|
|
|
5256
|
-
// src/
|
|
5259
|
+
// src/cloud/session-client.ts
|
|
5257
5260
|
var CACHE_IMPORT_BATCH_SIZE = 200;
|
|
5258
|
-
var
|
|
5261
|
+
var CloudSessionClient = class {
|
|
5259
5262
|
baseUrl;
|
|
5260
5263
|
key;
|
|
5261
5264
|
authScheme;
|
|
@@ -5276,7 +5279,17 @@ var RemoteSessionClient = class {
|
|
|
5276
5279
|
if (!response.ok) {
|
|
5277
5280
|
throw await parseHttpError(response);
|
|
5278
5281
|
}
|
|
5279
|
-
|
|
5282
|
+
let body;
|
|
5283
|
+
try {
|
|
5284
|
+
body = await response.json();
|
|
5285
|
+
} catch {
|
|
5286
|
+
throw new OpensteerCloudError(
|
|
5287
|
+
"CLOUD_CONTRACT_MISMATCH",
|
|
5288
|
+
"Invalid cloud session create response: expected a JSON object.",
|
|
5289
|
+
response.status
|
|
5290
|
+
);
|
|
5291
|
+
}
|
|
5292
|
+
return parseCreateResponse(body, response.status);
|
|
5280
5293
|
}
|
|
5281
5294
|
async close(sessionId) {
|
|
5282
5295
|
const response = await fetch(`${this.baseUrl}/sessions/${sessionId}`, {
|
|
@@ -5335,6 +5348,134 @@ var RemoteSessionClient = class {
|
|
|
5335
5348
|
function normalizeBaseUrl(baseUrl) {
|
|
5336
5349
|
return baseUrl.replace(/\/+$/, "");
|
|
5337
5350
|
}
|
|
5351
|
+
function parseCreateResponse(body, status) {
|
|
5352
|
+
const root = requireObject(
|
|
5353
|
+
body,
|
|
5354
|
+
"Invalid cloud session create response: expected a JSON object.",
|
|
5355
|
+
status
|
|
5356
|
+
);
|
|
5357
|
+
const sessionId = requireString(root, "sessionId", status);
|
|
5358
|
+
const actionWsUrl = requireString(root, "actionWsUrl", status);
|
|
5359
|
+
const cdpWsUrl = requireString(root, "cdpWsUrl", status);
|
|
5360
|
+
const actionToken = requireString(root, "actionToken", status);
|
|
5361
|
+
const cdpToken = requireString(root, "cdpToken", status);
|
|
5362
|
+
const cloudSessionUrl = requireString(root, "cloudSessionUrl", status);
|
|
5363
|
+
const cloudSessionRoot = requireObject(
|
|
5364
|
+
root.cloudSession,
|
|
5365
|
+
"Invalid cloud session create response: cloudSession must be an object.",
|
|
5366
|
+
status
|
|
5367
|
+
);
|
|
5368
|
+
const cloudSession = {
|
|
5369
|
+
sessionId: requireString(cloudSessionRoot, "sessionId", status, "cloudSession"),
|
|
5370
|
+
workspaceId: requireString(
|
|
5371
|
+
cloudSessionRoot,
|
|
5372
|
+
"workspaceId",
|
|
5373
|
+
status,
|
|
5374
|
+
"cloudSession"
|
|
5375
|
+
),
|
|
5376
|
+
state: requireString(cloudSessionRoot, "state", status, "cloudSession"),
|
|
5377
|
+
createdAt: requireNumber(cloudSessionRoot, "createdAt", status, "cloudSession"),
|
|
5378
|
+
sourceType: requireSourceType(cloudSessionRoot, "sourceType", status, "cloudSession"),
|
|
5379
|
+
sourceRef: optionalString(cloudSessionRoot, "sourceRef", status, "cloudSession"),
|
|
5380
|
+
label: optionalString(cloudSessionRoot, "label", status, "cloudSession")
|
|
5381
|
+
};
|
|
5382
|
+
const expiresAt = optionalNumber(root, "expiresAt", status);
|
|
5383
|
+
return {
|
|
5384
|
+
sessionId,
|
|
5385
|
+
actionWsUrl,
|
|
5386
|
+
cdpWsUrl,
|
|
5387
|
+
actionToken,
|
|
5388
|
+
cdpToken,
|
|
5389
|
+
expiresAt,
|
|
5390
|
+
cloudSessionUrl,
|
|
5391
|
+
cloudSession
|
|
5392
|
+
};
|
|
5393
|
+
}
|
|
5394
|
+
function requireObject(value, message, status) {
|
|
5395
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
5396
|
+
throw new OpensteerCloudError("CLOUD_CONTRACT_MISMATCH", message, status);
|
|
5397
|
+
}
|
|
5398
|
+
return value;
|
|
5399
|
+
}
|
|
5400
|
+
function requireString(source, field, status, parent) {
|
|
5401
|
+
const value = source[field];
|
|
5402
|
+
if (typeof value !== "string" || !value.trim()) {
|
|
5403
|
+
throw new OpensteerCloudError(
|
|
5404
|
+
"CLOUD_CONTRACT_MISMATCH",
|
|
5405
|
+
`Invalid cloud session create response: ${formatFieldPath(
|
|
5406
|
+
field,
|
|
5407
|
+
parent
|
|
5408
|
+
)} must be a non-empty string.`,
|
|
5409
|
+
status
|
|
5410
|
+
);
|
|
5411
|
+
}
|
|
5412
|
+
return value;
|
|
5413
|
+
}
|
|
5414
|
+
function requireNumber(source, field, status, parent) {
|
|
5415
|
+
const value = source[field];
|
|
5416
|
+
if (typeof value !== "number" || !Number.isFinite(value)) {
|
|
5417
|
+
throw new OpensteerCloudError(
|
|
5418
|
+
"CLOUD_CONTRACT_MISMATCH",
|
|
5419
|
+
`Invalid cloud session create response: ${formatFieldPath(
|
|
5420
|
+
field,
|
|
5421
|
+
parent
|
|
5422
|
+
)} must be a finite number.`,
|
|
5423
|
+
status
|
|
5424
|
+
);
|
|
5425
|
+
}
|
|
5426
|
+
return value;
|
|
5427
|
+
}
|
|
5428
|
+
function optionalString(source, field, status, parent) {
|
|
5429
|
+
const value = source[field];
|
|
5430
|
+
if (value == null) {
|
|
5431
|
+
return void 0;
|
|
5432
|
+
}
|
|
5433
|
+
if (typeof value !== "string") {
|
|
5434
|
+
throw new OpensteerCloudError(
|
|
5435
|
+
"CLOUD_CONTRACT_MISMATCH",
|
|
5436
|
+
`Invalid cloud session create response: ${formatFieldPath(
|
|
5437
|
+
field,
|
|
5438
|
+
parent
|
|
5439
|
+
)} must be a string when present.`,
|
|
5440
|
+
status
|
|
5441
|
+
);
|
|
5442
|
+
}
|
|
5443
|
+
return value;
|
|
5444
|
+
}
|
|
5445
|
+
function optionalNumber(source, field, status, parent) {
|
|
5446
|
+
const value = source[field];
|
|
5447
|
+
if (value == null) {
|
|
5448
|
+
return void 0;
|
|
5449
|
+
}
|
|
5450
|
+
if (typeof value !== "number" || !Number.isFinite(value)) {
|
|
5451
|
+
throw new OpensteerCloudError(
|
|
5452
|
+
"CLOUD_CONTRACT_MISMATCH",
|
|
5453
|
+
`Invalid cloud session create response: ${formatFieldPath(
|
|
5454
|
+
field,
|
|
5455
|
+
parent
|
|
5456
|
+
)} must be a finite number when present.`,
|
|
5457
|
+
status
|
|
5458
|
+
);
|
|
5459
|
+
}
|
|
5460
|
+
return value;
|
|
5461
|
+
}
|
|
5462
|
+
function requireSourceType(source, field, status, parent) {
|
|
5463
|
+
const value = source[field];
|
|
5464
|
+
if (value === "agent-thread" || value === "agent-run" || value === "local-cloud" || value === "manual") {
|
|
5465
|
+
return value;
|
|
5466
|
+
}
|
|
5467
|
+
throw new OpensteerCloudError(
|
|
5468
|
+
"CLOUD_CONTRACT_MISMATCH",
|
|
5469
|
+
`Invalid cloud session create response: ${formatFieldPath(
|
|
5470
|
+
field,
|
|
5471
|
+
parent
|
|
5472
|
+
)} must be one of "agent-thread", "agent-run", "local-cloud", or "manual".`,
|
|
5473
|
+
status
|
|
5474
|
+
);
|
|
5475
|
+
}
|
|
5476
|
+
function formatFieldPath(field, parent) {
|
|
5477
|
+
return parent ? `"${parent}.${field}"` : `"${field}"`;
|
|
5478
|
+
}
|
|
5338
5479
|
function zeroImportResponse() {
|
|
5339
5480
|
return {
|
|
5340
5481
|
imported: 0,
|
|
@@ -5358,19 +5499,19 @@ async function parseHttpError(response) {
|
|
|
5358
5499
|
} catch {
|
|
5359
5500
|
body = null;
|
|
5360
5501
|
}
|
|
5361
|
-
const code = typeof body?.code === "string" ?
|
|
5362
|
-
const message = typeof body?.error === "string" ? body.error : `
|
|
5363
|
-
return new
|
|
5502
|
+
const code = typeof body?.code === "string" ? toCloudErrorCode(body.code) : "CLOUD_TRANSPORT_ERROR";
|
|
5503
|
+
const message = typeof body?.error === "string" ? body.error : `Cloud request failed with status ${response.status}.`;
|
|
5504
|
+
return new OpensteerCloudError(code, message, response.status, body?.details);
|
|
5364
5505
|
}
|
|
5365
|
-
function
|
|
5366
|
-
if (code === "
|
|
5506
|
+
function toCloudErrorCode(code) {
|
|
5507
|
+
if (code === "CLOUD_AUTH_FAILED" || code === "CLOUD_SESSION_NOT_FOUND" || code === "CLOUD_SESSION_CLOSED" || code === "CLOUD_UNSUPPORTED_METHOD" || code === "CLOUD_INVALID_REQUEST" || code === "CLOUD_MODEL_NOT_ALLOWED" || code === "CLOUD_ACTION_FAILED" || code === "CLOUD_INTERNAL" || code === "CLOUD_CAPACITY_EXHAUSTED" || code === "CLOUD_RUNTIME_UNAVAILABLE" || code === "CLOUD_RUNTIME_MISMATCH" || code === "CLOUD_SESSION_STALE" || code === "CLOUD_CONTRACT_MISMATCH" || code === "CLOUD_CONTROL_PLANE_ERROR") {
|
|
5367
5508
|
return code;
|
|
5368
5509
|
}
|
|
5369
|
-
return "
|
|
5510
|
+
return "CLOUD_TRANSPORT_ERROR";
|
|
5370
5511
|
}
|
|
5371
5512
|
|
|
5372
5513
|
// src/opensteer.ts
|
|
5373
|
-
import { createHash } from "crypto";
|
|
5514
|
+
import { createHash, randomUUID as randomUUID2 } from "crypto";
|
|
5374
5515
|
|
|
5375
5516
|
// src/browser/pool.ts
|
|
5376
5517
|
import {
|
|
@@ -5786,7 +5927,7 @@ var BrowserPool = class {
|
|
|
5786
5927
|
const context = contexts[0];
|
|
5787
5928
|
const pages = context.pages();
|
|
5788
5929
|
const page = pages.length > 0 ? pages[0] : await context.newPage();
|
|
5789
|
-
return { browser, context, page,
|
|
5930
|
+
return { browser, context, page, isExternal: true };
|
|
5790
5931
|
} catch (error) {
|
|
5791
5932
|
if (browser) {
|
|
5792
5933
|
await browser.close().catch(() => void 0);
|
|
@@ -5821,7 +5962,7 @@ var BrowserPool = class {
|
|
|
5821
5962
|
context = await browser.newContext(options.context || {});
|
|
5822
5963
|
page = await context.newPage();
|
|
5823
5964
|
}
|
|
5824
|
-
return { browser, context, page,
|
|
5965
|
+
return { browser, context, page, isExternal: false };
|
|
5825
5966
|
}
|
|
5826
5967
|
async launchSandbox(options) {
|
|
5827
5968
|
const browser = await chromium2.launch({
|
|
@@ -5832,7 +5973,7 @@ var BrowserPool = class {
|
|
|
5832
5973
|
const context = await browser.newContext(options.context || {});
|
|
5833
5974
|
const page = await context.newPage();
|
|
5834
5975
|
this.browser = browser;
|
|
5835
|
-
return { browser, context, page,
|
|
5976
|
+
return { browser, context, page, isExternal: false };
|
|
5836
5977
|
}
|
|
5837
5978
|
};
|
|
5838
5979
|
|
|
@@ -5869,28 +6010,27 @@ function assertNoLegacyAiConfig(source, config) {
|
|
|
5869
6010
|
);
|
|
5870
6011
|
}
|
|
5871
6012
|
}
|
|
5872
|
-
function
|
|
6013
|
+
function assertNoLegacyRuntimeConfig(source, config) {
|
|
5873
6014
|
if (!config || typeof config !== "object") return;
|
|
5874
6015
|
const configRecord = config;
|
|
5875
6016
|
if (hasOwn(configRecord, "runtime")) {
|
|
5876
6017
|
throw new Error(
|
|
5877
|
-
`Legacy "runtime" config is no longer supported in ${source}. Use top-level "
|
|
6018
|
+
`Legacy "runtime" config is no longer supported in ${source}. Use top-level "cloud" instead.`
|
|
5878
6019
|
);
|
|
5879
6020
|
}
|
|
5880
|
-
if (hasOwn(configRecord, "
|
|
6021
|
+
if (hasOwn(configRecord, "mode")) {
|
|
5881
6022
|
throw new Error(
|
|
5882
|
-
`Top-level "
|
|
6023
|
+
`Top-level "mode" config is no longer supported in ${source}. Use "cloud: true" to enable cloud mode.`
|
|
5883
6024
|
);
|
|
5884
6025
|
}
|
|
5885
|
-
|
|
5886
|
-
if (typeof remoteValue === "boolean") {
|
|
6026
|
+
if (hasOwn(configRecord, "remote")) {
|
|
5887
6027
|
throw new Error(
|
|
5888
|
-
`
|
|
6028
|
+
`Top-level "remote" config is no longer supported in ${source}. Use "cloud" options instead.`
|
|
5889
6029
|
);
|
|
5890
6030
|
}
|
|
5891
|
-
if (
|
|
6031
|
+
if (hasOwn(configRecord, "apiKey")) {
|
|
5892
6032
|
throw new Error(
|
|
5893
|
-
`
|
|
6033
|
+
`Top-level "apiKey" config is not supported in ${source}. Use "cloud.apiKey" instead.`
|
|
5894
6034
|
);
|
|
5895
6035
|
}
|
|
5896
6036
|
}
|
|
@@ -5936,20 +6076,20 @@ function parseNumber(value) {
|
|
|
5936
6076
|
if (!Number.isFinite(parsed)) return void 0;
|
|
5937
6077
|
return parsed;
|
|
5938
6078
|
}
|
|
5939
|
-
function
|
|
6079
|
+
function parseRuntimeMode(value, source) {
|
|
5940
6080
|
if (value == null) return void 0;
|
|
5941
6081
|
if (typeof value !== "string") {
|
|
5942
6082
|
throw new Error(
|
|
5943
|
-
`Invalid ${source} value "${String(value)}". Use "local" or "
|
|
6083
|
+
`Invalid ${source} value "${String(value)}". Use "local" or "cloud".`
|
|
5944
6084
|
);
|
|
5945
6085
|
}
|
|
5946
6086
|
const normalized = value.trim().toLowerCase();
|
|
5947
6087
|
if (!normalized) return void 0;
|
|
5948
|
-
if (normalized === "local" || normalized === "
|
|
6088
|
+
if (normalized === "local" || normalized === "cloud") {
|
|
5949
6089
|
return normalized;
|
|
5950
6090
|
}
|
|
5951
6091
|
throw new Error(
|
|
5952
|
-
`Invalid ${source} value "${value}". Use "local" or "
|
|
6092
|
+
`Invalid ${source} value "${value}". Use "local" or "cloud".`
|
|
5953
6093
|
);
|
|
5954
6094
|
}
|
|
5955
6095
|
function parseAuthScheme(value, source) {
|
|
@@ -5968,6 +6108,22 @@ function parseAuthScheme(value, source) {
|
|
|
5968
6108
|
`Invalid ${source} value "${value}". Use "api-key" or "bearer".`
|
|
5969
6109
|
);
|
|
5970
6110
|
}
|
|
6111
|
+
function parseCloudAnnounce(value, source) {
|
|
6112
|
+
if (value == null) return void 0;
|
|
6113
|
+
if (typeof value !== "string") {
|
|
6114
|
+
throw new Error(
|
|
6115
|
+
`Invalid ${source} value "${String(value)}". Use "always", "off", or "tty".`
|
|
6116
|
+
);
|
|
6117
|
+
}
|
|
6118
|
+
const normalized = value.trim().toLowerCase();
|
|
6119
|
+
if (!normalized) return void 0;
|
|
6120
|
+
if (normalized === "always" || normalized === "off" || normalized === "tty") {
|
|
6121
|
+
return normalized;
|
|
6122
|
+
}
|
|
6123
|
+
throw new Error(
|
|
6124
|
+
`Invalid ${source} value "${value}". Use "always", "off", or "tty".`
|
|
6125
|
+
);
|
|
6126
|
+
}
|
|
5971
6127
|
function resolveOpensteerApiKey() {
|
|
5972
6128
|
const value = process.env.OPENSTEER_API_KEY?.trim();
|
|
5973
6129
|
if (!value) return void 0;
|
|
@@ -5979,29 +6135,40 @@ function resolveOpensteerAuthScheme() {
|
|
|
5979
6135
|
"OPENSTEER_AUTH_SCHEME"
|
|
5980
6136
|
);
|
|
5981
6137
|
}
|
|
5982
|
-
function
|
|
6138
|
+
function normalizeCloudOptions(value) {
|
|
5983
6139
|
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
5984
6140
|
return void 0;
|
|
5985
6141
|
}
|
|
5986
6142
|
return value;
|
|
5987
6143
|
}
|
|
5988
|
-
function
|
|
5989
|
-
|
|
5990
|
-
if (
|
|
6144
|
+
function parseCloudEnabled(value, source) {
|
|
6145
|
+
if (value == null) return void 0;
|
|
6146
|
+
if (typeof value === "boolean") return value;
|
|
6147
|
+
if (typeof value === "object" && !Array.isArray(value)) return true;
|
|
6148
|
+
throw new Error(
|
|
6149
|
+
`Invalid ${source} value "${String(value)}". Use true, false, or a cloud options object.`
|
|
6150
|
+
);
|
|
6151
|
+
}
|
|
6152
|
+
function resolveCloudSelection(config) {
|
|
6153
|
+
const configCloud = parseCloudEnabled(config.cloud, "cloud");
|
|
6154
|
+
if (configCloud !== void 0) {
|
|
5991
6155
|
return {
|
|
5992
|
-
|
|
5993
|
-
source: "config.
|
|
6156
|
+
cloud: configCloud,
|
|
6157
|
+
source: "config.cloud"
|
|
5994
6158
|
};
|
|
5995
6159
|
}
|
|
5996
|
-
const envMode =
|
|
6160
|
+
const envMode = parseRuntimeMode(
|
|
6161
|
+
process.env.OPENSTEER_MODE,
|
|
6162
|
+
"OPENSTEER_MODE"
|
|
6163
|
+
);
|
|
5997
6164
|
if (envMode) {
|
|
5998
6165
|
return {
|
|
5999
|
-
|
|
6166
|
+
cloud: envMode === "cloud",
|
|
6000
6167
|
source: "env.OPENSTEER_MODE"
|
|
6001
6168
|
};
|
|
6002
6169
|
}
|
|
6003
6170
|
return {
|
|
6004
|
-
|
|
6171
|
+
cloud: false,
|
|
6005
6172
|
source: "default"
|
|
6006
6173
|
};
|
|
6007
6174
|
}
|
|
@@ -6017,11 +6184,11 @@ function resolveConfig(input = {}) {
|
|
|
6017
6184
|
);
|
|
6018
6185
|
}
|
|
6019
6186
|
assertNoLegacyAiConfig("Opensteer constructor config", input);
|
|
6020
|
-
|
|
6187
|
+
assertNoLegacyRuntimeConfig("Opensteer constructor config", input);
|
|
6021
6188
|
const rootDir = input.storage?.rootDir ?? DEFAULT_CONFIG.storage.rootDir ?? process.cwd();
|
|
6022
6189
|
const fileConfig = loadConfigFile(rootDir);
|
|
6023
6190
|
assertNoLegacyAiConfig(".opensteer/config.json", fileConfig);
|
|
6024
|
-
|
|
6191
|
+
assertNoLegacyRuntimeConfig(".opensteer/config.json", fileConfig);
|
|
6025
6192
|
const envConfig = {
|
|
6026
6193
|
browser: {
|
|
6027
6194
|
headless: parseBool(process.env.OPENSTEER_HEADLESS),
|
|
@@ -6039,28 +6206,38 @@ function resolveConfig(input = {}) {
|
|
|
6039
6206
|
const resolved = mergeDeep(mergedWithEnv, input);
|
|
6040
6207
|
const envApiKey = resolveOpensteerApiKey();
|
|
6041
6208
|
const envAuthScheme = resolveOpensteerAuthScheme();
|
|
6042
|
-
const
|
|
6209
|
+
const envCloudAnnounce = parseCloudAnnounce(
|
|
6210
|
+
process.env.OPENSTEER_REMOTE_ANNOUNCE,
|
|
6211
|
+
"OPENSTEER_REMOTE_ANNOUNCE"
|
|
6212
|
+
);
|
|
6213
|
+
const inputCloudOptions = normalizeCloudOptions(input.cloud);
|
|
6043
6214
|
const inputAuthScheme = parseAuthScheme(
|
|
6044
|
-
|
|
6045
|
-
"
|
|
6215
|
+
inputCloudOptions?.authScheme,
|
|
6216
|
+
"cloud.authScheme"
|
|
6217
|
+
);
|
|
6218
|
+
const inputCloudAnnounce = parseCloudAnnounce(
|
|
6219
|
+
inputCloudOptions?.announce,
|
|
6220
|
+
"cloud.announce"
|
|
6046
6221
|
);
|
|
6047
|
-
const
|
|
6048
|
-
|
|
6222
|
+
const inputHasCloudApiKey = Boolean(
|
|
6223
|
+
inputCloudOptions && Object.prototype.hasOwnProperty.call(inputCloudOptions, "apiKey")
|
|
6049
6224
|
);
|
|
6050
|
-
const
|
|
6051
|
-
|
|
6225
|
+
const cloudSelection = resolveCloudSelection({
|
|
6226
|
+
cloud: resolved.cloud
|
|
6052
6227
|
});
|
|
6053
|
-
if (
|
|
6054
|
-
const
|
|
6055
|
-
const authScheme = inputAuthScheme ?? envAuthScheme ?? parseAuthScheme(
|
|
6056
|
-
|
|
6057
|
-
|
|
6058
|
-
|
|
6228
|
+
if (cloudSelection.cloud) {
|
|
6229
|
+
const resolvedCloud = normalizeCloudOptions(resolved.cloud) ?? {};
|
|
6230
|
+
const authScheme = inputAuthScheme ?? envAuthScheme ?? parseAuthScheme(resolvedCloud.authScheme, "cloud.authScheme") ?? "api-key";
|
|
6231
|
+
const announce = inputCloudAnnounce ?? envCloudAnnounce ?? parseCloudAnnounce(resolvedCloud.announce, "cloud.announce") ?? "always";
|
|
6232
|
+
resolved.cloud = {
|
|
6233
|
+
...resolvedCloud,
|
|
6234
|
+
authScheme,
|
|
6235
|
+
announce
|
|
6059
6236
|
};
|
|
6060
6237
|
}
|
|
6061
|
-
if (envApiKey &&
|
|
6062
|
-
resolved.
|
|
6063
|
-
...
|
|
6238
|
+
if (envApiKey && cloudSelection.cloud && !inputHasCloudApiKey) {
|
|
6239
|
+
resolved.cloud = {
|
|
6240
|
+
...normalizeCloudOptions(resolved.cloud) ?? {},
|
|
6064
6241
|
apiKey: envApiKey
|
|
6065
6242
|
};
|
|
6066
6243
|
}
|
|
@@ -7456,22 +7633,35 @@ function clonePersistedExtractNode(node) {
|
|
|
7456
7633
|
return JSON.parse(JSON.stringify(node));
|
|
7457
7634
|
}
|
|
7458
7635
|
|
|
7459
|
-
// src/
|
|
7460
|
-
var
|
|
7461
|
-
|
|
7636
|
+
// src/cloud/runtime.ts
|
|
7637
|
+
var DEFAULT_CLOUD_BASE_URL = "https://remote.opensteer.com";
|
|
7638
|
+
var DEFAULT_CLOUD_APP_URL = "https://opensteer.com";
|
|
7639
|
+
function createCloudRuntimeState(key, baseUrl = resolveCloudBaseUrl(), authScheme = "api-key", appUrl = resolveCloudAppUrl()) {
|
|
7462
7640
|
return {
|
|
7463
|
-
sessionClient: new
|
|
7464
|
-
cdpClient: new
|
|
7641
|
+
sessionClient: new CloudSessionClient(baseUrl, key, authScheme),
|
|
7642
|
+
cdpClient: new CloudCdpClient(),
|
|
7643
|
+
appUrl: normalizeCloudAppUrl(appUrl),
|
|
7465
7644
|
actionClient: null,
|
|
7466
|
-
sessionId: null
|
|
7645
|
+
sessionId: null,
|
|
7646
|
+
localRunId: null,
|
|
7647
|
+
cloudSessionUrl: null
|
|
7467
7648
|
};
|
|
7468
7649
|
}
|
|
7469
|
-
function
|
|
7650
|
+
function resolveCloudBaseUrl() {
|
|
7470
7651
|
const value = process.env.OPENSTEER_BASE_URL?.trim();
|
|
7471
|
-
if (!value) return
|
|
7652
|
+
if (!value) return DEFAULT_CLOUD_BASE_URL;
|
|
7472
7653
|
return value.replace(/\/+$/, "");
|
|
7473
7654
|
}
|
|
7474
|
-
function
|
|
7655
|
+
function resolveCloudAppUrl() {
|
|
7656
|
+
const value = process.env.OPENSTEER_APP_URL?.trim();
|
|
7657
|
+
if (!value) return DEFAULT_CLOUD_APP_URL;
|
|
7658
|
+
return normalizeCloudAppUrl(value);
|
|
7659
|
+
}
|
|
7660
|
+
function normalizeCloudAppUrl(value) {
|
|
7661
|
+
if (!value) return null;
|
|
7662
|
+
return value.replace(/\/+$/, "");
|
|
7663
|
+
}
|
|
7664
|
+
function readCloudActionDescription(payload) {
|
|
7475
7665
|
const description = payload.description;
|
|
7476
7666
|
if (typeof description !== "string") return void 0;
|
|
7477
7667
|
const normalized = description.trim();
|
|
@@ -7479,7 +7669,7 @@ function readRemoteActionDescription(payload) {
|
|
|
7479
7669
|
}
|
|
7480
7670
|
|
|
7481
7671
|
// src/opensteer.ts
|
|
7482
|
-
var
|
|
7672
|
+
var CLOUD_INTERACTION_METHODS = /* @__PURE__ */ new Set([
|
|
7483
7673
|
"click",
|
|
7484
7674
|
"dblclick",
|
|
7485
7675
|
"rightclick",
|
|
@@ -7496,7 +7686,7 @@ var Opensteer = class _Opensteer {
|
|
|
7496
7686
|
namespace;
|
|
7497
7687
|
storage;
|
|
7498
7688
|
pool;
|
|
7499
|
-
|
|
7689
|
+
cloud;
|
|
7500
7690
|
browser = null;
|
|
7501
7691
|
pageRef = null;
|
|
7502
7692
|
contextRef = null;
|
|
@@ -7504,8 +7694,8 @@ var Opensteer = class _Opensteer {
|
|
|
7504
7694
|
snapshotCache = null;
|
|
7505
7695
|
constructor(config = {}) {
|
|
7506
7696
|
const resolved = resolveConfig(config);
|
|
7507
|
-
const
|
|
7508
|
-
|
|
7697
|
+
const cloudSelection = resolveCloudSelection({
|
|
7698
|
+
cloud: resolved.cloud
|
|
7509
7699
|
});
|
|
7510
7700
|
const model = resolved.model;
|
|
7511
7701
|
this.config = resolved;
|
|
@@ -7515,21 +7705,22 @@ var Opensteer = class _Opensteer {
|
|
|
7515
7705
|
this.namespace = resolveNamespace(resolved, rootDir);
|
|
7516
7706
|
this.storage = new LocalSelectorStorage(rootDir, this.namespace);
|
|
7517
7707
|
this.pool = new BrowserPool(resolved.browser || {});
|
|
7518
|
-
if (
|
|
7519
|
-
const
|
|
7520
|
-
const apiKey =
|
|
7708
|
+
if (cloudSelection.cloud) {
|
|
7709
|
+
const cloudConfig = resolved.cloud && typeof resolved.cloud === "object" ? resolved.cloud : void 0;
|
|
7710
|
+
const apiKey = cloudConfig?.apiKey?.trim();
|
|
7521
7711
|
if (!apiKey) {
|
|
7522
7712
|
throw new Error(
|
|
7523
|
-
"
|
|
7713
|
+
"Cloud mode requires a non-empty API key via cloud.apiKey or OPENSTEER_API_KEY."
|
|
7524
7714
|
);
|
|
7525
7715
|
}
|
|
7526
|
-
this.
|
|
7716
|
+
this.cloud = createCloudRuntimeState(
|
|
7527
7717
|
apiKey,
|
|
7528
|
-
|
|
7529
|
-
|
|
7718
|
+
cloudConfig?.baseUrl,
|
|
7719
|
+
cloudConfig?.authScheme,
|
|
7720
|
+
cloudConfig?.appUrl
|
|
7530
7721
|
);
|
|
7531
7722
|
} else {
|
|
7532
|
-
this.
|
|
7723
|
+
this.cloud = null;
|
|
7533
7724
|
}
|
|
7534
7725
|
}
|
|
7535
7726
|
createLazyResolveCallback(model) {
|
|
@@ -7567,32 +7758,32 @@ var Opensteer = class _Opensteer {
|
|
|
7567
7758
|
};
|
|
7568
7759
|
return extract;
|
|
7569
7760
|
}
|
|
7570
|
-
async
|
|
7571
|
-
const result = await this.
|
|
7761
|
+
async invokeCloudActionAndResetCache(method, args) {
|
|
7762
|
+
const result = await this.invokeCloudAction(method, args);
|
|
7572
7763
|
this.snapshotCache = null;
|
|
7573
7764
|
return result;
|
|
7574
7765
|
}
|
|
7575
|
-
async
|
|
7576
|
-
const actionClient = this.
|
|
7577
|
-
const sessionId = this.
|
|
7766
|
+
async invokeCloudAction(method, args) {
|
|
7767
|
+
const actionClient = this.cloud?.actionClient;
|
|
7768
|
+
const sessionId = this.cloud?.sessionId;
|
|
7578
7769
|
if (!actionClient || !sessionId) {
|
|
7579
|
-
throw
|
|
7770
|
+
throw cloudNotLaunchedError();
|
|
7580
7771
|
}
|
|
7581
7772
|
const payload = args && typeof args === "object" ? args : {};
|
|
7582
7773
|
try {
|
|
7583
7774
|
return await actionClient.request(method, payload);
|
|
7584
7775
|
} catch (err) {
|
|
7585
|
-
if (err instanceof
|
|
7776
|
+
if (err instanceof OpensteerCloudError && err.code === "CLOUD_ACTION_FAILED" && CLOUD_INTERACTION_METHODS.has(method)) {
|
|
7586
7777
|
const detailsRecord = err.details && typeof err.details === "object" ? err.details : null;
|
|
7587
|
-
const
|
|
7778
|
+
const cloudFailure = normalizeActionFailure(
|
|
7588
7779
|
detailsRecord?.actionFailure
|
|
7589
7780
|
);
|
|
7590
|
-
const failure =
|
|
7781
|
+
const failure = cloudFailure || classifyActionFailure({
|
|
7591
7782
|
action: method,
|
|
7592
7783
|
error: err,
|
|
7593
7784
|
fallbackMessage: defaultActionFailureMessage(method)
|
|
7594
7785
|
});
|
|
7595
|
-
const description =
|
|
7786
|
+
const description = readCloudActionDescription(payload);
|
|
7596
7787
|
throw this.buildActionError(
|
|
7597
7788
|
method,
|
|
7598
7789
|
description,
|
|
@@ -7633,8 +7824,36 @@ var Opensteer = class _Opensteer {
|
|
|
7633
7824
|
}
|
|
7634
7825
|
return this.contextRef;
|
|
7635
7826
|
}
|
|
7636
|
-
|
|
7637
|
-
return this.
|
|
7827
|
+
getCloudSessionId() {
|
|
7828
|
+
return this.cloud?.sessionId ?? null;
|
|
7829
|
+
}
|
|
7830
|
+
getCloudSessionUrl() {
|
|
7831
|
+
return this.cloud?.cloudSessionUrl ?? null;
|
|
7832
|
+
}
|
|
7833
|
+
announceCloudSession(args) {
|
|
7834
|
+
if (!this.shouldAnnounceCloudSession()) {
|
|
7835
|
+
return;
|
|
7836
|
+
}
|
|
7837
|
+
const fields = [
|
|
7838
|
+
`sessionId=${args.sessionId}`,
|
|
7839
|
+
`workspaceId=${args.workspaceId}`
|
|
7840
|
+
];
|
|
7841
|
+
if (args.cloudSessionUrl) {
|
|
7842
|
+
fields.push(`url=${args.cloudSessionUrl}`);
|
|
7843
|
+
}
|
|
7844
|
+
process.stderr.write(`[opensteer] cloud session ready ${fields.join(" ")}
|
|
7845
|
+
`);
|
|
7846
|
+
}
|
|
7847
|
+
shouldAnnounceCloudSession() {
|
|
7848
|
+
const cloudConfig = this.config.cloud && typeof this.config.cloud === "object" ? this.config.cloud : null;
|
|
7849
|
+
const announce = cloudConfig?.announce ?? "always";
|
|
7850
|
+
if (announce === "off") {
|
|
7851
|
+
return false;
|
|
7852
|
+
}
|
|
7853
|
+
if (announce === "tty") {
|
|
7854
|
+
return Boolean(process.stderr.isTTY);
|
|
7855
|
+
}
|
|
7856
|
+
return true;
|
|
7638
7857
|
}
|
|
7639
7858
|
async launch(options = {}) {
|
|
7640
7859
|
if (this.pageRef && !this.ownsBrowser) {
|
|
@@ -7645,22 +7864,29 @@ var Opensteer = class _Opensteer {
|
|
|
7645
7864
|
if (this.pageRef && this.ownsBrowser) {
|
|
7646
7865
|
return;
|
|
7647
7866
|
}
|
|
7648
|
-
if (this.
|
|
7867
|
+
if (this.cloud) {
|
|
7649
7868
|
let actionClient = null;
|
|
7650
7869
|
let browser = null;
|
|
7651
7870
|
let sessionId = null;
|
|
7871
|
+
let localRunId = null;
|
|
7652
7872
|
try {
|
|
7653
7873
|
try {
|
|
7654
|
-
await this.
|
|
7874
|
+
await this.syncLocalSelectorCacheToCloud();
|
|
7655
7875
|
} catch (error) {
|
|
7656
7876
|
if (this.config.debug) {
|
|
7657
7877
|
const message = error instanceof Error ? error.message : String(error);
|
|
7658
7878
|
console.warn(
|
|
7659
|
-
`[opensteer]
|
|
7879
|
+
`[opensteer] cloud selector cache sync failed: ${message}`
|
|
7660
7880
|
);
|
|
7661
7881
|
}
|
|
7662
7882
|
}
|
|
7663
|
-
|
|
7883
|
+
localRunId = this.cloud.localRunId || buildLocalRunId(this.namespace);
|
|
7884
|
+
this.cloud.localRunId = localRunId;
|
|
7885
|
+
const session2 = await this.cloud.sessionClient.create({
|
|
7886
|
+
cloudSessionContractVersion,
|
|
7887
|
+
sourceType: "local-cloud",
|
|
7888
|
+
clientSessionHint: this.namespace,
|
|
7889
|
+
localRunId,
|
|
7664
7890
|
name: this.namespace,
|
|
7665
7891
|
model: this.config.model,
|
|
7666
7892
|
launchContext: options.context || void 0
|
|
@@ -7671,7 +7897,7 @@ var Opensteer = class _Opensteer {
|
|
|
7671
7897
|
token: session2.actionToken,
|
|
7672
7898
|
sessionId: session2.sessionId
|
|
7673
7899
|
});
|
|
7674
|
-
const cdpConnection = await this.
|
|
7900
|
+
const cdpConnection = await this.cloud.cdpClient.connect({
|
|
7675
7901
|
wsUrl: session2.cdpWsUrl,
|
|
7676
7902
|
token: session2.cdpToken
|
|
7677
7903
|
});
|
|
@@ -7681,8 +7907,17 @@ var Opensteer = class _Opensteer {
|
|
|
7681
7907
|
this.pageRef = cdpConnection.page;
|
|
7682
7908
|
this.ownsBrowser = true;
|
|
7683
7909
|
this.snapshotCache = null;
|
|
7684
|
-
this.
|
|
7685
|
-
this.
|
|
7910
|
+
this.cloud.actionClient = actionClient;
|
|
7911
|
+
this.cloud.sessionId = sessionId;
|
|
7912
|
+
this.cloud.cloudSessionUrl = buildCloudSessionUrl(
|
|
7913
|
+
this.cloud.appUrl,
|
|
7914
|
+
session2.cloudSession.sessionId
|
|
7915
|
+
);
|
|
7916
|
+
this.announceCloudSession({
|
|
7917
|
+
sessionId: session2.sessionId,
|
|
7918
|
+
workspaceId: session2.cloudSession.workspaceId,
|
|
7919
|
+
cloudSessionUrl: this.cloud.cloudSessionUrl
|
|
7920
|
+
});
|
|
7686
7921
|
return;
|
|
7687
7922
|
} catch (error) {
|
|
7688
7923
|
if (actionClient) {
|
|
@@ -7692,8 +7927,9 @@ var Opensteer = class _Opensteer {
|
|
|
7692
7927
|
await browser.close().catch(() => void 0);
|
|
7693
7928
|
}
|
|
7694
7929
|
if (sessionId) {
|
|
7695
|
-
await this.
|
|
7930
|
+
await this.cloud.sessionClient.close(sessionId).catch(() => void 0);
|
|
7696
7931
|
}
|
|
7932
|
+
this.cloud.cloudSessionUrl = null;
|
|
7697
7933
|
throw error;
|
|
7698
7934
|
}
|
|
7699
7935
|
}
|
|
@@ -7711,13 +7947,13 @@ var Opensteer = class _Opensteer {
|
|
|
7711
7947
|
}
|
|
7712
7948
|
static from(page, config = {}) {
|
|
7713
7949
|
const resolvedConfig = resolveConfig(config);
|
|
7714
|
-
const
|
|
7715
|
-
|
|
7950
|
+
const cloudSelection = resolveCloudSelection({
|
|
7951
|
+
cloud: resolvedConfig.cloud
|
|
7716
7952
|
});
|
|
7717
|
-
if (
|
|
7718
|
-
throw
|
|
7953
|
+
if (cloudSelection.cloud) {
|
|
7954
|
+
throw cloudUnsupportedMethodError(
|
|
7719
7955
|
"Opensteer.from(page)",
|
|
7720
|
-
"Opensteer.from(page) is not supported in
|
|
7956
|
+
"Opensteer.from(page) is not supported in cloud mode."
|
|
7721
7957
|
);
|
|
7722
7958
|
}
|
|
7723
7959
|
const instance = new _Opensteer(config);
|
|
@@ -7730,12 +7966,14 @@ var Opensteer = class _Opensteer {
|
|
|
7730
7966
|
}
|
|
7731
7967
|
async close() {
|
|
7732
7968
|
this.snapshotCache = null;
|
|
7733
|
-
if (this.
|
|
7734
|
-
const actionClient = this.
|
|
7735
|
-
const sessionId = this.
|
|
7969
|
+
if (this.cloud) {
|
|
7970
|
+
const actionClient = this.cloud.actionClient;
|
|
7971
|
+
const sessionId = this.cloud.sessionId;
|
|
7736
7972
|
const browser = this.browser;
|
|
7737
|
-
this.
|
|
7738
|
-
this.
|
|
7973
|
+
this.cloud.actionClient = null;
|
|
7974
|
+
this.cloud.sessionId = null;
|
|
7975
|
+
this.cloud.localRunId = null;
|
|
7976
|
+
this.cloud.cloudSessionUrl = null;
|
|
7739
7977
|
this.browser = null;
|
|
7740
7978
|
this.pageRef = null;
|
|
7741
7979
|
this.contextRef = null;
|
|
@@ -7747,7 +7985,7 @@ var Opensteer = class _Opensteer {
|
|
|
7747
7985
|
await browser.close().catch(() => void 0);
|
|
7748
7986
|
}
|
|
7749
7987
|
if (sessionId) {
|
|
7750
|
-
await this.
|
|
7988
|
+
await this.cloud.sessionClient.close(sessionId).catch(() => void 0);
|
|
7751
7989
|
}
|
|
7752
7990
|
return;
|
|
7753
7991
|
}
|
|
@@ -7759,17 +7997,17 @@ var Opensteer = class _Opensteer {
|
|
|
7759
7997
|
this.contextRef = null;
|
|
7760
7998
|
this.ownsBrowser = false;
|
|
7761
7999
|
}
|
|
7762
|
-
async
|
|
7763
|
-
if (!this.
|
|
8000
|
+
async syncLocalSelectorCacheToCloud() {
|
|
8001
|
+
if (!this.cloud) return;
|
|
7764
8002
|
const entries = collectLocalSelectorCacheEntries(this.storage);
|
|
7765
8003
|
if (!entries.length) return;
|
|
7766
|
-
await this.
|
|
8004
|
+
await this.cloud.sessionClient.importSelectorCache({
|
|
7767
8005
|
entries
|
|
7768
8006
|
});
|
|
7769
8007
|
}
|
|
7770
8008
|
async goto(url, options) {
|
|
7771
|
-
if (this.
|
|
7772
|
-
await this.
|
|
8009
|
+
if (this.cloud) {
|
|
8010
|
+
await this.invokeCloudActionAndResetCache("goto", { url, options });
|
|
7773
8011
|
return;
|
|
7774
8012
|
}
|
|
7775
8013
|
const { waitUntil = "domcontentloaded", ...rest } = options ?? {};
|
|
@@ -7778,8 +8016,8 @@ var Opensteer = class _Opensteer {
|
|
|
7778
8016
|
this.snapshotCache = null;
|
|
7779
8017
|
}
|
|
7780
8018
|
async snapshot(options = {}) {
|
|
7781
|
-
if (this.
|
|
7782
|
-
return await this.
|
|
8019
|
+
if (this.cloud) {
|
|
8020
|
+
return await this.invokeCloudActionAndResetCache("snapshot", {
|
|
7783
8021
|
options
|
|
7784
8022
|
});
|
|
7785
8023
|
}
|
|
@@ -7788,8 +8026,8 @@ var Opensteer = class _Opensteer {
|
|
|
7788
8026
|
return prepared.cleanedHtml;
|
|
7789
8027
|
}
|
|
7790
8028
|
async state() {
|
|
7791
|
-
if (this.
|
|
7792
|
-
return await this.
|
|
8029
|
+
if (this.cloud) {
|
|
8030
|
+
return await this.invokeCloudAction("state", {});
|
|
7793
8031
|
}
|
|
7794
8032
|
const html = await this.snapshot({ mode: "action" });
|
|
7795
8033
|
return {
|
|
@@ -7799,8 +8037,8 @@ var Opensteer = class _Opensteer {
|
|
|
7799
8037
|
};
|
|
7800
8038
|
}
|
|
7801
8039
|
async screenshot(options = {}) {
|
|
7802
|
-
if (this.
|
|
7803
|
-
const b64 = await this.
|
|
8040
|
+
if (this.cloud) {
|
|
8041
|
+
const b64 = await this.invokeCloudAction(
|
|
7804
8042
|
"screenshot",
|
|
7805
8043
|
options
|
|
7806
8044
|
);
|
|
@@ -7814,8 +8052,8 @@ var Opensteer = class _Opensteer {
|
|
|
7814
8052
|
});
|
|
7815
8053
|
}
|
|
7816
8054
|
async click(options) {
|
|
7817
|
-
if (this.
|
|
7818
|
-
return await this.
|
|
8055
|
+
if (this.cloud) {
|
|
8056
|
+
return await this.invokeCloudActionAndResetCache(
|
|
7819
8057
|
"click",
|
|
7820
8058
|
options
|
|
7821
8059
|
);
|
|
@@ -7827,8 +8065,8 @@ var Opensteer = class _Opensteer {
|
|
|
7827
8065
|
});
|
|
7828
8066
|
}
|
|
7829
8067
|
async dblclick(options) {
|
|
7830
|
-
if (this.
|
|
7831
|
-
return await this.
|
|
8068
|
+
if (this.cloud) {
|
|
8069
|
+
return await this.invokeCloudActionAndResetCache(
|
|
7832
8070
|
"dblclick",
|
|
7833
8071
|
options
|
|
7834
8072
|
);
|
|
@@ -7840,8 +8078,8 @@ var Opensteer = class _Opensteer {
|
|
|
7840
8078
|
});
|
|
7841
8079
|
}
|
|
7842
8080
|
async rightclick(options) {
|
|
7843
|
-
if (this.
|
|
7844
|
-
return await this.
|
|
8081
|
+
if (this.cloud) {
|
|
8082
|
+
return await this.invokeCloudActionAndResetCache(
|
|
7845
8083
|
"rightclick",
|
|
7846
8084
|
options
|
|
7847
8085
|
);
|
|
@@ -7853,8 +8091,8 @@ var Opensteer = class _Opensteer {
|
|
|
7853
8091
|
});
|
|
7854
8092
|
}
|
|
7855
8093
|
async hover(options) {
|
|
7856
|
-
if (this.
|
|
7857
|
-
return await this.
|
|
8094
|
+
if (this.cloud) {
|
|
8095
|
+
return await this.invokeCloudActionAndResetCache(
|
|
7858
8096
|
"hover",
|
|
7859
8097
|
options
|
|
7860
8098
|
);
|
|
@@ -7952,8 +8190,8 @@ var Opensteer = class _Opensteer {
|
|
|
7952
8190
|
);
|
|
7953
8191
|
}
|
|
7954
8192
|
async input(options) {
|
|
7955
|
-
if (this.
|
|
7956
|
-
return await this.
|
|
8193
|
+
if (this.cloud) {
|
|
8194
|
+
return await this.invokeCloudActionAndResetCache(
|
|
7957
8195
|
"input",
|
|
7958
8196
|
options
|
|
7959
8197
|
);
|
|
@@ -8055,8 +8293,8 @@ var Opensteer = class _Opensteer {
|
|
|
8055
8293
|
);
|
|
8056
8294
|
}
|
|
8057
8295
|
async select(options) {
|
|
8058
|
-
if (this.
|
|
8059
|
-
return await this.
|
|
8296
|
+
if (this.cloud) {
|
|
8297
|
+
return await this.invokeCloudActionAndResetCache(
|
|
8060
8298
|
"select",
|
|
8061
8299
|
options
|
|
8062
8300
|
);
|
|
@@ -8165,8 +8403,8 @@ var Opensteer = class _Opensteer {
|
|
|
8165
8403
|
);
|
|
8166
8404
|
}
|
|
8167
8405
|
async scroll(options = {}) {
|
|
8168
|
-
if (this.
|
|
8169
|
-
return await this.
|
|
8406
|
+
if (this.cloud) {
|
|
8407
|
+
return await this.invokeCloudActionAndResetCache(
|
|
8170
8408
|
"scroll",
|
|
8171
8409
|
options
|
|
8172
8410
|
);
|
|
@@ -8267,14 +8505,14 @@ var Opensteer = class _Opensteer {
|
|
|
8267
8505
|
}
|
|
8268
8506
|
// --- Tab Management ---
|
|
8269
8507
|
async tabs() {
|
|
8270
|
-
if (this.
|
|
8271
|
-
return await this.
|
|
8508
|
+
if (this.cloud) {
|
|
8509
|
+
return await this.invokeCloudAction("tabs", {});
|
|
8272
8510
|
}
|
|
8273
8511
|
return listTabs(this.context, this.page);
|
|
8274
8512
|
}
|
|
8275
8513
|
async newTab(url) {
|
|
8276
|
-
if (this.
|
|
8277
|
-
return await this.
|
|
8514
|
+
if (this.cloud) {
|
|
8515
|
+
return await this.invokeCloudActionAndResetCache("newTab", {
|
|
8278
8516
|
url
|
|
8279
8517
|
});
|
|
8280
8518
|
}
|
|
@@ -8284,8 +8522,8 @@ var Opensteer = class _Opensteer {
|
|
|
8284
8522
|
return info;
|
|
8285
8523
|
}
|
|
8286
8524
|
async switchTab(index) {
|
|
8287
|
-
if (this.
|
|
8288
|
-
await this.
|
|
8525
|
+
if (this.cloud) {
|
|
8526
|
+
await this.invokeCloudActionAndResetCache("switchTab", { index });
|
|
8289
8527
|
return;
|
|
8290
8528
|
}
|
|
8291
8529
|
const page = await switchTab(this.context, index);
|
|
@@ -8293,8 +8531,8 @@ var Opensteer = class _Opensteer {
|
|
|
8293
8531
|
this.snapshotCache = null;
|
|
8294
8532
|
}
|
|
8295
8533
|
async closeTab(index) {
|
|
8296
|
-
if (this.
|
|
8297
|
-
await this.
|
|
8534
|
+
if (this.cloud) {
|
|
8535
|
+
await this.invokeCloudActionAndResetCache("closeTab", { index });
|
|
8298
8536
|
return;
|
|
8299
8537
|
}
|
|
8300
8538
|
const newPage = await closeTab(this.context, this.page, index);
|
|
@@ -8305,8 +8543,8 @@ var Opensteer = class _Opensteer {
|
|
|
8305
8543
|
}
|
|
8306
8544
|
// --- Cookie Management ---
|
|
8307
8545
|
async getCookies(url) {
|
|
8308
|
-
if (this.
|
|
8309
|
-
return await this.
|
|
8546
|
+
if (this.cloud) {
|
|
8547
|
+
return await this.invokeCloudAction(
|
|
8310
8548
|
"getCookies",
|
|
8311
8549
|
{ url }
|
|
8312
8550
|
);
|
|
@@ -8314,41 +8552,41 @@ var Opensteer = class _Opensteer {
|
|
|
8314
8552
|
return getCookies(this.context, url);
|
|
8315
8553
|
}
|
|
8316
8554
|
async setCookie(cookie) {
|
|
8317
|
-
if (this.
|
|
8318
|
-
await this.
|
|
8555
|
+
if (this.cloud) {
|
|
8556
|
+
await this.invokeCloudAction("setCookie", cookie);
|
|
8319
8557
|
return;
|
|
8320
8558
|
}
|
|
8321
8559
|
return setCookie(this.context, cookie);
|
|
8322
8560
|
}
|
|
8323
8561
|
async clearCookies() {
|
|
8324
|
-
if (this.
|
|
8325
|
-
await this.
|
|
8562
|
+
if (this.cloud) {
|
|
8563
|
+
await this.invokeCloudAction("clearCookies", {});
|
|
8326
8564
|
return;
|
|
8327
8565
|
}
|
|
8328
8566
|
return clearCookies(this.context);
|
|
8329
8567
|
}
|
|
8330
8568
|
async exportCookies(filePath, url) {
|
|
8331
|
-
if (this.
|
|
8332
|
-
throw
|
|
8569
|
+
if (this.cloud) {
|
|
8570
|
+
throw cloudUnsupportedMethodError(
|
|
8333
8571
|
"exportCookies",
|
|
8334
|
-
"exportCookies() is not supported in
|
|
8572
|
+
"exportCookies() is not supported in cloud mode because it depends on local filesystem paths."
|
|
8335
8573
|
);
|
|
8336
8574
|
}
|
|
8337
8575
|
return exportCookies(this.context, filePath, url);
|
|
8338
8576
|
}
|
|
8339
8577
|
async importCookies(filePath) {
|
|
8340
|
-
if (this.
|
|
8341
|
-
throw
|
|
8578
|
+
if (this.cloud) {
|
|
8579
|
+
throw cloudUnsupportedMethodError(
|
|
8342
8580
|
"importCookies",
|
|
8343
|
-
"importCookies() is not supported in
|
|
8581
|
+
"importCookies() is not supported in cloud mode because it depends on local filesystem paths."
|
|
8344
8582
|
);
|
|
8345
8583
|
}
|
|
8346
8584
|
return importCookies(this.context, filePath);
|
|
8347
8585
|
}
|
|
8348
8586
|
// --- Keyboard Input ---
|
|
8349
8587
|
async pressKey(key) {
|
|
8350
|
-
if (this.
|
|
8351
|
-
await this.
|
|
8588
|
+
if (this.cloud) {
|
|
8589
|
+
await this.invokeCloudActionAndResetCache("pressKey", { key });
|
|
8352
8590
|
return;
|
|
8353
8591
|
}
|
|
8354
8592
|
await this.runWithPostActionWait("pressKey", void 0, async () => {
|
|
@@ -8357,8 +8595,8 @@ var Opensteer = class _Opensteer {
|
|
|
8357
8595
|
this.snapshotCache = null;
|
|
8358
8596
|
}
|
|
8359
8597
|
async type(text) {
|
|
8360
|
-
if (this.
|
|
8361
|
-
await this.
|
|
8598
|
+
if (this.cloud) {
|
|
8599
|
+
await this.invokeCloudActionAndResetCache("type", { text });
|
|
8362
8600
|
return;
|
|
8363
8601
|
}
|
|
8364
8602
|
await this.runWithPostActionWait("type", void 0, async () => {
|
|
@@ -8368,8 +8606,8 @@ var Opensteer = class _Opensteer {
|
|
|
8368
8606
|
}
|
|
8369
8607
|
// --- Element Info ---
|
|
8370
8608
|
async getElementText(options) {
|
|
8371
|
-
if (this.
|
|
8372
|
-
return await this.
|
|
8609
|
+
if (this.cloud) {
|
|
8610
|
+
return await this.invokeCloudAction("getElementText", options);
|
|
8373
8611
|
}
|
|
8374
8612
|
return this.executeElementInfoAction(
|
|
8375
8613
|
"getElementText",
|
|
@@ -8382,8 +8620,8 @@ var Opensteer = class _Opensteer {
|
|
|
8382
8620
|
);
|
|
8383
8621
|
}
|
|
8384
8622
|
async getElementValue(options) {
|
|
8385
|
-
if (this.
|
|
8386
|
-
return await this.
|
|
8623
|
+
if (this.cloud) {
|
|
8624
|
+
return await this.invokeCloudAction(
|
|
8387
8625
|
"getElementValue",
|
|
8388
8626
|
options
|
|
8389
8627
|
);
|
|
@@ -8398,8 +8636,8 @@ var Opensteer = class _Opensteer {
|
|
|
8398
8636
|
);
|
|
8399
8637
|
}
|
|
8400
8638
|
async getElementAttributes(options) {
|
|
8401
|
-
if (this.
|
|
8402
|
-
return await this.
|
|
8639
|
+
if (this.cloud) {
|
|
8640
|
+
return await this.invokeCloudAction(
|
|
8403
8641
|
"getElementAttributes",
|
|
8404
8642
|
options
|
|
8405
8643
|
);
|
|
@@ -8420,8 +8658,8 @@ var Opensteer = class _Opensteer {
|
|
|
8420
8658
|
);
|
|
8421
8659
|
}
|
|
8422
8660
|
async getElementBoundingBox(options) {
|
|
8423
|
-
if (this.
|
|
8424
|
-
return await this.
|
|
8661
|
+
if (this.cloud) {
|
|
8662
|
+
return await this.invokeCloudAction(
|
|
8425
8663
|
"getElementBoundingBox",
|
|
8426
8664
|
options
|
|
8427
8665
|
);
|
|
@@ -8436,14 +8674,14 @@ var Opensteer = class _Opensteer {
|
|
|
8436
8674
|
);
|
|
8437
8675
|
}
|
|
8438
8676
|
async getHtml(selector) {
|
|
8439
|
-
if (this.
|
|
8440
|
-
return await this.
|
|
8677
|
+
if (this.cloud) {
|
|
8678
|
+
return await this.invokeCloudAction("getHtml", { selector });
|
|
8441
8679
|
}
|
|
8442
8680
|
return getPageHtml(this.page, selector);
|
|
8443
8681
|
}
|
|
8444
8682
|
async getTitle() {
|
|
8445
|
-
if (this.
|
|
8446
|
-
return await this.
|
|
8683
|
+
if (this.cloud) {
|
|
8684
|
+
return await this.invokeCloudAction("getTitle", {});
|
|
8447
8685
|
}
|
|
8448
8686
|
return getPageTitle(this.page);
|
|
8449
8687
|
}
|
|
@@ -8481,10 +8719,10 @@ var Opensteer = class _Opensteer {
|
|
|
8481
8719
|
}
|
|
8482
8720
|
// --- File Upload ---
|
|
8483
8721
|
async uploadFile(options) {
|
|
8484
|
-
if (this.
|
|
8485
|
-
throw
|
|
8722
|
+
if (this.cloud) {
|
|
8723
|
+
throw cloudUnsupportedMethodError(
|
|
8486
8724
|
"uploadFile",
|
|
8487
|
-
"uploadFile() is not supported in
|
|
8725
|
+
"uploadFile() is not supported in cloud mode because file paths must be accessible on the cloud runtime."
|
|
8488
8726
|
);
|
|
8489
8727
|
}
|
|
8490
8728
|
const storageKey = this.resolveStorageKey(options.description);
|
|
@@ -8586,15 +8824,15 @@ var Opensteer = class _Opensteer {
|
|
|
8586
8824
|
}
|
|
8587
8825
|
// --- Wait for Text ---
|
|
8588
8826
|
async waitForText(text, options) {
|
|
8589
|
-
if (this.
|
|
8590
|
-
await this.
|
|
8827
|
+
if (this.cloud) {
|
|
8828
|
+
await this.invokeCloudAction("waitForText", { text, options });
|
|
8591
8829
|
return;
|
|
8592
8830
|
}
|
|
8593
8831
|
await this.page.getByText(text).first().waitFor({ timeout: options?.timeout ?? 3e4 });
|
|
8594
8832
|
}
|
|
8595
8833
|
async extract(options) {
|
|
8596
|
-
if (this.
|
|
8597
|
-
return await this.
|
|
8834
|
+
if (this.cloud) {
|
|
8835
|
+
return await this.invokeCloudAction("extract", options);
|
|
8598
8836
|
}
|
|
8599
8837
|
const storageKey = this.resolveStorageKey(options.description);
|
|
8600
8838
|
const schemaHash = options.schema ? computeSchemaHash(options.schema) : null;
|
|
@@ -8646,8 +8884,8 @@ var Opensteer = class _Opensteer {
|
|
|
8646
8884
|
return inflateDataPathObject(data);
|
|
8647
8885
|
}
|
|
8648
8886
|
async extractFromPlan(options) {
|
|
8649
|
-
if (this.
|
|
8650
|
-
return await this.
|
|
8887
|
+
if (this.cloud) {
|
|
8888
|
+
return await this.invokeCloudAction(
|
|
8651
8889
|
"extractFromPlan",
|
|
8652
8890
|
options
|
|
8653
8891
|
);
|
|
@@ -8696,10 +8934,10 @@ var Opensteer = class _Opensteer {
|
|
|
8696
8934
|
return this.storage;
|
|
8697
8935
|
}
|
|
8698
8936
|
clearCache() {
|
|
8699
|
-
if (this.
|
|
8937
|
+
if (this.cloud) {
|
|
8700
8938
|
this.snapshotCache = null;
|
|
8701
|
-
if (!this.
|
|
8702
|
-
void this.
|
|
8939
|
+
if (!this.cloud.actionClient) return;
|
|
8940
|
+
void this.invokeCloudAction("clearCache", {});
|
|
8703
8941
|
return;
|
|
8704
8942
|
}
|
|
8705
8943
|
this.storage.clearNamespace();
|
|
@@ -9727,6 +9965,16 @@ function getScrollDelta2(options) {
|
|
|
9727
9965
|
return { x: 0, y: absoluteAmount };
|
|
9728
9966
|
}
|
|
9729
9967
|
}
|
|
9968
|
+
function buildLocalRunId(namespace) {
|
|
9969
|
+
const normalized = namespace.trim() || "default";
|
|
9970
|
+
return `${normalized}-${Date.now().toString(36)}-${randomUUID2().slice(0, 8)}`;
|
|
9971
|
+
}
|
|
9972
|
+
function buildCloudSessionUrl(appUrl, sessionId) {
|
|
9973
|
+
if (!appUrl) {
|
|
9974
|
+
return null;
|
|
9975
|
+
}
|
|
9976
|
+
return `${appUrl}/browser/${encodeURIComponent(sessionId)}`;
|
|
9977
|
+
}
|
|
9730
9978
|
|
|
9731
9979
|
export {
|
|
9732
9980
|
normalizeNamespace,
|
|
@@ -9789,12 +10037,13 @@ export {
|
|
|
9789
10037
|
getPageTitle,
|
|
9790
10038
|
performFileUpload,
|
|
9791
10039
|
OpensteerActionError,
|
|
9792
|
-
|
|
9793
|
-
|
|
9794
|
-
|
|
10040
|
+
cloudSessionContractVersion,
|
|
10041
|
+
OpensteerCloudError,
|
|
10042
|
+
cloudUnsupportedMethodError,
|
|
10043
|
+
cloudNotLaunchedError,
|
|
9795
10044
|
ActionWsClient,
|
|
9796
10045
|
collectLocalSelectorCacheEntries,
|
|
9797
|
-
|
|
9798
|
-
|
|
10046
|
+
CloudCdpClient,
|
|
10047
|
+
CloudSessionClient,
|
|
9799
10048
|
Opensteer
|
|
9800
10049
|
};
|