Point coverage, shortcut generation, installers, and shared routing at dingtalk-misc references after retiring the standalone packages. Co-authored-by: Cursor <cursoragent@cursor.com>
140 lines
5.9 KiB
PowerShell
140 lines
5.9 KiB
PowerShell
# Copyright 2026 Alibaba Group
|
|
# Licensed under the Apache License, Version 2.0
|
|
#
|
|
# One-command installer for dws dev on native Windows (PowerShell).
|
|
# Downloads the dev binary (dws.exe) + dingtalk-misc skill (hosts open-platform app docs) from the DingTalk-Real-AI GitHub Releases.
|
|
#
|
|
# Usage:
|
|
# irm https://raw.githubusercontent.com/DingTalk-Real-AI/dingtalk-workspace-cli/main/scripts/install-devapp.ps1 | iex
|
|
#
|
|
# Env (all optional):
|
|
# DEVAPP_REPO repo holding dev releases (default: DingTalk-Real-AI/dingtalk-workspace-cli)
|
|
# DEVAPP_VERSION pin a release tag (default: latest release)
|
|
# DWS_ARCH architecture override (amd64 or arm64)
|
|
# DWS_INSTALL_DIR binary dir (default: ~/.local/bin)
|
|
# DWS_NO_SKILLS set 1 to skip the dev skill
|
|
|
|
$ErrorActionPreference = "Stop"
|
|
|
|
$Repo = if ($env:DEVAPP_REPO) { $env:DEVAPP_REPO } else { "DingTalk-Real-AI/dingtalk-workspace-cli" }
|
|
$Version = $env:DEVAPP_VERSION
|
|
$InstallDir = if ($env:DWS_INSTALL_DIR) { $env:DWS_INSTALL_DIR } else { Join-Path $HOME ".local\bin" }
|
|
$NoSkills = $env:DWS_NO_SKILLS -eq "1"
|
|
$SkillName = "dingtalk-misc"
|
|
|
|
function Say($m) { Write-Host " $m" }
|
|
function Die($m) { Write-Host " X $m" -ForegroundColor Red; exit 1 }
|
|
|
|
function Get-Arch {
|
|
if ($env:DWS_ARCH -eq "amd64" -or $env:DWS_ARCH -eq "arm64") { return $env:DWS_ARCH }
|
|
try {
|
|
switch ([System.Runtime.InteropServices.RuntimeInformation]::OSArchitecture) {
|
|
"X64" { return "amd64" }
|
|
"Arm64" { return "arm64" }
|
|
}
|
|
} catch {}
|
|
switch ($env:PROCESSOR_ARCHITECTURE) {
|
|
"AMD64" { return "amd64" }
|
|
"ARM64" { return "arm64" }
|
|
default { Die "Could not detect architecture. Set DWS_ARCH to amd64 or arm64." }
|
|
}
|
|
}
|
|
|
|
# Read the releases list (newest first) and take the top tag, so this also works
|
|
# if a release is ever published as a prerelease (which /releases/latest skips).
|
|
if (-not $Version) {
|
|
try {
|
|
$rel = Invoke-RestMethod -Uri "https://api.github.com/repos/$Repo/releases?per_page=1" `
|
|
-Headers @{ "User-Agent" = "dws-devapp-installer" } -UseBasicParsing
|
|
$Version = $rel[0].tag_name
|
|
} catch {}
|
|
if (-not $Version) { Die "No release found on $Repo. Set DEVAPP_VERSION to a published release tag." }
|
|
}
|
|
|
|
$arch = Get-Arch
|
|
$tmp = Join-Path $env:TEMP ("dws-dev-" + [System.Guid]::NewGuid().ToString())
|
|
New-Item -ItemType Directory -Path $tmp -Force | Out-Null
|
|
|
|
Write-Host ""
|
|
Say "dws dev installer (Windows, pre-built binary)"
|
|
Say "Repo: $Repo"
|
|
Say "Version: $Version"
|
|
Say "Target: windows/$arch"
|
|
Write-Host ""
|
|
|
|
# 1) binary
|
|
$asset = "dws-windows-$arch.zip"
|
|
$zip = Join-Path $tmp $asset
|
|
Say "Downloading $asset ..."
|
|
try {
|
|
Invoke-WebRequest -Uri "https://github.com/$Repo/releases/download/$Version/$asset" `
|
|
-OutFile $zip -UseBasicParsing
|
|
} catch { Die "Binary download failed - does release $Version have $asset?" }
|
|
|
|
Expand-Archive -Path $zip -DestinationPath $tmp -Force
|
|
$exe = Get-ChildItem -Path $tmp -Recurse -Filter "dws.exe" | Select-Object -First 1
|
|
if (-not $exe) { Die "dws.exe not found inside $asset" }
|
|
if (-not (Test-Path $InstallDir)) { New-Item -ItemType Directory -Path $InstallDir -Force | Out-Null }
|
|
Copy-Item -Path $exe.FullName -Destination (Join-Path $InstallDir "dws.exe") -Force
|
|
Say "Binary -> $InstallDir\dws.exe"
|
|
|
|
# 2) dev skill from the release's skills bundle
|
|
if (-not $NoSkills) {
|
|
try {
|
|
$skzip = Join-Path $tmp "dws-skills.zip"
|
|
Invoke-WebRequest -Uri "https://github.com/$Repo/releases/download/$Version/dws-skills.zip" `
|
|
-OutFile $skzip -UseBasicParsing
|
|
$skdir = Join-Path $tmp "sk"
|
|
Expand-Archive -Path $skzip -DestinationPath $skdir -Force
|
|
|
|
$src = $null
|
|
foreach ($c in @("multi\$SkillName", "skills\multi\$SkillName", "$SkillName")) {
|
|
$p = Join-Path $skdir $c
|
|
if (Test-Path (Join-Path $p "SKILL.md")) { $src = $p; break }
|
|
}
|
|
if ($src) {
|
|
# cache so `dws skill setup --mode multi` can find a source later
|
|
$cache = Join-Path $HOME ".dws\skills\multi\$SkillName"
|
|
if (Test-Path $cache) { Remove-Item -Recurse -Force $cache }
|
|
New-Item -ItemType Directory -Path $cache -Force | Out-Null
|
|
Copy-Item -Path "$src\*" -Destination $cache -Recurse -Force
|
|
|
|
$agentDirs = @(
|
|
".agents\skills", ".claude\skills", ".cursor\skills", ".qoder\skills", ".qoderwork\skills",
|
|
".gemini\skills", ".codex\skills", ".github\skills", ".windsurf\skills", ".augment\skills",
|
|
".cline\skills", ".amp\skills", ".kiro\skills", ".trae\skills", ".openclaw\skills",
|
|
".hermes\skills", ".config\opencode\skills"
|
|
)
|
|
$installed = 0; $idx = 0
|
|
foreach ($d in $agentDirs) {
|
|
$base = Join-Path $HOME $d
|
|
$parent = Split-Path $base -Parent
|
|
if ($idx -gt 0 -and -not (Test-Path $parent)) { $idx++; continue }
|
|
$dest = Join-Path $base $SkillName
|
|
if (Test-Path $dest) { Remove-Item -Recurse -Force $dest }
|
|
New-Item -ItemType Directory -Path $dest -Force | Out-Null
|
|
Copy-Item -Path "$src\*" -Destination $dest -Recurse -Force
|
|
$installed++; $idx++
|
|
}
|
|
Say "Skill dingtalk-misc -> $installed agent dir(s)"
|
|
} else {
|
|
Say "(dingtalk-misc not found in skills bundle; skipped)"
|
|
}
|
|
} catch {
|
|
Say "(skill install skipped: $($_.Exception.Message))"
|
|
}
|
|
}
|
|
|
|
Remove-Item -Recurse -Force $tmp -ErrorAction SilentlyContinue
|
|
|
|
Write-Host ""
|
|
Say "Done. Next steps:"
|
|
Say " dws version"
|
|
Say " dws auth login"
|
|
Say " dws dev --help --format json"
|
|
Write-Host ""
|
|
if (($env:Path -split ';') -notcontains $InstallDir) {
|
|
Say "Note: $InstallDir is not on PATH. Add it (new terminal after):"
|
|
Say " [Environment]::SetEnvironmentVariable('Path', `"`$env:Path;$InstallDir`", 'User')"
|
|
}
|