@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.
Files changed (2) hide show
  1. package/dist/cli.js +84 -54
  2. 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 = 100;
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(["nothing-to-inspect", "runner-unreachable"]),
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. The image is the runner's whole virtual desktop, browser window and all. ${screenNeedsARunDescription} ${screenNotReadyDescription} ${runnerHasNoScreenDescription} ${retryableRunnerUnreachableDescription}`,
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.15.0",
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.30.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: 60000 };
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
- const failure = result.value;
357284
- const { failureReason } = failure;
357285
- switch (failureReason) {
357286
- case "action-failed":
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=DD39A64EAC42A5D564756E2164756E21
358257
+ //# debugId=A9041D278FF748EF64756E2164756E21
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@qawolf/cli",
3
- "version": "1.15.0",
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.30.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",