mirror of
https://github.com/stablyai/orca.git
synced 2026-10-27 16:02:42 +00:00
* refactor: split agent config and auth services * chore: repoint wsl and global-fetch guards at split module paths * fix: restore merge-base Claude CLI error propagation Drop the secret-redaction rewriting added to Claude CLI error paths in the refactor: spawn errors again reject with the original Error (preserving .code/.errno/.syscall/.stack) and command output/auth-status logs are no longer rewritten.
52 lines
1.6 KiB
TypeScript
52 lines
1.6 KiB
TypeScript
import { randomUUID } from 'node:crypto'
|
|
import {
|
|
existsSync,
|
|
lstatSync,
|
|
mkdirSync,
|
|
realpathSync,
|
|
statSync,
|
|
unlinkSync,
|
|
writeFileSync
|
|
} from 'node:fs'
|
|
import { dirname, join } from 'node:path'
|
|
import { renameFileWithWindowsRetry } from '../codex-accounts/fs-utils'
|
|
import { writeRollingFileBackup } from '../rolling-file-backup'
|
|
|
|
export function writeTomlConfigAtomically(configPath: string, contents: string): void {
|
|
const writePath = resolveTomlWritePath(configPath)
|
|
const directory = dirname(writePath)
|
|
mkdirSync(directory, { recursive: true })
|
|
const temporaryPath = join(directory, `.${Date.now()}-${randomUUID()}.tmp`)
|
|
const existingMode = existsSync(writePath) ? statSync(writePath).mode : undefined
|
|
let renamed = false
|
|
try {
|
|
writeFileSync(temporaryPath, contents, { encoding: 'utf-8', mode: existingMode })
|
|
if (existsSync(writePath)) {
|
|
writeRollingFileBackup(writePath, `${writePath}.bak`)
|
|
}
|
|
renameFileWithWindowsRetry(temporaryPath, writePath)
|
|
renamed = true
|
|
} finally {
|
|
if (!renamed && existsSync(temporaryPath)) {
|
|
try {
|
|
unlinkSync(temporaryPath)
|
|
} catch {
|
|
// Why: cleanup failure must not mask the write failure.
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function resolveTomlWritePath(configPath: string): string {
|
|
let isSymlink = false
|
|
try {
|
|
isSymlink = lstatSync(configPath).isSymbolicLink()
|
|
} catch (error) {
|
|
if ((error as NodeJS.ErrnoException).code !== 'ENOENT') {
|
|
throw error
|
|
}
|
|
}
|
|
// Why: replacing the lexical path would destroy a dotfiles symlink; dangling links fail closed.
|
|
return isSymlink ? realpathSync.native(configPath) : configPath
|
|
}
|