agent-device 0.21.26 → 0.21.27

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 (26) hide show
  1. package/android/ime-helper/dist/{agent-device-android-ime-helper-0.21.26.apk → agent-device-android-ime-helper-0.21.27.apk} +0 -0
  2. package/android/ime-helper/dist/agent-device-android-ime-helper-0.21.27.apk.sha256 +1 -0
  3. package/android/ime-helper/dist/{agent-device-android-ime-helper-0.21.26.manifest.json → agent-device-android-ime-helper-0.21.27.manifest.json} +4 -4
  4. package/android/snapshot-helper/dist/{agent-device-android-snapshot-helper-0.21.26.apk → agent-device-android-snapshot-helper-0.21.27.apk} +0 -0
  5. package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.27.apk.sha256 +1 -0
  6. package/android/snapshot-helper/dist/{agent-device-android-snapshot-helper-0.21.26.manifest.json → agent-device-android-snapshot-helper-0.21.27.manifest.json} +7 -7
  7. package/dist/apple/runner/AgentDeviceRunner/RecordingScripts/recording-overlay.swift +11 -4
  8. package/dist/src/app-log-reconnect.js +1 -1
  9. package/dist/src/app-log-runtime2.js +3 -3
  10. package/dist/src/cli-help.js +1 -1
  11. package/dist/src/client-types.d.ts +3 -3
  12. package/dist/src/command-metadata.js +4 -4
  13. package/dist/src/connection.js +5 -5
  14. package/dist/src/internal/bin.js +1 -1
  15. package/dist/src/internal/daemon.js +4 -4
  16. package/dist/src/ios-snapshot-adapter.js +1 -1
  17. package/dist/src/limrun.js +1 -1
  18. package/dist/src/proxy.js +2 -2
  19. package/dist/src/session-allocation.js +1 -1
  20. package/dist/src/session2.js +5 -5
  21. package/dist/src/src.js +1 -1
  22. package/dist/src/text-entry-focus.js +1 -1
  23. package/package.json +4 -1
  24. package/server.json +2 -2
  25. package/android/ime-helper/dist/agent-device-android-ime-helper-0.21.26.apk.sha256 +0 -1
  26. package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.26.apk.sha256 +0 -1
@@ -1 +1 @@
1
- import{s as e}from"./src.js";import{r as t,t as n}from"./ios-snapshot-acquisition.js";async function r(t){let r=await t.client.elementTree(),a=i(r,t.client.deviceInfo);return n({producer:`limrun-ios-tree`,nodes:e(r),viewport:a,lineage:{targetId:t.instanceId}})}function i(e,n){let r=t((Array.isArray(e)?e:[e]).map(a));return r?.kind===`reported`?{kind:`derived`,rect:r.rect}:u(n)}function a(e){let t=e.rect??e.frame,n=o(t);return{type:e.elementType??e.type??e.role,...n?{rect:n}:{},rectStatus:l(t,n)}}function o(e){if(s(e))return{x:e.x,y:e.y,width:e.width,height:e.height}}function s(e){return[e?.x,e?.y,e?.width,e?.height].every(c)}function c(e){return typeof e==`number`&&Number.isFinite(e)}const l=(e,t)=>!e||!t?`not-provided`:t.width>0&&t.height>0?`reported`:`invalid`;function u(e){let t=e?.screenWidth,n=e?.screenHeight;return t===void 0||n===void 0?{kind:`missing`,reason:`not-provided`}:!d(t)||!d(n)?{kind:`missing`,reason:`invalid`}:{kind:`reported`,rect:{x:0,y:0,width:t,height:n}}}function d(e){return Number.isFinite(e)&&e>0}export{r as captureLimrunIosSnapshot};
1
+ import{c as e}from"./src.js";import{r as t,t as n}from"./ios-snapshot-acquisition.js";async function r(t){let r=await t.client.elementTree(),a=i(r,t.client.deviceInfo);return n({producer:`limrun-ios-tree`,nodes:e(r),viewport:a,lineage:{targetId:t.instanceId}})}function i(e,n){let r=t((Array.isArray(e)?e:[e]).map(a));return r?.kind===`reported`?{kind:`derived`,rect:r.rect}:u(n)}function a(e){let t=e.rect??e.frame,n=o(t);return{type:e.elementType??e.type??e.role,...n?{rect:n}:{},rectStatus:l(t,n)}}function o(e){if(s(e))return{x:e.x,y:e.y,width:e.width,height:e.height}}function s(e){return[e?.x,e?.y,e?.width,e?.height].every(c)}function c(e){return typeof e==`number`&&Number.isFinite(e)}const l=(e,t)=>!e||!t?`not-provided`:t.width>0&&t.height>0?`reported`:`invalid`;function u(e){let t=e?.screenWidth,n=e?.screenHeight;return t===void 0||n===void 0?{kind:`missing`,reason:`not-provided`}:!d(t)||!d(n)?{kind:`missing`,reason:`invalid`}:{kind:`reported`,rect:{x:0,y:0,width:t,height:n}}}function d(e){return Number.isFinite(e)&&e>0}export{r as captureLimrunIosSnapshot};
@@ -1 +1 @@
1
- import{m as e,r as t}from"./src.js";import{t as n}from"./limrun-runtime-dependencies.js";var r=class{implementation;provider=e;constructor(e){this.implementation=t(e,n())}get leaseLifecycle(){return this.implementation.leaseLifecycle}get recoverExpiredLease(){return this.implementation.recoverExpiredLease}get deviceInventoryProvider(){return this.implementation.deviceInventoryProvider}ownsDevice(e){return this.implementation.ownsDevice(e)}getInteractor(e){return this.implementation.getInteractor(e)}getDeviceSession(e){return this.implementation.getDeviceSession(e)}async installApp(e,t,n,r){return await this.implementation.installApp?.(e,t,n,r)}async installInstallablePath(e,t,n){return await this.implementation.installInstallablePath?.(e,t,n)}async configurePortReverse(e){return await this.implementation.configurePortReverse?.(e)}async shutdown(){await this.implementation.shutdown()}};export{r as LimrunRuntime};
1
+ import{h as e,r as t}from"./src.js";import{t as n}from"./limrun-runtime-dependencies.js";var r=class{implementation;provider=e;constructor(e){this.implementation=t(e,n())}get leaseLifecycle(){return this.implementation.leaseLifecycle}get recoverExpiredLease(){return this.implementation.recoverExpiredLease}get deviceInventoryProvider(){return this.implementation.deviceInventoryProvider}ownsDevice(e){return this.implementation.ownsDevice(e)}getInteractor(e){return this.implementation.getInteractor(e)}getDeviceSession(e){return this.implementation.getDeviceSession(e)}async installApp(e,t,n,r){return await this.implementation.installApp?.(e,t,n,r)}async installInstallablePath(e,t,n){return await this.implementation.installInstallablePath?.(e,t,n)}async configurePortReverse(e){return await this.implementation.configurePortReverse?.(e)}async shutdown(){await this.implementation.shutdown()}};export{r as LimrunRuntime};
package/dist/src/proxy.js CHANGED
@@ -1,2 +1,2 @@
1
- import{P as e,Y as t}from"./sdk-contracts.js";import{A as n,D as r,E as i,I as a,L as o,M as s,N as c,O as l,P as u,T as d,j as f,k as p,w as m}from"./daemon-resolution.js";import{t as h}from"./shared.js";import{ensureDaemon as g,resolveClientSettings as ee}from"./daemon-client-lifecycle.js";import{n as te,t as ne}from"./color.js";import{randomBytes as _,randomUUID as v}from"node:crypto";import y from"node:http";function b(e){let t=S(e);if(!t)return!1;let n=T(t.meta);return C(n)?!1:w(t.source)||w(n?.installSource)}function x(n){let r=new e(`INVALID_ARGS`,`Invalid params: an install source of kind "path" names a file on the daemon host and is not accepted through the proxy`,{hint:`Upload the artifact, or use a "url" or "github-actions-artifact" source.`});return Response.json({jsonrpc:`2.0`,id:n,error:{code:-32602,message:r.message,data:t(r)}},{status:400})}function S(e){if(e)try{return T(T(JSON.parse(e))?.params)}catch{return}}function C(e){let t=e?.uploadedArtifactId;return typeof t==`string`&&t.trim().length>0}function w(e){return T(e)?.kind===`path`}function T(e){return e&&typeof e==`object`&&!Array.isArray(e)?e:void 0}const E=`${d}/`,D=[`content-type`,`content-range`,`x-artifact-type`,`x-artifact-filename`,`x-artifact-hash`,`x-artifact-hash-algorithm`,n],O=[`content-type`,`content-disposition`,`x-request-id`,r];function k(e){let t=V(e),n=v();return{instanceId:n,handle:async e=>{try{return await M(e,t,n)}catch(e){return me(e)}}}}function A(e){return y.createServer(j(k(e)))}function j(e){return(t,n)=>{import(`./node-http.js`).then(({serveProxyRequest:r})=>r(e,t,n)).catch(e=>{n.destroyed||n.destroy(e instanceof Error?e:void 0)})}}async function M(e,t,n){let r=W(e.url);if(e.method===`GET`&&r===`/health`)return await N(e,t,n);if(!re(r,e.method))return new Response(new TextEncoder().encode(`Not found`),{status:404});let i;return r===`/rpc`&&(i=await ae(e,t.maxRpcBodyBytes,`Proxy request body is too large.`)),oe(e,t.clientToken,i)?de(e,r,Z(i),n)||(b(i)?x(Z(i)):await F({request:e,route:r,options:t,rpcBody:i})):pe(r,Z(i))}async function N(e,t,n){let[r,{readVersion:i},{readHostCpuArch:a}]=await Promise.all([P(e,t),import(`./version.js`).then(e=>e.t),import(`./process.js`).then(e=>e.t)]);return Response.json(s(`agent-device-proxy`,i(),{upstream:r,instanceId:n,hostArch:await a()}))}async function P(e,t){let n=await t.upstreamFetch(new Request(a(t.upstreamBaseUrl,`health`),{method:`GET`,headers:X(new Headers,t.upstreamToken,`/health`),signal:I(e,t)})),r=await n.text();try{return r?JSON.parse(r):{ok:n.ok,status:n.status}}catch{return{ok:n.ok,status:n.status}}}async function F(e){let{request:t,route:n,options:r,rpcBody:i}=e,a=ie(t,n,i,r.upstreamToken),o=await r.upstreamFetch(new Request(J(r.upstreamBaseUrl,n,t.url),{method:t.method,headers:X(t.headers,r.upstreamToken,n),signal:I(t,r),...a?{body:a,duplex:`half`}:{}})),s=L(o,t);return q(n)?await R({request:t,upstreamResponse:o,headers:s,clientToken:r.clientToken}):new Response(o.body,{status:o.status,headers:s})}function I(e,t){return AbortSignal.any([e.signal,AbortSignal.timeout(t.upstreamTimeoutMs)])}function L(e,t){let n=new Headers;for(let t of O){let r=e.headers.get(t);r&&n.set(t,r)}return n.has(`x-request-id`)||n.set(`x-request-id`,ue(t)),n}async function R(e){let{request:t,upstreamResponse:n,headers:r,clientToken:i}=e,a=await n.text();return r.set(`content-type`,n.headers.get(`content-type`)??`application/json`),new Response(z(a,t,i),{status:n.status,headers:r})}function z(e,t,n){let r;try{r=JSON.parse(e)}catch{return e}if(!r||typeof r!=`object`)return e;let i=r;if(!i.upload||typeof i.upload.url!=`string`)return e;let a=B(i.upload.url,t);if(!a)return e;let o=i.upload.headers&&typeof i.upload.headers==`object`?{...i.upload.headers}:{};return Object.assign(o,c(n)),JSON.stringify({...r,upload:{...i.upload,url:a,headers:o}})}function B(e,t){let n;try{n=new URL(e)}catch{return null}if(!n.pathname.startsWith(`/upload/`))return null;let r=new URL(t.url),i=r.pathname.lastIndexOf(`/upload/preflight`),a=i>=0?r.pathname.slice(0,i):``,o=t.headers.get(`x-forwarded-proto`)?.split(`,`)[0]?.trim(),s=new URL(`${o||r.protocol.replace(/:$/,``)}://${r.host}`);return s.pathname=`${a}${n.pathname}`,s.search=n.search,s.toString()}function V(e){return{upstreamBaseUrl:H(e.upstreamBaseUrl,`upstreamBaseUrl`),upstreamToken:U(e.upstreamToken,`upstreamToken`),clientToken:U(e.clientToken,`clientToken`),maxRpcBodyBytes:e.maxRpcBodyBytes??1048576,upstreamTimeoutMs:e.upstreamTimeoutMs??3e5,upstreamFetch:e.upstreamFetch??(e=>fetch(e))}}function H(t,n){try{let e=new URL(t);if(e.protocol!==`http:`&&e.protocol!==`https:`)throw Error(`unsupported protocol`);return e.toString().replace(/\/+$/,``)}catch(r){throw new e(`INVALID_ARGS`,`Invalid ${n}`,{[n]:t},r)}}function U(t,n){let r=t.trim();if(!r)throw new e(`INVALID_ARGS`,`Proxy ${n} is required.`);return r}function W(e){let t=new URL(e).pathname;return t===`/agent-device`?`/`:t.startsWith(E)?`/${t.slice(E.length)}`:t}function re(e,t){return e===`/rpc`?t===`POST`:K(e,t)?!0:e===`/artifacts`||e===`/artifacts/`||e.startsWith(`/artifacts/`)||G(e)?t===`GET`:!1}function G(e){let t=e.split(`/`);return t.length===6&&t[1]===`sessions`&&t[3]===`requests`&&t[5]===`diagnostics`&&t[2]!==``&&t[4]!==``}function K(e,t){return e===`/upload`||q(e)||e===`/upload/finalize`?t===`POST`:e.startsWith(`/upload/direct/`)?t===`PUT`:!1}function q(e){return e===`/upload/preflight`}function J(e,t,n){let r=new URL(a(e,t));return r.search=new URL(n).search,r}function Y(e){let t=e.get(f);return t===null?{}:{[i]:t}}function X(e,t,n){let r=new Headers;for(let t of D){let n=e.get(t);n?.trim()&&r.set(t,n)}if(n===`/rpc`&&!r.has(`content-type`)&&r.set(`content-type`,`application/json`),n===`/rpc`){r.set(l,p);for(let[t,n]of Object.entries(Y(e)))r.set(t,n)}for(let[e,n]of Object.entries(c(t)))r.set(e,n);return r}function ie(e,t,n,r){return e.method===`GET`||e.method===`HEAD`?null:t===`/rpc`?ce(n??``,r):e.body}async function ae(t,n,r){if(!t.body)return``;let i=t.body.getReader(),a=[],o=0;for(;;){let{done:t,value:s}=await i.read();if(t)break;if(o+=s.byteLength,o>n)throw await i.cancel(),new e(`INVALID_ARGS`,r);a.push(s)}return Buffer.concat(a).toString(`utf8`)}function oe(e,t,n){let r=se(e,n);return r.length>0&&m(r,t)}function se(e,t){let n=e.headers.get(`authorization`)??``;if(n.toLowerCase().startsWith(`bearer `))return n.slice(7);let r=e.headers.get(`x-agent-device-token`);if(r!==null)return r;if(t){let e=le(t);if(e)return e}return``}function ce(e,t){let n=JSON.parse(e);return n.params={...n.params??{},token:t},JSON.stringify(n)}function le(e){try{let t=JSON.parse(e);return typeof t.params?.token==`string`?t.params.token:``}catch{return``}}function Z(e){if(!e)return null;try{return JSON.parse(e).id??null}catch{return null}}function ue(e){let t=e.headers.get(`x-request-id`);return t?.trim()?t.trim().slice(0,128):v()}function de(e,t,n,r){if(t!==`/rpc`)return null;let a=e.headers.get(i);return a===null||a===r?null:fe(n)}function fe(n){return Response.json(o(n,`Proxy instance changed`,t(new e(`COMMAND_FAILED`,`Proxy instance changed`,{reason:`remote_instance_mismatch`}))),{status:409,headers:{[r]:`true`}})}function pe(n,r){return n===`/rpc`?Response.json({jsonrpc:`2.0`,id:r,error:{code:-32001,message:`Invalid proxy token`,data:t(new e(`UNAUTHORIZED`,`Invalid proxy token`))}},{status:401}):Response.json({ok:!1,error:`Invalid proxy token`,code:`UNAUTHORIZED`},{status:401})}function me(e){let n=t(e);return Response.json({ok:!1,error:n.message,code:n.code},{status:n.code===`INVALID_ARGS`?400:500})}const Q=async({positionals:t,flags:n})=>{if(t.length>0)throw new e(`INVALID_ARGS`,`proxy does not accept positional arguments.`);let r=await he(n);return await h(n,r,()=>be(r)),await xe(),!0};async function he(t){let n=ee({session:`default`,command:`proxy`,positionals:[],flags:{stateDir:t.stateDir,daemonBaseUrl:``,daemonTransport:`http`,daemonServerMode:`http`}}),r=await g(n),i=ge(r.info.httpPort),a=_e(t),o=A({upstreamBaseUrl:i,upstreamToken:r.info.token,clientToken:a});await ve(o,t.proxyHost?.trim()||`127.0.0.1`,t.proxyPort??0);let s=o.address();if(!s||typeof s==`string`)throw new e(`COMMAND_FAILED`,`Proxy did not bind to a TCP address.`);let c=`http://${ye(s.address)}:${s.port}`;return{proxyBaseUrl:c,agentDeviceBaseUrl:u(c),token:a,upstreamBaseUrl:i,stateDir:n.paths.baseDir}}function ge(t){if(!t)throw new e(`COMMAND_FAILED`,`Local daemon HTTP endpoint is unavailable.`,{hint:`Retry after cleaning daemon state, or run proxy with a fresh --state-dir.`});return`http://127.0.0.1:${t}`}function _e(e){return e.daemonAuthToken?.trim()||_(32).toString(`hex`)}function ve(e,t,n){return new Promise((r,i)=>{e.once(`error`,i),e.listen(n,t,()=>{e.off(`error`,i),r()})})}function ye(e){return e.includes(`:`)&&!e.startsWith(`[`)?`[${e}]`:e}function be(e,t={}){let n=t.useColor??te(),r=$(`✓`,`green`,n),i=$(e.proxyBaseUrl,`cyan`,n),a=$(`<tunnel URL>`,`cyan`,n),o=$(e.token,`yellow`,n);return[`${r} Proxy listening at ${i}`,``,`Provide this to the agent-device instance connecting:`,``,`Daemon base URL: ${a}`,`Daemon auth token: ${o}`].join(`
2
- `)}function $(e,t,n){return n?ne(e,t,{validateStream:!1}):e}function xe(){return new Promise(()=>{})}export{Q as proxyCommand};
1
+ import{P as e,Y as t}from"./sdk-contracts.js";import{A as n,D as r,E as i,I as a,L as o,M as s,N as c,O as l,P as u,T as d,j as f,k as p,w as m}from"./daemon-resolution.js";import{t as h}from"./shared.js";import{ensureDaemon as ee,resolveClientSettings as te}from"./daemon-client-lifecycle.js";import{n as ne,t as re}from"./color.js";import{randomBytes as g,randomUUID as _}from"node:crypto";import v from"node:http";function y(e){let t=x(e);if(!t)return!1;let n=w(t.meta);return S(n)?!1:C(t.source)||C(n?.installSource)}function b(n){let r=new e(`INVALID_ARGS`,`Invalid params: an install source of kind "path" names a file on the daemon host and is not accepted through the proxy`,{hint:`Upload the artifact, or use a "url" or "github-actions-artifact" source.`});return Response.json({jsonrpc:`2.0`,id:n,error:{code:-32602,message:r.message,data:t(r)}},{status:400})}function x(e){if(e)try{return w(w(JSON.parse(e))?.params)}catch{return}}function S(e){let t=e?.uploadedArtifactId;return typeof t==`string`&&t.trim().length>0}function C(e){return w(e)?.kind===`path`}function w(e){return e&&typeof e==`object`&&!Array.isArray(e)?e:void 0}const T=`${d}/`,E=[`content-type`,`content-range`,`x-artifact-type`,`x-artifact-filename`,`x-artifact-hash`,`x-artifact-hash-algorithm`,n],D=[`content-type`,`content-disposition`,`x-request-id`,r],O=[`range`,`x-upload-offset`],k=[`content-length`];function A(e){let t=U(e),n=_();return{instanceId:n,handle:async e=>{try{return await N(e,t,n)}catch(e){return ge(e)}}}}function j(e){return v.createServer(M(A(e)))}function M(e){return(t,n)=>{import(`./node-http.js`).then(({serveProxyRequest:r})=>r(e,t,n)).catch(e=>{n.destroyed||n.destroy(e instanceof Error?e:void 0)})}}async function N(e,t,n){let r=G(e.url);if(e.method===`GET`&&r===`/health`)return await P(e,t,n);if(!K(r,e.method))return new Response(new TextEncoder().encode(`Not found`),{status:404});let i;return r===`/rpc`&&(i=await ce(e,t.maxRpcBodyBytes,`Proxy request body is too large.`)),le(e,t.clientToken,i)?me(e,r,Z(i),n)||(y(i)?b(Z(i)):await I({request:e,route:r,options:t,rpcBody:i})):he(r,Z(i))}async function P(e,t,n){let[r,{readVersion:i},{readHostCpuArch:a}]=await Promise.all([F(e,t),import(`./version.js`).then(e=>e.t),import(`./process.js`).then(e=>e.t)]);return Response.json(s(`agent-device-proxy`,i(),{upstream:r,instanceId:n,hostArch:await a()}))}async function F(e,t){let n=await t.upstreamFetch(new Request(a(t.upstreamBaseUrl,`health`),{method:`GET`,headers:X(new Headers,t.upstreamToken,`/health`),signal:L(e,t)})),r=await n.text();try{return r?JSON.parse(r):{ok:n.ok,status:n.status}}catch{return{ok:n.ok,status:n.status}}}async function I(e){let{request:t,route:n,options:r,rpcBody:i}=e,a=se(t,n,i,r.upstreamToken),o=await r.upstreamFetch(new Request(ae(r.upstreamBaseUrl,n,t.url),{method:t.method,headers:X(t.headers,r.upstreamToken,n),signal:L(t,r),...a?{body:a,duplex:`half`}:{}})),s=R(o,t,n);return Y(n)?await B({request:t,upstreamResponse:o,headers:s,clientToken:r.clientToken}):new Response(o.body,{status:o.status,headers:s})}function L(e,t){return AbortSignal.any([e.signal,AbortSignal.timeout(t.upstreamTimeoutMs)])}function R(e,t,n){let r=new Headers;for(let t of[...D,...z(n)]){let n=e.headers.get(t);n&&r.set(t,n)}return r.has(`x-request-id`)||r.set(`x-request-id`,pe(t)),r}function z(e){return e.startsWith(`/upload/direct/`)?O:e.startsWith(`/artifacts/`)?k:[]}async function B(e){let{request:t,upstreamResponse:n,headers:r,clientToken:i}=e,a=await n.text();return r.set(`content-type`,n.headers.get(`content-type`)??`application/json`),new Response(V(a,t,i),{status:n.status,headers:r})}function V(e,t,n){let r;try{r=JSON.parse(e)}catch{return e}if(!r||typeof r!=`object`)return e;let i=r;if(!i.upload||typeof i.upload.url!=`string`)return e;let a=H(i.upload.url,t);if(!a)return e;let o=i.upload.headers&&typeof i.upload.headers==`object`?{...i.upload.headers}:{};return Object.assign(o,c(n)),JSON.stringify({...r,upload:{...i.upload,url:a,headers:o}})}function H(e,t){let n;try{n=new URL(e)}catch{return null}if(!n.pathname.startsWith(`/upload/`))return null;let r=new URL(t.url),i=r.pathname.lastIndexOf(`/upload/preflight`),a=i>=0?r.pathname.slice(0,i):``,o=t.headers.get(`x-forwarded-proto`)?.split(`,`)[0]?.trim(),s=new URL(`${o||r.protocol.replace(/:$/,``)}://${r.host}`);return s.pathname=`${a}${n.pathname}`,s.search=n.search,s.toString()}function U(e){return{upstreamBaseUrl:ie(e.upstreamBaseUrl,`upstreamBaseUrl`),upstreamToken:W(e.upstreamToken,`upstreamToken`),clientToken:W(e.clientToken,`clientToken`),maxRpcBodyBytes:e.maxRpcBodyBytes??1048576,upstreamTimeoutMs:e.upstreamTimeoutMs??3e5,upstreamFetch:e.upstreamFetch??(e=>fetch(e))}}function ie(t,n){try{let e=new URL(t);if(e.protocol!==`http:`&&e.protocol!==`https:`)throw Error(`unsupported protocol`);return e.toString().replace(/\/+$/,``)}catch(r){throw new e(`INVALID_ARGS`,`Invalid ${n}`,{[n]:t},r)}}function W(t,n){let r=t.trim();if(!r)throw new e(`INVALID_ARGS`,`Proxy ${n} is required.`);return r}function G(e){let t=new URL(e).pathname;return t===`/agent-device`?`/`:t.startsWith(T)?`/${t.slice(T.length)}`:t}function K(e,t){return e===`/rpc`?t===`POST`:J(e,t)?!0:e===`/artifacts`||e===`/artifacts/`||e.startsWith(`/artifacts/`)||q(e)?t===`GET`:!1}function q(e){let t=e.split(`/`);return t.length===6&&t[1]===`sessions`&&t[3]===`requests`&&t[5]===`diagnostics`&&t[2]!==``&&t[4]!==``}function J(e,t){return e===`/upload`||Y(e)||e===`/upload/finalize`?t===`POST`:e.startsWith(`/upload/direct/`)?t===`PUT`:!1}function Y(e){return e===`/upload/preflight`}function ae(e,t,n){let r=new URL(a(e,t));return r.search=new URL(n).search,r}function oe(e){let t=e.get(f);return t===null?{}:{[i]:t}}function X(e,t,n){let r=new Headers;for(let t of E){let n=e.get(t);n?.trim()&&r.set(t,n)}if(n===`/rpc`&&!r.has(`content-type`)&&r.set(`content-type`,`application/json`),n===`/rpc`){r.set(l,p);for(let[t,n]of Object.entries(oe(e)))r.set(t,n)}for(let[e,n]of Object.entries(c(t)))r.set(e,n);return r}function se(e,t,n,r){return e.method===`GET`||e.method===`HEAD`?null:t===`/rpc`?de(n??``,r):e.body}async function ce(t,n,r){if(!t.body)return``;let i=t.body.getReader(),a=[],o=0;for(;;){let{done:t,value:s}=await i.read();if(t)break;if(o+=s.byteLength,o>n)throw await i.cancel(),new e(`INVALID_ARGS`,r);a.push(s)}return Buffer.concat(a).toString(`utf8`)}function le(e,t,n){let r=ue(e,n);return r.length>0&&m(r,t)}function ue(e,t){let n=e.headers.get(`authorization`)??``;if(n.toLowerCase().startsWith(`bearer `))return n.slice(7);let r=e.headers.get(`x-agent-device-token`);if(r!==null)return r;if(t){let e=fe(t);if(e)return e}return``}function de(e,t){let n=JSON.parse(e);return n.params={...n.params??{},token:t},JSON.stringify(n)}function fe(e){try{let t=JSON.parse(e);return typeof t.params?.token==`string`?t.params.token:``}catch{return``}}function Z(e){if(!e)return null;try{return JSON.parse(e).id??null}catch{return null}}function pe(e){let t=e.headers.get(`x-request-id`);return t?.trim()?t.trim().slice(0,128):_()}function me(e,t,n,r){if(t!==`/rpc`)return null;let a=e.headers.get(i);return a===null||a===r?null:Q(n)}function Q(n){return Response.json(o(n,`Proxy instance changed`,t(new e(`COMMAND_FAILED`,`Proxy instance changed`,{reason:`remote_instance_mismatch`}))),{status:409,headers:{[r]:`true`}})}function he(n,r){return n===`/rpc`?Response.json({jsonrpc:`2.0`,id:r,error:{code:-32001,message:`Invalid proxy token`,data:t(new e(`UNAUTHORIZED`,`Invalid proxy token`))}},{status:401}):Response.json({ok:!1,error:`Invalid proxy token`,code:`UNAUTHORIZED`},{status:401})}function ge(e){let n=t(e);return Response.json({ok:!1,error:n.message,code:n.code},{status:n.code===`INVALID_ARGS`?400:500})}const _e=async({positionals:t,flags:n})=>{if(t.length>0)throw new e(`INVALID_ARGS`,`proxy does not accept positional arguments.`);let r=await ve(n);return await h(n,r,()=>Ce(r)),await we(),!0};async function ve(t){let n=te({session:`default`,command:`proxy`,positionals:[],flags:{stateDir:t.stateDir,daemonBaseUrl:``,daemonTransport:`http`,daemonServerMode:`http`}}),r=await ee(n),i=ye(r.info.httpPort),a=be(t),o=j({upstreamBaseUrl:i,upstreamToken:r.info.token,clientToken:a});await xe(o,t.proxyHost?.trim()||`127.0.0.1`,t.proxyPort??0);let s=o.address();if(!s||typeof s==`string`)throw new e(`COMMAND_FAILED`,`Proxy did not bind to a TCP address.`);let c=`http://${Se(s.address)}:${s.port}`;return{proxyBaseUrl:c,agentDeviceBaseUrl:u(c),token:a,upstreamBaseUrl:i,stateDir:n.paths.baseDir}}function ye(t){if(!t)throw new e(`COMMAND_FAILED`,`Local daemon HTTP endpoint is unavailable.`,{hint:`Retry after cleaning daemon state, or run proxy with a fresh --state-dir.`});return`http://127.0.0.1:${t}`}function be(e){return e.daemonAuthToken?.trim()||g(32).toString(`hex`)}function xe(e,t,n){return new Promise((r,i)=>{e.once(`error`,i),e.listen(n,t,()=>{e.off(`error`,i),r()})})}function Se(e){return e.includes(`:`)&&!e.startsWith(`[`)?`[${e}]`:e}function Ce(e,t={}){let n=t.useColor??ne(),r=$(`✓`,`green`,n),i=$(e.proxyBaseUrl,`cyan`,n),a=$(`<tunnel URL>`,`cyan`,n),o=$(e.token,`yellow`,n);return[`${r} Proxy listening at ${i}`,``,`Provide this to the agent-device instance connecting:`,``,`Daemon base URL: ${a}`,`Daemon auth token: ${o}`].join(`
2
+ `)}function $(e,t,n){return n?re(e,t,{validateStream:!1}):e}function we(){return new Promise(()=>{})}export{_e as proxyCommand};
@@ -1 +1 @@
1
- import{P as e}from"./sdk-contracts.js";import{a as t,g as n,o as r,p as i,u as a}from"./src.js";import{n as o}from"./provider-profile-fields.js";import{assertLimrunUploadedAppAccess as s,resolveInstalledAppIdForAsset as c,resolveLimrunAppAsset as l}from"./app-catalog.js";function u(e){o(e?.flags,i)}async function d(e,t,n){let r=n?.initialApp,i=typeof r==`string`?r.trim():``;if(i)return s(n?.publicNetworkOnly),await l(e,t,i,n?.signal)}async function f(n,r){let i=await t(n).listApps(`user-installed`),a=c(r.name,i);if(a)return a;throw new e(`COMMAND_FAILED`,`Limrun installed ${r.name}, but its application identifier could not be resolved unambiguously.`,{asset:r.name,installedApps:i.map(e=>e.id)})}async function p(t){let i=await t.limrun.iosInstances.create({wait:!0,metadata:t.metadata,spec:{...t.region?{region:t.region}:{},...t.app?{initialAssets:[{kind:`App`,source:`AssetID`,assetId:t.app.id,launchMode:`RelaunchIfRunning`}]}:{}}});try{if(!i.status.apiUrl)throw new e(`COMMAND_FAILED`,`Limrun iOS instance did not expose apiUrl`);return await r({lease:t.lease,instanceId:i.metadata.id,ownership:`created`,device:n(`ios`,t.lease,i.metadata.id),apiUrl:i.status.apiUrl,token:i.status.token},t.dependencies)}catch(e){throw await t.limrun.iosInstances.delete(i.metadata.id).catch(()=>{}),e}}async function m(t){let r=await t.limrun.androidInstances.create({wait:!0,metadata:t.metadata,spec:{...t.region?{region:t.region}:{},...t.app?{initialAssets:[{kind:`App`,source:`AssetIDs`,assetIds:[t.app.id]}]}:{}}});try{if(!r.status.apiUrl||!r.status.adbWebSocketUrl)throw new e(`COMMAND_FAILED`,`Limrun Android instance did not expose API and ADB websocket endpoints`);return await a({lease:t.lease,instanceId:r.metadata.id,ownership:`created`,device:n(`android`,t.lease,r.metadata.id),apiUrl:r.status.apiUrl,token:r.status.token,adbUrl:r.status.adbWebSocketUrl},t.dependencies)}catch(e){throw await t.limrun.androidInstances.delete(r.metadata.id).catch(()=>{}),e}}export{m as allocateLimrunAndroidSession,p as allocateLimrunIosSession,u as rejectRefusedLimrunProfileFields,f as resolvePreinstalledAppId,d as resolveRequestedLimrunAppAsset};
1
+ import{P as e}from"./sdk-contracts.js";import{_ as t,d as n,i as r,m as i,o as a,s as o}from"./src.js";import{n as s}from"./provider-profile-fields.js";import{assertLimrunUploadedAppAccess as c,resolveInstalledAppIdForAsset as l,resolveLimrunAppAsset as u}from"./app-catalog.js";function d(e){s(e?.flags,i)}async function f(e,t,n){let r=n?.initialApp,i=typeof r==`string`?r.trim():``;if(i)return c(n?.publicNetworkOnly),await u(e,t,i,n?.signal)}async function p(t,n){let r=await a(t).listApps(`user-installed`),i=l(n.name,r);if(i)return i;throw new e(`COMMAND_FAILED`,`Limrun installed ${n.name}, but its application identifier could not be resolved unambiguously.`,{asset:n.name,installedApps:r.map(e=>e.id)})}async function m(n){let i=await n.limrun.iosInstances.create({wait:!0,metadata:n.metadata,spec:{...n.region?{region:n.region}:{},...n.app?{initialAssets:[{kind:`App`,source:`AssetID`,assetId:n.app.id,launchMode:`RelaunchIfRunning`}]}:{}}},{headers:{"User-Agent":`${r}/${n.dependencies.clientVersion}`}});try{if(!i.status.apiUrl)throw new e(`COMMAND_FAILED`,`Limrun iOS instance did not expose apiUrl`);return await o({lease:n.lease,instanceId:i.metadata.id,ownership:`created`,device:t(`ios`,n.lease,i.metadata.id),apiUrl:i.status.apiUrl,token:i.status.token},n.dependencies)}catch(e){throw await n.limrun.iosInstances.delete(i.metadata.id).catch(()=>{}),e}}async function h(i){let a=await i.limrun.androidInstances.create({wait:!0,metadata:i.metadata,spec:{...i.region?{region:i.region}:{},...i.app?{initialAssets:[{kind:`App`,source:`AssetIDs`,assetIds:[i.app.id]}]}:{}}},{headers:{"User-Agent":`${r}/${i.dependencies.clientVersion}`}});try{if(!a.status.apiUrl||!a.status.adbWebSocketUrl)throw new e(`COMMAND_FAILED`,`Limrun Android instance did not expose API and ADB websocket endpoints`);return await n({lease:i.lease,instanceId:a.metadata.id,ownership:`created`,device:t(`android`,i.lease,a.metadata.id),apiUrl:a.status.apiUrl,token:a.status.token,adbUrl:a.status.adbWebSocketUrl},i.dependencies)}catch(e){throw await i.limrun.androidInstances.delete(a.metadata.id).catch(()=>{}),e}}export{h as allocateLimrunAndroidSession,m as allocateLimrunIosSession,d as rejectRefusedLimrunProfileFields,p as resolvePreinstalledAppId,f as resolveRequestedLimrunAppAsset};