glitchgrab 1.36.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.js CHANGED
@@ -1318,6 +1318,7 @@ function AssistSheet({
1318
1318
  onSeverityChange,
1319
1319
  showSeverity,
1320
1320
  onDuplicateChange,
1321
+ onConversationChange,
1321
1322
  isSubmitting,
1322
1323
  submitted,
1323
1324
  onSend,
@@ -1365,7 +1366,10 @@ function AssistSheet({
1365
1366
  onDegrade(result.degraded);
1366
1367
  return;
1367
1368
  }
1368
- if (result.conversationId) setConversationId(result.conversationId);
1369
+ if (result.conversationId) {
1370
+ setConversationId(result.conversationId);
1371
+ onConversationChange == null ? void 0 : onConversationChange(result.conversationId);
1372
+ }
1369
1373
  setDuplicate((_a = result.duplicate) != null ? _a : null);
1370
1374
  onDuplicateChange == null ? void 0 : onDuplicateChange((_c = (_b = result.duplicate) == null ? void 0 : _b.number) != null ? _c : null);
1371
1375
  if (result.solved) {
@@ -1535,20 +1539,24 @@ function AssistSheet({
1535
1539
  "button",
1536
1540
  {
1537
1541
  type: "button",
1542
+ "data-gg-write-myself": "",
1538
1543
  onClick: onClose,
1539
- "aria-label": "Close and write it myself",
1544
+ "aria-label": "Write it myself instead",
1540
1545
  style: {
1541
1546
  flexShrink: 0,
1542
- border: "none",
1547
+ border: `1px solid ${t2.inputBorder}`,
1548
+ borderRadius: "999px",
1543
1549
  background: "transparent",
1544
1550
  color: t2.textMuted,
1545
1551
  cursor: "pointer",
1546
- fontSize: narrow ? "18px" : "12px",
1552
+ fontSize: "11.5px",
1547
1553
  lineHeight: 1,
1548
1554
  fontFamily: "inherit",
1549
- padding: narrow ? "4px 6px" : "6px 4px"
1555
+ whiteSpace: "nowrap",
1556
+ // ~32px tall either way — this is the escape hatch, not a hint.
1557
+ padding: "9px 11px"
1550
1558
  },
1551
- children: narrow ? "\xD7" : "Write it myself"
1559
+ children: "Write it myself"
1552
1560
  }
1553
1561
  )
1554
1562
  ]
@@ -2106,7 +2114,7 @@ function AssistSheet({
2106
2114
  )
2107
2115
  }
2108
2116
  ),
2109
- !submitted && phase !== "type" && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
2117
+ !submitted && phase !== "type" && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
2110
2118
  "div",
2111
2119
  {
2112
2120
  style: {
@@ -2116,134 +2124,157 @@ function AssistSheet({
2116
2124
  paddingBottom: narrow ? "max(12px, env(safe-area-inset-bottom))" : "12px",
2117
2125
  backgroundColor: t2.bg
2118
2126
  },
2119
- children: phase === "solved" ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
2120
- "button",
2121
- {
2122
- type: "button",
2123
- "data-gg-sheet-send": "",
2124
- onClick: () => (onFinish != null ? onFinish : onClose)(),
2125
- style: {
2126
- width: "100%",
2127
- padding: "12px",
2128
- borderRadius: "10px",
2129
- border: "none",
2130
- backgroundColor: t2.accent,
2131
- color: t2.accentText,
2132
- fontSize: "14px",
2133
- fontWeight: 700,
2134
- fontFamily: "inherit",
2135
- cursor: "pointer"
2136
- },
2137
- children: "Done"
2138
- }
2139
- ) : phase === "rating" ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
2140
- "button",
2141
- {
2142
- type: "button",
2143
- "data-gg-sheet-send": "",
2144
- onClick: onSend,
2145
- disabled: isSubmitting || rating < 1,
2146
- style: {
2147
- width: "100%",
2148
- padding: "12px",
2149
- borderRadius: "10px",
2150
- border: "none",
2151
- backgroundColor: isSubmitting || rating < 1 ? t2.bgSecondary : "#f59e0b",
2152
- color: isSubmitting || rating < 1 ? t2.textMuted : "#1a1a1a",
2153
- fontSize: "14px",
2154
- fontWeight: 700,
2155
- fontFamily: "inherit",
2156
- cursor: isSubmitting || rating < 1 ? "default" : "pointer"
2157
- },
2158
- children: isSubmitting ? "Sending\u2026" : rating < 1 ? "Pick a star first" : "Send Rating"
2159
- }
2160
- ) : phase === "draft" ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
2161
- "button",
2162
- {
2163
- type: "button",
2164
- "data-gg-sheet-send": "",
2165
- onClick: onSend,
2166
- disabled: isSubmitting || !description.trim(),
2167
- style: {
2168
- width: "100%",
2169
- padding: "12px",
2170
- borderRadius: "10px",
2171
- border: "none",
2172
- backgroundColor: isSubmitting || !description.trim() ? t2.bgSecondary : t2.accent,
2173
- color: isSubmitting || !description.trim() ? t2.textMuted : t2.accentText,
2174
- fontSize: "14px",
2175
- fontWeight: 700,
2176
- fontFamily: "inherit",
2177
- cursor: isSubmitting || !description.trim() ? "default" : "pointer"
2178
- },
2179
- children: isSubmitting ? "Sending\u2026" : duplicate ? `Add to #${duplicate.number}` : "Send Report"
2180
- }
2181
- ) : /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { display: "flex", gap: "8px", alignItems: "flex-end" }, children: [
2182
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
2183
- "textarea",
2127
+ children: [
2128
+ phase === "solved" ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
2129
+ "button",
2184
2130
  {
2185
- ref: inputRef,
2186
- value: input,
2187
- onChange: (e) => setInput(e.target.value),
2188
- onKeyDown: (e) => {
2189
- if (e.key === "Enter" && !e.shiftKey) {
2190
- e.preventDefault();
2191
- send(input);
2192
- }
2131
+ type: "button",
2132
+ "data-gg-sheet-send": "",
2133
+ onClick: () => (onFinish != null ? onFinish : onClose)(),
2134
+ style: {
2135
+ width: "100%",
2136
+ padding: "12px",
2137
+ borderRadius: "10px",
2138
+ border: "none",
2139
+ backgroundColor: t2.accent,
2140
+ color: t2.accentText,
2141
+ fontSize: "14px",
2142
+ fontWeight: 700,
2143
+ fontFamily: "inherit",
2144
+ cursor: "pointer"
2193
2145
  },
2194
- placeholder: "Type your answer\u2026",
2195
- rows: 1,
2196
- disabled: busy,
2197
- autoFocus: true,
2146
+ children: "Done"
2147
+ }
2148
+ ) : phase === "rating" ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
2149
+ "button",
2150
+ {
2151
+ type: "button",
2152
+ "data-gg-sheet-send": "",
2153
+ onClick: onSend,
2154
+ disabled: isSubmitting || rating < 1,
2198
2155
  style: {
2199
- flex: 1,
2200
- minHeight: "42px",
2201
- maxHeight: "120px",
2202
- padding: "11px 12px",
2156
+ width: "100%",
2157
+ padding: "12px",
2203
2158
  borderRadius: "10px",
2204
- border: `1px solid ${t2.inputBorder}`,
2205
- backgroundColor: t2.inputBg,
2206
- color: t2.text,
2207
- fontSize: "13px",
2208
- lineHeight: 1.4,
2159
+ border: "none",
2160
+ backgroundColor: isSubmitting || rating < 1 ? t2.bgSecondary : "#f59e0b",
2161
+ color: isSubmitting || rating < 1 ? t2.textMuted : "#1a1a1a",
2162
+ fontSize: "14px",
2163
+ fontWeight: 700,
2209
2164
  fontFamily: "inherit",
2210
- resize: "none",
2211
- outline: "none",
2212
- boxSizing: "border-box"
2213
- }
2165
+ cursor: isSubmitting || rating < 1 ? "default" : "pointer"
2166
+ },
2167
+ children: isSubmitting ? "Sending\u2026" : rating < 1 ? "Pick a star first" : "Send Rating"
2214
2168
  }
2215
- ),
2216
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
2169
+ ) : phase === "draft" ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
2217
2170
  "button",
2218
2171
  {
2219
2172
  type: "button",
2220
2173
  "data-gg-sheet-send": "",
2221
- onClick: () => send(input),
2222
- disabled: busy || !input.trim(),
2223
- "aria-label": "Send message",
2174
+ onClick: onSend,
2175
+ disabled: isSubmitting || !description.trim(),
2224
2176
  style: {
2225
- flexShrink: 0,
2226
- width: "42px",
2227
- height: "42px",
2177
+ width: "100%",
2178
+ padding: "12px",
2228
2179
  borderRadius: "10px",
2229
2180
  border: "none",
2230
- display: "inline-flex",
2231
- alignItems: "center",
2232
- justifyContent: "center",
2233
- backgroundColor: busy || !input.trim() ? t2.bgSecondary : t2.accent,
2234
- color: busy || !input.trim() ? t2.textMuted : t2.accentText,
2235
- cursor: busy || !input.trim() ? "default" : "pointer"
2181
+ backgroundColor: isSubmitting || !description.trim() ? t2.bgSecondary : t2.accent,
2182
+ color: isSubmitting || !description.trim() ? t2.textMuted : t2.accentText,
2183
+ fontSize: "14px",
2184
+ fontWeight: 700,
2185
+ fontFamily: "inherit",
2186
+ cursor: isSubmitting || !description.trim() ? "default" : "pointer"
2236
2187
  },
2237
- children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { width: "17", height: "17", viewBox: "0 0 24 24", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
2238
- "path",
2239
- {
2240
- d: "M3 20.5L21.5 12 3 3.5V10l12 2-12 2v6.5z",
2241
- fill: "currentColor"
2188
+ children: isSubmitting ? "Sending\u2026" : duplicate ? `Add to #${duplicate.number}` : "Send Report"
2189
+ }
2190
+ ) : /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { display: "flex", gap: "8px", alignItems: "flex-end" }, children: [
2191
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
2192
+ "textarea",
2193
+ {
2194
+ ref: inputRef,
2195
+ value: input,
2196
+ onChange: (e) => setInput(e.target.value),
2197
+ onKeyDown: (e) => {
2198
+ if (e.key === "Enter" && !e.shiftKey) {
2199
+ e.preventDefault();
2200
+ send(input);
2201
+ }
2202
+ },
2203
+ placeholder: "Type your answer\u2026",
2204
+ rows: 1,
2205
+ disabled: busy,
2206
+ autoFocus: true,
2207
+ style: {
2208
+ flex: 1,
2209
+ minHeight: "42px",
2210
+ maxHeight: "120px",
2211
+ padding: "11px 12px",
2212
+ borderRadius: "10px",
2213
+ border: `1px solid ${t2.inputBorder}`,
2214
+ backgroundColor: t2.inputBg,
2215
+ color: t2.text,
2216
+ fontSize: "13px",
2217
+ lineHeight: 1.4,
2218
+ fontFamily: "inherit",
2219
+ resize: "none",
2220
+ outline: "none",
2221
+ boxSizing: "border-box"
2242
2222
  }
2243
- ) })
2223
+ }
2224
+ ),
2225
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
2226
+ "button",
2227
+ {
2228
+ type: "button",
2229
+ "data-gg-sheet-send": "",
2230
+ onClick: () => send(input),
2231
+ disabled: busy || !input.trim(),
2232
+ "aria-label": "Send message",
2233
+ "data-gg-send-message": "",
2234
+ style: {
2235
+ flexShrink: 0,
2236
+ width: "42px",
2237
+ height: "42px",
2238
+ borderRadius: "10px",
2239
+ border: "none",
2240
+ display: "inline-flex",
2241
+ alignItems: "center",
2242
+ justifyContent: "center",
2243
+ backgroundColor: busy || !input.trim() ? t2.bgSecondary : t2.accent,
2244
+ color: busy || !input.trim() ? t2.textMuted : t2.accentText,
2245
+ cursor: busy || !input.trim() ? "default" : "pointer"
2246
+ },
2247
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { width: "17", height: "17", viewBox: "0 0 24 24", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
2248
+ "path",
2249
+ {
2250
+ d: "M3 20.5L21.5 12 3 3.5V10l12 2-12 2v6.5z",
2251
+ fill: "currentColor"
2252
+ }
2253
+ ) })
2254
+ }
2255
+ )
2256
+ ] }),
2257
+ phase === "chat" && messages.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
2258
+ "button",
2259
+ {
2260
+ type: "button",
2261
+ "data-gg-write-myself": "",
2262
+ onClick: onClose,
2263
+ style: {
2264
+ display: "block",
2265
+ margin: "8px auto 0",
2266
+ border: "none",
2267
+ background: "transparent",
2268
+ color: t2.textMuted,
2269
+ fontSize: "11.5px",
2270
+ fontFamily: "inherit",
2271
+ padding: "6px 8px",
2272
+ cursor: "pointer"
2273
+ },
2274
+ children: "Not getting it? Fill the form yourself \u2192"
2244
2275
  }
2245
2276
  )
2246
- ] })
2277
+ ]
2247
2278
  }
2248
2279
  )
2249
2280
  ]
@@ -2615,6 +2646,7 @@ function ReportDialog({
2615
2646
  const [assistUsed, setAssistUsed] = (0, import_react.useState)(false);
2616
2647
  const [typeChosen, setTypeChosen] = (0, import_react.useState)(false);
2617
2648
  const [duplicateIssueNumber, setDuplicateIssueNumber] = (0, import_react.useState)(null);
2649
+ const [aiConversationId, setAiConversationId] = (0, import_react.useState)(null);
2618
2650
  const [isEnhanced, setIsEnhanced] = (0, import_react.useState)(false);
2619
2651
  const [originalDescription, setOriginalDescription] = (0, import_react.useState)(
2620
2652
  null
@@ -2667,6 +2699,10 @@ function ReportDialog({
2667
2699
  const sarvamChunksRef = (0, import_react.useRef)([]);
2668
2700
  const spaceTimerRef = (0, import_react.useRef)(null);
2669
2701
  const isPushToTalkRef = (0, import_react.useRef)(false);
2702
+ const spaceEditsRef = (0, import_react.useRef)(0);
2703
+ const descriptionRef = (0, import_react.useRef)("");
2704
+ const lastVoiceTextRef = (0, import_react.useRef)(null);
2705
+ const hadWebSpeechRef = (0, import_react.useRef)(false);
2670
2706
  (0, import_react.useEffect)(() => {
2671
2707
  if (!isOpen) return;
2672
2708
  const HOST_LAYERS = '[role="dialog"],[role="alertdialog"],[role="menu"],[role="listbox"]';
@@ -2927,6 +2963,22 @@ function ReportDialog({
2927
2963
  }, 3e3);
2928
2964
  return () => clearInterval(id);
2929
2965
  }, [isOpen, transcribeAudio2]);
2966
+ (0, import_react.useEffect)(() => {
2967
+ descriptionRef.current = description;
2968
+ }, [description]);
2969
+ const rebaseVoiceOnUserEdits = () => {
2970
+ var _a2;
2971
+ const live = descriptionRef.current;
2972
+ const baseline = (_a2 = lastVoiceTextRef.current) != null ? _a2 : textBeforeVoiceRef.current;
2973
+ if (live === baseline) return;
2974
+ voiceBaseRef.current = live;
2975
+ textBeforeVoiceRef.current = live;
2976
+ };
2977
+ const setDescriptionFromVoice = (text) => {
2978
+ lastVoiceTextRef.current = text;
2979
+ descriptionRef.current = text;
2980
+ setDescription(text);
2981
+ };
2930
2982
  const stopVoice = () => {
2931
2983
  var _a2, _b2;
2932
2984
  usingWebSpeechRef.current = false;
@@ -2993,6 +3045,8 @@ function ReportDialog({
2993
3045
  stopListeningAndTranscribe();
2994
3046
  return;
2995
3047
  }
3048
+ lastVoiceTextRef.current = null;
3049
+ hadWebSpeechRef.current = false;
2996
3050
  const SpeechRec = typeof window !== "undefined" ? window.SpeechRecognition || window.webkitSpeechRecognition : void 0;
2997
3051
  let stream = null;
2998
3052
  try {
@@ -3007,13 +3061,14 @@ function ReportDialog({
3007
3061
  if (stream && transcribeAudio2) {
3008
3062
  streamRef.current = stream;
3009
3063
  sarvamChunksRef.current = [];
3010
- textBeforeVoiceRef.current = description;
3064
+ textBeforeVoiceRef.current = descriptionRef.current;
3011
3065
  const rec = new MediaRecorder(stream);
3012
3066
  mediaRecorderRef.current = rec;
3013
3067
  rec.ondataavailable = (e) => {
3014
3068
  if (e.data.size > 0) sarvamChunksRef.current.push(e.data);
3015
3069
  };
3016
3070
  rec.onstop = async () => {
3071
+ var _a2;
3017
3072
  stream.getTracks().forEach((t22) => t22.stop());
3018
3073
  if (streamRef.current === stream) streamRef.current = null;
3019
3074
  mediaRecorderRef.current = null;
@@ -3025,11 +3080,18 @@ function ReportDialog({
3025
3080
  const blob = new Blob(chunks, { type: rec.mimeType || "audio/webm" });
3026
3081
  const text = await transcribeAudio2(blob);
3027
3082
  if (text.trim()) {
3028
- const sep = textBeforeVoiceRef.current.trim() ? " " : "";
3029
- setDescription(textBeforeVoiceRef.current + sep + text.trim());
3030
- setValidationError(null);
3031
- setIsEnhanced(false);
3032
- setOriginalDescription(null);
3083
+ const live = descriptionRef.current;
3084
+ const baseline = (_a2 = lastVoiceTextRef.current) != null ? _a2 : textBeforeVoiceRef.current;
3085
+ const userEdited = live !== baseline;
3086
+ if (userEdited && hadWebSpeechRef.current) {
3087
+ } else {
3088
+ const base = userEdited ? live : textBeforeVoiceRef.current;
3089
+ const sep = base.trim() ? " " : "";
3090
+ setDescriptionFromVoice(base + sep + text.trim());
3091
+ setValidationError(null);
3092
+ setIsEnhanced(false);
3093
+ setOriginalDescription(null);
3094
+ }
3033
3095
  }
3034
3096
  } catch (e) {
3035
3097
  }
@@ -3040,8 +3102,9 @@ function ReportDialog({
3040
3102
  if (SpeechRec) {
3041
3103
  setVoiceError(null);
3042
3104
  usingWebSpeechRef.current = true;
3043
- voiceBaseRef.current = description;
3044
- textBeforeVoiceRef.current = description;
3105
+ hadWebSpeechRef.current = true;
3106
+ voiceBaseRef.current = descriptionRef.current;
3107
+ textBeforeVoiceRef.current = descriptionRef.current;
3045
3108
  const recognition = new SpeechRec();
3046
3109
  recognition.lang = "en-IN";
3047
3110
  recognition.interimResults = true;
@@ -3056,12 +3119,13 @@ function ReportDialog({
3056
3119
  if (event.results[i].isFinal) finalText += text;
3057
3120
  else interimText += text;
3058
3121
  }
3122
+ rebaseVoiceOnUserEdits();
3059
3123
  if (finalText) {
3060
3124
  const sep = voiceBaseRef.current.trim() ? " " : "";
3061
3125
  voiceBaseRef.current += sep + finalText.trim();
3062
3126
  }
3063
3127
  const liveText = interimText ? voiceBaseRef.current + (voiceBaseRef.current.trim() ? " " : "") + interimText : voiceBaseRef.current;
3064
- setDescription(liveText);
3128
+ setDescriptionFromVoice(liveText);
3065
3129
  setValidationError(null);
3066
3130
  };
3067
3131
  recognition.onend = () => {
@@ -3088,37 +3152,54 @@ function ReportDialog({
3088
3152
  setIsListening(true);
3089
3153
  }
3090
3154
  };
3155
+ const cancelPushToTalkArm = () => {
3156
+ if (!spaceTimerRef.current) return;
3157
+ clearTimeout(spaceTimerRef.current);
3158
+ spaceTimerRef.current = null;
3159
+ };
3160
+ const notePushToTalkEdit = () => {
3161
+ if (!spaceTimerRef.current) return;
3162
+ spaceEditsRef.current += 1;
3163
+ if (spaceEditsRef.current > 1) cancelPushToTalkArm();
3164
+ };
3091
3165
  const handleSpaceDown = (e) => {
3092
- var _a2;
3093
- if (e.code !== "Space") return;
3166
+ if (e.code !== "Space") {
3167
+ if (!e.metaKey && !e.ctrlKey && !e.altKey) cancelPushToTalkArm();
3168
+ return;
3169
+ }
3094
3170
  if (isListening || isPushToTalkRef.current) {
3095
3171
  e.preventDefault();
3096
3172
  return;
3097
3173
  }
3098
3174
  if (e.repeat || !transcribeAudio2 || isTranscribing || spaceTimerRef.current)
3099
3175
  return;
3100
- const pos = (_a2 = e.currentTarget.selectionStart) != null ? _a2 : description.length;
3176
+ if (e.currentTarget.value !== "") return;
3177
+ spaceEditsRef.current = 0;
3101
3178
  spaceTimerRef.current = setTimeout(() => {
3179
+ var _a2;
3102
3180
  spaceTimerRef.current = null;
3103
3181
  isPushToTalkRef.current = true;
3104
- setDescription(
3105
- (prev) => prev[pos] === " " ? prev.slice(0, pos) + prev.slice(pos + 1) : prev
3106
- );
3107
- requestAnimationFrame(() => {
3108
- if (textareaRef.current) {
3109
- textareaRef.current.selectionStart = pos;
3110
- textareaRef.current.selectionEnd = pos;
3111
- }
3112
- });
3182
+ const el = textareaRef.current;
3183
+ const caret = (_a2 = el == null ? void 0 : el.selectionStart) != null ? _a2 : null;
3184
+ if (el && caret !== null && caret === el.selectionEnd && el.value[caret - 1] === " ") {
3185
+ const cut = caret - 1;
3186
+ setDescription(
3187
+ (prev) => prev[cut] === " " ? prev.slice(0, cut) + prev.slice(cut + 1) : prev
3188
+ );
3189
+ descriptionRef.current = descriptionRef.current.slice(0, cut) + descriptionRef.current.slice(cut + 1);
3190
+ requestAnimationFrame(() => {
3191
+ if (textareaRef.current) {
3192
+ textareaRef.current.selectionStart = cut;
3193
+ textareaRef.current.selectionEnd = cut;
3194
+ }
3195
+ });
3196
+ }
3113
3197
  void toggleVoice();
3114
3198
  }, 400);
3115
3199
  };
3116
3200
  const handleSpaceUp = (e) => {
3117
3201
  if (e.code !== "Space") return;
3118
- if (spaceTimerRef.current) {
3119
- clearTimeout(spaceTimerRef.current);
3120
- spaceTimerRef.current = null;
3121
- }
3202
+ cancelPushToTalkArm();
3122
3203
  if (isPushToTalkRef.current) {
3123
3204
  isPushToTalkRef.current = false;
3124
3205
  stopListeningAndTranscribe();
@@ -3166,6 +3247,9 @@ function ReportDialog({
3166
3247
  if (duplicateIssueNumber) {
3167
3248
  metadata.duplicateIssueNumber = String(duplicateIssueNumber);
3168
3249
  }
3250
+ if (aiConversationId) {
3251
+ metadata.aiConversationId = aiConversationId;
3252
+ }
3169
3253
  const result = await report(
3170
3254
  // The RATING branch returned above, so anything reaching here is a real
3171
3255
  // ReportType — the widened tile union can't leak into the report API.
@@ -3178,6 +3262,8 @@ function ReportDialog({
3178
3262
  setDescription("");
3179
3263
  setScreenshots([]);
3180
3264
  setAttachments([]);
3265
+ setAiConversationId(null);
3266
+ setDuplicateIssueNumber(null);
3181
3267
  setTimeout(() => {
3182
3268
  setSubmitted(false);
3183
3269
  handleClose();
@@ -3800,6 +3886,7 @@ function ReportDialog({
3800
3886
  ref: textareaRef,
3801
3887
  value: description,
3802
3888
  onChange: (e) => {
3889
+ notePushToTalkEdit();
3803
3890
  setDescription(e.target.value);
3804
3891
  if (validationError) setValidationError(null);
3805
3892
  if (isEnhanced) {
@@ -4917,6 +5004,7 @@ function ReportDialog({
4917
5004
  setStep(2);
4918
5005
  },
4919
5006
  onDuplicateChange: setDuplicateIssueNumber,
5007
+ onConversationChange: setAiConversationId,
4920
5008
  onFinish: handleClose,
4921
5009
  rating,
4922
5010
  onRatingChange: (value) => {
@@ -5936,6 +6024,12 @@ function GlitchgrabProviderInner({
5936
6024
  return assistTurn(
5937
6025
  {
5938
6026
  ...params,
6027
+ // Same identity the report itself carries, from the same prop.
6028
+ reporter: session ? {
6029
+ key: session.userId,
6030
+ name: session.name ? String(session.name) : null,
6031
+ email: session.email ? String(session.email) : null
6032
+ } : void 0,
5939
6033
  context: {
5940
6034
  ...(_a = params.context) != null ? _a : {},
5941
6035
  url: ctx.url,
@@ -5947,7 +6041,7 @@ function GlitchgrabProviderInner({
5947
6041
  baseUrl
5948
6042
  );
5949
6043
  },
5950
- [token, baseUrl]
6044
+ [token, baseUrl, session]
5951
6045
  );
5952
6046
  const transcribe = (0, import_react5.useCallback)(
5953
6047
  async (blob) => {