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.
@@ -4936,33 +4936,36 @@ var OpensteerActionError = class extends Error {
4936
4936
  }
4937
4937
  };
4938
4938
 
4939
- // src/remote/errors.ts
4940
- var OpensteerRemoteError = class extends Error {
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 = "OpensteerRemoteError";
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 remoteUnsupportedMethodError(method, message) {
4953
- return new OpensteerRemoteError(
4954
- "REMOTE_UNSUPPORTED_METHOD",
4955
- message || `${method} is not supported in remote mode.`
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 remoteNotLaunchedError() {
4959
- return new OpensteerRemoteError(
4960
- "REMOTE_SESSION_NOT_FOUND",
4961
- "Remote session is not connected. Call launch() first."
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/remote/action-ws-client.ts
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 OpensteerRemoteError(
4984
- "REMOTE_TRANSPORT_ERROR",
4985
- `Remote action websocket error: ${error.message}`
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 OpensteerRemoteError(
4993
- "REMOTE_SESSION_CLOSED",
4994
- "Remote action websocket closed."
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 OpensteerRemoteError(
5007
- "REMOTE_TRANSPORT_ERROR",
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 OpensteerRemoteError(
5018
- "REMOTE_SESSION_CLOSED",
5019
- "Remote action websocket is closed."
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 remote action request.";
5039
- throw new OpensteerRemoteError("REMOTE_TRANSPORT_ERROR", message);
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 OpensteerRemoteError(
5058
- "REMOTE_TRANSPORT_ERROR",
5059
- "Invalid remote action response payload."
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 OpensteerRemoteError(
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/remote/local-cache-sync.ts
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/remote/cdp-client.ts
5227
+ // src/cloud/cdp-client.ts
5225
5228
  import {
5226
5229
  chromium
5227
5230
  } from "playwright";
5228
- var RemoteCdpClient = class {
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 remote CDP endpoint.";
5236
- throw new OpensteerRemoteError("REMOTE_TRANSPORT_ERROR", message);
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 OpensteerRemoteError(
5242
- "REMOTE_INTERNAL",
5243
- "Remote browser returned no context."
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/remote/session-client.ts
5259
+ // src/cloud/session-client.ts
5257
5260
  var CACHE_IMPORT_BATCH_SIZE = 200;
5258
- var RemoteSessionClient = class {
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
- return await response.json();
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" ? toRemoteErrorCode(body.code) : "REMOTE_TRANSPORT_ERROR";
5362
- const message = typeof body?.error === "string" ? body.error : `Remote request failed with status ${response.status}.`;
5363
- return new OpensteerRemoteError(code, message, response.status, body?.details);
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 toRemoteErrorCode(code) {
5366
- if (code === "REMOTE_AUTH_FAILED" || code === "REMOTE_SESSION_NOT_FOUND" || code === "REMOTE_SESSION_CLOSED" || code === "REMOTE_UNSUPPORTED_METHOD" || code === "REMOTE_INVALID_REQUEST" || code === "REMOTE_MODEL_NOT_ALLOWED" || code === "REMOTE_ACTION_FAILED" || code === "REMOTE_INTERNAL" || code === "REMOTE_CAPACITY_EXHAUSTED" || code === "REMOTE_RUNTIME_UNAVAILABLE" || code === "REMOTE_RUNTIME_MISMATCH" || code === "REMOTE_SESSION_STALE" || code === "REMOTE_CONTROL_PLANE_ERROR") {
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 "REMOTE_TRANSPORT_ERROR";
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, isRemote: true };
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, isRemote: false };
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, isRemote: false };
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 assertNoLegacyModeConfig(source, config) {
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 "mode" instead.`
6018
+ `Legacy "runtime" config is no longer supported in ${source}. Use top-level "cloud" instead.`
5878
6019
  );
5879
6020
  }
5880
- if (hasOwn(configRecord, "apiKey")) {
6021
+ if (hasOwn(configRecord, "mode")) {
5881
6022
  throw new Error(
5882
- `Top-level "apiKey" config is not supported in ${source}. Use "remote.apiKey" instead.`
6023
+ `Top-level "mode" config is no longer supported in ${source}. Use "cloud: true" to enable cloud mode.`
5883
6024
  );
5884
6025
  }
5885
- const remoteValue = configRecord.remote;
5886
- if (typeof remoteValue === "boolean") {
6026
+ if (hasOwn(configRecord, "remote")) {
5887
6027
  throw new Error(
5888
- `Boolean "remote" config is no longer supported in ${source}. Use "mode: \\"remote\\"" with "remote" options.`
6028
+ `Top-level "remote" config is no longer supported in ${source}. Use "cloud" options instead.`
5889
6029
  );
5890
6030
  }
5891
- if (remoteValue && typeof remoteValue === "object" && !Array.isArray(remoteValue) && hasOwn(remoteValue, "key")) {
6031
+ if (hasOwn(configRecord, "apiKey")) {
5892
6032
  throw new Error(
5893
- `Legacy "remote.key" config is no longer supported in ${source}. Use "remote.apiKey" instead.`
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 parseMode(value, source) {
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 "remote".`
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 === "remote") {
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 "remote".`
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 normalizeRemoteOptions(value) {
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 resolveModeSelection(config) {
5989
- const configMode = parseMode(config.mode, "mode");
5990
- if (configMode) {
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
- mode: configMode,
5993
- source: "config.mode"
6156
+ cloud: configCloud,
6157
+ source: "config.cloud"
5994
6158
  };
5995
6159
  }
5996
- const envMode = parseMode(process.env.OPENSTEER_MODE, "OPENSTEER_MODE");
6160
+ const envMode = parseRuntimeMode(
6161
+ process.env.OPENSTEER_MODE,
6162
+ "OPENSTEER_MODE"
6163
+ );
5997
6164
  if (envMode) {
5998
6165
  return {
5999
- mode: envMode,
6166
+ cloud: envMode === "cloud",
6000
6167
  source: "env.OPENSTEER_MODE"
6001
6168
  };
6002
6169
  }
6003
6170
  return {
6004
- mode: "local",
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
- assertNoLegacyModeConfig("Opensteer constructor config", input);
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
- assertNoLegacyModeConfig(".opensteer/config.json", fileConfig);
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 inputRemoteOptions = normalizeRemoteOptions(input.remote);
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
- inputRemoteOptions?.authScheme,
6045
- "remote.authScheme"
6215
+ inputCloudOptions?.authScheme,
6216
+ "cloud.authScheme"
6217
+ );
6218
+ const inputCloudAnnounce = parseCloudAnnounce(
6219
+ inputCloudOptions?.announce,
6220
+ "cloud.announce"
6046
6221
  );
6047
- const inputHasRemoteApiKey = Boolean(
6048
- inputRemoteOptions && Object.prototype.hasOwnProperty.call(inputRemoteOptions, "apiKey")
6222
+ const inputHasCloudApiKey = Boolean(
6223
+ inputCloudOptions && Object.prototype.hasOwnProperty.call(inputCloudOptions, "apiKey")
6049
6224
  );
6050
- const modeSelection = resolveModeSelection({
6051
- mode: resolved.mode
6225
+ const cloudSelection = resolveCloudSelection({
6226
+ cloud: resolved.cloud
6052
6227
  });
6053
- if (modeSelection.mode === "remote") {
6054
- const resolvedRemote = normalizeRemoteOptions(resolved.remote) ?? {};
6055
- const authScheme = inputAuthScheme ?? envAuthScheme ?? parseAuthScheme(resolvedRemote.authScheme, "remote.authScheme") ?? "api-key";
6056
- resolved.remote = {
6057
- ...resolvedRemote,
6058
- authScheme
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 && modeSelection.mode === "remote" && !inputHasRemoteApiKey) {
6062
- resolved.remote = {
6063
- ...normalizeRemoteOptions(resolved.remote) ?? {},
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/remote/runtime.ts
7460
- var DEFAULT_REMOTE_BASE_URL = "https://remote.opensteer.com";
7461
- function createRemoteRuntimeState(key, baseUrl = resolveRemoteBaseUrl(), authScheme = "api-key") {
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 RemoteSessionClient(baseUrl, key, authScheme),
7464
- cdpClient: new RemoteCdpClient(),
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 resolveRemoteBaseUrl() {
7650
+ function resolveCloudBaseUrl() {
7470
7651
  const value = process.env.OPENSTEER_BASE_URL?.trim();
7471
- if (!value) return DEFAULT_REMOTE_BASE_URL;
7652
+ if (!value) return DEFAULT_CLOUD_BASE_URL;
7472
7653
  return value.replace(/\/+$/, "");
7473
7654
  }
7474
- function readRemoteActionDescription(payload) {
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 REMOTE_INTERACTION_METHODS = /* @__PURE__ */ new Set([
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
- remote;
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 modeSelection = resolveModeSelection({
7508
- mode: resolved.mode
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 (modeSelection.mode === "remote") {
7519
- const remoteConfig = resolved.remote && typeof resolved.remote === "object" ? resolved.remote : void 0;
7520
- const apiKey = remoteConfig?.apiKey?.trim();
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
- "Remote mode requires a non-empty API key via remote.apiKey or OPENSTEER_API_KEY."
7713
+ "Cloud mode requires a non-empty API key via cloud.apiKey or OPENSTEER_API_KEY."
7524
7714
  );
7525
7715
  }
7526
- this.remote = createRemoteRuntimeState(
7716
+ this.cloud = createCloudRuntimeState(
7527
7717
  apiKey,
7528
- remoteConfig?.baseUrl,
7529
- remoteConfig?.authScheme
7718
+ cloudConfig?.baseUrl,
7719
+ cloudConfig?.authScheme,
7720
+ cloudConfig?.appUrl
7530
7721
  );
7531
7722
  } else {
7532
- this.remote = null;
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 invokeRemoteActionAndResetCache(method, args) {
7571
- const result = await this.invokeRemoteAction(method, args);
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 invokeRemoteAction(method, args) {
7576
- const actionClient = this.remote?.actionClient;
7577
- const sessionId = this.remote?.sessionId;
7766
+ async invokeCloudAction(method, args) {
7767
+ const actionClient = this.cloud?.actionClient;
7768
+ const sessionId = this.cloud?.sessionId;
7578
7769
  if (!actionClient || !sessionId) {
7579
- throw remoteNotLaunchedError();
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 OpensteerRemoteError && err.code === "REMOTE_ACTION_FAILED" && REMOTE_INTERACTION_METHODS.has(method)) {
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 remoteFailure = normalizeActionFailure(
7778
+ const cloudFailure = normalizeActionFailure(
7588
7779
  detailsRecord?.actionFailure
7589
7780
  );
7590
- const failure = remoteFailure || classifyActionFailure({
7781
+ const failure = cloudFailure || classifyActionFailure({
7591
7782
  action: method,
7592
7783
  error: err,
7593
7784
  fallbackMessage: defaultActionFailureMessage(method)
7594
7785
  });
7595
- const description = readRemoteActionDescription(payload);
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
- getRemoteSessionId() {
7637
- return this.remote?.sessionId ?? null;
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.remote) {
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.syncLocalSelectorCacheToRemote();
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] remote selector cache sync failed: ${message}`
7879
+ `[opensteer] cloud selector cache sync failed: ${message}`
7660
7880
  );
7661
7881
  }
7662
7882
  }
7663
- const session2 = await this.remote.sessionClient.create({
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.remote.cdpClient.connect({
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.remote.actionClient = actionClient;
7685
- this.remote.sessionId = sessionId;
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.remote.sessionClient.close(sessionId).catch(() => void 0);
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 modeSelection = resolveModeSelection({
7715
- mode: resolvedConfig.mode
7950
+ const cloudSelection = resolveCloudSelection({
7951
+ cloud: resolvedConfig.cloud
7716
7952
  });
7717
- if (modeSelection.mode === "remote") {
7718
- throw remoteUnsupportedMethodError(
7953
+ if (cloudSelection.cloud) {
7954
+ throw cloudUnsupportedMethodError(
7719
7955
  "Opensteer.from(page)",
7720
- "Opensteer.from(page) is not supported in remote mode."
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.remote) {
7734
- const actionClient = this.remote.actionClient;
7735
- const sessionId = this.remote.sessionId;
7969
+ if (this.cloud) {
7970
+ const actionClient = this.cloud.actionClient;
7971
+ const sessionId = this.cloud.sessionId;
7736
7972
  const browser = this.browser;
7737
- this.remote.actionClient = null;
7738
- this.remote.sessionId = null;
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.remote.sessionClient.close(sessionId).catch(() => void 0);
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 syncLocalSelectorCacheToRemote() {
7763
- if (!this.remote) return;
8000
+ async syncLocalSelectorCacheToCloud() {
8001
+ if (!this.cloud) return;
7764
8002
  const entries = collectLocalSelectorCacheEntries(this.storage);
7765
8003
  if (!entries.length) return;
7766
- await this.remote.sessionClient.importSelectorCache({
8004
+ await this.cloud.sessionClient.importSelectorCache({
7767
8005
  entries
7768
8006
  });
7769
8007
  }
7770
8008
  async goto(url, options) {
7771
- if (this.remote) {
7772
- await this.invokeRemoteActionAndResetCache("goto", { url, options });
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.remote) {
7782
- return await this.invokeRemoteActionAndResetCache("snapshot", {
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.remote) {
7792
- return await this.invokeRemoteAction("state", {});
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.remote) {
7803
- const b64 = await this.invokeRemoteAction(
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.remote) {
7818
- return await this.invokeRemoteActionAndResetCache(
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.remote) {
7831
- return await this.invokeRemoteActionAndResetCache(
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.remote) {
7844
- return await this.invokeRemoteActionAndResetCache(
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.remote) {
7857
- return await this.invokeRemoteActionAndResetCache(
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.remote) {
7956
- return await this.invokeRemoteActionAndResetCache(
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.remote) {
8059
- return await this.invokeRemoteActionAndResetCache(
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.remote) {
8169
- return await this.invokeRemoteActionAndResetCache(
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.remote) {
8271
- return await this.invokeRemoteAction("tabs", {});
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.remote) {
8277
- return await this.invokeRemoteActionAndResetCache("newTab", {
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.remote) {
8288
- await this.invokeRemoteActionAndResetCache("switchTab", { index });
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.remote) {
8297
- await this.invokeRemoteActionAndResetCache("closeTab", { index });
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.remote) {
8309
- return await this.invokeRemoteAction(
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.remote) {
8318
- await this.invokeRemoteAction("setCookie", cookie);
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.remote) {
8325
- await this.invokeRemoteAction("clearCookies", {});
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.remote) {
8332
- throw remoteUnsupportedMethodError(
8569
+ if (this.cloud) {
8570
+ throw cloudUnsupportedMethodError(
8333
8571
  "exportCookies",
8334
- "exportCookies() is not supported in remote mode because it depends on local filesystem paths."
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.remote) {
8341
- throw remoteUnsupportedMethodError(
8578
+ if (this.cloud) {
8579
+ throw cloudUnsupportedMethodError(
8342
8580
  "importCookies",
8343
- "importCookies() is not supported in remote mode because it depends on local filesystem paths."
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.remote) {
8351
- await this.invokeRemoteActionAndResetCache("pressKey", { key });
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.remote) {
8361
- await this.invokeRemoteActionAndResetCache("type", { text });
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.remote) {
8372
- return await this.invokeRemoteAction("getElementText", options);
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.remote) {
8386
- return await this.invokeRemoteAction(
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.remote) {
8402
- return await this.invokeRemoteAction(
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.remote) {
8424
- return await this.invokeRemoteAction(
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.remote) {
8440
- return await this.invokeRemoteAction("getHtml", { selector });
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.remote) {
8446
- return await this.invokeRemoteAction("getTitle", {});
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.remote) {
8485
- throw remoteUnsupportedMethodError(
8722
+ if (this.cloud) {
8723
+ throw cloudUnsupportedMethodError(
8486
8724
  "uploadFile",
8487
- "uploadFile() is not supported in remote mode because file paths must be accessible on the remote server."
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.remote) {
8590
- await this.invokeRemoteAction("waitForText", { text, options });
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.remote) {
8597
- return await this.invokeRemoteAction("extract", options);
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.remote) {
8650
- return await this.invokeRemoteAction(
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.remote) {
8937
+ if (this.cloud) {
8700
8938
  this.snapshotCache = null;
8701
- if (!this.remote.actionClient) return;
8702
- void this.invokeRemoteAction("clearCache", {});
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
- OpensteerRemoteError,
9793
- remoteUnsupportedMethodError,
9794
- remoteNotLaunchedError,
10040
+ cloudSessionContractVersion,
10041
+ OpensteerCloudError,
10042
+ cloudUnsupportedMethodError,
10043
+ cloudNotLaunchedError,
9795
10044
  ActionWsClient,
9796
10045
  collectLocalSelectorCacheEntries,
9797
- RemoteCdpClient,
9798
- RemoteSessionClient,
10046
+ CloudCdpClient,
10047
+ CloudSessionClient,
9799
10048
  Opensteer
9800
10049
  };