feat: support DeepSeek's official Harness desktop app and dsh 0.1.7 profiles - #248
Merged
Merged
Conversation
DeepSeek Harness 0.1.7 removed $DSH_HOME/settings.yaml. Live configuration now lives in $DSH_HOME/profiles/<profile>/cordis.patch.yml, a top-level sequence of loader patch rows where each row replaces one plugin entry's whole config. dsh imports the legacy file once on first start and renames it settings.yaml.imported; agent-default-model has no import mapping, so a write into the legacy file after that loses the default selection. Resolve the target per profile: the patch when its profile directory exists, the legacy file otherwise, so the npm `latest` CLI (0.1.5) keeps working while the desktop app and `next` (0.1.7) read what BootAgent writes. The CLI Agent uses the `web` profile, the desktop Agent `desktop`. Writes into the patch keep every other provider in the llm-pi-ai row and round-trip the bundle's `!!js` tagged scalars untouched; the credential store stays at the harness home and is located from either layout. ReadDSHConfig tells the two layouts apart by the document's root kind. A fixture with the account-platform `records` the desktop app keeps beside `refs` proves the credential merge leaves them intact. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…uild The dsh-desktop entry installed anywhere-labs' "DSH Desktop". DeepSeek now publishes its own desktop shell, "DeepSeek Harness", signed under Developer ID team NAN929V4UM with bundle id com.deepseek.dsh and served from download.deepseek.com with an electron-updater feed per target. Keep the Agent id so existing bindings resolve; point everything it names at the vendor's product. Resolve the package from the feed (dsh-desk/feeds/mac-arm64/nightly-mac.yml, dsh-desk/feeds/win-x64/nightly.yml), verify the served bytes against its sha512, and pin the signature to the vendor: bundle id and Team ID plus notarization on macOS, publisher on Windows. The previous checks accepted any valid codesign or Authenticode signature. The host allowlist is reduced to download.deepseek.com; the GitHub release lookup and dshdesktop.cn mirror go. Only mac-arm64 and win-x64 are published, so Intel macOS is refused up front rather than by a 404. Detection matches on the bundle identifier and reports the version from the bundle on disk, since the app updates itself. Drop the Unofficial mark and its disclaimer: the row is the vendor's own app. The disclaimer path is still exercised on a synthetic entry. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ting The desktop Agent resolved its dsh document by whether profiles/desktop/ existed. The install flow leaves the app on disk without launching it, so at first configuration that directory is absent and the write went to the legacy settings.yaml -- a file the 0.1.7-only desktop app imports only partially on first start. Resolve the desktop profile to its patch unconditionally and let the write create the directory: dsh's initProfile fills in package.json and pnpm-workspace.yaml only where absent, so a patch that arrives first is read as-is. The web profile keeps its fallback, since npm `latest` is still 0.1.5. WriteDSHOfficial wrote the credential before validating reasoningEffort, so a rejected activation had already replaced DEEPSEEK_API_KEY and left a backup. Validate first, in both layouts. Smaller: a comment-only scaffold patch keeps its header through the first write; the patch is encoded with the two-space indent dsh uses, so untouched rows come back byte-for-byte; the reader takes the first row per id, as the writer does, instead of merging duplicates. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ckage Supported was decided from the OS alone while the feed lookup also refused by architecture, so an Intel Mac saw an install entry that failed on every click. One function now names the vendor's target for a platform and drives both: mac-arm64 for Apple Silicon, win-x64 for every Windows -- an ARM Windows machine installs the x64 build, as with the other x64-only desktop apps -- and nothing elsewhere. The macOS inspection and install paths report through the caller's platform instead of a hardcoded arm64. The "not offered" test asserted only that Install failed; it now asserts Supported=false through Inspect too, which is what the UI reads. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The win-x64 installer is signed "Hangzhou DeepSeek Artificial Intelligence Co., Ltd." (with the period), and .NET quotes that name in the Subject because it holds a comma. Splitting the Subject on every comma cut the organization to `"Hangzhou DeepSeek Artificial Intelligence Co.`, so the genuine installer was refused. Read O= in Go with a quote-aware parser and pin the publisher observed on 0.1.7-rc.2. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
On first launch the 0.1.7-rc.2 desktop app writes a credential document with version and records but no refs, and a patch scaffold ending in a flow-style `[]`. The missing refs made WriteDSH refuse outright, and the flow style put every appended row on a single line in a file dsh tells users to edit by hand. Create refs when it is absent and emit an empty list in block style. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Resolves the conflicts left by #247 landing squashed while this branch still carried its two commits. dsh.go takes this branch's zip-based install; the DMG mount path and its darwin test are superseded. writeDSHCredential keeps both sides: the fresh-install refs creation from this branch and main's Kind check on an existing refs node. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Stacked on #247 (
codex/dsh-latest-adaptation); the first two commits here are that PR's. Review the last two commits, or merge #247 first and this diff collapses to them.DeepSeek now ships its own desktop application, DeepSeek Harness (
com.deepseek.dsh, Developer ID teamNAN929V4UM, served fromdownload.deepseek.com). Thedsh-desktopAgent installed a third-party build (anywhere-labs "DSH Desktop") and wrote configuration into~/.dsh/settings.yaml, which dsh 0.1.7 no longer reads.Configuration layer (P0)
$DSH_HOME/profiles/<profile>/cordis.patch.yml, a top-level YAML sequence of loader patch rows (whole-config replacement per row). The legacysettings.yamlis imported once on first start and renamedsettings.yaml.imported;agent-default-modelhas no import mapping, so a legacy write after that loses the default selection.ResolveDSHConfigPath(home, profile). The desktop Agent (desktopprofile) always writes the patch and creates the directory ahead of the app's first launch: the Electron shell is 0.1.7-only, and itsinitProfilefills inpackage.json/pnpm-workspace.yamlonly where absent. The CLI Agent (webprofile) writes the patch once dsh has created that profile, otherwise the legacy file, since npmlatestis still 0.1.5.llm-pi-airow; rows the write does not address come back byte-for-byte (two-space indent,!!jstags and quoting preserved). Credentials stay at$DSH_HOME/.credentials.yamlfrom either layout.ReadDSHConfigtells the layouts apart by the document's root node kind.recordsthe desktop app keeps besiderefsproves the credential merge leaves them intact.Desktop entry (P1)
dsh-desk/feeds/mac-arm64/nightly-mac.yml,dsh-desk/feeds/win-x64/nightly.yml), served bytes verified against the feed's sha512. Host allowlist reduced todownload.deepseek.com; GitHub release lookup and dshdesktop.cn mirror removed.mac-arm64andwin-x64are published. One function decides bothSupportedand the feed: Intel macOS is unsupported (no install entry shown), Windows on ARM installs the x64 build. Detection matches on bundle identifier and reports the version from disk (the app self-updates).Unofficialmark and disclaimer dropped for this row; the disclaimer path is still tested on a synthetic entry. Agent iddsh-desktopis kept so existing bindings resolve.Test plan
go test ./...,go test -raceoninternal/config,internal/desktopapp,internal/appgo vet ./...,staticcheck ./...python3 scripts/check-docs.pycd frontend && pnpm run test && pnpm run buildcodesign -dvidentity,spctl --assessaccepted, feed sha512 matches the servedmac-arm64zip byte-for-byte,~/.dsh/profiles/desktop/cordis.patch.ymlis where 0.1.7 imported the old settings.Review follow-ups (addressed in
db3eacd,3a70a65)settings.yamlwhenprofiles/desktop/is absent.Supportednow agrees with the feed lookup (Intel Mac unsupported; Windows ARM supported via x64).WriteDSHOfficialvalidatesreasoningEffortbefore touching.credentials.yaml.Windows verification (
ea8ad96,c93ff4e)On Windows 11 x64 against the real
deepseek-harness-0.1.7-rc.2-win-x64.exe:Get-AuthenticodeSignature:Valid, subjectCN="Hangzhou DeepSeek Artificial Intelligence Co., Ltd.", O="Hangzhou DeepSeek Artificial Intelligence Co., Ltd.", …, issuer GlobalSign GCC R45 EV CodeSigning CA 2020.O=extraction split the quoted value at its comma ("Hangzhou DeepSeek Artificial Intelligence Co.).O=is now read in Go with a quote-aware parser (unit-tested), andverifyDSHWindowsInstalleraccepts the real.exeend to end whileverifyZCodeWindowsInstallerstill refuses it.installer-startedhands off to the user rather than completing on its own.%LOCALAPPDATA%\Programs\DeepSeek Harness\DeepSeek Harness.exe(HKCU uninstall entry,/currentuser), which is exactly whatdshWindowsCandidatesprobes;Inspectreports it installed.~/.dsh/profiles/desktop/cordis.patch.ymlas the header comment followed by a flow-style[], and~/.dsh/.credentials.yamlwithversion: 1andrecordsbut norefs. Against a copy of that directoryWriteDSHrefused (credentials refs must be an object);c93ff4ecreatesrefswhen absent and writes the empty list back in block style so rows are not all emitted on one line. Covered byTestWriteDSHProfileIntoAFreshDesktopInstall, and re-run against the real copy.go test ./internal/...on Windows: no new failures relative tomain; the remaining ones are pre-existing Unix-mode / macOS-path assertions.Not verified here
Inspectreports no version (macOS reads it from the bundle); the exe's ProductVersion or the HKCUDisplayVersionwould supply it. Follow-up.~/.dsh, not loaded by the live app).BOOTAGENT_API_KEYreference (gateway providers). Follow-up.🤖 Generated with Claude Code