fix(paths): treat empty DSH_HOME as unset; isolate telemetry env test

Review fixes for #462:
- resolveDshHome now treats an empty or whitespace-only $DSH_HOME as
  unset, so a blank override never resolves the home to cwd via
  resolve(''). Restores the guard telemetry's old resolver carried.
- The default-env telemetry test asserts only that globalConfigDir()
  returns an absolute path, so a machine DSH_HOME without a .dsh suffix
  cannot break it.
This commit is contained in:
Turtle
2026-07-21 14:43:38 +08:00
parent 92e0d0e04f
commit fac3fc090f
6 changed files with 18 additions and 8 deletions

View File

@@ -1,6 +1,6 @@
import { mkdtemp, readFile, rm, writeFile } from 'node:fs/promises'
import { tmpdir } from 'node:os'
import { join, resolve } from 'node:path'
import { isAbsolute, join, resolve } from 'node:path'
import { defaultDshHome } from '@deepseek-ai/dsh-paths'
import { afterEach, describe, expect, it } from 'vitest'
import {
@@ -34,7 +34,9 @@ describe('globalConfigDir', () => {
it('reads process.env by default', () => {
// No override supplied: the call must not throw and must return an absolute path.
expect(globalConfigDir()).toContain('.dsh')
// The ambient DSH_HOME is unknown here, so assert only the invariant the
// resolver guarantees rather than a specific location.
expect(isAbsolute(globalConfigDir())).toBe(true)
})
})

View File

@@ -39,13 +39,16 @@ export function expandHomePath(path: string): string {
* Resolve the single-root DeepSeek Harness home.
*
* Precedence, highest first: an explicit configured path, `$DSH_HOME`, then
* `~/.dsh`. The harness keeps all user data under one root.
* `~/.dsh`. The harness keeps all user data under one root. An empty or
* whitespace-only `$DSH_HOME` is treated as unset, so a blank override never
* resolves the home to the current working directory.
* @param configured - explicit harness-home override, which has highest precedence.
* @param env - environment mapping used to read `DSH_HOME`.
* @returns the normalized absolute harness home path.
*/
export function resolveDshHome(configured?: string, env: Record<string, string | undefined> = process.env): string {
const selected = configured ?? env[DSH_HOME_ENV] ?? defaultDshHome()
const fromEnv = env[DSH_HOME_ENV]
const selected = configured ?? (fromEnv !== undefined && fromEnv.trim().length > 0 ? fromEnv : defaultDshHome())
return resolve(expandHomePath(selected))
}

View File

@@ -33,6 +33,11 @@ describe('dsh path helpers', () => {
expect(resolveDshHome(undefined, {})).toBe(defaultDshHome())
})
it('treats an empty or whitespace-only DSH_HOME as unset', () => {
expect(resolveDshHome(undefined, { DSH_HOME: '' })).toBe(defaultDshHome())
expect(resolveDshHome(undefined, { DSH_HOME: ' ' })).toBe(defaultDshHome())
})
it('labels a resolved home by whether it is the default root', () => {
expect(dshHomeDisplay(resolve(defaultDshHome()))).toBe('~/.dsh')
expect(dshHomeDisplay('/some/other/root')).toBe('$DSH_HOME')