glitchgrab 1.58.3 → 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/dist/index.mjs CHANGED
@@ -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
- const response = await fetch(url, {
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
- return text;
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.");
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;
740
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;
@@ -5494,6 +5508,7 @@ function ReportDialog({
5494
5508
  const [aiConversationId, setAiConversationId] = useState4(null);
5495
5509
  const [issueTitle, setIssueTitle] = useState4("");
5496
5510
  const [isEnhanced, setIsEnhanced] = useState4(false);
5511
+ const [enhanceError, setEnhanceError] = useState4(null);
5497
5512
  const [originalDescription, setOriginalDescription] = useState4(
5498
5513
  null
5499
5514
  );
@@ -5948,6 +5963,7 @@ function ReportDialog({
5948
5963
  setSelfReportFrom(null);
5949
5964
  setVoiceError(null);
5950
5965
  setIsEnhanced(false);
5966
+ setEnhanceError(null);
5951
5967
  setOriginalDescription(null);
5952
5968
  setAssistOpen(false);
5953
5969
  setAssistUsed(false);
@@ -6013,6 +6029,7 @@ function ReportDialog({
6013
6029
  const sep = base.trim() ? " " : "";
6014
6030
  setDescriptionFromVoice(base + sep + text.trim());
6015
6031
  setValidationError(null);
6032
+ setEnhanceError(null);
6016
6033
  setIsEnhanced(false);
6017
6034
  setOriginalDescription(null);
6018
6035
  }
@@ -7108,6 +7125,7 @@ function ReportDialog({
7108
7125
  notePushToTalkEdit();
7109
7126
  setDescription(e.target.value);
7110
7127
  if (validationError) setValidationError(null);
7128
+ if (enhanceError) setEnhanceError(null);
7111
7129
  if (isEnhanced) {
7112
7130
  setIsEnhanced(false);
7113
7131
  setOriginalDescription(null);
@@ -7229,6 +7247,7 @@ function ReportDialog({
7229
7247
  var _a2;
7230
7248
  if (!description.trim() || isEnhancing) return;
7231
7249
  setIsEnhancing(true);
7250
+ setEnhanceError(null);
7232
7251
  try {
7233
7252
  const polished = await enhanceText2(
7234
7253
  description,
@@ -7241,6 +7260,10 @@ function ReportDialog({
7241
7260
  if (validationError)
7242
7261
  setValidationError(null);
7243
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
+ );
7244
7267
  } finally {
7245
7268
  setIsEnhancing(false);
7246
7269
  }
@@ -7499,6 +7522,20 @@ function ReportDialog({
7499
7522
  children: voiceError
7500
7523
  }
7501
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
+ ),
7502
7539
  assistNotice && /* @__PURE__ */ jsx5(
7503
7540
  "p",
7504
7541
  {
@@ -10252,21 +10289,27 @@ function GlitchgrabProviderInner({
10252
10289
  () => ({ userId: signedUserId != null ? signedUserId : null, signature }),
10253
10290
  [signedUserId, signature]
10254
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
+ );
10255
10304
  const enhance = useCallback3(
10256
10305
  async (text, screenshot) => {
10257
10306
  try {
10258
- const ctx = captureContext(visitedPagesRef.current);
10259
- const context = {
10260
- url: ctx.url,
10261
- visitedPages: ctx.visitedPages.slice(-5),
10262
- breadcrumbs: ctx.breadcrumbs.slice(-10).map((b) => ({ type: b.type, message: b.message }))
10263
- };
10264
- return await enhanceText(text, token, baseUrl, screenshot, context, identity);
10307
+ return await enhanceForDialog(text, screenshot);
10265
10308
  } catch (e) {
10266
10309
  return text;
10267
10310
  }
10268
10311
  },
10269
- [token, baseUrl, identity]
10312
+ [enhanceForDialog]
10270
10313
  );
10271
10314
  const assist = useCallback3(
10272
10315
  async (params) => {
@@ -10440,7 +10483,7 @@ function GlitchgrabProviderInner({
10440
10483
  {
10441
10484
  report,
10442
10485
  sendFeedback: feedback,
10443
- enhanceText: aiAssist && !aiBlockedUnsigned ? enhance : void 0,
10486
+ enhanceText: aiAssist && !aiBlockedUnsigned ? enhanceForDialog : void 0,
10444
10487
  assist: aiAssist && !aiBlockedUnsigned ? assist : void 0,
10445
10488
  findSimilarIssues: aiAssist && !aiBlockedUnsigned ? findSimilar : void 0,
10446
10489
  readFile: aiAssist && !aiBlockedUnsigned ? readFile : void 0,
@@ -10785,6 +10828,87 @@ function useGlitchgrabActions({
10785
10828
  error
10786
10829
  };
10787
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
+ }
10788
10912
 
10789
10913
  // src/use-feedback.ts
10790
10914
  import { useState as useState9, useEffect as useEffect8, useCallback as useCallback5 } from "react";
@@ -10865,12 +10989,14 @@ export {
10865
10989
  computeSignature,
10866
10990
  enhanceText,
10867
10991
  fetchGlitchgrabFeedback,
10992
+ fetchGlitchgrabReportThread,
10868
10993
  fetchGlitchgrabReports,
10869
10994
  getAppContext,
10870
10995
  getBreadcrumbs,
10871
10996
  getShortcutLabel2 as getShortcutLabel,
10872
10997
  initBreadcrumbs,
10873
10998
  matchesShortcut,
10999
+ postGlitchgrabReportComment,
10874
11000
  sanitizeUrl,
10875
11001
  sendFeedback,
10876
11002
  sendLead,
@@ -10881,6 +11007,7 @@ export {
10881
11007
  useGlitchgrab,
10882
11008
  useGlitchgrabActions,
10883
11009
  useGlitchgrabFeedback,
11010
+ useGlitchgrabReportThread,
10884
11011
  useGlitchgrabReports
10885
11012
  };
10886
11013
  //# sourceMappingURL=index.mjs.map