{"version":3,"sources":["/aoneci/runner/work/source/typescript/dist/index.cjs","../node_modules/dotenv/package.json","../node_modules/dotenv/lib/main.js","../node_modules/dotenv/lib/env-options.js","../node_modules/dotenv/lib/cli-options.js","../src/index.ts","../src/version.ts","../src/agent-bay.ts","../node_modules/dotenv/config.js","../src/api/index.ts","../src/api/client.ts","../src/config.ts","../src/context.ts","../src/types/api-response.ts","../src/beta-network.ts","../src/beta-skills.ts","../src/context-sync.ts","../src/session.ts","../src/agent/agent.ts","../node_modules/zod/index.js","../node_modules/zod/v3/external.js","../node_modules/zod/v3/errors.js","../node_modules/zod/v3/locales/en.js","../node_modules/zod/v3/ZodError.js","../node_modules/zod/v3/helpers/util.js","../node_modules/zod/v3/helpers/parseUtil.js","../node_modules/zod/v3/types.js","../node_modules/zod/v3/helpers/errorUtil.js","../node_modules/zod-to-json-schema/dist/esm/index.js","../node_modules/zod-to-json-schema/dist/esm/errorMessages.js","../node_modules/zod-to-json-schema/dist/esm/Options.js","../node_modules/zod-to-json-schema/dist/esm/parseDef.js","../node_modules/zod-to-json-schema/dist/esm/parsers/any.js","../node_modules/zod-to-json-schema/dist/esm/parsers/array.js","../node_modules/zod-to-json-schema/dist/esm/parsers/bigint.js","../node_modules/zod-to-json-schema/dist/esm/parsers/boolean.js","../node_modules/zod-to-json-schema/dist/esm/parsers/branded.js","../node_modules/zod-to-json-schema/dist/esm/parsers/catch.js","../node_modules/zod-to-json-schema/dist/esm/parsers/date.js","../node_modules/zod-to-json-schema/dist/esm/parsers/default.js","../node_modules/zod-to-json-schema/dist/esm/parsers/effects.js","../node_modules/zod-to-json-schema/dist/esm/parsers/enum.js","../node_modules/zod-to-json-schema/dist/esm/parsers/intersection.js","../node_modules/zod-to-json-schema/dist/esm/parsers/literal.js","../node_modules/zod-to-json-schema/dist/esm/parsers/map.js","../node_modules/zod-to-json-schema/dist/esm/parsers/record.js","../node_modules/zod-to-json-schema/dist/esm/parsers/string.js","../node_modules/zod-to-json-schema/dist/esm/parsers/nativeEnum.js","../node_modules/zod-to-json-schema/dist/esm/parsers/never.js","../node_modules/zod-to-json-schema/dist/esm/parsers/null.js","../node_modules/zod-to-json-schema/dist/esm/parsers/nullable.js","../node_modules/zod-to-json-schema/dist/esm/parsers/union.js","../node_modules/zod-to-json-schema/dist/esm/parsers/number.js","../node_modules/zod-to-json-schema/dist/esm/parsers/object.js","../node_modules/zod-to-json-schema/dist/esm/parsers/optional.js","../node_modules/zod-to-json-schema/dist/esm/parsers/pipeline.js","../node_modules/zod-to-json-schema/dist/esm/parsers/promise.js","../node_modules/zod-to-json-schema/dist/esm/parsers/set.js","../node_modules/zod-to-json-schema/dist/esm/parsers/tuple.js","../node_modules/zod-to-json-schema/dist/esm/parsers/undefined.js","../node_modules/zod-to-json-schema/dist/esm/parsers/unknown.js","../node_modules/zod-to-json-schema/dist/esm/parsers/readonly.js","../node_modules/zod-to-json-schema/dist/esm/Refs.js","../node_modules/zod-to-json-schema/dist/esm/zodToJsonSchema.js","../src/browser/index.ts","../src/browser/browser.ts","../src/browser/browser_operator.ts","../src/browser/fingerprint.ts","../src/code/index.ts","../src/code/code.ts","../src/command/command.ts","../src/command/command-templates.ts","../src/computer/index.ts","../src/computer/computer.ts","../src/utils/field-converter.ts","../src/env/env.ts","../src/context-manager.ts","../src/beta-context-mount.ts","../src/filesystem/filesystem.ts","../src/filesystem/file-transfer.ts","../src/git/index.ts","../src/git/git.ts","../src/git/errors.ts","../src/mobile/index.ts","../src/mobile/mobile.ts","../src/oss/index.ts","../src/oss/oss.ts","../src/pty/index.ts","../src/pty/pty.ts","../src/session-params.ts","../src/lifecycle-policy.ts","../src/agent/index.ts","../src/extension.ts","../src/mobile-simulate.ts","../src/types/extra-configs.ts","../src/types/index.ts","../src/types/list-session-params.ts","../src/browser/eval/index.ts","../src/browser/eval/local_page_agent.ts"],"names":["fs","path","crypto","parse","fullResponse","keyFields","context","errorMessage","resolve","elapsed","UploadStrategy","DownloadStrategy","UploadMode","Lifecycle","errorMap","processed","types","x","base","MouseButton","ScrollDirection","BetaContextMountAccessMode","BetaContextMountStrategy","mod","response","BrowserSyncMode","BROWSER_FINGERPRINT_PERSIST_PATH","BROWSER_DATA_PATH","requestId","MobileSimulateMode","join"],"mappings":"AAAA;AACE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACF,wDAA6B;AAC7B;AACE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACF,wDAA6B;AAC7B;AACE;AACA;AACA;AACA;AACA;AACA;AACF,wDAA6B;AAC7B;AACA;AC/KA,IAAA,gBAAA,EAAA,0CAAA;AAAA,EAAA,kCAAA,CAAA,OAAA,EAAA,MAAA,EAAA;AAAA,IAAA,MAAA,CAAA,QAAA,EAAA;AAAA,MACE,IAAA,EAAQ,QAAA;AAAA,MACR,OAAA,EAAW,QAAA;AAAA,MACX,WAAA,EAAe,4CAAA;AAAA,MACf,IAAA,EAAQ,aAAA;AAAA,MACR,KAAA,EAAS,eAAA;AAAA,MACT,OAAA,EAAW;AAAA,QACT,GAAA,EAAK;AAAA,UACH,KAAA,EAAS,iBAAA;AAAA,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A;AAElC,IAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA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;AACpB,IAAA;AACF,EAAA;AAAA;AAAA;AAAA;AAKyD,EAAA;AACX,IAAA;AAGrC,IAAA;AACI,MAAA;AACgC,MAAA;AAC3B,MAAA;AAChB,IAAA;AACF,EAAA;AACF;AAxE0C;AAAnC;AlG+swBgD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA","file":"/aoneci/runner/work/source/typescript/dist/index.cjs","sourcesContent":[null,"{\n  \"name\": \"dotenv\",\n  \"version\": \"16.6.1\",\n  \"description\": \"Loads environment variables from .env file\",\n  \"main\": \"lib/main.js\",\n  \"types\": \"lib/main.d.ts\",\n  \"exports\": {\n    \".\": {\n      \"types\": \"./lib/main.d.ts\",\n      \"require\": \"./lib/main.js\",\n      \"default\": \"./lib/main.js\"\n    },\n    \"./config\": \"./config.js\",\n    \"./config.js\": \"./config.js\",\n    \"./lib/env-options\": \"./lib/env-options.js\",\n    \"./lib/env-options.js\": \"./lib/env-options.js\",\n    \"./lib/cli-options\": \"./lib/cli-options.js\",\n    \"./lib/cli-options.js\": \"./lib/cli-options.js\",\n    \"./package.json\": \"./package.json\"\n  },\n  \"scripts\": {\n    \"dts-check\": \"tsc --project tests/types/tsconfig.json\",\n    \"lint\": \"standard\",\n    \"pretest\": \"npm run lint && npm run dts-check\",\n    \"test\": \"tap run --allow-empty-coverage --disable-coverage --timeout=60000\",\n    \"test:coverage\": \"tap run --show-full-coverage --timeout=60000 --coverage-report=text --coverage-report=lcov\",\n    \"prerelease\": \"npm test\",\n    \"release\": \"standard-version\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git://github.com/motdotla/dotenv.git\"\n  },\n  \"homepage\": \"https://github.com/motdotla/dotenv#readme\",\n  \"funding\": \"https://dotenvx.com\",\n  \"keywords\": [\n    \"dotenv\",\n    \"env\",\n    \".env\",\n    \"environment\",\n    \"variables\",\n    \"config\",\n    \"settings\"\n  ],\n  \"readmeFilename\": \"README.md\",\n  \"license\": \"BSD-2-Clause\",\n  \"devDependencies\": {\n    \"@types/node\": \"^18.11.3\",\n    \"decache\": \"^4.6.2\",\n    \"sinon\": \"^14.0.1\",\n    \"standard\": \"^17.0.0\",\n    \"standard-version\": \"^9.5.0\",\n    \"tap\": \"^19.2.0\",\n    \"typescript\": \"^4.8.4\"\n  },\n  \"engines\": {\n    \"node\": \">=12\"\n  },\n  \"browser\": {\n    \"fs\": false\n  }\n}\n","const fs = require('fs')\nconst path = require('path')\nconst os = require('os')\nconst crypto = require('crypto')\nconst packageJson = require('../package.json')\n\nconst version = packageJson.version\n\nconst LINE = /(?:^|^)\\s*(?:export\\s+)?([\\w.-]+)(?:\\s*=\\s*?|:\\s+?)(\\s*'(?:\\\\'|[^'])*'|\\s*\"(?:\\\\\"|[^\"])*\"|\\s*`(?:\\\\`|[^`])*`|[^#\\r\\n]+)?\\s*(?:#.*)?(?:$|$)/mg\n\n// Parse src into an Object\nfunction parse (src) {\n  const obj = {}\n\n  // Convert buffer to string\n  let lines = src.toString()\n\n  // Convert line breaks to same format\n  lines = lines.replace(/\\r\\n?/mg, '\\n')\n\n  let match\n  while ((match = LINE.exec(lines)) != null) {\n    const key = match[1]\n\n    // Default undefined or null to empty string\n    let value = (match[2] || '')\n\n    // Remove whitespace\n    value = value.trim()\n\n    // Check if double quoted\n    const maybeQuote = value[0]\n\n    // Remove surrounding quotes\n    value = value.replace(/^(['\"`])([\\s\\S]*)\\1$/mg, '$2')\n\n    // Expand newlines if double quoted\n    if (maybeQuote === '\"') {\n      value = value.replace(/\\\\n/g, '\\n')\n      value = value.replace(/\\\\r/g, '\\r')\n    }\n\n    // Add to object\n    obj[key] = value\n  }\n\n  return obj\n}\n\nfunction _parseVault (options) {\n  options = options || {}\n\n  const vaultPath = _vaultPath(options)\n  options.path = vaultPath // parse .env.vault\n  const result = DotenvModule.configDotenv(options)\n  if (!result.parsed) {\n    const err = new Error(`MISSING_DATA: Cannot parse ${vaultPath} for an unknown reason`)\n    err.code = 'MISSING_DATA'\n    throw err\n  }\n\n  // handle scenario for comma separated keys - for use with key rotation\n  // example: DOTENV_KEY=\"dotenv://:key_1234@dotenvx.com/vault/.env.vault?environment=prod,dotenv://:key_7890@dotenvx.com/vault/.env.vault?environment=prod\"\n  const keys = _dotenvKey(options).split(',')\n  const length = keys.length\n\n  let decrypted\n  for (let i = 0; i < length; i++) {\n    try {\n      // Get full key\n      const key = keys[i].trim()\n\n      // Get instructions for decrypt\n      const attrs = _instructions(result, key)\n\n      // Decrypt\n      decrypted = DotenvModule.decrypt(attrs.ciphertext, attrs.key)\n\n      break\n    } catch (error) {\n      // last key\n      if (i + 1 >= length) {\n        throw error\n      }\n      // try next key\n    }\n  }\n\n  // Parse decrypted .env string\n  return DotenvModule.parse(decrypted)\n}\n\nfunction _warn (message) {\n  console.log(`[dotenv@${version}][WARN] ${message}`)\n}\n\nfunction _debug (message) {\n  console.log(`[dotenv@${version}][DEBUG] ${message}`)\n}\n\nfunction _log (message) {\n  console.log(`[dotenv@${version}] ${message}`)\n}\n\nfunction _dotenvKey (options) {\n  // prioritize developer directly setting options.DOTENV_KEY\n  if (options && options.DOTENV_KEY && options.DOTENV_KEY.length > 0) {\n    return options.DOTENV_KEY\n  }\n\n  // secondary infra already contains a DOTENV_KEY environment variable\n  if (process.env.DOTENV_KEY && process.env.DOTENV_KEY.length > 0) {\n    return process.env.DOTENV_KEY\n  }\n\n  // fallback to empty string\n  return ''\n}\n\nfunction _instructions (result, dotenvKey) {\n  // Parse DOTENV_KEY. Format is a URI\n  let uri\n  try {\n    uri = new URL(dotenvKey)\n  } catch (error) {\n    if (error.code === 'ERR_INVALID_URL') {\n      const err = new Error('INVALID_DOTENV_KEY: Wrong format. Must be in valid uri format like dotenv://:key_1234@dotenvx.com/vault/.env.vault?environment=development')\n      err.code = 'INVALID_DOTENV_KEY'\n      throw err\n    }\n\n    throw error\n  }\n\n  // Get decrypt key\n  const key = uri.password\n  if (!key) {\n    const err = new Error('INVALID_DOTENV_KEY: Missing key part')\n    err.code = 'INVALID_DOTENV_KEY'\n    throw err\n  }\n\n  // Get environment\n  const environment = uri.searchParams.get('environment')\n  if (!environment) {\n    const err = new Error('INVALID_DOTENV_KEY: Missing environment part')\n    err.code = 'INVALID_DOTENV_KEY'\n    throw err\n  }\n\n  // Get ciphertext payload\n  const environmentKey = `DOTENV_VAULT_${environment.toUpperCase()}`\n  const ciphertext = result.parsed[environmentKey] // DOTENV_VAULT_PRODUCTION\n  if (!ciphertext) {\n    const err = new Error(`NOT_FOUND_DOTENV_ENVIRONMENT: Cannot locate environment ${environmentKey} in your .env.vault file.`)\n    err.code = 'NOT_FOUND_DOTENV_ENVIRONMENT'\n    throw err\n  }\n\n  return { ciphertext, key }\n}\n\nfunction _vaultPath (options) {\n  let possibleVaultPath = null\n\n  if (options && options.path && options.path.length > 0) {\n    if (Array.isArray(options.path)) {\n      for (const filepath of options.path) {\n        if (fs.existsSync(filepath)) {\n          possibleVaultPath = filepath.endsWith('.vault') ? filepath : `${filepath}.vault`\n        }\n      }\n    } else {\n      possibleVaultPath = options.path.endsWith('.vault') ? options.path : `${options.path}.vault`\n    }\n  } else {\n    possibleVaultPath = path.resolve(process.cwd(), '.env.vault')\n  }\n\n  if (fs.existsSync(possibleVaultPath)) {\n    return possibleVaultPath\n  }\n\n  return null\n}\n\nfunction _resolveHome (envPath) {\n  return envPath[0] === '~' ? path.join(os.homedir(), envPath.slice(1)) : envPath\n}\n\nfunction _configVault (options) {\n  const debug = Boolean(options && options.debug)\n  const quiet = options && 'quiet' in options ? options.quiet : true\n\n  if (debug || !quiet) {\n    _log('Loading env from encrypted .env.vault')\n  }\n\n  const parsed = DotenvModule._parseVault(options)\n\n  let processEnv = process.env\n  if (options && options.processEnv != null) {\n    processEnv = options.processEnv\n  }\n\n  DotenvModule.populate(processEnv, parsed, options)\n\n  return { parsed }\n}\n\nfunction configDotenv (options) {\n  const dotenvPath = path.resolve(process.cwd(), '.env')\n  let encoding = 'utf8'\n  const debug = Boolean(options && options.debug)\n  const quiet = options && 'quiet' in options ? options.quiet : true\n\n  if (options && options.encoding) {\n    encoding = options.encoding\n  } else {\n    if (debug) {\n      _debug('No encoding is specified. UTF-8 is used by default')\n    }\n  }\n\n  let optionPaths = [dotenvPath] // default, look for .env\n  if (options && options.path) {\n    if (!Array.isArray(options.path)) {\n      optionPaths = [_resolveHome(options.path)]\n    } else {\n      optionPaths = [] // reset default\n      for (const filepath of options.path) {\n        optionPaths.push(_resolveHome(filepath))\n      }\n    }\n  }\n\n  // Build the parsed data in a temporary object (because we need to return it).  Once we have the final\n  // parsed data, we will combine it with process.env (or options.processEnv if provided).\n  let lastError\n  const parsedAll = {}\n  for (const path of optionPaths) {\n    try {\n      // Specifying an encoding returns a string instead of a buffer\n      const parsed = DotenvModule.parse(fs.readFileSync(path, { encoding }))\n\n      DotenvModule.populate(parsedAll, parsed, options)\n    } catch (e) {\n      if (debug) {\n        _debug(`Failed to load ${path} ${e.message}`)\n      }\n      lastError = e\n    }\n  }\n\n  let processEnv = process.env\n  if (options && options.processEnv != null) {\n    processEnv = options.processEnv\n  }\n\n  DotenvModule.populate(processEnv, parsedAll, options)\n\n  if (debug || !quiet) {\n    const keysCount = Object.keys(parsedAll).length\n    const shortPaths = []\n    for (const filePath of optionPaths) {\n      try {\n        const relative = path.relative(process.cwd(), filePath)\n        shortPaths.push(relative)\n      } catch (e) {\n        if (debug) {\n          _debug(`Failed to load ${filePath} ${e.message}`)\n        }\n        lastError = e\n      }\n    }\n\n    _log(`injecting env (${keysCount}) from ${shortPaths.join(',')}`)\n  }\n\n  if (lastError) {\n    return { parsed: parsedAll, error: lastError }\n  } else {\n    return { parsed: parsedAll }\n  }\n}\n\n// Populates process.env from .env file\nfunction config (options) {\n  // fallback to original dotenv if DOTENV_KEY is not set\n  if (_dotenvKey(options).length === 0) {\n    return DotenvModule.configDotenv(options)\n  }\n\n  const vaultPath = _vaultPath(options)\n\n  // dotenvKey exists but .env.vault file does not exist\n  if (!vaultPath) {\n    _warn(`You set DOTENV_KEY but you are missing a .env.vault file at ${vaultPath}. Did you forget to build it?`)\n\n    return DotenvModule.configDotenv(options)\n  }\n\n  return DotenvModule._configVault(options)\n}\n\nfunction decrypt (encrypted, keyStr) {\n  const key = Buffer.from(keyStr.slice(-64), 'hex')\n  let ciphertext = Buffer.from(encrypted, 'base64')\n\n  const nonce = ciphertext.subarray(0, 12)\n  const authTag = ciphertext.subarray(-16)\n  ciphertext = ciphertext.subarray(12, -16)\n\n  try {\n    const aesgcm = crypto.createDecipheriv('aes-256-gcm', key, nonce)\n    aesgcm.setAuthTag(authTag)\n    return `${aesgcm.update(ciphertext)}${aesgcm.final()}`\n  } catch (error) {\n    const isRange = error instanceof RangeError\n    const invalidKeyLength = error.message === 'Invalid key length'\n    const decryptionFailed = error.message === 'Unsupported state or unable to authenticate data'\n\n    if (isRange || invalidKeyLength) {\n      const err = new Error('INVALID_DOTENV_KEY: It must be 64 characters long (or more)')\n      err.code = 'INVALID_DOTENV_KEY'\n      throw err\n    } else if (decryptionFailed) {\n      const err = new Error('DECRYPTION_FAILED: Please check your DOTENV_KEY')\n      err.code = 'DECRYPTION_FAILED'\n      throw err\n    } else {\n      throw error\n    }\n  }\n}\n\n// Populate process.env with parsed values\nfunction populate (processEnv, parsed, options = {}) {\n  const debug = Boolean(options && options.debug)\n  const override = Boolean(options && options.override)\n\n  if (typeof parsed !== 'object') {\n    const err = new Error('OBJECT_REQUIRED: Please check the processEnv argument being passed to populate')\n    err.code = 'OBJECT_REQUIRED'\n    throw err\n  }\n\n  // Set process.env\n  for (const key of Object.keys(parsed)) {\n    if (Object.prototype.hasOwnProperty.call(processEnv, key)) {\n      if (override === true) {\n        processEnv[key] = parsed[key]\n      }\n\n      if (debug) {\n        if (override === true) {\n          _debug(`\"${key}\" is already defined and WAS overwritten`)\n        } else {\n          _debug(`\"${key}\" is already defined and was NOT overwritten`)\n        }\n      }\n    } else {\n      processEnv[key] = parsed[key]\n    }\n  }\n}\n\nconst DotenvModule = {\n  configDotenv,\n  _configVault,\n  _parseVault,\n  config,\n  decrypt,\n  parse,\n  populate\n}\n\nmodule.exports.configDotenv = DotenvModule.configDotenv\nmodule.exports._configVault = DotenvModule._configVault\nmodule.exports._parseVault = DotenvModule._parseVault\nmodule.exports.config = DotenvModule.config\nmodule.exports.decrypt = DotenvModule.decrypt\nmodule.exports.parse = DotenvModule.parse\nmodule.exports.populate = DotenvModule.populate\n\nmodule.exports = DotenvModule\n","// ../config.js accepts options via environment variables\nconst options = {}\n\nif (process.env.DOTENV_CONFIG_ENCODING != null) {\n  options.encoding = process.env.DOTENV_CONFIG_ENCODING\n}\n\nif (process.env.DOTENV_CONFIG_PATH != null) {\n  options.path = process.env.DOTENV_CONFIG_PATH\n}\n\nif (process.env.DOTENV_CONFIG_QUIET != null) {\n  options.quiet = process.env.DOTENV_CONFIG_QUIET\n}\n\nif (process.env.DOTENV_CONFIG_DEBUG != null) {\n  options.debug = process.env.DOTENV_CONFIG_DEBUG\n}\n\nif (process.env.DOTENV_CONFIG_OVERRIDE != null) {\n  options.override = process.env.DOTENV_CONFIG_OVERRIDE\n}\n\nif (process.env.DOTENV_CONFIG_DOTENV_KEY != null) {\n  options.DOTENV_KEY = process.env.DOTENV_CONFIG_DOTENV_KEY\n}\n\nmodule.exports = options\n","const re = /^dotenv_config_(encoding|path|quiet|debug|override|DOTENV_KEY)=(.+)$/\n\nmodule.exports = function optionMatcher (args) {\n  const options = args.reduce(function (acc, cur) {\n    const matches = cur.match(re)\n    if (matches) {\n      acc[matches[1]] = matches[2]\n    }\n    return acc\n  }, {})\n\n  if (!('quiet' in options)) {\n    options.quiet = 'true'\n  }\n\n  return options\n}\n","// IMPORTANT: Load config first to ensure .env file is loaded before logger initialization\nexport { type Config } from \"./config\";\n\n// Export version information\nexport { VERSION, IS_RELEASE } from \"./version\";\n\n// Export all public classes and interfaces\nexport {\n  AgentBay,\n  CreateSessionParams,\n  CreateSessionParamsClass,\n  LifecyclePolicy,\n  type LifecyclePolicyOptions,\n} from \"./agent-bay\";\nexport * from \"./agent\";\nexport * from \"./api\";\nexport * from \"./browser\";\nexport { Code } from \"./code\";\nexport * from \"./command\";\nexport * from \"./env\";\nexport { Context, ContextService } from \"./context\";\nexport { BetaNetworkService } from \"./beta-network\";\nexport {\n  BetaSkillsService,\n  type SkillMetadataItem,\n  type SkillsMetadataResult,\n  type GetMetadataOptions,\n} from \"./beta-skills\";\nexport { Computer } from \"./computer\";\nexport * from \"./exceptions\";\nexport * from \"./git\";\nexport * from \"./extension\";\nexport * from \"./filesystem\";\nexport * from \"./oss\";\nexport { Mobile } from \"./mobile\";\nexport * from \"./pty\";\nexport {\n  MobileSimulateService,\n  type MobileSimulateUploadResult,\n} from \"./mobile-simulate\";\nexport { Session } from \"./session\";\nexport { type ListSessionParams } from \"./types\";\nexport * from \"./types\";\nexport * from \"./context-sync\";\nexport * from \"./beta-context-mount\";\nexport * from \"./context-manager\";\nexport * from \"./session-params\";\nexport * from \"./browser/eval\";\n// Export utility functions\nexport {\n  log,\n  logDebug,\n  logInfo,\n  logWarn,\n  logError,\n  setLogLevel,\n  getLogLevel,\n  setupLogger,\n  type LogLevel,\n  type LoggerConfig,\n} from \"./utils/logger\";\n","/**\n * Version information for the AgentBay SDK\n * Automatically read from package.json\n */\n\nimport * as fs from \"fs\";\nimport * as path from \"path\";\n\nfunction getVersionFromPackageJson(): string {\n  try {\n    // Get the path to package.json (relative to this file)\n    // When compiled, this will be in dist/, so we need to go up to find package.json\n    const packageJsonPath = path.join(__dirname, \"..\", \"package.json\");\n\n    if (fs.existsSync(packageJsonPath)) {\n      const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, \"utf-8\"));\n      return packageJson.version || \"0.0.0\";\n    }\n  } catch (error) {\n    // Fallback to default version if reading fails\n  }\n\n  // Fallback version if package.json cannot be read\n  return \"0.16.0\";\n}\n\n/**\n * Check if this is a release build.\n *\n * This value can be overridden at build time by replacing the placeholder below.\n * The CI/CD workflow will replace __AGENTBAY_IS_RELEASE_BUILD__ with true for release builds.\n */\nfunction isReleaseBuild(): boolean {\n  // This placeholder will be replaced by the build process\n  // For release builds: sed -i 's/__AGENTBAY_IS_RELEASE_BUILD__/true/g' src/version.ts\n  return __AGENTBAY_IS_RELEASE_BUILD__; // Default: false for development builds\n}\n\n// For release builds, the CI/CD will replace __AGENTBAY_IS_RELEASE_BUILD__ with true\nconst __AGENTBAY_IS_RELEASE_BUILD__ = false;\n\nexport const VERSION = getVersionFromPackageJson();\nexport const IS_RELEASE = isReleaseBuild();\n","import { $OpenApiUtil } from \"@alicloud/openapi-core\";\nimport \"dotenv/config\";\nimport * as fs from \"fs\";\nimport * as path from \"path\";\nimport * as dotenv from \"dotenv\";\nimport * as $_client from \"./api\";\nimport {\n  ListSessionRequest,\n  CreateMcpSessionRequestPersistenceDataList,\n  CreateMcpSessionRequestPersistenceDataListMountConfig,\n  GetSessionRequest as $GetSessionRequest,\n} from \"./api/models/model\";\nimport type { McpTool } from \"./session\";\nimport { Client } from \"./api/client\";\n\nimport {\n  Config,\n  BROWSER_RECORD_PATH,\n  loadConfig,\n  loadDotEnvWithFallback,\n} from \"./config\";\nimport type { ConfigOptions } from \"./config\";\nimport { ContextService } from \"./context\";\nimport { BetaNetworkService } from \"./beta-network\";\nimport { BetaSkillsService } from \"./beta-skills\";\nimport { ContextSync } from \"./context-sync\";\nimport { APIError, AuthenticationError } from \"./exceptions\";\nimport { Session } from \"./session\";\nimport {\n  BrowserContext,\n  CreateSessionParamsInterface,\n  CreateSessionParams as CreateSessionParamsClass,\n} from \"./session-params\";\nexport {\n  LifecyclePolicy,\n  type LifecyclePolicyOptions,\n} from \"./lifecycle-policy\";\nimport { BrowserSyncMode } from \"./session-params\";\nimport { Context } from \"./context\";\nimport { ExtraConfigs } from \"./types/extra-configs\";\nimport {\n  DeleteResult,\n  extractRequestId,\n  GetSessionResult as $GetSessionResult,\n  SessionResult,\n} from \"./types/api-response\";\nimport {\n  ListSessionParams,\n  SessionListResult,\n} from \"./types/list-session-params\";\nimport {\n  log,\n  logError,\n  logInfo,\n  logDebug,\n  logAPICall,\n  logAPIResponseWithDetails,\n  maskSensitiveData,\n  setRequestId,\n  getRequestId,\n  logInfoWithColor,\n  logWarn,\n} from \"./utils/logger\";\nimport { VERSION, IS_RELEASE } from \"./version\";\n\n// Browser data path constant (moved from config.ts)\nconst BROWSER_DATA_PATH = \"/tmp/agentbay_browser\";\n\n/**\n * Parameters for creating a session.\n * Can be either a plain object conforming to the interface or a CreateSessionParams class instance.\n */\nexport type CreateSessionParams = CreateSessionParamsInterface;\nexport { CreateSessionParams as CreateSessionParamsClass } from \"./session-params\";\n/**\n * Main class for interacting with the AgentBay cloud runtime environment.\n */\nexport class AgentBay {\n  private apiKey: string;\n  public client: Client;\n  private endpoint: string;\n  private config: Config;\n\n  /**\n   * Context service for managing persistent contexts.\n   */\n  context: ContextService;\n\n  /**\n   * Network service for managing networks.\n   */\n  /** Deprecated alias: use betaNetwork */\n  network: BetaNetworkService;\n\n  /**\n   * Beta network service for managing networks.\n   */\n  betaNetwork: BetaNetworkService;\n\n  /**\n   * Beta skills service for listing official skills metadata.\n   */\n  betaSkills: BetaSkillsService;\n\n  /**\n   * Initialize the AgentBay client.\n   *\n   * @param options - Configuration options\n   * @param options.apiKey - API key for authentication. If not provided, will look for AGENTBAY_API_KEY environment variable.\n   * @param options.config - Custom configuration object. If not provided, will use environment-based configuration.\n   * @param options.envFile - Custom path to .env file. If not provided, will search upward from current directory.\n   */\n  constructor(\n    options: {\n      apiKey?: string;\n      config?: ConfigOptions;\n      envFile?: string;\n    } = {}\n  ) {\n    // Load .env file first to ensure AGENTBAY_API_KEY is available\n    loadDotEnvWithFallback(options.envFile);\n\n    this.apiKey = options.apiKey || process.env.AGENTBAY_API_KEY || \"\";\n\n    if (!this.apiKey) {\n      throw new AuthenticationError(\n        \"API key is required. Provide it as a parameter or set the AGENTBAY_API_KEY environment variable.\"\n      );\n    }\n\n    this.config = loadConfig(options.config, options.envFile);\n\n    // Load configuration using the enhanced loadConfig function\n    const configData = loadConfig(options.config, options.envFile);\n    this.endpoint = configData.endpoint;\n\n    const config = new $OpenApiUtil.Config({\n      regionId: \"\",\n      endpoint: this.endpoint,\n    });\n\n    config.readTimeout = configData.timeout_ms;\n    config.connectTimeout = configData.timeout_ms;\n\n    try {\n      this.client = new Client(config);\n\n      // Initialize context service\n      this.context = new ContextService(this);\n      this.betaNetwork = new BetaNetworkService(this);\n      this.betaSkills = new BetaSkillsService(this);\n      // Deprecated alias: network APIs are beta for now\n      this.network = this.betaNetwork as any;\n    } catch (error) {\n      logError(`Failed to constructor:`, error);\n      throw new AuthenticationError(`Failed to constructor: ${error}`);\n    }\n  }\n\n  /**\n   * Get the region ID.\n   * @returns The region ID or undefined if not set.\n   */\n  getRegionId(): string | undefined {\n    return this.config.region_id;\n  }\n\n  /**\n   * Wait for mobile simulate command to complete.\n   *\n   * @param session - The session to wait for mobile simulate\n   * @param mobileSimPath - The dev info path to the mobile simulate\n   * @param mobileSimMode - The mode of the mobile simulate. If not provided, will use the default mode.\n   */\n  private async _waitForMobileSimulate(\n    session: Session,\n    mobileSimPath: string,\n    mobileSimMode?: string\n  ): Promise<void> {\n    log(\"⏳ Mobile simulate: Waiting for completion\");\n\n    if (!(session as any).mobile) {\n      logInfo(\"Mobile module not found in session, skipping mobile simulate\");\n      return;\n    }\n    if (!(session as any).command) {\n      logInfo(\"Command module not found in session, skipping mobile simulate\");\n      return;\n    }\n    if (!mobileSimPath) {\n      logInfo(\"Mobile simulate path is empty, skipping mobile simulate\");\n      return;\n    }\n\n    try {\n      // Run mobile simulate command\n      const startTime = Date.now();\n      const devInfoFilePath = `${mobileSimPath}/dev_info.json`;\n      let wyaApplyOption = \"\";\n\n      if (!mobileSimMode || mobileSimMode === \"PropertiesOnly\") {\n        wyaApplyOption = \"\";\n      } else if (mobileSimMode === \"SensorsOnly\") {\n        wyaApplyOption = \"-sensors\";\n      } else if (mobileSimMode === \"PackagesOnly\") {\n        wyaApplyOption = \"-packages\";\n      } else if (mobileSimMode === \"ServicesOnly\") {\n        wyaApplyOption = \"-services\";\n      } else if (mobileSimMode === \"All\") {\n        wyaApplyOption = \"-all\";\n      }\n\n      const command =\n        `chmod -R a+rwx ${mobileSimPath}; wya apply ${wyaApplyOption} ${devInfoFilePath}`.trim();\n      logInfo(\n        `ℹ️  ⏳ Waiting for mobile simulate completion, command: [${command}]`\n      );\n\n      const cmdResult = await (session as any).command.executeCommand(command);\n      if (cmdResult.success) {\n        const endTime = Date.now();\n        const consumeTime = (endTime - startTime) / 1000;\n        log(\n          `✅ Mobile simulate completed with mode: ${\n            mobileSimMode || \"PropertiesOnly\"\n          }, duration: ${consumeTime.toFixed(2)} seconds`\n        );\n        if (cmdResult.output) {\n          log(`   Output: ${cmdResult.output.trim()}`);\n        }\n      } else {\n        logInfo(\n          `Failed to execute mobile simulate command: ${cmdResult.errorMessage}`\n        );\n      }\n    } catch (error) {\n      logInfo(`Error executing mobile simulate command: ${error}`);\n    }\n  }\n\n  /**\n   * Create a new session in the AgentBay cloud environment.\n   *\n   * @param params - Optional parameters for creating the session\n   * @returns SessionResult containing the created session and request ID\n   */\n  /**\n   * Creates a new AgentBay session with specified configuration.\n   *\n   * @param params - Configuration parameters for the session:\n   *                 - labels: Key-value pairs for session metadata\n   *                 - imageId: Custom image ID for the session environment\n   *                 - contextSync: Array of context synchronization configurations\n   *                 - browserContext: Browser-specific context configuration\n   *                 - policyId: Security policy ID\n   *                 - enableBrowserReplay: Enable browser session recording\n   *                 - extraConfigs: Additional configuration options\n   *                 - framework: Framework identifier for tracking\n   *\n   * @returns Promise resolving to SessionResult containing:\n   *          - success: Whether session creation succeeded\n   *          - session: Session object for interacting with the environment\n   *          - requestId: Unique identifier for this API request\n   *          - errorMessage: Error description if creation failed\n   *\n   * @throws Error if API call fails or authentication is invalid.\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: 'your_api_key' });\n   * const result = await agentBay.create({ labels: { project: 'demo' } });\n   * if (result.success) {\n   *   await result.session.filesystem.readFile('/etc/hostname');\n   *   await result.session.delete();\n   * }\n   * ```\n   *\n   * @remarks\n   * **Behavior:**\n   * - Creates a new isolated cloud runtime environment\n   * - Automatically creates file transfer context if not provided\n   * - Waits for context synchronization if contextSync is specified\n   * - Browser replay creates a separate recording context\n   *\n   * @see {@link get}, {@link list}, {@link Session.delete}\n   */\n  async create(params: CreateSessionParams = {}): Promise<SessionResult> {\n    try {\n      // Create a deep copy of params to avoid modifying the original object\n      const paramsCopy = this.deepCopyParams(params);\n      logDebug(\n        `default context syncs length: ${paramsCopy.contextSync?.length}`\n      );\n\n      // Add context syncs for mobile simulate if provided\n      if (paramsCopy.extraConfigs?.mobile?.simulateConfig) {\n        const mobileSimContextId =\n          paramsCopy.extraConfigs.mobile.simulateConfig.simulatedContextId;\n        if (mobileSimContextId) {\n          const mobileSimContextSync = new ContextSync(\n            mobileSimContextId,\n            \"/data/agentbay_mobile_info\"\n          );\n          if (!paramsCopy.contextSync) {\n            paramsCopy.contextSync = [];\n          }\n          logInfo(\n            `Adding context sync for mobile simulate: ${JSON.stringify(\n              mobileSimContextSync\n            )}`\n          );\n          paramsCopy.contextSync.push(mobileSimContextSync);\n        }\n      }\n\n      const request = new $_client.CreateMcpSessionRequest({\n        authorization: \"Bearer \" + this.apiKey,\n      });\n\n      // Only set enable_record when user explicitly sets enable_browser_replay\n      // When undefined (not set), don't send the field - let server decide the default\n      if (paramsCopy.enableBrowserReplay !== undefined) {\n        request.enableRecord = paramsCopy.enableBrowserReplay;\n      }\n\n      // Add SDK stats for tracking\n      const framework = paramsCopy?.framework || \"\";\n      const sdkStatsJson = `{\"source\":\"sdk\",\"sdk_language\":\"typescript\",\"sdk_version\":\"${VERSION}\",\"is_release\":${IS_RELEASE},\"framework\":\"${framework}\"}`;\n      request.sdkStats = sdkStatsJson;\n\n      // Add LoginRegionId if region_id is set\n      if (this.config.region_id) {\n        request.loginRegionId = this.config.region_id;\n      }\n\n      // Add labels if provided\n      if (paramsCopy.labels) {\n        request.labels = JSON.stringify(paramsCopy.labels);\n      }\n\n      // Add image_id if provided\n      if (paramsCopy.imageId) {\n        request.imageId = paramsCopy.imageId;\n      }\n\n      // Add PolicyId if provided\n      if (paramsCopy.policyId) {\n        request.mcpPolicyId = paramsCopy.policyId;\n      }\n\n      // Beta: Add NetworkId if provided\n      if ((paramsCopy as any).betaNetworkId) {\n        (request as any).networkId = (paramsCopy as any).betaNetworkId;\n      }\n\n      // Lifecycle policy (minutes, full takeover)\n      if ((paramsCopy as any).lifecyclePolicy) {\n        const lp = (paramsCopy as any).lifecyclePolicy;\n        if (lp.manualRelease) {\n          (request as any).manualRelease = true;\n        } else {\n          (request as any).timeout = lp.idleReleaseTimeout;\n          (request as any).maxRuntime = lp.maxRuntime;\n        }\n      }\n      // Legacy SDK idle release timeout (seconds)\n      else if (\n        (paramsCopy as any).idleReleaseTimeout !== undefined &&\n        (paramsCopy as any).idleReleaseTimeout !== null &&\n        (paramsCopy as any).idleReleaseTimeout > 0\n      ) {\n        (request as any).timeout = (paramsCopy as any).idleReleaseTimeout;\n      }\n\n      // Flag to indicate if we need to wait for context synchronization\n      let needsContextSync = false;\n      const waitContextIds = new Set<string>();\n\n      // Flag to indicate if we need to wait for mobile simulate\n      let needsMobileSim = false;\n      let mobileSimMode: string | undefined = undefined;\n      let mobileSimPath: string | undefined = undefined;\n\n      // Add context sync configurations if provided\n      if (paramsCopy.contextSync && paramsCopy.contextSync.length > 0) {\n        const persistenceDataList: CreateMcpSessionRequestPersistenceDataList[] =\n          [];\n        for (const contextSync of paramsCopy.contextSync) {\n          const persistenceItem =\n            new CreateMcpSessionRequestPersistenceDataList({\n              contextId: contextSync.contextId,\n              path: contextSync.path,\n            });\n\n          // Convert policy to JSON string if provided\n          if (contextSync.policy) {\n            persistenceItem.policy = JSON.stringify(contextSync.policy);\n          }\n\n          persistenceDataList.push(persistenceItem);\n          if ((contextSync as any).betaWaitForCompletion !== false) {\n            waitContextIds.add(contextSync.contextId);\n          }\n        }\n        request.persistenceDataList = persistenceDataList;\n        needsContextSync = persistenceDataList.length > 0;\n      }\n\n      // Add context mounts if provided\n      if (\n        paramsCopy.betaContextMount &&\n        paramsCopy.betaContextMount.length > 0\n      ) {\n        if (!request.persistenceDataList) {\n          request.persistenceDataList = [];\n        }\n        for (const mount of paramsCopy.betaContextMount) {\n          const persistenceItem =\n            new CreateMcpSessionRequestPersistenceDataList({\n              contextId: mount.contextId,\n              path: mount.path,\n              type: \"mount\",\n              mountConfig:\n                new CreateMcpSessionRequestPersistenceDataListMountConfig({\n                  accessMode: mount.accessMode,\n                  storageMode: mount.strategy,\n                  sourcePath: mount.sourcePath,\n                }),\n            });\n          request.persistenceDataList.push(persistenceItem);\n          waitContextIds.add(mount.contextId);\n        }\n        needsContextSync = true;\n      }\n\n      // Add BrowserContext as a ContextSync if provided\n      if (paramsCopy.browserContext) {\n        const bc = paramsCopy.browserContext;\n        const syncMode = bc.syncMode ?? BrowserSyncMode.STANDARD;\n\n        let whiteLists: { path: string; excludePaths: string[] }[];\n        if (syncMode === BrowserSyncMode.MINIMAL) {\n          whiteLists = [\n            { path: \"/Local State\", excludePaths: [] },\n            { path: \"/Default/Cookies\", excludePaths: [] },\n            { path: \"/Default/Cookies-journal\", excludePaths: [] },\n          ];\n        } else {\n          // STANDARD mode: login state + anti-risk-control data\n          whiteLists = [\n            // Auth core\n            { path: \"/Local State\", excludePaths: [] },\n            { path: \"/Default/Cookies\", excludePaths: [] },\n            { path: \"/Default/Cookies-journal\", excludePaths: [] },\n            // Anti-risk-control device fingerprint (localStorage / IndexedDB)\n            { path: \"/Default/Local Storage\", excludePaths: [] },\n            { path: \"/Default/IndexedDB\", excludePaths: [] },\n            { path: \"/Default/Session Storage\", excludePaths: [] },\n            // Saved passwords and form autofill\n            { path: \"/Default/Login Data\", excludePaths: [] },\n            { path: \"/Default/Login Data-journal\", excludePaths: [] },\n            { path: \"/Default/Login Data For Account\", excludePaths: [] },\n            {\n              path: \"/Default/Login Data For Account-journal\",\n              excludePaths: [],\n            },\n            { path: \"/Default/Web Data\", excludePaths: [] },\n            { path: \"/Default/Web Data-journal\", excludePaths: [] },\n            // Browser settings and permission consistency\n            { path: \"/Default/Preferences\", excludePaths: [] },\n            { path: \"/Default/Secure Preferences\", excludePaths: [] },\n            // Network behavior consistency (HSTS / QUIC)\n            { path: \"/Default/TransportSecurity\", excludePaths: [] },\n            { path: \"/Default/Network Persistent State\", excludePaths: [] },\n            // Rendering fingerprint stability\n            { path: \"/Default/GPUCache\", excludePaths: [] },\n            // Cross-domain password matching\n            { path: \"/Default/Affiliation Database\", excludePaths: [] },\n            { path: \"/Default/Affiliation Database-journal\", excludePaths: [] },\n          ];\n        }\n\n        const syncPolicy = {\n          uploadPolicy: { autoUpload: bc.autoUpload },\n          downloadPolicy: null,\n          deletePolicy: null,\n          bwList: { whiteLists },\n          recyclePolicy: null,\n        };\n\n        // Create browser context sync item\n        const browserContextSync =\n          new CreateMcpSessionRequestPersistenceDataList({\n            contextId: bc.contextId,\n            path: BROWSER_DATA_PATH,\n            policy: JSON.stringify(syncPolicy),\n          });\n\n        // Add to persistence data list or create new one if not exists\n        if (!request.persistenceDataList) {\n          request.persistenceDataList = [];\n        }\n        request.persistenceDataList.push(browserContextSync);\n        needsContextSync = true;\n        waitContextIds.add(paramsCopy.browserContext.contextId);\n      }\n\n      // Add extra configs if provided\n      if (paramsCopy.extraConfigs) {\n        request.extraConfigs = JSON.stringify(paramsCopy.extraConfigs);\n\n        // Check mobile simulate config\n        if (paramsCopy.extraConfigs.mobile?.simulateConfig?.simulate) {\n          mobileSimPath =\n            paramsCopy.extraConfigs.mobile.simulateConfig.simulatePath;\n          if (!mobileSimPath) {\n            logInfo(\n              \"mobile_sim_path is not set now, skip mobile simulate operation\"\n            );\n          } else {\n            needsMobileSim = true;\n            mobileSimMode =\n              paramsCopy.extraConfigs.mobile.simulateConfig.simulateMode;\n          }\n        }\n      }\n\n      // Add skills loading if requested\n      if (paramsCopy.loadSkills) {\n        request.loadSkill = true;\n        if (paramsCopy.skillNames && paramsCopy.skillNames.length > 0) {\n          request.skills = paramsCopy.skillNames;\n        }\n      }\n\n      // Log API request\n      logAPICall(\"CreateMcpSession\", {\n        labels: paramsCopy.labels,\n        imageId: paramsCopy.imageId,\n        policyId: paramsCopy.policyId,\n        persistenceDataCount: paramsCopy.contextSync\n          ? paramsCopy.contextSync.length\n          : 0,\n      });\n\n      const response = await this.client.createMcpSession(request);\n\n      // Extract request ID\n      const requestId = extractRequestId(response) || \"\";\n      setRequestId(requestId);\n\n      const sessionData = response.body;\n\n      if (!sessionData || typeof sessionData !== \"object\") {\n        logAPIResponseWithDetails(\n          \"CreateMcpSession\",\n          requestId,\n          false,\n          {},\n          \"Invalid response format: expected a dictionary\"\n        );\n        logDebug(\"Full response:\", JSON.stringify(sessionData, null, 2));\n        return {\n          requestId,\n          success: false,\n          errorMessage: \"Invalid response format: expected a dictionary\",\n        };\n      }\n\n      // Check for API-level errors\n      if (sessionData.success === false && sessionData.code) {\n        const errorMessage = `[${sessionData.code}] ${\n          sessionData.message || \"Unknown error\"\n        }`;\n        logAPIResponseWithDetails(\n          \"CreateMcpSession\",\n          requestId,\n          false,\n          {},\n          errorMessage\n        );\n        logDebug(\"Full response:\", JSON.stringify(sessionData, null, 2));\n        return {\n          requestId,\n          success: false,\n          errorMessage,\n        };\n      }\n\n      const data = sessionData.data;\n      if (!data || typeof data !== \"object\") {\n        logAPIResponseWithDetails(\n          \"CreateMcpSession\",\n          requestId,\n          false,\n          {},\n          \"Invalid response format: 'data' field is not a dictionary\"\n        );\n        logDebug(\"Full response:\", JSON.stringify(sessionData, null, 2));\n        return {\n          requestId,\n          success: false,\n          errorMessage:\n            \"Invalid response format: 'data' field is not a dictionary\",\n        };\n      }\n\n      // Check data-level success field (business logic success)\n      if (data.success === false) {\n        const errorMessage = data.errMsg || \"Session creation failed\";\n        logAPIResponseWithDetails(\n          \"CreateMcpSession\",\n          requestId,\n          false,\n          {},\n          errorMessage\n        );\n        logDebug(\"Full response:\", JSON.stringify(sessionData, null, 2));\n        return {\n          requestId,\n          success: false,\n          errorMessage,\n        };\n      }\n\n      const sessionId = data.sessionId;\n      if (!sessionId) {\n        logAPIResponseWithDetails(\n          \"CreateMcpSession\",\n          requestId,\n          false,\n          {},\n          \"SessionId not found in response\"\n        );\n        logDebug(\"Full response:\", JSON.stringify(sessionData, null, 2));\n        return {\n          requestId,\n          success: false,\n          errorMessage: \"SessionId not found in response\",\n        };\n      }\n\n      // ResourceUrl is optional in CreateMcpSession response\n      const resourceUrl = data.resourceUrl || \"\";\n\n      logAPIResponseWithDetails(\"CreateMcpSession\", requestId, true, {\n        sessionId,\n        resourceUrl,\n      });\n\n      const session = new Session(this, sessionId);\n\n      // Set AppInstanceId and ResourceUrl\n      session.appInstanceId = data.appInstanceId || \"\";\n      session.resourceUrl = resourceUrl;\n\n      // VPC info, populated when upstream returns them\n      session.vpcIp = data.vpcIp || \"\";\n      session.vpcId = data.vpcId || \"\";\n\n      // LinkUrl/token may be returned by the server for direct tool calls.\n      session.token = data.token || \"\";\n      session.linkUrl = data.linkUrl || \"\";\n      session.wsUrl = data.wsUrl || \"\";\n      session.mcpTools = this.parseToolListToMcpTools(data.toolList);\n\n      // Set browser recording state\n      session.enableBrowserReplay = paramsCopy.enableBrowserReplay;\n\n      // Store imageId used for this session\n      (session as any).imageId = paramsCopy.imageId;\n\n      // Apply mobile configuration if provided\n      if (paramsCopy.extraConfigs && paramsCopy.extraConfigs.mobile) {\n        log(\"Applying mobile configuration...\");\n        try {\n          const configResult = await session.mobile.configure(\n            paramsCopy.extraConfigs.mobile\n          );\n          if (configResult.success) {\n            log(\"Mobile configuration applied successfully\");\n          } else {\n            logError(\n              `Warning: Failed to apply mobile configuration: ${configResult.errorMessage}`\n            );\n            // Continue with session creation even if mobile config fails\n          }\n        } catch (error) {\n          logError(`Warning: Failed to apply mobile configuration: ${error}`);\n          // Continue with session creation even if mobile config fails\n        }\n      }\n\n      // If we have persistence data, wait for context synchronization\n      if (needsContextSync && waitContextIds.size > 0) {\n        logDebug(\"Waiting for context synchronization to complete...\");\n\n        // Exponential backoff configuration\n        // Starts with short intervals (0.5s) for fast completion detection\n        // Gradually increases intervals (up to 5s max) to reduce server load\n        // Uses exponential backoff factor of 1.1\n        const initialInterval = 500; // Start with 0.5 seconds (500ms) for quick response\n        const maxInterval = 5000; // Maximum interval (5s) to avoid excessive delays\n        const backoffFactor = 1.1; // Multiply interval by this factor each retry\n        const maxRetries = 50; // Maximum number of retries\n\n        let currentInterval = initialInterval;\n\n        for (let retry = 0; retry < maxRetries; retry++) {\n          try {\n            // Get context status data\n            const infoResult = await session.context.info();\n\n            let hasFailure = false;\n            const statusByContextId = new Map<string, string>();\n\n            for (const item of infoResult.contextStatusData) {\n              if (!waitContextIds.has(item.contextId)) {\n                continue;\n              }\n              statusByContextId.set(item.contextId, item.status);\n              logDebug(\n                `Context ${item.contextId} status: ${item.status}, path: ${item.path}`\n              );\n\n              if (item.status === \"Failed\") {\n                hasFailure = true;\n                logError(\n                  `Context synchronization failed for ${item.contextId}: ${item.errorMessage}`\n                );\n              }\n            }\n\n            let allCompleted = true;\n            for (const ctxId of waitContextIds) {\n              const st = statusByContextId.get(ctxId);\n              if (!st || (st !== \"Success\" && st !== \"Failed\")) {\n                allCompleted = false;\n                break;\n              }\n            }\n\n            if (allCompleted) {\n              if (hasFailure) {\n                logDebug(\"Context synchronization completed with failures\");\n              } else {\n                logDebug(\"Context synchronization completed successfully\");\n              }\n              break;\n            }\n\n            logDebug(\n              `Waiting for context synchronization, attempt ${\n                retry + 1\n              }/${maxRetries}, next interval: ${(\n                currentInterval / 1000\n              ).toFixed(2)}s`\n            );\n            await new Promise((resolve) =>\n              setTimeout(resolve, currentInterval)\n            );\n\n            // Exponential backoff: increase interval for next retry, capped at maxInterval\n            currentInterval = Math.min(\n              currentInterval * backoffFactor,\n              maxInterval\n            );\n          } catch (error) {\n            logError(\n              `Error checking context status on attempt ${retry + 1}: ${error}`\n            );\n            await new Promise((resolve) =>\n              setTimeout(resolve, currentInterval)\n            );\n\n            // Exponential backoff: increase interval for next retry, capped at maxInterval\n            currentInterval = Math.min(\n              currentInterval * backoffFactor,\n              maxInterval\n            );\n          }\n        }\n      }\n\n      // If we need to do mobile simulate by command, wait for it\n      if (needsMobileSim && mobileSimPath) {\n        await this._waitForMobileSimulate(\n          session,\n          mobileSimPath,\n          mobileSimMode\n        );\n      }\n\n      // Return SessionResult with request ID\n      return {\n        requestId,\n        success: true,\n        session,\n      };\n    } catch (error) {\n      logError(\"Error calling create_mcp_session:\", error);\n      return {\n        requestId: \"\",\n        success: false,\n        errorMessage: `Failed to create session: ${error}`,\n      };\n    }\n  }\n\n  /**\n   * Returns paginated list of session IDs filtered by labels and status.\n   *\n   * @param labels - Optional labels to filter sessions (defaults to empty object)\n   * @param page - Optional page number for pagination (starting from 1, defaults to 1)\n   * @param limit - Optional maximum number of items per page (defaults to 10)\n   * @param status - Optional status to filter sessions. Must be one of: RUNNING, PAUSING, PAUSED, RESUMING, DELETING, DELETED (defaults to undefined)\n   * @returns SessionListResult - Paginated list of session IDs that match the labels and status\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: \"your_api_key\" });\n   * const result = await agentBay.list({ project: \"demo\" }, 1, 10, \"RUNNING\");\n   * if (result.success) {\n   *  log(`Found ${result.sessionIds.length} sessions`);\n   * }\n   * ```\n   */\n  async list(\n    labels: Record<string, string> = {},\n    page?: number,\n    limit = 10,\n    status?: string,\n    imageId?: string\n  ): Promise<SessionListResult> {\n    try {\n      // Validate status parameter\n      if (status !== undefined) {\n        const validStatuses = [\n          \"RUNNING\",\n          \"PAUSING\",\n          \"PAUSED\",\n          \"RESUMING\",\n          \"DELETING\",\n          \"DELETED\",\n        ];\n        if (!validStatuses.includes(status)) {\n          return {\n            requestId: \"\",\n            success: false,\n            errorMessage: `Invalid status '${status}'. Must be one of: ${validStatuses.join(\n              \", \"\n            )}`,\n            sessionIds: [],\n            nextToken: \"\",\n            maxResults: limit,\n            totalCount: 0,\n          };\n        }\n      }\n\n      // Validate page number\n      if (page !== undefined && page < 1) {\n        return {\n          requestId: \"\",\n          success: false,\n          errorMessage: `Cannot reach page ${page}: Page number must be >= 1`,\n          sessionIds: [],\n          nextToken: \"\",\n          maxResults: limit,\n          totalCount: 0,\n        };\n      }\n\n      // Calculate next_token based on page number\n      // Page 1 or undefined means no next_token (first page)\n      // For page > 1, we need to make multiple requests to get to that page\n      let nextToken = \"\";\n      if (page !== undefined && page > 1) {\n        // We need to fetch pages 1 through page-1 to get the next_token\n        let currentPage = 1;\n        while (currentPage < page) {\n          // Make API call to get next_token\n          const request = new ListSessionRequest({\n            authorization: `Bearer ${this.apiKey}`,\n            labels: JSON.stringify(labels),\n            maxResults: limit,\n          });\n          if (nextToken) {\n            request.nextToken = nextToken;\n          }\n          if (status) {\n            request.status = status;\n          }\n          if (imageId) {\n            request.imageId = imageId;\n          }\n\n          const response = await this.client.listSession(request);\n          const requestId = extractRequestId(response) || \"\";\n\n          if (!response.body?.success) {\n            const code = response.body?.code || \"Unknown\";\n            const message = response.body?.message || \"Unknown error\";\n            return {\n              requestId,\n              success: false,\n              errorMessage: `[${code}] ${message}`,\n              sessionIds: [],\n              nextToken: \"\",\n              maxResults: limit,\n              totalCount: 0,\n            };\n          }\n\n          nextToken = response.body.nextToken || \"\";\n          if (!nextToken) {\n            // No more pages available\n            return {\n              requestId,\n              success: false,\n              errorMessage: `Cannot reach page ${page}: No more pages available`,\n              sessionIds: [],\n              nextToken: \"\",\n              maxResults: limit,\n              totalCount: response.body.totalCount || 0,\n            };\n          }\n          currentPage += 1;\n        }\n      }\n\n      // Make the actual request for the desired page\n      const request = new ListSessionRequest({\n        authorization: `Bearer ${this.apiKey}`,\n        labels: JSON.stringify(labels),\n        maxResults: limit,\n      });\n      if (nextToken) {\n        request.nextToken = nextToken;\n      }\n      if (status) {\n        request.status = status;\n      }\n      if (imageId) {\n        request.imageId = imageId;\n      }\n\n      // Log API request\n      logAPICall(\"ListSession\", {\n        labels,\n        maxResults: limit,\n        nextToken: nextToken || undefined,\n        status: status || undefined,\n      });\n\n      const response = await this.client.listSession(request);\n\n      // Extract request ID\n      const requestId = extractRequestId(response) || \"\";\n      setRequestId(requestId);\n\n      // Check for errors in the response\n      if (!response.body?.success) {\n        const code = response.body?.code || \"Unknown\";\n        const message = response.body?.message || \"Unknown error\";\n        logAPIResponseWithDetails(\n          \"ListSession\",\n          requestId,\n          false,\n          {},\n          `[${code}] ${message}`\n        );\n        logDebug(\n          \"Full ListSession response:\",\n          JSON.stringify(response.body, null, 2)\n        );\n        return {\n          requestId,\n          success: false,\n          errorMessage: `[${code}] ${message}`,\n          sessionIds: [],\n          nextToken: \"\",\n          maxResults: limit,\n          totalCount: 0,\n        };\n      }\n\n      const sessionIds: Array<{\n        sessionId: string;\n        sessionStatus: string;\n        appInstanceId?: string;\n        imageId?: string;\n      }> = [];\n\n      // Extract session data\n      if (response.body.data) {\n        for (const sessionData of response.body.data) {\n          if (sessionData.sessionId) {\n            // Create a structured session object with both ID and status\n            const sessionInfo: {\n              sessionId: string;\n              sessionStatus: string;\n              appInstanceId?: string;\n              imageId?: string;\n            } = {\n              sessionId: sessionData.sessionId,\n              sessionStatus: sessionData.sessionStatus || \"UNKNOWN\",\n            };\n            if (sessionData.appInstanceId) {\n              sessionInfo.appInstanceId = sessionData.appInstanceId;\n            }\n            if (sessionData.imageId) {\n              sessionInfo.imageId = sessionData.imageId;\n            }\n            sessionIds.push(sessionInfo);\n          }\n        }\n      }\n\n      logAPIResponseWithDetails(\"ListSession\", requestId, true, {\n        sessionCount: sessionIds.length,\n        totalCount: response.body.totalCount || 0,\n        maxResults: response.body.maxResults || limit,\n      });\n\n      // Return SessionListResult with request ID and pagination info\n      return {\n        requestId,\n        success: true,\n        sessionIds,\n        nextToken: response.body.nextToken || \"\",\n        maxResults: response.body.maxResults || limit,\n        totalCount: response.body.totalCount || 0,\n      };\n    } catch (error) {\n      logError(\"Error calling list_session:\", error);\n      return {\n        requestId: \"\",\n        success: false,\n        errorMessage: `Failed to list sessions: ${error}`,\n        sessionIds: [],\n      };\n    }\n  }\n\n  /**\n   * Delete a session by session object.\n   *\n   * @param session - The session to delete.\n   * @param syncContext - Whether to sync context data (trigger file uploads) before deleting the session. Defaults to false.\n   * @returns DeleteResult indicating success or failure and request ID\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: 'your_api_key' });\n   * const result = await agentBay.create();\n   * if (result.success) {\n   *   await agentBay.delete(result.session);\n   * }\n   * ```\n   */\n  async delete(session: Session, syncContext = false): Promise<DeleteResult> {\n    try {\n      // Delete the session and get the result\n      logAPICall(\"DeleteSession\", { sessionId: session.sessionId });\n      const deleteResult = await session.delete(syncContext);\n\n      logAPIResponseWithDetails(\n        \"DeleteSession\",\n        deleteResult.requestId,\n        deleteResult.success,\n        { sessionId: session.sessionId }\n      );\n\n      // Return the DeleteResult obtained from session.delete()\n      return deleteResult;\n    } catch (error) {\n      logError(\"Error deleting session:\", error);\n      return {\n        requestId: \"\",\n        success: false,\n        errorMessage: `Failed to delete session ${session.sessionId}: ${error}`,\n      };\n    }\n  }\n\n  /**\n   * Get session information by session ID.\n   *\n   * @param sessionId - The ID of the session to retrieve.\n   * @returns GetSessionResult containing session information\n   */\n  /**\n   * Get session information by session ID (internal).\n   *\n   * Users should prefer {@link get} which returns a {@link Session}.\n   *\n   * @internal\n   */\n  async _getSession(sessionId: string): Promise<$GetSessionResult> {\n    try {\n      logAPICall(\"GetSession\", { sessionId });\n\n      const request = new $GetSessionRequest({\n        authorization: `Bearer ${this.apiKey}`,\n        sessionId: sessionId,\n      });\n\n      const response = await this.client.getSession(request);\n      const requestId = extractRequestId(response) || \"\";\n      const body = response.body;\n\n      setRequestId(requestId);\n\n      // Check for API-level errors\n      if (body?.success === false && body.code) {\n        logAPIResponseWithDetails(\n          \"GetSession\",\n          requestId,\n          false,\n          {},\n          `[${body.code}] ${body.message || \"Unknown error\"}`\n        );\n        logDebug(\"Full GetSession response:\", JSON.stringify(body, null, 2));\n        return {\n          requestId,\n          httpStatusCode: body.httpStatusCode || 0,\n          code: body.code,\n          success: false,\n          errorMessage: `[${body.code}] ${body.message || \"Unknown error\"}`,\n        };\n      }\n\n      const result: $GetSessionResult = {\n        requestId,\n        httpStatusCode: body?.httpStatusCode || 0,\n        code: body?.code || \"\",\n        success: body?.success || false,\n        errorMessage: \"\",\n      };\n\n      if (body?.data) {\n        // Extract contexts list from response\n        const contextsList = body.data.contexts || [];\n        const contexts: Array<{ name: string; id: string }> = [];\n        if (Array.isArray(contextsList)) {\n          for (const ctx of contextsList) {\n            if (ctx && typeof ctx === \"object\" && ctx.name && ctx.id) {\n              contexts.push({\n                name: ctx.name,\n                id: ctx.id,\n              });\n            }\n          }\n        }\n\n        const wsUrl = (body.data as any).wsUrl || \"\";\n        const data = {\n          appInstanceId: body.data.appInstanceId || \"\",\n          resourceId: body.data.resourceId || \"\",\n          sessionId: body.data.sessionId || \"\",\n          success: body.data.success || false,\n          httpPort: body.data.httpPort || \"\",\n          networkInterfaceIp: body.data.networkInterfaceIp || \"\",\n          token: body.data.token || \"\",\n          linkUrl: (body.data as any).linkUrl || \"\",\n          wsUrl,\n          vpcResource: body.data.vpcResource || false,\n          vpcIp: body.data.vpcIp || \"\",\n          vpcId: body.data.vpcId || \"\",\n          resourceUrl: body.data.resourceUrl || \"\",\n          status: body.data.status || \"\",\n          toolList: body.data.toolList || \"\",\n          contexts: contexts.length > 0 ? contexts : undefined,\n        };\n        result.data = data;\n\n        logAPIResponseWithDetails(\"GetSession\", requestId, true, {\n          sessionId: data.sessionId,\n          resourceId: data.resourceId,\n          httpPort: data.httpPort,\n        });\n      }\n\n      return result;\n    } catch (error: any) {\n      // Check if this is an expected business error (e.g., session not found)\n      const errorStr = String(error);\n      const errorCode = error?.data?.Code || error?.code || \"\";\n\n      if (\n        errorCode === \"InvalidMcpSession.NotFound\" ||\n        errorStr.includes(\"NotFound\")\n      ) {\n        // This is an expected error - session doesn't exist\n        // Use info level logging without stack trace, but with red color for visibility\n        logInfo(`Session not found: ${sessionId}`);\n        logDebug(`GetSession error details: ${errorStr}`);\n        return {\n          requestId: \"\",\n          httpStatusCode: 400,\n          code: \"InvalidMcpSession.NotFound\",\n          success: false,\n          errorMessage: `Session ${sessionId} not found`,\n        };\n      } else {\n        // This is an unexpected error - log with full error\n        logError(\"Error calling GetSession:\", error);\n        return {\n          requestId: \"\",\n          httpStatusCode: 0,\n          code: \"\",\n          success: false,\n          errorMessage: `Failed to get session ${sessionId}: ${error}`,\n        };\n      }\n    }\n  }\n\n  /**\n   * Get a session by its ID.\n   *\n   * This method retrieves a session by calling the GetSession API\n   * and returns a SessionResult containing the Session object and request ID.\n   *\n   * @param sessionId - The ID of the session to retrieve\n   * @returns Promise resolving to SessionResult with the Session instance, request ID, and success status\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: 'your_api_key' });\n   * const createResult = await agentBay.create();\n   * if (createResult.success) {\n   *   const result = await agentBay.get(createResult.session.sessionId);\n   *   await result.session?.filesystem.readFile('/etc/hostname');\n   *   await result.session?.delete();\n   * }\n   * ```\n   */\n  async get(sessionId: string): Promise<SessionResult> {\n    // Validate input\n    if (!sessionId || (typeof sessionId === \"string\" && !sessionId.trim())) {\n      return {\n        requestId: \"\",\n        success: false,\n        errorMessage: \"session_id is required\",\n      };\n    }\n\n    // Call GetSession API\n    const getResult = await this._getSession(sessionId);\n\n    // Check if the API call was successful\n    if (!getResult.success) {\n      const errorMsg = getResult.errorMessage || \"Unknown error\";\n      return {\n        requestId: getResult.requestId,\n        success: false,\n        errorMessage: `Failed to get session ${sessionId}: ${errorMsg}`,\n      };\n    }\n\n    // Create the Session object\n    const session = new Session(this, sessionId);\n\n    // Set ResourceUrl from GetSession response\n    if (getResult.data) {\n      session.appInstanceId = getResult.data.appInstanceId || \"\";\n      session.resourceUrl = getResult.data.resourceUrl;\n      session.vpcIp = getResult.data.vpcIp || \"\";\n      session.vpcId = getResult.data.vpcId || \"\";\n      session.token = getResult.data.token || \"\";\n      session.linkUrl = getResult.data.linkUrl || \"\";\n      session.wsUrl = getResult.data.wsUrl || \"\";\n      session.mcpTools = this.parseToolListToMcpTools(getResult.data.toolList);\n    }\n\n    return {\n      requestId: getResult.requestId,\n      success: true,\n      session,\n    };\n  }\n\n  /**\n   * Get the internal HTTP client instance.\n   *\n   * This is primarily for internal use and advanced scenarios where you need direct access\n   * to the underlying API client.\n   *\n   * @returns The Client instance used for API communication\n   *\n   * @internal\n   *\n   * @remarks\n   * **Note:** This method is primarily for internal use. Most users should interact\n   * with the SDK through higher-level methods like `create()`, `get()`, and `list()`.\n   */\n  getClient(): Client {\n    return this.client;\n  }\n\n  /**\n   * Get the API key used for authentication.\n   *\n   * @returns The API key string\n   *\n   * @internal\n   *\n   * @remarks\n   * **Security Note:** Be careful when logging or exposing API keys. Always keep them secure\n   * and never commit them to version control.\n   */\n  getAPIKey(): string {\n    return this.apiKey;\n  }\n\n  /**\n   * Asynchronously pause a session, putting it into a dormant state.\n   *\n   * **Note**: This feature is currently in whitelist-only access.\n   * Contact agentbay_dev@alibabacloud.com to request access.\n   *\n   * This method directly calls the PauseSessionAsync API without waiting for the session\n   * to reach the PAUSED state.\n   *\n   * @param session - The session to pause.\n   * @param timeout - Timeout in seconds to wait for the session to pause. Defaults to 600 seconds.\n   * @param pollInterval - Interval in seconds between status polls. Defaults to 2.0 seconds.\n   * @returns SessionPauseResult indicating success or failure and request ID\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: 'your_api_key' });\n   * const session = (await agentBay.create()).session;\n   * const pauseResult = await agentBay.betaPauseAsync(session);\n   * await agentBay.betaResumeAsync(session);\n   * await session.delete();\n   * ```\n   *\n   * @remarks\n   * **Behavior:**\n   * - This method does not wait for the session to reach the PAUSED state\n   * - It only submits the pause request to the API\n   * - The session state transitions from RUNNING -> PAUSING -> PAUSED\n   * - Paused sessions consume fewer resources but maintain their state\n   *\n   * @see {@link betaResumeAsync}, {@link Session.betaPauseAsync}\n   */\n  async betaPauseAsync(\n    session: Session,\n    timeout = 600,\n    pollInterval = 2.0\n  ): Promise<import(\"./types/api-response\").SessionPauseResult> {\n    try {\n      // Call session's pause_async method directly\n      return await session.betaPauseAsync(timeout, pollInterval);\n    } catch (error) {\n      logError(\"Error calling pause session async:\", error);\n      return {\n        requestId: \"\",\n        success: false,\n        errorMessage: `Failed to pause session ${session.sessionId}: ${error}`,\n      };\n    }\n  }\n\n  /**\n   * Asynchronously resume a session from a paused state.\n   *\n   * This method directly calls the ResumeSessionAsync API without waiting for the session\n   * to reach the RUNNING state.\n   *\n   * @param session - The session to resume.\n   * @param timeout - Timeout in seconds to wait for the session to resume. Defaults to 600 seconds.\n   * @param pollInterval - Interval in seconds between status polls. Defaults to 2.0 seconds.\n   * @returns SessionResumeResult indicating success or failure and request ID\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: 'your_api_key' });\n   * const session = (await agentBay.create()).session;\n   * await agentBay.betaPauseAsync(session);\n   * const resumeResult = await agentBay.betaResumeAsync(session);\n   * await session.delete();\n   * ```\n   *\n   * @remarks\n   * **Behavior:**\n   * - This method does not wait for the session to reach the RUNNING state\n   * - It only submits the resume request to the API\n   * - The session state transitions from PAUSED -> RESUMING -> RUNNING\n   * - Only sessions in PAUSED state can be resumed\n   *\n   * @see {@link betaPauseAsync}, {@link Session.betaResumeAsync}\n   */\n  async betaResumeAsync(\n    session: Session,\n    timeout = 600,\n    pollInterval = 2.0\n  ): Promise<import(\"./types/api-response\").SessionResumeResult> {\n    try {\n      // Call session's resume_async method directly\n      return await session.betaResumeAsync(timeout, pollInterval);\n    } catch (error) {\n      logError(\"Error calling resume session async:\", error);\n      return {\n        requestId: \"\",\n        success: false,\n        errorMessage: `Failed to resume session ${session.sessionId}: ${error}`,\n      };\n    }\n  }\n\n  private parseToolListToMcpTools(toolList: any): McpTool[] {\n    if (!toolList) {\n      return [];\n    }\n\n    let items = toolList;\n    if (typeof toolList === \"string\") {\n      try {\n        items = JSON.parse(toolList);\n      } catch (error) {\n        logDebug(`Failed to parse ToolList JSON: ${error}`);\n        return [];\n      }\n    }\n\n    if (!Array.isArray(items)) {\n      return [];\n    }\n\n    const tools: McpTool[] = [];\n    for (const item of items) {\n      if (!item || typeof item !== \"object\") {\n        continue;\n      }\n      const name = item.name || item.Name || \"\";\n      const server = item.server || item.serverName || item.Server || \"\";\n      const description = item.description || item.Description || \"\";\n      const inputSchema = item.inputSchema || item.input_schema || {};\n      const tool = item.tool || item.Tool || \"\";\n      tools.push({\n        name,\n        server,\n        description,\n        inputSchema,\n        tool,\n      });\n    }\n\n    return tools;\n  }\n\n  /**\n   * Creates a deep copy of CreateSessionParams to avoid modifying the original object.\n   * Extension contexts are automatically merged when browserContext is set in the class.\n   * @param params - The original params object to copy\n   * @returns A deep copy of the params object as interface with merged context syncs\n   */\n  private deepCopyParams(\n    params: CreateSessionParams\n  ): CreateSessionParamsInterface {\n    let result: CreateSessionParamsInterface;\n\n    // Check if params is a CreateSessionParams class instance\n    if (params instanceof CreateSessionParamsClass) {\n      // For class instances, extension contexts are already merged automatically when browserContext was set\n      // We can directly use the class properties without needing toJSON()\n      result = {\n        labels: params.labels,\n        imageId: params.imageId,\n        idleReleaseTimeout: (params as any).idleReleaseTimeout,\n        lifecyclePolicy: (params as any).lifecyclePolicy,\n        contextSync: params.contextSync, // Already contains merged extension contexts\n        browserContext: params.browserContext,\n        isVpc: params.isVpc,\n        mcpPolicyId: params.mcpPolicyId,\n        policyId: params.policyId,\n        betaNetworkId: params.betaNetworkId,\n        enableBrowserReplay: params.enableBrowserReplay,\n        extraConfigs: params.extraConfigs,\n        framework: params.framework,\n        loadSkills: params.loadSkills,\n        skillNames: params.skillNames,\n      };\n    } else {\n      // Use any type for JSON.parse result since params could be either interface or class instance\n      const copied = JSON.parse(JSON.stringify(params)) as any;\n      result = copied as CreateSessionParamsInterface;\n      // Don't set enableBrowserReplay default - leave as-is so server decides\n      const allContextSyncs = params?.contextSync\n        ? [...params.contextSync]\n        : [];\n      // **IMPORTANT: Apply extension context merging for plain objects automatically**\n      // Check if browserContext exists and has extension syncs to merge\n      if (\n        result.browserContext &&\n        result.browserContext.extensionContextSyncs\n      ) {\n        // Merge with extension syncs (equivalent to automatic merging in class)\n        result.contextSync = [\n          ...allContextSyncs,\n          ...result.browserContext.extensionContextSyncs,\n        ];\n      }\n      if (\n        params?.browserContext &&\n        params.browserContext.fingerprintContextSync\n      ) {\n        result.contextSync = [\n          ...(result.contextSync || []),\n          params.browserContext.fingerprintContextSync,\n        ];\n        log(\"Added fingerprint context sync from BrowserContext\");\n      }\n      // Reconstruct ContextSync objects if they exist (since they might be class instances)\n      if (result.contextSync && Array.isArray(result.contextSync)) {\n        result.contextSync = result.contextSync.map((cs: any) => {\n          // Reconstruct from plain object (JSON.parse converts class instances to plain objects)\n          return new ContextSync(\n            cs.contextId,\n            cs.path,\n            cs.policy,\n            cs.betaWaitForCompletion\n          );\n        });\n      }\n\n      // Reconstruct BrowserContext if it exists\n      if (result.browserContext) {\n        const bc = result.browserContext as any;\n        result.browserContext = new BrowserContext(\n          bc.contextId,\n          bc.autoUpload,\n          bc.extensionOption,\n          bc.fingerprintContext,\n          bc.syncMode\n        );\n      }\n    }\n\n    return result;\n  }\n}\n\n/**\n * Creates a new AgentBay client using default configuration.\n * This is a convenience function that allows creating an AgentBay instance without a config parameter.\n *\n * @param apiKey - API key for authentication\n * @returns A new AgentBay instance with default configuration\n */\nexport function newAgentBayWithDefaults(apiKey: string): AgentBay {\n  return new AgentBay({ apiKey });\n}\n","(function () {\n  require('./lib/main').config(\n    Object.assign(\n      {},\n      require('./lib/env-options'),\n      require('./lib/cli-options')(process.argv)\n    )\n  )\n})()\n","// Export the client and models\nimport { Client } from \"./client\";\nexport { Client } from \"./client\";\nexport * from \"./models/model\";\n\nexport default Client;\n","// This file is auto-generated, don't edit it\nimport * as $dara from \"@darabonba/typescript\";\nimport OpenApi from \"@alicloud/openapi-core\";\nimport { OpenApiUtil, $OpenApiUtil } from \"@alicloud/openapi-core\";\n\nimport * as $_model from \"./models/model\";\nexport * from \"./models/model\";\n\nexport class Client extends OpenApi {\n  constructor(config: $OpenApiUtil.Config) {\n    super(config);\n    this._signatureAlgorithm = \"v2\";\n    this._endpointRule = \"\";\n    this.checkConfig(config);\n    this._endpoint = this.getEndpoint(\n      \"wuyingai\",\n      this._regionId,\n      this._endpointRule,\n      this._network,\n      this._suffix,\n      this._endpointMap,\n      this._endpoint\n    );\n  }\n\n  getEndpoint(\n    productId: string,\n    regionId: string,\n    endpointRule: string,\n    network: string,\n    suffix: string,\n    endpointMap: { [key: string]: string },\n    endpoint: string\n  ): string {\n    if (!$dara.isNull(endpoint)) {\n      return endpoint;\n    }\n\n    if (!$dara.isNull(endpointMap) && !$dara.isNull(endpointMap[regionId])) {\n      return endpointMap[regionId];\n    }\n\n    return OpenApiUtil.getEndpointRules(\n      productId,\n      regionId,\n      endpointRule,\n      network,\n      suffix\n    );\n  }\n\n  /**\n   * Call MCP tool\n   *\n   * @param request - CallMcpToolRequest\n   * @param runtime - runtime options for this request RuntimeOptions\n   * @returns CallMcpToolResponse\n   */\n  async callMcpToolWithOptions(\n    request: $_model.CallMcpToolRequest,\n    runtime: $dara.RuntimeOptions\n  ): Promise<$_model.CallMcpToolResponse> {\n    request.validate();\n    const body: { [key: string]: any } = {};\n    if (!$dara.isNull(request.args)) {\n      body[\"Args\"] = request.args;\n    }\n\n    if (!$dara.isNull(request.authorization)) {\n      body[\"Authorization\"] = request.authorization;\n    }\n\n    if (!$dara.isNull(request.autoGenSession)) {\n      body[\"AutoGenSession\"] = request.autoGenSession;\n    }\n\n    if (!$dara.isNull(request.externalUserId)) {\n      body[\"ExternalUserId\"] = request.externalUserId;\n    }\n\n    if (!$dara.isNull(request.imageId)) {\n      body[\"ImageId\"] = request.imageId;\n    }\n\n    if (!$dara.isNull(request.name)) {\n      body[\"Name\"] = request.name;\n    }\n\n    if (!$dara.isNull(request.server)) {\n      body[\"Server\"] = request.server;\n    }\n\n    if (!$dara.isNull(request.sessionId)) {\n      body[\"SessionId\"] = request.sessionId;\n    }\n\n    if (!$dara.isNull(request.tool)) {\n      body[\"Tool\"] = request.tool;\n    }\n\n    const req = new $OpenApiUtil.OpenApiRequest({\n      body: OpenApiUtil.parseToMap(body),\n    });\n    const params = new $OpenApiUtil.Params({\n      action: \"CallMcpTool\",\n      version: \"2025-05-06\",\n      protocol: \"HTTPS\",\n      pathname: \"/\",\n      method: \"POST\",\n      authType: \"Anonymous\",\n      style: \"RPC\",\n      reqBodyType: \"formData\",\n      bodyType: \"json\",\n    });\n    return $dara.cast<$_model.CallMcpToolResponse>(\n      await this.callApi(params, req, runtime),\n      new $_model.CallMcpToolResponse({})\n    );\n  }\n\n  /**\n   * Call MCP tool\n   *\n   * @param request - CallMcpToolRequest\n   * @returns CallMcpToolResponse\n   */\n  async callMcpTool(\n    request: $_model.CallMcpToolRequest\n  ): Promise<$_model.CallMcpToolResponse> {\n    const runtime = new $dara.RuntimeOptions({});\n    return await this.callMcpToolWithOptions(request, runtime);\n  }\n\n  /**\n   * Delete Persistent Context\n   *\n   * @param request - ClearContextRequest\n   * @param runtime - runtime options for this request RuntimeOptions\n   * @returns ClearContextResponse\n   */\n  async clearContextWithOptions(\n    request: $_model.ClearContextRequest,\n    runtime: $dara.RuntimeOptions\n  ): Promise<$_model.ClearContextResponse> {\n    request.validate();\n    const body: { [key: string]: any } = {};\n    if (!$dara.isNull(request.authorization)) {\n      body[\"Authorization\"] = request.authorization;\n    }\n\n    if (!$dara.isNull(request.id)) {\n      body[\"Id\"] = request.id;\n    }\n\n    const req = new $OpenApiUtil.OpenApiRequest({\n      body: OpenApiUtil.parseToMap(body),\n    });\n    const params = new $OpenApiUtil.Params({\n      action: \"ClearContext\",\n      version: \"2025-05-06\",\n      protocol: \"HTTPS\",\n      pathname: \"/\",\n      method: \"POST\",\n      authType: \"Anonymous\",\n      style: \"RPC\",\n      reqBodyType: \"formData\",\n      bodyType: \"json\",\n    });\n    return $dara.cast<$_model.ClearContextResponse>(\n      await this.doRPCRequest(\n        params.action,\n        params.version,\n        params.protocol,\n        params.method,\n        params.authType,\n        params.bodyType,\n        req,\n        runtime\n      ),\n      new $_model.ClearContextResponse({})\n    );\n  }\n\n  /**\n   * Delete Persistent Context\n   *\n   * @param request - ClearContextRequest\n   * @returns ClearContextResponse\n   */\n  async clearContext(\n    request: $_model.ClearContextRequest\n  ): Promise<$_model.ClearContextResponse> {\n    const runtime = new $dara.RuntimeOptions({});\n    return await this.clearContextWithOptions(request, runtime);\n  }\n  /**\n   * Create MCP session\n   *\n   * @param tmpReq - CreateMcpSessionRequest\n   * @param runtime - runtime options for this request RuntimeOptions\n   * @returns CreateMcpSessionResponse\n   */\n  async createMcpSessionWithOptions(\n    tmpReq: $_model.CreateMcpSessionRequest,\n    runtime: $dara.RuntimeOptions\n  ): Promise<$_model.CreateMcpSessionResponse> {\n    tmpReq.validate();\n    const request = new $_model.CreateMcpSessionShrinkRequest({});\n    OpenApiUtil.convert(tmpReq, request);\n    if (!$dara.isNull(tmpReq.persistenceDataList)) {\n      request.persistenceDataListShrink =\n        OpenApiUtil.arrayToStringWithSpecifiedStyle(\n          tmpReq.persistenceDataList,\n          \"PersistenceDataList\",\n          \"json\"\n        );\n    }\n    if (!$dara.isNull(tmpReq.skills)) {\n      request.skillsShrink = OpenApiUtil.arrayToStringWithSpecifiedStyle(\n        tmpReq.skills,\n        \"Skills\",\n        \"json\"\n      );\n    }\n\n    const body: { [key: string]: any } = {};\n    if (!$dara.isNull(request.authorization)) {\n      body[\"Authorization\"] = request.authorization;\n    }\n\n    if (!$dara.isNull(request.contextId)) {\n      body[\"ContextId\"] = request.contextId;\n    }\n\n    if (!$dara.isNull(request.enableRecord)) {\n      body[\"EnableRecord\"] = request.enableRecord;\n    }\n\n    if (!$dara.isNull(request.externalUserId)) {\n      body[\"ExternalUserId\"] = request.externalUserId;\n    }\n\n    if (!$dara.isNull(request.imageId)) {\n      body[\"ImageId\"] = request.imageId;\n    }\n\n    if (!$dara.isNull((request as any).timeout)) {\n      body[\"Timeout\"] = (request as any).timeout;\n    }\n\n    if (!$dara.isNull(request.maxRuntime)) {\n      body[\"MaxRuntime\"] = request.maxRuntime;\n    }\n\n    if (!$dara.isNull(request.manualRelease)) {\n      body[\"ManualRelease\"] = request.manualRelease;\n    }\n\n    if (!$dara.isNull(request.labels)) {\n      body[\"Labels\"] = request.labels;\n    }\n\n    if (!$dara.isNull(request.mcpPolicyId)) {\n      body[\"McpPolicyId\"] = request.mcpPolicyId;\n    }\n\n    if (!$dara.isNull(request.networkId)) {\n      body[\"NetworkId\"] = request.networkId;\n    }\n\n    if (!$dara.isNull(request.persistenceDataListShrink)) {\n      body[\"PersistenceDataList\"] = request.persistenceDataListShrink;\n    }\n\n    if (!$dara.isNull(request.sessionId)) {\n      body[\"SessionId\"] = request.sessionId;\n    }\n\n    if (!$dara.isNull(request.vpcResource)) {\n      body[\"VpcResource\"] = request.vpcResource;\n    }\n\n    if (!$dara.isNull(request.extraConfigs)) {\n      body[\"ExtraConfigs\"] = request.extraConfigs;\n    }\n\n    if (!$dara.isNull(request.sdkStats)) {\n      body[\"SdkStats\"] = request.sdkStats;\n    }\n\n    if (!$dara.isNull(request.loginRegionId)) {\n      body[\"LoginRegionId\"] = request.loginRegionId;\n    }\n\n    if (!$dara.isNull(request.loadSkill)) {\n      body[\"LoadSkill\"] = request.loadSkill;\n    }\n\n    if (!$dara.isNull(request.skillGroupIdsShrink)) {\n      body[\"SkillGroupIds\"] = request.skillGroupIdsShrink;\n    }\n\n    const req = new $OpenApiUtil.OpenApiRequest({\n      body: OpenApiUtil.parseToMap(body),\n    });\n    const params = new $OpenApiUtil.Params({\n      action: \"CreateMcpSession\",\n      version: \"2025-05-06\",\n      protocol: \"HTTPS\",\n      pathname: \"/\",\n      method: \"POST\",\n      authType: \"Anonymous\",\n      style: \"RPC\",\n      reqBodyType: \"formData\",\n      bodyType: \"json\",\n    });\n    return $dara.cast<$_model.CreateMcpSessionResponse>(\n      await this.callApi(params, req, runtime),\n      new $_model.CreateMcpSessionResponse({})\n    );\n  }\n\n  /**\n   * Create MCP session\n   *\n   * @param request - CreateMcpSessionRequest\n   * @returns CreateMcpSessionResponse\n   */\n  async createMcpSession(\n    request: $_model.CreateMcpSessionRequest\n  ): Promise<$_model.CreateMcpSessionResponse> {\n    const runtime = new $dara.RuntimeOptions({});\n    return await this.createMcpSessionWithOptions(request, runtime);\n  }\n\n  /**\n   * Create network\n   *\n   * @param request - CreateNetworkRequest\n   * @param runtime - runtime options for this request RuntimeOptions\n   * @returns CreateNetworkResponse\n   */\n  async createNetworkWithOptions(\n    request: $_model.CreateNetworkRequest,\n    runtime: $dara.RuntimeOptions\n  ): Promise<$_model.CreateNetworkResponse> {\n    request.validate();\n    const body: { [key: string]: any } = {};\n    if (!$dara.isNull(request.authorization)) {\n      body[\"Authorization\"] = request.authorization;\n    }\n    if (!$dara.isNull(request.loginRegionId)) {\n      body[\"LoginRegionId\"] = request.loginRegionId;\n    }\n    if (!$dara.isNull(request.networkId)) {\n      body[\"NetworkId\"] = request.networkId;\n    }\n    const req = new $OpenApiUtil.OpenApiRequest({\n      body: OpenApiUtil.parseToMap(body),\n    });\n    const params = new $OpenApiUtil.Params({\n      action: \"CreateNetwork\",\n      version: \"2025-05-06\",\n      protocol: \"HTTPS\",\n      pathname: \"/\",\n      method: \"POST\",\n      authType: \"Anonymous\",\n      style: \"RPC\",\n      reqBodyType: \"formData\",\n      bodyType: \"json\",\n    });\n    return $dara.cast<$_model.CreateNetworkResponse>(\n      await this.callApi(params, req, runtime),\n      new $_model.CreateNetworkResponse({})\n    );\n  }\n\n  /**\n   * Create network\n   *\n   * @param request - CreateNetworkRequest\n   * @returns CreateNetworkResponse\n   */\n  async createNetwork(\n    request: $_model.CreateNetworkRequest\n  ): Promise<$_model.CreateNetworkResponse> {\n    const runtime = new $dara.RuntimeOptions({});\n    return await this.createNetworkWithOptions(request, runtime);\n  }\n\n  /**\n   * Describe network\n   *\n   * @param request - DescribeNetworkRequest\n   * @param runtime - runtime options for this request RuntimeOptions\n   * @returns DescribeNetworkResponse\n   */\n  async describeNetworkWithOptions(\n    request: $_model.DescribeNetworkRequest,\n    runtime: $dara.RuntimeOptions\n  ): Promise<$_model.DescribeNetworkResponse> {\n    request.validate();\n    const body: { [key: string]: any } = {};\n    if (!$dara.isNull(request.authorization)) {\n      body[\"Authorization\"] = request.authorization;\n    }\n    if (!$dara.isNull(request.networkId)) {\n      body[\"NetworkId\"] = request.networkId;\n    }\n    const req = new $OpenApiUtil.OpenApiRequest({\n      body: OpenApiUtil.parseToMap(body),\n    });\n    const params = new $OpenApiUtil.Params({\n      action: \"DescribeNetwork\",\n      version: \"2025-05-06\",\n      protocol: \"HTTPS\",\n      pathname: \"/\",\n      method: \"POST\",\n      authType: \"Anonymous\",\n      style: \"RPC\",\n      reqBodyType: \"formData\",\n      bodyType: \"json\",\n    });\n    return $dara.cast<$_model.DescribeNetworkResponse>(\n      await this.callApi(params, req, runtime),\n      new $_model.DescribeNetworkResponse({})\n    );\n  }\n\n  /**\n   * Describe network\n   *\n   * @param request - DescribeNetworkRequest\n   * @returns DescribeNetworkResponse\n   */\n  async describeNetwork(\n    request: $_model.DescribeNetworkRequest\n  ): Promise<$_model.DescribeNetworkResponse> {\n    const runtime = new $dara.RuntimeOptions({});\n    return await this.describeNetworkWithOptions(request, runtime);\n  }\n\n  /**\n   * Delete session\n   *\n   * @param request - DeleteSessionAsyncRequest\n   * @param runtime - runtime options for this request RuntimeOptions\n   * @returns DeleteSessionAsyncResponse\n   */\n  async deleteSessionAsyncWithOptions(\n    request: $_model.DeleteSessionAsyncRequest,\n    runtime: $dara.RuntimeOptions\n  ): Promise<$_model.DeleteSessionAsyncResponse> {\n    request.validate();\n    const body: { [key: string]: any } = {};\n    if (!$dara.isNull(request.authorization)) {\n      body[\"Authorization\"] = request.authorization;\n    }\n\n    if (!$dara.isNull(request.sessionId)) {\n      body[\"SessionId\"] = request.sessionId;\n    }\n\n    const req = new $OpenApiUtil.OpenApiRequest({\n      body: OpenApiUtil.parseToMap(body),\n    });\n    const params = new $OpenApiUtil.Params({\n      action: \"DeleteSessionAsync\",\n      version: \"2025-05-06\",\n      protocol: \"HTTPS\",\n      pathname: \"/\",\n      method: \"POST\",\n      authType: \"Anonymous\",\n      style: \"RPC\",\n      reqBodyType: \"formData\",\n      bodyType: \"json\",\n    });\n    return $dara.cast<$_model.DeleteSessionAsyncResponse>(\n      await this.doRPCRequest(\n        params.action,\n        params.version,\n        params.protocol,\n        params.method,\n        params.authType,\n        params.bodyType,\n        req,\n        runtime\n      ),\n      new $_model.DeleteSessionAsyncResponse({})\n    );\n  }\n\n  /**\n   * Delete session\n   *\n   * @param request - DeleteSessionAsyncRequest\n   * @returns DeleteSessionAsyncResponse\n   */\n  async deleteSessionAsync(\n    request: $_model.DeleteSessionAsyncRequest\n  ): Promise<$_model.DeleteSessionAsyncResponse> {\n    const runtime = new $dara.RuntimeOptions({});\n    return await this.deleteSessionAsyncWithOptions(request, runtime);\n  }\n\n  /**\n   * Delete persistent context\n   *\n   * @param request - DeleteContextRequest\n   * @param runtime - runtime options for this request RuntimeOptions\n   * @returns DeleteContextResponse\n   */\n  async deleteContextWithOptions(\n    request: $_model.DeleteContextRequest,\n    runtime: $dara.RuntimeOptions\n  ): Promise<$_model.DeleteContextResponse> {\n    request.validate();\n    const body: { [key: string]: any } = {};\n    if (!$dara.isNull(request.authorization)) {\n      body[\"Authorization\"] = request.authorization;\n    }\n\n    if (!$dara.isNull(request.id)) {\n      body[\"Id\"] = request.id;\n    }\n\n    const req = new $OpenApiUtil.OpenApiRequest({\n      body: OpenApiUtil.parseToMap(body),\n    });\n    const params = new $OpenApiUtil.Params({\n      action: \"DeleteContext\",\n      version: \"2025-05-06\",\n      protocol: \"HTTPS\",\n      pathname: \"/\",\n      method: \"POST\",\n      authType: \"Anonymous\",\n      style: \"RPC\",\n      reqBodyType: \"formData\",\n      bodyType: \"json\",\n    });\n    return $dara.cast<$_model.DeleteContextResponse>(\n      await this.callApi(params, req, runtime),\n      new $_model.DeleteContextResponse({})\n    );\n  }\n\n  /**\n   * Delete persistent context\n   *\n   * @param request - DeleteContextRequest\n   * @returns DeleteContextResponse\n   */\n  async deleteContext(\n    request: $_model.DeleteContextRequest\n  ): Promise<$_model.DeleteContextResponse> {\n    const runtime = new $dara.RuntimeOptions({});\n    return await this.deleteContextWithOptions(request, runtime);\n  }\n\n  /**\n   * Get context\n   *\n   * @param request - GetContextRequest\n   * @param runtime - runtime options for this request RuntimeOptions\n   * @returns GetContextResponse\n   */\n  async getContextWithOptions(\n    request: $_model.GetContextRequest,\n    runtime: $dara.RuntimeOptions\n  ): Promise<$_model.GetContextResponse> {\n    request.validate();\n    const body: { [key: string]: any } = {};\n    if (!$dara.isNull(request.allowCreate)) {\n      body[\"AllowCreate\"] = request.allowCreate;\n    }\n\n    if (!$dara.isNull(request.authorization)) {\n      body[\"Authorization\"] = request.authorization;\n    }\n\n    if (!$dara.isNull(request.contextId)) {\n      body[\"ContextId\"] = request.contextId;\n    }\n\n    if (!$dara.isNull(request.name)) {\n      body[\"Name\"] = request.name;\n    }\n\n    if (!$dara.isNull(request.loginRegionId)) {\n      body[\"LoginRegionId\"] = request.loginRegionId;\n    }\n\n    const req = new $OpenApiUtil.OpenApiRequest({\n      body: OpenApiUtil.parseToMap(body),\n    });\n    const params = new $OpenApiUtil.Params({\n      action: \"GetContext\",\n      version: \"2025-05-06\",\n      protocol: \"HTTPS\",\n      pathname: \"/\",\n      method: \"POST\",\n      authType: \"Anonymous\",\n      style: \"RPC\",\n      reqBodyType: \"formData\",\n      bodyType: \"json\",\n    });\n    return $dara.cast<$_model.GetContextResponse>(\n      await this.callApi(params, req, runtime),\n      new $_model.GetContextResponse({})\n    );\n  }\n\n  /**\n   * Get context\n   *\n   * @param request - GetContextRequest\n   * @returns GetContextResponse\n   */\n  async getContext(\n    request: $_model.GetContextRequest\n  ): Promise<$_model.GetContextResponse> {\n    const runtime = new $dara.RuntimeOptions({});\n    return await this.getContextWithOptions(request, runtime);\n  }\n\n  /**\n   * Get context information\n   *\n   * @param request - GetContextInfoRequest\n   * @param runtime - runtime options for this request RuntimeOptions\n   * @returns GetContextInfoResponse\n   */\n  async getContextInfoWithOptions(\n    request: $_model.GetContextInfoRequest,\n    runtime: $dara.RuntimeOptions\n  ): Promise<$_model.GetContextInfoResponse> {\n    request.validate();\n    const body: { [key: string]: any } = {};\n    if (!$dara.isNull(request.authorization)) {\n      body[\"Authorization\"] = request.authorization;\n    }\n\n    if (!$dara.isNull(request.contextId)) {\n      body[\"ContextId\"] = request.contextId;\n    }\n\n    if (!$dara.isNull(request.path)) {\n      body[\"Path\"] = request.path;\n    }\n\n    if (!$dara.isNull(request.sessionId)) {\n      body[\"SessionId\"] = request.sessionId;\n    }\n\n    if (!$dara.isNull(request.taskType)) {\n      body[\"TaskType\"] = request.taskType;\n    }\n\n    const req = new $OpenApiUtil.OpenApiRequest({\n      body: OpenApiUtil.parseToMap(body),\n    });\n    const params = new $OpenApiUtil.Params({\n      action: \"GetContextInfo\",\n      version: \"2025-05-06\",\n      protocol: \"HTTPS\",\n      pathname: \"/\",\n      method: \"POST\",\n      authType: \"Anonymous\",\n      style: \"RPC\",\n      reqBodyType: \"formData\",\n      bodyType: \"json\",\n    });\n    return $dara.cast<$_model.GetContextInfoResponse>(\n      await this.callApi(params, req, runtime),\n      new $_model.GetContextInfoResponse({})\n    );\n  }\n\n  /**\n   * Get context information\n   *\n   * @param request - GetContextInfoRequest\n   * @returns GetContextInfoResponse\n   */\n  async getContextInfo(\n    request: $_model.GetContextInfoRequest\n  ): Promise<$_model.GetContextInfoResponse> {\n    const runtime = new $dara.RuntimeOptions({});\n    return await this.getContextInfoWithOptions(request, runtime);\n  }\n\n  /**\n   * Get labels\n   *\n   * @param request - GetLabelRequest\n   * @param runtime - runtime options for this request RuntimeOptions\n   * @returns GetLabelResponse\n   */\n  async getLabelWithOptions(\n    request: $_model.GetLabelRequest,\n    runtime: $dara.RuntimeOptions\n  ): Promise<$_model.GetLabelResponse> {\n    request.validate();\n    const body: { [key: string]: any } = {};\n    if (!$dara.isNull(request.authorization)) {\n      body[\"Authorization\"] = request.authorization;\n    }\n\n    if (!$dara.isNull(request.maxResults)) {\n      body[\"MaxResults\"] = request.maxResults;\n    }\n\n    if (!$dara.isNull(request.nextToken)) {\n      body[\"NextToken\"] = request.nextToken;\n    }\n\n    if (!$dara.isNull(request.sessionId)) {\n      body[\"SessionId\"] = request.sessionId;\n    }\n\n    const req = new $OpenApiUtil.OpenApiRequest({\n      body: OpenApiUtil.parseToMap(body),\n    });\n    const params = new $OpenApiUtil.Params({\n      action: \"GetLabel\",\n      version: \"2025-05-06\",\n      protocol: \"HTTPS\",\n      pathname: \"/\",\n      method: \"POST\",\n      authType: \"Anonymous\",\n      style: \"RPC\",\n      reqBodyType: \"formData\",\n      bodyType: \"json\",\n    });\n    return $dara.cast<$_model.GetLabelResponse>(\n      await this.callApi(params, req, runtime),\n      new $_model.GetLabelResponse({})\n    );\n  }\n\n  /**\n   * Get labels\n   *\n   * @param request - GetLabelRequest\n   * @returns GetLabelResponse\n   */\n  async getLabel(\n    request: $_model.GetLabelRequest\n  ): Promise<$_model.GetLabelResponse> {\n    const runtime = new $dara.RuntimeOptions({});\n    return await this.getLabelWithOptions(request, runtime);\n  }\n\n  /**\n   * Get session information\n   *\n   * @param request - GetSessionRequest\n   * @param runtime - runtime options for this request RuntimeOptions\n   * @returns GetSessionResponse\n   */\n  async getSessionWithOptions(\n    request: $_model.GetSessionRequest,\n    runtime: $dara.RuntimeOptions\n  ): Promise<$_model.GetSessionResponse> {\n    request.validate();\n    const body: { [key: string]: any } = {};\n    if (!$dara.isNull(request.authorization)) {\n      body[\"Authorization\"] = request.authorization;\n    }\n\n    if (!$dara.isNull(request.sessionId)) {\n      body[\"SessionId\"] = request.sessionId;\n    }\n\n    const req = new $OpenApiUtil.OpenApiRequest({\n      body: OpenApiUtil.parseToMap(body),\n    });\n    const params = new $OpenApiUtil.Params({\n      action: \"GetSession\",\n      version: \"2025-05-06\",\n      protocol: \"HTTPS\",\n      pathname: \"/\",\n      method: \"POST\",\n      authType: \"Anonymous\",\n      style: \"RPC\",\n      reqBodyType: \"formData\",\n      bodyType: \"json\",\n    });\n    return $dara.cast<$_model.GetSessionResponse>(\n      await this.callApi(params, req, runtime),\n      new $_model.GetSessionResponse({})\n    );\n  }\n\n  /**\n   * Get session information\n   *\n   * @param request - GetSessionRequest\n   * @returns GetSessionResponse\n   */\n  async getSession(\n    request: $_model.GetSessionRequest\n  ): Promise<$_model.GetSessionResponse> {\n    const runtime = new $dara.RuntimeOptions({});\n    return await this.getSessionWithOptions(request, runtime);\n  }\n\n  /**\n   * Get basic session information by session ID\n   *\n   * @param request - GetSessionDetailRequest\n   * @param runtime - runtime options for this request RuntimeOptions\n   * @returns GetSessionDetailResponse\n   */\n  async getSessionDetailWithOptions(\n    request: $_model.GetSessionDetailRequest,\n    runtime: $dara.RuntimeOptions\n  ): Promise<$_model.GetSessionDetailResponse> {\n    request.validate();\n    const query: { [key: string]: any } = {};\n    if (!$dara.isNull(request.sessionId)) {\n      query[\"SessionId\"] = request.sessionId;\n    }\n\n    const body: { [key: string]: any } = {};\n    if (!$dara.isNull(request.authorization)) {\n      body[\"Authorization\"] = request.authorization;\n    }\n\n    const req = new $OpenApiUtil.OpenApiRequest({\n      query: OpenApiUtil.query(query),\n      body: OpenApiUtil.parseToMap(body),\n    });\n    const params = new $OpenApiUtil.Params({\n      action: \"GetSessionDetail\",\n      version: \"2025-05-06\",\n      protocol: \"HTTPS\",\n      pathname: \"/\",\n      method: \"POST\",\n      authType: \"Anonymous\",\n      style: \"RPC\",\n      reqBodyType: \"formData\",\n      bodyType: \"json\",\n    });\n    return $dara.cast<$_model.GetSessionDetailResponse>(\n      await this.callApi(params, req, runtime),\n      new $_model.GetSessionDetailResponse({})\n    );\n  }\n\n  /**\n   * Get basic session information by session ID\n   *\n   * @param request - GetSessionDetailRequest\n   * @returns GetSessionDetailResponse\n   */\n  async getSessionDetail(\n    request: $_model.GetSessionDetailRequest\n  ): Promise<$_model.GetSessionDetailResponse> {\n    const runtime = new $dara.RuntimeOptions({});\n    return await this.getSessionDetailWithOptions(request, runtime);\n  }\n\n  /**\n   * Pause session async\n   *\n   * @param request - PauseSessionAsyncRequest\n   * @param runtime - runtime options for this request RuntimeOptions\n   * @returns PauseSessionAsyncResponse\n   */\n  async pauseSessionAsyncWithOptions(\n    request: $_model.PauseSessionAsyncRequest,\n    runtime: $dara.RuntimeOptions\n  ): Promise<$_model.PauseSessionAsyncResponse> {\n    request.validate();\n    const body: { [key: string]: any } = {};\n    if (!$dara.isNull(request.authorization)) {\n      body[\"Authorization\"] = request.authorization;\n    }\n\n    if (!$dara.isNull(request.sessionId)) {\n      body[\"SessionId\"] = request.sessionId;\n    }\n\n    const req = new $OpenApiUtil.OpenApiRequest({\n      body: OpenApiUtil.parseToMap(body),\n    });\n    const params = new $OpenApiUtil.Params({\n      action: \"PauseSessionAsync\",\n      version: \"2025-05-06\",\n      protocol: \"HTTPS\",\n      pathname: \"/\",\n      method: \"POST\",\n      authType: \"Anonymous\",\n      style: \"RPC\",\n      reqBodyType: \"formData\",\n      bodyType: \"json\",\n    });\n    return $dara.cast<$_model.PauseSessionAsyncResponse>(\n      await this.callApi(params, req, runtime),\n      new $_model.PauseSessionAsyncResponse({})\n    );\n  }\n\n  /**\n   * Pause session async\n   *\n   * @param request - PauseSessionAsyncRequest\n   * @returns PauseSessionAsyncResponse\n   */\n  async pauseSessionAsync(\n    request: $_model.PauseSessionAsyncRequest\n  ): Promise<$_model.PauseSessionAsyncResponse> {\n    const runtime = new $dara.RuntimeOptions({});\n    return await this.pauseSessionAsyncWithOptions(request, runtime);\n  }\n\n  /**\n   * Refresh session idle timer\n   *\n   * @param request - RefreshSessionIdleTimeRequest\n   * @param runtime - runtime options for this request RuntimeOptions\n   * @returns RefreshSessionIdleTimeResponse\n   */\n  async refreshSessionIdleTimeWithOptions(\n    request: $_model.RefreshSessionIdleTimeRequest,\n    runtime: $dara.RuntimeOptions\n  ): Promise<$_model.RefreshSessionIdleTimeResponse> {\n    request.validate();\n    const body: { [key: string]: any } = {};\n    if (!$dara.isNull(request.authorization)) {\n      body[\"Authorization\"] = request.authorization;\n    }\n    if (!$dara.isNull(request.sessionId)) {\n      body[\"SessionId\"] = request.sessionId;\n    }\n    const req = new $OpenApiUtil.OpenApiRequest({\n      body: OpenApiUtil.parseToMap(body),\n    });\n    const params = new $OpenApiUtil.Params({\n      action: \"RefreshSessionIdleTime\",\n      version: \"2025-05-06\",\n      protocol: \"HTTPS\",\n      pathname: \"/\",\n      method: \"POST\",\n      authType: \"Anonymous\",\n      style: \"RPC\",\n      reqBodyType: \"formData\",\n      bodyType: \"json\",\n    });\n    return $dara.cast<$_model.RefreshSessionIdleTimeResponse>(\n      await this.callApi(params, req, runtime),\n      new $_model.RefreshSessionIdleTimeResponse({})\n    );\n  }\n\n  /**\n   * Refresh session idle timer\n   *\n   * @param request - RefreshSessionIdleTimeRequest\n   * @returns RefreshSessionIdleTimeResponse\n   */\n  async refreshSessionIdleTime(\n    request: $_model.RefreshSessionIdleTimeRequest\n  ): Promise<$_model.RefreshSessionIdleTimeResponse> {\n    const runtime = new $dara.RuntimeOptions({});\n    return await this.refreshSessionIdleTimeWithOptions(request, runtime);\n  }\n\n  /**\n   * Resume session async\n   *\n   * @param request - ResumeSessionAsyncRequest\n   * @param runtime - runtime options for this request RuntimeOptions\n   * @returns ResumeSessionAsyncResponse\n   */\n  async resumeSessionAsyncWithOptions(\n    request: $_model.ResumeSessionAsyncRequest,\n    runtime: $dara.RuntimeOptions\n  ): Promise<$_model.ResumeSessionAsyncResponse> {\n    request.validate();\n    const body: { [key: string]: any } = {};\n    if (!$dara.isNull(request.authorization)) {\n      body[\"Authorization\"] = request.authorization;\n    }\n\n    if (!$dara.isNull(request.sessionId)) {\n      body[\"SessionId\"] = request.sessionId;\n    }\n\n    const req = new $OpenApiUtil.OpenApiRequest({\n      body: OpenApiUtil.parseToMap(body),\n    });\n    const params = new $OpenApiUtil.Params({\n      action: \"ResumeSessionAsync\",\n      version: \"2025-05-06\",\n      protocol: \"HTTPS\",\n      pathname: \"/\",\n      method: \"POST\",\n      authType: \"Anonymous\",\n      style: \"RPC\",\n      reqBodyType: \"formData\",\n      bodyType: \"json\",\n    });\n    return $dara.cast<$_model.ResumeSessionAsyncResponse>(\n      await this.callApi(params, req, runtime),\n      new $_model.ResumeSessionAsyncResponse({})\n    );\n  }\n\n  /**\n   * Resume session async\n   *\n   * @param request - ResumeSessionAsyncRequest\n   * @returns ResumeSessionAsyncResponse\n   */\n  async resumeSessionAsync(\n    request: $_model.ResumeSessionAsyncRequest\n  ): Promise<$_model.ResumeSessionAsyncResponse> {\n    const runtime = new $dara.RuntimeOptions({});\n    return await this.resumeSessionAsyncWithOptions(request, runtime);\n  }\n\n  /**\n   * Get forwarding link for specific port\n   *\n   * @param request - GetLinkRequest\n   * @param runtime - runtime options for this request RuntimeOptions\n   * @returns GetLinkResponse\n   */\n  async getLinkWithOptions(\n    request: $_model.GetLinkRequest,\n    runtime: $dara.RuntimeOptions\n  ): Promise<$_model.GetLinkResponse> {\n    request.validate();\n    const body: { [key: string]: any } = {};\n    if (!$dara.isNull(request.authorization)) {\n      body[\"Authorization\"] = request.authorization;\n    }\n\n    if (!$dara.isNull(request.port)) {\n      body[\"Port\"] = request.port;\n    }\n\n    if (!$dara.isNull(request.protocolType)) {\n      body[\"ProtocolType\"] = request.protocolType;\n    }\n\n    if (!$dara.isNull(request.sessionId)) {\n      body[\"SessionId\"] = request.sessionId;\n    }\n\n    if (!$dara.isNull(request.option)) {\n      body[\"Option\"] = request.option;\n    }\n\n    const req = new $OpenApiUtil.OpenApiRequest({\n      body: OpenApiUtil.parseToMap(body),\n    });\n    const params = new $OpenApiUtil.Params({\n      action: \"GetLink\",\n      version: \"2025-05-06\",\n      protocol: \"HTTPS\",\n      pathname: \"/\",\n      method: \"POST\",\n      authType: \"Anonymous\",\n      style: \"RPC\",\n      reqBodyType: \"formData\",\n      bodyType: \"json\",\n    });\n    return $dara.cast<$_model.GetLinkResponse>(\n      await this.callApi(params, req, runtime),\n      new $_model.GetLinkResponse({})\n    );\n  }\n\n  /**\n   * Get forwarding link for specific port\n   *\n   * @param request - GetLinkRequest\n   * @returns GetLinkResponse\n   */\n  async getLink(\n    request: $_model.GetLinkRequest\n  ): Promise<$_model.GetLinkResponse> {\n    const runtime = new $dara.RuntimeOptions({});\n    return await this.getLinkWithOptions(request, runtime);\n  }\n\n  /**\n   * Get MCP resource information\n   *\n   * @param request - GetMcpResourceRequest\n   * @param runtime - runtime options for this request RuntimeOptions\n   * @returns GetMcpResourceResponse\n   */\n  async getMcpResourceWithOptions(\n    request: $_model.GetMcpResourceRequest,\n    runtime: $dara.RuntimeOptions\n  ): Promise<$_model.GetMcpResourceResponse> {\n    request.validate();\n    const body: { [key: string]: any } = {};\n    if (!$dara.isNull(request.authorization)) {\n      body[\"Authorization\"] = request.authorization;\n    }\n\n    if (!$dara.isNull(request.sessionId)) {\n      body[\"SessionId\"] = request.sessionId;\n    }\n\n    const req = new $OpenApiUtil.OpenApiRequest({\n      body: OpenApiUtil.parseToMap(body),\n    });\n    const params = new $OpenApiUtil.Params({\n      action: \"GetMcpResource\",\n      version: \"2025-05-06\",\n      protocol: \"HTTPS\",\n      pathname: \"/\",\n      method: \"POST\",\n      authType: \"Anonymous\",\n      style: \"RPC\",\n      reqBodyType: \"formData\",\n      bodyType: \"json\",\n    });\n    return $dara.cast<$_model.GetMcpResourceResponse>(\n      await this.callApi(params, req, runtime),\n      new $_model.GetMcpResourceResponse({})\n    );\n  }\n\n  /**\n   * Get MCP resource information\n   *\n   * @param request - GetMcpResourceRequest\n   * @returns GetMcpResourceResponse\n   */\n  async getMcpResource(\n    request: $_model.GetMcpResourceRequest\n  ): Promise<$_model.GetMcpResourceResponse> {\n    const runtime = new $dara.RuntimeOptions({});\n    return await this.getMcpResourceWithOptions(request, runtime);\n  }\n\n  /**\n   * Get internal context request\n   *\n   * @param request - GetAndLoadInternalContextRequest\n   * @param runtime - runtime options for this request RuntimeOptions\n   * @returns GetAndLoadInternalContextResponse\n   */\n  async getAndLoadInternalContextWithOptions(\n    request: $_model.GetAndLoadInternalContextRequest,\n    runtime: $dara.RuntimeOptions\n  ): Promise<$_model.GetAndLoadInternalContextResponse> {\n    request.validate();\n    const query = OpenApiUtil.query(request.toMap());\n    const req = new $OpenApiUtil.OpenApiRequest({\n      query: OpenApiUtil.query(query),\n    });\n    const params = new $OpenApiUtil.Params({\n      action: \"GetAndLoadInternalContext\",\n      version: \"2025-05-06\",\n      protocol: \"HTTPS\",\n      pathname: \"/\",\n      method: \"GET\",\n      authType: \"Anonymous\",\n      style: \"RPC\",\n      reqBodyType: \"formData\",\n      bodyType: \"json\",\n    });\n    return $dara.cast<$_model.GetAndLoadInternalContextResponse>(\n      await this.doRPCRequest(\n        params.action,\n        params.version,\n        params.protocol,\n        params.method,\n        params.authType,\n        params.bodyType,\n        req,\n        runtime\n      ),\n      new $_model.GetAndLoadInternalContextResponse({})\n    );\n  }\n\n  /**\n   * Get internal context request\n   *\n   * @param request - GetAndLoadInternalContextRequest\n   * @returns GetAndLoadInternalContextResponse\n   */\n  async getAndLoadInternalContext(\n    request: $_model.GetAndLoadInternalContextRequest\n  ): Promise<$_model.GetAndLoadInternalContextResponse> {\n    const runtime = new $dara.RuntimeOptions({});\n    return await this.getAndLoadInternalContextWithOptions(request, runtime);\n  }\n\n  /**\n   * Get context list\n   *\n   * @param request - ListContextsRequest\n   * @param runtime - runtime options for this request RuntimeOptions\n   * @returns ListContextsResponse\n   */\n  async listContextsWithOptions(\n    request: $_model.ListContextsRequest,\n    runtime: $dara.RuntimeOptions\n  ): Promise<$_model.ListContextsResponse> {\n    request.validate();\n    const body: { [key: string]: any } = {};\n    if (!$dara.isNull(request.authorization)) {\n      body[\"Authorization\"] = request.authorization;\n    }\n\n    if (!$dara.isNull(request.maxResults)) {\n      body[\"MaxResults\"] = request.maxResults;\n    }\n\n    if (!$dara.isNull(request.nextToken)) {\n      body[\"NextToken\"] = request.nextToken;\n    }\n\n    if (!$dara.isNull(request.sessionId)) {\n      body[\"SessionId\"] = request.sessionId;\n    }\n\n    if (!$dara.isNull(request.type)) {\n      body[\"ContextType\"] = request.type;\n    }\n\n    const req = new $OpenApiUtil.OpenApiRequest({\n      body: OpenApiUtil.parseToMap(body),\n    });\n    const params = new $OpenApiUtil.Params({\n      action: \"ListContexts\",\n      version: \"2025-05-06\",\n      protocol: \"HTTPS\",\n      pathname: \"/\",\n      method: \"POST\",\n      authType: \"Anonymous\",\n      style: \"RPC\",\n      reqBodyType: \"formData\",\n      bodyType: \"json\",\n    });\n    return $dara.cast<$_model.ListContextsResponse>(\n      await this.callApi(params, req, runtime),\n      new $_model.ListContextsResponse({})\n    );\n  }\n\n  /**\n   * Get context list\n   *\n   * @param request - ListContextsRequest\n   * @returns ListContextsResponse\n   */\n  async listContexts(\n    request: $_model.ListContextsRequest\n  ): Promise<$_model.ListContextsResponse> {\n    const runtime = new $dara.RuntimeOptions({});\n    return await this.listContextsWithOptions(request, runtime);\n  }\n\n  /**\n   * ListMcpTools\n   *\n   * @param request - ListMcpToolsRequest\n   * @param runtime - runtime options for this request RuntimeOptions\n   * @returns ListMcpToolsResponse\n   */\n  async listMcpToolsWithOptions(\n    request: $_model.ListMcpToolsRequest,\n    runtime: $dara.RuntimeOptions\n  ): Promise<$_model.ListMcpToolsResponse> {\n    request.validate();\n    const body: { [key: string]: any } = {};\n    if (!$dara.isNull(request.authorization)) {\n      body[\"Authorization\"] = request.authorization;\n    }\n\n    if (!$dara.isNull(request.imageId)) {\n      body[\"ImageId\"] = request.imageId;\n    }\n\n    const req = new $OpenApiUtil.OpenApiRequest({\n      body: OpenApiUtil.parseToMap(body),\n    });\n    const params = new $OpenApiUtil.Params({\n      action: \"ListMcpTools\",\n      version: \"2025-05-06\",\n      protocol: \"HTTPS\",\n      pathname: \"/\",\n      method: \"POST\",\n      authType: \"Anonymous\",\n      style: \"RPC\",\n      reqBodyType: \"formData\",\n      bodyType: \"json\",\n    });\n    return $dara.cast<$_model.ListMcpToolsResponse>(\n      await this.callApi(params, req, runtime),\n      new $_model.ListMcpToolsResponse({})\n    );\n  }\n\n  /**\n   * ListMcpTools\n   *\n   * @param request - ListMcpToolsRequest\n   * @returns ListMcpToolsResponse\n   */\n  async listMcpTools(\n    request: $_model.ListMcpToolsRequest\n  ): Promise<$_model.ListMcpToolsResponse> {\n    const runtime = new $dara.RuntimeOptions({});\n    return await this.listMcpToolsWithOptions(request, runtime);\n  }\n\n  /**\n   * Query session list by label\n   *\n   * @param request - ListSessionRequest\n   * @param runtime - runtime options for this request RuntimeOptions\n   * @returns ListSessionResponse\n   */\n  async listSessionWithOptions(\n    request: $_model.ListSessionRequest,\n    runtime: $dara.RuntimeOptions\n  ): Promise<$_model.ListSessionResponse> {\n    request.validate();\n    const body: { [key: string]: any } = {};\n    if (!$dara.isNull(request.authorization)) {\n      body[\"Authorization\"] = request.authorization;\n    }\n\n    if (!$dara.isNull(request.labels)) {\n      body[\"Labels\"] = request.labels;\n    }\n\n    if (!$dara.isNull(request.maxResults)) {\n      body[\"MaxResults\"] = request.maxResults;\n    }\n\n    if (!$dara.isNull(request.nextToken)) {\n      body[\"NextToken\"] = request.nextToken;\n    }\n\n    if (!$dara.isNull(request.status)) {\n      body[\"Status\"] = request.status;\n    }\n\n    if (!$dara.isNull(request.imageId)) {\n      body[\"ImageId\"] = request.imageId;\n    }\n\n    const req = new $OpenApiUtil.OpenApiRequest({\n      body: OpenApiUtil.parseToMap(body),\n    });\n    const params = new $OpenApiUtil.Params({\n      action: \"ListSession\",\n      version: \"2025-05-06\",\n      protocol: \"HTTPS\",\n      pathname: \"/\",\n      method: \"POST\",\n      authType: \"Anonymous\",\n      style: \"RPC\",\n      reqBodyType: \"formData\",\n      bodyType: \"json\",\n    });\n    return $dara.cast<$_model.ListSessionResponse>(\n      await this.callApi(params, req, runtime),\n      new $_model.ListSessionResponse({})\n    );\n  }\n\n  /**\n   * Query session list by label\n   *\n   * @param request - ListSessionRequest\n   * @returns ListSessionResponse\n   */\n  async listSession(\n    request: $_model.ListSessionRequest\n  ): Promise<$_model.ListSessionResponse> {\n    const runtime = new $dara.RuntimeOptions({});\n    return await this.listSessionWithOptions(request, runtime);\n  }\n\n  /**\n   * List official skills metadata\n   *\n   * @param request - ListSkillMetaDataRequest\n   * @param runtime - runtime options for this request RuntimeOptions\n   * @returns ListSkillMetaDataResponse\n   */\n  async listSkillMetaDataWithOptions(\n    request: $_model.ListSkillMetaDataRequest,\n    runtime: $dara.RuntimeOptions\n  ): Promise<$_model.ListSkillMetaDataResponse> {\n    request.validate();\n    const body: { [key: string]: any } = {};\n    if (!$dara.isNull(request.authorization)) {\n      body[\"Authorization\"] = request.authorization;\n    }\n\n    const req = new $OpenApiUtil.OpenApiRequest({\n      body: OpenApiUtil.parseToMap(body),\n    });\n    const params = new $OpenApiUtil.Params({\n      action: \"ListSkillMetaData\",\n      version: \"2025-05-06\",\n      protocol: \"HTTPS\",\n      pathname: \"/\",\n      method: \"POST\",\n      authType: \"Anonymous\",\n      style: \"RPC\",\n      reqBodyType: \"formData\",\n      bodyType: \"json\",\n    });\n    return $dara.cast<$_model.ListSkillMetaDataResponse>(\n      await this.callApi(params, req, runtime),\n      new $_model.ListSkillMetaDataResponse({})\n    );\n  }\n\n  /**\n   * List official skills metadata\n   *\n   * @param request - ListSkillMetaDataRequest\n   * @returns ListSkillMetaDataResponse\n   */\n  async listSkillMetaData(\n    request: $_model.ListSkillMetaDataRequest\n  ): Promise<$_model.ListSkillMetaDataResponse> {\n    const runtime = new $dara.RuntimeOptions({});\n    return await this.listSkillMetaDataWithOptions(request, runtime);\n  }\n\n  /**\n   * GetSkillMetaData\n   *\n   * @param tmpReq - GetSkillMetaDataRequest\n   * @param runtime - runtime options for this request RuntimeOptions\n   * @returns GetSkillMetaDataResponse\n   */\n  async getSkillMetaDataWithOptions(\n    tmpReq: $_model.GetSkillMetaDataRequest,\n    runtime: $dara.RuntimeOptions\n  ): Promise<$_model.GetSkillMetaDataResponse> {\n    tmpReq.validate();\n    const request = new $_model.GetSkillMetaDataShrinkRequest({});\n    OpenApiUtil.convert(tmpReq, request);\n    if (!$dara.isNull(tmpReq.skillGroupIds)) {\n      request.skillGroupIdsShrink = OpenApiUtil.arrayToStringWithSpecifiedStyle(\n        tmpReq.skillGroupIds,\n        \"SkillGroupIds\",\n        \"json\"\n      );\n    }\n\n    const body: { [key: string]: any } = {};\n    if (!$dara.isNull(request.authorization)) {\n      body[\"Authorization\"] = request.authorization;\n    }\n\n    if (!$dara.isNull(request.imageId)) {\n      body[\"ImageId\"] = request.imageId;\n    }\n\n    if (!$dara.isNull(request.skillGroupIdsShrink)) {\n      body[\"SkillGroupIds\"] = request.skillGroupIdsShrink;\n    }\n\n    const req = new $OpenApiUtil.OpenApiRequest({\n      body: OpenApiUtil.parseToMap(body),\n    });\n    const params = new $OpenApiUtil.Params({\n      action: \"GetSkillMetaData\",\n      version: \"2025-05-06\",\n      protocol: \"HTTPS\",\n      pathname: \"/\",\n      method: \"POST\",\n      authType: \"Anonymous\",\n      style: \"RPC\",\n      reqBodyType: \"formData\",\n      bodyType: \"json\",\n    });\n    return $dara.cast<$_model.GetSkillMetaDataResponse>(\n      await this.callApi(params, req, runtime),\n      new $_model.GetSkillMetaDataResponse({})\n    );\n  }\n\n  /**\n   * GetSkillMetaData\n   *\n   * @param request - GetSkillMetaDataRequest\n   * @returns GetSkillMetaDataResponse\n   */\n  async getSkillMetaData(\n    request: $_model.GetSkillMetaDataRequest\n  ): Promise<$_model.GetSkillMetaDataResponse> {\n    const runtime = new $dara.RuntimeOptions({});\n    return await this.getSkillMetaDataWithOptions(request, runtime);\n  }\n\n  /**\n   * Modify context\n   *\n   * @param request - ModifyContextRequest\n   * @param runtime - runtime options for this request RuntimeOptions\n   * @returns ModifyContextResponse\n   */\n  async modifyContextWithOptions(\n    request: $_model.ModifyContextRequest,\n    runtime: $dara.RuntimeOptions\n  ): Promise<$_model.ModifyContextResponse> {\n    request.validate();\n    const body: { [key: string]: any } = {};\n    if (!$dara.isNull(request.authorization)) {\n      body[\"Authorization\"] = request.authorization;\n    }\n\n    if (!$dara.isNull(request.id)) {\n      body[\"Id\"] = request.id;\n    }\n\n    if (!$dara.isNull(request.name)) {\n      body[\"Name\"] = request.name;\n    }\n\n    const req = new $OpenApiUtil.OpenApiRequest({\n      body: OpenApiUtil.parseToMap(body),\n    });\n    const params = new $OpenApiUtil.Params({\n      action: \"ModifyContext\",\n      version: \"2025-05-06\",\n      protocol: \"HTTPS\",\n      pathname: \"/\",\n      method: \"POST\",\n      authType: \"Anonymous\",\n      style: \"RPC\",\n      reqBodyType: \"formData\",\n      bodyType: \"json\",\n    });\n    return $dara.cast<$_model.ModifyContextResponse>(\n      await this.callApi(params, req, runtime),\n      new $_model.ModifyContextResponse({})\n    );\n  }\n\n  /**\n   * Modify context\n   *\n   * @param request - ModifyContextRequest\n   * @returns ModifyContextResponse\n   */\n  async modifyContext(\n    request: $_model.ModifyContextRequest\n  ): Promise<$_model.ModifyContextResponse> {\n    const runtime = new $dara.RuntimeOptions({});\n    return await this.modifyContextWithOptions(request, runtime);\n  }\n\n  /**\n   * Release MCP session\n   *\n   * @param request - ReleaseMcpSessionRequest\n   * @param runtime - runtime options for this request RuntimeOptions\n   * @returns ReleaseMcpSessionResponse\n   */\n  async releaseMcpSessionWithOptions(\n    request: $_model.ReleaseMcpSessionRequest,\n    runtime: $dara.RuntimeOptions\n  ): Promise<$_model.ReleaseMcpSessionResponse> {\n    request.validate();\n    const body: { [key: string]: any } = {};\n    if (!$dara.isNull(request.authorization)) {\n      body[\"Authorization\"] = request.authorization;\n    }\n\n    if (!$dara.isNull(request.sessionId)) {\n      body[\"SessionId\"] = request.sessionId;\n    }\n\n    const req = new $OpenApiUtil.OpenApiRequest({\n      body: OpenApiUtil.parseToMap(body),\n    });\n    const params = new $OpenApiUtil.Params({\n      action: \"ReleaseMcpSession\",\n      version: \"2025-05-06\",\n      protocol: \"HTTPS\",\n      pathname: \"/\",\n      method: \"POST\",\n      authType: \"Anonymous\",\n      style: \"RPC\",\n      reqBodyType: \"formData\",\n      bodyType: \"json\",\n    });\n    return $dara.cast<$_model.ReleaseMcpSessionResponse>(\n      await this.callApi(params, req, runtime),\n      new $_model.ReleaseMcpSessionResponse({})\n    );\n  }\n\n  /**\n   * Release MCP session\n   *\n   * @param request - ReleaseMcpSessionRequest\n   * @returns ReleaseMcpSessionResponse\n   */\n  async releaseMcpSession(\n    request: $_model.ReleaseMcpSessionRequest\n  ): Promise<$_model.ReleaseMcpSessionResponse> {\n    const runtime = new $dara.RuntimeOptions({});\n    return await this.releaseMcpSessionWithOptions(request, runtime);\n  }\n\n  /**\n   * Set labels\n   *\n   * @param request - SetLabelRequest\n   * @param runtime - runtime options for this request RuntimeOptions\n   * @returns SetLabelResponse\n   */\n  async setLabelWithOptions(\n    request: $_model.SetLabelRequest,\n    runtime: $dara.RuntimeOptions\n  ): Promise<$_model.SetLabelResponse> {\n    request.validate();\n    const body: { [key: string]: any } = {};\n    if (!$dara.isNull(request.authorization)) {\n      body[\"Authorization\"] = request.authorization;\n    }\n\n    if (!$dara.isNull(request.labels)) {\n      body[\"Labels\"] = request.labels;\n    }\n\n    if (!$dara.isNull(request.sessionId)) {\n      body[\"SessionId\"] = request.sessionId;\n    }\n\n    const req = new $OpenApiUtil.OpenApiRequest({\n      body: OpenApiUtil.parseToMap(body),\n    });\n    const params = new $OpenApiUtil.Params({\n      action: \"SetLabel\",\n      version: \"2025-05-06\",\n      protocol: \"HTTPS\",\n      pathname: \"/\",\n      method: \"POST\",\n      authType: \"Anonymous\",\n      style: \"RPC\",\n      reqBodyType: \"formData\",\n      bodyType: \"json\",\n    });\n    return $dara.cast<$_model.SetLabelResponse>(\n      await this.callApi(params, req, runtime),\n      new $_model.SetLabelResponse({})\n    );\n  }\n\n  /**\n   * Set labels\n   *\n   * @param request - SetLabelRequest\n   * @returns SetLabelResponse\n   */\n  async setLabel(\n    request: $_model.SetLabelRequest\n  ): Promise<$_model.SetLabelResponse> {\n    const runtime = new $dara.RuntimeOptions({});\n    return await this.setLabelWithOptions(request, runtime);\n  }\n\n  /**\n   * Sync context\n   *\n   * @param request - SyncContextRequest\n   * @param runtime - runtime options for this request RuntimeOptions\n   * @returns SyncContextResponse\n   */\n  async syncContextWithOptions(\n    request: $_model.SyncContextRequest,\n    runtime: $dara.RuntimeOptions\n  ): Promise<$_model.SyncContextResponse> {\n    request.validate();\n    const query: { [key: string]: any } = {};\n    if (!$dara.isNull(request.authorization)) {\n      query[\"Authorization\"] = request.authorization;\n    }\n\n    const body: { [key: string]: any } = {};\n    if (!$dara.isNull(request.contextId)) {\n      body[\"ContextId\"] = request.contextId;\n    }\n\n    if (!$dara.isNull(request.mode)) {\n      body[\"Mode\"] = request.mode;\n    }\n\n    if (!$dara.isNull(request.path)) {\n      body[\"Path\"] = request.path;\n    }\n\n    if (!$dara.isNull(request.sessionId)) {\n      body[\"SessionId\"] = request.sessionId;\n    }\n\n    const req = new $OpenApiUtil.OpenApiRequest({\n      query: OpenApiUtil.query(query),\n      body: OpenApiUtil.parseToMap(body),\n    });\n    const params = new $OpenApiUtil.Params({\n      action: \"SyncContext\",\n      version: \"2025-05-06\",\n      protocol: \"HTTPS\",\n      pathname: \"/\",\n      method: \"POST\",\n      authType: \"Anonymous\",\n      style: \"RPC\",\n      reqBodyType: \"formData\",\n      bodyType: \"json\",\n    });\n    return $dara.cast<$_model.SyncContextResponse>(\n      await this.callApi(params, req, runtime),\n      new $_model.SyncContextResponse({})\n    );\n  }\n\n  /**\n   * Sync context\n   *\n   * @param request - SyncContextRequest\n   * @returns SyncContextResponse\n   */\n  async syncContext(\n    request: $_model.SyncContextRequest\n  ): Promise<$_model.SyncContextResponse> {\n    const runtime = new $dara.RuntimeOptions({});\n    return await this.syncContextWithOptions(request, runtime);\n  }\n\n  /**\n   * Initialize browser\n   *\n   * @param tmpReq - InitBrowserRequest\n   * @param runtime - runtime options for this request RuntimeOptions\n   * @returns InitBrowserResponse\n   */\n  async initBrowserWithOptions(\n    request: $_model.InitBrowserRequest,\n    runtime: $dara.RuntimeOptions\n  ): Promise<$_model.InitBrowserResponse> {\n    request.validate();\n    const body: { [key: string]: any } = {};\n    if (!$dara.isNull(request.authorization)) {\n      body[\"Authorization\"] = request.authorization;\n    }\n    if (!$dara.isNull(request.persistentPath)) {\n      body[\"PersistentPath\"] = request.persistentPath;\n    }\n    if (!$dara.isNull(request.sessionId)) {\n      body[\"SessionId\"] = request.sessionId;\n    }\n    if (!$dara.isNull(request.browserOption)) {\n      body[\"BrowserOption\"] = JSON.stringify(request.browserOption);\n    }\n    const req = new $OpenApiUtil.OpenApiRequest({\n      body: OpenApiUtil.parseToMap(body),\n    });\n    const params = new $OpenApiUtil.Params({\n      action: \"InitBrowser\",\n      version: \"2025-05-06\",\n      protocol: \"HTTPS\",\n      pathname: \"/\",\n      method: \"POST\",\n      authType: \"Anonymous\",\n      style: \"RPC\",\n      reqBodyType: \"formData\",\n      bodyType: \"json\",\n    });\n    return $dara.cast<$_model.InitBrowserResponse>(\n      await this.callApi(params, req, runtime),\n      new $_model.InitBrowserResponse({})\n    );\n  }\n\n  /**\n   * Initialize browser\n   *\n   * @param request - InitBrowserRequest\n   * @returns InitBrowserResponse\n   */\n  async initBrowser(\n    request: $_model.InitBrowserRequest\n  ): Promise<$_model.InitBrowserResponse> {\n    const runtime = new $dara.RuntimeOptions({});\n    return await this.initBrowserWithOptions(request, runtime);\n  }\n\n  /**\n   * Initialize browser (sync version)\n   *\n   * @param request - InitBrowserRequest\n   * @returns InitBrowserResponse\n   */\n  initBrowserSync(\n    request: $_model.InitBrowserRequest\n  ): $_model.InitBrowserResponse {\n    const runtime = new $dara.RuntimeOptions({});\n\n    request.validate();\n    const body: { [key: string]: any } = {};\n    if (!$dara.isNull(request.authorization)) {\n      body[\"Authorization\"] = request.authorization;\n    }\n    if (!$dara.isNull(request.persistentPath)) {\n      body[\"PersistentPath\"] = request.persistentPath;\n    }\n    if (!$dara.isNull(request.sessionId)) {\n      body[\"SessionId\"] = request.sessionId;\n    }\n    if (!$dara.isNull(request.browserOption)) {\n      body[\"BrowserOption\"] = JSON.stringify(request.browserOption);\n    }\n    const req = new $OpenApiUtil.OpenApiRequest({\n      body: OpenApiUtil.parseToMap(body),\n    });\n    const params = new $OpenApiUtil.Params({\n      action: \"InitBrowser\",\n      version: \"2025-05-06\",\n      protocol: \"HTTPS\",\n      pathname: \"/\",\n      method: \"POST\",\n      authType: \"Anonymous\",\n      style: \"RPC\",\n      reqBodyType: \"formData\",\n      bodyType: \"json\",\n    });\n    return $dara.cast<$_model.InitBrowserResponse>(\n      this.callApi(params, req, runtime),\n      new $_model.InitBrowserResponse({})\n    );\n  }\n\n  /**\n   * Get context file upload URL\n   *\n   * @param request - DeleteContextFileRequest\n   * @param runtime - runtime options for this request RuntimeOptions\n   * @returns DeleteContextFileResponse\n   */\n  async deleteContextFileWithOptions(\n    request: $_model.DeleteContextFileRequest,\n    runtime: $dara.RuntimeOptions\n  ): Promise<$_model.DeleteContextFileResponse> {\n    request.validate();\n    const body: { [key: string]: any } = {};\n    if (!$dara.isNull(request.authorization)) {\n      body[\"Authorization\"] = request.authorization;\n    }\n\n    if (!$dara.isNull(request.contextId)) {\n      body[\"ContextId\"] = request.contextId;\n    }\n\n    if (!$dara.isNull(request.filePath)) {\n      body[\"FilePath\"] = request.filePath;\n    }\n\n    const req = new $OpenApiUtil.OpenApiRequest({\n      body: OpenApiUtil.parseToMap(body),\n    });\n    const params = new $OpenApiUtil.Params({\n      action: \"DeleteContextFile\",\n      version: \"2025-05-06\",\n      protocol: \"HTTPS\",\n      pathname: \"/\",\n      method: \"POST\",\n      authType: \"Anonymous\",\n      style: \"RPC\",\n      reqBodyType: \"formData\",\n      bodyType: \"json\",\n    });\n    return $dara.cast<$_model.DeleteContextFileResponse>(\n      await this.callApi(params, req, runtime),\n      new $_model.DeleteContextFileResponse({})\n    );\n  }\n\n  /**\n   * Get context file upload URL\n   *\n   * @param request - DeleteContextFileRequest\n   * @returns DeleteContextFileResponse\n   */\n  async deleteContextFile(\n    request: $_model.DeleteContextFileRequest\n  ): Promise<$_model.DeleteContextFileResponse> {\n    const runtime = new $dara.RuntimeOptions({});\n    return await this.deleteContextFileWithOptions(request, runtime);\n  }\n\n  /**\n   * Query context specific directory files\n   *\n   * @param request - DescribeContextFilesRequest\n   * @param runtime - runtime options for this request RuntimeOptions\n   * @returns DescribeContextFilesResponse\n   */\n  async describeContextFilesWithOptions(\n    request: $_model.DescribeContextFilesRequest,\n    runtime: $dara.RuntimeOptions\n  ): Promise<$_model.DescribeContextFilesResponse> {\n    request.validate();\n    const query: { [key: string]: any } = {};\n    if (!$dara.isNull(request.maxResults)) {\n      query[\"MaxResults\"] = request.maxResults;\n    }\n\n    if (!$dara.isNull(request.nextToken)) {\n      query[\"NextToken\"] = request.nextToken;\n    }\n\n    const body: { [key: string]: any } = {};\n    if (!$dara.isNull(request.authorization)) {\n      body[\"Authorization\"] = request.authorization;\n    }\n\n    if (!$dara.isNull(request.pageNumber)) {\n      body[\"PageNumber\"] = request.pageNumber;\n    }\n\n    if (!$dara.isNull(request.pageSize)) {\n      body[\"PageSize\"] = request.pageSize;\n    }\n\n    if (!$dara.isNull(request.parentFolderPath)) {\n      body[\"ParentFolderPath\"] = request.parentFolderPath;\n    }\n\n    if (!$dara.isNull(request.contextId)) {\n      body[\"ContextId\"] = request.contextId;\n    }\n\n    const req = new $OpenApiUtil.OpenApiRequest({\n      query: OpenApiUtil.query(query),\n      body: OpenApiUtil.parseToMap(body),\n    });\n    const params = new $OpenApiUtil.Params({\n      action: \"DescribeContextFiles\",\n      version: \"2025-05-06\",\n      protocol: \"HTTPS\",\n      pathname: \"/\",\n      method: \"POST\",\n      authType: \"Anonymous\",\n      style: \"RPC\",\n      reqBodyType: \"formData\",\n      bodyType: \"json\",\n    });\n    return $dara.cast<$_model.DescribeContextFilesResponse>(\n      await this.callApi(params, req, runtime),\n      new $_model.DescribeContextFilesResponse({})\n    );\n  }\n\n  /**\n   * Query context specific directory files\n   *\n   * @param request - DescribeContextFilesRequest\n   * @returns DescribeContextFilesResponse\n   */\n  async describeContextFiles(\n    request: $_model.DescribeContextFilesRequest\n  ): Promise<$_model.DescribeContextFilesResponse> {\n    const runtime = new $dara.RuntimeOptions({});\n    return await this.describeContextFilesWithOptions(request, runtime);\n  }\n\n  /**\n   * Get context file upload URL\n   *\n   * @param request - GetContextFileDownloadUrlRequest\n   * @param runtime - runtime options for this request RuntimeOptions\n   * @returns GetContextFileDownloadUrlResponse\n   */\n  async getContextFileDownloadUrlWithOptions(\n    request: $_model.GetContextFileDownloadUrlRequest,\n    runtime: $dara.RuntimeOptions\n  ): Promise<$_model.GetContextFileDownloadUrlResponse> {\n    request.validate();\n    const body: { [key: string]: any } = {};\n    if (!$dara.isNull(request.authorization)) {\n      body[\"Authorization\"] = request.authorization;\n    }\n\n    if (!$dara.isNull(request.contextId)) {\n      body[\"ContextId\"] = request.contextId;\n    }\n\n    if (!$dara.isNull(request.filePath)) {\n      body[\"FilePath\"] = request.filePath;\n    }\n\n    const req = new $OpenApiUtil.OpenApiRequest({\n      body: OpenApiUtil.parseToMap(body),\n    });\n    const params = new $OpenApiUtil.Params({\n      action: \"GetContextFileDownloadUrl\",\n      version: \"2025-05-06\",\n      protocol: \"HTTPS\",\n      pathname: \"/\",\n      method: \"POST\",\n      authType: \"Anonymous\",\n      style: \"RPC\",\n      reqBodyType: \"formData\",\n      bodyType: \"json\",\n    });\n    return $dara.cast<$_model.GetContextFileDownloadUrlResponse>(\n      await this.callApi(params, req, runtime),\n      new $_model.GetContextFileDownloadUrlResponse({})\n    );\n  }\n\n  /**\n   * Get context file upload URL\n   *\n   * @param request - GetContextFileDownloadUrlRequest\n   * @returns GetContextFileDownloadUrlResponse\n   */\n  async getContextFileDownloadUrl(\n    request: $_model.GetContextFileDownloadUrlRequest\n  ): Promise<$_model.GetContextFileDownloadUrlResponse> {\n    const runtime = new $dara.RuntimeOptions({});\n    return await this.getContextFileDownloadUrlWithOptions(request, runtime);\n  }\n\n  /**\n   * Get context file upload URL\n   *\n   * @param request - GetContextFileUploadUrlRequest\n   * @param runtime - runtime options for this request RuntimeOptions\n   * @returns GetContextFileUploadUrlResponse\n   */\n  async getContextFileUploadUrlWithOptions(\n    request: $_model.GetContextFileUploadUrlRequest,\n    runtime: $dara.RuntimeOptions\n  ): Promise<$_model.GetContextFileUploadUrlResponse> {\n    request.validate();\n    const body: { [key: string]: any } = {};\n    if (!$dara.isNull(request.authorization)) {\n      body[\"Authorization\"] = request.authorization;\n    }\n\n    if (!$dara.isNull(request.contextId)) {\n      body[\"ContextId\"] = request.contextId;\n    }\n\n    if (!$dara.isNull(request.filePath)) {\n      body[\"FilePath\"] = request.filePath;\n    }\n\n    const req = new $OpenApiUtil.OpenApiRequest({\n      body: OpenApiUtil.parseToMap(body),\n    });\n    const params = new $OpenApiUtil.Params({\n      action: \"GetContextFileUploadUrl\",\n      version: \"2025-05-06\",\n      protocol: \"HTTPS\",\n      pathname: \"/\",\n      method: \"POST\",\n      authType: \"Anonymous\",\n      style: \"RPC\",\n      reqBodyType: \"formData\",\n      bodyType: \"json\",\n    });\n    return $dara.cast<$_model.GetContextFileUploadUrlResponse>(\n      await this.callApi(params, req, runtime),\n      new $_model.GetContextFileUploadUrlResponse({})\n    );\n  }\n\n  /**\n   * Get context file upload URL\n   *\n   * @param request - GetContextFileUploadUrlRequest\n   * @returns GetContextFileUploadUrlResponse\n   */\n  async getContextFileUploadUrl(\n    request: $_model.GetContextFileUploadUrlRequest\n  ): Promise<$_model.GetContextFileUploadUrlResponse> {\n    const runtime = new $dara.RuntimeOptions({});\n    return await this.getContextFileUploadUrlWithOptions(request, runtime);\n  }\n\n  /**\n   * Get CDP link\n   *\n   * @param request - GetCdpLinkRequest\n   * @param runtime - runtime options for this request RuntimeOptions\n   * @returns GetCdpLinkResponse\n   */\n  async getCdpLinkWithOptions(\n    request: $_model.GetCdpLinkRequest,\n    runtime: $dara.RuntimeOptions\n  ): Promise<$_model.GetCdpLinkResponse> {\n    request.validate();\n    const body: { [key: string]: any } = {};\n    if (!$dara.isNull(request.authorization)) {\n      body[\"Authorization\"] = request.authorization;\n    }\n    if (!$dara.isNull(request.sessionId)) {\n      body[\"SessionId\"] = request.sessionId;\n    }\n\n    const req = new $OpenApiUtil.OpenApiRequest({\n      body: OpenApiUtil.parseToMap(body),\n    });\n    const params = new $OpenApiUtil.Params({\n      action: \"GetCdpLink\",\n      version: \"2025-05-06\",\n      protocol: \"HTTPS\",\n      pathname: \"/\",\n      method: \"POST\",\n      authType: \"Anonymous\",\n      style: \"RPC\",\n      reqBodyType: \"formData\",\n      bodyType: \"json\",\n    });\n    return $dara.cast<$_model.GetCdpLinkResponse>(\n      await this.doRPCRequest(\n        params.action,\n        params.version,\n        params.protocol,\n        params.method,\n        params.authType,\n        params.bodyType,\n        req,\n        runtime\n      ),\n      new $_model.GetCdpLinkResponse({})\n    );\n  }\n\n  /**\n   * Get CDP link\n   *\n   * @param request - GetCdpLinkRequest\n   * @returns GetCdpLinkResponse\n   */\n  async getCdpLink(\n    request: $_model.GetCdpLinkRequest\n  ): Promise<$_model.GetCdpLinkResponse> {\n    const runtime = new $dara.RuntimeOptions({});\n    return await this.getCdpLinkWithOptions(request, runtime);\n  }\n\n  /**\n   * Get ADB link\n   *\n   * @param request - GetAdbLinkRequest\n   * @param runtime - runtime options for this request RuntimeOptions\n   * @returns GetAdbLinkResponse\n   */\n  async getAdbLinkWithOptions(\n    request: $_model.GetAdbLinkRequest,\n    runtime: $dara.RuntimeOptions\n  ): Promise<$_model.GetAdbLinkResponse> {\n    request.validate();\n    const body: { [key: string]: any } = {};\n    if (!$dara.isNull(request.authorization)) {\n      body[\"Authorization\"] = request.authorization;\n    }\n    if (!$dara.isNull(request.option)) {\n      body[\"Option\"] = request.option;\n    }\n    if (!$dara.isNull(request.sessionId)) {\n      body[\"SessionId\"] = request.sessionId;\n    }\n\n    const req = new $OpenApiUtil.OpenApiRequest({\n      body: OpenApiUtil.parseToMap(body),\n    });\n    const params = new $OpenApiUtil.Params({\n      action: \"GetAdbLink\",\n      version: \"2025-05-06\",\n      protocol: \"HTTPS\",\n      pathname: \"/\",\n      method: \"POST\",\n      authType: \"Anonymous\",\n      style: \"RPC\",\n      reqBodyType: \"formData\",\n      bodyType: \"json\",\n    });\n    return $dara.cast<$_model.GetAdbLinkResponse>(\n      await this.doRPCRequest(\n        params.action,\n        params.version,\n        params.protocol,\n        params.method,\n        params.authType,\n        params.bodyType,\n        req,\n        runtime\n      ),\n      new $_model.GetAdbLinkResponse({})\n    );\n  }\n\n  /**\n   * Get ADB link\n   *\n   * @param request - GetAdbLinkRequest\n   * @returns GetAdbLinkResponse\n   */\n  async getAdbLink(\n    request: $_model.GetAdbLinkRequest\n  ): Promise<$_model.GetAdbLinkResponse> {\n    const runtime = new $dara.RuntimeOptions({});\n    return await this.getAdbLinkWithOptions(request, runtime);\n  }\n\n  async bindContextsWithOptions(\n    tmpReq: $_model.BindContextsRequest,\n    runtime: $dara.RuntimeOptions\n  ): Promise<$_model.BindContextsResponse> {\n    tmpReq.validate();\n    const request = new $_model.BindContextsShrinkRequest({});\n    OpenApiUtil.convert(tmpReq, request);\n    if (!$dara.isNull(tmpReq.persistenceDataList)) {\n      request.persistenceDataListShrink =\n        OpenApiUtil.arrayToStringWithSpecifiedStyle(\n          tmpReq.persistenceDataList,\n          \"PersistenceDataList\",\n          \"json\"\n        );\n    }\n\n    const body: { [key: string]: any } = {};\n    if (!$dara.isNull(request.authorization)) {\n      body[\"Authorization\"] = request.authorization;\n    }\n    if (!$dara.isNull(request.persistenceDataListShrink)) {\n      body[\"PersistenceDataList\"] = request.persistenceDataListShrink;\n    }\n    if (!$dara.isNull(request.sessionId)) {\n      body[\"SessionId\"] = request.sessionId;\n    }\n\n    const req = new $OpenApiUtil.OpenApiRequest({\n      body: OpenApiUtil.parseToMap(body),\n    });\n    const params = new $OpenApiUtil.Params({\n      action: \"BindContexts\",\n      version: \"2025-05-06\",\n      protocol: \"HTTPS\",\n      pathname: \"/\",\n      method: \"POST\",\n      authType: \"Anonymous\",\n      style: \"RPC\",\n      reqBodyType: \"formData\",\n      bodyType: \"json\",\n    });\n    return $dara.cast<$_model.BindContextsResponse>(\n      await this.doRPCRequest(\n        params.action,\n        params.version,\n        params.protocol,\n        params.method,\n        params.authType,\n        params.bodyType,\n        req,\n        runtime\n      ),\n      new $_model.BindContextsResponse({})\n    );\n  }\n\n  async bindContexts(\n    request: $_model.BindContextsRequest\n  ): Promise<$_model.BindContextsResponse> {\n    const runtime = new $dara.RuntimeOptions({});\n    return await this.bindContextsWithOptions(request, runtime);\n  }\n\n  async describeSessionContextsWithOptions(\n    request: $_model.DescribeSessionContextsRequest,\n    runtime: $dara.RuntimeOptions\n  ): Promise<$_model.DescribeSessionContextsResponse> {\n    request.validate();\n    const body: { [key: string]: any } = {};\n    if (!$dara.isNull(request.authorization)) {\n      body[\"Authorization\"] = request.authorization;\n    }\n    if (!$dara.isNull(request.sessionId)) {\n      body[\"SessionId\"] = request.sessionId;\n    }\n\n    const req = new $OpenApiUtil.OpenApiRequest({\n      body: OpenApiUtil.parseToMap(body),\n    });\n    const params = new $OpenApiUtil.Params({\n      action: \"DescribeSessionContexts\",\n      version: \"2025-05-06\",\n      protocol: \"HTTPS\",\n      pathname: \"/\",\n      method: \"POST\",\n      authType: \"Anonymous\",\n      style: \"RPC\",\n      reqBodyType: \"formData\",\n      bodyType: \"json\",\n    });\n    return $dara.cast<$_model.DescribeSessionContextsResponse>(\n      await this.doRPCRequest(\n        params.action,\n        params.version,\n        params.protocol,\n        params.method,\n        params.authType,\n        params.bodyType,\n        req,\n        runtime\n      ),\n      new $_model.DescribeSessionContextsResponse({})\n    );\n  }\n\n  async describeSessionContexts(\n    request: $_model.DescribeSessionContextsRequest\n  ): Promise<$_model.DescribeSessionContextsResponse> {\n    const runtime = new $dara.RuntimeOptions({});\n    return await this.describeSessionContextsWithOptions(request, runtime);\n  }\n}\n","import * as fs from \"fs\";\nimport * as path from \"path\";\nimport * as dotenv from \"dotenv\";\n\ninterface Config {\n  endpoint: string;\n  timeout_ms: number;\n  region_id?: string;\n}\n\n/**\n * User-supplied configuration. The preferred input is `region_id`; the SDK\n * derives the endpoint from it via direct pattern substitution. `endpoint`\n * is retained as a deprecated fallback: when `region_id` is not set the\n * value of `endpoint` is used as-is. When both are set, `region_id` wins.\n */\ntype ConfigOptions = {\n  timeout_ms?: number;\n  region_id?: string;\n  /**\n   * @deprecated Since 0.22.0. Pass `region_id` instead. The value is honored\n   * only as a fallback when `region_id` is not set (in code or via\n   * AGENTBAY_REGION_ID). Either form emits a deprecation warning. Will be\n   * removed in a future major version.\n   */\n  endpoint?: string;\n};\n\n/**\n * Endpoint is no longer user-configurable; it is derived from region_id by\n * direct pattern substitution for production regions, and by a hardcoded\n * lookup table for pre-release regions (since pre-release hostnames don't\n * follow a single pattern: e.g. cn-hangzhou uses \"agentbay-pre.*\" while\n * ap-southeast-1 uses \"wuyingai-pre.*\").\n */\nconst DEFAULT_REGION = \"cn-hangzhou\";\nconst PRE_PREFIX = \"pre-\";\n\n/**\n * Known production regions. Unknown entries are NOT rejected — they fall\n * through to the default \"agentbay.{region}.aliyuncs.com\" pattern with a\n * console.warn line, so newly onboarded regions work without an SDK\n * upgrade while typos still surface a hint before the request actually fires.\n */\nconst KNOWN_REGIONS: readonly string[] = [\n  \"cn-hangzhou\",\n  \"ap-southeast-1\",\n  \"us-east-1\",\n];\n\n/**\n * Hardcoded mapping for pre-release regions (after stripping the \"pre-\" prefix).\n * Unknown entries fall back to \"agentbay-pre.{actual}.aliyuncs.com\" with a\n * console.warn line, since we genuinely don't know which pre-release naming\n * convention a new region will adopt.\n */\nconst PRE_REGION_ENDPOINT_MAP: { readonly [region: string]: string } = {\n  \"cn-hangzhou\": \"agentbay-pre.cn-hangzhou.aliyuncs.com\",\n  \"ap-southeast-1\": \"wuyingai-pre.ap-southeast-1.aliyuncs.com\",\n};\n\n/**\n * Resolve (actualRegion, endpoint) from a user-supplied region_id.\n *\n * Empty/undefined region falls back to the default. A \"pre-\" prefix selects\n * the pre-release endpoint and is stripped from the returned region:\n *  - Known pre regions use the hardcoded entry in PRE_REGION_ENDPOINT_MAP.\n *  - Unknown pre regions log a warning and fall back to the default\n *    \"agentbay-pre.{actual}.aliyuncs.com\" pattern.\n *\n * Non-pre regions are composed by direct pattern substitution. No whitelist\n * validation — any non-empty region_id is accepted so newly onboarded\n * regions work without an SDK upgrade.\n */\nfunction resolveEndpoint(regionId?: string): {\n  region: string;\n  endpoint: string;\n} {\n  const id = regionId && regionId.length > 0 ? regionId : DEFAULT_REGION;\n\n  if (id.startsWith(PRE_PREFIX)) {\n    const actual = id.slice(PRE_PREFIX.length);\n    if (actual in PRE_REGION_ENDPOINT_MAP) {\n      return { region: actual, endpoint: PRE_REGION_ENDPOINT_MAP[actual] };\n    }\n    console.warn(\n      `Unknown pre-release region 'pre-${actual}'. Falling back to ` +\n        `'agentbay-pre.${actual}.aliyuncs.com'; the request may fail at DNS ` +\n        `resolution if the host does not exist. Known pre regions: ` +\n        `${Object.keys(PRE_REGION_ENDPOINT_MAP).join(\", \")}.`\n    );\n    return { region: actual, endpoint: `agentbay-pre.${actual}.aliyuncs.com` };\n  }\n\n  if (!KNOWN_REGIONS.includes(id)) {\n    console.warn(\n      `Unknown region '${id}'. Falling back to 'agentbay.${id}.aliyuncs.com'; ` +\n        `the request may fail at DNS resolution if the host does not exist. ` +\n        `Known regions: ${KNOWN_REGIONS.join(\", \")}.`\n    );\n  }\n  return { region: id, endpoint: `agentbay.${id}.aliyuncs.com` };\n}\n\n/**\n * Browser data path constant\n */\nconst BROWSER_DATA_PATH = \"/tmp/agentbay_browser\";\n\n/**\n * Browser fingerprint persistent path constant\n */\nconst BROWSER_FINGERPRINT_PERSIST_PATH = \"/tmp/browser_fingerprint\";\n\n/**\n * Browser recording path constant\n */\nexport const BROWSER_RECORD_PATH = \"/home/wuying/record\";\n\n/**\n * Returns the default configuration\n */\nfunction defaultConfig(): Config {\n  return {\n    endpoint: resolveEndpoint(DEFAULT_REGION).endpoint,\n    timeout_ms: 60000,\n    region_id: DEFAULT_REGION,\n  };\n}\n\n/**\n * Find .env file by searching upward from start_path.\n *\n * Search order:\n * 1. Current working directory\n * 2. Parent directories (up to root)\n * 3. Git repository root (if found)\n *\n * @param startPath Starting directory for search (defaults to current working directory)\n * @returns Path to .env file if found, null otherwise\n */\nfunction findDotEnvFile(startPath?: string): string | null {\n  const currentPath = startPath ? path.resolve(startPath) : process.cwd();\n  let searchPath = currentPath;\n\n  // Search upward until we reach root directory\n  while (searchPath !== path.dirname(searchPath)) {\n    const envFile = path.join(searchPath, \".env\");\n    if (fs.existsSync(envFile)) {\n      return envFile;\n    }\n\n    // Check if this is a git repository root\n    const gitDir = path.join(searchPath, \".git\");\n    if (fs.existsSync(gitDir)) {\n      // Found git root, continue searching\n    }\n\n    searchPath = path.dirname(searchPath);\n  }\n\n  // Check root directory as well\n  const rootEnv = path.join(searchPath, \".env\");\n  if (fs.existsSync(rootEnv)) {\n    return rootEnv;\n  }\n\n  return null;\n}\n\n/**\n * Load .env file with improved search strategy.\n *\n * @param customEnvPath Custom path to .env file (optional)\n */\nfunction loadDotEnvWithFallback(customEnvPath?: string): void {\n  if (customEnvPath) {\n    // Use custom path if provided\n    if (fs.existsSync(customEnvPath)) {\n      try {\n        const envConfig = dotenv.parse(fs.readFileSync(customEnvPath));\n        for (const k in envConfig) {\n          // only load env variables that are not already set in process.env\n          if (!process.env.hasOwnProperty(k)) {\n            process.env[k] = envConfig[k];\n          }\n        }\n        return;\n      } catch (error) {\n        // Silently fail - .env loading is optional\n      }\n    }\n  }\n\n  // Find .env file using upward search\n  const envFile = findDotEnvFile();\n  if (envFile) {\n    try {\n      const envConfig = dotenv.parse(fs.readFileSync(envFile));\n      for (const k in envConfig) {\n        // only load env variables that are not already set in process.env\n        if (!process.env.hasOwnProperty(k)) {\n          process.env[k] = envConfig[k];\n        }\n      }\n    } catch (error) {\n      // Silently fail - .env loading is optional\n    }\n  }\n}\n\n// Track if .env file has been loaded to avoid duplicate loading\nlet dotEnvLoaded = false;\n\n// Auto-load .env file on module initialization\n// This ensures environment variables are available before logger module is loaded\nif (!dotEnvLoaded) {\n  try {\n    loadDotEnvWithFallback();\n    dotEnvLoaded = true;\n  } catch (error) {\n    // Silently fail - .env loading is optional\n  }\n}\n\n/**\n * Precedence (highest to lowest), evaluated independently for region_id and\n * the deprecated endpoint fallback:\n *  1. Explicit customConfig.region_id in code.\n *  2. Explicit customConfig.endpoint in code (deprecated fallback).\n *  3. AGENTBAY_REGION_ID environment variable.\n *  4. AGENTBAY_ENDPOINT environment variable (deprecated fallback).\n *  5. Default region (cn-hangzhou).\n *\n * When region_id is resolved at any level, the endpoint is derived from it\n * via the pattern. The endpoint fallback only kicks in when no region_id is\n * found at any level, and it bypasses the pattern (the value is used as-is).\n */\nfunction loadConfig(\n  customConfig?: ConfigOptions,\n  customEnvPath?: string\n): Config {\n  const config = defaultConfig();\n  let explicitRegion: string | undefined;\n  let explicitEndpoint: string | undefined;\n\n  if (customConfig) {\n    // If custom config is provided, do NOT load env/.env.\n    if (\n      typeof customConfig.timeout_ms === \"number\" &&\n      Number.isFinite(customConfig.timeout_ms) &&\n      customConfig.timeout_ms > 0\n    ) {\n      config.timeout_ms = customConfig.timeout_ms;\n    }\n\n    if (\n      typeof customConfig.region_id === \"string\" &&\n      customConfig.region_id.length > 0\n    ) {\n      explicitRegion = customConfig.region_id;\n    }\n\n    if (\n      typeof customConfig.endpoint === \"string\" &&\n      customConfig.endpoint.length > 0\n    ) {\n      explicitEndpoint = customConfig.endpoint;\n    }\n\n    if (explicitRegion && explicitEndpoint) {\n      console.warn(\n        `[DeprecationWarning] Config region_id=${JSON.stringify(\n          explicitRegion\n        )} and endpoint=${JSON.stringify(\n          explicitEndpoint\n        )}: both set; endpoint is ignored because region_id takes precedence.`\n      );\n      explicitEndpoint = undefined;\n    } else if (explicitEndpoint) {\n      console.warn(\n        `[DeprecationWarning] Config endpoint=${JSON.stringify(\n          explicitEndpoint\n        )} is deprecated; pass region_id instead. The value is used as a fallback when region_id is not set, and will be removed in a future major version.`\n      );\n    }\n  } else {\n    // Load .env file with improved search first\n    try {\n      loadDotEnvWithFallback(customEnvPath);\n    } catch (error) {\n      // Silently fail - .env loading is optional\n    }\n\n    if (process.env.AGENTBAY_TIMEOUT_MS) {\n      const timeout = parseInt(process.env.AGENTBAY_TIMEOUT_MS, 10);\n      if (!isNaN(timeout) && timeout > 0) {\n        config.timeout_ms = timeout;\n      }\n    }\n\n    if (process.env.AGENTBAY_REGION_ID) {\n      explicitRegion = process.env.AGENTBAY_REGION_ID;\n    }\n    if (process.env.AGENTBAY_ENDPOINT) {\n      const envEndpoint = process.env.AGENTBAY_ENDPOINT;\n      if (explicitRegion) {\n        console.warn(\n          `[DeprecationWarning] AGENTBAY_ENDPOINT=${JSON.stringify(\n            envEndpoint\n          )} is deprecated and ignored because AGENTBAY_REGION_ID is also set. Unset AGENTBAY_ENDPOINT to silence this warning.`\n        );\n      } else {\n        console.warn(\n          `[DeprecationWarning] AGENTBAY_ENDPOINT=${JSON.stringify(\n            envEndpoint\n          )} is deprecated; set AGENTBAY_REGION_ID instead. The value is used as a fallback and will be removed in a future major version.`\n        );\n        explicitEndpoint = envEndpoint;\n      }\n    }\n  }\n\n  if (explicitRegion) {\n    const resolved = resolveEndpoint(explicitRegion);\n    config.region_id = resolved.region;\n    config.endpoint = resolved.endpoint;\n  } else if (explicitEndpoint) {\n    // Deprecated fallback: use the user-supplied endpoint verbatim.\n    // region_id is left at its default so downstream code that reads it\n    // (e.g. for telemetry) still has a non-empty value.\n    config.endpoint = explicitEndpoint;\n  } else {\n    const resolved = resolveEndpoint(config.region_id);\n    config.region_id = resolved.region;\n    config.endpoint = resolved.endpoint;\n  }\n  return config;\n}\n\nexport { Config, loadConfig, loadDotEnvWithFallback, resolveEndpoint };\nexport type { ConfigOptions };\n","import { AgentBay } from \"./agent-bay\";\nimport { APIError } from \"./exceptions\";\nimport * as $_client from \"./api\";\nimport {\n  log,\n  logError,\n  logInfo,\n  logDebug,\n  logAPICall,\n  logAPIResponseWithDetails,\n  setRequestId,\n  getRequestId,\n} from \"./utils/logger\";\nimport {\n  extractRequestId,\n  ContextResult,\n  ContextListResult,\n  OperationResult,\n  FileUrlResult,\n  ContextFileListResult,\n  ContextFileEntry,\n  ClearContextResult,\n} from \"./types/api-response\";\n\n/**\n * Represents a persistent storage context in the AgentBay cloud environment.\n */\nexport class Context {\n  /**\n   * The unique identifier of the context.\n   */\n  id: string;\n\n  /**\n   * The name of the context.\n   */\n  name: string;\n\n  /**\n   * Date and time when the Context was created.\n   */\n  createdAt?: string;\n\n  /**\n   * Date and time when the Context was last used.\n   */\n  lastUsedAt?: string;\n\n  /**\n   * Initialize a Context object.\n   *\n   * @param id - The unique identifier of the context.\n   * @param name - The name of the context.\n   * @param createdAt - Date and time when the Context was created.\n   * @param lastUsedAt - Date and time when the Context was last used.\n   */\n  constructor(\n    id: string,\n    name: string,\n    createdAt?: string,\n    lastUsedAt?: string\n  ) {\n    this.id = id;\n    this.name = name;\n    this.createdAt = createdAt;\n    this.lastUsedAt = lastUsedAt;\n  }\n}\n\n/**\n * Parameters for listing contexts with pagination support.\n */\nexport interface ContextListParams {\n  /**\n   * Maximum number of results per page.\n   * Defaults to 10 if not specified.\n   */\n  maxResults?: number;\n\n  /**\n   * Token for the next page of results.\n   */\n  nextToken?: string;\n  /**\n   * Optional session id to filter contexts by session\n   */\n  sessionId?: string;\n}\n\n/**\n * Provides methods to manage persistent contexts in the AgentBay cloud environment.\n */\nexport class ContextService {\n  private agentBay: AgentBay;\n\n  /**\n   * Initialize the ContextService.\n   *\n   * @param agentBay - The AgentBay instance.\n   */\n  constructor(agentBay: AgentBay) {\n    this.agentBay = agentBay;\n  }\n\n  /**\n   * Lists all available contexts with pagination support.\n   * Corresponds to Python's list() method\n   *\n   * @param params - Optional parameters for listing contexts.\n   * @returns ContextListResult with contexts list and pagination information\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: 'your_api_key' });\n   * const result = await agentBay.context.list({ maxResults: 10 });\n   * if (result.success) {\n   *   console.log(`Total contexts: ${result.totalCount}`);\n   *   console.log(`Page has ${result.contexts.length} contexts`);\n   * }\n   * ```\n   */\n  async list(params?: ContextListParams): Promise<ContextListResult> {\n    try {\n      // Set default maxResults if not specified\n      const maxResults =\n        params?.maxResults !== undefined ? params.maxResults : 10;\n\n      const request = new $_client.ListContextsRequest({\n        authorization: `Bearer ${this.agentBay.getAPIKey()}`,\n        maxResults: maxResults,\n        nextToken: params?.nextToken,\n        sessionId: params?.sessionId,\n      });\n\n      // Log API request\n      logAPICall(\"ListContexts\");\n      logDebug(\n        `Request: MaxResults=${maxResults}`,\n        params?.nextToken ? `, NextToken=${params.nextToken}` : \"\"\n      );\n\n      const response = await this.agentBay.getClient().listContexts(request);\n\n      // Extract request ID\n      const requestId = extractRequestId(response) || \"\";\n\n      // Check for API-level errors\n      if (response.body?.success === false && response.body?.code) {\n        const errorMessage = `[${response.body.code}] ${\n          response.body.message || \"Unknown error\"\n        }`;\n        const fullResponse = response.body\n          ? JSON.stringify(response.body, null, 2)\n          : \"\";\n        logAPIResponseWithDetails(\n          \"ListContexts\",\n          requestId,\n          false,\n          undefined,\n          fullResponse\n        );\n        return {\n          requestId,\n          success: false,\n          contexts: [],\n          errorMessage,\n        };\n      }\n\n      const contexts: Context[] = [];\n      if (response.body?.data) {\n        for (const contextData of response.body.data) {\n          contexts.push(\n            new Context(\n              contextData.id || \"\",\n              contextData.name || \"\",\n              contextData.createTime,\n              contextData.lastUsedTime\n            )\n          );\n        }\n      }\n\n      // Log API response with key fields\n      const keyFields: Record<string, any> = {\n        context_count: contexts.length,\n        max_results: maxResults,\n      };\n      if (response.body?.totalCount !== undefined) {\n        keyFields.total_count = response.body.totalCount;\n      }\n      const fullResponse = response.body\n        ? JSON.stringify(response.body, null, 2)\n        : \"\";\n      logAPIResponseWithDetails(\n        \"ListContexts\",\n        requestId,\n        true,\n        keyFields,\n        fullResponse\n      );\n\n      return {\n        requestId,\n        success: true,\n        contexts,\n        nextToken: response.body?.nextToken,\n        maxResults: response.body?.maxResults || maxResults,\n        totalCount: response.body?.totalCount,\n      };\n    } catch (error) {\n      logError(\"Error calling ListContexts:\", error);\n      return {\n        requestId: \"\",\n        success: false,\n        contexts: [],\n        errorMessage: `Failed to list contexts: ${error}`,\n      };\n    }\n  }\n\n  /**\n   * Retrieves an existing context or creates a new one.\n   *\n   * @param name - The name of the context to retrieve or create.\n   * @param create - If true, creates the context if it doesn't exist. Defaults to false.\n   *\n   * @returns Promise resolving to ContextResult containing the Context object.\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: 'your_api_key' });\n   * const result = await agentBay.context.get('my-context', true);\n   * if (result.success) {\n   *   console.log(`Context ID: ${result.context.id}`);\n   *   console.log(`Context Name: ${result.context.name}`);\n   * }\n   * ```\n   *\n   * @see {@link update}, {@link list}\n   */\n  async get(name: string, create = false): Promise<ContextResult> {\n    try {\n      const request = new $_client.GetContextRequest({\n        name: name,\n        allowCreate: create ? \"true\" : \"false\",\n        authorization: `Bearer ${this.agentBay.getAPIKey()}`,\n      });\n\n      // Add LoginRegionId only when creating (create=true)\n      if (create && this.agentBay.getRegionId()) {\n        request.loginRegionId = this.agentBay.getRegionId();\n      }\n\n      // Log API request\n      logAPICall(\"GetContext\");\n      logDebug(`Request: Name=${name}, AllowCreate=${create}`);\n\n      const response = await this.agentBay.getClient().getContext(request);\n\n      // Extract request ID\n      const requestId = extractRequestId(response) || \"\";\n\n      // Check for API-level errors\n      if (response.body?.success === false && response.body?.code) {\n        const errorMessage = `[${response.body.code}] ${\n          response.body.message || \"Unknown error\"\n        }`;\n        const fullResponse = response.body\n          ? JSON.stringify(response.body, null, 2)\n          : \"\";\n        logAPIResponseWithDetails(\n          \"GetContext\",\n          requestId,\n          false,\n          undefined,\n          fullResponse\n        );\n        return {\n          requestId,\n          success: false,\n          contextId: \"\",\n          context: undefined,\n          errorMessage,\n        };\n      }\n\n      const contextId = response.body?.data?.id || \"\";\n      if (!contextId) {\n        logAPIResponseWithDetails(\n          \"GetContext\",\n          requestId,\n          false,\n          undefined,\n          \"Context ID not found in response\"\n        );\n        return {\n          requestId,\n          success: false,\n          contextId: \"\",\n          context: undefined,\n          errorMessage: \"Context ID not found in response\",\n        };\n      }\n\n      // Get the full context details\n      try {\n        const contextsResponse = await this.list();\n        for (const context of contextsResponse.contexts) {\n          if (context.id === contextId) {\n            // Log API response with key fields\n            const keyFields: Record<string, any> = {\n              context_id: contextId,\n              context_name: context.name,\n            };\n            const fullResponse = response.body\n              ? JSON.stringify(response.body, null, 2)\n              : \"\";\n            logAPIResponseWithDetails(\n              \"GetContext\",\n              requestId,\n              true,\n              keyFields,\n              fullResponse\n            );\n            return {\n              requestId,\n              success: true,\n              contextId,\n              context,\n            };\n          }\n        }\n      } catch (listError) {\n        logDebug(\n          `Warning: Failed to get full context details from list: ${listError}`\n        );\n      }\n\n      // If we couldn't find the context in the list, create a basic one\n      const context = new Context(contextId, name);\n      const keyFields: Record<string, any> = {\n        context_id: contextId,\n        context_name: name,\n      };\n      const fullResponse = response.body\n        ? JSON.stringify(response.body, null, 2)\n        : \"\";\n      logAPIResponseWithDetails(\n        \"GetContext\",\n        requestId,\n        true,\n        keyFields,\n        fullResponse\n      );\n      return {\n        requestId,\n        success: true,\n        contextId,\n        context,\n      };\n    } catch (error) {\n      logError(\"Error calling GetContext:\", error);\n      return {\n        requestId: \"\",\n        success: false,\n        contextId: \"\",\n        context: undefined,\n        errorMessage: `Failed to get context ${name}: ${error}`,\n      };\n    }\n  }\n\n  /**\n   * Creates a new context with the given name.\n   * Corresponds to Python's create() method\n   *\n   * @param name - The name for the new context.\n   * @returns ContextResult with created context data and requestId\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: 'your_api_key' });\n   * const result = await agentBay.context.create('my-new-context');\n   * if (result.success) {\n   *   console.log(`Context ID: ${result.context.id}`);\n   *   console.log(`Context Name: ${result.context.name}`);\n   * }\n   * ```\n   */\n  async create(name: string): Promise<ContextResult> {\n    return await this.get(name, true);\n  }\n\n  /**\n   * Updates a context's name.\n   *\n   * @param context - The Context object with updated name.\n   *\n   * @returns Promise resolving to OperationResult with success status.\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: 'your_api_key' });\n   * const getResult = await agentBay.context.get('old-name');\n   * if (getResult.success && getResult.context) {\n   *   getResult.context.name = 'new-name';\n   *   const updateResult = await agentBay.context.update(getResult.context);\n   *   console.log('Context updated:', updateResult.success);\n   * }\n   * ```\n   *\n   * @see {@link get}, {@link list}\n   */\n  async update(context: Context): Promise<OperationResult> {\n    try {\n      const request = new $_client.ModifyContextRequest({\n        id: context.id,\n        name: context.name,\n        authorization: `Bearer ${this.agentBay.getAPIKey()}`,\n      });\n\n      // Log API request\n      logAPICall(\"ModifyContext\");\n      logDebug(`Request: Id=${context.id}, Name=${context.name}`);\n\n      const response = await this.agentBay.getClient().modifyContext(request);\n\n      // Extract request ID\n      const requestId = extractRequestId(response) || \"\";\n\n      // Check for success (matching Python logic)\n      const success = response.body?.success !== false;\n      const errorMessage = success\n        ? \"\"\n        : `[${response.body?.code || \"Unknown\"}] ${\n            response.body?.message || \"Unknown error\"\n          }`;\n\n      // Log API response with key fields\n      const keyFields: Record<string, any> = {\n        context_id: context.id,\n        context_name: context.name,\n      };\n      const fullResponse = response.body\n        ? JSON.stringify(response.body, null, 2)\n        : \"\";\n      logAPIResponseWithDetails(\n        \"ModifyContext\",\n        requestId,\n        success,\n        keyFields,\n        fullResponse\n      );\n\n      return {\n        requestId,\n        success,\n        data: success,\n        errorMessage,\n      };\n    } catch (error) {\n      logError(\"Error calling ModifyContext:\", error);\n      return {\n        requestId: \"\",\n        success: false,\n        errorMessage: `Failed to update context ${context.id}: ${error}`,\n      };\n    }\n  }\n\n  /**\n   * Deletes the specified context.\n   * Corresponds to Python's delete() method\n   *\n   * @param context - The Context object to delete.\n   * @returns OperationResult with requestId\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: 'your_api_key' });\n   * const getResult = await agentBay.context.get('my-context');\n   * if (getResult.success && getResult.context) {\n   *   const deleteResult = await agentBay.context.delete(getResult.context);\n   *   console.log('Context deleted:', deleteResult.success);\n   * }\n   * ```\n   */\n  async delete(context: Context): Promise<OperationResult> {\n    try {\n      const request = new $_client.DeleteContextRequest({\n        id: context.id,\n        authorization: `Bearer ${this.agentBay.getAPIKey()}`,\n      });\n\n      // Log API request\n      logAPICall(\"DeleteContext\");\n      logDebug(`Request: Id=${context.id}`);\n\n      const response = await this.agentBay.getClient().deleteContext(request);\n\n      // Extract request ID\n      const requestId = extractRequestId(response) || \"\";\n\n      // Check for success (matching Python logic)\n      const success = response.body?.success !== false;\n      const errorMessage = success\n        ? \"\"\n        : `[${response.body?.code || \"Unknown\"}] ${\n            response.body?.message || \"Unknown error\"\n          }`;\n\n      // Log API response with key fields\n      const keyFields: Record<string, any> = {\n        context_id: context.id,\n      };\n      const fullResponse = response.body\n        ? JSON.stringify(response.body, null, 2)\n        : \"\";\n      logAPIResponseWithDetails(\n        \"DeleteContext\",\n        requestId,\n        success,\n        keyFields,\n        fullResponse\n      );\n\n      return {\n        requestId,\n        success,\n        data: success,\n        errorMessage,\n      };\n    } catch (error) {\n      logError(\"Error calling DeleteContext:\", error);\n      return {\n        requestId: \"\",\n        success: false,\n        errorMessage: `Failed to delete context ${context.id}: ${error}`,\n      };\n    }\n  }\n\n  /**\n   * Get a presigned upload URL for a file in a context.\n   *\n   * Note: The presigned URL expires in 1 hour by default.\n   *\n   * @param contextId - The ID of the context.\n   * @param filePath - The path to the file in the context.\n   * @returns FileUrlResult with the presigned URL and expiration time.\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: 'your_api_key' });\n   * const contextResult = await agentBay.context.get('my-context', true);\n   * if (contextResult.success) {\n   *   const urlResult = await agentBay.context.getFileUploadUrl(contextResult.context.id, '/data/file.txt');\n   *   console.log('Upload URL:', urlResult.url);\n   *   console.log('Expires at:', urlResult.expireTime);\n   * }\n   * ```\n   */\n  async getFileUploadUrl(\n    contextId: string,\n    filePath: string\n  ): Promise<FileUrlResult> {\n    logAPICall(\"GetContextFileUploadUrl\");\n    logDebug(`Request: ContextId=${contextId}, FilePath=${filePath}`);\n    const req = new $_client.GetContextFileUploadUrlRequest({\n      authorization: `Bearer ${this.agentBay.getAPIKey()}`,\n      contextId,\n      filePath,\n    });\n    const resp = await this.agentBay.getClient().getContextFileUploadUrl(req);\n    const requestId = extractRequestId(resp) || \"\";\n    const body = resp.body;\n\n    // Check for API-level errors\n    if (body?.success === false && body.code) {\n      const errorMessage = `[${body.code}] ${body.message || \"Unknown error\"}`;\n      const fullResponse = body ? JSON.stringify(body, null, 2) : \"\";\n      logAPIResponseWithDetails(\n        \"GetContextFileUploadUrl\",\n        requestId,\n        false,\n        undefined,\n        fullResponse\n      );\n      return {\n        requestId,\n        success: false,\n        url: \"\",\n        expireTime: undefined,\n        errorMessage,\n      };\n    }\n\n    const data = body?.data;\n    const success = !!(body && body.success);\n\n    // Log API response with key fields\n    const keyFields: Record<string, any> = {\n      context_id: contextId,\n      file_path: filePath,\n    };\n    if (data?.expireTime) {\n      keyFields.expire_time = data.expireTime;\n    }\n    const fullResponse = body ? JSON.stringify(body, null, 2) : \"\";\n    logAPIResponseWithDetails(\n      \"GetContextFileUploadUrl\",\n      requestId,\n      success,\n      keyFields,\n      fullResponse\n    );\n\n    return {\n      requestId,\n      success,\n      url: data?.url || \"\",\n      expireTime: data?.expireTime,\n      errorMessage: undefined,\n    };\n  }\n\n  /**\n   * Get a presigned download URL for a file in a context.\n   *\n   * Note: The presigned URL expires in 1 hour by default.\n   *\n   * @param contextId - The ID of the context.\n   * @param filePath - The path to the file in the context.\n   * @returns FileUrlResult with the presigned URL and expiration time.\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: 'your_api_key' });\n   * const contextResult = await agentBay.context.get('my-context');\n   * if (contextResult.success) {\n   *   const urlResult = await agentBay.context.getFileDownloadUrl(contextResult.context.id, '/data/file.txt');\n   *   console.log('Download URL:', urlResult.url);\n   *   console.log('Expires at:', urlResult.expireTime);\n   * }\n   * ```\n   */\n  async getFileDownloadUrl(\n    contextId: string,\n    filePath: string\n  ): Promise<FileUrlResult> {\n    logAPICall(\"GetContextFileDownloadUrl\");\n    logDebug(`Request: ContextId=${contextId}, FilePath=${filePath}`);\n    const req = new $_client.GetContextFileDownloadUrlRequest({\n      authorization: `Bearer ${this.agentBay.getAPIKey()}`,\n      contextId,\n      filePath,\n    });\n    const resp = await this.agentBay.getClient().getContextFileDownloadUrl(req);\n    const requestId = extractRequestId(resp) || \"\";\n    const body = resp.body;\n\n    // Check for API-level errors\n    if (body?.success === false && body.code) {\n      const errorMessage = `[${body.code}] ${body.message || \"Unknown error\"}`;\n      const fullResponse = body ? JSON.stringify(body, null, 2) : \"\";\n      logAPIResponseWithDetails(\n        \"GetContextFileDownloadUrl\",\n        requestId,\n        false,\n        undefined,\n        fullResponse\n      );\n      return {\n        requestId,\n        success: false,\n        url: \"\",\n        expireTime: undefined,\n        errorMessage,\n      };\n    }\n\n    const data = body?.data;\n    const success = !!(body && body.success);\n\n    // Log API response with key fields\n    const keyFields: Record<string, any> = {\n      context_id: contextId,\n      file_path: filePath,\n    };\n    if (data?.expireTime) {\n      keyFields.expire_time = data.expireTime;\n    }\n    const fullResponse = body ? JSON.stringify(body, null, 2) : \"\";\n    logAPIResponseWithDetails(\n      \"GetContextFileDownloadUrl\",\n      requestId,\n      success,\n      keyFields,\n      fullResponse\n    );\n\n    return {\n      requestId,\n      success,\n      url: data?.url || \"\",\n      expireTime: data?.expireTime,\n      errorMessage: undefined,\n    };\n  }\n\n  /**\n   * Delete a file in a context.\n   *\n   * @param contextId - The ID of the context.\n   * @param filePath - The path to the file to delete.\n   * @returns OperationResult indicating success or failure.\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: 'your_api_key' });\n   * const contextResult = await agentBay.context.get('my-context');\n   * if (contextResult.success) {\n   *   const deleteResult = await agentBay.context.deleteFile(contextResult.context.id, '/data/file.txt');\n   *   console.log('File deleted:', deleteResult.success);\n   * }\n   * ```\n   */\n  async deleteFile(\n    contextId: string,\n    filePath: string\n  ): Promise<OperationResult> {\n    logAPICall(\"DeleteContextFile\");\n    logDebug(`Request: ContextId=${contextId}, FilePath=${filePath}`);\n    const req = new $_client.DeleteContextFileRequest({\n      authorization: `Bearer ${this.agentBay.getAPIKey()}`,\n      contextId,\n      filePath,\n    });\n    const resp = await this.agentBay.getClient().deleteContextFile(req);\n    const requestId = extractRequestId(resp) || \"\";\n    const body = resp.body;\n    const success = !!(body && body.success);\n\n    // Check for API-level errors\n    const errorMessage = success\n      ? \"\"\n      : `[${body?.code || \"Unknown\"}] ${\n          body?.message || \"Failed to delete file\"\n        }`;\n\n    // Log API response with key fields\n    const keyFields: Record<string, any> = {\n      context_id: contextId,\n      file_path: filePath,\n    };\n    const fullResponse = body ? JSON.stringify(body, null, 2) : \"\";\n    logAPIResponseWithDetails(\n      \"DeleteContextFile\",\n      requestId,\n      success,\n      keyFields,\n      fullResponse\n    );\n\n    return {\n      requestId,\n      success,\n      data: success,\n      errorMessage,\n    };\n  }\n\n  /**\n   * List files under a specific folder path in a context.\n   *\n   * @param contextId - The ID of the context.\n   * @param parentFolderPath - The parent folder path to list files from.\n   * @param pageNumber - Page number for pagination (default: 1). Ignored when `maxResults` or `nextToken` is set.\n   * @param pageSize - Number of files per page (default: 50). Ignored when `maxResults` or `nextToken` is set.\n   * @param maxResults - Maximum entries per request (token-based pagination). When set with or without `nextToken`, token pagination is used instead of page number/size.\n   * @param nextToken - Pagination token from a previous response.\n   * @returns ContextFileListResult with file entries and total count.\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: 'your_api_key' });\n   * const contextResult = await agentBay.context.get('my-context');\n   * if (contextResult.success) {\n   *   const listResult = await agentBay.context.listFiles(contextResult.context.id, '/data');\n   *   console.log(`Found ${listResult.entries.length} files`);\n   *   console.log(`Total count: ${listResult.count}`);\n   * }\n   * ```\n   */\n  async listFiles(\n    contextId: string,\n    parentFolderPath: string,\n    pageNumber = 1,\n    pageSize = 50,\n    maxResults?: number,\n    nextToken?: string\n  ): Promise<ContextFileListResult> {\n    const useTokenPagination =\n      maxResults !== undefined || nextToken !== undefined;\n    logAPICall(\"DescribeContextFiles\");\n    logDebug(\n      useTokenPagination\n        ? `Request: ContextId=${contextId}, ParentFolderPath=${parentFolderPath}, MaxResults=${maxResults}, NextToken=${nextToken}`\n        : `Request: ContextId=${contextId}, ParentFolderPath=${parentFolderPath}, PageNumber=${pageNumber}, PageSize=${pageSize}`\n    );\n    const req = new $_client.DescribeContextFilesRequest({\n      authorization: `Bearer ${this.agentBay.getAPIKey()}`,\n      parentFolderPath,\n      contextId,\n      pageNumber: useTokenPagination ? undefined : pageNumber,\n      pageSize: useTokenPagination ? undefined : pageSize,\n      maxResults: useTokenPagination ? maxResults : undefined,\n      nextToken: useTokenPagination ? nextToken : undefined,\n    });\n    const resp = await this.agentBay.getClient().describeContextFiles(req);\n    const requestId = extractRequestId(resp) || \"\";\n    const body = resp.body;\n\n    // Check for API-level errors\n    if (body?.success === false && body.code) {\n      const errorMessage = `[${body.code}] ${body.message || \"Unknown error\"}`;\n      const fullResponse = body ? JSON.stringify(body, null, 2) : \"\";\n      logAPIResponseWithDetails(\n        \"DescribeContextFiles\",\n        requestId,\n        false,\n        undefined,\n        fullResponse\n      );\n      return {\n        requestId,\n        success: false,\n        entries: [],\n        count: undefined,\n        nextToken: undefined,\n        errorMessage,\n      };\n    }\n\n    const rawList = body?.data || [];\n    const entries: ContextFileEntry[] = rawList.map((it: any) => ({\n      fileId: it.fileId,\n      fileName: it.fileName,\n      filePath: it.filePath || \"\",\n      fileType: it.fileType,\n      gmtCreate: it.gmtCreate,\n      gmtModified: it.gmtModified,\n      size: it.size,\n      status: it.status,\n    }));\n\n    const success = !!(body && body.success);\n\n    // Log API response with key fields\n    const keyFields: Record<string, any> = {\n      context_id: contextId,\n      parent_folder_path: parentFolderPath,\n      file_count: entries.length,\n    };\n    if (useTokenPagination) {\n      keyFields.max_results = maxResults;\n      keyFields.next_token = nextToken;\n    } else {\n      keyFields.page_number = pageNumber;\n      keyFields.page_size = pageSize;\n    }\n    if (body?.count !== undefined) {\n      keyFields.count = body.count;\n    }\n    const fullResponse = body ? JSON.stringify(body, null, 2) : \"\";\n    logAPIResponseWithDetails(\n      \"DescribeContextFiles\",\n      requestId,\n      success,\n      keyFields,\n      fullResponse\n    );\n\n    return {\n      requestId,\n      success,\n      entries,\n      count: body?.count,\n      nextToken: body?.nextToken,\n      errorMessage: undefined,\n    };\n  }\n\n  /**\n   * Asynchronously initiate a task to clear the context's persistent data.\n   *\n   * This is a non-blocking method that returns immediately after initiating the clearing task\n   * on the backend. The context's state will transition to \"clearing\" while the operation\n   * is in progress.\n   *\n   * @param contextId - Unique ID of the context to clear.\n   * @returns A ClearContextResult object indicating the task has been successfully started,\n   *          with status field set to \"clearing\".\n   * @throws APIError - If the backend API rejects the clearing request (e.g., invalid ID).\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: 'your_api_key' });\n   * const getResult = await agentBay.context.get('my-context');\n   * if (getResult.success) {\n   *   const clearResult = await agentBay.context.clearAsync(getResult.context.id);\n   *   console.log('Clear task started:', clearResult.success);\n   *   console.log('Status:', clearResult.status);\n   * }\n   * ```\n   */\n  async clearAsync(contextId: string): Promise<ClearContextResult> {\n    try {\n      logAPICall(\"ClearContext\");\n      logDebug(`Request: ContextId=${contextId}`);\n\n      const request = new $_client.ClearContextRequest({\n        authorization: `Bearer ${this.agentBay.getAPIKey()}`,\n        id: contextId,\n      });\n\n      const response = await this.agentBay.getClient().clearContext(request);\n\n      // Extract request ID\n      const requestId = extractRequestId(response) || \"\";\n\n      // Directly access response body object\n      if (!response.body) {\n        const fullResponse = \"Empty response body\";\n        logAPIResponseWithDetails(\n          \"ClearContext\",\n          requestId,\n          false,\n          undefined,\n          fullResponse\n        );\n        return {\n          requestId,\n          success: false,\n          errorMessage: \"Empty response body\",\n        };\n      }\n\n      const body = response.body;\n\n      // Check for API-level errors\n      if (!body.success && body.code) {\n        const errorMessage = `[${body.code}] ${\n          body.message || \"Unknown error\"\n        }`;\n        const fullResponse = body ? JSON.stringify(body, null, 2) : \"\";\n        logAPIResponseWithDetails(\n          \"ClearContext\",\n          requestId,\n          false,\n          undefined,\n          fullResponse\n        );\n        return {\n          requestId,\n          success: false,\n          errorMessage,\n        };\n      }\n\n      // ClearContext API returns success info without Data field\n      // Initial status is \"clearing\" when the task starts\n      const keyFields: Record<string, any> = {\n        context_id: contextId,\n        status: \"clearing\",\n      };\n      const fullResponse = body ? JSON.stringify(body, null, 2) : \"\";\n      logAPIResponseWithDetails(\n        \"ClearContext\",\n        requestId,\n        true,\n        keyFields,\n        fullResponse\n      );\n\n      return {\n        requestId,\n        success: true,\n        contextId,\n        status: \"clearing\",\n        errorMessage: \"\",\n      };\n    } catch (error) {\n      logError(\"Error calling ClearContext:\", error);\n      throw new APIError(\n        `Failed to start context clearing for ${contextId}: ${error}`\n      );\n    }\n  }\n\n  /**\n   * Queries the status of the clearing task.\n   *\n   * This method calls GetContext API directly and parses the raw response to extract\n   * the state field, which indicates the current clearing status.\n   *\n   * @param contextId - ID of the context.\n   * @returns ClearContextResult object containing the current task status.\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: 'your_api_key' });\n   * const getResult = await agentBay.context.get('my-context');\n   * if (getResult.success) {\n   *   const statusResult = await agentBay.context.getClearStatus(getResult.context.id);\n   *   console.log('Current status:', statusResult.status);\n   * }\n   * ```\n   */\n  async getClearStatus(contextId: string): Promise<ClearContextResult> {\n    try {\n      logAPICall(\"GetContext\");\n      logDebug(`Request: ContextId=${contextId} (for clear status)`);\n\n      const request = new $_client.GetContextRequest({\n        authorization: `Bearer ${this.agentBay.getAPIKey()}`,\n        contextId: contextId,\n        allowCreate: \"false\",\n      });\n\n      const response = await this.agentBay.getClient().getContext(request);\n\n      // Extract request ID\n      const requestId = extractRequestId(response) || \"\";\n\n      // Directly access response body object\n      if (!response.body) {\n        const fullResponse = \"Empty response body\";\n        logAPIResponseWithDetails(\n          \"GetContext (for clear status)\",\n          requestId,\n          false,\n          undefined,\n          fullResponse\n        );\n        return {\n          requestId,\n          success: false,\n          errorMessage: \"Empty response body\",\n        };\n      }\n\n      const body = response.body;\n\n      // Check for API-level errors\n      if (!body.success && body.code) {\n        const errorMessage = `[${body.code}] ${\n          body.message || \"Unknown error\"\n        }`;\n        const fullResponse = body ? JSON.stringify(body, null, 2) : \"\";\n        logAPIResponseWithDetails(\n          \"GetContext (for clear status)\",\n          requestId,\n          false,\n          undefined,\n          fullResponse\n        );\n        return {\n          requestId,\n          success: false,\n          errorMessage,\n        };\n      }\n\n      // Check if data exists\n      if (!body.data) {\n        const fullResponse = \"No data in response\";\n        logAPIResponseWithDetails(\n          \"GetContext (for clear status)\",\n          requestId,\n          false,\n          undefined,\n          fullResponse\n        );\n        return {\n          requestId,\n          success: false,\n          errorMessage: \"No data in response\",\n        };\n      }\n\n      const data = body.data;\n\n      // Extract clearing status from the response data object\n      // The server's state field indicates the clearing status:\n      // - \"clearing\": Clearing is in progress\n      // - \"available\": Clearing completed successfully\n      // - \"in-use\": Context is being used\n      // - \"pre-available\": Context is being prepared\n      const contextIdFromResponse = data.id || \"\";\n      const state = data.state || \"clearing\"; // Extract state from response object\n      const errorMessage = \"\"; // ErrorMessage is not in GetContextResponseBodyData\n\n      const keyFields: Record<string, any> = {\n        context_id: contextIdFromResponse,\n        state: state,\n      };\n      const fullResponse = body ? JSON.stringify(body, null, 2) : \"\";\n      logAPIResponseWithDetails(\n        \"GetContext (for clear status)\",\n        requestId,\n        true,\n        keyFields,\n        fullResponse\n      );\n\n      return {\n        requestId,\n        success: true,\n        contextId: contextIdFromResponse,\n        status: state,\n        errorMessage,\n      };\n    } catch (error) {\n      logError(\"Error calling GetContext (for clear status):\", error);\n      return {\n        requestId: \"\",\n        success: false,\n        errorMessage: `Failed to get clear status: ${error}`,\n      };\n    }\n  }\n\n  /**\n   * Synchronously clear the context's persistent data and wait for the final result.\n   *\n   * This method wraps the `clearAsync` and `getClearStatus` polling logic,\n   * providing the simplest and most direct way to handle clearing tasks.\n   *\n   * The clearing process transitions through the following states:\n   * - \"clearing\": Data clearing is in progress\n   * - \"available\": Clearing completed successfully (final success state)\n   *\n   * @param contextId - Unique ID of the context to clear.\n   * @param timeout - (Optional) Timeout in seconds to wait for task completion, default is 60 seconds.\n   * @param pollInterval - (Optional) Interval in seconds between status polls, default is 2 seconds.\n   * @returns A ClearContextResult object containing the final task result.\n   *          The status field will be \"available\" on success, or other states if interrupted.\n   * @throws APIError - If the task fails to complete within the specified timeout.\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: 'your_api_key' });\n   * const getResult = await agentBay.context.get('my-context');\n   * if (getResult.success) {\n   *   const clearResult = await agentBay.context.clear(getResult.context.id);\n   *   console.log('Context cleared:', clearResult.success);\n   *   console.log('Final status:', clearResult.status);\n   * }\n   * ```\n   */\n  async clear(\n    contextId: string,\n    timeout = 60,\n    pollInterval = 2.0\n  ): Promise<ClearContextResult> {\n    // 1. Asynchronously start the clearing task\n    const startResult = await this.clearAsync(contextId);\n    if (!startResult.success) {\n      return startResult;\n    }\n\n    logInfo(`Started context clearing task for: ${contextId}`);\n\n    // 2. Poll task status until completion or timeout\n    const startTime = Date.now();\n    const maxAttempts = Math.floor(timeout / pollInterval);\n    let attempt = 0;\n\n    while (attempt < maxAttempts) {\n      // Wait before querying\n      await new Promise((resolve) => setTimeout(resolve, pollInterval * 1000));\n      attempt++;\n\n      // Query task status (using GetContext API with context ID)\n      const statusResult = await this.getClearStatus(contextId);\n\n      if (!statusResult.success) {\n        logError(`Failed to get clear status: ${statusResult.errorMessage}`);\n        return statusResult;\n      }\n\n      const status = statusResult.status;\n      logInfo(\n        `Clear task status: ${status} (attempt ${attempt}/${maxAttempts})`\n      );\n\n      // Check if completed\n      // When clearing is complete, the state changes from \"clearing\" to \"available\"\n      if (status === \"available\") {\n        const elapsed = (Date.now() - startTime) / 1000;\n        logInfo(\n          `Context cleared successfully in ${elapsed.toFixed(2)} seconds`\n        );\n        return {\n          requestId: startResult.requestId,\n          success: true,\n          contextId: statusResult.contextId,\n          status,\n          errorMessage: \"\",\n        };\n      } else if (status && ![\"clearing\", \"pre-available\"].includes(status)) {\n        // If status is not \"clearing\" or \"pre-available\", and not \"available\",\n        // treat it as a potential error or unexpected state\n        const elapsed = (Date.now() - startTime) / 1000;\n        logError(\n          `Context in unexpected state after ${elapsed.toFixed(\n            2\n          )} seconds: ${status}`\n        );\n        // Continue polling as the state might transition to \"available\"\n      }\n    }\n\n    // Timeout\n    const elapsed = (Date.now() - startTime) / 1000;\n    const errorMsg = `Context clearing timed out after ${elapsed.toFixed(\n      2\n    )} seconds`;\n    logError(errorMsg);\n    throw new APIError(errorMsg);\n  }\n}\n","/**\n * Base interface for API responses\n */\nexport interface ApiResponse {\n  /** Optional request identifier for tracking API calls */\n  requestId?: string;\n  /** Optional error message if the operation failed */\n  errorMessage?: string;\n  /** Optional status code if the operation failed */\n  success?: boolean;\n}\n\n/**\n * Generic interface for API responses that include data payload\n * @template T The type of the data being returned\n */\nexport interface ApiResponseWithData<T> extends ApiResponse {\n  /** The actual data payload returned by the API */\n  session?: T;\n  data?: T;\n}\n\n/**\n * Interface for delete operation responses\n */\nexport interface DeleteResult extends ApiResponse {\n  /** Whether the delete operation was successful */\n  success: boolean;\n  /** Optional error message if the operation failed */\n  errorMessage?: string;\n}\n\n/**\n * Interface for context information in GetSession response\n */\nexport interface ContextInfo {\n  /** Context name */\n  name: string;\n  /** Context ID */\n  id: string;\n}\n\n/**\n * Interface for GetSession data\n */\nexport interface GetSessionData {\n  /** Application instance ID */\n  appInstanceId: string;\n  /** Resource ID */\n  resourceId: string;\n  /** Session ID */\n  sessionId: string;\n  /** Success status */\n  success: boolean;\n  /** HTTP port for VPC sessions */\n  httpPort: string;\n  /** Network interface IP for VPC sessions */\n  networkInterfaceIp: string;\n  /** Token for VPC sessions */\n  token: string;\n  /** LinkUrl for direct MCP tool calls (non-VPC) */\n  linkUrl?: string;\n  /** WebSocket URL for streaming/push features */\n  wsUrl?: string;\n  /** Whether this session uses VPC resources */\n  vpcResource: boolean;\n  /** VPC IP. Returned only for sessions created on a custom VPC network; empty otherwise. */\n  vpcIp: string;\n  /** VPC ID. Returned only for sessions created on a custom VPC network; empty otherwise. */\n  vpcId: string;\n  /** Resource URL for accessing the session */\n  resourceUrl: string;\n  /** Current status of the session */\n  status: string;\n  /** Tool list (JSON string) returned by GetSession */\n  toolList?: string;\n  /** List of contexts associated with the session */\n  contexts?: ContextInfo[];\n}\n\n/**\n * Interface for GetSession operation responses\n */\nexport interface GetSessionResult extends ApiResponse {\n  /** Request identifier for tracking API calls */\n  requestId: string;\n  /** HTTP status code */\n  httpStatusCode: number;\n  /** Response code */\n  code: string;\n  /** Whether the operation was successful */\n  success: boolean;\n  /** Session data */\n  data?: GetSessionData;\n  /** Optional error message if the operation failed */\n  errorMessage?: string;\n}\n\n/**\n * Interface for session creation operation responses\n * Corresponds to Python's SessionResult type\n */\nexport interface SessionResult extends ApiResponse {\n  /** Request identifier for tracking API calls */\n  requestId: string;\n  /** Whether the session creation was successful */\n  success: boolean;\n  /** The created session object (only present if successful) */\n  session?: any; // Will be Session type, avoiding circular import\n  /** Error message if the operation failed */\n  errorMessage?: string;\n}\n\n/**\n * Interface for operation results\n * Corresponds to Python's OperationResult type\n */\nexport interface OperationResult extends ApiResponse {\n  /** Request identifier for tracking API calls */\n  requestId: string;\n  /** Whether the operation was successful */\n  success: boolean;\n  /** Optional data payload */\n  data?: any;\n  /** Optional error message if the operation failed */\n  errorMessage?: string;\n}\n\n/**\n * Structured runtime metrics returned by Session.getMetrics().\n */\nexport interface SessionMetrics {\n  cpuCount: number;\n  cpuUsedPct: number;\n  diskTotal: number;\n  diskUsed: number;\n  memTotal: number;\n  memUsed: number;\n  rxRateKbytePerS: number;\n  txRateKbytePerS: number;\n  rxUsedKbyte: number;\n  txUsedKbyte: number;\n  timestamp: string;\n}\n\n/**\n * Result of Session.getMetrics() operation.\n */\nexport interface SessionMetricsResult extends OperationResult {\n  data?: SessionMetrics;\n  raw?: Record<string, any>;\n}\n\n/**\n * Interface for session info operation responses\n * Corresponds to Go's InfoResult type\n */\nexport interface InfoResult extends ApiResponse {\n  /** Request identifier for tracking API calls */\n  requestId: string;\n  /** Session information object */\n  info?: any; // Will be SessionInfo type, avoiding circular import\n}\n\n/**\n * Interface for label operation responses\n * Corresponds to Go's LabelResult type\n */\nexport interface LabelResult extends ApiResponse {\n  /** Request identifier for tracking API calls */\n  requestId: string;\n  /** Labels string (JSON format) */\n  labels: string;\n}\n\n/**\n * Interface for link operation responses\n * Corresponds to Go's LinkResult type\n */\nexport interface LinkResult extends ApiResponse {\n  /** Request identifier for tracking API calls */\n  requestId: string;\n  /** Link string */\n  link: string;\n}\n\n/**\n * Interface for process list operation responses\n * Corresponds to Python's ProcessListResult type\n */\nexport interface Process {\n  pname: string;\n  pid: number;\n  cmdline?: string;\n}\n\nexport interface ProcessListResult extends OperationResult {\n  data: Process[];\n}\n\n/**\n * Interface for installed app list operation responses\n * Corresponds to Python's InstalledAppListResult type\n */\n// export interface InstalledAppListResult extends ApiResponse {\n//   /** Request identifier for tracking API calls */\n//   requestId: string;\n//   /** Whether the operation was successful */\n//   success: boolean;\n//   /** The list of installed app objects */\n//   data: any[]; // Will be InstalledApp[] type, avoiding circular import\n//   /** Optional error message if the operation failed */\n//   errorMessage?: string;\n// }\n\nexport interface InstalledApp {\n  name: string;\n  startCmd: string;\n  stopCmd?: string;\n  workDirectory?: string;\n}\n\nexport interface InstalledAppListResult extends OperationResult {\n  data: InstalledApp[];\n}\n\n/**\n * Interface for application operation responses\n * Corresponds to Python's AppOperationResult type\n */\nexport interface AppOperationResult extends ApiResponse {\n  /** Request identifier for tracking API calls */\n  requestId: string;\n  /** Whether the operation was successful */\n  success: boolean;\n  /** Optional error message if the operation failed */\n  errorMessage?: string;\n}\n\n/**\n * Interface for application info operation responses\n * Corresponds to Python's AppInfoResult type\n */\nexport interface AppInfoResult extends ApiResponse {\n  /** Request identifier for tracking API calls */\n  requestId: string;\n  /** Whether the operation was successful */\n  success: boolean;\n  /** Application information */\n  appInfo: Record<string, any>;\n  /** Optional error message if the operation failed */\n  errorMessage?: string;\n}\n\n/**\n * Interface for application list operation responses\n * Corresponds to Python's AppListResult type\n */\nexport interface AppListResult extends ApiResponse {\n  /** Request identifier for tracking API calls */\n  requestId: string;\n  /** Whether the operation was successful */\n  success: boolean;\n  /** List of applications */\n  apps: Record<string, any>[];\n  /** Optional error message if the operation failed */\n  errorMessage?: string;\n}\n\n/**\n * Interface for application installation responses\n * Corresponds to Python's AppInstallResult type\n */\nexport interface AppInstallResult extends ApiResponse {\n  /** Request identifier for tracking API calls */\n  requestId: string;\n  /** Whether the installation was successful */\n  success: boolean;\n  /** Result description or error message */\n  message: string;\n}\n\n/**\n * Interface for command execution operation responses\n * Corresponds to Python's CommandResult type\n */\nexport interface CommandResult extends ApiResponse {\n  /** Request identifier for tracking API calls */\n  requestId: string;\n  /** Whether the command execution was successful */\n  success: boolean;\n  /** The command output (for backward compatibility, equals stdout + stderr) */\n  output: string;\n  /** Optional error message if the operation failed */\n  errorMessage?: string;\n  /** The exit code of the command execution. Default is 0. */\n  exitCode?: number;\n  /** Standard output from the command execution */\n  stdout?: string;\n  /** Standard error from the command execution */\n  stderr?: string;\n  /** Trace ID for error tracking. Only present when exit_code != 0. Used for quick problem localization. */\n  traceId?: string;\n}\n\n/**\n * Interface for single result item in enhanced code execution\n */\nexport interface CodeExecutionResultItem {\n  text?: string;\n  html?: string;\n  markdown?: string;\n  png?: string;\n  jpeg?: string;\n  svg?: string;\n  latex?: string;\n  json?: any;\n  chart?: any;\n  isMainResult?: boolean;\n}\n\n/**\n * Interface for code execution logs\n */\nexport interface CodeExecutionLogs {\n  stdout: string[];\n  stderr: string[];\n}\n\n/**\n * Interface for code execution error details\n */\nexport interface CodeExecutionError {\n  name: string;\n  value: string;\n  traceback: string;\n}\n\n/**\n * Interface for code execution operation responses\n * Corresponds to Python's EnhancedCodeExecutionResult type\n */\nexport interface CodeExecutionResult extends ApiResponse {\n  /** Request identifier for tracking API calls */\n  requestId: string;\n  /** Whether the code execution was successful */\n  success: boolean;\n  /** The execution result (backward compatible text) */\n  result: string;\n  /** Optional error message if the operation failed */\n  errorMessage?: string;\n\n  /** Enhanced fields */\n  logs?: CodeExecutionLogs;\n  results?: CodeExecutionResultItem[];\n  error?: CodeExecutionError;\n  executionTime?: number;\n  executionCount?: number;\n}\n\n/**\n * Interface for boolean operation responses\n * Corresponds to Python's BoolResult type\n */\nexport interface BoolResult extends ApiResponse {\n  /** Request identifier for tracking API calls */\n  requestId: string;\n  /** Whether the operation was successful */\n  success: boolean;\n  /** Boolean data result */\n  data?: boolean;\n  /** Optional error message if the operation failed */\n  errorMessage?: string;\n}\n\n/**\n * Interface for file info operation responses\n * Corresponds to Python's FileInfoResult type\n */\nexport interface FileInfoResult extends ApiResponse {\n  /** Request identifier for tracking API calls */\n  requestId: string;\n  /** Whether the operation was successful */\n  success: boolean;\n  /** File information object */\n  fileInfo?: Record<string, any>;\n  /** Optional error message if the operation failed */\n  errorMessage?: string;\n}\n\n/**\n * Interface for directory list operation responses\n * Corresponds to Python's DirectoryListResult type\n */\nexport interface DirectoryListResult extends ApiResponse {\n  /** Request identifier for tracking API calls */\n  requestId: string;\n  /** Whether the operation was successful */\n  success: boolean;\n  /** Directory entries */\n  entries: Record<string, any>[];\n  /** Optional error message if the operation failed */\n  errorMessage?: string;\n}\n\n/**\n * Interface for file content operation responses\n * Corresponds to Python's FileContentResult type\n */\nexport interface FileContentResult extends ApiResponse {\n  /** Request identifier for tracking API calls */\n  requestId: string;\n  /** Whether the operation was successful */\n  success: boolean;\n  /** File content */\n  content: string;\n  /** Optional error message if the operation failed */\n  errorMessage?: string;\n}\n\n/**\n * Interface for binary file content operation responses\n * Corresponds to Python's BinaryFileContentResult type\n */\nexport interface BinaryFileContentResult extends ApiResponse {\n  /** Request identifier for tracking API calls */\n  requestId: string;\n  /** Whether the operation was successful */\n  success: boolean;\n  /** Binary file content */\n  content: Uint8Array;\n  /** Optional error message if the operation failed */\n  errorMessage?: string;\n  /** Optional MIME type of the file */\n  contentType?: string;\n  /** Optional size of the file in bytes */\n  size?: number;\n}\n\n/**\n * Interface for multiple file content operation responses\n * Corresponds to Python's MultipleFileContentResult type\n */\nexport interface MultipleFileContentResult extends ApiResponse {\n  /** Request identifier for tracking API calls */\n  requestId: string;\n  /** Whether the operation was successful */\n  success: boolean;\n  /** Multiple file contents */\n  contents: Record<string, string>;\n  /** Optional error message if the operation failed */\n  errorMessage?: string;\n}\n\n/**\n * Interface for file search operation responses\n * Corresponds to Python's FileSearchResult type\n */\nexport interface FileSearchResult extends ApiResponse {\n  /** Request identifier for tracking API calls */\n  requestId: string;\n  /** Whether the operation was successful */\n  success: boolean;\n  /** Matching file paths */\n  matches: string[];\n  /** Optional error message if the operation failed */\n  errorMessage?: string;\n}\n\n/**\n * Interface for OSS client creation operation responses\n * Corresponds to Python's OSSClientResult type\n */\nexport interface OSSClientResult extends ApiResponse {\n  /** Request identifier for tracking API calls */\n  requestId: string;\n  /** Whether the operation was successful */\n  success: boolean;\n  /** OSS client configuration */\n  clientConfig: string;\n  /** Optional error message if the operation failed */\n  errorMessage?: string;\n}\n\n/**\n * Interface for OSS upload operation responses\n * Corresponds to Python's OSSUploadResult type\n */\nexport interface OSSUploadResult extends ApiResponse {\n  /** Request identifier for tracking API calls */\n  requestId: string;\n  /** Whether the operation was successful */\n  success: boolean;\n  /** Result of the upload operation */\n  content: string;\n  /** Optional error message if the operation failed */\n  errorMessage?: string;\n}\n\n/**\n * Interface for OSS download operation responses\n * Corresponds to Python's OSSDownloadResult type\n */\nexport interface OSSDownloadResult extends ApiResponse {\n  /** Request identifier for tracking API calls */\n  requestId: string;\n  /** Whether the operation was successful */\n  success: boolean;\n  /** Result of the download operation */\n  content: string;\n  /** Optional error message if the operation failed */\n  errorMessage?: string;\n}\n\n/**\n * Interface for UI element list operation responses\n * Corresponds to Python's UIElementListResult type\n */\nexport interface UIElementListResult extends ApiResponse {\n  /** Request identifier for tracking API calls */\n  requestId: string;\n  /** Whether the operation was successful */\n  success: boolean;\n  /** UI elements */\n  elements: Record<string, any>[];\n  /** Optional error message if the operation failed */\n  errorMessage?: string;\n}\n\nexport interface WindowInfo {\n  windowId: number;\n  title: string;\n  pid: number;\n  pname: string;\n}\n\n/**\n * Interface for window list operation responses\n * Corresponds to Python's WindowListResult type\n */\nexport interface WindowListResult extends ApiResponse {\n  /** Request identifier for tracking API calls */\n  requestId: string;\n  /** Whether the operation was successful */\n  success: boolean;\n  /** List of windows */\n  windows: WindowInfo[]; // Will be Window[] type, avoiding circular import\n  /** Optional error message if the operation failed */\n  errorMessage?: string;\n}\n\nexport interface Window {\n  windowId: number;\n  title: string;\n  absoluteUpperLeftX?: number;\n  absoluteUpperLeftY?: number;\n  width?: number;\n  height?: number;\n  pid?: number;\n  pname?: string;\n  childWindows?: Window[];\n}\n\n/**\n * Interface for window info operation responses\n * Corresponds to Python's WindowInfoResult type\n */\nexport interface WindowInfoResult extends ApiResponse {\n  /** Request identifier for tracking API calls */\n  requestId: string;\n  /** Whether the operation was successful */\n  success: boolean;\n  /** Window object */\n  window?: Window[]; // Will be Window type, avoiding circular import\n  /** Optional error message if the operation failed */\n  errorMessage?: string;\n}\n\n/**\n * Interface for context operation responses\n * Corresponds to Python's ContextResult type\n */\nexport interface ContextResult extends ApiResponse {\n  /** Request identifier for tracking API calls */\n  requestId: string;\n  /** Whether the operation was successful */\n  success: boolean;\n  /** The context ID */\n  contextId: string;\n  /** The context object (only present if successful) */\n  context?: any; // Will be Context type, avoiding circular import\n  /** Optional error message if the operation failed */\n  errorMessage?: string;\n}\n\n/**\n * Interface for context list operation responses\n * Corresponds to Python's ContextListResult type\n */\nexport interface ContextListResult extends ApiResponse {\n  /** Request identifier for tracking API calls */\n  requestId: string;\n  /** Whether the operation was successful */\n  success: boolean;\n  /** List of contexts */\n  contexts: any[]; // Will be Context[] type, avoiding circular import\n  /** Token for the next page of results */\n  nextToken?: string;\n  /** Maximum number of results per page */\n  maxResults?: number;\n  /** Total number of contexts available */\n  totalCount?: number;\n  /** Optional error message if the operation failed */\n  errorMessage?: string;\n}\n\n/**\n * Interface for network create operation responses.\n */\nexport interface NetworkResult extends ApiResponse {\n  /** Request identifier for tracking API calls */\n  requestId: string;\n  /** Whether the operation was successful */\n  success: boolean;\n  /** Created/returned network id */\n  networkId: string;\n  /** Network token for the created network */\n  networkToken: string;\n  /** Optional error message if the operation failed */\n  errorMessage?: string;\n}\n\n/**\n * Interface for network describe operation responses.\n */\nexport interface NetworkStatusResult extends ApiResponse {\n  /** Request identifier for tracking API calls */\n  requestId: string;\n  /** Whether the operation was successful */\n  success: boolean;\n  /** Whether network is online */\n  online: boolean;\n  /** Optional error message if the operation failed */\n  errorMessage?: string;\n}\n\n/**\n * Result of a presigned URL request\n */\nexport interface FileUrlResult extends ApiResponse {\n  /** Request identifier for tracking API calls */\n  requestId: string;\n  /** Whether the operation was successful */\n  success: boolean;\n  /** The presigned URL */\n  url: string;\n  /** Optional expire time (epoch seconds) */\n  expireTime?: number;\n  /** Optional error message if the operation failed */\n  errorMessage?: string;\n}\n\n/**\n * Represents a file item in a context\n */\nexport interface ContextFileEntry {\n  fileId?: string;\n  fileName?: string;\n  filePath: string;\n  fileType?: string;\n  gmtCreate?: string;\n  gmtModified?: string;\n  size?: number;\n  status?: string;\n}\n\n/**\n * Result of context file listing\n */\nexport interface ContextFileListResult extends ApiResponse {\n  /** Request identifier for tracking API calls */\n  requestId: string;\n  /** Whether the operation was successful */\n  success: boolean;\n  /** File entries under a folder */\n  entries: ContextFileEntry[];\n  /** Optional total count returned by backend */\n  count?: number;\n  /** Token for the next page when using MaxResults/NextToken pagination */\n  nextToken?: string;\n  /** Optional error message if the operation failed */\n  errorMessage?: string;\n}\n\n/**\n * Helper function to extract request ID from API responses\n */\nexport function extractRequestId(response: any): string | undefined {\n  if (!response) return undefined;\n\n  // If response is a string (like body?.requestId), return it directly\n  if (typeof response === \"string\" && response.length > 0) {\n    return response;\n  }\n\n  // Check for requestId in response.body first\n  if (response.body && response.body.requestId) {\n    return response.body.requestId;\n  }\n  // Check for requestId directly on response\n  if (response.requestId) {\n    return response.requestId;\n  }\n\n  return undefined;\n}\n\n/**\n * Result of context clear operations, including the real-time status.\n * Corresponds to Python's ClearContextResult type\n */\nexport interface ClearContextResult extends ApiResponse {\n  /** Request identifier for tracking API calls */\n  requestId: string;\n  /** Whether the operation was successful */\n  success: boolean;\n  /** Current status of the clearing task. This corresponds to the\n      context's state field. Possible values:\n      - \"clearing\": Context data is being cleared (in progress)\n      - \"available\": Clearing completed successfully\n      - Other values may indicate the context state after clearing */\n  status?: string;\n  /** The unique identifier of the context being cleared */\n  contextId?: string;\n  /** Optional error message if the operation failed */\n  errorMessage?: string;\n}\n\n/**\n * Result of session pause operations.\n */\nexport interface SessionPauseResult extends ApiResponse {\n  /** Request identifier for tracking API calls */\n  requestId: string;\n  /** Whether the pause operation was successful */\n  success: boolean;\n  /** Error message if the operation failed */\n  errorMessage?: string;\n  /** API error code */\n  code?: string;\n  /** Detailed error message from API */\n  message?: string;\n  /** HTTP status code */\n  httpStatusCode?: number;\n  /** Current status of the session. Possible values: \"RUNNING\", \"PAUSED\", \"PAUSING\" */\n  status?: string;\n}\n\n/**\n * Result of session resume operations.\n */\nexport interface SessionResumeResult extends ApiResponse {\n  /** Request identifier for tracking API calls */\n  requestId: string;\n  /** Whether the resume operation was successful */\n  success: boolean;\n  /** Error message if the operation failed */\n  errorMessage?: string;\n  /** API error code */\n  code?: string;\n  /** Detailed error message from API */\n  message?: string;\n  /** HTTP status code */\n  httpStatusCode?: number;\n  /** Current status of the session. Possible values: \"RUNNING\", \"PAUSED\", \"RESUMING\" */\n  status?: string;\n}\n\n/**\n * Represents the screen dimensions and DPI scaling information.\n *\n * @interface ScreenSize\n * @extends OperationResult\n */\nexport interface ScreenSize extends OperationResult {\n  /** Screen width in pixels */\n  width: number;\n  /** Screen height in pixels */\n  height: number;\n  /** DPI scaling factor (e.g., 1.0 for 100%, 1.5 for 150%, 2.0 for 200%) */\n  dpiScalingFactor: number;\n}\n\n/**\n * Represents the current cursor position on screen.\n *\n * @interface CursorPosition\n * @extends OperationResult\n */\nexport interface CursorPosition extends OperationResult {\n  /** X coordinate in pixels (0 is left edge of screen) */\n  x: number;\n  /** Y coordinate in pixels (0 is top edge of screen) */\n  y: number;\n}\n\n/**\n * Represents a single context binding entry returned by DescribeSessionContexts.\n */\nexport interface ContextBinding {\n  contextId: string;\n  contextName?: string;\n  path: string;\n  policy?: string;\n  bindTime?: string;\n}\n\n/**\n * Result of a bind() operation on contexts.\n */\nexport interface ContextBindResult extends ApiResponse {\n  requestId: string;\n  success: boolean;\n  errorMessage?: string;\n}\n\n/**\n * Result of a listBindings() operation.\n */\nexport interface ContextBindingsResult extends ApiResponse {\n  requestId: string;\n  success: boolean;\n  bindings: ContextBinding[];\n  errorMessage?: string;\n}\n","import { AgentBay } from \"./agent-bay\";\nimport * as $_client from \"./api\";\nimport { APIError } from \"./exceptions\";\nimport { extractRequestId } from \"./types/api-response\";\nimport type { NetworkResult, NetworkStatusResult } from \"./types/api-response\";\nimport {\n  logAPICall,\n  logAPIResponseWithDetails,\n  logDebug,\n} from \"./utils/logger\";\n\n/**\n * Beta network service (trial feature).\n */\nexport class BetaNetworkService {\n  private agentBay: AgentBay;\n\n  constructor(agentBay: AgentBay) {\n    this.agentBay = agentBay;\n  }\n\n  async getNetworkBindToken(networkId?: string): Promise<NetworkResult> {\n    try {\n      const request = new $_client.CreateNetworkRequest({\n        authorization: `Bearer ${this.agentBay.getAPIKey()}`,\n        loginRegionId: this.agentBay.getRegionId(),\n        networkId,\n      });\n\n      logAPICall(\"CreateNetwork(beta)\");\n      if (networkId) {\n        logDebug(`Request: NetworkId=${networkId}`);\n      }\n\n      const response = await this.agentBay.getClient().createNetwork(request);\n      const requestId = extractRequestId(response) || \"\";\n\n      if (!response.body || typeof response.body !== \"object\") {\n        logAPIResponseWithDetails(\n          \"CreateNetwork(beta)\",\n          requestId,\n          false,\n          undefined,\n          \"Invalid response format\"\n        );\n        return {\n          requestId,\n          success: false,\n          networkId: \"\",\n          networkToken: \"\",\n          errorMessage: \"Invalid response from CreateNetwork API\",\n        };\n      }\n\n      if (response.body.success === false) {\n        const code = response.body.code ? `[${response.body.code}] ` : \"\";\n        const msg = response.body.message || \"Unknown error\";\n        return {\n          requestId,\n          success: false,\n          networkId: \"\",\n          networkToken: \"\",\n          errorMessage: `${code}${msg}`,\n        };\n      }\n\n      const data = response.body.data;\n      if (!data || typeof data !== \"object\") {\n        return {\n          requestId,\n          success: false,\n          networkId: \"\",\n          networkToken: \"\",\n          errorMessage: \"Network data not found in response\",\n        };\n      }\n\n      return {\n        requestId,\n        success: true,\n        networkId: data.networkId || \"\",\n        networkToken: data.networkToken || \"\",\n      };\n    } catch (error: unknown) {\n      const msg = error instanceof Error ? error.message : `${error}`;\n      throw new APIError(`CreateNetwork(beta) failed: ${msg}`);\n    }\n  }\n\n  /**\n   * Deprecated: use getNetworkBindToken().\n   */\n  async create(networkId?: string): Promise<NetworkResult> {\n    return await this.getNetworkBindToken(networkId);\n  }\n\n  async describe(networkId: string): Promise<NetworkStatusResult> {\n    if (!networkId) {\n      return {\n        requestId: \"\",\n        success: false,\n        online: false,\n        errorMessage: \"network_id is required\",\n      };\n    }\n\n    const maxAttempts = 3;\n    let delayMs = 200;\n    for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n      try {\n        const request = new $_client.DescribeNetworkRequest({\n          authorization: `Bearer ${this.agentBay.getAPIKey()}`,\n          networkId,\n        });\n\n        logAPICall(\"DescribeNetwork(beta)\");\n        logDebug(`Request: NetworkId=${networkId}`);\n\n        const response = await this.agentBay\n          .getClient()\n          .describeNetwork(request);\n        const requestId = extractRequestId(response) || \"\";\n\n        if (!response.body || typeof response.body !== \"object\") {\n          logAPIResponseWithDetails(\n            \"DescribeNetwork(beta)\",\n            requestId,\n            false,\n            undefined,\n            \"Invalid response format\"\n          );\n          return {\n            requestId,\n            success: false,\n            online: false,\n            errorMessage: \"Invalid response from DescribeNetwork API\",\n          };\n        }\n\n        if (response.body.success === false) {\n          const code = response.body.code ? `[${response.body.code}] ` : \"\";\n          const msg = response.body.message || \"Unknown error\";\n          return {\n            requestId,\n            success: false,\n            online: false,\n            errorMessage: `${code}${msg}`,\n          };\n        }\n\n        const online = Boolean(response.body.data?.online);\n        return {\n          requestId,\n          success: true,\n          online,\n        };\n      } catch (error: unknown) {\n        const msg = error instanceof Error ? error.message : `${error}`;\n        if (\n          attempt < maxAttempts &&\n          (msg.includes(\"ServiceUnavailable\") || msg.includes(\"503\"))\n        ) {\n          await new Promise((resolve) => setTimeout(resolve, delayMs));\n          delayMs *= 2;\n          continue;\n        }\n        throw new APIError(`DescribeNetwork(beta) failed: ${msg}`);\n      }\n    }\n    throw new APIError(\"DescribeNetwork(beta) failed: exhausted retries\");\n  }\n}\n","import { AgentBay } from \"./agent-bay\";\nimport * as $_client from \"./api\";\nimport { APIError } from \"./exceptions\";\nimport { logAPICall, logDebug } from \"./utils/logger\";\n\nexport interface SkillMetadataItem {\n  name: string;\n  description: string;\n}\n\nexport interface SkillsMetadataResult {\n  skills: SkillMetadataItem[];\n  skillsRootPath: string;\n}\n\nexport interface GetMetadataOptions {\n  imageId?: string;\n  skillNames?: string[];\n}\n\n/**\n * Beta skills service (trial feature).\n */\nexport class BetaSkillsService {\n  private agentBay: AgentBay;\n\n  constructor(agentBay: AgentBay) {\n    this.agentBay = agentBay;\n  }\n\n  /**\n   * Get skills metadata without starting a sandbox.\n   *\n   * @param options - Optional filtering parameters.\n   * @param options.imageId - Image ID to determine the skills root path.\n   * @param options.groupIds - Filter by skill group IDs.\n   * @returns SkillsMetadataResult with skills list and skillsRootPath.\n   */\n  async getMetadata(\n    options: GetMetadataOptions = {}\n  ): Promise<SkillsMetadataResult> {\n    const request = new $_client.GetSkillMetaDataRequest({\n      authorization: `Bearer ${this.agentBay.getAPIKey()}`,\n      imageId: options.imageId,\n      skillGroupIds: options.skillNames,\n    });\n\n    const maxAttempts = 3;\n    let delayMs = 200;\n    for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n      try {\n        logAPICall(\"GetSkillMetaData(beta)\");\n        const response = await this.agentBay\n          .getClient()\n          .getSkillMetaData(request);\n\n        if (!response.body || typeof response.body !== \"object\") {\n          throw new APIError(\n            \"GetSkillMetaData failed: invalid response format\"\n          );\n        }\n\n        if (response.body.success === false) {\n          const code = response.body.code ? `[${response.body.code}] ` : \"\";\n          const msg = response.body.message || \"Unknown error\";\n          throw new APIError(`GetSkillMetaData failed: ${code}${msg}`);\n        }\n\n        const data = response.body.data;\n        if (!data) {\n          throw new APIError(\"GetSkillMetaData failed: missing Data field\");\n        }\n\n        const skillPath = String(data.skillPath || \"\");\n        const metaDataList = data.metaDataList || [];\n\n        const skills: SkillMetadataItem[] = [];\n        for (const raw of metaDataList) {\n          const name = String(raw?.name || \"\").trim();\n          if (!name) {\n            continue;\n          }\n          const description = String(raw?.description || \"\");\n          skills.push({ name, description });\n        }\n\n        return { skills, skillsRootPath: skillPath };\n      } catch (error: unknown) {\n        const msg = error instanceof Error ? error.message : `${error}`;\n        logDebug(`GetSkillMetaData attempt ${attempt} failed: ${msg}`);\n        if (\n          attempt < maxAttempts &&\n          (msg.includes(\"ServiceUnavailable\") || msg.includes(\"503\"))\n        ) {\n          await new Promise((resolve) => setTimeout(resolve, delayMs));\n          delayMs *= 2;\n          continue;\n        }\n        if (error instanceof APIError) {\n          throw error;\n        }\n        throw new APIError(`GetSkillMetaData failed: ${msg}`);\n      }\n    }\n    throw new APIError(\"GetSkillMetaData failed: exhausted retries\");\n  }\n\n  /**\n   * @deprecated Use getMetadata() instead.\n   */\n  async listMetadata(): Promise<SkillMetadataItem[]> {\n    const request = new $_client.ListSkillMetaDataRequest({\n      authorization: `Bearer ${this.agentBay.getAPIKey()}`,\n    });\n\n    const maxAttempts = 3;\n    let delayMs = 200;\n    for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n      try {\n        logAPICall(\"ListSkillMetaData(beta)\");\n        const response = await this.agentBay\n          .getClient()\n          .listSkillMetaData(request);\n\n        if (!response.body || typeof response.body !== \"object\") {\n          throw new APIError(\n            \"ListSkillMetaData(beta) failed: invalid response format\"\n          );\n        }\n\n        if (response.body.success === false) {\n          const code = response.body.code ? `[${response.body.code}] ` : \"\";\n          const msg = response.body.message || \"Unknown error\";\n          throw new APIError(`ListSkillMetaData(beta) failed: ${code}${msg}`);\n        }\n\n        const data = response.body.data;\n        if (!Array.isArray(data)) {\n          throw new APIError(\n            \"ListSkillMetaData(beta) failed: invalid Data field\"\n          );\n        }\n\n        const items: SkillMetadataItem[] = [];\n        for (const raw of data) {\n          const name = String((raw as any)?.name || \"\").trim();\n          if (!name) {\n            continue;\n          }\n          const description = String((raw as any)?.description || \"\");\n          items.push({ name, description });\n        }\n        return items;\n      } catch (error: unknown) {\n        const msg = error instanceof Error ? error.message : `${error}`;\n        logDebug(`ListSkillMetaData(beta) attempt ${attempt} failed: ${msg}`);\n        if (\n          attempt < maxAttempts &&\n          (msg.includes(\"ServiceUnavailable\") || msg.includes(\"503\"))\n        ) {\n          await new Promise((resolve) => setTimeout(resolve, delayMs));\n          delayMs *= 2;\n          continue;\n        }\n        if (error instanceof APIError) {\n          throw error;\n        }\n        throw new APIError(`ListSkillMetaData(beta) failed: ${msg}`);\n      }\n    }\n    throw new APIError(\"ListSkillMetaData(beta) failed: exhausted retries\");\n  }\n}\n","// UploadStrategy defines the upload strategy for context synchronization\nexport enum UploadStrategy {\n  UploadBeforeResourceRelease = \"UploadBeforeResourceRelease\",\n}\n\n// DownloadStrategy defines the download strategy for context synchronization\nexport enum DownloadStrategy {\n  DownloadAsync = \"DownloadAsync\",\n}\n\n// UploadMode defines the upload mode for context synchronization\nexport enum UploadMode {\n  File = \"File\",\n  Archive = \"Archive\",\n}\n\n// Lifecycle defines the lifecycle options for recycle policy\nexport enum Lifecycle {\n  Lifecycle_1Day = \"Lifecycle_1Day\",\n  Lifecycle_3Days = \"Lifecycle_3Days\",\n  Lifecycle_5Days = \"Lifecycle_5Days\",\n  Lifecycle_10Days = \"Lifecycle_10Days\",\n  Lifecycle_15Days = \"Lifecycle_15Days\",\n  Lifecycle_30Days = \"Lifecycle_30Days\",\n  Lifecycle_90Days = \"Lifecycle_90Days\",\n  Lifecycle_180Days = \"Lifecycle_180Days\",\n  Lifecycle_360Days = \"Lifecycle_360Days\",\n  Lifecycle_Forever = \"Lifecycle_Forever\",\n}\n\n// UploadPolicy defines the upload policy for context synchronization\nexport interface UploadPolicy {\n  autoUpload: boolean;\n  uploadStrategy: UploadStrategy;\n  uploadMode: UploadMode;\n  archiveExcludePaths?: string[];\n}\n\n// DownloadPolicy defines the download policy for context synchronization\nexport interface DownloadPolicy {\n  autoDownload: boolean;\n  downloadStrategy: DownloadStrategy;\n}\n\n// DeletePolicy defines the delete policy for context synchronization\nexport interface DeletePolicy {\n  syncLocalFile: boolean;\n}\n\n// ExtractPolicy defines the extract policy for context synchronization\nexport interface ExtractPolicy {\n  extract: boolean;\n  deleteSrcFile: boolean;\n  extractToCurrentFolder: boolean;\n}\n\n// RecyclePolicy defines the recycle policy for context synchronization\nexport interface RecyclePolicy {\n  lifecycle: Lifecycle;\n  paths: string[];\n}\n\n// ExtractPolicyClass provides a class-based implementation with default values\nexport class ExtractPolicyClass implements ExtractPolicy {\n  extract = true;\n  deleteSrcFile = true;\n  extractToCurrentFolder = false;\n\n  constructor(\n    extract = true,\n    deleteSrcFile = true,\n    extractToCurrentFolder = false\n  ) {\n    this.extract = extract;\n    this.deleteSrcFile = deleteSrcFile;\n    this.extractToCurrentFolder = extractToCurrentFolder;\n  }\n\n  /**\n   * Creates a new extract policy with default values\n   */\n  static default(): ExtractPolicyClass {\n    return new ExtractPolicyClass();\n  }\n\n  /**\n   * Converts to plain object for JSON serialization\n   */\n  toDict(): Record<string, any> {\n    return {\n      extract: this.extract,\n      deleteSrcFile: this.deleteSrcFile,\n      extractToCurrentFolder: this.extractToCurrentFolder,\n    };\n  }\n}\n\n// WhiteList defines the white list configuration\n// When isPathRegex is false (default), path must be an exact absolute directory path\n// and wildcard characters are not allowed.\n// When isPathRegex is true, path is treated as a regex pattern (e.g. \"/home/wuying/.*\").\n// When isExcludeRegex is false (default), excludePaths entries must be exact paths\n// and wildcard characters are not allowed.\n// When isExcludeRegex is true, excludePaths entries are treated as regex patterns.\nexport interface WhiteList {\n  path: string;\n  excludePaths?: string[];\n  isPathRegex?: boolean;\n  isExcludeRegex?: boolean;\n}\n\nexport class WhiteListValidator {\n  private static containsWildcard(path: string): boolean {\n    return /[*?\\[\\]]/.test(path);\n  }\n\n  static validate(whitelist: WhiteList): void {\n    // Only validate wildcard when isPathRegex is false (default)\n    if (!whitelist.isPathRegex && this.containsWildcard(whitelist.path)) {\n      throw new Error(\n        `Wildcard patterns are not supported in path when isPathRegex=false. Got: ${whitelist.path}. ` +\n          \"Please use exact directory paths or set isPathRegex=true for regex matching.\"\n      );\n    }\n\n    // Only validate wildcards in excludePaths when isExcludeRegex is false (default)\n    if (!whitelist.isExcludeRegex && whitelist.excludePaths) {\n      for (const excludePath of whitelist.excludePaths) {\n        if (this.containsWildcard(excludePath)) {\n          throw new Error(\n            `Wildcard patterns are not supported in excludePaths when isExcludeRegex=false. Got: ${excludePath}. ` +\n              \"Please use exact directory paths or set isExcludeRegex=true for regex matching.\"\n          );\n        }\n      }\n    }\n  }\n}\n\n// BWList defines the black and white list configuration\nexport interface BWList {\n  whiteLists?: WhiteList[];\n}\n\n// MappingPolicy defines the mapping policy for cross-platform context synchronization\nexport interface MappingPolicy {\n  path: string;\n}\n\n// SyncPolicy defines the synchronization policy\nexport interface SyncPolicy {\n  uploadPolicy?: UploadPolicy;\n  downloadPolicy?: DownloadPolicy;\n  deletePolicy?: DeletePolicy;\n  extractPolicy?: ExtractPolicy;\n  recyclePolicy?: RecyclePolicy;\n  bwList?: BWList;\n  mappingPolicy?: MappingPolicy;\n}\n\nconst ALLOWED_POLICY_KEYS = new Set([\n  \"uploadPolicy\",\n  \"downloadPolicy\",\n  \"deletePolicy\",\n  \"extractPolicy\",\n  \"recyclePolicy\",\n  \"bwList\",\n  \"mappingPolicy\",\n]);\n\n// Helper to validate object keys\nfunction validatePolicyKeys(policy: any): void {\n  if (!policy || typeof policy !== \"object\") return;\n\n  for (const key of Object.keys(policy)) {\n    if (!ALLOWED_POLICY_KEYS.has(key)) {\n      throw new Error(\n        `Unknown property in SyncPolicy: '${key}'. ` +\n          `Valid properties are: ${Array.from(ALLOWED_POLICY_KEYS).join(\", \")}`\n      );\n    }\n  }\n}\n\n// SyncPolicyImpl provides a class-based implementation with default value handling\nexport class SyncPolicyImpl implements SyncPolicy {\n  uploadPolicy?: UploadPolicy;\n  downloadPolicy?: DownloadPolicy;\n  deletePolicy?: DeletePolicy;\n  extractPolicy?: ExtractPolicy;\n  recyclePolicy?: RecyclePolicy;\n  bwList?: BWList;\n\n  constructor(policy?: Partial<SyncPolicy>) {\n    if (policy) {\n      validatePolicyKeys(policy);\n      this.uploadPolicy = policy.uploadPolicy;\n      this.downloadPolicy = policy.downloadPolicy;\n      this.deletePolicy = policy.deletePolicy;\n      this.extractPolicy = policy.extractPolicy;\n      this.recyclePolicy = policy.recyclePolicy;\n      this.bwList = policy.bwList;\n    }\n    this.ensureDefaults();\n  }\n\n  private ensureDefaults(): void {\n    if (!this.uploadPolicy) {\n      this.uploadPolicy = newUploadPolicy();\n    }\n    if (!this.downloadPolicy) {\n      this.downloadPolicy = newDownloadPolicy();\n    }\n    if (!this.deletePolicy) {\n      this.deletePolicy = newDeletePolicy();\n    }\n    if (!this.extractPolicy) {\n      this.extractPolicy = newExtractPolicy();\n    }\n    if (!this.recyclePolicy) {\n      this.recyclePolicy = newRecyclePolicy();\n    }\n    if (!this.bwList) {\n      this.bwList = {\n        whiteLists: [\n          {\n            path: \"\",\n            excludePaths: [],\n          },\n        ],\n      };\n    }\n  }\n\n  toJSON(): SyncPolicy {\n    this.ensureDefaults();\n    let uploadPolicy = this.uploadPolicy;\n    if (\n      uploadPolicy?.archiveExcludePaths &&\n      uploadPolicy.uploadMode !== UploadMode.Archive\n    ) {\n      const { archiveExcludePaths: _, ...rest } = uploadPolicy;\n      uploadPolicy = rest as UploadPolicy;\n    }\n    return {\n      uploadPolicy,\n      downloadPolicy: this.downloadPolicy,\n      deletePolicy: this.deletePolicy,\n      extractPolicy: this.extractPolicy,\n      recyclePolicy: this.recyclePolicy,\n      bwList: this.bwList,\n    };\n  }\n}\n\n// ContextSync defines the context synchronization configuration\nexport class ContextSync {\n  contextId: string;\n  path: string;\n  policy?: SyncPolicy;\n  /**\n   * Beta feature flag to control whether session creation should wait for this context's\n   * initial download to finish. If set to false, the SDK will not block create() on this context.\n   * Defaults to undefined (treated as true for backward compatibility).\n   */\n  betaWaitForCompletion?: boolean;\n\n  /**\n   * Defines a full context sync configuration with optional policy overrides.\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: 'your_api_key' });\n   * const result = await agentBay.create();\n   * if (result.success) {\n   *   const policy = new SyncPolicyImpl({\n   *     uploadPolicy: newUploadPolicy(),\n   *     downloadPolicy: newDownloadPolicy(),\n   *     recyclePolicy: newRecyclePolicy(),\n   *   });\n   *   const syncResult = await result.session.context.sync(\n   *     'project-data',\n   *     '/mnt/shared',\n   *     'upload'\n   *   );\n   *   console.log('Context sync:', syncResult.success);\n   *   await result.session.delete();\n   * }\n   * ```\n   */\n  constructor(\n    contextId: string,\n    path: string,\n    policy?: SyncPolicy,\n    betaWaitForCompletion?: boolean\n  ) {\n    if (policy) {\n      validateSyncPolicy(policy);\n    }\n    this.contextId = contextId;\n    this.path = path;\n    this.policy = policy;\n    this.betaWaitForCompletion = betaWaitForCompletion;\n  }\n\n  // WithPolicy sets the policy and returns the context sync for chaining\n  withPolicy(policy: SyncPolicy): ContextSync {\n    validateSyncPolicy(policy);\n    this.policy = policy;\n    return this;\n  }\n\n  withBetaWaitForCompletion(wait: boolean): ContextSync {\n    this.betaWaitForCompletion = wait;\n    return this;\n  }\n}\n\n// NewUploadPolicy creates a new upload policy with default values\nexport function newUploadPolicy(options?: Partial<UploadPolicy>): UploadPolicy {\n  const policy: UploadPolicy = {\n    autoUpload: options?.autoUpload ?? true,\n    uploadStrategy:\n      options?.uploadStrategy ?? UploadStrategy.UploadBeforeResourceRelease,\n    uploadMode: options?.uploadMode ?? UploadMode.File,\n  };\n  if (options?.archiveExcludePaths && options.archiveExcludePaths.length > 0) {\n    policy.archiveExcludePaths = options.archiveExcludePaths;\n  }\n  return policy;\n}\n\n// NewDownloadPolicy creates a new download policy with default values\nexport function newDownloadPolicy(): DownloadPolicy {\n  return {\n    autoDownload: true,\n    downloadStrategy: DownloadStrategy.DownloadAsync,\n  };\n}\n\n// NewDeletePolicy creates a new delete policy with default values\nexport function newDeletePolicy(): DeletePolicy {\n  return {\n    syncLocalFile: true,\n  };\n}\n\n// NewExtractPolicy creates a new extract policy with default values\nexport function newExtractPolicy(): ExtractPolicy {\n  return {\n    extract: true,\n    deleteSrcFile: true,\n    extractToCurrentFolder: false,\n  };\n}\n\n// NewRecyclePolicy creates a new recycle policy with default values\nexport function newRecyclePolicy(): RecyclePolicy {\n  return {\n    lifecycle: Lifecycle.Lifecycle_Forever,\n    paths: [\"\"],\n  };\n}\n\n// NewMappingPolicy creates a new mapping policy with default values\nexport function newMappingPolicy(): MappingPolicy {\n  return {\n    path: \"\",\n  };\n}\n\n// NewSyncPolicy creates a new sync policy with default values\nexport function newSyncPolicy(): SyncPolicy {\n  return {\n    uploadPolicy: newUploadPolicy(),\n    downloadPolicy: newDownloadPolicy(),\n    deletePolicy: newDeletePolicy(),\n    extractPolicy: newExtractPolicy(),\n    recyclePolicy: newRecyclePolicy(),\n    bwList: {\n      whiteLists: [\n        {\n          path: \"\",\n          excludePaths: [],\n        },\n      ],\n    },\n  };\n}\n\n// isValidLifecycle checks if the given lifecycle value is valid\nfunction isValidLifecycle(lifecycle: Lifecycle): boolean {\n  return Object.values(Lifecycle).includes(lifecycle);\n}\n\n// isValidUploadMode checks if the given uploadMode value is valid\nfunction isValidUploadMode(uploadMode: UploadMode): boolean {\n  return uploadMode === UploadMode.File || uploadMode === UploadMode.Archive;\n}\n\nexport function validateSyncPolicy(policy?: SyncPolicy): void {\n  if (policy) {\n    // If policy is NOT an instance of SyncPolicyImpl (which already validated keys), validate keys\n    // This catches POJOs passed directly to ContextSync\n    if (!(policy instanceof SyncPolicyImpl)) {\n      validatePolicyKeys(policy);\n    }\n  }\n\n  if (policy?.bwList?.whiteLists) {\n    for (const whitelist of policy.bwList.whiteLists) {\n      WhiteListValidator.validate(whitelist);\n    }\n  }\n\n  if (policy?.uploadPolicy?.uploadMode) {\n    // Validate uploadMode value\n    if (!isValidUploadMode(policy.uploadPolicy.uploadMode)) {\n      throw new Error(\n        `Invalid uploadMode value: ${policy.uploadPolicy.uploadMode}. ` +\n          `Valid values are: ${UploadMode.File}, ${UploadMode.Archive}`\n      );\n    }\n  }\n\n  if (policy?.recyclePolicy) {\n    // Validate lifecycle value\n    if (!isValidLifecycle(policy.recyclePolicy.lifecycle)) {\n      const validValues = Object.values(Lifecycle).join(\", \");\n      throw new Error(\n        `Invalid lifecycle value: ${policy.recyclePolicy.lifecycle}. ` +\n          `Valid values are: ${validValues}`\n      );\n    }\n\n    // Validate paths don't contain wildcard patterns\n    if (policy.recyclePolicy.paths) {\n      for (const path of policy.recyclePolicy.paths) {\n        if (path && path.trim() !== \"\") {\n          // Create a temporary WhiteList object for validation\n          const tempWhiteList: WhiteList = { path: path };\n          WhiteListValidator.validate(tempWhiteList);\n        }\n      }\n    }\n  }\n}\n\n// NewSyncPolicyWithDefaults creates a new sync policy with partial parameters and fills defaults\nexport function newSyncPolicyWithDefaults(\n  policy?: Partial<SyncPolicy>\n): SyncPolicy {\n  return new SyncPolicyImpl(policy).toJSON();\n}\n\n// NewContextSync creates a new context sync configuration\nexport function newContextSync(\n  contextId: string,\n  path: string,\n  policy?: SyncPolicy\n): ContextSync {\n  if (policy) {\n    validateSyncPolicy(policy);\n  }\n  return new ContextSync(contextId, path, policy);\n}\n","import { AgentBay } from \"./agent-bay\";\nimport { Agent } from \"./agent/agent\";\nimport { Client } from \"./api/client\";\nimport * as $_client from \"./api\";\nimport {\n  CallMcpToolRequest,\n  DeleteSessionAsyncRequest,\n  GetLabelRequest,\n  GetLinkRequest,\n  GetMcpResourceRequest,\n  GetSessionDetailRequest,\n  ListMcpToolsRequest,\n  RefreshSessionIdleTimeRequest,\n  SetLabelRequest,\n} from \"./api/models/model\";\nimport { Browser } from \"./browser\";\nimport { Code } from \"./code\";\nimport { Command } from \"./command\";\nimport { Computer } from \"./computer\";\nimport { Env } from \"./env\";\nimport {\n  ContextManager,\n  ContextSyncResult,\n  newContextManager,\n} from \"./context-manager\";\nimport { FileSystem } from \"./filesystem\";\nimport { Git } from \"./git\";\nimport { Mobile } from \"./mobile\";\nimport { Oss } from \"./oss\";\nimport { Pty } from \"./pty\";\nimport { WsClient } from \"./_internal/ws-client\";\nimport {\n  ApiResponse,\n  DeleteResult,\n  extractRequestId,\n  OperationResult,\n  SessionPauseResult,\n  SessionResumeResult,\n  SessionMetrics,\n  SessionMetricsResult,\n} from \"./types/api-response\";\nimport {\n  logError,\n  logInfo,\n  logDebug,\n  logWarn,\n  logAPICall,\n  logAPIResponseWithDetails,\n  logCodeExecutionOutput,\n  logInfoWithColor,\n  setRequestId,\n} from \"./utils/logger\";\n\nasync function fetchCompat(\n  input: any,\n  init: any,\n  timeoutMs?: number\n): Promise<any> {\n  // Add timeout support using AbortController if timeout is specified\n  if (timeoutMs && timeoutMs > 0) {\n    // Use globalThis.AbortController for better compatibility\n    const AbortControllerClass = (globalThis as any).AbortController;\n    if (!AbortControllerClass) {\n      // If AbortController is not available, fallback to fetch without timeout\n      const f = (globalThis as any).fetch;\n      if (typeof f === \"function\") {\n        return await f(input, init);\n      }\n\n      const mod: any = await import(\"node-fetch\");\n      const nodeFetch = mod.default || mod;\n      return await nodeFetch(input, init);\n    }\n\n    const controller = new AbortControllerClass();\n    const timeoutId = setTimeout(() => controller.abort(), timeoutMs);\n\n    init = {\n      ...init,\n      signal: controller.signal,\n    };\n\n    try {\n      const f = (globalThis as any).fetch;\n      if (typeof f === \"function\") {\n        const response = await f(input, init);\n        clearTimeout(timeoutId);\n        return response;\n      }\n\n      const mod: any = await import(\"node-fetch\");\n      const nodeFetch = mod.default || mod;\n      const response = await nodeFetch(input, init);\n      clearTimeout(timeoutId);\n      return response;\n    } catch (error: any) {\n      clearTimeout(timeoutId);\n      if (error.name === \"AbortError\") {\n        throw new Error(`Request timeout after ${timeoutMs}ms`);\n      }\n      throw error;\n    }\n  }\n\n  const f = (globalThis as any).fetch;\n  if (typeof f === \"function\") {\n    return await f(input, init);\n  }\n\n  const mod: any = await import(\"node-fetch\");\n  const nodeFetch = mod.default || mod;\n  return await nodeFetch(input, init);\n}\n\n/**\n * Represents an MCP tool with complete information.\n */\nexport interface McpTool {\n  name: string;\n  description: string;\n  inputSchema: Record<string, any>;\n  server: string;\n  tool: string;\n}\n\n/**\n * Result containing MCP tools list and request ID.\n */\nexport interface McpToolsResult extends OperationResult {\n  tools: McpTool[];\n}\n\n/**\n * Result containing MCP resource information and request ID.\n */\nexport interface McpResourceResult extends OperationResult {\n  uri: string;\n  name: string;\n  description: string;\n  mimeType: string;\n}\n\n/**\n * Result containing MCP resource content and request ID.\n */\nexport interface McpResourceContentResult extends OperationResult {\n  contents: Array<{\n    uri: string;\n    mimeType: string;\n    text?: string;\n    blob?: string;\n  }>;\n}\n\n/**\n * Result of Session.getStatus() (status only).\n */\nexport interface SessionStatusResult extends ApiResponse {\n  requestId: string;\n  httpStatusCode: number;\n  code: string;\n  success: boolean;\n  status: string;\n  errorMessage?: string;\n}\n\n/**\n * Contains information about a session.\n */\nexport interface SessionInfo {\n  sessionId: string;\n  resourceUrl: string;\n  appId?: string;\n  authCode?: string;\n  connectionProperties?: string;\n  resourceId?: string;\n  resourceType?: string;\n  ticket?: string;\n}\n\n/**\n * SessionInfo class to match Python version structure\n */\nexport class SessionInfoClass {\n  sessionId: string;\n  resourceUrl: string;\n  appId: string;\n  authCode: string;\n  connectionProperties: string;\n  resourceId: string;\n  resourceType: string;\n  ticket: string;\n\n  constructor(\n    sessionId = \"\",\n    resourceUrl = \"\",\n    appId = \"\",\n    authCode = \"\",\n    connectionProperties = \"\",\n    resourceId = \"\",\n    resourceType = \"\",\n    ticket = \"\"\n  ) {\n    this.sessionId = sessionId;\n    this.resourceUrl = resourceUrl;\n    this.appId = appId;\n    this.authCode = authCode;\n    this.connectionProperties = connectionProperties;\n    this.resourceId = resourceId;\n    this.resourceType = resourceType;\n    this.ticket = ticket;\n  }\n}\n\n/**\n * Represents a session in the AgentBay cloud environment.\n */\nexport class Session {\n  private agentBay: AgentBay;\n  public sessionId: string;\n\n  public resourceUrl = \"\";\n\n  /** Application instance ID */\n  public appInstanceId = \"\";\n\n  /** VPC IP. Returned only for sessions created on a custom VPC network; empty otherwise. */\n  public vpcIp = \"\";\n  /** VPC ID. Returned only for sessions created on a custom VPC network; empty otherwise. */\n  public vpcId = \"\";\n\n  /** Token for VPC sessions */\n  public token = \"\";\n  public linkUrl = \"\";\n\n  /** WebSocket URL for streaming features */\n  public wsUrl = \"\";\n\n  /** Cached WebSocket client instance */\n  private _wsClient: WsClient | null = null;\n\n  // Recording functionality\n  public enableBrowserReplay?: boolean; // Whether browser recording is enabled for this session (undefined = server default)\n\n  // File, command, code, and oss handlers (matching Python naming)\n  public fileSystem: FileSystem; // file_system in Python\n  public command: Command;\n  public env: Env;\n  public code: Code;\n  public oss: Oss;\n\n  // Computer and Mobile automation (new modules)\n  public computer: Computer;\n  public mobile: Mobile;\n\n  // Agent for task execution\n  public agent: Agent;\n\n  // Browser for web automation\n  public browser: Browser;\n\n  // Git operations\n  public git: Git;\n\n  // Context management (matching Go version)\n  public context: ContextManager;\n\n  public pty: Pty;\n\n  // MCP tools list returned by backend for this session\n  public mcpTools: McpTool[] = [];\n\n  /**\n   * Initialize a Session object.\n   *\n   * @param agentBay - The AgentBay instance that created this session.\n   * @param sessionId - The ID of this session.\n   */\n  constructor(agentBay: AgentBay, sessionId: string) {\n    this.agentBay = agentBay;\n    this.sessionId = sessionId;\n\n    // Initialize file system, command and code handlers (matching Python naming)\n    this.fileSystem = new FileSystem(this);\n    this.command = new Command(this);\n    this.env = new Env(this);\n    this.code = new Code(this);\n    this.oss = new Oss(this);\n\n    // Initialize Computer and Mobile modules\n    this.computer = new Computer(this);\n    this.mobile = new Mobile(this);\n\n    // Initialize Agent\n    this.agent = new Agent(this);\n\n    // Initialize Browser\n    this.browser = new Browser(this);\n\n    // Initialize Git\n    this.git = new Git(this);\n\n    // Initialize context manager (matching Go version)\n    this.context = newContextManager(this);\n\n    // Initialize PTY module\n    this.pty = new Pty(this);\n  }\n\n  /**\n   * Internal helper for WS streaming features.\n   */\n  async getWsClient(): Promise<WsClient> {\n    if (!this.wsUrl) {\n      throw new Error(\"Missing wsUrl on session; streaming is not available\");\n    }\n    if (!this.token) {\n      throw new Error(\"Missing token on session; streaming is not available\");\n    }\n    if (!this._wsClient) {\n      this._wsClient = new WsClient(this.wsUrl, this.token);\n    }\n    await this._wsClient.connect();\n    return this._wsClient;\n  }\n\n  /**\n   * Alias of fileSystem.\n   */\n  get fs(): FileSystem {\n    return this.fileSystem;\n  }\n\n  /**\n   * Alias of fileSystem.\n   */\n  get filesystem(): FileSystem {\n    return this.fileSystem;\n  }\n\n  /**\n   * Alias of fileSystem.\n   */\n  get files(): FileSystem {\n    return this.fileSystem;\n  }\n\n  /**\n   * Return the AgentBay instance that created this session.\n   *\n   * @returns The AgentBay client instance\n   * @internal\n   */\n  getAgentBay(): AgentBay {\n    return this.agentBay;\n  }\n\n  /**\n   * Return the API key for this session.\n   * Note: This method is used internally by SDK modules (Code, Computer, Mobile, Agent).\n   *\n   * @returns The API key string\n   * @internal\n   */\n  getAPIKey(): string {\n    return this.agentBay.getAPIKey();\n  }\n\n  /**\n   * @deprecated Internal SDK use only. Will be removed in a future version.\n   */\n  getToken(): string {\n    return this.token;\n  }\n\n  /**\n   * @deprecated Internal SDK use only. Will be removed in a future version.\n   */\n  getLinkUrl(): string {\n    return this.linkUrl;\n  }\n\n  /**\n   * Return the HTTP client for this session.\n   *\n   * @returns The Client instance used for API communication\n   * @internal\n   */\n  getClient(): Client {\n    return this.agentBay.getClient();\n  }\n\n  /**\n   * Return the session_id for this session.\n   * Note: This method is used internally by SDK modules. Users should prefer using the `sessionId` property.\n   *\n   * @returns The session ID string\n   * @internal\n   */\n  getSessionId(): string {\n    return this.sessionId;\n  }\n\n  /**\n   * Get basic session status.\n   *\n   * @returns SessionStatusResult containing status only.\n   */\n  async getStatus(): Promise<SessionStatusResult> {\n    try {\n      logAPICall(\"GetSessionDetail\", { sessionId: this.sessionId });\n\n      const request = new GetSessionDetailRequest({\n        authorization: `Bearer ${this.getAPIKey()}`,\n        sessionId: this.sessionId,\n      });\n\n      const response = await this.getClient().getSessionDetail(request);\n      const body = response.body;\n      const requestId = extractRequestId(response) || body?.requestId || \"\";\n\n      setRequestId(requestId);\n\n      // Check for API-level errors\n      if (body?.success === false && body.code) {\n        logAPIResponseWithDetails(\n          \"GetSessionDetail\",\n          requestId,\n          false,\n          {},\n          `[${body.code}] ${body.message || \"Unknown error\"}`\n        );\n        logDebug(\n          \"Full GetSessionDetail response:\",\n          JSON.stringify(body, null, 2)\n        );\n        return {\n          requestId,\n          httpStatusCode: body.httpStatusCode || 0,\n          code: body.code,\n          success: false,\n          status: \"\",\n          errorMessage: `[${body.code}] ${body.message || \"Unknown error\"}`,\n        };\n      }\n\n      const result: SessionStatusResult = {\n        requestId,\n        httpStatusCode: body?.httpStatusCode || 0,\n        code: body?.code || \"\",\n        success: body?.success || false,\n        status: body?.data?.status || \"\",\n        errorMessage: \"\",\n      };\n\n      logAPIResponseWithDetails(\"GetSessionDetail\", requestId, true, {\n        status: result.status,\n      });\n\n      return result;\n    } catch (error: any) {\n      const errorStr = String(error);\n      const errorCode = error?.data?.Code || error?.code || \"\";\n\n      if (\n        errorCode === \"InvalidMcpSession.NotFound\" ||\n        errorStr.includes(\"NotFound\")\n      ) {\n        logInfoWithColor(`Session not found: ${this.sessionId}`);\n        logDebug(`GetSessionDetail error details: ${errorStr}`);\n        return {\n          requestId: \"\",\n          httpStatusCode: 400,\n          code: \"InvalidMcpSession.NotFound\",\n          success: false,\n          status: \"\",\n          errorMessage: `Session ${this.sessionId} not found`,\n        };\n      }\n\n      logError(\"Error calling GetSessionDetail:\", error);\n      return {\n        requestId: \"\",\n        httpStatusCode: 0,\n        code: \"\",\n        success: false,\n        status: \"\",\n        errorMessage: `Failed to get session detail ${this.sessionId}: ${error}`,\n      };\n    }\n  }\n\n  /**\n   * Refresh the backend idle timer for this session.\n   *\n   * This method calls the RefreshSessionIdleTime API.\n   */\n  async keepAlive(): Promise<OperationResult> {\n    try {\n      logAPICall(\"RefreshSessionIdleTime\", { sessionId: this.sessionId });\n\n      const request = new RefreshSessionIdleTimeRequest({\n        authorization: `Bearer ${this.getAPIKey()}`,\n        sessionId: this.sessionId,\n      });\n\n      const response = await this.getClient().refreshSessionIdleTime(request);\n      const requestId =\n        extractRequestId(response) || response?.body?.requestId || \"\";\n\n      const body = response?.body;\n      if (body?.success === false && body.code) {\n        const errorMessage = `[${body.code}] ${\n          body.message || \"Unknown error\"\n        }`;\n        logAPIResponseWithDetails(\n          \"RefreshSessionIdleTime\",\n          requestId,\n          false,\n          {},\n          JSON.stringify(body, null, 2)\n        );\n        return {\n          requestId,\n          success: false,\n          errorMessage,\n        };\n      }\n\n      logAPIResponseWithDetails(\"RefreshSessionIdleTime\", requestId, true, {\n        session_id: this.sessionId,\n      });\n\n      return {\n        requestId,\n        success: true,\n      };\n    } catch (error) {\n      logError(\"Error calling RefreshSessionIdleTime:\", error);\n      return {\n        requestId: \"\",\n        success: false,\n        errorMessage: `Failed to keep session alive ${this.sessionId}: ${error}`,\n      };\n    }\n  }\n\n  /**\n   * Alias of keepAlive for API compatibility.\n   */\n  async keepAliveAsync(): Promise<OperationResult> {\n    return await this.keepAlive();\n  }\n\n  /**\n   * Delete this session.\n   *\n   * @param syncContext - Whether to sync context data (trigger file uploads) before deleting the session. Defaults to false.\n   * @returns DeleteResult indicating success or failure and request ID\n   */\n  /**\n   * Deletes the session and releases all associated resources.\n   *\n   * @param syncContext - Whether to synchronize context data before deletion.\n   *                      If true, uploads all context data to OSS.\n   *                      If false but browser replay is enabled, syncs only the recording context.\n   *                      Defaults to false.\n   *\n   * @returns Promise resolving to DeleteResult containing:\n   *          - success: Whether deletion succeeded\n   *          - requestId: Unique identifier for this API request\n   *          - errorMessage: Error description if deletion failed\n   *\n   * @throws Error if the API call fails or network issues occur.\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: 'your_api_key' });\n   * const result = await agentBay.create();\n   * if (result.success) {\n   *   await result.session.fileSystem.writeFile('/tmp/data.txt', 'data');\n   *   const deleteResult = await result.session.delete(true);\n   *   console.log('Session deleted:', deleteResult.success);\n   * }\n   * ```\n   *\n   * @remarks\n   * **Behavior:**\n   * - If `syncContext=true`: Uploads all context data to OSS before deletion\n   * - If `syncContext=false` but browser replay enabled: Syncs only recording context\n   * - If `syncContext=false` and no browser replay: Deletes immediately without sync\n   * - Continues with deletion even if context sync fails\n   * - Releases all associated resources (browser, computer, mobile, etc.)\n   *\n   * **Best Practices:**\n   * - Use `syncContext=true` when you need to preserve context data for later retrieval\n   * - For temporary sessions, use `syncContext=false` for faster cleanup\n   * - Always call `delete()` when done to avoid resource leaks\n   * - Handle deletion errors gracefully in production code\n   *\n   * @see {@link info}, {@link ContextManager.sync}\n   */\n  async delete(syncContext = false): Promise<DeleteResult> {\n    try {\n      if (this._wsClient) {\n        try {\n          await this._wsClient.close();\n        } catch (_e) {}\n        this._wsClient = null;\n      }\n      if (syncContext) {\n        logDebug(\n          \"Triggering context synchronization before session deletion...\"\n        );\n\n        // Use the new sync method without callback (sync mode)\n        const syncStartTime = Date.now();\n\n        try {\n          // Sync all contexts\n          const syncResult: ContextSyncResult = await this.context.sync();\n          logInfo(\"🔄 Synced all contexts\");\n\n          const syncDuration = Date.now() - syncStartTime;\n\n          if (syncResult.success) {\n            logInfo(`Context sync completed in ${syncDuration}ms`);\n          } else {\n            logInfo(\n              `Context sync completed with failures after ${syncDuration}ms`\n            );\n          }\n        } catch (error) {\n          const syncDuration = Date.now() - syncStartTime;\n          logError(\n            `Failed to trigger context sync after ${syncDuration}ms:`,\n            error\n          );\n          // Continue with deletion even if sync fails\n        }\n      }\n\n      // Proceed with session deletion\n      const request = new DeleteSessionAsyncRequest({\n        authorization: `Bearer ${this.getAPIKey()}`,\n        sessionId: this.sessionId,\n      });\n\n      const response = await this.getClient().deleteSessionAsync(request);\n      logDebug(\n        `Response from delete_session_async: ${JSON.stringify(response)}`\n      );\n\n      // Extract request ID\n      const requestId = extractRequestId(response) || \"\";\n\n      // Check if the response is success (matching Python logic)\n      const responseBody = response.body;\n      const success = responseBody?.success !== false; // Note: capital S to match Python\n\n      if (!success) {\n        const errorMessage = `[${responseBody?.code || \"Unknown\"}] ${\n          responseBody?.message || \"Failed to delete session\"\n        }`;\n        logAPIResponseWithDetails(\n          \"DeleteSessionAsync\",\n          requestId,\n          false,\n          {},\n          JSON.stringify(responseBody, null, 2)\n        );\n        return {\n          requestId,\n          success: false,\n          errorMessage,\n        };\n      }\n\n      // Poll for session deletion status\n      logInfo(`🔄 Waiting for session ${this.sessionId} to be deleted...`);\n      const pollTimeout = 300000; // 5 minutes timeout\n      const pollInterval = 1000; // Poll every 1 second\n      const pollStartTime = Date.now();\n\n      while (true) {\n        // Check timeout\n        const elapsedTime = Date.now() - pollStartTime;\n        if (elapsedTime >= pollTimeout) {\n          const errorMessage = `Timeout waiting for session deletion after ${pollTimeout}ms`;\n          logWarn(`⏱️  ${errorMessage}`);\n          return {\n            requestId,\n            success: false,\n            errorMessage,\n          };\n        }\n\n        // Get session status\n        const sessionResult = await this.getStatus();\n\n        // Check if session is deleted (NotFound error)\n        if (!sessionResult.success) {\n          const errorCode = sessionResult.code || \"\";\n          const errorMessage = sessionResult.errorMessage || \"\";\n          const httpStatusCode = sessionResult.httpStatusCode || 0;\n\n          // Check for InvalidMcpSession.NotFound, 400 with \"not found\", or error_message containing \"not found\"\n          const isNotFound =\n            errorCode === \"InvalidMcpSession.NotFound\" ||\n            (httpStatusCode === 400 &&\n              (errorMessage.toLowerCase().includes(\"not found\") ||\n                errorMessage.includes(\"NotFound\") ||\n                errorCode.toLowerCase().includes(\"not found\"))) ||\n            errorMessage.toLowerCase().includes(\"not found\");\n\n          if (isNotFound) {\n            // Session is deleted\n            logInfo(\n              `✅ Session ${this.sessionId} successfully deleted (NotFound)`\n            );\n            break;\n          } else {\n            // Other error, continue polling\n            logDebug(`⚠️  Get session error (will retry): ${errorMessage}`);\n            // Continue to next poll iteration\n          }\n        }\n        // Check session status if we got valid data\n        else if (sessionResult.status) {\n          const status = sessionResult.status;\n          logDebug(`📊 Session status: ${status}`);\n          if (status === \"FINISH\") {\n            logInfo(`✅ Session ${this.sessionId} successfully deleted`);\n            break;\n          }\n        }\n\n        // Wait before next poll\n        await new Promise((resolve) => setTimeout(resolve, pollInterval));\n      }\n\n      // Log successful deletion\n      logAPIResponseWithDetails(\"DeleteSessionAsync\", requestId, true, {\n        sessionId: this.sessionId,\n      });\n\n      // Return success result with request ID\n      return {\n        requestId,\n        success: true,\n      };\n    } catch (error) {\n      logError(\"Error calling delete_session_async:\", error);\n      // In case of error, return failure result with error message (matching Python)\n      return {\n        requestId: \"\",\n        success: false,\n        errorMessage: `Failed to delete session ${this.sessionId}: ${error}`,\n      };\n    }\n  }\n\n  /**\n   * Validates labels parameter for label operations.\n   *\n   * @param labels - The labels to validate\n   * @returns null if validation passes, or OperationResult with error if validation fails\n   */\n  private validateLabels(\n    labels: Record<string, string>\n  ): OperationResult | null {\n    // Check if labels is null, undefined, or invalid type\n    if (!labels || typeof labels !== \"object\") {\n      return {\n        requestId: \"\",\n        success: false,\n        errorMessage:\n          \"Labels cannot be null, undefined, or invalid type. Please provide a valid labels object.\",\n      };\n    }\n\n    // Check if labels is an array or other non-plain object\n    if (Array.isArray(labels)) {\n      return {\n        requestId: \"\",\n        success: false,\n        errorMessage:\n          \"Labels cannot be an array. Please provide a valid labels object.\",\n      };\n    }\n\n    // Check if labels is a Date, RegExp, or other built-in object types\n    if (\n      labels instanceof Date ||\n      labels instanceof RegExp ||\n      labels instanceof Error ||\n      labels instanceof Map ||\n      labels instanceof Set ||\n      labels instanceof WeakMap ||\n      labels instanceof WeakSet ||\n      labels instanceof Promise\n    ) {\n      return {\n        requestId: \"\",\n        success: false,\n        errorMessage:\n          \"Labels must be a plain object. Built-in object types are not allowed.\",\n      };\n    }\n\n    // Check if labels object is empty\n    if (Object.keys(labels).length === 0) {\n      return {\n        requestId: \"\",\n        success: false,\n        errorMessage:\n          \"Labels cannot be empty. Please provide at least one label.\",\n      };\n    }\n\n    for (const [key, value] of Object.entries(labels)) {\n      // Check key validity\n      if (!key || key.trim() === \"\") {\n        return {\n          requestId: \"\",\n          success: false,\n          errorMessage: \"Label keys cannot be empty Please provide valid keys.\",\n        };\n      }\n\n      // Check value is not null or undefined\n      if (!value || value.trim() === \"\") {\n        return {\n          requestId: \"\",\n          success: false,\n          errorMessage:\n            \"Label values cannot be empty Please provide valid values.\",\n        };\n      }\n    }\n\n    // Validation passed\n    return null;\n  }\n\n  /**\n   * Sets the labels for this session.\n   *\n   * @param labels - The labels to set for the session.\n   * @returns OperationResult indicating success or failure with request ID\n   * @throws Error if the operation fails (matching Python SessionError)\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: 'your_api_key' });\n   * const result = await agentBay.create();\n   * if (result.success) {\n   *   const setResult = await result.session.setLabels({ project: 'demo', env: 'test' });\n   *   console.log('Labels set:', setResult.success);\n   *   await result.session.delete();\n   * }\n   * ```\n   */\n  async setLabels(labels: Record<string, string>): Promise<OperationResult> {\n    try {\n      // Validate labels using the extracted validation function\n      const validationResult = this.validateLabels(labels);\n      if (validationResult !== null) {\n        return validationResult;\n      }\n\n      // Convert labels to JSON string\n      const labelsJSON = JSON.stringify(labels);\n\n      const request = new SetLabelRequest({\n        authorization: `Bearer ${this.getAPIKey()}`,\n        sessionId: this.sessionId,\n        labels: labelsJSON,\n      });\n\n      const response = await this.getClient().setLabel(request);\n\n      // Extract request ID\n      const requestId = extractRequestId(response) || \"\";\n\n      return {\n        requestId,\n        success: true,\n      };\n    } catch (error) {\n      logError(\"Error calling set_label:\", error);\n      throw new Error(\n        `Failed to set labels for session ${this.sessionId}: ${error}`\n      );\n    }\n  }\n\n  /**\n   * Gets the labels for this session.\n   *\n   * @returns OperationResult containing the labels as data and request ID\n   * @throws Error if the operation fails (matching Python SessionError)\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: 'your_api_key' });\n   * const result = await agentBay.create();\n   * if (result.success) {\n   *   await result.session.setLabels({ project: 'demo', env: 'test' });\n   *   const getResult = await result.session.getLabels();\n   *   console.log('Labels:', JSON.stringify(getResult.data));\n   *   await result.session.delete();\n   * }\n   * ```\n   */\n  async getLabels(): Promise<OperationResult> {\n    try {\n      const request = new GetLabelRequest({\n        authorization: `Bearer ${this.getAPIKey()}`,\n        sessionId: this.sessionId,\n      });\n\n      const response = await this.getClient().getLabel(request);\n\n      // Extract request ID\n      const requestId = extractRequestId(response) || \"\";\n\n      // Extract labels from response (matching Python structure)\n      const responseBody = response?.body;\n      const data = responseBody?.data; // Capital D to match Python\n      const labelsJSON = data?.labels; // Capital L to match Python\n\n      let labels = {};\n      if (labelsJSON) {\n        labels = JSON.parse(labelsJSON);\n      }\n\n      return {\n        requestId,\n        success: true,\n        data: labels,\n      };\n    } catch (error) {\n      logError(\"Error calling get_label:\", error);\n      throw new Error(\n        `Failed to get labels for session ${this.sessionId}: ${error}`\n      );\n    }\n  }\n\n  /**\n   * Retrieves detailed information about the current session.\n   *\n   * @returns Promise resolving to OperationResult containing:\n   *          - success: Whether the operation succeeded (always true if no exception)\n   *          - data: SessionInfo object with the following fields:\n   *            - sessionId (string): The session identifier\n   *            - resourceUrl (string): URL for accessing the session\n   *            - appId (string): Application ID (for desktop sessions)\n   *            - authCode (string): Authentication code\n   *            - connectionProperties (string): Connection configuration\n   *            - resourceId (string): Resource identifier\n   *            - resourceType (string): Type of resource (e.g., \"Desktop\")\n   *            - ticket (string): Access ticket\n   *          - requestId: Unique identifier for this API request\n   *          - errorMessage: Error description if operation failed\n   *\n   * @throws Error if the API request fails or response is invalid.\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: 'your_api_key' });\n   * const result = await agentBay.create();\n   * if (result.success) {\n   *   const infoResult = await result.session.info();\n   *   console.log(`Session ID: ${infoResult.data.sessionId}`);\n   *   console.log(`Resource URL: ${infoResult.data.resourceUrl}`);\n   *   await result.session.delete();\n   * }\n   * ```\n   *\n   * @remarks\n   * **Behavior:**\n   * - This method calls the GetMcpResource API to retrieve session metadata\n   * - The returned SessionInfo contains:\n   *   - sessionId: The session identifier\n   *   - resourceUrl: URL for accessing the session\n   *   - Desktop-specific fields (appId, authCode, connectionProperties, etc.)\n   *     are populated from the DesktopInfo section of the API response\n   * - Session info is retrieved from the AgentBay API in real-time\n   * - The resourceUrl can be used for browser-based access\n   * - Desktop-specific fields (appId, authCode) are only populated for desktop sessions\n   * - This method does not modify the session state\n   *\n   * @see {@link delete}, {@link getLink}\n   */\n  async info(): Promise<OperationResult> {\n    try {\n      const request = new GetMcpResourceRequest({\n        authorization: `Bearer ${this.getAPIKey()}`,\n        sessionId: this.sessionId,\n      });\n\n      logAPICall(\"GetMcpResource\");\n      logDebug(`Request: SessionId=${this.sessionId}`);\n\n      const response = await this.getClient().getMcpResource(request);\n\n      // Extract request ID\n      const requestId = extractRequestId(response) || \"\";\n\n      // Check for API-level errors\n      if (response?.body?.success === false && response.body?.code) {\n        const errorMessage = `[${response.body.code}] ${\n          response.body.message || \"Unknown error\"\n        }`;\n        const fullResponse = response.body\n          ? JSON.stringify(response.body, null, 2)\n          : \"\";\n        logAPIResponseWithDetails(\n          \"GetMcpResource\",\n          requestId,\n          false,\n          undefined,\n          fullResponse\n        );\n        return {\n          requestId,\n          success: false,\n          errorMessage,\n        };\n      }\n\n      // Extract session info from response (matching Python structure)\n      const responseBody = response.body;\n      const data = responseBody?.data; // Capital D to match Python\n\n      const sessionInfo = new SessionInfoClass();\n\n      if (data?.sessionId) {\n        // Capital S and I to match Python\n        sessionInfo.sessionId = data.sessionId;\n      }\n\n      if (data?.resourceUrl) {\n        // Capital R and U to match Python\n        sessionInfo.resourceUrl = data.resourceUrl;\n      }\n\n      // Transfer DesktopInfo fields to SessionInfo (matching Python structure)\n      if (data?.desktopInfo) {\n        // Capital D and I to match Python\n        const desktopInfo = data.desktopInfo;\n        if (desktopInfo.appId) {\n          sessionInfo.appId = desktopInfo.appId;\n        }\n        if (desktopInfo.authCode) {\n          sessionInfo.authCode = desktopInfo.authCode;\n        }\n        if (desktopInfo.connectionProperties) {\n          sessionInfo.connectionProperties = desktopInfo.connectionProperties;\n        }\n        if (desktopInfo.resourceId) {\n          sessionInfo.resourceId = desktopInfo.resourceId;\n        }\n        if (desktopInfo.resourceType) {\n          sessionInfo.resourceType = desktopInfo.resourceType;\n        }\n        if (desktopInfo.ticket) {\n          sessionInfo.ticket = desktopInfo.ticket;\n        }\n      }\n\n      // Log API response with key fields\n      const keyFields: Record<string, any> = {\n        session_id: this.sessionId,\n      };\n      if (sessionInfo.resourceUrl) {\n        keyFields.resource_url = sessionInfo.resourceUrl;\n      }\n      if (sessionInfo.appId) {\n        keyFields.app_id = sessionInfo.appId;\n      }\n      const fullResponse = responseBody\n        ? JSON.stringify(responseBody, null, 2)\n        : \"\";\n      logAPIResponseWithDetails(\n        \"GetMcpResource\",\n        requestId,\n        true,\n        keyFields,\n        fullResponse\n      );\n\n      return {\n        requestId,\n        success: true,\n        data: sessionInfo,\n      };\n    } catch (error: any) {\n      // Check if this is an expected business error (e.g., session not found)\n      const errorStr = String(error);\n      const errorCode = error?.data?.Code || error?.code || \"\";\n\n      if (\n        errorCode === \"InvalidMcpSession.NotFound\" ||\n        errorStr.includes(\"NotFound\")\n      ) {\n        // This is an expected error - session doesn't exist\n        // Use info level logging without stack trace, but with red color for visibility\n        logInfoWithColor(`Session not found: ${this.sessionId}`);\n        logDebug(`GetMcpResource error details: ${errorStr}`);\n        return {\n          requestId: \"\",\n          success: false,\n          errorMessage: `Session ${this.sessionId} not found`,\n        };\n      } else {\n        // This is an unexpected error - log with full error\n        logError(\n          `❌ Failed to get session info for session ${this.sessionId}`,\n          error\n        );\n        throw new Error(\n          `Failed to get session info for session ${this.sessionId}: ${error}`\n        );\n      }\n    }\n  }\n\n  /**\n   * Retrieves an access link for the session.\n   *\n   * @param protocolType - Protocol type for the link (optional, reserved for future use)\n   * @param port - Specific port number to access (default open range: [30100, 30199]; other ports require whitelist approval via agentbay_dev@alibabacloud.com).\n   *               If not specified, returns the default session link.\n   *\n   * @returns Promise resolving to OperationResult containing:\n   *          - success: Whether the operation succeeded\n   *          - data: String URL for accessing the session\n   *          - requestId: Unique identifier for this API request\n   *          - errorMessage: Error description if operation failed\n   *\n   * @throws Error if the API call fails or port is out of valid range.\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: 'your_api_key' });\n   * const result = await agentBay.create();\n   * if (result.success) {\n   *   const linkResult = await result.session.getLink();\n   *   console.log(`Session link: ${linkResult.data}`);\n   *   await result.session.delete();\n   * }\n   * ```\n   *\n   * @remarks\n   * **Behavior:**\n   * - Without port: Returns the default session access URL\n   * - With port: Returns URL for accessing specific port-mapped service\n   * - Default open port range: [30100, 30199]; other ports require whitelist approval\n   * - For ADB connections, use `session.mobile.getAdbUrl()` with appropriate ADB public key\n   *\n   * **Best Practices:**\n   * - Use default link for general session access\n   * - Use port-specific links when you've started services on specific ports\n   * - Validate port range before calling to avoid errors\n   *\n   * @see {@link info}\n   */\n  async getLink(\n    protocolType?: string,\n    port?: number,\n    options?: string\n  ): Promise<OperationResult> {\n    try {\n      // Log API call\n      let requestParams = `SessionId=${this.getSessionId()}, ProtocolType=${\n        protocolType || \"default\"\n      }, Port=${port || \"default\"}`;\n      if (options) {\n        requestParams += \", Options=provided\";\n      }\n      logAPICall(\"GetLink\", requestParams);\n\n      const request = new GetLinkRequest({\n        authorization: `Bearer ${this.getAPIKey()}`,\n        sessionId: this.getSessionId(),\n        protocolType,\n        port,\n        option: options,\n      });\n\n      const response = await this.agentBay.getClient().getLink(request);\n\n      // Extract request ID\n      const requestId = extractRequestId(response) || \"\";\n\n      const responseBody = response.body;\n\n      if (typeof responseBody !== \"object\") {\n        throw new Error(\n          \"Invalid response format: expected a dictionary from response body\"\n        );\n      }\n\n      let data = responseBody.data || {}; // Capital D to match Python\n      logDebug(`Data: ${JSON.stringify(data)}`);\n\n      if (typeof data !== \"object\") {\n        try {\n          data = typeof data === \"string\" ? JSON.parse(data) : {};\n        } catch (jsonError) {\n          data = {};\n        }\n      }\n\n      const url = (data as any).Url || (data as any).url;\n\n      // Log API response\n      const keyFields: Record<string, any> = {};\n      if (url) {\n        keyFields.url = url;\n      }\n      logAPIResponseWithDetails(\"GetLink\", requestId, true, keyFields);\n\n      return {\n        requestId,\n        success: true,\n        data: url,\n      };\n    } catch (error) {\n      if (\n        error instanceof Error &&\n        error.message.includes(\"Invalid response format\")\n      ) {\n        throw error;\n      }\n      throw new Error(`Failed to get link: ${error}`);\n    }\n  }\n\n  /**\n   * Asynchronously get a link associated with the current session.\n   *\n   * @param protocolType - Optional protocol type to use for the link\n   * @param port - Optional port to use for the link (default open range: [30100, 30199]; other ports require whitelist approval)\n   * @returns OperationResult containing the link as data and request ID\n   * @throws Error if the operation fails (matching Python SessionError)\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: 'your_api_key' });\n   * const result = await agentBay.create();\n   * if (result.success) {\n   *   const linkResult = await result.session.getLinkAsync(undefined, 30150);\n   *   console.log(`Port link: ${linkResult.data}`);\n   *   await result.session.delete();\n   * }\n   * ```\n   */\n  async getLinkAsync(\n    protocolType?: string,\n    port?: number,\n    options?: string\n  ): Promise<OperationResult> {\n    try {\n      // Log API call\n      let requestParams = `SessionId=${this.getSessionId()}, ProtocolType=${\n        protocolType || \"default\"\n      }, Port=${port || \"default\"}`;\n      if (options) {\n        requestParams += \", Options=provided\";\n      }\n      logAPICall(\"GetLink\", requestParams);\n\n      const request = new GetLinkRequest({\n        authorization: `Bearer ${this.getAPIKey()}`,\n        sessionId: this.getSessionId(),\n        protocolType,\n        port,\n        option: options,\n      });\n\n      // Note: In TypeScript, async is the default, but keeping this method for API compatibility\n      const response = await this.agentBay.getClient().getLink(request);\n\n      // Extract request ID\n      const requestId = extractRequestId(response) || \"\";\n\n      const responseBody = response?.body;\n\n      if (typeof responseBody !== \"object\") {\n        throw new Error(\n          \"Invalid response format: expected a dictionary from response body\"\n        );\n      }\n\n      let data = responseBody?.data || {}; // Capital D to match Python\n      logDebug(`Data: ${JSON.stringify(data)}`);\n\n      if (typeof data !== \"object\") {\n        try {\n          data = typeof data === \"string\" ? JSON.parse(data) : {};\n        } catch (jsonError) {\n          data = {};\n        }\n      }\n\n      const url = (data as any).Url || (data as any).url;\n\n      // Log API response\n      const keyFields: Record<string, any> = {};\n      if (url) {\n        keyFields.url = url;\n      }\n      logAPIResponseWithDetails(\"GetLink\", requestId, true, keyFields);\n\n      return {\n        requestId,\n        success: true,\n        data: url,\n      };\n    } catch (error) {\n      if (\n        error instanceof Error &&\n        error.message.includes(\"Invalid response format\")\n      ) {\n        throw error;\n      }\n      throw new Error(`Failed to get link asynchronously: ${error}`);\n    }\n  }\n\n  /**\n   * List MCP tools available for this session.\n   *\n   * @param imageId Optional image ID, defaults to session's imageId or \"linux_latest\"\n   * @returns McpToolsResult containing tools list and request ID\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: 'your_api_key' });\n   * const result = await agentBay.create();\n   * if (result.success) {\n   *   const toolsResult = await result.session.listMcpTools();\n   *   console.log(`Found ${toolsResult.tools.length} MCP tools`);\n   *   await result.session.delete();\n   * }\n   * ```\n   */\n  async listMcpTools(imageId?: string): Promise<McpToolsResult> {\n    // Use provided imageId, session's imageId, or default\n    if (!imageId) {\n      imageId = (this as any).imageId || \"linux_latest\";\n    }\n\n    const request = new ListMcpToolsRequest({\n      authorization: `Bearer ${this.getAPIKey()}`,\n      imageId: imageId,\n    });\n\n    logAPICall(\"ListMcpTools\");\n    logDebug(`Request: ImageId=${imageId}`);\n\n    const response = await this.getClient().listMcpTools(request);\n\n    // Extract request ID\n    const requestId = extractRequestId(response) || \"\";\n\n    // Check for API-level errors\n    if (response?.body?.success === false && response.body?.code) {\n      const errorMessage = `[${response.body.code}] ${\n        response.body.message || \"Unknown error\"\n      }`;\n      const fullResponse = response.body\n        ? JSON.stringify(response.body, null, 2)\n        : \"\";\n      logAPIResponseWithDetails(\n        \"ListMcpTools\",\n        requestId,\n        false,\n        undefined,\n        fullResponse\n      );\n      return {\n        requestId,\n        success: false,\n        tools: [],\n        errorMessage,\n      };\n    }\n\n    // Parse the response data\n    const tools: McpTool[] = [];\n    if (response && response.body && response.body.data) {\n      try {\n        const toolsData = JSON.parse(response.body.data as string);\n        for (const toolData of toolsData) {\n          const tool: McpTool = {\n            name: toolData.name || \"\",\n            description: toolData.description || \"\",\n            inputSchema: toolData.inputSchema || {},\n            server: toolData.server || \"\",\n            tool: toolData.tool || \"\",\n          };\n          tools.push(tool);\n        }\n      } catch (error) {\n        logError(`Error unmarshaling tools data: ${error}`);\n      }\n    }\n\n    // Do not store MCP tools in Session.\n\n    // Log API response with key fields\n    const keyFields: Record<string, any> = {\n      image_id: imageId,\n      tool_count: tools.length,\n    };\n    const fullResponse = response.body\n      ? JSON.stringify(response.body, null, 2)\n      : \"\";\n    logAPIResponseWithDetails(\n      \"ListMcpTools\",\n      requestId,\n      true,\n      keyFields,\n      fullResponse\n    );\n\n    return {\n      requestId,\n      success: true,\n      tools,\n    };\n  }\n\n  getMcpServerForTool(toolName: string): string | null {\n    for (const tool of this.mcpTools || []) {\n      if (tool && tool.name === toolName) {\n        return tool.server || null;\n      }\n    }\n    return null;\n  }\n\n  /**\n   * Call an MCP tool and return the result in a format compatible with Agent.\n   *\n   * @param toolName - Name of the MCP tool to call\n   * @param args - Arguments to pass to the tool\n   * @param autoGenSession - Whether to automatically generate session if not exists (default: false)\n   * @returns McpToolResult containing the response data\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: 'your_api_key' });\n   * const result = await agentBay.create();\n   * if (result.success) {\n   *   const shellResult = await result.session.callMcpTool('shell', { command: \"echo 'Hello'\" });\n   *   console.log(`Output: ${shellResult.data}`);\n   *   await result.session.delete();\n   * }\n   * ```\n   *\n   * @remarks\n   * For press_keys tool, key names are automatically normalized to correct case format.\n   * This improves case compatibility (e.g., \"CTRL\" -> \"Ctrl\", \"tab\" -> \"Tab\").\n   */\n  async callMcpTool(\n    toolName: string,\n    args: any,\n    autoGenSession = false\n  ): Promise<import(\"./agent/agent\").McpToolResult> {\n    try {\n      // Normalize press_keys arguments for better case compatibility\n      if (toolName === \"press_keys\" && args && Array.isArray(args.keys)) {\n        const { normalizeKeys } = await import(\"./key-normalizer\");\n        args = { ...args }; // Don't modify the original args\n        args.keys = normalizeKeys(args.keys);\n        logDebug(`Normalized press_keys arguments: ${JSON.stringify(args)}`);\n      }\n\n      // Server name is optional for API-based tool calls.\n      // Some environments do not return ToolList in CreateSession, and the backend\n      // can resolve the server by tool name.\n      const serverName = this.getMcpServerForTool(toolName) || \"\";\n\n      const argsJSON = JSON.stringify(args);\n\n      // LinkUrl route requires explicit server name. If it's not available,\n      // fall back to API-based call to let backend resolve the server.\n      if (this.getLinkUrl() && this.getToken() && serverName) {\n        return await this.callMcpToolLinkUrl(toolName, args, serverName);\n      }\n\n      // Use traditional API call\n      const callToolRequest = new CallMcpToolRequest({\n        authorization: `Bearer ${this.getAPIKey()}`,\n        sessionId: this.getSessionId(),\n        name: toolName,\n        args: argsJSON,\n        autoGenSession: autoGenSession,\n        server: serverName,\n      });\n\n      const response = await this.getClient().callMcpTool(callToolRequest);\n\n      if (!response.body?.data) {\n        return {\n          success: false,\n          data: \"\",\n          errorMessage: \"Invalid response data format\",\n          requestId: extractRequestId(response) || \"\",\n        };\n      }\n\n      // Check for API-level errors before parsing Data\n      if (response.body.success === false && response.body.code) {\n        const errorMessage = `[${response.body.code}] ${\n          response.body.message || \"Unknown error\"\n        }`;\n        return {\n          success: false,\n          data: \"\",\n          errorMessage,\n          requestId: extractRequestId(response) || \"\",\n        };\n      }\n\n      const data = response.body.data as Record<string, any>;\n      const reqId = extractRequestId(response) || \"\";\n      if (reqId) {\n        setRequestId(reqId);\n      }\n\n      // For run_code tool, return raw data to let Code service handle parsing\n      if (toolName === \"run_code\") {\n        let dataStr = \"\";\n\n        // Check if data has content array (standard MCP tool response)\n        // The backend might wrap the actual result JSON inside content[0].text\n        if (\n          data &&\n          Array.isArray(data.content) &&\n          data.content.length > 0 &&\n          data.content[0].text\n        ) {\n          dataStr = data.content[0].text;\n        } else {\n          // Fallback: use the whole data object/string\n          dataStr =\n            typeof response.body.data === \"string\"\n              ? response.body.data\n              : JSON.stringify(response.body.data);\n        }\n\n        logCodeExecutionOutput(reqId, dataStr);\n\n        // If the backend marked it as an error, we should reflect that\n        const isError = data.isError === true;\n\n        return {\n          success: !isError,\n          data: dataStr,\n          errorMessage: isError ? dataStr : \"\",\n          requestId: reqId,\n        };\n      }\n\n      // Check if there's an error in the response\n      if (data.isError) {\n        const errorContent = data.content || [];\n        const errorMessage = errorContent\n          .map((item: any) => item.text || \"Unknown error\")\n          .join(\"; \");\n\n        return {\n          success: false,\n          data: \"\",\n          errorMessage,\n          requestId: reqId,\n        };\n      }\n\n      // Extract text content from content array\n      const content = data.content || [];\n      let textContent = \"\";\n      if (content.length > 0) {\n        const c0 = content[0] || {};\n        if (typeof c0.text === \"string\" && c0.text) {\n          textContent = c0.text;\n        } else if (typeof c0.blob === \"string\" && c0.blob) {\n          textContent = c0.blob;\n        } else if (typeof c0.data === \"string\" && c0.data) {\n          textContent = c0.data;\n        }\n      }\n\n      return {\n        success: true,\n        data: textContent || JSON.stringify(data),\n        errorMessage: \"\",\n        requestId: reqId,\n      };\n    } catch (error) {\n      return {\n        success: false,\n        data: \"\",\n        errorMessage: error instanceof Error ? error.message : String(error),\n        requestId: \"\",\n      };\n    }\n  }\n\n  private async callMcpToolLinkUrl(\n    toolName: string,\n    args: any,\n    serverName: string\n  ): Promise<import(\"./agent/agent\").McpToolResult> {\n    if (!serverName) {\n      return {\n        success: false,\n        data: \"\",\n        errorMessage: `Server name is required for LinkUrl tool call: ${toolName}`,\n        requestId: \"\",\n      };\n    }\n\n    const linkUrl = this.getLinkUrl();\n    const token = this.getToken();\n    if (!linkUrl || !token) {\n      return {\n        success: false,\n        data: \"\",\n        errorMessage: \"LinkUrl/token not available\",\n        requestId: \"\",\n      };\n    }\n\n    const requestId = `link-${Date.now()}-${Math.floor(\n      Math.random() * 1_000_000_000\n    )\n      .toString()\n      .padStart(9, \"0\")}`;\n\n    logAPICall(\n      \"CallMcpTool(LinkUrl)\",\n      `Tool=${toolName}, ArgsLength=${\n        JSON.stringify(args).length\n      }, RequestId=${requestId}`\n    );\n\n    const url = `${linkUrl.replace(/\\/+$/, \"\")}/callTool`;\n    const payload = {\n      args,\n      server: serverName,\n      requestId,\n      tool: toolName,\n      token,\n    };\n\n    const resp = await fetchCompat(\n      url,\n      {\n        method: \"POST\",\n        headers: {\n          \"Content-Type\": \"application/json\",\n          \"X-Access-Token\": token,\n        },\n        body: JSON.stringify(payload),\n      },\n      900000\n    ); // 900 seconds timeout\n\n    if (!resp.ok) {\n      const bodyText = await resp.text().catch(() => \"\");\n      logAPIResponseWithDetails(\n        \"CallMcpTool(LinkUrl) Response\",\n        requestId,\n        false,\n        { http_status: resp.status, tool_name: toolName },\n        bodyText\n      );\n      return {\n        success: false,\n        data: \"\",\n        errorMessage: `HTTP request failed with code: ${resp.status}`,\n        requestId,\n      };\n    }\n\n    const outer = await resp.json();\n    const dataField = outer?.data;\n    let parsedData: any = dataField;\n    if (typeof dataField === \"string\") {\n      parsedData = JSON.parse(dataField);\n    }\n\n    const resultField = parsedData?.result;\n    const isError = resultField?.isError === true;\n    const content = Array.isArray(resultField?.content)\n      ? resultField.content\n      : [];\n    const first = content[0] ?? {};\n    const textContent =\n      typeof first === \"string\"\n        ? first\n        : (first as any).text ??\n          (first as any).blob ??\n          (first as any).data ??\n          \"\";\n\n    logAPIResponseWithDetails(\n      \"CallMcpTool(LinkUrl) Response\",\n      requestId,\n      !isError,\n      {\n        tool_name: toolName,\n        server: serverName,\n        is_error: isError,\n        data_len: String(textContent ?? \"\").length,\n      },\n      isError ? String(textContent ?? \"\") : \"\"\n    );\n\n    if (toolName === \"run_code\") {\n      const dataStr =\n        typeof textContent === \"string\"\n          ? textContent\n          : JSON.stringify(textContent);\n      logCodeExecutionOutput(requestId, dataStr);\n      return {\n        success: !isError,\n        data: dataStr,\n        errorMessage: isError ? dataStr : \"\",\n        requestId,\n      };\n    }\n\n    return {\n      success: !isError,\n      data: String(textContent ?? \"\"),\n      errorMessage: isError ? String(textContent ?? \"\") : \"\",\n      requestId,\n    };\n  }\n\n  /**\n   * Get runtime metrics for this session.\n   *\n   * The underlying service returns a JSON string. This method parses it and\n   * returns a structured result.\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: \"your_api_key\" });\n   * const create = await agentBay.create({ imageId: \"linux_latest\" });\n   * if (create.success && create.session) {\n   *   const metrics = await create.session.getMetrics();\n   *   console.log(metrics.data);\n   *   await create.session.delete();\n   * }\n   * ```\n   */\n  async getMetrics(): Promise<SessionMetricsResult> {\n    const toolResult = await this.callMcpTool(\"get_metrics\", {}, false);\n    const requestId = toolResult.requestId || \"\";\n\n    if (!toolResult.success) {\n      return {\n        requestId,\n        success: false,\n        data: undefined,\n        raw: undefined,\n        errorMessage: toolResult.errorMessage || \"\",\n      };\n    }\n\n    try {\n      const raw =\n        typeof toolResult.data === \"string\"\n          ? JSON.parse(toolResult.data)\n          : toolResult.data;\n\n      if (!raw || typeof raw !== \"object\" || Array.isArray(raw)) {\n        throw new Error(\"get_metrics returned non-object JSON\");\n      }\n\n      const metrics: SessionMetrics = {\n        cpuCount: Number((raw as any).cpu_count ?? 0),\n        cpuUsedPct: Number((raw as any).cpu_used_pct ?? 0),\n        diskTotal: Number((raw as any).disk_total ?? 0),\n        diskUsed: Number((raw as any).disk_used ?? 0),\n        memTotal: Number((raw as any).mem_total ?? 0),\n        memUsed: Number((raw as any).mem_used ?? 0),\n        rxRateKbytePerS: Number(\n          (raw as any).rx_rate_kbyte_per_s ??\n            (raw as any).rx_rate_kbps ??\n            (raw as any).rx_rate_KBps ??\n            0\n        ),\n        txRateKbytePerS: Number(\n          (raw as any).tx_rate_kbyte_per_s ??\n            (raw as any).tx_rate_kbps ??\n            (raw as any).tx_rate_KBps ??\n            0\n        ),\n        rxUsedKbyte: Number(\n          (raw as any).rx_used_kbyte ??\n            (raw as any).rx_used_kb ??\n            (raw as any).rx_used_KB ??\n            0\n        ),\n        txUsedKbyte: Number(\n          (raw as any).tx_used_kbyte ??\n            (raw as any).tx_used_kb ??\n            (raw as any).tx_used_KB ??\n            0\n        ),\n        timestamp: String((raw as any).timestamp ?? \"\"),\n      };\n\n      return {\n        requestId,\n        success: true,\n        data: metrics,\n        raw: raw as Record<string, any>,\n        errorMessage: \"\",\n      };\n    } catch (err: any) {\n      return {\n        requestId,\n        success: false,\n        data: undefined,\n        raw: undefined,\n        errorMessage: `Failed to parse get_metrics response: ${\n          err?.message || String(err)\n        }`,\n      };\n    }\n  }\n\n  /**\n   * Asynchronously pause this session (beta), putting it into a dormant state.\n   *\n   * **Note**: This feature is currently in whitelist-only access.\n   * Contact agentbay_dev@alibabacloud.com to request access.\n   *\n   * This method calls the PauseSessionAsync API to initiate the pause operation and then polls\n   * the GetSession API to check the session status until it becomes PAUSED or until timeout is reached.\n   * During the paused state, resource usage and costs are reduced while session state is preserved.\n   *\n   * @param timeout - Timeout in seconds to wait for the session to pause. Defaults to 600 seconds.\n   * @param pollInterval - Interval in seconds between status polls. Defaults to 2.0 seconds.\n   *\n   * @returns Promise resolving to SessionPauseResult containing:\n   *          - success: Whether the pause operation succeeded\n   *          - requestId: Unique identifier for this API request\n   *          - status: Final session status (should be \"PAUSED\" if successful)\n   *          - errorMessage: Error description if pause failed\n   *\n   * @throws Error if the API call fails or network issues occur.\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: 'your_api_key' });\n   * const result = await agentBay.create();\n   * if (result.success) {\n   *   const pauseResult = await result.session.betaPauseAsync();\n   *   if (pauseResult.success) {\n   *     console.log('Session paused successfully');\n   *   }\n   * }\n   * ```\n   *\n   * @remarks\n   * **Behavior:**\n   * - Initiates pause operation through PauseSessionAsync API\n   * - Polls session status until PAUSED state or timeout\n   * - Session state transitions: RUNNING -> PAUSING -> PAUSED\n   * - All session state is preserved during pause\n   *\n   * **Important Notes:**\n   * - Paused sessions cannot perform operations (deletion, task execution, etc.)\n   * - Use {@link betaResumeAsync} to restore the session to RUNNING state\n   * - During pause, both resource usage and costs are lower\n   * - If timeout is exceeded, returns with success=false\n   *\n   * @see {@link betaResumeAsync}\n   */\n  async betaPauseAsync(\n    timeout = 600,\n    pollInterval = 2.0\n  ): Promise<SessionPauseResult> {\n    try {\n      const request = new $_client.PauseSessionAsyncRequest({\n        authorization: `Bearer ${this.getAPIKey()}`,\n        sessionId: this.sessionId,\n      });\n\n      logAPICall(\"PauseSessionAsync\", `SessionId=${this.sessionId}`);\n\n      const response = await this.getClient().pauseSessionAsync(request);\n\n      // Extract request ID\n      const requestId = extractRequestId(response) || \"\";\n      setRequestId(requestId);\n\n      // Check for API-level errors\n      const responseMap = response.to_map ? response.to_map() : response;\n      if (!responseMap) {\n        return {\n          requestId: requestId || \"\",\n          success: false,\n          errorMessage: \"Invalid response format\",\n        };\n      }\n\n      const body = responseMap.body;\n      if (!body) {\n        return {\n          requestId: requestId || \"\",\n          success: false,\n          errorMessage: \"Invalid response body\",\n        };\n      }\n\n      // Extract fields from response body\n      const success = body.success !== false;\n      const code = body.code || \"\";\n      const message = body.message || \"\";\n      const httpStatusCode = body.httpStatusCode || 0;\n\n      // Build error message if not successful\n      if (!success) {\n        const errorMessage = `[${code}] ${message}` || \"Unknown error\";\n        logError(\"PauseSessionAsync\", errorMessage);\n        return {\n          requestId: requestId || \"\",\n          success: false,\n          errorMessage,\n          code,\n          message,\n          httpStatusCode,\n        };\n      }\n\n      logInfo(\n        `PauseSessionAsync`,\n        `Session ${this.sessionId} pause initiated successfully`\n      );\n\n      // Poll for session status until PAUSED or timeout\n      const startTime = Date.now();\n      const maxAttempts = Math.floor(timeout / pollInterval);\n      let attempt = 0;\n\n      while (attempt < maxAttempts) {\n        // Get session status\n        const getResult = await this.agentBay._getSession(this.sessionId);\n        if (!getResult.success) {\n          logError(`Failed to get session status: ${getResult.errorMessage}`);\n          return {\n            requestId: getResult.requestId || \"\",\n            success: false,\n            errorMessage: `Failed to get session status: ${getResult.errorMessage}`,\n          };\n        }\n\n        // Check session status\n        if (getResult.data) {\n          const status = getResult.data.status || \"UNKNOWN\";\n          logDebug(\n            `Session status: ${status} (attempt ${attempt + 1}/${maxAttempts})`\n          );\n\n          // Check if session is paused\n          if (status === \"PAUSED\") {\n            const elapsed = Date.now() - startTime;\n            logInfo(`Session paused successfully in ${elapsed}ms`);\n            return {\n              requestId: getResult.requestId || \"\",\n              success: true,\n              status,\n            };\n          } else if (status === \"PAUSING\") {\n            // Normal transitioning state, continue polling\n          } else {\n            // Any other status is unexpected - pause API succeeded but session is not pausing/paused\n            const elapsed = Date.now() - startTime;\n            const errorMessage = `Session pause failed: unexpected state '${status}' after ${elapsed}ms`;\n            logError(errorMessage);\n            return {\n              requestId: getResult.requestId || \"\",\n              success: false,\n              errorMessage,\n              status,\n            };\n          }\n        }\n\n        // Wait before next query (using setTimeout to avoid blocking)\n        // Only wait if we're not at the last attempt\n        attempt++;\n        if (attempt < maxAttempts) {\n          await new Promise((resolve) =>\n            setTimeout(resolve, pollInterval * 1000)\n          );\n        }\n      }\n\n      // Timeout\n      const elapsed = Date.now() - startTime;\n      const errorMsg = `Session pause timed out after ${elapsed}ms`;\n      logError(errorMsg);\n      return {\n        requestId: \"\",\n        success: false,\n        errorMessage: errorMsg,\n      };\n    } catch (error) {\n      logError(\"PauseSessionAsync\", error);\n      return {\n        requestId: \"\",\n        success: false,\n        errorMessage: `Unexpected error pausing session: ${error}`,\n      };\n    }\n  }\n\n  /**\n   * Asynchronously resume this session (beta) from a paused state.\n   *\n   * This method calls the ResumeSessionAsync API to initiate the resume operation and then polls\n   * the GetSession API to check the session status until it becomes RUNNING or until timeout is reached.\n   * After resuming, the session restores full functionality and can perform all operations normally.\n   *\n   * @param timeout - Timeout in seconds to wait for the session to resume. Defaults to 600 seconds.\n   * @param pollInterval - Interval in seconds between status polls. Defaults to 2.0 seconds.\n   *\n   * @returns Promise resolving to SessionResumeResult containing:\n   *          - success: Whether the resume operation succeeded\n   *          - requestId: Unique identifier for this API request\n   *          - status: Final session status (should be \"RUNNING\" if successful)\n   *          - errorMessage: Error description if resume failed\n   *\n   * @throws Error if the API call fails or network issues occur.\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: 'your_api_key' });\n   * const result = await agentBay.get('paused_session_id');\n   * if (result.success) {\n   *   const resumeResult = await result.session.betaResumeAsync();\n   *   if (resumeResult.success) {\n   *     console.log('Session resumed successfully');\n   *   }\n   * }\n   * ```\n   *\n   * @remarks\n   * **Behavior:**\n   * - Initiates resume operation through ResumeSessionAsync API\n   * - Polls session status until RUNNING state or timeout\n   * - Session state transitions: PAUSED -> RESUMING -> RUNNING\n   * - All previous session state is restored during resume\n   *\n   * **Important Notes:**\n   * - Only sessions in PAUSED state can be resumed\n   * - After resume, the session can perform all operations normally\n   * - Use {@link betaPauseAsync} to put a session into PAUSED state\n   * - If timeout is exceeded, returns with success=false\n   *\n   * @see {@link betaPauseAsync}\n   */\n  async betaResumeAsync(\n    timeout = 600,\n    pollInterval = 2.0\n  ): Promise<SessionResumeResult> {\n    try {\n      const request = new $_client.ResumeSessionAsyncRequest({\n        authorization: `Bearer ${this.getAPIKey()}`,\n        sessionId: this.sessionId,\n      });\n\n      logAPICall(\"ResumeSessionAsync\", `SessionId=${this.sessionId}`);\n\n      const response = await this.getClient().resumeSessionAsync(request);\n\n      // Extract request ID\n      const requestId = extractRequestId(response) || \"\";\n      setRequestId(requestId);\n\n      // Check for API-level errors\n      const responseMap = response.to_map ? response.to_map() : response;\n      if (!responseMap) {\n        return {\n          requestId: requestId || \"\",\n          success: false,\n          errorMessage: \"Invalid response format\",\n        };\n      }\n\n      const body = responseMap.body;\n      if (!body) {\n        return {\n          requestId: requestId || \"\",\n          success: false,\n          errorMessage: \"Invalid response body\",\n        };\n      }\n\n      // Extract fields from response body\n      const success = body.success !== false;\n      const code = body.code || \"\";\n      const message = body.message || \"\";\n      const httpStatusCode = body.httpStatusCode || 0;\n\n      // Build error message if not successful\n      if (!success) {\n        const errorMessage = `[${code}] ${message}` || \"Unknown error\";\n        logError(\"ResumeSessionAsync\", errorMessage);\n        return {\n          requestId: requestId || \"\",\n          success: false,\n          errorMessage,\n          code,\n          message,\n          httpStatusCode,\n        };\n      }\n\n      logInfo(\n        `ResumeSessionAsync`,\n        `Session ${this.sessionId} resume initiated successfully`\n      );\n\n      // Poll for session status until RUNNING or timeout\n      const startTime = Date.now();\n      const maxAttempts = Math.floor(timeout / pollInterval);\n      let attempt = 0;\n\n      while (attempt < maxAttempts) {\n        // Get session status\n        const getResult = await this.agentBay._getSession(this.sessionId);\n        if (!getResult.success) {\n          logError(`Failed to get session status: ${getResult.errorMessage}`);\n          return {\n            requestId: getResult.requestId || \"\",\n            success: false,\n            errorMessage: `Failed to get session status: ${getResult.errorMessage}`,\n          };\n        }\n\n        // Check session status\n        if (getResult.data) {\n          const status = getResult.data.status || \"UNKNOWN\";\n          logDebug(\n            `Session status: ${status} (attempt ${attempt + 1}/${maxAttempts})`\n          );\n\n          // Check if session is running\n          if (status === \"RUNNING\") {\n            const elapsed = Date.now() - startTime;\n            logInfo(`Session resumed successfully in ${elapsed}ms`);\n            return {\n              requestId: getResult.requestId || \"\",\n              success: true,\n              status,\n            };\n          } else if (status === \"RESUMING\") {\n            // Normal transitioning state, continue polling\n          } else {\n            // Any other status is unexpected - resume API succeeded but session is not resuming/running\n            const elapsed = Date.now() - startTime;\n            const errorMessage = `Session resume failed: unexpected state '${status}' after ${elapsed}ms`;\n            logError(errorMessage);\n            return {\n              requestId: getResult.requestId || \"\",\n              success: false,\n              errorMessage,\n              status,\n            };\n          }\n        }\n\n        // Wait before next query (using setTimeout to avoid blocking)\n        // Only wait if we're not at the last attempt\n        attempt++;\n        if (attempt < maxAttempts) {\n          await new Promise((resolve) =>\n            setTimeout(resolve, pollInterval * 1000)\n          );\n        }\n      }\n\n      // Timeout\n      const elapsed = Date.now() - startTime;\n      const errorMsg = `Session resume timed out after ${elapsed}ms`;\n      logError(errorMsg);\n      return {\n        requestId: \"\",\n        success: false,\n        errorMessage: errorMsg,\n      };\n    } catch (error) {\n      logError(\"ResumeSessionAsync\", error);\n      return {\n        requestId: \"\",\n        success: false,\n        errorMessage: `Unexpected error resuming session: ${error}`,\n      };\n    }\n  }\n}\n","import { BrowserOption } from \"src/browser\";\nimport { ApiResponse } from \"../types/api-response\";\nimport { logWarn, logDebug, logInfo } from \"../utils/logger\";\nimport { z, ZodTypeAny } from \"zod\";\nimport { zodToJsonSchema } from \"zod-to-json-schema\";\n\nconst DefaultSchema = z.object({});\n\n/**\n * Result of task execution.\n */\nexport interface ExecutionResult extends ApiResponse {\n  taskId: string;\n  taskStatus: string;\n  taskResult: string;\n}\n\n/**\n * Result of query operations.\n */\nexport interface QueryResult extends ApiResponse {\n  taskId: string;\n  taskStatus: string;\n  taskAction: string;\n  taskProduct: string;\n  stream?: Array<{\n    content?: string;\n    reasoning?: string;\n    timestamp_ms?: number;\n  }>;\n  error?: string;\n}\n\n/**\n * Represents a streaming event from an Agent execution.\n *\n * Event types map directly to LLM output field names:\n * - \"reasoning\": from LLM reasoning_content (model's internal reasoning/thinking)\n * - \"content\": from LLM content (model's text output, intermediate analysis or final answer)\n * - \"tool_call\": from LLM tool_calls (tool invocation request)\n * - \"tool_result\": tool execution result\n * - \"error\": execution error\n *\n * The `result` field in tool_result events carries an agent-defined structure\n * that the SDK passes through without parsing. Typical fields include\n * `isError` (boolean), `output` (string), and optionally `screenshot`\n * (base64 string). The final task outcome is delivered via the\n * `ExecutionResult` return value of `executeTaskAndWait`.\n */\nexport interface AgentEvent {\n  type: string;\n  seq: number;\n  round: number;\n  content?: string;\n  toolCallId?: string;\n  toolName?: string;\n  args?: Record<string, any>;\n  /** Prompt text for call_for_user tool_call events. */\n  prompt?: string;\n  /** Agent-defined tool execution result (e.g. {isError, output, screenshot}). Not parsed by SDK. */\n  result?: Record<string, any>;\n  error?: Record<string, any>;\n}\n\nexport type AgentEventCallback = (event: AgentEvent) => void;\n\n/**\n * Result of an MCP tool call.\n */\nexport interface McpToolResult {\n  success: boolean;\n  data: string;\n  errorMessage: string;\n  requestId: string;\n}\n\n/**\n * Interface defining the methods needed by Agent from Session.\n */\nexport interface McpSession {\n  getAPIKey(): string;\n  getSessionId(): string;\n  callMcpTool(\n    toolName: string,\n    args: Record<string, any>,\n    autoGenSession?: boolean\n  ): Promise<McpToolResult>;\n}\n\n/**\n * Options for streaming callbacks when using WebSocket-based agent execution.\n * Providing any callback enables WebSocket streaming mode automatically.\n */\nexport interface AgentStreamingOptions {\n  /** Called when the agent produces a reasoning step (thinking process). */\n  onReasoning?: AgentEventCallback;\n  /** Called when the agent produces content output (final or partial results). */\n  onContent?: AgentEventCallback;\n  /** Called when the agent invokes a tool (e.g. browser_navigate, tap). */\n  onToolCall?: AgentEventCallback;\n  /** Called when a tool returns its result. The `result` field is agent-defined; the SDK does not parse it. */\n  onToolResult?: AgentEventCallback;\n  /** Called when an error occurs during task execution. */\n  onError?: AgentEventCallback;\n}\n\n/**\n * Options for MobileUseAgent executeTask/executeTaskAndWait.\n * Extends AgentStreamingOptions with mobile-specific options.\n */\nexport interface MobileTaskOptions extends AgentStreamingOptions {\n  /** Maximum number of steps the agent can take (default: server-defined). */\n  maxSteps?: number;\n  /** Called when the agent requests user input (human-in-the-loop). Return a string response. */\n  onCallForUser?: (event: AgentEvent) => Promise<string>;\n}\n\n/**\n * Handle for a task started via executeTask. Call wait() to block until completion.\n */\nexport class TaskExecution {\n  readonly taskId: string;\n  private _resultPromise: Promise<ExecutionResult>;\n  private _cancelFn?: () => void;\n  private _requestId: string;\n\n  constructor(\n    taskId: string,\n    resultPromise: Promise<ExecutionResult>,\n    cancelFn?: () => void,\n    requestId?: string\n  ) {\n    this.taskId = taskId;\n    this._resultPromise = resultPromise;\n    this._cancelFn = cancelFn;\n    this._requestId = requestId ?? \"\";\n  }\n\n  async wait(timeout?: number): Promise<ExecutionResult> {\n    if (timeout) {\n      let timerId: ReturnType<typeof setTimeout>;\n      const timer = new Promise<ExecutionResult>((resolve) => {\n        timerId = setTimeout(() => {\n          if (this._cancelFn) {\n            try {\n              this._cancelFn();\n            } catch {\n              /* ignore cancel errors */\n            }\n          }\n          resolve({\n            requestId: this._requestId,\n            success: false,\n            errorMessage: `Task execution timed out after ${timeout} seconds.`,\n            taskId: this.taskId,\n            taskStatus: \"failed\",\n            taskResult: \"Task execution timed out.\",\n          });\n        }, timeout * 1000);\n      });\n      return Promise.race([this._resultPromise, timer]).finally(() =>\n        clearTimeout(timerId)\n      );\n    }\n    return this._resultPromise;\n  }\n}\n\n/**\n * Base class for task execution agents.\n * Provides common functionality for ComputerUseAgent and BrowserUseAgent.\n *\n * > **⚠️ Note**: Currently, for agent services (including ComputerUseAgent, BrowserUseAgent, and MobileUseAgent), we do not provide services for overseas users registered with **alibabacloud.com**.\n */\nabstract class BaseTaskAgent {\n  protected session: McpSession;\n  protected abstract toolPrefix: string;\n\n  constructor(session: McpSession) {\n    this.session = session;\n  }\n\n  /**\n   * Get the full MCP tool name based on prefix and action.\n   */\n  protected getToolName(action: string): string {\n    const toolMap: Record<string, string> = {\n      execute: \"execute_task\",\n      get_status: \"get_task_status\",\n      terminate: \"terminate_task\",\n    };\n    const baseName = toolMap[action] || action;\n    if (this.toolPrefix) {\n      return `${this.toolPrefix}_${baseName}`;\n    }\n    return baseName;\n  }\n\n  /**\n   * Check if any streaming option is provided.\n   */\n  protected hasStreamingParams(\n    options?: AgentStreamingOptions | MobileTaskOptions\n  ): boolean {\n    if (!options) return false;\n    return !!(\n      options.onReasoning ||\n      options.onContent ||\n      options.onToolCall ||\n      options.onToolResult ||\n      options.onError ||\n      (options as MobileTaskOptions).onCallForUser\n    );\n  }\n\n  /**\n   * Resolve the WS target for this agent from MCP tools list.\n   */\n  protected resolveAgentTarget(): string {\n    const executeToolName = this.getToolName(\"execute\");\n    const sessionWithTools = this.session as McpSession & {\n      mcpTools?: Array<{ name?: string; server?: string }>;\n    };\n    for (const tool of sessionWithTools.mcpTools || []) {\n      if (tool?.name === executeToolName && tool?.server) {\n        return tool.server;\n      }\n    }\n    if (this.toolPrefix === \"browser_use\") {\n      return \"wuying_browseruse\";\n    }\n    if (this.toolPrefix === \"flux\") {\n      return \"wuying_computer_agent\";\n    }\n    return \"wuying_mobile_agent\";\n  }\n\n  /**\n   * Start a task via WebSocket streaming channel. Returns handle and context\n   * immediately without blocking. Use handle.waitEnd() to await completion.\n   */\n  protected async startTaskStreamWs(params: {\n    taskParams: Record<string, any>;\n    options?: AgentStreamingOptions | MobileTaskOptions;\n  }): Promise<{\n    handle: {\n      waitEnd: () => Promise<any>;\n      cancel: () => Promise<void>;\n      write: (data: Record<string, any>) => Promise<void>;\n      invocationId: string;\n    };\n    context: {\n      finalContentParts: string[];\n      lastError: Record<string, any> | undefined;\n      errors: Error[];\n    };\n  }> {\n    const { taskParams, options } = params;\n    const sessionWithWs = this.session as McpSession & {\n      getWsClient?: () => Promise<{\n        callStream: (p: any) => Promise<{\n          waitEnd: () => Promise<any>;\n          cancel: () => Promise<void>;\n          write: (data: Record<string, any>) => Promise<void>;\n          invocationId: string;\n        }>;\n      }>;\n    };\n    if (!sessionWithWs.getWsClient) {\n      throw new Error(\"WS streaming is not available in this session\");\n    }\n\n    const wsClient = await sessionWithWs.getWsClient();\n    const target = this.resolveAgentTarget();\n\n    const finalContentParts: string[] = [];\n    let lastError: Record<string, any> | undefined;\n    const errors: Error[] = [];\n    const handleRef: {\n      current: { write: (data: Record<string, any>) => Promise<void> } | null;\n    } = { current: null };\n\n    const dispatchEvent = (event: AgentEvent): void => {\n      const cb = {\n        reasoning: options?.onReasoning,\n        content: options?.onContent,\n        tool_call: options?.onToolCall,\n        tool_result: options?.onToolResult,\n        error: options?.onError,\n      }[event.type];\n      if (cb) {\n        try {\n          cb(event);\n        } catch (ex) {\n          logWarn(`on_${event.type} callback error: ${ex}`);\n        }\n      }\n    };\n\n    const handle = await wsClient.callStream({\n      target,\n      data: {\n        method: \"exec_task\",\n        params: taskParams,\n      },\n      onEvent: (_invocationId: string, data: any) => {\n        const eventType = data?.eventType ?? \"\";\n        const seq = data?.seq ?? 0;\n        const round = data?.round ?? 0;\n\n        if (eventType === \"reasoning\") {\n          dispatchEvent({\n            type: \"reasoning\",\n            seq,\n            round,\n            content: data?.content ?? \"\",\n          });\n        } else if (eventType === \"content\") {\n          const contentText = data?.content ?? \"\";\n          finalContentParts.push(contentText);\n          dispatchEvent({ type: \"content\", seq, round, content: contentText });\n        } else if (eventType === \"tool_call\") {\n          const toolName = String(data?.toolName ?? \"\");\n          const args = (data?.args as Record<string, any>) ?? {};\n          const evt: AgentEvent = {\n            type: \"tool_call\",\n            seq,\n            round,\n            toolCallId: String(data?.toolCallId ?? \"\"),\n            toolName,\n            args,\n            prompt:\n              toolName === \"call_for_user\" ? args?.prompt ?? \"\" : undefined,\n            content:\n              toolName === \"call_for_user\" ? args?.prompt ?? \"\" : undefined,\n          };\n          dispatchEvent(evt);\n          if (toolName === \"call_for_user\") {\n            (async () => {\n              let response = \"\";\n              const onCb = (options as MobileTaskOptions)?.onCallForUser;\n              if (onCb) {\n                try {\n                  response = (await onCb(evt)) ?? \"\";\n                } catch (e) {\n                  logWarn(`onCallForUser callback error: ${e}`);\n                }\n              } else {\n                logWarn(\n                  \"Received call_for_user but no onCallForUser callback is set, sending empty response\"\n                );\n              }\n              if (handleRef.current) {\n                try {\n                  await handleRef.current.write({\n                    method: \"resume_task\",\n                    params: {\n                      toolCallId: evt.toolCallId,\n                      response: response || \"\",\n                    },\n                  });\n                } catch (e) {\n                  logWarn(`Failed to send resume_task: ${e}`);\n                }\n              }\n            })();\n          }\n        } else if (eventType === \"tool_result\") {\n          dispatchEvent({\n            type: \"tool_result\",\n            seq,\n            round,\n            toolCallId: data?.toolCallId ?? \"\",\n            toolName: data?.toolName ?? \"\",\n            result: data?.result ?? {},\n          });\n        } else if (eventType === \"error\") {\n          lastError = data?.error ?? data;\n          dispatchEvent({\n            type: \"error\",\n            seq,\n            round,\n            error: lastError,\n          });\n        }\n      },\n      onError: (_invocationId: string, err: Error) => {\n        errors.push(err);\n      },\n    });\n\n    handleRef.current = handle;\n\n    return {\n      handle,\n      context: { finalContentParts, lastError, errors },\n    };\n  }\n\n  /**\n   * Execute a task via WebSocket streaming channel.\n   */\n  protected async executeTaskStreamWs(params: {\n    taskParams: Record<string, any>;\n    timeout: number;\n    options?: AgentStreamingOptions | MobileTaskOptions;\n  }): Promise<ExecutionResult> {\n    const { taskParams, timeout, options } = params;\n    const sessionWithWs = this.session as McpSession & {\n      getWsClient?: () => Promise<{\n        callStream: (p: any) => Promise<{\n          waitEnd: () => Promise<any>;\n          cancel: () => Promise<void>;\n          write: (data: Record<string, any>) => Promise<void>;\n          invocationId: string;\n        }>;\n      }>;\n    };\n    if (!sessionWithWs.getWsClient) {\n      return {\n        requestId: \"\",\n        success: false,\n        errorMessage: \"WS streaming is not available in this session\",\n        taskStatus: \"failed\",\n        taskId: \"\",\n        taskResult: \"WS streaming is not available.\",\n      };\n    }\n\n    let handle: {\n      waitEnd: () => Promise<any>;\n      cancel: () => Promise<void>;\n      write: (data: Record<string, any>) => Promise<void>;\n      invocationId: string;\n    };\n    let context: {\n      finalContentParts: string[];\n      lastError: Record<string, any> | undefined;\n      errors: Error[];\n    };\n    try {\n      const result = await this.startTaskStreamWs({ taskParams, options });\n      handle = result.handle;\n      context = result.context;\n    } catch (e: any) {\n      return {\n        requestId: \"\",\n        success: false,\n        errorMessage: e instanceof Error ? e.message : String(e),\n        taskStatus: \"failed\",\n        taskId: \"\",\n        taskResult: \"WS streaming is not available.\",\n      };\n    }\n\n    const { finalContentParts, lastError, errors } = context;\n    let endData: any = {};\n    try {\n      const timeoutPromise = new Promise<never>((_, reject) =>\n        setTimeout(\n          () =>\n            reject(\n              new Error(`Task execution timed out after ${timeout} seconds.`)\n            ),\n          timeout * 1000\n        )\n      );\n      endData = await Promise.race([handle.waitEnd(), timeoutPromise]);\n    } catch (e: any) {\n      try {\n        await handle.cancel();\n      } catch (_cancelErr) {\n        // ignore\n      }\n      const msg = e instanceof Error ? e.message : String(e);\n      return {\n        requestId: handle.invocationId,\n        success: false,\n        errorMessage: msg,\n        taskStatus: \"timeout\",\n        taskId: \"\",\n        taskResult: finalContentParts.join(\"\") || msg,\n      };\n    }\n\n    if (errors.length > 0) {\n      return {\n        requestId: handle.invocationId,\n        success: false,\n        errorMessage: String(errors[0]),\n        taskStatus: \"failed\",\n        taskId: \"\",\n        taskResult: finalContentParts.join(\"\"),\n      };\n    }\n\n    if (lastError) {\n      return {\n        requestId: handle.invocationId,\n        success: false,\n        errorMessage: String(lastError),\n        taskStatus: \"failed\",\n        taskId: \"\",\n        taskResult: finalContentParts.join(\"\"),\n      };\n    }\n\n    const status = endData?.status ?? \"finished\";\n    const taskResult = endData?.taskResult ?? finalContentParts.join(\"\");\n\n    return {\n      requestId: handle.invocationId,\n      success: status === \"finished\",\n      errorMessage:\n        status === \"finished\" ? \"\" : `Task ended with status: ${status}`,\n      taskStatus: status,\n      taskId: \"\",\n      taskResult,\n    };\n  }\n\n  /**\n   * Execute a specific task described in human language.\n   * Note: MobileUseAgent overrides this to return TaskExecution instead.\n   */\n  async executeTask(task: string): Promise<ExecutionResult> {\n    try {\n      const args = { task };\n      const result = await this.session.callMcpTool(\n        this.getToolName(\"execute\"),\n        args,\n        false\n      );\n\n      if (!result.success) {\n        return {\n          requestId: result.requestId,\n          success: false,\n          errorMessage: result.errorMessage,\n          taskStatus: \"failed\",\n          taskId: \"\",\n          taskResult: \"Task Failed\",\n        };\n      }\n\n      // Parse task ID from response\n      let content: Record<string, any>;\n      try {\n        content = JSON.parse(result.data);\n      } catch (err) {\n        return {\n          requestId: result.requestId,\n          success: false,\n          errorMessage: `Failed to parse response: ${err}`,\n          taskStatus: \"failed\",\n          taskId: \"\",\n          taskResult: \"Invalid execution response.\",\n        };\n      }\n\n      const taskId = content.task_id || \"\";\n      if (!taskId) {\n        // 从后端返回的content中提取error信息\n        const errorMessage = content.error || \"Task ID not found in response\";\n        return {\n          requestId: result.requestId,\n          success: false,\n          errorMessage: errorMessage,\n          taskStatus: \"failed\",\n          taskId: \"\",\n          taskResult: \"Invalid task ID.\",\n        };\n      }\n\n      return {\n        requestId: result.requestId,\n        success: true,\n        errorMessage: \"\",\n        taskId: taskId,\n        taskStatus: \"running\",\n        taskResult: \"\",\n      };\n    } catch (error) {\n      return {\n        requestId: \"\",\n        success: false,\n        errorMessage: `Failed to execute: ${error}`,\n        taskStatus: \"failed\",\n        taskId: \"\",\n        taskResult: \"Task Failed\",\n      };\n    }\n  }\n\n  /**\n   * Execute a specific task described in human language synchronously.\n   * This is a synchronous interface that blocks until the task is completed or\n   * an error occurs, or timeout happens. The default polling interval is 3 seconds.\n   */\n  async executeTaskAndWait(\n    task: string,\n    timeout: number\n  ): Promise<ExecutionResult> {\n    const result = await this.executeTask(task);\n    if (!result.success) {\n      return result;\n    }\n\n    const taskId = result.taskId;\n    const pollInterval = 3;\n    const maxPollAttempts = Math.floor(timeout / pollInterval);\n    let triedTime = 0;\n\n    while (triedTime < maxPollAttempts) {\n      const query = await this.getTaskStatus(taskId);\n      if (!query.success) {\n        return {\n          requestId: query.requestId,\n          success: false,\n          errorMessage: query.errorMessage,\n          taskStatus: \"failed\",\n          taskId: taskId,\n          taskResult: \"\",\n        };\n      }\n\n      switch (query.taskStatus) {\n        case \"finished\":\n          return {\n            requestId: query.requestId,\n            success: true,\n            errorMessage: \"\",\n            taskId: taskId,\n            taskStatus: \"finished\",\n            taskResult: query.taskProduct,\n          };\n        case \"failed\":\n          return {\n            requestId: query.requestId,\n            success: false,\n            errorMessage: query.errorMessage || \"Failed to execute task.\",\n            taskId: taskId,\n            taskStatus: \"failed\",\n            taskResult: \"\",\n          };\n        case \"unsupported\":\n          return {\n            requestId: query.requestId,\n            success: false,\n            errorMessage: query.errorMessage || \"Unsupported task.\",\n            taskId: taskId,\n            taskStatus: \"unsupported\",\n            taskResult: \"\",\n          };\n      }\n\n      logDebug(`Task ${taskId} is still running, please wait for a while.`);\n      await new Promise((resolve) => setTimeout(resolve, pollInterval * 1000));\n      triedTime++;\n    }\n\n    try {\n      const terminateResult = await this.terminateTask(taskId);\n      if (terminateResult.success) {\n        logDebug(`✅ Terminate request sent for task ${taskId} after timeout`);\n      } else {\n        logDebug(\n          `⚠️ Failed to terminate task ${taskId} after timeout: ${terminateResult.errorMessage}`\n        );\n      }\n    } catch (e) {\n      logDebug(\n        `⚠️ Exception while terminating task ${taskId} after timeout: ${e}`\n      );\n    }\n\n    logDebug(`⏳ Waiting for task ${taskId} to be fully terminated...`);\n    const terminatePollInterval = 1;\n    const maxTerminatePollAttempts = 30;\n    let terminateTriedTime = 0;\n    let taskTerminatedConfirmed = false;\n\n    while (terminateTriedTime < maxTerminatePollAttempts) {\n      try {\n        const statusQuery = await this.getTaskStatus(taskId);\n        if (!statusQuery.success) {\n          const errorMsg = statusQuery.errorMessage || \"\";\n          if (errorMsg.startsWith(\"Task not found or already finished\")) {\n            logDebug(\n              `✅ Task ${taskId} confirmed terminated (not found or finished)`\n            );\n            taskTerminatedConfirmed = true;\n            break;\n          }\n        }\n        await new Promise((resolve) =>\n          setTimeout(resolve, terminatePollInterval * 1000)\n        );\n        terminateTriedTime++;\n      } catch (e) {\n        logDebug(\n          `⚠️ Exception while polling task status during termination: ${e}`\n        );\n        await new Promise((resolve) =>\n          setTimeout(resolve, terminatePollInterval * 1000)\n        );\n        terminateTriedTime++;\n      }\n    }\n\n    if (!taskTerminatedConfirmed) {\n      logDebug(`⚠️ Timeout waiting for task ${taskId} to be fully terminated`);\n    }\n\n    const timeoutErrorMsg = `Task execution timed out after ${timeout} seconds. Task ID: ${taskId}. Polled ${triedTime} times (max: ${maxPollAttempts}).`;\n    return {\n      requestId: result.requestId,\n      success: false,\n      errorMessage: timeoutErrorMsg,\n      taskStatus: \"timeout\",\n      taskId: taskId,\n      taskResult: `Task execution timed out after ${timeout} seconds.`,\n    };\n  }\n\n  /**\n   * Get the status of the task with the given task ID.\n   */\n  async getTaskStatus(taskId: string): Promise<QueryResult> {\n    try {\n      const args = { task_id: taskId };\n      const result = await this.session.callMcpTool(\n        this.getToolName(\"get_status\"),\n        args,\n        false\n      );\n\n      if (!result.success) {\n        return {\n          requestId: result.requestId,\n          success: false,\n          errorMessage: result.errorMessage,\n          taskId: taskId,\n          taskAction: \"\",\n          taskProduct: \"\",\n          taskStatus: \"failed\",\n        };\n      }\n      let queryResult: Record<string, any>;\n      try {\n        queryResult = JSON.parse(result.data);\n        return {\n          requestId: result.requestId,\n          success: true,\n          errorMessage: \"\",\n          taskId: queryResult.task_id || taskId,\n          taskAction: queryResult.action || \"\",\n          taskProduct: queryResult.product || \"\",\n          taskStatus: queryResult.status || \"finished\",\n        };\n      } catch (error) {\n        return {\n          requestId: result.requestId,\n          success: false,\n          errorMessage: `Failed to get task status: ${error}`,\n          taskId: taskId,\n          taskAction: \"\",\n          taskProduct: \"\",\n          taskStatus: \"failed\",\n        };\n      }\n    } catch (error) {\n      return {\n        requestId: \"\",\n        success: false,\n        errorMessage: `Failed to get task status: ${error}`,\n        taskId: taskId,\n        taskAction: \"\",\n        taskProduct: \"\",\n        taskStatus: \"failed\",\n      };\n    }\n  }\n\n  /**\n   * Terminate a task with a specified task ID.\n   */\n  async terminateTask(taskId: string): Promise<ExecutionResult> {\n    logDebug(\"Terminating task\");\n\n    try {\n      const args = { task_id: taskId };\n      const result = await this.session.callMcpTool(\n        this.getToolName(\"terminate\"),\n        args,\n        false\n      );\n\n      let content: Record<string, any>;\n      try {\n        content = JSON.parse(result.data);\n      } catch (err) {\n        return {\n          requestId: result.requestId,\n          success: false,\n          errorMessage: `Failed to parse response: ${err}`,\n          taskId,\n          taskStatus: \"failed\",\n          taskResult: \"\",\n        };\n      }\n\n      const terminatedTaskId = content.task_id || taskId;\n      const status = content.status || \"finished\";\n\n      if (result.success) {\n        return {\n          requestId: result.requestId,\n          success: true,\n          errorMessage: \"\",\n          taskId: terminatedTaskId,\n          taskStatus: status,\n          taskResult: \"\",\n        };\n      }\n\n      return {\n        requestId: result.requestId,\n        success: false,\n        errorMessage: result.errorMessage,\n        taskId: terminatedTaskId,\n        taskStatus: status,\n        taskResult: \"\",\n      };\n    } catch (error) {\n      return {\n        requestId: \"\",\n        success: false,\n        errorMessage: `Failed to terminate: ${error}`,\n        taskId,\n        taskStatus: \"failed\",\n        taskResult: \"\",\n      };\n    }\n  }\n}\n\n/**\n * An Agent to perform tasks on the computer.\n */\nexport class ComputerUseAgent extends BaseTaskAgent {\n  protected toolPrefix = \"flux\";\n}\n\nexport class BrowserUseAgent extends BaseTaskAgent {\n  protected toolPrefix = \"browser_use\";\n  private initialized = false;\n\n  /**\n   * Initialize the browser on which the agent performs tasks.\n   * You are supposed to call this API before executeTask is called, but it's optional.\n   * If you want to perform a hybrid usage of browser, you must call this API before executeTask is called.\n   *\n   * @param option - Browser configuration options. If not provided, default options will be used.\n   * @returns Promise<boolean> - True if the browser is successfully initialized, False otherwise.\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: process.env.AGENTBAY_API_KEY });\n   * const result = await agentBay.create({ imageId: 'browser_latest' });\n   * if (result.success) {\n   *   const success = await result.session.agent.browser.initialize();\n   *   console.log('Browser initialized:', success);\n   *   await result.session.delete();\n   * }\n   * ```\n   */\n  async initialize(option?: BrowserOption): Promise<boolean> {\n    if (this.initialized) {\n      return true;\n    }\n\n    if (!option) {\n      option = {};\n    }\n\n    try {\n      // Access browser through session - assuming session has a browser property\n      const success = await (this.session as any).browser.initializeAsync(\n        option\n      );\n      this.initialized = success;\n      return success;\n    } catch (error) {\n      logWarn(`Failed to initialize browser: ${error}`);\n      return false;\n    }\n  }\n\n  /**\n   * Execute a task described in human language on a browser without waiting for completion\n   * (non-blocking). This is a fire-and-return interface that immediately\n   * provides a task ID. Call getTaskStatus to check the task status.\n   *\n   * @param task - Task description in human language.\n   * @param use_vision - Whether to use vision in the task.\n   * @param output_schema - Optional Zod schema for a structured task output if you need.\n   * @returns ExecutionResult containing success status, task ID, task status,\n   *     and error message if any.\n   *\n   * @example\n   * ```typescript\n   * const WeatherSchema = z.object({city: z.string(), weather:z.string()});\n   * const agentBay = new AgentBay({ apiKey: 'your_api_key' });\n   * const result = await agentBay.create({ imageId: 'linux_latest' });\n   * if (result.success) {\n   *   const execResult = await result.session.agent.browser.executeTask(\n   *     'Query the weather in Shanghai', false, WeatherSchema\n   *   );\n   *   console.log(`Task ID: ${execResult.taskId}`);\n   *   await result.session.delete();\n   * }\n   * ```\n   */\n  async executeTask<TSchema extends ZodTypeAny>(\n    task: string,\n    use_vision = true,\n    output_schema?: TSchema\n  ): Promise<ExecutionResult> {\n    if (!this.initialized) {\n      logInfo(\"Browser is not initialized, initializing browser!\");\n      const success = await this.initialize();\n      if (!success) {\n        logWarn(\"Browser initialization failed!\");\n        return {\n          requestId: \"\",\n          success: false,\n          errorMessage: \"Browser initialization failed\",\n          taskStatus: \"failed\",\n          taskId: \"\",\n          taskResult: \"Browser initialization failed\",\n        };\n      }\n    }\n    try {\n      let json_schema = null;\n      if (output_schema !== undefined) {\n        json_schema = zodToJsonSchema(output_schema, {\n          $refStrategy: \"none\",\n        });\n      } else {\n        json_schema = zodToJsonSchema(DefaultSchema, {\n          $refStrategy: \"none\",\n        });\n      }\n\n      const args: any = {\n        task,\n        use_vision: use_vision,\n        output_schema: JSON.stringify(json_schema),\n      };\n      const result = await this.session.callMcpTool(\n        this.getToolName(\"execute\"),\n        args\n      );\n\n      if (!result.success) {\n        return {\n          requestId: result.requestId,\n          success: false,\n          errorMessage: result.errorMessage,\n          taskStatus: \"failed\",\n          taskId: \"\",\n          taskResult: \"Task Failed\",\n        };\n      }\n\n      // Parse task ID from response\n      let content: any;\n      try {\n        content = JSON.parse(result.data);\n      } catch (err) {\n        return {\n          requestId: result.requestId,\n          success: false,\n          errorMessage: `Failed to parse response: ${err}`,\n          taskStatus: \"failed\",\n          taskId: \"\",\n          taskResult: \"Invalid execution response.\",\n        };\n      }\n\n      const taskId = content.task_id || \"\";\n      if (!taskId) {\n        return {\n          requestId: result.requestId,\n          success: false,\n          errorMessage: \"Task ID not found in response\",\n          taskStatus: \"failed\",\n          taskId: \"\",\n          taskResult: \"Invalid task ID.\",\n        };\n      }\n\n      return {\n        requestId: result.requestId,\n        success: true,\n        errorMessage: \"\",\n        taskId: taskId,\n        taskStatus: \"running\",\n        taskResult: \"\",\n      };\n    } catch (error) {\n      return {\n        requestId: \"\",\n        success: false,\n        errorMessage: `Failed to execute: ${error}`,\n        taskStatus: \"failed\",\n        taskId: \"\",\n        taskResult: \"Task Failed\",\n      };\n    }\n  }\n\n  /**\n   * Execute a task described in human language on a browser synchronously.\n   * This is a synchronous interface that blocks until the task is completed or\n   * an error occurs, or timeout happens. The default polling interval is 3 seconds.\n   *\n   * @param task - Task description in human language.\n   * @param timeout - Maximum time to wait for task completion (in seconds). Used to control how long to wait for task completion.\n   * @param use_vision - Whether to use vision in the task.\n   * @param output_schema - Optional Zod schema for a structured task output if you need.\n   * @returns ExecutionResult containing success status, task ID, task status,\n   *     and error message if any.\n   *\n   * @example\n   * ```typescript\n   * const WeatherSchema = z.object({city: z.string(), weather:z.string()});\n   * const agentBay = new AgentBay({ apiKey: 'your_api_key' });\n   * const result = await agentBay.create({ imageId: 'linux_latest' });\n   * if (result.success) {\n   *   const execResult = await result.session.agent.browser.executeTask(\n   *     'Query the weather in Shanghai', false, WeatherSchema\n   *   );\n   *   console.log(`Task ID: ${execResult.taskId}`);\n   *   const pollInterval = 3;\n   *   const timeout = 180;\n   *   const maxPollAttempts = Math.floor(timeout / pollInterval);\n   *   let triedTime = 0;\n   *   while(triedTime < maxPollAttempts) {\n   *     const queryResult = await result.session.agent.browser.getTaskStatus(execResult.taskId);\n   *     if (queryResult.taskStatus === 'finished') {\n   *       console.log(`Task ${execResult.taskId} finished with result: ${queryResult.taskResult}`);\n   *       break;\n   *     }\n   *     triedTime++;\n   *   }\n   *   await result.session.delete();\n   * }\n   * ```\n   */\n  async executeTaskAndWait<TSchema extends ZodTypeAny>(\n    task: string,\n    timeout: number,\n    use_vision?: boolean,\n    output_schema?: TSchema\n  ): Promise<ExecutionResult> {\n    const use_vision_resolved = use_vision === undefined ? true : use_vision;\n\n    if (!this.initialized) {\n      logInfo(\"Browser is not initialized, initializing browser!\");\n      const success = await this.initialize();\n      if (!success) {\n        logWarn(\"Browser initialization failed!\");\n        return {\n          requestId: \"\",\n          success: false,\n          errorMessage: \"Browser initialization failed\",\n          taskStatus: \"failed\",\n          taskId: \"\",\n          taskResult: \"Browser initialization failed\",\n        };\n      }\n    }\n\n    const result = await this.executeTask(\n      task,\n      use_vision_resolved,\n      output_schema\n    );\n    if (!result.success) {\n      return result;\n    }\n\n    const taskId = result.taskId;\n    const pollInterval = 3;\n    const maxPollAttempts = Math.floor(timeout / pollInterval);\n    let triedTime = 0;\n\n    while (triedTime < maxPollAttempts) {\n      const query = await this.getTaskStatus(taskId);\n      if (!query.success) {\n        return {\n          requestId: query.requestId,\n          success: false,\n          errorMessage: query.errorMessage,\n          taskStatus: \"failed\",\n          taskId: taskId,\n          taskResult: \"\",\n        };\n      }\n\n      switch (query.taskStatus) {\n        case \"finished\":\n          return {\n            requestId: query.requestId,\n            success: true,\n            errorMessage: \"\",\n            taskId: taskId,\n            taskStatus: \"finished\",\n            taskResult: query.taskProduct,\n          };\n        case \"failed\":\n          return {\n            requestId: query.requestId,\n            success: false,\n            errorMessage: query.errorMessage || \"Failed to execute task.\",\n            taskId: taskId,\n            taskStatus: \"failed\",\n            taskResult: \"\",\n          };\n        case \"unsupported\":\n          return {\n            requestId: query.requestId,\n            success: false,\n            errorMessage: query.errorMessage || \"Unsupported task.\",\n            taskId: taskId,\n            taskStatus: \"unsupported\",\n            taskResult: \"\",\n          };\n      }\n\n      logDebug(`Task ${taskId} is still running, please wait for a while.`);\n      await new Promise((resolve) => setTimeout(resolve, pollInterval * 1000));\n      triedTime++;\n    }\n\n    // Automatically terminate the task on timeout\n    try {\n      const terminateResult = await this.terminateTask(taskId);\n      if (terminateResult.success) {\n        logDebug(`✅ Task ${taskId} terminated successfully after timeout`);\n      } else {\n        logDebug(\n          `⚠️ Failed to terminate task ${taskId} after timeout: ${terminateResult.errorMessage}`\n        );\n      }\n    } catch (e) {\n      logDebug(\n        `⚠️ Exception while terminating task ${taskId} after timeout: ${e}`\n      );\n    }\n\n    const timeoutErrorMsg = `Task execution timed out after ${timeout} seconds. Task ID: ${taskId}. Polled ${triedTime} times (max: ${maxPollAttempts}).`;\n    return {\n      requestId: result.requestId,\n      success: false,\n      errorMessage: timeoutErrorMsg,\n      taskStatus: \"timeout\",\n      taskId: taskId,\n      taskResult: `Task execution timed out after ${timeout} seconds.`,\n    };\n  }\n}\n\n/**\n * An Agent to perform tasks on mobile devices.\n */\nexport class MobileUseAgent extends BaseTaskAgent {\n  protected toolPrefix = \"\";\n\n  /**\n   * Poll task status until completion or timeout.\n   */\n  private async _pollTaskUntilComplete(\n    taskId: string,\n    requestId: string,\n    timeout: number\n  ): Promise<ExecutionResult> {\n    const pollInterval = 3;\n    const maxPollAttempts = Math.floor(timeout / pollInterval);\n    let triedTime = 0;\n    const processedTimestamps = new Set<number>();\n    let lastQuery: QueryResult | null = null;\n\n    while (triedTime < maxPollAttempts) {\n      const query = await this.getTaskStatus(taskId);\n      if (!query.success) {\n        return {\n          requestId: query.requestId,\n          success: false,\n          errorMessage: query.errorMessage,\n          taskStatus: \"failed\",\n          taskId: taskId,\n          taskResult: \"\",\n        };\n      }\n\n      if (query.stream && query.stream.length > 0) {\n        lastQuery = query;\n      }\n\n      if (query.stream) {\n        for (const streamItem of query.stream) {\n          const timestamp = streamItem.timestamp_ms;\n          if (timestamp !== undefined && !processedTimestamps.has(timestamp)) {\n            processedTimestamps.add(timestamp);\n            const content = streamItem.content || \"\";\n            if (content) {\n              process.stdout.write(content);\n            }\n          }\n        }\n      }\n\n      switch (query.taskStatus) {\n        case \"completed\":\n          return {\n            requestId: query.requestId,\n            success: true,\n            errorMessage: \"\",\n            taskId: taskId,\n            taskStatus: \"completed\",\n            taskResult: query.taskProduct,\n          };\n        case \"failed\":\n          return {\n            requestId: query.requestId,\n            success: false,\n            errorMessage:\n              query.error || query.errorMessage || \"Failed to execute task.\",\n            taskId: taskId,\n            taskStatus: \"failed\",\n            taskResult: \"\",\n          };\n        case \"cancelled\":\n          return {\n            requestId: query.requestId,\n            success: false,\n            errorMessage:\n              query.error || query.errorMessage || \"Task was cancelled.\",\n            taskId: taskId,\n            taskStatus: \"cancelled\",\n            taskResult: \"\",\n          };\n        case \"unsupported\":\n          return {\n            requestId: query.requestId,\n            success: false,\n            errorMessage:\n              query.error || query.errorMessage || \"Unsupported task.\",\n            taskId: taskId,\n            taskStatus: \"unsupported\",\n            taskResult: \"\",\n          };\n      }\n\n      logDebug(`⏳ Task ${taskId} running 🚀: ${query.taskAction}.`);\n      await new Promise((resolve) => setTimeout(resolve, 3000));\n      triedTime++;\n    }\n\n    logDebug(\"⚠️ task execution timeout!\");\n    try {\n      const terminateResult = await this.terminateTask(taskId);\n      if (terminateResult.success) {\n        logDebug(`✅ Terminate request sent for task ${taskId} after timeout`);\n      } else {\n        logDebug(\n          `⚠️ Failed to terminate task ${taskId} after timeout: ${terminateResult.errorMessage}`\n        );\n      }\n    } catch (e) {\n      logDebug(\n        `⚠️ Exception while terminating task ${taskId} after timeout: ${e}`\n      );\n    }\n\n    logDebug(`⏳ Waiting for task ${taskId} to be fully terminated...`);\n    const terminatePollInterval = 1;\n    const maxTerminatePollAttempts = 30;\n    let terminateTriedTime = 0;\n    let taskTerminatedConfirmed = false;\n\n    while (terminateTriedTime < maxTerminatePollAttempts) {\n      try {\n        const statusQuery = await this.getTaskStatus(taskId);\n        if (!statusQuery.success) {\n          const errorMsg = statusQuery.errorMessage || \"\";\n          if (errorMsg.startsWith(\"Task not found or already finished\")) {\n            logDebug(\n              `✅ Task ${taskId} confirmed terminated (not found or finished)`\n            );\n            taskTerminatedConfirmed = true;\n            break;\n          }\n        }\n        await new Promise((resolve) =>\n          setTimeout(resolve, terminatePollInterval * 1000)\n        );\n        terminateTriedTime++;\n      } catch (e) {\n        logDebug(\n          `⚠️ Exception while polling task status during termination: ${e}`\n        );\n        await new Promise((resolve) =>\n          setTimeout(resolve, terminatePollInterval * 1000)\n        );\n        terminateTriedTime++;\n      }\n    }\n\n    if (!taskTerminatedConfirmed) {\n      logDebug(`⚠️ Timeout waiting for task ${taskId} to be fully terminated`);\n    }\n\n    const timeoutErrorMsg = `Task execution timed out after ${timeout} seconds. Task ID: ${taskId}. Polled ${triedTime} times (max: ${maxPollAttempts}).`;\n    const taskResultParts: string[] = [\n      `Task execution timed out after ${timeout} seconds.`,\n    ];\n\n    if (lastQuery) {\n      if (lastQuery.stream && lastQuery.stream.length > 0) {\n        const streamContentParts: string[] = [];\n        for (const streamItem of lastQuery.stream) {\n          if (streamItem.content) {\n            streamContentParts.push(streamItem.content);\n          }\n        }\n        if (streamContentParts.length > 0) {\n          taskResultParts.push(\n            `Last task status output: ${streamContentParts.join(\"\")}`\n          );\n        }\n      }\n      if (lastQuery.taskAction) {\n        taskResultParts.push(`Last action: ${lastQuery.taskAction}`);\n      }\n      if (lastQuery.taskProduct) {\n        taskResultParts.push(`Last result: ${lastQuery.taskProduct}`);\n      }\n      if (lastQuery.error) {\n        taskResultParts.push(`Last error: ${lastQuery.error}`);\n      }\n      if (lastQuery.taskStatus) {\n        taskResultParts.push(`Last status: ${lastQuery.taskStatus}`);\n      }\n    }\n\n    return {\n      requestId,\n      success: false,\n      errorMessage: timeoutErrorMsg,\n      taskStatus: \"failed\",\n      taskId: taskId,\n      taskResult: taskResultParts.join(\" | \"),\n    };\n  }\n\n  /**\n   * Execute a task in human language without waiting for completion\n   * (non-blocking). Returns TaskExecution; call wait() to block until done.\n   *\n   * @param task - Task description in human language.\n   * @param options - Optional MobileTaskOptions (maxSteps, streaming callbacks).\n   * @returns TaskExecution with taskId and wait() method.\n   */\n  // @ts-expect-error MobileUseAgent returns TaskExecution; base returns ExecutionResult\n  async executeTask(\n    task: string,\n    options?: MobileTaskOptions\n  ): Promise<TaskExecution> {\n    const maxSteps = options?.maxSteps ?? 50;\n\n    if (this.hasStreamingParams(options)) {\n      const sessionWithWs = this.session as McpSession & {\n        getWsClient?: () => Promise<{\n          callStream: (p: any) => Promise<{\n            waitEnd: () => Promise<any>;\n            cancel: () => Promise<void>;\n            write: (data: Record<string, any>) => Promise<void>;\n            invocationId: string;\n          }>;\n        }>;\n      };\n      if (!sessionWithWs.getWsClient) {\n        return new TaskExecution(\n          \"\",\n          Promise.resolve({\n            requestId: \"\",\n            success: false,\n            errorMessage: \"WS streaming is not available in this session\",\n            taskStatus: \"failed\",\n            taskId: \"\",\n            taskResult: \"WS streaming is not available.\",\n          })\n        );\n      }\n\n      const { handle, context } = await this.startTaskStreamWs({\n        taskParams: { task, max_steps: maxSteps },\n        options,\n      });\n      const resultPromise = (async (): Promise<ExecutionResult> => {\n        const { finalContentParts, lastError, errors } = context;\n        let endData: any = {};\n        try {\n          endData = await handle.waitEnd();\n        } catch (e: any) {\n          try {\n            await handle.cancel();\n          } catch (_cancelErr) {\n            // ignore\n          }\n          const msg = e instanceof Error ? e.message : String(e);\n          return {\n            requestId: handle.invocationId,\n            success: false,\n            errorMessage: msg,\n            taskStatus: \"timeout\",\n            taskId: \"\",\n            taskResult: finalContentParts.join(\"\") || msg,\n          };\n        }\n\n        if (errors.length > 0) {\n          return {\n            requestId: handle.invocationId,\n            success: false,\n            errorMessage: String(errors[0]),\n            taskStatus: \"failed\",\n            taskId: \"\",\n            taskResult: finalContentParts.join(\"\"),\n          };\n        }\n\n        if (lastError) {\n          return {\n            requestId: handle.invocationId,\n            success: false,\n            errorMessage: String(lastError),\n            taskStatus: \"failed\",\n            taskId: \"\",\n            taskResult: finalContentParts.join(\"\"),\n          };\n        }\n\n        const status = endData?.status ?? \"finished\";\n        const taskResult = endData?.taskResult ?? finalContentParts.join(\"\");\n        return {\n          requestId: handle.invocationId,\n          success: status === \"finished\",\n          errorMessage:\n            status === \"finished\" ? \"\" : `Task ended with status: ${status}`,\n          taskStatus: status,\n          taskId: \"\",\n          taskResult,\n        };\n      })();\n\n      return new TaskExecution(\n        handle.invocationId,\n        resultPromise,\n        () => handle.cancel(),\n        handle.invocationId\n      );\n    }\n\n    const args = { task, max_steps: maxSteps };\n    try {\n      const result = await this.session.callMcpTool(\n        this.getToolName(\"execute\"),\n        args\n      );\n\n      if (!result.success) {\n        return new TaskExecution(\n          \"\",\n          Promise.resolve({\n            requestId: result.requestId,\n            success: false,\n            errorMessage: result.errorMessage || \"Failed to execute task\",\n            taskStatus: \"failed\",\n            taskId: \"\",\n            taskResult: \"Task Failed\",\n          })\n        );\n      }\n\n      let content: Record<string, any>;\n      try {\n        content = JSON.parse(result.data);\n      } catch {\n        // Backend executed the task synchronously and returned\n        // the result as plain text instead of JSON with taskId.\n        return new TaskExecution(\n          \"\",\n          Promise.resolve({\n            requestId: result.requestId,\n            success: true,\n            errorMessage: \"\",\n            taskStatus: \"completed\",\n            taskId: \"\",\n            taskResult: result.data || \"\",\n          })\n        );\n      }\n\n      const taskId = content.taskId || content.task_id;\n      if (!taskId) {\n        // No taskId means the backend completed the task synchronously.\n        return new TaskExecution(\n          \"\",\n          Promise.resolve({\n            requestId: result.requestId,\n            success: true,\n            errorMessage: \"\",\n            taskStatus: \"completed\",\n            taskId: \"\",\n            taskResult: result.data || \"\",\n          })\n        );\n      }\n\n      const resultPromise = this._pollTaskUntilComplete(\n        taskId,\n        result.requestId,\n        86400\n      );\n      return new TaskExecution(\n        taskId,\n        resultPromise,\n        undefined,\n        result.requestId\n      );\n    } catch (error) {\n      return new TaskExecution(\n        \"\",\n        Promise.resolve({\n          requestId: \"\",\n          success: false,\n          errorMessage: `Failed to execute: ${error}`,\n          taskStatus: \"failed\",\n          taskId: \"\",\n          taskResult: \"Task Failed\",\n        })\n      );\n    }\n  }\n\n  /**\n   * Execute a task described in human language synchronously.\n   * Blocks until the task is completed, an error occurs, or timeout.\n   *\n   * @param task - Task description in human language.\n   * @param timeout - Maximum time to wait for task completion (in seconds).\n   * @param options - Optional MobileTaskOptions (maxSteps, streaming callbacks).\n   * @returns ExecutionResult containing success status, task ID, task status.\n   */\n  async executeTaskAndWait(\n    task: string,\n    timeout: number,\n    options?: MobileTaskOptions\n  ): Promise<ExecutionResult> {\n    try {\n      const execution = await this.executeTask(task, options);\n      return await execution.wait(timeout);\n    } catch (e: any) {\n      return {\n        requestId: \"\",\n        success: false,\n        errorMessage: e instanceof Error ? e.message : String(e),\n        taskStatus: \"failed\",\n        taskId: \"\",\n        taskResult: \"Task Failed\",\n      };\n    }\n  }\n\n  /**\n   * Get the status of the task with the given task ID.\n   */\n  async getTaskStatus(taskId: string): Promise<QueryResult> {\n    try {\n      const args = { task_id: taskId };\n      const result = await this.session.callMcpTool(\n        this.getToolName(\"get_status\"),\n        args\n      );\n\n      if (!result.success) {\n        return {\n          requestId: result.requestId,\n          success: false,\n          errorMessage: result.errorMessage,\n          taskId: taskId,\n          taskAction: \"\",\n          taskProduct: \"\",\n          taskStatus: \"failed\",\n        };\n      }\n      let queryResult: Record<string, any>;\n      try {\n        queryResult = JSON.parse(result.data);\n        const contentTaskId =\n          queryResult.taskId || queryResult.task_id || taskId;\n        const taskProduct = queryResult.result || queryResult.product || \"\";\n        const stream = Array.isArray(queryResult.stream)\n          ? queryResult.stream\n          : undefined;\n        const error = queryResult.error || undefined;\n        return {\n          requestId: result.requestId,\n          success: true,\n          errorMessage: \"\",\n          taskId: contentTaskId,\n          taskAction: queryResult.action || \"\",\n          taskProduct: taskProduct,\n          taskStatus: queryResult.status || \"completed\",\n          stream: stream,\n          error: error,\n        };\n      } catch (error) {\n        return {\n          requestId: result.requestId,\n          success: false,\n          errorMessage: `Failed to get task status: ${error}`,\n          taskId: taskId,\n          taskAction: \"\",\n          taskProduct: \"\",\n          taskStatus: \"failed\",\n        };\n      }\n    } catch (error) {\n      return {\n        requestId: \"\",\n        success: false,\n        errorMessage: `Failed to get task status: ${error}`,\n        taskId: taskId,\n        taskAction: \"\",\n        taskProduct: \"\",\n        taskStatus: \"failed\",\n      };\n    }\n  }\n\n  /**\n   * Terminate a task with a specified task ID.\n   */\n  async terminateTask(taskId: string): Promise<ExecutionResult> {\n    logDebug(\"Terminating task\");\n\n    try {\n      const args = { task_id: taskId };\n      const result = await this.session.callMcpTool(\n        this.getToolName(\"terminate\"),\n        args\n      );\n\n      let content: Record<string, any>;\n      try {\n        content = JSON.parse(result.data);\n      } catch (err) {\n        return {\n          requestId: result.requestId,\n          success: false,\n          errorMessage: `Failed to parse response: ${err}`,\n          taskId,\n          taskStatus: \"failed\",\n          taskResult: \"\",\n        };\n      }\n\n      const terminatedTaskId = content.taskId || content.task_id || taskId;\n      const status = content.status || \"cancelling\";\n\n      if (result.success) {\n        return {\n          requestId: result.requestId,\n          success: true,\n          errorMessage: \"\",\n          taskId: terminatedTaskId,\n          taskStatus: status,\n          taskResult: \"\",\n        };\n      }\n\n      return {\n        requestId: result.requestId,\n        success: false,\n        errorMessage: result.errorMessage,\n        taskId: terminatedTaskId,\n        taskStatus: status,\n        taskResult: \"\",\n      };\n    } catch (error) {\n      return {\n        requestId: \"\",\n        success: false,\n        errorMessage: `Failed to terminate: ${error}`,\n        taskId,\n        taskStatus: \"failed\",\n        taskResult: \"\",\n      };\n    }\n  }\n}\n\n/**\n * An Agent to manipulate applications to complete specific tasks.\n * According to the use scenary, The agent can a browser use agent which is\n * specialized for browser automation tasks, The agent also can be  a computer\n * use agent which is specialized for multiple applications automation tasks.\n */\nexport class Agent {\n  /**\n   * An instance of Computer Use Agent.\n   */\n  public computer: ComputerUseAgent;\n  /**\n   * An instance of Browser Use Agent.\n   */\n  public browser: BrowserUseAgent;\n  /**\n   * An instance of Mobile Use Agent.\n   */\n  public mobile: MobileUseAgent;\n\n  /**\n   * Initialize an Agent object.\n   *\n   * @param session - The Session instance that this Agent belongs to.\n   */\n  constructor(session: McpSession) {\n    this.computer = new ComputerUseAgent(session);\n    this.browser = new BrowserUseAgent(session);\n    this.mobile = new MobileUseAgent(session);\n  }\n}\n","import * as z from \"./v3/external.js\";\nexport * from \"./v3/external.js\";\nexport { z };\nexport default z;\n","export * from \"./errors.js\";\nexport * from \"./helpers/parseUtil.js\";\nexport * from \"./helpers/typeAliases.js\";\nexport * from \"./helpers/util.js\";\nexport * from \"./types.js\";\nexport * from \"./ZodError.js\";\n","import defaultErrorMap from \"./locales/en.js\";\nlet overrideErrorMap = defaultErrorMap;\nexport { defaultErrorMap };\nexport function setErrorMap(map) {\n    overrideErrorMap = map;\n}\nexport function getErrorMap() {\n    return overrideErrorMap;\n}\n","import { ZodIssueCode } from \"../ZodError.js\";\nimport { util, ZodParsedType } from \"../helpers/util.js\";\nconst errorMap = (issue, _ctx) => {\n    let message;\n    switch (issue.code) {\n        case ZodIssueCode.invalid_type:\n            if (issue.received === ZodParsedType.undefined) {\n                message = \"Required\";\n            }\n            else {\n                message = `Expected ${issue.expected}, received ${issue.received}`;\n            }\n            break;\n        case ZodIssueCode.invalid_literal:\n            message = `Invalid literal value, expected ${JSON.stringify(issue.expected, util.jsonStringifyReplacer)}`;\n            break;\n        case ZodIssueCode.unrecognized_keys:\n            message = `Unrecognized key(s) in object: ${util.joinValues(issue.keys, \", \")}`;\n            break;\n        case ZodIssueCode.invalid_union:\n            message = `Invalid input`;\n            break;\n        case ZodIssueCode.invalid_union_discriminator:\n            message = `Invalid discriminator value. Expected ${util.joinValues(issue.options)}`;\n            break;\n        case ZodIssueCode.invalid_enum_value:\n            message = `Invalid enum value. Expected ${util.joinValues(issue.options)}, received '${issue.received}'`;\n            break;\n        case ZodIssueCode.invalid_arguments:\n            message = `Invalid function arguments`;\n            break;\n        case ZodIssueCode.invalid_return_type:\n            message = `Invalid function return type`;\n            break;\n        case ZodIssueCode.invalid_date:\n            message = `Invalid date`;\n            break;\n        case ZodIssueCode.invalid_string:\n            if (typeof issue.validation === \"object\") {\n                if (\"includes\" in issue.validation) {\n                    message = `Invalid input: must include \"${issue.validation.includes}\"`;\n                    if (typeof issue.validation.position === \"number\") {\n                        message = `${message} at one or more positions greater than or equal to ${issue.validation.position}`;\n                    }\n                }\n                else if (\"startsWith\" in issue.validation) {\n                    message = `Invalid input: must start with \"${issue.validation.startsWith}\"`;\n                }\n                else if (\"endsWith\" in issue.validation) {\n                    message = `Invalid input: must end with \"${issue.validation.endsWith}\"`;\n                }\n                else {\n                    util.assertNever(issue.validation);\n                }\n            }\n            else if (issue.validation !== \"regex\") {\n                message = `Invalid ${issue.validation}`;\n            }\n            else {\n                message = \"Invalid\";\n            }\n            break;\n        case ZodIssueCode.too_small:\n            if (issue.type === \"array\")\n                message = `Array must contain ${issue.exact ? \"exactly\" : issue.inclusive ? `at least` : `more than`} ${issue.minimum} element(s)`;\n            else if (issue.type === \"string\")\n                message = `String must contain ${issue.exact ? \"exactly\" : issue.inclusive ? `at least` : `over`} ${issue.minimum} character(s)`;\n            else if (issue.type === \"number\")\n                message = `Number must be ${issue.exact ? `exactly equal to ` : issue.inclusive ? `greater than or equal to ` : `greater than `}${issue.minimum}`;\n            else if (issue.type === \"bigint\")\n                message = `Number must be ${issue.exact ? `exactly equal to ` : issue.inclusive ? `greater than or equal to ` : `greater than `}${issue.minimum}`;\n            else if (issue.type === \"date\")\n                message = `Date must be ${issue.exact ? `exactly equal to ` : issue.inclusive ? `greater than or equal to ` : `greater than `}${new Date(Number(issue.minimum))}`;\n            else\n                message = \"Invalid input\";\n            break;\n        case ZodIssueCode.too_big:\n            if (issue.type === \"array\")\n                message = `Array must contain ${issue.exact ? `exactly` : issue.inclusive ? `at most` : `less than`} ${issue.maximum} element(s)`;\n            else if (issue.type === \"string\")\n                message = `String must contain ${issue.exact ? `exactly` : issue.inclusive ? `at most` : `under`} ${issue.maximum} character(s)`;\n            else if (issue.type === \"number\")\n                message = `Number must be ${issue.exact ? `exactly` : issue.inclusive ? `less than or equal to` : `less than`} ${issue.maximum}`;\n            else if (issue.type === \"bigint\")\n                message = `BigInt must be ${issue.exact ? `exactly` : issue.inclusive ? `less than or equal to` : `less than`} ${issue.maximum}`;\n            else if (issue.type === \"date\")\n                message = `Date must be ${issue.exact ? `exactly` : issue.inclusive ? `smaller than or equal to` : `smaller than`} ${new Date(Number(issue.maximum))}`;\n            else\n                message = \"Invalid input\";\n            break;\n        case ZodIssueCode.custom:\n            message = `Invalid input`;\n            break;\n        case ZodIssueCode.invalid_intersection_types:\n            message = `Intersection results could not be merged`;\n            break;\n        case ZodIssueCode.not_multiple_of:\n            message = `Number must be a multiple of ${issue.multipleOf}`;\n            break;\n        case ZodIssueCode.not_finite:\n            message = \"Number must be finite\";\n            break;\n        default:\n            message = _ctx.defaultError;\n            util.assertNever(issue);\n    }\n    return { message };\n};\nexport default errorMap;\n","import { util } from \"./helpers/util.js\";\nexport const ZodIssueCode = util.arrayToEnum([\n    \"invalid_type\",\n    \"invalid_literal\",\n    \"custom\",\n    \"invalid_union\",\n    \"invalid_union_discriminator\",\n    \"invalid_enum_value\",\n    \"unrecognized_keys\",\n    \"invalid_arguments\",\n    \"invalid_return_type\",\n    \"invalid_date\",\n    \"invalid_string\",\n    \"too_small\",\n    \"too_big\",\n    \"invalid_intersection_types\",\n    \"not_multiple_of\",\n    \"not_finite\",\n]);\nexport const quotelessJson = (obj) => {\n    const json = JSON.stringify(obj, null, 2);\n    return json.replace(/\"([^\"]+)\":/g, \"$1:\");\n};\nexport class ZodError extends Error {\n    get errors() {\n        return this.issues;\n    }\n    constructor(issues) {\n        super();\n        this.issues = [];\n        this.addIssue = (sub) => {\n            this.issues = [...this.issues, sub];\n        };\n        this.addIssues = (subs = []) => {\n            this.issues = [...this.issues, ...subs];\n        };\n        const actualProto = new.target.prototype;\n        if (Object.setPrototypeOf) {\n            // eslint-disable-next-line ban/ban\n            Object.setPrototypeOf(this, actualProto);\n        }\n        else {\n            this.__proto__ = actualProto;\n        }\n        this.name = \"ZodError\";\n        this.issues = issues;\n    }\n    format(_mapper) {\n        const mapper = _mapper ||\n            function (issue) {\n                return issue.message;\n            };\n        const fieldErrors = { _errors: [] };\n        const processError = (error) => {\n            for (const issue of error.issues) {\n                if (issue.code === \"invalid_union\") {\n                    issue.unionErrors.map(processError);\n                }\n                else if (issue.code === \"invalid_return_type\") {\n                    processError(issue.returnTypeError);\n                }\n                else if (issue.code === \"invalid_arguments\") {\n                    processError(issue.argumentsError);\n                }\n                else if (issue.path.length === 0) {\n                    fieldErrors._errors.push(mapper(issue));\n                }\n                else {\n                    let curr = fieldErrors;\n                    let i = 0;\n                    while (i < issue.path.length) {\n                        const el = issue.path[i];\n                        const terminal = i === issue.path.length - 1;\n                        if (!terminal) {\n                            curr[el] = curr[el] || { _errors: [] };\n                            // if (typeof el === \"string\") {\n                            //   curr[el] = curr[el] || { _errors: [] };\n                            // } else if (typeof el === \"number\") {\n                            //   const errorArray: any = [];\n                            //   errorArray._errors = [];\n                            //   curr[el] = curr[el] || errorArray;\n                            // }\n                        }\n                        else {\n                            curr[el] = curr[el] || { _errors: [] };\n                            curr[el]._errors.push(mapper(issue));\n                        }\n                        curr = curr[el];\n                        i++;\n                    }\n                }\n            }\n        };\n        processError(this);\n        return fieldErrors;\n    }\n    static assert(value) {\n        if (!(value instanceof ZodError)) {\n            throw new Error(`Not a ZodError: ${value}`);\n        }\n    }\n    toString() {\n        return this.message;\n    }\n    get message() {\n        return JSON.stringify(this.issues, util.jsonStringifyReplacer, 2);\n    }\n    get isEmpty() {\n        return this.issues.length === 0;\n    }\n    flatten(mapper = (issue) => issue.message) {\n        const fieldErrors = {};\n        const formErrors = [];\n        for (const sub of this.issues) {\n            if (sub.path.length > 0) {\n                const firstEl = sub.path[0];\n                fieldErrors[firstEl] = fieldErrors[firstEl] || [];\n                fieldErrors[firstEl].push(mapper(sub));\n            }\n            else {\n                formErrors.push(mapper(sub));\n            }\n        }\n        return { formErrors, fieldErrors };\n    }\n    get formErrors() {\n        return this.flatten();\n    }\n}\nZodError.create = (issues) => {\n    const error = new ZodError(issues);\n    return error;\n};\n","export var util;\n(function (util) {\n    util.assertEqual = (_) => { };\n    function assertIs(_arg) { }\n    util.assertIs = assertIs;\n    function assertNever(_x) {\n        throw new Error();\n    }\n    util.assertNever = assertNever;\n    util.arrayToEnum = (items) => {\n        const obj = {};\n        for (const item of items) {\n            obj[item] = item;\n        }\n        return obj;\n    };\n    util.getValidEnumValues = (obj) => {\n        const validKeys = util.objectKeys(obj).filter((k) => typeof obj[obj[k]] !== \"number\");\n        const filtered = {};\n        for (const k of validKeys) {\n            filtered[k] = obj[k];\n        }\n        return util.objectValues(filtered);\n    };\n    util.objectValues = (obj) => {\n        return util.objectKeys(obj).map(function (e) {\n            return obj[e];\n        });\n    };\n    util.objectKeys = typeof Object.keys === \"function\" // eslint-disable-line ban/ban\n        ? (obj) => Object.keys(obj) // eslint-disable-line ban/ban\n        : (object) => {\n            const keys = [];\n            for (const key in object) {\n                if (Object.prototype.hasOwnProperty.call(object, key)) {\n                    keys.push(key);\n                }\n            }\n            return keys;\n        };\n    util.find = (arr, checker) => {\n        for (const item of arr) {\n            if (checker(item))\n                return item;\n        }\n        return undefined;\n    };\n    util.isInteger = typeof Number.isInteger === \"function\"\n        ? (val) => Number.isInteger(val) // eslint-disable-line ban/ban\n        : (val) => typeof val === \"number\" && Number.isFinite(val) && Math.floor(val) === val;\n    function joinValues(array, separator = \" | \") {\n        return array.map((val) => (typeof val === \"string\" ? `'${val}'` : val)).join(separator);\n    }\n    util.joinValues = joinValues;\n    util.jsonStringifyReplacer = (_, value) => {\n        if (typeof value === \"bigint\") {\n            return value.toString();\n        }\n        return value;\n    };\n})(util || (util = {}));\nexport var objectUtil;\n(function (objectUtil) {\n    objectUtil.mergeShapes = (first, second) => {\n        return {\n            ...first,\n            ...second, // second overwrites first\n        };\n    };\n})(objectUtil || (objectUtil = {}));\nexport const ZodParsedType = util.arrayToEnum([\n    \"string\",\n    \"nan\",\n    \"number\",\n    \"integer\",\n    \"float\",\n    \"boolean\",\n    \"date\",\n    \"bigint\",\n    \"symbol\",\n    \"function\",\n    \"undefined\",\n    \"null\",\n    \"array\",\n    \"object\",\n    \"unknown\",\n    \"promise\",\n    \"void\",\n    \"never\",\n    \"map\",\n    \"set\",\n]);\nexport const getParsedType = (data) => {\n    const t = typeof data;\n    switch (t) {\n        case \"undefined\":\n            return ZodParsedType.undefined;\n        case \"string\":\n            return ZodParsedType.string;\n        case \"number\":\n            return Number.isNaN(data) ? ZodParsedType.nan : ZodParsedType.number;\n        case \"boolean\":\n            return ZodParsedType.boolean;\n        case \"function\":\n            return ZodParsedType.function;\n        case \"bigint\":\n            return ZodParsedType.bigint;\n        case \"symbol\":\n            return ZodParsedType.symbol;\n        case \"object\":\n            if (Array.isArray(data)) {\n                return ZodParsedType.array;\n            }\n            if (data === null) {\n                return ZodParsedType.null;\n            }\n            if (data.then && typeof data.then === \"function\" && data.catch && typeof data.catch === \"function\") {\n                return ZodParsedType.promise;\n            }\n            if (typeof Map !== \"undefined\" && data instanceof Map) {\n                return ZodParsedType.map;\n            }\n            if (typeof Set !== \"undefined\" && data instanceof Set) {\n                return ZodParsedType.set;\n            }\n            if (typeof Date !== \"undefined\" && data instanceof Date) {\n                return ZodParsedType.date;\n            }\n            return ZodParsedType.object;\n        default:\n            return ZodParsedType.unknown;\n    }\n};\n","import { getErrorMap } from \"../errors.js\";\nimport defaultErrorMap from \"../locales/en.js\";\nexport const makeIssue = (params) => {\n    const { data, path, errorMaps, issueData } = params;\n    const fullPath = [...path, ...(issueData.path || [])];\n    const fullIssue = {\n        ...issueData,\n        path: fullPath,\n    };\n    if (issueData.message !== undefined) {\n        return {\n            ...issueData,\n            path: fullPath,\n            message: issueData.message,\n        };\n    }\n    let errorMessage = \"\";\n    const maps = errorMaps\n        .filter((m) => !!m)\n        .slice()\n        .reverse();\n    for (const map of maps) {\n        errorMessage = map(fullIssue, { data, defaultError: errorMessage }).message;\n    }\n    return {\n        ...issueData,\n        path: fullPath,\n        message: errorMessage,\n    };\n};\nexport const EMPTY_PATH = [];\nexport function addIssueToContext(ctx, issueData) {\n    const overrideMap = getErrorMap();\n    const issue = makeIssue({\n        issueData: issueData,\n        data: ctx.data,\n        path: ctx.path,\n        errorMaps: [\n            ctx.common.contextualErrorMap, // contextual error map is first priority\n            ctx.schemaErrorMap, // then schema-bound map if available\n            overrideMap, // then global override map\n            overrideMap === defaultErrorMap ? undefined : defaultErrorMap, // then global default map\n        ].filter((x) => !!x),\n    });\n    ctx.common.issues.push(issue);\n}\nexport class ParseStatus {\n    constructor() {\n        this.value = \"valid\";\n    }\n    dirty() {\n        if (this.value === \"valid\")\n            this.value = \"dirty\";\n    }\n    abort() {\n        if (this.value !== \"aborted\")\n            this.value = \"aborted\";\n    }\n    static mergeArray(status, results) {\n        const arrayValue = [];\n        for (const s of results) {\n            if (s.status === \"aborted\")\n                return INVALID;\n            if (s.status === \"dirty\")\n                status.dirty();\n            arrayValue.push(s.value);\n        }\n        return { status: status.value, value: arrayValue };\n    }\n    static async mergeObjectAsync(status, pairs) {\n        const syncPairs = [];\n        for (const pair of pairs) {\n            const key = await pair.key;\n            const value = await pair.value;\n            syncPairs.push({\n                key,\n                value,\n            });\n        }\n        return ParseStatus.mergeObjectSync(status, syncPairs);\n    }\n    static mergeObjectSync(status, pairs) {\n        const finalObject = {};\n        for (const pair of pairs) {\n            const { key, value } = pair;\n            if (key.status === \"aborted\")\n                return INVALID;\n            if (value.status === \"aborted\")\n                return INVALID;\n            if (key.status === \"dirty\")\n                status.dirty();\n            if (value.status === \"dirty\")\n                status.dirty();\n            if (key.value !== \"__proto__\" && (typeof value.value !== \"undefined\" || pair.alwaysSet)) {\n                finalObject[key.value] = value.value;\n            }\n        }\n        return { status: status.value, value: finalObject };\n    }\n}\nexport const INVALID = Object.freeze({\n    status: \"aborted\",\n});\nexport const DIRTY = (value) => ({ status: \"dirty\", value });\nexport const OK = (value) => ({ status: \"valid\", value });\nexport const isAborted = (x) => x.status === \"aborted\";\nexport const isDirty = (x) => x.status === \"dirty\";\nexport const isValid = (x) => x.status === \"valid\";\nexport const isAsync = (x) => typeof Promise !== \"undefined\" && x instanceof Promise;\n","import { ZodError, ZodIssueCode, } from \"./ZodError.js\";\nimport { defaultErrorMap, getErrorMap } from \"./errors.js\";\nimport { errorUtil } from \"./helpers/errorUtil.js\";\nimport { DIRTY, INVALID, OK, ParseStatus, addIssueToContext, isAborted, isAsync, isDirty, isValid, makeIssue, } from \"./helpers/parseUtil.js\";\nimport { util, ZodParsedType, getParsedType } from \"./helpers/util.js\";\nclass ParseInputLazyPath {\n    constructor(parent, value, path, key) {\n        this._cachedPath = [];\n        this.parent = parent;\n        this.data = value;\n        this._path = path;\n        this._key = key;\n    }\n    get path() {\n        if (!this._cachedPath.length) {\n            if (Array.isArray(this._key)) {\n                this._cachedPath.push(...this._path, ...this._key);\n            }\n            else {\n                this._cachedPath.push(...this._path, this._key);\n            }\n        }\n        return this._cachedPath;\n    }\n}\nconst handleResult = (ctx, result) => {\n    if (isValid(result)) {\n        return { success: true, data: result.value };\n    }\n    else {\n        if (!ctx.common.issues.length) {\n            throw new Error(\"Validation failed but no issues detected.\");\n        }\n        return {\n            success: false,\n            get error() {\n                if (this._error)\n                    return this._error;\n                const error = new ZodError(ctx.common.issues);\n                this._error = error;\n                return this._error;\n            },\n        };\n    }\n};\nfunction processCreateParams(params) {\n    if (!params)\n        return {};\n    const { errorMap, invalid_type_error, required_error, description } = params;\n    if (errorMap && (invalid_type_error || required_error)) {\n        throw new Error(`Can't use \"invalid_type_error\" or \"required_error\" in conjunction with custom error map.`);\n    }\n    if (errorMap)\n        return { errorMap: errorMap, description };\n    const customMap = (iss, ctx) => {\n        const { message } = params;\n        if (iss.code === \"invalid_enum_value\") {\n            return { message: message ?? ctx.defaultError };\n        }\n        if (typeof ctx.data === \"undefined\") {\n            return { message: message ?? required_error ?? ctx.defaultError };\n        }\n        if (iss.code !== \"invalid_type\")\n            return { message: ctx.defaultError };\n        return { message: message ?? invalid_type_error ?? ctx.defaultError };\n    };\n    return { errorMap: customMap, description };\n}\nexport class ZodType {\n    get description() {\n        return this._def.description;\n    }\n    _getType(input) {\n        return getParsedType(input.data);\n    }\n    _getOrReturnCtx(input, ctx) {\n        return (ctx || {\n            common: input.parent.common,\n            data: input.data,\n            parsedType: getParsedType(input.data),\n            schemaErrorMap: this._def.errorMap,\n            path: input.path,\n            parent: input.parent,\n        });\n    }\n    _processInputParams(input) {\n        return {\n            status: new ParseStatus(),\n            ctx: {\n                common: input.parent.common,\n                data: input.data,\n                parsedType: getParsedType(input.data),\n                schemaErrorMap: this._def.errorMap,\n                path: input.path,\n                parent: input.parent,\n            },\n        };\n    }\n    _parseSync(input) {\n        const result = this._parse(input);\n        if (isAsync(result)) {\n            throw new Error(\"Synchronous parse encountered promise.\");\n        }\n        return result;\n    }\n    _parseAsync(input) {\n        const result = this._parse(input);\n        return Promise.resolve(result);\n    }\n    parse(data, params) {\n        const result = this.safeParse(data, params);\n        if (result.success)\n            return result.data;\n        throw result.error;\n    }\n    safeParse(data, params) {\n        const ctx = {\n            common: {\n                issues: [],\n                async: params?.async ?? false,\n                contextualErrorMap: params?.errorMap,\n            },\n            path: params?.path || [],\n            schemaErrorMap: this._def.errorMap,\n            parent: null,\n            data,\n            parsedType: getParsedType(data),\n        };\n        const result = this._parseSync({ data, path: ctx.path, parent: ctx });\n        return handleResult(ctx, result);\n    }\n    \"~validate\"(data) {\n        const ctx = {\n            common: {\n                issues: [],\n                async: !!this[\"~standard\"].async,\n            },\n            path: [],\n            schemaErrorMap: this._def.errorMap,\n            parent: null,\n            data,\n            parsedType: getParsedType(data),\n        };\n        if (!this[\"~standard\"].async) {\n            try {\n                const result = this._parseSync({ data, path: [], parent: ctx });\n                return isValid(result)\n                    ? {\n                        value: result.value,\n                    }\n                    : {\n                        issues: ctx.common.issues,\n                    };\n            }\n            catch (err) {\n                if (err?.message?.toLowerCase()?.includes(\"encountered\")) {\n                    this[\"~standard\"].async = true;\n                }\n                ctx.common = {\n                    issues: [],\n                    async: true,\n                };\n            }\n        }\n        return this._parseAsync({ data, path: [], parent: ctx }).then((result) => isValid(result)\n            ? {\n                value: result.value,\n            }\n            : {\n                issues: ctx.common.issues,\n            });\n    }\n    async parseAsync(data, params) {\n        const result = await this.safeParseAsync(data, params);\n        if (result.success)\n            return result.data;\n        throw result.error;\n    }\n    async safeParseAsync(data, params) {\n        const ctx = {\n            common: {\n                issues: [],\n                contextualErrorMap: params?.errorMap,\n                async: true,\n            },\n            path: params?.path || [],\n            schemaErrorMap: this._def.errorMap,\n            parent: null,\n            data,\n            parsedType: getParsedType(data),\n        };\n        const maybeAsyncResult = this._parse({ data, path: ctx.path, parent: ctx });\n        const result = await (isAsync(maybeAsyncResult) ? maybeAsyncResult : Promise.resolve(maybeAsyncResult));\n        return handleResult(ctx, result);\n    }\n    refine(check, message) {\n        const getIssueProperties = (val) => {\n            if (typeof message === \"string\" || typeof message === \"undefined\") {\n                return { message };\n            }\n            else if (typeof message === \"function\") {\n                return message(val);\n            }\n            else {\n                return message;\n            }\n        };\n        return this._refinement((val, ctx) => {\n            const result = check(val);\n            const setError = () => ctx.addIssue({\n                code: ZodIssueCode.custom,\n                ...getIssueProperties(val),\n            });\n            if (typeof Promise !== \"undefined\" && result instanceof Promise) {\n                return result.then((data) => {\n                    if (!data) {\n                        setError();\n                        return false;\n                    }\n                    else {\n                        return true;\n                    }\n                });\n            }\n            if (!result) {\n                setError();\n                return false;\n            }\n            else {\n                return true;\n            }\n        });\n    }\n    refinement(check, refinementData) {\n        return this._refinement((val, ctx) => {\n            if (!check(val)) {\n                ctx.addIssue(typeof refinementData === \"function\" ? refinementData(val, ctx) : refinementData);\n                return false;\n            }\n            else {\n                return true;\n            }\n        });\n    }\n    _refinement(refinement) {\n        return new ZodEffects({\n            schema: this,\n            typeName: ZodFirstPartyTypeKind.ZodEffects,\n            effect: { type: \"refinement\", refinement },\n        });\n    }\n    superRefine(refinement) {\n        return this._refinement(refinement);\n    }\n    constructor(def) {\n        /** Alias of safeParseAsync */\n        this.spa = this.safeParseAsync;\n        this._def = def;\n        this.parse = this.parse.bind(this);\n        this.safeParse = this.safeParse.bind(this);\n        this.parseAsync = this.parseAsync.bind(this);\n        this.safeParseAsync = this.safeParseAsync.bind(this);\n        this.spa = this.spa.bind(this);\n        this.refine = this.refine.bind(this);\n        this.refinement = this.refinement.bind(this);\n        this.superRefine = this.superRefine.bind(this);\n        this.optional = this.optional.bind(this);\n        this.nullable = this.nullable.bind(this);\n        this.nullish = this.nullish.bind(this);\n        this.array = this.array.bind(this);\n        this.promise = this.promise.bind(this);\n        this.or = this.or.bind(this);\n        this.and = this.and.bind(this);\n        this.transform = this.transform.bind(this);\n        this.brand = this.brand.bind(this);\n        this.default = this.default.bind(this);\n        this.catch = this.catch.bind(this);\n        this.describe = this.describe.bind(this);\n        this.pipe = this.pipe.bind(this);\n        this.readonly = this.readonly.bind(this);\n        this.isNullable = this.isNullable.bind(this);\n        this.isOptional = this.isOptional.bind(this);\n        this[\"~standard\"] = {\n            version: 1,\n            vendor: \"zod\",\n            validate: (data) => this[\"~validate\"](data),\n        };\n    }\n    optional() {\n        return ZodOptional.create(this, this._def);\n    }\n    nullable() {\n        return ZodNullable.create(this, this._def);\n    }\n    nullish() {\n        return this.nullable().optional();\n    }\n    array() {\n        return ZodArray.create(this);\n    }\n    promise() {\n        return ZodPromise.create(this, this._def);\n    }\n    or(option) {\n        return ZodUnion.create([this, option], this._def);\n    }\n    and(incoming) {\n        return ZodIntersection.create(this, incoming, this._def);\n    }\n    transform(transform) {\n        return new ZodEffects({\n            ...processCreateParams(this._def),\n            schema: this,\n            typeName: ZodFirstPartyTypeKind.ZodEffects,\n            effect: { type: \"transform\", transform },\n        });\n    }\n    default(def) {\n        const defaultValueFunc = typeof def === \"function\" ? def : () => def;\n        return new ZodDefault({\n            ...processCreateParams(this._def),\n            innerType: this,\n            defaultValue: defaultValueFunc,\n            typeName: ZodFirstPartyTypeKind.ZodDefault,\n        });\n    }\n    brand() {\n        return new ZodBranded({\n            typeName: ZodFirstPartyTypeKind.ZodBranded,\n            type: this,\n            ...processCreateParams(this._def),\n        });\n    }\n    catch(def) {\n        const catchValueFunc = typeof def === \"function\" ? def : () => def;\n        return new ZodCatch({\n            ...processCreateParams(this._def),\n            innerType: this,\n            catchValue: catchValueFunc,\n            typeName: ZodFirstPartyTypeKind.ZodCatch,\n        });\n    }\n    describe(description) {\n        const This = this.constructor;\n        return new This({\n            ...this._def,\n            description,\n        });\n    }\n    pipe(target) {\n        return ZodPipeline.create(this, target);\n    }\n    readonly() {\n        return ZodReadonly.create(this);\n    }\n    isOptional() {\n        return this.safeParse(undefined).success;\n    }\n    isNullable() {\n        return this.safeParse(null).success;\n    }\n}\nconst cuidRegex = /^c[^\\s-]{8,}$/i;\nconst cuid2Regex = /^[0-9a-z]+$/;\nconst ulidRegex = /^[0-9A-HJKMNP-TV-Z]{26}$/i;\n// const uuidRegex =\n//   /^([a-f0-9]{8}-[a-f0-9]{4}-[1-5][a-f0-9]{3}-[a-f0-9]{4}-[a-f0-9]{12}|00000000-0000-0000-0000-000000000000)$/i;\nconst uuidRegex = /^[0-9a-fA-F]{8}\\b-[0-9a-fA-F]{4}\\b-[0-9a-fA-F]{4}\\b-[0-9a-fA-F]{4}\\b-[0-9a-fA-F]{12}$/i;\nconst nanoidRegex = /^[a-z0-9_-]{21}$/i;\nconst jwtRegex = /^[A-Za-z0-9-_]+\\.[A-Za-z0-9-_]+\\.[A-Za-z0-9-_]*$/;\nconst durationRegex = /^[-+]?P(?!$)(?:(?:[-+]?\\d+Y)|(?:[-+]?\\d+[.,]\\d+Y$))?(?:(?:[-+]?\\d+M)|(?:[-+]?\\d+[.,]\\d+M$))?(?:(?:[-+]?\\d+W)|(?:[-+]?\\d+[.,]\\d+W$))?(?:(?:[-+]?\\d+D)|(?:[-+]?\\d+[.,]\\d+D$))?(?:T(?=[\\d+-])(?:(?:[-+]?\\d+H)|(?:[-+]?\\d+[.,]\\d+H$))?(?:(?:[-+]?\\d+M)|(?:[-+]?\\d+[.,]\\d+M$))?(?:[-+]?\\d+(?:[.,]\\d+)?S)?)??$/;\n// from https://stackoverflow.com/a/46181/1550155\n// old version: too slow, didn't support unicode\n// const emailRegex = /^((([a-z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])+(\\.([a-z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])+)*)|((\\x22)((((\\x20|\\x09)*(\\x0d\\x0a))?(\\x20|\\x09)+)?(([\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f]|\\x21|[\\x23-\\x5b]|[\\x5d-\\x7e]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(\\\\([\\x01-\\x09\\x0b\\x0c\\x0d-\\x7f]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF]))))*(((\\x20|\\x09)*(\\x0d\\x0a))?(\\x20|\\x09)+)?(\\x22)))@((([a-z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(([a-z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])([a-z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])*([a-z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])))\\.)+(([a-z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(([a-z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])([a-z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])*([a-z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])))$/i;\n//old email regex\n// const emailRegex = /^(([^<>()[\\].,;:\\s@\"]+(\\.[^<>()[\\].,;:\\s@\"]+)*)|(\".+\"))@((?!-)([^<>()[\\].,;:\\s@\"]+\\.)+[^<>()[\\].,;:\\s@\"]{1,})[^-<>()[\\].,;:\\s@\"]$/i;\n// eslint-disable-next-line\n// const emailRegex =\n//   /^(([^<>()[\\]\\\\.,;:\\s@\\\"]+(\\.[^<>()[\\]\\\\.,;:\\s@\\\"]+)*)|(\\\".+\\\"))@((\\[(((25[0-5])|(2[0-4][0-9])|(1[0-9]{2})|([0-9]{1,2}))\\.){3}((25[0-5])|(2[0-4][0-9])|(1[0-9]{2})|([0-9]{1,2}))\\])|(\\[IPv6:(([a-f0-9]{1,4}:){7}|::([a-f0-9]{1,4}:){0,6}|([a-f0-9]{1,4}:){1}:([a-f0-9]{1,4}:){0,5}|([a-f0-9]{1,4}:){2}:([a-f0-9]{1,4}:){0,4}|([a-f0-9]{1,4}:){3}:([a-f0-9]{1,4}:){0,3}|([a-f0-9]{1,4}:){4}:([a-f0-9]{1,4}:){0,2}|([a-f0-9]{1,4}:){5}:([a-f0-9]{1,4}:){0,1})([a-f0-9]{1,4}|(((25[0-5])|(2[0-4][0-9])|(1[0-9]{2})|([0-9]{1,2}))\\.){3}((25[0-5])|(2[0-4][0-9])|(1[0-9]{2})|([0-9]{1,2})))\\])|([A-Za-z0-9]([A-Za-z0-9-]*[A-Za-z0-9])*(\\.[A-Za-z]{2,})+))$/;\n// const emailRegex =\n//   /^[a-zA-Z0-9\\.\\!\\#\\$\\%\\&\\'\\*\\+\\/\\=\\?\\^\\_\\`\\{\\|\\}\\~\\-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/;\n// const emailRegex =\n//   /^(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|\"(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21\\x23-\\x5b\\x5d-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])*\")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21-\\x5a\\x53-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])+)\\])$/i;\nconst emailRegex = /^(?!\\.)(?!.*\\.\\.)([A-Z0-9_'+\\-\\.]*)[A-Z0-9_+-]@([A-Z0-9][A-Z0-9\\-]*\\.)+[A-Z]{2,}$/i;\n// const emailRegex =\n//   /^[a-z0-9.!#$%&’*+/=?^_`{|}~-]+@[a-z0-9-]+(?:\\.[a-z0-9\\-]+)*$/i;\n// from https://thekevinscott.com/emojis-in-javascript/#writing-a-regular-expression\nconst _emojiRegex = `^(\\\\p{Extended_Pictographic}|\\\\p{Emoji_Component})+$`;\nlet emojiRegex;\n// faster, simpler, safer\nconst ipv4Regex = /^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])$/;\nconst ipv4CidrRegex = /^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\\/(3[0-2]|[12]?[0-9])$/;\n// const ipv6Regex =\n// /^(([a-f0-9]{1,4}:){7}|::([a-f0-9]{1,4}:){0,6}|([a-f0-9]{1,4}:){1}:([a-f0-9]{1,4}:){0,5}|([a-f0-9]{1,4}:){2}:([a-f0-9]{1,4}:){0,4}|([a-f0-9]{1,4}:){3}:([a-f0-9]{1,4}:){0,3}|([a-f0-9]{1,4}:){4}:([a-f0-9]{1,4}:){0,2}|([a-f0-9]{1,4}:){5}:([a-f0-9]{1,4}:){0,1})([a-f0-9]{1,4}|(((25[0-5])|(2[0-4][0-9])|(1[0-9]{2})|([0-9]{1,2}))\\.){3}((25[0-5])|(2[0-4][0-9])|(1[0-9]{2})|([0-9]{1,2})))$/;\nconst ipv6Regex = /^(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))$/;\nconst ipv6CidrRegex = /^(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))\\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])$/;\n// https://stackoverflow.com/questions/7860392/determine-if-string-is-in-base64-using-javascript\nconst base64Regex = /^([0-9a-zA-Z+/]{4})*(([0-9a-zA-Z+/]{2}==)|([0-9a-zA-Z+/]{3}=))?$/;\n// https://base64.guru/standards/base64url\nconst base64urlRegex = /^([0-9a-zA-Z-_]{4})*(([0-9a-zA-Z-_]{2}(==)?)|([0-9a-zA-Z-_]{3}(=)?))?$/;\n// simple\n// const dateRegexSource = `\\\\d{4}-\\\\d{2}-\\\\d{2}`;\n// no leap year validation\n// const dateRegexSource = `\\\\d{4}-((0[13578]|10|12)-31|(0[13-9]|1[0-2])-30|(0[1-9]|1[0-2])-(0[1-9]|1\\\\d|2\\\\d))`;\n// with leap year validation\nconst dateRegexSource = `((\\\\d\\\\d[2468][048]|\\\\d\\\\d[13579][26]|\\\\d\\\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\\\d{4}-((0[13578]|1[02])-(0[1-9]|[12]\\\\d|3[01])|(0[469]|11)-(0[1-9]|[12]\\\\d|30)|(02)-(0[1-9]|1\\\\d|2[0-8])))`;\nconst dateRegex = new RegExp(`^${dateRegexSource}$`);\nfunction timeRegexSource(args) {\n    let secondsRegexSource = `[0-5]\\\\d`;\n    if (args.precision) {\n        secondsRegexSource = `${secondsRegexSource}\\\\.\\\\d{${args.precision}}`;\n    }\n    else if (args.precision == null) {\n        secondsRegexSource = `${secondsRegexSource}(\\\\.\\\\d+)?`;\n    }\n    const secondsQuantifier = args.precision ? \"+\" : \"?\"; // require seconds if precision is nonzero\n    return `([01]\\\\d|2[0-3]):[0-5]\\\\d(:${secondsRegexSource})${secondsQuantifier}`;\n}\nfunction timeRegex(args) {\n    return new RegExp(`^${timeRegexSource(args)}$`);\n}\n// Adapted from https://stackoverflow.com/a/3143231\nexport function datetimeRegex(args) {\n    let regex = `${dateRegexSource}T${timeRegexSource(args)}`;\n    const opts = [];\n    opts.push(args.local ? `Z?` : `Z`);\n    if (args.offset)\n        opts.push(`([+-]\\\\d{2}:?\\\\d{2})`);\n    regex = `${regex}(${opts.join(\"|\")})`;\n    return new RegExp(`^${regex}$`);\n}\nfunction isValidIP(ip, version) {\n    if ((version === \"v4\" || !version) && ipv4Regex.test(ip)) {\n        return true;\n    }\n    if ((version === \"v6\" || !version) && ipv6Regex.test(ip)) {\n        return true;\n    }\n    return false;\n}\nfunction isValidJWT(jwt, alg) {\n    if (!jwtRegex.test(jwt))\n        return false;\n    try {\n        const [header] = jwt.split(\".\");\n        if (!header)\n            return false;\n        // Convert base64url to base64\n        const base64 = header\n            .replace(/-/g, \"+\")\n            .replace(/_/g, \"/\")\n            .padEnd(header.length + ((4 - (header.length % 4)) % 4), \"=\");\n        const decoded = JSON.parse(atob(base64));\n        if (typeof decoded !== \"object\" || decoded === null)\n            return false;\n        if (\"typ\" in decoded && decoded?.typ !== \"JWT\")\n            return false;\n        if (!decoded.alg)\n            return false;\n        if (alg && decoded.alg !== alg)\n            return false;\n        return true;\n    }\n    catch {\n        return false;\n    }\n}\nfunction isValidCidr(ip, version) {\n    if ((version === \"v4\" || !version) && ipv4CidrRegex.test(ip)) {\n        return true;\n    }\n    if ((version === \"v6\" || !version) && ipv6CidrRegex.test(ip)) {\n        return true;\n    }\n    return false;\n}\nexport class ZodString extends ZodType {\n    _parse(input) {\n        if (this._def.coerce) {\n            input.data = String(input.data);\n        }\n        const parsedType = this._getType(input);\n        if (parsedType !== ZodParsedType.string) {\n            const ctx = this._getOrReturnCtx(input);\n            addIssueToContext(ctx, {\n                code: ZodIssueCode.invalid_type,\n                expected: ZodParsedType.string,\n                received: ctx.parsedType,\n            });\n            return INVALID;\n        }\n        const status = new ParseStatus();\n        let ctx = undefined;\n        for (const check of this._def.checks) {\n            if (check.kind === \"min\") {\n                if (input.data.length < check.value) {\n                    ctx = this._getOrReturnCtx(input, ctx);\n                    addIssueToContext(ctx, {\n                        code: ZodIssueCode.too_small,\n                        minimum: check.value,\n                        type: \"string\",\n                        inclusive: true,\n                        exact: false,\n                        message: check.message,\n                    });\n                    status.dirty();\n                }\n            }\n            else if (check.kind === \"max\") {\n                if (input.data.length > check.value) {\n                    ctx = this._getOrReturnCtx(input, ctx);\n                    addIssueToContext(ctx, {\n                        code: ZodIssueCode.too_big,\n                        maximum: check.value,\n                        type: \"string\",\n                        inclusive: true,\n                        exact: false,\n                        message: check.message,\n                    });\n                    status.dirty();\n                }\n            }\n            else if (check.kind === \"length\") {\n                const tooBig = input.data.length > check.value;\n                const tooSmall = input.data.length < check.value;\n                if (tooBig || tooSmall) {\n                    ctx = this._getOrReturnCtx(input, ctx);\n                    if (tooBig) {\n                        addIssueToContext(ctx, {\n                            code: ZodIssueCode.too_big,\n                            maximum: check.value,\n                            type: \"string\",\n                            inclusive: true,\n                            exact: true,\n                            message: check.message,\n                        });\n                    }\n                    else if (tooSmall) {\n                        addIssueToContext(ctx, {\n                            code: ZodIssueCode.too_small,\n                            minimum: check.value,\n                            type: \"string\",\n                            inclusive: true,\n                            exact: true,\n                            message: check.message,\n                        });\n                    }\n                    status.dirty();\n                }\n            }\n            else if (check.kind === \"email\") {\n                if (!emailRegex.test(input.data)) {\n                    ctx = this._getOrReturnCtx(input, ctx);\n                    addIssueToContext(ctx, {\n                        validation: \"email\",\n                        code: ZodIssueCode.invalid_string,\n                        message: check.message,\n                    });\n                    status.dirty();\n                }\n            }\n            else if (check.kind === \"emoji\") {\n                if (!emojiRegex) {\n                    emojiRegex = new RegExp(_emojiRegex, \"u\");\n                }\n                if (!emojiRegex.test(input.data)) {\n                    ctx = this._getOrReturnCtx(input, ctx);\n                    addIssueToContext(ctx, {\n                        validation: \"emoji\",\n                        code: ZodIssueCode.invalid_string,\n                        message: check.message,\n                    });\n                    status.dirty();\n                }\n            }\n            else if (check.kind === \"uuid\") {\n                if (!uuidRegex.test(input.data)) {\n                    ctx = this._getOrReturnCtx(input, ctx);\n                    addIssueToContext(ctx, {\n                        validation: \"uuid\",\n                        code: ZodIssueCode.invalid_string,\n                        message: check.message,\n                    });\n                    status.dirty();\n                }\n            }\n            else if (check.kind === \"nanoid\") {\n                if (!nanoidRegex.test(input.data)) {\n                    ctx = this._getOrReturnCtx(input, ctx);\n                    addIssueToContext(ctx, {\n                        validation: \"nanoid\",\n                        code: ZodIssueCode.invalid_string,\n                        message: check.message,\n                    });\n                    status.dirty();\n                }\n            }\n            else if (check.kind === \"cuid\") {\n                if (!cuidRegex.test(input.data)) {\n                    ctx = this._getOrReturnCtx(input, ctx);\n                    addIssueToContext(ctx, {\n                        validation: \"cuid\",\n                        code: ZodIssueCode.invalid_string,\n                        message: check.message,\n                    });\n                    status.dirty();\n                }\n            }\n            else if (check.kind === \"cuid2\") {\n                if (!cuid2Regex.test(input.data)) {\n                    ctx = this._getOrReturnCtx(input, ctx);\n                    addIssueToContext(ctx, {\n                        validation: \"cuid2\",\n                        code: ZodIssueCode.invalid_string,\n                        message: check.message,\n                    });\n                    status.dirty();\n                }\n            }\n            else if (check.kind === \"ulid\") {\n                if (!ulidRegex.test(input.data)) {\n                    ctx = this._getOrReturnCtx(input, ctx);\n                    addIssueToContext(ctx, {\n                        validation: \"ulid\",\n                        code: ZodIssueCode.invalid_string,\n                        message: check.message,\n                    });\n                    status.dirty();\n                }\n            }\n            else if (check.kind === \"url\") {\n                try {\n                    new URL(input.data);\n                }\n                catch {\n                    ctx = this._getOrReturnCtx(input, ctx);\n                    addIssueToContext(ctx, {\n                        validation: \"url\",\n                        code: ZodIssueCode.invalid_string,\n                        message: check.message,\n                    });\n                    status.dirty();\n                }\n            }\n            else if (check.kind === \"regex\") {\n                check.regex.lastIndex = 0;\n                const testResult = check.regex.test(input.data);\n                if (!testResult) {\n                    ctx = this._getOrReturnCtx(input, ctx);\n                    addIssueToContext(ctx, {\n                        validation: \"regex\",\n                        code: ZodIssueCode.invalid_string,\n                        message: check.message,\n                    });\n                    status.dirty();\n                }\n            }\n            else if (check.kind === \"trim\") {\n                input.data = input.data.trim();\n            }\n            else if (check.kind === \"includes\") {\n                if (!input.data.includes(check.value, check.position)) {\n                    ctx = this._getOrReturnCtx(input, ctx);\n                    addIssueToContext(ctx, {\n                        code: ZodIssueCode.invalid_string,\n                        validation: { includes: check.value, position: check.position },\n                        message: check.message,\n                    });\n                    status.dirty();\n                }\n            }\n            else if (check.kind === \"toLowerCase\") {\n                input.data = input.data.toLowerCase();\n            }\n            else if (check.kind === \"toUpperCase\") {\n                input.data = input.data.toUpperCase();\n            }\n            else if (check.kind === \"startsWith\") {\n                if (!input.data.startsWith(check.value)) {\n                    ctx = this._getOrReturnCtx(input, ctx);\n                    addIssueToContext(ctx, {\n                        code: ZodIssueCode.invalid_string,\n                        validation: { startsWith: check.value },\n                        message: check.message,\n                    });\n                    status.dirty();\n                }\n            }\n            else if (check.kind === \"endsWith\") {\n                if (!input.data.endsWith(check.value)) {\n                    ctx = this._getOrReturnCtx(input, ctx);\n                    addIssueToContext(ctx, {\n                        code: ZodIssueCode.invalid_string,\n                        validation: { endsWith: check.value },\n                        message: check.message,\n                    });\n                    status.dirty();\n                }\n            }\n            else if (check.kind === \"datetime\") {\n                const regex = datetimeRegex(check);\n                if (!regex.test(input.data)) {\n                    ctx = this._getOrReturnCtx(input, ctx);\n                    addIssueToContext(ctx, {\n                        code: ZodIssueCode.invalid_string,\n                        validation: \"datetime\",\n                        message: check.message,\n                    });\n                    status.dirty();\n                }\n            }\n            else if (check.kind === \"date\") {\n                const regex = dateRegex;\n                if (!regex.test(input.data)) {\n                    ctx = this._getOrReturnCtx(input, ctx);\n                    addIssueToContext(ctx, {\n                        code: ZodIssueCode.invalid_string,\n                        validation: \"date\",\n                        message: check.message,\n                    });\n                    status.dirty();\n                }\n            }\n            else if (check.kind === \"time\") {\n                const regex = timeRegex(check);\n                if (!regex.test(input.data)) {\n                    ctx = this._getOrReturnCtx(input, ctx);\n                    addIssueToContext(ctx, {\n                        code: ZodIssueCode.invalid_string,\n                        validation: \"time\",\n                        message: check.message,\n                    });\n                    status.dirty();\n                }\n            }\n            else if (check.kind === \"duration\") {\n                if (!durationRegex.test(input.data)) {\n                    ctx = this._getOrReturnCtx(input, ctx);\n                    addIssueToContext(ctx, {\n                        validation: \"duration\",\n                        code: ZodIssueCode.invalid_string,\n                        message: check.message,\n                    });\n                    status.dirty();\n                }\n            }\n            else if (check.kind === \"ip\") {\n                if (!isValidIP(input.data, check.version)) {\n                    ctx = this._getOrReturnCtx(input, ctx);\n                    addIssueToContext(ctx, {\n                        validation: \"ip\",\n                        code: ZodIssueCode.invalid_string,\n                        message: check.message,\n                    });\n                    status.dirty();\n                }\n            }\n            else if (check.kind === \"jwt\") {\n                if (!isValidJWT(input.data, check.alg)) {\n                    ctx = this._getOrReturnCtx(input, ctx);\n                    addIssueToContext(ctx, {\n                        validation: \"jwt\",\n                        code: ZodIssueCode.invalid_string,\n                        message: check.message,\n                    });\n                    status.dirty();\n                }\n            }\n            else if (check.kind === \"cidr\") {\n                if (!isValidCidr(input.data, check.version)) {\n                    ctx = this._getOrReturnCtx(input, ctx);\n                    addIssueToContext(ctx, {\n                        validation: \"cidr\",\n                        code: ZodIssueCode.invalid_string,\n                        message: check.message,\n                    });\n                    status.dirty();\n                }\n            }\n            else if (check.kind === \"base64\") {\n                if (!base64Regex.test(input.data)) {\n                    ctx = this._getOrReturnCtx(input, ctx);\n                    addIssueToContext(ctx, {\n                        validation: \"base64\",\n                        code: ZodIssueCode.invalid_string,\n                        message: check.message,\n                    });\n                    status.dirty();\n                }\n            }\n            else if (check.kind === \"base64url\") {\n                if (!base64urlRegex.test(input.data)) {\n                    ctx = this._getOrReturnCtx(input, ctx);\n                    addIssueToContext(ctx, {\n                        validation: \"base64url\",\n                        code: ZodIssueCode.invalid_string,\n                        message: check.message,\n                    });\n                    status.dirty();\n                }\n            }\n            else {\n                util.assertNever(check);\n            }\n        }\n        return { status: status.value, value: input.data };\n    }\n    _regex(regex, validation, message) {\n        return this.refinement((data) => regex.test(data), {\n            validation,\n            code: ZodIssueCode.invalid_string,\n            ...errorUtil.errToObj(message),\n        });\n    }\n    _addCheck(check) {\n        return new ZodString({\n            ...this._def,\n            checks: [...this._def.checks, check],\n        });\n    }\n    email(message) {\n        return this._addCheck({ kind: \"email\", ...errorUtil.errToObj(message) });\n    }\n    url(message) {\n        return this._addCheck({ kind: \"url\", ...errorUtil.errToObj(message) });\n    }\n    emoji(message) {\n        return this._addCheck({ kind: \"emoji\", ...errorUtil.errToObj(message) });\n    }\n    uuid(message) {\n        return this._addCheck({ kind: \"uuid\", ...errorUtil.errToObj(message) });\n    }\n    nanoid(message) {\n        return this._addCheck({ kind: \"nanoid\", ...errorUtil.errToObj(message) });\n    }\n    cuid(message) {\n        return this._addCheck({ kind: \"cuid\", ...errorUtil.errToObj(message) });\n    }\n    cuid2(message) {\n        return this._addCheck({ kind: \"cuid2\", ...errorUtil.errToObj(message) });\n    }\n    ulid(message) {\n        return this._addCheck({ kind: \"ulid\", ...errorUtil.errToObj(message) });\n    }\n    base64(message) {\n        return this._addCheck({ kind: \"base64\", ...errorUtil.errToObj(message) });\n    }\n    base64url(message) {\n        // base64url encoding is a modification of base64 that can safely be used in URLs and filenames\n        return this._addCheck({\n            kind: \"base64url\",\n            ...errorUtil.errToObj(message),\n        });\n    }\n    jwt(options) {\n        return this._addCheck({ kind: \"jwt\", ...errorUtil.errToObj(options) });\n    }\n    ip(options) {\n        return this._addCheck({ kind: \"ip\", ...errorUtil.errToObj(options) });\n    }\n    cidr(options) {\n        return this._addCheck({ kind: \"cidr\", ...errorUtil.errToObj(options) });\n    }\n    datetime(options) {\n        if (typeof options === \"string\") {\n            return this._addCheck({\n                kind: \"datetime\",\n                precision: null,\n                offset: false,\n                local: false,\n                message: options,\n            });\n        }\n        return this._addCheck({\n            kind: \"datetime\",\n            precision: typeof options?.precision === \"undefined\" ? null : options?.precision,\n            offset: options?.offset ?? false,\n            local: options?.local ?? false,\n            ...errorUtil.errToObj(options?.message),\n        });\n    }\n    date(message) {\n        return this._addCheck({ kind: \"date\", message });\n    }\n    time(options) {\n        if (typeof options === \"string\") {\n            return this._addCheck({\n                kind: \"time\",\n                precision: null,\n                message: options,\n            });\n        }\n        return this._addCheck({\n            kind: \"time\",\n            precision: typeof options?.precision === \"undefined\" ? null : options?.precision,\n            ...errorUtil.errToObj(options?.message),\n        });\n    }\n    duration(message) {\n        return this._addCheck({ kind: \"duration\", ...errorUtil.errToObj(message) });\n    }\n    regex(regex, message) {\n        return this._addCheck({\n            kind: \"regex\",\n            regex: regex,\n            ...errorUtil.errToObj(message),\n        });\n    }\n    includes(value, options) {\n        return this._addCheck({\n            kind: \"includes\",\n            value: value,\n            position: options?.position,\n            ...errorUtil.errToObj(options?.message),\n        });\n    }\n    startsWith(value, message) {\n        return this._addCheck({\n            kind: \"startsWith\",\n            value: value,\n            ...errorUtil.errToObj(message),\n        });\n    }\n    endsWith(value, message) {\n        return this._addCheck({\n            kind: \"endsWith\",\n            value: value,\n            ...errorUtil.errToObj(message),\n        });\n    }\n    min(minLength, message) {\n        return this._addCheck({\n            kind: \"min\",\n            value: minLength,\n            ...errorUtil.errToObj(message),\n        });\n    }\n    max(maxLength, message) {\n        return this._addCheck({\n            kind: \"max\",\n            value: maxLength,\n            ...errorUtil.errToObj(message),\n        });\n    }\n    length(len, message) {\n        return this._addCheck({\n            kind: \"length\",\n            value: len,\n            ...errorUtil.errToObj(message),\n        });\n    }\n    /**\n     * Equivalent to `.min(1)`\n     */\n    nonempty(message) {\n        return this.min(1, errorUtil.errToObj(message));\n    }\n    trim() {\n        return new ZodString({\n            ...this._def,\n            checks: [...this._def.checks, { kind: \"trim\" }],\n        });\n    }\n    toLowerCase() {\n        return new ZodString({\n            ...this._def,\n            checks: [...this._def.checks, { kind: \"toLowerCase\" }],\n        });\n    }\n    toUpperCase() {\n        return new ZodString({\n            ...this._def,\n            checks: [...this._def.checks, { kind: \"toUpperCase\" }],\n        });\n    }\n    get isDatetime() {\n        return !!this._def.checks.find((ch) => ch.kind === \"datetime\");\n    }\n    get isDate() {\n        return !!this._def.checks.find((ch) => ch.kind === \"date\");\n    }\n    get isTime() {\n        return !!this._def.checks.find((ch) => ch.kind === \"time\");\n    }\n    get isDuration() {\n        return !!this._def.checks.find((ch) => ch.kind === \"duration\");\n    }\n    get isEmail() {\n        return !!this._def.checks.find((ch) => ch.kind === \"email\");\n    }\n    get isURL() {\n        return !!this._def.checks.find((ch) => ch.kind === \"url\");\n    }\n    get isEmoji() {\n        return !!this._def.checks.find((ch) => ch.kind === \"emoji\");\n    }\n    get isUUID() {\n        return !!this._def.checks.find((ch) => ch.kind === \"uuid\");\n    }\n    get isNANOID() {\n        return !!this._def.checks.find((ch) => ch.kind === \"nanoid\");\n    }\n    get isCUID() {\n        return !!this._def.checks.find((ch) => ch.kind === \"cuid\");\n    }\n    get isCUID2() {\n        return !!this._def.checks.find((ch) => ch.kind === \"cuid2\");\n    }\n    get isULID() {\n        return !!this._def.checks.find((ch) => ch.kind === \"ulid\");\n    }\n    get isIP() {\n        return !!this._def.checks.find((ch) => ch.kind === \"ip\");\n    }\n    get isCIDR() {\n        return !!this._def.checks.find((ch) => ch.kind === \"cidr\");\n    }\n    get isBase64() {\n        return !!this._def.checks.find((ch) => ch.kind === \"base64\");\n    }\n    get isBase64url() {\n        // base64url encoding is a modification of base64 that can safely be used in URLs and filenames\n        return !!this._def.checks.find((ch) => ch.kind === \"base64url\");\n    }\n    get minLength() {\n        let min = null;\n        for (const ch of this._def.checks) {\n            if (ch.kind === \"min\") {\n                if (min === null || ch.value > min)\n                    min = ch.value;\n            }\n        }\n        return min;\n    }\n    get maxLength() {\n        let max = null;\n        for (const ch of this._def.checks) {\n            if (ch.kind === \"max\") {\n                if (max === null || ch.value < max)\n                    max = ch.value;\n            }\n        }\n        return max;\n    }\n}\nZodString.create = (params) => {\n    return new ZodString({\n        checks: [],\n        typeName: ZodFirstPartyTypeKind.ZodString,\n        coerce: params?.coerce ?? false,\n        ...processCreateParams(params),\n    });\n};\n// https://stackoverflow.com/questions/3966484/why-does-modulus-operator-return-fractional-number-in-javascript/31711034#31711034\nfunction floatSafeRemainder(val, step) {\n    const valDecCount = (val.toString().split(\".\")[1] || \"\").length;\n    const stepDecCount = (step.toString().split(\".\")[1] || \"\").length;\n    const decCount = valDecCount > stepDecCount ? valDecCount : stepDecCount;\n    const valInt = Number.parseInt(val.toFixed(decCount).replace(\".\", \"\"));\n    const stepInt = Number.parseInt(step.toFixed(decCount).replace(\".\", \"\"));\n    return (valInt % stepInt) / 10 ** decCount;\n}\nexport class ZodNumber extends ZodType {\n    constructor() {\n        super(...arguments);\n        this.min = this.gte;\n        this.max = this.lte;\n        this.step = this.multipleOf;\n    }\n    _parse(input) {\n        if (this._def.coerce) {\n            input.data = Number(input.data);\n        }\n        const parsedType = this._getType(input);\n        if (parsedType !== ZodParsedType.number) {\n            const ctx = this._getOrReturnCtx(input);\n            addIssueToContext(ctx, {\n                code: ZodIssueCode.invalid_type,\n                expected: ZodParsedType.number,\n                received: ctx.parsedType,\n            });\n            return INVALID;\n        }\n        let ctx = undefined;\n        const status = new ParseStatus();\n        for (const check of this._def.checks) {\n            if (check.kind === \"int\") {\n                if (!util.isInteger(input.data)) {\n                    ctx = this._getOrReturnCtx(input, ctx);\n                    addIssueToContext(ctx, {\n                        code: ZodIssueCode.invalid_type,\n                        expected: \"integer\",\n                        received: \"float\",\n                        message: check.message,\n                    });\n                    status.dirty();\n                }\n            }\n            else if (check.kind === \"min\") {\n                const tooSmall = check.inclusive ? input.data < check.value : input.data <= check.value;\n                if (tooSmall) {\n                    ctx = this._getOrReturnCtx(input, ctx);\n                    addIssueToContext(ctx, {\n                        code: ZodIssueCode.too_small,\n                        minimum: check.value,\n                        type: \"number\",\n                        inclusive: check.inclusive,\n                        exact: false,\n                        message: check.message,\n                    });\n                    status.dirty();\n                }\n            }\n            else if (check.kind === \"max\") {\n                const tooBig = check.inclusive ? input.data > check.value : input.data >= check.value;\n                if (tooBig) {\n                    ctx = this._getOrReturnCtx(input, ctx);\n                    addIssueToContext(ctx, {\n                        code: ZodIssueCode.too_big,\n                        maximum: check.value,\n                        type: \"number\",\n                        inclusive: check.inclusive,\n                        exact: false,\n                        message: check.message,\n                    });\n                    status.dirty();\n                }\n            }\n            else if (check.kind === \"multipleOf\") {\n                if (floatSafeRemainder(input.data, check.value) !== 0) {\n                    ctx = this._getOrReturnCtx(input, ctx);\n                    addIssueToContext(ctx, {\n                        code: ZodIssueCode.not_multiple_of,\n                        multipleOf: check.value,\n                        message: check.message,\n                    });\n                    status.dirty();\n                }\n            }\n            else if (check.kind === \"finite\") {\n                if (!Number.isFinite(input.data)) {\n                    ctx = this._getOrReturnCtx(input, ctx);\n                    addIssueToContext(ctx, {\n                        code: ZodIssueCode.not_finite,\n                        message: check.message,\n                    });\n                    status.dirty();\n                }\n            }\n            else {\n                util.assertNever(check);\n            }\n        }\n        return { status: status.value, value: input.data };\n    }\n    gte(value, message) {\n        return this.setLimit(\"min\", value, true, errorUtil.toString(message));\n    }\n    gt(value, message) {\n        return this.setLimit(\"min\", value, false, errorUtil.toString(message));\n    }\n    lte(value, message) {\n        return this.setLimit(\"max\", value, true, errorUtil.toString(message));\n    }\n    lt(value, message) {\n        return this.setLimit(\"max\", value, false, errorUtil.toString(message));\n    }\n    setLimit(kind, value, inclusive, message) {\n        return new ZodNumber({\n            ...this._def,\n            checks: [\n                ...this._def.checks,\n                {\n                    kind,\n                    value,\n                    inclusive,\n                    message: errorUtil.toString(message),\n                },\n            ],\n        });\n    }\n    _addCheck(check) {\n        return new ZodNumber({\n            ...this._def,\n            checks: [...this._def.checks, check],\n        });\n    }\n    int(message) {\n        return this._addCheck({\n            kind: \"int\",\n            message: errorUtil.toString(message),\n        });\n    }\n    positive(message) {\n        return this._addCheck({\n            kind: \"min\",\n            value: 0,\n            inclusive: false,\n            message: errorUtil.toString(message),\n        });\n    }\n    negative(message) {\n        return this._addCheck({\n            kind: \"max\",\n            value: 0,\n            inclusive: false,\n            message: errorUtil.toString(message),\n        });\n    }\n    nonpositive(message) {\n        return this._addCheck({\n            kind: \"max\",\n            value: 0,\n            inclusive: true,\n            message: errorUtil.toString(message),\n        });\n    }\n    nonnegative(message) {\n        return this._addCheck({\n            kind: \"min\",\n            value: 0,\n            inclusive: true,\n            message: errorUtil.toString(message),\n        });\n    }\n    multipleOf(value, message) {\n        return this._addCheck({\n            kind: \"multipleOf\",\n            value: value,\n            message: errorUtil.toString(message),\n        });\n    }\n    finite(message) {\n        return this._addCheck({\n            kind: \"finite\",\n            message: errorUtil.toString(message),\n        });\n    }\n    safe(message) {\n        return this._addCheck({\n            kind: \"min\",\n            inclusive: true,\n            value: Number.MIN_SAFE_INTEGER,\n            message: errorUtil.toString(message),\n        })._addCheck({\n            kind: \"max\",\n            inclusive: true,\n            value: Number.MAX_SAFE_INTEGER,\n            message: errorUtil.toString(message),\n        });\n    }\n    get minValue() {\n        let min = null;\n        for (const ch of this._def.checks) {\n            if (ch.kind === \"min\") {\n                if (min === null || ch.value > min)\n                    min = ch.value;\n            }\n        }\n        return min;\n    }\n    get maxValue() {\n        let max = null;\n        for (const ch of this._def.checks) {\n            if (ch.kind === \"max\") {\n                if (max === null || ch.value < max)\n                    max = ch.value;\n            }\n        }\n        return max;\n    }\n    get isInt() {\n        return !!this._def.checks.find((ch) => ch.kind === \"int\" || (ch.kind === \"multipleOf\" && util.isInteger(ch.value)));\n    }\n    get isFinite() {\n        let max = null;\n        let min = null;\n        for (const ch of this._def.checks) {\n            if (ch.kind === \"finite\" || ch.kind === \"int\" || ch.kind === \"multipleOf\") {\n                return true;\n            }\n            else if (ch.kind === \"min\") {\n                if (min === null || ch.value > min)\n                    min = ch.value;\n            }\n            else if (ch.kind === \"max\") {\n                if (max === null || ch.value < max)\n                    max = ch.value;\n            }\n        }\n        return Number.isFinite(min) && Number.isFinite(max);\n    }\n}\nZodNumber.create = (params) => {\n    return new ZodNumber({\n        checks: [],\n        typeName: ZodFirstPartyTypeKind.ZodNumber,\n        coerce: params?.coerce || false,\n        ...processCreateParams(params),\n    });\n};\nexport class ZodBigInt extends ZodType {\n    constructor() {\n        super(...arguments);\n        this.min = this.gte;\n        this.max = this.lte;\n    }\n    _parse(input) {\n        if (this._def.coerce) {\n            try {\n                input.data = BigInt(input.data);\n            }\n            catch {\n                return this._getInvalidInput(input);\n            }\n        }\n        const parsedType = this._getType(input);\n        if (parsedType !== ZodParsedType.bigint) {\n            return this._getInvalidInput(input);\n        }\n        let ctx = undefined;\n        const status = new ParseStatus();\n        for (const check of this._def.checks) {\n            if (check.kind === \"min\") {\n                const tooSmall = check.inclusive ? input.data < check.value : input.data <= check.value;\n                if (tooSmall) {\n                    ctx = this._getOrReturnCtx(input, ctx);\n                    addIssueToContext(ctx, {\n                        code: ZodIssueCode.too_small,\n                        type: \"bigint\",\n                        minimum: check.value,\n                        inclusive: check.inclusive,\n                        message: check.message,\n                    });\n                    status.dirty();\n                }\n            }\n            else if (check.kind === \"max\") {\n                const tooBig = check.inclusive ? input.data > check.value : input.data >= check.value;\n                if (tooBig) {\n                    ctx = this._getOrReturnCtx(input, ctx);\n                    addIssueToContext(ctx, {\n                        code: ZodIssueCode.too_big,\n                        type: \"bigint\",\n                        maximum: check.value,\n                        inclusive: check.inclusive,\n                        message: check.message,\n                    });\n                    status.dirty();\n                }\n            }\n            else if (check.kind === \"multipleOf\") {\n                if (input.data % check.value !== BigInt(0)) {\n                    ctx = this._getOrReturnCtx(input, ctx);\n                    addIssueToContext(ctx, {\n                        code: ZodIssueCode.not_multiple_of,\n                        multipleOf: check.value,\n                        message: check.message,\n                    });\n                    status.dirty();\n                }\n            }\n            else {\n                util.assertNever(check);\n            }\n        }\n        return { status: status.value, value: input.data };\n    }\n    _getInvalidInput(input) {\n        const ctx = this._getOrReturnCtx(input);\n        addIssueToContext(ctx, {\n            code: ZodIssueCode.invalid_type,\n            expected: ZodParsedType.bigint,\n            received: ctx.parsedType,\n        });\n        return INVALID;\n    }\n    gte(value, message) {\n        return this.setLimit(\"min\", value, true, errorUtil.toString(message));\n    }\n    gt(value, message) {\n        return this.setLimit(\"min\", value, false, errorUtil.toString(message));\n    }\n    lte(value, message) {\n        return this.setLimit(\"max\", value, true, errorUtil.toString(message));\n    }\n    lt(value, message) {\n        return this.setLimit(\"max\", value, false, errorUtil.toString(message));\n    }\n    setLimit(kind, value, inclusive, message) {\n        return new ZodBigInt({\n            ...this._def,\n            checks: [\n                ...this._def.checks,\n                {\n                    kind,\n                    value,\n                    inclusive,\n                    message: errorUtil.toString(message),\n                },\n            ],\n        });\n    }\n    _addCheck(check) {\n        return new ZodBigInt({\n            ...this._def,\n            checks: [...this._def.checks, check],\n        });\n    }\n    positive(message) {\n        return this._addCheck({\n            kind: \"min\",\n            value: BigInt(0),\n            inclusive: false,\n            message: errorUtil.toString(message),\n        });\n    }\n    negative(message) {\n        return this._addCheck({\n            kind: \"max\",\n            value: BigInt(0),\n            inclusive: false,\n            message: errorUtil.toString(message),\n        });\n    }\n    nonpositive(message) {\n        return this._addCheck({\n            kind: \"max\",\n            value: BigInt(0),\n            inclusive: true,\n            message: errorUtil.toString(message),\n        });\n    }\n    nonnegative(message) {\n        return this._addCheck({\n            kind: \"min\",\n            value: BigInt(0),\n            inclusive: true,\n            message: errorUtil.toString(message),\n        });\n    }\n    multipleOf(value, message) {\n        return this._addCheck({\n            kind: \"multipleOf\",\n            value,\n            message: errorUtil.toString(message),\n        });\n    }\n    get minValue() {\n        let min = null;\n        for (const ch of this._def.checks) {\n            if (ch.kind === \"min\") {\n                if (min === null || ch.value > min)\n                    min = ch.value;\n            }\n        }\n        return min;\n    }\n    get maxValue() {\n        let max = null;\n        for (const ch of this._def.checks) {\n            if (ch.kind === \"max\") {\n                if (max === null || ch.value < max)\n                    max = ch.value;\n            }\n        }\n        return max;\n    }\n}\nZodBigInt.create = (params) => {\n    return new ZodBigInt({\n        checks: [],\n        typeName: ZodFirstPartyTypeKind.ZodBigInt,\n        coerce: params?.coerce ?? false,\n        ...processCreateParams(params),\n    });\n};\nexport class ZodBoolean extends ZodType {\n    _parse(input) {\n        if (this._def.coerce) {\n            input.data = Boolean(input.data);\n        }\n        const parsedType = this._getType(input);\n        if (parsedType !== ZodParsedType.boolean) {\n            const ctx = this._getOrReturnCtx(input);\n            addIssueToContext(ctx, {\n                code: ZodIssueCode.invalid_type,\n                expected: ZodParsedType.boolean,\n                received: ctx.parsedType,\n            });\n            return INVALID;\n        }\n        return OK(input.data);\n    }\n}\nZodBoolean.create = (params) => {\n    return new ZodBoolean({\n        typeName: ZodFirstPartyTypeKind.ZodBoolean,\n        coerce: params?.coerce || false,\n        ...processCreateParams(params),\n    });\n};\nexport class ZodDate extends ZodType {\n    _parse(input) {\n        if (this._def.coerce) {\n            input.data = new Date(input.data);\n        }\n        const parsedType = this._getType(input);\n        if (parsedType !== ZodParsedType.date) {\n            const ctx = this._getOrReturnCtx(input);\n            addIssueToContext(ctx, {\n                code: ZodIssueCode.invalid_type,\n                expected: ZodParsedType.date,\n                received: ctx.parsedType,\n            });\n            return INVALID;\n        }\n        if (Number.isNaN(input.data.getTime())) {\n            const ctx = this._getOrReturnCtx(input);\n            addIssueToContext(ctx, {\n                code: ZodIssueCode.invalid_date,\n            });\n            return INVALID;\n        }\n        const status = new ParseStatus();\n        let ctx = undefined;\n        for (const check of this._def.checks) {\n            if (check.kind === \"min\") {\n                if (input.data.getTime() < check.value) {\n                    ctx = this._getOrReturnCtx(input, ctx);\n                    addIssueToContext(ctx, {\n                        code: ZodIssueCode.too_small,\n                        message: check.message,\n                        inclusive: true,\n                        exact: false,\n                        minimum: check.value,\n                        type: \"date\",\n                    });\n                    status.dirty();\n                }\n            }\n            else if (check.kind === \"max\") {\n                if (input.data.getTime() > check.value) {\n                    ctx = this._getOrReturnCtx(input, ctx);\n                    addIssueToContext(ctx, {\n                        code: ZodIssueCode.too_big,\n                        message: check.message,\n                        inclusive: true,\n                        exact: false,\n                        maximum: check.value,\n                        type: \"date\",\n                    });\n                    status.dirty();\n                }\n            }\n            else {\n                util.assertNever(check);\n            }\n        }\n        return {\n            status: status.value,\n            value: new Date(input.data.getTime()),\n        };\n    }\n    _addCheck(check) {\n        return new ZodDate({\n            ...this._def,\n            checks: [...this._def.checks, check],\n        });\n    }\n    min(minDate, message) {\n        return this._addCheck({\n            kind: \"min\",\n            value: minDate.getTime(),\n            message: errorUtil.toString(message),\n        });\n    }\n    max(maxDate, message) {\n        return this._addCheck({\n            kind: \"max\",\n            value: maxDate.getTime(),\n            message: errorUtil.toString(message),\n        });\n    }\n    get minDate() {\n        let min = null;\n        for (const ch of this._def.checks) {\n            if (ch.kind === \"min\") {\n                if (min === null || ch.value > min)\n                    min = ch.value;\n            }\n        }\n        return min != null ? new Date(min) : null;\n    }\n    get maxDate() {\n        let max = null;\n        for (const ch of this._def.checks) {\n            if (ch.kind === \"max\") {\n                if (max === null || ch.value < max)\n                    max = ch.value;\n            }\n        }\n        return max != null ? new Date(max) : null;\n    }\n}\nZodDate.create = (params) => {\n    return new ZodDate({\n        checks: [],\n        coerce: params?.coerce || false,\n        typeName: ZodFirstPartyTypeKind.ZodDate,\n        ...processCreateParams(params),\n    });\n};\nexport class ZodSymbol extends ZodType {\n    _parse(input) {\n        const parsedType = this._getType(input);\n        if (parsedType !== ZodParsedType.symbol) {\n            const ctx = this._getOrReturnCtx(input);\n            addIssueToContext(ctx, {\n                code: ZodIssueCode.invalid_type,\n                expected: ZodParsedType.symbol,\n                received: ctx.parsedType,\n            });\n            return INVALID;\n        }\n        return OK(input.data);\n    }\n}\nZodSymbol.create = (params) => {\n    return new ZodSymbol({\n        typeName: ZodFirstPartyTypeKind.ZodSymbol,\n        ...processCreateParams(params),\n    });\n};\nexport class ZodUndefined extends ZodType {\n    _parse(input) {\n        const parsedType = this._getType(input);\n        if (parsedType !== ZodParsedType.undefined) {\n            const ctx = this._getOrReturnCtx(input);\n            addIssueToContext(ctx, {\n                code: ZodIssueCode.invalid_type,\n                expected: ZodParsedType.undefined,\n                received: ctx.parsedType,\n            });\n            return INVALID;\n        }\n        return OK(input.data);\n    }\n}\nZodUndefined.create = (params) => {\n    return new ZodUndefined({\n        typeName: ZodFirstPartyTypeKind.ZodUndefined,\n        ...processCreateParams(params),\n    });\n};\nexport class ZodNull extends ZodType {\n    _parse(input) {\n        const parsedType = this._getType(input);\n        if (parsedType !== ZodParsedType.null) {\n            const ctx = this._getOrReturnCtx(input);\n            addIssueToContext(ctx, {\n                code: ZodIssueCode.invalid_type,\n                expected: ZodParsedType.null,\n                received: ctx.parsedType,\n            });\n            return INVALID;\n        }\n        return OK(input.data);\n    }\n}\nZodNull.create = (params) => {\n    return new ZodNull({\n        typeName: ZodFirstPartyTypeKind.ZodNull,\n        ...processCreateParams(params),\n    });\n};\nexport class ZodAny extends ZodType {\n    constructor() {\n        super(...arguments);\n        // to prevent instances of other classes from extending ZodAny. this causes issues with catchall in ZodObject.\n        this._any = true;\n    }\n    _parse(input) {\n        return OK(input.data);\n    }\n}\nZodAny.create = (params) => {\n    return new ZodAny({\n        typeName: ZodFirstPartyTypeKind.ZodAny,\n        ...processCreateParams(params),\n    });\n};\nexport class ZodUnknown extends ZodType {\n    constructor() {\n        super(...arguments);\n        // required\n        this._unknown = true;\n    }\n    _parse(input) {\n        return OK(input.data);\n    }\n}\nZodUnknown.create = (params) => {\n    return new ZodUnknown({\n        typeName: ZodFirstPartyTypeKind.ZodUnknown,\n        ...processCreateParams(params),\n    });\n};\nexport class ZodNever extends ZodType {\n    _parse(input) {\n        const ctx = this._getOrReturnCtx(input);\n        addIssueToContext(ctx, {\n            code: ZodIssueCode.invalid_type,\n            expected: ZodParsedType.never,\n            received: ctx.parsedType,\n        });\n        return INVALID;\n    }\n}\nZodNever.create = (params) => {\n    return new ZodNever({\n        typeName: ZodFirstPartyTypeKind.ZodNever,\n        ...processCreateParams(params),\n    });\n};\nexport class ZodVoid extends ZodType {\n    _parse(input) {\n        const parsedType = this._getType(input);\n        if (parsedType !== ZodParsedType.undefined) {\n            const ctx = this._getOrReturnCtx(input);\n            addIssueToContext(ctx, {\n                code: ZodIssueCode.invalid_type,\n                expected: ZodParsedType.void,\n                received: ctx.parsedType,\n            });\n            return INVALID;\n        }\n        return OK(input.data);\n    }\n}\nZodVoid.create = (params) => {\n    return new ZodVoid({\n        typeName: ZodFirstPartyTypeKind.ZodVoid,\n        ...processCreateParams(params),\n    });\n};\nexport class ZodArray extends ZodType {\n    _parse(input) {\n        const { ctx, status } = this._processInputParams(input);\n        const def = this._def;\n        if (ctx.parsedType !== ZodParsedType.array) {\n            addIssueToContext(ctx, {\n                code: ZodIssueCode.invalid_type,\n                expected: ZodParsedType.array,\n                received: ctx.parsedType,\n            });\n            return INVALID;\n        }\n        if (def.exactLength !== null) {\n            const tooBig = ctx.data.length > def.exactLength.value;\n            const tooSmall = ctx.data.length < def.exactLength.value;\n            if (tooBig || tooSmall) {\n                addIssueToContext(ctx, {\n                    code: tooBig ? ZodIssueCode.too_big : ZodIssueCode.too_small,\n                    minimum: (tooSmall ? def.exactLength.value : undefined),\n                    maximum: (tooBig ? def.exactLength.value : undefined),\n                    type: \"array\",\n                    inclusive: true,\n                    exact: true,\n                    message: def.exactLength.message,\n                });\n                status.dirty();\n            }\n        }\n        if (def.minLength !== null) {\n            if (ctx.data.length < def.minLength.value) {\n                addIssueToContext(ctx, {\n                    code: ZodIssueCode.too_small,\n                    minimum: def.minLength.value,\n                    type: \"array\",\n                    inclusive: true,\n                    exact: false,\n                    message: def.minLength.message,\n                });\n                status.dirty();\n            }\n        }\n        if (def.maxLength !== null) {\n            if (ctx.data.length > def.maxLength.value) {\n                addIssueToContext(ctx, {\n                    code: ZodIssueCode.too_big,\n                    maximum: def.maxLength.value,\n                    type: \"array\",\n                    inclusive: true,\n                    exact: false,\n                    message: def.maxLength.message,\n                });\n                status.dirty();\n            }\n        }\n        if (ctx.common.async) {\n            return Promise.all([...ctx.data].map((item, i) => {\n                return def.type._parseAsync(new ParseInputLazyPath(ctx, item, ctx.path, i));\n            })).then((result) => {\n                return ParseStatus.mergeArray(status, result);\n            });\n        }\n        const result = [...ctx.data].map((item, i) => {\n            return def.type._parseSync(new ParseInputLazyPath(ctx, item, ctx.path, i));\n        });\n        return ParseStatus.mergeArray(status, result);\n    }\n    get element() {\n        return this._def.type;\n    }\n    min(minLength, message) {\n        return new ZodArray({\n            ...this._def,\n            minLength: { value: minLength, message: errorUtil.toString(message) },\n        });\n    }\n    max(maxLength, message) {\n        return new ZodArray({\n            ...this._def,\n            maxLength: { value: maxLength, message: errorUtil.toString(message) },\n        });\n    }\n    length(len, message) {\n        return new ZodArray({\n            ...this._def,\n            exactLength: { value: len, message: errorUtil.toString(message) },\n        });\n    }\n    nonempty(message) {\n        return this.min(1, message);\n    }\n}\nZodArray.create = (schema, params) => {\n    return new ZodArray({\n        type: schema,\n        minLength: null,\n        maxLength: null,\n        exactLength: null,\n        typeName: ZodFirstPartyTypeKind.ZodArray,\n        ...processCreateParams(params),\n    });\n};\nfunction deepPartialify(schema) {\n    if (schema instanceof ZodObject) {\n        const newShape = {};\n        for (const key in schema.shape) {\n            const fieldSchema = schema.shape[key];\n            newShape[key] = ZodOptional.create(deepPartialify(fieldSchema));\n        }\n        return new ZodObject({\n            ...schema._def,\n            shape: () => newShape,\n        });\n    }\n    else if (schema instanceof ZodArray) {\n        return new ZodArray({\n            ...schema._def,\n            type: deepPartialify(schema.element),\n        });\n    }\n    else if (schema instanceof ZodOptional) {\n        return ZodOptional.create(deepPartialify(schema.unwrap()));\n    }\n    else if (schema instanceof ZodNullable) {\n        return ZodNullable.create(deepPartialify(schema.unwrap()));\n    }\n    else if (schema instanceof ZodTuple) {\n        return ZodTuple.create(schema.items.map((item) => deepPartialify(item)));\n    }\n    else {\n        return schema;\n    }\n}\nexport class ZodObject extends ZodType {\n    constructor() {\n        super(...arguments);\n        this._cached = null;\n        /**\n         * @deprecated In most cases, this is no longer needed - unknown properties are now silently stripped.\n         * If you want to pass through unknown properties, use `.passthrough()` instead.\n         */\n        this.nonstrict = this.passthrough;\n        // extend<\n        //   Augmentation extends ZodRawShape,\n        //   NewOutput extends util.flatten<{\n        //     [k in keyof Augmentation | keyof Output]: k extends keyof Augmentation\n        //       ? Augmentation[k][\"_output\"]\n        //       : k extends keyof Output\n        //       ? Output[k]\n        //       : never;\n        //   }>,\n        //   NewInput extends util.flatten<{\n        //     [k in keyof Augmentation | keyof Input]: k extends keyof Augmentation\n        //       ? Augmentation[k][\"_input\"]\n        //       : k extends keyof Input\n        //       ? Input[k]\n        //       : never;\n        //   }>\n        // >(\n        //   augmentation: Augmentation\n        // ): ZodObject<\n        //   extendShape<T, Augmentation>,\n        //   UnknownKeys,\n        //   Catchall,\n        //   NewOutput,\n        //   NewInput\n        // > {\n        //   return new ZodObject({\n        //     ...this._def,\n        //     shape: () => ({\n        //       ...this._def.shape(),\n        //       ...augmentation,\n        //     }),\n        //   }) as any;\n        // }\n        /**\n         * @deprecated Use `.extend` instead\n         *  */\n        this.augment = this.extend;\n    }\n    _getCached() {\n        if (this._cached !== null)\n            return this._cached;\n        const shape = this._def.shape();\n        const keys = util.objectKeys(shape);\n        this._cached = { shape, keys };\n        return this._cached;\n    }\n    _parse(input) {\n        const parsedType = this._getType(input);\n        if (parsedType !== ZodParsedType.object) {\n            const ctx = this._getOrReturnCtx(input);\n            addIssueToContext(ctx, {\n                code: ZodIssueCode.invalid_type,\n                expected: ZodParsedType.object,\n                received: ctx.parsedType,\n            });\n            return INVALID;\n        }\n        const { status, ctx } = this._processInputParams(input);\n        const { shape, keys: shapeKeys } = this._getCached();\n        const extraKeys = [];\n        if (!(this._def.catchall instanceof ZodNever && this._def.unknownKeys === \"strip\")) {\n            for (const key in ctx.data) {\n                if (!shapeKeys.includes(key)) {\n                    extraKeys.push(key);\n                }\n            }\n        }\n        const pairs = [];\n        for (const key of shapeKeys) {\n            const keyValidator = shape[key];\n            const value = ctx.data[key];\n            pairs.push({\n                key: { status: \"valid\", value: key },\n                value: keyValidator._parse(new ParseInputLazyPath(ctx, value, ctx.path, key)),\n                alwaysSet: key in ctx.data,\n            });\n        }\n        if (this._def.catchall instanceof ZodNever) {\n            const unknownKeys = this._def.unknownKeys;\n            if (unknownKeys === \"passthrough\") {\n                for (const key of extraKeys) {\n                    pairs.push({\n                        key: { status: \"valid\", value: key },\n                        value: { status: \"valid\", value: ctx.data[key] },\n                    });\n                }\n            }\n            else if (unknownKeys === \"strict\") {\n                if (extraKeys.length > 0) {\n                    addIssueToContext(ctx, {\n                        code: ZodIssueCode.unrecognized_keys,\n                        keys: extraKeys,\n                    });\n                    status.dirty();\n                }\n            }\n            else if (unknownKeys === \"strip\") {\n            }\n            else {\n                throw new Error(`Internal ZodObject error: invalid unknownKeys value.`);\n            }\n        }\n        else {\n            // run catchall validation\n            const catchall = this._def.catchall;\n            for (const key of extraKeys) {\n                const value = ctx.data[key];\n                pairs.push({\n                    key: { status: \"valid\", value: key },\n                    value: catchall._parse(new ParseInputLazyPath(ctx, value, ctx.path, key) //, ctx.child(key), value, getParsedType(value)\n                    ),\n                    alwaysSet: key in ctx.data,\n                });\n            }\n        }\n        if (ctx.common.async) {\n            return Promise.resolve()\n                .then(async () => {\n                const syncPairs = [];\n                for (const pair of pairs) {\n                    const key = await pair.key;\n                    const value = await pair.value;\n                    syncPairs.push({\n                        key,\n                        value,\n                        alwaysSet: pair.alwaysSet,\n                    });\n                }\n                return syncPairs;\n            })\n                .then((syncPairs) => {\n                return ParseStatus.mergeObjectSync(status, syncPairs);\n            });\n        }\n        else {\n            return ParseStatus.mergeObjectSync(status, pairs);\n        }\n    }\n    get shape() {\n        return this._def.shape();\n    }\n    strict(message) {\n        errorUtil.errToObj;\n        return new ZodObject({\n            ...this._def,\n            unknownKeys: \"strict\",\n            ...(message !== undefined\n                ? {\n                    errorMap: (issue, ctx) => {\n                        const defaultError = this._def.errorMap?.(issue, ctx).message ?? ctx.defaultError;\n                        if (issue.code === \"unrecognized_keys\")\n                            return {\n                                message: errorUtil.errToObj(message).message ?? defaultError,\n                            };\n                        return {\n                            message: defaultError,\n                        };\n                    },\n                }\n                : {}),\n        });\n    }\n    strip() {\n        return new ZodObject({\n            ...this._def,\n            unknownKeys: \"strip\",\n        });\n    }\n    passthrough() {\n        return new ZodObject({\n            ...this._def,\n            unknownKeys: \"passthrough\",\n        });\n    }\n    // const AugmentFactory =\n    //   <Def extends ZodObjectDef>(def: Def) =>\n    //   <Augmentation extends ZodRawShape>(\n    //     augmentation: Augmentation\n    //   ): ZodObject<\n    //     extendShape<ReturnType<Def[\"shape\"]>, Augmentation>,\n    //     Def[\"unknownKeys\"],\n    //     Def[\"catchall\"]\n    //   > => {\n    //     return new ZodObject({\n    //       ...def,\n    //       shape: () => ({\n    //         ...def.shape(),\n    //         ...augmentation,\n    //       }),\n    //     }) as any;\n    //   };\n    extend(augmentation) {\n        return new ZodObject({\n            ...this._def,\n            shape: () => ({\n                ...this._def.shape(),\n                ...augmentation,\n            }),\n        });\n    }\n    /**\n     * Prior to zod@1.0.12 there was a bug in the\n     * inferred type of merged objects. Please\n     * upgrade if you are experiencing issues.\n     */\n    merge(merging) {\n        const merged = new ZodObject({\n            unknownKeys: merging._def.unknownKeys,\n            catchall: merging._def.catchall,\n            shape: () => ({\n                ...this._def.shape(),\n                ...merging._def.shape(),\n            }),\n            typeName: ZodFirstPartyTypeKind.ZodObject,\n        });\n        return merged;\n    }\n    // merge<\n    //   Incoming extends AnyZodObject,\n    //   Augmentation extends Incoming[\"shape\"],\n    //   NewOutput extends {\n    //     [k in keyof Augmentation | keyof Output]: k extends keyof Augmentation\n    //       ? Augmentation[k][\"_output\"]\n    //       : k extends keyof Output\n    //       ? Output[k]\n    //       : never;\n    //   },\n    //   NewInput extends {\n    //     [k in keyof Augmentation | keyof Input]: k extends keyof Augmentation\n    //       ? Augmentation[k][\"_input\"]\n    //       : k extends keyof Input\n    //       ? Input[k]\n    //       : never;\n    //   }\n    // >(\n    //   merging: Incoming\n    // ): ZodObject<\n    //   extendShape<T, ReturnType<Incoming[\"_def\"][\"shape\"]>>,\n    //   Incoming[\"_def\"][\"unknownKeys\"],\n    //   Incoming[\"_def\"][\"catchall\"],\n    //   NewOutput,\n    //   NewInput\n    // > {\n    //   const merged: any = new ZodObject({\n    //     unknownKeys: merging._def.unknownKeys,\n    //     catchall: merging._def.catchall,\n    //     shape: () =>\n    //       objectUtil.mergeShapes(this._def.shape(), merging._def.shape()),\n    //     typeName: ZodFirstPartyTypeKind.ZodObject,\n    //   }) as any;\n    //   return merged;\n    // }\n    setKey(key, schema) {\n        return this.augment({ [key]: schema });\n    }\n    // merge<Incoming extends AnyZodObject>(\n    //   merging: Incoming\n    // ): //ZodObject<T & Incoming[\"_shape\"], UnknownKeys, Catchall> = (merging) => {\n    // ZodObject<\n    //   extendShape<T, ReturnType<Incoming[\"_def\"][\"shape\"]>>,\n    //   Incoming[\"_def\"][\"unknownKeys\"],\n    //   Incoming[\"_def\"][\"catchall\"]\n    // > {\n    //   // const mergedShape = objectUtil.mergeShapes(\n    //   //   this._def.shape(),\n    //   //   merging._def.shape()\n    //   // );\n    //   const merged: any = new ZodObject({\n    //     unknownKeys: merging._def.unknownKeys,\n    //     catchall: merging._def.catchall,\n    //     shape: () =>\n    //       objectUtil.mergeShapes(this._def.shape(), merging._def.shape()),\n    //     typeName: ZodFirstPartyTypeKind.ZodObject,\n    //   }) as any;\n    //   return merged;\n    // }\n    catchall(index) {\n        return new ZodObject({\n            ...this._def,\n            catchall: index,\n        });\n    }\n    pick(mask) {\n        const shape = {};\n        for (const key of util.objectKeys(mask)) {\n            if (mask[key] && this.shape[key]) {\n                shape[key] = this.shape[key];\n            }\n        }\n        return new ZodObject({\n            ...this._def,\n            shape: () => shape,\n        });\n    }\n    omit(mask) {\n        const shape = {};\n        for (const key of util.objectKeys(this.shape)) {\n            if (!mask[key]) {\n                shape[key] = this.shape[key];\n            }\n        }\n        return new ZodObject({\n            ...this._def,\n            shape: () => shape,\n        });\n    }\n    /**\n     * @deprecated\n     */\n    deepPartial() {\n        return deepPartialify(this);\n    }\n    partial(mask) {\n        const newShape = {};\n        for (const key of util.objectKeys(this.shape)) {\n            const fieldSchema = this.shape[key];\n            if (mask && !mask[key]) {\n                newShape[key] = fieldSchema;\n            }\n            else {\n                newShape[key] = fieldSchema.optional();\n            }\n        }\n        return new ZodObject({\n            ...this._def,\n            shape: () => newShape,\n        });\n    }\n    required(mask) {\n        const newShape = {};\n        for (const key of util.objectKeys(this.shape)) {\n            if (mask && !mask[key]) {\n                newShape[key] = this.shape[key];\n            }\n            else {\n                const fieldSchema = this.shape[key];\n                let newField = fieldSchema;\n                while (newField instanceof ZodOptional) {\n                    newField = newField._def.innerType;\n                }\n                newShape[key] = newField;\n            }\n        }\n        return new ZodObject({\n            ...this._def,\n            shape: () => newShape,\n        });\n    }\n    keyof() {\n        return createZodEnum(util.objectKeys(this.shape));\n    }\n}\nZodObject.create = (shape, params) => {\n    return new ZodObject({\n        shape: () => shape,\n        unknownKeys: \"strip\",\n        catchall: ZodNever.create(),\n        typeName: ZodFirstPartyTypeKind.ZodObject,\n        ...processCreateParams(params),\n    });\n};\nZodObject.strictCreate = (shape, params) => {\n    return new ZodObject({\n        shape: () => shape,\n        unknownKeys: \"strict\",\n        catchall: ZodNever.create(),\n        typeName: ZodFirstPartyTypeKind.ZodObject,\n        ...processCreateParams(params),\n    });\n};\nZodObject.lazycreate = (shape, params) => {\n    return new ZodObject({\n        shape,\n        unknownKeys: \"strip\",\n        catchall: ZodNever.create(),\n        typeName: ZodFirstPartyTypeKind.ZodObject,\n        ...processCreateParams(params),\n    });\n};\nexport class ZodUnion extends ZodType {\n    _parse(input) {\n        const { ctx } = this._processInputParams(input);\n        const options = this._def.options;\n        function handleResults(results) {\n            // return first issue-free validation if it exists\n            for (const result of results) {\n                if (result.result.status === \"valid\") {\n                    return result.result;\n                }\n            }\n            for (const result of results) {\n                if (result.result.status === \"dirty\") {\n                    // add issues from dirty option\n                    ctx.common.issues.push(...result.ctx.common.issues);\n                    return result.result;\n                }\n            }\n            // return invalid\n            const unionErrors = results.map((result) => new ZodError(result.ctx.common.issues));\n            addIssueToContext(ctx, {\n                code: ZodIssueCode.invalid_union,\n                unionErrors,\n            });\n            return INVALID;\n        }\n        if (ctx.common.async) {\n            return Promise.all(options.map(async (option) => {\n                const childCtx = {\n                    ...ctx,\n                    common: {\n                        ...ctx.common,\n                        issues: [],\n                    },\n                    parent: null,\n                };\n                return {\n                    result: await option._parseAsync({\n                        data: ctx.data,\n                        path: ctx.path,\n                        parent: childCtx,\n                    }),\n                    ctx: childCtx,\n                };\n            })).then(handleResults);\n        }\n        else {\n            let dirty = undefined;\n            const issues = [];\n            for (const option of options) {\n                const childCtx = {\n                    ...ctx,\n                    common: {\n                        ...ctx.common,\n                        issues: [],\n                    },\n                    parent: null,\n                };\n                const result = option._parseSync({\n                    data: ctx.data,\n                    path: ctx.path,\n                    parent: childCtx,\n                });\n                if (result.status === \"valid\") {\n                    return result;\n                }\n                else if (result.status === \"dirty\" && !dirty) {\n                    dirty = { result, ctx: childCtx };\n                }\n                if (childCtx.common.issues.length) {\n                    issues.push(childCtx.common.issues);\n                }\n            }\n            if (dirty) {\n                ctx.common.issues.push(...dirty.ctx.common.issues);\n                return dirty.result;\n            }\n            const unionErrors = issues.map((issues) => new ZodError(issues));\n            addIssueToContext(ctx, {\n                code: ZodIssueCode.invalid_union,\n                unionErrors,\n            });\n            return INVALID;\n        }\n    }\n    get options() {\n        return this._def.options;\n    }\n}\nZodUnion.create = (types, params) => {\n    return new ZodUnion({\n        options: types,\n        typeName: ZodFirstPartyTypeKind.ZodUnion,\n        ...processCreateParams(params),\n    });\n};\n/////////////////////////////////////////////////////\n/////////////////////////////////////////////////////\n//////////                                 //////////\n//////////      ZodDiscriminatedUnion      //////////\n//////////                                 //////////\n/////////////////////////////////////////////////////\n/////////////////////////////////////////////////////\nconst getDiscriminator = (type) => {\n    if (type instanceof ZodLazy) {\n        return getDiscriminator(type.schema);\n    }\n    else if (type instanceof ZodEffects) {\n        return getDiscriminator(type.innerType());\n    }\n    else if (type instanceof ZodLiteral) {\n        return [type.value];\n    }\n    else if (type instanceof ZodEnum) {\n        return type.options;\n    }\n    else if (type instanceof ZodNativeEnum) {\n        // eslint-disable-next-line ban/ban\n        return util.objectValues(type.enum);\n    }\n    else if (type instanceof ZodDefault) {\n        return getDiscriminator(type._def.innerType);\n    }\n    else if (type instanceof ZodUndefined) {\n        return [undefined];\n    }\n    else if (type instanceof ZodNull) {\n        return [null];\n    }\n    else if (type instanceof ZodOptional) {\n        return [undefined, ...getDiscriminator(type.unwrap())];\n    }\n    else if (type instanceof ZodNullable) {\n        return [null, ...getDiscriminator(type.unwrap())];\n    }\n    else if (type instanceof ZodBranded) {\n        return getDiscriminator(type.unwrap());\n    }\n    else if (type instanceof ZodReadonly) {\n        return getDiscriminator(type.unwrap());\n    }\n    else if (type instanceof ZodCatch) {\n        return getDiscriminator(type._def.innerType);\n    }\n    else {\n        return [];\n    }\n};\nexport class ZodDiscriminatedUnion extends ZodType {\n    _parse(input) {\n        const { ctx } = this._processInputParams(input);\n        if (ctx.parsedType !== ZodParsedType.object) {\n            addIssueToContext(ctx, {\n                code: ZodIssueCode.invalid_type,\n                expected: ZodParsedType.object,\n                received: ctx.parsedType,\n            });\n            return INVALID;\n        }\n        const discriminator = this.discriminator;\n        const discriminatorValue = ctx.data[discriminator];\n        const option = this.optionsMap.get(discriminatorValue);\n        if (!option) {\n            addIssueToContext(ctx, {\n                code: ZodIssueCode.invalid_union_discriminator,\n                options: Array.from(this.optionsMap.keys()),\n                path: [discriminator],\n            });\n            return INVALID;\n        }\n        if (ctx.common.async) {\n            return option._parseAsync({\n                data: ctx.data,\n                path: ctx.path,\n                parent: ctx,\n            });\n        }\n        else {\n            return option._parseSync({\n                data: ctx.data,\n                path: ctx.path,\n                parent: ctx,\n            });\n        }\n    }\n    get discriminator() {\n        return this._def.discriminator;\n    }\n    get options() {\n        return this._def.options;\n    }\n    get optionsMap() {\n        return this._def.optionsMap;\n    }\n    /**\n     * The constructor of the discriminated union schema. Its behaviour is very similar to that of the normal z.union() constructor.\n     * However, it only allows a union of objects, all of which need to share a discriminator property. This property must\n     * have a different value for each object in the union.\n     * @param discriminator the name of the discriminator property\n     * @param types an array of object schemas\n     * @param params\n     */\n    static create(discriminator, options, params) {\n        // Get all the valid discriminator values\n        const optionsMap = new Map();\n        // try {\n        for (const type of options) {\n            const discriminatorValues = getDiscriminator(type.shape[discriminator]);\n            if (!discriminatorValues.length) {\n                throw new Error(`A discriminator value for key \\`${discriminator}\\` could not be extracted from all schema options`);\n            }\n            for (const value of discriminatorValues) {\n                if (optionsMap.has(value)) {\n                    throw new Error(`Discriminator property ${String(discriminator)} has duplicate value ${String(value)}`);\n                }\n                optionsMap.set(value, type);\n            }\n        }\n        return new ZodDiscriminatedUnion({\n            typeName: ZodFirstPartyTypeKind.ZodDiscriminatedUnion,\n            discriminator,\n            options,\n            optionsMap,\n            ...processCreateParams(params),\n        });\n    }\n}\nfunction mergeValues(a, b) {\n    const aType = getParsedType(a);\n    const bType = getParsedType(b);\n    if (a === b) {\n        return { valid: true, data: a };\n    }\n    else if (aType === ZodParsedType.object && bType === ZodParsedType.object) {\n        const bKeys = util.objectKeys(b);\n        const sharedKeys = util.objectKeys(a).filter((key) => bKeys.indexOf(key) !== -1);\n        const newObj = { ...a, ...b };\n        for (const key of sharedKeys) {\n            const sharedValue = mergeValues(a[key], b[key]);\n            if (!sharedValue.valid) {\n                return { valid: false };\n            }\n            newObj[key] = sharedValue.data;\n        }\n        return { valid: true, data: newObj };\n    }\n    else if (aType === ZodParsedType.array && bType === ZodParsedType.array) {\n        if (a.length !== b.length) {\n            return { valid: false };\n        }\n        const newArray = [];\n        for (let index = 0; index < a.length; index++) {\n            const itemA = a[index];\n            const itemB = b[index];\n            const sharedValue = mergeValues(itemA, itemB);\n            if (!sharedValue.valid) {\n                return { valid: false };\n            }\n            newArray.push(sharedValue.data);\n        }\n        return { valid: true, data: newArray };\n    }\n    else if (aType === ZodParsedType.date && bType === ZodParsedType.date && +a === +b) {\n        return { valid: true, data: a };\n    }\n    else {\n        return { valid: false };\n    }\n}\nexport class ZodIntersection extends ZodType {\n    _parse(input) {\n        const { status, ctx } = this._processInputParams(input);\n        const handleParsed = (parsedLeft, parsedRight) => {\n            if (isAborted(parsedLeft) || isAborted(parsedRight)) {\n                return INVALID;\n            }\n            const merged = mergeValues(parsedLeft.value, parsedRight.value);\n            if (!merged.valid) {\n                addIssueToContext(ctx, {\n                    code: ZodIssueCode.invalid_intersection_types,\n                });\n                return INVALID;\n            }\n            if (isDirty(parsedLeft) || isDirty(parsedRight)) {\n                status.dirty();\n            }\n            return { status: status.value, value: merged.data };\n        };\n        if (ctx.common.async) {\n            return Promise.all([\n                this._def.left._parseAsync({\n                    data: ctx.data,\n                    path: ctx.path,\n                    parent: ctx,\n                }),\n                this._def.right._parseAsync({\n                    data: ctx.data,\n                    path: ctx.path,\n                    parent: ctx,\n                }),\n            ]).then(([left, right]) => handleParsed(left, right));\n        }\n        else {\n            return handleParsed(this._def.left._parseSync({\n                data: ctx.data,\n                path: ctx.path,\n                parent: ctx,\n            }), this._def.right._parseSync({\n                data: ctx.data,\n                path: ctx.path,\n                parent: ctx,\n            }));\n        }\n    }\n}\nZodIntersection.create = (left, right, params) => {\n    return new ZodIntersection({\n        left: left,\n        right: right,\n        typeName: ZodFirstPartyTypeKind.ZodIntersection,\n        ...processCreateParams(params),\n    });\n};\n// type ZodTupleItems = [ZodTypeAny, ...ZodTypeAny[]];\nexport class ZodTuple extends ZodType {\n    _parse(input) {\n        const { status, ctx } = this._processInputParams(input);\n        if (ctx.parsedType !== ZodParsedType.array) {\n            addIssueToContext(ctx, {\n                code: ZodIssueCode.invalid_type,\n                expected: ZodParsedType.array,\n                received: ctx.parsedType,\n            });\n            return INVALID;\n        }\n        if (ctx.data.length < this._def.items.length) {\n            addIssueToContext(ctx, {\n                code: ZodIssueCode.too_small,\n                minimum: this._def.items.length,\n                inclusive: true,\n                exact: false,\n                type: \"array\",\n            });\n            return INVALID;\n        }\n        const rest = this._def.rest;\n        if (!rest && ctx.data.length > this._def.items.length) {\n            addIssueToContext(ctx, {\n                code: ZodIssueCode.too_big,\n                maximum: this._def.items.length,\n                inclusive: true,\n                exact: false,\n                type: \"array\",\n            });\n            status.dirty();\n        }\n        const items = [...ctx.data]\n            .map((item, itemIndex) => {\n            const schema = this._def.items[itemIndex] || this._def.rest;\n            if (!schema)\n                return null;\n            return schema._parse(new ParseInputLazyPath(ctx, item, ctx.path, itemIndex));\n        })\n            .filter((x) => !!x); // filter nulls\n        if (ctx.common.async) {\n            return Promise.all(items).then((results) => {\n                return ParseStatus.mergeArray(status, results);\n            });\n        }\n        else {\n            return ParseStatus.mergeArray(status, items);\n        }\n    }\n    get items() {\n        return this._def.items;\n    }\n    rest(rest) {\n        return new ZodTuple({\n            ...this._def,\n            rest,\n        });\n    }\n}\nZodTuple.create = (schemas, params) => {\n    if (!Array.isArray(schemas)) {\n        throw new Error(\"You must pass an array of schemas to z.tuple([ ... ])\");\n    }\n    return new ZodTuple({\n        items: schemas,\n        typeName: ZodFirstPartyTypeKind.ZodTuple,\n        rest: null,\n        ...processCreateParams(params),\n    });\n};\nexport class ZodRecord extends ZodType {\n    get keySchema() {\n        return this._def.keyType;\n    }\n    get valueSchema() {\n        return this._def.valueType;\n    }\n    _parse(input) {\n        const { status, ctx } = this._processInputParams(input);\n        if (ctx.parsedType !== ZodParsedType.object) {\n            addIssueToContext(ctx, {\n                code: ZodIssueCode.invalid_type,\n                expected: ZodParsedType.object,\n                received: ctx.parsedType,\n            });\n            return INVALID;\n        }\n        const pairs = [];\n        const keyType = this._def.keyType;\n        const valueType = this._def.valueType;\n        for (const key in ctx.data) {\n            pairs.push({\n                key: keyType._parse(new ParseInputLazyPath(ctx, key, ctx.path, key)),\n                value: valueType._parse(new ParseInputLazyPath(ctx, ctx.data[key], ctx.path, key)),\n                alwaysSet: key in ctx.data,\n            });\n        }\n        if (ctx.common.async) {\n            return ParseStatus.mergeObjectAsync(status, pairs);\n        }\n        else {\n            return ParseStatus.mergeObjectSync(status, pairs);\n        }\n    }\n    get element() {\n        return this._def.valueType;\n    }\n    static create(first, second, third) {\n        if (second instanceof ZodType) {\n            return new ZodRecord({\n                keyType: first,\n                valueType: second,\n                typeName: ZodFirstPartyTypeKind.ZodRecord,\n                ...processCreateParams(third),\n            });\n        }\n        return new ZodRecord({\n            keyType: ZodString.create(),\n            valueType: first,\n            typeName: ZodFirstPartyTypeKind.ZodRecord,\n            ...processCreateParams(second),\n        });\n    }\n}\nexport class ZodMap extends ZodType {\n    get keySchema() {\n        return this._def.keyType;\n    }\n    get valueSchema() {\n        return this._def.valueType;\n    }\n    _parse(input) {\n        const { status, ctx } = this._processInputParams(input);\n        if (ctx.parsedType !== ZodParsedType.map) {\n            addIssueToContext(ctx, {\n                code: ZodIssueCode.invalid_type,\n                expected: ZodParsedType.map,\n                received: ctx.parsedType,\n            });\n            return INVALID;\n        }\n        const keyType = this._def.keyType;\n        const valueType = this._def.valueType;\n        const pairs = [...ctx.data.entries()].map(([key, value], index) => {\n            return {\n                key: keyType._parse(new ParseInputLazyPath(ctx, key, ctx.path, [index, \"key\"])),\n                value: valueType._parse(new ParseInputLazyPath(ctx, value, ctx.path, [index, \"value\"])),\n            };\n        });\n        if (ctx.common.async) {\n            const finalMap = new Map();\n            return Promise.resolve().then(async () => {\n                for (const pair of pairs) {\n                    const key = await pair.key;\n                    const value = await pair.value;\n                    if (key.status === \"aborted\" || value.status === \"aborted\") {\n                        return INVALID;\n                    }\n                    if (key.status === \"dirty\" || value.status === \"dirty\") {\n                        status.dirty();\n                    }\n                    finalMap.set(key.value, value.value);\n                }\n                return { status: status.value, value: finalMap };\n            });\n        }\n        else {\n            const finalMap = new Map();\n            for (const pair of pairs) {\n                const key = pair.key;\n                const value = pair.value;\n                if (key.status === \"aborted\" || value.status === \"aborted\") {\n                    return INVALID;\n                }\n                if (key.status === \"dirty\" || value.status === \"dirty\") {\n                    status.dirty();\n                }\n                finalMap.set(key.value, value.value);\n            }\n            return { status: status.value, value: finalMap };\n        }\n    }\n}\nZodMap.create = (keyType, valueType, params) => {\n    return new ZodMap({\n        valueType,\n        keyType,\n        typeName: ZodFirstPartyTypeKind.ZodMap,\n        ...processCreateParams(params),\n    });\n};\nexport class ZodSet extends ZodType {\n    _parse(input) {\n        const { status, ctx } = this._processInputParams(input);\n        if (ctx.parsedType !== ZodParsedType.set) {\n            addIssueToContext(ctx, {\n                code: ZodIssueCode.invalid_type,\n                expected: ZodParsedType.set,\n                received: ctx.parsedType,\n            });\n            return INVALID;\n        }\n        const def = this._def;\n        if (def.minSize !== null) {\n            if (ctx.data.size < def.minSize.value) {\n                addIssueToContext(ctx, {\n                    code: ZodIssueCode.too_small,\n                    minimum: def.minSize.value,\n                    type: \"set\",\n                    inclusive: true,\n                    exact: false,\n                    message: def.minSize.message,\n                });\n                status.dirty();\n            }\n        }\n        if (def.maxSize !== null) {\n            if (ctx.data.size > def.maxSize.value) {\n                addIssueToContext(ctx, {\n                    code: ZodIssueCode.too_big,\n                    maximum: def.maxSize.value,\n                    type: \"set\",\n                    inclusive: true,\n                    exact: false,\n                    message: def.maxSize.message,\n                });\n                status.dirty();\n            }\n        }\n        const valueType = this._def.valueType;\n        function finalizeSet(elements) {\n            const parsedSet = new Set();\n            for (const element of elements) {\n                if (element.status === \"aborted\")\n                    return INVALID;\n                if (element.status === \"dirty\")\n                    status.dirty();\n                parsedSet.add(element.value);\n            }\n            return { status: status.value, value: parsedSet };\n        }\n        const elements = [...ctx.data.values()].map((item, i) => valueType._parse(new ParseInputLazyPath(ctx, item, ctx.path, i)));\n        if (ctx.common.async) {\n            return Promise.all(elements).then((elements) => finalizeSet(elements));\n        }\n        else {\n            return finalizeSet(elements);\n        }\n    }\n    min(minSize, message) {\n        return new ZodSet({\n            ...this._def,\n            minSize: { value: minSize, message: errorUtil.toString(message) },\n        });\n    }\n    max(maxSize, message) {\n        return new ZodSet({\n            ...this._def,\n            maxSize: { value: maxSize, message: errorUtil.toString(message) },\n        });\n    }\n    size(size, message) {\n        return this.min(size, message).max(size, message);\n    }\n    nonempty(message) {\n        return this.min(1, message);\n    }\n}\nZodSet.create = (valueType, params) => {\n    return new ZodSet({\n        valueType,\n        minSize: null,\n        maxSize: null,\n        typeName: ZodFirstPartyTypeKind.ZodSet,\n        ...processCreateParams(params),\n    });\n};\nexport class ZodFunction extends ZodType {\n    constructor() {\n        super(...arguments);\n        this.validate = this.implement;\n    }\n    _parse(input) {\n        const { ctx } = this._processInputParams(input);\n        if (ctx.parsedType !== ZodParsedType.function) {\n            addIssueToContext(ctx, {\n                code: ZodIssueCode.invalid_type,\n                expected: ZodParsedType.function,\n                received: ctx.parsedType,\n            });\n            return INVALID;\n        }\n        function makeArgsIssue(args, error) {\n            return makeIssue({\n                data: args,\n                path: ctx.path,\n                errorMaps: [ctx.common.contextualErrorMap, ctx.schemaErrorMap, getErrorMap(), defaultErrorMap].filter((x) => !!x),\n                issueData: {\n                    code: ZodIssueCode.invalid_arguments,\n                    argumentsError: error,\n                },\n            });\n        }\n        function makeReturnsIssue(returns, error) {\n            return makeIssue({\n                data: returns,\n                path: ctx.path,\n                errorMaps: [ctx.common.contextualErrorMap, ctx.schemaErrorMap, getErrorMap(), defaultErrorMap].filter((x) => !!x),\n                issueData: {\n                    code: ZodIssueCode.invalid_return_type,\n                    returnTypeError: error,\n                },\n            });\n        }\n        const params = { errorMap: ctx.common.contextualErrorMap };\n        const fn = ctx.data;\n        if (this._def.returns instanceof ZodPromise) {\n            // Would love a way to avoid disabling this rule, but we need\n            // an alias (using an arrow function was what caused 2651).\n            // eslint-disable-next-line @typescript-eslint/no-this-alias\n            const me = this;\n            return OK(async function (...args) {\n                const error = new ZodError([]);\n                const parsedArgs = await me._def.args.parseAsync(args, params).catch((e) => {\n                    error.addIssue(makeArgsIssue(args, e));\n                    throw error;\n                });\n                const result = await Reflect.apply(fn, this, parsedArgs);\n                const parsedReturns = await me._def.returns._def.type\n                    .parseAsync(result, params)\n                    .catch((e) => {\n                    error.addIssue(makeReturnsIssue(result, e));\n                    throw error;\n                });\n                return parsedReturns;\n            });\n        }\n        else {\n            // Would love a way to avoid disabling this rule, but we need\n            // an alias (using an arrow function was what caused 2651).\n            // eslint-disable-next-line @typescript-eslint/no-this-alias\n            const me = this;\n            return OK(function (...args) {\n                const parsedArgs = me._def.args.safeParse(args, params);\n                if (!parsedArgs.success) {\n                    throw new ZodError([makeArgsIssue(args, parsedArgs.error)]);\n                }\n                const result = Reflect.apply(fn, this, parsedArgs.data);\n                const parsedReturns = me._def.returns.safeParse(result, params);\n                if (!parsedReturns.success) {\n                    throw new ZodError([makeReturnsIssue(result, parsedReturns.error)]);\n                }\n                return parsedReturns.data;\n            });\n        }\n    }\n    parameters() {\n        return this._def.args;\n    }\n    returnType() {\n        return this._def.returns;\n    }\n    args(...items) {\n        return new ZodFunction({\n            ...this._def,\n            args: ZodTuple.create(items).rest(ZodUnknown.create()),\n        });\n    }\n    returns(returnType) {\n        return new ZodFunction({\n            ...this._def,\n            returns: returnType,\n        });\n    }\n    implement(func) {\n        const validatedFunc = this.parse(func);\n        return validatedFunc;\n    }\n    strictImplement(func) {\n        const validatedFunc = this.parse(func);\n        return validatedFunc;\n    }\n    static create(args, returns, params) {\n        return new ZodFunction({\n            args: (args ? args : ZodTuple.create([]).rest(ZodUnknown.create())),\n            returns: returns || ZodUnknown.create(),\n            typeName: ZodFirstPartyTypeKind.ZodFunction,\n            ...processCreateParams(params),\n        });\n    }\n}\nexport class ZodLazy extends ZodType {\n    get schema() {\n        return this._def.getter();\n    }\n    _parse(input) {\n        const { ctx } = this._processInputParams(input);\n        const lazySchema = this._def.getter();\n        return lazySchema._parse({ data: ctx.data, path: ctx.path, parent: ctx });\n    }\n}\nZodLazy.create = (getter, params) => {\n    return new ZodLazy({\n        getter: getter,\n        typeName: ZodFirstPartyTypeKind.ZodLazy,\n        ...processCreateParams(params),\n    });\n};\nexport class ZodLiteral extends ZodType {\n    _parse(input) {\n        if (input.data !== this._def.value) {\n            const ctx = this._getOrReturnCtx(input);\n            addIssueToContext(ctx, {\n                received: ctx.data,\n                code: ZodIssueCode.invalid_literal,\n                expected: this._def.value,\n            });\n            return INVALID;\n        }\n        return { status: \"valid\", value: input.data };\n    }\n    get value() {\n        return this._def.value;\n    }\n}\nZodLiteral.create = (value, params) => {\n    return new ZodLiteral({\n        value: value,\n        typeName: ZodFirstPartyTypeKind.ZodLiteral,\n        ...processCreateParams(params),\n    });\n};\nfunction createZodEnum(values, params) {\n    return new ZodEnum({\n        values,\n        typeName: ZodFirstPartyTypeKind.ZodEnum,\n        ...processCreateParams(params),\n    });\n}\nexport class ZodEnum extends ZodType {\n    _parse(input) {\n        if (typeof input.data !== \"string\") {\n            const ctx = this._getOrReturnCtx(input);\n            const expectedValues = this._def.values;\n            addIssueToContext(ctx, {\n                expected: util.joinValues(expectedValues),\n                received: ctx.parsedType,\n                code: ZodIssueCode.invalid_type,\n            });\n            return INVALID;\n        }\n        if (!this._cache) {\n            this._cache = new Set(this._def.values);\n        }\n        if (!this._cache.has(input.data)) {\n            const ctx = this._getOrReturnCtx(input);\n            const expectedValues = this._def.values;\n            addIssueToContext(ctx, {\n                received: ctx.data,\n                code: ZodIssueCode.invalid_enum_value,\n                options: expectedValues,\n            });\n            return INVALID;\n        }\n        return OK(input.data);\n    }\n    get options() {\n        return this._def.values;\n    }\n    get enum() {\n        const enumValues = {};\n        for (const val of this._def.values) {\n            enumValues[val] = val;\n        }\n        return enumValues;\n    }\n    get Values() {\n        const enumValues = {};\n        for (const val of this._def.values) {\n            enumValues[val] = val;\n        }\n        return enumValues;\n    }\n    get Enum() {\n        const enumValues = {};\n        for (const val of this._def.values) {\n            enumValues[val] = val;\n        }\n        return enumValues;\n    }\n    extract(values, newDef = this._def) {\n        return ZodEnum.create(values, {\n            ...this._def,\n            ...newDef,\n        });\n    }\n    exclude(values, newDef = this._def) {\n        return ZodEnum.create(this.options.filter((opt) => !values.includes(opt)), {\n            ...this._def,\n            ...newDef,\n        });\n    }\n}\nZodEnum.create = createZodEnum;\nexport class ZodNativeEnum extends ZodType {\n    _parse(input) {\n        const nativeEnumValues = util.getValidEnumValues(this._def.values);\n        const ctx = this._getOrReturnCtx(input);\n        if (ctx.parsedType !== ZodParsedType.string && ctx.parsedType !== ZodParsedType.number) {\n            const expectedValues = util.objectValues(nativeEnumValues);\n            addIssueToContext(ctx, {\n                expected: util.joinValues(expectedValues),\n                received: ctx.parsedType,\n                code: ZodIssueCode.invalid_type,\n            });\n            return INVALID;\n        }\n        if (!this._cache) {\n            this._cache = new Set(util.getValidEnumValues(this._def.values));\n        }\n        if (!this._cache.has(input.data)) {\n            const expectedValues = util.objectValues(nativeEnumValues);\n            addIssueToContext(ctx, {\n                received: ctx.data,\n                code: ZodIssueCode.invalid_enum_value,\n                options: expectedValues,\n            });\n            return INVALID;\n        }\n        return OK(input.data);\n    }\n    get enum() {\n        return this._def.values;\n    }\n}\nZodNativeEnum.create = (values, params) => {\n    return new ZodNativeEnum({\n        values: values,\n        typeName: ZodFirstPartyTypeKind.ZodNativeEnum,\n        ...processCreateParams(params),\n    });\n};\nexport class ZodPromise extends ZodType {\n    unwrap() {\n        return this._def.type;\n    }\n    _parse(input) {\n        const { ctx } = this._processInputParams(input);\n        if (ctx.parsedType !== ZodParsedType.promise && ctx.common.async === false) {\n            addIssueToContext(ctx, {\n                code: ZodIssueCode.invalid_type,\n                expected: ZodParsedType.promise,\n                received: ctx.parsedType,\n            });\n            return INVALID;\n        }\n        const promisified = ctx.parsedType === ZodParsedType.promise ? ctx.data : Promise.resolve(ctx.data);\n        return OK(promisified.then((data) => {\n            return this._def.type.parseAsync(data, {\n                path: ctx.path,\n                errorMap: ctx.common.contextualErrorMap,\n            });\n        }));\n    }\n}\nZodPromise.create = (schema, params) => {\n    return new ZodPromise({\n        type: schema,\n        typeName: ZodFirstPartyTypeKind.ZodPromise,\n        ...processCreateParams(params),\n    });\n};\nexport class ZodEffects extends ZodType {\n    innerType() {\n        return this._def.schema;\n    }\n    sourceType() {\n        return this._def.schema._def.typeName === ZodFirstPartyTypeKind.ZodEffects\n            ? this._def.schema.sourceType()\n            : this._def.schema;\n    }\n    _parse(input) {\n        const { status, ctx } = this._processInputParams(input);\n        const effect = this._def.effect || null;\n        const checkCtx = {\n            addIssue: (arg) => {\n                addIssueToContext(ctx, arg);\n                if (arg.fatal) {\n                    status.abort();\n                }\n                else {\n                    status.dirty();\n                }\n            },\n            get path() {\n                return ctx.path;\n            },\n        };\n        checkCtx.addIssue = checkCtx.addIssue.bind(checkCtx);\n        if (effect.type === \"preprocess\") {\n            const processed = effect.transform(ctx.data, checkCtx);\n            if (ctx.common.async) {\n                return Promise.resolve(processed).then(async (processed) => {\n                    if (status.value === \"aborted\")\n                        return INVALID;\n                    const result = await this._def.schema._parseAsync({\n                        data: processed,\n                        path: ctx.path,\n                        parent: ctx,\n                    });\n                    if (result.status === \"aborted\")\n                        return INVALID;\n                    if (result.status === \"dirty\")\n                        return DIRTY(result.value);\n                    if (status.value === \"dirty\")\n                        return DIRTY(result.value);\n                    return result;\n                });\n            }\n            else {\n                if (status.value === \"aborted\")\n                    return INVALID;\n                const result = this._def.schema._parseSync({\n                    data: processed,\n                    path: ctx.path,\n                    parent: ctx,\n                });\n                if (result.status === \"aborted\")\n                    return INVALID;\n                if (result.status === \"dirty\")\n                    return DIRTY(result.value);\n                if (status.value === \"dirty\")\n                    return DIRTY(result.value);\n                return result;\n            }\n        }\n        if (effect.type === \"refinement\") {\n            const executeRefinement = (acc) => {\n                const result = effect.refinement(acc, checkCtx);\n                if (ctx.common.async) {\n                    return Promise.resolve(result);\n                }\n                if (result instanceof Promise) {\n                    throw new Error(\"Async refinement encountered during synchronous parse operation. Use .parseAsync instead.\");\n                }\n                return acc;\n            };\n            if (ctx.common.async === false) {\n                const inner = this._def.schema._parseSync({\n                    data: ctx.data,\n                    path: ctx.path,\n                    parent: ctx,\n                });\n                if (inner.status === \"aborted\")\n                    return INVALID;\n                if (inner.status === \"dirty\")\n                    status.dirty();\n                // return value is ignored\n                executeRefinement(inner.value);\n                return { status: status.value, value: inner.value };\n            }\n            else {\n                return this._def.schema._parseAsync({ data: ctx.data, path: ctx.path, parent: ctx }).then((inner) => {\n                    if (inner.status === \"aborted\")\n                        return INVALID;\n                    if (inner.status === \"dirty\")\n                        status.dirty();\n                    return executeRefinement(inner.value).then(() => {\n                        return { status: status.value, value: inner.value };\n                    });\n                });\n            }\n        }\n        if (effect.type === \"transform\") {\n            if (ctx.common.async === false) {\n                const base = this._def.schema._parseSync({\n                    data: ctx.data,\n                    path: ctx.path,\n                    parent: ctx,\n                });\n                if (!isValid(base))\n                    return INVALID;\n                const result = effect.transform(base.value, checkCtx);\n                if (result instanceof Promise) {\n                    throw new Error(`Asynchronous transform encountered during synchronous parse operation. Use .parseAsync instead.`);\n                }\n                return { status: status.value, value: result };\n            }\n            else {\n                return this._def.schema._parseAsync({ data: ctx.data, path: ctx.path, parent: ctx }).then((base) => {\n                    if (!isValid(base))\n                        return INVALID;\n                    return Promise.resolve(effect.transform(base.value, checkCtx)).then((result) => ({\n                        status: status.value,\n                        value: result,\n                    }));\n                });\n            }\n        }\n        util.assertNever(effect);\n    }\n}\nZodEffects.create = (schema, effect, params) => {\n    return new ZodEffects({\n        schema,\n        typeName: ZodFirstPartyTypeKind.ZodEffects,\n        effect,\n        ...processCreateParams(params),\n    });\n};\nZodEffects.createWithPreprocess = (preprocess, schema, params) => {\n    return new ZodEffects({\n        schema,\n        effect: { type: \"preprocess\", transform: preprocess },\n        typeName: ZodFirstPartyTypeKind.ZodEffects,\n        ...processCreateParams(params),\n    });\n};\nexport { ZodEffects as ZodTransformer };\nexport class ZodOptional extends ZodType {\n    _parse(input) {\n        const parsedType = this._getType(input);\n        if (parsedType === ZodParsedType.undefined) {\n            return OK(undefined);\n        }\n        return this._def.innerType._parse(input);\n    }\n    unwrap() {\n        return this._def.innerType;\n    }\n}\nZodOptional.create = (type, params) => {\n    return new ZodOptional({\n        innerType: type,\n        typeName: ZodFirstPartyTypeKind.ZodOptional,\n        ...processCreateParams(params),\n    });\n};\nexport class ZodNullable extends ZodType {\n    _parse(input) {\n        const parsedType = this._getType(input);\n        if (parsedType === ZodParsedType.null) {\n            return OK(null);\n        }\n        return this._def.innerType._parse(input);\n    }\n    unwrap() {\n        return this._def.innerType;\n    }\n}\nZodNullable.create = (type, params) => {\n    return new ZodNullable({\n        innerType: type,\n        typeName: ZodFirstPartyTypeKind.ZodNullable,\n        ...processCreateParams(params),\n    });\n};\nexport class ZodDefault extends ZodType {\n    _parse(input) {\n        const { ctx } = this._processInputParams(input);\n        let data = ctx.data;\n        if (ctx.parsedType === ZodParsedType.undefined) {\n            data = this._def.defaultValue();\n        }\n        return this._def.innerType._parse({\n            data,\n            path: ctx.path,\n            parent: ctx,\n        });\n    }\n    removeDefault() {\n        return this._def.innerType;\n    }\n}\nZodDefault.create = (type, params) => {\n    return new ZodDefault({\n        innerType: type,\n        typeName: ZodFirstPartyTypeKind.ZodDefault,\n        defaultValue: typeof params.default === \"function\" ? params.default : () => params.default,\n        ...processCreateParams(params),\n    });\n};\nexport class ZodCatch extends ZodType {\n    _parse(input) {\n        const { ctx } = this._processInputParams(input);\n        // newCtx is used to not collect issues from inner types in ctx\n        const newCtx = {\n            ...ctx,\n            common: {\n                ...ctx.common,\n                issues: [],\n            },\n        };\n        const result = this._def.innerType._parse({\n            data: newCtx.data,\n            path: newCtx.path,\n            parent: {\n                ...newCtx,\n            },\n        });\n        if (isAsync(result)) {\n            return result.then((result) => {\n                return {\n                    status: \"valid\",\n                    value: result.status === \"valid\"\n                        ? result.value\n                        : this._def.catchValue({\n                            get error() {\n                                return new ZodError(newCtx.common.issues);\n                            },\n                            input: newCtx.data,\n                        }),\n                };\n            });\n        }\n        else {\n            return {\n                status: \"valid\",\n                value: result.status === \"valid\"\n                    ? result.value\n                    : this._def.catchValue({\n                        get error() {\n                            return new ZodError(newCtx.common.issues);\n                        },\n                        input: newCtx.data,\n                    }),\n            };\n        }\n    }\n    removeCatch() {\n        return this._def.innerType;\n    }\n}\nZodCatch.create = (type, params) => {\n    return new ZodCatch({\n        innerType: type,\n        typeName: ZodFirstPartyTypeKind.ZodCatch,\n        catchValue: typeof params.catch === \"function\" ? params.catch : () => params.catch,\n        ...processCreateParams(params),\n    });\n};\nexport class ZodNaN extends ZodType {\n    _parse(input) {\n        const parsedType = this._getType(input);\n        if (parsedType !== ZodParsedType.nan) {\n            const ctx = this._getOrReturnCtx(input);\n            addIssueToContext(ctx, {\n                code: ZodIssueCode.invalid_type,\n                expected: ZodParsedType.nan,\n                received: ctx.parsedType,\n            });\n            return INVALID;\n        }\n        return { status: \"valid\", value: input.data };\n    }\n}\nZodNaN.create = (params) => {\n    return new ZodNaN({\n        typeName: ZodFirstPartyTypeKind.ZodNaN,\n        ...processCreateParams(params),\n    });\n};\nexport const BRAND = Symbol(\"zod_brand\");\nexport class ZodBranded extends ZodType {\n    _parse(input) {\n        const { ctx } = this._processInputParams(input);\n        const data = ctx.data;\n        return this._def.type._parse({\n            data,\n            path: ctx.path,\n            parent: ctx,\n        });\n    }\n    unwrap() {\n        return this._def.type;\n    }\n}\nexport class ZodPipeline extends ZodType {\n    _parse(input) {\n        const { status, ctx } = this._processInputParams(input);\n        if (ctx.common.async) {\n            const handleAsync = async () => {\n                const inResult = await this._def.in._parseAsync({\n                    data: ctx.data,\n                    path: ctx.path,\n                    parent: ctx,\n                });\n                if (inResult.status === \"aborted\")\n                    return INVALID;\n                if (inResult.status === \"dirty\") {\n                    status.dirty();\n                    return DIRTY(inResult.value);\n                }\n                else {\n                    return this._def.out._parseAsync({\n                        data: inResult.value,\n                        path: ctx.path,\n                        parent: ctx,\n                    });\n                }\n            };\n            return handleAsync();\n        }\n        else {\n            const inResult = this._def.in._parseSync({\n                data: ctx.data,\n                path: ctx.path,\n                parent: ctx,\n            });\n            if (inResult.status === \"aborted\")\n                return INVALID;\n            if (inResult.status === \"dirty\") {\n                status.dirty();\n                return {\n                    status: \"dirty\",\n                    value: inResult.value,\n                };\n            }\n            else {\n                return this._def.out._parseSync({\n                    data: inResult.value,\n                    path: ctx.path,\n                    parent: ctx,\n                });\n            }\n        }\n    }\n    static create(a, b) {\n        return new ZodPipeline({\n            in: a,\n            out: b,\n            typeName: ZodFirstPartyTypeKind.ZodPipeline,\n        });\n    }\n}\nexport class ZodReadonly extends ZodType {\n    _parse(input) {\n        const result = this._def.innerType._parse(input);\n        const freeze = (data) => {\n            if (isValid(data)) {\n                data.value = Object.freeze(data.value);\n            }\n            return data;\n        };\n        return isAsync(result) ? result.then((data) => freeze(data)) : freeze(result);\n    }\n    unwrap() {\n        return this._def.innerType;\n    }\n}\nZodReadonly.create = (type, params) => {\n    return new ZodReadonly({\n        innerType: type,\n        typeName: ZodFirstPartyTypeKind.ZodReadonly,\n        ...processCreateParams(params),\n    });\n};\n////////////////////////////////////////\n////////////////////////////////////////\n//////////                    //////////\n//////////      z.custom      //////////\n//////////                    //////////\n////////////////////////////////////////\n////////////////////////////////////////\nfunction cleanParams(params, data) {\n    const p = typeof params === \"function\" ? params(data) : typeof params === \"string\" ? { message: params } : params;\n    const p2 = typeof p === \"string\" ? { message: p } : p;\n    return p2;\n}\nexport function custom(check, _params = {}, \n/**\n * @deprecated\n *\n * Pass `fatal` into the params object instead:\n *\n * ```ts\n * z.string().custom((val) => val.length > 5, { fatal: false })\n * ```\n *\n */\nfatal) {\n    if (check)\n        return ZodAny.create().superRefine((data, ctx) => {\n            const r = check(data);\n            if (r instanceof Promise) {\n                return r.then((r) => {\n                    if (!r) {\n                        const params = cleanParams(_params, data);\n                        const _fatal = params.fatal ?? fatal ?? true;\n                        ctx.addIssue({ code: \"custom\", ...params, fatal: _fatal });\n                    }\n                });\n            }\n            if (!r) {\n                const params = cleanParams(_params, data);\n                const _fatal = params.fatal ?? fatal ?? true;\n                ctx.addIssue({ code: \"custom\", ...params, fatal: _fatal });\n            }\n            return;\n        });\n    return ZodAny.create();\n}\nexport { ZodType as Schema, ZodType as ZodSchema };\nexport const late = {\n    object: ZodObject.lazycreate,\n};\nexport var ZodFirstPartyTypeKind;\n(function (ZodFirstPartyTypeKind) {\n    ZodFirstPartyTypeKind[\"ZodString\"] = \"ZodString\";\n    ZodFirstPartyTypeKind[\"ZodNumber\"] = \"ZodNumber\";\n    ZodFirstPartyTypeKind[\"ZodNaN\"] = \"ZodNaN\";\n    ZodFirstPartyTypeKind[\"ZodBigInt\"] = \"ZodBigInt\";\n    ZodFirstPartyTypeKind[\"ZodBoolean\"] = \"ZodBoolean\";\n    ZodFirstPartyTypeKind[\"ZodDate\"] = \"ZodDate\";\n    ZodFirstPartyTypeKind[\"ZodSymbol\"] = \"ZodSymbol\";\n    ZodFirstPartyTypeKind[\"ZodUndefined\"] = \"ZodUndefined\";\n    ZodFirstPartyTypeKind[\"ZodNull\"] = \"ZodNull\";\n    ZodFirstPartyTypeKind[\"ZodAny\"] = \"ZodAny\";\n    ZodFirstPartyTypeKind[\"ZodUnknown\"] = \"ZodUnknown\";\n    ZodFirstPartyTypeKind[\"ZodNever\"] = \"ZodNever\";\n    ZodFirstPartyTypeKind[\"ZodVoid\"] = \"ZodVoid\";\n    ZodFirstPartyTypeKind[\"ZodArray\"] = \"ZodArray\";\n    ZodFirstPartyTypeKind[\"ZodObject\"] = \"ZodObject\";\n    ZodFirstPartyTypeKind[\"ZodUnion\"] = \"ZodUnion\";\n    ZodFirstPartyTypeKind[\"ZodDiscriminatedUnion\"] = \"ZodDiscriminatedUnion\";\n    ZodFirstPartyTypeKind[\"ZodIntersection\"] = \"ZodIntersection\";\n    ZodFirstPartyTypeKind[\"ZodTuple\"] = \"ZodTuple\";\n    ZodFirstPartyTypeKind[\"ZodRecord\"] = \"ZodRecord\";\n    ZodFirstPartyTypeKind[\"ZodMap\"] = \"ZodMap\";\n    ZodFirstPartyTypeKind[\"ZodSet\"] = \"ZodSet\";\n    ZodFirstPartyTypeKind[\"ZodFunction\"] = \"ZodFunction\";\n    ZodFirstPartyTypeKind[\"ZodLazy\"] = \"ZodLazy\";\n    ZodFirstPartyTypeKind[\"ZodLiteral\"] = \"ZodLiteral\";\n    ZodFirstPartyTypeKind[\"ZodEnum\"] = \"ZodEnum\";\n    ZodFirstPartyTypeKind[\"ZodEffects\"] = \"ZodEffects\";\n    ZodFirstPartyTypeKind[\"ZodNativeEnum\"] = \"ZodNativeEnum\";\n    ZodFirstPartyTypeKind[\"ZodOptional\"] = \"ZodOptional\";\n    ZodFirstPartyTypeKind[\"ZodNullable\"] = \"ZodNullable\";\n    ZodFirstPartyTypeKind[\"ZodDefault\"] = \"ZodDefault\";\n    ZodFirstPartyTypeKind[\"ZodCatch\"] = \"ZodCatch\";\n    ZodFirstPartyTypeKind[\"ZodPromise\"] = \"ZodPromise\";\n    ZodFirstPartyTypeKind[\"ZodBranded\"] = \"ZodBranded\";\n    ZodFirstPartyTypeKind[\"ZodPipeline\"] = \"ZodPipeline\";\n    ZodFirstPartyTypeKind[\"ZodReadonly\"] = \"ZodReadonly\";\n})(ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {}));\n// requires TS 4.4+\nclass Class {\n    constructor(..._) { }\n}\nconst instanceOfType = (\n// const instanceOfType = <T extends new (...args: any[]) => any>(\ncls, params = {\n    message: `Input not instance of ${cls.name}`,\n}) => custom((data) => data instanceof cls, params);\nconst stringType = ZodString.create;\nconst numberType = ZodNumber.create;\nconst nanType = ZodNaN.create;\nconst bigIntType = ZodBigInt.create;\nconst booleanType = ZodBoolean.create;\nconst dateType = ZodDate.create;\nconst symbolType = ZodSymbol.create;\nconst undefinedType = ZodUndefined.create;\nconst nullType = ZodNull.create;\nconst anyType = ZodAny.create;\nconst unknownType = ZodUnknown.create;\nconst neverType = ZodNever.create;\nconst voidType = ZodVoid.create;\nconst arrayType = ZodArray.create;\nconst objectType = ZodObject.create;\nconst strictObjectType = ZodObject.strictCreate;\nconst unionType = ZodUnion.create;\nconst discriminatedUnionType = ZodDiscriminatedUnion.create;\nconst intersectionType = ZodIntersection.create;\nconst tupleType = ZodTuple.create;\nconst recordType = ZodRecord.create;\nconst mapType = ZodMap.create;\nconst setType = ZodSet.create;\nconst functionType = ZodFunction.create;\nconst lazyType = ZodLazy.create;\nconst literalType = ZodLiteral.create;\nconst enumType = ZodEnum.create;\nconst nativeEnumType = ZodNativeEnum.create;\nconst promiseType = ZodPromise.create;\nconst effectsType = ZodEffects.create;\nconst optionalType = ZodOptional.create;\nconst nullableType = ZodNullable.create;\nconst preprocessType = ZodEffects.createWithPreprocess;\nconst pipelineType = ZodPipeline.create;\nconst ostring = () => stringType().optional();\nconst onumber = () => numberType().optional();\nconst oboolean = () => booleanType().optional();\nexport const coerce = {\n    string: ((arg) => ZodString.create({ ...arg, coerce: true })),\n    number: ((arg) => ZodNumber.create({ ...arg, coerce: true })),\n    boolean: ((arg) => ZodBoolean.create({\n        ...arg,\n        coerce: true,\n    })),\n    bigint: ((arg) => ZodBigInt.create({ ...arg, coerce: true })),\n    date: ((arg) => ZodDate.create({ ...arg, coerce: true })),\n};\nexport { anyType as any, arrayType as array, bigIntType as bigint, booleanType as boolean, dateType as date, discriminatedUnionType as discriminatedUnion, effectsType as effect, enumType as enum, functionType as function, instanceOfType as instanceof, intersectionType as intersection, lazyType as lazy, literalType as literal, mapType as map, nanType as nan, nativeEnumType as nativeEnum, neverType as never, nullType as null, nullableType as nullable, numberType as number, objectType as object, oboolean, onumber, optionalType as optional, ostring, pipelineType as pipeline, preprocessType as preprocess, promiseType as promise, recordType as record, setType as set, strictObjectType as strictObject, stringType as string, symbolType as symbol, effectsType as transformer, tupleType as tuple, undefinedType as undefined, unionType as union, unknownType as unknown, voidType as void, };\nexport const NEVER = INVALID;\n","export var errorUtil;\n(function (errorUtil) {\n    errorUtil.errToObj = (message) => typeof message === \"string\" ? { message } : message || {};\n    // biome-ignore lint:\n    errorUtil.toString = (message) => typeof message === \"string\" ? message : message?.message;\n})(errorUtil || (errorUtil = {}));\n","export * from \"./errorMessages.js\";\nexport * from \"./Options.js\";\nexport * from \"./parseDef.js\";\nexport * from \"./parsers/any.js\";\nexport * from \"./parsers/array.js\";\nexport * from \"./parsers/bigint.js\";\nexport * from \"./parsers/boolean.js\";\nexport * from \"./parsers/branded.js\";\nexport * from \"./parsers/catch.js\";\nexport * from \"./parsers/date.js\";\nexport * from \"./parsers/default.js\";\nexport * from \"./parsers/effects.js\";\nexport * from \"./parsers/enum.js\";\nexport * from \"./parsers/intersection.js\";\nexport * from \"./parsers/literal.js\";\nexport * from \"./parsers/map.js\";\nexport * from \"./parsers/nativeEnum.js\";\nexport * from \"./parsers/never.js\";\nexport * from \"./parsers/null.js\";\nexport * from \"./parsers/nullable.js\";\nexport * from \"./parsers/number.js\";\nexport * from \"./parsers/object.js\";\nexport * from \"./parsers/optional.js\";\nexport * from \"./parsers/pipeline.js\";\nexport * from \"./parsers/promise.js\";\nexport * from \"./parsers/readonly.js\";\nexport * from \"./parsers/record.js\";\nexport * from \"./parsers/set.js\";\nexport * from \"./parsers/string.js\";\nexport * from \"./parsers/tuple.js\";\nexport * from \"./parsers/undefined.js\";\nexport * from \"./parsers/union.js\";\nexport * from \"./parsers/unknown.js\";\nexport * from \"./Refs.js\";\nexport * from \"./zodToJsonSchema.js\";\nimport { zodToJsonSchema } from \"./zodToJsonSchema.js\";\nexport default zodToJsonSchema;\n","export function addErrorMessage(res, key, errorMessage, refs) {\n    if (!refs?.errorMessages)\n        return;\n    if (errorMessage) {\n        res.errorMessage = {\n            ...res.errorMessage,\n            [key]: errorMessage,\n        };\n    }\n}\nexport function setResponseValueAndErrors(res, key, value, errorMessage, refs) {\n    res[key] = value;\n    addErrorMessage(res, key, errorMessage, refs);\n}\n","export const defaultOptions = {\n    name: undefined,\n    $refStrategy: \"root\",\n    basePath: [\"#\"],\n    effectStrategy: \"input\",\n    pipeStrategy: \"all\",\n    dateStrategy: \"string\",\n    mapStrategy: \"entries\",\n    definitionPath: \"definitions\",\n    target: \"jsonSchema7\",\n    strictUnions: false,\n    definitions: {},\n    errorMessages: false,\n    markdownDescription: false,\n    patternStrategy: \"escape\",\n    emailStrategy: \"format:email\",\n};\nexport const getDefaultOptions = (options) => (typeof options === \"string\"\n    ? {\n        ...defaultOptions,\n        name: options,\n    }\n    : {\n        ...defaultOptions,\n        ...options,\n    });\n","import { ZodFirstPartyTypeKind } from \"zod\";\nimport { parseAnyDef } from \"./parsers/any.js\";\nimport { parseArrayDef } from \"./parsers/array.js\";\nimport { parseBigintDef } from \"./parsers/bigint.js\";\nimport { parseBooleanDef } from \"./parsers/boolean.js\";\nimport { parseBrandedDef } from \"./parsers/branded.js\";\nimport { parseCatchDef } from \"./parsers/catch.js\";\nimport { parseDateDef } from \"./parsers/date.js\";\nimport { parseDefaultDef } from \"./parsers/default.js\";\nimport { parseEffectsDef } from \"./parsers/effects.js\";\nimport { parseEnumDef } from \"./parsers/enum.js\";\nimport { parseIntersectionDef, } from \"./parsers/intersection.js\";\nimport { parseLiteralDef } from \"./parsers/literal.js\";\nimport { parseMapDef } from \"./parsers/map.js\";\nimport { parseNativeEnumDef, } from \"./parsers/nativeEnum.js\";\nimport { parseNeverDef } from \"./parsers/never.js\";\nimport { parseNullDef } from \"./parsers/null.js\";\nimport { parseNullableDef, } from \"./parsers/nullable.js\";\nimport { parseNumberDef } from \"./parsers/number.js\";\nimport { parseObjectDef } from \"./parsers/object.js\";\nimport { parseOptionalDef } from \"./parsers/optional.js\";\nimport { parsePipelineDef } from \"./parsers/pipeline.js\";\nimport { parsePromiseDef } from \"./parsers/promise.js\";\nimport { parseRecordDef } from \"./parsers/record.js\";\nimport { parseSetDef } from \"./parsers/set.js\";\nimport { parseStringDef } from \"./parsers/string.js\";\nimport { parseTupleDef } from \"./parsers/tuple.js\";\nimport { parseUndefinedDef, } from \"./parsers/undefined.js\";\nimport { parseUnionDef } from \"./parsers/union.js\";\nimport { parseUnknownDef } from \"./parsers/unknown.js\";\nimport { parseReadonlyDef } from \"./parsers/readonly.js\";\nexport function parseDef(def, refs, forceResolution = false) {\n    const seenItem = refs.seen.get(def);\n    if (seenItem && !forceResolution) {\n        const seenSchema = get$ref(seenItem, refs);\n        if (seenSchema !== undefined) {\n            return seenSchema;\n        }\n    }\n    const newItem = { def, path: refs.currentPath, jsonSchema: undefined };\n    refs.seen.set(def, newItem);\n    const jsonSchema = selectParser(def, def.typeName, refs);\n    if (jsonSchema) {\n        addMeta(def, refs, jsonSchema);\n    }\n    newItem.jsonSchema = jsonSchema;\n    return jsonSchema;\n}\nconst get$ref = (item, refs) => {\n    switch (refs.$refStrategy) {\n        case \"root\":\n            return { $ref: item.path.join(\"/\") };\n        case \"relative\":\n            return { $ref: getRelativePath(refs.currentPath, item.path) };\n        case \"none\":\n        case \"seen\": {\n            if (item.path.length < refs.currentPath.length &&\n                item.path.every((value, index) => refs.currentPath[index] === value)) {\n                console.warn(`Recursive reference detected at ${refs.currentPath.join(\"/\")}! Defaulting to any`);\n                return {};\n            }\n            return refs.$refStrategy === \"seen\" ? {} : undefined;\n        }\n    }\n};\nconst getRelativePath = (pathA, pathB) => {\n    let i = 0;\n    for (; i < pathA.length && i < pathB.length; i++) {\n        if (pathA[i] !== pathB[i])\n            break;\n    }\n    return [(pathA.length - i).toString(), ...pathB.slice(i)].join(\"/\");\n};\nconst selectParser = (def, typeName, refs) => {\n    switch (typeName) {\n        case ZodFirstPartyTypeKind.ZodString:\n            return parseStringDef(def, refs);\n        case ZodFirstPartyTypeKind.ZodNumber:\n            return parseNumberDef(def, refs);\n        case ZodFirstPartyTypeKind.ZodObject:\n            return parseObjectDef(def, refs);\n        case ZodFirstPartyTypeKind.ZodBigInt:\n            return parseBigintDef(def, refs);\n        case ZodFirstPartyTypeKind.ZodBoolean:\n            return parseBooleanDef();\n        case ZodFirstPartyTypeKind.ZodDate:\n            return parseDateDef(def, refs);\n        case ZodFirstPartyTypeKind.ZodUndefined:\n            return parseUndefinedDef();\n        case ZodFirstPartyTypeKind.ZodNull:\n            return parseNullDef(refs);\n        case ZodFirstPartyTypeKind.ZodArray:\n            return parseArrayDef(def, refs);\n        case ZodFirstPartyTypeKind.ZodUnion:\n        case ZodFirstPartyTypeKind.ZodDiscriminatedUnion:\n            return parseUnionDef(def, refs);\n        case ZodFirstPartyTypeKind.ZodIntersection:\n            return parseIntersectionDef(def, refs);\n        case ZodFirstPartyTypeKind.ZodTuple:\n            return parseTupleDef(def, refs);\n        case ZodFirstPartyTypeKind.ZodRecord:\n            return parseRecordDef(def, refs);\n        case ZodFirstPartyTypeKind.ZodLiteral:\n            return parseLiteralDef(def, refs);\n        case ZodFirstPartyTypeKind.ZodEnum:\n            return parseEnumDef(def);\n        case ZodFirstPartyTypeKind.ZodNativeEnum:\n            return parseNativeEnumDef(def);\n        case ZodFirstPartyTypeKind.ZodNullable:\n            return parseNullableDef(def, refs);\n        case ZodFirstPartyTypeKind.ZodOptional:\n            return parseOptionalDef(def, refs);\n        case ZodFirstPartyTypeKind.ZodMap:\n            return parseMapDef(def, refs);\n        case ZodFirstPartyTypeKind.ZodSet:\n            return parseSetDef(def, refs);\n        case ZodFirstPartyTypeKind.ZodLazy:\n            return parseDef(def.getter()._def, refs);\n        case ZodFirstPartyTypeKind.ZodPromise:\n            return parsePromiseDef(def, refs);\n        case ZodFirstPartyTypeKind.ZodNaN:\n        case ZodFirstPartyTypeKind.ZodNever:\n            return parseNeverDef();\n        case ZodFirstPartyTypeKind.ZodEffects:\n            return parseEffectsDef(def, refs);\n        case ZodFirstPartyTypeKind.ZodAny:\n            return parseAnyDef();\n        case ZodFirstPartyTypeKind.ZodUnknown:\n            return parseUnknownDef();\n        case ZodFirstPartyTypeKind.ZodDefault:\n            return parseDefaultDef(def, refs);\n        case ZodFirstPartyTypeKind.ZodBranded:\n            return parseBrandedDef(def, refs);\n        case ZodFirstPartyTypeKind.ZodReadonly:\n            return parseReadonlyDef(def, refs);\n        case ZodFirstPartyTypeKind.ZodCatch:\n            return parseCatchDef(def, refs);\n        case ZodFirstPartyTypeKind.ZodPipeline:\n            return parsePipelineDef(def, refs);\n        case ZodFirstPartyTypeKind.ZodFunction:\n        case ZodFirstPartyTypeKind.ZodVoid:\n        case ZodFirstPartyTypeKind.ZodSymbol:\n            return undefined;\n        default:\n            return ((_) => undefined)(typeName);\n    }\n};\nconst addMeta = (def, refs, jsonSchema) => {\n    if (def.description) {\n        jsonSchema.description = def.description;\n        if (refs.markdownDescription) {\n            jsonSchema.markdownDescription = def.description;\n        }\n    }\n    return jsonSchema;\n};\n","export function parseAnyDef() {\n    return {};\n}\n","import { ZodFirstPartyTypeKind } from \"zod\";\nimport { setResponseValueAndErrors } from \"../errorMessages.js\";\nimport { parseDef } from \"../parseDef.js\";\nexport function parseArrayDef(def, refs) {\n    const res = {\n        type: \"array\",\n    };\n    if (def.type?._def?.typeName !== ZodFirstPartyTypeKind.ZodAny) {\n        res.items = parseDef(def.type._def, {\n            ...refs,\n            currentPath: [...refs.currentPath, \"items\"],\n        });\n    }\n    if (def.minLength) {\n        setResponseValueAndErrors(res, \"minItems\", def.minLength.value, def.minLength.message, refs);\n    }\n    if (def.maxLength) {\n        setResponseValueAndErrors(res, \"maxItems\", def.maxLength.value, def.maxLength.message, refs);\n    }\n    if (def.exactLength) {\n        setResponseValueAndErrors(res, \"minItems\", def.exactLength.value, def.exactLength.message, refs);\n        setResponseValueAndErrors(res, \"maxItems\", def.exactLength.value, def.exactLength.message, refs);\n    }\n    return res;\n}\n","import { setResponseValueAndErrors } from \"../errorMessages.js\";\nexport function parseBigintDef(def, refs) {\n    const res = {\n        type: \"integer\",\n        format: \"int64\",\n    };\n    if (!def.checks)\n        return res;\n    for (const check of def.checks) {\n        switch (check.kind) {\n            case \"min\":\n                if (refs.target === \"jsonSchema7\") {\n                    if (check.inclusive) {\n                        setResponseValueAndErrors(res, \"minimum\", check.value, check.message, refs);\n                    }\n                    else {\n                        setResponseValueAndErrors(res, \"exclusiveMinimum\", check.value, check.message, refs);\n                    }\n                }\n                else {\n                    if (!check.inclusive) {\n                        res.exclusiveMinimum = true;\n                    }\n                    setResponseValueAndErrors(res, \"minimum\", check.value, check.message, refs);\n                }\n                break;\n            case \"max\":\n                if (refs.target === \"jsonSchema7\") {\n                    if (check.inclusive) {\n                        setResponseValueAndErrors(res, \"maximum\", check.value, check.message, refs);\n                    }\n                    else {\n                        setResponseValueAndErrors(res, \"exclusiveMaximum\", check.value, check.message, refs);\n                    }\n                }\n                else {\n                    if (!check.inclusive) {\n                        res.exclusiveMaximum = true;\n                    }\n                    setResponseValueAndErrors(res, \"maximum\", check.value, check.message, refs);\n                }\n                break;\n            case \"multipleOf\":\n                setResponseValueAndErrors(res, \"multipleOf\", check.value, check.message, refs);\n                break;\n        }\n    }\n    return res;\n}\n","export function parseBooleanDef() {\n    return {\n        type: \"boolean\",\n    };\n}\n","import { parseDef } from \"../parseDef.js\";\nexport function parseBrandedDef(_def, refs) {\n    return parseDef(_def.type._def, refs);\n}\n","import { parseDef } from \"../parseDef.js\";\nexport const parseCatchDef = (def, refs) => {\n    return parseDef(def.innerType._def, refs);\n};\n","import { setResponseValueAndErrors } from \"../errorMessages.js\";\nexport function parseDateDef(def, refs) {\n    if (refs.dateStrategy == \"integer\") {\n        return integerDateParser(def, refs);\n    }\n    else {\n        return {\n            type: \"string\",\n            format: \"date-time\",\n        };\n    }\n}\nconst integerDateParser = (def, refs) => {\n    const res = {\n        type: \"integer\",\n        format: \"unix-time\",\n    };\n    for (const check of def.checks) {\n        switch (check.kind) {\n            case \"min\":\n                if (refs.target === \"jsonSchema7\") {\n                    setResponseValueAndErrors(res, \"minimum\", check.value, // This is in milliseconds\n                    check.message, refs);\n                }\n                break;\n            case \"max\":\n                if (refs.target === \"jsonSchema7\") {\n                    setResponseValueAndErrors(res, \"maximum\", check.value, // This is in milliseconds\n                    check.message, refs);\n                }\n                break;\n        }\n    }\n    return res;\n};\n","import { parseDef } from \"../parseDef.js\";\nexport function parseDefaultDef(_def, refs) {\n    return {\n        ...parseDef(_def.innerType._def, refs),\n        default: _def.defaultValue(),\n    };\n}\n","import { parseDef } from \"../parseDef.js\";\nexport function parseEffectsDef(_def, refs) {\n    return refs.effectStrategy === \"input\"\n        ? parseDef(_def.schema._def, refs)\n        : {};\n}\n","export function parseEnumDef(def) {\n    return {\n        type: \"string\",\n        enum: def.values,\n    };\n}\n","import { parseDef } from \"../parseDef.js\";\nconst isJsonSchema7AllOfType = (type) => {\n    if (\"type\" in type && type.type === \"string\")\n        return false;\n    return \"allOf\" in type;\n};\nexport function parseIntersectionDef(def, refs) {\n    const allOf = [\n        parseDef(def.left._def, {\n            ...refs,\n            currentPath: [...refs.currentPath, \"allOf\", \"0\"],\n        }),\n        parseDef(def.right._def, {\n            ...refs,\n            currentPath: [...refs.currentPath, \"allOf\", \"1\"],\n        }),\n    ].filter((x) => !!x);\n    let unevaluatedProperties = refs.target === \"jsonSchema2019-09\"\n        ? { unevaluatedProperties: false }\n        : undefined;\n    const mergedAllOf = [];\n    // If either of the schemas is an allOf, merge them into a single allOf\n    allOf.forEach((schema) => {\n        if (isJsonSchema7AllOfType(schema)) {\n            mergedAllOf.push(...schema.allOf);\n            if (schema.unevaluatedProperties === undefined) {\n                // If one of the schemas has no unevaluatedProperties set,\n                // the merged schema should also have no unevaluatedProperties set\n                unevaluatedProperties = undefined;\n            }\n        }\n        else {\n            let nestedSchema = schema;\n            if (\"additionalProperties\" in schema &&\n                schema.additionalProperties === false) {\n                const { additionalProperties, ...rest } = schema;\n                nestedSchema = rest;\n            }\n            else {\n                // As soon as one of the schemas has additionalProperties set not to false, we allow unevaluatedProperties\n                unevaluatedProperties = undefined;\n            }\n            mergedAllOf.push(nestedSchema);\n        }\n    });\n    return mergedAllOf.length\n        ? {\n            allOf: mergedAllOf,\n            ...unevaluatedProperties,\n        }\n        : undefined;\n}\n","export function parseLiteralDef(def, refs) {\n    const parsedType = typeof def.value;\n    if (parsedType !== \"bigint\" &&\n        parsedType !== \"number\" &&\n        parsedType !== \"boolean\" &&\n        parsedType !== \"string\") {\n        return {\n            type: Array.isArray(def.value) ? \"array\" : \"object\",\n        };\n    }\n    if (refs.target === \"openApi3\") {\n        return {\n            type: parsedType === \"bigint\" ? \"integer\" : parsedType,\n            enum: [def.value],\n        };\n    }\n    return {\n        type: parsedType === \"bigint\" ? \"integer\" : parsedType,\n        const: def.value,\n    };\n}\n","import { parseDef } from \"../parseDef.js\";\nimport { parseRecordDef } from \"./record.js\";\nexport function parseMapDef(def, refs) {\n    if (refs.mapStrategy === \"record\") {\n        return parseRecordDef(def, refs);\n    }\n    const keys = parseDef(def.keyType._def, {\n        ...refs,\n        currentPath: [...refs.currentPath, \"items\", \"items\", \"0\"],\n    }) || {};\n    const values = parseDef(def.valueType._def, {\n        ...refs,\n        currentPath: [...refs.currentPath, \"items\", \"items\", \"1\"],\n    }) || {};\n    return {\n        type: \"array\",\n        maxItems: 125,\n        items: {\n            type: \"array\",\n            items: [keys, values],\n            minItems: 2,\n            maxItems: 2,\n        },\n    };\n}\n","import { ZodFirstPartyTypeKind, } from \"zod\";\nimport { parseDef } from \"../parseDef.js\";\nimport { parseStringDef } from \"./string.js\";\nexport function parseRecordDef(def, refs) {\n    if (refs.target === \"openApi3\" &&\n        def.keyType?._def.typeName === ZodFirstPartyTypeKind.ZodEnum) {\n        return {\n            type: \"object\",\n            required: def.keyType._def.values,\n            properties: def.keyType._def.values.reduce((acc, key) => ({\n                ...acc,\n                [key]: parseDef(def.valueType._def, {\n                    ...refs,\n                    currentPath: [...refs.currentPath, \"properties\", key],\n                }) ?? {},\n            }), {}),\n            additionalProperties: false,\n        };\n    }\n    const schema = {\n        type: \"object\",\n        additionalProperties: parseDef(def.valueType._def, {\n            ...refs,\n            currentPath: [...refs.currentPath, \"additionalProperties\"],\n        }) ?? {},\n    };\n    if (refs.target === \"openApi3\") {\n        return schema;\n    }\n    if (def.keyType?._def.typeName === ZodFirstPartyTypeKind.ZodString &&\n        def.keyType._def.checks?.length) {\n        const keyType = Object.entries(parseStringDef(def.keyType._def, refs)).reduce((acc, [key, value]) => (key === \"type\" ? acc : { ...acc, [key]: value }), {});\n        return {\n            ...schema,\n            propertyNames: keyType,\n        };\n    }\n    else if (def.keyType?._def.typeName === ZodFirstPartyTypeKind.ZodEnum) {\n        return {\n            ...schema,\n            propertyNames: {\n                enum: def.keyType._def.values,\n            },\n        };\n    }\n    return schema;\n}\n","import { setResponseValueAndErrors } from \"../errorMessages.js\";\n/**\n * Generated from the .source property of regular expressins found here:\n * https://github.com/colinhacks/zod/blob/master/src/types.ts.\n *\n * Escapes have been doubled, and expressions with /i flag have been changed accordingly\n */\nexport const zodPatterns = {\n    /**\n     * `c` was changed to `[cC]` to replicate /i flag\n     */\n    cuid: \"^[cC][^\\\\s-]{8,}$\",\n    cuid2: \"^[a-z][a-z0-9]*$\",\n    ulid: \"^[0-9A-HJKMNP-TV-Z]{26}$\",\n    /**\n     * `a-z` was added to replicate /i flag\n     */\n    email: \"^(?!\\\\.)(?!.*\\\\.\\\\.)([a-zA-Z0-9_+-\\\\.]*)[a-zA-Z0-9_+-]@([a-zA-Z0-9][a-zA-Z0-9\\\\-]*\\\\.)+[a-zA-Z]{2,}$\",\n    emoji: \"^(\\\\p{Extended_Pictographic}|\\\\p{Emoji_Component})+$\",\n    /**\n     * Unused\n     */\n    uuid: \"^[0-9a-fA-F]{8}\\\\b-[0-9a-fA-F]{4}\\\\b-[0-9a-fA-F]{4}\\\\b-[0-9a-fA-F]{4}\\\\b-[0-9a-fA-F]{12}$\",\n    /**\n     * Unused\n     */\n    ipv4: \"^(((25[0-5])|(2[0-4][0-9])|(1[0-9]{2})|([0-9]{1,2}))\\\\.){3}((25[0-5])|(2[0-4][0-9])|(1[0-9]{2})|([0-9]{1,2}))$\",\n    /**\n     * Unused\n     */\n    ipv6: \"^(([a-f0-9]{1,4}:){7}|::([a-f0-9]{1,4}:){0,6}|([a-f0-9]{1,4}:){1}:([a-f0-9]{1,4}:){0,5}|([a-f0-9]{1,4}:){2}:([a-f0-9]{1,4}:){0,4}|([a-f0-9]{1,4}:){3}:([a-f0-9]{1,4}:){0,3}|([a-f0-9]{1,4}:){4}:([a-f0-9]{1,4}:){0,2}|([a-f0-9]{1,4}:){5}:([a-f0-9]{1,4}:){0,1})([a-f0-9]{1,4}|(((25[0-5])|(2[0-4][0-9])|(1[0-9]{2})|([0-9]{1,2}))\\\\.){3}((25[0-5])|(2[0-4][0-9])|(1[0-9]{2})|([0-9]{1,2})))$\",\n};\nexport function parseStringDef(def, refs) {\n    const res = {\n        type: \"string\",\n    };\n    function processPattern(value) {\n        return refs.patternStrategy === \"escape\"\n            ? escapeNonAlphaNumeric(value)\n            : value;\n    }\n    if (def.checks) {\n        for (const check of def.checks) {\n            switch (check.kind) {\n                case \"min\":\n                    setResponseValueAndErrors(res, \"minLength\", typeof res.minLength === \"number\"\n                        ? Math.max(res.minLength, check.value)\n                        : check.value, check.message, refs);\n                    break;\n                case \"max\":\n                    setResponseValueAndErrors(res, \"maxLength\", typeof res.maxLength === \"number\"\n                        ? Math.min(res.maxLength, check.value)\n                        : check.value, check.message, refs);\n                    break;\n                case \"email\":\n                    switch (refs.emailStrategy) {\n                        case \"format:email\":\n                            addFormat(res, \"email\", check.message, refs);\n                            break;\n                        case \"format:idn-email\":\n                            addFormat(res, \"idn-email\", check.message, refs);\n                            break;\n                        case \"pattern:zod\":\n                            addPattern(res, zodPatterns.email, check.message, refs);\n                            break;\n                    }\n                    break;\n                case \"url\":\n                    addFormat(res, \"uri\", check.message, refs);\n                    break;\n                case \"uuid\":\n                    addFormat(res, \"uuid\", check.message, refs);\n                    break;\n                case \"regex\":\n                    addPattern(res, check.regex.source, check.message, refs);\n                    break;\n                case \"cuid\":\n                    addPattern(res, zodPatterns.cuid, check.message, refs);\n                    break;\n                case \"cuid2\":\n                    addPattern(res, zodPatterns.cuid2, check.message, refs);\n                    break;\n                case \"startsWith\":\n                    addPattern(res, \"^\" + processPattern(check.value), check.message, refs);\n                    break;\n                case \"endsWith\":\n                    addPattern(res, processPattern(check.value) + \"$\", check.message, refs);\n                    break;\n                case \"datetime\":\n                    addFormat(res, \"date-time\", check.message, refs);\n                    break;\n                case \"length\":\n                    setResponseValueAndErrors(res, \"minLength\", typeof res.minLength === \"number\"\n                        ? Math.max(res.minLength, check.value)\n                        : check.value, check.message, refs);\n                    setResponseValueAndErrors(res, \"maxLength\", typeof res.maxLength === \"number\"\n                        ? Math.min(res.maxLength, check.value)\n                        : check.value, check.message, refs);\n                    break;\n                case \"includes\": {\n                    addPattern(res, processPattern(check.value), check.message, refs);\n                    break;\n                }\n                case \"ip\": {\n                    if (check.version !== \"v6\") {\n                        addFormat(res, \"ipv4\", check.message, refs);\n                    }\n                    if (check.version !== \"v4\") {\n                        addFormat(res, \"ipv6\", check.message, refs);\n                    }\n                    break;\n                }\n                case \"emoji\":\n                    addPattern(res, zodPatterns.emoji, check.message, refs);\n                    break;\n                case \"ulid\": {\n                    addPattern(res, zodPatterns.ulid, check.message, refs);\n                    break;\n                }\n                case \"toLowerCase\":\n                case \"toUpperCase\":\n                case \"trim\":\n                    // I have no idea why these are checks in Zod 🤷\n                    break;\n                default:\n                    ((_) => { })(check);\n            }\n        }\n    }\n    return res;\n}\nconst escapeNonAlphaNumeric = (value) => Array.from(value)\n    .map((c) => (/[a-zA-Z0-9]/.test(c) ? c : `\\\\${c}`))\n    .join(\"\");\nconst addFormat = (schema, value, message, refs) => {\n    if (schema.format || schema.anyOf?.some((x) => x.format)) {\n        if (!schema.anyOf) {\n            schema.anyOf = [];\n        }\n        if (schema.format) {\n            schema.anyOf.push({\n                format: schema.format,\n                ...(schema.errorMessage &&\n                    refs.errorMessages && {\n                    errorMessage: { format: schema.errorMessage.format },\n                }),\n            });\n            delete schema.format;\n            if (schema.errorMessage) {\n                delete schema.errorMessage.format;\n                if (Object.keys(schema.errorMessage).length === 0) {\n                    delete schema.errorMessage;\n                }\n            }\n        }\n        schema.anyOf.push({\n            format: value,\n            ...(message &&\n                refs.errorMessages && { errorMessage: { format: message } }),\n        });\n    }\n    else {\n        setResponseValueAndErrors(schema, \"format\", value, message, refs);\n    }\n};\nconst addPattern = (schema, value, message, refs) => {\n    if (schema.pattern || schema.allOf?.some((x) => x.pattern)) {\n        if (!schema.allOf) {\n            schema.allOf = [];\n        }\n        if (schema.pattern) {\n            schema.allOf.push({\n                pattern: schema.pattern,\n                ...(schema.errorMessage &&\n                    refs.errorMessages && {\n                    errorMessage: { pattern: schema.errorMessage.pattern },\n                }),\n            });\n            delete schema.pattern;\n            if (schema.errorMessage) {\n                delete schema.errorMessage.pattern;\n                if (Object.keys(schema.errorMessage).length === 0) {\n                    delete schema.errorMessage;\n                }\n            }\n        }\n        schema.allOf.push({\n            pattern: value,\n            ...(message &&\n                refs.errorMessages && { errorMessage: { pattern: message } }),\n        });\n    }\n    else {\n        setResponseValueAndErrors(schema, \"pattern\", value, message, refs);\n    }\n};\n","export function parseNativeEnumDef(def) {\n    const object = def.values;\n    const actualKeys = Object.keys(def.values).filter((key) => {\n        return typeof object[object[key]] !== \"number\";\n    });\n    const actualValues = actualKeys.map((key) => object[key]);\n    const parsedTypes = Array.from(new Set(actualValues.map((values) => typeof values)));\n    return {\n        type: parsedTypes.length === 1\n            ? parsedTypes[0] === \"string\"\n                ? \"string\"\n                : \"number\"\n            : [\"string\", \"number\"],\n        enum: actualValues,\n    };\n}\n","export function parseNeverDef() {\n    return {\n        not: {},\n    };\n}\n","export function parseNullDef(refs) {\n    return refs.target === \"openApi3\"\n        ? {\n            enum: [\"null\"],\n            nullable: true,\n        }\n        : {\n            type: \"null\",\n        };\n}\n","import { parseDef } from \"../parseDef.js\";\nimport { primitiveMappings } from \"./union.js\";\nexport function parseNullableDef(def, refs) {\n    if ([\"ZodString\", \"ZodNumber\", \"ZodBigInt\", \"ZodBoolean\", \"ZodNull\"].includes(def.innerType._def.typeName) &&\n        (!def.innerType._def.checks || !def.innerType._def.checks.length)) {\n        if (refs.target === \"openApi3\") {\n            return {\n                type: primitiveMappings[def.innerType._def.typeName],\n                nullable: true,\n            };\n        }\n        return {\n            type: [\n                primitiveMappings[def.innerType._def.typeName],\n                \"null\",\n            ],\n        };\n    }\n    if (refs.target === \"openApi3\") {\n        const base = parseDef(def.innerType._def, {\n            ...refs,\n            currentPath: [...refs.currentPath],\n        });\n        if (base && '$ref' in base)\n            return { allOf: [base], nullable: true };\n        return base && { ...base, nullable: true };\n    }\n    const base = parseDef(def.innerType._def, {\n        ...refs,\n        currentPath: [...refs.currentPath, \"anyOf\", \"0\"],\n    });\n    return base && { anyOf: [base, { type: \"null\" }] };\n}\n","import { parseDef } from \"../parseDef.js\";\nexport const primitiveMappings = {\n    ZodString: \"string\",\n    ZodNumber: \"number\",\n    ZodBigInt: \"integer\",\n    ZodBoolean: \"boolean\",\n    ZodNull: \"null\",\n};\nexport function parseUnionDef(def, refs) {\n    if (refs.target === \"openApi3\")\n        return asAnyOf(def, refs);\n    const options = def.options instanceof Map ? Array.from(def.options.values()) : def.options;\n    // This blocks tries to look ahead a bit to produce nicer looking schemas with type array instead of anyOf.\n    if (options.every((x) => x._def.typeName in primitiveMappings &&\n        (!x._def.checks || !x._def.checks.length))) {\n        // all types in union are primitive and lack checks, so might as well squash into {type: [...]}\n        const types = options.reduce((types, x) => {\n            const type = primitiveMappings[x._def.typeName]; //Can be safely casted due to row 43\n            return type && !types.includes(type) ? [...types, type] : types;\n        }, []);\n        return {\n            type: types.length > 1 ? types : types[0],\n        };\n    }\n    else if (options.every((x) => x._def.typeName === \"ZodLiteral\" && !x.description)) {\n        // all options literals\n        const types = options.reduce((acc, x) => {\n            const type = typeof x._def.value;\n            switch (type) {\n                case \"string\":\n                case \"number\":\n                case \"boolean\":\n                    return [...acc, type];\n                case \"bigint\":\n                    return [...acc, \"integer\"];\n                case \"object\":\n                    if (x._def.value === null)\n                        return [...acc, \"null\"];\n                case \"symbol\":\n                case \"undefined\":\n                case \"function\":\n                default:\n                    return acc;\n            }\n        }, []);\n        if (types.length === options.length) {\n            // all the literals are primitive, as far as null can be considered primitive\n            const uniqueTypes = types.filter((x, i, a) => a.indexOf(x) === i);\n            return {\n                type: uniqueTypes.length > 1 ? uniqueTypes : uniqueTypes[0],\n                enum: options.reduce((acc, x) => {\n                    return acc.includes(x._def.value) ? acc : [...acc, x._def.value];\n                }, []),\n            };\n        }\n    }\n    else if (options.every((x) => x._def.typeName === \"ZodEnum\")) {\n        return {\n            type: \"string\",\n            enum: options.reduce((acc, x) => [\n                ...acc,\n                ...x._def.values.filter((x) => !acc.includes(x)),\n            ], []),\n        };\n    }\n    return asAnyOf(def, refs);\n}\nconst asAnyOf = (def, refs) => {\n    const anyOf = (def.options instanceof Map\n        ? Array.from(def.options.values())\n        : def.options)\n        .map((x, i) => parseDef(x._def, {\n        ...refs,\n        currentPath: [...refs.currentPath, \"anyOf\", `${i}`],\n    }))\n        .filter((x) => !!x &&\n        (!refs.strictUnions ||\n            (typeof x === \"object\" && Object.keys(x).length > 0)));\n    return anyOf.length ? { anyOf } : undefined;\n};\n","import { addErrorMessage, setResponseValueAndErrors, } from \"../errorMessages.js\";\nexport function parseNumberDef(def, refs) {\n    const res = {\n        type: \"number\",\n    };\n    if (!def.checks)\n        return res;\n    for (const check of def.checks) {\n        switch (check.kind) {\n            case \"int\":\n                res.type = \"integer\";\n                addErrorMessage(res, \"type\", check.message, refs);\n                break;\n            case \"min\":\n                if (refs.target === \"jsonSchema7\") {\n                    if (check.inclusive) {\n                        setResponseValueAndErrors(res, \"minimum\", check.value, check.message, refs);\n                    }\n                    else {\n                        setResponseValueAndErrors(res, \"exclusiveMinimum\", check.value, check.message, refs);\n                    }\n                }\n                else {\n                    if (!check.inclusive) {\n                        res.exclusiveMinimum = true;\n                    }\n                    setResponseValueAndErrors(res, \"minimum\", check.value, check.message, refs);\n                }\n                break;\n            case \"max\":\n                if (refs.target === \"jsonSchema7\") {\n                    if (check.inclusive) {\n                        setResponseValueAndErrors(res, \"maximum\", check.value, check.message, refs);\n                    }\n                    else {\n                        setResponseValueAndErrors(res, \"exclusiveMaximum\", check.value, check.message, refs);\n                    }\n                }\n                else {\n                    if (!check.inclusive) {\n                        res.exclusiveMaximum = true;\n                    }\n                    setResponseValueAndErrors(res, \"maximum\", check.value, check.message, refs);\n                }\n                break;\n            case \"multipleOf\":\n                setResponseValueAndErrors(res, \"multipleOf\", check.value, check.message, refs);\n                break;\n        }\n    }\n    return res;\n}\n","import { parseDef } from \"../parseDef.js\";\nexport function parseObjectDefX(def, refs) {\n    Object.keys(def.shape()).reduce((schema, key) => {\n        let prop = def.shape()[key];\n        const isOptional = prop.isOptional();\n        if (!isOptional) {\n            prop = { ...prop._def.innerSchema };\n        }\n        const propSchema = parseDef(prop._def, {\n            ...refs,\n            currentPath: [...refs.currentPath, \"properties\", key],\n            propertyPath: [...refs.currentPath, \"properties\", key],\n        });\n        if (propSchema !== undefined) {\n            schema.properties[key] = propSchema;\n            if (!isOptional) {\n                if (!schema.required) {\n                    schema.required = [];\n                }\n                schema.required.push(key);\n            }\n        }\n        return schema;\n    }, {\n        type: \"object\",\n        properties: {},\n        additionalProperties: def.catchall._def.typeName === \"ZodNever\"\n            ? def.unknownKeys === \"passthrough\"\n            : parseDef(def.catchall._def, {\n                ...refs,\n                currentPath: [...refs.currentPath, \"additionalProperties\"],\n            }) ?? true,\n    });\n    const result = {\n        type: \"object\",\n        ...Object.entries(def.shape()).reduce((acc, [propName, propDef]) => {\n            if (propDef === undefined || propDef._def === undefined)\n                return acc;\n            const parsedDef = parseDef(propDef._def, {\n                ...refs,\n                currentPath: [...refs.currentPath, \"properties\", propName],\n                propertyPath: [...refs.currentPath, \"properties\", propName],\n            });\n            if (parsedDef === undefined)\n                return acc;\n            return {\n                properties: { ...acc.properties, [propName]: parsedDef },\n                required: propDef.isOptional()\n                    ? acc.required\n                    : [...acc.required, propName],\n            };\n        }, { properties: {}, required: [] }),\n        additionalProperties: def.catchall._def.typeName === \"ZodNever\"\n            ? def.unknownKeys === \"passthrough\"\n            : parseDef(def.catchall._def, {\n                ...refs,\n                currentPath: [...refs.currentPath, \"additionalProperties\"],\n            }) ?? true,\n    };\n    if (!result.required.length)\n        delete result.required;\n    return result;\n}\nexport function parseObjectDef(def, refs) {\n    const result = {\n        type: \"object\",\n        ...Object.entries(def.shape()).reduce((acc, [propName, propDef]) => {\n            if (propDef === undefined || propDef._def === undefined)\n                return acc;\n            const parsedDef = parseDef(propDef._def, {\n                ...refs,\n                currentPath: [...refs.currentPath, \"properties\", propName],\n                propertyPath: [...refs.currentPath, \"properties\", propName],\n            });\n            if (parsedDef === undefined)\n                return acc;\n            return {\n                properties: { ...acc.properties, [propName]: parsedDef },\n                required: propDef.isOptional()\n                    ? acc.required\n                    : [...acc.required, propName],\n            };\n        }, { properties: {}, required: [] }),\n        additionalProperties: def.catchall._def.typeName === \"ZodNever\"\n            ? def.unknownKeys === \"passthrough\"\n            : parseDef(def.catchall._def, {\n                ...refs,\n                currentPath: [...refs.currentPath, \"additionalProperties\"],\n            }) ?? true,\n    };\n    if (!result.required.length)\n        delete result.required;\n    return result;\n}\n","import { parseDef } from \"../parseDef.js\";\nexport const parseOptionalDef = (def, refs) => {\n    if (refs.currentPath.toString() === refs.propertyPath?.toString()) {\n        return parseDef(def.innerType._def, refs);\n    }\n    const innerSchema = parseDef(def.innerType._def, {\n        ...refs,\n        currentPath: [...refs.currentPath, \"anyOf\", \"1\"],\n    });\n    return innerSchema\n        ? {\n            anyOf: [\n                {\n                    not: {},\n                },\n                innerSchema,\n            ],\n        }\n        : {};\n};\n","import { parseDef } from \"../parseDef.js\";\nexport const parsePipelineDef = (def, refs) => {\n    if (refs.pipeStrategy === \"input\") {\n        return parseDef(def.in._def, refs);\n    }\n    else if (refs.pipeStrategy === \"output\") {\n        return parseDef(def.out._def, refs);\n    }\n    const a = parseDef(def.in._def, {\n        ...refs,\n        currentPath: [...refs.currentPath, \"allOf\", \"0\"],\n    });\n    const b = parseDef(def.out._def, {\n        ...refs,\n        currentPath: [...refs.currentPath, \"allOf\", a ? \"1\" : \"0\"],\n    });\n    return {\n        allOf: [a, b].filter((x) => x !== undefined),\n    };\n};\n","import { parseDef } from \"../parseDef.js\";\nexport function parsePromiseDef(def, refs) {\n    return parseDef(def.type._def, refs);\n}\n","import { setResponseValueAndErrors } from \"../errorMessages.js\";\nimport { parseDef } from \"../parseDef.js\";\nexport function parseSetDef(def, refs) {\n    const items = parseDef(def.valueType._def, {\n        ...refs,\n        currentPath: [...refs.currentPath, \"items\"],\n    });\n    const schema = {\n        type: \"array\",\n        uniqueItems: true,\n        items,\n    };\n    if (def.minSize) {\n        setResponseValueAndErrors(schema, \"minItems\", def.minSize.value, def.minSize.message, refs);\n    }\n    if (def.maxSize) {\n        setResponseValueAndErrors(schema, \"maxItems\", def.maxSize.value, def.maxSize.message, refs);\n    }\n    return schema;\n}\n","import { parseDef } from \"../parseDef.js\";\nexport function parseTupleDef(def, refs) {\n    if (def.rest) {\n        return {\n            type: \"array\",\n            minItems: def.items.length,\n            items: def.items\n                .map((x, i) => parseDef(x._def, {\n                ...refs,\n                currentPath: [...refs.currentPath, \"items\", `${i}`],\n            }))\n                .reduce((acc, x) => (x === undefined ? acc : [...acc, x]), []),\n            additionalItems: parseDef(def.rest._def, {\n                ...refs,\n                currentPath: [...refs.currentPath, \"additionalItems\"],\n            }),\n        };\n    }\n    else {\n        return {\n            type: \"array\",\n            minItems: def.items.length,\n            maxItems: def.items.length,\n            items: def.items\n                .map((x, i) => parseDef(x._def, {\n                ...refs,\n                currentPath: [...refs.currentPath, \"items\", `${i}`],\n            }))\n                .reduce((acc, x) => (x === undefined ? acc : [...acc, x]), []),\n        };\n    }\n}\n","export function parseUndefinedDef() {\n    return {\n        not: {},\n    };\n}\n","export function parseUnknownDef() {\n    return {};\n}\n","import { parseDef } from \"../parseDef.js\";\nexport const parseReadonlyDef = (def, refs) => {\n    return parseDef(def.innerType._def, refs);\n};\n","import { getDefaultOptions } from \"./Options.js\";\nexport const getRefs = (options) => {\n    const _options = getDefaultOptions(options);\n    const currentPath = _options.name !== undefined\n        ? [..._options.basePath, _options.definitionPath, _options.name]\n        : _options.basePath;\n    return {\n        ..._options,\n        currentPath: currentPath,\n        propertyPath: undefined,\n        seen: new Map(Object.entries(_options.definitions).map(([name, def]) => [\n            def._def,\n            {\n                def: def._def,\n                path: [..._options.basePath, _options.definitionPath, name],\n                // Resolution of references will be forced even though seen, so it's ok that the schema is undefined here for now.\n                jsonSchema: undefined,\n            },\n        ])),\n    };\n};\n","import { parseDef } from \"./parseDef.js\";\nimport { getRefs } from \"./Refs.js\";\nconst zodToJsonSchema = (schema, options) => {\n    const refs = getRefs(options);\n    const definitions = typeof options === \"object\" && options.definitions\n        ? Object.entries(options.definitions).reduce((acc, [name, schema]) => ({\n            ...acc,\n            [name]: parseDef(schema._def, {\n                ...refs,\n                currentPath: [...refs.basePath, refs.definitionPath, name],\n            }, true) ?? {},\n        }), {})\n        : undefined;\n    const name = typeof options === \"string\" ? options : options?.name;\n    const main = parseDef(schema._def, name === undefined\n        ? refs\n        : {\n            ...refs,\n            currentPath: [...refs.basePath, refs.definitionPath, name],\n        }, false) ?? {};\n    const combined = name === undefined\n        ? definitions\n            ? {\n                ...main,\n                [refs.definitionPath]: definitions,\n            }\n            : main\n        : {\n            $ref: [\n                ...(refs.$refStrategy === \"relative\" ? [] : refs.basePath),\n                refs.definitionPath,\n                name,\n            ].join(\"/\"),\n            [refs.definitionPath]: {\n                ...definitions,\n                [name]: main,\n            },\n        };\n    if (refs.target === \"jsonSchema7\") {\n        combined.$schema = \"http://json-schema.org/draft-07/schema#\";\n    }\n    else if (refs.target === \"jsonSchema2019-09\") {\n        combined.$schema = \"https://json-schema.org/draft/2019-09/schema#\";\n    }\n    return combined;\n};\nexport { zodToJsonSchema };\n","export {\n  Browser,\n  BrowserViewport,\n  BrowserScreen,\n  BrowserFingerprint,\n  BrowserFingerprintContext,\n  BrowserProxy,\n  BrowserProxyClass,\n  BrowserOption,\n  BrowserOptionClass,\n  BrowserNotifyMessage,\n} from \"./browser\";\nexport type { BrowserCallback } from \"./browser\";\nexport { BrowserOperator } from \"./browser_operator\";\nexport type {\n  ActOptions,\n  ActResult,\n  ObserveOptions,\n  ObserveResult,\n  ExtractOptions,\n} from \"./browser_operator\";\nexport {\n  FingerprintFormat,\n  BrowserFingerprintGenerator,\n  type ScreenFingerprint,\n  type Brand,\n  type UserAgentData,\n  type ExtraProperties,\n  type NavigatorFingerprint,\n  type VideoCard,\n  type Fingerprint,\n} from \"./fingerprint\";\n","import { Session } from \"../session\";\nimport { BrowserOperator } from \"./browser_operator\";\nimport { BrowserError } from \"../exceptions\";\nimport { InitBrowserRequest } from \"../api/models/InitBrowserRequest\";\nimport { FingerprintFormat } from \"./fingerprint\";\n\n// Browser data path constant (moved from config.ts)\nconst BROWSER_DATA_PATH = \"/tmp/agentbay_browser\";\n// Browser fingerprint persistent path constant (moved from config.ts)\nconst BROWSER_FINGERPRINT_PERSIST_PATH = \"/tmp/browser_fingerprint\";\nimport {\n  log,\n  logError,\n  logInfo,\n  logDebug,\n  logAPICall,\n  logAPIResponseWithDetails,\n  setRequestId,\n} from \"../utils/logger\";\n\nexport interface BrowserViewport {\n  width: number;\n  height: number;\n}\n\nexport interface BrowserScreen {\n  width: number;\n  height: number;\n}\n\n/**\n * Browser notify message for SDK and sandbox communication, like call-for-user messages.\n *\n * @example\n * ```typescript\n * const notifyMsg = new BrowserNotifyMessage(\n *   'call-for-user',\n *   3,\n *   201,\n *   'captcha solving start',\n *   'pause',\n *   { max_wait_time: 30 }\n * );\n * ```\n */\nexport class BrowserNotifyMessage {\n  type?: string;\n  id?: number;\n  code?: number;\n  message?: string;\n  action?: string;\n  extraParams?: Record<string, any>;\n\n  constructor(\n    type?: string,\n    id?: number,\n    code?: number,\n    message?: string,\n    action?: string,\n    extraParams?: Record<string, any>\n  ) {\n    this.type = type;\n    this.id = id;\n    this.code = code;\n    this.message = message;\n    this.action = action;\n    this.extraParams = extraParams || {};\n  }\n\n  /**\n   * Convert BrowserNotifyMessage to dictionary format.\n   */\n  toMap(): Record<string, any> {\n    const notifyMap: Record<string, any> = {};\n\n    if (this.type !== undefined) notifyMap.type = this.type;\n    if (this.id !== undefined) notifyMap.id = this.id;\n    if (this.code !== undefined) notifyMap.code = this.code;\n    if (this.message !== undefined) notifyMap.message = this.message;\n    if (this.action !== undefined) notifyMap.action = this.action;\n    if (this.extraParams && Object.keys(this.extraParams).length > 0) {\n      notifyMap.extraParams = this.extraParams;\n    }\n\n    return notifyMap;\n  }\n\n  /**\n   * Create BrowserNotifyMessage from dictionary format.\n   */\n  static fromMap(m?: Record<string, any>): BrowserNotifyMessage | null {\n    if (!m) return null;\n\n    return new BrowserNotifyMessage(\n      m.type,\n      m.id,\n      m.code,\n      m.message,\n      m.action,\n      m.extraParams\n    );\n  }\n}\n\n/**\n * Type alias for browser callback function\n */\nexport type BrowserCallback = (notifyMsg: BrowserNotifyMessage) => void;\n\nexport interface BrowserFingerprint {\n  devices?: Array<\"desktop\" | \"mobile\">;\n  operatingSystems?: Array<\"windows\" | \"macos\" | \"linux\" | \"android\" | \"ios\">;\n  locales?: string[];\n}\n\n/**\n * Browser fingerprint context configuration.\n */\nexport class BrowserFingerprintContext {\n  /** ID of the fingerprint context for browser fingerprint */\n  fingerprintContextId: string;\n\n  /**\n   * Initialize BrowserFingerprintContext with context id.\n   *\n   * @param fingerprintContextId - ID of the fingerprint context for browser fingerprint.\n   *\n   * @throws {Error} If fingerprintContextId is empty.\n   */\n  constructor(fingerprintContextId: string) {\n    if (!fingerprintContextId || !fingerprintContextId.trim()) {\n      throw new Error(\"fingerprintContextId cannot be empty\");\n    }\n\n    this.fingerprintContextId = fingerprintContextId;\n  }\n}\n\nexport interface BrowserProxy {\n  type: \"custom\" | \"wuying\" | \"managed\";\n  server?: string;\n  username?: string;\n  password?: string;\n  strategy?: \"restricted\" | \"polling\" | \"sticky\" | \"rotating\" | \"matched\";\n  pollsize?: number;\n  userId?: string;\n  isp?: string;\n  country?: string;\n  province?: string;\n  city?: string;\n  toMap(): Record<string, any>;\n}\n\nexport class BrowserProxyClass implements BrowserProxy {\n  type: \"custom\" | \"wuying\" | \"managed\";\n  server?: string;\n  username?: string;\n  password?: string;\n  strategy?: \"restricted\" | \"polling\" | \"sticky\" | \"rotating\" | \"matched\";\n  pollsize?: number;\n  userId?: string;\n  isp?: string;\n  country?: string;\n  province?: string;\n  city?: string;\n\n  constructor(\n    proxyType: \"custom\" | \"wuying\" | \"managed\",\n    server?: string,\n    username?: string,\n    password?: string,\n    strategy?: \"restricted\" | \"polling\" | \"sticky\" | \"rotating\" | \"matched\",\n    pollsize?: number,\n    userId?: string,\n    isp?: string,\n    country?: string,\n    province?: string,\n    city?: string\n  ) {\n    this.type = proxyType;\n    this.server = server;\n    this.username = username;\n    this.password = password;\n    this.strategy = strategy;\n    this.pollsize = pollsize;\n    this.userId = userId;\n    this.isp = isp;\n    this.country = country;\n    this.province = province;\n    this.city = city;\n\n    // Validation\n    if (\n      proxyType !== \"custom\" &&\n      proxyType !== \"wuying\" &&\n      proxyType !== \"managed\"\n    ) {\n      throw new Error(\"proxy_type must be custom, wuying, or managed\");\n    }\n\n    if (proxyType === \"custom\" && !server) {\n      throw new Error(\"server is required for custom proxy type\");\n    }\n\n    if (proxyType === \"wuying\") {\n      if (!strategy) {\n        throw new Error(\"strategy is required for wuying proxy type\");\n      }\n      if (strategy !== \"restricted\" && strategy !== \"polling\") {\n        throw new Error(\n          \"strategy must be restricted or polling for wuying proxy type\"\n        );\n      }\n      if (strategy === \"polling\" && pollsize !== undefined && pollsize <= 0) {\n        throw new Error(\"pollsize must be greater than 0 for polling strategy\");\n      }\n    }\n\n    if (proxyType === \"managed\") {\n      if (!strategy) {\n        throw new Error(\"strategy is required for managed proxy type\");\n      }\n      if (\n        strategy !== \"polling\" &&\n        strategy !== \"sticky\" &&\n        strategy !== \"rotating\" &&\n        strategy !== \"matched\"\n      ) {\n        throw new Error(\n          \"strategy must be polling, sticky, rotating, or matched for managed proxy type\"\n        );\n      }\n      if (!userId) {\n        throw new Error(\"userId is required for managed proxy type\");\n      }\n      if (strategy === \"matched\" && !isp && !country && !province && !city) {\n        throw new Error(\n          \"at least one of isp, country, province, or city is required for matched strategy\"\n        );\n      }\n    }\n  }\n\n  toMap(): Record<string, any> {\n    const proxyMap: Record<string, any> = {\n      type: this.type,\n    };\n\n    if (this.type === \"custom\") {\n      proxyMap.server = this.server;\n      if (this.username) {\n        proxyMap.username = this.username;\n      }\n      if (this.password) {\n        proxyMap.password = this.password;\n      }\n    } else if (this.type === \"wuying\") {\n      proxyMap.strategy = this.strategy;\n      if (this.strategy === \"polling\") {\n        proxyMap.pollsize = this.pollsize;\n      }\n    } else if (this.type === \"managed\") {\n      proxyMap.strategy = this.strategy;\n      if (this.userId) {\n        proxyMap.userId = this.userId;\n      }\n      if (this.isp) {\n        proxyMap.isp = this.isp;\n      }\n      if (this.country) {\n        proxyMap.country = this.country;\n      }\n      if (this.province) {\n        proxyMap.province = this.province;\n      }\n      if (this.city) {\n        proxyMap.city = this.city;\n      }\n    }\n\n    return proxyMap;\n  }\n\n  static fromMap(\n    m: Record<string, any> | null | undefined\n  ): BrowserProxyClass | null {\n    if (!m || typeof m !== \"object\") {\n      return null;\n    }\n\n    const proxyType = m.type;\n    if (!proxyType) {\n      return null;\n    }\n\n    if (proxyType === \"custom\") {\n      return new BrowserProxyClass(proxyType, m.server, m.username, m.password);\n    } else if (proxyType === \"wuying\") {\n      return new BrowserProxyClass(\n        proxyType,\n        undefined,\n        undefined,\n        undefined,\n        m.strategy,\n        m.pollsize || 10\n      );\n    } else if (proxyType === \"managed\") {\n      return new BrowserProxyClass(\n        proxyType,\n        undefined,\n        undefined,\n        undefined,\n        m.strategy,\n        undefined,\n        m.userId,\n        m.isp,\n        m.country,\n        m.province,\n        m.city\n      );\n    } else {\n      throw new Error(`Unsupported proxy type: ${proxyType}`);\n    }\n  }\n}\n\nexport interface BrowserOption {\n  persistentPath?: string;\n  useStealth?: boolean;\n  userAgent?: string;\n  viewport?: BrowserViewport;\n  screen?: BrowserScreen;\n  fingerprint?: BrowserFingerprint;\n  /** Browser fingerprint format data for detailed fingerprint configuration */\n  fingerprintFormat?: FingerprintFormat;\n  /** Whether to enable fingerprint persistence across sessions */\n  fingerprintPersistent?: boolean;\n  solveCaptchas?: boolean;\n  /** Whether to enable auto login feature */\n  autoLogin?: boolean;\n  /** Whether to enable call for user feature */\n  callForUser?: boolean;\n  proxies?: BrowserProxy[];\n  /** Path to the extensions directory. Defaults to \"/tmp/extensions/\" */\n  extensionPath?: string;\n  /** Additional command line arguments for the browser */\n  cmdArgs?: string[];\n  /** Default URL to navigate to when browser starts */\n  defaultNavigateUrl?: string;\n  /** Browser type: 'chrome' or 'chromium'. Defaults to undefined */\n  browserType?: \"chrome\" | \"chromium\" | undefined;\n}\n\nexport class BrowserOptionClass implements BrowserOption {\n  persistentPath?: string;\n  useStealth?: boolean;\n  userAgent?: string;\n  viewport?: BrowserViewport;\n  screen?: BrowserScreen;\n  fingerprint?: BrowserFingerprint;\n  fingerprintFormat?: FingerprintFormat;\n  fingerprintPersistent?: boolean;\n  fingerprintPersistPath?: string;\n  solveCaptchas?: boolean;\n  autoLogin?: boolean;\n  callForUser?: boolean;\n  proxies?: BrowserProxy[];\n  extensionPath?: string;\n  cmdArgs?: string[];\n  defaultNavigateUrl?: string;\n  browserType?: \"chrome\" | \"chromium\" | undefined;\n\n  constructor(\n    useStealth = false,\n    userAgent?: string,\n    viewport?: BrowserViewport,\n    screen?: BrowserScreen,\n    fingerprint?: BrowserFingerprint,\n    fingerprintFormat?: FingerprintFormat,\n    fingerprintPersistent = false,\n    solveCaptchas = false,\n    autoLogin = false,\n    callForUser = false,\n    proxies?: BrowserProxy[],\n    cmdArgs?: string[],\n    defaultNavigateUrl?: string,\n    browserType?: \"chrome\" | \"chromium\"\n  ) {\n    this.useStealth = useStealth;\n    this.userAgent = userAgent;\n    this.viewport = viewport;\n    this.screen = screen;\n    this.fingerprint = fingerprint;\n    this.fingerprintFormat = fingerprintFormat;\n    this.fingerprintPersistent = fingerprintPersistent;\n    this.solveCaptchas = solveCaptchas;\n    this.autoLogin = autoLogin;\n    this.callForUser = callForUser;\n    this.extensionPath = \"/tmp/extensions/\";\n    this.cmdArgs = cmdArgs;\n    this.defaultNavigateUrl = defaultNavigateUrl;\n    this.browserType = browserType;\n\n    // Check fingerprint persistent if provided\n    if (fingerprintPersistent) {\n      // Currently only support persistent fingerprint in docker env\n      this.fingerprintPersistPath = `${BROWSER_FINGERPRINT_PERSIST_PATH}/fingerprint.json`;\n    } else {\n      this.fingerprintPersistPath = undefined;\n    }\n\n    // Validate proxies list items\n    if (proxies !== undefined) {\n      if (!Array.isArray(proxies)) {\n        throw new Error(\"proxies must be a list\");\n      }\n      if (proxies.length > 1) {\n        throw new Error(\"proxies list length must be limited to 1\");\n      }\n    }\n\n    // Set proxies after validation\n    this.proxies = proxies;\n\n    // Validate cmdArgs\n    if (cmdArgs !== undefined && !Array.isArray(cmdArgs)) {\n      throw new Error(\"cmdArgs must be a list\");\n    }\n\n    // Validate browser_type\n    if (\n      browserType !== undefined &&\n      browserType !== \"chrome\" &&\n      browserType !== \"chromium\"\n    ) {\n      throw new Error(\"browserType must be 'chrome' or 'chromium'\");\n    }\n  }\n\n  toMap(): Record<string, any> {\n    const optionMap: Record<string, any> = {};\n    if (process.env.AGENTBAY_BROWSER_BEHAVIOR_SIMULATE) {\n      optionMap[\"behaviorSimulate\"] = (process.env\n        .AGENTBAY_BROWSER_BEHAVIOR_SIMULATE !== \"0\") as boolean;\n    }\n    if (this.useStealth !== undefined) {\n      optionMap[\"useStealth\"] = this.useStealth;\n    }\n    if (this.userAgent !== undefined) {\n      optionMap[\"userAgent\"] = this.userAgent;\n    }\n    if (this.viewport !== undefined) {\n      optionMap[\"viewport\"] = {\n        width: this.viewport.width,\n        height: this.viewport.height,\n      };\n    }\n    if (this.screen !== undefined) {\n      optionMap[\"screen\"] = {\n        width: this.screen.width,\n        height: this.screen.height,\n      };\n    }\n    if (this.fingerprint !== undefined) {\n      const fp: Record<string, any> = {};\n      if (this.fingerprint.devices) fp[\"devices\"] = this.fingerprint.devices;\n      if (this.fingerprint.operatingSystems)\n        fp[\"operatingSystems\"] = this.fingerprint.operatingSystems;\n      if (this.fingerprint.locales) fp[\"locales\"] = this.fingerprint.locales;\n      optionMap[\"fingerprint\"] = fp;\n    }\n    if (this.fingerprintFormat !== undefined) {\n      // Encode fingerprint format to base64 string\n      try {\n        const jsonStr = this.fingerprintFormat.toJson();\n        optionMap[\"fingerprintRawData\"] = Buffer.from(\n          jsonStr,\n          \"utf-8\"\n        ).toString(\"base64\");\n      } catch (error) {\n        logError(\"Failed to serialize fingerprint format:\", error);\n        // Skip fingerprint format if serialization fails\n      }\n    }\n    if (this.fingerprintPersistent) {\n      this.fingerprintPersistPath = `${BROWSER_FINGERPRINT_PERSIST_PATH}/fingerprint.json`;\n      optionMap[\"fingerprintPersistPath\"] = this.fingerprintPersistPath;\n    }\n    if (this.solveCaptchas !== undefined) {\n      optionMap[\"solveCaptchas\"] = this.solveCaptchas;\n    }\n    if (this.autoLogin !== undefined) {\n      optionMap[\"autoLogin\"] = this.autoLogin;\n    }\n    if (this.callForUser !== undefined) {\n      optionMap[\"callForUser\"] = this.callForUser;\n    }\n    if (this.proxies !== undefined) {\n      optionMap[\"proxies\"] = this.proxies.map((proxy) => proxy.toMap());\n    }\n    if (this.extensionPath !== undefined) {\n      optionMap[\"extensionPath\"] = this.extensionPath;\n    }\n    if (this.cmdArgs !== undefined) {\n      optionMap[\"cmdArgs\"] = this.cmdArgs;\n    }\n    if (this.defaultNavigateUrl !== undefined) {\n      optionMap[\"defaultNavigateUrl\"] = this.defaultNavigateUrl;\n    }\n    if (this.browserType !== undefined) {\n      optionMap[\"browserType\"] = this.browserType;\n    }\n    return optionMap;\n  }\n\n  fromMap(m: Record<string, any> | null | undefined): BrowserOptionClass {\n    const map = m || {};\n    if (map.useStealth !== undefined) {\n      this.useStealth = map.useStealth;\n    } else {\n      this.useStealth = false;\n    }\n    if (map.userAgent !== undefined) {\n      this.userAgent = map.userAgent;\n    }\n    if (map.viewport !== undefined) {\n      this.viewport = {\n        width: map.viewport.width,\n        height: map.viewport.height,\n      };\n    }\n    if (map.screen !== undefined) {\n      this.screen = { width: map.screen.width, height: map.screen.height };\n    }\n    if (map.fingerprint !== undefined) {\n      const fp: BrowserFingerprint = {};\n      if (map.fingerprint.devices) fp.devices = map.fingerprint.devices;\n      if (map.fingerprint.operatingSystems)\n        fp.operatingSystems = map.fingerprint.operatingSystems;\n      if (map.fingerprint.locales) fp.locales = map.fingerprint.locales;\n      this.fingerprint = fp;\n    }\n    if (map.fingerprintFormat !== undefined) {\n      // Handle direct FingerprintFormat object\n      if (map.fingerprintFormat instanceof FingerprintFormat) {\n        this.fingerprintFormat = map.fingerprintFormat;\n      } else {\n        // Convert from plain object to FingerprintFormat\n        try {\n          this.fingerprintFormat = FingerprintFormat.fromDict(\n            map.fingerprintFormat\n          );\n        } catch (error) {\n          logError(\"Failed to convert fingerprintFormat from object:\", error);\n          this.fingerprintFormat = undefined;\n        }\n      }\n    } else if (map.fingerprintRawData !== undefined) {\n      // Decode base64 string to fingerprint format\n      try {\n        const jsonStr = Buffer.from(map.fingerprintRawData, \"base64\").toString(\n          \"utf-8\"\n        );\n        this.fingerprintFormat = FingerprintFormat.fromJson(jsonStr);\n      } catch (error) {\n        logError(\"Failed to decode fingerprint raw data:\", error);\n        this.fingerprintFormat = undefined;\n      }\n    }\n    if (map.fingerprintPersistent !== undefined) {\n      this.fingerprintPersistent = map.fingerprintPersistent;\n    } else if (map.fingerprintPersistPath !== undefined) {\n      this.fingerprintPersistPath = map.fingerprintPersistPath;\n      this.fingerprintPersistent = true;\n    } else {\n      this.fingerprintPersistent = false;\n    }\n    if (map.solveCaptchas !== undefined) {\n      this.solveCaptchas = map.solveCaptchas;\n    }\n    if (map.autoLogin !== undefined) {\n      this.autoLogin = map.autoLogin;\n    } else {\n      this.autoLogin = false;\n    }\n    if (map.callForUser !== undefined) {\n      this.callForUser = map.callForUser;\n    } else {\n      this.callForUser = false;\n    }\n    if (map.proxies !== undefined) {\n      const proxyList = map.proxies;\n      if (proxyList.length > 1) {\n        throw new Error(\"proxies list length must be limited to 1\");\n      }\n      this.proxies = proxyList\n        .map((proxyData: any) => {\n          // If it's already a BrowserProxyClass instance, return it\n          if (proxyData instanceof BrowserProxyClass) {\n            return proxyData;\n          }\n          // Otherwise, convert from map\n          return BrowserProxyClass.fromMap(proxyData);\n        })\n        .filter(Boolean) as BrowserProxy[];\n    }\n    if (map.extensionPath !== undefined) {\n      this.extensionPath = map.extensionPath;\n    }\n    if (map.cmdArgs !== undefined) {\n      this.cmdArgs = map.cmdArgs;\n    }\n    if (map.defaultNavigateUrl !== undefined) {\n      this.defaultNavigateUrl = map.defaultNavigateUrl;\n    }\n    if (map.browserType !== undefined) {\n      this.browserType = map.browserType;\n    }\n    return this;\n  }\n}\n\nexport class Browser {\n  private session: Session;\n  private _endpointUrl: string | null = null;\n  private _initialized = false;\n  private _option: BrowserOptionClass | null = null;\n  public operator: BrowserOperator;\n\n  // Internal callback management\n  private _userCallback: BrowserCallback | null = null;\n  private _wsCallbackRegistered = false;\n\n  constructor(session: Session) {\n    this.session = session;\n    this.operator = new BrowserOperator(this.session, this);\n  }\n\n  /**\n   * Initialize the browser instance with the given options.\n   * Returns true if successful, false otherwise.\n   */\n  initialize(option: BrowserOptionClass | BrowserOption): boolean {\n    if (this.isInitialized()) {\n      return true;\n    }\n\n    try {\n      logDebug(`Initializing browser with option: ${JSON.stringify(option)}`);\n      // Use direct API call to initialize browser\n      const request = new InitBrowserRequest();\n      request.authorization = `Bearer ${this.session.getAPIKey()}`;\n      request.persistentPath = BROWSER_DATA_PATH;\n      request.sessionId = this.session.getSessionId();\n\n      // Ensure option is a BrowserOptionClass instance\n      let browserOption: BrowserOptionClass;\n      if (option instanceof BrowserOptionClass) {\n        browserOption = option;\n      } else {\n        // Convert plain object to BrowserOptionClass instance\n        browserOption = new BrowserOptionClass();\n        browserOption.fromMap(option as Record<string, any>);\n      }\n\n      // Map BrowserOption to API BrowserOption payload\n      const browserOptionMap = browserOption.toMap();\n\n      // Set enableRecord based on session.enableBrowserReplay\n      if (this.session.enableBrowserReplay !== undefined) {\n        browserOptionMap[\"enableRecord\"] = this.session.enableBrowserReplay;\n      }\n\n      if (Object.keys(browserOptionMap).length > 0) {\n        request.browserOption = browserOptionMap;\n      }\n\n      const response = this.session.getClient().initBrowserSync(request);\n      logDebug(`Response from init_browser data:`, response.body?.data);\n\n      const success =\n        response.body?.data?.port !== null &&\n        response.body?.data?.port !== undefined;\n      if (success) {\n        this._initialized = true;\n        this._option = browserOption;\n        logInfo(\"Browser instance was successfully initialized.\");\n      }\n\n      return success;\n    } catch (error) {\n      logError(\"Failed to initialize browser instance:\", error);\n      this._initialized = false;\n      this._endpointUrl = null;\n      this._option = null;\n      return false;\n    }\n  }\n\n  /**\n   * Initialize the browser instance with the given options asynchronously.\n   * Returns true if successful, false otherwise.\n   *\n   * @param option - Browser configuration options\n   * @returns Promise resolving to true if successful, false otherwise\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: process.env.AGENTBAY_API_KEY });\n   * const result = await agentBay.create({ imageId: 'browser_latest' });\n   * if (result.success) {\n   *   const success = await result.session.browser.initializeAsync(new BrowserOptionClass());\n   *   console.log('Browser initialized:', success);\n   *   await result.session.delete();\n   * }\n   * ```\n   */\n  async initializeAsync(\n    option: BrowserOptionClass | BrowserOption\n  ): Promise<boolean> {\n    if (this.isInitialized()) {\n      return true;\n    }\n\n    try {\n      logDebug(\n        `Initializing browser asynchronously with option: ${JSON.stringify(\n          option\n        )}`\n      );\n      // Use direct API call to initialize browser\n      const request = new InitBrowserRequest();\n      request.authorization = `Bearer ${this.session.getAPIKey()}`;\n      request.persistentPath = BROWSER_DATA_PATH;\n      request.sessionId = this.session.getSessionId();\n\n      // Ensure option is a BrowserOptionClass instance\n      let browserOption: BrowserOptionClass;\n      if (option instanceof BrowserOptionClass) {\n        browserOption = option;\n      } else {\n        // Convert plain object to BrowserOptionClass instance\n        browserOption = new BrowserOptionClass();\n        browserOption.fromMap(option as Record<string, any>);\n      }\n\n      // Map BrowserOption to API BrowserOption payload\n      const browserOptionMap = browserOption.toMap();\n\n      // Set enableRecord based on session.enableBrowserReplay\n      if (this.session.enableBrowserReplay !== undefined) {\n        browserOptionMap[\"enableRecord\"] = this.session.enableBrowserReplay;\n      }\n\n      if (Object.keys(browserOptionMap).length > 0) {\n        request.browserOption = browserOptionMap;\n      }\n\n      const response = await this.session.getClient().initBrowser(request);\n      const requestId = response.body?.requestId || \"\";\n      setRequestId(requestId);\n\n      const success =\n        response.body?.data?.port !== null &&\n        response.body?.data?.port !== undefined;\n      if (success) {\n        logAPIResponseWithDetails(\"InitBrowser\", requestId, true, {\n          port: response.body?.data?.port,\n          endpoint: response.body?.data?.endpoint,\n        });\n        this._initialized = true;\n        this._option = browserOption;\n      } else {\n        logAPIResponseWithDetails(\n          \"InitBrowser\",\n          requestId,\n          false,\n          {},\n          \"Port not found in response\"\n        );\n      }\n\n      return success;\n    } catch (error) {\n      logError(\"Failed to initialize browser instance:\", error);\n      this._initialized = false;\n      this._endpointUrl = null;\n      this._option = null;\n      return false;\n    }\n  }\n\n  /**\n   * Destroy the browser instance.\n   */\n  async destroy(): Promise<void> {\n    if (this.isInitialized()) {\n      await this.session.callMcpTool(\"stopChrome\", {}, false);\n      // Reset browser state\n      this._initialized = false;\n      this._option = null;\n      this._endpointUrl = null;\n    } else {\n      throw new BrowserError(\n        \"Browser is not initialized. Cannot destroy browser.\"\n      );\n    }\n  }\n\n  /**\n   * Returns the endpoint URL if the browser is initialized, otherwise throws an exception.\n   * When initialized, always fetches the latest CDP url from session.getLink().\n   *\n   * @returns Promise resolving to the CDP endpoint URL\n   * @throws {BrowserError} If browser is not initialized\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: process.env.AGENTBAY_API_KEY });\n   * const result = await agentBay.create({ imageId: 'browser_latest' });\n   * if (result.success) {\n   *   await result.session.browser.initializeAsync(new BrowserOptionClass());\n   *   const endpointUrl = await result.session.browser.getEndpointUrl();\n   *   const browser = await chromium.connectOverCDP(endpointUrl);\n   *   await browser.close();\n   *   await result.session.delete();\n   * }\n   * ```\n   */\n  async getEndpointUrl(): Promise<string> {\n    if (!this.isInitialized()) {\n      throw new BrowserError(\n        \"Browser is not initialized. Cannot access endpoint URL.\"\n      );\n    }\n\n    try {\n      const { GetCdpLinkRequest } = await import(\"../api/models/model\");\n      const request = new GetCdpLinkRequest({\n        authorization: `Bearer ${this.session.getAPIKey()}`,\n        sessionId: this.session.sessionId,\n      });\n      const response = await this.session\n        .getAgentBay()\n        .getClient()\n        .getCdpLink(request);\n      if (response.body && response.body.success && response.body.data) {\n        this._endpointUrl = response.body.data.url || null;\n      } else {\n        const errorMsg = response.body?.message || \"Unknown error\";\n        throw new BrowserError(`Failed to get CDP link: ${errorMsg}`);\n      }\n      return this._endpointUrl!;\n    } catch (error) {\n      throw new BrowserError(\n        `Failed to get endpoint URL from session: ${error}`\n      );\n    }\n  }\n\n  /**\n   * Returns the current BrowserOption used to initialize the browser, or null if not set.\n   */\n  getOption(): BrowserOptionClass | null {\n    return this._option;\n  }\n\n  /**\n   * Returns true if the browser was initialized, false otherwise.\n   */\n  isInitialized(): boolean {\n    return this._initialized;\n  }\n\n  /**\n   * Stop the browser instance, internal use only.\n   */\n  private _stopBrowser(): void {\n    if (this.isInitialized()) {\n      this.session.callMcpTool(\"stopChrome\", {}, false);\n    } else {\n      throw new BrowserError(\n        \"Browser is not initialized. Cannot stop browser.\"\n      );\n    }\n  }\n\n  /**\n   * Takes a screenshot of the specified page with enhanced options and error handling.\n   * This method requires the caller to connect to the browser via Playwright or similar\n   * and pass the page object to this method.\n   *\n   * Note: This is a placeholder method that indicates where screenshot functionality\n   * should be implemented. In a complete implementation, this would use Playwright's\n   * page.screenshot() method or similar browser automation API.\n   *\n   * @param page The Playwright Page object to take a screenshot of. This is a required parameter.\n   * @param fullPage Whether to capture the full scrollable page. Defaults to false.\n   * @param options Additional screenshot options that will override defaults.\n   *                Common options include:\n   *                - type: Image type, either 'png' or 'jpeg' (default: 'png')\n   *                - quality: Quality of the image, between 0-100 (jpeg only)\n   *                - timeout: Maximum time in milliseconds (default: 60000)\n   *                - animations: How to handle animations (default: 'disabled')\n   *                - caret: How to handle the caret (default: 'hide')\n   *                - scale: Scale setting (default: 'css')\n   * @returns Screenshot data as Uint8Array.\n   * @throws BrowserError If browser is not initialized.\n   * @throws Error If screenshot capture fails.\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: process.env.AGENTBAY_API_KEY });\n   * const result = await agentBay.create({ imageId: 'browser_latest' });\n   * if (result.success) {\n   *   await result.session.browser.initializeAsync(new BrowserOptionClass());\n   *   const browser = await chromium.connectOverCDP(await result.session.browser.getEndpointUrl());\n   *   const page = await browser.contexts()[0].newPage();\n   *   await page.goto('https://example.com');\n   *   const screenshot = await result.session.browser.screenshot(page);\n   *   await writeFile('screenshot.png', Buffer.from(screenshot));\n   *   await browser.close();\n   *   await result.session.delete();\n   * }\n   * ```\n   */\n  async screenshot(\n    page: any,\n    fullPage = false,\n    options: Record<string, any> = {}\n  ): Promise<Uint8Array> {\n    // Check if browser is initialized\n    if (!this.isInitialized()) {\n      throw new BrowserError(\n        \"Browser must be initialized before calling screenshot.\"\n      );\n    }\n\n    if (page === null || page === undefined) {\n      throw new Error(\"Page cannot be null or undefined\");\n    }\n\n    // Set default enhanced options\n    const enhancedOptions: Record<string, any> = {\n      animations: \"disabled\",\n      caret: \"hide\",\n      scale: \"css\",\n      timeout: options.timeout || 60000,\n      fullPage: fullPage, // Use the function parameter, not options\n      type: options.type || \"png\",\n    };\n\n    // Update with user-provided options (but fullPage is already set from function parameter)\n    Object.assign(enhancedOptions, options);\n\n    try {\n      // Wait for page to load\n      // await page.waitForLoadState(\"networkidle\");\n      await page.evaluate(\"window.scrollTo(0, document.body.scrollHeight)\");\n      await page.waitForLoadState(\"domcontentloaded\");\n\n      // Scroll to load all content (especially for lazy-loaded elements)\n      await this._scrollToLoadAllContent(page);\n\n      // Ensure images with data-src attributes are loaded\n      await page.evaluate(`\n        () => {\n          document.querySelectorAll('img[data-src]').forEach(img => {\n            if (!img.src && img.dataset.src) {\n              img.src = img.dataset.src;\n            }\n          });\n          // Also handle background-image[data-bg]\n          document.querySelectorAll('[data-bg]').forEach(el => {\n            if (!el.style.backgroundImage) {\n              el.style.backgroundImage = \\`url(\\${el.dataset.bg})\\`;\n            }\n          });\n        }\n      `);\n\n      // Wait a bit for images to load\n      await page.waitForTimeout(1500);\n      const finalHeight = await page.evaluate(\"document.body.scrollHeight\");\n      await page.setViewportSize({\n        width: 1920,\n        height: Math.min(finalHeight, 10000),\n      });\n\n      // Take the screenshot\n      const screenshotBuffer = await page.screenshot(enhancedOptions);\n      logInfo(\"Screenshot captured successfully.\");\n\n      // Convert Buffer to Uint8Array\n      return new Uint8Array(screenshotBuffer);\n    } catch (error) {\n      // Convert error to string safely to avoid comparison issues\n      let errorStr: string;\n      try {\n        errorStr = String(error);\n      } catch {\n        errorStr = \"Unknown error occurred\";\n      }\n      const errorMsg = `Failed to capture screenshot: ${errorStr}`;\n      throw new Error(errorMsg);\n    }\n  }\n\n  /**\n   * Scrolls the page to load all content (especially for lazy-loaded elements)\n   */\n  private async _scrollToLoadAllContent(\n    page: any,\n    maxScrolls = 8,\n    delayMs = 1200\n  ): Promise<void> {\n    let lastHeight = 0;\n    for (let i = 0; i < maxScrolls; i++) {\n      await page.evaluate(\"window.scrollTo(0, document.body.scrollHeight)\");\n      await page.waitForTimeout(delayMs);\n      const newHeight = await page.evaluate(\n        \"Math.max(document.body.scrollHeight, document.documentElement.scrollHeight)\"\n      );\n      if (newHeight === lastHeight) {\n        break;\n      }\n      lastHeight = newHeight;\n    }\n  }\n\n  /**\n   * Internal WebSocket callback handler.\n   * @private\n   */\n  private _internalWsCallback(payload: Record<string, any>): void {\n    logDebug(`Browser layer received notification: ${JSON.stringify(payload)}`);\n\n    // Basic validation: data field should exist and not be None\n    if (!payload.data) {\n      logDebug(\n        `Ignoring notification with empty data: ${JSON.stringify(payload)}`\n      );\n      return;\n    }\n\n    // Dispatch to user callback if set\n    if (this._userCallback) {\n      try {\n        const notifyMsg = BrowserNotifyMessage.fromMap(payload.data);\n        if (notifyMsg) {\n          this._userCallback(notifyMsg);\n        }\n      } catch (error) {\n        logError(`Error when calling user callback: ${error}`);\n      }\n    }\n  }\n\n  /**\n   * Register a callback function to handle browser-related push notifications from sandbox.\n   *\n   * @param callback - Callback function that receives a BrowserNotifyMessage object containing\n   *                   notification details such as type, code, message, action, and extra_params.\n   * @returns Promise<boolean> - True if the callback was successfully registered.\n   *\n   * @example\n   * ```typescript\n   * function onBrowserCallback(notifyMsg: BrowserNotifyMessage) {\n   *   console.log(`Type: ${notifyMsg.type}`);\n   *   console.log(`Code: ${notifyMsg.code}`);\n   *   console.log(`Message: ${notifyMsg.message}`);\n   *   console.log(`Action: ${notifyMsg.action}`);\n   *   console.log(`Extra params: ${JSON.stringify(notifyMsg.extraParams)}`);\n   * }\n   *\n   * const createResult = await agentBay.create();\n   * const session = createResult.session;\n   *\n   * // Initialize browser\n   * await session.browser.initialize();\n   *\n   * // Register callback\n   * const success = await session.browser.registerCallback(onBrowserCallback);\n   *\n   * // ... do work ...\n   *\n   * // Unregister when done\n   * await session.browser.unregisterCallback();\n   * await session.delete();\n   * ```\n   */\n  async registerCallback(callback: BrowserCallback): Promise<boolean> {\n    try {\n      // Set user callback (replaces any existing callback)\n      this._userCallback = callback;\n      logInfo(\"Set user callback\");\n\n      // Register internal callback to ws_client only once\n      if (!this._wsCallbackRegistered) {\n        const wsClient = await this.session.getWsClient();\n        await wsClient.connect();\n        wsClient.registerCallback(\n          \"wuying_cdp_mcp_server\",\n          this._internalWsCallback.bind(this)\n        );\n        this._wsCallbackRegistered = true;\n        logDebug(\"Registered internal ws_callback to ws_client\");\n      }\n\n      return true;\n    } catch (error) {\n      logError(`Failed to register user callback: ${error}`);\n      return false;\n    }\n  }\n\n  /**\n   * Unregister the previously registered callback function.\n   *\n   * @example\n   * ```typescript\n   * function onBrowserCallback(notifyMsg: BrowserNotifyMessage) {\n   *   console.log(`Notification - Type: ${notifyMsg.type}, Message: ${notifyMsg.message}`);\n   * }\n   *\n   * const createResult = await agentBay.create();\n   * const session = createResult.session;\n   *\n   * await session.browser.initialize();\n   *\n   * await session.browser.registerCallback(onBrowserCallback);\n   *\n   * // ... do work ...\n   *\n   * // Unregister callback\n   * await session.browser.unregisterCallback();\n   *\n   * await session.delete();\n   * ```\n   */\n  async unregisterCallback(): Promise<void> {\n    try {\n      // Clear user callback\n      this._userCallback = null;\n      logInfo(\"Cleared user callback\");\n\n      // Unregister from ws_client\n      if (this._wsCallbackRegistered) {\n        const wsClient = await this.session.getWsClient();\n        wsClient.unregisterCallback(\n          \"wuying_cdp_mcp_server\",\n          this._internalWsCallback.bind(this)\n        );\n        await wsClient.close();\n        this._wsCallbackRegistered = false;\n        logDebug(\"Unregistered internal ws_callback from ws_client\");\n      }\n    } catch (error) {\n      logError(`Failed to unregister user callback: ${error}`);\n    }\n  }\n\n  /**\n   * Send a BrowserNotifyMessage to sandbox.\n   *\n   * @param notifyMessage - The notify message to send.\n   * @returns Promise<boolean> - True if the notify message was successfully sent, False otherwise.\n   *\n   * @example\n   * ```typescript\n   * function onBrowserCallback(notifyMsg: BrowserNotifyMessage) {\n   *   console.log(`Type: ${notifyMsg.type}`);\n   *   console.log(`Code: ${notifyMsg.code}`);\n   *   console.log(`Message: ${notifyMsg.message}`);\n   *   console.log(`Action: ${notifyMsg.action}`);\n   *   console.log(`Extra params: ${JSON.stringify(notifyMsg.extraParams)}`);\n   * }\n   *\n   * const createResult = await agentBay.create();\n   * const session = createResult.session;\n   *\n   * // Initialize browser\n   * await session.browser.initialize();\n   *\n   * // Register callback\n   * const success = await session.browser.registerCallback(onBrowserCallback);\n   *\n   * // ... do work ...\n   *\n   * // Send notify message\n   * const notifyMessage = new BrowserNotifyMessage(\n   *   'call-for-user',\n   *   3,\n   *   199,\n   *   'user handle done',\n   *   'takeoverdone',\n   *   {}\n   * );\n   * await session.browser.sendNotifyMessage(notifyMessage);\n   *\n   * // Unregister when done\n   * await session.browser.unregisterCallback();\n   * await session.delete();\n   * ```\n   */\n  async sendNotifyMessage(\n    notifyMessage: BrowserNotifyMessage\n  ): Promise<boolean> {\n    try {\n      const wsClient = await this.session.getWsClient();\n\n      // Send notify message through ws_client\n      await wsClient.sendMessage(\n        \"wuying_cdp_mcp_server\",\n        notifyMessage.toMap()\n      );\n      logInfo(\n        `Successfully sent browser notify message, notify_message: ${JSON.stringify(\n          notifyMessage.toMap()\n        )}`\n      );\n      return true;\n    } catch (error) {\n      logError(`Failed to send notify message: ${error}`);\n      return false;\n    }\n  }\n\n  /**\n   * Send a takeoverdone notify message to sandbox.\n   *\n   * @param notifyId - The notification ID associated with the takeover request message.\n   * @returns Promise<boolean> - True if the takeoverdone notify message was successfully sent, False otherwise.\n   *\n   * @example\n   * ```typescript\n   * function onBrowserCallback(notifyMsg: BrowserNotifyMessage) {\n   *   // receive call-for-user \"takeover\" action\n   *   if (notifyMsg.action === 'takeover') {\n   *     const takeoverNotifyId = notifyMsg.id;\n   *\n   *     // ... do work in other thread...\n   *     // send takeoverdone notify message\n   *     await session.browser.sendTakeoverDone(takeoverNotifyId);\n   *     // ... end...\n   *   }\n   * }\n   *\n   * const createResult = await agentBay.create();\n   * const session = createResult.session;\n   *\n   * // Initialize browser\n   * await session.browser.initialize();\n   *\n   * // Register callback\n   * const success = await session.browser.registerCallback(onBrowserCallback);\n   *\n   * // ... do work ...\n   *\n   * // Unregister when done\n   * await session.browser.unregisterCallback();\n   * await session.delete();\n   * ```\n   */\n  async sendTakeoverDone(notifyId: number): Promise<boolean> {\n    try {\n      // Get ws_client\n      const wsClient = await this.session.getWsClient();\n\n      // Build takeoverdone notify message\n      const notifyMessage = new BrowserNotifyMessage(\n        \"call-for-user\",\n        notifyId,\n        199,\n        \"user handle done\",\n        \"takeoverdone\",\n        {}\n      );\n      const messageData = notifyMessage.toMap();\n\n      // Send message through ws_client\n      await wsClient.sendMessage(\"wuying_cdp_mcp_server\", messageData);\n\n      logInfo(\n        `Successfully sent browser takeoverdone notify message, notify_id: ${notifyId}`\n      );\n      return true;\n    } catch (error) {\n      logError(`Failed to send browser notify message: ${error}`);\n      return false;\n    }\n  }\n}\n","import { Session } from \"../session\";\nimport { Browser } from \"./browser\";\nimport { BrowserError } from \"../exceptions\";\nimport { z, ZodTypeAny } from \"zod\";\nimport { zodToJsonSchema } from \"zod-to-json-schema\";\n\nimport { logInfo, logDebug, logWarn } from \"../utils/logger\";\n\n// Options interfaces\nexport interface ActOptions {\n  action: string;\n  timeout?: number;\n  variables?: Record<string, string>;\n  use_vision?: boolean;\n}\n\nexport interface ObserveOptions {\n  instruction: string;\n  use_vision?: boolean;\n  selector?: string;\n  timeout?: number;\n}\n\nexport interface ExtractOptions<TSchema extends ZodTypeAny = ZodTypeAny> {\n  instruction: string;\n  schema: TSchema;\n  use_text_extract?: boolean;\n  selector?: string;\n  use_vision?: boolean;\n  timeout?: number;\n  max_page?: number;\n}\n\nexport class ActResult {\n  success: boolean;\n  message: string;\n  constructor(success: boolean, message: string) {\n    this.success = success;\n    this.message = message;\n  }\n}\n\nexport class ObserveResult {\n  selector: string;\n  description: string;\n  method: string;\n  args: Record<string, any>;\n  constructor(\n    selector: string,\n    description: string,\n    method: string,\n    args: Record<string, any>\n  ) {\n    this.selector = selector;\n    this.description = description;\n    this.method = method;\n    this.args = args;\n  }\n}\n\n/**\n * BrowserOperator to perform tasks on the browser.\n *\n * > **⚠️ Note**: Currently, for agent services (including ComputerUseAgent, BrowserUseAgent, and MobileUseAgent), we do not provide services for overseas users registered with **alibabacloud.com**.\n */\nexport class BrowserOperator {\n  private session: Session;\n  private browser: Browser;\n\n  constructor(session: Session, browser: Browser) {\n    this.session = session;\n    this.browser = browser;\n  }\n\n  /** ------------------ NAVIGATE ------------------ **/\n  async navigate(url: string): Promise<string> {\n    if (!this.browser.isInitialized()) {\n      throw new BrowserError(\n        \"Browser must be initialized before calling navigate.\"\n      );\n    }\n    try {\n      const args: Record<string, any> = { url };\n      const response = await this._callMcpTool(\"page_use_navigate\", args);\n      if (response.success && response.data) {\n        return typeof response.data === \"string\"\n          ? response.data\n          : JSON.stringify(response.data);\n      }\n      return `Navigation failed: ${response.errorMessage || \"Unknown error\"}`;\n    } catch (e: any) {\n      throw new BrowserError(`Failed to navigate: ${e}`);\n    }\n  }\n\n  /** ------------------ SCREENSHOT ------------------ **/\n  async screenshot(\n    page: any = null,\n    full_page = true,\n    quality = 80,\n    clip?: Record<string, number>,\n    timeout?: number\n  ): Promise<string> {\n    if (!this.browser.isInitialized()) {\n      throw new BrowserError(\n        \"Browser must be initialized before calling screenshot.\"\n      );\n    }\n    try {\n      const [pageId, contextId] = await this._getPageAndContextIndexAsync(page);\n      logDebug(`Screenshot page_id: ${pageId}, context_id: ${contextId}`);\n\n      const args: Record<string, any> = {\n        context_id: contextId,\n        page_id: pageId,\n        full_page,\n        quality,\n        clip,\n        timeout,\n      };\n      Object.keys(args).forEach((k) => {\n        if (args[k] === undefined || args[k] === null) delete args[k];\n      });\n\n      const response = await this._callMcpTool(\"page_use_screenshot\", args);\n      if (response.success && response.data) {\n        return typeof response.data === \"string\"\n          ? response.data\n          : JSON.stringify(response.data);\n      }\n      return `Screenshot failed: ${response.errorMessage || \"Unknown error\"}`;\n    } catch (e: any) {\n      throw new BrowserError(`Failed to call screenshot: ${e}`);\n    }\n  }\n  /** ------------------ CLOSE ------------------ **/\n  async close(): Promise<boolean> {\n    try {\n      const response = await this._callMcpTool(\"page_use_close_session\", {});\n      if (response.success && response.data) {\n        logInfo(`Session close status: ${response.data}`);\n        return true;\n      } else {\n        logWarn(\n          `Failed to close session: ${response.errorMessage || \"Unknown error\"}`\n        );\n        return false;\n      }\n    } catch (e: any) {\n      throw new BrowserError(`Failed to call close: ${e}`);\n    }\n  }\n\n  /** ------------------ ACT ------------------ **/\n  async act(options: ActOptions, page?: any): Promise<ActResult> {\n    if (!this.browser.isInitialized())\n      throw new BrowserError(\"Browser must be initialized before calling act.\");\n\n    const [pageId, contextId] = await this._getPageAndContextIndexAsync(page);\n    logDebug(`Acting page_id: ${pageId}, context_id: ${contextId}`);\n\n    const args: Record<string, any> = {\n      context_id: contextId,\n      page_id: pageId,\n      action: options.action,\n      variables: options.variables,\n      timeout: options.timeout,\n      use_vision: options.use_vision,\n    };\n    Object.keys(args).forEach((k) => {\n      if (args[k] === undefined || args[k] === null) delete args[k];\n    });\n    const task_name = options.action;\n    logInfo(`${task_name}`);\n\n    const response = await this._callMcpTool(\"page_use_act\", args);\n\n    if (response.success && response.data) {\n      const msg =\n        typeof response.data === \"string\"\n          ? response.data\n          : JSON.stringify(response.data);\n      logInfo(`${task_name} response data: ${msg}`);\n      return new ActResult(true, msg);\n    }\n    return new ActResult(false, response.errorMessage || \"\");\n  }\n\n  async actAsync(options: ActOptions, page?: any): Promise<ActResult> {\n    if (!this.browser.isInitialized())\n      throw new BrowserError(\n        \"Browser must be initialized before calling actAsync.\"\n      );\n\n    const [pageId, contextId] = await this._getPageAndContextIndexAsync(page);\n    logDebug(`Acting page_id: ${pageId}, context_id: ${contextId}`);\n\n    const args: Record<string, any> = {\n      context_id: contextId,\n      page_id: pageId,\n      action: options.action,\n      variables: options.variables,\n      timeout: options.timeout,\n      use_vision: options.use_vision,\n    };\n    Object.keys(args).forEach((k) => {\n      if (args[k] === undefined || args[k] === null) delete args[k];\n    });\n    const task_name = options.action;\n    logInfo(`${task_name}`);\n\n    const startResp = await this._callMcpTool(\"page_use_act_async\", args);\n    if (!startResp.success) throw new BrowserError(\"Failed to start act task\");\n\n    const { task_id } = JSON.parse(startResp.data);\n    const clientTimeout = options.timeout;\n    const timeoutS = clientTimeout ?? 300;\n    const startTS = Date.now();\n\n    const noActionMsg = \"No actions have been executed.\";\n\n    while (true) {\n      await this._delay(3000);\n      const pollResp = await this._callMcpTool(\"page_use_get_act_result\", {\n        task_id,\n      });\n\n      if (pollResp.success && pollResp.data) {\n        const data =\n          typeof pollResp.data === \"string\"\n            ? JSON.parse(pollResp.data)\n            : pollResp.data;\n        const steps = data.steps || [];\n        const is_done = data.is_done || false;\n        const success = !!data.success;\n        if (is_done) {\n          const msg = steps.length ? JSON.stringify(steps) : noActionMsg;\n          logInfo(\n            `Task ${task_id}:${task_name} is done. Success: ${success}. ${msg}`\n          );\n          return new ActResult(success, msg);\n        } else {\n          const elapsed = (Date.now() - startTS) / 1000;\n          const statusMsg = steps.length\n            ? `${steps.length} steps done. Details: ${JSON.stringify(steps)}`\n            : noActionMsg;\n          logInfo(`Task ${task_id}:${task_name} in progress. ${statusMsg}`);\n\n          if (elapsed >= timeoutS) {\n            throw new BrowserError(\n              `Task ${task_id}:${task_name} timeout after ${timeoutS}s`\n            );\n          }\n        }\n      } else {\n        const elapsed = (Date.now() - startTS) / 1000;\n        if (elapsed >= timeoutS) {\n          throw new BrowserError(\n            `Task ${task_id}:${task_name} timeout after ${timeoutS}s`\n          );\n        }\n      }\n    }\n  }\n\n  /** ------------------ OBSERVE ------------------ **/\n  async observe(\n    options: ObserveOptions,\n    page?: any\n  ): Promise<[boolean, ObserveResult[]]> {\n    if (!this.browser.isInitialized())\n      throw new BrowserError(\n        \"Browser must be initialized before calling observe.\"\n      );\n\n    const [pageId, contextId] = await this._getPageAndContextIndexAsync(page);\n    logDebug(`Observing page_id: ${pageId}, context_id: ${contextId}`);\n\n    const args: Record<string, any> = {\n      context_id: contextId,\n      page_id: pageId,\n      instruction: options.instruction,\n      use_vision: options.use_vision,\n      selector: options.selector,\n    };\n    Object.keys(args).forEach((k) => {\n      if (args[k] === undefined || args[k] === null) delete args[k];\n    });\n    const response = await this._callMcpTool(\"page_use_observe\", args);\n    if (response.success && response.data) {\n      const data =\n        typeof response.data === \"string\"\n          ? JSON.parse(response.data)\n          : response.data;\n      logInfo(`observe results: ${data}`);\n      const results: ObserveResult[] = [];\n\n      for (const item of data) {\n        let argsParsed: any;\n        try {\n          argsParsed =\n            typeof item.arguments === \"string\"\n              ? JSON.parse(item.arguments)\n              : item.arguments;\n        } catch {\n          logWarn(`Warning: Could not parse arguments JSON: ${item.arguments}`);\n          argsParsed = item.arguments;\n        }\n        results.push(\n          new ObserveResult(\n            item.selector || \"\",\n            item.description || \"\",\n            item.method || \"\",\n            argsParsed\n          )\n        );\n      }\n      return [true, results];\n    }\n    return [false, []];\n  }\n\n  async observeAsync(\n    options: ObserveOptions,\n    page?: any\n  ): Promise<[boolean, ObserveResult[]]> {\n    if (!this.browser.isInitialized()) {\n      throw new BrowserError(\n        \"Browser must be initialized before calling observeAsync.\"\n      );\n    }\n\n    const [pageId, contextId] = await this._getPageAndContextIndexAsync(page);\n    logDebug(`Observing page_id: ${pageId}, context_id: ${contextId}`);\n\n    const args: Record<string, any> = {\n      context_id: contextId,\n      page_id: pageId,\n      instruction: options.instruction,\n      use_vision: options.use_vision,\n      selector: options.selector,\n    };\n    Object.keys(args).forEach((k) => {\n      if (args[k] === undefined || args[k] === null) delete args[k];\n    });\n    const startResp = await this._callMcpTool(\"page_use_observe_async\", args);\n    if (!startResp.success || !startResp.data) {\n      throw new BrowserError(\"Failed to start observe task\");\n    }\n\n    const { task_id } =\n      typeof startResp.data === \"string\"\n        ? JSON.parse(startResp.data)\n        : startResp.data;\n\n    const clientTimeout = options.timeout;\n    const timeoutS = clientTimeout ?? 300;\n    const startTS = Date.now();\n\n    while (true) {\n      await this._delay(3000);\n      const pollResp = await this._callMcpTool(\"page_use_get_observe_result\", {\n        task_id,\n      });\n\n      if (pollResp.success && pollResp.data) {\n        const data =\n          typeof pollResp.data === \"string\"\n            ? JSON.parse(pollResp.data)\n            : pollResp.data;\n        logInfo(`observe results: ${JSON.stringify(data)}`);\n\n        const results: ObserveResult[] = [];\n        for (const item of data) {\n          let argsParsed: any;\n          try {\n            argsParsed =\n              typeof item.arguments === \"string\"\n                ? JSON.parse(item.arguments)\n                : item.arguments;\n          } catch {\n            logWarn(\n              `Warning: Could not parse arguments JSON: ${item.arguments}`\n            );\n            argsParsed = item.arguments;\n          }\n          results.push(\n            new ObserveResult(\n              item.selector || \"\",\n              item.description || \"\",\n              item.method || \"\",\n              argsParsed\n            )\n          );\n        }\n        return [true, results];\n      }\n\n      const elapsed = (Date.now() - startTS) / 1000;\n      logDebug(\n        `Task ${task_id}: No observe result yet (elapsed=${elapsed.toFixed(\n          0\n        )}s)`\n      );\n      if (elapsed >= timeoutS) {\n        throw new BrowserError(\n          `Task ${task_id}: Observe timeout after ${timeoutS}s`\n        );\n      }\n    }\n  }\n\n  /** ------------------ EXTRACT ------------------ **/\n  async extract<TSchema extends ZodTypeAny>(\n    options: ExtractOptions<TSchema>,\n    page?: any\n  ): Promise<[boolean, z.infer<TSchema> | null]> {\n    if (!this.browser.isInitialized())\n      throw new BrowserError(\n        \"Browser must be initialized before calling extract.\"\n      );\n\n    const [pageId, contextId] = await this._getPageAndContextIndexAsync(page);\n    logDebug(`Extracting page_id: ${pageId}, context_id: ${contextId}`);\n\n    const jsonSchema = zodToJsonSchema(options.schema, \"ExtractSchema\");\n    const args: Record<string, any> = {\n      context_id: contextId,\n      page_id: pageId,\n      instruction: options.instruction,\n      field_schema: `schema: ${JSON.stringify(jsonSchema)}`,\n      use_text_extract: options.use_text_extract,\n      use_vision: options.use_vision,\n      selector: options.selector,\n      max_page: options.max_page,\n    };\n    Object.keys(args).forEach((k) => {\n      if (args[k] === undefined || args[k] === null) delete args[k];\n    });\n    const response = await this._callMcpTool(\"page_use_extract\", args);\n    if (response.success && response.data) {\n      const raw =\n        typeof response.data === \"string\"\n          ? JSON.parse(response.data)\n          : response.data;\n      const parsed = options.schema.parse(raw) as z.infer<TSchema>;\n      return [true, parsed];\n    }\n    return [false, null];\n  }\n\n  async extractAsync<TSchema extends ZodTypeAny>(\n    options: ExtractOptions<TSchema>,\n    page?: any\n  ): Promise<[boolean, z.infer<TSchema> | null]> {\n    if (!this.browser.isInitialized())\n      throw new BrowserError(\n        \"Browser must be initialized before calling extractAsync.\"\n      );\n\n    const [pageId, contextId] = await this._getPageAndContextIndexAsync(page);\n    logDebug(`Extracting page_id: ${pageId}, context_id: ${contextId}`);\n\n    const jsonSchema = zodToJsonSchema(options.schema, \"ExtractSchema\");\n    const args: Record<string, any> = {\n      context_id: contextId,\n      page_id: pageId,\n      instruction: options.instruction,\n      field_schema: `schema: ${JSON.stringify(jsonSchema)}`,\n      use_text_extract: options.use_text_extract,\n      use_vision: options.use_vision,\n      selector: options.selector,\n      max_page: options.max_page,\n    };\n    Object.keys(args).forEach((k) => {\n      if (args[k] === undefined || args[k] === null) delete args[k];\n    });\n    const startResp = await this._callMcpTool(\"page_use_extract_async\", args);\n    if (!startResp.success || !startResp.data) {\n      throw new BrowserError(\"Failed to start extract task\");\n    }\n\n    const { task_id } =\n      typeof startResp.data === \"string\"\n        ? JSON.parse(startResp.data)\n        : startResp.data;\n\n    const clientTimeout = options.timeout;\n    const timeoutS = clientTimeout ?? 300;\n    const startTS = Date.now();\n\n    while (true) {\n      await this._delay(3000);\n\n      const pollResp = await this._callMcpTool(\"page_use_get_extract_result\", {\n        task_id,\n      });\n\n      if (pollResp.success && pollResp.data) {\n        const raw =\n          typeof pollResp.data === \"string\"\n            ? JSON.parse(pollResp.data)\n            : pollResp.data;\n        const parsed = options.schema.parse(raw) as z.infer<TSchema>;\n        return [true, parsed];\n      }\n\n      const elapsed = (Date.now() - startTS) / 1000;\n      logDebug(\n        `Task ${task_id}: No extract result yet (elapsed=${elapsed.toFixed(\n          0\n        )}s)`\n      );\n      if (elapsed >= timeoutS) {\n        throw new BrowserError(\n          `Task ${task_id}: Extract timeout after ${timeoutS}s`\n        );\n      }\n    }\n  }\n\n  private async _getPageAndContextIndexAsync(\n    page: any\n  ): Promise<[string | null, number]> {\n    if (!page) {\n      return [null, 0];\n    }\n\n    // Try to use Playwright CDP if available\n    try {\n      if (page.context && typeof page.context === \"function\") {\n        const context = page.context();\n        if (context && typeof context.newCDPSession === \"function\") {\n          const cdpSession = await context.newCDPSession(page);\n          const targetInfo = await cdpSession.send(\"Target.getTargetInfo\");\n          const pageIndex =\n            targetInfo &&\n            targetInfo.targetInfo &&\n            targetInfo.targetInfo.targetId\n              ? targetInfo.targetInfo.targetId\n              : null;\n          if (typeof cdpSession.detach === \"function\") {\n            await cdpSession.detach();\n          }\n\n          let contextIndex = 0;\n          if (typeof context.browser === \"function\") {\n            const browserObj = context.browser();\n            if (browserObj && typeof browserObj.contexts === \"function\") {\n              const contexts = browserObj.contexts();\n              const idx = contexts.indexOf(context);\n              if (idx >= 0) {\n                contextIndex = idx;\n              }\n            }\n          }\n          return [pageIndex, contextIndex];\n        }\n      }\n    } catch (error) {\n      logWarn(`CDP targetId retrieval failed, fallback to defaults: ${error}`);\n    }\n    return [null, 0];\n  }\n\n  private async _callMcpTool(toolName: string, args: Record<string, any>) {\n    return this.session.callMcpTool(toolName, args, false);\n  }\n\n  private _delay(ms: number) {\n    return new Promise((res) => setTimeout(res, ms));\n  }\n}\n","import { chromium, Page } from \"playwright\";\nimport { logInfo, logWarn, logError } from \"../utils/logger\";\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\n/**\n * Screen fingerprint data structure.\n */\nexport interface ScreenFingerprint {\n  availHeight: number;\n  availWidth: number;\n  availTop: number;\n  availLeft: number;\n  colorDepth: number;\n  height: number;\n  pixelDepth: number;\n  width: number;\n  devicePixelRatio: number;\n  pageXOffset: number;\n  pageYOffset: number;\n  innerHeight: number;\n  outerHeight: number;\n  outerWidth: number;\n  innerWidth: number;\n  screenX: number;\n  clientWidth: number;\n  clientHeight: number;\n  hasHDR: boolean;\n}\n\n/**\n * Brand information data structure.\n */\nexport interface Brand {\n  brand: string;\n  version: string;\n}\n\n/**\n * User agent data structure.\n */\nexport interface UserAgentData {\n  brands: Brand[];\n  mobile: boolean;\n  platform: string;\n  architecture: string;\n  bitness: string;\n  fullVersionList: Brand[];\n  model: string;\n  platformVersion: string;\n  uaFullVersion: string;\n}\n\n/**\n * Navigator extra properties data structure.\n */\nexport interface ExtraProperties {\n  vendorFlavors: string[];\n  isBluetoothSupported: boolean;\n  globalPrivacyControl?: any;\n  pdfViewerEnabled: boolean;\n  installedApps: any[];\n}\n\n/**\n * Navigator fingerprint data structure.\n */\nexport interface NavigatorFingerprint {\n  userAgent: string;\n  userAgentData: UserAgentData;\n  doNotTrack: string;\n  appCodeName: string;\n  appName: string;\n  appVersion: string;\n  oscpu: string;\n  webdriver: string;\n  language: string;\n  languages: string[];\n  platform: string;\n  deviceMemory?: number;\n  hardwareConcurrency: number;\n  product: string;\n  productSub: string;\n  vendor: string;\n  vendorSub: string;\n  maxTouchPoints?: number;\n  extraProperties: ExtraProperties;\n}\n\n/**\n * Video card information data structure.\n */\nexport interface VideoCard {\n  renderer: string;\n  vendor: string;\n}\n\n/**\n * Main fingerprint data structure.\n */\nexport interface Fingerprint {\n  screen: ScreenFingerprint;\n  navigator: NavigatorFingerprint;\n  videoCodecs: Record<string, string>;\n  audioCodecs: Record<string, string>;\n  pluginsData: Record<string, string>;\n  battery?: Record<string, string>;\n  videoCard: VideoCard;\n  multimediaDevices: string[];\n  fonts: string[];\n  mockWebRTC: boolean;\n  slim?: boolean;\n}\n\n/**\n * Complete fingerprint format including fingerprint data and headers.\n */\nexport class FingerprintFormat {\n  public fingerprint: Fingerprint;\n  public headers: Record<string, string>;\n\n  constructor(fingerprint: Fingerprint, headers: Record<string, string>) {\n    this.fingerprint = fingerprint;\n    this.headers = headers;\n  }\n\n  /**\n   * Load fingerprint format from dict or JSON string.\n   *\n   * @param data - Dictionary or JSON string containing fingerprint data\n   * @returns FingerprintFormat instance\n   *\n   * @example\n   * ```typescript\n   * // From dict\n   * const fp = FingerprintFormat.load({fingerprint: {...}, headers: {...}});\n   * // From JSON file\n   * const data = fs.readFileSync('fingerprint.json', 'utf8');\n   * const fp2 = FingerprintFormat.load(data);\n   * ```\n   */\n  static load(data: string | Record<string, any>): FingerprintFormat {\n    if (typeof data === \"string\") {\n      return this.fromJson(data);\n    }\n    return this.fromDict(data);\n  }\n\n  /**\n   * Convert to dictionary format.\n   * Note: Used internally by SDK modules.\n   */\n  toDict(): Record<string, any> {\n    return {\n      fingerprint: this.fingerprint,\n      headers: this.headers,\n    };\n  }\n\n  /**\n   * Convert to JSON string format.\n   * Note: Used internally by SDK modules.\n   */\n  toJson(indent = 2): string {\n    return JSON.stringify(this.toDict(), null, indent);\n  }\n\n  /**\n   * Create FingerprintFormat from dictionary data.\n   * Note: Used internally by SDK modules.\n   */\n  static fromDict(data: Record<string, any>): FingerprintFormat {\n    if (!data || typeof data !== \"object\") {\n      throw new Error(\"Invalid data: expected an object\");\n    }\n\n    const fingerprintDict = data.fingerprint || {};\n    const headersDict = data.headers || {};\n\n    // Convert nested objects to proper interfaces\n    const screenDict = fingerprintDict.screen || {};\n    const screen: ScreenFingerprint = {\n      availHeight: screenDict.availHeight || 0,\n      availWidth: screenDict.availWidth || 0,\n      availTop: screenDict.availTop || 0,\n      availLeft: screenDict.availLeft || 0,\n      colorDepth: screenDict.colorDepth || 24,\n      height: screenDict.height || 0,\n      pixelDepth: screenDict.pixelDepth || 24,\n      width: screenDict.width || 0,\n      devicePixelRatio: screenDict.devicePixelRatio || 1,\n      pageXOffset: screenDict.pageXOffset || 0,\n      pageYOffset: screenDict.pageYOffset || 0,\n      innerHeight: screenDict.innerHeight || 0,\n      outerHeight: screenDict.outerHeight || 0,\n      outerWidth: screenDict.outerWidth || 0,\n      innerWidth: screenDict.innerWidth || 0,\n      screenX: screenDict.screenX || 0,\n      clientWidth: screenDict.clientWidth || 0,\n      clientHeight: screenDict.clientHeight || 0,\n      hasHDR: screenDict.hasHDR || false,\n    };\n\n    // Handle UserAgentData - safely get navigator data\n    const navDict = fingerprintDict.navigator || {};\n    const userAgentDataDict = navDict.userAgentData || {};\n\n    // Handle brands and fullVersionList safely\n    const brandsData = userAgentDataDict.brands || [];\n    const brands: Brand[] = [];\n    if (Array.isArray(brandsData)) {\n      for (const brandData of brandsData) {\n        if (typeof brandData === \"object\" && brandData !== null) {\n          brands.push({\n            brand: brandData.brand || \"\",\n            version: brandData.version || \"\",\n          });\n        }\n      }\n    }\n\n    const fullVersionListData = userAgentDataDict.fullVersionList || [];\n    const fullVersionList: Brand[] = [];\n    if (Array.isArray(fullVersionListData)) {\n      for (const brandData of fullVersionListData) {\n        if (typeof brandData === \"object\" && brandData !== null) {\n          fullVersionList.push({\n            brand: brandData.brand || \"\",\n            version: brandData.version || \"\",\n          });\n        }\n      }\n    }\n\n    const userAgentData: UserAgentData = {\n      brands: brands,\n      mobile: userAgentDataDict.mobile || false,\n      platform: userAgentDataDict.platform || \"\",\n      architecture: userAgentDataDict.architecture || \"\",\n      bitness: userAgentDataDict.bitness || \"\",\n      fullVersionList: fullVersionList,\n      model: userAgentDataDict.model || \"\",\n      platformVersion: userAgentDataDict.platformVersion || \"\",\n      uaFullVersion: userAgentDataDict.uaFullVersion || \"\",\n    };\n\n    // Handle ExtraProperties\n    const extraPropsDict = navDict.extraProperties || {};\n    const extraProps: ExtraProperties = {\n      vendorFlavors: extraPropsDict.vendorFlavors || [],\n      isBluetoothSupported: extraPropsDict.isBluetoothSupported || false,\n      globalPrivacyControl: extraPropsDict.globalPrivacyControl,\n      pdfViewerEnabled: extraPropsDict.pdfViewerEnabled !== false,\n      installedApps: extraPropsDict.installedApps || [],\n    };\n\n    // Create NavigatorFingerprint\n    const navigator: NavigatorFingerprint = {\n      userAgent: navDict.userAgent || \"\",\n      userAgentData: userAgentData,\n      doNotTrack: navDict.doNotTrack || \"\",\n      appCodeName: navDict.appCodeName || \"\",\n      appName: navDict.appName || \"\",\n      appVersion: navDict.appVersion || \"\",\n      oscpu: navDict.oscpu || \"\",\n      webdriver: navDict.webdriver || \"\",\n      language: navDict.language || \"\",\n      languages: navDict.languages || [],\n      platform: navDict.platform || \"\",\n      deviceMemory: navDict.deviceMemory,\n      hardwareConcurrency: navDict.hardwareConcurrency || 8,\n      product: navDict.product || \"\",\n      productSub: navDict.productSub || \"\",\n      vendor: navDict.vendor || \"\",\n      vendorSub: navDict.vendorSub || \"\",\n      maxTouchPoints: navDict.maxTouchPoints,\n      extraProperties: extraProps,\n    };\n\n    // Create VideoCard\n    const videoCardDict = fingerprintDict.videoCard || {};\n    const videoCard: VideoCard = {\n      renderer: videoCardDict.renderer || \"Unknown\",\n      vendor: videoCardDict.vendor || \"Unknown\",\n    };\n\n    // Create main Fingerprint\n    const fingerprint: Fingerprint = {\n      screen: screen,\n      navigator: navigator,\n      videoCodecs: fingerprintDict.videoCodecs || {},\n      audioCodecs: fingerprintDict.audioCodecs || {},\n      pluginsData: fingerprintDict.pluginsData || {},\n      battery: fingerprintDict.battery,\n      videoCard: videoCard,\n      multimediaDevices: fingerprintDict.multimediaDevices || [],\n      fonts: fingerprintDict.fonts || [],\n      mockWebRTC: fingerprintDict.mockWebRTC || false,\n      slim: fingerprintDict.slim,\n    };\n\n    return new FingerprintFormat(fingerprint, headersDict);\n  }\n\n  /**\n   * Create FingerprintFormat from JSON string.\n   */\n  static fromJson(jsonStr: string): FingerprintFormat {\n    const data = JSON.parse(jsonStr);\n    return FingerprintFormat.fromDict(data);\n  }\n\n  /**\n   * Create FingerprintFormat directly using component interfaces.\n   */\n  static create(\n    screen: ScreenFingerprint,\n    navigator: NavigatorFingerprint,\n    videoCard: VideoCard,\n    headers: Record<string, string>,\n    videoCodecs?: Record<string, string>,\n    audioCodecs?: Record<string, string>,\n    pluginsData?: Record<string, string>,\n    battery?: Record<string, string>,\n    multimediaDevices?: string[],\n    fonts?: string[],\n    mockWebRTC = false,\n    slim?: boolean\n  ): FingerprintFormat {\n    const fingerprint: Fingerprint = {\n      screen: screen,\n      navigator: navigator,\n      videoCodecs: videoCodecs || {},\n      audioCodecs: audioCodecs || {},\n      pluginsData: pluginsData || {},\n      battery: battery,\n      videoCard: videoCard,\n      multimediaDevices: multimediaDevices || [],\n      fonts: fonts || [],\n      mockWebRTC: mockWebRTC,\n      slim: slim,\n    };\n\n    return new FingerprintFormat(fingerprint, headers);\n  }\n}\n\n/**\n * Browser fingerprint generator class.\n */\nexport class BrowserFingerprintGenerator {\n  private headless: boolean;\n  private useChromeChannel: boolean;\n\n  constructor(\n    options: { headless?: boolean; useChromeChannel?: boolean } = {}\n  ) {\n    this.headless = options.headless ?? false;\n    this.useChromeChannel = options.useChromeChannel ?? true;\n  }\n\n  /**\n   * Extract comprehensive browser fingerprint using Playwright.\n   */\n  async generateFingerprint(): Promise<FingerprintFormat | null> {\n    try {\n      logInfo(\"Starting fingerprint generation\");\n\n      const launchOptions: any = {\n        headless: this.headless,\n        args: [\"--start-maximized\"],\n      };\n\n      if (this.useChromeChannel) {\n        launchOptions.channel = \"chrome\";\n      }\n\n      const browser = await chromium.launch(launchOptions);\n      const context = await browser.newContext({ viewport: null });\n      const page = await context.newPage();\n\n      // Navigate to a test page to ensure proper loading\n      await page.goto(\"about:blank\");\n\n      logInfo(\"Extracting comprehensive browser fingerprint...\");\n\n      // Extract comprehensive fingerprint data\n      const fingerprintData = await this.extractFingerprintData(page);\n\n      // Get request headers\n      const headersData = await this.extractHeadersData(page);\n\n      await browser.close();\n\n      // Combine fingerprint and headers using FingerprintFormat\n      const fingerprintFormat = FingerprintFormat.fromDict({\n        fingerprint: fingerprintData,\n        headers: headersData,\n      });\n\n      logInfo(\"Fingerprint generation completed successfully!\");\n      return fingerprintFormat;\n    } catch (error) {\n      logError(`Error generating fingerprint: ${error}`);\n      return null;\n    }\n  }\n\n  /**\n   * Extract comprehensive browser fingerprint and save to file.\n   */\n  async generateFingerprintToFile(\n    outputFilename = \"fingerprint_output.json\"\n  ): Promise<boolean> {\n    try {\n      logInfo(\n        `Starting fingerprint generation, output file: ${outputFilename}`\n      );\n\n      // Generate fingerprint data (FingerprintFormat object)\n      const fingerprintFormat = await this.generateFingerprint();\n\n      if (fingerprintFormat === null) {\n        logError(\"Failed to generate fingerprint data\");\n        return false;\n      }\n\n      // Convert to JSON string and save to file\n      const fingerprintJson = fingerprintFormat.toJson(2);\n      const success = await this.saveToFile(fingerprintJson, outputFilename);\n\n      if (success) {\n        logInfo(\n          `Fingerprint generation completed successfully! Saved to ${outputFilename}`\n        );\n        return true;\n      } else {\n        logError(\"Failed to save fingerprint data\");\n        return false;\n      }\n    } catch (error) {\n      logError(`Error generating fingerprint to file: ${error}`);\n      return false;\n    }\n  }\n\n  /**\n   * Extract fingerprint data from the page.\n   */\n  private async extractFingerprintData(page: Page): Promise<any> {\n    // Define the fingerprint extraction function as a string to avoid bundling issues\n    const extractionFunction = `\n      async function() {\n        // Helper function to get audio codec support\n        function getAudioCodecs() {\n          const audio = document.createElement('audio');\n          return {\n            ogg: audio.canPlayType('audio/ogg; codecs=\"vorbis\"') || '',\n            mp3: audio.canPlayType('audio/mpeg') || '',\n            wav: audio.canPlayType('audio/wav; codecs=\"1\"') || '',\n            m4a: audio.canPlayType('audio/x-m4a') || '',\n            aac: audio.canPlayType('audio/aac') || ''\n          };\n        }\n\n        // Helper function to get video codec support\n        function getVideoCodecs() {\n          const video = document.createElement('video');\n          return {\n            ogg: video.canPlayType('video/ogg; codecs=\"theora\"') || '',\n            h264: video.canPlayType('video/mp4; codecs=\"avc1.42E01E\"') || '',\n            webm: video.canPlayType('video/webm; codecs=\"vp8, vorbis\"') || ''\n          };\n        }\n\n        // Helper function to get plugins data\n        function getPluginsData() {\n          const plugins = [];\n          const mimeTypes = [];\n\n          for (let i = 0; i < navigator.plugins.length; i++) {\n            const plugin = navigator.plugins[i];\n            const pluginData = {\n              name: plugin.name,\n              description: plugin.description,\n              filename: plugin.filename,\n              mimeTypes: []\n            };\n\n            for (let j = 0; j < plugin.length; j++) {\n              const mimeType = plugin[j];\n              pluginData.mimeTypes.push({\n                type: mimeType.type,\n                suffixes: mimeType.suffixes,\n                description: mimeType.description,\n                enabledPlugin: plugin.name\n              });\n\n              mimeTypes.push(mimeType.description + '~~' + mimeType.type + '~~' + mimeType.suffixes);\n            }\n\n            plugins.push(pluginData);\n          }\n\n          return { plugins, mimeTypes };\n        }\n\n        // Helper function to get battery info\n        async function getBatteryInfo() {\n          try {\n            if ('getBattery' in navigator) {\n              const battery = await navigator.getBattery();\n              return {\n                charging: battery.charging,\n                chargingTime: battery.chargingTime,\n                dischargingTime: battery.dischargingTime,\n                level: battery.level\n              };\n            }\n          } catch (e) {\n            console.log('Battery API not supported');\n          }\n\n          return {\n            charging: true,\n            chargingTime: 0,\n            dischargingTime: null,\n            level: 1\n          };\n        }\n\n        // Helper function to get WebGL info\n        function getWebGLInfo() {\n          try {\n            const canvas = document.createElement('canvas');\n            const gl = canvas.getContext('webgl') || canvas.getContext('experimental-webgl');\n\n            if (gl) {\n              const debugInfo = gl.getExtension('WEBGL_debug_renderer_info');\n              return {\n                renderer: debugInfo ? gl.getParameter(debugInfo.UNMASKED_RENDERER_WEBGL) : gl.getParameter(gl.RENDERER),\n                vendor: debugInfo ? gl.getParameter(debugInfo.UNMASKED_VENDOR_WEBGL) : gl.getParameter(gl.VENDOR)\n              };\n            }\n          } catch (e) {\n            console.log('WebGL not supported');\n          }\n\n          return {\n            renderer: \"Adreno (TM) 735\",\n            vendor: \"Qualcomm\"\n          };\n        }\n\n        // Helper function to get multimedia devices\n        async function getMultimediaDevices() {\n          try {\n            if ('mediaDevices' in navigator && 'enumerateDevices' in navigator.mediaDevices) {\n              const devices = await navigator.mediaDevices.enumerateDevices();\n              const speakers = [];\n              const micros = [];\n              const webcams = [];\n\n              devices.forEach(function(device) {\n                const deviceInfo = {\n                  deviceId: device.deviceId || '',\n                  kind: device.kind,\n                  label: device.label || '',\n                  groupId: device.groupId || ''\n                };\n\n                if (device.kind === 'audiooutput') {\n                  speakers.push(deviceInfo);\n                } else if (device.kind === 'audioinput') {\n                  micros.push(deviceInfo);\n                } else if (device.kind === 'videoinput') {\n                  webcams.push(deviceInfo);\n                }\n              });\n\n              return { speakers: speakers, micros: micros, webcams: webcams };\n            }\n          } catch (e) {\n            console.log('Media devices not accessible');\n          }\n\n          return {\n            speakers: [{ deviceId: '', kind: 'audiooutput', label: '', groupId: '' }],\n            micros: [{ deviceId: '', kind: 'audioinput', label: '', groupId: '' }],\n            webcams: []\n          };\n        }\n\n        // Helper function to get available fonts\n        function getFonts() {\n          const testFonts = [\n            'Arial', 'Helvetica', 'Times New Roman', 'Courier New', 'Verdana',\n            'Georgia', 'Palatino', 'Garamond', 'Bookman', 'Comic Sans MS',\n            'Trebuchet MS', 'Arial Black', 'Impact'\n          ];\n\n          const availableFonts = [];\n          const testString = 'mmmmmmmmmmlli';\n          const testSize = '72px';\n          const baseWidth = {};\n          const baseHeight = {};\n\n          const canvas = document.createElement('canvas');\n          const context = canvas.getContext('2d');\n          if (!context) return availableFonts;\n\n          const defaultFonts = ['monospace', 'sans-serif', 'serif'];\n          defaultFonts.forEach(function(font) {\n            context.font = testSize + ' ' + font;\n            const metrics = context.measureText(testString);\n            baseWidth[font] = metrics.width;\n            baseHeight[font] = metrics.actualBoundingBoxAscent + metrics.actualBoundingBoxDescent;\n          });\n\n          testFonts.forEach(function(font) {\n            let detected = false;\n            defaultFonts.forEach(function(baseFont) {\n              context.font = testSize + ' ' + font + ', ' + baseFont;\n              const metrics = context.measureText(testString);\n              const width = metrics.width;\n              const height = metrics.actualBoundingBoxAscent + metrics.actualBoundingBoxDescent;\n\n              if (width !== baseWidth[baseFont] || height !== baseHeight[baseFont]) {\n                detected = true;\n              }\n            });\n\n            if (detected) {\n              availableFonts.push(font);\n            }\n          });\n\n          return availableFonts;\n        }\n\n        // Get battery info\n        const batteryInfo = await getBatteryInfo();\n\n        // Get multimedia devices\n        const multimediaDevices = await getMultimediaDevices();\n\n        // Build the complete fingerprint object\n        const fingerprint = {\n          screen: {\n            availTop: screen.availTop,\n            availLeft: screen.availLeft,\n            pageXOffset: window.pageXOffset,\n            pageYOffset: window.pageYOffset,\n            screenX: window.screenX,\n            hasHDR: screen.colorDepth > 24,\n            width: screen.width,\n            height: screen.height,\n            availWidth: screen.availWidth,\n            availHeight: screen.availHeight,\n            clientWidth: document.documentElement.clientWidth,\n            clientHeight: document.documentElement.clientHeight,\n            innerWidth: window.innerWidth,\n            innerHeight: window.innerHeight,\n            outerWidth: window.outerWidth,\n            outerHeight: window.outerHeight,\n            colorDepth: screen.colorDepth,\n            pixelDepth: screen.pixelDepth,\n            devicePixelRatio: window.devicePixelRatio\n          },\n          navigator: {\n            userAgent: navigator.userAgent,\n            userAgentData: navigator.userAgentData ? {\n              brands: navigator.userAgentData.brands || [],\n              mobile: navigator.userAgentData.mobile || false,\n              platform: navigator.userAgentData.platform || ''\n            } : null,\n            language: navigator.language,\n            languages: navigator.languages || [],\n            platform: navigator.platform,\n            deviceMemory: navigator.deviceMemory || 8,\n            hardwareConcurrency: navigator.hardwareConcurrency || 8,\n            maxTouchPoints: navigator.maxTouchPoints || 0,\n            product: navigator.product,\n            productSub: navigator.productSub,\n            vendor: navigator.vendor,\n            vendorSub: navigator.vendorSub,\n            doNotTrack: navigator.doNotTrack,\n            appCodeName: navigator.appCodeName,\n            appName: navigator.appName,\n            appVersion: navigator.appVersion,\n            oscpu: navigator.oscpu,\n            extraProperties: {\n              vendorFlavors: ['chrome'],\n              globalPrivacyControl: navigator.globalPrivacyControl || null,\n              pdfViewerEnabled: navigator.pdfViewerEnabled || true,\n              installedApps: []\n            },\n            webdriver: false\n          },\n          audioCodecs: getAudioCodecs(),\n          videoCodecs: getVideoCodecs(),\n          pluginsData: getPluginsData(),\n          battery: batteryInfo,\n          videoCard: getWebGLInfo(),\n          multimediaDevices: multimediaDevices,\n          fonts: getFonts(),\n          mockWebRTC: false,\n          slim: false\n        };\n\n        return fingerprint;\n      }\n    `;\n\n    return await page.evaluate(extractionFunction);\n  }\n\n  /**\n   * Extract headers data from httpbin.\n   */\n  private async extractHeadersData(\n    page: Page\n  ): Promise<Record<string, string>> {\n    try {\n      logInfo(\"Getting request headers...\");\n      await page.goto(\"https://httpbin.org/headers\", {\n        waitUntil: \"networkidle\",\n      });\n\n      // Extract headers from the response\n      const allHeaders = await page.evaluate(() => {\n        try {\n          // @ts-expect-error - document is available in browser context\n          const preElement = document.querySelector(\"pre\");\n          if (preElement) {\n            const data = JSON.parse(preElement.textContent || \"{}\");\n            return data.headers || {};\n          }\n        } catch (e) {\n          console.log(\"Failed to parse headers:\", e);\n        }\n        return {};\n      });\n\n      // Filter only the key headers from the example\n      const keyHeaders = [\n        \"sec-ch-ua\",\n        \"sec-ch-ua-mobile\",\n        \"sec-ch-ua-platform\",\n        \"upgrade-insecure-requests\",\n        \"user-agent\",\n        \"accept\",\n        \"sec-fetch-site\",\n        \"sec-fetch-mode\",\n        \"sec-fetch-user\",\n        \"sec-fetch-dest\",\n        \"accept-encoding\",\n        \"accept-language\",\n      ];\n\n      const headersData: Record<string, string> = {};\n      // Convert all_headers keys to lowercase for case-insensitive matching\n      const allHeadersLower: Record<string, string> = {};\n      for (const [key, value] of Object.entries(allHeaders)) {\n        allHeadersLower[key.toLowerCase()] = value as string;\n      }\n\n      for (const header of keyHeaders) {\n        const headerLower = header.toLowerCase();\n        if (headerLower in allHeadersLower) {\n          headersData[header] = allHeadersLower[headerLower];\n        }\n      }\n\n      return headersData;\n    } catch (error) {\n      logWarn(`Failed to extract headers: ${error}`);\n      return {};\n    }\n  }\n\n  /**\n   * Save JSON string data to a file.\n   */\n  private async saveToFile(\n    jsonData: string,\n    filename: string\n  ): Promise<boolean> {\n    try {\n      // In Node.js environment\n      if (typeof require !== \"undefined\") {\n        // eslint-disable-next-line @typescript-eslint/no-var-requires\n        const fs = require(\"fs\");\n        fs.writeFileSync(filename, jsonData, \"utf8\");\n        logInfo(`Fingerprint data saved to ${filename}`);\n        return true;\n      } else {\n        // In browser environment, we can't save files directly\n        logWarn(\"File saving not supported in browser environment\");\n        return false;\n      }\n    } catch (error) {\n      logError(`Failed to save fingerprint data: ${error}`);\n      return false;\n    }\n  }\n}\n","export { Code } from \"./code\";\nexport type { CodeExecutionResult } from \"../types/api-response\";\n","import {\n  CodeExecutionResult,\n  CodeExecutionResultItem,\n  CodeExecutionLogs,\n  CodeExecutionError,\n} from \"../types/api-response\";\n\n/**\n * Handles code execution operations in the AgentBay cloud environment.\n */\nexport class Code {\n  private session: {\n    getAPIKey(): string;\n    getSessionId(): string;\n    getWsClient?: () => Promise<any>;\n    mcpTools?: Array<{ name?: string; server?: string }>;\n    callMcpTool(\n      toolName: string,\n      args: any,\n      autoGenSession?: boolean\n    ): Promise<{\n      success: boolean;\n      data: string;\n      errorMessage: string;\n      requestId: string;\n    }>;\n  };\n\n  /**\n   * Initialize a Code object.\n   *\n   * @param session - The Session instance that this Code belongs to.\n   */\n  constructor(session: {\n    getAPIKey(): string;\n    getSessionId(): string;\n    getWsClient?: () => Promise<any>;\n    mcpTools?: Array<{ name?: string; server?: string }>;\n    callMcpTool(\n      toolName: string,\n      args: any,\n      autoGenSession?: boolean\n    ): Promise<{\n      success: boolean;\n      data: string;\n      errorMessage: string;\n      requestId: string;\n    }>;\n  }) {\n    this.session = session;\n  }\n\n  /**\n   * Parses the backend JSON response into a structured CodeExecutionResult\n   * @param data Raw JSON string from backend\n   */\n  private parseBackendResponse(data: string): CodeExecutionResult {\n    let raw: any;\n    try {\n      raw = JSON.parse(data);\n      // Handle double-encoded JSON if necessary\n      if (typeof raw === \"string\") {\n        try {\n          raw = JSON.parse(raw);\n        } catch (e) {\n          // If second parse fails, keep as string (legacy output)\n        }\n      }\n    } catch (e) {\n      // Not JSON, assume legacy plain string result or simple error message\n      return {\n        requestId: \"\", // Will be filled later\n        success: true,\n        result: data,\n        logs: { stdout: [data], stderr: [] },\n        results: [{ text: data, isMainResult: true }],\n      };\n    }\n\n    // Check if it's the expected structure (has result array or logs)\n    // If parsed but not the structure we want, treat as plain object result?\n    // But usually if it parses as object, it's likely our structure or empty object.\n\n    const logs: CodeExecutionLogs = {\n      stdout: raw.stdout || [],\n      stderr: raw.stderr || [],\n    };\n\n    const results: CodeExecutionResultItem[] = [];\n    if (Array.isArray(raw.result)) {\n      for (const itemStr of raw.result) {\n        try {\n          // Items in 'result' are JSON strings themselves\n          const itemMap =\n            typeof itemStr === \"string\" ? JSON.parse(itemStr) : itemStr;\n          const item: CodeExecutionResultItem = {};\n\n          if (itemMap.isMainResult) item.isMainResult = true;\n          if (itemMap.is_main_result) item.isMainResult = true;\n\n          // Map MIME types to fields\n          if (itemMap[\"text/plain\"]) item.text = itemMap[\"text/plain\"];\n          if (itemMap[\"text/html\"]) item.html = itemMap[\"text/html\"];\n          if (itemMap[\"text/markdown\"])\n            item.markdown = itemMap[\"text/markdown\"];\n          if (itemMap[\"image/png\"]) item.png = itemMap[\"image/png\"];\n          if (itemMap[\"image/jpeg\"]) item.jpeg = itemMap[\"image/jpeg\"];\n          if (itemMap[\"image/svg+xml\"]) item.svg = itemMap[\"image/svg+xml\"];\n          if (itemMap[\"text/latex\"]) item.latex = itemMap[\"text/latex\"];\n          if (itemMap[\"application/json\"])\n            item.json = itemMap[\"application/json\"];\n\n          // Chart support (Vega/Vega-Lite)\n          if (itemMap[\"application/vnd.vegalite.v4+json\"]) {\n            item.chart = itemMap[\"application/vnd.vegalite.v4+json\"];\n          } else if (itemMap[\"application/vnd.vegalite.v5+json\"]) {\n            item.chart = itemMap[\"application/vnd.vegalite.v5+json\"];\n          } else if (itemMap[\"application/vnd.vega.v5+json\"]) {\n            item.chart = itemMap[\"application/vnd.vega.v5+json\"];\n          }\n\n          results.push(item);\n        } catch (e) {\n          // Ignore parse errors for individual items\n        }\n      }\n    }\n\n    let error: CodeExecutionError | undefined;\n    if (raw.executionError) {\n      error = {\n        name: \"ExecutionError\",\n        value: raw.executionError,\n        traceback: \"\",\n      };\n    }\n\n    // Determine legacy result string for backward compatibility\n    let resultText = \"\";\n    const mainRes = results.find((r) => r.isMainResult && r.text);\n    if (mainRes && mainRes.text) {\n      resultText = mainRes.text;\n    } else if (results.length > 0 && results[0].text) {\n      resultText = results[0].text;\n    } else if (logs.stdout.length > 0) {\n      resultText = logs.stdout.join(\"\");\n    }\n\n    return {\n      requestId: \"\", // Will be filled by caller\n      success: !raw.executionError,\n      result: resultText,\n      errorMessage: raw.executionError,\n      logs,\n      results,\n      error,\n      executionTime: raw.executionTime || raw.execution_time,\n      executionCount: raw.executionCount || raw.execution_count,\n    };\n  }\n\n  private safeToString(v: any): string {\n    try {\n      if (typeof v === \"string\") return v;\n      return JSON.stringify(v);\n    } catch (_e) {\n      return String(v);\n    }\n  }\n\n  private toResultItem(payload: any): CodeExecutionResultItem {\n    const item: CodeExecutionResultItem = {};\n    if (!payload || typeof payload !== \"object\") {\n      item.text = String(payload);\n      return item;\n    }\n\n    if (payload.isMainResult) item.isMainResult = true;\n    if (payload.is_main_result) item.isMainResult = true;\n\n    if (payload[\"text/plain\"]) item.text = payload[\"text/plain\"];\n    if (payload[\"text/html\"]) item.html = payload[\"text/html\"];\n    if (payload[\"text/markdown\"]) item.markdown = payload[\"text/markdown\"];\n    if (payload[\"image/png\"]) item.png = payload[\"image/png\"];\n    if (payload[\"image/jpeg\"]) item.jpeg = payload[\"image/jpeg\"];\n    if (payload[\"image/svg+xml\"]) item.svg = payload[\"image/svg+xml\"];\n    if (payload[\"text/latex\"]) item.latex = payload[\"text/latex\"];\n    if (payload[\"application/json\"]) item.json = payload[\"application/json\"];\n\n    if (payload[\"application/vnd.vegalite.v4+json\"]) {\n      item.chart = payload[\"application/vnd.vegalite.v4+json\"];\n    } else if (payload[\"application/vnd.vegalite.v5+json\"]) {\n      item.chart = payload[\"application/vnd.vegalite.v5+json\"];\n    } else if (payload[\"application/vnd.vega.v5+json\"]) {\n      item.chart = payload[\"application/vnd.vega.v5+json\"];\n    }\n\n    if (payload.text && !item.text) item.text = payload.text;\n    return item;\n  }\n\n  private async runCodeStreamWs(params: {\n    code: string;\n    language: string;\n    timeoutS: number;\n    onStdout?: (chunk: string) => void;\n    onStderr?: (chunk: string) => void;\n    onError?: (err: any) => void;\n  }): Promise<CodeExecutionResult> {\n    const stdoutChunks: string[] = [];\n    const stderrChunks: string[] = [];\n    const results: CodeExecutionResultItem[] = [];\n    let errorObj: CodeExecutionError | undefined;\n    let errorMessage = \"\";\n\n    // Determine target from MCP tool list if available.\n    let target = \"wuying_codespace\";\n    for (const tool of this.session.mcpTools || []) {\n      if (tool && tool.name === \"run_code\" && tool.server) {\n        target = tool.server;\n        break;\n      }\n    }\n\n    if (!this.session.getWsClient) {\n      return {\n        requestId: \"\",\n        success: false,\n        result: \"\",\n        errorMessage: \"WS streaming is not available in this session\",\n      };\n    }\n\n    const wsClient = await this.session.getWsClient();\n\n    const handle = await wsClient.callStream({\n      target,\n      data: {\n        method: \"run_code\",\n        mode: \"stream\",\n        params: {\n          language: params.language,\n          timeoutS: params.timeoutS,\n          code: params.code,\n        },\n      },\n      onEvent: (_invocationId: string, data: any) => {\n        const eventType = data?.eventType;\n        if (eventType === \"stdout\") {\n          const chunk = String(data?.chunk ?? \"\");\n          stdoutChunks.push(chunk);\n          if (params.onStdout) params.onStdout(chunk);\n          return;\n        }\n        if (eventType === \"stderr\") {\n          const chunk = String(data?.chunk ?? \"\");\n          stderrChunks.push(chunk);\n          if (params.onStderr) params.onStderr(chunk);\n          return;\n        }\n        if (eventType === \"result\") {\n          const r = this.toResultItem(data?.result);\n          results.push(r);\n          return;\n        }\n        if (eventType === \"error\") {\n          const msg =\n            typeof data?.error === \"string\"\n              ? data.error\n              : this.safeToString(data);\n          errorMessage = msg;\n          errorObj = {\n            name: \"ExecutionError\",\n            value: msg,\n            traceback: \"\",\n          };\n          if (params.onError) params.onError(data);\n          return;\n        }\n      },\n      onEnd: (_invocationId: string, data: any) => {\n        const executionError = data?.executionError;\n        if (executionError && !errorObj) {\n          const msg = String(executionError);\n          errorMessage = msg;\n          errorObj = { name: \"ExecutionError\", value: msg, traceback: \"\" };\n        }\n      },\n      onError: (_invocationId: string, err: any) => {\n        const msg = err instanceof Error ? err.message : String(err);\n        errorMessage = msg;\n        if (!errorObj) {\n          errorObj = { name: \"ExecutionError\", value: msg, traceback: \"\" };\n        }\n        if (params.onError) params.onError(err);\n      },\n    });\n\n    let endData: any = {};\n    try {\n      endData = await handle.waitEnd();\n    } catch (e: any) {\n      const msg = e instanceof Error ? e.message : String(e);\n      return {\n        requestId: handle.invocationId,\n        success: false,\n        result: \"\",\n        errorMessage: msg,\n        logs: { stdout: stdoutChunks, stderr: stderrChunks },\n        results,\n        error: errorObj,\n      };\n    }\n\n    const ok =\n      !errorObj && !endData?.executionError && endData?.status !== \"failed\";\n\n    const logs: CodeExecutionLogs = {\n      stdout: stdoutChunks,\n      stderr: stderrChunks,\n    };\n\n    // Determine legacy result string for backward compatibility\n    let resultText = \"\";\n    const mainRes = results.find((r) => r.isMainResult && r.text);\n    if (mainRes && mainRes.text) {\n      resultText = mainRes.text;\n    } else if (results.length > 0 && results[0].text) {\n      resultText = results[0].text;\n    } else if (logs.stdout.length > 0) {\n      resultText = logs.stdout.join(\"\");\n    }\n\n    return {\n      requestId: handle.invocationId,\n      success: ok,\n      result: resultText,\n      errorMessage: ok\n        ? \"\"\n        : errorMessage || String(endData?.executionError || \"\"),\n      logs,\n      results,\n      error: errorObj,\n      executionTime: endData?.executionTime,\n      executionCount: endData?.executionCount,\n    };\n  }\n\n  /**\n   * Execute code in the specified language with a timeout.\n   * Corresponds to Python's run_code() method\n   *\n   * @param code - The code to execute.\n   * @param language - The programming language of the code. Case-insensitive.\n   *                  Supported values: 'python', 'javascript', 'r', 'java'.\n   * @param timeoutS - The timeout for the code execution in seconds. Default is 60s.\n   *                   Note: Due to gateway limitations, each request cannot exceed 60 seconds.\n   * @param options - Optional streaming options. When streamBeta is true, uses WebSocket\n   *                 streaming for real-time stdout/stderr output.\n   * @returns CodeExecutionResult with code execution output and requestId\n   * @throws Error if an unsupported language is specified.\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: 'your_api_key' });\n   * const result = await agentBay.create({ imageId: \"code_latest\" });\n   * if (result.success) {\n   *   const codeResult = await result.session.code.runCode('print(\"Hello\")', \"python\");\n   *   console.log(codeResult.result);\n   *   if (codeResult.results) {\n   *      // Access rich output like images or charts\n   *   }\n   *   await result.session.delete();\n   * }\n   * ```\n   */\n  async runCode(\n    code: string,\n    language: string,\n    timeoutS = 60,\n    options?: {\n      streamBeta?: boolean;\n      onStdout?: (chunk: string) => void;\n      onStderr?: (chunk: string) => void;\n      onError?: (err: any) => void;\n    }\n  ): Promise<CodeExecutionResult> {\n    try {\n      // Normalize and validate language (case-insensitive)\n      const rawLanguage = language ?? \"\";\n      const normalizedLanguage = String(rawLanguage).trim().toLowerCase();\n      const aliases: Record<string, string> = {\n        py: \"python\",\n        python3: \"python\",\n        js: \"javascript\",\n        node: \"javascript\",\n        nodejs: \"javascript\",\n      };\n      const canonicalLanguage =\n        aliases[normalizedLanguage] || normalizedLanguage;\n      const supported = new Set([\"python\", \"javascript\", \"r\", \"java\"]);\n\n      if (!supported.has(canonicalLanguage)) {\n        return {\n          requestId: \"\",\n          success: false,\n          result: \"\",\n          errorMessage: `Unsupported language: ${rawLanguage}. Supported languages are 'python', 'javascript', 'r', and 'java'`,\n        };\n      }\n\n      if (options?.streamBeta) {\n        return await this.runCodeStreamWs({\n          code,\n          language: canonicalLanguage,\n          timeoutS,\n          onStdout: options.onStdout,\n          onStderr: options.onStderr,\n          onError: options.onError,\n        });\n      }\n\n      const args = {\n        code,\n        language: canonicalLanguage,\n        timeout_s: timeoutS,\n      };\n\n      const response = await this.session.callMcpTool(\"run_code\", args, false);\n\n      let codeResult: CodeExecutionResult;\n\n      // Even if response.success is false, data might contain structured error info\n      if (response.success) {\n        codeResult = this.parseBackendResponse(response.data);\n      } else {\n        // Check if errorMessage is JSON\n        try {\n          if (\n            response.errorMessage &&\n            response.errorMessage.trim().startsWith(\"{\")\n          ) {\n            codeResult = this.parseBackendResponse(response.errorMessage);\n            codeResult.success = false;\n          } else {\n            // Real failure not from code execution but tool failure\n            return {\n              requestId: response.requestId,\n              success: false,\n              result: \"\",\n              errorMessage: response.errorMessage,\n            };\n          }\n        } catch {\n          return {\n            requestId: response.requestId,\n            success: false,\n            result: \"\",\n            errorMessage: response.errorMessage,\n          };\n        }\n      }\n\n      codeResult.requestId = response.requestId;\n      return codeResult;\n    } catch (error) {\n      return {\n        requestId: \"\",\n        success: false,\n        result: \"\",\n        errorMessage: `Failed to run code: ${error}`,\n      };\n    }\n  }\n\n  /**\n   * Alias of runCode().\n   */\n  async run(\n    code: string,\n    language: string,\n    timeoutS = 60,\n    options?: {\n      streamBeta?: boolean;\n      onStdout?: (chunk: string) => void;\n      onStderr?: (chunk: string) => void;\n      onError?: (err: any) => void;\n    }\n  ): Promise<CodeExecutionResult> {\n    return await this.runCode(code, language, timeoutS, options);\n  }\n\n  /**\n   * Alias of runCode().\n   */\n  async execute(\n    code: string,\n    language: string,\n    timeoutS = 60,\n    options?: {\n      streamBeta?: boolean;\n      onStdout?: (chunk: string) => void;\n      onStderr?: (chunk: string) => void;\n      onError?: (err: any) => void;\n    }\n  ): Promise<CodeExecutionResult> {\n    return await this.runCode(code, language, timeoutS, options);\n  }\n}\n","import { Session } from \"../session\";\nimport { CommandResult } from \"../types/api-response\";\n\n/**\n * Parsed result from a shell-tool MCP response payload.\n */\ninterface ParsedShellPayload {\n  stdout: string;\n  stderr: string;\n  exitCode: number;\n  traceId: string;\n}\n\n/**\n * Conservatively determines whether a parsed JSON object looks like the\n * shell-tool wrapped envelope `{exit_code, stdout, stderr}`.\n *\n * Different sandbox images return data in different shapes:\n * - **Wrapped** (code_latest): `{\"exit_code\":0,\"stdout\":\"...\",\"stderr\":\"...\"}`\n * - **Raw** (imgc-* / openclaw): the command's stdout returned verbatim\n *\n * We require strong signals to avoid mistaking user command JSON output\n * for the wrapper:\n * 1. Integer `exit_code` + at least one string `stdout`/`stderr`, OR\n * 2. Both string `stdout` and `stderr` present.\n */\nfunction looksLikeWrappedShellPayload(obj: any): boolean {\n  if (obj == null || typeof obj !== \"object\" || Array.isArray(obj)) {\n    return false;\n  }\n  const hasIntExitCode =\n    typeof obj.exit_code === \"number\" && Number.isInteger(obj.exit_code);\n  const hasStdout = typeof obj.stdout === \"string\";\n  const hasStderr = typeof obj.stderr === \"string\";\n  if (hasIntExitCode && (hasStdout || hasStderr)) {\n    return true;\n  }\n  return hasStdout && hasStderr;\n}\n\n/**\n * Parses a shell-tool MCP response payload into a structured result.\n * Detects the wrapped format conservatively; anything else is treated\n * as raw command output returned verbatim.\n */\nfunction parseShellPayload(rawData: string): ParsedShellPayload {\n  if (!rawData) {\n    return { stdout: \"\", stderr: \"\", exitCode: 0, traceId: \"\" };\n  }\n  try {\n    const parsed = JSON.parse(rawData);\n    if (looksLikeWrappedShellPayload(parsed)) {\n      return {\n        stdout: parsed.stdout || \"\",\n        stderr: parsed.stderr || \"\",\n        exitCode: typeof parsed.exit_code === \"number\" ? parsed.exit_code : 0,\n        traceId: parsed.traceId || \"\",\n      };\n    }\n  } catch {\n    // Not valid JSON — fall through to raw treatment.\n  }\n  return { stdout: rawData, stderr: \"\", exitCode: 0, traceId: \"\" };\n}\n\n/**\n * Handles command execution operations in the AgentBay cloud environment.\n */\nexport class Command {\n  private session: Session;\n\n  /**\n   * Initialize a Command object.\n   *\n   * @param session - The Session instance that this Command belongs to.\n   */\n  constructor(session: Session) {\n    this.session = session;\n  }\n\n  /**\n   * Sanitizes error messages to remove sensitive information like API keys.\n   *\n   * @param error - The error to sanitize\n   * @returns The sanitized error\n   */\n  private sanitizeError(error: any): any {\n    if (!error) {\n      return error;\n    }\n\n    const errorString = String(error);\n    return errorString.replace(/Bearer\\s+[^\\s]+/g, \"Bearer [REDACTED]\");\n  }\n\n  /**\n   * Execute a shell command with optional working directory and environment variables.\n   *\n   * Executes a shell command in the session environment with configurable timeout,\n   * working directory, and environment variables. The command runs with session\n   * user permissions in a Linux shell environment.\n   *\n   * @param command - The shell command to execute\n   * @param timeoutMs - Timeout in milliseconds (default: 50000ms/50s).\n   * @param cwd - The working directory for command execution. If not specified,\n   *              the command runs in the default session directory\n   * @param envs - Environment variables as a dictionary of key-value pairs.\n   *              These variables are set for the command execution only\n   *\n   * @returns Promise resolving to CommandResult containing:\n   *          - success: Whether the command executed successfully (exitCode === 0)\n   *          - output: Command output for backward compatibility (stdout + stderr)\n   *          - exitCode: The exit code of the command execution (0 for success)\n   *          - stdout: Standard output from the command execution\n   *          - stderr: Standard error from the command execution\n   *          - traceId: Trace ID for error tracking (only present when exitCode !== 0)\n   *          - requestId: Unique identifier for this API request\n   *          - errorMessage: Error description if execution failed\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: 'your_api_key' });\n   * const result = await agentBay.create();\n   * if (result.success) {\n   *   const cmdResult = await result.session.command.executeCommand('echo \"Hello\"', 5000);\n   *   console.log('Command output:', cmdResult.output);\n   *   console.log('Exit code:', cmdResult.exitCode);\n   *   console.log('Stdout:', cmdResult.stdout);\n   *   await result.session.delete();\n   * }\n   * ```\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: 'your_api_key' });\n   * const result = await agentBay.create();\n   * if (result.success) {\n   *   const cmdResult = await result.session.command.executeCommand(\n   *     'pwd',\n   *     5000,\n   *     '/tmp',\n   *     { TEST_VAR: 'test_value' }\n   *   );\n   *   console.log('Working directory:', cmdResult.stdout);\n   *   await result.session.delete();\n   * }\n   * ```\n   */\n  async executeCommand(\n    command: string,\n    timeoutMs = 1000,\n    cwd?: string,\n    envs?: Record<string, string>\n  ): Promise<CommandResult> {\n    // Validate environment variables - strict type checking (before try block to allow Error to propagate)\n    if (envs !== undefined) {\n      const invalidVars: string[] = [];\n      for (const [key, value] of Object.entries(envs)) {\n        if (typeof key !== \"string\") {\n          invalidVars.push(`key '${key}' (type: ${typeof key})`);\n        }\n        if (typeof value !== \"string\") {\n          invalidVars.push(`value for key '${key}' (type: ${typeof value})`);\n        }\n      }\n\n      if (invalidVars.length > 0) {\n        throw new Error(\n          `Invalid environment variables: all keys and values must be strings. ` +\n            `Found invalid entries: ${invalidVars.join(\", \")}`\n        );\n      }\n    }\n\n    try {\n      // Build request arguments\n      const args: Record<string, any> = {\n        command,\n        timeout_ms: timeoutMs,\n      };\n      if (cwd !== undefined) {\n        args.cwd = cwd;\n      }\n      if (envs !== undefined) {\n        args.envs = envs;\n      }\n\n      const result = await this.session.callMcpTool(\"shell\", args, false);\n\n      if (result.success) {\n        const rawData =\n          result.data == null\n            ? \"\"\n            : typeof result.data === \"string\"\n            ? result.data\n            : String(result.data);\n        const parsed = parseShellPayload(rawData);\n        return {\n          requestId: result.requestId,\n          success: parsed.exitCode === 0,\n          output: parsed.stdout + parsed.stderr,\n          exitCode: parsed.exitCode,\n          stdout: parsed.stdout,\n          stderr: parsed.stderr,\n          traceId: parsed.traceId || undefined,\n          errorMessage: result.errorMessage,\n        };\n      } else {\n        const rawErr = result.errorMessage || \"\";\n        const parsed = parseShellPayload(rawErr);\n        const effectiveExitCode = parsed.exitCode !== 0 ? parsed.exitCode : 1;\n        const effectiveError =\n          parsed.stderr || rawErr || \"Failed to execute command\";\n        return {\n          requestId: result.requestId,\n          success: false,\n          output: parsed.stdout + parsed.stderr,\n          exitCode: effectiveExitCode,\n          stdout: parsed.stdout,\n          stderr: parsed.stderr,\n          traceId: parsed.traceId || undefined,\n          errorMessage: effectiveError,\n        };\n      }\n    } catch (error) {\n      return {\n        requestId: \"\",\n        success: false,\n        output: \"\",\n        errorMessage: `Failed to execute command: ${error}`,\n      };\n    }\n  }\n\n  /**\n   * Alias of executeCommand().\n   */\n  async run(\n    command: string,\n    timeoutMs = 1000,\n    cwd?: string,\n    envs?: Record<string, string>\n  ): Promise<CommandResult> {\n    return await this.executeCommand(command, timeoutMs, cwd, envs);\n  }\n\n  /**\n   * Alias of executeCommand().\n   */\n  async exec(\n    command: string,\n    timeoutMs = 1000,\n    cwd?: string,\n    envs?: Record<string, string>\n  ): Promise<CommandResult> {\n    return await this.executeCommand(command, timeoutMs, cwd, envs);\n  }\n}\n","/**\n * Command templates for various AgentBay operations.\n *\n * This module contains shell command templates used by different modules\n * to execute operations in remote environments.\n *\n * Template naming convention:\n * - Use descriptive names that clearly indicate the operation\n * - Group templates by functionality (mobile, desktop, network, etc.)\n * - Use consistent parameter naming across similar templates\n *\n * Parameter conventions:\n * - Use snake_case for parameter names\n * - Include descriptive parameter names (e.g., lock_switch, package_list)\n * - Document expected parameter types and values\n */\n\n// ================================\n// Mobile Device Command Templates\n// ================================\n\n/**\n * Resolution lock template\n * Parameters:\n *   lock_switch (string): \"1\" to enable lock, \"0\" to disable lock\n */\nexport const RESOLUTION_LOCK_TEMPLATE =\n  \"setprop sys.wuying.lockres {lock_switch}\";\n\n/**\n * Application whitelist template\n * Parameters:\n *   package_list (string): Newline-separated list of package names\n */\nexport const APP_WHITELIST_TEMPLATE = `cat > /data/system/pm_whitelist.txt << 'EOF'\n{package_list}\nEOF\nchmod 644 /data/system/pm_whitelist.txt\nsetprop rw.wy.pm_whitelist.refresh 1\nsetprop persist.wy.pm_blacklist.switch 2`;\n\n/**\n * Application blacklist template\n * Parameters:\n *   package_list (string): Newline-separated list of package names\n */\nexport const APP_BLACKLIST_TEMPLATE = `cat > /data/system/pm_blacklist.txt << 'EOF'\n{package_list}\nEOF\nchmod 644 /data/system/pm_blacklist.txt\nsetprop rw.wy.pm_blacklist.refresh 1\nsetprop persist.wy.pm_blacklist.switch 1`;\n\n/**\n * Hide navigation bar template\n * Hides the system navigation bar by setting system property and restarting SystemUI\n */\nexport const HIDE_NAVIGATION_BAR_TEMPLATE =\n  \"setprop persist.wy.hasnavibar false; killall com.android.systemui\";\n\n/**\n * Show navigation bar template\n * Shows the system navigation bar by setting system property and restarting SystemUI\n */\nexport const SHOW_NAVIGATION_BAR_TEMPLATE =\n  \"setprop persist.wy.hasnavibar true; killall com.android.systemui\";\n\n/**\n * Uninstall blacklist template\n * Parameters:\n *   package_list (string): Newline-separated list of package names\n *   timestamp (string): Current timestamp for trigger property\n */\nexport const UNINSTALL_BLACKLIST_TEMPLATE = `cat > /data/system/pm_lock.conf << 'EOF'\n{package_list}\nEOF\nchmod 644 /data/system/pm_lock.conf\nsetprop persist.wy.pm_lock.trigger {timestamp}`;\n\n/**\n * Mobile command templates mapping for easy access\n */\nexport const MOBILE_COMMAND_TEMPLATES: Record<string, string> = {\n  resolution_lock_enable: \"setprop sys.wuying.lockres 1\",\n  resolution_lock_disable: \"setprop sys.wuying.lockres 0\",\n  app_whitelist: APP_WHITELIST_TEMPLATE,\n  app_blacklist: APP_BLACKLIST_TEMPLATE,\n  hide_navigation_bar: HIDE_NAVIGATION_BAR_TEMPLATE,\n  show_navigation_bar: SHOW_NAVIGATION_BAR_TEMPLATE,\n  uninstall_blacklist: UNINSTALL_BLACKLIST_TEMPLATE,\n};\n\n/**\n * Get a mobile command template by name\n *\n * @param templateName - The name of the template to retrieve\n * @returns The template string if found, undefined otherwise\n */\nexport function getMobileCommandTemplate(\n  templateName: string\n): string | undefined {\n  return MOBILE_COMMAND_TEMPLATES[templateName];\n}\n\n/**\n * Check if a mobile command template exists\n *\n * @param templateName - The name of the template to check\n * @returns True if the template exists, false otherwise\n */\nexport function hasMobileCommandTemplate(templateName: string): boolean {\n  return templateName in MOBILE_COMMAND_TEMPLATES;\n}\n\n/**\n * Replace placeholders in a template with actual values\n *\n * @param template - The template string with placeholders\n * @param replacements - Object containing placeholder-value pairs\n * @returns The template with placeholders replaced\n */\nexport function replaceTemplatePlaceholders(\n  template: string,\n  replacements: Record<string, string>\n): string {\n  let result = template;\n  for (const [placeholder, value] of Object.entries(replacements)) {\n    const placeholderPattern = new RegExp(`\\\\{${placeholder}\\\\}`, \"g\");\n    result = result.replace(placeholderPattern, value);\n  }\n  return result;\n}\n","export {\n  Computer,\n  BoolResult,\n  CursorPosition,\n  ScreenSize,\n  ScreenshotResult,\n} from \"./computer\";\n","/**\n * Computer module for desktop UI automation.\n * Provides mouse, keyboard, and screen operations for desktop environments.\n */\n\nimport {\n  OperationResult,\n  WindowListResult,\n  WindowInfoResult,\n  BoolResult as WindowBoolResult,\n  InstalledAppListResult,\n  ProcessListResult,\n  ScreenSize,\n  CursorPosition,\n} from \"../types/api-response\";\nimport { convertObjectKeys, convertWindowData } from \"../utils/field-converter\";\n\nexport type {\n  BoolResult,\n  CursorPosition,\n  ScreenSize,\n} from \"../types/api-response\";\n\nexport interface ScreenshotResult extends OperationResult {\n  data: string; // Screenshot URL\n}\n\nexport interface BetaScreenshotResult extends OperationResult {\n  type: string;\n  mimeType: string;\n  data: Uint8Array;\n  width?: number;\n  height?: number;\n}\n\nexport enum MouseButton {\n  LEFT = \"left\",\n  RIGHT = \"right\",\n  MIDDLE = \"middle\",\n  DOUBLE_LEFT = \"double_left\",\n}\n\nexport enum ScrollDirection {\n  UP = \"up\",\n  DOWN = \"down\",\n  LEFT = \"left\",\n  RIGHT = \"right\",\n}\n\n// Session interface for Computer module\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ninterface ComputerSession {\n  // eslint-disable-next-line @typescript-eslint/no-explicit-any\n  callMcpTool(\n    toolName: string,\n    args: Record<string, any>,\n    autoGenSession?: boolean\n  ): Promise<any>;\n  sessionId: string;\n  getAPIKey(): string;\n  getSessionId(): string;\n  linkUrl: string;\n}\n\nexport class Computer {\n  private session: ComputerSession;\n\n  constructor(session: ComputerSession) {\n    this.session = session;\n  }\n\n  private static normalizeImageFormat(\n    format: string,\n    defaultValue: string\n  ): string {\n    const f = String(format || \"\")\n      .trim()\n      .toLowerCase();\n    if (!f) {\n      return defaultValue;\n    }\n    if (f === \"jpg\") {\n      return \"jpeg\";\n    }\n    return f;\n  }\n\n  private static validateBase64String(base64String: string): void {\n    const s = String(base64String || \"\");\n    if (!s) {\n      throw new Error(\"Empty base64 string\");\n    }\n    if (s.length % 4 !== 0) {\n      throw new Error(\"Invalid base64 string length\");\n    }\n    const base64WithoutPadding = s.replace(/=+$/, \"\");\n    if (!/^[A-Za-z0-9+/]+$/.test(base64WithoutPadding)) {\n      throw new Error(\"Invalid base64 string format\");\n    }\n    const paddingMatch = s.match(/=+$/);\n    if (paddingMatch && paddingMatch[0].length > 2) {\n      throw new Error(\"Invalid base64 padding format\");\n    }\n  }\n\n  private static decodeScreenshotJsonStrict(\n    jsonText: string,\n    expectedFormat: string\n  ): {\n    bytes: Uint8Array;\n    width?: number;\n    height?: number;\n    type: string;\n    mimeType: string;\n  } {\n    const s = String(jsonText || \"\").trim();\n    if (!s) {\n      throw new Error(\"Empty image data\");\n    }\n    if (!s.startsWith(\"{\")) {\n      throw new Error(\"Screenshot tool returned non-JSON data\");\n    }\n\n    let obj: any;\n    try {\n      obj = JSON.parse(s);\n    } catch (e) {\n      throw new Error(\n        `Invalid screenshot JSON: ${e instanceof Error ? e.message : String(e)}`\n      );\n    }\n    if (!obj || typeof obj !== \"object\" || Array.isArray(obj)) {\n      throw new Error(\"Invalid screenshot JSON: expected object\");\n    }\n\n    const shotType = obj.type;\n    const mimeType = obj.mime_type;\n    const b64 = obj.data;\n    if (typeof shotType !== \"string\" || !shotType.trim()) {\n      throw new Error(\n        \"Invalid screenshot JSON: expected non-empty string 'type'\"\n      );\n    }\n    if (typeof mimeType !== \"string\" || !mimeType.trim()) {\n      throw new Error(\n        \"Invalid screenshot JSON: expected non-empty string 'mime_type'\"\n      );\n    }\n    if (typeof b64 !== \"string\" || !b64.trim()) {\n      throw new Error(\"Screenshot JSON missing base64 field\");\n    }\n    const width = obj.width;\n    const height = obj.height;\n    if (width !== undefined && typeof width !== \"number\") {\n      throw new Error(\"Invalid screenshot JSON: expected number 'width'\");\n    }\n    if (height !== undefined && typeof height !== \"number\") {\n      throw new Error(\"Invalid screenshot JSON: expected number 'height'\");\n    }\n    Computer.validateBase64String(b64);\n\n    let bytes: Uint8Array;\n    if (typeof Buffer !== \"undefined\") {\n      bytes = new Uint8Array(Buffer.from(b64, \"base64\"));\n    } else {\n      const binary = atob(b64);\n      const out = new Uint8Array(binary.length);\n      for (let i = 0; i < binary.length; i++) {\n        out[i] = binary.charCodeAt(i);\n      }\n      bytes = out;\n    }\n\n    const fmt = Computer.normalizeImageFormat(expectedFormat, \"png\");\n    if (fmt === \"png\") {\n      const pngMagic = new Uint8Array([\n        0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a,\n      ]);\n      for (let i = 0; i < pngMagic.length; i++) {\n        if (bytes[i] !== pngMagic[i]) {\n          throw new Error(\n            \"Screenshot data does not match expected format 'png'\"\n          );\n        }\n      }\n      if (String(mimeType).trim().toLowerCase() !== \"image/png\") {\n        throw new Error(\n          `Screenshot JSON mime_type does not match expected format: expected \"image/png\", got ${JSON.stringify(\n            mimeType\n          )}`\n        );\n      }\n      return {\n        bytes,\n        width,\n        height,\n        type: String(shotType).trim(),\n        mimeType: String(mimeType).trim(),\n      };\n    }\n    if (fmt === \"jpeg\") {\n      const jpgMagic = new Uint8Array([0xff, 0xd8, 0xff]);\n      for (let i = 0; i < jpgMagic.length; i++) {\n        if (bytes[i] !== jpgMagic[i]) {\n          throw new Error(\n            \"Screenshot data does not match expected format 'jpeg'\"\n          );\n        }\n      }\n      if (String(mimeType).trim().toLowerCase() !== \"image/jpeg\") {\n        throw new Error(\n          `Screenshot JSON mime_type does not match expected format: expected \"image/jpeg\", got ${JSON.stringify(\n            mimeType\n          )}`\n        );\n      }\n      return {\n        bytes,\n        width,\n        height,\n        type: String(shotType).trim(),\n        mimeType: String(mimeType).trim(),\n      };\n    }\n    throw new Error(`Unsupported format: ${JSON.stringify(expectedFormat)}`);\n  }\n\n  /**\n   * Click mouse at specified coordinates.\n   *\n   * @param x - X coordinate for the click\n   * @param y - Y coordinate for the click\n   * @param button - Mouse button to click (default: 'left'). Valid values: 'left', 'right', 'middle', 'double_left'\n   * @returns Promise resolving to result with success status\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: 'your_api_key' });\n   * const result = await agentBay.create({ imageId: 'windows_latest' });\n   * if (result.success) {\n   *   const clickResult = await result.session.computer.clickMouse(100, 100, 'left');\n   *   console.log('Clicked:', clickResult.success);\n   *   await result.session.delete();\n   * }\n   * ```\n   */\n  async clickMouse(\n    x: number,\n    y: number,\n    button: MouseButton | string = MouseButton.LEFT\n  ): Promise<OperationResult> {\n    const buttonStr = typeof button === \"string\" ? button : button;\n    const validButtons = Object.values(MouseButton);\n    if (!validButtons.includes(buttonStr as MouseButton)) {\n      throw new Error(\n        `Invalid button '${buttonStr}'. Must be one of ${validButtons.join(\n          \", \"\n        )}`\n      );\n    }\n\n    const args = { x, y, button: buttonStr };\n    try {\n      const result = await this.session.callMcpTool(\"click_mouse\", args, false);\n      return {\n        success: result.success || false,\n        requestId: result.requestId || \"\",\n        errorMessage: result.errorMessage || \"\",\n        data: result.success || false,\n      };\n    } catch (error) {\n      return {\n        success: false,\n        requestId: \"\",\n        errorMessage: `Failed to click mouse: ${\n          error instanceof Error ? error.message : String(error)\n        }`,\n        data: false,\n      };\n    }\n  }\n\n  /**\n   * Move mouse to specified coordinates.\n   *\n   * @param x - X coordinate to move to\n   * @param y - Y coordinate to move to\n   * @returns Promise resolving to result with success status\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: process.env.AGENTBAY_API_KEY });\n   * const result = await agentBay.create({ imageId: 'windows_latest' });\n   * if (result.success) {\n   *   await result.session.computer.moveMouse(300, 400);\n   *   const pos = await result.session.computer.getCursorPosition();\n   *   console.log(`Position: (${pos.x}, ${pos.y})`);\n   *   await result.session.delete();\n   * }\n   * ```\n   */\n  async moveMouse(x: number, y: number): Promise<OperationResult> {\n    const args = { x, y };\n    try {\n      const result = await this.session.callMcpTool(\"move_mouse\", args, false);\n      return {\n        success: result.success || false,\n        requestId: result.requestId || \"\",\n        errorMessage: result.errorMessage || \"\",\n        data: result.success || false,\n      };\n    } catch (error) {\n      return {\n        success: false,\n        requestId: \"\",\n        errorMessage: `Failed to move mouse: ${\n          error instanceof Error ? error.message : String(error)\n        }`,\n        data: false,\n      };\n    }\n  }\n\n  /**\n   * Drag mouse from one position to another.\n   *\n   * @param fromX - Starting X coordinate\n   * @param fromY - Starting Y coordinate\n   * @param toX - Ending X coordinate\n   * @param toY - Ending Y coordinate\n   * @param button - Mouse button to use for drag (default: 'left'). Valid values: 'left', 'right', 'middle'\n   * @returns Promise resolving to result with success status\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: process.env.AGENTBAY_API_KEY });\n   * const result = await agentBay.create({ imageId: 'windows_latest' });\n   * if (result.success) {\n   *   const dragResult = await result.session.computer.dragMouse(100, 100, 300, 300, 'left');\n   *   console.log('Dragged:', dragResult.success);\n   *   await result.session.delete();\n   * }\n   * ```\n   */\n  async dragMouse(\n    fromX: number,\n    fromY: number,\n    toX: number,\n    toY: number,\n    button: MouseButton | string = MouseButton.LEFT\n  ): Promise<OperationResult> {\n    const buttonStr = typeof button === \"string\" ? button : button;\n    const validButtons = [\n      MouseButton.LEFT,\n      MouseButton.RIGHT,\n      MouseButton.MIDDLE,\n    ];\n    if (!validButtons.includes(buttonStr as MouseButton)) {\n      throw new Error(\n        `Invalid button '${buttonStr}'. Must be one of ${validButtons.join(\n          \", \"\n        )}`\n      );\n    }\n\n    const args = {\n      from_x: fromX,\n      from_y: fromY,\n      to_x: toX,\n      to_y: toY,\n      button: buttonStr,\n    };\n    try {\n      const result = await this.session.callMcpTool(\"drag_mouse\", args, false);\n      return {\n        success: result.success || false,\n        requestId: result.requestId || \"\",\n        errorMessage: result.errorMessage || \"\",\n        data: result.success || false,\n      };\n    } catch (error) {\n      return {\n        success: false,\n        requestId: \"\",\n        errorMessage: `Failed to drag mouse: ${\n          error instanceof Error ? error.message : String(error)\n        }`,\n        data: false,\n      };\n    }\n  }\n\n  /**\n   * Scroll at specified coordinates.\n   *\n   * @param x - X coordinate to scroll at\n   * @param y - Y coordinate to scroll at\n   * @param direction - Scroll direction (default: 'up'). Valid values: 'up', 'down', 'left', 'right'\n   * @param amount - Scroll amount (default: 1)\n   * @returns Promise resolving to result with success status\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: process.env.AGENTBAY_API_KEY });\n   * const result = await agentBay.create({ imageId: 'windows_latest' });\n   * if (result.success) {\n   *   await result.session.computer.scroll(400, 300, 'up', 3);\n   *   await result.session.delete();\n   * }\n   * ```\n   */\n  async scroll(\n    x: number,\n    y: number,\n    direction: ScrollDirection | string = ScrollDirection.UP,\n    amount = 1\n  ): Promise<OperationResult> {\n    const directionStr = typeof direction === \"string\" ? direction : direction;\n    const validDirections = Object.values(ScrollDirection);\n    if (!validDirections.includes(directionStr as ScrollDirection)) {\n      throw new Error(\n        `Invalid direction '${directionStr}'. Must be one of ${validDirections.join(\n          \", \"\n        )}`\n      );\n    }\n\n    const args = { x, y, direction: directionStr, amount };\n    try {\n      const result = await this.session.callMcpTool(\"scroll\", args, false);\n      return {\n        success: result.success || false,\n        requestId: result.requestId || \"\",\n        errorMessage: result.errorMessage || \"\",\n        data: result.success || false,\n      };\n    } catch (error) {\n      return {\n        success: false,\n        requestId: \"\",\n        errorMessage: `Failed to scroll: ${\n          error instanceof Error ? error.message : String(error)\n        }`,\n        data: false,\n      };\n    }\n  }\n\n  /**\n   * Input text at the current cursor position.\n   *\n   * @param text - Text to input\n   * @returns Promise resolving to result with success status\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: process.env.AGENTBAY_API_KEY });\n   * const result = await agentBay.create({ imageId: 'windows_latest' });\n   * if (result.success) {\n   *   await result.session.computer.inputText('Hello AgentBay!');\n   *   await result.session.delete();\n   * }\n   * ```\n   */\n  async inputText(text: string): Promise<OperationResult> {\n    const args = { text };\n    try {\n      const result = await this.session.callMcpTool(\"input_text\", args, false);\n      return {\n        success: result.success || false,\n        requestId: result.requestId || \"\",\n        errorMessage: result.errorMessage || \"\",\n        data: result.success || false,\n      };\n    } catch (error) {\n      return {\n        success: false,\n        requestId: \"\",\n        errorMessage: `Failed to input text: ${\n          error instanceof Error ? error.message : String(error)\n        }`,\n        data: false,\n      };\n    }\n  }\n\n  /**\n   * Press one or more keys.\n   *\n   * @param keys - Array of key names to press\n   * @param hold - Whether to hold the keys down (default: false)\n   * @returns Promise resolving to result with success status\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: process.env.AGENTBAY_API_KEY });\n   * const result = await agentBay.create({ imageId: 'windows_latest' });\n   * if (result.success) {\n   *   await result.session.computer.pressKeys(['Ctrl', 'c'], true);\n   *   await result.session.computer.releaseKeys(['Ctrl', 'c']);\n   *   await result.session.delete();\n   * }\n   * ```\n   */\n  async pressKeys(keys: string[], hold = false): Promise<OperationResult> {\n    const args = { keys, hold };\n    try {\n      const result = await this.session.callMcpTool(\"press_keys\", args, false);\n      return {\n        success: result.success || false,\n        requestId: result.requestId || \"\",\n        errorMessage: result.errorMessage || \"\",\n        data: result.success || false,\n      };\n    } catch (error) {\n      return {\n        success: false,\n        requestId: \"\",\n        errorMessage: `Failed to press keys: ${\n          error instanceof Error ? error.message : String(error)\n        }`,\n        data: false,\n      };\n    }\n  }\n\n  /**\n   * Release previously pressed keys.\n   *\n   * @param keys - Array of key names to release\n   * @returns Promise resolving to result with success status\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: process.env.AGENTBAY_API_KEY });\n   * const result = await agentBay.create({ imageId: 'windows_latest' });\n   * if (result.success) {\n   *   await result.session.computer.pressKeys(['Ctrl'], true);\n   *   await result.session.computer.releaseKeys(['Ctrl']);\n   *   await result.session.delete();\n   * }\n   * ```\n   */\n  async releaseKeys(keys: string[]): Promise<OperationResult> {\n    const args = { keys };\n    try {\n      const result = await this.session.callMcpTool(\n        \"release_keys\",\n        args,\n        false\n      );\n      return {\n        success: result.success || false,\n        requestId: result.requestId || \"\",\n        errorMessage: result.errorMessage || \"\",\n        data: result.success || false,\n      };\n    } catch (error) {\n      return {\n        success: false,\n        requestId: \"\",\n        errorMessage: `Failed to release keys: ${\n          error instanceof Error ? error.message : String(error)\n        }`,\n        data: false,\n      };\n    }\n  }\n\n  /**\n   * Get cursor position.\n   *\n   * @returns Promise resolving to result containing cursor coordinates\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: process.env.AGENTBAY_API_KEY });\n   * const result = await agentBay.create({ imageId: 'windows_latest' });\n   * if (result.success) {\n   *   const pos = await result.session.computer.getCursorPosition();\n   *   console.log(`Cursor: (${pos.x}, ${pos.y})`);\n   *   await result.session.delete();\n   * }\n   * ```\n   */\n  async getCursorPosition(): Promise<CursorPosition> {\n    try {\n      const result = await this.session.callMcpTool(\n        \"get_cursor_position\",\n        {},\n        false\n      );\n\n      if (!result.success) {\n        return {\n          success: false,\n          requestId: result.requestId || \"\",\n          errorMessage: result.errorMessage || \"Failed to get cursor position\",\n          x: 0,\n          y: 0,\n        };\n      }\n\n      // Parse JSON response from data field (callMcpTool already extracts content[0].text to data)\n      const content = result.data;\n      if (!content) {\n        return {\n          success: false,\n          requestId: result.requestId || \"\",\n          errorMessage: \"No content in response\",\n          x: 0,\n          y: 0,\n        };\n      }\n\n      try {\n        const position = JSON.parse(content);\n        return {\n          success: true,\n          requestId: result.requestId || \"\",\n          errorMessage: \"\",\n          x: position.x || 0,\n          y: position.y || 0,\n        };\n      } catch (parseError) {\n        return {\n          success: false,\n          requestId: result.requestId || \"\",\n          errorMessage: `Failed to parse cursor position: ${parseError}`,\n          x: 0,\n          y: 0,\n        };\n      }\n    } catch (error) {\n      return {\n        success: false,\n        requestId: \"\",\n        errorMessage: `Failed to get cursor position: ${\n          error instanceof Error ? error.message : String(error)\n        }`,\n        x: 0,\n        y: 0,\n      };\n    }\n  }\n\n  /**\n   * Get screen size.\n   *\n   * @returns Promise resolving to result containing screen dimensions and DPI scaling\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: process.env.AGENTBAY_API_KEY });\n   * const result = await agentBay.create({ imageId: 'windows_latest' });\n   * if (result.success) {\n   *   const size = await result.session.computer.getScreenSize();\n   *   console.log(`Screen: ${size.width}x${size.height}`);\n   *   await result.session.delete();\n   * }\n   * ```\n   */\n  async getScreenSize(): Promise<ScreenSize> {\n    try {\n      const result = await this.session.callMcpTool(\n        \"get_screen_size\",\n        {},\n        false\n      );\n\n      if (!result.success) {\n        return {\n          success: false,\n          requestId: result.requestId || \"\",\n          errorMessage: result.errorMessage || \"Failed to get screen size\",\n          width: 0,\n          height: 0,\n          dpiScalingFactor: 1.0,\n        };\n      }\n\n      // Parse JSON response from data field (callMcpTool already extracts content[0].text to data)\n      const content = result.data;\n      if (!content) {\n        return {\n          success: false,\n          requestId: result.requestId || \"\",\n          errorMessage: \"No content in response\",\n          width: 0,\n          height: 0,\n          dpiScalingFactor: 1.0,\n        };\n      }\n\n      try {\n        const screenInfo = JSON.parse(content);\n        return {\n          success: true,\n          requestId: result.requestId || \"\",\n          errorMessage: \"\",\n          width: screenInfo.width || 0,\n          height: screenInfo.height || 0,\n          dpiScalingFactor: screenInfo.dpiScalingFactor || 1.0,\n        };\n      } catch (parseError) {\n        return {\n          success: false,\n          requestId: result.requestId || \"\",\n          errorMessage: `Failed to parse screen size: ${parseError}`,\n          width: 0,\n          height: 0,\n          dpiScalingFactor: 1.0,\n        };\n      }\n    } catch (error) {\n      return {\n        success: false,\n        requestId: \"\",\n        errorMessage: `Failed to get screen size: ${\n          error instanceof Error ? error.message : String(error)\n        }`,\n        width: 0,\n        height: 0,\n        dpiScalingFactor: 1.0,\n      };\n    }\n  }\n\n  /**\n   * Take a screenshot.\n   *\n   * @returns Promise resolving to result containing screenshot URL\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: process.env.AGENTBAY_API_KEY });\n   * const result = await agentBay.create({ imageId: 'windows_latest' });\n   * if (result.success) {\n   *   const screenshot = await result.session.computer.screenshot();\n   *   console.log('Screenshot URL:', screenshot.data);\n   *   await result.session.delete();\n   * }\n   * ```\n   */\n  async screenshot(): Promise<ScreenshotResult> {\n    if (this.session.linkUrl) {\n      return {\n        success: false,\n        requestId: \"\",\n        errorMessage:\n          \"This cloud environment does not support `screenshot()`. Please use `beta_take_screenshot()` instead.\",\n        data: \"\",\n      };\n    }\n    try {\n      const result = await this.session.callMcpTool(\n        \"system_screenshot\",\n        {},\n        false\n      );\n      if (!result.success) {\n        return {\n          success: false,\n          requestId: result.requestId || \"\",\n          errorMessage: result.errorMessage || \"Failed to take screenshot\",\n          data: \"\",\n        };\n      }\n      if (!result.data) {\n        return {\n          success: false,\n          requestId: result.requestId || \"\",\n          errorMessage: result.errorMessage || \"Failed to take screenshot\",\n          data: \"\",\n        };\n      }\n      const screenshotUrl = result.data || \"\";\n      return {\n        success: true,\n        requestId: result.requestId || \"\",\n        errorMessage: \"\",\n        data: screenshotUrl,\n      };\n    } catch (error) {\n      return {\n        success: false,\n        requestId: \"\",\n        errorMessage: `Failed to take screenshot: ${\n          error instanceof Error ? error.message : String(error)\n        }`,\n        data: \"\",\n      };\n    }\n  }\n\n  /**\n   * Capture the current screen and return raw image bytes (beta).\n   *\n   * This API uses the MCP tool `screenshot` (wuying_capture) and expects the backend to return\n   * a JSON string with top-level field `data` containing base64.\n   *\n   * @param format - Output image format (\"png\", \"jpeg\", or \"jpg\"). Default is \"png\"\n   */\n  async betaTakeScreenshot(format = \"png\"): Promise<BetaScreenshotResult> {\n    const fmt = Computer.normalizeImageFormat(format, \"png\");\n    if (!this.session.linkUrl) {\n      return {\n        success: false,\n        requestId: \"\",\n        errorMessage:\n          \"This cloud environment does not support `beta_take_screenshot()`. Please use `screenshot()` instead.\",\n        data: new Uint8Array(),\n        type: \"\",\n        mimeType: \"\",\n      };\n    }\n    if (fmt !== \"png\" && fmt !== \"jpeg\") {\n      return {\n        success: false,\n        requestId: \"\",\n        errorMessage: `Unsupported format: ${JSON.stringify(\n          format\n        )}. Supported values: \"png\", \"jpeg\".`,\n        data: new Uint8Array(),\n        type: \"\",\n        mimeType: \"\",\n      };\n    }\n\n    try {\n      const result = await this.session.callMcpTool(\n        \"screenshot\",\n        { format: fmt },\n        false\n      );\n      const requestId = result.requestId || \"\";\n      if (!result.success) {\n        return {\n          success: false,\n          requestId,\n          errorMessage: result.errorMessage || \"Failed to take screenshot\",\n          data: new Uint8Array(),\n          type: \"\",\n          mimeType: \"\",\n        };\n      }\n      const decoded = Computer.decodeScreenshotJsonStrict(\n        String(result.data || \"\"),\n        fmt\n      );\n      return {\n        success: true,\n        requestId,\n        errorMessage: \"\",\n        data: decoded.bytes,\n        type: decoded.type,\n        mimeType: decoded.mimeType,\n        width: decoded.width,\n        height: decoded.height,\n      };\n    } catch (error) {\n      return {\n        success: false,\n        requestId: \"\",\n        errorMessage: `Failed to take screenshot: ${\n          error instanceof Error ? error.message : String(error)\n        }`,\n        data: new Uint8Array(),\n        type: \"\",\n        mimeType: \"\",\n      };\n    }\n  }\n\n  /**\n   * Lists all root windows.\n   *\n   * @param timeoutMs - Timeout in milliseconds (default: 3000)\n   * @returns Promise resolving to result containing array of root windows\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: process.env.AGENTBAY_API_KEY });\n   * const result = await agentBay.create({ imageId: 'windows_latest' });\n   * if (result.success) {\n   *   const windows = await result.session.computer.listRootWindows();\n   *   console.log(`Found ${windows.windows.length} windows`);\n   *   await result.session.delete();\n   * }\n   * ```\n   */\n  async listRootWindows(timeoutMs = 3000): Promise<WindowListResult> {\n    try {\n      const args = { timeout_ms: timeoutMs };\n      const response = await this.session.callMcpTool(\n        \"list_root_windows\",\n        args,\n        false\n      );\n\n      if (!response.success) {\n        return {\n          requestId: response.requestId,\n          success: false,\n          windows: [],\n          errorMessage: response.errorMessage,\n        };\n      }\n\n      const rawWindows = response.data ? JSON.parse(response.data) : [];\n      const windows = convertWindowData(rawWindows);\n      return {\n        requestId: response.requestId,\n        success: true,\n        windows,\n      };\n    } catch (error) {\n      return {\n        requestId: \"\",\n        success: false,\n        windows: [],\n        errorMessage: `Failed to list root windows: ${error}`,\n      };\n    }\n  }\n\n  /**\n   * Gets the currently active window.\n   *\n   * @param timeoutMs - Timeout in milliseconds (default: 3000)\n   * @returns Promise resolving to result containing active window information\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: process.env.AGENTBAY_API_KEY });\n   * const result = await agentBay.create({ imageId: 'windows_latest' });\n   * if (result.success) {\n   *   const activeWindow = await result.session.computer.getActiveWindow();\n   *   console.log(`Active: ${activeWindow.window?.title}`);\n   *   await result.session.delete();\n   * }\n   * ```\n   */\n  async getActiveWindow(): Promise<WindowInfoResult> {\n    try {\n      const args = {};\n      const response = await this.session.callMcpTool(\n        \"get_active_window\",\n        args,\n        false\n      );\n\n      if (!response.success) {\n        return {\n          requestId: response.requestId,\n          success: false,\n          window: [],\n          errorMessage: response.errorMessage,\n        };\n      }\n\n      const rawWindow = response.data ? JSON.parse(response.data) : null;\n      // Convert snake_case fields to camelCase to match Go SDK behavior\n      const window = convertWindowData(rawWindow);\n      return {\n        requestId: response.requestId,\n        success: true,\n        window,\n      };\n    } catch (error) {\n      return {\n        requestId: \"\",\n        success: false,\n        window: [],\n        errorMessage: `Failed to get active window: ${error}`,\n      };\n    }\n  }\n\n  /**\n   * Activates the specified window.\n   *\n   * @param windowId - ID of the window to activate\n   * @returns Promise resolving to result with success status\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: 'your_api_key' });\n   * const result = await agentBay.create({ imageId: 'windows_latest' });\n   * if (result.success) {\n   *   const windows = await result.session.computer.listRootWindows();\n   *   await result.session.computer.activateWindow(windows.windows[0].id);\n   *   await result.session.delete();\n   * }\n   * ```\n   */\n  async activateWindow(windowId: number): Promise<WindowBoolResult> {\n    try {\n      const args = { window_id: windowId };\n      const response = await this.session.callMcpTool(\n        \"activate_window\",\n        args,\n        false\n      );\n\n      return {\n        requestId: response.requestId,\n        success: response.success,\n        errorMessage: response.errorMessage || \"\",\n      };\n    } catch (error) {\n      return {\n        requestId: \"\",\n        success: false,\n        errorMessage: `Failed to activate window: ${error}`,\n      };\n    }\n  }\n\n  /**\n   * Closes the specified window.\n   *\n   * @param windowId - ID of the window to close\n   * @returns Promise resolving to result with success status\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: process.env.AGENTBAY_API_KEY });\n   * const result = await agentBay.create({ imageId: 'windows_latest' });\n   * if (result.success) {\n   *   await result.session.computer.startApp('notepad.exe');\n   *   const win = await result.session.computer.getActiveWindow();\n   *   await result.session.computer.closeWindow(win.window!.id);\n   *   await result.session.delete();\n   * }\n   * ```\n   */\n  async closeWindow(windowId: number): Promise<WindowBoolResult> {\n    try {\n      const args = { window_id: windowId };\n      const response = await this.session.callMcpTool(\n        \"close_window\",\n        args,\n        false\n      );\n\n      return {\n        requestId: response.requestId,\n        success: response.success,\n        errorMessage: response.errorMessage || \"\",\n      };\n    } catch (error) {\n      return {\n        requestId: \"\",\n        success: false,\n        errorMessage: `Failed to close window: ${error}`,\n      };\n    }\n  }\n\n  /**\n   * Maximizes the specified window.\n   *\n   * @param windowId - ID of the window to maximize\n   * @returns Promise resolving to result with success status\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: process.env.AGENTBAY_API_KEY });\n   * const result = await agentBay.create({ imageId: 'windows_latest' });\n   * if (result.success) {\n   *   await result.session.computer.startApp('notepad.exe');\n   *   const win = await result.session.computer.getActiveWindow();\n   *   await result.session.computer.maximizeWindow(win.window!.id);\n   *   await result.session.delete();\n   * }\n   * ```\n   */\n  async maximizeWindow(windowId: number): Promise<WindowBoolResult> {\n    try {\n      const args = { window_id: windowId };\n      const response = await this.session.callMcpTool(\n        \"maximize_window\",\n        args,\n        false\n      );\n\n      return {\n        requestId: response.requestId,\n        success: response.success,\n        errorMessage: response.errorMessage || \"\",\n      };\n    } catch (error) {\n      return {\n        requestId: \"\",\n        success: false,\n        errorMessage: `Failed to maximize window: ${error}`,\n      };\n    }\n  }\n\n  /**\n   * Minimizes the specified window.\n   *\n   * @param windowId - ID of the window to minimize\n   * @returns Promise resolving to result with success status\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: process.env.AGENTBAY_API_KEY });\n   * const result = await agentBay.create({ imageId: 'windows_latest' });\n   * if (result.success) {\n   *   await result.session.computer.startApp('notepad.exe');\n   *   const win = await result.session.computer.getActiveWindow();\n   *   await result.session.computer.minimizeWindow(win.window!.id);\n   *   await result.session.delete();\n   * }\n   * ```\n   */\n  async minimizeWindow(windowId: number): Promise<WindowBoolResult> {\n    try {\n      const args = { window_id: windowId };\n      const response = await this.session.callMcpTool(\n        \"minimize_window\",\n        args,\n        false\n      );\n\n      return {\n        requestId: response.requestId,\n        success: response.success,\n        errorMessage: response.errorMessage || \"\",\n      };\n    } catch (error) {\n      return {\n        requestId: \"\",\n        success: false,\n        errorMessage: `Failed to minimize window: ${error}`,\n      };\n    }\n  }\n\n  /**\n   * Restores the specified window.\n   *\n   * @param windowId - ID of the window to restore\n   * @returns Promise resolving to result with success status\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: process.env.AGENTBAY_API_KEY });\n   * const result = await agentBay.create({ imageId: 'windows_latest' });\n   * if (result.success) {\n   *   await result.session.computer.startApp('notepad.exe');\n   *   const win = await result.session.computer.getActiveWindow();\n   *   await result.session.computer.minimizeWindow(win.window!.id);\n   *   await result.session.computer.restoreWindow(win.window!.id);\n   *   await result.session.delete();\n   * }\n   * ```\n   */\n  async restoreWindow(windowId: number): Promise<WindowBoolResult> {\n    try {\n      const args = { window_id: windowId };\n      const response = await this.session.callMcpTool(\n        \"restore_window\",\n        args,\n        false\n      );\n\n      return {\n        requestId: response.requestId,\n        success: response.success,\n        errorMessage: response.errorMessage || \"\",\n      };\n    } catch (error) {\n      return {\n        requestId: \"\",\n        success: false,\n        errorMessage: `Failed to restore window: ${error}`,\n      };\n    }\n  }\n\n  /**\n   * Resizes the specified window.\n   *\n   * @param windowId - ID of the window to resize\n   * @param width - New width of the window\n   * @param height - New height of the window\n   * @returns Promise resolving to result with success status\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: process.env.AGENTBAY_API_KEY });\n   * const result = await agentBay.create({ imageId: 'windows_latest' });\n   * if (result.success) {\n   *   await result.session.computer.startApp('notepad.exe');\n   *   const win = await result.session.computer.getActiveWindow();\n   *   await result.session.computer.resizeWindow(win.window!.id, 800, 600);\n   *   await result.session.delete();\n   * }\n   * ```\n   */\n  async resizeWindow(\n    windowId: number,\n    width: number,\n    height: number\n  ): Promise<WindowBoolResult> {\n    try {\n      const args = { window_id: windowId, width, height };\n      const response = await this.session.callMcpTool(\n        \"resize_window\",\n        args,\n        false\n      );\n\n      return {\n        requestId: response.requestId,\n        success: response.success,\n        errorMessage: response.errorMessage || \"\",\n      };\n    } catch (error) {\n      return {\n        requestId: \"\",\n        success: false,\n        errorMessage: `Failed to resize window: ${error}`,\n      };\n    }\n  }\n\n  /**\n   * Makes the specified window fullscreen.\n   *\n   * @param windowId - ID of the window to make fullscreen\n   * @returns Promise resolving to result with success status\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: process.env.AGENTBAY_API_KEY });\n   * const result = await agentBay.create({ imageId: 'windows_latest' });\n   * if (result.success) {\n   *   await result.session.computer.startApp('notepad.exe');\n   *   const win = await result.session.computer.getActiveWindow();\n   *   await result.session.computer.fullscreenWindow(win.window!.id);\n   *   await result.session.delete();\n   * }\n   * ```\n   */\n  async fullscreenWindow(windowId: number): Promise<WindowBoolResult> {\n    try {\n      const args = { window_id: windowId };\n      const response = await this.session.callMcpTool(\n        \"fullscreen_window\",\n        args,\n        false\n      );\n\n      return {\n        requestId: response.requestId,\n        success: response.success,\n        errorMessage: response.errorMessage || \"\",\n      };\n    } catch (error) {\n      return {\n        requestId: \"\",\n        success: false,\n        errorMessage: `Failed to make window fullscreen: ${error}`,\n      };\n    }\n  }\n\n  /**\n   * Toggles focus mode on or off.\n   *\n   * @param on - Whether to enable (true) or disable (false) focus mode\n   * @returns Promise resolving to result with success status\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: process.env.AGENTBAY_API_KEY });\n   * const result = await agentBay.create({ imageId: 'windows_latest' });\n   * if (result.success) {\n   *   await result.session.computer.focusMode(true);\n   *   await result.session.computer.focusMode(false);\n   *   await result.session.delete();\n   * }\n   * ```\n   */\n  async focusMode(on: boolean): Promise<WindowBoolResult> {\n    try {\n      const args = { on };\n      const response = await this.session.callMcpTool(\n        \"focus_mode\",\n        args,\n        false\n      );\n\n      return {\n        requestId: response.requestId,\n        success: response.success,\n        errorMessage: response.errorMessage || \"\",\n      };\n    } catch (error) {\n      return {\n        requestId: \"\",\n        success: false,\n        errorMessage: `Failed to toggle focus mode: ${error}`,\n      };\n    }\n  }\n\n  // Application Management Operations\n\n  /**\n   * Gets the list of installed applications.\n   *\n   * @param startMenu - Whether to include applications from start menu (default: true)\n   * @param desktop - Whether to include applications from desktop (default: false)\n   * @param ignoreSystemApps - Whether to exclude system applications (default: true)\n   * @returns Promise resolving to result containing array of installed applications\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: 'your_api_key' });\n   * const result = await agentBay.create({ imageId: 'windows_latest' });\n   * if (result.success) {\n   *   const apps = await result.session.computer.getInstalledApps();\n   *   console.log(`Found ${apps.data.length} apps`);\n   *   await result.session.delete();\n   * }\n   * ```\n   */\n  async getInstalledApps(\n    startMenu = true,\n    desktop = false,\n    ignoreSystemApps = true\n  ): Promise<InstalledAppListResult> {\n    try {\n      const args = {\n        start_menu: startMenu,\n        desktop,\n        ignore_system_app: ignoreSystemApps,\n      };\n\n      const response = await this.session.callMcpTool(\n        \"get_installed_apps\",\n        args,\n        false\n      );\n\n      if (!response.success) {\n        return {\n          requestId: response.requestId,\n          success: false,\n          data: [],\n          errorMessage: response.errorMessage,\n        };\n      }\n\n      const rawApps = response.data ? JSON.parse(response.data) : [];\n      const apps = convertObjectKeys(rawApps);\n      return {\n        requestId: response.requestId,\n        success: true,\n        data: apps,\n      };\n    } catch (error) {\n      return {\n        requestId: \"\",\n        success: false,\n        data: [],\n        errorMessage: `Failed to get installed apps: ${error}`,\n      };\n    }\n  }\n\n  /**\n   * Starts the specified application.\n   *\n   * @param startCmd - The command to start the application (e.g., 'notepad.exe', 'calculator:')\n   * @param workDirectory - The working directory for the application (optional)\n   * @param activity - The activity parameter (optional, primarily for mobile use)\n   * @returns Promise resolving to result containing array of started processes\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: 'your_api_key' });\n   * const result = await agentBay.create({ imageId: 'windows_latest' });\n   * if (result.success) {\n   *   const startResult = await result.session.computer.startApp('notepad.exe');\n   *   console.log(`Started ${startResult.data.length} process(es)`);\n   *   await result.session.delete();\n   * }\n   * ```\n   */\n  async startApp(\n    startCmd: string,\n    workDirectory = \"\",\n    activity = \"\"\n  ): Promise<ProcessListResult> {\n    try {\n      const args: Record<string, string> = { start_cmd: startCmd };\n      if (workDirectory) args.work_directory = workDirectory;\n      if (activity) args.activity = activity;\n\n      const response = await this.session.callMcpTool(\"start_app\", args, false);\n\n      if (!response.success) {\n        return {\n          requestId: response.requestId,\n          success: false,\n          data: [],\n          errorMessage: response.errorMessage,\n        };\n      }\n\n      const rawProcesses = response.data ? JSON.parse(response.data) : [];\n      const processes = convertObjectKeys(rawProcesses);\n      return {\n        requestId: response.requestId,\n        success: true,\n        data: processes,\n      };\n    } catch (error) {\n      return {\n        requestId: \"\",\n        success: false,\n        data: [],\n        errorMessage: `Failed to start app: ${error}`,\n      };\n    }\n  }\n\n  /**\n   * Stops an application by process name.\n   *\n   * @param pname - The process name to stop (e.g., 'notepad.exe', 'chrome.exe')\n   * @returns Promise resolving to result with success status\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: 'your_api_key' });\n   * const result = await agentBay.create({ imageId: 'windows_latest' });\n   * if (result.success) {\n   *   await result.session.computer.startApp('notepad.exe');\n   *   await result.session.computer.stopAppByPName('notepad.exe');\n   *   await result.session.delete();\n   * }\n   * ```\n   */\n  async stopAppByPName(pname: string): Promise<WindowBoolResult> {\n    try {\n      const args = { pname };\n      const response = await this.session.callMcpTool(\n        \"stop_app_by_pname\",\n        args,\n        false\n      );\n\n      return {\n        requestId: response.requestId,\n        success: response.success,\n        errorMessage: response.errorMessage || \"\",\n      };\n    } catch (error) {\n      return {\n        requestId: \"\",\n        success: false,\n        errorMessage: `Failed to stop app by pname: ${error}`,\n      };\n    }\n  }\n\n  /**\n   * Stops an application by process ID.\n   *\n   * @param pid - The process ID to stop\n   * @returns Promise resolving to result with success status\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: 'your_api_key' });\n   * const result = await agentBay.create({ imageId: 'windows_latest' });\n   * if (result.success) {\n   *   const startResult = await result.session.computer.startApp('notepad.exe');\n   *   const pid = startResult.data[0].pid;\n   *   await result.session.computer.stopAppByPID(pid);\n   *   await result.session.delete();\n   * }\n   * ```\n   */\n  async stopAppByPID(pid: number): Promise<WindowBoolResult> {\n    try {\n      const args = { pid };\n      const response = await this.session.callMcpTool(\n        \"stop_app_by_pid\",\n        args,\n        false\n      );\n\n      return {\n        requestId: response.requestId,\n        success: response.success,\n        errorMessage: response.errorMessage || \"\",\n      };\n    } catch (error) {\n      return {\n        requestId: \"\",\n        success: false,\n        errorMessage: `Failed to stop app by pid: ${error}`,\n      };\n    }\n  }\n\n  /**\n   * Stops an application by stop command.\n   *\n   * @param cmd - The command to stop the application\n   * @returns Promise resolving to result with success status\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: 'your_api_key' });\n   * const result = await agentBay.create({ imageId: 'windows_latest' });\n   * if (result.success) {\n   *   await result.session.computer.startApp('notepad.exe');\n   *   await result.session.computer.stopAppByCmd('taskkill /IM notepad.exe /F');\n   *   await result.session.delete();\n   * }\n   * ```\n   */\n  async stopAppByCmd(cmd: string): Promise<WindowBoolResult> {\n    try {\n      const args = { stop_cmd: cmd };\n      const response = await this.session.callMcpTool(\n        \"stop_app_by_cmd\",\n        args,\n        false\n      );\n\n      return {\n        requestId: response.requestId,\n        success: response.success,\n        errorMessage: response.errorMessage || \"\",\n      };\n    } catch (error) {\n      return {\n        requestId: \"\",\n        success: false,\n        errorMessage: `Failed to stop app by cmd: ${error}`,\n      };\n    }\n  }\n\n  /**\n   * Lists all visible applications.\n   *\n   * @returns Promise resolving to result containing array of visible application processes\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: 'your_api_key' });\n   * const result = await agentBay.create({ imageId: 'windows_latest' });\n   * if (result.success) {\n   *   const apps = await result.session.computer.listVisibleApps();\n   *   console.log(`Found ${apps.data.length} visible apps`);\n   *   await result.session.delete();\n   * }\n   * ```\n   */\n  async listVisibleApps(): Promise<ProcessListResult> {\n    try {\n      const response = await this.session.callMcpTool(\n        \"list_visible_apps\",\n        {},\n        false\n      );\n\n      if (!response.success) {\n        return {\n          requestId: response.requestId,\n          success: false,\n          data: [],\n          errorMessage: response.errorMessage,\n        };\n      }\n\n      const rawProcesses = response.data ? JSON.parse(response.data) : [];\n      const processes = convertObjectKeys(rawProcesses);\n      return {\n        requestId: response.requestId,\n        success: true,\n        data: processes,\n      };\n    } catch (error) {\n      return {\n        requestId: \"\",\n        success: false,\n        data: [],\n        errorMessage: `Failed to list visible apps: ${error}`,\n      };\n    }\n  }\n}\n","/**\n * Utility functions for converting field names between different naming conventions\n */\n\n/**\n * Converts a snake_case string to camelCase\n * @param str - The snake_case string to convert\n * @returns The camelCase version of the string\n *\n * @example\n * ```typescript\n * snakeToCamel('window_id') // returns 'windowId'\n * snakeToCamel('user_name') // returns 'userName'\n * snakeToCamel('simple') // returns 'simple'\n * ```\n */\nexport function snakeToCamel(str: string): string {\n  return str.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase());\n}\n\n/**\n * Converts an object with snake_case keys to camelCase keys\n * @param obj - The object to convert\n * @returns A new object with camelCase keys\n *\n * @example\n * ```typescript\n * const input = { window_id: 123, user_name: 'John', age: 30 };\n * const output = convertObjectKeys(input);\n * // output: { windowId: 123, userName: 'John', age: 30 }\n * ```\n */\nexport function convertObjectKeys<T = any>(obj: any): T {\n  if (obj === null || obj === undefined) {\n    return obj;\n  }\n\n  if (Array.isArray(obj)) {\n    return obj.map((item) => convertObjectKeys(item)) as T;\n  }\n\n  if (typeof obj === \"object\" && obj.constructor === Object) {\n    const converted: any = {};\n    for (const [key, value] of Object.entries(obj)) {\n      const camelKey = snakeToCamel(key);\n      converted[camelKey] = convertObjectKeys(value);\n    }\n    return converted as T;\n  }\n\n  return obj;\n}\n\n/**\n * Converts window data from backend snake_case format to frontend camelCase format\n * @param rawWindow - Raw window data from backend\n * @returns Converted window data with camelCase keys\n *\n * @example\n * ```typescript\n * const raw = { window_id: 123, title: 'Calculator', pid: 456, pname: 'calc.exe' };\n * const converted = convertWindowData(raw);\n * // converted: { windowId: 123, title: 'Calculator', pid: 456, pname: 'calc.exe' }\n * ```\n */\nexport function convertWindowData(rawWindow: any): any {\n  if (!rawWindow) return rawWindow;\n\n  const converted = convertObjectKeys(rawWindow);\n  if (converted && converted.windowTitle !== undefined) {\n    converted.title = converted.windowTitle;\n  }\n  return converted;\n}\n\n/**\n * Converts an array of window data from backend format to frontend format\n * @param rawWindows - Array of raw window data from backend\n * @returns Array of converted window data with camelCase keys\n *\n * @example\n * ```typescript\n * const rawList = [\n *   { window_id: 123, title: 'Calculator' },\n *   { window_id: 456, title: 'Notepad' }\n * ];\n * const converted = convertWindowList(rawList);\n * // converted: [\n * //   { windowId: 123, title: 'Calculator' },\n * //   { windowId: 456, title: 'Notepad' }\n * // ]\n * ```\n */\nexport function convertWindowList(rawWindows: any[]): any[] {\n  if (!Array.isArray(rawWindows)) return [];\n\n  return rawWindows.map((window) => convertWindowData(window));\n}\n","import { Session } from \"../session\";\n\nexport interface EnvResult {\n  requestId: string;\n  success: boolean;\n  envs: Record<string, string>;\n  errorMessage?: string;\n}\n\nexport interface BoolResult {\n  requestId: string;\n  success: boolean;\n  errorMessage?: string;\n}\n\nconst ENV_SERVER = \"wuying_system\";\nconst ENV_TOOLS = [\"set_env\", \"get_env\"];\n\nexport class Env {\n  private session: Session;\n\n  private toolsRegistered = false;\n\n  constructor(session: Session) {\n    this.session = session;\n  }\n\n  /**\n   * Pre-started sandbox instances may not include env tools in their initial\n   * ToolList. Register them so the SDK can route through LinkUrl.\n   */\n  private ensureEnvToolsRegistered(): void {\n    if (this.toolsRegistered) return;\n    this.toolsRegistered = true;\n    for (const toolName of ENV_TOOLS) {\n      if (!this.session.getMcpServerForTool(toolName)) {\n        this.session.mcpTools.push({\n          name: toolName,\n          server: ENV_SERVER,\n          description: \"\",\n          inputSchema: {},\n          tool: toolName,\n        });\n      }\n    }\n  }\n\n  async set(envs: Record<string, string>): Promise<BoolResult> {\n    this.ensureEnvToolsRegistered();\n    if (!envs || Object.keys(envs).length === 0) {\n      throw new Error(\"envs must not be empty\");\n    }\n    for (const [key, value] of Object.entries(envs)) {\n      if (typeof key !== \"string\") {\n        throw new Error(`Key must be string, got ${typeof key}`);\n      }\n      if (typeof value !== \"string\") {\n        throw new Error(\n          `Value for key '${key}' must be string, got ${typeof value}`\n        );\n      }\n    }\n\n    const envsArray = Object.entries(envs).map(([key, value]) => ({\n      key,\n      value,\n    }));\n    try {\n      const result = await this.session.callMcpTool(\n        \"set_env\",\n        { envs: envsArray },\n        false\n      );\n      return {\n        requestId: result.requestId,\n        success: result.success,\n        errorMessage: result.errorMessage || undefined,\n      };\n    } catch (error) {\n      return {\n        requestId: \"\",\n        success: false,\n        errorMessage: `Failed to set environment variables: ${error}`,\n      };\n    }\n  }\n\n  async get(keys?: string[]): Promise<EnvResult> {\n    this.ensureEnvToolsRegistered();\n    const args: Record<string, unknown> = {};\n    if (keys && keys.length > 0) {\n      args.keys = keys;\n    }\n    try {\n      const result = await this.session.callMcpTool(\"get_env\", args, false);\n      let envs: Record<string, string> = {};\n      if (result.success && result.data) {\n        try {\n          const parsed =\n            typeof result.data === \"string\"\n              ? JSON.parse(result.data)\n              : result.data;\n          if (parsed && typeof parsed === \"object\") {\n            envs = parsed as Record<string, string>;\n          }\n        } catch {\n          // leave envs empty if payload is not valid JSON\n        }\n      }\n      return {\n        requestId: result.requestId,\n        success: result.success,\n        envs,\n        errorMessage: result.errorMessage || undefined,\n      };\n    } catch (error) {\n      return {\n        requestId: \"\",\n        success: false,\n        envs: {},\n        errorMessage: `Failed to get environment variables: ${error}`,\n      };\n    }\n  }\n}\n","import { Client } from \"./api/client\";\nimport {\n  GetContextInfoRequest,\n  SyncContextRequest,\n  BindContextsRequest,\n  BindContextsRequestPersistenceDataList,\n  BindContextsRequestPersistenceDataListMountConfig,\n  DescribeSessionContextsRequest,\n} from \"./api/models/model\";\nimport {\n  ApiResponse,\n  ContextBinding,\n  ContextBindResult,\n  ContextBindingsResult,\n  extractRequestId,\n} from \"./types/api-response\";\nimport { ContextSync } from \"./context-sync\";\nimport { BetaContextMount } from \"./beta-context-mount\";\nimport {\n  log,\n  logError,\n  logInfo,\n  logDebug,\n  logAPICall,\n  logAPIResponseWithDetails,\n  setRequestId,\n  getRequestId,\n} from \"./utils/logger\";\n\nexport interface ContextStatusData {\n  contextId: string;\n  path: string;\n  errorMessage: string;\n  status: string;\n  startTime: number;\n  finishTime: number;\n  taskType: string;\n}\n\nexport interface ContextStatusItem {\n  type: string;\n  data: string;\n}\n\nexport interface ContextInfoResult extends ApiResponse {\n  success?: boolean;\n  contextStatusData: ContextStatusData[];\n  errorMessage?: string;\n}\n\nexport interface ContextSyncResult extends ApiResponse {\n  success: boolean;\n  errorMessage?: string;\n}\n\nexport type SyncCallback = (success: boolean) => void;\n\nexport interface SessionInterface {\n  getAPIKey(): string;\n  getClient(): Client;\n  getSessionId(): string;\n}\n\nexport class ContextManager {\n  private session: SessionInterface;\n\n  constructor(session: SessionInterface) {\n    this.session = session;\n  }\n\n  /**\n   * Gets information about context synchronization status for the current session.\n   *\n   * @returns Promise resolving to ContextInfoResult containing context status data and request ID\n   * @throws Error if the API call fails\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: 'your_api_key' });\n   * const result = await agentBay.create();\n   * if (result.success) {\n   *   const info = await result.session.context.info();\n   *   console.log(`Context count: ${info.contextStatusData.length}`);\n   *   await result.session.delete();\n   * }\n   * ```\n   */\n  async info(): Promise<ContextInfoResult> {\n    return this.infoWithParams();\n  }\n\n  /**\n   * Gets information about context synchronization status with optional filter parameters.\n   *\n   * @param contextId - Optional context ID to filter results\n   * @param path - Optional path to filter results\n   * @param taskType - Optional task type to filter results (e.g., \"upload\", \"download\")\n   * @returns Promise resolving to ContextInfoResult containing filtered context status data and request ID\n   * @throws Error if the API call fails\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: 'your_api_key' });\n   * const result = await agentBay.create();\n   * if (result.success) {\n   *   const info = await result.session.context.infoWithParams('SdkCtx-xxx', '/mnt/persistent');\n   *   console.log(`Context status: ${info.contextStatusData[0]?.status}`);\n   *   await result.session.delete();\n   * }\n   * ```\n   */\n  async infoWithParams(\n    contextId?: string,\n    path?: string,\n    taskType?: string\n  ): Promise<ContextInfoResult> {\n    const request = new GetContextInfoRequest({\n      authorization: `Bearer ${this.session.getAPIKey()}`,\n      sessionId: this.session.getSessionId(),\n    });\n\n    // Set optional parameters if provided\n    if (contextId) {\n      request.contextId = contextId;\n    }\n    if (path) {\n      request.path = path;\n    }\n    if (taskType) {\n      request.taskType = taskType;\n    }\n\n    // Log API request (matching Go version format)\n    logAPICall(\"GetContextInfo\");\n    let requestLog = `Request: SessionId=${request.sessionId}`;\n    if (request.contextId) {\n      requestLog += `, ContextId=${request.contextId}`;\n    }\n    if (request.path) {\n      requestLog += `, Path=${request.path}`;\n    }\n    if (request.taskType) {\n      requestLog += `, TaskType=${request.taskType}`;\n    }\n    logDebug(requestLog);\n\n    try {\n      const response = await this.session.getClient().getContextInfo(request);\n\n      // Extract RequestID\n      const requestId = extractRequestId(response) || \"\";\n\n      // Check for API-level errors\n      if (response?.body?.success === false && response.body.code) {\n        const errorMsg = `[${response.body.code}] ${\n          response.body.message || \"Unknown error\"\n        }`;\n        const fullResponse = response.body\n          ? JSON.stringify(response.body, null, 2)\n          : \"\";\n        logAPIResponseWithDetails(\n          \"GetContextInfo\",\n          requestId,\n          false,\n          undefined,\n          fullResponse\n        );\n        return {\n          requestId,\n          success: false,\n          contextStatusData: [],\n          errorMessage: errorMsg,\n        };\n      }\n\n      // Parse the context status data\n      const contextStatusData: ContextStatusData[] = [];\n      if (response?.body?.data?.contextStatus) {\n        try {\n          // First, parse the outer array\n          const contextStatusStr = response.body.data.contextStatus;\n          const statusItems: ContextStatusItem[] = JSON.parse(contextStatusStr);\n\n          // Process each item in the array\n          for (const item of statusItems) {\n            if (item.type === \"data\") {\n              // Parse the inner data string\n              const dataItems: ContextStatusData[] = JSON.parse(item.data);\n              contextStatusData.push(...dataItems);\n            }\n          }\n        } catch (error) {\n          logError(\"Error parsing context status:\", error);\n        }\n      }\n\n      // Log API response with key fields\n      const keyFields: Record<string, any> = {\n        session_id: request.sessionId,\n        context_count: contextStatusData.length,\n      };\n      if (request.contextId) {\n        keyFields.context_id = request.contextId;\n      }\n      if (request.path) {\n        keyFields.path = request.path;\n      }\n      if (request.taskType) {\n        keyFields.task_type = request.taskType;\n      }\n      const fullResponse = response.body\n        ? JSON.stringify(response.body, null, 2)\n        : \"\";\n      logAPIResponseWithDetails(\n        \"GetContextInfo\",\n        requestId,\n        true,\n        keyFields,\n        fullResponse\n      );\n\n      return {\n        requestId,\n        success: true,\n        contextStatusData,\n        errorMessage: undefined,\n      };\n    } catch (error) {\n      logError(\"Error calling GetContextInfo:\", error);\n      throw new Error(`Failed to get context info: ${error}`);\n    }\n  }\n\n  /**\n   * Synchronizes a context with the session. Supports both async and callback modes.\n   *\n   * @param contextId - Optional context ID to synchronize. If provided, `path` must also be provided.\n   * @param path - Optional path where the context should be mounted. If provided, `contextId` must also be provided.\n   * @param mode - Optional synchronization mode (e.g., \"upload\", \"download\")\n   * @param callback - Optional callback function. If provided, runs in background and calls callback when complete\n   * @param maxRetries - Maximum number of retries for polling completion status (default: 150)\n   * @param retryInterval - Initial interval in milliseconds for exponential backoff polling (default: 500). Interval grows by factor 1.1 up to 5000ms.\n   * @returns Promise resolving to ContextSyncResult with success status and request ID\n   * @throws Error if the API call fails\n   * @throws Error if `contextId` or `path` is provided without the other parameter.\n   *               Both must be provided together, or both must be omitted.\n   *\n   * @example\n   * Sync all contexts (no parameters):\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: 'your_api_key' });\n   * const result = await agentBay.create();\n   * if (result.success) {\n   *   const syncResult = await result.session.context.sync();\n   *   console.log(`Sync: ${syncResult.success}`);\n   *   await result.session.delete();\n   * }\n   * ```\n   *\n   * @example\n   * Sync specific context with path:\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: 'your_api_key' });\n   * const result = await agentBay.create();\n   * if (result.success) {\n   *   const ctxResult = await agentBay.context.get('my-context', true);\n   *   const syncResult = await result.session.context.sync(ctxResult.context!.id, '/mnt/persistent', 'upload');\n   *   console.log(`Sync: ${syncResult.success}`);\n   *   await result.session.delete();\n   * }\n   * ```\n   */\n  async sync(\n    contextId?: string,\n    path?: string,\n    mode?: string,\n    callback?: SyncCallback,\n    maxRetries = 150,\n    retryInterval = 500\n  ): Promise<ContextSyncResult> {\n    // Validate that contextId and path are provided together or both omitted\n    const hasContextId = contextId !== undefined && contextId.trim() !== \"\";\n    const hasPath = path !== undefined && path.trim() !== \"\";\n\n    if (hasContextId !== hasPath) {\n      throw new Error(\n        \"contextId and path must be provided together or both omitted. \" +\n          \"If you want to sync a specific context, both contextId and path are required. \" +\n          \"If you want to sync all contexts, omit both parameters.\"\n      );\n    }\n\n    const request = new SyncContextRequest({\n      authorization: `Bearer ${this.session.getAPIKey()}`,\n      sessionId: this.session.getSessionId(),\n    });\n\n    // Set optional parameters if provided\n    if (contextId) {\n      request.contextId = contextId;\n    }\n    if (path) {\n      request.path = path;\n    }\n    if (mode) {\n      request.mode = mode;\n    }\n\n    // Log API request (matching Go version format)\n    logAPICall(\"SyncContext\");\n    let requestLog = `Request: SessionId=${request.sessionId}`;\n    if (request.contextId) {\n      requestLog += `, ContextId=${request.contextId}`;\n    }\n    if (request.path) {\n      requestLog += `, Path=${request.path}`;\n    }\n    if (request.mode) {\n      requestLog += `, Mode=${request.mode}`;\n    }\n    logDebug(requestLog);\n\n    try {\n      const response = await this.session.getClient().syncContext(request);\n\n      // Extract RequestID\n      const requestId = extractRequestId(response) || \"\";\n\n      // Check for API-level errors\n      if (response?.body?.success === false && response.body.code) {\n        const errorMsg = `[${response.body.code}] ${\n          response.body.message || \"Unknown error\"\n        }`;\n        const fullResponse = response.body\n          ? JSON.stringify(response.body, null, 2)\n          : \"\";\n        logAPIResponseWithDetails(\n          \"SyncContext\",\n          requestId,\n          false,\n          undefined,\n          fullResponse\n        );\n        return {\n          requestId,\n          success: false,\n          errorMessage: errorMsg,\n        };\n      }\n\n      let success = false;\n      if (response?.body?.success !== undefined) {\n        success = response.body.success;\n      }\n\n      // Log API response with key fields\n      const keyFields: Record<string, any> = {\n        session_id: request.sessionId,\n        success: success,\n      };\n      if (request.contextId) {\n        keyFields.context_id = request.contextId;\n      }\n      if (request.path) {\n        keyFields.path = request.path;\n      }\n      if (request.mode) {\n        keyFields.mode = request.mode;\n      }\n      const fullResponse = response.body\n        ? JSON.stringify(response.body, null, 2)\n        : \"\";\n      logAPIResponseWithDetails(\n        \"SyncContext\",\n        requestId,\n        success,\n        keyFields,\n        fullResponse\n      );\n\n      // If callback is provided, start polling in background (async mode)\n      if (callback && success) {\n        // Start polling in background without blocking\n        this.pollForCompletion(\n          callback,\n          contextId,\n          path,\n          maxRetries,\n          retryInterval\n        ).catch((error) => {\n          logError(\"Error in background polling:\", error);\n          callback(false);\n        });\n        return {\n          requestId,\n          success,\n        };\n      }\n\n      // If no callback, wait for completion (sync mode)\n      if (success) {\n        const finalSuccess = await this.pollForCompletionAsync(\n          contextId,\n          path,\n          maxRetries,\n          retryInterval\n        );\n        return {\n          requestId,\n          success: finalSuccess,\n        };\n      }\n\n      return {\n        requestId,\n        success,\n      };\n    } catch (error) {\n      logError(\"Error calling SyncContext:\", error);\n      throw new Error(`Failed to sync context: ${error}`);\n    }\n  }\n\n  /**\n   * Polls the info interface to check if sync is completed and calls callback.\n   */\n  private async pollForCompletion(\n    callback: SyncCallback,\n    contextId?: string,\n    path?: string,\n    maxRetries = 150,\n    retryInterval = 500\n  ): Promise<void> {\n    const maxInterval = 5000;\n    const backoffFactor = 1.1;\n    let currentInterval = retryInterval;\n\n    for (let retry = 0; retry < maxRetries; retry++) {\n      try {\n        const infoResult = await this.infoWithParams(contextId, path);\n\n        let allCompleted = true;\n        let hasFailure = false;\n        let hasSyncTasks = false;\n\n        for (const item of infoResult.contextStatusData) {\n          if (item.taskType !== \"upload\" && item.taskType !== \"download\") {\n            continue;\n          }\n\n          hasSyncTasks = true;\n          logDebug(\n            `Sync task ${item.contextId} status: ${item.status}, path: ${item.path}`\n          );\n\n          if (item.status !== \"Success\" && item.status !== \"Failed\") {\n            allCompleted = false;\n            break;\n          }\n\n          if (item.status === \"Failed\") {\n            hasFailure = true;\n            logError(\n              `Sync failed for context ${item.contextId}: ${item.errorMessage}`\n            );\n          }\n        }\n\n        if (allCompleted || !hasSyncTasks) {\n          if (hasFailure) {\n            logInfo(\"Context sync completed with failures\");\n            callback(false);\n          } else if (hasSyncTasks) {\n            logInfo(\"Context sync completed successfully\");\n            callback(true);\n          } else {\n            logDebug(\"No sync tasks found\");\n            callback(true);\n          }\n          return;\n        }\n\n        logDebug(\n          `Waiting for context sync to complete, attempt ${\n            retry + 1\n          }/${maxRetries}, next interval: ${currentInterval}ms`\n        );\n        await this.sleep(currentInterval);\n        currentInterval = Math.min(\n          currentInterval * backoffFactor,\n          maxInterval\n        );\n      } catch (error) {\n        logError(\n          `Error checking context status on attempt ${retry + 1}:`,\n          error\n        );\n        await this.sleep(currentInterval);\n        currentInterval = Math.min(\n          currentInterval * backoffFactor,\n          maxInterval\n        );\n      }\n    }\n\n    logError(`Context sync polling timed out after ${maxRetries} attempts`);\n    callback(false);\n  }\n\n  /**\n   * Async version of polling for sync completion.\n   */\n  private async pollForCompletionAsync(\n    contextId?: string,\n    path?: string,\n    maxRetries = 150,\n    retryInterval = 500\n  ): Promise<boolean> {\n    const maxInterval = 5000;\n    const backoffFactor = 1.1;\n    let currentInterval = retryInterval;\n\n    for (let retry = 0; retry < maxRetries; retry++) {\n      try {\n        const infoResult = await this.infoWithParams(contextId, path);\n\n        let allCompleted = true;\n        let hasFailure = false;\n        let hasSyncTasks = false;\n\n        for (const item of infoResult.contextStatusData) {\n          if (item.taskType !== \"upload\" && item.taskType !== \"download\") {\n            continue;\n          }\n\n          hasSyncTasks = true;\n          logDebug(\n            `Sync task ${item.contextId} status: ${item.status}, path: ${item.path}`\n          );\n\n          if (item.status !== \"Success\" && item.status !== \"Failed\") {\n            allCompleted = false;\n            break;\n          }\n\n          if (item.status === \"Failed\") {\n            hasFailure = true;\n            logError(\n              `Sync failed for context ${item.contextId}: ${item.errorMessage}`\n            );\n          }\n        }\n\n        if (allCompleted || !hasSyncTasks) {\n          if (hasFailure) {\n            logInfo(\"Context sync completed with failures\");\n            return false;\n          } else if (hasSyncTasks) {\n            logInfo(\"Context sync completed successfully\");\n            return true;\n          } else {\n            logDebug(\"No sync tasks found\");\n            return true;\n          }\n        }\n\n        logDebug(\n          `Waiting for context sync to complete, attempt ${\n            retry + 1\n          }/${maxRetries}, next interval: ${currentInterval}ms`\n        );\n        await this.sleep(currentInterval);\n        currentInterval = Math.min(\n          currentInterval * backoffFactor,\n          maxInterval\n        );\n      } catch (error) {\n        logError(\n          `Error checking context status on attempt ${retry + 1}:`,\n          error\n        );\n        await this.sleep(currentInterval);\n        currentInterval = Math.min(\n          currentInterval * backoffFactor,\n          maxInterval\n        );\n      }\n    }\n\n    logError(`Context sync polling timed out after ${maxRetries} attempts`);\n    return false;\n  }\n\n  /**\n   * Dynamically binds one or more contexts to the current session.\n   *\n   * Accepts both ContextSync (sync-based persistence) and BetaContextMount (direct-mount\n   * write-through persistence) objects. They can be mixed in a single call.\n   *\n   * @param contexts - One or more ContextSync or BetaContextMount objects\n   * @param waitForCompletion - Whether to wait for bind registration and data download to complete (default: true). For ContextSync, waits until data is fully downloaded. For BetaContextMount, only waits for bind registration.\n   * @returns Promise resolving to ContextBindResult\n   *\n   * @example\n   * ```typescript\n   * const contextSync = new ContextSync(context.id, '/tmp/ctx-data');\n   * const result = await session.context.bind(contextSync);\n   *\n   * const contextMount = new BetaContextMount(context.id, '/mnt/data');\n   * const result2 = await session.context.bind(contextMount);\n   * ```\n   */\n  async bind(\n    contexts:\n      | ContextSync\n      | BetaContextMount\n      | (ContextSync | BetaContextMount)[],\n    waitForCompletion = true\n  ): Promise<ContextBindResult> {\n    const ctxArray = Array.isArray(contexts) ? contexts : [contexts];\n\n    if (ctxArray.length === 0) {\n      return {\n        requestId: \"\",\n        success: false,\n        errorMessage: \"At least one context is required\",\n      };\n    }\n\n    const persistenceDataList = ctxArray.map((ctx) => {\n      const item = new BindContextsRequestPersistenceDataList({\n        contextId: ctx.contextId,\n        path: ctx.path,\n      });\n      if (ctx instanceof BetaContextMount) {\n        item.type = \"mount\";\n        item.mountConfig =\n          new BindContextsRequestPersistenceDataListMountConfig({\n            accessMode: ctx.accessMode,\n            storageMode: ctx.strategy,\n            sourcePath: ctx.sourcePath,\n          });\n      } else if (ctx instanceof ContextSync && ctx.policy) {\n        item.policy = JSON.stringify(ctx.policy);\n      }\n      return item;\n    });\n\n    const request = new BindContextsRequest({\n      authorization: `Bearer ${this.session.getAPIKey()}`,\n      sessionId: this.session.getSessionId(),\n      persistenceDataList,\n    });\n\n    logAPICall(\"BindContexts\");\n    logDebug(\n      `Request: SessionId=${request.sessionId}, Contexts=${ctxArray\n        .map((c) => c.contextId)\n        .join(\",\")}`\n    );\n\n    try {\n      const response = await this.session.getClient().bindContexts(request);\n      const requestId = extractRequestId(response) || \"\";\n\n      if (response?.body?.success === false) {\n        const errorMsg = `[${response.body.code || \"Unknown\"}] ${\n          response.body.message || \"Unknown error\"\n        }`;\n        const fullResponse = response.body\n          ? JSON.stringify(response.body, null, 2)\n          : \"\";\n        logAPIResponseWithDetails(\n          \"BindContexts\",\n          requestId,\n          false,\n          undefined,\n          fullResponse\n        );\n        return { requestId, success: false, errorMessage: errorMsg };\n      }\n\n      const fullResponse = response.body\n        ? JSON.stringify(response.body, null, 2)\n        : \"\";\n      logAPIResponseWithDetails(\n        \"BindContexts\",\n        requestId,\n        true,\n        {\n          context_count: ctxArray.length,\n        },\n        fullResponse\n      );\n\n      if (waitForCompletion) {\n        const syncContexts = ctxArray.filter(\n          (c) => c instanceof ContextSync\n        ) as ContextSync[];\n        if (syncContexts.length > 0) {\n          const syncIds = syncContexts.map((c) => c.contextId);\n          await this.pollForBindCompletion(syncIds);\n          for (const ctx of syncContexts) {\n            await this.pollForDownloadAfterBind(ctx.contextId, ctx.path);\n          }\n        }\n      }\n\n      return { requestId, success: true };\n    } catch (error) {\n      logError(\"Error calling BindContexts:\", error);\n      throw new Error(`Failed to bind contexts: ${error}`);\n    }\n  }\n\n  /**\n   * Lists all context bindings for the current session.\n   *\n   * @returns Promise resolving to ContextBindingsResult with the list of bindings\n   *\n   * @example\n   * ```typescript\n   * const result = await session.context.listBindings();\n   * for (const binding of result.bindings) {\n   *   console.log(`Context ${binding.contextId} bound at ${binding.path}`);\n   * }\n   * ```\n   */\n  async listBindings(): Promise<ContextBindingsResult> {\n    const request = new DescribeSessionContextsRequest({\n      authorization: `Bearer ${this.session.getAPIKey()}`,\n      sessionId: this.session.getSessionId(),\n    });\n\n    logAPICall(\"DescribeSessionContexts\");\n    logDebug(`Request: SessionId=${request.sessionId}`);\n\n    try {\n      const response = await this.session\n        .getClient()\n        .describeSessionContexts(request);\n      const requestId = extractRequestId(response) || \"\";\n\n      if (response?.body?.success === false) {\n        const errorMsg = `[${response.body.code || \"Unknown\"}] ${\n          response.body.message || \"Unknown error\"\n        }`;\n        const fullResponse = response.body\n          ? JSON.stringify(response.body, null, 2)\n          : \"\";\n        logAPIResponseWithDetails(\n          \"DescribeSessionContexts\",\n          requestId,\n          false,\n          undefined,\n          fullResponse\n        );\n        return {\n          requestId,\n          success: false,\n          bindings: [],\n          errorMessage: errorMsg,\n        };\n      }\n\n      const bindings: ContextBinding[] = [];\n      if (response?.body?.data) {\n        for (const item of response.body.data) {\n          bindings.push({\n            contextId: item.contextId || \"\",\n            contextName: item.contextName,\n            path: item.path || \"\",\n            policy: item.policy,\n            bindTime: item.bindTime,\n          });\n        }\n      }\n\n      const fullResponse = response.body\n        ? JSON.stringify(response.body, null, 2)\n        : \"\";\n      logAPIResponseWithDetails(\n        \"DescribeSessionContexts\",\n        requestId,\n        true,\n        {\n          binding_count: bindings.length,\n        },\n        fullResponse\n      );\n\n      return { requestId, success: true, bindings };\n    } catch (error) {\n      logError(\"Error calling DescribeSessionContexts:\", error);\n      throw new Error(`Failed to list bindings: ${error}`);\n    }\n  }\n\n  private async pollForDownloadAfterBind(\n    contextId: string,\n    path: string,\n    maxRetries = 150,\n    retryInterval = 500\n  ): Promise<boolean> {\n    const maxInterval = 5000;\n    const backoffFactor = 1.1;\n    let currentInterval = retryInterval;\n\n    for (let i = 0; i < maxRetries; i++) {\n      try {\n        const infoResult = await this.infoWithParams(contextId, path);\n\n        let hasDownload = false;\n        let allDone = true;\n\n        for (const item of infoResult.contextStatusData) {\n          if (item.taskType !== \"download\") continue;\n          hasDownload = true;\n          if (item.status === \"Failed\") {\n            logError(\n              `Download failed for context ${item.contextId}: ${item.errorMessage}`\n            );\n            return false;\n          }\n          if (item.status !== \"Success\") {\n            allDone = false;\n            break;\n          }\n        }\n\n        if (hasDownload && allDone) {\n          logInfo(`Download completed for context ${contextId}`);\n          return true;\n        }\n\n        if (!hasDownload && i >= 2) {\n          return true;\n        }\n      } catch {\n        logDebug(`Download polling attempt ${i + 1} failed, retrying...`);\n      }\n\n      await this.sleep(currentInterval);\n      currentInterval = Math.min(currentInterval * backoffFactor, maxInterval);\n    }\n\n    logError(`Download polling timed out for context ${contextId}`);\n    return false;\n  }\n\n  private async pollForBindCompletion(\n    expectedContextIds: string[],\n    maxRetries = 60,\n    retryInterval = 2000\n  ): Promise<boolean> {\n    for (let i = 0; i < maxRetries; i++) {\n      try {\n        const result = await this.listBindings();\n        if (result.success) {\n          const boundIds = new Set(result.bindings.map((b) => b.contextId));\n          if (expectedContextIds.every((id) => boundIds.has(id))) {\n            logInfo(\"All contexts bound successfully\");\n            return true;\n          }\n        }\n      } catch {\n        logDebug(`Polling attempt ${i + 1} failed, retrying...`);\n      }\n      await this.sleep(retryInterval);\n    }\n    logError(`Bind polling timed out after ${maxRetries} attempts`);\n    return false;\n  }\n\n  /**\n   * Sleep utility function for TypeScript\n   */\n  private sleep(ms: number): Promise<void> {\n    return new Promise((resolve) => setTimeout(resolve, ms));\n  }\n}\n\nexport function newContextManager(session: SessionInterface): ContextManager {\n  return new ContextManager(session);\n}\n","export enum BetaContextMountAccessMode {\n  ReadWrite = \"readWrite\",\n  ReadOnly = \"readOnly\",\n}\n\nexport enum BetaContextMountStrategy {\n  Standard = \"standard\",\n  Performance = \"performance\",\n}\n\n/**\n * [Beta] Represents a context mount configuration for direct-mount persistence.\n *\n * IMPORTANT: BetaContextMount requires `imageId: \"aio-ubuntu-2404\"` on the session.\n * Other images do not provide a real OSS-backed mount — writes are not persisted to\n * the shared context store and are invisible to other sessions even with the same\n * contextId and mount path.\n *\n * Use `withSourcePath()` to mount only a subdirectory of the context. The\n * subdirectory's contents are projected to the mount root.\n */\nexport class BetaContextMount {\n  contextId: string;\n  path: string;\n  accessMode: BetaContextMountAccessMode;\n  strategy: BetaContextMountStrategy;\n  sourcePath: string;\n\n  constructor(\n    contextId: string,\n    path: string,\n    accessMode: BetaContextMountAccessMode = BetaContextMountAccessMode.ReadWrite,\n    strategy: BetaContextMountStrategy = BetaContextMountStrategy.Standard\n  ) {\n    this.contextId = contextId;\n    this.path = path;\n    this.accessMode = accessMode;\n    this.strategy = strategy;\n    this.sourcePath = \"\";\n  }\n\n  withAccessMode(accessMode: BetaContextMountAccessMode): BetaContextMount {\n    this.accessMode = accessMode;\n    return this;\n  }\n\n  withStrategy(strategy: BetaContextMountStrategy): BetaContextMount {\n    this.strategy = strategy;\n    return this;\n  }\n\n  /**\n   * Set the subpath within the context to mount. Empty string (default) mounts\n   * the entire context. The selected subdirectory's contents are projected to\n   * the mount root.\n   */\n  withSourcePath(sourcePath: string): BetaContextMount {\n    this.sourcePath = sourcePath;\n    return this;\n  }\n}\n\nexport function newBetaContextMount(\n  contextId: string,\n  path: string,\n  accessMode?: BetaContextMountAccessMode,\n  strategy?: BetaContextMountStrategy\n): BetaContextMount {\n  return new BetaContextMount(contextId, path, accessMode, strategy);\n}\n","import {\n  BoolResult,\n  FileInfoResult,\n  DirectoryListResult,\n  FileContentResult,\n  BinaryFileContentResult,\n  MultipleFileContentResult,\n  FileSearchResult,\n  ApiResponse,\n} from \"../types/api-response\";\nimport { UploadResult, DownloadResult } from \"./file-transfer\";\nimport { FileTransfer } from \"./file-transfer\";\nimport { Session } from \"../session\";\nimport { log, logWarn, logInfo, logError } from \"../utils/logger\";\n\n// Default chunk size for large file operations (60KB)\nconst DEFAULT_CHUNK_SIZE = 60 * 1024;\n\nfunction withTimeout<T>(promise: Promise<T>, timeoutMs: number): Promise<T> {\n  return new Promise<T>((resolve, reject) => {\n    const timer = setTimeout(\n      () => reject(new Error(`Timeout after ${timeoutMs}ms`)),\n      timeoutMs\n    );\n    promise.then(\n      (v) => {\n        clearTimeout(timer);\n        resolve(v);\n      },\n      (e) => {\n        clearTimeout(timer);\n        reject(e);\n      }\n    );\n  });\n}\n\n/**\n * Represents a single file change event\n */\nexport interface FileChangeEvent {\n  eventType: string; // \"create\", \"modify\", \"delete\"\n  path: string;\n  pathType: string; // \"file\", \"directory\"\n}\n\n/**\n * Result of file change detection operations\n */\nexport interface FileChangeResult extends ApiResponse {\n  events: FileChangeEvent[];\n  rawData: string;\n}\n\n/**\n * Helper functions for FileChangeEvent\n */\nexport class FileChangeEventHelper {\n  static toString(event: FileChangeEvent): string {\n    return `FileChangeEvent(eventType='${event.eventType}', path='${event.path}', pathType='${event.pathType}')`;\n  }\n\n  static toDict(event: FileChangeEvent): Record<string, string> {\n    return {\n      eventType: event.eventType,\n      path: event.path,\n      pathType: event.pathType,\n    };\n  }\n\n  static fromDict(data: Record<string, any>): FileChangeEvent {\n    return {\n      eventType: data.eventType || \"\",\n      path: data.path || \"\",\n      pathType: data.pathType || \"\",\n    };\n  }\n}\n\n/**\n * Helper functions for FileChangeResult\n */\nexport class FileChangeResultHelper {\n  static hasChanges(result: FileChangeResult): boolean {\n    return result.events.length > 0;\n  }\n\n  static getModifiedFiles(result: FileChangeResult): string[] {\n    return result.events\n      .filter(\n        (event) => event.eventType === \"modify\" && event.pathType === \"file\"\n      )\n      .map((event) => event.path);\n  }\n\n  static getCreatedFiles(result: FileChangeResult): string[] {\n    return result.events\n      .filter(\n        (event) => event.eventType === \"create\" && event.pathType === \"file\"\n      )\n      .map((event) => event.path);\n  }\n\n  static getDeletedFiles(result: FileChangeResult): string[] {\n    return result.events\n      .filter(\n        (event) => event.eventType === \"delete\" && event.pathType === \"file\"\n      )\n      .map((event) => event.path);\n  }\n}\n\n/**\n * FileInfo represents information about a file or directory\n */\nexport interface FileInfo {\n  name: string;\n  path: string;\n  size: number;\n  isDirectory: boolean;\n  modTime: string;\n  mode: string;\n  owner?: string;\n  group?: string;\n}\n\n/**\n * DirectoryEntry represents an entry in a directory listing\n */\nexport interface DirectoryEntry {\n  name: string;\n  isDirectory: boolean;\n}\n\n/**\n * Parse a file info string into a FileInfo object\n *\n * @param fileInfoStr - The file info string to parse\n * @returns A FileInfo object\n */\nfunction parseFileInfo(fileInfoStr: string): FileInfo {\n  const result: FileInfo = {\n    name: \"\",\n    path: \"\",\n    size: 0,\n    isDirectory: false,\n    modTime: \"\",\n    mode: \"\",\n  };\n\n  const lines = fileInfoStr.split(\"\\n\");\n  for (const line of lines) {\n    if (line.includes(\":\")) {\n      const [key, value] = line.split(\":\", 2).map((part) => part.trim());\n\n      switch (key) {\n        case \"name\":\n          result.name = value;\n          break;\n        case \"path\":\n          result.path = value;\n          break;\n        case \"size\":\n          result.size = parseInt(value, 10);\n          break;\n        case \"isDirectory\":\n          result.isDirectory = value === \"true\";\n          break;\n        case \"modTime\":\n          result.modTime = value;\n          break;\n        case \"mode\":\n          result.mode = value;\n          break;\n        case \"owner\":\n          result.owner = value;\n          break;\n        case \"group\":\n          result.group = value;\n          break;\n      }\n    }\n  }\n\n  return result;\n}\n\n/**\n * Parse a directory listing string into an array of DirectoryEntry objects\n *\n * @param text - The directory listing text to parse\n * @returns An array of DirectoryEntry objects\n */\nfunction parseDirectoryListing(text: string): DirectoryEntry[] {\n  const result: DirectoryEntry[] = [];\n  const lines = text.split(\"\\n\");\n\n  for (const line of lines) {\n    const trimmedLine = line.trim();\n    if (trimmedLine === \"\") {\n      continue;\n    }\n\n    if (trimmedLine.startsWith(\"[DIR]\")) {\n      result.push({\n        isDirectory: true,\n        name: trimmedLine.replace(\"[DIR]\", \"\").trim(),\n      });\n    } else if (trimmedLine.startsWith(\"[FILE]\")) {\n      result.push({\n        isDirectory: false,\n        name: trimmedLine.replace(\"[FILE]\", \"\").trim(),\n      });\n    }\n  }\n\n  return result;\n}\n\n/**\n * Handles file operations in the AgentBay cloud environment.\n */\nexport class FileSystem {\n  private session: Session;\n\n  private _fileTransfer: FileTransfer | null = null;\n\n  /**\n   * Initialize a FileSystem object.\n   *\n   * @param session - The Session instance that this FileSystem belongs to.\n   */\n  constructor(session: Session) {\n    this.session = session;\n  }\n\n  /**\n   * Ensure FileTransfer is initialized with the current session.\n   *\n   * @returns The FileTransfer instance\n   */\n  private _ensureFileTransfer(): FileTransfer {\n    if (this._fileTransfer === null) {\n      // Get the agent_bay instance from the session\n      const agentBay = this.session.getAgentBay();\n      if (agentBay === undefined) {\n        throw new Error(\"FileTransfer requires an AgentBay instance\");\n      }\n\n      this._fileTransfer = new FileTransfer(agentBay, this.session);\n    }\n\n    return this._fileTransfer;\n  }\n\n  /**\n   * Get the context path for file transfer operations.\n   *\n   * This method ensures the context ID is loaded and returns the associated\n   * context path that was retrieved from GetAndLoadInternalContext API.\n   *\n   * @returns The context path if available, null otherwise.\n   *\n   * @example\n   * ```typescript\n   * const session = (await agentBay.create(params)).session;\n   * const contextPath = await session.fileSystem.getFileTransferContextPath();\n   * if (contextPath) {\n   *   console.log(`Context path: ${contextPath}`);\n   * }\n   * ```\n   */\n  async getFileTransferContextPath(): Promise<string | null> {\n    const fileTransfer = this._ensureFileTransfer();\n    // Ensure context_id is loaded (this will also load context_path)\n    if (!fileTransfer.getContextId()) {\n      await (fileTransfer as any).ensureContextId();\n    }\n    return (fileTransfer as any).contextPath || null;\n  }\n\n  /**\n   * Creates a new directory at the specified path.\n   * Corresponds to Python's create_directory() method\n   *\n   * @param path - Path to the directory to create.\n   * @returns BoolResult with creation result and requestId\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: 'your_api_key' });\n   * const result = await agentBay.create();\n   * if (result.success) {\n   *   const createResult = await result.session.fileSystem.createDirectory('/tmp/mydir');\n   *   console.log('Directory created:', createResult.success);\n   *   await result.session.delete();\n   * }\n   * ```\n   */\n  async createDirectory(path: string): Promise<BoolResult> {\n    try {\n      const args = {\n        path,\n      };\n\n      const result = await this.session.callMcpTool(\n        \"create_directory\",\n        args,\n        false\n      );\n\n      if (!result.success) {\n        return {\n          requestId: result.requestId,\n          success: false,\n          errorMessage: result.errorMessage,\n        };\n      }\n\n      return {\n        requestId: result.requestId,\n        success: true,\n        data: true,\n      };\n    } catch (error) {\n      return {\n        requestId: \"\",\n        success: false,\n        errorMessage: `Failed to create directory: ${error}`,\n      };\n    }\n  }\n\n  /**\n   * Check if the current session uses LinkUrl (HTTP) channel.\n   * When using LinkUrl, chunking is not needed as HTTP has no message size limit.\n   */\n  private isUsingLinkUrl(): boolean {\n    return !!(this.session.linkUrl && this.session.token);\n  }\n\n  /**\n   * Deletes a file at the specified path.\n   * Corresponds to Python's delete_file() method\n   *\n   * @param path - Path to the file to delete.\n   * @returns BoolResult with deletion result and requestId\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: 'your_api_key' });\n   * const result = await agentBay.create();\n   * if (result.success) {\n   *   const session = result.session;\n   *   await session.fileSystem.writeFile('/tmp/to_delete.txt', 'hello');\n   *   const deleteResult = await session.fileSystem.deleteFile('/tmp/to_delete.txt');\n   *   console.log('File deleted:', deleteResult.success);\n   *   await session.delete();\n   * }\n   * ```\n   */\n  async deleteFile(path: string): Promise<BoolResult> {\n    try {\n      const args = { path };\n      const result = await this.session.callMcpTool(\"delete_file\", args, false);\n\n      if (!result.success) {\n        return {\n          requestId: result.requestId,\n          success: false,\n          errorMessage: result.errorMessage,\n        };\n      }\n\n      return {\n        requestId: result.requestId,\n        success: true,\n        data: true,\n      };\n    } catch (error) {\n      return {\n        requestId: \"\",\n        success: false,\n        errorMessage: `Failed to delete file: ${error}`,\n      };\n    }\n  }\n\n  /**\n   * Alias of readFile().\n   */\n  async read(path: string): Promise<FileContentResult> {\n    return await this.readFile(path);\n  }\n\n  /**\n   * Alias of writeFile().\n   */\n  async write(\n    path: string,\n    content: string,\n    mode = \"overwrite\"\n  ): Promise<BoolResult> {\n    return await this.writeFile(path, content, mode);\n  }\n\n  /**\n   * Alias of listDirectory().\n   */\n  async list(path: string): Promise<DirectoryListResult> {\n    return await this.listDirectory(path);\n  }\n\n  /**\n   * Alias of listDirectory().\n   */\n  async ls(path: string): Promise<DirectoryListResult> {\n    return await this.listDirectory(path);\n  }\n\n  /**\n   * Alias of deleteFile().\n   */\n  async delete(path: string): Promise<BoolResult> {\n    return await this.deleteFile(path);\n  }\n\n  /**\n   * Alias of deleteFile().\n   */\n  async remove(path: string): Promise<BoolResult> {\n    return await this.deleteFile(path);\n  }\n\n  /**\n   * Alias of deleteFile().\n   */\n  async rm(path: string): Promise<BoolResult> {\n    return await this.deleteFile(path);\n  }\n\n  /**\n   * Edits a file by replacing occurrences of oldText with newText.\n   * Corresponds to Python's edit_file() method\n   *\n   * @param path - Path to the file to edit.\n   * @param edits - Array of edit operations, each containing oldText and newText.\n   * @param dryRun - Optional: If true, preview changes without applying them.\n   * @returns BoolResult with edit result and requestId\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: 'your_api_key' });\n   * const result = await agentBay.create();\n   * if (result.success) {\n   *   await result.session.fileSystem.writeFile('/tmp/config.txt', 'DEBUG=false');\n   *   const edits = [{ oldText: 'DEBUG=false', newText: 'DEBUG=true' }];\n   *   const editResult = await result.session.fileSystem.editFile('/tmp/config.txt', edits);\n   *   console.log('File edited:', editResult.success);\n   *   await result.session.delete();\n   * }\n   * ```\n   */\n  async editFile(\n    path: string,\n    edits: Array<{ oldText: string; newText: string }>,\n    dryRun = false\n  ): Promise<BoolResult> {\n    try {\n      const args = {\n        path,\n        edits,\n        dryRun,\n      };\n\n      const result = await this.session.callMcpTool(\"edit_file\", args, false);\n\n      if (!result.success) {\n        return {\n          requestId: result.requestId,\n          success: false,\n          errorMessage: result.errorMessage,\n        };\n      }\n\n      return {\n        requestId: result.requestId,\n        success: true,\n        data: true,\n      };\n    } catch (error) {\n      return {\n        requestId: \"\",\n        success: false,\n        errorMessage: `Failed to edit file: ${error}`,\n      };\n    }\n  }\n\n  /**\n   * Gets information about a file or directory.\n   * Corresponds to Python's get_file_info() method\n   *\n   * @param path - Path to the file or directory to inspect.\n   * @returns FileInfoResult with file info and requestId\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: 'your_api_key' });\n   * const result = await agentBay.create();\n   * if (result.success) {\n   *   await result.session.fileSystem.writeFile('/tmp/test.txt', 'Sample content');\n   *   const infoResult = await result.session.fileSystem.getFileInfo('/tmp/test.txt');\n   *   console.log(`Size: ${infoResult.fileInfo.size} bytes`);\n   *   await result.session.delete();\n   * }\n   * ```\n   */\n  async getFileInfo(path: string): Promise<FileInfoResult> {\n    try {\n      const args = {\n        path,\n      };\n\n      const result = await this.session.callMcpTool(\n        \"get_file_info\",\n        args,\n        false\n      );\n\n      if (!result.success) {\n        return {\n          requestId: result.requestId,\n          success: false,\n          fileInfo: {},\n          errorMessage: result.errorMessage,\n        };\n      }\n\n      // Parse and return the file info\n      if (!result.data) {\n        return {\n          requestId: result.requestId,\n          success: false,\n          fileInfo: {},\n          errorMessage: \"Empty response from get_file_info\",\n        };\n      }\n\n      const fileInfo = parseFileInfo(result.data);\n\n      return {\n        requestId: result.requestId,\n        success: true,\n        fileInfo,\n      };\n    } catch (error) {\n      return {\n        requestId: \"\",\n        success: false,\n        errorMessage: `Failed to get file info: ${error}`,\n      };\n    }\n  }\n\n  /**\n   * Lists the contents of a directory.\n   * Corresponds to Python's list_directory() method\n   *\n   * @param path - Path to the directory to list.\n   * @returns DirectoryListResult with directory entries and requestId\n   */\n  /**\n   * Lists the contents of a directory.\n   *\n   * @param path - Absolute path to the directory to list.\n   *\n   * @returns Promise resolving to DirectoryListResult containing array of entries.\n   *\n   * @example\n   * ```typescript\n   * import { AgentBay } from 'wuying-agentbay-sdk';\n   *\n   * const agentBay = new AgentBay({ apiKey: 'your_api_key' });\n   * const result = await agentBay.create();\n   *\n   * if (result.success) {\n   *   const session = result.session;\n   *\n   *   // List directory contents\n   *   const listResult = await session.fileSystem.listDirectory('/tmp');\n   *   if (listResult.success) {\n   *     console.log(`Found ${listResult.entries.length} entries`);\n   *     for (const entry of listResult.entries) {\n   *       console.log(`${entry.name} (${entry.isDirectory ? 'dir' : 'file'})`);\n   *     }\n   *   }\n   *\n   *   await session.delete();\n   * }\n   * ```\n   *\n   * @see {@link readFile}, {@link writeFile}\n   */\n  async listDirectory(path: string): Promise<DirectoryListResult> {\n    try {\n      const args = {\n        path,\n      };\n\n      const result = await this.session.callMcpTool(\n        \"list_directory\",\n        args,\n        false\n      );\n\n      if (!result.success) {\n        return {\n          requestId: result.requestId,\n          success: false,\n          entries: [],\n          errorMessage: result.errorMessage,\n        };\n      }\n\n      // Parse the text content into directory entries\n      const entries = result.data ? parseDirectoryListing(result.data) : [];\n\n      return {\n        requestId: result.requestId,\n        success: true,\n        entries,\n      };\n    } catch (error) {\n      return {\n        requestId: \"\",\n        success: false,\n        entries: [],\n        errorMessage: `Failed to list directory: ${error}`,\n      };\n    }\n  }\n\n  /**\n   * Moves a file or directory from source to destination.\n   * Corresponds to Python's move_file() method\n   *\n   * @param source - Path to the source file or directory.\n   * @param destination - Path to the destination file or directory.\n   * @returns BoolResult with move result and requestId\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: 'your_api_key' });\n   * const result = await agentBay.create();\n   * if (result.success) {\n   *   await result.session.fileSystem.writeFile('/tmp/original.txt', 'Test content');\n   *   const moveResult = await result.session.fileSystem.moveFile('/tmp/original.txt', '/tmp/moved.txt');\n   *   console.log('File moved:', moveResult.success);\n   *   await result.session.delete();\n   * }\n   * ```\n   */\n  async moveFile(source: string, destination: string): Promise<BoolResult> {\n    try {\n      const args = {\n        source,\n        destination,\n      };\n\n      const result = await this.session.callMcpTool(\"move_file\", args, false);\n\n      if (!result.success) {\n        return {\n          requestId: result.requestId,\n          success: false,\n          errorMessage: result.errorMessage,\n        };\n      }\n\n      return {\n        requestId: result.requestId,\n        success: true,\n        data: true,\n      };\n    } catch (error) {\n      return {\n        requestId: \"\",\n        success: false,\n        errorMessage: `Failed to move file: ${error}`,\n      };\n    }\n  }\n\n  /**\n   * Internal method to read a file chunk. Used for chunked file operations.\n   *\n   * @param path - Path to the file to read.\n   * @param offset - Optional: Byte offset to start reading from (0-based).\n   * @param length - Optional: Number of bytes to read. If 0, reads the entire file from offset.\n   * @param formatType - Optional: Format to read the file in. \"text\" (default) or \"binary\".\n   * @returns FileContentResult for text format, BinaryFileContentResult for binary format\n   */\n  private async readFileChunk(\n    path: string,\n    offset = 0,\n    length = 0,\n    formatType: \"text\" | \"binary\" = \"text\"\n  ): Promise<FileContentResult | BinaryFileContentResult> {\n    try {\n      const args: any = {\n        path,\n      };\n\n      if (offset >= 0) {\n        args.offset = offset;\n      }\n\n      if (length >= 0) {\n        args.length = length;\n      }\n\n      // Only pass format parameter for binary files\n      if (formatType === \"binary\") {\n        args.format = \"binary\";\n      }\n\n      const result = await this.session.callMcpTool(\"read_file\", args, false);\n\n      if (!result.success) {\n        if (formatType === \"binary\") {\n          return {\n            requestId: result.requestId,\n            success: false,\n            content: new Uint8Array(0),\n            errorMessage: result.errorMessage,\n          };\n        } else {\n          return {\n            requestId: result.requestId,\n            success: false,\n            content: \"\",\n            errorMessage: result.errorMessage,\n          };\n        }\n      }\n\n      if (formatType === \"binary\") {\n        // Backend returns base64-encoded string, decode to Uint8Array\n        try {\n          // In Node.js environment, use Buffer\n          if (typeof Buffer !== \"undefined\") {\n            const base64String = result.data || \"\";\n            // Validate base64 string format before decoding\n            // Buffer.from() doesn't throw for invalid base64, so we need to validate\n            if (base64String) {\n              // Base64 string should only contain A-Z, a-z, 0-9, +, /, and = (padding)\n              // Remove padding for validation, then check remaining characters\n              const base64WithoutPadding = base64String.replace(/=+$/, \"\");\n              if (!/^[A-Za-z0-9+/]+$/.test(base64WithoutPadding)) {\n                throw new Error(\"Invalid base64 string format\");\n              }\n              // Also check padding format (0, 1, or 2 = characters at the end)\n              const paddingMatch = base64String.match(/=+$/);\n              if (paddingMatch && paddingMatch[0].length > 2) {\n                throw new Error(\"Invalid base64 padding format\");\n              }\n            }\n            const binaryContent = Buffer.from(base64String, \"base64\");\n            return {\n              requestId: result.requestId,\n              success: true,\n              content: new Uint8Array(binaryContent),\n            };\n          } else {\n            // In browser environment, use atob\n            const binaryString = atob(result.data || \"\");\n            const binaryContent = new Uint8Array(binaryString.length);\n            for (let i = 0; i < binaryString.length; i++) {\n              binaryContent[i] = binaryString.charCodeAt(i);\n            }\n            return {\n              requestId: result.requestId,\n              success: true,\n              content: binaryContent,\n            };\n          }\n        } catch (e) {\n          return {\n            requestId: result.requestId,\n            success: false,\n            content: new Uint8Array(0),\n            errorMessage: `Failed to decode base64: ${e}`,\n          };\n        }\n      } else {\n        // Text format\n        return {\n          requestId: result.requestId,\n          success: true,\n          content: result.data || \"\",\n        };\n      }\n    } catch (error) {\n      if (formatType === \"binary\") {\n        return {\n          requestId: \"\",\n          success: false,\n          content: new Uint8Array(0),\n          errorMessage: `Failed to read file: ${error}`,\n        };\n      } else {\n        return {\n          requestId: \"\",\n          success: false,\n          content: \"\",\n          errorMessage: `Failed to read file: ${error}`,\n        };\n      }\n    }\n  }\n\n  /**\n   * Reads the content of multiple files.\n   * Corresponds to Python's read_multiple_files() method\n   *\n   * @param paths - Array of file paths to read.\n   * @returns MultipleFileContentResult with file contents and requestId\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: 'your_api_key' });\n   * const result = await agentBay.create();\n   * if (result.success) {\n   *   await result.session.fileSystem.writeFile('/tmp/file1.txt', 'Content 1');\n   *   await result.session.fileSystem.writeFile('/tmp/file2.txt', 'Content 2');\n   *   const readResult = await result.session.fileSystem.readMultipleFiles(['/tmp/file1.txt', '/tmp/file2.txt']);\n   *   console.log(`Read ${Object.keys(readResult.contents).length} files`);\n   *   await result.session.delete();\n   * }\n   * ```\n   */\n  async readMultipleFiles(paths: string[]): Promise<MultipleFileContentResult> {\n    try {\n      const args = {\n        paths,\n      };\n\n      const result = await this.session.callMcpTool(\n        \"read_multiple_files\",\n        args,\n        false\n      );\n\n      if (!result.success) {\n        return {\n          requestId: result.requestId,\n          success: false,\n          contents: {},\n          errorMessage: result.errorMessage,\n        };\n      }\n\n      const fileContents: Record<string, string> = {};\n\n      if (result.data) {\n        // Parse the response into a map of file paths to contents\n        const lines = result.data.split(\"\\n\");\n        let currentPath = \"\";\n        let currentContent: string[] = [];\n\n        for (const line of lines) {\n          // Check if this line contains a file path (ends with a colon)\n          const colonIndex = line.indexOf(\":\");\n          if (\n            colonIndex > 0 &&\n            currentPath === \"\" &&\n            !line.substring(0, colonIndex).includes(\" \")\n          ) {\n            // Extract path (everything before the first colon)\n            const path = line.substring(0, colonIndex).trim();\n\n            // Start collecting content (everything after the colon)\n            currentPath = path;\n\n            // If there's content on the same line after the colon, add it\n            if (line.length > colonIndex + 1) {\n              const contentStart = line.substring(colonIndex + 1).trim();\n              if (contentStart) {\n                currentContent.push(contentStart);\n              }\n            }\n          } else if (line === \"---\") {\n            // Save the current file content\n            if (currentPath) {\n              fileContents[currentPath] = currentContent.join(\"\\n\");\n              currentPath = \"\";\n              currentContent = [];\n            }\n          } else if (currentPath) {\n            // If we're collecting content for a path, add this line\n            currentContent.push(line);\n          }\n        }\n\n        // Save the last file content if exists\n        if (currentPath) {\n          fileContents[currentPath] = currentContent.join(\"\\n\");\n        }\n\n        // Trim trailing newlines from file contents to match expected test values\n        for (const path in fileContents) {\n          fileContents[path] = fileContents[path].replace(/\\n+$/, \"\");\n        }\n      }\n\n      return {\n        requestId: result.requestId,\n        success: true,\n        contents: fileContents,\n      };\n    } catch (error) {\n      return {\n        requestId: \"\",\n        success: false,\n        contents: {},\n        errorMessage: `Failed to read multiple files: ${error}`,\n      };\n    }\n  }\n\n  /**\n   * Searches for files in a directory that match a wildcard pattern.\n   * Corresponds to Python's search_files() method\n   *\n   * @param path - Path to the directory to search in.\n   * @param pattern - Wildcard pattern to match against file names. Supports * (any characters)\n   *                  and ? (single character). Examples: \"*.py\", \"test_*\", \"*config*\".\n   * @param excludePatterns - Optional: Array of wildcard patterns to exclude.\n   * @returns FileSearchResult with search results and requestId\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: 'your_api_key' });\n   * const result = await agentBay.create();\n   * if (result.success) {\n   *   await result.session.fileSystem.createDirectory('/tmp/test');\n   *   await result.session.fileSystem.writeFile('/tmp/test/file1.py', \"print('hello')\");\n   *   const searchResult = await result.session.fileSystem.searchFiles('/tmp/test', '*.py');\n   *   console.log(`Found ${searchResult.matches.length} Python files`);\n   *   await result.session.delete();\n   * }\n   * ```\n   */\n  async searchFiles(\n    path: string,\n    pattern: string,\n    excludePatterns: string[] = []\n  ): Promise<FileSearchResult> {\n    try {\n      const args: any = {\n        path,\n        pattern,\n      };\n\n      if (excludePatterns.length > 0) {\n        args.excludePatterns = excludePatterns;\n      }\n\n      const result = await this.session.callMcpTool(\n        \"search_files\",\n        args,\n        false\n      );\n\n      if (!result.success) {\n        return {\n          requestId: result.requestId,\n          success: false,\n          matches: [],\n          errorMessage: result.errorMessage,\n        };\n      }\n\n      // Parse the text content into search results\n      let searchResults: string[] = [];\n      if (result.data) {\n        // Split by newlines and filter out empty lines\n        searchResults = result.data\n          .split(\"\\n\")\n          .map((line) => line.trim())\n          .filter((line) => line !== \"\");\n      }\n\n      return {\n        requestId: result.requestId,\n        success: true,\n        matches: searchResults,\n      };\n    } catch (error) {\n      return {\n        requestId: \"\",\n        success: false,\n        matches: [],\n        errorMessage: `Failed to search files: ${error}`,\n      };\n    }\n  }\n\n  /**\n   * Internal method to write a file chunk. Used for chunked file operations.\n   *\n   * @param path - Path to the file to write.\n   * @param content - Content to write to the file.\n   * @param mode - Optional: Write mode. One of \"overwrite\", \"append\", or \"create_new\". Default is \"overwrite\".\n   * @returns BoolResult with write result and requestId\n   */\n  private async writeFileChunk(\n    path: string,\n    content: string,\n    mode = \"overwrite\"\n  ): Promise<BoolResult> {\n    try {\n      // Validate mode\n      const validModes = [\"overwrite\", \"append\", \"create_new\"];\n      if (!validModes.includes(mode)) {\n        return {\n          requestId: \"\",\n          success: false,\n          errorMessage: `Invalid mode: ${mode}. Must be one of ${validModes.join(\n            \", \"\n          )}`,\n        };\n      }\n\n      const args = {\n        path,\n        content,\n        mode,\n      };\n\n      const result = await this.session.callMcpTool(\"write_file\", args, false);\n\n      if (!result.success) {\n        return {\n          requestId: result.requestId,\n          success: false,\n          errorMessage: result.errorMessage,\n        };\n      }\n\n      return {\n        requestId: result.requestId,\n        success: true,\n        data: true,\n      };\n    } catch (error) {\n      return {\n        requestId: \"\",\n        success: false,\n        errorMessage: `Failed to write file: ${error}`,\n      };\n    }\n  }\n\n  /**\n   * Reads the contents of a file. For MQTT channel, automatically handles large files by chunking.\n   * For HTTP LinkUrl channel, reads the entire file in a single call without chunking.\n   *\n   * @param path - Path to the file to read.\n   * @returns FileContentResult with complete file content and requestId\n   */\n  /**\n   * Reads the entire content of a file (text format, default).\n   *\n   * @param path - Absolute path to the file to read.\n   *\n   * @returns Promise resolving to FileContentResult containing:\n   *          - success: Whether the read operation succeeded\n   *          - content: String content of the file\n   *          - requestId: Unique identifier for this API request\n   *          - errorMessage: Error description if read failed\n   *\n   * @example\n   * ```typescript\n   * import { AgentBay } from 'wuying-agentbay-sdk';\n   *\n   * const agentBay = new AgentBay({ apiKey: 'your_api_key' });\n   * const result = await agentBay.create();\n   *\n   * if (result.success) {\n   *   const session = result.session;\n   *\n   *   // Read a text file (default)\n   *   const fileResult = await session.fileSystem.readFile('/etc/hostname');\n   *   if (fileResult.success) {\n   *     console.log(`Content: ${fileResult.content}`);\n   *   }\n   *\n   *   await session.delete();\n   * }\n   * ```\n   */\n  async readFile(path: string): Promise<FileContentResult>;\n  /**\n   * Reads the entire content of a file with explicit text format.\n   *\n   * @param path - Absolute path to the file to read.\n   * @param opts - Options object with format set to \"text\".\n   *\n   * @returns Promise resolving to FileContentResult containing:\n   *          - success: Whether the read operation succeeded\n   *          - content: String content of the file\n   *          - requestId: Unique identifier for this API request\n   *          - errorMessage: Error description if read failed\n   *\n   * @example\n   * ```typescript\n   * const fileResult = await session.fileSystem.readFile('/tmp/test.txt', { format: 'text' });\n   * ```\n   */\n  async readFile(\n    path: string,\n    opts: { format: \"text\" }\n  ): Promise<FileContentResult>;\n  /**\n   * Reads the entire content of a file in binary format.\n   *\n   * @param path - Absolute path to the file to read.\n   * @param opts - Options object with format set to \"bytes\".\n   *\n   * @returns Promise resolving to BinaryFileContentResult containing:\n   *          - success: Whether the read operation succeeded\n   *          - content: Uint8Array binary content of the file\n   *          - requestId: Unique identifier for this API request\n   *          - errorMessage: Error description if read failed\n   *          - contentType: Optional MIME type of the file\n   *          - size: Optional size of the file in bytes\n   *\n   * @example\n   * ```typescript\n   * import { AgentBay } from 'wuying-agentbay-sdk';\n   *\n   * const agentBay = new AgentBay({ apiKey: 'your_api_key' });\n   * const result = await agentBay.create();\n   *\n   * if (result.success) {\n   *   const session = result.session;\n   *\n   *   // Read a binary file\n   *   const binaryResult = await session.fileSystem.readFile('/tmp/image.png', { format: 'bytes' });\n   *   if (binaryResult.success) {\n   *     console.log(`File size: ${binaryResult.content.length} bytes`);\n   *   }\n   *\n   *   await session.delete();\n   * }\n   * ```\n   *\n   * @remarks\n   * **Behavior:**\n   * - For MQTT channel: automatically handles large files by reading in 60KB chunks\n   * - For HTTP LinkUrl channel: reads the entire file in a single call without chunking\n   * - Returns empty Uint8Array for empty files\n   * - Fails if path is a directory or doesn't exist\n   * - Content is returned as Uint8Array (backend uses base64 encoding internally)\n   */\n  async readFile(\n    path: string,\n    opts: { format: \"bytes\" }\n  ): Promise<BinaryFileContentResult>;\n  async readFile(\n    path: string,\n    opts?: { format?: \"text\" | \"bytes\" }\n  ): Promise<FileContentResult | BinaryFileContentResult> {\n    const format = opts?.format || \"text\";\n    const chunkSize = DEFAULT_CHUNK_SIZE;\n    try {\n      // HTTP (LinkUrl) channel: read entire file in a single call, no chunking needed\n      if (this.isUsingLinkUrl()) {\n        const formatType = format === \"bytes\" ? \"binary\" : \"text\";\n        return await this.readFileChunk(path, 0, 0, formatType);\n      }\n\n      // First get the file info\n      const fileInfoResult = await this.getFileInfo(path);\n\n      if (!fileInfoResult.success) {\n        if (format === \"bytes\") {\n          return {\n            requestId: fileInfoResult.requestId,\n            success: false,\n            content: new Uint8Array(0),\n            errorMessage: fileInfoResult.errorMessage,\n          };\n        } else {\n          return {\n            requestId: fileInfoResult.requestId,\n            success: false,\n            content: \"\",\n            errorMessage: fileInfoResult.errorMessage,\n          };\n        }\n      }\n\n      // Check if file exists and is a file (not a directory)\n      if (!fileInfoResult.fileInfo || fileInfoResult.fileInfo.isDirectory) {\n        const errorMsg = `Path does not exist or is a directory: ${path}`;\n        if (format === \"bytes\") {\n          return {\n            requestId: fileInfoResult.requestId,\n            success: false,\n            content: new Uint8Array(0),\n            errorMessage: errorMsg,\n          };\n        } else {\n          return {\n            requestId: fileInfoResult.requestId,\n            success: false,\n            content: \"\",\n            errorMessage: errorMsg,\n          };\n        }\n      }\n\n      // Get size from the fileInfo object\n      const fileSize = fileInfoResult.fileInfo.size || 0;\n\n      if (fileSize === 0) {\n        if (format === \"bytes\") {\n          return {\n            requestId: fileInfoResult.requestId,\n            success: true,\n            content: new Uint8Array(0),\n            size: 0,\n          };\n        } else {\n          return {\n            requestId: fileInfoResult.requestId,\n            success: true,\n            content: \"\",\n          };\n        }\n      }\n\n      if (format === \"bytes\") {\n        // Binary format: read chunks and combine as Uint8Array\n        const contentChunks: Uint8Array[] = [];\n        let offset = 0;\n        let chunkCount = 0;\n\n        while (offset < fileSize) {\n          // Calculate how much to read in this chunk\n          let length = chunkSize;\n          if (offset + length > fileSize) {\n            length = fileSize - offset;\n          }\n\n          try {\n            // Read the chunk\n            const chunkResult = await this.readFileChunk(\n              path,\n              offset,\n              length,\n              \"binary\"\n            );\n\n            if (!chunkResult.success) {\n              return chunkResult as BinaryFileContentResult; // Return the error\n            }\n\n            // chunkResult is BinaryFileContentResult for binary format\n            if (\n              \"content\" in chunkResult &&\n              chunkResult.content instanceof Uint8Array\n            ) {\n              contentChunks.push(chunkResult.content);\n            } else {\n              return {\n                requestId: chunkResult.requestId,\n                success: false,\n                content: new Uint8Array(0),\n                errorMessage: \"Unexpected result type for binary format\",\n              };\n            }\n\n            // Move to the next chunk\n            offset += length;\n            chunkCount++;\n          } catch (error) {\n            return {\n              requestId: fileInfoResult.requestId,\n              success: false,\n              content: new Uint8Array(0),\n              errorMessage: `Error reading chunk at offset ${offset}: ${error}`,\n            };\n          }\n        }\n\n        // Combine all binary chunks\n        const totalLength = contentChunks.reduce(\n          (sum, chunk) => sum + chunk.length,\n          0\n        );\n        const finalContent = new Uint8Array(totalLength);\n        let position = 0;\n        for (const chunk of contentChunks) {\n          finalContent.set(chunk, position);\n          position += chunk.length;\n        }\n\n        return {\n          requestId: fileInfoResult.requestId,\n          success: true,\n          content: finalContent,\n          size: finalContent.length,\n        };\n      } else {\n        // Text format (default)\n        let result = \"\";\n        let offset = 0;\n        let chunkCount = 0;\n\n        while (offset < fileSize) {\n          // Calculate how much to read in this chunk\n          let length = chunkSize;\n          if (offset + length > fileSize) {\n            length = fileSize - offset;\n          }\n\n          try {\n            // Read the chunk\n            const chunkResult = await this.readFileChunk(\n              path,\n              offset,\n              length,\n              \"text\"\n            );\n\n            if (!chunkResult.success) {\n              return chunkResult as FileContentResult; // Return the error\n            }\n\n            // Extract the actual content from the response\n            if (\n              \"content\" in chunkResult &&\n              typeof chunkResult.content === \"string\"\n            ) {\n              result += chunkResult.content;\n            } else {\n              return {\n                requestId: chunkResult.requestId,\n                success: false,\n                content: \"\",\n                errorMessage: \"Unexpected result type for text format\",\n              };\n            }\n\n            // Move to the next chunk\n            offset += length;\n            chunkCount++;\n          } catch (error) {\n            return {\n              requestId: fileInfoResult.requestId,\n              success: false,\n              content: \"\",\n              errorMessage: `Error reading chunk at offset ${offset}: ${error}`,\n            };\n          }\n        }\n\n        return {\n          requestId: fileInfoResult.requestId,\n          success: true,\n          content: result,\n        };\n      }\n    } catch (error) {\n      if (format === \"bytes\") {\n        return {\n          requestId: \"\",\n          success: false,\n          content: new Uint8Array(0),\n          errorMessage: `Failed to read large file: ${error}`,\n        };\n      } else {\n        return {\n          requestId: \"\",\n          success: false,\n          content: \"\",\n          errorMessage: `Failed to read large file: ${error}`,\n        };\n      }\n    }\n  }\n\n  /**\n   * Writes content to a file. For MQTT channel, automatically handles large files by chunking.\n   * For HTTP LinkUrl channel, writes the entire content in a single call without chunking.\n   *\n   * @param path - Path to the file to write.\n   * @param content - Content to write to the file.\n   * @param mode - Optional: Write mode. One of \"overwrite\", \"append\", or \"create_new\". Default is \"overwrite\".\n   * @returns BoolResult indicating success or failure with requestId\n   */\n  /**\n   * Writes content to a file.\n   *\n   * @param path - Absolute path to the file to write.\n   * @param content - String content to write to the file.\n   * @param mode - Write mode: \"overwrite\" (default) or \"append\".\n   *\n   * @returns Promise resolving to BoolResult with success status.\n   *\n   * @example\n   * ```typescript\n   * import { AgentBay } from 'wuying-agentbay-sdk';\n   *\n   * const agentBay = new AgentBay({ apiKey: 'your_api_key' });\n   * const result = await agentBay.create();\n   *\n   * if (result.success) {\n   *   const session = result.session;\n   *\n   *   // Write to a file (overwrite mode)\n   *   const writeResult = await session.fileSystem.writeFile(\n   *     '/tmp/test.txt',\n   *     'Hello, AgentBay!'\n   *   );\n   *   if (writeResult.success) {\n   *     console.log('File written successfully');\n   *   }\n   *\n   *   // Append to a file\n   *   const appendResult = await session.fileSystem.writeFile(\n   *     '/tmp/test.txt',\n   *     '\\nNew line',\n   *     'append'\n   *   );\n   *\n   *   await session.delete();\n   * }\n   * ```\n   *\n   * @remarks\n   * **Behavior:**\n   * - For MQTT channel: automatically handles large files by writing in 60KB chunks\n   * - For HTTP LinkUrl channel: writes the entire content in a single call without chunking\n   * - Creates parent directories if they don't exist\n   * - \"overwrite\" mode replaces existing file content\n   * - \"append\" mode adds content to the end of the file\n   *\n   * @see {@link readFile}, {@link listDirectory}\n   */\n  async writeFile(\n    path: string,\n    content: string,\n    mode = \"overwrite\"\n  ): Promise<BoolResult> {\n    const chunkSize = DEFAULT_CHUNK_SIZE;\n    try {\n      // HTTP (LinkUrl) channel: write entire content in a single call, no chunking needed\n      if (this.isUsingLinkUrl()) {\n        try {\n          return await this.writeFileChunk(path, content, mode);\n        } catch (error) {\n          return {\n            requestId: \"\",\n            success: false,\n            errorMessage: `Failed to write file: ${error}`,\n          };\n        }\n      }\n\n      const contentLen = content.length;\n\n      // If content is small enough, use the regular writeFileChunk method\n      if (contentLen <= chunkSize) {\n        return await this.writeFileChunk(path, content, mode);\n      }\n\n      // Write the first chunk with the specified mode\n      const firstChunkEnd = Math.min(chunkSize, contentLen);\n\n      const firstResult = await this.writeFileChunk(\n        path,\n        content.substring(0, firstChunkEnd),\n        mode\n      );\n\n      if (!firstResult.success) {\n        return firstResult;\n      }\n\n      // Write the remaining chunks with \"append\" mode\n      let chunkCount = 1; // Already wrote first chunk\n      for (let offset = firstChunkEnd; offset < contentLen; ) {\n        const end = Math.min(offset + chunkSize, contentLen);\n\n        const chunkResult = await this.writeFileChunk(\n          path,\n          content.substring(offset, end),\n          \"append\"\n        );\n\n        if (!chunkResult.success) {\n          return chunkResult;\n        }\n\n        offset = end;\n        chunkCount++;\n      }\n\n      return {\n        requestId: firstResult.requestId,\n        success: true,\n        data: true,\n      };\n    } catch (error) {\n      return {\n        requestId: \"\",\n        success: false,\n        errorMessage: `Failed to write large file: ${error}`,\n      };\n    }\n  }\n\n  /**\n   * Get file change information for the specified directory path\n   *\n   * @param path - Directory path to monitor\n   * @returns Promise resolving to result containing detected file changes\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: 'your_api_key' });\n   * const result = await agentBay.create();\n   * if (result.success) {\n   *   await result.session.fileSystem.createDirectory('/tmp/watch_dir');\n   *   const changeResult = await result.session.fileSystem.getFileChange('/tmp/watch_dir');\n   *   console.log(`Detected ${changeResult.events.length} changes`);\n   *   await result.session.delete();\n   * }\n   * ```\n   */\n  async getFileChange(path: string): Promise<FileChangeResult> {\n    try {\n      const args = { path };\n      const result = await this.session.callMcpTool(\n        \"get_file_change\",\n        args,\n        false\n      );\n\n      if (!result.success) {\n        return {\n          requestId: result.requestId,\n          success: false,\n          events: [],\n          rawData: result.data || \"\",\n          errorMessage: result.errorMessage,\n        };\n      }\n\n      // Parse the file change events\n      const events = this.parseFileChangeData(result.data);\n\n      return {\n        requestId: result.requestId,\n        success: true,\n        events,\n        rawData: result.data,\n      };\n    } catch (error) {\n      return {\n        requestId: \"\",\n        success: false,\n        events: [],\n        rawData: \"\",\n        errorMessage: `Failed to get file change: ${error}`,\n      };\n    }\n  }\n\n  /**\n   * Parse raw JSON data into FileChangeEvent array\n   */\n  private parseFileChangeData(rawData: string): FileChangeEvent[] {\n    const events: FileChangeEvent[] = [];\n\n    try {\n      const changeData = JSON.parse(rawData);\n      if (Array.isArray(changeData)) {\n        for (const eventDict of changeData) {\n          if (typeof eventDict === \"object\" && eventDict !== null) {\n            const event = FileChangeEventHelper.fromDict(eventDict);\n            events.push(event);\n          }\n        }\n      }\n    } catch (error) {\n      logWarn(`Failed to parse JSON data: ${error}`);\n    }\n\n    return events;\n  }\n\n  /**\n   * Watch a directory for file changes and call the callback function when changes occur.\n   *\n   * Uses WebSocket push notifications for near-real-time delivery when available,\n   * with automatic fallback to HTTP polling.\n   *\n   * @param path - Directory path to monitor\n   * @param callback - Function called when changes are detected\n   * @param interval - Polling interval in milliseconds (default: 500). Deprecated in WS push\n   *   mode where events are delivered in real time; retained for backward compatibility.\n   * @param signal - Signal to abort the monitoring\n   * @returns Object with `monitoring` promise (resolves when stopped) and `ready` promise\n   *   (resolves when baseline is established)\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: 'your_api_key' });\n   * const result = await agentBay.create();\n   * if (result.success) {\n   *   const testDir = '/tmp/watch_test';\n   *   await result.session.fileSystem.createDirectory(testDir);\n   *   const controller = new AbortController();\n   *   const callback = (events) => console.log(`Detected ${events.length} changes`);\n   *   const { ready } = result.session.fileSystem.watchDirectory(testDir, callback, 1000, controller.signal);\n   *   await ready; // wait for baseline to be established\n   *   await result.session.fileSystem.writeFile(`${testDir}/test.txt`, 'hello');\n   *   await result.session.delete();\n   * }\n   * ```\n   */\n  watchDirectory(\n    path: string,\n    callback: (events: FileChangeEvent[]) => void,\n    interval = 500,\n    signal?: AbortSignal\n  ): { monitoring: Promise<void>; ready: Promise<void> } {\n    logInfo(`Starting directory monitoring for: ${path}`);\n\n    let readyResolve!: () => void;\n    const ready = new Promise<void>((resolve) => {\n      readyResolve = resolve;\n    });\n\n    const serverName = this.session.getMcpServerForTool(\"get_file_change\");\n    const useWsPush = !!(\n      this.session.wsUrl &&\n      this.session.token &&\n      serverName\n    );\n\n    const monitoring = useWsPush\n      ? this.monitorWsPush(\n          path,\n          callback,\n          interval,\n          signal,\n          readyResolve,\n          serverName!\n        )\n      : this.monitorPolling(path, callback, interval, signal, readyResolve);\n\n    return { monitoring, ready };\n  }\n\n  private async monitorPolling(\n    path: string,\n    callback: (events: FileChangeEvent[]) => void,\n    interval: number,\n    signal: AbortSignal | undefined,\n    readyResolve: () => void\n  ): Promise<void> {\n    logInfo(`Starting polling directory monitoring for: ${path}`);\n    logInfo(`Polling interval: ${interval} ms`);\n\n    try {\n      await this.getFileChange(path);\n    } catch (error) {\n      logError(`Error establishing baseline: ${error}`);\n    }\n    readyResolve();\n\n    while (!signal?.aborted) {\n      await new Promise<void>((resolve) => {\n        const timeoutId = setTimeout(resolve, interval);\n        signal?.addEventListener(\"abort\", () => {\n          clearTimeout(timeoutId);\n          resolve();\n        });\n      });\n\n      if (signal?.aborted) break;\n\n      try {\n        if (\n          (this.session as any)._isExpired &&\n          (this.session as any)._isExpired()\n        ) {\n          logInfo(\n            `Session expired, stopping directory monitoring for: ${path}`\n          );\n          break;\n        }\n\n        const result = await this.getFileChange(path);\n\n        if (result.success && result.events.length > 0) {\n          logInfo(`Detected ${result.events.length} file changes:`);\n          for (const event of result.events) {\n            logInfo(`  - ${FileChangeEventHelper.toString(event)}`);\n          }\n          try {\n            callback(result.events);\n          } catch (error) {\n            logError(`Error in callback function: ${error}`);\n          }\n        } else if (!result.success) {\n          const errorMsg = (result.errorMessage || \"\").toLowerCase();\n          if (\n            errorMsg.includes(\"session\") &&\n            (errorMsg.includes(\"expired\") || errorMsg.includes(\"invalid\"))\n          ) {\n            logInfo(\n              `Session expired, stopping directory monitoring for: ${path}`\n            );\n            break;\n          }\n          logError(`Error monitoring directory: ${result.errorMessage}`);\n        }\n      } catch (error) {\n        logError(`Unexpected error in directory monitoring: ${error}`);\n        const errorStr = String(error).toLowerCase();\n        if (\n          errorStr.includes(\"session\") &&\n          (errorStr.includes(\"expired\") || errorStr.includes(\"invalid\"))\n        ) {\n          logInfo(\n            `Session expired, stopping directory monitoring for: ${path}`\n          );\n          break;\n        }\n      }\n    }\n\n    logInfo(`Stopped polling monitoring for: ${path}`);\n  }\n\n  private async monitorWsPush(\n    path: string,\n    callback: (events: FileChangeEvent[]) => void,\n    interval: number,\n    signal: AbortSignal | undefined,\n    readyResolve: () => void,\n    serverName: string\n  ): Promise<void> {\n    logInfo(`Starting WS push monitoring for: ${path}`);\n    const { WsConnectionState } = await import(\"../_internal/ws-client\");\n\n    // Phase 1: HTTP baseline\n    try {\n      await this.getFileChange(path);\n    } catch (error) {\n      logError(`Error establishing baseline: ${error}`);\n    }\n    readyResolve();\n    logInfo(`WS push: baseline established for: ${path}`);\n\n    // Phase 2: Attach to session's shared WsClient\n    let unsubscribePush: (() => void) | null = null;\n    let unsubscribeState: (() => void) | null = null;\n    let subscriptionActive = false;\n\n    try {\n      const wsClient = await this.session.getWsClient();\n\n      const onPush = (payload: { data: Record<string, any> }) => {\n        const data = payload.data || {};\n        if (data.eventType !== \"file_change\") return;\n        if (data.path !== path) return;\n        const eventsRaw = data.events || [];\n        const events: FileChangeEvent[] = [];\n        for (const ed of eventsRaw) {\n          if (ed && typeof ed === \"object\") {\n            events.push(FileChangeEventHelper.fromDict(ed));\n          }\n        }\n        if (events.length > 0) {\n          logInfo(`WS push: ${events.length} file changes for ${path}`);\n          try {\n            callback(events);\n          } catch (error) {\n            logError(`Error in watch callback: ${error}`);\n          }\n        }\n      };\n\n      unsubscribePush = wsClient.registerCallback(serverName, onPush);\n\n      unsubscribeState = wsClient.onConnectionStateChange(\n        (state: string, _reason: string) => {\n          if (state !== WsConnectionState.OPEN) return;\n          if (!subscriptionActive || signal?.aborted) return;\n\n          (async () => {\n            try {\n              const catchUpResult = await this.getFileChange(path);\n              if (catchUpResult.success && catchUpResult.events.length > 0) {\n                try {\n                  callback(catchUpResult.events);\n                } catch (error) {\n                  logError(`Catch-up callback error: ${error}`);\n                }\n              }\n              const handle = await wsClient.callStream({\n                target: serverName,\n                data: {\n                  method: \"subscribe_file_change\",\n                  params: { path },\n                },\n              });\n              await withTimeout(handle.waitEnd(), 10_000);\n              logInfo(`Resubscribed after reconnect for: ${path}`);\n            } catch (error) {\n              logError(`Catch-up/resubscribe failed: ${error}`);\n            }\n          })();\n        }\n      );\n\n      // Subscribe via WsClient\n      const handle = await wsClient.callStream({\n        target: serverName,\n        data: {\n          method: \"subscribe_file_change\",\n          params: { path },\n        },\n      });\n      await withTimeout(handle.waitEnd(), 15_000);\n      subscriptionActive = true;\n\n      // Catch-up poll: fill the gap between baseline and subscribe\n      const catchup = await this.getFileChange(path);\n      if (catchup.success && catchup.events.length > 0) {\n        try {\n          callback(catchup.events);\n        } catch (error) {\n          logError(`Catch-up callback error: ${error}`);\n        }\n      }\n\n      logInfo(`WS push monitoring active for: ${path}`);\n\n      // Wait loop\n      while (!signal?.aborted) {\n        if (\n          (this.session as any)._isExpired &&\n          (this.session as any)._isExpired()\n        ) {\n          logInfo(`Session expired, stopping WS monitoring for: ${path}`);\n          break;\n        }\n        await new Promise<void>((resolve) => {\n          const timeoutId = setTimeout(resolve, 1000);\n          signal?.addEventListener(\"abort\", () => {\n            clearTimeout(timeoutId);\n            resolve();\n          });\n        });\n      }\n    } catch (error) {\n      logWarn(`WS push subscribe failed: ${error}. Falling back to polling.`);\n      if (unsubscribePush) {\n        try {\n          unsubscribePush();\n        } catch (_e) {\n          /* */\n        }\n      }\n      if (unsubscribeState) {\n        try {\n          unsubscribeState();\n        } catch (_e) {\n          /* */\n        }\n      }\n      await this.monitorPollingAfterBaseline(path, callback, interval, signal);\n      return;\n    }\n\n    // Normal cleanup\n    subscriptionActive = false;\n    if (unsubscribePush) {\n      try {\n        unsubscribePush();\n      } catch (_e) {\n        /* */\n      }\n    }\n    if (unsubscribeState) {\n      try {\n        unsubscribeState();\n      } catch (_e) {\n        /* */\n      }\n    }\n    try {\n      const wsClient = await this.session.getWsClient();\n      await wsClient.sendMessage(serverName, {\n        method: \"unsubscribe_file_change\",\n        params: { path },\n      });\n    } catch (_e) {\n      /* best effort */\n    }\n    logInfo(`Stopped WS push monitoring for: ${path}`);\n  }\n\n  private async monitorPollingAfterBaseline(\n    path: string,\n    callback: (events: FileChangeEvent[]) => void,\n    interval: number,\n    signal: AbortSignal | undefined\n  ): Promise<void> {\n    logInfo(`Polling fallback (baseline pre-established) for: ${path}`);\n    while (!signal?.aborted) {\n      await new Promise<void>((resolve) => {\n        const timeoutId = setTimeout(resolve, interval);\n        signal?.addEventListener(\"abort\", () => {\n          clearTimeout(timeoutId);\n          resolve();\n        });\n      });\n      if (signal?.aborted) break;\n      try {\n        if (\n          (this.session as any)._isExpired &&\n          (this.session as any)._isExpired()\n        ) {\n          break;\n        }\n        const result = await this.getFileChange(path);\n        if (result.success && result.events.length > 0) {\n          try {\n            callback(result.events);\n          } catch (error) {\n            logError(`Error in callback: ${error}`);\n          }\n        } else if (!result.success) {\n          const errorMsg = (result.errorMessage || \"\").toLowerCase();\n          if (\n            errorMsg.includes(\"session\") &&\n            (errorMsg.includes(\"expired\") || errorMsg.includes(\"invalid\"))\n          ) {\n            break;\n          }\n        }\n      } catch (error) {\n        logError(`Polling error: ${error}`);\n      }\n    }\n    logInfo(`Stopped polling for: ${path}`);\n  }\n\n  /**\n   * Upload a file from local to remote path using pre-signed URLs.\n   * This is a synchronous wrapper around the FileTransfer.upload method.\n   *\n   * @param localPath - Local file path to upload\n   * @param remotePath - Remote file path to upload to\n   * @param options - Optional parameters\n   * @returns UploadResult with upload result and requestId\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: 'your_api_key' });\n   * const result = await agentBay.create({ imageId: 'code_latest' });\n   * if (result.success) {\n   *   const uploadResult = await result.session.fileSystem.uploadFile('/tmp/local.txt', '/workspace/remote.txt');\n   *   console.log('Upload success:', uploadResult.success);\n   *   await result.session.delete();\n   * }\n   * ```\n   */\n  async uploadFile(\n    localPath: string,\n    remotePath: string,\n    options?: {\n      contentType?: string;\n      wait?: boolean;\n      waitTimeout?: number;\n      pollInterval?: number;\n      progressCb?: (bytesTransferred: number) => void;\n    }\n  ): Promise<any> {\n    try {\n      // Ensure FileTransfer is initialized\n      const fileTransfer = this._ensureFileTransfer();\n\n      // Perform upload\n      const result = await fileTransfer.upload(localPath, remotePath, options);\n\n      // If upload was successful, delete the file from OSS\n      if (result.success) {\n        const contextId = (fileTransfer as any).contextId;\n        if (contextId) {\n          try {\n            // Delete the uploaded file from OSS\n            const deleteResult = await (\n              this.session as any\n            ).agentBay.context.deleteFile(contextId, remotePath);\n            if (!deleteResult.success) {\n              logWarn(\n                `Warning: Failed to delete uploaded file from OSS: ${deleteResult}`\n              );\n            }\n          } catch (deleteError: any) {\n            logWarn(\n              `Warning: Error deleting uploaded file from OSS: ${deleteError}`\n            );\n          }\n        }\n      }\n\n      return result;\n    } catch (error) {\n      return {\n        success: false,\n        bytesSent: 0,\n        path: remotePath,\n        error: `Upload failed: ${error}`,\n      };\n    }\n  }\n\n  /**\n   * Download a file from remote path to local path using pre-signed URLs.\n   * This is a synchronous wrapper around the FileTransfer.download method.\n   *\n   * @param remotePath - Remote file path to download from\n   * @param localPath - Local file path to download to\n   * @param options - Optional parameters\n   * @returns DownloadResult with download result and requestId\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: 'your_api_key' });\n   * const result = await agentBay.create({ imageId: 'code_latest' });\n   * if (result.success) {\n   *   await result.session.fileSystem.writeFile('/workspace/remote.txt', 'Content to download');\n   *   const downloadResult = await result.session.fileSystem.downloadFile('/workspace/remote.txt', '/tmp/local.txt');\n   *   console.log('Download success:', downloadResult.success);\n   *   await result.session.delete();\n   * }\n   * ```\n   */\n  async downloadFile(\n    remotePath: string,\n    localPath: string,\n    options?: {\n      overwrite?: boolean;\n      wait?: boolean;\n      waitTimeout?: number;\n      pollInterval?: number;\n      progressCb?: (bytesReceived: number) => void;\n    }\n  ): Promise<any> {\n    try {\n      // Ensure FileTransfer is initialized\n      const fileTransfer = this._ensureFileTransfer();\n\n      // Perform download\n      const result = await fileTransfer.download(\n        remotePath,\n        localPath,\n        options\n      );\n      // If download was successful, delete the file from OSS\n      if (result.success) {\n        const contextId = (fileTransfer as any).contextId;\n        if (contextId) {\n          try {\n            // Delete the downloaded file from OSS\n            const deleteResult = await (\n              this.session as any\n            ).agentBay.context.deleteFile(contextId, remotePath);\n            if (!deleteResult.success) {\n              logWarn(\n                `Warning: Failed to delete downloaded file from OSS: ${deleteResult}`\n              );\n            }\n          } catch (deleteError: any) {\n            logWarn(\n              `Warning: Error deleting downloaded file from OSS: ${deleteError}`\n            );\n          }\n        }\n      }\n\n      return result;\n    } catch (error) {\n      return {\n        success: false,\n        bytesReceived: 0,\n        path: remotePath,\n        localPath,\n        error: `Download failed: ${error}`,\n      };\n    }\n  }\n}\n","import { AgentBay } from \"../agent-bay\";\nimport { Session } from \"../session\";\nimport { ContextService } from \"../context\";\nimport { FileUrlResult, OperationResult } from \"../types/api-response\";\nimport * as fs from \"fs\";\nimport * as path from \"path\";\nimport fetch from \"node-fetch\";\nimport { log, logDebug, logError, logInfo } from \"../utils/logger\";\nimport { GetAndLoadInternalContextRequest } from \"../api/models/GetAndLoadInternalContextRequest\";\n\n/**\n * Result structure for file upload operations.\n */\nexport interface UploadResult {\n  /** Whether the upload was successful */\n  success: boolean;\n  /** Request ID for getting the upload URL */\n  requestIdUploadUrl?: string;\n  /** Request ID for sync operation */\n  requestIdSync?: string;\n  /** HTTP status code */\n  httpStatus?: number;\n  /** ETag of the uploaded file */\n  etag?: string;\n  /** Number of bytes sent */\n  bytesSent: number;\n  /** Remote file path */\n  path: string;\n  /** Error message if upload failed */\n  error?: string;\n}\n\n/**\n * Result structure for file download operations.\n */\nexport interface DownloadResult {\n  /** Whether the download was successful */\n  success: boolean;\n  /** Request ID for getting the download URL */\n  requestIdDownloadUrl?: string;\n  /** Request ID for sync operation */\n  requestIdSync?: string;\n  /** HTTP status code */\n  httpStatus?: number;\n  /** Number of bytes received */\n  bytesReceived: number;\n  /** Remote file path */\n  path: string;\n  /** Local file path where file was saved */\n  localPath: string;\n  /** Error message if download failed */\n  error?: string;\n}\n\n/**\n * FileTransfer provides pre-signed URL upload/download functionality between local and OSS,\n * with integration to Session Context synchronization.\n *\n * Prerequisites and Constraints:\n * - Session must be associated with the corresponding context_id and path through\n *   CreateSessionParams.contextSyncs, and remotePath should fall within that\n *   synchronization path (or conform to backend path rules).\n * - Requires available AgentBay context service (agentBay.context) and session context.\n */\nexport class FileTransfer {\n  private agentBay: AgentBay;\n  private contextSvc: ContextService;\n  private session: Session;\n  private httpTimeout: number;\n  private followRedirects: boolean;\n  private contextId: string;\n  private contextPath: string | null = null;\n\n  // Task completion states (for compatibility)\n  private finishedStates = new Set([\n    \"success\",\n    \"successful\",\n    \"ok\",\n    \"finished\",\n    \"done\",\n    \"completed\",\n    \"complete\",\n  ]);\n\n  /**\n   * Initialize FileTransfer with AgentBay client and session.\n   *\n   * @param agentBay - AgentBay instance for context service access\n   * @param session - Created session object for context operations\n   * @param httpTimeout - HTTP request timeout in seconds (default: 60.0)\n   * @param followRedirects - Whether to follow HTTP redirects (default: true)\n   */\n  constructor(\n    agentBay: AgentBay,\n    session: Session,\n    httpTimeout = 60.0,\n    followRedirects = true\n  ) {\n    this.agentBay = agentBay;\n    this.contextSvc = agentBay.context;\n    this.session = session;\n    this.httpTimeout = httpTimeout;\n    this.followRedirects = followRedirects;\n    this.contextId = \"\";\n  }\n\n  /**\n   * Get the current context ID.\n   * @returns The context ID, or empty string if not yet loaded\n   */\n  getContextId(): string {\n    return this.contextId;\n  }\n\n  /**\n   * Ensure the file transfer context id is set by calling GetAndLoadInternalContext with SessionId and ContextTypes=[\"file_transfer\"].\n   * Returns [success: boolean, errorMessage: string] tuple.\n   */\n  private async ensureContextId(): Promise<[boolean, string]> {\n    if (this.contextId) {\n      return [true, \"\"];\n    }\n\n    try {\n      const sid = this.session.getSessionId();\n      if (!sid) return [false, \"No session ID\"];\n\n      // Try to use GetAndLoadInternalContext API if available\n      const client = this.agentBay.getClient();\n      let response: any;\n\n      // Check if getAndLoadInternalContext method exists\n      try {\n        const req: any = new GetAndLoadInternalContextRequest({\n          authorization: `Bearer ${this.agentBay.getAPIKey()}`,\n          sessionId: sid,\n          contextTypes: [\"file_transfer\"],\n        });\n        response = await client.getAndLoadInternalContext(req);\n      } catch (e: any) {\n        logError(`getAndLoadInternalContext error:${e}`);\n        return [false, e?.message || String(e)];\n      }\n\n      const body = response && response.body ? response.body : {};\n\n      // Check for API-level errors\n      if (body.Success === false && body.Code) {\n        return [false, body.Message || \"Unknown error\"];\n      }\n\n      // Extract context_id and context_path from response\n      const data = body.Data || body.data;\n      if (Array.isArray(data) && data.length > 0) {\n        for (const item of data) {\n          if (item && typeof item === \"object\") {\n            const context_id = item.ContextId || item.contextId;\n            const context_path = item.ContextPath || item.contextPath;\n            if (context_id && context_path) {\n              this.contextId = context_id;\n              this.contextPath = context_path;\n              return [true, \"\"];\n            }\n          }\n        }\n      }\n\n      return [false, \"Response contains no data\"];\n    } catch (e: any) {\n      return [false, e?.message || String(e)];\n    }\n  }\n\n  /**\n   * Upload workflow:\n   * 1) Get OSS pre-signed URL via context.getFileUploadUrl\n   * 2) Upload local file to OSS using the URL (HTTP PUT)\n   * 3) Trigger session.context.sync(mode=\"download\") to sync OSS objects to cloud disk\n   * 4) If wait=true, poll session.context.info until upload task reaches completion or timeout\n   *\n   * Returns UploadResult containing request_ids, HTTP status, ETag and other information.\n   */\n  async upload(\n    localPath: string,\n    remotePath: string,\n    options?: {\n      contentType?: string;\n      wait?: boolean;\n      waitTimeout?: number;\n      pollInterval?: number;\n      progressCb?: (bytesTransferred: number) => void;\n    }\n  ): Promise<UploadResult> {\n    const {\n      contentType = null,\n      wait = true,\n      waitTimeout = 30.0,\n      pollInterval = 1.5,\n      progressCb = undefined,\n    } = options || {};\n\n    try {\n      // 0. Parameter validation\n      if (!fs.existsSync(localPath)) {\n        return {\n          success: false,\n          bytesSent: 0,\n          path: remotePath,\n          error: `Local file not found: ${localPath}`,\n        };\n      }\n\n      // Try to ensure context id is available (lazy-load)\n      if (!this.contextId) {\n        const [success, errorMsg] = await this.ensureContextId();\n        if (!success) {\n          return {\n            success: false,\n            bytesSent: 0,\n            path: remotePath,\n            error: errorMsg || \"No context ID\",\n          };\n        }\n      }\n\n      // 1. Get pre-signed upload URL\n      const urlRes = await this.contextSvc.getFileUploadUrl(\n        this.contextId,\n        remotePath\n      );\n      if (!urlRes.success || !urlRes.url) {\n        return {\n          success: false,\n          requestIdUploadUrl: urlRes.requestId,\n          bytesSent: 0,\n          path: remotePath,\n          error: `getFileUploadUrl failed: ${urlRes.url || \"unknown error\"}`,\n        };\n      }\n\n      const uploadUrl = urlRes.url;\n      const reqIdUpload = urlRes.requestId;\n\n      logDebug(`Uploading ${localPath} to ${uploadUrl}`);\n\n      // 2. PUT upload to pre-signed URL\n      try {\n        const { httpStatus, etag, bytesSent } = await this.putFile(\n          uploadUrl,\n          localPath,\n          contentType,\n          progressCb\n        );\n\n        logInfo(`Upload completed with HTTP ${httpStatus}`);\n        if (httpStatus && ![200, 201, 204].includes(httpStatus)) {\n          return {\n            success: false,\n            requestIdUploadUrl: reqIdUpload,\n            httpStatus,\n            etag,\n            bytesSent,\n            path: remotePath,\n            error: `Upload failed with HTTP ${httpStatus}`,\n          };\n        }\n      } catch (e: any) {\n        return {\n          success: false,\n          requestIdUploadUrl: reqIdUpload,\n          bytesSent: 0,\n          path: remotePath,\n          error: `Upload exception: ${e.message || e}`,\n        };\n      }\n\n      // 3. Trigger sync to cloud disk (download mode), download from oss to cloud disk\n      let reqIdSync: string | undefined;\n      try {\n        logDebug(\"Triggering sync to cloud disk\");\n        reqIdSync = await this.awaitSync(\n          \"download\",\n          remotePath,\n          this.contextId\n        );\n      } catch (e: any) {\n        return {\n          success: false,\n          requestIdUploadUrl: reqIdUpload,\n          requestIdSync: reqIdSync,\n          httpStatus: 200, // Assuming previous step succeeded\n          etag: \"\", // Assuming previous step succeeded\n          bytesSent: fs.statSync(localPath).size, // Assuming previous step succeeded\n          path: remotePath,\n          error: `session.context.sync(upload) failed: ${e.message || e}`,\n        };\n      }\n\n      logInfo(`Sync request ID: ${reqIdSync}`);\n\n      // 4. Optionally wait for task completion\n      if (wait) {\n        const { success, error } = await this.waitForTask({\n          contextId: this.contextId,\n          remotePath,\n          taskType: \"download\",\n          timeout: waitTimeout,\n          interval: pollInterval,\n        });\n\n        if (!success) {\n          return {\n            success: false,\n            requestIdUploadUrl: reqIdUpload,\n            requestIdSync: reqIdSync,\n            httpStatus: 200, // Assuming previous step succeeded\n            etag: \"\", // Assuming previous step succeeded\n            bytesSent: fs.statSync(localPath).size, // Assuming previous step succeeded\n            path: remotePath,\n            error: `Upload sync not finished: ${error || \"timeout or unknown\"}`,\n          };\n        }\n      }\n\n      return {\n        success: true,\n        requestIdUploadUrl: reqIdUpload,\n        requestIdSync: reqIdSync,\n        httpStatus: 200,\n        etag: \"\",\n        bytesSent: fs.statSync(localPath).size,\n        path: remotePath,\n      };\n    } catch (e: any) {\n      return {\n        success: false,\n        bytesSent: 0,\n        path: remotePath,\n        error: `Upload failed: ${e.message || e}`,\n      };\n    }\n  }\n\n  /**\n   * Download workflow:\n   * 1) Trigger session.context.sync(mode=\"upload\") to sync cloud disk data to OSS\n   * 2) Get pre-signed download URL via context.getFileDownloadUrl\n   * 3) Download the file and save to local localPath\n   * 4) If wait=true, wait for download task to reach completion after step 1\n   *    (ensuring backend has prepared the download object)\n   *\n   * Returns DownloadResult containing sync and download request_ids, HTTP status, byte count, etc.\n   */\n  async download(\n    remotePath: string,\n    localPath: string,\n    options?: {\n      overwrite?: boolean;\n      wait?: boolean;\n      waitTimeout?: number;\n      pollInterval?: number;\n      progressCb?: (bytesReceived: number) => void;\n    }\n  ): Promise<DownloadResult> {\n    const {\n      overwrite = true,\n      wait = true,\n      waitTimeout = 30.0,\n      pollInterval = 1.5,\n      progressCb = undefined,\n    } = options || {};\n\n    try {\n      // Try to ensure context id is available (lazy-load)\n      if (!this.contextId) {\n        const [success, errorMsg] = await this.ensureContextId();\n        if (!success) {\n          return {\n            success: false,\n            bytesReceived: 0,\n            path: remotePath,\n            localPath,\n            error: errorMsg || \"No context ID\",\n          };\n        }\n      }\n\n      // 1. Trigger cloud disk to OSS download sync\n      let reqIdSync: string | undefined;\n      try {\n        reqIdSync = await this.awaitSync(\"upload\", remotePath, this.contextId);\n      } catch (e: any) {\n        return {\n          success: false,\n          requestIdSync: reqIdSync,\n          bytesReceived: 0,\n          path: remotePath,\n          localPath,\n          error: `session.context.sync(download) failed: ${e.message || e}`,\n        };\n      }\n\n      // Optionally wait for task completion (ensure object is ready in OSS)\n      if (wait) {\n        const { success, error } = await this.waitForTask({\n          contextId: this.contextId,\n          remotePath,\n          taskType: \"upload\",\n          timeout: waitTimeout,\n          interval: pollInterval,\n        });\n\n        if (!success) {\n          return {\n            success: false,\n            requestIdSync: reqIdSync,\n            bytesReceived: 0,\n            path: remotePath,\n            localPath,\n            error: `Download sync not finished: ${\n              error || \"timeout or unknown\"\n            }`,\n          };\n        }\n      }\n\n      // 2. Get pre-signed download URL\n      const urlRes = await this.contextSvc.getFileDownloadUrl(\n        this.contextId,\n        remotePath\n      );\n      if (!urlRes.success || !urlRes.url) {\n        return {\n          success: false,\n          requestIdDownloadUrl: urlRes.requestId,\n          requestIdSync: reqIdSync,\n          bytesReceived: 0,\n          path: remotePath,\n          localPath,\n          error: `getFileDownloadUrl failed: ${urlRes.url || \"unknown error\"}`,\n        };\n      }\n\n      const downloadUrl = urlRes.url;\n      const reqIdDownload = urlRes.requestId;\n\n      // 3. Download and save to local\n      try {\n        // Ensure directory exists\n        const dir = path.dirname(localPath);\n        if (!fs.existsSync(dir)) {\n          fs.mkdirSync(dir, { recursive: true });\n        }\n\n        if (fs.existsSync(localPath) && !overwrite) {\n          return {\n            success: false,\n            requestIdDownloadUrl: reqIdDownload,\n            requestIdSync: reqIdSync,\n            bytesReceived: 0,\n            path: remotePath,\n            localPath,\n            error: `Destination exists and overwrite=false: ${localPath}`,\n          };\n        }\n\n        const bytesReceived = await this.getFile(\n          downloadUrl,\n          localPath,\n          progressCb\n        );\n\n        if (fs.existsSync(localPath)) {\n          return {\n            success: true,\n            requestIdDownloadUrl: reqIdDownload,\n            requestIdSync: reqIdSync,\n            httpStatus: 200,\n            bytesReceived: fs.statSync(localPath).size,\n            path: remotePath,\n            localPath,\n          };\n        } else {\n          return {\n            success: false,\n            requestIdDownloadUrl: reqIdDownload,\n            requestIdSync: reqIdSync,\n            bytesReceived,\n            path: remotePath,\n            localPath,\n            error: \"Download completed but file not found\",\n          };\n        }\n      } catch (e: any) {\n        return {\n          success: false,\n          requestIdDownloadUrl: reqIdDownload,\n          requestIdSync: reqIdSync,\n          bytesReceived: 0,\n          path: remotePath,\n          localPath,\n          error: `Download exception: ${e.message || e}`,\n        };\n      }\n    } catch (e: any) {\n      return {\n        success: false,\n        bytesReceived: 0,\n        path: remotePath,\n        localPath,\n        error: `Download failed: ${e.message || e}`,\n      };\n    }\n  }\n\n  // ========== Internal Utilities ==========\n\n  /**\n   * Compatibility wrapper for session.context.sync which may be sync or async:\n   * - Try async call first\n   * - Fall back to sync call\n   * Returns request_id if available\n   */\n  private async awaitSync(\n    mode: string,\n    remotePath = \"\",\n    contextId = \"\"\n  ): Promise<string | undefined> {\n    mode = mode.toLowerCase().trim();\n\n    // Check if session has context property\n    if (!this.session.context) {\n      throw new Error(\"Session does not have context property\");\n    }\n\n    const syncFn = this.session.context.sync.bind(this.session.context);\n    logDebug(\n      `session.context.sync(mode=${mode}, path=${remotePath}, contextId=${contextId})`\n    );\n\n    // Try calling with all parameters\n    try {\n      const result = await syncFn(\n        contextId || undefined,\n        remotePath || undefined,\n        mode\n      );\n      logDebug(`   Result: ${result.success}`);\n      return result.requestId;\n    } catch (e1) {\n      // Backend may not support all parameters, try with mode and path only\n      try {\n        const result = await syncFn(undefined, remotePath || undefined, mode);\n        logDebug(`   Result: ${result.success}`);\n        return result.requestId;\n      } catch (e2) {\n        // Backend may not support mode or path parameter\n        try {\n          const result = await syncFn(undefined, undefined, mode);\n          logDebug(`   Result: ${result.success}`);\n          return result.requestId;\n        } catch (e3) {\n          // Backend may not support mode parameter\n          const result = await syncFn();\n          logDebug(`   Result: ${result.success}`);\n          return result.requestId;\n        }\n      }\n    }\n  }\n\n  /**\n   * Poll session.context.info within timeout to check if specified task is completed.\n   * Returns { success, error } object.\n   */\n  private async waitForTask(options: {\n    contextId: string;\n    remotePath: string;\n    taskType?: string;\n    timeout: number;\n    interval: number;\n  }): Promise<{ success: boolean; error?: string }> {\n    const { contextId, remotePath, taskType, timeout, interval } = options;\n    const deadline = Date.now() + timeout * 1000;\n    let lastErr: string | null = null;\n\n    while (Date.now() < deadline) {\n      try {\n        // Check if session has context property\n        if (!this.session.context) {\n          throw new Error(\"Session does not have context property\");\n        }\n\n        const infoFn = this.session.context.infoWithParams.bind(\n          this.session.context\n        );\n        // Try calling with filter parameters\n        let res;\n        try {\n          res = await infoFn(contextId, remotePath, taskType);\n        } catch (e1) {\n          try {\n            res = await infoFn();\n          } catch (e2) {\n            // If all attempts fail, re-throw the last error\n            throw e2;\n          }\n        }\n\n        // Parse response\n        const statusList = res.contextStatusData || [];\n        for (const item of statusList) {\n          const cid = item.contextId;\n          const path = item.path;\n          const ttype = item.taskType;\n          const status = item.status;\n          const err = item.errorMessage;\n\n          if (\n            cid === contextId &&\n            path === remotePath &&\n            (taskType === undefined || ttype === taskType)\n          ) {\n            if (err) {\n              return { success: false, error: `Task error: ${err}` };\n            }\n            if (status && this.finishedStates.has(status.toLowerCase())) {\n              return { success: true };\n            }\n            // Otherwise continue waiting\n          }\n        }\n        lastErr = \"task not finished\";\n      } catch (e: any) {\n        lastErr = `info error: ${e.message || e}`;\n      }\n\n      // Wait before next poll\n      await new Promise((resolve) => setTimeout(resolve, interval * 1000));\n    }\n\n    return { success: false, error: lastErr || \"timeout\" };\n  }\n\n  /**\n   * Synchronously PUT file using node-fetch.\n   * Returns { status, etag, bytesSent }\n   */\n  private async putFile(\n    url: string,\n    filePath: string,\n    contentType: string | null,\n    progressCb?: (bytesTransferred: number) => void\n  ): Promise<{ httpStatus: number; etag?: string; bytesSent: number }> {\n    const headers: Record<string, string> = {};\n    if (contentType) {\n      headers[\"Content-Type\"] = contentType;\n    }\n\n    const fileBuffer = fs.readFileSync(filePath);\n    const response = await fetch(url, {\n      method: \"PUT\",\n      body: fileBuffer,\n      headers,\n    });\n\n    const status = response.status;\n    const etag = response.headers.get(\"ETag\") || undefined;\n    const bytesSent = fileBuffer.length;\n\n    if (progressCb) {\n      progressCb(bytesSent);\n    }\n\n    return { httpStatus: status, etag, bytesSent };\n  }\n\n  /**\n   * Synchronously GET download to local file using node-fetch.\n   * Returns bytesReceived\n   */\n  private async getFile(\n    url: string,\n    destPath: string,\n    progressCb?: (bytesReceived: number) => void\n  ): Promise<number> {\n    let bytesReceived = 0;\n\n    const response = await fetch(url);\n    const status = response.status;\n\n    if (status !== 200) {\n      throw new Error(`HTTP ${status}`);\n    }\n\n    const buffer = await response.buffer();\n    bytesReceived = buffer.length;\n\n    // Save to file\n    fs.writeFileSync(destPath, buffer);\n\n    if (progressCb) {\n      progressCb(bytesReceived);\n    }\n\n    return bytesReceived;\n  }\n}\n","export { Git } from \"./git\";\nexport {\n  GitError,\n  GitAuthError,\n  GitNotFoundError,\n  GitConflictError,\n  GitNotARepoError,\n} from \"./errors\";\nexport {\n  type GitCloneOpts,\n  type GitCloneResult,\n  type GitInitOpts,\n  type GitInitResult,\n  type GitAddOpts,\n  type GitCommitOpts,\n  type GitCommitResult,\n  type GitStatusOpts,\n  type GitFileStatus,\n  type GitStatusResult,\n  type GitLogOpts,\n  type GitLogEntry,\n  type GitLogResult,\n  type GitBranchListOpts,\n  type GitBranchInfo,\n  type GitBranchListResult,\n  type GitBranchCreateOpts,\n  type GitBranchDeleteOpts,\n  type GitCheckoutOpts,\n  type GitRemoteAddOpts,\n  type GitResetMode,\n  type GitResetOpts,\n  type GitRestoreOpts,\n  type GitPullOpts,\n  type GitConfigScope,\n  type GitConfigOpts,\n} from \"./types\";\n","import { Session } from \"../session\";\nimport { CommandResult } from \"../types/api-response\";\nimport {\n  GitError,\n  GitAuthError,\n  GitNotFoundError,\n  GitConflictError,\n  GitNotARepoError,\n} from \"./errors\";\nimport {\n  GitCloneOpts,\n  GitCloneResult,\n  GitInitOpts,\n  GitInitResult,\n  GitAddOpts,\n  GitCommitOpts,\n  GitCommitResult,\n  GitStatusOpts,\n  GitFileStatus,\n  GitStatusResult,\n  GitLogOpts,\n  GitLogEntry,\n  GitLogResult,\n  GitBranchListOpts,\n  GitBranchInfo,\n  GitBranchListResult,\n  GitBranchCreateOpts,\n  GitBranchDeleteOpts,\n  GitCheckoutOpts,\n  GitRemoteAddOpts,\n  GitResetOpts,\n  GitRestoreOpts,\n  GitPullOpts,\n  GitConfigOpts,\n} from \"./types\";\n\n/**\n * Default environment variables for all git commands.\n * GIT_TERMINAL_PROMPT=0 prevents git from prompting for credentials interactively,\n * which would cause the command to hang in a non-interactive environment.\n */\nconst DEFAULT_GIT_ENV: Record<string, string> = {\n  GIT_TERMINAL_PROMPT: \"0\",\n  LC_ALL: \"C\",\n};\n\n/**\n * Default timeout for git operations in milliseconds (30 seconds).\n */\nconst DEFAULT_GIT_TIMEOUT_MS = 30000;\n\n/**\n * Default timeout for git clone operations in milliseconds (5 minutes).\n */\nconst DEFAULT_CLONE_TIMEOUT_MS = 300000;\n\n/**\n * Default timeout for git pull operations in milliseconds (2 minutes).\n */\nconst DEFAULT_PULL_TIMEOUT_MS = 120000;\n\n/**\n * Provides high-level git operations in the AgentBay cloud environment.\n *\n * This module wraps git CLI commands and executes them on the remote session\n * via the Command module. All commands run with `GIT_TERMINAL_PROMPT=0` to\n * prevent interactive credential prompts, and `LC_ALL=C` to ensure consistent\n * English output for reliable parsing. Supports repository management, branch\n * operations, staging, committing, and configuration.\n *\n * @example\n * ```typescript\n * const agentBay = new AgentBay({ apiKey: process.env.AGENTBAY_API_KEY });\n * const result = await agentBay.create();\n * if (result.success) {\n *   const cloneResult = await result.session.git.clone('https://github.com/user/repo.git');\n *   console.log('Cloned to:', cloneResult.path);\n *   await result.session.delete();\n * }\n * ```\n */\nexport class Git {\n  private session: Session;\n  private gitAvailable: boolean | null = null;\n\n  /**\n   * Initialize a Git object.\n   *\n   * @param session - The Session instance that this Git module belongs to.\n   */\n  constructor(session: Session) {\n    this.session = session;\n  }\n\n  // ---------------------------------------------------------------------------\n  // Private helpers\n  // ---------------------------------------------------------------------------\n\n  /**\n   * Escape a string argument for safe use in a Linux shell command.\n   * Uses single-quote wrapping with proper escaping of embedded single quotes.\n   *\n   * @param arg - The argument to escape\n   * @returns The shell-escaped argument\n   *\n   * @example\n   * shellEscape(\"hello\") => \"'hello'\"\n   * shellEscape(\"it's\") => \"'it'\\\\''s'\"\n   * shellEscape(\"\") => \"''\"\n   */\n  private shellEscape(arg: string): string {\n    return \"'\" + arg.replace(/'/g, \"'\\\\''\") + \"'\";\n  }\n\n  /**\n   * Build a complete git command string with optional -C (repo path) prefix.\n   * All arguments are shell-escaped for safe execution.\n   *\n   * @param args - Array of git sub-command arguments (e.g., ['clone', '--depth', '1', url])\n   * @param repoPath - Optional repository path; if provided, git -C <path> is prepended\n   * @returns The complete shell command string\n   */\n  private buildGitCommand(args: string[], repoPath?: string): string {\n    const parts = [\"git\"];\n    if (repoPath) {\n      parts.push(\"-C\", this.shellEscape(repoPath));\n    }\n    parts.push(...args.map((a) => this.shellEscape(a)));\n    return parts.join(\" \");\n  }\n\n  /**\n   * Execute a standard git command via the Command module.\n   * Automatically merges DEFAULT_GIT_ENV into the environment.\n   *\n   * Use this for straightforward git commands (clone, pull, push, etc.).\n   * For commands requiring shell pipes or complex shell features, use runShell().\n   *\n   * @param args - Array of git sub-command arguments\n   * @param repoPath - Optional repository path for git -C\n   * @param opts - Optional settings (timeoutMs)\n   * @returns The CommandResult from executing the git command\n   */\n  private async runGit(\n    args: string[],\n    repoPath?: string,\n    opts?: { timeoutMs?: number }\n  ): Promise<CommandResult> {\n    const cmd = this.buildGitCommand(args, repoPath);\n    return this.session.command.executeCommand(\n      cmd,\n      opts?.timeoutMs || DEFAULT_GIT_TIMEOUT_MS,\n      undefined, // cwd is handled via git -C\n      DEFAULT_GIT_ENV\n    );\n  }\n\n  /**\n   * Execute a raw shell command with git environment variables.\n   * Automatically merges DEFAULT_GIT_ENV into the environment.\n   *\n   * Use this for commands that require shell features like pipes, redirects,\n   * or complex command chaining. For standard git commands, prefer runGit().\n   *\n   * This method is also used internally for operations that need to compose\n   * shell commands (e.g., credential helpers in future phases).\n   *\n   * @param cmd - The raw shell command string\n   * @param opts - Optional settings (timeoutMs)\n   * @returns The CommandResult from executing the shell command\n   */\n  private async runShell(\n    cmd: string,\n    opts?: { timeoutMs?: number }\n  ): Promise<CommandResult> {\n    return this.session.command.executeCommand(\n      cmd,\n      opts?.timeoutMs || DEFAULT_GIT_TIMEOUT_MS,\n      undefined,\n      DEFAULT_GIT_ENV\n    );\n  }\n\n  /**\n   * Check whether git is available on the remote environment.\n   * The result is cached after the first successful check.\n   *\n   * @throws GitNotFoundError if git is not installed\n   */\n  private async ensureGitAvailable(): Promise<void> {\n    if (this.gitAvailable === true) {\n      return;\n    }\n\n    const result = await this.runGit([\"--version\"]);\n\n    if (!result.success) {\n      this.gitAvailable = false;\n      throw new GitNotFoundError(\n        \"Git is not installed or not available on the remote environment. \" +\n          \"Please ensure git is installed in the session image.\",\n        result.exitCode || 127,\n        result.stderr || result.errorMessage || \"\"\n      );\n    }\n\n    this.gitAvailable = true;\n  }\n\n  /**\n   * Classify a failed git command result into a specific error type\n   * based on stderr content and exit code.\n   *\n   * @param operation - The git operation name (e.g., 'clone', 'pull')\n   * @param result - The failed CommandResult\n   * @returns A specific GitError subclass instance\n   */\n  private classifyError(operation: string, result: CommandResult): GitError {\n    const stderr = (result.stderr || result.errorMessage || \"\").toLowerCase();\n    const exitCode = result.exitCode || 1;\n    const rawStderr = result.stderr || result.errorMessage || \"\";\n\n    // Authentication errors\n    if (\n      stderr.includes(\"authentication failed\") ||\n      stderr.includes(\"could not read username\") ||\n      stderr.includes(\"invalid credentials\") ||\n      stderr.includes(\"authorization failed\") ||\n      stderr.includes(\"access denied\") ||\n      stderr.includes(\"permission denied\") ||\n      stderr.includes(\"403\")\n    ) {\n      return new GitAuthError(\n        `Git ${operation} failed: authentication error. ${rawStderr}`,\n        exitCode,\n        rawStderr\n      );\n    }\n\n    // Not a git repository\n    if (\n      stderr.includes(\"not a git repository\") ||\n      stderr.includes(\"does not appear to be a git repository\")\n    ) {\n      return new GitNotARepoError(\n        `Git ${operation} failed: not a git repository. ${rawStderr}`,\n        exitCode,\n        rawStderr\n      );\n    }\n\n    // Merge/rebase conflicts\n    if (\n      rawStderr.includes(\"CONFLICT\") ||\n      stderr.includes(\"merge conflict\") ||\n      stderr.includes(\"automatic merge failed\")\n    ) {\n      return new GitConflictError(\n        `Git ${operation} failed: merge conflict. ${rawStderr}`,\n        exitCode,\n        rawStderr\n      );\n    }\n\n    // Git not found (command not found)\n    if (\n      stderr.includes(\"command not found\") ||\n      stderr.includes(\"not found\") ||\n      exitCode === 127\n    ) {\n      return new GitNotFoundError(\n        `Git ${operation} failed: git not found. ${rawStderr}`,\n        exitCode,\n        rawStderr\n      );\n    }\n\n    // Generic git error\n    return new GitError(\n      `Git ${operation} failed (exit code ${exitCode}): ${rawStderr}`,\n      exitCode,\n      rawStderr\n    );\n  }\n\n  /**\n   * Derive the target directory name from a git repository URL.\n   *\n   * @param url - The git repository URL\n   * @returns The derived directory name\n   *\n   * @example\n   * deriveRepoDirFromUrl(\"https://github.com/user/repo.git\") => \"repo\"\n   * deriveRepoDirFromUrl(\"https://github.com/user/repo\") => \"repo\"\n   * deriveRepoDirFromUrl(\"git@github.com:user/repo.git\") => \"repo\"\n   */\n  private deriveRepoDirFromUrl(url: string): string {\n    // Remove trailing slashes\n    let cleaned = url.replace(/\\/+$/, \"\");\n\n    // Remove .git suffix\n    cleaned = cleaned.replace(/\\.git$/, \"\");\n\n    // Extract the last path segment\n    const lastSlash = cleaned.lastIndexOf(\"/\");\n    const lastColon = cleaned.lastIndexOf(\":\");\n\n    // Use whichever separator comes last (handles both HTTPS and SSH URLs)\n    const separatorIndex = Math.max(lastSlash, lastColon);\n\n    if (separatorIndex >= 0 && separatorIndex < cleaned.length - 1) {\n      return cleaned.substring(separatorIndex + 1);\n    }\n\n    // Fallback: return the whole cleaned string\n    return cleaned;\n  }\n\n  // ---------------------------------------------------------------------------\n  // Public API\n  // ---------------------------------------------------------------------------\n\n  /**\n   * Clone a git repository into the remote session environment.\n   *\n   * Clones a repository from the given URL into the remote session. When a\n   * branch is specified, `--single-branch` is automatically added to reduce\n   * data transfer. The target directory is derived from the URL if not\n   * explicitly provided via `opts.path`. Currently supports public\n   * repositories only; authentication support will be added in a future phase.\n   *\n   * @param url - The repository URL to clone (HTTPS or SSH)\n   * @param opts - Optional clone settings (path, branch, depth, timeoutMs)\n   * @returns Promise resolving to {@link GitCloneResult} with the cloned repository path\n   *\n   * @throws {GitNotFoundError} When git is not installed on the remote environment\n   * @throws {GitAuthError} When authentication fails (e.g., private repo without credentials)\n   * @throws {GitError} When the clone operation fails for other reasons\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: process.env.AGENTBAY_API_KEY });\n   * const result = await agentBay.create();\n   * if (result.success) {\n   *   const cloneResult = await result.session.git.clone('https://github.com/user/repo.git');\n   *   console.log('Cloned to:', cloneResult.path);\n   *   await result.session.delete();\n   * }\n   * ```\n   */\n  async clone(url: string, opts?: GitCloneOpts): Promise<GitCloneResult> {\n    await this.ensureGitAvailable();\n\n    const args: string[] = [\"clone\"];\n\n    // When a branch is specified, add --single-branch to only fetch that branch\n    // (reduces data transfer, inspired by E2B's approach)\n    if (opts?.branch) {\n      args.push(\"--branch\", opts.branch, \"--single-branch\");\n    }\n\n    if (opts?.depth) {\n      args.push(\"--depth\", String(opts.depth));\n    }\n\n    args.push(url);\n\n    const targetPath = opts?.path || this.deriveRepoDirFromUrl(url);\n    args.push(targetPath);\n\n    const result = await this.runGit(args, undefined, {\n      timeoutMs: opts?.timeoutMs ?? DEFAULT_CLONE_TIMEOUT_MS,\n    });\n\n    if (!result.success) {\n      throw this.classifyError(\"clone\", result);\n    }\n\n    return { path: targetPath };\n  }\n\n  /**\n   * Initialize a new git repository in the remote session environment.\n   *\n   * Creates an empty git repository at the specified path. Optionally sets the\n   * initial branch name (requires git >= 2.28) and supports creating bare\n   * repositories for server-side use.\n   *\n   * @param path - The directory path to initialize as a git repository\n   * @param opts - Optional init settings (initialBranch, bare, timeoutMs)\n   * @returns Promise resolving to {@link GitInitResult} with the initialized repository path\n   *\n   * @throws {GitNotFoundError} When git is not installed on the remote environment\n   * @throws {GitError} When the init operation fails\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: process.env.AGENTBAY_API_KEY });\n   * const result = await agentBay.create();\n   * if (result.success) {\n   *   const initResult = await result.session.git.init('/home/user/my-project');\n   *   console.log('Initialized at:', initResult.path);\n   *   await result.session.delete();\n   * }\n   * ```\n   */\n  async init(path: string, opts?: GitInitOpts): Promise<GitInitResult> {\n    await this.ensureGitAvailable();\n\n    const args: string[] = [\"init\"];\n\n    if (opts?.initialBranch) {\n      args.push(\"--initial-branch\", opts.initialBranch);\n    }\n\n    if (opts?.bare) {\n      args.push(\"--bare\");\n    }\n\n    args.push(path);\n\n    const result = await this.runGit(args, undefined, {\n      timeoutMs: opts?.timeoutMs,\n    });\n\n    if (!result.success) {\n      throw this.classifyError(\"init\", result);\n    }\n\n    return { path };\n  }\n\n  /**\n   * Add files to the git staging area.\n   *\n   * By default (when no files are specified and `all` is not explicitly false),\n   * stages all changes using `git add -A`. Specific files can be staged by\n   * providing them in `opts.files`. A `--` separator is automatically inserted\n   * before file paths to prevent them from being interpreted as options.\n   *\n   * @param repoPath - The repository path\n   * @param opts - Optional add settings (files, all, timeoutMs)\n   *\n   * @throws {GitNotFoundError} When git is not installed\n   * @throws {GitNotARepoError} When the path is not a git repository\n   * @throws {GitError} When the add operation fails\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: process.env.AGENTBAY_API_KEY });\n   * const result = await agentBay.create();\n   * if (result.success) {\n   *   await result.session.git.add('/home/user/my-project');\n   *   await result.session.delete();\n   * }\n   * ```\n   */\n  async add(repoPath: string, opts?: GitAddOpts): Promise<void> {\n    await this.ensureGitAvailable();\n\n    const args: string[] = [\"add\"];\n\n    if (opts?.files && opts.files.length > 0) {\n      // Use -- separator to prevent filenames from being interpreted as options\n      args.push(\"--\", ...opts.files);\n    } else if (opts?.all !== false) {\n      // Default: stage all changes\n      args.push(\"-A\");\n    } else {\n      // all=false: stage current directory only\n      args.push(\".\");\n    }\n\n    const result = await this.runGit(args, repoPath, {\n      timeoutMs: opts?.timeoutMs,\n    });\n\n    if (!result.success) {\n      throw this.classifyError(\"add\", result);\n    }\n  }\n\n  /**\n   * Create a git commit with the staged changes.\n   *\n   * Author information can be provided via `authorName` and `authorEmail`,\n   * which are applied as temporary `-c` configuration (not persisted to git config).\n   *\n   * @param repoPath - The repository path\n   * @param message - The commit message\n   * @param opts - Optional commit settings\n   * @returns Promise resolving to GitCommitResult with the commit hash\n   *\n   * @throws GitNotFoundError if git is not installed\n   * @throws GitNotARepoError if the path is not a git repository\n   * @throws GitError for other git errors\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: process.env.AGENTBAY_API_KEY });\n   * const result = await agentBay.create();\n   * if (result.success) {\n   *   const commitResult = await result.session.git.commit('/home/user/my-project', 'Initial commit');\n   *   console.log('Commit hash:', commitResult.commitHash);\n   *   await result.session.delete();\n   * }\n   * ```\n   */\n  async commit(\n    repoPath: string,\n    message: string,\n    opts?: GitCommitOpts\n  ): Promise<GitCommitResult> {\n    await this.ensureGitAvailable();\n\n    // -c parameters must come BEFORE the 'commit' subcommand (git requirement)\n    const args: string[] = [];\n\n    if (opts?.authorName) {\n      args.push(\"-c\", `user.name=${opts.authorName}`);\n    }\n    if (opts?.authorEmail) {\n      args.push(\"-c\", `user.email=${opts.authorEmail}`);\n    }\n\n    args.push(\"commit\", \"-m\", message);\n\n    if (opts?.allowEmpty) {\n      args.push(\"--allow-empty\");\n    }\n\n    const result = await this.runGit(args, repoPath, {\n      timeoutMs: opts?.timeoutMs,\n    });\n\n    if (!result.success) {\n      throw this.classifyError(\"commit\", result);\n    }\n\n    // Try to parse commit hash from stdout or stderr (git outputs commit info to stderr)\n    // Normal:      \"[main abc1234] Initial commit\"\n    // Root commit: \"[main (root-commit) abc1234] Initial commit\"\n    const commitOutput = result.stdout || result.output || \"\";\n    const hashMatch = commitOutput.match(\n      /\\[[\\w/.-]+(?:\\s+\\([^)]+\\))?\\s+([a-f0-9]+)\\]/\n    );\n    return { commitHash: hashMatch?.[1] };\n  }\n\n  /**\n   * Get the status of the working tree and staging area.\n   *\n   * Returns a structured result parsed from `git status --porcelain=1 -b`.\n   *\n   * @param repoPath - The repository path\n   * @param opts - Optional status settings\n   * @returns Promise resolving to GitStatusResult with branch info and file statuses\n   *\n   * @throws GitNotFoundError if git is not installed\n   * @throws GitNotARepoError if the path is not a git repository\n   * @throws GitError for other git errors\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: process.env.AGENTBAY_API_KEY });\n   * const result = await agentBay.create();\n   * if (result.success) {\n   *   const status = await result.session.git.status('/home/user/my-project');\n   *   console.log('Branch:', status.branch);\n   *   console.log('Clean:', status.isClean);\n   *   await result.session.delete();\n   * }\n   * ```\n   */\n  async status(\n    repoPath: string,\n    opts?: GitStatusOpts\n  ): Promise<GitStatusResult> {\n    await this.ensureGitAvailable();\n\n    const result = await this.runGit(\n      [\"status\", \"--porcelain=1\", \"-b\"],\n      repoPath,\n      { timeoutMs: opts?.timeoutMs }\n    );\n\n    if (!result.success) {\n      throw this.classifyError(\"status\", result);\n    }\n\n    return this.parseGitStatus(result.stdout || result.output || \"\");\n  }\n\n  /**\n   * Get the commit history of the repository.\n   *\n   * Returns a structured result with parsed commit entries.\n   *\n   * @param repoPath - The repository path\n   * @param opts - Optional log settings\n   * @returns Promise resolving to GitLogResult with commit entries\n   *\n   * @throws GitNotFoundError if git is not installed\n   * @throws GitNotARepoError if the path is not a git repository\n   * @throws GitError for other git errors\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: process.env.AGENTBAY_API_KEY });\n   * const result = await agentBay.create();\n   * if (result.success) {\n   *   const log = await result.session.git.log('/home/user/my-project');\n   *   console.log('Total commits:', log.entries.length);\n   *   await result.session.delete();\n   * }\n   * ```\n   */\n  async log(repoPath: string, opts?: GitLogOpts): Promise<GitLogResult> {\n    await this.ensureGitAvailable();\n\n    // Use special delimiters: %x01 between fields, %x00 between records\n    const format = \"%H%x01%h%x01%an%x01%ae%x01%aI%x01%s%x00\";\n    const args: string[] = [\"log\", `--format=${format}`];\n\n    if (opts?.maxCount) {\n      args.push(\"--max-count\", String(opts.maxCount));\n    }\n\n    const result = await this.runGit(args, repoPath, {\n      timeoutMs: opts?.timeoutMs,\n    });\n\n    if (!result.success) {\n      throw this.classifyError(\"log\", result);\n    }\n\n    return this.parseGitLog(result.stdout || result.output || \"\");\n  }\n\n  /**\n   * List all local branches in the repository.\n   *\n   * @param repoPath - The repository path\n   * @param opts - Optional settings\n   * @returns Promise resolving to GitBranchListResult with branch info\n   *\n   * @throws GitNotFoundError if git is not installed\n   * @throws GitNotARepoError if the path is not a git repository\n   * @throws GitError for other git errors\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: process.env.AGENTBAY_API_KEY });\n   * const result = await agentBay.create();\n   * if (result.success) {\n   *   const branches = await result.session.git.listBranches('/home/user/my-project');\n   *   console.log('Current branch:', branches.current);\n   *   await result.session.delete();\n   * }\n   * ```\n   */\n  async listBranches(\n    repoPath: string,\n    opts?: GitBranchListOpts\n  ): Promise<GitBranchListResult> {\n    await this.ensureGitAvailable();\n\n    // Use custom format: branch_name<TAB>HEAD_marker\n    // %(HEAD) outputs '*' for current branch, ' ' for others\n    const result = await this.runGit(\n      [\"branch\", \"--format=%(refname:short)\\t%(HEAD)\"],\n      repoPath,\n      { timeoutMs: opts?.timeoutMs }\n    );\n\n    if (!result.success) {\n      throw this.classifyError(\"listBranches\", result);\n    }\n\n    return this.parseGitBranches(result.stdout || result.output || \"\");\n  }\n\n  /**\n   * Create a new branch in the repository.\n   *\n   * By default, also checks out the new branch (using `git checkout -b`).\n   * Set `opts.checkout = false` to create without switching (using `git branch`).\n   *\n   * @param repoPath - The repository path\n   * @param branch - The name of the new branch\n   * @param opts - Optional settings\n   *\n   * @throws GitNotFoundError if git is not installed\n   * @throws GitNotARepoError if the path is not a git repository\n   * @throws GitError for other git errors (e.g., branch already exists)\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: process.env.AGENTBAY_API_KEY });\n   * const result = await agentBay.create();\n   * if (result.success) {\n   *   await result.session.git.createBranch('/home/user/my-project', 'feature/new-feature');\n   *   await result.session.delete();\n   * }\n   * ```\n   */\n  async createBranch(\n    repoPath: string,\n    branch: string,\n    opts?: GitBranchCreateOpts\n  ): Promise<void> {\n    await this.ensureGitAvailable();\n\n    let args: string[];\n\n    if (opts?.checkout === false) {\n      // Create branch without switching\n      args = [\"branch\", branch];\n    } else {\n      // Default: create and switch to the new branch\n      args = [\"checkout\", \"-b\", branch];\n    }\n\n    const result = await this.runGit(args, repoPath, {\n      timeoutMs: opts?.timeoutMs,\n    });\n\n    if (!result.success) {\n      throw this.classifyError(\"createBranch\", result);\n    }\n  }\n\n  /**\n   * Switch to an existing branch.\n   *\n   * @param repoPath - The repository path\n   * @param branch - The branch name to switch to\n   * @param opts - Optional settings\n   *\n   * @throws GitNotFoundError if git is not installed\n   * @throws GitNotARepoError if the path is not a git repository\n   * @throws GitError for other git errors (e.g., branch does not exist)\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: process.env.AGENTBAY_API_KEY });\n   * const result = await agentBay.create();\n   * if (result.success) {\n   *   await result.session.git.checkoutBranch('/home/user/my-project', 'main');\n   *   await result.session.delete();\n   * }\n   * ```\n   */\n  async checkoutBranch(\n    repoPath: string,\n    branch: string,\n    opts?: GitCheckoutOpts\n  ): Promise<void> {\n    await this.ensureGitAvailable();\n\n    const result = await this.runGit([\"checkout\", branch], repoPath, {\n      timeoutMs: opts?.timeoutMs,\n    });\n\n    if (!result.success) {\n      throw this.classifyError(\"checkoutBranch\", result);\n    }\n  }\n\n  // ---------------------------------------------------------------------------\n  // Remote operations\n  // ---------------------------------------------------------------------------\n\n  /**\n   * Add a remote repository.\n   *\n   * @param repoPath - The repository path\n   * @param name - The remote name (e.g., \"origin\")\n   * @param url - The remote URL\n   * @param opts - Optional settings\n   *\n   * @throws GitNotFoundError if git is not installed\n   * @throws GitNotARepoError if the path is not a git repository\n   * @throws GitError for other git errors\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: process.env.AGENTBAY_API_KEY });\n   * const result = await agentBay.create();\n   * if (result.success) {\n   *   await result.session.git.remoteAdd('/home/user/my-project', 'origin', 'https://github.com/user/repo.git');\n   *   await result.session.delete();\n   * }\n   * ```\n   */\n  async remoteAdd(\n    repoPath: string,\n    name: string,\n    url: string,\n    opts?: GitRemoteAddOpts\n  ): Promise<void> {\n    await this.ensureGitAvailable();\n\n    const { fetch, overwrite, timeoutMs } = opts ?? {};\n    const addArgs: string[] = [\"remote\", \"add\"];\n    if (fetch) addArgs.push(\"-f\");\n    addArgs.push(name, url);\n\n    if (!overwrite) {\n      // Simple mode: direct git remote add\n      const result = await this.runGit(addArgs, repoPath, { timeoutMs });\n      if (!result.success) {\n        throw this.classifyError(\"remoteAdd\", result);\n      }\n    } else {\n      // Idempotent mode: add fails, fallback to set-url\n      const addCmd = this.buildGitCommand(addArgs, repoPath);\n      const setUrlCmd = this.buildGitCommand(\n        [\"remote\", \"set-url\", name, url],\n        repoPath\n      );\n      let cmd = `${addCmd} || ${setUrlCmd}`;\n      if (fetch) {\n        const fetchCmd = this.buildGitCommand([\"fetch\", name], repoPath);\n        cmd = `(${cmd}) && ${fetchCmd}`;\n      }\n      const result = await this.runShell(cmd, { timeoutMs });\n      if (!result.success) {\n        throw this.classifyError(\"remoteAdd\", result);\n      }\n    }\n  }\n\n  /**\n   * Get the URL of a remote repository.\n   *\n   * @param repoPath - The repository path\n   * @param name - The remote name (e.g., \"origin\")\n   * @param opts - Optional settings\n   * @returns The remote URL, or undefined if the remote does not exist\n   *\n   * @throws GitNotFoundError if git is not installed\n   * @throws GitNotARepoError if the path is not a git repository\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: process.env.AGENTBAY_API_KEY });\n   * const result = await agentBay.create();\n   * if (result.success) {\n   *   const url = await result.session.git.remoteGet('/home/user/my-project', 'origin');\n   *   console.log('Remote URL:', url);\n   *   await result.session.delete();\n   * }\n   * ```\n   */\n  async remoteGet(\n    repoPath: string,\n    name: string,\n    opts?: { timeoutMs?: number }\n  ): Promise<string | undefined> {\n    await this.ensureGitAvailable();\n\n    const result = await this.runGit([\"remote\", \"get-url\", name], repoPath, {\n      timeoutMs: opts?.timeoutMs,\n    });\n    if (!result.success) {\n      const stderr = (result.stderr || \"\").toLowerCase();\n      if (stderr.includes(\"no such remote\")) {\n        return undefined;\n      }\n      throw this.classifyError(\"remote get\", result);\n    }\n    const trimmed = (result.stdout || \"\").trim();\n    return trimmed.length > 0 ? trimmed : undefined;\n  }\n\n  // ---------------------------------------------------------------------------\n  // Reset operations\n  // ---------------------------------------------------------------------------\n\n  /**\n   * Reset the repository to a specific state.\n   *\n   * @param repoPath - The repository path\n   * @param opts - Optional settings\n   *\n   * @throws GitNotFoundError if git is not installed\n   * @throws GitNotARepoError if the path is not a git repository\n   * @throws GitError for other git errors\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: process.env.AGENTBAY_API_KEY });\n   * const result = await agentBay.create();\n   * if (result.success) {\n   *   await result.session.git.reset('/home/user/my-project');\n   *   await result.session.delete();\n   * }\n   * ```\n   */\n  async reset(repoPath: string, opts?: GitResetOpts): Promise<void> {\n    await this.ensureGitAvailable();\n\n    const { mode, target, paths, timeoutMs } = opts ?? {};\n    const args: string[] = [\"reset\"];\n    if (mode) args.push(`--${mode}`);\n    if (target) args.push(target);\n    if (paths && paths.length > 0) args.push(\"--\", ...paths);\n\n    const result = await this.runGit(args, repoPath, { timeoutMs });\n    if (!result.success) {\n      throw this.classifyError(\"reset\", result);\n    }\n  }\n\n  // ---------------------------------------------------------------------------\n  // Restore operations\n  // ---------------------------------------------------------------------------\n\n  /**\n   * Restore files from the index or working tree.\n   *\n   * @param repoPath - The repository path\n   * @param opts - Restore options including paths (required)\n   *\n   * @throws GitNotFoundError if git is not installed\n   * @throws GitNotARepoError if the path is not a git repository\n   * @throws GitError for other git errors\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: process.env.AGENTBAY_API_KEY });\n   * const result = await agentBay.create();\n   * if (result.success) {\n   *   await result.session.git.restore('/home/user/my-project', { paths: ['src/index.ts'] });\n   *   await result.session.delete();\n   * }\n   * ```\n   */\n  async restore(repoPath: string, opts: GitRestoreOpts): Promise<void> {\n    await this.ensureGitAvailable();\n\n    const { paths, staged, worktree, source, timeoutMs } = opts;\n    const resolvedStaged = staged ?? false;\n    const resolvedWorktree = worktree ?? !resolvedStaged;\n\n    const args: string[] = [\"restore\"];\n    if (resolvedWorktree) args.push(\"--worktree\");\n    if (resolvedStaged) args.push(\"--staged\");\n    if (source) args.push(\"--source\", source);\n    args.push(\"--\", ...paths);\n\n    const result = await this.runGit(args, repoPath, { timeoutMs });\n    if (!result.success) {\n      throw this.classifyError(\"restore\", result);\n    }\n  }\n\n  // ---------------------------------------------------------------------------\n  // Pull operations\n  // ---------------------------------------------------------------------------\n\n  /**\n   * Pull changes from a remote repository.\n   *\n   * @param repoPath - The repository path\n   * @param opts - Optional settings\n   *\n   * @throws GitNotFoundError if git is not installed\n   * @throws GitNotARepoError if the path is not a git repository\n   * @throws GitError for other git errors (e.g., no upstream configured)\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: process.env.AGENTBAY_API_KEY });\n   * const result = await agentBay.create();\n   * if (result.success) {\n   *   await result.session.git.pull('/home/user/my-project');\n   *   await result.session.delete();\n   * }\n   * ```\n   */\n  async pull(repoPath: string, opts?: GitPullOpts): Promise<void> {\n    await this.ensureGitAvailable();\n\n    const { remote, branch, timeoutMs } = opts ?? {};\n    const args: string[] = [\"pull\"];\n    if (remote) args.push(remote);\n    if (branch) args.push(branch);\n\n    const result = await this.runGit(args, repoPath, {\n      timeoutMs: timeoutMs ?? DEFAULT_PULL_TIMEOUT_MS,\n    });\n    if (!result.success) {\n      throw this.classifyError(\"pull\", result);\n    }\n  }\n\n  // ---------------------------------------------------------------------------\n  // Config operations\n  // ---------------------------------------------------------------------------\n\n  /**\n   * Configure git user information.\n   *\n   * @param repoPath - The repository path\n   * @param name - The user name\n   * @param email - The user email\n   * @param opts - Optional settings\n   *\n   * @throws GitNotFoundError if git is not installed\n   * @throws GitNotARepoError if the path is not a git repository\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: process.env.AGENTBAY_API_KEY });\n   * const result = await agentBay.create();\n   * if (result.success) {\n   *   await result.session.git.configureUser('/home/user/my-project', 'Agent', 'agent@example.com');\n   *   await result.session.delete();\n   * }\n   * ```\n   */\n  async configureUser(\n    repoPath: string,\n    name: string,\n    email: string,\n    opts?: GitConfigOpts\n  ): Promise<void> {\n    await this.ensureGitAvailable();\n\n    const { scope, timeoutMs } = opts ?? {};\n    // Default scope is global (matches E2B behavior)\n    const scopeFlag = scope === \"local\" ? \"--local\" : \"--global\";\n    const baseArgs = [\"config\", scopeFlag];\n\n    const nameResult = await this.runGit(\n      [...baseArgs, \"user.name\", name],\n      repoPath,\n      { timeoutMs }\n    );\n    if (!nameResult.success) {\n      throw this.classifyError(\"configureUser\", nameResult);\n    }\n    const emailResult = await this.runGit(\n      [...baseArgs, \"user.email\", email],\n      repoPath,\n      { timeoutMs }\n    );\n    if (!emailResult.success) {\n      throw this.classifyError(\"configureUser\", emailResult);\n    }\n  }\n\n  /**\n   * Set a git configuration value.\n   *\n   * @param repoPath - The repository path\n   * @param key - The configuration key\n   * @param value - The configuration value\n   * @param opts - Optional settings\n   *\n   * @throws GitNotFoundError if git is not installed\n   * @throws GitNotARepoError if the path is not a git repository\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: process.env.AGENTBAY_API_KEY });\n   * const result = await agentBay.create();\n   * if (result.success) {\n   *   await result.session.git.setConfig('/home/user/my-project', 'pull.rebase', 'true');\n   *   await result.session.delete();\n   * }\n   * ```\n   */\n  async setConfig(\n    repoPath: string,\n    key: string,\n    value: string,\n    opts?: GitConfigOpts\n  ): Promise<void> {\n    await this.ensureGitAvailable();\n\n    const { scope, timeoutMs } = opts ?? {};\n    const args: string[] = [\"config\"];\n    // Default scope is global (matches E2B behavior)\n    args.push(scope === \"local\" ? \"--local\" : \"--global\");\n    args.push(key, value);\n\n    const result = await this.runGit(args, repoPath, { timeoutMs });\n    if (!result.success) {\n      throw this.classifyError(\"setConfig\", result);\n    }\n  }\n\n  /**\n   * Get a git configuration value.\n   *\n   * @param repoPath - The repository path\n   * @param key - The configuration key\n   * @param opts - Optional settings\n   * @returns The configuration value, or undefined if not found\n   *\n   * @throws GitNotFoundError if git is not installed\n   * @throws GitNotARepoError if the path is not a git repository\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: process.env.AGENTBAY_API_KEY });\n   * const result = await agentBay.create();\n   * if (result.success) {\n   *   const name = await result.session.git.getConfig('/home/user/my-project', 'user.name');\n   *   console.log('User name:', name);\n   *   await result.session.delete();\n   * }\n   * ```\n   */\n  async getConfig(\n    repoPath: string,\n    key: string,\n    opts?: GitConfigOpts\n  ): Promise<string | undefined> {\n    await this.ensureGitAvailable();\n\n    const { scope, timeoutMs } = opts ?? {};\n    const args: string[] = [\"config\"];\n    // Default scope is global (matches E2B behavior)\n    args.push(scope === \"local\" ? \"--local\" : \"--global\");\n    args.push(\"--get\", key);\n\n    const result = await this.runGit(args, repoPath, { timeoutMs });\n    if (!result.success) {\n      const rawStderr = (result.stderr || \"\").trim().toLowerCase();\n      // exit code 1 with empty/missing stderr means key does not exist\n      if (\n        result.exitCode === 1 &&\n        (rawStderr.length === 0 || rawStderr.includes(\"key does not contain\"))\n      ) {\n        return undefined;\n      }\n      throw this.classifyError(\"get config\", result);\n    }\n    const trimmed = (result.stdout || \"\").trim();\n    return trimmed.length > 0 ? trimmed : undefined;\n  }\n\n  /**\n   * Delete a local branch.\n   *\n   * @param repoPath - The repository path\n   * @param branch - The branch name to delete\n   * @param opts - Optional settings. Use `force: true` for `-D` (force delete)\n   *\n   * @throws GitNotFoundError if git is not installed\n   * @throws GitNotARepoError if the path is not a git repository\n   * @throws GitError for other git errors (e.g., branch not fully merged)\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: process.env.AGENTBAY_API_KEY });\n   * const result = await agentBay.create();\n   * if (result.success) {\n   *   await result.session.git.deleteBranch('/home/user/my-project', 'feature/old');\n   *   await result.session.delete();\n   * }\n   * ```\n   */\n  async deleteBranch(\n    repoPath: string,\n    branch: string,\n    opts?: GitBranchDeleteOpts\n  ): Promise<void> {\n    await this.ensureGitAvailable();\n\n    const deleteFlag = opts?.force ? \"-D\" : \"-d\";\n    const result = await this.runGit([\"branch\", deleteFlag, branch], repoPath, {\n      timeoutMs: opts?.timeoutMs,\n    });\n\n    if (!result.success) {\n      throw this.classifyError(\"deleteBranch\", result);\n    }\n  }\n\n  // ---------------------------------------------------------------------------\n  // Output parsers\n  // ---------------------------------------------------------------------------\n\n  /**\n   * Derive a human-readable status string from porcelain status characters.\n   *\n   * @param indexStatus - The index status character (first character in porcelain output)\n   * @param workTreeStatus - The worktree status character (second character in porcelain output)\n   * @returns A human-readable status string\n   */\n  private deriveStatus(indexStatus: string, workTreeStatus: string): string {\n    const combined = indexStatus + workTreeStatus;\n\n    if (combined.includes(\"U\")) {\n      return \"conflict\";\n    }\n    if (combined.includes(\"R\")) {\n      return \"renamed\";\n    }\n    if (combined.includes(\"C\")) {\n      return \"copied\";\n    }\n    if (combined.includes(\"D\")) {\n      return \"deleted\";\n    }\n    if (combined.includes(\"A\")) {\n      return \"added\";\n    }\n    if (combined.includes(\"M\")) {\n      return \"modified\";\n    }\n    if (combined.includes(\"T\")) {\n      return \"typechange\";\n    }\n    if (combined.includes(\"?\")) {\n      return \"untracked\";\n    }\n\n    return \"unknown\";\n  }\n\n  /**\n   * Parse the output of `git status --porcelain=1 -b` into a structured result.\n   *\n   * Format:\n   * - First line: `## branch_name` or `## branch_name...remote/branch_name`\n   * - Subsequent lines: `XY path` where X=index status, Y=worktree status\n   *\n   * @param output - Raw stdout from git status\n   * @returns Parsed GitStatusResult\n   */\n  private parseGitStatus(output: string): GitStatusResult {\n    const lines = output.split(\"\\n\").filter((l) => l.length > 0);\n    let currentBranch: string | undefined;\n    let upstream: string | undefined;\n    let ahead = 0;\n    let behind = 0;\n    let detached = false;\n    const files: GitFileStatus[] = [];\n\n    for (const line of lines) {\n      if (line.startsWith(\"## \")) {\n        // Branch line: \"## main...origin/main [ahead 1, behind 2]\" or similar\n        const branchInfo = line.substring(3);\n\n        // Handle \"No commits yet on <branch>\" format\n        const noCommitsMatch = branchInfo.match(/No commits yet on (.+)/);\n        if (noCommitsMatch) {\n          currentBranch = noCommitsMatch[1].split(\"...\")[0];\n        } else {\n          // Parse ahead/behind info\n          const aheadStart = branchInfo.indexOf(\" [\");\n          const branchPart =\n            aheadStart === -1\n              ? branchInfo\n              : branchInfo.substring(0, aheadStart);\n\n          // Extract branch and upstream\n          const parts = branchPart.split(\"...\");\n          currentBranch = parts[0];\n          upstream = parts[1];\n\n          // Parse ahead/behind from [ahead N, behind M] format\n          if (aheadStart !== -1) {\n            const aheadPart = branchInfo.substring(\n              aheadStart + 2,\n              branchInfo.length - 1\n            );\n            const aheadMatch = aheadPart.match(/ahead (\\d+)/);\n            const behindMatch = aheadPart.match(/behind (\\d+)/);\n\n            if (aheadMatch) {\n              ahead = parseInt(aheadMatch[1], 10);\n            }\n            if (behindMatch) {\n              behind = parseInt(behindMatch[1], 10);\n            }\n          }\n\n          // Detect detached HEAD\n          if (\n            currentBranch.includes(\"HEAD (detached\") ||\n            currentBranch === \"HEAD (no branch)\"\n          ) {\n            detached = true;\n          }\n        }\n      } else if (line.length >= 3) {\n        const indexStatus = line[0];\n        const workTreeStatus = line[1];\n        const path = line.substring(3);\n\n        // Handle renamed files (path contains \" -> \")\n        let renamedFrom: string | undefined;\n        let actualPath = path;\n        const renameMatch = path.match(/^(.+?) -> (.+)$/);\n        if (renameMatch) {\n          renamedFrom = renameMatch[1];\n          actualPath = renameMatch[2];\n        }\n\n        // Determine if staged (index status is not space and not '?')\n        const staged = indexStatus !== \" \" && indexStatus !== \"?\";\n\n        files.push({\n          path: actualPath,\n          indexStatus,\n          workTreeStatus,\n          status: this.deriveStatus(indexStatus, workTreeStatus),\n          staged,\n          renamedFrom,\n        });\n      }\n    }\n\n    // Calculate statistics\n    const totalCount = files.length;\n    const stagedCount = files.filter((f) => f.staged).length;\n    const untrackedCount = files.filter((f) => f.status === \"untracked\").length;\n    const conflictCount = files.filter((f) => f.status === \"conflict\").length;\n    const unstagedCount = files.filter(\n      (f) => !f.staged && f.status !== \"untracked\"\n    ).length;\n    const hasChanges = totalCount > 0;\n    const hasStaged = stagedCount > 0;\n    const hasUntracked = untrackedCount > 0;\n    const hasConflicts = conflictCount > 0;\n    const isClean = !hasChanges;\n\n    return {\n      currentBranch,\n      upstream,\n      ahead,\n      behind,\n      detached,\n      files,\n      isClean,\n      hasChanges,\n      hasStaged,\n      hasUntracked,\n      hasConflicts,\n      totalCount,\n      stagedCount,\n      unstagedCount,\n      untrackedCount,\n      conflictCount,\n    };\n  }\n\n  /**\n   * Parse the output of `git log --format=...` into a structured result.\n   *\n   * Uses %x00 (NUL) as record separator and %x01 (SOH) as field separator\n   * to avoid conflicts with commit messages containing newlines or special chars.\n   *\n   * @param output - Raw stdout from git log\n   * @returns Parsed GitLogResult\n   */\n  private parseGitLog(output: string): GitLogResult {\n    const entries: GitLogEntry[] = [];\n    const records = output.split(\"\\x00\").filter((r) => r.trim().length > 0);\n\n    for (const record of records) {\n      const parts = record.split(\"\\x01\");\n      if (parts.length >= 6) {\n        entries.push({\n          hash: parts[0].trim(),\n          shortHash: parts[1],\n          authorName: parts[2],\n          authorEmail: parts[3],\n          date: parts[4],\n          message: parts[5].trim(),\n        });\n      }\n    }\n\n    return { entries };\n  }\n\n  /**\n   * Parse the output of `git branch --format=%(refname:short)\\t%(HEAD)`.\n   *\n   * Each line is: `branch_name\\t*` (current) or `branch_name\\t ` (other).\n   *\n   * @param output - Raw stdout from git branch\n   * @returns Parsed GitBranchListResult\n   */\n  private parseGitBranches(output: string): GitBranchListResult {\n    const lines = output.split(\"\\n\").filter((l) => l.length > 0);\n    const branches: GitBranchInfo[] = [];\n    let current = \"\";\n\n    for (const line of lines) {\n      const parts = line.split(\"\\t\");\n      const name = parts[0].trim();\n\n      // Skip detached HEAD state (matches E2B behavior)\n      if (name.startsWith(\"(HEAD detached\")) {\n        continue;\n      }\n\n      const isCurrent = parts[1]?.trim() === \"*\";\n\n      if (name) {\n        branches.push({ name, isCurrent });\n        if (isCurrent) {\n          current = name;\n        }\n      }\n    }\n\n    return { branches, current };\n  }\n}\n","import { AgentBayError } from \"../exceptions\";\n\n/**\n * Base error for all Git operations.\n * Contains the exit code and stderr from the git command.\n */\nexport class GitError extends AgentBayError {\n  readonly exitCode: number;\n  readonly stderr: string;\n\n  constructor(message: string, exitCode: number, stderr: string) {\n    super(message, { exitCode, stderr });\n    this.name = \"GitError\";\n    this.exitCode = exitCode;\n    this.stderr = stderr;\n    Object.setPrototypeOf(this, GitError.prototype);\n  }\n}\n\n/**\n * Raised when git authentication fails (e.g., invalid credentials, missing access).\n */\nexport class GitAuthError extends GitError {\n  constructor(message: string, exitCode: number, stderr: string) {\n    super(message, exitCode, stderr);\n    this.name = \"GitAuthError\";\n    Object.setPrototypeOf(this, GitAuthError.prototype);\n  }\n}\n\n/**\n * Raised when git is not installed or not found on the remote environment.\n */\nexport class GitNotFoundError extends GitError {\n  constructor(message: string, exitCode: number, stderr: string) {\n    super(message, exitCode, stderr);\n    this.name = \"GitNotFoundError\";\n    Object.setPrototypeOf(this, GitNotFoundError.prototype);\n  }\n}\n\n/**\n * Raised when a git merge/rebase conflict occurs.\n */\nexport class GitConflictError extends GitError {\n  constructor(message: string, exitCode: number, stderr: string) {\n    super(message, exitCode, stderr);\n    this.name = \"GitConflictError\";\n    Object.setPrototypeOf(this, GitConflictError.prototype);\n  }\n}\n\n/**\n * Raised when the target directory is not a git repository.\n */\nexport class GitNotARepoError extends GitError {\n  constructor(message: string, exitCode: number, stderr: string) {\n    super(message, exitCode, stderr);\n    this.name = \"GitNotARepoError\";\n    Object.setPrototypeOf(this, GitNotARepoError.prototype);\n  }\n}\n","export {\n  Mobile,\n  BoolResult,\n  UIElement,\n  UIElementsResult,\n  InstalledApp,\n  InstalledAppsResult,\n  Process,\n  ProcessResult,\n  ScreenshotResult,\n} from \"./mobile\";\n","/**\n * Mobile module for mobile UI automation.\n * Provides touch, input, and app management operations for mobile environments.\n */\n\nimport { OperationResult } from \"../types/api-response\";\nimport { MobileExtraConfig } from \"../types/extra-configs\";\nimport { log, logError } from \"../utils/logger\";\nimport {\n  getMobileCommandTemplate,\n  replaceTemplatePlaceholders,\n} from \"../command/command-templates\";\n\nexport interface BoolResult extends OperationResult {\n  data?: boolean;\n}\n\nexport interface UIBounds {\n  left: number;\n  top: number;\n  right: number;\n  bottom: number;\n}\n\nexport interface UIElement {\n  text: string;\n  className: string;\n  bounds: UIBounds | string; // Can be either object or string format \"left,top,right,bottom\"\n}\n\nexport interface UIElementsResult extends OperationResult {\n  elements: UIElement[];\n  raw: string;\n  format: \"json\" | \"xml\";\n}\n\nexport interface InstalledApp {\n  name: string;\n  startCmd: string;\n  workDirectory: string;\n}\n\nexport interface InstalledAppsResult extends OperationResult {\n  apps: InstalledApp[];\n}\n\nexport interface Process {\n  pid: number;\n  pname: string;\n}\n\nexport interface ProcessResult extends OperationResult {\n  processes: Process[];\n}\n\nexport interface ScreenshotResult extends OperationResult {\n  data: string; // Screenshot URL\n}\n\nexport interface BetaScreenshotResult extends OperationResult {\n  type: string;\n  mimeType: string;\n  data: Uint8Array;\n  width?: number;\n  height?: number;\n}\n\nexport interface AdbUrlResult extends OperationResult {\n  data?: string; // ADB connection URL (e.g., \"adb connect xx.xx.xx.xx:xxxxx\")\n  url?: string; // Alternative field name for compatibility\n}\n\n// Session interface for Mobile module\ninterface MobileSession {\n  callMcpTool(\n    toolName: string,\n    args: Record<string, any>,\n    autoGenSession?: boolean\n  ): Promise<any>;\n  sessionId: string;\n  getAPIKey(): string;\n  getAgentBay(): any;\n  imageId?: string;\n  getLink(protocolType?: string, port?: number, options?: string): Promise<any>;\n  linkUrl: string;\n}\n\n/**\n * Parse bounds string format \"left,top,right,bottom\" to UIBounds object\n */\nfunction parseBoundsString(boundsStr: string): UIBounds | null {\n  const parts = boundsStr.split(\",\");\n  if (parts.length !== 4) {\n    return null;\n  }\n\n  const [left, top, right, bottom] = parts.map((p) => parseInt(p.trim(), 10));\n  if (isNaN(left) || isNaN(top) || isNaN(right) || isNaN(bottom)) {\n    return null;\n  }\n\n  return { left, top, right, bottom };\n}\n\n/**\n * Normalize UIElement bounds field from string to object format if needed\n */\nfunction normalizeUIElement(element: any): UIElement {\n  if (element.bounds && typeof element.bounds === \"string\") {\n    const parsedBounds = parseBoundsString(element.bounds);\n    if (parsedBounds) {\n      element.bounds = parsedBounds;\n    }\n  }\n\n  // Recursively normalize children if present\n  if (element.children && Array.isArray(element.children)) {\n    element.children = element.children.map(normalizeUIElement);\n  }\n\n  return element;\n}\n\nconst PNG_MAGIC = new Uint8Array([\n  0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a,\n]);\nconst JPEG_MAGIC = new Uint8Array([0xff, 0xd8, 0xff]);\n\nfunction normalizeImageFormat(format: string, defaultValue: string): string {\n  const f = String(format || \"\")\n    .trim()\n    .toLowerCase();\n  if (!f) {\n    return defaultValue;\n  }\n  if (f === \"jpg\") {\n    return \"jpeg\";\n  }\n  return f;\n}\n\nfunction validateBase64String(base64String: string): void {\n  const s = String(base64String || \"\");\n  if (!s) {\n    throw new Error(\"Empty base64 string\");\n  }\n\n  const base64WithoutPadding = s.replace(/=+$/, \"\");\n  if (!/^[A-Za-z0-9+/]+$/.test(base64WithoutPadding)) {\n    throw new Error(\"Invalid base64 string format\");\n  }\n\n  if (s.length % 4 !== 0) {\n    throw new Error(\"Invalid base64 string length\");\n  }\n\n  const paddingMatch = s.match(/=+$/);\n  if (paddingMatch && paddingMatch[0].length > 2) {\n    throw new Error(\"Invalid base64 padding format\");\n  }\n}\n\nfunction base64ToUint8ArrayStrict(input: string): Uint8Array {\n  const s = String(input || \"\").trim();\n  validateBase64String(s);\n\n  if (typeof Buffer !== \"undefined\") {\n    return new Uint8Array(Buffer.from(s, \"base64\"));\n  }\n\n  const binary = atob(s);\n  const out = new Uint8Array(binary.length);\n  for (let i = 0; i < binary.length; i++) {\n    out[i] = binary.charCodeAt(i);\n  }\n  return out;\n}\n\nfunction startsWithMagic(bytes: Uint8Array, magic: Uint8Array): boolean {\n  if (bytes.length < magic.length) {\n    return false;\n  }\n  for (let i = 0; i < magic.length; i++) {\n    if (bytes[i] !== magic[i]) {\n      return false;\n    }\n  }\n  return true;\n}\n\nfunction detectImageFormat(bytes: Uint8Array): string {\n  if (startsWithMagic(bytes, PNG_MAGIC)) {\n    return \"png\";\n  }\n  if (startsWithMagic(bytes, JPEG_MAGIC)) {\n    return \"jpeg\";\n  }\n  return \"\";\n}\n\nfunction decodeBase64Image(\n  input: string,\n  expectedFormat: string\n): {\n  bytes: Uint8Array;\n  format: string;\n  width?: number;\n  height?: number;\n  type: string;\n  mimeType: string;\n} {\n  const s = String(input || \"\").trim();\n  if (!s) {\n    throw new Error(\"Empty image data\");\n  }\n  if (!s.startsWith(\"{\")) {\n    throw new Error(\"Screenshot tool returned non-JSON data\");\n  }\n\n  let obj: any;\n  try {\n    obj = JSON.parse(s);\n  } catch (e) {\n    throw new Error(\n      `Invalid screenshot JSON: ${e instanceof Error ? e.message : String(e)}`\n    );\n  }\n  if (!obj || typeof obj !== \"object\" || Array.isArray(obj)) {\n    throw new Error(\"Invalid screenshot JSON: expected object\");\n  }\n  const shotType = (obj as any).type;\n  const mimeType = (obj as any).mime_type;\n  const b64 = (obj as any).data;\n  if (typeof shotType !== \"string\" || !shotType.trim()) {\n    throw new Error(\n      \"Invalid screenshot JSON: expected non-empty string 'type'\"\n    );\n  }\n  if (typeof mimeType !== \"string\" || !mimeType.trim()) {\n    throw new Error(\n      \"Invalid screenshot JSON: expected non-empty string 'mime_type'\"\n    );\n  }\n  if (typeof b64 !== \"string\" || !b64.trim()) {\n    throw new Error(\"Screenshot JSON missing base64 field\");\n  }\n  const width = (obj as any).width;\n  const height = (obj as any).height;\n  if (width !== undefined && typeof width !== \"number\") {\n    throw new Error(\"Invalid screenshot JSON: expected number 'width'\");\n  }\n  if (height !== undefined && typeof height !== \"number\") {\n    throw new Error(\"Invalid screenshot JSON: expected number 'height'\");\n  }\n\n  const bytes = base64ToUint8ArrayStrict(b64);\n  const detected = detectImageFormat(bytes);\n  const fmt = normalizeImageFormat(expectedFormat, expectedFormat);\n  if (fmt === \"png\" && detected !== \"png\") {\n    throw new Error(\"Screenshot data does not match expected format 'png'\");\n  }\n  if (fmt === \"jpeg\" && detected !== \"jpeg\") {\n    throw new Error(\"Screenshot data does not match expected format 'jpeg'\");\n  }\n  const expectedMimeType =\n    fmt === \"png\" ? \"image/png\" : fmt === \"jpeg\" ? \"image/jpeg\" : \"\";\n  if (!expectedMimeType) {\n    throw new Error(`Unsupported format: ${JSON.stringify(expectedFormat)}`);\n  }\n  if (String(mimeType).trim().toLowerCase() !== expectedMimeType) {\n    throw new Error(\n      `Screenshot JSON mime_type does not match expected format: expected ${JSON.stringify(\n        expectedMimeType\n      )}, got ${JSON.stringify(mimeType)}`\n    );\n  }\n  return {\n    bytes,\n    format: detected || fmt,\n    width,\n    height,\n    type: String(shotType).trim(),\n    mimeType: String(mimeType).trim(),\n  };\n}\n\nexport class Mobile {\n  private session: MobileSession;\n\n  constructor(session: MobileSession) {\n    this.session = session;\n  }\n\n  /**\n   * Tap at specified coordinates on the mobile screen.\n   *\n   * @param x - X coordinate for the tap\n   * @param y - Y coordinate for the tap\n   * @returns Promise resolving to BoolResult with success status\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: process.env.AGENTBAY_API_KEY });\n   * const result = await agentBay.create({ imageId: 'mobile_latest' });\n   * if (result.success) {\n   *   const tapResult = await result.session.mobile.tap(100, 100);\n   *   console.log('Tap success:', tapResult.success);\n   *   await result.session.delete();\n   * }\n   * ```\n   */\n  async tap(x: number, y: number): Promise<BoolResult> {\n    const args = { x, y };\n    try {\n      const result = await this.session.callMcpTool(\"tap\", args, false);\n      return {\n        success: result.success || false,\n        requestId: result.requestId || \"\",\n        errorMessage: result.errorMessage || \"\",\n        data: result.success || false,\n      };\n    } catch (error) {\n      return {\n        success: false,\n        requestId: \"\",\n        errorMessage: `Failed to tap: ${\n          error instanceof Error ? error.message : String(error)\n        }`,\n        data: false,\n      };\n    }\n  }\n\n  /**\n   * Swipe from one position to another on the mobile screen.\n   *\n   * @param startX - Starting X coordinate\n   * @param startY - Starting Y coordinate\n   * @param endX - Ending X coordinate\n   * @param endY - Ending Y coordinate\n   * @param durationMs - Swipe duration in milliseconds. Default is 300\n   * @returns Promise resolving to BoolResult with success status\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: process.env.AGENTBAY_API_KEY });\n   * const result = await agentBay.create({ imageId: 'mobile_latest' });\n   * if (result.success) {\n   *   const swipeResult = await result.session.mobile.swipe(200, 400, 200, 100, 300);\n   *   console.log('Swipe success:', swipeResult.success);\n   *   await result.session.delete();\n   * }\n   * ```\n   */\n  async swipe(\n    startX: number,\n    startY: number,\n    endX: number,\n    endY: number,\n    durationMs = 300\n  ): Promise<BoolResult> {\n    const args = {\n      start_x: startX,\n      start_y: startY,\n      end_x: endX,\n      end_y: endY,\n      duration_ms: durationMs,\n    };\n    try {\n      const result = await this.session.callMcpTool(\"swipe\", args, false);\n      return {\n        success: result.success || false,\n        requestId: result.requestId || \"\",\n        errorMessage: result.errorMessage || \"\",\n        data: result.success || false,\n      };\n    } catch (error) {\n      return {\n        success: false,\n        requestId: \"\",\n        errorMessage: `Failed to swipe: ${\n          error instanceof Error ? error.message : String(error)\n        }`,\n        data: false,\n      };\n    }\n  }\n\n  /**\n   * Input text at the current focus position.\n   *\n   * @param text - Text to input\n   * @returns Promise resolving to BoolResult with success status\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: process.env.AGENTBAY_API_KEY });\n   * const result = await agentBay.create({ imageId: 'mobile_latest' });\n   * if (result.success) {\n   *   const inputResult = await result.session.mobile.inputText('Hello Mobile');\n   *   console.log('Text input successfully:', inputResult.success);\n   *   await result.session.delete();\n   * }\n   * ```\n   */\n  async inputText(text: string): Promise<BoolResult> {\n    const args = { text };\n    try {\n      const result = await this.session.callMcpTool(\"input_text\", args, false);\n      return {\n        success: result.success || false,\n        requestId: result.requestId || \"\",\n        errorMessage: result.errorMessage || \"\",\n        data: result.success || false,\n      };\n    } catch (error) {\n      return {\n        success: false,\n        requestId: \"\",\n        errorMessage: `Failed to input text: ${\n          error instanceof Error ? error.message : String(error)\n        }`,\n        data: false,\n      };\n    }\n  }\n\n  /**\n   * Send Android key code.\n   *\n   * @param key - Android key code (e.g., 4 for BACK, 3 for HOME, 24 for VOLUME_UP)\n   * @returns Promise resolving to BoolResult with success status\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: process.env.AGENTBAY_API_KEY });\n   * const result = await agentBay.create({ imageId: 'mobile_latest' });\n   * if (result.success) {\n   *   const keyResult = await result.session.mobile.sendKey(4);\n   *   console.log('BACK key sent:', keyResult.success);\n   *   await result.session.delete();\n   * }\n   * ```\n   */\n  async sendKey(key: number): Promise<BoolResult> {\n    const args = { key };\n    try {\n      const result = await this.session.callMcpTool(\"send_key\", args, false);\n      return {\n        success: result.success || false,\n        requestId: result.requestId || \"\",\n        errorMessage: result.errorMessage || \"\",\n        data: result.success || false,\n      };\n    } catch (error) {\n      return {\n        success: false,\n        requestId: \"\",\n        errorMessage: `Failed to send key: ${\n          error instanceof Error ? error.message : String(error)\n        }`,\n        data: false,\n      };\n    }\n  }\n\n  /**\n   * Get clickable UI elements.\n   */\n  async getClickableUIElements(timeoutMs = 5000): Promise<UIElementsResult> {\n    const args = { timeout_ms: timeoutMs };\n    try {\n      const result = await this.session.callMcpTool(\n        \"get_clickable_ui_elements\",\n        args,\n        false\n      );\n\n      if (!result.success) {\n        return {\n          success: false,\n          requestId: result.requestId || \"\",\n          errorMessage:\n            result.errorMessage || \"Failed to get clickable UI elements\",\n          elements: [],\n          raw: result.data || \"\",\n          format: \"json\",\n        };\n      }\n\n      if (!result.data) {\n        return {\n          success: true,\n          requestId: result.requestId || \"\",\n          errorMessage: \"\",\n          elements: [],\n          raw: \"\",\n          format: \"json\",\n        };\n      }\n\n      try {\n        const elements = JSON.parse(result.data);\n        // Normalize bounds from string to object format if needed\n        const normalizedElements = (elements || []).map(normalizeUIElement);\n        return {\n          success: true,\n          requestId: result.requestId || \"\",\n          errorMessage: \"\",\n          elements: normalizedElements,\n          raw: result.data || \"\",\n          format: \"json\",\n        };\n      } catch (parseError) {\n        return {\n          success: false,\n          requestId: result.requestId || \"\",\n          errorMessage: `Failed to parse UI elements: ${parseError}`,\n          elements: [],\n          raw: result.data || \"\",\n          format: \"json\",\n        };\n      }\n    } catch (error) {\n      return {\n        success: false,\n        requestId: \"\",\n        errorMessage: `Failed to get clickable UI elements: ${\n          error instanceof Error ? error.message : String(error)\n        }`,\n        elements: [],\n        raw: \"\",\n        format: \"json\",\n      };\n    }\n  }\n\n  /**\n   * Get all UI elements.\n   */\n  async getAllUIElements(\n    timeoutMs = 3000,\n    format: \"json\" | \"xml\" = \"json\"\n  ): Promise<UIElementsResult> {\n    const formatNorm =\n      ((format || \"json\") as string).trim().toLowerCase() || \"json\";\n    const args = { timeout_ms: timeoutMs, format: formatNorm };\n    try {\n      const result = await this.session.callMcpTool(\n        \"get_all_ui_elements\",\n        args,\n        false\n      );\n\n      if (!result.success) {\n        return {\n          success: false,\n          requestId: result.requestId || \"\",\n          errorMessage: result.errorMessage || \"Failed to get all UI elements\",\n          elements: [],\n          raw: result.data || \"\",\n          format: formatNorm === \"xml\" ? \"xml\" : \"json\",\n        };\n      }\n\n      if (!result.data) {\n        return {\n          success: true,\n          requestId: result.requestId || \"\",\n          errorMessage: \"\",\n          elements: [],\n          raw: \"\",\n          format: formatNorm === \"xml\" ? \"xml\" : \"json\",\n        };\n      }\n\n      if (formatNorm === \"xml\") {\n        return {\n          success: true,\n          requestId: result.requestId || \"\",\n          errorMessage: \"\",\n          elements: [],\n          raw: result.data || \"\",\n          format: \"xml\",\n        };\n      }\n\n      if (formatNorm !== \"json\") {\n        return {\n          success: false,\n          requestId: result.requestId || \"\",\n          errorMessage: `Unsupported UI elements format: ${JSON.stringify(\n            format\n          )}. Supported values: \"json\", \"xml\".`,\n          elements: [],\n          raw: result.data || \"\",\n          format: \"json\",\n        };\n      }\n\n      try {\n        const elements = JSON.parse(result.data);\n        // Normalize bounds from string to object format if needed\n        const normalizedElements = (elements || []).map(normalizeUIElement);\n        return {\n          success: true,\n          requestId: result.requestId || \"\",\n          errorMessage: \"\",\n          elements: normalizedElements,\n          raw: result.data || \"\",\n          format: \"json\",\n        };\n      } catch (parseError) {\n        return {\n          success: false,\n          requestId: result.requestId || \"\",\n          errorMessage: `Failed to parse UI elements: ${parseError}`,\n          elements: [],\n          raw: result.data || \"\",\n          format: \"json\",\n        };\n      }\n    } catch (error) {\n      return {\n        success: false,\n        requestId: \"\",\n        errorMessage: `Failed to get all UI elements: ${\n          error instanceof Error ? error.message : String(error)\n        }`,\n        elements: [],\n        raw: \"\",\n        format: formatNorm === \"xml\" ? \"xml\" : \"json\",\n      };\n    }\n  }\n\n  /**\n   * Get installed apps.\n   */\n  async getInstalledApps(\n    startMenu = false,\n    desktop = true,\n    ignoreSystemApps = true\n  ): Promise<InstalledAppsResult> {\n    const args = {\n      start_menu: startMenu,\n      desktop,\n      ignore_system_app: ignoreSystemApps,\n    };\n    try {\n      const result = await this.session.callMcpTool(\n        \"get_installed_apps\",\n        args,\n        false\n      );\n\n      if (!result.success) {\n        return {\n          success: false,\n          requestId: result.requestId || \"\",\n          errorMessage: result.errorMessage || \"Failed to get installed apps\",\n          apps: [],\n        };\n      }\n\n      if (!result.data) {\n        return {\n          success: true,\n          requestId: result.requestId || \"\",\n          errorMessage: \"\",\n          apps: [],\n        };\n      }\n\n      try {\n        const apps = JSON.parse(result.data);\n        return {\n          success: true,\n          requestId: result.requestId || \"\",\n          errorMessage: \"\",\n          apps: apps || [],\n        };\n      } catch (parseError) {\n        return {\n          success: false,\n          requestId: result.requestId || \"\",\n          errorMessage: `Failed to parse installed apps: ${parseError}`,\n          apps: [],\n        };\n      }\n    } catch (error) {\n      return {\n        success: false,\n        requestId: \"\",\n        errorMessage: `Failed to get installed apps: ${\n          error instanceof Error ? error.message : String(error)\n        }`,\n        apps: [],\n      };\n    }\n  }\n\n  /**\n   * Start an app.\n   *\n   * @param startCmd - Start command using \"monkey -p\" format (e.g., 'monkey -p com.android.settings')\n   * @param workDirectory - Optional working directory for the app\n   * @param activity - Optional activity name to launch\n   * @returns Promise resolving to ProcessResult containing launched process information\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: process.env.AGENTBAY_API_KEY });\n   * const result = await agentBay.create({ imageId: 'mobile_latest' });\n   * if (result.success) {\n   *   const startResult = await result.session.mobile.startApp('monkey -p com.android.settings');\n   *   console.log('App started:', startResult.success);\n   *   await result.session.delete();\n   * }\n   * ```\n   */\n  async startApp(\n    startCmd: string,\n    workDirectory = \"\",\n    activity = \"\"\n  ): Promise<ProcessResult> {\n    const args = {\n      start_cmd: startCmd,\n      work_directory: workDirectory,\n      activity,\n    };\n    try {\n      const result = await this.session.callMcpTool(\"start_app\", args, false);\n\n      if (!result.success) {\n        return {\n          success: false,\n          requestId: result.requestId || \"\",\n          errorMessage: result.errorMessage || \"Failed to start app\",\n          processes: [],\n        };\n      }\n\n      if (!result.data) {\n        return {\n          success: true,\n          requestId: result.requestId || \"\",\n          errorMessage: \"\",\n          processes: [],\n        };\n      }\n\n      try {\n        const processes = JSON.parse(result.data);\n        return {\n          success: true,\n          requestId: result.requestId || \"\",\n          errorMessage: \"\",\n          processes: processes || [],\n        };\n      } catch (parseError) {\n        return {\n          success: false,\n          requestId: result.requestId || \"\",\n          errorMessage: `Failed to parse process result: ${parseError}`,\n          processes: [],\n        };\n      }\n    } catch (error) {\n      return {\n        success: false,\n        requestId: \"\",\n        errorMessage: `Failed to start app: ${\n          error instanceof Error ? error.message : String(error)\n        }`,\n        processes: [],\n      };\n    }\n  }\n\n  /**\n   * Stop app by command.\n   *\n   * @param stopCmd - Package name of the app to stop (e.g., 'com.android.settings')\n   * @returns Promise resolving to BoolResult with success status\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: process.env.AGENTBAY_API_KEY });\n   * const result = await agentBay.create({ imageId: 'mobile_latest' });\n   * if (result.success) {\n   *   await result.session.mobile.startApp('monkey -p com.android.settings');\n   *   const stopResult = await result.session.mobile.stopAppByCmd('com.android.settings');\n   *   console.log('App stopped:', stopResult.success);\n   *   await result.session.delete();\n   * }\n   * ```\n   */\n  async stopAppByCmd(stopCmd: string): Promise<BoolResult> {\n    const args = { stop_cmd: stopCmd };\n    try {\n      const result = await this.session.callMcpTool(\n        \"stop_app_by_cmd\",\n        args,\n        false\n      );\n      return {\n        success: result.success || false,\n        requestId: result.requestId || \"\",\n        errorMessage: result.errorMessage || \"\",\n        data: result.success || false,\n      };\n    } catch (error) {\n      return {\n        success: false,\n        requestId: \"\",\n        errorMessage: `Failed to stop app: ${\n          error instanceof Error ? error.message : String(error)\n        }`,\n        data: false,\n      };\n    }\n  }\n\n  /**\n   * Take a screenshot of the current mobile screen.\n   *\n   * @returns Promise resolving to ScreenshotResult containing screenshot URL\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: process.env.AGENTBAY_API_KEY });\n   * const result = await agentBay.create({ imageId: 'mobile_latest' });\n   * if (result.success) {\n   *   const screenshotResult = await result.session.mobile.screenshot();\n   *   console.log('Screenshot URL:', screenshotResult.data);\n   *   await result.session.delete();\n   * }\n   * ```\n   */\n  async screenshot(): Promise<ScreenshotResult> {\n    if (this.session.linkUrl) {\n      return {\n        success: false,\n        requestId: \"\",\n        errorMessage:\n          \"This cloud environment does not support `screenshot()`. Please use `beta_take_screenshot()` instead.\",\n        data: \"\",\n      };\n    }\n    try {\n      const result = await this.session.callMcpTool(\n        \"system_screenshot\",\n        {},\n        false\n      );\n\n      if (!result.success) {\n        return {\n          success: false,\n          requestId: result.requestId || \"\",\n          errorMessage: result.errorMessage || \"Failed to take screenshot\",\n          data: \"\",\n        };\n      }\n\n      return {\n        success: true,\n        requestId: result.requestId || \"\",\n        errorMessage: \"\",\n        data: result.data || \"\",\n      };\n    } catch (error) {\n      return {\n        success: false,\n        requestId: \"\",\n        errorMessage: `Failed to take screenshot: ${\n          error instanceof Error ? error.message : String(error)\n        }`,\n        data: \"\",\n      };\n    }\n  }\n\n  /**\n   * Capture the current screen and return raw image bytes.\n   *\n   * @param format - Output image format (\"png\", \"jpeg\", or \"jpg\"). Default is \"png\"\n   * @returns Promise resolving to BetaScreenshotResult containing image bytes\n   */\n  async betaTakeScreenshot(format = \"png\"): Promise<BetaScreenshotResult> {\n    const formatNorm = normalizeImageFormat(format, \"png\");\n    if (!this.session.linkUrl) {\n      return {\n        success: false,\n        requestId: \"\",\n        errorMessage:\n          \"This cloud environment does not support `beta_take_screenshot()`. Please use `screenshot()` instead.\",\n        data: new Uint8Array(),\n        type: \"\",\n        mimeType: \"\",\n      };\n    }\n    if (formatNorm !== \"png\" && formatNorm !== \"jpeg\") {\n      return {\n        success: false,\n        requestId: \"\",\n        errorMessage: `Unsupported format: ${JSON.stringify(\n          format\n        )}. Supported values: \"png\", \"jpeg\".`,\n        data: new Uint8Array(),\n        type: \"\",\n        mimeType: \"\",\n      };\n    }\n    try {\n      const result = await this.session.callMcpTool(\n        \"screenshot\",\n        { format: formatNorm },\n        false\n      );\n      const requestId = result.requestId || \"\";\n      if (!result.success) {\n        return {\n          success: false,\n          requestId,\n          errorMessage: result.errorMessage || \"Failed to take screenshot\",\n          data: new Uint8Array(),\n          type: \"\",\n          mimeType: \"\",\n        };\n      }\n      const decoded = decodeBase64Image(String(result.data || \"\"), formatNorm);\n      return {\n        success: true,\n        requestId,\n        errorMessage: \"\",\n        data: decoded.bytes,\n        type: decoded.type,\n        mimeType: decoded.mimeType,\n        width: decoded.width,\n        height: decoded.height,\n      };\n    } catch (error) {\n      return {\n        success: false,\n        requestId: \"\",\n        errorMessage: `Failed to take screenshot: ${\n          error instanceof Error ? error.message : String(error)\n        }`,\n        data: new Uint8Array(),\n        type: \"\",\n        mimeType: \"\",\n      };\n    }\n  }\n\n  /**\n   * Capture a long screenshot and return raw image bytes.\n   *\n   * @param maxScreens - Number of screens to stitch (range: [2, 10])\n   * @param format - Output image format (\"png\", \"jpeg\", or \"jpg\"). Default is \"png\"\n   * @param quality - JPEG quality (range: [1, 100])\n   */\n  async betaTakeLongScreenshot(\n    maxScreens = 4,\n    format = \"png\",\n    quality?: number\n  ): Promise<BetaScreenshotResult> {\n    const formatNorm = normalizeImageFormat(format, \"png\");\n    if (!Number.isInteger(maxScreens) || maxScreens < 2 || maxScreens > 10) {\n      return {\n        success: false,\n        requestId: \"\",\n        errorMessage:\n          \"Invalid maxScreens: must be an integer in the range [2, 10]\",\n        data: new Uint8Array(),\n        type: \"\",\n        mimeType: \"\",\n      };\n    }\n    if (formatNorm !== \"png\" && formatNorm !== \"jpeg\") {\n      return {\n        success: false,\n        requestId: \"\",\n        errorMessage: `Unsupported format: ${JSON.stringify(\n          format\n        )}. Supported values: \"png\", \"jpeg\".`,\n        data: new Uint8Array(),\n        type: \"\",\n        mimeType: \"\",\n      };\n    }\n    if (quality !== undefined) {\n      if (!Number.isInteger(quality) || quality < 1 || quality > 100) {\n        return {\n          success: false,\n          requestId: \"\",\n          errorMessage:\n            \"Invalid quality: must be an integer in the range [1, 100]\",\n          data: new Uint8Array(),\n          type: \"\",\n          mimeType: \"\",\n        };\n      }\n    }\n\n    try {\n      const args: Record<string, any> = {\n        max_screens: maxScreens,\n        format: formatNorm,\n      };\n      if (quality !== undefined) {\n        args.quality = quality;\n      }\n\n      const result = await this.session.callMcpTool(\n        \"long_screenshot\",\n        args,\n        false\n      );\n      const requestId = result.requestId || \"\";\n      if (!result.success) {\n        return {\n          success: false,\n          requestId,\n          errorMessage: result.errorMessage || \"Failed to take long screenshot\",\n          data: new Uint8Array(),\n          type: \"\",\n          mimeType: \"\",\n        };\n      }\n\n      const decoded = decodeBase64Image(String(result.data || \"\"), formatNorm);\n      return {\n        success: true,\n        requestId,\n        errorMessage: \"\",\n        data: decoded.bytes,\n        type: decoded.type,\n        mimeType: decoded.mimeType,\n        width: decoded.width,\n        height: decoded.height,\n      };\n    } catch (error) {\n      return {\n        success: false,\n        requestId: \"\",\n        errorMessage: `Failed to take long screenshot: ${\n          error instanceof Error ? error.message : String(error)\n        }`,\n        data: new Uint8Array(),\n        type: \"\",\n        mimeType: \"\",\n      };\n    }\n  }\n\n  /**\n   * Retrieves the ADB connection URL for the mobile environment.\n   * This method is only supported in mobile environments (mobile_latest image).\n   * It uses the provided ADB public key to establish the connection and returns\n   * the ADB connect URL.\n   *\n   * @param adbkeyPub - ADB public key for authentication\n   * @returns AdbUrlResult containing the ADB connection URL\n   */\n  async getAdbUrl(adbkeyPub: string): Promise<AdbUrlResult> {\n    try {\n      // Build options JSON with adbkey_pub\n      const optionsJson = JSON.stringify({ adbkey_pub: adbkeyPub });\n\n      // Call get_adb_link API\n      const { GetAdbLinkRequest } = await import(\"../api/models/model\");\n      const request = new GetAdbLinkRequest({\n        authorization: `Bearer ${this.session.getAPIKey()}`,\n        sessionId: this.session.sessionId,\n        option: optionsJson,\n      });\n\n      const response = await this.session\n        .getAgentBay()\n        .getClient()\n        .getAdbLink(request);\n\n      // Check response\n      if (response.body && response.body.success && response.body.data) {\n        const adbUrl = response.body.data.url;\n        const requestId = response.body.requestId || \"\";\n        log(`✅ get_adb_url completed successfully. RequestID: ${requestId}`);\n        return {\n          success: true,\n          requestId: requestId,\n          errorMessage: \"\",\n          data: adbUrl,\n          url: adbUrl,\n        };\n      } else {\n        const errorMsg = response.body?.message || \"Unknown error\";\n        const requestId = response.body?.requestId || \"\";\n        logError(`❌ Failed to get ADB URL: ${errorMsg}`);\n        return {\n          success: false,\n          requestId: requestId,\n          errorMessage: errorMsg,\n          data: undefined,\n          url: undefined,\n        };\n      }\n    } catch (error) {\n      const errorMsg = `Failed to get ADB URL: ${\n        error instanceof Error ? error.message : String(error)\n      }`;\n      logError(`❌ ${errorMsg}`);\n      return {\n        success: false,\n        requestId: \"\",\n        errorMessage: errorMsg,\n        data: undefined,\n        url: undefined,\n      };\n    }\n  }\n\n  /**\n   * Configure mobile device settings based on MobileExtraConfig.\n   * This method applies various mobile configuration settings including\n   * resolution lock and app access management.\n   *\n   * @param config - The mobile configuration to apply\n   * @returns OperationResult indicating success or failure\n   */\n  async configure(config: MobileExtraConfig): Promise<OperationResult> {\n    try {\n      if (!config) {\n        return {\n          success: false,\n          requestId: \"\",\n          errorMessage: \"No mobile configuration provided\",\n        };\n      }\n\n      // Configure resolution lock\n      const resolutionResult = await this.setResolutionLock(\n        config.lockResolution\n      );\n      if (!resolutionResult.success) {\n        return {\n          success: false,\n          requestId: resolutionResult.requestId,\n          errorMessage: `Failed to set resolution lock: ${resolutionResult.errorMessage}`,\n        };\n      }\n\n      // Configure app management rules\n      if (config.appManagerRule && config.appManagerRule.ruleType) {\n        const appRule = config.appManagerRule;\n        const packageNames = appRule.appPackageNameList;\n\n        if (\n          packageNames &&\n          packageNames.length > 0 &&\n          (appRule.ruleType === \"White\" || appRule.ruleType === \"Black\")\n        ) {\n          let appResult: OperationResult;\n          if (appRule.ruleType === \"White\") {\n            appResult = await this.setAppWhitelist(packageNames);\n          } else {\n            appResult = await this.setAppBlacklist(packageNames);\n          }\n\n          if (!appResult.success) {\n            return {\n              success: false,\n              requestId: appResult.requestId,\n              errorMessage: `Failed to set app ${appRule.ruleType.toLowerCase()}list: ${\n                appResult.errorMessage\n              }`,\n            };\n          }\n        } else if (packageNames && packageNames.length === 0) {\n          return {\n            success: false,\n            requestId: \"\",\n            errorMessage: `No package names provided for ${appRule.ruleType} list`,\n          };\n        }\n      }\n\n      // Configure navigation bar visibility\n      if (config.hideNavigationBar !== undefined) {\n        const navResult = await this.setNavigationBarVisibility(\n          config.hideNavigationBar\n        );\n        if (!navResult.success) {\n          return {\n            success: false,\n            requestId: navResult.requestId,\n            errorMessage: `Failed to set navigation bar visibility: ${navResult.errorMessage}`,\n          };\n        }\n      }\n\n      // Configure uninstall blacklist\n      if (config.uninstallBlacklist && config.uninstallBlacklist.length > 0) {\n        const uninstallResult = await this.setUninstallBlacklist(\n          config.uninstallBlacklist\n        );\n        if (!uninstallResult.success) {\n          return {\n            success: false,\n            requestId: uninstallResult.requestId,\n            errorMessage: `Failed to set uninstall blacklist: ${uninstallResult.errorMessage}`,\n          };\n        }\n      }\n\n      log(\"Mobile configuration applied successfully\");\n      return {\n        success: true,\n        requestId: \"\",\n        errorMessage: \"\",\n      };\n    } catch (error) {\n      const errorMsg = `Failed to configure mobile: ${\n        error instanceof Error ? error.message : String(error)\n      }`;\n      logError(errorMsg);\n      return {\n        success: false,\n        requestId: \"\",\n        errorMessage: errorMsg,\n      };\n    }\n  }\n\n  /**\n   * Set display resolution lock for mobile devices.\n   *\n   * @param enable - Whether to enable resolution lock\n   * @returns OperationResult indicating success or failure\n   */\n  async setResolutionLock(enable: boolean): Promise<OperationResult> {\n    try {\n      const templateName = enable\n        ? \"resolution_lock_enable\"\n        : \"resolution_lock_disable\";\n      const template = getMobileCommandTemplate(templateName);\n\n      if (!template) {\n        return {\n          success: false,\n          requestId: \"\",\n          errorMessage: `Resolution lock template not found: ${templateName}`,\n        };\n      }\n\n      const description = `Resolution lock ${enable ? \"enable\" : \"disable\"}`;\n      return await this.executeCommand(template, description);\n    } catch (error) {\n      return {\n        success: false,\n        requestId: \"\",\n        errorMessage: `Failed to set resolution lock: ${\n          error instanceof Error ? error.message : String(error)\n        }`,\n      };\n    }\n  }\n\n  /**\n   * Set app whitelist configuration.\n   *\n   * @param packageNames - List of package names to whitelist\n   * @returns OperationResult indicating success or failure\n   */\n  async setAppWhitelist(packageNames: string[]): Promise<OperationResult> {\n    try {\n      const template = getMobileCommandTemplate(\"app_whitelist\");\n      if (!template) {\n        return {\n          success: false,\n          requestId: \"\",\n          errorMessage: \"App whitelist template not found\",\n        };\n      }\n\n      // Replace placeholder with actual package names (newline-separated for file content)\n      const packageList = packageNames.join(\"\\n\");\n      const command = replaceTemplatePlaceholders(template, {\n        package_list: packageList,\n      });\n\n      const description = `App whitelist configuration (${packageNames.length} packages)`;\n      return await this.executeCommand(command, description);\n    } catch (error) {\n      return {\n        success: false,\n        requestId: \"\",\n        errorMessage: `Failed to set app whitelist: ${\n          error instanceof Error ? error.message : String(error)\n        }`,\n      };\n    }\n  }\n\n  /**\n   * Set app blacklist configuration.\n   *\n   * @param packageNames - List of package names to blacklist\n   * @returns OperationResult indicating success or failure\n   */\n  async setAppBlacklist(packageNames: string[]): Promise<OperationResult> {\n    try {\n      const template = getMobileCommandTemplate(\"app_blacklist\");\n      if (!template) {\n        return {\n          success: false,\n          requestId: \"\",\n          errorMessage: \"App blacklist template not found\",\n        };\n      }\n\n      // Replace placeholder with actual package names (newline-separated for file content)\n      const packageList = packageNames.join(\"\\n\");\n      const command = replaceTemplatePlaceholders(template, {\n        package_list: packageList,\n      });\n\n      const description = `App blacklist configuration (${packageNames.length} packages)`;\n      return await this.executeCommand(command, description);\n    } catch (error) {\n      return {\n        success: false,\n        requestId: \"\",\n        errorMessage: `Failed to set app blacklist: ${\n          error instanceof Error ? error.message : String(error)\n        }`,\n      };\n    }\n  }\n\n  /**\n   * Set navigation bar visibility for mobile devices.\n   *\n   * @param hide - True to hide navigation bar, false to show navigation bar\n   * @returns OperationResult indicating success or failure\n   */\n  async setNavigationBarVisibility(hide: boolean): Promise<OperationResult> {\n    try {\n      const templateName = hide ? \"hide_navigation_bar\" : \"show_navigation_bar\";\n      const template = getMobileCommandTemplate(templateName);\n\n      if (!template) {\n        return {\n          success: false,\n          requestId: \"\",\n          errorMessage: `Navigation bar template not found: ${templateName}`,\n        };\n      }\n\n      const description = `Navigation bar visibility (hide: ${hide})`;\n      return await this.executeCommand(template, description);\n    } catch (error) {\n      return {\n        success: false,\n        requestId: \"\",\n        errorMessage: `Failed to set navigation bar visibility: ${\n          error instanceof Error ? error.message : String(error)\n        }`,\n      };\n    }\n  }\n\n  /**\n   * Set uninstall protection blacklist for mobile devices.\n   *\n   * @param packageNames - List of Android package names to protect from uninstallation\n   * @returns OperationResult indicating success or failure\n   */\n  async setUninstallBlacklist(\n    packageNames: string[]\n  ): Promise<OperationResult> {\n    try {\n      const template = getMobileCommandTemplate(\"uninstall_blacklist\");\n      if (!template) {\n        return {\n          success: false,\n          requestId: \"\",\n          errorMessage: \"Uninstall blacklist template not found\",\n        };\n      }\n\n      // Use newline-separated format for uninstall blacklist file content\n      const packageList = packageNames.join(\"\\n\");\n      const timestamp = Math.floor(Date.now() / 1000).toString();\n      const command = replaceTemplatePlaceholders(template, {\n        package_list: packageList,\n        timestamp: timestamp,\n      });\n\n      const description = `Uninstall blacklist configuration (${packageNames.length} packages)`;\n      return await this.executeCommand(command, description);\n    } catch (error) {\n      return {\n        success: false,\n        requestId: \"\",\n        errorMessage: `Failed to set uninstall blacklist: ${\n          error instanceof Error ? error.message : String(error)\n        }`,\n      };\n    }\n  }\n\n  /**\n   * Execute a command template for mobile configuration.\n   *\n   * @param command - The command to execute\n   * @param description - Description of the operation\n   * @returns OperationResult indicating success or failure\n   */\n  private async executeCommand(\n    command: string,\n    description: string\n  ): Promise<OperationResult> {\n    try {\n      log(`Executing ${description}`);\n\n      // Use the session's command module to execute the command with longer timeout for mobile operations\n      const result = await (this.session as any).command.executeCommand(\n        command,\n        10000\n      );\n\n      if (result && result.success) {\n        log(`✅ ${description} completed successfully`);\n        if (result.output) {\n          log(`Command output: ${result.output}`);\n        }\n        return {\n          success: true,\n          requestId: result.requestId || \"\",\n          errorMessage: \"\",\n        };\n      } else {\n        const errorMessage =\n          result?.errorMessage || `Failed to execute ${description}`;\n        logError(`Failed to execute ${description}: ${errorMessage}`);\n        return {\n          success: false,\n          requestId: result?.requestId || \"\",\n          errorMessage: errorMessage,\n        };\n      }\n    } catch (error) {\n      const errorMsg = `Failed to execute ${description}: ${\n        error instanceof Error ? error.message : String(error)\n      }`;\n      logError(errorMsg);\n      return {\n        success: false,\n        requestId: \"\",\n        errorMessage: errorMsg,\n      };\n    }\n  }\n}\n","export { Oss } from \"./oss\";\n","import { Session } from \"../session\";\nimport {\n  OSSClientResult,\n  OSSUploadResult,\n  OSSDownloadResult,\n} from \"../types/api-response\";\n\n/**\n * Handles OSS operations in the AgentBay cloud environment.\n */\nexport class Oss {\n  private session: Session;\n\n  /**\n   * Initialize an Oss object.\n   *\n   * @param session - The Session instance that this Oss belongs to.\n   */\n  constructor(session: Session) {\n    this.session = session;\n  }\n\n  /**\n   * Sanitizes error messages to remove sensitive information like API keys.\n   *\n   * @param error - The error to sanitize\n   * @returns The sanitized error\n   */\n  private sanitizeError(error: any): any {\n    if (!error) {\n      return error;\n    }\n\n    const errorString = String(error);\n    return errorString.replace(/Bearer\\s+[^\\s]+/g, \"Bearer [REDACTED]\");\n  }\n\n  /**\n   * Initialize OSS environment variables with the specified STS temporary credentials.\n   * Corresponds to Python's env_init() method\n   *\n   * @param accessKeyId - The access key ID from STS temporary credentials\n   * @param accessKeySecret - The access key secret from STS temporary credentials\n   * @param securityToken - The security token from STS temporary credentials (required)\n   * @param endpoint - The OSS endpoint (optional)\n   * @param region - The OSS region (optional)\n   * @returns OSSClientResult with client configuration and requestId\n   * @throws APIError if the operation fails.\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: 'your_api_key' });\n   * const createResult = await agentBay.create();\n   * if (createResult.success) {\n   *   const result = await createResult.session.oss.envInit('sts_key_id', 'sts_key_secret', 'sts_token', 'oss-cn-hangzhou.aliyuncs.com', 'cn-hangzhou');\n   *   console.log('OSS initialized:', result.success);\n   *   await createResult.session.delete();\n   * }\n   * ```\n   */\n  async envInit(\n    accessKeyId: string,\n    accessKeySecret: string,\n    securityToken: string,\n    endpoint?: string,\n    region?: string\n  ): Promise<OSSClientResult> {\n    try {\n      const args = {\n        access_key_id: accessKeyId,\n        access_key_secret: accessKeySecret,\n        security_token: securityToken,\n        endpoint: endpoint || \"\",\n        region: region || \"\",\n      };\n      const result = await this.session.callMcpTool(\n        \"oss_env_init\",\n        args,\n        false\n      );\n\n      if (result.success) {\n        if (result.data) {\n          const clientConfigRaw = result.data;\n          // Check if data contains \"failed\" field\n          if (\n            typeof clientConfigRaw === \"string\" &&\n            clientConfigRaw.toLowerCase().includes(\"failed\")\n          ) {\n            return {\n              requestId: result.requestId,\n              success: false,\n              clientConfig: \"\",\n              errorMessage: `OSS environment initialization failed: ${clientConfigRaw}`,\n            };\n          }\n          return {\n            requestId: result.requestId,\n            success: true,\n            clientConfig: clientConfigRaw,\n            errorMessage: \"\",\n          };\n        } else {\n          return {\n            requestId: result.requestId,\n            success: false,\n            clientConfig: \"\",\n            errorMessage: \"Failed to initialize OSS environment\",\n          };\n        }\n      } else {\n        return {\n          requestId: result.requestId,\n          success: false,\n          clientConfig: \"\",\n          errorMessage:\n            result.errorMessage || \"Failed to initialize OSS environment\",\n        };\n      }\n    } catch (error) {\n      return {\n        requestId: \"\",\n        success: false,\n        clientConfig: \"\",\n        errorMessage: `Failed to initialize OSS environment: ${error}`,\n      };\n    }\n  }\n\n  /**\n   * Upload a file to OSS.\n   * Corresponds to Python's upload() method\n   *\n   * @param bucket - The OSS bucket name\n   * @param object - The OSS object key\n   * @param path - The local file path to upload\n   * @returns OSSUploadResult with upload result and requestId\n   * @throws APIError if the operation fails.\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: 'your_api_key' });\n   * const createResult = await agentBay.create();\n   * if (createResult.success) {\n   *   await createResult.session.oss.envInit('key_id', 'key_secret', 'token', 'oss-cn-hangzhou.aliyuncs.com', 'cn-hangzhou');\n   *   const result = await createResult.session.oss.upload('my-bucket', 'my-folder/file.txt', '/path/to/local/file.txt');\n   *   console.log('Upload success:', result.success);\n   *   await createResult.session.delete();\n   * }\n   * ```\n   */\n  async upload(\n    bucket: string,\n    object: string,\n    path: string\n  ): Promise<OSSUploadResult> {\n    try {\n      const args = {\n        bucket,\n        object,\n        path,\n      };\n      const result = await this.session.callMcpTool(\"oss_upload\", args, false);\n\n      return {\n        requestId: result.requestId,\n        success: result.success,\n        content: result.data,\n        errorMessage: result.errorMessage,\n      };\n    } catch (error) {\n      return {\n        requestId: \"\",\n        success: false,\n        content: \"\",\n        errorMessage: `Failed to upload file: ${error}`,\n      };\n    }\n  }\n\n  /**\n   * Upload a file to OSS using an anonymous URL.\n   * Corresponds to Python's upload_anonymous() method\n   *\n   * @param url - The anonymous upload URL\n   * @param path - The local file path to upload\n   * @returns OSSUploadResult with upload result and requestId\n   * @throws APIError if the operation fails.\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: 'your_api_key' });\n   * const createResult = await agentBay.create();\n   * if (createResult.success) {\n   *   const result = await createResult.session.oss.uploadAnonymous('https://example.com/upload', '/path/to/local/file.txt');\n   *   console.log('Anonymous upload success:', result.success);\n   *   await createResult.session.delete();\n   * }\n   * ```\n   */\n  async uploadAnonymous(url: string, path: string): Promise<OSSUploadResult> {\n    try {\n      const args = {\n        url,\n        path,\n      };\n      const result = await this.session.callMcpTool(\n        \"oss_upload_annon\",\n        args,\n        false\n      );\n\n      return {\n        requestId: result.requestId,\n        success: result.success,\n        content: result.data,\n        errorMessage: result.errorMessage,\n      };\n    } catch (error) {\n      return {\n        requestId: \"\",\n        success: false,\n        content: \"\",\n        errorMessage: `Failed to upload file anonymously: ${error}`,\n      };\n    }\n  }\n\n  /**\n   * Download a file from OSS.\n   * Corresponds to Python's download() method\n   *\n   * @param bucket - The OSS bucket name\n   * @param object - The OSS object key\n   * @param path - The local file path to save the downloaded file\n   * @returns OSSDownloadResult with download result and requestId\n   * @throws APIError if the operation fails.\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: 'your_api_key' });\n   * const createResult = await agentBay.create();\n   * if (createResult.success) {\n   *   await createResult.session.oss.envInit('key_id', 'key_secret', 'token', 'oss-cn-hangzhou.aliyuncs.com', 'cn-hangzhou');\n   *   const result = await createResult.session.oss.download('my-bucket', 'my-folder/file.txt', '/path/to/save/file.txt');\n   *   console.log('Download success:', result.success);\n   *   await createResult.session.delete();\n   * }\n   * ```\n   */\n  async download(\n    bucket: string,\n    object: string,\n    path: string\n  ): Promise<OSSDownloadResult> {\n    try {\n      const args = {\n        bucket,\n        object,\n        path,\n      };\n      const result = await this.session.callMcpTool(\n        \"oss_download\",\n        args,\n        false\n      );\n\n      return {\n        requestId: result.requestId,\n        success: result.success,\n        content: result.data,\n        errorMessage: result.errorMessage,\n      };\n    } catch (error) {\n      return {\n        requestId: \"\",\n        success: false,\n        content: \"\",\n        errorMessage: `Failed to download file: ${error}`,\n      };\n    }\n  }\n\n  /**\n   * Download a file from OSS using an anonymous URL.\n   * Corresponds to Python's download_anonymous() method\n   *\n   * @param url - The anonymous download URL\n   * @param path - The local file path to save the downloaded file\n   * @returns OSSDownloadResult with download result and requestId\n   * @throws APIError if the operation fails.\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: 'your_api_key' });\n   * const createResult = await agentBay.create();\n   * if (createResult.success) {\n   *   const result = await createResult.session.oss.downloadAnonymous('https://example.com/file.txt', '/path/to/save/file.txt');\n   *   console.log('Anonymous download success:', result.success);\n   *   await createResult.session.delete();\n   * }\n   * ```\n   */\n  async downloadAnonymous(\n    url: string,\n    path: string\n  ): Promise<OSSDownloadResult> {\n    try {\n      const args = {\n        url,\n        path,\n      };\n      const result = await this.session.callMcpTool(\n        \"oss_download_annon\",\n        args,\n        false\n      );\n\n      return {\n        requestId: result.requestId,\n        success: result.success,\n        content: result.data,\n        errorMessage: result.errorMessage,\n      };\n    } catch (error) {\n      return {\n        requestId: \"\",\n        success: false,\n        content: \"\",\n        errorMessage: `Failed to download file anonymously: ${error}`,\n      };\n    }\n  }\n}\n","export { Pty, PtyHandle, PtyError, PtyNotConnectedError } from \"./pty\";\n\nexport type { PtySession, PtyCreateOptions } from \"./pty\";\n","/**\n * PTY (Pseudo Terminal) module for interactive terminal sessions\n * in cloud sandbox environments.\n */\n\nimport type { WsClient } from \"../_internal/ws-client\";\n\nconst PTY_TARGET = \"PTY_SERVER\";\n\nconst DEFAULT_ENVS: Record<string, string> = {\n  TERM: \"xterm-256color\",\n  LANG: \"en_US.UTF-8\",\n};\n\nconst MAX_TERMINAL_SIZE = 500;\n\nexport interface PtySession {\n  ptySessionId: string;\n  cols: number;\n  rows: number;\n  status: string;\n  exitCode?: number;\n}\n\nexport interface PtyCreateOptions {\n  cols?: number;\n  rows?: number;\n  cwd?: string;\n  envs?: Record<string, string>;\n  shell?: string;\n  onData?: (data: Uint8Array) => void;\n  timeoutMs?: number;\n}\n\nexport class PtyError extends Error {\n  constructor(message = \"PTY operation error\") {\n    super(message);\n    this.name = \"PtyError\";\n  }\n}\n\nexport class PtyNotConnectedError extends PtyError {\n  constructor(message = \"PTY handle is not connected\") {\n    super(message);\n    this.name = \"PtyNotConnectedError\";\n  }\n}\n\nexport class PtyHandle {\n  private _ptySessionId: string;\n  private _ptyModule: Pty;\n  private _onData?: (data: Uint8Array) => void;\n  private _connected = true;\n  private _exitCode: number | undefined = undefined;\n  private _errorMsg: string | undefined = undefined;\n\n  constructor(\n    ptySessionId: string,\n    ptyModule: Pty,\n    onData?: (data: Uint8Array) => void\n  ) {\n    this._ptySessionId = ptySessionId;\n    this._ptyModule = ptyModule;\n    this._onData = onData;\n  }\n\n  get ptySessionId(): string {\n    return this._ptySessionId;\n  }\n\n  get isConnected(): boolean {\n    return this._connected;\n  }\n\n  get exitCode(): number | undefined {\n    return this._exitCode;\n  }\n\n  async sendInput(data: Uint8Array): Promise<void> {\n    if (!this._connected) throw new PtyNotConnectedError();\n    let text: string;\n    let encoding: string;\n    try {\n      text = new TextDecoder(\"utf-8\", { fatal: true }).decode(data);\n      encoding = \"utf8\";\n    } catch {\n      text = Buffer.from(data).toString(\"base64\");\n      encoding = \"base64\";\n    }\n    const wsClient = await this._ptyModule.getWsClient();\n    await wsClient.sendMessage(PTY_TARGET, {\n      method: \"pty.input\",\n      params: {\n        ptySessionId: this._ptySessionId,\n        encoding,\n        data: text,\n      },\n    });\n  }\n\n  async resize(cols: number, rows: number): Promise<void> {\n    if (!this._connected) throw new PtyNotConnectedError();\n    if (\n      cols < 1 ||\n      cols > MAX_TERMINAL_SIZE ||\n      rows < 1 ||\n      rows > MAX_TERMINAL_SIZE\n    ) {\n      throw new PtyError(\n        `Invalid terminal size: cols=${cols}, rows=${rows} (must be 1-${MAX_TERMINAL_SIZE})`\n      );\n    }\n    const wsClient = await this._ptyModule.getWsClient();\n    await wsClient.sendMessage(PTY_TARGET, {\n      method: \"pty.resize\",\n      params: {\n        ptySessionId: this._ptySessionId,\n        cols,\n        rows,\n      },\n    });\n  }\n\n  async kill(): Promise<void> {\n    if (!this._connected) throw new PtyNotConnectedError();\n    const wsClient = await this._ptyModule.getWsClient();\n    await wsClient.call(PTY_TARGET, {\n      method: \"pty.kill\",\n      params: { ptySessionId: this._ptySessionId },\n    });\n  }\n\n  async wait(timeoutMs?: number): Promise<number> {\n    const deadline = timeoutMs ? Date.now() + timeoutMs : undefined;\n    while (this._exitCode === undefined && this._errorMsg === undefined) {\n      if (deadline !== undefined && Date.now() >= deadline) {\n        throw new PtyError(`PTY wait timed out after ${timeoutMs}ms`);\n      }\n      await new Promise((r) => setTimeout(r, 100));\n    }\n    if (this._errorMsg !== undefined) {\n      throw new PtyError(this._errorMsg);\n    }\n    return this._exitCode!;\n  }\n\n  disconnect(): void {\n    if (!this._connected) return;\n    this._connected = false;\n    this._ptyModule.unregisterHandle(this._ptySessionId);\n  }\n\n  /** @internal */\n  _handleOutput(dataBytes: Uint8Array): void {\n    if (this._onData) {\n      try {\n        this._onData(dataBytes);\n      } catch (e) {\n        console.error(\"on_data callback raised an exception\", e);\n      }\n    }\n  }\n\n  /** @internal */\n  _handleExit(exitCode: number): void {\n    this._exitCode = exitCode;\n    this._connected = false;\n  }\n\n  /** @internal */\n  _handleError(errorMsg: string): void {\n    this._errorMsg = errorMsg;\n    this._connected = false;\n  }\n}\n\nexport class Pty {\n  private session: any;\n  private wsClient: WsClient | null = null;\n  private handles = new Map<string, PtyHandle>();\n  private callbackRegistered = false;\n\n  constructor(session: any) {\n    this.session = session;\n  }\n\n  /** @internal */\n  async getWsClient(): Promise<WsClient> {\n    if (!this.wsClient) {\n      this.wsClient = await this.session.getWsClient();\n    }\n    return this.wsClient!;\n  }\n\n  private async ensureCallback(): Promise<void> {\n    if (this.callbackRegistered) return;\n    const wsClient = await this.getWsClient();\n    await wsClient.connect();\n    wsClient.registerCallback(PTY_TARGET, (payload) => {\n      this.pushCallback(payload);\n    });\n    this.callbackRegistered = true;\n  }\n\n  private pushCallback(payload: {\n    requestId: string;\n    target: string;\n    data: Record<string, any>;\n  }): void {\n    const data = payload.data ?? {};\n    const eventType = data.eventType ?? \"\";\n    const ptySessionId = data.ptySessionId ?? \"\";\n\n    if (eventType === \"pty.output\") {\n      const handle = this.handles.get(ptySessionId);\n      if (!handle) return;\n      const encoding = data.encoding ?? \"utf8\";\n      const raw = data.data ?? \"\";\n      let dataBytes: Uint8Array;\n      if (encoding === \"base64\") {\n        dataBytes = Buffer.from(raw, \"base64\");\n      } else {\n        dataBytes =\n          typeof raw === \"string\"\n            ? new TextEncoder().encode(raw)\n            : new Uint8Array(raw);\n      }\n      handle._handleOutput(dataBytes);\n    } else if (eventType === \"pty.exit\") {\n      const handle = this.handles.get(ptySessionId);\n      if (!handle) return;\n      const exitCode = typeof data.exitCode === \"number\" ? data.exitCode : -1;\n      handle._handleExit(exitCode);\n    } else if (eventType === \"pty.error\") {\n      const handle = this.handles.get(ptySessionId);\n      if (!handle) return;\n      const errorMsg =\n        typeof data.error === \"string\" ? data.error : \"Unknown PTY error\";\n      handle._handleError(errorMsg);\n    }\n  }\n\n  /** @internal */\n  unregisterHandle(ptySessionId: string): void {\n    this.handles.delete(ptySessionId);\n  }\n\n  async create(options: PtyCreateOptions = {}): Promise<PtyHandle> {\n    const cols = options.cols ?? 80;\n    const rows = options.rows ?? 24;\n\n    if (\n      cols < 1 ||\n      cols > MAX_TERMINAL_SIZE ||\n      rows < 1 ||\n      rows > MAX_TERMINAL_SIZE\n    ) {\n      throw new PtyError(\n        `Invalid terminal size: cols=${cols}, rows=${rows} (must be 1-${MAX_TERMINAL_SIZE})`\n      );\n    }\n\n    await this.ensureCallback();\n    const wsClient = await this.getWsClient();\n\n    const params: Record<string, any> = { cols, rows };\n    if (options.cwd !== undefined) params.cwd = options.cwd;\n    const mergedEnvs = { ...DEFAULT_ENVS, ...(options.envs ?? {}) };\n    params.envs = mergedEnvs;\n    if (options.shell !== undefined) params.shell = options.shell;\n\n    const timeoutMs = options.timeoutMs ?? 30000;\n    const response = await wsClient.call(\n      PTY_TARGET,\n      { method: \"pty.create\", params },\n      timeoutMs\n    );\n\n    const result = (response.result as Record<string, any>) ?? {};\n    const ptySessionId = result.ptySessionId as string;\n    if (!ptySessionId) {\n      throw new PtyError(\n        `pty.create did not return ptySessionId: ${JSON.stringify(response)}`\n      );\n    }\n\n    const handle = new PtyHandle(ptySessionId, this, options.onData);\n    this.handles.set(ptySessionId, handle);\n    return handle;\n  }\n\n  async list(): Promise<PtySession[]> {\n    await this.ensureCallback();\n    const wsClient = await this.getWsClient();\n\n    const response = await wsClient.call(PTY_TARGET, {\n      method: \"pty.list\",\n      params: {},\n    });\n\n    const result = (response.result as Record<string, any>) ?? {};\n    const ptySessionIds = (result.ptySessionIds as string[]) ?? [];\n    const sessions: PtySession[] = [];\n    for (const sid of ptySessionIds) {\n      const handle = this.handles.get(sid);\n      let status = \"running\";\n      let exitCode: number | undefined;\n      if (handle && handle.exitCode !== undefined) {\n        status = \"exited\";\n        exitCode = handle.exitCode;\n      }\n      sessions.push({\n        ptySessionId: sid,\n        cols: 0,\n        rows: 0,\n        status,\n        exitCode,\n      });\n    }\n    return sessions;\n  }\n\n  async connect(\n    ptySessionId: string,\n    onData?: (data: Uint8Array) => void\n  ): Promise<PtyHandle> {\n    await this.ensureCallback();\n    const wsClient = await this.getWsClient();\n\n    const response = await wsClient.call(PTY_TARGET, {\n      method: \"pty.connect\",\n      params: { ptySessionId },\n    });\n\n    const result = (response.result as Record<string, any>) ?? {};\n    const returnedId = (result.ptySessionId as string) || ptySessionId;\n\n    const handle = new PtyHandle(returnedId, this, onData);\n    this.handles.set(returnedId, handle);\n    return handle;\n  }\n\n  async kill(ptySessionId: string): Promise<void> {\n    await this.ensureCallback();\n    const wsClient = await this.getWsClient();\n\n    await wsClient.call(PTY_TARGET, {\n      method: \"pty.kill\",\n      params: { ptySessionId },\n    });\n\n    const handle = this.handles.get(ptySessionId);\n    if (handle) {\n      (handle as any)._connected = false;\n      this.handles.delete(ptySessionId);\n    }\n  }\n}\n","import { BetaContextMount } from \"./beta-context-mount\";\nimport {\n  ContextSync,\n  SyncPolicy,\n  newUploadPolicy,\n  newExtractPolicy,\n  newRecyclePolicy,\n  Lifecycle,\n  DownloadStrategy,\n  WhiteList,\n  newDeletePolicy,\n} from \"./context-sync\";\nimport { ExtensionOption } from \"./extension\";\nimport { BrowserFingerprintContext } from \"./browser\";\nimport { ExtraConfigs, extraConfigsToJSON } from \"./types/extra-configs\";\nimport { LifecyclePolicy } from \"./lifecycle-policy\";\n\n// Browser fingerprint persistent path constant (moved from config.ts)\nconst BROWSER_FINGERPRINT_PERSIST_PATH = \"/tmp/browser_fingerprint\";\n\n/**\n * Browser data synchronization mode.\n *\n * Controls the scope of browser data synchronized between sessions.\n * - MINIMAL: Only Cookies + Local State. Smallest footprint, sufficient for basic cookie-based auth.\n * - STANDARD: Login state + anti-risk-control data. Includes Cookies, localStorage, IndexedDB,\n *   saved passwords, preferences, HSTS, GPU cache, etc. Recommended for most scenarios.\n */\nexport enum BrowserSyncMode {\n  /** Synchronize only essential files (Cookies, Local State). */\n  MINIMAL = \"minimal\",\n  /** Synchronize login state and anti-risk-control data (recommended). */\n  STANDARD = \"standard\",\n}\nimport {\n  log,\n  logError,\n  logInfo,\n  logDebug,\n  logAPICall,\n  logAPIResponseWithDetails,\n  maskSensitiveData,\n  setRequestId,\n  getRequestId,\n} from \"./utils/logger\";\n\n/**\n * Browser context configuration for session with optional extension support.\n *\n * This class provides browser context configuration for cloud sessions and supports\n * automatic extension synchronization when ExtensionOption is provided.\n *\n * Key Features:\n * - Browser context binding for sessions\n * - Automatic browser data upload on session end\n * - Optional extension integration with automatic context sync generation\n * - Clean API with ExtensionOption encapsulation\n *\n * Extension Configuration:\n * - **ExtensionOption**: Pass an ExtensionOption object with contextId and extensionIds\n * - **No Extensions**: Don't provide extensionOption parameter (extensionContextSyncs will be undefined)\n *\n * Usage Examples:\n * ```typescript\n * // With extensions using ExtensionOption\n * import { ExtensionOption } from \"./extension\";\n *\n * const extOption = new ExtensionOption(\n *   \"my_extensions\",\n *   [\"ext1\", \"ext2\"]\n * );\n *\n * const browserContext = new BrowserContext(\n *   \"browser_session\",\n *   true,\n *   extOption\n * );\n *\n * // Without extensions (minimal configuration)\n * const browserContext = new BrowserContext(\n *   \"browser_session\",\n *   true\n * );\n * // extensionContextSyncs will be undefined\n * ```\n */\nexport class BrowserContext {\n  /** ID of the browser context to bind to the session */\n  contextId: string;\n  /** Whether to automatically upload browser data when the session ends */\n  autoUpload: boolean;\n  /** Browser data synchronization mode. Defaults to STANDARD. */\n  syncMode: BrowserSyncMode;\n  /** Optional browser fingerprint context configuration object containing fingerprintContextId */\n  fingerprintContext?: BrowserFingerprintContext;\n  /** ID of the fingerprint context for browser fingerprint. Set automatically from fingerprint_context. */\n  fingerprintContextId?: string;\n  /** Auto-generated context sync for fingerprint. None if no fingerprint configuration provided. */\n  fingerprintContextSync?: ContextSync;\n  /** Optional extension configuration object containing context_id and extension_ids */\n  extensionOption?: ExtensionOption;\n  /** ID of the extension context for browser extensions. Set automatically from extension_option. */\n  extensionContextId?: string;\n  /** List of extension IDs to synchronize. Set automatically from extension_option. */\n  extensionIds?: string[];\n  /** Auto-generated context syncs for extensions. None if no extension configuration provided. */\n  extensionContextSyncs?: ContextSync[];\n\n  /**\n   * Initialize BrowserContextImpl with optional extension and fingerprint support.\n   *\n   * @param contextId - ID of the browser context to bind to the session.\n   *                   This identifies the browser instance for the session.\n   * @param autoUpload - Whether to automatically upload browser data\n   *                    when the session ends. Defaults to true.\n   * @param extensionOption - Extension configuration object containing\n   *                         contextId and extensionIds. This encapsulates\n   *                         all extension-related configuration.\n   *                         Defaults to undefined.\n   * @param fingerprintContext - Browser fingerprint context configuration object containing\n   *                            fingerprintContextId. This encapsulates\n   *                            all fingerprint-related configuration.\n   *                            Defaults to undefined.\n   * @param syncMode - Browser data synchronization mode.\n   *                  MINIMAL: only Cookies + Local State.\n   *                  STANDARD: login state + anti-risk-control data (recommended).\n   *                  Defaults to STANDARD.\n   *\n   * Extension Configuration:\n   * - **ExtensionOption**: Use extensionOption parameter with an ExtensionOption object\n   * - **No Extensions**: Don't provide extensionOption parameter\n   *\n   * Fingerprint Configuration:\n   * - **BrowserFingerprintContext**: Use fingerprintContext parameter with a BrowserFingerprintContext object\n   * - **No Fingerprint**: Don't provide fingerprintContext parameter\n   *\n   * Auto-generation:\n   * - extensionContextSyncs is automatically generated when extensionOption is provided\n   * - extensionContextSyncs will be undefined if no extensionOption is provided\n   * - extensionContextSyncs will be a ContextSync[] if extensionOption is valid\n   * - fingerprintContextSync is automatically generated when fingerprintContext is provided\n   * - fingerprintContextSync will be undefined if no fingerprintContext is provided\n   * - fingerprintContextSync will be a ContextSync if fingerprintContext is valid\n   */\n  constructor(\n    contextId: string,\n    autoUpload = true,\n    extensionOption?: ExtensionOption,\n    fingerprintContext?: BrowserFingerprintContext,\n    syncMode: BrowserSyncMode = BrowserSyncMode.STANDARD\n  ) {\n    this.contextId = contextId;\n    this.autoUpload = autoUpload;\n    this.syncMode = syncMode;\n    this.extensionOption = extensionOption;\n    this.fingerprintContext = fingerprintContext;\n\n    // Handle fingerprint configuration from BrowserFingerprintContext\n    if (fingerprintContext) {\n      // Extract fingerprint information from BrowserFingerprintContext\n      this.fingerprintContextId = fingerprintContext.fingerprintContextId;\n      // Auto-generate fingerprint context sync\n      this.fingerprintContextSync = this._createFingerprintContextSync();\n    } else {\n      // No fingerprint configuration provided\n      this.fingerprintContextId = undefined;\n      this.fingerprintContextSync = undefined;\n    }\n\n    // Handle extension configuration from ExtensionOption\n    if (extensionOption) {\n      // Extract extension information from ExtensionOption\n      this.extensionContextId = extensionOption.contextId;\n      this.extensionIds = extensionOption.extensionIds;\n      // Auto-generate extension context syncs\n      this.extensionContextSyncs = this._createExtensionContextSyncs();\n    } else {\n      // No extension configuration provided\n      this.extensionContextId = undefined;\n      this.extensionIds = [];\n      this.extensionContextSyncs = undefined;\n    }\n  }\n\n  /**\n   * Create ContextSync configurations for browser extensions.\n   *\n   * This method is called only when extensionOption is provided and contains\n   * valid extension configuration (contextId and extensionIds).\n   *\n   * @returns ContextSync[] - List of context sync configurations for extensions.\n   *                         Returns empty list if extension configuration is invalid.\n   */\n  private _createExtensionContextSyncs(): ContextSync[] {\n    if (\n      !this.extensionIds ||\n      this.extensionIds.length === 0 ||\n      !this.extensionContextId\n    ) {\n      return [];\n    }\n\n    // Create whitelist for each extension ID\n    const whiteLists: WhiteList[] = this.extensionIds.map((extId) => ({\n      path: extId,\n      excludePaths: [],\n    }));\n\n    // Create sync policy for extensions\n    const syncPolicy: SyncPolicy = {\n      uploadPolicy: {\n        ...newUploadPolicy(),\n        autoUpload: false,\n      },\n      extractPolicy: {\n        ...newExtractPolicy(),\n        extract: true,\n        deleteSrcFile: true,\n      },\n      deletePolicy: {\n        ...newDeletePolicy(),\n        syncLocalFile: false,\n      },\n      recyclePolicy: newRecyclePolicy(),\n      bwList: {\n        whiteLists: whiteLists,\n      },\n      downloadPolicy: {\n        autoDownload: true,\n        downloadStrategy: DownloadStrategy.DownloadAsync,\n      },\n    };\n\n    // Create context sync for extensions\n    const extensionSync = new ContextSync(\n      this.extensionContextId,\n      \"/tmp/extensions/\",\n      syncPolicy\n    );\n\n    return [extensionSync];\n  }\n\n  /**\n   * Create ContextSync configuration for browser fingerprint.\n   *\n   * This method is called only when fingerprintContext is provided and contains\n   * valid fingerprint configuration (fingerprintContextId).\n   *\n   * @returns ContextSync - Context sync configuration for fingerprint.\n   *                       Returns undefined if fingerprint configuration is invalid.\n   */\n  private _createFingerprintContextSync(): ContextSync | undefined {\n    if (!this.fingerprintContextId || !this.fingerprintContextId.trim()) {\n      return undefined;\n    }\n\n    // Create sync policy for fingerprint\n    const syncPolicy: SyncPolicy = {\n      uploadPolicy: {\n        ...newUploadPolicy(),\n        autoUpload: false,\n      },\n      extractPolicy: {\n        ...newExtractPolicy(),\n        extract: true,\n        deleteSrcFile: true,\n      },\n      deletePolicy: {\n        ...newDeletePolicy(),\n        syncLocalFile: false,\n      },\n      recyclePolicy: newRecyclePolicy(),\n      bwList: {\n        whiteLists: [],\n      },\n    };\n\n    // Create context sync for fingerprint\n    const fingerprintSync = new ContextSync(\n      this.fingerprintContextId,\n      BROWSER_FINGERPRINT_PERSIST_PATH,\n      syncPolicy\n    );\n\n    return fingerprintSync;\n  }\n\n  /**\n   * Get context syncs for extensions.\n   *\n   * @returns ContextSync[] - Context sync configurations for extensions. Returns empty list if no extensions configured.\n   */\n  getExtensionContextSyncs(): ContextSync[] {\n    return this.extensionContextSyncs || [];\n  }\n\n  /**\n   * Get context sync for fingerprint.\n   *\n   * @returns ContextSync - Context sync configuration for fingerprint.\n   *                       Returns undefined if fingerprint configuration is invalid.\n   */\n  getFingerprintContextSync(): ContextSync | undefined {\n    return this.fingerprintContextSync;\n  }\n}\n\n/**\n * Parameters for creating a session.\n * This interface defines all possible fields that can be used when creating a session.\n */\nexport interface CreateSessionParamsInterface {\n  /** Custom labels for the Session. These can be used for organizing and filtering sessions. */\n  labels?: Record<string, string>;\n  /** Image ID to use for the session. */\n  imageId?: string;\n  /** SDK-side idle release timeout in seconds (deprecated). Use lifecyclePolicy (minutes) instead. */\n  idleReleaseTimeout?: number;\n  /** Lifecycle policy for session timeout and manual release (minutes). Mutually exclusive with positive idleReleaseTimeout. */\n  lifecyclePolicy?: LifecyclePolicy;\n  /** List of context synchronization configurations. */\n  contextSync?: ContextSync[];\n  /** List of context mount configurations for direct-mount persistence. */\n  betaContextMount?: BetaContextMount[];\n  /** Optional configuration for browser data synchronization. */\n  browserContext?: BrowserContext;\n  /** Security policy ID (interface field name). */\n  policyId?: string;\n  /** Beta network ID to bind this session to. */\n  betaNetworkId?: string;\n  /** Whether to enable browser session recording. */\n  enableBrowserReplay?: boolean;\n  /** Additional configuration options. */\n  extraConfigs?: ExtraConfigs;\n  /** Framework identifier for tracking. */\n  framework?: string;\n  /** Whether to create a VPC-based session. Defaults to false. */\n  isVpc?: boolean;\n  /** MCP policy id to apply when creating the session (class field name). */\n  mcpPolicyId?: string;\n  /** Whether to load skills into the sandbox. */\n  loadSkills?: boolean;\n  /** Skill names to load. Loads all visible skills when loadSkills=true and this is not specified. */\n  skillNames?: string[];\n}\n\n/**\n * CreateSessionParams provides a way to configure the parameters for creating a new session\n * in the AgentBay cloud environment.\n */\nexport class CreateSessionParams implements CreateSessionParamsInterface {\n  /** Custom labels for the Session. These can be used for organizing and filtering sessions. */\n  public labels: Record<string, string>;\n\n  /** Image ID to use for the session. */\n  public imageId?: string;\n\n  /** SDK-side idle release timeout in seconds (deprecated). Default 0 when omitted. */\n  public idleReleaseTimeout: number;\n\n  /** Lifecycle policy (minutes). Mutually exclusive with positive idleReleaseTimeout. */\n  public lifecyclePolicy: LifecyclePolicy | undefined;\n\n  /**\n   * List of context synchronization configurations.\n   * These configurations define how contexts should be synchronized and mounted.\n   */\n  public contextSync: ContextSync[];\n\n  /** List of context mount configurations for direct-mount persistence. */\n  public betaContextMount: BetaContextMount[];\n\n  /** Whether to create a VPC-based session. Defaults to false. */\n  public isVpc?: boolean;\n\n  /** MCP policy id to apply when creating the session. */\n  public mcpPolicyId?: string;\n\n  /** Security policy ID (interface field name). Maps to mcpPolicyId internally. */\n  public policyId?: string;\n\n  /** Beta network ID to bind this session to. */\n  public betaNetworkId?: string;\n\n  /** Whether to enable browser session recording. When undefined, server-side default applies. */\n  public enableBrowserReplay?: boolean;\n\n  /** Additional configuration options. */\n  public extraConfigs?: ExtraConfigs;\n\n  /** Framework identifier for tracking. */\n  public framework: string;\n\n  public browserContext?: BrowserContext;\n\n  /** Whether to load skills into the sandbox. */\n  public loadSkills?: boolean;\n\n  /** Skill names to load. */\n  public skillNames?: string[];\n\n  constructor(params?: CreateSessionParamsInterface) {\n    this.labels = params?.labels || {};\n    this.imageId = params?.imageId;\n    const idle = (params as any)?.idleReleaseTimeout;\n    if (idle === undefined || idle === null) {\n      this.idleReleaseTimeout = 0;\n    } else if (\n      typeof idle !== \"number\" ||\n      !Number.isInteger(idle) ||\n      idle <= 0\n    ) {\n      throw new Error(\n        \"idleReleaseTimeout must be a positive integer (seconds)\"\n      );\n    } else {\n      this.idleReleaseTimeout = idle;\n    }\n    this.lifecyclePolicy = (params as any)?.lifecyclePolicy || undefined;\n    if (this.lifecyclePolicy && this.idleReleaseTimeout > 0) {\n      throw new Error(\n        \"lifecyclePolicy cannot be used together with deprecated idleReleaseTimeout (seconds); use lifecyclePolicy only\"\n      );\n    }\n    this.isVpc = params?.isVpc || false;\n    // Handle policyId mapping - if policyId is provided, use it, otherwise use mcpPolicyId\n    this.mcpPolicyId = params?.mcpPolicyId ? params.mcpPolicyId : \"\";\n    this.policyId = params?.policyId ? params.policyId : \"\";\n    this.betaNetworkId = params?.betaNetworkId;\n    // When not set, leave as undefined - let server decide the default\n    this.enableBrowserReplay = params?.enableBrowserReplay;\n    this.extraConfigs = params?.extraConfigs;\n    this.framework = params?.framework || \"\";\n\n    // Start with provided contextSync\n    let allContextSyncs = params?.contextSync ? [...params.contextSync] : [];\n\n    // Add extension context syncs from browserContext if available\n    if (params?.browserContext && params.browserContext.extensionContextSyncs) {\n      allContextSyncs = [\n        ...allContextSyncs,\n        ...params.browserContext.extensionContextSyncs,\n      ];\n      log(\n        `Added ${params.browserContext.extensionContextSyncs.length} extension context sync(s) from BrowserContext`\n      );\n    }\n\n    // Add fingerprint context sync from browserContext if available\n    if (\n      params?.browserContext &&\n      params.browserContext.fingerprintContextSync\n    ) {\n      allContextSyncs = [\n        ...allContextSyncs,\n        params.browserContext.fingerprintContextSync,\n      ];\n      log(\"Added fingerprint context sync from BrowserContext\");\n    }\n\n    this.contextSync = allContextSyncs;\n    this.betaContextMount = params?.betaContextMount\n      ? [...params.betaContextMount]\n      : [];\n    this.browserContext = params?.browserContext;\n    this.loadSkills = params?.loadSkills;\n    this.skillNames = params?.skillNames;\n  }\n}\n","/**\n * Options for creating a LifecyclePolicy.\n */\nexport interface LifecyclePolicyOptions {\n  /** Idle release timeout in minutes (default: 5). Must be a positive integer. */\n  idleReleaseTimeout?: number;\n  /** Maximum session runtime in minutes from creation (default: 30). Must be a positive integer. */\n  maxRuntime?: number;\n  /** When true, disables all auto-release; the session only ends via delete(). */\n  manualRelease?: boolean;\n}\n\n/**\n * Lifecycle policy for session management.\n *\n * Controls how and when a session is automatically released.\n * When used, SDK takes full control of lifecycle — console defaults are overridden.\n * All time values are in MINUTES.\n *\n * Three control dimensions:\n * - **idleReleaseTimeout**: Minutes of inactivity before auto-release (default: 5)\n * - **maxRuntime**: Absolute maximum session duration from creation (default: 30)\n * - **manualRelease**: Disable all auto-release; session only ends via `delete()`\n */\nexport class LifecyclePolicy {\n  /** Minutes of inactivity before auto-release (default: 5). */\n  readonly idleReleaseTimeout: number;\n  /** Maximum session runtime in minutes from creation (default: 30). */\n  readonly maxRuntime: number;\n  /** When true, disables all auto-release; session only ends via delete(). */\n  readonly manualRelease: boolean;\n\n  constructor(options?: LifecyclePolicyOptions) {\n    const opts = options || {};\n\n    if (opts.manualRelease) {\n      if (\n        opts.idleReleaseTimeout !== undefined &&\n        opts.idleReleaseTimeout !== null\n      ) {\n        throw new Error(\n          \"idleReleaseTimeout cannot be set when manualRelease=true. \" +\n            \"In manual release mode, the session is only released via delete().\"\n        );\n      }\n      if (opts.maxRuntime !== undefined && opts.maxRuntime !== null) {\n        throw new Error(\n          \"maxRuntime cannot be set when manualRelease=true. \" +\n            \"In manual release mode, the session is only released via delete().\"\n        );\n      }\n      this.idleReleaseTimeout = 0;\n      this.maxRuntime = 0;\n      this.manualRelease = true;\n      return;\n    }\n\n    const idle =\n      opts.idleReleaseTimeout !== undefined && opts.idleReleaseTimeout !== null\n        ? opts.idleReleaseTimeout\n        : 5;\n    const max =\n      opts.maxRuntime !== undefined && opts.maxRuntime !== null\n        ? opts.maxRuntime\n        : 30;\n\n    if (typeof idle !== \"number\" || !Number.isInteger(idle) || idle <= 0) {\n      throw new Error(\n        \"idleReleaseTimeout must be a positive integer (minutes)\"\n      );\n    }\n    if (typeof max !== \"number\" || !Number.isInteger(max) || max <= 0) {\n      throw new Error(\"maxRuntime must be a positive integer (minutes)\");\n    }\n\n    this.idleReleaseTimeout = idle;\n    this.maxRuntime = max;\n    this.manualRelease = false;\n  }\n}\n","export {\n  ComputerUseAgent,\n  BrowserUseAgent,\n  MobileUseAgent,\n  Agent,\n  AgentEvent,\n  AgentEventCallback,\n  AgentStreamingOptions,\n  MobileTaskOptions,\n  TaskExecution,\n  ExecutionResult,\n  QueryResult,\n  McpToolResult,\n  McpSession,\n} from \"./agent\";\n","import * as fs from \"fs\";\nimport * as path from \"path\";\nimport * as crypto from \"crypto\";\nimport fetch from \"node-fetch\";\nimport { AgentBay } from \"./agent-bay\";\nimport { ContextService, Context } from \"./context\";\nimport { AgentBayError } from \"./exceptions\";\nimport {\n  OperationResult,\n  ContextFileListResult,\n  FileUrlResult,\n} from \"./types/api-response\";\nimport { log, logError, logInfo, logDebug } from \"./utils/logger\";\n\n// ==============================================================================\n// Constants\n// ==============================================================================\nconst EXTENSIONS_BASE_PATH = \"/tmp/extensions\";\n\n// ==============================================================================\n// 1. Data Models\n// ==============================================================================\ninterface FileSystemError extends Error {\n  code?: string;\n}\n/**\n * Represents a browser extension as a cloud resource.\n */\nexport class Extension {\n  /**\n   * The unique identifier of the extension.\n   */\n  id: string;\n\n  /**\n   * The name of the extension.\n   */\n  name: string;\n\n  /**\n   * Date and time when the extension was created.\n   */\n  createdAt?: string;\n\n  /**\n   * Initialize an Extension object.\n   *\n   * @param id - The unique identifier of the extension.\n   * @param name - The name of the extension.\n   * @param createdAt - Date and time when the extension was created.\n   */\n  constructor(id: string, name: string, createdAt?: string) {\n    this.id = id;\n    this.name = name;\n    this.createdAt = createdAt;\n  }\n}\n\n/**\n * Configuration options for browser extension integration.\n *\n * This class encapsulates the necessary parameters for setting up\n * browser extension synchronization and context management.\n */\nexport class ExtensionOption {\n  /**\n   * ID of the extension context for browser extensions.\n   */\n  contextId: string;\n\n  /**\n   * List of extension IDs to be loaded/synchronized.\n   */\n  extensionIds: string[];\n\n  /**\n   * Initialize ExtensionOption with context and extension configuration.\n   *\n   * @param contextId - ID of the extension context for browser extensions.\n   *                   This should match the context where extensions are stored.\n   * @param extensionIds - List of extension IDs to be loaded in the browser session.\n   *                      Each ID should correspond to a valid extension in the context.\n   *\n   * @throws {Error} If contextId is empty or extensionIds is empty.\n   */\n  constructor(contextId: string, extensionIds: string[]) {\n    if (!contextId || !contextId.trim()) {\n      throw new Error(\"contextId cannot be empty\");\n    }\n\n    if (!extensionIds || extensionIds.length === 0) {\n      throw new Error(\"extensionIds cannot be empty\");\n    }\n\n    this.contextId = contextId;\n    this.extensionIds = extensionIds;\n  }\n\n  /**\n   * String representation of ExtensionOption.\n   */\n  toString(): string {\n    return `ExtensionOption(contextId='${\n      this.contextId\n    }', extensionIds=${JSON.stringify(this.extensionIds)})`;\n  }\n\n  /**\n   * Human-readable string representation.\n   */\n  toDisplayString(): string {\n    return `Extension Config: ${this.extensionIds.length} extension(s) in context '${this.contextId}'`;\n  }\n\n  /**\n   * Validate the extension option configuration.\n   *\n   * @returns True if configuration is valid, false otherwise.\n   */\n  validate(): boolean {\n    try {\n      // Check contextId\n      if (!this.contextId || !this.contextId.trim()) {\n        return false;\n      }\n\n      // Check extensionIds\n      if (!this.extensionIds || this.extensionIds.length === 0) {\n        return false;\n      }\n\n      // Check that all extension IDs are non-empty strings\n      for (const extId of this.extensionIds) {\n        if (typeof extId !== \"string\" || !extId.trim()) {\n          return false;\n        }\n      }\n\n      return true;\n    } catch (error) {\n      return false;\n    }\n  }\n}\n\n// ==============================================================================\n// 2. Core Service Class (Scoped Stateless Model)\n// ==============================================================================\n\n/**\n * Provides methods to manage user browser extensions.\n * This service integrates with the existing context functionality for file operations.\n *\n * **Usage** (Simplified - Auto-detection):\n * ```typescript\n * // Service automatically detects if context exists and creates if needed\n * const extensionsService = new ExtensionsService(agentBay, \"browser_extensions\");\n *\n * // Or use with empty contextId to auto-generate context name\n * const extensionsService = new ExtensionsService(agentBay);  // Uses default generated name\n *\n * // Use the service immediately - initialization happens automatically\n * const extension = await extensionsService.create(\"/path/to/plugin.zip\");\n * ```\n *\n * **Integration with ExtensionOption (Simplified)**:\n * ```typescript\n * // Create extensions and configure for browser sessions\n * const extensionsService = new ExtensionsService(agentBay, \"my_extensions\");\n * const ext1 = await extensionsService.create(\"/path/to/ext1.zip\");\n * const ext2 = await extensionsService.create(\"/path/to/ext2.zip\");\n *\n * // Create extension option for browser integration (no contextId needed!)\n * const extOption = extensionsService.createExtensionOption([ext1.id, ext2.id]);\n *\n * // Use with BrowserContext for session creation\n * const browserContext = new BrowserContext({\n *   contextId: \"browser_session\",\n *   autoUpload: true,\n *   extensionOption: extOption  // All extension config encapsulated\n * });\n * ```\n *\n * **Context Management**:\n * - If contextId provided and exists: Uses the existing context\n * - If contextId provided but doesn't exist: Creates context with provided name\n * - If contextId empty or not provided: Generates default name and creates context\n * - No need to manually manage context creation or call initialize()\n * - Context initialization happens automatically on first method call\n */\nexport class ExtensionsService {\n  private agentBay: AgentBay;\n  private contextService: ContextService;\n  private extensionContext!: Context;\n  private contextId!: string;\n  private contextName: string;\n  private autoCreated: boolean;\n  private _initializationPromise: Promise<void> | null = null;\n\n  /**\n   * Initializes the ExtensionsService with a context.\n   *\n   * @param agentBay - The AgentBay client instance.\n   * @param contextId - The context ID or name. If empty or not provided,\n   *                   a default context name will be generated automatically.\n   *                   If the context doesn't exist, it will be automatically created.\n   *\n   * Note:\n   *   The service automatically detects if the context exists. If not,\n   *   it creates a new context with the provided name or a generated default name.\n   *   Context initialization is handled lazily on first use.\n   */\n  constructor(agentBay: AgentBay, contextId = \"\") {\n    if (!agentBay) {\n      throw new AgentBayError(\"AgentBay instance is required\");\n    }\n    if (!agentBay.context) {\n      throw new AgentBayError(\"AgentBay instance must have a context service\");\n    }\n\n    this.agentBay = agentBay;\n    this.contextService = agentBay.context;\n    this.autoCreated = true;\n\n    // Generate default context name if contextId is empty\n    if (!contextId || contextId.trim() === \"\") {\n      contextId = `extensions-${Math.floor(Date.now() / 1000)}`;\n      logDebug(`Generated default context name: ${contextId}`);\n    }\n\n    this.contextName = contextId;\n\n    // Initialize context lazily - will be set on first method call\n    this._initializationPromise = this._initializeContext();\n  }\n\n  /**\n   * Internal method to initialize the context.\n   * This ensures the context is ready before any operations.\n   */\n  private async _initializeContext(): Promise<void> {\n    try {\n      // Context doesn't exist, create it\n      const contextResult = await this.contextService.get(\n        this.contextName,\n        true\n      );\n      if (!contextResult.success || !contextResult.context) {\n        throw new AgentBayError(\n          `Failed to create extension repository context: ${this.contextName}`\n        );\n      }\n\n      this.extensionContext = contextResult.context;\n      this.contextId = this.extensionContext.id;\n    } catch (error) {\n      throw new AgentBayError(\n        `Failed to initialize ExtensionsService: ${\n          error instanceof Error ? error.message : String(error)\n        }`\n      );\n    }\n  }\n\n  /**\n   * Ensures the service is initialized before performing operations.\n   */\n  private async _ensureInitialized(): Promise<void> {\n    if (this._initializationPromise) {\n      await this._initializationPromise;\n      this._initializationPromise = null;\n    }\n  }\n\n  /**\n   * An internal helper method that encapsulates the flow of \"get upload URL for a specific path and upload\".\n   * Uses the existing context service for file operations.\n   *\n   * @param localPath - The path to the local file.\n   * @param remotePath - The path of the file in context storage.\n   *\n   * @throws {AgentBayError} If getting the credential or uploading fails.\n   */\n  private async _uploadToCloud(\n    localPath: string,\n    remotePath: string\n  ): Promise<void> {\n    try {\n      // 1. Get upload URL using context service\n      const urlResult = await this.contextService.getFileUploadUrl(\n        this.contextId,\n        remotePath\n      );\n      if (!urlResult.success || !urlResult.url) {\n        throw new AgentBayError(\n          `Failed to get upload URL: ${urlResult.url || \"No URL returned\"}`\n        );\n      }\n\n      const preSignedUrl = urlResult.url;\n\n      // 2. Use the presigned URL to upload the file directly\n      // Using async file reading for better performance with large files\n      const fileBuffer = await fs.promises.readFile(localPath);\n\n      const response = await fetch(preSignedUrl, {\n        method: \"PUT\",\n        body: fileBuffer,\n      });\n\n      // Check response status and handle errors appropriately\n      if (!response.ok) {\n        throw new AgentBayError(\n          `HTTP error uploading file: ${response.status} ${response.statusText}`\n        );\n      }\n    } catch (error) {\n      // Provide more specific error handling based on error types\n      if (error instanceof AgentBayError) {\n        throw error;\n      }\n\n      // Handle filesystem errors specifically\n      if (error instanceof Error && \"code\" in error) {\n        const errorCode = (error as FileSystemError).code;\n        if (errorCode === \"ENOENT\") {\n          throw new AgentBayError(`File not found: ${localPath}`);\n        } else if (errorCode === \"EACCES\") {\n          throw new AgentBayError(\n            `Permission denied accessing file: ${localPath}`\n          );\n        } else {\n          throw new AgentBayError(`File system error: ${error.message}`);\n        }\n      }\n\n      // Handle network/HTTP errors\n      if (error instanceof TypeError && error.message.includes(\"fetch\")) {\n        throw new AgentBayError(\n          `Network error during file upload: ${error.message}`\n        );\n      }\n\n      // Generic error handler\n      throw new AgentBayError(\n        `An error occurred while uploading the file: ${\n          error instanceof Error ? error.message : String(error)\n        }`\n      );\n    }\n  }\n\n  /**\n   * Lists all available browser extensions within this context from the cloud.\n   * Uses the context service to list files under the extensions directory.\n   *\n   * @returns Promise that resolves to an array of Extension objects.\n   * @throws {AgentBayError} If listing extensions fails.\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: 'your_api_key' });\n   * const service = new ExtensionsService(agentBay, 'my_extensions');\n   * await service.create('/path/to/ext1.zip');\n   * const extensions = await service.list();\n   * console.log(`Found ${extensions.length} extensions`);\n   * await service.cleanup();\n   * ```\n   */\n  async list(): Promise<Extension[]> {\n    await this._ensureInitialized();\n\n    try {\n      // Use context service to list files in the extensions directory\n      const fileListResult = await this.contextService.listFiles(\n        this.contextId,\n        EXTENSIONS_BASE_PATH,\n        1, // pageNumber\n        100 // pageSize - reasonable limit for extensions\n      );\n\n      if (!fileListResult.success) {\n        throw new AgentBayError(\n          \"Failed to list extensions: Context file listing failed.\"\n        );\n      }\n\n      const extensions: Extension[] = [];\n      for (const fileEntry of fileListResult.entries) {\n        // Extract the extension ID from the file name\n        const extensionId = fileEntry.fileName || fileEntry.filePath;\n        extensions.push(\n          new Extension(\n            extensionId,\n            fileEntry.fileName || extensionId,\n            fileEntry.gmtCreate\n          )\n        );\n      }\n      return extensions;\n    } catch (error) {\n      if (error instanceof AgentBayError) {\n        throw error;\n      }\n      throw new AgentBayError(\n        `An error occurred while listing browser extensions: ${\n          error instanceof Error ? error.message : String(error)\n        }`\n      );\n    }\n  }\n\n  /**\n   * Uploads a new browser extension from a local path into the current context.\n   *\n   * @param localPath - Path to the local extension file (must be a .zip file).\n   * @returns Promise that resolves to an Extension object.\n   * @throws {Error} If the local file doesn't exist.\n   * @throws {Error} If the file format is not supported (only .zip is supported).\n   * @throws {AgentBayError} If upload fails.\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: 'your_api_key' });\n   * const service = new ExtensionsService(agentBay);\n   * const extension = await service.create('/path/to/my-extension.zip');\n   * console.log(`Extension ID: ${extension.id}`);\n   * await service.cleanup();\n   * ```\n   */\n  async create(localPath: string): Promise<Extension> {\n    await this._ensureInitialized();\n\n    if (!fs.existsSync(localPath)) {\n      throw new Error(`The specified local file was not found: ${localPath}`);\n    }\n\n    // Determine the ID and cloud path before uploading\n    // Validate file type - only ZIP format is supported\n    const fileExtension = path.extname(localPath).toLowerCase();\n    if (fileExtension !== \".zip\") {\n      throw new Error(\n        `Unsupported plugin format '${fileExtension}'. Only ZIP format (.zip) is supported.`\n      );\n    }\n\n    const extensionId = `ext_${crypto\n      .randomBytes(16)\n      .toString(\"hex\")}${fileExtension}`;\n    const extensionName = path.basename(localPath);\n    const remotePath = `${EXTENSIONS_BASE_PATH}/${extensionId}`;\n\n    // Use the helper method to perform the cloud upload\n    await this._uploadToCloud(localPath, remotePath);\n\n    // Upload implies creation. Return a locally constructed object with basic info.\n    return new Extension(extensionId, extensionName);\n  }\n\n  /**\n   * Updates an existing browser extension in the current context with a new file.\n   *\n   * @param extensionId - ID of the extension to update.\n   * @param newLocalPath - Path to the new local extension file.\n   * @returns Promise that resolves to an Extension object.\n   * @throws {Error} If the new local file doesn't exist.\n   * @throws {Error} If the extension doesn't exist in the context.\n   * @throws {AgentBayError} If update fails.\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: 'your_api_key' });\n   * const service = new ExtensionsService(agentBay, 'my_extensions');\n   * const ext = await service.create('/path/to/ext-v1.zip');\n   * const updated = await service.update(ext.id, '/path/to/ext-v2.zip');\n   * console.log('Extension updated:', updated.name);\n   * await service.cleanup();\n   * ```\n   */\n  async update(extensionId: string, newLocalPath: string): Promise<Extension> {\n    await this._ensureInitialized();\n\n    if (!fs.existsSync(newLocalPath)) {\n      throw new Error(\n        `The specified new local file was not found: ${newLocalPath}`\n      );\n    }\n\n    // Validate that the extension exists by checking the file list\n    const existingExtensions = await this.list();\n    const extensionExists = existingExtensions.some(\n      (ext) => ext.id === extensionId\n    );\n\n    if (!extensionExists) {\n      throw new Error(\n        `Browser extension with ID '${extensionId}' not found in the context. Cannot update.`\n      );\n    }\n\n    const remotePath = `${EXTENSIONS_BASE_PATH}/${extensionId}`;\n\n    // Use the helper method to perform the cloud upload (overwrite)\n    await this._uploadToCloud(newLocalPath, remotePath);\n\n    return new Extension(extensionId, path.basename(newLocalPath));\n  }\n\n  /**\n   * Gets detailed information about a specific browser extension.\n   *\n   * @param extensionId - The ID of the extension to get info for.\n   * @returns Promise that resolves to an Extension object if found, undefined otherwise.\n   */\n  private async _getExtensionInfo(\n    extensionId: string\n  ): Promise<Extension | undefined> {\n    await this._ensureInitialized();\n\n    try {\n      const extensions = await this.list();\n      return extensions.find((ext) => ext.id === extensionId);\n    } catch (error) {\n      logError(\n        `An error occurred while getting extension info for '${extensionId}':`,\n        error\n      );\n      return undefined;\n    }\n  }\n\n  /**\n   * Cleans up the auto-created context if it was created by this service.\n   *\n   * @returns Promise that resolves to true if cleanup was successful or not needed, false if cleanup failed.\n   *\n   * Note:\n   *   This method only works if the context was auto-created by this service.\n   *   For existing contexts, no cleanup is performed.\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: 'your_api_key' });\n   * const service = new ExtensionsService(agentBay);\n   * await service.create('/path/to/my-extension.zip');\n   * const success = await service.cleanup();\n   * console.log('Cleanup success:', success);\n   * ```\n   */\n  async cleanup(): Promise<boolean> {\n    await this._ensureInitialized();\n\n    if (!this.autoCreated) {\n      // Context was not auto-created by this service, no cleanup needed\n      return true;\n    }\n\n    try {\n      const deleteResult = await this.contextService.delete(\n        this.extensionContext\n      );\n      if (deleteResult) {\n        logInfo(\n          `Extension context deleted: ${this.contextName} (ID: ${this.contextId})`\n        );\n        return true;\n      } else {\n        logError(\n          `Warning: Failed to delete extension context: ${this.contextName}`,\n          new Error(\"Delete operation returned false\")\n        );\n        return false;\n      }\n    } catch (error) {\n      logError(`Warning: Failed to delete extension context:`, error);\n      return false;\n    }\n  }\n\n  /**\n   * Deletes a browser extension from the current context.\n   *\n   * @param extensionId - ID of the extension to delete.\n   * @returns Promise that resolves to true if deletion was successful, false otherwise.\n   *\n   * @example\n   * ```typescript\n   * const agentBay = new AgentBay({ apiKey: 'your_api_key' });\n   * const service = new ExtensionsService(agentBay, 'my_extensions');\n   * const ext = await service.create('/path/to/my-extension.zip');\n   * const success = await service.delete(ext.id);\n   * console.log('Delete success:', success);\n   * await service.cleanup();\n   * ```\n   */\n  async delete(extensionId: string): Promise<boolean> {\n    await this._ensureInitialized();\n\n    const remotePath = `${EXTENSIONS_BASE_PATH}/${extensionId}`;\n    try {\n      // Use context service to delete the file\n      const deleteResult = await this.contextService.deleteFile(\n        this.contextId,\n        remotePath\n      );\n\n      return deleteResult.success;\n    } catch (error) {\n      logError(\n        `An error occurred while deleting browser extension '${extensionId}':`,\n        error\n      );\n      return false;\n    }\n  }\n\n  /**\n   * Create an ExtensionOption for the current context with specified extension IDs.\n   *\n   * This is a convenience method that creates an ExtensionOption using the current\n   * service's contextId and the provided extension IDs. This option can then be\n   * used with BrowserContext for browser session creation.\n   *\n   * @param extensionIds - List of extension IDs to include in the option.\n   *                      These should be extensions that exist in the current context.\n   * @returns ExtensionOption configuration object for browser extension integration.\n   * @throws {Error} If extensionIds is empty or invalid.\n   *\n   * @example\n   * ```typescript\n   * // Create extensions\n   * const ext1 = await extensionsService.create(\"/path/to/ext1.zip\");\n   * const ext2 = await extensionsService.create(\"/path/to/ext2.zip\");\n   *\n   * // Create extension option for browser integration\n   * const extOption = extensionsService.createExtensionOption([ext1.id, ext2.id]);\n   *\n   * // Use with BrowserContext\n   * const browserContext = new BrowserContext({\n   *   contextId: \"browser_session\",\n   *   autoUpload: true,\n   *   extensionContextId: extOption.contextId,\n   *   extensionIds: extOption.extensionIds\n   * });\n   * ```\n   */\n  createExtensionOption(extensionIds: string[]): ExtensionOption {\n    // Note: This method is synchronous like in Python, but contextId might not be available yet\n    // In practice, this should be called after the service has been used at least once\n    if (!this.contextId) {\n      throw new Error(\n        \"Service not initialized. Please call an async method first or ensure context is created.\"\n      );\n    }\n\n    return new ExtensionOption(this.contextId, extensionIds);\n  }\n}\n","import { AgentBay } from \"./agent-bay\";\nimport { Context, ContextService } from \"./context\";\nimport { ContextSync, newSyncPolicy } from \"./context-sync\";\nimport { logError, logInfo, logDebug } from \"./utils/logger\";\nimport fetch from \"node-fetch\";\nimport {\n  MobileSimulateMode,\n  MobileSimulateConfig,\n} from \"./types/extra-configs\";\n\n// Mobile info path constants\nconst MOBILE_INFO_DEFAULT_PATH = \"/data/agentbay_mobile_info\";\nconst MOBILE_INFO_SUB_PATH = \"/agentbay_mobile_info\";\nconst MOBILE_INFO_FILE_NAME = \"dev_info.json\";\n\n/**\n * Result of the upload mobile info for mobile simulate.\n */\nexport interface MobileSimulateUploadResult {\n  /**\n   * Whether the operation was successful.\n   */\n  success: boolean;\n\n  /**\n   * The context ID of the mobile info.\n   */\n  mobileSimulateContextId?: string;\n\n  /**\n   * The error message if the operation failed.\n   */\n  errorMessage?: string;\n}\n\n/**\n * Provides methods to manage persistent mobile dev info and sync to the mobile device.\n */\nexport class MobileSimulateService {\n  private agentBay: AgentBay;\n  private contextService: ContextService;\n  private simulateEnable = false;\n  private simulateMode: MobileSimulateMode = MobileSimulateMode.PropertiesOnly;\n  private contextId?: string;\n  private contextSync?: ContextSync;\n  private mobileDevInfoPath?: string;\n  private useInternalContext = true;\n\n  /**\n   * Initialize the MobileSimulateService.\n   *\n   * @param agentBay - The AgentBay instance.\n   */\n  constructor(agentBay: AgentBay) {\n    if (!agentBay) {\n      throw new Error(\"agentBay is required\");\n    }\n    if (!agentBay.context) {\n      throw new Error(\"agentBay.context is required\");\n    }\n\n    this.agentBay = agentBay;\n    this.contextService = agentBay.context;\n  }\n\n  /**\n   * Set the simulate enable flag.\n   *\n   * @param enable - The simulate feature enable flag.\n   */\n  setSimulateEnable(enable: boolean): void {\n    this.simulateEnable = enable;\n  }\n\n  /**\n   * Get the simulate enable flag.\n   *\n   * @returns The simulate feature enable flag.\n   */\n  getSimulateEnable(): boolean {\n    return this.simulateEnable;\n  }\n\n  /**\n   * Set the simulate mode.\n   *\n   * @param mode - The simulate mode.\n   *   - PropertiesOnly: Simulate only device properties.\n   *   - SensorsOnly: Simulate only device sensors.\n   *   - PackagesOnly: Simulate only installed packages.\n   *   - ServicesOnly: Simulate only system services.\n   *   - All: Simulate all aspects of the device.\n   */\n  setSimulateMode(mode: MobileSimulateMode): void {\n    this.simulateMode = mode;\n  }\n\n  /**\n   * Get the simulate mode.\n   *\n   * @returns The simulate mode.\n   */\n  getSimulateMode(): MobileSimulateMode {\n    return this.simulateMode;\n  }\n\n  /**\n   * Set a previously saved simulate context id. Please make sure the context id is provided by MobileSimulateService\n   * but not user side created context.\n   *\n   * @param contextId - The context ID of the previously saved mobile simulate context.\n   */\n  setSimulateContextId(contextId: string): void {\n    this.contextId = contextId;\n    logInfo(`set simulate context id = ${contextId}`);\n    this.updateContext(true, contextId, undefined);\n  }\n\n  /**\n   * Get the simulate context id.\n   *\n   * @returns The context ID of the mobile simulate context.\n   */\n  getSimulateContextId(): string | undefined {\n    return this.contextId;\n  }\n\n  /**\n   * Get the simulate config.\n   *\n   * @returns The simulate config.\n   *   - simulate: The simulate feature enable flag.\n   *   - simulatePath: The path of the mobile dev info file.\n   *   - simulateMode: The simulate mode.\n   *   - simulatedContextId: The context ID of the mobile info.\n   */\n  getSimulateConfig(): MobileSimulateConfig {\n    const simulatedContextId = this.useInternalContext\n      ? this.contextId\n      : undefined;\n\n    return {\n      simulate: this.simulateEnable,\n      simulatePath: this.mobileDevInfoPath,\n      simulateMode: this.simulateMode,\n      simulatedContextId: simulatedContextId,\n    };\n  }\n\n  /**\n   * Check if the mobile dev info file exists in one context sync. (Only for user provided context sync)\n   *\n   * @param contextSync - The context sync to check.\n   * @returns True if the mobile dev info file exists, False otherwise.\n   * @throws Error if context_sync is not provided or context_sync.context_id or context_sync.path is not provided.\n   *\n   * @remarks\n   * This method can only be used when mobile simulate context sync is managed by user side. For internal mobile simulate\n   * context sync, this method will not work.\n   */\n  async hasMobileInfo(contextSync: ContextSync): Promise<boolean> {\n    if (!contextSync) {\n      throw new Error(\"contextSync is required\");\n    }\n    if (!contextSync.contextId) {\n      throw new Error(\"contextSync.contextId is required\");\n    }\n    if (!contextSync.path) {\n      throw new Error(\"contextSync.path is required\");\n    }\n\n    const mobileDevInfoPath = contextSync.path + MOBILE_INFO_SUB_PATH + \"/\";\n    logDebug(\n      `hasMobileInfo: context_id = ${contextSync.contextId}, mobile_dev_info_path = ${mobileDevInfoPath}`\n    );\n\n    const res = await this.contextService.listFiles(\n      contextSync.contextId,\n      mobileDevInfoPath,\n      1,\n      50\n    );\n\n    let foundDevInfo = false;\n    if (res.success) {\n      for (const entry of res.entries) {\n        if (entry.fileName === MOBILE_INFO_FILE_NAME) {\n          foundDevInfo = true;\n          break;\n        }\n      }\n    } else {\n      logError(`failed to list files: ${res.errorMessage}`);\n      return false;\n    }\n\n    if (foundDevInfo) {\n      logInfo(\"mobile dev info already exists\");\n      // update and save context sync if check success\n      this.updateContext(false, contextSync.contextId, contextSync);\n      return true;\n    } else {\n      logInfo(\"mobile dev info does not exist\");\n      return false;\n    }\n  }\n\n  /**\n   * Upload the mobile simulate dev info.\n   *\n   * @param mobileDevInfoContent - The mobile simulate dev info content to upload.\n   * @param contextSync - Optional\n   *   - If not provided, a new context sync will be created for the mobile simulate service and this context id will\n   *     be returned by the MobileSimulateUploadResult. User can use this context id to do persistent mobile simulate across sessions.\n   *   - If provided, the mobile simulate dev info will be uploaded to the context sync in a specific path.\n   *\n   * @returns The result of the upload operation.\n   *\n   * @throws Error if mobile_dev_info_content is not provided or not a valid JSON string.\n   * @throws Error if context_sync is provided but context_sync.context_id is not provided.\n   *\n   * @remarks\n   * If context_sync is not provided, a new context sync will be created for the mobile simulate.\n   * If context_sync is provided, the mobile simulate dev info will be uploaded to the context sync.\n   * If the mobile simulate dev info already exists in the context sync, the context sync will be updated.\n   * If the mobile simulate dev info does not exist in the context sync, the context sync will be created.\n   * If the upload operation fails, the error message will be returned.\n   */\n  async uploadMobileInfo(\n    mobileDevInfoContent: string,\n    contextSync?: ContextSync\n  ): Promise<MobileSimulateUploadResult> {\n    // validate parameters\n    if (!mobileDevInfoContent) {\n      throw new Error(\"mobileDevInfoContent is required\");\n    }\n\n    try {\n      JSON.parse(mobileDevInfoContent);\n    } catch (error) {\n      throw new Error(\"mobileDevInfoContent is not a valid JSON string\");\n    }\n\n    // Create context for simulate if not provided\n    if (!contextSync) {\n      const createdContext = await this.createContextForSimulate();\n      if (!createdContext) {\n        logError(\"Failed to create context for simulate\");\n        return {\n          success: false,\n          errorMessage: \"Failed to create context for simulate\",\n        };\n      }\n      this.updateContext(true, createdContext.id, undefined);\n    } else {\n      if (!contextSync.contextId) {\n        throw new Error(\"contextSync.contextId is required\");\n      }\n      this.updateContext(false, contextSync.contextId, contextSync);\n    }\n\n    const uploadPath = `${this.mobileDevInfoPath}/${MOBILE_INFO_FILE_NAME}`;\n    const uploadUrlResult = await this.contextService.getFileUploadUrl(\n      this.contextId!,\n      uploadPath\n    );\n\n    if (!uploadUrlResult.success) {\n      logError(\n        `Failed to get file upload URL: ${uploadUrlResult.errorMessage}`\n      );\n      return {\n        success: false,\n        errorMessage: uploadUrlResult.errorMessage,\n      };\n    }\n\n    logDebug(`upload_url = ${uploadUrlResult.url}`);\n\n    try {\n      // Convert JSON string to Uint8Array\n      const encoder = new TextEncoder();\n      const uint8Array = encoder.encode(mobileDevInfoContent);\n      const response = await fetch(uploadUrlResult.url, {\n        method: \"PUT\",\n        body: uint8Array,\n      });\n\n      if (!response.ok) {\n        throw new Error(\n          `Upload failed with status ${response.status}: ${response.statusText}`\n        );\n      }\n    } catch (error) {\n      const errorMsg = `An error occurred while uploading the file: ${\n        error instanceof Error ? error.message : String(error)\n      }`;\n      logError(errorMsg);\n      return {\n        success: false,\n        errorMessage: errorMsg,\n      };\n    }\n\n    logInfo(\"mobile dev info uploaded successfully\");\n    return {\n      success: true,\n      mobileSimulateContextId: this.contextId,\n    };\n  }\n\n  /**\n   * Update the context information.\n   *\n   * @param isInternal - Whether this is an internal context.\n   * @param contextId - The context ID.\n   * @param contextSync - The context sync (required for external context).\n   */\n  private updateContext(\n    isInternal: boolean,\n    contextId: string,\n    contextSync?: ContextSync\n  ): void {\n    if (!isInternal) {\n      if (!contextSync) {\n        throw new Error(\"contextSync is required for external context\");\n      }\n      // add mobile info path to context sync bw list\n      if (contextSync.policy?.bwList?.whiteLists) {\n        const exists = contextSync.policy.bwList.whiteLists.some(\n          (whiteList) => whiteList.path === MOBILE_INFO_SUB_PATH\n        );\n\n        if (!exists) {\n          contextSync.policy.bwList.whiteLists.push({\n            path: MOBILE_INFO_SUB_PATH,\n            excludePaths: [],\n          });\n          logInfo(\n            `added mobile_dev_info_path to context_sync.policy.bw_list.white_lists: ${MOBILE_INFO_SUB_PATH}`\n          );\n        }\n      }\n    }\n\n    this.useInternalContext = isInternal;\n    this.contextId = contextId;\n    this.contextSync = contextSync;\n    if (isInternal) {\n      this.mobileDevInfoPath = MOBILE_INFO_DEFAULT_PATH;\n    } else {\n      this.mobileDevInfoPath = contextSync!.path + MOBILE_INFO_SUB_PATH;\n    }\n    logInfo(\n      `updated context, is_internal = ${isInternal}, context_id = ${this.contextId}, mobile_dev_info_path = ${this.mobileDevInfoPath}`\n    );\n  }\n\n  /**\n   * Create a context for simulate.\n   *\n   * @returns The created context or null if failed.\n   */\n  private async createContextForSimulate(): Promise<Context | null> {\n    const randomHex = Array.from({ length: 16 }, () =>\n      Math.floor(Math.random() * 256)\n        .toString(16)\n        .padStart(2, \"0\")\n    ).join(\"\");\n    const contextName = `mobile_sim_${randomHex}_${Math.floor(\n      Date.now() / 1000\n    )}`;\n\n    const contextResult = await this.contextService.get(contextName, true);\n    if (!contextResult.success || !contextResult.context) {\n      logError(\n        `Failed to create mobile simulate context: ${contextResult.errorMessage}`\n      );\n      return null;\n    }\n\n    const context = contextResult.context;\n    logInfo(\n      `created mobile simulate context, context_id = ${context.id}, context_name = ${context.name}`\n    );\n    return context;\n  }\n}\n","/**\n * App manager rule for mobile device configuration.\n *\n * Defines rules for managing app access on mobile devices through whitelist or blacklist modes.\n */\nexport interface AppManagerRule {\n  /**\n   * Type of rule to apply.\n   * - \"White\": Whitelist mode - only allow specified apps\n   * - \"Black\": Blacklist mode - block specified apps\n   */\n  ruleType: \"White\" | \"Black\";\n\n  /**\n   * List of Android package names to apply the rule to.\n   * Example: [\"com.android.settings\", \"com.example.app\"]\n   */\n  appPackageNameList: string[];\n}\n\n/**\n * Mobile simulate mode enum.\n */\nexport enum MobileSimulateMode {\n  PropertiesOnly = \"PropertiesOnly\",\n  SensorsOnly = \"SensorsOnly\",\n  PackagesOnly = \"PackagesOnly\",\n  ServicesOnly = \"ServicesOnly\",\n  All = \"All\",\n}\n\n/**\n * Mobile simulate configuration.\n */\nexport interface MobileSimulateConfig {\n  simulate: boolean;\n  simulatePath?: string;\n  simulateMode: MobileSimulateMode;\n  simulatedContextId?: string;\n}\n\n/**\n * Mobile-specific configuration settings for session creation.\n *\n * These settings allow control over mobile device behavior including\n * resolution locking, app access management, navigation bar visibility, and uninstall protection.\n */\nexport interface MobileExtraConfig {\n  /**\n   * Whether to lock the screen resolution.\n   * - true: Locks resolution for consistent mobile testing environments\n   * - false: Allows adaptive resolution for different device types\n   */\n  lockResolution: boolean;\n\n  /**\n   * Optional app manager rule for controlling app access.\n   * Defines which apps are allowed (whitelist) or blocked (blacklist).\n   */\n  appManagerRule?: AppManagerRule;\n\n  /**\n   * Whether to hide the system navigation bar for immersive full-screen experience.\n   * - true: Hide navigation bar\n   * - false: Show navigation bar (default)\n   */\n  hideNavigationBar?: boolean;\n\n  /**\n   * List of package names to protect from uninstallation.\n   * Prevents accidental or malicious removal of critical apps.\n   * Example: [\"com.android.systemui\", \"com.android.settings\"]\n   */\n  uninstallBlacklist?: string[];\n\n  /**\n   * Configuration for mobile device simulation.\n   * Used to simulate specific device properties, sensors, etc.\n   */\n  simulateConfig?: MobileSimulateConfig;\n}\n\n/**\n * Extra configuration settings for different session types.\n *\n * This container holds specialized configurations for various\n * session environments (mobile, desktop, etc.).\n */\nexport interface ExtraConfigs {\n  /**\n   * Mobile-specific configuration settings.\n   * Only applicable when creating mobile sessions.\n   */\n  mobile?: MobileExtraConfig;\n}\n\n/**\n * Serializes ExtraConfigs to JSON string format.\n * Returns empty string if extraConfigs is null or undefined.\n *\n * @param extraConfigs - The extra configs to serialize\n * @returns JSON string representation\n */\nexport function extraConfigsToJSON(extraConfigs?: ExtraConfigs | null): string {\n  if (!extraConfigs) {\n    return \"\";\n  }\n\n  return JSON.stringify(extraConfigs);\n}\n\n/**\n * Deserializes ExtraConfigs from JSON string format.\n * Returns null if jsonStr is empty or invalid.\n *\n * @param jsonStr - JSON string to deserialize\n * @returns Parsed ExtraConfigs object or null\n */\nexport function extraConfigsFromJSON(jsonStr: string): ExtraConfigs | null {\n  if (!jsonStr || jsonStr.trim() === \"\") {\n    return null;\n  }\n\n  try {\n    return JSON.parse(jsonStr) as ExtraConfigs;\n  } catch (error) {\n    throw new Error(`Failed to parse ExtraConfigs JSON: ${error}`);\n  }\n}\n\n/**\n * Validates an AppManagerRule object.\n * Throws an error if validation fails.\n *\n * @param rule - The rule to validate\n */\nexport function validateAppManagerRule(rule: AppManagerRule): void {\n  if (!rule.ruleType) {\n    throw new Error(\"AppManagerRule ruleType is required\");\n  }\n\n  if (rule.ruleType !== \"White\" && rule.ruleType !== \"Black\") {\n    throw new Error(\n      `Invalid ruleType: ${rule.ruleType}. Must be \"White\" or \"Black\"`\n    );\n  }\n\n  if (!Array.isArray(rule.appPackageNameList)) {\n    throw new Error(\"AppManagerRule appPackageNameList must be an array\");\n  }\n\n  for (const packageName of rule.appPackageNameList) {\n    if (typeof packageName !== \"string\") {\n      throw new Error(\n        \"AppManagerRule appPackageNameList items must be strings\"\n      );\n    }\n  }\n}\n\n/**\n * Validates a MobileSimulateConfig object.\n * Throws an error if validation fails.\n *\n * @param config - The config to validate\n */\nexport function validateMobileSimulateConfig(\n  config: MobileSimulateConfig\n): void {\n  if (typeof config.simulate !== \"boolean\") {\n    throw new Error(\"MobileSimulateConfig simulate must be a boolean\");\n  }\n\n  if (!config.simulateMode) {\n    throw new Error(\"MobileSimulateConfig simulateMode is required\");\n  }\n\n  if (!Object.values(MobileSimulateMode).includes(config.simulateMode)) {\n    throw new Error(`Invalid simulateMode: ${config.simulateMode}`);\n  }\n\n  if (\n    config.simulatePath !== undefined &&\n    typeof config.simulatePath !== \"string\"\n  ) {\n    throw new Error(\"MobileSimulateConfig simulatePath must be a string\");\n  }\n\n  if (\n    config.simulatedContextId !== undefined &&\n    typeof config.simulatedContextId !== \"string\"\n  ) {\n    throw new Error(\"MobileSimulateConfig simulatedContextId must be a string\");\n  }\n}\n\n/**\n * Validates a MobileExtraConfig object.\n * Throws an error if validation fails.\n *\n * @param config - The config to validate\n */\nexport function validateMobileExtraConfig(config: MobileExtraConfig): void {\n  if (typeof config.lockResolution !== \"boolean\") {\n    throw new Error(\"MobileExtraConfig lockResolution must be a boolean\");\n  }\n\n  if (config.appManagerRule) {\n    validateAppManagerRule(config.appManagerRule);\n  }\n\n  if (\n    config.hideNavigationBar !== undefined &&\n    typeof config.hideNavigationBar !== \"boolean\"\n  ) {\n    throw new Error(\"MobileExtraConfig hideNavigationBar must be a boolean\");\n  }\n\n  if (config.uninstallBlacklist) {\n    if (!Array.isArray(config.uninstallBlacklist)) {\n      throw new Error(\"MobileExtraConfig uninstallBlacklist must be an array\");\n    }\n\n    for (const packageName of config.uninstallBlacklist) {\n      if (typeof packageName !== \"string\" || packageName.trim() === \"\") {\n        throw new Error(\n          \"MobileExtraConfig uninstallBlacklist items must be non-empty strings\"\n        );\n      }\n    }\n  }\n\n  if (config.simulateConfig) {\n    validateMobileSimulateConfig(config.simulateConfig);\n  }\n}\n\n/**\n * Validates an ExtraConfigs object.\n * Throws an error if validation fails.\n *\n * @param extraConfigs - The extra configs to validate\n */\nexport function validateExtraConfigs(extraConfigs: ExtraConfigs): void {\n  if (extraConfigs.mobile) {\n    validateMobileExtraConfig(extraConfigs.mobile);\n  }\n}\n","export {\n  createListSessionParams,\n  type ListSessionParams,\n  type SessionListResult,\n} from \"./list-session-params\";\n\nexport {\n  extractRequestId,\n  type ApiResponse,\n  type ApiResponseWithData,\n  type DeleteResult,\n  type SessionMetrics,\n  type SessionMetricsResult,\n  type BinaryFileContentResult,\n  type FileContentResult,\n  type FileInfoResult,\n  type DirectoryListResult,\n  type MultipleFileContentResult,\n  type FileSearchResult,\n} from \"./api-response\";\n\nexport {\n  type AppManagerRule,\n  MobileSimulateMode,\n  type MobileSimulateConfig,\n  type MobileExtraConfig,\n  type ExtraConfigs,\n  validateAppManagerRule,\n  validateMobileSimulateConfig,\n  validateMobileExtraConfig,\n  validateExtraConfigs,\n  extraConfigsToJSON,\n  extraConfigsFromJSON,\n} from \"./extra-configs\";\n","import { Session } from \"../session\";\nimport { ApiResponse } from \"./api-response\";\n\n/**\n * Parameters for listing sessions with pagination support\n */\nexport interface ListSessionParams {\n  /** Number of results per page (default: 10) */\n  maxResults?: number;\n\n  /** Token for the next page */\n  nextToken?: string;\n\n  /** Labels to filter by */\n  labels: Record<string, string>;\n}\n\n/**\n * Result type for session listing with pagination information\n */\nexport interface SessionListResult extends ApiResponse {\n  /** Array of session information with ID and status */\n  sessionIds: Array<{\n    sessionId: string;\n    sessionStatus: string;\n    appInstanceId?: string;\n    imageId?: string;\n  }>;\n\n  /** Token for the next page (if available) */\n  nextToken?: string;\n\n  /** Number of results per page */\n  maxResults?: number;\n\n  /** Total number of results */\n  totalCount?: number;\n}\n\n/**\n * Helper function to create ListSessionParams with default values\n */\nexport function createListSessionParams(\n  labels: Record<string, string> = {}\n): ListSessionParams {\n  return {\n    maxResults: 10,\n    labels,\n  };\n}\n","export { LocalPageAgent, LocalBrowser, LocalSession } from \"./local_page_agent\";\n","import { spawn, ChildProcess } from \"child_process\";\nimport { readFile, writeFile, mkdir } from \"fs/promises\";\nimport { join } from \"path\";\nimport { randomUUID } from \"crypto\";\nimport {\n  chromium,\n  Browser as PlaywrightBrowser,\n  BrowserContext,\n} from \"playwright\";\nimport { Session } from \"../../session\";\nimport { Browser } from \"../browser\";\nimport { BrowserOperator } from \"../browser_operator\";\nimport { OperationResult, DeleteResult } from \"../../types/api-response\";\nimport { McpToolResult } from \"../../agent/agent\";\nimport { logInfo, logDebug, logWarn, logError } from \"../../utils/logger\";\n\n/**\n * Local MCP Client for communicating with MCP servers via stdio\n */\nclass LocalMCPClient {\n  private server: string;\n  private command: string;\n  private args: string[];\n  private env: NodeJS.ProcessEnv | null;\n  private session: any | null = null;\n  private workerThread: ChildProcess | null = null;\n  private toolCallQueue: Array<{\n    toolName: string;\n    arguments: Record<string, any>;\n    resolve: (result: OperationResult) => void;\n    reject: (error: Error) => void;\n  }> = [];\n  private isConnected = false;\n  private connectPromise: Promise<void> | null = null;\n\n  /**\n   * Check if the MCP client is connected\n   */\n  get connected(): boolean {\n    return this.isConnected && this.workerThread !== null;\n  }\n\n  constructor(\n    server: string,\n    command: string,\n    args: string[],\n    env: NodeJS.ProcessEnv | null = null\n  ) {\n    this.server = server;\n    this.command = command;\n    this.args = args;\n    this.env = env;\n  }\n\n  /**\n   * Connect to the MCP server\n   * If already connected, returns immediately\n   * If connection is in progress, waits for it to complete\n   */\n  async connect(): Promise<void> {\n    // If already connected, return immediately\n    if (this.connected) {\n      return;\n    }\n\n    // If connection is in progress, wait for it\n    if (this.connectPromise) {\n      return this.connectPromise;\n    }\n\n    // Start a new connection\n    this.connectPromise = this._doConnect();\n    return this.connectPromise;\n  }\n\n  /**\n   * Internal method to perform the actual connection\n   */\n  private async _doConnect(): Promise<void> {\n    return new Promise((resolve, reject) => {\n      logInfo(\"[LocalMCPClient] Starting connection to MCP server\");\n      logInfo(\n        `[LocalMCPClient] command = ${this.command}, args = ${this.args.join(\n          \" \"\n        )}`\n      );\n\n      // Spawn the MCP server process\n      // Use provided env if available, otherwise use process.env\n      const envToUse = this.env !== null ? this.env : process.env;\n      const childProcess = spawn(this.command, this.args, {\n        stdio: [\"pipe\", \"pipe\", \"pipe\"],\n        env: envToUse,\n      });\n\n      this.workerThread = childProcess;\n\n      let initResolved = false;\n      const initTimeout = setTimeout(() => {\n        if (!initResolved) {\n          initResolved = true;\n          this.isConnected = true;\n          this.connectPromise = null;\n          logInfo(\n            \"[LocalMCPClient] MCP client connection timeout - marking as connected (server may still be initializing)\"\n          );\n          resolve();\n        }\n      }, 15000); // 15 second timeout as fallback\n\n      // Handle stdout (MCP server responses)\n      let buffer = \"\";\n      childProcess.stdout?.on(\"data\", (data: Buffer) => {\n        buffer += data.toString();\n        // Try to parse JSON messages (simplified - real MCP protocol is more complex)\n        try {\n          const lines = buffer.split(\"\\n\");\n          buffer = lines.pop() || \"\";\n          for (const line of lines) {\n            if (line.trim()) {\n              const parsed = JSON.parse(line.trim());\n              // Check for initialization response or any response that indicates server is ready\n              if (\n                parsed.result ||\n                parsed.method === \"notifications/initialized\" ||\n                (parsed.id && parsed.id === \"init\")\n              ) {\n                if (!initResolved) {\n                  clearTimeout(initTimeout);\n                  initResolved = true;\n                  this.isConnected = true;\n                  this.connectPromise = null;\n                  logInfo(\n                    \"[LocalMCPClient] MCP client session initialized (received response from server)\"\n                  );\n                  resolve();\n                }\n              }\n              this.handleMessage(line.trim());\n            }\n          }\n        } catch (e) {\n          // Not JSON or parse error, continue\n        }\n      });\n\n      // Handle stderr\n      childProcess.stderr?.on(\"data\", (data: Buffer) => {\n        const stderrText = data.toString();\n        logDebug(`[LocalMCPClient] stderr: ${stderrText}`);\n        // Check for initialization complete indicators in stderr logs\n        if (\n          stderrText.includes(\"started\") ||\n          stderrText.includes(\"initialized\") ||\n          stderrText.includes(\"ready\")\n        ) {\n          // Give it a moment after seeing these messages\n          setTimeout(() => {\n            if (!initResolved) {\n              clearTimeout(initTimeout);\n              initResolved = true;\n              this.isConnected = true;\n              this.connectPromise = null;\n              logInfo(\n                \"[LocalMCPClient] MCP client session initialized (detected from stderr logs)\"\n              );\n              resolve();\n            }\n          }, 2000); // Wait 2 seconds after seeing ready message\n        }\n      });\n\n      // Handle process exit\n      childProcess.on(\"exit\", (code: number | null) => {\n        logInfo(`[LocalMCPClient] Process exited with code ${code}`);\n        clearTimeout(initTimeout);\n        this.isConnected = false;\n        this.workerThread = null;\n        this.connectPromise = null; // Clear the promise on exit\n        if (!initResolved) {\n          initResolved = true;\n          reject(\n            new Error(\n              `MCP server process exited with code ${code} before initialization completed`\n            )\n          );\n        }\n      });\n\n      childProcess.on(\"error\", (error: Error) => {\n        clearTimeout(initTimeout);\n        this.connectPromise = null; // Clear the promise on error\n        logError(`[LocalMCPClient] Failed to spawn MCP server: ${error}`);\n        if (!initResolved) {\n          initResolved = true;\n          reject(error);\n        }\n      });\n\n      // Send initialization request (MCP protocol)\n      const initRequest = {\n        jsonrpc: \"2.0\",\n        id: \"init\",\n        method: \"initialize\",\n        params: {\n          protocolVersion: \"2024-11-05\",\n          capabilities: {},\n          clientInfo: {\n            name: \"LocalPageAgent\",\n            version: \"1.0.0\",\n          },\n        },\n      };\n\n      // Wait a moment for the process to start, then send init request\n      setTimeout(() => {\n        if (childProcess.stdin && !childProcess.stdin.destroyed) {\n          childProcess.stdin.write(JSON.stringify(initRequest) + \"\\n\");\n          logInfo(\"[LocalMCPClient] Sent initialization request to MCP server\");\n        }\n      }, 1000);\n    });\n  }\n\n  /**\n   * Handle incoming messages from MCP server\n   */\n  private handleMessage(message: string): void {\n    // Simplified message handling - real MCP protocol requires proper JSON-RPC parsing\n    try {\n      const parsed = JSON.parse(message);\n      // Process tool call responses\n      if (parsed.result && this.toolCallQueue.length > 0) {\n        const queued = this.toolCallQueue.shift();\n        if (queued) {\n          // Extract the actual data from MCP response format\n          // MCP responses have format: { jsonrpc: \"2.0\", id: \"...\", result: { content: [{ type: \"text\", text: \"...\" }] } }\n          let responseData: any = parsed.result;\n\n          //logInfo(`[LocalMCPClient] Tool call response raw data: ${JSON.stringify(responseData, null, 2)}`);\n          // If result has content array, extract text from the first content item\n          if (\n            parsed.result &&\n            parsed.result.content &&\n            Array.isArray(parsed.result.content) &&\n            parsed.result.content.length > 0\n          ) {\n            const contentItem = parsed.result.content[0];\n            if (contentItem && contentItem.text !== undefined) {\n              // Extract the text field which contains the actual data\n              responseData = contentItem.text;\n            }\n          } else if (typeof parsed.result === \"string\") {\n            // If result is already a string, use it directly\n            responseData = parsed.result;\n          } else {\n            // For other formats, stringify the result\n            responseData =\n              typeof parsed.result === \"string\"\n                ? parsed.result\n                : JSON.stringify(parsed.result);\n          }\n\n          const response: OperationResult = {\n            requestId: parsed.id || `local_request_${randomUUID()}`,\n            success: !parsed.error,\n            data:\n              typeof responseData === \"string\"\n                ? responseData\n                : JSON.stringify(responseData),\n            errorMessage: parsed.error?.message,\n          };\n          //logInfo(`[LocalMCPClient] Tool call response: ${JSON.stringify(response, null, 2)}`);\n          queued.resolve(response);\n        }\n      }\n    } catch (e) {\n      // Not JSON, continue\n      logDebug(\n        `[LocalMCPClient] Failed to parse message: ${e}, message: ${message.substring(\n          0,\n          200\n        )}`\n      );\n    }\n  }\n\n  /**\n   * Call an MCP tool\n   */\n  async callTool(\n    toolName: string,\n    arguments_: Record<string, any>\n  ): Promise<OperationResult> {\n    if (!this.connected) {\n      throw new RuntimeError(\n        \"MCP client is not connected. Call connect() and ensure it completes before calling callTool.\"\n      );\n    }\n\n    return new Promise((resolve, reject) => {\n      logInfo(\n        `[LocalMCPClient] Call tool ${toolName} with arguments ${JSON.stringify(\n          arguments_\n        )}`\n      );\n\n      // Queue the tool call\n      this.toolCallQueue.push({\n        toolName,\n        arguments: arguments_,\n        resolve,\n        reject,\n      });\n\n      // Send tool call request (simplified JSON-RPC format)\n      const request = {\n        jsonrpc: \"2.0\",\n        id: randomUUID(),\n        method: \"tools/call\",\n        params: {\n          name: toolName,\n          arguments: arguments_,\n        },\n      };\n\n      this.workerThread?.stdin?.write(JSON.stringify(request) + \"\\n\");\n\n      // Timeout after 180 seconds\n      const TOOL_CALL_TIMEOUT = 180000;\n      setTimeout(() => {\n        reject(new Error(`Tool call timeout: ${toolName}`));\n      }, TOOL_CALL_TIMEOUT);\n    });\n  }\n}\n\nclass RuntimeError extends Error {\n  constructor(message: string) {\n    super(message);\n    this.name = \"RuntimeError\";\n  }\n}\n\n/**\n * Local Page Agent that extends BrowserOperator for local execution\n *\n * Note: Since BrowserOperator._callMcpTool is private, we route through the session instead.\n * The LocalSession.callMcpTool method routes to this agent's MCP client.\n */\nexport class LocalPageAgent extends BrowserOperator {\n  private mcpClient: LocalMCPClient | null = null;\n\n  constructor(session: Session, browser: Browser) {\n    super(session, browser);\n\n    const mcpScript = process.env.PAGE_TASK_MCP_SERVER_SCRIPT || \"\";\n\n    if (mcpScript) {\n      // Pass environment variables to MCP client\n      const env = { ...process.env };\n      this.mcpClient = new LocalMCPClient(\n        \"PageUseAgent\",\n        \"python\",\n        [mcpScript],\n        env\n      );\n    } else {\n      this.mcpClient = null;\n      logWarn(\n        \"PAGE_TASK_MCP_SERVER_SCRIPT not set. MCP client will not be initialized.\"\n      );\n    }\n  }\n\n  /**\n   * Initialize the MCP client connection\n   */\n  async initialize(): Promise<void> {\n    if (this.mcpClient) {\n      await this.mcpClient.connect();\n    }\n  }\n\n  /**\n   * Call MCP tool asynchronously (used by LocalSession)\n   * Public to allow LocalSession to route tool calls through the MCP client\n   * Automatically ensures the MCP client is connected before calling\n   */\n  async _callMcpToolAsync(\n    name: string,\n    args: Record<string, any>\n  ): Promise<OperationResult> {\n    if (!this.mcpClient) {\n      throw new RuntimeError(\"mcp_client is not set on LocalPageAgent.\");\n    }\n    // Ensure connection is established before calling tool\n    if (!this.mcpClient.connected) {\n      await this.mcpClient.connect();\n    }\n    return await this.mcpClient.callTool(name, args);\n  }\n}\n\n/**\n * Local Browser implementation that uses Playwright directly\n */\nexport class LocalBrowser extends Browser {\n  private _cdpPort = 9222;\n  private _browser: PlaywrightBrowser | BrowserContext | null = null;\n  private _workerThread: ChildProcess | null = null;\n  private _playwrightInteractiveLoopAbortSignal: AbortSignal | null = null;\n  private _playwrightInteractiveLoopAbortController: AbortController | null =\n    null;\n  public agent: LocalPageAgent;\n\n  constructor(session?: Session) {\n    // Create a minimal mock session if none provided (static method to avoid using 'this')\n    const tempSession = session || LocalBrowser._createMinimalMockSession();\n    super(tempSession);\n    // @ts-expect-error - Access protected member\n    this.contexts = [];\n    // @ts-expect-error - LocalBrowser uses async initialize, incompatible with base Browser type\n    this.agent = new LocalPageAgent(tempSession, this);\n\n    // Create an abort signal for the playwright interactive loop\n    this._playwrightInteractiveLoopAbortController = new AbortController();\n    this._playwrightInteractiveLoopAbortSignal =\n      this._playwrightInteractiveLoopAbortController.signal;\n\n    // Update the mock session's callMcpTool to use the agent now that it's created\n    if (!session && (tempSession as any).__isMock) {\n      (tempSession as any).callMcpTool = async (\n        name: string,\n        args: Record<string, any>\n      ) => {\n        return await this.agent._callMcpToolAsync(name, args);\n      };\n    }\n  }\n\n  /**\n   * Create a minimal mock session for local mode (static to avoid using 'this' before super())\n   */\n  private static _createMinimalMockSession(): Session {\n    // Create a minimal session-like object that will be updated after agent creation\n    const mockSession = {\n      sessionId: \"local_session\",\n      __isMock: true,\n      callMcpTool: async (_name: string, _args: Record<string, any>) => {\n        throw new Error(\n          \"Mock session not yet initialized - this should not be called\"\n        );\n      },\n    } as any as Session;\n\n    return mockSession;\n  }\n\n  /**\n   * Initialize the local browser\n   * Note: This overrides the base class sync initialize method with async implementation\n   */\n  // @ts-expect-error - LocalBrowser uses async initialization, incompatible with base class sync signature\n  async initialize(options: any): Promise<boolean> {\n    if (this._workerThread) {\n      return true;\n    }\n\n    return new Promise(async (resolve) => {\n      logInfo(\"[LocalBrowser] Start launching local browser\");\n\n      try {\n        // Create CDP ports file\n        const tmpDir =\n          process.platform === \"win32\" ? process.env.TEMP || \"/tmp\" : \"/tmp\";\n        const chromeCdpPortsPath = join(tmpDir, \"chrome_cdp_ports.json\");\n        const cdpPortsData = {\n          chrome: String(this._cdpPort),\n          router: String(this._cdpPort),\n          local: String(this._cdpPort),\n        };\n\n        await writeFile(\n          chromeCdpPortsPath,\n          JSON.stringify(cdpPortsData, null, 2)\n        );\n\n        const cwd = process.cwd();\n        const userDataDir = join(\n          cwd,\n          \"tmp\",\n          `browser_user_data_${process.pid}_${randomUUID()}`\n        );\n\n        // Read env variable HEADLESS_MODE\n        const headlessMode = process.env.HEADLESS || \"false\";\n        const headless = headlessMode.toLowerCase() === \"true\";\n\n        // Launch Playwright browser with persistent context\n        const playwright = await import(\"playwright\");\n        const browser = await playwright.chromium.launchPersistentContext(\n          userDataDir,\n          {\n            headless: headless,\n            viewport: { width: 1280, height: 1200 },\n            args: [`--remote-debugging-port=${this._cdpPort}`],\n          }\n        );\n\n        this._browser = browser;\n\n        logInfo(\"[LocalBrowser] Local browser launched successfully\");\n        // Initialize MCP agent connection (don't block on it, but start it)\n        this.agent.initialize().catch((err) => {\n          logWarn(`[LocalBrowser] Failed to initialize agent: ${err}`);\n        });\n        resolve(true);\n\n        // Keep the process alive\n        await this._playwrightInteractiveLoop(\n          this._playwrightInteractiveLoopAbortSignal ?? undefined\n        );\n        logInfo(\"[LocalBrowser] Local browser interactive loop completed\");\n      } catch (error: any) {\n        logError(`[LocalBrowser] Failed to connect to browser: ${error}`);\n        resolve(false);\n      }\n    });\n  }\n\n  /**\n   * Check if browser is initialized\n   */\n  isInitialized(): boolean {\n    return this._browser !== null;\n  }\n\n  /**\n   * Get the endpoint URL for CDP connection\n   */\n  async getEndpointUrl(): Promise<string> {\n    return `http://localhost:${this._cdpPort}`;\n  }\n\n  /**\n   * Playwright interactive loop to keep the browser alive\n   */\n  private async _playwrightInteractiveLoop(\n    shutdownSignal?: AbortSignal\n  ): Promise<void> {\n    while (!shutdownSignal?.aborted) {\n      await new Promise((resolve) => setTimeout(resolve, 3000));\n    }\n  }\n\n  /**\n   * Abort the playwright interactive loop\n   */\n  abortPlaywrightInteractiveLoop(): void {\n    this._playwrightInteractiveLoopAbortController?.abort();\n  }\n}\n\n/**\n * Local Session implementation for local mode execution\n */\nexport class LocalSession extends Session {\n  // @ts-expect-error - LocalBrowser uses async initialize, incompatible with base Browser type\n  public browser: LocalBrowser;\n\n  constructor() {\n    // Create a mock agent_bay with the required attributes\n    const mockAgentBay = {\n      apiKey: process.env.AGENTBAY_API_KEY || \"\",\n      apiKeyConfigured: !!process.env.AGENTBAY_API_KEY,\n      client: {\n        apiBaseUrl: \"\",\n        getSessionStatus: (request: any) => ({\n          toMap: () => ({\n            success: true,\n            data: { status: \"running\" },\n          }),\n        }),\n        callMcpTool: (\n          name: string,\n          args: Record<string, any>,\n          kwargs?: any\n        ) => ({\n          requestId: \"mock_request_id\",\n          success: false,\n          data: null,\n          errorMessage:\n            \"Mock mode: Cannot execute tool calls without proper API connection\",\n        }),\n      },\n    } as any;\n\n    super(mockAgentBay, \"local_session\");\n    // @ts-expect-error - LocalBrowser uses async initialize, incompatible with base Browser type\n    this.browser = new LocalBrowser(this);\n  }\n\n  /**\n   * Call MCP tool asynchronously\n   */\n  async callMcpTool(\n    toolName: string,\n    args: any,\n    autoGenSession = false\n  ): Promise<McpToolResult> {\n    /**\n     * Async stub for local mode. Keeps call signature compatible with the base\n     * Session.callMcpTool signature. Routes through LocalPageAgent's MCP client.\n     */\n    const localAgent = this.browser.operator as LocalPageAgent;\n    const result = await localAgent._callMcpToolAsync(toolName, args);\n    // Convert OperationResult to McpToolResult format\n    return {\n      success: result.success,\n      data: result.data as string,\n      errorMessage: result.errorMessage || \"\",\n      requestId: result.requestId,\n    };\n  }\n\n  /**\n   * Delete the session (no-op for local mode)\n   */\n  async delete(syncContext = false): Promise<DeleteResult> {\n    this.browser.abortPlaywrightInteractiveLoop();\n\n    // No-op for local session\n    return {\n      success: true,\n      requestId: `local_delete_${this.sessionId}`,\n      errorMessage: undefined,\n    };\n  }\n}\n"]}