feat(desktop): error card offers Nous support link on Portal-auth sessions
Sessions running on provider 'nous' get a 'Nous support' action on the failed-turn card, opening the portal help hub (https://portal.nousresearch.com/help — docs, Discord, GitHub) in the external browser. All five locales + docs updated.
This commit is contained in:
@@ -31,6 +31,7 @@ import { Codicon } from '@/components/ui/codicon'
|
||||
import { CopyButton } from '@/components/ui/copy-button'
|
||||
import { useI18n } from '@/i18n'
|
||||
import { type ErrorSurface, formatErrorDiagnostics } from '@/lib/error-surface'
|
||||
import { openExternalLink } from '@/lib/external-link'
|
||||
import { triggerHaptic } from '@/lib/haptics'
|
||||
import { AudioLines, GitForkIcon, Loader2Icon, RefreshCwIcon, SmilePlusIcon, VolumeXIcon, XIcon } from '@/lib/icons'
|
||||
import { extractPreviewTargets } from '@/lib/preview-targets'
|
||||
@@ -39,13 +40,17 @@ import { useEnterAnimation } from '@/lib/use-enter-animation'
|
||||
import { cn } from '@/lib/utils'
|
||||
import { playSpeechText, stopVoicePlayback } from '@/lib/voice-playback'
|
||||
import { notifyError } from '@/store/notifications'
|
||||
import { $currentModel } from '@/store/session'
|
||||
import { $currentModel, $currentProvider } from '@/store/session'
|
||||
import { $voicePlayback } from '@/store/voice-playback'
|
||||
|
||||
// Stable empty identity for the settled-parts selector — a fresh [] per render
|
||||
// would re-derive the changed-files card on every message re-render.
|
||||
const EMPTY_PARTS: readonly unknown[] = []
|
||||
|
||||
// Nous Portal's help hub (docs, Discord, GitHub, support) — the error card's
|
||||
// "Nous support" action for sessions running on Portal auth.
|
||||
const NOUS_SUPPORT_URL = 'https://portal.nousresearch.com/help'
|
||||
|
||||
// PERF: hoisted to module scope so the element OBJECT is identical on every
|
||||
// render of every assistant message. React bails out of re-rendering a child
|
||||
// whose element identity is unchanged, so a status flip on the message root
|
||||
@@ -490,6 +495,13 @@ const ErrorRecoveryActions: FC = () => {
|
||||
// child mounts only when one is (see SwitchProviderAction).
|
||||
const inRouter = useInRouterContext()
|
||||
const model = useStore($currentModel)
|
||||
const provider = useStore($currentProvider)
|
||||
|
||||
// Nous Portal users get a direct line to Nous support (docs/Discord/GitHub
|
||||
// hub behind their portal account). Provider === 'nous' means the session
|
||||
// runs on Portal auth — the "logged in" signal that's available
|
||||
// synchronously without an extra billing query per error card.
|
||||
const showNousSupport = provider.trim().toLowerCase() === 'nous'
|
||||
|
||||
// Retry = assistant-ui reload (same wiring as the footer's refresh action):
|
||||
// re-runs the failed turn's prompt in place. Suppressed when the classifier
|
||||
@@ -541,6 +553,15 @@ const ErrorRecoveryActions: FC = () => {
|
||||
</ActionBarPrimitive.Reload>
|
||||
)}
|
||||
{showSwitchProvider && inRouter && <SwitchProviderAction label={copy.errorSwitchProvider} />}
|
||||
{showNousSupport && (
|
||||
<button
|
||||
className="aui-error-action"
|
||||
onClick={() => openExternalLink(NOUS_SUPPORT_URL)}
|
||||
type="button"
|
||||
>
|
||||
{copy.errorNousSupport}
|
||||
</button>
|
||||
)}
|
||||
{window.hermesDesktop?.logsRoot && (
|
||||
<button className="aui-error-action" onClick={() => void openLogs()} type="button">
|
||||
{copy.errorOpenLogs}
|
||||
|
||||
@@ -2449,6 +2449,7 @@ export const ar = defineLocale({
|
||||
errorSwitchProvider: 'تبديل المزوّد',
|
||||
errorOpenLogs: 'فتح السجلات',
|
||||
errorOpenLogsFailed: 'تعذّر فتح مجلد السجلات',
|
||||
errorNousSupport: 'دعم Nous',
|
||||
errorCopyDiagnostics: 'نسخ التشخيصات',
|
||||
filesChanged: count => `${count} ملفات تم تغييرها`,
|
||||
reviewChanges: 'مراجعة',
|
||||
|
||||
@@ -3094,6 +3094,7 @@ export const en: Translations = {
|
||||
errorSwitchProvider: 'Switch provider',
|
||||
errorOpenLogs: 'Open logs',
|
||||
errorOpenLogsFailed: 'Could not open the logs folder',
|
||||
errorNousSupport: 'Nous support',
|
||||
errorCopyDiagnostics: 'Copy diagnostics',
|
||||
filesChanged: count => (count === 1 ? '1 file changed' : `${count} files changed`),
|
||||
reviewChanges: 'Review',
|
||||
|
||||
@@ -2746,6 +2746,7 @@ export const ja = defineLocale({
|
||||
errorSwitchProvider: 'プロバイダーを切り替え',
|
||||
errorOpenLogs: 'ログを開く',
|
||||
errorOpenLogsFailed: 'ログフォルダを開けませんでした',
|
||||
errorNousSupport: 'Nousサポート',
|
||||
errorCopyDiagnostics: '診断情報をコピー',
|
||||
filesChanged: count => `${count} 件のファイルを変更`,
|
||||
reviewChanges: 'レビュー',
|
||||
|
||||
@@ -2665,6 +2665,7 @@ export interface Translations {
|
||||
errorSwitchProvider: string
|
||||
errorOpenLogs: string
|
||||
errorOpenLogsFailed: string
|
||||
errorNousSupport: string
|
||||
errorCopyDiagnostics: string
|
||||
filesChanged: (count: number) => string
|
||||
reviewChanges: string
|
||||
|
||||
@@ -2656,6 +2656,7 @@ export const zhHant = defineLocale({
|
||||
errorSwitchProvider: '切換服務商',
|
||||
errorOpenLogs: '開啟日誌',
|
||||
errorOpenLogsFailed: '無法開啟日誌資料夾',
|
||||
errorNousSupport: 'Nous 支援',
|
||||
errorCopyDiagnostics: '複製診斷資訊',
|
||||
filesChanged: count => `${count} 個檔案已變更`,
|
||||
reviewChanges: '檢視',
|
||||
|
||||
@@ -3258,6 +3258,7 @@ export const zh: Translations = {
|
||||
errorSwitchProvider: '切换服务商',
|
||||
errorOpenLogs: '打开日志',
|
||||
errorOpenLogsFailed: '无法打开日志文件夹',
|
||||
errorNousSupport: 'Nous 支持',
|
||||
errorCopyDiagnostics: '复制诊断信息',
|
||||
filesChanged: count => `${count} 个文件已更改`,
|
||||
reviewChanges: '查看',
|
||||
|
||||
@@ -420,6 +420,9 @@ generic error toast. The card offers recovery actions matched to the failure:
|
||||
deterministically reproduce the failure, e.g. a content-policy rejection).
|
||||
- **Switch provider** — jumps to Settings → Models for provider, endpoint,
|
||||
auth, and billing failures.
|
||||
- **Nous support** — shown when the session runs on Nous Portal auth; opens
|
||||
the [portal help hub](https://portal.nousresearch.com/help) (docs, Discord,
|
||||
GitHub) in your browser.
|
||||
- **Open logs** — opens `HERMES_HOME/logs` in your file manager.
|
||||
- **Copy diagnostics** — copies a compact plain-text summary (layer, code,
|
||||
provider/model, error message) you can paste into a bug report or Discord.
|
||||
|
||||
Reference in New Issue
Block a user