fix(auth): use path.dirname for credential dir on Windows (#1148)

Provider auth controllers derived the credential directory with
`authPath.substring(0, authPath.lastIndexOf('/'))`. On Windows paths use
backslashes, so `lastIndexOf('/')` returns -1 and the slice yields an
empty string, making `mkdirSync('')` throw
`ENOENT: no such file or directory, mkdir ''` during OAuth login.

Replace the manual slicing with the cross-platform `path.dirname()` in
codex-auth (auth.json + codex CLI token paths), xai-auth, and nous-auth.

Fixes Codex/xAI/Nous login on Windows.

Co-authored-by: xingzhi <chuzihao.czh@alibaba-inc.com>
This commit is contained in:
sir1st
2026-05-30 16:31:00 +08:00
committed by GitHub
parent f7991572af
commit eea1d1decd
3 changed files with 7 additions and 5 deletions
@@ -1,5 +1,5 @@
import { randomUUID } from 'crypto'
import { join } from 'path'
import { join, dirname } from 'path'
import { homedir } from 'os'
import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'fs'
import { getActiveAuthPath } from '../../services/hermes/hermes-profile'
@@ -47,7 +47,7 @@ function loadAuthJson(authPath: string): AuthJson {
function saveAuthJson(authPath: string, data: AuthJson): void {
data.updated_at = new Date().toISOString()
const dir = authPath.substring(0, authPath.lastIndexOf('/'))
const dir = dirname(authPath)
if (!existsSync(dir)) mkdirSync(dir, { recursive: true })
writeFileSync(authPath, JSON.stringify(data, null, 2) + '\n', { mode: 0o600 })
}
@@ -55,7 +55,7 @@ function saveAuthJson(authPath: string, data: AuthJson): void {
function saveCodexCliTokens(accessToken: string, refreshToken: string): void {
const codexHome = process.env.CODEX_HOME || CODEX_HOME
const codexAuthPath = join(codexHome, 'auth.json')
const dir = codexAuthPath.substring(0, codexAuthPath.lastIndexOf('/'))
const dir = dirname(codexAuthPath)
if (!existsSync(dir)) mkdirSync(dir, { recursive: true })
writeFileSync(codexAuthPath, JSON.stringify({ tokens: { access_token: accessToken, refresh_token: refreshToken }, last_refresh: new Date().toISOString() }, null, 2) + '\n', { mode: 0o600 })
}
@@ -1,5 +1,6 @@
import { randomUUID } from 'crypto'
import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'fs'
import { dirname } from 'path'
import { getActiveAuthPath } from '../../services/hermes/hermes-profile'
import { logger } from '../../services/logger'
@@ -46,7 +47,7 @@ function loadAuthJson(authPath: string): AuthJson {
function saveAuthJson(authPath: string, data: AuthJson): void {
data.updated_at = new Date().toISOString()
const dir = authPath.substring(0, authPath.lastIndexOf('/'))
const dir = dirname(authPath)
if (!existsSync(dir)) mkdirSync(dir, { recursive: true })
writeFileSync(authPath, JSON.stringify(data, null, 2) + '\n', { mode: 0o600 })
}
@@ -2,6 +2,7 @@ import { createHash, randomBytes, randomUUID } from 'crypto'
import { createServer, type Server } from 'http'
import { request as httpsRequest, type RequestOptions } from 'https'
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs'
import { dirname } from 'path'
import { URL } from 'url'
import { getActiveAuthPath } from '../../services/hermes/hermes-profile'
import { logger } from '../../services/logger'
@@ -153,7 +154,7 @@ function loadAuthJson(authPath: string): AuthJson {
function saveAuthJson(authPath: string, data: AuthJson): void {
data.updated_at = new Date().toISOString()
const dir = authPath.substring(0, authPath.lastIndexOf('/'))
const dir = dirname(authPath)
if (!existsSync(dir)) mkdirSync(dir, { recursive: true })
writeFileSync(authPath, JSON.stringify(data, null, 2) + '\n', { mode: 0o600 })
}