feat: add Codex OAuth login and fix channel config display

- Add OpenAI Codex Device Code Flow login (backend polling + frontend modal)
- Codex provider integrated into preset dropdown (hides URL/API key fields)
- Sync provider model catalogs with Hermes system
- Fix channel config not displaying on first visit (wait for data load)
- Fix sidebar model list not refreshing after adding provider
- Add autocomplete="off" to API key input to prevent browser autofill

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
ekko
2026-04-17 23:11:57 +08:00
parent 26bb821e29
commit 9979871550
19 changed files with 722 additions and 6 deletions
+7
View File
@@ -14,6 +14,7 @@ export default {
common: {
loading: 'Laden...',
cancel: 'Abbrechen',
retry: 'Erneutern',
delete: 'Loschen',
edit: 'Bearbeiten',
save: 'Speichern',
@@ -195,6 +196,12 @@ export default {
providerDeleted: 'Anbieter geloscht',
deleteProvider: 'Anbieter loschen',
deleteConfirm: 'Mochten Sie "{name}" wirklich loschen?',
codexLoginTitle: 'OpenAI Codex Anmeldung',
codexWaiting: 'Geben Sie diesen Code auf der Autorisierungsseite ein, um sich anzumelden:',
codexCopyCode: 'Code kopiert',
codexOpenLink: 'Autorisierungsseite öffnen',
codexApproved: 'Anmeldung erfolgreich',
codexExpired: 'Die Autorisierung ist abgelaufen. Bitte versuchen Sie es erneut.',
noProviders: 'Keine Anbieter gefunden. Fugen Sie einen benutzerdefinierten Anbieter hinzu, um zu beginnen.',
builtIn: 'Integriert',
customType: 'Benutzerdefiniert',
+7
View File
@@ -17,6 +17,7 @@ export default {
delete: 'Delete',
edit: 'Edit',
save: 'Save',
retry: 'Retry',
saved: 'Saved',
update: 'Update',
create: 'Create',
@@ -195,6 +196,12 @@ export default {
providerDeleted: 'Provider deleted',
deleteProvider: 'Delete Provider',
deleteConfirm: 'Are you sure you want to delete "{name}"?',
codexLoginTitle: 'OpenAI Codex Login',
codexWaiting: 'Enter this code at the authorization page to complete login:',
codexCopyCode: 'Code copied',
codexOpenLink: 'Open authorization page',
codexApproved: 'Login successful',
codexExpired: 'Authorization expired. Please try again.',
noProviders: 'No providers found. Add a custom provider to get started.',
builtIn: 'Built-in',
customType: 'Custom',
+7
View File
@@ -14,6 +14,7 @@ export default {
common: {
loading: 'Cargando...',
cancel: 'Cancelar',
retry: 'Reintentar',
delete: 'Eliminar',
edit: 'Editar',
save: 'Guardar',
@@ -195,6 +196,12 @@ export default {
providerDeleted: 'Proveedor eliminado',
deleteProvider: 'Eliminar proveedor',
deleteConfirm: 'Estas seguro de que quieres eliminar "{name}"?',
codexLoginTitle: 'Inicio de sesión de OpenAI Codex',
codexWaiting: 'Ingrese este código en la página de autorización para iniciar sesión:',
codexCopyCode: 'Código copiado',
codexOpenLink: 'Abrir página de autorización',
codexApproved: 'Inicio de sesión exitoso',
codexExpired: 'La autorización ha expirado. Por favor, inténtelo de nuevo.',
noProviders: 'No se encontraron proveedores. Anade un proveedor personalizado para comenzar.',
builtIn: 'Integrado',
customType: 'Personalizado',
+7
View File
@@ -14,6 +14,7 @@ export default {
common: {
loading: 'Chargement...',
cancel: 'Annuler',
retry: 'Réessayer',
delete: 'Supprimer',
edit: 'Modifier',
save: 'Enregistrer',
@@ -195,6 +196,12 @@ export default {
providerDeleted: 'Fournisseur supprime',
deleteProvider: 'Supprimer le fournisseur',
deleteConfirm: 'Etes-vous sur de vouloir supprimer "{name}" ?',
codexLoginTitle: 'Connexion OpenAI Codex',
codexWaiting: 'Entrez ce code sur la page d\'autorisation pour vous connecter :',
codexCopyCode: 'Code copié',
codexOpenLink: 'Ouvrir la page d\'autorisation',
codexApproved: 'Connexion réussie',
codexExpired: 'L\'autorisation a expiré. Veuillez réessayer.',
noProviders: 'Aucun fournisseur trouve. Ajoutez un fournisseur personnalise pour commencer.',
builtIn: 'Integre',
customType: 'Personnalise',
+7
View File
@@ -14,6 +14,7 @@ export default {
common: {
loading: '読み込み中...',
cancel: 'キャンセル',
retry: '再試行',
delete: '削除',
edit: '編集',
save: '保存',
@@ -195,6 +196,12 @@ export default {
providerDeleted: 'プロバイダーを削除しました',
deleteProvider: 'プロバイダーを削除',
deleteConfirm: '「{name}」を削除しますか?',
codexLoginTitle: 'OpenAI Codex ログイン',
codexWaiting: '認証ページで以下のコードを入力してログインしてください:',
codexCopyCode: 'コードをコピーしました',
codexOpenLink: '認証ページを開く',
codexApproved: 'ログイン成功',
codexExpired: '認証の有効期限が切れました。もう一度お試しください。',
noProviders: 'プロバイダーがありません。カスタムプロバイダーを追加して始めましょう。',
builtIn: '組み込み',
customType: 'カスタム',
+7
View File
@@ -14,6 +14,7 @@ export default {
common: {
loading: '로딩 중...',
cancel: '취소',
retry: '재시도',
delete: '삭제',
edit: '편집',
save: '저장',
@@ -195,6 +196,12 @@ export default {
providerDeleted: 'Provider가 삭제되었습니다',
deleteProvider: 'Provider 삭제',
deleteConfirm: '"{name}"을(를) 삭제하시겠습니까?',
codexLoginTitle: 'OpenAI Codex 로그인',
codexWaiting: '인증 페이지에서 아래 코드를 입력하여 로그인하세요:',
codexCopyCode: '코드가 복사되었습니다',
codexOpenLink: '인증 페이지 열기',
codexApproved: '로그인 성공',
codexExpired: '인증이 만료되었습니다. 다시 시도해주세요.',
noProviders: 'Provider가 없습니다. 사용자 지정 Provider를 추가하여 시작하세요.',
builtIn: '내장',
customType: '사용자 지정',
+7
View File
@@ -14,6 +14,7 @@ export default {
common: {
loading: 'Carregando...',
cancel: 'Cancelar',
retry: 'Tentar novamente',
delete: 'Excluir',
edit: 'Editar',
save: 'Salvar',
@@ -195,6 +196,12 @@ export default {
providerDeleted: 'Provedor excluido',
deleteProvider: 'Excluir provedor',
deleteConfirm: 'Tem certeza de que deseja excluir "{name}"?',
codexLoginTitle: 'Login do OpenAI Codex',
codexWaiting: 'Digite este código na página de autorização para fazer login:',
codexCopyCode: 'Código copiado',
codexOpenLink: 'Abrir página de autorização',
codexApproved: 'Login bem-sucedido',
codexExpired: 'A autorização expirou. Por favor, tente novamente.',
noProviders: 'Nenhum provedor encontrado. Adicione um provedor personalizado para comecar.',
builtIn: 'Integrado',
customType: 'Personalizado',
+7
View File
@@ -15,6 +15,7 @@ export default {
loading: '加载中...',
cancel: '取消',
delete: '删除',
retry: '重试',
edit: '编辑',
save: '保存',
saved: '已保存',
@@ -195,6 +196,12 @@ export default {
providerDeleted: 'Provider 已删除',
deleteProvider: '删除 Provider',
deleteConfirm: '确定删除 "{name}" 吗?',
codexLoginTitle: 'OpenAI Codex 登录',
codexWaiting: '在授权页面输入以下代码完成登录:',
codexCopyCode: '代码已复制',
codexOpenLink: '打开授权页面',
codexApproved: '登录成功',
codexExpired: '授权已过期,请重试。',
noProviders: '暂无 Provider,添加一个开始吧。',
builtIn: '内置',
customType: '自定义',