summaryrefslogtreecommitdiffhomepage
path: root/packages/app/src
diff options
context:
space:
mode:
authorBrendan Allan <[email protected]>2026-05-01 11:56:31 +0800
committerGitHub <[email protected]>2026-05-01 11:56:31 +0800
commit163290bcf08eacaf8d62330b8fff92cf0701eab5 (patch)
treed4ecfafa5159dd7df9af38f1ea876ab6b148f1fb /packages/app/src
parentc68c33d4fea5b34bf2ca8529b4f54fdb58d07701 (diff)
downloadopencode-163290bcf08eacaf8d62330b8fff92cf0701eab5.tar.gz
opencode-163290bcf08eacaf8d62330b8fff92cf0701eab5.zip
desktop: sentry integration (#15300)
Co-authored-by: Jay V <[email protected]>
Diffstat (limited to 'packages/app/src')
-rw-r--r--packages/app/src/app.tsx20
-rw-r--r--packages/app/src/entry.tsx20
-rw-r--r--packages/app/src/env.d.ts4
-rw-r--r--packages/app/src/i18n/ar.ts2
-rw-r--r--packages/app/src/i18n/br.ts2
-rw-r--r--packages/app/src/i18n/bs.ts2
-rw-r--r--packages/app/src/i18n/da.ts2
-rw-r--r--packages/app/src/i18n/de.ts2
-rw-r--r--packages/app/src/i18n/en.ts2
-rw-r--r--packages/app/src/i18n/es.ts2
-rw-r--r--packages/app/src/i18n/fr.ts2
-rw-r--r--packages/app/src/i18n/ja.ts2
-rw-r--r--packages/app/src/i18n/ko.ts2
-rw-r--r--packages/app/src/i18n/no.ts2
-rw-r--r--packages/app/src/i18n/pl.ts2
-rw-r--r--packages/app/src/i18n/ru.ts2
-rw-r--r--packages/app/src/i18n/th.ts2
-rw-r--r--packages/app/src/i18n/tr.ts2
-rw-r--r--packages/app/src/i18n/zh.ts2
-rw-r--r--packages/app/src/i18n/zht.ts2
-rw-r--r--packages/app/src/pages/error.tsx22
21 files changed, 92 insertions, 8 deletions
diff --git a/packages/app/src/app.tsx b/packages/app/src/app.tsx
index bf8138fcd..3189d8025 100644
--- a/packages/app/src/app.tsx
+++ b/packages/app/src/app.tsx
@@ -1,4 +1,5 @@
import "@/index.css"
+import * as Sentry from "@sentry/solid"
import { I18nProvider } from "@opencode-ai/ui/context"
import { DialogProvider } from "@opencode-ai/ui/context/dialog"
import { FileComponentProvider } from "@opencode-ai/ui/context/file"
@@ -148,12 +149,19 @@ export function AppBaseProviders(props: ParentProps<{ locale?: Locale }>) {
>
<LanguageProvider locale={props.locale}>
<UiI18nBridge>
- <ErrorBoundary fallback={(error) => <ErrorPage error={error} />}>
- <DialogProvider>
- <MarkedProvider>
- <FileComponentProvider component={File}>{props.children}</FileComponentProvider>
- </MarkedProvider>
- </DialogProvider>
+ <ErrorBoundary
+ fallback={(error) => {
+ Sentry.captureException(error)
+ return <ErrorPage error={error} />
+ }}
+ >
+ <QueryProvider>
+ <DialogProvider>
+ <MarkedProvider>
+ <FileComponentProvider component={File}>{props.children}</FileComponentProvider>
+ </MarkedProvider>
+ </DialogProvider>
+ </QueryProvider>
</ErrorBoundary>
</UiI18nBridge>
</LanguageProvider>
diff --git a/packages/app/src/entry.tsx b/packages/app/src/entry.tsx
index b5cbed6e7..ade572c2f 100644
--- a/packages/app/src/entry.tsx
+++ b/packages/app/src/entry.tsx
@@ -1,5 +1,6 @@
// @refresh reload
+import * as Sentry from "@sentry/solid"
import { render } from "solid-js/web"
import { AppBaseProviders, AppInterface } from "@/app"
import { type Platform, PlatformProvider } from "@/context/platform"
@@ -125,6 +126,25 @@ const platform: Platform = {
setDefaultServer: writeDefaultServerUrl,
}
+if (import.meta.env.VITE_SENTRY_DSN) {
+ Sentry.init({
+ dsn: import.meta.env.VITE_SENTRY_DSN,
+ environment: import.meta.env.VITE_SENTRY_ENVIRONMENT ?? import.meta.env.MODE,
+ release: import.meta.env.VITE_SENTRY_RELEASE ?? `web@${pkg.version}`,
+ initialScope: {
+ tags: {
+ platform: "web",
+ },
+ },
+ integrations: (integrations) => {
+ return integrations.filter(
+ (i) =>
+ i.name !== "Breadcrumbs" && !(import.meta.env.OPENCODE_CHANNEL === "prod" && i.name === "GlobalHandlers"),
+ )
+ },
+ })
+}
+
if (root instanceof HTMLElement) {
const server: ServerConnection.Http = { type: "http", http: { url: getCurrentUrl() } }
render(
diff --git a/packages/app/src/env.d.ts b/packages/app/src/env.d.ts
index 9b03d336f..39f827eb6 100644
--- a/packages/app/src/env.d.ts
+++ b/packages/app/src/env.d.ts
@@ -2,6 +2,10 @@ interface ImportMetaEnv {
readonly VITE_OPENCODE_SERVER_HOST: string
readonly VITE_OPENCODE_SERVER_PORT: string
readonly VITE_OPENCODE_CHANNEL?: "dev" | "beta" | "prod"
+
+ readonly VITE_SENTRY_DSN?: string
+ readonly VITE_SENTRY_ENVIRONMENT?: string
+ readonly VITE_SENTRY_RELEASE?: string
}
interface ImportMeta {
diff --git a/packages/app/src/i18n/ar.ts b/packages/app/src/i18n/ar.ts
index 49808f3fb..405153647 100644
--- a/packages/app/src/i18n/ar.ts
+++ b/packages/app/src/i18n/ar.ts
@@ -402,6 +402,8 @@ export const dict = {
"error.page.description": "حدث خطأ أثناء تحميل التطبيق.",
"error.page.details.label": "تفاصيل الخطأ",
"error.page.action.restart": "إعادة تشغيل",
+ "error.page.action.report": "الإبلاغ عن الخطأ",
+ "error.page.action.reported": "تم الإبلاغ عن الخطأ",
"error.page.action.checking": "جارٍ التحقق...",
"error.page.action.checkUpdates": "التحقق من وجود تحديثات",
"error.page.action.updateTo": "تحديث إلى {{version}}",
diff --git a/packages/app/src/i18n/br.ts b/packages/app/src/i18n/br.ts
index 5b96ff57a..9a3a47680 100644
--- a/packages/app/src/i18n/br.ts
+++ b/packages/app/src/i18n/br.ts
@@ -403,6 +403,8 @@ export const dict = {
"error.page.description": "Ocorreu um erro ao carregar a aplicação.",
"error.page.details.label": "Detalhes do Erro",
"error.page.action.restart": "Reiniciar",
+ "error.page.action.report": "Reportar erro",
+ "error.page.action.reported": "Erro reportado",
"error.page.action.checking": "Verificando...",
"error.page.action.checkUpdates": "Verificar atualizações",
"error.page.action.updateTo": "Atualizar para {{version}}",
diff --git a/packages/app/src/i18n/bs.ts b/packages/app/src/i18n/bs.ts
index 98e565464..ae34749c3 100644
--- a/packages/app/src/i18n/bs.ts
+++ b/packages/app/src/i18n/bs.ts
@@ -449,6 +449,8 @@ export const dict = {
"error.page.description": "Došlo je do greške prilikom učitavanja aplikacije.",
"error.page.details.label": "Detalji greške",
"error.page.action.restart": "Restartuj",
+ "error.page.action.report": "Prijavi grešku",
+ "error.page.action.reported": "Greška prijavljena",
"error.page.action.checking": "Provjera...",
"error.page.action.checkUpdates": "Provjeri ažuriranja",
"error.page.action.updateTo": "Ažuriraj na {{version}}",
diff --git a/packages/app/src/i18n/da.ts b/packages/app/src/i18n/da.ts
index 5c1dcfcae..370420398 100644
--- a/packages/app/src/i18n/da.ts
+++ b/packages/app/src/i18n/da.ts
@@ -446,6 +446,8 @@ export const dict = {
"error.page.description": "Der opstod en fejl under indlæsning af applikationen.",
"error.page.details.label": "Fejldetaljer",
"error.page.action.restart": "Genstart",
+ "error.page.action.report": "Rapportér fejl",
+ "error.page.action.reported": "Fejl rapporteret",
"error.page.action.checking": "Tjekker...",
"error.page.action.checkUpdates": "Tjek for opdateringer",
"error.page.action.updateTo": "Opdater til {{version}}",
diff --git a/packages/app/src/i18n/de.ts b/packages/app/src/i18n/de.ts
index 68a4def36..532ff7c08 100644
--- a/packages/app/src/i18n/de.ts
+++ b/packages/app/src/i18n/de.ts
@@ -410,6 +410,8 @@ export const dict = {
"error.page.description": "Beim Laden der Anwendung ist ein Fehler aufgetreten.",
"error.page.details.label": "Fehlerdetails",
"error.page.action.restart": "Neustart",
+ "error.page.action.report": "Fehler melden",
+ "error.page.action.reported": "Fehler gemeldet",
"error.page.action.checking": "Prüfen...",
"error.page.action.checkUpdates": "Nach Updates suchen",
"error.page.action.updateTo": "Auf {{version}} aktualisieren",
diff --git a/packages/app/src/i18n/en.ts b/packages/app/src/i18n/en.ts
index 1d2b03db7..250d26edb 100644
--- a/packages/app/src/i18n/en.ts
+++ b/packages/app/src/i18n/en.ts
@@ -465,6 +465,8 @@ export const dict = {
"error.page.description": "An error occurred while loading the application.",
"error.page.details.label": "Error Details",
"error.page.action.restart": "Restart",
+ "error.page.action.report": "Report Error",
+ "error.page.action.reported": "Error Reported",
"error.page.action.checking": "Checking...",
"error.page.action.checkUpdates": "Check for updates",
"error.page.action.updateTo": "Update to {{version}}",
diff --git a/packages/app/src/i18n/es.ts b/packages/app/src/i18n/es.ts
index 4761cd200..cde8f3ec5 100644
--- a/packages/app/src/i18n/es.ts
+++ b/packages/app/src/i18n/es.ts
@@ -449,6 +449,8 @@ export const dict = {
"error.page.description": "Ocurrió un error al cargar la aplicación.",
"error.page.details.label": "Detalles del error",
"error.page.action.restart": "Reiniciar",
+ "error.page.action.report": "Informar error",
+ "error.page.action.reported": "Error informado",
"error.page.action.checking": "Comprobando...",
"error.page.action.checkUpdates": "Buscar actualizaciones",
"error.page.action.updateTo": "Actualizar a {{version}}",
diff --git a/packages/app/src/i18n/fr.ts b/packages/app/src/i18n/fr.ts
index f470cace4..6cea948b1 100644
--- a/packages/app/src/i18n/fr.ts
+++ b/packages/app/src/i18n/fr.ts
@@ -406,6 +406,8 @@ export const dict = {
"error.page.description": "Une erreur s'est produite lors du chargement de l'application.",
"error.page.details.label": "Détails de l'erreur",
"error.page.action.restart": "Redémarrer",
+ "error.page.action.report": "Signaler l'erreur",
+ "error.page.action.reported": "Erreur signalée",
"error.page.action.checking": "Vérification...",
"error.page.action.checkUpdates": "Vérifier les mises à jour",
"error.page.action.updateTo": "Mettre à jour vers {{version}}",
diff --git a/packages/app/src/i18n/ja.ts b/packages/app/src/i18n/ja.ts
index 51eab3d09..ec4d95b98 100644
--- a/packages/app/src/i18n/ja.ts
+++ b/packages/app/src/i18n/ja.ts
@@ -402,6 +402,8 @@ export const dict = {
"error.page.description": "アプリケーションの読み込み中にエラーが発生しました。",
"error.page.details.label": "エラー詳細",
"error.page.action.restart": "再起動",
+ "error.page.action.report": "エラーを報告",
+ "error.page.action.reported": "エラーを報告しました",
"error.page.action.checking": "確認中...",
"error.page.action.checkUpdates": "アップデートを確認",
"error.page.action.updateTo": "{{version}}にアップデート",
diff --git a/packages/app/src/i18n/ko.ts b/packages/app/src/i18n/ko.ts
index 206ae23d8..6eb064244 100644
--- a/packages/app/src/i18n/ko.ts
+++ b/packages/app/src/i18n/ko.ts
@@ -401,6 +401,8 @@ export const dict = {
"error.page.description": "애플리케이션을 로드하는 동안 오류가 발생했습니다.",
"error.page.details.label": "오류 세부 정보",
"error.page.action.restart": "다시 시작",
+ "error.page.action.report": "오류 신고",
+ "error.page.action.reported": "오류가 신고됨",
"error.page.action.checking": "확인 중...",
"error.page.action.checkUpdates": "업데이트 확인",
"error.page.action.updateTo": "{{version}} 버전으로 업데이트",
diff --git a/packages/app/src/i18n/no.ts b/packages/app/src/i18n/no.ts
index 3014e1e5d..a280a3dbf 100644
--- a/packages/app/src/i18n/no.ts
+++ b/packages/app/src/i18n/no.ts
@@ -450,6 +450,8 @@ export const dict = {
"error.page.description": "Det oppstod en feil under lasting av applikasjonen.",
"error.page.details.label": "Feildetaljer",
"error.page.action.restart": "Start på nytt",
+ "error.page.action.report": "Rapporter feil",
+ "error.page.action.reported": "Feil rapportert",
"error.page.action.checking": "Sjekker...",
"error.page.action.checkUpdates": "Se etter oppdateringer",
"error.page.action.updateTo": "Oppdater til {{version}}",
diff --git a/packages/app/src/i18n/pl.ts b/packages/app/src/i18n/pl.ts
index a555f09e3..eea33b723 100644
--- a/packages/app/src/i18n/pl.ts
+++ b/packages/app/src/i18n/pl.ts
@@ -403,6 +403,8 @@ export const dict = {
"error.page.description": "Wystąpił błąd podczas ładowania aplikacji.",
"error.page.details.label": "Szczegóły błędu",
"error.page.action.restart": "Restartuj",
+ "error.page.action.report": "Zgłoś błąd",
+ "error.page.action.reported": "Błąd zgłoszony",
"error.page.action.checking": "Sprawdzanie...",
"error.page.action.checkUpdates": "Sprawdź aktualizacje",
"error.page.action.updateTo": "Zaktualizuj do {{version}}",
diff --git a/packages/app/src/i18n/ru.ts b/packages/app/src/i18n/ru.ts
index d8a81357b..6e455220b 100644
--- a/packages/app/src/i18n/ru.ts
+++ b/packages/app/src/i18n/ru.ts
@@ -448,6 +448,8 @@ export const dict = {
"error.page.description": "Произошла ошибка при загрузке приложения.",
"error.page.details.label": "Детали ошибки",
"error.page.action.restart": "Перезапустить",
+ "error.page.action.report": "Сообщить об ошибке",
+ "error.page.action.reported": "Об ошибке сообщено",
"error.page.action.checking": "Проверка...",
"error.page.action.checkUpdates": "Проверить обновления",
"error.page.action.updateTo": "Обновить до {{version}}",
diff --git a/packages/app/src/i18n/th.ts b/packages/app/src/i18n/th.ts
index b51b9a13c..998962db9 100644
--- a/packages/app/src/i18n/th.ts
+++ b/packages/app/src/i18n/th.ts
@@ -447,6 +447,8 @@ export const dict = {
"error.page.description": "เกิดข้อผิดพลาดระหว่างการโหลดแอปพลิเคชัน",
"error.page.details.label": "รายละเอียดข้อผิดพลาด",
"error.page.action.restart": "รีสตาร์ท",
+ "error.page.action.report": "รายงานข้อผิดพลาด",
+ "error.page.action.reported": "รายงานข้อผิดพลาดแล้ว",
"error.page.action.checking": "กำลังตรวจสอบ...",
"error.page.action.checkUpdates": "ตรวจสอบการอัปเดต",
"error.page.action.updateTo": "อัปเดตเป็น {{version}}",
diff --git a/packages/app/src/i18n/tr.ts b/packages/app/src/i18n/tr.ts
index 0284e908b..4d006a43b 100644
--- a/packages/app/src/i18n/tr.ts
+++ b/packages/app/src/i18n/tr.ts
@@ -452,6 +452,8 @@ export const dict = {
"error.page.description": "Uygulama yüklenirken bir hata oluştu.",
"error.page.details.label": "Hata Detayları",
"error.page.action.restart": "Yeniden Başlat",
+ "error.page.action.report": "Hatayı Bildir",
+ "error.page.action.reported": "Hata Bildirildi",
"error.page.action.checking": "Kontrol ediliyor...",
"error.page.action.checkUpdates": "Güncellemeleri kontrol et",
"error.page.action.updateTo": "{{version}} sürümüne güncelle",
diff --git a/packages/app/src/i18n/zh.ts b/packages/app/src/i18n/zh.ts
index e9d0fa471..a422a5d61 100644
--- a/packages/app/src/i18n/zh.ts
+++ b/packages/app/src/i18n/zh.ts
@@ -452,6 +452,8 @@ export const dict = {
"error.page.description": "加载应用程序时发生错误。",
"error.page.details.label": "错误详情",
"error.page.action.restart": "重启",
+ "error.page.action.report": "上报错误",
+ "error.page.action.reported": "错误已上报",
"error.page.action.checking": "检查中...",
"error.page.action.checkUpdates": "检查更新",
"error.page.action.updateTo": "更新到 {{version}}",
diff --git a/packages/app/src/i18n/zht.ts b/packages/app/src/i18n/zht.ts
index ff6392d25..7d894a83e 100644
--- a/packages/app/src/i18n/zht.ts
+++ b/packages/app/src/i18n/zht.ts
@@ -445,6 +445,8 @@ export const dict = {
"error.page.description": "載入應用程式時發生錯誤。",
"error.page.details.label": "錯誤詳情",
"error.page.action.restart": "重新啟動",
+ "error.page.action.report": "回報錯誤",
+ "error.page.action.reported": "已回報錯誤",
"error.page.action.checking": "檢查中...",
"error.page.action.checkUpdates": "檢查更新",
"error.page.action.updateTo": "更新到 {{version}}",
diff --git a/packages/app/src/pages/error.tsx b/packages/app/src/pages/error.tsx
index ba0045ec9..5f3d7baa6 100644
--- a/packages/app/src/pages/error.tsx
+++ b/packages/app/src/pages/error.tsx
@@ -1,7 +1,8 @@
import { TextField } from "@opencode-ai/ui/text-field"
+import * as Sentry from "@sentry/solid"
import { Logo } from "@opencode-ai/ui/logo"
import { Button } from "@opencode-ai/ui/button"
-import { Component, Show } from "solid-js"
+import { Component, createSignal, Show } from "solid-js"
import { createStore } from "solid-js/store"
import { usePlatform } from "@/context/platform"
import { useLanguage } from "@/context/language"
@@ -270,10 +271,27 @@ export const ErrorPage: Component<ErrorPageProps> = (props) => {
label={language.t("error.page.details.label")}
hideLabel
/>
- <div class="flex items-center gap-3">
+ <div class="flex flex-row items-center justify-center gap-3 flex-wrap max-w-64">
<Button size="large" onClick={platform.restart}>
{language.t("error.page.action.restart")}
</Button>
+ <Show when={Sentry.isEnabled}>
+ {(_) => {
+ const [reported, setReported] = createSignal(false)
+ return (
+ <Button
+ size="large"
+ disabled={reported()}
+ onClick={() => {
+ Sentry.captureException(props.error)
+ setReported(true)
+ }}
+ >
+ {language.t(reported() ? "error.page.action.reported" : "error.page.action.report")}
+ </Button>
+ )
+ }}
+ </Show>
<Show when={platform.checkUpdate}>
<Show
when={store.version}