@qawolf/cli 1.7.5 → 1.8.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 +138 -10
- package/package.json +2 -2
- package/skills/qawolf-cli/SKILL.md +39 -38
package/dist/cli.js
CHANGED
|
@@ -171390,6 +171390,7 @@ var identityResponse = exports_external.union([
|
|
|
171390
171390
|
]);
|
|
171391
171391
|
// node_modules/@qawolf/api-contracts/dist/v1/ids.js
|
|
171392
171392
|
var defaultIdSchemas = {
|
|
171393
|
+
aiTask: exports_external.string().min(1).describe("The id of the AI task."),
|
|
171393
171394
|
automation: exports_external.string().min(1).describe("The id of the automation."),
|
|
171394
171395
|
environment: exports_external.string().min(1).describe("The id of the environment."),
|
|
171395
171396
|
environmentRef: exports_external.string().min(1).describe("The id or alias of the environment. Aliases require a team API key."),
|
|
@@ -171418,6 +171419,7 @@ var makeFlowSelectionSchema = (ids) => exports_external.object({
|
|
|
171418
171419
|
// node_modules/@qawolf/api-contracts/dist/v1/run/index.js
|
|
171419
171420
|
var makeCreateRunContract = (ids) => {
|
|
171420
171421
|
const input = exports_external.object({
|
|
171422
|
+
aiTaskId: ids.aiTask.describe("The AI task whose conversation should receive run status updates.").optional(),
|
|
171421
171423
|
environmentId: ids.environmentRef,
|
|
171422
171424
|
environmentVariables: exports_external.record(exports_external.string(), exports_external.string()).optional(),
|
|
171423
171425
|
ignoreRules: exports_external.boolean().default(false),
|
|
@@ -171434,6 +171436,64 @@ var makeCreateRunContract = (ids) => {
|
|
|
171434
171436
|
};
|
|
171435
171437
|
};
|
|
171436
171438
|
|
|
171439
|
+
// node_modules/@qawolf/api-contracts/dist/v1/runner/browserAction.js
|
|
171440
|
+
var maxScreenCoordinate = 20000;
|
|
171441
|
+
var screenCoordinateSchema = exports_external.int().min(0).max(maxScreenCoordinate);
|
|
171442
|
+
var screenPointSchema = exports_external.strictObject({
|
|
171443
|
+
x: screenCoordinateSchema,
|
|
171444
|
+
y: screenCoordinateSchema
|
|
171445
|
+
});
|
|
171446
|
+
var maxScrollDelta = 5000;
|
|
171447
|
+
var scrollDeltaSchema = exports_external.int().min(-maxScrollDelta).max(maxScrollDelta);
|
|
171448
|
+
var maxTypedTextLength = 200;
|
|
171449
|
+
var maxKeypressKeys = 10;
|
|
171450
|
+
var maxKeyNameLength = 32;
|
|
171451
|
+
var minDragPathPoints = 2;
|
|
171452
|
+
var maxDragPathPoints = 100;
|
|
171453
|
+
var maxNavigateUrlLength = 2048;
|
|
171454
|
+
var navigableUrlSchema = exports_external.url({ protocol: /^https?$/ }).max(maxNavigateUrlLength);
|
|
171455
|
+
var browserActionSchema = exports_external.discriminatedUnion("type", [
|
|
171456
|
+
exports_external.strictObject({
|
|
171457
|
+
button: exports_external.literal(["left", "right", "wheel", "back", "forward"]),
|
|
171458
|
+
type: exports_external.literal("click"),
|
|
171459
|
+
x: screenCoordinateSchema,
|
|
171460
|
+
y: screenCoordinateSchema
|
|
171461
|
+
}),
|
|
171462
|
+
exports_external.strictObject({
|
|
171463
|
+
type: exports_external.literal("double_click"),
|
|
171464
|
+
x: screenCoordinateSchema,
|
|
171465
|
+
y: screenCoordinateSchema
|
|
171466
|
+
}),
|
|
171467
|
+
exports_external.strictObject({
|
|
171468
|
+
scroll_x: scrollDeltaSchema,
|
|
171469
|
+
scroll_y: scrollDeltaSchema,
|
|
171470
|
+
type: exports_external.literal("scroll"),
|
|
171471
|
+
x: screenCoordinateSchema,
|
|
171472
|
+
y: screenCoordinateSchema
|
|
171473
|
+
}),
|
|
171474
|
+
exports_external.strictObject({
|
|
171475
|
+
type: exports_external.literal("move"),
|
|
171476
|
+
x: screenCoordinateSchema,
|
|
171477
|
+
y: screenCoordinateSchema
|
|
171478
|
+
}),
|
|
171479
|
+
exports_external.strictObject({
|
|
171480
|
+
path: exports_external.array(screenPointSchema).min(minDragPathPoints).max(maxDragPathPoints),
|
|
171481
|
+
type: exports_external.literal("drag")
|
|
171482
|
+
}),
|
|
171483
|
+
exports_external.strictObject({
|
|
171484
|
+
keys: exports_external.array(exports_external.string().min(1).max(maxKeyNameLength)).min(1).max(maxKeypressKeys),
|
|
171485
|
+
type: exports_external.literal("keypress")
|
|
171486
|
+
}),
|
|
171487
|
+
exports_external.strictObject({
|
|
171488
|
+
type: exports_external.literal("navigate"),
|
|
171489
|
+
url: navigableUrlSchema
|
|
171490
|
+
}),
|
|
171491
|
+
exports_external.strictObject({
|
|
171492
|
+
text: exports_external.string().min(1).max(maxTypedTextLength),
|
|
171493
|
+
type: exports_external.literal("type")
|
|
171494
|
+
})
|
|
171495
|
+
]);
|
|
171496
|
+
|
|
171437
171497
|
// node_modules/@qawolf/api-contracts/dist/v1/runner/environment.js
|
|
171438
171498
|
var reservedRunEnvironmentVariablePrefix = "QAWOLF_";
|
|
171439
171499
|
function refusalForRunEnvironmentVariableName(name) {
|
|
@@ -171567,6 +171627,54 @@ var runFilesSchema = exports_external.record(exports_external.string(), exports_
|
|
|
171567
171627
|
error: `The files in one request may carry at most ${maxRunFilesByteLength} bytes in total.`
|
|
171568
171628
|
});
|
|
171569
171629
|
|
|
171630
|
+
// node_modules/@qawolf/api-contracts/dist/v1/runner/screen.js
|
|
171631
|
+
var runnerScreenNotReadySchema = exports_external.object({
|
|
171632
|
+
outcome: exports_external.literal("screen-not-ready")
|
|
171633
|
+
});
|
|
171634
|
+
var screenNotReadyDescription = "`screen-not-ready` if the runner has a screen that cannot serve this instant. Retry in a second or two: the desktop restarts when a run changes the display size, and it serves one see-or-act request at a time, so a screenshot or action already in flight is the usual reason. Do not submit a run to clear this — a run may restart the display and discard what is on it.";
|
|
171635
|
+
var runnerScreenNeedsARunSchema = exports_external.object({
|
|
171636
|
+
outcome: exports_external.literal("screen-needs-a-run")
|
|
171637
|
+
});
|
|
171638
|
+
var screenNeedsARunDescription = "`screen-needs-a-run` if the runner has not run anything yet, so its virtual desktop has never started. Waiting will not change this and retrying is pointless — call `runner.runFlow` on the runner, then ask for the screen again. Evaluating a snippet does not start the desktop.";
|
|
171639
|
+
var runnerHasNoScreenSchema = exports_external.object({
|
|
171640
|
+
outcome: exports_external.literal("runner-has-no-screen")
|
|
171641
|
+
});
|
|
171642
|
+
var runnerHasNoScreenDescription = "`runner-has-no-screen` if this runner is not one that runs a browser on a virtual desktop. Nothing about it can be seen or driven, and retrying will never help — launch a `node20WithPlaywright` runner instead.";
|
|
171643
|
+
|
|
171644
|
+
// node_modules/@qawolf/api-contracts/dist/v1/runner/unreachable.js
|
|
171645
|
+
var runnerUnreachableSchema = exports_external.object({
|
|
171646
|
+
outcome: exports_external.literal("runner-unreachable")
|
|
171647
|
+
});
|
|
171648
|
+
var retryableRunnerUnreachableDescription = "`runner-unreachable` if the runner could not be reached: it may still be starting, it may have terminated after inactivity, or it may be too busy to answer. Nothing was changed, so retrying is safe; if it persists, launch the runner again.";
|
|
171649
|
+
|
|
171650
|
+
// node_modules/@qawolf/api-contracts/dist/v1/runner/performAction.js
|
|
171651
|
+
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.";
|
|
171652
|
+
var maxActionErrorMessageLength = 1000;
|
|
171653
|
+
var makePerformActionOnRunnerContract = () => {
|
|
171654
|
+
const input = exports_external.object({
|
|
171655
|
+
action: browserActionSchema.describe("The action to perform. Coordinates are pixels on the screenshot's own coordinate space."),
|
|
171656
|
+
id: runnerIdSchema.describe("Id of the runner to act on.")
|
|
171657
|
+
});
|
|
171658
|
+
const output = exports_external.discriminatedUnion("outcome", [
|
|
171659
|
+
exports_external.object({ outcome: exports_external.literal("performed") }),
|
|
171660
|
+
exports_external.object({
|
|
171661
|
+
errorMessage: exports_external.string().max(maxActionErrorMessageLength).describe("What stopped the action from taking effect."),
|
|
171662
|
+
outcome: exports_external.literal("action-failed")
|
|
171663
|
+
}),
|
|
171664
|
+
runnerScreenNeedsARunSchema,
|
|
171665
|
+
runnerScreenNotReadySchema,
|
|
171666
|
+
runnerHasNoScreenSchema,
|
|
171667
|
+
runnerUnreachableSchema
|
|
171668
|
+
]);
|
|
171669
|
+
return {
|
|
171670
|
+
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). \`performed\` if the action took effect. \`action-failed\`, with a reason, if it reached the runner and did not take effect. ${screenNeedsARunDescription} ${screenNotReadyDescription} A \`navigate\` does not go through the screen, so a screen that is not ready does not stop it — but it still needs the runner to have run something, and until then it answers \`action-failed\` rather than \`screen-needs-a-run\`. ${runnerHasNoScreenDescription} ${unreachableDescription}`,
|
|
171671
|
+
input,
|
|
171672
|
+
kind: "write",
|
|
171673
|
+
name: "runner.performAction",
|
|
171674
|
+
output
|
|
171675
|
+
};
|
|
171676
|
+
};
|
|
171677
|
+
|
|
171570
171678
|
// node_modules/@qawolf/api-contracts/dist/v1/automate/index.js
|
|
171571
171679
|
var makeAutomateContract = (ids) => {
|
|
171572
171680
|
const input = exports_external.object({
|
|
@@ -172042,12 +172150,6 @@ var makeGetRunContract = (ids) => {
|
|
|
172042
172150
|
};
|
|
172043
172151
|
};
|
|
172044
172152
|
|
|
172045
|
-
// node_modules/@qawolf/api-contracts/dist/v1/runner/unreachable.js
|
|
172046
|
-
var runnerUnreachableSchema = exports_external.object({
|
|
172047
|
-
outcome: exports_external.literal("runner-unreachable")
|
|
172048
|
-
});
|
|
172049
|
-
var retryableRunnerUnreachableDescription = "`runner-unreachable` if the runner could not be reached: it may still be starting, it may have terminated after inactivity, or it may be too busy to answer. Nothing was changed, so retrying is safe; if it persists, launch the runner again.";
|
|
172050
|
-
|
|
172051
172153
|
// node_modules/@qawolf/api-contracts/dist/v1/runner/evaluateSnippet.js
|
|
172052
172154
|
var maxSnippetCodeLength = 64 * 1024;
|
|
172053
172155
|
var makeEvaluateSnippetOnRunnerContract = () => {
|
|
@@ -172165,6 +172267,30 @@ var makeRunFlowOnRunnerContract = () => {
|
|
|
172165
172267
|
};
|
|
172166
172268
|
};
|
|
172167
172269
|
|
|
172270
|
+
// node_modules/@qawolf/api-contracts/dist/v1/runner/takeScreenshot.js
|
|
172271
|
+
var makeTakeScreenshotOnRunnerContract = () => {
|
|
172272
|
+
const input = exports_external.object({
|
|
172273
|
+
id: runnerIdSchema.describe("Id of the runner to take a screenshot of.")
|
|
172274
|
+
});
|
|
172275
|
+
const output = exports_external.discriminatedUnion("outcome", [
|
|
172276
|
+
exports_external.object({
|
|
172277
|
+
imageJpegBase64: exports_external.string().min(1).describe("The screenshot, as a base64-encoded JPEG. Decode it and write the bytes to a `.jpg` file — writing this string to the file leaves you with base64 text rather than an image."),
|
|
172278
|
+
outcome: exports_external.literal("captured")
|
|
172279
|
+
}),
|
|
172280
|
+
runnerScreenNeedsARunSchema,
|
|
172281
|
+
runnerScreenNotReadySchema,
|
|
172282
|
+
runnerHasNoScreenSchema,
|
|
172283
|
+
runnerUnreachableSchema
|
|
172284
|
+
]);
|
|
172285
|
+
return {
|
|
172286
|
+
description: `Take one screenshot of an interactive runner's screen. The image is the runner's whole virtual desktop, browser window and all. ${screenNeedsARunDescription} ${screenNotReadyDescription} ${runnerHasNoScreenDescription} ${retryableRunnerUnreachableDescription}`,
|
|
172287
|
+
input,
|
|
172288
|
+
kind: "read",
|
|
172289
|
+
name: "runner.takeScreenshot",
|
|
172290
|
+
output
|
|
172291
|
+
};
|
|
172292
|
+
};
|
|
172293
|
+
|
|
172168
172294
|
// node_modules/@qawolf/api-contracts/dist/v1/tag/list.js
|
|
172169
172295
|
var makeListTagsContract = (ids) => {
|
|
172170
172296
|
const input = exports_external.object({
|
|
@@ -172221,9 +172347,11 @@ var makeContractsV1 = (ids) => {
|
|
|
172221
172347
|
runner: {
|
|
172222
172348
|
evaluateSnippet: makeEvaluateSnippetOnRunnerContract(),
|
|
172223
172349
|
launch: makeLaunchRunnerContract(),
|
|
172350
|
+
performAction: makePerformActionOnRunnerContract(),
|
|
172224
172351
|
readJournal: makeReadRunnerJournalContract(),
|
|
172225
172352
|
runFlow: makeRunFlowOnRunnerContract(),
|
|
172226
|
-
stop: makeStopRunnerContract()
|
|
172353
|
+
stop: makeStopRunnerContract(),
|
|
172354
|
+
takeScreenshot: makeTakeScreenshotOnRunnerContract()
|
|
172227
172355
|
},
|
|
172228
172356
|
tag: {
|
|
172229
172357
|
create: makeCreateTagContract(),
|
|
@@ -174742,7 +174870,7 @@ function startUpdateCheck(deps) {
|
|
|
174742
174870
|
// package.json
|
|
174743
174871
|
var package_default = {
|
|
174744
174872
|
name: "@qawolf/cli",
|
|
174745
|
-
version: "1.
|
|
174873
|
+
version: "1.8.0",
|
|
174746
174874
|
description: "Run and manage QA Wolf flows from the terminal, CI, or an AI agent",
|
|
174747
174875
|
keywords: [
|
|
174748
174876
|
"automation",
|
|
@@ -174802,7 +174930,7 @@ var package_default = {
|
|
|
174802
174930
|
"@clack/prompts": "1.5.1",
|
|
174803
174931
|
"@napi-rs/keyring": "1.3.0",
|
|
174804
174932
|
"@oxc-node/core": "0.1.0",
|
|
174805
|
-
"@qawolf/api-contracts": "0.
|
|
174933
|
+
"@qawolf/api-contracts": "0.24.0",
|
|
174806
174934
|
"@qawolf/emails": "1.1.1",
|
|
174807
174935
|
"@qawolf/flow-targets": "1.0.0",
|
|
174808
174936
|
"@qawolf/flows": "0.1.4",
|
|
@@ -184967,4 +185095,4 @@ createProgram({ signals }).parseAsync().catch(() => {
|
|
|
184967
185095
|
process.exitCode = 1;
|
|
184968
185096
|
}).finally(() => flushAndExit(typeof process.exitCode === "number" ? process.exitCode : 0));
|
|
184969
185097
|
|
|
184970
|
-
//# debugId=
|
|
185098
|
+
//# debugId=E21CB4505E563EFF64756E2164756E21
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@qawolf/cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.8.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.24.0",
|
|
64
64
|
"@qawolf/emails": "1.1.1",
|
|
65
65
|
"@qawolf/flow-targets": "1.0.0",
|
|
66
66
|
"@qawolf/flows": "0.1.4",
|
|
@@ -68,44 +68,45 @@ current branch.
|
|
|
68
68
|
|
|
69
69
|
<!-- commands-table:start — generated by `bun run generate`, do not edit -->
|
|
70
70
|
|
|
71
|
-
| Command | Kind | What it does
|
|
72
|
-
| -------------------------------------- | -------------------------- |
|
|
73
|
-
| `qawolf auth login` | local | Authenticate with your QA Wolf API key
|
|
74
|
-
| `qawolf auth logout` | local | Remove stored credentials
|
|
75
|
-
| `qawolf auth whoami` | read | Show authentication status
|
|
76
|
-
| `qawolf automate` | write | Request automation for draft flows. First create a named local .flow.ts draft for every requested journey that does not already have a matching draft; never reuse a generic starter or placeholder. Each new draft must start with a JSDoc Goal: description, import flow from @qawolf/flows/web, and use export default flow(...); a comment-only file or direct test(...) call is not a valid draft. Commit and push all changes with Git to publish them, then list remote drafts to resolve every selected ID. Do not use patch to create or rename a selected flow. Finally make one automation request containing all requested flow IDs.
|
|
77
|
-
| `qawolf doctor` | local | Diagnose problems running flows locally
|
|
78
|
-
| `qawolf environment create` | write | Create an environment on the caller's team and return it in the environment.get shape.
|
|
79
|
-
| `qawolf environment deleteVariable` | write | Remove one environment variable by name. Succeeds whether or not the variable existed.
|
|
80
|
-
| `qawolf environment find` | read | List the team's environments, newest first.
|
|
81
|
-
| `qawolf environment get` | read | Read a single environment's name, kind, health status, run concurrency limit, and termination state.
|
|
82
|
-
| `qawolf environment getVariable` | read | Read the values of named environment variables in one call. Values are secrets. Names that do not exist go to missingNames and do not fail the call.
|
|
83
|
-
| `qawolf environment listVariableNames` | read | Use this to answer which QA Wolf environment variables are available to test code. Returns names only; values never leave the server.
|
|
84
|
-
| `qawolf environment setVariable` | write | Create or replace an environment variable. If the user asks to create one for "my email" without naming it, use DEFAULT_ENVIRONMENT_EMAIL. The value is never returned.
|
|
85
|
-
| `qawolf environment update` | write | Update an environment owned by the caller's team and return it in the environment.get shape. Omitted fields remain unchanged.
|
|
86
|
-
| `qawolf flow addTag` | write | Assign an existing tag to the selected flows. Create tags with tag.create.
|
|
87
|
-
| `qawolf flow update` | write | Move a flow between draft and active readiness. The other statuses shown in the app are derived and cannot be set.
|
|
88
|
-
| `qawolf flows list` | local (read with --remote) | List flows matching [pattern] from the local project, or from a QA Wolf environment with --remote
|
|
89
|
-
| `qawolf flows pull` | read | Download an environment's flows into the local .qawolf/<env>/ cache
|
|
90
|
-
| `qawolf flows run` | local (read with --env) | Run flows matching [pattern], or every flow when omitted; with --env, pull missing flows from that QA Wolf environment
|
|
91
|
-
| `qawolf init` | local | Scaffold a QA Wolf project in the current directory
|
|
92
|
-
| `qawolf install` | local | Install every runtime dependency the project's flows need
|
|
93
|
-
| `qawolf install android` | local | Install Android system images, AVDs, and the Appium driver used by the project's Android flows
|
|
94
|
-
| `qawolf install browsers` | local | Install Playwright browsers used by the project's web flows
|
|
95
|
-
| `qawolf install clear` | local | Remove the managed runtime cache (all installed runtime versions)
|
|
96
|
-
| `qawolf issue create` | write | Create a bug or coverage request issue for the caller's team. Maintenance issues cannot be created through the public API.
|
|
97
|
-
| `qawolf issue find` | read | List the team's bug reports, maintenance reports, or coverage requests, newest first.
|
|
98
|
-
| `qawolf issue get` | read | Get an issue by id.
|
|
99
|
-
| `qawolf run create` | write | Create a run for the selected flows and/or tags in an environment.
|
|
100
|
-
| `qawolf run find` | read | List an environment's recent runs, newest first.
|
|
101
|
-
| `qawolf run get` | read | Get a run's status, per-flow results, and links.
|
|
102
|
-
| `qawolf runner evaluateSnippet` | write | Evaluate a snippet against whatever the runner's browser is showing right now. Answers whether the snippet ran, and its error if it threw — not the value it evaluated to, so read anything you want back out of the runner's journal (a snippet's `console.log` lands in the `console` stream). A snippet starts no run and leaves no run-scoped journal entries of its own. `runner-unreachable` if the runner could not be reached or could not evaluate: as well as a runner that is still starting, has terminated after inactivity, or is busy, this covers a runner with no live page to evaluate against — which will never clear, so check that the runner you launched is one that runs a browser before retrying. It is NOT proof the snippet did not run: a snippet that outlives the answer window is still executing when you read this, so do not blindly resubmit one that mutates what the page is looking at.
|
|
103
|
-
| `qawolf runner launch` | write | Launch an interactive runner on the caller's team under an id the caller chooses. Launching the same id again returns the runner already running rather than starting a second one, and the same id with a different runnerName is refused. A runner is not permanent: it terminates on its own after a period of inactivity, and launching the same id after that starts and bills a new runner — so read `outcome` to tell which happened.
|
|
104
|
-
| `qawolf runner readJournal` | read | Read a window of one of an interactive runner's journal streams — the newest few, everything after a cursor, or everything belonging to one run. This is how a flow run's outcome and output are followed: `run-status` settles it, `run-logs` and `run-events` carry what it produced, and `recorder` carries the browser actions the runner recorded. A read counts as activity, so working through history does not get the runner reaped underneath you. `runner-unreachable` if the runner could not be reached: it may still be starting, it may have terminated after inactivity, or it may be too busy to answer. Nothing was changed, so retrying is safe; if it persists, launch the runner again.
|
|
105
|
-
| `qawolf runner runFlow` | write | Run a flow on an interactive runner. Answers as soon as the run is accepted, with the id to follow it by — nothing waits for the run to finish. Which browser or device the run needs is read from the flow file's own execution target, so it is not supplied here; when it does not match what the runner is, the call answers `runner-target-mismatch` rather than failing partway through the run. `runner-unreachable` means the answer did not arrive, which is NOT the same as the run not having started: the runner may have accepted it and been too slow to say so, and resubmitting would start a second run that is billed and journalled alongside the first. Read the runner's `run-status` journal stream before resubmitting, and use the newest run id there if one appeared.
|
|
106
|
-
| `qawolf runner stop` | write | Stop an interactive runner on the caller's team. Stopping a runner that is not running succeeds and reports `not-running`, so a retry needs no special handling.
|
|
107
|
-
| `qawolf
|
|
108
|
-
| `qawolf tag
|
|
71
|
+
| Command | Kind | What it does |
|
|
72
|
+
| -------------------------------------- | -------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
73
|
+
| `qawolf auth login` | local | Authenticate with your QA Wolf API key |
|
|
74
|
+
| `qawolf auth logout` | local | Remove stored credentials |
|
|
75
|
+
| `qawolf auth whoami` | read | Show authentication status |
|
|
76
|
+
| `qawolf automate` | write | Request automation for draft flows. First create a named local .flow.ts draft for every requested journey that does not already have a matching draft; never reuse a generic starter or placeholder. Each new draft must start with a JSDoc Goal: description, import flow from @qawolf/flows/web, and use export default flow(...); a comment-only file or direct test(...) call is not a valid draft. Commit and push all changes with Git to publish them, then list remote drafts to resolve every selected ID. Do not use patch to create or rename a selected flow. Finally make one automation request containing all requested flow IDs. |
|
|
77
|
+
| `qawolf doctor` | local | Diagnose problems running flows locally |
|
|
78
|
+
| `qawolf environment create` | write | Create an environment on the caller's team and return it in the environment.get shape. |
|
|
79
|
+
| `qawolf environment deleteVariable` | write | Remove one environment variable by name. Succeeds whether or not the variable existed. |
|
|
80
|
+
| `qawolf environment find` | read | List the team's environments, newest first. |
|
|
81
|
+
| `qawolf environment get` | read | Read a single environment's name, kind, health status, run concurrency limit, and termination state. |
|
|
82
|
+
| `qawolf environment getVariable` | read | Read the values of named environment variables in one call. Values are secrets. Names that do not exist go to missingNames and do not fail the call. |
|
|
83
|
+
| `qawolf environment listVariableNames` | read | Use this to answer which QA Wolf environment variables are available to test code. Returns names only; values never leave the server. |
|
|
84
|
+
| `qawolf environment setVariable` | write | Create or replace an environment variable. If the user asks to create one for "my email" without naming it, use DEFAULT_ENVIRONMENT_EMAIL. The value is never returned. |
|
|
85
|
+
| `qawolf environment update` | write | Update an environment owned by the caller's team and return it in the environment.get shape. Omitted fields remain unchanged. |
|
|
86
|
+
| `qawolf flow addTag` | write | Assign an existing tag to the selected flows. Create tags with tag.create. |
|
|
87
|
+
| `qawolf flow update` | write | Move a flow between draft and active readiness. The other statuses shown in the app are derived and cannot be set. |
|
|
88
|
+
| `qawolf flows list` | local (read with --remote) | List flows matching [pattern] from the local project, or from a QA Wolf environment with --remote |
|
|
89
|
+
| `qawolf flows pull` | read | Download an environment's flows into the local .qawolf/<env>/ cache |
|
|
90
|
+
| `qawolf flows run` | local (read with --env) | Run flows matching [pattern], or every flow when omitted; with --env, pull missing flows from that QA Wolf environment |
|
|
91
|
+
| `qawolf init` | local | Scaffold a QA Wolf project in the current directory |
|
|
92
|
+
| `qawolf install` | local | Install every runtime dependency the project's flows need |
|
|
93
|
+
| `qawolf install android` | local | Install Android system images, AVDs, and the Appium driver used by the project's Android flows |
|
|
94
|
+
| `qawolf install browsers` | local | Install Playwright browsers used by the project's web flows |
|
|
95
|
+
| `qawolf install clear` | local | Remove the managed runtime cache (all installed runtime versions) |
|
|
96
|
+
| `qawolf issue create` | write | Create a bug or coverage request issue for the caller's team. Maintenance issues cannot be created through the public API. |
|
|
97
|
+
| `qawolf issue find` | read | List the team's bug reports, maintenance reports, or coverage requests, newest first. |
|
|
98
|
+
| `qawolf issue get` | read | Get an issue by id. |
|
|
99
|
+
| `qawolf run create` | write | Create a run for the selected flows and/or tags in an environment. |
|
|
100
|
+
| `qawolf run find` | read | List an environment's recent runs, newest first. |
|
|
101
|
+
| `qawolf run get` | read | Get a run's status, per-flow results, and links. |
|
|
102
|
+
| `qawolf runner evaluateSnippet` | write | Evaluate a snippet against whatever the runner's browser is showing right now. Answers whether the snippet ran, and its error if it threw — not the value it evaluated to, so read anything you want back out of the runner's journal (a snippet's `console.log` lands in the `console` stream). A snippet starts no run and leaves no run-scoped journal entries of its own. `runner-unreachable` if the runner could not be reached or could not evaluate: as well as a runner that is still starting, has terminated after inactivity, or is busy, this covers a runner with no live page to evaluate against — which will never clear, so check that the runner you launched is one that runs a browser before retrying. It is NOT proof the snippet did not run: a snippet that outlives the answer window is still executing when you read this, so do not blindly resubmit one that mutates what the page is looking at. |
|
|
103
|
+
| `qawolf runner launch` | write | Launch an interactive runner on the caller's team under an id the caller chooses. Launching the same id again returns the runner already running rather than starting a second one, and the same id with a different runnerName is refused. A runner is not permanent: it terminates on its own after a period of inactivity, and launching the same id after that starts and bills a new runner — so read `outcome` to tell which happened. |
|
|
104
|
+
| `qawolf runner readJournal` | read | Read a window of one of an interactive runner's journal streams — the newest few, everything after a cursor, or everything belonging to one run. This is how a flow run's outcome and output are followed: `run-status` settles it, `run-logs` and `run-events` carry what it produced, and `recorder` carries the browser actions the runner recorded. A read counts as activity, so working through history does not get the runner reaped underneath you. `runner-unreachable` if the runner could not be reached: it may still be starting, it may have terminated after inactivity, or it may be too busy to answer. Nothing was changed, so retrying is safe; if it persists, launch the runner again. |
|
|
105
|
+
| `qawolf runner runFlow` | write | Run a flow on an interactive runner. Answers as soon as the run is accepted, with the id to follow it by — nothing waits for the run to finish. Which browser or device the run needs is read from the flow file's own execution target, so it is not supplied here; when it does not match what the runner is, the call answers `runner-target-mismatch` rather than failing partway through the run. `runner-unreachable` means the answer did not arrive, which is NOT the same as the run not having started: the runner may have accepted it and been too slow to say so, and resubmitting would start a second run that is billed and journalled alongside the first. Read the runner's `run-status` journal stream before resubmitting, and use the newest run id there if one appeared. |
|
|
106
|
+
| `qawolf runner stop` | write | Stop an interactive runner on the caller's team. Stopping a runner that is not running succeeds and reports `not-running`, so a retry needs no special handling. |
|
|
107
|
+
| `qawolf runner takeScreenshot` | read | Take one screenshot of an interactive runner's screen. The image is the runner's whole virtual desktop, browser window and all. `screen-needs-a-run` if the runner has not run anything yet, so its virtual desktop has never started. Waiting will not change this and retrying is pointless — call `runner.runFlow` on the runner, then ask for the screen again. Evaluating a snippet does not start the desktop. `screen-not-ready` if the runner has a screen that cannot serve this instant. Retry in a second or two: the desktop restarts when a run changes the display size, and it serves one see-or-act request at a time, so a screenshot or action already in flight is the usual reason. Do not submit a run to clear this — a run may restart the display and discard what is on it. `runner-has-no-screen` if this runner is not one that runs a browser on a virtual desktop. Nothing about it can be seen or driven, and retrying will never help — launch a `node20WithPlaywright` runner instead. `runner-unreachable` if the runner could not be reached: it may still be starting, it may have terminated after inactivity, or it may be too busy to answer. Nothing was changed, so retrying is safe; if it persists, launch the runner again. |
|
|
108
|
+
| `qawolf tag create` | write | Create a tag on the caller's team. Tags select flows in run.create. |
|
|
109
|
+
| `qawolf tag list` | read | List the team's tags, alphabetical by name. Tag names select flows in run.create. |
|
|
109
110
|
|
|
110
111
|
<!-- commands-table:end -->
|
|
111
112
|
|