diff --git a/services/agents-login/src/worker/agentsApiClient.ts b/services/agents-login/src/worker/agentsApiClient.ts index 30b854aa..9f047b0f 100644 --- a/services/agents-login/src/worker/agentsApiClient.ts +++ b/services/agents-login/src/worker/agentsApiClient.ts @@ -88,10 +88,11 @@ export function payloadForApi(provider: Provider, bundle: CredentialBundle): Rec const authJson = bundle.data.auth_json const configToml = bundle.data.config_toml - if (!authJson || !configToml) { + if (!authJson) { throw new Error('no Codex credential captured') } - return { auth_json: authJson, config_toml: configToml } + // config_toml is optional (codex login does not write it); include when present. + return { auth_json: authJson, ...(configToml ? { config_toml: configToml } : {}) } } async function safeText(res: Response): Promise { diff --git a/services/agents-login/src/worker/credentials.ts b/services/agents-login/src/worker/credentials.ts index 9cd925dc..196119c4 100644 --- a/services/agents-login/src/worker/credentials.ts +++ b/services/agents-login/src/worker/credentials.ts @@ -146,16 +146,19 @@ export async function captureCodex( ): Promise { const authPath = join(paths.codexHome, 'auth.json') const configPath = join(paths.codexHome, 'config.toml') - const [auth, config] = await Promise.all([readUtf8(authPath), readUtf8(configPath)]) - return { - data: { - auth_json: auth, - config_toml: config, - schema_version: SCHEMA_VERSION, - updated_at: now().toISOString(), - updated_by: updatedBy, - }, + // `codex login` writes auth.json (the credential) but NOT config.toml, so + // config.toml is optional — requiring it threw ENOENT and broke sign-in. + const [auth, config] = await Promise.all([readUtf8(authPath), readUtf8OrUndefined(configPath)]) + const data: Record = { + auth_json: auth, + schema_version: SCHEMA_VERSION, + updated_at: now().toISOString(), + updated_by: updatedBy, + } + if (config !== undefined) { + data.config_toml = config } + return { data } } export async function capture( diff --git a/services/agents-login/test/agentsApiClient.test.ts b/services/agents-login/test/agentsApiClient.test.ts index 85a48aa7..155c79f6 100644 --- a/services/agents-login/test/agentsApiClient.test.ts +++ b/services/agents-login/test/agentsApiClient.test.ts @@ -120,7 +120,12 @@ describe('AgentsApiClient', () => { it('rejects incomplete provider payloads before posting', () => { expect(() => payloadForApi('claude', { data: { account_json: '{}' } })).toThrow(/Claude credentials_json/) - expect(() => payloadForApi('codex', { data: { auth_json: '{}' } })).toThrow(/Codex credential/) + // Codex requires auth_json; config_toml is optional (codex login never writes it). + expect(() => payloadForApi('codex', { data: { config_toml: 'x = 1' } })).toThrow(/Codex credential/) + }) + + it('posts a codex payload with auth_json alone (config_toml optional)', () => { + expect(payloadForApi('codex', { data: { auth_json: '{"tokens":"t"}' } })).toEqual({ auth_json: '{"tokens":"t"}' }) }) it('reports only unknown local stored status', () => {