@qawolf/cli 1.30.0 → 1.31.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 CHANGED
@@ -8382,12 +8382,13 @@ function isTimeoutError(err) {
8382
8382
  }
8383
8383
  var missingPackagePattern = /Cannot find (?:package|module) '([^']+)'/;
8384
8384
  var pathLikeSpecifierPattern = /^(?:\.|\/|[A-Za-z]:[\\/])/;
8385
- function extractMissingPackage(text) {
8385
+ var sourceFileSpecifierPattern = /\.(?:[cm]?[jt]sx?)$/;
8386
+ function extractMissingSpecifier(text) {
8386
8387
  const specifier = missingPackagePattern.exec(text)?.[1];
8387
8388
  if (specifier === undefined || pathLikeSpecifierPattern.test(specifier)) {
8388
8389
  return;
8389
8390
  }
8390
- return specifier;
8391
+ return sourceFileSpecifierPattern.test(specifier) ? { kind: "path-alias", specifier } : { kind: "package", specifier };
8391
8392
  }
8392
8393
 
8393
8394
  // src/core/formatSeconds.ts
@@ -8435,7 +8436,14 @@ var authErrorMessages = {
8435
8436
  rejected401: (noun) => `QA Wolf API rejected the${noun ? ` ${noun}` : ""} request (HTTP 401). Check your API key.`,
8436
8437
  rejected402: (noun) => `QA Wolf API refused the${noun ? ` ${noun}` : ""} request (HTTP 402): billing prevented it.`,
8437
8438
  rejected403: (noun) => `QA Wolf API rejected the${noun ? ` ${noun}` : ""} request (HTTP 403). Check that your API key has access to this environment.`,
8438
- notFound404: (noun) => `QA Wolf API could not find ${noun ? `${noun} for that environment` : "that environment"} (HTTP 404). Check the --env value.`,
8439
+ notFound404Environment: (noun) => `QA Wolf API could not find ${noun ? `${noun} for that environment` : "that environment"} (HTTP 404). Check the --env value.`,
8440
+ notFound404Runner: (runnerId) => runnerId === undefined ? "That runner is not running (HTTP 404)." : `Runner ${runnerId} is not running (HTTP 404).`,
8441
+ runnerIsGone: "It was never launched, or it has since been terminated or idled out.",
8442
+ launchTheRunner: (runnerId) => runnerId === undefined ? "Launch one with qawolf runner launch --id <id>, or name a running one with --runner." : `Launch it with qawolf runner launch --id ${runnerId}, or send this to a different runner with --runner.`,
8443
+ notFound404Run: (runId) => `QA Wolf has no run ${runId ?? "by that id"} on this team (HTTP 404).`,
8444
+ runIdMayBeRunnerLocal: (runId) => `A run id printed by qawolf runner run belongs to that runner rather than to the platform, so this command cannot resolve it. Read that run with qawolf runner events run-status --run ${runId ?? "<id>"}.`,
8445
+ notFound404Record: (noun, id) => `QA Wolf has no ${noun} ${id} (HTTP 404).`,
8446
+ notFound404: (noun) => noun === undefined ? "QA Wolf found nothing matching the request (HTTP 404)." : `QA Wolf found nothing matching the ${noun} request (HTTP 404).`,
8439
8447
  failedWithStatus: (status, noun) => `QA Wolf API${noun ? ` ${noun}` : ""} request failed (HTTP ${status}).`,
8440
8448
  networkUnreachable: (baseUrl, noun) => `Could not reach the QA Wolf API at ${baseUrl}${noun ? ` to fetch ${noun}` : ""}. Check your network connection and QAWOLF_HOST_URL.`,
8441
8449
  timedOut: (timeoutMs, noun) => `The QA Wolf API${noun ? ` ${noun}` : ""} request timed out after ${formatSeconds(timeoutMs)}. The work may still be finishing on the platform.`,
@@ -8888,7 +8896,14 @@ var lifecycleMessages = {
8888
8896
  terminated: (id) => `Terminated runner ${id}.`,
8889
8897
  runStopped: (id) => `Stopped the run on runner ${id}. The runner is still up, on whatever page the run reached.`,
8890
8898
  nothingToStop: (id) => `Runner ${id} had nothing to stop. The run had already finished, or none had been submitted.`,
8891
- runnerUnreachable: "The runner could not be reached. It may still be starting, or it may have terminated after inactivity. Retry, or launch it again."
8899
+ runnerUnreachable: "The runner could not be reached. It may still be starting, or it may have terminated after inactivity. Retry, or launch it again.",
8900
+ runnerIdCameFrom: (id, source) => ({
8901
+ environment: `The id ${id} came from QAWOLF_RUNNER_ID.`,
8902
+ flag: `The id ${id} came from --runner.`,
8903
+ given: `The id ${id} is the one this call named.`,
8904
+ launched: `Runner ${id} was launched for this command.`,
8905
+ stored: `The id ${id} came from the runner this directory last launched, recorded in .qawolf.`
8906
+ })[source]
8892
8907
  };
8893
8908
 
8894
8909
  // src/core/messages/interactiveRunner/list.ts
@@ -8987,7 +9002,9 @@ ${dir}`,
8987
9002
  ].join(`
8988
9003
  `),
8989
9004
  outerHopCarriedOver: (names) => `Carried over ${pluralize(names.length, "undeclared package")} from the project node_modules: ${listNames(names)}. Declare them in package.json "dependencies".`,
8990
- moduleNotFoundHint: (pkg, projectDir) => projectDir === undefined ? `Hint: '${pkg}' could not be resolved. Run from within your flows project so its dependencies can be found.` : `Hint: '${pkg}' could not be resolved. Ensure it is declared in ${projectDir}/package.json "dependencies" and run npm install in that project.`
9005
+ moduleNotFoundHint: (pkg, projectDir) => projectDir === undefined ? `Hint: '${pkg}' could not be resolved. Run from within your flows project so its dependencies can be found.` : `Hint: '${pkg}' could not be resolved. Ensure it is declared in ${projectDir}/package.json "dependencies" and run npm install in that project.`,
9006
+ tsconfigUnparsedNotice: (projectDir) => `Not resolving path aliases: ${projectDir}/tsconfig.json is not valid JSON. Comments and trailing commas are not supported, here or on the platform. Remove them so "compilerOptions.paths" can be read.`,
9007
+ pathAliasNotFoundHint: (specifier, projectDir) => projectDir === undefined ? `Hint: '${specifier}' looks like a tsconfig path alias. Run from within your flows project so its tsconfig.json can be found.` : `Hint: '${specifier}' looks like a tsconfig path alias. Ensure "compilerOptions.paths" in ${projectDir}/tsconfig.json maps it to a file that exists.`
8991
9008
  };
8992
9009
  // src/core/messages/updateCheck.ts
8993
9010
  var updateCheckMessages = {
@@ -9111,7 +9128,8 @@ var exitCodes = {
9111
9128
  network: 4,
9112
9129
  config: 5,
9113
9130
  timeout: 6,
9114
- payment: 7
9131
+ payment: 7,
9132
+ notFound: 8
9115
9133
  };
9116
9134
  function exit(code, message, proc = process) {
9117
9135
  if (message !== undefined && message.length > 0) {
@@ -15110,6 +15128,47 @@ function createLoggingSystem(opts) {
15110
15128
  };
15111
15129
  }
15112
15130
 
15131
+ // src/core/publicApi/notFoundSubject.ts
15132
+ var runnerRoutesThatNameNoRunner = new Set([
15133
+ "runner.launch",
15134
+ "runner.list"
15135
+ ]);
15136
+ var runRoutesThatResolveOneRun = new Set([
15137
+ "run.diagnose",
15138
+ "run.get",
15139
+ "run.reattempt",
15140
+ "run.stop"
15141
+ ]);
15142
+ var recordFieldNouns = [
15143
+ ["sessionId", "session"],
15144
+ ["triggerId", "trigger"],
15145
+ ["issueId", "issue"],
15146
+ ["flowId", "flow"],
15147
+ ["filePath", "file"]
15148
+ ];
15149
+ function field(input, name) {
15150
+ if (typeof input !== "object" || input === null)
15151
+ return;
15152
+ const value = input[name];
15153
+ return typeof value === "string" ? value : undefined;
15154
+ }
15155
+ function notFoundSubject(contractName, input) {
15156
+ if (contractName.startsWith("runner.") && !runnerRoutesThatNameNoRunner.has(contractName)) {
15157
+ return { kind: "runner", runnerId: field(input, "id") };
15158
+ }
15159
+ if (runRoutesThatResolveOneRun.has(contractName)) {
15160
+ return { kind: "run", runId: field(input, "runId") };
15161
+ }
15162
+ for (const [name, noun] of recordFieldNouns) {
15163
+ const id = field(input, name);
15164
+ if (id !== undefined)
15165
+ return { id, kind: "record", noun };
15166
+ }
15167
+ if (field(input, "environmentId") !== undefined)
15168
+ return { kind: "environment" };
15169
+ return { kind: "other" };
15170
+ }
15171
+
15113
15172
  // src/core/publicApi/flagKind.ts
15114
15173
  function flagKind(schema) {
15115
15174
  if (schema.type === "string")
@@ -15280,6 +15339,42 @@ function applyWorkspaceId(inputSchema, input, workspaceId) {
15280
15339
  return { ...input, workspaceId };
15281
15340
  }
15282
15341
 
15342
+ // src/shell/platform/describeNotFound.ts
15343
+ var m = authMessages.errors.request;
15344
+ var saysNothingMore = (reason) => /^(\w+ )*not ?found\.?$/i.test(reason.trim());
15345
+ function describeNotFound(subject, noun, reason) {
15346
+ const explained = reason && !saysNothingMore(reason) ? reason : undefined;
15347
+ const say = (own) => {
15348
+ const body = [explained ? undefined : own.guess, own.guidance].filter((line) => line);
15349
+ return {
15350
+ error: explained ? `${explained} (HTTP 404)` : own.statement,
15351
+ exitCode: exitCodes.notFound,
15352
+ ...body.length > 0 ? { errorBody: body.join(`
15353
+ `) } : {}
15354
+ };
15355
+ };
15356
+ switch (subject?.kind) {
15357
+ case "runner":
15358
+ return say({
15359
+ guess: m.runnerIsGone,
15360
+ guidance: m.launchTheRunner(subject.runnerId),
15361
+ statement: m.notFound404Runner(subject.runnerId)
15362
+ });
15363
+ case "run":
15364
+ return say({
15365
+ guess: m.runIdMayBeRunnerLocal(subject.runId),
15366
+ statement: m.notFound404Run(subject.runId)
15367
+ });
15368
+ case "record":
15369
+ return say({ statement: m.notFound404Record(subject.noun, subject.id) });
15370
+ case "other":
15371
+ return say({ statement: m.notFound404(noun) });
15372
+ case "environment":
15373
+ case undefined:
15374
+ return say({ statement: m.notFound404Environment(noun) });
15375
+ }
15376
+ }
15377
+
15283
15378
  // src/shell/platform/parseErrorBody.ts
15284
15379
  var defaultMaxLength = 1024;
15285
15380
  function asRecord(value) {
@@ -15322,69 +15417,69 @@ function clip(message, maxLength) {
15322
15417
  }
15323
15418
 
15324
15419
  // src/shell/platform/describeErrors.ts
15325
- var m = authMessages.errors;
15420
+ var m2 = authMessages.errors;
15326
15421
  var inlineReasonMaxLength = 200;
15327
15422
  function describeIdentityError(err) {
15328
15423
  if (err.kind === "http") {
15329
15424
  if (err.status === 401 || err.status === 403) {
15330
15425
  return {
15331
- error: m.identity.invalidOrUnauthorized,
15426
+ error: m2.identity.invalidOrUnauthorized,
15332
15427
  ...err.status === 401 ? { exitCode: exitCodes.auth } : {}
15333
15428
  };
15334
15429
  }
15335
15430
  return {
15336
- error: m.identity.couldNotVerify(parseErrorBody(err.body, inlineReasonMaxLength), err.status)
15431
+ error: m2.identity.couldNotVerify(parseErrorBody(err.body, inlineReasonMaxLength), err.status)
15337
15432
  };
15338
15433
  }
15339
15434
  if (err.kind === "network") {
15340
- return { error: m.identity.couldNotVerifyNetwork(err.cause.message) };
15435
+ return { error: m2.identity.couldNotVerifyNetwork(err.cause.message) };
15341
15436
  }
15342
15437
  if (err.kind === "timeout") {
15343
- return { error: m.identity.timedOut(err.timeoutMs) };
15438
+ return { error: m2.identity.timedOut(err.timeoutMs) };
15344
15439
  }
15345
- return { error: m.identity.unexpectedFormat };
15440
+ return { error: m2.identity.unexpectedFormat };
15346
15441
  }
15347
- function describeRequestError(err, baseUrl, noun) {
15442
+ function describeRequestError(err, baseUrl, noun, notFound) {
15348
15443
  if (err.kind === "http") {
15349
15444
  const reason = parseErrorBody(err.body);
15350
15445
  const body = reason ? { errorBody: reason } : {};
15351
15446
  if (err.status === 401)
15352
15447
  return {
15353
- error: m.request.rejected401(noun),
15448
+ error: m2.request.rejected401(noun),
15354
15449
  exitCode: exitCodes.auth,
15355
15450
  ...body
15356
15451
  };
15357
15452
  if (err.status === 402)
15358
15453
  return {
15359
- error: m.request.rejected402(noun),
15454
+ error: m2.request.rejected402(noun),
15360
15455
  exitCode: exitCodes.payment,
15361
15456
  ...body
15362
15457
  };
15363
15458
  if (err.status === 403)
15364
- return { error: m.request.rejected403(noun), ...body };
15459
+ return { error: m2.request.rejected403(noun), ...body };
15365
15460
  if (err.status === 404)
15366
- return { error: m.request.notFound404(noun), ...body };
15367
- return { error: m.request.failedWithStatus(err.status, noun), ...body };
15461
+ return describeNotFound(notFound, noun, reason);
15462
+ return { error: m2.request.failedWithStatus(err.status, noun), ...body };
15368
15463
  }
15369
15464
  if (err.kind === "network") {
15370
- return { error: m.request.networkUnreachable(baseUrl, noun) };
15465
+ return { error: m2.request.networkUnreachable(baseUrl, noun) };
15371
15466
  }
15372
15467
  if (err.kind === "timeout") {
15373
- return { error: m.request.timedOut(err.timeoutMs, noun) };
15468
+ return { error: m2.request.timedOut(err.timeoutMs, noun) };
15374
15469
  }
15375
- return { error: m.request.unexpectedResponse(noun) };
15470
+ return { error: m2.request.unexpectedResponse(noun) };
15376
15471
  }
15377
15472
  function describeBundleDownloadError(err) {
15378
15473
  if (err.kind === "http") {
15379
15474
  if (err.status === 401 || err.status === 403)
15380
- return m.bundle.linkExpired;
15381
- return m.bundle.failedWithStatus(err.status);
15475
+ return m2.bundle.linkExpired;
15476
+ return m2.bundle.failedWithStatus(err.status);
15382
15477
  }
15383
15478
  if (err.kind === "network")
15384
- return m.bundle.networkUnreachable;
15479
+ return m2.bundle.networkUnreachable;
15385
15480
  if (err.kind === "timeout")
15386
- return m.bundle.timedOut(err.timeoutMs);
15387
- return m.bundle.malformed;
15481
+ return m2.bundle.timedOut(err.timeoutMs);
15482
+ return m2.bundle.malformed;
15388
15483
  }
15389
15484
  function describeTeamStorageDownloadError(path, err) {
15390
15485
  if (err.kind === "http") {
@@ -15445,12 +15540,16 @@ function callPublicApi(trpc, contract, input, options) {
15445
15540
  return trpc.mutation(path, input, contract.output, options);
15446
15541
  }
15447
15542
  function makeCallPublicApiMethod(trpc, deps, readBackoffMs) {
15448
- return async (contract, input, options) => requestWithRetry({
15449
- call: () => callPublicApi(trpc, contract, applyWorkspaceId(contract.input, input, deps.workspaceId), options),
15450
- backoffMs: contract.kind === "read" ? readBackoffMs : [],
15451
- describe: (err) => describeRequestError(err, deps.baseUrl, contract.name),
15452
- sleep: deps.sleep
15453
- });
15543
+ return async (contract, input, options) => {
15544
+ const sent = applyWorkspaceId(contract.input, input, deps.workspaceId);
15545
+ const subject = notFoundSubject(contract.name, sent);
15546
+ return requestWithRetry({
15547
+ call: () => callPublicApi(trpc, contract, sent, options),
15548
+ backoffMs: contract.kind === "read" ? readBackoffMs : [],
15549
+ describe: (err) => describeRequestError(err, deps.baseUrl, contract.name, subject),
15550
+ sleep: deps.sleep
15551
+ });
15552
+ };
15454
15553
  }
15455
15554
 
15456
15555
  // node_modules/superjson/dist/double-indexed-kv.js
@@ -20095,7 +20194,7 @@ function p$1(l, e) {
20095
20194
  function g(l, e) {
20096
20195
  return (e.label ?? String(e.value)).toLowerCase().includes(l.toLowerCase());
20097
20196
  }
20098
- function m2(l, e) {
20197
+ function m3(l, e) {
20099
20198
  if (e)
20100
20199
  return l ? e : e[0];
20101
20200
  }
@@ -20145,7 +20244,7 @@ var T$1 = class T extends V {
20145
20244
  this.userInput === "\t" && this._clearUserInput(), this._setUserInput(u, true), this.isNavigating = false;
20146
20245
  return;
20147
20246
  }
20148
- i || s ? (this.#e = findCursor(this.#e, i ? -1 : 1, this.filteredOptions), this.focusedValue = this.filteredOptions[this.#e]?.value, this.multiple || (this.selectedValues = [this.focusedValue]), this.isNavigating = true) : n ? this.value = m2(this.multiple, this.selectedValues) : this.multiple ? this.focusedValue !== undefined && (t.name === "tab" || this.isNavigating && t.name === "space") ? this.toggleSelected(this.focusedValue) : this.isNavigating = false : (this.focusedValue && (this.selectedValues = [this.focusedValue]), this.isNavigating = false);
20247
+ i || s ? (this.#e = findCursor(this.#e, i ? -1 : 1, this.filteredOptions), this.focusedValue = this.filteredOptions[this.#e]?.value, this.multiple || (this.selectedValues = [this.focusedValue]), this.isNavigating = true) : n ? this.value = m3(this.multiple, this.selectedValues) : this.multiple ? this.focusedValue !== undefined && (t.name === "tab" || this.isNavigating && t.name === "space") ? this.toggleSelected(this.focusedValue) : this.isNavigating = false : (this.focusedValue && (this.selectedValues = [this.focusedValue]), this.isNavigating = false);
20149
20248
  }
20150
20249
  deselectAll() {
20151
20250
  this.selectedValues = [];
@@ -21466,7 +21565,7 @@ function startUpdateCheck(deps) {
21466
21565
  // package.json
21467
21566
  var package_default = {
21468
21567
  name: "@qawolf/cli",
21469
- version: "1.30.0",
21568
+ version: "1.31.0",
21470
21569
  description: "Run and manage QA Wolf flows from the terminal, CI, or an AI agent",
21471
21570
  keywords: [
21472
21571
  "automation",
@@ -21884,12 +21983,15 @@ async function followSession(ctx, options, deps) {
21884
21983
 
21885
21984
  // src/core/resolveId.ts
21886
21985
  async function resolveIdFrom(options) {
21887
- if (options.given !== undefined)
21888
- return options.given;
21986
+ if (options.given !== undefined) {
21987
+ return { id: options.given, source: "flag" };
21988
+ }
21889
21989
  const fromEnvironment = options.env[options.environmentVariable]?.trim();
21890
- if (fromEnvironment)
21891
- return fromEnvironment;
21892
- return options.readStored();
21990
+ if (fromEnvironment) {
21991
+ return { id: fromEnvironment, source: "environment" };
21992
+ }
21993
+ const stored = await options.readStored();
21994
+ return stored === undefined ? undefined : { id: stored, source: "stored" };
21893
21995
  }
21894
21996
 
21895
21997
  // src/domains/agent/resolveSessionId.ts
@@ -21901,12 +22003,12 @@ function chooseGivenSessionId(given) {
21901
22003
  }
21902
22004
  return { ok: true, sessionId: argument ?? flag };
21903
22005
  }
21904
- var resolveSessionId = (session, deps) => resolveIdFrom({
22006
+ var resolveSessionId = async (session, deps) => (await resolveIdFrom({
21905
22007
  env: deps.env,
21906
22008
  environmentVariable: sessionIdEnvironmentVariable,
21907
22009
  given: session,
21908
22010
  readStored: deps.store.readLastSessionId
21909
- });
22011
+ }))?.id;
21910
22012
 
21911
22013
  // src/domains/agent/get.ts
21912
22014
  function renderSession(ctx, session) {
@@ -27226,7 +27328,7 @@ var Jr = I.writev;
27226
27328
  var ht = Symbol("_autoClose");
27227
27329
  var H = Symbol("_close");
27228
27330
  var te = Symbol("_ended");
27229
- var m3 = Symbol("_fd");
27331
+ var m4 = Symbol("_fd");
27230
27332
  var Ni = Symbol("_finished");
27231
27333
  var tt = Symbol("_flags");
27232
27334
  var Ai = Symbol("_flush");
@@ -27253,7 +27355,7 @@ var Me = Symbol("_defaultFlag");
27253
27355
  var bt = Symbol("_errored");
27254
27356
  var _t = class extends A2 {
27255
27357
  [bt] = false;
27256
- [m3];
27358
+ [m4];
27257
27359
  [U2];
27258
27360
  [Ci];
27259
27361
  [j] = false;
@@ -27263,10 +27365,10 @@ var _t = class extends A2 {
27263
27365
  constructor(t, e) {
27264
27366
  if (e = e || {}, super(e), this.readable = true, this.writable = false, typeof t != "string")
27265
27367
  throw new TypeError("path must be a string");
27266
- this[bt] = false, this[m3] = typeof e.fd == "number" ? e.fd : undefined, this[U2] = t, this[Ci] = e.readSize || 16 * 1024 * 1024, this[j] = false, this[Fi] = typeof e.size == "number" ? e.size : 1 / 0, this[ee] = this[Fi], this[ht] = typeof e.autoClose == "boolean" ? e.autoClose : true, typeof this[m3] == "number" ? this[zt]() : this[at]();
27368
+ this[bt] = false, this[m4] = typeof e.fd == "number" ? e.fd : undefined, this[U2] = t, this[Ci] = e.readSize || 16 * 1024 * 1024, this[j] = false, this[Fi] = typeof e.size == "number" ? e.size : 1 / 0, this[ee] = this[Fi], this[ht] = typeof e.autoClose == "boolean" ? e.autoClose : true, typeof this[m4] == "number" ? this[zt]() : this[at]();
27267
27369
  }
27268
27370
  get fd() {
27269
- return this[m3];
27371
+ return this[m4];
27270
27372
  }
27271
27373
  get path() {
27272
27374
  return this[U2];
@@ -27281,7 +27383,7 @@ var _t = class extends A2 {
27281
27383
  I.open(this[U2], "r", (t, e) => this[Ht](t, e));
27282
27384
  }
27283
27385
  [Ht](t, e) {
27284
- t ? this[Ut](t) : (this[m3] = e, this.emit("open", e), this[zt]());
27386
+ t ? this[Ut](t) : (this[m4] = e, this.emit("open", e), this[zt]());
27285
27387
  }
27286
27388
  [vi]() {
27287
27389
  return Buffer.allocUnsafe(Math.min(this[Ci], this[ee]));
@@ -27292,16 +27394,16 @@ var _t = class extends A2 {
27292
27394
  let t = this[vi]();
27293
27395
  if (t.length === 0)
27294
27396
  return process.nextTick(() => this[Ii](null, 0, t));
27295
- I.read(this[m3], t, 0, t.length, null, (e, i, r) => this[Ii](e, i, r));
27397
+ I.read(this[m4], t, 0, t.length, null, (e, i, r) => this[Ii](e, i, r));
27296
27398
  }
27297
27399
  }
27298
27400
  [Ii](t, e, i) {
27299
27401
  this[j] = false, t ? this[Ut](t) : this[ki](e, i) && this[zt]();
27300
27402
  }
27301
27403
  [H]() {
27302
- if (this[ht] && typeof this[m3] == "number") {
27303
- let t = this[m3];
27304
- this[m3] = undefined, I.close(t, (e) => e ? this.emit("error", e) : this.emit("close"));
27404
+ if (this[ht] && typeof this[m4] == "number") {
27405
+ let t = this[m4];
27406
+ this[m4] = undefined, I.close(t, (e) => e ? this.emit("error", e) : this.emit("close"));
27305
27407
  }
27306
27408
  }
27307
27409
  [Ut](t) {
@@ -27317,7 +27419,7 @@ var _t = class extends A2 {
27317
27419
  case "finish":
27318
27420
  return false;
27319
27421
  case "drain":
27320
- return typeof this[m3] == "number" && this[zt](), false;
27422
+ return typeof this[m4] == "number" && this[zt](), false;
27321
27423
  case "error":
27322
27424
  return this[bt] ? false : (this[bt] = true, super.emit(t, ...e));
27323
27425
  default:
@@ -27340,7 +27442,7 @@ var Be = class extends _t {
27340
27442
  if (!this[j]) {
27341
27443
  this[j] = true;
27342
27444
  do {
27343
- let e = this[vi](), i = e.length === 0 ? 0 : I.readSync(this[m3], e, 0, e.length, null);
27445
+ let e = this[vi](), i = e.length === 0 ? 0 : I.readSync(this[m4], e, 0, e.length, null);
27344
27446
  if (!this[ki](i, e))
27345
27447
  break;
27346
27448
  } while (true);
@@ -27352,9 +27454,9 @@ var Be = class extends _t {
27352
27454
  }
27353
27455
  }
27354
27456
  [H]() {
27355
- if (this[ht] && typeof this[m3] == "number") {
27356
- let t = this[m3];
27357
- this[m3] = undefined, I.closeSync(t), this.emit("close");
27457
+ if (this[ht] && typeof this[m4] == "number") {
27458
+ let t = this[m4];
27459
+ this[m4] = undefined, I.closeSync(t), this.emit("close");
27358
27460
  }
27359
27461
  }
27360
27462
  };
@@ -27369,15 +27471,15 @@ var et = class extends Qr {
27369
27471
  [U2];
27370
27472
  [ie];
27371
27473
  [ht];
27372
- [m3];
27474
+ [m4];
27373
27475
  [Me];
27374
27476
  [tt];
27375
27477
  [Ni] = false;
27376
27478
  [ot];
27377
27479
  constructor(t, e) {
27378
- e = e || {}, super(e), this[U2] = t, this[m3] = typeof e.fd == "number" ? e.fd : undefined, this[ie] = e.mode === undefined ? 438 : e.mode, this[ot] = typeof e.start == "number" ? e.start : undefined, this[ht] = typeof e.autoClose == "boolean" ? e.autoClose : true;
27480
+ e = e || {}, super(e), this[U2] = t, this[m4] = typeof e.fd == "number" ? e.fd : undefined, this[ie] = e.mode === undefined ? 438 : e.mode, this[ot] = typeof e.start == "number" ? e.start : undefined, this[ht] = typeof e.autoClose == "boolean" ? e.autoClose : true;
27379
27481
  let i = this[ot] !== undefined ? "r+" : "w";
27380
- this[Me] = e.flags === undefined, this[tt] = e.flags === undefined ? i : e.flags, this[m3] === undefined && this[at]();
27482
+ this[Me] = e.flags === undefined, this[tt] = e.flags === undefined ? i : e.flags, this[m4] === undefined && this[at]();
27381
27483
  }
27382
27484
  emit(t, ...e) {
27383
27485
  if (t === "error") {
@@ -27388,7 +27490,7 @@ var et = class extends Qr {
27388
27490
  return super.emit(t, ...e);
27389
27491
  }
27390
27492
  get fd() {
27391
- return this[m3];
27493
+ return this[m4];
27392
27494
  }
27393
27495
  get path() {
27394
27496
  return this[U2];
@@ -27400,16 +27502,16 @@ var et = class extends Qr {
27400
27502
  I.open(this[U2], this[tt], this[ie], (t, e) => this[Ht](t, e));
27401
27503
  }
27402
27504
  [Ht](t, e) {
27403
- this[Me] && this[tt] === "r+" && t && t.code === "ENOENT" ? (this[tt] = "w", this[at]()) : t ? this[Ut](t) : (this[m3] = e, this.emit("open", e), this[gt] || this[Ai]());
27505
+ this[Me] && this[tt] === "r+" && t && t.code === "ENOENT" ? (this[tt] = "w", this[at]()) : t ? this[Ut](t) : (this[m4] = e, this.emit("open", e), this[gt] || this[Ai]());
27404
27506
  }
27405
27507
  end(t, e) {
27406
- return t && this.write(t, e), this[te] = true, !this[gt] && !this[Y].length && typeof this[m3] == "number" && this[Pt](null, 0), this;
27508
+ return t && this.write(t, e), this[te] = true, !this[gt] && !this[Y].length && typeof this[m4] == "number" && this[Pt](null, 0), this;
27407
27509
  }
27408
27510
  write(t, e) {
27409
- return typeof t == "string" && (t = Buffer.from(t, e)), this[te] ? (this.emit("error", new Error("write() after end()")), false) : this[m3] === undefined || this[gt] || this[Y].length ? (this[Y].push(t), this[ke] = true, false) : (this[gt] = true, this[ve](t), true);
27511
+ return typeof t == "string" && (t = Buffer.from(t, e)), this[te] ? (this.emit("error", new Error("write() after end()")), false) : this[m4] === undefined || this[gt] || this[Y].length ? (this[Y].push(t), this[ke] = true, false) : (this[gt] = true, this[ve](t), true);
27410
27512
  }
27411
27513
  [ve](t) {
27412
- I.write(this[m3], t, 0, t.length, this[ot], (e, i) => this[Pt](e, i));
27514
+ I.write(this[m4], t, 0, t.length, this[ot], (e, i) => this[Pt](e, i));
27413
27515
  }
27414
27516
  [Pt](t, e) {
27415
27517
  t ? this[Ut](t) : (this[ot] !== undefined && typeof e == "number" && (this[ot] += e), this[Y].length ? this[Ai]() : (this[gt] = false, this[te] && !this[Ni] ? (this[Ni] = true, this[H](), this.emit("finish")) : this[ke] && (this[ke] = false, this.emit("drain"))));
@@ -27421,13 +27523,13 @@ var et = class extends Qr {
27421
27523
  this[ve](this[Y].pop());
27422
27524
  else {
27423
27525
  let t = this[Y];
27424
- this[Y] = [], Jr(this[m3], t, this[ot], (e, i) => this[Pt](e, i));
27526
+ this[Y] = [], Jr(this[m4], t, this[ot], (e, i) => this[Pt](e, i));
27425
27527
  }
27426
27528
  }
27427
27529
  [H]() {
27428
- if (this[ht] && typeof this[m3] == "number") {
27429
- let t = this[m3];
27430
- this[m3] = undefined, I.close(t, (e) => e ? this.emit("error", e) : this.emit("close"));
27530
+ if (this[ht] && typeof this[m4] == "number") {
27531
+ let t = this[m4];
27532
+ this[m4] = undefined, I.close(t, (e) => e ? this.emit("error", e) : this.emit("close"));
27431
27533
  }
27432
27534
  }
27433
27535
  };
@@ -27447,15 +27549,15 @@ var Wt = class extends et {
27447
27549
  this[Ht](null, t);
27448
27550
  }
27449
27551
  [H]() {
27450
- if (this[ht] && typeof this[m3] == "number") {
27451
- let t = this[m3];
27452
- this[m3] = undefined, I.closeSync(t), this.emit("close");
27552
+ if (this[ht] && typeof this[m4] == "number") {
27553
+ let t = this[m4];
27554
+ this[m4] = undefined, I.closeSync(t), this.emit("close");
27453
27555
  }
27454
27556
  }
27455
27557
  [ve](t) {
27456
27558
  let e = true;
27457
27559
  try {
27458
- this[Pt](null, I.writeSync(this[m3], t, 0, t.length, this[ot])), e = false;
27560
+ this[Pt](null, I.writeSync(this[m4], t, 0, t.length, this[ot])), e = false;
27459
27561
  } finally {
27460
27562
  if (e)
27461
27563
  try {
@@ -30589,10 +30691,10 @@ async function resolveEnvChoice(args) {
30589
30691
 
30590
30692
  // src/core/flowFailureHint.ts
30591
30693
  function flowFailureHint(errText, projectDir) {
30592
- const missingPackage = extractMissingPackage(errText);
30593
- if (missingPackage === undefined)
30694
+ const missing = extractMissingSpecifier(errText);
30695
+ if (missing === undefined)
30594
30696
  return;
30595
- return runnerMessages.moduleNotFoundHint(missingPackage, projectDir);
30697
+ return missing.kind === "path-alias" ? runnerMessages.pathAliasNotFoundHint(missing.specifier, projectDir) : runnerMessages.moduleNotFoundHint(missing.specifier, projectDir);
30596
30698
  }
30597
30699
 
30598
30700
  // src/shell/reporter/createCompositeReporter.ts
@@ -31127,7 +31229,7 @@ async function defaultRunWebFlowDeps(envDir = process.cwd(), signals) {
31127
31229
 
31128
31230
  // src/domains/runtimeEnv/prepareRunDir.ts
31129
31231
  import { createHash as createHash4 } from "node:crypto";
31130
- import { join as join40, resolve as resolve9 } from "node:path";
31232
+ import { join as join41, resolve as resolve9 } from "node:path";
31131
31233
 
31132
31234
  // src/domains/runtimeEnv/execSubpathImports.ts
31133
31235
  import { join as join33 } from "node:path";
@@ -31354,16 +31456,266 @@ async function installOuterDeps(runDir, deps, fs, install) {
31354
31456
  }
31355
31457
  }
31356
31458
 
31459
+ // src/domains/runtimeEnv/rewriteStagedAliases.ts
31460
+ import { join as join38 } from "node:path";
31461
+
31462
+ // src/core/aliasImports/rewriteAliasImports.ts
31463
+ import { posix as posix3 } from "node:path";
31464
+
31465
+ // src/core/aliasImports/collectAliasSpecifiers.ts
31466
+ function isRelativeSpecifier(specifier) {
31467
+ return specifier.startsWith("./") || specifier.startsWith("../");
31468
+ }
31469
+ function collectAliasSpecifiers(options) {
31470
+ const { sourceFile, typescript: compiler } = options;
31471
+ const specifiers = [];
31472
+ const addCandidate = (literal) => {
31473
+ if (isRelativeSpecifier(literal.text))
31474
+ return;
31475
+ specifiers.push({
31476
+ end: literal.getEnd(),
31477
+ specifier: literal.text,
31478
+ start: literal.getStart(sourceFile)
31479
+ });
31480
+ };
31481
+ for (const statement of sourceFile.statements) {
31482
+ if (compiler.isImportDeclaration(statement)) {
31483
+ const phase = statement.importClause?.phaseModifier;
31484
+ if (phase === compiler.SyntaxKind.TypeKeyword)
31485
+ continue;
31486
+ if (compiler.isStringLiteral(statement.moduleSpecifier)) {
31487
+ addCandidate(statement.moduleSpecifier);
31488
+ }
31489
+ continue;
31490
+ }
31491
+ if (compiler.isExportDeclaration(statement) && !statement.isTypeOnly) {
31492
+ const { moduleSpecifier } = statement;
31493
+ if (moduleSpecifier !== undefined && compiler.isStringLiteral(moduleSpecifier)) {
31494
+ addCandidate(moduleSpecifier);
31495
+ }
31496
+ }
31497
+ }
31498
+ const visit = (node) => {
31499
+ if (compiler.isCallExpression(node) && node.expression.kind === compiler.SyntaxKind.ImportKeyword) {
31500
+ const [firstArgument] = node.arguments;
31501
+ if (firstArgument !== undefined && (compiler.isStringLiteral(firstArgument) || compiler.isNoSubstitutionTemplateLiteral(firstArgument))) {
31502
+ addCandidate(firstArgument);
31503
+ }
31504
+ return;
31505
+ }
31506
+ compiler.forEachChild(node, visit);
31507
+ };
31508
+ visit(sourceFile);
31509
+ return specifiers;
31510
+ }
31511
+
31512
+ // src/core/aliasImports/filePathVariants.ts
31513
+ var sourceExtensionPattern = /\.(js|ts)$/;
31514
+ var sourceExtensions2 = [".ts", ".js"];
31515
+ function filePathVariants(importPath) {
31516
+ const hasSourceExtension = sourceExtensionPattern.test(importPath);
31517
+ const base = importPath.replace(sourceExtensionPattern, "");
31518
+ const siblings = sourceExtensions2.map((extension) => base + extension);
31519
+ const indexes = hasSourceExtension ? [] : sourceExtensions2.map((extension) => `${base}/index${extension}`);
31520
+ return [...new Set([importPath, ...siblings, ...indexes])];
31521
+ }
31522
+
31523
+ // src/core/aliasImports/tsconfigPaths.ts
31524
+ function isRecord2(value) {
31525
+ return typeof value === "object" && value !== null;
31526
+ }
31527
+ function isTsconfigPaths(value) {
31528
+ return isRecord2(value) && Object.values(value).every((targets) => Array.isArray(targets) && targets.every((target) => typeof target === "string"));
31529
+ }
31530
+ function parseTsconfigContent(tsconfigContent) {
31531
+ let parsed;
31532
+ try {
31533
+ parsed = JSON.parse(tsconfigContent);
31534
+ } catch {
31535
+ return { type: "unparseable" };
31536
+ }
31537
+ if (!isRecord2(parsed))
31538
+ return { paths: undefined, type: "parsed" };
31539
+ const compilerOptions = parsed["compilerOptions"];
31540
+ if (!isRecord2(compilerOptions))
31541
+ return { paths: undefined, type: "parsed" };
31542
+ const paths = compilerOptions["paths"];
31543
+ return {
31544
+ paths: isTsconfigPaths(paths) ? paths : undefined,
31545
+ type: "parsed"
31546
+ };
31547
+ }
31548
+ function parseTsconfigPaths(tsconfigContent) {
31549
+ const parsed = parseTsconfigContent(tsconfigContent);
31550
+ return parsed.type === "parsed" ? parsed.paths : undefined;
31551
+ }
31552
+ function parseWildcardPattern(pattern) {
31553
+ const wildcard = pattern.indexOf("*");
31554
+ if (wildcard === -1 || wildcard !== pattern.lastIndexOf("*"))
31555
+ return;
31556
+ return {
31557
+ prefix: pattern.slice(0, wildcard),
31558
+ suffix: pattern.slice(wildcard + 1)
31559
+ };
31560
+ }
31561
+ function matchesWildcard(importPath, { prefix, suffix }) {
31562
+ return importPath.length >= prefix.length + suffix.length && importPath.startsWith(prefix) && importPath.endsWith(suffix);
31563
+ }
31564
+ function longestPrefixMatch(importPath, paths) {
31565
+ return Object.entries(paths).flatMap(([pattern, targets]) => {
31566
+ const parsed = parseWildcardPattern(pattern);
31567
+ if (parsed === undefined || !matchesWildcard(importPath, parsed)) {
31568
+ return [];
31569
+ }
31570
+ return [{ pattern: parsed, targets }];
31571
+ }).reduce((best, candidate) => best === undefined || candidate.pattern.prefix.length > best.pattern.prefix.length ? candidate : best, undefined);
31572
+ }
31573
+ function resolvePathAlias(importPath, paths) {
31574
+ if (paths === undefined)
31575
+ return;
31576
+ const [exactTarget] = paths[importPath] ?? [];
31577
+ if (exactTarget !== undefined)
31578
+ return exactTarget;
31579
+ const match = longestPrefixMatch(importPath, paths);
31580
+ if (match === undefined)
31581
+ return;
31582
+ const [target] = match.targets;
31583
+ if (target === undefined)
31584
+ return;
31585
+ const substituted = importPath.slice(match.pattern.prefix.length, importPath.length - match.pattern.suffix.length);
31586
+ return target.replace("*", substituted);
31587
+ }
31588
+
31589
+ // src/core/aliasImports/rewriteAliasImports.ts
31590
+ function findTargetFilePath(options) {
31591
+ return filePathVariants(posix3.normalize(options.aliasTarget)).find((candidate) => options.projectFilePaths.has(candidate));
31592
+ }
31593
+ function toRelativeSpecifier(options) {
31594
+ const relativePath = posix3.relative(posix3.dirname(options.importingFilePath), options.targetFilePath);
31595
+ return relativePath.startsWith(".") ? relativePath : `./${relativePath}`;
31596
+ }
31597
+ function applyEdit(code, edit) {
31598
+ const quote = code.slice(edit.start, edit.start + 1);
31599
+ return code.slice(0, edit.start) + quote + edit.relativeSpecifier + quote + code.slice(edit.end);
31600
+ }
31601
+ function rewriteAliasImports(options) {
31602
+ const { code, importingFilePath, projectFilePaths, tsconfigPaths } = options;
31603
+ const compiler = options.typescript;
31604
+ if (tsconfigPaths === undefined)
31605
+ return code;
31606
+ const sourceFile = compiler.createSourceFile(importingFilePath, code, compiler.ScriptTarget.Latest, true);
31607
+ const edits = collectAliasSpecifiers({
31608
+ sourceFile,
31609
+ typescript: compiler
31610
+ }).flatMap((candidate) => {
31611
+ const aliasTarget = resolvePathAlias(candidate.specifier, tsconfigPaths);
31612
+ if (aliasTarget === undefined)
31613
+ return [];
31614
+ const targetFilePath = findTargetFilePath({
31615
+ aliasTarget,
31616
+ projectFilePaths
31617
+ });
31618
+ if (targetFilePath === undefined)
31619
+ return [];
31620
+ return [
31621
+ {
31622
+ end: candidate.end,
31623
+ relativeSpecifier: toRelativeSpecifier({
31624
+ importingFilePath,
31625
+ targetFilePath
31626
+ }),
31627
+ start: candidate.start
31628
+ }
31629
+ ];
31630
+ });
31631
+ return edits.sort((left, right) => right.start - left.start).reduce(applyEdit, code);
31632
+ }
31633
+
31634
+ // src/domains/runtimeEnv/rewriteStagedAliases.ts
31635
+ var skippedDirs = new Set(["node_modules", ".git", ".qawolf"]);
31636
+ var sourceExtensions3 = [".ts", ".js"];
31637
+ async function rewriteStagedAliases(args) {
31638
+ const tsconfig = await readStagedTsconfig(args);
31639
+ if (tsconfig.type === "unparseable") {
31640
+ args.onTsconfigUnparsed?.();
31641
+ return [];
31642
+ }
31643
+ if (tsconfig.type === "absent" || tsconfig.paths === undefined)
31644
+ return [];
31645
+ const tsconfigPaths = tsconfig.paths;
31646
+ const stagedPaths = await listStagedSourceFiles({
31647
+ dir: args.execDir,
31648
+ fs: args.fs,
31649
+ prefix: ""
31650
+ });
31651
+ const projectFilePaths = new Set(stagedPaths);
31652
+ const aliasPrefixes = Object.keys(tsconfigPaths).map((pattern) => pattern.split("*")[0] ?? pattern);
31653
+ const mentionsAnAlias = (code) => aliasPrefixes.some((prefix) => code.includes(prefix));
31654
+ const { default: typescript } = await import("typescript");
31655
+ const rewriteOne = async (stagedPath) => {
31656
+ const absolutePath = join38(args.execDir, stagedPath);
31657
+ const code = await args.fs.readFile(absolutePath);
31658
+ if (!mentionsAnAlias(code))
31659
+ return;
31660
+ const rewritten = rewriteAliasImports({
31661
+ code,
31662
+ importingFilePath: stagedPath,
31663
+ projectFilePaths,
31664
+ tsconfigPaths,
31665
+ typescript
31666
+ });
31667
+ if (rewritten === code)
31668
+ return;
31669
+ await args.fs.writeFile(absolutePath, rewritten);
31670
+ return stagedPath;
31671
+ };
31672
+ const rewrittenPaths = [];
31673
+ for await (const stagedPath of batchMap(stagedPaths, rewriteOne, flowBatchSize)) {
31674
+ if (stagedPath !== undefined)
31675
+ rewrittenPaths.push(stagedPath);
31676
+ }
31677
+ return rewrittenPaths;
31678
+ }
31679
+ async function readStagedTsconfig(options) {
31680
+ let content;
31681
+ try {
31682
+ content = await options.fs.readFile(join38(options.execDir, "tsconfig.json"));
31683
+ } catch (err) {
31684
+ if (isNoEntError(err))
31685
+ return { type: "absent" };
31686
+ throw err;
31687
+ }
31688
+ return parseTsconfigContent(content);
31689
+ }
31690
+ async function listStagedSourceFiles(options) {
31691
+ const entries = await options.fs.readdirWithTypes(options.dir);
31692
+ const nested = await Promise.all(entries.map(async (entry) => {
31693
+ if (skippedDirs.has(entry.name))
31694
+ return [];
31695
+ const stagedPath = options.prefix === "" ? entry.name : `${options.prefix}/${entry.name}`;
31696
+ if (entry.isDirectory()) {
31697
+ return listStagedSourceFiles({
31698
+ dir: join38(options.dir, entry.name),
31699
+ fs: options.fs,
31700
+ prefix: stagedPath
31701
+ });
31702
+ }
31703
+ const isSource = sourceExtensions3.some((extension) => entry.name.endsWith(extension));
31704
+ return entry.isFile() && isSource ? [stagedPath] : [];
31705
+ }));
31706
+ return nested.flat();
31707
+ }
31708
+
31357
31709
  // src/domains/runtimeEnv/stageFlowFiles.ts
31358
31710
  import { createHash as createHash3 } from "node:crypto";
31359
- import { basename as basename6, dirname as dirname12, join as join39, sep as sep4 } from "node:path";
31711
+ import { basename as basename6, dirname as dirname12, join as join40, sep as sep4 } from "node:path";
31360
31712
 
31361
31713
  // src/shell/copyDir.ts
31362
31714
  import { cp, readdir as readdir2 } from "node:fs/promises";
31363
- import { basename as basename5, join as join38 } from "node:path";
31715
+ import { basename as basename5, join as join39 } from "node:path";
31364
31716
  async function copyDirExcluding(source, destination, excludedNames) {
31365
31717
  const entries = await readdir2(source, { withFileTypes: true });
31366
- await Promise.all(entries.filter((entry) => !excludedNames.has(entry.name)).map((entry) => cp(join38(source, entry.name), join38(destination, entry.name), {
31718
+ await Promise.all(entries.filter((entry) => !excludedNames.has(entry.name)).map((entry) => cp(join39(source, entry.name), join39(destination, entry.name), {
31367
31719
  recursive: true,
31368
31720
  filter: (path) => !excludedNames.has(basename5(path))
31369
31721
  })));
@@ -31380,14 +31732,14 @@ async function stageFlowFiles(args) {
31380
31732
  if (files.length > 1) {
31381
31733
  return Promise.all(files.map((f) => stageOneFile(f, execDir, fs)));
31382
31734
  }
31383
- await Promise.all(files.map((f) => fs.copyFile(f, join39(execDir, basename6(f)))));
31384
- return files.map((f) => join39(execDir, basename6(f)));
31735
+ await Promise.all(files.map((f) => fs.copyFile(f, join40(execDir, basename6(f)))));
31736
+ return files.map((f) => join40(execDir, basename6(f)));
31385
31737
  }
31386
31738
  async function stageOneFile(file, execDir, fs) {
31387
31739
  const dirHash = createHash3("sha256").update(dirname12(file)).digest("hex").slice(0, 8);
31388
- const subDir = join39(execDir, dirHash);
31740
+ const subDir = join40(execDir, dirHash);
31389
31741
  await fs.mkdir(subDir, { recursive: true });
31390
- const dest = join39(subDir, basename6(file));
31742
+ const dest = join40(subDir, basename6(file));
31391
31743
  await fs.copyFile(file, dest);
31392
31744
  return dest;
31393
31745
  }
@@ -31395,7 +31747,7 @@ function remapPath(file, projectDir, execDir) {
31395
31747
  if (file === projectDir)
31396
31748
  return execDir;
31397
31749
  if (file.startsWith(projectDir + sep4)) {
31398
- return join39(execDir, file.slice(projectDir.length + 1));
31750
+ return join40(execDir, file.slice(projectDir.length + 1));
31399
31751
  }
31400
31752
  return;
31401
31753
  }
@@ -31405,15 +31757,21 @@ async function prepareRunDir(args) {
31405
31757
  const { files, projectDir, depsRoot, runRoot } = args;
31406
31758
  const fs = args.fs ?? makeDefaultFs();
31407
31759
  const runId = buildRunId(projectDir, files);
31408
- const runDir = join40(runRoot, runId);
31760
+ const runDir = join41(runRoot, runId);
31409
31761
  await fs.rm(runDir, { recursive: true, force: true });
31410
31762
  await fs.mkdir(runDir, { recursive: true });
31411
- const execDir = join40(runDir, "exec");
31763
+ const execDir = join41(runDir, "exec");
31412
31764
  await fs.mkdir(execDir, { recursive: true });
31413
31765
  await populateInnerHop({ depsRoot, execDir, fs });
31414
31766
  const stagedFiles = await stageFlowFiles({ files, projectDir, execDir, fs });
31415
31767
  if (projectDir !== undefined) {
31416
31768
  await writeExecSubpathImports({ execDir, fs });
31769
+ const onTsconfigUnparsed = args.onTsconfigUnparsed;
31770
+ await rewriteStagedAliases({
31771
+ execDir,
31772
+ fs,
31773
+ ...onTsconfigUnparsed !== undefined ? { onTsconfigUnparsed: () => onTsconfigUnparsed(projectDir) } : {}
31774
+ });
31417
31775
  }
31418
31776
  const outerHop = await populateOuterHop({
31419
31777
  projectDir,
@@ -31439,17 +31797,17 @@ function buildRunId(projectDir, files) {
31439
31797
  }
31440
31798
 
31441
31799
  // src/shell/testkit.ts
31442
- import { join as join41 } from "node:path";
31800
+ import { join as join42 } from "node:path";
31443
31801
  function notAvailableLocally(name) {
31444
31802
  throw new Error(runnerMessages.notAvailableLocally(name));
31445
31803
  }
31446
31804
  async function loadSdkDeps(cwd) {
31447
- const testkitDir = join41(cwd, "node_modules", "@qawolf", "testkit");
31805
+ const testkitDir = join42(cwd, "node_modules", "@qawolf", "testkit");
31448
31806
  try {
31449
31807
  const clientMod = await importFromPath(resolveFromEnvDir(cwd, "@qawolf/testkit/client"));
31450
31808
  if (typeof clientMod.createTestkitClient !== "function")
31451
31809
  throw new Error("createTestkitClient is not a function");
31452
- const scopeMod = await importFromPath(join41(testkitDir, "dist", "clientScope.js"));
31810
+ const scopeMod = await importFromPath(join42(testkitDir, "dist", "clientScope.js"));
31453
31811
  if (typeof scopeMod.configureTestkitClient !== "function")
31454
31812
  throw new Error("configureTestkitClient is not a function");
31455
31813
  return {
@@ -31507,9 +31865,9 @@ async function registerLazyEmailsClient(getInbox, cwd, deps) {
31507
31865
  }
31508
31866
 
31509
31867
  // src/commands/flows/envVarDeps.ts
31510
- import { join as join42 } from "node:path";
31868
+ import { join as join43 } from "node:path";
31511
31869
  function envFilePath(envDir) {
31512
- return join42(envDir, ".env");
31870
+ return join43(envDir, ".env");
31513
31871
  }
31514
31872
  async function readEnv(envDir, fs) {
31515
31873
  try {
@@ -31633,7 +31991,7 @@ async function selectRunByTag(args) {
31633
31991
  }
31634
31992
 
31635
31993
  // src/commands/flows/runStagedFlows.ts
31636
- import { join as join46 } from "node:path";
31994
+ import { join as join47 } from "node:path";
31637
31995
 
31638
31996
  // src/shell/appium/createAppiumServer.ts
31639
31997
  import { existsSync as existsSync2 } from "node:fs";
@@ -32939,14 +33297,14 @@ async function runWebFlow({
32939
33297
 
32940
33298
  // src/shell/embeddedWorkerCli.ts
32941
33299
  import { existsSync as existsSync3, mkdirSync as mkdirSync3, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "node:fs";
32942
- import { basename as basename7, join as join43 } from "node:path";
33300
+ import { basename as basename7, join as join44 } from "node:path";
32943
33301
  var embeddedCliPathEnv = "QAWOLF_EMBEDDED_CLI_PATH";
32944
33302
  function extractEmbeddedWorkerCli() {
32945
33303
  const assetPath = process.env[embeddedCliPathEnv];
32946
33304
  if (assetPath === undefined || assetPath === "")
32947
33305
  return;
32948
- const dir = join43(getDataDir(), "worker");
32949
- const dest = join43(dir, basename7(assetPath));
33306
+ const dir = join44(getDataDir(), "worker");
33307
+ const dest = join44(dir, basename7(assetPath));
32950
33308
  if (existsSync3(dest))
32951
33309
  return dest;
32952
33310
  mkdirSync3(dir, { recursive: true });
@@ -33184,7 +33542,7 @@ ${styleText5("dim", "─".repeat(width))}
33184
33542
  };
33185
33543
  }
33186
33544
  // src/shell/reporter/createJUnitReporter.ts
33187
- import { join as join44 } from "node:path";
33545
+ import { join as join45 } from "node:path";
33188
33546
 
33189
33547
  // src/shell/reporter/junitXml.ts
33190
33548
  function escapeXml(str) {
@@ -33223,7 +33581,7 @@ ${suites}`;
33223
33581
 
33224
33582
  // src/shell/reporter/createJUnitReporter.ts
33225
33583
  function resolveJUnitOutputPath(junit, outputDir) {
33226
- return typeof junit === "string" && junit.trim() !== "" ? junit : join44(outputDir, "junit-report.xml");
33584
+ return typeof junit === "string" && junit.trim() !== "" ? junit : join45(outputDir, "junit-report.xml");
33227
33585
  }
33228
33586
  function createJUnitReporter(deps) {
33229
33587
  const flows = [];
@@ -33314,11 +33672,11 @@ function buildFlowsRunDeps(args) {
33314
33672
 
33315
33673
  // src/commands/flows/loadEnvFile.ts
33316
33674
  import { readFile } from "node:fs/promises";
33317
- import { join as join45 } from "node:path";
33675
+ import { join as join46 } from "node:path";
33318
33676
  async function loadEnvFile(envDir) {
33319
33677
  let content;
33320
33678
  try {
33321
- content = await readFile(join45(envDir, ".env"), "utf8");
33679
+ content = await readFile(join46(envDir, ".env"), "utf8");
33322
33680
  } catch (err) {
33323
33681
  if (isNoEntError(err))
33324
33682
  return;
@@ -33356,14 +33714,15 @@ async function runStagedFlows(args) {
33356
33714
  projectDir,
33357
33715
  depsRoot: runtimeEnv.depsRoot,
33358
33716
  runRoot: runStagingRoot(),
33359
- onInstallStart: (depCount) => ctx.ui.info(runnerMessages.installingProjectDeps(depCount))
33717
+ onInstallStart: (depCount) => ctx.ui.info(runnerMessages.installingProjectDeps(depCount)),
33718
+ onTsconfigUnparsed: (dir) => ctx.ui.warn(runnerMessages.tsconfigUnparsedNotice(dir))
33360
33719
  });
33361
33720
  if (staged.outerHop.mode === "install") {
33362
33721
  const log = ctx.log("runner");
33363
33722
  for (const candidate of staged.outerHop.rejected) {
33364
33723
  log.debug(runnerMessages.outerHopCandidateRejected(candidate.dir, candidate.missing));
33365
33724
  }
33366
- const ownModules = projectDir === undefined ? undefined : join46(projectDir, "node_modules");
33725
+ const ownModules = projectDir === undefined ? undefined : join47(projectDir, "node_modules");
33367
33726
  const own = staged.outerHop.rejected.find((c) => c.dir === ownModules);
33368
33727
  if (own !== undefined) {
33369
33728
  ctx.ui.warn(runnerMessages.outerHopFallbackNotice(own.dir, own.missing));
@@ -33459,7 +33818,7 @@ async function chooseEnv(ctx, files, allEnvs) {
33459
33818
  }
33460
33819
 
33461
33820
  // src/commands/flows/hybridRunDefaults.ts
33462
- import { join as join47, resolve as resolve10 } from "node:path";
33821
+ import { join as join48, resolve as resolve10 } from "node:path";
33463
33822
 
33464
33823
  // src/core/selectFlowFiles.ts
33465
33824
  function selectFlowFiles(args) {
@@ -33564,7 +33923,7 @@ async function handleHybridFlowsRun(ctx, pattern, flags, options = {}) {
33564
33923
  if (validation !== "ok") {
33565
33924
  return { error: validation.error, exitCode: 2 };
33566
33925
  }
33567
- const envDir = resolve10(join47(".qawolf", flags.env));
33926
+ const envDir = resolve10(join48(".qawolf", flags.env));
33568
33927
  const patternArgs = buildPatternArgs(pattern);
33569
33928
  const globFlows = () => resolvedDeps.expandPatterns(patternArgs, envDir, ctx.log("flows"));
33570
33929
  let files = await globFlows();
@@ -33760,12 +34119,12 @@ function registerFlowsCommand(program, signals, deps = { withResolvedEnv }) {
33760
34119
  }
33761
34120
 
33762
34121
  // src/domains/init/init.ts
33763
- import { dirname as dirname14, join as join49, relative as relative9 } from "node:path";
34122
+ import { dirname as dirname14, join as join50, relative as relative9 } from "node:path";
33764
34123
 
33765
34124
  // src/domains/init/ensurePackageJson.ts
33766
- import { join as join48 } from "node:path";
34125
+ import { join as join49 } from "node:path";
33767
34126
  async function ensurePackageJson(ctx, yes, deps) {
33768
- const pkgPath = join48(deps.cwd, "package.json");
34127
+ const pkgPath = join49(deps.cwd, "package.json");
33769
34128
  if (!await deps.fs.pathExists(pkgPath)) {
33770
34129
  const confirmed = await ctx.ui.confirm(initMessages.createPackageJsonPrompt, { yes });
33771
34130
  if (!confirmed.ok || !confirmed.value) {
@@ -33791,7 +34150,7 @@ async function ensurePackageJson(ctx, yes, deps) {
33791
34150
  ctx.ui.warn(initMessages.packageJsonInvalidJson);
33792
34151
  return;
33793
34152
  }
33794
- if (!isRecord2(parsed)) {
34153
+ if (!isRecord3(parsed)) {
33795
34154
  ctx.ui.warn(initMessages.packageJsonNotAnObject);
33796
34155
  return;
33797
34156
  }
@@ -33842,14 +34201,14 @@ async function ensurePackageJson(ctx, yes, deps) {
33842
34201
  ctx.ui.warn(initMessages.typeChanged(label));
33843
34202
  }
33844
34203
  }
33845
- function isRecord2(value) {
34204
+ function isRecord3(value) {
33846
34205
  return typeof value === "object" && value !== null && !Array.isArray(value);
33847
34206
  }
33848
34207
  function readSection(ctx, pkg, key) {
33849
34208
  const value = pkg[key];
33850
34209
  if (value === undefined)
33851
34210
  return {};
33852
- if (isRecord2(value))
34211
+ if (isRecord3(value))
33853
34212
  return value;
33854
34213
  ctx.ui.warn(initMessages.packageJsonMalformedSection(key));
33855
34214
  return;
@@ -33891,9 +34250,9 @@ function makeDefaultInitDeps() {
33891
34250
  async function handleInit(ctx, opts, deps = makeDefaultInitDeps()) {
33892
34251
  ctx.ui.gap();
33893
34252
  ctx.ui.intro(initMessages.title);
33894
- const configPath = join49(deps.cwd, "qawolf.config.ts");
33895
- const flowPath = join49(deps.cwd, "src", "flows", "example.flow.ts");
33896
- const gitignorePath = join49(deps.cwd, ".qawolf", ".gitignore");
34253
+ const configPath = join50(deps.cwd, "qawolf.config.ts");
34254
+ const flowPath = join50(deps.cwd, "src", "flows", "example.flow.ts");
34255
+ const gitignorePath = join50(deps.cwd, ".qawolf", ".gitignore");
33897
34256
  await writeWithPrompt(ctx, configPath, qawolfConfigTs, opts.yes, deps);
33898
34257
  await writeWithPrompt(ctx, flowPath, exampleFlowTs, opts.yes, deps);
33899
34258
  await writeWithPrompt(ctx, gitignorePath, qawolfGitignore, opts.yes, deps);
@@ -33928,7 +34287,7 @@ Examples:
33928
34287
  }
33929
34288
 
33930
34289
  // src/domains/install/android/avd.ts
33931
- import { join as join50 } from "node:path";
34290
+ import { join as join51 } from "node:path";
33932
34291
  async function installAvds(ctx, specs, deps) {
33933
34292
  const sdkManagerPath = sdkManagerBin(deps.androidHome, deps.platform);
33934
34293
  const avdManagerPath = avdManagerBin(deps.androidHome, deps.platform);
@@ -33938,7 +34297,7 @@ async function installAvds(ctx, specs, deps) {
33938
34297
  if (versionResult.exitCode !== 0) {
33939
34298
  throw new Error(installMessages.android.sdkmanagerNotFound(sdkManagerPath));
33940
34299
  }
33941
- const licenseFile = join50(deps.androidHome, "licenses", "android-sdk-license");
34300
+ const licenseFile = join51(deps.androidHome, "licenses", "android-sdk-license");
33942
34301
  if (deps.checkExists(licenseFile)) {
33943
34302
  ctx.ui.info(installMessages.android.licensesAlreadyAccepted);
33944
34303
  } else {
@@ -33953,7 +34312,7 @@ async function installAvds(ctx, specs, deps) {
33953
34312
  for (const spec of specs) {
33954
34313
  if (installedImages.has(spec.systemImage))
33955
34314
  continue;
33956
- const systemImg = join50(deps.androidHome, ...spec.systemImage.split(";"), "system.img");
34315
+ const systemImg = join51(deps.androidHome, ...spec.systemImage.split(";"), "system.img");
33957
34316
  if (deps.checkExists(systemImg)) {
33958
34317
  ctx.ui.info(installMessages.android.systemImageAlreadyInstalled(spec.systemImage));
33959
34318
  installedImages.add(spec.systemImage);
@@ -34394,14 +34753,14 @@ function parseKeyValueRecord(flag, pairs) {
34394
34753
  }
34395
34754
  return { ok: true, record };
34396
34755
  }
34397
- var isRecord3 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
34756
+ var isRecord4 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
34398
34757
  function setAtPath(input, path, value) {
34399
34758
  const leaf = path[path.length - 1];
34400
34759
  if (leaf === undefined)
34401
34760
  return;
34402
34761
  const target = path.slice(0, -1).reduce((node, segment) => {
34403
34762
  const existing = node[segment];
34404
- const next = isRecord3(existing) ? existing : {};
34763
+ const next = isRecord4(existing) ? existing : {};
34405
34764
  node[segment] = next;
34406
34765
  return next;
34407
34766
  }, input);
@@ -34620,8 +34979,8 @@ var chooseRunnerId = (runner, deps) => resolveIdFrom({
34620
34979
  async function resolveRunner(ctx, options, deps) {
34621
34980
  const chosen = await chooseRunnerId(options.runner, deps);
34622
34981
  if (chosen !== undefined) {
34623
- const parsed = parseRunnerId(chosen);
34624
- return parsed.ok ? { runnerId: parsed.id, type: "resolved" } : {
34982
+ const parsed = parseRunnerId(chosen.id);
34983
+ return parsed.ok ? { runnerId: parsed.id, source: chosen.source, type: "resolved" } : {
34625
34984
  error: parsed.error,
34626
34985
  exitCode: exitCodes.invalidArgs,
34627
34986
  type: "failed"
@@ -34644,6 +35003,7 @@ async function resolveRunner(ctx, options, deps) {
34644
35003
  }
34645
35004
  return {
34646
35005
  runnerId: launched.value.id,
35006
+ source: "launched",
34647
35007
  type: "launched",
34648
35008
  url: launched.value.url
34649
35009
  };
@@ -34654,6 +35014,21 @@ function announceRunner(ctx, resolved) {
34654
35014
  }
34655
35015
  }
34656
35016
 
35017
+ // src/domains/interactiveRunner/runnerRequestFailure.ts
35018
+ function runnerRequestFailure(failure, runner) {
35019
+ const fields = failureFields(failure);
35020
+ if (failure.exitCode !== exitCodes.notFound) {
35021
+ return { ...fields, exitCode: failure.exitCode ?? exitCodes.network };
35022
+ }
35023
+ const cameFrom = interactiveRunnerMessages.runnerIdCameFrom(runner.runnerId, runner.source);
35024
+ return {
35025
+ ...fields,
35026
+ errorBody: fields.errorBody ? `${fields.errorBody}
35027
+ ${cameFrom}` : cameFrom,
35028
+ exitCode: exitCodes.notFound
35029
+ };
35030
+ }
35031
+
34657
35032
  // src/core/interactiveRunner/runFiles.ts
34658
35033
  import { isAbsolute as isAbsolute5, relative as relative10, resolve as resolve11, sep as sep5 } from "node:path";
34659
35034
  function toCollectedPath(cwd, path) {
@@ -34765,10 +35140,7 @@ async function handleRunnerExec(ctx, options, deps) {
34765
35140
  ...scope.files === undefined ? {} : { files: scope.files }
34766
35141
  }, runnerCallOptions);
34767
35142
  if (!result.ok) {
34768
- return {
34769
- ...failureFields(result),
34770
- exitCode: result.exitCode ?? exitCodes.network
34771
- };
35143
+ return runnerRequestFailure(result, resolved);
34772
35144
  }
34773
35145
  if (result.value.outcome === "failure") {
34774
35146
  return describeEvaluateSnippetFailure(result.value);
@@ -34791,7 +35163,7 @@ async function handleRunnerExec(ctx, options, deps) {
34791
35163
  }
34792
35164
 
34793
35165
  // src/shell/interactiveRunner/collectRunFiles.ts
34794
- import { join as join52 } from "node:path";
35166
+ import { join as join53 } from "node:path";
34795
35167
 
34796
35168
  // src/core/interactiveRunner/getImports.ts
34797
35169
  function getImports(options) {
@@ -34830,46 +35202,7 @@ function isPathAlias(importPath, paths) {
34830
35202
  }
34831
35203
 
34832
35204
  // src/core/interactiveRunner/resolveImportPath.ts
34833
- import { dirname as dirname15, join as join51, normalize as normalize3 } from "node:path/posix";
34834
-
34835
- // src/core/interactiveRunner/tsconfigPaths.ts
34836
- function isRecord4(value) {
34837
- return typeof value === "object" && value !== null;
34838
- }
34839
- function isTsconfigPaths(value) {
34840
- return isRecord4(value) && Object.values(value).every((targets) => Array.isArray(targets) && targets.every((target) => typeof target === "string"));
34841
- }
34842
- function parseTsconfigPaths(tsconfigContent) {
34843
- let parsed;
34844
- try {
34845
- parsed = JSON.parse(tsconfigContent);
34846
- } catch {
34847
- return;
34848
- }
34849
- if (!isRecord4(parsed))
34850
- return;
34851
- const compilerOptions = parsed["compilerOptions"];
34852
- if (!isRecord4(compilerOptions))
34853
- return;
34854
- const paths = compilerOptions["paths"];
34855
- return isTsconfigPaths(paths) ? paths : undefined;
34856
- }
34857
- function resolvePathAlias(importPath, paths) {
34858
- if (paths === undefined)
34859
- return;
34860
- for (const [pattern, targets] of Object.entries(paths)) {
34861
- const prefix = pattern.replace("*", "");
34862
- if (!importPath.startsWith(prefix))
34863
- continue;
34864
- const [target] = targets;
34865
- if (target !== undefined) {
34866
- return target.replace("*", importPath.slice(prefix.length));
34867
- }
34868
- }
34869
- return;
34870
- }
34871
-
34872
- // src/core/interactiveRunner/resolveImportPath.ts
35205
+ import { dirname as dirname15, join as join52, normalize as normalize3 } from "node:path/posix";
34873
35206
  var supportedExtensions = [".ts", ".js"];
34874
35207
  function candidatesForExplicitExtension(options) {
34875
35208
  const matching = supportedExtensions.find((extension) => options.importPath.endsWith(extension));
@@ -34883,7 +35216,7 @@ function candidatesForExplicitExtension(options) {
34883
35216
  }
34884
35217
  function resolveImportPath(options) {
34885
35218
  const aliasTarget = resolvePathAlias(options.importPath, options.tsconfigPaths);
34886
- const resolvedPath = aliasTarget === undefined ? normalize3(join51(dirname15(options.importingFilePath), options.importPath)) : normalize3(aliasTarget);
35219
+ const resolvedPath = aliasTarget === undefined ? normalize3(join52(dirname15(options.importingFilePath), options.importPath)) : normalize3(aliasTarget);
34887
35220
  const hasExplicitExtension = supportedExtensions.some((extension) => options.importPath.endsWith(extension));
34888
35221
  const candidates = hasExplicitExtension ? candidatesForExplicitExtension({
34889
35222
  importPath: options.importPath,
@@ -34907,7 +35240,7 @@ function resolveImportPath(options) {
34907
35240
  var tsconfigPath = "tsconfig.json";
34908
35241
  async function collectRunFiles(options) {
34909
35242
  const held = await listShippablePaths(options);
34910
- const readFile = (path) => options.fs.readFile(join52(options.cwd, path));
35243
+ const readFile = (path) => options.fs.readFile(join53(options.cwd, path));
34911
35244
  const tsconfigContent = held.has(tsconfigPath) ? await readFile(tsconfigPath).catch(() => {
34912
35245
  return;
34913
35246
  }) : undefined;
@@ -34990,7 +35323,7 @@ function makeRunnerId() {
34990
35323
  }
34991
35324
 
34992
35325
  // src/shell/interactiveRunner/runFilesManifest.ts
34993
- import { join as join53 } from "node:path";
35326
+ import { join as join54 } from "node:path";
34994
35327
  var manifestFileName = "runner-files.json";
34995
35328
  var manifestSchema2 = object({
34996
35329
  files: array(object({ contentHash: string2(), path: string2() })),
@@ -34998,8 +35331,8 @@ var manifestSchema2 = object({
34998
35331
  version: literal(1)
34999
35332
  });
35000
35333
  function makeRunFilesManifestStore(options) {
35001
- const directory = join53(options.cwd, qawolfDir);
35002
- const path = join53(directory, manifestFileName);
35334
+ const directory = join54(options.cwd, qawolfDir);
35335
+ const path = join54(directory, manifestFileName);
35003
35336
  return {
35004
35337
  read: () => readJsonFile(options.fs, path, manifestSchema2),
35005
35338
  async write(manifest) {
@@ -35010,7 +35343,7 @@ function makeRunFilesManifestStore(options) {
35010
35343
  }
35011
35344
 
35012
35345
  // src/shell/interactiveRunner/runnerStore.ts
35013
- import { join as join54 } from "node:path";
35346
+ import { join as join55 } from "node:path";
35014
35347
  var storeFileName2 = "runner.json";
35015
35348
  var runnersDirName = "runners";
35016
35349
  var storedRunnerSchema = object({
@@ -35021,10 +35354,10 @@ var storeSchema2 = object({
35021
35354
  defaultRunnerId: string2().optional()
35022
35355
  });
35023
35356
  function makeRunnerStore(options) {
35024
- const directory = join54(options.cwd, qawolfDir);
35025
- const path = join54(directory, storeFileName2);
35026
- const runnersDir = join54(directory, runnersDirName);
35027
- const runnerPath = (runnerId) => join54(runnersDir, `${encodeURIComponent(runnerId)}.json`);
35357
+ const directory = join55(options.cwd, qawolfDir);
35358
+ const path = join55(directory, storeFileName2);
35359
+ const runnersDir = join55(directory, runnersDirName);
35360
+ const runnerPath = (runnerId) => join55(runnersDir, `${encodeURIComponent(runnerId)}.json`);
35028
35361
  const writeAtomically = (target, contents) => writeJsonFileAtomically(options.fs, target, contents);
35029
35362
  const readDefaultRunnerId = async () => {
35030
35363
  const stored = await readJsonFile(options.fs, path, storeSchema2);
@@ -35050,7 +35383,7 @@ function makeRunnerStore(options) {
35050
35383
  },
35051
35384
  readDefaultRunnerId,
35052
35385
  async readRunners() {
35053
- const runners = await Promise.all((await readRunnerFileNames()).map((name) => readJsonFile(options.fs, join54(runnersDir, name), storedRunnerSchema)));
35386
+ const runners = await Promise.all((await readRunnerFileNames()).map((name) => readJsonFile(options.fs, join55(runnersDir, name), storedRunnerSchema)));
35054
35387
  return runners.filter((runner) => !!runner).sort((left, right) => left.id.localeCompare(right.id));
35055
35388
  },
35056
35389
  async rememberLaunch(runner) {
@@ -35062,7 +35395,7 @@ function makeRunnerStore(options) {
35062
35395
  await Promise.all(runnerIds.map((runnerId) => options.fs.rm(runnerPath(runnerId), { force: true })));
35063
35396
  const names = await readRunnerFileNames();
35064
35397
  await Promise.all(names.map(async (name) => {
35065
- const runnerFile = join54(runnersDir, name);
35398
+ const runnerFile = join55(runnersDir, name);
35066
35399
  const contents = await options.fs.readFile(runnerFile).catch(() => {
35067
35400
  return;
35068
35401
  });
@@ -35177,7 +35510,7 @@ async function handleRunnerHighlightSelector(ctx, options, deps) {
35177
35510
  const selector = options.selector ?? "";
35178
35511
  const result = await ctx.platformClient.callPublicApi(publicContractsV1.runner.highlightSelector, { id: resolved.runnerId, selector }, runnerCallOptions);
35179
35512
  if (!result.ok) {
35180
- return { ...failureFields(result), exitCode: exitCodes.network };
35513
+ return runnerRequestFailure(result, resolved);
35181
35514
  }
35182
35515
  const { outcome } = result.value;
35183
35516
  switch (outcome) {
@@ -35240,7 +35573,7 @@ function registerRunnerHighlightSelectorCommand(runner, signals) {
35240
35573
  }
35241
35574
 
35242
35575
  // src/domains/interactiveRunner/importPackage.ts
35243
- import { join as join55 } from "node:path";
35576
+ import { join as join56 } from "node:path";
35244
35577
 
35245
35578
  // src/core/interactiveRunner/npmDependencies.ts
35246
35579
  var sectionsInPrecedenceOrder = ["dependencies", "devDependencies"];
@@ -35281,7 +35614,7 @@ function readNpmDependencies(packageJsonContent) {
35281
35614
  // src/domains/interactiveRunner/importPackage.ts
35282
35615
  var defaultPackageVersion = "latest";
35283
35616
  async function handleRunnerImportPackage(ctx, options, deps) {
35284
- const content = await deps.readFile(join55(deps.cwd, runPackageJsonPath)).catch(() => {
35617
+ const content = await deps.readFile(join56(deps.cwd, runPackageJsonPath)).catch(() => {
35285
35618
  return;
35286
35619
  });
35287
35620
  if (content === undefined) {
@@ -35313,10 +35646,7 @@ async function handleRunnerImportPackage(ctx, options, deps) {
35313
35646
  packageVersion
35314
35647
  }, runnerCallOptions);
35315
35648
  if (!result.ok) {
35316
- return {
35317
- ...failureFields(result),
35318
- exitCode: result.exitCode ?? exitCodes.network
35319
- };
35649
+ return runnerRequestFailure(result, resolved);
35320
35650
  }
35321
35651
  if (result.value.outcome === "failure") {
35322
35652
  const failure = result.value;
@@ -35383,7 +35713,7 @@ async function handleRunnerInspect(ctx, options, deps) {
35383
35713
  }
35384
35714
  const result = await ctx.platformClient.callPublicApi(publicContractsV1.runner.inspect, { id: resolved.runnerId, request: built.request }, runnerCallOptions);
35385
35715
  if (!result.ok) {
35386
- return { ...failureFields(result), exitCode: exitCodes.network };
35716
+ return runnerRequestFailure(result, resolved);
35387
35717
  }
35388
35718
  if (result.value.outcome === "failure") {
35389
35719
  const failure = result.value;
@@ -35518,7 +35848,7 @@ async function handleRunnerInspectMobile(ctx, options, deps) {
35518
35848
  }
35519
35849
  const result = await ctx.platformClient.callPublicApi(publicContractsV1.runner.inspectMobile, { id: resolved.runnerId, request: built.request }, runnerCallOptions);
35520
35850
  if (!result.ok) {
35521
- return { ...failureFields(result), exitCode: exitCodes.network };
35851
+ return runnerRequestFailure(result, resolved);
35522
35852
  }
35523
35853
  if (result.value.outcome === "success") {
35524
35854
  const value = result.value;
@@ -35810,14 +36140,11 @@ async function handleRunnerAct(ctx, options, deps) {
35810
36140
  ...options.screenshot === undefined ? {} : { withScreenshot: true }
35811
36141
  }, runnerCallOptions);
35812
36142
  if (!result.ok) {
35813
- const fields = failureFields(result);
35814
- return {
36143
+ const fields = runnerRequestFailure(result, resolved);
36144
+ return result.mayHaveArrived ? {
35815
36145
  ...fields,
35816
- ...result.mayHaveArrived ? {
35817
- error: appendSentence(fields.error, interactiveRunnerMessages.actionMayHaveHappened)
35818
- } : {},
35819
- exitCode: exitCodes.network
35820
- };
36146
+ error: appendSentence(fields.error, interactiveRunnerMessages.actionMayHaveHappened)
36147
+ } : fields;
35821
36148
  }
35822
36149
  const answer = result.value;
35823
36150
  if (answer.outcome === "success") {
@@ -35862,9 +36189,8 @@ async function handleRunnerScreenshot(ctx, options, deps) {
35862
36189
  };
35863
36190
  }
35864
36191
  const result = await ctx.platformClient.callPublicApi(publicContractsV1.runner.takeScreenshot, { id: resolved.runnerId }, runnerCallOptions);
35865
- if (!result.ok) {
35866
- return { ...failureFields(result), exitCode: exitCodes.network };
35867
- }
36192
+ if (!result.ok)
36193
+ return runnerRequestFailure(result, resolved);
35868
36194
  if (result.value.outcome === "success") {
35869
36195
  const written = await deps.writeScreenshot({
35870
36196
  imageJpegBase64: result.value.imageJpegBase64,
@@ -35969,20 +36295,16 @@ var unreachableFailure = {
35969
36295
  error: interactiveRunnerMessages.runnerUnreachable,
35970
36296
  exitCode: exitCodes.network
35971
36297
  };
35972
- async function readJournal(ctx, runnerId, request) {
36298
+ async function readJournal(ctx, runner, request) {
35973
36299
  const result = await ctx.platformClient.callPublicApi(publicContractsV1.runner.readJournal, {
35974
- id: runnerId,
36300
+ id: runner.runnerId,
35975
36301
  stream: request.stream,
35976
36302
  ...request.runId === undefined ? {} : { runId: request.runId },
35977
36303
  ...request.sinceSequence === undefined ? {} : { sinceSequence: request.sinceSequence },
35978
36304
  ...request.tail === undefined ? {} : { tail: request.tail }
35979
36305
  }, runnerCallOptions);
35980
36306
  if (!result.ok) {
35981
- return {
35982
- ...failureFields(result),
35983
- exitCode: exitCodes.network,
35984
- type: "failed"
35985
- };
36307
+ return { ...runnerRequestFailure(result, runner), type: "failed" };
35986
36308
  }
35987
36309
  if (result.value.outcome === "failure") {
35988
36310
  result.value.failureReason;
@@ -35997,7 +36319,7 @@ async function handleRunnerKeepalive(ctx, options, deps) {
35997
36319
  if (resolved.type === "failed") {
35998
36320
  return { ...failureFields(resolved), exitCode: resolved.exitCode };
35999
36321
  }
36000
- const window = await readJournal(ctx, resolved.runnerId, {
36322
+ const window = await readJournal(ctx, resolved, {
36001
36323
  stream: "run-status",
36002
36324
  tail: 1
36003
36325
  });
@@ -36106,7 +36428,7 @@ async function handleRunnerStopRun(ctx, options, deps) {
36106
36428
  }
36107
36429
  const result = await ctx.platformClient.callPublicApi(publicContractsV1.runner.stopRun, { id: resolved.runnerId }, runnerCallOptions);
36108
36430
  if (!result.ok) {
36109
- return { ...failureFields(result), exitCode: exitCodes.network };
36431
+ return runnerRequestFailure(result, resolved);
36110
36432
  }
36111
36433
  if (result.value.outcome === "failure") {
36112
36434
  result.value.failureReason;
@@ -36129,7 +36451,7 @@ async function handleRunnerTerminate(ctx, options, deps) {
36129
36451
  id: resolved.runnerId
36130
36452
  }, runnerCallOptions);
36131
36453
  if (!result.ok) {
36132
- return { ...failureFields(result), exitCode: exitCodes.network };
36454
+ return runnerRequestFailure(result, resolved);
36133
36455
  }
36134
36456
  await deps.store.forgetRunner(resolved.runnerId).catch(() => {
36135
36457
  ctx.ui.warn(interactiveRunnerMessages.defaultNotForgotten(resolved.runnerId));
@@ -36177,7 +36499,7 @@ async function handleRunnerPromoteSnapshot(ctx, options, deps) {
36177
36499
  screenshotPath: options.screenshotPath
36178
36500
  }, runnerCallOptions);
36179
36501
  if (!result.ok) {
36180
- return { ...failureFields(result), exitCode: exitCodes.network };
36502
+ return runnerRequestFailure(result, resolved);
36181
36503
  }
36182
36504
  if (result.value.outcome === "success") {
36183
36505
  ctx.ui.output(result.value, interactiveRunnerMessages.snapshotPromoted(options.screenshotPath, options.baselinePath));
@@ -36301,12 +36623,12 @@ function parseEventsOptions(options) {
36301
36623
  }
36302
36624
 
36303
36625
  // src/domains/interactiveRunner/journalCursor.ts
36304
- function createJournalCursor(ctx, runnerId, request) {
36626
+ function createJournalCursor(ctx, runner, request) {
36305
36627
  let sinceSequence = request.sinceSequence;
36306
36628
  let tail = request.tail;
36307
36629
  let warnedUnsearchedHistory = false;
36308
36630
  return async function read() {
36309
- const window = await readJournal(ctx, runnerId, {
36631
+ const window = await readJournal(ctx, runner, {
36310
36632
  ...request,
36311
36633
  sinceSequence,
36312
36634
  tail
@@ -36328,8 +36650,8 @@ function createJournalCursor(ctx, runnerId, request) {
36328
36650
  return { entries: window.value.entries, type: "entries" };
36329
36651
  };
36330
36652
  }
36331
- function createPrintingCursor(ctx, runnerId, request, format) {
36332
- const read = createJournalCursor(ctx, runnerId, request);
36653
+ function createPrintingCursor(ctx, runner, request, format) {
36654
+ const read = createJournalCursor(ctx, runner, request);
36333
36655
  return async () => {
36334
36656
  const window = await read();
36335
36657
  if (window.type !== "entries")
@@ -36370,7 +36692,7 @@ async function handleRunnerEvents(ctx, options, deps) {
36370
36692
  if (!known.includes(parsed.value.stream)) {
36371
36693
  ctx.ui.warn(interactiveRunnerMessages.unknownStream(parsed.value.stream, known));
36372
36694
  }
36373
- const read = createJournalCursor(ctx, resolved.runnerId, parsed.value);
36695
+ const read = createJournalCursor(ctx, resolved, parsed.value);
36374
36696
  const unreachable = createUnreachableBudget(pollIntervalMs3);
36375
36697
  const maxPolls = Math.max(1, Math.ceil(timeout.seconds * 1000 / pollIntervalMs3));
36376
36698
  for (let poll = 1;; poll++) {
@@ -36426,12 +36748,12 @@ var anchorPollIntervalMs = 1000;
36426
36748
  async function resolveRecorderAnchor(ctx, resolved, deps) {
36427
36749
  if (resolved.type === "launched")
36428
36750
  return { ok: true, sinceSequence: 0 };
36429
- return anchorRecorderCursor(ctx, resolved.runnerId, deps);
36751
+ return anchorRecorderCursor(ctx, resolved, deps);
36430
36752
  }
36431
- async function anchorRecorderCursor(ctx, runnerId, deps) {
36753
+ async function anchorRecorderCursor(ctx, runner, deps) {
36432
36754
  const unreachable = createUnreachableBudget(anchorPollIntervalMs);
36433
36755
  for (;; ) {
36434
- const anchor = await readJournal(ctx, runnerId, {
36756
+ const anchor = await readJournal(ctx, runner, {
36435
36757
  stream: "recorder",
36436
36758
  tail: 1
36437
36759
  });
@@ -36451,13 +36773,13 @@ function createFollowPrinters(ctx, options) {
36451
36773
  const jsonLine = (payload) => JSON.stringify(payload);
36452
36774
  const printers = [];
36453
36775
  if (options.logs) {
36454
- printers.push(createPrintingCursor(ctx, options.runnerId, { runId: options.runId, stream: "run-logs" }, formatRunLogLine));
36776
+ printers.push(createPrintingCursor(ctx, options.runner, { runId: options.runId, stream: "run-logs" }, formatRunLogLine));
36455
36777
  }
36456
36778
  if (options.runEvents) {
36457
- printers.push(createPrintingCursor(ctx, options.runnerId, { runId: options.runId, stream: "run-events" }, jsonLine));
36779
+ printers.push(createPrintingCursor(ctx, options.runner, { runId: options.runId, stream: "run-events" }, jsonLine));
36458
36780
  }
36459
36781
  if (options.recorderSinceSequence !== undefined) {
36460
- printers.push(createPrintingCursor(ctx, options.runnerId, { sinceSequence: options.recorderSinceSequence, stream: "recorder" }, jsonLine));
36782
+ printers.push(createPrintingCursor(ctx, options.runner, { sinceSequence: options.recorderSinceSequence, stream: "recorder" }, jsonLine));
36461
36783
  }
36462
36784
  return printers;
36463
36785
  }
@@ -36476,7 +36798,7 @@ function reportSettlement2(ctx, settlement) {
36476
36798
  }
36477
36799
  async function followRun(ctx, options, deps) {
36478
36800
  const printers = createFollowPrinters(ctx, options);
36479
- const readStatus = createJournalCursor(ctx, options.runnerId, {
36801
+ const readStatus = createJournalCursor(ctx, options.runner, {
36480
36802
  runId: options.runId,
36481
36803
  stream: "run-status"
36482
36804
  });
@@ -36523,7 +36845,7 @@ async function followRun(ctx, options, deps) {
36523
36845
  }
36524
36846
  if (poll >= maxPolls) {
36525
36847
  return {
36526
- error: interactiveRunnerMessages.followTimedOut(options.runId, options.runnerId, options.timeoutSeconds),
36848
+ error: interactiveRunnerMessages.followTimedOut(options.runId, options.runner.runnerId, options.timeoutSeconds),
36527
36849
  exitCode: exitCodes.timeout
36528
36850
  };
36529
36851
  }
@@ -36731,10 +37053,7 @@ async function sendRunFlowRequest(ctx, options, delta) {
36731
37053
  }, runnerCallOptions);
36732
37054
  if (!result.ok) {
36733
37055
  return {
36734
- failure: {
36735
- ...failureFields(result),
36736
- exitCode: result.exitCode ?? exitCodes.network
36737
- },
37056
+ failure: runnerRequestFailure(result, options.resolved),
36738
37057
  type: "failed"
36739
37058
  };
36740
37059
  }
@@ -36867,7 +37186,7 @@ async function handleRunnerRun(ctx, options, deps) {
36867
37186
  recorderSinceSequence,
36868
37187
  runEvents: options.runEvents,
36869
37188
  runId,
36870
- runnerId: resolved.runnerId,
37189
+ runner: resolved,
36871
37190
  timeoutSeconds: timeout.seconds
36872
37191
  }, deps);
36873
37192
  }
@@ -36939,4 +37258,4 @@ createProgram({ signals }).parseAsync().catch(() => {
36939
37258
  process.exitCode = 1;
36940
37259
  }).finally(() => exitWhenIdle(typeof process.exitCode === "number" ? process.exitCode : 0));
36941
37260
 
36942
- //# debugId=65A771FAB553A0D964756E2164756E21
37261
+ //# debugId=59D2DE48FE68917864756E2164756E21