@exodus/xqa 1.14.1 → 1.14.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +85 -16
- package/dist/xqa.cjs +75 -67
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -14,12 +14,20 @@ The tool manages configuration, project initialization, session state tracking,
|
|
|
14
14
|
|
|
15
15
|
Initialize a new xqa project in the current directory.
|
|
16
16
|
|
|
17
|
-
Creates a `.xqa/` directory with
|
|
17
|
+
Creates a `.xqa/` directory with `app.md` and `explore.md` templates plus subdirectories for specs, designs, and suites. Installs bundled xqa skills.
|
|
18
18
|
|
|
19
19
|
```bash
|
|
20
20
|
xqa init
|
|
21
21
|
```
|
|
22
22
|
|
|
23
|
+
### update
|
|
24
|
+
|
|
25
|
+
Update installed xqa skills to the current CLI version.
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
xqa update
|
|
29
|
+
```
|
|
30
|
+
|
|
23
31
|
### explore [prompt]
|
|
24
32
|
|
|
25
33
|
Run the explorer agent; omit prompt for a full breadth-first sweep.
|
|
@@ -31,44 +39,73 @@ xqa explore # breadth-first exploration
|
|
|
31
39
|
xqa explore "test the login flow" # focused exploration
|
|
32
40
|
xqa explore -v prompt,screen # verbose output for categories
|
|
33
41
|
xqa explore -v # verbose output for all categories
|
|
42
|
+
xqa explore -t 600 # override explorer timeout (seconds)
|
|
43
|
+
xqa explore --debug # log timing and event details to stderr
|
|
34
44
|
```
|
|
35
45
|
|
|
36
|
-
|
|
46
|
+
Flags:
|
|
47
|
+
|
|
48
|
+
- `-v, --verbose [categories]` — Log categories (prompt, tools, screen, memory). Default: all if flag is present without value.
|
|
49
|
+
- `-t, --timeout <seconds>` — Explorer timeout in seconds (overrides `QA_EXPLORE_TIMEOUT_SECONDS`).
|
|
50
|
+
- `--debug` — Log timing and event details to stderr.
|
|
37
51
|
|
|
38
52
|
### spec [spec-file]
|
|
39
53
|
|
|
40
54
|
Run the explorer agent against a spec file.
|
|
41
55
|
|
|
42
|
-
Loads a spec markdown file from `.xqa/specs/` (or an absolute path) and executes the agent against it.
|
|
56
|
+
Loads a spec markdown file from `.xqa/specs/` (or an absolute path) and executes the agent against it. Omit the argument to pick from available specs interactively.
|
|
43
57
|
|
|
44
58
|
```bash
|
|
45
59
|
xqa spec # interactive spec picker
|
|
46
|
-
xqa spec .xqa/specs/authentication.test.md
|
|
60
|
+
xqa spec .xqa/specs/authentication.test.md # explicit spec file
|
|
47
61
|
xqa spec -v tools,memory # verbose output
|
|
62
|
+
xqa spec --debug # debug logging
|
|
48
63
|
```
|
|
49
64
|
|
|
50
|
-
|
|
65
|
+
Flags:
|
|
66
|
+
|
|
67
|
+
- `-v, --verbose [categories]` — Same as explore.
|
|
68
|
+
- `--debug` — Log timing and event details to stderr.
|
|
51
69
|
|
|
52
70
|
Spec file format (YAML frontmatter + markdown):
|
|
53
71
|
|
|
54
72
|
```markdown
|
|
55
73
|
---
|
|
56
74
|
feature: 'Feature Name'
|
|
57
|
-
entry: 'Screen name or navigation path'
|
|
58
75
|
timeout: 300
|
|
59
76
|
---
|
|
60
77
|
|
|
61
78
|
# Spec content
|
|
62
79
|
```
|
|
63
80
|
|
|
81
|
+
Frontmatter fields: `feature` (required), `timeout` (optional, seconds).
|
|
82
|
+
|
|
83
|
+
### run
|
|
84
|
+
|
|
85
|
+
Run a test suite or a set of spec files in parallel across booted simulators.
|
|
86
|
+
|
|
87
|
+
Exactly one of `--suite` or `--spec` is required.
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
xqa run --suite smoke # run .xqa/suites/smoke.suite.json
|
|
91
|
+
xqa run --spec 'specs/**/*.test.md' # run matching spec files
|
|
92
|
+
xqa run --suite smoke --debug # debug logging
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Flags:
|
|
96
|
+
|
|
97
|
+
- `--suite <name>` — Name of the suite (`<name>.suite.json`) under `.xqa/suites/`.
|
|
98
|
+
- `--spec <globs...>` — Glob patterns matching spec files, resolved from the xqa directory.
|
|
99
|
+
- `--debug` — Log timing and event details to stderr.
|
|
100
|
+
|
|
64
101
|
### review [findings-path]
|
|
65
102
|
|
|
66
103
|
Review findings and mark false positives.
|
|
67
104
|
|
|
68
|
-
Interactive session for triaging findings generated by explore or spec runs.
|
|
105
|
+
Interactive session for triaging findings generated by explore or spec runs. Mark findings as dismissed (with optional reason) or undo previous dismissals. Dismissals are written to `dismissals.json` next to the `.xqa` directory (override with `QA_DISMISSALS_PATH`). Defaults to the last findings path if omitted.
|
|
69
106
|
|
|
70
107
|
```bash
|
|
71
|
-
xqa review
|
|
108
|
+
xqa review # use last findings file
|
|
72
109
|
xqa review .xqa/output/findings-abc123.json # explicit path
|
|
73
110
|
```
|
|
74
111
|
|
|
@@ -93,26 +130,35 @@ xqa completion bash # generate bash completions
|
|
|
93
130
|
xqa completion zsh # generate zsh completions
|
|
94
131
|
```
|
|
95
132
|
|
|
96
|
-
### Suite
|
|
133
|
+
### Suite config
|
|
97
134
|
|
|
98
|
-
Suite
|
|
135
|
+
Suite files live at `.xqa/suites/<name>.suite.json` and declare the work items plus optional hooks.
|
|
99
136
|
|
|
100
137
|
```json
|
|
101
138
|
{
|
|
102
139
|
"specs": ["specs/send.test.md"],
|
|
140
|
+
"freestyle": [{ "prompt": "explore settings", "timeoutSeconds": 300 }],
|
|
103
141
|
"hooks": {
|
|
104
142
|
"beforeEach": {
|
|
105
143
|
"script": "qa/prepare-sim.mjs",
|
|
106
|
-
"env": { "APP_PROFILE": "funded" }
|
|
144
|
+
"env": { "APP_PROFILE": "funded" },
|
|
145
|
+
"timeoutSeconds": 120
|
|
107
146
|
}
|
|
108
147
|
}
|
|
109
148
|
}
|
|
110
149
|
```
|
|
111
150
|
|
|
151
|
+
Fields:
|
|
152
|
+
|
|
153
|
+
- `specs` (optional) — glob patterns resolved from the xqa directory.
|
|
154
|
+
- `freestyle` (optional) — either a positive integer (N empty entries) or an array of `{ prompt?, timeoutSeconds }` entries.
|
|
155
|
+
- At least one of `specs` or `freestyle` must resolve to a work item.
|
|
156
|
+
- `hooks.beforeEach` (optional) — runs before every work item on every simulator. Use for project-owned setup (wallet provisioning, cache warming, login seeding).
|
|
157
|
+
|
|
112
158
|
The hook script is invoked as a Node child process. It receives:
|
|
113
159
|
|
|
114
160
|
- Inherited `process.env`
|
|
115
|
-
- Suite-declared `env`
|
|
161
|
+
- Suite-declared `env` overlaid with reserved keys (reserved wins)
|
|
116
162
|
- Reserved xqa-owned keys: `XQA_SIM_UDID`, `XQA_ITEM_ID`, `XQA_ITEM_TYPE`, `XQA_ITEM_NAME`, `XQA_SUITE`, and (when item type is `spec`) `XQA_SPEC_PATH`
|
|
117
163
|
|
|
118
164
|
Suite-declared `env` cannot override reserved keys — the parser rejects such configs.
|
|
@@ -121,7 +167,7 @@ Contract:
|
|
|
121
167
|
|
|
122
168
|
- Exit 0 → proceed with item.
|
|
123
169
|
- Non-zero exit → item marked failed, `executeItem` skipped, counts toward simulator-unhealthy threshold.
|
|
124
|
-
- 120s timeout
|
|
170
|
+
- Default 120s timeout, overridable via `hooks.beforeEach.timeoutSeconds`.
|
|
125
171
|
- Honors the suite abort signal.
|
|
126
172
|
|
|
127
173
|
## Configuration
|
|
@@ -133,15 +179,17 @@ Configuration is loaded from environment variables and `.env.local`:
|
|
|
133
179
|
- `QA_RUN_ID` (optional) — Custom run identifier; defaults to auto-generated
|
|
134
180
|
- `QA_EXPLORE_TIMEOUT_SECONDS` (optional) — Exploration timeout in seconds
|
|
135
181
|
- `QA_BUILD_ENV` (optional) — Build environment: `dev` or `prod` (default: prod)
|
|
182
|
+
- `QA_DISMISSALS_PATH` (optional) — Override the dismissals file path used by `xqa review`
|
|
136
183
|
|
|
137
184
|
## Architecture
|
|
138
185
|
|
|
139
186
|
Key files and directories:
|
|
140
187
|
|
|
141
188
|
- `src/index.ts` — CLI entry point; wires commander commands and manages graceful shutdown via process locks
|
|
142
|
-
- `src/commands/` — Command implementations (init, explore, spec, review, analyse, completion)
|
|
143
|
-
- `src/
|
|
144
|
-
- `src/
|
|
189
|
+
- `src/commands/` — Command implementations (init, update, explore, spec, review, analyse, completion)
|
|
190
|
+
- `src/suite/` — Suite runner: config parsing, work-item building, worker pool, hooks
|
|
191
|
+
- `src/core/` — Pure functions: completion generation, verbose/timeout option parsing, last-path tracking
|
|
192
|
+
- `src/shell/` — I/O wrappers: app/explore context reading, debug logging, display factory, preflight, xqa directory discovery
|
|
145
193
|
- `src/config.ts`, `src/config-schema.ts` — Configuration loading and validation with Zod
|
|
146
194
|
- `src/review-session.ts` — Interactive finding review loop with dismissal tracking
|
|
147
195
|
- `src/spec-frontmatter.ts` — Spec markdown frontmatter parsing (YAML)
|
|
@@ -157,6 +205,8 @@ Core error discriminated unions:
|
|
|
157
205
|
- `XqaDirectoryError` — No .xqa directory found (XQA_NOT_INITIALIZED)
|
|
158
206
|
- `SpecFrontmatterError` — Malformed spec markdown (MISSING_FRONTMATTER, MISSING_FIELD, PARSE_ERROR)
|
|
159
207
|
- `LastPathError` — No findings path provided and no prior session (NO_ARG_AND_NO_STATE)
|
|
208
|
+
- `SuiteConfigError` — Suite config JSON malformed or schema-invalid (INVALID_SUITE_CONFIG)
|
|
209
|
+
- `HookError` — Suite hook failure (HOOK_SPAWN_FAILED, HOOK_EXIT_NONZERO, HOOK_TIMEOUT, HOOK_ABORTED)
|
|
160
210
|
|
|
161
211
|
## Development
|
|
162
212
|
|
|
@@ -231,20 +281,39 @@ src/
|
|
|
231
281
|
|
|
232
282
|
commands/
|
|
233
283
|
init-command.ts # Project initialization
|
|
284
|
+
update-command.ts # Skill updates
|
|
285
|
+
install-skills.ts # Bundled skill installer
|
|
234
286
|
explore-command.ts # Breadth-first exploration
|
|
235
287
|
spec-command.ts # Spec-based exploration
|
|
288
|
+
spec-resolver.ts # Spec file discovery and parsing
|
|
236
289
|
review-command.ts # Finding triage workflow
|
|
237
290
|
analyse-command.ts # Video analysis
|
|
238
291
|
completion-command.ts # Shell completion generation
|
|
292
|
+
item-events.ts # Start/complete/fail event emitters
|
|
239
293
|
|
|
240
294
|
core/
|
|
241
295
|
parse-verbose.ts # Verbose flag parsing
|
|
296
|
+
parse-timeout-seconds.ts # Timeout flag parsing
|
|
242
297
|
completion-generator.ts # Bash/zsh completion script generation
|
|
243
298
|
last-path.ts # Last findings path tracking
|
|
244
299
|
|
|
245
300
|
shell/
|
|
246
301
|
app-context.ts # Read app.md and explore.md
|
|
247
302
|
xqa-directory.ts # Locate .xqa directory
|
|
303
|
+
preflight.ts # Environment preflight checks
|
|
304
|
+
ffmpeg-check.ts # ffmpeg availability probe
|
|
305
|
+
display-factory.ts # Solo and suite display factories
|
|
306
|
+
debug-logger.ts # Debug event logging
|
|
307
|
+
debug-agent-events.ts # Agent event debug formatter
|
|
308
|
+
debug-suite-events.ts # Suite event debug formatter
|
|
309
|
+
debug-logger-core.ts # Pure logging helpers
|
|
310
|
+
trigger-abort.ts # Abort signal plumbing
|
|
311
|
+
|
|
312
|
+
suite/
|
|
313
|
+
types.ts # Suite work-item and findings types
|
|
314
|
+
core/ # Pure: config parser, item builders, hook env, queue
|
|
315
|
+
shell/ # I/O: worker pool, hook runner, findings writer
|
|
316
|
+
commands/ # run-command, execute-item, suite-run-context
|
|
248
317
|
|
|
249
318
|
__tests__/
|
|
250
319
|
*.test.ts # Test files co-located with src/
|
package/dist/xqa.cjs
CHANGED
|
@@ -52351,27 +52351,13 @@ var DEFAULT_LONG_PRESS_DURATION_MS = 500;
|
|
|
52351
52351
|
var MS_PER_SECOND = 1e3;
|
|
52352
52352
|
var DEFAULT_SWIPE_DURATION_SECONDS = 0.1;
|
|
52353
52353
|
var ENTER_KEY_CODE = "0x28";
|
|
52354
|
-
var TAP_SCHEMA = { x: external_exports.number(), y: external_exports.number() };
|
|
52355
|
-
var LONG_PRESS_SCHEMA = { x: external_exports.number(), y: external_exports.number(), duration: external_exports.number().optional() };
|
|
52356
|
-
var SWIPE_SCHEMA = {
|
|
52357
|
-
x_start: external_exports.number(),
|
|
52358
|
-
y_start: external_exports.number(),
|
|
52359
|
-
x_end: external_exports.number(),
|
|
52360
|
-
y_end: external_exports.number(),
|
|
52361
|
-
duration: external_exports.number().positive().optional().describe(
|
|
52362
|
-
"Gesture duration in seconds. Smaller values (e.g. 0.1) produce a flick that scrolls lists and dismisses sheets; larger values (e.g. 0.5+) produce a slow drag suitable for reordering or panning. Defaults to 0.1s (flick)."
|
|
52363
|
-
)
|
|
52364
|
-
};
|
|
52365
|
-
var TYPE_TEXT_SCHEMA = { text: external_exports.string(), submit: external_exports.boolean().optional() };
|
|
52366
|
-
var PRESS_BUTTON_SCHEMA = {
|
|
52367
|
-
button: external_exports.enum(["HOME", "LOCK", "SIRI", "SIDE_BUTTON", "APPLE_PAY"])
|
|
52368
|
-
};
|
|
52369
52354
|
function errorResult2(error48) {
|
|
52370
52355
|
return {
|
|
52371
52356
|
content: [{ type: "text", text: `Error: ${String(error48.cause)}` }],
|
|
52372
52357
|
isError: true
|
|
52373
52358
|
};
|
|
52374
52359
|
}
|
|
52360
|
+
var TAP_SCHEMA = { x: external_exports.number(), y: external_exports.number() };
|
|
52375
52361
|
function buildTapArguments(resolvedUdid, input) {
|
|
52376
52362
|
return ["ui", "tap", "--udid", resolvedUdid, String(input.x), String(input.y)];
|
|
52377
52363
|
}
|
|
@@ -52406,6 +52392,23 @@ async function handleDoubleTap(input) {
|
|
|
52406
52392
|
]
|
|
52407
52393
|
};
|
|
52408
52394
|
}
|
|
52395
|
+
function createTapTool(udid = "booted") {
|
|
52396
|
+
return _x(
|
|
52397
|
+
"tap",
|
|
52398
|
+
"Tap on the screen at the given coordinates.",
|
|
52399
|
+
TAP_SCHEMA,
|
|
52400
|
+
async ({ x, y: y6 }) => handleTap({ udid, x, y: y6 })
|
|
52401
|
+
);
|
|
52402
|
+
}
|
|
52403
|
+
function createDoubleTapTool(udid = "booted") {
|
|
52404
|
+
return _x(
|
|
52405
|
+
"double_tap",
|
|
52406
|
+
"Double-tap on the screen at the given coordinates.",
|
|
52407
|
+
TAP_SCHEMA,
|
|
52408
|
+
async ({ x, y: y6 }) => handleDoubleTap({ udid, x, y: y6 })
|
|
52409
|
+
);
|
|
52410
|
+
}
|
|
52411
|
+
var LONG_PRESS_SCHEMA = { x: external_exports.number(), y: external_exports.number(), duration: external_exports.number().optional() };
|
|
52409
52412
|
function buildLongPressArguments(resolvedUdid, input) {
|
|
52410
52413
|
return [
|
|
52411
52414
|
"ui",
|
|
@@ -52434,8 +52437,39 @@ async function handleLongPress(input) {
|
|
|
52434
52437
|
]
|
|
52435
52438
|
};
|
|
52436
52439
|
}
|
|
52440
|
+
function createLongPressTool(udid = "booted") {
|
|
52441
|
+
return _x(
|
|
52442
|
+
"long_press",
|
|
52443
|
+
"Long-press on the screen at the given coordinates.",
|
|
52444
|
+
LONG_PRESS_SCHEMA,
|
|
52445
|
+
async ({ x, y: y6, duration: duration3 }) => handleLongPress({ udid, x, y: y6, duration: duration3 ?? DEFAULT_LONG_PRESS_DURATION_MS })
|
|
52446
|
+
);
|
|
52447
|
+
}
|
|
52448
|
+
var SWIPE_SCHEMA = {
|
|
52449
|
+
x_start: external_exports.number(),
|
|
52450
|
+
y_start: external_exports.number(),
|
|
52451
|
+
x_end: external_exports.number(),
|
|
52452
|
+
y_end: external_exports.number(),
|
|
52453
|
+
duration: external_exports.number().positive().optional().describe(
|
|
52454
|
+
"Seconds for the full gesture. Velocity = distance / duration \u2014 raise duration at fixed distance to slow the gesture and reduce momentum. Default 0.1s (flick) works for short lists; raise to 0.4\u20130.8 for controlled scrolling on long lists where the flick overshoots."
|
|
52455
|
+
),
|
|
52456
|
+
delta: external_exports.number().positive().optional().describe(
|
|
52457
|
+
"Pixel distance between interpolated touch points along the swipe path. Smaller values (e.g. 5) produce a denser event stream \u2014 smoother motion and more controllable stop-velocity, recommended when combining with a raised duration to tame long-list overshoot. Larger values produce coarser strokes. Omit to use idb defaults."
|
|
52458
|
+
)
|
|
52459
|
+
};
|
|
52460
|
+
function toSwipeInput(udid, params) {
|
|
52461
|
+
return {
|
|
52462
|
+
udid,
|
|
52463
|
+
xStart: params.x_start,
|
|
52464
|
+
yStart: params.y_start,
|
|
52465
|
+
xEnd: params.x_end,
|
|
52466
|
+
yEnd: params.y_end,
|
|
52467
|
+
duration: params.duration ?? DEFAULT_SWIPE_DURATION_SECONDS,
|
|
52468
|
+
delta: params.delta
|
|
52469
|
+
};
|
|
52470
|
+
}
|
|
52437
52471
|
function buildSwipeArguments(resolvedUdid, input) {
|
|
52438
|
-
|
|
52472
|
+
const arguments_ = [
|
|
52439
52473
|
"ui",
|
|
52440
52474
|
"swipe",
|
|
52441
52475
|
"--udid",
|
|
@@ -52447,6 +52481,10 @@ function buildSwipeArguments(resolvedUdid, input) {
|
|
|
52447
52481
|
"--duration",
|
|
52448
52482
|
String(input.duration)
|
|
52449
52483
|
];
|
|
52484
|
+
if (input.delta !== void 0) {
|
|
52485
|
+
arguments_.push("--delta", String(input.delta));
|
|
52486
|
+
}
|
|
52487
|
+
return arguments_;
|
|
52450
52488
|
}
|
|
52451
52489
|
async function handleSwipe(input) {
|
|
52452
52490
|
const result = await resolveUdid(input.udid).andThen(
|
|
@@ -52464,6 +52502,15 @@ async function handleSwipe(input) {
|
|
|
52464
52502
|
]
|
|
52465
52503
|
};
|
|
52466
52504
|
}
|
|
52505
|
+
function createSwipeTool(udid = "booted") {
|
|
52506
|
+
return _x(
|
|
52507
|
+
"swipe",
|
|
52508
|
+
"Swipe on the screen from one point to another. Default duration 0.1s produces a flick \u2014 use for scrolling lists, dismissing sheets, triggering paging. Use duration 0.5+ for slow drag (reorder, pan). For long lists where default flick overshoots: shorten swipe distance AND raise duration to 0.4\u20130.8 to lower velocity; optionally lower delta for denser touch events and a more controllable stop. Omitting duration uses the flick default.",
|
|
52509
|
+
SWIPE_SCHEMA,
|
|
52510
|
+
async (params) => handleSwipe(toSwipeInput(udid, params))
|
|
52511
|
+
);
|
|
52512
|
+
}
|
|
52513
|
+
var TYPE_TEXT_SCHEMA = { text: external_exports.string(), submit: external_exports.boolean().optional() };
|
|
52467
52514
|
async function handleTypeText({ udid, text, submit }) {
|
|
52468
52515
|
const result = await resolveUdid(udid).andThen((resolvedUdid) => {
|
|
52469
52516
|
const typeResult = runCommand("idb", ["ui", "text", "--udid", resolvedUdid, text]);
|
|
@@ -52479,6 +52526,17 @@ async function handleTypeText({ udid, text, submit }) {
|
|
|
52479
52526
|
}
|
|
52480
52527
|
return { content: [{ type: "text", text: `Typed: ${text}` }] };
|
|
52481
52528
|
}
|
|
52529
|
+
function createTypeTextTool(udid = "booted") {
|
|
52530
|
+
return _x(
|
|
52531
|
+
"type_text",
|
|
52532
|
+
"Type text into the currently focused element.",
|
|
52533
|
+
TYPE_TEXT_SCHEMA,
|
|
52534
|
+
async ({ text, submit }) => handleTypeText({ udid, text, submit: submit ?? false })
|
|
52535
|
+
);
|
|
52536
|
+
}
|
|
52537
|
+
var PRESS_BUTTON_SCHEMA = {
|
|
52538
|
+
button: external_exports.enum(["HOME", "LOCK", "SIRI", "SIDE_BUTTON", "APPLE_PAY"])
|
|
52539
|
+
};
|
|
52482
52540
|
async function handlePressButton(udid, button) {
|
|
52483
52541
|
const result = await resolveUdid(udid).andThen(
|
|
52484
52542
|
(resolvedUdid) => runCommand("idb", ["ui", "button", "--udid", resolvedUdid, button])
|
|
@@ -52488,56 +52546,6 @@ async function handlePressButton(udid, button) {
|
|
|
52488
52546
|
}
|
|
52489
52547
|
return { content: [{ type: "text", text: `Pressed button: ${button}` }] };
|
|
52490
52548
|
}
|
|
52491
|
-
function createTapTool(udid = "booted") {
|
|
52492
|
-
return _x(
|
|
52493
|
-
"tap",
|
|
52494
|
-
"Tap on the screen at the given coordinates.",
|
|
52495
|
-
TAP_SCHEMA,
|
|
52496
|
-
async ({ x, y: y6 }) => handleTap({ udid, x, y: y6 })
|
|
52497
|
-
);
|
|
52498
|
-
}
|
|
52499
|
-
function createDoubleTapTool(udid = "booted") {
|
|
52500
|
-
return _x(
|
|
52501
|
-
"double_tap",
|
|
52502
|
-
"Double-tap on the screen at the given coordinates.",
|
|
52503
|
-
TAP_SCHEMA,
|
|
52504
|
-
async ({ x, y: y6 }) => handleDoubleTap({ udid, x, y: y6 })
|
|
52505
|
-
);
|
|
52506
|
-
}
|
|
52507
|
-
function createLongPressTool(udid = "booted") {
|
|
52508
|
-
return _x(
|
|
52509
|
-
"long_press",
|
|
52510
|
-
"Long-press on the screen at the given coordinates.",
|
|
52511
|
-
LONG_PRESS_SCHEMA,
|
|
52512
|
-
async ({ x, y: y6, duration: duration3 }) => handleLongPress({ udid, x, y: y6, duration: duration3 ?? DEFAULT_LONG_PRESS_DURATION_MS })
|
|
52513
|
-
);
|
|
52514
|
-
}
|
|
52515
|
-
function toSwipeInput(udid, params) {
|
|
52516
|
-
return {
|
|
52517
|
-
udid,
|
|
52518
|
-
xStart: params.x_start,
|
|
52519
|
-
yStart: params.y_start,
|
|
52520
|
-
xEnd: params.x_end,
|
|
52521
|
-
yEnd: params.y_end,
|
|
52522
|
-
duration: params.duration ?? DEFAULT_SWIPE_DURATION_SECONDS
|
|
52523
|
-
};
|
|
52524
|
-
}
|
|
52525
|
-
function createSwipeTool(udid = "booted") {
|
|
52526
|
-
return _x(
|
|
52527
|
-
"swipe",
|
|
52528
|
-
"Swipe on the screen from one point to another. `duration` (seconds) controls gesture velocity: the default 0.1s produces a flick that scrolls lists, dismisses sheets and triggers paging; pass a larger value (e.g. 0.5+) for a slow drag suitable for reordering or panning. Omitting `duration` uses the flick default.",
|
|
52529
|
-
SWIPE_SCHEMA,
|
|
52530
|
-
async (params) => handleSwipe(toSwipeInput(udid, params))
|
|
52531
|
-
);
|
|
52532
|
-
}
|
|
52533
|
-
function createTypeTextTool(udid = "booted") {
|
|
52534
|
-
return _x(
|
|
52535
|
-
"type_text",
|
|
52536
|
-
"Type text into the currently focused element.",
|
|
52537
|
-
TYPE_TEXT_SCHEMA,
|
|
52538
|
-
async ({ text, submit }) => handleTypeText({ udid, text, submit: submit ?? false })
|
|
52539
|
-
);
|
|
52540
|
-
}
|
|
52541
52549
|
function createPressButtonTool(udid = "booted") {
|
|
52542
52550
|
return _x(
|
|
52543
52551
|
"press_button",
|
|
@@ -76515,7 +76523,7 @@ function resolveXqaDirectory() {
|
|
|
76515
76523
|
return result.value;
|
|
76516
76524
|
}
|
|
76517
76525
|
var program2 = new Command();
|
|
76518
|
-
program2.name("xqa").description("AI-powered QA agent CLI").version(`${"1.14.
|
|
76526
|
+
program2.name("xqa").description("AI-powered QA agent CLI").version(`${"1.14.2"}${false ? ` (dev build +${"5d87cb5"})` : ""}`);
|
|
76519
76527
|
program2.command("init").description("Initialize a new xqa project in the current directory").action(() => {
|
|
76520
76528
|
runInitCommand();
|
|
76521
76529
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@exodus/xqa",
|
|
3
|
-
"version": "1.14.
|
|
3
|
+
"version": "1.14.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"engines": {
|
|
6
6
|
"node": ">=22"
|
|
@@ -26,11 +26,11 @@
|
|
|
26
26
|
"typescript": "^5.8.3",
|
|
27
27
|
"vitest": "^3.2.1",
|
|
28
28
|
"zod": "^3.0.0",
|
|
29
|
+
"@qa-agents/display": "0.0.0",
|
|
30
|
+
"@qa-agents/eslint-config": "0.0.0",
|
|
29
31
|
"@qa-agents/explorer": "0.0.0",
|
|
30
32
|
"@qa-agents/mobile-ios": "0.0.0",
|
|
31
33
|
"@qa-agents/pipeline": "0.0.0",
|
|
32
|
-
"@qa-agents/display": "0.0.0",
|
|
33
|
-
"@qa-agents/eslint-config": "0.0.0",
|
|
34
34
|
"@qa-agents/shared": "0.0.0",
|
|
35
35
|
"@qa-agents/typescript-config": "0.0.0"
|
|
36
36
|
},
|