@swmansion/argent 0.28.1-next.8 → 0.29.0
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/agents/argent-environment-inspector.md +7 -7
- package/agents/references/quality-control-checklist.md +14 -14
- package/assets/manifest.json +2 -2
- package/bin/argent-android-devtools-0.3.0.apk +0 -0
- package/bin/darwin/ax-service +0 -0
- package/bin/darwin/simulator-server +0 -0
- package/bin/darwin/tvos-ax-service +0 -0
- package/bin/darwin/tvos-hid-daemon +0 -0
- package/bin/linux/simulator-server +0 -0
- package/bin/linux-arm64/simulator-server +0 -0
- package/bin/tcp/ax-service +0 -0
- package/bin/win32/simulator-server.exe +0 -0
- package/dist/cli-cmds.mjs +4 -1
- package/dist/client.d.ts +18 -0
- package/dist/client.js +3 -0
- package/dist/installer.mjs +9 -2
- package/dist/mcp-server.mjs +13 -1
- package/dist/tool-args.generated.d.ts +87 -77
- package/dist/tool-server.cjs +948 -370
- package/dylibs/libArgentInjectionBootstrap.dylib +0 -0
- package/dylibs/libKeyboardPatch.dylib +0 -0
- package/dylibs/libNativeDevtoolsIos.dylib +0 -0
- package/dylibs/tcp/libArgentInjectionBootstrap.dylib +0 -0
- package/dylibs/tcp/libKeyboardPatch.dylib +0 -0
- package/dylibs/tcp/libNativeDevtoolsIos.dylib +0 -0
- package/dylibs/tvos/libArgentInjectionBootstrap.dylib +0 -0
- package/dylibs/tvos/libKeyboardPatch.dylib +0 -0
- package/dylibs/tvos/libNativeDevtoolsIos.dylib +0 -0
- package/package.json +1 -1
- package/rules/argent.md +16 -16
- package/skills/argent-android-emulator-setup/SKILL.md +9 -9
- package/skills/argent-create-flow/references/flow-yaml.md +11 -11
- package/skills/argent-create-flow/references/live-authoring.md +11 -11
- package/skills/argent-create-flow/references/reliability-and-recovery.md +13 -13
- package/skills/argent-device-interact/SKILL.md +47 -47
- package/skills/argent-device-interact/references/chromium.md +1 -1
- package/skills/argent-device-interact/references/gesture-examples.md +7 -7
- package/skills/argent-device-interact/references/secrets.md +6 -6
- package/skills/argent-lens/SKILL.md +21 -21
- package/skills/argent-metro-debugger/SKILL.md +24 -24
- package/skills/argent-metro-debugger/references/failure-scenarios.md +11 -11
- package/skills/argent-metro-debugger/references/source-maps.md +4 -4
- package/skills/argent-native-profiler/SKILL.md +13 -13
- package/skills/argent-qa-flows/SKILL.md +3 -3
- package/skills/argent-react-native-app-workflow/SKILL.md +18 -18
- package/skills/argent-react-native-optimization/SKILL.md +12 -12
- package/skills/argent-react-native-optimization/references/fix-reference.md +10 -10
- package/skills/argent-react-native-optimization/references/lint-rules.md +1 -1
- package/skills/argent-react-native-profiler/SKILL.md +25 -25
- package/skills/argent-react-native-profiler/references/diagnostic-tools.md +19 -19
- package/skills/argent-screen-recording/SKILL.md +14 -14
- package/skills/argent-test-ui-flow/SKILL.md +9 -9
- package/skills/argent-tv-interact/SKILL.md +19 -19
- package/bin/argent-android-devtools-0.2.0.apk +0 -0
package/dist/tool-server.cjs
CHANGED
|
@@ -1517,6 +1517,9 @@ var init_failure_codes = __esm({
|
|
|
1517
1517
|
KEYBOARD_CHARACTER_UNSUPPORTED: "KEYBOARD_CHARACTER_UNSUPPORTED",
|
|
1518
1518
|
KEYBOARD_TEXT_AND_KEY_COMBINED: "KEYBOARD_TEXT_AND_KEY_COMBINED",
|
|
1519
1519
|
KEYBOARD_INPUT_NOT_FOCUSED: "KEYBOARD_INPUT_NOT_FOCUSED",
|
|
1520
|
+
FILL_NO_FOCUSED_FIELD: "FILL_NO_FOCUSED_FIELD",
|
|
1521
|
+
FILL_NOT_VERIFIED: "FILL_NOT_VERIFIED",
|
|
1522
|
+
FILL_UNSUPPORTED_FIELD: "FILL_UNSUPPORTED_FIELD",
|
|
1520
1523
|
SECRET_PLACEHOLDER_UNKNOWN: "SECRET_PLACEHOLDER_UNKNOWN",
|
|
1521
1524
|
SCREENSHOT_DIFF_INPUT_INVALID: "SCREENSHOT_DIFF_INPUT_INVALID",
|
|
1522
1525
|
BOOT_DEVICE_TARGET_SELECTION_INVALID: "BOOT_DEVICE_TARGET_SELECTION_INVALID",
|
|
@@ -13223,8 +13226,8 @@ function finalize(ctx, schema) {
|
|
|
13223
13226
|
const root = ctx.seen.get(schema);
|
|
13224
13227
|
if (!root)
|
|
13225
13228
|
throw new Error("Unprocessed schema. This is a bug in Zod.");
|
|
13226
|
-
const flattenRef = (
|
|
13227
|
-
const seen = ctx.seen.get(
|
|
13229
|
+
const flattenRef = (zodSchema82) => {
|
|
13230
|
+
const seen = ctx.seen.get(zodSchema82);
|
|
13228
13231
|
if (seen.ref === null)
|
|
13229
13232
|
return;
|
|
13230
13233
|
const schema2 = seen.def ?? seen.schema;
|
|
@@ -13242,7 +13245,7 @@ function finalize(ctx, schema) {
|
|
|
13242
13245
|
Object.assign(schema2, refSchema);
|
|
13243
13246
|
}
|
|
13244
13247
|
Object.assign(schema2, _cached);
|
|
13245
|
-
const isParentRef =
|
|
13248
|
+
const isParentRef = zodSchema82._zod.parent === ref;
|
|
13246
13249
|
if (isParentRef) {
|
|
13247
13250
|
for (const key2 in schema2) {
|
|
13248
13251
|
if (key2 === "$ref" || key2 === "allOf")
|
|
@@ -13262,7 +13265,7 @@ function finalize(ctx, schema) {
|
|
|
13262
13265
|
}
|
|
13263
13266
|
}
|
|
13264
13267
|
}
|
|
13265
|
-
const parent =
|
|
13268
|
+
const parent = zodSchema82._zod.parent;
|
|
13266
13269
|
if (parent && parent !== ref) {
|
|
13267
13270
|
flattenRef(parent);
|
|
13268
13271
|
const parentSeen = ctx.seen.get(parent);
|
|
@@ -13280,7 +13283,7 @@ function finalize(ctx, schema) {
|
|
|
13280
13283
|
}
|
|
13281
13284
|
}
|
|
13282
13285
|
ctx.override({
|
|
13283
|
-
zodSchema:
|
|
13286
|
+
zodSchema: zodSchema82,
|
|
13284
13287
|
jsonSchema: schema2,
|
|
13285
13288
|
path: seen.path ?? []
|
|
13286
13289
|
});
|
|
@@ -16081,10 +16084,10 @@ function convertBaseSchema(schema, ctx) {
|
|
|
16081
16084
|
}
|
|
16082
16085
|
ctx.processing.add(refPath);
|
|
16083
16086
|
const resolved = resolveRef(refPath, ctx);
|
|
16084
|
-
const
|
|
16085
|
-
ctx.refs.set(refPath,
|
|
16087
|
+
const zodSchema83 = convertSchema(resolved, ctx);
|
|
16088
|
+
ctx.refs.set(refPath, zodSchema83);
|
|
16086
16089
|
ctx.processing.delete(refPath);
|
|
16087
|
-
return
|
|
16090
|
+
return zodSchema83;
|
|
16088
16091
|
}
|
|
16089
16092
|
if (schema.enum !== void 0) {
|
|
16090
16093
|
const enumValues = schema.enum;
|
|
@@ -16126,7 +16129,7 @@ function convertBaseSchema(schema, ctx) {
|
|
|
16126
16129
|
if (!type) {
|
|
16127
16130
|
return z.any();
|
|
16128
16131
|
}
|
|
16129
|
-
let
|
|
16132
|
+
let zodSchema82;
|
|
16130
16133
|
switch (type) {
|
|
16131
16134
|
case "string": {
|
|
16132
16135
|
let stringSchema = z.string();
|
|
@@ -16189,7 +16192,7 @@ function convertBaseSchema(schema, ctx) {
|
|
|
16189
16192
|
if (schema.pattern) {
|
|
16190
16193
|
stringSchema = stringSchema.regex(new RegExp(schema.pattern));
|
|
16191
16194
|
}
|
|
16192
|
-
|
|
16195
|
+
zodSchema82 = stringSchema;
|
|
16193
16196
|
break;
|
|
16194
16197
|
}
|
|
16195
16198
|
case "number":
|
|
@@ -16214,15 +16217,15 @@ function convertBaseSchema(schema, ctx) {
|
|
|
16214
16217
|
if (typeof schema.multipleOf === "number") {
|
|
16215
16218
|
numberSchema = numberSchema.multipleOf(schema.multipleOf);
|
|
16216
16219
|
}
|
|
16217
|
-
|
|
16220
|
+
zodSchema82 = numberSchema;
|
|
16218
16221
|
break;
|
|
16219
16222
|
}
|
|
16220
16223
|
case "boolean": {
|
|
16221
|
-
|
|
16224
|
+
zodSchema82 = z.boolean();
|
|
16222
16225
|
break;
|
|
16223
16226
|
}
|
|
16224
16227
|
case "null": {
|
|
16225
|
-
|
|
16228
|
+
zodSchema82 = z.null();
|
|
16226
16229
|
break;
|
|
16227
16230
|
}
|
|
16228
16231
|
case "object": {
|
|
@@ -16237,12 +16240,12 @@ function convertBaseSchema(schema, ctx) {
|
|
|
16237
16240
|
const keySchema = convertSchema(schema.propertyNames, ctx);
|
|
16238
16241
|
const valueSchema = schema.additionalProperties && typeof schema.additionalProperties === "object" ? convertSchema(schema.additionalProperties, ctx) : z.any();
|
|
16239
16242
|
if (Object.keys(shape).length === 0) {
|
|
16240
|
-
|
|
16243
|
+
zodSchema82 = z.record(keySchema, valueSchema);
|
|
16241
16244
|
break;
|
|
16242
16245
|
}
|
|
16243
16246
|
const objectSchema2 = z.object(shape).passthrough();
|
|
16244
16247
|
const recordSchema = z.looseRecord(keySchema, valueSchema);
|
|
16245
|
-
|
|
16248
|
+
zodSchema82 = z.intersection(objectSchema2, recordSchema);
|
|
16246
16249
|
break;
|
|
16247
16250
|
}
|
|
16248
16251
|
if (schema.patternProperties) {
|
|
@@ -16260,25 +16263,25 @@ function convertBaseSchema(schema, ctx) {
|
|
|
16260
16263
|
}
|
|
16261
16264
|
schemasToIntersect.push(...looseRecords);
|
|
16262
16265
|
if (schemasToIntersect.length === 0) {
|
|
16263
|
-
|
|
16266
|
+
zodSchema82 = z.object({}).passthrough();
|
|
16264
16267
|
} else if (schemasToIntersect.length === 1) {
|
|
16265
|
-
|
|
16268
|
+
zodSchema82 = schemasToIntersect[0];
|
|
16266
16269
|
} else {
|
|
16267
16270
|
let result = z.intersection(schemasToIntersect[0], schemasToIntersect[1]);
|
|
16268
16271
|
for (let i = 2; i < schemasToIntersect.length; i++) {
|
|
16269
16272
|
result = z.intersection(result, schemasToIntersect[i]);
|
|
16270
16273
|
}
|
|
16271
|
-
|
|
16274
|
+
zodSchema82 = result;
|
|
16272
16275
|
}
|
|
16273
16276
|
break;
|
|
16274
16277
|
}
|
|
16275
16278
|
const objectSchema = z.object(shape);
|
|
16276
16279
|
if (schema.additionalProperties === false) {
|
|
16277
|
-
|
|
16280
|
+
zodSchema82 = objectSchema.strict();
|
|
16278
16281
|
} else if (typeof schema.additionalProperties === "object") {
|
|
16279
|
-
|
|
16282
|
+
zodSchema82 = objectSchema.catchall(convertSchema(schema.additionalProperties, ctx));
|
|
16280
16283
|
} else {
|
|
16281
|
-
|
|
16284
|
+
zodSchema82 = objectSchema.passthrough();
|
|
16282
16285
|
}
|
|
16283
16286
|
break;
|
|
16284
16287
|
}
|
|
@@ -16289,29 +16292,29 @@ function convertBaseSchema(schema, ctx) {
|
|
|
16289
16292
|
const tupleItems = prefixItems.map((item) => convertSchema(item, ctx));
|
|
16290
16293
|
const rest = items && typeof items === "object" && !Array.isArray(items) ? convertSchema(items, ctx) : void 0;
|
|
16291
16294
|
if (rest) {
|
|
16292
|
-
|
|
16295
|
+
zodSchema82 = z.tuple(tupleItems).rest(rest);
|
|
16293
16296
|
} else {
|
|
16294
|
-
|
|
16297
|
+
zodSchema82 = z.tuple(tupleItems);
|
|
16295
16298
|
}
|
|
16296
16299
|
if (typeof schema.minItems === "number") {
|
|
16297
|
-
|
|
16300
|
+
zodSchema82 = zodSchema82.check(z.minLength(schema.minItems));
|
|
16298
16301
|
}
|
|
16299
16302
|
if (typeof schema.maxItems === "number") {
|
|
16300
|
-
|
|
16303
|
+
zodSchema82 = zodSchema82.check(z.maxLength(schema.maxItems));
|
|
16301
16304
|
}
|
|
16302
16305
|
} else if (Array.isArray(items)) {
|
|
16303
16306
|
const tupleItems = items.map((item) => convertSchema(item, ctx));
|
|
16304
16307
|
const rest = schema.additionalItems && typeof schema.additionalItems === "object" ? convertSchema(schema.additionalItems, ctx) : void 0;
|
|
16305
16308
|
if (rest) {
|
|
16306
|
-
|
|
16309
|
+
zodSchema82 = z.tuple(tupleItems).rest(rest);
|
|
16307
16310
|
} else {
|
|
16308
|
-
|
|
16311
|
+
zodSchema82 = z.tuple(tupleItems);
|
|
16309
16312
|
}
|
|
16310
16313
|
if (typeof schema.minItems === "number") {
|
|
16311
|
-
|
|
16314
|
+
zodSchema82 = zodSchema82.check(z.minLength(schema.minItems));
|
|
16312
16315
|
}
|
|
16313
16316
|
if (typeof schema.maxItems === "number") {
|
|
16314
|
-
|
|
16317
|
+
zodSchema82 = zodSchema82.check(z.maxLength(schema.maxItems));
|
|
16315
16318
|
}
|
|
16316
16319
|
} else if (items !== void 0) {
|
|
16317
16320
|
const element = convertSchema(items, ctx);
|
|
@@ -16322,16 +16325,16 @@ function convertBaseSchema(schema, ctx) {
|
|
|
16322
16325
|
if (typeof schema.maxItems === "number") {
|
|
16323
16326
|
arraySchema = arraySchema.max(schema.maxItems);
|
|
16324
16327
|
}
|
|
16325
|
-
|
|
16328
|
+
zodSchema82 = arraySchema;
|
|
16326
16329
|
} else {
|
|
16327
|
-
|
|
16330
|
+
zodSchema82 = z.array(z.any());
|
|
16328
16331
|
}
|
|
16329
16332
|
break;
|
|
16330
16333
|
}
|
|
16331
16334
|
default:
|
|
16332
16335
|
throw new Error(`Unsupported type: ${type}`);
|
|
16333
16336
|
}
|
|
16334
|
-
return
|
|
16337
|
+
return zodSchema82;
|
|
16335
16338
|
}
|
|
16336
16339
|
function convertSchema(schema, ctx) {
|
|
16337
16340
|
if (typeof schema === "boolean") {
|
|
@@ -73655,16 +73658,16 @@ function lookupExternalDeviceNow(id) {
|
|
|
73655
73658
|
}
|
|
73656
73659
|
return device;
|
|
73657
73660
|
}
|
|
73658
|
-
async function assertExternalCapability(namespace, device,
|
|
73659
|
-
assertExternalCapabilitySync(namespace, device,
|
|
73661
|
+
async function assertExternalCapability(namespace, device, capability39) {
|
|
73662
|
+
assertExternalCapabilitySync(namespace, device, capability39);
|
|
73660
73663
|
}
|
|
73661
|
-
function assertExternalCapabilitySync(namespace, device,
|
|
73664
|
+
function assertExternalCapabilitySync(namespace, device, capability39) {
|
|
73662
73665
|
const id = typeof device === "string" ? device : device.id;
|
|
73663
73666
|
const externalDevice = isExternalId(id) ? lookupExternalDeviceNow(id) : externalClaimForNativeId(id);
|
|
73664
73667
|
if (!externalDevice) return;
|
|
73665
|
-
if (externalDevice.capabilities.has(
|
|
73668
|
+
if (externalDevice.capabilities.has(capability39)) return;
|
|
73666
73669
|
throw new FailureError(
|
|
73667
|
-
`${namespace} is not available on '${externalDevice.name}': ${externalDevice.provider.name} did not grant the '${
|
|
73670
|
+
`${namespace} is not available on '${externalDevice.name}': ${externalDevice.provider.name} did not grant the '${capability39}' capability for this device.`,
|
|
73668
73671
|
{
|
|
73669
73672
|
error_code: FAILURE_CODES.EXTERNAL_DEVICE_CAPABILITY_DENIED,
|
|
73670
73673
|
error_kind: "unsupported",
|
|
@@ -94920,7 +94923,7 @@ var _CI_VENDOR_COUNT_FOR_TEST = vendors_default.length;
|
|
|
94920
94923
|
var SESSION_ID = (0, import_node_crypto3.randomUUID)();
|
|
94921
94924
|
function readCliVersion() {
|
|
94922
94925
|
if (true) {
|
|
94923
|
-
return "0.
|
|
94926
|
+
return "0.29.0";
|
|
94924
94927
|
}
|
|
94925
94928
|
return "0.0.0";
|
|
94926
94929
|
}
|
|
@@ -96280,7 +96283,7 @@ var import_node_path6 = __toESM(require("node:path"));
|
|
|
96280
96283
|
var import_semver2 = __toESM(require_semver2());
|
|
96281
96284
|
|
|
96282
96285
|
// ../tool-server/package.json
|
|
96283
|
-
var version2 = "0.
|
|
96286
|
+
var version2 = "0.29.0";
|
|
96284
96287
|
|
|
96285
96288
|
// ../tool-server/src/utils/update-checker.ts
|
|
96286
96289
|
var import_update_core = __toESM(require_dist4());
|
|
@@ -96694,8 +96697,8 @@ async function simctlArgsForUdid(udid, args, options) {
|
|
|
96694
96697
|
return [...simctlPrefix(await deviceSetForUdid(udid)), ...nativeArgs(udid, args)];
|
|
96695
96698
|
}
|
|
96696
96699
|
function assertSimctlEntitlement(udid, options) {
|
|
96697
|
-
const
|
|
96698
|
-
assertExternalCapabilitySync(
|
|
96700
|
+
const capability39 = options?.granted ?? "simctl";
|
|
96701
|
+
assertExternalCapabilitySync(capability39, udid, capability39);
|
|
96699
96702
|
}
|
|
96700
96703
|
async function simctlTargetForUdid(udid, options) {
|
|
96701
96704
|
assertSimctlEntitlement(udid, options);
|
|
@@ -97439,6 +97442,7 @@ function axServiceRef(device, { transport = "unix" } = {}) {
|
|
|
97439
97442
|
};
|
|
97440
97443
|
}
|
|
97441
97444
|
var LIVE_PANEL_TIMEOUT_MS = 2e3;
|
|
97445
|
+
var FILL_TIMEOUT_MS = 6e3;
|
|
97442
97446
|
function getSocketPath(udid) {
|
|
97443
97447
|
return `/tmp/ax-${udid.slice(0, 8)}.sock`;
|
|
97444
97448
|
}
|
|
@@ -97689,7 +97693,7 @@ var axServiceBlueprint = {
|
|
|
97689
97693
|
}
|
|
97690
97694
|
throw err;
|
|
97691
97695
|
}
|
|
97692
|
-
function query(command, timeoutMs = 5e3) {
|
|
97696
|
+
function query(command, timeoutMs = 5e3, params) {
|
|
97693
97697
|
return new Promise((resolve14, reject) => {
|
|
97694
97698
|
if (!daemonSocket || daemonSocket.destroyed) {
|
|
97695
97699
|
reject(
|
|
@@ -97717,7 +97721,9 @@ var axServiceBlueprint = {
|
|
|
97717
97721
|
}
|
|
97718
97722
|
}, timeoutMs);
|
|
97719
97723
|
pendingRpc.set(id, { resolve: resolve14, reject, timer });
|
|
97720
|
-
daemonSocket.write(
|
|
97724
|
+
daemonSocket.write(
|
|
97725
|
+
JSON.stringify(params === void 0 ? { id, command } : { id, command, params }) + "\n"
|
|
97726
|
+
);
|
|
97721
97727
|
});
|
|
97722
97728
|
}
|
|
97723
97729
|
const api = {
|
|
@@ -97760,6 +97766,9 @@ var axServiceBlueprint = {
|
|
|
97760
97766
|
treeVersion: result.treeVersion
|
|
97761
97767
|
};
|
|
97762
97768
|
},
|
|
97769
|
+
async foregroundApp() {
|
|
97770
|
+
return await query("foreground_app");
|
|
97771
|
+
},
|
|
97763
97772
|
async livePanel() {
|
|
97764
97773
|
const result = await query("live_panel", LIVE_PANEL_TIMEOUT_MS);
|
|
97765
97774
|
if (result.error) {
|
|
@@ -97772,6 +97781,47 @@ var axServiceBlueprint = {
|
|
|
97772
97781
|
}
|
|
97773
97782
|
return typeof result.displayId === "number" && result.displayId > 0 ? result.displayId : null;
|
|
97774
97783
|
},
|
|
97784
|
+
async fill(text, options2 = {}) {
|
|
97785
|
+
let result;
|
|
97786
|
+
try {
|
|
97787
|
+
result = await query("fill", FILL_TIMEOUT_MS, {
|
|
97788
|
+
text,
|
|
97789
|
+
...options2.check ? { check: true } : {},
|
|
97790
|
+
...options2.typeable === false ? { typeable: false } : {}
|
|
97791
|
+
});
|
|
97792
|
+
} catch (err) {
|
|
97793
|
+
const code = err instanceof Error ? err.message : "";
|
|
97794
|
+
if (code === "unknown_command") {
|
|
97795
|
+
throw new FailureError("ax-service predates `fill`; update argent", {
|
|
97796
|
+
error_code: FAILURE_CODES.AX_QUERY_FAILED,
|
|
97797
|
+
failure_stage: "ax_service_fill",
|
|
97798
|
+
failure_area: "tool_server",
|
|
97799
|
+
error_kind: "unknown"
|
|
97800
|
+
});
|
|
97801
|
+
}
|
|
97802
|
+
if (code === "no_focused_field" || code === "not_editable") {
|
|
97803
|
+
return { focused: false, verified: false };
|
|
97804
|
+
}
|
|
97805
|
+
if (code === "unsupported_field") {
|
|
97806
|
+
return { focused: true, verified: false, unsupported: true };
|
|
97807
|
+
}
|
|
97808
|
+
if (code === "single_line") return { focused: true, verified: false, singleLine: true };
|
|
97809
|
+
if (code === "select_failed") return { focused: true, verified: false, untouched: true };
|
|
97810
|
+
if (code === "fill_failed") return { focused: true, verified: false };
|
|
97811
|
+
if (code === "fill_timeout" || code === "fill_busy" || getFailureSignal(err)?.error_code === FAILURE_CODES.AX_QUERY_TIMEOUT) {
|
|
97812
|
+
return { focused: true, verified: false, timedOut: true };
|
|
97813
|
+
}
|
|
97814
|
+
throw err;
|
|
97815
|
+
}
|
|
97816
|
+
return {
|
|
97817
|
+
focused: true,
|
|
97818
|
+
verified: result.verified === true,
|
|
97819
|
+
...result.needsBackspace === true ? { needsBackspace: true } : {},
|
|
97820
|
+
...result.secure === true ? { secure: true } : {},
|
|
97821
|
+
...typeof result.cleared === "boolean" ? { cleared: result.cleared } : {},
|
|
97822
|
+
...result.untouched === true ? { untouched: true } : {}
|
|
97823
|
+
};
|
|
97824
|
+
},
|
|
97775
97825
|
async alertCheck() {
|
|
97776
97826
|
const result = await query("alert_check");
|
|
97777
97827
|
return result.alertVisible ?? false;
|
|
@@ -97869,23 +97919,23 @@ var InvalidToolInputError = class extends Error {
|
|
|
97869
97919
|
});
|
|
97870
97920
|
}
|
|
97871
97921
|
};
|
|
97872
|
-
function platformMatrix(platform,
|
|
97922
|
+
function platformMatrix(platform, capability39) {
|
|
97873
97923
|
switch (platform) {
|
|
97874
97924
|
case "ios":
|
|
97875
|
-
return
|
|
97925
|
+
return capability39.apple;
|
|
97876
97926
|
case "ios-remote":
|
|
97877
|
-
return
|
|
97927
|
+
return capability39.appleRemote;
|
|
97878
97928
|
case "android":
|
|
97879
|
-
return
|
|
97929
|
+
return capability39.android;
|
|
97880
97930
|
case "chromium":
|
|
97881
|
-
return
|
|
97931
|
+
return capability39.chromium;
|
|
97882
97932
|
case "vega":
|
|
97883
|
-
return
|
|
97933
|
+
return capability39.vega;
|
|
97884
97934
|
}
|
|
97885
97935
|
}
|
|
97886
|
-
function assertSupported(toolId,
|
|
97887
|
-
if (!
|
|
97888
|
-
const matrix = platformMatrix(device.platform,
|
|
97936
|
+
function assertSupported(toolId, capability39, device) {
|
|
97937
|
+
if (!capability39) return;
|
|
97938
|
+
const matrix = platformMatrix(device.platform, capability39);
|
|
97889
97939
|
if (!matrix) {
|
|
97890
97940
|
throw new UnsupportedOperationError(toolId, device, `no ${device.platform} support declared`);
|
|
97891
97941
|
}
|
|
@@ -97893,7 +97943,7 @@ function assertSupported(toolId, capability37, device) {
|
|
|
97893
97943
|
if (!supported) {
|
|
97894
97944
|
throw new UnsupportedOperationError(toolId, device, `kind '${device.kind}' not supported`);
|
|
97895
97945
|
}
|
|
97896
|
-
if (
|
|
97946
|
+
if (capability39.supports && !capability39.supports(device)) {
|
|
97897
97947
|
throw new UnsupportedOperationError(toolId, device, "supports() refiner rejected device");
|
|
97898
97948
|
}
|
|
97899
97949
|
}
|
|
@@ -107907,6 +107957,7 @@ var os5 = __toESM(require("node:os"));
|
|
|
107907
107957
|
var import_node_crypto6 = require("node:crypto");
|
|
107908
107958
|
var import_node_url = require("node:url");
|
|
107909
107959
|
var DEFAULT_SCREENSHOT_SCALE = 0.25;
|
|
107960
|
+
var TV_DEFAULT_LONG_SIDE = 576;
|
|
107910
107961
|
var NO_IMAGE_ERROR = /no image to export/i;
|
|
107911
107962
|
var FIRST_FRAME_WAIT_MS = 6e3;
|
|
107912
107963
|
var FIRST_FRAME_POLL_MS = 250;
|
|
@@ -108262,19 +108313,24 @@ async function simulatorPost(toolLabel, api, endpoint, reqBody, signal, fallback
|
|
|
108262
108313
|
return { res, body };
|
|
108263
108314
|
}
|
|
108264
108315
|
var warnedScaleValue;
|
|
108265
|
-
function
|
|
108316
|
+
function getScreenshotScaleOverride() {
|
|
108266
108317
|
const v = process.env.ARGENT_SCREENSHOT_SCALE;
|
|
108267
|
-
if (v)
|
|
108268
|
-
|
|
108269
|
-
|
|
108270
|
-
|
|
108271
|
-
|
|
108272
|
-
|
|
108273
|
-
|
|
108274
|
-
|
|
108275
|
-
}
|
|
108318
|
+
if (!v) return void 0;
|
|
108319
|
+
const n = parseFloat(v);
|
|
108320
|
+
if (!Number.isNaN(n) && n >= 0.01 && n <= 1) return n;
|
|
108321
|
+
if (v !== warnedScaleValue) {
|
|
108322
|
+
warnedScaleValue = v;
|
|
108323
|
+
console.warn(
|
|
108324
|
+
`[screenshot] Ignoring ARGENT_SCREENSHOT_SCALE=${v}: expected a number between 0.01 and 1.0. Using the default.`
|
|
108325
|
+
);
|
|
108276
108326
|
}
|
|
108277
|
-
return
|
|
108327
|
+
return void 0;
|
|
108328
|
+
}
|
|
108329
|
+
function getScreenshotScale() {
|
|
108330
|
+
return getScreenshotScaleOverride() ?? DEFAULT_SCREENSHOT_SCALE;
|
|
108331
|
+
}
|
|
108332
|
+
function tvDefaultScale(width, height) {
|
|
108333
|
+
return Math.min(1, TV_DEFAULT_LONG_SIDE / Math.max(width, height));
|
|
108278
108334
|
}
|
|
108279
108335
|
async function httpScreenshot(api, rotation, signal, scale, screen) {
|
|
108280
108336
|
if (api.transport) {
|
|
@@ -111338,13 +111394,13 @@ var listDevicesTool = {
|
|
|
111338
111394
|
description: `List iOS simulators, Android emulators, connected physical Android devices, running Chromium apps, and Vega (Fire TV) devices in one place.
|
|
111339
111395
|
Use at the start of a session to pick a target id ('udid' for iOS entries, 'serial' for Android/Vega entries, 'id' for Chromium) to pass to interaction tools, and to see which targets are already running.
|
|
111340
111396
|
Returns { devices, avds } where each device carries a 'platform' discriminator ('ios', 'android', 'chromium', or 'vega'); 'avds' lists Android AVDs bootable via boot-device. A Vega VVD is listed under 'devices' whether running or stopped (state 'running'/'stopped'); start a stopped one with boot-device using its 'vvdImage'.
|
|
111341
|
-
Android entries also carry a 'kind' ('emulator' for a local AVD, 'device' for a physical phone connected over USB / wireless adb)
|
|
111397
|
+
Android entries also carry a 'kind' ('emulator' for a local AVD, 'device' for a physical phone connected over USB / wireless adb). Physical phones are detected from \`adb devices\` (any serial that is not an \`emulator-*\` one) and are driven through the same interaction tools as emulators; they do not need boot-device (just connect the phone with USB debugging authorised).
|
|
111342
111398
|
Physical iPhones appear as iOS entries with kind 'device' (no iPads); no boot-device. State 'connected' = cabled and usable; 'paired' = not reachable over USB, never auto-bound.
|
|
111343
|
-
TV targets are tagged with runtimeKind 'tv' (Apple TV simulators on iOS, Android TV / leanback devices on Android)
|
|
111344
|
-
iOS simulators from an additional CoreSimulator device set (the 'ios.additionalDeviceSets' configuration
|
|
111399
|
+
TV targets are tagged with runtimeKind 'tv' (Apple TV simulators on iOS, Android TV / leanback devices on Android). These are focus-driven, not touch-driven: use \`describe\` to read focus, \`tv-remote\` for remote presses (up/down/left/right/select/back/menu/home), and \`keyboard\` to type, rather than the coordinate/gesture tools.
|
|
111400
|
+
iOS simulators from an additional CoreSimulator device set (the 'ios.additionalDeviceSets' configuration, e.g. devices created by Radon IDE) are listed alongside default-set ones, tagged with their owning 'deviceSet' path; they are driven through the same tools by udid, but run headless (no Simulator.app window attaches to them).
|
|
111345
111401
|
A foldable iOS simulator (the iPhone Duo) has 'foldable: true'. Use the \`fold\` tool to fold or unfold it.
|
|
111346
|
-
Chromium apps are discovered by probing CDP debugging ports (default 9222; extend via the ARGENT_CHROMIUM_PORTS=<comma-separated-ports> env var). They must already be running with --remote-debugging-port=<port
|
|
111347
|
-
Booted/ready devices are listed first. Platforms whose CLI is unavailable are silently omitted
|
|
111402
|
+
Chromium apps are discovered by probing CDP debugging ports (default 9222; extend via the ARGENT_CHROMIUM_PORTS=<comma-separated-ports> env var). They must already be running with --remote-debugging-port=<port>; use boot-device with electronAppPath to launch one.
|
|
111403
|
+
Booted/ready devices are listed first. Platforms whose CLI is unavailable are silently omitted; an empty result usually means xcode-select, Android platform-tools, or the Vega SDK is not installed.`,
|
|
111348
111404
|
alwaysLoad: true,
|
|
111349
111405
|
searchHint: "list devices simulators emulators avd serial udid ios android chromium vega app fire tv session start",
|
|
111350
111406
|
zodSchema,
|
|
@@ -111918,7 +111974,7 @@ var NATIVE_DEVTOOLS_NAMESPACE = "NativeDevtools";
|
|
|
111918
111974
|
function isInjectableBundleId(bundleId) {
|
|
111919
111975
|
return !bundleId.toLowerCase().startsWith("com.apple.");
|
|
111920
111976
|
}
|
|
111921
|
-
var NON_INJECTABLE_NATIVE_WARNING = "Do not fall back to the native-devtools feature tools (native-describe-screen, native-find-views, native-full-hierarchy, native-network-logs, native-view-at-point, native-user-interactable-view-at-point)
|
|
111977
|
+
var NON_INJECTABLE_NATIVE_WARNING = "Do not fall back to the native-devtools feature tools (native-describe-screen, native-find-views, native-full-hierarchy, native-network-logs, native-view-at-point, native-user-interactable-view-at-point): they run the same injection precheck and fail with the same non-injectable error.";
|
|
111922
111978
|
var NON_INJECTABLE_RECOVERY = "Use the standard `describe` tool (its accessibility path reads the screen without injection) or `screenshot` (then interact by coordinate). " + NON_INJECTABLE_NATIVE_WARNING;
|
|
111923
111979
|
var MAX_NATIVE_DEVTOOLS_INIT_ATTEMPTS = 3;
|
|
111924
111980
|
var NATIVE_DEVTOOLS_AGE_SLOP_MS = 3e3;
|
|
@@ -113332,7 +113388,8 @@ function parseUiAutomatorDump(rawOutput, screenW, screenH, options = {}) {
|
|
|
113332
113388
|
if (xmlEnd !== -1) xml = xml.slice(0, xmlEnd + "</hierarchy>".length);
|
|
113333
113389
|
const root = parseUiAutomatorXml(xml);
|
|
113334
113390
|
if (!root) {
|
|
113335
|
-
|
|
113391
|
+
const got = rawOutput.trim() ? `${rawOutput.length} chars: ${JSON.stringify(rawOutput.slice(0, 200))}` : "empty";
|
|
113392
|
+
throw new FailureError(`Failed to parse uiautomator dump output (${got})`, {
|
|
113336
113393
|
error_code: FAILURE_CODES.ANDROID_UIAUTOMATOR_PARSE_FAILED,
|
|
113337
113394
|
failure_stage: "android_uiautomator_parse_dump",
|
|
113338
113395
|
failure_area: "tool_server",
|
|
@@ -113758,6 +113815,7 @@ var net3 = __toESM(require("node:net"));
|
|
|
113758
113815
|
init_src2();
|
|
113759
113816
|
var DEFAULT_RPC_TIMEOUT_MS = 5e3;
|
|
113760
113817
|
var LONG_RPC_TIMEOUT_MS = 15e3;
|
|
113818
|
+
var SET_TEXT_RPC_TIMEOUT_MS = 14e3;
|
|
113761
113819
|
function connectAndroidDevtoolsClient(localPort, onTerminated) {
|
|
113762
113820
|
return new Promise((resolve14, reject) => {
|
|
113763
113821
|
const socket = net3.createConnection({ host: "127.0.0.1", port: localPort });
|
|
@@ -113828,7 +113886,7 @@ function connectAndroidDevtoolsClient(localPort, onTerminated) {
|
|
|
113828
113886
|
);
|
|
113829
113887
|
}
|
|
113830
113888
|
const id = nextId++;
|
|
113831
|
-
const timeoutMs = method === "getHierarchy" ? LONG_RPC_TIMEOUT_MS : DEFAULT_RPC_TIMEOUT_MS;
|
|
113889
|
+
const timeoutMs = method === "getHierarchy" ? LONG_RPC_TIMEOUT_MS : method === "setText" ? SET_TEXT_RPC_TIMEOUT_MS : DEFAULT_RPC_TIMEOUT_MS;
|
|
113832
113890
|
return new Promise((resolveReq, rejectReq) => {
|
|
113833
113891
|
const timer = setTimeout(() => {
|
|
113834
113892
|
pending.delete(id);
|
|
@@ -114197,6 +114255,35 @@ var androidDevtoolsBlueprint = {
|
|
|
114197
114255
|
},
|
|
114198
114256
|
ping() {
|
|
114199
114257
|
return client2.request("ping");
|
|
114258
|
+
},
|
|
114259
|
+
async setText(text, setOpts = {}) {
|
|
114260
|
+
let result;
|
|
114261
|
+
try {
|
|
114262
|
+
result = await client2.request("setText", {
|
|
114263
|
+
text,
|
|
114264
|
+
...setOpts.check ? { check: true } : {}
|
|
114265
|
+
});
|
|
114266
|
+
} catch (err) {
|
|
114267
|
+
if (err instanceof Error && err.message.includes("Unknown method: setText")) {
|
|
114268
|
+
throw new FailureError("The devtools helper predates `setText`; update argent", {
|
|
114269
|
+
error_code: FAILURE_CODES.ANDROID_DEVTOOLS_RPC_ERROR,
|
|
114270
|
+
failure_stage: "android_devtools_set_text",
|
|
114271
|
+
failure_area: "tool_server",
|
|
114272
|
+
error_kind: "unknown"
|
|
114273
|
+
});
|
|
114274
|
+
}
|
|
114275
|
+
if (getFailureSignal(err)?.error_code === FAILURE_CODES.ANDROID_DEVTOOLS_RPC_TIMEOUT || err instanceof Error && err.message.includes("Helper worker timed out")) {
|
|
114276
|
+
return { focused: true, verified: false, timedOut: true };
|
|
114277
|
+
}
|
|
114278
|
+
throw err;
|
|
114279
|
+
}
|
|
114280
|
+
return {
|
|
114281
|
+
focused: result.focused === true,
|
|
114282
|
+
verified: result.verified === true,
|
|
114283
|
+
...typeof result.performed === "boolean" ? { performed: result.performed } : {},
|
|
114284
|
+
...typeof result.password === "boolean" ? { password: result.password } : {},
|
|
114285
|
+
...result.singleLine === true ? { singleLine: true } : {}
|
|
114286
|
+
};
|
|
114200
114287
|
}
|
|
114201
114288
|
};
|
|
114202
114289
|
const instance = {
|
|
@@ -116729,11 +116816,11 @@ function scheduleGroupSigkill(pid, graceMs, opts) {
|
|
|
116729
116816
|
}
|
|
116730
116817
|
async function pollPidsUntilGone(pids, opts) {
|
|
116731
116818
|
const isAlive2 = opts.isAlive ?? pidIsAlive;
|
|
116732
|
-
const
|
|
116819
|
+
const sleep15 = opts.sleep ?? ((ms) => new Promise((resolve14) => setTimeout(resolve14, ms)));
|
|
116733
116820
|
const maxPolls = Math.max(1, Math.ceil(opts.timeoutMs / opts.pollIntervalMs));
|
|
116734
116821
|
let remaining = pids.filter((pid) => isAlive2(pid));
|
|
116735
116822
|
for (let poll = 0; poll < maxPolls && remaining.length > 0; poll += 1) {
|
|
116736
|
-
await
|
|
116823
|
+
await sleep15(opts.pollIntervalMs);
|
|
116737
116824
|
remaining = remaining.filter((pid) => isAlive2(pid));
|
|
116738
116825
|
}
|
|
116739
116826
|
return remaining;
|
|
@@ -118905,19 +118992,19 @@ Returns { envSetup, appRunning, connected, requiresRestart, state, message, next
|
|
|
118905
118992
|
- envSetup: DYLD_INSERT_LIBRARIES is configured in the simulator's launchd environment
|
|
118906
118993
|
- appRunning: the target bundle currently has a running UIKit process on the simulator
|
|
118907
118994
|
- connected: the dylib is active in the current running process for this bundleId
|
|
118908
|
-
- requiresRestart: the app is already running and a fresh process would reach this simulator's devtools endpoint where the current one does not
|
|
118909
|
-
- state: why devtools are or aren't live, measured from the running process. "connected"; "not_running"; "stale_process" (the process cannot reach this simulator's devtools endpoint
|
|
118910
|
-
- message: the remedy for that state, in full, including for a state not listed above. Omitted when connected or non-injectable. Prefer it over inferring one from the booleans
|
|
118995
|
+
- requiresRestart: the app is already running and a fresh process would reach this simulator's devtools endpoint where the current one does not: it carries no argent injection, was pointed at an earlier tool-server's listener, or could not be inspected to tell. Always false for a non-injectable app, and false when state is unregistered or connecting, where a relaunch cannot help.
|
|
118996
|
+
- state: why devtools are or aren't live, measured from the running process. "connected"; "not_running"; "stale_process" (the process cannot reach this simulator's devtools endpoint, launched either before argent's instrumentation was in place or against an earlier tool-server's listener, so restart-app fixes it); "unregistered" (the process IS injected and pointed at this simulator's devtools endpoint yet the service never registered it, so restarting the app cannot help); "connecting" (the process IS injected but launched moments ago and is still connecting, so waiting is what helps); "indeterminate" (the process could not be inspected). Omitted when injectable is false, which is terminal on its own.
|
|
118997
|
+
- message: the remedy for that state, in full, including for a state not listed above. Omitted when connected or non-injectable. Prefer it over inferring one from the booleans: it is the only field that can tell you to stop restarting the app.
|
|
118911
118998
|
- nextLaunchWillBeInjected: if you launch this bundle now, native devtools env setup is already in place (always false for a non-injectable app)
|
|
118912
118999
|
- injectable: whether this app is a supported target for Argent native devtools. Apple system apps (bundle ids under com.apple.) are not: they are never the app under test, so the native tools refuse to read one.
|
|
118913
119000
|
|
|
118914
119001
|
Call this before using app-scoped native hierarchy tools or native-network-logs.
|
|
118915
|
-
If injectable is false: treat this as TERMINAL
|
|
119002
|
+
If injectable is false: treat this as TERMINAL. The app is not a supported native-devtools target, and no relaunch changes that. Do NOT restart/retry. Use the standard \`describe\` tool (its accessibility path reads the screen without injection) or \`screenshot\` (then interact by coordinate). Do not fall back to the native-devtools feature tools (native-describe-screen, native-find-views, native-full-hierarchy, native-network-logs, native-view-at-point, native-user-interactable-view-at-point): they run the same injection precheck and fail with the same non-injectable error.
|
|
118916
119003
|
If appRunning is false and nextLaunchWillBeInjected is true: use launch-app normally.
|
|
118917
|
-
If requiresRestart is true: call restart-app once, then proceed with the native feature. Read state before acting on a second such reading
|
|
118918
|
-
If state is unregistered: do NOT restart the app again
|
|
118919
|
-
If state is connecting: do NOT restart the app
|
|
118920
|
-
If state is indeterminate: the process could not be inspected, so restart-app is worth one attempt. If this call still reports it after that restart, do NOT restart the app again
|
|
119004
|
+
If requiresRestart is true: call restart-app once, then proceed with the native feature. Read state before acting on a second such reading. Indeterminate reaches this rule too, and its line below bounds it at that one restart.
|
|
119005
|
+
If state is unregistered: do NOT restart the app again: it already launched under the terms a restart would recreate. Restart the tool-server (\`argent server stop && argent server start --detach\`), then retry. If it reads unregistered again after that restart, stop: the process loads argent's dylib but never dials, and no further restart on either side changes it. Treat native devtools as unavailable, then use \`describe\` or \`screenshot\` and drive by coordinate.
|
|
119006
|
+
If state is connecting: do NOT restart the app. Launching it is what starts the connection, so a relaunch discards the one in progress and returns this same state. Wait a few seconds and repeat this call.
|
|
119007
|
+
If state is indeterminate: the process could not be inspected, so restart-app is worth one attempt. If this call still reports it after that restart, do NOT restart the app again: the service is stale rather than the app uninjected, so restart the tool-server (\`argent server stop && argent server start --detach\`) and retry. Remote simulators can never inspect the process, so this is the only unconnected state a running app reaches there.
|
|
118921
119008
|
Returns { status: "init_failed", message, attempts } instead when the simulator's native-devtools environment failed to initialize.
|
|
118922
119009
|
Fails if the simulator server is not running for the given UDID.`,
|
|
118923
119010
|
zodSchema: zodSchema2,
|
|
@@ -119012,8 +119099,8 @@ var nativeNetworkLogsTool = {
|
|
|
119012
119099
|
Unlike the JS-level network inspector (view-network-logs), this captures ALL network traffic from the app including native modules, Swift/Objective-C networking, and background transfers that bypass JS fetch.
|
|
119013
119100
|
Use when you need to inspect native-level HTTP traffic that is invisible to JS fetch interception.
|
|
119014
119101
|
Returns { status, count, events } where each event contains URL, method, status code, headers, and timing.
|
|
119015
|
-
If status is restart_required: follow the message (usually restart-app), then retry. If status is service_stale: the app is already injected, so restarting it cannot help
|
|
119016
|
-
A not-running app comes back as one of those statuses rather than a failure. An app that is not connected does too, except on a device whose devtools agent argent attached to rather than armed itself
|
|
119102
|
+
If status is restart_required: follow the message (usually restart-app), then retry. If status is service_stale: the app is already injected, so restarting it cannot help. Restart the tool-server (\`argent server stop && argent server start --detach\`) and retry. If the same status comes back after that restart, stop restarting: follow the message, which names the terminal fallback. If status is connect_pending: the app is injected and still connecting. Do not restart it, wait a few seconds and retry. If status is init_failed: the simulator's native-devtools environment could not be initialised. Follow the message (re-boot the simulator) rather than retrying this tool.
|
|
119103
|
+
A not-running app comes back as one of those statuses rather than a failure. An app that is not connected does too, except on a device whose devtools agent argent attached to rather than armed itself: there it fails with \`NATIVE_DEVTOOLS_NOT_CONNECTED\`, since no restart of ours can complete a handshake we do not own. Failures are separate: an Apple system app is rejected outright (terminal: never retry it), while a missing host dependency or a udid that is not an Apple device is not.`,
|
|
119017
119104
|
zodSchema: zodSchema3,
|
|
119018
119105
|
services: (params) => ({
|
|
119019
119106
|
nativeDevtools: nativeDevtoolsRef(resolveDevice(params.udid))
|
|
@@ -119075,8 +119162,8 @@ var nativeFindViewsTool = {
|
|
|
119075
119162
|
Use when you need to locate a specific view by its properties without dumping the entire hierarchy.
|
|
119076
119163
|
Returns { status: "ok", matches } with matching views including their frames, properties, optional ancestors, and optional children. Much more targeted than native-full-hierarchy.
|
|
119077
119164
|
At least one of className, identifier, label, tag, or nativeID must be provided.
|
|
119078
|
-
If status is restart_required: follow the message (usually restart-app), then retry. If status is service_stale: the app is already injected, so restarting it cannot help
|
|
119079
|
-
A not-connected or not-running app comes back as one of those statuses rather than a failure. Failures are separate: an Apple system app is rejected outright (terminal
|
|
119165
|
+
If status is restart_required: follow the message (usually restart-app), then retry. If status is service_stale: the app is already injected, so restarting it cannot help. Restart the tool-server (\`argent server stop && argent server start --detach\`) and retry. If the same status comes back after that restart, stop restarting: follow the message, which names the terminal fallback. If status is connect_pending: the app is injected and still connecting. Do not restart it, wait a few seconds and retry. If status is init_failed: the simulator's native-devtools environment could not be initialised. Follow the message (re-boot the simulator) rather than retrying this tool.
|
|
119166
|
+
A not-connected or not-running app comes back as one of those statuses rather than a failure. Failures are separate: an Apple system app is rejected outright (terminal: never retry it), and the hierarchy query itself can error or time out.`,
|
|
119080
119167
|
zodSchema: zodSchema4,
|
|
119081
119168
|
services: (params) => ({
|
|
119082
119169
|
nativeDevtools: nativeDevtoolsRef(resolveDevice(params.udid))
|
|
@@ -119126,7 +119213,7 @@ var zodSchema5 = external_exports.object({
|
|
|
119126
119213
|
'Exact UIView class names whose entire subtree should be pruned (e.g. ["UIImageView"] to drop image leaf nodes)'
|
|
119127
119214
|
),
|
|
119128
119215
|
skipClassPrefixes: external_exports.array(external_exports.string()).optional().describe(
|
|
119129
|
-
'Class name prefixes to prune entire subtrees. For SwiftUI apps use ["_TtGC7SwiftUI"] to drop mangled SwiftUI generic type subtrees while keeping _UIHostingView and UIKit bridges. Avoid broad prefixes like "_UI"
|
|
119216
|
+
'Class name prefixes to prune entire subtrees. For SwiftUI apps use ["_TtGC7SwiftUI"] to drop mangled SwiftUI generic type subtrees while keeping _UIHostingView and UIKit bridges. Avoid broad prefixes like "_UI": they prune useful system views.'
|
|
119130
119217
|
),
|
|
119131
119218
|
maxDepth: external_exports.number().int().positive().optional().describe(
|
|
119132
119219
|
"Maximum recursion depth (default 8). Increase for deeper inspection, decrease to reduce output size."
|
|
@@ -119145,8 +119232,8 @@ WARNING: Output can be extremely large (100KB\u2013500KB+) for complex apps, esp
|
|
|
119145
119232
|
Use skipClasses / skipClassPrefixes to prune SwiftUI internal subtrees and reduce output size. Use the fields param to request only the properties you need.
|
|
119146
119233
|
Use when you need deep layout debugging, finding views with no accessibility labels, or verifying view structure not exposed through the accessibility tree.
|
|
119147
119234
|
Returns { status: "ok", windows, screen } with the full view hierarchy. screen gives the screen size in points on its portrait axes, and the interfaceOrientation of the UI (portrait, portraitUpsideDown, landscapeLeft, landscapeRight). Each screenFrame uses the portrait axes of the screen. Each windowFrame uses the axes of its window, which turn with the UI.
|
|
119148
|
-
If status is restart_required: follow the message (usually restart-app), then retry. If status is service_stale: the app is already injected, so restarting it cannot help
|
|
119149
|
-
A not-connected or not-running app comes back as one of those statuses rather than a failure. Failures are separate: an Apple system app is rejected outright (terminal
|
|
119235
|
+
If status is restart_required: follow the message (usually restart-app), then retry. If status is service_stale: the app is already injected, so restarting it cannot help. Restart the tool-server (\`argent server stop && argent server start --detach\`) and retry. If the same status comes back after that restart, stop restarting: follow the message, which names the terminal fallback. If status is connect_pending: the app is injected and still connecting. Do not restart it, wait a few seconds and retry. If status is init_failed: the simulator's native-devtools environment could not be initialised. Follow the message (re-boot the simulator) rather than retrying this tool.
|
|
119236
|
+
A not-connected or not-running app comes back as one of those statuses rather than a failure. Failures are separate: an Apple system app is rejected outright (terminal: never retry it), and the hierarchy query itself can error or time out.`,
|
|
119150
119237
|
zodSchema: zodSchema5,
|
|
119151
119238
|
services: (params) => ({
|
|
119152
119239
|
nativeDevtools: nativeDevtoolsRef(resolveDevice(params.udid))
|
|
@@ -119214,8 +119301,8 @@ Use when you are evaluating or debugging the lower-level native data behind the
|
|
|
119214
119301
|
describe tool, or when you need its raw point-space geometry rather than describe's
|
|
119215
119302
|
normalized contract.
|
|
119216
119303
|
|
|
119217
|
-
If status is restart_required: follow the message (usually restart-app), then retry. If status is service_stale: the app is already injected, so restarting it cannot help
|
|
119218
|
-
A not-connected or not-running app comes back as one of those statuses rather than a failure. Failures are separate: an Apple system app is rejected outright (terminal
|
|
119304
|
+
If status is restart_required: follow the message (usually restart-app), then retry. If status is service_stale: the app is already injected, so restarting it cannot help. Restart the tool-server (\`argent server stop && argent server start --detach\`) and retry. If the same status comes back after that restart, stop restarting: follow the message, which names the terminal fallback. If status is connect_pending: the app is injected and still connecting. Do not restart it, wait a few seconds and retry. If status is init_failed: the simulator's native-devtools environment could not be initialised. Follow the message (re-boot the simulator) rather than retrying this tool.
|
|
119305
|
+
A not-connected or not-running app comes back as one of those statuses rather than a failure. Failures are separate: an Apple system app is rejected outright (terminal: never retry it), and the screen query itself can error or time out.`,
|
|
119219
119306
|
zodSchema: zodSchema6,
|
|
119220
119307
|
services: (params) => ({
|
|
119221
119308
|
nativeDevtools: nativeDevtoolsRef(resolveDevice(params.udid))
|
|
@@ -119283,8 +119370,8 @@ var nativeViewAtPointTool = {
|
|
|
119283
119370
|
Unlike native-user-interactable-view-at-point, this ignores userInteractionEnabled,
|
|
119284
119371
|
so it answers "what is visually here?" rather than "what would receive the touch?".
|
|
119285
119372
|
|
|
119286
|
-
Use when a screenshot shows something the accessibility tree does not name
|
|
119287
|
-
unlabeled icon, a decorative overlay, a custom-drawn cell
|
|
119373
|
+
Use when a screenshot shows something the accessibility tree does not name (an
|
|
119374
|
+
unlabeled icon, a decorative overlay, a custom-drawn cell) and you need the class,
|
|
119288
119375
|
identifier or nativeID of whatever draws it.
|
|
119289
119376
|
|
|
119290
119377
|
Returns { status: "ok", view }: the matched view with its class name, frames,
|
|
@@ -119296,8 +119383,8 @@ normalized [0,1] simulator tap coordinates. To get them from a describe frame,
|
|
|
119296
119383
|
multiply the normalized values by the screen size in points. Do this also when
|
|
119297
119384
|
the UI is landscape.
|
|
119298
119385
|
|
|
119299
|
-
If status is restart_required: follow the message (usually restart-app), then retry. If status is service_stale: the app is already injected, so restarting it cannot help
|
|
119300
|
-
A not-connected or not-running app comes back as one of those statuses rather than a failure. Failures are separate: an Apple system app is rejected outright (terminal
|
|
119386
|
+
If status is restart_required: follow the message (usually restart-app), then retry. If status is service_stale: the app is already injected, so restarting it cannot help. Restart the tool-server (\`argent server stop && argent server start --detach\`) and retry. If the same status comes back after that restart, stop restarting: follow the message, which names the terminal fallback. If status is connect_pending: the app is injected and still connecting. Do not restart it, wait a few seconds and retry. If status is init_failed: the simulator's native-devtools environment could not be initialised. Follow the message (re-boot the simulator) rather than retrying this tool.
|
|
119387
|
+
A not-connected or not-running app comes back as one of those statuses rather than a failure. Failures are separate: an Apple system app is rejected outright (terminal: never retry it), and the point query itself can error or time out.`,
|
|
119301
119388
|
zodSchema: zodSchema7,
|
|
119302
119389
|
services: (params) => ({
|
|
119303
119390
|
nativeDevtools: nativeDevtoolsRef(resolveDevice(params.udid))
|
|
@@ -119372,7 +119459,7 @@ Unlike native-view-at-point, this respects userInteractionEnabled and is closer
|
|
|
119372
119459
|
UIKit hit-testing semantics.
|
|
119373
119460
|
|
|
119374
119461
|
Use when a tap lands somewhere unexpected or does nothing, to see which control
|
|
119375
|
-
UIKit would hand the touch to
|
|
119462
|
+
UIKit would hand the touch to: a transparent overlay swallowing it, a parent
|
|
119376
119463
|
recognizer, a disabled button.
|
|
119377
119464
|
|
|
119378
119465
|
Returns { status: "ok", view }: the hit-test winner with its class name, frames,
|
|
@@ -119384,8 +119471,8 @@ normalized [0,1] simulator tap coordinates. To get them from a describe frame,
|
|
|
119384
119471
|
multiply the normalized values by the screen size in points. Do this also when
|
|
119385
119472
|
the UI is landscape.
|
|
119386
119473
|
|
|
119387
|
-
If status is restart_required: follow the message (usually restart-app), then retry. If status is service_stale: the app is already injected, so restarting it cannot help
|
|
119388
|
-
A not-connected or not-running app comes back as one of those statuses rather than a failure. Failures are separate: an Apple system app is rejected outright (terminal
|
|
119474
|
+
If status is restart_required: follow the message (usually restart-app), then retry. If status is service_stale: the app is already injected, so restarting it cannot help. Restart the tool-server (\`argent server stop && argent server start --detach\`) and retry. If the same status comes back after that restart, stop restarting: follow the message, which names the terminal fallback. If status is connect_pending: the app is injected and still connecting. Do not restart it, wait a few seconds and retry. If status is init_failed: the simulator's native-devtools environment could not be initialised. Follow the message (re-boot the simulator) rather than retrying this tool.
|
|
119475
|
+
A not-connected or not-running app comes back as one of those statuses rather than a failure. Failures are separate: an Apple system app is rejected outright (terminal: never retry it), and the point query itself can error or time out.`,
|
|
119389
119476
|
zodSchema: zodSchema8,
|
|
119390
119477
|
services: (params) => ({
|
|
119391
119478
|
nativeDevtools: nativeDevtoolsRef(resolveDevice(params.udid))
|
|
@@ -119501,7 +119588,7 @@ init_zod();
|
|
|
119501
119588
|
init_external_devices();
|
|
119502
119589
|
var DEFAULT_METRO_PORT = 8081;
|
|
119503
119590
|
var metroPortField = external_exports.coerce.number().int().min(1).max(65535).optional().describe(
|
|
119504
|
-
"Metro server port. Optional
|
|
119591
|
+
"Metro server port. Optional: omit it to use this device's port, 8081 by default. Ignored for Chromium, whose CDP port is encoded in device_id."
|
|
119505
119592
|
);
|
|
119506
119593
|
function metroPort(params) {
|
|
119507
119594
|
if (params.port !== void 0) return params.port;
|
|
@@ -121451,9 +121538,10 @@ async function bootElectronApp(options) {
|
|
|
121451
121538
|
}
|
|
121452
121539
|
const onSpawnError = (err, reject) => {
|
|
121453
121540
|
const codeSuffix = err.code ? ` (${err.code})` : "";
|
|
121541
|
+
const installHint = launcher.command === "electron" && err.code === "ENOENT" ? ` Make sure 'electron' is installed (npm i electron in the app dir, or globally) and on PATH.` : "";
|
|
121454
121542
|
reject(
|
|
121455
121543
|
new FailureError(
|
|
121456
|
-
`Electron boot: failed to launch ${launcher.command}${codeSuffix}: ${err.message}
|
|
121544
|
+
`Electron boot: failed to launch ${launcher.command}${codeSuffix}: ${err.message}.${installHint}`,
|
|
121457
121545
|
{
|
|
121458
121546
|
error_code: FAILURE_CODES.CHROMIUM_ELECTRON_SPAWN_FAILED,
|
|
121459
121547
|
failure_stage: "electron_spawn_error",
|
|
@@ -121474,18 +121562,21 @@ async function bootElectronApp(options) {
|
|
|
121474
121562
|
};
|
|
121475
121563
|
child.once("error", spawnErrorListener);
|
|
121476
121564
|
if (!child.pid) {
|
|
121477
|
-
|
|
121478
|
-
|
|
121479
|
-
|
|
121480
|
-
|
|
121481
|
-
|
|
121482
|
-
|
|
121483
|
-
|
|
121484
|
-
|
|
121485
|
-
|
|
121486
|
-
|
|
121487
|
-
|
|
121488
|
-
|
|
121565
|
+
return Promise.race([
|
|
121566
|
+
spawnError,
|
|
121567
|
+
sleepUnref(1e3).then(() => {
|
|
121568
|
+
throw new FailureError(
|
|
121569
|
+
`Electron boot: spawn returned without a pid (binary: ${launcher.command}).`,
|
|
121570
|
+
{
|
|
121571
|
+
error_code: FAILURE_CODES.CHROMIUM_ELECTRON_SPAWN_FAILED,
|
|
121572
|
+
failure_stage: "electron_spawn_no_pid",
|
|
121573
|
+
failure_area: "tool_server",
|
|
121574
|
+
error_kind: "subprocess",
|
|
121575
|
+
failure_command: "electron"
|
|
121576
|
+
}
|
|
121577
|
+
);
|
|
121578
|
+
})
|
|
121579
|
+
]);
|
|
121489
121580
|
}
|
|
121490
121581
|
child.stderr?.on("data", (chunk) => {
|
|
121491
121582
|
process.stderr.write(`[chromium-cdp-${port}] ${chunk}`);
|
|
@@ -121556,14 +121647,14 @@ var zodSchema9 = external_exports.object({
|
|
|
121556
121647
|
"Android: AVD name to launch a new emulator from (from `list-devices` \u2192 `avds[].name`). Provide exactly one of `udid`, `avdName`, `vvdImage`, or `electronAppPath`."
|
|
121557
121648
|
),
|
|
121558
121649
|
vvdImage: external_exports.string().optional().describe(
|
|
121559
|
-
"Vega (Fire TV): VVD image to boot
|
|
121650
|
+
"Vega (Fire TV): VVD image to boot: the `vvdImage` of a Vega device from `list-devices` (e.g. `tv`). Starts the single SDK-managed Vega Virtual Device. Provide exactly one of `udid`, `avdName`, `vvdImage`, or `electronAppPath`."
|
|
121560
121651
|
),
|
|
121561
121652
|
bootTimeoutMs: external_exports.number().int().min(3e4).max(9e5).optional().describe(
|
|
121562
121653
|
"Android/Vega: overall budget for the boot sequence. Default 480000 (8 min) on Android, 120000 (2 min) on Vega. Clamped to [30s, 15min]. Ignored on iOS."
|
|
121563
121654
|
),
|
|
121564
121655
|
force: external_exports.boolean().optional().describe("Shut down and re-boot the device even if already running."),
|
|
121565
121656
|
sound: external_exports.boolean().optional().describe(
|
|
121566
|
-
"Android only: boot the emulator with audio output enabled. Defaults to false
|
|
121657
|
+
"Android only: boot the emulator with audio output enabled. Defaults to false: argent boots emulators MUTED so several agent-driven devices don't all play sound on the host machine; pass `true` when the task involves playing, hearing, or testing audio. Takes effect at boot: if the emulator is already running muted, add `force: true` to reboot it with sound. A boot snapshot saved in the other audio mode can't be reused, so the first boot after toggling is a slower cold boot. The `boot-sound` argent flag flips this default to true. Ignored on iOS/Vega/Electron, which argent never mutes."
|
|
121567
121658
|
),
|
|
121568
121659
|
headless: external_exports.boolean().optional().describe(
|
|
121569
121660
|
"iOS only: boot the simulator core WITHOUT opening its GUI window (Simulator.app, or Device Hub on Xcode 27+). The device still streams via simulator-server; used by Argent Lens. Set the `ARGENT_SIMULATOR_NO_WINDOW` env var (1/true/yes) to force this host-wide without passing the flag per call (the iOS analog of `ARGENT_EMULATOR_NO_WINDOW`). Ignored on Android/Vega/Electron, which have no equivalent GUI step."
|
|
@@ -122707,8 +122798,9 @@ async function resolveLauncherActivity(udid, bundleId, isTv = false) {
|
|
|
122707
122798
|
}
|
|
122708
122799
|
const launcher = await resolveFor();
|
|
122709
122800
|
if (launcher) return launcher;
|
|
122801
|
+
const pmPath = await adbShell(udid, `pm path ${shellQuote(bundleId)}; true`);
|
|
122710
122802
|
throw new FailureError(
|
|
122711
|
-
`Could not resolve a ${isTv ? "LEANBACK_LAUNCHER or LAUNCHER" : "LAUNCHER"} activity for ${bundleId}.
|
|
122803
|
+
`Could not resolve a ${isTv ? "LEANBACK_LAUNCHER or LAUNCHER" : "LAUNCHER"} activity for ${bundleId}. ` + (pmPath.includes("package:") ? `It is installed but declares no such activity: pass an explicit \`activity\`. ` : `It is not installed on ${udid}: install it with \`reinstall-app\`. `) + `(resolve-activity output: ${lastRaw.trim() || "empty"})`,
|
|
122712
122804
|
{
|
|
122713
122805
|
error_code: FAILURE_CODES.ANDROID_LAUNCH_ACTIVITY_RESOLVE_FAILED,
|
|
122714
122806
|
failure_stage: "android_launch_resolve_activity",
|
|
@@ -122796,7 +122888,7 @@ function createLaunchAppTool(registry2) {
|
|
|
122796
122888
|
failedMsg: ({ params, failureSignal: failureSignal2 }) => `Failed to launch ${params.bundleId}: ${failureSignal2.error_code}`
|
|
122797
122889
|
},
|
|
122798
122890
|
description: `Open an app by its bundle id (iOS) or package name (Android), or confirm the running renderer (Chromium).
|
|
122799
|
-
Use when starting any app
|
|
122891
|
+
Use when starting any app; prefer this over tapping home-screen / launcher icons. Also prepares the native-devtools injection before the app starts (the iOS slice on iOS, the tvOS slice on Apple TV); on tvOS, interaction is focus-driven; use the tv-* tools rather than coordinate taps.
|
|
122800
122892
|
Returns { launched, bundleId, note? }. Fails if the app is not installed on the target device (iOS / Android). On a physical iPhone this registers the app every other tool acts on; com.apple.springboard and com.apple.Spotlight register without launching. note warns when runner signing is not ready.
|
|
122801
122893
|
For Chromium, the app is already running behind a CDP port; this call simply refreshes the cached viewport and acknowledges the bundleId tag. To change the visible route, use \`open-url\`.
|
|
122802
122894
|
On Vega (Fire TV), pass the interactive component app id from manifest.toml (e.g. com.example.app.main) as bundleId.
|
|
@@ -123015,7 +123107,7 @@ function createRestartAppTool(registry2) {
|
|
|
123015
123107
|
failedMsg: ({ params, failureSignal: failureSignal2 }) => `Failed to restart ${params.bundleId}: ${failureSignal2.error_code}`
|
|
123016
123108
|
},
|
|
123017
123109
|
description: `Terminate then relaunch an app by bundle id / package name.
|
|
123018
|
-
Use when you need a clean in-memory state without a full reinstall. Also refreshes the native-devtools injection before the relaunch (the iOS slice on iOS, the tvOS slice on Apple TV); on tvOS, interaction is focus-driven
|
|
123110
|
+
Use when you need a clean in-memory state without a full reinstall. Also refreshes the native-devtools injection before the relaunch (the iOS slice on iOS, the tvOS slice on Apple TV); on tvOS, interaction is focus-driven; use the tv-* tools rather than coordinate taps.
|
|
123019
123111
|
Returns { restarted, bundleId }. Fails if the app is not installed.`,
|
|
123020
123112
|
alwaysLoad: true,
|
|
123021
123113
|
searchHint: "terminate relaunch restart reset app bundle id package simulator emulator vega tvos fire tv",
|
|
@@ -123584,7 +123676,7 @@ var zodSchema14 = external_exports.object({
|
|
|
123584
123676
|
"The permission to change. `notifications` is Android-only (iOS has no simctl service for it); `reminders` is iOS-only; `camera` works on Android and on iOS only when the target simulator's runtime models the service (varies by simruntime, not by the installed Xcode)."
|
|
123585
123677
|
),
|
|
123586
123678
|
bundleId: external_exports.string().regex(BUNDLE_ID_PATTERN, BUNDLE_ID_MESSAGE).describe(
|
|
123587
|
-
"App to change the permission for
|
|
123679
|
+
"App to change the permission for, required for every action. iOS: bundle id (e.g. com.example.app). Android: package name. `reset` is per-app too: simctl's device-wide reset (no bundleId) silently leaves existing per-app grants untouched on recent iOS, so the permission is always reset for this one app."
|
|
123588
123680
|
)
|
|
123589
123681
|
});
|
|
123590
123682
|
var permissionAction = {
|
|
@@ -123610,9 +123702,9 @@ var settingsPermissionsTool = {
|
|
|
123610
123702
|
},
|
|
123611
123703
|
description: `Grant, deny, or reset a runtime permission for an app without navigating the system Settings UI. Use during test setup to pre-authorize (or explicitly deny) a service before the app asks, or \`reset\` so the permission dialog appears again on next use. Always per-app: bundleId is required.
|
|
123612
123704
|
Permissions: camera, microphone, photos, contacts, notifications, calendar, location, location-always, media-library, motion, reminders.
|
|
123613
|
-
iOS simulator: edits the simulator's TCC store, always per-app. \`notifications\` is not supported (no iOS equivalent). \`reset\` is per-app
|
|
123705
|
+
iOS simulator: edits the simulator's TCC store, always per-app. \`notifications\` is not supported (no iOS equivalent). \`reset\` is per-app: a device-wide reset is a no-op for existing grants on recent iOS, so it is not offered. \`grant location\`/\`location-always\` needs the app already installed (location auth isn't stored in TCC and isn't applied to a bundle id until the app exists). This is enforced on local simulators; a remote simulator can't be probed for install state, so ensure the app is installed there first. Other services can be granted before install.
|
|
123614
123706
|
Android: changes the mapped \`android.permission.*\` runtime permissions (reset also best-effort clears the user-set permission flags). The app must be installed and declare them in its manifest; \`reminders\` has no Android equivalent.
|
|
123615
|
-
Some permission changes terminate the app if it is running (system behavior on both platforms)
|
|
123707
|
+
Some permission changes terminate the app if it is running (system behavior on both platforms), so set permissions before launching, or relaunch after.
|
|
123616
123708
|
Returns { action, permission, bundleId, applied, skipped? }: \`applied\` lists the platform-level services/permissions actually changed; \`skipped\` (Android) lists mapped permissions the package manager rejected, e.g. ones the manifest doesn't declare. Fails if nothing could be applied.`,
|
|
123617
123709
|
searchHint: "grant deny reset revoke app permissions privacy camera microphone location settings",
|
|
123618
123710
|
zodSchema: zodSchema14,
|
|
@@ -123780,7 +123872,7 @@ var openUrlTool = {
|
|
|
123780
123872
|
description: `Open a URL or URL scheme on the device.
|
|
123781
123873
|
Use to navigate to a web page or deep-link into an app. On Chromium, this navigates the primary renderer to the given URL.
|
|
123782
123874
|
Cross-platform schemes: https://, tel:, mailto:. iOS also: messages://, settings://, maps://. Android also: geo:, plus any app-specific deep link.
|
|
123783
|
-
Deep-linking caveat: an https:// link opens the native app only when an installed app is verified for the link's domain (iOS Universal Links / Android App Links)
|
|
123875
|
+
Deep-linking caveat: an https:// link opens the native app only when an installed app is verified for the link's domain (iOS Universal Links / Android App Links); otherwise it opens in the browser, and on iOS simulators it may open in Safari even when the owning app is installed. To reliably open an installed app, use its custom scheme (scheme://path) or launch-app with its bundle id.
|
|
123784
123876
|
On a physical iPhone, http(s) URLs default to Safari and any other scheme needs bundleId; the receiving app becomes the app under automation.
|
|
123785
123877
|
Returns { opened, url, note? }. note carries the deep-linking caveat when a web URL was opened on a native device. Fails if no app is registered to handle the URI (iOS/Android) or the renderer rejects the navigation (Chromium).`,
|
|
123786
123878
|
zodSchema: zodSchema15,
|
|
@@ -123810,6 +123902,7 @@ var os13 = __toESM(require("node:os"));
|
|
|
123810
123902
|
var path29 = __toESM(require("node:path"));
|
|
123811
123903
|
init_zod();
|
|
123812
123904
|
init_device_info();
|
|
123905
|
+
init_adb();
|
|
123813
123906
|
|
|
123814
123907
|
// ../tool-server/src/utils/device-orientation.ts
|
|
123815
123908
|
var import_node_fs13 = require("node:fs");
|
|
@@ -124361,7 +124454,7 @@ async function captureViaEmulatorConsole(opts) {
|
|
|
124361
124454
|
}
|
|
124362
124455
|
}
|
|
124363
124456
|
function scalePng(src, scale) {
|
|
124364
|
-
const s = scale ??
|
|
124457
|
+
const s = scale ?? getScreenshotScaleOverride() ?? tvDefaultScale(src.width, src.height);
|
|
124365
124458
|
if (s >= 1) return src;
|
|
124366
124459
|
const outW = Math.max(1, Math.round(src.width * s));
|
|
124367
124460
|
const outH = Math.max(1, Math.round(src.height * s));
|
|
@@ -124386,10 +124479,10 @@ var zodSchema16 = external_exports.object({
|
|
|
124386
124479
|
"Orientation override for the screenshot (rotates the captured image after Page.captureScreenshot on Chromium). On Android the capture already follows the device's rotation. Ignored on physical iPhones."
|
|
124387
124480
|
),
|
|
124388
124481
|
scale: external_exports.number().min(0.01).max(1).optional().describe(
|
|
124389
|
-
"Scale factor (0.01-1.0). Defaults to ARGENT_SCREENSHOT_SCALE env var, or 0.25 if unset for iOS/Android. On Chromium the default is 1.0 (no downscale); pass <1 to opt in. Downscaling on Chromium requires the optional `sharp` dependency."
|
|
124482
|
+
"Scale factor (0.01-1.0). Defaults to ARGENT_SCREENSHOT_SCALE env var, or 0.25 if unset for iOS/Android. On a local Apple TV simulator, an Android TV or Vega, with neither set, the capture is downscaled to a 576 px long side (0.15 of a 4K capture); an Android TV whose form factor or display size cannot be read in time keeps 0.25. On Chromium the default is 1.0 (no downscale); pass <1 to opt in. Downscaling on Chromium requires the optional `sharp` dependency."
|
|
124390
124483
|
),
|
|
124391
124484
|
includeImageInContext: external_exports.boolean().optional().default(true).describe(
|
|
124392
|
-
"Default true. Set false only when capturing a full-resolution PNG (scale: 1.0) to save as a baseline/current for screenshot-diff
|
|
124485
|
+
"Default true. Set false only when capturing a full-resolution PNG (scale: 1.0) to save as a baseline/current for screenshot-diff. The file is still written, but the image bytes are not attached to the agent context."
|
|
124393
124486
|
),
|
|
124394
124487
|
downscaler: external_exports.enum(["lanczos3", "box", "bilinear", "nearest"]).optional().describe(
|
|
124395
124488
|
"Downscaling algorithm when scale<1 on Chromium. Defaults to lanczos3 (highest quality). Mirrors sim-server's wire enum. Ignored on physical iPhones."
|
|
@@ -124421,7 +124514,7 @@ async function tvScreenshot(udid, scale, signal) {
|
|
|
124421
124514
|
await execFileAsync25("xcrun", await simctlArgsForUdid(udid, ["io", udid, "screenshot", file2]), {
|
|
124422
124515
|
signal
|
|
124423
124516
|
});
|
|
124424
|
-
if (scale < 1) {
|
|
124517
|
+
if (scale === void 0 || scale < 1) {
|
|
124425
124518
|
await execFileAsync25("sips", ["-Z", String(await tvTargetLongSide(file2, scale)), file2], {
|
|
124426
124519
|
signal
|
|
124427
124520
|
}).catch(() => {
|
|
@@ -124440,7 +124533,28 @@ async function tvTargetLongSide(file2, scale) {
|
|
|
124440
124533
|
}
|
|
124441
124534
|
} catch {
|
|
124442
124535
|
}
|
|
124443
|
-
return Math.round(longSide * scale);
|
|
124536
|
+
return scale === void 0 ? Math.min(TV_DEFAULT_LONG_SIDE, longSide) : Math.round(longSide * scale);
|
|
124537
|
+
}
|
|
124538
|
+
var ANDROID_TV_PROBE_BUDGET_MS = 2e3;
|
|
124539
|
+
async function androidTvDefaultScale(serial, notBefore) {
|
|
124540
|
+
if (getScreenshotScaleOverride() !== void 0) return void 0;
|
|
124541
|
+
const probe3 = Promise.all([
|
|
124542
|
+
isAndroidTv(serial).catch(() => false),
|
|
124543
|
+
getAndroidScreenSize(serial).catch(() => void 0)
|
|
124544
|
+
]).then(([isTv, size]) => isTv && size ? tvDefaultScale(size.width, size.height) : void 0);
|
|
124545
|
+
let timer;
|
|
124546
|
+
const budget = new Promise((resolve14) => {
|
|
124547
|
+
timer = setTimeout(resolve14, ANDROID_TV_PROBE_BUDGET_MS);
|
|
124548
|
+
});
|
|
124549
|
+
try {
|
|
124550
|
+
return await Promise.race([
|
|
124551
|
+
probe3,
|
|
124552
|
+
Promise.all([budget, notBefore.catch(() => {
|
|
124553
|
+
})]).then(() => void 0)
|
|
124554
|
+
]);
|
|
124555
|
+
} finally {
|
|
124556
|
+
clearTimeout(timer);
|
|
124557
|
+
}
|
|
124444
124558
|
}
|
|
124445
124559
|
async function downscalePngInPlace(file2, scale, signal) {
|
|
124446
124560
|
if (scale >= 1) {
|
|
@@ -124507,7 +124621,11 @@ Fails if the simulator-server / emulator backend / Chromium CDP is not reachable
|
|
|
124507
124621
|
return { image: image2, ...note ? { [RESULT_NOTE_KEY]: note } : {} };
|
|
124508
124622
|
}
|
|
124509
124623
|
if (device.platform === "ios" && await isTvOsSimulator(params.udid)) {
|
|
124510
|
-
const pngPath = await tvScreenshot(
|
|
124624
|
+
const pngPath = await tvScreenshot(
|
|
124625
|
+
params.udid,
|
|
124626
|
+
params.scale ?? getScreenshotScaleOverride(),
|
|
124627
|
+
signal
|
|
124628
|
+
);
|
|
124511
124629
|
const image2 = await requireArtifacts(ctx).register({
|
|
124512
124630
|
hostPath: pngPath,
|
|
124513
124631
|
kind: "screenshot",
|
|
@@ -124533,14 +124651,18 @@ Fails if the simulator-server / emulator backend / Chromium CDP is not reachable
|
|
|
124533
124651
|
return { image: image2, ...note ? { [RESULT_NOTE_KEY]: note } : {} };
|
|
124534
124652
|
}
|
|
124535
124653
|
const ref = simulatorServerRef(device);
|
|
124536
|
-
const
|
|
124654
|
+
const apiReady = registry2.resolveService(ref.urn, ref.options);
|
|
124655
|
+
const [api, androidTvScale] = await Promise.all([
|
|
124656
|
+
apiReady,
|
|
124657
|
+
params.scale === void 0 && device.platform === "android" ? androidTvDefaultScale(device.id, apiReady) : void 0
|
|
124658
|
+
]);
|
|
124537
124659
|
const panel = await resolveCapturePanel(api);
|
|
124538
124660
|
const { path: capturedPath } = await captureScreenshotUpright(
|
|
124539
124661
|
api,
|
|
124540
124662
|
device,
|
|
124541
124663
|
params.rotation,
|
|
124542
124664
|
signal,
|
|
124543
|
-
params.scale,
|
|
124665
|
+
params.scale ?? androidTvScale,
|
|
124544
124666
|
panel ? (a, r, s, sc) => httpScreenshot(a, r, s, sc, panel.screen) : void 0,
|
|
124545
124667
|
androidDevtoolsRotationPeek(registry2, device)
|
|
124546
124668
|
);
|
|
@@ -124632,11 +124754,11 @@ var gestureTapTool = {
|
|
|
124632
124754
|
},
|
|
124633
124755
|
description: `Press the device screen (iOS simulator or physical device, Android emulator, or Chromium app) at normalized coordinates: x and y are fractions of screen width and height in 0.0\u20131.0 (not pixels).
|
|
124634
124756
|
Sends a Down event followed by an Up event at the same point. For Chromium, this dispatches a CDP mouse-press/release on the renderer.
|
|
124635
|
-
Set clickCount: 2 for a double-tap / double-click
|
|
124757
|
+
Set clickCount: 2 for a double-tap / double-click: the taps are dispatched as one gesture with proper click counting, which two separate tap calls cannot guarantee.
|
|
124636
124758
|
Use when you need to tap a button, link, or any tappable element on the screen.
|
|
124637
124759
|
Returns { tapped: true, timestampMs }. On physical iOS, reactivated: true = app was re-fronted; re-describe. Fails if the simulator-server / emulator backend / Chromium CDP is not reachable for the given device.
|
|
124638
124760
|
On a physical iPhone use \`describe\`; \`native-describe-screen\` is simulator-only.
|
|
124639
|
-
Before tapping, determine the correct coordinates by using discovery tools
|
|
124761
|
+
Before tapping, determine the correct coordinates by using discovery tools. Pick by platform: iOS / Android use \`describe\`, \`native-describe-screen\`, or \`debugger-component-tree\`; Chromium uses \`describe\` (the DOM walker), since the native and RN-specific discovery tools don't apply. More information in \`argent-device-interact\` skill`,
|
|
124640
124762
|
alwaysLoad: true,
|
|
124641
124763
|
searchHint: "tap press button element device simulator emulator chromium touch down up click",
|
|
124642
124764
|
zodSchema: zodSchema17,
|
|
@@ -124751,7 +124873,7 @@ var gestureSwipeTool = {
|
|
|
124751
124873
|
description: `Execute a smooth swipe / drag touch gesture between two points on the device (iOS simulator or physical device, or Android emulator). All from/to positions are normalized 0.0\u20131.0 (fractions of screen width/height, not pixels), same as gesture-tap.
|
|
124752
124874
|
Generates interpolated Move events for a natural feel (~60fps).
|
|
124753
124875
|
Swipe up (fromY > toY) to scroll content down.
|
|
124754
|
-
Use when you need to scroll a list, dismiss a modal, drag an element, or navigate between pages. Not supported on Chromium
|
|
124876
|
+
Use when you need to scroll a list, dismiss a modal, drag an element, or navigate between pages. Not supported on Chromium; use gesture-scroll there instead.
|
|
124755
124877
|
Physical iOS: an edge gesture (back-swipe) needs fromX 0 exactly; durationMs sets drag speed, not time; momentum:false only rests 300ms at the end and does not damp.
|
|
124756
124878
|
Pass momentum:false for a momentum-free swipe that lands where the finger lifts (little to no fling at the 300 default), when you need a deterministic scroll distance; it needs durationMs >= 150 and is rejected below that, a shorter ease-out leaving the OS too little wall clock to read the deceleration as a stop. At 150 it lands short of the lift point instead, and 2 of 47 runs still flung backwards. A plain swipe takes any duration up to 10000ms and is delivered as close to the speed it was authored as a 16ms frame allows: below ~32ms the whole travel lands in one or two frames, which the OS flings as hard as it flings anything. Returns { swiped: true, timestampMs }. On physical iOS, reactivated: true = app was re-fronted; re-describe. Fails if the simulator-server / emulator backend is not reachable for the given device.`,
|
|
124757
124879
|
alwaysLoad: true,
|
|
@@ -124854,7 +124976,7 @@ var sleep4 = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
|
124854
124976
|
var zodSchema19 = external_exports.object({
|
|
124855
124977
|
udid: external_exports.string().describe("Target Chromium device id from `list-devices` (chromium-cdp-<port>)."),
|
|
124856
124978
|
x: external_exports.number().describe(
|
|
124857
|
-
"Anchor x: normalized 0.0\u20131.0 (fraction of window width, not pixels). The wheel events land here
|
|
124979
|
+
"Anchor x: normalized 0.0\u20131.0 (fraction of window width, not pixels). The wheel events land here; put it over the element you want to scroll."
|
|
124858
124980
|
),
|
|
124859
124981
|
y: external_exports.number().describe("Anchor y: normalized 0.0\u20131.0 (fraction of window height, not pixels)."),
|
|
124860
124982
|
deltaX: external_exports.number().optional().describe(
|
|
@@ -124887,9 +125009,8 @@ var gestureScrollTool = {
|
|
|
124887
125009
|
failedMsg: ({ failureSignal: failureSignal2 }) => `Failed to scroll: ${failureSignal2.error_code}`
|
|
124888
125010
|
},
|
|
124889
125011
|
description: `Scroll content in a Chromium app by dispatching mouse-wheel events at a point. Anchor x/y are normalized 0.0\u20131.0 (fractions of the window, not pixels), same coordinate space as gesture-tap and describe. Deltas are fractions of the window too: deltaY 0.5 scrolls down half a window; negative scrolls back up.
|
|
124890
|
-
Use when content is below/above the fold (describe shows off-screen elements with zero height) or a list needs scrolling. Chromium only
|
|
125012
|
+
Use when content is below/above the fold (describe shows off-screen elements with zero height) or a list needs scrolling. Chromium only: on iOS/Android use gesture-swipe.
|
|
124891
125013
|
Returns { scrolled: true, timestampMs }. Fails if the Chromium CDP session is not reachable for the given device.`,
|
|
124892
|
-
alwaysLoad: true,
|
|
124893
125014
|
searchHint: "scroll wheel list page chromium mouse down up content fold",
|
|
124894
125015
|
zodSchema: zodSchema19,
|
|
124895
125016
|
capability: capability11,
|
|
@@ -124933,7 +125054,7 @@ var zodSchema20 = external_exports.object({
|
|
|
124933
125054
|
`Total drag duration in milliseconds (default 300, at most ${MAX_DURATION_MS2} - the button stays down for exactly this long), interpolated at ~60fps.`
|
|
124934
125055
|
),
|
|
124935
125056
|
momentum: external_exports.boolean().optional().describe(
|
|
124936
|
-
"Whether the drag releases with momentum; default true (a constant-speed drag). Pass false to decelerate into the release point (ease-out) so an app deriving fling from pointer release velocity (carousels, drag libraries) reads ~0 and applies little to no momentum
|
|
125057
|
+
"Whether the drag releases with momentum; default true (a constant-speed drag). Pass false to decelerate into the release point (ease-out) so an app deriving fling from pointer release velocity (carousels, drag libraries) reads ~0 and applies little to no momentum. Use it when the drag must stop where it was aimed rather than fling past. Deceleration needs wall clock: under ~100ms the whole drag fits inside the velocity window a page averages over (tens of ms), so some fling survives, and under ~70ms its extra frames cannot dispatch fast enough to fit durationMs. Keep durationMs at its default when the fling must be fully suppressed."
|
|
124937
125058
|
),
|
|
124938
125059
|
// `momentum`'s earlier spelling, with the opposite polarity. Declared so this
|
|
124939
125060
|
// non-strict object refuses it instead of stripping it and running the default.
|
|
@@ -124953,10 +125074,9 @@ var gestureDragTool = {
|
|
|
124953
125074
|
completedMsg: ({ params }) => `Dragged from (${Math.round(params.fromX * 100)}%, ${Math.round(params.fromY * 100)}%) to (${Math.round(params.toX * 100)}%, ${Math.round(params.toY * 100)}%)`,
|
|
124954
125075
|
failedMsg: ({ failureSignal: failureSignal2 }) => `Failed to drag: ${failureSignal2.error_code}`
|
|
124955
125076
|
},
|
|
124956
|
-
description: `Press the left mouse button at a start point, move to an end point, and release
|
|
124957
|
-
Use for slider thumbs, drag-and-drop, text selection, or draggable UI elements. Dragging never scrolls content on desktop
|
|
125077
|
+
description: `Press the left mouse button at a start point, move to an end point, and release: a desktop mouse drag in a Chromium app. All positions are normalized 0.0\u20131.0 (fractions of the window, not pixels), same coordinate space as gesture-tap and describe, except that a coordinate of exactly 1.0 lands one pixel inside the window edge (gesture-tap maps it to the edge itself). Interpolates mouse-move events at ~60fps over durationMs for a natural drag (a momentum-free drag samples more finely when durationMs is short, so its ease-out has a curve).
|
|
125078
|
+
Use for slider thumbs, drag-and-drop, text selection, or draggable UI elements. Dragging never scrolls content on desktop; use gesture-scroll for lists/pages. Chromium only: on iOS/Android use gesture-swipe.
|
|
124958
125079
|
Pass momentum:false for a momentum-free drag that decelerates into the release, so apps that compute a fling from the pointer stream read ~0 velocity and the drag ends where it was aimed instead of flinging past it (a durationMs under ~100ms is too short for the deceleration to suppress the fling entirely). Returns { dragged: true, timestampMs }. Fails if the Chromium CDP session is not reachable for the given device.`,
|
|
124959
|
-
alwaysLoad: true,
|
|
124960
125080
|
searchHint: "drag drop slider mouse press move release chromium select",
|
|
124961
125081
|
zodSchema: zodSchema20,
|
|
124962
125082
|
capability: capability12,
|
|
@@ -125268,7 +125388,7 @@ var gesturePinchTool = {
|
|
|
125268
125388
|
completedMsg: ({ params }) => `Pinched ${params.endDistance > params.startDistance ? "out" : "in"} at (${Math.round(params.centerX * 100)}%, ${Math.round(params.centerY * 100)}%)`,
|
|
125269
125389
|
failedMsg: ({ failureSignal: failureSignal2 }) => `Failed to pinch: ${failureSignal2.error_code}`
|
|
125270
125390
|
},
|
|
125271
|
-
description: `Execute a pinch-to-zoom gesture by moving two fingers toward or away from a center point to change the scale of on-screen content. All positions and distances are normalized 0.0\u20131.0 (fractions of screen width/height, not pixels)
|
|
125391
|
+
description: `Execute a pinch-to-zoom gesture by moving two fingers toward or away from a center point to change the scale of on-screen content. All positions and distances are normalized 0.0\u20131.0 (fractions of screen width/height, not pixels), same coordinate space as gesture-tap and gesture-swipe.
|
|
125272
125392
|
startDistance > endDistance = pinch in (zoom out). startDistance < endDistance = pinch out (zoom in).
|
|
125273
125393
|
Typical values: startDistance 0.2, endDistance 0.6 for a zoom-in pinch at screen center.
|
|
125274
125394
|
Auto-generates interpolated frames at ~60fps. The angle parameter controls the axis (0 = horizontal, 90 = vertical). Optional endCenterX/endCenterY drift the centroid linearly over the gesture (omitted = fixed center).
|
|
@@ -125322,13 +125442,13 @@ var zodSchema23 = external_exports.object({
|
|
|
125322
125442
|
"Center of rotation, vertical: normalized 0.0\u20131.0 (fraction of screen height, not pixels)"
|
|
125323
125443
|
),
|
|
125324
125444
|
radius: external_exports.number().optional().describe(
|
|
125325
|
-
"Distance from center to each finger: normalized 0.0\u20131.0 (fraction of screen, not pixels). E.g. 0.15 = fingers placed 15% of screen away from center. One value for both axes, so on a non-square screen the orbit is a physical ellipse
|
|
125445
|
+
"Distance from center to each finger: normalized 0.0\u20131.0 (fraction of screen, not pixels). E.g. 0.15 = fingers placed 15% of screen away from center. One value for both axes, so on a non-square screen the orbit is a physical ellipse; pass radiusX+radiusY instead for a true circle. Required unless radiusX and radiusY are given."
|
|
125326
125446
|
),
|
|
125327
125447
|
radiusX: external_exports.number().optional().describe(
|
|
125328
|
-
"Per-axis finger distance, horizontal: normalized 0.0\u20131.0 fraction of screen WIDTH. Give both radiusX and radiusY (they override radius) with radiusX\xB7screenWidth = radiusY\xB7screenHeight for a physically circular orbit
|
|
125448
|
+
"Per-axis finger distance, horizontal: normalized 0.0\u20131.0 fraction of screen WIDTH. Give both radiusX and radiusY (they override radius) with radiusX\xB7screenWidth = radiusY\xB7screenHeight for a physically circular orbit: constant finger separation, no pinch coupled into the turn."
|
|
125329
125449
|
),
|
|
125330
125450
|
radiusY: external_exports.number().optional().describe(
|
|
125331
|
-
"Per-axis finger distance, vertical: normalized 0.0\u20131.0 fraction of screen HEIGHT. Always paired with radiusX
|
|
125451
|
+
"Per-axis finger distance, vertical: normalized 0.0\u20131.0 fraction of screen HEIGHT. Always paired with radiusX; see radiusX."
|
|
125332
125452
|
),
|
|
125333
125453
|
startAngle: external_exports.number().describe("Starting angle in degrees (0 = right, 90 = down)"),
|
|
125334
125454
|
endAngle: external_exports.number().describe("Ending angle in degrees. endAngle > startAngle = clockwise."),
|
|
@@ -125358,7 +125478,7 @@ var gestureRotateTool = {
|
|
|
125358
125478
|
},
|
|
125359
125479
|
failedMsg: ({ failureSignal: failureSignal2 }) => `Failed to rotate gesture: ${failureSignal2.error_code}`
|
|
125360
125480
|
},
|
|
125361
|
-
description: `Send a two-finger circular arc gesture to rotate on-screen content by a specified angle. Two fingers are placed opposite each other at a fixed radius from the center, then swept from startAngle to endAngle degrees. All positions and radii are normalized 0.0\u20131.0 (fractions of screen width/height, not pixels)
|
|
125481
|
+
description: `Send a two-finger circular arc gesture to rotate on-screen content by a specified angle. Two fingers are placed opposite each other at a fixed radius from the center, then swept from startAngle to endAngle degrees. All positions and radii are normalized 0.0\u20131.0 (fractions of screen width/height, not pixels), same coordinate space as gesture-tap and gesture-swipe.
|
|
125362
125482
|
endAngle > startAngle = clockwise rotation. Typical values: radius 0.15, startAngle 0, endAngle 90 for a 90\xB0 clockwise turn. A single radius applies to both axes, so on a non-square screen it traces a physical ellipse (finger separation varies through the turn); pass radiusX+radiusY (fractions of width/height with radiusX\xB7width = radiusY\xB7height) for a physically circular orbit instead.
|
|
125363
125483
|
Auto-generates interpolated frames at ~60fps.
|
|
125364
125484
|
Unlike gesture-pinch which moves fingers linearly to zoom, this orbits fingers in an arc to change orientation.
|
|
@@ -126159,7 +126279,7 @@ var zodSchema25 = external_exports.object({
|
|
|
126159
126279
|
"Target device id from `list-devices` (iOS UDID, Android serial, Vega serial, or Chromium id)."
|
|
126160
126280
|
),
|
|
126161
126281
|
text: external_exports.string().optional().describe(
|
|
126162
|
-
'Text to type character by character. Cannot be combined with `key` in one call
|
|
126282
|
+
'Text to type character by character. Cannot be combined with `key` in one call (one call per action); to type and then press a key, put two `keyboard` steps in one `run-sequence`. Handles uppercase and common punctuation. To type a credential without its plaintext ever entering your context, use a secret placeholder: `{{secret:<NAME>}}`, e.g. text: "{{secret:APP_PASSWORD}}". The value is resolved on the machine running the tool-server, from the first source that defines the name: the `ARGENT_SECRET_<NAME>` environment variable, `.argent/secrets.env` in the project, the project\'s `.env.local` / `.env` (only their `ARGENT_SECRET_`-prefixed keys), then `~/.argent/secrets.env`. Nothing else on the host is reachable. Placeholders can be embedded in longer text and are never echoed back resolved. If the secret you need is not set, the failure lists the available names and every source it looked in; ask the user to add it to one of them (a secrets file applies immediately; an env var needs a restart), NEVER ask the user to paste the secret value into the conversation.'
|
|
126163
126283
|
),
|
|
126164
126284
|
key: external_exports.string().optional().describe(
|
|
126165
126285
|
"Named key to press: enter, escape, backspace, tab, space, arrow-up, arrow-down, arrow-left, arrow-right, f1-f12. Cannot be combined with `text` in one call: one call per action; to type and then press a key, put two `keyboard` steps in one `run-sequence`. Not supported on TV targets; move focus with `tv-remote` (up/down/left/right) instead. Physical iOS: only `enter` and `backspace`."
|
|
@@ -126207,13 +126327,17 @@ function createKeyboardTool(registry2) {
|
|
|
126207
126327
|
description: `Type text or press special keys on the device (iOS simulator, Android emulator or device, Chromium app, Vega Virtual Device, or Apple TV / Android TV) using keyboard events.
|
|
126208
126328
|
Use when you need to enter text or trigger a named key such as enter, escape, or arrow keys. On Vega and Apple TV / Android TV, prefer the remote tools for D-pad navigation; use keyboard to type into a focused text field (e.g. a search or login box).
|
|
126209
126329
|
Returns { typed: string, keys: number }. On physical iOS, reactivated: true = app was re-fronted; re-describe. Fails if text and key are both given in one call (rejected before anything is typed), if an unsupported key name is provided, or if the device's input backend is not reachable.
|
|
126210
|
-
A failure is not rolled back. An unsupported key name is always rejected before anything is sent. Un-typeable text is not: the iOS simulator and Chromium reject it mid-string and leave the characters before it in the field (Android, Vega and TV targets check the whole string up front). A transport failure partway also leaves the text already sent. On a retry, read the field's actual contents
|
|
126211
|
-
- text: types a string (supports uppercase, digits, common punctuation). To type a credential, use \`{{secret:<NAME>}}
|
|
126330
|
+
A failure is not rolled back. An unsupported key name is always rejected before anything is sent. Un-typeable text is not: the iOS simulator and Chromium reject it mid-string and leave the characters before it in the field (Android, Vega and TV targets check the whole string up front). A transport failure partway also leaves the text already sent. On a retry, read the field's actual contents; do not assume it is unchanged.
|
|
126331
|
+
- text: types a string (supports uppercase, digits, common punctuation). To type a credential, use \`{{secret:<NAME>}}\`, resolved server-side from the \`ARGENT_SECRET_<NAME>\` env var or an argent secrets file (\`.argent/secrets.env\` in the project, \`~/.argent/secrets.env\`, or an \`ARGENT_SECRET_\`-prefixed key in the project's \`.env\`/\`.env.local\`), so the plaintext never enters agent context; the result echoes the placeholder, not the value, and the after-typing auto-screenshot is skipped. To submit after typing a secret, put both steps in ONE \`run-sequence\`: that keeps the skip covering the Enter, which a second bare \`keyboard\` call would not.
|
|
126212
126332
|
- key: presses a single named key (enter, escape, backspace, tab, arrow-up/down/left/right, f1-f12). NOT supported on TV targets; move focus with \`tv-remote\` instead. Physical iOS: only \`enter\` and \`backspace\`.
|
|
126213
|
-
On a TV target (runtimeKind 'tv') only \`text\` applies
|
|
126214
|
-
One call does one action: pass text OR key, never both. To type and then press a key, send two \`keyboard\` steps in one \`run-sequence\`
|
|
126333
|
+
On a TV target (runtimeKind 'tv') only \`text\` applies. Focus a text field first (with \`tv-remote\`), then type into it (injected HID keyboard on Apple TV, \`adb input text\` on Android TV).
|
|
126334
|
+
One call does one action: pass text OR key, never both. To type and then press a key, send two \`keyboard\` steps in one \`run-sequence\` ({ text: "hello" } then { key: "enter" }), which also keeps it to a single round-trip.`,
|
|
126215
126335
|
zodSchema: zodSchema25,
|
|
126216
126336
|
capability: capability17,
|
|
126337
|
+
alwaysLoad: true,
|
|
126338
|
+
// Typing time grows with text length on several backends and can outlast the MCP
|
|
126339
|
+
// fetch timeout, whose abort replays the call: the text would be typed twice.
|
|
126340
|
+
longRunning: true,
|
|
126217
126341
|
searchHint: "type text keyboard input named key enter escape arrow tv vega fire tv search field hid leanback",
|
|
126218
126342
|
services: () => ({}),
|
|
126219
126343
|
execute: async (services, params, options) => {
|
|
@@ -126272,7 +126396,7 @@ var pasteZodSchema = external_exports.object({
|
|
|
126272
126396
|
"Target device id from `list-devices` (iOS simulator UDID or Android emulator serial)."
|
|
126273
126397
|
),
|
|
126274
126398
|
text: external_exports.string().min(1).describe(
|
|
126275
|
-
"Text to put on the device clipboard and paste into the focused field. Supports `{{secret:<NAME>}}` placeholders, resolved on the tool-server from the `ARGENT_SECRET_<NAME>` environment variable or an argent secrets file
|
|
126399
|
+
"Text to put on the device clipboard and paste into the focused field. Supports `{{secret:<NAME>}}` placeholders, resolved on the tool-server from the `ARGENT_SECRET_<NAME>` environment variable or an argent secrets file (the same sources as `keyboard`), so a credential never enters your context. If the secret is not set, the failure lists the available names and every source it looked in; ask the user to add it there, NEVER ask for the value in the conversation."
|
|
126276
126400
|
)
|
|
126277
126401
|
});
|
|
126278
126402
|
|
|
@@ -126418,7 +126542,7 @@ function createPasteTool(registry2) {
|
|
|
126418
126542
|
failedMsg: ({ failureSignal: failureSignal2 }) => `Failed to paste text: ${failureSignal2.error_code}`
|
|
126419
126543
|
},
|
|
126420
126544
|
description: `Paste text into the focused field: puts \`text\` on the DEVICE clipboard, then triggers the platform's paste shortcut (iOS simulator, Android emulator).
|
|
126421
|
-
Do NOT use this in place of \`keyboard\`. \`keyboard\` types as a user would and is the default for all text entry; use \`paste\` only where a real user would paste
|
|
126545
|
+
Do NOT use this in place of \`keyboard\`. \`keyboard\` types as a user would and is the default for all text entry; use \`paste\` only where a real user would paste: a 2FA/OTP code copied from another app, a long link or token, or when testing the app's own paste handling.
|
|
126422
126546
|
Tap the field first so it has focus. Returns { pasted: true }, plus via: "keyboard" when a secret was typed instead of pasted. Fails on a TV target, when the device clipboard cannot be set, when a secret that has to be typed holds a character that cannot be typed, or when the simulator-server build lacks clipboard support.
|
|
126423
126547
|
Supports \`{{secret:<NAME>}}\` placeholders like \`keyboard\`; the value is never echoed back.`,
|
|
126424
126548
|
searchHint: "paste clipboard pasteboard otp 2fa code fill field",
|
|
@@ -126459,7 +126583,7 @@ var rotateTool = {
|
|
|
126459
126583
|
failedMsg: ({ failureSignal: failureSignal2 }) => `Failed to rotate device: ${failureSignal2.error_code}`
|
|
126460
126584
|
},
|
|
126461
126585
|
description: `Set the device orientation to Portrait, LandscapeLeft, LandscapeRight, or PortraitUpsideDown.
|
|
126462
|
-
Use to test layout in a different orientation. Re-run \`describe\` afterwards
|
|
126586
|
+
Use to test layout in a different orientation. Re-run \`describe\` afterwards: frame coordinates change with the orientation.
|
|
126463
126587
|
On an unfolded foldable iOS simulator (the iPhone Duo), the value sets the orientation of the device, not of the UI: \`Portrait\` gives a landscape UI and \`LandscapeLeft\` gives a portrait UI. To fold or unfold the device, use \`fold\`.
|
|
126464
126588
|
Returns { orientation }. Fails if the target device is not booted.`,
|
|
126465
126589
|
zodSchema: zodSchema26,
|
|
@@ -126924,7 +127048,7 @@ var shakeTool = {
|
|
|
126924
127048
|
},
|
|
126925
127049
|
description: `Shake the device (iOS simulator or Android emulator).
|
|
126926
127050
|
Use to trigger anything bound to the shake gesture: iOS's "Undo Typing" / "Redo Typing" prompt in a text field, React Native's developer menu in a debug build, or an app's own shake-to-report handler.
|
|
126927
|
-
iOS delivers one discrete shake per gesture (the same motion event a physical device raises). Android has no OS-level shake event
|
|
127051
|
+
iOS delivers one discrete shake per gesture (the same motion event a physical device raises). Android has no OS-level shake event: the accelerometer is driven through a burst of hard direction changes so app-side detectors fire, and the resting orientation is restored afterwards.
|
|
126928
127052
|
Set \`count\` above 1 when a detector needs sustained motion before it triggers.
|
|
126929
127053
|
Returns { shaken: true, count }.
|
|
126930
127054
|
Works on local and remote (sim-remote) iOS simulators.
|
|
@@ -127182,7 +127306,7 @@ var buttonSchema = external_exports.preprocess(
|
|
|
127182
127306
|
},
|
|
127183
127307
|
external_exports.union([external_exports.enum(BUTTONS), external_exports.array(external_exports.enum(BUTTONS)).min(1).max(64)])
|
|
127184
127308
|
).describe(
|
|
127185
|
-
'A single TV-remote button, or a path of them run in one call. Buttons: up/down/left/right (D-pad), select (OK), back, home, menu, playPause, rewind, fastForward, next, previous, volumeUp, volumeDown, mute. The media-transport and volume keys work on Android TV and Vega; on the Apple TV simulator they are rejected (its HID stack ignores them)
|
|
127309
|
+
'A single TV-remote button, or a path of them run in one call. Buttons: up/down/left/right (D-pad), select (OK), back, home, menu, playPause, rewind, fastForward, next, previous, volumeUp, volumeDown, mute. The media-transport and volume keys work on Android TV and Vega; on the Apple TV simulator they are rejected (its HID stack ignores them). The D-pad/select/back/menu/home/playPause core works on all three. For multi-step navigation pass an array, e.g. ["up","right","right","select"]; strongly prefer this over multiple `tv-remote` calls: the whole path runs in a single call.'
|
|
127186
127310
|
);
|
|
127187
127311
|
var zodSchema28 = external_exports.object({
|
|
127188
127312
|
udid: external_exports.string().describe("Target TV device id from `list-devices` (Apple TV, Android TV, or Vega)."),
|
|
@@ -127204,13 +127328,12 @@ function createTvRemoteTool(registry2) {
|
|
|
127204
127328
|
completedMsg: ({ params }) => `Pressed ${params.button} on TV remote${(params.repeat ?? 1) > 1 ? ` ${params.repeat} times` : ""}`,
|
|
127205
127329
|
failedMsg: ({ params, failureSignal: failureSignal2 }) => `Failed to press ${params.button} on TV remote: ${failureSignal2.error_code}`
|
|
127206
127330
|
},
|
|
127207
|
-
description: `Press a TV remote / D-pad button (or a whole path of them) on a TV device
|
|
127208
|
-
A TV is navigated with a directional remote, not touch
|
|
127331
|
+
description: `Press a TV remote / D-pad button (or a whole path of them) on a TV device: Apple TV (tvOS), Android TV (leanback), or Vega (Fire TV).
|
|
127332
|
+
A TV is navigated with a directional remote, not touch. Use this instead of gesture-tap/swipe (which do not apply on a TV). Move focus with up/down/left/right, confirm with select, go back with back/menu, exit with home, and use playPause/rewind/fastForward/next/previous/volumeUp/volumeDown/mute for the corresponding remote keys. (On the Apple TV simulator the media-transport and volume keys are rejected (its HID stack ignores them); they work on Android TV and Vega.)
|
|
127209
127333
|
Single press: { button: "down" }. Repeat the same button: { button: "down", repeat: 3 }.
|
|
127210
|
-
Multi-step navigation: pass a path as { button: ["up","right","right","select"] }
|
|
127334
|
+
Multi-step navigation: pass a path as { button: ["up","right","right","select"] }. It runs in one tool call, far cheaper than separate presses.
|
|
127211
127335
|
Read the screen with \`describe\` before and after to see where focus landed.
|
|
127212
127336
|
Returns { pressed, count }.`,
|
|
127213
|
-
alwaysLoad: true,
|
|
127214
127337
|
// A path (≤64 buttons) × repeat (≤50) flattens to thousands of presses, sent
|
|
127215
127338
|
// one round-trip at a time on the Apple/Android path — minutes of wall-clock.
|
|
127216
127339
|
longRunning: true,
|
|
@@ -127261,9 +127384,9 @@ async function invokeSubTool(registry2, ctx, toolId, args, extra) {
|
|
|
127261
127384
|
}
|
|
127262
127385
|
function describeNestedParamError(registry2, err, toolId, dispatchedArgs, authoredArgs) {
|
|
127263
127386
|
if (getFailureSignal(err)?.error_code !== FAILURE_CODES.TOOL_INPUT_INVALID) return void 0;
|
|
127264
|
-
const
|
|
127265
|
-
if (!
|
|
127266
|
-
const parsed =
|
|
127387
|
+
const zodSchema82 = registry2.getTool(toolId)?.zodSchema;
|
|
127388
|
+
if (!zodSchema82) return void 0;
|
|
127389
|
+
const parsed = zodSchema82.safeParse(dispatchedArgs ?? {});
|
|
127267
127390
|
if (parsed.success) return void 0;
|
|
127268
127391
|
return `Invalid params for tool "${toolId}": ${describeParamIssues(parsed.error, authoredArgs)}`;
|
|
127269
127392
|
}
|
|
@@ -133432,6 +133555,9 @@ function evaluateCondition(condition, expectedText, matches2, textMatch = "conta
|
|
|
133432
133555
|
case "text": {
|
|
133433
133556
|
const first = firstInReadingOrder(matches2.filter(isVisible), orientation) ?? firstInReadingOrder(matches2, orientation);
|
|
133434
133557
|
if (first === void 0 || expectedText === void 0) return false;
|
|
133558
|
+
if (textMatch === "matches" && first.role !== "AXTextField" && !assertText(first) && !nodeText(first)) {
|
|
133559
|
+
return uiTreeMatchInternals.createRegExp(expectedText).test("");
|
|
133560
|
+
}
|
|
133435
133561
|
return textMatches(assertText(first), expectedText, textMatch) || textMatches(nodeText(first), expectedText, textMatch);
|
|
133436
133562
|
}
|
|
133437
133563
|
default:
|
|
@@ -133560,11 +133686,11 @@ var DEFAULT_POLL_INTERVAL_MS = 400;
|
|
|
133560
133686
|
var zodSchema29 = external_exports.object({
|
|
133561
133687
|
udid: external_exports.string().min(1).describe("Target device id from `list-devices` (iOS UDID, Android serial, or Chromium id)."),
|
|
133562
133688
|
condition: external_exports.enum(["exists", "visible", "hidden", "text"]).describe(
|
|
133563
|
-
"What to wait for. `exists`: selector is anywhere in the tree. `visible`: selector is present with a non-zero on-screen frame. `hidden`: selector is absent or zero-area. `text`: the first visible match in reading order (topmost), falling back to the first match overall if none is visible, contains (or, with textMatch `equals`, exactly matches) expectedText
|
|
133689
|
+
"What to wait for. `exists`: selector is anywhere in the tree. `visible`: selector is present with a non-zero on-screen frame. `hidden`: selector is absent or zero-area. `text`: the first visible match in reading order (topmost), falling back to the first match overall if none is visible, contains (or, with textMatch `equals`, exactly matches) expectedText. If a loose selector hits several elements, only that one is checked, so narrow it to target the intended element."
|
|
133564
133690
|
),
|
|
133565
133691
|
selector: selectorSchema.describe("Element to match (text / identifier / role)."),
|
|
133566
133692
|
expectedText: external_exports.string().min(1).optional().describe(
|
|
133567
|
-
"For condition `text`: the string the first visible matched element (topmost in reading order; the first match overall if none is visible) must contain (default) or equal
|
|
133693
|
+
"For condition `text`: the string the first visible matched element (topmost in reading order; the first match overall if none is visible) must contain (default) or equal (see `textMatch`). Case-insensitive."
|
|
133568
133694
|
),
|
|
133569
133695
|
textMatch: external_exports.enum(["contains", "equals"]).optional().describe(
|
|
133570
133696
|
"For condition `text`: how expectedText is compared. `contains` (default) is a case-insensitive substring; `equals` is a case-insensitive full-string match."
|
|
@@ -133674,13 +133800,13 @@ function createAwaitUiElementTool(registry2) {
|
|
|
133674
133800
|
description: `Block until a UI element reaches an expected state or a timeout elapses, so you don't have to poll screenshot/describe yourself.
|
|
133675
133801
|
|
|
133676
133802
|
Conditions:
|
|
133677
|
-
exists
|
|
133678
|
-
visible
|
|
133679
|
-
hidden
|
|
133680
|
-
text
|
|
133803
|
+
exists: the selector matches an element anywhere in the tree.
|
|
133804
|
+
visible: the selector matches an element with a non-zero on-screen frame.
|
|
133805
|
+
hidden: the selector matches nothing, or only a zero-area element (e.g. a spinner that disappeared).
|
|
133806
|
+
text: the first VISIBLE match in reading order (topmost, then leftmost; falling back to the first match
|
|
133681
133807
|
overall if none is visible) contains expectedText (case-insensitive substring), or exactly matches
|
|
133682
133808
|
it when textMatch is \`equals\`. A loose selector can match several elements; only that one is
|
|
133683
|
-
inspected, so if a different match is the one holding the text the wait still reports failure
|
|
133809
|
+
inspected, so if a different match is the one holding the text the wait still reports failure;
|
|
133684
133810
|
narrow the selector to target it.
|
|
133685
133811
|
|
|
133686
133812
|
The selector is { text?, identifier?, role? }; every provided field must match. text and role match as
|
|
@@ -133691,10 +133817,10 @@ It polls the same accessibility / DOM tree as \`describe\`
|
|
|
133691
133817
|
Vega automation toolkit) every pollIntervalMs
|
|
133692
133818
|
(default ${DEFAULT_POLL_INTERVAL_MS}ms) until timeoutMs (default ${DEFAULT_TIMEOUT_MS3}ms).
|
|
133693
133819
|
|
|
133694
|
-
Returns { success: boolean, elapsed: number, note?, cause? }
|
|
133695
|
-
condition holding, which is not always a verdict on the condition: \`cause\` says which it was
|
|
133820
|
+
Returns { success: boolean, elapsed: number, note?, cause? }. success=false means the wait ended without the
|
|
133821
|
+
condition holding, which is not always a verdict on the condition: \`cause\` says which it was: \`unmet\` (the tree
|
|
133696
133822
|
was read and the condition was false there), \`unreadable\` (no trustworthy read, so nothing was judged) or
|
|
133697
|
-
\`cancelled
|
|
133823
|
+
\`cancelled\`. \`note\` describes what was seen. Only \`unmet\` licenses rewriting the check. Use this after a
|
|
133698
133824
|
tap/navigation to wait for the next screen, or before tapping an element that appears asynchronously.`,
|
|
133699
133825
|
alwaysLoad: true,
|
|
133700
133826
|
searchHint: "wait await poll until visible hidden exists text appears disappears timeout element condition settle",
|
|
@@ -133790,12 +133916,12 @@ var ALLOWED_TOOLS = /* @__PURE__ */ new Set([
|
|
|
133790
133916
|
]);
|
|
133791
133917
|
var zodSchema30 = external_exports.object({
|
|
133792
133918
|
udid: external_exports.string().describe(
|
|
133793
|
-
"Target device id from `list-devices` (iOS UDID, Android serial, Vega serial, or Chromium id)
|
|
133919
|
+
"Target device id from `list-devices` (iOS UDID, Android serial, Vega serial, or Chromium id), shared across all steps."
|
|
133794
133920
|
),
|
|
133795
133921
|
steps: external_exports.array(
|
|
133796
133922
|
external_exports.object({
|
|
133797
133923
|
tool: external_exports.string().describe(
|
|
133798
|
-
"Tool name
|
|
133924
|
+
"Tool name, one of: gesture-tap, gesture-swipe, gesture-scroll, gesture-drag, gesture-custom, gesture-pinch, gesture-rotate, button, keyboard, paste, rotate, shake, fold, tv-remote, await-ui-element. On a TV target (Apple TV / Android TV / Vega) use tv-remote (remote presses) and keyboard (text)."
|
|
133799
133925
|
),
|
|
133800
133926
|
args: external_exports.record(external_exports.string(), external_exports.unknown()).describe("Tool arguments (excluding udid, which is injected automatically)"),
|
|
133801
133927
|
delayMs: external_exports.number().optional().describe(
|
|
@@ -133828,7 +133954,7 @@ On a physical iOS device only gesture-tap, gesture-swipe, gesture-custom, button
|
|
|
133828
133954
|
Use when you need sequential actions and do NOT need to observe the screen between them
|
|
133829
133955
|
(e.g. scrolling multiple times, typing then pressing enter, rotating back and forth).
|
|
133830
133956
|
Returns { completed, total, steps } with per-step results. Fails if an unrecognised tool name is used in a step (error returned at that step, execution stops).
|
|
133831
|
-
One screenshot is captured automatically after the whole sequence (not per step)
|
|
133957
|
+
One screenshot is captured automatically after the whole sequence (not per step). Call screenshot separately only for a baseline BEFORE it, or to observe an intermediate step.
|
|
133832
133958
|
That single capture is also why a secret belongs in this call rather than in two bare ones: the skip is decided from the whole request, so a \`{{secret:...}}\` in any step suppresses the capture that would otherwise follow the submit.
|
|
133833
133959
|
|
|
133834
133960
|
ONLY use this when every step is known in advance. If any step depends on the
|
|
@@ -133846,41 +133972,41 @@ Allowed tools and their args (udid is auto-injected, do NOT include it in args):
|
|
|
133846
133972
|
gesture-rotate: { centerX: number, centerY: number, radius?: number, radiusX?: number, radiusY?: number, startAngle: number, endAngle: number, durationMs?: number } [ios/android]
|
|
133847
133973
|
button: { button: "home"|"back"|"power"|"volumeUp"|"volumeDown"|"appSwitch"|"actionButton" } [ios/android]
|
|
133848
133974
|
keyboard: { text?: string, key?: string, delayMs?: number } (text OR key per step, never both; TV: text only) [ios/android/chromium/vega/tv]
|
|
133849
|
-
text supports {{secret:<NAME>}} placeholders, resolved server-side from ARGENT_SECRET_<NAME> env vars or an argent secrets file
|
|
133850
|
-
paste: { text: string } (device clipboard + paste shortcut; only where a user would paste, e.g. an OTP
|
|
133975
|
+
text supports {{secret:<NAME>}} placeholders, resolved server-side from ARGENT_SECRET_<NAME> env vars or an argent secrets file; credentials never enter agent context
|
|
133976
|
+
paste: { text: string } (device clipboard + paste shortcut; only where a user would paste, e.g. an OTP; keyboard otherwise) [ios sim/android emu]
|
|
133851
133977
|
rotate: { orientation: "Portrait"|"LandscapeLeft"|"LandscapeRight"|"PortraitUpsideDown" } [ios/android]
|
|
133852
133978
|
shake: { count?: number } [ios sim/android emu]
|
|
133853
133979
|
fold: { posture?: "closed"|"half-open"|"open", angle?: 0-180 } (one of posture/angle; the next step lands on the new panel, whose coordinates are different) [foldable ios sim]
|
|
133854
133980
|
tv-remote: { button: <remote button | array of them>, repeat?: number } [apple tv/android tv/vega]
|
|
133855
|
-
buttons: up/down/left/right/select/back/home/menu/playPause (+ rewind/fastForward/next/previous/volumeUp/volumeDown/mute
|
|
133981
|
+
buttons: up/down/left/right/select/back/home/menu/playPause (+ rewind/fastForward/next/previous/volumeUp/volumeDown/mute work on Android TV and Vega; rejected on the Apple TV simulator)
|
|
133856
133982
|
await-ui-element: { condition: "exists"|"visible"|"hidden"|"text", selector: {text?,identifier?,role?}, expectedText?, timeoutMs?, pollIntervalMs? } [ios/android/chromium]
|
|
133857
133983
|
|
|
133858
|
-
Example
|
|
133984
|
+
Example: scroll down three times (use gesture-scroll with positive deltaY on Chromium):
|
|
133859
133985
|
{ "udid": "<UDID>", "steps": [
|
|
133860
133986
|
{ "tool": "gesture-swipe", "args": { "fromX": 0.5, "fromY": 0.7, "toX": 0.5, "toY": 0.3 } },
|
|
133861
133987
|
{ "tool": "gesture-swipe", "args": { "fromX": 0.5, "fromY": 0.7, "toX": 0.5, "toY": 0.3 } },
|
|
133862
133988
|
{ "tool": "gesture-swipe", "args": { "fromX": 0.5, "fromY": 0.7, "toX": 0.5, "toY": 0.3 } }
|
|
133863
133989
|
]}
|
|
133864
133990
|
|
|
133865
|
-
Example
|
|
133991
|
+
Example: type text and submit (two keyboard steps; one call cannot carry both):
|
|
133866
133992
|
{ "udid": "<UDID>", "steps": [
|
|
133867
133993
|
{ "tool": "keyboard", "args": { "text": "hello world" } },
|
|
133868
133994
|
{ "tool": "keyboard", "args": { "key": "enter" } }
|
|
133869
133995
|
]}
|
|
133870
133996
|
|
|
133871
|
-
Example
|
|
133997
|
+
Example (TV): move focus right twice then activate (one tv-remote step with a path is cheaper):
|
|
133872
133998
|
{ "udid": "<TV-TARGET-ID>", "steps": [
|
|
133873
133999
|
{ "tool": "tv-remote", "args": { "button": ["right", "right", "select"] } }
|
|
133874
134000
|
]}
|
|
133875
134001
|
|
|
133876
|
-
Example
|
|
134002
|
+
Example: tap, wait for the next screen's element, then tap it:
|
|
133877
134003
|
{ "udid": "<UDID>", "steps": [
|
|
133878
134004
|
{ "tool": "gesture-tap", "args": { "x": 0.5, "y": 0.9 } },
|
|
133879
134005
|
{ "tool": "await-ui-element", "args": { "condition": "visible", "selector": { "text": "Continue" } } },
|
|
133880
134006
|
{ "tool": "gesture-tap", "args": { "x": 0.5, "y": 0.5 } }
|
|
133881
134007
|
]}
|
|
133882
134008
|
If the await-ui-element condition is not met before its timeout, the sequence stops there and the
|
|
133883
|
-
following steps do NOT run
|
|
134009
|
+
following steps do NOT run, so the tap above only fires once "Continue" is actually on screen.
|
|
133884
134010
|
|
|
133885
134011
|
Stops on the first error (or unmet await-ui-element condition) and returns partial results.`,
|
|
133886
134012
|
alwaysLoad: true,
|
|
@@ -133987,7 +134113,7 @@ function debuggerServiceRef(params) {
|
|
|
133987
134113
|
var zodSchema31 = external_exports.object({
|
|
133988
134114
|
port: metroPortField,
|
|
133989
134115
|
device_id: external_exports.string().describe(
|
|
133990
|
-
"Device id from list-devices: iOS simulator UDID, Android serial, Vega serial (amazon-...), or Chromium device id (chromium-cdp-<port>). Pass this SAME id as device_id to every subsequent debugger-* call to pin them to this device. The returned logicalDeviceId is informational (Metro's own per-connection handle, absent on Vega); you do not switch to it
|
|
134116
|
+
"Device id from list-devices: iOS simulator UDID, Android serial, Vega serial (amazon-...), or Chromium device id (chromium-cdp-<port>). Pass this SAME id as device_id to every subsequent debugger-* call to pin them to this device. The returned logicalDeviceId is informational (Metro's own per-connection handle, absent on Vega); you do not switch to it. Forwarding it still resolves here, but the list-devices id is the stable one."
|
|
133991
134117
|
)
|
|
133992
134118
|
});
|
|
133993
134119
|
var debuggerConnectTool = {
|
|
@@ -133998,7 +134124,7 @@ var debuggerConnectTool = {
|
|
|
133998
134124
|
failedMsg: ({ failureSignal: failureSignal2 }) => `Failed to connect JavaScript debugger: ${failureSignal2.error_code}`
|
|
133999
134125
|
},
|
|
134000
134126
|
description: `Connect to a JS runtime CDP debugger.
|
|
134001
|
-
iOS / Android / Vega: connects to Metro's CDP endpoint on the given port. Chromium: re-uses the page CDP session opened by boot-device
|
|
134127
|
+
iOS / Android / Vega: connects to Metro's CDP endpoint on the given port. Chromium: re-uses the page CDP session opened by boot-device; port is ignored.
|
|
134002
134128
|
Returns connection info including port, projectRoot (empty on Chromium and on legacy Metro, e.g. Vega), deviceName, appName, logicalDeviceId (absent on Vega), and isNewDebugger, plus a note naming the kept log file when the previous session ended because the app crashed. If already connected, returns the existing connection.
|
|
134003
134129
|
Use when starting a debug session or before calling other debugger-* tools. Fails if the runtime is unreachable (Metro down, or Chromium CDP terminated).`,
|
|
134004
134130
|
zodSchema: zodSchema31,
|
|
@@ -134110,7 +134236,7 @@ function isDebuggerNotConnectedResult(toolId, result) {
|
|
|
134110
134236
|
var zodSchema32 = external_exports.object({
|
|
134111
134237
|
port: metroPortField,
|
|
134112
134238
|
device_id: external_exports.string().describe(
|
|
134113
|
-
"Device id from list-devices
|
|
134239
|
+
"Device id from list-devices: the SAME id you passed to debugger-connect (iOS simulator UDID, Android serial, Vega serial, or Chromium device id). The logicalDeviceId debugger-connect returns also resolves here, but prefer the stable list-devices id."
|
|
134114
134240
|
)
|
|
134115
134241
|
});
|
|
134116
134242
|
function createDebuggerStatusTool(registry2) {
|
|
@@ -134122,9 +134248,9 @@ function createDebuggerStatusTool(registry2) {
|
|
|
134122
134248
|
failedMsg: ({ failureSignal: failureSignal2 }) => `Failed to check JavaScript debugger: ${failureSignal2.error_code}`
|
|
134123
134249
|
},
|
|
134124
134250
|
description: `Get JS runtime debugger connection status and diagnostic info.
|
|
134125
|
-
Use when you need to verify connectivity before using other debugger tools. Never fails when the runtime is simply unreachable
|
|
134126
|
-
- { status: "connected", ... } with port, projectRoot (empty on Chromium and on legacy Metro, e.g. Vega), deviceName, appName, logicalDeviceId (absent on Vega), isNewDebugger (false on the legacy inspector), connected flag, loadedScripts count, and sourceMapReady (always true
|
|
134127
|
-
- { status: "not_connected", connected: false, reason, detail, guidance } (port omitted on Chromium) when Metro is not running (reason "metro_not_running"), no app is attached ("no_app_connected"), the device_id matches no target ("device_mismatch"), the CDP endpoint is unreachable or answered malformed ("cdp_unreachable"), the runtime accepted the connection but never answered ("runtime_unresponsive"), the cached connection went stale ("stale_connection"), or a reconnect is in flight ("reconnecting"). Follow the guidance field
|
|
134251
|
+
Use when you need to verify connectivity before using other debugger tools. Never fails when the runtime is simply unreachable: it returns a discriminated result instead:
|
|
134252
|
+
- { status: "connected", ... } with port, projectRoot (empty on Chromium and on legacy Metro, e.g. Vega), deviceName, appName, logicalDeviceId (absent on Vega), isNewDebugger (false on the legacy inspector), connected flag, loadedScripts count, and sourceMapReady (always true: waits for pending source maps before returning; no-op on Chromium).
|
|
134253
|
+
- { status: "not_connected", connected: false, reason, detail, guidance } (port omitted on Chromium) when Metro is not running (reason "metro_not_running"), no app is attached ("no_app_connected"), the device_id matches no target ("device_mismatch"), the CDP endpoint is unreachable or answered malformed ("cdp_unreachable"), the runtime accepted the connection but never answered ("runtime_unresponsive"), the cached connection went stale ("stale_connection"), or a reconnect is in flight ("reconnecting"). Follow the guidance field; do not retry in a loop.`,
|
|
134128
134254
|
zodSchema: zodSchema32,
|
|
134129
134255
|
capability: DEBUGGER_TOOL_CAPABILITY,
|
|
134130
134256
|
// Resolved manually in execute so a not-connected precondition becomes a
|
|
@@ -134185,7 +134311,7 @@ init_src2();
|
|
|
134185
134311
|
var zodSchema33 = external_exports.object({
|
|
134186
134312
|
port: metroPortField,
|
|
134187
134313
|
device_id: external_exports.string().describe(
|
|
134188
|
-
"Device id from list-devices
|
|
134314
|
+
"Device id from list-devices: the SAME id you passed to debugger-connect (iOS simulator UDID, Android serial, Vega serial, or Chromium device id). The logicalDeviceId debugger-connect returns also resolves here, but prefer the stable list-devices id."
|
|
134189
134315
|
),
|
|
134190
134316
|
expression: external_exports.string().describe("JavaScript expression to evaluate in the app runtime")
|
|
134191
134317
|
});
|
|
@@ -134196,8 +134322,8 @@ var debuggerEvaluateTool = {
|
|
|
134196
134322
|
completedMsg: () => "Ran JavaScript in the app",
|
|
134197
134323
|
failedMsg: ({ failureSignal: failureSignal2 }) => `Failed to run JavaScript in the app: ${failureSignal2.error_code}`
|
|
134198
134324
|
},
|
|
134199
|
-
description: `Execute arbitrary JavaScript in the app's JS runtime via CDP
|
|
134200
|
-
Returns the evaluation result as a JSON-serializable value, along with deviceName, appName, and logicalDeviceId for context. Use when you need to read app state, call app functions, or test logic at runtime. The result is serialized by value, so cyclic objects (many RN runtime values
|
|
134325
|
+
description: `Execute arbitrary JavaScript in the app's JS runtime via CDP: Hermes on iOS / Android / Vega, V8 on Chromium.
|
|
134326
|
+
Returns the evaluation result as a JSON-serializable value, along with deviceName, appName, and logicalDeviceId for context. Use when you need to read app state, call app functions, or test logic at runtime. The result is serialized by value, so cyclic objects (many RN runtime values, such as fiber nodes, navigation refs and global, are cyclic) fail with a serialization error rather than returning silently. Fails if the expression throws or the runtime is not connected.`,
|
|
134201
134327
|
zodSchema: zodSchema33,
|
|
134202
134328
|
capability: DEBUGGER_TOOL_CAPABILITY,
|
|
134203
134329
|
services: (params) => ({
|
|
@@ -134238,7 +134364,7 @@ init_src2();
|
|
|
134238
134364
|
var zodSchema34 = external_exports.object({
|
|
134239
134365
|
port: metroPortField,
|
|
134240
134366
|
device_id: external_exports.string().describe(
|
|
134241
|
-
"Device id from list-devices
|
|
134367
|
+
"Device id from list-devices: the SAME id you passed to debugger-connect (iOS simulator UDID or Android serial)."
|
|
134242
134368
|
)
|
|
134243
134369
|
});
|
|
134244
134370
|
var debuggerReloadMetroTool = {
|
|
@@ -135190,7 +135316,7 @@ async function readTapAxes(registry2, app) {
|
|
|
135190
135316
|
var zodSchema35 = external_exports.object({
|
|
135191
135317
|
port: metroPortField,
|
|
135192
135318
|
device_id: external_exports.string().describe(
|
|
135193
|
-
"Device id from list-devices
|
|
135319
|
+
"Device id from list-devices: the SAME id you passed to debugger-connect (iOS simulator UDID or Android serial)."
|
|
135194
135320
|
),
|
|
135195
135321
|
udid: external_exports.string().optional().describe(
|
|
135196
135322
|
"iOS simulator UDID from list-devices. Pass it when device_id is a logicalDeviceId (two or more devices share one Metro), so that the tap coordinates of a landscape UI are on the screen's axes. Give the UDID of the simulator that shows the app."
|
|
@@ -135214,11 +135340,11 @@ function createDebuggerComponentTreeTool(registry2) {
|
|
|
135214
135340
|
failedMsg: ({ failureSignal: failureSignal2 }) => `Failed to read React component tree: ${failureSignal2.error_code}`
|
|
135215
135341
|
},
|
|
135216
135342
|
description: `Fetch the current screen of a running React Native app as a compact component text tree.
|
|
135217
|
-
Only shows on-screen components with unique positions
|
|
135343
|
+
Only shows on-screen components with unique positions. Off-screen (scrolled) content,
|
|
135218
135344
|
full-screen transparent wrappers, and implementation-detail components are pruned.
|
|
135219
135345
|
|
|
135220
135346
|
Each visible component is listed with its name, text content, and normalized
|
|
135221
|
-
tap coordinates in [0,1] space (fractions of the screen, not pixels
|
|
135347
|
+
tap coordinates in [0,1] space (fractions of the screen, not pixels; same space as tap/swipe/gesture).
|
|
135222
135348
|
On an iOS simulator with a landscape UI (a rotated device, or an unfolded foldable), the tap
|
|
135223
135349
|
coordinates are on the screen's axes, which the gesture tools use. When two or more devices share
|
|
135224
135350
|
one Metro, pass the simulator's udid too. If the result says that the orientation could not be
|
|
@@ -135717,7 +135843,7 @@ function filterInspectItems(items, includeSkipped = false) {
|
|
|
135717
135843
|
var zodSchema36 = external_exports.object({
|
|
135718
135844
|
port: metroPortField,
|
|
135719
135845
|
device_id: external_exports.string().describe(
|
|
135720
|
-
"Device id from list-devices
|
|
135846
|
+
"Device id from list-devices: the SAME id you passed to debugger-connect (iOS simulator UDID or Android serial)."
|
|
135721
135847
|
),
|
|
135722
135848
|
x: external_exports.coerce.number().describe("Logical X coordinate on device screen"),
|
|
135723
135849
|
y: external_exports.coerce.number().describe("Logical Y coordinate on device screen"),
|
|
@@ -135726,7 +135852,7 @@ var zodSchema36 = external_exports.object({
|
|
|
135726
135852
|
"When true, resolves bundled frame locations to original source files via Metro symbolication and includes a code fragment. When false, returns the raw bundled frame info (file, line, column) without symbolication or source reading."
|
|
135727
135853
|
),
|
|
135728
135854
|
maxItems: external_exports.coerce.number().default(35).describe(
|
|
135729
|
-
"Maximum number of hierarchy items to return, counted from the bottom (most specific component first). The hierarchy walks from the tapped element up to the root
|
|
135855
|
+
"Maximum number of hierarchy items to return, counted from the bottom (most specific component first). The hierarchy walks from the tapped element up to the root, so the first items are the most relevant for editing. Increase to 70+ if you need to understand the broader navigation/screen structure."
|
|
135730
135856
|
),
|
|
135731
135857
|
includeSkipped: external_exports.boolean().default(false).describe(
|
|
135732
135858
|
"When true, items that would normally be filtered are kept in the response with skipped=true and a skipReason. Useful for understanding what was pruned."
|
|
@@ -135743,7 +135869,7 @@ var debuggerInspectElementTool = {
|
|
|
135743
135869
|
Returns components from the tapped element upward through its parent hierarchy,
|
|
135744
135870
|
each with its source file:line and a code fragment.
|
|
135745
135871
|
|
|
135746
|
-
The first items (lowest indices) are the most specific
|
|
135872
|
+
The first items (lowest indices) are the most specific: the exact component under
|
|
135747
135873
|
the tap point and its direct parents. Higher indices are broader context (page, navigator).
|
|
135748
135874
|
Default shows 35 items which covers all app-specific code; use maxItems=70+ to also
|
|
135749
135875
|
see the navigation/screen structure.
|
|
@@ -135854,7 +135980,7 @@ init_zod();
|
|
|
135854
135980
|
var zodSchema37 = external_exports.object({
|
|
135855
135981
|
port: metroPortField,
|
|
135856
135982
|
device_id: external_exports.string().describe(
|
|
135857
|
-
"Device id from list-devices
|
|
135983
|
+
"Device id from list-devices: the SAME id you passed to debugger-connect (iOS simulator UDID, Android serial, Vega serial, or Chromium device id). The logicalDeviceId debugger-connect returns also resolves here, but prefer the stable list-devices id."
|
|
135858
135984
|
)
|
|
135859
135985
|
});
|
|
135860
135986
|
function createDebuggerLogRegistryTool(registry2) {
|
|
@@ -135867,8 +135993,8 @@ function createDebuggerLogRegistryTool(registry2) {
|
|
|
135867
135993
|
},
|
|
135868
135994
|
description: `Get a summary of all console logs captured from the app's JS runtime.
|
|
135869
135995
|
Returns the log file path, entry counts by level, and message clusters (grouped by similarity). Works against Hermes (iOS / Android / Vega) and V8 (Chromium).
|
|
135870
|
-
Use when investigating warnings, errors, or unexpected output
|
|
135871
|
-
When the debugger cannot be reached, this tool does not fail: it returns { status: "not_connected", reason, detail, guidance } with NO log file
|
|
135996
|
+
Use when investigating warnings, errors, or unexpected output. Call this first for an overview, then read the returned file for details. Returns empty stats if no log data has been captured yet, but check { note }, which is present only when the stats are empty BECAUSE the previous debugger session ended: torn down (e.g. by stop-all-simulator-servers) with its log file deleted, or cut off by the app crashing with its log file kept at the path the note names. Absent that note, empty really does mean the app has logged nothing.
|
|
135997
|
+
When the debugger cannot be reached, this tool does not fail: it returns { status: "not_connected", reason, detail, guidance } with NO log file. Follow the guidance (do not retry in a loop). Read a log file in this state only when a { note } names one kept from before the app crashed. A "connected" result's stats may come from a session whose socket has since died. Use debugger-status, not this tool, to judge debugger health.`,
|
|
135872
135998
|
zodSchema: zodSchema37,
|
|
135873
135999
|
capability: DEBUGGER_TOOL_CAPABILITY,
|
|
135874
136000
|
// Resolved manually in execute so a not-connected precondition becomes a
|
|
@@ -135980,7 +136106,7 @@ ${lines.join("\n")}`;
|
|
|
135980
136106
|
var zodSchema38 = external_exports.object({
|
|
135981
136107
|
port: metroPortField,
|
|
135982
136108
|
device_id: external_exports.string().describe(
|
|
135983
|
-
"Device id from list-devices (iOS simulator UDID or Android serial)
|
|
136109
|
+
"Device id from list-devices (iOS simulator UDID or Android serial), the same id used with debugger-connect."
|
|
135984
136110
|
),
|
|
135985
136111
|
pageIndex: external_exports.union([external_exports.coerce.number().int().nonnegative(), external_exports.literal("latest")]).default("latest").describe(
|
|
135986
136112
|
'Page index (0-based) or "latest" for the most recent page. Each page contains up to 50 entries.'
|
|
@@ -135996,7 +136122,7 @@ var networkLogsTool = {
|
|
|
135996
136122
|
description: `Retrieve captured network (HTTP) requests from the running app.
|
|
135997
136123
|
Returns a paginated list of requests with method, URL, status, resource type, size, and duration.
|
|
135998
136124
|
Each entry includes a requestId that can be passed to view-network-request-details for full details.
|
|
135999
|
-
On React Native (iOS / Android / Vega) interception is injected into the JS runtime
|
|
136125
|
+
On React Native (iOS / Android / Vega) interception is injected into the JS runtime: it captures fetch() calls. On Chromium it reads the browser's native CDP Network domain (the active tab; all request types).
|
|
136000
136126
|
Use when inspecting outbound HTTP traffic or debugging API calls in the running app.
|
|
136001
136127
|
Fails if the app is not connected (RN) or the device is not reachable (Chromium).`,
|
|
136002
136128
|
zodSchema: zodSchema38,
|
|
@@ -136074,7 +136200,7 @@ var MAX_BODY_SIZE = 1e3;
|
|
|
136074
136200
|
var zodSchema39 = external_exports.object({
|
|
136075
136201
|
port: metroPortField,
|
|
136076
136202
|
device_id: external_exports.string().describe(
|
|
136077
|
-
"Device id from list-devices (iOS simulator UDID or Android serial)
|
|
136203
|
+
"Device id from list-devices (iOS simulator UDID or Android serial), the same id used with debugger-connect."
|
|
136078
136204
|
),
|
|
136079
136205
|
requestId: external_exports.string().describe("The requestId from view-network-logs to get full details for"),
|
|
136080
136206
|
includeBody: external_exports.coerce.boolean().default(true).describe("Whether to include the response body (if captured). Defaults to true.")
|
|
@@ -136089,7 +136215,7 @@ var networkRequestTool = {
|
|
|
136089
136215
|
description: `Get full details of a specific network request by its requestId (from view-network-logs).
|
|
136090
136216
|
Returns request/response headers (sensitive headers redacted), status, timing, and optionally the response body.
|
|
136091
136217
|
Large response bodies are truncated. Use when you need headers, body, or timing for a specific request after listing logs.
|
|
136092
|
-
Returns an error message string if the requestId is not found
|
|
136218
|
+
Returns an error message string if the requestId is not found; use view-network-logs to get valid requestId values.`,
|
|
136093
136219
|
zodSchema: zodSchema39,
|
|
136094
136220
|
capability: DEBUGGER_TOOL_CAPABILITY,
|
|
136095
136221
|
services: (params) => {
|
|
@@ -136478,10 +136604,10 @@ function createDescribeTool(registry2) {
|
|
|
136478
136604
|
failedMsg: ({ failureSignal: failureSignal2 }) => `Failed to read screen: ${failureSignal2.error_code}`
|
|
136479
136605
|
},
|
|
136480
136606
|
description: `Get the accessibility / DOM element tree for the current screen.
|
|
136481
|
-
On iOS, uses the AXRuntime accessibility service to inspect whatever is currently visible
|
|
136607
|
+
On iOS, uses the AXRuntime accessibility service to inspect whatever is currently visible, including
|
|
136482
136608
|
system dialogs, permission prompts, and any foreground app content. On a physical iOS device the tree
|
|
136483
136609
|
covers only the app registered by launch-app. On Android, runs \`uiautomator dump\`.
|
|
136484
|
-
On Chromium, walks the renderer's DOM via Chrome DevTools Protocol
|
|
136610
|
+
On Chromium, walks the renderer's DOM via Chrome DevTools Protocol: every visible element with its ARIA
|
|
136485
136611
|
role, accessible name, and bounding rect (normalized to 0\u20131).
|
|
136486
136612
|
On Vega (Fire TV), reads the on-device automation toolkit (\`getPageSource\`); each element carries
|
|
136487
136613
|
\`[focused]\`/\`[selected]\` so you can see where the D-pad cursor is, then move it with the \`tv-remote\` tool
|
|
@@ -136492,9 +136618,9 @@ When a system dialog is visible, describe returns the dialog's interactive eleme
|
|
|
136492
136618
|
with tap coordinates. When no dialog is present, it returns the foreground app's accessible elements.
|
|
136493
136619
|
On a physical iOS device, launch-app \`com.apple.springboard\` first to read system dialogs.
|
|
136494
136620
|
|
|
136495
|
-
Returns \`{ description, source }\` where \`description\` is a text rendering of the UI tree
|
|
136621
|
+
Returns \`{ description, source }\` where \`description\` is a text rendering of the UI tree, one
|
|
136496
136622
|
line per element with its role, label/value/id, interactivity flags, and frame. Frame coordinates
|
|
136497
|
-
are normalized [0,1] fractions of the screen / window width/height (not pixels)
|
|
136623
|
+
are normalized [0,1] fractions of the screen / window width/height (not pixels), the same space as
|
|
136498
136624
|
gesture-tap / gesture-swipe / gesture-pinch.
|
|
136499
136625
|
|
|
136500
136626
|
To tap an element use the centre of its frame: \`tap_x = frame.x + frame.width / 2\`,
|
|
@@ -136507,7 +136633,7 @@ For app-scoped inspection with full UIKit properties (accessibilityIdentifier, v
|
|
|
136507
136633
|
use native-describe-screen with an explicit bundleId instead (iOS simulator only).
|
|
136508
136634
|
For React Native apps, debugger-component-tree returns React component names with tap coordinates.
|
|
136509
136635
|
|
|
136510
|
-
On a TV target (Apple TV / Android TV
|
|
136636
|
+
On a TV target (Apple TV / Android TV: a \`list-devices\` entry with runtimeKind 'tv') this returns
|
|
136511
136637
|
the focus-driven view instead: the currently FOCUSED element and the list of FOCUSABLE elements,
|
|
136512
136638
|
since a TV UI has no tap coordinates. Move the highlight with \`tv-remote\` (up/down/left/right/select/
|
|
136513
136639
|
back/menu/home), then call describe again to confirm where focus landed.`,
|
|
@@ -137041,6 +137167,456 @@ Fails if the iOS ax-service predates the tree command; update argent.`,
|
|
|
137041
137167
|
};
|
|
137042
137168
|
}
|
|
137043
137169
|
|
|
137170
|
+
// ../tool-server/src/tools/foreground-app/index.ts
|
|
137171
|
+
init_zod();
|
|
137172
|
+
var zodSchema42 = external_exports.object({
|
|
137173
|
+
udid: external_exports.string().min(1).describe("Target device id from `list-devices`.")
|
|
137174
|
+
});
|
|
137175
|
+
var capability27 = {
|
|
137176
|
+
apple: { simulator: true },
|
|
137177
|
+
appleRemote: { simulator: true },
|
|
137178
|
+
android: { emulator: true, device: true, unknown: true }
|
|
137179
|
+
};
|
|
137180
|
+
async function readIosForegroundApp(registry2, device) {
|
|
137181
|
+
const ref = axServiceRef(device);
|
|
137182
|
+
const ax = await registry2.resolveService(ref.urn, ref.options);
|
|
137183
|
+
const { bundleId, name, alertVisible } = await ax.foregroundApp();
|
|
137184
|
+
return { bundleId, name, alertVisible };
|
|
137185
|
+
}
|
|
137186
|
+
async function readAndroidForegroundApp(registry2, device) {
|
|
137187
|
+
const ref = androidDevtoolsRef(device);
|
|
137188
|
+
const devtools = await registry2.resolveService(ref.urn, ref.options);
|
|
137189
|
+
const [capture, size] = await Promise.all([
|
|
137190
|
+
// The default settle, as ui-tree: free on a settled screen, and it keeps a
|
|
137191
|
+
// mid-transition window list (right after home or a launch) from naming the old app.
|
|
137192
|
+
devtools.getHierarchy({ maxDepth: 0, clearCache: true }),
|
|
137193
|
+
devtools.getScreenSize()
|
|
137194
|
+
]);
|
|
137195
|
+
const tree = adaptAndroidTree({ ...capture, truncated: false }, size);
|
|
137196
|
+
return { bundleId: tree.foregroundApp, alertVisible: tree.alertVisible };
|
|
137197
|
+
}
|
|
137198
|
+
function createForegroundAppTool(registry2) {
|
|
137199
|
+
return {
|
|
137200
|
+
id: "foreground-app",
|
|
137201
|
+
interaction: {
|
|
137202
|
+
startedMsg: () => "Reading foreground app",
|
|
137203
|
+
completedMsg: () => "Read foreground app",
|
|
137204
|
+
failedMsg: ({ failureSignal: failureSignal2 }) => `Failed to read foreground app: ${failureSignal2.error_code}`
|
|
137205
|
+
},
|
|
137206
|
+
description: `Read which app is in front, for SDK callers.
|
|
137207
|
+
Returns { bundleId, name, alertVisible }; under a system alert, bundleId is the app it covers.
|
|
137208
|
+
A field is unset when it is unknown.`,
|
|
137209
|
+
hideFromMcp: true,
|
|
137210
|
+
zodSchema: zodSchema42,
|
|
137211
|
+
capability: capability27,
|
|
137212
|
+
services: () => ({}),
|
|
137213
|
+
execute: dispatchByPlatform({
|
|
137214
|
+
toolId: "foreground-app",
|
|
137215
|
+
capability: capability27,
|
|
137216
|
+
ios: {
|
|
137217
|
+
requires: iosRequires,
|
|
137218
|
+
handler: async (_services, _params, device) => {
|
|
137219
|
+
if (await isTvOsSimulator(device.id)) {
|
|
137220
|
+
throw new UnsupportedOperationError("foreground-app", device, "tvOS");
|
|
137221
|
+
}
|
|
137222
|
+
return readIosForegroundApp(registry2, device);
|
|
137223
|
+
}
|
|
137224
|
+
},
|
|
137225
|
+
iosRemote: {
|
|
137226
|
+
requires: ["sim-remote"],
|
|
137227
|
+
handler: async (_services, _params, device) => readIosForegroundApp(registry2, device)
|
|
137228
|
+
},
|
|
137229
|
+
android: {
|
|
137230
|
+
requires: androidRequires,
|
|
137231
|
+
handler: async (_services, _params, device) => readAndroidForegroundApp(registry2, device)
|
|
137232
|
+
}
|
|
137233
|
+
})
|
|
137234
|
+
};
|
|
137235
|
+
}
|
|
137236
|
+
|
|
137237
|
+
// ../tool-server/src/tools/fill/index.ts
|
|
137238
|
+
init_zod();
|
|
137239
|
+
init_adb();
|
|
137240
|
+
|
|
137241
|
+
// ../tool-server/src/tools/fill/errors.ts
|
|
137242
|
+
init_src2();
|
|
137243
|
+
function noFocusedFieldError(stage) {
|
|
137244
|
+
return new InvalidToolInputError(
|
|
137245
|
+
"Nothing that takes text has keyboard focus, so nothing was changed. Tap the text field first, then call fill again.",
|
|
137246
|
+
{
|
|
137247
|
+
error_code: FAILURE_CODES.FILL_NO_FOCUSED_FIELD,
|
|
137248
|
+
failure_stage: stage,
|
|
137249
|
+
error_kind: "validation"
|
|
137250
|
+
}
|
|
137251
|
+
);
|
|
137252
|
+
}
|
|
137253
|
+
function notVerifiedError(stage) {
|
|
137254
|
+
return new FailureError(
|
|
137255
|
+
"fill wrote to the focused field, but reading it back did not show the requested text. The field may hold other or partial text: read it before retrying.",
|
|
137256
|
+
{
|
|
137257
|
+
error_code: FAILURE_CODES.FILL_NOT_VERIFIED,
|
|
137258
|
+
failure_stage: stage,
|
|
137259
|
+
failure_area: "tool_server",
|
|
137260
|
+
error_kind: "unknown"
|
|
137261
|
+
}
|
|
137262
|
+
);
|
|
137263
|
+
}
|
|
137264
|
+
function notChangedError(stage) {
|
|
137265
|
+
return new FailureError(
|
|
137266
|
+
"fill could not select the text of the focused field, so nothing was changed. Tap the field and retry.",
|
|
137267
|
+
{
|
|
137268
|
+
error_code: FAILURE_CODES.FILL_NOT_VERIFIED,
|
|
137269
|
+
failure_stage: stage,
|
|
137270
|
+
failure_area: "tool_server",
|
|
137271
|
+
error_kind: "unknown"
|
|
137272
|
+
}
|
|
137273
|
+
);
|
|
137274
|
+
}
|
|
137275
|
+
function notAnsweredError(stage) {
|
|
137276
|
+
return new FailureError(
|
|
137277
|
+
"The device did not finish the fill in time. The field may have changed: read it before retrying.",
|
|
137278
|
+
{
|
|
137279
|
+
error_code: FAILURE_CODES.FILL_NOT_VERIFIED,
|
|
137280
|
+
failure_stage: stage,
|
|
137281
|
+
failure_area: "tool_server",
|
|
137282
|
+
error_kind: "timeout"
|
|
137283
|
+
}
|
|
137284
|
+
);
|
|
137285
|
+
}
|
|
137286
|
+
function unsupportedFieldError(detail, stage) {
|
|
137287
|
+
return new InvalidToolInputError(
|
|
137288
|
+
`fill cannot set this field's text: ${detail}. Nothing was changed.`,
|
|
137289
|
+
{
|
|
137290
|
+
error_code: FAILURE_CODES.FILL_UNSUPPORTED_FIELD,
|
|
137291
|
+
failure_stage: stage,
|
|
137292
|
+
error_kind: "unsupported"
|
|
137293
|
+
}
|
|
137294
|
+
);
|
|
137295
|
+
}
|
|
137296
|
+
|
|
137297
|
+
// ../tool-server/src/tools/fill/keys.ts
|
|
137298
|
+
init_src2();
|
|
137299
|
+
init_src2();
|
|
137300
|
+
var MAX_CLEAR_KEYS = 100;
|
|
137301
|
+
var XCTEST_DELETE = "\b";
|
|
137302
|
+
var KEY_TIMING = { holdMs: 20, settleMs: 300, typeDelayMs: 30 };
|
|
137303
|
+
var sleep14 = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
137304
|
+
function typeableOnSimulator(text) {
|
|
137305
|
+
for (const char of text) if (!charToKeyPress(char)) return false;
|
|
137306
|
+
return true;
|
|
137307
|
+
}
|
|
137308
|
+
async function withoutTextInErrors(stage, run2) {
|
|
137309
|
+
try {
|
|
137310
|
+
return await run2();
|
|
137311
|
+
} catch (err) {
|
|
137312
|
+
const signal = getFailureSignal(err);
|
|
137313
|
+
throw new FailureError(
|
|
137314
|
+
"fill failed partway through typing: the focused field may hold part of the text. Read it before retrying.",
|
|
137315
|
+
signal ?? {
|
|
137316
|
+
error_code: FAILURE_CODES.FILL_NOT_VERIFIED,
|
|
137317
|
+
failure_stage: stage,
|
|
137318
|
+
failure_area: "tool_server",
|
|
137319
|
+
error_kind: "unknown"
|
|
137320
|
+
}
|
|
137321
|
+
);
|
|
137322
|
+
}
|
|
137323
|
+
}
|
|
137324
|
+
async function pressSimulatorBackspace(registry2, device) {
|
|
137325
|
+
const ref = simulatorServerRef(device);
|
|
137326
|
+
const api = await registry2.resolveService(ref.urn, ref.options);
|
|
137327
|
+
await api.pressKey("Down", NAMED_KEYS.backspace);
|
|
137328
|
+
await sleep14(KEY_TIMING.holdMs);
|
|
137329
|
+
await api.pressKey("Up", NAMED_KEYS.backspace);
|
|
137330
|
+
await sleep14(KEY_TIMING.settleMs);
|
|
137331
|
+
}
|
|
137332
|
+
async function typeOnSimulator(registry2, device, text) {
|
|
137333
|
+
if (!text) return;
|
|
137334
|
+
await withoutTextInErrors(
|
|
137335
|
+
"fill_keys_ios",
|
|
137336
|
+
() => typeSimulatorServer(registry2, device, {
|
|
137337
|
+
udid: device.id,
|
|
137338
|
+
text,
|
|
137339
|
+
delayMs: KEY_TIMING.typeDelayMs
|
|
137340
|
+
})
|
|
137341
|
+
);
|
|
137342
|
+
}
|
|
137343
|
+
async function fillByDeviceKeys(registry2, device, text) {
|
|
137344
|
+
const bundleId = requireCurrentIosDeviceApp(device.id);
|
|
137345
|
+
const ref = iosDeviceRunnerRef(device);
|
|
137346
|
+
const api = await registry2.resolveService(ref.urn, ref.options);
|
|
137347
|
+
const type = async (chars) => {
|
|
137348
|
+
try {
|
|
137349
|
+
await typeText(api, bundleId, chars);
|
|
137350
|
+
} catch (err) {
|
|
137351
|
+
if (err instanceof RunnerCommandError && err.code === "TEXT_INPUT_NOT_FOCUSED") {
|
|
137352
|
+
throw noFocusedFieldError("fill_keys_ios_device_focus");
|
|
137353
|
+
}
|
|
137354
|
+
throw err;
|
|
137355
|
+
}
|
|
137356
|
+
};
|
|
137357
|
+
await type(XCTEST_DELETE.repeat(MAX_CLEAR_KEYS));
|
|
137358
|
+
if (text) await withoutTextInErrors("fill_keys_ios_device", () => type(text));
|
|
137359
|
+
}
|
|
137360
|
+
|
|
137361
|
+
// ../tool-server/src/tools/fill/ios.ts
|
|
137362
|
+
var NEWLINE = /[\r\n]/;
|
|
137363
|
+
async function fillIos(registry2, device, text) {
|
|
137364
|
+
const ref = axServiceRef(device);
|
|
137365
|
+
const ax = await registry2.resolveService(ref.urn, ref.options);
|
|
137366
|
+
const typeable = typeableOnSimulator(text) && !NEWLINE.test(text);
|
|
137367
|
+
const first = await ax.fill(text, { typeable });
|
|
137368
|
+
if (!first.focused) throw noFocusedFieldError("fill_ios_no_focus");
|
|
137369
|
+
if (first.unsupported) {
|
|
137370
|
+
throw unsupportedFieldError(
|
|
137371
|
+
"the focused element is not a text input (a date or time input, or a picker)",
|
|
137372
|
+
"fill_ios_unsupported_field"
|
|
137373
|
+
);
|
|
137374
|
+
}
|
|
137375
|
+
if (first.singleLine) {
|
|
137376
|
+
throw unsupportedFieldError(
|
|
137377
|
+
"a single-line text field cannot hold a newline",
|
|
137378
|
+
"fill_ios_single_line"
|
|
137379
|
+
);
|
|
137380
|
+
}
|
|
137381
|
+
if (first.timedOut) throw notAnsweredError("fill_ios_timeout");
|
|
137382
|
+
if (first.untouched) throw notChangedError("fill_ios_select_failed");
|
|
137383
|
+
if (first.verified) return { verified: true };
|
|
137384
|
+
if (first.secure) {
|
|
137385
|
+
if (!typeable) {
|
|
137386
|
+
throw unsupportedFieldError(
|
|
137387
|
+
"a secure text field takes only text the keyboard can type on one line, and this text has a character it cannot",
|
|
137388
|
+
"fill_ios_secure_untypeable"
|
|
137389
|
+
);
|
|
137390
|
+
}
|
|
137391
|
+
if (!first.cleared) throw notVerifiedError("fill_ios_secure_not_cleared");
|
|
137392
|
+
await typeOnSimulator(registry2, device, text);
|
|
137393
|
+
const check3 = await ax.fill(text, { check: true });
|
|
137394
|
+
if (check3.verified) return { verified: true };
|
|
137395
|
+
throw notVerifiedError("fill_ios_not_verified");
|
|
137396
|
+
}
|
|
137397
|
+
if (first.needsBackspace) {
|
|
137398
|
+
await pressSimulatorBackspace(registry2, device);
|
|
137399
|
+
const check3 = await ax.fill(text, { check: true });
|
|
137400
|
+
if (check3.verified) return { verified: true };
|
|
137401
|
+
}
|
|
137402
|
+
throw notVerifiedError("fill_ios_not_verified");
|
|
137403
|
+
}
|
|
137404
|
+
|
|
137405
|
+
// ../tool-server/src/tools/fill/android.ts
|
|
137406
|
+
async function fillAndroid(registry2, device, text) {
|
|
137407
|
+
const ref = androidDevtoolsRef(device);
|
|
137408
|
+
const helper = await registry2.resolveService(ref.urn, ref.options);
|
|
137409
|
+
const answer = await helper.setText(text);
|
|
137410
|
+
if (!answer.focused) throw noFocusedFieldError("fill_android_no_focus");
|
|
137411
|
+
if (answer.singleLine) {
|
|
137412
|
+
throw unsupportedFieldError(
|
|
137413
|
+
"a single-line text field cannot hold a newline",
|
|
137414
|
+
"fill_android_single_line"
|
|
137415
|
+
);
|
|
137416
|
+
}
|
|
137417
|
+
if (answer.timedOut) throw notAnsweredError("fill_android_timeout");
|
|
137418
|
+
if (answer.verified) return { verified: true };
|
|
137419
|
+
throw notVerifiedError("fill_android_not_verified");
|
|
137420
|
+
}
|
|
137421
|
+
|
|
137422
|
+
// ../tool-server/src/tools/fill/chromium.ts
|
|
137423
|
+
init_src2();
|
|
137424
|
+
function buildChromiumFillScript(text) {
|
|
137425
|
+
return `(async () => {
|
|
137426
|
+
const text = ${JSON.stringify(text)};
|
|
137427
|
+
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
137428
|
+
try {
|
|
137429
|
+
const deepActive = (doc) => {
|
|
137430
|
+
let el = doc.activeElement;
|
|
137431
|
+
while (el && el.shadowRoot && el.shadowRoot.activeElement) el = el.shadowRoot.activeElement;
|
|
137432
|
+
return el;
|
|
137433
|
+
};
|
|
137434
|
+
let el = deepActive(document);
|
|
137435
|
+
while (el && String(el.tagName).toLowerCase() === "iframe") {
|
|
137436
|
+
let inner = null;
|
|
137437
|
+
try { inner = el.contentDocument; } catch (e) { inner = null; }
|
|
137438
|
+
if (!inner) return { status: "no_focus" };
|
|
137439
|
+
el = deepActive(inner);
|
|
137440
|
+
}
|
|
137441
|
+
if (!el || el.tagName === undefined) return { status: "no_focus" };
|
|
137442
|
+
const doc = el.ownerDocument || document;
|
|
137443
|
+
const win = doc.defaultView || window;
|
|
137444
|
+
const tag = String(el.tagName).toLowerCase();
|
|
137445
|
+
const type = tag === "input" ? String(el.type || "text").toLowerCase() : null;
|
|
137446
|
+
if (type !== null && /^(date|time|month|week|datetime-local)$/.test(type)) {
|
|
137447
|
+
return { status: "unsupported", detail: "a " + type + " input holds a structured value" };
|
|
137448
|
+
}
|
|
137449
|
+
const control =
|
|
137450
|
+
tag === "textarea" ||
|
|
137451
|
+
(tag === "input" && !/^(button|checkbox|radio|file|submit|reset|image|range|color|hidden)$/.test(type));
|
|
137452
|
+
if (!control && el.isContentEditable !== true) return { status: "no_focus" };
|
|
137453
|
+
if (control && el.disabled === true) return { status: "unsupported", detail: "it is disabled" };
|
|
137454
|
+
if (control && el.readOnly === true) return { status: "unsupported", detail: "it is read-only" };
|
|
137455
|
+
// An <input> holds one line and drops a newline.
|
|
137456
|
+
if (tag === "input" && /[\\r\\n]/.test(text)) {
|
|
137457
|
+
return { status: "unsupported", detail: "a single-line input cannot hold a newline" };
|
|
137458
|
+
}
|
|
137459
|
+
if (!control) {
|
|
137460
|
+
// designMode or <body contenteditable>: the whole document is the field.
|
|
137461
|
+
let host = el;
|
|
137462
|
+
while (host.parentElement && host.parentElement.isContentEditable === true) host = host.parentElement;
|
|
137463
|
+
if (host === doc.body || host === doc.documentElement) {
|
|
137464
|
+
return { status: "unsupported", detail: "the whole document is editable" };
|
|
137465
|
+
}
|
|
137466
|
+
}
|
|
137467
|
+
const trimEnd = (s) => s.replace(/[\\u200b\\ufeff]/g, "").replace(/\\n+$/, "");
|
|
137468
|
+
const read = () =>
|
|
137469
|
+
control ? String(el.value == null ? "" : el.value) : trimEnd(String(el.innerText == null ? el.textContent || "" : el.innerText));
|
|
137470
|
+
const matches = () => (control ? read() === text : read() === trimEnd(text));
|
|
137471
|
+
const settle = async () => {
|
|
137472
|
+
for (let i = 0; i < 10; i++) {
|
|
137473
|
+
await sleep(i === 0 ? 0 : 50);
|
|
137474
|
+
if (matches()) return true;
|
|
137475
|
+
}
|
|
137476
|
+
return false;
|
|
137477
|
+
};
|
|
137478
|
+
|
|
137479
|
+
if (control) {
|
|
137480
|
+
try { el.select(); } catch (e) { /* no selection API */ }
|
|
137481
|
+
} else {
|
|
137482
|
+
const sel = doc.getSelection();
|
|
137483
|
+
const range = doc.createRange();
|
|
137484
|
+
range.selectNodeContents(el);
|
|
137485
|
+
sel.removeAllRanges();
|
|
137486
|
+
sel.addRange(range);
|
|
137487
|
+
}
|
|
137488
|
+
if (text === "") {
|
|
137489
|
+
if (read() !== "") doc.execCommand("delete");
|
|
137490
|
+
} else {
|
|
137491
|
+
doc.execCommand("insertText", false, text);
|
|
137492
|
+
}
|
|
137493
|
+
let verified = await settle();
|
|
137494
|
+
if (!verified && control) {
|
|
137495
|
+
const proto = tag === "textarea" ? win.HTMLTextAreaElement.prototype : win.HTMLInputElement.prototype;
|
|
137496
|
+
const setter = Object.getOwnPropertyDescriptor(proto, "value").set;
|
|
137497
|
+
setter.call(el, text);
|
|
137498
|
+
el.dispatchEvent(new win.Event("input", { bubbles: true }));
|
|
137499
|
+
el.dispatchEvent(new win.Event("change", { bubbles: true }));
|
|
137500
|
+
verified = await settle();
|
|
137501
|
+
}
|
|
137502
|
+
return { status: "ok", verified: verified };
|
|
137503
|
+
} catch (e) {
|
|
137504
|
+
return { status: "error" };
|
|
137505
|
+
}
|
|
137506
|
+
})()`;
|
|
137507
|
+
}
|
|
137508
|
+
async function fillChromium(registry2, device, text) {
|
|
137509
|
+
const ref = chromiumCdpRef(device);
|
|
137510
|
+
const api = await registry2.resolveService(ref.urn, ref.options);
|
|
137511
|
+
const out = await api.cdp.send(
|
|
137512
|
+
"Runtime.evaluate",
|
|
137513
|
+
{ expression: buildChromiumFillScript(text), awaitPromise: true, returnByValue: true },
|
|
137514
|
+
1e4
|
|
137515
|
+
);
|
|
137516
|
+
const answer = out.result?.value;
|
|
137517
|
+
switch (answer?.status) {
|
|
137518
|
+
case "ok":
|
|
137519
|
+
if (answer.verified === true) {
|
|
137520
|
+
return { verified: true };
|
|
137521
|
+
}
|
|
137522
|
+
throw notVerifiedError("fill_chromium_not_verified");
|
|
137523
|
+
case "no_focus":
|
|
137524
|
+
throw noFocusedFieldError("fill_chromium_no_focus");
|
|
137525
|
+
case "unsupported":
|
|
137526
|
+
throw unsupportedFieldError(answer.detail ?? "unsupported field", "fill_chromium_field");
|
|
137527
|
+
default:
|
|
137528
|
+
throw new FailureError("fill could not run in the page; nothing is known about the field.", {
|
|
137529
|
+
error_code: FAILURE_CODES.FILL_NOT_VERIFIED,
|
|
137530
|
+
failure_stage: "fill_chromium_script",
|
|
137531
|
+
failure_area: "tool_server",
|
|
137532
|
+
error_kind: "unknown",
|
|
137533
|
+
failure_command: "cdp"
|
|
137534
|
+
});
|
|
137535
|
+
}
|
|
137536
|
+
}
|
|
137537
|
+
|
|
137538
|
+
// ../tool-server/src/tools/fill/index.ts
|
|
137539
|
+
var zodSchema43 = external_exports.object({
|
|
137540
|
+
udid: external_exports.string().min(1).describe("Target device id from `list-devices`."),
|
|
137541
|
+
text: external_exports.string().describe(
|
|
137542
|
+
'The text the focused field must hold afterwards; "" clears it. Supports `{{secret:<NAME>}}` placeholders like `keyboard`.'
|
|
137543
|
+
)
|
|
137544
|
+
});
|
|
137545
|
+
var capability28 = {
|
|
137546
|
+
apple: { simulator: true, device: true },
|
|
137547
|
+
appleRemote: { simulator: true },
|
|
137548
|
+
android: { emulator: true, device: true, unknown: true },
|
|
137549
|
+
chromium: { app: true }
|
|
137550
|
+
};
|
|
137551
|
+
function createFillTool(registry2) {
|
|
137552
|
+
const dispatch = dispatchByPlatform({
|
|
137553
|
+
toolId: "fill",
|
|
137554
|
+
capability: capability28,
|
|
137555
|
+
ios: {
|
|
137556
|
+
requires: iosRequires,
|
|
137557
|
+
handler: async (_services, params, device) => {
|
|
137558
|
+
if (await isTvOsSimulator(device.id)) {
|
|
137559
|
+
throw new UnsupportedOperationError("fill", device, "tvOS");
|
|
137560
|
+
}
|
|
137561
|
+
return fillIos(registry2, device, params.text);
|
|
137562
|
+
}
|
|
137563
|
+
},
|
|
137564
|
+
iosRemote: {
|
|
137565
|
+
requires: ["sim-remote"],
|
|
137566
|
+
handler: async (_services, params, device) => {
|
|
137567
|
+
if (await isRemoteTvOsSimulator(device.id)) {
|
|
137568
|
+
throw new UnsupportedOperationError("fill", device, "tvOS");
|
|
137569
|
+
}
|
|
137570
|
+
return fillIos(registry2, device, params.text);
|
|
137571
|
+
}
|
|
137572
|
+
},
|
|
137573
|
+
iosDevice: {
|
|
137574
|
+
requires: ["xcrun"],
|
|
137575
|
+
handler: async (_services, params, device) => {
|
|
137576
|
+
await fillByDeviceKeys(registry2, device, params.text);
|
|
137577
|
+
return { verified: false };
|
|
137578
|
+
}
|
|
137579
|
+
},
|
|
137580
|
+
android: {
|
|
137581
|
+
requires: androidRequires,
|
|
137582
|
+
handler: async (_services, params, device) => {
|
|
137583
|
+
if (await isAndroidTv(device.id)) {
|
|
137584
|
+
throw new UnsupportedOperationError("fill", device, "Android TV");
|
|
137585
|
+
}
|
|
137586
|
+
return fillAndroid(registry2, device, params.text);
|
|
137587
|
+
}
|
|
137588
|
+
},
|
|
137589
|
+
chromium: {
|
|
137590
|
+
handler: async (_services, params, device) => fillChromium(registry2, device, params.text)
|
|
137591
|
+
}
|
|
137592
|
+
});
|
|
137593
|
+
return {
|
|
137594
|
+
id: "fill",
|
|
137595
|
+
interaction: {
|
|
137596
|
+
// Never quote `text`: it may be a credential, and these messages reach
|
|
137597
|
+
// the event log.
|
|
137598
|
+
startedMsg: () => "Filling the focused field",
|
|
137599
|
+
completedMsg: () => "Filled the focused field",
|
|
137600
|
+
failedMsg: ({ failureSignal: failureSignal2 }) => `Failed to fill the field: ${failureSignal2.error_code}`
|
|
137601
|
+
},
|
|
137602
|
+
description: `Set the text of the focused text field to exactly \`text\`, replacing what it holds; "" clears it. Tap the field first.
|
|
137603
|
+
Returns { verified }, never the text: true when the field was read back holding the text, false on a physical iPhone, where nothing can read it back.
|
|
137604
|
+
Fails with FILL_NO_FOCUSED_FIELD when nothing editable has focus, FILL_NOT_VERIFIED when the field does not read back the text, FILL_UNSUPPORTED_FIELD for a field that cannot take the text (a date or time input, a newline in a single-line field; nothing is changed). Fails if the device's ax-service or devtools helper predates fill; update argent. Not supported on TV targets or Vega.`,
|
|
137605
|
+
hideFromMcp: true,
|
|
137606
|
+
zodSchema: zodSchema43,
|
|
137607
|
+
capability: capability28,
|
|
137608
|
+
services: () => ({}),
|
|
137609
|
+
execute: async (services, params, options) => {
|
|
137610
|
+
const { text, secrets } = resolveSecretPlaceholders(params.text);
|
|
137611
|
+
try {
|
|
137612
|
+
return await dispatch(services, { udid: params.udid, text }, options);
|
|
137613
|
+
} catch (err) {
|
|
137614
|
+
throw redactSecretsFromError(err, secrets);
|
|
137615
|
+
}
|
|
137616
|
+
}
|
|
137617
|
+
};
|
|
137618
|
+
}
|
|
137619
|
+
|
|
137044
137620
|
// ../tool-server/src/tools/await-screen-idle/index.ts
|
|
137045
137621
|
init_zod();
|
|
137046
137622
|
init_device_info();
|
|
@@ -137049,7 +137625,7 @@ var AWAIT_SCREEN_IDLE_TOOL_ID = "await-screen-idle";
|
|
|
137049
137625
|
var DEFAULT_TIMEOUT_MS4 = 3e3;
|
|
137050
137626
|
var DEFAULT_POLL_INTERVAL_MS2 = 200;
|
|
137051
137627
|
var DEFAULT_MIN_STABLE_MS = 250;
|
|
137052
|
-
var
|
|
137628
|
+
var zodSchema44 = external_exports.object({
|
|
137053
137629
|
udid: external_exports.string().min(1).describe("Target device id from `list-devices` (iOS UDID, Android serial, or Chromium id)."),
|
|
137054
137630
|
timeoutMs: external_exports.number().int().positive().max(12e4).optional().describe(
|
|
137055
137631
|
`Max time to wait for the screen to settle before giving up (default ${DEFAULT_TIMEOUT_MS4}).`
|
|
@@ -137059,7 +137635,7 @@ var zodSchema42 = external_exports.object({
|
|
|
137059
137635
|
`The screen must hold the same content for at least this long to count as settled (default ${DEFAULT_MIN_STABLE_MS}).`
|
|
137060
137636
|
)
|
|
137061
137637
|
}).strict();
|
|
137062
|
-
var
|
|
137638
|
+
var capability29 = {
|
|
137063
137639
|
apple: { simulator: true, device: true },
|
|
137064
137640
|
appleRemote: { simulator: true },
|
|
137065
137641
|
android: { emulator: true, device: true, unknown: true },
|
|
@@ -137102,12 +137678,12 @@ function createAwaitScreenIdleTool(registry2) {
|
|
|
137102
137678
|
|
|
137103
137679
|
Polls the same accessibility / DOM tree as \`describe\` every pollIntervalMs (default ${DEFAULT_POLL_INTERVAL_MS2}ms) until it
|
|
137104
137680
|
has content and that content holds identical for minStableMs (default ${DEFAULT_MIN_STABLE_MS}ms), or timeoutMs (default
|
|
137105
|
-
${DEFAULT_TIMEOUT_MS4}ms) is reached. Returns { settled, waitedMs, polls }
|
|
137681
|
+
${DEFAULT_TIMEOUT_MS4}ms) is reached. Returns { settled, waitedMs, polls }; settled=false means the screen never went
|
|
137106
137682
|
still before the timeout. Use after a launch/navigation to wait for the UI to render before screenshotting or tapping.`,
|
|
137107
137683
|
searchHint: "wait until screen settles idle stable stops changing animation transition rendered ready before screenshot",
|
|
137108
137684
|
longRunning: true,
|
|
137109
|
-
zodSchema:
|
|
137110
|
-
capability:
|
|
137685
|
+
zodSchema: zodSchema44,
|
|
137686
|
+
capability: capability29,
|
|
137111
137687
|
services: (params) => {
|
|
137112
137688
|
const device = resolveDevice(params.udid);
|
|
137113
137689
|
if (device.platform === "chromium") {
|
|
@@ -137117,7 +137693,7 @@ still before the timeout. Use after a launch/navigation to wait for the UI to re
|
|
|
137117
137693
|
},
|
|
137118
137694
|
async execute(services, params, ctx) {
|
|
137119
137695
|
const device = resolveDevice(params.udid);
|
|
137120
|
-
assertSupported(AWAIT_SCREEN_IDLE_TOOL_ID,
|
|
137696
|
+
assertSupported(AWAIT_SCREEN_IDLE_TOOL_ID, capability29, device);
|
|
137121
137697
|
if (device.platform === "ios") await ensureDeps(iosRequires);
|
|
137122
137698
|
else if (device.platform === "ios-remote") await ensureDeps(["sim-remote"]);
|
|
137123
137699
|
else if (device.platform === "android") await ensureDeps(androidRequires);
|
|
@@ -137204,10 +137780,10 @@ function bootstrapFailureMessage(bootstrap) {
|
|
|
137204
137780
|
// ../tool-server/src/tools/profiler/react/react-profiler-start.ts
|
|
137205
137781
|
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.";
|
|
137206
137782
|
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.";
|
|
137207
|
-
var
|
|
137783
|
+
var zodSchema45 = external_exports.object({
|
|
137208
137784
|
port: metroPortField,
|
|
137209
137785
|
device_id: external_exports.string().describe(
|
|
137210
|
-
"Device id from list-devices
|
|
137786
|
+
"Device id from list-devices: the SAME id you passed to debugger-connect (iOS simulator UDID or Android serial)."
|
|
137211
137787
|
),
|
|
137212
137788
|
sample_interval_us: external_exports.coerce.number().int().positive().default(100).describe("CPU sampling interval in microseconds (default 100)"),
|
|
137213
137789
|
force: external_exports.boolean().default(false).describe(
|
|
@@ -137232,11 +137808,11 @@ function createReactProfilerStartTool(registry2) {
|
|
|
137232
137808
|
description: `Start CPU profiling + React commit capture on the connected Hermes runtime.
|
|
137233
137809
|
Delegates React commit capture to the in-app React DevTools backend (ri.startProfiling).
|
|
137234
137810
|
If another tool-server already owns the session, returns { already_running: true, owner, stale, how_to_reclaim } without clobbering their data. Pass { force: true } to reclaim a fresh owner's session, but BEFORE OVERTAKING - ask the user for approval first, see relevant skill for guidance.
|
|
137235
|
-
Before calling this, ask the user if they also want native profiling (native-profiler-start)
|
|
137811
|
+
Before calling this, ask the user if they also want native profiling (native-profiler-start), and recommend running both in parallel for a complete picture.
|
|
137236
137812
|
After starting, ask the user to perform the interaction to profile, then call react-profiler-stop.
|
|
137237
137813
|
Returns { started_at, startedAtEpochMs, hermes_version, detected_architecture } on success, or the already_running payload described above.
|
|
137238
137814
|
Fails if the Hermes runtime is not reachable or the Metro CDP connection cannot be established.`,
|
|
137239
|
-
zodSchema:
|
|
137815
|
+
zodSchema: zodSchema45,
|
|
137240
137816
|
capability: RN_ONLY_TOOL_CAPABILITY,
|
|
137241
137817
|
services: () => ({}),
|
|
137242
137818
|
async execute(_services, params) {
|
|
@@ -137507,10 +138083,10 @@ async function readCommitTree(path53) {
|
|
|
137507
138083
|
}
|
|
137508
138084
|
|
|
137509
138085
|
// ../tool-server/src/tools/profiler/react/react-profiler-stop.ts
|
|
137510
|
-
var
|
|
138086
|
+
var zodSchema46 = external_exports.object({
|
|
137511
138087
|
port: metroPortField,
|
|
137512
138088
|
device_id: external_exports.string().describe(
|
|
137513
|
-
"Device id from list-devices
|
|
138089
|
+
"Device id from list-devices: the SAME id you passed to debugger-connect (iOS simulator UDID or Android serial)."
|
|
137514
138090
|
)
|
|
137515
138091
|
});
|
|
137516
138092
|
function normalizeChangeDescription(raw) {
|
|
@@ -137594,9 +138170,9 @@ Reads commit data from the in-app React DevTools backend.
|
|
|
137594
138170
|
Stores results in the ReactProfilerSession for later use by react-profiler-analyze or react-profiler-cpu-summary.
|
|
137595
138171
|
Call react-profiler-start first, then exercise the app, then call this.
|
|
137596
138172
|
Returns { duration_ms, sample_count, fiber_renders_captured, total_react_commits, hot_commit_indices } summarizing the session.
|
|
137597
|
-
When any commit had fibers whose display name could not be resolved at stop time (typically transient components like modals/tooltips/animations that unmounted before stop), the response also includes { unattributed_ms, unattributed_fiber_count, unattributed_commit_count }
|
|
138173
|
+
When any commit had fibers whose display name could not be resolved at stop time (typically transient components like modals/tooltips/animations that unmounted before stop), the response also includes { unattributed_ms, unattributed_fiber_count, unattributed_commit_count }. These quantify how much work is not accounted for in the per-component breakdown (the per-commit duration itself remains correct).
|
|
137598
138174
|
Fails if no active profiling session exists or the CDP connection was lost during recording.`,
|
|
137599
|
-
zodSchema:
|
|
138175
|
+
zodSchema: zodSchema46,
|
|
137600
138176
|
capability: RN_ONLY_TOOL_CAPABILITY,
|
|
137601
138177
|
services: () => ({}),
|
|
137602
138178
|
async execute(_services, params) {
|
|
@@ -137821,7 +138397,7 @@ Fails if no active profiling session exists or the CDP connection was lost durin
|
|
|
137821
138397
|
|
|
137822
138398
|
// ../tool-server/src/tools/profiler/react/react-profiler-status.ts
|
|
137823
138399
|
init_zod();
|
|
137824
|
-
var
|
|
138400
|
+
var zodSchema47 = external_exports.object({
|
|
137825
138401
|
port: metroPortField,
|
|
137826
138402
|
device_id: external_exports.string().describe(
|
|
137827
138403
|
"Device logicalDeviceId from debugger-connect (iOS simulator UDID or Android logicalDeviceId)."
|
|
@@ -137835,8 +138411,8 @@ function createReactProfilerStatusTool(registry2) {
|
|
|
137835
138411
|
completedMsg: ({ result }) => result.is_running ? "React profiler is running" : "React profiler is stopped",
|
|
137836
138412
|
failedMsg: ({ failureSignal: failureSignal2 }) => `Failed to check React profiler: ${failureSignal2.error_code}`
|
|
137837
138413
|
},
|
|
137838
|
-
description: `Check the state of the React profiler session without side effects. Use after an interruption (debugger disconnect, unexpected error, agent pause) to decide whether to continue with react-profiler-stop, start a new session, or reconnect the debugger. Ownership is verified server-side against this tool-server's in-memory session
|
|
137839
|
-
zodSchema:
|
|
138414
|
+
description: `Check the state of the React profiler session without side effects. Use after an interruption (debugger disconnect, unexpected error, agent pause) to decide whether to continue with react-profiler-stop, start a new session, or reconnect the debugger. Ownership is verified server-side against this tool-server's in-memory session, so no token-threading is required. Returns { session_status, is_running, current_owner, \u2026 }. If this tool-server process restarted after react-profiler-start, status will report 'taken_over'; use react-profiler-start { force: true } to reclaim.`,
|
|
138415
|
+
zodSchema: zodSchema47,
|
|
137840
138416
|
// RN-only: companion to react-profiler-start.
|
|
137841
138417
|
capability: RN_ONLY_TOOL_CAPABILITY,
|
|
137842
138418
|
services: () => ({}),
|
|
@@ -139450,7 +140026,7 @@ var annotationSchema = external_exports.object({
|
|
|
139450
140026
|
),
|
|
139451
140027
|
label: external_exports.string().describe("Description of the action performed")
|
|
139452
140028
|
});
|
|
139453
|
-
var
|
|
140029
|
+
var zodSchema48 = external_exports.object({
|
|
139454
140030
|
port: metroPortField,
|
|
139455
140031
|
device_id: external_exports.string().describe(
|
|
139456
140032
|
"Device logicalDeviceId from debugger-connect (iOS simulator UDID or Android logicalDeviceId)."
|
|
@@ -139483,7 +140059,7 @@ where tapTimestampMs is the timestampMs returned by the tap/swipe tool and start
|
|
|
139483
140059
|
is returned by react-profiler-start.
|
|
139484
140060
|
Use when the profiling session is complete and you need to interpret the collected data.
|
|
139485
140061
|
Fails if react-profiler-stop has not been called or no profiling data is stored.`,
|
|
139486
|
-
zodSchema:
|
|
140062
|
+
zodSchema: zodSchema48,
|
|
139487
140063
|
// RN-only: reads commit data captured via the React DevTools backend, which
|
|
139488
140064
|
// Chromium does not have.
|
|
139489
140065
|
capability: RN_ONLY_TOOL_CAPABILITY,
|
|
@@ -139620,7 +140196,7 @@ Fails if react-profiler-stop has not been called or no profiling data is stored.
|
|
|
139620
140196
|
// ../tool-server/src/tools/profiler/react/react-profiler-component-source.ts
|
|
139621
140197
|
init_zod();
|
|
139622
140198
|
var import_fs6 = require("fs");
|
|
139623
|
-
var
|
|
140199
|
+
var zodSchema49 = external_exports.object({
|
|
139624
140200
|
component_name: external_exports.string().describe("Name of the React component to look up"),
|
|
139625
140201
|
project_root: external_exports.string().describe("Absolute path to the RN project root")
|
|
139626
140202
|
});
|
|
@@ -139637,8 +140213,8 @@ var reactProfilerComponentSourceTool = {
|
|
|
139637
140213
|
description: `Find a React component's source via tree-sitter AST lookup: returns file path, line number, memoization status (isMemoized, hasUseCallback, hasUseMemo), and 50 lines of source for a named React component.
|
|
139638
140214
|
Call this per-finding after react-profiler-analyze to inspect source before proposing a fix.
|
|
139639
140215
|
Returns found: false if the component is not found in user-owned code (e.g. lives in node_modules).
|
|
139640
|
-
When several files define a component with the same name (e.g. platform variants like List.tsx and List.web.tsx), returns the primary match and lists the rest under otherMatches[] (file/line/col)
|
|
139641
|
-
zodSchema:
|
|
140216
|
+
When several files define a component with the same name (e.g. platform variants like List.tsx and List.web.tsx), returns the primary match and lists the rest under otherMatches[] (file/line/col). Check it before assuming the returned file is the one you meant.`,
|
|
140217
|
+
zodSchema: zodSchema49,
|
|
139642
140218
|
// Declared so the tool catalogue groups this with the other react-profiler-*
|
|
139643
140219
|
// tools; the HTTP gate itself is a no-op here, as there is no device arg to
|
|
139644
140220
|
// inspect.
|
|
@@ -139694,7 +140270,7 @@ When several files define a component with the same name (e.g. platform variants
|
|
|
139694
140270
|
// ../tool-server/src/tools/profiler/react/react-profiler-cpu-summary.ts
|
|
139695
140271
|
init_zod();
|
|
139696
140272
|
init_src2();
|
|
139697
|
-
var
|
|
140273
|
+
var zodSchema50 = external_exports.object({
|
|
139698
140274
|
port: metroPortField,
|
|
139699
140275
|
device_id: external_exports.string().describe(
|
|
139700
140276
|
"Device logicalDeviceId from debugger-connect (iOS simulator UDID or Android logicalDeviceId)."
|
|
@@ -139770,13 +140346,13 @@ var reactProfilerCpuSummaryTool = {
|
|
|
139770
140346
|
failedMsg: ({ failureSignal: failureSignal2 }) => `Failed to summarize React CPU profile: ${failureSignal2.error_code}`
|
|
139771
140347
|
},
|
|
139772
140348
|
description: `Return a raw Hermes CPU flamegraph summary (top hotspot functions by self-time).
|
|
139773
|
-
FOR DEDICATED CPU INVESTIGATION ONLY
|
|
140349
|
+
FOR DEDICATED CPU INVESTIGATION ONLY: do NOT call this as part of a normal profiling session.
|
|
139774
140350
|
Use react-profiler-analyze instead; it covers all React rendering performance analysis.
|
|
139775
140351
|
Use when you specifically need to investigate JS CPU hotspots that are NOT tied to React rendering (e.g. regex slowness, cryptography, heavy computations).
|
|
139776
140352
|
Call react-profiler-stop first. Reads directly from the stored cpuProfile.
|
|
139777
140353
|
Returns a markdown table of the top hotspot functions with self-time, total-time, and location.
|
|
139778
140354
|
Fails if react-profiler-stop has not been called or no CPU profile is stored.`,
|
|
139779
|
-
zodSchema:
|
|
140355
|
+
zodSchema: zodSchema50,
|
|
139780
140356
|
// RN-only: reads a Hermes CPU profile; Chromium's V8 sample format differs.
|
|
139781
140357
|
capability: RN_ONLY_TOOL_CAPABILITY,
|
|
139782
140358
|
services: () => ({}),
|
|
@@ -139872,7 +140448,7 @@ function renderMarkdownTable2(entries) {
|
|
|
139872
140448
|
);
|
|
139873
140449
|
return [header, sep5, ...rows].join("\n");
|
|
139874
140450
|
}
|
|
139875
|
-
var
|
|
140451
|
+
var zodSchema51 = external_exports.object({
|
|
139876
140452
|
port: metroPortField,
|
|
139877
140453
|
device_id: external_exports.string().describe(
|
|
139878
140454
|
"Device logicalDeviceId from debugger-connect (iOS simulator UDID or Android logicalDeviceId)."
|
|
@@ -139887,10 +140463,10 @@ var reactProfilerRendersTool = {
|
|
|
139887
140463
|
failedMsg: ({ failureSignal: failureSignal2 }) => `Failed to read React render activity: ${failureSignal2.error_code}`
|
|
139888
140464
|
},
|
|
139889
140465
|
description: `Scan the live React fiber tree to collect component render counts and durations.
|
|
139890
|
-
Returns a markdown table of the top re-rendering components. No profiling session required
|
|
140466
|
+
Returns a markdown table of the top re-rendering components. No profiling session required; works on a live connected app.
|
|
139891
140467
|
Use when you want a quick snapshot of render counts without a full profiling session.
|
|
139892
140468
|
Fails if the React DevTools hook is not present in the runtime or the app is not connected.`,
|
|
139893
|
-
zodSchema:
|
|
140469
|
+
zodSchema: zodSchema51,
|
|
139894
140470
|
// RN-only: queries the React DevTools backend hook on the live runtime.
|
|
139895
140471
|
capability: RN_ONLY_TOOL_CAPABILITY,
|
|
139896
140472
|
services: (params) => ({
|
|
@@ -140047,7 +140623,7 @@ function buildFiberTreeScript(maxDepth, filter) {
|
|
|
140047
140623
|
}
|
|
140048
140624
|
})()`;
|
|
140049
140625
|
}
|
|
140050
|
-
var
|
|
140626
|
+
var zodSchema52 = external_exports.object({
|
|
140051
140627
|
port: metroPortField,
|
|
140052
140628
|
device_id: external_exports.string().describe(
|
|
140053
140629
|
"Device logicalDeviceId from debugger-connect (iOS simulator UDID or Android logicalDeviceId)."
|
|
@@ -140066,7 +140642,7 @@ var reactProfilerFiberTreeTool = {
|
|
|
140066
140642
|
Use when tracing ancestry of a library component or checking for useMemoCache hook (confirms React Compiler is active on a component).
|
|
140067
140643
|
Returns a nested JSON tree of fiber nodes with name, tag, actualDuration, selfBaseDuration, and children.
|
|
140068
140644
|
Fails if the React DevTools hook is not present or no fiber roots have been committed yet.`,
|
|
140069
|
-
zodSchema:
|
|
140645
|
+
zodSchema: zodSchema52,
|
|
140070
140646
|
// RN-only: walks the fiber tree via the React DevTools backend hook.
|
|
140071
140647
|
capability: RN_ONLY_TOOL_CAPABILITY,
|
|
140072
140648
|
services: (params) => ({
|
|
@@ -143864,7 +144440,7 @@ function metroDeviceIdParam(description) {
|
|
|
143864
144440
|
}
|
|
143865
144441
|
|
|
143866
144442
|
// ../tool-server/src/tools/profiler/native-profiler/native-profiler-start.ts
|
|
143867
|
-
var
|
|
144443
|
+
var zodSchema53 = external_exports.object({
|
|
143868
144444
|
device_id: metroDeviceIdParam(
|
|
143869
144445
|
"Target device id from `list-devices` (iOS UDID or Android serial)."
|
|
143870
144446
|
),
|
|
@@ -143875,10 +144451,10 @@ var zodSchema51 = external_exports.object({
|
|
|
143875
144451
|
"iOS-only: path to an Instruments .tracetemplate file (defaults to bundled Argent template). Ignored on Android."
|
|
143876
144452
|
),
|
|
143877
144453
|
malloc_stack_logging: external_exports.boolean().optional().describe(
|
|
143878
|
-
"iOS-only. When true, cold-launches the app under the profiler with Malloc Stack Logging enabled so memory leaks carry an allocation backtrace (responsible frame + library). Without it, leaks are still detected but unattributable
|
|
144454
|
+
"iOS-only. When true, cold-launches the app under the profiler with Malloc Stack Logging enabled so memory leaks carry an allocation backtrace (responsible frame + library). Without it, leaks are still detected but unattributable: Instruments reports '<Call stack limit reached>'. Trade-offs: this RESTARTS the app (current state is lost), adds memory/CPU overhead, and makes the app noticeably slow to launch (every startup allocation records a backtrace), so leave it off for pure CPU/hang profiling. Requires a non-degraded Xcode: on Xcode 26.4 and later the cold-launch path is broken, so the call is rejected up front (re-run without the flag, or set ARGENT_IOS_CAPTURE=device to override if the device path works on your host). ARGENT_IOS_CAPTURE=all-processes (e.g. exported globally for the normal capture path) also rejects this flag up front, since that fallback cannot cold-launch; unset it (or set it to device) first. Ignored on Android."
|
|
143879
144455
|
)
|
|
143880
144456
|
});
|
|
143881
|
-
var
|
|
144457
|
+
var capability30 = {
|
|
143882
144458
|
apple: { simulator: true },
|
|
143883
144459
|
android: { emulator: true, device: true, unknown: true }
|
|
143884
144460
|
};
|
|
@@ -143889,21 +144465,21 @@ var nativeProfilerStartTool = {
|
|
|
143889
144465
|
completedMsg: () => "Started native profiler",
|
|
143890
144466
|
failedMsg: ({ failureSignal: failureSignal2 }) => `Failed to start native profiler: ${failureSignal2.error_code}`
|
|
143891
144467
|
},
|
|
143892
|
-
capability:
|
|
144468
|
+
capability: capability30,
|
|
143893
144469
|
description: `Start native profiling on a booted device. iOS: Instruments via xctrace (CPU, hangs, memory). Android: Perfetto (CPU, jank, RSS-growth weak signal).
|
|
143894
144470
|
Auto-detects the running app process unless app_process is explicitly provided.
|
|
143895
144471
|
After starting, let the user interact with the app, then call native-profiler-stop.
|
|
143896
144472
|
Use when you want to capture native CPU, hang, and memory data for a running app.
|
|
143897
144473
|
Returns { status, pid, traceFile } confirming the recording has started.
|
|
143898
144474
|
Fails if no app is running on the device, or the profiler cannot attach to the process.`,
|
|
143899
|
-
zodSchema:
|
|
144475
|
+
zodSchema: zodSchema53,
|
|
143900
144476
|
services: (params) => ({
|
|
143901
144477
|
session: nativeProfilerSessionRef(resolveDevice(params.device_id))
|
|
143902
144478
|
}),
|
|
143903
144479
|
async execute(services, params) {
|
|
143904
144480
|
const api = services.session;
|
|
143905
144481
|
const device = resolveDevice(params.device_id);
|
|
143906
|
-
assertSupported("native-profiler-start",
|
|
144482
|
+
assertSupported("native-profiler-start", capability30, device);
|
|
143907
144483
|
if (api.platform === "ios") {
|
|
143908
144484
|
await ensureDeps(["xcrun"]);
|
|
143909
144485
|
return startNativeProfilerIos(api, params);
|
|
@@ -143916,12 +144492,12 @@ Fails if no app is running on the device, or the profiler cannot attach to the p
|
|
|
143916
144492
|
// ../tool-server/src/tools/profiler/native-profiler/native-profiler-stop.ts
|
|
143917
144493
|
init_zod();
|
|
143918
144494
|
init_device_info();
|
|
143919
|
-
var
|
|
144495
|
+
var zodSchema54 = external_exports.object({
|
|
143920
144496
|
device_id: metroDeviceIdParam(
|
|
143921
144497
|
"Target device id from `list-devices` (iOS UDID or Android serial)."
|
|
143922
144498
|
)
|
|
143923
144499
|
});
|
|
143924
|
-
var
|
|
144500
|
+
var capability31 = {
|
|
143925
144501
|
apple: { simulator: true },
|
|
143926
144502
|
android: { emulator: true, device: true, unknown: true }
|
|
143927
144503
|
};
|
|
@@ -143949,7 +144525,7 @@ var nativeProfilerStopTool = {
|
|
|
143949
144525
|
completedMsg: ({ result }) => `Saved native profile ${result.traceFile.filename}`,
|
|
143950
144526
|
failedMsg: ({ failureSignal: failureSignal2 }) => `Failed to stop native profiler: ${failureSignal2.error_code}`
|
|
143951
144527
|
},
|
|
143952
|
-
capability:
|
|
144528
|
+
capability: capability31,
|
|
143953
144529
|
// Packaging plus the export passes routinely exceed the 30s MCP fetch timeout.
|
|
143954
144530
|
longRunning: true,
|
|
143955
144531
|
description: `Stop native profiling and export trace data.
|
|
@@ -143959,14 +144535,14 @@ Call native-profiler-start first.
|
|
|
143959
144535
|
Use when the user has finished the interaction to profile and you need to export the trace.
|
|
143960
144536
|
Returns { traceFile, exportedFiles, exportDiagnostics? }; traceFile is the raw trace bundle and exportedFiles the exports, all downloadable artifacts materialized to local paths.
|
|
143961
144537
|
Fails if no active native-profiler-start session exists for the given device_id.`,
|
|
143962
|
-
zodSchema:
|
|
144538
|
+
zodSchema: zodSchema54,
|
|
143963
144539
|
services: (params) => ({
|
|
143964
144540
|
session: nativeProfilerSessionRef(resolveDevice(params.device_id))
|
|
143965
144541
|
}),
|
|
143966
144542
|
async execute(services, params, ctx) {
|
|
143967
144543
|
const api = services.session;
|
|
143968
144544
|
const device = resolveDevice(params.device_id);
|
|
143969
|
-
assertSupported("native-profiler-stop",
|
|
144545
|
+
assertSupported("native-profiler-stop", capability31, device);
|
|
143970
144546
|
if (api.platform === "ios") {
|
|
143971
144547
|
await ensureDeps(["xcrun"]);
|
|
143972
144548
|
const ios = await stopNativeProfilerIos(api);
|
|
@@ -143994,12 +144570,12 @@ Fails if no active native-profiler-start session exists for the given device_id.
|
|
|
143994
144570
|
// ../tool-server/src/tools/profiler/native-profiler/native-profiler-analyze.ts
|
|
143995
144571
|
init_zod();
|
|
143996
144572
|
init_device_info();
|
|
143997
|
-
var
|
|
144573
|
+
var zodSchema55 = external_exports.object({
|
|
143998
144574
|
device_id: metroDeviceIdParam(
|
|
143999
144575
|
"Target device id from `list-devices` (iOS UDID or Android serial)."
|
|
144000
144576
|
)
|
|
144001
144577
|
});
|
|
144002
|
-
var
|
|
144578
|
+
var capability32 = {
|
|
144003
144579
|
apple: { simulator: true },
|
|
144004
144580
|
android: { emulator: true, device: true, unknown: true }
|
|
144005
144581
|
};
|
|
@@ -144010,7 +144586,7 @@ var nativeProfilerAnalyzeTool = {
|
|
|
144010
144586
|
completedMsg: () => "Analyzed native profile",
|
|
144011
144587
|
failedMsg: ({ failureSignal: failureSignal2 }) => `Failed to analyze native profile: ${failureSignal2.error_code}`
|
|
144012
144588
|
},
|
|
144013
|
-
capability:
|
|
144589
|
+
capability: capability32,
|
|
144014
144590
|
// Parsing a trace from a recording up to RECORDING_CAP_MS long routinely exceeds
|
|
144015
144591
|
// the 30s MCP fetch timeout, and an aborted call is replayed, not cancelled.
|
|
144016
144592
|
longRunning: true,
|
|
@@ -144023,14 +144599,14 @@ profiler-stack-query for hang stacks, CPU context, leak details) or implement fi
|
|
|
144023
144599
|
Call native-profiler-stop first to export the trace data.
|
|
144024
144600
|
Use when you need to interpret a completed native profiling recording.
|
|
144025
144601
|
Fails if native-profiler-stop has not been called first to export trace data.`,
|
|
144026
|
-
zodSchema:
|
|
144602
|
+
zodSchema: zodSchema55,
|
|
144027
144603
|
services: (params) => ({
|
|
144028
144604
|
session: nativeProfilerSessionRef(resolveDevice(params.device_id))
|
|
144029
144605
|
}),
|
|
144030
144606
|
async execute(services, params, ctx) {
|
|
144031
144607
|
const api = services.session;
|
|
144032
144608
|
const device = resolveDevice(params.device_id);
|
|
144033
|
-
assertSupported("native-profiler-analyze",
|
|
144609
|
+
assertSupported("native-profiler-analyze", capability32, device);
|
|
144034
144610
|
let result;
|
|
144035
144611
|
if (api.platform === "ios") {
|
|
144036
144612
|
await ensureDeps(["xcrun"]);
|
|
@@ -145093,7 +145669,7 @@ var DEFAULT_TIME_LIMIT_SECONDS = 180;
|
|
|
145093
145669
|
var MAX_TIME_LIMIT_SECONDS = 600;
|
|
145094
145670
|
var POINTER_TRAIL_LENGTH = 8;
|
|
145095
145671
|
var POINTER_REQUEST_TIMEOUT_MS = 2e3;
|
|
145096
|
-
var
|
|
145672
|
+
var zodSchema56 = external_exports.object({
|
|
145097
145673
|
udid: external_exports.string().describe("Target device id from `list-devices` (iOS Simulator UDID or Android serial)."),
|
|
145098
145674
|
timeLimitSeconds: external_exports.number().int().min(1).max(MAX_TIME_LIMIT_SECONDS).optional().describe(
|
|
145099
145675
|
`Auto-stop cap in seconds (default ${DEFAULT_TIME_LIMIT_SECONDS}, max ${MAX_TIME_LIMIT_SECONDS}). Set it to slightly more than the interaction you plan to capture.`
|
|
@@ -145105,7 +145681,7 @@ var zodSchema54 = external_exports.object({
|
|
|
145105
145681
|
"Default true. Draw simulator-server's touch visualizer into the recording: a pulse marks each tap, a comet trail follows swipes and drags, and paired markers show two-finger pinch/rotate, so the video makes clear where every interaction landed. Set false to record the raw screen with no overlay."
|
|
145106
145682
|
)
|
|
145107
145683
|
});
|
|
145108
|
-
var
|
|
145684
|
+
var capability33 = {
|
|
145109
145685
|
apple: { simulator: true },
|
|
145110
145686
|
android: { emulator: true, device: true, unknown: true }
|
|
145111
145687
|
};
|
|
@@ -145117,16 +145693,16 @@ function createScreenRecordingStartTool(registry2) {
|
|
|
145117
145693
|
completedMsg: () => "Started screen recording",
|
|
145118
145694
|
failedMsg: ({ failureSignal: failureSignal2 }) => `Failed to start screen recording: ${failureSignal2.error_code}`
|
|
145119
145695
|
},
|
|
145120
|
-
capability:
|
|
145696
|
+
capability: capability33,
|
|
145121
145697
|
description: `Start recording the device screen to a video file (h264 mp4, 30fps at the device's native resolution).
|
|
145122
145698
|
By default stretches where the screen does not change are trimmed out (see trimStatic), so a long session with only brief activity comes back as a short clip instead of minutes of dead air.
|
|
145123
145699
|
By default every tap, swipe, drag, pinch and rotate is drawn into the video as an on-screen touch marker (see showTouches), so the recording shows where each interaction landed.
|
|
145124
|
-
The recording keeps running across other tool calls (every result carries a reminder) until \`screen-recording-stop\` is called or timeLimitSeconds elapses
|
|
145125
|
-
Use when the user wants a video of an interaction, animation, or app behavior
|
|
145126
|
-
Returns { status: "recording", timeLimitSeconds, outputFile }
|
|
145700
|
+
The recording keeps running across other tool calls (every result carries a reminder) until \`screen-recording-stop\` is called or timeLimitSeconds elapses. Immediately after starting, set yourself a reminder/wakeup for the expected end of the recording so it is never left running.
|
|
145701
|
+
Use when the user wants a video of an interaction, animation, or app behavior; for a single still frame use \`screenshot\` instead.
|
|
145702
|
+
Returns { status: "recording", timeLimitSeconds, outputFile }. The video is retrieved later by \`screen-recording-stop\`, not by reading outputFile directly.
|
|
145127
145703
|
Fails if a recording is already running on the device, the device is not booted, ffmpeg is not installed, or the platform cannot be recorded (tvOS, Chromium, Vega and remote simulators are unsupported).`,
|
|
145128
145704
|
searchHint: "record video screen capture movie mp4 start filming screencast",
|
|
145129
|
-
zodSchema:
|
|
145705
|
+
zodSchema: zodSchema56,
|
|
145130
145706
|
// Resolved inside execute, not declared eagerly: a tvOS udid classifies as
|
|
145131
145707
|
// iOS by shape, so an eager service would spawn simulator-server for a
|
|
145132
145708
|
// device it cannot drive and hang on its ready timeout (as in `screenshot`).
|
|
@@ -145136,7 +145712,7 @@ Fails if a recording is already running on the device, the device is not booted,
|
|
|
145136
145712
|
async execute(services, params) {
|
|
145137
145713
|
const api = services.session;
|
|
145138
145714
|
const device = resolveDevice(params.udid);
|
|
145139
|
-
assertSupported("screen-recording-start",
|
|
145715
|
+
assertSupported("screen-recording-start", capability33, device);
|
|
145140
145716
|
if (device.platform === "ios" && await isTvOsSimulator(params.udid)) {
|
|
145141
145717
|
throw new FailureError(
|
|
145142
145718
|
`Screen recording is not supported on tvOS simulators (device ${params.udid}).`,
|
|
@@ -145225,11 +145801,11 @@ function makePointerControl(simulator) {
|
|
|
145225
145801
|
var import_node_path22 = require("node:path");
|
|
145226
145802
|
init_zod();
|
|
145227
145803
|
init_device_info();
|
|
145228
|
-
var
|
|
145804
|
+
var zodSchema57 = external_exports.object({
|
|
145229
145805
|
udid: external_exports.string().describe("Target device id from `list-devices` (iOS Simulator UDID or Android serial).")
|
|
145230
145806
|
});
|
|
145231
145807
|
var RECORDINGS_DIR = ".argent/recordings";
|
|
145232
|
-
var
|
|
145808
|
+
var capability34 = {
|
|
145233
145809
|
apple: { simulator: true },
|
|
145234
145810
|
android: { emulator: true, device: true, unknown: true }
|
|
145235
145811
|
};
|
|
@@ -145240,21 +145816,21 @@ var screenRecordingStopTool = {
|
|
|
145240
145816
|
completedMsg: ({ result }) => `Saved screen recording ${result.video.filename}`,
|
|
145241
145817
|
failedMsg: ({ failureSignal: failureSignal2 }) => `Failed to stop screen recording: ${failureSignal2.error_code}`
|
|
145242
145818
|
},
|
|
145243
|
-
capability:
|
|
145819
|
+
capability: capability34,
|
|
145244
145820
|
description: `Stop the screen recording started by \`screen-recording-start\` and retrieve the video: frame capture ends and ffmpeg finalizes the mp4.
|
|
145245
|
-
Also retrieves the video when the recording already ended on its own (time limit reached, capture process died)
|
|
145821
|
+
Also retrieves the video when the recording already ended on its own (time limit reached, capture process died); call it even after the cap fired.
|
|
145246
145822
|
Use when the interaction being captured is finished, or a tool-result note reminds you a recording is still running.
|
|
145247
145823
|
Returns { video, durationMs, wallClockMs?, trimmedMs?, panelSwitches?, warning? }; video is a downloadable artifact materialized to a local path. When static-frame trimming removed dead air, durationMs is the trimmed video length and wallClockMs/trimmedMs report the real duration and how much was cut. On a foldable simulator, the recording follows the panel that shows the UI. panelSwitches gives the number of panel changes. The video keeps the size of the first panel. warning is set when argent could not find that panel during the recording.
|
|
145248
145824
|
Fails if no recording (running or finished-but-unretrieved) exists for the given udid.`,
|
|
145249
145825
|
searchHint: "stop end finish screen recording video capture save retrieve",
|
|
145250
|
-
zodSchema:
|
|
145826
|
+
zodSchema: zodSchema57,
|
|
145251
145827
|
services: (params) => ({
|
|
145252
145828
|
session: screenRecordingSessionRef(resolveDevice(params.udid))
|
|
145253
145829
|
}),
|
|
145254
145830
|
async execute(services, params, ctx) {
|
|
145255
145831
|
const api = services.session;
|
|
145256
145832
|
const device = resolveDevice(params.udid);
|
|
145257
|
-
assertSupported("screen-recording-stop",
|
|
145833
|
+
assertSupported("screen-recording-stop", capability34, device);
|
|
145258
145834
|
const stopped = await stopCapture(api);
|
|
145259
145835
|
const artifacts = requireArtifacts(ctx);
|
|
145260
145836
|
const video = await artifacts.register({
|
|
@@ -145280,13 +145856,13 @@ init_src2();
|
|
|
145280
145856
|
var import_fs18 = require("fs");
|
|
145281
145857
|
var timeWindowSchema = external_exports.object({
|
|
145282
145858
|
start: external_exports.coerce.number().describe(
|
|
145283
|
-
"Start of window in ms since profiling started
|
|
145859
|
+
"Start of window in ms since profiling started, the same clock profiler-commit-query prints"
|
|
145284
145860
|
),
|
|
145285
145861
|
end: external_exports.coerce.number().describe(
|
|
145286
|
-
"End of window in ms since profiling started
|
|
145862
|
+
"End of window in ms since profiling started, the same clock profiler-commit-query prints"
|
|
145287
145863
|
)
|
|
145288
145864
|
});
|
|
145289
|
-
var
|
|
145865
|
+
var zodSchema58 = external_exports.object({
|
|
145290
145866
|
port: metroPortField,
|
|
145291
145867
|
device_id: metroDeviceIdParam(
|
|
145292
145868
|
"Device logicalDeviceId from debugger-connect (iOS simulator UDID or Android logicalDeviceId)."
|
|
@@ -145295,7 +145871,7 @@ var zodSchema56 = external_exports.object({
|
|
|
145295
145871
|
"Query mode: top_functions (global hotspots), time_window (CPU in a time range), call_tree (callers/callees of a function), component_cpu (CPU during a component's commits)"
|
|
145296
145872
|
),
|
|
145297
145873
|
time_window_ms: timeWindowSchema.optional().describe(
|
|
145298
|
-
"Time window filter for time_window mode (ms since profiling started
|
|
145874
|
+
"Time window filter for time_window mode (ms since profiling started, the same clock profiler-commit-query prints)"
|
|
145299
145875
|
),
|
|
145300
145876
|
component_name: external_exports.string().optional().describe("Component name for component_cpu mode"),
|
|
145301
145877
|
function_name: external_exports.string().optional().describe("Function name for call_tree mode"),
|
|
@@ -145574,8 +146150,8 @@ Every table states how many samples it covers and how much of that was idle.
|
|
|
145574
146150
|
- component_cpu: For a given component_name, aggregate CPU activity across all its commits.
|
|
145575
146151
|
Use when investigating JS CPU hotspots or correlating CPU cost with specific components.
|
|
145576
146152
|
Returns a markdown table of CPU hotspots, call tree, or per-component CPU breakdown.
|
|
145577
|
-
Fails if no CPU profile is stored
|
|
145578
|
-
zodSchema:
|
|
146153
|
+
Fails if no CPU profile is stored; run react-profiler-stop first.`,
|
|
146154
|
+
zodSchema: zodSchema58,
|
|
145579
146155
|
// RN-only: reads Hermes-format CPU profiles; Chromium's V8 sample format differs.
|
|
145580
146156
|
capability: RN_ONLY_TOOL_CAPABILITY,
|
|
145581
146157
|
services: () => ({}),
|
|
@@ -145655,13 +146231,13 @@ init_zod();
|
|
|
145655
146231
|
init_src2();
|
|
145656
146232
|
var timeRangeSchema = external_exports.object({
|
|
145657
146233
|
start: external_exports.coerce.number().describe(
|
|
145658
|
-
"Start of range in ms since profiling started
|
|
146234
|
+
"Start of range in ms since profiling started, the same clock profiler-commit-query prints"
|
|
145659
146235
|
),
|
|
145660
146236
|
end: external_exports.coerce.number().describe(
|
|
145661
|
-
"End of range in ms since profiling started
|
|
146237
|
+
"End of range in ms since profiling started, the same clock profiler-commit-query prints"
|
|
145662
146238
|
)
|
|
145663
146239
|
});
|
|
145664
|
-
var
|
|
146240
|
+
var zodSchema59 = external_exports.object({
|
|
145665
146241
|
port: metroPortField,
|
|
145666
146242
|
device_id: metroDeviceIdParam(
|
|
145667
146243
|
"Device logicalDeviceId from debugger-connect (iOS simulator UDID or Android logicalDeviceId)."
|
|
@@ -145673,7 +146249,7 @@ var zodSchema57 = external_exports.object({
|
|
|
145673
146249
|
time_range_ms: timeRangeSchema.optional().describe("Time range filter for by_time_range mode"),
|
|
145674
146250
|
commit_index: external_exports.coerce.number().int().optional().describe("Commit index for by_index and cascade_tree modes"),
|
|
145675
146251
|
top_n: external_exports.coerce.number().int().positive().optional().describe(
|
|
145676
|
-
"Max results to return. Defaults to 20 for by_component / by_time_range, which count commits. by_index counts individual fibers and returns all of them unless this is set, because one commit's fibers collapse to far fewer distinct components
|
|
146252
|
+
"Max results to return. Defaults to 20 for by_component / by_time_range, which count commits. by_index counts individual fibers and returns all of them unless this is set, because one commit's fibers collapse to far fewer distinct components, and a small cap there can show less than the analyze report it is meant to expand on."
|
|
145677
146253
|
)
|
|
145678
146254
|
});
|
|
145679
146255
|
async function getCommitTree(port, deviceId) {
|
|
@@ -145934,7 +146510,7 @@ Modes:
|
|
|
145934
146510
|
Use when drilling into specific components or time windows after react-profiler-analyze.
|
|
145935
146511
|
Returns a markdown table or tree of commit data matching the requested mode.
|
|
145936
146512
|
Fails if react-profiler-stop has not been called or no commit data is stored.`,
|
|
145937
|
-
zodSchema:
|
|
146513
|
+
zodSchema: zodSchema59,
|
|
145938
146514
|
// Reads React commit data captured via the React DevTools backend.
|
|
145939
146515
|
capability: RN_ONLY_TOOL_CAPABILITY,
|
|
145940
146516
|
services: () => ({}),
|
|
@@ -146005,7 +146581,7 @@ Fails if react-profiler-stop has not been called or no commit data is stored.`,
|
|
|
146005
146581
|
init_zod();
|
|
146006
146582
|
init_src2();
|
|
146007
146583
|
init_device_info();
|
|
146008
|
-
var
|
|
146584
|
+
var zodSchema60 = external_exports.object({
|
|
146009
146585
|
device_id: metroDeviceIdParam("iOS Simulator UDID or Android serial."),
|
|
146010
146586
|
mode: external_exports.enum(["hang_stacks", "function_callers", "thread_breakdown", "leak_stacks"]).describe(
|
|
146011
146587
|
"Query mode: hang_stacks (full CPU context during a hang), function_callers (who calls a native function), thread_breakdown (CPU split by thread), leak_stacks (leak details by object type)"
|
|
@@ -146323,7 +146899,7 @@ Modes:
|
|
|
146323
146899
|
Use when drilling into native hang stacks, thread CPU breakdown, or memory leaks after native-profiler-analyze.
|
|
146324
146900
|
Returns a markdown report with native call stacks, thread weights, or leak details for the selected mode.
|
|
146325
146901
|
Fails if native-profiler-analyze has not been run or no parsed trace data is in memory.`,
|
|
146326
|
-
zodSchema:
|
|
146902
|
+
zodSchema: zodSchema60,
|
|
146327
146903
|
// No chromium entry: it has no native trace capture.
|
|
146328
146904
|
capability: {
|
|
146329
146905
|
apple: { simulator: true },
|
|
@@ -146393,7 +146969,7 @@ function buildPerfettoAnchor(wallClockStartMs) {
|
|
|
146393
146969
|
}
|
|
146394
146970
|
|
|
146395
146971
|
// ../tool-server/src/tools/profiler/combined/profiler-combined-report.ts
|
|
146396
|
-
var
|
|
146972
|
+
var zodSchema61 = external_exports.object({
|
|
146397
146973
|
port: metroPortField,
|
|
146398
146974
|
device_id: metroDeviceIdParam("iOS Simulator/device UDID or Android serial")
|
|
146399
146975
|
});
|
|
@@ -146410,7 +146986,7 @@ Requires both react-profiler-analyze and native-profiler-analyze to have been ca
|
|
|
146410
146986
|
Call this tool when both profilers were run in parallel on the same session.
|
|
146411
146987
|
Returns a markdown report correlating hangs with React commits, memory leaks, and investigation hints.
|
|
146412
146988
|
Fails if either react-profiler-analyze or native-profiler-analyze has not been called first.`,
|
|
146413
|
-
zodSchema:
|
|
146989
|
+
zodSchema: zodSchema61,
|
|
146414
146990
|
// iOS reads xctrace output; Android re-queries the Perfetto .pftrace via
|
|
146415
146991
|
// loadAndroidCombinedData. Chromium has no native trace capture.
|
|
146416
146992
|
capability: {
|
|
@@ -146734,7 +147310,7 @@ function assertSafeSessionId(sessionId) {
|
|
|
146734
147310
|
);
|
|
146735
147311
|
}
|
|
146736
147312
|
}
|
|
146737
|
-
var
|
|
147313
|
+
var zodSchema62 = external_exports.object({
|
|
146738
147314
|
mode: external_exports.enum(["list", "load_react", "load_native"]).describe(
|
|
146739
147315
|
"list: show available sessions on disk. load_react: load a React profiler session into memory for query tools. load_native: re-parse native profiler XML files (xctrace on iOS) into memory for query tools."
|
|
146740
147316
|
),
|
|
@@ -147095,7 +147671,7 @@ Modes:
|
|
|
147095
147671
|
For Android .pftrace restores, pass app_process for older sessions that do not have a metadata sidecar.
|
|
147096
147672
|
Returns a summary of the loaded session or a session list for the list mode.
|
|
147097
147673
|
Fails if the session_id is not found or required XML files are missing from disk.`,
|
|
147098
|
-
zodSchema:
|
|
147674
|
+
zodSchema: zodSchema62,
|
|
147099
147675
|
// The Hermes, xctrace and perfetto formats this loads have no Chromium
|
|
147100
147676
|
// equivalent; the gate fails at the call site, not inside the trace parser.
|
|
147101
147677
|
capability: RN_ONLY_TOOL_CAPABILITY,
|
|
@@ -147224,7 +147800,7 @@ function unnameableSessionUrns(urns) {
|
|
|
147224
147800
|
}
|
|
147225
147801
|
|
|
147226
147802
|
// ../tool-server/src/tools/simulator/stop-simulator-server.ts
|
|
147227
|
-
var
|
|
147803
|
+
var zodSchema63 = external_exports.object({
|
|
147228
147804
|
udid: external_exports.string().describe(
|
|
147229
147805
|
"Target device id (iOS UDID, Android serial, or Chromium id) whose transport session to stop"
|
|
147230
147806
|
)
|
|
@@ -147238,7 +147814,7 @@ function createStopSimulatorServerTool(registry2) {
|
|
|
147238
147814
|
failedMsg: ({ params, failureSignal: failureSignal2 }) => `Failed to stop simulator server for ${params.udid}: ${failureSignal2.error_code}`
|
|
147239
147815
|
},
|
|
147240
147816
|
description: `Stop the transport session for a specific device (iOS simulator / Android: simulator-server process; physical iOS: the on-device runner; Chromium: CDP WebSocket) and free its resources; on a TV target it also reaps that device's TV-control daemons. Use when you are done interacting with one device but want to keep others running, or to restart a wedged transport. On iOS / Android / TV it deliberately leaves this device's native-devtools, accessibility, profiler and debugger services running - to drain those as well, use stop-all-simulator-servers with \`devices\`. On CHROMIUM that does not hold: the JS-runtime debugger declares the CDP session as a dependency, so stopping the transport cascades to it and its captured console history goes with it - reconnect with debugger-connect afterwards. Returns { stopped, udid }. Fails silently if no session is open for the given id.`,
|
|
147241
|
-
zodSchema:
|
|
147817
|
+
zodSchema: zodSchema63,
|
|
147242
147818
|
services: () => ({}),
|
|
147243
147819
|
async execute(_services, params) {
|
|
147244
147820
|
const udid = params.udid;
|
|
@@ -147269,9 +147845,9 @@ function createStopSimulatorServerTool(registry2) {
|
|
|
147269
147845
|
init_zod();
|
|
147270
147846
|
init_src2();
|
|
147271
147847
|
init_external_devices();
|
|
147272
|
-
var
|
|
147848
|
+
var zodSchema64 = external_exports.object({
|
|
147273
147849
|
devices: external_exports.array(external_exports.string()).optional().describe(
|
|
147274
|
-
"Device ids (iOS UDID / Android serial / Chromium id) to scope the teardown to
|
|
147850
|
+
"Device ids (iOS UDID / Android serial / Chromium id) to scope the teardown to. Pass the devices THIS session actually used. Omit only for a deliberate machine-wide cleanup: one tool-server serves every agent using this argent install, so an unscoped stop also kills devices another agent is mid-session on."
|
|
147275
147851
|
)
|
|
147276
147852
|
}).strict();
|
|
147277
147853
|
function createStopAllSimulatorServersTool(registry2) {
|
|
@@ -147305,10 +147881,10 @@ function createStopAllSimulatorServersTool(registry2) {
|
|
|
147305
147881
|
failedMsg: ({ failureSignal: failureSignal2 }) => `Failed to stop simulator servers: ${failureSignal2.error_code}`
|
|
147306
147882
|
},
|
|
147307
147883
|
description: `Stop the services a device owns - simulator-server processes (iOS + Android), native devtools, the iOS accessibility service, TV-control daemons, Chromium CDP sessions, screen recordings, native profiler sessions, and JS-runtime debugger sessions along with the network inspectors and React profiler sessions that ride on them - freeing their spawned processes, sockets and ports. Call this when your session ends or the user says they are done.
|
|
147308
|
-
PASS \`devices\` with the device ids this session used
|
|
147884
|
+
PASS \`devices\` with the device ids this session used: one tool-server serves every agent, subagent and CLI call using this argent install, and an unscoped call tears down THEIR devices too (a mid-recording devtools teardown degrades another agent's flow to brittle coordinate taps; that agent is warned, but its recorded steps are already the worse kind). Omit \`devices\` only when a machine-wide cleanup is what you actually want. Passing an EMPTY array scopes to nothing and stops nothing - it is not a way to ask for the machine-wide sweep.
|
|
147309
147885
|
A JS-runtime debugger session is keyed by the id you called \`debugger-connect\` with. On a Metro serving two or more devices that id is not a udid or serial - connect refuses those and tells you to re-target with the \`logicalDeviceId\` it returns - so a scope built from \`list-devices\` ids cannot reach that session. Pass any such \`logicalDeviceId\` in \`devices\` ALONGSIDE the device id; { left_running } names the ones you missed.
|
|
147310
|
-
Returns { stopped } - the URNs of the services that were actually live and got shut down; an ERROR node is disposed too but never appears there, so an empty \`stopped\` only means nothing was still running. { unmatched } lists supplied ids that own no service here, so a mistyped id - or a device NAME passed where an id was expected - does not read as a clean machine. It is NOT proof the id is wrong: a Vega device is driven through CLI/adb shell-outs, so one you only booted and drove with the remote registers no service and always lands here
|
|
147311
|
-
zodSchema:
|
|
147886
|
+
Returns { stopped } - the URNs of the services that were actually live and got shut down; an ERROR node is disposed too but never appears there, so an empty \`stopped\` only means nothing was still running. { unmatched } lists supplied ids that own no service here, so a mistyped id - or a device NAME passed where an id was expected - does not read as a clean machine. It is NOT proof the id is wrong: a Vega device is driven through CLI/adb shell-outs, so one you only booted and drove with the remote registers no service and always lands here, as does a real device of any platform this session never started anything on. Present ONLY when \`devices\` was supplied AND at least one id matched nothing - absent on an unscoped call and when every id matched. Stopping the same device twice does not report it unmatched: ownership counts regardless of service state. { left_running } lists the URNs of live debugger sessions (and the network inspectors / React profiler sessions riding on them) whose id no device scope can name - re-call with the id after each URN's \`<namespace>:<port>:\` prefix to reap them. { aborted: true } means the caller cancelled the request part-way, so the rest of the machine was left untouched and neither of the other two fields was computed. Past the schema - which rejects an unknown key outright, so the \`udids\` slip is an error rather than a silent machine-wide sweep - the call always succeeds; reaping nothing is a result, not a failure.`,
|
|
147887
|
+
zodSchema: zodSchema64,
|
|
147312
147888
|
services: () => ({}),
|
|
147313
147889
|
async execute(_services, params, ctx) {
|
|
147314
147890
|
const devices = params.devices;
|
|
@@ -147388,7 +147964,7 @@ function listeningPids(port) {
|
|
|
147388
147964
|
if (!output) return [];
|
|
147389
147965
|
return output.split("\n").map((s) => parseInt(s.trim(), 10)).filter((n) => !Number.isNaN(n));
|
|
147390
147966
|
}
|
|
147391
|
-
var
|
|
147967
|
+
var zodSchema65 = external_exports.object({
|
|
147392
147968
|
port: external_exports.number().int().min(1).max(65535).default(8081).describe("TCP port Metro is listening on (default 8081)")
|
|
147393
147969
|
});
|
|
147394
147970
|
var stopMetroTool = {
|
|
@@ -147398,8 +147974,8 @@ var stopMetroTool = {
|
|
|
147398
147974
|
completedMsg: ({ params }) => `Stopped Metro on port ${params.port}`,
|
|
147399
147975
|
failedMsg: ({ params, failureSignal: failureSignal2 }) => `Failed to stop Metro on port ${params.port}: ${failureSignal2.error_code}`
|
|
147400
147976
|
},
|
|
147401
|
-
description: `Stop the Metro bundler process listening on a given port (default 8081). Use when ending a React Native session or when Metro must be restarted. Returns { stopped, port, pids }; stopped=false if no process is found on the port. Fails if the port lookup command times out or the process cannot be killed. This is DESTRUCTIVE
|
|
147402
|
-
zodSchema:
|
|
147977
|
+
description: `Stop the Metro bundler process listening on a given port (default 8081). Use when ending a React Native session or when Metro must be restarted. Returns { stopped, port, pids }; stopped=false if no process is found on the port. Fails if the port lookup command times out or the process cannot be killed. This is DESTRUCTIVE: always ask the user for confirmation before calling this tool.`,
|
|
147978
|
+
zodSchema: zodSchema65,
|
|
147403
147979
|
services: () => ({}),
|
|
147404
147980
|
async execute(_services, params) {
|
|
147405
147981
|
const port = params.port;
|
|
@@ -149743,15 +150319,15 @@ async function appendStepToFlow(session, step) {
|
|
|
149743
150319
|
}
|
|
149744
150320
|
|
|
149745
150321
|
// ../tool-server/src/tools/flows/flow-start-recording.ts
|
|
149746
|
-
var
|
|
150322
|
+
var zodSchema66 = external_exports.object({
|
|
149747
150323
|
name: external_exports.string().describe(
|
|
149748
|
-
'Name for this flow (e.g. "settings-explore")
|
|
150324
|
+
'Name for this flow (e.g. "settings-explore"): letters, digits, underscore and hyphen only.'
|
|
149749
150325
|
),
|
|
149750
150326
|
project_root: external_exports.string().describe(
|
|
149751
150327
|
"Absolute path to the project root directory (the directory that contains or should contain `.argent/flows/`). The flow file is created at `<project_root>/.argent/flows/<name>.yaml`."
|
|
149752
150328
|
),
|
|
149753
150329
|
executionPrerequisite: external_exports.string().optional().describe(
|
|
149754
|
-
'Fragments only: the app/device state assumed on entry (e.g. "Settings app open on General page"). For a self-contained e2e flow, omit this and record a `restart-app` as the first step instead
|
|
150330
|
+
'Fragments only: the app/device state assumed on entry (e.g. "Settings app open on General page"). For a self-contained e2e flow, omit this and record a `restart-app` as the first step instead; it is captured as the flow\'s `launch` step. restart-app has no chromium support, so a chromium flow records as a fragment; add the `launch: { chromium: <app path> }` line to the YAML afterward, deleting the executionPrerequisite line if you passed one, since a flow that starts with a launch must not declare it.'
|
|
149755
150331
|
)
|
|
149756
150332
|
});
|
|
149757
150333
|
var fileInputs2 = [
|
|
@@ -149775,19 +150351,19 @@ Use when you want to capture a reusable sequence of device interactions for late
|
|
|
149775
150351
|
Returns { message, flowFile, savedTo } and optionally { restarted, discardedSteps } if a live recording of the same flow was discarded.
|
|
149776
150352
|
Without a link, it creates that file and fails if the .argent/flows/ directory cannot be created or the file cannot be written. Over a link (argent link or ARGENT_TOOLS_URL, also to 127.0.0.1), your client writes the file, and \`savedTo\` is its path on your computer, or null when that write failed.
|
|
149777
150353
|
|
|
149778
|
-
Several flows can be recorded at once
|
|
149779
|
-
that every subsequent recording tool repeats
|
|
150354
|
+
Several flows can be recorded at once, each keyed by the \`name\` + \`project_root\`
|
|
150355
|
+
that every subsequent recording tool repeats, and one recording's steps never
|
|
149780
150356
|
land in another's file. Steps still run LIVE, so give each concurrent recording
|
|
149781
150357
|
its own device and pick a name unique to your task.
|
|
149782
150358
|
|
|
149783
|
-
After starting, use flow-add-step to append tool calls
|
|
150359
|
+
After starting, use flow-add-step to append tool calls. Each step is executed
|
|
149784
150360
|
LIVE so you can verify it works before it gets recorded. Read each step's
|
|
149785
150361
|
\`message\`: an await-ui-element whose condition never held is still recorded (it
|
|
149786
150362
|
returns success:false rather than failing), and a check that passes live can
|
|
149787
150363
|
still fail once polished into an \`await:\`/\`assert:\` directive, which resolves
|
|
149788
150364
|
against a different tree. flow-add-step warns about both when you record the
|
|
149789
150365
|
wait DIRECTLY. A wait nested inside a recorded run-sequence gets neither warning
|
|
149790
|
-
|
|
150366
|
+
(that tool reports its own shape), so for those, read \`toolResult\`. For a self-contained
|
|
149791
150367
|
e2e flow, record a restart-app of the app under test as the FIRST step (captured
|
|
149792
150368
|
as the flow's \`launch\` step); for a reusable fragment, skip that and pass
|
|
149793
150369
|
executionPrerequisite instead. Use flow-add-echo to add labels, and
|
|
@@ -149800,7 +150376,7 @@ recording. Over a link, the next recorded step writes over your edit.
|
|
|
149800
150376
|
Without a link, the recorder reads the file again before each step, but an
|
|
149801
150377
|
edit that renumbers the steps drops the warnings that flow-finish-recording
|
|
149802
150378
|
reports for those steps.`,
|
|
149803
|
-
zodSchema:
|
|
150379
|
+
zodSchema: zodSchema66,
|
|
149804
150380
|
fileInputs: fileInputs2,
|
|
149805
150381
|
services: () => ({}),
|
|
149806
150382
|
async execute(_services, params, ctx) {
|
|
@@ -152300,10 +152876,10 @@ function stepAnchor(step) {
|
|
|
152300
152876
|
|
|
152301
152877
|
// ../tool-server/src/tools/flows/flow-add-step.ts
|
|
152302
152878
|
init_device_info();
|
|
152303
|
-
var
|
|
152304
|
-
name: external_exports.string().describe("Name of the flow being recorded
|
|
152879
|
+
var zodSchema67 = external_exports.object({
|
|
152880
|
+
name: external_exports.string().describe("Name of the flow being recorded: the one passed to flow-start-recording."),
|
|
152305
152881
|
project_root: external_exports.string().describe(
|
|
152306
|
-
"Absolute path to the project root of the flow being recorded
|
|
152882
|
+
"Absolute path to the project root of the flow being recorded: the same value passed to flow-start-recording. Together with `name` it identifies which recording this step belongs to."
|
|
152307
152883
|
),
|
|
152308
152884
|
command: external_exports.string().describe(
|
|
152309
152885
|
'MCP tool to execute and record, for example "gesture-tap". Do not pass a flow directive or a recording tool. Call flow-add-script directly for a requested script step.'
|
|
@@ -152759,7 +153335,7 @@ Returns { message, stepCount, recorded, savedTo }; \`recorded\`, not the status,
|
|
|
152759
153335
|
// more times — and every retry re-runs the action and appends another step,
|
|
152760
153336
|
// because an aborted request still appends its first.
|
|
152761
153337
|
longRunning: true,
|
|
152762
|
-
zodSchema:
|
|
153338
|
+
zodSchema: zodSchema67,
|
|
152763
153339
|
fileInputs: fileInputs3,
|
|
152764
153340
|
services: () => ({}),
|
|
152765
153341
|
async execute(_services, params, ctx) {
|
|
@@ -152948,10 +153524,10 @@ Returns { message, stepCount, recorded, savedTo }; \`recorded\`, not the status,
|
|
|
152948
153524
|
|
|
152949
153525
|
// ../tool-server/src/tools/flows/flow-insert-echo.ts
|
|
152950
153526
|
init_zod();
|
|
152951
|
-
var
|
|
152952
|
-
name: external_exports.string().describe("Name of the flow being recorded
|
|
153527
|
+
var zodSchema68 = external_exports.object({
|
|
153528
|
+
name: external_exports.string().describe("Name of the flow being recorded: the one passed to flow-start-recording."),
|
|
152953
153529
|
project_root: external_exports.string().describe(
|
|
152954
|
-
"Absolute path to the project root of the flow being recorded
|
|
153530
|
+
"Absolute path to the project root of the flow being recorded: the same value passed to flow-start-recording. Together with `name` it identifies which recording this echo belongs to."
|
|
152955
153531
|
),
|
|
152956
153532
|
message: external_exports.string().describe("Message to echo when the flow is replayed")
|
|
152957
153533
|
});
|
|
@@ -152963,10 +153539,10 @@ var flowInsertEchoTool = {
|
|
|
152963
153539
|
completedMsg: ({ params }) => `Added note to flow ${params.name}`,
|
|
152964
153540
|
failedMsg: ({ params, failureSignal: failureSignal2 }) => `Failed to add note to flow ${params.name}: ${failureSignal2.error_code}`
|
|
152965
153541
|
},
|
|
152966
|
-
description: `Record an echo step in the flow named by \`name\` + \`project_root\`. Echo steps print a message when the flow is replayed
|
|
153542
|
+
description: `Record an echo step in the flow named by \`name\` + \`project_root\`. Echo steps print a message when the flow is replayed, useful as labels between tool calls.
|
|
152967
153543
|
Use when you want to annotate a recorded flow with a human-readable label or checkpoint message.
|
|
152968
153544
|
Returns { message, stepCount, savedTo }. Fails if that flow has no recording in progress.`,
|
|
152969
|
-
zodSchema:
|
|
153545
|
+
zodSchema: zodSchema68,
|
|
152970
153546
|
services: () => ({}),
|
|
152971
153547
|
async execute(_services, params) {
|
|
152972
153548
|
const session = await requireRecordingSession(params.project_root, params.name);
|
|
@@ -154269,7 +154845,7 @@ function errMsg3(err) {
|
|
|
154269
154845
|
|
|
154270
154846
|
// ../tool-server/src/tools/flows/flow-add-script.ts
|
|
154271
154847
|
var OUTPUT_RENDER_LIMIT_BYTES = 64 * 1024;
|
|
154272
|
-
var
|
|
154848
|
+
var zodSchema69 = external_exports.object({
|
|
154273
154849
|
name: external_exports.string().describe("Flow name passed to flow-start-recording."),
|
|
154274
154850
|
project_root: external_exports.string().describe("Absolute project root passed to flow-start-recording."),
|
|
154275
154851
|
path: external_exports.string().describe(
|
|
@@ -154326,7 +154902,7 @@ var flowAddScriptTool = {
|
|
|
154326
154902
|
// The flag only skips the adapter's own abort timer; its retry loop is
|
|
154327
154903
|
// untouched, so a call that fails some other way is still re-POSTed.
|
|
154328
154904
|
longRunning: true,
|
|
154329
|
-
zodSchema:
|
|
154905
|
+
zodSchema: zodSchema69,
|
|
154330
154906
|
services: () => ({}),
|
|
154331
154907
|
async execute(_services, params, ctx) {
|
|
154332
154908
|
const session = await requireRecordingSession(params.project_root, params.name);
|
|
@@ -154416,10 +154992,10 @@ var flowAddScriptTool = {
|
|
|
154416
154992
|
// ../tool-server/src/tools/flows/flow-finish-recording.ts
|
|
154417
154993
|
init_zod();
|
|
154418
154994
|
var fs60 = __toESM(require("node:fs/promises"));
|
|
154419
|
-
var
|
|
154420
|
-
name: external_exports.string().describe("Name of the flow being recorded
|
|
154995
|
+
var zodSchema70 = external_exports.object({
|
|
154996
|
+
name: external_exports.string().describe("Name of the flow being recorded: the one passed to flow-start-recording."),
|
|
154421
154997
|
project_root: external_exports.string().describe(
|
|
154422
|
-
"Absolute path to the project root of the flow being recorded
|
|
154998
|
+
"Absolute path to the project root of the flow being recorded: the same value passed to flow-start-recording. Together with `name` it identifies which recording to finish."
|
|
154423
154999
|
)
|
|
154424
155000
|
});
|
|
154425
155001
|
function attachStepWarnings(summary, warnings) {
|
|
@@ -154475,7 +155051,7 @@ var flowFinishRecordingTool = {
|
|
|
154475
155051
|
description: `Finish recording the flow named by \`name\` + \`project_root\`, leaving recordings under any other key untouched. Returns { message, path, executionPrerequisite, steps, summary, flowFile, savedTo } - a summary of all recorded steps plus the final YAML. Use when you have added all desired steps and want to finalize the flow file. Fails if that flow has no recording in progress.
|
|
154476
155052
|
A warning flow-add-step raised on a recorded \`await-ui-element\` is repeated in \`summary\` as a \`warning:\` line of its own, right below the step it judges, and \`message\` counts them by kind. A warning is repeated only while the step it judges is still identifiable by its number: hand-editing the .yaml during the recording moves the steps, so those warnings are DROPPED rather than pinned on whichever step inherited the number, and \`message\` says how many were dropped. A step that carries a cross-tree warning was re-probed against the runner's tree: read it before converting that wait to \`await:\`/\`assert:\`, which is what the verdict is about and what this moment is for. A step that recorded a wait which did not pass was never probed at all, and its own warning names the CAUSE, because only one of them judges the condition: an unmet wait was read and found false, and it stops the run at replay; a wait whose tree source could not be read, or one that was cancelled, observed nothing and leaves the condition UNKNOWN rather than known-bad. Read those before replaying.
|
|
154477
155053
|
You can still edit the .yaml file directly afterwards to remove or reorder steps.`,
|
|
154478
|
-
zodSchema:
|
|
155054
|
+
zodSchema: zodSchema70,
|
|
154479
155055
|
services: () => ({}),
|
|
154480
155056
|
async execute(_services, params) {
|
|
154481
155057
|
const { filePath, flowFile, savedTo, flow, summary, headline } = await withFlowFileLock(
|
|
@@ -156953,24 +157529,24 @@ async function restoreStatusBar(device) {
|
|
|
156953
157529
|
}
|
|
156954
157530
|
|
|
156955
157531
|
// ../tool-server/src/tools/flows/flow-run.ts
|
|
156956
|
-
var
|
|
157532
|
+
var zodSchema71 = external_exports.object({
|
|
156957
157533
|
name: external_exports.string().optional().describe(
|
|
156958
157534
|
'Name of a saved flow to run from `.argent/flows` (e.g. "settings-explore"). Omit when flow_path is set.'
|
|
156959
157535
|
),
|
|
156960
157536
|
project_root: external_exports.string().describe(
|
|
156961
|
-
"Absolute path to the calling agent's project root
|
|
157537
|
+
"Absolute path to the calling agent's project root: the cwd it is working in. With name, the saved flow is read from `.argent/flows/<name>.yaml` under this root; with flow_path, the flow, its run: siblings, its script: paths and baselines all resolve beside the YAML instead, so pass the agent's cwd. A script still RUNS in this root whichever source was used."
|
|
156962
157538
|
),
|
|
156963
157539
|
flow_file: external_exports.string().optional().describe(
|
|
156964
|
-
"Path to the flow .yaml as readable by the tool-server. Internal
|
|
157540
|
+
"Path to the flow .yaml as readable by the tool-server. Internal: the argent client derives it from project_root and name automatically; leave unset."
|
|
156965
157541
|
),
|
|
156966
157542
|
flow_path: external_exports.string().optional().describe(
|
|
156967
157543
|
"Omit when name is set. Absolute path to a flow .yaml on the client. Over a link (argent link or ARGENT_TOOLS_URL), the argent client uploads the file, its run: fragments and the snapshot baselines of each run, and the tool-server runs those copies. Keep run: fragments under project_root or beside the flow file. With updateBaselines, the client writes the new baselines when the run ends. The client also uploads each absolute .png or .yaml path that a tool: step takes as a file argument, when the file is under project_root or beside the flow file. A tool: flow-execute step that names a flow with name and an absolute project_root without a .. segment runs: the client also uploads that flow and its own files. Over a link, the uploaded flows must not have: script: steps; tool: steps that run a flow another way or record a flow; tool: steps that take a directory, an app or an output directory; tool: steps whose tool builds a file path from several arguments; tool: steps that name a relative path or a file other than .png or .yaml. Without a link, the tool-server reads the files in place and all step kinds run."
|
|
156968
157544
|
),
|
|
156969
157545
|
device: external_exports.string().optional().describe(
|
|
156970
|
-
"Device id to run against (iOS UDID, Android/Vega serial, Chromium id)
|
|
157546
|
+
"Device id to run against (iOS UDID, Android/Vega serial, Chromium id), as list-devices reports it. Auto-detected when omitted, but only when exactly one booted device matches (optionally narrowed by `platform`); with several booted the run fails and lists them, so pass this explicitly whenever more than one device is up."
|
|
156971
157547
|
),
|
|
156972
157548
|
platform: external_exports.enum(SELECTABLE_PLATFORMS).optional().describe(
|
|
156973
|
-
"Restrict auto-detection to this platform when several devices are booted. `ios` selects local simulators only
|
|
157549
|
+
"Restrict auto-detection to this platform when several devices are booted. `ios` selects local simulators only; pass `ios-remote` to select a remote one. `chromium` does more than filter: with no `device` it SELECTS the self-boot branch for an e2e flow - the runner boots an Electron instance from the `launch` step's chromium value and tears it down after the run (a single-key `launch: { chromium: \u2026 }` map selects it on its own, without this parameter). When it selects that branch it never falls back to device auto-detection (a fragment, or an e2e launch map with no `chromium` key, still does), and the launch value must be a real Electron app path on the tool-server host: a bare-string `launch:` - what the recorder writes - holds an installed-app bundle id, so passing `chromium` for one fails the whole run with `Electron boot: path does not exist`. Edit the launch to `{ chromium: <app path> }` first."
|
|
156974
157550
|
),
|
|
156975
157551
|
updateBaselines: external_exports.boolean().optional().describe(
|
|
156976
157552
|
"Write/refresh screenshot baselines for `snapshot` steps instead of diffing against them, also in the flows that tool: flow-execute steps run, unless such a step sets updateBaselines itself."
|
|
@@ -157460,7 +158036,7 @@ one-off interaction use the gesture tools instead, and to author a flow use flow
|
|
|
157460
158036
|
exactly one flow source: name (under project_root) or flow_path.
|
|
157461
158037
|
Returns a per-step report: the first failure stops the run and the rest report as skipped.`,
|
|
157462
158038
|
longRunning: true,
|
|
157463
|
-
zodSchema:
|
|
158039
|
+
zodSchema: zodSchema71,
|
|
157464
158040
|
fileInputs: fileInputs4,
|
|
157465
158041
|
services: () => ({}),
|
|
157466
158042
|
async execute(_services, params, ctx) {
|
|
@@ -158437,15 +159013,15 @@ async function resolveFlowSource(params, fileInput, flowPathInput) {
|
|
|
158437
159013
|
// ../tool-server/src/tools/flows/flow-read-prerequisite.ts
|
|
158438
159014
|
init_zod();
|
|
158439
159015
|
var fs64 = __toESM(require("node:fs/promises"));
|
|
158440
|
-
var
|
|
159016
|
+
var zodSchema72 = external_exports.object({
|
|
158441
159017
|
name: external_exports.string().optional().describe(
|
|
158442
159018
|
'Name of a saved flow to inspect from `.argent/flows` (e.g. "settings-explore"). Omit when flow_path is set.'
|
|
158443
159019
|
),
|
|
158444
159020
|
project_root: external_exports.string().describe(
|
|
158445
|
-
"Absolute path to the calling agent's project root
|
|
159021
|
+
"Absolute path to the calling agent's project root: the cwd it is working in. With name, the saved flow is read from `.argent/flows/<name>.yaml` under this root; with flow_path, the prerequisite is read from that YAML instead, so pass the agent's cwd."
|
|
158446
159022
|
),
|
|
158447
159023
|
flow_file: external_exports.string().optional().describe(
|
|
158448
|
-
"Path to the flow .yaml as readable by the tool-server. Internal
|
|
159024
|
+
"Path to the flow .yaml as readable by the tool-server. Internal: the argent client derives it from project_root and name automatically; leave unset."
|
|
158449
159025
|
),
|
|
158450
159026
|
flow_path: external_exports.string().optional().describe(
|
|
158451
159027
|
"Omit when name is set. Absolute path to a flow .yaml on the client. Over a link (argent link or ARGENT_TOOLS_URL), the argent client uploads the file and the tool-server reads the uploaded copy; without a link, the tool-server reads the file in place. Pass the path through the argent client; a raw path that the file-input boundary did not verify is rejected. Pass the same flow source here as to flow-execute, so the prerequisite you read belongs to the flow that will run."
|
|
@@ -158483,7 +159059,7 @@ var flowReadPrerequisiteTool = {
|
|
|
158483
159059
|
completedMsg: () => "Read flow prerequisite",
|
|
158484
159060
|
failedMsg: ({ failureSignal: failureSignal2 }) => `Failed to read flow prerequisite: ${failureSignal2.error_code}`
|
|
158485
159061
|
},
|
|
158486
|
-
description: `Read the execution prerequisite of a flow without running it
|
|
159062
|
+
description: `Read the execution prerequisite of a flow without running it: a saved flow from the .argent/flows/ directory, or an explicit boundary-managed flow_path.
|
|
158487
159063
|
Returns { flow, executionPrerequisite }: the logical name, plus the precondition its author recorded
|
|
158488
159064
|
verbatim. Empty when none was declared, which is always so for a self-contained scenario: one opening
|
|
158489
159065
|
on a launch may declare no prerequisite, because it builds its own start state.
|
|
@@ -158493,7 +159069,7 @@ Touches no device: nothing is launched, tapped, dispatched or torn down, and no
|
|
|
158493
159069
|
needs booting, so calling this costs nothing but a file read.
|
|
158494
159070
|
Fails if the flow file does not exist.
|
|
158495
159071
|
Address the flow exactly as you will address it in flow-execute: name or flow_path, one and only one; supplying both or neither is rejected. The name goes in \`name\`, which resolves <project_root>/.argent/flows/<name>.yaml.`,
|
|
158496
|
-
zodSchema:
|
|
159072
|
+
zodSchema: zodSchema72,
|
|
158497
159073
|
fileInputs: fileInputs5,
|
|
158498
159074
|
services: () => ({}),
|
|
158499
159075
|
async execute(_services, params, ctx) {
|
|
@@ -158809,7 +159385,7 @@ async function readWorkspaceSnapshot(workspacePath) {
|
|
|
158809
159385
|
}
|
|
158810
159386
|
|
|
158811
159387
|
// ../tool-server/src/tools/workspace/gather-workspace-data.ts
|
|
158812
|
-
var
|
|
159388
|
+
var zodSchema73 = external_exports.object({
|
|
158813
159389
|
workspacePath: external_exports.string().describe("Absolute path to the project root directory to inspect (e.g. /Users/dev/MyApp)")
|
|
158814
159390
|
});
|
|
158815
159391
|
var fileInputs6 = [
|
|
@@ -158840,7 +159416,7 @@ exploration of anything the snapshot surfaces.
|
|
|
158840
159416
|
Use when you need to inspect project configuration without manually reading multiple files.
|
|
158841
159417
|
Returns partial data if workspacePath does not exist or is not readable; missing items are represented as null or empty collections.
|
|
158842
159418
|
Fails if the workspacePath is not an absolute path or the directory cannot be accessed.`,
|
|
158843
|
-
zodSchema:
|
|
159419
|
+
zodSchema: zodSchema73,
|
|
158844
159420
|
fileInputs: fileInputs6,
|
|
158845
159421
|
services: () => ({}),
|
|
158846
159422
|
async execute(_services, params) {
|
|
@@ -158914,9 +159490,9 @@ function targetFlagsFor(target) {
|
|
|
158914
159490
|
if (target === "both") return ["--global", "--local"];
|
|
158915
159491
|
return [`--${target}`];
|
|
158916
159492
|
}
|
|
158917
|
-
var
|
|
159493
|
+
var zodSchema74 = external_exports.object({
|
|
158918
159494
|
target: external_exports.enum(["auto", "global", "local", "both"]).optional().describe(
|
|
158919
|
-
"Which install to update. 'auto' (default) updates the install serving this session
|
|
159495
|
+
"Which install to update. 'auto' (default) updates the install serving this session: the global PATH install or this project's local devDependency, whichever this server runs from. Pass 'global' / 'local' to force one, or 'both' when the user has both and wants each updated."
|
|
158920
159496
|
)
|
|
158921
159497
|
});
|
|
158922
159498
|
var updateScheduled = false;
|
|
@@ -158928,7 +159504,7 @@ var updateArgentTool = {
|
|
|
158928
159504
|
failedMsg: ({ failureSignal: failureSignal2 }) => `Failed to update Argent: ${failureSignal2.error_code}`
|
|
158929
159505
|
},
|
|
158930
159506
|
description: "Apply a pending Argent update. Only call this tool when the user has explicitly consented to updating Argent in this conversation. Use when an update notification indicates a new version is available and the user agrees to update. By default updates the install serving this session; pass `target` to choose global/local/both. Returns { message } with the update status and version info. The tool server will restart automatically after the update. Fails if no update is available or an update is already in progress.",
|
|
158931
|
-
zodSchema:
|
|
159507
|
+
zodSchema: zodSchema74,
|
|
158932
159508
|
services: () => ({}),
|
|
158933
159509
|
async execute(_services, params, _options) {
|
|
158934
159510
|
const { updateAvailable, updateInstallable, currentVersion, installableVersion } = getUpdateState();
|
|
@@ -159013,7 +159589,7 @@ var updateArgentTool = {
|
|
|
159013
159589
|
|
|
159014
159590
|
// ../tool-server/src/tools/system/dismiss-update.ts
|
|
159015
159591
|
init_zod();
|
|
159016
|
-
var
|
|
159592
|
+
var zodSchema75 = external_exports.object({
|
|
159017
159593
|
hours: external_exports.number().min(0).describe("Number of hours to suppress the update notification")
|
|
159018
159594
|
});
|
|
159019
159595
|
var dismissUpdateTool = {
|
|
@@ -159024,7 +159600,7 @@ var dismissUpdateTool = {
|
|
|
159024
159600
|
failedMsg: ({ failureSignal: failureSignal2 }) => `Failed to dismiss Argent update: ${failureSignal2.error_code}`
|
|
159025
159601
|
},
|
|
159026
159602
|
description: "Clear the Argent update notification for the given number of hours. Use when the user asks to postpone or silence update reminders. Returns { message } confirming the suppression duration. Fails if the hours value is negative or the suppression state cannot be persisted.",
|
|
159027
|
-
zodSchema:
|
|
159603
|
+
zodSchema: zodSchema75,
|
|
159028
159604
|
services: () => ({}),
|
|
159029
159605
|
async execute(_services, params, _options) {
|
|
159030
159606
|
const durationMs = params.hours * 60 * 60 * 1e3;
|
|
@@ -159043,7 +159619,7 @@ var import_path8 = __toESM(require("path"));
|
|
|
159043
159619
|
init_zod();
|
|
159044
159620
|
init_src2();
|
|
159045
159621
|
init_device_info();
|
|
159046
|
-
var
|
|
159622
|
+
var zodSchema76 = external_exports.object({
|
|
159047
159623
|
baselinePath: external_exports.string().min(1).optional().describe("Path to the baseline PNG file. Required unless captureBaseline is true."),
|
|
159048
159624
|
currentPath: external_exports.string().min(1).optional().describe("Path to the current PNG file. Required unless captureCurrent is true."),
|
|
159049
159625
|
udid: external_exports.string().min(1).describe("Target device id from `list-devices` (iOS UDID or Android serial)."),
|
|
@@ -159057,10 +159633,10 @@ var zodSchema74 = external_exports.object({
|
|
|
159057
159633
|
"Orientation override for live baseline/current captures. Ignored on physical iPhones."
|
|
159058
159634
|
),
|
|
159059
159635
|
outputDir: external_exports.string().min(1).optional().describe(
|
|
159060
|
-
"Directory where diff artifacts should be written. Optional
|
|
159636
|
+
"Directory where diff artifacts should be written. Optional: defaults to a temp directory; the diff images are returned in the result either way."
|
|
159061
159637
|
)
|
|
159062
159638
|
}).strict();
|
|
159063
|
-
var
|
|
159639
|
+
var capability35 = {
|
|
159064
159640
|
apple: { simulator: true, device: true },
|
|
159065
159641
|
android: { emulator: true, device: true, unknown: true }
|
|
159066
159642
|
};
|
|
@@ -159085,8 +159661,8 @@ Returns { summary, diffPath, contextDiffPath }. The summary uses normalized [0,1
|
|
|
159085
159661
|
Ignores the fixed top status-bar band for both pixel and OCR text comparisons.
|
|
159086
159662
|
Fails if the input sources are invalid, PNG files cannot be read, outputDir cannot be written, or the simulator-server / emulator backend is not reachable.`,
|
|
159087
159663
|
searchHint: "compare screenshots png diff visual UI changes UI regression visual regression screenshot diff changed regions text ocr live capture",
|
|
159088
|
-
zodSchema:
|
|
159089
|
-
capability:
|
|
159664
|
+
zodSchema: zodSchema76,
|
|
159665
|
+
capability: capability35,
|
|
159090
159666
|
fileInputs: fileInputs7,
|
|
159091
159667
|
services: (params) => {
|
|
159092
159668
|
if (params.captureBaseline || params.captureCurrent) {
|
|
@@ -159399,12 +159975,12 @@ async function captureElementFrame(registry2, udid, match, opts = {}) {
|
|
|
159399
159975
|
}
|
|
159400
159976
|
|
|
159401
159977
|
// ../tool-server/src/tools/variants/propose-variant.ts
|
|
159402
|
-
var
|
|
159978
|
+
var zodSchema77 = external_exports.object({
|
|
159403
159979
|
element: external_exports.string().min(1).max(200).describe(
|
|
159404
159980
|
'Human name of the on-screen element this variant targets, e.g. "Foo button" or "profile header". Repeated calls with the same element accumulate multiple variants on it. Used as the default screen matcher when `match` is omitted.'
|
|
159405
159981
|
),
|
|
159406
159982
|
udid: external_exports.string().min(1).max(200).optional().describe(
|
|
159407
|
-
"Device id (iOS udid / Android serial) the variants were captured on. The preview window streams THIS device directly
|
|
159983
|
+
"Device id (iOS udid / Android serial) the variants were captured on. The preview window streams THIS device directly; pass the same udid you screenshotted/described with, so the human never has to pick a simulator. Set it on the first propose_variant of a round; later calls may omit it (the last non-empty value wins)."
|
|
159408
159984
|
),
|
|
159409
159985
|
match: external_exports.object({
|
|
159410
159986
|
by: external_exports.enum(["text", "label", "identifier", "role"]).describe(
|
|
@@ -159428,7 +160004,7 @@ var zodSchema75 = external_exports.object({
|
|
|
159428
160004
|
width: external_exports.number(),
|
|
159429
160005
|
height: external_exports.number()
|
|
159430
160006
|
}).optional().describe(
|
|
159431
|
-
"Normalized [0..1] bounds (fractions of screen width/height) of the target element AS IT APPEARS IN THIS VARIANT
|
|
160007
|
+
"Normalized [0..1] bounds (fractions of screen width/height) of the target element AS IT APPEARS IN THIS VARIANT. Read the matched node's `frame` from `describe` AFTER applying this variant. The preview window crops the screenshot to these bounds, so each variant shows its own re-laid-out element instead of every variant sharing one stale frame. The element moves/resizes between variants, so capture it per variant. Omit if unknown."
|
|
159432
160008
|
)
|
|
159433
160009
|
}).describe("The variant being proposed for `element`.")
|
|
159434
160010
|
});
|
|
@@ -159446,20 +160022,20 @@ function createProposeVariantTool(registry2) {
|
|
|
159446
160022
|
Use when you have produced multiple alternative designs for an element and want the human to pick.
|
|
159447
160023
|
Call this once per variant: e.g. propose_variant("Foo", v1), propose_variant("Foo", v2),
|
|
159448
160024
|
propose_variant("Bar", v1)\u2026 Variants accumulate per element and across elements. The agent is NOT
|
|
159449
|
-
blocked
|
|
160025
|
+
blocked: keep proposing and keep working. Each element appears live in the Argent Lens window (a
|
|
159450
160026
|
native window that opens automatically) as a floating card beside the streamed simulator, with a thin
|
|
159451
160027
|
line connecting it to the matched on-screen element; you don't open or display anything yourself. Pass
|
|
159452
160028
|
variant.previewImage (e.g. a screenshot path) to show how each variant looks.
|
|
159453
160029
|
|
|
159454
|
-
When you have proposed every variant for every element, you are done staging
|
|
160030
|
+
When you have proposed every variant for every element, you are done staging. The human reviews them
|
|
159455
160031
|
in the Argent Lens window and sends back their picks and comments. If an \`await_user_selection\` tool
|
|
159456
160032
|
is available, call it once to block until they submit; otherwise just end your turn and their feedback
|
|
159457
160033
|
arrives as a follow-up message (this is the case in an \`argent lens\` CLI session).
|
|
159458
160034
|
|
|
159459
|
-
Returns { round, elementId, variantId, element, variantCount, totalElements }
|
|
160035
|
+
Returns { round, elementId, variantId, element, variantCount, totalElements }: confirmation only;
|
|
159460
160036
|
it does not wait for the user.`,
|
|
159461
160037
|
searchHint: "propose design variant alternative option for element non-blocking ab choice",
|
|
159462
|
-
zodSchema:
|
|
160038
|
+
zodSchema: zodSchema77,
|
|
159463
160039
|
services: () => ({}),
|
|
159464
160040
|
async execute(_services, params) {
|
|
159465
160041
|
let frame = params.variant.frame;
|
|
@@ -159483,9 +160059,9 @@ it does not wait for the user.`,
|
|
|
159483
160059
|
|
|
159484
160060
|
// ../tool-server/src/tools/variants/await-user-selection.ts
|
|
159485
160061
|
init_zod();
|
|
159486
|
-
var
|
|
160062
|
+
var zodSchema78 = external_exports.object({
|
|
159487
160063
|
timeoutSeconds: external_exports.number().int().min(5).max(86400).optional().describe(
|
|
159488
|
-
"Max seconds to block this call before returning a re-awaitable { status: 'pending' } result (default 1800). The user's proposals stay live across timeouts
|
|
160064
|
+
"Max seconds to block this call before returning a re-awaitable { status: 'pending' } result (default 1800). The user's proposals stay live across timeouts; on 'pending' just call await_user_selection again. Lower this if your MCP client enforces a short request timeout."
|
|
159489
160065
|
)
|
|
159490
160066
|
});
|
|
159491
160067
|
var awaitUserSelectionTool = {
|
|
@@ -159510,21 +160086,21 @@ that opens automatically on the user's screen), then returns their choices and a
|
|
|
159510
160086
|
Returns one of:
|
|
159511
160087
|
\u2022 { status: "completed", round, selections: [{ element, chosenVariant, comment? }], unselected,
|
|
159512
160088
|
annotations: [{ target, match, comment }], globalComment, morePending? }
|
|
159513
|
-
|
|
160089
|
+
The user finished this round; apply chosenVariant for each element (skip ones in
|
|
159514
160090
|
\`unselected\`). \`annotations\` are free-form comments the user pinned to specific on-screen
|
|
159515
|
-
elements via the inspector
|
|
160091
|
+
elements via the inspector; treat each as a change request for that element.
|
|
159516
160092
|
If \`morePending\` is true, another already-decided round or a freshly-staged round is
|
|
159517
|
-
still waiting
|
|
160093
|
+
still waiting. Call await_user_selection AGAIN (repeat until you get a completed result
|
|
159518
160094
|
without \`morePending\`, a \`pending\`, or \`no_proposals\`); do not stop on this result alone.
|
|
159519
|
-
\u2022 { status: "pending", message, proposedElements }
|
|
160095
|
+
\u2022 { status: "pending", message, proposedElements }: timeoutSeconds elapsed with no submission.
|
|
159520
160096
|
Expected, not an error: the proposals are still live; call await_user_selection AGAIN.
|
|
159521
|
-
\u2022 { status: "no_proposals" }
|
|
160097
|
+
\u2022 { status: "no_proposals" }: you called this before propose_variant.
|
|
159522
160098
|
|
|
159523
160099
|
This tool is long-running; it intentionally holds the request open. It honors client
|
|
159524
160100
|
disconnects (aborts cleanly).`,
|
|
159525
160101
|
searchHint: "await wait user selection choice variant blocking confirm picks complete",
|
|
159526
160102
|
longRunning: true,
|
|
159527
|
-
zodSchema:
|
|
160103
|
+
zodSchema: zodSchema78,
|
|
159528
160104
|
services: () => ({}),
|
|
159529
160105
|
async execute(_services, params, options) {
|
|
159530
160106
|
const timeoutMs = (params.timeoutSeconds ?? 1800) * 1e3;
|
|
@@ -159539,7 +160115,7 @@ disconnects (aborts cleanly).`,
|
|
|
159539
160115
|
init_zod();
|
|
159540
160116
|
init_src2();
|
|
159541
160117
|
init_device_info();
|
|
159542
|
-
var
|
|
160118
|
+
var zodSchema79 = external_exports.object({
|
|
159543
160119
|
udid: external_exports.string().describe("Chromium device id from `list-devices` (e.g. `chromium-cdp-9222`)."),
|
|
159544
160120
|
action: external_exports.enum(["list", "select", "new", "close"]).describe(
|
|
159545
160121
|
"list: enumerate tabs/windows. select: make a tab active (every other tool then acts on it). new: open a tab. close: close a tab."
|
|
@@ -159572,7 +160148,7 @@ var tabAction = {
|
|
|
159572
160148
|
failure: "close"
|
|
159573
160149
|
}
|
|
159574
160150
|
};
|
|
159575
|
-
var
|
|
160151
|
+
var capability36 = {
|
|
159576
160152
|
chromium: { app: true }
|
|
159577
160153
|
};
|
|
159578
160154
|
var chromiumTabsTool = {
|
|
@@ -159590,8 +160166,8 @@ var chromiumTabsTool = {
|
|
|
159590
160166
|
Use when an app exposes multiple windows or tabs and you need to inspect or drive one other than the current page, or to open/close a page during a flow. tabIds are stable for the session and never reused.
|
|
159591
160167
|
Returns { tabs: [{ tabId, targetId, title, url, active, label? }] }. Fails if the device is not a Chromium (CDP) device, or the requested tabId/label no longer matches a live tab. Chromium-only.`,
|
|
159592
160168
|
searchHint: "tab tabs window windows switch select close new open multi-tab chromium electron",
|
|
159593
|
-
zodSchema:
|
|
159594
|
-
capability:
|
|
160169
|
+
zodSchema: zodSchema79,
|
|
160170
|
+
capability: capability36,
|
|
159595
160171
|
services: (params) => {
|
|
159596
160172
|
const device = resolveDevice(params.udid);
|
|
159597
160173
|
if (device.platform === "chromium") {
|
|
@@ -159692,7 +160268,7 @@ async function clearStorage(cdp, type) {
|
|
|
159692
160268
|
}
|
|
159693
160269
|
|
|
159694
160270
|
// ../tool-server/src/tools/chromium-cookies/index.ts
|
|
159695
|
-
var
|
|
160271
|
+
var zodSchema80 = external_exports.object({
|
|
159696
160272
|
udid: external_exports.string().describe("Chromium device id from `list-devices` (e.g. `chromium-cdp-9222`)."),
|
|
159697
160273
|
action: external_exports.enum(["get", "set", "delete", "clear"]).describe(
|
|
159698
160274
|
"get: read cookies. set: create/update a cookie. delete: remove a named cookie. clear: remove all browser cookies."
|
|
@@ -159715,7 +160291,7 @@ var cookieAction = {
|
|
|
159715
160291
|
delete: { started: "Deleting", completed: "Deleted", failure: "delete" },
|
|
159716
160292
|
clear: { started: "Clearing", completed: "Cleared", failure: "clear" }
|
|
159717
160293
|
};
|
|
159718
|
-
var
|
|
160294
|
+
var capability37 = {
|
|
159719
160295
|
chromium: { app: true }
|
|
159720
160296
|
};
|
|
159721
160297
|
var chromiumCookiesTool = {
|
|
@@ -159733,8 +160309,8 @@ var chromiumCookiesTool = {
|
|
|
159733
160309
|
Use when seeding an authenticated session before a flow (set the session cookie, then navigate) or asserting cookie state after one.
|
|
159734
160310
|
Returns { cookies, count } for get, or a small status object ({ set } / { deleted } / { cleared }) otherwise. Fails if the device is not a Chromium (CDP) device, or set is missing name/value. Chromium-only.`,
|
|
159735
160311
|
searchHint: "cookies cookie get set delete clear httponly samesite session auth chromium",
|
|
159736
|
-
zodSchema:
|
|
159737
|
-
capability:
|
|
160312
|
+
zodSchema: zodSchema80,
|
|
160313
|
+
capability: capability37,
|
|
159738
160314
|
services: (params) => {
|
|
159739
160315
|
const device = resolveDevice(params.udid);
|
|
159740
160316
|
if (device.platform === "chromium") {
|
|
@@ -159799,7 +160375,7 @@ Returns { cookies, count } for get, or a small status object ({ set } / { delete
|
|
|
159799
160375
|
init_zod();
|
|
159800
160376
|
init_src2();
|
|
159801
160377
|
init_device_info();
|
|
159802
|
-
var
|
|
160378
|
+
var zodSchema81 = external_exports.object({
|
|
159803
160379
|
udid: external_exports.string().describe("Chromium device id from `list-devices` (e.g. `chromium-cdp-9222`)."),
|
|
159804
160380
|
store: external_exports.enum(["local", "session"]).describe("Which Web Storage area: `local` (localStorage) or `session` (sessionStorage)."),
|
|
159805
160381
|
action: external_exports.enum(["get", "set", "remove", "clear"]).describe(
|
|
@@ -159814,7 +160390,7 @@ var storageAction = {
|
|
|
159814
160390
|
remove: { started: "Removing from", completed: "Removed from", failure: "remove from" },
|
|
159815
160391
|
clear: { started: "Clearing", completed: "Cleared", failure: "clear" }
|
|
159816
160392
|
};
|
|
159817
|
-
var
|
|
160393
|
+
var capability38 = {
|
|
159818
160394
|
chromium: { app: true }
|
|
159819
160395
|
};
|
|
159820
160396
|
var chromiumStorageTool = {
|
|
@@ -159833,8 +160409,8 @@ Set \`store\` to "local" or "session". Storage is per-origin, so it reflects the
|
|
|
159833
160409
|
Use when seeding feature flags / auth tokens before a flow or asserting persisted app state after one.
|
|
159834
160410
|
Returns { value } for a single key, { entries, count } for all, or a status object ({ set } / { removed } / { cleared }) otherwise. Fails if the device is not a Chromium (CDP) device, or set is missing key/value. Chromium-only.`,
|
|
159835
160411
|
searchHint: "storage localstorage sessionstorage local session get set remove clear key value chromium",
|
|
159836
|
-
zodSchema:
|
|
159837
|
-
capability:
|
|
160412
|
+
zodSchema: zodSchema81,
|
|
160413
|
+
capability: capability38,
|
|
159838
160414
|
services: (params) => {
|
|
159839
160415
|
const device = resolveDevice(params.udid);
|
|
159840
160416
|
if (device.platform === "chromium") {
|
|
@@ -159946,6 +160522,8 @@ function createRegistry() {
|
|
|
159946
160522
|
registry2.registerTool(networkRequestTool);
|
|
159947
160523
|
registry2.registerTool(createDescribeTool(registry2));
|
|
159948
160524
|
registry2.registerTool(createUiTreeTool(registry2));
|
|
160525
|
+
registry2.registerTool(createForegroundAppTool(registry2));
|
|
160526
|
+
registry2.registerTool(createFillTool(registry2));
|
|
159949
160527
|
registry2.registerTool(createAwaitUiElementTool(registry2));
|
|
159950
160528
|
registry2.registerTool(createAwaitScreenIdleTool(registry2));
|
|
159951
160529
|
registry2.registerTool(createReactProfilerStartTool(registry2));
|