+ {state.phase === 'consent' || state.phase === 'uploading' ? (
+ <>
+
+
+
+ {copy.title}
+
+
+ {copy.privacyNotice}
+
+
+
+
+
+
+ >
+ ) : state.phase === 'error' ? (
+ <>
+
+ {copy.failedTitle}
+
+ {state.error}
+ {'\n'}
+ {copy.failedHint}
+
+
+
+
+
+ >
+ ) : (
+ <>
+
+ {copy.doneTitle}
+ {copy.doneDescription}
+
+ {state.result?.viewUrl && (
+
+
+ {state.result.viewUrl}
+
+
+
+ )}
+ {copy.handoffLead}
+
+ {SUPPORT_LINKS.map(link => (
+
+ ))}
+
+
+
+
+ >
+ )}
+
+
+ )
+}
diff --git a/apps/desktop/src/i18n/ar.ts b/apps/desktop/src/i18n/ar.ts
index a30db33914..89fce6ff1a 100644
--- a/apps/desktop/src/i18n/ar.ts
+++ b/apps/desktop/src/i18n/ar.ts
@@ -1,6 +1,26 @@
import { defineLocale } from './define-locale'
export const ar = defineLocale({
+ sendDiagnostics: {
+ title: 'إرسال التشخيصات إلى Nous',
+ privacyNotice:
+ 'سيؤدي هذا إلى رفع حزمة تصحيح إلى التخزين الداخلي لدى Nous (ليست لصيقة عامة). تتضمن معلومات النظام (نظام التشغيل، الإصدارات، المزوّد — وليس مفاتيح API الخاصة بك أبداً) وسجلات حديثة للوكيل والبوابة وسطح المكتب، وقد تحتوي على محتوى المحادثات ومسارات الملفات. تُحجب الأسرار قبل الرفع. لا يمكن الاطلاع عليها إلا لموظفي Nous، وتُحذف تلقائياً بعد 14 يوماً.',
+ upload: 'رفع',
+ uploading: 'جارٍ الرفع…',
+ cancel: 'إلغاء',
+ close: 'إغلاق',
+ copyLink: 'نسخ الرابط',
+ doneTitle: 'تم إرسال التشخيصات',
+ doneDescription: 'تم رفع الحزمة بشكل خاص. شارك الرابط أدناه في محادثة الدعم لكي يتمكن الفريق من رؤية سجلاتك.',
+ failedTitle: 'فشل الرفع',
+ failedHint: 'يمكنك أيضاً تشغيل `hermes debug share --nous` من الطرفية، أو `hermes debug share --local` لعرض التقرير دون رفعه.',
+ handoffLead: 'تابع النقاش في:',
+ links: {
+ github: 'GitHub Issues',
+ portal: 'دعم بوابة Nous',
+ discord: 'Discord'
+ }
+ },
common: {
apply: 'تطبيق',
back: 'رجوع',
@@ -2457,6 +2477,7 @@ export const ar = defineLocale({
errorOpenLogsFailed: 'تعذّر فتح مجلد السجلات',
errorOpenDesktopLogs: 'فتح سجلات سطح المكتب',
errorCopyDiagnostics: 'نسخ تفاصيل الخطأ',
+ errorSendDiagnostics: 'إرسال التشخيصات',
filesChanged: count => `${count} ملفات تم تغييرها`,
reviewChanges: 'مراجعة',
readAloudFailed: 'فشلت القراءة بصوت عال',
diff --git a/apps/desktop/src/i18n/en.ts b/apps/desktop/src/i18n/en.ts
index 1adb019c81..5b2b93ac92 100644
--- a/apps/desktop/src/i18n/en.ts
+++ b/apps/desktop/src/i18n/en.ts
@@ -210,6 +210,27 @@ export const en: Translations = {
dismiss: 'Dismiss'
},
+ sendDiagnostics: {
+ title: 'Send diagnostics to Nous',
+ privacyNotice:
+ 'This uploads a debug bundle to Nous-internal storage (not a public paste). It includes system info (OS, versions, provider — never your API keys) and recent agent, gateway, and desktop logs, which may contain conversation content and file paths. Secrets are redacted before upload. Only Nous staff can view it, and it auto-deletes after 14 days.',
+ upload: 'Upload',
+ uploading: 'Uploading…',
+ cancel: 'Cancel',
+ close: 'Close',
+ copyLink: 'Copy link',
+ doneTitle: 'Diagnostics sent',
+ doneDescription: 'Your bundle was uploaded privately. Share the link below in your support thread so the team can see your logs.',
+ failedTitle: 'Upload failed',
+ failedHint: 'You can also run `hermes debug share --nous` from a terminal, or `hermes debug share --local` to print the report without uploading.',
+ handoffLead: 'Pick up the discussion in:',
+ links: {
+ github: 'GitHub Issues',
+ portal: 'Nous Portal Support',
+ discord: 'Discord'
+ }
+ },
+
titlebar: {
hideSidebar: 'Hide sidebar',
showSidebar: 'Show sidebar',
@@ -3103,6 +3124,7 @@ export const en: Translations = {
errorOpenLogsFailed: 'Could not open the logs folder',
errorOpenDesktopLogs: 'Open Desktop logs',
errorCopyDiagnostics: 'Copy error details',
+ errorSendDiagnostics: 'Send diagnostics',
filesChanged: count => (count === 1 ? '1 file changed' : `${count} files changed`),
reviewChanges: 'Review',
readAloudFailed: 'Read aloud failed',
diff --git a/apps/desktop/src/i18n/ja.ts b/apps/desktop/src/i18n/ja.ts
index 5e522df6dd..4dc433fae2 100644
--- a/apps/desktop/src/i18n/ja.ts
+++ b/apps/desktop/src/i18n/ja.ts
@@ -211,6 +211,27 @@ export const ja = defineLocale({
dismiss: '閉じる'
},
+ sendDiagnostics: {
+ title: 'Nous に診断情報を送信',
+ privacyNotice:
+ 'デバッグバンドルを Nous 内部ストレージにアップロードします(公開ペーストではありません)。システム情報(OS、バージョン、プロバイダー — API キーは含まれません)と、最近のエージェント/ゲートウェイ/デスクトップのログ(会話内容やファイルパスを含む場合があります)が含まれます。シークレットはアップロード前にマスクされます。閲覧できるのは Nous スタッフのみで、14 日後に自動削除されます。',
+ upload: 'アップロード',
+ uploading: 'アップロード中…',
+ cancel: 'キャンセル',
+ close: '閉じる',
+ copyLink: 'リンクをコピー',
+ doneTitle: '診断情報を送信しました',
+ doneDescription: 'バンドルは非公開でアップロードされました。サポートスレッドで以下のリンクを共有すると、チームがログを確認できます。',
+ failedTitle: 'アップロードに失敗しました',
+ failedHint: 'ターミナルから `hermes debug share --nous` を実行するか、`hermes debug share --local` でアップロードせずにレポートを表示することもできます。',
+ handoffLead: '続きは次の場所で:',
+ links: {
+ github: 'GitHub Issues',
+ portal: 'Nous Portal サポート',
+ discord: 'Discord'
+ }
+ },
+
titlebar: {
hideSidebar: 'サイドバーを非表示',
showSidebar: 'サイドバーを表示',
@@ -2755,6 +2776,7 @@ export const ja = defineLocale({
errorOpenLogsFailed: 'ログフォルダを開けませんでした',
errorOpenDesktopLogs: 'デスクトップのログを開く',
errorCopyDiagnostics: 'エラー詳細をコピー',
+ errorSendDiagnostics: '診断情報を送信',
filesChanged: count => `${count} 件のファイルを変更`,
reviewChanges: 'レビュー',
readAloudFailed: '読み上げに失敗しました',
diff --git a/apps/desktop/src/i18n/types.ts b/apps/desktop/src/i18n/types.ts
index 4440e5134f..0bd5967ca8 100644
--- a/apps/desktop/src/i18n/types.ts
+++ b/apps/desktop/src/i18n/types.ts
@@ -250,6 +250,26 @@ export interface Translations {
dismiss: string
}
+ sendDiagnostics: {
+ title: string
+ privacyNotice: string
+ upload: string
+ uploading: string
+ cancel: string
+ close: string
+ copyLink: string
+ doneTitle: string
+ doneDescription: string
+ failedTitle: string
+ failedHint: string
+ handoffLead: string
+ links: {
+ discord: string
+ github: string
+ portal: string
+ }
+ }
+
titlebar: {
hideSidebar: string
showSidebar: string
@@ -2672,6 +2692,7 @@ export interface Translations {
errorOpenLogsFailed: string
errorOpenDesktopLogs: string
errorCopyDiagnostics: string
+ errorSendDiagnostics: string
filesChanged: (count: number) => string
reviewChanges: string
readAloudFailed: string
diff --git a/apps/desktop/src/i18n/zh-hant.ts b/apps/desktop/src/i18n/zh-hant.ts
index 593ab6bdb4..7878988cf4 100644
--- a/apps/desktop/src/i18n/zh-hant.ts
+++ b/apps/desktop/src/i18n/zh-hant.ts
@@ -204,6 +204,27 @@ export const zhHant = defineLocale({
dismiss: '忽略'
},
+ sendDiagnostics: {
+ title: '向 Nous 傳送診斷資訊',
+ privacyNotice:
+ '這會將偵錯套件上傳到 Nous 內部儲存空間(並非公開貼上板)。內容包括系統資訊(作業系統、版本、服務商 — 絕不包含您的 API 金鑰)以及最近的 agent、gateway 與桌面端日誌(可能包含對話內容與檔案路徑)。上傳前會先遮罩機密資訊。僅 Nous 員工可檢視,14 天後自動刪除。',
+ upload: '上傳',
+ uploading: '上傳中…',
+ cancel: '取消',
+ close: '關閉',
+ copyLink: '複製連結',
+ doneTitle: '診斷資訊已傳送',
+ doneDescription: '偵錯套件已私密上傳。在您的支援討論串中分享以下連結,團隊即可檢視您的日誌。',
+ failedTitle: '上傳失敗',
+ failedHint: '您也可以在終端機執行 `hermes debug share --nous`,或執行 `hermes debug share --local` 在不上傳的情況下檢視報告。',
+ handoffLead: '在以下位置繼續討論:',
+ links: {
+ github: 'GitHub Issues',
+ portal: 'Nous Portal 支援',
+ discord: 'Discord'
+ }
+ },
+
titlebar: {
hideSidebar: '隱藏側邊欄',
showSidebar: '顯示側邊欄',
@@ -2664,6 +2685,7 @@ export const zhHant = defineLocale({
errorOpenLogsFailed: '無法開啟日誌資料夾',
errorOpenDesktopLogs: '開啟桌面端日誌',
errorCopyDiagnostics: '複製錯誤詳細資訊',
+ errorSendDiagnostics: '傳送診斷資訊',
filesChanged: count => `${count} 個檔案已變更`,
reviewChanges: '檢視',
readAloudFailed: '朗讀失敗',
diff --git a/apps/desktop/src/i18n/zh.ts b/apps/desktop/src/i18n/zh.ts
index 4fa78ec6a0..b9286a06c6 100644
--- a/apps/desktop/src/i18n/zh.ts
+++ b/apps/desktop/src/i18n/zh.ts
@@ -204,6 +204,27 @@ export const zh: Translations = {
dismiss: '忽略'
},
+ sendDiagnostics: {
+ title: '向 Nous 发送诊断信息',
+ privacyNotice:
+ '这会将调试包上传到 Nous 内部存储(并非公开粘贴板)。内容包括系统信息(操作系统、版本、服务商 — 绝不包含您的 API 密钥)以及最近的 agent、gateway 和桌面端日志(可能包含对话内容与文件路径)。上传前会先脱敏。仅 Nous 员工可查看,14 天后自动删除。',
+ upload: '上传',
+ uploading: '上传中…',
+ cancel: '取消',
+ close: '关闭',
+ copyLink: '复制链接',
+ doneTitle: '诊断信息已发送',
+ doneDescription: '调试包已私密上传。在您的支持会话中分享以下链接,团队即可查看您的日志。',
+ failedTitle: '上传失败',
+ failedHint: '您也可以在终端运行 `hermes debug share --nous`,或运行 `hermes debug share --local` 在不上传的情况下查看报告。',
+ handoffLead: '在以下位置继续讨论:',
+ links: {
+ github: 'GitHub Issues',
+ portal: 'Nous Portal 支持',
+ discord: 'Discord'
+ }
+ },
+
titlebar: {
hideSidebar: '隐藏侧边栏',
showSidebar: '显示侧边栏',
@@ -3266,6 +3287,7 @@ export const zh: Translations = {
errorOpenLogsFailed: '无法打开日志文件夹',
errorOpenDesktopLogs: '打开桌面端日志',
errorCopyDiagnostics: '复制错误详情',
+ errorSendDiagnostics: '发送诊断信息',
filesChanged: count => `${count} 个文件已更改`,
reviewChanges: '查看',
readAloudFailed: '朗读失败',
diff --git a/apps/desktop/src/store/send-diagnostics.test.ts b/apps/desktop/src/store/send-diagnostics.test.ts
new file mode 100644
index 0000000000..b69e1951f9
--- /dev/null
+++ b/apps/desktop/src/store/send-diagnostics.test.ts
@@ -0,0 +1,144 @@
+import { afterEach, describe, expect, it, vi } from 'vitest'
+
+import { $gateway } from '@/store/gateway'
+import {
+ $sendDiagnostics,
+ confirmSendDiagnostics,
+ dismissSendDiagnostics,
+ requestSendDiagnostics
+} from '@/store/send-diagnostics'
+
+function stubGateway(request: (method: string, params?: Record