feat(provider): support Codex subscriptions with ChatGPT sign-in (#2513)

* feat(provider): support Codex subscriptions with ChatGPT sign-in

* style: format Codex live integration test

* fix(provider): preserve Codex identity in temporary model tests

* fix(web): portal provider selector without dialog overflow

* fix(web): allow native scrolling in provider dropdown

* fix(provider): surface safe Codex quota and upstream errors

* fix(web): provide reliable Codex copy feedback in dialogs

* feat(provider): confirm cascade deletion from edit dialog

* fix(persistence): discard connections after failed commit

* fix(web): polish provider loading and confirmation motion

---------

Co-authored-by: dadachann <185672915+dadachann@users.noreply.github.com>
This commit is contained in:
Hyu
2026-09-06 23:31:02 +08:00
committed by GitHub
parent ec63978ecf
commit 0f216a0d4d
52 changed files with 5490 additions and 360 deletions
+33
View File
@@ -182,6 +182,37 @@ const enUS = {
help: 'Get Help',
},
models: {
codex: {
account: 'ChatGPT subscription',
description:
'Sign in with your ChatGPT account. Subscription access is separate from OpenAI API billing; model availability and usage limits depend on your plan.',
disconnected: 'Not connected',
loading: 'Checking connection…',
starting: 'Starting sign-in…',
pending: 'Waiting for authorization',
connected: 'Connected',
expired: 'Sign-in expired. Start again to get a new code.',
error: 'Unable to sign in. Check your connection and try again.',
canceling: 'Canceling sign-in…',
saveAndSignIn: 'Save and sign in',
done: 'Done',
instructions:
'Enter this code on the OpenAI page. Keep this dialog open until sign-in completes.',
copyCode: 'Copy code',
copied: 'Copied',
copyManually: 'Select and copy the code manually.',
continueAtOpenAI: 'Continue at OpenAI',
expiresAt: 'Code expires at {{time}}.',
retrying: 'Connection interrupted. Retrying automatically…',
cancelSignIn: 'Cancel sign-in',
tryAgain: 'Try again',
signIn: 'Sign in',
reconnect: 'Reconnect',
disconnect: 'Disconnect',
disconnectConfirm:
'Disconnect this provider? Its models will stop working until you sign in again. This does not cancel your ChatGPT subscription.',
confirmDisconnect: 'Confirm disconnect',
},
title: 'Models',
description: 'Configure and manage models that can be used in pipelines',
createModel: 'Create Model',
@@ -316,6 +347,8 @@ const enUS = {
providerSaveError: 'Failed to save provider: ',
providerDeleted: 'Provider deleted',
providerDeleteError: 'Failed to delete provider: ',
deleteProviderCascadeConfirmation:
'Delete this provider and ALL models it contains? This action is irreversible and cannot be undone.',
deleteProviderConfirmation:
'Are you sure you want to delete this provider?',
loadError: 'Failed to load data',
+34
View File
@@ -187,6 +187,38 @@ const esES = {
help: 'Obtener ayuda',
},
models: {
codex: {
account: 'Suscripción de ChatGPT',
description:
'Inicia sesión con tu cuenta de ChatGPT. La suscripción es independiente de la facturación de la API de OpenAI; los modelos y límites dependen de tu plan.',
disconnected: 'Sin conexión',
loading: 'Comprobando conexión…',
starting: 'Iniciando sesión…',
pending: 'Esperando autorización',
connected: 'Conectado',
expired: 'El inicio de sesión ha caducado. Solicita un nuevo código.',
error:
'No se pudo iniciar sesión. Comprueba la conexión e inténtalo de nuevo.',
canceling: 'Cancelando inicio de sesión…',
saveAndSignIn: 'Guardar e iniciar sesión',
done: 'Listo',
instructions:
'Introduce este código en la página de OpenAI. Mantén este diálogo abierto hasta completar el inicio de sesión.',
copyCode: 'Copiar código',
copied: 'Copiado',
copyManually: 'Selecciona y copia el código manualmente.',
continueAtOpenAI: 'Continuar en OpenAI',
expiresAt: 'El código caduca a las {{time}}.',
retrying: 'Conexión interrumpida. Reintentando automáticamente…',
cancelSignIn: 'Cancelar inicio de sesión',
tryAgain: 'Reintentar',
signIn: 'Iniciar sesión',
reconnect: 'Reconectar',
disconnect: 'Desconectar',
disconnectConfirm:
'¿Desconectar este proveedor? Sus modelos dejarán de funcionar hasta que vuelvas a iniciar sesión. Esto no cancela tu suscripción de ChatGPT.',
confirmDisconnect: 'Confirmar desconexión',
},
title: 'Modelos',
description:
'Configura y gestiona los modelos que se pueden usar en los Pipelines',
@@ -324,6 +356,8 @@ const esES = {
providerSaveError: 'Error al guardar el proveedor: ',
providerDeleted: 'Proveedor eliminado',
providerDeleteError: 'Error al eliminar el proveedor: ',
deleteProviderCascadeConfirmation:
'¿Eliminar este proveedor y TODOS los modelos que contiene? Esta acción es irreversible y no se puede deshacer.',
deleteProviderConfirmation:
'¿Estás seguro de que deseas eliminar este proveedor?',
loadError: 'Error al cargar datos',
+34
View File
@@ -185,6 +185,38 @@ const jaJP = {
help: 'ヘルプドキュメントを見る',
},
models: {
codex: {
account: 'ChatGPT サブスクリプション',
description:
'ChatGPT アカウントでログインします。サブスクリプションと OpenAI API の課金は別です。利用可能なモデルと使用制限はプランによって異なります。',
disconnected: '未接続',
loading: '接続を確認中…',
starting: 'ログインを開始中…',
pending: '認証を待機中',
connected: '接続済み',
expired:
'ログインの有効期限が切れました。新しいコードを取得してください。',
error: 'ログインできません。接続を確認して再試行してください。',
canceling: 'ログインをキャンセル中…',
saveAndSignIn: '保存してログイン',
done: '完了',
instructions:
'OpenAI のページでこのコードを入力してください。ログインが完了するまでこの画面を開いたままにしてください。',
copyCode: 'コードをコピー',
copied: 'コピー済み',
copyManually: 'コードを選択して手動でコピーしてください。',
continueAtOpenAI: 'OpenAI で続行',
expiresAt: 'コードの有効期限: {{time}}',
retrying: '接続が切れました。自動的に再試行しています…',
cancelSignIn: 'ログインをキャンセル',
tryAgain: '再試行',
signIn: 'ログイン',
reconnect: '再接続',
disconnect: '切断',
disconnectConfirm:
'このプロバイダーを切断しますか?再ログインするまでモデルは使用できません。ChatGPT のサブスクリプションは解約されません。',
confirmDisconnect: '切断を確認',
},
title: 'モデル設定',
description: 'パイプラインで使用できるモデルを設定・管理',
createModel: 'モデルを作成',
@@ -322,6 +354,8 @@ const jaJP = {
providerSaveError: 'プロバイダーの保存に失敗しました:',
providerDeleted: 'プロバイダーを削除しました',
providerDeleteError: 'プロバイダーの削除に失敗しました:',
deleteProviderCascadeConfirmation:
'このプロバイダーと、その中のすべてのモデルを削除しますか?この操作は取り消せず、元に戻せません。',
deleteProviderConfirmation: 'このプロバイダーを削除してもよろしいですか?',
loadError: 'データの読み込みに失敗しました',
chat: 'チャット',
+33
View File
@@ -184,6 +184,37 @@ const ruRU = {
help: 'Помощь',
},
models: {
codex: {
account: 'Подписка ChatGPT',
description:
'Войдите в аккаунт ChatGPT. Подписка не связана с оплатой API OpenAI; доступные модели и лимиты зависят от тарифа.',
disconnected: 'Не подключено',
loading: 'Проверка подключения…',
starting: 'Начало входа…',
pending: 'Ожидание авторизации',
connected: 'Подключено',
expired: 'Срок входа истёк. Получите новый код.',
error: 'Не удалось войти. Проверьте подключение и повторите попытку.',
canceling: 'Отмена входа…',
saveAndSignIn: 'Сохранить и войти',
done: 'Готово',
instructions:
'Введите этот код на странице OpenAI. Не закрывайте это окно до завершения входа.',
copyCode: 'Копировать код',
copied: 'Скопировано',
copyManually: 'Выделите и скопируйте код вручную.',
continueAtOpenAI: 'Продолжить в OpenAI',
expiresAt: 'Код действителен до {{time}}.',
retrying: 'Соединение прервано. Автоматическая повторная попытка…',
cancelSignIn: 'Отменить вход',
tryAgain: 'Повторить',
signIn: 'Войти',
reconnect: 'Переподключить',
disconnect: 'Отключить',
disconnectConfirm:
'Отключить этого провайдера? Его модели перестанут работать до повторного входа. Подписка ChatGPT не будет отменена.',
confirmDisconnect: 'Подтвердить отключение',
},
title: 'Модели',
description: 'Настройка и управление моделями, используемыми в конвейерах',
createModel: 'Создать модель',
@@ -322,6 +353,8 @@ const ruRU = {
providerSaveError: 'Ошибка сохранения провайдера: ',
providerDeleted: 'Провайдер удалён',
providerDeleteError: 'Ошибка удаления провайдера: ',
deleteProviderCascadeConfirmation:
'Удалить этого провайдера и ВСЕ содержащиеся в нём модели? Это действие необратимо, его нельзя отменить.',
deleteProviderConfirmation:
'Вы уверены, что хотите удалить этого провайдера?',
loadError: 'Не удалось загрузить данные',
+33
View File
@@ -181,6 +181,37 @@ const thTH = {
help: 'ขอความช่วยเหลือ',
},
models: {
codex: {
account: 'การสมัครสมาชิก ChatGPT',
description:
'ลงชื่อเข้าใช้ด้วยบัญชี ChatGPT การใช้งานผ่านการสมัครสมาชิกแยกจากการเรียกเก็บเงิน OpenAI API รุ่นโมเดลและขีดจำกัดการใช้งานขึ้นอยู่กับแพ็กเกจของคุณ',
disconnected: 'ยังไม่ได้เชื่อมต่อ',
loading: 'กำลังตรวจสอบการเชื่อมต่อ…',
starting: 'กำลังเริ่มลงชื่อเข้าใช้…',
pending: 'กำลังรอการอนุญาต',
connected: 'เชื่อมต่อแล้ว',
expired: 'การลงชื่อเข้าใช้หมดอายุ เริ่มใหม่เพื่อรับรหัสใหม่',
error: 'ไม่สามารถลงชื่อเข้าใช้ได้ ตรวจสอบการเชื่อมต่อแล้วลองอีกครั้ง',
canceling: 'กำลังยกเลิกการลงชื่อเข้าใช้…',
saveAndSignIn: 'บันทึกและลงชื่อเข้าใช้',
done: 'เสร็จสิ้น',
instructions:
'ป้อนรหัสนี้บนหน้า OpenAI เปิดกล่องโต้ตอบนี้ไว้จนกว่าจะลงชื่อเข้าใช้เสร็จ',
copyCode: 'คัดลอกรหัส',
copied: 'คัดลอกแล้ว',
copyManually: 'เลือกรหัสและคัดลอกด้วยตนเอง',
continueAtOpenAI: 'ดำเนินการต่อที่ OpenAI',
expiresAt: 'รหัสหมดอายุเวลา {{time}}',
retrying: 'การเชื่อมต่อขัดข้อง กำลังลองใหม่โดยอัตโนมัติ…',
cancelSignIn: 'ยกเลิกการลงชื่อเข้าใช้',
tryAgain: 'ลองอีกครั้ง',
signIn: 'ลงชื่อเข้าใช้',
reconnect: 'เชื่อมต่อใหม่',
disconnect: 'ยกเลิกการเชื่อมต่อ',
disconnectConfirm:
'ยกเลิกการเชื่อมต่อผู้ให้บริการนี้หรือไม่? โมเดลจะหยุดทำงานจนกว่าคุณจะลงชื่อเข้าใช้อีกครั้ง การดำเนินการนี้ไม่ได้ยกเลิกการสมัครสมาชิก ChatGPT',
confirmDisconnect: 'ยืนยันการยกเลิกการเชื่อมต่อ',
},
title: 'โมเดล',
description: 'กำหนดค่าและจัดการโมเดลที่สามารถใช้ใน Pipeline',
createModel: 'สร้างโมเดล',
@@ -310,6 +341,8 @@ const thTH = {
providerSaveError: 'บันทึกผู้ให้บริการล้มเหลว: ',
providerDeleted: 'ลบผู้ให้บริการแล้ว',
providerDeleteError: 'ลบผู้ให้บริการล้มเหลว: ',
deleteProviderCascadeConfirmation:
'ลบผู้ให้บริการนี้และโมเดลทั้งหมดที่อยู่ภายในหรือไม่? การดำเนินการนี้ไม่สามารถย้อนกลับหรือยกเลิกได้',
deleteProviderConfirmation: 'คุณแน่ใจหรือไม่ว่าต้องการลบผู้ให้บริการนี้?',
loadError: 'โหลดข้อมูลล้มเหลว',
chat: 'แชท',
+33
View File
@@ -184,6 +184,37 @@ const viVN = {
help: 'Trợ giúp',
},
models: {
codex: {
account: 'Gói đăng ký ChatGPT',
description:
'Đăng nhập bằng tài khoản ChatGPT. Gói đăng ký độc lập với thanh toán API OpenAI; mô hình và giới hạn sử dụng tùy thuộc vào gói của bạn.',
disconnected: 'Chưa kết nối',
loading: 'Đang kiểm tra kết nối…',
starting: 'Đang bắt đầu đăng nhập…',
pending: 'Đang chờ cấp quyền',
connected: 'Đã kết nối',
expired: 'Phiên đăng nhập đã hết hạn. Hãy lấy mã mới.',
error: 'Không thể đăng nhập. Kiểm tra kết nối và thử lại.',
canceling: 'Đang hủy đăng nhập…',
saveAndSignIn: 'Lưu và đăng nhập',
done: 'Xong',
instructions:
'Nhập mã này trên trang OpenAI. Giữ hộp thoại này mở cho đến khi đăng nhập hoàn tất.',
copyCode: 'Sao chép mã',
copied: 'Đã sao chép',
copyManually: 'Chọn và sao chép mã thủ công.',
continueAtOpenAI: 'Tiếp tục tại OpenAI',
expiresAt: 'Mã hết hạn lúc {{time}}.',
retrying: 'Kết nối bị gián đoạn. Đang tự động thử lại…',
cancelSignIn: 'Hủy đăng nhập',
tryAgain: 'Thử lại',
signIn: 'Đăng nhập',
reconnect: 'Kết nối lại',
disconnect: 'Ngắt kết nối',
disconnectConfirm:
'Ngắt kết nối nhà cung cấp này? Các mô hình sẽ ngừng hoạt động cho đến khi bạn đăng nhập lại. Thao tác này không hủy gói ChatGPT của bạn.',
confirmDisconnect: 'Xác nhận ngắt kết nối',
},
title: 'Mô hình',
description:
'Cấu hình và quản lý các mô hình có thể sử dụng trong Pipeline',
@@ -318,6 +349,8 @@ const viVN = {
providerSaveError: 'Lưu nhà cung cấp thất bại: ',
providerDeleted: 'Đã xóa nhà cung cấp',
providerDeleteError: 'Xóa nhà cung cấp thất bại: ',
deleteProviderCascadeConfirmation:
'Xóa nhà cung cấp này và TẤT CẢ mô hình bên trong? Hành động này không thể đảo ngược hoặc hoàn tác.',
deleteProviderConfirmation:
'Bạn có chắc chắn muốn xóa nhà cung cấp này không?',
loadError: 'Tải dữ liệu thất bại',
+33
View File
@@ -172,6 +172,37 @@ const zhHans = {
help: '查看帮助文档',
},
models: {
codex: {
account: 'ChatGPT 订阅',
description:
'使用 ChatGPT 账号登录。订阅权限与 OpenAI API 计费相互独立,可用模型和使用额度取决于你的订阅方案。',
disconnected: '未连接',
loading: '正在检查连接…',
starting: '正在开始登录…',
pending: '等待授权',
connected: '已连接',
expired: '登录已过期,请重试以获取新验证码。',
error: '无法登录,请检查网络连接后重试。',
canceling: '正在取消登录…',
saveAndSignIn: '保存并登录',
done: '完成',
instructions:
'在 OpenAI 页面输入此验证码,登录完成前请保持此对话框打开。',
copyCode: '复制验证码',
copied: '已复制',
copyManually: '请选中并手动复制验证码。',
continueAtOpenAI: '前往 OpenAI 继续',
expiresAt: '验证码将于 {{time}} 过期。',
retrying: '连接中断,正在自动重试…',
cancelSignIn: '取消登录',
tryAgain: '重试',
signIn: '登录',
reconnect: '重新连接',
disconnect: '断开连接',
disconnectConfirm:
'断开此供应商的连接?重新登录前,其模型将无法使用。此操作不会取消你的 ChatGPT 订阅。',
confirmDisconnect: '确认断开',
},
title: '模型配置',
description: '配置和管理可在流水线中使用的模型',
createModel: '创建对话模型',
@@ -302,6 +333,8 @@ const zhHans = {
providerSaveError: '保存供应商失败:',
providerDeleted: '供应商已删除',
providerDeleteError: '删除供应商失败:',
deleteProviderCascadeConfirmation:
'确定删除此供应商及其包含的所有模型吗?此操作不可逆,无法撤销。',
deleteProviderConfirmation: '你确定要删除这个供应商吗?',
loadError: '加载数据失败',
chat: '对话',
+33
View File
@@ -173,6 +173,37 @@ const zhHant = {
help: '查看說明文件',
},
models: {
codex: {
account: 'ChatGPT 訂閱',
description:
'使用 ChatGPT 帳號登入。訂閱權限與 OpenAI API 計費相互獨立,可用模型和使用額度取決於你的訂閱方案。',
disconnected: '未連線',
loading: '正在檢查連線…',
starting: '正在開始登入…',
pending: '等待授權',
connected: '已連線',
expired: '登入已過期,請重試以取得新驗證碼。',
error: '無法登入,請檢查網路連線後重試。',
canceling: '正在取消登入…',
saveAndSignIn: '儲存並登入',
done: '完成',
instructions:
'在 OpenAI 頁面輸入此驗證碼,登入完成前請保持此對話框開啟。',
copyCode: '複製驗證碼',
copied: '已複製',
copyManually: '請選取並手動複製驗證碼。',
continueAtOpenAI: '前往 OpenAI 繼續',
expiresAt: '驗證碼將於 {{time}} 過期。',
retrying: '連線中斷,正在自動重試…',
cancelSignIn: '取消登入',
tryAgain: '重試',
signIn: '登入',
reconnect: '重新連線',
disconnect: '中斷連線',
disconnectConfirm:
'中斷此供應商的連線?重新登入前,其模型將無法使用。此操作不會取消你的 ChatGPT 訂閱。',
confirmDisconnect: '確認中斷',
},
title: '模型設定',
description: '設定和管理可在流程線中使用的模型',
createModel: '建立模型',
@@ -299,6 +330,8 @@ const zhHant = {
providerSaveError: '儲存供應商失敗:',
providerDeleted: '供應商已刪除',
providerDeleteError: '刪除供應商失敗:',
deleteProviderCascadeConfirmation:
'確定刪除此供應商及其包含的所有模型嗎?此操作不可逆,無法復原。',
deleteProviderConfirmation: '您確定要刪除這個供應商嗎?',
loadError: '載入資料失敗',
chat: '對話',