glitchgrab 1.58.2 → 1.59.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/README.md +40 -0
- package/dist/index.d.mts +77 -1
- package/dist/index.d.ts +77 -1
- package/dist/index.js +1630 -737
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1627 -737
- package/dist/index.mjs.map +1 -1
- package/dist/server.d.mts +11 -0
- package/dist/server.d.ts +11 -0
- package/dist/server.js +7 -2
- package/dist/server.js.map +1 -1
- package/dist/server.mjs +7 -2
- package/dist/server.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -178,7 +178,7 @@ function argsToString(args) {
|
|
|
178
178
|
function previewJson(value, max) {
|
|
179
179
|
let out = "";
|
|
180
180
|
const path = /* @__PURE__ */ new WeakSet();
|
|
181
|
-
const
|
|
181
|
+
const write2 = (input, inArray) => {
|
|
182
182
|
if (out.length > max) return;
|
|
183
183
|
let v = input;
|
|
184
184
|
if (v !== null && typeof v === "object" && typeof v.toJSON === "function") {
|
|
@@ -215,7 +215,7 @@ function previewJson(value, max) {
|
|
|
215
215
|
out += "[";
|
|
216
216
|
for (let i = 0; i < obj.length && out.length <= max; i++) {
|
|
217
217
|
if (i > 0) out += ",";
|
|
218
|
-
|
|
218
|
+
write2(obj[i], true);
|
|
219
219
|
}
|
|
220
220
|
out += "]";
|
|
221
221
|
} else {
|
|
@@ -228,13 +228,13 @@ function previewJson(value, max) {
|
|
|
228
228
|
if (child === void 0 || typeof child === "function" || typeof child === "symbol") continue;
|
|
229
229
|
out += `${first ? "" : ","}${JSON.stringify(key)}:`;
|
|
230
230
|
first = false;
|
|
231
|
-
|
|
231
|
+
write2(child, false);
|
|
232
232
|
}
|
|
233
233
|
out += "}";
|
|
234
234
|
}
|
|
235
235
|
path.delete(obj);
|
|
236
236
|
};
|
|
237
|
-
|
|
237
|
+
write2(value, false);
|
|
238
238
|
return out;
|
|
239
239
|
}
|
|
240
240
|
async function readErrorBody(response, url) {
|
|
@@ -711,12 +711,21 @@ function signedFields(identity) {
|
|
|
711
711
|
return { userId: identity.userId, signature: identity.signature };
|
|
712
712
|
}
|
|
713
713
|
async function enhanceText(text, token, baseUrl, screenshot, context, identity) {
|
|
714
|
+
try {
|
|
715
|
+
return await enhanceTextOrThrow(text, token, baseUrl, screenshot, context, identity);
|
|
716
|
+
} catch (e) {
|
|
717
|
+
return text;
|
|
718
|
+
}
|
|
719
|
+
}
|
|
720
|
+
async function enhanceTextOrThrow(text, token, baseUrl, screenshot, context, identity) {
|
|
714
721
|
var _a;
|
|
722
|
+
const trimmed = text.trim();
|
|
723
|
+
if (!trimmed) return text;
|
|
724
|
+
const unavailable = "AI enhance isn't available right now \u2014 send your report as written.";
|
|
725
|
+
let response;
|
|
715
726
|
try {
|
|
716
|
-
const trimmed = text.trim();
|
|
717
|
-
if (!trimmed) return text;
|
|
718
727
|
const url = `${baseUrl != null ? baseUrl : DEFAULT_BASE_URL}/api/v1/ai/enhance-text`;
|
|
719
|
-
|
|
728
|
+
response = await fetch(url, {
|
|
720
729
|
method: "POST",
|
|
721
730
|
headers: {
|
|
722
731
|
"Content-Type": "application/json",
|
|
@@ -729,15 +738,20 @@ async function enhanceText(text, token, baseUrl, screenshot, context, identity)
|
|
|
729
738
|
...signedFields(identity)
|
|
730
739
|
})
|
|
731
740
|
});
|
|
732
|
-
if (!response.ok) return text;
|
|
733
|
-
const envelope = await response.json();
|
|
734
|
-
if ((envelope == null ? void 0 : envelope.success) && typeof ((_a = envelope.data) == null ? void 0 : _a.text) === "string") {
|
|
735
|
-
return envelope.data.text;
|
|
736
|
-
}
|
|
737
|
-
return text;
|
|
738
741
|
} catch (e) {
|
|
739
|
-
|
|
742
|
+
throw new Error(unavailable);
|
|
743
|
+
}
|
|
744
|
+
if (response.status === 429) {
|
|
745
|
+
throw new Error("Too many AI enhance tries \u2014 wait a while, or send your report as written.");
|
|
740
746
|
}
|
|
747
|
+
const envelope = await response.json().catch(() => null);
|
|
748
|
+
if (response.ok && (envelope == null ? void 0 : envelope.success) && typeof ((_a = envelope.data) == null ? void 0 : _a.text) === "string") {
|
|
749
|
+
return envelope.data.text;
|
|
750
|
+
}
|
|
751
|
+
if (response.status === 400 && typeof (envelope == null ? void 0 : envelope.error) === "string") {
|
|
752
|
+
throw new Error(envelope.error);
|
|
753
|
+
}
|
|
754
|
+
throw new Error(unavailable);
|
|
741
755
|
}
|
|
742
756
|
async function findSimilarIssues(description, token, baseUrl, identity, files) {
|
|
743
757
|
var _a;
|
|
@@ -895,6 +909,292 @@ function clearDedupCache() {
|
|
|
895
909
|
seen.clear();
|
|
896
910
|
}
|
|
897
911
|
|
|
912
|
+
// src/hydration.ts
|
|
913
|
+
var HYDRATION_CODE_RE = /Minified React error #(418|419|422|423|425)\b/;
|
|
914
|
+
var HYDRATION_DEV_RE = /Hydration failed|hydration mismatch|Text content does not match|did not match\. Server|There was an error while hydrating|error occurred during hydration|server rendered HTML didn't match/i;
|
|
915
|
+
var BAILOUT_DIGEST = "BAILOUT_TO_CLIENT_SIDE_RENDERING";
|
|
916
|
+
var DOM_SNIPPET_MAX = 3e3;
|
|
917
|
+
var STACK_FRAMES_MAX = 40;
|
|
918
|
+
function messageOf(error) {
|
|
919
|
+
if (error && typeof error === "object" && typeof error.message === "string") {
|
|
920
|
+
return error.message;
|
|
921
|
+
}
|
|
922
|
+
return typeof error === "string" ? error : "";
|
|
923
|
+
}
|
|
924
|
+
function hydrationCode(message) {
|
|
925
|
+
if (!message) return null;
|
|
926
|
+
const m = HYDRATION_CODE_RE.exec(message);
|
|
927
|
+
if (m) return m[1];
|
|
928
|
+
return HYDRATION_DEV_RE.test(message) ? "dev" : null;
|
|
929
|
+
}
|
|
930
|
+
function isHydrationError(error) {
|
|
931
|
+
if (hydrationCode(messageOf(error))) return true;
|
|
932
|
+
const cause = error && typeof error === "object" ? error.cause : void 0;
|
|
933
|
+
return cause !== void 0 && cause !== error && hydrationCode(messageOf(cause)) !== null;
|
|
934
|
+
}
|
|
935
|
+
function isBailout(error) {
|
|
936
|
+
const e = error;
|
|
937
|
+
if (!e || typeof e !== "object") return false;
|
|
938
|
+
if (e.digest === BAILOUT_DIGEST) return true;
|
|
939
|
+
const c = e.cause;
|
|
940
|
+
return !!c && typeof c === "object" && c.digest === BAILOUT_DIGEST;
|
|
941
|
+
}
|
|
942
|
+
function componentStackNames(stack) {
|
|
943
|
+
if (!stack) return [];
|
|
944
|
+
const names = [];
|
|
945
|
+
for (const raw of stack.split("\n")) {
|
|
946
|
+
const line = raw.trim();
|
|
947
|
+
if (!line) continue;
|
|
948
|
+
let name = "";
|
|
949
|
+
if (line.startsWith("at ")) {
|
|
950
|
+
name = line.slice(3).split(" (")[0].trim();
|
|
951
|
+
} else if (line.includes("@")) {
|
|
952
|
+
name = line.slice(0, line.indexOf("@")).trim();
|
|
953
|
+
} else {
|
|
954
|
+
name = line;
|
|
955
|
+
}
|
|
956
|
+
if (name) names.push(name);
|
|
957
|
+
if (names.length >= STACK_FRAMES_MAX) break;
|
|
958
|
+
}
|
|
959
|
+
return names;
|
|
960
|
+
}
|
|
961
|
+
function componentStackKey(stack) {
|
|
962
|
+
return componentStackNames(stack).join(">");
|
|
963
|
+
}
|
|
964
|
+
var observer = null;
|
|
965
|
+
var observerStarted = false;
|
|
966
|
+
var observerStopAt = 0;
|
|
967
|
+
var OBSERVE_MS = 3e4;
|
|
968
|
+
function startObserver() {
|
|
969
|
+
if (observerStarted || typeof MutationObserver === "undefined" || typeof document === "undefined") {
|
|
970
|
+
return;
|
|
971
|
+
}
|
|
972
|
+
observerStarted = true;
|
|
973
|
+
try {
|
|
974
|
+
observer = new MutationObserver(() => {
|
|
975
|
+
if (Date.now() > observerStopAt) stopObserver();
|
|
976
|
+
});
|
|
977
|
+
observer.observe(document, { childList: true, subtree: true });
|
|
978
|
+
observerStopAt = Date.now() + OBSERVE_MS;
|
|
979
|
+
setTimeout(stopObserver, OBSERVE_MS);
|
|
980
|
+
} catch (e) {
|
|
981
|
+
observer = null;
|
|
982
|
+
}
|
|
983
|
+
}
|
|
984
|
+
function stopObserver() {
|
|
985
|
+
try {
|
|
986
|
+
observer == null ? void 0 : observer.disconnect();
|
|
987
|
+
} catch (e) {
|
|
988
|
+
}
|
|
989
|
+
observer = null;
|
|
990
|
+
}
|
|
991
|
+
function describeNode(node) {
|
|
992
|
+
if (!node) return "";
|
|
993
|
+
if (node.nodeType === 9) return "#document";
|
|
994
|
+
const el = node;
|
|
995
|
+
if (!el.tagName) return node.nodeName;
|
|
996
|
+
const id = el.id ? `#${el.id}` : "";
|
|
997
|
+
const cls = typeof el.className === "string" && el.className.trim() ? "." + el.className.trim().split(/\s+/).slice(0, 3).join(".") : "";
|
|
998
|
+
return `${el.tagName.toLowerCase()}${id}${cls}`;
|
|
999
|
+
}
|
|
1000
|
+
function pathOf(node) {
|
|
1001
|
+
const parts = [];
|
|
1002
|
+
let cur = node;
|
|
1003
|
+
while (cur && parts.length < 6) {
|
|
1004
|
+
parts.unshift(describeNode(cur));
|
|
1005
|
+
if (cur.nodeType === 9) break;
|
|
1006
|
+
cur = cur.parentNode;
|
|
1007
|
+
}
|
|
1008
|
+
return parts.join(" > ");
|
|
1009
|
+
}
|
|
1010
|
+
var NON_CONTENT_TAGS = /* @__PURE__ */ new Set(["SCRIPT", "STYLE", "LINK", "META", "NOSCRIPT", "TEMPLATE", "TITLE", "HEAD"]);
|
|
1011
|
+
function isInHead(node) {
|
|
1012
|
+
for (let cur = node; cur; cur = cur.parentNode) {
|
|
1013
|
+
if (cur.nodeName === "HEAD") return true;
|
|
1014
|
+
if (cur.nodeName === "BODY") return false;
|
|
1015
|
+
}
|
|
1016
|
+
return false;
|
|
1017
|
+
}
|
|
1018
|
+
var GSTIN_RE = /\b\d{2}[A-Z]{5}\d{4}[A-Z][A-Z0-9]Z[A-Z0-9]\b/g;
|
|
1019
|
+
var PAN_RE = /\b[A-Z]{5}\d{4}[A-Z]\b/g;
|
|
1020
|
+
function scrubHtml(html) {
|
|
1021
|
+
return redactString(
|
|
1022
|
+
html.replace(/\svalue="[^"]*"/gi, ' value="[REDACTED]"').replace(GSTIN_RE, "[REDACTED_GSTIN]").replace(PAN_RE, "[REDACTED_PAN]").replace(/\d{6,}/g, (m) => "#".repeat(Math.min(m.length, 6)))
|
|
1023
|
+
);
|
|
1024
|
+
}
|
|
1025
|
+
function takeRemovedServerHtml() {
|
|
1026
|
+
var _a, _b;
|
|
1027
|
+
if (!observer) return { html: "", where: "" };
|
|
1028
|
+
try {
|
|
1029
|
+
const records = observer.takeRecords();
|
|
1030
|
+
let html = "";
|
|
1031
|
+
let where = "";
|
|
1032
|
+
for (const rec of records) {
|
|
1033
|
+
if (rec.type !== "childList" || rec.removedNodes.length === 0) continue;
|
|
1034
|
+
if (isInHead(rec.target)) continue;
|
|
1035
|
+
if (!where) where = pathOf(rec.target);
|
|
1036
|
+
for (const node of Array.from(rec.removedNodes)) {
|
|
1037
|
+
if (node.nodeType === 1 && NON_CONTENT_TAGS.has(node.tagName)) continue;
|
|
1038
|
+
if (node.nodeType === 3 && !((_a = node.textContent) != null ? _a : "").trim()) continue;
|
|
1039
|
+
const piece = node.nodeType === 1 ? node.outerHTML : node.nodeType === 3 ? `#text "${(_b = node.textContent) != null ? _b : ""}"` : "";
|
|
1040
|
+
if (!piece) continue;
|
|
1041
|
+
html += (html ? "\n" : "") + piece;
|
|
1042
|
+
if (html.length >= DOM_SNIPPET_MAX) break;
|
|
1043
|
+
}
|
|
1044
|
+
if (html.length >= DOM_SNIPPET_MAX) break;
|
|
1045
|
+
}
|
|
1046
|
+
const scrubbed = scrubHtml(html);
|
|
1047
|
+
return {
|
|
1048
|
+
html: scrubbed.length > DOM_SNIPPET_MAX ? `${scrubbed.slice(0, DOM_SNIPPET_MAX)}\u2026[truncated]` : scrubbed,
|
|
1049
|
+
where
|
|
1050
|
+
};
|
|
1051
|
+
} catch (e) {
|
|
1052
|
+
return { html: "", where: "" };
|
|
1053
|
+
}
|
|
1054
|
+
}
|
|
1055
|
+
function detectForeignNodes(doc = document) {
|
|
1056
|
+
var _a;
|
|
1057
|
+
const found = [];
|
|
1058
|
+
try {
|
|
1059
|
+
const html = doc.documentElement;
|
|
1060
|
+
if ((html == null ? void 0 : html.classList.contains("translated-ltr")) || (html == null ? void 0 : html.classList.contains("translated-rtl"))) {
|
|
1061
|
+
found.push("Google Translate is active (html.translated-*)");
|
|
1062
|
+
}
|
|
1063
|
+
const fonts = doc.getElementsByTagName("font").length;
|
|
1064
|
+
if (fonts > 0) found.push(`<font> \xD7 ${fonts} (Google Translate or a translation extension)`);
|
|
1065
|
+
const detectors = doc.querySelectorAll("a[x-apple-data-detectors]").length;
|
|
1066
|
+
if (detectors > 0) {
|
|
1067
|
+
found.push(`<a x-apple-data-detectors> \xD7 ${detectors} (iOS format detection turned text into links)`);
|
|
1068
|
+
}
|
|
1069
|
+
if (doc.querySelector("[data-gr-ext-installed],[data-new-gr-c-s-check-loaded],grammarly-desktop-integration")) {
|
|
1070
|
+
found.push("Grammarly extension attributes");
|
|
1071
|
+
}
|
|
1072
|
+
if (doc.querySelector("[data-lt-installed]")) found.push("LanguageTool extension attributes");
|
|
1073
|
+
if ((_a = doc.body) == null ? void 0 : _a.hasAttribute("cz-shortcut-listen")) found.push("ColorZilla extension attribute on <body>");
|
|
1074
|
+
const custom = /* @__PURE__ */ new Set();
|
|
1075
|
+
for (const parent of [html, doc.body]) {
|
|
1076
|
+
if (!parent) continue;
|
|
1077
|
+
for (const child of Array.from(parent.children)) {
|
|
1078
|
+
const tag = child.tagName.toLowerCase();
|
|
1079
|
+
if (tag.includes("-")) custom.add(tag);
|
|
1080
|
+
}
|
|
1081
|
+
}
|
|
1082
|
+
if (custom.size > 0) {
|
|
1083
|
+
found.push(`custom elements at top level: ${Array.from(custom).slice(0, 5).join(", ")} (often an extension)`);
|
|
1084
|
+
}
|
|
1085
|
+
} catch (e) {
|
|
1086
|
+
}
|
|
1087
|
+
return found;
|
|
1088
|
+
}
|
|
1089
|
+
function hydrationTiming() {
|
|
1090
|
+
var _a, _b, _c, _d;
|
|
1091
|
+
try {
|
|
1092
|
+
if (typeof performance === "undefined") return "";
|
|
1093
|
+
const at2 = Math.round(performance.now());
|
|
1094
|
+
const parts = [`error at ${at2}ms after navigation start`];
|
|
1095
|
+
const nav = (_b = (_a = performance.getEntriesByType) == null ? void 0 : _a.call(performance, "navigation")) == null ? void 0 : _b[0];
|
|
1096
|
+
if (nav == null ? void 0 : nav.domContentLoadedEventEnd) {
|
|
1097
|
+
parts.push(`DOMContentLoaded ${Math.round(nav.domContentLoadedEventEnd)}ms`);
|
|
1098
|
+
}
|
|
1099
|
+
const fetches = ((_d = (_c = performance.getEntriesByType) == null ? void 0 : _c.call(performance, "resource")) != null ? _d : []).filter((e) => {
|
|
1100
|
+
const t = e.initiatorType;
|
|
1101
|
+
return t === "fetch" || t === "xmlhttprequest";
|
|
1102
|
+
}).sort((a, b) => a.responseEnd - b.responseEnd).slice(0, 8).map((e) => {
|
|
1103
|
+
let path = e.name;
|
|
1104
|
+
try {
|
|
1105
|
+
const u = new URL(e.name);
|
|
1106
|
+
path = u.origin === window.location.origin ? u.pathname : `${u.host}${u.pathname}`;
|
|
1107
|
+
} catch (e2) {
|
|
1108
|
+
}
|
|
1109
|
+
return `${path} ${Math.round(e.responseEnd)}ms`;
|
|
1110
|
+
});
|
|
1111
|
+
if (fetches.length > 0) parts.push(`fetches finished before it: ${fetches.join(", ")}`);
|
|
1112
|
+
else parts.push("no fetch had finished yet");
|
|
1113
|
+
return parts.join("; ");
|
|
1114
|
+
} catch (e) {
|
|
1115
|
+
return "";
|
|
1116
|
+
}
|
|
1117
|
+
}
|
|
1118
|
+
function hydrationMetadata(error, extra) {
|
|
1119
|
+
var _a, _b, _c;
|
|
1120
|
+
const code = (_a = hydrationCode(messageOf(error))) != null ? _a : hydrationCode(messageOf(error == null ? void 0 : error.cause));
|
|
1121
|
+
const meta = { errorKind: "hydration" };
|
|
1122
|
+
if (code) meta.hydrationCode = code;
|
|
1123
|
+
const cause = error == null ? void 0 : error.cause;
|
|
1124
|
+
if (cause && cause !== error && messageOf(cause)) {
|
|
1125
|
+
meta.hydrationCause = messageOf(cause).slice(0, 500);
|
|
1126
|
+
}
|
|
1127
|
+
if ((_b = extra == null ? void 0 : extra.removed) == null ? void 0 : _b.html) meta.hydrationServerHtml = extra.removed.html;
|
|
1128
|
+
if ((_c = extra == null ? void 0 : extra.removed) == null ? void 0 : _c.where) meta.hydrationReplacedIn = extra.removed.where;
|
|
1129
|
+
const foreign = detectForeignNodes();
|
|
1130
|
+
if (foreign.length > 0) meta.hydrationForeignNodes = foreign.join("\n");
|
|
1131
|
+
const timing = hydrationTiming();
|
|
1132
|
+
if (timing) meta.hydrationTiming = timing;
|
|
1133
|
+
return meta;
|
|
1134
|
+
}
|
|
1135
|
+
var handled = /* @__PURE__ */ new WeakSet();
|
|
1136
|
+
function isHandledHydrationError(error) {
|
|
1137
|
+
return !!error && typeof error === "object" && handled.has(error);
|
|
1138
|
+
}
|
|
1139
|
+
function markHandled(error) {
|
|
1140
|
+
if (error && typeof error === "object") {
|
|
1141
|
+
handled.add(error);
|
|
1142
|
+
const cause = error.cause;
|
|
1143
|
+
if (cause && typeof cause === "object") handled.add(cause);
|
|
1144
|
+
}
|
|
1145
|
+
}
|
|
1146
|
+
var reporter = null;
|
|
1147
|
+
var PATCHED = "__glitchgrabHydrationPatched";
|
|
1148
|
+
function findFiberRoot(container) {
|
|
1149
|
+
if (!container || typeof container !== "object") return null;
|
|
1150
|
+
try {
|
|
1151
|
+
const key = Object.keys(container).find((k) => k.startsWith("__reactContainer$"));
|
|
1152
|
+
if (!key) return null;
|
|
1153
|
+
const hostRoot = container[key];
|
|
1154
|
+
const root = hostRoot == null ? void 0 : hostRoot.stateNode;
|
|
1155
|
+
return root && typeof root === "object" ? root : null;
|
|
1156
|
+
} catch (e) {
|
|
1157
|
+
return null;
|
|
1158
|
+
}
|
|
1159
|
+
}
|
|
1160
|
+
function patchRoot(root) {
|
|
1161
|
+
if (root[PATCHED]) return true;
|
|
1162
|
+
const original = root.onRecoverableError;
|
|
1163
|
+
if (typeof original !== "function") return false;
|
|
1164
|
+
root.onRecoverableError = function glitchgrabOnRecoverableError(error, info) {
|
|
1165
|
+
var _a;
|
|
1166
|
+
try {
|
|
1167
|
+
if (reporter && isHydrationError(error) && !isBailout(error)) {
|
|
1168
|
+
const removed = takeRemovedServerHtml();
|
|
1169
|
+
markHandled(error);
|
|
1170
|
+
reporter(error, (_a = info == null ? void 0 : info.componentStack) != null ? _a : "", hydrationMetadata(error, { removed }));
|
|
1171
|
+
}
|
|
1172
|
+
} catch (e) {
|
|
1173
|
+
}
|
|
1174
|
+
return original.call(this, error, info);
|
|
1175
|
+
};
|
|
1176
|
+
root[PATCHED] = true;
|
|
1177
|
+
return true;
|
|
1178
|
+
}
|
|
1179
|
+
function patchKnownRoots() {
|
|
1180
|
+
if (typeof document === "undefined") return false;
|
|
1181
|
+
let patched = false;
|
|
1182
|
+
for (const container of [document, document.getElementById("__next"), document.getElementById("root")]) {
|
|
1183
|
+
const root = findFiberRoot(container);
|
|
1184
|
+
if (root && patchRoot(root)) patched = true;
|
|
1185
|
+
}
|
|
1186
|
+
return patched;
|
|
1187
|
+
}
|
|
1188
|
+
function installHydrationCapture(report) {
|
|
1189
|
+
try {
|
|
1190
|
+
if (typeof window === "undefined") return;
|
|
1191
|
+
reporter = report;
|
|
1192
|
+
startObserver();
|
|
1193
|
+
patchKnownRoots();
|
|
1194
|
+
} catch (e) {
|
|
1195
|
+
}
|
|
1196
|
+
}
|
|
1197
|
+
|
|
898
1198
|
// src/capture.ts
|
|
899
1199
|
var config = null;
|
|
900
1200
|
function registerCaptureConfig(next) {
|
|
@@ -914,7 +1214,7 @@ function sessionMetadata(session) {
|
|
|
914
1214
|
...(session == null ? void 0 : session.phone) ? { sessionUserPhone: String(session.phone) } : {}
|
|
915
1215
|
};
|
|
916
1216
|
}
|
|
917
|
-
function buildCapturedErrorPayload(error, options, cfg, capturedBy = "captureError") {
|
|
1217
|
+
function buildCapturedErrorPayload(error, options, cfg, capturedBy = "captureError", dedupKey) {
|
|
918
1218
|
var _a, _b, _c;
|
|
919
1219
|
const err = error instanceof Error ? error : void 0;
|
|
920
1220
|
const errorMessage = err ? err.message : String(error);
|
|
@@ -926,7 +1226,7 @@ function buildCapturedErrorPayload(error, options, cfg, capturedBy = "captureErr
|
|
|
926
1226
|
const sig = computeSignature({
|
|
927
1227
|
errorMessage,
|
|
928
1228
|
pageUrl: context.url,
|
|
929
|
-
errorStack: err == null ? void 0 : err.stack,
|
|
1229
|
+
errorStack: dedupKey ? `at ${dedupKey}` : err == null ? void 0 : err.stack,
|
|
930
1230
|
digest
|
|
931
1231
|
});
|
|
932
1232
|
if (shouldSkipDuplicate(sig)) return null;
|
|
@@ -966,6 +1266,25 @@ function captureError(error, options) {
|
|
|
966
1266
|
} catch (e) {
|
|
967
1267
|
}
|
|
968
1268
|
}
|
|
1269
|
+
function reportHydrationError(error, componentStack, metadata) {
|
|
1270
|
+
try {
|
|
1271
|
+
const cfg = config;
|
|
1272
|
+
if (!(cfg == null ? void 0 : cfg.token)) return;
|
|
1273
|
+
const payload = buildCapturedErrorPayload(
|
|
1274
|
+
error,
|
|
1275
|
+
{ componentStack: componentStack || void 0, metadata },
|
|
1276
|
+
cfg,
|
|
1277
|
+
"onRecoverableError",
|
|
1278
|
+
componentStackKey(componentStack) || void 0
|
|
1279
|
+
);
|
|
1280
|
+
if (!payload) return;
|
|
1281
|
+
void sendReport(payload, cfg.baseUrl).then((result) => {
|
|
1282
|
+
if (result && cfg.onReportSent) cfg.onReportSent(result);
|
|
1283
|
+
});
|
|
1284
|
+
if (cfg.onError && error instanceof Error) cfg.onError(error);
|
|
1285
|
+
} catch (e) {
|
|
1286
|
+
}
|
|
1287
|
+
}
|
|
969
1288
|
|
|
970
1289
|
// src/error-boundary.tsx
|
|
971
1290
|
var GlitchgrabErrorBoundary = class extends React.Component {
|
|
@@ -1892,6 +2211,79 @@ function renderBlocks(lines, theme, key) {
|
|
|
1892
2211
|
function ChatMarkdown({ text, theme }) {
|
|
1893
2212
|
return /* @__PURE__ */ jsx2("div", { style: STACK, children: renderBlocks(text.replace(/\r\n?/g, "\n").split("\n"), theme, "md") });
|
|
1894
2213
|
}
|
|
2214
|
+
var MAX_SAVED_CHATS = 20;
|
|
2215
|
+
var SAVED_CHAT_MAX_AGE_MS = 30 * 24 * 60 * 60 * 1e3;
|
|
2216
|
+
var TITLE_CHARS = 80;
|
|
2217
|
+
var PREFIX = "glitchgrab:ai-chats:";
|
|
2218
|
+
function chatHistoryKey(...parts) {
|
|
2219
|
+
const input = parts.map((p) => p != null ? p : "").join("\0");
|
|
2220
|
+
let hash = 2166136261;
|
|
2221
|
+
for (let i = 0; i < input.length; i++) {
|
|
2222
|
+
hash ^= input.charCodeAt(i);
|
|
2223
|
+
hash = Math.imul(hash, 16777619);
|
|
2224
|
+
}
|
|
2225
|
+
return (hash >>> 0).toString(36);
|
|
2226
|
+
}
|
|
2227
|
+
function chatTitle(messages) {
|
|
2228
|
+
var _a, _b;
|
|
2229
|
+
const first = (_b = (_a = messages.find((m) => m.role === "user")) == null ? void 0 : _a.content.trim()) != null ? _b : "";
|
|
2230
|
+
const line = first.replace(/\s+/g, " ");
|
|
2231
|
+
return line.length > TITLE_CHARS ? `${line.slice(0, TITLE_CHARS - 1)}\u2026` : line;
|
|
2232
|
+
}
|
|
2233
|
+
function storage() {
|
|
2234
|
+
try {
|
|
2235
|
+
return typeof window !== "undefined" && window.localStorage ? window.localStorage : null;
|
|
2236
|
+
} catch (e) {
|
|
2237
|
+
return null;
|
|
2238
|
+
}
|
|
2239
|
+
}
|
|
2240
|
+
function isSavedChat(value) {
|
|
2241
|
+
if (!value || typeof value !== "object") return false;
|
|
2242
|
+
const c = value;
|
|
2243
|
+
return typeof c.id === "string" && typeof c.title === "string" && typeof c.updatedAt === "number" && (c.status === "open" || c.status === "filed") && Array.isArray(c.messages);
|
|
2244
|
+
}
|
|
2245
|
+
function loadChats(key, now = Date.now()) {
|
|
2246
|
+
const store = storage();
|
|
2247
|
+
if (!store) return [];
|
|
2248
|
+
try {
|
|
2249
|
+
const raw = store.getItem(PREFIX + key);
|
|
2250
|
+
if (!raw) return [];
|
|
2251
|
+
const parsed = JSON.parse(raw);
|
|
2252
|
+
if (!Array.isArray(parsed)) return [];
|
|
2253
|
+
return parsed.filter(isSavedChat).filter((c) => now - c.updatedAt < SAVED_CHAT_MAX_AGE_MS).sort((a, b) => b.updatedAt - a.updatedAt).slice(0, MAX_SAVED_CHATS);
|
|
2254
|
+
} catch (e) {
|
|
2255
|
+
return [];
|
|
2256
|
+
}
|
|
2257
|
+
}
|
|
2258
|
+
function write(key, chats) {
|
|
2259
|
+
const store = storage();
|
|
2260
|
+
if (!store) return;
|
|
2261
|
+
try {
|
|
2262
|
+
if (chats.length === 0) store.removeItem(PREFIX + key);
|
|
2263
|
+
else store.setItem(PREFIX + key, JSON.stringify(chats));
|
|
2264
|
+
} catch (e) {
|
|
2265
|
+
}
|
|
2266
|
+
}
|
|
2267
|
+
function saveChat(key, chat, now = Date.now()) {
|
|
2268
|
+
const rest = loadChats(key, now).filter((c) => c.id !== chat.id);
|
|
2269
|
+
const next = [chat, ...rest].slice(0, MAX_SAVED_CHATS);
|
|
2270
|
+
write(key, next);
|
|
2271
|
+
return next;
|
|
2272
|
+
}
|
|
2273
|
+
function markChatFiled(key, conversationId, label, now = Date.now()) {
|
|
2274
|
+
const chats = loadChats(key, now);
|
|
2275
|
+
const hit = chats.find((c) => c.conversationId === conversationId);
|
|
2276
|
+
if (!hit || hit.status === "filed") return;
|
|
2277
|
+
write(
|
|
2278
|
+
key,
|
|
2279
|
+
chats.map((c) => c === hit ? { ...c, status: "filed", filedLabel: label, updatedAt: now } : c)
|
|
2280
|
+
);
|
|
2281
|
+
}
|
|
2282
|
+
function removeChat(key, id, now = Date.now()) {
|
|
2283
|
+
const next = loadChats(key, now).filter((c) => c.id !== id);
|
|
2284
|
+
write(key, next);
|
|
2285
|
+
return next;
|
|
2286
|
+
}
|
|
1895
2287
|
function pickAssistImages(all) {
|
|
1896
2288
|
const picked = [];
|
|
1897
2289
|
let total = 0;
|
|
@@ -1918,6 +2310,18 @@ function pickAssistFiles(files) {
|
|
|
1918
2310
|
}
|
|
1919
2311
|
return picked;
|
|
1920
2312
|
}
|
|
2313
|
+
function newChatId() {
|
|
2314
|
+
return `local-${Date.now().toString(36)}${Math.random().toString(36).slice(2, 6)}`;
|
|
2315
|
+
}
|
|
2316
|
+
function chatAge(at2, now = Date.now()) {
|
|
2317
|
+
const min = Math.round((now - at2) / 6e4);
|
|
2318
|
+
if (min < 1) return "just now";
|
|
2319
|
+
if (min < 60) return `${min} min ago`;
|
|
2320
|
+
const hours = Math.round(min / 60);
|
|
2321
|
+
if (hours < 24) return `${hours} h ago`;
|
|
2322
|
+
if (hours < 48) return "yesterday";
|
|
2323
|
+
return new Date(at2).toLocaleDateString(void 0, { day: "numeric", month: "short" });
|
|
2324
|
+
}
|
|
1921
2325
|
var STARTERS = [
|
|
1922
2326
|
"Something on this page is broken",
|
|
1923
2327
|
"It did the wrong thing",
|
|
@@ -2000,6 +2404,33 @@ function Avatar({
|
|
|
2000
2404
|
}
|
|
2001
2405
|
);
|
|
2002
2406
|
}
|
|
2407
|
+
var THINKING_SLOW_SECONDS = 20;
|
|
2408
|
+
function ThinkingClock({ color }) {
|
|
2409
|
+
const [seconds, setSeconds] = useState2(0);
|
|
2410
|
+
useEffect2(() => {
|
|
2411
|
+
const started = Date.now();
|
|
2412
|
+
const id = setInterval(() => setSeconds(Math.floor((Date.now() - started) / 1e3)), 1e3);
|
|
2413
|
+
return () => clearInterval(id);
|
|
2414
|
+
}, []);
|
|
2415
|
+
return (
|
|
2416
|
+
// Hidden from screen readers: the bubble already says "Thinking", and a
|
|
2417
|
+
// number changing every second would be read out every second.
|
|
2418
|
+
/* @__PURE__ */ jsxs3(
|
|
2419
|
+
"span",
|
|
2420
|
+
{
|
|
2421
|
+
"data-gg-thinking-clock": "",
|
|
2422
|
+
"aria-hidden": "true",
|
|
2423
|
+
style: { marginLeft: "6px", fontSize: "12px", color, fontVariantNumeric: "tabular-nums" },
|
|
2424
|
+
children: [
|
|
2425
|
+
"Thinking\u2026 ",
|
|
2426
|
+
seconds,
|
|
2427
|
+
"s",
|
|
2428
|
+
seconds >= THINKING_SLOW_SECONDS ? " \xB7 taking longer than usual, still working" : ""
|
|
2429
|
+
]
|
|
2430
|
+
}
|
|
2431
|
+
)
|
|
2432
|
+
);
|
|
2433
|
+
}
|
|
2003
2434
|
function AssistSheet({
|
|
2004
2435
|
assist,
|
|
2005
2436
|
theme: t,
|
|
@@ -2040,14 +2471,22 @@ function AssistSheet({
|
|
|
2040
2471
|
onDegrade,
|
|
2041
2472
|
onClose,
|
|
2042
2473
|
onFinish,
|
|
2043
|
-
onReportGlitchgrabProblem
|
|
2474
|
+
onReportGlitchgrabProblem,
|
|
2475
|
+
historyKey = null
|
|
2044
2476
|
}) {
|
|
2477
|
+
var _a;
|
|
2045
2478
|
const narrow = useIsNarrow();
|
|
2046
2479
|
const severityAsked = showSeverity && currentTile === "BUG";
|
|
2047
2480
|
const [messages, setMessages] = useState2([]);
|
|
2048
2481
|
const [input, setInput] = useState2("");
|
|
2049
2482
|
const [busy, setBusy] = useState2(false);
|
|
2050
2483
|
const [conversationId, setConversationId] = useState2(null);
|
|
2484
|
+
const chatIdRef = useRef2(newChatId());
|
|
2485
|
+
const [savedChats, setSavedChats] = useState2(
|
|
2486
|
+
() => historyKey ? loadChats(historyKey) : []
|
|
2487
|
+
);
|
|
2488
|
+
const [showChats, setShowChats] = useState2(false);
|
|
2489
|
+
const [viewingChat, setViewingChat] = useState2(null);
|
|
2051
2490
|
const [hoveredStar, setHoveredStar] = useState2(0);
|
|
2052
2491
|
const [options, setOptions] = useState2([]);
|
|
2053
2492
|
const [duplicate, setDuplicate] = useState2(null);
|
|
@@ -2099,8 +2538,8 @@ function AssistSheet({
|
|
|
2099
2538
|
if (el) el.scrollTop = el.scrollHeight;
|
|
2100
2539
|
}, [messages, busy, phase]);
|
|
2101
2540
|
useEffect2(() => {
|
|
2102
|
-
var
|
|
2103
|
-
if (phase === "draft") (
|
|
2541
|
+
var _a2;
|
|
2542
|
+
if (phase === "draft") (_a2 = draftRef.current) == null ? void 0 : _a2.focus();
|
|
2104
2543
|
}, [phase]);
|
|
2105
2544
|
useEffect2(() => {
|
|
2106
2545
|
const el = composerRef.current;
|
|
@@ -2132,7 +2571,8 @@ function AssistSheet({
|
|
|
2132
2571
|
onDegrade(message, retryable);
|
|
2133
2572
|
}
|
|
2134
2573
|
async function runTurn(history2, autoFile = false) {
|
|
2135
|
-
var
|
|
2574
|
+
var _a2, _b, _c;
|
|
2575
|
+
const turnChat = chatIdRef.current;
|
|
2136
2576
|
setBusy(true);
|
|
2137
2577
|
setAutoFileLeft(null);
|
|
2138
2578
|
let result;
|
|
@@ -2169,6 +2609,7 @@ function AssistSheet({
|
|
|
2169
2609
|
} finally {
|
|
2170
2610
|
setBusy(false);
|
|
2171
2611
|
}
|
|
2612
|
+
if (chatIdRef.current !== turnChat) return;
|
|
2172
2613
|
if (result.degraded) {
|
|
2173
2614
|
degradeKeepingEvents(events, result.degraded, result.retryable === true);
|
|
2174
2615
|
return;
|
|
@@ -2179,7 +2620,7 @@ function AssistSheet({
|
|
|
2179
2620
|
}
|
|
2180
2621
|
const attach = result.duplicate ? { ...result.duplicate, kind: "duplicate" } : result.related ? { ...result.related, kind: "related" } : null;
|
|
2181
2622
|
setDuplicate(attach);
|
|
2182
|
-
onDuplicateChange == null ? void 0 : onDuplicateChange((
|
|
2623
|
+
onDuplicateChange == null ? void 0 : onDuplicateChange((_a2 = attach == null ? void 0 : attach.number) != null ? _a2 : null, attach == null ? void 0 : attach.kind);
|
|
2183
2624
|
setGlitchgrabOffer(!!result.aboutGlitchgrab && !!onReportGlitchgrabProblem && !!result.question);
|
|
2184
2625
|
if (result.solved) {
|
|
2185
2626
|
setSolved(result.solved);
|
|
@@ -2233,9 +2674,9 @@ function AssistSheet({
|
|
|
2233
2674
|
}
|
|
2234
2675
|
}
|
|
2235
2676
|
function sendTyped(text) {
|
|
2236
|
-
var
|
|
2677
|
+
var _a2;
|
|
2237
2678
|
const lastAssistant = [...messages].reverse().find((m) => m.role === "assistant");
|
|
2238
|
-
const checkingBack = options.includes(CONFIRM_OPTION) || (lastAssistant == null ? void 0 : lastAssistant.kind) !== "report" && isCheckBackQuestion((
|
|
2679
|
+
const checkingBack = options.includes(CONFIRM_OPTION) || (lastAssistant == null ? void 0 : lastAssistant.kind) !== "report" && isCheckBackQuestion((_a2 = lastAssistant == null ? void 0 : lastAssistant.content) != null ? _a2 : "");
|
|
2239
2680
|
send(text, checkingBack && isAffirmativeReply(text));
|
|
2240
2681
|
}
|
|
2241
2682
|
function send(text, autoFile = false) {
|
|
@@ -2277,7 +2718,215 @@ function AssistSheet({
|
|
|
2277
2718
|
flushEvents();
|
|
2278
2719
|
onSend();
|
|
2279
2720
|
}
|
|
2721
|
+
useEffect2(() => {
|
|
2722
|
+
if (!historyKey || !messages.some((m) => m.role === "user")) return;
|
|
2723
|
+
const done = submitted || phase === "solved";
|
|
2724
|
+
const kept = submitted || phase === "draft" ? withCurrentDraft(messages) : messages;
|
|
2725
|
+
setSavedChats(
|
|
2726
|
+
saveChat(historyKey, {
|
|
2727
|
+
id: chatIdRef.current,
|
|
2728
|
+
conversationId,
|
|
2729
|
+
title: chatTitle(kept),
|
|
2730
|
+
tile: currentTile,
|
|
2731
|
+
messages: kept,
|
|
2732
|
+
...issueTitle ? { issueTitle } : {},
|
|
2733
|
+
status: done ? "filed" : "open",
|
|
2734
|
+
...done ? {
|
|
2735
|
+
filedLabel: submitted ? submittedText != null ? submittedText : `${reportTypeLabel} sent` : "Answered \u2014 nothing was filed"
|
|
2736
|
+
} : {},
|
|
2737
|
+
updatedAt: Date.now()
|
|
2738
|
+
})
|
|
2739
|
+
);
|
|
2740
|
+
}, [
|
|
2741
|
+
historyKey,
|
|
2742
|
+
messages,
|
|
2743
|
+
conversationId,
|
|
2744
|
+
submitted,
|
|
2745
|
+
phase === "solved",
|
|
2746
|
+
issueTitle,
|
|
2747
|
+
phase === "draft" ? description : null
|
|
2748
|
+
]);
|
|
2749
|
+
function resumeChat(chat) {
|
|
2750
|
+
var _a2;
|
|
2751
|
+
flushEvents();
|
|
2752
|
+
chatIdRef.current = chat.id;
|
|
2753
|
+
setMessages(chat.messages);
|
|
2754
|
+
setConversationId(chat.conversationId);
|
|
2755
|
+
onConversationChange == null ? void 0 : onConversationChange(chat.conversationId);
|
|
2756
|
+
setOptions([]);
|
|
2757
|
+
setDuplicate(null);
|
|
2758
|
+
onDuplicateChange == null ? void 0 : onDuplicateChange(null);
|
|
2759
|
+
setGlitchgrabOffer(false);
|
|
2760
|
+
setAutoFileLeft(null);
|
|
2761
|
+
setInput("");
|
|
2762
|
+
if (chat.tile !== currentTile && tiles.includes(chat.tile)) {
|
|
2763
|
+
onPickType(chat.tile);
|
|
2764
|
+
}
|
|
2765
|
+
const last = chat.messages[chat.messages.length - 1];
|
|
2766
|
+
if ((last == null ? void 0 : last.kind) === "report") {
|
|
2767
|
+
onDescriptionChange(last.content);
|
|
2768
|
+
onIssueTitleChange((_a2 = chat.issueTitle) != null ? _a2 : "");
|
|
2769
|
+
aiDraftRef.current = last.content;
|
|
2770
|
+
setPhase("draft");
|
|
2771
|
+
} else {
|
|
2772
|
+
setPhase("chat");
|
|
2773
|
+
}
|
|
2774
|
+
setShowChats(false);
|
|
2775
|
+
setViewingChat(null);
|
|
2776
|
+
}
|
|
2777
|
+
function startNewChat() {
|
|
2778
|
+
flushEvents();
|
|
2779
|
+
chatIdRef.current = newChatId();
|
|
2780
|
+
setMessages([]);
|
|
2781
|
+
setConversationId(null);
|
|
2782
|
+
onConversationChange == null ? void 0 : onConversationChange(null);
|
|
2783
|
+
setOptions([]);
|
|
2784
|
+
setDuplicate(null);
|
|
2785
|
+
onDuplicateChange == null ? void 0 : onDuplicateChange(null);
|
|
2786
|
+
setGlitchgrabOffer(false);
|
|
2787
|
+
setAutoFileLeft(null);
|
|
2788
|
+
setInput("");
|
|
2789
|
+
onDescriptionChange("");
|
|
2790
|
+
onIssueTitleChange("");
|
|
2791
|
+
aiDraftRef.current = null;
|
|
2792
|
+
setPhase("chat");
|
|
2793
|
+
setShowChats(false);
|
|
2794
|
+
setViewingChat(null);
|
|
2795
|
+
}
|
|
2796
|
+
function forgetChat(id) {
|
|
2797
|
+
if (!historyKey) return;
|
|
2798
|
+
setSavedChats(removeChat(historyKey, id));
|
|
2799
|
+
if (viewingChat === id) setViewingChat(null);
|
|
2800
|
+
}
|
|
2801
|
+
const otherChats = savedChats.filter((c) => c.id !== chatIdRef.current);
|
|
2802
|
+
const resumable = (_a = otherChats.find((c) => c.status === "open" && c.messages.length > 0)) != null ? _a : null;
|
|
2280
2803
|
const empty = phase === "chat" && messages.length === 0 && !busy;
|
|
2804
|
+
function renderChatList() {
|
|
2805
|
+
return /* @__PURE__ */ jsxs3("div", { "data-gg-chat-list": "", style: { display: "flex", flexDirection: "column", gap: "8px" }, children: [
|
|
2806
|
+
/* @__PURE__ */ jsxs3("div", { style: { display: "flex", alignItems: "center", justifyContent: "space-between" }, children: [
|
|
2807
|
+
/* @__PURE__ */ jsx3("span", { style: { fontSize: "13px", fontWeight: 600 }, children: "Your chats" }),
|
|
2808
|
+
messages.length > 0 && /* @__PURE__ */ jsx3(
|
|
2809
|
+
"button",
|
|
2810
|
+
{
|
|
2811
|
+
type: "button",
|
|
2812
|
+
"data-gg-new-chat": "",
|
|
2813
|
+
onClick: startNewChat,
|
|
2814
|
+
style: {
|
|
2815
|
+
border: `1px solid ${t.inputBorder}`,
|
|
2816
|
+
borderRadius: "999px",
|
|
2817
|
+
background: "transparent",
|
|
2818
|
+
color: t.text,
|
|
2819
|
+
padding: "7px 12px",
|
|
2820
|
+
fontSize: "12px",
|
|
2821
|
+
fontFamily: "inherit",
|
|
2822
|
+
cursor: "pointer"
|
|
2823
|
+
},
|
|
2824
|
+
children: "+ New chat"
|
|
2825
|
+
}
|
|
2826
|
+
)
|
|
2827
|
+
] }),
|
|
2828
|
+
/* @__PURE__ */ jsx3("span", { style: { fontSize: "11.5px", color: t.textMuted, lineHeight: 1.5 }, children: "Kept in this browser only, for 30 days." }),
|
|
2829
|
+
otherChats.length === 0 && /* @__PURE__ */ jsx3("span", { style: { fontSize: "12.5px", color: t.textMuted, padding: "12px 0" }, children: "No other chats yet." }),
|
|
2830
|
+
otherChats.map((chat) => {
|
|
2831
|
+
var _a2;
|
|
2832
|
+
const filed = chat.status === "filed";
|
|
2833
|
+
const open = viewingChat === chat.id;
|
|
2834
|
+
return /* @__PURE__ */ jsxs3(
|
|
2835
|
+
"div",
|
|
2836
|
+
{
|
|
2837
|
+
"data-gg-saved-chat": chat.status,
|
|
2838
|
+
style: {
|
|
2839
|
+
border: `1px solid ${t.border}`,
|
|
2840
|
+
borderRadius: "10px",
|
|
2841
|
+
padding: "10px 12px",
|
|
2842
|
+
display: "flex",
|
|
2843
|
+
flexDirection: "column",
|
|
2844
|
+
gap: "6px",
|
|
2845
|
+
minWidth: 0
|
|
2846
|
+
},
|
|
2847
|
+
children: [
|
|
2848
|
+
/* @__PURE__ */ jsxs3("div", { style: { display: "flex", gap: "8px", alignItems: "flex-start", minWidth: 0 }, children: [
|
|
2849
|
+
/* @__PURE__ */ jsxs3(
|
|
2850
|
+
"button",
|
|
2851
|
+
{
|
|
2852
|
+
type: "button",
|
|
2853
|
+
onClick: () => filed ? setViewingChat(open ? null : chat.id) : resumeChat(chat),
|
|
2854
|
+
style: {
|
|
2855
|
+
flex: 1,
|
|
2856
|
+
minWidth: 0,
|
|
2857
|
+
textAlign: "left",
|
|
2858
|
+
border: "none",
|
|
2859
|
+
background: "transparent",
|
|
2860
|
+
color: t.text,
|
|
2861
|
+
padding: 0,
|
|
2862
|
+
fontFamily: "inherit",
|
|
2863
|
+
cursor: "pointer",
|
|
2864
|
+
display: "flex",
|
|
2865
|
+
flexDirection: "column",
|
|
2866
|
+
gap: "4px"
|
|
2867
|
+
},
|
|
2868
|
+
children: [
|
|
2869
|
+
/* @__PURE__ */ jsx3("span", { style: { fontSize: "13px", lineHeight: 1.45, overflowWrap: "anywhere" }, children: chat.title || "Untitled chat" }),
|
|
2870
|
+
/* @__PURE__ */ jsxs3("span", { style: { fontSize: "11.5px", color: t.textMuted }, children: [
|
|
2871
|
+
filed ? (_a2 = chat.filedLabel) != null ? _a2 : "Sent" : "Not sent yet \u2014 tap to continue",
|
|
2872
|
+
" \xB7",
|
|
2873
|
+
" ",
|
|
2874
|
+
chatAge(chat.updatedAt)
|
|
2875
|
+
] })
|
|
2876
|
+
]
|
|
2877
|
+
}
|
|
2878
|
+
),
|
|
2879
|
+
/* @__PURE__ */ jsx3(
|
|
2880
|
+
"button",
|
|
2881
|
+
{
|
|
2882
|
+
type: "button",
|
|
2883
|
+
"aria-label": `Delete chat: ${chat.title}`,
|
|
2884
|
+
onClick: () => forgetChat(chat.id),
|
|
2885
|
+
style: {
|
|
2886
|
+
flexShrink: 0,
|
|
2887
|
+
border: "none",
|
|
2888
|
+
background: "transparent",
|
|
2889
|
+
color: t.textMuted,
|
|
2890
|
+
fontSize: "16px",
|
|
2891
|
+
lineHeight: 1,
|
|
2892
|
+
padding: "4px 6px",
|
|
2893
|
+
cursor: "pointer",
|
|
2894
|
+
fontFamily: "inherit"
|
|
2895
|
+
},
|
|
2896
|
+
children: "\xD7"
|
|
2897
|
+
}
|
|
2898
|
+
)
|
|
2899
|
+
] }),
|
|
2900
|
+
open && /* @__PURE__ */ jsx3(
|
|
2901
|
+
"div",
|
|
2902
|
+
{
|
|
2903
|
+
"data-gg-saved-transcript": "",
|
|
2904
|
+
style: {
|
|
2905
|
+
display: "flex",
|
|
2906
|
+
flexDirection: "column",
|
|
2907
|
+
gap: "6px",
|
|
2908
|
+
borderTop: `1px solid ${t.border}`,
|
|
2909
|
+
paddingTop: "8px",
|
|
2910
|
+
fontSize: "12.5px",
|
|
2911
|
+
lineHeight: 1.5
|
|
2912
|
+
},
|
|
2913
|
+
children: chat.messages.map((m, i) => /* @__PURE__ */ jsxs3("div", { style: { minWidth: 0, overflowWrap: "anywhere" }, children: [
|
|
2914
|
+
/* @__PURE__ */ jsxs3("span", { style: { color: t.textMuted, fontWeight: 600 }, children: [
|
|
2915
|
+
m.role === "user" ? "You" : m.kind === "report" ? "Report" : "Assistant",
|
|
2916
|
+
":",
|
|
2917
|
+
" "
|
|
2918
|
+
] }),
|
|
2919
|
+
/* @__PURE__ */ jsx3("span", { style: { whiteSpace: "pre-wrap" }, children: m.content })
|
|
2920
|
+
] }, i))
|
|
2921
|
+
}
|
|
2922
|
+
)
|
|
2923
|
+
]
|
|
2924
|
+
},
|
|
2925
|
+
chat.id
|
|
2926
|
+
);
|
|
2927
|
+
})
|
|
2928
|
+
] });
|
|
2929
|
+
}
|
|
2281
2930
|
function renderKnownIssue({ title, footer }) {
|
|
2282
2931
|
if (!duplicate) return null;
|
|
2283
2932
|
return /* @__PURE__ */ jsxs3(
|
|
@@ -2311,8 +2960,8 @@ function AssistSheet({
|
|
|
2311
2960
|
);
|
|
2312
2961
|
}
|
|
2313
2962
|
const initials2 = (reporterName != null ? reporterName : "").split(/\s+/).filter(Boolean).slice(0, 2).map((w) => {
|
|
2314
|
-
var
|
|
2315
|
-
return (_b = (
|
|
2963
|
+
var _a2, _b;
|
|
2964
|
+
return (_b = (_a2 = w[0]) == null ? void 0 : _a2.toUpperCase()) != null ? _b : "";
|
|
2316
2965
|
}).join("");
|
|
2317
2966
|
const panelStyle = narrow ? {
|
|
2318
2967
|
width: "100%",
|
|
@@ -2403,7 +3052,9 @@ function AssistSheet({
|
|
|
2403
3052
|
alignItems: "center",
|
|
2404
3053
|
gap: "7px",
|
|
2405
3054
|
fontSize: "14px",
|
|
2406
|
-
fontWeight: 600
|
|
3055
|
+
fontWeight: 600,
|
|
3056
|
+
// One line even with the Chats pill beside it (#567).
|
|
3057
|
+
whiteSpace: "nowrap"
|
|
2407
3058
|
},
|
|
2408
3059
|
children: [
|
|
2409
3060
|
/* @__PURE__ */ jsx3(Sparkle, { color: t.accent }),
|
|
@@ -2433,801 +3084,914 @@ function AssistSheet({
|
|
|
2433
3084
|
projectSlot ? /* @__PURE__ */ jsx3("span", { style: { marginLeft: "6px" }, children: projectSlot }) : null
|
|
2434
3085
|
] })
|
|
2435
3086
|
] }),
|
|
2436
|
-
/* @__PURE__ */
|
|
2437
|
-
|
|
2438
|
-
|
|
2439
|
-
|
|
2440
|
-
|
|
2441
|
-
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
|
|
2450
|
-
|
|
2451
|
-
|
|
2452
|
-
|
|
2453
|
-
|
|
2454
|
-
|
|
2455
|
-
|
|
2456
|
-
|
|
2457
|
-
|
|
2458
|
-
|
|
2459
|
-
|
|
2460
|
-
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
|
|
2467
|
-
|
|
2468
|
-
|
|
2469
|
-
|
|
2470
|
-
|
|
2471
|
-
|
|
3087
|
+
/* @__PURE__ */ jsxs3("div", { style: { display: "flex", gap: "6px", flexShrink: 0 }, children: [
|
|
3088
|
+
historyKey && (showChats || otherChats.length > 0) && /* @__PURE__ */ jsx3(
|
|
3089
|
+
"button",
|
|
3090
|
+
{
|
|
3091
|
+
type: "button",
|
|
3092
|
+
"data-gg-chats-toggle": "",
|
|
3093
|
+
disabled: busy,
|
|
3094
|
+
"aria-pressed": showChats,
|
|
3095
|
+
onClick: () => {
|
|
3096
|
+
setShowChats((v) => !v);
|
|
3097
|
+
setViewingChat(null);
|
|
3098
|
+
},
|
|
3099
|
+
style: {
|
|
3100
|
+
flexShrink: 0,
|
|
3101
|
+
border: `1px solid ${showChats ? t.accent : t.inputBorder}`,
|
|
3102
|
+
borderRadius: "999px",
|
|
3103
|
+
background: "transparent",
|
|
3104
|
+
color: showChats ? t.accent : t.textMuted,
|
|
3105
|
+
cursor: busy ? "default" : "pointer",
|
|
3106
|
+
opacity: busy ? 0.5 : 1,
|
|
3107
|
+
fontSize: "11.5px",
|
|
3108
|
+
lineHeight: 1,
|
|
3109
|
+
fontFamily: "inherit",
|
|
3110
|
+
whiteSpace: "nowrap",
|
|
3111
|
+
padding: "9px 11px"
|
|
3112
|
+
},
|
|
3113
|
+
children: showChats ? "\u2190 Chat" : `Chats \xB7 ${otherChats.length}`
|
|
3114
|
+
}
|
|
3115
|
+
),
|
|
3116
|
+
/* @__PURE__ */ jsx3(
|
|
3117
|
+
"button",
|
|
3118
|
+
{
|
|
3119
|
+
type: "button",
|
|
3120
|
+
"data-gg-write-myself": "",
|
|
3121
|
+
onClick: () => leave("write_myself", `header, ${phase}`),
|
|
3122
|
+
"aria-label": "Write it myself instead",
|
|
3123
|
+
style: {
|
|
3124
|
+
flexShrink: 0,
|
|
3125
|
+
border: `1px solid ${t.inputBorder}`,
|
|
3126
|
+
borderRadius: "999px",
|
|
3127
|
+
background: "transparent",
|
|
3128
|
+
color: t.textMuted,
|
|
3129
|
+
cursor: "pointer",
|
|
3130
|
+
fontSize: "11.5px",
|
|
3131
|
+
lineHeight: 1,
|
|
3132
|
+
fontFamily: "inherit",
|
|
3133
|
+
whiteSpace: "nowrap",
|
|
3134
|
+
// ~32px tall either way — this is the escape hatch, not a hint.
|
|
3135
|
+
padding: "9px 11px"
|
|
3136
|
+
},
|
|
3137
|
+
children: "Write it myself"
|
|
3138
|
+
}
|
|
3139
|
+
)
|
|
3140
|
+
] })
|
|
3141
|
+
]
|
|
3142
|
+
}
|
|
3143
|
+
),
|
|
3144
|
+
/* @__PURE__ */ jsxs3(
|
|
3145
|
+
"div",
|
|
3146
|
+
{
|
|
3147
|
+
ref: scrollRef,
|
|
3148
|
+
style: {
|
|
3149
|
+
flex: 1,
|
|
3150
|
+
minHeight: narrow ? "180px" : 0,
|
|
3151
|
+
overflowY: "auto",
|
|
3152
|
+
padding: "16px",
|
|
2472
3153
|
display: "flex",
|
|
2473
3154
|
flexDirection: "column"
|
|
2474
3155
|
},
|
|
2475
|
-
children:
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
|
|
2479
|
-
|
|
2480
|
-
|
|
2481
|
-
|
|
2482
|
-
|
|
2483
|
-
|
|
2484
|
-
|
|
2485
|
-
|
|
2486
|
-
|
|
2487
|
-
|
|
2488
|
-
|
|
2489
|
-
/* @__PURE__ */ jsxs3(
|
|
3156
|
+
children: [
|
|
3157
|
+
showChats && renderChatList(),
|
|
3158
|
+
/* @__PURE__ */ jsx3(
|
|
3159
|
+
"div",
|
|
3160
|
+
{
|
|
3161
|
+
style: {
|
|
3162
|
+
marginTop: "auto",
|
|
3163
|
+
display: "flex",
|
|
3164
|
+
flexDirection: "column",
|
|
3165
|
+
gap: "12px",
|
|
3166
|
+
minWidth: 0
|
|
3167
|
+
},
|
|
3168
|
+
children: /* @__PURE__ */ jsxs3("div", { style: { display: showChats ? "none" : "contents" }, children: [
|
|
3169
|
+
phase === "type" && /* @__PURE__ */ jsxs3("div", { style: { display: "flex", flexDirection: "column", gap: "12px" }, children: [
|
|
3170
|
+
/* @__PURE__ */ jsxs3("div", { style: { display: "flex", gap: "8px" }, children: [
|
|
3171
|
+
/* @__PURE__ */ jsx3(Avatar, { who: "assistant", theme: t }),
|
|
3172
|
+
/* @__PURE__ */ jsxs3(
|
|
3173
|
+
"div",
|
|
3174
|
+
{
|
|
3175
|
+
style: {
|
|
3176
|
+
padding: "9px 12px",
|
|
3177
|
+
borderRadius: "12px 12px 12px 4px",
|
|
3178
|
+
backgroundColor: t.bgSecondary,
|
|
3179
|
+
fontSize: "13px",
|
|
3180
|
+
lineHeight: 1.55,
|
|
3181
|
+
maxWidth: "88%"
|
|
3182
|
+
},
|
|
3183
|
+
children: [
|
|
3184
|
+
reporterName ? `Hi ${reporterName.split(" ")[0]} \u2014 w` : "W",
|
|
3185
|
+
"hat do you want to do? Pick one and I'll take it from there."
|
|
3186
|
+
]
|
|
3187
|
+
}
|
|
3188
|
+
)
|
|
3189
|
+
] }),
|
|
3190
|
+
/* @__PURE__ */ jsx3(
|
|
2490
3191
|
"div",
|
|
2491
3192
|
{
|
|
2492
3193
|
style: {
|
|
2493
|
-
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
lineHeight: 1.55,
|
|
2498
|
-
maxWidth: "88%"
|
|
3194
|
+
display: "flex",
|
|
3195
|
+
flexWrap: "wrap",
|
|
3196
|
+
gap: "6px",
|
|
3197
|
+
paddingLeft: "32px"
|
|
2499
3198
|
},
|
|
2500
|
-
children:
|
|
2501
|
-
|
|
2502
|
-
|
|
2503
|
-
|
|
3199
|
+
children: tiles.map((tile) => {
|
|
3200
|
+
const rate = tile === "RATING";
|
|
3201
|
+
return /* @__PURE__ */ jsx3(
|
|
3202
|
+
"button",
|
|
3203
|
+
{
|
|
3204
|
+
type: "button",
|
|
3205
|
+
"data-gg-chip": "",
|
|
3206
|
+
"data-gg-tile": tile,
|
|
3207
|
+
onClick: () => pickType(tile),
|
|
3208
|
+
style: {
|
|
3209
|
+
display: "inline-flex",
|
|
3210
|
+
alignItems: "center",
|
|
3211
|
+
gap: "5px",
|
|
3212
|
+
// The rating is the only tile that isn't a report, so
|
|
3213
|
+
// it wears the star colour the dialog's hero row uses
|
|
3214
|
+
// rather than hiding among the report types.
|
|
3215
|
+
border: `1px solid ${rate ? "rgba(245,158,11,0.5)" : t.inputBorder}`,
|
|
3216
|
+
background: rate ? "rgba(245,158,11,0.08)" : "transparent",
|
|
3217
|
+
color: rate ? "#f59e0b" : t.textMuted,
|
|
3218
|
+
borderRadius: "999px",
|
|
3219
|
+
// 8px vertical keeps the tap target at ~32px.
|
|
3220
|
+
padding: "8px 12px",
|
|
3221
|
+
fontSize: "12px",
|
|
3222
|
+
fontWeight: rate ? 600 : 400,
|
|
3223
|
+
fontFamily: "inherit",
|
|
3224
|
+
cursor: "pointer"
|
|
3225
|
+
},
|
|
3226
|
+
children: rate ? "\u2605 Rate us" : getTypeLabel(tile)
|
|
3227
|
+
},
|
|
3228
|
+
tile
|
|
3229
|
+
);
|
|
3230
|
+
})
|
|
2504
3231
|
}
|
|
2505
3232
|
)
|
|
2506
3233
|
] }),
|
|
2507
|
-
/* @__PURE__ */
|
|
2508
|
-
"div",
|
|
2509
|
-
|
|
2510
|
-
|
|
2511
|
-
|
|
2512
|
-
|
|
2513
|
-
|
|
2514
|
-
|
|
2515
|
-
|
|
2516
|
-
|
|
2517
|
-
|
|
2518
|
-
|
|
3234
|
+
phase === "severity" && /* @__PURE__ */ jsxs3("div", { style: { display: "flex", flexDirection: "column", gap: "12px" }, children: [
|
|
3235
|
+
/* @__PURE__ */ jsxs3("div", { style: { display: "flex", gap: "8px" }, children: [
|
|
3236
|
+
/* @__PURE__ */ jsx3(Avatar, { who: "assistant", theme: t }),
|
|
3237
|
+
/* @__PURE__ */ jsx3(
|
|
3238
|
+
"div",
|
|
3239
|
+
{
|
|
3240
|
+
style: {
|
|
3241
|
+
padding: "9px 12px",
|
|
3242
|
+
borderRadius: "12px 12px 12px 4px",
|
|
3243
|
+
backgroundColor: t.bgSecondary,
|
|
3244
|
+
fontSize: "13px",
|
|
3245
|
+
lineHeight: 1.55,
|
|
3246
|
+
maxWidth: "88%"
|
|
3247
|
+
},
|
|
3248
|
+
children: "How bad is it?"
|
|
3249
|
+
}
|
|
3250
|
+
)
|
|
3251
|
+
] }),
|
|
3252
|
+
/* @__PURE__ */ jsx3(
|
|
3253
|
+
"div",
|
|
3254
|
+
{
|
|
3255
|
+
role: "radiogroup",
|
|
3256
|
+
"aria-label": "Severity",
|
|
3257
|
+
style: {
|
|
3258
|
+
display: "flex",
|
|
3259
|
+
flexWrap: "wrap",
|
|
3260
|
+
gap: "6px",
|
|
3261
|
+
paddingLeft: "32px"
|
|
3262
|
+
},
|
|
3263
|
+
children: SEVERITY_LEVELS.map((s) => /* @__PURE__ */ jsx3(
|
|
2519
3264
|
"button",
|
|
2520
3265
|
{
|
|
2521
3266
|
type: "button",
|
|
3267
|
+
role: "radio",
|
|
3268
|
+
"aria-checked": severity === s,
|
|
2522
3269
|
"data-gg-chip": "",
|
|
2523
|
-
"data-gg-
|
|
2524
|
-
onClick: () =>
|
|
3270
|
+
"data-gg-severity": s,
|
|
3271
|
+
onClick: () => answerSeverity(s),
|
|
2525
3272
|
style: {
|
|
2526
|
-
|
|
2527
|
-
|
|
2528
|
-
|
|
2529
|
-
// The rating is the only tile that isn't a report, so
|
|
2530
|
-
// it wears the star colour the dialog's hero row uses
|
|
2531
|
-
// rather than hiding among the report types.
|
|
2532
|
-
border: `1px solid ${rate ? "rgba(245,158,11,0.5)" : t.inputBorder}`,
|
|
2533
|
-
background: rate ? "rgba(245,158,11,0.08)" : "transparent",
|
|
2534
|
-
color: rate ? "#f59e0b" : t.textMuted,
|
|
3273
|
+
border: `1px solid ${t.inputBorder}`,
|
|
3274
|
+
background: "transparent",
|
|
3275
|
+
color: t.textMuted,
|
|
2535
3276
|
borderRadius: "999px",
|
|
2536
|
-
//
|
|
3277
|
+
// Same as the picker and option chips — one chip size.
|
|
2537
3278
|
padding: "8px 12px",
|
|
2538
3279
|
fontSize: "12px",
|
|
2539
|
-
fontWeight: rate ? 600 : 400,
|
|
2540
3280
|
fontFamily: "inherit",
|
|
2541
3281
|
cursor: "pointer"
|
|
2542
3282
|
},
|
|
2543
|
-
children:
|
|
3283
|
+
children: SEVERITY_LABELS[s]
|
|
2544
3284
|
},
|
|
2545
|
-
|
|
2546
|
-
)
|
|
2547
|
-
})
|
|
2548
|
-
}
|
|
2549
|
-
)
|
|
2550
|
-
] }),
|
|
2551
|
-
phase === "severity" && /* @__PURE__ */ jsxs3("div", { style: { display: "flex", flexDirection: "column", gap: "12px" }, children: [
|
|
2552
|
-
/* @__PURE__ */ jsxs3("div", { style: { display: "flex", gap: "8px" }, children: [
|
|
2553
|
-
/* @__PURE__ */ jsx3(Avatar, { who: "assistant", theme: t }),
|
|
2554
|
-
/* @__PURE__ */ jsx3(
|
|
2555
|
-
"div",
|
|
2556
|
-
{
|
|
2557
|
-
style: {
|
|
2558
|
-
padding: "9px 12px",
|
|
2559
|
-
borderRadius: "12px 12px 12px 4px",
|
|
2560
|
-
backgroundColor: t.bgSecondary,
|
|
2561
|
-
fontSize: "13px",
|
|
2562
|
-
lineHeight: 1.55,
|
|
2563
|
-
maxWidth: "88%"
|
|
2564
|
-
},
|
|
2565
|
-
children: "How bad is it?"
|
|
3285
|
+
s
|
|
3286
|
+
))
|
|
2566
3287
|
}
|
|
2567
3288
|
)
|
|
2568
3289
|
] }),
|
|
2569
|
-
/* @__PURE__ */
|
|
2570
|
-
"div",
|
|
2571
|
-
|
|
2572
|
-
|
|
2573
|
-
|
|
2574
|
-
style: {
|
|
2575
|
-
display: "flex",
|
|
2576
|
-
flexWrap: "wrap",
|
|
2577
|
-
gap: "6px",
|
|
2578
|
-
paddingLeft: "32px"
|
|
2579
|
-
},
|
|
2580
|
-
children: SEVERITY_LEVELS.map((s) => /* @__PURE__ */ jsx3(
|
|
2581
|
-
"button",
|
|
3290
|
+
phase === "rating" && !submitted && /* @__PURE__ */ jsxs3("div", { style: { display: "flex", flexDirection: "column", gap: "12px" }, children: [
|
|
3291
|
+
/* @__PURE__ */ jsxs3("div", { style: { display: "flex", gap: "8px" }, children: [
|
|
3292
|
+
/* @__PURE__ */ jsx3(Avatar, { who: "assistant", theme: t }),
|
|
3293
|
+
/* @__PURE__ */ jsx3(
|
|
3294
|
+
"div",
|
|
2582
3295
|
{
|
|
2583
|
-
type: "button",
|
|
2584
|
-
role: "radio",
|
|
2585
|
-
"aria-checked": severity === s,
|
|
2586
|
-
"data-gg-chip": "",
|
|
2587
|
-
"data-gg-severity": s,
|
|
2588
|
-
onClick: () => answerSeverity(s),
|
|
2589
3296
|
style: {
|
|
2590
|
-
|
|
2591
|
-
|
|
2592
|
-
|
|
2593
|
-
|
|
2594
|
-
|
|
2595
|
-
|
|
2596
|
-
fontSize: "12px",
|
|
2597
|
-
fontFamily: "inherit",
|
|
2598
|
-
cursor: "pointer"
|
|
3297
|
+
padding: "9px 12px",
|
|
3298
|
+
borderRadius: "12px 12px 12px 4px",
|
|
3299
|
+
backgroundColor: t.bgSecondary,
|
|
3300
|
+
fontSize: "13px",
|
|
3301
|
+
lineHeight: 1.55,
|
|
3302
|
+
maxWidth: "88%"
|
|
2599
3303
|
},
|
|
2600
|
-
children:
|
|
2601
|
-
}
|
|
2602
|
-
|
|
2603
|
-
|
|
2604
|
-
|
|
2605
|
-
)
|
|
2606
|
-
] }),
|
|
2607
|
-
phase === "rating" && !submitted && /* @__PURE__ */ jsxs3("div", { style: { display: "flex", flexDirection: "column", gap: "12px" }, children: [
|
|
2608
|
-
/* @__PURE__ */ jsxs3("div", { style: { display: "flex", gap: "8px" }, children: [
|
|
2609
|
-
/* @__PURE__ */ jsx3(Avatar, { who: "assistant", theme: t }),
|
|
2610
|
-
/* @__PURE__ */ jsx3(
|
|
3304
|
+
children: "How are we doing? Tap a star \u2014 the words are optional."
|
|
3305
|
+
}
|
|
3306
|
+
)
|
|
3307
|
+
] }),
|
|
3308
|
+
/* @__PURE__ */ jsxs3(
|
|
2611
3309
|
"div",
|
|
2612
3310
|
{
|
|
2613
3311
|
style: {
|
|
2614
|
-
|
|
2615
|
-
|
|
2616
|
-
|
|
2617
|
-
|
|
2618
|
-
|
|
2619
|
-
|
|
3312
|
+
display: "flex",
|
|
3313
|
+
flexDirection: "column",
|
|
3314
|
+
gap: "10px",
|
|
3315
|
+
marginLeft: "32px",
|
|
3316
|
+
padding: "12px",
|
|
3317
|
+
borderRadius: "12px",
|
|
3318
|
+
border: "1px solid rgba(245,158,11,0.4)",
|
|
3319
|
+
backgroundColor: "rgba(245,158,11,0.06)"
|
|
2620
3320
|
},
|
|
2621
|
-
children:
|
|
2622
|
-
|
|
2623
|
-
|
|
2624
|
-
|
|
2625
|
-
|
|
2626
|
-
|
|
2627
|
-
|
|
2628
|
-
|
|
2629
|
-
|
|
2630
|
-
|
|
2631
|
-
|
|
2632
|
-
|
|
2633
|
-
|
|
2634
|
-
|
|
2635
|
-
|
|
2636
|
-
|
|
2637
|
-
|
|
2638
|
-
|
|
2639
|
-
|
|
2640
|
-
|
|
2641
|
-
|
|
3321
|
+
children: [
|
|
3322
|
+
/* @__PURE__ */ jsx3("div", { style: { display: "flex", gap: "4px" }, role: "group", "aria-label": "Rating", children: [1, 2, 3, 4, 5].map((star) => {
|
|
3323
|
+
const filled = star <= (hoveredStar || rating);
|
|
3324
|
+
return /* @__PURE__ */ jsx3(
|
|
3325
|
+
"button",
|
|
3326
|
+
{
|
|
3327
|
+
type: "button",
|
|
3328
|
+
"aria-label": `${star} star${star > 1 ? "s" : ""}`,
|
|
3329
|
+
"aria-pressed": star <= rating,
|
|
3330
|
+
onClick: () => onRatingChange(star),
|
|
3331
|
+
onMouseEnter: () => setHoveredStar(star),
|
|
3332
|
+
onMouseLeave: () => setHoveredStar(0),
|
|
3333
|
+
style: {
|
|
3334
|
+
border: "none",
|
|
3335
|
+
background: "transparent",
|
|
3336
|
+
padding: 0,
|
|
3337
|
+
cursor: "pointer",
|
|
3338
|
+
lineHeight: 0
|
|
3339
|
+
},
|
|
3340
|
+
children: /* @__PURE__ */ jsx3("svg", { width: "30", height: "30", viewBox: "0 0 24 24", "aria-hidden": "true", children: /* @__PURE__ */ jsx3(
|
|
3341
|
+
"path",
|
|
3342
|
+
{
|
|
3343
|
+
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",
|
|
3344
|
+
fill: filled ? "#f59e0b" : "transparent",
|
|
3345
|
+
stroke: filled ? "#f59e0b" : t.inputBorder,
|
|
3346
|
+
strokeWidth: "1.5",
|
|
3347
|
+
strokeLinejoin: "round"
|
|
3348
|
+
}
|
|
3349
|
+
) })
|
|
3350
|
+
},
|
|
3351
|
+
star
|
|
3352
|
+
);
|
|
3353
|
+
}) }),
|
|
3354
|
+
/* @__PURE__ */ jsx3(
|
|
3355
|
+
"textarea",
|
|
3356
|
+
{
|
|
3357
|
+
value: description,
|
|
3358
|
+
onChange: (e) => onDescriptionChange(e.target.value),
|
|
3359
|
+
rows: 3,
|
|
3360
|
+
placeholder: "What made it good \u2014 or what let you down? (optional)",
|
|
3361
|
+
style: {
|
|
3362
|
+
width: "100%",
|
|
3363
|
+
padding: "10px",
|
|
3364
|
+
borderRadius: "8px",
|
|
3365
|
+
border: `1px solid ${t.inputBorder}`,
|
|
3366
|
+
backgroundColor: t.inputBg,
|
|
3367
|
+
color: t.text,
|
|
3368
|
+
fontSize: "13px",
|
|
3369
|
+
lineHeight: 1.5,
|
|
3370
|
+
fontFamily: "inherit",
|
|
3371
|
+
resize: "vertical",
|
|
3372
|
+
outline: "none",
|
|
3373
|
+
boxSizing: "border-box"
|
|
3374
|
+
}
|
|
3375
|
+
}
|
|
3376
|
+
),
|
|
3377
|
+
/* @__PURE__ */ jsx3(
|
|
2642
3378
|
"button",
|
|
2643
3379
|
{
|
|
2644
3380
|
type: "button",
|
|
2645
|
-
|
|
2646
|
-
"aria-pressed": star <= rating,
|
|
2647
|
-
onClick: () => onRatingChange(star),
|
|
2648
|
-
onMouseEnter: () => setHoveredStar(star),
|
|
2649
|
-
onMouseLeave: () => setHoveredStar(0),
|
|
3381
|
+
onClick: () => setPhase("type"),
|
|
2650
3382
|
style: {
|
|
3383
|
+
alignSelf: "flex-start",
|
|
2651
3384
|
border: "none",
|
|
2652
3385
|
background: "transparent",
|
|
2653
|
-
|
|
3386
|
+
color: t.textMuted,
|
|
3387
|
+
fontSize: "12px",
|
|
3388
|
+
fontFamily: "inherit",
|
|
3389
|
+
// A bare text link is ~14px tall — half a thumb.
|
|
3390
|
+
padding: "9px 0",
|
|
2654
3391
|
cursor: "pointer",
|
|
2655
|
-
|
|
3392
|
+
textDecoration: "underline"
|
|
2656
3393
|
},
|
|
2657
|
-
children:
|
|
2658
|
-
"path",
|
|
2659
|
-
{
|
|
2660
|
-
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",
|
|
2661
|
-
fill: filled ? "#f59e0b" : "transparent",
|
|
2662
|
-
stroke: filled ? "#f59e0b" : t.inputBorder,
|
|
2663
|
-
strokeWidth: "1.5",
|
|
2664
|
-
strokeLinejoin: "round"
|
|
2665
|
-
}
|
|
2666
|
-
) })
|
|
2667
|
-
},
|
|
2668
|
-
star
|
|
2669
|
-
);
|
|
2670
|
-
}) }),
|
|
2671
|
-
/* @__PURE__ */ jsx3(
|
|
2672
|
-
"textarea",
|
|
2673
|
-
{
|
|
2674
|
-
value: description,
|
|
2675
|
-
onChange: (e) => onDescriptionChange(e.target.value),
|
|
2676
|
-
rows: 3,
|
|
2677
|
-
placeholder: "What made it good \u2014 or what let you down? (optional)",
|
|
2678
|
-
style: {
|
|
2679
|
-
width: "100%",
|
|
2680
|
-
padding: "10px",
|
|
2681
|
-
borderRadius: "8px",
|
|
2682
|
-
border: `1px solid ${t.inputBorder}`,
|
|
2683
|
-
backgroundColor: t.inputBg,
|
|
2684
|
-
color: t.text,
|
|
2685
|
-
fontSize: "13px",
|
|
2686
|
-
lineHeight: 1.5,
|
|
2687
|
-
fontFamily: "inherit",
|
|
2688
|
-
resize: "vertical",
|
|
2689
|
-
outline: "none",
|
|
2690
|
-
boxSizing: "border-box"
|
|
3394
|
+
children: "Report something instead"
|
|
2691
3395
|
}
|
|
2692
|
-
|
|
2693
|
-
|
|
2694
|
-
|
|
2695
|
-
|
|
2696
|
-
|
|
2697
|
-
|
|
2698
|
-
|
|
2699
|
-
style: {
|
|
2700
|
-
alignSelf: "flex-start",
|
|
2701
|
-
border: "none",
|
|
2702
|
-
background: "transparent",
|
|
2703
|
-
color: t.textMuted,
|
|
2704
|
-
fontSize: "12px",
|
|
2705
|
-
fontFamily: "inherit",
|
|
2706
|
-
// A bare text link is ~14px tall — half a thumb.
|
|
2707
|
-
padding: "9px 0",
|
|
2708
|
-
cursor: "pointer",
|
|
2709
|
-
textDecoration: "underline"
|
|
2710
|
-
},
|
|
2711
|
-
children: "Report something instead"
|
|
2712
|
-
}
|
|
2713
|
-
)
|
|
2714
|
-
]
|
|
2715
|
-
}
|
|
2716
|
-
)
|
|
2717
|
-
] }),
|
|
2718
|
-
empty && /* @__PURE__ */ jsxs3("div", { style: { display: "flex", flexDirection: "column", gap: "12px" }, children: [
|
|
2719
|
-
/* @__PURE__ */ jsxs3("div", { style: { display: "flex", gap: "8px" }, children: [
|
|
2720
|
-
/* @__PURE__ */ jsx3(Avatar, { who: "assistant", theme: t }),
|
|
2721
|
-
/* @__PURE__ */ jsxs3(
|
|
3396
|
+
)
|
|
3397
|
+
]
|
|
3398
|
+
}
|
|
3399
|
+
)
|
|
3400
|
+
] }),
|
|
3401
|
+
empty && /* @__PURE__ */ jsxs3("div", { style: { display: "flex", flexDirection: "column", gap: "12px" }, children: [
|
|
3402
|
+
resumable && /* @__PURE__ */ jsxs3(
|
|
2722
3403
|
"div",
|
|
2723
3404
|
{
|
|
3405
|
+
"data-gg-resume-chat": "",
|
|
2724
3406
|
style: {
|
|
2725
|
-
|
|
2726
|
-
|
|
3407
|
+
display: "flex",
|
|
3408
|
+
flexDirection: "column",
|
|
3409
|
+
gap: "8px",
|
|
3410
|
+
padding: "10px 12px",
|
|
3411
|
+
borderRadius: "10px",
|
|
3412
|
+
border: `1px solid ${t.accent}55`,
|
|
2727
3413
|
backgroundColor: t.bgSecondary,
|
|
2728
|
-
|
|
2729
|
-
lineHeight: 1.55,
|
|
2730
|
-
maxWidth: "88%"
|
|
3414
|
+
minWidth: 0
|
|
2731
3415
|
},
|
|
2732
3416
|
children: [
|
|
2733
|
-
|
|
2734
|
-
|
|
2735
|
-
|
|
2736
|
-
|
|
2737
|
-
|
|
2738
|
-
|
|
2739
|
-
|
|
2740
|
-
|
|
2741
|
-
|
|
2742
|
-
|
|
2743
|
-
|
|
2744
|
-
|
|
2745
|
-
|
|
2746
|
-
|
|
2747
|
-
|
|
2748
|
-
|
|
2749
|
-
"button",
|
|
2750
|
-
{
|
|
2751
|
-
type: "button",
|
|
2752
|
-
"data-gg-chip": "",
|
|
2753
|
-
onClick: () => {
|
|
2754
|
-
logEvent("starter_tap", s);
|
|
2755
|
-
send(s);
|
|
2756
|
-
},
|
|
2757
|
-
style: {
|
|
2758
|
-
border: `1px solid ${t.inputBorder}`,
|
|
2759
|
-
background: "transparent",
|
|
2760
|
-
color: t.textMuted,
|
|
2761
|
-
borderRadius: "999px",
|
|
2762
|
-
padding: "6px 11px",
|
|
2763
|
-
fontSize: "12px",
|
|
2764
|
-
fontFamily: "inherit",
|
|
2765
|
-
cursor: "pointer"
|
|
2766
|
-
},
|
|
2767
|
-
children: s
|
|
2768
|
-
},
|
|
2769
|
-
s
|
|
2770
|
-
))
|
|
2771
|
-
}
|
|
2772
|
-
)
|
|
2773
|
-
] }),
|
|
2774
|
-
messages.map((m, i) => {
|
|
2775
|
-
const mine = m.role === "user";
|
|
2776
|
-
if (m.kind === "report") {
|
|
2777
|
-
const live = phase === "draft" && i === messages.length - 1;
|
|
2778
|
-
return /* @__PURE__ */ jsxs3("div", { style: { display: "flex", gap: "8px", minWidth: 0 }, children: [
|
|
2779
|
-
/* @__PURE__ */ jsx3(Avatar, { who: "assistant", theme: t }),
|
|
2780
|
-
/* @__PURE__ */ jsx3(
|
|
2781
|
-
"div",
|
|
2782
|
-
{
|
|
2783
|
-
"data-gg-draft-bubble": "",
|
|
2784
|
-
style: {
|
|
2785
|
-
maxWidth: "82%",
|
|
2786
|
-
minWidth: 0,
|
|
2787
|
-
padding: "9px 12px",
|
|
2788
|
-
borderRadius: "12px 12px 12px 4px",
|
|
2789
|
-
fontSize: "13px",
|
|
2790
|
-
lineHeight: 1.55,
|
|
2791
|
-
backgroundColor: t.bgSecondary,
|
|
2792
|
-
color: t.text,
|
|
2793
|
-
border: live ? "none" : `1px solid ${t.accent}66`
|
|
2794
|
-
},
|
|
2795
|
-
children: live ? (
|
|
2796
|
-
// #402: "have a read" beside a countdown reads as a
|
|
2797
|
-
// contradiction. Say what is about to happen instead.
|
|
2798
|
-
autoFileLeft !== null ? "Here's your report \u2014 I'll file it unless you want to change something." : "Here's your report \u2014 have a read."
|
|
2799
|
-
) : /* @__PURE__ */ jsxs3(Fragment2, { children: [
|
|
3417
|
+
/* @__PURE__ */ jsxs3("span", { style: { fontSize: "11.5px", color: t.textMuted }, children: [
|
|
3418
|
+
"Pick up where you left off \xB7 ",
|
|
3419
|
+
chatAge(resumable.updatedAt)
|
|
3420
|
+
] }),
|
|
3421
|
+
/* @__PURE__ */ jsx3(
|
|
3422
|
+
"span",
|
|
3423
|
+
{
|
|
3424
|
+
style: {
|
|
3425
|
+
fontSize: "13px",
|
|
3426
|
+
lineHeight: 1.45,
|
|
3427
|
+
overflowWrap: "anywhere"
|
|
3428
|
+
},
|
|
3429
|
+
children: resumable.title
|
|
3430
|
+
}
|
|
3431
|
+
),
|
|
3432
|
+
/* @__PURE__ */ jsxs3("div", { style: { display: "flex", gap: "8px", flexWrap: "wrap" }, children: [
|
|
2800
3433
|
/* @__PURE__ */ jsx3(
|
|
2801
|
-
"
|
|
3434
|
+
"button",
|
|
2802
3435
|
{
|
|
3436
|
+
type: "button",
|
|
3437
|
+
"data-gg-resume-continue": "",
|
|
3438
|
+
onClick: () => resumeChat(resumable),
|
|
2803
3439
|
style: {
|
|
2804
|
-
|
|
2805
|
-
|
|
2806
|
-
|
|
2807
|
-
|
|
2808
|
-
|
|
2809
|
-
|
|
2810
|
-
|
|
3440
|
+
border: "none",
|
|
3441
|
+
borderRadius: "999px",
|
|
3442
|
+
backgroundColor: t.accent,
|
|
3443
|
+
color: t.accentText,
|
|
3444
|
+
padding: "7px 13px",
|
|
3445
|
+
fontSize: "12px",
|
|
3446
|
+
fontWeight: 600,
|
|
3447
|
+
fontFamily: "inherit",
|
|
3448
|
+
cursor: "pointer"
|
|
2811
3449
|
},
|
|
2812
|
-
children: "
|
|
3450
|
+
children: "Continue this chat"
|
|
2813
3451
|
}
|
|
2814
3452
|
),
|
|
2815
3453
|
/* @__PURE__ */ jsx3(
|
|
2816
|
-
"
|
|
3454
|
+
"button",
|
|
2817
3455
|
{
|
|
3456
|
+
type: "button",
|
|
3457
|
+
onClick: () => setShowChats(true),
|
|
2818
3458
|
style: {
|
|
2819
|
-
|
|
2820
|
-
|
|
2821
|
-
|
|
2822
|
-
|
|
2823
|
-
|
|
2824
|
-
|
|
3459
|
+
border: `1px solid ${t.inputBorder}`,
|
|
3460
|
+
borderRadius: "999px",
|
|
3461
|
+
background: "transparent",
|
|
3462
|
+
color: t.textMuted,
|
|
3463
|
+
padding: "7px 13px",
|
|
3464
|
+
fontSize: "12px",
|
|
3465
|
+
fontFamily: "inherit",
|
|
3466
|
+
cursor: "pointer"
|
|
2825
3467
|
},
|
|
2826
|
-
children:
|
|
3468
|
+
children: "All chats"
|
|
2827
3469
|
}
|
|
2828
3470
|
)
|
|
2829
3471
|
] })
|
|
3472
|
+
]
|
|
3473
|
+
}
|
|
3474
|
+
),
|
|
3475
|
+
/* @__PURE__ */ jsxs3("div", { style: { display: "flex", gap: "8px" }, children: [
|
|
3476
|
+
/* @__PURE__ */ jsx3(Avatar, { who: "assistant", theme: t }),
|
|
3477
|
+
/* @__PURE__ */ jsxs3(
|
|
3478
|
+
"div",
|
|
3479
|
+
{
|
|
3480
|
+
style: {
|
|
3481
|
+
padding: "9px 12px",
|
|
3482
|
+
borderRadius: "12px 12px 12px 4px",
|
|
3483
|
+
backgroundColor: t.bgSecondary,
|
|
3484
|
+
fontSize: "13px",
|
|
3485
|
+
lineHeight: 1.55,
|
|
3486
|
+
maxWidth: "88%"
|
|
3487
|
+
},
|
|
3488
|
+
children: [
|
|
3489
|
+
reporterName ? `Hi ${reporterName.split(" ")[0]} \u2014 t` : "T",
|
|
3490
|
+
"ell me what went wrong in your own words. I can already see your screenshot and what you clicked, so skip the boring parts."
|
|
3491
|
+
]
|
|
2830
3492
|
}
|
|
2831
3493
|
)
|
|
2832
|
-
] },
|
|
2833
|
-
|
|
2834
|
-
|
|
2835
|
-
|
|
2836
|
-
|
|
2837
|
-
|
|
2838
|
-
|
|
2839
|
-
|
|
2840
|
-
|
|
2841
|
-
|
|
2842
|
-
|
|
2843
|
-
children: [
|
|
2844
|
-
/* @__PURE__ */ jsx3(Avatar, { who: m.role, theme: t, initials: initials2 }),
|
|
2845
|
-
/* @__PURE__ */ jsx3(
|
|
2846
|
-
"div",
|
|
2847
|
-
{
|
|
2848
|
-
style: {
|
|
2849
|
-
maxWidth: "82%",
|
|
2850
|
-
minWidth: 0,
|
|
2851
|
-
padding: "9px 12px",
|
|
2852
|
-
borderRadius: mine ? "12px 12px 4px 12px" : "12px 12px 12px 4px",
|
|
2853
|
-
fontSize: "13px",
|
|
2854
|
-
lineHeight: 1.55,
|
|
2855
|
-
// Markdown owns the assistant's line breaks and lists.
|
|
2856
|
-
whiteSpace: mine ? "pre-wrap" : "normal",
|
|
2857
|
-
wordBreak: "break-word",
|
|
2858
|
-
backgroundColor: mine ? t.accent : t.bgSecondary,
|
|
2859
|
-
color: mine ? t.accentText : t.text
|
|
2860
|
-
},
|
|
2861
|
-
children: mine ? m.content : /* @__PURE__ */ jsx3(ChatMarkdown, { text: m.content, theme: t })
|
|
2862
|
-
}
|
|
2863
|
-
)
|
|
2864
|
-
]
|
|
2865
|
-
},
|
|
2866
|
-
i
|
|
2867
|
-
);
|
|
2868
|
-
}),
|
|
2869
|
-
duplicate && !busy && phase === "chat" && /* @__PURE__ */ jsx3("div", { style: { paddingLeft: "32px", minWidth: 0 }, children: renderKnownIssue({ title: false }) }),
|
|
2870
|
-
glitchgrabOffer && onReportGlitchgrabProblem && !busy && phase === "chat" && /* @__PURE__ */ jsx3("div", { style: { paddingLeft: "32px", minWidth: 0 }, children: /* @__PURE__ */ jsxs3(
|
|
2871
|
-
"div",
|
|
2872
|
-
{
|
|
2873
|
-
"data-gg-glitchgrab-offer": "",
|
|
2874
|
-
style: {
|
|
2875
|
-
display: "flex",
|
|
2876
|
-
flexDirection: "column",
|
|
2877
|
-
gap: "8px",
|
|
2878
|
-
padding: "10px",
|
|
2879
|
-
borderRadius: "8px",
|
|
2880
|
-
border: `1px solid ${t.accent}55`,
|
|
2881
|
-
backgroundColor: `${t.accent}14`,
|
|
2882
|
-
fontSize: "12px",
|
|
2883
|
-
lineHeight: 1.5
|
|
2884
|
-
},
|
|
2885
|
-
children: [
|
|
2886
|
-
/* @__PURE__ */ jsx3("span", { style: { color: t.text, fontWeight: 600 }, children: "This is about Glitchgrab, not this app" }),
|
|
2887
|
-
/* @__PURE__ */ jsx3("span", { style: { color: t.textMuted }, children: "It goes to the team that builds this reporter, with your chat attached." }),
|
|
2888
|
-
/* @__PURE__ */ jsxs3("div", { style: { display: "flex", flexWrap: "wrap", gap: "6px" }, children: [
|
|
2889
|
-
/* @__PURE__ */ jsx3(
|
|
3494
|
+
] }),
|
|
3495
|
+
/* @__PURE__ */ jsx3(
|
|
3496
|
+
"div",
|
|
3497
|
+
{
|
|
3498
|
+
style: {
|
|
3499
|
+
display: "flex",
|
|
3500
|
+
flexWrap: "wrap",
|
|
3501
|
+
gap: "6px",
|
|
3502
|
+
paddingLeft: "32px"
|
|
3503
|
+
},
|
|
3504
|
+
children: STARTERS.map((s) => /* @__PURE__ */ jsx3(
|
|
2890
3505
|
"button",
|
|
2891
3506
|
{
|
|
2892
3507
|
type: "button",
|
|
2893
|
-
"data-gg-
|
|
3508
|
+
"data-gg-chip": "",
|
|
2894
3509
|
onClick: () => {
|
|
2895
|
-
logEvent("
|
|
2896
|
-
|
|
2897
|
-
onReportGlitchgrabProblem(
|
|
2898
|
-
messages.filter((m) => m.role === "user").map((m) => m.content.trim()).filter(Boolean).join("\n\n")
|
|
2899
|
-
);
|
|
3510
|
+
logEvent("starter_tap", s);
|
|
3511
|
+
send(s);
|
|
2900
3512
|
},
|
|
2901
3513
|
style: {
|
|
2902
|
-
|
|
3514
|
+
border: `1px solid ${t.inputBorder}`,
|
|
3515
|
+
background: "transparent",
|
|
3516
|
+
color: t.textMuted,
|
|
2903
3517
|
borderRadius: "999px",
|
|
2904
|
-
|
|
2905
|
-
backgroundColor: t.accent,
|
|
2906
|
-
color: t.accentText,
|
|
3518
|
+
padding: "6px 11px",
|
|
2907
3519
|
fontSize: "12px",
|
|
2908
|
-
fontWeight: 700,
|
|
2909
3520
|
fontFamily: "inherit",
|
|
2910
|
-
cursor: "pointer"
|
|
2911
|
-
// Both stretch, so on a phone each wrapped line reads as
|
|
2912
|
-
// a choice rather than one button left stranded.
|
|
2913
|
-
flex: "1 1 auto"
|
|
3521
|
+
cursor: "pointer"
|
|
2914
3522
|
},
|
|
2915
|
-
children:
|
|
2916
|
-
}
|
|
2917
|
-
|
|
3523
|
+
children: s
|
|
3524
|
+
},
|
|
3525
|
+
s
|
|
3526
|
+
))
|
|
3527
|
+
}
|
|
3528
|
+
)
|
|
3529
|
+
] }),
|
|
3530
|
+
messages.map((m, i) => {
|
|
3531
|
+
const mine = m.role === "user";
|
|
3532
|
+
if (m.kind === "report") {
|
|
3533
|
+
const live = phase === "draft" && i === messages.length - 1;
|
|
3534
|
+
return /* @__PURE__ */ jsxs3("div", { style: { display: "flex", gap: "8px", minWidth: 0 }, children: [
|
|
3535
|
+
/* @__PURE__ */ jsx3(Avatar, { who: "assistant", theme: t }),
|
|
2918
3536
|
/* @__PURE__ */ jsx3(
|
|
2919
|
-
"
|
|
3537
|
+
"div",
|
|
2920
3538
|
{
|
|
2921
|
-
|
|
2922
|
-
"data-gg-glitchgrab-offer-no": "",
|
|
2923
|
-
onClick: () => {
|
|
2924
|
-
logEvent("glitchgrab_offer_declined");
|
|
2925
|
-
send("No \u2014 it's about this app, not the reporting tool");
|
|
2926
|
-
},
|
|
3539
|
+
"data-gg-draft-bubble": "",
|
|
2927
3540
|
style: {
|
|
2928
|
-
|
|
2929
|
-
|
|
2930
|
-
|
|
2931
|
-
|
|
2932
|
-
|
|
2933
|
-
|
|
2934
|
-
|
|
2935
|
-
|
|
2936
|
-
|
|
3541
|
+
maxWidth: "82%",
|
|
3542
|
+
minWidth: 0,
|
|
3543
|
+
padding: "9px 12px",
|
|
3544
|
+
borderRadius: "12px 12px 12px 4px",
|
|
3545
|
+
fontSize: "13px",
|
|
3546
|
+
lineHeight: 1.55,
|
|
3547
|
+
backgroundColor: t.bgSecondary,
|
|
3548
|
+
color: t.text,
|
|
3549
|
+
border: live ? "none" : `1px solid ${t.accent}66`
|
|
2937
3550
|
},
|
|
2938
|
-
children:
|
|
3551
|
+
children: live ? (
|
|
3552
|
+
// #402: "have a read" beside a countdown reads as a
|
|
3553
|
+
// contradiction. Say what is about to happen instead.
|
|
3554
|
+
autoFileLeft !== null ? "Here's your report \u2014 I'll file it unless you want to change something." : "Here's your report \u2014 have a read."
|
|
3555
|
+
) : /* @__PURE__ */ jsxs3(Fragment2, { children: [
|
|
3556
|
+
/* @__PURE__ */ jsx3(
|
|
3557
|
+
"span",
|
|
3558
|
+
{
|
|
3559
|
+
style: {
|
|
3560
|
+
display: "block",
|
|
3561
|
+
fontSize: "10px",
|
|
3562
|
+
fontWeight: 700,
|
|
3563
|
+
letterSpacing: ".06em",
|
|
3564
|
+
textTransform: "uppercase",
|
|
3565
|
+
color: t.accent,
|
|
3566
|
+
marginBottom: "4px"
|
|
3567
|
+
},
|
|
3568
|
+
children: "Draft so far"
|
|
3569
|
+
}
|
|
3570
|
+
),
|
|
3571
|
+
/* @__PURE__ */ jsx3(
|
|
3572
|
+
"span",
|
|
3573
|
+
{
|
|
3574
|
+
style: {
|
|
3575
|
+
display: "block",
|
|
3576
|
+
whiteSpace: "pre-wrap",
|
|
3577
|
+
wordBreak: "break-word",
|
|
3578
|
+
maxHeight: "160px",
|
|
3579
|
+
overflowY: "auto",
|
|
3580
|
+
color: t.textMuted
|
|
3581
|
+
},
|
|
3582
|
+
children: m.content
|
|
3583
|
+
}
|
|
3584
|
+
)
|
|
3585
|
+
] })
|
|
2939
3586
|
}
|
|
2940
3587
|
)
|
|
2941
|
-
] })
|
|
2942
|
-
|
|
2943
|
-
|
|
2944
|
-
|
|
2945
|
-
options.length > 0 && !busy && phase === "chat" && !glitchgrabOffer && /* @__PURE__ */ jsx3(
|
|
2946
|
-
"div",
|
|
2947
|
-
{
|
|
2948
|
-
style: {
|
|
2949
|
-
display: "flex",
|
|
2950
|
-
// Long labels wrapped into a ragged row that always stranded
|
|
2951
|
-
// the last chip on a line of its own. Past ~24 characters
|
|
2952
|
-
// these stop being chips and become a choice list, so they
|
|
2953
|
-
// stack full width and read like one.
|
|
2954
|
-
flexDirection: options.some((o) => o.length > 24) ? "column" : "row",
|
|
2955
|
-
alignItems: options.some((o) => o.length > 24) ? "stretch" : "flex-start",
|
|
2956
|
-
flexWrap: "wrap",
|
|
2957
|
-
gap: "6px",
|
|
2958
|
-
paddingLeft: "32px"
|
|
2959
|
-
},
|
|
2960
|
-
children: options.map((option) => /* @__PURE__ */ jsx3(
|
|
2961
|
-
"button",
|
|
3588
|
+
] }, i);
|
|
3589
|
+
}
|
|
3590
|
+
return /* @__PURE__ */ jsxs3(
|
|
3591
|
+
"div",
|
|
2962
3592
|
{
|
|
2963
|
-
type: "button",
|
|
2964
|
-
"data-gg-chip": "",
|
|
2965
|
-
"data-gg-option": "",
|
|
2966
|
-
onClick: () => {
|
|
2967
|
-
logEvent("option_tap", option);
|
|
2968
|
-
send(option, option === CONFIRM_OPTION);
|
|
2969
|
-
},
|
|
2970
3593
|
style: {
|
|
2971
|
-
|
|
2972
|
-
|
|
2973
|
-
|
|
2974
|
-
|
|
2975
|
-
// Same 8px as the picker chips — one tap target size in
|
|
2976
|
-
// this sheet, not two.
|
|
2977
|
-
padding: "8px 12px",
|
|
2978
|
-
fontSize: "12px",
|
|
2979
|
-
fontFamily: "inherit",
|
|
2980
|
-
cursor: "pointer",
|
|
2981
|
-
textAlign: "left"
|
|
3594
|
+
display: "flex",
|
|
3595
|
+
gap: "8px",
|
|
3596
|
+
minWidth: 0,
|
|
3597
|
+
flexDirection: mine ? "row-reverse" : "row"
|
|
2982
3598
|
},
|
|
2983
|
-
children:
|
|
3599
|
+
children: [
|
|
3600
|
+
/* @__PURE__ */ jsx3(Avatar, { who: m.role, theme: t, initials: initials2 }),
|
|
3601
|
+
/* @__PURE__ */ jsx3(
|
|
3602
|
+
"div",
|
|
3603
|
+
{
|
|
3604
|
+
style: {
|
|
3605
|
+
maxWidth: "82%",
|
|
3606
|
+
minWidth: 0,
|
|
3607
|
+
padding: "9px 12px",
|
|
3608
|
+
borderRadius: mine ? "12px 12px 4px 12px" : "12px 12px 12px 4px",
|
|
3609
|
+
fontSize: "13px",
|
|
3610
|
+
lineHeight: 1.55,
|
|
3611
|
+
// Markdown owns the assistant's line breaks and lists.
|
|
3612
|
+
whiteSpace: mine ? "pre-wrap" : "normal",
|
|
3613
|
+
wordBreak: "break-word",
|
|
3614
|
+
backgroundColor: mine ? t.accent : t.bgSecondary,
|
|
3615
|
+
color: mine ? t.accentText : t.text
|
|
3616
|
+
},
|
|
3617
|
+
children: mine ? m.content : /* @__PURE__ */ jsx3(ChatMarkdown, { text: m.content, theme: t })
|
|
3618
|
+
}
|
|
3619
|
+
)
|
|
3620
|
+
]
|
|
2984
3621
|
},
|
|
2985
|
-
|
|
2986
|
-
)
|
|
2987
|
-
}
|
|
2988
|
-
|
|
2989
|
-
|
|
2990
|
-
|
|
2991
|
-
/* @__PURE__ */ jsx3(
|
|
2992
|
-
"span",
|
|
3622
|
+
i
|
|
3623
|
+
);
|
|
3624
|
+
}),
|
|
3625
|
+
duplicate && !busy && phase === "chat" && /* @__PURE__ */ jsx3("div", { style: { paddingLeft: "32px", minWidth: 0 }, children: renderKnownIssue({ title: false }) }),
|
|
3626
|
+
glitchgrabOffer && onReportGlitchgrabProblem && !busy && phase === "chat" && /* @__PURE__ */ jsx3("div", { style: { paddingLeft: "32px", minWidth: 0 }, children: /* @__PURE__ */ jsxs3(
|
|
3627
|
+
"div",
|
|
2993
3628
|
{
|
|
3629
|
+
"data-gg-glitchgrab-offer": "",
|
|
2994
3630
|
style: {
|
|
2995
|
-
display: "
|
|
2996
|
-
|
|
2997
|
-
gap: "
|
|
2998
|
-
padding: "
|
|
2999
|
-
borderRadius: "
|
|
3000
|
-
|
|
3631
|
+
display: "flex",
|
|
3632
|
+
flexDirection: "column",
|
|
3633
|
+
gap: "8px",
|
|
3634
|
+
padding: "10px",
|
|
3635
|
+
borderRadius: "8px",
|
|
3636
|
+
border: `1px solid ${t.accent}55`,
|
|
3637
|
+
backgroundColor: `${t.accent}14`,
|
|
3638
|
+
fontSize: "12px",
|
|
3639
|
+
lineHeight: 1.5
|
|
3001
3640
|
},
|
|
3002
|
-
children: [
|
|
3003
|
-
"span",
|
|
3004
|
-
{
|
|
3005
|
-
|
|
3006
|
-
|
|
3007
|
-
|
|
3008
|
-
|
|
3009
|
-
|
|
3010
|
-
|
|
3011
|
-
|
|
3012
|
-
|
|
3013
|
-
|
|
3014
|
-
|
|
3641
|
+
children: [
|
|
3642
|
+
/* @__PURE__ */ jsx3("span", { style: { color: t.text, fontWeight: 600 }, children: "This is about Glitchgrab, not this app" }),
|
|
3643
|
+
/* @__PURE__ */ jsx3("span", { style: { color: t.textMuted }, children: "It goes to the team that builds this reporter, with your chat attached." }),
|
|
3644
|
+
/* @__PURE__ */ jsxs3("div", { style: { display: "flex", flexWrap: "wrap", gap: "6px" }, children: [
|
|
3645
|
+
/* @__PURE__ */ jsx3(
|
|
3646
|
+
"button",
|
|
3647
|
+
{
|
|
3648
|
+
type: "button",
|
|
3649
|
+
"data-gg-glitchgrab-offer-send": "",
|
|
3650
|
+
onClick: () => {
|
|
3651
|
+
logEvent("glitchgrab_offer_tap");
|
|
3652
|
+
setGlitchgrabOffer(false);
|
|
3653
|
+
onReportGlitchgrabProblem(
|
|
3654
|
+
messages.filter((m) => m.role === "user").map((m) => m.content.trim()).filter(Boolean).join("\n\n")
|
|
3655
|
+
);
|
|
3656
|
+
},
|
|
3657
|
+
style: {
|
|
3658
|
+
padding: "8px 12px",
|
|
3659
|
+
borderRadius: "999px",
|
|
3660
|
+
border: "none",
|
|
3661
|
+
backgroundColor: t.accent,
|
|
3662
|
+
color: t.accentText,
|
|
3663
|
+
fontSize: "12px",
|
|
3664
|
+
fontWeight: 700,
|
|
3665
|
+
fontFamily: "inherit",
|
|
3666
|
+
cursor: "pointer",
|
|
3667
|
+
// Both stretch, so on a phone each wrapped line reads as
|
|
3668
|
+
// a choice rather than one button left stranded.
|
|
3669
|
+
flex: "1 1 auto"
|
|
3670
|
+
},
|
|
3671
|
+
children: "Send to the Glitchgrab team"
|
|
3672
|
+
}
|
|
3673
|
+
),
|
|
3674
|
+
/* @__PURE__ */ jsx3(
|
|
3675
|
+
"button",
|
|
3676
|
+
{
|
|
3677
|
+
type: "button",
|
|
3678
|
+
"data-gg-glitchgrab-offer-no": "",
|
|
3679
|
+
onClick: () => {
|
|
3680
|
+
logEvent("glitchgrab_offer_declined");
|
|
3681
|
+
send("No \u2014 it's about this app, not the reporting tool");
|
|
3682
|
+
},
|
|
3683
|
+
style: {
|
|
3684
|
+
padding: "8px 12px",
|
|
3685
|
+
borderRadius: "999px",
|
|
3686
|
+
border: `1px solid ${t.inputBorder}`,
|
|
3687
|
+
background: "transparent",
|
|
3688
|
+
color: t.textMuted,
|
|
3689
|
+
fontSize: "12px",
|
|
3690
|
+
fontFamily: "inherit",
|
|
3691
|
+
cursor: "pointer",
|
|
3692
|
+
flex: "1 1 auto"
|
|
3693
|
+
},
|
|
3694
|
+
children: "No, it's about this app"
|
|
3695
|
+
}
|
|
3696
|
+
)
|
|
3697
|
+
] })
|
|
3698
|
+
]
|
|
3015
3699
|
}
|
|
3016
|
-
)
|
|
3017
|
-
|
|
3018
|
-
|
|
3019
|
-
|
|
3020
|
-
|
|
3021
|
-
|
|
3022
|
-
|
|
3023
|
-
|
|
3024
|
-
|
|
3025
|
-
|
|
3026
|
-
|
|
3027
|
-
|
|
3028
|
-
|
|
3029
|
-
|
|
3030
|
-
|
|
3031
|
-
|
|
3032
|
-
|
|
3033
|
-
|
|
3034
|
-
"span",
|
|
3035
|
-
{
|
|
3036
|
-
style: {
|
|
3037
|
-
fontSize: "10px",
|
|
3038
|
-
fontWeight: 700,
|
|
3039
|
-
letterSpacing: ".06em",
|
|
3040
|
-
textTransform: "uppercase",
|
|
3041
|
-
color: t.accent
|
|
3042
|
-
},
|
|
3043
|
-
children: duplicate ? `What we'll add to #${duplicate.number}${duplicate.kind === "related" ? " as a related request" : ""} \xB7 edit anything` : "Your report \xB7 edit anything"
|
|
3044
|
-
}
|
|
3045
|
-
),
|
|
3046
|
-
renderKnownIssue({
|
|
3047
|
-
title: true,
|
|
3048
|
-
footer: "Your details will be added to it instead of opening a new issue."
|
|
3049
|
-
}),
|
|
3050
|
-
!duplicate && issueTitle && // Wraps rather than scrolls sideways: a title cut off at the
|
|
3051
|
-
// box edge is the very thing #543 is about. One line of text,
|
|
3052
|
-
// so Enter is swallowed.
|
|
3053
|
-
/* @__PURE__ */ jsx3(
|
|
3054
|
-
"textarea",
|
|
3055
|
-
{
|
|
3056
|
-
"aria-label": "Title",
|
|
3057
|
-
value: issueTitle,
|
|
3058
|
-
maxLength: 120,
|
|
3059
|
-
rows: 2,
|
|
3060
|
-
onKeyDown: (e) => {
|
|
3061
|
-
if (e.key === "Enter") e.preventDefault();
|
|
3062
|
-
},
|
|
3063
|
-
onChange: (e) => {
|
|
3064
|
-
stopAutoFile("edited the title");
|
|
3065
|
-
onIssueTitleChange(e.target.value.replace(/[\r\n]+/g, " "));
|
|
3066
|
-
},
|
|
3067
|
-
style: {
|
|
3068
|
-
width: "100%",
|
|
3069
|
-
padding: "8px 10px",
|
|
3070
|
-
lineHeight: 1.45,
|
|
3071
|
-
resize: "none",
|
|
3072
|
-
borderRadius: "8px",
|
|
3073
|
-
border: `1px solid ${t.inputBorder}`,
|
|
3074
|
-
backgroundColor: t.inputBg,
|
|
3075
|
-
color: t.text,
|
|
3076
|
-
fontSize: "13px",
|
|
3077
|
-
fontWeight: 600,
|
|
3078
|
-
fontFamily: "inherit",
|
|
3079
|
-
outline: "none",
|
|
3080
|
-
boxSizing: "border-box"
|
|
3081
|
-
}
|
|
3082
|
-
}
|
|
3083
|
-
),
|
|
3084
|
-
/* @__PURE__ */ jsx3(
|
|
3085
|
-
"textarea",
|
|
3700
|
+
) }),
|
|
3701
|
+
options.length > 0 && !busy && phase === "chat" && !glitchgrabOffer && /* @__PURE__ */ jsx3(
|
|
3702
|
+
"div",
|
|
3703
|
+
{
|
|
3704
|
+
style: {
|
|
3705
|
+
display: "flex",
|
|
3706
|
+
// Long labels wrapped into a ragged row that always stranded
|
|
3707
|
+
// the last chip on a line of its own. Past ~24 characters
|
|
3708
|
+
// these stop being chips and become a choice list, so they
|
|
3709
|
+
// stack full width and read like one.
|
|
3710
|
+
flexDirection: options.some((o) => o.length > 24) ? "column" : "row",
|
|
3711
|
+
alignItems: options.some((o) => o.length > 24) ? "stretch" : "flex-start",
|
|
3712
|
+
flexWrap: "wrap",
|
|
3713
|
+
gap: "6px",
|
|
3714
|
+
paddingLeft: "32px"
|
|
3715
|
+
},
|
|
3716
|
+
children: options.map((option) => /* @__PURE__ */ jsx3(
|
|
3717
|
+
"button",
|
|
3086
3718
|
{
|
|
3087
|
-
|
|
3088
|
-
|
|
3089
|
-
|
|
3090
|
-
|
|
3091
|
-
|
|
3719
|
+
type: "button",
|
|
3720
|
+
"data-gg-chip": "",
|
|
3721
|
+
"data-gg-option": "",
|
|
3722
|
+
onClick: () => {
|
|
3723
|
+
logEvent("option_tap", option);
|
|
3724
|
+
send(option, option === CONFIRM_OPTION);
|
|
3092
3725
|
},
|
|
3093
|
-
rows: 6,
|
|
3094
3726
|
style: {
|
|
3095
|
-
width: "100%",
|
|
3096
|
-
minHeight: "120px",
|
|
3097
|
-
padding: "10px",
|
|
3098
|
-
borderRadius: "8px",
|
|
3099
3727
|
border: `1px solid ${t.inputBorder}`,
|
|
3100
|
-
|
|
3101
|
-
color: t.
|
|
3102
|
-
|
|
3103
|
-
|
|
3728
|
+
background: "transparent",
|
|
3729
|
+
color: t.textMuted,
|
|
3730
|
+
borderRadius: "999px",
|
|
3731
|
+
// Same 8px as the picker chips — one tap target size in
|
|
3732
|
+
// this sheet, not two.
|
|
3733
|
+
padding: "8px 12px",
|
|
3734
|
+
fontSize: "12px",
|
|
3104
3735
|
fontFamily: "inherit",
|
|
3105
|
-
|
|
3106
|
-
|
|
3107
|
-
|
|
3108
|
-
|
|
3109
|
-
}
|
|
3110
|
-
|
|
3111
|
-
|
|
3112
|
-
|
|
3736
|
+
cursor: "pointer",
|
|
3737
|
+
textAlign: "left"
|
|
3738
|
+
},
|
|
3739
|
+
children: option
|
|
3740
|
+
},
|
|
3741
|
+
option
|
|
3742
|
+
))
|
|
3743
|
+
}
|
|
3744
|
+
),
|
|
3745
|
+
busy && /* @__PURE__ */ jsxs3("div", { style: { display: "flex", gap: "8px", minWidth: 0 }, role: "status", "aria-label": "Thinking", children: [
|
|
3746
|
+
/* @__PURE__ */ jsx3(Avatar, { who: "assistant", theme: t }),
|
|
3747
|
+
/* @__PURE__ */ jsxs3(
|
|
3748
|
+
"span",
|
|
3749
|
+
{
|
|
3750
|
+
style: {
|
|
3751
|
+
display: "inline-flex",
|
|
3752
|
+
alignItems: "center",
|
|
3753
|
+
// The "still working" line must wrap on a phone, not push
|
|
3754
|
+
// the bubble past the sheet's edge.
|
|
3755
|
+
flexWrap: "wrap",
|
|
3756
|
+
minWidth: 0,
|
|
3757
|
+
gap: "4px",
|
|
3758
|
+
padding: "12px",
|
|
3759
|
+
borderRadius: "12px 12px 12px 4px",
|
|
3760
|
+
backgroundColor: t.bgSecondary
|
|
3761
|
+
},
|
|
3762
|
+
children: [
|
|
3763
|
+
[0, 1, 2].map((i) => /* @__PURE__ */ jsx3(
|
|
3764
|
+
"span",
|
|
3765
|
+
{
|
|
3766
|
+
style: {
|
|
3767
|
+
width: "5px",
|
|
3768
|
+
height: "5px",
|
|
3769
|
+
borderRadius: "50%",
|
|
3770
|
+
backgroundColor: t.textMuted,
|
|
3771
|
+
animation: `gg-dot 1.1s ease-in-out ${i * 0.15}s infinite`
|
|
3772
|
+
}
|
|
3773
|
+
},
|
|
3774
|
+
i
|
|
3775
|
+
)),
|
|
3776
|
+
/* @__PURE__ */ jsx3(ThinkingClock, { color: t.textMuted })
|
|
3777
|
+
]
|
|
3778
|
+
}
|
|
3779
|
+
)
|
|
3780
|
+
] }),
|
|
3781
|
+
phase === "draft" && !submitted && /* @__PURE__ */ jsxs3(
|
|
3782
|
+
"div",
|
|
3783
|
+
{
|
|
3784
|
+
style: {
|
|
3785
|
+
border: `1px solid ${t.accent}`,
|
|
3786
|
+
borderRadius: "12px",
|
|
3787
|
+
backgroundColor: t.bgSecondary,
|
|
3788
|
+
padding: "12px",
|
|
3789
|
+
display: "flex",
|
|
3790
|
+
flexDirection: "column",
|
|
3791
|
+
gap: "10px",
|
|
3792
|
+
minWidth: 0,
|
|
3793
|
+
boxSizing: "border-box"
|
|
3794
|
+
},
|
|
3795
|
+
children: [
|
|
3796
|
+
/* @__PURE__ */ jsx3(
|
|
3113
3797
|
"span",
|
|
3114
3798
|
{
|
|
3115
3799
|
style: {
|
|
3116
|
-
fontSize: "
|
|
3117
|
-
|
|
3118
|
-
|
|
3119
|
-
|
|
3800
|
+
fontSize: "10px",
|
|
3801
|
+
fontWeight: 700,
|
|
3802
|
+
letterSpacing: ".06em",
|
|
3803
|
+
textTransform: "uppercase",
|
|
3804
|
+
color: t.accent
|
|
3120
3805
|
},
|
|
3121
|
-
children:
|
|
3122
|
-
"How bad is it?",
|
|
3123
|
-
!severity && /* @__PURE__ */ jsx3(
|
|
3124
|
-
"span",
|
|
3125
|
-
{
|
|
3126
|
-
style: {
|
|
3127
|
-
marginLeft: "6px",
|
|
3128
|
-
fontSize: "11px",
|
|
3129
|
-
color: severityRefused ? "#ef4444" : t.textMuted
|
|
3130
|
-
},
|
|
3131
|
-
children: "\xB7 required"
|
|
3132
|
-
}
|
|
3133
|
-
)
|
|
3134
|
-
]
|
|
3806
|
+
children: duplicate ? `What we'll add to #${duplicate.number}${duplicate.kind === "related" ? " as a related request" : ""} \xB7 edit anything` : "Your report \xB7 edit anything"
|
|
3135
3807
|
}
|
|
3136
3808
|
),
|
|
3809
|
+
renderKnownIssue({
|
|
3810
|
+
title: true,
|
|
3811
|
+
footer: "Your details will be added to it instead of opening a new issue."
|
|
3812
|
+
}),
|
|
3813
|
+
!duplicate && issueTitle && // Wraps rather than scrolls sideways: a title cut off at the
|
|
3814
|
+
// box edge is the very thing #543 is about. One line of text,
|
|
3815
|
+
// so Enter is swallowed.
|
|
3137
3816
|
/* @__PURE__ */ jsx3(
|
|
3138
|
-
"
|
|
3817
|
+
"textarea",
|
|
3139
3818
|
{
|
|
3140
|
-
|
|
3141
|
-
|
|
3142
|
-
|
|
3143
|
-
|
|
3144
|
-
|
|
3145
|
-
|
|
3146
|
-
|
|
3147
|
-
|
|
3148
|
-
|
|
3149
|
-
|
|
3150
|
-
|
|
3151
|
-
|
|
3152
|
-
|
|
3153
|
-
|
|
3154
|
-
|
|
3155
|
-
|
|
3156
|
-
|
|
3157
|
-
|
|
3158
|
-
|
|
3159
|
-
|
|
3160
|
-
|
|
3161
|
-
|
|
3162
|
-
|
|
3163
|
-
|
|
3164
|
-
|
|
3165
|
-
|
|
3166
|
-
cursor: "pointer"
|
|
3167
|
-
},
|
|
3168
|
-
children: SEVERITY_LABELS[s]
|
|
3169
|
-
},
|
|
3170
|
-
s
|
|
3171
|
-
);
|
|
3172
|
-
})
|
|
3819
|
+
"aria-label": "Title",
|
|
3820
|
+
value: issueTitle,
|
|
3821
|
+
maxLength: 120,
|
|
3822
|
+
rows: 2,
|
|
3823
|
+
onKeyDown: (e) => {
|
|
3824
|
+
if (e.key === "Enter") e.preventDefault();
|
|
3825
|
+
},
|
|
3826
|
+
onChange: (e) => {
|
|
3827
|
+
stopAutoFile("edited the title");
|
|
3828
|
+
onIssueTitleChange(e.target.value.replace(/[\r\n]+/g, " "));
|
|
3829
|
+
},
|
|
3830
|
+
style: {
|
|
3831
|
+
width: "100%",
|
|
3832
|
+
padding: "8px 10px",
|
|
3833
|
+
lineHeight: 1.45,
|
|
3834
|
+
resize: "none",
|
|
3835
|
+
borderRadius: "8px",
|
|
3836
|
+
border: `1px solid ${t.inputBorder}`,
|
|
3837
|
+
backgroundColor: t.inputBg,
|
|
3838
|
+
color: t.text,
|
|
3839
|
+
fontSize: "13px",
|
|
3840
|
+
fontWeight: 600,
|
|
3841
|
+
fontFamily: "inherit",
|
|
3842
|
+
outline: "none",
|
|
3843
|
+
boxSizing: "border-box"
|
|
3844
|
+
}
|
|
3173
3845
|
}
|
|
3174
|
-
)
|
|
3175
|
-
|
|
3176
|
-
|
|
3177
|
-
|
|
3178
|
-
|
|
3179
|
-
|
|
3180
|
-
|
|
3181
|
-
|
|
3182
|
-
|
|
3183
|
-
|
|
3184
|
-
|
|
3185
|
-
|
|
3186
|
-
|
|
3187
|
-
|
|
3846
|
+
),
|
|
3847
|
+
/* @__PURE__ */ jsx3(
|
|
3848
|
+
"textarea",
|
|
3849
|
+
{
|
|
3850
|
+
ref: draftRef,
|
|
3851
|
+
value: description,
|
|
3852
|
+
onChange: (e) => {
|
|
3853
|
+
stopAutoFile("edited the draft");
|
|
3854
|
+
onDescriptionChange(e.target.value);
|
|
3855
|
+
},
|
|
3856
|
+
rows: 6,
|
|
3857
|
+
style: {
|
|
3858
|
+
width: "100%",
|
|
3859
|
+
minHeight: "120px",
|
|
3860
|
+
padding: "10px",
|
|
3861
|
+
borderRadius: "8px",
|
|
3862
|
+
border: `1px solid ${t.inputBorder}`,
|
|
3863
|
+
backgroundColor: t.inputBg,
|
|
3864
|
+
color: t.text,
|
|
3865
|
+
fontSize: "13px",
|
|
3866
|
+
lineHeight: 1.55,
|
|
3867
|
+
fontFamily: "inherit",
|
|
3868
|
+
resize: "vertical",
|
|
3869
|
+
outline: "none",
|
|
3870
|
+
boxSizing: "border-box"
|
|
3871
|
+
}
|
|
3872
|
+
}
|
|
3873
|
+
),
|
|
3874
|
+
severityAsked && autoFileLeft === null && /* @__PURE__ */ jsxs3("div", { children: [
|
|
3875
|
+
/* @__PURE__ */ jsxs3(
|
|
3876
|
+
"span",
|
|
3877
|
+
{
|
|
3878
|
+
style: {
|
|
3879
|
+
fontSize: "11.5px",
|
|
3880
|
+
color: t.textMuted,
|
|
3881
|
+
display: "block",
|
|
3882
|
+
marginBottom: "6px"
|
|
3883
|
+
},
|
|
3884
|
+
children: [
|
|
3885
|
+
"How bad is it?",
|
|
3886
|
+
!severity && /* @__PURE__ */ jsx3(
|
|
3887
|
+
"span",
|
|
3888
|
+
{
|
|
3889
|
+
style: {
|
|
3890
|
+
marginLeft: "6px",
|
|
3891
|
+
fontSize: "11px",
|
|
3892
|
+
color: severityRefused ? "#ef4444" : t.textMuted
|
|
3893
|
+
},
|
|
3894
|
+
children: "\xB7 required"
|
|
3895
|
+
}
|
|
3896
|
+
)
|
|
3897
|
+
]
|
|
3898
|
+
}
|
|
3899
|
+
),
|
|
3900
|
+
/* @__PURE__ */ jsx3(
|
|
3901
|
+
"div",
|
|
3902
|
+
{
|
|
3903
|
+
role: "radiogroup",
|
|
3904
|
+
"aria-label": "Severity",
|
|
3905
|
+
style: { display: "flex", gap: "6px" },
|
|
3906
|
+
children: SEVERITY_LEVELS.map((s) => {
|
|
3907
|
+
const on = severity === s;
|
|
3908
|
+
return /* @__PURE__ */ jsx3(
|
|
3909
|
+
"button",
|
|
3910
|
+
{
|
|
3911
|
+
type: "button",
|
|
3912
|
+
onClick: () => onSeverityChange(s),
|
|
3913
|
+
role: "radio",
|
|
3914
|
+
"aria-checked": on,
|
|
3915
|
+
style: {
|
|
3916
|
+
flex: 1,
|
|
3917
|
+
minWidth: 0,
|
|
3918
|
+
padding: "8px 2px",
|
|
3919
|
+
borderRadius: "8px",
|
|
3920
|
+
border: `1px solid ${on ? t.accent : severityRefused ? "#ef4444" : t.inputBorder}`,
|
|
3921
|
+
backgroundColor: on ? t.accent : "transparent",
|
|
3922
|
+
color: on ? t.accentText : t.textMuted,
|
|
3923
|
+
fontSize: "12px",
|
|
3924
|
+
fontWeight: 600,
|
|
3925
|
+
fontFamily: "inherit",
|
|
3926
|
+
whiteSpace: "nowrap",
|
|
3927
|
+
overflow: "hidden",
|
|
3928
|
+
textOverflow: "ellipsis",
|
|
3929
|
+
cursor: "pointer"
|
|
3930
|
+
},
|
|
3931
|
+
children: SEVERITY_LABELS[s]
|
|
3932
|
+
},
|
|
3933
|
+
s
|
|
3934
|
+
);
|
|
3935
|
+
})
|
|
3936
|
+
}
|
|
3937
|
+
)
|
|
3938
|
+
] }),
|
|
3939
|
+
attachmentCount > 0 && /* @__PURE__ */ jsxs3("span", { style: { fontSize: "11.5px", color: t.textMuted }, children: [
|
|
3940
|
+
attachmentCount,
|
|
3941
|
+
" ",
|
|
3942
|
+
attachmentCount === 1 ? "attachment" : "attachments",
|
|
3943
|
+
" will be sent with this."
|
|
3944
|
+
] })
|
|
3945
|
+
]
|
|
3946
|
+
}
|
|
3947
|
+
),
|
|
3948
|
+
phase === "solved" && solved && /* @__PURE__ */ jsxs3("div", { style: { display: "flex", flexDirection: "column", gap: "12px" }, children: [
|
|
3949
|
+
/* @__PURE__ */ jsxs3("div", { style: { display: "flex", gap: "8px" }, children: [
|
|
3950
|
+
/* @__PURE__ */ jsx3(Avatar, { who: "assistant", theme: t }),
|
|
3951
|
+
/* @__PURE__ */ jsx3(
|
|
3952
|
+
"div",
|
|
3953
|
+
{
|
|
3954
|
+
style: {
|
|
3955
|
+
padding: "9px 12px",
|
|
3956
|
+
borderRadius: "12px 12px 12px 4px",
|
|
3957
|
+
backgroundColor: t.bgSecondary,
|
|
3958
|
+
fontSize: "13px",
|
|
3959
|
+
lineHeight: 1.55,
|
|
3960
|
+
maxWidth: "88%",
|
|
3961
|
+
whiteSpace: "pre-wrap"
|
|
3962
|
+
},
|
|
3963
|
+
children: solved
|
|
3964
|
+
}
|
|
3965
|
+
)
|
|
3966
|
+
] }),
|
|
3188
3967
|
/* @__PURE__ */ jsx3(
|
|
3189
|
-
"
|
|
3968
|
+
"span",
|
|
3190
3969
|
{
|
|
3191
|
-
style: {
|
|
3192
|
-
|
|
3193
|
-
borderRadius: "12px 12px 12px 4px",
|
|
3194
|
-
backgroundColor: t.bgSecondary,
|
|
3195
|
-
fontSize: "13px",
|
|
3196
|
-
lineHeight: 1.55,
|
|
3197
|
-
maxWidth: "88%",
|
|
3198
|
-
whiteSpace: "pre-wrap"
|
|
3199
|
-
},
|
|
3200
|
-
children: solved
|
|
3970
|
+
style: { fontSize: "11.5px", color: t.textMuted, paddingLeft: "32px" },
|
|
3971
|
+
children: "Nothing was filed \u2014 you are all set."
|
|
3201
3972
|
}
|
|
3202
3973
|
)
|
|
3203
3974
|
] }),
|
|
3204
|
-
/* @__PURE__ */ jsx3(
|
|
3205
|
-
"
|
|
3975
|
+
submitted && /* @__PURE__ */ jsx3(
|
|
3976
|
+
"div",
|
|
3206
3977
|
{
|
|
3207
|
-
style: {
|
|
3208
|
-
|
|
3978
|
+
style: {
|
|
3979
|
+
textAlign: "center",
|
|
3980
|
+
padding: "24px 0",
|
|
3981
|
+
color: t.accent,
|
|
3982
|
+
fontSize: "14px",
|
|
3983
|
+
fontWeight: 600
|
|
3984
|
+
},
|
|
3985
|
+
children: submittedText != null ? submittedText : `${reportTypeLabel} sent. Thank you!`
|
|
3209
3986
|
}
|
|
3210
3987
|
)
|
|
3211
|
-
] })
|
|
3212
|
-
|
|
3213
|
-
|
|
3214
|
-
|
|
3215
|
-
style: {
|
|
3216
|
-
textAlign: "center",
|
|
3217
|
-
padding: "24px 0",
|
|
3218
|
-
color: t.accent,
|
|
3219
|
-
fontSize: "14px",
|
|
3220
|
-
fontWeight: 600
|
|
3221
|
-
},
|
|
3222
|
-
children: submittedText != null ? submittedText : `${reportTypeLabel} sent. Thank you!`
|
|
3223
|
-
}
|
|
3224
|
-
)
|
|
3225
|
-
]
|
|
3226
|
-
}
|
|
3227
|
-
)
|
|
3988
|
+
] })
|
|
3989
|
+
}
|
|
3990
|
+
)
|
|
3991
|
+
]
|
|
3228
3992
|
}
|
|
3229
3993
|
),
|
|
3230
|
-
!submitted && phase !== "type" && phase !== "severity" && /* @__PURE__ */ jsxs3(
|
|
3994
|
+
!submitted && !showChats && phase !== "type" && phase !== "severity" && /* @__PURE__ */ jsxs3(
|
|
3231
3995
|
"div",
|
|
3232
3996
|
{
|
|
3233
3997
|
style: {
|
|
@@ -3544,8 +4308,8 @@ function AssistSheet({
|
|
|
3544
4308
|
accept: canReadPdf ? ASSIST_ATTACHMENT_ACCEPT_WITH_PDF : ASSIST_ATTACHMENT_ACCEPT,
|
|
3545
4309
|
multiple: true,
|
|
3546
4310
|
onChange: (e) => {
|
|
3547
|
-
var
|
|
3548
|
-
const picked = Array.from((
|
|
4311
|
+
var _a2;
|
|
4312
|
+
const picked = Array.from((_a2 = e.target.files) != null ? _a2 : []);
|
|
3549
4313
|
if (picked.length) {
|
|
3550
4314
|
stopAutoFile("changed attachments");
|
|
3551
4315
|
const images = picked.filter((f) => f.type.startsWith("image/")).length;
|
|
@@ -4523,20 +5287,20 @@ function initialsOf(name) {
|
|
|
4523
5287
|
}).join("");
|
|
4524
5288
|
}
|
|
4525
5289
|
function ReporterChip({
|
|
4526
|
-
reporter,
|
|
5290
|
+
reporter: reporter2,
|
|
4527
5291
|
t
|
|
4528
5292
|
}) {
|
|
4529
5293
|
var _a;
|
|
4530
5294
|
const [avatarFailed, setAvatarFailed] = useState4(false);
|
|
4531
|
-
const avatarUrl = (
|
|
5295
|
+
const avatarUrl = (reporter2 == null ? void 0 : reporter2.avatarUrl) || "";
|
|
4532
5296
|
useEffect4(() => {
|
|
4533
5297
|
setAvatarFailed(false);
|
|
4534
5298
|
}, [avatarUrl]);
|
|
4535
|
-
const name = ((_a =
|
|
5299
|
+
const name = ((_a = reporter2 == null ? void 0 : reporter2.name) == null ? void 0 : _a.trim()) || "";
|
|
4536
5300
|
const isAnonymous = !name;
|
|
4537
5301
|
const initials2 = isAnonymous ? "" : initialsOf(name);
|
|
4538
5302
|
const label = isAnonymous ? "Anonymous" : name;
|
|
4539
|
-
const title = isAnonymous ? "No reporter identity was passed to Glitchgrab \u2014 this report won't be attributed to anyone" : [name,
|
|
5303
|
+
const title = isAnonymous ? "No reporter identity was passed to Glitchgrab \u2014 this report won't be attributed to anyone" : [name, reporter2 == null ? void 0 : reporter2.email, reporter2 == null ? void 0 : reporter2.role].filter(Boolean).join(" \xB7 ");
|
|
4540
5304
|
const showAvatarImage = !!avatarUrl && !avatarFailed;
|
|
4541
5305
|
return /* @__PURE__ */ jsxs5(
|
|
4542
5306
|
"span",
|
|
@@ -4600,7 +5364,7 @@ function ReporterChip({
|
|
|
4600
5364
|
},
|
|
4601
5365
|
children: [
|
|
4602
5366
|
label,
|
|
4603
|
-
(
|
|
5367
|
+
(reporter2 == null ? void 0 : reporter2.role) ? ` \xB7 ${reporter2.role}` : ""
|
|
4604
5368
|
]
|
|
4605
5369
|
}
|
|
4606
5370
|
)
|
|
@@ -4717,11 +5481,12 @@ function ReportDialog({
|
|
|
4717
5481
|
types,
|
|
4718
5482
|
showSeverity = true,
|
|
4719
5483
|
captureScreenshot = captureDefaultScreenshot,
|
|
4720
|
-
reporter,
|
|
5484
|
+
reporter: reporter2,
|
|
4721
5485
|
onClose,
|
|
4722
5486
|
headerSlot,
|
|
4723
5487
|
reportGlitchgrabProblem,
|
|
4724
|
-
layout = "modal"
|
|
5488
|
+
layout = "modal",
|
|
5489
|
+
chatHistoryKey: chatHistoryKey2 = null
|
|
4725
5490
|
}) {
|
|
4726
5491
|
var _a;
|
|
4727
5492
|
const sheet = layout === "sheet";
|
|
@@ -4743,6 +5508,7 @@ function ReportDialog({
|
|
|
4743
5508
|
const [aiConversationId, setAiConversationId] = useState4(null);
|
|
4744
5509
|
const [issueTitle, setIssueTitle] = useState4("");
|
|
4745
5510
|
const [isEnhanced, setIsEnhanced] = useState4(false);
|
|
5511
|
+
const [enhanceError, setEnhanceError] = useState4(null);
|
|
4746
5512
|
const [originalDescription, setOriginalDescription] = useState4(
|
|
4747
5513
|
null
|
|
4748
5514
|
);
|
|
@@ -4826,15 +5592,15 @@ function ReportDialog({
|
|
|
4826
5592
|
});
|
|
4827
5593
|
};
|
|
4828
5594
|
applyInert();
|
|
4829
|
-
const
|
|
5595
|
+
const observer2 = new MutationObserver((mutations) => {
|
|
4830
5596
|
const structural = mutations.some(
|
|
4831
5597
|
(m) => m.addedNodes.length > 0 || m.removedNodes.length > 0
|
|
4832
5598
|
);
|
|
4833
5599
|
if (structural) applyInert();
|
|
4834
5600
|
});
|
|
4835
|
-
|
|
5601
|
+
observer2.observe(document.body, { childList: true, subtree: true });
|
|
4836
5602
|
return () => {
|
|
4837
|
-
|
|
5603
|
+
observer2.disconnect();
|
|
4838
5604
|
inerted.forEach((el) => el.removeAttribute("inert"));
|
|
4839
5605
|
};
|
|
4840
5606
|
}, [isOpen]);
|
|
@@ -5197,6 +5963,7 @@ function ReportDialog({
|
|
|
5197
5963
|
setSelfReportFrom(null);
|
|
5198
5964
|
setVoiceError(null);
|
|
5199
5965
|
setIsEnhanced(false);
|
|
5966
|
+
setEnhanceError(null);
|
|
5200
5967
|
setOriginalDescription(null);
|
|
5201
5968
|
setAssistOpen(false);
|
|
5202
5969
|
setAssistUsed(false);
|
|
@@ -5262,6 +6029,7 @@ function ReportDialog({
|
|
|
5262
6029
|
const sep = base.trim() ? " " : "";
|
|
5263
6030
|
setDescriptionFromVoice(base + sep + text.trim());
|
|
5264
6031
|
setValidationError(null);
|
|
6032
|
+
setEnhanceError(null);
|
|
5265
6033
|
setIsEnhanced(false);
|
|
5266
6034
|
setOriginalDescription(null);
|
|
5267
6035
|
}
|
|
@@ -5486,6 +6254,9 @@ function ReportDialog({
|
|
|
5486
6254
|
setAddedAsRelated(!!duplicateOf && result.issueNumber === duplicateOf && attachKind === "related");
|
|
5487
6255
|
const queued = result.status === "QUEUED" && !!result.message;
|
|
5488
6256
|
setQueuedMessage(queued ? (_c = result.message) != null ? _c : null : null);
|
|
6257
|
+
if (chatHistoryKey2 && aiConversationId) {
|
|
6258
|
+
markChatFiled(chatHistoryKey2, aiConversationId, `${getTypeLabel(reportType)} sent`);
|
|
6259
|
+
}
|
|
5489
6260
|
setSubmitted(true);
|
|
5490
6261
|
setDescription("");
|
|
5491
6262
|
setScreenshots([]);
|
|
@@ -6354,6 +7125,7 @@ function ReportDialog({
|
|
|
6354
7125
|
notePushToTalkEdit();
|
|
6355
7126
|
setDescription(e.target.value);
|
|
6356
7127
|
if (validationError) setValidationError(null);
|
|
7128
|
+
if (enhanceError) setEnhanceError(null);
|
|
6357
7129
|
if (isEnhanced) {
|
|
6358
7130
|
setIsEnhanced(false);
|
|
6359
7131
|
setOriginalDescription(null);
|
|
@@ -6475,6 +7247,7 @@ function ReportDialog({
|
|
|
6475
7247
|
var _a2;
|
|
6476
7248
|
if (!description.trim() || isEnhancing) return;
|
|
6477
7249
|
setIsEnhancing(true);
|
|
7250
|
+
setEnhanceError(null);
|
|
6478
7251
|
try {
|
|
6479
7252
|
const polished = await enhanceText2(
|
|
6480
7253
|
description,
|
|
@@ -6487,6 +7260,10 @@ function ReportDialog({
|
|
|
6487
7260
|
if (validationError)
|
|
6488
7261
|
setValidationError(null);
|
|
6489
7262
|
}
|
|
7263
|
+
} catch (err) {
|
|
7264
|
+
setEnhanceError(
|
|
7265
|
+
err instanceof Error && err.message ? err.message : "AI enhance isn't available right now \u2014 send your report as written."
|
|
7266
|
+
);
|
|
6490
7267
|
} finally {
|
|
6491
7268
|
setIsEnhancing(false);
|
|
6492
7269
|
}
|
|
@@ -6745,6 +7522,20 @@ function ReportDialog({
|
|
|
6745
7522
|
children: voiceError
|
|
6746
7523
|
}
|
|
6747
7524
|
),
|
|
7525
|
+
enhanceError && /* @__PURE__ */ jsx5(
|
|
7526
|
+
"p",
|
|
7527
|
+
{
|
|
7528
|
+
role: "alert",
|
|
7529
|
+
style: {
|
|
7530
|
+
color: "#ef4444",
|
|
7531
|
+
fontSize: "11px",
|
|
7532
|
+
lineHeight: 1.5,
|
|
7533
|
+
marginTop: "4px",
|
|
7534
|
+
marginBottom: 0
|
|
7535
|
+
},
|
|
7536
|
+
children: enhanceError
|
|
7537
|
+
}
|
|
7538
|
+
),
|
|
6748
7539
|
assistNotice && /* @__PURE__ */ jsx5(
|
|
6749
7540
|
"p",
|
|
6750
7541
|
{
|
|
@@ -7305,7 +8096,7 @@ function ReportDialog({
|
|
|
7305
8096
|
gap: "12px"
|
|
7306
8097
|
},
|
|
7307
8098
|
children: [
|
|
7308
|
-
/* @__PURE__ */ jsx5(ReporterChip, { reporter, t }),
|
|
8099
|
+
/* @__PURE__ */ jsx5(ReporterChip, { reporter: reporter2, t }),
|
|
7309
8100
|
reportGlitchgrabProblem ? /* @__PURE__ */ jsx5(
|
|
7310
8101
|
"button",
|
|
7311
8102
|
{
|
|
@@ -7585,6 +8376,7 @@ function ReportDialog({
|
|
|
7585
8376
|
setDuplicateKind(issueNumber && kind === "related" ? "related" : "duplicate");
|
|
7586
8377
|
},
|
|
7587
8378
|
onConversationChange: setAiConversationId,
|
|
8379
|
+
historyKey: chatHistoryKey2,
|
|
7588
8380
|
onFinish: handleClose,
|
|
7589
8381
|
rating,
|
|
7590
8382
|
onRatingChange: (value) => {
|
|
@@ -7592,7 +8384,7 @@ function ReportDialog({
|
|
|
7592
8384
|
if (validationError) setValidationError(null);
|
|
7593
8385
|
},
|
|
7594
8386
|
projectSlot: headerSlot,
|
|
7595
|
-
reporterName: (_a =
|
|
8387
|
+
reporterName: (_a = reporter2 == null ? void 0 : reporter2.name) != null ? _a : null,
|
|
7596
8388
|
description,
|
|
7597
8389
|
onDescriptionChange: (value) => {
|
|
7598
8390
|
setDescription(value);
|
|
@@ -9179,6 +9971,9 @@ function GlitchgrabProviderInner({
|
|
|
9179
9971
|
onError,
|
|
9180
9972
|
onReportSent
|
|
9181
9973
|
});
|
|
9974
|
+
if (process.env.NODE_ENV !== "development") {
|
|
9975
|
+
installHydrationCapture(reportHydrationError);
|
|
9976
|
+
}
|
|
9182
9977
|
useEffect6(() => {
|
|
9183
9978
|
if (enableBreadcrumbs) {
|
|
9184
9979
|
initBreadcrumbs(maxBreadcrumbs2, { responseBodyOrigins: responseBodyOrigins2 });
|
|
@@ -9234,7 +10029,7 @@ function GlitchgrabProviderInner({
|
|
|
9234
10029
|
return matchesIgnorePatterns(message, ignoreErrors);
|
|
9235
10030
|
};
|
|
9236
10031
|
const handleError = (event) => {
|
|
9237
|
-
var _a, _b, _c, _d, _e, _f, _g;
|
|
10032
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i;
|
|
9238
10033
|
try {
|
|
9239
10034
|
const isOpaqueCrossOrigin = event.message === "Script error." || event.message === "Script error" || !event.error && !event.filename;
|
|
9240
10035
|
if (isOpaqueCrossOrigin) {
|
|
@@ -9249,6 +10044,7 @@ function GlitchgrabProviderInner({
|
|
|
9249
10044
|
if (event.filename && EXTENSION_ORIGIN_RE.test(event.filename) || ((_a = event.error) == null ? void 0 : _a.stack) && EXTENSION_ORIGIN_RE.test(event.error.stack)) {
|
|
9250
10045
|
return;
|
|
9251
10046
|
}
|
|
10047
|
+
if (isHandledHydrationError(event.error)) return;
|
|
9252
10048
|
incrementErrorCount();
|
|
9253
10049
|
const context = captureContext(visitedPagesRef.current);
|
|
9254
10050
|
const sig = computeSignature({
|
|
@@ -9274,6 +10070,9 @@ function GlitchgrabProviderInner({
|
|
|
9274
10070
|
filename: (_e = event.filename) != null ? _e : "",
|
|
9275
10071
|
lineno: String((_f = event.lineno) != null ? _f : ""),
|
|
9276
10072
|
colno: String((_g = event.colno) != null ? _g : ""),
|
|
10073
|
+
// The root patch could not attach (React internals moved, or a
|
|
10074
|
+
// root it does not know): still label it and send the DOM context.
|
|
10075
|
+
...isHydrationError((_h = event.error) != null ? _h : event.message) ? hydrationMetadata((_i = event.error) != null ? _i : event.message) : {},
|
|
9277
10076
|
...(session == null ? void 0 : session.userId) ? { sessionUserId: session.userId } : {},
|
|
9278
10077
|
...(session == null ? void 0 : session.name) ? { sessionUserName: String(session.name) } : {},
|
|
9279
10078
|
...(session == null ? void 0 : session.email) ? { sessionUserEmail: String(session.email) } : {},
|
|
@@ -9490,21 +10289,27 @@ function GlitchgrabProviderInner({
|
|
|
9490
10289
|
() => ({ userId: signedUserId != null ? signedUserId : null, signature }),
|
|
9491
10290
|
[signedUserId, signature]
|
|
9492
10291
|
);
|
|
10292
|
+
const enhanceForDialog = useCallback3(
|
|
10293
|
+
async (text, screenshot) => {
|
|
10294
|
+
const ctx = captureContext(visitedPagesRef.current);
|
|
10295
|
+
const context = {
|
|
10296
|
+
url: ctx.url,
|
|
10297
|
+
visitedPages: ctx.visitedPages.slice(-5),
|
|
10298
|
+
breadcrumbs: ctx.breadcrumbs.slice(-10).map((b) => ({ type: b.type, message: b.message }))
|
|
10299
|
+
};
|
|
10300
|
+
return await enhanceTextOrThrow(text, token, baseUrl, screenshot, context, identity);
|
|
10301
|
+
},
|
|
10302
|
+
[token, baseUrl, identity]
|
|
10303
|
+
);
|
|
9493
10304
|
const enhance = useCallback3(
|
|
9494
10305
|
async (text, screenshot) => {
|
|
9495
10306
|
try {
|
|
9496
|
-
|
|
9497
|
-
const context = {
|
|
9498
|
-
url: ctx.url,
|
|
9499
|
-
visitedPages: ctx.visitedPages.slice(-5),
|
|
9500
|
-
breadcrumbs: ctx.breadcrumbs.slice(-10).map((b) => ({ type: b.type, message: b.message }))
|
|
9501
|
-
};
|
|
9502
|
-
return await enhanceText(text, token, baseUrl, screenshot, context, identity);
|
|
10307
|
+
return await enhanceForDialog(text, screenshot);
|
|
9503
10308
|
} catch (e) {
|
|
9504
10309
|
return text;
|
|
9505
10310
|
}
|
|
9506
10311
|
},
|
|
9507
|
-
[
|
|
10312
|
+
[enhanceForDialog]
|
|
9508
10313
|
);
|
|
9509
10314
|
const assist = useCallback3(
|
|
9510
10315
|
async (params) => {
|
|
@@ -9615,7 +10420,7 @@ function GlitchgrabProviderInner({
|
|
|
9615
10420
|
} catch (e) {
|
|
9616
10421
|
}
|
|
9617
10422
|
}, [openReportDialog]);
|
|
9618
|
-
const
|
|
10423
|
+
const reporter2 = useMemo4(() => {
|
|
9619
10424
|
var _a;
|
|
9620
10425
|
if (!session) return null;
|
|
9621
10426
|
const avatar = (_a = session.avatarUrl) != null ? _a : session.image;
|
|
@@ -9678,7 +10483,7 @@ function GlitchgrabProviderInner({
|
|
|
9678
10483
|
{
|
|
9679
10484
|
report,
|
|
9680
10485
|
sendFeedback: feedback,
|
|
9681
|
-
enhanceText: aiAssist && !aiBlockedUnsigned ?
|
|
10486
|
+
enhanceText: aiAssist && !aiBlockedUnsigned ? enhanceForDialog : void 0,
|
|
9682
10487
|
assist: aiAssist && !aiBlockedUnsigned ? assist : void 0,
|
|
9683
10488
|
findSimilarIssues: aiAssist && !aiBlockedUnsigned ? findSimilar : void 0,
|
|
9684
10489
|
readFile: aiAssist && !aiBlockedUnsigned ? readFile : void 0,
|
|
@@ -9686,7 +10491,8 @@ function GlitchgrabProviderInner({
|
|
|
9686
10491
|
transcribeAudio: aiBlockedUnsigned ? void 0 : transcribe,
|
|
9687
10492
|
types,
|
|
9688
10493
|
showSeverity,
|
|
9689
|
-
reporter,
|
|
10494
|
+
reporter: reporter2,
|
|
10495
|
+
chatHistoryKey: chatHistoryKey("sdk", token, session == null ? void 0 : session.userId),
|
|
9690
10496
|
headerSlot: projectName ? /* @__PURE__ */ jsxs7("div", { style: { fontSize: 11, color: "#9aa0a6" }, children: [
|
|
9691
10497
|
"Reporting to ",
|
|
9692
10498
|
/* @__PURE__ */ jsx7("strong", { style: { color: "#e5e5e5" }, children: projectName })
|
|
@@ -10022,6 +10828,87 @@ function useGlitchgrabActions({
|
|
|
10022
10828
|
error
|
|
10023
10829
|
};
|
|
10024
10830
|
}
|
|
10831
|
+
async function fetchGlitchgrabReportThread({
|
|
10832
|
+
token,
|
|
10833
|
+
reportId
|
|
10834
|
+
}) {
|
|
10835
|
+
var _a, _b, _c;
|
|
10836
|
+
const res = await fetch(`${BASE_URL}/api/v1/sdk/reports/${encodeURIComponent(reportId)}`, {
|
|
10837
|
+
headers: { Authorization: `Bearer ${token}` }
|
|
10838
|
+
});
|
|
10839
|
+
const data = await res.json().catch(() => ({}));
|
|
10840
|
+
if (!res.ok || !data.success) throw new Error((_a = data.error) != null ? _a : "Failed to fetch report");
|
|
10841
|
+
return { ...data.data, comments: (_c = (_b = data.data) == null ? void 0 : _b.comments) != null ? _c : [] };
|
|
10842
|
+
}
|
|
10843
|
+
async function postGlitchgrabReportComment({
|
|
10844
|
+
token,
|
|
10845
|
+
reportId,
|
|
10846
|
+
message,
|
|
10847
|
+
reporterName,
|
|
10848
|
+
reporterEmail
|
|
10849
|
+
}) {
|
|
10850
|
+
var _a;
|
|
10851
|
+
const res = await fetch(`${BASE_URL}/api/v1/sdk/reports/${encodeURIComponent(reportId)}/comments`, {
|
|
10852
|
+
method: "POST",
|
|
10853
|
+
headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/json" },
|
|
10854
|
+
body: JSON.stringify({ message, reporterName, reporterEmail })
|
|
10855
|
+
});
|
|
10856
|
+
const data = await res.json().catch(() => ({}));
|
|
10857
|
+
if (!res.ok || !data.success) throw new Error((_a = data.error) != null ? _a : "Failed to post comment");
|
|
10858
|
+
return data.data;
|
|
10859
|
+
}
|
|
10860
|
+
function useGlitchgrabReportThread({
|
|
10861
|
+
token,
|
|
10862
|
+
reportId,
|
|
10863
|
+
reporterName,
|
|
10864
|
+
reporterEmail
|
|
10865
|
+
}) {
|
|
10866
|
+
var _a;
|
|
10867
|
+
const [report, setReport] = useState8(null);
|
|
10868
|
+
const [isLoading, setIsLoading] = useState8(!!reportId);
|
|
10869
|
+
const [isFetching, setIsFetching] = useState8(false);
|
|
10870
|
+
const [isPosting, setIsPosting] = useState8(false);
|
|
10871
|
+
const [error, setError] = useState8(null);
|
|
10872
|
+
const refetch = useCallback4(async () => {
|
|
10873
|
+
if (!token || !reportId) {
|
|
10874
|
+
setReport(null);
|
|
10875
|
+
setIsLoading(false);
|
|
10876
|
+
return;
|
|
10877
|
+
}
|
|
10878
|
+
setIsFetching(true);
|
|
10879
|
+
setError(null);
|
|
10880
|
+
try {
|
|
10881
|
+
setReport(await fetchGlitchgrabReportThread({ token, reportId }));
|
|
10882
|
+
} catch (e) {
|
|
10883
|
+
setError(e instanceof Error ? e.message : "Network error");
|
|
10884
|
+
} finally {
|
|
10885
|
+
setIsLoading(false);
|
|
10886
|
+
setIsFetching(false);
|
|
10887
|
+
}
|
|
10888
|
+
}, [token, reportId]);
|
|
10889
|
+
useEffect7(() => {
|
|
10890
|
+
refetch();
|
|
10891
|
+
}, [refetch]);
|
|
10892
|
+
const addComment = useCallback4(
|
|
10893
|
+
async (message) => {
|
|
10894
|
+
if (!token || !reportId || !message.trim()) return false;
|
|
10895
|
+
setIsPosting(true);
|
|
10896
|
+
setError(null);
|
|
10897
|
+
try {
|
|
10898
|
+
await postGlitchgrabReportComment({ token, reportId, message: message.trim(), reporterName, reporterEmail });
|
|
10899
|
+
await refetch();
|
|
10900
|
+
return true;
|
|
10901
|
+
} catch (e) {
|
|
10902
|
+
setError(e instanceof Error ? e.message : "Failed to post comment");
|
|
10903
|
+
return false;
|
|
10904
|
+
} finally {
|
|
10905
|
+
setIsPosting(false);
|
|
10906
|
+
}
|
|
10907
|
+
},
|
|
10908
|
+
[token, reportId, reporterName, reporterEmail, refetch]
|
|
10909
|
+
);
|
|
10910
|
+
return { report, comments: (_a = report == null ? void 0 : report.comments) != null ? _a : [], isLoading, isFetching, isPosting, error, refetch, addComment };
|
|
10911
|
+
}
|
|
10025
10912
|
|
|
10026
10913
|
// src/use-feedback.ts
|
|
10027
10914
|
import { useState as useState9, useEffect as useEffect8, useCallback as useCallback5 } from "react";
|
|
@@ -10102,12 +10989,14 @@ export {
|
|
|
10102
10989
|
computeSignature,
|
|
10103
10990
|
enhanceText,
|
|
10104
10991
|
fetchGlitchgrabFeedback,
|
|
10992
|
+
fetchGlitchgrabReportThread,
|
|
10105
10993
|
fetchGlitchgrabReports,
|
|
10106
10994
|
getAppContext,
|
|
10107
10995
|
getBreadcrumbs,
|
|
10108
10996
|
getShortcutLabel2 as getShortcutLabel,
|
|
10109
10997
|
initBreadcrumbs,
|
|
10110
10998
|
matchesShortcut,
|
|
10999
|
+
postGlitchgrabReportComment,
|
|
10111
11000
|
sanitizeUrl,
|
|
10112
11001
|
sendFeedback,
|
|
10113
11002
|
sendLead,
|
|
@@ -10118,6 +11007,7 @@ export {
|
|
|
10118
11007
|
useGlitchgrab,
|
|
10119
11008
|
useGlitchgrabActions,
|
|
10120
11009
|
useGlitchgrabFeedback,
|
|
11010
|
+
useGlitchgrabReportThread,
|
|
10121
11011
|
useGlitchgrabReports
|
|
10122
11012
|
};
|
|
10123
11013
|
//# sourceMappingURL=index.mjs.map
|