@qawolf/cli 1.15.0 → 1.16.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/dist/cli.js +84 -54
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -326098,11 +326098,13 @@ var interactMessages = {
|
|
|
326098
326098
|
actionFlagsWithStdin: '"-" reads the whole action from stdin, so an action flag passed alongside it would be ignored. Pipe the action in on its own, or name the action type and use flags.',
|
|
326099
326099
|
actionMayHaveHappened: "The runner could not be reached, which does not mean the action was not performed: it may have stopped answering mid-action. Take a screenshot before repeating it.",
|
|
326100
326100
|
actionNotJson: `Stdin did not hold a JSON action. Pipe one object, for example '{"type":"click","button":"left","x":480,"y":260}'.`,
|
|
326101
|
+
actionNotSupportedOnMobile: (type) => `A mobile runner has a touchscreen, so it cannot perform ${type} as asked. It taps with a left-button click, swipes with drag, and types into whatever the last tap focused.`,
|
|
326101
326102
|
actionPerformed: (type) => `Performed ${type}.`,
|
|
326102
326103
|
actionAnsweredUnknown: (failureReason) => `The runner answered "${failureReason}", which this version of the CLI does not know how to report. Upgrade with npm install -g @qawolf/cli.`,
|
|
326103
326104
|
screenshotAnsweredUnknown: (failureReason) => `The runner answered "${failureReason}", which this version of the CLI does not know how to report. Upgrade with npm install -g @qawolf/cli.`,
|
|
326104
326105
|
runnerHasNoScreen: "This runner does not run a browser on a virtual desktop, so there is nothing about it to see or drive. Retrying will never help: launch a playwright runner instead.",
|
|
326105
326106
|
runnerHasNoScreenToEvaluate: "The runner could not evaluate the snippet. This covers a runner that is still starting or busy, and also one with no live page to evaluate against: a freshly launched runner has no page until a run opens one, so run a flow on it with qawolf runner run first. If it is not a runner that runs a browser at all, this will never clear. It is not proof the snippet did not run, so do not resubmit one that mutates the page without reading qawolf runner events console first.",
|
|
326107
|
+
inspectNeedsABrowserRunner: "This runner is a mobile device, and element and page HTML are a browser's shapes. Retrying will never help. Launch a playwright runner to inspect one.",
|
|
326106
326108
|
nothingToInspect: (errorMessage2) => `The runner had nothing to inspect${errorMessage2 === undefined ? "" : `: ${errorMessage2}`}. There is no live page, nothing matched the selector, or no variable has that name; a runner cannot tell those apart. Run a flow on it first, or check the selector or name.`,
|
|
326107
326109
|
inspectAnsweredUnknown: (failureReason) => `The runner answered "${failureReason}", which this version of the CLI does not know how to report. Upgrade with npm install -g @qawolf/cli.`,
|
|
326108
326110
|
screenNeedsARun: "This runner has not run anything yet, so its screen has never started. Waiting will not clear this and there is nothing to retry: run a flow on it with qawolf runner run, then ask again. Evaluating a snippet does not start a screen.",
|
|
@@ -342183,7 +342185,7 @@ var makeCreateRunContract = (ids) => {
|
|
|
342183
342185
|
aiTaskId: ids.aiTask.describe("The AI task whose conversation should receive run status updates.").optional(),
|
|
342184
342186
|
environmentId: ids.environmentRef,
|
|
342185
342187
|
environmentVariables: exports_external.record(exports_external.string(), exports_external.string()).optional(),
|
|
342186
|
-
ignoreRules: exports_external.boolean().default(false),
|
|
342188
|
+
ignoreRules: exports_external.boolean().describe("Ignore this team's sequencing rules for this run. By default they are honoured: the flows your selection depends on are added to the run, and flows run in the order the rules require. Set this to run exactly what you selected, in any order.").default(false),
|
|
342187
342189
|
pullRequestNumber: exports_external.number().int().positive().describe("The number of the pull request to associate with the run.").optional(),
|
|
342188
342190
|
repository: exports_external.string().min(1).describe('The owner/name of the repository, e.g. "acme/web".').optional()
|
|
342189
342191
|
}).and(makeFlowSelectionSchema(ids));
|
|
@@ -342272,7 +342274,7 @@ function refusalForRunEnvironmentVariableName(name) {
|
|
|
342272
342274
|
return `${reservedRunEnvironmentVariableName} is reserved by QA Wolf and set for you.`;
|
|
342273
342275
|
return;
|
|
342274
342276
|
}
|
|
342275
|
-
var maxRunEnvironmentVariables =
|
|
342277
|
+
var maxRunEnvironmentVariables = 200;
|
|
342276
342278
|
var maxRunEnvironmentValueLength = 8 * 1024;
|
|
342277
342279
|
var runEnvironmentSchema = exports_external.record(exports_external.string(), exports_external.string().max(maxRunEnvironmentValueLength)).superRefine((environment, refinementContext) => {
|
|
342278
342280
|
for (const name of Object.keys(environment)) {
|
|
@@ -342366,18 +342368,30 @@ var makeInspectOnRunnerContract = () => {
|
|
|
342366
342368
|
}),
|
|
342367
342369
|
exports_external.object({
|
|
342368
342370
|
errorMessage: exports_external.string().optional().describe("What the runner said, when it said anything."),
|
|
342369
|
-
failureReason: exports_external.enum([
|
|
342371
|
+
failureReason: exports_external.enum([
|
|
342372
|
+
"nothing-to-inspect",
|
|
342373
|
+
"runner-is-not-a-browser",
|
|
342374
|
+
"runner-unreachable"
|
|
342375
|
+
]),
|
|
342370
342376
|
outcome: exports_external.literal("failure")
|
|
342371
342377
|
})
|
|
342372
342378
|
]);
|
|
342373
342379
|
return {
|
|
342374
|
-
description: "Inspect one thing on an interactive runner: an element's HTML, the page's HTML simplified for a model, or a top-level variable's value as JSON. `nothing-to-inspect` means the runner had nothing to answer with: no live page, no element matching the selector, or no variable under that name. A runner cannot tell those apart, so it reports the one reason and puts whatever it did say in `errorMessage`. " + retryableRunnerUnreachableDescription,
|
|
342380
|
+
description: "Inspect one thing on an interactive runner: an element's HTML, the page's HTML simplified for a model, or a top-level variable's value as JSON. `nothing-to-inspect` means the runner had nothing to answer with: no live page, no element matching the selector, or no variable under that name. A runner cannot tell those apart, so it reports the one reason and puts whatever it did say in `errorMessage`. `runner-is-not-a-browser` on a mobile runner — call `runner.inspectMobile` for its equivalent surface instead. " + retryableRunnerUnreachableDescription,
|
|
342375
342381
|
input,
|
|
342376
342382
|
kind: "read",
|
|
342377
342383
|
name: "runner.inspect",
|
|
342378
342384
|
output
|
|
342379
342385
|
};
|
|
342380
342386
|
};
|
|
342387
|
+
// node_modules/@qawolf/api-contracts/dist/v1/runner/outcome.js
|
|
342388
|
+
function makeRunnerFailureSchema(reasons) {
|
|
342389
|
+
return exports_external.object({
|
|
342390
|
+
failureReason: exports_external.enum(reasons),
|
|
342391
|
+
outcome: exports_external.literal("failure")
|
|
342392
|
+
});
|
|
342393
|
+
}
|
|
342394
|
+
|
|
342381
342395
|
// node_modules/@qawolf/api-contracts/dist/v1/runner/journal.js
|
|
342382
342396
|
var journalEntrySchema = exports_external.object({
|
|
342383
342397
|
payload: exports_external.unknown(),
|
|
@@ -342434,14 +342448,6 @@ var runFilesSchema = exports_external.record(exports_external.string(), exports_
|
|
|
342434
342448
|
}).refine((files) => runFilesByteLength(files) <= maxRunFilesByteLength, {
|
|
342435
342449
|
error: `The files in one request may carry at most ${maxRunFilesByteLength} bytes in total.`
|
|
342436
342450
|
});
|
|
342437
|
-
// node_modules/@qawolf/api-contracts/dist/v1/runner/outcome.js
|
|
342438
|
-
function makeRunnerFailureSchema(reasons) {
|
|
342439
|
-
return exports_external.object({
|
|
342440
|
-
failureReason: exports_external.enum(reasons),
|
|
342441
|
-
outcome: exports_external.literal("failure")
|
|
342442
|
-
});
|
|
342443
|
-
}
|
|
342444
|
-
|
|
342445
342451
|
// node_modules/@qawolf/api-contracts/dist/v1/runner/screen.js
|
|
342446
342452
|
var screenFailureReasons = [
|
|
342447
342453
|
"runner-has-no-screen",
|
|
@@ -342454,6 +342460,7 @@ var runnerHasNoScreenDescription = "`runner-has-no-screen` if this runner is not
|
|
|
342454
342460
|
|
|
342455
342461
|
// node_modules/@qawolf/api-contracts/dist/v1/runner/performAction.js
|
|
342456
342462
|
var unreachableDescription = "`runner-unreachable` if the runner could not be reached: it may still be starting, it may have terminated after inactivity, or it may have stopped answering mid-action. This does not mean the action was not performed — take a screenshot before repeating it.";
|
|
342463
|
+
var notSupportedOnMobileDescription = "`action-not-supported-on-mobile` if the runner is a mobile device and this action has no touchscreen equivalent: `double_click`, `scroll`, `move`, `keypress` and `navigate`, and a `click` whose `button` is not `left`, are all pointer-device concepts a touchscreen has nothing to offer for. `click` taps, `drag` swipes between its path's first and last point, and `type` types into whatever the last tap focused.";
|
|
342457
342464
|
var maxActionErrorMessageLength = 1000;
|
|
342458
342465
|
var makePerformActionOnRunnerContract = () => {
|
|
342459
342466
|
const input = exports_external.object({
|
|
@@ -342468,6 +342475,7 @@ var makePerformActionOnRunnerContract = () => {
|
|
|
342468
342475
|
}),
|
|
342469
342476
|
makeRunnerFailureSchema([
|
|
342470
342477
|
...screenFailureReasons,
|
|
342478
|
+
"action-not-supported-on-mobile",
|
|
342471
342479
|
runnerUnreachableFailureReason
|
|
342472
342480
|
])
|
|
342473
342481
|
]);
|
|
@@ -342476,7 +342484,7 @@ var makePerformActionOnRunnerContract = () => {
|
|
|
342476
342484
|
failure
|
|
342477
342485
|
]);
|
|
342478
342486
|
return {
|
|
342479
|
-
description: `Perform one raw browser action on an interactive runner: click, double_click, move, drag, scroll, keypress, type, or navigate. Coordinates are whole pixels on the runner's virtual desktop, in the same space as \`runner.takeScreenshot\`. One action per request, and the runner serves one at a time. The action shapes follow the computer-use vocabulary, minus \`screenshot\` (use \`runner.takeScreenshot\`) and \`wait\` (delay on the caller's side). A success means the action took effect. \`action-failed\`, with a reason, if it reached the runner and did not take effect. On a runner image with a browser, the first action on a runner that has never run anything starts its browser and waits for it, so it can take up to a minute to answer — no \`runner.runFlow\` is needed before acting; if the browser is still starting when the wait runs out, the answer is \`screen-not-ready\` and retrying converges. \`screen-needs-a-run\` if the browser could not be started that way — usually a runner whose runs all finished without starting its desktop; call \`runner.runFlow\` with a flow that opens a browser. ${screenNotReadyDescription} A \`navigate\` does not go through the screen, so a screen that is not ready does not stop it. ${runnerHasNoScreenDescription} ${unreachableDescription}`,
|
|
342487
|
+
description: `Perform one raw browser action on an interactive runner: click, double_click, move, drag, scroll, keypress, type, or navigate. Coordinates are whole pixels on the runner's virtual desktop, in the same space as \`runner.takeScreenshot\`. One action per request, and the runner serves one at a time. The action shapes follow the computer-use vocabulary, minus \`screenshot\` (use \`runner.takeScreenshot\`) and \`wait\` (delay on the caller's side). A success means the action took effect. \`action-failed\`, with a reason, if it reached the runner and did not take effect. On a runner image with a browser, the first action on a runner that has never run anything starts its browser and waits for it, so it can take up to a minute to answer — no \`runner.runFlow\` is needed before acting; if the browser is still starting when the wait runs out, the answer is \`screen-not-ready\` and retrying converges. On a mobile runner, the same \`screen-needs-a-run\` and \`screen-not-ready\` outcomes mean no Appium session has started yet, or it did not answer this instant; \`runner.runFlow\` is what starts one, same as a browser. \`screen-needs-a-run\` if the browser could not be started that way — usually a runner whose runs all finished without starting its desktop; call \`runner.runFlow\` with a flow that opens a browser. ${screenNotReadyDescription} A \`navigate\` does not go through the screen, so a screen that is not ready does not stop it. ${runnerHasNoScreenDescription} ${notSupportedOnMobileDescription} ${unreachableDescription}`,
|
|
342480
342488
|
input,
|
|
342481
342489
|
kind: "write",
|
|
342482
342490
|
name: "runner.performAction",
|
|
@@ -343268,7 +343276,7 @@ var makeTakeScreenshotOnRunnerContract = () => {
|
|
|
343268
343276
|
])
|
|
343269
343277
|
]);
|
|
343270
343278
|
return {
|
|
343271
|
-
description: `Take one screenshot of an interactive runner's screen.
|
|
343279
|
+
description: `Take one screenshot of an interactive runner's screen. On a runner with a browser the image is the whole virtual desktop, browser window and all. On a mobile runner it is the device's own screen, re-encoded to JPEG on the pod so this contract reads one image format regardless of runner family. ${screenNeedsARunDescription} ${screenNotReadyDescription} ${runnerHasNoScreenDescription} ${retryableRunnerUnreachableDescription}`,
|
|
343272
343280
|
input,
|
|
343273
343281
|
kind: "read",
|
|
343274
343282
|
name: "runner.takeScreenshot",
|
|
@@ -345866,7 +345874,7 @@ function startUpdateCheck(deps) {
|
|
|
345866
345874
|
// package.json
|
|
345867
345875
|
var package_default = {
|
|
345868
345876
|
name: "@qawolf/cli",
|
|
345869
|
-
version: "1.
|
|
345877
|
+
version: "1.16.0",
|
|
345870
345878
|
description: "Run and manage QA Wolf flows from the terminal, CI, or an AI agent",
|
|
345871
345879
|
keywords: [
|
|
345872
345880
|
"automation",
|
|
@@ -345926,7 +345934,7 @@ var package_default = {
|
|
|
345926
345934
|
"@clack/prompts": "1.5.1",
|
|
345927
345935
|
"@napi-rs/keyring": "1.3.0",
|
|
345928
345936
|
"@oxc-node/core": "0.1.0",
|
|
345929
|
-
"@qawolf/api-contracts": "0.
|
|
345937
|
+
"@qawolf/api-contracts": "0.32.0",
|
|
345930
345938
|
"@qawolf/emails": "1.1.1",
|
|
345931
345939
|
"@qawolf/flow-targets": "1.0.0",
|
|
345932
345940
|
"@qawolf/flows": "0.1.4",
|
|
@@ -356462,7 +356470,7 @@ function readNpmDependencies(packageJsonContent) {
|
|
|
356462
356470
|
}
|
|
356463
356471
|
|
|
356464
356472
|
// src/domains/interactiveRunner/runnerCallOptions.ts
|
|
356465
|
-
var runnerCallOptions = { timeoutMs:
|
|
356473
|
+
var runnerCallOptions = { timeoutMs: 90000 };
|
|
356466
356474
|
|
|
356467
356475
|
// src/domains/interactiveRunner/runnerIds.ts
|
|
356468
356476
|
function parseRunnerId(id) {
|
|
@@ -357021,6 +357029,11 @@ async function handleRunnerInspect(ctx, options, deps) {
|
|
|
357021
357029
|
error: interactiveRunnerMessages.nothingToInspect(failure.errorMessage),
|
|
357022
357030
|
exitCode: exitCodes.invalidArgs
|
|
357023
357031
|
};
|
|
357032
|
+
case "runner-is-not-a-browser":
|
|
357033
|
+
return {
|
|
357034
|
+
error: interactiveRunnerMessages.inspectNeedsABrowserRunner,
|
|
357035
|
+
exitCode: exitCodes.invalidArgs
|
|
357036
|
+
};
|
|
357024
357037
|
case "runner-unreachable":
|
|
357025
357038
|
return {
|
|
357026
357039
|
error: interactiveRunnerMessages.runnerUnreachable,
|
|
@@ -357238,6 +357251,50 @@ function parseBrowserAction(candidate) {
|
|
|
357238
357251
|
return { action: parsed.data, ok: true };
|
|
357239
357252
|
}
|
|
357240
357253
|
|
|
357254
|
+
// src/domains/interactiveRunner/performActionFailure.ts
|
|
357255
|
+
function describePerformActionFailure(options) {
|
|
357256
|
+
const { actionType, failure } = options;
|
|
357257
|
+
const { failureReason } = failure;
|
|
357258
|
+
switch (failureReason) {
|
|
357259
|
+
case "action-failed":
|
|
357260
|
+
return {
|
|
357261
|
+
error: interactiveRunnerMessages.actionFailed(failure.errorMessage),
|
|
357262
|
+
exitCode: exitCodes.testFailure
|
|
357263
|
+
};
|
|
357264
|
+
case "action-not-supported-on-mobile":
|
|
357265
|
+
return {
|
|
357266
|
+
error: interactiveRunnerMessages.actionNotSupportedOnMobile(actionType),
|
|
357267
|
+
exitCode: exitCodes.invalidArgs
|
|
357268
|
+
};
|
|
357269
|
+
case "screen-needs-a-run":
|
|
357270
|
+
return {
|
|
357271
|
+
error: interactiveRunnerMessages.screenNeedsARun,
|
|
357272
|
+
exitCode: exitCodes.invalidArgs
|
|
357273
|
+
};
|
|
357274
|
+
case "screen-not-ready":
|
|
357275
|
+
return {
|
|
357276
|
+
error: interactiveRunnerMessages.screenNotReady,
|
|
357277
|
+
exitCode: exitCodes.network
|
|
357278
|
+
};
|
|
357279
|
+
case "runner-has-no-screen":
|
|
357280
|
+
return {
|
|
357281
|
+
error: interactiveRunnerMessages.runnerHasNoScreen,
|
|
357282
|
+
exitCode: exitCodes.invalidArgs
|
|
357283
|
+
};
|
|
357284
|
+
case "runner-unreachable":
|
|
357285
|
+
return {
|
|
357286
|
+
error: interactiveRunnerMessages.actionMayHaveHappened,
|
|
357287
|
+
exitCode: exitCodes.network
|
|
357288
|
+
};
|
|
357289
|
+
default: {
|
|
357290
|
+
return {
|
|
357291
|
+
error: interactiveRunnerMessages.actionAnsweredUnknown(failureReason),
|
|
357292
|
+
exitCode: exitCodes.network
|
|
357293
|
+
};
|
|
357294
|
+
}
|
|
357295
|
+
}
|
|
357296
|
+
}
|
|
357297
|
+
|
|
357241
357298
|
// src/domains/interactiveRunner/performAction.ts
|
|
357242
357299
|
var stdinArgument2 = "-";
|
|
357243
357300
|
async function readAction(type, flags, deps) {
|
|
@@ -357280,41 +357337,10 @@ async function handleRunnerAct(ctx, options, deps) {
|
|
|
357280
357337
|
ctx.ui.output({ action: built.action, outcome: "success" }, interactiveRunnerMessages.actionPerformed(built.action.type));
|
|
357281
357338
|
return;
|
|
357282
357339
|
}
|
|
357283
|
-
|
|
357284
|
-
|
|
357285
|
-
|
|
357286
|
-
|
|
357287
|
-
return {
|
|
357288
|
-
error: interactiveRunnerMessages.actionFailed(failure.errorMessage),
|
|
357289
|
-
exitCode: exitCodes.testFailure
|
|
357290
|
-
};
|
|
357291
|
-
case "screen-needs-a-run":
|
|
357292
|
-
return {
|
|
357293
|
-
error: interactiveRunnerMessages.screenNeedsARun,
|
|
357294
|
-
exitCode: exitCodes.invalidArgs
|
|
357295
|
-
};
|
|
357296
|
-
case "screen-not-ready":
|
|
357297
|
-
return {
|
|
357298
|
-
error: interactiveRunnerMessages.screenNotReady,
|
|
357299
|
-
exitCode: exitCodes.network
|
|
357300
|
-
};
|
|
357301
|
-
case "runner-has-no-screen":
|
|
357302
|
-
return {
|
|
357303
|
-
error: interactiveRunnerMessages.runnerHasNoScreen,
|
|
357304
|
-
exitCode: exitCodes.invalidArgs
|
|
357305
|
-
};
|
|
357306
|
-
case "runner-unreachable":
|
|
357307
|
-
return {
|
|
357308
|
-
error: interactiveRunnerMessages.actionMayHaveHappened,
|
|
357309
|
-
exitCode: exitCodes.network
|
|
357310
|
-
};
|
|
357311
|
-
default: {
|
|
357312
|
-
return {
|
|
357313
|
-
error: interactiveRunnerMessages.actionAnsweredUnknown(failureReason),
|
|
357314
|
-
exitCode: exitCodes.network
|
|
357315
|
-
};
|
|
357316
|
-
}
|
|
357317
|
-
}
|
|
357340
|
+
return describePerformActionFailure({
|
|
357341
|
+
actionType: built.action.type,
|
|
357342
|
+
failure: result.value
|
|
357343
|
+
});
|
|
357318
357344
|
}
|
|
357319
357345
|
|
|
357320
357346
|
// src/domains/interactiveRunner/takeScreenshot.ts
|
|
@@ -357969,6 +357995,9 @@ function buildRunFileDelta(options) {
|
|
|
357969
357995
|
}
|
|
357970
357996
|
const heldHashes = new Map(held.files.map((entry) => [entry.path, entry.contentHash]));
|
|
357971
357997
|
const alwaysSent = new Set([options.entryPointPath, runPackageJsonPath]);
|
|
357998
|
+
if (options.selectionPath !== undefined) {
|
|
357999
|
+
alwaysSent.add(options.selectionPath);
|
|
358000
|
+
}
|
|
357972
358001
|
const files = {};
|
|
357973
358002
|
const unchangedFiles = {};
|
|
357974
358003
|
for (const [path9, content] of Object.entries(options.files)) {
|
|
@@ -358056,7 +358085,8 @@ async function submitRun(ctx, options, deps) {
|
|
|
358056
358085
|
entryPointPath: options.entryPointPath,
|
|
358057
358086
|
files: options.files,
|
|
358058
358087
|
held,
|
|
358059
|
-
runnerId: options.resolved.runnerId
|
|
358088
|
+
runnerId: options.resolved.runnerId,
|
|
358089
|
+
selectionPath: options.selection?.path
|
|
358060
358090
|
});
|
|
358061
358091
|
const first2 = await sendRunFlowRequest(ctx, options, delta);
|
|
358062
358092
|
if (first2.type === "needs-full-sync") {
|
|
@@ -358224,4 +358254,4 @@ createProgram({ signals }).parseAsync().catch(() => {
|
|
|
358224
358254
|
process.exitCode = 1;
|
|
358225
358255
|
}).finally(() => flushAndExit(typeof process.exitCode === "number" ? process.exitCode : 0));
|
|
358226
358256
|
|
|
358227
|
-
//# debugId=
|
|
358257
|
+
//# debugId=A9041D278FF748EF64756E2164756E21
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@qawolf/cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.16.0",
|
|
4
4
|
"description": "Run and manage QA Wolf flows from the terminal, CI, or an AI agent",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"automation",
|
|
@@ -60,7 +60,7 @@
|
|
|
60
60
|
"@clack/prompts": "1.5.1",
|
|
61
61
|
"@napi-rs/keyring": "1.3.0",
|
|
62
62
|
"@oxc-node/core": "0.1.0",
|
|
63
|
-
"@qawolf/api-contracts": "0.
|
|
63
|
+
"@qawolf/api-contracts": "0.32.0",
|
|
64
64
|
"@qawolf/emails": "1.1.1",
|
|
65
65
|
"@qawolf/flow-targets": "1.0.0",
|
|
66
66
|
"@qawolf/flows": "0.1.4",
|