wuying-agentbay-sdk 0.11.0 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -94,16 +94,22 @@ import {
94
94
  ModifyContextRequest,
95
95
  ModifyContextResponse,
96
96
  ModifyContextResponseBody,
97
+ PauseSessionAsyncRequest,
98
+ PauseSessionAsyncResponse,
99
+ PauseSessionAsyncResponseBody,
97
100
  ReleaseMcpSessionRequest,
98
101
  ReleaseMcpSessionResponse,
99
102
  ReleaseMcpSessionResponseBody,
103
+ ResumeSessionAsyncRequest,
104
+ ResumeSessionAsyncResponse,
105
+ ResumeSessionAsyncResponseBody,
100
106
  SetLabelRequest,
101
107
  SetLabelResponse,
102
108
  SetLabelResponseBody,
103
109
  SyncContextRequest,
104
110
  SyncContextResponse,
105
111
  SyncContextResponseBody
106
- } from "./chunk-E7QC5S76.mjs";
112
+ } from "./chunk-BVWUCG4J.mjs";
107
113
  import {
108
114
  __commonJS,
109
115
  __dirname,
@@ -186,14 +192,14 @@ var require_main = __commonJS({
186
192
  "node_modules/dotenv/lib/main.js"(exports, module) {
187
193
  "use strict";
188
194
  init_esm_shims();
189
- var fs6 = __require("fs");
190
- var path6 = __require("path");
195
+ var fs7 = __require("fs");
196
+ var path7 = __require("path");
191
197
  var os = __require("os");
192
198
  var crypto2 = __require("crypto");
193
199
  var packageJson = require_package();
194
200
  var version = packageJson.version;
195
201
  var LINE = /(?:^|^)\s*(?:export\s+)?([\w.-]+)(?:\s*=\s*?|:\s+?)(\s*'(?:\\'|[^'])*'|\s*"(?:\\"|[^"])*"|\s*`(?:\\`|[^`])*`|[^#\r\n]+)?\s*(?:#.*)?(?:$|$)/mg;
196
- function parse2(src) {
202
+ function parse3(src) {
197
203
  const obj = {};
198
204
  let lines = src.toString();
199
205
  lines = lines.replace(/\r\n?/mg, "\n");
@@ -212,7 +218,7 @@ var require_main = __commonJS({
212
218
  }
213
219
  return obj;
214
220
  }
215
- __name(parse2, "parse");
221
+ __name(parse3, "parse");
216
222
  function _parseVault(options) {
217
223
  options = options || {};
218
224
  const vaultPath = _vaultPath(options);
@@ -302,7 +308,7 @@ var require_main = __commonJS({
302
308
  if (options && options.path && options.path.length > 0) {
303
309
  if (Array.isArray(options.path)) {
304
310
  for (const filepath of options.path) {
305
- if (fs6.existsSync(filepath)) {
311
+ if (fs7.existsSync(filepath)) {
306
312
  possibleVaultPath = filepath.endsWith(".vault") ? filepath : `${filepath}.vault`;
307
313
  }
308
314
  }
@@ -310,16 +316,16 @@ var require_main = __commonJS({
310
316
  possibleVaultPath = options.path.endsWith(".vault") ? options.path : `${options.path}.vault`;
311
317
  }
312
318
  } else {
313
- possibleVaultPath = path6.resolve(process.cwd(), ".env.vault");
319
+ possibleVaultPath = path7.resolve(process.cwd(), ".env.vault");
314
320
  }
315
- if (fs6.existsSync(possibleVaultPath)) {
321
+ if (fs7.existsSync(possibleVaultPath)) {
316
322
  return possibleVaultPath;
317
323
  }
318
324
  return null;
319
325
  }
320
326
  __name(_vaultPath, "_vaultPath");
321
327
  function _resolveHome(envPath) {
322
- return envPath[0] === "~" ? path6.join(os.homedir(), envPath.slice(1)) : envPath;
328
+ return envPath[0] === "~" ? path7.join(os.homedir(), envPath.slice(1)) : envPath;
323
329
  }
324
330
  __name(_resolveHome, "_resolveHome");
325
331
  function _configVault(options) {
@@ -338,7 +344,7 @@ var require_main = __commonJS({
338
344
  }
339
345
  __name(_configVault, "_configVault");
340
346
  function configDotenv(options) {
341
- const dotenvPath = path6.resolve(process.cwd(), ".env");
347
+ const dotenvPath = path7.resolve(process.cwd(), ".env");
342
348
  let encoding = "utf8";
343
349
  const debug = Boolean(options && options.debug);
344
350
  const quiet = options && "quiet" in options ? options.quiet : true;
@@ -362,13 +368,13 @@ var require_main = __commonJS({
362
368
  }
363
369
  let lastError;
364
370
  const parsedAll = {};
365
- for (const path7 of optionPaths) {
371
+ for (const path8 of optionPaths) {
366
372
  try {
367
- const parsed = DotenvModule.parse(fs6.readFileSync(path7, { encoding }));
373
+ const parsed = DotenvModule.parse(fs7.readFileSync(path8, { encoding }));
368
374
  DotenvModule.populate(parsedAll, parsed, options);
369
375
  } catch (e) {
370
376
  if (debug) {
371
- _debug(`Failed to load ${path7} ${e.message}`);
377
+ _debug(`Failed to load ${path8} ${e.message}`);
372
378
  }
373
379
  lastError = e;
374
380
  }
@@ -383,7 +389,7 @@ var require_main = __commonJS({
383
389
  const shortPaths = [];
384
390
  for (const filePath of optionPaths) {
385
391
  try {
386
- const relative = path6.relative(process.cwd(), filePath);
392
+ const relative = path7.relative(process.cwd(), filePath);
387
393
  shortPaths.push(relative);
388
394
  } catch (e) {
389
395
  if (debug) {
@@ -473,7 +479,7 @@ var require_main = __commonJS({
473
479
  _parseVault,
474
480
  config,
475
481
  decrypt,
476
- parse: parse2,
482
+ parse: parse3,
477
483
  populate
478
484
  };
479
485
  module.exports.configDotenv = DotenvModule.configDotenv;
@@ -553,7 +559,7 @@ function getVersionFromPackageJson() {
553
559
  }
554
560
  } catch (error) {
555
561
  }
556
- return "0.9.4";
562
+ return "0.12.0";
557
563
  }
558
564
  __name(getVersionFromPackageJson, "getVersionFromPackageJson");
559
565
  function isReleaseBuild() {
@@ -581,9 +587,9 @@ init_esm_shims();
581
587
  })();
582
588
 
583
589
  // src/agent-bay.ts
584
- var dotenv = __toESM(require_main());
585
- import * as fs4 from "fs";
586
- import * as path4 from "path";
590
+ var dotenv2 = __toESM(require_main());
591
+ import * as fs5 from "fs";
592
+ import * as path5 from "path";
587
593
 
588
594
  // src/api/index.ts
589
595
  init_esm_shims();
@@ -1059,6 +1065,96 @@ var _Client = class _Client extends (OpenApi.default || OpenApi) {
1059
1065
  const runtime = new $dara.RuntimeOptions({});
1060
1066
  return await this.getSessionWithOptions(request, runtime);
1061
1067
  }
1068
+ /**
1069
+ * Pause session async
1070
+ *
1071
+ * @param request - PauseSessionAsyncRequest
1072
+ * @param runtime - runtime options for this request RuntimeOptions
1073
+ * @returns PauseSessionAsyncResponse
1074
+ */
1075
+ async pauseSessionAsyncWithOptions(request, runtime) {
1076
+ request.validate();
1077
+ const body = {};
1078
+ if (!$dara.isNull(request.authorization)) {
1079
+ body["Authorization"] = request.authorization;
1080
+ }
1081
+ if (!$dara.isNull(request.sessionId)) {
1082
+ body["SessionId"] = request.sessionId;
1083
+ }
1084
+ const req = new $OpenApiUtil.OpenApiRequest({
1085
+ body: OpenApiUtil.parseToMap(body)
1086
+ });
1087
+ const params = new $OpenApiUtil.Params({
1088
+ action: "PauseSessionAsync",
1089
+ version: "2025-05-06",
1090
+ protocol: "HTTPS",
1091
+ pathname: "/",
1092
+ method: "POST",
1093
+ authType: "Anonymous",
1094
+ style: "RPC",
1095
+ reqBodyType: "formData",
1096
+ bodyType: "json"
1097
+ });
1098
+ return $dara.cast(
1099
+ await this.callApi(params, req, runtime),
1100
+ new PauseSessionAsyncResponse({})
1101
+ );
1102
+ }
1103
+ /**
1104
+ * Pause session async
1105
+ *
1106
+ * @param request - PauseSessionAsyncRequest
1107
+ * @returns PauseSessionAsyncResponse
1108
+ */
1109
+ async pauseSessionAsync(request) {
1110
+ const runtime = new $dara.RuntimeOptions({});
1111
+ return await this.pauseSessionAsyncWithOptions(request, runtime);
1112
+ }
1113
+ /**
1114
+ * Resume session async
1115
+ *
1116
+ * @param request - ResumeSessionAsyncRequest
1117
+ * @param runtime - runtime options for this request RuntimeOptions
1118
+ * @returns ResumeSessionAsyncResponse
1119
+ */
1120
+ async resumeSessionAsyncWithOptions(request, runtime) {
1121
+ request.validate();
1122
+ const body = {};
1123
+ if (!$dara.isNull(request.authorization)) {
1124
+ body["Authorization"] = request.authorization;
1125
+ }
1126
+ if (!$dara.isNull(request.sessionId)) {
1127
+ body["SessionId"] = request.sessionId;
1128
+ }
1129
+ const req = new $OpenApiUtil.OpenApiRequest({
1130
+ body: OpenApiUtil.parseToMap(body)
1131
+ });
1132
+ const params = new $OpenApiUtil.Params({
1133
+ action: "ResumeSessionAsync",
1134
+ version: "2025-05-06",
1135
+ protocol: "HTTPS",
1136
+ pathname: "/",
1137
+ method: "POST",
1138
+ authType: "Anonymous",
1139
+ style: "RPC",
1140
+ reqBodyType: "formData",
1141
+ bodyType: "json"
1142
+ });
1143
+ return $dara.cast(
1144
+ await this.callApi(params, req, runtime),
1145
+ new ResumeSessionAsyncResponse({})
1146
+ );
1147
+ }
1148
+ /**
1149
+ * Resume session async
1150
+ *
1151
+ * @param request - ResumeSessionAsyncRequest
1152
+ * @returns ResumeSessionAsyncResponse
1153
+ */
1154
+ async resumeSessionAsync(request) {
1155
+ const runtime = new $dara.RuntimeOptions({});
1156
+ return await this.resumeSessionAsyncWithOptions(request, runtime);
1157
+ }
1062
1158
  /**
1063
1159
  * Get forwarding link for specific port
1064
1160
  *
@@ -1904,6 +2000,70 @@ var _Client = class _Client extends (OpenApi.default || OpenApi) {
1904
2000
  __name(_Client, "Client");
1905
2001
  var Client = _Client;
1906
2002
 
2003
+ // src/config.ts
2004
+ init_esm_shims();
2005
+ var dotenv = __toESM(require_main());
2006
+ import * as fs2 from "fs";
2007
+ import * as path2 from "path";
2008
+ var BROWSER_RECORD_PATH = "/home/guest/record";
2009
+ function findDotEnvFile(startPath) {
2010
+ const currentPath = startPath ? path2.resolve(startPath) : process.cwd();
2011
+ let searchPath = currentPath;
2012
+ while (searchPath !== path2.dirname(searchPath)) {
2013
+ const envFile = path2.join(searchPath, ".env");
2014
+ if (fs2.existsSync(envFile)) {
2015
+ return envFile;
2016
+ }
2017
+ const gitDir = path2.join(searchPath, ".git");
2018
+ if (fs2.existsSync(gitDir)) {
2019
+ }
2020
+ searchPath = path2.dirname(searchPath);
2021
+ }
2022
+ const rootEnv = path2.join(searchPath, ".env");
2023
+ if (fs2.existsSync(rootEnv)) {
2024
+ return rootEnv;
2025
+ }
2026
+ return null;
2027
+ }
2028
+ __name(findDotEnvFile, "findDotEnvFile");
2029
+ function loadDotEnvWithFallback(customEnvPath) {
2030
+ if (customEnvPath) {
2031
+ if (fs2.existsSync(customEnvPath)) {
2032
+ try {
2033
+ const envConfig = dotenv.parse(fs2.readFileSync(customEnvPath));
2034
+ for (const k in envConfig) {
2035
+ if (!process.env.hasOwnProperty(k)) {
2036
+ process.env[k] = envConfig[k];
2037
+ }
2038
+ }
2039
+ return;
2040
+ } catch (error) {
2041
+ }
2042
+ }
2043
+ }
2044
+ const envFile = findDotEnvFile();
2045
+ if (envFile) {
2046
+ try {
2047
+ const envConfig = dotenv.parse(fs2.readFileSync(envFile));
2048
+ for (const k in envConfig) {
2049
+ if (!process.env.hasOwnProperty(k)) {
2050
+ process.env[k] = envConfig[k];
2051
+ }
2052
+ }
2053
+ } catch (error) {
2054
+ }
2055
+ }
2056
+ }
2057
+ __name(loadDotEnvWithFallback, "loadDotEnvWithFallback");
2058
+ var dotEnvLoaded = false;
2059
+ if (!dotEnvLoaded) {
2060
+ try {
2061
+ loadDotEnvWithFallback();
2062
+ dotEnvLoaded = true;
2063
+ } catch (error) {
2064
+ }
2065
+ }
2066
+
1907
2067
  // src/context.ts
1908
2068
  init_esm_shims();
1909
2069
 
@@ -1978,8 +2138,8 @@ var BrowserError = _BrowserError;
1978
2138
 
1979
2139
  // src/utils/logger.ts
1980
2140
  init_esm_shims();
1981
- import * as fs2 from "fs";
1982
- import * as path2 from "path";
2141
+ import * as fs3 from "fs";
2142
+ import * as path3 from "path";
1983
2143
  var LOG_LEVEL_VALUES = {
1984
2144
  DEBUG: 0,
1985
2145
  INFO: 1,
@@ -2158,17 +2318,17 @@ function writeToFile(message) {
2158
2318
  return;
2159
2319
  }
2160
2320
  try {
2161
- if (fs2.existsSync(logFilePath)) {
2162
- const stats = fs2.statSync(logFilePath);
2321
+ if (fs3.existsSync(logFilePath)) {
2322
+ const stats = fs3.statSync(logFilePath);
2163
2323
  if (stats.size >= logFileMaxSize) {
2164
2324
  const rotatedPath = `${logFilePath}.1`;
2165
- if (fs2.existsSync(rotatedPath)) {
2166
- fs2.unlinkSync(rotatedPath);
2325
+ if (fs3.existsSync(rotatedPath)) {
2326
+ fs3.unlinkSync(rotatedPath);
2167
2327
  }
2168
- fs2.renameSync(logFilePath, rotatedPath);
2328
+ fs3.renameSync(logFilePath, rotatedPath);
2169
2329
  }
2170
2330
  }
2171
- fs2.appendFileSync(logFilePath, message + "\n", "utf8");
2331
+ fs3.appendFileSync(logFilePath, message + "\n", "utf8");
2172
2332
  } catch (error) {
2173
2333
  if (consoleLoggingEnabled) {
2174
2334
  process.stderr.write(`Failed to write to log file: ${error}
@@ -2185,9 +2345,9 @@ function setupLogger(config) {
2185
2345
  if (config.logFile) {
2186
2346
  logFilePath = config.logFile;
2187
2347
  fileLoggingEnabled = true;
2188
- const dir = path2.dirname(logFilePath);
2189
- if (!fs2.existsSync(dir)) {
2190
- fs2.mkdirSync(dir, { recursive: true });
2348
+ const dir = path3.dirname(logFilePath);
2349
+ if (!fs3.existsSync(dir)) {
2350
+ fs3.mkdirSync(dir, { recursive: true });
2191
2351
  }
2192
2352
  if (config.maxFileSize) {
2193
2353
  logFileMaxSize = parseFileSize(config.maxFileSize);
@@ -3223,7 +3383,7 @@ var _ContextService = class _ContextService {
3223
3383
  const maxAttempts = Math.floor(timeout / pollInterval);
3224
3384
  let attempt = 0;
3225
3385
  while (attempt < maxAttempts) {
3226
- await new Promise((resolve2) => setTimeout(resolve2, pollInterval * 1e3));
3386
+ await new Promise((resolve3) => setTimeout(resolve3, pollInterval * 1e3));
3227
3387
  attempt++;
3228
3388
  const statusResult = await this.getClearStatus(contextId);
3229
3389
  if (!statusResult.success) {
@@ -3313,8 +3473,8 @@ var _ExtractPolicyClass = class _ExtractPolicyClass {
3313
3473
  __name(_ExtractPolicyClass, "ExtractPolicyClass");
3314
3474
  var ExtractPolicyClass = _ExtractPolicyClass;
3315
3475
  var _WhiteListValidator = class _WhiteListValidator {
3316
- static containsWildcard(path6) {
3317
- return /[*?\[\]]/.test(path6);
3476
+ static containsWildcard(path7) {
3477
+ return /[*?\[\]]/.test(path7);
3318
3478
  }
3319
3479
  static validate(whitelist) {
3320
3480
  if (this.containsWildcard(whitelist.path)) {
@@ -3389,12 +3549,12 @@ var _SyncPolicyImpl = class _SyncPolicyImpl {
3389
3549
  __name(_SyncPolicyImpl, "SyncPolicyImpl");
3390
3550
  var SyncPolicyImpl = _SyncPolicyImpl;
3391
3551
  var _ContextSync = class _ContextSync {
3392
- constructor(contextId, path6, policy) {
3552
+ constructor(contextId, path7, policy) {
3393
3553
  if (policy) {
3394
3554
  validateSyncPolicy(policy);
3395
3555
  }
3396
3556
  this.contextId = contextId;
3397
- this.path = path6;
3557
+ this.path = path7;
3398
3558
  this.policy = policy;
3399
3559
  }
3400
3560
  // WithPolicy sets the policy and returns the context sync for chaining
@@ -3495,9 +3655,9 @@ function validateSyncPolicy(policy) {
3495
3655
  );
3496
3656
  }
3497
3657
  if (policy.recyclePolicy.paths) {
3498
- for (const path6 of policy.recyclePolicy.paths) {
3499
- if (path6 && path6.trim() !== "") {
3500
- const tempWhiteList = { path: path6 };
3658
+ for (const path7 of policy.recyclePolicy.paths) {
3659
+ if (path7 && path7.trim() !== "") {
3660
+ const tempWhiteList = { path: path7 };
3501
3661
  WhiteListValidator.validate(tempWhiteList);
3502
3662
  }
3503
3663
  }
@@ -3509,11 +3669,11 @@ function newSyncPolicyWithDefaults(policy) {
3509
3669
  return new SyncPolicyImpl(policy).toJSON();
3510
3670
  }
3511
3671
  __name(newSyncPolicyWithDefaults, "newSyncPolicyWithDefaults");
3512
- function newContextSync(contextId, path6, policy) {
3672
+ function newContextSync(contextId, path7, policy) {
3513
3673
  if (policy) {
3514
3674
  validateSyncPolicy(policy);
3515
3675
  }
3516
- return new ContextSync(contextId, path6, policy);
3676
+ return new ContextSync(contextId, path7, policy);
3517
3677
  }
3518
3678
  __name(newContextSync, "newContextSync");
3519
3679
 
@@ -3645,7 +3805,7 @@ var _Agent = class _Agent {
3645
3805
  };
3646
3806
  }
3647
3807
  logDebug(`Task ${taskId} is still running, please wait for a while.`);
3648
- await new Promise((resolve2) => setTimeout(resolve2, 3e3));
3808
+ await new Promise((resolve3) => setTimeout(resolve3, 3e3));
3649
3809
  triedTime++;
3650
3810
  }
3651
3811
  return {
@@ -4582,8 +4742,8 @@ var _BrowserFingerprintGenerator = class _BrowserFingerprintGenerator {
4582
4742
  async saveToFile(jsonData, filename) {
4583
4743
  try {
4584
4744
  if (typeof __require !== "undefined") {
4585
- const fs6 = __require("fs");
4586
- fs6.writeFileSync(filename, jsonData, "utf8");
4745
+ const fs7 = __require("fs");
4746
+ fs7.writeFileSync(filename, jsonData, "utf8");
4587
4747
  console.log(`Fingerprint data saved to ${filename}`);
4588
4748
  return true;
4589
4749
  } else {
@@ -5032,7 +5192,7 @@ var _Browser = class _Browser {
5032
5192
  logDebug(`VPC mode, endpoint_router_port: ${this.session.httpPort}`);
5033
5193
  this._endpointUrl = `ws://${this.session.networkInterfaceIp}:${this.session.httpPort}`;
5034
5194
  } else {
5035
- const { GetCdpLinkRequest: GetCdpLinkRequest2 } = await import("./model-ZFTLKEMC.mjs");
5195
+ const { GetCdpLinkRequest: GetCdpLinkRequest2 } = await import("./model-LGWQJWKQ.mjs");
5036
5196
  const request = new GetCdpLinkRequest2({
5037
5197
  authorization: `Bearer ${this.session.getAPIKey()}`,
5038
5198
  sessionId: this.session.sessionId
@@ -6544,7 +6704,7 @@ var _ContextManager = class _ContextManager {
6544
6704
  * }
6545
6705
  * ```
6546
6706
  */
6547
- async infoWithParams(contextId, path6, taskType) {
6707
+ async infoWithParams(contextId, path7, taskType) {
6548
6708
  const request = new GetContextInfoRequest({
6549
6709
  authorization: `Bearer ${this.session.getAPIKey()}`,
6550
6710
  sessionId: this.session.getSessionId()
@@ -6552,8 +6712,8 @@ var _ContextManager = class _ContextManager {
6552
6712
  if (contextId) {
6553
6713
  request.contextId = contextId;
6554
6714
  }
6555
- if (path6) {
6556
- request.path = path6;
6715
+ if (path7) {
6716
+ request.path = path7;
6557
6717
  }
6558
6718
  if (taskType) {
6559
6719
  request.taskType = taskType;
@@ -6628,16 +6788,31 @@ var _ContextManager = class _ContextManager {
6628
6788
  /**
6629
6789
  * Synchronizes a context with the session. Supports both async and callback modes.
6630
6790
  *
6631
- * @param contextId - Optional context ID to synchronize
6632
- * @param path - Optional path where the context should be mounted
6791
+ * @param contextId - Optional context ID to synchronize. If provided, `path` must also be provided.
6792
+ * @param path - Optional path where the context should be mounted. If provided, `contextId` must also be provided.
6633
6793
  * @param mode - Optional synchronization mode (e.g., "upload", "download")
6634
6794
  * @param callback - Optional callback function. If provided, runs in background and calls callback when complete
6635
6795
  * @param maxRetries - Maximum number of retries for polling completion status (default: 150)
6636
6796
  * @param retryInterval - Milliseconds to wait between retries (default: 1500)
6637
6797
  * @returns Promise resolving to ContextSyncResult with success status and request ID
6638
6798
  * @throws Error if the API call fails
6799
+ * @throws Error if `contextId` or `path` is provided without the other parameter.
6800
+ * Both must be provided together, or both must be omitted.
6801
+ *
6802
+ * @example
6803
+ * Sync all contexts (no parameters):
6804
+ * ```typescript
6805
+ * const agentBay = new AgentBay({ apiKey: 'your_api_key' });
6806
+ * const result = await agentBay.create();
6807
+ * if (result.success) {
6808
+ * const syncResult = await result.session.context.sync();
6809
+ * console.log(`Sync: ${syncResult.success}`);
6810
+ * await result.session.delete();
6811
+ * }
6812
+ * ```
6639
6813
  *
6640
6814
  * @example
6815
+ * Sync specific context with path:
6641
6816
  * ```typescript
6642
6817
  * const agentBay = new AgentBay({ apiKey: 'your_api_key' });
6643
6818
  * const result = await agentBay.create();
@@ -6649,7 +6824,14 @@ var _ContextManager = class _ContextManager {
6649
6824
  * }
6650
6825
  * ```
6651
6826
  */
6652
- async sync(contextId, path6, mode, callback, maxRetries = 150, retryInterval = 1500) {
6827
+ async sync(contextId, path7, mode, callback, maxRetries = 150, retryInterval = 1500) {
6828
+ const hasContextId = contextId !== void 0 && contextId.trim() !== "";
6829
+ const hasPath = path7 !== void 0 && path7.trim() !== "";
6830
+ if (hasContextId !== hasPath) {
6831
+ throw new Error(
6832
+ "contextId and path must be provided together or both omitted. If you want to sync a specific context, both contextId and path are required. If you want to sync all contexts, omit both parameters."
6833
+ );
6834
+ }
6653
6835
  const request = new SyncContextRequest({
6654
6836
  authorization: `Bearer ${this.session.getAPIKey()}`,
6655
6837
  sessionId: this.session.getSessionId()
@@ -6657,8 +6839,8 @@ var _ContextManager = class _ContextManager {
6657
6839
  if (contextId) {
6658
6840
  request.contextId = contextId;
6659
6841
  }
6660
- if (path6) {
6661
- request.path = path6;
6842
+ if (path7) {
6843
+ request.path = path7;
6662
6844
  }
6663
6845
  if (mode) {
6664
6846
  request.mode = mode;
@@ -6708,7 +6890,7 @@ var _ContextManager = class _ContextManager {
6708
6890
  const fullResponse = response.body ? JSON.stringify(response.body, null, 2) : "";
6709
6891
  logAPIResponseWithDetails("SyncContext", requestId, success, keyFields, fullResponse);
6710
6892
  if (callback && success) {
6711
- this.pollForCompletion(callback, contextId, path6, maxRetries, retryInterval).catch((error) => {
6893
+ this.pollForCompletion(callback, contextId, path7, maxRetries, retryInterval).catch((error) => {
6712
6894
  logError("Error in background polling:", error);
6713
6895
  callback(false);
6714
6896
  });
@@ -6720,7 +6902,7 @@ var _ContextManager = class _ContextManager {
6720
6902
  if (success) {
6721
6903
  const finalSuccess = await this.pollForCompletionAsync(
6722
6904
  contextId,
6723
- path6,
6905
+ path7,
6724
6906
  maxRetries,
6725
6907
  retryInterval
6726
6908
  );
@@ -6741,10 +6923,10 @@ var _ContextManager = class _ContextManager {
6741
6923
  /**
6742
6924
  * Polls the info interface to check if sync is completed and calls callback.
6743
6925
  */
6744
- async pollForCompletion(callback, contextId, path6, maxRetries = 150, retryInterval = 1500) {
6926
+ async pollForCompletion(callback, contextId, path7, maxRetries = 150, retryInterval = 1500) {
6745
6927
  for (let retry = 0; retry < maxRetries; retry++) {
6746
6928
  try {
6747
- const infoResult = await this.infoWithParams(contextId, path6);
6929
+ const infoResult = await this.infoWithParams(contextId, path7);
6748
6930
  let allCompleted = true;
6749
6931
  let hasFailure = false;
6750
6932
  let hasSyncTasks = false;
@@ -6789,10 +6971,10 @@ var _ContextManager = class _ContextManager {
6789
6971
  /**
6790
6972
  * Async version of polling for sync completion.
6791
6973
  */
6792
- async pollForCompletionAsync(contextId, path6, maxRetries = 150, retryInterval = 1500) {
6974
+ async pollForCompletionAsync(contextId, path7, maxRetries = 150, retryInterval = 1500) {
6793
6975
  for (let retry = 0; retry < maxRetries; retry++) {
6794
6976
  try {
6795
- const infoResult = await this.infoWithParams(contextId, path6);
6977
+ const infoResult = await this.infoWithParams(contextId, path7);
6796
6978
  let allCompleted = true;
6797
6979
  let hasFailure = false;
6798
6980
  let hasSyncTasks = false;
@@ -6837,7 +7019,7 @@ var _ContextManager = class _ContextManager {
6837
7019
  * Sleep utility function for TypeScript
6838
7020
  */
6839
7021
  sleep(ms) {
6840
- return new Promise((resolve2) => setTimeout(resolve2, ms));
7022
+ return new Promise((resolve3) => setTimeout(resolve3, ms));
6841
7023
  }
6842
7024
  };
6843
7025
  __name(_ContextManager, "ContextManager");
@@ -6852,8 +7034,8 @@ init_esm_shims();
6852
7034
 
6853
7035
  // src/filesystem/file-transfer.ts
6854
7036
  init_esm_shims();
6855
- import * as fs3 from "fs";
6856
- import * as path3 from "path";
7037
+ import * as fs4 from "fs";
7038
+ import * as path4 from "path";
6857
7039
  import fetch2 from "node-fetch";
6858
7040
  var _FileTransfer = class _FileTransfer {
6859
7041
  /**
@@ -6892,7 +7074,7 @@ var _FileTransfer = class _FileTransfer {
6892
7074
  progressCb = void 0
6893
7075
  } = options || {};
6894
7076
  try {
6895
- if (!fs3.existsSync(localPath)) {
7077
+ if (!fs4.existsSync(localPath)) {
6896
7078
  return {
6897
7079
  success: false,
6898
7080
  bytesSent: 0,
@@ -6962,7 +7144,7 @@ var _FileTransfer = class _FileTransfer {
6962
7144
  // Assuming previous step succeeded
6963
7145
  etag: "",
6964
7146
  // Assuming previous step succeeded
6965
- bytesSent: fs3.statSync(localPath).size,
7147
+ bytesSent: fs4.statSync(localPath).size,
6966
7148
  // Assuming previous step succeeded
6967
7149
  path: remotePath,
6968
7150
  error: `session.context.sync(upload) failed: ${e.message || e}`
@@ -6986,7 +7168,7 @@ var _FileTransfer = class _FileTransfer {
6986
7168
  // Assuming previous step succeeded
6987
7169
  etag: "",
6988
7170
  // Assuming previous step succeeded
6989
- bytesSent: fs3.statSync(localPath).size,
7171
+ bytesSent: fs4.statSync(localPath).size,
6990
7172
  // Assuming previous step succeeded
6991
7173
  path: remotePath,
6992
7174
  error: `Upload sync not finished: ${error || "timeout or unknown"}`
@@ -6999,7 +7181,7 @@ var _FileTransfer = class _FileTransfer {
6999
7181
  requestIdSync: reqIdSync,
7000
7182
  httpStatus: 200,
7001
7183
  etag: "",
7002
- bytesSent: fs3.statSync(localPath).size,
7184
+ bytesSent: fs4.statSync(localPath).size,
7003
7185
  path: remotePath
7004
7186
  };
7005
7187
  } catch (e) {
@@ -7086,11 +7268,11 @@ var _FileTransfer = class _FileTransfer {
7086
7268
  const downloadUrl = urlRes.url;
7087
7269
  const reqIdDownload = urlRes.requestId;
7088
7270
  try {
7089
- const dir = path3.dirname(localPath);
7090
- if (!fs3.existsSync(dir)) {
7091
- fs3.mkdirSync(dir, { recursive: true });
7271
+ const dir = path4.dirname(localPath);
7272
+ if (!fs4.existsSync(dir)) {
7273
+ fs4.mkdirSync(dir, { recursive: true });
7092
7274
  }
7093
- if (fs3.existsSync(localPath) && !overwrite) {
7275
+ if (fs4.existsSync(localPath) && !overwrite) {
7094
7276
  return {
7095
7277
  success: false,
7096
7278
  requestIdDownloadUrl: reqIdDownload,
@@ -7106,13 +7288,13 @@ var _FileTransfer = class _FileTransfer {
7106
7288
  localPath,
7107
7289
  progressCb
7108
7290
  );
7109
- if (fs3.existsSync(localPath)) {
7291
+ if (fs4.existsSync(localPath)) {
7110
7292
  return {
7111
7293
  success: true,
7112
7294
  requestIdDownloadUrl: reqIdDownload,
7113
7295
  requestIdSync: reqIdSync,
7114
7296
  httpStatus: 200,
7115
- bytesReceived: fs3.statSync(localPath).size,
7297
+ bytesReceived: fs4.statSync(localPath).size,
7116
7298
  path: remotePath,
7117
7299
  localPath
7118
7300
  };
@@ -7211,11 +7393,11 @@ var _FileTransfer = class _FileTransfer {
7211
7393
  const statusList = res.contextStatusData || [];
7212
7394
  for (const item of statusList) {
7213
7395
  const cid = item.contextId;
7214
- const path6 = item.path;
7396
+ const path7 = item.path;
7215
7397
  const ttype = item.taskType;
7216
7398
  const status = item.status;
7217
7399
  const err = item.errorMessage;
7218
- if (cid === contextId && path6 === remotePath && (taskType === void 0 || ttype === taskType)) {
7400
+ if (cid === contextId && path7 === remotePath && (taskType === void 0 || ttype === taskType)) {
7219
7401
  if (err) {
7220
7402
  return { success: false, error: `Task error: ${err}` };
7221
7403
  }
@@ -7228,7 +7410,7 @@ var _FileTransfer = class _FileTransfer {
7228
7410
  } catch (e) {
7229
7411
  lastErr = `info error: ${e.message || e}`;
7230
7412
  }
7231
- await new Promise((resolve2) => setTimeout(resolve2, interval * 1e3));
7413
+ await new Promise((resolve3) => setTimeout(resolve3, interval * 1e3));
7232
7414
  }
7233
7415
  return { success: false, error: lastErr || "timeout" };
7234
7416
  }
@@ -7241,7 +7423,7 @@ var _FileTransfer = class _FileTransfer {
7241
7423
  if (contentType) {
7242
7424
  headers["Content-Type"] = contentType;
7243
7425
  }
7244
- const fileBuffer = fs3.readFileSync(filePath);
7426
+ const fileBuffer = fs4.readFileSync(filePath);
7245
7427
  const response = await fetch2(url, {
7246
7428
  method: "PUT",
7247
7429
  body: fileBuffer,
@@ -7268,7 +7450,7 @@ var _FileTransfer = class _FileTransfer {
7268
7450
  }
7269
7451
  const buffer = await response.buffer();
7270
7452
  bytesReceived = buffer.length;
7271
- fs3.writeFileSync(destPath, buffer);
7453
+ fs4.writeFileSync(destPath, buffer);
7272
7454
  if (progressCb) {
7273
7455
  progressCb(bytesReceived);
7274
7456
  }
@@ -7427,10 +7609,10 @@ var _FileSystem = class _FileSystem {
7427
7609
  * }
7428
7610
  * ```
7429
7611
  */
7430
- async createDirectory(path6) {
7612
+ async createDirectory(path7) {
7431
7613
  try {
7432
7614
  const args = {
7433
- path: path6
7615
+ path: path7
7434
7616
  };
7435
7617
  const result = await this.session.callMcpTool(
7436
7618
  "create_directory",
@@ -7478,10 +7660,10 @@ var _FileSystem = class _FileSystem {
7478
7660
  * }
7479
7661
  * ```
7480
7662
  */
7481
- async editFile(path6, edits, dryRun = false) {
7663
+ async editFile(path7, edits, dryRun = false) {
7482
7664
  try {
7483
7665
  const args = {
7484
- path: path6,
7666
+ path: path7,
7485
7667
  edits,
7486
7668
  dryRun
7487
7669
  };
@@ -7528,10 +7710,10 @@ var _FileSystem = class _FileSystem {
7528
7710
  * }
7529
7711
  * ```
7530
7712
  */
7531
- async getFileInfo(path6) {
7713
+ async getFileInfo(path7) {
7532
7714
  try {
7533
7715
  const args = {
7534
- path: path6
7716
+ path: path7
7535
7717
  };
7536
7718
  const result = await this.session.callMcpTool(
7537
7719
  "get_file_info",
@@ -7606,10 +7788,10 @@ var _FileSystem = class _FileSystem {
7606
7788
  *
7607
7789
  * @see {@link readFile}, {@link writeFile}
7608
7790
  */
7609
- async listDirectory(path6) {
7791
+ async listDirectory(path7) {
7610
7792
  try {
7611
7793
  const args = {
7612
- path: path6
7794
+ path: path7
7613
7795
  };
7614
7796
  const result = await this.session.callMcpTool(
7615
7797
  "list_directory",
@@ -7696,10 +7878,10 @@ var _FileSystem = class _FileSystem {
7696
7878
  * @param length - Optional: Number of bytes to read. If 0, reads the entire file from offset.
7697
7879
  * @returns FileContentResult with file content and requestId
7698
7880
  */
7699
- async readFileChunk(path6, offset = 0, length = 0) {
7881
+ async readFileChunk(path7, offset = 0, length = 0) {
7700
7882
  try {
7701
7883
  const args = {
7702
- path: path6
7884
+ path: path7
7703
7885
  };
7704
7886
  if (offset > 0) {
7705
7887
  args.offset = offset;
@@ -7778,8 +7960,8 @@ var _FileSystem = class _FileSystem {
7778
7960
  for (const line of lines) {
7779
7961
  const colonIndex = line.indexOf(":");
7780
7962
  if (colonIndex > 0 && currentPath === "" && !line.substring(0, colonIndex).includes(" ")) {
7781
- const path6 = line.substring(0, colonIndex).trim();
7782
- currentPath = path6;
7963
+ const path7 = line.substring(0, colonIndex).trim();
7964
+ currentPath = path7;
7783
7965
  if (line.length > colonIndex + 1) {
7784
7966
  const contentStart = line.substring(colonIndex + 1).trim();
7785
7967
  if (contentStart) {
@@ -7799,8 +7981,8 @@ var _FileSystem = class _FileSystem {
7799
7981
  if (currentPath) {
7800
7982
  fileContents[currentPath] = currentContent.join("\n");
7801
7983
  }
7802
- for (const path6 in fileContents) {
7803
- fileContents[path6] = fileContents[path6].replace(/\n+$/, "");
7984
+ for (const path7 in fileContents) {
7985
+ fileContents[path7] = fileContents[path7].replace(/\n+$/, "");
7804
7986
  }
7805
7987
  }
7806
7988
  return {
@@ -7840,10 +8022,10 @@ var _FileSystem = class _FileSystem {
7840
8022
  * }
7841
8023
  * ```
7842
8024
  */
7843
- async searchFiles(path6, pattern, excludePatterns = []) {
8025
+ async searchFiles(path7, pattern, excludePatterns = []) {
7844
8026
  try {
7845
8027
  const args = {
7846
- path: path6,
8028
+ path: path7,
7847
8029
  pattern
7848
8030
  };
7849
8031
  if (excludePatterns.length > 0) {
@@ -7887,7 +8069,7 @@ var _FileSystem = class _FileSystem {
7887
8069
  * @param mode - Optional: Write mode. One of "overwrite", "append", or "create_new". Default is "overwrite".
7888
8070
  * @returns BoolResult with write result and requestId
7889
8071
  */
7890
- async writeFileChunk(path6, content, mode = "overwrite") {
8072
+ async writeFileChunk(path7, content, mode = "overwrite") {
7891
8073
  try {
7892
8074
  const validModes = ["overwrite", "append", "create_new"];
7893
8075
  if (!validModes.includes(mode)) {
@@ -7900,7 +8082,7 @@ var _FileSystem = class _FileSystem {
7900
8082
  };
7901
8083
  }
7902
8084
  const args = {
7903
- path: path6,
8085
+ path: path7,
7904
8086
  content,
7905
8087
  mode
7906
8088
  };
@@ -7977,10 +8159,10 @@ var _FileSystem = class _FileSystem {
7977
8159
  *
7978
8160
  * @see {@link writeFile}, {@link listDirectory}
7979
8161
  */
7980
- async readFile(path6) {
8162
+ async readFile(path7) {
7981
8163
  const chunkSize = DEFAULT_CHUNK_SIZE;
7982
8164
  try {
7983
- const fileInfoResult = await this.getFileInfo(path6);
8165
+ const fileInfoResult = await this.getFileInfo(path7);
7984
8166
  if (!fileInfoResult.success) {
7985
8167
  return {
7986
8168
  requestId: fileInfoResult.requestId,
@@ -7994,7 +8176,7 @@ var _FileSystem = class _FileSystem {
7994
8176
  requestId: fileInfoResult.requestId,
7995
8177
  success: false,
7996
8178
  content: "",
7997
- errorMessage: `Path does not exist or is a directory: ${path6}`
8179
+ errorMessage: `Path does not exist or is a directory: ${path7}`
7998
8180
  };
7999
8181
  }
8000
8182
  const fileSize = fileInfoResult.fileInfo.size || 0;
@@ -8014,7 +8196,7 @@ var _FileSystem = class _FileSystem {
8014
8196
  length = fileSize - offset;
8015
8197
  }
8016
8198
  try {
8017
- const chunkResult = await this.readFileChunk(path6, offset, length);
8199
+ const chunkResult = await this.readFileChunk(path7, offset, length);
8018
8200
  if (!chunkResult.success) {
8019
8201
  return chunkResult;
8020
8202
  }
@@ -8100,16 +8282,16 @@ var _FileSystem = class _FileSystem {
8100
8282
  *
8101
8283
  * @see {@link readFile}, {@link listDirectory}
8102
8284
  */
8103
- async writeFile(path6, content, mode = "overwrite") {
8285
+ async writeFile(path7, content, mode = "overwrite") {
8104
8286
  const chunkSize = DEFAULT_CHUNK_SIZE;
8105
8287
  try {
8106
8288
  const contentLen = content.length;
8107
8289
  if (contentLen <= chunkSize) {
8108
- return await this.writeFileChunk(path6, content, mode);
8290
+ return await this.writeFileChunk(path7, content, mode);
8109
8291
  }
8110
8292
  const firstChunkEnd = Math.min(chunkSize, contentLen);
8111
8293
  const firstResult = await this.writeFileChunk(
8112
- path6,
8294
+ path7,
8113
8295
  content.substring(0, firstChunkEnd),
8114
8296
  mode
8115
8297
  );
@@ -8120,7 +8302,7 @@ var _FileSystem = class _FileSystem {
8120
8302
  for (let offset = firstChunkEnd; offset < contentLen; ) {
8121
8303
  const end = Math.min(offset + chunkSize, contentLen);
8122
8304
  const chunkResult = await this.writeFileChunk(
8123
- path6,
8305
+ path7,
8124
8306
  content.substring(offset, end),
8125
8307
  "append"
8126
8308
  );
@@ -8161,9 +8343,9 @@ var _FileSystem = class _FileSystem {
8161
8343
  * }
8162
8344
  * ```
8163
8345
  */
8164
- async getFileChange(path6) {
8346
+ async getFileChange(path7) {
8165
8347
  try {
8166
- const args = { path: path6 };
8348
+ const args = { path: path7 };
8167
8349
  const result = await this.session.callMcpTool("get_file_change", args);
8168
8350
  if (!result.success) {
8169
8351
  return {
@@ -8234,17 +8416,17 @@ var _FileSystem = class _FileSystem {
8234
8416
  * }
8235
8417
  * ```
8236
8418
  */
8237
- async watchDirectory(path6, callback, interval = 500, signal) {
8238
- console.log(`Starting directory monitoring for: ${path6}`);
8419
+ async watchDirectory(path7, callback, interval = 500, signal) {
8420
+ console.log(`Starting directory monitoring for: ${path7}`);
8239
8421
  console.log(`Polling interval: ${interval} ms`);
8240
8422
  const monitor = /* @__PURE__ */ __name(async () => {
8241
8423
  while (!signal?.aborted) {
8242
8424
  try {
8243
8425
  if (this.session._isExpired && this.session._isExpired()) {
8244
- console.log(`Session expired, stopping directory monitoring for: ${path6}`);
8426
+ console.log(`Session expired, stopping directory monitoring for: ${path7}`);
8245
8427
  break;
8246
8428
  }
8247
- const result = await this.getFileChange(path6);
8429
+ const result = await this.getFileChange(path7);
8248
8430
  if (result.success && result.events.length > 0) {
8249
8431
  console.log(`Detected ${result.events.length} file changes:`);
8250
8432
  for (const event of result.events) {
@@ -8258,29 +8440,29 @@ var _FileSystem = class _FileSystem {
8258
8440
  } else if (!result.success) {
8259
8441
  const errorMsg = (result.errorMessage || "").toLowerCase();
8260
8442
  if (errorMsg.includes("session") && (errorMsg.includes("expired") || errorMsg.includes("invalid"))) {
8261
- console.log(`Session expired, stopping directory monitoring for: ${path6}`);
8443
+ console.log(`Session expired, stopping directory monitoring for: ${path7}`);
8262
8444
  break;
8263
8445
  }
8264
8446
  console.error(`Error monitoring directory: ${result.errorMessage}`);
8265
8447
  }
8266
- await new Promise((resolve2) => {
8267
- const timeoutId = setTimeout(resolve2, interval);
8448
+ await new Promise((resolve3) => {
8449
+ const timeoutId = setTimeout(resolve3, interval);
8268
8450
  signal?.addEventListener("abort", () => {
8269
8451
  clearTimeout(timeoutId);
8270
- resolve2(void 0);
8452
+ resolve3(void 0);
8271
8453
  });
8272
8454
  });
8273
8455
  } catch (error) {
8274
8456
  console.error(`Unexpected error in directory monitoring: ${error}`);
8275
8457
  const errorStr = String(error).toLowerCase();
8276
8458
  if (errorStr.includes("session") && (errorStr.includes("expired") || errorStr.includes("invalid"))) {
8277
- console.log(`Session expired, stopping directory monitoring for: ${path6}`);
8459
+ console.log(`Session expired, stopping directory monitoring for: ${path7}`);
8278
8460
  break;
8279
8461
  }
8280
- await new Promise((resolve2) => setTimeout(resolve2, interval));
8462
+ await new Promise((resolve3) => setTimeout(resolve3, interval));
8281
8463
  }
8282
8464
  }
8283
- console.log(`Stopped monitoring directory: ${path6}`);
8465
+ console.log(`Stopped monitoring directory: ${path7}`);
8284
8466
  }, "monitor");
8285
8467
  return monitor();
8286
8468
  }
@@ -8868,7 +9050,7 @@ var _Mobile = class _Mobile {
8868
9050
  async getAdbUrl(adbkeyPub) {
8869
9051
  try {
8870
9052
  const optionsJson = JSON.stringify({ adbkey_pub: adbkeyPub });
8871
- const { GetAdbLinkRequest: GetAdbLinkRequest2 } = await import("./model-ZFTLKEMC.mjs");
9053
+ const { GetAdbLinkRequest: GetAdbLinkRequest2 } = await import("./model-LGWQJWKQ.mjs");
8872
9054
  const request = new GetAdbLinkRequest2({
8873
9055
  authorization: `Bearer ${this.session.getAPIKey()}`,
8874
9056
  sessionId: this.session.sessionId,
@@ -9298,12 +9480,12 @@ var _Oss = class _Oss {
9298
9480
  * }
9299
9481
  * ```
9300
9482
  */
9301
- async upload(bucket, object, path6) {
9483
+ async upload(bucket, object, path7) {
9302
9484
  try {
9303
9485
  const args = {
9304
9486
  bucket,
9305
9487
  object,
9306
- path: path6
9488
+ path: path7
9307
9489
  };
9308
9490
  const result = await this.session.callMcpTool("oss_upload", args);
9309
9491
  return {
@@ -9341,11 +9523,11 @@ var _Oss = class _Oss {
9341
9523
  * }
9342
9524
  * ```
9343
9525
  */
9344
- async uploadAnonymous(url, path6) {
9526
+ async uploadAnonymous(url, path7) {
9345
9527
  try {
9346
9528
  const args = {
9347
9529
  url,
9348
- path: path6
9530
+ path: path7
9349
9531
  };
9350
9532
  const result = await this.session.callMcpTool("oss_upload_annon", args);
9351
9533
  return {
@@ -9385,12 +9567,12 @@ var _Oss = class _Oss {
9385
9567
  * }
9386
9568
  * ```
9387
9569
  */
9388
- async download(bucket, object, path6) {
9570
+ async download(bucket, object, path7) {
9389
9571
  try {
9390
9572
  const args = {
9391
9573
  bucket,
9392
9574
  object,
9393
- path: path6
9575
+ path: path7
9394
9576
  };
9395
9577
  const result = await this.session.callMcpTool("oss_download", args);
9396
9578
  return {
@@ -9428,11 +9610,11 @@ var _Oss = class _Oss {
9428
9610
  * }
9429
9611
  * ```
9430
9612
  */
9431
- async downloadAnonymous(url, path6) {
9613
+ async downloadAnonymous(url, path7) {
9432
9614
  try {
9433
9615
  const args = {
9434
9616
  url,
9435
- path: path6
9617
+ path: path7
9436
9618
  };
9437
9619
  const result = await this.session.callMcpTool("oss_download_annon", args);
9438
9620
  return {
@@ -9667,7 +9849,7 @@ var _Session = class _Session {
9667
9849
  try {
9668
9850
  let syncResult;
9669
9851
  if (syncContextId) {
9670
- syncResult = await this.context.sync(syncContextId);
9852
+ syncResult = await this.context.sync(syncContextId, BROWSER_RECORD_PATH);
9671
9853
  logInfo(`\u{1F3A5} Synced browser recording context: ${syncContextId}`);
9672
9854
  } else {
9673
9855
  syncResult = await this.context.sync();
@@ -10427,80 +10609,374 @@ var _Session = class _Session {
10427
10609
  };
10428
10610
  }
10429
10611
  }
10430
- };
10431
- __name(_Session, "Session");
10432
- var Session = _Session;
10433
-
10434
- // src/agent-bay.ts
10435
- var BROWSER_DATA_PATH2 = "/tmp/agentbay_browser";
10436
- function defaultConfig() {
10437
- return {
10438
- endpoint: "wuyingai.cn-shanghai.aliyuncs.com",
10439
- timeout_ms: 6e4
10440
- };
10441
- }
10442
- __name(defaultConfig, "defaultConfig");
10443
- function findDotEnvFile(startPath) {
10444
- const currentPath = startPath ? path4.resolve(startPath) : process.cwd();
10445
- let searchPath = currentPath;
10446
- while (searchPath !== path4.dirname(searchPath)) {
10447
- const envFile = path4.join(searchPath, ".env");
10448
- if (fs4.existsSync(envFile)) {
10449
- return envFile;
10450
- }
10451
- const gitDir = path4.join(searchPath, ".git");
10452
- if (fs4.existsSync(gitDir)) {
10453
- }
10454
- searchPath = path4.dirname(searchPath);
10455
- }
10456
- const rootEnv = path4.join(searchPath, ".env");
10457
- if (fs4.existsSync(rootEnv)) {
10458
- return rootEnv;
10459
- }
10460
- return null;
10461
- }
10462
- __name(findDotEnvFile, "findDotEnvFile");
10463
- function loadDotEnvWithFallback(customEnvPath) {
10464
- if (customEnvPath) {
10465
- if (fs4.existsSync(customEnvPath)) {
10466
- try {
10467
- const envConfig = dotenv.parse(fs4.readFileSync(customEnvPath));
10468
- for (const k in envConfig) {
10469
- if (!process.env.hasOwnProperty(k)) {
10470
- process.env[k] = envConfig[k];
10612
+ /**
10613
+ * Asynchronously pause this session, putting it into a dormant state.
10614
+ *
10615
+ * This method calls the PauseSessionAsync API to initiate the pause operation and then polls
10616
+ * the GetSession API to check the session status until it becomes PAUSED or until timeout is reached.
10617
+ * During the paused state, resource usage and costs are reduced while session state is preserved.
10618
+ *
10619
+ * @param timeout - Timeout in seconds to wait for the session to pause. Defaults to 600 seconds.
10620
+ * @param pollInterval - Interval in seconds between status polls. Defaults to 2.0 seconds.
10621
+ *
10622
+ * @returns Promise resolving to SessionPauseResult containing:
10623
+ * - success: Whether the pause operation succeeded
10624
+ * - requestId: Unique identifier for this API request
10625
+ * - status: Final session status (should be "PAUSED" if successful)
10626
+ * - errorMessage: Error description if pause failed
10627
+ *
10628
+ * @throws Error if the API call fails or network issues occur.
10629
+ *
10630
+ * @example
10631
+ * ```typescript
10632
+ * const agentBay = new AgentBay({ apiKey: 'your_api_key' });
10633
+ * const result = await agentBay.create();
10634
+ * if (result.success) {
10635
+ * const pauseResult = await result.session.pauseAsync();
10636
+ * if (pauseResult.success) {
10637
+ * console.log('Session paused successfully');
10638
+ * }
10639
+ * }
10640
+ * ```
10641
+ *
10642
+ * @remarks
10643
+ * **Behavior:**
10644
+ * - Initiates pause operation through PauseSessionAsync API
10645
+ * - Polls session status until PAUSED state or timeout
10646
+ * - Session state transitions: RUNNING -> PAUSING -> PAUSED
10647
+ * - All session state is preserved during pause
10648
+ *
10649
+ * **Important Notes:**
10650
+ * - Paused sessions cannot perform operations (deletion, task execution, etc.)
10651
+ * - Use {@link resumeAsync} to restore the session to RUNNING state
10652
+ * - During pause, both resource usage and costs are lower
10653
+ * - If timeout is exceeded, returns with success=false
10654
+ *
10655
+ * @see {@link resumeAsync}
10656
+ */
10657
+ async pauseAsync(timeout = 600, pollInterval = 2) {
10658
+ try {
10659
+ const request = new PauseSessionAsyncRequest({
10660
+ authorization: `Bearer ${this.getAPIKey()}`,
10661
+ sessionId: this.sessionId
10662
+ });
10663
+ logAPICall("PauseSessionAsync", `SessionId=${this.sessionId}`);
10664
+ const response = await this.getClient().pauseSessionAsync(request);
10665
+ const requestId = extractRequestId(response) || "";
10666
+ setRequestId(requestId);
10667
+ const responseMap = response.to_map ? response.to_map() : response;
10668
+ if (!responseMap) {
10669
+ return {
10670
+ requestId: requestId || "",
10671
+ success: false,
10672
+ errorMessage: "Invalid response format"
10673
+ };
10674
+ }
10675
+ const body = responseMap.body;
10676
+ if (!body) {
10677
+ return {
10678
+ requestId: requestId || "",
10679
+ success: false,
10680
+ errorMessage: "Invalid response body"
10681
+ };
10682
+ }
10683
+ const success = body.success !== false;
10684
+ const code = body.code || "";
10685
+ const message = body.message || "";
10686
+ const httpStatusCode = body.httpStatusCode || 0;
10687
+ if (!success) {
10688
+ const errorMessage = `[${code}] ${message}` || "Unknown error";
10689
+ logError("PauseSessionAsync", errorMessage);
10690
+ return {
10691
+ requestId: requestId || "",
10692
+ success: false,
10693
+ errorMessage,
10694
+ code,
10695
+ message,
10696
+ httpStatusCode
10697
+ };
10698
+ }
10699
+ logInfo(`PauseSessionAsync`, `Session ${this.sessionId} pause initiated successfully`);
10700
+ const startTime = Date.now();
10701
+ const maxAttempts = Math.floor(timeout / pollInterval);
10702
+ let attempt = 0;
10703
+ while (attempt < maxAttempts) {
10704
+ const getResult = await this.agentBay.getSession(this.sessionId);
10705
+ if (!getResult.success) {
10706
+ logError(`Failed to get session status: ${getResult.errorMessage}`);
10707
+ return {
10708
+ requestId: getResult.requestId || "",
10709
+ success: false,
10710
+ errorMessage: `Failed to get session status: ${getResult.errorMessage}`
10711
+ };
10712
+ }
10713
+ if (getResult.data) {
10714
+ const status = getResult.data.status || "UNKNOWN";
10715
+ logDebug(`Session status: ${status} (attempt ${attempt + 1}/${maxAttempts})`);
10716
+ if (status === "PAUSED") {
10717
+ const elapsed2 = Date.now() - startTime;
10718
+ logInfo(`Session paused successfully in ${elapsed2}ms`);
10719
+ return {
10720
+ requestId: getResult.requestId || "",
10721
+ success: true,
10722
+ status
10723
+ };
10724
+ } else if (status === "PAUSING") {
10725
+ } else {
10726
+ const elapsed2 = Date.now() - startTime;
10727
+ const errorMessage = `Session pause failed: unexpected state '${status}' after ${elapsed2}ms`;
10728
+ logError(errorMessage);
10729
+ return {
10730
+ requestId: getResult.requestId || "",
10731
+ success: false,
10732
+ errorMessage,
10733
+ status
10734
+ };
10471
10735
  }
10472
10736
  }
10473
- return;
10474
- } catch (error) {
10475
- }
10476
- }
10477
- }
10478
- const envFile = findDotEnvFile();
10479
- if (envFile) {
10480
- try {
10481
- const envConfig = dotenv.parse(fs4.readFileSync(envFile));
10482
- for (const k in envConfig) {
10483
- if (!process.env.hasOwnProperty(k)) {
10484
- process.env[k] = envConfig[k];
10737
+ attempt++;
10738
+ if (attempt < maxAttempts) {
10739
+ await new Promise((resolve3) => setTimeout(resolve3, pollInterval * 1e3));
10485
10740
  }
10486
10741
  }
10742
+ const elapsed = Date.now() - startTime;
10743
+ const errorMsg = `Session pause timed out after ${elapsed}ms`;
10744
+ logError(errorMsg);
10745
+ return {
10746
+ requestId: "",
10747
+ success: false,
10748
+ errorMessage: errorMsg
10749
+ };
10487
10750
  } catch (error) {
10751
+ logError("PauseSessionAsync", error);
10752
+ return {
10753
+ requestId: "",
10754
+ success: false,
10755
+ errorMessage: `Unexpected error pausing session: ${error}`
10756
+ };
10488
10757
  }
10489
10758
  }
10490
- }
10491
- __name(loadDotEnvWithFallback, "loadDotEnvWithFallback");
10492
- function loadConfig(customConfig, customEnvPath) {
10493
- if (customConfig) {
10494
- return customConfig;
10495
- }
10496
- const config = defaultConfig();
10497
- try {
10498
- loadDotEnvWithFallback(customEnvPath);
10499
- } catch (error) {
10500
- }
10501
- if (process.env.AGENTBAY_ENDPOINT) {
10502
- config.endpoint = process.env.AGENTBAY_ENDPOINT;
10503
- }
10759
+ /**
10760
+ * Asynchronously resume this session from a paused state.
10761
+ *
10762
+ * This method calls the ResumeSessionAsync API to initiate the resume operation and then polls
10763
+ * the GetSession API to check the session status until it becomes RUNNING or until timeout is reached.
10764
+ * After resuming, the session restores full functionality and can perform all operations normally.
10765
+ *
10766
+ * @param timeout - Timeout in seconds to wait for the session to resume. Defaults to 600 seconds.
10767
+ * @param pollInterval - Interval in seconds between status polls. Defaults to 2.0 seconds.
10768
+ *
10769
+ * @returns Promise resolving to SessionResumeResult containing:
10770
+ * - success: Whether the resume operation succeeded
10771
+ * - requestId: Unique identifier for this API request
10772
+ * - status: Final session status (should be "RUNNING" if successful)
10773
+ * - errorMessage: Error description if resume failed
10774
+ *
10775
+ * @throws Error if the API call fails or network issues occur.
10776
+ *
10777
+ * @example
10778
+ * ```typescript
10779
+ * const agentBay = new AgentBay({ apiKey: 'your_api_key' });
10780
+ * const result = await agentBay.get('paused_session_id');
10781
+ * if (result.success) {
10782
+ * const resumeResult = await result.session.resumeAsync();
10783
+ * if (resumeResult.success) {
10784
+ * console.log('Session resumed successfully');
10785
+ * }
10786
+ * }
10787
+ * ```
10788
+ *
10789
+ * @remarks
10790
+ * **Behavior:**
10791
+ * - Initiates resume operation through ResumeSessionAsync API
10792
+ * - Polls session status until RUNNING state or timeout
10793
+ * - Session state transitions: PAUSED -> RESUMING -> RUNNING
10794
+ * - All previous session state is restored during resume
10795
+ *
10796
+ * **Important Notes:**
10797
+ * - Only sessions in PAUSED state can be resumed
10798
+ * - After resume, the session can perform all operations normally
10799
+ * - Use {@link pauseAsync} to put a session into PAUSED state
10800
+ * - If timeout is exceeded, returns with success=false
10801
+ *
10802
+ * @see {@link pauseAsync}
10803
+ */
10804
+ async resumeAsync(timeout = 600, pollInterval = 2) {
10805
+ try {
10806
+ const request = new ResumeSessionAsyncRequest({
10807
+ authorization: `Bearer ${this.getAPIKey()}`,
10808
+ sessionId: this.sessionId
10809
+ });
10810
+ logAPICall("ResumeSessionAsync", `SessionId=${this.sessionId}`);
10811
+ const response = await this.getClient().resumeSessionAsync(request);
10812
+ const requestId = extractRequestId(response) || "";
10813
+ setRequestId(requestId);
10814
+ const responseMap = response.to_map ? response.to_map() : response;
10815
+ if (!responseMap) {
10816
+ return {
10817
+ requestId: requestId || "",
10818
+ success: false,
10819
+ errorMessage: "Invalid response format"
10820
+ };
10821
+ }
10822
+ const body = responseMap.body;
10823
+ if (!body) {
10824
+ return {
10825
+ requestId: requestId || "",
10826
+ success: false,
10827
+ errorMessage: "Invalid response body"
10828
+ };
10829
+ }
10830
+ const success = body.success !== false;
10831
+ const code = body.code || "";
10832
+ const message = body.message || "";
10833
+ const httpStatusCode = body.httpStatusCode || 0;
10834
+ if (!success) {
10835
+ const errorMessage = `[${code}] ${message}` || "Unknown error";
10836
+ logError("ResumeSessionAsync", errorMessage);
10837
+ return {
10838
+ requestId: requestId || "",
10839
+ success: false,
10840
+ errorMessage,
10841
+ code,
10842
+ message,
10843
+ httpStatusCode
10844
+ };
10845
+ }
10846
+ logInfo(`ResumeSessionAsync`, `Session ${this.sessionId} resume initiated successfully`);
10847
+ const startTime = Date.now();
10848
+ const maxAttempts = Math.floor(timeout / pollInterval);
10849
+ let attempt = 0;
10850
+ while (attempt < maxAttempts) {
10851
+ const getResult = await this.agentBay.getSession(this.sessionId);
10852
+ if (!getResult.success) {
10853
+ logError(`Failed to get session status: ${getResult.errorMessage}`);
10854
+ return {
10855
+ requestId: getResult.requestId || "",
10856
+ success: false,
10857
+ errorMessage: `Failed to get session status: ${getResult.errorMessage}`
10858
+ };
10859
+ }
10860
+ if (getResult.data) {
10861
+ const status = getResult.data.status || "UNKNOWN";
10862
+ logDebug(`Session status: ${status} (attempt ${attempt + 1}/${maxAttempts})`);
10863
+ if (status === "RUNNING") {
10864
+ const elapsed2 = Date.now() - startTime;
10865
+ logInfo(`Session resumed successfully in ${elapsed2}ms`);
10866
+ return {
10867
+ requestId: getResult.requestId || "",
10868
+ success: true,
10869
+ status
10870
+ };
10871
+ } else if (status === "RESUMING") {
10872
+ } else {
10873
+ const elapsed2 = Date.now() - startTime;
10874
+ const errorMessage = `Session resume failed: unexpected state '${status}' after ${elapsed2}ms`;
10875
+ logError(errorMessage);
10876
+ return {
10877
+ requestId: getResult.requestId || "",
10878
+ success: false,
10879
+ errorMessage,
10880
+ status
10881
+ };
10882
+ }
10883
+ }
10884
+ attempt++;
10885
+ if (attempt < maxAttempts) {
10886
+ await new Promise((resolve3) => setTimeout(resolve3, pollInterval * 1e3));
10887
+ }
10888
+ }
10889
+ const elapsed = Date.now() - startTime;
10890
+ const errorMsg = `Session resume timed out after ${elapsed}ms`;
10891
+ logError(errorMsg);
10892
+ return {
10893
+ requestId: "",
10894
+ success: false,
10895
+ errorMessage: errorMsg
10896
+ };
10897
+ } catch (error) {
10898
+ logError("ResumeSessionAsync", error);
10899
+ return {
10900
+ requestId: "",
10901
+ success: false,
10902
+ errorMessage: `Unexpected error resuming session: ${error}`
10903
+ };
10904
+ }
10905
+ }
10906
+ };
10907
+ __name(_Session, "Session");
10908
+ var Session = _Session;
10909
+
10910
+ // src/agent-bay.ts
10911
+ var BROWSER_DATA_PATH2 = "/tmp/agentbay_browser";
10912
+ function defaultConfig() {
10913
+ return {
10914
+ endpoint: "wuyingai.cn-shanghai.aliyuncs.com",
10915
+ timeout_ms: 6e4
10916
+ };
10917
+ }
10918
+ __name(defaultConfig, "defaultConfig");
10919
+ function findDotEnvFile2(startPath) {
10920
+ const currentPath = startPath ? path5.resolve(startPath) : process.cwd();
10921
+ let searchPath = currentPath;
10922
+ while (searchPath !== path5.dirname(searchPath)) {
10923
+ const envFile = path5.join(searchPath, ".env");
10924
+ if (fs5.existsSync(envFile)) {
10925
+ return envFile;
10926
+ }
10927
+ const gitDir = path5.join(searchPath, ".git");
10928
+ if (fs5.existsSync(gitDir)) {
10929
+ }
10930
+ searchPath = path5.dirname(searchPath);
10931
+ }
10932
+ const rootEnv = path5.join(searchPath, ".env");
10933
+ if (fs5.existsSync(rootEnv)) {
10934
+ return rootEnv;
10935
+ }
10936
+ return null;
10937
+ }
10938
+ __name(findDotEnvFile2, "findDotEnvFile");
10939
+ function loadDotEnvWithFallback2(customEnvPath) {
10940
+ if (customEnvPath) {
10941
+ if (fs5.existsSync(customEnvPath)) {
10942
+ try {
10943
+ const envConfig = dotenv2.parse(fs5.readFileSync(customEnvPath));
10944
+ for (const k in envConfig) {
10945
+ if (!process.env.hasOwnProperty(k)) {
10946
+ process.env[k] = envConfig[k];
10947
+ }
10948
+ }
10949
+ return;
10950
+ } catch (error) {
10951
+ }
10952
+ }
10953
+ }
10954
+ const envFile = findDotEnvFile2();
10955
+ if (envFile) {
10956
+ try {
10957
+ const envConfig = dotenv2.parse(fs5.readFileSync(envFile));
10958
+ for (const k in envConfig) {
10959
+ if (!process.env.hasOwnProperty(k)) {
10960
+ process.env[k] = envConfig[k];
10961
+ }
10962
+ }
10963
+ } catch (error) {
10964
+ }
10965
+ }
10966
+ }
10967
+ __name(loadDotEnvWithFallback2, "loadDotEnvWithFallback");
10968
+ function loadConfig(customConfig, customEnvPath) {
10969
+ if (customConfig) {
10970
+ return customConfig;
10971
+ }
10972
+ const config = defaultConfig();
10973
+ try {
10974
+ loadDotEnvWithFallback2(customEnvPath);
10975
+ } catch (error) {
10976
+ }
10977
+ if (process.env.AGENTBAY_ENDPOINT) {
10978
+ config.endpoint = process.env.AGENTBAY_ENDPOINT;
10979
+ }
10504
10980
  if (process.env.AGENTBAY_TIMEOUT_MS) {
10505
10981
  const timeout = parseInt(process.env.AGENTBAY_TIMEOUT_MS, 10);
10506
10982
  if (!isNaN(timeout) && timeout > 0) {
@@ -10530,9 +11006,8 @@ var _AgentBay = class _AgentBay {
10530
11006
  * @param options.envFile - Custom path to .env file. If not provided, will search upward from current directory.
10531
11007
  */
10532
11008
  constructor(options = {}) {
10533
- this.sessions = /* @__PURE__ */ new Map();
10534
11009
  this.fileTransferContext = null;
10535
- loadDotEnvWithFallback(options.envFile);
11010
+ loadDotEnvWithFallback2(options.envFile);
10536
11011
  this.apiKey = options.apiKey || process.env.AGENTBAY_API_KEY || "";
10537
11012
  if (!this.apiKey) {
10538
11013
  throw new AuthenticationError(
@@ -10555,6 +11030,59 @@ var _AgentBay = class _AgentBay {
10555
11030
  throw new AuthenticationError(`Failed to constructor: ${error}`);
10556
11031
  }
10557
11032
  }
11033
+ /**
11034
+ * Wait for mobile simulate command to complete.
11035
+ *
11036
+ * @param session - The session to wait for mobile simulate
11037
+ * @param mobileSimPath - The dev info path to the mobile simulate
11038
+ * @param mobileSimMode - The mode of the mobile simulate. If not provided, will use the default mode.
11039
+ */
11040
+ async _waitForMobileSimulate(session, mobileSimPath, mobileSimMode) {
11041
+ log("\u23F3 Mobile simulate: Waiting for completion");
11042
+ if (!session.mobile) {
11043
+ logInfo("Mobile module not found in session, skipping mobile simulate");
11044
+ return;
11045
+ }
11046
+ if (!session.command) {
11047
+ logInfo("Command module not found in session, skipping mobile simulate");
11048
+ return;
11049
+ }
11050
+ if (!mobileSimPath) {
11051
+ logInfo("Mobile simulate path is empty, skipping mobile simulate");
11052
+ return;
11053
+ }
11054
+ try {
11055
+ const startTime = Date.now();
11056
+ const devInfoFilePath = `${mobileSimPath}/dev_info.json`;
11057
+ let wyaApplyOption = "";
11058
+ if (!mobileSimMode || mobileSimMode === "PropertiesOnly") {
11059
+ wyaApplyOption = "";
11060
+ } else if (mobileSimMode === "SensorsOnly") {
11061
+ wyaApplyOption = "-sensors";
11062
+ } else if (mobileSimMode === "PackagesOnly") {
11063
+ wyaApplyOption = "-packages";
11064
+ } else if (mobileSimMode === "ServicesOnly") {
11065
+ wyaApplyOption = "-services";
11066
+ } else if (mobileSimMode === "All") {
11067
+ wyaApplyOption = "-all";
11068
+ }
11069
+ const command = `chmod -R a+rwx ${mobileSimPath}; wya apply ${wyaApplyOption} ${devInfoFilePath}`.trim();
11070
+ logInfo(`\u2139\uFE0F \u23F3 Waiting for mobile simulate completion, command: ${command}`);
11071
+ const cmdResult = await session.command.executeCommand(command);
11072
+ if (cmdResult.success) {
11073
+ const endTime = Date.now();
11074
+ const consumeTime = (endTime - startTime) / 1e3;
11075
+ log(`\u2705 Mobile simulate completed with mode: ${mobileSimMode || "PropertiesOnly"}, duration: ${consumeTime.toFixed(2)} seconds`);
11076
+ if (cmdResult.output) {
11077
+ log(` Output: ${cmdResult.output.trim()}`);
11078
+ }
11079
+ } else {
11080
+ logInfo(`Failed to execute mobile simulate command: ${cmdResult.errorMessage}`);
11081
+ }
11082
+ } catch (error) {
11083
+ logInfo(`Error executing mobile simulate command: ${error}`);
11084
+ }
11085
+ }
10558
11086
  /**
10559
11087
  * Update browser replay context with AppInstanceId from response data.
10560
11088
  *
@@ -10635,13 +11163,28 @@ var _AgentBay = class _AgentBay {
10635
11163
  async create(params = {}) {
10636
11164
  try {
10637
11165
  logDebug(`default context syncs length: ${params.contextSync?.length}`);
11166
+ if (params.extraConfigs?.mobile?.simulateConfig) {
11167
+ const mobileSimContextId = params.extraConfigs.mobile.simulateConfig.simulatedContextId;
11168
+ if (mobileSimContextId) {
11169
+ const mobileSimContextSync = new ContextSync(
11170
+ mobileSimContextId,
11171
+ "/data/agentbay_mobile_info"
11172
+ );
11173
+ if (!params.contextSync) {
11174
+ params.contextSync = [];
11175
+ }
11176
+ logInfo(`Adding context sync for mobile simulate: ${JSON.stringify(mobileSimContextSync)}`);
11177
+ params.contextSync.push(mobileSimContextSync);
11178
+ }
11179
+ }
11180
+ logDebug(`Origin context syncs length: ${params.contextSync?.length}`);
10638
11181
  const contextName = `file-transfer-context-${Date.now()}`;
10639
11182
  const contextResult = await this.context.get(contextName, true);
10640
11183
  if (contextResult.success && contextResult.context) {
10641
11184
  this.fileTransferContext = contextResult.context;
10642
11185
  const fileTransferContextSync = new ContextSync(
10643
11186
  contextResult.context.id,
10644
- "/temp/file-transfer"
11187
+ "/tmp/file-transfer"
10645
11188
  );
10646
11189
  if (!params.contextSync) {
10647
11190
  params.contextSync = [];
@@ -10666,6 +11209,9 @@ var _AgentBay = class _AgentBay {
10666
11209
  }
10667
11210
  request.vpcResource = params.isVpc || false;
10668
11211
  let needsContextSync = false;
11212
+ let needsMobileSim = false;
11213
+ let mobileSimMode = void 0;
11214
+ let mobileSimPath = void 0;
10669
11215
  if (params.contextSync && params.contextSync.length > 0) {
10670
11216
  const persistenceDataList = [];
10671
11217
  for (const contextSync of params.contextSync) {
@@ -10703,7 +11249,7 @@ var _AgentBay = class _AgentBay {
10703
11249
  }
10704
11250
  let recordContextId = "";
10705
11251
  if (params.enableBrowserReplay) {
10706
- const recordPath = "/home/guest/record";
11252
+ const recordPath = BROWSER_RECORD_PATH;
10707
11253
  const recordContextName = generateRandomContextName();
10708
11254
  const result = await this.context.get(recordContextName, true);
10709
11255
  recordContextId = result.success ? result.contextId : "";
@@ -10718,6 +11264,15 @@ var _AgentBay = class _AgentBay {
10718
11264
  }
10719
11265
  if (params.extraConfigs) {
10720
11266
  request.extraConfigs = JSON.stringify(params.extraConfigs);
11267
+ if (params.extraConfigs.mobile?.simulateConfig?.simulate) {
11268
+ mobileSimPath = params.extraConfigs.mobile.simulateConfig.simulatePath;
11269
+ if (!mobileSimPath) {
11270
+ logInfo("mobile_sim_path is not set now, skip mobile simulate operation");
11271
+ } else {
11272
+ needsMobileSim = true;
11273
+ mobileSimMode = params.extraConfigs.mobile.simulateConfig.simulateMode;
11274
+ }
11275
+ }
10721
11276
  }
10722
11277
  logAPICall("CreateMcpSession", {
10723
11278
  labels: params.labels,
@@ -10835,7 +11390,6 @@ var _AgentBay = class _AgentBay {
10835
11390
  session.fileTransferContextId = this.fileTransferContext ? this.fileTransferContext.id : null;
10836
11391
  session.recordContextId = recordContextId || null;
10837
11392
  session.imageId = params.imageId;
10838
- this.sessions.set(session.sessionId, session);
10839
11393
  if (params.extraConfigs && params.extraConfigs.mobile) {
10840
11394
  log("Applying mobile configuration...");
10841
11395
  try {
@@ -10890,13 +11444,16 @@ var _AgentBay = class _AgentBay {
10890
11444
  break;
10891
11445
  }
10892
11446
  logDebug(`Waiting for context synchronization, attempt ${retry + 1}/${maxRetries}`);
10893
- await new Promise((resolve2) => setTimeout(resolve2, retryInterval));
11447
+ await new Promise((resolve3) => setTimeout(resolve3, retryInterval));
10894
11448
  } catch (error) {
10895
11449
  logError(`Error checking context status on attempt ${retry + 1}: ${error}`);
10896
- await new Promise((resolve2) => setTimeout(resolve2, retryInterval));
11450
+ await new Promise((resolve3) => setTimeout(resolve3, retryInterval));
10897
11451
  }
10898
11452
  }
10899
11453
  }
11454
+ if (needsMobileSim && mobileSimPath) {
11455
+ await this._waitForMobileSimulate(session, mobileSimPath, mobileSimMode);
11456
+ }
10900
11457
  return {
10901
11458
  requestId,
10902
11459
  success: true,
@@ -11082,7 +11639,6 @@ var _AgentBay = class _AgentBay {
11082
11639
  deleteResult.success,
11083
11640
  { sessionId: session.sessionId }
11084
11641
  );
11085
- this.sessions.delete(session.sessionId);
11086
11642
  return deleteResult;
11087
11643
  } catch (error) {
11088
11644
  logError("Error deleting session:", error);
@@ -11093,27 +11649,6 @@ var _AgentBay = class _AgentBay {
11093
11649
  };
11094
11650
  }
11095
11651
  }
11096
- /**
11097
- * Remove a session from the internal session cache.
11098
- *
11099
- * This is an internal utility method that removes a session reference from the AgentBay client's
11100
- * session cache without actually deleting the session from the cloud. Use this when you need to
11101
- * clean up local references to a session that was deleted externally or no longer needed.
11102
- *
11103
- * @param sessionId - The ID of the session to remove from the cache.
11104
- *
11105
- * @internal
11106
- *
11107
- * @remarks
11108
- * **Note:** This method only removes the session from the local cache. It does not delete the
11109
- * session from the cloud. To delete a session from the cloud, use {@link delete} or
11110
- * {@link Session.delete}.
11111
- *
11112
- * @see {@link delete}, {@link Session.delete}
11113
- */
11114
- removeSession(sessionId) {
11115
- this.sessions.delete(sessionId);
11116
- }
11117
11652
  /**
11118
11653
  * Get session information by session ID.
11119
11654
  *
@@ -11156,6 +11691,18 @@ var _AgentBay = class _AgentBay {
11156
11691
  errorMessage: ""
11157
11692
  };
11158
11693
  if (body?.data) {
11694
+ const contextsList = body.data.contexts || [];
11695
+ const contexts = [];
11696
+ if (Array.isArray(contextsList)) {
11697
+ for (const ctx of contextsList) {
11698
+ if (ctx && typeof ctx === "object" && ctx.name && ctx.id) {
11699
+ contexts.push({
11700
+ name: ctx.name,
11701
+ id: ctx.id
11702
+ });
11703
+ }
11704
+ }
11705
+ }
11159
11706
  result.data = {
11160
11707
  appInstanceId: body.data.appInstanceId || "",
11161
11708
  resourceId: body.data.resourceId || "",
@@ -11165,7 +11712,9 @@ var _AgentBay = class _AgentBay {
11165
11712
  networkInterfaceIp: body.data.networkInterfaceIp || "",
11166
11713
  token: body.data.token || "",
11167
11714
  vpcResource: body.data.vpcResource || false,
11168
- resourceUrl: body.data.resourceUrl || ""
11715
+ resourceUrl: body.data.resourceUrl || "",
11716
+ status: body.data.status || "",
11717
+ contexts: contexts.length > 0 ? contexts : void 0
11169
11718
  };
11170
11719
  logAPIResponseWithDetails(
11171
11720
  "GetSession",
@@ -11249,13 +11798,40 @@ var _AgentBay = class _AgentBay {
11249
11798
  session.token = getResult.data.token;
11250
11799
  session.resourceUrl = getResult.data.resourceUrl;
11251
11800
  }
11252
- const contextName = `file-transfer-context-${Date.now()}`;
11253
- const contextResult = await this.context.get(contextName, true);
11254
- if (contextResult.success && contextResult.context) {
11255
- session.fileTransferContextId = contextResult.context.id;
11256
- logInfo(`\u{1F4C1} Created file transfer context for recovered session: ${contextResult.context.id}`);
11801
+ if (getResult.data && getResult.data.contexts && getResult.data.contexts.length > 0) {
11802
+ const contexts = getResult.data.contexts;
11803
+ const fileTransferContexts = contexts.filter(
11804
+ (ctx) => ctx.name && ctx.name.startsWith("file-transfer-context-")
11805
+ );
11806
+ if (fileTransferContexts.length === 0) {
11807
+ const availableContexts = contexts.map((ctx) => ctx.name || "unknown");
11808
+ logWarn(
11809
+ `\u26A0\uFE0F No file-transfer-context- found in contexts list for session ${sessionId}. Available contexts: ${availableContexts.join(", ")}`
11810
+ );
11811
+ session.fileTransferContextId = null;
11812
+ } else if (fileTransferContexts.length === 1) {
11813
+ const contextId = fileTransferContexts[0].id;
11814
+ if (contextId) {
11815
+ session.fileTransferContextId = contextId;
11816
+ logInfo(`\u{1F4C1} Found file transfer context for recovered session: ${contextId}`);
11817
+ } else {
11818
+ logWarn(
11819
+ `\u26A0\uFE0F File transfer context found but missing 'id' field: ${JSON.stringify(fileTransferContexts[0])}`
11820
+ );
11821
+ session.fileTransferContextId = null;
11822
+ }
11823
+ } else {
11824
+ const contextNames = fileTransferContexts.map((ctx) => ctx.name || "unknown");
11825
+ logWarn(
11826
+ `\u26A0\uFE0F Multiple file-transfer-context- found in contexts list for session ${sessionId}. Found ${fileTransferContexts.length} contexts: ${contextNames.join(", ")}. Not setting fileTransferContextId.`
11827
+ );
11828
+ session.fileTransferContextId = null;
11829
+ }
11257
11830
  } else {
11258
- logError(`\u26A0\uFE0F Failed to create file transfer context for recovered session: ${contextResult.errorMessage || "Unknown error"}`);
11831
+ logWarn(
11832
+ `\u26A0\uFE0F No contexts list found in GetSession response for session ${sessionId}. fileTransferContextId will remain null.`
11833
+ );
11834
+ session.fileTransferContextId = null;
11259
11835
  }
11260
11836
  return {
11261
11837
  requestId: getResult.requestId,
@@ -11294,6 +11870,88 @@ var _AgentBay = class _AgentBay {
11294
11870
  getAPIKey() {
11295
11871
  return this.apiKey;
11296
11872
  }
11873
+ /**
11874
+ * Asynchronously pause a session, putting it into a dormant state.
11875
+ *
11876
+ * This method directly calls the PauseSessionAsync API without waiting for the session
11877
+ * to reach the PAUSED state.
11878
+ *
11879
+ * @param session - The session to pause.
11880
+ * @param timeout - Timeout in seconds to wait for the session to pause. Defaults to 600 seconds.
11881
+ * @param pollInterval - Interval in seconds between status polls. Defaults to 2.0 seconds.
11882
+ * @returns SessionPauseResult indicating success or failure and request ID
11883
+ *
11884
+ * @example
11885
+ * ```typescript
11886
+ * const agentBay = new AgentBay({ apiKey: 'your_api_key' });
11887
+ * const session = (await agentBay.create()).session;
11888
+ * const pauseResult = await agentBay.pauseAsync(session);
11889
+ * await agentBay.resumeAsync(session);
11890
+ * await session.delete();
11891
+ * ```
11892
+ *
11893
+ * @remarks
11894
+ * **Behavior:**
11895
+ * - This method does not wait for the session to reach the PAUSED state
11896
+ * - It only submits the pause request to the API
11897
+ * - The session state transitions from RUNNING -> PAUSING -> PAUSED
11898
+ * - Paused sessions consume fewer resources but maintain their state
11899
+ *
11900
+ * @see {@link resumeAsync}, {@link Session.pauseAsync}
11901
+ */
11902
+ async pauseAsync(session, timeout = 600, pollInterval = 2) {
11903
+ try {
11904
+ return await session.pauseAsync(timeout, pollInterval);
11905
+ } catch (error) {
11906
+ logError("Error calling pause session async:", error);
11907
+ return {
11908
+ requestId: "",
11909
+ success: false,
11910
+ errorMessage: `Failed to pause session ${session.sessionId}: ${error}`
11911
+ };
11912
+ }
11913
+ }
11914
+ /**
11915
+ * Asynchronously resume a session from a paused state.
11916
+ *
11917
+ * This method directly calls the ResumeSessionAsync API without waiting for the session
11918
+ * to reach the RUNNING state.
11919
+ *
11920
+ * @param session - The session to resume.
11921
+ * @param timeout - Timeout in seconds to wait for the session to resume. Defaults to 600 seconds.
11922
+ * @param pollInterval - Interval in seconds between status polls. Defaults to 2.0 seconds.
11923
+ * @returns SessionResumeResult indicating success or failure and request ID
11924
+ *
11925
+ * @example
11926
+ * ```typescript
11927
+ * const agentBay = new AgentBay({ apiKey: 'your_api_key' });
11928
+ * const session = (await agentBay.create()).session;
11929
+ * await agentBay.pauseAsync(session);
11930
+ * const resumeResult = await agentBay.resumeAsync(session);
11931
+ * await session.delete();
11932
+ * ```
11933
+ *
11934
+ * @remarks
11935
+ * **Behavior:**
11936
+ * - This method does not wait for the session to reach the RUNNING state
11937
+ * - It only submits the resume request to the API
11938
+ * - The session state transitions from PAUSED -> RESUMING -> RUNNING
11939
+ * - Only sessions in PAUSED state can be resumed
11940
+ *
11941
+ * @see {@link pauseAsync}, {@link Session.resumeAsync}
11942
+ */
11943
+ async resumeAsync(session, timeout = 600, pollInterval = 2) {
11944
+ try {
11945
+ return await session.resumeAsync(timeout, pollInterval);
11946
+ } catch (error) {
11947
+ logError("Error calling resume session async:", error);
11948
+ return {
11949
+ requestId: "",
11950
+ success: false,
11951
+ errorMessage: `Failed to resume session ${session.sessionId}: ${error}`
11952
+ };
11953
+ }
11954
+ }
11297
11955
  };
11298
11956
  __name(_AgentBay, "AgentBay");
11299
11957
  var AgentBay = _AgentBay;
@@ -11303,8 +11961,8 @@ init_esm_shims();
11303
11961
 
11304
11962
  // src/extension.ts
11305
11963
  init_esm_shims();
11306
- import * as fs5 from "fs";
11307
- import * as path5 from "path";
11964
+ import * as fs6 from "fs";
11965
+ import * as path6 from "path";
11308
11966
  import * as crypto from "crypto";
11309
11967
  import fetch3 from "node-fetch";
11310
11968
  var EXTENSIONS_BASE_PATH = "/tmp/extensions";
@@ -11456,7 +12114,7 @@ var _ExtensionsService = class _ExtensionsService {
11456
12114
  throw new AgentBayError(`Failed to get upload URL: ${urlResult.url || "No URL returned"}`);
11457
12115
  }
11458
12116
  const preSignedUrl = urlResult.url;
11459
- const fileBuffer = fs5.readFileSync(localPath);
12117
+ const fileBuffer = fs6.readFileSync(localPath);
11460
12118
  const response = await fetch3(preSignedUrl, {
11461
12119
  method: "PUT",
11462
12120
  body: fileBuffer
@@ -11539,15 +12197,15 @@ var _ExtensionsService = class _ExtensionsService {
11539
12197
  */
11540
12198
  async create(localPath) {
11541
12199
  await this._ensureInitialized();
11542
- if (!fs5.existsSync(localPath)) {
12200
+ if (!fs6.existsSync(localPath)) {
11543
12201
  throw new Error(`The specified local file was not found: ${localPath}`);
11544
12202
  }
11545
- const fileExtension = path5.extname(localPath).toLowerCase();
12203
+ const fileExtension = path6.extname(localPath).toLowerCase();
11546
12204
  if (fileExtension !== ".zip") {
11547
12205
  throw new Error(`Unsupported plugin format '${fileExtension}'. Only ZIP format (.zip) is supported.`);
11548
12206
  }
11549
12207
  const extensionId = `ext_${crypto.randomBytes(16).toString("hex")}${fileExtension}`;
11550
- const extensionName = path5.basename(localPath);
12208
+ const extensionName = path6.basename(localPath);
11551
12209
  const remotePath = `${EXTENSIONS_BASE_PATH}/${extensionId}`;
11552
12210
  await this._uploadToCloud(localPath, remotePath);
11553
12211
  return new Extension(extensionId, extensionName);
@@ -11574,7 +12232,7 @@ var _ExtensionsService = class _ExtensionsService {
11574
12232
  */
11575
12233
  async update(extensionId, newLocalPath) {
11576
12234
  await this._ensureInitialized();
11577
- if (!fs5.existsSync(newLocalPath)) {
12235
+ if (!fs6.existsSync(newLocalPath)) {
11578
12236
  throw new Error(`The specified new local file was not found: ${newLocalPath}`);
11579
12237
  }
11580
12238
  const existingExtensions = await this.list();
@@ -11584,7 +12242,7 @@ var _ExtensionsService = class _ExtensionsService {
11584
12242
  }
11585
12243
  const remotePath = `${EXTENSIONS_BASE_PATH}/${extensionId}`;
11586
12244
  await this._uploadToCloud(newLocalPath, remotePath);
11587
- return new Extension(extensionId, path5.basename(newLocalPath));
12245
+ return new Extension(extensionId, path6.basename(newLocalPath));
11588
12246
  }
11589
12247
  /**
11590
12248
  * Gets detailed information about a specific browser extension.
@@ -11709,21 +12367,20 @@ var _ExtensionsService = class _ExtensionsService {
11709
12367
  __name(_ExtensionsService, "ExtensionsService");
11710
12368
  var ExtensionsService = _ExtensionsService;
11711
12369
 
11712
- // src/types/index.ts
11713
- init_esm_shims();
11714
-
11715
- // src/types/list-session-params.ts
12370
+ // src/mobile-simulate.ts
11716
12371
  init_esm_shims();
11717
- function createListSessionParams(labels = {}) {
11718
- return {
11719
- maxResults: 10,
11720
- labels
11721
- };
11722
- }
11723
- __name(createListSessionParams, "createListSessionParams");
12372
+ import fetch4 from "node-fetch";
11724
12373
 
11725
12374
  // src/types/extra-configs.ts
11726
12375
  init_esm_shims();
12376
+ var MobileSimulateMode = /* @__PURE__ */ ((MobileSimulateMode2) => {
12377
+ MobileSimulateMode2["PropertiesOnly"] = "PropertiesOnly";
12378
+ MobileSimulateMode2["SensorsOnly"] = "SensorsOnly";
12379
+ MobileSimulateMode2["PackagesOnly"] = "PackagesOnly";
12380
+ MobileSimulateMode2["ServicesOnly"] = "ServicesOnly";
12381
+ MobileSimulateMode2["All"] = "All";
12382
+ return MobileSimulateMode2;
12383
+ })(MobileSimulateMode || {});
11727
12384
  function extraConfigsToJSON(extraConfigs) {
11728
12385
  if (!extraConfigs) {
11729
12386
  return "";
@@ -11759,6 +12416,21 @@ function validateAppManagerRule(rule) {
11759
12416
  }
11760
12417
  }
11761
12418
  __name(validateAppManagerRule, "validateAppManagerRule");
12419
+ function validateMobileSimulateConfig(config) {
12420
+ if (typeof config.simulate !== "boolean") {
12421
+ throw new Error("MobileSimulateConfig simulate must be a boolean");
12422
+ }
12423
+ if (config.simulateMode !== void 0) {
12424
+ const validModes = Object.values(MobileSimulateMode);
12425
+ if (!validModes.includes(config.simulateMode)) {
12426
+ throw new Error(`Invalid simulateMode: ${config.simulateMode}. Must be one of: ${validModes.join(", ")}`);
12427
+ }
12428
+ }
12429
+ if (config.simulatedContextId !== void 0 && typeof config.simulatedContextId !== "string") {
12430
+ throw new Error("MobileSimulateConfig simulatedContextId must be a string");
12431
+ }
12432
+ }
12433
+ __name(validateMobileSimulateConfig, "validateMobileSimulateConfig");
11762
12434
  function validateMobileExtraConfig(config) {
11763
12435
  if (typeof config.lockResolution !== "boolean") {
11764
12436
  throw new Error("MobileExtraConfig lockResolution must be a boolean");
@@ -11779,6 +12451,9 @@ function validateMobileExtraConfig(config) {
11779
12451
  }
11780
12452
  }
11781
12453
  }
12454
+ if (config.simulateConfig) {
12455
+ validateMobileSimulateConfig(config.simulateConfig);
12456
+ }
11782
12457
  }
11783
12458
  __name(validateMobileExtraConfig, "validateMobileExtraConfig");
11784
12459
  function validateExtraConfigs(extraConfigs) {
@@ -11788,6 +12463,300 @@ function validateExtraConfigs(extraConfigs) {
11788
12463
  }
11789
12464
  __name(validateExtraConfigs, "validateExtraConfigs");
11790
12465
 
12466
+ // src/mobile-simulate.ts
12467
+ var MOBILE_INFO_DEFAULT_PATH = "/data/agentbay_mobile_info";
12468
+ var MOBILE_INFO_SUB_PATH = "/agentbay_mobile_info";
12469
+ var MOBILE_INFO_FILE_NAME = "dev_info.json";
12470
+ var _MobileSimulateService = class _MobileSimulateService {
12471
+ /**
12472
+ * Initialize the MobileSimulateService.
12473
+ *
12474
+ * @param agentBay - The AgentBay instance.
12475
+ */
12476
+ constructor(agentBay) {
12477
+ this.simulateEnable = false;
12478
+ this.simulateMode = "PropertiesOnly" /* PropertiesOnly */;
12479
+ this.useInternalContext = true;
12480
+ if (!agentBay) {
12481
+ throw new Error("agentBay is required");
12482
+ }
12483
+ if (!agentBay.context) {
12484
+ throw new Error("agentBay.context is required");
12485
+ }
12486
+ this.agentBay = agentBay;
12487
+ this.contextService = agentBay.context;
12488
+ }
12489
+ /**
12490
+ * Set the simulate enable flag.
12491
+ *
12492
+ * @param enable - The simulate feature enable flag.
12493
+ */
12494
+ setSimulateEnable(enable) {
12495
+ this.simulateEnable = enable;
12496
+ }
12497
+ /**
12498
+ * Get the simulate enable flag.
12499
+ *
12500
+ * @returns The simulate feature enable flag.
12501
+ */
12502
+ getSimulateEnable() {
12503
+ return this.simulateEnable;
12504
+ }
12505
+ /**
12506
+ * Set the simulate mode.
12507
+ *
12508
+ * @param mode - The simulate mode.
12509
+ * - PropertiesOnly: Simulate only device properties.
12510
+ * - SensorsOnly: Simulate only device sensors.
12511
+ * - PackagesOnly: Simulate only installed packages.
12512
+ * - ServicesOnly: Simulate only system services.
12513
+ * - All: Simulate all aspects of the device.
12514
+ */
12515
+ setSimulateMode(mode) {
12516
+ this.simulateMode = mode;
12517
+ }
12518
+ /**
12519
+ * Get the simulate mode.
12520
+ *
12521
+ * @returns The simulate mode.
12522
+ */
12523
+ getSimulateMode() {
12524
+ return this.simulateMode;
12525
+ }
12526
+ /**
12527
+ * Set a previously saved simulate context id. Please make sure the context id is provided by MobileSimulateService
12528
+ * but not user side created context.
12529
+ *
12530
+ * @param contextId - The context ID of the previously saved mobile simulate context.
12531
+ */
12532
+ setSimulateContextId(contextId) {
12533
+ this.contextId = contextId;
12534
+ logInfo(`set simulate context id = ${contextId}`);
12535
+ this.updateContext(true, contextId, void 0);
12536
+ }
12537
+ /**
12538
+ * Get the simulate context id.
12539
+ *
12540
+ * @returns The context ID of the mobile simulate context.
12541
+ */
12542
+ getSimulateContextId() {
12543
+ return this.contextId;
12544
+ }
12545
+ /**
12546
+ * Get the simulate config.
12547
+ *
12548
+ * @returns The simulate config.
12549
+ * - simulate: The simulate feature enable flag.
12550
+ * - simulatePath: The path of the mobile dev info file.
12551
+ * - simulateMode: The simulate mode.
12552
+ * - simulatedContextId: The context ID of the mobile info.
12553
+ */
12554
+ getSimulateConfig() {
12555
+ const simulatedContextId = this.useInternalContext ? this.contextId : void 0;
12556
+ return {
12557
+ simulate: this.simulateEnable,
12558
+ simulatePath: this.mobileDevInfoPath,
12559
+ simulateMode: this.simulateMode,
12560
+ simulatedContextId
12561
+ };
12562
+ }
12563
+ /**
12564
+ * Check if the mobile dev info file exists in one context sync. (Only for user provided context sync)
12565
+ *
12566
+ * @param contextSync - The context sync to check.
12567
+ * @returns True if the mobile dev info file exists, False otherwise.
12568
+ * @throws Error if context_sync is not provided or context_sync.context_id or context_sync.path is not provided.
12569
+ *
12570
+ * @remarks
12571
+ * This method can only be used when mobile simulate context sync is managed by user side. For internal mobile simulate
12572
+ * context sync, this method will not work.
12573
+ */
12574
+ async hasMobileInfo(contextSync) {
12575
+ if (!contextSync) {
12576
+ throw new Error("contextSync is required");
12577
+ }
12578
+ if (!contextSync.contextId) {
12579
+ throw new Error("contextSync.contextId is required");
12580
+ }
12581
+ if (!contextSync.path) {
12582
+ throw new Error("contextSync.path is required");
12583
+ }
12584
+ const mobileDevInfoPath = contextSync.path + MOBILE_INFO_SUB_PATH + "/";
12585
+ logDebug(`hasMobileInfo: context_id = ${contextSync.contextId}, mobile_dev_info_path = ${mobileDevInfoPath}`);
12586
+ const res = await this.contextService.listFiles(contextSync.contextId, mobileDevInfoPath, 1, 50);
12587
+ let foundDevInfo = false;
12588
+ if (res.success) {
12589
+ for (const entry of res.entries) {
12590
+ if (entry.fileName === MOBILE_INFO_FILE_NAME) {
12591
+ foundDevInfo = true;
12592
+ break;
12593
+ }
12594
+ }
12595
+ } else {
12596
+ logError(`failed to list files: ${res.errorMessage}`);
12597
+ return false;
12598
+ }
12599
+ if (foundDevInfo) {
12600
+ logInfo("mobile dev info already exists");
12601
+ this.updateContext(false, contextSync.contextId, contextSync);
12602
+ return true;
12603
+ } else {
12604
+ logInfo("mobile dev info does not exist");
12605
+ return false;
12606
+ }
12607
+ }
12608
+ /**
12609
+ * Upload the mobile simulate dev info.
12610
+ *
12611
+ * @param mobileDevInfoContent - The mobile simulate dev info content to upload.
12612
+ * @param contextSync - Optional
12613
+ * - If not provided, a new context sync will be created for the mobile simulate service and this context id will
12614
+ * be returned by the MobileSimulateUploadResult. User can use this context id to do persistent mobile simulate across sessions.
12615
+ * - If provided, the mobile simulate dev info will be uploaded to the context sync in a specific path.
12616
+ *
12617
+ * @returns The result of the upload operation.
12618
+ *
12619
+ * @throws Error if mobile_dev_info_content is not provided or not a valid JSON string.
12620
+ * @throws Error if context_sync is provided but context_sync.context_id is not provided.
12621
+ *
12622
+ * @remarks
12623
+ * If context_sync is not provided, a new context sync will be created for the mobile simulate.
12624
+ * If context_sync is provided, the mobile simulate dev info will be uploaded to the context sync.
12625
+ * If the mobile simulate dev info already exists in the context sync, the context sync will be updated.
12626
+ * If the mobile simulate dev info does not exist in the context sync, the context sync will be created.
12627
+ * If the upload operation fails, the error message will be returned.
12628
+ */
12629
+ async uploadMobileInfo(mobileDevInfoContent, contextSync) {
12630
+ if (!mobileDevInfoContent) {
12631
+ throw new Error("mobileDevInfoContent is required");
12632
+ }
12633
+ try {
12634
+ JSON.parse(mobileDevInfoContent);
12635
+ } catch (error) {
12636
+ throw new Error("mobileDevInfoContent is not a valid JSON string");
12637
+ }
12638
+ if (!contextSync) {
12639
+ const createdContext = await this.createContextForSimulate();
12640
+ if (!createdContext) {
12641
+ logError("Failed to create context for simulate");
12642
+ return {
12643
+ success: false,
12644
+ errorMessage: "Failed to create context for simulate"
12645
+ };
12646
+ }
12647
+ this.updateContext(true, createdContext.id, void 0);
12648
+ } else {
12649
+ if (!contextSync.contextId) {
12650
+ throw new Error("contextSync.contextId is required");
12651
+ }
12652
+ this.updateContext(false, contextSync.contextId, contextSync);
12653
+ }
12654
+ const uploadPath = `${this.mobileDevInfoPath}/${MOBILE_INFO_FILE_NAME}`;
12655
+ const uploadUrlResult = await this.contextService.getFileUploadUrl(this.contextId, uploadPath);
12656
+ if (!uploadUrlResult.success) {
12657
+ logError(`Failed to get file upload URL: ${uploadUrlResult.errorMessage}`);
12658
+ return {
12659
+ success: false,
12660
+ errorMessage: uploadUrlResult.errorMessage
12661
+ };
12662
+ }
12663
+ logDebug(`upload_url = ${uploadUrlResult.url}`);
12664
+ try {
12665
+ const encoder = new TextEncoder();
12666
+ const uint8Array = encoder.encode(mobileDevInfoContent);
12667
+ const response = await fetch4(uploadUrlResult.url, {
12668
+ method: "PUT",
12669
+ body: uint8Array
12670
+ });
12671
+ if (!response.ok) {
12672
+ throw new Error(`Upload failed with status ${response.status}: ${response.statusText}`);
12673
+ }
12674
+ } catch (error) {
12675
+ const errorMsg = `An error occurred while uploading the file: ${error instanceof Error ? error.message : String(error)}`;
12676
+ logError(errorMsg);
12677
+ return {
12678
+ success: false,
12679
+ errorMessage: errorMsg
12680
+ };
12681
+ }
12682
+ logInfo("mobile dev info uploaded successfully");
12683
+ return {
12684
+ success: true,
12685
+ mobileSimulateContextId: this.contextId
12686
+ };
12687
+ }
12688
+ /**
12689
+ * Update the context information.
12690
+ *
12691
+ * @param isInternal - Whether this is an internal context.
12692
+ * @param contextId - The context ID.
12693
+ * @param contextSync - The context sync (required for external context).
12694
+ */
12695
+ updateContext(isInternal, contextId, contextSync) {
12696
+ if (!isInternal) {
12697
+ if (!contextSync) {
12698
+ throw new Error("contextSync is required for external context");
12699
+ }
12700
+ if (contextSync.policy?.bwList?.whiteLists) {
12701
+ const exists = contextSync.policy.bwList.whiteLists.some(
12702
+ (whiteList) => whiteList.path === MOBILE_INFO_SUB_PATH
12703
+ );
12704
+ if (!exists) {
12705
+ contextSync.policy.bwList.whiteLists.push({
12706
+ path: MOBILE_INFO_SUB_PATH,
12707
+ excludePaths: []
12708
+ });
12709
+ logInfo(`added mobile_dev_info_path to context_sync.policy.bw_list.white_lists: ${MOBILE_INFO_SUB_PATH}`);
12710
+ }
12711
+ }
12712
+ }
12713
+ this.useInternalContext = isInternal;
12714
+ this.contextId = contextId;
12715
+ this.contextSync = contextSync;
12716
+ if (isInternal) {
12717
+ this.mobileDevInfoPath = MOBILE_INFO_DEFAULT_PATH;
12718
+ } else {
12719
+ this.mobileDevInfoPath = contextSync.path + MOBILE_INFO_SUB_PATH;
12720
+ }
12721
+ logInfo(`updated context, is_internal = ${isInternal}, context_id = ${this.contextId}, mobile_dev_info_path = ${this.mobileDevInfoPath}`);
12722
+ }
12723
+ /**
12724
+ * Create a context for simulate.
12725
+ *
12726
+ * @returns The created context or null if failed.
12727
+ */
12728
+ async createContextForSimulate() {
12729
+ const randomHex = Array.from(
12730
+ { length: 16 },
12731
+ () => Math.floor(Math.random() * 256).toString(16).padStart(2, "0")
12732
+ ).join("");
12733
+ const contextName = `mobile_sim_${randomHex}_${Math.floor(Date.now() / 1e3)}`;
12734
+ const contextResult = await this.contextService.get(contextName, true);
12735
+ if (!contextResult.success || !contextResult.context) {
12736
+ logError(`Failed to create mobile simulate context: ${contextResult.errorMessage}`);
12737
+ return null;
12738
+ }
12739
+ const context = contextResult.context;
12740
+ logInfo(`created mobile simulate context, context_id = ${context.id}, context_name = ${context.name}`);
12741
+ return context;
12742
+ }
12743
+ };
12744
+ __name(_MobileSimulateService, "MobileSimulateService");
12745
+ var MobileSimulateService = _MobileSimulateService;
12746
+
12747
+ // src/types/index.ts
12748
+ init_esm_shims();
12749
+
12750
+ // src/types/list-session-params.ts
12751
+ init_esm_shims();
12752
+ function createListSessionParams(labels = {}) {
12753
+ return {
12754
+ maxResults: 10,
12755
+ labels
12756
+ };
12757
+ }
12758
+ __name(createListSessionParams, "createListSessionParams");
12759
+
11791
12760
  // src/session-params.ts
11792
12761
  init_esm_shims();
11793
12762
  var BROWSER_FINGERPRINT_PERSIST_PATH2 = "/tmp/browser_fingerprint";
@@ -12061,8 +13030,8 @@ var _CreateSessionParams = class _CreateSessionParams {
12061
13030
  /**
12062
13031
  * AddContextSync adds a context sync configuration to the session parameters.
12063
13032
  */
12064
- addContextSync(contextId, path6, policy) {
12065
- const contextSync = new ContextSync(contextId, path6, policy);
13033
+ addContextSync(contextId, path7, policy) {
13034
+ const contextSync = new ContextSync(contextId, path7, policy);
12066
13035
  this.contextSync.push(contextSync);
12067
13036
  return this;
12068
13037
  }
@@ -12273,15 +13242,23 @@ export {
12273
13242
  ListSessionResponseBodyData,
12274
13243
  MOBILE_COMMAND_TEMPLATES,
12275
13244
  Mobile,
13245
+ MobileSimulateMode,
13246
+ MobileSimulateService,
12276
13247
  ModifyContextRequest,
12277
13248
  ModifyContextResponse,
12278
13249
  ModifyContextResponseBody,
12279
13250
  Oss,
12280
13251
  OssError,
13252
+ PauseSessionAsyncRequest,
13253
+ PauseSessionAsyncResponse,
13254
+ PauseSessionAsyncResponseBody,
12281
13255
  RESOLUTION_LOCK_TEMPLATE,
12282
13256
  ReleaseMcpSessionRequest,
12283
13257
  ReleaseMcpSessionResponse,
12284
13258
  ReleaseMcpSessionResponseBody,
13259
+ ResumeSessionAsyncRequest,
13260
+ ResumeSessionAsyncResponse,
13261
+ ResumeSessionAsyncResponseBody,
12285
13262
  SHOW_NAVIGATION_BAR_TEMPLATE,
12286
13263
  Session,
12287
13264
  SessionError,
@@ -12325,7 +13302,8 @@ export {
12325
13302
  setupLogger,
12326
13303
  validateAppManagerRule,
12327
13304
  validateExtraConfigs,
12328
- validateMobileExtraConfig
13305
+ validateMobileExtraConfig,
13306
+ validateMobileSimulateConfig
12329
13307
  };
12330
13308
  //# sourceMappingURL=index.mjs.map
12331
13309