diff --git a/src/components/layout/ErrorBoundary.tsx b/src/components/layout/ErrorBoundary.tsx
index 651a837..c280aeb 100644
--- a/src/components/layout/ErrorBoundary.tsx
+++ b/src/components/layout/ErrorBoundary.tsx
@@ -1,6 +1,8 @@
"use client";
-import React from "react";
+import React, { useState } from "react";
+import { CircleAlert } from "lucide-react";
+import { useTranslation } from "@/hooks/useTranslation";
interface ErrorBoundaryProps {
children: React.ReactNode;
@@ -10,16 +12,77 @@ interface ErrorBoundaryProps {
interface ErrorBoundaryState {
hasError: boolean;
error: Error | null;
- showDetails: boolean;
}
+/* ── Fallback UI (functional, so it can use hooks) ──────────── */
+
+function ErrorFallback({
+ error,
+ onReset,
+}: {
+ error: Error | null;
+ onReset: () => void;
+}) {
+ const { t } = useTranslation();
+ const [showDetails, setShowDetails] = useState(false);
+
+ return (
+
{
@@ -32,11 +95,7 @@ export class ErrorBoundary extends React.Component<
}
handleReset = () => {
- this.setState({ hasError: false, error: null, showDetails: false });
- };
-
- handleReload = () => {
- window.location.reload();
+ this.setState({ hasError: false, error: null });
};
render() {
@@ -44,91 +103,10 @@ export class ErrorBoundary extends React.Component<
if (this.props.fallback) {
return this.props.fallback;
}
-
return (
-
-
- {/* Error icon */}
-
-
-
-
-
- Something went wrong
-
-
- An unexpected error occurred. You can try again or reload the app.
-
-
- {/* Expandable error details */}
- {this.state.error && (
-
- )}
- {this.state.showDetails && this.state.error && (
-
- {this.state.error.message}
- {this.state.error.stack && `\n\n${this.state.error.stack}`}
-
- )}
-
- {/* Action buttons */}
-
-
-
-
-
-
+
);
}
-
return this.props.children;
}
}
-
-/** Convenience HOC to wrap any component with an ErrorBoundary */
-export function withErrorBoundary(
- Component: React.ComponentType
,
- fallback?: React.ReactNode
-) {
- const displayName = Component.displayName || Component.name || "Component";
-
- const Wrapped = (props: P) => (
-
-
-
- );
-
- Wrapped.displayName = `withErrorBoundary(${displayName})`;
- return Wrapped;
-}
diff --git a/src/components/settings/ProviderManager.tsx b/src/components/settings/ProviderManager.tsx
index 7a15173..3aa8778 100644
--- a/src/components/settings/ProviderManager.tsx
+++ b/src/components/settings/ProviderManager.tsx
@@ -146,8 +146,8 @@ const QUICK_PRESETS: QuickPreset[] = [
{
key: "glm-cn",
name: "GLM (CN)",
- description: "Zhipu GLM — China region",
- descriptionZh: "智谱 GLM — 中国区",
+ description: "Zhipu GLM Code Plan — China region",
+ descriptionZh: "智谱 GLM 编程套餐 — 中国区",
icon: ,
provider_type: "custom",
base_url: "https://open.bigmodel.cn/api/anthropic",
@@ -157,8 +157,8 @@ const QUICK_PRESETS: QuickPreset[] = [
{
key: "glm-global",
name: "GLM (Global)",
- description: "Zhipu GLM — Global region",
- descriptionZh: "智谱 GLM — 国际区",
+ description: "Zhipu GLM Code Plan — Global region",
+ descriptionZh: "智谱 GLM 编程套餐 — 国际区",
icon: ,
provider_type: "custom",
base_url: "https://api.z.ai/api/anthropic",
@@ -190,8 +190,8 @@ const QUICK_PRESETS: QuickPreset[] = [
{
key: "minimax-cn",
name: "MiniMax (CN)",
- description: "MiniMax API — China region",
- descriptionZh: "MiniMax API — 中国区",
+ description: "MiniMax Code Plan — China region",
+ descriptionZh: "MiniMax 编程套餐 — 中国区",
icon: ,
provider_type: "custom",
base_url: "https://api.minimaxi.com/anthropic",
@@ -201,8 +201,8 @@ const QUICK_PRESETS: QuickPreset[] = [
{
key: "minimax-global",
name: "MiniMax (Global)",
- description: "MiniMax API — Global region",
- descriptionZh: "MiniMax API — 国际区",
+ description: "MiniMax Code Plan — Global region",
+ descriptionZh: "MiniMax 编程套餐 — 国际区",
icon: ,
provider_type: "custom",
base_url: "https://api.minimax.io/anthropic",
@@ -563,20 +563,30 @@ export function ProviderManager() {
{t('provider.connectedProviders')}
- {/* Environment variable detection */}
- {Object.keys(envDetected).length > 0 && (
-
+ {/* Claude Code default config */}
+
+
-
{t('provider.environment')}
-
- ENV
-
+
+ Claude Code
+
+ {t('provider.default')}
+
+ {Object.keys(envDetected).length > 0 && (
+
+ ENV
+
+ )}
+
- )}
+
+ {t('provider.ccSwitchHint')}
+
+
{/* Connected provider list */}
{sorted.length > 0 ? (
diff --git a/src/i18n/en.ts b/src/i18n/en.ts
index 0bb3392..a921863 100644
--- a/src/i18n/en.ts
+++ b/src/i18n/en.ts
@@ -145,6 +145,7 @@ const en = {
'provider.disconnecting': 'Disconnecting...',
'provider.disconnectProvider': 'Disconnect Provider',
'provider.disconnectConfirm': 'Are you sure you want to disconnect "{name}"? This action cannot be undone.',
+ 'provider.ccSwitchHint': 'Claude Code configurations added via tools like cc switch may not be readable by CodePilot. We recommend re-adding your provider here.',
'provider.addProviderSection': 'Add Provider',
'provider.addProviderDesc': 'Select a provider to connect. Most presets only require an API key.',
@@ -290,6 +291,14 @@ const en = {
'common.enabled': 'Enabled',
'common.disabled': 'Disabled',
+ // ── Error boundary ────────────────────────────────────────
+ 'error.title': 'Something went wrong',
+ 'error.description': 'An unexpected error occurred. You can try again or reload the app.',
+ 'error.showDetails': 'Show details',
+ 'error.hideDetails': 'Hide details',
+ 'error.tryAgain': 'Try Again',
+ 'error.reloadApp': 'Reload App',
+
// ── CLI dynamic field labels ──────────────────────────────
'cli.loadingSettings': 'Loading settings...',
'cli.field.skipDangerousModePermissionPrompt': 'Skip Dangerous Mode Permission Prompt',
diff --git a/src/i18n/zh.ts b/src/i18n/zh.ts
index 89a0a96..7e2433d 100644
--- a/src/i18n/zh.ts
+++ b/src/i18n/zh.ts
@@ -142,6 +142,7 @@ const zh: Record
= {
'provider.disconnecting': '断开中...',
'provider.disconnectProvider': '断开提供商',
'provider.disconnectConfirm': '确定要断开"{name}"吗?此操作无法撤销。',
+ 'provider.ccSwitchHint': '通过类似 cc switch 等工具添加的 Claude Code 配置可能无法被 CodePilot 读取,建议在此处重新添加。',
'provider.addProviderSection': '添加提供商',
'provider.addProviderDesc': '选择要连接的提供商。大多数预设只需填写 API 密钥。',
@@ -287,6 +288,14 @@ const zh: Record = {
'common.enabled': '已启用',
'common.disabled': '已禁用',
+ // ── Error boundary ────────────────────────────────────────
+ 'error.title': '出错了',
+ 'error.description': '发生了意外错误。您可以重试或重新加载应用。',
+ 'error.showDetails': '显示详情',
+ 'error.hideDetails': '隐藏详情',
+ 'error.tryAgain': '重试',
+ 'error.reloadApp': '重新加载',
+
// ── CLI dynamic field labels ──────────────────────────────
'cli.loadingSettings': '加载设置中...',
'cli.field.skipDangerousModePermissionPrompt': '跳过危险模式权限提示',