@bugbug-io/sdk 14.19.1 → 14.21.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/index.js CHANGED
@@ -1339,13 +1339,13 @@ var require_Collection = __commonJS({
1339
1339
  var require_stringifyComment = __commonJS({
1340
1340
  "../../node_modules/yaml/dist/stringify/stringifyComment.js"(exports) {
1341
1341
  "use strict";
1342
- var stringifyComment = (str) => str.replace(/^(?!$)(?: $)?/gm, "#");
1342
+ var stringifyComment = (str2) => str2.replace(/^(?!$)(?: $)?/gm, "#");
1343
1343
  function indentComment(comment, indent) {
1344
1344
  if (/^\n+$/.test(comment))
1345
1345
  return comment.substring(1);
1346
1346
  return indent ? comment.replace(/^(?! *$)/gm, indent) : comment;
1347
1347
  }
1348
- var lineComment = (str, indent, comment) => str.endsWith("\n") ? indentComment(comment, indent) : comment.includes("\n") ? "\n" + indentComment(comment, indent) : (str.endsWith(" ") ? "" : " ") + comment;
1348
+ var lineComment = (str2, indent, comment) => str2.endsWith("\n") ? indentComment(comment, indent) : comment.includes("\n") ? "\n" + indentComment(comment, indent) : (str2.endsWith(" ") ? "" : " ") + comment;
1349
1349
  exports.indentComment = indentComment;
1350
1350
  exports.lineComment = lineComment;
1351
1351
  exports.stringifyComment = stringifyComment;
@@ -1499,16 +1499,16 @@ var require_stringifyString = __commonJS({
1499
1499
  lineWidth: ctx.options.lineWidth,
1500
1500
  minContentWidth: ctx.options.minContentWidth
1501
1501
  });
1502
- var containsDocumentMarker = (str) => /^(%|---|\.\.\.)/m.test(str);
1503
- function lineLengthOverLimit(str, lineWidth, indentLength) {
1502
+ var containsDocumentMarker = (str2) => /^(%|---|\.\.\.)/m.test(str2);
1503
+ function lineLengthOverLimit(str2, lineWidth, indentLength) {
1504
1504
  if (!lineWidth || lineWidth < 0)
1505
1505
  return false;
1506
1506
  const limit = lineWidth - indentLength;
1507
- const strLen = str.length;
1507
+ const strLen = str2.length;
1508
1508
  if (strLen <= limit)
1509
1509
  return false;
1510
1510
  for (let i = 0, start = 0; i < strLen; ++i) {
1511
- if (str[i] === "\n") {
1511
+ if (str2[i] === "\n") {
1512
1512
  if (i - start > limit)
1513
1513
  return true;
1514
1514
  start = i + 1;
@@ -1525,11 +1525,11 @@ var require_stringifyString = __commonJS({
1525
1525
  const { implicitKey } = ctx;
1526
1526
  const minMultiLineLength = ctx.options.doubleQuotedMinMultiLineLength;
1527
1527
  const indent = ctx.indent || (containsDocumentMarker(value) ? " " : "");
1528
- let str = "";
1528
+ let str2 = "";
1529
1529
  let start = 0;
1530
1530
  for (let i = 0, ch = json2[i]; ch; ch = json2[++i]) {
1531
1531
  if (ch === " " && json2[i + 1] === "\\" && json2[i + 2] === "n") {
1532
- str += json2.slice(start, i) + "\\ ";
1532
+ str2 += json2.slice(start, i) + "\\ ";
1533
1533
  i += 1;
1534
1534
  start = i;
1535
1535
  ch = "\\";
@@ -1538,38 +1538,38 @@ var require_stringifyString = __commonJS({
1538
1538
  switch (json2[i + 1]) {
1539
1539
  case "u":
1540
1540
  {
1541
- str += json2.slice(start, i);
1541
+ str2 += json2.slice(start, i);
1542
1542
  const code = json2.substr(i + 2, 4);
1543
1543
  switch (code) {
1544
1544
  case "0000":
1545
- str += "\\0";
1545
+ str2 += "\\0";
1546
1546
  break;
1547
1547
  case "0007":
1548
- str += "\\a";
1548
+ str2 += "\\a";
1549
1549
  break;
1550
1550
  case "000b":
1551
- str += "\\v";
1551
+ str2 += "\\v";
1552
1552
  break;
1553
1553
  case "001b":
1554
- str += "\\e";
1554
+ str2 += "\\e";
1555
1555
  break;
1556
1556
  case "0085":
1557
- str += "\\N";
1557
+ str2 += "\\N";
1558
1558
  break;
1559
1559
  case "00a0":
1560
- str += "\\_";
1560
+ str2 += "\\_";
1561
1561
  break;
1562
1562
  case "2028":
1563
- str += "\\L";
1563
+ str2 += "\\L";
1564
1564
  break;
1565
1565
  case "2029":
1566
- str += "\\P";
1566
+ str2 += "\\P";
1567
1567
  break;
1568
1568
  default:
1569
1569
  if (code.substr(0, 2) === "00")
1570
- str += "\\x" + code.substr(2);
1570
+ str2 += "\\x" + code.substr(2);
1571
1571
  else
1572
- str += json2.substr(i, 6);
1572
+ str2 += json2.substr(i, 6);
1573
1573
  }
1574
1574
  i += 5;
1575
1575
  start = i + 1;
@@ -1579,14 +1579,14 @@ var require_stringifyString = __commonJS({
1579
1579
  if (implicitKey || json2[i + 2] === '"' || json2.length < minMultiLineLength) {
1580
1580
  i += 1;
1581
1581
  } else {
1582
- str += json2.slice(start, i) + "\n\n";
1582
+ str2 += json2.slice(start, i) + "\n\n";
1583
1583
  while (json2[i + 2] === "\\" && json2[i + 3] === "n" && json2[i + 4] !== '"') {
1584
- str += "\n";
1584
+ str2 += "\n";
1585
1585
  i += 2;
1586
1586
  }
1587
- str += indent;
1587
+ str2 += indent;
1588
1588
  if (json2[i + 2] === " ")
1589
- str += "\\";
1589
+ str2 += "\\";
1590
1590
  i += 1;
1591
1591
  start = i + 1;
1592
1592
  }
@@ -1595,8 +1595,8 @@ var require_stringifyString = __commonJS({
1595
1595
  i += 1;
1596
1596
  }
1597
1597
  }
1598
- str = start ? str + json2.slice(start) : json2;
1599
- return implicitKey ? str : foldFlowLines.foldFlowLines(str, indent, foldFlowLines.FOLD_QUOTED, getFoldOptions(ctx, false));
1598
+ str2 = start ? str2 + json2.slice(start) : json2;
1599
+ return implicitKey ? str2 : foldFlowLines.foldFlowLines(str2, indent, foldFlowLines.FOLD_QUOTED, getFoldOptions(ctx, false));
1600
1600
  }
1601
1601
  function singleQuotedString(value, ctx) {
1602
1602
  if (ctx.options.singleQuote === false || ctx.implicitKey && value.includes("\n") || /[ \t]\n|\n[ \t]/.test(value))
@@ -1724,15 +1724,15 @@ ${indent}${start}${value}${end}`;
1724
1724
  return quotedString(value, ctx);
1725
1725
  }
1726
1726
  }
1727
- const str = value.replace(/\n+/g, `$&
1727
+ const str2 = value.replace(/\n+/g, `$&
1728
1728
  ${indent}`);
1729
1729
  if (actualString) {
1730
- const test = (tag) => tag.default && tag.tag !== "tag:yaml.org,2002:str" && tag.test?.test(str);
1730
+ const test = (tag) => tag.default && tag.tag !== "tag:yaml.org,2002:str" && tag.test?.test(str2);
1731
1731
  const { compat, tags } = ctx.doc.schema;
1732
1732
  if (tags.some(test) || compat?.some(test))
1733
1733
  return quotedString(value, ctx);
1734
1734
  }
1735
- return implicitKey ? str : foldFlowLines.foldFlowLines(str, indent, foldFlowLines.FOLD_FLOW, getFoldOptions(ctx, false));
1735
+ return implicitKey ? str2 : foldFlowLines.foldFlowLines(str2, indent, foldFlowLines.FOLD_FLOW, getFoldOptions(ctx, false));
1736
1736
  }
1737
1737
  function stringifyString(item, ctx, onComment, onChompKeep) {
1738
1738
  const { implicitKey, inFlow } = ctx;
@@ -1884,11 +1884,11 @@ var require_stringify = __commonJS({
1884
1884
  const props = stringifyProps(node2, tagObj, ctx);
1885
1885
  if (props.length > 0)
1886
1886
  ctx.indentAtStart = (ctx.indentAtStart ?? 0) + props.length + 1;
1887
- const str = typeof tagObj.stringify === "function" ? tagObj.stringify(node2, ctx, onComment, onChompKeep) : identity.isScalar(node2) ? stringifyString.stringifyString(node2, ctx, onComment, onChompKeep) : node2.toString(ctx, onComment, onChompKeep);
1887
+ const str2 = typeof tagObj.stringify === "function" ? tagObj.stringify(node2, ctx, onComment, onChompKeep) : identity.isScalar(node2) ? stringifyString.stringifyString(node2, ctx, onComment, onChompKeep) : node2.toString(ctx, onComment, onChompKeep);
1888
1888
  if (!props)
1889
- return str;
1890
- return identity.isScalar(node2) || str[0] === "{" || str[0] === "[" ? `${props} ${str}` : `${props}
1891
- ${ctx.indent}${str}`;
1889
+ return str2;
1890
+ return identity.isScalar(node2) || str2[0] === "{" || str2[0] === "[" ? `${props} ${str2}` : `${props}
1891
+ ${ctx.indent}${str2}`;
1892
1892
  }
1893
1893
  exports.createStringifyContext = createStringifyContext;
1894
1894
  exports.stringify = stringify2;
@@ -1923,8 +1923,8 @@ var require_stringifyPair = __commonJS({
1923
1923
  });
1924
1924
  let keyCommentDone = false;
1925
1925
  let chompKeep = false;
1926
- let str = stringify2.stringify(key, ctx, () => keyCommentDone = true, () => chompKeep = true);
1927
- if (!explicitKey && !ctx.inFlow && str.length > 1024) {
1926
+ let str2 = stringify2.stringify(key, ctx, () => keyCommentDone = true, () => chompKeep = true);
1927
+ if (!explicitKey && !ctx.inFlow && str2.length > 1024) {
1928
1928
  if (simpleKeys)
1929
1929
  throw new Error("With simple keys, single line scalar must not span more than 1024 characters");
1930
1930
  explicitKey = true;
@@ -1933,27 +1933,27 @@ var require_stringifyPair = __commonJS({
1933
1933
  if (allNullValues || value == null) {
1934
1934
  if (keyCommentDone && onComment)
1935
1935
  onComment();
1936
- return str === "" ? "?" : explicitKey ? `? ${str}` : str;
1936
+ return str2 === "" ? "?" : explicitKey ? `? ${str2}` : str2;
1937
1937
  }
1938
1938
  } else if (allNullValues && !simpleKeys || value == null && explicitKey) {
1939
- str = `? ${str}`;
1939
+ str2 = `? ${str2}`;
1940
1940
  if (keyComment && !keyCommentDone) {
1941
- str += stringifyComment.lineComment(str, ctx.indent, commentString(keyComment));
1941
+ str2 += stringifyComment.lineComment(str2, ctx.indent, commentString(keyComment));
1942
1942
  } else if (chompKeep && onChompKeep)
1943
1943
  onChompKeep();
1944
- return str;
1944
+ return str2;
1945
1945
  }
1946
1946
  if (keyCommentDone)
1947
1947
  keyComment = null;
1948
1948
  if (explicitKey) {
1949
1949
  if (keyComment)
1950
- str += stringifyComment.lineComment(str, ctx.indent, commentString(keyComment));
1951
- str = `? ${str}
1950
+ str2 += stringifyComment.lineComment(str2, ctx.indent, commentString(keyComment));
1951
+ str2 = `? ${str2}
1952
1952
  ${indent}:`;
1953
1953
  } else {
1954
- str = `${str}:`;
1954
+ str2 = `${str2}:`;
1955
1955
  if (keyComment)
1956
- str += stringifyComment.lineComment(str, ctx.indent, commentString(keyComment));
1956
+ str2 += stringifyComment.lineComment(str2, ctx.indent, commentString(keyComment));
1957
1957
  }
1958
1958
  let vsb, vcb, valueComment;
1959
1959
  if (identity.isNode(value)) {
@@ -1969,7 +1969,7 @@ ${indent}:`;
1969
1969
  }
1970
1970
  ctx.implicitKey = false;
1971
1971
  if (!explicitKey && !keyComment && identity.isScalar(value))
1972
- ctx.indentAtStart = str.length + 1;
1972
+ ctx.indentAtStart = str2.length + 1;
1973
1973
  chompKeep = false;
1974
1974
  if (!indentSeq && indentStep.length >= 2 && !ctx.inFlow && !explicitKey && identity.isSeq(value) && !value.flow && !value.tag && !value.anchor) {
1975
1975
  ctx.indent = ctx.indent.substring(2);
@@ -2013,16 +2013,16 @@ ${ctx.indent}`;
2013
2013
  } else if (valueStr === "" || valueStr[0] === "\n") {
2014
2014
  ws = "";
2015
2015
  }
2016
- str += ws + valueStr;
2016
+ str2 += ws + valueStr;
2017
2017
  if (ctx.inFlow) {
2018
2018
  if (valueCommentDone && onComment)
2019
2019
  onComment();
2020
2020
  } else if (valueComment && !valueCommentDone) {
2021
- str += stringifyComment.lineComment(str, ctx.indent, commentString(valueComment));
2021
+ str2 += stringifyComment.lineComment(str2, ctx.indent, commentString(valueComment));
2022
2022
  } else if (chompKeep && onChompKeep) {
2023
2023
  onChompKeep();
2024
2024
  }
2025
- return str;
2025
+ return str2;
2026
2026
  }
2027
2027
  exports.stringifyPair = stringifyPair;
2028
2028
  }
@@ -2249,31 +2249,31 @@ var require_stringifyCollection = __commonJS({
2249
2249
  }
2250
2250
  }
2251
2251
  chompKeep = false;
2252
- let str2 = stringify2.stringify(item, itemCtx, () => comment2 = null, () => chompKeep = true);
2252
+ let str3 = stringify2.stringify(item, itemCtx, () => comment2 = null, () => chompKeep = true);
2253
2253
  if (comment2)
2254
- str2 += stringifyComment.lineComment(str2, itemIndent, commentString(comment2));
2254
+ str3 += stringifyComment.lineComment(str3, itemIndent, commentString(comment2));
2255
2255
  if (chompKeep && comment2)
2256
2256
  chompKeep = false;
2257
- lines.push(blockItemPrefix + str2);
2257
+ lines.push(blockItemPrefix + str3);
2258
2258
  }
2259
- let str;
2259
+ let str2;
2260
2260
  if (lines.length === 0) {
2261
- str = flowChars.start + flowChars.end;
2261
+ str2 = flowChars.start + flowChars.end;
2262
2262
  } else {
2263
- str = lines[0];
2263
+ str2 = lines[0];
2264
2264
  for (let i = 1; i < lines.length; ++i) {
2265
2265
  const line = lines[i];
2266
- str += line ? `
2266
+ str2 += line ? `
2267
2267
  ${indent}${line}` : "\n";
2268
2268
  }
2269
2269
  }
2270
2270
  if (comment) {
2271
- str += "\n" + stringifyComment.indentComment(commentString(comment), indent);
2271
+ str2 += "\n" + stringifyComment.indentComment(commentString(comment), indent);
2272
2272
  if (onComment)
2273
2273
  onComment();
2274
2274
  } else if (chompKeep && onChompKeep)
2275
2275
  onChompKeep();
2276
- return str;
2276
+ return str2;
2277
2277
  }
2278
2278
  function stringifyFlowCollection({ items }, ctx, { flowChars, itemIndent }) {
2279
2279
  const { indent, indentStep, flowCollectionPadding: fcPadding, options: { commentString } } = ctx;
@@ -2316,21 +2316,21 @@ ${indent}${line}` : "\n";
2316
2316
  }
2317
2317
  if (comment)
2318
2318
  reqNewline = true;
2319
- let str = stringify2.stringify(item, itemCtx, () => comment = null);
2320
- reqNewline || (reqNewline = lines.length > linesAtValue || str.includes("\n"));
2319
+ let str2 = stringify2.stringify(item, itemCtx, () => comment = null);
2320
+ reqNewline || (reqNewline = lines.length > linesAtValue || str2.includes("\n"));
2321
2321
  if (i < items.length - 1) {
2322
- str += ",";
2322
+ str2 += ",";
2323
2323
  } else if (ctx.options.trailingComma) {
2324
2324
  if (ctx.options.lineWidth > 0) {
2325
- reqNewline || (reqNewline = lines.reduce((sum, line) => sum + line.length + 2, 2) + (str.length + 2) > ctx.options.lineWidth);
2325
+ reqNewline || (reqNewline = lines.reduce((sum, line) => sum + line.length + 2, 2) + (str2.length + 2) > ctx.options.lineWidth);
2326
2326
  }
2327
2327
  if (reqNewline) {
2328
- str += ",";
2328
+ str2 += ",";
2329
2329
  }
2330
2330
  }
2331
2331
  if (comment)
2332
- str += stringifyComment.lineComment(str, itemIndent, commentString(comment));
2333
- lines.push(str);
2332
+ str2 += stringifyComment.lineComment(str2, itemIndent, commentString(comment));
2333
+ lines.push(str2);
2334
2334
  linesAtValue = lines.length;
2335
2335
  }
2336
2336
  const { start, end } = flowChars;
@@ -2342,11 +2342,11 @@ ${indent}${line}` : "\n";
2342
2342
  reqNewline = ctx.options.lineWidth > 0 && len > ctx.options.lineWidth;
2343
2343
  }
2344
2344
  if (reqNewline) {
2345
- let str = start;
2345
+ let str2 = start;
2346
2346
  for (const line of lines)
2347
- str += line ? `
2347
+ str2 += line ? `
2348
2348
  ${indentStep}${indent}${line}` : "\n";
2349
- return `${str}
2349
+ return `${str2}
2350
2350
  ${indent}${end}`;
2351
2351
  } else {
2352
2352
  return `${start}${fcPadding}${lines.join(" ")}${fcPadding}${end}`;
@@ -2678,7 +2678,7 @@ var require_string = __commonJS({
2678
2678
  identify: (value) => typeof value === "string",
2679
2679
  default: true,
2680
2680
  tag: "tag:yaml.org,2002:str",
2681
- resolve: (str) => str,
2681
+ resolve: (str2) => str2,
2682
2682
  stringify(item, ctx, onComment, onChompKeep) {
2683
2683
  ctx = Object.assign({ actualString: true }, ctx);
2684
2684
  return stringifyString.stringifyString(item, ctx, onComment, onChompKeep);
@@ -2716,7 +2716,7 @@ var require_bool = __commonJS({
2716
2716
  default: true,
2717
2717
  tag: "tag:yaml.org,2002:bool",
2718
2718
  test: /^(?:[Tt]rue|TRUE|[Ff]alse|FALSE)$/,
2719
- resolve: (str) => new Scalar.Scalar(str[0] === "t" || str[0] === "T"),
2719
+ resolve: (str2) => new Scalar.Scalar(str2[0] === "t" || str2[0] === "T"),
2720
2720
  stringify({ source, value }, ctx) {
2721
2721
  if (source && boolTag.test.test(source)) {
2722
2722
  const sv = source[0] === "t" || source[0] === "T";
@@ -2737,9 +2737,9 @@ var require_stringifyNumber = __commonJS({
2737
2737
  function stringifyNumber({ format, minFractionDigits, tag, value }) {
2738
2738
  if (typeof value === "bigint")
2739
2739
  return String(value);
2740
- const num = typeof value === "number" ? value : Number(value);
2741
- if (!isFinite(num))
2742
- return isNaN(num) ? ".nan" : num < 0 ? "-.inf" : ".inf";
2740
+ const num2 = typeof value === "number" ? value : Number(value);
2741
+ if (!isFinite(num2))
2742
+ return isNaN(num2) ? ".nan" : num2 < 0 ? "-.inf" : ".inf";
2743
2743
  let n = Object.is(value, -0) ? "-0" : JSON.stringify(value);
2744
2744
  if (!format && minFractionDigits && (!tag || tag === "tag:yaml.org,2002:float") && /^-?\d/.test(n) && !n.includes("e")) {
2745
2745
  let i = n.indexOf(".");
@@ -2768,7 +2768,7 @@ var require_float = __commonJS({
2768
2768
  default: true,
2769
2769
  tag: "tag:yaml.org,2002:float",
2770
2770
  test: /^(?:[-+]?\.(?:inf|Inf|INF)|\.nan|\.NaN|\.NAN)$/,
2771
- resolve: (str) => str.slice(-3).toLowerCase() === "nan" ? NaN : str[0] === "-" ? Number.NEGATIVE_INFINITY : Number.POSITIVE_INFINITY,
2771
+ resolve: (str2) => str2.slice(-3).toLowerCase() === "nan" ? NaN : str2[0] === "-" ? Number.NEGATIVE_INFINITY : Number.POSITIVE_INFINITY,
2772
2772
  stringify: stringifyNumber.stringifyNumber
2773
2773
  };
2774
2774
  var floatExp = {
@@ -2777,10 +2777,10 @@ var require_float = __commonJS({
2777
2777
  tag: "tag:yaml.org,2002:float",
2778
2778
  format: "EXP",
2779
2779
  test: /^[-+]?(?:\.[0-9]+|[0-9]+(?:\.[0-9]*)?)[eE][-+]?[0-9]+$/,
2780
- resolve: (str) => parseFloat(str),
2780
+ resolve: (str2) => parseFloat(str2),
2781
2781
  stringify(node2) {
2782
- const num = Number(node2.value);
2783
- return isFinite(num) ? num.toExponential() : stringifyNumber.stringifyNumber(node2);
2782
+ const num2 = Number(node2.value);
2783
+ return isFinite(num2) ? num2.toExponential() : stringifyNumber.stringifyNumber(node2);
2784
2784
  }
2785
2785
  };
2786
2786
  var float = {
@@ -2788,11 +2788,11 @@ var require_float = __commonJS({
2788
2788
  default: true,
2789
2789
  tag: "tag:yaml.org,2002:float",
2790
2790
  test: /^[-+]?(?:\.[0-9]+|[0-9]+\.[0-9]*)$/,
2791
- resolve(str) {
2792
- const node2 = new Scalar.Scalar(parseFloat(str));
2793
- const dot = str.indexOf(".");
2794
- if (dot !== -1 && str[str.length - 1] === "0")
2795
- node2.minFractionDigits = str.length - dot - 1;
2791
+ resolve(str2) {
2792
+ const node2 = new Scalar.Scalar(parseFloat(str2));
2793
+ const dot = str2.indexOf(".");
2794
+ if (dot !== -1 && str2[str2.length - 1] === "0")
2795
+ node2.minFractionDigits = str2.length - dot - 1;
2796
2796
  return node2;
2797
2797
  },
2798
2798
  stringify: stringifyNumber.stringifyNumber
@@ -2809,7 +2809,7 @@ var require_int = __commonJS({
2809
2809
  "use strict";
2810
2810
  var stringifyNumber = require_stringifyNumber();
2811
2811
  var intIdentify = (value) => typeof value === "bigint" || Number.isInteger(value);
2812
- var intResolve = (str, offset, radix, { intAsBigInt }) => intAsBigInt ? BigInt(str) : parseInt(str.substring(offset), radix);
2812
+ var intResolve = (str2, offset, radix, { intAsBigInt }) => intAsBigInt ? BigInt(str2) : parseInt(str2.substring(offset), radix);
2813
2813
  function intStringify(node2, radix, prefix) {
2814
2814
  const { value } = node2;
2815
2815
  if (intIdentify(value) && value >= 0)
@@ -2822,7 +2822,7 @@ var require_int = __commonJS({
2822
2822
  tag: "tag:yaml.org,2002:int",
2823
2823
  format: "OCT",
2824
2824
  test: /^0o[0-7]+$/,
2825
- resolve: (str, _onError, opt) => intResolve(str, 2, 8, opt),
2825
+ resolve: (str2, _onError, opt) => intResolve(str2, 2, 8, opt),
2826
2826
  stringify: (node2) => intStringify(node2, 8, "0o")
2827
2827
  };
2828
2828
  var int2 = {
@@ -2830,7 +2830,7 @@ var require_int = __commonJS({
2830
2830
  default: true,
2831
2831
  tag: "tag:yaml.org,2002:int",
2832
2832
  test: /^[-+]?[0-9]+$/,
2833
- resolve: (str, _onError, opt) => intResolve(str, 0, 10, opt),
2833
+ resolve: (str2, _onError, opt) => intResolve(str2, 0, 10, opt),
2834
2834
  stringify: stringifyNumber.stringifyNumber
2835
2835
  };
2836
2836
  var intHex = {
@@ -2839,7 +2839,7 @@ var require_int = __commonJS({
2839
2839
  tag: "tag:yaml.org,2002:int",
2840
2840
  format: "HEX",
2841
2841
  test: /^0x[0-9a-fA-F]+$/,
2842
- resolve: (str, _onError, opt) => intResolve(str, 2, 16, opt),
2842
+ resolve: (str2, _onError, opt) => intResolve(str2, 2, 16, opt),
2843
2843
  stringify: (node2) => intStringify(node2, 16, "0x")
2844
2844
  };
2845
2845
  exports.int = int2;
@@ -2892,7 +2892,7 @@ var require_schema2 = __commonJS({
2892
2892
  identify: (value) => typeof value === "string",
2893
2893
  default: true,
2894
2894
  tag: "tag:yaml.org,2002:str",
2895
- resolve: (str) => str,
2895
+ resolve: (str2) => str2,
2896
2896
  stringify: stringifyJSON
2897
2897
  },
2898
2898
  {
@@ -2909,7 +2909,7 @@ var require_schema2 = __commonJS({
2909
2909
  default: true,
2910
2910
  tag: "tag:yaml.org,2002:bool",
2911
2911
  test: /^true$|^false$/,
2912
- resolve: (str) => str === "true",
2912
+ resolve: (str2) => str2 === "true",
2913
2913
  stringify: stringifyJSON
2914
2914
  },
2915
2915
  {
@@ -2917,7 +2917,7 @@ var require_schema2 = __commonJS({
2917
2917
  default: true,
2918
2918
  tag: "tag:yaml.org,2002:int",
2919
2919
  test: /^-?(?:0|[1-9][0-9]*)$/,
2920
- resolve: (str, _onError, { intAsBigInt }) => intAsBigInt ? BigInt(str) : parseInt(str, 10),
2920
+ resolve: (str2, _onError, { intAsBigInt }) => intAsBigInt ? BigInt(str2) : parseInt(str2, 10),
2921
2921
  stringify: ({ value }) => intIdentify(value) ? value.toString() : JSON.stringify(value)
2922
2922
  },
2923
2923
  {
@@ -2925,7 +2925,7 @@ var require_schema2 = __commonJS({
2925
2925
  default: true,
2926
2926
  tag: "tag:yaml.org,2002:float",
2927
2927
  test: /^-?(?:0|[1-9][0-9]*)(?:\.[0-9]*)?(?:[eE][-+]?[0-9]+)?$/,
2928
- resolve: (str) => parseFloat(str),
2928
+ resolve: (str2) => parseFloat(str2),
2929
2929
  stringify: stringifyJSON
2930
2930
  }
2931
2931
  ];
@@ -2933,9 +2933,9 @@ var require_schema2 = __commonJS({
2933
2933
  default: true,
2934
2934
  tag: "",
2935
2935
  test: /^/,
2936
- resolve(str, onError) {
2937
- onError(`Unresolved plain scalar ${JSON.stringify(str)}`);
2938
- return str;
2936
+ resolve(str2, onError) {
2937
+ onError(`Unresolved plain scalar ${JSON.stringify(str2)}`);
2938
+ return str2;
2939
2939
  }
2940
2940
  };
2941
2941
  var schema = [map2.map, seq.seq].concat(jsonScalars, jsonError);
@@ -2967,10 +2967,10 @@ var require_binary = __commonJS({
2967
2967
  if (typeof node_buffer.Buffer === "function") {
2968
2968
  return node_buffer.Buffer.from(src, "base64");
2969
2969
  } else if (typeof atob === "function") {
2970
- const str = atob(src.replace(/[\n\r]/g, ""));
2971
- const buffer = new Uint8Array(str.length);
2972
- for (let i = 0; i < str.length; ++i)
2973
- buffer[i] = str.charCodeAt(i);
2970
+ const str2 = atob(src.replace(/[\n\r]/g, ""));
2971
+ const buffer = new Uint8Array(str2.length);
2972
+ for (let i = 0; i < str2.length; ++i)
2973
+ buffer[i] = str2.charCodeAt(i);
2974
2974
  return buffer;
2975
2975
  } else {
2976
2976
  onError("This environment does not support reading binary tags; either Buffer or atob is required");
@@ -2981,28 +2981,28 @@ var require_binary = __commonJS({
2981
2981
  if (!value)
2982
2982
  return "";
2983
2983
  const buf = value;
2984
- let str;
2984
+ let str2;
2985
2985
  if (typeof node_buffer.Buffer === "function") {
2986
- str = buf instanceof node_buffer.Buffer ? buf.toString("base64") : node_buffer.Buffer.from(buf.buffer).toString("base64");
2986
+ str2 = buf instanceof node_buffer.Buffer ? buf.toString("base64") : node_buffer.Buffer.from(buf.buffer).toString("base64");
2987
2987
  } else if (typeof btoa === "function") {
2988
2988
  let s = "";
2989
2989
  for (let i = 0; i < buf.length; ++i)
2990
2990
  s += String.fromCharCode(buf[i]);
2991
- str = btoa(s);
2991
+ str2 = btoa(s);
2992
2992
  } else {
2993
2993
  throw new Error("This environment does not support writing binary tags; either Buffer or btoa is required");
2994
2994
  }
2995
2995
  type ?? (type = Scalar.Scalar.BLOCK_LITERAL);
2996
2996
  if (type !== Scalar.Scalar.QUOTE_DOUBLE) {
2997
2997
  const lineWidth = Math.max(ctx.options.lineWidth - ctx.indent.length, ctx.options.minContentWidth);
2998
- const n = Math.ceil(str.length / lineWidth);
2998
+ const n = Math.ceil(str2.length / lineWidth);
2999
2999
  const lines = new Array(n);
3000
3000
  for (let i = 0, o = 0; i < n; ++i, o += lineWidth) {
3001
- lines[i] = str.substr(o, lineWidth);
3001
+ lines[i] = str2.substr(o, lineWidth);
3002
3002
  }
3003
- str = lines.join(type === Scalar.Scalar.BLOCK_LITERAL ? "\n" : " ");
3003
+ str2 = lines.join(type === Scalar.Scalar.BLOCK_LITERAL ? "\n" : " ");
3004
3004
  }
3005
- return stringifyString.stringifyString({ comment, type, value: str }, ctx, onComment, onChompKeep);
3005
+ return stringifyString.stringifyString({ comment, type, value: str2 }, ctx, onComment, onChompKeep);
3006
3006
  }
3007
3007
  };
3008
3008
  exports.binary = binary;
@@ -3208,7 +3208,7 @@ var require_float2 = __commonJS({
3208
3208
  default: true,
3209
3209
  tag: "tag:yaml.org,2002:float",
3210
3210
  test: /^(?:[-+]?\.(?:inf|Inf|INF)|\.nan|\.NaN|\.NAN)$/,
3211
- resolve: (str) => str.slice(-3).toLowerCase() === "nan" ? NaN : str[0] === "-" ? Number.NEGATIVE_INFINITY : Number.POSITIVE_INFINITY,
3211
+ resolve: (str2) => str2.slice(-3).toLowerCase() === "nan" ? NaN : str2[0] === "-" ? Number.NEGATIVE_INFINITY : Number.POSITIVE_INFINITY,
3212
3212
  stringify: stringifyNumber.stringifyNumber
3213
3213
  };
3214
3214
  var floatExp = {
@@ -3217,10 +3217,10 @@ var require_float2 = __commonJS({
3217
3217
  tag: "tag:yaml.org,2002:float",
3218
3218
  format: "EXP",
3219
3219
  test: /^[-+]?(?:[0-9][0-9_]*)?(?:\.[0-9_]*)?[eE][-+]?[0-9]+$/,
3220
- resolve: (str) => parseFloat(str.replace(/_/g, "")),
3220
+ resolve: (str2) => parseFloat(str2.replace(/_/g, "")),
3221
3221
  stringify(node2) {
3222
- const num = Number(node2.value);
3223
- return isFinite(num) ? num.toExponential() : stringifyNumber.stringifyNumber(node2);
3222
+ const num2 = Number(node2.value);
3223
+ return isFinite(num2) ? num2.toExponential() : stringifyNumber.stringifyNumber(node2);
3224
3224
  }
3225
3225
  };
3226
3226
  var float = {
@@ -3228,11 +3228,11 @@ var require_float2 = __commonJS({
3228
3228
  default: true,
3229
3229
  tag: "tag:yaml.org,2002:float",
3230
3230
  test: /^[-+]?(?:[0-9][0-9_]*)?\.[0-9_]*$/,
3231
- resolve(str) {
3232
- const node2 = new Scalar.Scalar(parseFloat(str.replace(/_/g, "")));
3233
- const dot = str.indexOf(".");
3231
+ resolve(str2) {
3232
+ const node2 = new Scalar.Scalar(parseFloat(str2.replace(/_/g, "")));
3233
+ const dot = str2.indexOf(".");
3234
3234
  if (dot !== -1) {
3235
- const f = str.substring(dot + 1).replace(/_/g, "");
3235
+ const f = str2.substring(dot + 1).replace(/_/g, "");
3236
3236
  if (f[f.length - 1] === "0")
3237
3237
  node2.minFractionDigits = f.length;
3238
3238
  }
@@ -3252,34 +3252,34 @@ var require_int2 = __commonJS({
3252
3252
  "use strict";
3253
3253
  var stringifyNumber = require_stringifyNumber();
3254
3254
  var intIdentify = (value) => typeof value === "bigint" || Number.isInteger(value);
3255
- function intResolve(str, offset, radix, { intAsBigInt }) {
3256
- const sign = str[0];
3255
+ function intResolve(str2, offset, radix, { intAsBigInt }) {
3256
+ const sign = str2[0];
3257
3257
  if (sign === "-" || sign === "+")
3258
3258
  offset += 1;
3259
- str = str.substring(offset).replace(/_/g, "");
3259
+ str2 = str2.substring(offset).replace(/_/g, "");
3260
3260
  if (intAsBigInt) {
3261
3261
  switch (radix) {
3262
3262
  case 2:
3263
- str = `0b${str}`;
3263
+ str2 = `0b${str2}`;
3264
3264
  break;
3265
3265
  case 8:
3266
- str = `0o${str}`;
3266
+ str2 = `0o${str2}`;
3267
3267
  break;
3268
3268
  case 16:
3269
- str = `0x${str}`;
3269
+ str2 = `0x${str2}`;
3270
3270
  break;
3271
3271
  }
3272
- const n2 = BigInt(str);
3272
+ const n2 = BigInt(str2);
3273
3273
  return sign === "-" ? BigInt(-1) * n2 : n2;
3274
3274
  }
3275
- const n = parseInt(str, radix);
3275
+ const n = parseInt(str2, radix);
3276
3276
  return sign === "-" ? -1 * n : n;
3277
3277
  }
3278
3278
  function intStringify(node2, radix, prefix) {
3279
3279
  const { value } = node2;
3280
3280
  if (intIdentify(value)) {
3281
- const str = value.toString(radix);
3282
- return value < 0 ? "-" + prefix + str.substr(1) : prefix + str;
3281
+ const str2 = value.toString(radix);
3282
+ return value < 0 ? "-" + prefix + str2.substr(1) : prefix + str2;
3283
3283
  }
3284
3284
  return stringifyNumber.stringifyNumber(node2);
3285
3285
  }
@@ -3289,7 +3289,7 @@ var require_int2 = __commonJS({
3289
3289
  tag: "tag:yaml.org,2002:int",
3290
3290
  format: "BIN",
3291
3291
  test: /^[-+]?0b[0-1_]+$/,
3292
- resolve: (str, _onError, opt) => intResolve(str, 2, 2, opt),
3292
+ resolve: (str2, _onError, opt) => intResolve(str2, 2, 2, opt),
3293
3293
  stringify: (node2) => intStringify(node2, 2, "0b")
3294
3294
  };
3295
3295
  var intOct = {
@@ -3298,7 +3298,7 @@ var require_int2 = __commonJS({
3298
3298
  tag: "tag:yaml.org,2002:int",
3299
3299
  format: "OCT",
3300
3300
  test: /^[-+]?0[0-7_]+$/,
3301
- resolve: (str, _onError, opt) => intResolve(str, 1, 8, opt),
3301
+ resolve: (str2, _onError, opt) => intResolve(str2, 1, 8, opt),
3302
3302
  stringify: (node2) => intStringify(node2, 8, "0")
3303
3303
  };
3304
3304
  var int2 = {
@@ -3306,7 +3306,7 @@ var require_int2 = __commonJS({
3306
3306
  default: true,
3307
3307
  tag: "tag:yaml.org,2002:int",
3308
3308
  test: /^[-+]?[0-9][0-9_]*$/,
3309
- resolve: (str, _onError, opt) => intResolve(str, 0, 10, opt),
3309
+ resolve: (str2, _onError, opt) => intResolve(str2, 0, 10, opt),
3310
3310
  stringify: stringifyNumber.stringifyNumber
3311
3311
  };
3312
3312
  var intHex = {
@@ -3315,7 +3315,7 @@ var require_int2 = __commonJS({
3315
3315
  tag: "tag:yaml.org,2002:int",
3316
3316
  format: "HEX",
3317
3317
  test: /^[-+]?0x[0-9a-fA-F_]+$/,
3318
- resolve: (str, _onError, opt) => intResolve(str, 2, 16, opt),
3318
+ resolve: (str2, _onError, opt) => intResolve(str2, 2, 16, opt),
3319
3319
  stringify: (node2) => intStringify(node2, 16, "0x")
3320
3320
  };
3321
3321
  exports.int = int2;
@@ -3419,26 +3419,26 @@ var require_timestamp = __commonJS({
3419
3419
  "../../node_modules/yaml/dist/schema/yaml-1.1/timestamp.js"(exports) {
3420
3420
  "use strict";
3421
3421
  var stringifyNumber = require_stringifyNumber();
3422
- function parseSexagesimal(str, asBigInt) {
3423
- const sign = str[0];
3424
- const parts = sign === "-" || sign === "+" ? str.substring(1) : str;
3425
- const num = (n) => asBigInt ? BigInt(n) : Number(n);
3426
- const res = parts.replace(/_/g, "").split(":").reduce((res2, p) => res2 * num(60) + num(p), num(0));
3427
- return sign === "-" ? num(-1) * res : res;
3422
+ function parseSexagesimal(str2, asBigInt) {
3423
+ const sign = str2[0];
3424
+ const parts = sign === "-" || sign === "+" ? str2.substring(1) : str2;
3425
+ const num2 = (n) => asBigInt ? BigInt(n) : Number(n);
3426
+ const res = parts.replace(/_/g, "").split(":").reduce((res2, p) => res2 * num2(60) + num2(p), num2(0));
3427
+ return sign === "-" ? num2(-1) * res : res;
3428
3428
  }
3429
3429
  function stringifySexagesimal(node2) {
3430
3430
  let { value } = node2;
3431
- let num = (n) => n;
3431
+ let num2 = (n) => n;
3432
3432
  if (typeof value === "bigint")
3433
- num = (n) => BigInt(n);
3433
+ num2 = (n) => BigInt(n);
3434
3434
  else if (isNaN(value) || !isFinite(value))
3435
3435
  return stringifyNumber.stringifyNumber(node2);
3436
3436
  let sign = "";
3437
3437
  if (value < 0) {
3438
3438
  sign = "-";
3439
- value *= num(-1);
3439
+ value *= num2(-1);
3440
3440
  }
3441
- const _60 = num(60);
3441
+ const _60 = num2(60);
3442
3442
  const parts = [value % _60];
3443
3443
  if (value < 60) {
3444
3444
  parts.unshift(0);
@@ -3458,7 +3458,7 @@ var require_timestamp = __commonJS({
3458
3458
  tag: "tag:yaml.org,2002:int",
3459
3459
  format: "TIME",
3460
3460
  test: /^[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+$/,
3461
- resolve: (str, _onError, { intAsBigInt }) => parseSexagesimal(str, intAsBigInt),
3461
+ resolve: (str2, _onError, { intAsBigInt }) => parseSexagesimal(str2, intAsBigInt),
3462
3462
  stringify: stringifySexagesimal
3463
3463
  };
3464
3464
  var floatTime = {
@@ -3467,7 +3467,7 @@ var require_timestamp = __commonJS({
3467
3467
  tag: "tag:yaml.org,2002:float",
3468
3468
  format: "TIME",
3469
3469
  test: /^[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\.[0-9_]*$/,
3470
- resolve: (str) => parseSexagesimal(str, false),
3470
+ resolve: (str2) => parseSexagesimal(str2, false),
3471
3471
  stringify: stringifySexagesimal
3472
3472
  };
3473
3473
  var timestamp = {
@@ -3478,8 +3478,8 @@ var require_timestamp = __commonJS({
3478
3478
  // may be omitted altogether, resulting in a date format. In such a case, the time part is
3479
3479
  // assumed to be 00:00:00Z (start of day, UTC).
3480
3480
  test: RegExp("^([0-9]{4})-([0-9]{1,2})-([0-9]{1,2})(?:(?:t|T|[ \\t]+)([0-9]{1,2}):([0-9]{1,2}):([0-9]{1,2}(\\.[0-9]+)?)(?:[ \\t]*(Z|[-+][012]?[0-9](?::[0-9]{2})?))?)?$"),
3481
- resolve(str) {
3482
- const match = str.match(timestamp.test);
3481
+ resolve(str2) {
3482
+ const match = str2.match(timestamp.test);
3483
3483
  if (!match)
3484
3484
  throw new Error("!!timestamp expects a date, starting with yyyy-mm-dd");
3485
3485
  const [, year, month, day, hour, minute, second] = match.map(Number);
@@ -8031,120 +8031,6 @@ var FoldersModule = class {
8031
8031
  };
8032
8032
  };
8033
8033
 
8034
- // src/utils/pagination.ts
8035
- var DEFAULT_PAGE_SIZE = 100;
8036
- var getAllPages = async (listPage, options = {}) => {
8037
- const items = [];
8038
- const baseOptions = options;
8039
- let { cursor } = baseOptions;
8040
- do {
8041
- const response = await listPage({
8042
- ...baseOptions,
8043
- cursor,
8044
- pageSize: baseOptions.pageSize ?? DEFAULT_PAGE_SIZE
8045
- });
8046
- items.push(...response.results ?? []);
8047
- cursor = response.nextToken ?? void 0;
8048
- } while (cursor);
8049
- return items;
8050
- };
8051
-
8052
- // src/modules/groups/groups.ts
8053
- var GroupsModule = class {
8054
- #client;
8055
- constructor(client) {
8056
- this.#client = client;
8057
- }
8058
- /**
8059
- * List groups with pagination, search, and ordering.
8060
- *
8061
- * @param options.query - Search query matched against group name.
8062
- * @param options.ordering - Sort key; prefix with `-` for descending.
8063
- * @param options.folderId - Only components directly in this folder.
8064
- * @param options.noFolder - Only components at the root (not in any folder).
8065
- * @returns Paginated `GroupsListResponse`.
8066
- */
8067
- list = async (options = {}) => {
8068
- const {
8069
- query: searchQuery,
8070
- cursor,
8071
- pageSize,
8072
- ordering,
8073
- folderId,
8074
- noFolder,
8075
- ...requestOptions
8076
- } = options;
8077
- return this.#client.get("/groups/", {
8078
- queryParams: {
8079
- query: searchQuery,
8080
- cursor,
8081
- page_size: pageSize,
8082
- ordering,
8083
- folderId,
8084
- noFolder
8085
- },
8086
- ...requestOptions
8087
- });
8088
- };
8089
- /**
8090
- * Fetch every group across all pages.
8091
- */
8092
- getAll = async (options = {}) => getAllPages((pageOptions) => this.list({ ...options, ...pageOptions }));
8093
- /**
8094
- * Fetch a single group by ID (with nested steps).
8095
- *
8096
- * @throws {NotFoundError} When no group matches `groupId`.
8097
- */
8098
- get = async (groupId, options = {}) => this.#client.get("/groups/{id}/", {
8099
- pathParams: { id: groupId },
8100
- ...options
8101
- });
8102
- /**
8103
- * Create a new (empty) group.
8104
- *
8105
- * @throws {ValidationError} On invalid payload.
8106
- */
8107
- create = async (data, options = {}) => this.#client.post("/groups/", {
8108
- body: data,
8109
- ...options
8110
- });
8111
- /**
8112
- * Fully replace a group via PUT. Use {@link partialUpdate} for PATCH semantics.
8113
- *
8114
- * @throws {NotFoundError} When the group does not exist.
8115
- * @throws {ValidationError} On invalid payload.
8116
- */
8117
- update = async (groupId, data, options = {}) => this.#client.put("/groups/{id}/", {
8118
- pathParams: { id: groupId },
8119
- body: data,
8120
- ...options
8121
- });
8122
- /**
8123
- * Patch selected fields on a group (PATCH semantics).
8124
- *
8125
- * @throws {NotFoundError} When the group does not exist.
8126
- * @throws {ValidationError} On invalid payload.
8127
- */
8128
- partialUpdate = async (groupId, data, options = {}) => this.#client.patch("/groups/{id}/", {
8129
- pathParams: { id: groupId },
8130
- body: data,
8131
- ...options
8132
- });
8133
- /**
8134
- * Delete a group by ID. Tests that reference this group will lose those steps.
8135
- *
8136
- * @throws {NotFoundError} When the group does not exist.
8137
- */
8138
- delete = async (groupId, options = {}) => this.#client.delete("/groups/{id}/", {
8139
- pathParams: { id: groupId },
8140
- ...options
8141
- });
8142
- };
8143
-
8144
- // ../core/dist/utils/validation.js
8145
- var UUID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
8146
- var isUuid = (value) => UUID_REGEX.test(value);
8147
-
8148
8034
  // src/constants/sdk-error-codes.ts
8149
8035
  var SDK_ERROR_CODES = {
8150
8036
  AUTHENTICATION_ERROR: "AUTHENTICATION_ERROR",
@@ -8289,7 +8175,8 @@ var NotFoundError = class extends BugBugError {
8289
8175
  };
8290
8176
  var RateLimitError = class extends BugBugError {
8291
8177
  retryAfter;
8292
- constructor(retryAfter, message = "Rate limit exceeded", response, request) {
8178
+ throttled;
8179
+ constructor(retryAfter, message = "Rate limit exceeded", response, request, throttled = false) {
8293
8180
  super(
8294
8181
  SDK_ERROR_CODES.RATE_LIMIT_ERROR,
8295
8182
  message,
@@ -8300,6 +8187,7 @@ var RateLimitError = class extends BugBugError {
8300
8187
  );
8301
8188
  this.name = "RateLimitError";
8302
8189
  this.retryAfter = retryAfter;
8190
+ this.throttled = throttled;
8303
8191
  }
8304
8192
  };
8305
8193
  var TimeoutError = class extends BugBugError {
@@ -8433,6 +8321,164 @@ function isHttpError(error62) {
8433
8321
  return error62 instanceof HttpError;
8434
8322
  }
8435
8323
 
8324
+ // src/utils/pagination.ts
8325
+ var DEFAULT_PAGE_SIZE = 100;
8326
+ var getAllPages = async (listPage, options = {}) => {
8327
+ const items = [];
8328
+ const baseOptions = options;
8329
+ let { cursor } = baseOptions;
8330
+ do {
8331
+ const response = await listPage({
8332
+ ...baseOptions,
8333
+ cursor,
8334
+ pageSize: baseOptions.pageSize ?? DEFAULT_PAGE_SIZE
8335
+ });
8336
+ items.push(...response.results ?? []);
8337
+ cursor = response.nextToken ?? void 0;
8338
+ } while (cursor);
8339
+ return items;
8340
+ };
8341
+ var isPageNumberEnvelope = (value) => {
8342
+ if (!value || typeof value !== "object") {
8343
+ return false;
8344
+ }
8345
+ const { count, page, results } = value;
8346
+ return typeof count === "number" && typeof page === "number" && Array.isArray(results);
8347
+ };
8348
+ var toPositiveInt = (value) => {
8349
+ const parsed = Number(value);
8350
+ return Number.isInteger(parsed) && parsed > 0 ? parsed : void 0;
8351
+ };
8352
+ var parseCursor = (cursor) => {
8353
+ if (typeof cursor !== "string" || cursor === "") {
8354
+ return void 0;
8355
+ }
8356
+ const [rawPage, rawPageSize] = cursor.split(":");
8357
+ const page = toPositiveInt(rawPage);
8358
+ if (page === void 0) {
8359
+ throw new ValidationError(
8360
+ `Invalid pagination cursor "${cursor}". Pass the nextToken from the previous page.`
8361
+ );
8362
+ }
8363
+ return { page, pageSize: toPositiveInt(rawPageSize) };
8364
+ };
8365
+ var SERVER_MAX_PAGE_SIZE = 100;
8366
+ var withNextToken = (response, requestedPageSize) => {
8367
+ if (!isPageNumberEnvelope(response)) {
8368
+ return response;
8369
+ }
8370
+ const { count, page, results } = response;
8371
+ const pageSize = requestedPageSize === void 0 ? page === 1 ? results.length : void 0 : Math.min(requestedPageSize, SERVER_MAX_PAGE_SIZE);
8372
+ const hasMore = "next" in response ? Boolean(response.next) : pageSize !== void 0 && results.length > 0 && page * pageSize < count;
8373
+ return {
8374
+ ...response,
8375
+ nextToken: hasMore && pageSize !== void 0 ? `${page + 1}:${pageSize}` : null
8376
+ };
8377
+ };
8378
+ var requireKnownPageSize = (cursor, pageSize) => {
8379
+ if (cursor && cursor.page > 1 && pageSize === void 0) {
8380
+ throw new ValidationError(
8381
+ "Pagination cursor has no page size. Pass the full nextToken from the previous page or set pageSize."
8382
+ );
8383
+ }
8384
+ };
8385
+
8386
+ // src/modules/groups/groups.ts
8387
+ var GroupsModule = class {
8388
+ #client;
8389
+ constructor(client) {
8390
+ this.#client = client;
8391
+ }
8392
+ /**
8393
+ * List groups with pagination, search, and ordering.
8394
+ *
8395
+ * @param options.query - Search query matched against group name.
8396
+ * @param options.ordering - Sort key; prefix with `-` for descending.
8397
+ * @param options.folderId - Only components directly in this folder.
8398
+ * @param options.noFolder - Only components at the root (not in any folder).
8399
+ * @returns Paginated `GroupsListResponse`.
8400
+ */
8401
+ list = async (options = {}) => {
8402
+ const {
8403
+ query: searchQuery,
8404
+ cursor,
8405
+ pageSize,
8406
+ ordering,
8407
+ folderId,
8408
+ noFolder,
8409
+ ...requestOptions
8410
+ } = options;
8411
+ return this.#client.get("/groups/", {
8412
+ queryParams: {
8413
+ query: searchQuery,
8414
+ cursor,
8415
+ page_size: pageSize,
8416
+ ordering,
8417
+ folderId,
8418
+ noFolder
8419
+ },
8420
+ ...requestOptions
8421
+ });
8422
+ };
8423
+ /**
8424
+ * Fetch every group across all pages.
8425
+ */
8426
+ getAll = async (options = {}) => getAllPages((pageOptions) => this.list({ ...options, ...pageOptions }));
8427
+ /**
8428
+ * Fetch a single group by ID (with nested steps).
8429
+ *
8430
+ * @throws {NotFoundError} When no group matches `groupId`.
8431
+ */
8432
+ get = async (groupId, options = {}) => this.#client.get("/groups/{id}/", {
8433
+ pathParams: { id: groupId },
8434
+ ...options
8435
+ });
8436
+ /**
8437
+ * Create a new (empty) group.
8438
+ *
8439
+ * @throws {ValidationError} On invalid payload.
8440
+ */
8441
+ create = async (data, options = {}) => this.#client.post("/groups/", {
8442
+ body: data,
8443
+ ...options
8444
+ });
8445
+ /**
8446
+ * Fully replace a group via PUT. Use {@link partialUpdate} for PATCH semantics.
8447
+ *
8448
+ * @throws {NotFoundError} When the group does not exist.
8449
+ * @throws {ValidationError} On invalid payload.
8450
+ */
8451
+ update = async (groupId, data, options = {}) => this.#client.put("/groups/{id}/", {
8452
+ pathParams: { id: groupId },
8453
+ body: data,
8454
+ ...options
8455
+ });
8456
+ /**
8457
+ * Patch selected fields on a group (PATCH semantics).
8458
+ *
8459
+ * @throws {NotFoundError} When the group does not exist.
8460
+ * @throws {ValidationError} On invalid payload.
8461
+ */
8462
+ partialUpdate = async (groupId, data, options = {}) => this.#client.patch("/groups/{id}/", {
8463
+ pathParams: { id: groupId },
8464
+ body: data,
8465
+ ...options
8466
+ });
8467
+ /**
8468
+ * Delete a group by ID. Tests that reference this group will lose those steps.
8469
+ *
8470
+ * @throws {NotFoundError} When the group does not exist.
8471
+ */
8472
+ delete = async (groupId, options = {}) => this.#client.delete("/groups/{id}/", {
8473
+ pathParams: { id: groupId },
8474
+ ...options
8475
+ });
8476
+ };
8477
+
8478
+ // ../core/dist/utils/validation.js
8479
+ var UUID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
8480
+ var isUuid = (value) => UUID_REGEX.test(value);
8481
+
8436
8482
  // src/modules/profiles/profiles.ts
8437
8483
  var ProfilesModule = class {
8438
8484
  #client;
@@ -8513,11 +8559,20 @@ var ProfilesModule = class {
8513
8559
  if (isUuid(profileNameOrId)) {
8514
8560
  return profileNameOrId;
8515
8561
  }
8516
- const profile = await this.findByName(profileNameOrId, options);
8517
- if (!profile) {
8518
- throw new NotFoundError(`Profile '${profileNameOrId}' not found`);
8562
+ const profiles = await this.getAll(options);
8563
+ const matches = profiles.filter((profile) => profile.name === profileNameOrId);
8564
+ if (matches.length > 1) {
8565
+ throw new ValidationError(
8566
+ `Profile name '${profileNameOrId}' is ambiguous (${matches.length} profiles share it). Pass the profile UUID or select a project. Matching IDs: ${matches.map((profile) => profile.id).join(", ")}`
8567
+ );
8519
8568
  }
8520
- return profile.id;
8569
+ if (matches.length === 0) {
8570
+ const available = profiles.map((profile) => profile.name).join(", ") || "none";
8571
+ throw new NotFoundError(
8572
+ `Profile '${profileNameOrId}' not found. Available profiles: ${available}`
8573
+ );
8574
+ }
8575
+ return matches[0].id;
8521
8576
  };
8522
8577
  };
8523
8578
 
@@ -8784,6 +8839,72 @@ var pollRunUntilComplete = async (getRun, isComplete, options) => {
8784
8839
  throw new TimeoutError(timeout, options.timeoutMessage(timeout));
8785
8840
  };
8786
8841
 
8842
+ // src/modules/suites/suites.utils.ts
8843
+ var FAILED_STATUSES = /* @__PURE__ */ new Set(["failed", "error"]);
8844
+ var asString = (value) => typeof value === "string" && value !== "" ? value : null;
8845
+ var parseStepRuns = (stepsRuns) => {
8846
+ if (Array.isArray(stepsRuns)) {
8847
+ return stepsRuns;
8848
+ }
8849
+ if (typeof stepsRuns === "string" && stepsRuns.trim().startsWith("[")) {
8850
+ try {
8851
+ const parsed = JSON.parse(stepsRuns);
8852
+ return Array.isArray(parsed) ? parsed : [];
8853
+ } catch {
8854
+ return [];
8855
+ }
8856
+ }
8857
+ return [];
8858
+ };
8859
+ var findFailingStep = (testRun) => {
8860
+ const failing = parseStepRuns(testRun.stepsRuns).findLast(
8861
+ (stepRun) => FAILED_STATUSES.has(String(stepRun.status)) && !stepRun.ignoredFailed
8862
+ );
8863
+ if (!failing) {
8864
+ return null;
8865
+ }
8866
+ return {
8867
+ stepRunId: asString(failing.id) ?? "",
8868
+ stepId: asString(failing.stepId),
8869
+ stepType: asString(failing.stepType),
8870
+ status: asString(failing.status),
8871
+ errorCode: asString(failing.errorCode),
8872
+ error: asString(failing.error)
8873
+ };
8874
+ };
8875
+ var summarizeFailedTest = (testRun) => ({
8876
+ testRunId: testRun.id,
8877
+ testId: testRun.testId ?? null,
8878
+ name: testRun.name,
8879
+ status: testRun.status,
8880
+ errorCode: testRun.errorCode ?? null,
8881
+ isAutoRetried: testRun.isAutoRetried,
8882
+ ...testRun.webappUrl ? { webappUrl: testRun.webappUrl } : {},
8883
+ failingStep: findFailingStep(testRun)
8884
+ });
8885
+ var summarizeSuiteRun = (run) => {
8886
+ const testRuns = run.testRuns ?? [];
8887
+ const byStatus = {};
8888
+ for (const testRun of testRuns) {
8889
+ byStatus[testRun.status] = (byStatus[testRun.status] ?? 0) + 1;
8890
+ }
8891
+ const failedTestRuns = testRuns.filter((testRun) => FAILED_STATUSES.has(testRun.status));
8892
+ return {
8893
+ id: run.id,
8894
+ name: run.name,
8895
+ status: run.status,
8896
+ suiteId: run.suiteId ?? null,
8897
+ errorCode: run.errorCode ?? null,
8898
+ started: run.started ?? null,
8899
+ ended: run.ended ?? null,
8900
+ duration: run.duration ?? null,
8901
+ webappUrl: run.webappUrl,
8902
+ totals: { total: testRuns.length, byStatus },
8903
+ failedTestsCount: failedTestRuns.length,
8904
+ failedTests: failedTestRuns.map(summarizeFailedTest)
8905
+ };
8906
+ };
8907
+
8787
8908
  // src/modules/suites/suites.ts
8788
8909
  var SuitesModule = class {
8789
8910
  #client;
@@ -8917,6 +9038,14 @@ var SuitesModule = class {
8917
9038
  pathParams: { id: runId },
8918
9039
  ...options
8919
9040
  });
9041
+ /**
9042
+ * Fetch a compact suite-run view: status, totals per status and only the failed tests with
9043
+ * their failing step. Use it instead of {@link getRun} for large suites; the full payload of
9044
+ * a 300-test run is several MB.
9045
+ *
9046
+ * @throws {NotFoundError} When the run does not exist.
9047
+ */
9048
+ getRunSummary = async (runId, options = {}) => summarizeSuiteRun(await this.getRun(runId, options));
8920
9049
  /**
8921
9050
  * Replace tags assigned directly to a suite by tag name.
8922
9051
  */
@@ -9909,14 +10038,14 @@ function promiseAllObject(promisesObj) {
9909
10038
  }
9910
10039
  function randomString(length = 10) {
9911
10040
  const chars = "abcdefghijklmnopqrstuvwxyz";
9912
- let str = "";
10041
+ let str2 = "";
9913
10042
  for (let i = 0; i < length; i++) {
9914
- str += chars[Math.floor(Math.random() * chars.length)];
10043
+ str2 += chars[Math.floor(Math.random() * chars.length)];
9915
10044
  }
9916
- return str;
10045
+ return str2;
9917
10046
  }
9918
- function esc(str) {
9919
- return JSON.stringify(str);
10047
+ function esc(str2) {
10048
+ return JSON.stringify(str2);
9920
10049
  }
9921
10050
  function slugify(input2) {
9922
10051
  return input2.toLowerCase().trim().replace(/[^\w\s-]/g, "").replace(/[\s_-]+/g, "-").replace(/^-+|-+$/g, "");
@@ -10030,8 +10159,8 @@ var primitiveTypes = /* @__PURE__ */ new Set([
10030
10159
  "symbol",
10031
10160
  "undefined"
10032
10161
  ]);
10033
- function escapeRegex(str) {
10034
- return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
10162
+ function escapeRegex(str2) {
10163
+ return str2.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
10035
10164
  }
10036
10165
  function clone(inst, def, params) {
10037
10166
  const cl = new inst._zod.constr(def ?? inst._zod.def);
@@ -10297,13 +10426,13 @@ function getSizableOrigin(input2) {
10297
10426
  return "unknown";
10298
10427
  }
10299
10428
  var highSurrogate = /[\uD800-\uDBFF]/;
10300
- function codePointLength(str) {
10301
- const units = str.length;
10302
- if (!highSurrogate.test(str))
10429
+ function codePointLength(str2) {
10430
+ const units = str2.length;
10431
+ if (!highSurrogate.test(str2))
10303
10432
  return units;
10304
10433
  let count = units;
10305
10434
  for (let i = 0; i < units - 1; i++) {
10306
- if ((str.charCodeAt(i) & 64512) === 55296 && (str.charCodeAt(i + 1) & 64512) === 56320) {
10435
+ if ((str2.charCodeAt(i) & 64512) === 55296 && (str2.charCodeAt(i + 1) & 64512) === 56320) {
10307
10436
  count--;
10308
10437
  i++;
10309
10438
  }
@@ -28794,7 +28923,7 @@ function date4(params) {
28794
28923
  // ../api-schema/dist/schemas/common.js
28795
28924
  var UuidSchema = external_exports.string().min(1).describe("UUID");
28796
28925
  var DateTimeSchema = external_exports.string().describe("ISO 8601 date-time string");
28797
- var CursorSchema = external_exports.string().describe("Opaque cursor for the next page: pass the `next_token` value from the previous response. There is no page number parameter.");
28926
+ var CursorSchema = external_exports.string().describe("Opaque cursor for the next page: pass the `nextToken` value from the previous response. It is `null` on the last page.");
28798
28927
  var PageSizeSchema = external_exports.number().int().min(1).max(100).describe("Number of results per page.");
28799
28928
  var StepTimingSecondsSchema = external_exports.number().min(0).max(300).nullable().optional();
28800
28929
 
@@ -29476,6 +29605,7 @@ var TagsModule = class {
29476
29605
  };
29477
29606
 
29478
29607
  // src/modules/tests/tests.utils.ts
29608
+ import { unzipSync } from "fflate";
29479
29609
  function buildTestImportFormData(payload, fmt) {
29480
29610
  const form = new FormData();
29481
29611
  const filename = fmt === "yaml" ? "test.yaml" : "test.zip";
@@ -29484,6 +29614,194 @@ function buildTestImportFormData(payload, fmt) {
29484
29614
  form.append("file", blob, filename);
29485
29615
  return form;
29486
29616
  }
29617
+ var CONSOLE_MESSAGE_MAX_CHARS = 2e3;
29618
+ var NETWORK_BODY_MAX_CHARS = 4e3;
29619
+ var DEFAULT_QUERY_LIMIT = 50;
29620
+ var MAX_QUERY_LIMIT = 200;
29621
+ var REDACTED = "[REDACTED]";
29622
+ var SENSITIVE_NAME = /authorization|cookie|token|secret|password|api[-_]?key|session|credential/i;
29623
+ var LOG_LINE = /^(\d{4}-\d{2}-\d{2}T[\d:.]+) \[tab: ([^\]]+)\]: \[(BUGBUG:BACKGROUND|BUGBUG:CONTENT|WEBSITE)(?::([A-Z]+))?\] ?(.*)$/;
29624
+ var SOURCE_BY_TAG = {
29625
+ "BUGBUG:BACKGROUND": "bugbug-background",
29626
+ "BUGBUG:CONTENT": "bugbug-content",
29627
+ WEBSITE: "website"
29628
+ };
29629
+ var parseConsoleLogs = (text) => {
29630
+ const entries = [];
29631
+ for (const line of text.split("\n")) {
29632
+ const match = LOG_LINE.exec(line);
29633
+ if (match) {
29634
+ const [, timestamp, tab, tag, level, message] = match;
29635
+ entries.push({
29636
+ timestamp,
29637
+ tab,
29638
+ source: SOURCE_BY_TAG[tag],
29639
+ level: level ? level.toLowerCase() : null,
29640
+ message
29641
+ });
29642
+ } else if (entries.length > 0) {
29643
+ entries[entries.length - 1].message += `
29644
+ ${line}`;
29645
+ }
29646
+ }
29647
+ return entries;
29648
+ };
29649
+ var parseConsoleLogsPartial = (text) => {
29650
+ const raw = JSON.parse(text);
29651
+ if (!Array.isArray(raw)) {
29652
+ return [];
29653
+ }
29654
+ return raw.flatMap((item) => {
29655
+ const { type, timestamp, message, tab_id: tabId } = item;
29656
+ if (typeof type !== "string" || typeof message !== "string" || typeof timestamp !== "number") {
29657
+ return [];
29658
+ }
29659
+ const [kind, level] = type.split(":");
29660
+ const source = kind === "website" ? "website" : type === "BugBug:Content" ? "bugbug-content" : "bugbug-background";
29661
+ return [
29662
+ {
29663
+ timestamp: new Date(timestamp).toISOString().replace("Z", ""),
29664
+ tab: tabId === null || tabId === void 0 ? "background" : String(tabId),
29665
+ source,
29666
+ level: kind === "website" ? level ?? null : null,
29667
+ message: message.replace(/^\[[A-Z:]+\] ?/, "")
29668
+ }
29669
+ ];
29670
+ });
29671
+ };
29672
+ var clampLimit = (limit) => Math.min(toPositiveInt(limit) ?? DEFAULT_QUERY_LIMIT, MAX_QUERY_LIMIT);
29673
+ var pageOf = (items, options) => {
29674
+ const offset = options.cursor === void 0 ? 0 : Number(options.cursor);
29675
+ if (!Number.isInteger(offset) || offset < 0) {
29676
+ throw new ValidationError(
29677
+ `Invalid cursor "${options.cursor}". Pass the nextToken from the previous response.`
29678
+ );
29679
+ }
29680
+ const page = items.slice(offset, offset + clampLimit(options.limit));
29681
+ const next = offset + page.length;
29682
+ return { page, total: items.length, nextToken: next < items.length ? String(next) : null };
29683
+ };
29684
+ var queryConsoleLogEntries = (entries, options = {}) => {
29685
+ const { source = "website", levels, text, tabId, after, before } = options;
29686
+ const wantedLevels = levels?.map((level) => level.toLowerCase());
29687
+ const needle = text?.toLowerCase();
29688
+ const matching = entries.filter((entry) => {
29689
+ if (source === "website" && entry.source !== "website") return false;
29690
+ if (source === "bugbug" && entry.source === "website") return false;
29691
+ if (wantedLevels && !(entry.level && wantedLevels.includes(entry.level))) return false;
29692
+ if (needle && !entry.message.toLowerCase().includes(needle)) return false;
29693
+ if (tabId && entry.tab !== tabId) return false;
29694
+ if (after && entry.timestamp < after.replace("Z", "")) return false;
29695
+ if (before && entry.timestamp >= before.replace("Z", "")) return false;
29696
+ return true;
29697
+ });
29698
+ const { page, total, nextToken } = pageOf(matching, options);
29699
+ return {
29700
+ entries: page.map(
29701
+ (entry) => entry.message.length > CONSOLE_MESSAGE_MAX_CHARS ? { ...entry, message: entry.message.slice(0, CONSOLE_MESSAGE_MAX_CHARS), truncated: true } : entry
29702
+ ),
29703
+ total,
29704
+ nextToken
29705
+ };
29706
+ };
29707
+ var parseHarEntries = (text) => {
29708
+ const har = JSON.parse(text);
29709
+ const entries = har?.log?.entries;
29710
+ return Array.isArray(entries) ? entries : [];
29711
+ };
29712
+ var str = (value) => typeof value === "string" ? value : "";
29713
+ var num = (value) => typeof value === "number" && Number.isFinite(value) ? value : null;
29714
+ var redactUrl = (rawUrl) => {
29715
+ try {
29716
+ const url2 = new URL(rawUrl);
29717
+ for (const key of [...url2.searchParams.keys()]) {
29718
+ if (SENSITIVE_NAME.test(key)) url2.searchParams.set(key, REDACTED);
29719
+ }
29720
+ return url2.toString();
29721
+ } catch {
29722
+ return rawUrl;
29723
+ }
29724
+ };
29725
+ var redactHeaders = (headers) => (headers ?? []).map((header) => {
29726
+ const name = str(header.name);
29727
+ return { name, value: SENSITIVE_NAME.test(name) ? REDACTED : str(header.value) };
29728
+ });
29729
+ var cut = (value) => value.length > NETWORK_BODY_MAX_CHARS ? { text: value.slice(0, NETWORK_BODY_MAX_CHARS), truncated: true } : { text: value, truncated: false };
29730
+ var toNetworkEntry = (entry, includeDetails) => {
29731
+ const status = num(entry.response?.status) ?? 0;
29732
+ const result = {
29733
+ startedDateTime: str(entry.startedDateTime),
29734
+ method: str(entry.request?.method).toUpperCase(),
29735
+ url: redactUrl(str(entry.request?.url)),
29736
+ status,
29737
+ statusText: str(entry.response?.statusText),
29738
+ mimeType: str(entry.response?.content?.mimeType) || null,
29739
+ durationMs: num(entry.time) === null ? null : Math.round(entry.time),
29740
+ responseSizeBytes: num(entry.response?.content?.size) ?? num(entry.response?.bodySize),
29741
+ tabId: entry._tabId === void 0 ? null : String(entry._tabId),
29742
+ tabUrl: str(entry._tabUrl) || null
29743
+ };
29744
+ if (!includeDetails) {
29745
+ return result;
29746
+ }
29747
+ result.requestHeaders = redactHeaders(entry.request?.headers);
29748
+ result.responseHeaders = redactHeaders(entry.response?.headers);
29749
+ const requestBody = cut(str(entry.request?.postData?.text));
29750
+ const responseBody = cut(str(entry.response?.content?.text));
29751
+ if (requestBody.text) result.requestBody = requestBody.text;
29752
+ if (responseBody.text) result.responseBody = responseBody.text;
29753
+ if (requestBody.truncated || responseBody.truncated) result.truncated = true;
29754
+ return result;
29755
+ };
29756
+ var queryNetworkEntries = (entries, options = {}) => {
29757
+ const { urlContains, method, status, failedOnly, mimeType, tabId, includeDetails } = options;
29758
+ const matching = entries.filter((entry) => {
29759
+ const entryStatus = num(entry.response?.status) ?? 0;
29760
+ if (urlContains && !str(entry.request?.url).toLowerCase().includes(urlContains.toLowerCase()))
29761
+ return false;
29762
+ if (method && str(entry.request?.method).toUpperCase() !== method.toUpperCase()) return false;
29763
+ if (status !== void 0 && entryStatus !== status) return false;
29764
+ if (failedOnly && entryStatus !== 0 && entryStatus < 400) return false;
29765
+ if (mimeType && !str(entry.response?.content?.mimeType).toLowerCase().includes(mimeType.toLowerCase()))
29766
+ return false;
29767
+ if (tabId && String(entry._tabId) !== tabId) return false;
29768
+ return true;
29769
+ });
29770
+ const { page, total, nextToken } = pageOf(matching, options);
29771
+ return {
29772
+ entries: page.map((entry) => toNetworkEntry(entry, Boolean(includeDetails))),
29773
+ total,
29774
+ nextToken
29775
+ };
29776
+ };
29777
+ var downloadArtifact = async (artifact, signal) => {
29778
+ const fileUrl = artifact.file;
29779
+ if (typeof fileUrl !== "string" || fileUrl === "") {
29780
+ throw new UnexpectedResponseError(`Debug artifact ${artifact.kind} has no file URL`);
29781
+ }
29782
+ const response = await fetch(fileUrl, { signal });
29783
+ if (!response.ok) {
29784
+ throw new UnexpectedResponseError(
29785
+ `Failed to download ${artifact.kind} artifact: ${response.status} ${response.statusText}`
29786
+ );
29787
+ }
29788
+ return new Uint8Array(await response.arrayBuffer());
29789
+ };
29790
+ var unzipHar = (bytes) => {
29791
+ try {
29792
+ const files = unzipSync(bytes);
29793
+ const name = Object.keys(files).find((file2) => file2.endsWith(".har"));
29794
+ if (!name) {
29795
+ throw new Error("the archive contains no .har file");
29796
+ }
29797
+ return new TextDecoder().decode(files[name]);
29798
+ } catch (error62) {
29799
+ throw new UnexpectedResponseError(
29800
+ `The network_logs artifact could not be unpacked (${error62 instanceof Error ? error62.message : String(error62)}). Retry later; it may still be uploading.`,
29801
+ error62 instanceof Error ? error62 : void 0
29802
+ );
29803
+ }
29804
+ };
29487
29805
 
29488
29806
  // src/modules/tests/tests.ts
29489
29807
  var TestsModule = class {
@@ -29877,6 +30195,49 @@ var TestsModule = class {
29877
30195
  pathParams: { id: runId, artifact_type: artifactType },
29878
30196
  ...options
29879
30197
  });
30198
+ /**
30199
+ * Query the console output of a test run. By default only the tested page's own console
30200
+ * (`source: 'website'`) is returned; the runner's internal entries are hidden.
30201
+ *
30202
+ * Reads the `logs` artifact, or the in-progress `logs_partial` one while the final upload is
30203
+ * pending (`partial: true`). Needs run logs enabled in the project settings.
30204
+ *
30205
+ * @throws {NotFoundError} When the run has no logs artifact.
30206
+ */
30207
+ queryConsoleLogs = async (runId, options = {}) => {
30208
+ const { signal, timeout, headers, ...query } = options;
30209
+ const artifacts = await this.listRunDebugArtifacts(runId, { signal, timeout, headers });
30210
+ const logs = artifacts.find((artifact2) => artifact2.kind === "logs");
30211
+ const artifact = logs ?? artifacts.find((a) => a.kind === "logs_partial");
30212
+ if (!artifact) {
30213
+ throw new NotFoundError(
30214
+ `Test run ${runId} has no logs artifact. Enable run logs in the project settings, or retry shortly: it may still be uploading.`
30215
+ );
30216
+ }
30217
+ const text = new TextDecoder().decode(await downloadArtifact(artifact, signal));
30218
+ const entries = logs ? parseConsoleLogs(text) : parseConsoleLogsPartial(text);
30219
+ return { ...queryConsoleLogEntries(entries, query), partial: !logs };
30220
+ };
30221
+ /**
30222
+ * Query the network requests of a test run from its `network_logs` (HAR) artifact. Credential
30223
+ * headers and query parameters are redacted; bodies are only returned with `includeDetails`
30224
+ * and are truncated.
30225
+ *
30226
+ * @throws {NotFoundError} When the run has no network logs artifact.
30227
+ */
30228
+ queryNetworkRequests = async (runId, options = {}) => {
30229
+ const { signal, timeout, headers, ...query } = options;
30230
+ const artifacts = await this.listRunDebugArtifacts(runId, { signal, timeout, headers });
30231
+ const artifact = artifacts.find((a) => a.kind === "network_logs");
30232
+ if (!artifact) {
30233
+ throw new NotFoundError(
30234
+ `Test run ${runId} has no network logs artifact. Enable run logs in the project settings, or retry shortly: it may still be uploading.`
30235
+ );
30236
+ }
30237
+ const bytes = await downloadArtifact(artifact, signal);
30238
+ const har = unzipHar(bytes);
30239
+ return queryNetworkEntries(parseHarEntries(har), query);
30240
+ };
29880
30241
  /**
29881
30242
  * Get the email inbox of a test run with its (optionally filtered) messages.
29882
30243
  *
@@ -29942,6 +30303,9 @@ var TestsModule = class {
29942
30303
  * @param fmt - Format matching `payload` (`'yaml'` or `'zip'`).
29943
30304
  * @param options.conflictMode - How to resolve naming collisions on the server
29944
30305
  * (e.g. `'rename'`). Forwarded as a query string parameter.
30306
+ * @param options.folderId - Test folder to import into. Wins over a folder path inside a ZIP;
30307
+ * omit to import to the project root. An unknown folder, a folder of another project or a
30308
+ * component folder is rejected with a {@link ValidationError}.
29945
30309
  * @throws {ValidationError} When the server rejects the payload.
29946
30310
  *
29947
30311
  * @example
@@ -29951,12 +30315,13 @@ var TestsModule = class {
29951
30315
  * ```
29952
30316
  */
29953
30317
  import = async (payload, fmt, options = {}) => {
29954
- const { conflictMode, ...requestOptions } = options;
30318
+ const { conflictMode, folderId, ...requestOptions } = options;
29955
30319
  const form = buildTestImportFormData(payload, fmt);
29956
30320
  return this.#client.postForm("/tests/import/", form, {
29957
30321
  ...requestOptions,
29958
30322
  queryParams: {
29959
- conflictMode
30323
+ conflictMode,
30324
+ folderId
29960
30325
  }
29961
30326
  });
29962
30327
  };
@@ -30256,7 +30621,7 @@ var buildUserAgent = (clientType, version2) => `BugBug ${clientType.toUpperCase(
30256
30621
  // ../core/package.json
30257
30622
  var package_default = {
30258
30623
  name: "@bugbug-io/core",
30259
- version: "14.19.1",
30624
+ version: "14.21.0",
30260
30625
  private: true,
30261
30626
  type: "module",
30262
30627
  main: "dist/index.js",
@@ -30500,6 +30865,7 @@ var RateLimiter = class {
30500
30865
  maxRequests: config2.maxRequests,
30501
30866
  windowMs: config2.windowMs,
30502
30867
  maxConcurrentRequests: config2.maxConcurrentRequests ?? Number.POSITIVE_INFINITY,
30868
+ maxQueueWaitMs: config2.maxQueueWaitMs ?? 0,
30503
30869
  retryAfter: config2.retryAfter || 1e3,
30504
30870
  retryServer429: config2.retryServer429 ?? true,
30505
30871
  exponentialBackoff: {
@@ -30539,12 +30905,22 @@ var RateLimiter = class {
30539
30905
  */
30540
30906
  async execute(fn, options = {}) {
30541
30907
  const retryServer429 = options.retryServer429 ?? this.#config.retryServer429;
30908
+ const retryThrottled = options.retryThrottled ?? false;
30909
+ const retryNetworkErrors = options.retryNetworkErrors ?? false;
30542
30910
  let lastError = null;
30911
+ let queuedMs = 0;
30543
30912
  await this.#acquireSlot();
30544
30913
  try {
30545
30914
  for (let attempt = 0; attempt <= this.#config.exponentialBackoff.maxRetries; attempt++) {
30546
30915
  if (!this.#canMakeRequest()) {
30547
30916
  const waitTime = this.#getWaitTime();
30917
+ if (queuedMs + waitTime <= this.#config.maxQueueWaitMs) {
30918
+ const sleepMs = Math.max(waitTime, 1);
30919
+ queuedMs += sleepMs;
30920
+ await this.#sleep(sleepMs + 1);
30921
+ attempt -= 1;
30922
+ continue;
30923
+ }
30548
30924
  const gateError = new RateLimitError(
30549
30925
  waitTime,
30550
30926
  `Rate limit exceeded. Wait ${waitTime}ms before retrying.`
@@ -30561,11 +30937,19 @@ var RateLimiter = class {
30561
30937
  return await fn();
30562
30938
  } catch (fnError) {
30563
30939
  this.#releaseRequest(stamp);
30940
+ if (fnError instanceof NetworkError) {
30941
+ if (!retryNetworkErrors || attempt === this.#config.exponentialBackoff.maxRetries) {
30942
+ throw fnError;
30943
+ }
30944
+ lastError = fnError;
30945
+ await this.#sleep(this.#computeBackoff(attempt));
30946
+ continue;
30947
+ }
30564
30948
  if (!(fnError instanceof RateLimitError)) {
30565
30949
  throw fnError;
30566
30950
  }
30567
30951
  lastError = fnError;
30568
- if (!retryServer429) {
30952
+ if (!retryServer429 && !(retryThrottled && fnError.throttled)) {
30569
30953
  throw fnError;
30570
30954
  }
30571
30955
  if (attempt === this.#config.exponentialBackoff.maxRetries) {
@@ -30767,6 +31151,12 @@ function extractSubscriptionUpgradeUrl(body) {
30767
31151
  }
30768
31152
  return void 0;
30769
31153
  }
31154
+ function isThrottledErrorBody(body) {
31155
+ const errorDetails = Array.isArray(body) ? body : [body];
31156
+ return errorDetails.some(
31157
+ (errorDetail) => Boolean(errorDetail) && typeof errorDetail === "object" && errorDetail.code === "throttled"
31158
+ );
31159
+ }
30770
31160
  function formatApiErrorValue(value, path = "") {
30771
31161
  if (typeof value === "string") return value;
30772
31162
  if (typeof value === "number" || typeof value === "boolean") return String(value);
@@ -30994,7 +31384,11 @@ var BugBugApiClient = class {
30994
31384
  throw this.#toTransportError(error62, requestOrigin, abortContext);
30995
31385
  }
30996
31386
  },
30997
- { retryServer429: this.#canRetryServer429(method) }
31387
+ {
31388
+ retryServer429: this.#canRetryServer429(method),
31389
+ retryThrottled: this.#config.rateLimit.retryServer429 !== false,
31390
+ retryNetworkErrors: method === "GET"
31391
+ }
30998
31392
  );
30999
31393
  };
31000
31394
  /**
@@ -31051,7 +31445,8 @@ var BugBugApiClient = class {
31051
31445
  parseRetryAfterMs(response?.headers.get("Retry-After")),
31052
31446
  errorMessage || "Rate limit exceeded",
31053
31447
  response,
31054
- requestWithResponseContext
31448
+ requestWithResponseContext,
31449
+ isThrottledErrorBody(errorBody)
31055
31450
  );
31056
31451
  }
31057
31452
  case 500:
@@ -31095,13 +31490,28 @@ var BugBugApiClient = class {
31095
31490
  */
31096
31491
  get = async (path, options = {}) => {
31097
31492
  const { queryParams, pathParams, ...requestOptions } = options;
31098
- return this.#makeRequest("GET", path, {
31493
+ if (queryParams === void 0 || !("cursor" in queryParams)) {
31494
+ return this.#makeRequest("GET", path, {
31495
+ params: { query: queryParams, path: pathParams },
31496
+ ...requestOptions
31497
+ });
31498
+ }
31499
+ const { cursor, ...otherParams } = queryParams;
31500
+ const parsedCursor = parseCursor(cursor);
31501
+ const pageSize = toPositiveInt(otherParams.page_size) ?? parsedCursor?.pageSize;
31502
+ requireKnownPageSize(parsedCursor, pageSize);
31503
+ const response = await this.#makeRequest("GET", path, {
31099
31504
  params: {
31100
- query: queryParams,
31505
+ query: {
31506
+ ...otherParams,
31507
+ ...pageSize === void 0 ? {} : { page_size: pageSize },
31508
+ ...parsedCursor ? { page: parsedCursor.page } : {}
31509
+ },
31101
31510
  path: pathParams
31102
31511
  },
31103
31512
  ...requestOptions
31104
31513
  });
31514
+ return withNextToken(response, pageSize);
31105
31515
  };
31106
31516
  /**
31107
31517
  * Issue a POST request. The body is JSON-serialized by openapi-fetch.
@@ -31344,7 +31754,11 @@ var BugBugApiClient = class {
31344
31754
  throw this.#toTransportError(error62, requestOrigin, abortContext);
31345
31755
  }
31346
31756
  },
31347
- { retryServer429: this.#canRetryServer429(method) }
31757
+ {
31758
+ retryServer429: this.#canRetryServer429(method),
31759
+ retryThrottled: this.#config.rateLimit.retryServer429 !== false,
31760
+ retryNetworkErrors: method === "GET"
31761
+ }
31348
31762
  );
31349
31763
  };
31350
31764
  #canRetryServer429 = (method) => method === "GET" && this.#config.rateLimit.retryServer429 !== false;
@@ -31696,6 +32110,7 @@ export {
31696
32110
  createOAuthCodeChallenge,
31697
32111
  createOAuthCodeVerifier,
31698
32112
  createOAuthState,
32113
+ findFailingStep,
31699
32114
  isAssertionStepType,
31700
32115
  isAuthenticationError,
31701
32116
  isAuthorizationError,