Skip to content

Commit 1f76805

Browse files
Merge pull request #9 from starsstreaming/feat/dsh-installer
bundle DeepSeek Harness runtime in the Windows installer
2 parents dcf9be5 + 3ebc37f commit 1f76805

3 files changed

Lines changed: 297 additions & 11 deletions

File tree

installer/windows/beauticode.iss

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#pragma codepage "utf-8"
1+
#pragma codepage 65001
22

33
#define MyAppName "beautiCode"
44
#define MyAppPublisher "beautiCode"
@@ -53,9 +53,10 @@ Name: "autostart"; Description: "登录 Windows 后自动启动"; GroupDescripti
5353
Source: "{#StageDir}\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
5454

5555
[Icons]
56-
Name: "{autoprograms}\beautiCode"; Filename: "{sys}\WindowsPowerShell\v1.0\powershell.exe"; Parameters: "-NoProfile -ExecutionPolicy Bypass -WindowStyle Hidden -File ""{app}\scripts\start-beauticode-engine.ps1"""; WorkingDir: "{app}"; IconFilename: "{app}\beauticode.ico"
57-
Name: "{autodesktop}\beautiCode"; Filename: "{sys}\WindowsPowerShell\v1.0\powershell.exe"; Parameters: "-NoProfile -ExecutionPolicy Bypass -WindowStyle Hidden -File ""{app}\scripts\start-beauticode-engine.ps1"""; WorkingDir: "{app}"; IconFilename: "{app}\beauticode.ico"; Tasks: desktopicon
56+
Name: "{autoprograms}\beautiCode"; Filename: "{sys}\WindowsPowerShell\v1.0\powershell.exe"; Parameters: "-NoProfile -ExecutionPolicy Bypass -WindowStyle Hidden -File ""{app}\scripts\start-beauticode.ps1"""; WorkingDir: "{app}"; IconFilename: "{app}\beauticode.ico"
57+
Name: "{autoprograms}\beautiCode · DeepSeek Harness"; Filename: "{sys}\WindowsPowerShell\v1.0\powershell.exe"; Parameters: "-NoProfile -ExecutionPolicy Bypass -WindowStyle Hidden -File ""{app}\scripts\start-beauticode-dsh.ps1"" -SkipBuild"; WorkingDir: "{app}"; IconFilename: "{app}\beauticode.ico"
58+
Name: "{autodesktop}\beautiCode"; Filename: "{sys}\WindowsPowerShell\v1.0\powershell.exe"; Parameters: "-NoProfile -ExecutionPolicy Bypass -WindowStyle Hidden -File ""{app}\scripts\start-beauticode.ps1"""; WorkingDir: "{app}"; IconFilename: "{app}\beauticode.ico"; Tasks: desktopicon
5859
Name: "{userstartup}\beautiCode"; Filename: "{sys}\WindowsPowerShell\v1.0\powershell.exe"; Parameters: "-NoProfile -ExecutionPolicy Bypass -WindowStyle Hidden -File ""{app}\scripts\start-beauticode-engine.ps1"" -NoLaunchCodex"; WorkingDir: "{app}"; IconFilename: "{app}\beauticode.ico"; Tasks: autostart
5960

6061
[Run]
61-
Filename: "{sys}\WindowsPowerShell\v1.0\powershell.exe"; Parameters: "-NoProfile -ExecutionPolicy Bypass -WindowStyle Hidden -File ""{app}\scripts\start-beauticode-engine.ps1"""; WorkingDir: "{app}"; Description: "启动 beautiCode"; Flags: postinstall nowait skipifsilent
62+
Filename: "{sys}\WindowsPowerShell\v1.0\powershell.exe"; Parameters: "-NoProfile -ExecutionPolicy Bypass -WindowStyle Hidden -File ""{app}\scripts\start-beauticode.ps1"""; WorkingDir: "{app}"; Description: "启动 beautiCode"; Flags: postinstall nowait skipifsilent

scripts/build-windows-installer.ps1

Lines changed: 71 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,16 @@
44
Build a self-contained beautiCode Windows installer.
55
66
.DESCRIPTION
7-
Builds TypeScript, stages only runtime files, downloads and verifies the
8-
official Node.js Windows x64 runtime, then compiles an Inno Setup installer.
7+
Builds TypeScript, stages both host adapters, downloads and verifies the
8+
official Node.js Windows x64 runtime, installs the integrity-pinned DSH into
9+
a private bundle, then compiles an Inno Setup installer.
910
#>
1011
[CmdletBinding()]
1112
param(
1213
[ValidatePattern("^\d+\.\d+\.\d+$")]
1314
[string]$NodeVersion = "24.18.0",
14-
[string]$InnoCompiler = ""
15+
[string]$InnoCompiler = "",
16+
[string]$DshRuntimeCache = ""
1517
)
1618

1719
$ErrorActionPreference = "Stop"
@@ -20,6 +22,11 @@ $ArtifactsRoot = Join-Path $RepoRoot "artifacts\windows"
2022
$StageRoot = Join-Path $ArtifactsRoot "stage"
2123
$CacheRoot = Join-Path $ArtifactsRoot "cache"
2224
$OutputRoot = Join-Path $ArtifactsRoot "installer"
25+
$DshCacheRoot = if ($DshRuntimeCache) {
26+
[IO.Path]::GetFullPath($DshRuntimeCache)
27+
} else {
28+
Join-Path $CacheRoot "dsh-runtime"
29+
}
2330
$InstallerScript = Join-Path $RepoRoot "installer\windows\beauticode.iss"
2431
$PinnedNodeVersion = "24.18.0"
2532
$PinnedNodeArchiveSha256 = "0ae68406b42d7725661da979b1403ec9926da205c6770827f33aac9d8f26e821"
@@ -36,6 +43,17 @@ function Assert-WorkspaceChild([string]$Path) {
3643
}
3744
}
3845

46+
function Get-Sha256Hex([string]$Path) {
47+
$stream = [System.IO.File]::OpenRead($Path)
48+
$sha256 = [System.Security.Cryptography.SHA256]::Create()
49+
try {
50+
return ([System.BitConverter]::ToString($sha256.ComputeHash($stream))).Replace("-", "").ToLowerInvariant()
51+
} finally {
52+
$sha256.Dispose()
53+
$stream.Dispose()
54+
}
55+
}
56+
3957
function Reset-Directory([string]$Path) {
4058
Assert-WorkspaceChild $Path
4159
if (Test-Path -LiteralPath $Path) {
@@ -144,6 +162,12 @@ if (-not (Test-Path -LiteralPath $InstallerScript -PathType Leaf)) {
144162

145163
$package = Get-Content -Raw -LiteralPath (Join-Path $RepoRoot "package.json") |
146164
ConvertFrom-Json
165+
$compatibility = Get-Content -Raw -LiteralPath (
166+
Join-Path $RepoRoot "integrations\deepseek-harness\compatibility.json"
167+
) | ConvertFrom-Json
168+
if ($compatibility.schema -ne "beauticode.dsh-compatibility/v1") {
169+
throw "DSH compatibility manifest is invalid."
170+
}
147171
$appVersion = [string]$package.version
148172
if ($appVersion -notmatch "^\d+\.\d+\.\d+$") {
149173
throw ("Installer requires a numeric three-part package version: {0}" -f $appVersion)
@@ -177,7 +201,7 @@ if (-not $checksumLine) {
177201
throw ("Official checksum was not found for {0}" -f $nodeArchiveName)
178202
}
179203
$expectedHash = ($checksumLine -split "\s+")[0].ToLowerInvariant()
180-
$actualHash = (Get-FileHash -Algorithm SHA256 -LiteralPath $nodeArchive).Hash.ToLowerInvariant()
204+
$actualHash = Get-Sha256Hex $nodeArchive
181205
if ($actualHash -ne $expectedHash) {
182206
throw ("Node.js archive checksum mismatch: expected {0}, got {1}" -f $expectedHash, $actualHash)
183207
}
@@ -196,9 +220,12 @@ foreach ($relativeDir in @(
196220
"scripts",
197221
"packages\core",
198222
"packages\adapter-codex",
223+
"packages\adapter-dsh",
224+
"integrations\deepseek-harness",
199225
"node_modules\@beauticode\core",
200226
"runtime",
201-
"licenses\node"
227+
"licenses\node",
228+
"licenses\dsh"
202229
)) {
203230
New-Item -ItemType Directory -Path (Join-Path $StageRoot $relativeDir) -Force | Out-Null
204231
}
@@ -208,9 +235,16 @@ foreach ($relativeFile in @(
208235
"apps\tray\start-tray.ps1",
209236
"assets\beauticode-icon-borderless.png",
210237
"scripts\codex-launch.ps1",
238+
"scripts\start-beauticode.ps1",
211239
"scripts\start-beauticode-engine.ps1",
240+
"scripts\start-beauticode-dsh.ps1",
241+
"scripts\install-dsh-runtime.ps1",
212242
"packages\core\package.json",
213243
"packages\adapter-codex\package.json",
244+
"packages\adapter-dsh\package.json",
245+
"integrations\deepseek-harness\index.mjs",
246+
"integrations\deepseek-harness\client.js",
247+
"integrations\deepseek-harness\compatibility.json",
214248
"LICENSE",
215249
"NOTICE.md",
216250
"THIRD_PARTY_NOTICES.md"
@@ -229,6 +263,9 @@ Copy-RuntimeDirectory `
229263
Copy-RuntimeDirectory `
230264
(Join-Path $RepoRoot "packages\adapter-codex\dist") `
231265
(Join-Path $StageRoot "packages\adapter-codex\dist")
266+
Copy-RuntimeDirectory `
267+
(Join-Path $RepoRoot "packages\adapter-dsh\dist") `
268+
(Join-Path $StageRoot "packages\adapter-dsh\dist")
232269
Copy-Item -LiteralPath (Join-Path $RepoRoot "packages\core\package.json") `
233270
-Destination (Join-Path $StageRoot "node_modules\@beauticode\core\package.json") -Force
234271
Copy-RuntimeDirectory `
@@ -240,6 +277,18 @@ Copy-Item -LiteralPath (Join-Path $nodeDistribution "node.exe") `
240277
Copy-Item -LiteralPath (Join-Path $nodeDistribution "LICENSE") `
241278
-Destination (Join-Path $StageRoot "licenses\node\LICENSE") -Force
242279

280+
& (Join-Path $RepoRoot "scripts\install-dsh-runtime.ps1") `
281+
-InstallRoot $DshCacheRoot `
282+
-CompatibilityFile (Join-Path $RepoRoot "integrations\deepseek-harness\compatibility.json") `
283+
-NodeCommand (Join-Path $StageRoot "runtime\node.exe") `
284+
-NpmCommand ((Get-Command npm.cmd -ErrorAction Stop).Source)
285+
Copy-RuntimeDirectory $DshCacheRoot (Join-Path $StageRoot "runtime\dsh")
286+
$dshLicense = Join-Path $StageRoot "runtime\dsh\versions\$($compatibility.supportedVersion)\node_modules\@deepseek-ai\dsh\LICENSE"
287+
if (-not (Test-Path -LiteralPath $dshLicense -PathType Leaf)) {
288+
throw "Staged DSH license is missing."
289+
}
290+
Copy-Item -LiteralPath $dshLicense -Destination (Join-Path $StageRoot "licenses\dsh\LICENSE") -Force
291+
243292
New-InstallerIcon `
244293
(Join-Path $RepoRoot "assets\beauticode-icon-borderless.png") `
245294
(Join-Path $StageRoot "beauticode.ico")
@@ -250,6 +299,8 @@ $manifest = [ordered]@{
250299
schema = "beauticode.release/v1"
251300
appVersion = $appVersion
252301
nodeVersion = $NodeVersion
302+
dshVersion = [string]$compatibility.supportedVersion
303+
dshBridgeProtocol = [int]$compatibility.bridgeProtocol
253304
platform = "win-x64"
254305
commit = $commit
255306
dirty = ($trackedChanges.Count -gt 0)
@@ -271,6 +322,19 @@ $adapterProbe = & $stagedNode --input-type=module -e `
271322
if ($LASTEXITCODE -ne 0 -or $adapterProbe -ne "function") {
272323
throw ("Staged adapter import failed: {0}" -f $adapterProbe)
273324
}
325+
$dshAdapterUrl = ([System.Uri](Join-Path $StageRoot "packages\adapter-dsh\dist\index.js")).AbsoluteUri
326+
$dshAdapterProbe = & $stagedNode --input-type=module -e `
327+
"const m=await import(process.argv[1]); console.log(typeof m.DshSession);" `
328+
$dshAdapterUrl
329+
if ($LASTEXITCODE -ne 0 -or $dshAdapterProbe -ne "function") {
330+
throw ("Staged DSH adapter import failed: {0}" -f $dshAdapterProbe)
331+
}
332+
$dshManifest = Get-Content -Raw -LiteralPath (Join-Path $StageRoot "runtime\dsh\current.json") | ConvertFrom-Json
333+
$dshCli = Join-Path (Join-Path $StageRoot "runtime\dsh") ([string]$dshManifest.cli)
334+
$stagedDshVersion = (& $stagedNode $dshCli --version).Trim()
335+
if ($LASTEXITCODE -ne 0 -or $stagedDshVersion -ne [string]$compatibility.supportedVersion) {
336+
throw ("Staged DSH version mismatch: expected {0}, got {1}" -f $compatibility.supportedVersion, $stagedDshVersion)
337+
}
274338

275339
$iscc = Resolve-InnoCompiler $InnoCompiler
276340
& $iscc `
@@ -289,8 +353,8 @@ if (-not $installer) {
289353
throw "Inno Setup completed without producing an installer."
290354
}
291355

292-
$installerHash = Get-FileHash -Algorithm SHA256 -LiteralPath $installer.FullName
356+
$installerHash = Get-Sha256Hex $installer.FullName
293357
Write-Host ""
294358
Write-Host "Windows installer created:"
295359
Write-Host (" {0}" -f $installer.FullName)
296-
Write-Host (" SHA256 {0}" -f $installerHash.Hash)
360+
Write-Host (" SHA256 {0}" -f $installerHash.ToUpperInvariant())

0 commit comments

Comments
 (0)