@swmansion/argent 0.30.2-next.14 → 0.30.2-next.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli-cmds.mjs +22 -6
- package/dist/client.js +21 -5
- package/dist/installer.mjs +2 -1
- package/dist/mcp-server.mjs +30 -8
- package/dist/tool-server.cjs +268 -53
- package/package.json +1 -1
- package/skills/argent-native-profiler/SKILL.md +1 -0
- package/skills/argent-react-native-profiler/SKILL.md +2 -0
package/dist/cli-cmds.mjs
CHANGED
|
@@ -9855,6 +9855,7 @@ var FAILURE_CODES = {
|
|
|
9855
9855
|
REACT_PROFILER_DEVTOOLS_RENDERER_MISSING: "REACT_PROFILER_DEVTOOLS_RENDERER_MISSING",
|
|
9856
9856
|
REACT_PROFILER_START_FAILED: "REACT_PROFILER_START_FAILED",
|
|
9857
9857
|
REACT_PROFILER_START_VERIFY_FAILED: "REACT_PROFILER_START_VERIFY_FAILED",
|
|
9858
|
+
REACT_PROFILER_SESSION_TORN_DOWN: "REACT_PROFILER_SESSION_TORN_DOWN",
|
|
9858
9859
|
REACT_PROFILER_HOOK_ERROR: "REACT_PROFILER_HOOK_ERROR",
|
|
9859
9860
|
REACT_PROFILER_ANALYZE_NO_DATA: "REACT_PROFILER_ANALYZE_NO_DATA",
|
|
9860
9861
|
NATIVE_PROFILER_FACTORY_OPTIONS_MISSING: "NATIVE_PROFILER_FACTORY_OPTIONS_MISSING",
|
|
@@ -30810,8 +30811,13 @@ async function consumeToolStream(name, body, onProgress, signal) {
|
|
|
30810
30811
|
if (msg.event === "progress") {
|
|
30811
30812
|
progress++;
|
|
30812
30813
|
onProgress(msg.data);
|
|
30813
|
-
} else if (msg.event === "result")
|
|
30814
|
-
|
|
30814
|
+
} else if (msg.event === "result") {
|
|
30815
|
+
final = {
|
|
30816
|
+
data: msg.data,
|
|
30817
|
+
note: msg.note,
|
|
30818
|
+
...msg.profiling === true ? { profiling: true } : {}
|
|
30819
|
+
};
|
|
30820
|
+
} else if (msg.event === "error") {
|
|
30815
30821
|
throw new ToolInvocationError(msg.error ?? "tool invocation failed", {
|
|
30816
30822
|
errorCode: msg.error_code,
|
|
30817
30823
|
errorKind: msg.error_kind
|
|
@@ -30858,7 +30864,11 @@ async function consumeToolStream(name, body, onProgress, signal) {
|
|
|
30858
30864
|
if (!final) {
|
|
30859
30865
|
throw brokenStream(name, "the stream ended without a result", progress);
|
|
30860
30866
|
}
|
|
30861
|
-
return {
|
|
30867
|
+
return {
|
|
30868
|
+
data: final.data,
|
|
30869
|
+
note: final.note,
|
|
30870
|
+
...final.profiling ? { profiling: true } : {}
|
|
30871
|
+
};
|
|
30862
30872
|
}
|
|
30863
30873
|
function errorBodyMessage(body) {
|
|
30864
30874
|
if (Array.isArray(body.issues) && typeof body.message === "string") return body.message;
|
|
@@ -31031,7 +31041,8 @@ function createToolsClient(options = {}) {
|
|
|
31031
31041
|
return {
|
|
31032
31042
|
data: await settle2(streamed.data),
|
|
31033
31043
|
note: streamed.note,
|
|
31034
|
-
outputHint: meta3?.outputHint
|
|
31044
|
+
outputHint: meta3?.outputHint,
|
|
31045
|
+
...streamed.profiling ? { profiling: true } : {}
|
|
31035
31046
|
};
|
|
31036
31047
|
}
|
|
31037
31048
|
let json2;
|
|
@@ -31056,7 +31067,12 @@ function createToolsClient(options = {}) {
|
|
|
31056
31067
|
});
|
|
31057
31068
|
}
|
|
31058
31069
|
opts?.signal?.throwIfAborted();
|
|
31059
|
-
return {
|
|
31070
|
+
return {
|
|
31071
|
+
data: await settle2(json2.data),
|
|
31072
|
+
note: json2.note,
|
|
31073
|
+
outputHint: meta3?.outputHint,
|
|
31074
|
+
...json2.profiling === true ? { profiling: true } : {}
|
|
31075
|
+
};
|
|
31060
31076
|
}
|
|
31061
31077
|
return { fetchTools, fetchTool, callTool, baseUrl };
|
|
31062
31078
|
}
|
|
@@ -35578,7 +35594,7 @@ var _CI_VENDOR_COUNT_FOR_TEST = vendors_default.length;
|
|
|
35578
35594
|
var SESSION_ID2 = randomUUID5();
|
|
35579
35595
|
function readCliVersion() {
|
|
35580
35596
|
if (true) {
|
|
35581
|
-
return "0.30.2-next.
|
|
35597
|
+
return "0.30.2-next.15";
|
|
35582
35598
|
}
|
|
35583
35599
|
return "0.0.0";
|
|
35584
35600
|
}
|
package/dist/client.js
CHANGED
|
@@ -9059,6 +9059,7 @@ var FAILURE_CODES = {
|
|
|
9059
9059
|
REACT_PROFILER_DEVTOOLS_RENDERER_MISSING: "REACT_PROFILER_DEVTOOLS_RENDERER_MISSING",
|
|
9060
9060
|
REACT_PROFILER_START_FAILED: "REACT_PROFILER_START_FAILED",
|
|
9061
9061
|
REACT_PROFILER_START_VERIFY_FAILED: "REACT_PROFILER_START_VERIFY_FAILED",
|
|
9062
|
+
REACT_PROFILER_SESSION_TORN_DOWN: "REACT_PROFILER_SESSION_TORN_DOWN",
|
|
9062
9063
|
REACT_PROFILER_HOOK_ERROR: "REACT_PROFILER_HOOK_ERROR",
|
|
9063
9064
|
REACT_PROFILER_ANALYZE_NO_DATA: "REACT_PROFILER_ANALYZE_NO_DATA",
|
|
9064
9065
|
NATIVE_PROFILER_FACTORY_OPTIONS_MISSING: "NATIVE_PROFILER_FACTORY_OPTIONS_MISSING",
|
|
@@ -10190,8 +10191,13 @@ async function consumeToolStream(name, body, onProgress, signal) {
|
|
|
10190
10191
|
if (msg.event === "progress") {
|
|
10191
10192
|
progress++;
|
|
10192
10193
|
onProgress(msg.data);
|
|
10193
|
-
} else if (msg.event === "result")
|
|
10194
|
-
|
|
10194
|
+
} else if (msg.event === "result") {
|
|
10195
|
+
final = {
|
|
10196
|
+
data: msg.data,
|
|
10197
|
+
note: msg.note,
|
|
10198
|
+
...msg.profiling === true ? { profiling: true } : {}
|
|
10199
|
+
};
|
|
10200
|
+
} else if (msg.event === "error") {
|
|
10195
10201
|
throw new ToolInvocationError(msg.error ?? "tool invocation failed", {
|
|
10196
10202
|
errorCode: msg.error_code,
|
|
10197
10203
|
errorKind: msg.error_kind
|
|
@@ -10238,7 +10244,11 @@ async function consumeToolStream(name, body, onProgress, signal) {
|
|
|
10238
10244
|
if (!final) {
|
|
10239
10245
|
throw brokenStream(name, "the stream ended without a result", progress);
|
|
10240
10246
|
}
|
|
10241
|
-
return {
|
|
10247
|
+
return {
|
|
10248
|
+
data: final.data,
|
|
10249
|
+
note: final.note,
|
|
10250
|
+
...final.profiling ? { profiling: true } : {}
|
|
10251
|
+
};
|
|
10242
10252
|
}
|
|
10243
10253
|
function errorBodyMessage(body) {
|
|
10244
10254
|
if (Array.isArray(body.issues) && typeof body.message === "string") return body.message;
|
|
@@ -10411,7 +10421,8 @@ function createToolsClient(options = {}) {
|
|
|
10411
10421
|
return {
|
|
10412
10422
|
data: await settle(streamed.data),
|
|
10413
10423
|
note: streamed.note,
|
|
10414
|
-
outputHint: meta?.outputHint
|
|
10424
|
+
outputHint: meta?.outputHint,
|
|
10425
|
+
...streamed.profiling ? { profiling: true } : {}
|
|
10415
10426
|
};
|
|
10416
10427
|
}
|
|
10417
10428
|
let json;
|
|
@@ -10436,7 +10447,12 @@ function createToolsClient(options = {}) {
|
|
|
10436
10447
|
});
|
|
10437
10448
|
}
|
|
10438
10449
|
opts?.signal?.throwIfAborted();
|
|
10439
|
-
return {
|
|
10450
|
+
return {
|
|
10451
|
+
data: await settle(json.data),
|
|
10452
|
+
note: json.note,
|
|
10453
|
+
outputHint: meta?.outputHint,
|
|
10454
|
+
...json.profiling === true ? { profiling: true } : {}
|
|
10455
|
+
};
|
|
10440
10456
|
}
|
|
10441
10457
|
return { fetchTools, fetchTool, callTool, baseUrl };
|
|
10442
10458
|
}
|
package/dist/installer.mjs
CHANGED
|
@@ -15962,6 +15962,7 @@ var FAILURE_CODES = {
|
|
|
15962
15962
|
REACT_PROFILER_DEVTOOLS_RENDERER_MISSING: "REACT_PROFILER_DEVTOOLS_RENDERER_MISSING",
|
|
15963
15963
|
REACT_PROFILER_START_FAILED: "REACT_PROFILER_START_FAILED",
|
|
15964
15964
|
REACT_PROFILER_START_VERIFY_FAILED: "REACT_PROFILER_START_VERIFY_FAILED",
|
|
15965
|
+
REACT_PROFILER_SESSION_TORN_DOWN: "REACT_PROFILER_SESSION_TORN_DOWN",
|
|
15965
15966
|
REACT_PROFILER_HOOK_ERROR: "REACT_PROFILER_HOOK_ERROR",
|
|
15966
15967
|
REACT_PROFILER_ANALYZE_NO_DATA: "REACT_PROFILER_ANALYZE_NO_DATA",
|
|
15967
15968
|
NATIVE_PROFILER_FACTORY_OPTIONS_MISSING: "NATIVE_PROFILER_FACTORY_OPTIONS_MISSING",
|
|
@@ -16899,7 +16900,7 @@ var _CI_VENDOR_COUNT_FOR_TEST = vendors_default.length;
|
|
|
16899
16900
|
var SESSION_ID = randomUUID4();
|
|
16900
16901
|
function readCliVersion() {
|
|
16901
16902
|
if (true) {
|
|
16902
|
-
return "0.30.2-next.
|
|
16903
|
+
return "0.30.2-next.15";
|
|
16903
16904
|
}
|
|
16904
16905
|
return "0.0.0";
|
|
16905
16906
|
}
|
package/dist/mcp-server.mjs
CHANGED
|
@@ -25314,6 +25314,7 @@ var FAILURE_CODES = {
|
|
|
25314
25314
|
REACT_PROFILER_DEVTOOLS_RENDERER_MISSING: "REACT_PROFILER_DEVTOOLS_RENDERER_MISSING",
|
|
25315
25315
|
REACT_PROFILER_START_FAILED: "REACT_PROFILER_START_FAILED",
|
|
25316
25316
|
REACT_PROFILER_START_VERIFY_FAILED: "REACT_PROFILER_START_VERIFY_FAILED",
|
|
25317
|
+
REACT_PROFILER_SESSION_TORN_DOWN: "REACT_PROFILER_SESSION_TORN_DOWN",
|
|
25317
25318
|
REACT_PROFILER_HOOK_ERROR: "REACT_PROFILER_HOOK_ERROR",
|
|
25318
25319
|
REACT_PROFILER_ANALYZE_NO_DATA: "REACT_PROFILER_ANALYZE_NO_DATA",
|
|
25319
25320
|
NATIVE_PROFILER_FACTORY_OPTIONS_MISSING: "NATIVE_PROFILER_FACTORY_OPTIONS_MISSING",
|
|
@@ -26486,8 +26487,13 @@ async function consumeToolStream(name, body, onProgress, signal) {
|
|
|
26486
26487
|
if (msg.event === "progress") {
|
|
26487
26488
|
progress++;
|
|
26488
26489
|
onProgress(msg.data);
|
|
26489
|
-
} else if (msg.event === "result")
|
|
26490
|
-
|
|
26490
|
+
} else if (msg.event === "result") {
|
|
26491
|
+
final = {
|
|
26492
|
+
data: msg.data,
|
|
26493
|
+
note: msg.note,
|
|
26494
|
+
...msg.profiling === true ? { profiling: true } : {}
|
|
26495
|
+
};
|
|
26496
|
+
} else if (msg.event === "error") {
|
|
26491
26497
|
throw new ToolInvocationError(msg.error ?? "tool invocation failed", {
|
|
26492
26498
|
errorCode: msg.error_code,
|
|
26493
26499
|
errorKind: msg.error_kind
|
|
@@ -26534,7 +26540,11 @@ async function consumeToolStream(name, body, onProgress, signal) {
|
|
|
26534
26540
|
if (!final) {
|
|
26535
26541
|
throw brokenStream(name, "the stream ended without a result", progress);
|
|
26536
26542
|
}
|
|
26537
|
-
return {
|
|
26543
|
+
return {
|
|
26544
|
+
data: final.data,
|
|
26545
|
+
note: final.note,
|
|
26546
|
+
...final.profiling ? { profiling: true } : {}
|
|
26547
|
+
};
|
|
26538
26548
|
}
|
|
26539
26549
|
function errorBodyMessage(body) {
|
|
26540
26550
|
if (Array.isArray(body.issues) && typeof body.message === "string") return body.message;
|
|
@@ -26707,7 +26717,8 @@ function createToolsClient(options = {}) {
|
|
|
26707
26717
|
return {
|
|
26708
26718
|
data: await settle2(streamed.data),
|
|
26709
26719
|
note: streamed.note,
|
|
26710
|
-
outputHint: meta2?.outputHint
|
|
26720
|
+
outputHint: meta2?.outputHint,
|
|
26721
|
+
...streamed.profiling ? { profiling: true } : {}
|
|
26711
26722
|
};
|
|
26712
26723
|
}
|
|
26713
26724
|
let json;
|
|
@@ -26732,7 +26743,12 @@ function createToolsClient(options = {}) {
|
|
|
26732
26743
|
});
|
|
26733
26744
|
}
|
|
26734
26745
|
opts?.signal?.throwIfAborted();
|
|
26735
|
-
return {
|
|
26746
|
+
return {
|
|
26747
|
+
data: await settle2(json.data),
|
|
26748
|
+
note: json.note,
|
|
26749
|
+
outputHint: meta2?.outputHint,
|
|
26750
|
+
...json.profiling === true ? { profiling: true } : {}
|
|
26751
|
+
};
|
|
26736
26752
|
}
|
|
26737
26753
|
return { fetchTools, fetchTool, callTool, baseUrl };
|
|
26738
26754
|
}
|
|
@@ -28540,6 +28556,7 @@ var AUTO_DESCRIBE_TOOLS = /* @__PURE__ */ new Set([
|
|
|
28540
28556
|
function autoDescribeEnabled(options) {
|
|
28541
28557
|
return !isFlagEnabled("disable-auto-describe", options);
|
|
28542
28558
|
}
|
|
28559
|
+
var PROFILING_CAPTURE_SKIPPED_NOTE = "Auto-screenshot and element tree skipped while a profiler is recording on this device. Call screenshot or describe if you need to see the screen.";
|
|
28543
28560
|
var AUTO_DESCRIBE_HEADER = "--- Elements after action (describe) ---";
|
|
28544
28561
|
function shouldAutoDescribe(toolName) {
|
|
28545
28562
|
return AUTO_DESCRIBE_TOOLS.has(normalizeToolName(toolName));
|
|
@@ -28692,8 +28709,8 @@ function createToolCaller(deps) {
|
|
|
28692
28709
|
return {
|
|
28693
28710
|
fetchTools: client.fetchTools,
|
|
28694
28711
|
async callTool(name, args) {
|
|
28695
|
-
const { data, note, outputHint } = await client.callTool(name, args);
|
|
28696
|
-
return { result: data, outputHint, note };
|
|
28712
|
+
const { data, note, outputHint, profiling } = await client.callTool(name, args);
|
|
28713
|
+
return { result: data, outputHint, note, ...profiling ? { profiling } : {} };
|
|
28697
28714
|
}
|
|
28698
28715
|
};
|
|
28699
28716
|
}
|
|
@@ -28857,7 +28874,7 @@ ${desc}` }];
|
|
|
28857
28874
|
args: params.arguments
|
|
28858
28875
|
});
|
|
28859
28876
|
try {
|
|
28860
|
-
const { result, outputHint, note } = await callTool(params.name, params.arguments);
|
|
28877
|
+
const { result, outputHint, note, profiling } = await callTool(params.name, params.arguments);
|
|
28861
28878
|
await spyLog({
|
|
28862
28879
|
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
28863
28880
|
event: "tool_result",
|
|
@@ -28890,6 +28907,11 @@ ${desc}` }];
|
|
|
28890
28907
|
text: "Auto-screenshot and element tree skipped: the input contains a {{secret:\u2026}} placeholder, and a capture of this screen could reveal the typed secret. The secret is already typed \u2014 do not send the typing step again, or the field will hold two copies of it. Submit or navigate away, then verify the resulting screen as usual. Only this call is covered: the next call is captured normally, and shows the secret if the field is still on screen. To cover the submit as well, put the typing and the submit in ONE `run-sequence` the next time you type a secret."
|
|
28891
28908
|
}
|
|
28892
28909
|
];
|
|
28910
|
+
} else if (udid && (wantScreenshot || wantTree) && profiling) {
|
|
28911
|
+
if (params.name !== "describe") {
|
|
28912
|
+
await awaitScreenSettled(udid, params.name);
|
|
28913
|
+
content = [...content, { type: "text", text: PROFILING_CAPTURE_SKIPPED_NOTE }];
|
|
28914
|
+
}
|
|
28893
28915
|
} else if (udid && (wantScreenshot || wantTree)) {
|
|
28894
28916
|
const screenSettled = await awaitScreenSettled(udid, params.name);
|
|
28895
28917
|
const screenshot = wantScreenshot ? captureScreenshotBlocks(udid) : Promise.resolve([]);
|
package/dist/tool-server.cjs
CHANGED
|
@@ -1584,6 +1584,7 @@ var init_failure_codes = __esm({
|
|
|
1584
1584
|
REACT_PROFILER_DEVTOOLS_RENDERER_MISSING: "REACT_PROFILER_DEVTOOLS_RENDERER_MISSING",
|
|
1585
1585
|
REACT_PROFILER_START_FAILED: "REACT_PROFILER_START_FAILED",
|
|
1586
1586
|
REACT_PROFILER_START_VERIFY_FAILED: "REACT_PROFILER_START_VERIFY_FAILED",
|
|
1587
|
+
REACT_PROFILER_SESSION_TORN_DOWN: "REACT_PROFILER_SESSION_TORN_DOWN",
|
|
1587
1588
|
REACT_PROFILER_HOOK_ERROR: "REACT_PROFILER_HOOK_ERROR",
|
|
1588
1589
|
REACT_PROFILER_ANALYZE_NO_DATA: "REACT_PROFILER_ANALYZE_NO_DATA",
|
|
1589
1590
|
NATIVE_PROFILER_FACTORY_OPTIONS_MISSING: "NATIVE_PROFILER_FACTORY_OPTIONS_MISSING",
|
|
@@ -100944,7 +100945,7 @@ var _CI_VENDOR_COUNT_FOR_TEST = vendors_default.length;
|
|
|
100944
100945
|
var SESSION_ID = (0, import_node_crypto3.randomUUID)();
|
|
100945
100946
|
function readCliVersion() {
|
|
100946
100947
|
if (true) {
|
|
100947
|
-
return "0.30.2-next.
|
|
100948
|
+
return "0.30.2-next.15";
|
|
100948
100949
|
}
|
|
100949
100950
|
return "0.0.0";
|
|
100950
100951
|
}
|
|
@@ -122147,19 +122148,23 @@ async function openMoqClient(udid) {
|
|
|
122147
122148
|
async function openMoqClientFromInfo(info) {
|
|
122148
122149
|
await installNodeWebTransport();
|
|
122149
122150
|
const session = new MoqDeviceSession(await connectMoq(info), { publishPath: PUBLISH_PATH });
|
|
122150
|
-
|
|
122151
|
+
let closed = false;
|
|
122152
|
+
disposeWhenTransportDies(session, () => closed = true);
|
|
122151
122153
|
return {
|
|
122152
|
-
|
|
122154
|
+
// The SDK resolves sends on a closed session, reporting undelivered input as sent.
|
|
122155
|
+
sendControl: (payload) => closed ? Promise.reject(new Error("MoQ session is closed")) : session.sendControl(payload),
|
|
122153
122156
|
async screenshot(opts) {
|
|
122154
122157
|
return Buffer.from(await session.screenshot({ scale: opts?.scale }));
|
|
122155
122158
|
},
|
|
122156
122159
|
async close() {
|
|
122160
|
+
closed = true;
|
|
122157
122161
|
session.close();
|
|
122158
122162
|
}
|
|
122159
122163
|
};
|
|
122160
122164
|
}
|
|
122161
|
-
function disposeWhenTransportDies(session) {
|
|
122165
|
+
function disposeWhenTransportDies(session, onDispose) {
|
|
122162
122166
|
const dispose = () => {
|
|
122167
|
+
onDispose();
|
|
122163
122168
|
try {
|
|
122164
122169
|
session.close();
|
|
122165
122170
|
} catch {
|
|
@@ -122219,6 +122224,52 @@ function settleWithin(p, ms, signal) {
|
|
|
122219
122224
|
// ../tool-server/src/utils/simulator-client.ts
|
|
122220
122225
|
init_external_devices();
|
|
122221
122226
|
|
|
122227
|
+
// ../tool-server/src/utils/profiling-devices.ts
|
|
122228
|
+
var runs = /* @__PURE__ */ new Map();
|
|
122229
|
+
var servers = /* @__PURE__ */ new Map();
|
|
122230
|
+
function trackProfilingRun(deviceId, run2) {
|
|
122231
|
+
let set2 = runs.get(deviceId);
|
|
122232
|
+
if (!set2) {
|
|
122233
|
+
set2 = /* @__PURE__ */ new Set();
|
|
122234
|
+
runs.set(deviceId, set2);
|
|
122235
|
+
}
|
|
122236
|
+
set2.add(run2);
|
|
122237
|
+
syncCaptureOnDemand();
|
|
122238
|
+
}
|
|
122239
|
+
function isProfiling(deviceId) {
|
|
122240
|
+
syncCaptureOnDemand();
|
|
122241
|
+
return runs.has(deviceId);
|
|
122242
|
+
}
|
|
122243
|
+
function syncCaptureOnDemand() {
|
|
122244
|
+
for (const [deviceId, set2] of runs) {
|
|
122245
|
+
for (const run2 of set2) {
|
|
122246
|
+
if (!run2.profilingActive) set2.delete(run2);
|
|
122247
|
+
}
|
|
122248
|
+
if (set2.size === 0) runs.delete(deviceId);
|
|
122249
|
+
}
|
|
122250
|
+
for (const [deviceId, server] of servers) {
|
|
122251
|
+
const profiling = runs.has(deviceId);
|
|
122252
|
+
if (server.onDemand !== profiling) {
|
|
122253
|
+
server.onDemand = profiling;
|
|
122254
|
+
server.send(profiling);
|
|
122255
|
+
}
|
|
122256
|
+
}
|
|
122257
|
+
}
|
|
122258
|
+
function registerCaptureOnDemandSender(deviceId, endpoint, send) {
|
|
122259
|
+
const entry = { endpoint, send, onDemand: false };
|
|
122260
|
+
servers.set(deviceId, entry);
|
|
122261
|
+
syncCaptureOnDemand();
|
|
122262
|
+
return () => {
|
|
122263
|
+
if (servers.get(deviceId) !== entry) return;
|
|
122264
|
+
servers.delete(deviceId);
|
|
122265
|
+
if (entry.onDemand) entry.send(false);
|
|
122266
|
+
};
|
|
122267
|
+
}
|
|
122268
|
+
function captureOnDemandDropped(deviceId, endpoint) {
|
|
122269
|
+
const server = servers.get(deviceId);
|
|
122270
|
+
if (server?.endpoint === endpoint) server.onDemand = false;
|
|
122271
|
+
}
|
|
122272
|
+
|
|
122222
122273
|
// ../tool-server/src/utils/foldable.ts
|
|
122223
122274
|
var import_node_child_process13 = require("node:child_process");
|
|
122224
122275
|
var fs17 = __toESM(require("node:fs"));
|
|
@@ -122461,6 +122512,14 @@ var FIRST_FRAME_POLL_MS = 250;
|
|
|
122461
122512
|
var COMMAND_ACK_TIMEOUT_MS = 5e3;
|
|
122462
122513
|
var connections = /* @__PURE__ */ new Map();
|
|
122463
122514
|
var cmdId = 0;
|
|
122515
|
+
function pendingIdNamedBy(conn, message) {
|
|
122516
|
+
const named = message?.match(/unknown variant `([^`]+)`/)?.[1];
|
|
122517
|
+
if (named === void 0) return void 0;
|
|
122518
|
+
for (const [id, entry] of conn.pending) {
|
|
122519
|
+
if (entry.cmd === named) return id;
|
|
122520
|
+
}
|
|
122521
|
+
return void 0;
|
|
122522
|
+
}
|
|
122464
122523
|
function failAllPending(conn, makeError) {
|
|
122465
122524
|
const entries = [...conn.pending.values()];
|
|
122466
122525
|
conn.pending.clear();
|
|
@@ -122507,7 +122566,7 @@ function getOrCreateConnection(api) {
|
|
|
122507
122566
|
}
|
|
122508
122567
|
if (ack.status !== "ok" && ack.status !== "error") return;
|
|
122509
122568
|
if (ack.id != null && !conn.pending.has(ack.id)) return;
|
|
122510
|
-
const id = ack.id ?? conn.pending.keys().next().value;
|
|
122569
|
+
const id = ack.id ?? pendingIdNamedBy(conn, ack.message) ?? conn.pending.keys().next().value;
|
|
122511
122570
|
if (id == null) return;
|
|
122512
122571
|
const entry = conn.pending.get(id);
|
|
122513
122572
|
if (entry == null) return;
|
|
@@ -122536,6 +122595,7 @@ function getOrCreateConnection(api) {
|
|
|
122536
122595
|
ws.on("close", () => {
|
|
122537
122596
|
connections.delete(key2);
|
|
122538
122597
|
failAllPending(conn, (cmd) => transportError(cmd, key2, "the connection closed"));
|
|
122598
|
+
if (api.deviceId) captureOnDemandDropped(api.deviceId, key2);
|
|
122539
122599
|
});
|
|
122540
122600
|
connections.set(key2, conn);
|
|
122541
122601
|
return conn;
|
|
@@ -123211,6 +123271,19 @@ async function spawnSimulatorServerProcess(udid, subcommand) {
|
|
|
123211
123271
|
}, READY_TIMEOUT_MS);
|
|
123212
123272
|
});
|
|
123213
123273
|
}
|
|
123274
|
+
function withCaptureOnDemand(deviceId, instance) {
|
|
123275
|
+
const unregister = registerCaptureOnDemandSender(deviceId, instance.api.apiUrl, (enabled) => {
|
|
123276
|
+
sendCommand(instance.api, { cmd: "capture_on_demand", enabled }).catch(() => {
|
|
123277
|
+
});
|
|
123278
|
+
});
|
|
123279
|
+
return {
|
|
123280
|
+
...instance,
|
|
123281
|
+
dispose: async () => {
|
|
123282
|
+
unregister();
|
|
123283
|
+
await instance.dispose();
|
|
123284
|
+
}
|
|
123285
|
+
};
|
|
123286
|
+
}
|
|
123214
123287
|
var simulatorServerBlueprint = {
|
|
123215
123288
|
namespace: SIMULATOR_SERVER_NAMESPACE,
|
|
123216
123289
|
getURN(device) {
|
|
@@ -123255,7 +123328,7 @@ var simulatorServerBlueprint = {
|
|
|
123255
123328
|
}
|
|
123256
123329
|
const claim2 = externalClaimForAnyId(device.id);
|
|
123257
123330
|
if (claim2) {
|
|
123258
|
-
return buildAttachedInstance(device, claim2);
|
|
123331
|
+
return withCaptureOnDemand(device.id, await buildAttachedInstance(device, claim2));
|
|
123259
123332
|
}
|
|
123260
123333
|
if (device.platform === "ios-remote") {
|
|
123261
123334
|
return buildRemoteInstance(device);
|
|
@@ -123313,7 +123386,7 @@ var simulatorServerBlueprint = {
|
|
|
123313
123386
|
events
|
|
123314
123387
|
};
|
|
123315
123388
|
await attachFoldableDisplay(instance.api, device);
|
|
123316
|
-
return instance;
|
|
123389
|
+
return withCaptureOnDemand(device.id, instance);
|
|
123317
123390
|
}
|
|
123318
123391
|
};
|
|
123319
123392
|
|
|
@@ -130976,11 +131049,12 @@ function createHttpApp(registry2, options) {
|
|
|
130976
131049
|
const toolNote = takeToolNote(data);
|
|
130977
131050
|
if (toolNote) notes.push(toolNote);
|
|
130978
131051
|
const notePayload = notes.length > 0 ? { note: notes.join("\n\n") } : {};
|
|
131052
|
+
const profilingPayload = deviceArg && isProfiling(canonicalDeviceId(deviceArg) ?? deviceArg) ? { profiling: true } : {};
|
|
130979
131053
|
if (wantsStream) {
|
|
130980
|
-
writeLine({ event: "result", data, ...notePayload });
|
|
131054
|
+
writeLine({ event: "result", data, ...notePayload, ...profilingPayload });
|
|
130981
131055
|
res.end();
|
|
130982
131056
|
} else {
|
|
130983
|
-
res.json({ data, ...notePayload });
|
|
131057
|
+
res.json({ data, ...notePayload, ...profilingPayload });
|
|
130984
131058
|
}
|
|
130985
131059
|
} catch (err) {
|
|
130986
131060
|
const attribute = (message) => {
|
|
@@ -136761,6 +136835,7 @@ var reactProfilerSessionBlueprint = {
|
|
|
136761
136835
|
profileStartWallMs: null,
|
|
136762
136836
|
sessionId: null,
|
|
136763
136837
|
ownerToolServerPid: null,
|
|
136838
|
+
disposed: false,
|
|
136764
136839
|
disposeSession: () => events.emit("terminated")
|
|
136765
136840
|
};
|
|
136766
136841
|
await cdp.send("Profiler.enable").catch(warnOnError("Profiler.enable"));
|
|
@@ -136823,11 +136898,25 @@ var reactProfilerSessionBlueprint = {
|
|
|
136823
136898
|
);
|
|
136824
136899
|
};
|
|
136825
136900
|
cdp.events.on("disconnected", onDisconnected);
|
|
136901
|
+
const onCdpEvent = (method) => {
|
|
136902
|
+
if (method !== "Runtime.executionContextDestroyed" && method !== "Runtime.executionContextsCleared") {
|
|
136903
|
+
return;
|
|
136904
|
+
}
|
|
136905
|
+
if (state3.profilingActive) {
|
|
136906
|
+
state3.profilingActive = false;
|
|
136907
|
+
clearCachedProfilerPaths(state3.port, state3.deviceId);
|
|
136908
|
+
stopSamplerInNextRuntime(cdp);
|
|
136909
|
+
}
|
|
136910
|
+
events.emit("terminated");
|
|
136911
|
+
};
|
|
136912
|
+
cdp.events.on("event", onCdpEvent);
|
|
136826
136913
|
return {
|
|
136827
136914
|
api: state3,
|
|
136828
136915
|
dispose: async () => {
|
|
136916
|
+
state3.disposed = true;
|
|
136829
136917
|
cdp.events.off("scriptParsed", onScriptParsed);
|
|
136830
136918
|
cdp.events.off("disconnected", onDisconnected);
|
|
136919
|
+
cdp.events.off("event", onCdpEvent);
|
|
136831
136920
|
if (state3.profilingActive) {
|
|
136832
136921
|
state3.profilingActive = false;
|
|
136833
136922
|
await cdp.send("Runtime.evaluate", {
|
|
@@ -136842,6 +136931,20 @@ var reactProfilerSessionBlueprint = {
|
|
|
136842
136931
|
};
|
|
136843
136932
|
}
|
|
136844
136933
|
};
|
|
136934
|
+
function stopSamplerInNextRuntime(cdp) {
|
|
136935
|
+
const onEvent = (method) => {
|
|
136936
|
+
if (method !== "Runtime.executionContextCreated") return;
|
|
136937
|
+
disarm();
|
|
136938
|
+
void cdp.send("Profiler.stop").catch(() => {
|
|
136939
|
+
});
|
|
136940
|
+
};
|
|
136941
|
+
const disarm = () => {
|
|
136942
|
+
cdp.events.off("event", onEvent);
|
|
136943
|
+
cdp.events.off("disconnected", disarm);
|
|
136944
|
+
};
|
|
136945
|
+
cdp.events.on("event", onEvent);
|
|
136946
|
+
cdp.events.on("disconnected", disarm);
|
|
136947
|
+
}
|
|
136845
136948
|
var profilerPathsCache = /* @__PURE__ */ new Map();
|
|
136846
136949
|
function cacheKey(port, deviceId) {
|
|
136847
136950
|
return `${port}:${deviceId}`;
|
|
@@ -154859,6 +154962,96 @@ function classifyStaleness({
|
|
|
154859
154962
|
};
|
|
154860
154963
|
}
|
|
154861
154964
|
|
|
154965
|
+
// ../tool-server/src/utils/debugger/runtime-device.ts
|
|
154966
|
+
var import_node_crypto12 = require("node:crypto");
|
|
154967
|
+
var import_node_child_process38 = require("node:child_process");
|
|
154968
|
+
var import_node_util30 = require("node:util");
|
|
154969
|
+
init_adb();
|
|
154970
|
+
var execFileAsync30 = (0, import_node_util30.promisify)(import_node_child_process38.execFile);
|
|
154971
|
+
var LOG_READ_TIMEOUT_MS = 5e3;
|
|
154972
|
+
var RETRY_DELAY_MS = 300;
|
|
154973
|
+
async function findRuntimeDevice(cdp) {
|
|
154974
|
+
const marker = `argent-device-probe:${(0, import_node_crypto12.randomUUID)()}`;
|
|
154975
|
+
const logged = await cdp.evaluate(
|
|
154976
|
+
`(function () {
|
|
154977
|
+
if (typeof nativeLoggingHook !== "function") return false;
|
|
154978
|
+
nativeLoggingHook(${JSON.stringify(marker)}, 1);
|
|
154979
|
+
return true;
|
|
154980
|
+
})()`
|
|
154981
|
+
).catch(() => false);
|
|
154982
|
+
if (logged !== true) return void 0;
|
|
154983
|
+
const checks = [
|
|
154984
|
+
async () => firstFound((await androidSerials()).map((serial) => () => logcatHolds(serial, marker))),
|
|
154985
|
+
async () => firstFound((await bootedSimulators()).map((udid) => () => simulatorLogHolds(udid, marker)))
|
|
154986
|
+
];
|
|
154987
|
+
for (let attempt = 0; attempt < 2; attempt++) {
|
|
154988
|
+
if (attempt > 0) await new Promise((r) => setTimeout(r, RETRY_DELAY_MS));
|
|
154989
|
+
const found = await firstFound(checks);
|
|
154990
|
+
if (found !== void 0) return found;
|
|
154991
|
+
}
|
|
154992
|
+
return void 0;
|
|
154993
|
+
}
|
|
154994
|
+
function firstFound(checks) {
|
|
154995
|
+
return new Promise((resolve16) => {
|
|
154996
|
+
let left = checks.length;
|
|
154997
|
+
if (left === 0) resolve16(void 0);
|
|
154998
|
+
for (const check3 of checks) {
|
|
154999
|
+
void check3().then((id) => {
|
|
155000
|
+
if (id !== void 0) resolve16(id);
|
|
155001
|
+
else if (--left === 0) resolve16(void 0);
|
|
155002
|
+
});
|
|
155003
|
+
}
|
|
155004
|
+
});
|
|
155005
|
+
}
|
|
155006
|
+
async function androidSerials() {
|
|
155007
|
+
try {
|
|
155008
|
+
const { stdout } = await runAdb(["devices"], { timeoutMs: ADB_DEVICES_TIMEOUT_MS });
|
|
155009
|
+
return parseAdbDevices(stdout).filter((d) => d.state === "device").map((d) => d.serial);
|
|
155010
|
+
} catch {
|
|
155011
|
+
return [];
|
|
155012
|
+
}
|
|
155013
|
+
}
|
|
155014
|
+
async function bootedSimulators() {
|
|
155015
|
+
const simulators = await listIosSimulators();
|
|
155016
|
+
return simulators.filter((s) => s.state === "Booted").map((s) => s.udid);
|
|
155017
|
+
}
|
|
155018
|
+
async function logcatHolds(serial, marker) {
|
|
155019
|
+
try {
|
|
155020
|
+
const { stdout } = await runAdb(
|
|
155021
|
+
["-s", serial, "logcat", "-d", "-s", "ReactNativeJS", "-e", marker],
|
|
155022
|
+
{ timeoutMs: LOG_READ_TIMEOUT_MS }
|
|
155023
|
+
);
|
|
155024
|
+
return stdout.includes(marker) ? serial : void 0;
|
|
155025
|
+
} catch {
|
|
155026
|
+
return void 0;
|
|
155027
|
+
}
|
|
155028
|
+
}
|
|
155029
|
+
async function simulatorLogHolds(udid, marker) {
|
|
155030
|
+
try {
|
|
155031
|
+
const args = await simctlArgsForUdid(udid, [
|
|
155032
|
+
"spawn",
|
|
155033
|
+
udid,
|
|
155034
|
+
"log",
|
|
155035
|
+
"show",
|
|
155036
|
+
"--info",
|
|
155037
|
+
"--last",
|
|
155038
|
+
"1m",
|
|
155039
|
+
"--style",
|
|
155040
|
+
"compact",
|
|
155041
|
+
"--predicate",
|
|
155042
|
+
`eventMessage CONTAINS ${JSON.stringify(marker)} AND process != "log"`
|
|
155043
|
+
]);
|
|
155044
|
+
const { stdout } = await execFileAsync30("xcrun", args, {
|
|
155045
|
+
timeout: LOG_READ_TIMEOUT_MS,
|
|
155046
|
+
killSignal: SIMCTL_KILL_SIGNAL,
|
|
155047
|
+
encoding: "utf-8"
|
|
155048
|
+
});
|
|
155049
|
+
return stdout.includes(marker) ? udid : void 0;
|
|
155050
|
+
} catch {
|
|
155051
|
+
return void 0;
|
|
155052
|
+
}
|
|
155053
|
+
}
|
|
155054
|
+
|
|
154862
155055
|
// ../tool-server/src/utils/react-profiler/devtools-bootstrap.ts
|
|
154863
155056
|
function bootstrapFailureMessage(bootstrap) {
|
|
154864
155057
|
switch (bootstrap.reason) {
|
|
@@ -154881,6 +155074,7 @@ function bootstrapFailureMessage(bootstrap) {
|
|
|
154881
155074
|
// ../tool-server/src/tools/profiler/react/react-profiler-start.ts
|
|
154882
155075
|
var NO_DEVTOOLS_HOOK_ERROR = "React DevTools hook (__REACT_DEVTOOLS_GLOBAL_HOOK__) is not present in this app's JavaScript runtime. React profiling requires a development build with React DevTools enabled. Likely causes: (1) the app is a release/production build \u2014 DevTools is stripped to reduce bundle size; (2) you connected to the wrong JS runtime; (3) this isn't a React (Native) app. Fix: rebuild in debug/dev mode (e.g. `npx react-native run-ios` without --configuration Release; for Expo, run a dev client). Once the app is running with DevTools attached, call react-profiler-start again.";
|
|
154883
155076
|
var NO_RENDERERS_ATTACHED_ERROR = "React DevTools hook is present but no React renderer has registered yet. The hook is loaded but no fiber renderer has attached \u2014 typically because the app has not committed its first render, or the DevTools backend has not been bootstrapped on a bridgeless React Native dev build. Fix: ensure the app has rendered (interact with it once, then retry); if it stays empty, call react-profiler-start first \u2014 it will attempt to attach the DevTools backend automatically.";
|
|
155077
|
+
var UNKNOWN_DEVICE_NOTE = "Two or more devices share this Metro, and Argent could not tell which of them runs this app. So taps and swipes on that device still return a screenshot and an element tree, and the capture loads the app while the profiler records. To avoid this, run the app on its own Metro port.";
|
|
154884
155078
|
var zodSchema45 = external_exports.object({
|
|
154885
155079
|
port: metroPortField,
|
|
154886
155080
|
device_id: external_exports.string().describe(
|
|
@@ -155056,6 +155250,7 @@ Fails if the Hermes runtime is not reachable or the Metro CDP connection cannot
|
|
|
155056
155250
|
await cdp.send("Profiler.stop").catch(ignore);
|
|
155057
155251
|
api.profilingActive = false;
|
|
155058
155252
|
}
|
|
155253
|
+
const runtimeDevice = isLogicalKeyedDevice(api.deviceId) ? await findRuntimeDevice(cdp) : void 0;
|
|
155059
155254
|
const sessionId = crypto6.randomUUID();
|
|
155060
155255
|
const ownerPayload = {
|
|
155061
155256
|
sessionId,
|
|
@@ -155100,6 +155295,19 @@ Fails if the Hermes runtime is not reachable or the Metro CDP connection cannot
|
|
|
155100
155295
|
}
|
|
155101
155296
|
);
|
|
155102
155297
|
}
|
|
155298
|
+
if (api.disposed) {
|
|
155299
|
+
await cdp.evaluate(STOP_FOR_TAKEOVER_SCRIPT).catch(ignore);
|
|
155300
|
+
await cdp.send("Profiler.stop").catch(ignore);
|
|
155301
|
+
throw new FailureError(
|
|
155302
|
+
`The React profiler session for ${api.deviceId} was torn down while the profiler was starting, so nothing is recorded. One tool-server serves every agent using this argent install, so another agent may have run stop-all-simulator-servers. Call react-profiler-start again.`,
|
|
155303
|
+
{
|
|
155304
|
+
error_code: FAILURE_CODES.REACT_PROFILER_SESSION_TORN_DOWN,
|
|
155305
|
+
failure_stage: "react_profiler_start_session_torn_down",
|
|
155306
|
+
failure_area: "tool_server",
|
|
155307
|
+
error_kind: "not_found"
|
|
155308
|
+
}
|
|
155309
|
+
);
|
|
155310
|
+
}
|
|
155103
155311
|
const startedAtEpochMs = startResult.startedAtEpochMs ?? Date.now();
|
|
155104
155312
|
clearCachedProfilerPaths(api.port, api.deviceId);
|
|
155105
155313
|
api.sessionPaths = null;
|
|
@@ -155110,11 +155318,14 @@ Fails if the Hermes runtime is not reachable or the Metro CDP connection cannot
|
|
|
155110
155318
|
api.profileStartWallMs = startedAtEpochMs;
|
|
155111
155319
|
api.sessionId = sessionId;
|
|
155112
155320
|
api.ownerToolServerPid = process.pid;
|
|
155321
|
+
trackProfilingRun(api.deviceId, api);
|
|
155322
|
+
if (runtimeDevice) trackProfilingRun(runtimeDevice, api);
|
|
155113
155323
|
return {
|
|
155114
155324
|
started_at: new Date(startedAtEpochMs).toISOString(),
|
|
155115
155325
|
startedAtEpochMs,
|
|
155116
155326
|
hermes_version: api.hermesVersion,
|
|
155117
|
-
detected_architecture: api.detectedArchitecture
|
|
155327
|
+
detected_architecture: api.detectedArchitecture,
|
|
155328
|
+
...isLogicalKeyedDevice(api.deviceId) && !runtimeDevice ? { [RESULT_NOTE_KEY]: UNKNOWN_DEVICE_NOTE } : {}
|
|
155118
155329
|
};
|
|
155119
155330
|
}
|
|
155120
155331
|
};
|
|
@@ -155307,7 +155518,7 @@ Fails if no active profiling session exists or the CDP connection was lost durin
|
|
|
155307
155518
|
}
|
|
155308
155519
|
if (!api.profilingActive) {
|
|
155309
155520
|
throw new FailureError(
|
|
155310
|
-
"No active profiling run to stop.
|
|
155521
|
+
"No active profiling run to stop. Either the run ended without its data (a JS reload ends it: Metro's `r`, a red-box Reload, debugger-reload-metro), or Hermes CPU sampling was never started \u2014 typically because react-profiler-start failed before reaching the sampler (often on release builds without React DevTools). After a reload, call react-profiler-start again. Otherwise check the error react-profiler-start returned, address the underlying cause (rebuild in dev mode, reconnect the debugger, etc.), then call react-profiler-start again.",
|
|
155311
155522
|
{
|
|
155312
155523
|
error_code: FAILURE_CODES.REACT_PROFILER_NO_ACTIVE_SESSION,
|
|
155313
155524
|
failure_stage: "react_profiler_stop_inactive",
|
|
@@ -158171,8 +158382,8 @@ var import_util14 = require("util");
|
|
|
158171
158382
|
var DEFAULT_EXEC_TIMEOUT_MS = 6e4;
|
|
158172
158383
|
var DEFAULT_EXEC_MAX_BUFFER = 256 * 1024 * 1024;
|
|
158173
158384
|
async function execFileAsyncWithTimeout(file2, args, options = {}) {
|
|
158174
|
-
const
|
|
158175
|
-
const { stdout, stderr } = await
|
|
158385
|
+
const execFileAsync35 = (0, import_util14.promisify)(import_child_process2.execFile);
|
|
158386
|
+
const { stdout, stderr } = await execFileAsync35(file2, args, {
|
|
158176
158387
|
encoding: "utf-8",
|
|
158177
158388
|
...options,
|
|
158178
158389
|
// Applied after ...options so a caller cannot weaken the guards; maxBuffer
|
|
@@ -159704,7 +159915,7 @@ var STARTUP_TIMEOUT_MS = 1e4;
|
|
|
159704
159915
|
var DETECT_RUNNING_APP_TIMEOUT_MS = 1e4;
|
|
159705
159916
|
var NOTIFY_REGISTER_TIMEOUT_MS = 2e3;
|
|
159706
159917
|
var MAX_START_ATTEMPTS = 2;
|
|
159707
|
-
var
|
|
159918
|
+
var RETRY_DELAY_MS2 = 1200;
|
|
159708
159919
|
var COLD_START_SIGNATURE = "Cannot find process matching name:";
|
|
159709
159920
|
var STOP_GRACE_MS = 3e5;
|
|
159710
159921
|
var STOP_TERM_MS = 5e3;
|
|
@@ -160128,10 +160339,10 @@ async function startNativeProfilerIos(api, params) {
|
|
|
160128
160339
|
if (!isColdStart) throw err;
|
|
160129
160340
|
if (attempt >= MAX_START_ATTEMPTS) break;
|
|
160130
160341
|
process.stderr.write(
|
|
160131
|
-
`[native-profiler] xctrace could not find "${appProcess}" on attempt ${attempt}/${MAX_START_ATTEMPTS}; waiting ${
|
|
160342
|
+
`[native-profiler] xctrace could not find "${appProcess}" on attempt ${attempt}/${MAX_START_ATTEMPTS}; waiting ${RETRY_DELAY_MS2} ms for cold-start to settle, then retrying.
|
|
160132
160343
|
`
|
|
160133
160344
|
);
|
|
160134
|
-
await new Promise((r) => setTimeout(r,
|
|
160345
|
+
await new Promise((r) => setTimeout(r, RETRY_DELAY_MS2));
|
|
160135
160346
|
}
|
|
160136
160347
|
}
|
|
160137
160348
|
const totalMs = Date.now() - startMs;
|
|
@@ -161589,12 +161800,16 @@ Fails if no app is running on the device, or the profiler cannot attach to the p
|
|
|
161589
161800
|
const api = services.session;
|
|
161590
161801
|
const device = resolveDevice(params.device_id);
|
|
161591
161802
|
assertSupported("native-profiler-start", capability30, device);
|
|
161803
|
+
let started;
|
|
161592
161804
|
if (api.platform === "ios") {
|
|
161593
161805
|
await ensureDeps(["xcrun"]);
|
|
161594
|
-
|
|
161806
|
+
started = await startNativeProfilerIos(api, params);
|
|
161807
|
+
} else {
|
|
161808
|
+
await ensureDeps(["adb"]);
|
|
161809
|
+
started = await startNativeProfilerAndroid(api, params);
|
|
161595
161810
|
}
|
|
161596
|
-
|
|
161597
|
-
return
|
|
161811
|
+
trackProfilingRun(device.id, api);
|
|
161812
|
+
return started;
|
|
161598
161813
|
}
|
|
161599
161814
|
};
|
|
161600
161815
|
|
|
@@ -162221,7 +162436,7 @@ var WATERMARK_PNG_HEIGHT = 277;
|
|
|
162221
162436
|
var WATERMARK_PNG_BASE64 = "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";
|
|
162222
162437
|
|
|
162223
162438
|
// ../tool-server/src/tools/screen-recording/watermark.ts
|
|
162224
|
-
var
|
|
162439
|
+
var execFileAsync31 = (0, import_util15.promisify)(import_child_process6.execFile);
|
|
162225
162440
|
var OUTPUT_FPS = 30;
|
|
162226
162441
|
var FFMPEG_FALLBACK_PATHS = [
|
|
162227
162442
|
"/opt/homebrew/bin/ffmpeg",
|
|
@@ -162238,7 +162453,7 @@ var MASK_DARK_MAX_LUMA = 90;
|
|
|
162238
162453
|
var MASK_LIGHT_MIN_LUMA = 165;
|
|
162239
162454
|
async function resolveBinary(name, fallbacks) {
|
|
162240
162455
|
try {
|
|
162241
|
-
await
|
|
162456
|
+
await execFileAsync31("/bin/sh", ["-c", `command -v ${name}`], { timeout: 2e3 });
|
|
162242
162457
|
return name;
|
|
162243
162458
|
} catch {
|
|
162244
162459
|
}
|
|
@@ -165049,7 +165264,7 @@ Returns { stopped } - the URNs of the services that were actually live and got s
|
|
|
165049
165264
|
|
|
165050
165265
|
// ../tool-server/src/tools/simulator/stop-metro.ts
|
|
165051
165266
|
init_zod();
|
|
165052
|
-
var
|
|
165267
|
+
var import_node_child_process39 = require("node:child_process");
|
|
165053
165268
|
function parseNetstatListeningPids(netstatOutput, port) {
|
|
165054
165269
|
const pids = /* @__PURE__ */ new Set();
|
|
165055
165270
|
for (const line of netstatOutput.split(/\r?\n/)) {
|
|
@@ -165065,7 +165280,7 @@ function parseNetstatListeningPids(netstatOutput, port) {
|
|
|
165065
165280
|
}
|
|
165066
165281
|
function listeningPids(port) {
|
|
165067
165282
|
if (process.platform === "win32") {
|
|
165068
|
-
const output3 = (0,
|
|
165283
|
+
const output3 = (0, import_node_child_process39.execFileSync)("netstat", ["-ano"], {
|
|
165069
165284
|
encoding: "utf-8",
|
|
165070
165285
|
timeout: 5e3,
|
|
165071
165286
|
// `netstat -ano` dumps every socket on the host; overflowing Node's
|
|
@@ -165074,7 +165289,7 @@ function listeningPids(port) {
|
|
|
165074
165289
|
});
|
|
165075
165290
|
return parseNetstatListeningPids(output3, port);
|
|
165076
165291
|
}
|
|
165077
|
-
const output2 = (0,
|
|
165292
|
+
const output2 = (0, import_node_child_process39.execFileSync)("lsof", ["-ti", `tcp:${port}`, "-sTCP:LISTEN"], {
|
|
165078
165293
|
encoding: "utf-8",
|
|
165079
165294
|
timeout: 5e3
|
|
165080
165295
|
}).trim();
|
|
@@ -170831,7 +171046,7 @@ var import_node_url4 = require("node:url");
|
|
|
170831
171046
|
init_src2();
|
|
170832
171047
|
|
|
170833
171048
|
// ../tool-server/src/tools/flows/script/flow-script-executor.ts
|
|
170834
|
-
var
|
|
171049
|
+
var import_node_child_process40 = require("node:child_process");
|
|
170835
171050
|
var fs59 = __toESM(require("node:fs"));
|
|
170836
171051
|
var os17 = __toESM(require("node:os"));
|
|
170837
171052
|
var path45 = __toESM(require("node:path"));
|
|
@@ -171216,7 +171431,7 @@ var FlowScriptExecutor = class {
|
|
|
171216
171431
|
detached: process.platform !== "win32",
|
|
171217
171432
|
windowsHide: process.platform === "win32"
|
|
171218
171433
|
};
|
|
171219
|
-
child = (0,
|
|
171434
|
+
child = (0, import_node_child_process40.fork)(scriptPath, [], forkOptions);
|
|
171220
171435
|
} catch (err) {
|
|
171221
171436
|
return emptyResult(
|
|
171222
171437
|
{ kind: "spawn", message: `Could not start the script process: ${errorMessage(err)}` },
|
|
@@ -171660,7 +171875,7 @@ async function stopProcessTree(child, graceMs) {
|
|
|
171660
171875
|
if (process.platform === "win32") {
|
|
171661
171876
|
if (hasExited(child)) return;
|
|
171662
171877
|
tryKill(() => {
|
|
171663
|
-
const killer = (0,
|
|
171878
|
+
const killer = (0, import_node_child_process40.spawn)("taskkill", ["/pid", String(pid), "/t", "/f"], {
|
|
171664
171879
|
windowsHide: true,
|
|
171665
171880
|
stdio: "ignore"
|
|
171666
171881
|
});
|
|
@@ -172366,7 +172581,7 @@ init_src2();
|
|
|
172366
172581
|
init_device_info();
|
|
172367
172582
|
|
|
172368
172583
|
// ../tool-server/src/tools/flows/flow-visual.ts
|
|
172369
|
-
var
|
|
172584
|
+
var import_node_crypto13 = require("node:crypto");
|
|
172370
172585
|
var fs63 = __toESM(require("node:fs/promises"));
|
|
172371
172586
|
var os18 = __toESM(require("node:os"));
|
|
172372
172587
|
var path48 = __toESM(require("node:path"));
|
|
@@ -172382,7 +172597,7 @@ init_src2();
|
|
|
172382
172597
|
// ../tool-server/src/tools/screenshot-diff/screenshot-diff-ocr.ts
|
|
172383
172598
|
var import_child_process8 = require("child_process");
|
|
172384
172599
|
var import_util16 = require("util");
|
|
172385
|
-
var
|
|
172600
|
+
var execFileAsync32 = (0, import_util16.promisify)(import_child_process8.execFile);
|
|
172386
172601
|
var OCR_TIMEOUT_MS = 1e4;
|
|
172387
172602
|
var OCR_MAX_BUFFER_BYTES = 32 * 1024 * 1024;
|
|
172388
172603
|
var TESSERACT_BINARY = "tesseract";
|
|
@@ -172427,7 +172642,7 @@ async function extractOcrTextBlocks(imagePath) {
|
|
|
172427
172642
|
}
|
|
172428
172643
|
}
|
|
172429
172644
|
async function recognizeTsv(imagePath) {
|
|
172430
|
-
const { stdout } = await
|
|
172645
|
+
const { stdout } = await execFileAsync32(
|
|
172431
172646
|
TESSERACT_BINARY,
|
|
172432
172647
|
[
|
|
172433
172648
|
imagePath,
|
|
@@ -174537,7 +174752,7 @@ async function runSnapshot(env, opts) {
|
|
|
174537
174752
|
});
|
|
174538
174753
|
const captureWarned = shot.warning !== void 0 ? { warning: shot.warning } : {};
|
|
174539
174754
|
const { w, h } = await pngDimensions(shot.image.hostPath);
|
|
174540
|
-
const cropSuffix = opts.cropOn === void 0 ? "" : `-crop-${(0,
|
|
174755
|
+
const cropSuffix = opts.cropOn === void 0 ? "" : `-crop-${(0, import_node_crypto13.createHash)("sha256").update(cropIdentity(opts.cropOn)).digest("hex").slice(0, 8)}`;
|
|
174541
174756
|
const snapshotKey = `${opts.name}__${authoringPlatform(env.device.platform)}-${w}x${h}${cropSuffix}`;
|
|
174542
174757
|
const key2 = `${snapshotKey}.png`;
|
|
174543
174758
|
const baselinePath = opts.clientFlowPath === void 0 ? path48.join(baselineDir(opts.flowsDir, opts.flowName), key2) : clientBaselinePath(opts.clientFlowPath, opts.flowName, key2);
|
|
@@ -174709,11 +174924,11 @@ async function runSnapshot(env, opts) {
|
|
|
174709
174924
|
}
|
|
174710
174925
|
|
|
174711
174926
|
// ../tool-server/src/utils/status-bar.ts
|
|
174712
|
-
var
|
|
174713
|
-
var
|
|
174927
|
+
var import_node_child_process41 = require("node:child_process");
|
|
174928
|
+
var import_node_util31 = require("node:util");
|
|
174714
174929
|
init_adb();
|
|
174715
174930
|
init_device_info();
|
|
174716
|
-
var
|
|
174931
|
+
var execFileAsync33 = (0, import_node_util31.promisify)(import_node_child_process41.execFile);
|
|
174717
174932
|
var DEMO_BROADCAST = "am broadcast -a com.android.systemui.demo";
|
|
174718
174933
|
var IOS_STATUS_BAR_OVERRIDE = [
|
|
174719
174934
|
"override",
|
|
@@ -174737,7 +174952,7 @@ async function pinStatusBar(device, signal) {
|
|
|
174737
174952
|
if (isIosPhysicalDevice(device)) return false;
|
|
174738
174953
|
try {
|
|
174739
174954
|
if (device.platform === "ios") {
|
|
174740
|
-
await
|
|
174955
|
+
await execFileAsync33(
|
|
174741
174956
|
"xcrun",
|
|
174742
174957
|
await simctlArgsForUdid(device.id, ["status_bar", device.id, ...IOS_STATUS_BAR_OVERRIDE])
|
|
174743
174958
|
);
|
|
@@ -174773,7 +174988,7 @@ async function pinStatusBar(device, signal) {
|
|
|
174773
174988
|
async function restoreStatusBar(device) {
|
|
174774
174989
|
try {
|
|
174775
174990
|
if (device.platform === "ios") {
|
|
174776
|
-
await
|
|
174991
|
+
await execFileAsync33(
|
|
174777
174992
|
"xcrun",
|
|
174778
174993
|
await simctlArgsForUdid(device.id, ["status_bar", device.id, "clear"])
|
|
174779
174994
|
);
|
|
@@ -176382,7 +176597,7 @@ init_zod();
|
|
|
176382
176597
|
// ../tool-server/src/utils/workspace-reader.ts
|
|
176383
176598
|
var import_promises19 = require("node:fs/promises");
|
|
176384
176599
|
var import_node_path29 = require("node:path");
|
|
176385
|
-
var
|
|
176600
|
+
var import_node_child_process42 = require("node:child_process");
|
|
176386
176601
|
var import_dotenv2 = __toESM(require_dist());
|
|
176387
176602
|
async function exists2(path54) {
|
|
176388
176603
|
try {
|
|
@@ -176426,7 +176641,7 @@ async function listDir(path54) {
|
|
|
176426
176641
|
var COMMAND_TIMEOUT_MS = 3e3;
|
|
176427
176642
|
function runVersionCommand(cmd, args, cwd) {
|
|
176428
176643
|
return new Promise((resolve16) => {
|
|
176429
|
-
const child = (0,
|
|
176644
|
+
const child = (0, import_node_child_process42.execFile)(cmd, args, { cwd, timeout: COMMAND_TIMEOUT_MS }, (err, stdout) => {
|
|
176430
176645
|
if (err) {
|
|
176431
176646
|
resolve16(null);
|
|
176432
176647
|
return;
|
|
@@ -176716,7 +176931,7 @@ Fails if the workspacePath is not an absolute path or the directory cannot be ac
|
|
|
176716
176931
|
};
|
|
176717
176932
|
|
|
176718
176933
|
// ../tool-server/src/tools/system/update-argent.ts
|
|
176719
|
-
var
|
|
176934
|
+
var import_node_child_process43 = require("node:child_process");
|
|
176720
176935
|
var fs66 = __toESM(require("node:fs"));
|
|
176721
176936
|
var path50 = __toESM(require("node:path"));
|
|
176722
176937
|
init_zod();
|
|
@@ -176851,7 +177066,7 @@ var updateArgentTool = {
|
|
|
176851
177066
|
if (spawnRoot) updateArgs.push("--project-root", spawnRoot);
|
|
176852
177067
|
const cmd = cliEntry ? process.execPath : "argent";
|
|
176853
177068
|
const args = cliEntry ? [cliEntry, ...updateArgs] : updateArgs;
|
|
176854
|
-
const child = (0,
|
|
177069
|
+
const child = (0, import_node_child_process43.spawn)(cmd, args, {
|
|
176855
177070
|
detached: true,
|
|
176856
177071
|
stdio: "ignore",
|
|
176857
177072
|
env: { ...process.env, ARGENT_UPDATE_TRIGGER: "mcp_update" }
|
|
@@ -176903,7 +177118,7 @@ var dismissUpdateTool = {
|
|
|
176903
177118
|
};
|
|
176904
177119
|
|
|
176905
177120
|
// ../tool-server/src/tools/screenshot-diff/index.ts
|
|
176906
|
-
var
|
|
177121
|
+
var import_node_crypto14 = __toESM(require("node:crypto"));
|
|
176907
177122
|
var import_promises20 = __toESM(require("fs/promises"));
|
|
176908
177123
|
var import_node_os15 = __toESM(require("node:os"));
|
|
176909
177124
|
var import_path8 = __toESM(require("path"));
|
|
@@ -177050,7 +177265,7 @@ async function resolveOutputDir(params, options) {
|
|
|
177050
177265
|
const dir = import_path8.default.join(
|
|
177051
177266
|
import_node_os15.default.tmpdir(),
|
|
177052
177267
|
"argent-screenshot-diff",
|
|
177053
|
-
|
|
177268
|
+
import_node_crypto14.default.randomBytes(6).toString("hex")
|
|
177054
177269
|
);
|
|
177055
177270
|
await import_promises20.default.mkdir(dir, { recursive: true });
|
|
177056
177271
|
return dir;
|
|
@@ -177148,7 +177363,7 @@ function requireIosDeviceRunner(services) {
|
|
|
177148
177363
|
}
|
|
177149
177364
|
async function captureIosDeviceLiveInput(params) {
|
|
177150
177365
|
const png = await captureRunnerScreenshotPng(params.runner, RUNNER_COMMAND_TIMEOUT_MS);
|
|
177151
|
-
const suffix =
|
|
177366
|
+
const suffix = import_node_crypto14.default.randomBytes(4).toString("hex");
|
|
177152
177367
|
const destination = import_path8.default.join(params.outputDir, `${params.name}-${suffix}.live.png`);
|
|
177153
177368
|
await import_promises20.default.mkdir(params.outputDir, { recursive: true });
|
|
177154
177369
|
await import_promises20.default.writeFile(destination, png);
|
|
@@ -177166,7 +177381,7 @@ async function captureHarmonyLiveInput(params) {
|
|
|
177166
177381
|
}
|
|
177167
177382
|
await ensureDep("hdc");
|
|
177168
177383
|
const captured = await captureHarmonyScreenshotPng({ connectKey: params.connectKey, scale: 1 });
|
|
177169
|
-
const suffix =
|
|
177384
|
+
const suffix = import_node_crypto14.default.randomBytes(4).toString("hex");
|
|
177170
177385
|
const destination = import_path8.default.join(params.outputDir, `${params.name}-${suffix}.live.png`);
|
|
177171
177386
|
try {
|
|
177172
177387
|
await import_promises20.default.mkdir(params.outputDir, { recursive: true });
|
|
@@ -177202,7 +177417,7 @@ async function captureLiveInput(params) {
|
|
|
177202
177417
|
params.peekFor?.(params.device)
|
|
177203
177418
|
);
|
|
177204
177419
|
}
|
|
177205
|
-
const suffix =
|
|
177420
|
+
const suffix = import_node_crypto14.default.randomBytes(4).toString("hex");
|
|
177206
177421
|
const destination = import_path8.default.join(params.outputDir, `${params.name}-${suffix}.live.png`);
|
|
177207
177422
|
await import_promises20.default.mkdir(params.outputDir, { recursive: true });
|
|
177208
177423
|
await import_promises20.default.copyFile(capture.path, destination);
|
|
@@ -177921,13 +178136,13 @@ function probeArgentToolServer(host, port, timeoutMs = 500) {
|
|
|
177921
178136
|
|
|
177922
178137
|
// ../tool-server/src/utils/simulator-watcher.ts
|
|
177923
178138
|
var fs68 = __toESM(require("node:fs"));
|
|
177924
|
-
var
|
|
177925
|
-
var
|
|
178139
|
+
var import_node_child_process44 = require("node:child_process");
|
|
178140
|
+
var import_node_util32 = require("node:util");
|
|
177926
178141
|
init_external_devices();
|
|
177927
|
-
var
|
|
178142
|
+
var execFileAsync34 = (0, import_node_util32.promisify)(import_node_child_process44.execFile);
|
|
177928
178143
|
var POLL_INTERVAL_MS2 = 1e4;
|
|
177929
178144
|
async function getBootedUdidsInSet(deviceSet) {
|
|
177930
|
-
const { stdout } = await
|
|
178145
|
+
const { stdout } = await execFileAsync34("xcrun", [
|
|
177931
178146
|
...simctlPrefix(deviceSet),
|
|
177932
178147
|
"list",
|
|
177933
178148
|
"devices",
|
|
@@ -178046,7 +178261,7 @@ function startSimulatorWatcher(registry2) {
|
|
|
178046
178261
|
}
|
|
178047
178262
|
|
|
178048
178263
|
// ../tool-server/src/utils/preview-window.ts
|
|
178049
|
-
var
|
|
178264
|
+
var import_node_child_process45 = require("node:child_process");
|
|
178050
178265
|
var fs69 = __toESM(require("node:fs"));
|
|
178051
178266
|
var os20 = __toESM(require("node:os"));
|
|
178052
178267
|
var path52 = __toESM(require("node:path"));
|
|
@@ -178078,10 +178293,10 @@ function ensureLensAppBundle(electronBin) {
|
|
|
178078
178293
|
fs69.copyFileSync(path52.join(realContents, "Info.plist"), plist);
|
|
178079
178294
|
const setPlist = (entry, value) => {
|
|
178080
178295
|
try {
|
|
178081
|
-
(0,
|
|
178296
|
+
(0, import_node_child_process45.execFileSync)("/usr/libexec/PlistBuddy", ["-c", `Set :${entry} ${value}`, plist]);
|
|
178082
178297
|
} catch {
|
|
178083
178298
|
try {
|
|
178084
|
-
(0,
|
|
178299
|
+
(0, import_node_child_process45.execFileSync)("/usr/libexec/PlistBuddy", ["-c", `Add :${entry} string ${value}`, plist]);
|
|
178085
178300
|
} catch {
|
|
178086
178301
|
}
|
|
178087
178302
|
}
|
|
@@ -178140,7 +178355,7 @@ function createPreviewWindowManager(opts = {}) {
|
|
|
178140
178355
|
const wrapperBin = ensureLensAppBundle(electronBin);
|
|
178141
178356
|
const launchBin = wrapperBin ?? electronBin;
|
|
178142
178357
|
const launchArgs = wrapperBin ? ["--no-sandbox", mainScript] : [mainScript];
|
|
178143
|
-
const next = (0,
|
|
178358
|
+
const next = (0, import_node_child_process45.spawn)(launchBin, launchArgs, {
|
|
178144
178359
|
// Strips ELECTRON_RUN_AS_NODE, which an Electron-based MCP host leaves in
|
|
178145
178360
|
// our env, so the child boots as a GUI app instead of bare Node.
|
|
178146
178361
|
env: electronGuiChildEnv({ ARGENT_PREVIEW_URL: url2 }),
|
package/package.json
CHANGED
|
@@ -57,6 +57,7 @@ You do not need to derive `app_process` manually; just make sure the app is laun
|
|
|
57
57
|
|
|
58
58
|
Call `native-profiler-start` with `device_id` (iOS UDID or Android serial). The tool auto-detects the running app and saves the trace to `/tmp/argent-profiler-cwd/` with a timestamped filename.
|
|
59
59
|
Let the user interact with the app or drive interaction via simulator tools (see `argent-device-interact` skill).
|
|
60
|
+
While a profiler records, interaction tools return no automatic screenshot or element tree, so the capture does not load the app. Call `screenshot` or `describe` when you need to see the screen; interaction tools still wait for the screen to settle before they return, so add no wait of your own; on an Android emulator each screenshot during a profile takes one frame in about 100 ms and does not wake the screen capture; on a physical Android device it takes about 150–200 ms and briefly wakes the device screen capture, so take them sparingly there.
|
|
60
61
|
|
|
61
62
|
### Step 2: Stop and export
|
|
62
63
|
|
|
@@ -88,6 +88,8 @@ Mind the react-native and ios-native profiler selection mentioned above when sta
|
|
|
88
88
|
- if session is marked as "stale", you may overtake it without prompting the user for allowance
|
|
89
89
|
- if session is NOT "stale" - before taking action and terminating the other session, **stop and ask user what you should do**, explaining the situation.
|
|
90
90
|
|
|
91
|
+
While a profiler records, interaction tools return no automatic screenshot or element tree, so the capture does not load the app. Call `screenshot` or `describe` when you need to see the screen; interaction tools still wait for the screen to settle before they return, so add no wait of your own; on an Android emulator each screenshot during a profile takes one frame in about 100 ms and does not wake the screen capture; on a physical Android device it takes about 150–200 ms and briefly wakes the device screen capture, so take them sparingly there.
|
|
92
|
+
|
|
91
93
|
#### Annotate every interaction
|
|
92
94
|
|
|
93
95
|
After each `gesture-tap` or `gesture-swipe` call, record an annotation using the returned `timestampMs`. Compute `offsetMs = timestampMs - startedAtEpochMs`. Do this for _every_ interaction, including back-navigation swipes, not just the primary action. Pass all collected annotations to `react-profiler-analyze` in Step 3.
|