agent-device 0.14.9 → 0.15.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/README.md +7 -4
  2. package/android-snapshot-helper/dist/{agent-device-android-snapshot-helper-0.14.9.apk → agent-device-android-snapshot-helper-0.15.1.apk} +0 -0
  3. package/android-snapshot-helper/dist/agent-device-android-snapshot-helper-0.15.1.apk.sha256 +1 -0
  4. package/android-snapshot-helper/dist/{agent-device-android-snapshot-helper-0.14.9.manifest.json → agent-device-android-snapshot-helper-0.15.1.manifest.json} +6 -6
  5. package/dist/src/1393.js +1 -0
  6. package/dist/src/1769.js +7 -0
  7. package/dist/src/1974.js +2 -2
  8. package/dist/src/208.js +1 -1
  9. package/dist/src/2151.js +434 -0
  10. package/dist/src/221.js +4 -4
  11. package/dist/src/2842.js +1 -0
  12. package/dist/src/3572.js +1 -0
  13. package/dist/src/4057.js +1 -1
  14. package/dist/src/4829.js +1 -1
  15. package/dist/src/9542.js +2 -2
  16. package/dist/src/9639.js +2 -2
  17. package/dist/src/989.js +1 -1
  18. package/dist/src/android-adb.d.ts +38 -9
  19. package/dist/src/android-adb.js +1 -1
  20. package/dist/src/android-snapshot-helper.d.ts +23 -0
  21. package/dist/src/cli.js +60 -57
  22. package/dist/src/contracts.d.ts +1 -0
  23. package/dist/src/finders.d.ts +1 -0
  24. package/dist/src/index.d.ts +56 -27
  25. package/dist/src/internal/companion-tunnel.js +1 -1
  26. package/dist/src/internal/daemon.js +51 -23
  27. package/dist/src/remote-config.d.ts +17 -14
  28. package/dist/src/selectors.d.ts +2 -0
  29. package/dist/src/server.js +2 -20
  30. package/ios-runner/AgentDeviceRunner/AgentDeviceRunner.xcodeproj/xcshareddata/xcschemes/AgentDeviceRunner.xcscheme +7 -1
  31. package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Alert.swift +155 -0
  32. package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandExecution.swift +131 -72
  33. package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Interaction.swift +734 -10
  34. package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Lifecycle.swift +89 -16
  35. package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Models.swift +5 -0
  36. package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Snapshot.swift +9 -0
  37. package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SystemModal.swift +4 -3
  38. package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests.swift +1 -2
  39. package/ios-runner/AgentDeviceRunner/AgentDeviceRunnerUITests.xctestplan +26 -0
  40. package/ios-runner/AgentDeviceRunner/RecordingScripts/recording-overlay.swift +7 -1
  41. package/package.json +30 -11
  42. package/server.json +3 -3
  43. package/skills/agent-device/SKILL.md +2 -7
  44. package/android-snapshot-helper/dist/agent-device-android-snapshot-helper-0.14.9.apk.sha256 +0 -1
  45. package/dist/src/180.js +0 -1
  46. package/dist/src/6108.js +0 -26
  47. package/dist/src/6642.js +0 -1
  48. package/dist/src/7462.js +0 -1
  49. package/dist/src/8809.js +0 -8
  50. package/dist/src/command-schema.js +0 -382
@@ -180,6 +180,7 @@ declare type RawSnapshotNode = {
180
180
  surface?: string;
181
181
  hiddenContentAbove?: boolean;
182
182
  hiddenContentBelow?: boolean;
183
+ presentationHints?: string[];
183
184
  };
184
185
 
185
186
  export declare type Rect = {
@@ -64,6 +64,7 @@ declare type RawSnapshotNode = {
64
64
  surface?: string;
65
65
  hiddenContentAbove?: boolean;
66
66
  hiddenContentBelow?: boolean;
67
+ presentationHints?: string[];
67
68
  };
68
69
 
69
70
  declare type Rect = {
@@ -10,9 +10,6 @@ export declare type AgentDeviceClient = {
10
10
  shutdown?: boolean;
11
11
  }) => Promise<SessionCloseResult>;
12
12
  };
13
- simulators: {
14
- ensure: (options: EnsureSimulatorOptions) => Promise<EnsureSimulatorResult>;
15
- };
16
13
  apps: {
17
14
  install: (options: AppDeployOptions) => Promise<AppDeployResult>;
18
15
  reinstall: (options: AppDeployOptions) => Promise<AppDeployResult>;
@@ -107,6 +104,7 @@ export declare type AgentDeviceCommandClient = {
107
104
  appSwitcher: (options?: AppSwitcherCommandOptions) => Promise<AppSwitcherCommandResult>;
108
105
  keyboard: (options?: KeyboardCommandOptions) => Promise<KeyboardCommandResult>;
109
106
  clipboard: (options: ClipboardCommandOptions) => Promise<ClipboardCommandResult>;
107
+ reactNative: (options: ReactNativeCommandOptions) => Promise<CommandRequestResult>;
110
108
  };
111
109
 
112
110
  export declare type AgentDeviceDaemonTransport = (req: Omit<DaemonRequest, 'token'>) => Promise<DaemonResponse>;
@@ -172,12 +170,39 @@ export declare type AgentDeviceSessionDevice = {
172
170
  };
173
171
  };
174
172
 
173
+ export declare type AlertAction = 'get' | 'accept' | 'dismiss' | 'wait';
174
+
175
175
  export declare type AlertCommandOptions = DeviceCommandBaseOptions & {
176
176
  action?: 'get' | 'accept' | 'dismiss' | 'wait';
177
177
  timeoutMs?: number;
178
178
  };
179
179
 
180
- export declare type AlertCommandResult = DaemonResponseData;
180
+ export declare type AlertCommandResult = DaemonResponseData & {
181
+ kind?: 'alertStatus' | 'alertHandled' | 'alertWait';
182
+ action?: AlertCommandOptions['action'];
183
+ alert?: AlertInfo | null;
184
+ handled?: boolean;
185
+ button?: string;
186
+ waitedMs?: number;
187
+ timedOut?: boolean;
188
+ platform?: AlertInfo['platform'];
189
+ accepted?: boolean;
190
+ dismissed?: boolean;
191
+ items?: string[];
192
+ };
193
+
194
+ export declare type AlertInfo = {
195
+ title?: string;
196
+ message?: string;
197
+ buttons?: string[];
198
+ platform?: AlertPlatform;
199
+ source?: AlertSource;
200
+ packageName?: string;
201
+ };
202
+
203
+ export declare type AlertPlatform = 'android' | 'ios' | 'macos';
204
+
205
+ export declare type AlertSource = 'permission' | 'native-dialog' | 'system-dialog';
181
206
 
182
207
  declare type AndroidSnapshotBackendMetadata = {
183
208
  backend: 'android-helper' | 'uiautomator-dump';
@@ -261,7 +286,7 @@ export declare type AppInstallFromSourceResult = {
261
286
  declare type ApplePlatform = 'ios' | 'macos';
262
287
 
263
288
  export declare type AppListOptions = AgentDeviceRequestOverrides & AgentDeviceSelectionOptions & {
264
- appsFilter?: 'all' | 'user-installed';
289
+ appsFilter?: AppsFilter;
265
290
  };
266
291
 
267
292
  export declare type AppOpenOptions = AgentDeviceRequestOverrides & AgentDeviceSelectionOptions & {
@@ -291,6 +316,8 @@ export declare type AppPushOptions = ClientCommandBaseOptions & {
291
316
  payload: string | Record<string, unknown>;
292
317
  };
293
318
 
319
+ declare type AppsFilter = 'user-installed' | 'all';
320
+
294
321
  export declare type AppStateCommandOptions = DeviceCommandBaseOptions;
295
322
 
296
323
  export declare type AppStateCommandResult = DaemonResponseData & {
@@ -365,6 +392,7 @@ export declare type CaptureScreenshotOptions = AgentDeviceRequestOverrides & {
365
392
  overlayRefs?: boolean;
366
393
  fullscreen?: boolean;
367
394
  maxSize?: number;
395
+ stabilize?: boolean;
368
396
  surface?: 'app' | 'frontmost-app' | 'desktop' | 'menubar';
369
397
  };
370
398
 
@@ -380,6 +408,7 @@ export declare type CaptureSnapshotOptions = AgentDeviceRequestOverrides & Agent
380
408
  depth?: number;
381
409
  scope?: string;
382
410
  raw?: boolean;
411
+ forceFull?: boolean;
383
412
  };
384
413
 
385
414
  export declare type CaptureSnapshotResult = {
@@ -390,6 +419,7 @@ export declare type CaptureSnapshotResult = {
390
419
  visibility?: SnapshotVisibility;
391
420
  androidSnapshot?: AndroidSnapshotBackendMetadata;
392
421
  warnings?: string[];
422
+ unchanged?: SnapshotUnchanged;
393
423
  identifiers: AgentDeviceIdentifiers;
394
424
  };
395
425
 
@@ -536,24 +566,6 @@ declare type DeviceTarget = 'mobile' | 'tv' | 'desktop';
536
566
 
537
567
  export declare type ElementTarget = RefTarget | SelectorTarget;
538
568
 
539
- export declare type EnsureSimulatorOptions = AgentDeviceRequestOverrides & {
540
- device: string;
541
- runtime?: string;
542
- boot?: boolean;
543
- reuseExisting?: boolean;
544
- iosSimulatorDeviceSet?: string;
545
- };
546
-
547
- export declare type EnsureSimulatorResult = {
548
- udid: string;
549
- device: string;
550
- runtime: string;
551
- created: boolean;
552
- booted: boolean;
553
- iosSimulatorDeviceSet?: string | null;
554
- identifiers: AgentDeviceIdentifiers;
555
- };
556
-
557
569
  export declare type FileInputRef = {
558
570
  kind: 'path';
559
571
  path: string;
@@ -638,7 +650,11 @@ export declare type KeyboardCommandResult = DaemonResponseData & {
638
650
  action?: 'status' | 'dismiss';
639
651
  visible?: boolean;
640
652
  inputType?: string | null;
653
+ inputMethodPackage?: string | null;
641
654
  type?: string | null;
655
+ focusedPackage?: string | null;
656
+ focusedResourceId?: string | null;
657
+ inputOwner?: 'app' | 'ime' | 'unknown';
642
658
  wasVisible?: boolean;
643
659
  dismissed?: boolean;
644
660
  attempts?: number;
@@ -686,9 +702,7 @@ export declare type LogsOptions = AgentDeviceRequestOverrides & {
686
702
  restart?: boolean;
687
703
  };
688
704
 
689
- export declare type LongPressOptions = ClientCommandBaseOptions & {
690
- x: number;
691
- y: number;
705
+ export declare type LongPressOptions = ClientCommandBaseOptions & SelectorSnapshotCommandOptions & InteractionTarget & {
692
706
  durationMs?: number;
693
707
  };
694
708
 
@@ -851,6 +865,11 @@ declare type RawSnapshotNode = {
851
865
  surface?: string;
852
866
  hiddenContentAbove?: boolean;
853
867
  hiddenContentBelow?: boolean;
868
+ presentationHints?: string[];
869
+ };
870
+
871
+ declare type ReactNativeCommandOptions = ClientCommandBaseOptions & {
872
+ action: 'dismiss-overlay';
854
873
  };
855
874
 
856
875
  declare type RecordingQuality = 5 | 6 | 7 | 8 | 9 | 10;
@@ -896,6 +915,9 @@ declare type RepeatedPressOptions = {
896
915
  export declare type ReplayRunOptions = AgentDeviceRequestOverrides & {
897
916
  path: string;
898
917
  update?: boolean;
918
+ /** @deprecated Use backend: 'maestro'. */
919
+ maestro?: boolean;
920
+ backend?: string;
899
921
  env?: string[];
900
922
  };
901
923
 
@@ -953,7 +975,7 @@ export declare type ScreenshotOverlayRef = {
953
975
  };
954
976
 
955
977
  declare type ScrollOptions_2 = ClientCommandBaseOptions & {
956
- direction: 'up' | 'down' | 'left' | 'right';
978
+ direction: 'up' | 'down' | 'left' | 'right' | 'top' | 'bottom';
957
979
  amount?: number;
958
980
  pixels?: number;
959
981
  };
@@ -1016,6 +1038,13 @@ export declare type SnapshotNode = RawSnapshotNode & {
1016
1038
  ref: string;
1017
1039
  };
1018
1040
 
1041
+ declare type SnapshotUnchanged = {
1042
+ ageMs: number;
1043
+ nodeCount: number;
1044
+ interactiveOnly?: boolean;
1045
+ scope?: string;
1046
+ };
1047
+
1019
1048
  export declare type SnapshotVisibility = {
1020
1049
  partial: boolean;
1021
1050
  visibleNodeCount: number;
@@ -1 +1 @@
1
- import e from"node:fs";import{setTimeout as r}from"node:timers/promises";import{normalizeBaseUrl as t,ENV_COMPANION_TUNNEL_UNREGISTER_PATH as n,MissingCompanionEnvError as s,ENV_COMPANION_TUNNEL_SERVER_BASE_URL as a,ENV_COMPANION_TUNNEL_STATE_PATH as o,ENV_COMPANION_TUNNEL_LAUNCH_URL as i,ENV_COMPANION_TUNNEL_SCOPE_LEASE_ID as c,ENV_COMPANION_TUNNEL_SCOPE_TENANT_ID as f,ENV_COMPANION_TUNNEL_DEVICE_PORT as l,METRO_COMPANION_RUN_ARG as u,ENV_COMPANION_TUNNEL_SESSION as d,ENV_COMPANION_TUNNEL_SCOPE_RUN_ID as m,ENV_COMPANION_TUNNEL_REGISTER_PATH as p,ENV_COMPANION_TUNNEL_LOCAL_BASE_URL as y,REACT_DEVTOOLS_COMPANION_RUN_ARG as g,ENV_COMPANION_TUNNEL_BEARER_TOKEN as w}from"../2301.js";class h extends Error{retryable;retryAfterMs;constructor(e,r,t){super(e),this.retryable=r,this.retryAfterMs=t}}function b(e,r){return{authorization:`Bearer ${r}`,"content-type":"application/json",...e.includes("ngrok")?{"ngrok-skip-browser-warning":"1"}:{}}}function S(e){return{...e.bridgeScope,...e.session?{session:e.session}:{},local_base_url:t(e.localBaseUrl),...e.devicePort?{device_port:e.devicePort}:{},...e.launchUrl?{launch_url:e.launchUrl}:{}}}async function v(e){let r,n,s=e.registerPath;try{r=await fetch(`${t(e.serverBaseUrl)}${s}`,{method:"POST",headers:b(e.serverBaseUrl,e.bearerToken),body:JSON.stringify(S(e)),signal:AbortSignal.timeout(5e3)})}catch(r){if(r instanceof Error&&"TimeoutError"===r.name)throw Error(`${s} timed out after 5000ms calling ${t(e.serverBaseUrl)}${s}`);throw r}let a=await r.text();try{n=a?JSON.parse(a):{}}catch{let e;throw new h(`Failed to register companion (${r.status}): invalid JSON response: ${(e=a.replaceAll(/\s+/g," ").trim()).length>300?`${e.slice(0,300)}...`:e}`,E(r.status,void 0),I(r,{}))}if(!r.ok||!0!==n.ok||"string"!=typeof n.data?.ws_url)throw new h(`Failed to register companion (${r.status}): ${JSON.stringify(n)}`,E(r.status,n.error?.code),I(r,n));return{wsUrl:n.data.ws_url}}function E(e,r){return"RATE_LIMITED"===r||"UNAUTHORIZED"!==r&&"INVALID_ARGS"!==r&&"SESSION_NOT_FOUND"!==r&&(408===e||409===e||425===e||429===e||e>=500)}function I(e,r){let t=r.error?.details?.retryAfterMs;if("number"==typeof t&&Number.isFinite(t))return B(t);let n=e.headers.get("retry-after");if(!n)return;let s=Number(n);if(Number.isFinite(s))return B(1e3*s);let a=Date.parse(n);if(Number.isFinite(a))return B(a-Date.now())}function B(e){return Math.max(0,Math.min(6e4,Math.ceil(e)))}async function N(e){let r=e.unregisterPath??null;if(r)try{await fetch(`${t(e.serverBaseUrl)}${r}`,{method:"POST",headers:b(e.serverBaseUrl,e.bearerToken),body:JSON.stringify(S(e)),signal:AbortSignal.timeout(2e3)})}catch(e){console.error(e instanceof Error?e.message:String(e))}}async function k(e){return"string"==typeof e?Buffer.from(e,"utf8"):e instanceof ArrayBuffer?Buffer.from(e):ArrayBuffer.isView(e)?Buffer.from(e.buffer,e.byteOffset,e.byteLength):"u">typeof Blob&&e instanceof Blob?Buffer.from(await e.arrayBuffer()):Buffer.from(String(e),"utf8")}async function L(e){return JSON.parse((await k(e.data)).toString("utf8"))}function U(e,r){1===e.readyState&&e.send(JSON.stringify(r))}async function O(e,r){1!==e.readyState&&await new Promise((t,n)=>{let s=()=>{i(),t()},a=()=>{i(),n(Error(`${r} WebSocket failed before opening.`))},o=()=>{i(),n(Error(`${r} WebSocket closed before opening.`))},i=()=>{e.removeEventListener("open",s),e.removeEventListener("error",a),e.removeEventListener("close",o)};e.addEventListener("open",s,{once:!0}),e.addEventListener("error",a,{once:!0}),e.addEventListener("close",o,{once:!0})})}async function $(e){e.readyState>=WebSocket.CLOSING||await new Promise(r=>{let t=()=>{n(),r()},n=()=>{e.removeEventListener("close",t),e.removeEventListener("error",t)};e.addEventListener("close",t,{once:!0}),e.addEventListener("error",t,{once:!0}),e.readyState>=WebSocket.CLOSING&&t()})}function T(e,r,t){try{e.close(1e3===r||r>=3e3&&r<=4999?r:3001,t)}catch{}}function _(r){return!r.statePath||e.existsSync(r.statePath)}async function A(e,r,n){try{let s=await fetch(new URL(r.path,`${t(n.localBaseUrl)}/`),{method:r.method,headers:r.headers,...r.bodyBase64?{body:Buffer.from(r.bodyBase64,"base64")}:{}}),a=Buffer.from(await s.arrayBuffer());U(e,{type:"http-response",requestId:r.requestId,status:s.status,headers:Object.fromEntries(s.headers.entries()),...a.length>0?{bodyBase64:a.toString("base64")}:{}})}catch(t){U(e,{type:"http-error",requestId:r.requestId,message:t instanceof Error?t.message:String(t)})}}async function P(e,r,n,s){var a;let o,i=new WebSocket((a=n.localBaseUrl,(o=new URL(r.path,`${t(a)}/`)).protocol="https:"===o.protocol?"wss:":"ws:",o.toString()));i.binaryType="arraybuffer";let c=!1;i.addEventListener("message",t=>{(async()=>{if(!c)return;let n=await k(t.data);U(e,{type:"ws-frame",streamId:r.streamId,dataBase64:n.toString("base64"),binary:"string"!=typeof t.data})})().catch(e=>{console.error(e instanceof Error?e.message:String(e))})}),i.addEventListener("close",t=>{s.delete(r.streamId),c&&U(e,{type:"ws-close",streamId:r.streamId,code:t.code,reason:t.reason})}),i.addEventListener("error",()=>{c&&U(e,{type:"ws-close",streamId:r.streamId,code:1011,reason:"Upstream WebSocket error."})}),s.set(r.streamId,i);try{await O(i,"Upstream"),c=!0,U(e,{type:"ws-open-result",streamId:r.streamId,success:!0,headers:{}})}catch(t){s.delete(r.streamId),T(i,1011,"open failed"),U(e,{type:"ws-open-result",streamId:r.streamId,success:!1,error:t instanceof Error?t.message:String(t)})}}async function M(e,r,t,n){switch(r.type){case"ping":return void U(e,{type:"pong",timestamp:r.timestamp});case"http-request":return void await A(e,r,t);case"ws-open":return void await P(e,r,t,n);case"ws-frame":return void function(e,r){let t=r.get(e.streamId);if(!t||1!==t.readyState)return;let n=Buffer.from(e.dataBase64,"base64");t.send(e.binary?n:n.toString("utf8"))}(r,n);case"ws-close":return void function(e,r){let t=r.get(e.streamId);if(t){var n;r.delete(e.streamId),T(t,"number"==typeof(n=e.code)&&Number.isInteger(n)&&(1e3===n||n>=3e3&&n<=4999||n>=1001&&n<=1015&&1004!==n&&1005!==n&&1006!==n)?n:1011,e.reason??"bridge requested close")}}(r,n)}}async function C(e){let t=new Map,n=!1,s=null,a=!1,o=()=>{n||(n=!0,a&&N(e).finally(()=>process.exit(0)),s&&T(s,1e3,"companion stopping"),setTimeout(()=>process.exit(0),900).unref())};process.once("SIGTERM",o),process.once("SIGINT",o);let i=setInterval(()=>{_(e)||process.exit(0)},250);i.unref();let c=1e3;for(;!n&&_(e);){let o,i=!1;try{a=!1;let r=await v(e);if(c=1e3,i=!0,a=!0,n||!_(e)){await N(e),i=!1,a=!1;break}let o=new WebSocket(r.wsUrl);s=o,o.binaryType="arraybuffer";try{await O(o,"Bridge"),o.addEventListener("message",r=>{(async()=>{let n=await L(r);await M(o,n,e,t)})().catch(e=>{console.error(e instanceof Error?e.message:String(e))})}),await $(o)}finally{s=null,a=!1,t.forEach(e=>T(e,1012,"bridge disconnected")),t.clear(),i&&(await N(e),i=!1)}}catch(r){if(s=null,a=!1,i&&(await N(e),i=!1),n||!_(e)||(console.error(r instanceof Error?r.message:String(r)),r instanceof h&&!r.retryable))break;o=r instanceof h?r.retryAfterMs:void 0}if(n||!_(e))break;let f=o??c;void 0===o&&(c=Math.min(2*c,6e4)),await r(f)}clearInterval(i)}(async function(e,r){let t=function(e,r){let t=e[0];if(t!==u&&t!==g)return null;let h=r[a]?.trim(),b=r[w]?.trim(),S=r[y]?.trim();if(!h||!b||!S)throw new s("Companion tunnel worker is missing required environment configuration.");let v=r[f]?.trim(),E=r[m]?.trim(),I=r[c]?.trim();if(!v||!E||!I)throw new s("Companion tunnel worker is missing required bridge scope configuration.");let B=r[p]?.trim();if(!B)throw new s("Companion tunnel worker is missing required register path configuration.");return{serverBaseUrl:h,bearerToken:b,localBaseUrl:S,registerPath:B,bridgeScope:{tenantId:v,runId:E,leaseId:I},launchUrl:r[i]?.trim(),statePath:r[o]?.trim(),unregisterPath:r[n]?.trim(),devicePort:function(e){if(!e?.trim())return;let r=Number.parseInt(e,10);if(!Number.isInteger(r)||r<1||r>65535)throw Error("Companion worker received invalid device port configuration.");return r}(r[l]?.trim()),session:r[d]?.trim()}}(e,r);return!!t&&(await C(t),!0)})(process.argv.slice(2),process.env).catch(e=>{if(e instanceof s){console.error(e.message),process.exitCode=1;return}console.error(e instanceof Error?e.stack??e.message:String(e)),process.exitCode=1});
1
+ import e from"node:fs";import{setTimeout as r}from"node:timers/promises";import{normalizeBaseUrl as t,ENV_COMPANION_TUNNEL_UNREGISTER_PATH as n,MissingCompanionEnvError as s,ENV_COMPANION_TUNNEL_SERVER_BASE_URL as a,ENV_COMPANION_TUNNEL_STATE_PATH as o,ENV_COMPANION_TUNNEL_LAUNCH_URL as i,ENV_COMPANION_TUNNEL_SCOPE_LEASE_ID as c,ENV_COMPANION_TUNNEL_SCOPE_TENANT_ID as l,ENV_COMPANION_TUNNEL_DEVICE_PORT as f,METRO_COMPANION_RUN_ARG as u,ENV_COMPANION_TUNNEL_SESSION as d,ENV_COMPANION_TUNNEL_SCOPE_RUN_ID as m,ENV_COMPANION_TUNNEL_REGISTER_PATH as y,ENV_COMPANION_TUNNEL_LOCAL_BASE_URL as p,REACT_DEVTOOLS_COMPANION_RUN_ARG as g,ENV_COMPANION_TUNNEL_BEARER_TOKEN as w}from"../2301.js";class h extends Error{retryable;retryAfterMs;constructor(e,r,t){super(e),this.retryable=r,this.retryAfterMs=t}}function b(e,r){return{authorization:`Bearer ${r}`,"content-type":"application/json",...e.includes("ngrok")?{"ngrok-skip-browser-warning":"1"}:{}}}function S(e){return{...e.bridgeScope,...e.session?{session:e.session}:{},local_base_url:t(e.localBaseUrl),...e.devicePort?{device_port:e.devicePort}:{},...e.launchUrl?{launch_url:e.launchUrl}:{}}}async function v(e){let r,n,s=e.registerPath;try{r=await fetch(`${t(e.serverBaseUrl)}${s}`,{method:"POST",headers:b(e.serverBaseUrl,e.bearerToken),body:JSON.stringify(S(e)),signal:AbortSignal.timeout(5e3)})}catch(r){if(r instanceof Error&&"TimeoutError"===r.name)throw Error(`${s} timed out after 5000ms calling ${t(e.serverBaseUrl)}${s}`);throw r}let a=await r.text();try{n=a?JSON.parse(a):{}}catch{let e;throw new h(`Failed to register companion (${r.status}): invalid JSON response: ${(e=a.replaceAll(/\s+/g," ").trim()).length>300?`${e.slice(0,300)}...`:e}`,I(r.status,void 0),E(r,{}))}if(!r.ok||!0!==n.ok||"string"!=typeof n.data?.ws_url)throw new h(`Failed to register companion (${r.status}): ${JSON.stringify(n)}`,I(r.status,n.error?.code),E(r,n));return{wsUrl:n.data.ws_url}}function I(e,r){return"RATE_LIMITED"===r||"UNAUTHORIZED"!==r&&"INVALID_ARGS"!==r&&"SESSION_NOT_FOUND"!==r&&(408===e||409===e||425===e||429===e||e>=500)}function E(e,r){let t=r.error?.details?.retryAfterMs;if("number"==typeof t&&Number.isFinite(t))return B(t);let n=e.headers.get("retry-after");if(!n)return;let s=Number(n);if(Number.isFinite(s))return B(1e3*s);let a=Date.parse(n);if(Number.isFinite(a))return B(a-Date.now())}function B(e){return Math.max(0,Math.min(6e4,Math.ceil(e)))}async function N(e){let r=e.unregisterPath??null;if(r)try{await fetch(`${t(e.serverBaseUrl)}${r}`,{method:"POST",headers:b(e.serverBaseUrl,e.bearerToken),body:JSON.stringify(S(e)),signal:AbortSignal.timeout(2e3)})}catch(e){console.error(e instanceof Error?e.message:String(e))}}async function k(e){return"string"==typeof e?Buffer.from(e,"utf8"):e instanceof ArrayBuffer?Buffer.from(e):ArrayBuffer.isView(e)?Buffer.from(e.buffer,e.byteOffset,e.byteLength):"u">typeof Blob&&e instanceof Blob?Buffer.from(await e.arrayBuffer()):Buffer.from(String(e),"utf8")}async function L(e){return JSON.parse((await k(e.data)).toString("utf8"))}function U(e,r){1===e.readyState&&e.send(JSON.stringify(r))}async function P(e,r){1!==e.readyState&&await new Promise((t,n)=>{let s=()=>{i(),t()},a=()=>{i(),n(Error(`${r} WebSocket failed before opening.`))},o=()=>{i(),n(Error(`${r} WebSocket closed before opening.`))},i=()=>{e.removeEventListener("open",s),e.removeEventListener("error",a),e.removeEventListener("close",o)};e.addEventListener("open",s,{once:!0}),e.addEventListener("error",a,{once:!0}),e.addEventListener("close",o,{once:!0})})}async function O(e){e.readyState>=WebSocket.CLOSING||await new Promise(r=>{let t=()=>{n(),r()},n=()=>{e.removeEventListener("close",t),e.removeEventListener("error",t)};e.addEventListener("close",t,{once:!0}),e.addEventListener("error",t,{once:!0}),e.readyState>=WebSocket.CLOSING&&t()})}function T(e,r,t){try{e.close(1e3===r||r>=3e3&&r<=4999?r:3001,t)}catch{}}function $(r){return!r.statePath||e.existsSync(r.statePath)}async function M(e,r,n){try{let s=await fetch(new URL(r.path,`${t(n.localBaseUrl)}/`),{method:r.method,headers:r.headers,...r.bodyBase64?{body:Buffer.from(r.bodyBase64,"base64")}:{}}),a=Buffer.from(await s.arrayBuffer());U(e,{type:"http-response",requestId:r.requestId,status:s.status,headers:Object.fromEntries(s.headers.entries()),...a.length>0?{bodyBase64:a.toString("base64")}:{}})}catch(t){U(e,{type:"http-error",requestId:r.requestId,message:t instanceof Error?t.message:String(t)})}}async function _(e,r,n,s){var a;let o,i=new WebSocket((a=n.localBaseUrl,(o=new URL(r.path,`${t(a)}/`)).protocol="https:"===o.protocol?"wss:":"ws:",o.toString()));i.binaryType="arraybuffer";let c=!1;i.addEventListener("message",t=>{(async()=>{if(!c)return;let n=await k(t.data);U(e,{type:"ws-frame",streamId:r.streamId,dataBase64:n.toString("base64"),binary:"string"!=typeof t.data})})().catch(e=>{console.error(e instanceof Error?e.message:String(e))})}),i.addEventListener("close",t=>{s.delete(r.streamId),c&&U(e,{type:"ws-close",streamId:r.streamId,code:t.code,reason:t.reason})}),i.addEventListener("error",()=>{c&&U(e,{type:"ws-close",streamId:r.streamId,code:1011,reason:"Upstream WebSocket error."})}),s.set(r.streamId,i);try{await P(i,"Upstream"),c=!0,U(e,{type:"ws-open-result",streamId:r.streamId,success:!0,headers:{}})}catch(t){s.delete(r.streamId),T(i,1011,"open failed"),U(e,{type:"ws-open-result",streamId:r.streamId,success:!1,error:t instanceof Error?t.message:String(t)})}}async function A(e,r,t,n){switch(r.type){case"ping":return void U(e,{type:"pong",timestamp:r.timestamp});case"http-request":return void await M(e,r,t);case"ws-open":return void await _(e,r,t,n);case"ws-frame":return void function(e,r){let t=r.get(e.streamId);if(!t||1!==t.readyState)return;let n=Buffer.from(e.dataBase64,"base64");t.send(e.binary?n:n.toString("utf8"))}(r,n);case"ws-close":return void function(e,r){let t=r.get(e.streamId);if(t){var n;r.delete(e.streamId),T(t,"number"==typeof(n=e.code)&&Number.isInteger(n)&&(1e3===n||n>=3e3&&n<=4999||n>=1001&&n<=1015&&1004!==n&&1005!==n&&1006!==n)?n:1011,e.reason??"bridge requested close")}}(r,n)}}async function C(e,t={}){let n,s=new Map,a=!1,o=null,i=!1,c=null,l=t.delay??r,f=new Promise(e=>{n=e}),u=()=>{t.exit?.(0)},d=async()=>{(i||c)&&(c??=N(e).finally(()=>{i=!1,c=null}),await c)},m=()=>{!a&&(a=!0,n(),i&&d().finally(u),o&&T(o,1e3,"companion stopping"),t.exit&&setTimeout(u,900).unref())};t.registerProcessSignals&&(process.once("SIGTERM",m),process.once("SIGINT",m));let y=setInterval(()=>{$(e)||(m(),u())},t.leaseCheckIntervalMs??250);y.unref();let p=t.reconnectDelayMs??1e3;try{for(;!a&&$(e);){var g;let r,n=!1;try{i=!1;let r=await v(e);if(p=t.reconnectDelayMs??1e3,n=!0,i=!0,a||!$(e)){await d(),n=!1;break}let c=new WebSocket(r.wsUrl);o=c,c.binaryType="arraybuffer";try{await P(c,"Bridge"),c.addEventListener("message",r=>{(async()=>{let t=await L(r);await A(c,t,e,s)})().catch(e=>{console.error(e instanceof Error?e.message:String(e))})}),await Promise.race([O(c),f])}finally{o=null,s.forEach(e=>T(e,1012,"bridge disconnected")),s.clear(),n&&(await d(),n=!1)}}catch(t){if(o=null,n&&(await d(),n=!1),a||!$(e)||(console.error(t instanceof Error?t.message:String(t)),t instanceof h&&!t.retryable))break;r=t instanceof h?t.retryAfterMs:void 0}if(a||!$(e))break;let c=r??p;void 0===r&&(g=p,p=Math.min(2*g,6e4)),await l(c)}}finally{clearInterval(y),t.registerProcessSignals&&(process.off("SIGTERM",m),process.off("SIGINT",m))}}(async function(e,r){let t=function(e,r){let t=e[0];if(t!==u&&t!==g)return null;let h=r[a]?.trim(),b=r[w]?.trim(),S=r[p]?.trim();if(!h||!b||!S)throw new s("Companion tunnel worker is missing required environment configuration.");let v=r[l]?.trim(),I=r[m]?.trim(),E=r[c]?.trim();if(!v||!I||!E)throw new s("Companion tunnel worker is missing required bridge scope configuration.");let B=r[y]?.trim();if(!B)throw new s("Companion tunnel worker is missing required register path configuration.");return{serverBaseUrl:h,bearerToken:b,localBaseUrl:S,registerPath:B,bridgeScope:{tenantId:v,runId:I,leaseId:E},launchUrl:r[i]?.trim(),statePath:r[o]?.trim(),unregisterPath:r[n]?.trim(),devicePort:function(e){if(!e?.trim())return;let r=Number.parseInt(e,10);if(!Number.isInteger(r)||r<1||r>65535)throw Error("Companion worker received invalid device port configuration.");return r}(r[f]?.trim()),session:r[d]?.trim()}}(e,r);return!!t&&(await C(t,{exit:e=>process.exit(e),registerProcessSignals:!0}),!0)})(process.argv.slice(2),process.env).catch(e=>{if(e instanceof s){console.error(e.message),process.exitCode=1;return}console.error(e instanceof Error?e.stack??e.message:String(e)),process.exitCode=1});