The first-use directory name and its stored title came from the Client's startup language, so one product decision carried two incompatible requirements: a path addressed by shell commands, tool arguments, @path references, and session logs, and a label a reader reads. The controller now owns the fixed `default-workspace` directory name and the registry titles the Workspace after that same segment, so `workspace.initializeDefault` takes no request at all — WorkspaceInitializeDefaultRequest and its name validation are gone, and the registry resolver returns a path instead of a path and title. No language reaches the Host. Browser consumers label a Workspace through the new `workspaceDisplayTitle`: a title still equal to the automatic one reads as the localized default name from the `common` namespace, every other title reads verbatim. The Workspace browser resolves it once at the store read, so rows, hover card, search meta, and the rename and delete dialogs inherit it; the hero picker and the Conversation chip resolve it too. Confirming a rename stores the text on screen, which is what stops a row following the language.
49 lines
2.8 KiB
TypeScript
49 lines
2.8 KiB
TypeScript
import { describe, expect, it, vi } from 'vitest'
|
|
import type { NativeCommandRunner } from '@deepseek-ai/dsh-native-command'
|
|
import { defaultWorkspaceDirectory, validateDocumentsDirectory } from '../src/default-directory.ts'
|
|
|
|
describe('system Documents directory', () => {
|
|
it.each([
|
|
['darwin', '/Users/a/文档/\n', '/Users/a/文档/deepseek-harness/default-workspace', 'osascript'],
|
|
['win32', 'D:\\Redirected Documents\r\n', 'D:\\Redirected Documents\\deepseek-harness\\default-workspace', 'powershell.exe'],
|
|
['linux', '/home/a/My Documents\n', '/home/a/My Documents/deepseek-harness/default-workspace', 'xdg-user-dir'],
|
|
] as const)('uses the %s account directory and preserves spaces and Unicode', async (platform, stdout, path, command) => {
|
|
const run = vi.fn<NativeCommandRunner>(async () => ({ stdout, stderr: '' }))
|
|
const signal = new AbortController().signal
|
|
await expect(defaultWorkspaceDirectory(undefined, signal, { platform, run })).resolves.toBe(path)
|
|
expect(run).toHaveBeenCalledWith(command, expect.any(Array), signal)
|
|
})
|
|
|
|
it('uses the configured directory without a system lookup', async () => {
|
|
const run = vi.fn<NativeCommandRunner>()
|
|
await expect(defaultWorkspaceDirectory('/documents', new AbortController().signal, { platform: 'linux', run }))
|
|
.resolves.toBe('/documents/deepseek-harness/default-workspace')
|
|
expect(run).not.toHaveBeenCalled()
|
|
})
|
|
|
|
it.each(['', '\r\n', '/home/a\n'])('rejects an unavailable XDG directory %j', async (stdout) => {
|
|
const run: NativeCommandRunner = async () => ({ stdout, stderr: '' })
|
|
await expect(defaultWorkspaceDirectory(undefined, new AbortController().signal, { platform: 'linux', home: '/home/a', run }))
|
|
.rejects.toThrow('unavailable')
|
|
})
|
|
|
|
it('propagates lookup failure and cancellation', async () => {
|
|
const run: NativeCommandRunner = async () => { throw new Error('lookup denied') }
|
|
await expect(defaultWorkspaceDirectory(undefined, new AbortController().signal, { platform: 'darwin', run }))
|
|
.rejects.toThrow('lookup denied')
|
|
await expect(defaultWorkspaceDirectory('/documents', AbortSignal.abort(), { platform: 'linux' }))
|
|
.rejects.toThrow()
|
|
await expect(defaultWorkspaceDirectory(undefined, new AbortController().signal, { platform: 'freebsd' }))
|
|
.rejects.toThrow('unavailable')
|
|
})
|
|
|
|
it.each(['relative', 'C:relative', '\\rooted'])('rejects a Windows path without a fully qualified root: %s', (path) => {
|
|
expect(() => validateDocumentsDirectory(path, 'win32')).toThrow('fully qualified')
|
|
})
|
|
|
|
it('accepts redirected UNC Documents directories', () => {
|
|
expect(validateDocumentsDirectory('\\\\server\\share\\Documents', 'win32')).toBe('\\\\server\\share\\Documents')
|
|
expect(() => validateDocumentsDirectory('relative', 'linux')).toThrow('fully qualified')
|
|
})
|
|
})
|