From eea1d1decd675299803127773e3d0c72ffaaa3aa Mon Sep 17 00:00:00 2001 From: sir1st <1174702930@qq.com> Date: Sat, 30 May 2026 16:31:00 +0800 Subject: [PATCH] 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 --- packages/server/src/controllers/hermes/codex-auth.ts | 6 +++--- packages/server/src/controllers/hermes/nous-auth.ts | 3 ++- packages/server/src/controllers/hermes/xai-auth.ts | 3 ++- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/packages/server/src/controllers/hermes/codex-auth.ts b/packages/server/src/controllers/hermes/codex-auth.ts index 5a84081..a4a57ff 100644 --- a/packages/server/src/controllers/hermes/codex-auth.ts +++ b/packages/server/src/controllers/hermes/codex-auth.ts @@ -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 }) } diff --git a/packages/server/src/controllers/hermes/nous-auth.ts b/packages/server/src/controllers/hermes/nous-auth.ts index 6240396..de235c4 100644 --- a/packages/server/src/controllers/hermes/nous-auth.ts +++ b/packages/server/src/controllers/hermes/nous-auth.ts @@ -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 }) } diff --git a/packages/server/src/controllers/hermes/xai-auth.ts b/packages/server/src/controllers/hermes/xai-auth.ts index 902bb3b..9410002 100644 --- a/packages/server/src/controllers/hermes/xai-auth.ts +++ b/packages/server/src/controllers/hermes/xai-auth.ts @@ -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 }) }