@qawolf/cli 1.29.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.
@@ -9463,15 +9463,14 @@ var makeContractsV1 = (ids) => {
9463
9463
  };
9464
9464
  var publicContractsV1 = makeContractsV1(defaultIdSchemas);
9465
9465
 
9466
- // src/core/pluralize.ts
9467
- function pluralize(count, singular, plural = `${singular}s`) {
9468
- return `${String(count)} ${count === 1 ? singular : plural}`;
9469
- }
9470
-
9471
9466
  // src/core/formatSeconds.ts
9472
9467
  function formatSeconds(ms) {
9473
9468
  return `${Math.round(ms / 1000)}s`;
9474
9469
  }
9470
+ // src/core/pluralize.ts
9471
+ function pluralize(count, singular, plural = `${singular}s`) {
9472
+ return `${String(count)} ${count === 1 ? singular : plural}`;
9473
+ }
9475
9474
 
9476
9475
  // src/core/messages/authErrors.ts
9477
9476
  var authErrorMessages = {
@@ -9486,7 +9485,14 @@ var authErrorMessages = {
9486
9485
  rejected401: (noun) => `QA Wolf API rejected the${noun ? ` ${noun}` : ""} request (HTTP 401). Check your API key.`,
9487
9486
  rejected402: (noun) => `QA Wolf API refused the${noun ? ` ${noun}` : ""} request (HTTP 402): billing prevented it.`,
9488
9487
  rejected403: (noun) => `QA Wolf API rejected the${noun ? ` ${noun}` : ""} request (HTTP 403). Check that your API key has access to this environment.`,
9489
- notFound404: (noun) => `QA Wolf API could not find ${noun ? `${noun} for that environment` : "that environment"} (HTTP 404). Check the --env value.`,
9488
+ notFound404Environment: (noun) => `QA Wolf API could not find ${noun ? `${noun} for that environment` : "that environment"} (HTTP 404). Check the --env value.`,
9489
+ notFound404Runner: (runnerId) => runnerId === undefined ? "That runner is not running (HTTP 404)." : `Runner ${runnerId} is not running (HTTP 404).`,
9490
+ runnerIsGone: "It was never launched, or it has since been terminated or idled out.",
9491
+ 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.`,
9492
+ notFound404Run: (runId) => `QA Wolf has no run ${runId ?? "by that id"} on this team (HTTP 404).`,
9493
+ 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>"}.`,
9494
+ notFound404Record: (noun, id) => `QA Wolf has no ${noun} ${id} (HTTP 404).`,
9495
+ notFound404: (noun) => noun === undefined ? "QA Wolf found nothing matching the request (HTTP 404)." : `QA Wolf found nothing matching the ${noun} request (HTTP 404).`,
9490
9496
  failedWithStatus: (status, noun) => `QA Wolf API${noun ? ` ${noun}` : ""} request failed (HTTP ${status}).`,
9491
9497
  networkUnreachable: (baseUrl, noun) => `Could not reach the QA Wolf API at ${baseUrl}${noun ? ` to fetch ${noun}` : ""}. Check your network connection and QAWOLF_HOST_URL.`,
9492
9498
  timedOut: (timeoutMs, noun) => `The QA Wolf API${noun ? ` ${noun}` : ""} request timed out after ${formatSeconds(timeoutMs)}. The work may still be finishing on the platform.`,
@@ -9665,7 +9671,7 @@ var flowsMessages = {
9665
9671
  extractingBundle: "Extracting bundle",
9666
9672
  downloadingTeamStorageAssets: "Downloading team-storage assets",
9667
9673
  downloadingTeamStorageAssetsProgress: (current, total) => `Downloading team-storage assets (${String(current)}/${String(total)})`,
9668
- teamStorageRequiresTeamKey: "Team storage requires a team API key; organization keys are not supported here.",
9674
+ teamStorageRequiresTeam: "Team storage needs a team. Pull an environment to name its team, choose a workspace with 'qawolf auth switch', or use a team API key.",
9669
9675
  summary: (result, assetsAbs) => {
9670
9676
  const flows = pluralize(result.flowCount, "flow");
9671
9677
  const envVars = result.envVarCount === 0 ? "" : ` and ${pluralize(result.envVarCount, "environment variable")}`;
@@ -9815,17 +9821,18 @@ var interactMessages = {
9815
9821
  };
9816
9822
 
9817
9823
  // src/core/messages/interactiveRunner/lifecycle.ts
9824
+ var pageAt = (url) => `Its runner page is at ${url}`;
9818
9825
  var noRunnerId = "No runner id. Pass --runner, set QAWOLF_RUNNER_ID, or run qawolf runner launch first.";
9819
9826
  var lifecycleMessages = {
9820
- alreadyRunning: (id) => `Runner ${id} was already running.`,
9827
+ alreadyRunning: (id, url) => `Runner ${id} was already running. ${pageAt(url)}`,
9821
9828
  defaultNotRemembered: (id) => `Runner ${id} could not be written to .qawolf as this directory's default, so later commands will not find it on their own. Pass --runner ${id}, or set QAWOLF_RUNNER_ID=${id}.`,
9822
9829
  defaultNotForgotten: (id) => `Runner ${id} was terminated, but it could not be removed from .qawolf as this directory's default, so later commands will still be sent to it. Pass --runner, or launch a new runner.`,
9823
9830
  envRunnerIdShadowsLaunch: (launchedId, envId) => `QAWOLF_RUNNER_ID=${envId} is still set, so commands that omit --runner will keep targeting it instead of the runner just launched. Pass --runner ${launchedId} to address this one.`,
9824
9831
  keptAlive: (id) => `Runner ${id} is alive, and its inactivity clock has been reset.`,
9825
9832
  launchFailed: (id, error) => `Launching runner ${id} failed. ${error}`,
9826
9833
  launchLost: (id, error) => `Launching runner ${id} failed. ${error}. The request may still have reached QA Wolf and started a runner, so relaunch the same id with qawolf runner launch --id ${id} to attach to it rather than start a second one, or terminate it with qawolf runner terminate --runner ${id}.`,
9827
- launched: (id) => `Launched runner ${id}.`,
9828
- launchedForCommand: (id) => `No runner was given, so launched ${id} for this command. Its browser is fresh: nothing has been run on it and nothing is signed in. It bills until it is terminated or idles out, so terminate it with qawolf runner terminate --runner ${id} when you are done.`,
9834
+ launched: (id, url) => `Launched runner ${id}. ${pageAt(url)}`,
9835
+ launchedForCommand: (id, url) => `No runner was given, so launched ${id} for this command. Its browser is fresh: nothing has been run on it and nothing is signed in. It bills until it is terminated or idles out, so terminate it with qawolf runner terminate --runner ${id} when you are done. ${pageAt(url)}`,
9829
9836
  noRunnerIdForImport: `${noRunnerId} An install also needs a live run to go into, which a runner gets from qawolf runner run.`,
9830
9837
  noRunnerIdForHighlight: `${noRunnerId} Highlighting also needs a live page to draw on, which a runner gets from its first run: run a flow on it with qawolf runner run.`,
9831
9838
  noRunnerIdForInspect: `${noRunnerId} Inspecting also needs a page, which a runner gets from its first run: run a flow on it with qawolf runner run.`,
@@ -9836,7 +9843,14 @@ var lifecycleMessages = {
9836
9843
  terminated: (id) => `Terminated runner ${id}.`,
9837
9844
  runStopped: (id) => `Stopped the run on runner ${id}. The runner is still up, on whatever page the run reached.`,
9838
9845
  nothingToStop: (id) => `Runner ${id} had nothing to stop. The run had already finished, or none had been submitted.`,
9839
- runnerUnreachable: "The runner could not be reached. It may still be starting, or it may have terminated after inactivity. Retry, or launch it again."
9846
+ runnerUnreachable: "The runner could not be reached. It may still be starting, or it may have terminated after inactivity. Retry, or launch it again.",
9847
+ runnerIdCameFrom: (id, source) => ({
9848
+ environment: `The id ${id} came from QAWOLF_RUNNER_ID.`,
9849
+ flag: `The id ${id} came from --runner.`,
9850
+ given: `The id ${id} is the one this call named.`,
9851
+ launched: `Runner ${id} was launched for this command.`,
9852
+ stored: `The id ${id} came from the runner this directory last launched, recorded in .qawolf.`
9853
+ })[source]
9840
9854
  };
9841
9855
 
9842
9856
  // src/core/messages/interactiveRunner/list.ts
@@ -9935,7 +9949,9 @@ ${dir}`,
9935
9949
  ].join(`
9936
9950
  `),
9937
9951
  outerHopCarriedOver: (names) => `Carried over ${pluralize(names.length, "undeclared package")} from the project node_modules: ${listNames(names)}. Declare them in package.json "dependencies".`,
9938
- 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.`
9952
+ 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.`,
9953
+ 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.`,
9954
+ 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.`
9939
9955
  };
9940
9956
  // src/shell/exit.ts
9941
9957
  var exitCodes = {
@@ -9946,7 +9962,8 @@ var exitCodes = {
9946
9962
  network: 4,
9947
9963
  config: 5,
9948
9964
  timeout: 6,
9949
- payment: 7
9965
+ payment: 7,
9966
+ notFound: 8
9950
9967
  };
9951
9968
 
9952
9969
  // src/core/sleep.ts
@@ -10017,7 +10034,8 @@ async function listRunners(ctx, deps) {
10017
10034
  id: runner.id,
10018
10035
  isDefault: runner.id === defaultRunnerId,
10019
10036
  launchedHere: heldIds.has(runner.id),
10020
- runnerName: runner.runnerName
10037
+ runnerName: runner.runnerName,
10038
+ url: runner.url
10021
10039
  }));
10022
10040
  return {
10023
10041
  items: items.sort((left, right) => rank(left) - rank(right) || left.id.localeCompare(right.id)),
@@ -10893,41 +10911,70 @@ function isPathAlias(importPath, paths) {
10893
10911
  // src/core/interactiveRunner/resolveImportPath.ts
10894
10912
  import { dirname as dirname2, join, normalize as normalize2 } from "node:path/posix";
10895
10913
 
10896
- // src/core/interactiveRunner/tsconfigPaths.ts
10914
+ // src/core/aliasImports/tsconfigPaths.ts
10897
10915
  function isRecord(value) {
10898
10916
  return typeof value === "object" && value !== null;
10899
10917
  }
10900
10918
  function isTsconfigPaths(value) {
10901
10919
  return isRecord(value) && Object.values(value).every((targets) => Array.isArray(targets) && targets.every((target) => typeof target === "string"));
10902
10920
  }
10903
- function parseTsconfigPaths(tsconfigContent) {
10921
+ function parseTsconfigContent(tsconfigContent) {
10904
10922
  let parsed;
10905
10923
  try {
10906
10924
  parsed = JSON.parse(tsconfigContent);
10907
10925
  } catch {
10908
- return;
10926
+ return { type: "unparseable" };
10909
10927
  }
10910
10928
  if (!isRecord(parsed))
10911
- return;
10929
+ return { paths: undefined, type: "parsed" };
10912
10930
  const compilerOptions = parsed["compilerOptions"];
10913
10931
  if (!isRecord(compilerOptions))
10914
- return;
10932
+ return { paths: undefined, type: "parsed" };
10915
10933
  const paths = compilerOptions["paths"];
10916
- return isTsconfigPaths(paths) ? paths : undefined;
10934
+ return {
10935
+ paths: isTsconfigPaths(paths) ? paths : undefined,
10936
+ type: "parsed"
10937
+ };
10938
+ }
10939
+ function parseTsconfigPaths(tsconfigContent) {
10940
+ const parsed = parseTsconfigContent(tsconfigContent);
10941
+ return parsed.type === "parsed" ? parsed.paths : undefined;
10942
+ }
10943
+ function parseWildcardPattern(pattern) {
10944
+ const wildcard = pattern.indexOf("*");
10945
+ if (wildcard === -1 || wildcard !== pattern.lastIndexOf("*"))
10946
+ return;
10947
+ return {
10948
+ prefix: pattern.slice(0, wildcard),
10949
+ suffix: pattern.slice(wildcard + 1)
10950
+ };
10951
+ }
10952
+ function matchesWildcard(importPath, { prefix, suffix }) {
10953
+ return importPath.length >= prefix.length + suffix.length && importPath.startsWith(prefix) && importPath.endsWith(suffix);
10954
+ }
10955
+ function longestPrefixMatch(importPath, paths) {
10956
+ return Object.entries(paths).flatMap(([pattern, targets]) => {
10957
+ const parsed = parseWildcardPattern(pattern);
10958
+ if (parsed === undefined || !matchesWildcard(importPath, parsed)) {
10959
+ return [];
10960
+ }
10961
+ return [{ pattern: parsed, targets }];
10962
+ }).reduce((best, candidate) => best === undefined || candidate.pattern.prefix.length > best.pattern.prefix.length ? candidate : best, undefined);
10917
10963
  }
10918
10964
  function resolvePathAlias(importPath, paths) {
10919
10965
  if (paths === undefined)
10920
10966
  return;
10921
- for (const [pattern, targets] of Object.entries(paths)) {
10922
- const prefix = pattern.replace("*", "");
10923
- if (!importPath.startsWith(prefix))
10924
- continue;
10925
- const [target] = targets;
10926
- if (target !== undefined) {
10927
- return target.replace("*", importPath.slice(prefix.length));
10928
- }
10929
- }
10930
- return;
10967
+ const [exactTarget] = paths[importPath] ?? [];
10968
+ if (exactTarget !== undefined)
10969
+ return exactTarget;
10970
+ const match = longestPrefixMatch(importPath, paths);
10971
+ if (match === undefined)
10972
+ return;
10973
+ const [target] = match.targets;
10974
+ if (target === undefined)
10975
+ return;
10976
+ const substituted = importPath.slice(match.pattern.prefix.length, importPath.length - match.pattern.suffix.length);
10977
+ return target.replace("*", substituted);
10931
10978
  }
10932
10979
 
10933
10980
  // src/core/interactiveRunner/resolveImportPath.ts
@@ -11057,6 +11104,37 @@ import { join as join3 } from "node:path";
11057
11104
  var qawolfDir = ".qawolf";
11058
11105
  var defaultOutputDir = `${qawolfDir}/output`;
11059
11106
 
11107
+ // src/core/parseJson.ts
11108
+ function parseJson(text) {
11109
+ try {
11110
+ return JSON.parse(text);
11111
+ } catch {
11112
+ return;
11113
+ }
11114
+ }
11115
+
11116
+ // src/shell/jsonFile.ts
11117
+ var pendingWrites = 0;
11118
+ async function readJsonFile(fs, path, schema) {
11119
+ const contents = await fs.readFile(path).catch(() => {
11120
+ return;
11121
+ });
11122
+ if (contents === undefined)
11123
+ return;
11124
+ const parsed = schema.safeParse(parseJson(contents));
11125
+ return parsed.success ? parsed.data : undefined;
11126
+ }
11127
+ async function writeJsonFileAtomically(fs, path, value) {
11128
+ const pendingPath = `${path}.${String(process.pid)}.${String(++pendingWrites)}.tmp`;
11129
+ try {
11130
+ await fs.writeFile(pendingPath, `${JSON.stringify(value, undefined, 2)}
11131
+ `);
11132
+ await fs.rename(pendingPath, path);
11133
+ } finally {
11134
+ await fs.rm(pendingPath, { force: true }).catch(() => {});
11135
+ }
11136
+ }
11137
+
11060
11138
  // src/shell/interactiveRunner/runFilesManifest.ts
11061
11139
  var manifestFileName = "runner-files.json";
11062
11140
  var manifestSchema = object({
@@ -11067,33 +11145,14 @@ var manifestSchema = object({
11067
11145
  function makeRunFilesManifestStore(options) {
11068
11146
  const directory = join3(options.cwd, qawolfDir);
11069
11147
  const path = join3(directory, manifestFileName);
11070
- let pendingWrites = 0;
11071
11148
  return {
11072
- async read() {
11073
- const contents = await options.fs.readFile(path).catch(() => {
11074
- return;
11075
- });
11076
- if (contents === undefined)
11077
- return;
11078
- const parsed = manifestSchema.safeParse(parseJson(contents));
11079
- return parsed.success ? parsed.data : undefined;
11080
- },
11149
+ read: () => readJsonFile(options.fs, path, manifestSchema),
11081
11150
  async write(manifest) {
11082
- const pendingPath = `${path}.${String(process.pid)}.${String(++pendingWrites)}.tmp`;
11083
11151
  await options.fs.mkdir(directory, { recursive: true });
11084
- await options.fs.writeFile(pendingPath, `${JSON.stringify(manifest, undefined, 2)}
11085
- `);
11086
- await options.fs.rename(pendingPath, path);
11152
+ await writeJsonFileAtomically(options.fs, path, manifest);
11087
11153
  }
11088
11154
  };
11089
11155
  }
11090
- function parseJson(text) {
11091
- try {
11092
- return JSON.parse(text);
11093
- } catch {
11094
- return;
11095
- }
11096
- }
11097
11156
 
11098
11157
  // src/shell/interactiveRunner/runnerStore.ts
11099
11158
  import { join as join4 } from "node:path";
@@ -11106,34 +11165,15 @@ var storedRunnerSchema = object({
11106
11165
  var storeSchema = object({
11107
11166
  defaultRunnerId: string2().optional()
11108
11167
  });
11109
- function parseJson2(text) {
11110
- try {
11111
- return JSON.parse(text);
11112
- } catch {
11113
- return;
11114
- }
11115
- }
11116
- var pendingWrites = 0;
11117
11168
  function makeRunnerStore(options) {
11118
11169
  const directory = join4(options.cwd, qawolfDir);
11119
11170
  const path = join4(directory, storeFileName);
11120
11171
  const runnersDir = join4(directory, runnersDirName);
11121
- const nextPendingPath = (target) => `${target}.${process.pid}.${++pendingWrites}.tmp`;
11122
11172
  const runnerPath = (runnerId) => join4(runnersDir, `${encodeURIComponent(runnerId)}.json`);
11123
- const writeAtomically = async (target, contents) => {
11124
- const pendingPath = nextPendingPath(target);
11125
- await options.fs.writeFile(pendingPath, `${JSON.stringify(contents, undefined, 2)}
11126
- `);
11127
- await options.fs.rename(pendingPath, target);
11128
- };
11173
+ const writeAtomically = (target, contents) => writeJsonFileAtomically(options.fs, target, contents);
11129
11174
  const readDefaultRunnerId = async () => {
11130
- const contents = await options.fs.readFile(path).catch(() => {
11131
- return;
11132
- });
11133
- if (contents === undefined)
11134
- return;
11135
- const parsed = storeSchema.safeParse(parseJson2(contents));
11136
- return parsed.success ? parsed.data.defaultRunnerId : undefined;
11175
+ const stored = await readJsonFile(options.fs, path, storeSchema);
11176
+ return stored?.defaultRunnerId;
11137
11177
  };
11138
11178
  const writeDefaultRunnerId = async (runnerId) => {
11139
11179
  await options.fs.mkdir(directory, { recursive: true });
@@ -11155,15 +11195,7 @@ function makeRunnerStore(options) {
11155
11195
  },
11156
11196
  readDefaultRunnerId,
11157
11197
  async readRunners() {
11158
- const runners = await Promise.all((await readRunnerFileNames()).map(async (name) => {
11159
- const contents = await options.fs.readFile(join4(runnersDir, name)).catch(() => {
11160
- return;
11161
- });
11162
- if (contents === undefined)
11163
- return;
11164
- const parsed = storedRunnerSchema.safeParse(parseJson2(contents));
11165
- return parsed.success ? parsed.data : undefined;
11166
- }));
11198
+ const runners = await Promise.all((await readRunnerFileNames()).map((name) => readJsonFile(options.fs, join4(runnersDir, name), storedRunnerSchema)));
11167
11199
  return runners.filter((runner) => !!runner).sort((left, right) => left.id.localeCompare(right.id));
11168
11200
  },
11169
11201
  async rememberLaunch(runner) {
@@ -11181,7 +11213,7 @@ function makeRunnerStore(options) {
11181
11213
  });
11182
11214
  if (contents === undefined)
11183
11215
  return;
11184
- if (storedRunnerSchema.safeParse(parseJson2(contents)).success)
11216
+ if (storedRunnerSchema.safeParse(parseJson(contents)).success)
11185
11217
  return;
11186
11218
  await options.fs.rm(runnerFile, { force: true });
11187
11219
  }));
@@ -11380,6 +11412,47 @@ function makeDefaultFs() {
11380
11412
  };
11381
11413
  }
11382
11414
 
11415
+ // src/core/publicApi/notFoundSubject.ts
11416
+ var runnerRoutesThatNameNoRunner = new Set([
11417
+ "runner.launch",
11418
+ "runner.list"
11419
+ ]);
11420
+ var runRoutesThatResolveOneRun = new Set([
11421
+ "run.diagnose",
11422
+ "run.get",
11423
+ "run.reattempt",
11424
+ "run.stop"
11425
+ ]);
11426
+ var recordFieldNouns = [
11427
+ ["sessionId", "session"],
11428
+ ["triggerId", "trigger"],
11429
+ ["issueId", "issue"],
11430
+ ["flowId", "flow"],
11431
+ ["filePath", "file"]
11432
+ ];
11433
+ function field(input, name) {
11434
+ if (typeof input !== "object" || input === null)
11435
+ return;
11436
+ const value = input[name];
11437
+ return typeof value === "string" ? value : undefined;
11438
+ }
11439
+ function notFoundSubject(contractName, input) {
11440
+ if (contractName.startsWith("runner.") && !runnerRoutesThatNameNoRunner.has(contractName)) {
11441
+ return { kind: "runner", runnerId: field(input, "id") };
11442
+ }
11443
+ if (runRoutesThatResolveOneRun.has(contractName)) {
11444
+ return { kind: "run", runId: field(input, "runId") };
11445
+ }
11446
+ for (const [name, noun] of recordFieldNouns) {
11447
+ const id = field(input, name);
11448
+ if (id !== undefined)
11449
+ return { id, kind: "record", noun };
11450
+ }
11451
+ if (field(input, "environmentId") !== undefined)
11452
+ return { kind: "environment" };
11453
+ return { kind: "other" };
11454
+ }
11455
+
11383
11456
  // src/core/publicApi/flagKind.ts
11384
11457
  function flagKind(schema) {
11385
11458
  if (schema.type === "string")
@@ -11550,6 +11623,42 @@ function applyWorkspaceId(inputSchema, input, workspaceId) {
11550
11623
  return { ...input, workspaceId };
11551
11624
  }
11552
11625
 
11626
+ // src/shell/platform/describeNotFound.ts
11627
+ var m = authMessages.errors.request;
11628
+ var saysNothingMore = (reason) => /^(\w+ )*not ?found\.?$/i.test(reason.trim());
11629
+ function describeNotFound(subject, noun, reason) {
11630
+ const explained = reason && !saysNothingMore(reason) ? reason : undefined;
11631
+ const say = (own) => {
11632
+ const body = [explained ? undefined : own.guess, own.guidance].filter((line) => line);
11633
+ return {
11634
+ error: explained ? `${explained} (HTTP 404)` : own.statement,
11635
+ exitCode: exitCodes.notFound,
11636
+ ...body.length > 0 ? { errorBody: body.join(`
11637
+ `) } : {}
11638
+ };
11639
+ };
11640
+ switch (subject?.kind) {
11641
+ case "runner":
11642
+ return say({
11643
+ guess: m.runnerIsGone,
11644
+ guidance: m.launchTheRunner(subject.runnerId),
11645
+ statement: m.notFound404Runner(subject.runnerId)
11646
+ });
11647
+ case "run":
11648
+ return say({
11649
+ guess: m.runIdMayBeRunnerLocal(subject.runId),
11650
+ statement: m.notFound404Run(subject.runId)
11651
+ });
11652
+ case "record":
11653
+ return say({ statement: m.notFound404Record(subject.noun, subject.id) });
11654
+ case "other":
11655
+ return say({ statement: m.notFound404(noun) });
11656
+ case "environment":
11657
+ case undefined:
11658
+ return say({ statement: m.notFound404Environment(noun) });
11659
+ }
11660
+ }
11661
+
11553
11662
  // src/shell/platform/parseErrorBody.ts
11554
11663
  var defaultMaxLength = 1024;
11555
11664
  function asRecord(value) {
@@ -11592,69 +11701,69 @@ function clip(message, maxLength) {
11592
11701
  }
11593
11702
 
11594
11703
  // src/shell/platform/describeErrors.ts
11595
- var m = authMessages.errors;
11704
+ var m2 = authMessages.errors;
11596
11705
  var inlineReasonMaxLength = 200;
11597
11706
  function describeIdentityError(err) {
11598
11707
  if (err.kind === "http") {
11599
11708
  if (err.status === 401 || err.status === 403) {
11600
11709
  return {
11601
- error: m.identity.invalidOrUnauthorized,
11710
+ error: m2.identity.invalidOrUnauthorized,
11602
11711
  ...err.status === 401 ? { exitCode: exitCodes.auth } : {}
11603
11712
  };
11604
11713
  }
11605
11714
  return {
11606
- error: m.identity.couldNotVerify(parseErrorBody(err.body, inlineReasonMaxLength), err.status)
11715
+ error: m2.identity.couldNotVerify(parseErrorBody(err.body, inlineReasonMaxLength), err.status)
11607
11716
  };
11608
11717
  }
11609
11718
  if (err.kind === "network") {
11610
- return { error: m.identity.couldNotVerifyNetwork(err.cause.message) };
11719
+ return { error: m2.identity.couldNotVerifyNetwork(err.cause.message) };
11611
11720
  }
11612
11721
  if (err.kind === "timeout") {
11613
- return { error: m.identity.timedOut(err.timeoutMs) };
11722
+ return { error: m2.identity.timedOut(err.timeoutMs) };
11614
11723
  }
11615
- return { error: m.identity.unexpectedFormat };
11724
+ return { error: m2.identity.unexpectedFormat };
11616
11725
  }
11617
- function describeRequestError(err, baseUrl, noun) {
11726
+ function describeRequestError(err, baseUrl, noun, notFound) {
11618
11727
  if (err.kind === "http") {
11619
11728
  const reason = parseErrorBody(err.body);
11620
11729
  const body = reason ? { errorBody: reason } : {};
11621
11730
  if (err.status === 401)
11622
11731
  return {
11623
- error: m.request.rejected401(noun),
11732
+ error: m2.request.rejected401(noun),
11624
11733
  exitCode: exitCodes.auth,
11625
11734
  ...body
11626
11735
  };
11627
11736
  if (err.status === 402)
11628
11737
  return {
11629
- error: m.request.rejected402(noun),
11738
+ error: m2.request.rejected402(noun),
11630
11739
  exitCode: exitCodes.payment,
11631
11740
  ...body
11632
11741
  };
11633
11742
  if (err.status === 403)
11634
- return { error: m.request.rejected403(noun), ...body };
11743
+ return { error: m2.request.rejected403(noun), ...body };
11635
11744
  if (err.status === 404)
11636
- return { error: m.request.notFound404(noun), ...body };
11637
- return { error: m.request.failedWithStatus(err.status, noun), ...body };
11745
+ return describeNotFound(notFound, noun, reason);
11746
+ return { error: m2.request.failedWithStatus(err.status, noun), ...body };
11638
11747
  }
11639
11748
  if (err.kind === "network") {
11640
- return { error: m.request.networkUnreachable(baseUrl, noun) };
11749
+ return { error: m2.request.networkUnreachable(baseUrl, noun) };
11641
11750
  }
11642
11751
  if (err.kind === "timeout") {
11643
- return { error: m.request.timedOut(err.timeoutMs, noun) };
11752
+ return { error: m2.request.timedOut(err.timeoutMs, noun) };
11644
11753
  }
11645
- return { error: m.request.unexpectedResponse(noun) };
11754
+ return { error: m2.request.unexpectedResponse(noun) };
11646
11755
  }
11647
11756
  function describeBundleDownloadError(err) {
11648
11757
  if (err.kind === "http") {
11649
11758
  if (err.status === 401 || err.status === 403)
11650
- return m.bundle.linkExpired;
11651
- return m.bundle.failedWithStatus(err.status);
11759
+ return m2.bundle.linkExpired;
11760
+ return m2.bundle.failedWithStatus(err.status);
11652
11761
  }
11653
11762
  if (err.kind === "network")
11654
- return m.bundle.networkUnreachable;
11763
+ return m2.bundle.networkUnreachable;
11655
11764
  if (err.kind === "timeout")
11656
- return m.bundle.timedOut(err.timeoutMs);
11657
- return m.bundle.malformed;
11765
+ return m2.bundle.timedOut(err.timeoutMs);
11766
+ return m2.bundle.malformed;
11658
11767
  }
11659
11768
  function describeTeamStorageDownloadError(path, err) {
11660
11769
  if (err.kind === "http") {
@@ -11681,12 +11790,16 @@ function callPublicApi(trpc, contract, input, options) {
11681
11790
  return trpc.mutation(path, input, contract.output, options);
11682
11791
  }
11683
11792
  function makeCallPublicApiMethod(trpc, deps, readBackoffMs) {
11684
- return async (contract, input, options) => requestWithRetry({
11685
- call: () => callPublicApi(trpc, contract, applyWorkspaceId(contract.input, input, deps.workspaceId), options),
11686
- backoffMs: contract.kind === "read" ? readBackoffMs : [],
11687
- describe: (err) => describeRequestError(err, deps.baseUrl, contract.name),
11688
- sleep: deps.sleep
11689
- });
11793
+ return async (contract, input, options) => {
11794
+ const sent = applyWorkspaceId(contract.input, input, deps.workspaceId);
11795
+ const subject = notFoundSubject(contract.name, sent);
11796
+ return requestWithRetry({
11797
+ call: () => callPublicApi(trpc, contract, sent, options),
11798
+ backoffMs: contract.kind === "read" ? readBackoffMs : [],
11799
+ describe: (err) => describeRequestError(err, deps.baseUrl, contract.name, subject),
11800
+ sleep: deps.sleep
11801
+ });
11802
+ };
11690
11803
  }
11691
11804
 
11692
11805
  // node_modules/superjson/dist/double-indexed-kv.js
@@ -12800,7 +12913,8 @@ var environmentListItemSchema = object({
12800
12913
  slug: string2()
12801
12914
  });
12802
12915
  var environmentWithVariablesResponseSchema = object({
12803
- environmentVariables: record(string2(), string2())
12916
+ environmentVariables: record(string2(), string2()),
12917
+ teamId: string2()
12804
12918
  });
12805
12919
  var flowListItemSchema = object({
12806
12920
  flowId: string2(),
@@ -13077,7 +13191,10 @@ async function writeTeamStorageAssets(args, deps) {
13077
13191
 
13078
13192
  // src/shell/platform/teamStorageMethods.ts
13079
13193
  function createTeamStorageMethods(trpc, deps, fs, getIdentity) {
13080
- async function list() {
13194
+ async function list(opts) {
13195
+ if (opts?.teamId !== undefined) {
13196
+ return listTeamStorageFiles(trpc, { teamId: opts.teamId }, deps);
13197
+ }
13081
13198
  if (deps.workspaceId !== undefined) {
13082
13199
  return listTeamStorageFiles(trpc, { teamId: deps.workspaceId }, deps);
13083
13200
  }
@@ -13087,7 +13204,7 @@ function createTeamStorageMethods(trpc, deps, fs, getIdentity) {
13087
13204
  if (!("team" in identity.value)) {
13088
13205
  return {
13089
13206
  ok: false,
13090
- error: flowsMessages.pull.teamStorageRequiresTeamKey
13207
+ error: flowsMessages.pull.teamStorageRequiresTeam
13091
13208
  };
13092
13209
  }
13093
13210
  return listTeamStorageFiles(trpc, { teamId: identity.value.team.id }, deps);
@@ -13095,7 +13212,7 @@ function createTeamStorageMethods(trpc, deps, fs, getIdentity) {
13095
13212
  return {
13096
13213
  listTeamStorageFiles: list,
13097
13214
  async syncTeamStorageAssets(assetsAbs, opts) {
13098
- const files = await list();
13215
+ const files = await list({ teamId: opts?.teamId });
13099
13216
  if (!files.ok)
13100
13217
  return files;
13101
13218
  return downloadTeamStorageAssets({ assetsAbs, files: files.value }, { fetch: deps.fetch, fs, onProgress: opts?.onProgress });
@@ -13125,16 +13242,14 @@ function createPlatformClient(apiKey, deps) {
13125
13242
  ...createTeamStorageMethods(trpc, deps, fs, identityMethods.getIdentity),
13126
13243
  getFlowsBundleUrl: getFlowsBundleUrlImpl,
13127
13244
  callPublicApi: makeCallPublicApiMethod(trpc, deps, requestBackoffMs2),
13128
- async getEnvVars(envId) {
13245
+ async getEnvironmentWithVariables(envId) {
13129
13246
  const result = await requestWithRetry({
13130
13247
  call: () => trpc.query("environment.getEnvironmentWithVariables", { id: envId }, environmentWithVariablesResponseSchema),
13131
13248
  backoffMs: requestBackoffMs2,
13132
13249
  describe: (err) => describeRequestError(err, deps.baseUrl, "env-vars"),
13133
13250
  sleep: deps.sleep
13134
13251
  });
13135
- if (!result.ok)
13136
- return result;
13137
- return { ok: true, value: result.value.environmentVariables };
13252
+ return result;
13138
13253
  },
13139
13254
  async downloadBundle(envId) {
13140
13255
  const urlResult = await getFlowsBundleUrlImpl(envId);
@@ -13173,25 +13288,36 @@ function createSdkContext(options) {
13173
13288
  };
13174
13289
  }
13175
13290
 
13291
+ // src/domains/interactiveRunner/runnerRequestFailure.ts
13292
+ function runnerRequestFailure(failure, runner) {
13293
+ const fields = failureFields(failure);
13294
+ if (failure.exitCode !== exitCodes.notFound) {
13295
+ return { ...fields, exitCode: failure.exitCode ?? exitCodes.network };
13296
+ }
13297
+ const cameFrom = interactiveRunnerMessages.runnerIdCameFrom(runner.runnerId, runner.source);
13298
+ return {
13299
+ ...fields,
13300
+ errorBody: fields.errorBody ? `${fields.errorBody}
13301
+ ${cameFrom}` : cameFrom,
13302
+ exitCode: exitCodes.notFound
13303
+ };
13304
+ }
13305
+
13176
13306
  // src/domains/interactiveRunner/readJournal.ts
13177
13307
  var unreachableFailure = {
13178
13308
  error: interactiveRunnerMessages.runnerUnreachable,
13179
13309
  exitCode: exitCodes.network
13180
13310
  };
13181
- async function readJournal(ctx, runnerId, request) {
13311
+ async function readJournal(ctx, runner, request) {
13182
13312
  const result = await ctx.platformClient.callPublicApi(publicContractsV1.runner.readJournal, {
13183
- id: runnerId,
13313
+ id: runner.runnerId,
13184
13314
  stream: request.stream,
13185
13315
  ...request.runId === undefined ? {} : { runId: request.runId },
13186
13316
  ...request.sinceSequence === undefined ? {} : { sinceSequence: request.sinceSequence },
13187
13317
  ...request.tail === undefined ? {} : { tail: request.tail }
13188
13318
  }, runnerCallOptions);
13189
13319
  if (!result.ok) {
13190
- return {
13191
- ...failureFields(result),
13192
- exitCode: exitCodes.network,
13193
- type: "failed"
13194
- };
13320
+ return { ...runnerRequestFailure(result, runner), type: "failed" };
13195
13321
  }
13196
13322
  if (result.value.outcome === "failure") {
13197
13323
  result.value.failureReason;
@@ -13200,9 +13326,24 @@ async function readJournal(ctx, runnerId, request) {
13200
13326
  return { type: "read", value: result.value };
13201
13327
  }
13202
13328
 
13329
+ // src/runnerSdk/givenRunner.ts
13330
+ var givenRunner = (runnerId) => ({
13331
+ runnerId,
13332
+ source: "given"
13333
+ });
13334
+
13335
+ // src/runnerSdk/toSdkFailure.ts
13336
+ function toSdkFailure(failure) {
13337
+ return {
13338
+ error: failure.error,
13339
+ ...failure.errorBody ? { errorDetail: failure.errorBody } : {},
13340
+ ok: false
13341
+ };
13342
+ }
13343
+
13203
13344
  // src/runnerSdk/toSdkResult.ts
13204
13345
  function toSdkResult(result) {
13205
- return result.ok ? { ok: true, value: result.value } : { error: result.error, ok: false };
13346
+ return result.ok ? { ok: true, value: result.value } : toSdkFailure(result);
13206
13347
  }
13207
13348
 
13208
13349
  // src/runnerSdk/lifecycleVerbs.ts
@@ -13213,16 +13354,13 @@ function createLifecycleVerbs({ platformClient }) {
13213
13354
  async keepalive({
13214
13355
  runnerId
13215
13356
  }) {
13216
- const read = await readJournal(ctx, runnerId, {
13357
+ const read = await readJournal(ctx, givenRunner(runnerId), {
13217
13358
  stream: "run-status",
13218
13359
  tail: 1
13219
13360
  });
13220
13361
  if (read.type === "read")
13221
13362
  return { ok: true, value: { id: runnerId } };
13222
- return {
13223
- error: read.type === "unreachable" ? "The runner could not be reached." : read.error,
13224
- ok: false
13225
- };
13363
+ return read.type === "unreachable" ? { error: "The runner could not be reached.", ok: false } : toSdkFailure(read);
13226
13364
  },
13227
13365
  async launch({
13228
13366
  id,
@@ -13704,10 +13842,7 @@ async function sendRunFlowRequest(ctx, options, delta) {
13704
13842
  }, runnerCallOptions);
13705
13843
  if (!result.ok) {
13706
13844
  return {
13707
- failure: {
13708
- ...failureFields(result),
13709
- exitCode: result.exitCode ?? exitCodes.network
13710
- },
13845
+ failure: runnerRequestFailure(result, options.resolved),
13711
13846
  type: "failed"
13712
13847
  };
13713
13848
  }
@@ -13796,17 +13931,14 @@ function createRunVerbs({ deps, platformClient }) {
13796
13931
  stream,
13797
13932
  window
13798
13933
  }) {
13799
- const read = await readJournal(ctx, runnerId, {
13934
+ const read = await readJournal(ctx, givenRunner(runnerId), {
13800
13935
  stream,
13801
13936
  ...runFilter === "all-runs" ? {} : { runId: runFilter.runId },
13802
13937
  ...window === "newest" ? {} : ("tail" in window) ? { tail: window.tail } : { sinceSequence: window.sinceSequence }
13803
13938
  });
13804
13939
  if (read.type === "read")
13805
13940
  return { ok: true, value: read.value };
13806
- return {
13807
- error: read.type === "unreachable" ? "The runner could not be reached." : read.error,
13808
- ok: false
13809
- };
13941
+ return read.type === "unreachable" ? { error: "The runner could not be reached.", ok: false } : toSdkFailure(read);
13810
13942
  },
13811
13943
  async run({
13812
13944
  entryPointPath,
@@ -13828,11 +13960,11 @@ function createRunVerbs({ deps, platformClient }) {
13828
13960
  environment: prepared.environment,
13829
13961
  environmentId: prepared.environmentId,
13830
13962
  files: prepared.files,
13831
- resolved: { runnerId, type: "resolved" },
13963
+ resolved: { ...givenRunner(runnerId), type: "resolved" },
13832
13964
  selection: prepared.selection
13833
13965
  }, deps);
13834
13966
  if (!submitted.ok)
13835
- return { error: submitted.error, ok: false };
13967
+ return toSdkFailure(submitted);
13836
13968
  return {
13837
13969
  ok: true,
13838
13970
  value: {
@@ -13863,4 +13995,4 @@ export {
13863
13995
  createRunnerSdk
13864
13996
  };
13865
13997
 
13866
- //# debugId=A460E98091C1C6D964756E2164756E21
13998
+ //# debugId=C50E262AB8A599ED64756E2164756E21