refactor: rename the backend to dsh-subagent-dsh-sdk

The group's convention is package suffix == provider default
(subagent-acp/'acp', subagent-spawn/'spawn', subagent-fork/'fork'), and the
provider default became dsh-sdk in the last review round — so the package
follows: @deepseek-ai/dsh-subagent-dsh-sdk at
packages/subagent/subagent-dsh-sdk, plugin name subagent-dsh-sdk,
diagnostics prefixed subagent-dsh-sdk:. The dsh echo has precedent
(dsh-llm-deepseek). Directory, fixture path, knip/tsconfig/examples
registrations, catalogs, READMEs (en+zh), and the Agent Note follow; the
sdk-client dispose ladder moves to its own module (src/dispose.ts) with the
deterministic FakeChild tier tests restored alongside it.
This commit is contained in:
Tianyi Cui
2026-07-27 22:17:10 +08:00
parent 87a249106f
commit ed8f9c2808
37 changed files with 521 additions and 242 deletions

View File

@@ -4,7 +4,7 @@
* under their never-reject and idempotence contracts.
*/
import { chmodSync, mkdtempSync, rmSync } from 'node:fs'
import { chmodSync, mkdtempSync, rmSync, writeFileSync } from 'node:fs'
import { tmpdir } from 'node:os'
import { join, relative, resolve } from 'node:path'
import { describe, expect, it, vi } from 'vitest'
@@ -43,6 +43,17 @@ describe('child cwd resolution', () => {
expect(() => assertUsableCwd('p', 'config cwd', join(tmpdir(), 'dsh-no-such-dir-xyz'))).toThrow('not an accessible directory')
})
it('rejects an existing path that is a file, not a directory', () => {
const tmp = mkdtempSync(join(tmpdir(), 'oop-file-'))
const file = join(tmp, 'plain.txt')
try {
writeFileSync(file, 'not a dir\n')
expect(() => assertUsableCwd('p', 'config cwd', file)).toThrow('not an accessible directory')
} finally {
rmSync(tmp, { recursive: true, force: true })
}
})
// Windows ACLs do not expose the POSIX directory search-bit state this fixture creates.
it.skipIf(process.platform === 'win32')('rejects a directory without search permission', () => {
// statSync().isDirectory() is true for a mode-600 directory, but a