(), {
showManualOption: true,
initialInputMethod: 'manual',
platform: 'anthropic',
- showProjectId: true
+ showProjectId: true,
+ titleOverride: '',
+ agentIdentityOnly: false
})
const emit = defineEmits<{
@@ -881,7 +885,7 @@ const getOAuthKey = (key: string) => {
}
// Computed translations for current platform
-const oauthTitle = computed(() => t(getOAuthKey('title')))
+const oauthTitle = computed(() => props.titleOverride || t(getOAuthKey('title')))
const oauthFollowSteps = computed(() => t(getOAuthKey('followSteps')))
const oauthStep1GenerateUrl = computed(() => t(getOAuthKey('step1GenerateUrl')))
const oauthGenerateAuthUrl = computed(() => t(getOAuthKey('generateAuthUrl')))
diff --git a/frontend/src/components/account/__tests__/CreateAccountModal.spec.ts b/frontend/src/components/account/__tests__/CreateAccountModal.spec.ts
index 62c97d35a4..dcd34c0902 100644
--- a/frontend/src/components/account/__tests__/CreateAccountModal.spec.ts
+++ b/frontend/src/components/account/__tests__/CreateAccountModal.spec.ts
@@ -64,6 +64,14 @@ const BaseDialogStub = defineComponent({
const OAuthAuthorizationFlowStub = defineComponent({
name: 'OAuthAuthorizationFlow',
+ props: {
+ showManualOption: Boolean,
+ showCodexSessionImportOption: Boolean,
+ showCodexPatOption: Boolean,
+ initialInputMethod: String,
+ agentIdentityOnly: Boolean,
+ titleOverride: String,
+ },
emits: ['import-codex-session', 'import-codex-pat'],
template: `
@@ -147,6 +155,38 @@ describe('CreateAccountModal OpenAI long-context billing', () => {
expect(createAccountMock.mock.calls[0]?.[0]?.extra?.openai_long_context_billing_enabled).toBe(false)
})
+ it('shows Agent Identity as a separate OpenAI account type', async () => {
+ const wrapper = mountModal()
+ await selectButtonByText(wrapper, 'OpenAI')
+ await wrapper.get('[data-testid="openai-account-type-agent-identity"]').trigger('click')
+ await wrapper.get('form#create-account-form input[type="text"]').setValue('Agent Identity')
+ await wrapper.get('form#create-account-form').trigger('submit.prevent')
+
+ const flow = wrapper.getComponent(OAuthAuthorizationFlowStub)
+ expect(flow.props('showManualOption')).toBe(false)
+ expect(flow.props('showCodexSessionImportOption')).toBe(true)
+ expect(flow.props('showCodexPatOption')).toBe(false)
+ expect(flow.props('initialInputMethod')).toBe('codex_session')
+ expect(flow.props('agentIdentityOnly')).toBe(true)
+ expect(flow.props('titleOverride')).toBe('Agent Identity')
+ })
+
+ it('shows Codex PAT as a separate OpenAI account type', async () => {
+ const wrapper = mountModal()
+ await selectButtonByText(wrapper, 'OpenAI')
+ await wrapper.get('[data-testid="openai-account-type-codex-pat"]').trigger('click')
+ await wrapper.get('form#create-account-form input[type="text"]').setValue('Codex PAT')
+ await wrapper.get('form#create-account-form').trigger('submit.prevent')
+
+ const flow = wrapper.getComponent(OAuthAuthorizationFlowStub)
+ expect(flow.props('showManualOption')).toBe(false)
+ expect(flow.props('showCodexSessionImportOption')).toBe(false)
+ expect(flow.props('showCodexPatOption')).toBe(true)
+ expect(flow.props('initialInputMethod')).toBe('codex_pat')
+ expect(flow.props('agentIdentityOnly')).toBe(false)
+ expect(flow.props('titleOverride')).toBe('Codex PAT')
+ })
+
it('sends true explicitly when OpenAI long-context billing is enabled', async () => {
await submitApiKeyAccount('openai', true)
diff --git a/frontend/src/i18n/locales/en/admin/accounts.ts b/frontend/src/i18n/locales/en/admin/accounts.ts
index 6b0fa554f9..14233f1f6a 100644
--- a/frontend/src/i18n/locales/en/admin/accounts.ts
+++ b/frontend/src/i18n/locales/en/admin/accounts.ts
@@ -108,6 +108,8 @@ export default {
types: {
oauth: 'OAuth',
chatgptOauth: 'ChatGPT OAuth',
+ agentIdentity: 'Import Codex auth.json',
+ codexPat: 'Personal access token',
responsesApi: 'Responses API',
googleOauth: 'Google OAuth',
codeAssist: 'Code Assist',
@@ -825,16 +827,21 @@ export default {
refreshTokenAuth: 'Manual RT Input',
refreshTokenDesc: 'Enter your existing OpenAI Refresh Token(s). Supports batch input (one per line). The system will automatically validate and create accounts.',
refreshTokenPlaceholder: 'Paste your OpenAI Refresh Token...\nSupports multiple, one per line',
- codexSessionAuth: 'Codex auth.json / AT Import',
- codexSessionDesc: 'Paste a Codex auth.json (OAuth or Agent Identity) or an accessToken. Accounts use the step 1 settings.',
- codexSessionInputLabel: 'Codex auth.json or accessToken',
+ codexSessionAuth: 'Codex OAuth auth.json / AT Import',
+ codexSessionDesc: 'Paste a Codex OAuth auth.json or an accessToken. Accounts use the step 1 settings.',
+ codexSessionInputLabel: 'Codex OAuth auth.json or accessToken',
codexSessionPlaceholder: 'Multiple lines supported, one token or auth.json object per line',
- codexSessionHint: 'Agent Identity keeps no OAuth token and signs each upstream request dynamically. Session/access-token imports retain their existing expiration behavior.',
+ codexSessionHint: 'OAuth session/access-token imports retain their existing expiration behavior.',
codexSessionImportAndCreate: 'Import & Create Account',
codexSessionEmpty: 'Please enter a Codex auth.json or accessToken',
codexSessionImportFailed: 'Failed to import Codex account',
codexSessionImportSuccess: 'Import completed: created {created}, updated {updated}, skipped {skipped}',
codexSessionImportPartial: 'Partial success: created {created}, updated {updated}, skipped {skipped}, failed {failed}',
+ agentIdentityDesc: 'Import a Codex Agent Identity auth.json. No OAuth access or refresh token is stored.',
+ agentIdentityInputLabel: 'Agent Identity auth.json',
+ agentIdentityPlaceholder: 'Paste one Agent Identity auth.json object',
+ agentIdentityHint: 'The file must use auth_mode=agentIdentity. Upstream requests are signed dynamically.',
+ agentIdentityInvalid: 'Use a Codex auth.json with auth_mode=agentIdentity.',
codexPatAuth: 'Codex Personal Access Token',
codexPatDesc: 'Enter a Codex at- personal access token. The system validates it with OpenAI whoami before creating the account.',
codexPatInputLabel: 'Codex PAT',
diff --git a/frontend/src/i18n/locales/zh/admin/accounts.ts b/frontend/src/i18n/locales/zh/admin/accounts.ts
index bb6b309123..c873edc861 100644
--- a/frontend/src/i18n/locales/zh/admin/accounts.ts
+++ b/frontend/src/i18n/locales/zh/admin/accounts.ts
@@ -227,6 +227,8 @@ export default {
types: {
oauth: 'OAuth',
chatgptOauth: 'ChatGPT OAuth',
+ agentIdentity: '导入 Codex auth.json',
+ codexPat: '个人访问令牌',
responsesApi: 'Responses API',
googleOauth: 'Google OAuth',
codeAssist: 'Code Assist',
@@ -912,16 +914,21 @@ export default {
refreshTokenAuth: '手动输入 RT',
refreshTokenDesc: '输入您已有的 OpenAI Refresh Token,支持批量输入(每行一个),系统将自动验证并创建账号。',
refreshTokenPlaceholder: '粘贴您的 OpenAI Refresh Token...\n支持多个,每行一个',
- codexSessionAuth: 'Codex auth.json / AT 导入',
- codexSessionDesc: '粘贴 Codex auth.json(OAuth 或 Agent Identity)或 accessToken,按第一步配置创建账号。',
- codexSessionInputLabel: 'Codex auth.json 或 accessToken',
+ codexSessionAuth: 'Codex OAuth auth.json / AT 导入',
+ codexSessionDesc: '粘贴 Codex OAuth auth.json 或 accessToken,按第一步配置创建账号。',
+ codexSessionInputLabel: 'Codex OAuth auth.json 或 accessToken',
codexSessionPlaceholder: '支持多行,每行一个 token 或 auth.json 对象',
- codexSessionHint: 'Agent Identity 不保存 OAuth token,并为每次上游请求动态签名;session/accessToken 导入继续沿用原有过期规则。',
+ codexSessionHint: 'OAuth session/accessToken 导入继续沿用原有过期规则。',
codexSessionImportAndCreate: '导入并创建账号',
codexSessionEmpty: '请输入 Codex auth.json 或 accessToken',
codexSessionImportFailed: 'Codex 账号导入失败',
codexSessionImportSuccess: '导入完成:新增 {created},更新 {updated},跳过 {skipped}',
codexSessionImportPartial: '部分成功:新增 {created},更新 {updated},跳过 {skipped},失败 {failed}',
+ agentIdentityDesc: '导入 Codex Agent Identity auth.json,不保存 OAuth access token 或 refresh token。',
+ agentIdentityInputLabel: 'Agent Identity auth.json',
+ agentIdentityPlaceholder: '粘贴一个 Agent Identity auth.json 对象',
+ agentIdentityHint: '文件必须使用 auth_mode=agentIdentity;每次上游请求都会动态签名。',
+ agentIdentityInvalid: '请选择 auth_mode=agentIdentity 的 Codex auth.json。',
codexPatAuth: 'Codex Personal Access Token',
codexPatDesc: '输入 Codex at- Personal Access Token,系统会先调用 OpenAI whoami 校验后再创建账号。',
codexPatInputLabel: 'Codex PAT',