glitchgrab 1.35.0 → 1.37.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.mjs CHANGED
@@ -588,7 +588,7 @@ async function enhanceText(text, token, baseUrl, screenshot, context) {
588
588
  }
589
589
  }
590
590
  async function assistTurn(params, token, baseUrl) {
591
- var _a, _b, _c, _d, _e, _f, _g;
591
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m;
592
592
  const offline = {
593
593
  conversationId: null,
594
594
  question: null,
@@ -617,7 +617,10 @@ async function assistTurn(params, token, baseUrl) {
617
617
  return {
618
618
  conversationId: (_c = (_b = envelope.data) == null ? void 0 : _b.conversationId) != null ? _c : null,
619
619
  question: (_e = (_d = envelope.data) == null ? void 0 : _d.question) != null ? _e : null,
620
- report: (_g = (_f = envelope.data) == null ? void 0 : _f.report) != null ? _g : null,
620
+ options: (_g = (_f = envelope.data) == null ? void 0 : _f.options) != null ? _g : [],
621
+ report: (_i = (_h = envelope.data) == null ? void 0 : _h.report) != null ? _i : null,
622
+ duplicate: (_k = (_j = envelope.data) == null ? void 0 : _j.duplicate) != null ? _k : null,
623
+ solved: (_m = (_l = envelope.data) == null ? void 0 : _l.solved) != null ? _m : null,
621
624
  degraded: null
622
625
  };
623
626
  } catch (e) {
@@ -1148,6 +1151,26 @@ function AnnotationCanvas({ imageSrc, onSave, onCancel }) {
1148
1151
  }
1149
1152
  );
1150
1153
  }
1154
+ function getTypeLabel(type) {
1155
+ switch (type) {
1156
+ case "RATING":
1157
+ return "Rating";
1158
+ case "BUG":
1159
+ return "Bug Report";
1160
+ case "FEATURE_REQUEST":
1161
+ return "Feature Request";
1162
+ case "UI_IMPROVEMENT":
1163
+ return "UI Improvement";
1164
+ case "PERFORMANCE":
1165
+ return "Performance";
1166
+ case "SECURITY":
1167
+ return "Security";
1168
+ case "QUESTION":
1169
+ return "Question";
1170
+ case "OTHER":
1171
+ return "Other";
1172
+ }
1173
+ }
1151
1174
  var STARTERS = [
1152
1175
  "Something on this page is broken",
1153
1176
  "It did the wrong thing",
@@ -1226,6 +1249,12 @@ function AssistSheet({
1226
1249
  attachmentCount,
1227
1250
  context,
1228
1251
  reportTypeLabel,
1252
+ typePicked,
1253
+ currentTile,
1254
+ tiles,
1255
+ onPickType,
1256
+ rating,
1257
+ onRatingChange,
1229
1258
  projectSlot,
1230
1259
  reporterName,
1231
1260
  description,
@@ -1233,18 +1262,27 @@ function AssistSheet({
1233
1262
  severity,
1234
1263
  onSeverityChange,
1235
1264
  showSeverity,
1265
+ onDuplicateChange,
1266
+ onConversationChange,
1236
1267
  isSubmitting,
1237
1268
  submitted,
1238
1269
  onSend,
1239
1270
  onDegrade,
1240
- onClose
1271
+ onClose,
1272
+ onFinish
1241
1273
  }) {
1242
1274
  const narrow = useIsNarrow();
1243
1275
  const [messages, setMessages] = useState2([]);
1244
1276
  const [input, setInput] = useState2("");
1245
1277
  const [busy, setBusy] = useState2(false);
1246
1278
  const [conversationId, setConversationId] = useState2(null);
1247
- const [phase, setPhase] = useState2("chat");
1279
+ const [hoveredStar, setHoveredStar] = useState2(0);
1280
+ const [options, setOptions] = useState2([]);
1281
+ const [duplicate, setDuplicate] = useState2(null);
1282
+ const [solved, setSolved] = useState2(null);
1283
+ const [phase, setPhase] = useState2(
1284
+ !typePicked ? "type" : currentTile === "RATING" ? "rating" : "chat"
1285
+ );
1248
1286
  const scrollRef = useRef2(null);
1249
1287
  const inputRef = useRef2(null);
1250
1288
  const draftRef = useRef2(null);
@@ -1258,6 +1296,7 @@ function AssistSheet({
1258
1296
  if (phase === "draft") (_a = draftRef.current) == null ? void 0 : _a.focus();
1259
1297
  }, [phase]);
1260
1298
  async function runTurn(history2) {
1299
+ var _a, _b, _c, _d;
1261
1300
  setBusy(true);
1262
1301
  let result;
1263
1302
  try {
@@ -1272,15 +1311,28 @@ function AssistSheet({
1272
1311
  onDegrade(result.degraded);
1273
1312
  return;
1274
1313
  }
1275
- if (result.conversationId) setConversationId(result.conversationId);
1314
+ if (result.conversationId) {
1315
+ setConversationId(result.conversationId);
1316
+ onConversationChange == null ? void 0 : onConversationChange(result.conversationId);
1317
+ }
1318
+ setDuplicate((_a = result.duplicate) != null ? _a : null);
1319
+ onDuplicateChange == null ? void 0 : onDuplicateChange((_c = (_b = result.duplicate) == null ? void 0 : _b.number) != null ? _c : null);
1320
+ if (result.solved) {
1321
+ setSolved(result.solved);
1322
+ setOptions([]);
1323
+ setPhase("solved");
1324
+ return;
1325
+ }
1276
1326
  if (result.report) {
1277
1327
  onDescriptionChange(result.report);
1278
1328
  setMessages([...history2, { role: "assistant", content: "Here's your report \u2014 have a read." }]);
1329
+ setOptions([]);
1279
1330
  setPhase("draft");
1280
1331
  return;
1281
1332
  }
1282
1333
  if (result.question) {
1283
1334
  setMessages([...history2, { role: "assistant", content: result.question }]);
1335
+ setOptions((_d = result.options) != null ? _d : []);
1284
1336
  return;
1285
1337
  }
1286
1338
  onDegrade("The assistant had nothing to add \u2014 write your report below and send it as normal.");
@@ -1288,6 +1340,7 @@ function AssistSheet({
1288
1340
  useEffect2(() => {
1289
1341
  if (seededRef.current) return;
1290
1342
  seededRef.current = true;
1343
+ if (!typePicked || currentTile === "RATING") return;
1291
1344
  const seed = description.trim();
1292
1345
  if (!seed) return;
1293
1346
  const history2 = [{ role: "user", content: seed }];
@@ -1297,12 +1350,17 @@ function AssistSheet({
1297
1350
  function send(text) {
1298
1351
  const value = text.trim();
1299
1352
  if (!value || busy) return;
1353
+ setOptions([]);
1300
1354
  const history2 = [...messages, { role: "user", content: value }];
1301
1355
  setMessages(history2);
1302
1356
  setInput("");
1303
1357
  void runTurn(history2);
1304
1358
  }
1305
- const empty = messages.length === 0 && !busy;
1359
+ function pickType(tile) {
1360
+ onPickType(tile);
1361
+ setPhase(tile === "RATING" ? "rating" : "chat");
1362
+ }
1363
+ const empty = phase === "chat" && messages.length === 0 && !busy;
1306
1364
  const initials = (reporterName != null ? reporterName : "").split(/\s+/).filter(Boolean).slice(0, 2).map((w) => {
1307
1365
  var _a, _b;
1308
1366
  return (_b = (_a = w[0]) == null ? void 0 : _a.toUpperCase()) != null ? _b : "";
@@ -1418,7 +1476,7 @@ function AssistSheet({
1418
1476
  }
1419
1477
  ),
1420
1478
  /* @__PURE__ */ jsxs2("div", { style: { fontSize: "11.5px", color: t2.textMuted, marginTop: "3px" }, children: [
1421
- reportTypeLabel,
1479
+ phase === "type" ? null : reportTypeLabel,
1422
1480
  projectSlot ? /* @__PURE__ */ jsx2("span", { style: { marginLeft: "6px" }, children: projectSlot }) : null
1423
1481
  ] })
1424
1482
  ] }),
@@ -1426,20 +1484,24 @@ function AssistSheet({
1426
1484
  "button",
1427
1485
  {
1428
1486
  type: "button",
1487
+ "data-gg-write-myself": "",
1429
1488
  onClick: onClose,
1430
- "aria-label": "Close and write it myself",
1489
+ "aria-label": "Write it myself instead",
1431
1490
  style: {
1432
1491
  flexShrink: 0,
1433
- border: "none",
1492
+ border: `1px solid ${t2.inputBorder}`,
1493
+ borderRadius: "999px",
1434
1494
  background: "transparent",
1435
1495
  color: t2.textMuted,
1436
1496
  cursor: "pointer",
1437
- fontSize: narrow ? "18px" : "12px",
1497
+ fontSize: "11.5px",
1438
1498
  lineHeight: 1,
1439
1499
  fontFamily: "inherit",
1440
- padding: narrow ? "4px 6px" : "6px 4px"
1500
+ whiteSpace: "nowrap",
1501
+ // ~32px tall either way — this is the escape hatch, not a hint.
1502
+ padding: "9px 11px"
1441
1503
  },
1442
- children: narrow ? "\xD7" : "Write it myself"
1504
+ children: "Write it myself"
1443
1505
  }
1444
1506
  )
1445
1507
  ]
@@ -1468,6 +1530,182 @@ function AssistSheet({
1468
1530
  minWidth: 0
1469
1531
  },
1470
1532
  children: [
1533
+ phase === "type" && /* @__PURE__ */ jsxs2("div", { style: { display: "flex", flexDirection: "column", gap: "12px" }, children: [
1534
+ /* @__PURE__ */ jsxs2("div", { style: { display: "flex", gap: "8px" }, children: [
1535
+ /* @__PURE__ */ jsx2(Avatar, { who: "assistant", theme: t2 }),
1536
+ /* @__PURE__ */ jsxs2(
1537
+ "div",
1538
+ {
1539
+ style: {
1540
+ padding: "9px 12px",
1541
+ borderRadius: "12px 12px 12px 4px",
1542
+ backgroundColor: t2.bgSecondary,
1543
+ fontSize: "13px",
1544
+ lineHeight: 1.55,
1545
+ maxWidth: "88%"
1546
+ },
1547
+ children: [
1548
+ reporterName ? `Hi ${reporterName.split(" ")[0]} \u2014 w` : "W",
1549
+ "hat do you want to do? Pick one and I'll take it from there."
1550
+ ]
1551
+ }
1552
+ )
1553
+ ] }),
1554
+ /* @__PURE__ */ jsx2(
1555
+ "div",
1556
+ {
1557
+ style: {
1558
+ display: "flex",
1559
+ flexWrap: "wrap",
1560
+ gap: "6px",
1561
+ paddingLeft: "32px"
1562
+ },
1563
+ children: tiles.map((tile) => {
1564
+ const rate = tile === "RATING";
1565
+ return /* @__PURE__ */ jsx2(
1566
+ "button",
1567
+ {
1568
+ type: "button",
1569
+ "data-gg-chip": "",
1570
+ "data-gg-tile": tile,
1571
+ onClick: () => pickType(tile),
1572
+ style: {
1573
+ display: "inline-flex",
1574
+ alignItems: "center",
1575
+ gap: "5px",
1576
+ // The rating is the only tile that isn't a report, so
1577
+ // it wears the star colour the dialog's hero row uses
1578
+ // rather than hiding among the report types.
1579
+ border: `1px solid ${rate ? "rgba(245,158,11,0.5)" : t2.inputBorder}`,
1580
+ background: rate ? "rgba(245,158,11,0.08)" : "transparent",
1581
+ color: rate ? "#f59e0b" : t2.textMuted,
1582
+ borderRadius: "999px",
1583
+ // 8px vertical keeps the tap target at ~32px.
1584
+ padding: "8px 12px",
1585
+ fontSize: "12px",
1586
+ fontWeight: rate ? 600 : 400,
1587
+ fontFamily: "inherit",
1588
+ cursor: "pointer"
1589
+ },
1590
+ children: rate ? "\u2605 Rate us" : getTypeLabel(tile)
1591
+ },
1592
+ tile
1593
+ );
1594
+ })
1595
+ }
1596
+ )
1597
+ ] }),
1598
+ phase === "rating" && !submitted && /* @__PURE__ */ jsxs2("div", { style: { display: "flex", flexDirection: "column", gap: "12px" }, children: [
1599
+ /* @__PURE__ */ jsxs2("div", { style: { display: "flex", gap: "8px" }, children: [
1600
+ /* @__PURE__ */ jsx2(Avatar, { who: "assistant", theme: t2 }),
1601
+ /* @__PURE__ */ jsx2(
1602
+ "div",
1603
+ {
1604
+ style: {
1605
+ padding: "9px 12px",
1606
+ borderRadius: "12px 12px 12px 4px",
1607
+ backgroundColor: t2.bgSecondary,
1608
+ fontSize: "13px",
1609
+ lineHeight: 1.55,
1610
+ maxWidth: "88%"
1611
+ },
1612
+ children: "How are we doing? Tap a star \u2014 the words are optional."
1613
+ }
1614
+ )
1615
+ ] }),
1616
+ /* @__PURE__ */ jsxs2(
1617
+ "div",
1618
+ {
1619
+ style: {
1620
+ display: "flex",
1621
+ flexDirection: "column",
1622
+ gap: "10px",
1623
+ marginLeft: "32px",
1624
+ padding: "12px",
1625
+ borderRadius: "12px",
1626
+ border: "1px solid rgba(245,158,11,0.4)",
1627
+ backgroundColor: "rgba(245,158,11,0.06)"
1628
+ },
1629
+ children: [
1630
+ /* @__PURE__ */ jsx2("div", { style: { display: "flex", gap: "4px" }, role: "group", "aria-label": "Rating", children: [1, 2, 3, 4, 5].map((star) => {
1631
+ const filled = star <= (hoveredStar || rating);
1632
+ return /* @__PURE__ */ jsx2(
1633
+ "button",
1634
+ {
1635
+ type: "button",
1636
+ "aria-label": `${star} star${star > 1 ? "s" : ""}`,
1637
+ "aria-pressed": star <= rating,
1638
+ onClick: () => onRatingChange(star),
1639
+ onMouseEnter: () => setHoveredStar(star),
1640
+ onMouseLeave: () => setHoveredStar(0),
1641
+ style: {
1642
+ border: "none",
1643
+ background: "transparent",
1644
+ padding: 0,
1645
+ cursor: "pointer",
1646
+ lineHeight: 0
1647
+ },
1648
+ children: /* @__PURE__ */ jsx2("svg", { width: "30", height: "30", viewBox: "0 0 24 24", "aria-hidden": "true", children: /* @__PURE__ */ jsx2(
1649
+ "path",
1650
+ {
1651
+ d: "M12 3l2.6 5.3 5.9.9-4.3 4.1 1 5.8L12 16.4 6.8 19.1l1-5.8L3.5 9.2l5.9-.9L12 3z",
1652
+ fill: filled ? "#f59e0b" : "transparent",
1653
+ stroke: filled ? "#f59e0b" : t2.inputBorder,
1654
+ strokeWidth: "1.5",
1655
+ strokeLinejoin: "round"
1656
+ }
1657
+ ) })
1658
+ },
1659
+ star
1660
+ );
1661
+ }) }),
1662
+ /* @__PURE__ */ jsx2(
1663
+ "textarea",
1664
+ {
1665
+ value: description,
1666
+ onChange: (e) => onDescriptionChange(e.target.value),
1667
+ rows: 3,
1668
+ placeholder: "What made it good \u2014 or what let you down? (optional)",
1669
+ style: {
1670
+ width: "100%",
1671
+ padding: "10px",
1672
+ borderRadius: "8px",
1673
+ border: `1px solid ${t2.inputBorder}`,
1674
+ backgroundColor: t2.inputBg,
1675
+ color: t2.text,
1676
+ fontSize: "13px",
1677
+ lineHeight: 1.5,
1678
+ fontFamily: "inherit",
1679
+ resize: "vertical",
1680
+ outline: "none",
1681
+ boxSizing: "border-box"
1682
+ }
1683
+ }
1684
+ ),
1685
+ /* @__PURE__ */ jsx2(
1686
+ "button",
1687
+ {
1688
+ type: "button",
1689
+ onClick: () => setPhase("type"),
1690
+ style: {
1691
+ alignSelf: "flex-start",
1692
+ border: "none",
1693
+ background: "transparent",
1694
+ color: t2.textMuted,
1695
+ fontSize: "12px",
1696
+ fontFamily: "inherit",
1697
+ // A bare text link is ~14px tall — half a thumb.
1698
+ padding: "9px 0",
1699
+ cursor: "pointer",
1700
+ textDecoration: "underline"
1701
+ },
1702
+ children: "Report something instead"
1703
+ }
1704
+ )
1705
+ ]
1706
+ }
1707
+ )
1708
+ ] }),
1471
1709
  empty && /* @__PURE__ */ jsxs2("div", { style: { display: "flex", flexDirection: "column", gap: "12px" }, children: [
1472
1710
  /* @__PURE__ */ jsxs2("div", { style: { display: "flex", gap: "8px" }, children: [
1473
1711
  /* @__PURE__ */ jsx2(Avatar, { who: "assistant", theme: t2 }),
@@ -1556,6 +1794,47 @@ function AssistSheet({
1556
1794
  i
1557
1795
  );
1558
1796
  }),
1797
+ options.length > 0 && !busy && phase === "chat" && /* @__PURE__ */ jsx2(
1798
+ "div",
1799
+ {
1800
+ style: {
1801
+ display: "flex",
1802
+ // Long labels wrapped into a ragged row that always stranded
1803
+ // the last chip on a line of its own. Past ~24 characters
1804
+ // these stop being chips and become a choice list, so they
1805
+ // stack full width and read like one.
1806
+ flexDirection: options.some((o) => o.length > 24) ? "column" : "row",
1807
+ alignItems: options.some((o) => o.length > 24) ? "stretch" : "flex-start",
1808
+ flexWrap: "wrap",
1809
+ gap: "6px",
1810
+ paddingLeft: "32px"
1811
+ },
1812
+ children: options.map((option) => /* @__PURE__ */ jsx2(
1813
+ "button",
1814
+ {
1815
+ type: "button",
1816
+ "data-gg-chip": "",
1817
+ "data-gg-option": "",
1818
+ onClick: () => send(option),
1819
+ style: {
1820
+ border: `1px solid ${t2.inputBorder}`,
1821
+ background: "transparent",
1822
+ color: t2.textMuted,
1823
+ borderRadius: "999px",
1824
+ // Same 8px as the picker chips — one tap target size in
1825
+ // this sheet, not two.
1826
+ padding: "8px 12px",
1827
+ fontSize: "12px",
1828
+ fontFamily: "inherit",
1829
+ cursor: "pointer",
1830
+ textAlign: "left"
1831
+ },
1832
+ children: option
1833
+ },
1834
+ option
1835
+ ))
1836
+ }
1837
+ ),
1559
1838
  busy && /* @__PURE__ */ jsxs2("div", { style: { display: "flex", gap: "8px" }, role: "status", "aria-label": "Thinking", children: [
1560
1839
  /* @__PURE__ */ jsx2(Avatar, { who: "assistant", theme: t2 }),
1561
1840
  /* @__PURE__ */ jsx2(
@@ -1613,6 +1892,32 @@ function AssistSheet({
1613
1892
  children: "Your report \xB7 edit anything"
1614
1893
  }
1615
1894
  ),
1895
+ duplicate && /* @__PURE__ */ jsxs2(
1896
+ "div",
1897
+ {
1898
+ style: {
1899
+ display: "flex",
1900
+ flexDirection: "column",
1901
+ gap: "3px",
1902
+ padding: "9px 10px",
1903
+ borderRadius: "8px",
1904
+ border: "1px solid rgba(245,158,11,0.4)",
1905
+ backgroundColor: "rgba(245,158,11,0.08)",
1906
+ fontSize: "12px",
1907
+ lineHeight: 1.5
1908
+ },
1909
+ children: [
1910
+ /* @__PURE__ */ jsx2("span", { style: { color: "#f59e0b", fontWeight: 600 }, children: "Our team is already on this" }),
1911
+ /* @__PURE__ */ jsxs2("span", { style: { color: t2.textMuted, wordBreak: "break-word" }, children: [
1912
+ "#",
1913
+ duplicate.number,
1914
+ " ",
1915
+ duplicate.title
1916
+ ] }),
1917
+ /* @__PURE__ */ jsx2("span", { style: { color: t2.textMuted }, children: "Your details will be added to it instead of opening a new issue." })
1918
+ ]
1919
+ }
1920
+ ),
1616
1921
  /* @__PURE__ */ jsx2(
1617
1922
  "textarea",
1618
1923
  {
@@ -1696,7 +2001,7 @@ function AssistSheet({
1696
2001
  color: t2.textMuted,
1697
2002
  fontSize: "12px",
1698
2003
  fontFamily: "inherit",
1699
- padding: 0,
2004
+ padding: "9px 0",
1700
2005
  cursor: "pointer",
1701
2006
  textDecoration: "underline"
1702
2007
  },
@@ -1706,6 +2011,33 @@ function AssistSheet({
1706
2011
  ]
1707
2012
  }
1708
2013
  ),
2014
+ phase === "solved" && solved && /* @__PURE__ */ jsxs2("div", { style: { display: "flex", flexDirection: "column", gap: "12px" }, children: [
2015
+ /* @__PURE__ */ jsxs2("div", { style: { display: "flex", gap: "8px" }, children: [
2016
+ /* @__PURE__ */ jsx2(Avatar, { who: "assistant", theme: t2 }),
2017
+ /* @__PURE__ */ jsx2(
2018
+ "div",
2019
+ {
2020
+ style: {
2021
+ padding: "9px 12px",
2022
+ borderRadius: "12px 12px 12px 4px",
2023
+ backgroundColor: t2.bgSecondary,
2024
+ fontSize: "13px",
2025
+ lineHeight: 1.55,
2026
+ maxWidth: "88%",
2027
+ whiteSpace: "pre-wrap"
2028
+ },
2029
+ children: solved
2030
+ }
2031
+ )
2032
+ ] }),
2033
+ /* @__PURE__ */ jsx2(
2034
+ "span",
2035
+ {
2036
+ style: { fontSize: "11.5px", color: t2.textMuted, paddingLeft: "32px" },
2037
+ children: "Nothing was filed \u2014 you are all set."
2038
+ }
2039
+ )
2040
+ ] }),
1709
2041
  submitted && /* @__PURE__ */ jsxs2(
1710
2042
  "div",
1711
2043
  {
@@ -1727,7 +2059,7 @@ function AssistSheet({
1727
2059
  )
1728
2060
  }
1729
2061
  ),
1730
- !submitted && /* @__PURE__ */ jsx2(
2062
+ !submitted && phase !== "type" && /* @__PURE__ */ jsxs2(
1731
2063
  "div",
1732
2064
  {
1733
2065
  style: {
@@ -1737,93 +2069,157 @@ function AssistSheet({
1737
2069
  paddingBottom: narrow ? "max(12px, env(safe-area-inset-bottom))" : "12px",
1738
2070
  backgroundColor: t2.bg
1739
2071
  },
1740
- children: phase === "draft" ? /* @__PURE__ */ jsx2(
1741
- "button",
1742
- {
1743
- type: "button",
1744
- "data-gg-sheet-send": "",
1745
- onClick: onSend,
1746
- disabled: isSubmitting || !description.trim(),
1747
- style: {
1748
- width: "100%",
1749
- padding: "12px",
1750
- borderRadius: "10px",
1751
- border: "none",
1752
- backgroundColor: isSubmitting || !description.trim() ? t2.bgSecondary : t2.accent,
1753
- color: isSubmitting || !description.trim() ? t2.textMuted : t2.accentText,
1754
- fontSize: "14px",
1755
- fontWeight: 700,
1756
- fontFamily: "inherit",
1757
- cursor: isSubmitting || !description.trim() ? "default" : "pointer"
1758
- },
1759
- children: isSubmitting ? "Sending\u2026" : "Send Report"
1760
- }
1761
- ) : /* @__PURE__ */ jsxs2("div", { style: { display: "flex", gap: "8px", alignItems: "flex-end" }, children: [
1762
- /* @__PURE__ */ jsx2(
1763
- "textarea",
2072
+ children: [
2073
+ phase === "solved" ? /* @__PURE__ */ jsx2(
2074
+ "button",
1764
2075
  {
1765
- ref: inputRef,
1766
- value: input,
1767
- onChange: (e) => setInput(e.target.value),
1768
- onKeyDown: (e) => {
1769
- if (e.key === "Enter" && !e.shiftKey) {
1770
- e.preventDefault();
1771
- send(input);
1772
- }
2076
+ type: "button",
2077
+ "data-gg-sheet-send": "",
2078
+ onClick: () => (onFinish != null ? onFinish : onClose)(),
2079
+ style: {
2080
+ width: "100%",
2081
+ padding: "12px",
2082
+ borderRadius: "10px",
2083
+ border: "none",
2084
+ backgroundColor: t2.accent,
2085
+ color: t2.accentText,
2086
+ fontSize: "14px",
2087
+ fontWeight: 700,
2088
+ fontFamily: "inherit",
2089
+ cursor: "pointer"
1773
2090
  },
1774
- placeholder: "Type your answer\u2026",
1775
- rows: 1,
1776
- disabled: busy,
1777
- autoFocus: true,
2091
+ children: "Done"
2092
+ }
2093
+ ) : phase === "rating" ? /* @__PURE__ */ jsx2(
2094
+ "button",
2095
+ {
2096
+ type: "button",
2097
+ "data-gg-sheet-send": "",
2098
+ onClick: onSend,
2099
+ disabled: isSubmitting || rating < 1,
1778
2100
  style: {
1779
- flex: 1,
1780
- minHeight: "42px",
1781
- maxHeight: "120px",
1782
- padding: "11px 12px",
2101
+ width: "100%",
2102
+ padding: "12px",
1783
2103
  borderRadius: "10px",
1784
- border: `1px solid ${t2.inputBorder}`,
1785
- backgroundColor: t2.inputBg,
1786
- color: t2.text,
1787
- fontSize: "13px",
1788
- lineHeight: 1.4,
2104
+ border: "none",
2105
+ backgroundColor: isSubmitting || rating < 1 ? t2.bgSecondary : "#f59e0b",
2106
+ color: isSubmitting || rating < 1 ? t2.textMuted : "#1a1a1a",
2107
+ fontSize: "14px",
2108
+ fontWeight: 700,
1789
2109
  fontFamily: "inherit",
1790
- resize: "none",
1791
- outline: "none",
1792
- boxSizing: "border-box"
1793
- }
2110
+ cursor: isSubmitting || rating < 1 ? "default" : "pointer"
2111
+ },
2112
+ children: isSubmitting ? "Sending\u2026" : rating < 1 ? "Pick a star first" : "Send Rating"
1794
2113
  }
1795
- ),
1796
- /* @__PURE__ */ jsx2(
2114
+ ) : phase === "draft" ? /* @__PURE__ */ jsx2(
1797
2115
  "button",
1798
2116
  {
1799
2117
  type: "button",
1800
2118
  "data-gg-sheet-send": "",
1801
- onClick: () => send(input),
1802
- disabled: busy || !input.trim(),
1803
- "aria-label": "Send message",
2119
+ onClick: onSend,
2120
+ disabled: isSubmitting || !description.trim(),
1804
2121
  style: {
1805
- flexShrink: 0,
1806
- width: "42px",
1807
- height: "42px",
2122
+ width: "100%",
2123
+ padding: "12px",
1808
2124
  borderRadius: "10px",
1809
2125
  border: "none",
1810
- display: "inline-flex",
1811
- alignItems: "center",
1812
- justifyContent: "center",
1813
- backgroundColor: busy || !input.trim() ? t2.bgSecondary : t2.accent,
1814
- color: busy || !input.trim() ? t2.textMuted : t2.accentText,
1815
- cursor: busy || !input.trim() ? "default" : "pointer"
2126
+ backgroundColor: isSubmitting || !description.trim() ? t2.bgSecondary : t2.accent,
2127
+ color: isSubmitting || !description.trim() ? t2.textMuted : t2.accentText,
2128
+ fontSize: "14px",
2129
+ fontWeight: 700,
2130
+ fontFamily: "inherit",
2131
+ cursor: isSubmitting || !description.trim() ? "default" : "pointer"
1816
2132
  },
1817
- children: /* @__PURE__ */ jsx2("svg", { width: "17", height: "17", viewBox: "0 0 24 24", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx2(
1818
- "path",
1819
- {
1820
- d: "M3 20.5L21.5 12 3 3.5V10l12 2-12 2v6.5z",
1821
- fill: "currentColor"
2133
+ children: isSubmitting ? "Sending\u2026" : duplicate ? `Add to #${duplicate.number}` : "Send Report"
2134
+ }
2135
+ ) : /* @__PURE__ */ jsxs2("div", { style: { display: "flex", gap: "8px", alignItems: "flex-end" }, children: [
2136
+ /* @__PURE__ */ jsx2(
2137
+ "textarea",
2138
+ {
2139
+ ref: inputRef,
2140
+ value: input,
2141
+ onChange: (e) => setInput(e.target.value),
2142
+ onKeyDown: (e) => {
2143
+ if (e.key === "Enter" && !e.shiftKey) {
2144
+ e.preventDefault();
2145
+ send(input);
2146
+ }
2147
+ },
2148
+ placeholder: "Type your answer\u2026",
2149
+ rows: 1,
2150
+ disabled: busy,
2151
+ autoFocus: true,
2152
+ style: {
2153
+ flex: 1,
2154
+ minHeight: "42px",
2155
+ maxHeight: "120px",
2156
+ padding: "11px 12px",
2157
+ borderRadius: "10px",
2158
+ border: `1px solid ${t2.inputBorder}`,
2159
+ backgroundColor: t2.inputBg,
2160
+ color: t2.text,
2161
+ fontSize: "13px",
2162
+ lineHeight: 1.4,
2163
+ fontFamily: "inherit",
2164
+ resize: "none",
2165
+ outline: "none",
2166
+ boxSizing: "border-box"
1822
2167
  }
1823
- ) })
2168
+ }
2169
+ ),
2170
+ /* @__PURE__ */ jsx2(
2171
+ "button",
2172
+ {
2173
+ type: "button",
2174
+ "data-gg-sheet-send": "",
2175
+ onClick: () => send(input),
2176
+ disabled: busy || !input.trim(),
2177
+ "aria-label": "Send message",
2178
+ "data-gg-send-message": "",
2179
+ style: {
2180
+ flexShrink: 0,
2181
+ width: "42px",
2182
+ height: "42px",
2183
+ borderRadius: "10px",
2184
+ border: "none",
2185
+ display: "inline-flex",
2186
+ alignItems: "center",
2187
+ justifyContent: "center",
2188
+ backgroundColor: busy || !input.trim() ? t2.bgSecondary : t2.accent,
2189
+ color: busy || !input.trim() ? t2.textMuted : t2.accentText,
2190
+ cursor: busy || !input.trim() ? "default" : "pointer"
2191
+ },
2192
+ children: /* @__PURE__ */ jsx2("svg", { width: "17", height: "17", viewBox: "0 0 24 24", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx2(
2193
+ "path",
2194
+ {
2195
+ d: "M3 20.5L21.5 12 3 3.5V10l12 2-12 2v6.5z",
2196
+ fill: "currentColor"
2197
+ }
2198
+ ) })
2199
+ }
2200
+ )
2201
+ ] }),
2202
+ phase === "chat" && messages.length > 0 && /* @__PURE__ */ jsx2(
2203
+ "button",
2204
+ {
2205
+ type: "button",
2206
+ "data-gg-write-myself": "",
2207
+ onClick: onClose,
2208
+ style: {
2209
+ display: "block",
2210
+ margin: "8px auto 0",
2211
+ border: "none",
2212
+ background: "transparent",
2213
+ color: t2.textMuted,
2214
+ fontSize: "11.5px",
2215
+ fontFamily: "inherit",
2216
+ padding: "6px 8px",
2217
+ cursor: "pointer"
2218
+ },
2219
+ children: "Not getting it? Fill the form yourself \u2192"
1824
2220
  }
1825
2221
  )
1826
- ] })
2222
+ ]
1827
2223
  }
1828
2224
  )
1829
2225
  ]
@@ -2193,6 +2589,9 @@ function ReportDialog({
2193
2589
  const [assistOpen, setAssistOpen] = useState3(false);
2194
2590
  const [assistNotice, setAssistNotice] = useState3(null);
2195
2591
  const [assistUsed, setAssistUsed] = useState3(false);
2592
+ const [typeChosen, setTypeChosen] = useState3(false);
2593
+ const [duplicateIssueNumber, setDuplicateIssueNumber] = useState3(null);
2594
+ const [aiConversationId, setAiConversationId] = useState3(null);
2196
2595
  const [isEnhanced, setIsEnhanced] = useState3(false);
2197
2596
  const [originalDescription, setOriginalDescription] = useState3(
2198
2597
  null
@@ -2245,6 +2644,10 @@ function ReportDialog({
2245
2644
  const sarvamChunksRef = useRef3([]);
2246
2645
  const spaceTimerRef = useRef3(null);
2247
2646
  const isPushToTalkRef = useRef3(false);
2647
+ const spaceEditsRef = useRef3(0);
2648
+ const descriptionRef = useRef3("");
2649
+ const lastVoiceTextRef = useRef3(null);
2650
+ const hadWebSpeechRef = useRef3(false);
2248
2651
  useEffect3(() => {
2249
2652
  if (!isOpen) return;
2250
2653
  const HOST_LAYERS = '[role="dialog"],[role="alertdialog"],[role="menu"],[role="listbox"]';
@@ -2300,6 +2703,7 @@ function ReportDialog({
2300
2703
  e.preventDefault();
2301
2704
  setRating(Number(e.key));
2302
2705
  setReportType("RATING");
2706
+ setTypeChosen(true);
2303
2707
  setStep(2);
2304
2708
  return;
2305
2709
  }
@@ -2311,6 +2715,7 @@ function ReportDialog({
2311
2715
  if (match) {
2312
2716
  e.preventDefault();
2313
2717
  setReportType(match);
2718
+ setTypeChosen(true);
2314
2719
  setStep(2);
2315
2720
  }
2316
2721
  };
@@ -2364,10 +2769,12 @@ function ReportDialog({
2364
2769
  setAnnotatingIndex(null);
2365
2770
  if (availableTypes.length === 1) {
2366
2771
  setReportType(availableTypes[0]);
2772
+ setTypeChosen(true);
2367
2773
  setStep(2);
2368
2774
  }
2369
2775
  const shot = await captureScreenshot();
2370
2776
  if (shot) setScreenshots([shot]);
2777
+ if (assist && !assistUsed) setAssistOpen(true);
2371
2778
  setIsOpen(true);
2372
2779
  };
2373
2780
  useEffect3(() => {
@@ -2377,6 +2784,7 @@ function ReportDialog({
2377
2784
  if (detail == null ? void 0 : detail.description) setDescription(detail.description);
2378
2785
  if (detail == null ? void 0 : detail.type) {
2379
2786
  setReportType(detail.type);
2787
+ setTypeChosen(true);
2380
2788
  setStep(2);
2381
2789
  }
2382
2790
  handleOpen();
@@ -2500,6 +2908,22 @@ function ReportDialog({
2500
2908
  }, 3e3);
2501
2909
  return () => clearInterval(id);
2502
2910
  }, [isOpen, transcribeAudio2]);
2911
+ useEffect3(() => {
2912
+ descriptionRef.current = description;
2913
+ }, [description]);
2914
+ const rebaseVoiceOnUserEdits = () => {
2915
+ var _a2;
2916
+ const live = descriptionRef.current;
2917
+ const baseline = (_a2 = lastVoiceTextRef.current) != null ? _a2 : textBeforeVoiceRef.current;
2918
+ if (live === baseline) return;
2919
+ voiceBaseRef.current = live;
2920
+ textBeforeVoiceRef.current = live;
2921
+ };
2922
+ const setDescriptionFromVoice = (text) => {
2923
+ lastVoiceTextRef.current = text;
2924
+ descriptionRef.current = text;
2925
+ setDescription(text);
2926
+ };
2503
2927
  const stopVoice = () => {
2504
2928
  var _a2, _b2;
2505
2929
  usingWebSpeechRef.current = false;
@@ -2528,7 +2952,7 @@ function ReportDialog({
2528
2952
  } catch (e) {
2529
2953
  }
2530
2954
  };
2531
- const sheetUp = !!assist && assistOpen && !isRating;
2955
+ const sheetUp = !!assist && assistOpen;
2532
2956
  useEffect3(() => {
2533
2957
  const el = modalRef.current;
2534
2958
  if (!el) return;
@@ -2550,6 +2974,8 @@ function ReportDialog({
2550
2974
  setRating(0);
2551
2975
  setHoveredStar(0);
2552
2976
  setReportType("BUG");
2977
+ setTypeChosen(false);
2978
+ setDuplicateIssueNumber(null);
2553
2979
  setSeverity("medium");
2554
2980
  setValidationError(null);
2555
2981
  setVoiceError(null);
@@ -2564,6 +2990,8 @@ function ReportDialog({
2564
2990
  stopListeningAndTranscribe();
2565
2991
  return;
2566
2992
  }
2993
+ lastVoiceTextRef.current = null;
2994
+ hadWebSpeechRef.current = false;
2567
2995
  const SpeechRec = typeof window !== "undefined" ? window.SpeechRecognition || window.webkitSpeechRecognition : void 0;
2568
2996
  let stream = null;
2569
2997
  try {
@@ -2578,13 +3006,14 @@ function ReportDialog({
2578
3006
  if (stream && transcribeAudio2) {
2579
3007
  streamRef.current = stream;
2580
3008
  sarvamChunksRef.current = [];
2581
- textBeforeVoiceRef.current = description;
3009
+ textBeforeVoiceRef.current = descriptionRef.current;
2582
3010
  const rec = new MediaRecorder(stream);
2583
3011
  mediaRecorderRef.current = rec;
2584
3012
  rec.ondataavailable = (e) => {
2585
3013
  if (e.data.size > 0) sarvamChunksRef.current.push(e.data);
2586
3014
  };
2587
3015
  rec.onstop = async () => {
3016
+ var _a2;
2588
3017
  stream.getTracks().forEach((t22) => t22.stop());
2589
3018
  if (streamRef.current === stream) streamRef.current = null;
2590
3019
  mediaRecorderRef.current = null;
@@ -2596,11 +3025,18 @@ function ReportDialog({
2596
3025
  const blob = new Blob(chunks, { type: rec.mimeType || "audio/webm" });
2597
3026
  const text = await transcribeAudio2(blob);
2598
3027
  if (text.trim()) {
2599
- const sep = textBeforeVoiceRef.current.trim() ? " " : "";
2600
- setDescription(textBeforeVoiceRef.current + sep + text.trim());
2601
- setValidationError(null);
2602
- setIsEnhanced(false);
2603
- setOriginalDescription(null);
3028
+ const live = descriptionRef.current;
3029
+ const baseline = (_a2 = lastVoiceTextRef.current) != null ? _a2 : textBeforeVoiceRef.current;
3030
+ const userEdited = live !== baseline;
3031
+ if (userEdited && hadWebSpeechRef.current) {
3032
+ } else {
3033
+ const base = userEdited ? live : textBeforeVoiceRef.current;
3034
+ const sep = base.trim() ? " " : "";
3035
+ setDescriptionFromVoice(base + sep + text.trim());
3036
+ setValidationError(null);
3037
+ setIsEnhanced(false);
3038
+ setOriginalDescription(null);
3039
+ }
2604
3040
  }
2605
3041
  } catch (e) {
2606
3042
  }
@@ -2611,8 +3047,9 @@ function ReportDialog({
2611
3047
  if (SpeechRec) {
2612
3048
  setVoiceError(null);
2613
3049
  usingWebSpeechRef.current = true;
2614
- voiceBaseRef.current = description;
2615
- textBeforeVoiceRef.current = description;
3050
+ hadWebSpeechRef.current = true;
3051
+ voiceBaseRef.current = descriptionRef.current;
3052
+ textBeforeVoiceRef.current = descriptionRef.current;
2616
3053
  const recognition = new SpeechRec();
2617
3054
  recognition.lang = "en-IN";
2618
3055
  recognition.interimResults = true;
@@ -2627,12 +3064,13 @@ function ReportDialog({
2627
3064
  if (event.results[i].isFinal) finalText += text;
2628
3065
  else interimText += text;
2629
3066
  }
3067
+ rebaseVoiceOnUserEdits();
2630
3068
  if (finalText) {
2631
3069
  const sep = voiceBaseRef.current.trim() ? " " : "";
2632
3070
  voiceBaseRef.current += sep + finalText.trim();
2633
3071
  }
2634
3072
  const liveText = interimText ? voiceBaseRef.current + (voiceBaseRef.current.trim() ? " " : "") + interimText : voiceBaseRef.current;
2635
- setDescription(liveText);
3073
+ setDescriptionFromVoice(liveText);
2636
3074
  setValidationError(null);
2637
3075
  };
2638
3076
  recognition.onend = () => {
@@ -2659,37 +3097,54 @@ function ReportDialog({
2659
3097
  setIsListening(true);
2660
3098
  }
2661
3099
  };
3100
+ const cancelPushToTalkArm = () => {
3101
+ if (!spaceTimerRef.current) return;
3102
+ clearTimeout(spaceTimerRef.current);
3103
+ spaceTimerRef.current = null;
3104
+ };
3105
+ const notePushToTalkEdit = () => {
3106
+ if (!spaceTimerRef.current) return;
3107
+ spaceEditsRef.current += 1;
3108
+ if (spaceEditsRef.current > 1) cancelPushToTalkArm();
3109
+ };
2662
3110
  const handleSpaceDown = (e) => {
2663
- var _a2;
2664
- if (e.code !== "Space") return;
3111
+ if (e.code !== "Space") {
3112
+ if (!e.metaKey && !e.ctrlKey && !e.altKey) cancelPushToTalkArm();
3113
+ return;
3114
+ }
2665
3115
  if (isListening || isPushToTalkRef.current) {
2666
3116
  e.preventDefault();
2667
3117
  return;
2668
3118
  }
2669
3119
  if (e.repeat || !transcribeAudio2 || isTranscribing || spaceTimerRef.current)
2670
3120
  return;
2671
- const pos = (_a2 = e.currentTarget.selectionStart) != null ? _a2 : description.length;
3121
+ if (e.currentTarget.value !== "") return;
3122
+ spaceEditsRef.current = 0;
2672
3123
  spaceTimerRef.current = setTimeout(() => {
3124
+ var _a2;
2673
3125
  spaceTimerRef.current = null;
2674
3126
  isPushToTalkRef.current = true;
2675
- setDescription(
2676
- (prev) => prev[pos] === " " ? prev.slice(0, pos) + prev.slice(pos + 1) : prev
2677
- );
2678
- requestAnimationFrame(() => {
2679
- if (textareaRef.current) {
2680
- textareaRef.current.selectionStart = pos;
2681
- textareaRef.current.selectionEnd = pos;
2682
- }
2683
- });
3127
+ const el = textareaRef.current;
3128
+ const caret = (_a2 = el == null ? void 0 : el.selectionStart) != null ? _a2 : null;
3129
+ if (el && caret !== null && caret === el.selectionEnd && el.value[caret - 1] === " ") {
3130
+ const cut = caret - 1;
3131
+ setDescription(
3132
+ (prev) => prev[cut] === " " ? prev.slice(0, cut) + prev.slice(cut + 1) : prev
3133
+ );
3134
+ descriptionRef.current = descriptionRef.current.slice(0, cut) + descriptionRef.current.slice(cut + 1);
3135
+ requestAnimationFrame(() => {
3136
+ if (textareaRef.current) {
3137
+ textareaRef.current.selectionStart = cut;
3138
+ textareaRef.current.selectionEnd = cut;
3139
+ }
3140
+ });
3141
+ }
2684
3142
  void toggleVoice();
2685
3143
  }, 400);
2686
3144
  };
2687
3145
  const handleSpaceUp = (e) => {
2688
3146
  if (e.code !== "Space") return;
2689
- if (spaceTimerRef.current) {
2690
- clearTimeout(spaceTimerRef.current);
2691
- spaceTimerRef.current = null;
2692
- }
3147
+ cancelPushToTalkArm();
2693
3148
  if (isPushToTalkRef.current) {
2694
3149
  isPushToTalkRef.current = false;
2695
3150
  stopListeningAndTranscribe();
@@ -2734,6 +3189,12 @@ function ReportDialog({
2734
3189
  if (showSeverity && reportType === "BUG") {
2735
3190
  metadata.severity = severity;
2736
3191
  }
3192
+ if (duplicateIssueNumber) {
3193
+ metadata.duplicateIssueNumber = String(duplicateIssueNumber);
3194
+ }
3195
+ if (aiConversationId) {
3196
+ metadata.aiConversationId = aiConversationId;
3197
+ }
2737
3198
  const result = await report(
2738
3199
  // The RATING branch returned above, so anything reaching here is a real
2739
3200
  // ReportType — the widened tile union can't leak into the report API.
@@ -2746,6 +3207,8 @@ function ReportDialog({
2746
3207
  setDescription("");
2747
3208
  setScreenshots([]);
2748
3209
  setAttachments([]);
3210
+ setAiConversationId(null);
3211
+ setDuplicateIssueNumber(null);
2749
3212
  setTimeout(() => {
2750
3213
  setSubmitted(false);
2751
3214
  handleClose();
@@ -3096,6 +3559,7 @@ function ReportDialog({
3096
3559
  onClick: () => {
3097
3560
  setRating(star);
3098
3561
  setReportType("RATING");
3562
+ setTypeChosen(true);
3099
3563
  setStep(2);
3100
3564
  },
3101
3565
  style: {
@@ -3206,6 +3670,7 @@ function ReportDialog({
3206
3670
  "data-gg-type": type,
3207
3671
  onClick: () => {
3208
3672
  setReportType(type);
3673
+ setTypeChosen(true);
3209
3674
  setStep(2);
3210
3675
  },
3211
3676
  style: {
@@ -3325,6 +3790,7 @@ function ReportDialog({
3325
3790
  type: "button",
3326
3791
  onClick: () => {
3327
3792
  setAssistNotice(null);
3793
+ setTypeChosen(true);
3328
3794
  setAssistOpen(true);
3329
3795
  },
3330
3796
  style: {
@@ -3365,6 +3831,7 @@ function ReportDialog({
3365
3831
  ref: textareaRef,
3366
3832
  value: description,
3367
3833
  onChange: (e) => {
3834
+ notePushToTalkEdit();
3368
3835
  setDescription(e.target.value);
3369
3836
  if (validationError) setValidationError(null);
3370
3837
  if (isEnhanced) {
@@ -4473,6 +4940,22 @@ function ReportDialog({
4473
4940
  attachmentCount: screenshots.length + attachments.length,
4474
4941
  context: { ...assistContext != null ? assistContext : {}, reportType },
4475
4942
  reportTypeLabel: getTypeLabel(reportType),
4943
+ typePicked: typeChosen,
4944
+ currentTile: reportType,
4945
+ tiles: sendFeedback2 ? [...availableTypes, "RATING"] : availableTypes,
4946
+ onPickType: (tile) => {
4947
+ setReportType(tile);
4948
+ setTypeChosen(true);
4949
+ setStep(2);
4950
+ },
4951
+ onDuplicateChange: setDuplicateIssueNumber,
4952
+ onConversationChange: setAiConversationId,
4953
+ onFinish: handleClose,
4954
+ rating,
4955
+ onRatingChange: (value) => {
4956
+ setRating(value);
4957
+ if (validationError) setValidationError(null);
4958
+ },
4476
4959
  projectSlot: headerSlot,
4477
4960
  reporterName: (_b = reporter == null ? void 0 : reporter.name) != null ? _b : null,
4478
4961
  description,
@@ -4502,26 +4985,6 @@ function ReportDialog({
4502
4985
  )
4503
4986
  ] });
4504
4987
  }
4505
- function getTypeLabel(type) {
4506
- switch (type) {
4507
- case "RATING":
4508
- return "Rating";
4509
- case "BUG":
4510
- return "Bug Report";
4511
- case "FEATURE_REQUEST":
4512
- return "Feature Request";
4513
- case "UI_IMPROVEMENT":
4514
- return "UI Improvement";
4515
- case "PERFORMANCE":
4516
- return "Performance";
4517
- case "SECURITY":
4518
- return "Security";
4519
- case "QUESTION":
4520
- return "Question";
4521
- case "OTHER":
4522
- return "Other";
4523
- }
4524
- }
4525
4988
  function getPlaceholder(type, idx = 0, hasVoice = false) {
4526
4989
  if (type === "RATING") return "What made it good \u2014 or what let you down? (optional)";
4527
4990
  if (hasVoice && idx === 1) return "Hold Space to speak \u2014 we'll transcribe it";
@@ -5506,6 +5969,12 @@ function GlitchgrabProviderInner({
5506
5969
  return assistTurn(
5507
5970
  {
5508
5971
  ...params,
5972
+ // Same identity the report itself carries, from the same prop.
5973
+ reporter: session ? {
5974
+ key: session.userId,
5975
+ name: session.name ? String(session.name) : null,
5976
+ email: session.email ? String(session.email) : null
5977
+ } : void 0,
5509
5978
  context: {
5510
5979
  ...(_a = params.context) != null ? _a : {},
5511
5980
  url: ctx.url,
@@ -5517,7 +5986,7 @@ function GlitchgrabProviderInner({
5517
5986
  baseUrl
5518
5987
  );
5519
5988
  },
5520
- [token, baseUrl]
5989
+ [token, baseUrl, session]
5521
5990
  );
5522
5991
  const transcribe = useCallback2(
5523
5992
  async (blob) => {