refactor(paths): collapse harness home resolution into one resolver
Delete @deepseek-ai/dsh-home and make dsh-paths the sole owner of the single-root harness home ($DSH_HOME || ~/.dsh). Migrate tool-bash, skill-local, and agent-spine-demo off dsh-home, and fold telemetry's divergent globalConfigDir onto the shared resolver, dropping its second XDG/APPDATA policy and the deepseek-harness namespace so the anonymous id lives under the harness home. Add dshHomeDisplay() for symbolic user-facing paths, replacing workspace-context's bespoke check.
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* Per-machine anonymous telemetry id.
|
||||
*
|
||||
* The id is a random UUID persisted in a per-user GLOBAL config file — never in
|
||||
* The id is a random UUID persisted in the per-user harness home — never in
|
||||
* the project, and never derived from the git remote, repository URL, or any
|
||||
* other identifying source (a derived id would make "anonymous" a fiction). The
|
||||
* same id is reused across projects on one machine so telemetry counts machines,
|
||||
@@ -12,52 +12,36 @@
|
||||
|
||||
import { randomUUID } from 'node:crypto'
|
||||
import { mkdir, readFile, writeFile } from 'node:fs/promises'
|
||||
import { homedir } from 'node:os'
|
||||
import { dirname, join } from 'node:path'
|
||||
import type { Branded } from '@deepseek-ai/dsh-brand'
|
||||
import { resolveDshHome } from '@deepseek-ai/dsh-paths'
|
||||
|
||||
/** A machine-scoped anonymous telemetry id (random UUID v4). */
|
||||
export type AnonymousId = Branded<'AnonymousId'>
|
||||
|
||||
/** Config directory name owned by the DeepSeek Harness across tools. */
|
||||
const CONFIG_NAMESPACE = 'deepseek-harness'
|
||||
|
||||
/** Default file, inside the global config dir, storing the anonymous id. */
|
||||
/** Default file, inside the harness home, storing the anonymous id. */
|
||||
export const ANONYMOUS_ID_FILE_NAME = 'telemetry.json'
|
||||
|
||||
const UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i
|
||||
|
||||
/** Ambient seams for locating and generating the id; every field has a default. */
|
||||
export interface AnonymousIdOptions {
|
||||
/** Environment consulted for `DSH_CONFIG_HOME`/`XDG_CONFIG_HOME`/`APPDATA`; defaults to `process.env`. */
|
||||
/** Environment consulted for `DSH_HOME`; defaults to `process.env`. */
|
||||
env?: NodeJS.ProcessEnv
|
||||
/** Platform string used to pick the Windows path; defaults to `process.platform`. */
|
||||
platform?: NodeJS.Platform
|
||||
/** Home directory resolver; defaults to `os.homedir`. */
|
||||
homeDir?: () => string
|
||||
/** UUID generator; defaults to `crypto.randomUUID` (test seam). */
|
||||
randomUUID?: () => string
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the per-user global config directory for harness tooling.
|
||||
* Precedence: `DSH_CONFIG_HOME` (explicit override) > `XDG_CONFIG_HOME` >
|
||||
* platform default (`%APPDATA%` on Windows, else `~/.config`).
|
||||
* @param options - environment, platform, and home-directory seams.
|
||||
* @returns absolute config directory path for the harness namespace.
|
||||
* Resolve the single-root harness home that stores the anonymous id.
|
||||
* Delegates to {@link resolveDshHome} so telemetry shares the harness's one
|
||||
* home-resolution policy (`DSH_HOME` > `~/.dsh`) instead of maintaining a
|
||||
* second config-directory convention.
|
||||
* @param options - environment seam.
|
||||
* @returns absolute harness home path.
|
||||
*/
|
||||
export function globalConfigDir(options: AnonymousIdOptions = {}): string {
|
||||
const env = options.env ?? process.env
|
||||
const platform = options.platform ?? process.platform
|
||||
const home = options.homeDir ?? homedir
|
||||
if (env.DSH_CONFIG_HOME !== undefined && env.DSH_CONFIG_HOME.length > 0) return env.DSH_CONFIG_HOME
|
||||
if (env.XDG_CONFIG_HOME !== undefined && env.XDG_CONFIG_HOME.length > 0) {
|
||||
return join(env.XDG_CONFIG_HOME, CONFIG_NAMESPACE)
|
||||
}
|
||||
if (platform === 'win32' && env.APPDATA !== undefined && env.APPDATA.length > 0) {
|
||||
return join(env.APPDATA, CONFIG_NAMESPACE)
|
||||
}
|
||||
return join(home(), '.config', CONFIG_NAMESPACE)
|
||||
return resolveDshHome(undefined, options.env ?? process.env)
|
||||
}
|
||||
|
||||
/** Read a valid persisted id from the store, or `undefined` when absent/corrupt. */
|
||||
|
||||
Reference in New Issue
Block a user