agent-device 0.13.0 → 0.13.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -0
- package/dist/src/1974.js +2 -2
- package/dist/src/2301.js +1 -0
- package/dist/src/3918.js +29 -28
- package/dist/src/4993.js +1 -0
- package/dist/src/5721.js +1 -0
- package/dist/src/7166.js +1 -0
- package/dist/src/7651.js +1 -1
- package/dist/src/8564.js +1 -1
- package/dist/src/8656.js +1 -0
- package/dist/src/9076.js +1 -1
- package/dist/src/9152.js +1 -1
- package/dist/src/9542.js +2 -2
- package/dist/src/backend.js +1 -1
- package/dist/src/bin.js +49 -41
- package/dist/src/contracts.d.ts +12 -1
- package/dist/src/contracts.js +1 -1
- package/dist/src/daemon.js +18 -15
- package/dist/src/index.d.ts +36 -8
- package/dist/src/metro-companion.js +1 -1
- package/dist/src/metro.d.ts +29 -8
- package/dist/src/metro.js +1 -1
- package/dist/src/observability.d.ts +91 -0
- package/dist/src/observability.js +1 -0
- package/package.json +5 -1
- package/skills/agent-device/SKILL.md +2 -0
- package/skills/agent-device/references/bootstrap-install.md +26 -6
- package/skills/agent-device/references/exploration.md +11 -0
- package/skills/agent-device/references/remote-tenancy.md +45 -26
- package/skills/react-devtools/SKILL.md +2 -0
- package/dist/src/320.js +0 -1
- package/dist/src/3883.js +0 -1
- package/dist/src/8164.js +0 -1
- package/dist/src/9323.js +0 -5
package/dist/src/index.d.ts
CHANGED
|
@@ -145,6 +145,7 @@ export declare type AgentDeviceClient = {
|
|
|
145
145
|
};
|
|
146
146
|
metro: {
|
|
147
147
|
prepare: (options: MetroPrepareOptions) => Promise<MetroPrepareResult>;
|
|
148
|
+
reload: (options?: MetroReloadOptions) => Promise<MetroReloadResult>;
|
|
148
149
|
};
|
|
149
150
|
capture: {
|
|
150
151
|
snapshot: (options?: CaptureSnapshotOptions) => Promise<CaptureSnapshotResult>;
|
|
@@ -1371,6 +1372,12 @@ export declare type CommandSessionStore = {
|
|
|
1371
1372
|
list?(): readonly CommandSessionRecord[] | Promise<readonly CommandSessionRecord[]>;
|
|
1372
1373
|
};
|
|
1373
1374
|
|
|
1375
|
+
declare type CompanionTunnelScope = {
|
|
1376
|
+
tenantId: string;
|
|
1377
|
+
runId: string;
|
|
1378
|
+
leaseId: string;
|
|
1379
|
+
};
|
|
1380
|
+
|
|
1374
1381
|
export declare function createAgentDevice(config: AgentDeviceRuntimeConfig): AgentDevice;
|
|
1375
1382
|
|
|
1376
1383
|
export declare function createAgentDeviceClient(config?: AgentDeviceClientConfig, deps?: {
|
|
@@ -1412,7 +1419,18 @@ declare type DaemonInstallSource = {
|
|
|
1412
1419
|
} | {
|
|
1413
1420
|
kind: 'path';
|
|
1414
1421
|
path: string;
|
|
1415
|
-
}
|
|
1422
|
+
} | ({
|
|
1423
|
+
kind: 'github-actions-artifact';
|
|
1424
|
+
owner: string;
|
|
1425
|
+
repo: string;
|
|
1426
|
+
} & ({
|
|
1427
|
+
artifactId: number;
|
|
1428
|
+
} | {
|
|
1429
|
+
runId: number;
|
|
1430
|
+
artifactName: string;
|
|
1431
|
+
} | {
|
|
1432
|
+
artifactName: string;
|
|
1433
|
+
}));
|
|
1416
1434
|
|
|
1417
1435
|
declare type DaemonLockPolicy = 'reject' | 'strip';
|
|
1418
1436
|
|
|
@@ -1902,12 +1920,6 @@ declare type MetroBridgeResult = {
|
|
|
1902
1920
|
};
|
|
1903
1921
|
};
|
|
1904
1922
|
|
|
1905
|
-
declare type MetroBridgeScope = {
|
|
1906
|
-
tenantId: string;
|
|
1907
|
-
runId: string;
|
|
1908
|
-
leaseId: string;
|
|
1909
|
-
};
|
|
1910
|
-
|
|
1911
1923
|
declare type MetroPrepareKind = 'auto' | 'react-native' | 'expo';
|
|
1912
1924
|
|
|
1913
1925
|
export declare type MetroPrepareOptions = {
|
|
@@ -1916,7 +1928,7 @@ export declare type MetroPrepareOptions = {
|
|
|
1916
1928
|
publicBaseUrl?: string;
|
|
1917
1929
|
proxyBaseUrl?: string;
|
|
1918
1930
|
bearerToken?: string;
|
|
1919
|
-
bridgeScope?:
|
|
1931
|
+
bridgeScope?: CompanionTunnelScope;
|
|
1920
1932
|
launchUrl?: string;
|
|
1921
1933
|
companionProfileKey?: string;
|
|
1922
1934
|
companionConsumerKey?: string;
|
|
@@ -1933,6 +1945,15 @@ export declare type MetroPrepareOptions = {
|
|
|
1933
1945
|
|
|
1934
1946
|
export declare type MetroPrepareResult = PrepareMetroRuntimeResult;
|
|
1935
1947
|
|
|
1948
|
+
export declare type MetroReloadOptions = {
|
|
1949
|
+
metroHost?: string;
|
|
1950
|
+
metroPort?: number;
|
|
1951
|
+
bundleUrl?: string;
|
|
1952
|
+
timeoutMs?: number;
|
|
1953
|
+
};
|
|
1954
|
+
|
|
1955
|
+
export declare type MetroReloadResult = ReloadMetroResult;
|
|
1956
|
+
|
|
1936
1957
|
/** Re-export of {@link SessionRuntimeHints} under the Metro-specific alias used by public API consumers. */
|
|
1937
1958
|
declare type MetroRuntimeHints = SessionRuntimeHints;
|
|
1938
1959
|
|
|
@@ -2153,6 +2174,13 @@ declare type RefTarget_2 = {
|
|
|
2153
2174
|
selector?: never;
|
|
2154
2175
|
};
|
|
2155
2176
|
|
|
2177
|
+
declare type ReloadMetroResult = {
|
|
2178
|
+
reloaded: true;
|
|
2179
|
+
reloadUrl: string;
|
|
2180
|
+
status: number;
|
|
2181
|
+
body: string;
|
|
2182
|
+
};
|
|
2183
|
+
|
|
2156
2184
|
declare type RepeatedPressOptions = {
|
|
2157
2185
|
count?: number;
|
|
2158
2186
|
intervalMs?: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import e from"node:fs";import{setTimeout as r}from"node:timers/promises";import{normalizeBaseUrl as t,
|
|
1
|
+
import e from"node:fs";import{setTimeout as r}from"node:timers/promises";import{normalizeBaseUrl as t,ENV_COMPANION_TUNNEL_BEARER_TOKEN as s,ENV_COMPANION_TUNNEL_SERVER_BASE_URL as n,ENV_COMPANION_TUNNEL_STATE_PATH as o,ENV_COMPANION_TUNNEL_LAUNCH_URL as a,ENV_COMPANION_TUNNEL_SCOPE_LEASE_ID as i,ENV_COMPANION_TUNNEL_SCOPE_TENANT_ID as c,ENV_COMPANION_TUNNEL_DEVICE_PORT as l,METRO_COMPANION_RUN_ARG as f,ENV_COMPANION_TUNNEL_SESSION as d,ENV_COMPANION_TUNNEL_SCOPE_RUN_ID as u,ENV_COMPANION_TUNNEL_REGISTER_PATH as m,ENV_COMPANION_TUNNEL_LOCAL_BASE_URL as p,REACT_DEVTOOLS_COMPANION_RUN_ARG as g,ENV_COMPANION_TUNNEL_UNREGISTER_PATH as y}from"./2301.js";function w(e,r){return{authorization:`Bearer ${r}`,"content-type":"application/json",...e.includes("ngrok")?{"ngrok-skip-browser-warning":"1"}:{}}}function h(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 b(e){let r,s,n=e.registerPath;try{r=await fetch(`${t(e.serverBaseUrl)}${n}`,{method:"POST",headers:w(e.serverBaseUrl,e.bearerToken),body:JSON.stringify(h(e)),signal:AbortSignal.timeout(5e3)})}catch(r){if(r instanceof Error&&"TimeoutError"===r.name)throw Error(`${n} timed out after 5000ms calling ${t(e.serverBaseUrl)}${n}`);throw r}let o=await r.text();try{s=o?JSON.parse(o):{}}catch{let e;throw Error(`Failed to register companion (${r.status}): invalid JSON response: ${(e=o.replaceAll(/\s+/g," ").trim()).length>300?`${e.slice(0,300)}...`:e}`)}if(!r.ok||!0!==s.ok||"string"!=typeof s.data?.ws_url)throw Error(`Failed to register companion (${r.status}): ${JSON.stringify(s)}`);return{wsUrl:s.data.ws_url}}async function S(e){let r=e.unregisterPath??null;if(r)try{await fetch(`${t(e.serverBaseUrl)}${r}`,{method:"POST",headers:w(e.serverBaseUrl,e.bearerToken),body:JSON.stringify(h(e)),signal:AbortSignal.timeout(2e3)})}catch(e){console.error(e instanceof Error?e.message:String(e))}}async function v(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 E(e){return JSON.parse((await v(e.data)).toString("utf8"))}function I(e,r){1===e.readyState&&e.send(JSON.stringify(r))}async function B(e,r){1!==e.readyState&&await new Promise((t,s)=>{let n=()=>{i(),t()},o=()=>{i(),s(Error(`${r} WebSocket failed before opening.`))},a=()=>{i(),s(Error(`${r} WebSocket closed before opening.`))},i=()=>{e.removeEventListener("open",n),e.removeEventListener("error",o),e.removeEventListener("close",a)};e.addEventListener("open",n,{once:!0}),e.addEventListener("error",o,{once:!0}),e.addEventListener("close",a,{once:!0})})}async function k(e){e.readyState>=WebSocket.CLOSING||await new Promise(r=>{let t=()=>{s(),r()},s=()=>{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 L(e,r,t){try{e.close(1e3===r||r>=3e3&&r<=4999?r:3001,t)}catch{}}function U(r){return!r.statePath||e.existsSync(r.statePath)}async function $(e,r,s,n){var o,a;switch(r.type){case"ping":return void I(e,{type:"pong",timestamp:r.timestamp});case"http-request":try{let n=await fetch(new URL(r.path,`${t(s.localBaseUrl)}/`),{method:r.method,headers:r.headers,...r.bodyBase64?{body:Buffer.from(r.bodyBase64,"base64")}:{}}),o=Buffer.from(await n.arrayBuffer());I(e,{type:"http-response",requestId:r.requestId,status:n.status,headers:Object.fromEntries(n.headers.entries()),...o.length>0?{bodyBase64:o.toString("base64")}:{}})}catch(t){I(e,{type:"http-error",requestId:r.requestId,message:t instanceof Error?t.message:String(t)})}return;case"ws-open":{let a,i=new WebSocket((o=s.localBaseUrl,(a=new URL(r.path,`${t(o)}/`)).protocol="https:"===a.protocol?"wss:":"ws:",a.toString()));i.binaryType="arraybuffer";let c=!1;i.addEventListener("message",t=>{(async()=>{if(!c)return;let s=await v(t.data);I(e,{type:"ws-frame",streamId:r.streamId,dataBase64:s.toString("base64"),binary:"string"!=typeof t.data})})().catch(e=>{console.error(e instanceof Error?e.message:String(e))})}),i.addEventListener("close",t=>{n.delete(r.streamId),c&&I(e,{type:"ws-close",streamId:r.streamId,code:t.code,reason:t.reason})}),i.addEventListener("error",()=>{c&&I(e,{type:"ws-close",streamId:r.streamId,code:1011,reason:"Upstream WebSocket error."})}),n.set(r.streamId,i);try{await B(i,"Upstream"),c=!0,I(e,{type:"ws-open-result",streamId:r.streamId,success:!0,headers:{}})}catch(t){n.delete(r.streamId),L(i,1011,"open failed"),I(e,{type:"ws-open-result",streamId:r.streamId,success:!1,error:t instanceof Error?t.message:String(t)})}return}case"ws-frame":{let e=n.get(r.streamId);if(!e||1!==e.readyState)return;let t=Buffer.from(r.dataBase64,"base64");e.send(r.binary?t:t.toString("utf8"));return}case"ws-close":{let e=n.get(r.streamId);if(!e)return;n.delete(r.streamId),L(e,"number"==typeof(a=r.code)&&Number.isInteger(a)&&(1e3===a||a>=3e3&&a<=4999||a>=1001&&a<=1015&&1004!==a&&1005!==a&&1006!==a)?a:1011,r.reason??"bridge requested close");return}}}async function N(e){let t=new Map,s=!1,n=null,o=!1,a=()=>{s||(s=!0,o&&S(e).finally(()=>process.exit(0)),n&&L(n,1e3,"companion stopping"),setTimeout(()=>process.exit(0),900).unref())};process.once("SIGTERM",a),process.once("SIGINT",a);let i=setInterval(()=>{U(e)||process.exit(0)},250);for(i.unref();!s&&U(e);){let a=!1;try{o=!1;let r=await b(e);if(a=!0,o=!0,s||!U(e)){await S(e),a=!1,o=!1;break}let i=new WebSocket(r.wsUrl);n=i,i.binaryType="arraybuffer";try{await B(i,"Bridge"),i.addEventListener("message",r=>{(async()=>{let s=await E(r);await $(i,s,e,t)})().catch(e=>{console.error(e instanceof Error?e.message:String(e))})}),await k(i)}finally{n=null,o=!1,t.forEach(e=>L(e,1012,"bridge disconnected")),t.clear(),a&&(await S(e),a=!1)}}catch(r){if(n=null,o=!1,a&&(await S(e),a=!1),s||!U(e))break;console.error(r instanceof Error?r.message:String(r))}if(s||!U(e))break;await r(1e3)}clearInterval(i)}(async function(e,r){let t=function(e,r){let t=e[0];if(t!==f&&t!==g)return null;let w=r[n]?.trim(),h=r[s]?.trim(),b=r[p]?.trim();if(!w||!h||!b)throw Error("Companion tunnel worker is missing required environment configuration.");let S=r[c]?.trim(),v=r[u]?.trim(),E=r[i]?.trim();if(!S||!v||!E)throw Error("Companion tunnel worker is missing required bridge scope configuration.");let I=r[m]?.trim();if(!I)throw Error("Companion tunnel worker is missing required register path configuration.");return{serverBaseUrl:w,bearerToken:h,localBaseUrl:b,registerPath:I,bridgeScope:{tenantId:S,runId:v,leaseId:E},launchUrl:r[a]?.trim()||void 0,statePath:r[o]?.trim()||void 0,unregisterPath:r[y]?.trim()||void 0,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]),session:r[d]?.trim()||void 0}}(e,r);return!!t&&(await N(t),!0)})(process.argv.slice(2),process.env).catch(e=>{if(e instanceof Error&&e.message.includes("missing required environment")){console.error(e.message),process.exitCode=1;return}console.error(e instanceof Error?e.stack??e.message:String(e)),process.exitCode=1});
|
package/dist/src/metro.d.ts
CHANGED
|
@@ -4,6 +4,12 @@ export declare function buildBundleUrl(baseUrl: string, platform: 'ios' | 'andro
|
|
|
4
4
|
|
|
5
5
|
export declare function buildIosRuntimeHints(baseUrl: string): MetroRuntimeHints;
|
|
6
6
|
|
|
7
|
+
declare type CompanionTunnelScope = {
|
|
8
|
+
tenantId: string;
|
|
9
|
+
runId: string;
|
|
10
|
+
leaseId: string;
|
|
11
|
+
};
|
|
12
|
+
|
|
7
13
|
export declare function ensureMetroTunnel(options: EnsureMetroTunnelOptions): Promise<EnsureMetroTunnelResult>;
|
|
8
14
|
|
|
9
15
|
export declare type EnsureMetroTunnelOptions = {
|
|
@@ -11,7 +17,7 @@ export declare type EnsureMetroTunnelOptions = {
|
|
|
11
17
|
serverBaseUrl: string;
|
|
12
18
|
bearerToken: string;
|
|
13
19
|
localBaseUrl: string;
|
|
14
|
-
bridgeScope:
|
|
20
|
+
bridgeScope: CompanionTunnelScope;
|
|
15
21
|
launchUrl?: string;
|
|
16
22
|
profileKey?: string;
|
|
17
23
|
consumerKey?: string;
|
|
@@ -75,12 +81,6 @@ export declare type MetroBridgeRuntimePayload = {
|
|
|
75
81
|
launch_url?: string;
|
|
76
82
|
};
|
|
77
83
|
|
|
78
|
-
declare type MetroBridgeScope = {
|
|
79
|
-
tenantId: string;
|
|
80
|
-
runId: string;
|
|
81
|
-
leaseId: string;
|
|
82
|
-
};
|
|
83
|
-
|
|
84
84
|
/** Re-export of {@link SessionRuntimeHints} under the Metro-specific alias used by public API consumers. */
|
|
85
85
|
export declare type MetroRuntimeHints = SessionRuntimeHints;
|
|
86
86
|
|
|
@@ -162,7 +162,7 @@ export declare type PrepareRemoteMetroOptions = {
|
|
|
162
162
|
publicBaseUrl?: string;
|
|
163
163
|
proxyBaseUrl?: string;
|
|
164
164
|
proxyBearerToken?: string;
|
|
165
|
-
bridgeScope?:
|
|
165
|
+
bridgeScope?: CompanionTunnelScope;
|
|
166
166
|
launchUrl?: string;
|
|
167
167
|
profileKey?: string;
|
|
168
168
|
consumerKey?: string;
|
|
@@ -187,6 +187,27 @@ export declare type PrepareRemoteMetroResult = {
|
|
|
187
187
|
logPath: string;
|
|
188
188
|
};
|
|
189
189
|
|
|
190
|
+
declare type ReloadMetroOptions = {
|
|
191
|
+
metroHost?: string;
|
|
192
|
+
metroPort?: number | string;
|
|
193
|
+
bundleUrl?: string;
|
|
194
|
+
runtime?: MetroRuntimeHints;
|
|
195
|
+
timeoutMs?: number | string;
|
|
196
|
+
};
|
|
197
|
+
|
|
198
|
+
declare type ReloadMetroResult = {
|
|
199
|
+
reloaded: true;
|
|
200
|
+
reloadUrl: string;
|
|
201
|
+
status: number;
|
|
202
|
+
body: string;
|
|
203
|
+
};
|
|
204
|
+
|
|
205
|
+
export declare function reloadRemoteMetro(options?: ReloadRemoteMetroOptions): Promise<ReloadRemoteMetroResult>;
|
|
206
|
+
|
|
207
|
+
export declare type ReloadRemoteMetroOptions = ReloadMetroOptions;
|
|
208
|
+
|
|
209
|
+
export declare type ReloadRemoteMetroResult = ReloadMetroResult;
|
|
210
|
+
|
|
190
211
|
export declare function resolveRuntimeTransport(runtime: SessionRuntimeHints | undefined): {
|
|
191
212
|
host: string;
|
|
192
213
|
port: number;
|
package/dist/src/metro.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{buildMetroRuntimeHints as e,ensureMetroCompanion as t,
|
|
1
|
+
import{buildMetroRuntimeHints as e,ensureMetroCompanion as t,reloadMetro as r,stopMetroCompanion as o,prepareMetroRuntime as n}from"./1974.js";import{resolveRuntimeTransportHints as i}from"./8656.js";function s(e){return i(e)}async function a(e){let t=await n({projectRoot:e.projectRoot,kind:e.kind,publicBaseUrl:e.publicBaseUrl,proxyBaseUrl:e.proxyBaseUrl,proxyBearerToken:e.proxyBearerToken,bridgeScope:e.bridgeScope,launchUrl:e.launchUrl,companionProfileKey:e.profileKey,companionConsumerKey:e.consumerKey,metroPort:e.port,listenHost:e.listenHost,statusHost:e.statusHost,startupTimeoutMs:e.startupTimeoutMs,probeTimeoutMs:e.probeTimeoutMs,reuseExisting:e.reuseExisting,installDependenciesIfNeeded:e.installDependenciesIfNeeded,runtimeFilePath:e.runtimeFilePath,logPath:e.logPath,env:e.env});return{iosRuntime:t.iosRuntime,androidRuntime:t.androidRuntime,bridge:t.bridge,started:t.started,reused:t.reused,logPath:t.logPath}}async function u(e){let r=await t(e);return{pid:r.pid,started:r.spawned,logPath:r.logPath}}async function l(e){await o(e)}async function d(e={}){return await r(e)}function p(t){return e(t,"ios")}function m(t){return e(t,"android")}export{buildBundleUrl,normalizeBaseUrl}from"./2301.js";export{m as buildAndroidRuntimeHints,p as buildIosRuntimeHints,u as ensureMetroTunnel,a as prepareRemoteMetro,d as reloadRemoteMetro,s as resolveRuntimeTransport,l as stopMetroTunnel};
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
declare type BackendDiagnosticsTimeWindow = {
|
|
2
|
+
since?: string;
|
|
3
|
+
until?: string;
|
|
4
|
+
};
|
|
5
|
+
|
|
6
|
+
declare type BackendDumpNetworkResult = {
|
|
7
|
+
entries: readonly BackendNetworkEntry[];
|
|
8
|
+
nextCursor?: string;
|
|
9
|
+
timeWindow?: BackendDiagnosticsTimeWindow;
|
|
10
|
+
backend?: string;
|
|
11
|
+
redacted?: boolean;
|
|
12
|
+
notes?: readonly string[];
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
declare type BackendNetworkEntry = {
|
|
16
|
+
timestamp?: string;
|
|
17
|
+
method?: string;
|
|
18
|
+
url?: string;
|
|
19
|
+
status?: number;
|
|
20
|
+
durationMs?: number;
|
|
21
|
+
requestHeaders?: Record<string, string>;
|
|
22
|
+
responseHeaders?: Record<string, string>;
|
|
23
|
+
requestBody?: string;
|
|
24
|
+
responseBody?: string;
|
|
25
|
+
metadata?: Record<string, unknown>;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export declare function mapNetworkDumpToBackendResult(dump: ParsedNetworkDump, options?: {
|
|
29
|
+
backend?: string;
|
|
30
|
+
redacted?: boolean;
|
|
31
|
+
notes?: readonly string[];
|
|
32
|
+
}): BackendDumpNetworkResult;
|
|
33
|
+
|
|
34
|
+
export declare function mergeNetworkDumps(primary: ParsedNetworkDump, secondary: ParsedNetworkDump, maxEntries?: number): ParsedNetworkDump;
|
|
35
|
+
|
|
36
|
+
export declare type NetworkIncludeMode = NetworkIncludeMode_2;
|
|
37
|
+
|
|
38
|
+
declare type NetworkIncludeMode_2 = 'summary' | 'headers' | 'body' | 'all';
|
|
39
|
+
|
|
40
|
+
export declare type NetworkLogBackend = NetworkLogBackend_2 | (string & {});
|
|
41
|
+
|
|
42
|
+
declare type NetworkLogBackend_2 = 'ios-simulator' | 'ios-device' | 'android' | 'macos';
|
|
43
|
+
|
|
44
|
+
export declare type ParsedNetworkDump = {
|
|
45
|
+
sourcePath?: string;
|
|
46
|
+
scannedLines: number;
|
|
47
|
+
matchedLines: number;
|
|
48
|
+
entries: ParsedNetworkEntry[];
|
|
49
|
+
include: NetworkIncludeMode;
|
|
50
|
+
limits: {
|
|
51
|
+
maxEntries: number;
|
|
52
|
+
maxPayloadChars: number;
|
|
53
|
+
maxScanLines: number;
|
|
54
|
+
};
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
export declare type ParsedNetworkEntry = {
|
|
58
|
+
url: string;
|
|
59
|
+
timestamp?: string;
|
|
60
|
+
method?: string;
|
|
61
|
+
status?: number;
|
|
62
|
+
durationMs?: number;
|
|
63
|
+
headers?: string;
|
|
64
|
+
requestBody?: string;
|
|
65
|
+
responseBody?: string;
|
|
66
|
+
raw?: string;
|
|
67
|
+
line?: number;
|
|
68
|
+
packetId?: string;
|
|
69
|
+
metadata?: {
|
|
70
|
+
packetId?: string;
|
|
71
|
+
[key: string]: unknown;
|
|
72
|
+
};
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
export declare function readRecentNetworkTrafficFromText(content: string, options?: {
|
|
76
|
+
sourcePath?: string;
|
|
77
|
+
backend?: NetworkLogBackend;
|
|
78
|
+
maxEntries?: number;
|
|
79
|
+
include?: NetworkIncludeMode;
|
|
80
|
+
maxPayloadChars?: number;
|
|
81
|
+
maxScanLines?: number;
|
|
82
|
+
}): ParsedNetworkDump;
|
|
83
|
+
|
|
84
|
+
export declare type RedactionResult = {
|
|
85
|
+
value: string;
|
|
86
|
+
redacted: boolean;
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
export declare function redactNetworkLogText(text: string): RedactionResult;
|
|
90
|
+
|
|
91
|
+
export { }
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{NETWORK_LOG_MEMORY_PATH as e,readRecentNetworkTrafficFromText as t}from"./5721.js";function a(a,s){var r;let d;return r=t(a,{path:s?.sourcePath,backend:function(e){switch(e){case"ios-simulator":return"ios-simulator";case"ios-device":return"ios-device";case"android":return"android";case"macos":return"macos";default:return}}(s?.backend),maxEntries:s?.maxEntries,include:s?.include,maxPayloadChars:s?.maxPayloadChars,maxScanLines:s?.maxScanLines}),{...(d=s?.sourcePath??(r.path===e?void 0:r.path))?{sourcePath:d}:{},scannedLines:r.scannedLines,matchedLines:r.matchedLines,entries:r.entries.map(e=>({url:e.url,...e.timestamp?{timestamp:e.timestamp}:{},...e.method?{method:e.method}:{},...void 0!==e.status?{status:e.status}:{},...void 0!==e.durationMs?{durationMs:e.durationMs}:{},...e.headers?{headers:e.headers}:{},...void 0!==e.requestBody?{requestBody:e.requestBody}:{},...void 0!==e.responseBody?{responseBody:e.responseBody}:{},...e.raw?{raw:e.raw}:{},...void 0!==e.line?{line:e.line}:{},...e.packetId?{packetId:e.packetId}:{}})),include:r.include,limits:r.limits}}function s(e,t,a=e.limits.maxEntries){let r=Math.max(0,a),o=e.entries.slice(0,r),n=new Set(o.map(e=>d(e)));for(let e of t.entries){if(o.length>=r)break;let t=d(e);n.has(t)||(n.add(t),o.push(e))}return{...e,matchedLines:o.length,entries:o}}function r(e,t){return{entries:e.entries.map(e=>{var t,a;let s,r;return r=(s={...(a=t=e).metadata??{}},a.packetId&&void 0===s.packetId&&(s.packetId=a.packetId),a.headers&&void 0===s.headers&&(s.headers=a.headers),Object.keys(s).length>0?s:void 0),{...t.timestamp?{timestamp:t.timestamp}:{},...t.method?{method:t.method}:{},url:t.url,...void 0!==t.status?{status:t.status}:{},...void 0!==t.durationMs?{durationMs:t.durationMs}:{},...void 0!==t.requestBody?{requestBody:t.requestBody}:{},...void 0!==t.responseBody?{responseBody:t.responseBody}:{},...r?{metadata:r}:{}}}),...t?.backend?{backend:t.backend}:{},...t?.redacted!==void 0?{redacted:t.redacted}:{},...t?.notes?{notes:t.notes}:{}}}function d(e){return`${e.timestamp??""}|${e.method??""}|${e.url}|${e.status??""}|${e.raw??""}`}export{redactNetworkLogText}from"./7166.js";export{r as mapNetworkDumpToBackendResult,s as mergeNetworkDumps,a as readRecentNetworkTrafficFromText};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agent-device",
|
|
3
|
-
"version": "0.13.
|
|
3
|
+
"version": "0.13.2",
|
|
4
4
|
"description": "Agent-driven CLI for mobile UI automation, network inspection, and performance diagnostics across iOS, Android, tvOS, and macOS.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Callstack",
|
|
@@ -40,6 +40,10 @@
|
|
|
40
40
|
"import": "./dist/src/artifacts.js",
|
|
41
41
|
"types": "./dist/src/artifacts.d.ts"
|
|
42
42
|
},
|
|
43
|
+
"./observability": {
|
|
44
|
+
"import": "./dist/src/observability.js",
|
|
45
|
+
"types": "./dist/src/observability.d.ts"
|
|
46
|
+
},
|
|
43
47
|
"./metro": {
|
|
44
48
|
"import": "./dist/src/metro.js",
|
|
45
49
|
"types": "./dist/src/metro.d.ts"
|
|
@@ -16,6 +16,7 @@ Use this skill as a router with mandatory defaults. Read this file first. For no
|
|
|
16
16
|
- Prefer `diff snapshot` after a nearby mutation when you only need to know what changed.
|
|
17
17
|
- Avoid speculative mutations. You may take the smallest reversible UI action needed to unblock inspection or complete the requested task, such as dismissing a popup, closing an alert, or clearing an unintended surface.
|
|
18
18
|
- In React Native dev or debug builds, check early for visible warning or error overlays, tooltips, and toasts that can steal focus or intercept taps. If they are not part of the requested behavior, dismiss them and continue. If you saw them, report them in the final summary.
|
|
19
|
+
- In Metro-backed React Native dev loops, use `agent-device metro reload` for a JS app reload before falling back to `open <app> --relaunch`. It mirrors pressing `r` in the Metro terminal and preserves the native app process.
|
|
19
20
|
- Do not browse the web or use external sources unless the user explicitly asks.
|
|
20
21
|
- Re-snapshot after meaningful UI changes instead of reusing stale refs.
|
|
21
22
|
- Treat refs in default snapshot output as actionable-now, not durable identities. If a target appears only in an off-screen summary, use `scroll <direction>` and re-snapshot until the target is visible.
|
|
@@ -60,6 +61,7 @@ Use this skill as a router with mandatory defaults. Read this file first. For no
|
|
|
60
61
|
- If there is no simulator, no app install, or no open app session yet, switch to `bootstrap-install.md` instead of improvising setup steps.
|
|
61
62
|
- Use the smallest unblock action first when transient UI blocks inspection, but do not navigate, search, or enter new text just to make the UI reveal data unless the user asked for that interaction.
|
|
62
63
|
- In React Native dev or debug apps, treat visible warning or error overlays as transient blockers unless the user is explicitly asking you to diagnose them. Dismiss them when safe, then continue the requested flow.
|
|
64
|
+
- For React Native code changes where the app is already connected to Metro, prefer `agent-device metro reload`, then wait and re-snapshot. Use `open <app> --relaunch` only when Metro reload does not reconnect or native startup state must reset.
|
|
63
65
|
- Do not use external lookups to compensate for missing on-screen data unless the user asked for them.
|
|
64
66
|
- If the needed information is not exposed on screen, say that plainly instead of compensating with extra navigation, text entry, or web search.
|
|
65
67
|
- Prefer `@ref` or selector targeting over raw coordinates.
|
|
@@ -18,6 +18,7 @@ Use this exact order when you are not sure about the installed app identifier. O
|
|
|
18
18
|
|
|
19
19
|
- `install` or `reinstall`
|
|
20
20
|
- `install-from-source` when the artifact already exists at a URL the daemon can reach
|
|
21
|
+
- `install-from-source --github-actions-artifact` when a compatible remote daemon should resolve a GitHub Actions artifact
|
|
21
22
|
|
|
22
23
|
## Most common mistake to avoid
|
|
23
24
|
|
|
@@ -35,8 +36,6 @@ After setup is confirmed or completed, move to `exploration.md` before doing UI
|
|
|
35
36
|
- If `open <app>` fails, run `agent-device apps` and retry with a discovered app name before considering install steps.
|
|
36
37
|
- Do not install or reinstall on the first attempt unless the user explicitly asks for installation or provides a concrete artifact path or URL.
|
|
37
38
|
- When installation is required from a known location, prefer a checked-in shell script or other deterministic bootstrap command over ad hoc path guessing.
|
|
38
|
-
|
|
39
|
-
- If `open <app>` fails, or you are not sure which app name is available on the target, run `agent-device apps` first and choose from the discovered app list instead of guessing.
|
|
40
39
|
- Use `apps --platform <platform>` together with `--device`, `--udid`, or `--serial` when target selection matters.
|
|
41
40
|
- Once you have the correct app name, retry `open` with that exact discovered value.
|
|
42
41
|
|
|
@@ -64,8 +63,27 @@ agent-device install com.example.app ./build/MyApp.app --platform ios --device "
|
|
|
64
63
|
```bash
|
|
65
64
|
ARTIFACT_URL="<trusted-artifact-url>"
|
|
66
65
|
agent-device install-from-source "$ARTIFACT_URL" --platform android
|
|
67
|
-
|
|
68
|
-
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Daemon-resolved GitHub Actions artifacts:
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
agent-device install-from-source \
|
|
72
|
+
--github-actions-artifact ORG/REPO:1234567890 \
|
|
73
|
+
--platform android
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Project config can provide an artifact name instead:
|
|
77
|
+
|
|
78
|
+
```json
|
|
79
|
+
{
|
|
80
|
+
"platform": "android",
|
|
81
|
+
"installSource": {
|
|
82
|
+
"type": "github-actions-artifact",
|
|
83
|
+
"repo": "ORG/REPO",
|
|
84
|
+
"artifact": "app-debug"
|
|
85
|
+
}
|
|
86
|
+
}
|
|
69
87
|
```
|
|
70
88
|
|
|
71
89
|
## Install guidance
|
|
@@ -73,6 +91,7 @@ agent-device install-from-source "$GITHUB_ARTIFACT_URL" --platform ios --header
|
|
|
73
91
|
- Use `install <app> <path>` when the app may already be installed and you do not need a fresh-state reset.
|
|
74
92
|
- Use `reinstall <app> <path>` when you explicitly need uninstall plus install as one deterministic step.
|
|
75
93
|
- Use `install-from-source <url>` only when an existing artifact URL is trusted, operator-approved, and reachable by the daemon.
|
|
94
|
+
- Use `--github-actions-artifact <org>/<repo>:<artifact>` when a compatible remote daemon should resolve a GitHub Actions artifact. Numeric artifacts are IDs; non-numeric artifacts are names.
|
|
76
95
|
- Local `.apk`, `.aab`, `.app`, and `.ipa` paths go through `install` or `reinstall`; existing reachable URLs go through `install-from-source`.
|
|
77
96
|
- Do not download, re-zip, publish temporary GitHub releases, or move CI artifacts elsewhere just to make an install command work.
|
|
78
97
|
- Keep install and open as separate phases. Do not turn them into one default command flow.
|
|
@@ -80,10 +99,10 @@ agent-device install-from-source "$GITHUB_ARTIFACT_URL" --platform ios --header
|
|
|
80
99
|
- Android: `.apk` and `.aab`
|
|
81
100
|
- iOS: `.app` and `.ipa`
|
|
82
101
|
- Android URL sources can be direct `.apk` or `.aab` files.
|
|
83
|
-
- Trusted artifact service URLs
|
|
102
|
+
- Trusted artifact service URLs may point at archive-backed downloads that contain one installable artifact. Prefer `--github-actions-artifact` for GitHub Actions artifacts that a compatible remote daemon can resolve with its own credentials.
|
|
84
103
|
- If a trusted artifact archive contains multiple installables, stop and ask for the intended artifact instead of guessing.
|
|
85
104
|
- `.aab` still requires `bundletool` in `PATH`, or `AGENT_DEVICE_BUNDLETOOL_JAR=<absolute-path-to-bundletool-all.jar>` with `java` in `PATH`, when the daemon installs the materialized artifact.
|
|
86
|
-
- For
|
|
105
|
+
- For `.ipa` archives with multiple app bundles, `<app>` is the bundle id or bundle name selection hint.
|
|
87
106
|
- After install or reinstall, later use `open <app>` with the exact discovered or known package/bundle identifier, not the artifact path.
|
|
88
107
|
|
|
89
108
|
## Choose the right starting point
|
|
@@ -115,6 +134,7 @@ agent-device --session auth snapshot -i
|
|
|
115
134
|
- Use semantic session names when you need multiple concurrent runs.
|
|
116
135
|
- Use `--save-script=<path>` on `close` when you want to keep a replay script.
|
|
117
136
|
- For dev loops where state can linger, prefer `open <app> --relaunch`.
|
|
137
|
+
- For Metro-backed React Native JS changes with the app already running, prefer `metro reload` instead of `open <app> --relaunch`; it asks Metro to reload connected apps without restarting the native process.
|
|
118
138
|
- In iOS sessions, use `open <app>` for the app itself. Use `open <url>` for deep links, and `open <app> <url>` when you need to launch the app and deep link in one step.
|
|
119
139
|
- On iOS, `appstate` is session-scoped and requires the matching active session on the target device.
|
|
120
140
|
|
|
@@ -21,6 +21,7 @@ Open this file when the app or screen is already running and you need to discove
|
|
|
21
21
|
- User asks for exact text from a known target: `get text`
|
|
22
22
|
- User asks you to tap, type, or choose an element: `snapshot -i`, then act
|
|
23
23
|
- User asks for the React Native component tree, props/state/hooks, or render profiling: use `agent-device react-devtools ...` and the `skills/react-devtools` workflow
|
|
24
|
+
- User asks to reload a Metro-backed React Native app after JS changes: `agent-device metro reload`, then wait briefly and re-run `snapshot` or `snapshot -i`
|
|
24
25
|
- React Native dev or debug build shows warning/error UI: capture enough evidence to identify it, dismiss it if it is not the requested behavior, then continue the flow and report it in the summary
|
|
25
26
|
- The on-screen keyboard is blocking the next step: `keyboard dismiss`; on iOS do this only while an app session is active, and use `keyboard status|get` only on Android
|
|
26
27
|
- UI does not expose the answer: say so plainly; do not browse or force the app into a new state unless asked
|
|
@@ -60,6 +61,16 @@ Open this file when the app or screen is already running and you need to discove
|
|
|
60
61
|
- Blocking or recurring: switch to [debugging.md](debugging.md) and collect evidence.
|
|
61
62
|
- Seen at any point: mention in the final summary even if dismissed.
|
|
62
63
|
|
|
64
|
+
**React Native Metro reload.** When a dev app is already running and connected to Metro, prefer a Metro reload over restarting the native app process:
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
agent-device metro reload
|
|
68
|
+
agent-device wait 1000
|
|
69
|
+
agent-device snapshot -i
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Use `--metro-host`, `--metro-port`, or `--bundle-url` only when the active connection does not already carry the right runtime hints. Fall back to `open <app> --relaunch` when the app is not connected to Metro, Metro reload fails, or native startup state needs a clean process.
|
|
73
|
+
|
|
63
74
|
## Common example loops
|
|
64
75
|
|
|
65
76
|
These are examples, not required exact sequences. Adapt them to the app, state, and task at hand.
|
|
@@ -8,11 +8,14 @@ Open this file for remote daemon HTTP flows that let an agent running in a Linux
|
|
|
8
8
|
|
|
9
9
|
- `agent-device connect --remote-config <path>`
|
|
10
10
|
- `agent-device install-from-source <url> --remote-config <path> --platform android`
|
|
11
|
+
- `agent-device install-from-source --github-actions-artifact <org>/<repo>:<artifact> --remote-config <path> --platform android`
|
|
11
12
|
- `agent-device open <package> --remote-config <path> --relaunch`
|
|
13
|
+
- `agent-device metro reload --remote-config <path>`
|
|
12
14
|
- `agent-device snapshot --remote-config <path> -i`
|
|
13
15
|
- `agent-device disconnect --remote-config <path>`
|
|
14
16
|
- `agent-device connection status`
|
|
15
|
-
- `
|
|
17
|
+
- `agent-device auth status`
|
|
18
|
+
- `AGENT_DEVICE_DAEMON_AUTH_TOKEN=...` for CI/service-token automation
|
|
16
19
|
|
|
17
20
|
## Most common mistake to avoid
|
|
18
21
|
|
|
@@ -28,20 +31,18 @@ Do not mix an arbitrary `--session` plus ad-hoc daemon, tenant, run, or lease fl
|
|
|
28
31
|
Use this when the agent will run several commands in one session.
|
|
29
32
|
|
|
30
33
|
```bash
|
|
31
|
-
export AGENT_DEVICE_DAEMON_AUTH_TOKEN="YOUR_TOKEN"
|
|
32
|
-
export AGENT_DEVICE_PROXY_TOKEN="$AGENT_DEVICE_DAEMON_AUTH_TOKEN"
|
|
33
|
-
|
|
34
34
|
agent-device connect --remote-config ./remote-config.json
|
|
35
35
|
|
|
36
36
|
ARTIFACT_URL="<trusted-artifact-url>"
|
|
37
37
|
agent-device install-from-source "$ARTIFACT_URL" --platform android
|
|
38
38
|
agent-device open com.example.app --relaunch
|
|
39
|
+
agent-device metro reload
|
|
39
40
|
agent-device snapshot -i
|
|
40
41
|
agent-device fill @e3 "test@example.com"
|
|
41
42
|
agent-device disconnect
|
|
42
43
|
```
|
|
43
44
|
|
|
44
|
-
After `connect`, normal commands use the active remote connection. End with `disconnect` to release the lease and stop the owned Metro companion.
|
|
45
|
+
After `connect`, normal commands use the active remote connection. If cloud credentials are missing, `connect` starts login automatically in an interactive shell and stores a revocable CLI session that silently mints short-lived `adc_agent_...` command tokens. The cloud side remains responsible for token expiry, tenant/run claim checks, revocation, one-time device approval, and polling rate limits. End with `disconnect` to release the lease and stop the owned Metro companion.
|
|
45
46
|
|
|
46
47
|
### Self-contained script flow
|
|
47
48
|
|
|
@@ -73,6 +74,7 @@ The first command that needs a lease or Metro runtime prepares and persists it.
|
|
|
73
74
|
- `connect` stores local non-secret connection state and defers tenant lease allocation plus Metro preparation until a later command needs them.
|
|
74
75
|
- Commands such as `install-from-source`, `open`, `snapshot`, and `apps` allocate or refresh the lease when needed.
|
|
75
76
|
- `open` prepares Metro runtime hints when the remote profile has Metro fields and no compatible runtime is already saved.
|
|
77
|
+
- `metro reload` reuses saved Metro runtime hints and asks Metro to reload connected React Native apps without restarting the native process.
|
|
76
78
|
- `batch` also prepares Metro when any step opens an app and that step does not provide its own runtime.
|
|
77
79
|
- `disconnect` closes the session when possible, stops the Metro companion owned by the connection, releases the lease when one was allocated, and removes local connection state.
|
|
78
80
|
|
|
@@ -82,12 +84,11 @@ Remote install examples:
|
|
|
82
84
|
agent-device install com.example.app ./app.apk
|
|
83
85
|
ARTIFACT_URL="<trusted-artifact-url>"
|
|
84
86
|
agent-device install-from-source "$ARTIFACT_URL" --platform android
|
|
85
|
-
GITHUB_ARTIFACT_URL="<trusted-github-actions-artifact-api-url>"
|
|
86
|
-
agent-device install-from-source "$GITHUB_ARTIFACT_URL" --platform ios --header "authorization: Bearer TOKEN"
|
|
87
87
|
```
|
|
88
88
|
|
|
89
89
|
- Use `install` or `reinstall` for local paths; remote daemons upload local artifacts automatically.
|
|
90
90
|
- Use `install-from-source` only for trusted, operator-approved artifact URLs the remote daemon can reach. Do not fetch arbitrary user-supplied URLs.
|
|
91
|
+
- Use `install-from-source --github-actions-artifact <org>/<repo>:<artifact>` when the remote daemon has repository credentials and supports daemon-resolved GitHub Actions artifacts.
|
|
91
92
|
- For local-path versus URL artifact rules, follow [bootstrap-install.md](bootstrap-install.md).
|
|
92
93
|
|
|
93
94
|
Use `agent-device connection status --session adc-android` to inspect the active connection without reading JSON state manually. Status output must not include auth tokens.
|
|
@@ -120,7 +121,7 @@ Optional overrides stay available for advanced cases:
|
|
|
120
121
|
}
|
|
121
122
|
```
|
|
122
123
|
|
|
123
|
-
- Keep
|
|
124
|
+
- Keep service tokens in env/config managed by the operator boundary. Do not persist auth tokens in connection state. Human login uses `agent-device auth login` or implicit `connect` login and stores only the CLI session credential.
|
|
124
125
|
- Omit Metro fields for non-React Native flows.
|
|
125
126
|
- Put `tenant`, `runId`, and `sessionIsolation` in the remote profile so agents can run `agent-device connect --remote-config ./remote-config.json` without extra scope flags. Add `platform`, `leaseBackend`, `session`, or Metro overrides only when the default inference is not enough for that flow.
|
|
126
127
|
- Explicit command-line flags override connected defaults. Use them intentionally when switching session, platform, target, tenant, run, or lease scope.
|
|
@@ -134,31 +135,49 @@ Optional overrides stay available for advanced cases:
|
|
|
134
135
|
|
|
135
136
|
- Start the daemon in HTTP mode with `AGENT_DEVICE_DAEMON_SERVER_MODE=http|dual` on the host.
|
|
136
137
|
- Point the profile or env at the remote host with `daemonBaseUrl` or `AGENT_DEVICE_DAEMON_BASE_URL=http(s)://host:port[/base-path]`.
|
|
137
|
-
- For
|
|
138
|
-
-
|
|
138
|
+
- For humans, run `connect --remote-config <path>` and let it refresh or create the CLI session. Use `agent-device auth status` to inspect it and `agent-device auth logout` to remove it.
|
|
139
|
+
- For CI/non-interactive shells, set `AGENT_DEVICE_DAEMON_AUTH_TOKEN=adc_live_...` or pass `--daemon-auth-token`. The client does not start device-code polling in CI by default.
|
|
139
140
|
- Prefer an auth hook such as `AGENT_DEVICE_HTTP_AUTH_HOOK` when the host needs caller validation or tenant injection.
|
|
140
141
|
|
|
141
|
-
##
|
|
142
|
+
## Lease debug fallback
|
|
143
|
+
|
|
144
|
+
The main agent flow should use `connect` and `connection status`. For daemon-side auth, scope, or lease debugging, inspect host-side daemon logs and operator tooling instead of issuing raw daemon RPC from the agent shell.
|
|
145
|
+
|
|
146
|
+
## GitHub Actions artifact install
|
|
142
147
|
|
|
143
|
-
|
|
148
|
+
Use this when a compatible remote daemon resolves GitHub Actions artifacts server-side. Do not download CI artifacts locally or add a local `GITHUB_TOKEN` just to install CI output.
|
|
149
|
+
|
|
150
|
+
Artifact ID shape:
|
|
144
151
|
|
|
145
152
|
```bash
|
|
146
|
-
|
|
147
|
-
-
|
|
148
|
-
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
153
|
+
agent-device install-from-source \
|
|
154
|
+
--github-actions-artifact OWNER/REPO:1234567890 \
|
|
155
|
+
--remote-config ./remote-config.json \
|
|
156
|
+
--platform android
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
Artifact-name shape:
|
|
160
|
+
|
|
161
|
+
```bash
|
|
162
|
+
agent-device install-from-source \
|
|
163
|
+
--github-actions-artifact OWNER/REPO:app-debug \
|
|
164
|
+
--remote-config ./remote-config.json \
|
|
165
|
+
--platform ios
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
Config shape:
|
|
169
|
+
|
|
170
|
+
```json
|
|
171
|
+
{
|
|
172
|
+
"installSource": {
|
|
173
|
+
"type": "github-actions-artifact",
|
|
174
|
+
"repo": "OWNER/REPO",
|
|
175
|
+
"artifact": "app-debug"
|
|
176
|
+
}
|
|
177
|
+
}
|
|
159
178
|
```
|
|
160
179
|
|
|
161
|
-
|
|
180
|
+
Numeric artifacts are passed as artifact IDs. Non-numeric artifacts are passed as artifact names.
|
|
162
181
|
|
|
163
182
|
## Failure semantics and trust notes
|
|
164
183
|
|
|
@@ -44,6 +44,8 @@ agent-device react-devtools profile rerenders --limit 5
|
|
|
44
44
|
- Labels like `@c5` reset when the app reloads or components remount. After reload, run `wait --connected` and inspect again.
|
|
45
45
|
- Profiling only captures renders between `profile start` and `profile stop`.
|
|
46
46
|
- On Android, set `adb reverse tcp:8097 tcp:8097` for React DevTools. If Metro is local, also set `adb reverse tcp:8081 tcp:8081`.
|
|
47
|
+
- For Android sessions connected through `agent-device connect --remote-config`, run `agent-device react-devtools ...` normally. The CLI registers a bridge companion tunnel to the local DevTools daemon on `127.0.0.1:8097` and unregisters it when the command exits.
|
|
48
|
+
- Remote Android React DevTools assumes the React Native-bundled DevTools behavior in React Native 0.83+. Do not assume older browser/Chromium DevTools workflows exist in remote sandboxes. For Expo apps, verify the SDK's bundled React Native version and runtime behavior first; no Expo SDK version is separately verified by this skill.
|
|
47
49
|
|
|
48
50
|
## References
|
|
49
51
|
|
package/dist/src/320.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
let E="--agent-device-run-metro-companion",_="AGENT_DEVICE_METRO_COMPANION_SERVER_BASE_URL",N="AGENT_DEVICE_METRO_COMPANION_BEARER_TOKEN",A="AGENT_DEVICE_METRO_COMPANION_LOCAL_BASE_URL",O="AGENT_DEVICE_METRO_COMPANION_LAUNCH_URL",e="AGENT_DEVICE_METRO_COMPANION_STATE_PATH",T="AGENT_DEVICE_METRO_COMPANION_SCOPE_TENANT_ID",C="AGENT_DEVICE_METRO_COMPANION_SCOPE_RUN_ID",R="AGENT_DEVICE_METRO_COMPANION_SCOPE_LEASE_ID";function I(E){let _=E.length;for(;_>0&&47===E.charCodeAt(_-1);)_-=1;return _===E.length?E:E.slice(0,_)}function r(E,_){let N=new URL(`${I(E)}/index.bundle`);return N.searchParams.set("platform",_),N.searchParams.set("dev","true"),N.searchParams.set("minify","false"),N.toString()}export{N as ENV_BEARER_TOKEN,O as ENV_LAUNCH_URL,A as ENV_LOCAL_BASE_URL,R as ENV_SCOPE_LEASE_ID,C as ENV_SCOPE_RUN_ID,T as ENV_SCOPE_TENANT_ID,_ as ENV_SERVER_BASE_URL,e as ENV_STATE_PATH,E as METRO_COMPANION_RUN_ARG,r as buildBundleUrl,I as normalizeBaseUrl};
|
package/dist/src/3883.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{runCmdSync as e}from"./9818.js";import{sleep as t}from"./4829.js";let r=[/(^|[/\s"'=])dist\/src\/daemon\.js($|[\s"'])/,/(^|[/\s"'=])src\/daemon\.ts($|[\s"'])/];function n(e){if(!Number.isInteger(e)||e<=0)return!1;try{return process.kill(e,0),!0}catch(e){return"EPERM"===e.code}}function i(t){if(!Number.isInteger(t)||t<=0)return null;try{let r=e("ps",["-p",String(t),"-o","lstart="],{allowFailure:!0,timeoutMs:1e3});if(0!==r.exitCode)return null;let n=r.stdout.trim();return n.length>0?n:null}catch{return null}}function o(t){if(!Number.isInteger(t)||t<=0)return null;try{let r=e("ps",["-p",String(t),"-o","command="],{allowFailure:!0,timeoutMs:1e3});if(0!==r.exitCode)return null;let n=r.stdout.trim();return n.length>0?n:null}catch{return null}}function l(e,t){let l;if(!n(e))return!1;if(t){let r=i(e);if(!r||r!==t)return!1}let s=o(e);return!!s&&!!(l=s.toLowerCase().replaceAll("\\","/")).includes("agent-device")&&r.some(e=>e.test(l))}function s(e,t){try{return process.kill(e,t),!0}catch(t){let e=t.code;if("ESRCH"===e||"EPERM"===e)return!1;throw t}}async function u(e,r){if(!n(e))return!0;let i=Date.now();for(;Date.now()-i<r;)if(await t(50),!n(e))return!0;return!n(e)}async function c(e,t){!l(e,t.expectedStartTime)||!s(e,"SIGTERM")||await u(e,t.termTimeoutMs)||s(e,"SIGKILL")&&await u(e,t.killTimeoutMs)}export{l as isAgentDeviceDaemonProcess,n as isProcessAlive,o as readProcessCommand,i as readProcessStartTime,c as stopProcessForTakeover,u as waitForProcessExit};
|
package/dist/src/8164.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{promises as t}from"node:fs";import o from"node:os";import e from"node:path";let r=["emulator","platform-tools",e.join("cmdline-tools","latest","bin"),e.join("cmdline-tools","tools","bin")];function n(t){let o=new Set,e=[];for(let r of t){let t=r.trim();!t||o.has(t)||(o.add(t),e.push(t))}return e}function i(t=process.env){let r=t.ANDROID_SDK_ROOT?.trim(),l=t.ANDROID_HOME?.trim(),s=t.HOME?.trim()||o.homedir();return n([r??"",l??"",s?e.join(s,"Android","Sdk"):""])}async function l(o){try{return await t.access(o,t.constants.X_OK),!0}catch{return!1}}async function s(t=process.env){let o,m=[];for(let n of i(t)){let t=[];for(let o of r){let r=e.join(n,o);await l(r)&&t.push(r)}0!==t.length&&(o||(o=n),m.push(...t))}if(o&&(t.ANDROID_SDK_ROOT=t.ANDROID_SDK_ROOT?.trim()||o,t.ANDROID_HOME=t.ANDROID_HOME?.trim()||o),0===m.length)return;let d=(t.PATH??"").split(e.delimiter).map(t=>t.trim()).filter(t=>t.length>0);t.PATH=n([...m,...d]).join(e.delimiter)}export{s as ensureAndroidSdkPathConfigured,i as resolveAndroidSdkRoots};
|