@swmansion/argent 0.21.1-next.16 → 0.21.1-next.18
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/bin/darwin/simulator-server +0 -0
- package/bin/linux/simulator-server +0 -0
- package/bin/linux-arm64/simulator-server +0 -0
- package/bin/win32/simulator-server.exe +0 -0
- package/dist/cli-cmds.mjs +3 -1
- package/dist/installer.mjs +3 -1
- package/dist/mcp-server.mjs +4 -0
- package/dist/tool-server.cjs +274 -72
- package/package.json +1 -1
- package/skills/argent-device-interact/SKILL.md +35 -22
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/dist/cli-cmds.mjs
CHANGED
|
@@ -2309,6 +2309,8 @@ var FAILURE_CODES = {
|
|
|
2309
2309
|
IOS_SETTINGS_PERMISSION_FAILED: "IOS_SETTINGS_PERMISSION_FAILED",
|
|
2310
2310
|
IOS_SHAKE_FAILED: "IOS_SHAKE_FAILED",
|
|
2311
2311
|
ANDROID_SHAKE_FAILED: "ANDROID_SHAKE_FAILED",
|
|
2312
|
+
PASTE_CLIPBOARD_SET_FAILED: "PASTE_CLIPBOARD_SET_FAILED",
|
|
2313
|
+
PASTE_CLIPBOARD_UNSUPPORTED: "PASTE_CLIPBOARD_UNSUPPORTED",
|
|
2312
2314
|
SETTINGS_PERMISSION_UNSUPPORTED: "SETTINGS_PERMISSION_UNSUPPORTED",
|
|
2313
2315
|
NATIVE_DEVTOOLS_DESCRIBE_ERROR: "NATIVE_DEVTOOLS_DESCRIBE_ERROR",
|
|
2314
2316
|
NATIVE_DEVTOOLS_VIEW_AT_POINT_ERROR: "NATIVE_DEVTOOLS_VIEW_AT_POINT_ERROR",
|
|
@@ -7214,7 +7216,7 @@ var _CI_VENDOR_COUNT_FOR_TEST = vendors_default.length;
|
|
|
7214
7216
|
var SESSION_ID2 = randomUUID5();
|
|
7215
7217
|
function readCliVersion() {
|
|
7216
7218
|
if (true) {
|
|
7217
|
-
return "0.21.1-next.
|
|
7219
|
+
return "0.21.1-next.18";
|
|
7218
7220
|
}
|
|
7219
7221
|
return "0.0.0";
|
|
7220
7222
|
}
|
package/dist/installer.mjs
CHANGED
|
@@ -15468,6 +15468,8 @@ var FAILURE_CODES = {
|
|
|
15468
15468
|
IOS_SETTINGS_PERMISSION_FAILED: "IOS_SETTINGS_PERMISSION_FAILED",
|
|
15469
15469
|
IOS_SHAKE_FAILED: "IOS_SHAKE_FAILED",
|
|
15470
15470
|
ANDROID_SHAKE_FAILED: "ANDROID_SHAKE_FAILED",
|
|
15471
|
+
PASTE_CLIPBOARD_SET_FAILED: "PASTE_CLIPBOARD_SET_FAILED",
|
|
15472
|
+
PASTE_CLIPBOARD_UNSUPPORTED: "PASTE_CLIPBOARD_UNSUPPORTED",
|
|
15471
15473
|
SETTINGS_PERMISSION_UNSUPPORTED: "SETTINGS_PERMISSION_UNSUPPORTED",
|
|
15472
15474
|
NATIVE_DEVTOOLS_DESCRIBE_ERROR: "NATIVE_DEVTOOLS_DESCRIBE_ERROR",
|
|
15473
15475
|
NATIVE_DEVTOOLS_VIEW_AT_POINT_ERROR: "NATIVE_DEVTOOLS_VIEW_AT_POINT_ERROR",
|
|
@@ -16434,7 +16436,7 @@ var _CI_VENDOR_COUNT_FOR_TEST = vendors_default.length;
|
|
|
16434
16436
|
var SESSION_ID = randomUUID4();
|
|
16435
16437
|
function readCliVersion() {
|
|
16436
16438
|
if (true) {
|
|
16437
|
-
return "0.21.1-next.
|
|
16439
|
+
return "0.21.1-next.18";
|
|
16438
16440
|
}
|
|
16439
16441
|
return "0.0.0";
|
|
16440
16442
|
}
|
package/dist/mcp-server.mjs
CHANGED
|
@@ -16493,6 +16493,8 @@ var FAILURE_CODES = {
|
|
|
16493
16493
|
IOS_SETTINGS_PERMISSION_FAILED: "IOS_SETTINGS_PERMISSION_FAILED",
|
|
16494
16494
|
IOS_SHAKE_FAILED: "IOS_SHAKE_FAILED",
|
|
16495
16495
|
ANDROID_SHAKE_FAILED: "ANDROID_SHAKE_FAILED",
|
|
16496
|
+
PASTE_CLIPBOARD_SET_FAILED: "PASTE_CLIPBOARD_SET_FAILED",
|
|
16497
|
+
PASTE_CLIPBOARD_UNSUPPORTED: "PASTE_CLIPBOARD_UNSUPPORTED",
|
|
16496
16498
|
SETTINGS_PERMISSION_UNSUPPORTED: "SETTINGS_PERMISSION_UNSUPPORTED",
|
|
16497
16499
|
NATIVE_DEVTOOLS_DESCRIBE_ERROR: "NATIVE_DEVTOOLS_DESCRIBE_ERROR",
|
|
16498
16500
|
NATIVE_DEVTOOLS_VIEW_AT_POINT_ERROR: "NATIVE_DEVTOOLS_VIEW_AT_POINT_ERROR",
|
|
@@ -18491,6 +18493,7 @@ var AUTO_SCREENSHOT_TOOLS = /* @__PURE__ */ new Set([
|
|
|
18491
18493
|
"gesture-rotate",
|
|
18492
18494
|
"button",
|
|
18493
18495
|
"keyboard",
|
|
18496
|
+
"paste",
|
|
18494
18497
|
"rotate",
|
|
18495
18498
|
"launch-app",
|
|
18496
18499
|
"restart-app",
|
|
@@ -18513,6 +18516,7 @@ var AUTO_SCREENSHOT_DELAY_MS_BY_TOOL = {
|
|
|
18513
18516
|
"button": 1500,
|
|
18514
18517
|
"rotate": 1e3,
|
|
18515
18518
|
"keyboard": 300,
|
|
18519
|
+
"paste": 300,
|
|
18516
18520
|
"describe": 100
|
|
18517
18521
|
};
|
|
18518
18522
|
var DEFAULT_DELAY_MS = 1400;
|
package/dist/tool-server.cjs
CHANGED
|
@@ -610,6 +610,8 @@ var init_failure_codes = __esm({
|
|
|
610
610
|
IOS_SETTINGS_PERMISSION_FAILED: "IOS_SETTINGS_PERMISSION_FAILED",
|
|
611
611
|
IOS_SHAKE_FAILED: "IOS_SHAKE_FAILED",
|
|
612
612
|
ANDROID_SHAKE_FAILED: "ANDROID_SHAKE_FAILED",
|
|
613
|
+
PASTE_CLIPBOARD_SET_FAILED: "PASTE_CLIPBOARD_SET_FAILED",
|
|
614
|
+
PASTE_CLIPBOARD_UNSUPPORTED: "PASTE_CLIPBOARD_UNSUPPORTED",
|
|
613
615
|
SETTINGS_PERMISSION_UNSUPPORTED: "SETTINGS_PERMISSION_UNSUPPORTED",
|
|
614
616
|
NATIVE_DEVTOOLS_DESCRIBE_ERROR: "NATIVE_DEVTOOLS_DESCRIBE_ERROR",
|
|
615
617
|
NATIVE_DEVTOOLS_VIEW_AT_POINT_ERROR: "NATIVE_DEVTOOLS_VIEW_AT_POINT_ERROR",
|
|
@@ -95690,7 +95692,7 @@ var _CI_VENDOR_COUNT_FOR_TEST = vendors_default.length;
|
|
|
95690
95692
|
var SESSION_ID = (0, import_node_crypto3.randomUUID)();
|
|
95691
95693
|
function readCliVersion() {
|
|
95692
95694
|
if (true) {
|
|
95693
|
-
return "0.21.1-next.
|
|
95695
|
+
return "0.21.1-next.18";
|
|
95694
95696
|
}
|
|
95695
95697
|
return "0.0.0";
|
|
95696
95698
|
}
|
|
@@ -98281,23 +98283,23 @@ var InvalidToolInputError = class extends Error {
|
|
|
98281
98283
|
});
|
|
98282
98284
|
}
|
|
98283
98285
|
};
|
|
98284
|
-
function platformMatrix(platform,
|
|
98286
|
+
function platformMatrix(platform, capability34) {
|
|
98285
98287
|
switch (platform) {
|
|
98286
98288
|
case "ios":
|
|
98287
|
-
return
|
|
98289
|
+
return capability34.apple;
|
|
98288
98290
|
case "ios-remote":
|
|
98289
|
-
return
|
|
98291
|
+
return capability34.appleRemote;
|
|
98290
98292
|
case "android":
|
|
98291
|
-
return
|
|
98293
|
+
return capability34.android;
|
|
98292
98294
|
case "chromium":
|
|
98293
|
-
return
|
|
98295
|
+
return capability34.chromium;
|
|
98294
98296
|
case "vega":
|
|
98295
|
-
return
|
|
98297
|
+
return capability34.vega;
|
|
98296
98298
|
}
|
|
98297
98299
|
}
|
|
98298
|
-
function assertSupported(toolId,
|
|
98299
|
-
if (!
|
|
98300
|
-
const matrix = platformMatrix(device.platform,
|
|
98300
|
+
function assertSupported(toolId, capability34, device) {
|
|
98301
|
+
if (!capability34) return;
|
|
98302
|
+
const matrix = platformMatrix(device.platform, capability34);
|
|
98301
98303
|
if (!matrix) {
|
|
98302
98304
|
throw new UnsupportedOperationError(toolId, device, `no ${device.platform} support declared`);
|
|
98303
98305
|
}
|
|
@@ -98305,7 +98307,7 @@ function assertSupported(toolId, capability33, device) {
|
|
|
98305
98307
|
if (!supported) {
|
|
98306
98308
|
throw new UnsupportedOperationError(toolId, device, `kind '${device.kind}' not supported`);
|
|
98307
98309
|
}
|
|
98308
|
-
if (
|
|
98310
|
+
if (capability34.supports && !capability34.supports(device)) {
|
|
98309
98311
|
throw new UnsupportedOperationError(toolId, device, "supports() refiner rejected device");
|
|
98310
98312
|
}
|
|
98311
98313
|
}
|
|
@@ -108130,6 +108132,42 @@ async function pointerPost(api, body, signal) {
|
|
|
108130
108132
|
return false;
|
|
108131
108133
|
}
|
|
108132
108134
|
}
|
|
108135
|
+
async function setSimulatorClipboardText(api, text, signal) {
|
|
108136
|
+
let res;
|
|
108137
|
+
try {
|
|
108138
|
+
res = await fetch(`${api.apiUrl}/api/clipboard/text`, {
|
|
108139
|
+
method: "POST",
|
|
108140
|
+
headers: { "Content-Type": "application/json" },
|
|
108141
|
+
body: JSON.stringify({ text }),
|
|
108142
|
+
signal
|
|
108143
|
+
});
|
|
108144
|
+
} catch (err) {
|
|
108145
|
+
throw toSimulatorNetworkError("Paste", err, api.apiUrl);
|
|
108146
|
+
}
|
|
108147
|
+
if (res.status === 404) {
|
|
108148
|
+
throw new FailureError(
|
|
108149
|
+
"Paste failed: this simulator-server build has no clipboard endpoint. Update argent so its bundled simulator-server includes clipboard support, or type the text with the keyboard tool instead.",
|
|
108150
|
+
{
|
|
108151
|
+
error_code: FAILURE_CODES.PASTE_CLIPBOARD_UNSUPPORTED,
|
|
108152
|
+
failure_stage: "simulator_clipboard_endpoint_missing",
|
|
108153
|
+
failure_area: "tool_server",
|
|
108154
|
+
error_kind: "unsupported"
|
|
108155
|
+
}
|
|
108156
|
+
);
|
|
108157
|
+
}
|
|
108158
|
+
const body = await res.json().catch(() => null);
|
|
108159
|
+
if (!res.ok || body?.status !== "ok") {
|
|
108160
|
+
throw new FailureError(
|
|
108161
|
+
`Paste failed: could not set the device clipboard (${body?.error ?? `HTTP ${res.status}`}).`,
|
|
108162
|
+
{
|
|
108163
|
+
error_code: FAILURE_CODES.PASTE_CLIPBOARD_SET_FAILED,
|
|
108164
|
+
failure_stage: "simulator_clipboard_set",
|
|
108165
|
+
failure_area: "tool_server",
|
|
108166
|
+
error_kind: "unknown"
|
|
108167
|
+
}
|
|
108168
|
+
);
|
|
108169
|
+
}
|
|
108170
|
+
}
|
|
108133
108171
|
async function simulatorPost(toolLabel, api, endpoint, reqBody, signal, fallbackHint) {
|
|
108134
108172
|
let res;
|
|
108135
108173
|
try {
|
|
@@ -108245,10 +108283,6 @@ function routeViaTransport(transport, cmd) {
|
|
|
108245
108283
|
case "rotate":
|
|
108246
108284
|
transport.rotate(cmd.direction);
|
|
108247
108285
|
return;
|
|
108248
|
-
case "paste": {
|
|
108249
|
-
void Promise.resolve(transport.paste(cmd.text));
|
|
108250
|
-
return;
|
|
108251
|
-
}
|
|
108252
108286
|
default:
|
|
108253
108287
|
throw new Error(`MoQ transport does not implement sendCommand cmd '${String(cmd.cmd)}'`);
|
|
108254
108288
|
}
|
|
@@ -122346,13 +122380,176 @@ One call does one action: pass text OR key, never both. To type and then press a
|
|
|
122346
122380
|
};
|
|
122347
122381
|
}
|
|
122348
122382
|
|
|
122383
|
+
// ../tool-server/src/tools/paste/schema.ts
|
|
122384
|
+
init_zod();
|
|
122385
|
+
var pasteZodSchema = external_exports.object({
|
|
122386
|
+
udid: external_exports.string().min(1).describe(
|
|
122387
|
+
"Target device id from `list-devices` (iOS simulator UDID or Android emulator serial)."
|
|
122388
|
+
),
|
|
122389
|
+
text: external_exports.string().min(1).describe(
|
|
122390
|
+
"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 \u2014 the same sources as `keyboard` \u2014 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."
|
|
122391
|
+
)
|
|
122392
|
+
});
|
|
122393
|
+
|
|
122394
|
+
// ../tool-server/src/tools/paste/platforms/ios.ts
|
|
122395
|
+
var LEFT_GUI_KEYCODE = 227;
|
|
122396
|
+
var V_KEYCODE = charToKeyPress("v").keyCode;
|
|
122397
|
+
var CHORD_STEP_MS = 50;
|
|
122398
|
+
var sleep10 = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
122399
|
+
function rejectTv(device) {
|
|
122400
|
+
throw new UnsupportedOperationError(
|
|
122401
|
+
"paste",
|
|
122402
|
+
device,
|
|
122403
|
+
"tvOS has no pasteboard to paste from \u2014 type into the focused field with keyboard instead"
|
|
122404
|
+
);
|
|
122405
|
+
}
|
|
122406
|
+
async function pasteSimulator(api, text) {
|
|
122407
|
+
await setSimulatorClipboardText(api, text);
|
|
122408
|
+
api.pressKey("Down", LEFT_GUI_KEYCODE);
|
|
122409
|
+
await sleep10(CHORD_STEP_MS);
|
|
122410
|
+
api.pressKey("Down", V_KEYCODE);
|
|
122411
|
+
await sleep10(CHORD_STEP_MS);
|
|
122412
|
+
api.pressKey("Up", V_KEYCODE);
|
|
122413
|
+
await sleep10(CHORD_STEP_MS);
|
|
122414
|
+
api.pressKey("Up", LEFT_GUI_KEYCODE);
|
|
122415
|
+
await sleep10(CHORD_STEP_MS);
|
|
122416
|
+
return { pasted: true };
|
|
122417
|
+
}
|
|
122418
|
+
function makeIosImpl4(registry2) {
|
|
122419
|
+
return {
|
|
122420
|
+
// `isTvOsSimulator` shells out to `simctl`; the simulator-server itself is
|
|
122421
|
+
// resolved through the blueprint.
|
|
122422
|
+
requires: ["xcrun"],
|
|
122423
|
+
async handler(_services, params, device) {
|
|
122424
|
+
if (await isTvOsSimulator(device.id)) rejectTv(device);
|
|
122425
|
+
const ref = simulatorServerRef(device);
|
|
122426
|
+
const api = await registry2.resolveService(ref.urn, ref.options);
|
|
122427
|
+
return pasteSimulator(api, params.text);
|
|
122428
|
+
}
|
|
122429
|
+
};
|
|
122430
|
+
}
|
|
122431
|
+
function makeIosRemoteImpl2(registry2) {
|
|
122432
|
+
return {
|
|
122433
|
+
requires: ["sim-remote"],
|
|
122434
|
+
async handler(_services, params, device) {
|
|
122435
|
+
if (await isRemoteTvOsSimulator(device.id)) rejectTv(device);
|
|
122436
|
+
const ref = simulatorServerRef(device);
|
|
122437
|
+
const api = await registry2.resolveService(ref.urn, ref.options);
|
|
122438
|
+
if (!api.transport) {
|
|
122439
|
+
throw new Error(
|
|
122440
|
+
`Tool 'paste' resolved an ios-remote simulator-server without a transport for ${device.id}.`
|
|
122441
|
+
);
|
|
122442
|
+
}
|
|
122443
|
+
await api.transport.paste(params.text);
|
|
122444
|
+
return { pasted: true };
|
|
122445
|
+
}
|
|
122446
|
+
};
|
|
122447
|
+
}
|
|
122448
|
+
|
|
122449
|
+
// ../tool-server/src/tools/paste/platforms/android.ts
|
|
122450
|
+
init_adb();
|
|
122451
|
+
var KEYCODE_PASTE = 279;
|
|
122452
|
+
function makeAndroidImpl2(registry2) {
|
|
122453
|
+
return {
|
|
122454
|
+
requires: ["adb"],
|
|
122455
|
+
async handler(_services, params, device) {
|
|
122456
|
+
if (await isAndroidTv(device.id)) {
|
|
122457
|
+
throw new UnsupportedOperationError(
|
|
122458
|
+
"paste",
|
|
122459
|
+
device,
|
|
122460
|
+
"Android TV is focus-driven \u2014 type into the focused field with keyboard instead"
|
|
122461
|
+
);
|
|
122462
|
+
}
|
|
122463
|
+
const ref = simulatorServerRef(device);
|
|
122464
|
+
const api = await registry2.resolveService(ref.urn, ref.options);
|
|
122465
|
+
await setSimulatorClipboardText(api, params.text);
|
|
122466
|
+
await injectAndroidKeycode(device.id, KEYCODE_PASTE);
|
|
122467
|
+
return { pasted: true };
|
|
122468
|
+
}
|
|
122469
|
+
};
|
|
122470
|
+
}
|
|
122471
|
+
|
|
122472
|
+
// ../tool-server/src/tools/paste/index.ts
|
|
122473
|
+
var capability17 = {
|
|
122474
|
+
// Simulators only. A physical iPhone's pasteboard is reachable through the
|
|
122475
|
+
// same simulator-server endpoint, but the paste keystroke is not verified
|
|
122476
|
+
// over the CoreDevice HID path, so `device` stays off until it is.
|
|
122477
|
+
apple: { simulator: true },
|
|
122478
|
+
// A remote simulator pastes through the MoQ transport's existing paste
|
|
122479
|
+
// primitive (device pasteboard + ⌘V on the remote host).
|
|
122480
|
+
appleRemote: { simulator: true },
|
|
122481
|
+
// Emulators only: the clipboard is set through the emulator's gRPC
|
|
122482
|
+
// endpoint, which a physical phone does not have. `unknown` is admitted
|
|
122483
|
+
// because an unresolved serial may still be an emulator — the
|
|
122484
|
+
// simulator-server refuses a phone either way.
|
|
122485
|
+
android: { emulator: true, unknown: true }
|
|
122486
|
+
// No `chromium`: the renderer can only reach the HOST clipboard, so a paste
|
|
122487
|
+
// there would overwrite whatever the user has copied. No `vega`: no
|
|
122488
|
+
// clipboard API is exposed by the VVD tooling.
|
|
122489
|
+
//
|
|
122490
|
+
// TV targets are not separate platforms (an Apple TV simulator is
|
|
122491
|
+
// `ios`/`simulator`, an Android TV emulator `android`/`emulator`), so each
|
|
122492
|
+
// handler probes the runtime kind and rejects a TV itself.
|
|
122493
|
+
};
|
|
122494
|
+
var pasteQueues = /* @__PURE__ */ new Map();
|
|
122495
|
+
function serializedPerDevice(deviceId, task) {
|
|
122496
|
+
const previous = pasteQueues.get(deviceId) ?? Promise.resolve();
|
|
122497
|
+
const next = previous.then(task, task);
|
|
122498
|
+
pasteQueues.set(deviceId, next);
|
|
122499
|
+
void next.then(
|
|
122500
|
+
() => {
|
|
122501
|
+
if (pasteQueues.get(deviceId) === next) pasteQueues.delete(deviceId);
|
|
122502
|
+
},
|
|
122503
|
+
() => {
|
|
122504
|
+
if (pasteQueues.get(deviceId) === next) pasteQueues.delete(deviceId);
|
|
122505
|
+
}
|
|
122506
|
+
);
|
|
122507
|
+
return next;
|
|
122508
|
+
}
|
|
122509
|
+
function createPasteTool(registry2) {
|
|
122510
|
+
const dispatch = dispatchByPlatform({
|
|
122511
|
+
toolId: "paste",
|
|
122512
|
+
capability: capability17,
|
|
122513
|
+
ios: makeIosImpl4(registry2),
|
|
122514
|
+
iosRemote: makeIosRemoteImpl2(registry2),
|
|
122515
|
+
android: makeAndroidImpl2(registry2)
|
|
122516
|
+
});
|
|
122517
|
+
return {
|
|
122518
|
+
id: "paste",
|
|
122519
|
+
interaction: {
|
|
122520
|
+
startedMsg: () => "Pasting text",
|
|
122521
|
+
completedMsg: () => "Pasted text",
|
|
122522
|
+
failedMsg: ({ failureSignal: failureSignal2 }) => `Failed to paste text: ${failureSignal2.error_code}`
|
|
122523
|
+
},
|
|
122524
|
+
description: `Paste text into the focused field: puts \`text\` on the DEVICE clipboard (the host clipboard is untouched), then triggers the platform's paste shortcut (iOS simulator, Android emulator).
|
|
122525
|
+
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 \u2014 a 2FA/OTP code copied from another app, a long link or token, or when testing the app's own paste handling.
|
|
122526
|
+
Tap the field first so it has focus. Returns { pasted: true }. Fails on a TV target, when the device clipboard cannot be set, or when the simulator-server build lacks clipboard support.
|
|
122527
|
+
Supports \`{{secret:<NAME>}}\` placeholders like \`keyboard\`; the value is never echoed back.`,
|
|
122528
|
+
searchHint: "paste clipboard pasteboard otp 2fa code fill field",
|
|
122529
|
+
zodSchema: pasteZodSchema,
|
|
122530
|
+
capability: capability17,
|
|
122531
|
+
services: () => ({}),
|
|
122532
|
+
execute: async (services, params, options) => {
|
|
122533
|
+
const { text, secrets } = resolveSecretPlaceholders(params.text);
|
|
122534
|
+
return serializedPerDevice(params.udid, async () => {
|
|
122535
|
+
if (secrets.length === 0) return dispatch(services, params, options);
|
|
122536
|
+
try {
|
|
122537
|
+
return await dispatch(services, { ...params, text }, options);
|
|
122538
|
+
} catch (err) {
|
|
122539
|
+
throw redactSecretsFromError(err, secrets);
|
|
122540
|
+
}
|
|
122541
|
+
});
|
|
122542
|
+
}
|
|
122543
|
+
};
|
|
122544
|
+
}
|
|
122545
|
+
|
|
122349
122546
|
// ../tool-server/src/tools/rotate/index.ts
|
|
122350
122547
|
init_zod();
|
|
122351
122548
|
var zodSchema25 = external_exports.object({
|
|
122352
122549
|
udid: external_exports.string().describe("Target device id from `list-devices` (iOS UDID or Android serial)."),
|
|
122353
122550
|
orientation: external_exports.enum(["Portrait", "LandscapeLeft", "LandscapeRight", "PortraitUpsideDown"]).describe("Target orientation")
|
|
122354
122551
|
});
|
|
122355
|
-
var
|
|
122552
|
+
var capability18 = {
|
|
122356
122553
|
apple: { simulator: true, device: true },
|
|
122357
122554
|
appleRemote: { simulator: true },
|
|
122358
122555
|
android: { emulator: true, device: true, unknown: true }
|
|
@@ -122368,7 +122565,7 @@ var rotateTool = {
|
|
|
122368
122565
|
Use to test layout in a different orientation. Re-run \`describe\` afterwards \u2014 frame coordinates change with the orientation.
|
|
122369
122566
|
Returns { orientation }. Fails if the target device is not booted.`,
|
|
122370
122567
|
zodSchema: zodSchema25,
|
|
122371
|
-
capability:
|
|
122568
|
+
capability: capability18,
|
|
122372
122569
|
services: (params) => ({
|
|
122373
122570
|
simulatorServer: simulatorServerRef(resolveDevice(params.udid))
|
|
122374
122571
|
}),
|
|
@@ -122599,9 +122796,9 @@ async function prepareHostWindowShake(target) {
|
|
|
122599
122796
|
var execFileAsync20 = (0, import_node_util20.promisify)(import_node_child_process27.execFile);
|
|
122600
122797
|
var SHAKE_NOTIFICATION = "com.apple.UIKit.SimulatorShake";
|
|
122601
122798
|
var SHAKE_INTERVAL_MS = 400;
|
|
122602
|
-
var
|
|
122799
|
+
var sleep11 = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
122603
122800
|
var NOTIFYUTIL_ARGV = ["notifyutil", "-p", SHAKE_NOTIFICATION];
|
|
122604
|
-
function
|
|
122801
|
+
function rejectTv2(toolId, device) {
|
|
122605
122802
|
throw new UnsupportedOperationError(
|
|
122606
122803
|
toolId,
|
|
122607
122804
|
device,
|
|
@@ -122630,11 +122827,11 @@ var iosImpl4 = {
|
|
|
122630
122827
|
async handler(_services, params, device) {
|
|
122631
122828
|
const { udid } = params;
|
|
122632
122829
|
const count2 = params.count ?? 1;
|
|
122633
|
-
if (await isTvOsSimulator(udid))
|
|
122830
|
+
if (await isTvOsSimulator(udid)) rejectTv2("shake", device);
|
|
122634
122831
|
const args = await simctlArgsForUdid(udid, ["spawn", udid, ...NOTIFYUTIL_ARGV]);
|
|
122635
122832
|
const shaker = await prepareHostWindowShake({ kind: "ios", udid, name: device.name });
|
|
122636
122833
|
for (let i = 0; i < count2; i++) {
|
|
122637
|
-
if (i > 0) await
|
|
122834
|
+
if (i > 0) await sleep11(SHAKE_INTERVAL_MS);
|
|
122638
122835
|
shaker.begin();
|
|
122639
122836
|
try {
|
|
122640
122837
|
await execFileAsync20("xcrun", args, { timeout: 15e3 });
|
|
@@ -122652,9 +122849,9 @@ var iosRemoteImpl6 = {
|
|
|
122652
122849
|
async handler(_services, params, device) {
|
|
122653
122850
|
const { udid } = params;
|
|
122654
122851
|
const count2 = params.count ?? 1;
|
|
122655
|
-
if (await isRemoteTvOsSimulator(udid))
|
|
122852
|
+
if (await isRemoteTvOsSimulator(udid)) rejectTv2("shake", device);
|
|
122656
122853
|
for (let i = 0; i < count2; i++) {
|
|
122657
|
-
if (i > 0) await
|
|
122854
|
+
if (i > 0) await sleep11(SHAKE_INTERVAL_MS);
|
|
122658
122855
|
let result;
|
|
122659
122856
|
try {
|
|
122660
122857
|
result = await simctlSpawn(udid, { args: NOTIFYUTIL_ARGV });
|
|
@@ -122701,7 +122898,7 @@ function restingVectorFrom(stdout) {
|
|
|
122701
122898
|
return read;
|
|
122702
122899
|
}
|
|
122703
122900
|
var fmt = (v) => `${v.x.toFixed(4)}:${v.y.toFixed(4)}:${v.z.toFixed(4)}`;
|
|
122704
|
-
var
|
|
122901
|
+
var sleep12 = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
122705
122902
|
async function emuConsole(serial, args) {
|
|
122706
122903
|
const { stdout } = await runAdb(["-s", serial, "emu", ...args], { timeoutMs: 1e4 });
|
|
122707
122904
|
const lines = stdout.split("\n").map((line) => line.trim()).filter(Boolean);
|
|
@@ -122775,7 +122972,7 @@ var androidImpl6 = {
|
|
|
122775
122972
|
y: rest.y,
|
|
122776
122973
|
z: rest.z
|
|
122777
122974
|
});
|
|
122778
|
-
await
|
|
122975
|
+
await sleep12(SWING_INTERVAL_MS);
|
|
122779
122976
|
}
|
|
122780
122977
|
}
|
|
122781
122978
|
} catch (err) {
|
|
@@ -122800,7 +122997,7 @@ var androidImpl6 = {
|
|
|
122800
122997
|
};
|
|
122801
122998
|
|
|
122802
122999
|
// ../tool-server/src/tools/shake/index.ts
|
|
122803
|
-
var
|
|
123000
|
+
var capability19 = {
|
|
122804
123001
|
// Simulator only. A physical iPhone's motion comes from real hardware; there
|
|
122805
123002
|
// is no host-side hook to fake it, so `device` stays false and a paired phone
|
|
122806
123003
|
// gets a clean 400 instead of a silent no-op.
|
|
@@ -122838,13 +123035,13 @@ Works on local and remote (sim-remote) iOS simulators.
|
|
|
122838
123035
|
Only phone/tablet simulators and emulators are supported.`,
|
|
122839
123036
|
searchHint: "shake motion accelerometer undo typing dev menu gesture",
|
|
122840
123037
|
zodSchema: shakeZodSchema,
|
|
122841
|
-
capability:
|
|
123038
|
+
capability: capability19,
|
|
122842
123039
|
// Talks to `simctl` / `adb` directly, so no simulator-server is resolved —
|
|
122843
123040
|
// avoids spawning one (and its ready-wait) for a tool that never uses it.
|
|
122844
123041
|
services: () => ({}),
|
|
122845
123042
|
execute: dispatchByPlatform({
|
|
122846
123043
|
toolId: "shake",
|
|
122847
|
-
capability:
|
|
123044
|
+
capability: capability19,
|
|
122848
123045
|
ios: iosImpl4,
|
|
122849
123046
|
iosRemote: iosRemoteImpl6,
|
|
122850
123047
|
android: androidImpl6
|
|
@@ -122894,14 +123091,14 @@ var APPLE_TV_UNSUPPORTED = /* @__PURE__ */ new Set([
|
|
|
122894
123091
|
"volumeDown",
|
|
122895
123092
|
"mute"
|
|
122896
123093
|
]);
|
|
122897
|
-
function
|
|
123094
|
+
function makeIosImpl5(registry2) {
|
|
122898
123095
|
return {
|
|
122899
123096
|
handler: (_services, params, device, options) => pressFocusRemote(registry2, device, params, APPLE_TV_UNSUPPORTED, options)
|
|
122900
123097
|
};
|
|
122901
123098
|
}
|
|
122902
123099
|
|
|
122903
123100
|
// ../tool-server/src/tools/tv-remote/platforms/android.ts
|
|
122904
|
-
function
|
|
123101
|
+
function makeAndroidImpl3(registry2) {
|
|
122905
123102
|
return {
|
|
122906
123103
|
requires: ["adb"],
|
|
122907
123104
|
handler: (_services, params, device, options) => pressFocusRemote(registry2, device, params, void 0, options)
|
|
@@ -122947,7 +123144,7 @@ var zodSchema26 = external_exports.object({
|
|
|
122947
123144
|
'Repeat the whole `button` value this many times (default 1). Compact for long same-button runs, e.g. { button: "down", repeat: 12 }.'
|
|
122948
123145
|
)
|
|
122949
123146
|
});
|
|
122950
|
-
var
|
|
123147
|
+
var capability20 = {
|
|
122951
123148
|
apple: { simulator: true, device: true },
|
|
122952
123149
|
android: { emulator: true, device: true, unknown: true },
|
|
122953
123150
|
vega: { vvd: true }
|
|
@@ -122974,13 +123171,13 @@ Returns { pressed, count }.`,
|
|
|
122974
123171
|
longRunning: true,
|
|
122975
123172
|
searchHint: "tv remote dpad d-pad navigate focus up down left right select ok back home menu play pause rewind fast forward sequence path apple tv tvos android tv leanback vega fire tv",
|
|
122976
123173
|
zodSchema: zodSchema26,
|
|
122977
|
-
capability:
|
|
123174
|
+
capability: capability20,
|
|
122978
123175
|
services: () => ({}),
|
|
122979
123176
|
execute: dispatchByPlatform({
|
|
122980
123177
|
toolId: "tv-remote",
|
|
122981
|
-
capability:
|
|
122982
|
-
ios:
|
|
122983
|
-
android:
|
|
123178
|
+
capability: capability20,
|
|
123179
|
+
ios: makeIosImpl5(registry2),
|
|
123180
|
+
android: makeAndroidImpl3(registry2),
|
|
122984
123181
|
vega: vegaImpl5
|
|
122985
123182
|
})
|
|
122986
123183
|
};
|
|
@@ -129152,7 +129349,7 @@ var conditionCompleted = {
|
|
|
129152
129349
|
hidden: "UI element became hidden",
|
|
129153
129350
|
text: "UI element matched expected text"
|
|
129154
129351
|
};
|
|
129155
|
-
var
|
|
129352
|
+
var capability21 = {
|
|
129156
129353
|
apple: { simulator: true, device: true },
|
|
129157
129354
|
android: { emulator: true, device: true, unknown: true },
|
|
129158
129355
|
chromium: { app: true },
|
|
@@ -129244,7 +129441,7 @@ or before tapping an element that appears asynchronously.`,
|
|
|
129244
129441
|
searchHint: "wait await poll until visible hidden exists text appears disappears timeout element condition settle",
|
|
129245
129442
|
longRunning: true,
|
|
129246
129443
|
zodSchema: zodSchema27,
|
|
129247
|
-
capability:
|
|
129444
|
+
capability: capability21,
|
|
129248
129445
|
services: (params) => {
|
|
129249
129446
|
const device = resolveDevice(params.udid);
|
|
129250
129447
|
if (device.platform === "chromium") {
|
|
@@ -129255,7 +129452,7 @@ or before tapping an element that appears asynchronously.`,
|
|
|
129255
129452
|
async execute(services, params, ctx) {
|
|
129256
129453
|
const signal = ctx?.signal;
|
|
129257
129454
|
const device = resolveDevice(params.udid);
|
|
129258
|
-
assertSupported(AWAIT_UI_ELEMENT_TOOL_ID,
|
|
129455
|
+
assertSupported(AWAIT_UI_ELEMENT_TOOL_ID, capability21, device);
|
|
129259
129456
|
if (device.platform === "ios") await ensureDeps(iosRequires);
|
|
129260
129457
|
else if (device.platform === "android") await ensureDeps(androidRequires);
|
|
129261
129458
|
else if (device.platform === "vega") await ensureDeps(vegaRequires);
|
|
@@ -129312,6 +129509,9 @@ var ALLOWED_TOOLS = /* @__PURE__ */ new Set([
|
|
|
129312
129509
|
"gesture-rotate",
|
|
129313
129510
|
"button",
|
|
129314
129511
|
"keyboard",
|
|
129512
|
+
// `paste` belongs in a sequence for the same reason `keyboard` does: the
|
|
129513
|
+
// focus tap, the paste and the submit are one user action.
|
|
129514
|
+
"paste",
|
|
129315
129515
|
"rotate",
|
|
129316
129516
|
// Sequencing matters for shake: the interesting cases are races (shake while
|
|
129317
129517
|
// a sheet is dismissing, shake right after typing), which need the steps
|
|
@@ -129329,7 +129529,7 @@ var zodSchema28 = external_exports.object({
|
|
|
129329
129529
|
steps: external_exports.array(
|
|
129330
129530
|
external_exports.object({
|
|
129331
129531
|
tool: external_exports.string().describe(
|
|
129332
|
-
"Tool name \u2014 one of: gesture-tap, gesture-swipe, gesture-scroll, gesture-drag, gesture-custom, gesture-pinch, gesture-rotate, button, keyboard, rotate, shake, tv-remote, await-ui-element. On a TV target (Apple TV / Android TV / Vega) use tv-remote (remote presses) and keyboard (text)."
|
|
129532
|
+
"Tool name \u2014 one of: gesture-tap, gesture-swipe, gesture-scroll, gesture-drag, gesture-custom, gesture-pinch, gesture-rotate, button, keyboard, paste, rotate, shake, tv-remote, await-ui-element. On a TV target (Apple TV / Android TV / Vega) use tv-remote (remote presses) and keyboard (text)."
|
|
129333
129533
|
),
|
|
129334
129534
|
args: external_exports.record(external_exports.string(), external_exports.unknown()).describe("Tool arguments (excluding udid, which is injected automatically)"),
|
|
129335
129535
|
delayMs: external_exports.number().optional().describe(
|
|
@@ -129338,7 +129538,7 @@ var zodSchema28 = external_exports.object({
|
|
|
129338
129538
|
})
|
|
129339
129539
|
).min(1).describe("Ordered list of interaction steps to execute sequentially")
|
|
129340
129540
|
});
|
|
129341
|
-
var
|
|
129541
|
+
var capability22 = {
|
|
129342
129542
|
apple: { simulator: true, device: true },
|
|
129343
129543
|
appleRemote: { simulator: true },
|
|
129344
129544
|
android: { emulator: true, device: true, unknown: true },
|
|
@@ -129380,6 +129580,7 @@ Allowed tools and their args (udid is auto-injected, do NOT include it in args):
|
|
|
129380
129580
|
button: { button: "home"|"back"|"power"|"volumeUp"|"volumeDown"|"appSwitch"|"actionButton" } [ios/android]
|
|
129381
129581
|
keyboard: { text?: string, key?: string, delayMs?: number } (text OR key per step, never both; TV: text only) [ios/android/chromium/vega/tv]
|
|
129382
129582
|
text supports {{secret:<NAME>}} placeholders, resolved server-side from ARGENT_SECRET_<NAME> env vars or an argent secrets file \u2014 credentials never enter agent context
|
|
129583
|
+
paste: { text: string } (device clipboard + paste shortcut; only where a user would paste, e.g. an OTP \u2014 keyboard otherwise) [ios sim/android emu]
|
|
129383
129584
|
rotate: { orientation: "Portrait"|"LandscapeLeft"|"LandscapeRight"|"PortraitUpsideDown" } [ios/android]
|
|
129384
129585
|
shake: { count?: number } [ios sim/android emu]
|
|
129385
129586
|
tv-remote: { button: <remote button | array of them>, repeat?: number } [apple tv/android tv/vega]
|
|
@@ -129418,7 +129619,7 @@ Stops on the first error (or unmet await-ui-element condition) and returns parti
|
|
|
129418
129619
|
longRunning: true,
|
|
129419
129620
|
searchHint: "batch sequence multiple gesture steps sequentially",
|
|
129420
129621
|
zodSchema: zodSchema28,
|
|
129421
|
-
capability:
|
|
129622
|
+
capability: capability22,
|
|
129422
129623
|
// No eagerly-declared service: each step resolves its own services through
|
|
129423
129624
|
// `invokeSubTool` below (simulator-server for iOS/Android, CDP for
|
|
129424
129625
|
// Chromium), so run-sequence itself needs none. An eager resolver can't be
|
|
@@ -131696,7 +131897,7 @@ function formatDescribeTree(root, opts) {
|
|
|
131696
131897
|
}
|
|
131697
131898
|
|
|
131698
131899
|
// ../tool-server/src/tools/describe/platforms/tv.ts
|
|
131699
|
-
var
|
|
131900
|
+
var sleep13 = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
131700
131901
|
var EMPTY_RETRY_ATTEMPTS = 3;
|
|
131701
131902
|
var EMPTY_RETRY_DELAY_MS = 600;
|
|
131702
131903
|
var EMPTY_HINT = "No focusable elements after retrying and recycling the read path. The app is most likely still launching (splash / loading screen) or mid-transition \u2014 this is normal right after launch-app / restart-app. Wait ~2-3s and call describe again; a React Native app only exposes focus once its JS bundle has loaded. If it stays empty, take a screenshot to confirm what's actually on screen.";
|
|
@@ -131737,7 +131938,7 @@ async function describeTv(registry2, device) {
|
|
|
131737
131938
|
let res = await api.describe();
|
|
131738
131939
|
if (device.platform !== "android") {
|
|
131739
131940
|
for (let attempt = 1; attempt < EMPTY_RETRY_ATTEMPTS && isEmpty(res); attempt++) {
|
|
131740
|
-
await
|
|
131941
|
+
await sleep13(EMPTY_RETRY_DELAY_MS);
|
|
131741
131942
|
res = await api.describe();
|
|
131742
131943
|
}
|
|
131743
131944
|
}
|
|
@@ -131787,7 +131988,7 @@ var zodSchema38 = external_exports.object({
|
|
|
131787
131988
|
"Optional app bundle ID. Used as a target hint on iOS when the AX-service returns no elements and the describe tool falls back to native-devtools inspection. If omitted, the fallback auto-detects the frontmost connected app. Ignored on Android / Chromium."
|
|
131788
131989
|
)
|
|
131789
131990
|
});
|
|
131790
|
-
var
|
|
131991
|
+
var capability23 = {
|
|
131791
131992
|
apple: { simulator: true, device: true },
|
|
131792
131993
|
appleRemote: { simulator: true },
|
|
131793
131994
|
android: { emulator: true, device: true, unknown: true },
|
|
@@ -131797,7 +131998,7 @@ var capability22 = {
|
|
|
131797
131998
|
function makeDescribeExecute(registry2) {
|
|
131798
131999
|
return dispatchByPlatform({
|
|
131799
132000
|
toolId: "describe",
|
|
131800
|
-
capability:
|
|
132001
|
+
capability: capability23,
|
|
131801
132002
|
ios: {
|
|
131802
132003
|
requires: iosRequires,
|
|
131803
132004
|
handler: async (_services, params, device) => (
|
|
@@ -131882,7 +132083,7 @@ back/menu/home), then call describe again to confirm where focus landed.`,
|
|
|
131882
132083
|
alwaysLoad: true,
|
|
131883
132084
|
searchHint: "accessibility element tree ui hierarchy tap coordinates ios android chromium vega dom tv tvos apple tv android tv fire tv focus focusable remote dpad",
|
|
131884
132085
|
zodSchema: zodSchema38,
|
|
131885
|
-
capability:
|
|
132086
|
+
capability: capability23,
|
|
131886
132087
|
services: (params) => {
|
|
131887
132088
|
const device = resolveDevice(params.udid);
|
|
131888
132089
|
if (device.platform === "chromium") {
|
|
@@ -131911,7 +132112,7 @@ var zodSchema39 = external_exports.object({
|
|
|
131911
132112
|
`The screen must hold the same content for at least this long to count as settled (default ${DEFAULT_MIN_STABLE_MS}).`
|
|
131912
132113
|
)
|
|
131913
132114
|
});
|
|
131914
|
-
var
|
|
132115
|
+
var capability24 = {
|
|
131915
132116
|
apple: { simulator: true, device: true },
|
|
131916
132117
|
android: { emulator: true, device: true, unknown: true },
|
|
131917
132118
|
chromium: { app: true }
|
|
@@ -131955,7 +132156,7 @@ still before the timeout. Use after a launch/navigation to wait for the UI to re
|
|
|
131955
132156
|
searchHint: "wait until screen settles idle stable stops changing animation transition rendered ready before screenshot",
|
|
131956
132157
|
longRunning: true,
|
|
131957
132158
|
zodSchema: zodSchema39,
|
|
131958
|
-
capability:
|
|
132159
|
+
capability: capability24,
|
|
131959
132160
|
services: (params) => {
|
|
131960
132161
|
const device = resolveDevice(params.udid);
|
|
131961
132162
|
if (device.platform === "chromium") {
|
|
@@ -131965,7 +132166,7 @@ still before the timeout. Use after a launch/navigation to wait for the UI to re
|
|
|
131965
132166
|
},
|
|
131966
132167
|
async execute(services, params, ctx) {
|
|
131967
132168
|
const device = resolveDevice(params.udid);
|
|
131968
|
-
assertSupported(AWAIT_SCREEN_IDLE_TOOL_ID,
|
|
132169
|
+
assertSupported(AWAIT_SCREEN_IDLE_TOOL_ID, capability24, device);
|
|
131969
132170
|
if (device.platform === "ios") await ensureDeps(iosRequires);
|
|
131970
132171
|
else if (device.platform === "android") await ensureDeps(androidRequires);
|
|
131971
132172
|
const isTvOs = device.platform === "ios" && await isTvOsSimulator(device.id);
|
|
@@ -138728,7 +138929,7 @@ var zodSchema48 = external_exports.object({
|
|
|
138728
138929
|
"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 \u2014 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 \u2014 e.g. exported globally for the normal capture path \u2014 also rejects this flag up front, since that fallback cannot cold-launch; unset it (or set it to device) first. Ignored on Android."
|
|
138729
138930
|
)
|
|
138730
138931
|
});
|
|
138731
|
-
var
|
|
138932
|
+
var capability25 = {
|
|
138732
138933
|
apple: { simulator: true, device: true },
|
|
138733
138934
|
android: { emulator: true, device: true, unknown: true }
|
|
138734
138935
|
};
|
|
@@ -138739,7 +138940,7 @@ var nativeProfilerStartTool = {
|
|
|
138739
138940
|
completedMsg: () => "Started native profiler",
|
|
138740
138941
|
failedMsg: ({ failureSignal: failureSignal2 }) => `Failed to start native profiler: ${failureSignal2.error_code}`
|
|
138741
138942
|
},
|
|
138742
|
-
capability:
|
|
138943
|
+
capability: capability25,
|
|
138743
138944
|
description: `Start native profiling on a booted device. iOS: Instruments via xctrace (CPU, hangs, memory). Android: Perfetto (CPU, jank, RSS-growth weak signal).
|
|
138744
138945
|
Auto-detects the running app process unless app_process is explicitly provided.
|
|
138745
138946
|
After starting, let the user interact with the app, then call native-profiler-stop.
|
|
@@ -138753,7 +138954,7 @@ Fails if no app is running on the device, or the profiler cannot attach to the p
|
|
|
138753
138954
|
async execute(services, params) {
|
|
138754
138955
|
const api = services.session;
|
|
138755
138956
|
const device = resolveDevice(params.device_id);
|
|
138756
|
-
assertSupported("native-profiler-start",
|
|
138957
|
+
assertSupported("native-profiler-start", capability25, device);
|
|
138757
138958
|
if (api.platform === "ios") {
|
|
138758
138959
|
await ensureDeps(["xcrun"]);
|
|
138759
138960
|
return startNativeProfilerIos(api, params);
|
|
@@ -138770,7 +138971,7 @@ var zodSchema49 = external_exports.object({
|
|
|
138770
138971
|
"Target device id from `list-devices` (iOS UDID or Android serial)."
|
|
138771
138972
|
)
|
|
138772
138973
|
});
|
|
138773
|
-
var
|
|
138974
|
+
var capability26 = {
|
|
138774
138975
|
apple: { simulator: true, device: true },
|
|
138775
138976
|
android: { emulator: true, device: true, unknown: true }
|
|
138776
138977
|
};
|
|
@@ -138791,7 +138992,7 @@ var nativeProfilerStopTool = {
|
|
|
138791
138992
|
completedMsg: ({ result }) => `Saved native profile ${result.traceFile.filename}`,
|
|
138792
138993
|
failedMsg: ({ failureSignal: failureSignal2 }) => `Failed to stop native profiler: ${failureSignal2.error_code}`
|
|
138793
138994
|
},
|
|
138794
|
-
capability:
|
|
138995
|
+
capability: capability26,
|
|
138795
138996
|
// Packaging plus the export passes routinely exceed the 30s fetch timeout.
|
|
138796
138997
|
longRunning: true,
|
|
138797
138998
|
description: `Stop native profiling and export trace data.
|
|
@@ -138808,7 +139009,7 @@ Fails if no active native-profiler-start session exists for the given device_id.
|
|
|
138808
139009
|
async execute(services, params, ctx) {
|
|
138809
139010
|
const api = services.session;
|
|
138810
139011
|
const device = resolveDevice(params.device_id);
|
|
138811
|
-
assertSupported("native-profiler-stop",
|
|
139012
|
+
assertSupported("native-profiler-stop", capability26, device);
|
|
138812
139013
|
if (api.platform === "ios") {
|
|
138813
139014
|
await ensureDeps(["xcrun"]);
|
|
138814
139015
|
const ios = await stopNativeProfilerIos(api);
|
|
@@ -138840,7 +139041,7 @@ var zodSchema50 = external_exports.object({
|
|
|
138840
139041
|
"Target device id from `list-devices` (iOS UDID or Android serial)."
|
|
138841
139042
|
)
|
|
138842
139043
|
});
|
|
138843
|
-
var
|
|
139044
|
+
var capability27 = {
|
|
138844
139045
|
apple: { simulator: true, device: true },
|
|
138845
139046
|
android: { emulator: true, device: true, unknown: true }
|
|
138846
139047
|
};
|
|
@@ -138851,7 +139052,7 @@ var nativeProfilerAnalyzeTool = {
|
|
|
138851
139052
|
completedMsg: () => "Analyzed native profile",
|
|
138852
139053
|
failedMsg: ({ failureSignal: failureSignal2 }) => `Failed to analyze native profile: ${failureSignal2.error_code}`
|
|
138853
139054
|
},
|
|
138854
|
-
capability:
|
|
139055
|
+
capability: capability27,
|
|
138855
139056
|
description: `Analyze exported native trace data and return an LLM-optimized markdown report.
|
|
138856
139057
|
iOS: parses CPU time profile, UI hangs, and memory leaks from the exported XML files.
|
|
138857
139058
|
Android: queries the Perfetto .pftrace via the in-process Perfetto trace-processor engine for CPU hotspots, UI hangs with jank reason + main-thread state breakdown, GC annotation, and an RSS-growth weak signal.
|
|
@@ -138868,7 +139069,7 @@ Fails if native-profiler-stop has not been called first to export trace data.`,
|
|
|
138868
139069
|
async execute(services, params, ctx) {
|
|
138869
139070
|
const api = services.session;
|
|
138870
139071
|
const device = resolveDevice(params.device_id);
|
|
138871
|
-
assertSupported("native-profiler-analyze",
|
|
139072
|
+
assertSupported("native-profiler-analyze", capability27, device);
|
|
138872
139073
|
let result;
|
|
138873
139074
|
if (api.platform === "ios") {
|
|
138874
139075
|
await ensureDeps(["xcrun"]);
|
|
@@ -139847,7 +140048,7 @@ var zodSchema51 = external_exports.object({
|
|
|
139847
140048
|
"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."
|
|
139848
140049
|
)
|
|
139849
140050
|
});
|
|
139850
|
-
var
|
|
140051
|
+
var capability28 = {
|
|
139851
140052
|
apple: { simulator: true },
|
|
139852
140053
|
android: { emulator: true, device: true, unknown: true }
|
|
139853
140054
|
};
|
|
@@ -139859,7 +140060,7 @@ function createScreenRecordingStartTool(registry2) {
|
|
|
139859
140060
|
completedMsg: () => "Started screen recording",
|
|
139860
140061
|
failedMsg: ({ failureSignal: failureSignal2 }) => `Failed to start screen recording: ${failureSignal2.error_code}`
|
|
139861
140062
|
},
|
|
139862
|
-
capability:
|
|
140063
|
+
capability: capability28,
|
|
139863
140064
|
description: `Start recording the device screen to a video file (h264 mp4, 30fps at the device's native resolution).
|
|
139864
140065
|
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.
|
|
139865
140066
|
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.
|
|
@@ -139879,7 +140080,7 @@ Fails if a recording is already running on the device, the device is not booted,
|
|
|
139879
140080
|
async execute(services, params) {
|
|
139880
140081
|
const api = services.session;
|
|
139881
140082
|
const device = resolveDevice(params.udid);
|
|
139882
|
-
assertSupported("screen-recording-start",
|
|
140083
|
+
assertSupported("screen-recording-start", capability28, device);
|
|
139883
140084
|
if (device.platform === "ios" && await isTvOsSimulator(params.udid)) {
|
|
139884
140085
|
throw new FailureError(
|
|
139885
140086
|
`Screen recording is not supported on tvOS simulators (device ${params.udid}).`,
|
|
@@ -139954,7 +140155,7 @@ var zodSchema52 = external_exports.object({
|
|
|
139954
140155
|
udid: external_exports.string().describe("Target device id from `list-devices` (iOS Simulator UDID or Android serial).")
|
|
139955
140156
|
});
|
|
139956
140157
|
var RECORDINGS_DIR = ".argent/recordings";
|
|
139957
|
-
var
|
|
140158
|
+
var capability29 = {
|
|
139958
140159
|
apple: { simulator: true },
|
|
139959
140160
|
android: { emulator: true, device: true, unknown: true }
|
|
139960
140161
|
};
|
|
@@ -139965,7 +140166,7 @@ var screenRecordingStopTool = {
|
|
|
139965
140166
|
completedMsg: ({ result }) => `Saved screen recording ${result.video.filename}`,
|
|
139966
140167
|
failedMsg: ({ failureSignal: failureSignal2 }) => `Failed to stop screen recording: ${failureSignal2.error_code}`
|
|
139967
140168
|
},
|
|
139968
|
-
capability:
|
|
140169
|
+
capability: capability29,
|
|
139969
140170
|
description: `Stop the screen recording started by \`screen-recording-start\` and retrieve the video: frame capture ends and ffmpeg finalizes the mp4.
|
|
139970
140171
|
Also retrieves the video when the recording already ended on its own (time limit reached, capture process died) \u2014 call it even after the cap fired.
|
|
139971
140172
|
Use when the interaction being captured is finished, or a tool-result note reminds you a recording is still running.
|
|
@@ -139979,7 +140180,7 @@ Fails if no recording (running or finished-but-unretrieved) exists for the given
|
|
|
139979
140180
|
async execute(services, params, ctx) {
|
|
139980
140181
|
const api = services.session;
|
|
139981
140182
|
const device = resolveDevice(params.udid);
|
|
139982
|
-
assertSupported("screen-recording-stop",
|
|
140183
|
+
assertSupported("screen-recording-stop", capability29, device);
|
|
139983
140184
|
const stopped = await stopCapture(api);
|
|
139984
140185
|
const artifacts = requireArtifacts(ctx);
|
|
139985
140186
|
const video = await artifacts.register(stopped.outputFile, {
|
|
@@ -150048,7 +150249,7 @@ var zodSchema70 = external_exports.object({
|
|
|
150048
150249
|
"Directory where diff artifacts should be written. Optional \u2014 defaults to a temp directory; the diff images are returned in the result either way."
|
|
150049
150250
|
)
|
|
150050
150251
|
}).strict();
|
|
150051
|
-
var
|
|
150252
|
+
var capability30 = {
|
|
150052
150253
|
apple: { simulator: true, device: true },
|
|
150053
150254
|
android: { emulator: true, device: true, unknown: true }
|
|
150054
150255
|
};
|
|
@@ -150073,7 +150274,7 @@ Ignores the fixed top status-bar band for both pixel and OCR text comparisons.
|
|
|
150073
150274
|
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.`,
|
|
150074
150275
|
searchHint: "compare screenshots png diff visual UI changes UI regression visual regression screenshot diff changed regions text ocr live capture",
|
|
150075
150276
|
zodSchema: zodSchema70,
|
|
150076
|
-
capability:
|
|
150277
|
+
capability: capability30,
|
|
150077
150278
|
fileInputs: fileInputs6,
|
|
150078
150279
|
services: (params) => {
|
|
150079
150280
|
if (params.captureBaseline || params.captureCurrent) {
|
|
@@ -150472,7 +150673,7 @@ var tabAction = {
|
|
|
150472
150673
|
failure: "close"
|
|
150473
150674
|
}
|
|
150474
150675
|
};
|
|
150475
|
-
var
|
|
150676
|
+
var capability31 = {
|
|
150476
150677
|
chromium: { app: true }
|
|
150477
150678
|
};
|
|
150478
150679
|
var chromiumTabsTool = {
|
|
@@ -150491,7 +150692,7 @@ Use when an app exposes multiple windows or tabs and you need to inspect or driv
|
|
|
150491
150692
|
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.`,
|
|
150492
150693
|
searchHint: "tab tabs window windows switch select close new open multi-tab chromium electron",
|
|
150493
150694
|
zodSchema: zodSchema73,
|
|
150494
|
-
capability:
|
|
150695
|
+
capability: capability31,
|
|
150495
150696
|
services: (params) => {
|
|
150496
150697
|
const device = resolveDevice(params.udid);
|
|
150497
150698
|
if (device.platform === "chromium") {
|
|
@@ -150614,7 +150815,7 @@ var cookieAction = {
|
|
|
150614
150815
|
delete: { started: "Deleting", completed: "Deleted", failure: "delete" },
|
|
150615
150816
|
clear: { started: "Clearing", completed: "Cleared", failure: "clear" }
|
|
150616
150817
|
};
|
|
150617
|
-
var
|
|
150818
|
+
var capability32 = {
|
|
150618
150819
|
chromium: { app: true }
|
|
150619
150820
|
};
|
|
150620
150821
|
var chromiumCookiesTool = {
|
|
@@ -150633,7 +150834,7 @@ Use when seeding an authenticated session before a flow (set the session cookie,
|
|
|
150633
150834
|
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.`,
|
|
150634
150835
|
searchHint: "cookies cookie get set delete clear httponly samesite session auth chromium",
|
|
150635
150836
|
zodSchema: zodSchema74,
|
|
150636
|
-
capability:
|
|
150837
|
+
capability: capability32,
|
|
150637
150838
|
services: (params) => {
|
|
150638
150839
|
const device = resolveDevice(params.udid);
|
|
150639
150840
|
if (device.platform === "chromium") {
|
|
@@ -150712,7 +150913,7 @@ var storageAction = {
|
|
|
150712
150913
|
remove: { started: "Removing from", completed: "Removed from", failure: "remove from" },
|
|
150713
150914
|
clear: { started: "Clearing", completed: "Cleared", failure: "clear" }
|
|
150714
150915
|
};
|
|
150715
|
-
var
|
|
150916
|
+
var capability33 = {
|
|
150716
150917
|
chromium: { app: true }
|
|
150717
150918
|
};
|
|
150718
150919
|
var chromiumStorageTool = {
|
|
@@ -150732,7 +150933,7 @@ Use when seeding feature flags / auth tokens before a flow or asserting persiste
|
|
|
150732
150933
|
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.`,
|
|
150733
150934
|
searchHint: "storage localstorage sessionstorage local session get set remove clear key value chromium",
|
|
150734
150935
|
zodSchema: zodSchema75,
|
|
150735
|
-
capability:
|
|
150936
|
+
capability: capability33,
|
|
150736
150937
|
services: (params) => {
|
|
150737
150938
|
const device = resolveDevice(params.udid);
|
|
150738
150939
|
if (device.platform === "chromium") {
|
|
@@ -150820,6 +151021,7 @@ function createRegistry() {
|
|
|
150820
151021
|
registry2.registerTool(gestureRotateTool);
|
|
150821
151022
|
registry2.registerTool(buttonTool);
|
|
150822
151023
|
registry2.registerTool(createKeyboardTool(registry2));
|
|
151024
|
+
registry2.registerTool(createPasteTool(registry2));
|
|
150823
151025
|
registry2.registerTool(rotateTool);
|
|
150824
151026
|
registry2.registerTool(shakeTool);
|
|
150825
151027
|
registry2.registerTool(createTvRemoteTool(registry2));
|
package/package.json
CHANGED
|
@@ -56,27 +56,28 @@ Common schemes: `messages://`, `settings://`, `maps://?q=<query>`, `tel://<numbe
|
|
|
56
56
|
|
|
57
57
|
## 4. Choosing the Right Tool
|
|
58
58
|
|
|
59
|
-
| Action | Tool | Notes
|
|
60
|
-
| ----------------- | ------------------- |
|
|
61
|
-
| Multiple actions | `run-sequence` | Batch steps in one call (no intermediate screenshots)
|
|
62
|
-
| Open an app | `launch-app` | **Always — never tap home-screen icons**
|
|
63
|
-
| Restart an app | `restart-app` | Terminate and relaunch by bundle ID
|
|
64
|
-
| Open URL/scheme | `open-url` | Web pages, deep links, URL schemes
|
|
65
|
-
| Single tap | `gesture-tap` | Buttons, links, checkboxes
|
|
66
|
-
| Scroll/swipe | `gesture-swipe` | Straight-line scroll or swipe
|
|
67
|
-
| Scroll (Chromium) | `gesture-scroll` | Wheel-based; deltas are window fractions, positive deltaY = down
|
|
68
|
-
| Drag (Chromium) | `gesture-drag` | Sliders, drag-and-drop, text selection
|
|
69
|
-
| Long press | `gesture-custom` | Context menus, drag start
|
|
70
|
-
| Drag & drop | `gesture-custom` | Complex drag interactions
|
|
71
|
-
| Pinch/zoom | `gesture-pinch` | Two-finger pinch with auto-interpolation
|
|
72
|
-
| Rotation | `gesture-rotate` | Two-finger rotation with auto-interpolation
|
|
73
|
-
| Custom gesture | `gesture-custom` | Arbitrary touch sequences, optional interpolation
|
|
74
|
-
| Hardware key | `button` | Home, back, power, volume, appSwitch, actionButton
|
|
75
|
-
| Type text | `keyboard` | Every platform. Text or one named key per call, never both
|
|
76
|
-
|
|
|
77
|
-
|
|
|
78
|
-
|
|
|
79
|
-
| Wait for
|
|
59
|
+
| Action | Tool | Notes |
|
|
60
|
+
| ----------------- | ------------------- | ----------------------------------------------------------------- |
|
|
61
|
+
| Multiple actions | `run-sequence` | Batch steps in one call (no intermediate screenshots) |
|
|
62
|
+
| Open an app | `launch-app` | **Always — never tap home-screen icons** |
|
|
63
|
+
| Restart an app | `restart-app` | Terminate and relaunch by bundle ID |
|
|
64
|
+
| Open URL/scheme | `open-url` | Web pages, deep links, URL schemes |
|
|
65
|
+
| Single tap | `gesture-tap` | Buttons, links, checkboxes |
|
|
66
|
+
| Scroll/swipe | `gesture-swipe` | Straight-line scroll or swipe |
|
|
67
|
+
| Scroll (Chromium) | `gesture-scroll` | Wheel-based; deltas are window fractions, positive deltaY = down |
|
|
68
|
+
| Drag (Chromium) | `gesture-drag` | Sliders, drag-and-drop, text selection |
|
|
69
|
+
| Long press | `gesture-custom` | Context menus, drag start |
|
|
70
|
+
| Drag & drop | `gesture-custom` | Complex drag interactions |
|
|
71
|
+
| Pinch/zoom | `gesture-pinch` | Two-finger pinch with auto-interpolation |
|
|
72
|
+
| Rotation | `gesture-rotate` | Two-finger rotation with auto-interpolation |
|
|
73
|
+
| Custom gesture | `gesture-custom` | Arbitrary touch sequences, optional interpolation |
|
|
74
|
+
| Hardware key | `button` | Home, back, power, volume, appSwitch, actionButton |
|
|
75
|
+
| Type text | `keyboard` | Every platform. Text or one named key per call, never both |
|
|
76
|
+
| Paste text | `paste` | Only where a user would paste (OTP code, long link). Sim/emu only |
|
|
77
|
+
| Rotate device | `rotate` | Orientation changes |
|
|
78
|
+
| Shake device | `shake` | Shake handlers (sim/emu only), Undo-typing prompt, RN dev menu |
|
|
79
|
+
| Wait for UI | `await-ui-element` | Block until an element is visible/hidden/exists/contains text |
|
|
80
|
+
| Wait for idle | `await-screen-idle` | Block until a non-empty screen tree stops changing |
|
|
80
81
|
|
|
81
82
|
## 5. Finding Tap Targets
|
|
82
83
|
|
|
@@ -197,6 +198,18 @@ Rules:
|
|
|
197
198
|
- Nothing outside those sources is reachable; never ask the user to paste a secret value into the conversation. Ask them to put it in a secrets file instead — a file edit applies to the next call, while an exported env var only reaches a tool-server started afterwards.
|
|
198
199
|
- The project sources are found by walking up from the tool-server's working directory. If a project file is not being picked up, the failure's source list shows the paths actually consulted; `~/.argent/secrets.env` needs no project and always applies.
|
|
199
200
|
|
|
201
|
+
### paste — Paste text into the focused field
|
|
202
|
+
|
|
203
|
+
```json
|
|
204
|
+
{ "udid": "<UDID>", "text": "482913" }
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
Puts `text` on the **device** clipboard (the host clipboard is untouched) and triggers the platform's paste shortcut. iOS simulator and Android emulator only; a TV target, a physical device, Chromium and Vega are rejected.
|
|
208
|
+
|
|
209
|
+
`paste` is **not** a faster `keyboard`. `keyboard` types the way a user types and stays the default for every text entry — a search query, a login, a form field. Reach for `paste` only where a real user would paste: a 2FA / OTP code copied from another app, a long link or token, or to test how the app handles pasted input. It also carries what `keyboard` can't type on a given platform (multi-line text, non-ASCII on Android), but that alone is not a reason to paste — ask whether the user would.
|
|
210
|
+
|
|
211
|
+
Tap the field first so it has focus; pasting with no focused field is a silent no-op, as with `keyboard`. `text` accepts the same `{{secret:<NAME>}}` placeholders as `keyboard`, with the same auto-screenshot skip.
|
|
212
|
+
|
|
200
213
|
### rotate — Change orientation
|
|
201
214
|
|
|
202
215
|
```json
|
|
@@ -297,7 +310,7 @@ Use the sequencing when:
|
|
|
297
310
|
|
|
298
311
|
### Allowed tools inside `run-sequence`
|
|
299
312
|
|
|
300
|
-
`gesture-tap`, `gesture-swipe`, `gesture-scroll`, `gesture-drag`, `gesture-custom`, `gesture-pinch`, `gesture-rotate`, `button`, `keyboard`, `rotate`, `await-ui-element`
|
|
313
|
+
`gesture-tap`, `gesture-swipe`, `gesture-scroll`, `gesture-drag`, `gesture-custom`, `gesture-pinch`, `gesture-rotate`, `button`, `keyboard`, `paste`, `rotate`, `shake`, `tv-remote`, `await-ui-element`
|
|
301
314
|
|
|
302
315
|
The `udid` is shared — do **not** include it in each step's `args`. Optional `delayMs` per step (default 100ms).
|
|
303
316
|
|